Commit 88e4bc32 authored by Andi Kleen's avatar Andi Kleen Committed by Russell King

[PATCH] x86-64 architecture specific sync for 2.5.8

This patch brings 2.5.8 in sync with the x86-64 2.4 development tree again
(excluding device drivers)

It has lots of bug fixes and enhancements. It only touches architecture
specific files.

- Sync with 2.5.8
- SMP/APIC supported now.
- Module loading works now.
- Time keeping bugs fixed.
- entry.S streamlined and some bugs fixed.
- modify_ldt works now
- mostly rewritten FPU support (including FXRSTOR for initial FPU
  initialization based on the initial state)
- 32bit emulation enhanced and bugs fixed.
- rewrote mm initialization and lots of cleanups in the page table handling
  __PAGE_OFFSET is now moved to 0x10000000000 and some vmalloc/ioremap
  problems have been fixed. They have an own PML4 slot now.
- WCHAN reporting support for RIP (but not RSP)
- Lots of various other bug fixes and cleanups.

Currently broken:
- ACPI
- MTRR

It needs some other bugfixes outside architecture specific code. I sent
them all in separate mail.
parent 61aacaa2
...@@ -396,33 +396,31 @@ CONFIG_PM ...@@ -396,33 +396,31 @@ CONFIG_PM
sending the processor to sleep and saving power. sending the processor to sleep and saving power.
CONFIG_ACPI CONFIG_ACPI
ACPI/OSPM support for Linux is currently under development. As such, Advanced Configuration and Power Interface (ACPI) support for
this support is preliminary and EXPERIMENTAL. Configuring ACPI Linux requires an ACPI compliant platform (hardware/firmware),
support enables kernel interfaces that allow higher level software and assumes the presence of OS-directed configuration and power
(OSPM) to manipulate ACPI defined hardware and software interfaces, management (OSPM) software.
including the evaluation of ACPI control methods. If unsure, choose
N here. Note, this option will enlarge your kernel by about 120K. Linux ACPI provides a robust functional replacement for several
legacy configuration and power management intefaces, including
This support requires an ACPI compliant platform (hardware/firmware). the Plug-and-Play BIOS specification (PnP BIOS), the
If both ACPI and Advanced Power Management (APM) support are MultiProcessor Specification (MPS), and the Advanced Power
configured, whichever is loaded first shall be used. Management (APM) specification. If both ACPI and APM support
are configured, whichever is loaded first shall be used.
This code DOES NOT currently provide a complete OSPM implementation
-- it has not yet reached APM's level of functionality. When fully The ACPI SourceForge project contains the latest source code,
implemented, Linux ACPI/OSPM will provide a more robust functional documentation, tools, mailing list subscription, and other
replacement for legacy configuration and power management information. This project is available at:
interfaces, including the Plug-and-Play BIOS specification (PnP <http://sourceforge.net/projects/acpi>
BIOS), the Multi-Processor Specification (MPS), and the Advanced
Power Management specification (APM). Linux support for ACPI is based on Intel Corporation's ACPI
Component Architecture (ACPI CA). For more information see:
Linux support for ACPI/OSPM is based on Intel Corporation's ACPI <http://developer.intel.com/technology/iapc/acpi>
Component Architecture (ACPI CA). The latest ACPI CA source code,
documentation, debug builds, and implementation status information ACPI is an open industry specification co-developed by Compaq,
can be downloaded from: Intel, Microsoft, Phoenix, and Toshiba. The specification is
<http://developer.intel.com/technology/iapc/acpi/downloads.htm>. available at:
<http://www.acpi.info>
The ACPI Sourceforge project may also be of interest:
<http://sf.net/projects/acpi/>
CONFIG_X86_MSR CONFIG_X86_MSR
This device gives privileged processes access to the x86 This device gives privileged processes access to the x86
...@@ -437,34 +435,6 @@ CONFIG_X86_CPUID ...@@ -437,34 +435,6 @@ CONFIG_X86_CPUID
with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
/dev/cpu/31/cpuid. /dev/cpu/31/cpuid.
CONFIG_SOUND
If you have a sound card in your computer, i.e. if it can say more
than an occasional beep, say Y. Be sure to have all the information
about your sound card and its configuration down (I/O port,
interrupt and DMA channel), because you will be asked for it.
You want to read the Sound-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>. General information about
the modular sound system is contained in the files
<file:Documentation/sound/Introduction>. The file
<file:Documentation/sound/README.OSS> contains some slightly
outdated but still useful information as well.
If you have a PnP sound card and you want to configure it at boot
time using the ISA PnP tools (read
<http://www.roestock.demon.co.uk/isapnptools/>), then you need to
compile the sound card support as a module ( = code which can be
inserted in and removed from the running kernel whenever you want)
and load that module after the PnP configuration is finished. To do
this, say M here and read <file:Documentation/modules.txt> as well
as <file:Documentation/sound/README.modules>; the module will be
called soundcore.o.
I'm told that even without a sound card, you can make your computer
say more than an occasional beep, by programming the PC speaker.
Kernel patches and supporting utilities to do that are in the pcsp
package, available at <ftp://ftp.infradead.org/pub/pcsp/>.
CONFIG_PREEMPT CONFIG_PREEMPT
This option reduces the latency of the kernel when reacting to This option reduces the latency of the kernel when reacting to
real-time or interactive events by allowing a low priority process to real-time or interactive events by allowing a low priority process to
...@@ -529,3 +499,13 @@ CONFIG_EARLY_PRINTK ...@@ -529,3 +499,13 @@ CONFIG_EARLY_PRINTK
klogd/syslogd or the X server.You should normally N here, unless klogd/syslogd or the X server.You should normally N here, unless
you want to debug such a crash. 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)
...@@ -17,20 +17,19 @@ ...@@ -17,20 +17,19 @@
# 20000913 Pavel Machek <pavel@suse.cz> # 20000913 Pavel Machek <pavel@suse.cz>
# Converted for x86_64 architecture # Converted for x86_64 architecture
# 20010105 Andi Kleen, add IA32 compiler. # 20010105 Andi Kleen, add IA32 compiler.
# ....and later removed it again....
# #
# $Id: Makefile,v 1.28 2001/06/29 17:47:43 aj Exp $ # $Id: Makefile,v 1.31 2002/03/22 15:56:07 ak Exp $
# #
# boot system currently needs IA32 tools to link (to be fixed) # early bootup linking needs 32bit. You can either use real 32bit tools
# here or 64bit tools switch to 32bit mode.
# #
# Change this to your i386 compiler/binutils IA32_CC := $(CROSS_COMPILE)gcc -m32 -O2 -fomit-frame-pointer -nostdinc -I $(HPATH)
IA32_PREFIX := /usr/bin/ IA32_LD := $(CROSS_COMPILE)ld -m elf_i386
IA32_CC := $(IA32_PREFIX)gcc -O2 -fomit-frame-pointer -nostdinc -I $(HPATH) IA32_AS := $(CROSS_COMPILE)gcc -m32 -Wa,--32 -D__ASSEMBLY__ -traditional -c -nostdinc -I $(HPATH)
IA32_LD := $(IA32_PREFIX)ld IA32_OBJCOPY := $(CROSS_COMPILE)objcopy
IA32_AS := $(IA32_PREFIX)gcc -D__ASSEMBLY__ -traditional -c -nostdinc -I $(HPATH) IA32_CPP := $(CROSS_COMPILE)gcc -m32 -E
IA32_OBJCOPY := $(IA32_PREFIX)objcopy
IA32_CPP := $(IA32_PREFIX)gcc -E
export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP
...@@ -39,16 +38,14 @@ OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S ...@@ -39,16 +38,14 @@ OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
LDFLAGS=-e stext LDFLAGS=-e stext
LINKFLAGS =-T $(TOPDIR)/arch/x86_64/vmlinux.lds $(LDFLAGS) LINKFLAGS =-T $(TOPDIR)/arch/x86_64/vmlinux.lds $(LDFLAGS)
CFLAGS += $(shell if $(CC) -mno-red-zone -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mno-red-zone"; fi ) CFLAGS += -mno-red-zone
CFLAGS += -mcmodel=kernel CFLAGS += -mcmodel=kernel
CFLAGS += -pipe CFLAGS += -pipe
# generates worse code, but makes the assembly much more readable:
CFLAGS += -fno-reorder-blocks CFLAGS += -fno-reorder-blocks
# work around early gcc 3.1 bugs. Later snapshots should this already fixed. # needed for later gcc 3.1
CFLAGS += -finline-limit=2000
# needed for earlier gcc 3.1
CFLAGS += -fno-strength-reduce CFLAGS += -fno-strength-reduce
# make sure all inline functions are inlined
CFLAGS += -finline-limit=3000
#CFLAGS += -g #CFLAGS += -g
# prevent gcc from keeping the stack 16 byte aligned (FIXME) # prevent gcc from keeping the stack 16 byte aligned (FIXME)
...@@ -61,8 +58,6 @@ CORE_FILES := arch/x86_64/kernel/kernel.o $(CORE_FILES) ...@@ -61,8 +58,6 @@ CORE_FILES := arch/x86_64/kernel/kernel.o $(CORE_FILES)
CORE_FILES += arch/x86_64/mm/mm.o CORE_FILES += arch/x86_64/mm/mm.o
LIBS := $(TOPDIR)/arch/x86_64/lib/lib.a $(LIBS) LIBS := $(TOPDIR)/arch/x86_64/lib/lib.a $(LIBS)
CLEAN_FILES += include/asm-x86_64/offset.h
ifdef CONFIG_IA32_EMULATION ifdef CONFIG_IA32_EMULATION
SUBDIRS += arch/x86_64/ia32 SUBDIRS += arch/x86_64/ia32
CORE_FILES += arch/x86_64/ia32/ia32.o CORE_FILES += arch/x86_64/ia32/ia32.o
...@@ -88,14 +83,14 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot ...@@ -88,14 +83,14 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
vmlinux: arch/x86_64/vmlinux.lds vmlinux: arch/x86_64/vmlinux.lds
checkoffset: FORCE
make -C arch/$(ARCH)/tools $(TOPDIR)/include/asm-x86_64/offset.h
FORCE: ; FORCE: ;
.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \ .PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
clean archclean archmrproper archdep checkoffset clean archclean archmrproper archdep checkoffset
checkoffset: FORCE
make -C arch/$(ARCH)/tools $(TOPDIR)/include/asm-x86_64/offset.h
bzImage: checkoffset vmlinux bzImage: checkoffset vmlinux
@$(MAKEBOOT) bzImage @$(MAKEBOOT) bzImage
...@@ -104,12 +99,10 @@ bzImage-padded: checkoffset vmlinux ...@@ -104,12 +99,10 @@ bzImage-padded: checkoffset vmlinux
tmp: tmp:
@$(MAKEBOOT) BOOTIMAGE=bzImage zlilo @$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
bzlilo: checkoffset vmlinux bzlilo: checkoffset vmlinux
@$(MAKEBOOT) BOOTIMAGE=bzImage zlilo @$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
zdisk: checkoffset vmlinux
@$(MAKEBOOT) BOOTIMAGE=zImage zdisk
bzdisk: checkoffset vmlinux bzdisk: checkoffset vmlinux
@$(MAKEBOOT) BOOTIMAGE=bzImage zdisk @$(MAKEBOOT) BOOTIMAGE=bzImage zdisk
...@@ -118,7 +111,7 @@ install: checkoffset vmlinux ...@@ -118,7 +111,7 @@ install: checkoffset vmlinux
archclean: archclean:
@$(MAKEBOOT) clean @$(MAKEBOOT) clean
$(MAKE) -C $(TOPDIR)/arch/x86_64/tools clean @$(MAKE) -C $(TOPDIR)/arch/x86_64/tools clean
archmrproper: archmrproper:
rm -f $(TOPDIR)/arch/x86_64/tools/offset.h rm -f $(TOPDIR)/arch/x86_64/tools/offset.h
......
...@@ -435,36 +435,7 @@ no_disk1: ...@@ -435,36 +435,7 @@ no_disk1:
rep rep
stosb stosb
is_disk1: is_disk1:
# check for Micro Channel (MCA) bus
movw %cs, %ax # aka SETUPSEG
subw $DELTA_INITSEG, %ax # aka INITSEG
movw %ax, %ds
xorw %ax, %ax
movw %ax, (0xa0) # set table length to 0
movb $0xc0, %ah
stc
int $0x15 # moves feature table to es:bx
jc no_mca
pushw %ds
movw %es, %ax
movw %ax, %ds
movw %cs, %ax # aka SETUPSEG
subw $DELTA_INITSEG, %ax # aka INITSEG
movw %ax, %es
movw %bx, %si
movw $0xa0, %di
movw (%si), %cx
addw $2, %cx # table length is a short
cmpw $0x10, %cx
jc sysdesc_ok
movw $0x10, %cx # we keep only first 16 bytes
sysdesc_ok:
rep
movsb
popw %ds
no_mca:
# Check for PS/2 pointing device # Check for PS/2 pointing device
movw %cs, %ax # aka SETUPSEG movw %cs, %ax # aka SETUPSEG
subw $DELTA_INITSEG, %ax # aka INITSEG subw $DELTA_INITSEG, %ax # aka INITSEG
...@@ -477,71 +448,11 @@ no_mca: ...@@ -477,71 +448,11 @@ no_mca:
movw $0xAA, (0x1ff) # device present movw $0xAA, (0x1ff) # device present
no_psmouse: no_psmouse:
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
# Then check for an APM BIOS...
# %ds points to the bootsector
movw $0, 0x40 # version = 0 means no APM BIOS
movw $0x05300, %ax # APM BIOS installation check
xorw %bx, %bx
int $0x15
jc done_apm_bios # Nope, no APM BIOS
cmpw $0x0504d, %bx # Check for "PM" signature
jne done_apm_bios # No signature, no APM BIOS
andw $0x02, %cx # Is 32 bit supported?
je done_apm_bios # No 32-bit, no (good) APM BIOS
movw $0x05304, %ax # Disconnect first just in case
xorw %bx, %bx
int $0x15 # ignore return code
movw $0x05303, %ax # 32 bit connect
xorl %ebx, %ebx
xorw %cx, %cx # paranoia :-)
xorw %dx, %dx # ...
xorl %esi, %esi # ...
xorw %di, %di # ...
int $0x15
jc no_32_apm_bios # Ack, error.
movw %ax, (66) # BIOS code segment
movl %ebx, (68) # BIOS entry point offset
movw %cx, (72) # BIOS 16 bit code segment
movw %dx, (74) # BIOS data segment
movl %esi, (78) # BIOS code segment lengths
movw %di, (82) # BIOS data segment length
# Redo the installation check as the 32 bit connect
# modifies the flags returned on some BIOSs
movw $0x05300, %ax # APM BIOS installation check
xorw %bx, %bx
xorw %cx, %cx # paranoia
int $0x15
jc apm_disconnect # error -> shouldn't happen
cmpw $0x0504d, %bx # check for "PM" signature
jne apm_disconnect # no sig -> shouldn't happen
movw %ax, (64) # record the APM BIOS version
movw %cx, (76) # and flags
jmp done_apm_bios
apm_disconnect: # Tidy up
movw $0x05304, %ax # Disconnect
xorw %bx, %bx
int $0x15 # ignore return code
jmp done_apm_bios
no_32_apm_bios:
andw $0xfffd, (76) # remove 32 bit support bit
done_apm_bios:
#endif
# Now we want to move to protected mode ... # Now we want to move to protected mode ...
cmpw $0, %cs:realmode_swtch cmpw $0, %cs:realmode_swtch
jz rmodeswtch_normal jz rmodeswtch_normal
lcall *%cs:realmode_swtch lcall %cs:realmode_swtch
jmp rmodeswtch_end jmp rmodeswtch_end
......
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#define VIDEO_80x30 0x0f05 #define VIDEO_80x30 0x0f05
#define VIDEO_80x34 0x0f06 #define VIDEO_80x34 0x0f06
#define VIDEO_80x60 0x0f07 #define VIDEO_80x60 0x0f07
#define VIDEO_GFX_HACK 0x0f08
#define VIDEO_LAST_SPECIAL 0x0f09 #define VIDEO_LAST_SPECIAL 0x0f09
/* Video modes given by resolution */ /* Video modes given by resolution */
...@@ -741,15 +740,7 @@ set_80x60: ...@@ -741,15 +740,7 @@ set_80x60:
movw $0x503c, force_size movw $0x503c, force_size
jmp setvde jmp setvde
# Special hack for ThinkPad graphics
set_gfx: set_gfx:
#ifdef CONFIG_VIDEO_GFX_HACK
movw $VIDEO_GFX_BIOS_AX, %ax
movw $VIDEO_GFX_BIOS_BX, %bx
int $0x10
movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
stc
#endif
ret ret
#ifdef CONFIG_VIDEO_RETAIN #ifdef CONFIG_VIDEO_RETAIN
...@@ -974,10 +965,6 @@ vga_modes: ...@@ -974,10 +965,6 @@ vga_modes:
.word 0x5022 # 80x34 .word 0x5022 # 80x34
.word VIDEO_80x60 .word VIDEO_80x60
.word 0x503c # 80x60 .word 0x503c # 80x60
#ifdef CONFIG_VIDEO_GFX_HACK
.word VIDEO_GFX_HACK
.word VIDEO_GFX_DUMMY_RESOLUTION
#endif
vga_modes_end: vga_modes_end:
# Detect VESA modes. # Detect VESA modes.
......
...@@ -11,16 +11,16 @@ define_bool CONFIG_ISA y ...@@ -11,16 +11,16 @@ define_bool CONFIG_ISA y
define_bool CONFIG_SBUS n define_bool CONFIG_SBUS n
define_bool CONFIG_UID16 y define_bool CONFIG_UID16 y
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
define_bool CONFIG_X86_CMPXCHG y
source init/Config.in source init/Config.in
mainmenu_option next_comment mainmenu_option next_comment
comment 'Processor type and features' comment 'Processor type and features'
choice 'Processor family' \ choice 'Processor family' \
"Clawhammer CONFIG_MK8" Clawhammer "AMD-Hammer CONFIG_MK8" CONFIG_MK8
# #
# Define implied options from the CPU selection here # Define implied options from the CPU selection here
...@@ -29,7 +29,6 @@ define_int CONFIG_X86_L1_CACHE_BYTES 64 ...@@ -29,7 +29,6 @@ define_int CONFIG_X86_L1_CACHE_BYTES 64
define_int CONFIG_X86_L1_CACHE_SHIFT 6 define_int CONFIG_X86_L1_CACHE_SHIFT 6
define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_GOOD_APIC y
define_bool CONFIG_X86_CMPXCHG y
tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR
tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID
...@@ -37,32 +36,31 @@ tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID ...@@ -37,32 +36,31 @@ tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID
define_bool CONFIG_MATH_EMULATION n define_bool CONFIG_MATH_EMULATION n
define_bool CONFIG_MCA n define_bool CONFIG_MCA n
define_bool CONFIG_EISA n define_bool CONFIG_EISA n
define_bool CONFIG_X86_IO_APIC y
define_bool CONFIG_X86_LOCAL_APIC y
bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR #currently broken:
#bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
bool 'Symmetric multi-processing support' CONFIG_SMP bool 'Symmetric multi-processing support' CONFIG_SMP
bool 'Preemptible Kernel' CONFIG_PREEMPT bool 'Preemptible Kernel' CONFIG_PREEMPT
# currently doesn't boot without hacks. probably simulator bug.
#if [ "$CONFIG_SMP" != "y" ]; then
# bool 'APIC and IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC
# if [ "$CONFIG_X86_UP_IOAPIC" = "y" ]; then
# define_bool CONFIG_X86_IO_APIC y
# define_bool CONFIG_X86_LOCAL_APIC y
# fi
#fi
if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
define_bool CONFIG_HAVE_DEC_LOCK y define_bool CONFIG_HAVE_DEC_LOCK y
fi fi
define_bool CONFIG_X86_MCE y
bool 'Check for non-fatal machine check errors' CONFIG_X86_MCE_NONFATAL $CONFIG_X86_MCE
endmenu endmenu
mainmenu_option next_comment mainmenu_option next_comment
comment 'General options' comment 'General options'
if [ "$CONFIG_SMP" = "y" ]; then source drivers/acpi/Config.in
define_bool CONFIG_X86_IO_APIC y
define_bool CONFIG_X86_LOCAL_APIC y
fi
bool 'PCI support' CONFIG_PCI bool 'PCI support' CONFIG_PCI
if [ "$CONFIG_PCI" = "y" ]; then if [ "$CONFIG_PCI" = "y" ]; then
# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
define_bool CONFIG_PCI_DIRECT y define_bool CONFIG_PCI_DIRECT y
fi fi
...@@ -80,22 +78,14 @@ fi ...@@ -80,22 +78,14 @@ fi
if [ "$CONFIG_PROC_FS" = "y" ]; then if [ "$CONFIG_PROC_FS" = "y" ]; then
define_bool CONFIG_KCORE_ELF y define_bool CONFIG_KCORE_ELF y
fi fi
# We probably are not going to support a.out, are we? Or should we support a.out in i386 compatibility mode? #tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
#tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
bool 'Power Management support' CONFIG_PM bool 'Power Management support' CONFIG_PM
bool 'IA32 Emulation' CONFIG_IA32_EMULATION bool 'IA32 Emulation' CONFIG_IA32_EMULATION
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_bool ' ACPI support' CONFIG_ACPI $CONFIG_PM
if [ "$CONFIG_ACPI" != "n" ]; then
source drivers/acpi/Config.in
fi
fi
endmenu endmenu
source drivers/mtd/Config.in source drivers/mtd/Config.in
...@@ -186,10 +176,6 @@ endmenu ...@@ -186,10 +176,6 @@ endmenu
source drivers/input/Config.in source drivers/input/Config.in
source drivers/char/Config.in source drivers/char/Config.in
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
source net/bluetooth/Config.in
fi
source drivers/misc/Config.in source drivers/misc/Config.in
source drivers/media/Config.in source drivers/media/Config.in
...@@ -219,6 +205,10 @@ endmenu ...@@ -219,6 +205,10 @@ endmenu
source drivers/usb/Config.in source drivers/usb/Config.in
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
source net/bluetooth/Config.in
fi
mainmenu_option next_comment mainmenu_option next_comment
comment 'Kernel hacking' comment 'Kernel hacking'
...@@ -228,13 +218,13 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then ...@@ -228,13 +218,13 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
# bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT # bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
# bool ' Early printk' CONFIG_EARLY_PRINTK bool ' Early printk' CONFIG_EARLY_PRINTK
bool ' Additional run-time checks' CONFIG_CHECKING bool ' Additional run-time checks' CONFIG_CHECKING
fi bool ' Debug __init statements' CONFIG_INIT_DEBUG
bool 'Simnow environment (disables time-consuming things)' CONFIG_SIMNOW
#if [ "$CONFIG_SERIAL_CONSOLE" = "y" ]; then #if [ "$CONFIG_SERIAL_CONSOLE" = "y" ]; then
# bool 'Early serial console (ttyS0)' CONFIG_EARLY_SERIAL_CONSOLE # bool 'Early serial console (ttyS0)' CONFIG_EARLY_SERIAL_CONSOLE
#fi #fi
fi
endmenu endmenu
source lib/Config.in source lib/Config.in
...@@ -6,8 +6,9 @@ CONFIG_X86=y ...@@ -6,8 +6,9 @@ CONFIG_X86=y
CONFIG_ISA=y CONFIG_ISA=y
# CONFIG_SBUS is not set # CONFIG_SBUS is not set
CONFIG_UID16=y CONFIG_UID16=y
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_X86_CMPXCHG=y
# #
# Code maturity level options # Code maturity level options
...@@ -37,19 +38,27 @@ CONFIG_X86_L1_CACHE_BYTES=64 ...@@ -37,19 +38,27 @@ CONFIG_X86_L1_CACHE_BYTES=64
CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_TSC=y CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y CONFIG_X86_GOOD_APIC=y
CONFIG_X86_CMPXCHG=y
CONFIG_X86_MSR=y CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y CONFIG_X86_CPUID=y
# CONFIG_MATH_EMULATION is not set # CONFIG_MATH_EMULATION is not set
# CONFIG_MCA is not set # CONFIG_MCA is not set
# CONFIG_EISA is not set # CONFIG_EISA is not set
CONFIG_MTRR=y CONFIG_X86_IO_APIC=y
# CONFIG_SMP is not set CONFIG_X86_LOCAL_APIC=y
CONFIG_SMP=y
# CONFIG_PREEMPT is not set # CONFIG_PREEMPT is not set
CONFIG_HAVE_DEC_LOCK=y
CONFIG_X86_MCE=y
# CONFIG_X86_MCE_NONFATAL is not set
# #
# General options # General options
# #
#
# ACPI Support
#
# CONFIG_ACPI is not set
CONFIG_PCI=y CONFIG_PCI=y
CONFIG_PCI_DIRECT=y CONFIG_PCI_DIRECT=y
# CONFIG_PCI_NAMES is not set # CONFIG_PCI_NAMES is not set
...@@ -60,7 +69,6 @@ CONFIG_BINFMT_ELF=y ...@@ -60,7 +69,6 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set # CONFIG_BINFMT_MISC is not set
CONFIG_PM=y CONFIG_PM=y
CONFIG_IA32_EMULATION=y CONFIG_IA32_EMULATION=y
# CONFIG_ACPI is not set
# #
# Memory Technology Devices (MTD) # Memory Technology Devices (MTD)
...@@ -162,7 +170,7 @@ CONFIG_INET=y ...@@ -162,7 +170,7 @@ CONFIG_INET=y
CONFIG_IDE=y CONFIG_IDE=y
# #
# IDE, ATA and ATAPI Block devices # ATA and ATAPI Block devices
# #
CONFIG_BLK_DEV_IDE=y CONFIG_BLK_DEV_IDE=y
...@@ -172,7 +180,7 @@ CONFIG_BLK_DEV_IDE=y ...@@ -172,7 +180,7 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD_IDE is not set # CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set # CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set CONFIG_IDEDISK_MULTI_MODE=y
# CONFIG_IDEDISK_STROKE is not set # CONFIG_IDEDISK_STROKE is not set
# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set # CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set # CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
...@@ -184,23 +192,55 @@ CONFIG_BLK_DEV_IDEDISK=y ...@@ -184,23 +192,55 @@ CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_BLK_DEV_COMMERIAL is not set # CONFIG_BLK_DEV_COMMERIAL is not set
# CONFIG_BLK_DEV_TIVO is not set # CONFIG_BLK_DEV_TIVO is not set
# CONFIG_BLK_DEV_IDECS is not set # CONFIG_BLK_DEV_IDECS is not set
# CONFIG_BLK_DEV_IDECD is not set CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_BLK_DEV_IDESCSI is not set
# #
# IDE chipset support/bugfixes # IDE chipset support
# #
# CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_ISAPNP is not set # CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_RZ1000 is not set
# CONFIG_BLK_DEV_IDEPCI is not set CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_IDEPCI_SHARE_IRQ is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
CONFIG_IDEDMA_PCI_AUTO=y
# 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_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_HPT34X_AUTODMA is not set
# CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_PDC_ADMA is not set
# CONFIG_BLK_DEV_PDC202XX is not set
# CONFIG_PDC202XX_BURST is not set
# CONFIG_PDC202XX_FORCE is not set
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_CHIPSETS is not set # CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set # CONFIG_IDEDMA_IVB is not set
CONFIG_IDEDMA_AUTO=y
# CONFIG_DMA_NONPCI is not set # CONFIG_DMA_NONPCI is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
# CONFIG_BLK_DEV_ATARAID is not set # CONFIG_BLK_DEV_ATARAID is not set
# CONFIG_BLK_DEV_ATARAID_PDC is not set # CONFIG_BLK_DEV_ATARAID_PDC is not set
# CONFIG_BLK_DEV_ATARAID_HPT is not set # CONFIG_BLK_DEV_ATARAID_HPT is not set
...@@ -315,11 +355,6 @@ CONFIG_PSMOUSE=y ...@@ -315,11 +355,6 @@ CONFIG_PSMOUSE=y
# CONFIG_DRM is not set # CONFIG_DRM is not set
# CONFIG_MWAVE is not set # CONFIG_MWAVE is not set
#
# Bluetooth support
#
# CONFIG_BLUEZ is not set
# #
# Misc devices # Misc devices
# #
...@@ -359,6 +394,9 @@ CONFIG_RAMFS=y ...@@ -359,6 +394,9 @@ CONFIG_RAMFS=y
# CONFIG_ISO9660_FS is not set # CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set # CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set # CONFIG_ZISOFS is not set
# CONFIG_JFS_FS is not set
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_MINIX_FS is not set # CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set # CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set # CONFIG_NTFS_FS is not set
...@@ -389,6 +427,7 @@ CONFIG_EXT2_FS=y ...@@ -389,6 +427,7 @@ CONFIG_EXT2_FS=y
# CONFIG_ROOT_NFS is not set # CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set # CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set # CONFIG_NFSD_V3 is not set
# CONFIG_NFSD_TCP is not set
# CONFIG_SUNRPC is not set # CONFIG_SUNRPC is not set
# CONFIG_LOCKD is not set # CONFIG_LOCKD is not set
# CONFIG_SMB_FS is not set # CONFIG_SMB_FS is not set
...@@ -434,110 +473,9 @@ CONFIG_VGA_CONSOLE=y ...@@ -434,110 +473,9 @@ CONFIG_VGA_CONSOLE=y
# CONFIG_USB is not set # CONFIG_USB is not set
# #
# USB Host Controller Drivers # Bluetooth support
#
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
# CONFIG_USB_OHCI is not set
#
# USB Device Class drivers
#
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_BLUETOOTH is not set
#
# SCSI support is needed for USB Storage
#
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_HP8200e is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
#
# USB Human Interface Devices (HID)
#
#
# Input core support is needed for USB HID
#
#
# USB Imaging devices
#
# CONFIG_USB_DC2XX is not set
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_SCANNER is not set
# CONFIG_USB_MICROTEK is not set
# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
#
#
# Video4Linux support is needed for USB Multimedia device support
#
#
# USB Network adaptors
#
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_CDCETHER is not set
# CONFIG_USB_USBNET is not set
#
# USB port drivers
#
# CONFIG_USB_USS720 is not set
#
# USB Serial Converter support
#
# CONFIG_USB_SERIAL is not set
# CONFIG_USB_SERIAL_GENERIC is not set
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_WHITEHEAT is not set
# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
# CONFIG_USB_SERIAL_VISOR is not set
# CONFIG_USB_SERIAL_IPAQ is not set
# CONFIG_USB_SERIAL_IR is not set
# CONFIG_USB_SERIAL_EDGEPORT is not set
# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
# CONFIG_USB_SERIAL_KEYSPAN is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OMNINET is not set
#
# USB Miscellaneous drivers
# #
# CONFIG_USB_RIO500 is not set # CONFIG_BLUEZ is not set
# CONFIG_USB_AUERSWALD is not set
# #
# Kernel hacking # Kernel hacking
...@@ -546,8 +484,9 @@ CONFIG_DEBUG_KERNEL=y ...@@ -546,8 +484,9 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SLAB is not set
# CONFIG_MAGIC_SYSRQ is not set # CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_EARLY_PRINTK is not set
# CONFIG_CHECKING is not set # CONFIG_CHECKING is not set
CONFIG_SIMNOW=y # CONFIG_INIT_DEBUG is not set
# #
# Library routines # Library routines
......
...@@ -7,11 +7,13 @@ ...@@ -7,11 +7,13 @@
.S.o: .S.o:
$(CC) $(AFLAGS) -c -o $*.o $< $(CC) $(AFLAGS) -c -o $*.o $<
export-objs := ia32_ioctl.o
all: ia32.o all: ia32.o
O_TARGET := ia32.o O_TARGET := ia32.o
obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o ia32_binfmt.o \ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o \
socket32.o ptrace32.o ia32_binfmt.o fpu32.o socket32.o ptrace32.o
clean:: clean::
......
/*
* Copyright 2002 Andi Kleen, SuSE Labs.
* FXSAVE<->i387 conversion support. Based on code by Gareth Hughes.
* This is used for ptrace, signals and coredumps in 32bit emulation.
* $Id: fpu32.c,v 1.1 2002/03/21 14:16:32 ak Exp $
*/
#include <linux/sched.h>
#include <asm/sigcontext32.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/i387.h>
static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
{
unsigned int tmp; /* to avoid 16 bit prefixes in the code */
/* Transform each pair of bits into 01 (valid) or 00 (empty) */
tmp = ~twd;
tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
/* and move the valid bits to the lower byte. */
tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
return tmp;
}
static inline unsigned long twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
{
struct _fpxreg *st = NULL;
unsigned long twd = (unsigned long) fxsave->twd;
unsigned long tag;
unsigned long ret = 0xffff0000;
int i;
#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
for (i = 0 ; i < 8 ; i++) {
if (twd & 0x1) {
st = (struct _fpxreg *) FPREG_ADDR( fxsave, i );
switch (st->exponent & 0x7fff) {
case 0x7fff:
tag = 2; /* Special */
break;
case 0x0000:
if ( !st->significand[0] &&
!st->significand[1] &&
!st->significand[2] &&
!st->significand[3] ) {
tag = 1; /* Zero */
} else {
tag = 2; /* Special */
}
break;
default:
if (st->significand[3] & 0x8000) {
tag = 0; /* Valid */
} else {
tag = 2; /* Special */
}
break;
}
} else {
tag = 3; /* Empty */
}
ret |= (tag << (2 * i));
twd = twd >> 1;
}
return ret;
}
static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave,
struct _fpstate_ia32 *buf)
{
struct _fpxreg *to;
struct _fpreg *from;
int i;
int err;
__u32 v;
err = __get_user(fxsave->cwd, (u16 *)&buf->cw);
err |= __get_user(fxsave->swd, (u16 *)&buf->sw);
err |= __get_user(fxsave->twd, (u16 *)&buf->tag);
fxsave->twd = twd_i387_to_fxsr(fxsave->twd);
err |= __get_user(fxsave->rip, &buf->ipoff);
err |= __get_user(fxsave->rdp, &buf->dataoff);
err |= __get_user(v, &buf->cssel);
fxsave->fop = v >> 16;
if (err)
return -1;
to = (struct _fpxreg *)&fxsave->st_space[0];
from = &buf->_st[0];
for (i = 0 ; i < 8 ; i++, to++, from++) {
if (__copy_from_user(to, from, sizeof(*from)))
return -1;
}
return 0;
}
static inline int convert_fxsr_to_user(struct _fpstate_ia32 *buf,
struct i387_fxsave_struct *fxsave,
struct pt_regs *regs,
struct task_struct *tsk)
{
struct _fpreg *to;
struct _fpxreg *from;
int i;
u32 ds;
int err;
err = __put_user((unsigned long)fxsave->cwd | 0xffff0000, &buf->cw);
err |= __put_user((unsigned long)fxsave->swd | 0xffff0000, &buf->sw);
err |= __put_user((u32)fxsave->rip, &buf->ipoff);
err |= __put_user((u32)(regs->cs | ((u32)fxsave->fop << 16)),
&buf->cssel);
err |= __put_user((u32)twd_fxsr_to_i387(fxsave), &buf->tag);
err |= __put_user((u32)fxsave->rdp, &buf->dataoff);
if (tsk == current)
asm("movl %%ds,%0 " : "=r" (ds));
else /* ptrace. task has stopped. */
ds = tsk->thread.ds;
err |= __put_user(ds, &buf->datasel);
if (err)
return -1;
to = &buf->_st[0];
from = (struct _fpxreg *) &fxsave->st_space[0];
for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
if (__copy_to_user(to, from, sizeof(*to)))
return -1;
}
return 0;
}
int restore_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 *buf, int fsave)
{
clear_fpu(tsk);
if (!fsave) {
if (__copy_from_user(&tsk->thread.i387.fxsave,
&buf->_fxsr_env[0],
sizeof(struct i387_fxsave_struct)))
return -1;
}
tsk->thread.i387.fxsave.mxcsr &= 0xffbf;
return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf);
}
int save_i387_ia32(struct task_struct *tsk,
struct _fpstate_ia32 *buf,
struct pt_regs *regs,
int fsave)
{
int err = 0;
if (!tsk->used_math)
return 0;
tsk->used_math = 0;
unlazy_fpu(tsk);
if (convert_fxsr_to_user(buf, &tsk->thread.i387.fxsave, regs, tsk))
return -1;
err |= __put_user(tsk->thread.i387.fxsave.swd, &buf->status);
if (fsave)
return err ? -1 : 1;
err |= __put_user(X86_FXSR_MAGIC, &buf->magic);
err |= __copy_to_user(&buf->_fxsr_env[0], &tsk->thread.i387.fxsave,
sizeof(struct i387_fxsave_struct));
return err ? -1 : 1;
}
/* /*
* Written 2000 by Andi Kleen. * Written 2000,2002 by Andi Kleen.
* *
* Losely based on the sparc64 and IA64 32bit emulation loaders. * Losely based on the sparc64 and IA64 32bit emulation loaders.
* This tricks binfmt_elf.c into loading 32bit binaries using lots
* of ugly preprocessor tricks. Talk about very very poor man's inheritance.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/user32.h>
#include <asm/sigcontext32.h>
#include <asm/fpu32.h>
#include <asm/i387.h>
struct file; struct file;
struct elf_phdr; struct elf_phdr;
...@@ -28,19 +36,99 @@ struct elf_phdr; ...@@ -28,19 +36,99 @@ struct elf_phdr;
#define ELF_CLASS ELFCLASS32 #define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2LSB #define ELF_DATA ELFDATA2LSB
//#define USE_ELF_CORE_DUMP
#define USE_ELF_CORE_DUMP 1
/* Overwrite elfcore.h */
#define _LINUX_ELFCORE_H 1
typedef unsigned int elf_greg_t;
#define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
struct elf_siginfo
{
int si_signo; /* signal number */
int si_code; /* extra code */
int si_errno; /* errno */
};
struct timeval32
{
int tv_sec, tv_usec;
};
struct elf_prstatus
{
struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */
unsigned int pr_sigpend; /* Set of pending signals */
unsigned int pr_sighold; /* Set of held signals */
pid_t pr_pid;
pid_t pr_ppid;
pid_t pr_pgrp;
pid_t pr_sid;
struct timeval32 pr_utime; /* User time */
struct timeval32 pr_stime; /* System time */
struct timeval32 pr_cutime; /* Cumulative user time */
struct timeval32 pr_cstime; /* Cumulative system time */
elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */
};
#define ELF_PRARGSZ (80) /* Number of chars for args */
struct elf_prpsinfo
{
char pr_state; /* numeric process state */
char pr_sname; /* char for pr_state */
char pr_zomb; /* zombie */
char pr_nice; /* nice val */
unsigned int pr_flag; /* flags */
__u16 pr_uid;
__u16 pr_gid;
pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
/* Lots missing */
char pr_fname[16]; /* filename of executable */
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};
#define __STR(x) #x
#define STR(x) __STR(x)
#define _GET_SEG(x) \
({ __u32 seg; asm("movl %%" STR(x) ",%0" : "=r"(seg)); seg; })
/* Assumes current==process to be dumped */
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
pr_reg[0] = regs->rbx; \
pr_reg[1] = regs->rcx; \
pr_reg[2] = regs->rdx; \
pr_reg[3] = regs->rsi; \
pr_reg[4] = regs->rdi; \
pr_reg[5] = regs->rbp; \
pr_reg[6] = regs->rax; \
pr_reg[7] = _GET_SEG(ds); \
pr_reg[8] = _GET_SEG(es); \
pr_reg[9] = _GET_SEG(fs); \
pr_reg[10] = _GET_SEG(gs); \
pr_reg[11] = regs->orig_rax; \
pr_reg[12] = regs->rip; \
pr_reg[13] = regs->cs; \
pr_reg[14] = regs->eflags; \
pr_reg[15] = regs->rsp; \
pr_reg[16] = regs->ss;
#define user user32
#define dump_fpu dump_fpu_ia32
#define __ASM_X86_64_ELF_H 1 #define __ASM_X86_64_ELF_H 1
#include <asm/ia32.h> #include <asm/ia32.h>
#include <linux/elf.h> #include <linux/elf.h>
typedef __u32 elf_greg_t;
typedef elf_greg_t elf_gregset_t[8];
/* FIXME -- wrong */
typedef struct user_i387_ia32_struct elf_fpregset_t; typedef struct user_i387_ia32_struct elf_fpregset_t;
typedef struct user_i387_struct elf_fpxregset_t; typedef struct user32_fxsr_struct elf_fpxregset_t;
#undef elf_check_arch #undef elf_check_arch
#define elf_check_arch(x) \ #define elf_check_arch(x) \
...@@ -177,11 +265,35 @@ elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int p ...@@ -177,11 +265,35 @@ elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int p
unsigned long map_addr; unsigned long map_addr;
struct task_struct *me = current; struct task_struct *me = current;
if (prot & PROT_READ)
prot |= PROT_EXEC;
down_write(&me->mm->mmap_sem); down_write(&me->mm->mmap_sem);
map_addr = do_mmap(filep, ELF_PAGESTART(addr), map_addr = do_mmap(filep, ELF_PAGESTART(addr),
eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type|MAP_32BIT, eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot,
type|MAP_32BIT,
eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr)); eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
up_write(&me->mm->mmap_sem); up_write(&me->mm->mmap_sem);
return(map_addr); return(map_addr);
} }
int dump_fpu_ia32(struct pt_regs *regs, elf_fpregset_t *fp)
{
struct _fpstate_ia32 *fpu = (void*)fp;
struct task_struct *tsk = current;
mm_segment_t oldfs = get_fs();
int ret;
if (!tsk->used_math)
return 0;
if (!(test_thread_flag(TIF_IA32)))
BUG();
unlazy_fpu(tsk);
set_fs(KERNEL_DS);
ret = save_i387_ia32(current, fpu, regs, 1);
/* Correct for i386 bug. It puts the fop into the upper 16bits of
the tag word (like FXSAVE), not into the fcs*/
fpu->cssel |= fpu->tag & 0xffff0000;
set_fs(oldfs);
return ret;
}
/* $Id: ia32_ioctl.c,v 1.2 2001/07/05 06:28:42 ak Exp $ /* $Id: ia32_ioctl.c,v 1.11 2002/04/18 14:36:37 ak Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls. * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
* *
* Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 2001 Andi Kleen, SuSE Labs * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
* *
* These routines maintain argument size conversion between 32bit and 64bit * These routines maintain argument size conversion between 32bit and 64bit
* ioctls. * ioctls.
...@@ -51,6 +51,10 @@ ...@@ -51,6 +51,10 @@
#include <linux/elevator.h> #include <linux/elevator.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/rtc.h>
#include <linux/module.h>
#include <linux/serial.h>
#include <linux/reiserfs_fs.h>
#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
/* Ugh. This header really is not clean */ /* Ugh. This header really is not clean */
#define min min #define min min
...@@ -2972,12 +2976,139 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -2972,12 +2976,139 @@ static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
} }
/* SuSE extension */
#ifndef TIOCGDEV
#define TIOCGDEV _IOR('T',0x32, unsigned int)
#endif
static int tiocgdev(unsigned fd, unsigned cmd, unsigned int *ptr)
{
struct file *file = fget(fd);
struct tty_struct *real_tty;
if (!fd)
return -EBADF;
if (file->f_op->ioctl != tty_ioctl)
return -EINVAL;
real_tty = (struct tty_struct *)file->private_data;
if (!real_tty)
return -EINVAL;
return put_user(kdev_t_to_nr(real_tty->device), ptr);
}
struct raw32_config_request
{
int raw_minor;
__u64 block_major;
__u64 block_minor;
} __attribute__((packed));
static int raw_ioctl(unsigned fd, unsigned cmd, void *ptr)
{
int ret;
switch (cmd) {
case RAW_SETBIND:
case RAW_GETBIND: {
struct raw_config_request req;
struct raw32_config_request *user_req = ptr;
mm_segment_t oldfs = get_fs();
if (get_user(req.raw_minor, &user_req->raw_minor) ||
get_user(req.block_major, &user_req->block_major) ||
get_user(req.block_minor, &user_req->block_minor))
return -EFAULT;
set_fs(KERNEL_DS);
ret = sys_ioctl(fd,cmd,(unsigned long)&req);
set_fs(oldfs);
break;
}
default:
ret = sys_ioctl(fd,cmd,(unsigned long)ptr);
break;
}
return ret;
}
struct serial_struct32 {
int type;
int line;
unsigned int port;
int irq;
int flags;
int xmit_fifo_size;
int custom_divisor;
int baud_base;
unsigned short close_delay;
char io_type;
char reserved_char[1];
int hub6;
unsigned short closing_wait; /* time to wait before closing */
unsigned short closing_wait2; /* no longer used... */
__u32 iomem_base;
unsigned short iomem_reg_shift;
unsigned int port_high;
int reserved[1];
};
static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr)
{
typedef struct serial_struct SS;
struct serial_struct32 *ss32 = ptr;
int err = 0;
struct serial_struct ss;
mm_segment_t oldseg = get_fs();
set_fs(KERNEL_DS);
if (cmd == TIOCSSERIAL) {
err = -EFAULT;
if (copy_from_user(&ss, ss32, sizeof(struct serial_struct32)))
goto out;
memmove(&ss.iomem_reg_shift, ((char*)&ss.iomem_base)+4,
sizeof(SS)-offsetof(SS,iomem_reg_shift));
ss.iomem_base = (void *)((unsigned long)ss.iomem_base & 0xffffffff);
}
if (!err)
err = sys_ioctl(fd,cmd,(unsigned long)(&ss));
if (cmd == TIOCGSERIAL && err >= 0) {
__u32 base;
if (__copy_to_user(ss32,&ss,offsetof(SS,iomem_base)) ||
__copy_to_user(&ss32->iomem_reg_shift,
&ss.iomem_reg_shift,
sizeof(SS) - offsetof(SS, iomem_reg_shift)))
err = -EFAULT;
if (ss.iomem_base > (unsigned char *)0xffffffff)
base = -1;
else
base = (unsigned long)ss.iomem_base;
err |= __put_user(base, &ss32->iomem_base);
}
out:
set_fs(oldseg);
return err;
}
struct ioctl_trans { struct ioctl_trans {
unsigned long cmd; unsigned long cmd;
unsigned long handler; int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
struct ioctl_trans *next; struct ioctl_trans *next;
}; };
/* generic function to change a single long put_user to arg to 32bit */
static int arg2long(unsigned int fd, unsigned int cmd, unsigned long arg)
{
int ret;
unsigned long val = 0;
mm_segment_t oldseg = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl(fd, cmd, (unsigned long)&val);
set_fs(oldseg);
if (!ret || val) {
if (put_user((int)val, (unsigned int *)arg))
return -EFAULT;
}
return ret;
}
#define REF_SYMBOL(handler) if (0) (void)handler; #define REF_SYMBOL(handler) if (0) (void)handler;
#define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %c0, " #handler ",0"::"i" (cmd)); #define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %c0, " #handler ",0"::"i" (cmd));
#define HANDLE_IOCTL(cmd,handler) HANDLE_IOCTL2(cmd,handler) #define HANDLE_IOCTL(cmd,handler) HANDLE_IOCTL2(cmd,handler)
...@@ -2986,7 +3117,7 @@ struct ioctl_trans { ...@@ -2986,7 +3117,7 @@ struct ioctl_trans {
#define IOCTL_TABLE_END asm volatile("\nioctl_end:"); } #define IOCTL_TABLE_END asm volatile("\nioctl_end:"); }
IOCTL_TABLE_START IOCTL_TABLE_START
/* List here exlicitly which ioctl's are known to have /* List here explicitly which ioctl's are known to have
* compatable types passed or none at all... * compatable types passed or none at all...
*/ */
/* Big T */ /* Big T */
...@@ -3002,6 +3133,7 @@ COMPATIBLE_IOCTL(TCSETS) ...@@ -3002,6 +3133,7 @@ COMPATIBLE_IOCTL(TCSETS)
COMPATIBLE_IOCTL(TCSETSW) COMPATIBLE_IOCTL(TCSETSW)
COMPATIBLE_IOCTL(TCSETSF) COMPATIBLE_IOCTL(TCSETSF)
COMPATIBLE_IOCTL(TIOCLINUX) COMPATIBLE_IOCTL(TIOCLINUX)
HANDLE_IOCTL(TIOCGDEV, tiocgdev)
/* Little t */ /* Little t */
COMPATIBLE_IOCTL(TIOCGETD) COMPATIBLE_IOCTL(TIOCGETD)
COMPATIBLE_IOCTL(TIOCSETD) COMPATIBLE_IOCTL(TIOCSETD)
...@@ -3025,8 +3157,6 @@ COMPATIBLE_IOCTL(TIOCGPGRP) ...@@ -3025,8 +3157,6 @@ COMPATIBLE_IOCTL(TIOCGPGRP)
COMPATIBLE_IOCTL(TIOCSCTTY) COMPATIBLE_IOCTL(TIOCSCTTY)
COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCGPTN)
COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSPTLCK)
COMPATIBLE_IOCTL(TIOCGSERIAL)
COMPATIBLE_IOCTL(TIOCSSERIAL)
COMPATIBLE_IOCTL(TIOCSERGETLSR) COMPATIBLE_IOCTL(TIOCSERGETLSR)
COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO)
COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO)
...@@ -3082,6 +3212,8 @@ COMPATIBLE_IOCTL(BLKROSET) ...@@ -3082,6 +3212,8 @@ COMPATIBLE_IOCTL(BLKROSET)
COMPATIBLE_IOCTL(BLKROGET) COMPATIBLE_IOCTL(BLKROGET)
COMPATIBLE_IOCTL(BLKRRPART) COMPATIBLE_IOCTL(BLKRRPART)
COMPATIBLE_IOCTL(BLKFLSBUF) COMPATIBLE_IOCTL(BLKFLSBUF)
COMPATIBLE_IOCTL(BLKRASET)
COMPATIBLE_IOCTL(BLKFRASET)
COMPATIBLE_IOCTL(BLKSECTSET) COMPATIBLE_IOCTL(BLKSECTSET)
COMPATIBLE_IOCTL(BLKSSZGET) COMPATIBLE_IOCTL(BLKSSZGET)
...@@ -3203,7 +3335,7 @@ COMPATIBLE_IOCTL(RTC_RD_TIME) ...@@ -3203,7 +3335,7 @@ COMPATIBLE_IOCTL(RTC_RD_TIME)
COMPATIBLE_IOCTL(RTC_SET_TIME) COMPATIBLE_IOCTL(RTC_SET_TIME)
COMPATIBLE_IOCTL(RTC_WKALM_SET) COMPATIBLE_IOCTL(RTC_WKALM_SET)
COMPATIBLE_IOCTL(RTC_WKALM_RD) COMPATIBLE_IOCTL(RTC_WKALM_RD)
COMPATIBLE_IOCTL(RTC_IRQP_READ) HANDLE_IOCTL(RTC_IRQP_READ,arg2long)
COMPATIBLE_IOCTL(RTC_IRQP_SET) COMPATIBLE_IOCTL(RTC_IRQP_SET)
COMPATIBLE_IOCTL(RTC_EPOCH_READ) COMPATIBLE_IOCTL(RTC_EPOCH_READ)
COMPATIBLE_IOCTL(RTC_EPOCH_SET) COMPATIBLE_IOCTL(RTC_EPOCH_SET)
...@@ -3479,9 +3611,6 @@ COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) ...@@ -3479,9 +3611,6 @@ COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE) COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE)
COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK) COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK)
/* Raw devices */
COMPATIBLE_IOCTL(RAW_SETBIND)
COMPATIBLE_IOCTL(RAW_GETBIND)
/* SMB ioctls which do not need any translations */ /* SMB ioctls which do not need any translations */
COMPATIBLE_IOCTL(SMB_IOC_NEWCONN) COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
/* Little a */ /* Little a */
...@@ -3543,6 +3672,18 @@ COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) ...@@ -3543,6 +3672,18 @@ COMPATIBLE_IOCTL(DRM_IOCTL_LOCK)
COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK)
COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) COMPATIBLE_IOCTL(DRM_IOCTL_FINISH)
#endif /* DRM */ #endif /* DRM */
#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
COMPATIBLE_IOCTL(REISERFS_IOC_UNPACK);
/* serial driver */
HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl);
HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl);
/* elevator */ /* elevator */
COMPATIBLE_IOCTL(BLKELVGET) COMPATIBLE_IOCTL(BLKELVGET)
COMPATIBLE_IOCTL(BLKELVSET) COMPATIBLE_IOCTL(BLKELVSET)
...@@ -3589,6 +3730,8 @@ HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) ...@@ -3589,6 +3730,8 @@ HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl)
HANDLE_IOCTL(SIOCADDRT, routing_ioctl) HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
HANDLE_IOCTL(SIOCDELRT, routing_ioctl) HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
/* 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. */ /* 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(SIOCRTMSG, ret_einval)
HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
...@@ -3751,14 +3894,14 @@ static struct ioctl_trans *additional_ioctls; ...@@ -3751,14 +3894,14 @@ static struct ioctl_trans *additional_ioctls;
/* Always call these with kernel lock held! */ /* Always call these with kernel lock held! */
int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)) int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *))
{ {
int i; int i;
if (!additional_ioctls) { if (!additional_ioctls) {
additional_ioctls = module_map(PAGE_SIZE); additional_ioctls = (struct ioctl_trans *)get_zeroed_page(GFP_KERNEL);
if (!additional_ioctls) if (!additional_ioctls)
return -ENOMEM; return -ENOMEM;
memset(additional_ioctls, 0, PAGE_SIZE);
} }
for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++) for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++)
if (!additional_ioctls[i].cmd) if (!additional_ioctls[i].cmd)
...@@ -3767,13 +3910,15 @@ int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, u ...@@ -3767,13 +3910,15 @@ int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, u
return -ENOMEM; return -ENOMEM;
additional_ioctls[i].cmd = cmd; additional_ioctls[i].cmd = cmd;
if (!handler) if (!handler)
additional_ioctls[i].handler = (u32)(long)sys_ioctl; additional_ioctls[i].handler =
(int (*)(unsigned,unsigned,unsigned long, struct file *))sys_ioctl;
else else
additional_ioctls[i].handler = (u32)(long)handler; additional_ioctls[i].handler = handler;
ioctl32_insert_translation(&additional_ioctls[i]); ioctl32_insert_translation(&additional_ioctls[i]);
return 0; return 0;
} }
int unregister_ioctl32_conversion(unsigned int cmd) int unregister_ioctl32_conversion(unsigned int cmd)
{ {
unsigned long hash = ioctl32_hash(cmd); unsigned long hash = ioctl32_hash(cmd);
...@@ -3799,6 +3944,9 @@ int unregister_ioctl32_conversion(unsigned int cmd) ...@@ -3799,6 +3944,9 @@ int unregister_ioctl32_conversion(unsigned int cmd)
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL(register_ioctl32_conversion);
EXPORT_SYMBOL(unregister_ioctl32_conversion);
asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct file * filp; struct file * filp;
...@@ -3820,7 +3968,7 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -3820,7 +3968,7 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
while (t && t->cmd != cmd) while (t && t->cmd != cmd)
t = (struct ioctl_trans *)(long)t->next; t = (struct ioctl_trans *)(long)t->next;
if (t) { if (t) {
handler = (void *)(long)t->handler; handler = t->handler;
error = handler(fd, cmd, arg, filp); error = handler(fd, cmd, arg, filp);
} else { } else {
static int count = 0; static int count = 0;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
* 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen
* *
* $Id: ia32_signal.c,v 1.15 2001/10/16 23:41:42 ak Exp $ * $Id: ia32_signal.c,v 1.17 2002/03/21 14:16:32 ak Exp $
*/ */
#include <linux/sched.h> #include <linux/sched.h>
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/ia32_unistd.h> #include <asm/ia32_unistd.h>
#include <asm/user32.h> #include <asm/user32.h>
#include <asm/sigcontext32.h>
#include <asm/fpu32.h>
#define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */ #define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */
...@@ -147,7 +149,7 @@ struct rt_sigframe ...@@ -147,7 +149,7 @@ struct rt_sigframe
}; };
static int static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsigned int *peax) ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsigned int *peax)
{ {
unsigned int err = 0; unsigned int err = 0;
...@@ -171,7 +173,13 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsigned in ...@@ -171,7 +173,13 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsigned in
/* 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 This does not handle long fs/gs base changes in the handler, but does not clobber
them at least in the normal case. */ them at least in the normal case. */
RELOAD_SEG(gs);
{
unsigned short gs;
err |= __get_user(gs, &sc->gs);
load_gs_index(gs);
}
RELOAD_SEG(fs); RELOAD_SEG(fs);
COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
...@@ -187,13 +195,13 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsigned in ...@@ -187,13 +195,13 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsigned in
{ {
u32 tmp; u32 tmp;
struct _fpstate * buf; struct _fpstate_ia32 * buf;
err |= __get_user(tmp, &sc->fpstate); err |= __get_user(tmp, &sc->fpstate);
buf = (struct _fpstate *) (u64)tmp; buf = (struct _fpstate_ia32 *) (u64)tmp;
if (buf) { if (buf) {
if (verify_area(VERIFY_READ, buf, sizeof(*buf))) if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
goto badframe; goto badframe;
err |= restore_i387(buf); err |= restore_i387_ia32(current, buf, 0);
} }
} }
...@@ -228,7 +236,7 @@ asmlinkage int sys32_sigreturn(struct pt_regs regs) ...@@ -228,7 +236,7 @@ asmlinkage int sys32_sigreturn(struct pt_regs regs)
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
if (restore_sigcontext(&regs, &frame->sc, &eax)) if (ia32_restore_sigcontext(&regs, &frame->sc, &eax))
goto badframe; goto badframe;
return eax; return eax;
...@@ -255,7 +263,7 @@ asmlinkage int sys32_rt_sigreturn(struct pt_regs regs) ...@@ -255,7 +263,7 @@ asmlinkage int sys32_rt_sigreturn(struct pt_regs regs)
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &eax)) if (ia32_restore_sigcontext(&regs, &frame->uc.uc_mcontext, &eax))
goto badframe; goto badframe;
if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
...@@ -281,7 +289,7 @@ asmlinkage int sys32_rt_sigreturn(struct pt_regs regs) ...@@ -281,7 +289,7 @@ asmlinkage int sys32_rt_sigreturn(struct pt_regs regs)
*/ */
static int static int
setup_sigcontext(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate, ia32_setup_sigcontext(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
struct pt_regs *regs, unsigned int mask) struct pt_regs *regs, unsigned int mask)
{ {
int tmp, err = 0; int tmp, err = 0;
...@@ -306,7 +314,7 @@ setup_sigcontext(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate, ...@@ -306,7 +314,7 @@ setup_sigcontext(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
err |= __put_user((u32)regs->eflags, &sc->eflags); err |= __put_user((u32)regs->eflags, &sc->eflags);
err |= __put_user((u32)regs->rsp, &sc->esp_at_signal); err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
tmp = save_i387(fpstate); tmp = save_i387_ia32(current, fpstate, regs, 0);
if (tmp < 0) if (tmp < 0)
err = -EFAULT; err = -EFAULT;
else else
...@@ -351,23 +359,24 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, ...@@ -351,23 +359,24 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
{ {
struct sigframe *frame; struct sigframe *frame;
int err = 0; int err = 0;
struct exec_domain *exec_domain = current_thread_info()->exec_domain;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= __put_user((exec_domain {
&& exec_domain->signal_invmap struct exec_domain *ed = current_thread_info()->exec_domain;
&& sig < 32
? exec_domain->signal_invmap[sig] err |= __put_user((ed && ed->signal_invmap && sig < 32
? ed->signal_invmap[sig]
: sig), : sig),
&frame->sig); &frame->sig);
}
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
...@@ -419,19 +428,19 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -419,19 +428,19 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
{ {
struct rt_sigframe *frame; struct rt_sigframe *frame;
int err = 0; int err = 0;
struct exec_domain *exec_domain = current_thread_info()->exec_domain;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= __put_user((exec_domain {
&& exec_domain->signal_invmap struct exec_domain *ed = current_thread_info()->exec_domain;
&& sig < 32 err |= __put_user((ed && ed->signal_invmap && sig < 32
? exec_domain->signal_invmap[sig] ? ed->signal_invmap[sig]
: sig), : sig),
&frame->sig); &frame->sig);
}
err |= __put_user((u32)(u64)&frame->info, &frame->pinfo); err |= __put_user((u32)(u64)&frame->info, &frame->pinfo);
err |= __put_user((u32)(u64)&frame->uc, &frame->puc); err |= __put_user((u32)(u64)&frame->uc, &frame->puc);
err |= ia32_copy_siginfo_to_user(&frame->info, info); err |= ia32_copy_siginfo_to_user(&frame->info, info);
...@@ -445,7 +454,7 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -445,7 +454,7 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(sas_ss_flags(regs->rsp), err |= __put_user(sas_ss_flags(regs->rsp),
&frame->uc.uc_stack.ss_flags); &frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
regs, set->sig[0]); regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
......
/* /*
* Compatibility mode system call entry point for x86-64. * Compatibility mode system call entry point for x86-64.
* *
* Copyright 2000,2001,2002 Andi Kleen, SuSE Labs. * Copyright 2000,2001 Andi Kleen, SuSE Labs.
* *
* $Id: ia32entry.S,v 1.24 2001/11/11 17:47:47 ak Exp $ * $Id: ia32entry.S,v 1.31 2002/03/24 13:01:45 ak Exp $
*/ */
#include <asm/calling.h> #include <asm/calling.h>
#include <asm/offset.h> #include <asm/offset.h>
#include <asm/thread_info.h> #include <asm/current.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/ia32_unistd.h> #include <asm/ia32_unistd.h>
#include <asm/thread_info.h>
.macro IA32_ARG_FIXUP .macro IA32_ARG_FIXUP
movl %edi,%r8d movl %edi,%r8d
...@@ -29,7 +30,7 @@ ...@@ -29,7 +30,7 @@
*/ */
ENTRY(ia32_cstar_target) ENTRY(ia32_cstar_target)
movq $-ENOSYS,%rax movq $-ENOSYS,%rax
SYSRET32 sysret
/* /*
* Emulated IA32 system calls via int 0x80. * Emulated IA32 system calls via int 0x80.
...@@ -65,7 +66,6 @@ ia32_do_syscall: ...@@ -65,7 +66,6 @@ ia32_do_syscall:
cmpl $(IA32_NR_syscalls),%eax cmpl $(IA32_NR_syscalls),%eax
jae ia32_badsys jae ia32_badsys
IA32_ARG_FIXUP IA32_ARG_FIXUP
movl $1,%r10d
call *ia32_sys_call_table(,%rax,8) # xxx: rip relative call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
movq %rax,RAX-ARGOFFSET(%rsp) movq %rax,RAX-ARGOFFSET(%rsp)
jmp int_ret_from_sys_call jmp int_ret_from_sys_call
...@@ -106,7 +106,7 @@ ni_syscall: ...@@ -106,7 +106,7 @@ ni_syscall:
PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend
ENTRY(ia32_ptregs_common) ENTRY(ia32_ptregs_common)
popq %r11 /* save return address outside the stack frame. */ popq %r11
SAVE_REST SAVE_REST
movq %r11, %r15 movq %r11, %r15
call *%rax call *%rax
...@@ -241,14 +241,14 @@ ia32_sys_call_table: ...@@ -241,14 +241,14 @@ ia32_sys_call_table:
.quad stub32_clone /* 120 */ .quad stub32_clone /* 120 */
.quad sys_setdomainname .quad sys_setdomainname
.quad sys_newuname .quad sys_newuname
.quad ni_syscall /* modify_ldt */ .quad sys_modify_ldt
.quad sys32_adjtimex .quad sys32_adjtimex
.quad sys_mprotect /* 125 */ .quad sys32_mprotect /* 125 */
.quad sys32_sigprocmask .quad sys32_sigprocmask
.quad ni_syscall /* query_module */ .quad sys32_module_warning /* create_module */
.quad ni_syscall /* init_module */ .quad sys32_module_warning /* init_module */
.quad ni_syscall /* delete module */ .quad sys32_module_warning /* delete module */
.quad ni_syscall /* 130 get_kernel_syms */ .quad sys32_module_warning /* 130 get_kernel_syms */
.quad ni_syscall /* quotactl */ .quad ni_syscall /* quotactl */
.quad sys_getpgid .quad sys_getpgid
.quad sys_fchdir .quad sys_fchdir
...@@ -287,7 +287,7 @@ ia32_sys_call_table: ...@@ -287,7 +287,7 @@ ia32_sys_call_table:
.quad ni_syscall /* vm86 */ .quad ni_syscall /* vm86 */
.quad ni_syscall /* query_module */ .quad ni_syscall /* query_module */
.quad sys_poll .quad sys_poll
.quad ni_syscall /* nfsserverctl */ .quad sys32_nfsservctl
.quad sys_setresgid16 /* 170 */ .quad sys_setresgid16 /* 170 */
.quad sys_getresgid16 .quad sys_getresgid16
.quad sys_prctl .quad sys_prctl
...@@ -302,8 +302,8 @@ ia32_sys_call_table: ...@@ -302,8 +302,8 @@ ia32_sys_call_table:
.quad sys32_pwrite .quad sys32_pwrite
.quad sys_chown16 .quad sys_chown16
.quad sys_getcwd .quad sys_getcwd
.quad ni_syscall /* capget */ .quad sys_capget
.quad ni_syscall /* capset */ .quad sys_capset
.quad stub32_sigaltstack .quad stub32_sigaltstack
.quad sys32_sendfile .quad sys32_sendfile
.quad ni_syscall /* streams1 */ .quad ni_syscall /* streams1 */
...@@ -338,7 +338,7 @@ ia32_sys_call_table: ...@@ -338,7 +338,7 @@ ia32_sys_call_table:
.quad sys_pivot_root .quad sys_pivot_root
.quad sys_mincore .quad sys_mincore
.quad sys_madvise .quad sys_madvise
.quad sys_getdents64 /* 220 */ .quad sys_getdents64 /* 220 getdents64 */
.quad sys32_fcntl64 .quad sys32_fcntl64
.quad sys_ni_syscall /* tux */ .quad sys_ni_syscall /* tux */
.quad sys_ni_syscall /* security */ .quad sys_ni_syscall /* security */
...@@ -357,6 +357,10 @@ ia32_sys_call_table: ...@@ -357,6 +357,10 @@ ia32_sys_call_table:
.quad sys_lremovexattr .quad sys_lremovexattr
.quad sys_fremovexattr .quad sys_fremovexattr
.quad sys_tkill /* 238 */ .quad sys_tkill /* 238 */
.quad sys_sendfile64
.quad sys_futex
.quad sys32_sched_setaffinity
.quad sys32_sched_getaffinity
ia32_syscall_end: ia32_syscall_end:
.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
.quad ni_syscall .quad ni_syscall
......
/* /*
* 32bit ptrace for x86-64. * 32bit ptrace for x86-64.
* *
* Copyright 2001 Andi Kleen, SuSE Labs. * Copyright 2001,2002 Andi Kleen, SuSE Labs.
* Some parts copied from arch/i386/kernel/ptrace.c. See that file for * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier
* earlier copyright. * copyright.
* *
* This allows to access 64bit processes too but there is no way to see * This allows to access 64bit processes too; but there is no way to see the extended
* the extended register contents. * register contents.
* *
* $Id: ptrace32.c,v 1.2 2001/08/15 06:41:13 ak Exp $ * $Id: ptrace32.c,v 1.12 2002/03/24 13:02:02 ak Exp $
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mm.h>
#include <linux/ptrace.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/user32.h> #include <asm/user32.h>
#include <asm/user.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/debugreg.h> #include <asm/debugreg.h>
#include <asm/i387.h>
#include <asm/fpu32.h>
#include <linux/mm.h>
#define R32(l,q) \ #define R32(l,q) \
case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break
...@@ -139,7 +141,6 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) ...@@ -139,7 +141,6 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
#undef R32 #undef R32
static struct task_struct *find_target(int request, int pid, int *err) static struct task_struct *find_target(int request, int pid, int *err)
{ {
struct task_struct *child; struct task_struct *child;
...@@ -154,23 +155,11 @@ static struct task_struct *find_target(int request, int pid, int *err) ...@@ -154,23 +155,11 @@ static struct task_struct *find_target(int request, int pid, int *err)
if (child) if (child)
get_task_struct(child); get_task_struct(child);
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
if (child) { *err = ptrace_check_attach(child,0);
*err = -ESRCH; if (*err == 0)
if (!(child->ptrace & PT_PTRACED))
goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
goto out;
}
if (child->p_pptr != current)
goto out;
return child; return child;
}
out:
put_task_struct(child); put_task_struct(child);
return NULL; return NULL;
} }
extern asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, unsigned long data); extern asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, unsigned long data);
...@@ -178,6 +167,7 @@ extern asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, un ...@@ -178,6 +167,7 @@ extern asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, un
asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
{ {
struct task_struct *child; struct task_struct *child;
struct pt_regs *childregs;
int ret; int ret;
__u32 val; __u32 val;
...@@ -203,6 +193,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -203,6 +193,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
case PTRACE_SETREGS: case PTRACE_SETREGS:
case PTRACE_SETFPREGS: case PTRACE_SETFPREGS:
case PTRACE_GETFPREGS: case PTRACE_GETFPREGS:
case PTRACE_SETFPXREGS:
case PTRACE_GETFPXREGS:
break; break;
default: default:
...@@ -213,11 +205,13 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -213,11 +205,13 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
if (!child) if (!child)
return ret; return ret;
childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs));
switch (request) { switch (request) {
case PTRACE_PEEKDATA: case PTRACE_PEEKDATA:
case PTRACE_PEEKTEXT: case PTRACE_PEEKTEXT:
ret = 0; ret = 0;
if (access_process_vm(child, addr, &val, sizeof(u32), 0) != sizeof(u32)) if (access_process_vm(child, addr, &val, sizeof(u32), 0)!=sizeof(u32))
ret = -EIO; ret = -EIO;
else else
ret = put_user(val, (unsigned int *)(u64)data); ret = put_user(val, (unsigned int *)(u64)data);
...@@ -226,13 +220,13 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -226,13 +220,13 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
case PTRACE_POKETEXT: case PTRACE_POKETEXT:
ret = 0; ret = 0;
if (access_process_vm(child, addr, &data, sizeof(u32), 1) != sizeof(u32)) if (access_process_vm(child, addr, &data, sizeof(u32), 1)!=sizeof(u32))
ret = -EIO; ret = -EIO;
break; break;
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
ret = getreg32(child, addr, &val); ret = getreg32(child, addr, &val);
if (ret >= 0) if (ret == 0)
ret = put_user(val, (__u32 *)(unsigned long) data); ret = put_user(val, (__u32 *)(unsigned long) data);
break; break;
...@@ -242,7 +236,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -242,7 +236,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
case PTRACE_GETREGS: { /* Get all gp regs from the child. */ case PTRACE_GETREGS: { /* Get all gp regs from the child. */
int i; int i;
if (!access_ok(VERIFY_WRITE, (unsigned *)(unsigned long)data, FRAME_SIZE)) { if (!access_ok(VERIFY_WRITE, (unsigned *)(unsigned long)data, 16*4)) {
ret = -EIO; ret = -EIO;
break; break;
} }
...@@ -258,10 +252,11 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -258,10 +252,11 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
case PTRACE_SETREGS: { /* Set all gp regs in the child. */ case PTRACE_SETREGS: { /* Set all gp regs in the child. */
unsigned long tmp; unsigned long tmp;
int i; int i;
if (!access_ok(VERIFY_READ, (unsigned *)(unsigned long)data, FRAME_SIZE)) { if (!access_ok(VERIFY_READ, (unsigned *)(unsigned long)data, 16*4)) {
ret = -EIO; ret = -EIO;
break; break;
} }
empty_fpu(child);
ret = 0; ret = 0;
for ( i = 0; i <= 16*4; i += sizeof(u32) ) { for ( i = 0; i <= 16*4; i += sizeof(u32) ) {
ret |= __get_user(tmp, (u32 *) (unsigned long) data); ret |= __get_user(tmp, (u32 *) (unsigned long) data);
...@@ -271,35 +266,37 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -271,35 +266,37 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
break; break;
} }
#if 0 /* to be done. */ case PTRACE_SETFPREGS:
case PTRACE_GETFPREGS: { /* Get the child extended FPU state. */ empty_fpu(child);
if (!access_ok(VERIFY_WRITE, (unsigned *)data, save_i387_ia32(child, (void *)(u64)data, childregs, 1);
sizeof(struct user_i387_struct))) { ret = 0;
ret = -EIO;
break; break;
}
if ( !child->used_math ) { case PTRACE_GETFPREGS:
/* Simulate an empty FPU. */ empty_fpu(child);
set_fpu_cwd(child, 0x037f); restore_i387_ia32(child, (void *)(u64)data, 1);
set_fpu_swd(child, 0x0000); ret = 0;
set_fpu_twd(child, 0xffff);
set_fpu_mxcsr(child, 0x1f80);
}
ret = get_fpregs((struct user_i387_struct *)data, child);
break; break;
}
case PTRACE_SETFPREGS: { /* Set the child extended FPU state. */ case PTRACE_GETFPXREGS: {
if (!access_ok(VERIFY_READ, (unsigned *)data, struct user32_fxsr_struct *u = (void *)(u64)data;
sizeof(struct user_i387_struct))) { empty_fpu(child);
ret = -EIO; ret = copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u));
ret |= __put_user(childregs->cs, &u->fcs);
ret |= __put_user(child->thread.ds, &u->fos);
if (ret)
ret = -EFAULT;
break;
}
case PTRACE_SETFPXREGS: {
struct user32_fxsr_struct *u = (void *)(u64)data;
empty_fpu(child);
/* no error checking to be bug to bug compatible with i386 */
copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u));
child->thread.i387.fxsave.mxcsr &= 0xffbf;
ret = 0;
break; break;
} }
child->used_math = 1;
ret = set_fpregs(child, (struct user_i387_struct *)data);
break;
#endif
default: default:
ret = -EINVAL; ret = -EINVAL;
......
This diff is collapsed.
...@@ -19,8 +19,8 @@ export-objs := mtrr.o msr.o cpuid.o x8664_ksyms.o ...@@ -19,8 +19,8 @@ export-objs := mtrr.o msr.o cpuid.o x8664_ksyms.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.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 \ 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 early_printk.o vsyscall.o \ pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \
setup64.o bluesmoke.o setup64.o bluesmoke.o bootflag.o
ifdef CONFIG_PCI ifdef CONFIG_PCI
obj-y += pci-x86_64.o obj-y += pci-x86_64.o
...@@ -33,6 +33,9 @@ obj-$(CONFIG_X86_CPUID) += cpuid.o ...@@ -33,6 +33,9 @@ obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o
#obj-$(CONFIG_ACPI) += acpi.o
#obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
/* Using APIC to generate smp_local_timer_interrupt? */ /* Using APIC to generate smp_local_timer_interrupt? */
int using_apic_timer = 0; int using_apic_timer = 0;
int dont_enable_local_apic __initdata = 0;
int prof_multiplier[NR_CPUS] = { 1, }; int prof_multiplier[NR_CPUS] = { 1, };
int prof_old_multiplier[NR_CPUS] = { 1, }; int prof_old_multiplier[NR_CPUS] = { 1, };
int prof_counter[NR_CPUS] = { 1, }; int prof_counter[NR_CPUS] = { 1, };
...@@ -51,7 +53,7 @@ int get_maxlvt(void) ...@@ -51,7 +53,7 @@ int get_maxlvt(void)
void clear_local_APIC(void) void clear_local_APIC(void)
{ {
int maxlvt; int maxlvt;
unsigned long v; unsigned int v;
maxlvt = get_maxlvt(); maxlvt = get_maxlvt();
...@@ -90,7 +92,7 @@ void clear_local_APIC(void) ...@@ -90,7 +92,7 @@ void clear_local_APIC(void)
apic_write_around(APIC_LVTPC, APIC_LVT_MASKED); apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
v = GET_APIC_VERSION(apic_read(APIC_LVR)); v = GET_APIC_VERSION(apic_read(APIC_LVR));
if (APIC_INTEGRATED(v)) { /* !82489DX */ if (APIC_INTEGRATED(v)) { /* !82489DX */
if (maxlvt > 3) if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
apic_read(APIC_ESR); apic_read(APIC_ESR);
} }
...@@ -130,7 +132,7 @@ void disconnect_bsp_APIC(void) ...@@ -130,7 +132,7 @@ void disconnect_bsp_APIC(void)
void disable_local_APIC(void) void disable_local_APIC(void)
{ {
unsigned long value; unsigned int value;
clear_local_APIC(); clear_local_APIC();
...@@ -223,7 +225,7 @@ extern void __error_in_apic_c (void); ...@@ -223,7 +225,7 @@ extern void __error_in_apic_c (void);
*/ */
void __init init_bsp_APIC(void) void __init init_bsp_APIC(void)
{ {
unsigned long value, ver; unsigned int value, ver;
/* /*
* Don't do the setup now if we have a SMP BIOS as the * Don't do the setup now if we have a SMP BIOS as the
...@@ -262,7 +264,7 @@ void __init init_bsp_APIC(void) ...@@ -262,7 +264,7 @@ void __init init_bsp_APIC(void)
void __init setup_local_APIC (void) void __init setup_local_APIC (void)
{ {
unsigned long value, ver, maxlvt; unsigned int value, ver, maxlvt;
/* Pound the ESR really hard over the head with a big hammer - mbligh */ /* Pound the ESR really hard over the head with a big hammer - mbligh */
if (esr_disable) { if (esr_disable) {
...@@ -395,7 +397,7 @@ void __init setup_local_APIC (void) ...@@ -395,7 +397,7 @@ void __init setup_local_APIC (void)
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
value = apic_read(APIC_ESR); value = apic_read(APIC_ESR);
printk("ESR value before enabling vector: %08lx\n", value); printk("ESR value before enabling vector: %08x\n", value);
value = ERROR_APIC_VECTOR; // enables sending errors value = ERROR_APIC_VECTOR; // enables sending errors
apic_write_around(APIC_LVTERR, value); apic_write_around(APIC_LVTERR, value);
...@@ -405,7 +407,7 @@ void __init setup_local_APIC (void) ...@@ -405,7 +407,7 @@ void __init setup_local_APIC (void)
if (maxlvt > 3) if (maxlvt > 3)
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
value = apic_read(APIC_ESR); value = apic_read(APIC_ESR);
printk("ESR value after enabling vector: %08lx\n", value); printk("ESR value after enabling vector: %08x\n", value);
} else { } else {
if (esr_disable) if (esr_disable)
/* /*
...@@ -449,6 +451,7 @@ static struct { ...@@ -449,6 +451,7 @@ static struct {
unsigned int apic_lvterr; unsigned int apic_lvterr;
unsigned int apic_tmict; unsigned int apic_tmict;
unsigned int apic_tdcr; unsigned int apic_tdcr;
unsigned int apic_thmr;
} apic_pm_state; } apic_pm_state;
static void apic_pm_suspend(void *data) static void apic_pm_suspend(void *data)
...@@ -470,6 +473,7 @@ static void apic_pm_suspend(void *data) ...@@ -470,6 +473,7 @@ static void apic_pm_suspend(void *data)
apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
__save_flags(flags); __save_flags(flags);
__cli(); __cli();
disable_local_APIC(); disable_local_APIC();
...@@ -498,6 +502,7 @@ static void apic_pm_resume(void *data) ...@@ -498,6 +502,7 @@ static void apic_pm_resume(void *data)
apic_write(APIC_SPIV, apic_pm_state.apic_spiv); apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
...@@ -586,7 +591,6 @@ static inline void apic_pm_init2(void) { } ...@@ -586,7 +591,6 @@ static inline void apic_pm_init2(void) { }
static int __init detect_init_APIC (void) static int __init detect_init_APIC (void)
{ {
u32 h, l, features; u32 h, l, features;
int needs_pm = 0;
extern void get_cpu_vendor(struct cpuinfo_x86*); extern void get_cpu_vendor(struct cpuinfo_x86*);
/* Workaround for us being called before identify_cpu(). */ /* Workaround for us being called before identify_cpu(). */
...@@ -619,7 +623,6 @@ static int __init detect_init_APIC (void) ...@@ -619,7 +623,6 @@ static int __init detect_init_APIC (void)
l &= ~MSR_IA32_APICBASE_BASE; l &= ~MSR_IA32_APICBASE_BASE;
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
wrmsr(MSR_IA32_APICBASE, l, h); wrmsr(MSR_IA32_APICBASE, l, h);
needs_pm = 1;
} }
} }
/* /*
...@@ -631,17 +634,13 @@ static int __init detect_init_APIC (void) ...@@ -631,17 +634,13 @@ static int __init detect_init_APIC (void)
printk("Could not enable APIC!\n"); printk("Could not enable APIC!\n");
return -1; return -1;
} }
set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability); set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
boot_cpu_id = 0; boot_cpu_id = 0;
if (nmi_watchdog != NMI_NONE) if (nmi_watchdog != NMI_NONE)
nmi_watchdog = NMI_LOCAL_APIC; nmi_watchdog = NMI_LOCAL_APIC;
printk("Found and enabled local APIC!\n"); printk("Found and enabled local APIC!\n");
if (needs_pm)
apic_pm_init1();
return 0; return 0;
no_apic: no_apic:
...@@ -782,7 +781,7 @@ void __setup_APIC_LVTT(unsigned int clocks) ...@@ -782,7 +781,7 @@ void __setup_APIC_LVTT(unsigned int clocks)
void setup_APIC_timer(void * data) void setup_APIC_timer(void * data)
{ {
unsigned long clocks = (unsigned long) data, slice, t0, t1; unsigned int clocks = (unsigned long) data, slice, t0, t1;
unsigned long flags; unsigned long flags;
int delta; int delta;
...@@ -799,7 +798,8 @@ void setup_APIC_timer(void * data) ...@@ -799,7 +798,8 @@ void setup_APIC_timer(void * data)
*/ */
slice = clocks / (smp_num_cpus+1); slice = clocks / (smp_num_cpus+1);
printk("cpu: %d, clocks: %lu, slice: %lu\n", smp_processor_id(), clocks, slice); printk("cpu: %d, clocks: %d, slice: %d\n",
smp_processor_id(), clocks, slice);
/* /*
* Wait for IRQ0's slice: * Wait for IRQ0's slice:
...@@ -822,7 +822,8 @@ void setup_APIC_timer(void * data) ...@@ -822,7 +822,8 @@ void setup_APIC_timer(void * data)
__setup_APIC_LVTT(clocks); __setup_APIC_LVTT(clocks);
printk("CPU%d<T0:%lu,T1:%lu,D:%d,S:%lu,C:%lu>\n", smp_processor_id(), t0, t1, delta, slice, clocks); printk("CPU%d<T0:%u,T1:%u,D:%d,S:%u,C:%u>\n",
smp_processor_id(), t0, t1, delta, slice, clocks);
__restore_flags(flags); __restore_flags(flags);
} }
...@@ -842,9 +843,9 @@ void setup_APIC_timer(void * data) ...@@ -842,9 +843,9 @@ void setup_APIC_timer(void * data)
int __init calibrate_APIC_clock(void) int __init calibrate_APIC_clock(void)
{ {
unsigned long long t1 = 0, t2 = 0; unsigned long t1 = 0, t2 = 0;
long tt1, tt2; int tt1, tt2;
long result; int result;
int i; int i;
const int LOOPS = HZ/10; const int LOOPS = HZ/10;
...@@ -892,19 +893,23 @@ int __init calibrate_APIC_clock(void) ...@@ -892,19 +893,23 @@ int __init calibrate_APIC_clock(void)
result = (tt1-tt2)*APIC_DIVISOR/LOOPS; result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
printk("t1 = %ld t2 = %ld tt1 = %d tt2 = %d\n", t1, t2, tt1, tt2);
if (cpu_has_tsc) if (cpu_has_tsc)
printk("..... CPU clock speed is %ld.%04ld MHz.\n", printk("..... CPU clock speed is %d.%04d MHz.\n",
((long)(t2-t1)/LOOPS)/(1000000/HZ), ((int)(t2-t1)/LOOPS)/(1000000/HZ),
((long)(t2-t1)/LOOPS)%(1000000/HZ)); ((int)(t2-t1)/LOOPS)%(1000000/HZ));
printk("..... host bus clock speed is %ld.%04ld MHz.\n", printk("..... host bus clock speed is %d.%04d MHz.\n",
result/(1000000/HZ), result/(1000000/HZ),
result%(1000000/HZ)); result%(1000000/HZ));
return result; return result;
} }
static unsigned long calibration_result; static unsigned int calibration_result;
void __init setup_APIC_clocks (void) void __init setup_APIC_clocks (void)
{ {
...@@ -917,12 +922,12 @@ void __init setup_APIC_clocks (void) ...@@ -917,12 +922,12 @@ void __init setup_APIC_clocks (void)
/* /*
* Now set up the timer for real. * Now set up the timer for real.
*/ */
setup_APIC_timer((void *)calibration_result); setup_APIC_timer((void *)(u64)calibration_result);
__sti(); __sti();
/* and update all other cpus */ /* and update all other cpus */
smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1); smp_call_function(setup_APIC_timer, (void *)(u64)calibration_result, 1, 1);
} }
void __init disable_APIC_timer(void) void __init disable_APIC_timer(void)
...@@ -985,7 +990,7 @@ int setup_profiling_timer(unsigned int multiplier) ...@@ -985,7 +990,7 @@ int setup_profiling_timer(unsigned int multiplier)
* value into /proc/profile. * value into /proc/profile.
*/ */
inline void smp_local_timer_interrupt(struct pt_regs * regs) inline void smp_local_timer_interrupt(struct pt_regs *regs)
{ {
int user = user_mode(regs); int user = user_mode(regs);
int cpu = smp_processor_id(); int cpu = smp_processor_id();
...@@ -1041,7 +1046,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) ...@@ -1041,7 +1046,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs)
*/ */
unsigned int apic_timer_irqs [NR_CPUS]; unsigned int apic_timer_irqs [NR_CPUS];
void smp_apic_timer_interrupt(struct pt_regs regs) void smp_apic_timer_interrupt(struct pt_regs *regs)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
...@@ -1061,7 +1066,7 @@ void smp_apic_timer_interrupt(struct pt_regs regs) ...@@ -1061,7 +1066,7 @@ void smp_apic_timer_interrupt(struct pt_regs regs)
* interrupt lock, which is the WrongThing (tm) to do. * interrupt lock, which is the WrongThing (tm) to do.
*/ */
irq_enter(cpu, 0); irq_enter(cpu, 0);
smp_local_timer_interrupt(&regs); smp_local_timer_interrupt(regs);
irq_exit(cpu, 0); irq_exit(cpu, 0);
if (softirq_pending(cpu)) if (softirq_pending(cpu))
...@@ -1073,7 +1078,9 @@ void smp_apic_timer_interrupt(struct pt_regs regs) ...@@ -1073,7 +1078,9 @@ void smp_apic_timer_interrupt(struct pt_regs regs)
*/ */
asmlinkage void smp_spurious_interrupt(void) asmlinkage void smp_spurious_interrupt(void)
{ {
unsigned long v; unsigned int v;
static unsigned long last_warning;
static unsigned long skipped;
/* /*
* Check if this really is a spurious interrupt and ACK it * Check if this really is a spurious interrupt and ACK it
...@@ -1085,8 +1092,13 @@ asmlinkage void smp_spurious_interrupt(void) ...@@ -1085,8 +1092,13 @@ asmlinkage void smp_spurious_interrupt(void)
ack_APIC_irq(); ack_APIC_irq();
/* see sw-dev-man vol 3, chapter 7.4.13.5 */ /* see sw-dev-man vol 3, chapter 7.4.13.5 */
printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n", if (last_warning+30*HZ < jiffies) {
smp_processor_id()); printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
smp_processor_id(), skipped);
last_warning = jiffies;
} else {
skipped++;
}
} }
/* /*
...@@ -1095,7 +1107,7 @@ asmlinkage void smp_spurious_interrupt(void) ...@@ -1095,7 +1107,7 @@ asmlinkage void smp_spurious_interrupt(void)
asmlinkage void smp_error_interrupt(void) asmlinkage void smp_error_interrupt(void)
{ {
unsigned long v, v1; unsigned int v, v1;
/* First tickle the hardware, only then report what went on. -- REW */ /* First tickle the hardware, only then report what went on. -- REW */
v = apic_read(APIC_ESR); v = apic_read(APIC_ESR);
...@@ -1114,7 +1126,7 @@ asmlinkage void smp_error_interrupt(void) ...@@ -1114,7 +1126,7 @@ asmlinkage void smp_error_interrupt(void)
6: Received illegal vector 6: Received illegal vector
7: Illegal register address 7: Illegal register address
*/ */
printk (KERN_ERR "APIC error on CPU%d: %02lx(%02lx)\n", printk (KERN_ERR "APIC error on CPU%d: %02x(%02x)\n",
smp_processor_id(), v , v1); smp_processor_id(), v , v1);
} }
......
...@@ -3,16 +3,127 @@ ...@@ -3,16 +3,127 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/smp.h>
#include <linux/config.h>
#include <linux/irq.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/apic.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
static int mce_disabled __initdata = 0; static int mce_disabled __initdata = 0;
static int banks;
/* /*
* Machine Check Handler For PII/PIII/K7 * If we get an MCE, we don't know what state the caches/TLB's are
* going to be in, so we throw them all away.
*/ */
static void inline flush_all (void)
{
__asm__ __volatile__ ("invd": : );
__flush_tlb();
}
static int banks; /*
* P4/Xeon Thermal transition interrupt handler
*/
static void intel_thermal_interrupt(struct pt_regs *regs)
{
#ifdef CONFIG_X86_LOCAL_APIC
u32 l, h;
unsigned int cpu = smp_processor_id();
ack_APIC_irq();
rdmsr(MSR_IA32_THERM_STATUS, l, h);
if (l & 1) {
printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu);
printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu);
} else {
printk(KERN_INFO "CPU#%d: Temperature/speed normal\n", cpu);
}
#endif
}
static void unexpected_thermal_interrupt(struct pt_regs *regs)
{
printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id());
}
/*
* Thermal interrupt handler for this CPU setup
*/
static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
asmlinkage void smp_thermal_interrupt(struct pt_regs regs)
{
vendor_thermal_interrupt(&regs);
}
/* P4/Xeon Thermal regulation detect and init */
static void __init intel_init_thermal(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_LOCAL_APIC
u32 l, h;
unsigned int cpu = smp_processor_id();
/* Thermal monitoring */
if (!test_bit(X86_FEATURE_ACPI, &c->x86_capability))
return; /* -ENODEV */
/* Clock modulation */
if (!test_bit(X86_FEATURE_ACC, &c->x86_capability))
return; /* -ENODEV */
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
/* first check if its enabled already, in which case there might
* be some SMM goo which handles it, so we can't even put a handler
* since it might be delivered via SMI already -zwanem.
*/
if (l & (1<<3)) {
printk(KERN_DEBUG "CPU#%d: Thermal monitoring already enabled\n", cpu);
} else {
wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
}
/* check wether a vector already exists */
l = apic_read(APIC_LVTTHMR);
if (l & 0xff) {
printk(KERN_DEBUG "CPU#%d: Thermal LVT already handled\n", cpu);
return; /* -EBUSY */
}
wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
/* The temperature transition interrupt handler setup */
l = THERMAL_APIC_VECTOR; /* our delivery vector */
l |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */
apic_write_around(APIC_LVTTHMR, l);
rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x3 , h);
/* ok we're good to go... */
vendor_thermal_interrupt = intel_thermal_interrupt;
l = apic_read(APIC_LVTTHMR);
apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
return;
#endif
}
/*
* Machine Check Handler For PII/PIII
*/
static void intel_machine_check(struct pt_regs * regs, long error_code) static void intel_machine_check(struct pt_regs * regs, long error_code)
{ {
...@@ -21,6 +132,8 @@ static void intel_machine_check(struct pt_regs * regs, long error_code) ...@@ -21,6 +132,8 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
u32 mcgstl, mcgsth; u32 mcgstl, mcgsth;
int i; int i;
flush_all();
rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
if(mcgstl&(1<<0)) /* Recoverable ? */ if(mcgstl&(1<<0)) /* Recoverable ? */
recover=0; recover=0;
...@@ -41,13 +154,12 @@ static void intel_machine_check(struct pt_regs * regs, long error_code) ...@@ -41,13 +154,12 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
if(high&(1<<27)) if(high&(1<<27))
{ {
rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
printk("[%08x%08x]", alow, ahigh); printk("[%08x%08x]", ahigh, alow);
} }
if(high&(1<<26)) if(high&(1<<26))
{ {
rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
printk(" at %08x%08x", printk(" at %08x%08x", ahigh, alow);
ahigh, alow);
} }
printk("\n"); printk("\n");
/* Clear it */ /* Clear it */
...@@ -66,9 +178,13 @@ static void intel_machine_check(struct pt_regs * regs, long error_code) ...@@ -66,9 +178,13 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth); wrmsr(MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
} }
static void unexpected_machine_check(struct pt_regs *regs, long error_code) /*
* Handle unconfigured int18 (should never happen)
*/
static void unexpected_machine_check(struct pt_regs * regs, long error_code)
{ {
printk("unexpected machine check %lx\n", error_code); printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
} }
/* /*
...@@ -77,13 +193,60 @@ static void unexpected_machine_check(struct pt_regs *regs, long error_code) ...@@ -77,13 +193,60 @@ static void unexpected_machine_check(struct pt_regs *regs, long error_code)
static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
void do_machine_check(struct pt_regs * regs, long error_code) asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
{ {
machine_check_vector(regs, error_code); machine_check_vector(regs, error_code);
} }
#ifdef CONFIG_X86_MCE_NONFATAL
struct timer_list mce_timer;
static void mce_checkregs (unsigned int cpu)
{
u32 low, high;
int i;
if (cpu!=smp_processor_id())
BUG();
for (i=0; i<banks; i++) {
rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
if ((low | high) != 0) {
flush_all();
printk (KERN_EMERG "MCE: The hardware reports a non fatal, correctable incident occured on CPU %d.\n", smp_processor_id());
printk (KERN_EMERG "Bank %d: %08x%08x\n", i, high, low);
/* Scrub the error so we don't pick it up in 5 seconds time. */
wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
/* Serialize */
wmb();
}
}
/* Refresh the timer. */
mce_timer.expires = jiffies + 5 * HZ;
add_timer (&mce_timer);
}
static void mce_timerfunc (unsigned long data)
{
int i;
for (i=0; i<smp_num_cpus; i++) {
if (i == smp_processor_id())
mce_checkregs(i);
else
smp_call_function (mce_checkregs, i, 1, 1);
}
}
#endif
/* /*
* Set up machine check reporting for Intel processors * Set up machine check reporting for processors with Intel style MCE
*/ */
static void __init intel_mcheck_init(struct cpuinfo_x86 *c) static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
...@@ -96,14 +259,14 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c) ...@@ -96,14 +259,14 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
* Check for MCE support * Check for MCE support
*/ */
if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) ) if( !test_bit(X86_FEATURE_MCE, c->x86_capability) )
return; return;
/* /*
* Check for PPro style MCA * Check for PPro style MCA
*/ */
if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) ) if( !test_bit(X86_FEATURE_MCA, c->x86_capability) )
return; return;
/* Ok machine check is available */ /* Ok machine check is available */
...@@ -114,19 +277,27 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c) ...@@ -114,19 +277,27 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
if(done==0) if(done==0)
printk(KERN_INFO "Intel machine check architecture supported.\n"); printk(KERN_INFO "Intel machine check architecture supported.\n");
rdmsr(MSR_IA32_MCG_CAP, l, h); rdmsr(MSR_IA32_MCG_CAP, l, h);
if(l&(1<<8)) if(l&(1<<8)) /* Control register present ? */
wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
banks = l&0xff; banks = l&0xff;
for(i=1;i<banks;i++)
{ /* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */
if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6) {
for(i=1; i<banks; i++)
wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
} else {
for(i=0; i<banks; i++)
wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff); wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
} }
for(i=0;i<banks;i++)
{ for(i=0; i<banks; i++)
wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
}
set_in_cr4(X86_CR4_MCE); set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id()); printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
intel_init_thermal(c);
done=1; done=1;
} }
...@@ -134,8 +305,6 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c) ...@@ -134,8 +305,6 @@ static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
* This has to be run for each processor * This has to be run for each processor
*/ */
void __init mcheck_init(struct cpuinfo_x86 *c) void __init mcheck_init(struct cpuinfo_x86 *c)
{ {
if(mce_disabled==1) if(mce_disabled==1)
...@@ -144,15 +313,23 @@ void __init mcheck_init(struct cpuinfo_x86 *c) ...@@ -144,15 +313,23 @@ void __init mcheck_init(struct cpuinfo_x86 *c)
switch(c->x86_vendor) switch(c->x86_vendor)
{ {
case X86_VENDOR_AMD: case X86_VENDOR_AMD:
/* if(c->x86 == 6 || c->x86 == 15) {
* AMD K7 machine check is Intel like
*/
if(c->x86 == 6)
intel_mcheck_init(c); intel_mcheck_init(c);
#ifdef CONFIG_X86_MCE_NONFATAL
/* Set the timer to check for non-fatal errors every 5 seconds */
init_timer (&mce_timer);
mce_timer.expires = jiffies + 5 * HZ;
mce_timer.data = 0;
mce_timer.function = &mce_timerfunc;
add_timer (&mce_timer);
#endif
}
break; break;
case X86_VENDOR_INTEL: case X86_VENDOR_INTEL:
intel_mcheck_init(c); intel_mcheck_init(c);
break; break;
default: default:
break; break;
} }
......
/*
* Implement 'Simple Boot Flag Specification 1.0'
*
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <linux/mc146818rtc.h>
#define SBF_RESERVED (0x78)
#define SBF_PNPOS (1<<0)
#define SBF_BOOTING (1<<1)
#define SBF_DIAG (1<<2)
#define SBF_PARITY (1<<7)
struct sbf_boot
{
u8 sbf_signature[4];
u32 sbf_len;
u8 sbf_revision __attribute((packed));
u8 sbf_csum __attribute((packed));
u8 sbf_oemid[6] __attribute((packed));
u8 sbf_oemtable[8] __attribute((packed));
u8 sbf_revdata[4] __attribute((packed));
u8 sbf_creator[4] __attribute((packed));
u8 sbf_crearev[4] __attribute((packed));
u8 sbf_cmos __attribute((packed));
u8 sbf_spare[3] __attribute((packed));
};
static int sbf_port __initdata = -1;
static int __init sbf_struct_valid(unsigned long tptr)
{
u8 *ap;
u8 v;
unsigned int i;
struct sbf_boot sb;
memcpy_fromio(&sb, tptr, sizeof(sb));
if(sb.sbf_len != 40 && sb.sbf_len != 39)
// 39 on IBM ThinkPad A21m, BIOS version 1.02b (KXET24WW; 2000-12-19).
return 0;
ap = (u8 *)&sb;
v= 0;
for(i=0;i<sb.sbf_len;i++)
v+=*ap++;
if(v)
return 0;
if(memcmp(sb.sbf_signature, "BOOT", 4))
return 0;
if (sb.sbf_len == 39)
printk (KERN_WARNING "SBF: ACPI BOOT descriptor is wrong length (%d)\n",
sb.sbf_len);
sbf_port = sb.sbf_cmos; /* Save CMOS port */
return 1;
}
static int __init parity(u8 v)
{
int x = 0;
int i;
for(i=0;i<8;i++)
{
x^=(v&1);
v>>=1;
}
return x;
}
static void __init sbf_write(u8 v)
{
unsigned long flags;
if(sbf_port != -1)
{
v &= ~SBF_PARITY;
if(!parity(v))
v|=SBF_PARITY;
printk(KERN_INFO "SBF: Setting boot flags 0x%x\n",v);
spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(v, sbf_port);
spin_unlock_irqrestore(&rtc_lock, flags);
}
}
static u8 __init sbf_read(void)
{
u8 v;
unsigned long flags;
if(sbf_port == -1)
return 0;
spin_lock_irqsave(&rtc_lock, flags);
v = CMOS_READ(sbf_port);
spin_unlock_irqrestore(&rtc_lock, flags);
return v;
}
static int __init sbf_value_valid(u8 v)
{
if(v&SBF_RESERVED) /* Reserved bits */
return 0;
if(!parity(v))
return 0;
return 1;
}
static void __init sbf_bootup(void)
{
u8 v;
if(sbf_port == -1)
return;
v = sbf_read();
if(!sbf_value_valid(v))
printk(KERN_WARNING "SBF: Simple boot flag value 0x%x read from CMOS RAM was invalid\n",v);
v &= ~SBF_RESERVED;
v &= ~SBF_BOOTING;
v &= ~SBF_DIAG;
#if defined(CONFIG_ISAPNP)
v |= SBF_PNPOS;
#endif
sbf_write(v);
}
static int __init sbf_init(void)
{
unsigned int i;
void *rsdt;
u32 rsdtlen = 0;
u32 rsdtbase = 0;
u8 sum = 0;
int n;
u8 *p;
for(i=0xE0000; i <= 0xFFFE0; i+=16)
{
p = phys_to_virt(i);
if(memcmp(p, "RSD PTR ", 8))
continue;
sum = 0;
for(n=0; n<20; n++)
sum+=p[n];
if(sum != 0)
continue;
/* So it says RSD PTR and it checksums... */
/*
* Process the RDSP pointer
*/
rsdtbase = *(u32 *)(p+16);
/*
* RSDT length is ACPI 2 only, for ACPI 1 we must map
* and remap.
*/
if(p[15]>1)
rsdtlen = *(u32 *)(p+20);
else
rsdtlen = 36;
if(rsdtlen < 36 || rsdtlen > 1024)
continue;
break;
}
if(i>0xFFFE0)
return 0;
rsdt = ioremap(rsdtbase, rsdtlen);
if(rsdt == 0)
return 0;
i = readl(rsdt + 4);
/*
* Remap if needed
*/
if(i > rsdtlen)
{
rsdtlen = i;
iounmap(rsdt);
rsdt = ioremap(rsdtbase, rsdtlen);
if(rsdt == 0)
return 0;
}
for(n = 0; n < i; n++)
sum += readb(rsdt + n);
if(sum)
{
iounmap(rsdt);
return 0;
}
/* Ok the RSDT checksums too */
for(n = 36; n+3 < i; n += 4)
{
unsigned long rp = readl(rsdt+n);
int len = 4096;
if(rp > 0xFFFFFFFFUL - len)
len = 0xFFFFFFFFUL - rp;
/* Too close to the end!! */
if(len < 20)
continue;
rp = (unsigned long)ioremap(rp, 4096);
if(rp == 0)
continue;
if(sbf_struct_valid(rp))
{
/* Found the BOOT table and processed it */
printk(KERN_INFO "SBF: Simple Boot Flag extension found and enabled.\n");
}
iounmap((void *)rp);
}
iounmap(rsdt);
sbf_bootup();
return 0;
}
module_init(sbf_init);
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/fs.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/fs.h> #include <linux/fs.h>
......
#define printk real_printk
#include <asm/io.h> #include <asm/io.h>
#undef printk
/* This is "wrong" address to access it, we should access it using
0xffff8000000b8000ul; but 0xffff8000000b8000ul is not available #define VGABASE 0xffffffff800b8000ul /* This is "wrong" address to access it, we should access it using 0xffff8000000b8000ul; but 0xffff8000000b8000ul is not available early at boot. */
early at boot. */
#define VGABASE 0xffffffff800b8000ul
#define MAX_YPOS 25 #define MAX_YPOS 25
#define MAX_XPOS 80 #define MAX_XPOS 80
...@@ -62,6 +62,8 @@ early_puts (const char *str) ...@@ -62,6 +62,8 @@ early_puts (const char *str)
static char buf[1024]; static char buf[1024];
int printk(const char *fmt, ...) __attribute__((alias("early_printk")));
int early_printk(const char *fmt, ...) int early_printk(const char *fmt, ...)
{ {
va_list args; va_list args;
......
This diff is collapsed.
...@@ -4,29 +4,30 @@ ...@@ -4,29 +4,30 @@
* Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
* Copyright (C) 2000 Pavel Machek <pavel@suse.cz> * Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
* Copyright (C) 2000 Karsten Keil <kkeil@suse.de> * Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
* Copyright (C) 2001 2002 Andi Kleen <ak@suse.de> * Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
* *
* $Id: head.S,v 1.41 2001/07/05 23:43:45 ak Exp $ * $Id: head.S,v 1.49 2002/03/19 17:39:25 ak Exp $
*/ */
.code64
.text
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/offset.h> #include <asm/msr.h>
/* we don't able to switch in one step to final KERNEL ADDRESS SPACE /* we are not able to switch in one step to the final KERNEL ADRESS SPACE
* because we need identity-mapped pages on setup so define __START_KERNEL to * because we need identity-mapped pages on setup so define __START_KERNEL to
* 0x100000 for this stage * 0x100000 for this stage
* *
*/ */
.text
.code32
/* %bx: 1 if comming from smp trampoline on secondary cpu */
startup_32: startup_32:
.code32
/* /*
* At this point the CPU runs in 32bit protected mode (CS.D = 1) with * At this point the CPU runs in 32bit protected mode (CS.D = 1) with
* paging disabled and the point of this file is to switch to 64bit * paging disabled and the point of this file is to switch to 64bit
...@@ -35,7 +36,9 @@ startup_32: ...@@ -35,7 +36,9 @@ startup_32:
* There is no stack until we set one up. * There is no stack until we set one up.
*/ */
/* As first check if extended functions are implemented */ movl %ebx,%ebp /* Save trampoline flag */
/* First check if extended functions are implemented */
movl $0x80000000, %eax movl $0x80000000, %eax
cpuid cpuid
cmpl $0x80000000, %eax cmpl $0x80000000, %eax
...@@ -46,6 +49,8 @@ startup_32: ...@@ -46,6 +49,8 @@ startup_32:
btl $29, %edx btl $29, %edx
jnc no_long_mode jnc no_long_mode
movl %edx,%edi
/* /*
* Prepare for entering 64bits mode * Prepare for entering 64bits mode
*/ */
...@@ -61,14 +66,23 @@ startup_32: ...@@ -61,14 +66,23 @@ startup_32:
movl %eax, %cr3 movl %eax, %cr3
/* Setup EFER (Extended Feature Enable Register) */ /* Setup EFER (Extended Feature Enable Register) */
movl $0xc0000080, %ecx movl $MSR_EFER, %ecx
rdmsr rdmsr
/* Fool rdmsr and reset %eax to avoid dependences */ /* Fool rdmsr and reset %eax to avoid dependences */
xorl %eax, %eax xorl %eax, %eax
/* Enable Long Mode */ /* Enable Long Mode */
btsl $8, %eax btsl $_EFER_LME, %eax
/* Enable System Call */ /* Enable System Call */
btsl $0, %eax btsl $_EFER_SCE, %eax
#if 0
/* No Execute supported? */
btl $20,%edi
jnc 1f
btsl $_EFER_NX, %eax
1:
#endif
/* Make changes effective */ /* Make changes effective */
wrmsr wrmsr
...@@ -99,27 +113,37 @@ reach_compatibility_mode: ...@@ -99,27 +113,37 @@ reach_compatibility_mode:
* the new gdt/idt that has __KERNEL_CS with CS.L = 1. * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
*/ */
testw %bp,%bp /* secondary CPU? */
jnz second
/* Load new GDT with the 64bit segment using 32bit descriptor */ /* Load new GDT with the 64bit segment using 32bit descriptor */
/* to avoid 32bit relocations we use fixed adresses here */ /* to avoid 32bit relocations we use fixed adresses here */
movl $0x100F00, %eax movl $0x100F00, %eax
lgdt (%eax) lgdt (%eax)
movl $0x100F10, %eax movl $0x100F10, %eax
/* Finally jump in 64bit mode */ /* Finally jump in 64bit mode */
ljmp *(%eax) ljmp *(%eax)
.code64 second:
reach_long64: /* abuse syscall to get into 64bit mode. this way we don't need
/* a working low identity mapping just for the short 32bit roundtrip.
* Where we're running at 0x0000000000100000, and yes, finally XXX kludge. this should not be needed. */
* in 64bit mode. movl $MSR_STAR,%ecx
*/ xorl %eax,%eax
.globl init_rsp movl $(__USER32_CS<<16)|__KERNEL_CS,%edx
wrmsr
/* Setup the first kernel stack (this instruction is modified by smpboot) */ movl $MSR_CSTAR,%ecx
.byte 0x48, 0xb8 /* movq *init_rsp,%rax */ movl $0xffffffff,%edx
init_rsp: movl $0x80100100,%eax # reach_long64 absolute
.quad init_thread_union+THREAD_SIZE wrmsr
movq %rax, %rsp syscall
.code64
.org 0x100
reach_long64:
movq init_rsp(%rip),%rsp
/* zero EFLAGS after setting rsp */ /* zero EFLAGS after setting rsp */
pushq $0 pushq $0
...@@ -133,15 +157,15 @@ init_rsp: ...@@ -133,15 +157,15 @@ init_rsp:
*/ */
lgdt pGDT64 lgdt pGDT64
/* esi is pointer to real mode structure with interesting info.
pass it to C */
movl %esi, %edi
movl $__KERNEL_DS,%eax movl $__KERNEL_DS,%eax
movl %eax,%ss
movl %eax,%ds movl %eax,%ds
movl %eax,%ss
movl %eax,%es movl %eax,%es
/* esi is pointer to real mode structure with interesting info.
pass it to C */
movl %esi, %edi
/* Finally jump to run C code and to be on real kernel address /* Finally jump to run C code and to be on real kernel address
* Since we are running on identity-mapped space we have to jump * Since we are running on identity-mapped space we have to jump
* to the full 64bit address , this is only possible as indirect * to the full 64bit address , this is only possible as indirect
...@@ -150,11 +174,14 @@ init_rsp: ...@@ -150,11 +174,14 @@ init_rsp:
movq initial_code(%rip),%rax movq initial_code(%rip),%rax
jmp *%rax jmp *%rax
/* SMP bootup changes these two */
/* SMP bootup changes this */
.globl initial_code .globl initial_code
initial_code: initial_code:
.quad x86_64_start_kernel .quad x86_64_start_kernel
.globl init_rsp
init_rsp:
.quad init_thread_union+THREAD_SIZE-8
.code32 .code32
ENTRY(no_long_mode) ENTRY(no_long_mode)
...@@ -165,7 +192,7 @@ ENTRY(no_long_mode) ...@@ -165,7 +192,7 @@ ENTRY(no_long_mode)
.org 0xf00 .org 0xf00
pGDT32: pGDT32:
.word gdt32_end-gdt_table32 .word gdt32_end-gdt_table32
.quad gdt_table32-__START_KERNEL+0x100000 .long gdt_table32-__START_KERNEL+0x100000
.org 0xf10 .org 0xf10
ljumpvector: ljumpvector:
...@@ -182,10 +209,9 @@ ENTRY(_stext) ...@@ -182,10 +209,9 @@ ENTRY(_stext)
* 2Mbyte large pages provided by PAE mode) * 2Mbyte large pages provided by PAE mode)
*/ */
.org 0x1000 .org 0x1000
ENTRY(level4_pgt) ENTRY(init_level4_pgt)
.quad 0x0000000000102007 /* -> level3_ident_pgt */ .quad 0x0000000000102007 /* -> level3_ident_pgt */
.fill 255,8,0 .fill 255,8,0
/* __PAGE_OFFSET 0xffff800000000000 */
.quad 0x000000000010a007 .quad 0x000000000010a007
.fill 254,8,0 .fill 254,8,0
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
...@@ -193,7 +219,6 @@ ENTRY(level4_pgt) ...@@ -193,7 +219,6 @@ ENTRY(level4_pgt)
.org 0x2000 .org 0x2000
/* Kernel does not "know" about 4-th level of page tables. */ /* Kernel does not "know" about 4-th level of page tables. */
ENTRY(swapper_pg_dir)
ENTRY(level3_ident_pgt) ENTRY(level3_ident_pgt)
.quad 0x0000000000104007 .quad 0x0000000000104007
.fill 511,8,0 .fill 511,8,0
...@@ -207,10 +232,8 @@ ENTRY(level3_kernel_pgt) ...@@ -207,10 +232,8 @@ ENTRY(level3_kernel_pgt)
.org 0x4000 .org 0x4000
ENTRY(level2_ident_pgt) ENTRY(level2_ident_pgt)
/* 2 Mbytes are enough, this is necessary only for head.S */ /* 40MB for bootup. */
.quad 0x0000000000000283 .quad 0x0000000000000283
/* .fill 511,8,0 */
/* Jan needs more than 2Mbytes, so set a 40Mbyte mapping instead */
.quad 0x0000000000200183 .quad 0x0000000000200183
.quad 0x0000000000400183 .quad 0x0000000000400183
.quad 0x0000000000600183 .quad 0x0000000000600183
...@@ -230,10 +253,15 @@ ENTRY(level2_ident_pgt) ...@@ -230,10 +253,15 @@ ENTRY(level2_ident_pgt)
.quad 0x0000000002200183 .quad 0x0000000002200183
.quad 0x0000000002400183 .quad 0x0000000002400183
.quad 0x0000000002600183 .quad 0x0000000002600183
/* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */
.globl temp_boot_pmds
temp_boot_pmds:
.fill 492,8,0 .fill 492,8,0
.org 0x5000 .org 0x5000
ENTRY(level2_kernel_pgt) ENTRY(level2_kernel_pgt)
/* 40MB kernel mapping. The kernel code cannot be bigger than that.
When you change this change KERNEL_TEXT_SIZE in pgtable.h too. */
/* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */
.quad 0x0000000000000183 .quad 0x0000000000000183
.quad 0x0000000000200183 .quad 0x0000000000200183
...@@ -255,11 +283,7 @@ ENTRY(level2_kernel_pgt) ...@@ -255,11 +283,7 @@ ENTRY(level2_kernel_pgt)
.quad 0x0000000002200183 .quad 0x0000000002200183
.quad 0x0000000002400183 .quad 0x0000000002400183
.quad 0x0000000002600183 .quad 0x0000000002600183
/* /* Module mapping starts here */
* We could go ahead without any downside (except typing programmer
* wise :) but 40Mbyte are just enough for the kernel statically
* linked part (and extending it is trivial).
*/
.fill 492,8,0 .fill 492,8,0
.org 0x6000 .org 0x6000
...@@ -278,11 +302,7 @@ ENTRY(empty_bad_pmd_table) ...@@ -278,11 +302,7 @@ ENTRY(empty_bad_pmd_table)
ENTRY(level3_physmem_pgt) ENTRY(level3_physmem_pgt)
.quad 0x0000000000105007 /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */ .quad 0x0000000000105007 /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
.org 0xb000 .org 0xb000
.data .data
.globl SYMBOL_NAME(gdt) .globl SYMBOL_NAME(gdt)
...@@ -317,16 +337,17 @@ ENTRY(gdt_table) ...@@ -317,16 +337,17 @@ ENTRY(gdt_table)
.quad 0x00cffe000000ffff /* __USER32_CS */ .quad 0x00cffe000000ffff /* __USER32_CS */
.quad 0x00cff2000000ffff /* __USER_DS, __USER32_DS */ .quad 0x00cff2000000ffff /* __USER_DS, __USER32_DS */
.quad 0x00affa000000ffff /* __USER_CS */ .quad 0x00affa000000ffff /* __USER_CS */
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9A00 # code read/exec
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
/* __KERNEL32_CS */
.globl tss_start .globl tss_start
tss_start: tss_start:
.rept NR_CPUS .rept NR_CPUS
.quad 0,0 /* TSS descriptors. filled in later */ .quad 0,0,0,0,0,0,0,0 /* TSS/LDT/per cpu entries. filled in later */
.endr
.globl ldt_start
ldt_start:
.rept NR_CPUS
.quad 0,0 /* LDT descriptors. filled in later */
.endr .endr
gdt_end: gdt_end:
.globl gdt_end .globl gdt_end
...@@ -337,6 +358,3 @@ ENTRY(idt_table) ...@@ -337,6 +358,3 @@ ENTRY(idt_table)
.quad 0 .quad 0
.quad 0 .quad 0
.endr .endr
.section .text.lock
ENTRY(stext_lock)
...@@ -64,7 +64,7 @@ static void __init setup_boot_cpu_data(void) ...@@ -64,7 +64,7 @@ static void __init setup_boot_cpu_data(void)
(int *)&boot_cpu_data.x86_vendor_id[4]); (int *)&boot_cpu_data.x86_vendor_id[4]);
/* get cpu type */ /* get cpu type */
cpuid(1, &eax, &dummy, &dummy, &boot_cpu_data.x86_capability[0]); cpuid(1, &eax, &dummy, &dummy, (int *) &boot_cpu_data.x86_capability);
boot_cpu_data.x86 = (eax >> 8) & 0xf; boot_cpu_data.x86 = (eax >> 8) & 0xf;
boot_cpu_data.x86_model = (eax >> 4) & 0xf; boot_cpu_data.x86_model = (eax >> 4) & 0xf;
boot_cpu_data.x86_mask = eax & 0xf; boot_cpu_data.x86_mask = eax & 0xf;
......
This diff is collapsed.
This diff is collapsed.
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/thread_info.h>
static struct fs_struct init_fs = INIT_FS; static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES; static struct files_struct init_files = INIT_FILES;
...@@ -15,7 +14,7 @@ static struct signal_struct init_signals = INIT_SIGNALS; ...@@ -15,7 +14,7 @@ static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm); struct mm_struct init_mm = INIT_MM(init_mm);
/* /*
* Initial thread structure. * Initial task structure.
* *
* We need to make sure that this is 8192-byte aligned due to the * We need to make sure that this is 8192-byte aligned due to the
* way process stacks are handled. This is done by having a special * way process stacks are handled. This is done by having a special
...@@ -39,4 +38,9 @@ struct task_struct init_task = INIT_TASK(init_task); ...@@ -39,4 +38,9 @@ struct task_struct init_task = INIT_TASK(init_task);
* section. Since TSS's are completely CPU-local, we want them * section. Since TSS's are completely CPU-local, we want them
* on exact cacheline boundaries, to eliminate cacheline ping-pong. * on exact cacheline boundaries, to eliminate cacheline ping-pong.
*/ */
struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS }; struct tss_struct init_tss[NR_CPUS] __cacheline_aligned;
#define ALIGN_TO_4K __attribute__((section(".data.init_task")))
pgd_t boot_vmalloc_pgt[512] ALIGN_TO_4K;
...@@ -67,7 +67,7 @@ static struct irq_pin_list { ...@@ -67,7 +67,7 @@ static struct irq_pin_list {
* shared ISA-space IRQs, so we have to support them. We are super * shared ISA-space IRQs, so we have to support them. We are super
* fast in the common case, and fast for shared ISA-space IRQs. * fast in the common case, and fast for shared ISA-space IRQs.
*/ */
static void add_pin_to_irq(unsigned int irq, int apic, int pin) static void __init add_pin_to_irq(unsigned int irq, int apic, int pin)
{ {
static int first_free_entry = NR_IRQS; static int first_free_entry = NR_IRQS;
struct irq_pin_list *entry = irq_2_pin + irq; struct irq_pin_list *entry = irq_2_pin + irq;
......
...@@ -354,7 +354,7 @@ static inline void get_irqlock(int cpu) ...@@ -354,7 +354,7 @@ static inline void get_irqlock(int cpu)
*/ */
void __global_cli(void) void __global_cli(void)
{ {
unsigned int flags; unsigned long flags;
__save_flags(flags); __save_flags(flags);
if (flags & (1 << EFLAGS_IF_SHIFT)) { if (flags & (1 << EFLAGS_IF_SHIFT)) {
...@@ -570,12 +570,14 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) ...@@ -570,12 +570,14 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
* 0 return value means that this irq is already being * 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled) * handled by some other CPU. (or is disabled)
*/ */
int irq = regs->orig_rax & 0xff; /* high bits used in ret_from_ code */ unsigned irq = regs->orig_rax & 0xff; /* high bits used in ret_from_ code */
int cpu = smp_processor_id(); int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = irq_desc + irq;
struct irqaction * action; struct irqaction * action;
unsigned int status; unsigned int status;
if (irq > 256) BUG();
kstat.irqs[cpu][irq]++; kstat.irqs[cpu][irq]++;
spin_lock(&desc->lock); spin_lock(&desc->lock);
desc->handler->ack(irq); desc->handler->ack(irq);
...@@ -632,6 +634,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) ...@@ -632,6 +634,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
* The ->end() handler has to deal with interrupts which got * The ->end() handler has to deal with interrupts which got
* disabled while the handler was running. * disabled while the handler was running.
*/ */
if (irq > 256) BUG();
desc->handler->end(irq); desc->handler->end(irq);
spin_unlock(&desc->lock); spin_unlock(&desc->lock);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -14,8 +14,6 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, ...@@ -14,8 +14,6 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
void *ret; void *ret;
int gfp = GFP_ATOMIC; int gfp = GFP_ATOMIC;
/* We need to always allocate below 4Gig. We probably need new
GPF mask to say that */
gfp |= GFP_DMA; gfp |= GFP_DMA;
ret = (void *)__get_free_pages(gfp, get_order(size)); ret = (void *)__get_free_pages(gfp, get_order(size));
......
This diff is collapsed.
This diff is collapsed.
...@@ -18,9 +18,11 @@ ...@@ -18,9 +18,11 @@
#define PCI_NO_SORT 0x0100 #define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200 #define PCI_BIOS_SORT 0x0200
#define PCI_NO_CHECKS 0x0400 #define PCI_NO_CHECKS 0x0400
#define PCI_USE_PIRQ_MASK 0x0800
#define PCI_ASSIGN_ROMS 0x1000 #define PCI_ASSIGN_ROMS 0x1000
#define PCI_BIOS_IRQ_SCAN 0x2000 #define PCI_BIOS_IRQ_SCAN 0x2000
#define PCI_ASSIGN_ALL_BUSSES 0x4000 #define PCI_ASSIGN_ALL_BUSSES 0x4000
#define PCI_NO_ACPI_ROUTING 0x8000
extern unsigned int pci_probe; extern unsigned int pci_probe;
...@@ -67,6 +69,8 @@ struct irq_routing_table { ...@@ -67,6 +69,8 @@ struct irq_routing_table {
extern unsigned int pcibios_irq_mask; extern unsigned int pcibios_irq_mask;
extern int pci_use_acpi_routing;
void pcibios_irq_init(void); void pcibios_irq_init(void);
void pcibios_fixup_irqs(void); void pcibios_fixup_irqs(void);
void pcibios_enable_irq(struct pci_dev *dev); void pcibios_enable_irq(struct pci_dev *dev);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment