diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-18 06:19:39 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-18 06:19:39 -0700 |
| commit | 76dd2761f3527e958e287bf4e83ddea04b92c2cf (patch) | |
| tree | 7df06b326c08ca27c17c60cc1f405a4b132d7068 | |
| parent | 1e215a63539c42fb4b4c936551b04ea44621b390 (diff) | |
| parent | 1a19232d88b8f4545aca468056b924d58b01991b (diff) | |
Merge home.transmeta.com:/home/torvalds/v2.5/x86-64
into home.transmeta.com:/home/torvalds/v2.5/linux
41 files changed, 2389 insertions, 608 deletions
diff --git a/arch/x86_64/Config.help b/arch/x86_64/Config.help index 4bc75426d7b7..1f0a6e48a1fe 100644 --- a/arch/x86_64/Config.help +++ b/arch/x86_64/Config.help @@ -435,6 +435,14 @@ CONFIG_X86_CPUID with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to /dev/cpu/31/cpuid. +CONFIG_NR_CPUS + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 and the + minimum value which makes sense is 2. + + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. + CONFIG_PREEMPT This option reduces the latency of the kernel when reacting to real-time or interactive events by allowing a low priority process to @@ -487,10 +495,6 @@ CONFIG_CHECKING Enables some internal consistency checks for kernel debugging. You should normally say N. -CONFIG_SIMNOW - Disable some time consuming optional things for slow CPU simulators. - Say N unless you're running on a slow simulator like Simics or SimNow. - CONFIG_EARLY_PRINTK Write kernel log output directly into the VGA buffer. This is useful for kernel debugging when your machine crashes very early before @@ -499,13 +503,26 @@ CONFIG_EARLY_PRINTK klogd/syslogd or the X server.You should normally N here, unless you want to debug such a crash. -CONFIG_X86_MCE_NONFATAL - Enabling this feature starts a timer that triggers every 5 seconds which - will look at the machine check registers to see if anything happened. - Non-fatal problems automatically get corrected (but still logged). - Disable this if you don't want to see these messages. - Seeing the messages this option prints out may be indicative of dying hardware, - or out-of-spec (ie, overclocked) hardware. - This option only does something on hardware with Intel P6 style MCE. - (Pentium Pro and above, AMD Athlon/Duron) +CONFIG_KALLSYMS + Say Y here to let the kernel print out symbolic crash information and + symbolic stack backtraces. This increases the size of the kernel + somewhat, as all symbols have to be loaded into the kernel image. + +CONFIG_INIT_DEBUG + Fill __init and __initdata at the end of boot. This is only for debugging. + +CONFIG_IA32_EMULATION + Include code to run 32bit programs under an 64bit kernel. You should likely + turn this on, unless you're 100% sure that you don't have any 32bit programs + left. + +CONFIG_GART_IOMMU + Support the K8 IOMMU. Needed to run systems with more than 4GB of memory + properly with 32bit devices. You should probably turn this on. + The iommu can be turned off at runtime with the iommu=off parameter. + +CONFIG_DUMMY_IOMMU + Don't use IOMMU code. This will cause problems when you have more than 4GB + of memory and any 32bit devices. Don't turn on unless you know what you + are doing. diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 07650a3a0ce1..382b3a091704 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -33,7 +33,7 @@ IA32_CPP := $(CROSS_COMPILE)gcc -m32 -E export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP -LD=$(CROSS_COMPILE)ld -m elf_x86_64 +LDFLAGS := -m elf_x86_64 OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -e stext @@ -47,52 +47,39 @@ CFLAGS += -finline-limit=2000 HEAD := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o -SUBDIRS += arch/x86_64/kernel arch/x86_64/mm arch/x86_64/lib -CORE_FILES := arch/x86_64/kernel/kernel.o $(CORE_FILES) -CORE_FILES += arch/x86_64/mm/mm.o -LIBS := $(TOPDIR)/arch/x86_64/lib/lib.a $(LIBS) - -ifdef CONFIG_IA32_EMULATION -SUBDIRS += arch/x86_64/ia32 -CORE_FILES += arch/x86_64/ia32/ia32.o -endif - -ifdef CONFIG_PCI -SUBDIRS += arch/x86_64/pci -DRIVERS += arch/x86_64/pci/pci.o -endif - -CORE_FILES += $(core-y) +libs-y += arch/x86_64/lib/ +core-y += arch/x86_64/kernel/ arch/x86_64/mm/ +core-$(CONFIG_IA32_EMULATION) += arch/x86_64/ia32/ +drivers-$(CONFIG_PCI) += arch/x86_64/pci/ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +makeboot = $(call descend,arch/x86_64/boot,$(1)) .PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \ clean archclean archmrproper -bzImage: vmlinux - @$(MAKEBOOT) bzImage +BOOTIMAGE=arch/x86_64/boot/bzImage +zImage zlilo zdisk: BOOTIMAGE=arch/x86_64/boot/zImage -bzImage-padded: vmlinux - @$(MAKEBOOT) bzImage-padded +zImage bzImage: vmlinux + +@$(call makeboot,$(BOOTIMAGE)) -tmp: - @$(MAKEBOOT) BOOTIMAGE=bzImage zlilo +compressed: zImage -bzlilo: vmlinux - @$(MAKEBOOT) BOOTIMAGE=bzImage zlilo +zlilo bzlilo: vmlinux + +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zlilo) -bzdisk: vmlinux - @$(MAKEBOOT) BOOTIMAGE=bzImage zdisk +zdisk bzdisk: vmlinux + +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zdisk) install: vmlinux - @$(MAKEBOOT) BOOTIMAGE=bzImage install + +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install) archclean: - @$(MAKEBOOT) clean + +@$(call makeboot,clean) archmrproper: - prepare: include/asm-$(ARCH)/offset.h arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c index 8c674582130e..cc5d85df42fe 100644 --- a/arch/x86_64/boot/compressed/misc.c +++ b/arch/x86_64/boot/compressed/misc.c @@ -190,7 +190,7 @@ static void puts(const char *s) outb_p(0xff & (pos >> 1), vidport+1); } -void* memset(void* s, int c, size_t n) +void* memset(void* s, int c, unsigned n) { int i; char *ss = (char*)s; @@ -199,14 +199,13 @@ void* memset(void* s, int c, size_t n) return s; } -void* memcpy(void* __dest, __const void* __src, - size_t __n) +void* memcpy(void* dest, const void* src, unsigned n) { int i; - char *d = (char *)__dest, *s = (char *)__src; + char *d = (char *)dest, *s = (char *)src; - for (i=0;i<__n;i++) d[i] = s[i]; - return __dest; + for (i=0;i<n;i++) d[i] = s[i]; + return dest; } /* =========================================================================== diff --git a/arch/x86_64/config.in b/arch/x86_64/config.in index 6c41e4e22b1d..95a1393387e8 100644 --- a/arch/x86_64/config.in +++ b/arch/x86_64/config.in @@ -21,6 +21,7 @@ define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n define_bool CONFIG_X86_CMPXCHG y define_bool CONFIG_EARLY_PRINTK y +define_bool CONFIG_GENERIC_ISA_DMA y source init/Config.in @@ -54,11 +55,17 @@ if [ "$CONFIG_SMP" = "n" ]; then fi if [ "$CONFIG_SMP" = "y" ]; then define_bool CONFIG_HAVE_DEC_LOCK y + # actually 64 maximum, but you need to fix the APIC code first + # to use clustered mode or whatever your big iron needs int 'Maximum number of CPUs (2-8)' CONFIG_NR_CPUS 8 fi +bool 'IOMMU support' CONFIG_GART_IOMMU +if [ "$CONFIG_GART_IOMMU" != "y" ]; then + define_bool CONFIG_DUMMY_IOMMU y +fi + define_bool CONFIG_X86_MCE y -bool 'Check for non-fatal machine check errors' CONFIG_X86_MCE_NONFATAL $CONFIG_X86_MCE endmenu @@ -108,22 +115,20 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'IA32 Emulation' CONFIG_IA32_EMULATION + + endmenu source drivers/mtd/Config.in source drivers/parport/Config.in -#source drivers/pnp/Config.in - source drivers/block/Config.in -source drivers/md/Config.in - mainmenu_option next_comment comment 'ATA/ATAPI/MFM/RLL support' -tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE +tristate 'ATA/ATAPI/MFM/RLL device support' CONFIG_IDE if [ "$CONFIG_IDE" != "n" ]; then source drivers/ide/Config.in @@ -133,15 +138,19 @@ fi endmenu mainmenu_option next_comment -comment 'SCSI support' +comment 'SCSI device support' -tristate 'SCSI support' CONFIG_SCSI +tristate 'SCSI device support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then source drivers/scsi/Config.in fi endmenu +source drivers/md/Config.in + +source drivers/telephony/Config.in + source drivers/message/fusion/Config.in source drivers/ieee1394/Config.in @@ -172,8 +181,6 @@ source net/irda/Config.in source drivers/isdn/Config.in -source drivers/telephony/Config.in - # no support for non IDE/SCSI cdroms as they were all ISA only # @@ -224,6 +231,8 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK bool ' Additional run-time checks' CONFIG_CHECKING bool ' Debug __init statements' CONFIG_INIT_DEBUG + bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK + bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS fi endmenu diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 6651cfc904a3..57a53ec3cc0f 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,5 +1,5 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # CONFIG_X86_64=y CONFIG_X86=y @@ -10,6 +10,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_X86_CMPXCHG=y CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ISA_DMA=y # # Code maturity level options @@ -47,11 +48,12 @@ CONFIG_X86_CPUID=y # CONFIG_EISA is not set CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y +CONFIG_MTRR=y CONFIG_SMP=y CONFIG_HAVE_DEC_LOCK=y -CONFIG_X86_MCE=y -# CONFIG_X86_MCE_NONFATAL is not set CONFIG_NR_CPUS=8 +CONFIG_GART_IOMMU=y +CONFIG_X86_MCE=y # # Power management options @@ -61,7 +63,25 @@ CONFIG_NR_CPUS=8 # # ACPI Support # -# CONFIG_ACPI is not set +CONFIG_ACPI=y +# CONFIG_ACPI_HT_ONLY is not set +CONFIG_ACPI_BOOT=y +# CONFIG_ACPI_SLEEP is not set +CONFIG_ACPI_AC=y +CONFIG_ACPI_BATTERY=y +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_FAN=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_TOSHIBA=y +CONFIG_ACPI_DEBUG=y +CONFIG_ACPI_BOOT=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 # # Bus options (PCI etc.) @@ -106,81 +126,21 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_LBD=y # -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing +# ATA/ATAPI/MFM/RLL support # -# CONFIG_NET_SCHED is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set +CONFIG_IDE=y # -# ATA/IDE/MFM/RLL support +# IDE, ATA and ATAPI Block devices # -CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y # -# ATA and ATAPI Block devices +# Please see Documentation/ide.txt for help/info on IDE drives # -CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_HD_IDE is not set # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y @@ -188,27 +148,35 @@ CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_IDEDISK_STROKE is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_BLK_DEV_GENERIC is not set # CONFIG_IDEPCI_SHARE_IRQ is not set CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_IDEDMA_PCI_AUTO is not set -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y # CONFIG_BLK_DEV_IDE_TCQ is not set # CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC6280_BURST is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set CONFIG_BLK_DEV_AMD74XX=y +# CONFIG_AMD74XX_OVERRIDE is not set # CONFIG_BLK_DEV_CMD64X is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -216,88 +184,58 @@ CONFIG_BLK_DEV_AMD74XX=y # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set # CONFIG_PDC202XX_BURST is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set # CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set # CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_SL82C105 is not set # CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y # CONFIG_IDEDMA_IVB is not set -CONFIG_ATAPI=y -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -CONFIG_SCSI_AIC7XXX=y -CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_IDE_MODES=y + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set # # Fusion MPT device support # # CONFIG_FUSION is not set +# CONFIG_FUSION_BOOT is not set +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LAN is not set # # IEEE 1394 (FireWire) support (EXPERIMENTAL) @@ -305,6 +243,53 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_IEEE1394 is not set # +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_FILTER=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +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_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -339,6 +324,11 @@ CONFIG_VORTEX=y # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set @@ -350,6 +340,7 @@ CONFIG_VORTEX=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000_NAPI is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -381,11 +372,6 @@ CONFIG_TIGON3=y # CONFIG_WAN is not set # -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set - -# # Amateur Radio support # # CONFIG_HAMRADIO is not set @@ -403,31 +389,106 @@ CONFIG_TIGON3=y # # Input device support # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_GAMEPORT_NS558 is not set # CONFIG_GAMEPORT_L4 is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_GAMEPORT_PCIGAME is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_VORTEX is not set # CONFIG_GAMEPORT_FM801 is not set # CONFIG_GAMEPORT_CS461x is not set -# CONFIG_SERIO is not set +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y # CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDDLER is not set +# CONFIG_JOYSTICK_DB9 is not set +# CONFIG_JOYSTICK_GAMECON is not set +# CONFIG_JOYSTICK_TURBOGRAFX is not set +# CONFIG_INPUT_JOYDUMP is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_PCSPKR is not set +# CONFIG_INPUT_UINPUT is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -440,10 +501,6 @@ CONFIG_UNIX98_PTY_COUNT=256 # Mice # # CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set # CONFIG_QIC02_TAPE is not set # @@ -451,6 +508,7 @@ CONFIG_PSMOUSE=y # # CONFIG_WATCHDOG is not set # CONFIG_INTEL_RNG is not set +# CONFIG_AMD_RNG is not set # CONFIG_NVRAM is not set CONFIG_RTC=y # CONFIG_DTLK is not set @@ -462,9 +520,18 @@ CONFIG_RTC=y # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_AGP is not set +CONFIG_AGP=y +# CONFIG_AGP_INTEL is not set +# CONFIG_AGP_I810 is not set +# CONFIG_AGP_VIA is not set +# CONFIG_AGP_AMD is not set +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_ALI is not set +# CONFIG_AGP_SWORKS is not set # CONFIG_DRM is not set # CONFIG_MWAVE is not set +# CONFIG_SCx200_GPIO is not set +CONFIG_RAW_DRIVER=y # # Misc devices @@ -504,7 +571,7 @@ CONFIG_JBD=y # CONFIG_CRAMFS is not set CONFIG_TMPFS=y CONFIG_RAMFS=y -# CONFIG_ISO9660_FS is not set +CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set # CONFIG_JFS_FS is not set @@ -530,6 +597,9 @@ CONFIG_EXT2_FS=y # CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set # CONFIG_UFS_FS_WRITE is not set +# CONFIG_XFS_FS is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set # # Network File Systems @@ -537,14 +607,18 @@ CONFIG_EXT2_FS=y # CONFIG_CODA_FS is not set # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -555,6 +629,7 @@ CONFIG_EXPORTFS=y # CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set +# CONFIG_AFS_FS is not set # CONFIG_ZISOFS_FS is not set # @@ -599,8 +674,15 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_CHECKING is not set +CONFIG_CHECKING=y # CONFIG_INIT_DEBUG is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_KALLSYMS is not set + +# +# Security options +# +CONFIG_SECURITY_CAPABILITIES=y # # Library routines diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 32fd068146e5..557d4f5e7575 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -25,7 +25,7 @@ struct elf_phdr; #define IA32_EMULATOR 1 -#define IA32_PAGE_OFFSET 0xE0000000 +#define IA32_PAGE_OFFSET 0xffff0000 #define IA32_STACK_TOP IA32_PAGE_OFFSET #define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000) @@ -216,13 +216,15 @@ static void elf32_init(struct pt_regs *regs) extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address); -int ia32_setup_arg_pages(struct linux_binprm *bprm) +int setup_arg_pages(struct linux_binprm *bprm) { unsigned long stack_base; struct vm_area_struct *mpnt; + struct mm_struct *mm = current->mm; int i; - stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE; + stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE; + mm->arg_start = bprm->p + stack_base; bprm->p += stack_base; if (bprm->loader) @@ -233,9 +235,14 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm) if (!mpnt) return -ENOMEM; - down_write(¤t->mm->mmap_sem); + if (!vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) { + kmem_cache_free(vm_area_cachep, mpnt); + return -ENOMEM; + } + + down_write(&mm->mmap_sem); { - mpnt->vm_mm = current->mm; + mpnt->vm_mm = mm; mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; mpnt->vm_end = IA32_STACK_TOP; mpnt->vm_page_prot = PAGE_COPY; @@ -243,24 +250,25 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm) mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; + INIT_LIST_HEAD(&mpnt->shared); mpnt->vm_private_data = (void *) 0; - insert_vm_struct(current->mm, mpnt); - current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + insert_vm_struct(mm, mpnt); + mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { struct page *page = bprm->page[i]; if (page) { bprm->page[i] = NULL; - current->mm->rss++; put_dirty_page(current,page,stack_base); } stack_base += PAGE_SIZE; } - up_write(¤t->mm->mmap_sem); + up_write(&mm->mmap_sem); return 0; } + static unsigned long elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) { diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 42fc19f33e41..8a84ef80c15b 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -1,4 +1,4 @@ -/* $Id: ia32_ioctl.c,v 1.11 2002/04/18 14:36:37 ak Exp $ +/* $Id: ia32_ioctl.c,v 1.25 2002/10/11 07:17:06 ak Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -21,6 +21,7 @@ #include <linux/hdreg.h> #include <linux/raid/md.h> #include <linux/kd.h> +#include <linux/dirent.h> #include <linux/route.h> #include <linux/in6.h> #include <linux/ipv6_route.h> @@ -55,7 +56,9 @@ #include <linux/module.h> #include <linux/serial.h> #include <linux/reiserfs_fs.h> +#include <linux/if_tun.h> #include <linux/dirent.h> +#include <linux/ctype.h> #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) /* Ugh. This header really is not clean */ #define min min @@ -74,8 +77,14 @@ #include <asm/ia32.h> #include <asm/uaccess.h> #include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/if_bonding.h> +#include <linux/watchdog.h> + #include <asm/module.h> +#include <asm/ioctl32.h> #include <linux/soundcard.h> +#include <linux/lp.h> #include <linux/atm.h> #include <linux/atmarp.h> @@ -88,6 +97,19 @@ #include <linux/atm_tcp.h> #include <linux/sonet.h> #include <linux/atm_suni.h> +#include <linux/mtd/mtd.h> + +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci.h> + +#include <linux/usb.h> +#include <linux/usbdevice_fs.h> +#include <linux/nbd.h> +#include <linux/random.h> +#include <linux/filter.h> + +#include <asm/mtrr.h> + #define A(__x) ((void *)(unsigned long)(__x)) #define AA(__x) A(__x) @@ -114,7 +136,6 @@ static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) return err; } -#if 0 static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); @@ -130,7 +151,6 @@ static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) return -EFAULT; return err; } -#endif static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { @@ -443,6 +463,7 @@ struct ifconf32 { __kernel_caddr_t32 ifcbuf; }; +#ifdef CONFIG_NET static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) { struct net_device *dev; @@ -458,10 +479,12 @@ static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) strncpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name)-1); ifr32.ifr_name[sizeof(ifr32.ifr_name)-1] = 0; + dev_put(dev); err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32)); return (err ? -EFAULT : 0); } +#endif static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) { @@ -558,9 +581,25 @@ static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) } switch (ethcmd) { case ETHTOOL_GDRVINFO: len = sizeof(struct ethtool_drvinfo); break; + case ETHTOOL_GMSGLVL: + case ETHTOOL_SMSGLVL: + case ETHTOOL_GLINK: + case ETHTOOL_NWAY_RST: len = sizeof(struct ethtool_value); break; + case ETHTOOL_GREGS: { + struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data); + /* darned variable size arguments */ + if (get_user(len, (u32 *)®addr->len)) { + err = -EFAULT; + goto out; + } + len += sizeof(struct ethtool_regs); + break; + } case ETHTOOL_GSET: - case ETHTOOL_SSET: - default: len = sizeof(struct ethtool_cmd); break; + case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break; + default: + err = -EOPNOTSUPP; + goto out; } if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { @@ -586,6 +625,91 @@ out: return err; } + +static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq ifr; + mm_segment_t old_fs; + int err, len; + u32 data; + + if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) + return -EFAULT; + ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL); + if (!ifr.ifr_data) + return -EAGAIN; + + switch (cmd) { + case SIOCBONDENSLAVE: + case SIOCBONDRELEASE: + case SIOCBONDSETHWADDR: + case SIOCBONDCHANGEACTIVE: + len = IFNAMSIZ * sizeof(char); + break; + case SIOCBONDSLAVEINFOQUERY: + len = sizeof(struct ifslave); + break; + case SIOCBONDINFOQUERY: + len = sizeof(struct ifbond); + break; + default: + err = -EINVAL; + goto out; + }; + + __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); + if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { + err = -EFAULT; + goto out; + } + + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&ifr); + set_fs (old_fs); + if (!err) { + len = copy_to_user((char *)A(data), ifr.ifr_data, len); + if (len) + err = -EFAULT; + } + +out: + free_page((unsigned long)ifr.ifr_data); + return err; +} + +static __inline__ void *alloc_user_space(long len) +{ + struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs); + return (void *)regs->rsp - len; +} + +static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq *u_ifreq64; + struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg; + char tmp_buf[IFNAMSIZ]; + void *data64; + u32 data32; + + if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), + IFNAMSIZ)) + return -EFAULT; + if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) + return -EFAULT; + data64 = (void *) A(data32); + + u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64)); + + /* Don't check these user accesses, just let that get trapped + * in the ioctl handler instead. + */ + copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ); + __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data); + + return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); +} + static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq ifr; @@ -604,15 +728,6 @@ static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) if (err) return -EFAULT; break; - case SIOCGPPPSTATS: - case SIOCGPPPCSTATS: - case SIOCGPPPVER: - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL); - if (!ifr.ifr_data) - return -EAGAIN; - break; default: if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) return -EFAULT; @@ -638,27 +753,6 @@ static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32))) return -EFAULT; break; - case SIOCGPPPSTATS: - case SIOCGPPPCSTATS: - case SIOCGPPPVER: - { - u32 data; - int len; - - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if(cmd == SIOCGPPPVER) - len = strlen((char *)ifr.ifr_data) + 1; - else if(cmd == SIOCGPPPCSTATS) - len = sizeof(struct ppp_comp_stats); - else - len = sizeof(struct ppp_stats); - - len = copy_to_user((char *)A(data), ifr.ifr_data, len); - free_page((unsigned long)ifr.ifr_data); - if(len) - return -EFAULT; - break; - } case SIOCGIFMAP: err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name)); err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); @@ -671,14 +765,6 @@ static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) err = -EFAULT; break; } - } else { - switch (cmd) { - case SIOCGPPPSTATS: - case SIOCGPPPCSTATS: - case SIOCGPPPVER: - free_page((unsigned long)ifr.ifr_data); - break; - } } return err; } @@ -792,14 +878,6 @@ static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) return err ? -EFAULT : 0; } -struct fbcmap32 { - int index; /* first element (0 origin) */ - int count; - u32 red; - u32 green; - u32 blue; -}; - struct fb_fix_screeninfo32 { char id[16]; __kernel_caddr_t32 smem_start; @@ -883,7 +961,7 @@ static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) break; default: do { - static int count = 0; + static int count; if (++count <= 20) printk("%s: Unknown fb ioctl cmd fd(%d) " "cmd(%08x) arg(%08lx)\n", @@ -1262,6 +1340,269 @@ out: if (karg) kfree(karg); return err; } + +typedef struct sg_io_hdr32 { + s32 interface_id; /* [i] 'S' for SCSI generic (required) */ + s32 dxfer_direction; /* [i] data transfer direction */ + u8 cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + u8 mx_sb_len; /* [i] max length to write to sbp */ + u16 iovec_count; /* [i] 0 implies no scatter gather */ + u32 dxfer_len; /* [i] byte count of data transfer */ + u32 dxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ + u32 cmdp; /* [i], [*i] points to command to perform */ + u32 sbp; /* [i], [*o] points to sense_buffer memory */ + u32 timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + u32 flags; /* [i] 0 -> default, see SG_FLAG... */ + s32 pack_id; /* [i->o] unused internally (normally) */ + u32 usr_ptr; /* [i->o] unused internally */ + u8 status; /* [o] scsi status */ + u8 masked_status; /* [o] shifted, masked scsi status */ + u8 msg_status; /* [o] messaging level data (optional) */ + u8 sb_len_wr; /* [o] byte count actually written to sbp */ + u16 host_status; /* [o] errors from host adapter */ + u16 driver_status; /* [o] errors from software driver */ + s32 resid; /* [o] dxfer_len - actual_transferred */ + u32 duration; /* [o] time taken by cmd (unit: millisec) */ + u32 info; /* [o] auxiliary information */ +} sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ + +typedef struct sg_iovec32 { + u32 iov_base; + u32 iov_len; +} sg_iovec32_t; + +static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) +{ + sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); + sg_iovec_t *kiov; + int i; + + sgp->dxferp = kmalloc(sgp->iovec_count * + sizeof(sg_iovec_t), GFP_KERNEL); + if (!sgp->dxferp) + return -ENOMEM; + memset(sgp->dxferp, 0, + sgp->iovec_count * sizeof(sg_iovec_t)); + + kiov = (sg_iovec_t *) sgp->dxferp; + for (i = 0; i < sgp->iovec_count; i++) { + u32 iov_base32; + if (__get_user(iov_base32, &uiov->iov_base) || + __get_user(kiov->iov_len, &uiov->iov_len)) + return -EFAULT; + + kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); + if (!kiov->iov_base) + return -ENOMEM; + if (copy_from_user(kiov->iov_base, + (void *) A(iov_base32), + kiov->iov_len)) + return -EFAULT; + + uiov++; + kiov++; + } + + return 0; +} + +static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) +{ + sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); + sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; + int i; + + for (i = 0; i < sgp->iovec_count; i++) { + u32 iov_base32; + + if (__get_user(iov_base32, &uiov->iov_base)) + return -EFAULT; + + if (copy_to_user((void *) A(iov_base32), + kiov->iov_base, + kiov->iov_len)) + return -EFAULT; + + uiov++; + kiov++; + } + + return 0; +} + +static void free_sg_iovec(sg_io_hdr_t *sgp) +{ + sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; + int i; + + for (i = 0; i < sgp->iovec_count; i++) { + if (kiov->iov_base) { + kfree(kiov->iov_base); + kiov->iov_base = NULL; + } + kiov++; + } + kfree(sgp->dxferp); + sgp->dxferp = NULL; +} + +static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + sg_io_hdr32_t *sg_io32; + sg_io_hdr_t sg_io64; + u32 dxferp32, cmdp32, sbp32; + mm_segment_t old_fs; + int err = 0; + + sg_io32 = (sg_io_hdr32_t *)arg; + err = __get_user(sg_io64.interface_id, &sg_io32->interface_id); + err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction); + err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len); + err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len); + err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count); + err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len); + err |= __get_user(sg_io64.timeout, &sg_io32->timeout); + err |= __get_user(sg_io64.flags, &sg_io32->flags); + err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id); + + sg_io64.dxferp = NULL; + sg_io64.cmdp = NULL; + sg_io64.sbp = NULL; + + err |= __get_user(cmdp32, &sg_io32->cmdp); + sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); + if (!sg_io64.cmdp) { + err = -ENOMEM; + goto out; + } + if (copy_from_user(sg_io64.cmdp, + (void *) A(cmdp32), + sg_io64.cmd_len)) { + err = -EFAULT; + goto out; + } + + err |= __get_user(sbp32, &sg_io32->sbp); + sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL); + if (!sg_io64.sbp) { + err = -ENOMEM; + goto out; + } + if (copy_from_user(sg_io64.sbp, + (void *) A(sbp32), + sg_io64.mx_sb_len)) { + err = -EFAULT; + goto out; + } + + err |= __get_user(dxferp32, &sg_io32->dxferp); + if (sg_io64.iovec_count) { + int ret; + + if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) { + err = ret; + goto out; + } + } else { + sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); + if (!sg_io64.dxferp) { + err = -ENOMEM; + goto out; + } + if (copy_from_user(sg_io64.dxferp, + (void *) A(dxferp32), + sg_io64.dxfer_len)) { + err = -EFAULT; + goto out; + } + } + + /* Unused internally, do not even bother to copy it over. */ + sg_io64.usr_ptr = NULL; + + if (err) + return -EFAULT; + + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64); + set_fs (old_fs); + + if (err < 0) + goto out; + + err = __put_user(sg_io64.pack_id, &sg_io32->pack_id); + err |= __put_user(sg_io64.status, &sg_io32->status); + err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status); + err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status); + err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr); + err |= __put_user(sg_io64.host_status, &sg_io32->host_status); + err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status); + err |= __put_user(sg_io64.resid, &sg_io32->resid); + err |= __put_user(sg_io64.duration, &sg_io32->duration); + err |= __put_user(sg_io64.info, &sg_io32->info); + err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); + if (sg_io64.dxferp) { + if (sg_io64.iovec_count) + err |= copy_back_sg_iovec(&sg_io64, dxferp32); + else + err |= copy_to_user((void *)A(dxferp32), + sg_io64.dxferp, + sg_io64.dxfer_len); + } + if (err) + err = -EFAULT; + +out: + if (sg_io64.cmdp) + kfree(sg_io64.cmdp); + if (sg_io64.sbp) + kfree(sg_io64.sbp); + if (sg_io64.dxferp) { + if (sg_io64.iovec_count) { + free_sg_iovec(&sg_io64); + } else { + kfree(sg_io64.dxferp); + } + } + return err; +} + +struct sock_fprog32 { + __u16 len; + __u32 filter; +}; + +#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) +#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32) + +static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg; + struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog)); + void *fptr64; + u32 fptr32; + u16 flen; + + if (get_user(flen, &u_fprog32->len) || + get_user(fptr32, &u_fprog32->filter)) + return -EFAULT; + + fptr64 = (void *) A(fptr32); + + if (put_user(flen, &u_fprog64->len) || + put_user(fptr64, &u_fprog64->filter)) + return -EFAULT; + + if (cmd == PPPIOCSPASS32) + cmd = PPPIOCSPASS; + else + cmd = PPPIOCSACTIVE; + + return sys_ioctl(fd, cmd, (unsigned long) u_fprog64); +} + struct ppp_option_data32 { __kernel_caddr_t32 ptr; __u32 length; @@ -1308,7 +1649,7 @@ static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) break; default: do { - static int count = 0; + static int count; if (++count <= 20) printk("ppp_ioctl: Unknown cmd fd(%d) " "cmd(%08x) arg(%08x)\n", @@ -1418,7 +1759,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) break; default: do { - static int count = 0; + static int count; if (++count <= 20) printk("mt_ioctl: Unknown cmd fd(%d) " "cmd(%08x) arg(%08x)\n", @@ -1536,7 +1877,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar break; default: do { - static int count = 0; + static int count; if (++count <= 20) printk("cdrom_ioctl: Unknown cmd fd(%d) " "cmd(%08x) arg(%08x)\n", @@ -1623,7 +1964,7 @@ static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) } break; default: { - static int count = 0; + static int count; if (++count <= 20) printk("%s: Unknown loop ioctl cmd, fd(%d) " "cmd(%08x) arg(%08lx)\n", @@ -1652,9 +1993,9 @@ static int vt_check(struct file *file) /* * To have permissions to do most of the vt ioctls, we either have - * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. + * to be the owner of the tty, or super-user. */ - if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + if (current->tty == tty || capable(CAP_SYS_ADMIN)) return 1; return 0; } @@ -2024,6 +2365,7 @@ typedef struct { u32 pv[ABS_MAX_PV + 1]; u32 lv[ABS_MAX_LV + 1]; uint8_t vg_uuid[UUID_LEN+1]; /* volume group UUID */ + uint8_t dummy1[200]; } vg32_t; typedef struct { @@ -2138,7 +2480,8 @@ static lv_t *get_lv_t(u32 p, int *errp) lv_block_exception32_t *lbe32; lv_block_exception_t *lbe; lv32_t *ul = (lv32_t *)A(p); - lv_t *l = (lv_t *)kmalloc(sizeof(lv_t), GFP_KERNEL); + lv_t *l = (lv_t *) kmalloc(sizeof(lv_t), GFP_KERNEL); + if (!l) { *errp = -ENOMEM; return NULL; @@ -2173,7 +2516,6 @@ static lv_t *get_lv_t(u32 p, int *errp) err |= __get_user(lbe->rdev_org, &lbe32->rdev_org); err |= __get_user(lbe->rsector_new, &lbe32->rsector_new); err |= __get_user(lbe->rdev_new, &lbe32->rdev_new); - } } } @@ -2211,7 +2553,7 @@ static int copy_lv_t(u32 ptr, lv_t *l) static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { - vg_t *v; + vg_t *v = NULL; union { lv_req_t lv_req; le_remap_req_t le_remap; @@ -2229,17 +2571,22 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) switch (cmd) { case VG_STATUS: v = kmalloc(sizeof(vg_t), GFP_KERNEL); - if (!v) return -ENOMEM; + if (!v) + return -ENOMEM; karg = v; break; + + case VG_CREATE_OLD: case VG_CREATE: v = kmalloc(sizeof(vg_t), GFP_KERNEL); - if (!v) return -ENOMEM; - if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc) || - __get_user(v->proc, &((vg32_t *)arg)->proc)) { + if (!v) + return -ENOMEM; + if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc)) { kfree(v); return -EFAULT; } + /* 'proc' field is unused, just NULL it out. */ + v->proc = NULL; if (copy_from_user(v->vg_uuid, ((vg32_t *)arg)->vg_uuid, UUID_LEN+1)) { kfree(v); return -EFAULT; @@ -2251,94 +2598,117 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) return -EPERM; for (i = 0; i < v->pv_max; i++) { err = __get_user(ptr, &((vg32_t *)arg)->pv[i]); - if (err) break; + if (err) + break; if (ptr) { v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL); if (!v->pv[i]) { err = -ENOMEM; break; } - err = copy_from_user(v->pv[i], (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1); + err = copy_from_user(v->pv[i], (void *)A(ptr), + sizeof(pv32_t) - 8 - UUID_LEN+1); if (err) { err = -EFAULT; break; } - err = copy_from_user(v->pv[i]->pv_uuid, ((pv32_t *)A(ptr))->pv_uuid, UUID_LEN+1); + err = copy_from_user(v->pv[i]->pv_uuid, + ((pv32_t *)A(ptr))->pv_uuid, + UUID_LEN+1); if (err) { err = -EFAULT; break; } - - v->pv[i]->pe = NULL; v->pv[i]->inode = NULL; + v->pv[i]->pe = NULL; + v->pv[i]->bd = NULL; } } if (!err) { for (i = 0; i < v->lv_max; i++) { err = __get_user(ptr, &((vg32_t *)arg)->lv[i]); - if (err) break; + if (err) + break; if (ptr) { v->lv[i] = get_lv_t(ptr, &err); - if (err) break; + if (err) + break; } } } break; + case LV_CREATE: case LV_EXTEND: case LV_REDUCE: case LV_REMOVE: case LV_RENAME: case LV_STATUS_BYNAME: - err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); - if (err) return -EFAULT; + err = copy_from_user(&u.pv_status, (void*)arg, sizeof(u.pv_status.pv_name)); + if (err) + return -EFAULT; if (cmd != LV_REMOVE) { err = __get_user(ptr, &((lv_req32_t *)arg)->lv); - if (err) return err; + if (err) + return err; u.lv_req.lv = get_lv_t(ptr, &err); } else u.lv_req.lv = NULL; break; - case LV_STATUS_BYINDEX: - err = get_user(u.lv_byindex.lv_index, &((lv_status_byindex_req32_t *)arg)->lv_index); + err = get_user(u.lv_byindex.lv_index, + &((lv_status_byindex_req32_t *)arg)->lv_index); err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv); - if (err) return err; + if (err) + return err; u.lv_byindex.lv = get_lv_t(ptr, &err); break; + case LV_STATUS_BYDEV: err = get_user(u.lv_bydev.dev, &((lv_status_bydev_req32_t *)arg)->dev); + err |= __get_user(ptr, &((lv_status_bydev_req32_t *)arg)->lv); + if (err) + return err; u.lv_bydev.lv = get_lv_t(ptr, &err); - if (err) return err; - u.lv_bydev.lv = &p; - p.pe = NULL; p.inode = NULL; break; + case VG_EXTEND: err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) return -EFAULT; + if (err) + return -EFAULT; err = copy_from_user(p.pv_uuid, ((pv32_t *)arg)->pv_uuid, UUID_LEN+1); - if (err) return -EFAULT; - p.pe = NULL; p.inode = NULL; + if (err) + return -EFAULT; + p.pe = NULL; + p.bd = NULL; karg = &p; break; + case PV_CHANGE: case PV_STATUS: - err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name)); - if (err) return -EFAULT; + err = copy_from_user(&u.pv_status, (void*)arg, sizeof(u.lv_req.lv_name)); + if (err) + return -EFAULT; err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv); - if (err) return err; + if (err) + return err; u.pv_status.pv = &p; if (cmd == PV_CHANGE) { - err = copy_from_user(&p, (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) return -EFAULT; - p.pe = NULL; p.inode = NULL; + err = copy_from_user(&p, (void *)A(ptr), + sizeof(pv32_t) - 8 - UUID_LEN+1); + if (err) + return -EFAULT; + p.pe = NULL; + p.bd = NULL; } break; - } + }; + old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)karg); set_fs (old_fs); + switch (cmd) { case VG_STATUS: if (!err) { @@ -2351,42 +2721,60 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) } kfree(v); break; + + case VG_CREATE_OLD: case VG_CREATE: - for (i = 0; i < v->pv_max; i++) - if (v->pv[i]) kfree(v->pv[i]); - for (i = 0; i < v->lv_max; i++) - if (v->lv[i]) put_lv_t(v->lv[i]); + for (i = 0; i < v->pv_max; i++) { + if (v->pv[i]) + kfree(v->pv[i]); + } + for (i = 0; i < v->lv_max; i++) { + if (v->lv[i]) + put_lv_t(v->lv[i]); + } kfree(v); break; + case LV_STATUS_BYNAME: - if (!err && u.lv_req.lv) err = copy_lv_t(ptr, u.lv_req.lv); + if (!err && u.lv_req.lv) + err = copy_lv_t(ptr, u.lv_req.lv); /* Fall through */ + case LV_CREATE: case LV_EXTEND: case LV_REDUCE: - if (u.lv_req.lv) put_lv_t(u.lv_req.lv); + if (u.lv_req.lv) + put_lv_t(u.lv_req.lv); break; + case LV_STATUS_BYINDEX: if (u.lv_byindex.lv) { - if (!err) err = copy_lv_t(ptr, u.lv_byindex.lv); + if (!err) + err = copy_lv_t(ptr, u.lv_byindex.lv); put_lv_t(u.lv_byindex.lv); } break; - case PV_STATUS: - if (!err) { - err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1); - if (err) return -EFAULT; - err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1); - if (err) return -EFAULT; - } - break; + case LV_STATUS_BYDEV: - if (!err) { - if (!err) err = copy_lv_t(ptr, u.lv_bydev.lv); + if (u.lv_bydev.lv) { + if (!err) + err = copy_lv_t(ptr, u.lv_bydev.lv); put_lv_t(u.lv_byindex.lv); } break; + + case PV_STATUS: + if (!err) { + err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1); + if (err) + return -EFAULT; + err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1); + if (err) + return -EFAULT; } + break; + }; + return err; } #endif @@ -2976,7 +3364,11 @@ static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioc return err; } -/* SuSE extension */ +static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); +} + #ifndef TIOCGDEV #define TIOCGDEV _IOR('T',0x32, unsigned int) #endif @@ -3088,6 +3480,15 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr) } +#define REISERFS_IOC_UNPACK32 _IOW(0xCD,1,int) + +static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) +{ + if (cmd == REISERFS_IOC_UNPACK32) + cmd = REISERFS_IOC_UNPACK; + return sys_ioctl(fd,cmd,ptr); +} + struct dirent32 { unsigned int d_ino; __kernel_off_t32 d_off; @@ -3125,32 +3526,6 @@ static int vfat_ioctl32(unsigned fd, unsigned cmd, void *ptr) return ret; } - - -#define REISERFS_IOC_UNPACK32 _IOW(0xCD,1,int) - -static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) -{ - if (cmd == REISERFS_IOC_UNPACK32) - cmd = REISERFS_IOC_UNPACK; - return sys_ioctl(fd,cmd,ptr); -} - -#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) - -static int autofs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr) -{ - int ret; - unsigned long val; - mm_segment_t oldfs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, AUTOFS_IOC_SETTIMEOUT32, (unsigned long)&val); - set_fs(oldfs); - if (!ret) - ret = put_user(val, (int *) ptr); - return ret; -} - #define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */ #define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */ #define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */ @@ -3190,6 +3565,572 @@ static int rtc32_ioctl(unsigned fd, unsigned cmd, unsigned long arg) return sys_ioctl(fd,cmd,arg); } +/* Fix sizeof(sizeof()) breakage */ +#define BLKELVGET_32 _IOR(0x12,106,int) +#define BLKELVSET_32 _IOW(0x12,107,int) +#define BLKBSZGET_32 _IOR(0x12,112,int) +#define BLKBSZSET_32 _IOW(0x12,113,int) +#define BLKGETSIZE64_32 _IOR(0x12,114,int) + +static int do_blkelvget(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return sys_ioctl(fd, BLKELVGET, arg); +} + +static int do_blkelvset(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return sys_ioctl(fd, BLKELVSET, arg); +} + +static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return sys_ioctl(fd, BLKBSZGET, arg); +} + +static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return sys_ioctl(fd, BLKBSZSET, arg); +} + +static int do_blkgetsize64(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + return sys_ioctl(fd, BLKGETSIZE64, arg); +} + + + +struct usbdevfs_ctrltransfer32 { + __u8 bRequestType; + __u8 bRequest; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + __u32 timeout; /* in milliseconds */ + __u32 data; +}; + +#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) + +static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_ctrltransfer kctrl; + struct usbdevfs_ctrltransfer32 *uctrl; + mm_segment_t old_fs; + __u32 udata; + void *uptr, *kptr; + int err; + + uctrl = (struct usbdevfs_ctrltransfer32 *) arg; + + if (copy_from_user(&kctrl, uctrl, + (sizeof(struct usbdevfs_ctrltransfer) - + sizeof(void *)))) + return -EFAULT; + + if (get_user(udata, &uctrl->data)) + return -EFAULT; + uptr = (void *) A(udata); + + /* In usbdevice_fs, it limits the control buffer to a page, + * for simplicity so do we. + */ + if (!uptr || kctrl.wLength > PAGE_SIZE) + return -EINVAL; + + kptr = (void *)__get_free_page(GFP_KERNEL); + + if ((kctrl.bRequestType & 0x80) == 0) { + err = -EFAULT; + if (copy_from_user(kptr, uptr, kctrl.wLength)) + goto out; + } + + kctrl.data = kptr; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl); + set_fs(old_fs); + + if (err >= 0 && + ((kctrl.bRequestType & 0x80) != 0)) { + if (copy_to_user(uptr, kptr, kctrl.wLength)) + err = -EFAULT; + } + +out: + free_page((unsigned long) kptr); + return err; +} + +struct usbdevfs_bulktransfer32 { + unsigned int ep; + unsigned int len; + unsigned int timeout; /* in milliseconds */ + __u32 data; +}; + +#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) + +static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_bulktransfer kbulk; + struct usbdevfs_bulktransfer32 *ubulk; + mm_segment_t old_fs; + __u32 udata; + void *uptr, *kptr; + int err; + + ubulk = (struct usbdevfs_bulktransfer32 *) arg; + + if (get_user(kbulk.ep, &ubulk->ep) || + get_user(kbulk.len, &ubulk->len) || + get_user(kbulk.timeout, &ubulk->timeout) || + get_user(udata, &ubulk->data)) + return -EFAULT; + + uptr = (void *) A(udata); + + /* In usbdevice_fs, it limits the control buffer to a page, + * for simplicity so do we. + */ + if (!uptr || kbulk.len > PAGE_SIZE) + return -EINVAL; + + kptr = (void *) __get_free_page(GFP_KERNEL); + + if ((kbulk.ep & 0x80) == 0) { + err = -EFAULT; + if (copy_from_user(kptr, uptr, kbulk.len)) + goto out; + } + + kbulk.data = kptr; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk); + set_fs(old_fs); + + if (err >= 0 && + ((kbulk.ep & 0x80) != 0)) { + if (copy_to_user(uptr, kptr, kbulk.len)) + err = -EFAULT; + } + +out: + free_page((unsigned long) kptr); + return err; +} + +/* This needs more work before we can enable it. Unfortunately + * because of the fancy asynchronous way URB status/error is written + * back to userspace, we'll need to fiddle with USB devio internals + * and/or reimplement entirely the frontend of it ourselves. -DaveM + * + * The issue is: + * + * When an URB is submitted via usbdevicefs it is put onto an + * asynchronous queue. When the URB completes, it may be reaped + * via another ioctl. During this reaping the status is written + * back to userspace along with the length of the transfer. + * + * We must translate into 64-bit kernel types so we pass in a kernel + * space copy of the usbdevfs_urb structure. This would mean that we + * must do something to deal with the async entry reaping. First we + * have to deal somehow with this transitory memory we've allocated. + * This is problematic since there are many call sites from which the + * async entries can be destroyed (and thus when we'd need to free up + * this kernel memory). One of which is the close() op of usbdevicefs. + * To handle that we'd need to make our own file_operations struct which + * overrides usbdevicefs's release op with our own which runs usbdevicefs's + * real release op then frees up the kernel memory. + * + * But how to keep track of these kernel buffers? We'd need to either + * keep track of them in some table _or_ know about usbdevicefs internals + * (ie. the exact layout of it's file private, which is actually defined + * in linux/usbdevice_fs.h, the layout of the async queues are private to + * devio.c) + * + * There is one possible other solution I considered, also involving knowledge + * of usbdevicefs internals: + * + * After an URB is submitted, we "fix up" the address back to the user + * space one. This would work if the status/length fields written back + * by the async URB completion lines up perfectly in the 32-bit type with + * the 64-bit kernel type. Unfortunately, it does not because the iso + * frame descriptors, at the end of the struct, can be written back. + * + * I think we'll just need to simply duplicate the devio URB engine here. + */ +#if 0 +struct usbdevfs_urb32 { + __u8 type; + __u8 endpoint; + __s32 status; + __u32 flags; + __u32 buffer; + __s32 buffer_length; + __s32 actual_length; + __s32 start_frame; + __s32 number_of_packets; + __s32 error_count; + __u32 signr; + __u32 usercontext; /* unused */ + struct usbdevfs_iso_packet_desc iso_frame_desc[0]; +}; + +#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32) + +static int get_urb32(struct usbdevfs_urb *kurb, + struct usbdevfs_urb32 *uurb) +{ + if (get_user(kurb->type, &uurb->type) || + __get_user(kurb->endpoint, &uurb->endpoint) || + __get_user(kurb->status, &uurb->status) || + __get_user(kurb->flags, &uurb->flags) || + __get_user(kurb->buffer_length, &uurb->buffer_length) || + __get_user(kurb->actual_length, &uurb->actual_length) || + __get_user(kurb->start_frame, &uurb->start_frame) || + __get_user(kurb->number_of_packets, &uurb->number_of_packets) || + __get_user(kurb->error_count, &uurb->error_count) || + __get_user(kurb->signr, &uurb->signr)) + return -EFAULT; + + kurb->usercontext = 0; /* unused currently */ + + return 0; +} + +/* Just put back the values which usbdevfs actually changes. */ +static int put_urb32(struct usbdevfs_urb *kurb, + struct usbdevfs_urb32 *uurb) +{ + if (put_user(kurb->status, &uurb->status) || + __put_user(kurb->actual_length, &uurb->actual_length) || + __put_user(kurb->error_count, &uurb->error_count)) + return -EFAULT; + + if (kurb->number_of_packets != 0) { + int i; + + for (i = 0; i < kurb->number_of_packets; i++) { + if (__put_user(kurb->iso_frame_desc[i].actual_length, + &uurb->iso_frame_desc[i].actual_length) || + __put_user(kurb->iso_frame_desc[i].status, + &uurb->iso_frame_desc[i].status)) + return -EFAULT; + } + } + + return 0; +} + +static int get_urb32_isoframes(struct usbdevfs_urb *kurb, + struct usbdevfs_urb32 *uurb) +{ + unsigned int totlen; + int i; + + if (kurb->type != USBDEVFS_URB_TYPE_ISO) { + kurb->number_of_packets = 0; + return 0; + } + + if (kurb->number_of_packets < 1 || + kurb->number_of_packets > 128) + return -EINVAL; + + if (copy_from_user(&kurb->iso_frame_desc[0], + &uurb->iso_frame_desc[0], + sizeof(struct usbdevfs_iso_packet_desc) * + kurb->number_of_packets)) + return -EFAULT; + + totlen = 0; + for (i = 0; i < kurb->number_of_packets; i++) { + unsigned int this_len; + + this_len = kurb->iso_frame_desc[i].length; + if (this_len > 1023) + return -EINVAL; + + totlen += this_len; + } + + if (totlen > 32768) + return -EINVAL; + + kurb->buffer_length = totlen; + + return 0; +} + +static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_urb *kurb; + struct usbdevfs_urb32 *uurb; + mm_segment_t old_fs; + __u32 udata; + void *uptr, *kptr; + unsigned int buflen; + int err; + + uurb = (struct usbdevfs_urb32 *) arg; + + err = -ENOMEM; + kurb = kmalloc(sizeof(struct usbdevfs_urb) + + (sizeof(struct usbdevfs_iso_packet_desc) * 128), + GFP_KERNEL); + if (!kurb) + goto out; + + err = -EFAULT; + if (get_urb32(kurb, uurb)) + goto out; + + err = get_urb32_isoframes(kurb, uurb); + if (err) + goto out; + + err = -EFAULT; + if (__get_user(udata, &uurb->buffer)) + goto out; + uptr = (void *) A(udata); + + err = -ENOMEM; + buflen = kurb->buffer_length; + kptr = kmalloc(buflen, GFP_KERNEL); + if (!kptr) + goto out; + + kurb->buffer = kptr; + + err = -EFAULT; + if (copy_from_user(kptr, uptr, buflen)) + goto out_kptr; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb); + set_fs(old_fs); + + if (err >= 0) { + /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */ + if (put_urb32(kurb, uurb)) { + err = -EFAULT; + } else if ((kurb->endpoint & USB_DIR_IN) != 0) { + if (copy_to_user(uptr, kptr, buflen)) + err = -EFAULT; + } + } + +out_kptr: + kfree(kptr); + +out: + kfree(kurb); + return err; +} +#endif + +#define USBDEVFS_REAPURB32 _IOW('U', 12, u32) +#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32) + +static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs; + void *kptr; + int err; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, + (cmd == USBDEVFS_REAPURB32 ? + USBDEVFS_REAPURB : + USBDEVFS_REAPURBNDELAY), + (unsigned long) &kptr); + set_fs(old_fs); + + if (err >= 0 && + put_user(((u32)(long)kptr), (u32 *) A(arg))) + err = -EFAULT; + + return err; +} + +struct usbdevfs_disconnectsignal32 { + unsigned int signr; + u32 context; +}; + +#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) + +static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct usbdevfs_disconnectsignal kdis; + struct usbdevfs_disconnectsignal32 *udis; + mm_segment_t old_fs; + u32 uctx; + int err; + + udis = (struct usbdevfs_disconnectsignal32 *) arg; + + if (get_user(kdis.signr, &udis->signr) || + __get_user(uctx, &udis->context)) + return -EFAULT; + + kdis.context = (void *) (long)uctx; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis); + set_fs(old_fs); + + return err; +} + +struct mtd_oob_buf32 { + u32 start; + u32 length; + u32 ptr; /* unsigned char* */ +}; + +#define MEMWRITEOOB32 _IOWR('M',3,struct mtd_oob_buf32) +#define MEMREADOOB32 _IOWR('M',4,struct mtd_oob_buf32) + +static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct mtd_oob_buf32 *uarg = (struct mtd_oob_buf32 *)arg; + struct mtd_oob_buf karg; + u32 tmp; + char *ptr; + int ret; + + if (get_user(karg.start, &uarg->start) || + get_user(karg.length, &uarg->length) || + get_user(tmp, &uarg->ptr)) + return -EFAULT; + + ptr = (char *)A(tmp); + if (0 >= karg.length) + return -EINVAL; + + karg.ptr = kmalloc(karg.length, GFP_KERNEL); + if (NULL == karg.ptr) + return -ENOMEM; + + if (copy_from_user(karg.ptr, ptr, karg.length)) { + kfree(karg.ptr); + return -EFAULT; + } + + set_fs(KERNEL_DS); + if (MEMREADOOB32 == cmd) + ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg); + else if (MEMWRITEOOB32 == cmd) + ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg); + else + ret = -EINVAL; + set_fs(old_fs); + + if (0 == ret && cmd == MEMREADOOB32) { + ret = copy_to_user(ptr, karg.ptr, karg.length); + ret |= put_user(karg.start, &uarg->start); + ret |= put_user(karg.length, &uarg->length); + } + + kfree(karg.ptr); + return ((0 == ret) ? 0 : -EFAULT); +} + +/* /proc/mtrr ioctls */ + + +struct mtrr_sentry32 +{ + unsigned int base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int type; /* Type of region */ +}; + +struct mtrr_gentry32 +{ + unsigned int regnum; /* Register number */ + unsigned int base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int type; /* Type of region */ +}; + +#define MTRR_IOCTL_BASE 'M' + +#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32) +#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32) +#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32) +#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32) +#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32) +#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32) +#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32) +#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32) +#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32) +#define MTRRIOC32_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32) + + +static int mtrr_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct mtrr_gentry g; + struct mtrr_sentry s; + int get = 0, err = 0; + struct mtrr_gentry32 *g32 = (struct mtrr_gentry32 *)arg; + mm_segment_t oldfs = get_fs(); + + switch (cmd) { +#define SET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; break +#define GET(x) case MTRRIOC32_ ## x ## _ENTRY: cmd = MTRRIOC_ ## x ## _ENTRY; get=1; break + SET(ADD); + SET(SET); + SET(DEL); + GET(GET); + SET(KILL); + SET(ADD_PAGE); + SET(SET_PAGE); + SET(DEL_PAGE); + GET(GET_PAGE); + SET(KILL_PAGE); + } + + if (get) { + err = get_user(g.regnum, &g32->regnum); + err |= get_user(g.base, &g32->base); + err |= get_user(g.size, &g32->size); + err |= get_user(g.type, &g32->type); + + arg = (unsigned long)&g; + } else { + struct mtrr_sentry32 *s32 = (struct mtrr_sentry32 *)arg; + err = get_user(s.base, &s32->base); + err |= get_user(s.size, &s32->size); + err |= get_user(s.type, &s32->type); + + arg = (unsigned long)&s; + } + if (err) return err; + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, arg); + set_fs(oldfs); + + if (!err && get) { + err = put_user(g.base, &g32->base); + err |= put_user(g.size, &g32->size); + err |= put_user(g.regnum, &g32->regnum); + err |= put_user(g.type, &g32->type); + } + return err; +} + struct ioctl_trans { unsigned long cmd; int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp); @@ -3220,7 +4161,6 @@ COMPATIBLE_IOCTL(TCSETS) COMPATIBLE_IOCTL(TCSETSW) COMPATIBLE_IOCTL(TCSETSF) COMPATIBLE_IOCTL(TIOCLINUX) -HANDLE_IOCTL(TIOCGDEV, tiocgdev) /* Little t */ COMPATIBLE_IOCTL(TIOCGETD) COMPATIBLE_IOCTL(TIOCSETD) @@ -3245,6 +4185,7 @@ COMPATIBLE_IOCTL(TIOCSCTTY) COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) +/* Big F */ COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) @@ -3269,12 +4210,14 @@ COMPATIBLE_IOCTL(FIGETBSZ) */ COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) COMPATIBLE_IOCTL(HDIO_SET_DMA) +COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR) COMPATIBLE_IOCTL(HDIO_SET_NOWERR) COMPATIBLE_IOCTL(HDIO_SET_32BIT) COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT) COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) +COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) COMPATIBLE_IOCTL(HDIO_SET_NICE) /* 0x02 -- Floppy ioctls */ COMPATIBLE_IOCTL(FDMSGON) @@ -3302,7 +4245,6 @@ COMPATIBLE_IOCTL(BLKRASET) COMPATIBLE_IOCTL(BLKFRASET) COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKSSZGET) - /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) COMPATIBLE_IOCTL(GET_ARRAY_INFO) @@ -3323,7 +4265,6 @@ COMPATIBLE_IOCTL(START_ARRAY) COMPATIBLE_IOCTL(STOP_ARRAY) COMPATIBLE_IOCTL(STOP_ARRAY_RO) COMPATIBLE_IOCTL(RESTART_ARRAY_RW) - /* Big K */ COMPATIBLE_IOCTL(PIO_FONT) COMPATIBLE_IOCTL(GIO_FONT) @@ -3345,6 +4286,7 @@ COMPATIBLE_IOCTL(KDGKBSENT) COMPATIBLE_IOCTL(KDSKBSENT) COMPATIBLE_IOCTL(KDGKBDIACR) COMPATIBLE_IOCTL(KDSKBDIACR) +COMPATIBLE_IOCTL(KDKBDREP) COMPATIBLE_IOCTL(KDGKBLED) COMPATIBLE_IOCTL(KDSKBLED) COMPATIBLE_IOCTL(KDGETLED) @@ -3364,6 +4306,14 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) +COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) +COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) +/* Big T */ +COMPATIBLE_IOCTL(TUNSETNOCSUM) +COMPATIBLE_IOCTL(TUNSETDEBUG) +COMPATIBLE_IOCTL(TUNSETIFF) +COMPATIBLE_IOCTL(TUNSETPERSIST) +COMPATIBLE_IOCTL(TUNSETOWNER) /* Big V */ COMPATIBLE_IOCTL(VT_SETMODE) COMPATIBLE_IOCTL(VT_GETMODE) @@ -3377,7 +4327,8 @@ COMPATIBLE_IOCTL(VT_RESIZE) COMPATIBLE_IOCTL(VT_RESIZEX) COMPATIBLE_IOCTL(VT_LOCKSWITCH) COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -/* Little v, the video4linux ioctls */ +/* Little v */ +/* Little v, the video4linux ioctls (conflict?) */ COMPATIBLE_IOCTL(VIDIOCGCAP) COMPATIBLE_IOCTL(VIDIOCGCHAN) COMPATIBLE_IOCTL(VIDIOCSCHAN) @@ -3417,10 +4368,6 @@ COMPATIBLE_IOCTL(RTC_RD_TIME) COMPATIBLE_IOCTL(RTC_SET_TIME) COMPATIBLE_IOCTL(RTC_WKALM_SET) COMPATIBLE_IOCTL(RTC_WKALM_RD) -HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl) -HANDLE_IOCTL(RTC_IRQP_SET32,rtc32_ioctl) -HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl) -HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl) /* Little m */ COMPATIBLE_IOCTL(MTIOCTOP) /* Socket level stuff */ @@ -3442,6 +4389,11 @@ COMPATIBLE_IOCTL(SIOCGRARP) COMPATIBLE_IOCTL(SIOCDRARP) COMPATIBLE_IOCTL(SIOCADDDLCI) COMPATIBLE_IOCTL(SIOCDELDLCI) +COMPATIBLE_IOCTL(SIOCGMIIPHY) +COMPATIBLE_IOCTL(SIOCGMIIREG) +COMPATIBLE_IOCTL(SIOCSMIIREG) +COMPATIBLE_IOCTL(SIOCGIFVLAN) +COMPATIBLE_IOCTL(SIOCSIFVLAN) /* SG stuff */ COMPATIBLE_IOCTL(SG_SET_TIMEOUT) COMPATIBLE_IOCTL(SG_GET_TIMEOUT) @@ -3463,7 +4415,6 @@ COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) COMPATIBLE_IOCTL(SG_SCSI_RESET) -COMPATIBLE_IOCTL(SG_IO) COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) @@ -3481,10 +4432,14 @@ COMPATIBLE_IOCTL(PPPIOCSMAXCID) COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) COMPATIBLE_IOCTL(PPPIOCXFERUNIT) +/* PPPIOCSCOMPRESS is translated */ COMPATIBLE_IOCTL(PPPIOCGNPMODE) COMPATIBLE_IOCTL(PPPIOCSNPMODE) COMPATIBLE_IOCTL(PPPIOCGDEBUG) COMPATIBLE_IOCTL(PPPIOCSDEBUG) +/* PPPIOCSPASS is translated */ +/* PPPIOCSACTIVE is translated */ +/* PPPIOCGIDLE is translated */ COMPATIBLE_IOCTL(PPPIOCNEWUNIT) COMPATIBLE_IOCTL(PPPIOCATTACH) COMPATIBLE_IOCTL(PPPIOCDETACH) @@ -3494,8 +4449,10 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN) COMPATIBLE_IOCTL(PPPIOCATTCHAN) COMPATIBLE_IOCTL(PPPIOCGCHAN) /* PPPOX */ -COMPATIBLE_IOCTL(PPPOEIOCSFWD); -COMPATIBLE_IOCTL(PPPOEIOCDFWD); +COMPATIBLE_IOCTL(PPPOEIOCSFWD) +COMPATIBLE_IOCTL(PPPOEIOCDFWD) +/* LP */ +COMPATIBLE_IOCTL(LPGETSTATUS) /* CDROM stuff */ COMPATIBLE_IOCTL(CDROMPAUSE) COMPATIBLE_IOCTL(CDROMRESUME) @@ -3527,9 +4484,15 @@ COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) COMPATIBLE_IOCTL(CDROM_LOCKDOOR) COMPATIBLE_IOCTL(CDROM_DEBUG) COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) +/* DVD ioctls */ +COMPATIBLE_IOCTL(DVD_READ_STRUCT) +COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) +COMPATIBLE_IOCTL(DVD_AUTH) /* Big L */ COMPATIBLE_IOCTL(LOOP_SET_FD) COMPATIBLE_IOCTL(LOOP_CLR_FD) +/* Big A */ +/* sparc only */ /* Big Q for sound/OSS */ COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET) COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC) @@ -3688,7 +4651,6 @@ COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) -HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, autofs_ioctl32); /* DEVFS */ COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) @@ -3755,15 +4717,68 @@ COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) #endif /* DRM */ -HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32); -HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32); -HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32); -/* serial driver */ -HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl); -HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl); -/* elevator */ -COMPATIBLE_IOCTL(BLKELVGET) -COMPATIBLE_IOCTL(BLKELVSET) +#ifdef CONFIG_AUTOFS_FS +COMPATIBLE_IOCTL(AUTOFS_IOC_READY) +COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) +COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) +COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) +COMPATIBLE_IOCTL(AUTOFS_IOC_SETTIMEOUT) +COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) +#endif +#ifdef CONFIG_RTC +COMPATIBLE_IOCTL(RTC_AIE_ON) +COMPATIBLE_IOCTL(RTC_AIE_OFF) +COMPATIBLE_IOCTL(RTC_UIE_ON) +COMPATIBLE_IOCTL(RTC_UIE_OFF) +COMPATIBLE_IOCTL(RTC_PIE_ON) +COMPATIBLE_IOCTL(RTC_PIE_OFF) +COMPATIBLE_IOCTL(RTC_WIE_ON) +COMPATIBLE_IOCTL(RTC_WIE_OFF) +COMPATIBLE_IOCTL(RTC_ALM_SET) +COMPATIBLE_IOCTL(RTC_ALM_READ) +COMPATIBLE_IOCTL(RTC_RD_TIME) +COMPATIBLE_IOCTL(RTC_SET_TIME) +COMPATIBLE_IOCTL(RTC_WKALM_SET) +COMPATIBLE_IOCTL(RTC_WKALM_RD) +#endif +/* Big W */ +/* WIOC_GETSUPPORT not yet implemented -E */ +COMPATIBLE_IOCTL(WDIOC_GETSTATUS) +COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS) +COMPATIBLE_IOCTL(WDIOC_GETTEMP) +COMPATIBLE_IOCTL(WDIOC_SETOPTIONS) +COMPATIBLE_IOCTL(WDIOC_KEEPALIVE) +#if 0 /* sparc only ? */ +COMPATIBLE_IOCTL(WIOCSTART) +COMPATIBLE_IOCTL(WIOCSTOP) +COMPATIBLE_IOCTL(WIOCGSTAT) +#endif +/* Big R */ +COMPATIBLE_IOCTL(RNDGETENTCNT) +COMPATIBLE_IOCTL(RNDADDTOENTCNT) +COMPATIBLE_IOCTL(RNDGETPOOL) +COMPATIBLE_IOCTL(RNDADDENTROPY) +COMPATIBLE_IOCTL(RNDZAPENTCNT) +COMPATIBLE_IOCTL(RNDCLEARPOOL) +/* Bluetooth ioctls */ +COMPATIBLE_IOCTL(HCIDEVUP) +COMPATIBLE_IOCTL(HCIDEVDOWN) +COMPATIBLE_IOCTL(HCIDEVRESET) +COMPATIBLE_IOCTL(HCIDEVRESTAT) +COMPATIBLE_IOCTL(HCIGETDEVLIST) +COMPATIBLE_IOCTL(HCIGETDEVINFO) +COMPATIBLE_IOCTL(HCIGETCONNLIST) +COMPATIBLE_IOCTL(HCIGETCONNINFO) +COMPATIBLE_IOCTL(HCISETRAW) +COMPATIBLE_IOCTL(HCISETSCAN) +COMPATIBLE_IOCTL(HCISETAUTH) +COMPATIBLE_IOCTL(HCISETENCRYPT) +COMPATIBLE_IOCTL(HCISETPTYPE) +COMPATIBLE_IOCTL(HCISETLINKPOL) +COMPATIBLE_IOCTL(HCISETLINKMODE) +COMPATIBLE_IOCTL(HCISETACLMTU) +COMPATIBLE_IOCTL(HCISETSCOMTU) +COMPATIBLE_IOCTL(HCIINQUIRY) /* Misc. */ COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */ @@ -3771,8 +4786,46 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) +COMPATIBLE_IOCTL(0x4B50); /* KDGHWCLK - not in the kernel, but don't complain */ +COMPATIBLE_IOCTL(0x4B51); /* KDSHWCLK - not in the kernel, but don't complain */ +/* USB */ +COMPATIBLE_IOCTL(USBDEVFS_RESETEP) +COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE) +COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION) +COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER) +COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB) +COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE) +COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE) +COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO) +COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO) +COMPATIBLE_IOCTL(USBDEVFS_RESET) +COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT) +/* MTD */ +COMPATIBLE_IOCTL(MEMGETINFO) +COMPATIBLE_IOCTL(MEMERASE) +COMPATIBLE_IOCTL(MEMLOCK) +COMPATIBLE_IOCTL(MEMUNLOCK) +COMPATIBLE_IOCTL(MEMGETREGIONCOUNT) +COMPATIBLE_IOCTL(MEMGETREGIONINFO) +/* NBD */ +COMPATIBLE_IOCTL(NBD_SET_SOCK) +COMPATIBLE_IOCTL(NBD_SET_BLKSIZE) +COMPATIBLE_IOCTL(NBD_SET_SIZE) +COMPATIBLE_IOCTL(NBD_DO_IT) +COMPATIBLE_IOCTL(NBD_CLEAR_SOCK) +COMPATIBLE_IOCTL(NBD_CLEAR_QUE) +COMPATIBLE_IOCTL(NBD_PRINT_DEBUG) +COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS) +COMPATIBLE_IOCTL(NBD_DISCONNECT) /* And these ioctls need translation */ +HANDLE_IOCTL(TIOCGDEV, tiocgdev) +HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl) +HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) +HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) +HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) +#ifdef CONFIG_NET HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) +#endif HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) @@ -3799,26 +4852,42 @@ HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc) HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc) HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc) -HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc) -HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc) HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) +HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) +HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) +HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl) +HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl) +HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl) +HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl) HANDLE_IOCTL(SIOCADDRT, routing_ioctl) HANDLE_IOCTL(SIOCDELRT, routing_ioctl) +/* realtime device */ +HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl) +HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl) +HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl) +HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl) +HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl) +HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32) +HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) +HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32) /* Raw devices */ HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ HANDLE_IOCTL(SIOCRTMSG, ret_einval) HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) +HANDLE_IOCTL(BLKRAGET, w_long) HANDLE_IOCTL(BLKGETSIZE, w_long) HANDLE_IOCTL(0x1260, broken_blkgetsize) +HANDLE_IOCTL(BLKFRAGET, w_long) HANDLE_IOCTL(BLKSECTGET, w_long) +HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans) HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) @@ -3834,8 +4903,11 @@ HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans) HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans) HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) +HANDLE_IOCTL(SG_IO,sg_ioctl_trans) HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans) HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans) +HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans) +HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans) HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans) @@ -3849,6 +4921,8 @@ HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans) HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) HANDLE_IOCTL(LOOP_SET_STATUS, loop_status) HANDLE_IOCTL(LOOP_GET_STATUS, loop_status) +#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) +HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl) HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl) HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl) @@ -3907,18 +4981,48 @@ HANDLE_IOCTL(LV_STATUS_BYNAME, do_lvm_ioctl) HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl) HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl) HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl) +HANDLE_IOCTL(VG_CREATE_OLD, do_lvm_ioctl) +HANDLE_IOCTL(LV_STATUS_BYDEV, do_lvm_ioctl) #endif /* LVM */ #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version); -HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique); -HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique); -HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap); -HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs); -HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs); -HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs); -HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma); -HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx); +HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version) +HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique) +HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique) +HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap) +HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs) +HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs) +HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs) +HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma) +HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx) #endif /* DRM */ +/* VFAT */ +HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32) +HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32) +HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) +HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) +/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ +HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) +HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) +HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) +/* take care of sizeof(sizeof()) breakage */ +/* elevator */ +HANDLE_IOCTL(BLKELVGET_32, do_blkelvget) +HANDLE_IOCTL(BLKELVSET_32, do_blkelvset) +/* block stuff */ +HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) +HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) +HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) +/* mtrr */ +HANDLE_IOCTL(MTRRIOC32_ADD_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_SET_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_DEL_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_GET_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_KILL_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_ADD_PAGE_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_SET_PAGE_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_DEL_PAGE_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_GET_PAGE_ENTRY, mtrr_ioctl32) +HANDLE_IOCTL(MTRRIOC32_KILL_PAGE_ENTRY, mtrr_ioctl32) IOCTL_TABLE_END #define IOCTL_HASHSIZE 256 @@ -3926,6 +5030,8 @@ struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE]; extern struct ioctl_trans ioctl_start[], ioctl_end[]; +extern struct ioctl_trans ioctl_start[], ioctl_end[]; + static inline unsigned long ioctl32_hash(unsigned long cmd) { return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE; @@ -4022,7 +5128,7 @@ static inline int builtin_ioctl(struct ioctl_trans *t) /* Problem: This function cannot unregister duplicate ioctls, because they are not unique. - When they happen we need to extend the prototype to pass handler too. */ + When they happen we need to extend the prototype to pass the handler too. */ int unregister_ioctl32_conversion(unsigned int cmd) { @@ -4096,13 +5202,35 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) if (t) { handler = t->handler; error = handler(fd, cmd, arg, filp); + } else if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { + error = siocdevprivate_ioctl(fd, cmd, arg); } else { - static int count = 0; - if (++count <= 50) - printk("sys32_ioctl(%s:%d): Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", + static int count; + if (++count <= 50) { + char buf[10]; + char *path = (char *)__get_free_page(GFP_KERNEL), *fn = "?"; + + /* find the name of the device. */ + if (path) { + struct file *f = fget(fd); + if (f) { + fn = d_path(f->f_dentry, f->f_vfsmnt, + path, PAGE_SIZE); + fput(f); + } + } + + sprintf(buf,"'%c'", (cmd>>24) & 0x3f); + if (!isprint(buf[1])) + sprintf(buf, "%02x", buf[1]); + printk("ioctl32(%s:%d): Unknown cmd fd(%d) " + "cmd(%08x){%s} arg(%08x) on %s\n", current->comm, current->pid, - (int)fd, (unsigned int)cmd, (unsigned int)arg); + (int)fd, (unsigned int)cmd, buf, (unsigned int)arg, + fn); + if (path) + free_page((unsigned long)path); + } error = -EINVAL; } out: @@ -4110,3 +5238,4 @@ out: out2: return error; } + diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index 5274839f0e34..782e6144eedf 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -7,7 +7,7 @@ * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen * - * $Id: ia32_signal.c,v 1.17 2002/03/21 14:16:32 ak Exp $ + * $Id: ia32_signal.c,v 1.22 2002/07/29 10:34:03 ak Exp $ */ #include <linux/sched.h> @@ -39,6 +39,7 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 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) { @@ -163,32 +164,38 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsign regs->r ## x = reg; \ } -#define RELOAD_SEG(seg) \ +#define RELOAD_SEG(seg,mask) \ { unsigned int cur; \ unsigned short pre; \ err |= __get_user(pre, &sc->seg); \ asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \ + pre |= mask; \ if (pre != cur) loadsegment(seg,pre); } - /* Reload fs and gs if they have changed in the signal handler. */ + /* Reload fs and gs if they have changed in the signal handler. + This does not handle long fs/gs base changes in the handler, but + does not clobber them at least in the normal case. */ { - unsigned short gs; + unsigned gs, oldgs; err |= __get_user(gs, &sc->gs); + gs |= 3; + asm("movl %%gs,%0" : "=r" (oldgs)); + if (gs != oldgs) load_gs_index(gs); } - RELOAD_SEG(fs); - RELOAD_SEG(ds); - RELOAD_SEG(es); + RELOAD_SEG(fs,3); + RELOAD_SEG(ds,3); + RELOAD_SEG(es,3); COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(dx); COPY(cx); COPY(ip); /* Don't touch extended registers */ err |= __get_user(regs->cs, &sc->cs); - regs->cs |= 2; + regs->cs |= 3; err |= __get_user(regs->ss, &sc->ss); - regs->ss |= 2; + regs->ss |= 3; { unsigned int tmpflags; @@ -284,7 +291,7 @@ asmlinkage int sys32_rt_sigreturn(struct pt_regs regs) return eax; badframe: - signal_fault(®s, frame, "32bit rt sigreturn"); + signal_fault(®s,frame,"32bit rt sigreturn"); return 0; } @@ -377,8 +384,9 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, { struct exec_domain *ed = current_thread_info()->exec_domain; - - err |= __put_user((ed && ed->signal_invmap && sig < 32 + err |= __put_user((ed + && ed->signal_invmap + && sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig); @@ -435,7 +443,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; - signal_fault(regs,frame,"32bit signal setup"); + signal_fault(regs,frame,"32bit signal deliver"); } void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -449,9 +457,12 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; + { struct exec_domain *ed = current_thread_info()->exec_domain; - err |= __put_user((ed && ed->signal_invmap && sig < 32 + err |= __put_user((ed + && ed->signal_invmap + && sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig); diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 406e6ddb2dac..df4e6d13ec3d 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -27,7 +27,7 @@ */ ENTRY(ia32_cstar_target) movq $-ENOSYS,%rax - sysret + sysretl /* * Emulated IA32 system calls via int 0x80. @@ -77,6 +77,7 @@ ia32_tracesys: jmp ia32_do_syscall ia32_badsys: + movq $0,ORIG_RAX-ARGOFFSET(%rsp) movq $-ENOSYS,RAX-ARGOFFSET(%rsp) jmp int_ret_from_sys_call @@ -84,6 +85,10 @@ ni_syscall: movq %rax,%rdi jmp sys32_ni_syscall +quiet_ni_syscall: + movq $-ENOSYS,%rax + ret + .macro PTREGSCALL label, func .globl \label \label: @@ -229,7 +234,7 @@ ia32_sys_call_table: .quad stub32_iopl /* 110 */ .quad sys_vhangup .quad ni_syscall /* old "idle" system call */ - .quad ni_syscall /* vm86old */ + .quad sys32_vm86_warning /* vm86old */ .quad sys32_wait4 .quad sys_swapoff /* 115 */ .quad sys32_sysinfo @@ -238,7 +243,7 @@ ia32_sys_call_table: .quad stub32_sigreturn .quad stub32_clone /* 120 */ .quad sys_setdomainname - .quad sys32_newuname + .quad sys_uname .quad sys_modify_ldt .quad sys32_adjtimex .quad sys32_mprotect /* 125 */ @@ -282,8 +287,8 @@ ia32_sys_call_table: .quad sys_mremap .quad sys_setresuid16 .quad sys_getresuid16 /* 165 */ - .quad ni_syscall /* vm86 */ - .quad ni_syscall /* query_module */ + .quad sys32_vm86_warning /* vm86 */ + .quad quiet_ni_syscall /* query_module */ .quad sys_poll .quad sys32_nfsservctl .quad sys_setresgid16 /* 170 */ @@ -368,7 +373,7 @@ ia32_sys_call_table: .quad sys_io_cancel .quad sys_ni_syscall /* 250 alloc_huge_pages */ .quad sys_ni_syscall /* free_huge_pages */ - .quad sys_ni_syscall /* exit_group */ + .quad sys_exit_group /* exit_group */ ia32_syscall_end: .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 .quad ni_syscall diff --git a/arch/x86_64/ia32/ipc32.c b/arch/x86_64/ia32/ipc32.c index e441f93a3f98..d8e7eebcfc22 100644 --- a/arch/x86_64/ia32/ipc32.c +++ b/arch/x86_64/ia32/ipc32.c @@ -264,6 +264,9 @@ semctl32 (int first, int second, int third, void *uptr) if (err2) err = -EFAULT; break; + default: + err = -EINVAL; + break; } return err; } @@ -284,7 +287,7 @@ do_sys32_msgsnd (int first, int second, int third, void *uptr) if (!p) return -ENOMEM; err = get_user(p->mtype, &up->mtype); - err |= copy_from_user(p->mtext, &up->mtext, second); + err |= (copy_from_user(p->mtext, &up->mtext, second) ? -EFAULT : 0); if (err) goto out; old_fs = get_fs(); diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index d56ddadce445..6039be04e21e 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -35,7 +35,6 @@ #include <linux/smp_lock.h> #include <linux/sem.h> #include <linux/msg.h> -#include <linux/binfmts.h> #include <linux/mm.h> #include <linux/shm.h> #include <linux/slab.h> @@ -56,6 +55,7 @@ #include <linux/stat.h> #include <linux/ipc.h> #include <linux/rwsem.h> +#include <linux/binfmts.h> #include <linux/init.h> #include <linux/aio_abi.h> #include <asm/mman.h> @@ -264,8 +264,11 @@ sys32_mmap(struct mmap_arg_struct *arg) if (!file) return -EBADF; } + +#if 0 /* reenable when noexec works */ if (a.prot & PROT_READ) a.prot |= PROT_EXEC; +#endif a.flags |= MAP_32BIT; @@ -275,8 +278,8 @@ sys32_mmap(struct mmap_arg_struct *arg) if (file) fput(file); - /* Should not happen */ - if (retval >= 0xFFFFFFFF && (long)retval > 0) { + /* Cannot wrap */ + if (retval+a.len >= 0xFFFFFFFF && (long)retval > 0) { do_munmap(mm, retval, a.len); retval = -ENOMEM; } @@ -964,22 +967,24 @@ sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp) asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long); asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long); -struct iovec * -get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type) +static struct iovec * +get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) { int i; u32 buf, len; struct iovec *ivp, *iov; + unsigned long totlen; /* Get the "struct iovec" from user memory */ if (!count) return 0; - if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) - return(struct iovec *)0; if (count > UIO_MAXIOV) return(struct iovec *)0; + if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) + return(struct iovec *)0; if (count > UIO_FASTIOV) { + *errp = -ENOMEM; iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); if (!iov) return((struct iovec *)0); @@ -987,24 +992,33 @@ get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type) iov = iov_buf; ivp = iov; + totlen = 0; for (i = 0; i < count; i++) { - if (__get_user(len, &iov32->iov_len) || - __get_user(buf, &iov32->iov_base)) { - if (iov != iov_buf) - kfree(iov); - return((struct iovec *)0); - } - if (verify_area(type, (void *)A(buf), len)) { - if (iov != iov_buf) - kfree(iov); - return((struct iovec *)0); - } + *errp = __get_user(len, &iov32->iov_len) | + __get_user(buf, &iov32->iov_base); + if (*errp) + goto error; + *errp = verify_area(type, (void *)A(buf), len); + if (*errp) + goto error; + /* SuS checks: */ + *errp = -EINVAL; + if ((int)len < 0) + goto error; + if ((totlen += len) >= 0x7fffffff) + goto error; ivp->iov_base = (void *)A(buf); ivp->iov_len = (__kernel_size_t)len; iov32++; ivp++; } + *errp = 0; return(iov); + +error: + if (iov != iov_buf) + kfree(iov); + return NULL; } asmlinkage long @@ -1015,8 +1029,8 @@ sys32_readv(int fd, struct iovec32 *vector, u32 count) int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE)) == (struct iovec *)0) - return -EFAULT; + if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) + return ret; set_fs(KERNEL_DS); ret = sys_readv(fd, iov, count); set_fs(old_fs); @@ -1033,8 +1047,8 @@ sys32_writev(int fd, struct iovec32 *vector, u32 count) int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ)) == (struct iovec *)0) - return -EFAULT; + if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) + return ret; set_fs(KERNEL_DS); ret = sys_writev(fd, iov, count); set_fs(old_fs); @@ -1121,7 +1135,7 @@ sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) /* * sys_time() can be implemented in user-level using - * sys_gettimeofday(). IA64 did this but i386 Linux did not + * sys_gettimeofday(). x86-64 did this but i386 Linux did not * so we have to implement this system call here. */ asmlinkage long sys32_time(int * tloc) @@ -1288,6 +1302,39 @@ static inline int put_flock(struct flock *kfl, struct flock32 *ufl) } extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); +asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg); + + +asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case F_GETLK: + case F_SETLK: + case F_SETLKW: + { + struct flock f; + mm_segment_t old_fs; + long ret; + + if (get_flock(&f, (struct flock32 *)arg)) + return -EFAULT; + old_fs = get_fs(); set_fs (KERNEL_DS); + ret = sys_fcntl(fd, cmd, (unsigned long)&f); + set_fs (old_fs); + if (ret) return ret; + if (put_flock(&f, (struct flock32 *)arg)) + return -EFAULT; + return 0; + } + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: + return sys32_fcntl64(fd,cmd,arg); + + default: + return sys_fcntl(fd, cmd, (unsigned long)arg); + } +} static inline int get_flock64(struct ia32_flock64 *fl32, struct flock *fl64) { @@ -1319,40 +1366,34 @@ asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long a { struct flock fl64; mm_segment_t oldfs = get_fs(); - int ret = 0, origcmd; - unsigned long origarg; + int ret = 0; + int oldcmd = cmd; + unsigned long oldarg = arg; - origcmd = cmd; - origarg = arg; switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - ret = get_flock(&fl64, (struct flock32 *)arg); - arg = (unsigned long) &fl64; - set_fs(KERNEL_DS); - break; case F_GETLK64: cmd = F_GETLK; - goto cnv64; + goto cnv; case F_SETLK64: cmd = F_SETLK; - goto cnv64; + goto cnv; case F_SETLKW64: cmd = F_SETLKW; - cnv64: + cnv: ret = get_flock64((struct ia32_flock64 *)arg, &fl64); arg = (unsigned long)&fl64; set_fs(KERNEL_DS); break; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + return sys32_fcntl(fd,cmd,arg); } if (!ret) ret = sys_fcntl(fd, cmd, arg); set_fs(oldfs); - if (origcmd == F_GETLK && !ret) - ret = put_flock(&fl64, (struct flock32 *)origarg); - else if (cmd == F_GETLK && !ret) - ret = put_flock64((struct ia32_flock64 *)origarg, &fl64); + if (oldcmd == F_GETLK64 && !ret) + ret = put_flock64((struct ia32_flock64 *)oldarg, &fl64); return ret; } @@ -1804,19 +1845,6 @@ sys32_sysctl(struct sysctl_ia32 *args32) #endif } -extern asmlinkage long sys_newuname(struct new_utsname * name); - -asmlinkage long -sys32_newuname(struct new_utsname * name) -{ - int ret = sys_newuname(name); - - if (current->personality == PER_LINUX32 && !ret) { - ret = copy_to_user(name->machine, "i686\0\0", 6); - } - return ret; -} - extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, size_t count, loff_t pos); @@ -1825,7 +1853,8 @@ extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, typedef __kernel_ssize_t32 ssize_t32; -/* warning. next two assume LE */ + +/* warning: next two assume little endian */ asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count, u32 poslo, u32 poshi) @@ -1849,7 +1878,8 @@ asmlinkage long sys32_personality(unsigned long personality) { int ret; - if (current->personality == PER_LINUX32 && personality == PER_LINUX) + if (personality(current->personality) == PER_LINUX32 && + personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); if (ret == PER_LINUX32) @@ -1956,42 +1986,39 @@ sys32_adjtimex(struct timex32 *utp) return ret; } - -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, +asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - int error = -EBADF; + struct mm_struct *mm = current->mm; + unsigned long error; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) - goto out; + return -EBADF; } - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); + /* later add PROT_EXEC for PROT_READ here */ + + down_write(&mm->mmap_sem); + error = do_mmap_pgoff(file, addr, len, prot, flags|MAP_32BIT, pgoff); + up_write(&mm->mmap_sem); + + /* cannot wrap */ + if (error+len >= 0xFFFFFFFF && (long)error >= 0) { + do_munmap(mm, error, len); + error = -ENOMEM; + } if (file) fput(file); -out: return error; } -asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - - -asmlinkage int sys32_olduname(struct oldold_utsname * name) +asmlinkage long sys32_olduname(struct oldold_utsname * name) { int error; @@ -2581,6 +2608,19 @@ long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p) return ret; } + +int sys32_vm86_warning(void) +{ + static long warn_time = -(60*HZ); + if (time_before(warn_time + 60*HZ,jiffies)) { + printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n", + current->comm); + warn_time = jiffies; + } + return -ENOSYS ; +} + + struct exec_domain ia32_exec_domain = { .name = "linux/x86", .pers_low = PER_LINUX32, diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index f4fde633c039..606bb3f46405 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -9,7 +9,7 @@ export-objs := mtrr.o x8664_ksyms.o pci-gart.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bluesmoke.o bootflag.o e820.o reboot.o + setup64.o bluesmoke.o bootflag.o e820.o reboot.o profile.o obj-$(CONFIG_MTRR) += mtrr.o obj-$(CONFIG_X86_MSR) += msr.o diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 6d6905297e00..6bc56ac417bf 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -897,17 +897,9 @@ int setup_profiling_timer(unsigned int multiplier) inline void smp_local_timer_interrupt(struct pt_regs *regs) { - int user = user_mode(regs); int cpu = smp_processor_id(); - /* - * The profiling function is SMP safe. (nothing can mess - * around with "current", and the profiling counters are - * updated with atomic operations). This is especially - * useful with a profiling multiplier != 1 - */ - if (!user) - x86_do_profile(regs->rip); + x86_do_profile(regs); if (--prof_counter[cpu] <= 0) { /* @@ -925,7 +917,7 @@ inline void smp_local_timer_interrupt(struct pt_regs *regs) } #ifdef CONFIG_SMP - update_process_times(user); + update_process_times(user_mode(regs)); #endif } @@ -951,8 +943,6 @@ inline void smp_local_timer_interrupt(struct pt_regs *regs) */ void smp_apic_timer_interrupt(struct pt_regs *regs) { - int cpu = smp_processor_id(); - /* * the NMI deadlock-detector uses this. */ @@ -1084,11 +1074,13 @@ int __init APIC_init_uniprocessor (void) static __init int setup_disableapic(char *str) { disable_apic = 1; + return 0; } static __init int setup_noapictimer(char *str) { disable_apic_timer = 1; + return 0; } __setup("disableapic", setup_disableapic); diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index 0b397c901511..92ca3b015fc8 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -785,7 +785,7 @@ void __init mp_register_ioapic ( mp_ioapic_routing[idx].irq_end = irq_base + io_apic_get_redir_entries(idx); - printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " + printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, mp_ioapic_routing[idx].irq_start, diff --git a/arch/x86_64/kernel/mtrr.c b/arch/x86_64/kernel/mtrr.c index 9d478fa81f6b..26325a4a579c 100644 --- a/arch/x86_64/kernel/mtrr.c +++ b/arch/x86_64/kernel/mtrr.c @@ -646,7 +646,7 @@ int mtrr_add_page (u64 base, u32 size, unsigned int type, char increment) } if (base & (size_or_mask>>PAGE_SHIFT)) { - printk (KERN_WARNING "mtrr: base(%lx) exceeds the MTRR width(%lx)\n", + printk (KERN_WARNING "mtrr: base(%Lx) exceeds the MTRR width(%Lx)\n", (unsigned long) base, (unsigned long) (size_or_mask>>PAGE_SHIFT)); return -EINVAL; diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index ddc060329c9a..e6d6b251367f 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -23,6 +23,7 @@ #include <asm/smp.h> #include <asm/mtrr.h> #include <asm/mpspec.h> +#include <asm/nmi.h> unsigned int nmi_watchdog = NMI_LOCAL_APIC; static unsigned int nmi_hz = HZ; @@ -137,6 +138,18 @@ static int nmi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) return 0; } +struct pm_dev * set_nmi_pm_callback(pm_callback callback) +{ + apic_pm_unregister(nmi_pmdev); + return apic_pm_register(PM_SYS_DEV, 0, callback); +} + +void unset_nmi_pm_callback(struct pm_dev * dev) +{ + apic_pm_unregister(dev); + nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback); +} + static void nmi_pm_init(void) { if (!nmi_pmdev) @@ -178,7 +191,7 @@ static void __pminit setup_k7_watchdog(void) | K7_NMI_EVENT; wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); - printk(KERN_INFO "watchdog: setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000)); + printk(KERN_INFO "watchdog: setting K7_PERFCTR0 to %08x\n", -(cpu_khz/nmi_hz*1000)); wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1); apic_write(APIC_LVTPC, APIC_DM_NMI); evntsel |= K7_EVNTSEL_ENABLE; @@ -275,3 +288,30 @@ void nmi_watchdog_tick (struct pt_regs * regs) if (nmi_perfctr_msr) wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1); } + +static int dummy_nmi_callback(struct pt_regs * regs, int cpu) +{ + return 0; +} + +static nmi_callback_t nmi_callback = dummy_nmi_callback; + +asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +{ + int cpu = smp_processor_id(); + + add_pda(__nmi_count,1); + + if (!nmi_callback(regs, cpu)) + default_do_nmi(regs); +} + +void set_nmi_callback(nmi_callback_t callback) +{ + nmi_callback = callback; +} + +void unset_nmi_callback(void) +{ + nmi_callback = dummy_nmi_callback; +} diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 2113d078275a..0dbfe91c9c9c 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -32,6 +32,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/user.h> +#include <linux/module.h> #include <linux/a.out.h> #include <linux/interrupt.h> #include <linux/config.h> diff --git a/arch/x86_64/kernel/profile.c b/arch/x86_64/kernel/profile.c new file mode 100644 index 000000000000..334af20585cb --- /dev/null +++ b/arch/x86_64/kernel/profile.c @@ -0,0 +1,45 @@ +/* + * linux/arch/i386/kernel/profile.c + * + * (C) 2002 John Levon <levon@movementarian.org> + * + */ + +#include <linux/profile.h> +#include <linux/spinlock.h> +#include <linux/notifier.h> +#include <linux/irq.h> +#include <asm/hw_irq.h> + +static struct notifier_block * profile_listeners; +static rwlock_t profile_lock = RW_LOCK_UNLOCKED; + +int register_profile_notifier(struct notifier_block * nb) +{ + int err; + write_lock_irq(&profile_lock); + err = notifier_chain_register(&profile_listeners, nb); + write_unlock_irq(&profile_lock); + return err; +} + + +int unregister_profile_notifier(struct notifier_block * nb) +{ + int err; + write_lock_irq(&profile_lock); + err = notifier_chain_unregister(&profile_listeners, nb); + write_unlock_irq(&profile_lock); + return err; +} + + +void x86_profile_hook(struct pt_regs * regs) +{ + /* we would not even need this lock if + * we had a global cli() on register/unregister + */ + read_lock(&profile_lock); + notifier_call_chain(&profile_listeners, 0, regs); + read_unlock(&profile_lock); +} diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index a08766e0d67d..a260d52f756c 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c @@ -8,6 +8,7 @@ #include <asm/io.h> #include <asm/kdebug.h> #include <asm/delay.h> +#include <asm/hw_irq.h> /* diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 7564e806e5c1..26368cee8ec0 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -234,7 +234,6 @@ static void __init contig_initmem_init(void) void __init setup_arch(char **cmdline_p) { - unsigned long bootmap_size, low_mem_size; int i; ROOT_DEV = ORIG_ROOT_DEV; @@ -284,14 +283,8 @@ void __init setup_arch(char **cmdline_p) contig_initmem_init(); - /* - * Reserve the bootmem bitmap itself as well. We do this in two - * steps (first step was init_bootmem()) because this catches - * the (very unlikely) case of us accidentally initializing the - * bootmem allocator with an invalid RAM area. - */ - reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) + - bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY)); + /* reserve kernel */ + reserve_bootmem(HIGH_MEMORY, PFN_PHYS(start_pfn) - HIGH_MEMORY); /* * reserve physical page 0 - it's a special BIOS page on many boxes, diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 53b2b002c491..61ba37b6f4a1 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -559,11 +559,10 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) printk("Do you have a strange power saving mode enabled?\n"); } -asmlinkage void do_nmi(struct pt_regs * regs) +asmlinkage void default_do_nmi(struct pt_regs * regs) { unsigned char reason = inb(0x61); - add_pda(__nmi_count,1); if (!(reason & 0xc0)) { #if CONFIG_X86_LOCAL_APIC /* diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile index 9dbb65684d90..d95a85e2d0d5 100644 --- a/arch/x86_64/mm/Makefile +++ b/arch/x86_64/mm/Makefile @@ -1,13 +1,9 @@ # # Makefile for the linux i386-specific parts of the memory manager. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definition is now in the main makefile... -O_TARGET := mm.o -obj-y := init.o fault.o ioremap.o extable.o modutil.o +export-objs := pageattr.o + +obj-y := init.o fault.o ioremap.o extable.o modutil.o pageattr.o include $(TOPDIR)/Rules.make diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index b222113c97c3..8faa403b596a 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -32,18 +32,14 @@ extern void die(const char *,struct pt_regs *,long); -extern spinlock_t console_lock, timerlist_lock; +extern spinlock_t console_lock; void bust_spinlocks(int yes) { - spin_lock_init(&timerlist_lock); + int loglevel_save = console_loglevel; if (yes) { oops_in_progress = 1; -#ifdef CONFIG_SMP - global_irq_lock = 0; /* Many serial drivers do __global_cli() */ -#endif } else { - int loglevel_save = console_loglevel; #ifdef CONFIG_VT unblank_screen(); #endif @@ -108,6 +104,18 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) int write; siginfo_t info; +#ifdef CONFIG_CHECKING + { + unsigned long gs; + struct x8664_pda *pda = cpu_pda + stack_smp_processor_id(); + rdmsrl(MSR_GS_BASE, gs); + if (gs != (unsigned long)pda) { + wrmsrl(MSR_GS_BASE, pda); + printk("page_fault: wrong gs %lx expected %p\n", gs, pda); + } + } +#endif + /* get the address */ __asm__("movq %%cr2,%0":"=r" (address)); @@ -129,7 +137,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; again: @@ -223,7 +231,7 @@ no_context: /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(regs->rip)) != 0) { regs->rip = fixup; - if (exception_trace) + if (0 && exception_trace) printk(KERN_ERR "%s: fixed kernel exception at %lx address %lx err:%ld\n", current->comm, regs->rip, address, error_code); diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 0c5b3b0e1e49..f9af1cde89a0 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -37,6 +37,8 @@ #include <asm/tlb.h> #include <asm/mmu_context.h> +unsigned long start_pfn, end_pfn; + mmu_gather_t mmu_gathers[NR_CPUS]; /* @@ -49,19 +51,24 @@ void show_mem(void) { int i, total = 0, reserved = 0; int shared = 0, cached = 0; + pg_data_t *pgdat; + struct page *page; printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - i = max_mapnr; - while (i-- > 0) { + + for_each_pgdat(pgdat) { + for (i = 0; i < pgdat->node_size; ++i) { + page = pgdat->node_mem_map + i; total++; - if (PageReserved(mem_map+i)) + if (PageReserved(page)) reserved++; - else if (PageSwapCache(mem_map+i)) + else if (PageSwapCache(page)) cached++; - else if (page_count(mem_map+i)) - shared += page_count(mem_map+i) - 1; + else if (page_count(page)) + shared += page_count(page) - 1; + } } printk("%d pages of RAM\n", total); printk("%d reserved pages\n",reserved); @@ -264,16 +271,15 @@ void __init paging_init(void) { { unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - unsigned int max_dma, low; + unsigned int max_dma; max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; - low = max_low_pfn; - if (low < max_dma) - zones_size[ZONE_DMA] = low; + if (end_pfn < max_dma) + zones_size[ZONE_DMA] = end_pfn; else { zones_size[ZONE_DMA] = max_dma; - zones_size[ZONE_NORMAL] = low - max_dma; + zones_size[ZONE_NORMAL] = end_pfn - max_dma; } free_area_init(zones_size); } @@ -308,11 +314,15 @@ void __init mem_init(void) int codesize, reservedpages, datasize, initsize; int tmp; + printk("mem_init\n"); + if (!mem_map) BUG(); - max_mapnr = num_physpages = max_low_pfn; - high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); + max_low_pfn = end_pfn; + max_pfn = end_pfn; + max_mapnr = num_physpages = end_pfn; + high_memory = (void *) __va(end_pfn * PAGE_SIZE); /* clear the zero-page */ memset(empty_zero_page, 0, PAGE_SIZE); @@ -323,7 +333,7 @@ void __init mem_init(void) after_bootmem = 1; reservedpages = 0; - for (tmp = 0; tmp < max_low_pfn; tmp++) + for (tmp = 0; tmp < end_pfn; tmp++) /* * Only count reserved RAM pages */ diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c index 4f2c33115ef5..c095886d9b16 100644 --- a/arch/x86_64/mm/ioremap.c +++ b/arch/x86_64/mm/ioremap.c @@ -10,6 +10,7 @@ #include <linux/vmalloc.h> #include <linux/init.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/pgalloc.h> #include <asm/fixmap.h> @@ -157,14 +158,72 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag return NULL; addr = area->addr; if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) { - vfree(addr); + vunmap(addr); return NULL; } return (void *) (offset + (char *)addr); } +/** + * ioremap_nocache - map bus memory into CPU space + * @offset: bus address of the memory + * @size: size of the resource to map + * + * ioremap_nocache performs a platform specific sequence of operations to + * make bus memory CPU accessible via the readb/readw/readl/writeb/ + * writew/writel functions and the other mmio helpers. The returned + * address is not guaranteed to be usable directly as a virtual + * address. + * + * This version of ioremap ensures that the memory is marked uncachable + * on the CPU as well as honouring existing caching rules from things like + * the PCI bus. Note that there are other caches and buffers on many + * busses. In particular driver authors should read up on PCI writes + * + * It's useful if some control registers are in such an area and + * write combining or read caching is not desirable: + * + * Must be freed with iounmap. + */ + +void *ioremap_nocache (unsigned long phys_addr, unsigned long size) +{ + void *p = __ioremap(phys_addr, size, _PAGE_PCD); + if (!p) + return p; + + if (phys_addr + size < virt_to_phys(high_memory)) { + struct page *ppage = virt_to_page(__va(phys_addr)); + unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; + + BUG_ON(phys_addr+size > (unsigned long)high_memory); + BUG_ON(phys_addr + size < phys_addr); + + if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { + iounmap(p); + p = NULL; + } + } + + return p; +} + void iounmap(void *addr) { - if (addr > high_memory) - vfree((void *) (PAGE_MASK & (unsigned long) addr)); + struct vm_struct *p; + if (addr <= high_memory) + return; + p = remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr)); + if (!p) { + printk("__iounmap: bad address %p\n", addr); + return; + } + + unmap_vm_area(p); + if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { + change_page_attr(virt_to_page(__va(p->phys_addr)), + p->size >> PAGE_SHIFT, + PAGE_KERNEL); + } + kfree(p); } diff --git a/arch/x86_64/mm/modutil.c b/arch/x86_64/mm/modutil.c index 52751604fd7a..5a5827166a04 100644 --- a/arch/x86_64/mm/modutil.c +++ b/arch/x86_64/mm/modutil.c @@ -13,12 +13,15 @@ #include <asm/uaccess.h> #include <asm/system.h> +#include <asm/page.h> +#include <asm/pgtable.h> static struct vm_struct * modvmlist = NULL; void module_unmap (void * addr) { struct vm_struct **p, *tmp; + int i; if (!addr) return; @@ -29,21 +32,33 @@ void module_unmap (void * addr) for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { *p = tmp->next; - vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size); - kfree(tmp); - return; + goto found; } } printk("Trying to unmap nonexistent module vm area (%p)\n", addr); + return; + found: + unmap_vm_area(tmp); + for (i = 0; i < tmp->nr_pages; i++) { + if (unlikely(!tmp->pages[i])) + BUG(); + __free_page(tmp->pages[i]); + } + + kfree(tmp->pages); + kfree(tmp); } void * module_map (unsigned long size) { - void * addr; struct vm_struct **p, *tmp, *area; + struct page **pages; + void * addr; + unsigned int nr_pages, array_size, i; size = PAGE_ALIGN(size); - if (!size || size > MODULES_LEN) return NULL; + if (!size || size > MODULES_LEN) + return NULL; addr = (void *) MODULES_VADDR; for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) { @@ -51,18 +66,53 @@ void * module_map (unsigned long size) break; addr = (void *) (tmp->size + (unsigned long) tmp->addr); } - if ((unsigned long) addr + size >= MODULES_END) return NULL; + if ((unsigned long) addr + size >= MODULES_END) + return NULL; area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); - if (!area) return NULL; + if (!area) + return NULL; area->size = size + PAGE_SIZE; area->addr = addr; area->next = *p; + area->pages = NULL; + area->nr_pages = 0; + area->phys_addr = 0; *p = area; - if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL)) { - module_unmap(addr); - return NULL; + nr_pages = size >> PAGE_SHIFT; + array_size = (nr_pages * sizeof(struct page *)); + + area->nr_pages = nr_pages; + area->pages = pages = kmalloc(array_size, GFP_KERNEL); + if (!area->pages) + goto fail; + + memset(area->pages, 0, array_size); + + for (i = 0; i < area->nr_pages; i++) { + area->pages[i] = alloc_page(GFP_KERNEL); + if (unlikely(!area->pages[i])) + goto fail; + } + + if (map_vm_area(area, PAGE_KERNEL, &pages)) { + unmap_vm_area(area); + goto fail; } - return addr; + + return area->addr; + +fail: + if (area->pages) { + for (i = 0; i < area->nr_pages; i++) { + if (area->pages[i]) + __free_page(area->pages[i]); + } + kfree(area->pages); + } + kfree(area); + + return NULL; } + diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c new file mode 100644 index 000000000000..3d9e3498d2cc --- /dev/null +++ b/arch/x86_64/mm/pageattr.c @@ -0,0 +1,210 @@ +/* + * Copyright 2002 Andi Kleen, SuSE Labs. + * Thanks to Ben LaHaise for precious feedback. + */ + +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/highmem.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/uaccess.h> +#include <asm/processor.h> +#include <asm/tlbflush.h> +#include <asm/io.h> + +static inline pte_t *lookup_address(unsigned long address) +{ + pgd_t *pgd = pgd_offset_k(address); + pmd_t *pmd; + pte_t *pte; + if (!pgd || !pgd_present(*pgd)) + return NULL; + pmd = pmd_offset(pgd, address); + if (!pmd_present(*pmd)) + return NULL; + if (pmd_large(*pmd)) + return (pte_t *)pmd; + pte = pte_offset_kernel(pmd, address); + if (pte && !pte_present(*pte)) + pte = NULL; + return pte; +} + +static struct page *split_large_page(unsigned long address, pgprot_t prot) +{ + int i; + unsigned long addr; + struct page *base = alloc_pages(GFP_KERNEL, 0); + pte_t *pbase; + if (!base) + return NULL; + address = __pa(address); + addr = address & LARGE_PAGE_MASK; + pbase = (pte_t *)page_address(base); + for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { + pbase[i] = pfn_pte(addr >> PAGE_SHIFT, + addr == address ? prot : PAGE_KERNEL); + } + return base; +} + + +static void flush_kernel_map(void *address) +{ + if (address && cpu_has_clflush) { + /* is this worth it? */ + int i; + for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) + asm volatile("clflush %0" :: "m" (address + i)); + } else + asm volatile("wbinvd":::"memory"); + __flush_tlb_one(address); +} + +/* + * No more special protections in this 2/4MB area - revert to a + * large page again. + */ +static inline void revert_page(struct page *kpte_page, unsigned long address) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t large_pte; + + pgd = pgd_offset_k(address); + if (!pgd) BUG(); + pmd = pmd_offset(pgd, address); + if (!pmd) BUG(); + if ((pmd_val(*pmd) & _PAGE_GLOBAL) == 0) BUG(); + + large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, PAGE_KERNEL_LARGE); + set_pte((pte_t *)pmd, large_pte); +} + +static int +__change_page_attr(unsigned long address, struct page *page, pgprot_t prot, + struct page **oldpage) +{ + pte_t *kpte; + struct page *kpte_page; + unsigned kpte_flags; + + kpte = lookup_address(address); + if (!kpte) return 0; + kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); + kpte_flags = pte_val(*kpte); + if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { + if ((kpte_flags & _PAGE_PSE) == 0) { + pte_t old = *kpte; + pte_t standard = mk_pte(page, PAGE_KERNEL); + + set_pte(kpte, mk_pte(page, prot)); + if (pte_same(old,standard)) + atomic_inc(&kpte_page->count); + } else { + struct page *split = split_large_page(address, prot); + if (!split) + return -ENOMEM; + set_pte(kpte,mk_pte(split, PAGE_KERNEL)); + } + } else if ((kpte_flags & _PAGE_PSE) == 0) { + set_pte(kpte, mk_pte(page, PAGE_KERNEL)); + atomic_dec(&kpte_page->count); + } + + if (atomic_read(&kpte_page->count) == 1) { + *oldpage = kpte_page; + revert_page(kpte_page, address); + } + return 0; +} + +static inline void flush_map(unsigned long address) +{ +#ifdef CONFIG_SMP + smp_call_function(flush_kernel_map, (void *)address, 1, 1); +#endif + flush_kernel_map((void *)address); +} + +struct deferred_page { + struct deferred_page *next; + struct page *fpage; + unsigned long address; +}; +static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */ + +static inline void save_page(unsigned long address, struct page *fpage) +{ + struct deferred_page *df; + df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); + if (!df) { + flush_map(address); + __free_page(fpage); + } else { + df->next = df_list; + df->fpage = fpage; + df->address = address; + df_list = df; + } +} + +/* + * Change the page attributes of an page in the linear mapping. + * + * This should be used when a page is mapped with a different caching policy + * than write-back somewhere - some CPUs do not like it when mappings with + * different caching policies exist. This changes the page attributes of the + * in kernel linear mapping too. + * + * The caller needs to ensure that there are no conflicting mappings elsewhere. + * This function only deals with the kernel linear map. + * + * Caller must call global_flush_tlb() after this. + */ +int change_page_attr(struct page *page, int numpages, pgprot_t prot) +{ + int err = 0; + struct page *fpage, *fpage2; + int i; + + down_write(&init_mm.mmap_sem); + for (i = 0; i < numpages; i++, page++) { + unsigned long address = (unsigned long)page_address(page); + fpage = NULL; + err = __change_page_attr(address, page, prot, &fpage); + /* Handle kernel mapping too which aliases part of the lowmem */ + if (!err && page_to_phys(page) < KERNEL_TEXT_SIZE) { + unsigned long addr2 = __START_KERNEL_map + page_to_phys(page); + fpage2 = NULL; + err = __change_page_attr(addr2, page, prot, &fpage2); + if (fpage2) + save_page(addr2, fpage2); + } + if (fpage) + save_page(address, fpage); + } + up_write(&init_mm.mmap_sem); + return err; +} + +void global_flush_tlb(void) +{ + struct deferred_page *df, *next_df; + + down_read(&init_mm.mmap_sem); + df = xchg(&df_list, NULL); + up_read(&init_mm.mmap_sem); + flush_map((df && !df->next) ? df->address : 0); + for (; df; df = next_df) { + next_df = df->next; + if (df->fpage) + __free_page(df->fpage); + kfree(df); + } +} + +EXPORT_SYMBOL(change_page_attr); +EXPORT_SYMBOL(global_flush_tlb); diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h index 811c69f8743d..9d7d039d5222 100644 --- a/include/asm-x86_64/hw_irq.h +++ b/include/asm-x86_64/hw_irq.h @@ -20,6 +20,10 @@ #include <linux/config.h> #include <asm/atomic.h> #include <asm/irq.h> +#include <linux/profile.h> +#include <linux/smp.h> + +struct hw_interrupt_type; #endif /* @@ -126,20 +130,23 @@ __asm__( \ "push $" #nr "-256 ; " \ "jmp common_interrupt"); -extern unsigned long prof_cpu_mask; -extern unsigned int * prof_buffer; -extern unsigned long prof_len; -extern unsigned long prof_shift; - -/* - * x86 profiling function, SMP safe. We might want to do this in - * assembly totally? - */ -static inline void x86_do_profile (unsigned long rip) +static inline void x86_do_profile (struct pt_regs *regs) { + unsigned long rip; + extern unsigned long prof_cpu_mask; + extern char _stext; +#ifdef CONFIG_PROFILING + extern void x86_profile_hook(struct pt_regs *); + + x86_profile_hook(regs); +#endif + if (user_mode(regs)) + return; if (!prof_buffer) return; + rip = regs->rip; + /* * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. * (default is all CPUs.) @@ -159,6 +166,11 @@ static inline void x86_do_profile (unsigned long rip) atomic_inc((atomic_t *)&prof_buffer[rip]); } +struct notifier_block; + +int register_profile_notifier(struct notifier_block * nb); +int unregister_profile_notifier(struct notifier_block * nb); + #ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */ static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { if (IO_APIC_IRQ(i)) diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h index 7830bf40cfd4..23be4a85e415 100644 --- a/include/asm-x86_64/ia32.h +++ b/include/asm-x86_64/ia32.h @@ -235,11 +235,6 @@ struct iovec32 { }; -#ifdef __KERNEL__ -struct iovec *get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type); -#endif - - #endif /* !CONFIG_IA32_SUPPORT */ #endif diff --git a/include/asm-x86_64/ide.h b/include/asm-x86_64/ide.h index 8e0ad03131b3..ac0d00e0d535 100644 --- a/include/asm-x86_64/ide.h +++ b/include/asm-x86_64/ide.h @@ -5,7 +5,7 @@ */ /* - * This file contains the i386 architecture specific IDE code. + * This file contains the x86_64 architecture specific IDE code. */ #ifndef __ASMx86_64_IDE_H diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h index 6a460b5f5340..8cee542f40f4 100644 --- a/include/asm-x86_64/io_apic.h +++ b/include/asm-x86_64/io_apic.h @@ -148,9 +148,18 @@ extern int io_apic_get_redir_entries (int ioapic); extern int io_apic_set_pci_routing (int ioapic, int pin, int irq); #endif +#ifdef CONFIG_ACPI_BOOT +extern int io_apic_get_unique_id (int ioapic, int apic_id); +extern int io_apic_get_version (int ioapic); +extern int io_apic_get_redir_entries (int ioapic); +extern int io_apic_set_pci_routing (int ioapic, int pin, int irq); +#endif + #else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 #endif +void enable_NMI_through_LVT0 (void * dummy); + #endif diff --git a/include/asm-x86_64/ioctl32.h b/include/asm-x86_64/ioctl32.h new file mode 100644 index 000000000000..d0d227f45e05 --- /dev/null +++ b/include/asm-x86_64/ioctl32.h @@ -0,0 +1 @@ +#include <linux/ioctl32.h> diff --git a/include/asm-x86_64/ipc.h b/include/asm-x86_64/ipc.h index c6f281e673ff..8736ba68c118 100644 --- a/include/asm-x86_64/ipc.h +++ b/include/asm-x86_64/ipc.h @@ -1,5 +1,5 @@ -#ifndef __x86_64_IPC_H__ -#define __x86_64_IPC_H__ +#ifndef __x8664_IPC_H__ +#define __x8664_IPC_H__ /* dummy */ diff --git a/include/asm-x86_64/ipcbuf.h b/include/asm-x86_64/ipcbuf.h index 0dcad4f84c2a..470cf85e3ba8 100644 --- a/include/asm-x86_64/ipcbuf.h +++ b/include/asm-x86_64/ipcbuf.h @@ -1,8 +1,8 @@ -#ifndef __i386_IPCBUF_H__ -#define __i386_IPCBUF_H__ +#ifndef __x86_64_IPCBUF_H__ +#define __x86_64_IPCBUF_H__ /* - * The ipc64_perm structure for i386 architecture. + * The ipc64_perm structure for x86_64 architecture. * Note extra padding because this structure is passed back and forth * between kernel and user space. * @@ -26,4 +26,4 @@ struct ipc64_perm unsigned long __unused2; }; -#endif /* __i386_IPCBUF_H__ */ +#endif /* __x86_64_IPCBUF_H__ */ diff --git a/include/asm-x86_64/namei.h b/include/asm-x86_64/namei.h index c6f90b5cf0af..bef239f5318f 100644 --- a/include/asm-x86_64/namei.h +++ b/include/asm-x86_64/namei.h @@ -1,9 +1,3 @@ -/* $Id: namei.h,v 1.2 2001/07/04 09:08:13 ak Exp $ - * linux/include/asm-i386/namei.h - * - * Included from linux/fs/namei.c - */ - #ifndef __X8664_NAMEI_H #define __X8664_NAMEI_H diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h new file mode 100644 index 000000000000..d20f0fb9ad2b --- /dev/null +++ b/include/asm-x86_64/nmi.h @@ -0,0 +1,49 @@ +/* + * linux/include/asm-i386/nmi.h + */ +#ifndef ASM_NMI_H +#define ASM_NMI_H + +#include <linux/pm.h> + +struct pt_regs; + +typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu); + +/** + * set_nmi_callback + * + * Set a handler for an NMI. Only one handler may be + * set. Return 1 if the NMI was handled. + */ +void set_nmi_callback(nmi_callback_t callback); + +/** + * unset_nmi_callback + * + * Remove the handler previously set. + */ +void unset_nmi_callback(void); + +#ifdef CONFIG_PM + +/** Replace the PM callback routine for NMI. */ +struct pm_dev * set_nmi_pm_callback(pm_callback callback); + +/** Unset the PM callback routine back to the default. */ +void unset_nmi_pm_callback(struct pm_dev * dev); + +#else + +static inline struct pm_dev * set_nmi_pm_callback(pm_callback callback) +{ + return 0; +} + +static inline void unset_nmi_pm_callback(struct pm_dev * dev) +{ +} + +#endif /* CONFIG_PM */ + +#endif /* ASM_NMI_H */ diff --git a/include/asm-x86_64/param.h b/include/asm-x86_64/param.h index 3921e50c76b2..ef316e2cb5e2 100644 --- a/include/asm-x86_64/param.h +++ b/include/asm-x86_64/param.h @@ -2,7 +2,7 @@ #define _ASMx86_64_PARAM_H #ifdef __KERNEL__ -# define HZ 100 /* Internal kernel timer frequency */ +# define HZ 1000 /* Internal kernel timer frequency */ # define USER_HZ 100 /* .. some user interfaces are in "ticks */ #define CLOCKS_PER_SEC (USER_HZ) /* like times() */ #endif diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index b580f59b7649..aee29a94ba84 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -42,6 +42,7 @@ extern void exception_table_check(void); extern void acpi_boot_init(char *); +int iommu_setup(char *opt); #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) #define round_down(x,y) ((x) & ~((y)-1)) diff --git a/include/asm-x86_64/softirq.h b/include/asm-x86_64/softirq.h index 23fa952e98e4..436bdc869980 100644 --- a/include/asm-x86_64/softirq.h +++ b/include/asm-x86_64/softirq.h @@ -9,6 +9,8 @@ #define __local_bh_enable() \ do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0) +void do_softirq(void); + #define local_bh_enable() \ do { \ __local_bh_enable(); \ diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 3faf01e59d61..50fa45bc8d9c 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -482,8 +482,10 @@ __SYSCALL(__NR_io_submit, sys_io_submit) __SYSCALL(__NR_io_cancel, sys_io_cancel) #define __NR_get_thread_area 211 __SYSCALL(__NR_get_thread_area, sys_get_thread_area) +#define __NR_lookup_dcookie 212 +__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie) -#define __NR_syscall_max __NR_get_thread_area +#define __NR_syscall_max __NR_lookup_dcookie #ifndef __NO_STUBS /* user-visible error numbers are in the range -1 - -4095 */ @@ -503,7 +505,6 @@ do { \ #define __syscall "syscall" -/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ #define _syscall0(type,name) \ type name(void) \ { \ diff --git a/include/linux/ioctl32.h b/include/linux/ioctl32.h new file mode 100644 index 000000000000..b7abfe6eae10 --- /dev/null +++ b/include/linux/ioctl32.h @@ -0,0 +1,23 @@ +#ifndef IOCTL32_H +#define IOCTL32_H 1 + +struct file; + +int sys_ioctl(unsigned int, unsigned int, unsigned long); + +/* + * Register an 32bit ioctl translation handler for ioctl cmd. + * + * handler == NULL: use 64bit ioctl handler. + * arguments to handler: fd: file descriptor + * cmd: ioctl command. + * arg: ioctl argument + * struct file *file: file descriptor pointer. + */ + +extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); + +extern int unregister_ioctl32_conversion(unsigned int cmd); + + +#endif |
