From: Andi Kleen All of the remaining bug fixes for x86-64 from my tree. Only touches x86-64 specific files. Other changes have been submitted by the respective maintainers. - defconfig updated - Add suspend support code (Pavel Machek) [still has generic problems, shared with i386] - Add iommu=nofullflush option - Rewrite 32bit emulation for siginfo conversion (Joe Korty) - Allow remapping of scatterlists after unmap. This fixes some problems with the SCSI layer retrying previously mapped sg lists when iommu merging was enabled (it's disabled now by default) - Port HPET rtc device emulation code from i386 - Export idle_warning for ACPI (Srihari Vijayaraghavan) --- arch/x86_64/Kconfig | 3 arch/x86_64/defconfig | 75 ++++++++---- arch/x86_64/ia32/ia32_signal.c | 45 +++++-- arch/x86_64/ia32/sys_ia32.c | 93 +-------------- arch/x86_64/kernel/acpi/sleep.c | 17 ++ arch/x86_64/kernel/acpi/wakeup.S | 19 ++- arch/x86_64/kernel/pci-dma.c | 3 arch/x86_64/kernel/pci-gart.c | 20 ++- arch/x86_64/kernel/process.c | 3 arch/x86_64/kernel/time.c | 234 ++++++++++++++++++++++++++++++++++++++- include/asm-x86_64/hpet.h | 59 +++++++++ include/asm-x86_64/hw_irq.h | 2 include/asm-x86_64/ia32.h | 10 + include/asm-x86_64/mc146818rtc.h | 5 include/asm-x86_64/scatterlist.h | 3 include/asm-x86_64/timex.h | 29 ---- 16 files changed, 445 insertions(+), 175 deletions(-) diff -puN arch/x86_64/defconfig~x86_64-merge arch/x86_64/defconfig --- 25/arch/x86_64/defconfig~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/defconfig 2004-01-09 01:27:17.000000000 -0800 @@ -9,6 +9,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_X86_CMPXCHG=y CONFIG_EARLY_PRINTK=y CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y CONFIG_GENERIC_ISA_DMA=y # @@ -26,7 +27,8 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=18 -# CONFIG_IKCONFIG is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_FUTEX=y @@ -34,6 +36,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -59,7 +62,6 @@ CONFIG_X86_CPUID=y CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_MTRR=y -# CONFIG_HUGETLB_PAGE is not set CONFIG_SMP=y # CONFIG_PREEMPT is not set CONFIG_K8_NUMA=y @@ -79,9 +81,9 @@ CONFIG_SOFTWARE_SUSPEND=y # # ACPI (Advanced Configuration and Power Interface) Support # -# CONFIG_ACPI_HT is not set CONFIG_ACPI=y CONFIG_ACPI_BOOT=y +CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_SLEEP=y CONFIG_ACPI_SLEEP_PROC_FS=y CONFIG_ACPI_AC=y @@ -94,17 +96,23 @@ CONFIG_ACPI_THERMAL=y CONFIG_ACPI_TOSHIBA=y CONFIG_ACPI_DEBUG=y CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_EC=y CONFIG_ACPI_POWER=y CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y +# CONFIG_ACPI_RELAXED_AML is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set # # Bus options (PCI etc.) # CONFIG_PCI=y CONFIG_PCI_DIRECT=y +# CONFIG_PCI_USE_VECTOR is not set # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set @@ -115,6 +123,7 @@ CONFIG_PCI_DIRECT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_IA32_EMULATION=y +# CONFIG_IA32_AOUT is not set CONFIG_COMPAT=y CONFIG_UID16=y @@ -179,7 +188,6 @@ CONFIG_BLK_DEV_IDEPCI=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDE_TCQ is not set # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set @@ -246,6 +254,7 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set @@ -260,7 +269,7 @@ CONFIG_SCSI_IPS=m # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set # @@ -313,7 +322,12 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_TUNNEL is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set @@ -325,7 +339,9 @@ CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -358,7 +374,7 @@ CONFIG_NETDEVICES=y # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set +CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -388,7 +404,6 @@ CONFIG_8139TOO=m # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # @@ -421,10 +436,10 @@ CONFIG_TIGON3=y # CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Token Ring devices # +# CONFIG_TR is not set # CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -443,6 +458,11 @@ CONFIG_TIGON3=y # CONFIG_IRDA is not set # +# Bluetooth support +# +# CONFIG_BT is not set + +# # ISDN subsystem # # CONFIG_ISDN_BOOL is not set @@ -504,6 +524,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y # CONFIG_SERIAL_8250_ACPI is not set +CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -520,7 +541,11 @@ CONFIG_UNIX98_PTY_COUNT=256 # CONFIG_I2C is not set # -# I2C Hardware Sensors Mainboard support +# I2C Algorithms +# + +# +# I2C Hardware Bus support # # @@ -549,7 +574,6 @@ CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -559,6 +583,7 @@ CONFIG_AGP_AMD64=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=256 CONFIG_HANGCHECK_TIMER=y # @@ -619,10 +644,13 @@ CONFIG_ISO9660_FS=y # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -647,6 +675,7 @@ CONFIG_RAMFS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y # CONFIG_NFSD_V4 is not set @@ -670,6 +699,11 @@ CONFIG_SUNRPC=y CONFIG_MSDOS_PARTITION=y # +# Native Language Support +# +# CONFIG_NLS is not set + +# # Graphics support # # CONFIG_FB is not set @@ -707,13 +741,15 @@ CONFIG_SOUND_PRIME=y # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set CONFIG_SOUND_ICH=y -# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set # CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_OSS is not set # CONFIG_SOUND_ALI5455 is not set # CONFIG_SOUND_FORTE is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_AD1980 is not set # @@ -723,11 +759,6 @@ CONFIG_SOUND_ICH=y # CONFIG_USB_GADGET is not set # -# Bluetooth support -# -# CONFIG_BT is not set - -# # Profiling support # CONFIG_PROFILING=y @@ -744,8 +775,6 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_INFO is not set # CONFIG_FRAME_POINTER is not set # CONFIG_IOMMU_DEBUG is not set -CONFIG_IOMMU_LEAK=y -CONFIG_MCE_DEBUG=y # # Security options @@ -760,4 +789,4 @@ CONFIG_MCE_DEBUG=y # # Library routines # -# CONFIG_CRC32 is not set +CONFIG_CRC32=y diff -puN arch/x86_64/ia32/ia32_signal.c~x86_64-merge arch/x86_64/ia32/ia32_signal.c --- 25/arch/x86_64/ia32/ia32_signal.c~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/ia32/ia32_signal.c 2004-01-09 01:27:17.000000000 -0800 @@ -44,10 +44,10 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); void signal_fault(struct pt_regs *regs, void *frame, char *where); -static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from) +int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from) { int err; - if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) + if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) return -EFAULT; /* If you change siginfo_t structure, please make sure that @@ -55,21 +55,17 @@ static int ia32_copy_siginfo_to_user(sig It should never copy any pad contained in the structure to avoid security leaks, but must copy the generic 3 ints plus the relevant union member. */ - - if (from->si_code < 0) { err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); err |= __put_user(from->si_code, &to->si_code); - err |= __put_user(from->_sifields._rt._pid, &to->_sifields._rt._pid); - err |= __put_user(from->_sifields._rt._uid, &to->_sifields._rt._uid); - err |= __put_user((u32)(u64)from->_sifields._rt._sigval.sival_ptr, - &to->_sifields._rt._sigval.sival_ptr); - } else { - err = __put_user(from->si_signo, &to->si_signo); - err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user(from->si_code, &to->si_code); - /* First 32bits of unions are always present. */ + + if (from->si_code < 0) { err |= __put_user(from->si_pid, &to->si_pid); + err |= __put_user(from->si_uid, &to->si_uid); + err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr); + } else { + /* First 32bits of unions are always present: + * si_pid === si_band === si_tid === si_addr(LS half) */ switch (from->si_code >> 16) { case __SI_FAULT >> 16: break; @@ -78,18 +74,39 @@ static int ia32_copy_siginfo_to_user(sig err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); default: + case __SI_KILL >> 16: err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_POLL >> 16: - err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; + case __SI_TIMER >> 16: + err |= __put_user(from->si_overrun, &to->si_overrun); + err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr); + break; /* case __SI_RT: This is not generated by the kernel as of now. */ } } return err; } +int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from) +{ + int err; + if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) + return -EFAULT; + + err = __get_user(to->si_signo, &from->si_signo); + err |= __get_user(to->si_errno, &from->si_errno); + err |= __get_user(to->si_code, &from->si_code); + + err |= __get_user(to->si_pid, &from->si_pid); + err |= __get_user(to->si_uid, &from->si_uid); + err |= __get_user((u32)(u64)to->si_ptr, &from->si_ptr); + + return err; +} + asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs) { diff -puN arch/x86_64/ia32/sys_ia32.c~x86_64-merge arch/x86_64/ia32/sys_ia32.c --- 25/arch/x86_64/ia32/sys_ia32.c~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/ia32/sys_ia32.c 2004-01-09 01:27:17.000000000 -0800 @@ -1022,84 +1022,6 @@ sys32_rt_sigpending(compat_sigset_t *set return ret; } -siginfo_t32 * -siginfo64to32(siginfo_t32 *d, siginfo_t *s) -{ - memset (d, 0, sizeof(siginfo_t32)); - d->si_signo = s->si_signo; - d->si_errno = s->si_errno; - d->si_code = s->si_code; - if (s->si_signo >= SIGRTMIN) { - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - memcpy(&d->si_int, &s->si_int, - sizeof(siginfo_t) - offsetof(siginfo_t,si_int)); - } else switch (s->si_signo) { - /* XXX: What about POSIX1.b timers */ - case SIGCHLD: - d->si_pid = s->si_pid; - d->si_status = s->si_status; - d->si_utime = s->si_utime; - d->si_stime = s->si_stime; - break; - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - d->si_addr = (long)(s->si_addr); -// d->si_trapno = s->si_trapno; - break; - case SIGPOLL: - d->si_band = s->si_band; - d->si_fd = s->si_fd; - break; - default: - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - break; - } - return d; -} - -siginfo_t * -siginfo32to64(siginfo_t *d, siginfo_t32 *s) -{ - d->si_signo = s->si_signo; - d->si_errno = s->si_errno; - d->si_code = s->si_code; - if (s->si_signo >= SIGRTMIN) { - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - memcpy(&d->si_int, - &s->si_int, - sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); - } else switch (s->si_signo) { - /* XXX: What about POSIX1.b timers */ - case SIGCHLD: - d->si_pid = s->si_pid; - d->si_status = s->si_status; - d->si_utime = s->si_utime; - d->si_stime = s->si_stime; - break; - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - d->si_addr = (void *)A(s->si_addr); -// d->si_trapno = s->si_trapno; - break; - case SIGPOLL: - d->si_band = s->si_band; - d->si_fd = s->si_fd; - break; - default: - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - break; - } - return d; -} - extern asmlinkage long sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize); @@ -1114,7 +1036,6 @@ sys32_rt_sigtimedwait(compat_sigset_t *u int ret; mm_segment_t old_fs = get_fs(); siginfo_t info; - siginfo_t32 info32; if (copy_from_user (&s32, uthese, sizeof(compat_sigset_t))) return -EFAULT; @@ -1126,13 +1047,18 @@ sys32_rt_sigtimedwait(compat_sigset_t *u } if (uts && get_compat_timespec(&t, uts)) return -EFAULT; + if (uinfo) { + /* stop data leak to user space in case of structure fill mismatch + * between sys_rt_sigtimedwait & ia32_copy_siginfo_to_user. + */ + memset(&info, 0, sizeof(info)); + } set_fs (KERNEL_DS); ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL, sigsetsize); set_fs (old_fs); if (ret >= 0 && uinfo) { - if (copy_to_user (uinfo, siginfo64to32(&info32, &info), - sizeof(siginfo_t32))) + if (ia32_copy_siginfo_to_user(uinfo, &info)) return -EFAULT; } return ret; @@ -1145,14 +1071,11 @@ asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) { siginfo_t info; - siginfo_t32 info32; int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32))) + if (ia32_copy_siginfo_from_user(&info, uinfo)) return -EFAULT; - /* XXX: Is this correct? */ - siginfo32to64(&info, &info32); set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, &info); set_fs (old_fs); diff -puN arch/x86_64/Kconfig~x86_64-merge arch/x86_64/Kconfig --- 25/arch/x86_64/Kconfig~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/Kconfig 2004-01-09 01:27:17.000000000 -0800 @@ -68,6 +68,9 @@ config HPET_TIMER If unsure, say Y. +config HPET_EMULATE_RTC + def_bool HPET_TIMER && RTC=y + config GENERIC_ISA_DMA bool default y diff -puN arch/x86_64/kernel/acpi/sleep.c~x86_64-merge arch/x86_64/kernel/acpi/sleep.c --- 25/arch/x86_64/kernel/acpi/sleep.c~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/acpi/sleep.c 2004-01-09 01:27:17.000000000 -0800 @@ -56,6 +56,7 @@ /* address in low memory of the wakeup routine. */ unsigned long acpi_wakeup_address = 0; +unsigned long acpi_video_flags; extern char wakeup_start, wakeup_end; extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); @@ -116,6 +117,22 @@ void __init acpi_reserve_bootmem(void) printk(KERN_DEBUG "ACPI: have wakeup address 0x%8.8lx\n", acpi_wakeup_address); } +static int __init acpi_sleep_setup(char *str) +{ + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "s3_bios", 7) == 0) + acpi_video_flags = 1; + if (strncmp(str, "s3_mode", 7) == 0) + acpi_video_flags |= 2; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("acpi_sleep=", acpi_sleep_setup); + #endif /*CONFIG_ACPI_SLEEP*/ void acpi_pci_link_exit(void) {} diff -puN arch/x86_64/kernel/acpi/wakeup.S~x86_64-merge arch/x86_64/kernel/acpi/wakeup.S --- 25/arch/x86_64/kernel/acpi/wakeup.S~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/acpi/wakeup.S 2004-01-09 01:27:17.000000000 -0800 @@ -41,7 +41,19 @@ wakeup_code: cmpl $0x12345678, %eax jne bogus_real_magic + testl $1, video_flags - wakeup_code + jz 1f lcall $0xc000,$3 + movw %cs, %ax + movw %ax, %ds # Bios might have played with that + movw %ax, %ss +1: + + testl $2, video_flags - wakeup_code + jz 1f + mov video_mode - wakeup_code, %ax + call mode_seta +1: movw $0xb800, %ax movw %ax,%fs @@ -250,6 +262,7 @@ real_save_gdt: .word 0 .quad 0 real_magic: .quad 0 video_mode: .quad 0 +video_flags: .quad 0 bogus_real_magic: movb $0xba,%al ; outb %al,$0x80 @@ -382,8 +395,10 @@ ENTRY(acpi_copy_wakeup_routine) movl %eax, saved_efer movl %edx, saved_efer2 -# movq saved_videomode, %rdx # FIXME: videomode - movq %rdx, video_mode - wakeup_start (,%rdi) + movl saved_video_mode, %edx + movl %edx, video_mode - wakeup_start (,%rdi) + movl acpi_video_flags, %edx + movl %edx, video_flags - wakeup_start (,%rdi) movq $0x12345678, real_magic - wakeup_start (,%rdi) movq $0x123456789abcdef0, %rdx movq %rdx, saved_magic diff -puN arch/x86_64/kernel/pci-dma.c~x86_64-merge arch/x86_64/kernel/pci-dma.c --- 25/arch/x86_64/kernel/pci-dma.c~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/pci-dma.c 2004-01-09 01:27:17.000000000 -0800 @@ -35,6 +35,7 @@ int pci_map_sg(struct pci_dev *hwdev, st BUG_ON(!s->page); s->dma_address = pci_map_page(hwdev, s->page, s->offset, s->length, direction); + s->dma_length = s->length; } return nents; } @@ -53,7 +54,7 @@ void pci_unmap_sg(struct pci_dev *dev, s struct scatterlist *s = &sg[i]; BUG_ON(s->page == NULL); BUG_ON(s->dma_address == 0); - pci_unmap_single(dev, s->dma_address, s->length, dir); + pci_unmap_single(dev, s->dma_address, s->dma_length, dir); } } diff -puN arch/x86_64/kernel/pci-gart.c~x86_64-merge arch/x86_64/kernel/pci-gart.c --- 25/arch/x86_64/kernel/pci-gart.c~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/pci-gart.c 2004-01-09 01:27:17.000000000 -0800 @@ -382,10 +382,12 @@ static int pci_map_sg_nonforce(struct pc if (i > 0) pci_unmap_sg(dev, sg, i, dir); nents = 0; + sg[0].dma_length = 0; break; } } s->dma_address = addr; + s->dma_length = s->length; } flush_gart(dev); return nents; @@ -412,8 +414,9 @@ static int __pci_map_cont(struct scatter *sout = *s; sout->dma_address = iommu_bus_base; sout->dma_address += iommu_page*PAGE_SIZE + s->offset; + sout->dma_length = s->length; } else { - sout->length += s->length; + sout->dma_length += s->length; } addr = phys_addr; @@ -436,6 +439,7 @@ static inline int pci_map_cont(struct sc if (!need) { BUG_ON(stopat - start != 1); *sout = sg[start]; + sout->dma_length = sg[start].length; return 0; } return __pci_map_cont(sg, start, stopat, sout, pages); @@ -453,8 +457,6 @@ int pci_map_sg(struct pci_dev *dev, stru unsigned long pages = 0; int need = 0, nextneed; - unsigned long size = 0; - BUG_ON(dir == PCI_DMA_NONE); if (nents == 0) return 0; @@ -466,7 +468,6 @@ int pci_map_sg(struct pci_dev *dev, stru s->dma_address = addr; BUG_ON(s->length == 0); - size += s->length; nextneed = need_iommu(dev, addr, s->length); /* Handle the previous not yet processed entries */ @@ -493,7 +494,7 @@ int pci_map_sg(struct pci_dev *dev, stru out++; flush_gart(dev); if (out < nents) - sg[out].length = 0; + sg[out].dma_length = 0; return out; error: @@ -540,9 +541,9 @@ void pci_unmap_sg(struct pci_dev *dev, s int i; for (i = 0; i < nents; i++) { struct scatterlist *s = &sg[i]; - if (!s->length) + if (!s->dma_length || !s->length) break; - pci_unmap_single(dev, s->dma_address, s->length, dir); + pci_unmap_single(dev, s->dma_address, s->dma_length, dir); } } @@ -800,7 +801,8 @@ fs_initcall(pci_iommu_init); merge Do SG merging. Implies force (experimental) nomerge Don't do SG merging. forcesac For SAC mode for masks <40bits (experimental) - fullflush Flush IOMMU on each allocation (for testing) + fullflush Flush IOMMU on each allocation (default) + nofullflush Don't use IOMMU fullflush */ __init int iommu_setup(char *opt) { @@ -838,6 +840,8 @@ __init int iommu_setup(char *opt) iommu_sac_force = 1; if (!memcmp(p, "fullflush", 9)) iommu_fullflush = 1; + if (!memcmp(p, "nofullflush", 11)) + iommu_fullflush = 0; #ifdef CONFIG_IOMMU_LEAK if (!memcmp(p,"leak", 4)) { leak_trace = 1; diff -puN arch/x86_64/kernel/process.c~x86_64-merge arch/x86_64/kernel/process.c --- 25/arch/x86_64/kernel/process.c~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/process.c 2004-01-09 01:27:17.000000000 -0800 @@ -166,6 +166,8 @@ void idle_warning(void) printk(KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n"); } +EXPORT_SYMBOL(idle_warning); + /* Prints also some state that isn't saved in the pt_regs */ void __show_regs(struct pt_regs * regs) { @@ -440,7 +442,6 @@ struct task_struct *__switch_to(struct t write_pda(pcurrent, next_p); write_pda(kernelstack, (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET); - /* * Now maybe reload the debug registers */ diff -puN arch/x86_64/kernel/time.c~x86_64-merge arch/x86_64/kernel/time.c --- 25/arch/x86_64/kernel/time.c~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/time.c 2004-01-09 01:27:17.000000000 -0800 @@ -10,6 +10,7 @@ * Copyright (c) 1998 Andrea Arcangeli * Copyright (c) 2002 Vojtech Pavlik * Copyright (c) 2003 Andi Kleen + * RTC support code taken from arch/i386/kernel/timers/time_hpet.c * */ @@ -28,6 +29,7 @@ #include #include #include +#include #include #ifdef CONFIG_X86_LOCAL_APIC #include @@ -627,10 +629,10 @@ static int hpet_init(void) * and period also hpet_tick. */ - hpet_writel(HPET_T0_ENABLE | HPET_T0_PERIODIC | HPET_T0_SETVAL | - HPET_T0_32BIT, HPET_T0_CFG); - hpet_writel(hpet_tick, HPET_T0_CMP); + hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | + HPET_TN_32BIT, HPET_T0_CFG); hpet_writel(hpet_tick, HPET_T0_CMP); + hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */ /* * Go! @@ -733,3 +735,229 @@ void __init time_init_smp(void) } __setup("report_lost_ticks", time_setup); + +#ifdef CONFIG_HPET_EMULATE_RTC +/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET + * is enabled, we support RTC interrupt functionality in software. + * RTC has 3 kinds of interrupts: + * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock + * is updated + * 2) Alarm Interrupt - generate an interrupt at a specific time of day + * 3) Periodic Interrupt - generate periodic interrupt, with frequencies + * 2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2) + * (1) and (2) above are implemented using polling at a frequency of + * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt + * overhead. (DEFAULT_RTC_INT_FREQ) + * For (3), we use interrupts at 64Hz or user specified periodic + * frequency, whichever is higher. + */ +#include +#include + +extern irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs); + +#define DEFAULT_RTC_INT_FREQ 64 +#define RTC_NUM_INTS 1 + +static unsigned long UIE_on; +static unsigned long prev_update_sec; + +static unsigned long AIE_on; +static struct rtc_time alarm_time; + +static unsigned long PIE_on; +static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ; +static unsigned long PIE_count; + +static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */ + +int is_hpet_enabled(void) +{ + return vxtime.hpet_address != 0; +} + +/* + * Timer 1 for RTC, we do not use periodic interrupt feature, + * even if HPET supports periodic interrupts on Timer 1. + * The reason being, to set up a periodic interrupt in HPET, we need to + * stop the main counter. And if we do that everytime someone diables/enables + * RTC, we will have adverse effect on main kernel timer running on Timer 0. + * So, for the time being, simulate the periodic interrupt in software. + * + * hpet_rtc_timer_init() is called for the first time and during subsequent + * interuppts reinit happens through hpet_rtc_timer_reinit(). + */ +int hpet_rtc_timer_init(void) +{ + unsigned int cfg, cnt; + unsigned long flags; + + if (!is_hpet_enabled()) + return 0; + /* + * Set the counter 1 and enable the interrupts. + */ + if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) + hpet_rtc_int_freq = PIE_freq; + else + hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; + + local_irq_save(flags); + cnt = hpet_readl(HPET_COUNTER); + cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); + hpet_writel(cnt, HPET_T1_CMP); + local_irq_restore(flags); + + cfg = hpet_readl(HPET_T1_CFG); + cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT; + hpet_writel(cfg, HPET_T1_CFG); + + return 1; +} + +static void hpet_rtc_timer_reinit(void) +{ + unsigned int cfg, cnt; + + if (!(PIE_on | AIE_on | UIE_on)) + return; + + if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) + hpet_rtc_int_freq = PIE_freq; + else + hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; + + /* It is more accurate to use the comparator value than current count.*/ + cnt = hpet_readl(HPET_T1_CMP); + cnt += hpet_tick*HZ/hpet_rtc_int_freq; + hpet_writel(cnt, HPET_T1_CMP); + + cfg = hpet_readl(HPET_T1_CFG); + cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT; + hpet_writel(cfg, HPET_T1_CFG); + + return; +} + +/* + * The functions below are called from rtc driver. + * Return 0 if HPET is not being used. + * Otherwise do the necessary changes and return 1. + */ +int hpet_mask_rtc_irq_bit(unsigned long bit_mask) +{ + if (!is_hpet_enabled()) + return 0; + + if (bit_mask & RTC_UIE) + UIE_on = 0; + if (bit_mask & RTC_PIE) + PIE_on = 0; + if (bit_mask & RTC_AIE) + AIE_on = 0; + + return 1; +} + +int hpet_set_rtc_irq_bit(unsigned long bit_mask) +{ + int timer_init_reqd = 0; + + if (!is_hpet_enabled()) + return 0; + + if (!(PIE_on | AIE_on | UIE_on)) + timer_init_reqd = 1; + + if (bit_mask & RTC_UIE) { + UIE_on = 1; + } + if (bit_mask & RTC_PIE) { + PIE_on = 1; + PIE_count = 0; + } + if (bit_mask & RTC_AIE) { + AIE_on = 1; + } + + if (timer_init_reqd) + hpet_rtc_timer_init(); + + return 1; +} + +int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec) +{ + if (!is_hpet_enabled()) + return 0; + + alarm_time.tm_hour = hrs; + alarm_time.tm_min = min; + alarm_time.tm_sec = sec; + + return 1; +} + +int hpet_set_periodic_freq(unsigned long freq) +{ + if (!is_hpet_enabled()) + return 0; + + PIE_freq = freq; + PIE_count = 0; + + return 1; +} + +int hpet_rtc_dropped_irq(void) +{ + if (!is_hpet_enabled()) + return 0; + + return 1; +} + +irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct rtc_time curr_time; + unsigned long rtc_int_flag = 0; + int call_rtc_interrupt = 0; + + hpet_rtc_timer_reinit(); + + if (UIE_on | AIE_on) { + rtc_get_rtc_time(&curr_time); + } + if (UIE_on) { + if (curr_time.tm_sec != prev_update_sec) { + /* Set update int info, call real rtc int routine */ + call_rtc_interrupt = 1; + rtc_int_flag = RTC_UF; + prev_update_sec = curr_time.tm_sec; + } + } + if (PIE_on) { + PIE_count++; + if (PIE_count >= hpet_rtc_int_freq/PIE_freq) { + /* Set periodic int info, call real rtc int routine */ + call_rtc_interrupt = 1; + rtc_int_flag |= RTC_PF; + PIE_count = 0; + } + } + if (AIE_on) { + if ((curr_time.tm_sec == alarm_time.tm_sec) && + (curr_time.tm_min == alarm_time.tm_min) && + (curr_time.tm_hour == alarm_time.tm_hour)) { + /* Set alarm int info, call real rtc int routine */ + call_rtc_interrupt = 1; + rtc_int_flag |= RTC_AF; + } + } + if (call_rtc_interrupt) { + rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8)); + rtc_interrupt(rtc_int_flag, dev_id, regs); + } + return IRQ_HANDLED; +} +#endif diff -puN /dev/null include/asm-x86_64/hpet.h --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/include/asm-x86_64/hpet.h 2004-01-09 01:27:17.000000000 -0800 @@ -0,0 +1,59 @@ +#ifndef _ASM_X8664_HPET_H +#define _ASM_X8664_HPET_H 1 + +#include + +/* + * Documentation on HPET can be found at: + * http://www.intel.com/ial/home/sp/pcmmspec.htm + * ftp://download.intel.com/ial/home/sp/mmts098.pdf + */ + +#define HPET_MMAP_SIZE 1024 + +#define HPET_ID 0x000 +#define HPET_PERIOD 0x004 +#define HPET_CFG 0x010 +#define HPET_STATUS 0x020 +#define HPET_COUNTER 0x0f0 +#define HPET_T0_CFG 0x100 +#define HPET_T0_CMP 0x108 +#define HPET_T0_ROUTE 0x110 +#define HPET_T1_CFG 0x120 +#define HPET_T1_CMP 0x128 +#define HPET_T1_ROUTE 0x130 +#define HPET_T2_CFG 0x140 +#define HPET_T2_CMP 0x148 +#define HPET_T2_ROUTE 0x150 + +#define HPET_ID_VENDOR 0xffff0000 +#define HPET_ID_LEGSUP 0x00008000 +#define HPET_ID_NUMBER 0x00001f00 +#define HPET_ID_REV 0x000000ff + +#define HPET_ID_VENDOR_SHIFT 16 +#define HPET_ID_VENDOR_8086 0x8086 + +#define HPET_CFG_ENABLE 0x001 +#define HPET_CFG_LEGACY 0x002 + +#define HPET_TN_ENABLE 0x004 +#define HPET_TN_PERIODIC 0x008 +#define HPET_TN_PERIODIC_CAP 0x010 +#define HPET_TN_SETVAL 0x040 +#define HPET_TN_32BIT 0x100 + +extern int is_hpet_enabled(void); +extern int hpet_rtc_timer_init(void); + +#ifdef CONFIG_HPET_EMULATE_RTC +extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask); +extern int hpet_set_rtc_irq_bit(unsigned long bit_mask); +extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec); +extern int hpet_set_periodic_freq(unsigned long freq); +extern int hpet_rtc_dropped_irq(void); +extern int hpet_rtc_timer_init(void); +extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs); +#endif /* CONFIG_HPET_EMULATE_RTC */ + +#endif diff -puN include/asm-x86_64/hw_irq.h~x86_64-merge include/asm-x86_64/hw_irq.h --- 25/include/asm-x86_64/hw_irq.h~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/include/asm-x86_64/hw_irq.h 2004-01-09 01:27:17.000000000 -0800 @@ -106,8 +106,6 @@ extern unsigned long io_apic_irqs; extern atomic_t irq_err_count; extern atomic_t irq_mis_count; -extern char _stext, _etext; - #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs)) #define __STR(x) #x diff -puN include/asm-x86_64/ia32.h~x86_64-merge include/asm-x86_64/ia32.h --- 25/include/asm-x86_64/ia32.h~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/include/asm-x86_64/ia32.h 2004-01-09 01:27:17.000000000 -0800 @@ -100,8 +100,11 @@ typedef struct siginfo32 { /* POSIX.1b timers */ struct { - unsigned int _timer1; - unsigned int _timer2; + int _tid; /* timer id */ + int _overrun; /* overrun count */ + sigval_t32 _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + int _overrun_incr; /* amount to add to overrun */ } _timer; /* POSIX.1b signals */ @@ -164,9 +167,12 @@ struct ustat32 { #ifdef __KERNEL__ struct user_desc; +struct siginfo_t; int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info); int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info); int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs); +int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from); +int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from); #endif #endif /* !CONFIG_IA32_SUPPORT */ diff -puN include/asm-x86_64/mc146818rtc.h~x86_64-merge include/asm-x86_64/mc146818rtc.h --- 25/include/asm-x86_64/mc146818rtc.h~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/include/asm-x86_64/mc146818rtc.h 2004-01-09 01:27:17.000000000 -0800 @@ -24,11 +24,6 @@ outb_p((addr),RTC_PORT(0)); \ outb_p((val),RTC_PORT(1)); \ }) -#ifndef CONFIG_HPET_TIMER #define RTC_IRQ 8 -#else -/* Temporary workaround due to IRQ routing problem. */ -#define RTC_IRQ 0 -#endif #endif /* _ASM_MC146818RTC_H */ diff -puN include/asm-x86_64/scatterlist.h~x86_64-merge include/asm-x86_64/scatterlist.h --- 25/include/asm-x86_64/scatterlist.h~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/include/asm-x86_64/scatterlist.h 2004-01-09 01:27:17.000000000 -0800 @@ -6,6 +6,7 @@ struct scatterlist { unsigned int offset; unsigned int length; dma_addr_t dma_address; + unsigned int dma_length; }; #define ISA_DMA_THRESHOLD (0x00ffffff) @@ -16,6 +17,6 @@ struct scatterlist { * returns. */ #define sg_dma_address(sg) ((sg)->dma_address) -#define sg_dma_len(sg) ((sg)->length) +#define sg_dma_len(sg) ((sg)->dma_length) #endif diff -puN include/asm-x86_64/timex.h~x86_64-merge include/asm-x86_64/timex.h --- 25/include/asm-x86_64/timex.h~x86_64-merge 2004-01-09 01:27:17.000000000 -0800 +++ 25-akpm/include/asm-x86_64/timex.h 2004-01-09 01:27:17.000000000 -0800 @@ -9,6 +9,7 @@ #include #include #include +#include #define CLOCK_TICK_RATE 1193182 /* Underlying HZ */ #define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ @@ -30,34 +31,6 @@ static inline cycles_t get_cycles (void) extern unsigned int cpu_khz; -/* - * Documentation on HPET can be found at: - * http://www.intel.com/ial/home/sp/pcmmspec.htm - * ftp://download.intel.com/ial/home/sp/mmts098.pdf - */ - -#define HPET_ID 0x000 -#define HPET_PERIOD 0x004 -#define HPET_CFG 0x010 -#define HPET_STATUS 0x020 -#define HPET_COUNTER 0x0f0 -#define HPET_T0_CFG 0x100 -#define HPET_T0_CMP 0x108 -#define HPET_T0_ROUTE 0x110 - -#define HPET_ID_VENDOR 0xffff0000 -#define HPET_ID_LEGSUP 0x00008000 -#define HPET_ID_NUMBER 0x00000f00 -#define HPET_ID_REV 0x000000ff - -#define HPET_CFG_ENABLE 0x001 -#define HPET_CFG_LEGACY 0x002 - -#define HPET_T0_ENABLE 0x004 -#define HPET_T0_PERIODIC 0x008 -#define HPET_T0_SETVAL 0x040 -#define HPET_T0_32BIT 0x100 - extern struct vxtime_data vxtime; #endif _