diff -urN linux-2.3.51/Documentation/ia64/efirtc.txt linux-2.3.51-lia/Documentation/ia64/efirtc.txt --- linux-2.3.51/Documentation/ia64/efirtc.txt Wed Dec 31 16:00:00 1969 +++ linux-2.3.51-lia/Documentation/ia64/efirtc.txt Fri Mar 17 10:43:41 2000 @@ -0,0 +1,128 @@ +EFI Real Time Clock driver +------------------------------- +S. Eranian +March 2000 + +I/ Introduction + +This document describes the efirtc.c driver has provided for +the IA-64 platform. + +The purpose of this driver is to supply an API for kernel and user applications +to get access to the Time Service offered by EFI version 0.92. + +EFI provides 4 calls one can make once the OS is booted: GetTime(), +SetTime(), GetWakeupTime(), SetWakeupTime() which are all supported by this driver. +We describes those calls as well the the design of the driver in the following +sections. + +II/ Design Decisions + +The original ideas was to provide a very simple driver to get access to, +at first, the time of day service. This is required in order to access, in a +portable way, the CMOS clock. A program like /sbin/hwclock uses such a clock +to initialize the system view of the time during boot. + +Because we wanted to minimize the impact on existing user-level apps using +the CMOS clock, we decided to expose an API that was very similar to the one +used today with the legacy RTC driver (driver/char/rtc.c). However, because +EFI provides a simpler services, not all all ioctl() are available. Also +new ioctl()s have been introduced for things that EFI provides but not the +legacy. + +EFI uses a slightly different way of representing the time, noticeably +the reference date is different. Year is the using the full 4-digit format. +The Epoch is January 1st 1998. For backward compatibility reasons we don't +expose this new way of representing time. Instead we use something very +similar to the struct tm, i.e. struct rtc_time, as used by hwclock. +One of the reasons for doing it this way is to allow for EFI to still evolve +without necessarily impatcing any of the user applications. The decoupling +enables flexibility and permits writing wrapper code is ncase things change. + +The driver exposes two interfaces, one via the device file and a set of ioctl()s. +The other is read-only via the /proc filesystem. + +As of today we don't offer a /proc/sys interface. + +To allow for a uniform interface between the legacy RTC and EFI time service, +we have created the include/linux/rtc.h header file to contain only the +"public" API of the two drivers. The specifics of the legacy RTC are still +in include/linux/mc146818rtc.h. + + +III/ Time of day service + +The part of the driver gives access to the time of day service of EFI. +Two ioctl()s, compatible with the legacy RTC calls: + + Read the CMOS clock: ioctl(d, RTC_RD_TIME, &rtc); + + Write the CMOS clock: ioctl(d, RTC_SET_TIME, &rtc); + +The rtc is a pointer to a data structure defined in rtc.h which is close +to a struct tm: + +struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +The driver takes care of converting back an forth between the EFI time and +this format. + +Those two ioctl()s can be exercised with the hwclock command: + +For reading: +# /sbin/hwclock --show +Mon Mar 6 15:32:32 2000 -0.910248 seconds + +For setting: +# /sbin/hwclock --systohc + +Root privileges are required to be able to set the time of day. + +IV/ Wakeup Alarm service + +EFI provides an API by which one can program when a machine should wakeup, +i.e. reboot. This is very different from the alarm provided by the legacy +RTC which is some kind of interval timer alarm. For this reason we don't use +the same ioctl()s to get access to the service. Instead we have +introduced 2 news ioctl()s to the interface of an RTC. + +We have added 2 new ioctl()s that are specific to the EFI driver: + + Read the current state of the alarm + ioctl(d, RTC_WKLAM_RD, &wkt) + + Set the alarm or change its status + ioctl(d, RTC_WKALM_SET, &wkt) + +The wkt structure encapsulates a struct rtc_time + 2 extra fields to get +status information: + +struct rtc_wkalrm { + + unsigned char enabled; /* =1 if alarm is enabled */ + unsigned char pending; /* =1 if alarm is pending */ + + struct rtc_time time; +} + +As of today, none of the existing user-level apps supports this feature. +However writing such a program should be hard by simply using those two +ioctl(). + +Root privileges are required to be able to set the alarm. + +V/ References. + +Checkout the following Web site for more information on EFI: + +http://developer.intel.com/technology/efi/ diff -urN linux-2.3.51/Makefile linux-2.3.51-lia/Makefile --- linux-2.3.51/Makefile Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/Makefile Tue Mar 28 13:49:30 2000 @@ -93,7 +93,7 @@ CPPFLAGS += -D__SMP__ endif -CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer +CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -g -O2 -fomit-frame-pointer AFLAGS := $(CPPFLAGS) # diff -urN linux-2.3.51/arch/i386/kernel/smp.c linux-2.3.51-lia/arch/i386/kernel/smp.c --- linux-2.3.51/arch/i386/kernel/smp.c Fri Feb 11 08:19:45 2000 +++ linux-2.3.51-lia/arch/i386/kernel/smp.c Mon Apr 3 22:27:59 2000 @@ -588,4 +588,3 @@ if (wait) atomic_inc(&call_data->finished); } - diff -urN linux-2.3.51/arch/ia64/Makefile linux-2.3.51-lia/arch/ia64/Makefile --- linux-2.3.51/arch/ia64/Makefile Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/Makefile Tue Mar 28 13:44:44 2000 @@ -16,10 +16,10 @@ # The next line is needed when compiling with the July snapshot of the Cygnus compiler: #EXTRA = -D__GCC_DOESNT_KNOW_IN_REGS__ # next two lines are for the September snapshot of the Cygnus compiler: -AFLAGS += -D__GCC_MULTIREG_RETVALS__ +AFLAGS += -D__GCC_MULTIREG_RETVALS__ -Wa,-x EXTRA = -D__GCC_MULTIREG_RETVALS__ -CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 +CFLAGS := $(CFLAGS) -pipe $(EXTRA) -Wa,-x -ffixed-r13 -mfixed-range=f10-f15,f32-f127 ifdef CONFIG_IA64_GENERIC CORE_FILES := arch/$(ARCH)/hp/hp.a \ @@ -34,14 +34,14 @@ else # !GENERIC -ifeq ($(CONFIG_IA64_HP_SIM),y) +ifdef CONFIG_IA64_HP_SIM SUBDIRS := arch/$(ARCH)/hp \ $(SUBDIRS) CORE_FILES := arch/$(ARCH)/hp/hp.a \ $(CORE_FILES) endif -ifeq ($(CONFIG_IA64_SGI_SN1_SIM),y) +ifdef CONFIG_IA64_SGI_SN1_SIM SUBDIRS := arch/$(ARCH)/sn/sn1 \ arch/$(ARCH)/sn \ $(SUBDIRS) @@ -49,14 +49,14 @@ $(CORE_FILES) endif -ifeq ($(CONFIG_IA64_SOFTSDV),y) +ifdef CONFIG_IA64_SOFTSDV SUBDIRS := arch/$(ARCH)/dig \ $(SUBDIRS) CORE_FILES := arch/$(ARCH)/dig/dig.a \ $(CORE_FILES) endif -ifeq ($(CONFIG_IA64_DIG),y) +ifdef CONFIG_IA64_DIG SUBDIRS := arch/$(ARCH)/dig \ $(SUBDIRS) CORE_FILES := arch/$(ARCH)/dig/dig.a \ @@ -65,14 +65,9 @@ endif # !GENERIC -ifeq ($(CONFIG_IA32_SUPPORT),y) +ifdef CONFIG_IA32_SUPPORT SUBDIRS := arch/$(ARCH)/ia32 $(SUBDIRS) CORE_FILES := arch/$(ARCH)/ia32/ia32.o $(CORE_FILES) -endif - -ifdef CONFIG_KDB - LIBS := $(LIBS) $(TOPDIR)/arch/$(ARCH)/kdb/kdb.a - SUBDIRS := $(SUBDIRS) arch/$(ARCH)/kdb endif HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o diff -urN linux-2.3.51/arch/ia64/config.in linux-2.3.51-lia/arch/ia64/config.in --- linux-2.3.51/arch/ia64/config.in Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/config.in Tue Mar 28 13:46:33 2000 @@ -24,6 +24,7 @@ bool ' Enable Lion hacks' CONFIG_IA64_LION_HACKS n bool ' Emulate PAL/SAL/EFI firmware' CONFIG_IA64_FW_EMU n bool ' Get PCI IRQ routing from firmware/ACPI' CONFIG_IA64_IRQ_ACPI y + bool ' Enable IA64 Machine Check Abort' CONFIG_IA64_MCA n fi if [ "$CONFIG_IA64_GENERIC" = "y" ]; then @@ -165,10 +166,5 @@ bool 'Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG n bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ n bool 'Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS n -bool 'Built-in Kernel Debugger support' CONFIG_KDB -if [ "$CONFIG_KDB" = "y" ]; then - bool 'Compile the kernel with frame pointers' CONFIG_KDB_FRAMEPTR - int 'KDB Kernel Symbol Table size?' CONFIG_KDB_STBSIZE 10000 -fi endmenu diff -urN linux-2.3.51/arch/ia64/dig/Makefile linux-2.3.51-lia/arch/ia64/dig/Makefile --- linux-2.3.51/arch/ia64/dig/Makefile Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/dig/Makefile Tue Mar 28 13:45:20 2000 @@ -15,7 +15,7 @@ O_TARGET = dig.a O_OBJS = iosapic.o setup.o -ifeq ($(CONFIG_IA64_GENERIC),y) +ifdef CONFIG_IA64_GENERIC O_OBJS += machvec.o endif diff -urN linux-2.3.51/arch/ia64/dig/iosapic.c linux-2.3.51-lia/arch/ia64/dig/iosapic.c --- linux-2.3.51/arch/ia64/dig/iosapic.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/dig/iosapic.c Mon Apr 3 23:05:59 2000 @@ -12,11 +12,11 @@ #include #include -#include #include #include #include #include +#include #include #include @@ -210,8 +210,11 @@ set_rte (unsigned long iosapic_addr, int entry, int pol, int trigger, int delivery, long dest, int vector) { - int low32; - int high32; + u32 low32; + u32 high32; + +if (entry == 15) printk("set_rte(addr=%lx,entry=%d,pol=%d,trigger=%d,delivery=%d,dest=%lx,vector=%d)\n", + iosapic_addr, entry, pol, trigger, delivery, dest, vector); low32 = ((pol << IO_SAPIC_POLARITY_SHIFT) | (trigger << IO_SAPIC_TRIGGER_SHIFT) | @@ -234,7 +237,7 @@ static void enable_pin (unsigned int pin, unsigned long iosapic_addr) { - int low32; + u32 low32; writel(IO_SAPIC_RTE_LOW(pin), iosapic_addr + IO_SAPIC_REG_SELECT); low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); @@ -247,7 +250,7 @@ static void disable_pin (unsigned int pin, unsigned long iosapic_addr) { - int low32; + u32 low32; writel(IO_SAPIC_RTE_LOW(pin), iosapic_addr + IO_SAPIC_REG_SELECT); low32 = readl(iosapic_addr + IO_SAPIC_WINDOW); @@ -256,14 +259,13 @@ writel(low32, iosapic_addr + IO_SAPIC_WINDOW); } -#define iosapic_shutdown_irq iosapic_disable_irq - static unsigned int iosapic_startup_irq (unsigned int irq) { - int pin; + int pin = iosapic_pin(irq); - pin = iosapic_pin(irq); +if (irq == 65) printk("iosapic_startup_irq(irq=65,status=0x%x,pin=%d)\n", + irq_desc[irq].status, pin); if (pin < 0) /* happens during irq auto probing... */ return 0; @@ -278,6 +280,8 @@ { int pin = iosapic_pin(irq); +if (irq == 65) printk("iosapic_enable_irq(irq=65,status=0x%x,pin=%d)\n", + irq_desc[irq].status, pin); if (pin < 0) /* happens during irq auto probing... */ return; @@ -289,6 +293,7 @@ { int pin = iosapic_pin(irq); +if (irq == 65) printk("iosapic_disable_irq(irq=65, status=0x%x)\n", irq_desc[irq].status); if (pin < 0) return; disable_pin(pin, iosapic_addr(irq)); @@ -331,12 +336,12 @@ void iosapic_init (unsigned long address) { - int i; + int i; #ifdef CONFIG_IA64_IRQ_ACPI struct pci_vector_struct *vectors; - int irq; + int irq; #else - int vector; + int vector; #endif /* @@ -393,7 +398,7 @@ } #else /* !defined(CONFIG_IA64_SOFTSDV_HACKS) && defined(CONFIG_IA64_IRQ_ACPI) */ /* - * Map the legacy ISA devices into the IOAPIC data; We'll override these + * Map the legacy ISA devices into the IOSAPIC data; We'll override these * later with data from the ACPI Interrupt Source Override table. * * Huh, the Lion w/ FPSWA firmware has entries for _all_ of the legacy IRQs, @@ -402,7 +407,7 @@ * here, so that this works on BigSur but will go ask Intel. --wfd 2000-Jan-19 * */ - for (i =0 ; i < 16; i++) { + for (i = 0; i < 16; i++) { irq = isa_irq_to_vector(i); iosapic_pin(irq) = i; iosapic_bus(irq) = BUS_ISA; @@ -451,7 +456,7 @@ struct hw_interrupt_type irq_type_iosapic = { typename: "IOSAPIC", startup: iosapic_startup_irq, - shutdown: iosapic_shutdown_irq, + shutdown: iosapic_disable_irq, enable: iosapic_enable_irq, disable: iosapic_disable_irq, ack: iosapic_ack_irq, @@ -464,25 +469,19 @@ { int i; - /* - * Claim all non-legacy irq vectors as ours unless they're - * claimed by someone else already (e.g., timer or IPI are - * handled internally). - */ -#if 0 - for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) { - if (irq_desc[i].handler == &no_irq_type) - irq_desc[i].handler = &irq_type_iosapic; - } -#else - for (i = 0; i <= IA64_MAX_VECTORED_IRQ; ++i) { - if (irq_desc[i].handler == &no_irq_type) - irq_desc[i].handler = &irq_type_iosapic; - } -#endif #ifndef CONFIG_IA64_DIG iosapic_init(IO_SAPIC_DEFAULT_ADDR); #endif + + for (i = 0; i < NR_IRQS; ++i) { + if (iosapic_pin(i) != -1) { + if (irq_desc[i].handler != &no_irq_type) + printk("dig_irq_init: warning: changing vector %d from %s to %s\n", + i, irq_desc[i].handler->typename, + irq_type_iosapic.typename); + irq_desc[i].handler = &irq_type_iosapic; + } + } } void diff -urN linux-2.3.51/arch/ia64/hp/Makefile linux-2.3.51-lia/arch/ia64/hp/Makefile --- linux-2.3.51/arch/ia64/hp/Makefile Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/hp/Makefile Tue Mar 28 13:45:06 2000 @@ -10,7 +10,7 @@ O_TARGET = hp.a O_OBJS = hpsim_console.o hpsim_irq.o hpsim_setup.o -ifeq ($(CONFIG_IA64_GENERIC),y) +ifdef CONFIG_IA64_GENERIC O_OBJS += hpsim_machvec.o endif diff -urN linux-2.3.51/arch/ia64/ia32/Makefile linux-2.3.51-lia/arch/ia64/ia32/Makefile --- linux-2.3.51/arch/ia64/ia32/Makefile Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/ia32/Makefile Mon Apr 10 21:20:36 2000 @@ -10,7 +10,7 @@ all: ia32.o O_TARGET := ia32.o -O_OBJS := ia32_entry.o ia32_signal.o sys_ia32.o ia32_support.o binfmt_elf32.o +O_OBJS := ia32_entry.o sys_ia32.o ia32_signal.o ia32_support.o ia32_traps.o binfmt_elf32.o clean:: diff -urN linux-2.3.51/arch/ia64/ia32/binfmt_elf32.c linux-2.3.51-lia/arch/ia64/ia32/binfmt_elf32.c --- linux-2.3.51/arch/ia64/ia32/binfmt_elf32.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/ia32/binfmt_elf32.c Mon Apr 10 21:12:42 2000 @@ -134,6 +134,19 @@ regs->cr_ipsr &= ~IA64_PSR_AC; regs->loadrs = 0; + /* + * According to the ABI %edx points to an `atexit' handler. + * Since we don't have one we'll set it to 0 and initialize + * all the other registers just to make things more deterministic, + * ala the i386 implementation. + */ + regs->r8 = 0; /* %eax */ + regs->r11 = 0; /* %ebx */ + regs->r9 = 0; /* %ecx */ + regs->r10 = 0; /* %edx */ + regs->r13 = 0; /* %ebp */ + regs->r14 = 0; /* %esi */ + regs->r15 = 0; /* %edi */ } #undef STACK_TOP diff -urN linux-2.3.51/arch/ia64/ia32/ia32_entry.S linux-2.3.51-lia/arch/ia64/ia32/ia32_entry.S --- linux-2.3.51/arch/ia64/ia32/ia32_entry.S Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/arch/ia64/ia32/ia32_entry.S Mon Apr 10 21:12:42 2000 @@ -1,14 +1,55 @@ #include #include + // + // Get possibly unaligned sigmask argument into an aligned + // kernel buffer + .text + .proc ia32_rt_sigsuspend + .global ia32_rt_sigsuspend +ia32_rt_sigsuspend: + + // We'll cheat and not do an alloc here since we are ultimately + // going to do a simple branch to the IA64 sys_rt_sigsuspend. + // r32 is still the first argument which is the signal mask. + // We copy this 4-byte aligned value to an 8-byte aligned buffer + // in the task structure and then jump to the IA64 code. + + mov r8=r0 // no memory access errors yet + add r10=4,r32 + ;; +1: + ld4 r2=[r32] // get first half of sigmask + ld4 r3=[r10] // get second half of sigmask +2: + cmp.lt p6,p0=r8,r0 // check memory access + ;; +(p6) br.ret.sptk.many rp // it failed + + adds r32=IA64_TASK_THREAD_SIGMASK_OFFSET,r13 + adds r10=IA64_TASK_THREAD_SIGMASK_OFFSET+4,r13 + ;; + st4 [r32]=r2 + st4 [r10]=r3 + br.cond.sptk.many sys_rt_sigsuspend + + .section __ex_table,"a" + data4 @gprel(1b) + data4 (2b-1b)|1 + .previous + + + .endp ia32_rt_sigsuspend + .global ia32_ret_from_syscall - .proc ia64_ret_from_syscall + .proc ia32_ret_from_syscall ia32_ret_from_syscall: cmp.ge p6,p7=r8,r0 // syscall executed successfully? adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 ;; st8 [r2]=r8 // store return value in slot for r8 br.cond.sptk.few ia64_leave_kernel + .endp ia32_ret_from_syscall // // Invoke a system call, but do some tracing before and after the call. @@ -35,10 +76,21 @@ .endp ia32_trace_syscall .align 16 + .global sys32_vfork + .proc sys32_vfork +sys32_vfork: + alloc r16=ar.pfs,2,2,3,0;; + mov out0=IA64_CLONE_VFORK|IA64_CLONE_VM|SIGCHLD // out0 = clone_flags + br.cond.sptk.few .fork1 // do the work + .endp sys32_vfork + + .align 16 .global sys32_fork .proc sys32_fork sys32_fork: alloc r16=ar.pfs,2,2,3,0;; + mov out0=SIGCHLD // out0 = clone_flags +.fork1: movl r28=1f mov loc1=rp br.cond.sptk.many save_switch_stack @@ -46,7 +98,6 @@ mov loc0=r16 // save ar.pfs across do_fork adds out2=IA64_SWITCH_STACK_SIZE+16,sp adds r2=IA64_SWITCH_STACK_SIZE+IA64_PT_REGS_R12_OFFSET+16,sp - mov out0=SIGCHLD // out0 = clone_flags ;; ld8 out1=[r2] // fetch usp from pt_regs.r12 br.call.sptk.few rp=do_fork @@ -88,7 +139,7 @@ data8 sys_setuid data8 sys_getuid data8 sys_ni_syscall /* sys_stime is not supported on IA64 */ /* 25 */ - data8 sys_ptrace + data8 sys32_ptrace data8 sys32_alarm data8 sys_ni_syscall data8 sys_ni_syscall @@ -105,7 +156,7 @@ data8 sys_rmdir /* 40 */ data8 sys_dup data8 sys32_pipe - data8 sys_times + data8 sys32_times data8 sys_ni_syscall /* old prof syscall holder */ data8 sys_brk /* 45 */ data8 sys_setgid @@ -139,7 +190,7 @@ data8 sys_sethostname data8 sys32_setrlimit /* 75 */ data8 sys32_getrlimit - data8 sys_getrusage + data8 sys32_getrusage data8 sys32_gettimeofday data8 sys32_settimeofday data8 sys_getgroups /* 80 */ @@ -241,7 +292,7 @@ data8 sys_rt_sigpending data8 sys_rt_sigtimedwait data8 sys_rt_sigqueueinfo - data8 sys_rt_sigsuspend + data8 ia32_rt_sigsuspend data8 sys_pread /* 180 */ data8 sys_pwrite data8 sys_chown diff -urN linux-2.3.51/arch/ia64/ia32/ia32_signal.c linux-2.3.51-lia/arch/ia64/ia32/ia32_signal.c --- linux-2.3.51/arch/ia64/ia32/ia32_signal.c Sun Feb 13 10:30:38 2000 +++ linux-2.3.51-lia/arch/ia64/ia32/ia32_signal.c Mon Apr 10 21:12:42 2000 @@ -94,7 +94,9 @@ err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate); /* non-iBCS2 extensions.. */ +#endif err |= __put_user(mask, &sc->oldmask); +#if 0 err |= __put_user(current->tss.cr2, &sc->cr2); #endif @@ -196,7 +198,7 @@ return (void *)((esp - frame_size) & -8ul); } -static void +static int setup_frame_ia32(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { @@ -247,20 +249,21 @@ regs->eflags &= ~TF_MASK; #endif -#if 1 - printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n", - current->comm, current->pid, frame, regs->cr_iip, frame->pretcode); +#if 0 + printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n", + current->comm, current->pid, sig, frame, regs->cr_iip, frame->pretcode); #endif - return; + return 1; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); + return 0; } -static void +static int setup_rt_frame_ia32(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { @@ -316,29 +319,29 @@ regs->eflags &= ~TF_MASK; #endif -#if 1 +#if 0 printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n", current->comm, current->pid, frame, regs->cr_iip, frame->pretcode); #endif - return; + return 1; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); + return 0; } -long +int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame_ia32(sig, ka, info, set, regs); + return(setup_rt_frame_ia32(sig, ka, info, set, regs)); else - setup_frame_ia32(sig, ka, set, regs); - + return(setup_frame_ia32(sig, ka, set, regs)); } asmlinkage int diff -urN linux-2.3.51/arch/ia64/ia32/ia32_traps.c linux-2.3.51-lia/arch/ia64/ia32/ia32_traps.c --- linux-2.3.51/arch/ia64/ia32/ia32_traps.c Wed Dec 31 16:00:00 1969 +++ linux-2.3.51-lia/arch/ia64/ia32/ia32_traps.c Mon Apr 10 21:23:35 2000 @@ -0,0 +1,47 @@ +#include +#include + +#include +#include + +int +ia32_exception (struct pt_regs *regs, unsigned long isr) +{ + struct siginfo siginfo; + + switch ((isr >> 16) & 0xff) { + case 1: + case 2: + if (isr == 0) + siginfo.si_code = TRAP_TRACE; + else if (isr & 0x4) + siginfo.si_code = TRAP_BRANCH; + else + siginfo.si_code = TRAP_BRKPT; + break; + + case 3: + siginfo.si_code = TRAP_BRKPT; + break; + + case 0: /* Divide fault */ + case 4: /* Overflow */ + case 5: /* Bounds fault */ + case 6: /* Invalid Op-code */ + case 7: /* FP DNA */ + case 8: /* Double Fault */ + case 9: /* Invalid TSS */ + case 11: /* Segment not present */ + case 12: /* Stack fault */ + case 13: /* General Protection Fault */ + case 16: /* Pending FP error */ + case 17: /* Alignment check */ + case 19: /* SSE Numeric error */ + default: + return -1; + } + siginfo.si_signo = SIGTRAP; + siginfo.si_errno = 0; + send_sig_info(SIGTRAP, &siginfo, current); + return 0; +} diff -urN linux-2.3.51/arch/ia64/ia32/sys_ia32.c linux-2.3.51-lia/arch/ia64/ia32/sys_ia32.c --- linux-2.3.51/arch/ia64/ia32/sys_ia32.c Sat Feb 26 20:33:02 2000 +++ linux-2.3.51-lia/arch/ia64/ia32/sys_ia32.c Mon Apr 10 21:28:33 2000 @@ -58,32 +58,6 @@ #define A(__x) ((unsigned long)(__x)) #define AA(__x) ((unsigned long)(__x)) -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage int sys32_vfork( -int dummy0, -int dummy1, -int dummy2, -int dummy3, -int dummy4, -int dummy5, -int dummy6, -int dummy7, -int stack) -{ - struct pt_regs *regs = (struct pt_regs *)&stack; - - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r12, regs); -} - static int nargs(unsigned int arg, char **ap) { @@ -842,82 +816,6 @@ return sys32_select(a.n, a.inp, a.outp, a.exp, a.tvp); } -struct rusage32 { - struct timeval32 ru_utime; - struct timeval32 ru_stime; - int ru_maxrss; - int ru_ixrss; - int ru_idrss; - int ru_isrss; - int ru_minflt; - int ru_majflt; - int ru_nswap; - int ru_inblock; - int ru_oublock; - int ru_msgsnd; - int ru_msgrcv; - int ru_nsignals; - int ru_nvcsw; - int ru_nivcsw; -}; - -static int -put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - -extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, - int options, struct rusage * ru); - -asmlinkage int -sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, - struct rusage32 *ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - if (stat_addr && put_user (status, stat_addr)) - return -EFAULT; - return ret; - } -} - -asmlinkage int -sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options) -{ - return sys32_wait4(pid, stat_addr, options, NULL); -} - struct timespec32 { int tv_sec; int tv_nsec; @@ -1586,367 +1484,904 @@ { union semun fourth; u32 pad; - int err = -EINVAL; + int err, err2; + struct semid64_ds s; + struct semid_ds32 *usp; + mm_segment_t old_fs; if (!uptr) - goto out; + return -EINVAL; err = -EFAULT; if (get_user (pad, (u32 *)uptr)) - goto out; + return err; if(third == SETVAL) fourth.val = (int)pad; else fourth.__pad = (void *)A(pad); - if (IPCOP_MASK (third) & - (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | - IPCOP_MASK (GETVAL) | IPCOP_MASK (GETPID) | - IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) | - IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | - IPCOP_MASK (IPC_RMID))) { + switch (third) { + + case IPC_INFO: + case IPC_RMID: + case IPC_SET: + case SEM_INFO: + case GETVAL: + case GETPID: + case GETNCNT: + case GETZCNT: + case GETALL: + case SETVAL: + case SETALL: err = sys_semctl (first, second, third, fourth); - } else { - struct semid_ds s; - struct semid_ds32 *usp = (struct semid_ds32 *)A(pad); - mm_segment_t old_fs; - int need_back_translation; + break; - if (third == IPC_SET) { - err = get_user (s.sem_perm.uid, &usp->sem_perm.uid); - err |= __get_user(s.sem_perm.gid, &usp->sem_perm.gid); - err |= __get_user(s.sem_perm.mode, &usp->sem_perm.mode); - if (err) - goto out; - fourth.__pad = &s; - } - need_back_translation = - (IPCOP_MASK (third) & - (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0; - if (need_back_translation) - fourth.__pad = &s; + case IPC_STAT: + case SEM_STAT: + usp = (struct semid_ds32 *)A(pad); + fourth.__pad = &s; old_fs = get_fs (); set_fs (KERNEL_DS); err = sys_semctl (first, second, third, fourth); set_fs (old_fs); - if (need_back_translation) { - int err2 = put_user(s.sem_perm.key, &usp->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, - &usp->sem_perm.cuid); - err2 |= __put_user (s.sem_perm.cgid, - &usp->sem_perm.cgid); - err2 |= __put_user (s.sem_perm.mode, - &usp->sem_perm.mode); - err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); - err2 |= __put_user (s.sem_otime, &usp->sem_otime); - err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); - err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); - if (err2) err = -EFAULT; - } + err2 = put_user(s.sem_perm.key, &usp->sem_perm.key); + err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid); + err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid); + err2 |= __put_user(s.sem_perm.cuid, + &usp->sem_perm.cuid); + err2 |= __put_user (s.sem_perm.cgid, + &usp->sem_perm.cgid); + err2 |= __put_user (s.sem_perm.mode, + &usp->sem_perm.mode); + err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); + err2 |= __put_user (s.sem_otime, &usp->sem_otime); + err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); + err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); + if (err2) + err = -EFAULT; + break; + } -out: + return err; } static int do_sys32_msgsnd (int first, int second, int third, void *uptr) { - struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) - + 4, GFP_USER); - struct msgbuf32 *up = (struct msgbuf32 *)uptr; - mm_segment_t old_fs; - int err; + struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + + 4, GFP_USER); + struct msgbuf32 *up = (struct msgbuf32 *)uptr; + mm_segment_t old_fs; + int err; + + if (!p) + return -ENOMEM; + err = get_user (p->mtype, &up->mtype); + err |= __copy_from_user (p->mtext, &up->mtext, second); + if (err) + goto out; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgsnd (first, p, second, third); + set_fs (old_fs); +out: + kfree (p); + return err; +} + +static int +do_sys32_msgrcv (int first, int second, int msgtyp, int third, + int version, void *uptr) +{ + struct msgbuf32 *up; + struct msgbuf *p; + mm_segment_t old_fs; + int err; + + if (!version) { + struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; + struct ipc_kludge ipck; + + err = -EINVAL; + if (!uptr) + goto out; + err = -EFAULT; + if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge))) + goto out; + uptr = (void *)A(ipck.msgp); + msgtyp = ipck.msgtyp; + } + err = -ENOMEM; + p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); + if (!p) + goto out; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgrcv (first, p, second + 4, msgtyp, third); + set_fs (old_fs); + if (err < 0) + goto free_then_out; + up = (struct msgbuf32 *)uptr; + if (put_user (p->mtype, &up->mtype) || + __copy_to_user (&up->mtext, p->mtext, err)) + err = -EFAULT; +free_then_out: + kfree (p); +out: + return err; +} + +static int +do_sys32_msgctl (int first, int second, void *uptr) +{ + int err, err2; + struct msqid_ds m; + struct msqid64_ds m64; + struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; + mm_segment_t old_fs; + + switch (second) { + + case IPC_INFO: + case IPC_RMID: + case MSG_INFO: + err = sys_msgctl (first, second, (struct msqid_ds *)uptr); + break; + + case IPC_SET: + err = get_user (m.msg_perm.uid, &up->msg_perm.uid); + err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); + err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); + err |= __get_user (m.msg_qbytes, &up->msg_qbytes); + if (err) + break; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgctl (first, second, &m); + set_fs (old_fs); + break; + + case IPC_STAT: + case MSG_STAT: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgctl (first, second, &m64); + set_fs (old_fs); + err2 = put_user (m64.msg_perm.key, &up->msg_perm.key); + err2 |= __put_user(m64.msg_perm.uid, &up->msg_perm.uid); + err2 |= __put_user(m64.msg_perm.gid, &up->msg_perm.gid); + err2 |= __put_user(m64.msg_perm.cuid, &up->msg_perm.cuid); + err2 |= __put_user(m64.msg_perm.cgid, &up->msg_perm.cgid); + err2 |= __put_user(m64.msg_perm.mode, &up->msg_perm.mode); + err2 |= __put_user(m64.msg_perm.seq, &up->msg_perm.seq); + err2 |= __put_user(m64.msg_stime, &up->msg_stime); + err2 |= __put_user(m64.msg_rtime, &up->msg_rtime); + err2 |= __put_user(m64.msg_ctime, &up->msg_ctime); + err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes); + err2 |= __put_user(m64.msg_qnum, &up->msg_qnum); + err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes); + err2 |= __put_user(m64.msg_lspid, &up->msg_lspid); + err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid); + if (err2) + err = -EFAULT; + break; + + } + + return err; +} + +static int +do_sys32_shmat (int first, int second, int third, int version, void *uptr) +{ + unsigned long raddr; + u32 *uaddr = (u32 *)A((u32)third); + int err = -EINVAL; + + if (version == 1) + return err; + err = sys_shmat (first, uptr, second, &raddr); + if (err) + return err; + err = put_user (raddr, uaddr); + return err; +} + +static int +do_sys32_shmctl (int first, int second, void *uptr) +{ + int err = -EFAULT, err2; + struct shmid_ds s; + struct shmid64_ds s64; + struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; + mm_segment_t old_fs; + struct shm_info32 { + int used_ids; + u32 shm_tot, shm_rss, shm_swp; + u32 swap_attempts, swap_successes; + } *uip = (struct shm_info32 *)uptr; + struct shm_info si; + + switch (second) { + + case IPC_INFO: + case IPC_RMID: + case SHM_LOCK: + case SHM_UNLOCK: + err = sys_shmctl (first, second, (struct shmid_ds *)uptr); + break; + case IPC_SET: + err = get_user (s.shm_perm.uid, &up->shm_perm.uid); + err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); + err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); + if (err) + break; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, &s); + set_fs (old_fs); + break; + + case IPC_STAT: + case SHM_STAT: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, &s64); + set_fs (old_fs); + if (err < 0) + break; + err2 = put_user (s64.shm_perm.key, &up->shm_perm.key); + err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid); + err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid); + err2 |= __put_user (s64.shm_perm.cuid, + &up->shm_perm.cuid); + err2 |= __put_user (s64.shm_perm.cgid, + &up->shm_perm.cgid); + err2 |= __put_user (s64.shm_perm.mode, + &up->shm_perm.mode); + err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq); + err2 |= __put_user (s64.shm_atime, &up->shm_atime); + err2 |= __put_user (s64.shm_dtime, &up->shm_dtime); + err2 |= __put_user (s64.shm_ctime, &up->shm_ctime); + err2 |= __put_user (s64.shm_segsz, &up->shm_segsz); + err2 |= __put_user (s64.shm_nattch, &up->shm_nattch); + err2 |= __put_user (s64.shm_cpid, &up->shm_cpid); + err2 |= __put_user (s64.shm_lpid, &up->shm_lpid); + if (err2) + err = -EFAULT; + break; + + case SHM_INFO: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, &si); + set_fs (old_fs); + if (err < 0) + break; + err2 = put_user (si.used_ids, &uip->used_ids); + err2 |= __put_user (si.shm_tot, &uip->shm_tot); + err2 |= __put_user (si.shm_rss, &uip->shm_rss); + err2 |= __put_user (si.shm_swp, &uip->shm_swp); + err2 |= __put_user (si.swap_attempts, + &uip->swap_attempts); + err2 |= __put_user (si.swap_successes, + &uip->swap_successes); + if (err2) + err = -EFAULT; + break; + + } + return err; +} + +asmlinkage int +sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) +{ + int version, err; + + lock_kernel(); + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + switch (call) { + + case SEMOP: + /* struct sembuf is the same on 32 and 64bit :)) */ + err = sys_semop (first, (struct sembuf *)AA(ptr), + second); + break; + case SEMGET: + err = sys_semget (first, second, third); + break; + case SEMCTL: + err = do_sys32_semctl (first, second, third, + (void *)AA(ptr)); + break; + + case MSGSND: + err = do_sys32_msgsnd (first, second, third, + (void *)AA(ptr)); + break; + case MSGRCV: + err = do_sys32_msgrcv (first, second, fifth, third, + version, (void *)AA(ptr)); + break; + case MSGGET: + err = sys_msgget ((key_t) first, second); + break; + case MSGCTL: + err = do_sys32_msgctl (first, second, (void *)AA(ptr)); + break; + + case SHMAT: + err = do_sys32_shmat (first, second, third, + version, (void *)AA(ptr)); + break; + case SHMDT: + err = sys_shmdt ((char *)AA(ptr)); + break; + case SHMGET: + err = sys_shmget (first, second, third); + break; + case SHMCTL: + err = do_sys32_shmctl (first, second, (void *)AA(ptr)); + break; + default: + err = -EINVAL; + break; + } + + unlock_kernel(); + return err; +} + +/* + * sys_time() can be implemented in user-level using + * sys_gettimeofday(). IA64 did this but i386 Linux did not + * so we have to implement this system call here. + */ +asmlinkage long sys32_time(int * tloc) +{ + int i; + + /* SMP: This is fairly trivial. We grab CURRENT_TIME and + stuff it to user space. No side effects */ + i = CURRENT_TIME; + if (tloc) { + if (put_user(i,tloc)) + i = -EFAULT; + } + return i; +} + +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int ru_maxrss; + int ru_ixrss; + int ru_idrss; + int ru_isrss; + int ru_minflt; + int ru_majflt; + int ru_nswap; + int ru_inblock; + int ru_oublock; + int ru_msgsnd; + int ru_msgrcv; + int ru_nsignals; + int ru_nvcsw; + int ru_nivcsw; +}; + +static int +put_rusage (struct rusage32 *ru, struct rusage *r) +{ + int err; + + err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); + err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); + err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); + err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); + err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); + err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); + err |= __put_user (r->ru_idrss, &ru->ru_idrss); + err |= __put_user (r->ru_isrss, &ru->ru_isrss); + err |= __put_user (r->ru_minflt, &ru->ru_minflt); + err |= __put_user (r->ru_majflt, &ru->ru_majflt); + err |= __put_user (r->ru_nswap, &ru->ru_nswap); + err |= __put_user (r->ru_inblock, &ru->ru_inblock); + err |= __put_user (r->ru_oublock, &ru->ru_oublock); + err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); + err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); + err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); + err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); + err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); + return err; +} + +extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, + int options, struct rusage * ru); + +asmlinkage int +sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, + struct rusage32 *ru) +{ + if (!ru) + return sys_wait4(pid, stat_addr, options, NULL); + else { + struct rusage r; + int ret; + unsigned int status; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); + set_fs (old_fs); + if (put_rusage (ru, &r)) return -EFAULT; + if (stat_addr && put_user (status, stat_addr)) + return -EFAULT; + return ret; + } +} + +asmlinkage int +sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options) +{ + return sys32_wait4(pid, stat_addr, options, NULL); +} + + +extern asmlinkage int +sys_getrusage(int who, struct rusage *ru); + +asmlinkage int +sys32_getrusage(int who, struct rusage32 *ru) +{ + struct rusage r; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_getrusage(who, &r); + set_fs (old_fs); + if (put_rusage (ru, &r)) return -EFAULT; + return ret; +} + +struct tms32 { + __kernel_clock_t32 tms_utime; + __kernel_clock_t32 tms_stime; + __kernel_clock_t32 tms_cutime; + __kernel_clock_t32 tms_cstime; +}; + +extern asmlinkage long sys_times(struct tms * tbuf); + +asmlinkage long +sys32_times(struct tms32 *tbuf) +{ + struct tms t; + long ret; + mm_segment_t old_fs = get_fs (); + int err; + + set_fs (KERNEL_DS); + ret = sys_times(tbuf ? &t : NULL); + set_fs (old_fs); + if (tbuf) { + err = put_user (t.tms_utime, &tbuf->tms_utime); + err |= __put_user (t.tms_stime, &tbuf->tms_stime); + err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); + err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); + if (err) + ret = -EFAULT; + } + return ret; +} + +unsigned int +ia32_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int *val) +{ + size_t copied; + unsigned int ret; + + copied = access_process_vm(child, addr, val, sizeof(*val), 0); + return(copied != sizeof(ret) ? -EIO : 0); +} + +unsigned int +ia32_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int val) +{ + + if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) + return -EIO; + return 0; +} + +/* + * The order in which registers are stored in the ptrace regs structure + */ +#define PT_EBX 0 +#define PT_ECX 1 +#define PT_EDX 2 +#define PT_ESI 3 +#define PT_EDI 4 +#define PT_EBP 5 +#define PT_EAX 6 +#define PT_DS 7 +#define PT_ES 8 +#define PT_FS 9 +#define PT_GS 10 +#define PT_ORIG_EAX 11 +#define PT_EIP 12 +#define PT_CS 13 +#define PT_EFL 14 +#define PT_UESP 15 +#define PT_SS 16 + +unsigned int +getreg(struct task_struct *child, int regno) +{ + struct pt_regs *child_regs; + + child_regs = ia64_task_regs(child); + switch (regno / sizeof(int)) { + + case PT_EBX: + return(child_regs->r11); + case PT_ECX: + return(child_regs->r9); + case PT_EDX: + return(child_regs->r10); + case PT_ESI: + return(child_regs->r14); + case PT_EDI: + return(child_regs->r15); + case PT_EBP: + return(child_regs->r13); + case PT_EAX: + case PT_ORIG_EAX: + return(child_regs->r8); + case PT_EIP: + return(child_regs->cr_iip); + case PT_UESP: + return(child_regs->r12); + case PT_EFL: + return(child->thread.eflag); + case PT_DS: + case PT_ES: + case PT_FS: + case PT_GS: + case PT_SS: + return((unsigned int)__USER_DS); + case PT_CS: + return((unsigned int)__USER_CS); + default: + printk("getregs:unknown register %d\n", regno); + break; + + } + return(0); +} + +void +putreg(struct task_struct *child, int regno, unsigned int value) +{ + struct pt_regs *child_regs; + + child_regs = ia64_task_regs(child); + switch (regno / sizeof(int)) { + + case PT_EBX: + child_regs->r11 = value; + break; + case PT_ECX: + child_regs->r9 = value; + break; + case PT_EDX: + child_regs->r10 = value; + break; + case PT_ESI: + child_regs->r14 = value; + break; + case PT_EDI: + child_regs->r15 = value; + break; + case PT_EBP: + child_regs->r13 = value; + break; + case PT_EAX: + case PT_ORIG_EAX: + child_regs->r8 = value; + break; + case PT_EIP: + child_regs->cr_iip = value; + break; + case PT_UESP: + child_regs->r12 = value; + break; + case PT_EFL: + child->thread.eflag = value; + break; + case PT_DS: + case PT_ES: + case PT_FS: + case PT_GS: + case PT_SS: + if (value != __USER_DS) + printk("setregs:try to set invalid segment register %d = %x\n", regno, value); + break; + case PT_CS: + if (value != __USER_CS) + printk("setregs:try to set invalid segment register %d = %x\n", regno, value); + break; + default: + printk("getregs:unknown register %d\n", regno); + break; + + } +} + +static inline void +ia32f2ia64f(void *dst, void *src) +{ + + __asm__ ("ldfe f6=[%1] ;;\n\t" + "stf.spill [%0]=f6" + : + : "r"(dst), "r"(src)); + return; +} + +static inline void +ia64f2ia32f(void *dst, void *src) +{ - if (!p) - return -ENOMEM; - err = get_user (p->mtype, &up->mtype); - err |= __copy_from_user (p->mtext, &up->mtext, second); - if (err) - goto out; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgsnd (first, p, second, third); - set_fs (old_fs); -out: - kfree (p); - return err; + __asm__ ("ldf.fill f6=[%1] ;;\n\t" + "stfe [%0]=f6" + : + : "r"(dst), "r"(src)); + return; } -static int -do_sys32_msgrcv (int first, int second, int msgtyp, int third, - int version, void *uptr) +void +put_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos) { - struct msgbuf32 *up; - struct msgbuf *p; - mm_segment_t old_fs; - int err; + struct _fpreg_ia32 *f; + char buf[32]; - if (!version) { - struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; - struct ipc_kludge ipck; + f = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); + if ((regno += tos) >= 8) + regno -= 8; + switch (regno) { + + case 0: + ia64f2ia32f(f, &ptp->f8); + break; + case 1: + ia64f2ia32f(f, &ptp->f9); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + ia64f2ia32f(f, &swp->f10 + (regno - 2)); + break; - err = -EINVAL; - if (!uptr) - goto out; - err = -EFAULT; - if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge))) - goto out; - uptr = (void *)A(ipck.msgp); - msgtyp = ipck.msgtyp; } - err = -ENOMEM; - p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); - if (!p) - goto out; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgrcv (first, p, second + 4, msgtyp, third); - set_fs (old_fs); - if (err < 0) - goto free_then_out; - up = (struct msgbuf32 *)uptr; - if (put_user (p->mtype, &up->mtype) || - __copy_to_user (&up->mtext, p->mtext, err)) - err = -EFAULT; -free_then_out: - kfree (p); -out: - return err; + __copy_to_user(reg, f, sizeof(*reg)); + return; } -static int -do_sys32_msgctl (int first, int second, void *uptr) +void +get_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos) { - int err; - if (IPCOP_MASK (second) & - (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) | - IPCOP_MASK (IPC_RMID))) { - err = sys_msgctl (first, second, (struct msqid_ds *)uptr); - } else { - struct msqid_ds m; - struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; - mm_segment_t old_fs; + if ((regno += tos) >= 8) + regno -= 8; + switch (regno) { - if (second == IPC_SET) { - err = get_user (m.msg_perm.uid, &up->msg_perm.uid); - err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); - err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); - err |= __get_user (m.msg_qbytes, &up->msg_qbytes); - if (err) - goto out; - } - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgctl (first, second, &m); - set_fs (old_fs); - if (IPCOP_MASK (second) & - (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) { - int err2 = put_user (m.msg_perm.key, &up->msg_perm.key); - err2 |= __put_user(m.msg_perm.uid, &up->msg_perm.uid); - err2 |= __put_user(m.msg_perm.gid, &up->msg_perm.gid); - err2 |= __put_user(m.msg_perm.cuid, &up->msg_perm.cuid); - err2 |= __put_user(m.msg_perm.cgid, &up->msg_perm.cgid); - err2 |= __put_user(m.msg_perm.mode, &up->msg_perm.mode); - err2 |= __put_user(m.msg_perm.seq, &up->msg_perm.seq); - err2 |= __put_user(m.msg_stime, &up->msg_stime); - err2 |= __put_user(m.msg_rtime, &up->msg_rtime); - err2 |= __put_user(m.msg_ctime, &up->msg_ctime); - err2 |= __put_user(m.msg_cbytes, &up->msg_cbytes); - err2 |= __put_user(m.msg_qnum, &up->msg_qnum); - err2 |= __put_user(m.msg_qbytes, &up->msg_qbytes); - err2 |= __put_user(m.msg_lspid, &up->msg_lspid); - err2 |= __put_user(m.msg_lrpid, &up->msg_lrpid); - if (err2) - err = -EFAULT; - } - } + case 0: + __copy_from_user(&ptp->f8, reg, sizeof(*reg)); + break; + case 1: + __copy_from_user(&ptp->f9, reg, sizeof(*reg)); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + __copy_from_user(&swp->f10 + (regno - 2), reg, sizeof(*reg)); + break; -out: - return err; + } + return; } -static int -do_sys32_shmat (int first, int second, int third, int version, void *uptr) +int +save_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save) { - unsigned long raddr; - u32 *uaddr = (u32 *)A((u32)third); - int err = -EINVAL; + struct switch_stack *swp; + struct pt_regs *ptp; + int i, tos; + + if (!access_ok(VERIFY_WRITE, save, sizeof(*save))) + return(-EIO); + __put_user(tsk->thread.fcr, &save->cw); + __put_user(tsk->thread.fsr, &save->sw); + __put_user(tsk->thread.fsr >> 32, &save->tag); + __put_user(tsk->thread.fir, &save->ipoff); + __put_user(__USER_CS, &save->cssel); + __put_user(tsk->thread.fdr, &save->dataoff); + __put_user(__USER_DS, &save->datasel); + /* + * Stack frames start with 16-bytes of temp space + */ + swp = (struct switch_stack *)(tsk->thread.ksp + 16); + ptp = ia64_task_regs(tsk); + tos = (tsk->thread.fsr >> 11) & 3; + for (i = 0; i < 8; i++) + put_fpreg(i, &save->_st[i], ptp, swp, tos); + return(0); +} - if (version == 1) - goto out; - err = sys_shmat (first, uptr, second, &raddr); - if (err) - goto out; - err = put_user (raddr, uaddr); -out: - return err; +int +restore_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save) +{ + struct switch_stack *swp; + struct pt_regs *ptp; + int i, tos; + int fsrlo, fsrhi; + + if (!access_ok(VERIFY_READ, save, sizeof(*save))) + return(-EIO); + __get_user(tsk->thread.fcr, (unsigned int *)&save->cw); + __get_user(fsrlo, (unsigned int *)&save->sw); + __get_user(fsrhi, (unsigned int *)&save->tag); + tsk->thread.fsr = ((long)fsrhi << 32) | (long)fsrlo; + __get_user(tsk->thread.fir, (unsigned int *)&save->ipoff); + __get_user(tsk->thread.fdr, (unsigned int *)&save->dataoff); + /* + * Stack frames start with 16-bytes of temp space + */ + swp = (struct switch_stack *)(tsk->thread.ksp + 16); + ptp = ia64_task_regs(tsk); + tos = (tsk->thread.fsr >> 11) & 3; + for (i = 0; i < 8; i++) + get_fpreg(i, &save->_st[i], ptp, swp, tos); + return(0); } -static int -do_sys32_shmctl (int first, int second, void *uptr) +asmlinkage long sys_ptrace(long, pid_t, unsigned long, unsigned long, long, long, long, long, long); + +/* + * Note that the IA32 version of `ptrace' calls the IA64 routine for + * many of the requests. This will only work for requests that do + * not need access to the calling processes `pt_regs' which is located + * at the address of `stack'. Once we call the IA64 `sys_ptrace' then + * the address of `stack' will not be the address of the `pt_regs'. + */ +asmlinkage long +sys32_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, + long arg4, long arg5, long arg6, long arg7, long stack) { - int err; + struct pt_regs *regs = (struct pt_regs *) &stack; + struct task_struct *child; + long i, ret; + unsigned int value; - if (IPCOP_MASK (second) & - (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) - | IPCOP_MASK (SHM_UNLOCK) | IPCOP_MASK (IPC_RMID))) { - err = sys_shmctl (first, second, (struct shmid_ds *)uptr); - } else { - struct shmid_ds s; - struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; - mm_segment_t old_fs; + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = sys_ptrace(request, pid, addr, data, + arg4, arg5, arg6, arg7, stack); + goto out; + } - if (second == IPC_SET) { - err = get_user (s.shm_perm.uid, &up->shm_perm.uid); - err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); - err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); - if (err) - goto out; - } - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_shmctl (first, second, &s); - set_fs (old_fs); - if (err < 0) - goto out; + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + read_unlock(&tasklist_lock); + if (!child) + goto out; + ret = -EPERM; + if (pid == 1) /* no messing around with init! */ + goto out; - /* Mask it even in this case so it becomes a CSE. */ - if (second == SHM_INFO) { - struct shm_info32 { - int used_ids; - u32 shm_tot, shm_rss, shm_swp; - u32 swap_attempts, swap_successes; - } *uip = (struct shm_info32 *)uptr; - struct shm_info *kp = (struct shm_info *)&s; - int err2 = put_user (kp->used_ids, &uip->used_ids); - err2 |= __put_user (kp->shm_tot, &uip->shm_tot); - err2 |= __put_user (kp->shm_rss, &uip->shm_rss); - err2 |= __put_user (kp->shm_swp, &uip->shm_swp); - err2 |= __put_user (kp->swap_attempts, - &uip->swap_attempts); - err2 |= __put_user (kp->swap_successes, - &uip->swap_successes); - if (err2) - err = -EFAULT; - } else if (IPCOP_MASK (second) & - (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) { - int err2 = put_user (s.shm_perm.key, &up->shm_perm.key); - err2 |= __put_user (s.shm_perm.uid, &up->shm_perm.uid); - err2 |= __put_user (s.shm_perm.gid, &up->shm_perm.gid); - err2 |= __put_user (s.shm_perm.cuid, - &up->shm_perm.cuid); - err2 |= __put_user (s.shm_perm.cgid, - &up->shm_perm.cgid); - err2 |= __put_user (s.shm_perm.mode, - &up->shm_perm.mode); - err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq); - err2 |= __put_user (s.shm_atime, &up->shm_atime); - err2 |= __put_user (s.shm_dtime, &up->shm_dtime); - err2 |= __put_user (s.shm_ctime, &up->shm_ctime); - err2 |= __put_user (s.shm_segsz, &up->shm_segsz); - err2 |= __put_user (s.shm_nattch, &up->shm_nattch); - err2 |= __put_user (s.shm_cpid, &up->shm_cpid); - err2 |= __put_user (s.shm_lpid, &up->shm_lpid); - if (err2) - err = -EFAULT; - } + if (request == PTRACE_ATTACH) { + ret = sys_ptrace(request, pid, addr, data, + arg4, arg5, arg6, arg7, stack); + goto out; } -out: - return err; -} + ret = -ESRCH; + if (!(child->flags & PF_PTRACED)) + goto out; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out; + } + if (child->p_pptr != current) + goto out; -asmlinkage int -sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) -{ - int version, err; + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: /* read word at location addr */ + ret = ia32_peek(regs, child, addr, &value); + if (ret == 0) + ret = put_user(value, (unsigned int *)data); + else + ret = -EIO; + goto out; - lock_kernel(); - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: /* write the word at location addr */ + ret = ia32_poke(regs, child, addr, (unsigned int)data); + goto out; - if (call <= SEMCTL) - switch (call) { - case SEMOP: - /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semop (first, (struct sembuf *)AA(ptr), - second); - goto out; - case SEMGET: - err = sys_semget (first, second, third); - goto out; - case SEMCTL: - err = do_sys32_semctl (first, second, third, - (void *)AA(ptr)); - goto out; - default: - err = -EINVAL; - goto out; - }; - if (call <= MSGCTL) - switch (call) { - case MSGSND: - err = do_sys32_msgsnd (first, second, third, - (void *)AA(ptr)); - goto out; - case MSGRCV: - err = do_sys32_msgrcv (first, second, fifth, third, - version, (void *)AA(ptr)); - goto out; - case MSGGET: - err = sys_msgget ((key_t) first, second); - goto out; - case MSGCTL: - err = do_sys32_msgctl (first, second, (void *)AA(ptr)); - goto out; - default: - err = -EINVAL; - goto out; + case PTRACE_PEEKUSR: /* read word at addr in USER area */ + ret = 0; + break; + + case PTRACE_POKEUSR: /* write word at addr in USER area */ + ret = 0; + break; + + case IA32_PTRACE_GETREGS: + if (!access_ok(VERIFY_WRITE, (int *)data, 17*sizeof(int))) { + ret = -EIO; + break; } - if (call <= SHMCTL) - switch (call) { - case SHMAT: - err = do_sys32_shmat (first, second, third, - version, (void *)AA(ptr)); - goto out; - case SHMDT: - err = sys_shmdt ((char *)AA(ptr)); - goto out; - case SHMGET: - err = sys_shmget (first, second, third); - goto out; - case SHMCTL: - err = do_sys32_shmctl (first, second, (void *)AA(ptr)); - goto out; - default: - err = -EINVAL; - goto out; + for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + __put_user(getreg(child, i),(unsigned int *) data); + data += sizeof(int); } + ret = 0; + break; - err = -EINVAL; + case IA32_PTRACE_SETREGS: + { + unsigned int tmp; + if (!access_ok(VERIFY_READ, (int *)data, 17*sizeof(int))) { + ret = -EIO; + break; + } + for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + __get_user(tmp, (unsigned int *) data); + putreg(child, i, tmp); + data += sizeof(int); + } + ret = 0; + break; + } -out: - unlock_kernel(); - return err; -} + case IA32_PTRACE_GETFPREGS: + ret = save_ia32_fpstate(child, (struct _fpstate_ia32 *)data); + break; -/* - * sys_time() can be implemented in user-level using - * sys_gettimeofday(). IA64 did this but i386 Linux did not - * so we have to implement this system call here. - */ -asmlinkage long sys32_time(int * tloc) -{ - int i; + case IA32_PTRACE_SETFPREGS: + ret = restore_ia32_fpstate(child, (struct _fpstate_ia32 *)data); + break; + + case PTRACE_SYSCALL: /* continue, stop after next syscall */ + case PTRACE_CONT: /* restart after signal. */ + case PTRACE_KILL: + case PTRACE_SINGLESTEP: /* execute chile for one instruction */ + case PTRACE_DETACH: /* detach a process */ + unlock_kernel(); + ret = sys_ptrace(request, pid, addr, data, + arg4, arg5, arg6, arg7, stack); + return(ret); + + default: + ret = -EIO; + break; - /* SMP: This is fairly trivial. We grab CURRENT_TIME and - stuff it to user space. No side effects */ - i = CURRENT_TIME; - if (tloc) { - if (put_user(i,tloc)) - i = -EFAULT; } - return i; + out: + unlock_kernel(); + return ret; } #ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */ @@ -2722,37 +3157,6 @@ return ret; } -struct tms32 { - __kernel_clock_t32 tms_utime; - __kernel_clock_t32 tms_stime; - __kernel_clock_t32 tms_cutime; - __kernel_clock_t32 tms_cstime; -}; - -extern asmlinkage long sys_times(struct tms * tbuf); - -asmlinkage long -sys32_times(struct tms32 *tbuf) -{ - struct tms t; - long ret; - mm_segment_t old_fs = get_fs (); - int err; - - set_fs (KERNEL_DS); - ret = sys_times(tbuf ? &t : NULL); - set_fs (old_fs); - if (tbuf) { - err = put_user (t.tms_utime, &tbuf->tms_utime); - err |= __put_user (t.tms_stime, &tbuf->tms_stime); - err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); - err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); - if (err) - ret = -EFAULT; - } - return ret; -} - extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); asmlinkage int @@ -2792,23 +3196,6 @@ return ret; } -extern asmlinkage int -sys_getrusage(int who, struct rusage *ru); - -asmlinkage int -sys32_getrusage(int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getrusage(who, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) return -EFAULT; - return ret; -} - /* XXX These as well... */ extern __inline__ struct socket * @@ -4358,4 +4745,3 @@ return ret; } #endif // NOTYET - diff -urN linux-2.3.51/arch/ia64/kdb/Makefile linux-2.3.51-lia/arch/ia64/kdb/Makefile --- linux-2.3.51/arch/ia64/kdb/Makefile Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kdb/Makefile Wed Dec 31 16:00:00 1969 @@ -1,21 +0,0 @@ -# -# Makefile for ia64-specific kdb files.. -# -# Copyright 1999, Silicon Graphics Inc. -# -# Written March 1999 by Scott Lurndal at Silicon Graphics, Inc. -# Code for IA64 written by Goutham Rao and -# Sreenivas Subramoney -# - -SUB_DIRS := -MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) - -.S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o - -L_TARGET = kdb.a -L_OBJS = kdbsupport.o kdb_io.o kdb_bt.o kdb_traps.o - -include $(TOPDIR)/Rules.make diff -urN linux-2.3.51/arch/ia64/kdb/kdb_bt.c linux-2.3.51-lia/arch/ia64/kdb/kdb_bt.c --- linux-2.3.51/arch/ia64/kdb/kdb_bt.c Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kdb/kdb_bt.c Wed Dec 31 16:00:00 1969 @@ -1,104 +0,0 @@ -/** - * Minimalist Kernel Debugger - * Machine dependent stack traceback code for IA-64. - * - * Copyright (C) 1999 Goutham Rao - * Copyright (C) 1999 Sreenivas Subramoney - * Intel Corporation, August 1999. - * Copyright (C) 1999 Hewlett-Packard Co - * Copyright (C) 1999 David Mosberger-Tang - * - * 99/12/03 D. Mosberger Reimplemented based on API. - * 99/12/06 D. Mosberger Added support for backtracing other processes. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Minimal stack back trace functionality. - */ -int -kdb_bt (int argc, const char **argv, const char **envp, struct pt_regs *regs) -{ - struct task_struct *task = current; - struct ia64_frame_info info; - char *name; - int diag; - - if (strcmp(argv[0], "btp") == 0) { - unsigned long pid; - - diag = kdbgetularg(argv[1], &pid); - if (diag) - return diag; - - task = find_task_by_pid(pid); - if (!task) { - kdb_printf("No process with pid == %d found\n", pid); - return 0; - } - regs = ia64_task_regs(task); - } else if (argc) { - kdb_printf("bt
is unsupported for IA-64\n"); - return 0; - } - - if (task == current) { - /* - * Upon entering kdb, the stack frame looks like this: - * - * +---------------------+ - * | struct pt_regs | - * +---------------------+ - * | | - * | kernel stack | - * | | - * +=====================+ <--- top of stack upon entering kdb - * | struct pt_regs | - * +---------------------+ - * | struct switch_stack | - * +---------------------+ - */ - if (user_mode(regs)) { - /* We are not implementing stack backtrace from user mode code */ - kdb_printf ("Not in Kernel\n"); - return 0; - } - ia64_unwind_init_from_current(&info, regs); - } else { - /* - * For a blocked task, the stack frame looks like this: - * - * +---------------------+ - * | struct pt_regs | - * +---------------------+ - * | | - * | kernel stack | - * | | - * +---------------------+ - * | struct switch_stack | - * +=====================+ <--- task->thread.ksp - */ - ia64_unwind_init_from_blocked_task(&info, task); - } - - kdb_printf("Ret Address Reg Stack base Name\n\n") ; - do { - unsigned long ip = ia64_unwind_get_ip(&info); - - name = kdbnearsym(ip); - if (!name) { - kdb_printf("Interrupt\n"); - return 0; - } - kdb_printf("0x%016lx: [0x%016lx] %s\n", ip, ia64_unwind_get_bsp(&info), name); - } while (ia64_unwind_to_previous_frame(&info) >= 0); - return 0; -} diff -urN linux-2.3.51/arch/ia64/kdb/kdb_io.c linux-2.3.51-lia/arch/ia64/kdb/kdb_io.c --- linux-2.3.51/arch/ia64/kdb/kdb_io.c Tue Feb 8 12:01:59 2000 +++ linux-2.3.51-lia/arch/ia64/kdb/kdb_io.c Wed Dec 31 16:00:00 1969 @@ -1,350 +0,0 @@ -/* - * Kernel Debugger Console I/O handler - * - * Copyright (C) 1999 Silicon Graphics, Inc. - * Copyright (C) Scott Lurndal (slurn@engr.sgi.com) - * Copyright (C) Scott Foehner (sfoehner@engr.sgi.com) - * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com) - * - * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc. - * - * Modifications from: - * Chuck Fleckenstein 1999/07/20 - * Move kdb_info struct declaration to this file - * for cases where serial support is not compiled into - * the kernel. - * - * Masahiro Adegawa 1999/07/20 - * Handle some peculiarities of japanese 86/106 - * keyboards. - * - * marc@mucom.co.il 1999/07/20 - * Catch buffer overflow for serial input. - * - * Scott Foehner - * Port to ia64 - */ - -#include -#include -#include -#include -#include - -#include - -#include "pc_keyb.h" - -int kdb_port = 0; - -/* - * This module contains code to read characters from the keyboard or a serial - * port. - * - * It is used by the kernel debugger, and is polled, not interrupt driven. - * - */ - -/* - * send: Send a byte to the keyboard controller. Used primarily to - * alter LED settings. - */ - -static void -kdb_kbdsend(unsigned char byte) -{ - while (inb(KBD_STATUS_REG) & KBD_STAT_IBF) - ; - outb(KBD_DATA_REG, byte); -} - -static void -kdb_kbdsetled(int leds) -{ - kdb_kbdsend(KBD_CMD_SET_LEDS); - kdb_kbdsend((unsigned char)leds); -} - -static void -console_read (char *buffer, size_t bufsize) -{ - struct console *in; - struct console *out; - char *cp, ch; - - for (in = console_drivers; in; in = in->next) { - if ((in->flags & CON_ENABLED) && (in->read || in->wait_key)) - break; - } - for (out = console_drivers; out; out = out->next) { - if ((out->flags & CON_ENABLED) && out->write) - break; - } - - if ((!in->read && !in->wait_key) || !out->write) { - panic("kdb_io: can't do console i/o!"); - } - - if (in->read) { - /* this is untested... */ - (*in->read)(in, buffer, bufsize); - return; - } - - bufsize -= 2; /* leave room for CR & NUL terminator */ - cp = buffer; - while (1) { - ch = (*in->wait_key)(in); - switch (ch) { - case '\b': - if (cp > buffer) { - --cp, ++bufsize; - (*out->write)(out, "\b \b", 3); - } - break; - - case '\025': - while (cp > buffer) { - --cp, ++bufsize; - (*out->write)(out, "\b \b", 3); - } - break; - - case '\r': - case '\n': - (*out->write)(out, "\r\n", 2); - *cp++ = '\n'; - *cp++ = '\0'; - return; - - default: - if (bufsize > 0) { - (*out->write)(out, &ch, 1); - --bufsize; - *cp++ = ch; - } - break; - } - } -} - -char * -kdb_getscancode(char *buffer, size_t bufsize) -{ - /* - * XXX Shouldn't kdb _always_ use console based I/O? That's what the console - * abstraction is for, after all... ---davidm - */ -#ifdef CONFIG_IA64_HP_SIM - extern spinlock_t console_lock; - unsigned long flags; - - spin_lock_irqsave(&console_lock, flags); - console_read(buffer, bufsize); - spin_unlock_irqrestore(&console_lock, flags); - return buffer; -#else /* !CONFIG_IA64_HP_SIM */ - char *cp = buffer; - int scancode, scanstatus; - static int shift_lock = 0; /* CAPS LOCK state (0-off, 1-on) */ - static int shift_key = 0; /* Shift next keypress */ - static int ctrl_key = 0; - static int leds = 2; /* Num lock */ - u_short keychar; - extern u_short plain_map[], shift_map[], ctrl_map[]; - - bufsize -= 2; /* Reserve space for newline and null byte */ - - /* - * If we came in via a serial console, we allow that to - * be the input window for kdb. - */ - if (kdb_port != 0) { - char ch; - int status; -#define serial_inp(info, offset) inb((info) + (offset)) -#define serial_out(info, offset, v) outb((v), (info) + (offset)) - - while(1) { - while ((status = serial_inp(kdb_port, UART_LSR)) - & UART_LSR_DR) { -readchar: - ch = serial_inp(kdb_port, UART_RX); - if (ch == 8) { /* BS */ - if (cp > buffer) { - --cp, bufsize++; - printk("%c %c", 0x08, 0x08); - } - continue; - } - serial_out(kdb_port, UART_TX, ch); - if (ch == 13) { /* CR */ - *cp++ = '\n'; - *cp++ = '\0'; - serial_out(kdb_port, UART_TX, 10); - return(buffer); - } - /* - * Discard excess characters - */ - if (bufsize > 0) { - *cp++ = ch; - bufsize--; - } - } - while (((status = serial_inp(kdb_port, UART_LSR)) - & UART_LSR_DR) == 0); - } - } - - while (1) { - - /* - * Wait for a valid scancode - */ - - while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) - ; - - /* - * Fetch the scancode - */ - scancode = inb(KBD_DATA_REG); - scanstatus = inb(KBD_STATUS_REG); - - /* - * Ignore mouse events. - */ - if (scanstatus & KBD_STAT_MOUSE_OBF) - continue; - - /* - * Ignore release, trigger on make - * (except for shift keys, where we want to - * keep the shift state so long as the key is - * held down). - */ - - if (((scancode&0x7f) == 0x2a) - || ((scancode&0x7f) == 0x36)) { - /* - * Next key may use shift table - */ - if ((scancode & 0x80) == 0) { - shift_key=1; - } else { - shift_key=0; - } - continue; - } - - if ((scancode&0x7f) == 0x1d) { - /* - * Left ctrl key - */ - if ((scancode & 0x80) == 0) { - ctrl_key = 1; - } else { - ctrl_key = 0; - } - continue; - } - - if ((scancode & 0x80) != 0) - continue; - - scancode &= 0x7f; - - /* - * Translate scancode - */ - - if (scancode == 0x3a) { - /* - * Toggle caps lock - */ - shift_lock ^= 1; - leds ^= 0x4; /* toggle caps lock led */ - - kdb_kbdsetled(leds); - continue; - } - - if (scancode == 0x0e) { - /* - * Backspace - */ - if (cp > buffer) { - --cp, bufsize++; - - /* - * XXX - erase character on screen - */ - printk("%c %c", 0x08, 0x08); - } - continue; - } - - if (scancode == 0xe0) { - continue; - } - - /* - * For Japanese 86/106 keyboards - * See comment in drivers/char/pc_keyb.c. - * - Masahiro Adegawa - */ - if (scancode == 0x73) { - scancode = 0x59; - } else if (scancode == 0x7d) { - scancode = 0x7c; - } - - if (!shift_lock && !shift_key) { - keychar = plain_map[scancode]; - } else if (shift_lock || shift_key) { - keychar = shift_map[scancode]; - } else if (ctrl_key) { - keychar = ctrl_map[scancode]; - } else { - keychar = 0x0020; - printk("Unknown state/scancode (%d)\n", scancode); - } - - if ((scancode & 0x7f) == 0x1c) { - /* - * enter key. All done. - */ - printk("\n"); - break; - } - - /* - * echo the character. - */ - printk("%c", keychar&0xff); - - if (bufsize) { - --bufsize; - *cp++ = keychar&0xff; - } else { - printk("buffer overflow\n"); - break; - } - - } - - *cp++ = '\n'; /* White space for parser */ - *cp++ = '\0'; /* String termination */ - -#if defined(NOTNOW) - cp = buffer; - while (*cp) { - printk("char 0x%x\n", *cp++); - } -#endif - - return buffer; -#endif /* !CONFIG_IA64_HP_SIM */ -} - diff -urN linux-2.3.51/arch/ia64/kdb/kdb_traps.c linux-2.3.51-lia/arch/ia64/kdb/kdb_traps.c --- linux-2.3.51/arch/ia64/kdb/kdb_traps.c Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kdb/kdb_traps.c Wed Dec 31 16:00:00 1969 @@ -1,55 +0,0 @@ -#include -#include -#include -#include - -static struct kdb_bp_support { - unsigned long addr ; - int slot ; -} kdb_bp_info[NR_CPUS] ; - - -extern void kdb_bp_install (void); - -/* - * This gets invoked right before a call to ia64_fault(). - * Returns zero the normal fault handler should be invoked. - */ -long -ia64_kdb_fault_handler (unsigned long vector, unsigned long isr, unsigned long ifa, - unsigned long iim, unsigned long itir, unsigned long arg5, - unsigned long arg6, unsigned long arg7, unsigned long stack) -{ - struct switch_stack *sw = (struct switch_stack *) &stack; - struct pt_regs *regs = (struct pt_regs *) (sw + 1); - int bundle_slot; - - /* - * TBD - * If KDB is configured, enter KDB for any fault. - */ - if ((vector == 29) || (vector == 35) || (vector == 36)) { - if (!user_mode(regs)) { - bundle_slot = ia64_psr(regs)->ri; - if (vector == 29) { - if (bundle_slot == 0) { - kdb_bp_info[0].addr = regs->cr_iip; - kdb_bp_info[0].slot = bundle_slot; - kdb(KDB_REASON_FLTDBG, 0, regs); - } else { - if ((bundle_slot < 3) && - (kdb_bp_info[0].addr == regs->cr_iip)) - { - ia64_psr(regs)->id = 1; - ia64_psr(regs)->db = 1; - kdb_bp_install() ; - } else /* some error ?? */ - kdb(KDB_REASON_FLTDBG, 0, regs); - } - } else /* single step or taken branch */ - kdb(KDB_REASON_DEBUG, 0, regs); - return 1; - } - } - return 0; -} diff -urN linux-2.3.51/arch/ia64/kdb/kdbsupport.c linux-2.3.51-lia/arch/ia64/kdb/kdbsupport.c --- linux-2.3.51/arch/ia64/kdb/kdbsupport.c Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/arch/ia64/kdb/kdbsupport.c Wed Dec 31 16:00:00 1969 @@ -1,1329 +0,0 @@ -/* - * Minimalist Kernel Debugger - * - * Copyright (C) 1999 Silicon Graphics, Inc. - * Copyright (C) Scott Lurndal (slurn@engr.sgi.com) - * Copyright (C) Scott Foehner (sfoehner@engr.sgi.com) - * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com) - * Copyright (C) David Mosberger-Tang - * - * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc. - * - * Modifications from: - * Richard Bass 1999/07/20 - * Many bug fixes and enhancements. - * Scott Foehner - * Port to ia64 - * Srinivasa Thirumalachar - * RSE support for ia64 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -extern kdb_state_t kdb_state ; -k_machreg_t dbregs[KDB_DBREGS]; - -static int __init -kdb_setup (char *str) -{ - kdb_flags |= KDB_FLAG_EARLYKDB; - return 1; -} - -__setup("kdb", kdb_setup); - -static int -kdb_ia64_itm (int argc, const char **argv, const char **envp, struct pt_regs *regs) -{ - int diag; - unsigned long val; - - diag = kdbgetularg(argv[1], &val); - if (diag) - return diag; - kdb_printf("new itm=%0xlx\n", val); - - ia64_set_itm(val); - return 0; -} - -static int -kdb_ia64_sir (int argc, const char **argv, const char **envp, struct pt_regs *regs) -{ - u64 lid, tpr, lrr0, lrr1, itv, pmv, cmcv; - - asm ("mov %0=cr.lid" : "=r"(lid)); - asm ("mov %0=cr.tpr" : "=r"(tpr)); - asm ("mov %0=cr.lrr0" : "=r"(lrr0)); - asm ("mov %0=cr.lrr1" : "=r"(lrr1)); - printk("lid=0x%lx, tpr=0x%lx, lrr0=0x%lx, llr1=0x%lx\n", lid, tpr, lrr0, lrr1); - - asm ("mov %0=cr.itv" : "=r"(itv)); - asm ("mov %0=cr.pmv" : "=r"(pmv)); - asm ("mov %0=cr.cmcv" : "=r"(cmcv)); - printk("itv=0x%lx, pmv=0x%lx, cmcv=0x%lx\n", itv, pmv, cmcv); - - printk("irr=0x%016lx,0x%016lx,0x%016lx,0x%016lx\n", - ia64_get_irr0(), ia64_get_irr1(), ia64_get_irr2(), ia64_get_irr3()); - - printk("itc=0x%016lx, itm=0x%016lx\n", ia64_get_itc(), ia64_get_itm()); - return 0; -} - -void __init -kdb_init (void) -{ - extern void kdb_inittab(void); - unsigned long reg; - - kdb_inittab(); - kdb_initbptab(); -#if 0 - kdb_disinit(); -#endif - kdb_printf("kdb version %d.%d by Scott Lurndal. "\ - "Copyright SGI, All Rights Reserved\n", - KDB_MAJOR_VERSION, KDB_MINOR_VERSION); - - /* Enable debug registers */ - __asm__ ("mov %0=psr":"=r"(reg)); - reg |= IA64_PSR_DB; - __asm__ ("mov psr.l=%0"::"r"(reg)); - ia64_srlz_d(); - - /* Init kdb state */ - kdb_state.bkpt_handling_state = BKPTSTATE_NOT_HANDLED ; - - kdb_register("irr", kdb_ia64_sir, "", "Show interrupt registers", 0); - kdb_register("itm", kdb_ia64_itm, "", "Set new ITM value", 0); -} - -/* - * kdbprintf - * kdbgetword - * kdb_getstr - */ - -char * -kbd_getstr(char *buffer, size_t bufsize, char *prompt) -{ - extern char* kdb_getscancode(char *, size_t); - -#if defined(CONFIG_SMP) - kdb_printf(prompt, smp_processor_id()); -#else - kdb_printf("%s", prompt); -#endif - - return kdb_getscancode(buffer, bufsize); - -} - -int -kdb_printf(const char *fmt, ...) -{ - char buffer[256]; - va_list ap; - int diag; - int linecount; - - diag = kdbgetintenv("LINES", &linecount); - if (diag) - linecount = 22; - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - - printk("%s", buffer); -#if 0 - if (strchr(buffer, '\n') != NULL) { - kdb_nextline++; - } - - if (kdb_nextline == linecount) { - char buf1[16]; - char buf2[32]; - extern char* kdb_getscancode(char *, size_t); - char *moreprompt; - - /* - * Pause until cr. - */ - moreprompt = kdbgetenv("MOREPROMPT"); - if (moreprompt == NULL) { - moreprompt = "more> "; - } - -#if defined(CONFIG_SMP) - if (strchr(moreprompt, '%')) { - sprintf(buf2, moreprompt, smp_processor_id()); - moreprompt = buf2; - } -#endif - - printk(moreprompt); - (void) kdb_getscancode(buf1, sizeof(buf1)); - - kdb_nextline = 1; - - if ((buf1[0] == 'q') - || (buf1[0] == 'Q')) { - kdb_longjmp(&kdbjmpbuf, 1); - } - } -#endif - return 0; -} - -unsigned long -kdbgetword(unsigned long addr, int width) -{ - /* - * This function checks the address for validity. Any address - * in the range PAGE_OFFSET to high_memory is legal, any address - * which maps to a vmalloc region is legal, and any address which - * is a user address, we use get_user() to verify validity. - */ - - if (addr < PAGE_OFFSET) { - /* - * Usermode address. - */ - unsigned long diag; - unsigned long ulval; - - switch (width) { - case 8: - { unsigned long *lp; - - lp = (unsigned long *) addr; - diag = get_user(ulval, lp); - break; - } - case 4: - { unsigned int *ip; - - ip = (unsigned int *) addr; - diag = get_user(ulval, ip); - break; - } - case 2: - { unsigned short *sp; - - sp = (unsigned short *) addr; - diag = get_user(ulval, sp); - break; - } - case 1: - { unsigned char *cp; - - cp = (unsigned char *) addr; - diag = get_user(ulval, cp); - break; - } - default: - printk("kdbgetword: Bad width\n"); - return 0L; - } - - if (diag) { - if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) { - printk("kdb: Bad user address 0x%lx\n", addr); - kdb_flags |= KDB_FLAG_SUPRESS; - } - return 0L; - } - kdb_flags &= ~KDB_FLAG_SUPRESS; - return ulval; - } - - if (addr > (unsigned long)high_memory) { - extern int kdb_vmlist_check(unsigned long, unsigned long); - - if (!kdb_vmlist_check(addr, addr+width)) { - /* - * Would appear to be an illegal kernel address; - * Print a message once, and don't print again until - * a legal address is used. - */ - if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) { - printk("kdb: Bad kernel address 0x%lx\n", addr); - kdb_flags |= KDB_FLAG_SUPRESS; - } - return 0L; - } - } - - /* - * A good address. Reset error flag. - */ - kdb_flags &= ~KDB_FLAG_SUPRESS; - - switch (width) { - case 8: - { unsigned long *lp; - - lp = (unsigned long *)(addr); - return *lp; - } - case 4: - { unsigned int *ip; - - ip = (unsigned int *)(addr); - return *ip; - } - case 2: - { unsigned short *sp; - - sp = (unsigned short *)(addr); - return *sp; - } - case 1: - { unsigned char *cp; - - cp = (unsigned char *)(addr); - return *cp; - } - } - - printk("kdbgetword: Bad width\n"); - return 0L; -} - -/* - * Start of breakpoint management routines - */ - -/* - * Arg: bp structure - */ - -int -kdb_allocdbreg(kdb_bp_t *bp) -{ - int i=0; - - /* For inst bkpt, just return. No hw reg alloc to be done. */ - - if (bp->bp_mode == BKPTMODE_INST) { - return i; - } else if (bp->bp_mode == BKPTMODE_DATAW) { - for(i=0; ibp_mode == BKPTMODE_DATAW) - dbregs[bp->bp_reg] = 0xffffffff; -} - -void -kdb_initdbregs(void) -{ - int i; - - for(i=0; ibp_addr ; - bundle_t *bundle = (bundle_t *)bp->bp_longinst; - - /* save current bundle */ - *bundle = *(bundle_t *)addr ; - - /* Set the break point! */ - ((bundle_t *)addr)->lform.low8 = ( - (((bundle_t *)addr)->lform.low8 & ~INST_SLOT0_MASK) | - BREAK_INSTR); - - /* set flag */ - bp->bp_instvalid = 1 ; - - /* flush icache as it is stale now */ - ia64_flush_icache_page((unsigned long)addr) ; - -#ifdef KDB_DEBUG - kdb_printf ("[0x%016lx]: install 0x%016lx with 0x%016lx\n", - addr, bundle->lform.low8, addr[0]) ; -#endif - return 0 ; -} - -int -install_databkpt(kdb_bp_t *bp) -{ - unsigned long dbreg_addr = bp->bp_reg * 2; - unsigned long dbreg_cond = dbreg_addr + 1; - unsigned long value = 0x8fffffffffffffff; - unsigned long addr = (unsigned long)bp->bp_addr; - __asm__ ("mov dbr[%0]=%1"::"r"(dbreg_cond),"r"(value)); -// __asm__ ("movl %0,%%db0\n\t"::"r"(contents)); - __asm__ ("mov dbr[%0]=%1"::"r"(dbreg_addr),"r"(addr)); - ia64_insn_group_barrier(); - ia64_srlz_i(); - ia64_insn_group_barrier(); - -#ifdef KDB_DEBUG - kdb_printf("installed dbkpt at 0x%016lx\n", addr) ; -#endif - return 0; -} - -int -kdbinstalldbreg(kdb_bp_t *bp) -{ - if (bp->bp_mode == BKPTMODE_INST) { - return install_instbkpt(bp) ; - } else if (bp->bp_mode == BKPTMODE_DATAW) { - return install_databkpt(bp) ; - } - return 0; -} - -void -remove_instbkpt(kdb_bp_t *bp) -{ - unsigned long *addr = (unsigned long *)bp->bp_addr ; - bundle_t *bundle = (bundle_t *)bp->bp_longinst; - - if (!bp->bp_instvalid) - /* Nothing to remove. If we just alloced the bkpt - * but never resumed, the bp_inst will not be valid. */ - return ; - -#ifdef KDB_DEBUG - kdb_printf ("[0x%016lx]: remove 0x%016lx with 0x%016lx\n", - addr, addr[0], bundle->lform.low8) ; -#endif - - /* restore current bundle */ - *(bundle_t *)addr = *bundle ; - /* reset the flag */ - bp->bp_instvalid = 0 ; - ia64_flush_icache_page((unsigned long)addr) ; -} - -void -remove_databkpt(kdb_bp_t *bp) -{ - int regnum = bp->bp_reg ; - unsigned long dbreg_addr = regnum * 2; - unsigned long dbreg_cond = dbreg_addr + 1; - unsigned long value = 0x0fffffffffffffff; - __asm__ ("mov dbr[%0]=%1"::"r"(dbreg_cond),"r"(value)); -// __asm__ ("movl %0,%%db0\n\t"::"r"(contents)); - ia64_insn_group_barrier(); - ia64_srlz_i(); - ia64_insn_group_barrier(); - -#ifdef KDB_DEBUG - kdb_printf("removed dbkpt at 0x%016lx\n", bp->bp_addr) ; -#endif -} - -void -kdbremovedbreg(kdb_bp_t *bp) -{ - if (bp->bp_mode == BKPTMODE_INST) { - remove_instbkpt(bp) ; - } else if (bp->bp_mode == BKPTMODE_DATAW) { - remove_databkpt(bp) ; - } -} - -k_machreg_t -kdb_getdr6(void) -{ - return kdb_getdr(6); -} - -k_machreg_t -kdb_getdr7(void) -{ - return kdb_getdr(7); -} - -k_machreg_t -kdb_getdr(int regnum) -{ - k_machreg_t contents = 0; - unsigned long reg = (unsigned long)regnum; - - __asm__ ("mov %0=ibr[%1]"::"r"(contents),"r"(reg)); -// __asm__ ("mov ibr[%0]=%1"::"r"(dbreg_cond),"r"(value)); - - return contents; -} - - -k_machreg_t -kdb_getcr(int regnum) -{ - k_machreg_t contents = 0; - return contents; -} - -void -kdb_putdr6(k_machreg_t contents) -{ - kdb_putdr(6, contents); -} - -void -kdb_putdr7(k_machreg_t contents) -{ - kdb_putdr(7, contents); -} - -void -kdb_putdr(int regnum, k_machreg_t contents) -{ -} - -void -get_fault_regs(fault_regs_t *fr) -{ - fr->ifa = 0 ; - fr->isr = 0 ; - - __asm__ ("rsm psr.ic;;") ; - ia64_srlz_d(); - __asm__ ("mov %0=cr.ifa" : "=r"(fr->ifa)); - __asm__ ("mov %0=cr.isr" : "=r"(fr->isr)); - __asm__ ("ssm psr.ic;;") ; - ia64_srlz_d(); -} - -/* - * kdb_db_trap - * - * Perform breakpoint processing upon entry to the - * processor debugger fault. Determine and print - * the active breakpoint. - * - * Parameters: - * ef Exception frame containing machine register state - * reason Why did we enter kdb - fault or break - * Outputs: - * None. - * Returns: - * 0 Standard instruction or data breakpoint encountered - * 1 Single Step fault ('ss' command) - * 2 Single Step fault, caller should continue ('ssb' command) - * Locking: - * None. - * Remarks: - * Yup, there be goto's here. - */ - -int -kdb_db_trap(struct pt_regs *ef, int reason) -{ - int i, rv=0; - - /* Trying very hard to not change the interface to kdb. - * So, eventhough we have these values in the fault function - * it is not passed in but read again. - */ - fault_regs_t faultregs ; - - if (reason == KDB_REASON_FLTDBG) - get_fault_regs(&faultregs) ; - - /* NOTE : XXX: This has to be done only for data bkpts */ - /* Prevent it from continuously faulting */ - ef->cr_ipsr |= 0x0000002000000000; - - if (ef->cr_ipsr & 0x0000010000000000) { - /* single step */ - ef->cr_ipsr &= 0xfffffeffffffffff; - if ((kdb_state.bkpt_handling_state == BKPTSTATE_HANDLED) - && (kdb_state.cmd_given == CMDGIVEN_GO)) - ; - else - kdb_printf("SS trap at 0x%lx\n", ef->cr_iip + ia64_psr(ef)->ri); - rv = 1; - kdb_state.reason_for_entry = ENTRYREASON_SSTEP ; - goto handled; - } else - kdb_state.reason_for_entry = ENTRYREASON_GO ; - - /* - * Determine which breakpoint was encountered. - */ - for(i=0; icr_iip) || - ((faultregs.ifa) && - (breakpoints[i].bp_addr == faultregs.ifa)))) { - /* - * Hit this breakpoint. Remove it while we are - * handling hit to avoid recursion. XXX ?? - */ - if (breakpoints[i].bp_addr == faultregs.ifa) - kdb_printf("Data breakpoint #%d for 0x%lx at 0x%lx\n", - i, breakpoints[i].bp_addr, ef->cr_iip + ia64_psr(ef)->ri); - else - kdb_printf("%s breakpoint #%d at 0x%lx\n", - rwtypes[0], - i, breakpoints[i].bp_addr); - - /* - * For an instruction breakpoint, disassemble - * the current instruction. - */ -#if 0 - if (rw == 0) { - kdb_id1(ef->eip); - } -#endif - - goto handled; - } - } - -#if 0 -unknown: -#endif - kdb_printf("Unknown breakpoint. Should forward. \n"); - /* Need a flag for this. The skip should be done XXX - * when a go or single step command is done for this session. - * For now it is here. - */ - ia64_increment_ip(ef) ; - return rv ; - -handled: - - /* We are here after handling a break inst/data bkpt */ - if (kdb_state.bkpt_handling_state == BKPTSTATE_NOT_HANDLED) { - kdb_state.bkpt_handling_state = BKPTSTATE_HANDLED ; - if (kdb_state.reason_for_entry == ENTRYREASON_GO) { - kdb_setsinglestep(ef) ; - kdb_state.kdb_action = ACTION_NOBPINSTALL; - /* We dont want bp install just this once */ - kdb_state.cmd_given = CMDGIVEN_UNKNOWN ; - } - } else if (kdb_state.bkpt_handling_state == BKPTSTATE_HANDLED) { - kdb_state.bkpt_handling_state = BKPTSTATE_NOT_HANDLED ; - if (kdb_state.reason_for_entry == ENTRYREASON_SSTEP) { - if (kdb_state.cmd_given == CMDGIVEN_GO) - kdb_state.kdb_action = ACTION_NOPROMPT ; - kdb_state.cmd_given = CMDGIVEN_UNKNOWN ; - } - } else - kdb_printf("Unknown value of bkpt state\n") ; - - return rv; - -} - -void -kdb_setsinglestep(struct pt_regs *regs) -{ - regs->cr_ipsr |= 0x0000010000000000; -#if 0 - regs->eflags |= EF_TF; -#endif -} - -/* - * Symbol table functions. - */ - -/* - * kdbgetsym - * - * Return the symbol table entry for the given symbol - * - * Parameters: - * symname Character string containing symbol name - * Outputs: - * Returns: - * NULL Symbol doesn't exist - * ksp Pointer to symbol table entry - * Locking: - * None. - * Remarks: - */ - -__ksymtab_t * -kdbgetsym(const char *symname) -{ - __ksymtab_t *ksp = __kdbsymtab; - int i; - - if (symname == NULL) - return NULL; - - for (i=0; i<__kdbsymtabsize; i++, ksp++) { - if (ksp->name && (strcmp(ksp->name, symname)==0)) { - return ksp; - } - } - - return NULL; -} - -/* - * kdbgetsymval - * - * Return the address of the given symbol. - * - * Parameters: - * symname Character string containing symbol name - * Outputs: - * Returns: - * 0 Symbol name is NULL - * addr Address corresponding to symname - * Locking: - * None. - * Remarks: - */ - -unsigned long -kdbgetsymval(const char *symname) -{ - __ksymtab_t *ksp = kdbgetsym(symname); - - return (ksp?ksp->value:0); -} - -/* - * kdbaddmodsym - * - * Add a symbol to the kernel debugger symbol table. Called when - * a new module is loaded into the kernel. - * - * Parameters: - * symname Character string containing symbol name - * value Value of symbol - * Outputs: - * Returns: - * 0 Successfully added to table. - * 1 Duplicate symbol - * 2 Symbol table full - * Locking: - * None. - * Remarks: - */ - -int -kdbaddmodsym(char *symname, unsigned long value) -{ - - /* - * Check for duplicate symbols. - */ - if (kdbgetsym(symname)) { - printk("kdb: Attempt to register duplicate symbol '%s' @ 0x%lx\n", - symname, value); - return 1; - } - - if (__kdbsymtabsize < __kdbmaxsymtabsize) { - __ksymtab_t *ksp = &__kdbsymtab[__kdbsymtabsize++]; - - ksp->name = symname; - ksp->value = value; - return 0; - } - - /* - * No room left in kernel symbol table. - */ - { - static int __kdbwarn = 0; - - if (__kdbwarn == 0) { - __kdbwarn++; - printk("kdb: Exceeded symbol table size. Increase CONFIG_KDB_SYMTAB_SIZE in kernel configuration\n"); - } - } - - return 2; -} - -/* - * kdbdelmodsym - * - * Add a symbol to the kernel debugger symbol table. Called when - * a new module is loaded into the kernel. - * - * Parameters: - * symname Character string containing symbol name - * value Value of symbol - * Outputs: - * Returns: - * 0 Successfully added to table. - * 1 Symbol not found - * Locking: - * None. - * Remarks: - */ - -int -kdbdelmodsym(const char *symname) -{ - __ksymtab_t *ksp, *endksp; - - if (symname == NULL) - return 1; - - /* - * Search for the symbol. If found, move - * all successive symbols down one position - * in the symbol table to avoid leaving holes. - */ - endksp = &__kdbsymtab[__kdbsymtabsize]; - for (ksp = __kdbsymtab; ksp < endksp; ksp++) { - if (ksp->name && (strcmp(ksp->name, symname) == 0)) { - endksp--; - for ( ; ksp < endksp; ksp++) { - *ksp = *(ksp + 1); - } - __kdbsymtabsize--; - return 0; - } - } - - return 1; -} - -/* - * kdbnearsym - * - * Return the name of the symbol with the nearest address - * less than 'addr'. - * - * Parameters: - * addr Address to check for symbol near - * Outputs: - * Returns: - * NULL No symbol with address less than 'addr' - * symbol Returns the actual name of the symbol. - * Locking: - * None. - * Remarks: - */ - -char * -kdbnearsym(unsigned long addr) -{ - __ksymtab_t *ksp = __kdbsymtab; - __ksymtab_t *kpp = NULL; - int i; - - for(i=0; i<__kdbsymtabsize; i++, ksp++) { - if (!ksp->name) - continue; - - if (addr == ksp->value) { - kpp = ksp; - break; - } - if (addr > ksp->value) { - if ((kpp == NULL) - || (ksp->value > kpp->value)) { - kpp = ksp; - } - } - } - - /* - * If more than 128k away, don't bother. - */ - if ((kpp == NULL) - || ((addr - kpp->value) > 0x20000)) { - return NULL; - } - - return kpp->name; -} - -/* - * kdbgetregcontents - * - * Return the contents of the register specified by the - * input string argument. Return an error if the string - * does not match a machine register. - * - * The following pseudo register names are supported: - * ®s - Prints address of exception frame - * kesp - Prints kernel stack pointer at time of fault - * sstk - Prints switch stack for ia64 - * % - Uses the value of the registers at the - * last time the user process entered kernel - * mode, instead of the registers at the time - * kdb was entered. - * - * Parameters: - * regname Pointer to string naming register - * regs Pointer to structure containing registers. - * Outputs: - * *contents Pointer to unsigned long to recieve register contents - * Returns: - * 0 Success - * KDB_BADREG Invalid register name - * Locking: - * None. - * Remarks: - * - * Note that this function is really machine independent. The kdb - * register list is not, however. - */ - -static struct kdbregs { - char *reg_name; - size_t reg_offset; -} kdbreglist[] = { - { " psr", offsetof(struct pt_regs, cr_ipsr) }, - { " ifs", offsetof(struct pt_regs, cr_ifs) }, - { " ip", offsetof(struct pt_regs, cr_iip) }, - - { "unat", offsetof(struct pt_regs, ar_unat) }, - { " pfs", offsetof(struct pt_regs, ar_pfs) }, - { " rsc", offsetof(struct pt_regs, ar_rsc) }, - - { "rnat", offsetof(struct pt_regs, ar_rnat) }, - { "bsps", offsetof(struct pt_regs, ar_bspstore) }, - { " pr", offsetof(struct pt_regs, pr) }, - - { "ldrs", offsetof(struct pt_regs, loadrs) }, - { " ccv", offsetof(struct pt_regs, ar_ccv) }, - { "fpsr", offsetof(struct pt_regs, ar_fpsr) }, - - { " b0", offsetof(struct pt_regs, b0) }, - { " b6", offsetof(struct pt_regs, b6) }, - { " b7", offsetof(struct pt_regs, b7) }, - - { " r1",offsetof(struct pt_regs, r1) }, - { " r2",offsetof(struct pt_regs, r2) }, - { " r3",offsetof(struct pt_regs, r3) }, - - { " r8",offsetof(struct pt_regs, r8) }, - { " r9",offsetof(struct pt_regs, r9) }, - { " r10",offsetof(struct pt_regs, r10) }, - - { " r11",offsetof(struct pt_regs, r11) }, - { " r12",offsetof(struct pt_regs, r12) }, - { " r13",offsetof(struct pt_regs, r13) }, - - { " r14",offsetof(struct pt_regs, r14) }, - { " r15",offsetof(struct pt_regs, r15) }, - { " r16",offsetof(struct pt_regs, r16) }, - - { " r17",offsetof(struct pt_regs, r17) }, - { " r18",offsetof(struct pt_regs, r18) }, - { " r19",offsetof(struct pt_regs, r19) }, - - { " r20",offsetof(struct pt_regs, r20) }, - { " r21",offsetof(struct pt_regs, r21) }, - { " r22",offsetof(struct pt_regs, r22) }, - - { " r23",offsetof(struct pt_regs, r23) }, - { " r24",offsetof(struct pt_regs, r24) }, - { " r25",offsetof(struct pt_regs, r25) }, - - { " r26",offsetof(struct pt_regs, r26) }, - { " r27",offsetof(struct pt_regs, r27) }, - { " r28",offsetof(struct pt_regs, r28) }, - - { " r29",offsetof(struct pt_regs, r29) }, - { " r30",offsetof(struct pt_regs, r30) }, - { " r31",offsetof(struct pt_regs, r31) }, - -}; - -static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs); - -int -kdbgetregcontents(const char *regname, - struct pt_regs *regs, - unsigned long *contents) -{ - int i; - - if (strcmp(regname, "®s") == 0) { - *contents = (unsigned long)regs; - return 0; - } - - if (strcmp(regname, "sstk") == 0) { - *contents = (unsigned long)getprsregs(regs) ; - return 0; - } - - if (strcmp(regname, "isr") == 0) { - fault_regs_t fr ; - get_fault_regs(&fr) ; - *contents = fr.isr ; - return 0 ; - } - -#if 0 - /* XXX need to verify this */ - if (strcmp(regname, "kesp") == 0) { - *contents = (unsigned long)regs + sizeof(struct pt_regs); - return 0; - } - - if (regname[0] == '%') { - /* User registers: %%e[a-c]x, etc */ - regname++; - regs = (struct pt_regs *) - (current->thread.ksp - sizeof(struct pt_regs)); - } -#endif - - for (i=0; i - * - * Parameters: - * regname Pointer to string naming register - * regs Pointer to structure containing registers. - * contents Unsigned long containing new register contents - * Outputs: - * Returns: - * 0 Success - * KDB_BADREG Invalid register name - * Locking: - * None. - * Remarks: - */ - -int -kdbsetregcontents(const char *regname, - struct pt_regs *regs, - unsigned long contents) -{ - int i; - - if (regname[0] == '%') { - regname++; - regs = (struct pt_regs *) - (current->thread.ksp - sizeof(struct pt_regs)); - } - - for (i=0; ithread.ksp - sizeof(struct pt_regs)); - } - - if (type == NULL) { - for (i=0; icr_iip + ia64_psr(regs)->ri; -} - -int -kdb_setpc(struct pt_regs *regs, k_machreg_t newpc) -{ - regs->cr_iip = newpc & ~0xf; - ia64_psr(regs)->ri = newpc & 0x3; - return 0; -} - -void -kdb_disableint(kdbintstate_t *state) -{ - int *fp = (int *)state; - int flags; - - __save_flags(flags); - __cli(); - - *fp = flags; -} - -void -kdb_restoreint(kdbintstate_t *state) -{ - int flags = *(int *)state; - __restore_flags(flags); -} - -int -kdb_putword(unsigned long addr, unsigned long contents) -{ - *(unsigned long *)addr = contents; - return 0; -} - -int -kdb_getcurrentframe(struct pt_regs *regs) -{ -#if 0 - regs->xcs = 0; -#if defined(CONFIG_KDB_FRAMEPTR) - asm volatile("movl %%ebp,%0":"=m" (*(int *)®s->ebp)); -#endif - asm volatile("movl %%esp,%0":"=m" (*(int *)®s->esp)); -#endif - return 0; -} - -unsigned long -show_cur_stack_frame(struct pt_regs *regs, int regno, unsigned long *contents) -{ - long sof = regs->cr_ifs & ((1<<7)-1) ; /* size of frame */ - unsigned long i ; - int j; - struct switch_stack *prs_regs = getprsregs(regs) ; - unsigned long *sofptr = (prs_regs? ia64_rse_skip_regs( - (unsigned long *)prs_regs->ar_bspstore, -sof) : NULL) ; - - if (!sofptr) { - printk("Unable to display Current Stack Frame\n") ; - return 0 ; - } - - if (regno < 0) - return 0 ; - - for (i=sof, j=0;i;i--,j++) { - /* remember to skip the nat collection dword */ - if ((((unsigned long)sofptr>>3) & (((1<<6)-1))) - == ((1<<6)-1)) - sofptr++ ; - - /* return the value in the reg if regno is non zero */ - - if (regno) { - if ((j+1) == regno) { - if (contents) - *contents = *sofptr ; - return -1; - } - sofptr++ ; - } else { - printk(" r%d: %016lx ", 32+j, *sofptr++) ; - if (!((j+1)%3)) printk("\n") ; - } - } - - if (regno) { - if (!i) /* bogus rse number */ - return 0 ; - } else - printk("\n") ; - - return 0 ; -} diff -urN linux-2.3.51/arch/ia64/kdb/pc_keyb.h linux-2.3.51-lia/arch/ia64/kdb/pc_keyb.h --- linux-2.3.51/arch/ia64/kdb/pc_keyb.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kdb/pc_keyb.h Wed Dec 31 16:00:00 1969 @@ -1,127 +0,0 @@ -/* - * linux/drivers/char/pc_keyb.h - * - * PC Keyboard And Keyboard Controller - * - * (c) 1997 Martin Mares - */ - -/* - * Configuration Switches - */ - -#undef KBD_REPORT_ERR /* Report keyboard errors */ -#define KBD_REPORT_UNKN /* Report unknown scan codes */ -#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */ -#undef KBD_IS_FOCUS_9000 /* We have the brain-damaged FOCUS-9000 keyboard */ -#undef INITIALIZE_MOUSE /* Define if your PS/2 mouse needs initialization. */ - - - -#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the keyboard */ -#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ -#define KBD_TIMEOUT 1000 /* Timeout in ms for keyboard command acknowledge */ - -/* - * Internal variables of the driver - */ - -extern unsigned char pckbd_read_mask; -extern unsigned char aux_device_present; - -/* - * Keyboard Controller Registers - */ - -#define KBD_STATUS_REG 0x64 /* Status register (R) */ -#define KBD_CNTL_REG 0x64 /* Controller command register (W) */ -#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */ - -/* - * Keyboard Controller Commands - */ - -#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ -#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ -#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ -#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ -#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ -#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ -#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ -#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ -#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ -#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ -#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if - initiated by the auxiliary device */ -#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ - -/* - * Keyboard Commands - */ - -#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ -#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ -#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ -#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */ -#define KBD_CMD_RESET 0xFF /* Reset */ - -/* - * Keyboard Replies - */ - -#define KBD_REPLY_POR 0xAA /* Power on reset */ -#define KBD_REPLY_ACK 0xFA /* Command ACK */ -#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ - -/* - * Status Register Bits - */ - -#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ -#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ -#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ -#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ -#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ -#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ -#define KBD_STAT_PERR 0x80 /* Parity error */ - -#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF) - -/* - * Controller Mode Register Bits - */ - -#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ -#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ -#define KBD_MODE_SYS 0x04 /* The system flag (?) */ -#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ -#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ -#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ -#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ -#define KBD_MODE_RFU 0x80 - -/* - * Mouse Commands - */ - -#define AUX_SET_RES 0xE8 /* Set resolution */ -#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ -#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ -#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ -#define AUX_SET_STREAM 0xEA /* Set stream mode */ -#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ -#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ -#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ -#define AUX_RESET 0xFF /* Reset aux device */ - -#define AUX_BUF_SIZE 2048 - -struct aux_queue { - unsigned long head; - unsigned long tail; - struct wait_queue *proc_list; - struct fasync_struct *fasync; - unsigned char buf[AUX_BUF_SIZE]; -}; - diff -urN linux-2.3.51/arch/ia64/kernel/Makefile linux-2.3.51-lia/arch/ia64/kernel/Makefile --- linux-2.3.51/arch/ia64/kernel/Makefile Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/Makefile Mon Apr 3 23:00:36 2000 @@ -15,13 +15,13 @@ all: kernel.o head.o init_task.o O_TARGET := kernel.o -O_OBJS := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_internal.o ivt.o \ - pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o sal_stub.o semaphore.o setup.o signal.o \ - sys_ia64.o traps.o time.o unaligned.o unwind.o +O_OBJS := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_sapic.o ivt.o \ + pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o sal_stub.o semaphore.o setup.o \ + signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o #O_OBJS := fpreg.o #OX_OBJS := ia64_ksyms.o -ifeq ($(CONFIG_IA64_GENERIC),y) +ifdef CONFIG_IA64_GENERIC O_OBJS += machvec.o endif @@ -30,10 +30,10 @@ endif ifdef CONFIG_SMP -O_OBJS += smp.o irq_lock.o +O_OBJS += smp.o endif -ifeq ($(CONFIG_MCA),y) +ifdef CONFIG_IA64_MCA O_OBJS += mca.o mca_asm.o endif diff -urN linux-2.3.51/arch/ia64/kernel/acpi.c linux-2.3.51-lia/arch/ia64/kernel/acpi.c --- linux-2.3.51/arch/ia64/kernel/acpi.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/acpi.c Mon Apr 3 22:43:36 2000 @@ -11,12 +11,12 @@ #include #include -#include #include #include #include #include #include +#include #include #include @@ -174,7 +174,7 @@ break; } -#ifdef ACPI_DEBUG +#if 1/*def 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"), @@ -208,7 +208,7 @@ #ifdef CONFIG_SMP /* Base address of IPI Message Block */ - ipi_base_addr = ioremap(msapic->interrupt_block, 0); + ipi_base_addr = (unsigned long) ioremap(msapic->interrupt_block, 0); #endif p = (char *) (msapic + 1); @@ -238,7 +238,18 @@ } /* Move to next table entry. */ - p += *(p + 1); +#define BAD_ACPI_TABLE +#ifdef BAD_ACPI_TABLE + /* + * Some prototype Lion's have a bad ACPI table + * requiring this fix. Without this fix, those + * machines crash during bootup. + */ + if (p[1] == 0) + p = end; + else +#endif + p += p[1]; } /* Make bootup pretty */ diff -urN linux-2.3.51/arch/ia64/kernel/efi.c linux-2.3.51-lia/arch/ia64/kernel/efi.c --- linux-2.3.51/arch/ia64/kernel/efi.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/efi.c Mon Apr 3 22:11:22 2000 @@ -24,7 +24,7 @@ #include #include -#define EFI_DEBUG +#define EFI_DEBUG 0 extern efi_status_t efi_call_phys (void *, ...); @@ -210,9 +210,8 @@ void __init efi_init (void) { - void *efi_map_start, *efi_map_end, *p; + void *efi_map_start, *efi_map_end; efi_config_table_t *config_tables; - efi_memory_desc_t *md; efi_char16_t *c16; u64 efi_desc_size; char vendor[100] = "unknown"; @@ -278,13 +277,18 @@ efi_map_end = efi_map_start + ia64_boot_param.efi_memmap_size; efi_desc_size = ia64_boot_param.efi_memdesc_size; -#ifdef EFI_DEBUG +#if EFI_DEBUG /* print EFI memory map: */ - for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { - md = p; - printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", - i, md->type, md->attribute, - md->phys_addr, md->phys_addr + (md->num_pages<<12) - 1, md->num_pages >> 8); + { + efi_memory_desc_t *md = p; + void *p; + + for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { + md = p; + printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", + i, md->type, md->attribute, md->phys_addr, + md->phys_addr + (md->num_pages<<12) - 1, md->num_pages >> 8); + } } #endif } diff -urN linux-2.3.51/arch/ia64/kernel/entry.S linux-2.3.51-lia/arch/ia64/kernel/entry.S --- linux-2.3.51/arch/ia64/kernel/entry.S Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/entry.S Mon Apr 10 19:07:51 2000 @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -504,7 +505,9 @@ ;; ld4 r2=[r2] ;; - shladd r3=r2,3,r3 + shl r2=r2,SMP_LOG_CACHE_BYTES // can't use shladd here... + ;; + add r3=r2,r3 #else movl r3=softirq_state #endif @@ -905,10 +908,11 @@ .align 16 .proc sys_rt_sigreturn sys_rt_sigreturn: - alloc loc0=ar.pfs,8,1,1,0 // preserve all eight input regs in case of syscall restart! + .regstk 0,0,3,0 // inherited from gate.s:invoke_sighandler() adds out0=16,sp // out0 = &pt_regs - ;; adds sp=-IA64_SWITCH_STACK_SIZE,sp // make space for unat and padding + ;; + cmp.eq pNonSys,p0=r0,r0 // sigreturn isn't a normal syscall... br.call.sptk.few rp=ia64_rt_sigreturn .ret13: adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp @@ -918,8 +922,7 @@ ;; adds sp=IA64_SWITCH_STACK_SIZE,sp // drop (dummy) switch-stack frame mov ar.unat=r9 - mov ar.pfs=loc0 - br.ret.sptk.many rp + br rp .endp sys_rt_sigreturn .align 16 @@ -939,76 +942,6 @@ br.cond.sptk.many load_switch_stack 2: br.cond.sptk.many rp // goes to ia64_leave_kernel .endp ia64_prepare_handle_unaligned - -#ifdef CONFIG_KDB - // - // This gets called from ivt.S with: - // SAVE MIN with cover done - // SAVE REST done - // no parameters - // r15 has return value = ia64_leave_kernel - // - .align 16 - .global ia64_invoke_kdb - .proc ia64_invoke_kdb -ia64_invoke_kdb: - alloc r16=ar.pfs,0,0,4,0 - movl r28=1f // save_switch_stack protocol - ;; // avoid WAW on CFM - br.cond.sptk.many save_switch_stack // to flushrs -1: mov out0=4 // kdb entry reason - mov out1=0 // err number - adds out2=IA64_SWITCH_STACK_SIZE+16,sp // pt_regs - add out3=16,sp // switch_stack - br.call.sptk.few rp=kdb -.ret15: - movl r28=1f // load_switch_stack proto - br.cond.sptk.many load_switch_stack -1: br.ret.sptk.many rp - .endp ia64_invoke_kdb - - // - // When KDB is compiled in, we intercept each fault and give - // kdb a chance to run before calling the normal fault handler. - // - .align 16 - .global ia64_invoke_kdb_fault_handler - .proc ia64_invoke_kdb_fault_handler -ia64_invoke_kdb_fault_handler: - alloc r16=ar.pfs,5,1,5,0 - movl r28=1f - mov loc0=rp // save this - br.cond.sptk.many save_switch_stack // to flushrs - ;; // avoid WAW on CFM -1: mov out0=in0 // vector number - mov out1=in1 // cr.isr - mov out2=in2 // cr.ifa - mov out3=in3 // cr.iim - mov out4=in4 // cr.itir - br.call.sptk.few rp=ia64_kdb_fault_handler -.ret16: - - movl r28=1f - br.cond.sptk.many load_switch_stack -1: cmp.ne p6,p0=r8,r0 // did ia64_kdb_fault_handler return 0? - mov rp=loc0 -(p6) br.ret.spnt.many rp // no, we're done - ;; // avoid WAW on rp - mov out0=in0 // vector number - mov out1=in1 // cr.isr - mov out2=in2 // cr.ifa - mov out3=in3 // cr.iim - mov out4=in4 // cr.itir - mov in0=ar.pfs // preserve ar.pfs returned by load_switch_stack - br.call.sptk.few rp=ia64_fault // yup -> we need to invoke normal fault handler now -.ret17: - mov ar.pfs=in0 - mov rp=loc0 - br.ret.sptk.many rp - - .endp ia64_invoke_kdb_fault_handler - -#endif /* CONFIG_KDB */ .rodata .align 8 diff -urN linux-2.3.51/arch/ia64/kernel/gate.S linux-2.3.51-lia/arch/ia64/kernel/gate.S --- linux-2.3.51/arch/ia64/kernel/gate.S Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/gate.S Sat Apr 8 00:46:40 2000 @@ -80,8 +80,6 @@ ia64_sigtramp: ld8 r10=[r3],8 // get signal handler entry point br.call.sptk.many rp=invoke_sighandler -.ret0: mov r15=__NR_rt_sigreturn - break __BREAK_SYSCALL .endp ia64_sigtramp .proc invoke_sighandler @@ -90,10 +88,9 @@ mov b6=r10 cover // push args in interrupted frame onto backing store ;; - alloc r8=ar.pfs,0,1,3,0 // get CFM0, EC0, and CPL0 into r8 - mov r17=ar.bsp // fetch ar.bsp - mov loc0=rp // save return pointer + alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8 ;; + mov r17=ar.bsp // fetch ar.bsp cmp.ne p8,p0=r15,r0 // do we need to switch the rbs? mov out0=r2 // signal number (p8) br.cond.spnt.few setup_rbs // yup -> (clobbers r14 and r16) @@ -101,10 +98,11 @@ adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; st8 [base0]=r17,(CFM_OFF-BSP_OFF) // save sc_ar_bsp + dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp ;; - st8 [base0]=r8 // save CFM0, EC0, and CPL0 + st8 [base0]=r8 // save CFM0 adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp ;; stf.spill [base0]=f6,32 @@ -124,7 +122,8 @@ stf.spill [base0]=f14,32 stf.spill [base1]=f15,32 br.call.sptk.few rp=b6 // call the signal handler -.ret2: adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp +.ret2: + adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF mov r14=ar.bsp @@ -134,23 +133,11 @@ (p8) br.cond.spnt.few restore_rbs // yup -> (clobbers r14 and r16) ;; back_from_restore_rbs: - { - and r9=0x7f,r8 // r9 <- CFM0.sof - extr.u r10=r8,7,7 // r10 <- CFM0.sol - mov r11=ip - } - ;; adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp - adds r11=(cont-back_from_restore_rbs),r11 - sub r9=r9,r10 // r9 <- CFM0.sof - CFM0.sol == CFM0.nout - ;; adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp - dep r9=r9,r9,7,7 // r9.sol = r9.sof - mov b6=r11 ;; ldf.fill f6=[base0],32 ldf.fill f7=[base1],32 - mov rp=loc0 // copy return pointer out of stacked register ;; ldf.fill f8=[base0],32 ldf.fill f9=[base1],32 @@ -160,26 +147,23 @@ ;; ldf.fill f12=[base0],32 ldf.fill f13=[base1],32 - mov ar.pfs=r9 ;; ldf.fill f14=[base0],32 ldf.fill f15=[base1],32 - br.ret.sptk.few b6 -cont: mov ar.pfs=r8 // ar.pfs = CFM0 - br.ret.sptk.few rp // re-establish CFM0 + mov r15=__NR_rt_sigreturn + break __BREAK_SYSCALL .endp invoke_sighandler .proc setup_rbs setup_rbs: flushrs // must be first in insn - ;; mov ar.rsc=r0 // put RSE into enforced lazy mode adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp - mov r14=ar.rnat // get rnat as updated by flushrs ;; + mov r14=ar.rnat // get rnat as updated by flushrs mov ar.bspstore=r15 // set new register backing store area - st8 [r16]=r14 // save sc_ar_rnat ;; + st8 [r16]=r14 // save sc_ar_rnat mov ar.rsc=0xf // set RSE into eager mode, pl 3 invala // invalidate ALAT br.cond.sptk.many back_from_setup_rbs diff -urN linux-2.3.51/arch/ia64/kernel/irq.c linux-2.3.51-lia/arch/ia64/kernel/irq.c --- linux-2.3.51/arch/ia64/kernel/irq.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/irq.c Tue Apr 4 08:14:18 2000 @@ -66,7 +66,7 @@ * Controller mappings for all interrupt sources: */ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = - { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; + { [0 ... NR_IRQS-1] = { IRQ_DISABLED, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; static void register_irq_proc (unsigned int irq); @@ -164,7 +164,7 @@ p += sprintf(p, "%10u ", atomic_read(&nmi_counter(cpu_logical_map(j)))); p += sprintf(p, "\n"); -#if CONFIG_SMP +#if defined(CONFIG_SMP) && defined(__i386__) p += sprintf(p, "LOC: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", @@ -182,8 +182,8 @@ */ #ifdef CONFIG_SMP -unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile int global_irq_lock; +unsigned int global_irq_holder = NO_PROC_ID; +volatile unsigned int global_irq_lock; extern void show_stack(unsigned long* esp); @@ -201,6 +201,10 @@ printk(" %d",local_bh_count(i)); printk(" ]\nStack dumps:"); +#ifdef __ia64__ + printk(" ]\nStack dumps: "); + /* for now we don't have stack dumping support... */ +#elif __i386__ for(i=0;i< smp_num_cpus;i++) { unsigned long esp; if(i==cpu) @@ -219,8 +223,13 @@ esp += sizeof(struct task_struct); show_stack((void*)esp); } +#else + You lose... +#endif printk("\nCPU %d:",cpu); +#ifdef __i386__ show_stack(NULL); +#endif printk("\n"); } @@ -250,7 +259,11 @@ /* * We have to allow irqs to arrive between __sti and __cli */ -# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") +# ifdef __ia64__ +# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop 0") +# else +# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") +# endif #endif static inline void wait_on_irq(int cpu) @@ -311,7 +324,7 @@ { if (test_and_set_bit(0,&global_irq_lock)) { /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) + if (cpu == global_irq_holder) return; /* Uhhuh.. Somebody else got it. Wait.. */ do { @@ -349,6 +362,15 @@ { unsigned int flags; +#ifdef __ia64__ + __save_flags(flags); + if (flags & IA64_PSR_I) { + int cpu = smp_processor_id(); + __cli(); + if (!local_irq_count(cpu)) + get_irqlock(cpu); + } +#else __save_flags(flags); if (flags & (1 << EFLAGS_IF_SHIFT)) { int cpu = smp_processor_id(); @@ -356,6 +378,7 @@ if (!local_irq_count(cpu)) get_irqlock(cpu); } +#endif } void __global_sti(void) @@ -382,7 +405,11 @@ int cpu = smp_processor_id(); __save_flags(flags); +#ifdef __ia64__ + local_enabled = (flags & IA64_PSR_I) != 0; +#else local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1; +#endif /* default to local */ retval = 2 + local_enabled; @@ -479,11 +506,13 @@ { disable_irq_nosync(irq); +#ifdef CONFIG_SMP if (!local_irq_count(smp_processor_id())) { do { barrier(); } while (irq_desc[irq].status & IRQ_INPROGRESS); } +#endif } void enable_irq(unsigned int irq) @@ -553,21 +582,20 @@ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { action = desc->action; status &= ~IRQ_PENDING; /* we commit to handling */ +#ifdef CONFIG_SMP status |= IRQ_INPROGRESS; /* we are handling it */ +#endif } desc->status = status; /* * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. + * Since we set PENDING, if another processor is handling + * a different instance of this same irq, the other processor + * will take care of it. */ if (!action) -{ - desc->status = status & ~IRQ_INPROGRESS; goto out; -} /* * Edge triggered interrupts need to remember @@ -588,7 +616,9 @@ break; desc->status &= ~IRQ_PENDING; } +#ifdef CONFIG_SMP desc->status &= ~IRQ_INPROGRESS; +#endif out: /* * The ->end() handler has to deal with interrupts which got @@ -597,15 +627,6 @@ desc->handler->end(irq); spin_unlock(&desc->lock); -#if 0 - /* - * let kernel exit path take care of this; we want to do the - * CPU EOI before doing softirq() so a new interrupt can come - * through - */ - if (softirq_state[cpu].active & softirq_state[cpu].mask) - do_softirq(); -#endif return 1; } @@ -711,6 +732,7 @@ unsigned long val; unsigned long delay; +printk("probe_irq_on\n"); /* * something may have generated an irq long ago and we want to * flush such a longstanding irq before considering it as spurious. @@ -838,6 +860,7 @@ if (nr_irqs > 1) irq_found = -irq_found; +printk("probe_irq_off=%d\n", irq_found); return irq_found; } @@ -849,6 +872,7 @@ struct irqaction *old, **p; irq_desc_t *desc = irq_desc + irq; +printk("setup_irq(irq=%u,type=%s)\n", irq, desc->handler->typename); /* * Some drivers like serial.c use request_irq() heavily, * so we have to be careful not to interfere with a diff -urN linux-2.3.51/arch/ia64/kernel/irq_ia64.c linux-2.3.51-lia/arch/ia64/kernel/irq_ia64.c --- linux-2.3.51/arch/ia64/kernel/irq_ia64.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/irq_ia64.c Mon Apr 3 22:31:57 2000 @@ -25,10 +25,6 @@ #include #include -#ifdef CONFIG_KDB -# include -#endif - #include #include #include @@ -45,9 +41,9 @@ * Legacy IRQ to IA-64 vector translation table. Any vector not in * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30) */ -__u8 isa_irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = { +__u8 isa_irq_to_vector_map[16] = { /* 8259 IRQ translation, first 16 entries */ - 0x60, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54, + 0x60, 0x50, 0x10, 0x51, 0x52, 0x53, 0x43, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41 }; @@ -80,8 +76,8 @@ #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC # ifndef CONFIG_SMP static unsigned int max_prio = 0; -# endif unsigned int prev_prio; +# endif unsigned long eoi_ptr; # ifdef CONFIG_USB @@ -95,21 +91,25 @@ * Stop IPIs by getting the ivr_read_lock */ spin_lock(&ivr_read_lock); + { + unsigned int tmp; - /* - * Disable PCI writes - */ - outl(0x80ff81c0, 0xcf8); - outl(0x73002188, 0xcfc); - eoi_ptr = inl(0xcfc); - - vector = ia64_get_ivr(); - - /* - * Enable PCI writes - */ - outl(0x73182188, 0xcfc); - + /* + * Disable PCI writes + */ + outl(0x80ff81c0, 0xcf8); + tmp = inl(0xcfc); + outl(tmp | 0x400, 0xcfc); + + eoi_ptr = inl(0xcfc); + + vector = ia64_get_ivr(); + + /* + * Enable PCI writes + */ + outl(tmp, 0xcfc); + } spin_unlock(&ivr_read_lock); # ifdef CONFIG_USB @@ -152,11 +152,11 @@ printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n" "(bsp=0x%lx, sp=%lx)\n", bsp, sp); } -#ifdef CONFIG_KDB - kdb(KDB_REASON_PANIC, 0, regs); -#endif } +if (vector == 65 || vector < 16) + printk("ia64_handle_irq(vector=%lu, status=%x)\n", vector, irq_desc[vector].status); + /* * The interrupt is now said to be in service */ @@ -175,9 +175,6 @@ if (!pEOI) { printk("Yikes: ia64_handle_irq() without pEOI!!\n"); asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI)); -# ifdef CONFIG_KDB - kdb(KDB_REASON_PANIC, 0, regs); -# endif } } @@ -195,11 +192,18 @@ #ifdef CONFIG_SMP +extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs); + +static struct irqaction ipi_irqaction = { + handler: handle_IPI, + flags: SA_INTERRUPT, + name: "IPI" +}; + void __init init_IRQ_SMP (void) { - if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL)) - panic("Could not allocate IPI Interrupt Handler!"); + setup_irq(IPI_IRQ, &ipi_irqaction); } #endif @@ -214,12 +218,13 @@ ia64_set_lrr0(0, 1); ia64_set_lrr1(0, 1); - irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal; + irq_desc[TIMER_IRQ].handler = &irq_type_ia64_sapic; + irq_desc[IA64_SPURIOUS_INT].handler = &irq_type_ia64_sapic; #ifdef CONFIG_SMP /* * Configure the IPI vector and handler */ - irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal; + irq_desc[IPI_IRQ].handler = &irq_type_ia64_sapic; init_IRQ_SMP(); #endif diff -urN linux-2.3.51/arch/ia64/kernel/irq_internal.c linux-2.3.51-lia/arch/ia64/kernel/irq_internal.c --- linux-2.3.51/arch/ia64/kernel/irq_internal.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/irq_internal.c Wed Dec 31 16:00:00 1969 @@ -1,36 +0,0 @@ -/* - * Internal Interrupt Vectors - * - * This takes care of interrupts that are generated by the CPU - * internally, such as the ITC and IPI interrupts. - * - * Copyright (C) 1999 VA Linux Systems - * Copyright (C) 1999 Walt Drummond - * Copyright (C) 2000 Hewlett-Packard Co - * Copyright (C) 2000 David Mosberger-Tang - */ - -#include - -static unsigned int -internal_noop_startup (unsigned int irq) -{ - return 0; -} - -static void -internal_noop (unsigned int irq) -{ - /* nuthing to do... */ -} - -struct hw_interrupt_type irq_type_ia64_internal = { - typename: "IA64-internal", - startup: internal_noop_startup, - shutdown: internal_noop, - enable: internal_noop, - disable: internal_noop, - ack: internal_noop, - end: internal_noop, - set_affinity: (void (*)(unsigned int, unsigned long)) internal_noop -}; diff -urN linux-2.3.51/arch/ia64/kernel/irq_lock.c linux-2.3.51-lia/arch/ia64/kernel/irq_lock.c --- linux-2.3.51/arch/ia64/kernel/irq_lock.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/irq_lock.c Wed Dec 31 16:00:00 1969 @@ -1,287 +0,0 @@ -/* - * SMP IRQ Lock support - * - * Global interrupt locks for SMP. Allow interrupts to come in on any - * CPU, yet make cli/sti act globally to protect critical regions.. - * These function usually appear in irq.c, but I think it's cleaner this way. - * - * Copyright (C) 1999 VA Linux Systems - * Copyright (C) 1999 Walt Drummond - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -int global_irq_holder = NO_PROC_ID; -spinlock_t global_irq_lock; -atomic_t global_irq_count; -atomic_t global_bh_count; -spinlock_t global_bh_lock; - -#define INIT_STUCK (1<<26) - -void -irq_enter(int cpu, int irq) -{ - int stuck = INIT_STUCK; - - hardirq_enter(cpu, irq); - barrier(); - while (global_irq_lock.lock) { - if (cpu == global_irq_holder) { - break; - } - - if (!--stuck) { - printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", - irq, cpu,global_irq_holder); - stuck = INIT_STUCK; - } - barrier(); - } -} - -void -irq_exit(int cpu, int irq) -{ - hardirq_exit(cpu, irq); - release_irqlock(cpu); -} - -static void -show(char * str) -{ - int i; - unsigned long *stack; - int cpu = smp_processor_id(); - - printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [%d %d]\n", - atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]); - printk("bh: %d [%d %d]\n", - atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]); - - stack = (unsigned long *) &stack; - for (i = 40; i ; i--) { - unsigned long x = *++stack; - if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) { - printk("<[%08lx]> ", x); - } - } -} - -#define MAXCOUNT 100000000 - -static inline void -wait_on_bh(void) -{ - int count = MAXCOUNT; - do { - if (!--count) { - show("wait_on_bh"); - count = ~0; - } - /* nothing .. wait for the other bh's to go away */ - } while (atomic_read(&global_bh_count) != 0); -} - -static inline void -wait_on_irq(int cpu) -{ - int count = MAXCOUNT; - - for (;;) { - - /* - * Wait until all interrupts are gone. Wait - * for bottom half handlers unless we're - * already executing in one.. - */ - if (!atomic_read(&global_irq_count)) { - if (local_bh_count[cpu] || !atomic_read(&global_bh_count)) - break; - } - - /* Duh, we have to loop. Release the lock to avoid deadlocks */ - spin_unlock(&global_irq_lock); - mb(); - - for (;;) { - if (!--count) { - show("wait_on_irq"); - count = ~0; - } - __sti(); - udelay(cpu + 1); - __cli(); - if (atomic_read(&global_irq_count)) - continue; - if (global_irq_lock.lock) - continue; - if (!local_bh_count[cpu] && atomic_read(&global_bh_count)) - continue; - if (spin_trylock(&global_irq_lock)) - break; - } - } -} - -/* - * This is called when we want to synchronize with - * bottom half handlers. We need to wait until - * no other CPU is executing any bottom half handler. - * - * Don't wait if we're already running in an interrupt - * context or are inside a bh handler. - */ -void -synchronize_bh(void) -{ - if (atomic_read(&global_bh_count)) { - int cpu = smp_processor_id(); - if (!local_irq_count[cpu] && !local_bh_count[cpu]) { - wait_on_bh(); - } - } -} - - -/* - * This is called when we want to synchronize with - * interrupts. We may for example tell a device to - * stop sending interrupts: but to make sure there - * are no interrupts that are executing on another - * CPU we need to call this function. - */ -void -synchronize_irq(void) -{ - int cpu = smp_processor_id(); - int local_count; - int global_count; - - mb(); - do { - local_count = local_irq_count[cpu]; - global_count = atomic_read(&global_irq_count); - } while (global_count != local_count); -} - -static inline void -get_irqlock(int cpu) -{ - if (!spin_trylock(&global_irq_lock)) { - /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) - return; - /* Uhhuh.. Somebody else got it. Wait.. */ - spin_lock(&global_irq_lock); - } - /* - * We also to make sure that nobody else is running - * in an interrupt context. - */ - wait_on_irq(cpu); - - /* - * Ok, finally.. - */ - global_irq_holder = cpu; -} - -/* - * A global "cli()" while in an interrupt context - * turns into just a local cli(). Interrupts - * should use spinlocks for the (very unlikely) - * case that they ever want to protect against - * each other. - * - * If we already have local interrupts disabled, - * this will not turn a local disable into a - * global one (problems with spinlocks: this makes - * save_flags+cli+sti usable inside a spinlock). - */ -void -__global_cli(void) -{ - unsigned long flags; - - __save_flags(flags); - if (flags & IA64_PSR_I) { - int cpu = smp_processor_id(); - __cli(); - if (!local_irq_count[cpu]) - get_irqlock(cpu); - } -} - -void -__global_sti(void) -{ - int cpu = smp_processor_id(); - - if (!local_irq_count[cpu]) - release_irqlock(cpu); - __sti(); -} - -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long -__global_save_flags(void) -{ - int retval; - int local_enabled; - unsigned long flags; - - __save_flags(flags); - local_enabled = flags & IA64_PSR_I; - /* default to local */ - retval = 2 + local_enabled; - - /* check for global flags if we're not in an interrupt */ - if (!local_irq_count[smp_processor_id()]) { - if (local_enabled) - retval = 1; - if (global_irq_holder == (unsigned char) smp_processor_id()) - retval = 0; - } - return retval; -} - -void -__global_restore_flags(unsigned long flags) -{ - switch (flags) { - case 0: - __global_cli(); - break; - case 1: - __global_sti(); - break; - case 2: - __cli(); - break; - case 3: - __sti(); - break; - default: - printk("global_restore_flags: %08lx (%08lx) from %p\n", - flags, (&flags)[-1], __builtin_return_address(0)); - } -} diff -urN linux-2.3.51/arch/ia64/kernel/irq_sapic.c linux-2.3.51-lia/arch/ia64/kernel/irq_sapic.c --- linux-2.3.51/arch/ia64/kernel/irq_sapic.c Wed Dec 31 16:00:00 1969 +++ linux-2.3.51-lia/arch/ia64/kernel/irq_sapic.c Mon Apr 3 23:12:11 2000 @@ -0,0 +1,38 @@ +/* + * SAPIC Interrupt Controller + * + * This takes care of interrupts that are generated by the CPU's + * internal Streamlined Advanced Programmable Interrupt Controller + * (SAPIC), such as the ITC and IPI interrupts. + * + * Copyright (C) 1999 VA Linux Systems + * Copyright (C) 1999 Walt Drummond + * Copyright (C) 2000 Hewlett-Packard Co + * Copyright (C) 2000 David Mosberger-Tang + */ + +#include +#include + +static unsigned int +sapic_noop_startup (unsigned int irq) +{ + return 0; +} + +static void +sapic_noop (unsigned int irq) +{ + /* nuthing to do... */ +} + +struct hw_interrupt_type irq_type_ia64_sapic = { + typename: "SAPIC", + startup: sapic_noop_startup, + shutdown: sapic_noop, + enable: sapic_noop, + disable: sapic_noop, + ack: sapic_noop, + end: sapic_noop, + set_affinity: (void (*)(unsigned int, unsigned long)) sapic_noop +}; diff -urN linux-2.3.51/arch/ia64/kernel/ivt.S linux-2.3.51-lia/arch/ia64/kernel/ivt.S --- linux-2.3.51/arch/ia64/kernel/ivt.S Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/ivt.S Tue Apr 4 12:28:36 2000 @@ -491,14 +491,14 @@ movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RX ;; shr.u r18=r16,57 // move address bit 61 to bit 4 - dep r16=0,r16,52,12 // clear top 12 bits of address + dep r16=0,r16,50,14 // clear top 14 bits of address ;; andcm r18=0x10,r18 // bit 4=~address-bit(61) dep r16=r17,r16,0,12 // insert PTE control bits into r16 ;; or r16=r16,r18 // set bit 4 (uncached) if the access was to region 6 ;; - itc.i r16;; // insert the TLB entry(EAS2.6: must be last in insn group!) + itc.i r16;; // insert the TLB entry (must be last in insn group) rfi;; // must be last insn in an insn group .align 1024 @@ -508,7 +508,7 @@ movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RW ;; shr.u r18=r16,57 // move address bit 61 to bit 4 - dep r16=0,r16,52,12 // clear top 12 bits of address + dep r16=0,r16,50,14 // clear top 14 bits of address ;; andcm r18=0x10,r18 // bit 4=~address-bit(61) dep r16=r17,r16,0,12 // insert PTE control bits into r16 @@ -885,13 +885,6 @@ FAULT(17) non_syscall: - -#ifdef CONFIG_KDB - mov r17=__IA64_BREAK_KDB - ;; - cmp.eq p8,p0=r16,r17 // is this a kernel breakpoint? -#endif - SAVE_MIN_WITH_COVER // There is no particular reason for this code to be here, other than that @@ -918,9 +911,6 @@ SAVE_REST mov rp=r15 ;; -#ifdef CONFIG_KDB -(p8) br.call.sptk.few b6=ia64_invoke_kdb -#endif br.call.sptk.few b6=ia64_bad_break // avoid WAW on CFM and ignore return addr .align 1024 @@ -1012,11 +1002,7 @@ movl r14=ia64_leave_kernel ;; mov rp=r14 -#ifdef CONFIG_KDB - br.call.sptk.few b6=ia64_invoke_kdb_fault_handler -#else br.call.sptk.few b6=ia64_fault -#endif // // --- End of long entries, Beginning of short entries // @@ -1142,11 +1128,7 @@ ;; srlz.d // ensure everyone knows psr.dt is off mov r19=30 // error vector for fault_handler (when kernel) - extr.u r16=r16,32,2 // extract psr.cpl - ;; - cmp.eq p6,p7=r0,r16 // if kernel cpl then fault else emulate -(p7) br.cond.sptk.many dispatch_unaligned_handler -(p6) br.cond.sptk.many dispatch_to_fault_handler + br.cond.sptk.many dispatch_unaligned_handler .align 256 ///////////////////////////////////////////////////////////////////////////////////////// @@ -1226,6 +1208,31 @@ .align 256 ///////////////////////////////////////////////////////////////////////////////////////// // 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) +#ifdef CONFIG_IA32_SUPPORT + rsm psr.dt + ;; + srlz.d + mov r31=pr + mov r16=cr.isr + ;; + extr.u r17=r16,16,8 // get ISR.code + mov r18=ar.eflag + mov r19=cr.iim // old eflag value + ;; + cmp.ne p2,p0=2,r17 +(p2) br.cond.spnt 1f // not a system flag fault + xor r16=r18,r19 + ;; + extr.u r17=r16,18,1 // get the eflags.ac bit + ;; + cmp.eq p2,p0=0,r17 +(p2) br.cond.spnt 1f // eflags.ac bit didn't change + mov pr=r31,-1 // restore predicate registers + rfi + ;; + +1: +#endif // CONFIG_IA32_SUPPORT FAULT(46) .align 256 diff -urN linux-2.3.51/arch/ia64/kernel/mca.c linux-2.3.51-lia/arch/ia64/kernel/mca.c --- linux-2.3.51/arch/ia64/kernel/mca.c Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/mca.c Mon Apr 3 23:03:12 2000 @@ -2,18 +2,28 @@ * File: mca.c * Purpose: Generic MCA handling layer * + * + * Updated for latest kernel + * Copyright (C) 2000 Intel + * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com) + * + * * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) + * */ #include #include #include +#include +#include + #include #include #include #include #include -#include + #include #include @@ -36,6 +46,33 @@ static void ia64_log_clear(int,int,int, prfunc_t); /* + * hack for now, add platform dependent handlers + * here + */ +#ifndef PLATFORM_MCA_HANDLERS +void mca_handler_platform (void) +{ + +} +void cmci_handler_platform (int cmc_irq, void *arg, struct pt_regs *ptregs) +{ + +} + +void log_print_platform ( void *cur_buff_ptr, prfunc_t prfunc) +{ + +} + +void ia64_mca_init_platform(void) +{ + +} +#endif /* PLATFORM_MCA_HANDLERS */ + + + +/* * ia64_mca_cmc_vector_setup * Setup the correctable machine check vector register in the processor * Inputs @@ -83,7 +120,7 @@ #endif /* #if defined(MCA_TEST) */ /* - * mca_init + * ia64_mca_init * Do all the mca specific initialization on a per-processor basis. * * 1. Register spinloop and wakeup request interrupt vectors @@ -93,7 +130,7 @@ * 3. Register OS_INIT handler entry point * * 4. Initialize CMCV register to enable/disable CMC interrupt on the - * processor and hook a handler in the platform-specific mca_init. + * processor and hook a handler in the platform-specific ia64_mca_init. * * 5. Initialize MCA/CMC/INIT related log buffers maintained by the OS. * @@ -103,11 +140,11 @@ * None */ void __init -mca_init(void) +ia64_mca_init(void) { int i; - MCA_DEBUG("mca_init : begin\n"); + IA64_MCA_DEBUG("ia64_mca_init : begin\n"); /* Clear the Rendez checkin flag for all cpus */ for(i = 0 ; i < IA64_MAXCPUS; i++) ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; @@ -134,14 +171,14 @@ 0)) return; - MCA_DEBUG("mca_init : registered mca rendezvous spinloop and wakeup mech.\n"); + IA64_MCA_DEBUG("ia64_mca_init : registered mca rendezvous spinloop and wakeup mech.\n"); /* * Setup the correctable machine check vector */ ia64_mca_cmc_vector_setup(IA64_CMC_INT_ENABLE, IA64_MCA_CMC_INT_VECTOR); - MCA_DEBUG("mca_init : correctable mca vector setup done\n"); + 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 = @@ -155,7 +192,7 @@ return; - MCA_DEBUG("mca_init : registered os mca handler with SAL\n"); + IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL\n"); ia64_mc_info.imi_monarch_init_handler = __pa(ia64_monarch_init_handler); ia64_mc_info.imi_monarch_init_handler_size = IA64_INIT_HANDLER_SIZE; @@ -173,7 +210,7 @@ return; - MCA_DEBUG("mca_init : registered os init handler with SAL\n"); + IA64_MCA_DEBUG("ia64_mca_init : registered os init handler with SAL\n"); /* Initialize the areas set aside by the OS to buffer the * platform/processor error states for MCA/INIT/CMC @@ -186,9 +223,9 @@ ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR); ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM); - mca_init_platform(); + ia64_mca_init_platform(); - MCA_DEBUG("mca_init : platform-specific mca handling setup done\n"); + IA64_MCA_DEBUG("ia64_mca_init : platform-specific mca handling setup done\n"); #if defined(MCA_TEST) mca_test(); @@ -399,7 +436,7 @@ /* * SAL to OS entry point for INIT on the monarch processor * This has been defined for registration purposes with SAL - * as a part of mca_init. + * as a part of ia64_mca_init. */ void ia64_monarch_init_handler() @@ -408,7 +445,7 @@ /* * SAL to OS entry point for INIT on the slave processor * This has been defined for registration purposes with SAL - * as a part of mca_init. + * as a part of ia64_mca_init. */ void diff -urN linux-2.3.51/arch/ia64/kernel/mca_asm.S linux-2.3.51-lia/arch/ia64/kernel/mca_asm.S --- linux-2.3.51/arch/ia64/kernel/mca_asm.S Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/mca_asm.S Wed Mar 15 17:34:20 2000 @@ -1,7 +1,12 @@ +// +// assembly portion of the IA64 MCA handling +// +// Mods by cfleck for current kernel build +// 00/03/15 davidm Added various stop bits to get a clean compile +#include #include -#include -#include -#include +#include + .psr abi64 .psr lsb @@ -54,7 +59,9 @@ 100: (p) mov temp=ip; \ ;; \ (p) adds temp=to_label-100b,temp;\ + ;; \ (p) adds temp=adjust,temp; \ + ;; \ (p) mov b1=temp ; \ (p) br b1 @@ -341,6 +348,7 @@ mov r3=ar16 // ar.rsc mov ar16=r0 // put RSE in enforced lazy mode mov r5=ar17 // ar.bsp + ;; mov r7=ar18;; // ar.bspstore st8 [r2]=r3,3*8 st8 [r4]=r5,3*8 @@ -575,6 +583,7 @@ // mov ar16=r3 // ar.rsc // mov ar17=r5 // ar.bsp is read only mov ar16=r0 // make sure that RSE is in enforced lazy mode + ;; mov ar18=r7;; // ar.bspstore ld8 r9=[r2],8*13;; diff -urN linux-2.3.51/arch/ia64/kernel/ptrace.c linux-2.3.51-lia/arch/ia64/kernel/ptrace.c --- linux-2.3.51/arch/ia64/kernel/ptrace.c Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/ptrace.c Fri Apr 7 23:10:26 2000 @@ -23,6 +23,14 @@ #include /* + * Bits in the PSR that we allow ptrace() to change: + * be, up, ac, mfl, mfh (the user mask; five bits total) + * db (debug breakpoint fault; one bit) + * ri (restart instruction; two bits) + */ +#define CR_IPSR_CHANGE_MASK 0x06000100003eUL + +/* * Collect the NaT bits for r1-r31 from sw->caller_unat and * sw->ar_unat and return a NaT bitset where bit i is set iff the NaT * bit of register i is set. @@ -352,6 +360,94 @@ } /* + * Synchronize (i.e, write) the RSE backing store living in kernel + * space to the VM of the indicated child process. + * + * If new_bsp is non-zero, the bsp will (effectively) be updated to + * the new value upon resumption of the child process. This is + * accomplished by setting the loadrs value to zero and the bspstore + * value to the new bsp value. + * + * When new_bsp and force_loadrs_to_zero are both 0, the register + * backing store in kernel space is written to user space and the + * loadrs and bspstore values are left alone. + * + * When new_bsp is zero and force_loadrs_to_zero is 1 (non-zero), + * loadrs is set to 0, and the bspstore value is set to the old bsp + * value. This will cause the stacked registers (r32 and up) to be + * obtained entirely from the the child's memory space rather than + * from the kernel. (This makes it easier to write code for + * modifying the stacked registers in multi-threaded programs.) + * + * Note: I had originally written this function without the + * force_loadrs_to_zero parameter; it was written so that loadrs would + * always be set to zero. But I had problems with certain system + * calls apparently causing a portion of the RBS to be zeroed. (I + * still don't understand why this was happening.) Anyway, it'd + * definitely less intrusive to leave loadrs and bspstore alone if + * possible. + */ +static long +sync_kernel_register_backing_store (struct task_struct *child, + long new_bsp, + int force_loadrs_to_zero) +{ + unsigned long *krbs, bspstore, bsp, krbs_num_regs, rbs_end, addr, val; + long ndirty, ret; + struct pt_regs *child_regs; + struct switch_stack *child_stack; + + ret = 0; + child_regs = ia64_task_regs(child); + child_stack = (struct switch_stack *) child_regs - 1; + + krbs = (unsigned long *) child + IA64_RBS_OFFSET/8; + ndirty = ia64_rse_num_regs(krbs, krbs + (child_regs->loadrs >> 19)); + bspstore = child_regs->ar_bspstore; + bsp = (long) ia64_rse_skip_regs((long *)bspstore, ndirty); + krbs_num_regs = ia64_rse_num_regs(krbs, (unsigned long *) child_stack->ar_bspstore); + rbs_end = (long) ia64_rse_skip_regs((long *)bspstore, krbs_num_regs); + + /* Return early if nothing to do */ + if (bsp == new_bsp) + return 0; + + /* Write portion of backing store living on kernel stack to the child's VM. */ + for (addr = bspstore; addr < rbs_end; addr += 8) { + ret = ia64_peek(child_regs, child, addr, &val); + if (ret != 0) + return ret; + if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) + return -EIO; + } + + if (new_bsp != 0) { + force_loadrs_to_zero = 1; + bsp = new_bsp; + } + + if (force_loadrs_to_zero) { + child_regs->loadrs = 0; + child_regs->ar_bspstore = bsp; + } + + return ret; +} + +static void +sync_thread_rbs (struct task_struct *child, int make_writable) +{ + struct task_struct *p; + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->mm == child->mm && p->state != TASK_RUNNING) + sync_kernel_register_backing_store(p, 0, make_writable); + } + read_unlock(&tasklist_lock); + child->thread.flags |= IA64_THREAD_KRBS_SYNCED; +} + +/* * Ensure the state in child->thread.fph is up-to-date. */ static void @@ -375,8 +471,8 @@ struct switch_stack *child_stack; struct pt_regs *child_regs; struct task_struct *child; - unsigned long flags, *base; - long ret, regnum; + unsigned long flags, regnum, *base; + long ret; lock_kernel(); ret = -EPERM; @@ -441,6 +537,9 @@ switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: /* read word at location addr */ + if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED) + && atomic_read(&child->mm->mm_users) > 1) + sync_thread_rbs(child, 0); ret = ia64_peek(regs, child, addr, &data); if (ret == 0) { ret = data; @@ -450,6 +549,9 @@ case PTRACE_POKETEXT: case PTRACE_POKEDATA: /* write the word at location addr */ + if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED) + && atomic_read(&child->mm->mm_users) > 1) + sync_thread_rbs(child, 1); ret = ia64_poke(regs, child, addr, data); goto out; @@ -477,8 +579,35 @@ bspstore = (unsigned long *) child_regs->ar_bspstore; ndirty = ia64_rse_num_regs(rbs, rbs + (ret >> 19)); ret = (unsigned long) ia64_rse_skip_regs(bspstore, ndirty); + + /* + * If we're in a system call, no ``cover'' was done. So + * to make things uniform, we'll add the appropriate + * displacement onto bsp if we're in a system call. + * + * Note: It may be better to leave the system call case + * alone and subtract the amount of the cover for the + * non-syscall case. That way the reported bsp value + * would actually be the correct bsp for the child + * process. + */ + if (!(child_regs->cr_ifs & (1UL << 63))) { + ret = (unsigned long) + ia64_rse_skip_regs((unsigned long *) ret, + child_stack->ar_pfs & 0x7f); + } + } else if (addr == PT_CFM) { + /* ret currently contains pt_regs.cr_ifs */ + if ((ret & (1UL << 63)) == 0) + ret = child_stack->ar_pfs; + ret &= 0x3fffffffffUL; /* return only the CFM */ } } else { + if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { + child->thread.flags |= IA64_THREAD_DBG_VALID; + memset(child->thread.dbr, 0, sizeof child->thread.dbr); + memset(child->thread.ibr, 0, sizeof child->thread.ibr); + } if (addr >= PT_IBR) { regnum = (addr - PT_IBR) >> 3; base = &child->thread.ibr[0]; @@ -488,7 +617,7 @@ } if (regnum >= 8) goto out; - data = base[regnum]; + ret = base[regnum]; } regs->r8 = 0; /* ensure "ret" is not mistaken as an error code */ goto out; @@ -503,29 +632,47 @@ sync_fph(child); addr += (unsigned long) &child->thread.fph; *(unsigned long *) addr = data; - if (ret < 0) - goto out; + } else if (addr == PT_AR_BSPSTORE || addr == PT_CALLER_UNAT + || addr == PT_KERNEL_FPSR || addr == PT_K_B0 || addr == PT_K_AR_PFS + || (PT_K_AR_UNAT <= addr && addr <= PT_K_PR)) { + /* + * Don't permit changes to certain registers. + * + * We don't allow bspstore to be modified because doing + * so would mess up any modifications to bsp. (See + * sync_kernel_register_backing_store for the details.) + */ + goto out; + } else if (addr == PT_AR_BSP) { + /* FIXME? Account for lack of ``cover'' in the syscall case */ + ret = sync_kernel_register_backing_store(child, data, 1); + goto out; + } else if (addr == PT_CFM) { + child_regs = ia64_task_regs(child); + child_stack = (struct switch_stack *) child_regs - 1; + + if (child_regs->cr_ifs & (1UL << 63)) { + child_regs->cr_ifs = (child_regs->cr_ifs & ~0x3fffffffffUL) + | (data & 0x3fffffffffUL); + } else { + child_stack->ar_pfs = (child_stack->ar_pfs & ~0x3fffffffffUL) + | (data & 0x3fffffffffUL); + } } else if (addr < PT_F9+16) { /* accessing switch_stack or pt_regs */ child_regs = ia64_task_regs(child); child_stack = (struct switch_stack *) child_regs - 1; - if (addr == PT_AR_BSP) { - /* compute the loadrs value based on bsp and bspstore: */ - unsigned long *rbs, *bspstore, ndirty, *kbsp; - - bspstore = (unsigned long *) child_regs->ar_bspstore; - ndirty = ia64_rse_num_regs(bspstore, (unsigned long *) data); - rbs = (unsigned long *) child + IA64_RBS_OFFSET/8; - kbsp = ia64_rse_skip_regs(rbs, ndirty); - data = (kbsp - rbs) << 19; - } + if (addr == PT_CR_IPSR) + data = (data & CR_IPSR_CHANGE_MASK) + | (child_regs->cr_ipsr & ~CR_IPSR_CHANGE_MASK); + *(unsigned long *) ((long) child_stack + addr - PT_CALLER_UNAT) = data; } else { if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { child->thread.flags |= IA64_THREAD_DBG_VALID; - memset(current->thread.dbr, 0, sizeof current->thread.dbr); - memset(current->thread.ibr, 0, sizeof current->thread.ibr); + memset(child->thread.dbr, 0, sizeof child->thread.dbr); + memset(child->thread.ibr, 0, sizeof child->thread.ibr); } if (addr >= PT_IBR) { @@ -538,7 +685,7 @@ if (regnum >= 8) goto out; if (regnum & 1) { - /* force breakpoint to be effective a most for user-level: */ + /* force breakpoint to be effective only for user-level: */ data &= ~(0x7UL << 56); } base[regnum] = data; @@ -561,6 +708,9 @@ ia64_psr(ia64_task_regs(child))->ss = 0; ia64_psr(ia64_task_regs(child))->tb = 0; + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; + wake_up_process(child); ret = 0; goto out; @@ -579,6 +729,9 @@ ia64_psr(ia64_task_regs(child))->ss = 0; ia64_psr(ia64_task_regs(child))->tb = 0; + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; + wake_up_process(child); ret = 0; goto out; @@ -597,6 +750,9 @@ } child->exit_code = data; + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; + /* give it a chance to run. */ wake_up_process(child); ret = 0; @@ -618,6 +774,9 @@ /* make sure the single step/take-branch tra bits are not set: */ ia64_psr(ia64_task_regs(child))->ss = 0; ia64_psr(ia64_task_regs(child))->tb = 0; + + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; wake_up_process(child); ret = 0; diff -urN linux-2.3.51/arch/ia64/kernel/sal_stub.S linux-2.3.51-lia/arch/ia64/kernel/sal_stub.S --- linux-2.3.51/arch/ia64/kernel/sal_stub.S Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/sal_stub.S Tue Mar 28 20:36:01 2000 @@ -1,17 +1,19 @@ /* - * gcc currently does not conform to the ia-64 calling convention as far - * as returning function values are concerned. Instead of returning - * values up to 32 bytes in size in r8-r11, gcc returns any value - * bigger than a doubleword via a structure that's allocated by the - * caller and whose address is passed into the function. Since - * SAL_PROC returns values according to the calling convention, this - * stub takes care of copying r8-r11 to the place where gcc expects - * them. - * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang */ #ifndef __GCC_MULTIREG_RETVALS__ + /* + * gcc currently does not conform to the ia-64 calling + * convention as far as returning function values are + * concerned. Instead of returning values up to 32 bytes in + * size in r8-r11, gcc returns any value bigger than a + * doubleword via a structure that's allocated by the caller + * and whose address is passed into the function. Since + * SAL_PROC returns values according to the calling + * convention, this stub takes care of copying r8-r11 to the + * place where gcc expects them. + */ .text .psr abi64 .psr lsb diff -urN linux-2.3.51/arch/ia64/kernel/semaphore.c linux-2.3.51-lia/arch/ia64/kernel/semaphore.c --- linux-2.3.51/arch/ia64/kernel/semaphore.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/semaphore.c Mon Apr 3 22:32:19 2000 @@ -310,7 +310,7 @@ do { old_count = sem->count; count = old_count - RW_LOCK_BIAS; - } while (cmpxchg(&sem->count, old_count, count) != old_count); + } while (cmpxchg_acq(&sem->count, old_count, count) != old_count); if (count == 0) return; diff -urN linux-2.3.51/arch/ia64/kernel/setup.c linux-2.3.51-lia/arch/ia64/kernel/setup.c --- linux-2.3.51/arch/ia64/kernel/setup.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/setup.c Tue Apr 4 19:05:32 2000 @@ -8,10 +8,12 @@ * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond * - * 02/04/00 D.Mosberger some more get_cpuinfo fixes... - * 02/01/00 R.Seth fixed get_cpuinfo for SMP - * 01/07/99 S.Eranian added the support for command line argument - * 06/24/99 W.Drummond added boot_cpu_data. + * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map + * 03/31/00 R.Seth cpu_initialized and current->processor fixes + * 02/04/00 D.Mosberger some more get_cpuinfo fixes... + * 02/01/00 R.Seth fixed get_cpuinfo for SMP + * 01/07/99 S.Eranian added the support for command line argument + * 06/24/99 W.Drummond added boot_cpu_data. */ #include #include @@ -32,6 +34,7 @@ #include #include #include +#include extern char _end; @@ -41,7 +44,7 @@ unsigned long ia64_cycles_per_usec; struct ia64_boot_param ia64_boot_param; struct screen_info screen_info; -unsigned long cpu_initialized = 0; +volatile unsigned long cpu_online_map; /* This tells _start which CPU is booting. */ int cpu_now_booting = 0; @@ -101,7 +104,6 @@ setup_arch (char **cmdline_p) { unsigned long max_pfn, bootmap_start, bootmap_size; - u64 progress; /* * The secondary bootstrap loader passes us the boot @@ -147,7 +149,10 @@ printk("args to kernel: %s\n", *cmdline_p); -#ifndef CONFIG_SMP +#ifdef CONFIG_SMP + bootstrap_processor = hard_smp_processor_id(); + current->processor = bootstrap_processor; +#else cpu_init(); identify_cpu(&cpu_data[0]); #endif @@ -168,6 +173,11 @@ conswitchp = &dummy_con; # endif #endif + +#ifdef CONFIG_IA64_MCA + /* enable IA-64 Machine Check Abort Handling */ + ia64_mca_init(); +#endif paging_init(); platform_setup(cmdline_p); } @@ -183,7 +193,7 @@ unsigned long mask; for (c = cpu_data; c < cpu_data + NR_CPUS; ++c) { - if (!(cpu_initialized & (1UL << (c - cpu_data)))) + if (!(cpu_online_map & (1UL << (c - cpu_data)))) continue; mask = c->features; @@ -209,7 +219,7 @@ if (mask) sprintf(cp, " 0x%lx", mask); - p += sprintf(buffer, + p += sprintf(p, "CPU# %lu\n" "\tvendor : %s\n" "\tfamily : %s\n" @@ -303,8 +313,6 @@ void cpu_init (void) { - int nr = smp_processor_id(); - /* Clear the stack memory reserved for pt_regs: */ memset(ia64_task_regs(current), 0, sizeof(struct pt_regs)); @@ -318,11 +326,6 @@ */ ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_PP); ia64_set_fpu_owner(0); /* initialize ar.k5 */ - - if (test_and_set_bit(nr, &cpu_initialized)) { - printk("CPU#%d already initialized!\n", nr); - machine_halt(); - } atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; } diff -urN linux-2.3.51/arch/ia64/kernel/signal.c linux-2.3.51-lia/arch/ia64/kernel/signal.c --- linux-2.3.51/arch/ia64/kernel/signal.c Tue Feb 8 12:01:59 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/signal.c Fri Apr 7 19:11:21 2000 @@ -94,7 +94,7 @@ restore_sigcontext (struct sigcontext *sc, struct pt_regs *pt) { struct switch_stack *sw = (struct switch_stack *) pt - 1; - unsigned long ip, flags, nat, um; + unsigned long ip, flags, nat, um, cfm; long err; /* restore scratch that always needs gets updated during signal delivery: */ @@ -102,20 +102,24 @@ err |= __get_user(nat, &sc->sc_nat); err |= __get_user(ip, &sc->sc_ip); /* instruction pointer */ - err |= __get_user(pt->ar_fpsr, &sc->sc_ar_fpsr); - err |= __get_user(pt->ar_pfs, &sc->sc_ar_pfs); + err |= __get_user(cfm, &sc->sc_cfm); err |= __get_user(um, &sc->sc_um); /* user mask */ err |= __get_user(pt->ar_rsc, &sc->sc_ar_rsc); err |= __get_user(pt->ar_ccv, &sc->sc_ar_ccv); err |= __get_user(pt->ar_unat, &sc->sc_ar_unat); + err |= __get_user(pt->ar_fpsr, &sc->sc_ar_fpsr); + err |= __get_user(pt->ar_pfs, &sc->sc_ar_pfs); err |= __get_user(pt->pr, &sc->sc_pr); /* predicates */ err |= __get_user(pt->b0, &sc->sc_br[0]); /* b0 (rp) */ - err |= __get_user(pt->b6, &sc->sc_br[6]); + err |= __get_user(pt->b6, &sc->sc_br[6]); /* b6 */ + err |= __get_user(pt->b7, &sc->sc_br[7]); /* b7 */ err |= __copy_from_user(&pt->r1, &sc->sc_gr[1], 3*8); /* r1-r3 */ err |= __copy_from_user(&pt->r8, &sc->sc_gr[8], 4*8); /* r8-r11 */ err |= __copy_from_user(&pt->r12, &sc->sc_gr[12], 4*8); /* r12-r15 */ err |= __copy_from_user(&pt->r16, &sc->sc_gr[16], 16*8); /* r16-r31 */ + pt->cr_ifs = cfm | (1UL << 63); + /* establish new instruction pointer: */ pt->cr_iip = ip & ~0x3UL; ia64_psr(pt)->ri = ip & 0x3; @@ -240,6 +244,7 @@ nat = ia64_get_nat_bits(pt, sw); err = __put_user(flags, &sc->sc_flags); + err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); err |= __put_user(pt->cr_ipsr & IA64_PSR_UM, &sc->sc_um); @@ -255,8 +260,8 @@ err |= __copy_to_user(&sc->sc_gr[1], &pt->r1, 3*8); /* r1-r3 */ err |= __copy_to_user(&sc->sc_gr[8], &pt->r8, 4*8); /* r8-r11 */ - err |= __copy_to_user(&sc->sc_gr[12], &pt->r12, 4*8); /* r12-r15 */ - err |= __copy_to_user(&sc->sc_gr[16], &pt->r16, 16*8); /* r16-r31 */ + err |= __copy_to_user(&sc->sc_gr[12], &pt->r12, 4*8); /* r12-r15 */ + err |= __copy_to_user(&sc->sc_gr[16], &pt->r16, 16*8); /* r16-r31 */ err |= __put_user(pt->cr_iip + ia64_psr(pt)->ri, &sc->sc_ip); err |= __put_user(pt->r12, &sc->sc_gr[12]); /* r12 */ diff -urN linux-2.3.51/arch/ia64/kernel/smp.c linux-2.3.51-lia/arch/ia64/kernel/smp.c --- linux-2.3.51/arch/ia64/kernel/smp.c Sun Feb 13 10:30:38 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/smp.c Tue Apr 4 08:17:39 2000 @@ -6,6 +6,8 @@ * * Lots of stuff stolen from arch/alpha/kernel/smp.c * + * 00/03/31 Rohit Seth Fixes for Bootstrap Processor & cpu_online_map + * now gets done here (instead of setup.c) * 99/10/05 davidm Update to bring it in sync with new command-line processing scheme. */ #define __KERNEL_SYSCALLS__ @@ -24,15 +26,6 @@ #include #include #include - -#ifdef CONFIG_KDB -#include -void smp_kdb_interrupt (struct pt_regs* regs); -void kdb_global(int cpuid); -extern unsigned long smp_kdb_wait; -extern int kdb_new_cpu; -#endif - #include #include #include @@ -47,25 +40,21 @@ extern int cpu_idle(void * unused); extern void _start(void); -extern int cpu_now_booting; /* Used by head.S to find idle task */ -extern unsigned long cpu_initialized; /* Bitmap of available cpu's */ -extern struct cpuinfo_ia64 cpu_data[NR_CPUS]; /* Duh... */ +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 */ +extern struct cpuinfo_ia64 cpu_data[NR_CPUS]; /* Duh... */ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; -#ifdef CONFIG_KDB -unsigned long cpu_online_map = 1; -#endif - volatile int __cpu_number_map[NR_CPUS] = { -1, }; /* SAPIC ID -> Logical ID */ volatile int __cpu_logical_map[NR_CPUS] = { -1, }; /* logical ID -> SAPIC ID */ int smp_num_cpus = 1; -int bootstrap_processor = -1; /* SAPIC ID of BSP */ -int smp_threads_ready = 0; /* Set when the idlers are all forked */ +int bootstrap_processor = -1; /* SAPIC ID of BSP */ +int smp_threads_ready = 0; /* Set when the idlers are all forked */ unsigned long ipi_base_addr = IPI_DEFAULT_BASE_ADDR; /* Base addr of IPI table */ cycles_t cacheflush_time = 0; -unsigned long ap_wakeup_vector = -1; /* External Int to use to wakeup AP's */ -static int max_cpus = -1; /* Command line */ +unsigned long ap_wakeup_vector = -1; /* External Int to use to wakeup AP's */ +static int max_cpus = -1; /* Command line */ static unsigned long ipi_op[NR_CPUS]; struct smp_call_struct { void (*func) (void *info); @@ -76,10 +65,6 @@ }; static struct smp_call_struct *smp_call_function_data; -#ifdef CONFIG_KDB -unsigned long smp_kdb_wait = 0; /* Bitmask of waiters */ -#endif - #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC extern spinlock_t ivr_read_lock; #endif @@ -89,7 +74,6 @@ #define IPI_RESCHEDULE 0 #define IPI_CALL_FUNC 1 #define IPI_CPU_STOP 2 -#define IPI_KDB_INTERRUPT 4 /* * Setup routine for controlling SMP activation @@ -124,7 +108,7 @@ void halt_processor(void) { - clear_bit(smp_processor_id(), &cpu_initialized); + clear_bit(smp_processor_id(), &cpu_online_map); max_xtp(); __cli(); for (;;) @@ -188,12 +172,6 @@ halt_processor(); break; -#ifdef CONFIG_KDB - case IPI_KDB_INTERRUPT: - smp_kdb_interrupt(regs); - break; -#endif - default: printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which); break; @@ -204,7 +182,7 @@ } } -static inline void +inline void send_IPI(int dest_cpu, unsigned char vector) { unsigned long ipi_addr; @@ -214,8 +192,8 @@ #endif ipi_data = vector; - ipi_addr = ipi_base_addr | ((dest_cpu << 8) << 4); /* 16-bit SAPIC ID's; assume CPU bus 0 */ - mb(); + /* 16-bit SAPIC ID's; assume CPU bus 0 */ + ipi_addr = ipi_base_addr | ((dest_cpu << 8) << 4); #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC /* @@ -492,6 +470,10 @@ smp_store_cpu_info(smp_processor_id()); smp_setup_percpu_timer(smp_processor_id()); + if (test_and_set_bit(smp_processor_id(), &cpu_online_map)) { + printk("CPU#%d already initialized!\n", smp_processor_id()); + machine_halt(); + } while (!smp_threads_ready) mb(); @@ -575,9 +557,9 @@ * is waiting for smp_threads_ready to be 1 and we can move on. */ for (timeout = 0; timeout < 100000; timeout++) { - if (test_bit(cpuid, &cpu_initialized)) + if (test_bit(cpuid, &cpu_online_map)) goto alive; - udelay(10); + udelay(100); barrier(); } @@ -587,10 +569,6 @@ alive: /* Remember the AP data */ __cpu_number_map[cpuid] = cpunum; -#ifdef CONFIG_KDB - cpu_online_map |= (1< */ #include + #include -#include #include #include #include +#include #include #include @@ -145,9 +146,14 @@ */ write_lock(&xtime_lock); while (1) { - /* do kernel PC profiling here. */ + /* + * Do kernel PC profiling here. We multiply the + * instruction number by four so that we can use a + * prof_shift of 2 to get instruction-level instead of + * just bundle-level accuracy. + */ if (!user_mode(regs)) - do_profile(regs->cr_iip); + do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri); #ifdef CONFIG_SMP smp_do_timer(regs); @@ -303,8 +309,6 @@ time_init (void) { /* we can't do request_irq() here because the kmalloc() would fail... */ - irq_desc[TIMER_IRQ].status = IRQ_DISABLED; - irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal; setup_irq(TIMER_IRQ, &timer_irqaction); efi_gettimeofday(&xtime); diff -urN linux-2.3.51/arch/ia64/kernel/traps.c linux-2.3.51-lia/arch/ia64/kernel/traps.c --- linux-2.3.51/arch/ia64/kernel/traps.c Fri Mar 17 16:03:27 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/traps.c Mon Apr 10 21:25:41 2000 @@ -32,10 +32,7 @@ #include #include -#ifdef CONFIG_KDB -# include -#endif - +#include #include #include @@ -88,13 +85,6 @@ printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err); -#ifdef CONFIG_KDB - while (1) { - kdb(KDB_REASON_PANIC, 0, regs); - printk("Cant go anywhere from Panic!\n"); - } -#endif - show_regs(regs); if (current->thread.flags & IA64_KERNEL_DEATH) { @@ -479,12 +469,18 @@ break; case 45: - printk("Unexpected IA-32 exception\n"); +#ifdef CONFIG_IA32_SUPPORT + if (ia32_exception(regs, isr) == 0) + return; +#endif + printk("Unexpected IA-32 exception (Trap 45)\n"); + printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr); force_sig(SIGSEGV, current); - return; + break; case 46: - printk("Unexpected IA-32 intercept trap\n"); + printk("Unexpected IA-32 intercept trap (Trap 46)\n"); + printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr); force_sig(SIGSEGV, current); return; diff -urN linux-2.3.51/arch/ia64/kernel/unaligned.c linux-2.3.51-lia/arch/ia64/kernel/unaligned.c --- linux-2.3.51/arch/ia64/kernel/unaligned.c Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/arch/ia64/kernel/unaligned.c Tue Mar 28 15:27:41 2000 @@ -305,7 +305,7 @@ DPRINT(("rnat @%p = 0x%lx nat=%d rnatval=%lx\n", addr, rnats, nat, rnats &ia64_rse_slot_num(slot))); - if ( nat ) { + if (nat) { rnats |= __IA64_UL(1) << ia64_rse_slot_num(slot); } else { rnats &= ~(__IA64_UL(1) << ia64_rse_slot_num(slot)); @@ -385,7 +385,8 @@ ia64_peek(regs, current, (unsigned long)addr, &rnats); DPRINT(("rnat @%p = 0x%lx\n", addr, rnats)); - if ( nat ) *nat = rnats >> ia64_rse_slot_num(slot) & 0x1; + if (nat) + *nat = rnats >> ia64_rse_slot_num(slot) & 0x1; } @@ -401,7 +402,7 @@ /* * First takes care of stacked registers */ - if ( regnum >= IA64_FIRST_STACKED_GR ) { + if (regnum >= IA64_FIRST_STACKED_GR) { set_rse_reg(regs, regnum, val, nat); return; } @@ -414,7 +415,7 @@ /* * Now look at registers in [0-31] range and init correct UNAT */ - if ( GR_IN_SW(regnum) ) { + if (GR_IN_SW(regnum)) { addr = (unsigned long)sw; unat = &sw->ar_unat; } else { @@ -437,7 +438,7 @@ */ bitmask = __IA64_UL(1) << (addr >> 3 & 0x3f); DPRINT(("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, unat, *unat)); - if ( nat ) { + if (nat) { *unat |= bitmask; } else { *unat &= ~bitmask; @@ -465,7 +466,7 @@ * fly to store to the right register. * For now, we are using the (slow) save/restore way. */ - if ( regnum >= IA64_FIRST_ROTATING_FR ) { + if (regnum >= IA64_FIRST_ROTATING_FR) { /* * force a save of [32-127] to tss * we use the __() form to avoid fiddling with the dfh bit @@ -489,7 +490,7 @@ /* * pt_regs or switch_stack ? */ - if ( FR_IN_SW(regnum) ) { + if (FR_IN_SW(regnum)) { addr = (unsigned long)sw; } else { addr = (unsigned long)regs; @@ -542,7 +543,7 @@ * we need to force a save to the tss to get access to it. * See discussion in setfpreg() for reasons and other ways of doing this. */ - if ( regnum >= IA64_FIRST_ROTATING_FR ) { + if (regnum >= IA64_FIRST_ROTATING_FR) { /* * force a save of [32-127] to tss @@ -587,7 +588,7 @@ struct switch_stack *sw = (struct switch_stack *)regs -1; unsigned long addr, *unat; - if ( regnum >= IA64_FIRST_STACKED_GR ) { + if (regnum >= IA64_FIRST_STACKED_GR) { get_rse_reg(regs, regnum, val, nat); return; } @@ -595,7 +596,7 @@ /* * take care of r0 (read-only always evaluate to 0) */ - if ( regnum == 0 ) { + if (regnum == 0) { *val = 0; *nat = 0; return; @@ -604,7 +605,7 @@ /* * Now look at registers in [0-31] range and init correct UNAT */ - if ( GR_IN_SW(regnum) ) { + if (GR_IN_SW(regnum)) { addr = (unsigned long)sw; unat = &sw->ar_unat; } else { @@ -621,7 +622,8 @@ /* * do it only when requested */ - if ( nat ) *nat = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL; + if (nat) + *nat = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL; } static void @@ -633,7 +635,7 @@ * not get to this point in the code but we keep this sanity check, * just in case. */ - if ( ld->x6_op == 1 || ld->x6_op == 3 ) { + if (ld->x6_op == 1 || ld->x6_op == 3) { printk(KERN_ERR __FUNCTION__": register update on speculative load, error\n"); die_if_kernel("unaligned reference on specualtive load with register update\n", regs, 30); @@ -644,7 +646,7 @@ * at this point, we know that the base register to update is valid i.e., * it's not r0 */ - if ( type == UPD_IMMEDIATE ) { + if (type == UPD_IMMEDIATE) { unsigned long imm; /* @@ -670,7 +672,7 @@ DPRINT(("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld->x, ld->m, imm, ifa)); - } else if ( ld->m ) { + } else if (ld->m) { unsigned long r2; int nat_r2; @@ -719,7 +721,7 @@ * * Note: the first argument is ignored */ - if ( access_ok(VERIFY_READ, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_READ, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n", ifa)); return -1; } @@ -737,7 +739,7 @@ * invalidate the ALAT entry. * See comment below for explanation on how we handle ldX.a */ - if ( ld->x6_op != 0x2 ) { + if (ld->x6_op != 0x2) { /* * we rely on the macros in unaligned.h for now i.e., * we let the compiler figure out how to read memory gracefully. @@ -767,9 +769,8 @@ /* * check for updates on any kind of loads */ - if ( ld->op == 0x5 || ld->m ) - emulate_load_updates(ld->op == 0x5 ? UPD_IMMEDIATE: UPD_REG, - ld, regs, ifa); + if (ld->op == 0x5 || ld->m) + emulate_load_updates(ld->op == 0x5 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); /* * handling of various loads (based on EAS2.4): @@ -882,7 +883,7 @@ * * Note: the first argument is ignored */ - if ( access_ok(VERIFY_WRITE, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_WRITE, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n",ifa)); return -1; } @@ -926,7 +927,7 @@ * ld->r3 can never be r0, because r0 would not generate an * unaligned access. */ - if ( ld->op == 0x5 ) { + if (ld->op == 0x5) { unsigned long imm; /* @@ -936,7 +937,7 @@ /* * sign extend (8bits) if m set */ - if ( ld->m ) imm |= SIGN_EXT9; + if (ld->m) imm |= SIGN_EXT9; /* * ifa == r3 (NaT is necessarily cleared) */ @@ -955,7 +956,8 @@ /* * stX.rel: use fence instead of release */ - if ( ld->x6_op == 0xd ) mb(); + if (ld->x6_op == 0xd) + mb(); return 0; } @@ -1033,7 +1035,7 @@ struct ia64_fpreg fpr_final[2]; unsigned long len = float_fsz[ld->x6_sz]; - if ( access_ok(VERIFY_READ, (void *)ifa, len<<1) < 0 ) { + if (access_ok(VERIFY_READ, (void *)ifa, len<<1) < 0) { DPRINT(("verify area failed on %lx\n", ifa)); return -1; } @@ -1055,7 +1057,7 @@ * ldfpX.a: we don't try to emulate anything but we must * invalidate the ALAT entry and execute updates, if any. */ - if ( ld->x6_op != 0x2 ) { + if (ld->x6_op != 0x2) { /* * does the unaligned access */ @@ -1118,7 +1120,7 @@ * Check for updates: only immediate updates are available for this * instruction. */ - if ( ld->m ) { + if (ld->m) { /* * the immediate is implicit given the ldsz of the operation: @@ -1132,8 +1134,9 @@ * as long as we don't come here with a ldfpX.s. * For this reason we keep this sanity check */ - if ( ld->x6_op == 1 || ld->x6_op == 3 ) { - printk(KERN_ERR "%s: register update on speculative load pair, error\n", __FUNCTION__); + if (ld->x6_op == 1 || ld->x6_op == 3) { + printk(KERN_ERR "%s: register update on speculative load pair, error\n", + __FUNCTION__); } @@ -1143,7 +1146,7 @@ /* * Invalidate ALAT entries, if any, for both registers. */ - if ( ld->x6_op == 0x2 ) { + if (ld->x6_op == 0x2) { invala_fr(ld->r1); invala_fr(ld->imm); } @@ -1160,10 +1163,10 @@ /* * check for load pair because our masking scheme is not fine grain enough - if ( ld->x == 1 ) return emulate_load_floatpair(ifa,ld,regs); + if (ld->x == 1) return emulate_load_floatpair(ifa,ld,regs); */ - if ( access_ok(VERIFY_READ, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_READ, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n", ifa)); return -1; } @@ -1187,7 +1190,7 @@ * invalidate the ALAT entry. * See comments in ldX for descriptions on how the various loads are handled. */ - if ( ld->x6_op != 0x2 ) { + if (ld->x6_op != 0x2) { /* * does the unaligned access @@ -1243,7 +1246,7 @@ /* * check for updates on any loads */ - if ( ld->op == 0x7 || ld->m ) + if (ld->op == 0x7 || ld->m) emulate_load_updates(ld->op == 0x7 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); @@ -1274,7 +1277,7 @@ * * Note: the first argument is ignored */ - if ( access_ok(VERIFY_WRITE, (void *)ifa, len) < 0 ) { + if (access_ok(VERIFY_WRITE, (void *)ifa, len) < 0) { DPRINT(("verify area failed on %lx\n",ifa)); return -1; } @@ -1342,7 +1345,7 @@ * ld->r3 can never be r0, because r0 would not generate an * unaligned access. */ - if ( ld->op == 0x7 ) { + if (ld->op == 0x7) { unsigned long imm; /* @@ -1352,7 +1355,8 @@ /* * sign extend (8bits) if m set */ - if ( ld->m ) imm |= SIGN_EXT9; + if (ld->m) + imm |= SIGN_EXT9; /* * ifa == r3 (NaT is necessarily cleared) */ @@ -1384,6 +1388,28 @@ load_store_t *insn; int ret = -1; + /* + * Unaligned references in the kernel could come from unaligned + * arguments to system calls. We fault the user process in + * these cases and panic the kernel otherwise (the kernel should + * be fixed to not make unaligned accesses). + */ + if (!user_mode(regs)) { + const struct exception_table_entry *fix; + + fix = search_exception_table(regs->cr_iip); + if (fix) { + regs->r8 = -EFAULT; + if (fix->skip & 1) { + regs->r9 = 0; + } + regs->cr_iip += ((long) fix->skip) & ~15; + regs->cr_ipsr &= ~IA64_PSR_RI; /* clear exception slot number */ + return; + } + die_if_kernel("Unaligned reference while in kernel\n", regs, 30); + /* NOT_REACHED */ + } if (current->thread.flags & IA64_THREAD_UAC_SIGBUS) { struct siginfo si; @@ -1539,7 +1565,7 @@ } DPRINT(("ret=%d\n", ret)); - if ( ret ) { + if (ret) { lock_kernel(); force_sig(SIGSEGV, current); unlock_kernel(); @@ -1549,7 +1575,8 @@ * because a memory access instruction (M) can never be in the * last slot of a bundle. But let's keep it for now. */ - if ( ipsr->ri == 2 ) regs->cr_iip += 16; + if (ipsr->ri == 2) + regs->cr_iip += 16; ipsr->ri = ++ipsr->ri & 3; } diff -urN linux-2.3.51/arch/ia64/lib/strlen.S linux-2.3.51-lia/arch/ia64/lib/strlen.S --- linux-2.3.51/arch/ia64/lib/strlen.S Wed Feb 9 19:45:43 2000 +++ linux-2.3.51-lia/arch/ia64/lib/strlen.S Tue Mar 28 15:47:39 2000 @@ -186,6 +186,7 @@ ;; cmp.eq p6,p0=8,val1 // val1==8 ? (p6) br.wtop.dptk.few 2b // loop until p6 == 0 + ;; // (avoid WAW on p63) sub ret0=base,orig // distance from base sub tmp=8,val1 mov pr=saved_pr,0xffffffffffff0000 diff -urN linux-2.3.51/arch/ia64/mm/tlb.c linux-2.3.51-lia/arch/ia64/mm/tlb.c --- linux-2.3.51/arch/ia64/mm/tlb.c Fri Mar 17 16:03:28 2000 +++ linux-2.3.51-lia/arch/ia64/mm/tlb.c Tue Mar 28 15:45:56 2000 @@ -138,7 +138,7 @@ */ ++nbits; if (((1UL << nbits) & SUPPORTED_PGBITS) == 0) - panic("flush_tlb_range: BUG: nbits=%lu\n", nbits); + panic("flush_tlb_range: BUG: nbits=%lu\n", nbits); } start &= ~((1UL << nbits) - 1); diff -urN linux-2.3.51/arch/ia64/tools/Makefile linux-2.3.51-lia/arch/ia64/tools/Makefile --- linux-2.3.51/arch/ia64/tools/Makefile Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/tools/Makefile Mon Mar 13 11:52:11 2000 @@ -8,6 +8,8 @@ all: +mrproper: + clean: rm -f print_offsets.s print_offsets offsets.h diff -urN linux-2.3.51/arch/ia64/tools/print_offsets.c linux-2.3.51-lia/arch/ia64/tools/print_offsets.c --- linux-2.3.51/arch/ia64/tools/print_offsets.c Sun Feb 13 10:30:38 2000 +++ linux-2.3.51-lia/arch/ia64/tools/print_offsets.c Tue Apr 4 22:32:04 2000 @@ -12,6 +12,8 @@ * file, be sure to verify that the awk procedure still works (see * prin_offsets.awk). */ +#include + #include #include @@ -50,6 +52,9 @@ { "IA64_TASK_PROCESSOR_OFFSET", offsetof (struct task_struct, processor) }, { "IA64_TASK_THREAD_OFFSET", offsetof (struct task_struct, thread) }, { "IA64_TASK_THREAD_KSP_OFFSET", offsetof (struct task_struct, thread.ksp) }, +#ifdef CONFIG_IA32_SUPPORT + { "IA64_TASK_THREAD_SIGMASK_OFFSET",offsetof (struct task_struct, thread.un.sigmask) }, +#endif { "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) }, { "IA64_TASK_MM_OFFSET", offsetof (struct task_struct, mm) }, { "IA64_PT_REGS_CR_IPSR_OFFSET", offsetof (struct pt_regs, cr_ipsr) }, @@ -63,6 +68,8 @@ { "IA64_SIGCONTEXT_FLAGS_OFFSET", offsetof (struct sigcontext, sc_flags) }, { "IA64_SIGCONTEXT_CFM_OFFSET", offsetof (struct sigcontext, sc_cfm) }, { "IA64_SIGCONTEXT_FR6_OFFSET", offsetof (struct sigcontext, sc_fr[6]) }, + { "IA64_CLONE_VFORK", CLONE_VFORK }, + { "IA64_CLONE_VM", CLONE_VM }, }; static const char *tabs = "\t\t\t\t\t\t\t\t\t\t"; diff -urN linux-2.3.51/arch/ia64/vmlinux.lds.S linux-2.3.51-lia/arch/ia64/vmlinux.lds.S --- linux-2.3.51/arch/ia64/vmlinux.lds.S Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/arch/ia64/vmlinux.lds.S Tue Mar 28 13:47:45 2000 @@ -8,7 +8,7 @@ ENTRY(_start) SECTIONS { - v = PAGE_OFFSET; /* this symbol is here to make debugging with kdb easier... */ + v = PAGE_OFFSET; /* this symbol is here to make debugging easier... */ . = KERNEL_START; @@ -38,21 +38,6 @@ __ex_table : AT(ADDR(__ex_table) - PAGE_OFFSET) { *(__ex_table) } __stop___ex_table = .; - -#if defined(CONFIG_KDB) - /* Kernel symbols and strings for kdb */ -# define KDB_MEAN_SYMBOL_SIZE 48 -# define KDB_SPACE (CONFIG_KDB_STBSIZE * KDB_MEAN_SYMBOL_SIZE) - . = ALIGN(8); - _skdb = .; - .kdb : AT(ADDR(.kdb) - PAGE_OFFSET) - { - *(kdbsymtab) - *(kdbstrings) - } - _ekdb = .; - . = _skdb + KDB_SPACE; -#endif /* Kernel symbol names for modules: */ .kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET) diff -urN linux-2.3.51/drivers/block/ide-cd.c linux-2.3.51-lia/drivers/block/ide-cd.c --- linux-2.3.51/drivers/block/ide-cd.c Thu Mar 9 23:13:06 2000 +++ linux-2.3.51-lia/drivers/block/ide-cd.c Thu Mar 9 23:13:46 2000 @@ -2312,6 +2312,7 @@ */ cdi->handle = (ide_drive_t *) drive; cdi->ops = &ide_cdrom_dops; +#ifndef CONFIG_IA64_SOFTSDV_HACKS /* MODE_SENSE unsupported by simulator */ #ifndef __ACER50__ /* we seem to get stat=0x01,err=0x00 the first time (??) */ do { @@ -2323,6 +2324,7 @@ if (ide_cdrom_get_capabilities(cdi,&buf)) return 0; #endif /* __ACER50__ */ +#endif /* CONFIG_IA64_SOFTSDV_HACKS */ if (buf.cap.lock == 0) CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; diff -urN linux-2.3.51/drivers/char/Config.in linux-2.3.51-lia/drivers/char/Config.in --- linux-2.3.51/drivers/char/Config.in Fri Mar 17 16:03:29 2000 +++ linux-2.3.51-lia/drivers/char/Config.in Fri Mar 17 16:04:46 2000 @@ -16,6 +16,11 @@ tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL fi fi + +if [ "$CONFIG_SERIAL" = "n" ]; then + bool 'Simulated serial driver support' CONFIG_SIM_SERIAL +fi + bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS diff -urN linux-2.3.51/drivers/char/Makefile linux-2.3.51-lia/drivers/char/Makefile --- linux-2.3.51/drivers/char/Makefile Thu Mar 9 23:13:06 2000 +++ linux-2.3.51-lia/drivers/char/Makefile Thu Mar 9 23:13:46 2000 @@ -111,6 +111,7 @@ endif endif +obj-$(CONFIG_SIM_SERIAL) += simserial.o obj-$(CONFIG_ROCKETPORT) += rocket.o obj-$(CONFIG_MOXA_SMARTIO) += mxser.o obj-$(CONFIG_MOXA_INTELLIO) += moxa.o diff -urN linux-2.3.51/drivers/char/efirtc.c linux-2.3.51-lia/drivers/char/efirtc.c --- linux-2.3.51/drivers/char/efirtc.c Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/drivers/char/efirtc.c Tue Apr 4 07:14:18 2000 @@ -39,7 +39,7 @@ #include #include -#define EFI_RTC_VERSION "0.1" +#define EFI_RTC_VERSION "0.2" #define EFI_ISDST (EFI_TIME_ADJUST_DAYLIGHT|EFI_TIME_IN_DAYLIGHT) /* @@ -47,7 +47,7 @@ */ #define EFI_RTC_EPOCH 1998 -static spinlock_t efi_rtc_lock; +static spinlock_t efi_rtc_lock = SPIN_LOCK_UNLOCKED; static int efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); @@ -153,6 +153,8 @@ efi_time_t eft; efi_time_cap_t cap; struct rtc_time wtime; + struct rtc_wkalrm *ewp; + unsigned char enabled, pending; switch (cmd) { case RTC_UIE_ON: @@ -203,6 +205,50 @@ spin_unlock_irqrestore(&efi_rtc_lock,flags); return status == EFI_SUCCESS ? 0 : -EINVAL; + + case RTC_WKALM_SET: + + if (!capable(CAP_SYS_TIME)) return -EACCES; + + ewp = (struct rtc_wkalrm *)arg; + + if ( get_user(enabled, &ewp->enabled) + || copy_from_user(&wtime, &ewp->time, sizeof(struct rtc_time)) ) + return -EFAULT; + + convert_to_efi_time(&wtime, &eft); + + spin_lock_irqsave(&efi_rtc_lock, flags); + /* + * XXX Fixme: + * As of EFI 0.92 with the firmware I have on my + * machine this call does not seem to work quite + * right + */ + status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); + + spin_unlock_irqrestore(&efi_rtc_lock,flags); + + return status == EFI_SUCCESS ? 0 : -EINVAL; + + case RTC_WKALM_RD: + + spin_lock_irqsave(&efi_rtc_lock, flags); + + status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); + + spin_unlock_irqrestore(&efi_rtc_lock,flags); + + if (status != EFI_SUCCESS) return -EINVAL; + + ewp = (struct rtc_wkalrm *)arg; + + if ( put_user(enabled, &ewp->enabled) + || put_user(pending, &ewp->pending)) return -EFAULT; + + convert_from_efi_time(&eft, &wtime); + + return copy_to_user((void *)&ewp->time, &wtime, sizeof(struct rtc_time)); } return -EINVAL; } diff -urN linux-2.3.51/drivers/char/n_tty.c linux-2.3.51-lia/drivers/char/n_tty.c --- linux-2.3.51/drivers/char/n_tty.c Tue Oct 19 10:22:20 1999 +++ linux-2.3.51-lia/drivers/char/n_tty.c Fri Mar 17 10:44:14 2000 @@ -206,10 +206,10 @@ nr = space; if (nr > sizeof(buf)) nr = sizeof(buf); - nr -= copy_from_user(buf, inbuf, nr); - if (!nr) - return 0; - + + if (copy_from_user(buf, inbuf, nr)) + return -EFAULT; + for (i = 0, cp = buf; i < nr; i++, cp++) { switch (*cp) { case '\n': diff -urN linux-2.3.51/drivers/char/serial.c linux-2.3.51-lia/drivers/char/serial.c --- linux-2.3.51/drivers/char/serial.c Fri Feb 25 10:26:42 2000 +++ linux-2.3.51-lia/drivers/char/serial.c Tue Mar 28 13:43:34 2000 @@ -4786,9 +4786,6 @@ int cflag = CREAD | HUPCL | CLOCAL; int quot = 0; char *s; -#if defined(CONFIG_KDB) - extern int kdb_port; -#endif if (options) { baud = simple_strtoul(options, NULL, 10); @@ -4892,14 +4889,6 @@ if (serial_in(info, UART_LSR) == 0xff) return -1; -#if defined(CONFIG_KDB) - /* - * Remember I/O port for kdb - */ - if (kdb_port == 0 ) - kdb_port = ser->port; -#endif /* CONFIG_KDB */ - return 0; } diff -urN linux-2.3.51/drivers/char/simserial.c linux-2.3.51-lia/drivers/char/simserial.c --- linux-2.3.51/drivers/char/simserial.c Wed Dec 31 16:00:00 1969 +++ linux-2.3.51-lia/drivers/char/simserial.c Fri Apr 7 22:41:34 2000 @@ -0,0 +1,1103 @@ +/* + * Simulated Serial Driver (fake serial) + * + * This driver is mostly used for bringup purposes and will go away. + * It has a strong dependency on the system console. All outputs + * are rerouted to the same facility as the one used by printk which, in our + * case means sys_sim.c console (goes via the simulator). The code hereafter + * is completely leveraged from the serial.c driver. + * + * Copyright (C) 1999 Hewlett-Packard Co + * Copyright (C) 1999 Stephane Eranian + * Copyright (C) 2000 David Mosberger-Tang + * + * 02/04/00 D. Mosberger Merged in serial.c bug fixes in rs_close(). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_KDB +# include +#endif + +#include +#include + +#undef SIMSERIAL_DEBUG /* define this to get some debug information */ + +#define KEYBOARD_INTR 3 /* must match with simulator! */ +#define SIMSERIAL_IRQ 0xee + +#define NR_PORTS 1 /* only one port for now */ +#define SERIAL_INLINE 1 + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) + +#define SSC_GETCHAR 21 + +extern long ia64_ssc (long, long, long, long, int); +extern void ia64_ssc_connect_irq (long intr, long irq); + +static char *serial_name = "SimSerial driver"; +static char *serial_version = "0.6"; + +/* + * This has been extracted from asm/serial.h. We need one eventually but + * I don't know exactly what we're going to put in it so just fake one + * for now. + */ +#define BASE_BAUD ( 1843200 / 16 ) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + +/* + * Most of the values here are meaningless to this particular driver. + * However some values must be preserved for the code (leveraged from serial.c + * to work correctly). + * port must not be 0 + * type must not be UNKNOWN + * So I picked arbitrary (guess from where?) values instead + */ +static struct serial_state rs_table[NR_PORTS]={ + /* UART CLK PORT IRQ FLAGS */ + { 0, BASE_BAUD, 0x3F8, SIMSERIAL_IRQ, STD_COM_FLAGS,0,PORT_16550 } /* ttyS0 */ +}; + +/* + * Just for the fun of it ! + */ +static struct serial_uart_config uart_config[] = { + { "unknown", 1, 0 }, + { "8250", 1, 0 }, + { "16450", 1, 0 }, + { "16550", 1, 0 }, + { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, + { "cirrus", 1, 0 }, + { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, + { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | + UART_STARTECH }, + { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, + { 0, 0} +}; + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +static struct async_struct *IRQ_ports[NR_IRQS]; +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + +static struct console *console; + +static unsigned char *tmp_buf; +static DECLARE_MUTEX(tmp_buf_sem); + +extern struct console *console_drivers; /* from kernel/printk.c */ + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ +#ifdef SIMSERIAL_DEBUG + printk("rs_stop: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", + tty->stopped, tty->hw_stopped, tty->flow_stopped); +#endif + +} + +static void rs_start(struct tty_struct *tty) +{ +#if SIMSERIAL_DEBUG + printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n", + tty->stopped, tty->hw_stopped, tty->flow_stopped); +#endif +} + +static void receive_chars(struct tty_struct *tty) +{ + unsigned char ch; + static unsigned char seen_esc = 0; + + while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) { + if ( ch == 27 && seen_esc == 0 ) { + seen_esc = 1; + continue; + } else { + if ( seen_esc==1 && ch == 'O' ) { + seen_esc = 2; + continue; + } else if ( seen_esc == 2 ) { + if ( ch == 'P' ) show_state(); /* F1 key */ + if ( ch == 'Q' ) show_buffers(); /* F2 key */ +#ifdef CONFIG_KDB + if ( ch == 'S' ) KDB_ENTER(); /* F4 key */ +#endif + seen_esc = 0; + continue; + } + } + seen_esc = 0; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; + + *tty->flip.char_buf_ptr = ch; + + *tty->flip.flag_buf_ptr = 0; + + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + tty_flip_buffer_push(tty); +} + +/* + * This is the serial driver's interrupt routine for a single port + */ +static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) +{ + struct async_struct * info; + + /* + * I don't know exactly why they don't use the dev_id opaque data + * pointer instead of this extra lookup table + */ + info = IRQ_ports[irq]; + if (!info || !info->tty) { + printk("simrs_interrupt_single: info|tty=0 info=%p problem\n", info); + return; + } + /* + * pretty simple in our case, because we only get interrupts + * on inbound traffic + */ + receive_chars(info->tty); +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +#if 0 +/* + * not really used in our situation so keep them commented out for now + */ +static DECLARE_TASK_QUEUE(tq_serial); /* used to be at the top of the file */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_serial); + printk("do_serial_bh: called\n"); +} +#endif + +static void do_softint(void *private_) +{ + printk("simserial: do_softint called\n"); +} + +static void rs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (!tty || !info->xmit_buf) return; + + save_flags(flags); cli(); + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + restore_flags(flags); + return; + } + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE-1; + info->xmit_cnt++; + restore_flags(flags); +} + +static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) +{ + int count; + unsigned long flags; + + save_flags(flags); cli(); + + if (info->x_char) { + char c = info->x_char; + + console->write(console, &c, 1); + + info->state->icount.tx++; + info->x_char = 0; + + goto out; + } + + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) { +#ifdef SIMSERIAL_DEBUG + printk("transmit_chars: cnt=%d stopped=%d\n", info->xmit_cnt, info->tty->stopped); +#endif + goto out; + } + /* + * We removed the loop and try to do it in to chunks. We need + * 2 operations maximum because it's a ring buffer. + * + * First from current to tail if possible. + * Then from the beginning of the buffer until necessary + */ + + count = MIN(info->xmit_cnt, SERIAL_XMIT_SIZE - info->xmit_tail); + console->write(console, info->xmit_buf+info->xmit_tail, count); + + info->xmit_cnt -= count; + info->xmit_tail = (info->xmit_tail+count) & (SERIAL_XMIT_SIZE-1); + + /* + * We have more at the beginning of the buffer + */ + if ( info->xmit_cnt ) { + console->write(console, info->xmit_buf, info->xmit_cnt); + info->xmit_tail += info->xmit_cnt; + info->xmit_cnt = 0; + } +out: + restore_flags(flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + transmit_chars(info, NULL); +} + + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (!tty || !info->xmit_buf || !tmp_buf) return 0; + + save_flags(flags); + if (from_user) { + down(&tmp_buf_sem); + while (1) { + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + cli(); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + while (1) { + + cli(); + + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + restore_flags(flags); + break; + } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + + restore_flags(flags); + + buf += c; + count -= c; + ret += c; + } + } + /* + * Hey, we transmit directly from here in our case + */ + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped ) { + transmit_chars(info, NULL); + } + return ret; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + int ret; + + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + save_flags(flags); cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + restore_flags(flags); + + wake_up_interruptible(&tty->write_wait); + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void rs_send_xchar(struct tty_struct *tty, char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + info->x_char = ch; + if (ch) { + /* + * I guess we could call console->write() directly but + * let's do that for now. + */ + transmit_chars(info, NULL); + } +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); + + printk("simrs_throttle called\n"); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } + printk("simrs_unthrottle called\n"); +} + +/* + * rs_break() --- routine which turns the break handling on or off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + printk("rs_ioctl: TIOCMGET called\n"); + return -EINVAL; + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + printk("rs_ioctl: TIOCMBIS/BIC/SET called\n"); + return -EINVAL; + case TIOCGSERIAL: + printk("simrs_ioctl TIOCGSERIAL called\n"); + return 0; + case TIOCSSERIAL: + printk("simrs_ioctl TIOCSSERIAL called\n"); + return 0; + case TIOCSERCONFIG: + printk("rs_ioctl: TIOCSERCONFIG called\n"); + return -EINVAL; + + case TIOCSERGETLSR: /* Get line status register */ + printk("rs_ioctl: TIOCSERGETLSR called\n"); + return -EINVAL; + + case TIOCSERGSTRUCT: + printk("rs_ioctl: TIOCSERGSTRUCT called\n"); +#if 0 + if (copy_to_user((struct async_struct *) arg, + info, sizeof(struct async_struct))) + return -EFAULT; +#endif + return 0; + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + printk("rs_ioctl: TIOCMIWAIT: called\n"); + return 0; + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + printk("rs_ioctl: TIOCGICOUNT called\n"); + return 0; + + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + unsigned int cflag = tty->termios->c_cflag; + + if ( (cflag == old_termios->c_cflag) + && ( RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_start(tty); + } +} +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct async_struct * info) +{ + unsigned long flags; + struct serial_state *state; + int retval; + + if (!(info->flags & ASYNC_INITIALIZED)) return; + + state = info->state; + +#ifdef SIMSERIAL_DEBUG + printk("Shutting down serial port %d (irq %d)....", info->line, + state->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + /* + * First unlink the serial port from the IRQ chain... + */ + if (info->next_port) + info->next_port->prev_port = info->prev_port; + if (info->prev_port) + info->prev_port->next_port = info->next_port; + else + IRQ_ports[state->irq] = info->next_port; + + /* + * Free the IRQ, if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + free_irq(state->irq, NULL); + retval = request_irq(state->irq, rs_interrupt_single, + IRQ_T(info), "serial", NULL); + + if (retval) + printk("serial shutdown: request_irq: error %d" + " Couldn't reacquire IRQ.\n", retval); + } else + free_irq(state->irq, NULL); + } + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + restore_flags(flags); +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state; + unsigned long flags; + + if (!info ) return; + + state = info->state; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { +#ifdef SIMSERIAL_DEBUG + printk("rs_close: hung_up\n"); +#endif + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } +#ifdef SIMSERIAL_DEBUG + printk("rs_close ttys%d, count = %d\n", info->line, state->count); +#endif + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("rs_close: bad serial port count; tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, state->count); + state->count = 0; + } + if (state->count) { + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + info->flags |= ASYNC_CLOSING; + restore_flags(flags); + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + shutdown(info); + if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ +} + + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_hangup(struct tty_struct *tty) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state = info->state; + +#ifdef SIMSERIAL_DEBUG + printk("rs_hangup: called\n"); +#endif + + state = info->state; + + rs_flush_buffer(tty); + if (info->flags & ASYNC_CLOSING) + return; + shutdown(info); + + info->event = 0; + state->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + + +static int get_async_struct(int line, struct async_struct **ret_info) +{ + struct async_struct *info; + struct serial_state *sstate; + + sstate = rs_table + line; + sstate->count++; + if (sstate->info) { + *ret_info = sstate->info; + return 0; + } + info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); + if (!info) { + sstate->count--; + return -ENOMEM; + } + memset(info, 0, sizeof(struct async_struct)); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->delta_msr_wait); + info->magic = SERIAL_MAGIC; + info->port = sstate->port; + info->flags = sstate->flags; + info->xmit_fifo_size = sstate->xmit_fifo_size; + info->line = line; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->state = sstate; + if (sstate->info) { + kfree_s(info, sizeof(struct async_struct)); + *ret_info = sstate->info; + return 0; + } + *ret_info = sstate->info = info; + return 0; +} + +static int +startup(struct async_struct *info) +{ + unsigned long flags; + int retval=0; + void (*handler)(int, void *, struct pt_regs *); + struct serial_state *state= info->state; + unsigned long page; + + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + + if (!state->port || !state->type) { + if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + goto errout; + } + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + +#ifdef SIMSERIAL_DEBUG + printk("startup: ttys%d (irq %d)...", info->line, state->irq); +#endif + + /* + * Allocate the IRQ if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + retval = -EBUSY; + goto errout; + } else + handler = rs_interrupt_single; + + retval = request_irq(state->irq, handler, IRQ_T(info), + "simserial", NULL); + if (retval) { + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, + &info->tty->flags); + retval = 0; + } + goto errout; + } + } + + /* + * Insert serial port into IRQ chain. + */ + info->prev_port = 0; + info->next_port = IRQ_ports[state->irq]; + if (info->next_port) + info->next_port->prev_port = info; + IRQ_ports[state->irq] = info; + + if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); + + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + +#if 0 + /* + * Set up serial timers... + */ + timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; + timer_active |= 1 << RS_TIMER; +#endif + + /* + * Set up the tty->alt_speed kludge + */ + if (info->tty) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + } + + info->flags |= ASYNC_INITIALIZED; + restore_flags(flags); + return 0; + +errout: + restore_flags(flags); + return retval; +} + + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct async_struct *info; + int retval, line; + unsigned long page; + + MOD_INC_USE_COUNT; + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + retval = get_async_struct(line, &info); + if (retval) { + MOD_DEC_USE_COUNT; + return retval; + } + tty->driver_data = info; + info->tty = tty; + +#ifdef SIMSERIAL_DEBUG + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->state->count); +#endif + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + if (!tmp_buf) { + page = get_free_page(GFP_KERNEL); + if (!page) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ + return -ENOMEM; + } + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + } + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */ + return retval; + } + + if ((info->state->count == 1) && + (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->state->normal_termios; + else + *tty->termios = info->state->callout_termios; + } + + /* + * figure out which console to use (should be one already) + */ + console = console_drivers; + while (console) { + if ((console->flags & CON_ENABLED) && console->write) break; + console = console->next; + } + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SIMSERIAL_DEBUG + printk("rs_open ttys%d successful\n", info->line); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline int line_info(char *buf, struct serial_state *state) +{ + return sprintf(buf, "%d: uart:%s port:%X irq:%d\n", + state->line, uart_config[state->type].name, + state->port, state->irq); +} + +int rs_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int i, len = 0, l; + off_t begin = 0; + + len += sprintf(page, "simserinfo:1.0 driver:%s\n", serial_version); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + l = line_info(page + len, &rs_table[i]); + len += l; + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * --------------------------------------------------------------------- + * rs_init() and friends + * + * rs_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static inline void show_serial_version(void) +{ + printk(KERN_INFO "%s version %s with", serial_name, serial_version); + printk(" no serial options enabled\n"); +} + +/* + * The serial driver boot-time initialization code! + */ +int __init +simrs_init (void) +{ + int i; + struct serial_state *state; + + show_serial_version(); + + /* connect the platform's keyboard interrupt to SIMSERIAL_IRQ */ + ia64_ssc_connect_irq(KEYBOARD_INTR, SIMSERIAL_IRQ); + + /* Initialize the tty_driver structure */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "simserial"; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = 1; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.put_char = rs_put_char; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.send_xchar = rs_send_xchar; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.break_ctl = rs_break; + serial_driver.wait_until_sent = rs_wait_until_sent; + serial_driver.read_proc = rs_read_proc; + + /* + * Let's have a little bit of fun ! + */ + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + + if (state->type == PORT_UNKNOWN) continue; + + printk(KERN_INFO "ttyS%02d at 0x%04x (irq = %d) is a %s\n", + state->line, + state->port, state->irq, + uart_config[state->type].name); + } + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register simserial driver\n"); + + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + return 0; +} diff -urN linux-2.3.51/drivers/char/tty_io.c linux-2.3.51-lia/drivers/char/tty_io.c --- linux-2.3.51/drivers/char/tty_io.c Thu Mar 9 23:13:07 2000 +++ linux-2.3.51-lia/drivers/char/tty_io.c Thu Mar 9 23:13:46 2000 @@ -2280,6 +2280,9 @@ #ifdef CONFIG_SERIAL rs_init(); #endif +#ifdef CONFIG_SIM_SERIAL + simrs_init(); +#endif #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) vme_scc_init(); #endif diff -urN linux-2.3.51/drivers/net/Config.in linux-2.3.51-lia/drivers/net/Config.in --- linux-2.3.51/drivers/net/Config.in Thu Mar 9 23:13:07 2000 +++ linux-2.3.51-lia/drivers/net/Config.in Thu Mar 9 23:13:47 2000 @@ -7,6 +7,7 @@ tristate 'Dummy net driver support' CONFIG_DUMMY tristate 'Bonding driver support' CONFIG_BONDING +tristate 'Simulated Ethernet ' CONFIG_SIMETH tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_NETLINK" = "y" ]; then diff -urN linux-2.3.51/drivers/net/Makefile linux-2.3.51-lia/drivers/net/Makefile --- linux-2.3.51/drivers/net/Makefile Thu Mar 9 23:13:07 2000 +++ linux-2.3.51-lia/drivers/net/Makefile Thu Mar 9 23:13:47 2000 @@ -203,6 +203,7 @@ obj-$(CONFIG_ES3210) += es3210.o 8390.o obj-$(CONFIG_LNE390) += lne390.o 8390.o obj-$(CONFIG_NE3210) += ne3210.o 8390.o +obj-$(CONFIG_SIMETH) += simeth.o # bsd_comp.o is *always* a module, for some documented reason # (licensing). diff -urN linux-2.3.51/drivers/net/Space.c linux-2.3.51-lia/drivers/net/Space.c --- linux-2.3.51/drivers/net/Space.c Sun Feb 27 18:45:10 2000 +++ linux-2.3.51-lia/drivers/net/Space.c Mon Mar 6 15:19:15 2000 @@ -123,6 +123,9 @@ extern int apfddi_init(struct net_device *dev); extern int skfp_probe(struct net_device *dev); +/* Simulated Ethernet */ +extern int simeth_probe(struct net_device *); + /* Fibre Channel adapters */ extern int iph5526_probe(struct net_device *dev); @@ -355,6 +358,9 @@ #endif #ifdef CONFIG_HPLANCE /* HP300 internal Ethernet */ {hplance_probe, 0}, +#endif +#ifdef CONFIG_SIMETH + {simeth_probe, 0}, #endif #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ {mvme147lance_probe, 0}, diff -urN linux-2.3.51/drivers/net/eepro100.c linux-2.3.51-lia/drivers/net/eepro100.c --- linux-2.3.51/drivers/net/eepro100.c Sat Feb 26 20:22:09 2000 +++ linux-2.3.51-lia/drivers/net/eepro100.c Mon Feb 28 18:46:02 2000 @@ -178,7 +178,16 @@ /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. Lower values use more memory, but are faster. */ +#ifdef __ia64__ +/* + * Bug: this driver may generate unaligned accesses when not copying + * an incoming packet. Setting rx_copybreak to a large value force a + * copy and prevents unaligned accesses. + */ +static int rx_copybreak = 0x10000; +#else static int rx_copybreak = 200; +#endif /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static int max_interrupt_work = 20; @@ -366,17 +375,17 @@ }; /* The Speedo3 Rx and Tx frame/buffer descriptors. */ -struct descriptor { /* A generic descriptor. */ - s32 cmd_status; /* All command and status fields. */ - u32 link; /* struct descriptor * */ +struct descriptor { /* A generic descriptor. */ + volatile s32 cmd_status; /* All command and status fields. */ + u32 link; /* struct descriptor * */ unsigned char params[0]; }; /* The Speedo3 Rx and Tx buffer descriptors. */ -struct RxFD { /* Receive frame descriptor. */ - s32 status; - u32 link; /* struct RxFD * */ - u32 rx_buf_addr; /* void * */ +struct RxFD { /* Receive frame descriptor. */ + volatile s32 status; + u32 link; /* struct RxFD * */ + u32 rx_buf_addr; /* void * */ u32 count; }; @@ -396,10 +405,10 @@ }; struct TxFD { /* Transmit frame descriptor set. */ - s32 status; - u32 link; /* void * */ + volatile s32 status; + u32 link; /* void * */ u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ - s32 count; /* # of TBD (=1), Tx start thresh., etc. */ + s32 count; /* # of TBD (=1), Tx start thresh., etc. */ /* This constitutes two "TBD" entries -- we only use one. */ u32 tx_buf_addr0; /* void *, frame to be transmitted. */ s32 tx_buf_size0; /* Length of Tx frame. */ @@ -640,9 +649,27 @@ } } if (sum != 0xBABA) +{ printk(KERN_WARNING "%s: Invalid EEPROM checksum %#4.4x, " "check settings before activating this device!\n", dev->name, sum); + + /* + * Ugly, ugly, ugly---I need this because our Lion has a + * bad checksum flash ROM with dev_addr=ff:ff:ff:ff:ff:ff. + * Don't do this at home... --davidm 99/12/22 + */ + eeprom[5] = 1 << 0; /* hardcode RJ45 connector */ + eeprom[6] = 0x701; + eeprom[7] = 0; /* no secondary interface chip */ + dev->dev_addr[0] = 0x08; + dev->dev_addr[1] = 0x22; + dev->dev_addr[2] = 0x33; + dev->dev_addr[3] = 0x44; + dev->dev_addr[4] = 0x55; + dev->dev_addr[5] = 0x6d; + +} /* Don't unregister_netdev(dev); as the EEPro may actually be usable, especially if the MAC address is set later. */ } @@ -1218,7 +1245,25 @@ { struct descriptor *last_cmd = sp->last_cmd; sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; +#if 0 last_cmd->cmd_status &= cpu_to_le32(~(CmdSuspend | CmdIntr)); +#else + /* + * Dave Miller thinks this shouldn't have to be atomic. I + * agree with him, yet we _do_ get TX timeouts if this + * isn't done atomically. Most likely, something else is + * wrong here and doing this atomically simply masks the + * real problem. Oh, well... --davidm 00/02/22 + */ + { + s32 old, new; + + do { + old = last_cmd->cmd_status; + new = old & ~(CmdSuspend | CmdIntr); + } while (cmpxchg(&last_cmd->cmd_status, old, new) != old); + } +#endif } if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) { sp->tx_full = 1; diff -urN linux-2.3.51/drivers/net/simeth.c linux-2.3.51-lia/drivers/net/simeth.c --- linux-2.3.51/drivers/net/simeth.c Wed Dec 31 16:00:00 1969 +++ linux-2.3.51-lia/drivers/net/simeth.c Tue Apr 4 09:07:06 2000 @@ -0,0 +1,611 @@ +/* + * Simulated Ethernet Driver + * + * Copyright (C) 1999-2000 Hewlett-Packard Co + * Copyright (C) 1999-2000 Stephane Eranain + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SIMETH_IRQ 0xed +#define SIMETH_RECV_MAX 10 + +/* + * Maximum possible received frame for Ethernet. + * We preallocate an sk_buff of that size to avoid costly + * memcpy for temporary buffer into sk_buff. We do basically + * what's done in other drivers, like eepro with a ring. + * The difference is, of course, that we don't have real DMA !!! + */ +#define SIMETH_FRAME_SIZE ETH_FRAME_LEN + + +#define SSC_NETDEV_PROBE 100 +#define SSC_NETDEV_SEND 101 +#define SSC_NETDEV_RECV 102 +#define SSC_NETDEV_ATTACH 103 +#define SSC_NETDEV_DETACH 104 + +#define NETWORK_INTR 8 + +/* + * This structure is need for the module version + * It hasn't been tested yet + */ +struct simeth_local { + struct net_device *next_module; + struct net_device_stats stats; + int simfd; /* descriptor in the simulator */ +}; + +static int simeth_probe1(struct net_device *dev); +static int simeth_open(struct net_device *dev); +static int simeth_close(struct net_device *dev); +static int simeth_tx(struct sk_buff *skb, struct net_device *dev); +static int simeth_rx(struct net_device *dev); +static struct net_device_stats *simeth_get_stats(struct net_device *dev); +static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static void set_multicast_list(struct net_device *dev); +static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr); + +static char *simeth_version="v0.2"; + +/* + * This variable is used to establish a mapping between the Linux/ia64 kernel + * and the host linux kernel. + * + * As of today, we support only one card, even though most of the code + * is ready for many more. The mapping is then: + * linux/ia64 -> linux/x86 + * eth0 -> eth1 + * + * In the future, we some string operations, we could easily support up + * to 10 cards (0-9). + * + * The default mapping can be changed on the kernel command line by + * specifying simeth=ethX (or whatever string you want). + */ +static char *simeth_device="eth0"; /* default host interface to use */ + + + +static volatile unsigned int card_count; /* how many cards "found" so far */ +static int simeth_debug=0; /* set to 1 to get debug information */ + +/* + * Used to catch IFF_UP & IFF_DOWN events + */ +static struct notifier_block simeth_dev_notifier = { + simeth_device_event, + 0 +}; + + +/* + * Function used when using a kernel command line option. + * + * Format: simeth=interface_name (like eth0) + */ +static int __init +simeth_setup(char *str) +{ + simeth_device = str; + return 1; +} + +__setup("simeth=", simeth_setup); + +/* + * Function used to probe for simeth devices when not installed + * as a loadable module + */ + +int __init +simeth_probe (struct net_device *dev) +{ + return simeth_probe1(dev); +} + +extern long ia64_ssc (long, long, long, long, int); +extern void ia64_ssc_connect_irq (long intr, long irq); + +static inline int +netdev_probe(char *name, unsigned char *ether) +{ + return ia64_ssc(__pa(name), __pa(ether), 0,0, SSC_NETDEV_PROBE); +} + + +static inline int +netdev_connect(int irq) +{ + /* XXX Fix me + * this does not support multiple cards + * also no return value + */ + ia64_ssc_connect_irq(NETWORK_INTR, irq); + return 0; +} + +static inline int +netdev_attach(int fd, int irq, unsigned int ipaddr) +{ + /* this puts the host interface in the right mode (start interupting) */ + return ia64_ssc(fd, ipaddr, 0,0, SSC_NETDEV_ATTACH); +} + + +static inline int +netdev_detach(int fd) +{ + /* + * inactivate the host interface (don't interrupt anymore) */ + return ia64_ssc(fd, 0,0,0, SSC_NETDEV_DETACH); +} + +static inline int +netdev_send(int fd, unsigned char *buf, unsigned int len) +{ + return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_SEND); +} + +static inline int +netdev_read(int fd, unsigned char *buf, unsigned int len) +{ + return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_RECV); +} + +/* + * Function shared with module code, so cannot be in init section + * + * So far this function "detects" only one card (test_&_set) but could + * be extended easily. + * + * Return: + * - -ENODEV is no device found + * - -ENOMEM is no more memory + * - 0 otherwise + */ +static int +simeth_probe1(struct net_device *dev) +{ + struct simeth_local *local; + int dev_was_null = 0; + int fd, i; + + /* + * XXX Fix me + * let's support just one card for now + */ + if ( test_and_set_bit(0, &card_count) ) return -ENODEV; + + /* true when coming from init_module */ + if ( dev == NULL ) { + printk("simeth: dev was null\n"); + dev = init_etherdev(0,0); + if ( dev == NULL ) return -ENOMEM; + dev_was_null = 1; + } + + /* + * check with the simulator for the device + */ + fd = netdev_probe(simeth_device, dev->dev_addr); + if ( fd == -1 ) { + /* don't leak memory */ + if (dev_was_null) kfree(dev); + return -ENODEV; + } + + + /* + * XXX Fix me + * does not support more than one card ! + */ + dev->irq = SIMETH_IRQ; + + dev->priv = kmalloc(sizeof(struct simeth_local), GFP_KERNEL); + if (dev->priv == NULL) { + if ( dev_was_null ) kfree(dev); + return -ENOMEM; + } + + /* + * attach the interrupt in the simulator, this does enable interrupts + * until a netdev_attach() is called + */ + netdev_connect(dev->irq); + + memset(dev->priv, 0, sizeof(struct simeth_local)); + + local = dev->priv; + local->simfd = fd; /* keep track of underlying file descriptor */ + local->next_module = NULL; + + dev->open = simeth_open; + dev->stop = simeth_close; + dev->hard_start_xmit = simeth_tx; + dev->get_stats = simeth_get_stats; + dev->set_multicast_list = set_multicast_list; /* no yet used */ + + /* Fill in the fields of the device structure with ethernet-generic values. */ + ether_setup(dev); + + printk("simeth: %s alpha\n", simeth_version); + printk("%s: hosteth=%s simfd=%d, HwAddr", dev->name, simeth_device, local->simfd); + for(i = 0; i < ETH_ALEN; i++) { + printk(" %2.2x", dev->dev_addr[i]); + } + printk(", IRQ %d\n", dev->irq); + +#ifdef MODULE + local->next_module = simeth_dev; + simeth_dev = dev; +#endif + /* + * XXX Fix me + * would not work with more than one device ! + */ + register_netdevice_notifier(&simeth_dev_notifier); + + return 0; +} + +/* + * actually binds the device to an interrupt vector + */ +static int +simeth_open(struct net_device *dev) +{ + if (request_irq(dev->irq, simeth_interrupt, 0, "simeth", dev)) { + printk ("simeth: unable to get IRQ %d.\n", dev->irq); + return -EAGAIN; + } + + netif_start_queue(dev); + MOD_INC_USE_COUNT; + + return 0; +} + +/* copied from lapbether.c */ +static __inline__ int dev_is_ethdev(struct net_device *dev) +{ + return ( dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5)); +} + + +/* + * Handler for IFF_UP or IFF_DOWN + * + * The reason for that is that we don't want to be interrupted when the + * interface is down. There is no way to unconnect in the simualtor. Instead + * we use this function to shutdown packet processing in the frame filter + * in the simulator. Thus no interrupts are generated + * + * + * That's also the place where we pass the IP address of this device to the + * simulator so that that we can start filtering packets for it + * + * There may be a better way of doing this, but I don't know which yet. + */ +static int +simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr) +{ + struct net_device *dev = (struct net_device *)ptr; + struct simeth_local *local; + struct in_device *in_dev; + struct in_ifaddr **ifap = NULL; + struct in_ifaddr *ifa = NULL; + int r; + + + if ( ! dev ) { + printk(KERN_WARNING "simeth_device_event dev=0\n"); + return NOTIFY_DONE; + } + + if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE; + + /* + * Check whether or not it's for an ethernet device + * + * XXX Fixme: This works only as long as we support one + * type of ethernet device. + */ + if ( !dev_is_ethdev(dev) ) return NOTIFY_DONE; + + if ((in_dev=dev->ip_ptr) != NULL) { + for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) + if (strcmp(dev->name, ifa->ifa_label) == 0) break; + } + if ( ifa == NULL ) { + printk("simeth_open: can't find device %s's ifa\n", dev->name); + return NOTIFY_DONE; + } + + printk("simeth_device_event: %s ipaddr=0x%x\n", dev->name, htonl(ifa->ifa_local)); + + /* + * XXX Fix me + * if the device was up, and we're simply reconfiguring it, not sure + * we get DOWN then UP. + */ + + local = dev->priv; + /* now do it for real */ + r = event == NETDEV_UP ? + netdev_attach(local->simfd, dev->irq, htonl(ifa->ifa_local)): + netdev_detach(local->simfd); + + printk("simeth: netdev_attach/detach: event=%s ->%d\n", event == NETDEV_UP ? "attach":"detach", r); + + return NOTIFY_DONE; +} + +static int +simeth_close(struct net_device *dev) +{ + netif_stop_queue(dev); + + free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; + + return 0; +} + +/* + * Only used for debug + */ +static void +frame_print(unsigned char *from, unsigned char *frame, int len) +{ + int i; + + printk("%s: (%d) %02x", from, len, frame[0] & 0xff); + for(i=1; i < 6; i++ ) { + printk(":%02x", frame[i] &0xff); + } + printk(" %2x", frame[6] &0xff); + for(i=7; i < 12; i++ ) { + printk(":%02x", frame[i] &0xff); + } + printk(" [%02x%02x]\n", frame[12], frame[13]); + + for(i=14; i < len; i++ ) { + printk("%02x ", frame[i] &0xff); + if ( (i%10)==0) printk("\n"); + } + printk("\n"); +} + + +/* + * Function used to transmit of frame, very last one on the path before + * going to the simulator. + */ +static int +simeth_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct simeth_local *local = (struct simeth_local *)dev->priv; + +#if 0 + /* ensure we have at least ETH_ZLEN bytes (min frame size) */ + unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + /* Where do the extra padding bytes comes from inthe skbuff ? */ +#else + /* the real driver in the host system is going to take care of that + * or maybe it's the NIC itself. + */ + unsigned int length = skb->len; +#endif + + local->stats.tx_bytes += skb->len; + local->stats.tx_packets++; + + + if (simeth_debug > 5) frame_print("simeth_tx", skb->data, length); + + netdev_send(local->simfd, skb->data, length); + + /* + * we are synchronous on write, so we don't simulate a + * trasnmit complete interrupt, thus we don't need to arm a tx + */ + + dev_kfree_skb(skb); + return 0; +} + +static inline struct sk_buff * +make_new_skb(struct net_device *dev) +{ + struct sk_buff *nskb; + + /* + * The +2 is used to make sure that the IP header is nicely + * aligned (on 4byte boundary I assume 14+2=16) + */ + nskb = dev_alloc_skb(SIMETH_FRAME_SIZE + 2); + if ( nskb == NULL ) { + printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name); + return NULL; + } + nskb->dev = dev; + + skb_reserve(nskb, 2); /* Align IP on 16 byte boundaries */ + + skb_put(nskb,SIMETH_FRAME_SIZE); + + return nskb; +} + +/* + * called from interrupt handler to process a received frame + */ +static int +simeth_rx(struct net_device *dev) +{ + struct simeth_local *local; + struct sk_buff *skb; + int len; + int rcv_count = SIMETH_RECV_MAX; + + local = (struct simeth_local *)dev->priv; + /* + * the loop concept has been borrowed from other drivers + * looks to me like it's a throttling thing to avoid pushing to many + * packets at one time into the stack. Making sure we can process them + * upstream and make forward progress overall + */ + do { + if ( (skb=make_new_skb(dev)) == NULL ) { + printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name); + local->stats.rx_dropped++; + return 0; + } + /* + * Read only one frame at a time + */ + len = netdev_read(local->simfd, skb->data, SIMETH_FRAME_SIZE); + if ( len == 0 ) { + if ( simeth_debug > 0 ) printk(KERN_WARNING "%s: count=%d netdev_read=0\n", dev->name, SIMETH_RECV_MAX-rcv_count); + break; + } +#if 0 + /* + * XXX Fix me + * Should really do a csum+copy here + */ + memcpy(skb->data, frame, len); +#endif + skb->protocol = eth_type_trans(skb, dev); + + if ( simeth_debug > 6 ) frame_print("simeth_rx", skb->data, len); + + /* + * push the packet up & trigger software interrupt + */ + netif_rx(skb); + + local->stats.rx_packets++; + local->stats.rx_bytes += len; + + } while ( --rcv_count ); + + return len; /* 0 = nothing left to read, otherwise, we can try again */ +} + +/* + * Interrupt handler (Yes, we can do it too !!!) + */ +static void +simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct net_device *dev = dev_id; + + if ( dev == NULL ) { + printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq); + return; + } + + /* + * very simple loop because we get interrupts only when receving + */ + while (simeth_rx(dev)); +} + +static struct net_device_stats * +simeth_get_stats(struct net_device *dev) +{ + struct simeth_local *local = (struct simeth_local *) dev->priv; + + return &local->stats; +} + +/* fake multicast ability */ +static void +set_multicast_list(struct net_device *dev) +{ + printk(KERN_WARNING "%s: set_multicast_list called\n", dev->name); +} + +#ifdef CONFIG_NET_FASTROUTE +static int +simeth_accept_fastpath(struct net_device *dev, struct dst_entry *dst) +{ + printk(KERN_WARNING "%s: simeth_accept_fastpath called\n", dev->name); + return -1; +} +#endif + + +#ifdef MODULE + + +static int +simeth_init(void) +{ + unsigned int cards_found = 0; + + /* iterate over probe */ + + while ( simeth_probe1(NULL) == 0 ) cards_found++; + + return cards_found ? 0 : -ENODEV; +} + + +int +init_module(void) +{ + simeth_dev = NULL; + + /* the register_netdev is done "indirectly by ether_initdev() */ + + return simeth_init(); +} + +void +cleanup_module(void) +{ + struct net_device *next; + + while ( simeth_dev ) { + + next = ((struct simeth_private *)simeth_dev->priv)->next_module; + + unregister_netdev(simeth_dev); + + kfree(simeth_dev); + + simeth_dev = next; + } + /* + * XXX fix me + * not clean wihen multiple devices + */ + unregister_netdevice_notifier(&simeth_dev_notifier); +} +#endif /* MODULE */ diff -urN linux-2.3.51/drivers/scsi/Makefile linux-2.3.51-lia/drivers/scsi/Makefile --- linux-2.3.51/drivers/scsi/Makefile Thu Feb 24 22:51:47 2000 +++ linux-2.3.51-lia/drivers/scsi/Makefile Mon Feb 28 18:46:07 2000 @@ -645,6 +645,10 @@ endif endif +ifeq ($(CONFIG_SCSI_SIM),y) +L_OBJS += simscsi.o +endif + ifeq ($(CONFIG_SCSI_EATA),y) L_OBJS += eata.o else diff -urN linux-2.3.51/drivers/scsi/hosts.c linux-2.3.51-lia/drivers/scsi/hosts.c --- linux-2.3.51/drivers/scsi/hosts.c Thu Feb 24 22:51:47 2000 +++ linux-2.3.51-lia/drivers/scsi/hosts.c Mon Feb 28 18:46:07 2000 @@ -317,6 +317,10 @@ #include "scsi_debug.h" #endif +#ifdef CONFIG_SCSI_SIM +#include "simscsi.h" +#endif + #ifdef CONFIG_SCSI_ACORNSCSI_3 #include "../acorn/scsi/acornscsi.h" #endif @@ -618,6 +622,9 @@ #endif #ifdef CONFIG_SCSI_PLUTO PLUTO, +#endif +#ifdef CONFIG_SCSI_SIM + SIMSCSI, #endif #ifdef CONFIG_ARCH_ACORN #ifdef CONFIG_SCSI_ACORNSCSI_3 diff -urN linux-2.3.51/drivers/scsi/simscsi.c linux-2.3.51-lia/drivers/scsi/simscsi.c --- linux-2.3.51/drivers/scsi/simscsi.c Wed Dec 31 16:00:00 1969 +++ linux-2.3.51-lia/drivers/scsi/simscsi.c Fri Feb 11 15:56:18 2000 @@ -0,0 +1,354 @@ +/* + * Simulated SCSI driver. + * + * Copyright (C) 1999 Hewlett-Packard Co + * Copyright (C) 1999 David Mosberger-Tang + * Copyright (C) 1999 Stephane Eranian + * + * 99/12/18 David Mosberger Added support for READ10/WRITE10 needed by linux v2.3.33 + */ +#include +#include +#include +#include +#include + +#include + +#include + +#include "scsi.h" +#include "sd.h" +#include "hosts.h" +#include "simscsi.h" + +#define DEBUG_SIMSCSI 0 + +/* Simulator system calls: */ + +#define SSC_OPEN 50 +#define SSC_CLOSE 51 +#define SSC_READ 52 +#define SSC_WRITE 53 +#define SSC_GET_COMPLETION 54 +#define SSC_WAIT_COMPLETION 55 + +#define SSC_WRITE_ACCESS 2 +#define SSC_READ_ACCESS 1 + +struct timer_list disk_timer; + +struct disk_req { + unsigned long addr; + unsigned len; +}; + +struct disk_stat { + int fd; + unsigned count; +}; + +extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr); + +static int desc[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + +static struct queue_entry { + Scsi_Cmnd *sc; +} queue[SIMSCSI_REQ_QUEUE_LEN]; + +static int rd, wr; +static atomic_t num_reqs = ATOMIC_INIT(0); + +/* base name for default disks */ +static char *simscsi_root = DEFAULT_SIMSCSI_ROOT; + +#define MAX_ROOT_LEN 128 + +/* + * used to setup a new base for disk images + * to use /foo/bar/disk[a-z] as disk images + * you have to specify simscsi=/foo/bar/disk on the command line + */ +static int __init +simscsi_setup (char *s) +{ + /* XXX Fix me we may need to strcpy() ? */ + if (strlen(s) > MAX_ROOT_LEN) { + printk("simscsi_setup: prefix too long---using default %s\n", simscsi_root); + } + simscsi_root = s; + return 1; +} + +__setup("simscsi=", simscsi_setup); + +static void +simscsi_interrupt (unsigned long val) +{ + Scsi_Cmnd *sc; + + while ((sc = queue[rd].sc) != 0) { + atomic_dec(&num_reqs); + queue[rd].sc = 0; +#if DEBUG_SIMSCSI + printk("simscsi_interrupt: done with %ld\n", sc->serial_number); +#endif + (*sc->scsi_done)(sc); + rd = (rd + 1) % SIMSCSI_REQ_QUEUE_LEN; + } +} + +int +simscsi_detect (Scsi_Host_Template *templ) +{ + templ->proc_name = "simscsi"; + init_timer(&disk_timer); + disk_timer.function = simscsi_interrupt; + return 1; /* fake one SCSI host adapter */ +} + +int +simscsi_release (struct Scsi_Host *host) +{ + return 0; /* this is easy... */ +} + +const char * +simscsi_info (struct Scsi_Host *host) +{ + return "simulated SCSI host adapter"; +} + +int +simscsi_abort (Scsi_Cmnd *cmd) +{ + printk ("simscsi_abort: unimplemented\n"); + return SCSI_ABORT_SUCCESS; +} + +int +simscsi_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) +{ + printk ("simscsi_reset: unimplemented\n"); + return SCSI_RESET_SUCCESS; +} + +int +simscsi_biosparam (Disk *disk, kdev_t n, int ip[]) +{ + int size = disk->capacity; + + ip[0] = 64; + ip[1] = 32; + ip[2] = size >> 11; + return 0; +} + +static void +simscsi_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset, unsigned long len) +{ + struct disk_stat stat; + struct disk_req req; + + req.addr = __pa(sc->request_buffer); + req.len = len; /* # of bytes to transfer */ + + if (sc->request_bufflen < req.len) + return; + + stat.fd = desc[sc->target]; +#if DEBUG_SIMSCSI + printk("simscsi_%s @ %lx (off %lx)\n", + mode == SSC_READ ? "read":"write", req.addr, offset); +#endif + ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); + ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); + + if (stat.count == req.len) { + sc->result = GOOD; + } else { + sc->result = DID_ERROR << 16; + } +} + +static void +simscsi_sg_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset) +{ + int list_len = sc->use_sg; + struct scatterlist *sl = (struct scatterlist *)sc->buffer; + struct disk_stat stat; + struct disk_req req; + + stat.fd = desc[sc->target]; + + while (list_len) { + req.addr = __pa(sl->address); + req.len = sl->length; +#if DEBUG_SIMSCSI + printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n", + mode == SSC_READ ? "read":"write", req.addr, offset, list_len, sl->length); +#endif + ia64_ssc(stat.fd, 1, __pa(&req), offset, mode); + ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION); + + /* should not happen in our case */ + if (stat.count != req.len) { + sc->result = DID_ERROR << 16; + return; + } + offset += sl->length; + sl++; + list_len--; + } + sc->result = GOOD; +} + +/* + * function handling both READ_6/WRITE_6 (non-scatter/gather mode) + * commands. + * Added 02/26/99 S.Eranian + */ +static void +simscsi_readwrite6 (Scsi_Cmnd *sc, int mode) +{ + unsigned long offset; + + offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512; + if (sc->use_sg > 0) + simscsi_sg_readwrite(sc, mode, offset); + else + simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512); +} + + +static void +simscsi_readwrite10 (Scsi_Cmnd *sc, int mode) +{ + unsigned long offset; + + offset = ( (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16) + | (sc->cmnd[4] << 8) | (sc->cmnd[5] << 0))*512; + if (sc->use_sg > 0) + simscsi_sg_readwrite(sc, mode, offset); + else + simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); +} + +int +simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) +{ + char fname[MAX_ROOT_LEN+16]; + char *buf; + +#if DEBUG_SIMSCSI + register long sp asm ("sp"); + printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n", + sc->target, sc->cmnd[0], sc->serial_number, sp, done); +#endif + + sc->result = DID_BAD_TARGET << 16; + sc->scsi_done = done; + if (sc->target <= 7 && sc->lun == 0) { + switch (sc->cmnd[0]) { + case INQUIRY: + if (sc->request_bufflen < 35) { + break; + } + sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target); + desc[sc->target] = ia64_ssc (__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, + 0, 0, SSC_OPEN); + if (desc[sc->target] < 0) { + /* disk doesn't exist... */ + break; + } + buf = sc->request_buffer; + buf[0] = 0; /* magnetic disk */ + buf[1] = 0; /* not a removable medium */ + buf[2] = 2; /* SCSI-2 compliant device */ + buf[3] = 2; /* SCSI-2 response data format */ + buf[4] = 31; /* additional length (bytes) */ + buf[5] = 0; /* reserved */ + buf[6] = 0; /* reserved */ + buf[7] = 0; /* various flags */ + memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); + sc->result = GOOD; + break; + + case TEST_UNIT_READY: + sc->result = GOOD; + break; + + case READ_6: + if (desc[sc->target] < 0 ) + break; + simscsi_readwrite6(sc, SSC_READ); + break; + + case READ_10: + if (desc[sc->target] < 0 ) + break; + simscsi_readwrite10(sc, SSC_READ); + break; + + case WRITE_6: + if (desc[sc->target] < 0) + break; + simscsi_readwrite6(sc, SSC_WRITE); + break; + + case WRITE_10: + if (desc[sc->target] < 0) + break; + simscsi_readwrite10(sc, SSC_WRITE); + break; + + + case READ_CAPACITY: + if (desc[sc->target] < 0 || sc->request_bufflen < 8) { + break; + } + buf = sc->request_buffer; + + /* pretend to be a 1GB disk (partition table contains real stuff): */ + buf[0] = 0x00; + buf[1] = 0x1f; + buf[2] = 0xff; + buf[3] = 0xff; + /* set block size of 512 bytes: */ + buf[4] = 0; + buf[5] = 0; + buf[6] = 2; + buf[7] = 0; + sc->result = GOOD; + break; + + case MODE_SENSE: + printk("MODE_SENSE\n"); + break; + + case START_STOP: + printk("START_STOP\n"); + break; + + default: + panic("simscsi: unknown SCSI command %u\n", sc->cmnd[0]); + } + } + if (sc->result == DID_BAD_TARGET) { + sc->result |= DRIVER_SENSE << 24; + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = 0x00; + } + if (atomic_read(&num_reqs) >= SIMSCSI_REQ_QUEUE_LEN) { + panic("Attempt to queue command while command is pending!!"); + } + atomic_inc(&num_reqs); + queue[wr].sc = sc; + wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN; + + if (!timer_pending(&disk_timer)) { + disk_timer.expires = jiffies + HZ/20; + add_timer(&disk_timer); + } + return 0; +} diff -urN linux-2.3.51/drivers/scsi/simscsi.h linux-2.3.51-lia/drivers/scsi/simscsi.h --- linux-2.3.51/drivers/scsi/simscsi.h Wed Dec 31 16:00:00 1969 +++ linux-2.3.51-lia/drivers/scsi/simscsi.h Fri Feb 11 12:37:36 2000 @@ -0,0 +1,39 @@ +/* + * Simulated SCSI driver. + * + * Copyright (C) 1999 Hewlett-Packard Co + * Copyright (C) 1999 David Mosberger-Tang + */ +#ifndef SIMSCSI_H +#define SIMSCSI_H + +#define SIMSCSI_REQ_QUEUE_LEN 64 + +#define DEFAULT_SIMSCSI_ROOT "/lia/sd" + +extern int simscsi_detect (Scsi_Host_Template *); +extern int simscsi_release (struct Scsi_Host *); +extern const char *simscsi_info (struct Scsi_Host *); +extern int simscsi_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int simscsi_abort (Scsi_Cmnd *); +extern int simscsi_reset (Scsi_Cmnd *, unsigned int); +extern int simscsi_biosparam (Disk *, kdev_t, int[]); + +#define SIMSCSI { \ + detect: simscsi_detect, \ + release: simscsi_release, \ + info: simscsi_info, \ + queuecommand: simscsi_queuecommand, \ + abort: simscsi_abort, \ + reset: simscsi_reset, \ + bios_param: simscsi_biosparam, \ + can_queue: SIMSCSI_REQ_QUEUE_LEN, \ + this_id: -1, \ + sg_tablesize: 32, \ + cmd_per_lun: SIMSCSI_REQ_QUEUE_LEN, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: DISABLE_CLUSTERING \ +} + +#endif /* SIMSCSI_H */ diff -urN linux-2.3.51/drivers/usb/hub.c linux-2.3.51-lia/drivers/usb/hub.c --- linux-2.3.51/drivers/usb/hub.c Fri Mar 17 16:03:31 2000 +++ linux-2.3.51-lia/drivers/usb/hub.c Fri Mar 17 16:11:43 2000 @@ -13,7 +13,7 @@ #include #include #include -#define DEBUG +#undef DEBUG #include #include diff -urN linux-2.3.51/drivers/usb/uhci.c linux-2.3.51-lia/drivers/usb/uhci.c --- linux-2.3.51/drivers/usb/uhci.c Fri Mar 17 16:03:31 2000 +++ linux-2.3.51-lia/drivers/usb/uhci.c Fri Mar 17 16:10:45 2000 @@ -33,7 +33,7 @@ #include #include #include -#define DEBUG +#undef DEBUG #include #include @@ -67,6 +67,46 @@ /* If a transfer is still active after this much time, turn off FSBR */ #define IDLE_TIMEOUT (HZ / 20) /* 50 ms */ +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC + +static struct uhci *guhci; + +void +disable_usb (void) +{ + unsigned short cmd; + unsigned int io_addr; + + if (guhci == NULL) + return; + + io_addr = guhci->io_addr; + + cmd = inw (io_addr + USBCMD); + + outw(cmd & ~ USBCMD_RS, io_addr+USBCMD); + + while ((inw (io_addr + USBSTS) & USBSTS_HCH) == 0); +} + +void +reenable_usb (void) +{ + unsigned int io_addr; + unsigned short cmd; + + if (guhci == NULL) + return; + + io_addr = guhci->io_addr; + + cmd = inw (io_addr + USBCMD); + + outw(cmd | USBCMD_RS, io_addr+USBCMD); +} + +#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */ + /* * Only the USB core should call uhci_alloc_dev and uhci_free_dev */ @@ -1963,6 +2003,11 @@ if (!uhci_start_root_hub(uhci)) { struct pm_dev *pmdev; +#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC + guhci = uhci; + printk("%s: enabling Lion USB workaround io_addr=%x\n", + __FILE__, guhci->io_addr); +#endif pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(dev), handle_pm_event); diff -urN linux-2.3.51/drivers/usb/usb-debug.c linux-2.3.51-lia/drivers/usb/usb-debug.c --- linux-2.3.51/drivers/usb/usb-debug.c Fri Mar 17 16:03:31 2000 +++ linux-2.3.51-lia/drivers/usb/usb-debug.c Fri Mar 17 16:11:34 2000 @@ -8,7 +8,7 @@ #include #include #include -#define DEBUG +#undef DEBUG #include static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint) diff -urN linux-2.3.51/fs/binfmt_elf.c linux-2.3.51-lia/fs/binfmt_elf.c --- linux-2.3.51/fs/binfmt_elf.c Thu Mar 9 23:13:09 2000 +++ linux-2.3.51-lia/fs/binfmt_elf.c Thu Mar 9 23:13:49 2000 @@ -163,7 +163,11 @@ NEW_AUX_ENT(0, AT_PHDR, load_addr + exec->e_phoff); NEW_AUX_ENT(1, AT_PHENT, sizeof (struct elf_phdr)); NEW_AUX_ENT(2, AT_PHNUM, exec->e_phnum); +#ifdef CONFIG_BINFMT_ELF32 + NEW_AUX_ENT(3, AT_PAGESZ, 4096); +#else // CONFIG_BINFMT_ELF32 NEW_AUX_ENT(3, AT_PAGESZ, ELF_EXEC_PAGESIZE); +#endif // CONFIG_BINFMT_ELF32 NEW_AUX_ENT(4, AT_BASE, interp_load_addr); NEW_AUX_ENT(5, AT_FLAGS, 0); NEW_AUX_ENT(6, AT_ENTRY, load_bias + exec->e_entry); @@ -200,6 +204,19 @@ return sp; } +#ifdef CONFIG_BINFMT_ELF32 +static unsigned long +ia32_mm_addr(unsigned long addr) +{ + struct vm_area_struct *vma; + + if ((vma = find_vma(current->mm, addr)) == NULL) + return(ELF_PAGESTART(addr)); + if (vma->vm_start > addr) + return(ELF_PAGESTART(addr)); + return(ELF_PAGEALIGN(addr)); +} +#endif // CONFIG_BINFMT_ELF32 /* This is much more generalized than the library routine read function, so we keep this separate. Technically the library read function @@ -273,14 +290,32 @@ if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) elf_type |= MAP_FIXED; +#ifdef CONFIG_BINFMT_ELF32 + set_brk(ia32_mm_addr(vaddr + load_addr), vaddr + load_addr + eppnt->p_memsz); + memset((char *) vaddr + load_addr + eppnt->p_filesz, 0, + eppnt->p_memsz - eppnt->p_filesz); + read_exec(file->f_dentry, eppnt->p_offset, + (char *)(vaddr + load_addr), eppnt->p_filesz, 0); + map_addr = vaddr + load_addr; +#else /* !CONFIG_BINFMT_ELF32 */ map_addr = do_mmap(file, load_addr + ELF_PAGESTART(vaddr), eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), elf_prot, elf_type, eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr)); - if (map_addr > -1024UL) /* Real error */ - goto out_close; +#endif /* !CONFIG_BINFMT_ELF32 */ + if (IS_ERR(map_addr)) { + printk("elf_interp:0x%lx+%lx, 0x%lx(0x%lx)\n", + (unsigned long)vaddr, (unsigned long)load_addr, + (unsigned long) eppnt->p_memsz, (unsigned long) eppnt->p_filesz); + map_addr = vaddr + load_addr; + do_brk(map_addr & PAGE_MASK, eppnt->p_filesz); + if (read_exec(file->f_dentry, eppnt->p_offset, (char *) map_addr, + eppnt->p_filesz, 0) + < 0) + goto out_close; + } if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { load_addr = map_addr - ELF_PAGESTART(vaddr); @@ -487,6 +522,17 @@ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) ibcs2_interpreter = 1; +#ifdef CONFIG_BINFMT_ELF32 +#define INTRP32 "/lib/i386/ld-linux.so.2" + if (strcmp(elf_interpreter,"/lib/ld-linux.so.2") == 0) { + kfree(elf_interpreter); + elf_interpreter=(char *)kmalloc(sizeof(INTRP32), + GFP_KERNEL); + if (!elf_interpreter) + goto out_free_file; + strcpy(elf_interpreter, INTRP32); + } +#endif /* CONFIG_BINFMT_ELF32 */ #if 0 printk("Using ELF interpreter %s\n", elf_interpreter); #endif @@ -626,11 +672,30 @@ elf_flags |= MAP_FIXED; } +#ifdef CONFIG_BINFMT_ELF32 + set_brk(ia32_mm_addr(vaddr + load_bias), vaddr + load_bias + elf_ppnt->p_memsz); + memset((char *) vaddr + load_bias + elf_ppnt->p_filesz, 0, + elf_ppnt->p_memsz - elf_ppnt->p_filesz); + read_exec(bprm->dentry, elf_ppnt->p_offset, + (char *)(vaddr + load_bias), elf_ppnt->p_filesz, 0); + error = vaddr + load_bias; +#else /* CONFIG_BINFMT_ELF32 */ error = do_mmap(file, ELF_PAGESTART(load_bias + vaddr), (elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), elf_prot, elf_flags, (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); +#endif /* CONFIG_BINFMT_ELF32 */ + if (IS_ERR(error)) { + printk("do_load:0x%lx+%lx, 0x%lx(0x%lx)\n", + (unsigned long)vaddr, (unsigned long)load_bias, + (unsigned long)elf_ppnt->p_memsz, + (unsigned long)elf_ppnt->p_filesz); + error = vaddr + load_bias; + do_brk(error & PAGE_MASK, elf_ppnt->p_filesz); + error = read_exec(bprm->dentry, elf_ppnt->p_offset, (char *) error, + elf_ppnt->p_filesz, 0); + } if (!load_addr_set) { load_addr_set = 1; diff -urN linux-2.3.51/fs/nfsd/nfsfh.c linux-2.3.51-lia/fs/nfsd/nfsfh.c --- linux-2.3.51/fs/nfsd/nfsfh.c Fri Mar 17 16:03:32 2000 +++ linux-2.3.51-lia/fs/nfsd/nfsfh.c Mon Apr 10 22:51:46 2000 @@ -370,7 +370,7 @@ /* It's a directory, or we are required to confirm the file's * location in the tree. */ - dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino); + dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,(long) ino); down(&sb->s_nfsd_free_path_sem); /* claiming the semaphore might have allowed things to get fixed up */ diff -urN linux-2.3.51/include/asm-ia64/atomic.h linux-2.3.51-lia/include/asm-ia64/atomic.h --- linux-2.3.51/include/asm-ia64/atomic.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/asm-ia64/atomic.h Mon Apr 10 21:42:26 2000 @@ -44,7 +44,7 @@ CMPXCHG_BUGCHECK(v); old = atomic_read(v); new = old + i; - } while (ia64_cmpxchg(v, old, old + i, sizeof(atomic_t)) != old); + } while (ia64_cmpxchg("acq", v, old, old + i, sizeof(atomic_t)) != old); return new; } @@ -58,7 +58,7 @@ CMPXCHG_BUGCHECK(v); old = atomic_read(v); new = old - i; - } while (ia64_cmpxchg(v, old, new, sizeof(atomic_t)) != old); + } while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old); return new; } diff -urN linux-2.3.51/include/asm-ia64/bitops.h linux-2.3.51-lia/include/asm-ia64/bitops.h --- linux-2.3.51/include/asm-ia64/bitops.h Wed Feb 9 19:45:43 2000 +++ linux-2.3.51-lia/include/asm-ia64/bitops.h Mon Apr 10 21:42:26 2000 @@ -33,7 +33,7 @@ CMPXCHG_BUGCHECK(m); old = *m; new = old | bit; - } while (cmpxchg(m, old, new) != old); + } while (cmpxchg_acq(m, old, new) != old); } extern __inline__ void @@ -49,7 +49,7 @@ CMPXCHG_BUGCHECK(m); old = *m; new = old & mask; - } while (cmpxchg(m, old, new) != old); + } while (cmpxchg_acq(m, old, new) != old); } extern __inline__ void @@ -65,7 +65,7 @@ CMPXCHG_BUGCHECK(m); old = *m; new = old ^ bit; - } while (cmpxchg(m, old, new) != old); + } while (cmpxchg_acq(m, old, new) != old); } extern __inline__ int @@ -81,7 +81,7 @@ CMPXCHG_BUGCHECK(m); old = *m; new = old | bit; - } while (cmpxchg(m, old, new) != old); + } while (cmpxchg_acq(m, old, new) != old); return (old & bit) != 0; } @@ -98,7 +98,7 @@ CMPXCHG_BUGCHECK(m); old = *m; new = old & mask; - } while (cmpxchg(m, old, new) != old); + } while (cmpxchg_acq(m, old, new) != old); return (old & ~mask) != 0; } @@ -115,7 +115,7 @@ CMPXCHG_BUGCHECK(m); old = *m; new = old ^ bit; - } while (cmpxchg(m, old, new) != old); + } while (cmpxchg_acq(m, old, new) != old); return (old & bit) != 0; } diff -urN linux-2.3.51/include/asm-ia64/cache.h linux-2.3.51-lia/include/asm-ia64/cache.h --- linux-2.3.51/include/asm-ia64/cache.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/cache.h Mon Apr 10 21:42:26 2000 @@ -1,12 +1,28 @@ #ifndef _ASM_IA64_CACHE_H #define _ASM_IA64_CACHE_H +#include + /* - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang */ /* Bytes per L1 (data) cache line. */ -#define L1_CACHE_BYTES 64 +#define LOG_L1_CACHE_BYTES 6 +#define L1_CACHE_BYTES (1 << LOG_L1_CACHE_BYTES) + +#ifdef CONFIG_SMP +# define SMP_LOG_CACHE_BYTES LOG_L1_CACHE_BYTES +# define SMP_CACHE_BYTES L1_CACHE_BYTES +#else + /* + * The "aligned" directive can only _increase_ alignment, so this is + * safe and provides an easy way to avoid wasting space on a + * uni-processor: + */ +# define SMP_LOG_CACHE_BYTES 3 +# define SMP_CACHE_BYTES (1 << 3) +#endif #endif /* _ASM_IA64_CACHE_H */ diff -urN linux-2.3.51/include/asm-ia64/current.h linux-2.3.51-lia/include/asm-ia64/current.h --- linux-2.3.51/include/asm-ia64/current.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/current.h Mon Apr 3 22:43:48 2000 @@ -2,8 +2,8 @@ #define _ASM_IA64_CURRENT_H /* - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang */ /* In kernel mode, thread pointer (r13) is used to point to the diff -urN linux-2.3.51/include/asm-ia64/hardirq.h linux-2.3.51-lia/include/asm-ia64/hardirq.h --- linux-2.3.51/include/asm-ia64/hardirq.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/asm-ia64/hardirq.h Mon Apr 10 21:42:29 2000 @@ -54,8 +54,8 @@ #include #include -extern unsigned char global_irq_holder; -extern unsigned volatile int global_irq_lock; +extern unsigned int global_irq_holder; +extern volatile unsigned int global_irq_lock; static inline int irqs_running (void) { diff -urN linux-2.3.51/include/asm-ia64/hw_irq.h linux-2.3.51-lia/include/asm-ia64/hw_irq.h --- linux-2.3.51/include/asm-ia64/hw_irq.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/asm-ia64/hw_irq.h Mon Apr 10 21:42:26 2000 @@ -11,8 +11,7 @@ #include #include - -#define NR_ISA_IRQS 16 +#include /* * 0 special @@ -57,17 +56,17 @@ extern __u8 isa_irq_to_vector_map[16]; #define isa_irq_to_vector(x) isa_irq_to_vector_map[(x)] -extern struct hw_interrupt_type irq_type_ia64_internal; /* CPU-internal interrupt controller */ +extern struct hw_interrupt_type irq_type_ia64_sapic; /* CPU-internal interrupt controller */ extern void ipi_send (int cpu, int vector, int delivery_mode); #ifdef CONFIG_SMP -extern void handle_IPI(int irq, void *dev_id, struct pt_regs *regs); +extern void send_IPI (int dest_cpu, unsigned char vector); static inline void -hw_resend_irq (struct hw_interrupt_type *h, unsigned int i) +hw_resend_irq (struct hw_interrupt_type *h, unsigned int vector) { - send_IPI_self(i); + send_IPI(smp_processor_id(), vector); } #else # define hw_resend_irq(h,i) diff -urN linux-2.3.51/include/asm-ia64/ia32.h linux-2.3.51-lia/include/asm-ia64/ia32.h --- linux-2.3.51/include/asm-ia64/ia32.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/ia32.h Mon Apr 10 22:58:26 2000 @@ -90,7 +90,7 @@ unsigned int eflags; unsigned int esp_at_signal; unsigned short ss, __ssh; - struct _fpstate_ia32 * fpstate; + unsigned int fpstate; /* really (struct _fpstate_ia32 *) */ unsigned int oldmask; unsigned int cr2; }; @@ -288,9 +288,14 @@ * IA32 floating point control registers starting values */ -#define IA32_FSR_DEFAULT 0x555500000 /* set all tag bits */ +#define IA32_FSR_DEFAULT 0x55550000 /* set all tag bits */ #define IA32_FCR_DEFAULT 0x33f /* single precision, all masks */ +#define IA32_PTRACE_GETREGS 12 +#define IA32_PTRACE_SETREGS 13 +#define IA32_PTRACE_GETFPREGS 14 +#define IA32_PTRACE_SETFPREGS 15 + #define ia32_start_thread(regs,new_ip,new_sp) do { \ set_fs(USER_DS); \ ia64_psr(regs)->cpl = 3; /* set user mode */ \ @@ -303,10 +308,11 @@ } while (0) extern void ia32_gdt_init (void); -extern long ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, +extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs); extern void ia32_init_addr_space (struct pt_regs *regs); extern int ia32_setup_arg_pages (struct linux_binprm *bprm); +extern int ia32_exception (struct pt_regs *regs, unsigned long isr); #endif /* !CONFIG_IA32_SUPPORT */ diff -urN linux-2.3.51/include/asm-ia64/ide.h linux-2.3.51-lia/include/asm-ia64/ide.h --- linux-2.3.51/include/asm-ia64/ide.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/asm-ia64/ide.h Mon Apr 10 21:47:45 2000 @@ -15,6 +15,8 @@ #include +#include + #ifndef MAX_HWIFS # ifdef CONFIG_BLK_DEV_IDEPCI #define MAX_HWIFS 10 @@ -29,12 +31,12 @@ ide_default_irq (ide_ioreg_t base) { switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - case 0x168: return 10; - case 0x1e0: return 8; - case 0x160: return 12; + case 0x1f0: return isa_irq_to_vector(14); + case 0x170: return isa_irq_to_vector(15); + case 0x1e8: return isa_irq_to_vector(11); + case 0x168: return isa_irq_to_vector(10); + case 0x1e0: return isa_irq_to_vector(8); + case 0x160: return isa_irq_to_vector(12); default: return 0; } diff -urN linux-2.3.51/include/asm-ia64/io.h linux-2.3.51-lia/include/asm-ia64/io.h --- linux-2.3.51/include/asm-ia64/io.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/io.h Mon Apr 10 21:42:26 2000 @@ -13,8 +13,8 @@ * over and over again with slight variations and possibly making a * mistake somewhere. * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang * Copyright (C) 1999 Asit Mallick * Copyright (C) 1999 Don Dugger */ @@ -253,66 +253,66 @@ /* * The address passed to these functions are ioremap()ped already. */ -extern inline unsigned long -__readb (unsigned long addr) +extern inline unsigned char +__readb (void *addr) { return *(volatile unsigned char *)addr; } -extern inline unsigned long -__readw (unsigned long addr) +extern inline unsigned short +__readw (void *addr) { return *(volatile unsigned short *)addr; } -extern inline unsigned long -__readl (unsigned long addr) +extern inline unsigned int +__readl (void *addr) { return *(volatile unsigned int *) addr; } extern inline unsigned long -__readq (unsigned long addr) +__readq (void *addr) { return *(volatile unsigned long *) addr; } extern inline void -__writeb (unsigned char val, unsigned long addr) +__writeb (unsigned char val, void *addr) { *(volatile unsigned char *) addr = val; } extern inline void -__writew (unsigned short val, unsigned long addr) +__writew (unsigned short val, void *addr) { *(volatile unsigned short *) addr = val; } extern inline void -__writel (unsigned int val, unsigned long addr) +__writel (unsigned int val, void *addr) { *(volatile unsigned int *) addr = val; } extern inline void -__writeq (unsigned long val, unsigned long addr) +__writeq (unsigned long val, void *addr) { *(volatile unsigned long *) addr = val; } -#define readb __readb -#define readw __readw -#define readl __readl -#define readq __readqq +#define readb(a) __readb((void *)(a)) +#define readw(a) __readw((void *)(a)) +#define readl(a) __readl((void *)(a)) +#define readq(a) __readqq((void *)(a)) #define __raw_readb readb #define __raw_readw readw #define __raw_readl readl #define __raw_readq readq -#define writeb __writeb -#define writew __writew -#define writel __writel -#define writeq __writeq +#define writeb(v,a) __writeb((v), (void *) (a)) +#define writew(v,a) __writew((v), (void *) (a)) +#define writel(v,a) __writel((v), (void *) (a)) +#define writeq(v,a) __writeq((v), (void *) (a)) #define __raw_writeb writeb #define __raw_writew writew #define __raw_writeq writeq diff -urN linux-2.3.51/include/asm-ia64/kdbsupport.h linux-2.3.51-lia/include/asm-ia64/kdbsupport.h --- linux-2.3.51/include/asm-ia64/kdbsupport.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/kdbsupport.h Wed Dec 31 16:00:00 1969 @@ -1,252 +0,0 @@ -#ifndef _ASM_IA64_KDBSUPPORT_H -#define _ASM_IA64_KDBSUPPORT_H - -/* - * Kernel Debugger Breakpoint Handler - * - * Copyright 1999, Silicon Graphics, Inc. - * - * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc. - */ - -#include - - /* - * This file provides definitions for functions that - * are dependent upon the product into which kdb is - * linked. - * - * This version is for linux. - */ -typedef void (*handler_t)(struct pt_regs *); -typedef unsigned long k_machreg_t; - -unsigned long show_cur_stack_frame(struct pt_regs *, int, unsigned long *) ; - -extern char* kbd_getstr(char *, size_t, char *); -extern int kdbinstalltrap(int, handler_t, handler_t*); -extern int kdbinstalldbreg(kdb_bp_t *); -extern void kdbremovedbreg(kdb_bp_t *); -extern void kdb_initbptab(void); -extern int kdbgetregcontents(const char *, struct pt_regs *, unsigned long *); -extern int kdbsetregcontents(const char *, struct pt_regs *, unsigned long); -extern int kdbdumpregs(struct pt_regs *, const char *, const char *); - -typedef int kdbintstate_t; - -extern void kdb_disableint(kdbintstate_t *); -extern void kdb_restoreint(kdbintstate_t *); - -extern k_machreg_t kdb_getpc(struct pt_regs *); -extern int kdb_setpc(struct pt_regs *, k_machreg_t); - -extern int kdb_putword(unsigned long, unsigned long); -extern int kdb_getcurrentframe(struct pt_regs *); - -/* - * kdb_db_trap is a processor dependent routine invoked - * from kdb() via the #db trap handler. It handles breakpoints involving - * the processor debug registers and handles single step traps - * using the processor trace flag. - */ - -#define KDB_DB_BPT 0 /* Straight breakpoint */ -#define KDB_DB_SS 1 /* Single Step trap */ -#define KDB_DB_SSB 2 /* Single Step, caller should continue */ - -extern int kdb_db_trap(struct pt_regs *, int); - -extern int kdb_allocdbreg(kdb_bp_t *); -extern void kdb_freedbreg(kdb_bp_t *); -extern void kdb_initdbregs(void); - -extern void kdb_setsinglestep(struct pt_regs *); - - /* - * Support for ia32 architecture debug registers. - */ -#define KDB_DBREGS 4 -extern k_machreg_t dbregs[]; - -#define DR6_BT 0x00008000 -#define DR6_BS 0x00004000 -#define DR6_BD 0x00002000 - -#define DR6_B3 0x00000008 -#define DR6_B2 0x00000004 -#define DR6_B1 0x00000002 -#define DR6_B0 0x00000001 - -#define DR7_RW_VAL(dr, drnum) \ - (((dr) >> (16 + (4 * (drnum)))) & 0x3) - -#define DR7_RW_SET(dr, drnum, rw) \ - do { \ - (dr) &= ~(0x3 << (16 + (4 * (drnum)))); \ - (dr) |= (((rw) & 0x3) << (16 + (4 * (drnum)))); \ - } while (0) - -#define DR7_RW0(dr) DR7_RW_VAL(dr, 0) -#define DR7_RW0SET(dr,rw) DR7_RW_SET(dr, 0, rw) -#define DR7_RW1(dr) DR7_RW_VAL(dr, 1) -#define DR7_RW1SET(dr,rw) DR7_RW_SET(dr, 1, rw) -#define DR7_RW2(dr) DR7_RW_VAL(dr, 2) -#define DR7_RW2SET(dr,rw) DR7_RW_SET(dr, 2, rw) -#define DR7_RW3(dr) DR7_RW_VAL(dr, 3) -#define DR7_RW3SET(dr,rw) DR7_RW_SET(dr, 3, rw) - - -#define DR7_LEN_VAL(dr, drnum) \ - (((dr) >> (18 + (4 * (drnum)))) & 0x3) - -#define DR7_LEN_SET(dr, drnum, rw) \ - do { \ - (dr) &= ~(0x3 << (18 + (4 * (drnum)))); \ - (dr) |= (((rw) & 0x3) << (18 + (4 * (drnum)))); \ - } while (0) - -#define DR7_LEN0(dr) DR7_LEN_VAL(dr, 0) -#define DR7_LEN0SET(dr,len) DR7_LEN_SET(dr, 0, len) -#define DR7_LEN1(dr) DR7_LEN_VAL(dr, 1) -#define DR7_LEN1SET(dr,len) DR7_LEN_SET(dr, 1, len) -#define DR7_LEN2(dr) DR7_LEN_VAL(dr, 2) -#define DR7_LEN2SET(dr,len) DR7_LEN_SET(dr, 2, len) -#define DR7_LEN3(dr) DR7_LEN_VAL(dr, 3) -#define DR7_LEN3SET(dr,len) DR7_LEN_SET(dr, 3, len) - -#define DR7_G0(dr) (((dr)>>1)&0x1) -#define DR7_G0SET(dr) ((dr) |= 0x2) -#define DR7_G0CLR(dr) ((dr) &= ~0x2) -#define DR7_G1(dr) (((dr)>>3)&0x1) -#define DR7_G1SET(dr) ((dr) |= 0x8) -#define DR7_G1CLR(dr) ((dr) &= ~0x8) -#define DR7_G2(dr) (((dr)>>5)&0x1) -#define DR7_G2SET(dr) ((dr) |= 0x20) -#define DR7_G2CLR(dr) ((dr) &= ~0x20) -#define DR7_G3(dr) (((dr)>>7)&0x1) -#define DR7_G3SET(dr) ((dr) |= 0x80) -#define DR7_G3CLR(dr) ((dr) &= ~0x80) - -#define DR7_L0(dr) (((dr))&0x1) -#define DR7_L0SET(dr) ((dr) |= 0x1) -#define DR7_L0CLR(dr) ((dr) &= ~0x1) -#define DR7_L1(dr) (((dr)>>2)&0x1) -#define DR7_L1SET(dr) ((dr) |= 0x4) -#define DR7_L1CLR(dr) ((dr) &= ~0x4) -#define DR7_L2(dr) (((dr)>>4)&0x1) -#define DR7_L2SET(dr) ((dr) |= 0x10) -#define DR7_L2CLR(dr) ((dr) &= ~0x10) -#define DR7_L3(dr) (((dr)>>6)&0x1) -#define DR7_L3SET(dr) ((dr) |= 0x40) -#define DR7_L3CLR(dr) ((dr) &= ~0x40) - -#define DR7_GD 0x00002000 /* General Detect Enable */ -#define DR7_GE 0x00000200 /* Global exact */ -#define DR7_LE 0x00000100 /* Local exact */ - -extern k_machreg_t kdb_getdr6(void); -extern void kdb_putdr6(k_machreg_t); - -extern k_machreg_t kdb_getdr7(void); -extern void kdb_putdr7(k_machreg_t); - -extern k_machreg_t kdb_getdr(int); -extern void kdb_putdr(int, k_machreg_t); - -extern k_machreg_t kdb_getcr(int); - -extern void kdb_bp_install(void); -extern void kdb_bp_remove(void); - -/* - * Support for setjmp/longjmp - */ -#define JB_BX 0 -#define JB_SI 1 -#define JB_DI 2 -#define JB_BP 3 -#define JB_SP 4 -#define JB_PC 5 - -typedef struct __kdb_jmp_buf { - unsigned long regs[6]; -} kdb_jmp_buf; - -extern int kdb_setjmp(kdb_jmp_buf *); -extern void kdb_longjmp(kdb_jmp_buf *, int); - -extern kdb_jmp_buf kdbjmpbuf; - -#define getprsregs(regs) ((struct switch_stack *)regs -1) - -#define BITMASK(bp,value) (value << bp) - -/* bkpt support using break inst instead of IBP reg */ - -/* - * Define certain specific instructions - */ -#define BREAK_INSTR (0x00000080100L << 11) -#define INST_SLOT0_MASK (0x1ffffffffffL << 5) - -#if 0 -#define MAX_BREAKPOINTS 40 -#define PSR_SS 40 -#endif - -/** - * IA-64 instruction format structures - */ -typedef union bundle { - struct { - long low8; - long high8; - } lform; - struct { - int low_low4; - int low_high4; - long high8; - } iform; -} bundle_t; - -#define BKPTMODE_DATAR 3 -#define BKPTMODE_IO 2 -#define BKPTMODE_DATAW 1 -#define BKPTMODE_INST 0 - -/* Some of the fault registers needed by kdb but not passed with - * regs or switch stack. - */ -typedef struct fault_regs { - unsigned long isr ; - unsigned long ifa ; - unsigned long iim ; - unsigned long itir ; -} fault_regs_t ; - -/* - * State of kdb - */ - -typedef struct kdb_state { - int cmd_given ; - int reason_for_entry ; - int bkpt_handling_state ; - int kdb_action ; -} kdb_state_t ; - -#define BKPTSTATE_NOT_HANDLED 0 -#define BKPTSTATE_HANDLED 1 - -#define CMDGIVEN_UNKNOWN 0 -#define CMDGIVEN_SSTEP 1 -#define CMDGIVEN_GO 2 - -#define ENTRYREASON_GO 0 -#define ENTRYREASON_SSTEP 1 - -#define ACTION_UNKNOWN 0 -#define ACTION_NOBPINSTALL 1 -#define ACTION_NOPROMPT 2 - -#endif /* _ASM_IA64_KDBSUPPORT_H */ diff -urN linux-2.3.51/include/asm-ia64/keyboard.h linux-2.3.51-lia/include/asm-ia64/keyboard.h --- linux-2.3.51/include/asm-ia64/keyboard.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/asm-ia64/keyboard.h Mon Apr 10 21:52:08 2000 @@ -13,6 +13,8 @@ #include +#include + #define KEYBOARD_IRQ isa_irq_to_vector(1) #define DISABLE_KBD_DURING_INTERRUPTS 0 @@ -38,9 +40,6 @@ #define INIT_KBD #define SYSRQ_KEY 0x54 -#if defined(CONFIG_KDB) -#define E1_PAUSE 119 /* PAUSE key */ -#endif /* resource allocation */ #define kbd_request_region() diff -urN linux-2.3.51/include/asm-ia64/mca.h linux-2.3.51-lia/include/asm-ia64/mca.h --- linux-2.3.51/include/asm-ia64/mca.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/mca.h Mon Apr 10 22:58:15 2000 @@ -119,7 +119,7 @@ typedef int (*prfunc_t)(const char * fmt, ...); -extern void mca_init(void); +extern void ia64_mca_init(void); extern void ia64_os_mca_dispatch(void); extern void ia64_os_mca_dispatch_end(void); extern void ia64_mca_ucmc_handler(void); @@ -134,10 +134,12 @@ #undef MCA_TEST -#if defined(MCA_TEST) -# define MCA_DEBUG printk +#define IA64_MCA_DEBUG_INFO 1 + +#if defined(IA64_MCA_DEBUG_INFO) +# define IA64_MCA_DEBUG printk #else -# define MCA_DEBUG +# define IA64_MCA_DEBUG #endif #endif /* _ASM_IA64_MCA_H */ diff -urN linux-2.3.51/include/asm-ia64/mca_asm.h linux-2.3.51-lia/include/asm-ia64/mca_asm.h --- linux-2.3.51/include/asm-ia64/mca_asm.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/mca_asm.h Tue Mar 28 15:21:25 2000 @@ -3,7 +3,9 @@ * * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander (vijay@engr.sgi.com) - * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com) + * Copyright (C) Srinivasa Thirumalachar + * Copyright (C) 2000 Hewlett-Packard Co. + * Copyright (C) 2000 David Mosberger-Tang */ #ifndef _ASM_IA64_MCA_ASM_H #define _ASM_IA64_MCA_ASM_H @@ -70,25 +72,26 @@ ;; \ dep old_psr = 0, old_psr, 32, 32; \ \ - mov ar##.##rsc = r0 ; \ + mov ar.rsc = r0 ; \ ;; \ - mov temp2 = ar##.##bspstore; \ + mov temp2 = ar.bspstore; \ ;; \ DATA_VA_TO_PA(temp2); \ ;; \ - mov temp1 = ar##.##rnat; \ + mov temp1 = ar.rnat; \ ;; \ - mov ar##.##bspstore = temp2; \ + mov ar.bspstore = temp2; \ ;; \ - mov ar##.##rnat = temp1; \ + mov ar.rnat = temp1; \ mov temp1 = psr; \ mov temp2 = psr; \ ;; \ \ dep temp2 = 0, temp2, PSR_IC, 2; \ ;; \ - mov psr##.##l = temp2; \ - \ + mov psr.l = temp2; \ + ;; \ + srlz.d; \ dep temp1 = 0, temp1, 32, 32; \ ;; \ dep temp1 = 0, temp1, PSR_IT, 1; \ @@ -100,15 +103,16 @@ dep temp1 = 0, temp1, PSR_I, 1; \ ;; \ movl temp2 = start_addr; \ - mov cr##.##ipsr = temp1; \ + mov cr.ipsr = temp1; \ ;; \ INST_VA_TO_PA(temp2); \ - mov cr##.##iip = temp2; \ - mov cr##.##ifs = r0; \ + ;; \ + mov cr.iip = temp2; \ + mov cr.ifs = r0; \ DATA_VA_TO_PA(sp) \ DATA_VA_TO_PA(gp) \ ;; \ - srlz##.##i; \ + srlz.i; \ ;; \ nop 1; \ nop 2; \ @@ -143,18 +147,19 @@ ;; \ dep temp2 = 0, temp2, PSR_IC, 2; \ ;; \ - mov psr##.##l = temp2; \ - mov ar##.##rsc = r0 ; \ + mov psr.l = temp2; \ + mov ar.rsc = r0; \ ;; \ - mov temp2 = ar##.##bspstore; \ + srlz.d; \ + mov temp2 = ar.bspstore; \ ;; \ DATA_PA_TO_VA(temp2,temp1); \ ;; \ - mov temp1 = ar##.##rnat; \ + mov temp1 = ar.rnat; \ ;; \ - mov ar##.##bspstore = temp2; \ + mov ar.bspstore = temp2; \ ;; \ - mov ar##.##rnat = temp1; \ + mov ar.rnat = temp1; \ ;; \ mov temp1 = old_psr; \ ;; \ @@ -172,12 +177,12 @@ dep temp1 = temp2, temp1, PSR_BN, 1; \ ;; \ \ - mov cr##.##ipsr = temp1; \ + mov cr.ipsr = temp1; \ movl temp2 = start_addr; \ ;; \ - mov cr##.##iip = temp2; \ + mov cr.iip = temp2; \ DATA_PA_TO_VA(sp, temp1); \ - DATA_PA_TO_VA(gp, temp1); \ + DATA_PA_TO_VA(gp, temp2); \ ;; \ nop 1; \ nop 2; \ @@ -226,19 +231,19 @@ */ #define rse_switch_context(temp,p_stackframe,p_bspstore) \ ;; \ - mov temp=ar##.##rsc;; \ + mov temp=ar.rsc;; \ st8 [p_stackframe]=temp,8;; \ - mov temp=ar##.##pfs;; \ + mov temp=ar.pfs;; \ st8 [p_stackframe]=temp,8; \ cover ;; \ - mov temp=cr##.##ifs;; \ + mov temp=cr.ifs;; \ st8 [p_stackframe]=temp,8;; \ - mov temp=ar##.##bspstore;; \ + mov temp=ar.bspstore;; \ st8 [p_stackframe]=temp,8;; \ - mov temp=ar##.##rnat;; \ + mov temp=ar.rnat;; \ st8 [p_stackframe]=temp,8; \ - mov ar##.##bspstore=p_bspstore;; \ - mov temp=ar##.##bsp;; \ + mov ar.bspstore=p_bspstore;; \ + mov temp=ar.bsp;; \ sub temp=temp,p_bspstore;; \ st8 [p_stackframe]=temp,8 @@ -262,23 +267,23 @@ add p_stackframe=rse_ndirty_offset,p_stackframe;; \ ld8 temp=[p_stackframe];; \ shl temp=temp,16;; \ - mov ar##.##rsc=temp;; \ + mov ar.rsc=temp;; \ loadrs;; \ add p_stackframe=-rse_ndirty_offset+rse_bspstore_offset,p_stackframe;;\ ld8 temp=[p_stackframe];; \ - mov ar##.##bspstore=temp;; \ + mov ar.bspstore=temp;; \ add p_stackframe=-rse_bspstore_offset+rse_rnat_offset,p_stackframe;;\ ld8 temp=[p_stackframe];; \ - mov ar##.##rnat=temp;; \ + mov ar.rnat=temp;; \ add p_stackframe=-rse_rnat_offset+rse_pfs_offset,p_stackframe;; \ ld8 temp=[p_stackframe];; \ - mov ar##.##pfs=temp; \ + mov ar.pfs=temp; \ add p_stackframe=-rse_pfs_offset+rse_ifs_offset,p_stackframe;; \ ld8 temp=[p_stackframe];; \ - mov cr##.##ifs=temp; \ + mov cr.ifs=temp; \ add p_stackframe=-rse_ifs_offset+rse_rsc_offset,p_stackframe;; \ ld8 temp=[p_stackframe];; \ - mov ar##.##rsc=temp ; \ + mov ar.rsc=temp ; \ add p_stackframe=-rse_rsc_offset,p_stackframe; \ mov temp=cr.ipsr;; \ st8 [p_stackframe]=temp,8; \ diff -urN linux-2.3.51/include/asm-ia64/offsets.h linux-2.3.51-lia/include/asm-ia64/offsets.h --- linux-2.3.51/include/asm-ia64/offsets.h Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/include/asm-ia64/offsets.h Mon Apr 10 21:35:09 2000 @@ -10,7 +10,7 @@ #define PF_PTRACED_BIT 4 -#define IA64_TASK_SIZE 2800 /* 0xaf0 */ +#define IA64_TASK_SIZE 2816 /* 0xb00 */ #define IA64_PT_REGS_SIZE 400 /* 0x190 */ #define IA64_SWITCH_STACK_SIZE 560 /* 0x230 */ #define IA64_SIGINFO_SIZE 136 /* 0x88 */ @@ -21,6 +21,7 @@ #define IA64_TASK_PROCESSOR_OFFSET 108 /* 0x6c */ #define IA64_TASK_THREAD_OFFSET 928 /* 0x3a0 */ #define IA64_TASK_THREAD_KSP_OFFSET 928 /* 0x3a0 */ +#define IA64_TASK_THREAD_SIGMASK_OFFSET 2656 /* 0xa60 */ #define IA64_TASK_PID_OFFSET 188 /* 0xbc */ #define IA64_TASK_MM_OFFSET 88 /* 0x58 */ #define IA64_PT_REGS_CR_IPSR_OFFSET 0 /* 0x0 */ @@ -34,5 +35,7 @@ #define IA64_SIGCONTEXT_FLAGS_OFFSET 0 /* 0x0 */ #define IA64_SIGCONTEXT_CFM_OFFSET 48 /* 0x30 */ #define IA64_SIGCONTEXT_FR6_OFFSET 560 /* 0x230 */ +#define IA64_CLONE_VFORK 16384 /* 0x4000 */ +#define IA64_CLONE_VM 256 /* 0x100 */ #endif /* _ASM_IA64_OFFSETS_H */ diff -urN linux-2.3.51/include/asm-ia64/pgalloc.h linux-2.3.51-lia/include/asm-ia64/pgalloc.h --- linux-2.3.51/include/asm-ia64/pgalloc.h Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/include/asm-ia64/pgalloc.h Mon Apr 10 22:56:00 2000 @@ -242,11 +242,6 @@ /* * Page-granular tlb flush. - * - * do a tbisd (type = 2) normally, and a tbis (type = 3) - * if it is an executable mapping. We want to avoid the - * itlb flush, because that potentially also does a - * icache flush. */ static __inline__ void flush_tlb_page (struct vm_area_struct *vma, unsigned long addr) diff -urN linux-2.3.51/include/asm-ia64/processor.h linux-2.3.51-lia/include/asm-ia64/processor.h --- linux-2.3.51/include/asm-ia64/processor.h Thu Feb 24 10:14:29 2000 +++ linux-2.3.51-lia/include/asm-ia64/processor.h Mon Apr 10 22:49:05 2000 @@ -151,6 +151,7 @@ #define IA64_THREAD_DBG_VALID (__IA64_UL(1) << 1) /* debug registers valid? */ #define IA64_THREAD_UAC_NOPRINT (__IA64_UL(1) << 2) /* don't log unaligned accesses */ #define IA64_THREAD_UAC_SIGBUS (__IA64_UL(1) << 3) /* generate SIGBUS on unaligned acc. */ +#define IA64_THREAD_KRBS_SYNCED (__IA64_UL(1) << 4) /* krbs synced with process vm? */ #define IA64_KERNEL_DEATH (__IA64_UL(1) << 63) /* see die_if_kernel()... */ #define IA64_THREAD_UAC_SHIFT 2 @@ -278,11 +279,15 @@ __u64 ibr[IA64_NUM_DBG_REGS]; __u64 map_base; /* base address for mmap() */ #ifdef CONFIG_IA32_SUPPORT + __u64 eflag; /* IA32 EFLAGS reg */ __u64 fsr; /* IA32 floating pt status reg */ __u64 fcr; /* IA32 floating pt control reg */ __u64 fir; /* IA32 fp except. instr. reg */ __u64 fdr; /* IA32 fp except. data reg */ -# define INIT_THREAD_IA32 , 0, 0, 0, 0 + union { + __u64 sigmask; /* aligned mask for sigsuspend scall */ + } un; +# define INIT_THREAD_IA32 , 0, 0, 0, 0, 0, {0} #else # define INIT_THREAD_IA32 #endif /* CONFIG_IA32_SUPPORT */ diff -urN linux-2.3.51/include/asm-ia64/ptrace_offsets.h linux-2.3.51-lia/include/asm-ia64/ptrace_offsets.h --- linux-2.3.51/include/asm-ia64/ptrace_offsets.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/asm-ia64/ptrace_offsets.h Fri Apr 7 23:12:04 2000 @@ -13,9 +13,9 @@ * struct ia64_fpreg fph[96]; // f32-f127 * struct switch_stack sw; * struct pt_regs pt; - * unsigned long rsvd1[358]; + * unsigned long rsvd1[712]; * unsigned long dbr[8]; - * unsigned long rsvd2[252]; + * unsigned long rsvd2[504]; * unsigned long ibr[8]; * } */ @@ -165,7 +165,8 @@ /* pt_regs */ #define PT_CR_IPSR 0x0830 #define PT_CR_IIP 0x0838 -#define PT_CR_IFS 0x0840 +#define PT_CFM 0x0840 +#define PT_CR_IFS PT_CFM /* Use of PT_CR_IFS is deprecated */ #define PT_AR_UNAT 0x0848 #define PT_AR_PFS 0x0850 #define PT_AR_RSC 0x0858 diff -urN linux-2.3.51/include/asm-ia64/semaphore.h linux-2.3.51-lia/include/asm-ia64/semaphore.h --- linux-2.3.51/include/asm-ia64/semaphore.h Sun Feb 13 10:31:06 2000 +++ linux-2.3.51-lia/include/asm-ia64/semaphore.h Mon Apr 10 22:55:54 2000 @@ -230,7 +230,7 @@ do { old_count = sem->count; new_count = old_count - RW_LOCK_BIAS; - } while (cmpxchg(&sem->count, old_count, new_count) != old_count); + } while (cmpxchg_acq(&sem->count, old_count, new_count) != old_count); if (new_count != 0) __down_write_failed(sem, new_count); @@ -279,7 +279,7 @@ do { old_count = sem->count; new_count = old_count + RW_LOCK_BIAS; - } while (cmpxchg(&sem->count, old_count, new_count) != old_count); + } while (cmpxchg_rel(&sem->count, old_count, new_count) != old_count); /* * Note: new_count old_count < 0 && new_count >= 0. diff -urN linux-2.3.51/include/asm-ia64/smp.h linux-2.3.51-lia/include/asm-ia64/smp.h --- linux-2.3.51/include/asm-ia64/smp.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/asm-ia64/smp.h Mon Apr 10 21:42:26 2000 @@ -21,7 +21,7 @@ #define IPI_DEFAULT_BASE_ADDR 0xfee00000 #define XTP_OFFSET 0x1e0008 -#define smp_processor_id() (current->processor) +#define smp_processor_id() (current->processor) extern unsigned long cpu_present_map; extern unsigned long cpu_online_map; @@ -33,10 +33,6 @@ #define cpu_number_map(i) __cpu_number_map[i] #define cpu_logical_map(i) __cpu_logical_map[i] -#if defined(CONFIG_KDB) -extern volatile unsigned long smp_kdb_wait; -#endif /* CONFIG_KDB */ - extern unsigned long ap_wakeup_vector; /* @@ -74,7 +70,7 @@ writeb(0x8f, ipi_base_addr | XTP_OFFSET); /* Set XTP to max... */ } -extern __inline unsigned int +extern __inline__ unsigned int hard_smp_processor_id(void) { struct { @@ -85,17 +81,11 @@ } lid; __asm__ __volatile__ ("mov %0=cr.lid" : "=r" (lid)); - - /* - * Damn. IA64 CPU ID's are 16 bits long, Linux expect the hard id to be - * in the range 0..31. So, return the low-order bits of the bus-local ID - * only and hope it's less than 32. This needs to be fixed... - */ - return (lid.id & 0x0f); + return lid.eid << 8 | lid.id; } -#define NO_PROC_ID 0xffffffff -#define PROC_CHANGE_PENALTY 20 +#define NO_PROC_ID 0xffffffff +#define PROC_CHANGE_PENALTY 20 extern void __init init_smp_config (void); extern void smp_do_timer (struct pt_regs *regs); diff -urN linux-2.3.51/include/asm-ia64/spinlock.h linux-2.3.51-lia/include/asm-ia64/spinlock.h --- linux-2.3.51/include/asm-ia64/spinlock.h Sun Feb 6 18:42:40 2000 +++ linux-2.3.51-lia/include/asm-ia64/spinlock.h Mon Apr 10 21:42:26 2000 @@ -2,8 +2,8 @@ #define _ASM_IA64_SPINLOCK_H /* - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang * Copyright (C) 1999 Walt Drummond * * This file is used for SMP configurations only. @@ -16,29 +16,38 @@ typedef struct { volatile unsigned int lock; } spinlock_t; + #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #define spin_lock_init(x) ((x)->lock = 0) /* Streamlined test_and_set_bit(0, (x)) */ -#define spin_lock(x) __asm__ __volatile__ ( \ - "mov ar.ccv = r0\n" \ - "mov r29 = 1\n" \ - ";;\n" \ - "1:\n" \ - "ld4 r2 = [%0]\n" \ - ";;\n" \ - "cmp4.eq p0,p7 = r0,r2\n" \ - "(p7) br.cond.dptk.few 1b \n" \ - "cmpxchg4.acq r2 = [%0], r29, ar.ccv\n" \ - ";;\n" \ - "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.dptk.few 1b\n" \ - ";;\n" \ - :: "m" __atomic_fool_gcc((x)) : "r2", "r29") - -#define spin_unlock(x) __asm__ __volatile__ ("st4.rel [%0] = r0;;" : "=m" (__atomic_fool_gcc((x)))) - -#define spin_trylock(x) (!test_and_set_bit(0, (x))) +#define spin_lock(x) \ +{ \ + spinlock_t *__x = (x); \ + __u32 old; \ + \ + do { \ + old = __x->lock; \ + if (old) \ + continue; \ + } while (cmpxchg_acq(&__x->lock, old, 1) != old); \ +} + +#define spin_is_locked(x) ((x)->lock != 0) + +#define spin_unlock(x) (((spinlock_t *) x)->lock = 0) + +/* Streamlined !test_and_set_bit(0, (x)) */ +#define spin_trylock(x) \ +({ \ + spinlock_t *__x = (x); \ + __u32 old; \ + \ + do { \ + old = __x->lock; \ + } while (cmpxchg_acq(&__x->lock, old, 1) != old); \ + old == 0; \ +}) #define spin_unlock_wait(x) \ ({ do { barrier(); } while(((volatile spinlock_t *)x)->lock); }) @@ -49,30 +58,30 @@ } rwlock_t; #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 } -#define read_lock(rw) \ -do { \ - int tmp = 0; \ - __asm__ __volatile__ ("1:\tfetchadd4.acq %0 = %1, 1\n" \ - ";;\n" \ - "tbit.nz p6,p0 = %0, 31\n" \ - "(p6) br.cond.sptk.few 2f\n" \ - ".section .text.lock,\"ax\"\n" \ - "2:\tfetchadd4.rel %0 = %1, -1\n" \ - ";;\n" \ - "3:\tld4.acq %0 = %1\n" \ - ";;\n" \ - "tbit.nz p6,p0 = %0, 31\n" \ - "(p6) br.cond.sptk.few 3b\n" \ - "br.cond.sptk.few 1b\n" \ - ";;\n" \ - ".previous\n": "=r" (tmp), "=m" (__atomic_fool_gcc(rw))); \ +#define read_lock(rw) \ +do { \ + int tmp = 0; \ + __asm__ __volatile__ ("1:\tfetchadd4.acq %0 = %1, 1\n" \ + ";;\n" \ + "tbit.nz p6,p0 = %0, 31\n" \ + "(p6) br.cond.sptk.few 2f\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\tfetchadd4.rel %0 = %1, -1\n" \ + ";;\n" \ + "3:\tld4.acq %0 = %1\n" \ + ";;\n" \ + "tbit.nz p6,p0 = %0, 31\n" \ + "(p6) br.cond.sptk.few 3b\n" \ + "br.cond.sptk.few 1b\n" \ + ";;\n" \ + ".previous\n": "=r" (tmp), "=m" (__atomic_fool_gcc(rw))); \ } while(0) -#define read_unlock(rw) \ -do { \ - int tmp = 0; \ - __asm__ __volatile__ ("fetchadd4.rel %0 = %1, -1\n" \ - : "=r" (tmp) : "m" (__atomic_fool_gcc(rw))); \ +#define read_unlock(rw) \ +do { \ + int tmp = 0; \ + __asm__ __volatile__ ("fetchadd4.rel %0 = %1, -1\n" \ + : "=r" (tmp) : "m" (__atomic_fool_gcc(rw))); \ } while(0) /* diff -urN linux-2.3.51/include/asm-ia64/system.h linux-2.3.51-lia/include/asm-ia64/system.h --- linux-2.3.51/include/asm-ia64/system.h Wed Feb 9 19:45:43 2000 +++ linux-2.3.51-lia/include/asm-ia64/system.h Mon Apr 10 21:42:26 2000 @@ -323,7 +323,7 @@ struct __xchg_dummy { unsigned long a[100]; }; #define __xg(x) (*(struct __xchg_dummy *)(x)) -#define ia64_cmpxchg(ptr,old,new,size) \ +#define ia64_cmpxchg(sem,ptr,old,new,size) \ ({ \ __typeof__(ptr) _p_ = (ptr); \ __typeof__(new) _n_ = (new); \ @@ -339,25 +339,25 @@ __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "r"(_o_)); \ switch (size) { \ case 1: \ - __asm__ __volatile__ ("cmpxchg1.rel %0=%2,%3,ar.ccv" \ + __asm__ __volatile__ ("cmpxchg1."sem" %0=%2,%3,ar.ccv" \ : "=r"(_r_), "=m"(__xg(_p_)) \ : "m"(__xg(_p_)), "r"(_n_)); \ break; \ \ case 2: \ - __asm__ __volatile__ ("cmpxchg2.rel %0=%2,%3,ar.ccv" \ + __asm__ __volatile__ ("cmpxchg2."sem" %0=%2,%3,ar.ccv" \ : "=r"(_r_), "=m"(__xg(_p_)) \ : "m"(__xg(_p_)), "r"(_n_)); \ break; \ \ case 4: \ - __asm__ __volatile__ ("cmpxchg4.rel %0=%2,%3,ar.ccv" \ + __asm__ __volatile__ ("cmpxchg4."sem" %0=%2,%3,ar.ccv" \ : "=r"(_r_), "=m"(__xg(_p_)) \ : "m"(__xg(_p_)), "r"(_n_)); \ break; \ \ case 8: \ - __asm__ __volatile__ ("cmpxchg8.rel %0=%2,%3,ar.ccv" \ + __asm__ __volatile__ ("cmpxchg8."sem" %0=%2,%3,ar.ccv" \ : "=r"(_r_), "=m"(__xg(_p_)) \ : "m"(__xg(_p_)), "r"(_n_)); \ break; \ @@ -369,7 +369,11 @@ (__typeof__(old)) _r_; \ }) -#define cmpxchg(ptr,o,n) ia64_cmpxchg((ptr), (o), (n), sizeof(*(ptr))) +#define cmpxchg_acq(ptr,o,n) ia64_cmpxchg("acq", (ptr), (o), (n), sizeof(*(ptr))) +#define cmpxchg_rel(ptr,o,n) ia64_cmpxchg("rel", (ptr), (o), (n), sizeof(*(ptr))) + +/* for compatibility with other platforms: */ +#define cmpxchg(ptr,o,n) cmpxchg_acq(ptr,o,n) #ifdef CONFIG_IA64_DEBUG_CMPXCHG # define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128; @@ -396,24 +400,24 @@ #define prepare_to_switch() do { } while(0) #ifdef CONFIG_IA32_SUPPORT -# define TASK_TO_PTREGS(t) \ - ((struct pt_regs *)(((unsigned long)(t) + IA64_STK_OFFSET - IA64_PT_REGS_SIZE))) # define IS_IA32_PROCESS(regs) (ia64_psr(regs)->is != 0) -# define IA32_FP_STATE(prev,next) \ - if (IS_IA32_PROCESS(TASK_TO_PTREGS(prev))) { \ +# define IA32_STATE(prev,next) \ + if (IS_IA32_PROCESS(ia64_task_regs(prev))) { \ + __asm__ __volatile__("mov %0=ar.eflag":"=r"((prev)->thread.eflag)); \ __asm__ __volatile__("mov %0=ar.fsr":"=r"((prev)->thread.fsr)); \ __asm__ __volatile__("mov %0=ar.fcr":"=r"((prev)->thread.fcr)); \ __asm__ __volatile__("mov %0=ar.fir":"=r"((prev)->thread.fir)); \ __asm__ __volatile__("mov %0=ar.fdr":"=r"((prev)->thread.fdr)); \ } \ - if (IS_IA32_PROCESS(TASK_TO_PTREGS(next))) { \ + if (IS_IA32_PROCESS(ia64_task_regs(next))) { \ + __asm__ __volatile__("mov ar.eflag=%0"::"r"((next)->thread.eflag)); \ __asm__ __volatile__("mov ar.fsr=%0"::"r"((next)->thread.fsr)); \ __asm__ __volatile__("mov ar.fcr=%0"::"r"((next)->thread.fcr)); \ __asm__ __volatile__("mov ar.fir=%0"::"r"((next)->thread.fir)); \ __asm__ __volatile__("mov ar.fdr=%0"::"r"((next)->thread.fdr)); \ } #else /* !CONFIG_IA32_SUPPORT */ -# define IA32_FP_STATE(prev,next) +# define IA32_STATE(prev,next) # define IS_IA32_PROCESS(regs) 0 #endif /* CONFIG_IA32_SUPPORT */ @@ -436,7 +440,7 @@ if ((next)->thread.flags & IA64_THREAD_DBG_VALID) { \ ia64_load_debug_regs(&(next)->thread.dbr[0]); \ } \ - IA32_FP_STATE(prev,next); \ + IA32_STATE(prev,next); \ (last) = ia64_switch_to((next)); \ } while (0) diff -urN linux-2.3.51/include/asm-ia64/types.h linux-2.3.51-lia/include/asm-ia64/types.h --- linux-2.3.51/include/asm-ia64/types.h Sun Feb 13 10:31:07 2000 +++ linux-2.3.51-lia/include/asm-ia64/types.h Mon Apr 10 13:16:50 2000 @@ -13,10 +13,10 @@ */ #ifdef __ASSEMBLY__ -# define __IA64_UL(x) x +# define __IA64_UL(x) (x) # define __IA64_UL_CONST(x) x #else -# define __IA64_UL(x) ((unsigned long)x) +# define __IA64_UL(x) ((unsigned long)(x)) # define __IA64_UL_CONST(x) x##UL #endif diff -urN linux-2.3.51/include/linux/ide.h linux-2.3.51-lia/include/linux/ide.h --- linux-2.3.51/include/linux/ide.h Fri Mar 17 16:03:33 2000 +++ linux-2.3.51-lia/include/linux/ide.h Mon Apr 10 21:47:45 2000 @@ -384,7 +384,7 @@ ide_resetproc_t *resetproc; /* routine to reset controller after a disk reset */ ide_dmaproc_t *dmaproc; /* dma read/write/abort routine */ unsigned int *dmatable_cpu; /* dma physical region descriptor table (cpu view) */ - u32 dmatable_dma; /* dma physical region descriptor table (dma view) */ + dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */ struct scatterlist *sg_table; /* Scatter-gather list used to build the above */ int sg_nents; /* Current number of entries in it */ int sg_dma_direction; /* dma transfer direction */ diff -urN linux-2.3.51/include/linux/irq.h linux-2.3.51-lia/include/linux/irq.h --- linux-2.3.51/include/linux/irq.h Fri Mar 17 16:03:34 2000 +++ linux-2.3.51-lia/include/linux/irq.h Mon Apr 10 21:42:26 2000 @@ -55,6 +55,7 @@ #include /* the arch dependent stuff */ +extern unsigned int do_IRQ (unsigned long irq, struct pt_regs *regs); extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); extern int setup_irq(unsigned int , struct irqaction * ); diff -urN linux-2.3.51/include/linux/rtc.h linux-2.3.51-lia/include/linux/rtc.h --- linux-2.3.51/include/linux/rtc.h Mon Feb 7 19:45:28 2000 +++ linux-2.3.51-lia/include/linux/rtc.h Fri Mar 17 10:43:41 2000 @@ -28,6 +28,17 @@ }; /* + * This data structure is inspired by the EFI (v0.92) wakeup + * alarm API. + */ +struct rtc_wkalrm { + unsigned char enabled; /* 0 = alarm disable, 1 = alarm disabled */ + unsigned char pending; /* 0 = alarm pending, 1 = alarm not pending */ + struct rtc_time time; /* time the alarm is set to */ +}; + + +/* * ioctl calls that are permitted to the /dev/rtc interface, if * CONFIG_RTC/CONFIG_EFI_RTC was enabled. */ @@ -47,5 +58,8 @@ #define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */ #define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ #define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ + +#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ +#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ #endif /* _LINUX_RTC_H_ */ diff -urN linux-2.3.51/init/main.c linux-2.3.51-lia/init/main.c --- linux-2.3.51/init/main.c Fri Mar 17 16:03:34 2000 +++ linux-2.3.51-lia/init/main.c Tue Mar 28 13:38:16 2000 @@ -105,6 +105,9 @@ #if defined(CONFIG_QUOTA) extern void dquot_init_hash(void); #endif +#ifdef CONFIG_PERFMON +extern void perfmon_init(void); +#endif /* * Boot command-line arguments @@ -522,6 +525,9 @@ #endif /* 0000 */ mem_init(); kmem_cache_sizes_init(); +#ifdef CONFIG_PERFMON + perfmon_init(); +#endif #ifdef CONFIG_PROC_FS proc_root_init(); #endif diff -urN linux-2.3.51/kernel/module.c linux-2.3.51-lia/kernel/module.c --- linux-2.3.51/kernel/module.c Fri Mar 17 16:03:34 2000 +++ linux-2.3.51-lia/kernel/module.c Tue Mar 28 13:38:35 2000 @@ -800,7 +800,6 @@ { struct module_ref *dep; unsigned i; - /* Let the module clean up. */ if (mod->flags & MOD_RUNNING) @@ -1001,6 +1000,12 @@ #else /* CONFIG_MODULES */ /* Dummy syscalls for people who don't want modules */ + +int +try_inc_mod_count (struct module *mod) +{ + return 1; +} asmlinkage unsigned long sys_create_module(const char *name_user, size_t size) diff -urN linux-2.3.51/kernel/printk.c linux-2.3.51-lia/kernel/printk.c --- linux-2.3.51/kernel/printk.c Mon Feb 14 15:31:14 2000 +++ linux-2.3.51-lia/kernel/printk.c Fri Feb 18 16:57:45 2000 @@ -296,6 +296,12 @@ break; } } +#ifdef CONFIG_IA64_EARLY_PRINTK + if (!console_drivers) { + static void early_printk (const char *str); + early_printk(msg); + } else +#endif if (msg_level < console_loglevel && console_drivers) { struct console *c = console_drivers; while(c) { @@ -412,6 +418,10 @@ } if ((console->flags & CON_PRINTBUFFER) == 0) goto done; +#ifdef CONFIG_IA64_EARLY_PRINTK + goto done; +#endif + /* * Print out buffered log messages. */ @@ -487,3 +497,47 @@ tty->driver.write(tty, 0, msg, strlen(msg)); return; } + +#ifdef CONFIG_IA64_EARLY_PRINTK + +#include + +#define VGABASE 0x00000000000b8000 + +static int current_ypos = 0, current_xpos = 0; + +void +early_printk (const char *str) +{ + char c; + int i, k, j; + + while ((c = *str++) != '\0') { + if (current_ypos >= 50) { + /* scroll 1 line up */ + for(k = 1, j = 0; k < 50; k++, j++) { + for(i = 0; i < 80; i++) { + writew(readw(VGABASE + 2*(80*k + i)), + VGABASE + 2*(80*j + i)); + } + } + for(i = 0; i < 80; i++) { + writew(0x720, VGABASE + 2*(80*j + i)); + } + current_ypos = 49; + } + if (c == '\n') { + current_xpos = 0; + current_ypos++; + } else if (c != '\r') { + writew(((0x7 << 8) | (unsigned short) c), + VGABASE + 2*(80*current_ypos + current_xpos++)); + if (current_xpos >= 80) { + current_xpos = 0; + current_ypos++; + } + } + } +} + +#endif /* CONFIG_IA64_EARLY_PRINTK */