Commit 4522d582 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6

* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6: (156 commits)
  [PATCH] x86-64: Export smp_call_function_single
  [PATCH] i386: Clean up smp_tune_scheduling()
  [PATCH] unwinder: move .eh_frame to RODATA
  [PATCH] unwinder: fully support linker generated .eh_frame_hdr section
  [PATCH] x86-64: don't use set_irq_regs()
  [PATCH] x86-64: check vector in setup_ioapic_dest to verify if need setup_IO_APIC_irq
  [PATCH] x86-64: Make ix86 default to HIGHMEM4G instead of NOHIGHMEM
  [PATCH] i386: replace kmalloc+memset with kzalloc
  [PATCH] x86-64: remove remaining pc98 code
  [PATCH] x86-64: remove unused variable
  [PATCH] x86-64: Fix constraints in atomic_add_return()
  [PATCH] x86-64: fix asm constraints in i386 atomic_add_return
  [PATCH] x86-64: Correct documentation for bzImage protocol v2.05
  [PATCH] x86-64: replace kmalloc+memset with kzalloc in MTRR code
  [PATCH] x86-64: Fix numaq build error
  [PATCH] x86-64: include/asm-x86_64/cpufeature.h isn't a userspace header
  [PATCH] unwinder: Add debugging output to the Dwarf2 unwinder
  [PATCH] x86-64: Clarify error message in GART code
  [PATCH] x86-64: Fix interrupt race in idle callback (3rd try)
  [PATCH] x86-64: Remove unwind stack pointer alignment forcing again
  ...

Fixed conflict in include/linux/uaccess.h manually
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parents 6cf24f03 64a26a73
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
---------------------------- ----------------------------
H. Peter Anvin <hpa@zytor.com> H. Peter Anvin <hpa@zytor.com>
Last update 2005-09-02 Last update 2006-11-17
On the i386 platform, the Linux kernel uses a rather complicated boot On the i386 platform, the Linux kernel uses a rather complicated boot
convention. This has evolved partially due to historical aspects, as convention. This has evolved partially due to historical aspects, as
...@@ -35,6 +35,8 @@ Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible ...@@ -35,6 +35,8 @@ Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
initrd address available to the bootloader. initrd address available to the bootloader.
Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes. Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable.
Introduce relocatable_kernel and kernel_alignment fields.
**** MEMORY LAYOUT **** MEMORY LAYOUT
...@@ -129,6 +131,8 @@ Offset Proto Name Meaning ...@@ -129,6 +131,8 @@ Offset Proto Name Meaning
0226/2 N/A pad1 Unused 0226/2 N/A pad1 Unused
0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line 0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line
022C/4 2.03+ initrd_addr_max Highest legal initrd address 022C/4 2.03+ initrd_addr_max Highest legal initrd address
0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel
0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not
(1) For backwards compatibility, if the setup_sects field contains 0, the (1) For backwards compatibility, if the setup_sects field contains 0, the
real value is 4. real value is 4.
......
...@@ -599,8 +599,6 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -599,8 +599,6 @@ and is between 256 and 4096 characters. It is defined in the file
hugepages= [HW,IA-32,IA-64] Maximal number of HugeTLB pages. hugepages= [HW,IA-32,IA-64] Maximal number of HugeTLB pages.
noirqbalance [IA-32,SMP,KNL] Disable kernel irq balancing
i8042.direct [HW] Put keyboard port into non-translated mode i8042.direct [HW] Put keyboard port into non-translated mode
i8042.dumbkbd [HW] Pretend that controller can only read data from i8042.dumbkbd [HW] Pretend that controller can only read data from
keyboard and cannot control its state keyboard and cannot control its state
...@@ -1065,9 +1063,14 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1065,9 +1063,14 @@ and is between 256 and 4096 characters. It is defined in the file
in certain environments such as networked servers or in certain environments such as networked servers or
real-time systems. real-time systems.
noirqbalance [IA-32,SMP,KNL] Disable kernel irq balancing
noirqdebug [IA-32] Disables the code which attempts to detect and noirqdebug [IA-32] Disables the code which attempts to detect and
disable unhandled interrupt sources. disable unhandled interrupt sources.
no_timer_check [IA-32,X86_64,APIC] Disables the code which tests for
broken timer IRQ sources.
noisapnp [ISAPNP] Disables ISA PnP code. noisapnp [ISAPNP] Disables ISA PnP code.
noinitrd [RAM] Tells the kernel not to load any configured noinitrd [RAM] Tells the kernel not to load any configured
...@@ -1752,6 +1755,9 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1752,6 +1755,9 @@ and is between 256 and 4096 characters. It is defined in the file
norandmaps Don't use address space randomization norandmaps Don't use address space randomization
Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space
unwind_debug=N N > 0 will enable dwarf2 unwinder debugging
This is useful to get more information why
you got a "dwarf2 unwinder stuck"
______________________________________________________________________ ______________________________________________________________________
......
...@@ -62,9 +62,6 @@ consider the following facts about the Linux kernel: ...@@ -62,9 +62,6 @@ consider the following facts about the Linux kernel:
- different structures can contain different fields - different structures can contain different fields
- Some functions may not be implemented at all, (i.e. some locks - Some functions may not be implemented at all, (i.e. some locks
compile away to nothing for non-SMP builds.) compile away to nothing for non-SMP builds.)
- Parameter passing of variables from function to function can be
done in different ways (the CONFIG_REGPARM option controls
this.)
- Memory within the kernel can be aligned in different ways, - Memory within the kernel can be aligned in different ways,
depending on the build options. depending on the build options.
- Linux runs on a wide range of different processor architectures. - Linux runs on a wide range of different processor architectures.
......
...@@ -27,6 +27,7 @@ show up in /proc/sys/kernel: ...@@ -27,6 +27,7 @@ show up in /proc/sys/kernel:
- hotplug - hotplug
- java-appletviewer [ binfmt_java, obsolete ] - java-appletviewer [ binfmt_java, obsolete ]
- java-interpreter [ binfmt_java, obsolete ] - java-interpreter [ binfmt_java, obsolete ]
- kstack_depth_to_print [ X86 only ]
- l2cr [ PPC only ] - l2cr [ PPC only ]
- modprobe ==> Documentation/kmod.txt - modprobe ==> Documentation/kmod.txt
- msgmax - msgmax
...@@ -170,6 +171,13 @@ This flag controls the L2 cache of G3 processor boards. If ...@@ -170,6 +171,13 @@ This flag controls the L2 cache of G3 processor boards. If
============================================================== ==============================================================
kstack_depth_to_print: (X86 only)
Controls the number of words to print when dumping the raw
kernel stack.
==============================================================
osrelease, ostype & version: osrelease, ostype & version:
# cat osrelease # cat osrelease
......
...@@ -52,10 +52,6 @@ APICs ...@@ -52,10 +52,6 @@ APICs
apicmaintimer. Useful when your PIT timer is totally apicmaintimer. Useful when your PIT timer is totally
broken. broken.
disable_8254_timer / enable_8254_timer
Enable interrupt 0 timer routing over the 8254 in addition to over
the IO-APIC. The kernel tries to set a sensible default.
Early Console Early Console
syntax: earlyprintk=vga syntax: earlyprintk=vga
...@@ -183,7 +179,7 @@ PCI ...@@ -183,7 +179,7 @@ PCI
IOMMU IOMMU
iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
[,forcesac][,fullflush][,nomerge][,noaperture] [,forcesac][,fullflush][,nomerge][,noaperture][,calgary]
size set size of iommu (in bytes) size set size of iommu (in bytes)
noagp don't initialize the AGP driver and use full aperture. noagp don't initialize the AGP driver and use full aperture.
off don't use the IOMMU off don't use the IOMMU
...@@ -204,6 +200,7 @@ IOMMU ...@@ -204,6 +200,7 @@ IOMMU
buffering. buffering.
nodac Forbid DMA >4GB nodac Forbid DMA >4GB
panic Always panic when IOMMU overflows panic Always panic when IOMMU overflows
calgary Use the Calgary IOMMU if it is available
swiotlb=pages[,force] swiotlb=pages[,force]
......
...@@ -70,6 +70,7 @@ SECTIONS ...@@ -70,6 +70,7 @@ SECTIONS
#endif #endif
.text : .text :
{ {
_text = .;
#if defined(CONFIG_ROMKERNEL) #if defined(CONFIG_ROMKERNEL)
*(.int_redirect) *(.int_redirect)
#endif #endif
......
...@@ -182,6 +182,17 @@ config X86_ES7000 ...@@ -182,6 +182,17 @@ config X86_ES7000
endchoice endchoice
config PARAVIRT
bool "Paravirtualization support (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
Paravirtualization is a way of running multiple instances of
Linux on the same machine, under a hypervisor. This option
changes the kernel so it can modify itself when it is run
under a hypervisor, improving performance significantly.
However, when run without a hypervisor the kernel is
theoretically slower. If in doubt, say N.
config ACPI_SRAT config ACPI_SRAT
bool bool
default y default y
...@@ -443,7 +454,8 @@ source "drivers/firmware/Kconfig" ...@@ -443,7 +454,8 @@ source "drivers/firmware/Kconfig"
choice choice
prompt "High Memory Support" prompt "High Memory Support"
default NOHIGHMEM default HIGHMEM4G if !X86_NUMAQ
default HIGHMEM64G if X86_NUMAQ
config NOHIGHMEM config NOHIGHMEM
bool "off" bool "off"
...@@ -710,20 +722,6 @@ config BOOT_IOREMAP ...@@ -710,20 +722,6 @@ config BOOT_IOREMAP
depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
default y default y
config REGPARM
bool "Use register arguments"
default y
help
Compile the kernel with -mregparm=3. This instructs gcc to use
a more efficient function call ABI which passes the first three
arguments of a function call via registers, which results in denser
and faster code.
If this option is disabled, then the default ABI of passing
arguments via the stack is used.
If unsure, say Y.
config SECCOMP config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode" bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS depends on PROC_FS
...@@ -773,23 +771,39 @@ config CRASH_DUMP ...@@ -773,23 +771,39 @@ config CRASH_DUMP
PHYSICAL_START. PHYSICAL_START.
For more details see Documentation/kdump/kdump.txt For more details see Documentation/kdump/kdump.txt
config PHYSICAL_START config RELOCATABLE
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) bool "Build a relocatable kernel(EXPERIMENTAL)"
depends on EXPERIMENTAL
help
This build a kernel image that retains relocation information
so it can be loaded someplace besides the default 1MB.
The relocations tend to the kernel binary about 10% larger,
but are discarded at runtime.
One use is for the kexec on panic case where the recovery kernel
must live at a different physical address than the primary
kernel.
default "0x1000000" if CRASH_DUMP config PHYSICAL_ALIGN
hex "Alignment value to which kernel should be aligned"
default "0x100000" default "0x100000"
range 0x2000 0x400000
help help
This gives the physical address where the kernel is loaded. Normally This value puts the alignment restrictions on physical address
for regular kernels this value is 0x100000 (1MB). But in the case where kernel is loaded and run from. Kernel is compiled for an
of kexec on panic the fail safe kernel needs to run at a different address which meets above alignment restriction.
address than the panic-ed kernel. This option is used to set the load
address for kernels used to capture crash dump on being kexec'ed If bootloader loads the kernel at a non-aligned address and
after panic. The default value for crash dump kernels is CONFIG_RELOCATABLE is set, kernel will move itself to nearest
0x1000000 (16MB). This can also be set based on the "X" value as address aligned to above value and run from there.
specified in the "crashkernel=YM@XM" command line boot parameter
passed to the panic-ed kernel. Typically this parameter is set as If bootloader loads the kernel at a non-aligned address and
crashkernel=64M@16M. Please take a look at CONFIG_RELOCATABLE is not set, kernel will ignore the run time
Documentation/kdump/kdump.txt for more details about crash dumps. load address and decompress itself to the address it has been
compiled for and run from there. The address for which kernel is
compiled already meets above alignment restrictions. Hence the
end result is that kernel runs from a physical address meeting
above alignment restrictions.
Don't change this unless you know what you are doing. Don't change this unless you know what you are doing.
......
...@@ -103,8 +103,15 @@ config MPENTIUMM ...@@ -103,8 +103,15 @@ config MPENTIUMM
Select this for Intel Pentium M (not Pentium-4 M) Select this for Intel Pentium M (not Pentium-4 M)
notebook chips. notebook chips.
config MCORE2
bool "Core 2/newer Xeon"
help
Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
CPUs. You can distingush newer from older Xeons by the CPU family
in /proc/cpuinfo. Newer ones have 6.
config MPENTIUM4 config MPENTIUM4
bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon" bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon"
help help
Select this for Intel Pentium 4 chips. This includes the Select this for Intel Pentium 4 chips. This includes the
Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M
...@@ -229,7 +236,7 @@ config X86_L1_CACHE_SHIFT ...@@ -229,7 +236,7 @@ config X86_L1_CACHE_SHIFT
default "7" if MPENTIUM4 || X86_GENERIC default "7" if MPENTIUM4 || X86_GENERIC
default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
default "6" if MK7 || MK8 || MPENTIUMM default "6" if MK7 || MK8 || MPENTIUMM || MCORE2
config RWSEM_GENERIC_SPINLOCK config RWSEM_GENERIC_SPINLOCK
bool bool
...@@ -287,17 +294,17 @@ config X86_ALIGNMENT_16 ...@@ -287,17 +294,17 @@ config X86_ALIGNMENT_16
config X86_GOOD_APIC config X86_GOOD_APIC
bool bool
depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2
default y default y
config X86_INTEL_USERCOPY config X86_INTEL_USERCOPY
bool bool
depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
default y default y
config X86_USE_PPRO_CHECKSUM config X86_USE_PPRO_CHECKSUM
bool bool
depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2
default y default y
config X86_USE_3DNOW config X86_USE_3DNOW
...@@ -312,5 +319,5 @@ config X86_OOSTORE ...@@ -312,5 +319,5 @@ config X86_OOSTORE
config X86_TSC config X86_TSC
bool bool
depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ
default y default y
...@@ -85,4 +85,14 @@ config DOUBLEFAULT ...@@ -85,4 +85,14 @@ config DOUBLEFAULT
option saves about 4k and might cause you much additional grey option saves about 4k and might cause you much additional grey
hair. hair.
config DEBUG_PARAVIRT
bool "Enable some paravirtualization debugging"
default y
depends on PARAVIRT && DEBUG_KERNEL
help
Currently deliberately clobbers regs which are allowed to be
clobbered in inlined paravirt hooks, even in native mode.
If turning this off solves a problem, then DISABLE_INTERRUPTS() or
ENABLE_INTERRUPTS() is lying about what registers can be clobbered.
endmenu endmenu
...@@ -26,10 +26,12 @@ endif ...@@ -26,10 +26,12 @@ endif
LDFLAGS := -m elf_i386 LDFLAGS := -m elf_i386
OBJCOPYFLAGS := -O binary -R .note -R .comment -S OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux := ifdef CONFIG_RELOCATABLE
LDFLAGS_vmlinux := --emit-relocs
endif
CHECKFLAGS += -D__i386__ CHECKFLAGS += -D__i386__
CFLAGS += -pipe -msoft-float CFLAGS += -pipe -msoft-float -mregparm=3
# prevent gcc from keeping the stack 16 byte aligned # prevent gcc from keeping the stack 16 byte aligned
CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
...@@ -37,8 +39,6 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) ...@@ -37,8 +39,6 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
# CPU-specific tuning. Anything which can be shared with UML should go here. # CPU-specific tuning. Anything which can be shared with UML should go here.
include $(srctree)/arch/i386/Makefile.cpu include $(srctree)/arch/i386/Makefile.cpu
cflags-$(CONFIG_REGPARM) += -mregparm=3
# temporary until string.h is fixed # temporary until string.h is fixed
cflags-y += -ffreestanding cflags-y += -ffreestanding
......
...@@ -32,6 +32,7 @@ cflags-$(CONFIG_MWINCHIP2) += $(call cc-option,-march=winchip2,-march=i586) ...@@ -32,6 +32,7 @@ cflags-$(CONFIG_MWINCHIP2) += $(call cc-option,-march=winchip2,-march=i586)
cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586)
cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686)
cflags-$(CONFIG_MCORE2) += -march=i686 $(call cc-option,-mtune=core2,$(call cc-option,-mtune=generic,-mtune=i686))
# AMD Elan support # AMD Elan support
cflags-$(CONFIG_X86_ELAN) += -march=i486 cflags-$(CONFIG_X86_ELAN) += -march=i486
......
...@@ -4,22 +4,42 @@ ...@@ -4,22 +4,42 @@
# create a compressed vmlinux image from the original vmlinux # create a compressed vmlinux image from the original vmlinux
# #
targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
vmlinux.bin.all vmlinux.relocs
EXTRA_AFLAGS := -traditional EXTRA_AFLAGS := -traditional
LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 LDFLAGS_vmlinux := -T
CFLAGS_misc.o += -fPIC
hostprogs-y := relocs
$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE $(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
$(call if_changed,ld) $(call if_changed,ld)
@: @:
$(obj)/vmlinux.bin: vmlinux FORCE $(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy) $(call if_changed,objcopy)
quiet_cmd_relocs = RELOCS $@
cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
$(call if_changed,relocs)
vmlinux.bin.all-y := $(obj)/vmlinux.bin
vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
quiet_cmd_relocbin = BUILD $@
cmd_relocbin = cat $(filter-out FORCE,$^) > $@
$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
$(call if_changed,relocbin)
ifdef CONFIG_RELOCATABLE
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
$(call if_changed,gzip)
else
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
$(call if_changed,gzip) $(call if_changed,gzip)
endif
LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE $(obj)/piggy.o: $(src)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
$(call if_changed,ld) $(call if_changed,ld)
...@@ -26,7 +26,9 @@ ...@@ -26,7 +26,9 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/boot.h>
.section ".text.head"
.globl startup_32 .globl startup_32
startup_32: startup_32:
...@@ -37,93 +39,142 @@ startup_32: ...@@ -37,93 +39,142 @@ startup_32:
movl %eax,%es movl %eax,%es
movl %eax,%fs movl %eax,%fs
movl %eax,%gs movl %eax,%gs
movl %eax,%ss
lss stack_start,%esp /* Calculate the delta between where we were compiled to run
xorl %eax,%eax * at and where we were actually loaded at. This can only be done
1: incl %eax # check that A20 really IS enabled * with a short local call on x86. Nothing else will tell us what
movl %eax,0x000000 # loop forever if it isn't * address we are running at. The reserved chunk of the real-mode
cmpl %eax,0x100000 * data at 0x34-0x3f are used as the stack for this calculation.
je 1b * Only 4 bytes are needed.
*/
leal 0x40(%esi), %esp
call 1f
1: popl %ebp
subl $1b, %ebp
/* %ebp contains the address we are loaded at by the boot loader and %ebx
* contains the address where we should move the kernel image temporarily
* for safe in-place decompression.
*/
#ifdef CONFIG_RELOCATABLE
movl %ebp, %ebx
addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
#else
movl $LOAD_PHYSICAL_ADDR, %ebx
#endif
/* Replace the compressed data size with the uncompressed size */
subl input_len(%ebp), %ebx
movl output_len(%ebp), %eax
addl %eax, %ebx
/* Add 8 bytes for every 32K input block */
shrl $12, %eax
addl %eax, %ebx
/* Add 32K + 18 bytes of extra slack */
addl $(32768 + 18), %ebx
/* Align on a 4K boundary */
addl $4095, %ebx
andl $~4095, %ebx
/* Copy the compressed kernel to the end of our buffer
* where decompression in place becomes safe.
*/
pushl %esi
leal _end(%ebp), %esi
leal _end(%ebx), %edi
movl $(_end - startup_32), %ecx
std
rep
movsb
cld
popl %esi
/* Compute the kernel start address.
*/
#ifdef CONFIG_RELOCATABLE
addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebp
andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp
#else
movl $LOAD_PHYSICAL_ADDR, %ebp
#endif
/* /*
* Initialize eflags. Some BIOS's leave bits like NT set. This would * Jump to the relocated address.
* confuse the debugger if this code is traced.
* XXX - best to initialize before switching to protected mode.
*/ */
pushl $0 leal relocated(%ebx), %eax
popfl jmp *%eax
.section ".text"
relocated:
/* /*
* Clear BSS * Clear BSS
*/ */
xorl %eax,%eax xorl %eax,%eax
movl $_edata,%edi leal _edata(%ebx),%edi
movl $_end,%ecx leal _end(%ebx), %ecx
subl %edi,%ecx subl %edi,%ecx
cld cld
rep rep
stosb stosb
/*
* Setup the stack for the decompressor
*/
leal stack_end(%ebx), %esp
/* /*
* Do the decompression, and jump to the new kernel.. * Do the decompression, and jump to the new kernel..
*/ */
subl $16,%esp # place for structure on the stack movl output_len(%ebx), %eax
movl %esp,%eax pushl %eax
pushl %ebp # output address
movl input_len(%ebx), %eax
pushl %eax # input_len
leal input_data(%ebx), %eax
pushl %eax # input_data
leal _end(%ebx), %eax
pushl %eax # end of the image as third argument
pushl %esi # real mode pointer as second arg pushl %esi # real mode pointer as second arg
pushl %eax # address of structure as first arg
call decompress_kernel call decompress_kernel
orl %eax,%eax addl $20, %esp
jnz 3f popl %ecx
popl %esi # discard address
popl %esi # real mode pointer
xorl %ebx,%ebx
ljmp $(__BOOT_CS), $__PHYSICAL_START
#if CONFIG_RELOCATABLE
/* Find the address of the relocations.
*/
movl %ebp, %edi
addl %ecx, %edi
/* Calculate the delta between where vmlinux was compiled to run
* and where it was actually loaded.
*/
movl %ebp, %ebx
subl $LOAD_PHYSICAL_ADDR, %ebx
jz 2f /* Nothing to be done if loaded at compiled addr. */
/* /*
* We come here, if we were loaded high. * Process relocations.
* We need to move the move-in-place routine down to 0x1000
* and then start it with the buffer addresses in registers,
* which we got from the stack.
*/ */
3:
movl $move_routine_start,%esi 1: subl $4, %edi
movl $0x1000,%edi movl 0(%edi), %ecx
movl $move_routine_end,%ecx testl %ecx, %ecx
subl %esi,%ecx jz 2f
addl $3,%ecx addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)
shrl $2,%ecx jmp 1b
cld 2:
rep #endif
movsl
popl %esi # discard the address
popl %ebx # real mode pointer
popl %esi # low_buffer_start
popl %ecx # lcount
popl %edx # high_buffer_start
popl %eax # hcount
movl $__PHYSICAL_START,%edi
cli # make sure we don't get interrupted
ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
/* /*
* Routine (template) for moving the decompressed kernel in place, * Jump to the decompressed kernel.
* if we were high loaded. This _must_ PIC-code !
*/ */
move_routine_start:
movl %ecx,%ebp
shrl $2,%ecx
rep
movsl
movl %ebp,%ecx
andl $3,%ecx
rep
movsb
movl %edx,%esi
movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
addl $3,%ecx
shrl $2,%ecx
rep
movsl
movl %ebx,%esi # Restore setup pointer
xorl %ebx,%ebx xorl %ebx,%ebx
ljmp $(__BOOT_CS), $__PHYSICAL_START jmp *%ebp
move_routine_end:
.bss
.balign 4
stack:
.fill 4096, 1, 0
stack_end:
This diff is collapsed.
This diff is collapsed.
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(startup_32)
SECTIONS
{
/* Be careful parts of head.S assume startup_32 is at
* address 0.
*/
. = 0 ;
.text.head : {
_head = . ;
*(.text.head)
_ehead = . ;
}
.data.compressed : {
*(.data.compressed)
}
.text : {
_text = .; /* Text */
*(.text)
*(.text.*)
_etext = . ;
}
.rodata : {
_rodata = . ;
*(.rodata) /* read-only data */
*(.rodata.*)
_erodata = . ;
}
.data : {
_data = . ;
*(.data)
*(.data.*)
_edata = . ;
}
.bss : {
_bss = . ;
*(.bss)
*(.bss.*)
*(COMMON)
_end = . ;
}
}
SECTIONS SECTIONS
{ {
.data : { .data.compressed : {
input_len = .; input_len = .;
LONG(input_data_end - input_data) input_data = .; LONG(input_data_end - input_data) input_data = .;
*(.data) *(.data)
output_len = . - 4;
input_data_end = .; input_data_end = .;
} }
} }
...@@ -81,7 +81,7 @@ start: ...@@ -81,7 +81,7 @@ start:
# This is the setup header, and it must start at %cs:2 (old 0x9020:2) # This is the setup header, and it must start at %cs:2 (old 0x9020:2)
.ascii "HdrS" # header signature .ascii "HdrS" # header signature
.word 0x0204 # header version number (>= 0x0105) .word 0x0205 # header version number (>= 0x0105)
# or else old loadlin-1.5 will fail) # or else old loadlin-1.5 will fail)
realmode_swtch: .word 0, 0 # default_switch, SETUPSEG realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
start_sys_seg: .word SYSSEG start_sys_seg: .word SYSSEG
...@@ -160,6 +160,17 @@ ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff ...@@ -160,6 +160,17 @@ ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
# The highest safe address for # The highest safe address for
# the contents of an initrd # the contents of an initrd
kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
#required for protected mode
#kernel
#ifdef CONFIG_RELOCATABLE
relocatable_kernel: .byte 1
#else
relocatable_kernel: .byte 0
#endif
pad2: .byte 0
pad3: .word 0
trampoline: call start_of_setup trampoline: call start_of_setup
.align 16 .align 16
# The offset at this point is 0x240 # The offset at this point is 0x240
...@@ -588,11 +599,6 @@ rmodeswtch_normal: ...@@ -588,11 +599,6 @@ rmodeswtch_normal:
call default_switch call default_switch
rmodeswtch_end: rmodeswtch_end:
# we get the code32 start address and modify the below 'jmpi'
# (loader may have changed it)
movl %cs:code32_start, %eax
movl %eax, %cs:code32
# Now we move the system to its rightful place ... but we check if we have a # Now we move the system to its rightful place ... but we check if we have a
# big-kernel. In that case we *must* not move it ... # big-kernel. In that case we *must* not move it ...
testb $LOADED_HIGH, %cs:loadflags testb $LOADED_HIGH, %cs:loadflags
...@@ -788,11 +794,12 @@ a20_err_msg: ...@@ -788,11 +794,12 @@ a20_err_msg:
a20_done: a20_done:
#endif /* CONFIG_X86_VOYAGER */ #endif /* CONFIG_X86_VOYAGER */
# set up gdt and idt # set up gdt and idt and 32bit start address
lidt idt_48 # load idt with 0,0 lidt idt_48 # load idt with 0,0
xorl %eax, %eax # Compute gdt_base xorl %eax, %eax # Compute gdt_base
movw %ds, %ax # (Convert %ds:gdt to a linear ptr) movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
shll $4, %eax shll $4, %eax
addl %eax, code32
addl $gdt, %eax addl $gdt, %eax
movl %eax, (gdt_48+2) movl %eax, (gdt_48+2)
lgdt gdt_48 # load gdt with whatever is lgdt gdt_48 # load gdt with whatever is
...@@ -851,9 +858,26 @@ flush_instr: ...@@ -851,9 +858,26 @@ flush_instr:
# Manual, Mixing 16-bit and 32-bit code, page 16-6) # Manual, Mixing 16-bit and 32-bit code, page 16-6)
.byte 0x66, 0xea # prefix + jmpi-opcode .byte 0x66, 0xea # prefix + jmpi-opcode
code32: .long 0x1000 # will be set to 0x100000 code32: .long startup_32 # will be set to %cs+startup_32
# for big kernels
.word __BOOT_CS .word __BOOT_CS
.code32
startup_32:
movl $(__BOOT_DS), %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movl %eax, %ss
xorl %eax, %eax
1: incl %eax # check that A20 really IS enabled
movl %eax, 0x00000000 # loop forever if it isn't
cmpl %eax, 0x00100000
je 1b
# Jump to the 32bit entry point
jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi)
.code16
# Here's a bunch of information about your current kernel.. # Here's a bunch of information about your current kernel..
kernel_version: .ascii UTS_RELEASE kernel_version: .ascii UTS_RELEASE
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.19-rc2-git4 # Linux kernel version: 2.6.19-git7
# Sat Oct 21 03:38:56 2006 # Wed Dec 6 23:50:49 2006
# #
CONFIG_X86_32=y CONFIG_X86_32=y
CONFIG_GENERIC_TIME=y CONFIG_GENERIC_TIME=y
...@@ -40,13 +40,14 @@ CONFIG_POSIX_MQUEUE=y ...@@ -40,13 +40,14 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_IKCONFIG=y CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set # CONFIG_CPUSETS is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set # CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE="" CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set # CONFIG_EMBEDDED is not set
CONFIG_UID16=y CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set
...@@ -110,6 +111,7 @@ CONFIG_SMP=y ...@@ -110,6 +111,7 @@ CONFIG_SMP=y
# CONFIG_X86_VISWS is not set # CONFIG_X86_VISWS is not set
CONFIG_X86_GENERICARCH=y CONFIG_X86_GENERICARCH=y
# CONFIG_X86_ES7000 is not set # CONFIG_X86_ES7000 is not set
# CONFIG_PARAVIRT is not set
CONFIG_X86_CYCLONE_TIMER=y CONFIG_X86_CYCLONE_TIMER=y
# CONFIG_M386 is not set # CONFIG_M386 is not set
# CONFIG_M486 is not set # CONFIG_M486 is not set
...@@ -120,6 +122,7 @@ CONFIG_X86_CYCLONE_TIMER=y ...@@ -120,6 +122,7 @@ CONFIG_X86_CYCLONE_TIMER=y
# CONFIG_MPENTIUMII is not set # CONFIG_MPENTIUMII is not set
CONFIG_MPENTIUMIII=y CONFIG_MPENTIUMIII=y
# CONFIG_MPENTIUMM is not set # CONFIG_MPENTIUMM is not set
# CONFIG_MCORE2 is not set
# CONFIG_MPENTIUM4 is not set # CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set # CONFIG_MK6 is not set
# CONFIG_MK7 is not set # CONFIG_MK7 is not set
...@@ -197,7 +200,6 @@ CONFIG_RESOURCES_64BIT=y ...@@ -197,7 +200,6 @@ CONFIG_RESOURCES_64BIT=y
CONFIG_MTRR=y CONFIG_MTRR=y
# CONFIG_EFI is not set # CONFIG_EFI is not set
# CONFIG_IRQBALANCE is not set # CONFIG_IRQBALANCE is not set
CONFIG_REGPARM=y
CONFIG_SECCOMP=y CONFIG_SECCOMP=y
# CONFIG_HZ_100 is not set # CONFIG_HZ_100 is not set
CONFIG_HZ_250=y CONFIG_HZ_250=y
...@@ -205,7 +207,8 @@ CONFIG_HZ_250=y ...@@ -205,7 +207,8 @@ CONFIG_HZ_250=y
CONFIG_HZ=250 CONFIG_HZ=250
# CONFIG_KEXEC is not set # CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set # CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x100000 # CONFIG_RELOCATABLE is not set
CONFIG_PHYSICAL_ALIGN=0x100000
# CONFIG_HOTPLUG_CPU is not set # CONFIG_HOTPLUG_CPU is not set
CONFIG_COMPAT_VDSO=y CONFIG_COMPAT_VDSO=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
...@@ -367,6 +370,7 @@ CONFIG_INET_TCP_DIAG=y ...@@ -367,6 +370,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set # CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set # CONFIG_IPV6_ROUTER_PREF is not set
...@@ -677,6 +681,7 @@ CONFIG_SATA_INTEL_COMBINED=y ...@@ -677,6 +681,7 @@ CONFIG_SATA_INTEL_COMBINED=y
# CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT821X is not set
# CONFIG_PATA_JMICRON is not set # CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
# CONFIG_PATA_MPIIX is not set # CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set # CONFIG_PATA_NETCELL is not set
...@@ -850,6 +855,7 @@ CONFIG_BNX2=y ...@@ -850,6 +855,7 @@ CONFIG_BNX2=y
# CONFIG_IXGB is not set # CONFIG_IXGB is not set
# CONFIG_S2IO is not set # CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set # CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# #
# Token Ring devices # Token Ring devices
...@@ -984,10 +990,6 @@ CONFIG_RTC=y ...@@ -984,10 +990,6 @@ CONFIG_RTC=y
# CONFIG_R3964 is not set # CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set # CONFIG_APPLICOM is not set
# CONFIG_SONYPI is not set # CONFIG_SONYPI is not set
#
# Ftape, the floppy tape device driver
#
CONFIG_AGP=y CONFIG_AGP=y
# CONFIG_AGP_ALI is not set # CONFIG_AGP_ALI is not set
# CONFIG_AGP_ATI is not set # CONFIG_AGP_ATI is not set
...@@ -1108,6 +1110,7 @@ CONFIG_USB_DEVICEFS=y ...@@ -1108,6 +1110,7 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set # CONFIG_USB_SUSPEND is not set
# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set # CONFIG_USB_OTG is not set
# #
...@@ -1185,6 +1188,7 @@ CONFIG_USB_HIDINPUT=y ...@@ -1185,6 +1188,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_KAWETH is not set # CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set # CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set # CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set # CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y CONFIG_USB_MON=y
......
...@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds ...@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o signal.o entry.o traps.o irq.o \ obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
pci-dma.o i386_ksyms.o i387.o bootflag.o \ pci-dma.o i386_ksyms.o i387.o bootflag.o e820.o\
quirks.o i8237.o topology.o alternative.o i8253.o tsc.o quirks.o i8237.o topology.o alternative.o i8253.o tsc.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o
...@@ -40,6 +40,9 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ...@@ -40,6 +40,9 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_HPET_TIMER) += hpet.o
obj-$(CONFIG_K8_NB) += k8.o obj-$(CONFIG_K8_NB) += k8.o
# Make sure this is linked after any other paravirt_ops structs: see head.S
obj-$(CONFIG_PARAVIRT) += paravirt.o
EXTRA_AFLAGS := -traditional EXTRA_AFLAGS := -traditional
obj-$(CONFIG_SCx200) += scx200.o obj-$(CONFIG_SCx200) += scx200.o
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <asm/pci-direct.h> #include <asm/pci-direct.h>
#include <asm/acpi.h> #include <asm/acpi.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/irq.h>
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
...@@ -49,6 +50,24 @@ static int __init check_bridge(int vendor, int device) ...@@ -49,6 +50,24 @@ static int __init check_bridge(int vendor, int device)
return 0; return 0;
} }
static void check_intel(void)
{
u16 vendor, device;
vendor = read_pci_config_16(0, 0, 0, PCI_VENDOR_ID);
if (vendor != PCI_VENDOR_ID_INTEL)
return;
device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID);
#ifdef CONFIG_SMP
if (device == PCI_DEVICE_ID_INTEL_E7320_MCH ||
device == PCI_DEVICE_ID_INTEL_E7520_MCH ||
device == PCI_DEVICE_ID_INTEL_E7525_MCH)
quirk_intel_irqbalance();
#endif
}
void __init check_acpi_pci(void) void __init check_acpi_pci(void)
{ {
int num, slot, func; int num, slot, func;
...@@ -60,6 +79,8 @@ void __init check_acpi_pci(void) ...@@ -60,6 +79,8 @@ void __init check_acpi_pci(void)
if (!early_pci_allowed()) if (!early_pci_allowed())
return; return;
check_intel();
/* Poor man's PCI discovery */ /* Poor man's PCI discovery */
for (num = 0; num < 32; num++) { for (num = 0; num < 32; num++) {
for (slot = 0; slot < 32; slot++) { for (slot = 0; slot < 32; slot++) {
......
...@@ -124,6 +124,20 @@ static unsigned char** find_nop_table(void) ...@@ -124,6 +124,20 @@ static unsigned char** find_nop_table(void)
#endif /* CONFIG_X86_64 */ #endif /* CONFIG_X86_64 */
static void nop_out(void *insns, unsigned int len)
{
unsigned char **noptable = find_nop_table();
while (len > 0) {
unsigned int noplen = len;
if (noplen > ASM_NOP_MAX)
noplen = ASM_NOP_MAX;
memcpy(insns, noptable[noplen], noplen);
insns += noplen;
len -= noplen;
}
}
extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[]; extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
extern u8 *__smp_locks[], *__smp_locks_end[]; extern u8 *__smp_locks[], *__smp_locks_end[];
...@@ -138,10 +152,9 @@ extern u8 __smp_alt_begin[], __smp_alt_end[]; ...@@ -138,10 +152,9 @@ extern u8 __smp_alt_begin[], __smp_alt_end[];
void apply_alternatives(struct alt_instr *start, struct alt_instr *end) void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
{ {
unsigned char **noptable = find_nop_table();
struct alt_instr *a; struct alt_instr *a;
u8 *instr; u8 *instr;
int diff, i, k; int diff;
DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end); DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
for (a = start; a < end; a++) { for (a = start; a < end; a++) {
...@@ -159,13 +172,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end) ...@@ -159,13 +172,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
#endif #endif
memcpy(instr, a->replacement, a->replacementlen); memcpy(instr, a->replacement, a->replacementlen);
diff = a->instrlen - a->replacementlen; diff = a->instrlen - a->replacementlen;
/* Pad the rest with nops */ nop_out(instr + a->replacementlen, diff);
for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
k = diff;
if (k > ASM_NOP_MAX)
k = ASM_NOP_MAX;
memcpy(a->instr + i, noptable[k], k);
}
} }
} }
...@@ -209,7 +216,6 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) ...@@ -209,7 +216,6 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
{ {
unsigned char **noptable = find_nop_table();
u8 **ptr; u8 **ptr;
for (ptr = start; ptr < end; ptr++) { for (ptr = start; ptr < end; ptr++) {
...@@ -217,7 +223,7 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end ...@@ -217,7 +223,7 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end
continue; continue;
if (*ptr > text_end) if (*ptr > text_end)
continue; continue;
**ptr = noptable[1][0]; nop_out(*ptr, 1);
}; };
} }
...@@ -343,6 +349,40 @@ void alternatives_smp_switch(int smp) ...@@ -343,6 +349,40 @@ void alternatives_smp_switch(int smp)
#endif #endif
#ifdef CONFIG_PARAVIRT
void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
{
struct paravirt_patch *p;
for (p = start; p < end; p++) {
unsigned int used;
used = paravirt_ops.patch(p->instrtype, p->clobbers, p->instr,
p->len);
#ifdef CONFIG_DEBUG_PARAVIRT
{
int i;
/* Deliberately clobber regs using "not %reg" to find bugs. */
for (i = 0; i < 3; i++) {
if (p->len - used >= 2 && (p->clobbers & (1 << i))) {
memcpy(p->instr + used, "\xf7\xd0", 2);
p->instr[used+1] |= i;
used += 2;
}
}
}
#endif
/* Pad the rest with nops */
nop_out(p->instr + used, p->len - used);
}
/* Sync to be conservative, in case we patched following instructions */
sync_core();
}
extern struct paravirt_patch __start_parainstructions[],
__stop_parainstructions[];
#endif /* CONFIG_PARAVIRT */
void __init alternative_instructions(void) void __init alternative_instructions(void)
{ {
unsigned long flags; unsigned long flags;
...@@ -390,5 +430,6 @@ void __init alternative_instructions(void) ...@@ -390,5 +430,6 @@ void __init alternative_instructions(void)
alternatives_smp_switch(0); alternatives_smp_switch(0);
} }
#endif #endif
apply_paravirt(__start_parainstructions, __stop_parainstructions);
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -647,23 +647,30 @@ static struct { ...@@ -647,23 +647,30 @@ static struct {
static int lapic_suspend(struct sys_device *dev, pm_message_t state) static int lapic_suspend(struct sys_device *dev, pm_message_t state)
{ {
unsigned long flags; unsigned long flags;
int maxlvt;
if (!apic_pm_state.active) if (!apic_pm_state.active)
return 0; return 0;
maxlvt = get_maxlvt();
apic_pm_state.apic_id = apic_read(APIC_ID); apic_pm_state.apic_id = apic_read(APIC_ID);
apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
apic_pm_state.apic_ldr = apic_read(APIC_LDR); apic_pm_state.apic_ldr = apic_read(APIC_LDR);
apic_pm_state.apic_dfr = apic_read(APIC_DFR); apic_pm_state.apic_dfr = apic_read(APIC_DFR);
apic_pm_state.apic_spiv = apic_read(APIC_SPIV); apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
if (maxlvt >= 4)
apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
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);
#ifdef CONFIG_X86_MCE_P4THERMAL
if (maxlvt >= 5)
apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
#endif
local_irq_save(flags); local_irq_save(flags);
disable_local_APIC(); disable_local_APIC();
...@@ -675,10 +682,13 @@ static int lapic_resume(struct sys_device *dev) ...@@ -675,10 +682,13 @@ static int lapic_resume(struct sys_device *dev)
{ {
unsigned int l, h; unsigned int l, h;
unsigned long flags; unsigned long flags;
int maxlvt;
if (!apic_pm_state.active) if (!apic_pm_state.active)
return 0; return 0;
maxlvt = get_maxlvt();
local_irq_save(flags); local_irq_save(flags);
/* /*
...@@ -700,7 +710,11 @@ static int lapic_resume(struct sys_device *dev) ...@@ -700,7 +710,11 @@ static int lapic_resume(struct sys_device *dev)
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);
#ifdef CONFIG_X86_MCE_P4THERMAL
if (maxlvt >= 5)
apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
#endif
if (maxlvt >= 4)
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);
......
...@@ -231,6 +231,7 @@ ...@@ -231,6 +231,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/i8253.h> #include <asm/i8253.h>
#include <asm/paravirt.h>
#include "io_ports.h" #include "io_ports.h"
...@@ -2235,7 +2236,7 @@ static int __init apm_init(void) ...@@ -2235,7 +2236,7 @@ static int __init apm_init(void)
dmi_check_system(apm_dmi_table); dmi_check_system(apm_dmi_table);
if (apm_info.bios.version == 0) { if (apm_info.bios.version == 0 || paravirt_enabled()) {
printk(KERN_INFO "apm: BIOS not found.\n"); printk(KERN_INFO "apm: BIOS not found.\n");
return -ENODEV; return -ENODEV;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/pda.h>
#define DEFINE(sym, val) \ #define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val)) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
...@@ -51,13 +52,35 @@ void foo(void) ...@@ -51,13 +52,35 @@ void foo(void)
OFFSET(TI_exec_domain, thread_info, exec_domain); OFFSET(TI_exec_domain, thread_info, exec_domain);
OFFSET(TI_flags, thread_info, flags); OFFSET(TI_flags, thread_info, flags);
OFFSET(TI_status, thread_info, status); OFFSET(TI_status, thread_info, status);
OFFSET(TI_cpu, thread_info, cpu);
OFFSET(TI_preempt_count, thread_info, preempt_count); OFFSET(TI_preempt_count, thread_info, preempt_count);
OFFSET(TI_addr_limit, thread_info, addr_limit); OFFSET(TI_addr_limit, thread_info, addr_limit);
OFFSET(TI_restart_block, thread_info, restart_block); OFFSET(TI_restart_block, thread_info, restart_block);
OFFSET(TI_sysenter_return, thread_info, sysenter_return); OFFSET(TI_sysenter_return, thread_info, sysenter_return);
BLANK(); BLANK();
OFFSET(GDS_size, Xgt_desc_struct, size);
OFFSET(GDS_address, Xgt_desc_struct, address);
OFFSET(GDS_pad, Xgt_desc_struct, pad);
BLANK();
OFFSET(PT_EBX, pt_regs, ebx);
OFFSET(PT_ECX, pt_regs, ecx);
OFFSET(PT_EDX, pt_regs, edx);
OFFSET(PT_ESI, pt_regs, esi);
OFFSET(PT_EDI, pt_regs, edi);
OFFSET(PT_EBP, pt_regs, ebp);
OFFSET(PT_EAX, pt_regs, eax);
OFFSET(PT_DS, pt_regs, xds);
OFFSET(PT_ES, pt_regs, xes);
OFFSET(PT_GS, pt_regs, xgs);
OFFSET(PT_ORIG_EAX, pt_regs, orig_eax);
OFFSET(PT_EIP, pt_regs, eip);
OFFSET(PT_CS, pt_regs, xcs);
OFFSET(PT_EFLAGS, pt_regs, eflags);
OFFSET(PT_OLDESP, pt_regs, esp);
OFFSET(PT_OLDSS, pt_regs, xss);
BLANK();
OFFSET(EXEC_DOMAIN_handler, exec_domain, handler); OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
OFFSET(RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext); OFFSET(RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
BLANK(); BLANK();
...@@ -74,4 +97,18 @@ void foo(void) ...@@ -74,4 +97,18 @@ void foo(void)
DEFINE(VDSO_PRELINK, VDSO_PRELINK); DEFINE(VDSO_PRELINK, VDSO_PRELINK);
OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
BLANK();
OFFSET(PDA_cpu, i386_pda, cpu_number);
OFFSET(PDA_pcurrent, i386_pda, pcurrent);
#ifdef CONFIG_PARAVIRT
BLANK();
OFFSET(PARAVIRT_enabled, paravirt_ops, paravirt_enabled);
OFFSET(PARAVIRT_irq_disable, paravirt_ops, irq_disable);
OFFSET(PARAVIRT_irq_enable, paravirt_ops, irq_enable);
OFFSET(PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit);
OFFSET(PARAVIRT_iret, paravirt_ops, iret);
OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0);
#endif
} }
...@@ -105,9 +105,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) ...@@ -105,9 +105,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
rdtscl(d2); rdtscl(d2);
d = d2-d; d = d2-d;
/* Knock these two lines out if it debugs out ok */
printk(KERN_INFO "AMD K6 stepping B detected - ");
/* -- cut here -- */
if (d > 20*K6_BUG_LOOP) if (d > 20*K6_BUG_LOOP)
printk("system stability may be impaired when more than 32 MB are used.\n"); printk("system stability may be impaired when more than 32 MB are used.\n");
else else
......
This diff is collapsed.
...@@ -107,7 +107,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) ...@@ -107,7 +107,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
* Note that the workaround only should be initialized once... * Note that the workaround only should be initialized once...
*/ */
c->f00f_bug = 0; c->f00f_bug = 0;
if ( c->x86 == 5 ) { if (!paravirt_enabled() && c->x86 == 5) {
static int f00f_workaround_enabled = 0; static int f00f_workaround_enabled = 0;
c->f00f_bug = 1; c->f00f_bug = 1;
...@@ -195,8 +195,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) ...@@ -195,8 +195,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
if ((c->x86 == 0xf && c->x86_model >= 0x03) || if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
(c->x86 == 0x6 && c->x86_model >= 0x0e)) (c->x86 == 0x6 && c->x86_model >= 0x0e))
set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
}
if (cpu_has_ds) {
unsigned int l1;
rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
if (!(l1 & (1<<11)))
set_bit(X86_FEATURE_BTS, c->x86_capability);
if (!(l1 & (1<<12)))
set_bit(X86_FEATURE_PEBS, c->x86_capability);
}
}
static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size) static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
{ {
......
...@@ -480,12 +480,10 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) ...@@ -480,12 +480,10 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
if (num_cache_leaves == 0) if (num_cache_leaves == 0)
return -ENOENT; return -ENOENT;
cpuid4_info[cpu] = kmalloc( cpuid4_info[cpu] = kzalloc(
sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL); sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
if (unlikely(cpuid4_info[cpu] == NULL)) if (unlikely(cpuid4_info[cpu] == NULL))
return -ENOMEM; return -ENOMEM;
memset(cpuid4_info[cpu], 0,
sizeof(struct _cpuid4_info) * num_cache_leaves);
oldmask = current->cpus_allowed; oldmask = current->cpus_allowed;
retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
...@@ -658,17 +656,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) ...@@ -658,17 +656,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
return -ENOENT; return -ENOENT;
/* Allocate all required memory */ /* Allocate all required memory */
cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL); cache_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
if (unlikely(cache_kobject[cpu] == NULL)) if (unlikely(cache_kobject[cpu] == NULL))
goto err_out; goto err_out;
memset(cache_kobject[cpu], 0, sizeof(struct kobject));
index_kobject[cpu] = kmalloc( index_kobject[cpu] = kzalloc(
sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL); sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
if (unlikely(index_kobject[cpu] == NULL)) if (unlikely(index_kobject[cpu] == NULL))
goto err_out; goto err_out;
memset(index_kobject[cpu], 0,
sizeof(struct _index_kobject) * num_cache_leaves);
return 0; return 0;
......
obj-y := main.o if.o generic.o state.o obj-y := main.o if.o generic.o state.o
obj-y += amd.o obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o
obj-y += cyrix.o
obj-y += centaur.o
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
static void static void
amd_get_mtrr(unsigned int reg, unsigned long *base, amd_get_mtrr(unsigned int reg, unsigned long *base,
unsigned int *size, mtrr_type * type) unsigned long *size, mtrr_type * type)
{ {
unsigned long low, high; unsigned long low, high;
......
...@@ -17,7 +17,7 @@ static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */ ...@@ -17,7 +17,7 @@ static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */
*/ */
static int static int
centaur_get_free_region(unsigned long base, unsigned long size) centaur_get_free_region(unsigned long base, unsigned long size, int replace_reg)
/* [SUMMARY] Get a free MTRR. /* [SUMMARY] Get a free MTRR.
<base> The starting (base) address of the region. <base> The starting (base) address of the region.
<size> The size (in bytes) of the region. <size> The size (in bytes) of the region.
...@@ -26,10 +26,11 @@ centaur_get_free_region(unsigned long base, unsigned long size) ...@@ -26,10 +26,11 @@ centaur_get_free_region(unsigned long base, unsigned long size)
{ {
int i, max; int i, max;
mtrr_type ltype; mtrr_type ltype;
unsigned long lbase; unsigned long lbase, lsize;
unsigned int lsize;
max = num_var_ranges; max = num_var_ranges;
if (replace_reg >= 0 && replace_reg < max)
return replace_reg;
for (i = 0; i < max; ++i) { for (i = 0; i < max; ++i) {
if (centaur_mcr_reserved & (1 << i)) if (centaur_mcr_reserved & (1 << i))
continue; continue;
...@@ -49,7 +50,7 @@ mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) ...@@ -49,7 +50,7 @@ mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
static void static void
centaur_get_mcr(unsigned int reg, unsigned long *base, centaur_get_mcr(unsigned int reg, unsigned long *base,
unsigned int *size, mtrr_type * type) unsigned long *size, mtrr_type * type)
{ {
*base = centaur_mcr[reg].high >> PAGE_SHIFT; *base = centaur_mcr[reg].high >> PAGE_SHIFT;
*size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT; *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT;
......
...@@ -9,7 +9,7 @@ int arr3_protected; ...@@ -9,7 +9,7 @@ int arr3_protected;
static void static void
cyrix_get_arr(unsigned int reg, unsigned long *base, cyrix_get_arr(unsigned int reg, unsigned long *base,
unsigned int *size, mtrr_type * type) unsigned long *size, mtrr_type * type)
{ {
unsigned long flags; unsigned long flags;
unsigned char arr, ccr3, rcr, shift; unsigned char arr, ccr3, rcr, shift;
...@@ -77,7 +77,7 @@ cyrix_get_arr(unsigned int reg, unsigned long *base, ...@@ -77,7 +77,7 @@ cyrix_get_arr(unsigned int reg, unsigned long *base,
} }
static int static int
cyrix_get_free_region(unsigned long base, unsigned long size) cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
/* [SUMMARY] Get a free ARR. /* [SUMMARY] Get a free ARR.
<base> The starting (base) address of the region. <base> The starting (base) address of the region.
<size> The size (in bytes) of the region. <size> The size (in bytes) of the region.
...@@ -86,9 +86,24 @@ cyrix_get_free_region(unsigned long base, unsigned long size) ...@@ -86,9 +86,24 @@ cyrix_get_free_region(unsigned long base, unsigned long size)
{ {
int i; int i;
mtrr_type ltype; mtrr_type ltype;
unsigned long lbase; unsigned long lbase, lsize;
unsigned int lsize;
switch (replace_reg) {
case 7:
if (size < 0x40)
break;
case 6:
case 5:
case 4:
return replace_reg;
case 3:
if (arr3_protected)
break;
case 2:
case 1:
case 0:
return replace_reg;
}
/* If we are to set up a region >32M then look at ARR7 immediately */ /* If we are to set up a region >32M then look at ARR7 immediately */
if (size > 0x2000) { if (size > 0x2000) {
cyrix_get_arr(7, &lbase, &lsize, &ltype); cyrix_get_arr(7, &lbase, &lsize, &ltype);
...@@ -214,7 +229,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base, ...@@ -214,7 +229,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base,
typedef struct { typedef struct {
unsigned long base; unsigned long base;
unsigned int size; unsigned long size;
mtrr_type type; mtrr_type type;
} arr_state_t; } arr_state_t;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
#include <asm/msr.h> #include <asm/msr.h>
...@@ -15,12 +16,19 @@ struct mtrr_state { ...@@ -15,12 +16,19 @@ struct mtrr_state {
struct mtrr_var_range *var_ranges; struct mtrr_var_range *var_ranges;
mtrr_type fixed_ranges[NUM_FIXED_RANGES]; mtrr_type fixed_ranges[NUM_FIXED_RANGES];
unsigned char enabled; unsigned char enabled;
unsigned char have_fixed;
mtrr_type def_type; mtrr_type def_type;
}; };
static unsigned long smp_changes_mask; static unsigned long smp_changes_mask;
static struct mtrr_state mtrr_state = {}; static struct mtrr_state mtrr_state = {};
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "mtrr."
static __initdata int mtrr_show;
module_param_named(show, mtrr_show, bool, 0);
/* Get the MSR pair relating to a var range */ /* Get the MSR pair relating to a var range */
static void __init static void __init
get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr) get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
...@@ -43,6 +51,14 @@ get_fixed_ranges(mtrr_type * frs) ...@@ -43,6 +51,14 @@ get_fixed_ranges(mtrr_type * frs)
rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]); rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]);
} }
static void __init print_fixed(unsigned base, unsigned step, const mtrr_type*types)
{
unsigned i;
for (i = 0; i < 8; ++i, ++types, base += step)
printk(KERN_INFO "MTRR %05X-%05X %s\n", base, base + step - 1, mtrr_attrib_to_str(*types));
}
/* Grab all of the MTRR state for this CPU into *state */ /* Grab all of the MTRR state for this CPU into *state */
void __init get_mtrr_state(void) void __init get_mtrr_state(void)
{ {
...@@ -58,13 +74,49 @@ void __init get_mtrr_state(void) ...@@ -58,13 +74,49 @@ void __init get_mtrr_state(void)
} }
vrs = mtrr_state.var_ranges; vrs = mtrr_state.var_ranges;
rdmsr(MTRRcap_MSR, lo, dummy);
mtrr_state.have_fixed = (lo >> 8) & 1;
for (i = 0; i < num_var_ranges; i++) for (i = 0; i < num_var_ranges; i++)
get_mtrr_var_range(i, &vrs[i]); get_mtrr_var_range(i, &vrs[i]);
if (mtrr_state.have_fixed)
get_fixed_ranges(mtrr_state.fixed_ranges); get_fixed_ranges(mtrr_state.fixed_ranges);
rdmsr(MTRRdefType_MSR, lo, dummy); rdmsr(MTRRdefType_MSR, lo, dummy);
mtrr_state.def_type = (lo & 0xff); mtrr_state.def_type = (lo & 0xff);
mtrr_state.enabled = (lo & 0xc00) >> 10; mtrr_state.enabled = (lo & 0xc00) >> 10;
if (mtrr_show) {
int high_width;
printk(KERN_INFO "MTRR default type: %s\n", mtrr_attrib_to_str(mtrr_state.def_type));
if (mtrr_state.have_fixed) {
printk(KERN_INFO "MTRR fixed ranges %sabled:\n",
mtrr_state.enabled & 1 ? "en" : "dis");
print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0);
for (i = 0; i < 2; ++i)
print_fixed(0x80000 + i * 0x20000, 0x04000, mtrr_state.fixed_ranges + (i + 1) * 8);
for (i = 0; i < 8; ++i)
print_fixed(0xC0000 + i * 0x08000, 0x01000, mtrr_state.fixed_ranges + (i + 3) * 8);
}
printk(KERN_INFO "MTRR variable ranges %sabled:\n",
mtrr_state.enabled & 2 ? "en" : "dis");
high_width = ((size_or_mask ? ffs(size_or_mask) - 1 : 32) - (32 - PAGE_SHIFT) + 3) / 4;
for (i = 0; i < num_var_ranges; ++i) {
if (mtrr_state.var_ranges[i].mask_lo & (1 << 11))
printk(KERN_INFO "MTRR %u base %0*X%05X000 mask %0*X%05X000 %s\n",
i,
high_width,
mtrr_state.var_ranges[i].base_hi,
mtrr_state.var_ranges[i].base_lo >> 12,
high_width,
mtrr_state.var_ranges[i].mask_hi,
mtrr_state.var_ranges[i].mask_lo >> 12,
mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff));
else
printk(KERN_INFO "MTRR %u disabled\n", i);
}
}
} }
/* Some BIOS's are fucked and don't set all MTRRs the same! */ /* Some BIOS's are fucked and don't set all MTRRs the same! */
...@@ -95,7 +147,7 @@ void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b) ...@@ -95,7 +147,7 @@ void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
smp_processor_id(), msr, a, b); smp_processor_id(), msr, a, b);
} }
int generic_get_free_region(unsigned long base, unsigned long size) int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg)
/* [SUMMARY] Get a free MTRR. /* [SUMMARY] Get a free MTRR.
<base> The starting (base) address of the region. <base> The starting (base) address of the region.
<size> The size (in bytes) of the region. <size> The size (in bytes) of the region.
...@@ -104,10 +156,11 @@ int generic_get_free_region(unsigned long base, unsigned long size) ...@@ -104,10 +156,11 @@ int generic_get_free_region(unsigned long base, unsigned long size)
{ {
int i, max; int i, max;
mtrr_type ltype; mtrr_type ltype;
unsigned long lbase; unsigned long lbase, lsize;
unsigned lsize;
max = num_var_ranges; max = num_var_ranges;
if (replace_reg >= 0 && replace_reg < max)
return replace_reg;
for (i = 0; i < max; ++i) { for (i = 0; i < max; ++i) {
mtrr_if->get(i, &lbase, &lsize, &ltype); mtrr_if->get(i, &lbase, &lsize, &ltype);
if (lsize == 0) if (lsize == 0)
...@@ -117,7 +170,7 @@ int generic_get_free_region(unsigned long base, unsigned long size) ...@@ -117,7 +170,7 @@ int generic_get_free_region(unsigned long base, unsigned long size)
} }
static void generic_get_mtrr(unsigned int reg, unsigned long *base, static void generic_get_mtrr(unsigned int reg, unsigned long *base,
unsigned int *size, mtrr_type * type) unsigned long *size, mtrr_type *type)
{ {
unsigned int mask_lo, mask_hi, base_lo, base_hi; unsigned int mask_lo, mask_hi, base_lo, base_hi;
...@@ -202,7 +255,9 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) ...@@ -202,7 +255,9 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
return changed; return changed;
} }
static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) static u32 deftype_lo, deftype_hi;
static unsigned long set_mtrr_state(void)
/* [SUMMARY] Set the MTRR state for this CPU. /* [SUMMARY] Set the MTRR state for this CPU.
<state> The MTRR state information to read. <state> The MTRR state information to read.
<ctxt> Some relevant CPU context. <ctxt> Some relevant CPU context.
...@@ -217,14 +272,14 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) ...@@ -217,14 +272,14 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi)
if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i])) if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i]))
change_mask |= MTRR_CHANGE_MASK_VARIABLE; change_mask |= MTRR_CHANGE_MASK_VARIABLE;
if (set_fixed_ranges(mtrr_state.fixed_ranges)) if (mtrr_state.have_fixed && set_fixed_ranges(mtrr_state.fixed_ranges))
change_mask |= MTRR_CHANGE_MASK_FIXED; change_mask |= MTRR_CHANGE_MASK_FIXED;
/* Set_mtrr_restore restores the old value of MTRRdefType, /* Set_mtrr_restore restores the old value of MTRRdefType,
so to set it we fiddle with the saved value */ so to set it we fiddle with the saved value */
if ((deftype_lo & 0xff) != mtrr_state.def_type if ((deftype_lo & 0xff) != mtrr_state.def_type
|| ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) { || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) {
deftype_lo |= (mtrr_state.def_type | mtrr_state.enabled << 10); deftype_lo = (deftype_lo & ~0xcff) | mtrr_state.def_type | (mtrr_state.enabled << 10);
change_mask |= MTRR_CHANGE_MASK_DEFTYPE; change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
} }
...@@ -233,7 +288,6 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) ...@@ -233,7 +288,6 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi)
static unsigned long cr4 = 0; static unsigned long cr4 = 0;
static u32 deftype_lo, deftype_hi;
static DEFINE_SPINLOCK(set_atomicity_lock); static DEFINE_SPINLOCK(set_atomicity_lock);
/* /*
...@@ -271,7 +325,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) ...@@ -271,7 +325,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi); rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
/* Disable MTRRs, and set the default type to uncached */ /* Disable MTRRs, and set the default type to uncached */
mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi); mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & ~0xcff, deftype_hi);
} }
static void post_set(void) __releases(set_atomicity_lock) static void post_set(void) __releases(set_atomicity_lock)
...@@ -300,7 +354,7 @@ static void generic_set_all(void) ...@@ -300,7 +354,7 @@ static void generic_set_all(void)
prepare_set(); prepare_set();
/* Actually set the state */ /* Actually set the state */
mask = set_mtrr_state(deftype_lo,deftype_hi); mask = set_mtrr_state();
post_set(); post_set();
local_irq_restore(flags); local_irq_restore(flags);
...@@ -366,7 +420,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i ...@@ -366,7 +420,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base); printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
return -EINVAL; return -EINVAL;
} }
if (!(base + size < 0x70000000 || base > 0x7003FFFF) && if (!(base + size < 0x70000 || base > 0x7003F) &&
(type == MTRR_TYPE_WRCOMB (type == MTRR_TYPE_WRCOMB
|| type == MTRR_TYPE_WRBACK)) { || type == MTRR_TYPE_WRBACK)) {
printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n"); printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
......
...@@ -17,7 +17,7 @@ extern unsigned int *usage_table; ...@@ -17,7 +17,7 @@ extern unsigned int *usage_table;
#define FILE_FCOUNT(f) (((struct seq_file *)((f)->private_data))->private) #define FILE_FCOUNT(f) (((struct seq_file *)((f)->private_data))->private)
static char *mtrr_strings[MTRR_NUM_TYPES] = static const char *const mtrr_strings[MTRR_NUM_TYPES] =
{ {
"uncachable", /* 0 */ "uncachable", /* 0 */
"write-combining", /* 1 */ "write-combining", /* 1 */
...@@ -28,7 +28,7 @@ static char *mtrr_strings[MTRR_NUM_TYPES] = ...@@ -28,7 +28,7 @@ static char *mtrr_strings[MTRR_NUM_TYPES] =
"write-back", /* 6 */ "write-back", /* 6 */
}; };
char *mtrr_attrib_to_str(int x) const char *mtrr_attrib_to_str(int x)
{ {
return (x <= 6) ? mtrr_strings[x] : "?"; return (x <= 6) ? mtrr_strings[x] : "?";
} }
...@@ -44,10 +44,9 @@ mtrr_file_add(unsigned long base, unsigned long size, ...@@ -44,10 +44,9 @@ mtrr_file_add(unsigned long base, unsigned long size,
max = num_var_ranges; max = num_var_ranges;
if (fcount == NULL) { if (fcount == NULL) {
fcount = kmalloc(max * sizeof *fcount, GFP_KERNEL); fcount = kzalloc(max * sizeof *fcount, GFP_KERNEL);
if (!fcount) if (!fcount)
return -ENOMEM; return -ENOMEM;
memset(fcount, 0, max * sizeof *fcount);
FILE_FCOUNT(file) = fcount; FILE_FCOUNT(file) = fcount;
} }
if (!page) { if (!page) {
...@@ -155,6 +154,7 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) ...@@ -155,6 +154,7 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
{ {
int err = 0; int err = 0;
mtrr_type type; mtrr_type type;
unsigned long size;
struct mtrr_sentry sentry; struct mtrr_sentry sentry;
struct mtrr_gentry gentry; struct mtrr_gentry gentry;
void __user *arg = (void __user *) __arg; void __user *arg = (void __user *) __arg;
...@@ -235,15 +235,15 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) ...@@ -235,15 +235,15 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
case MTRRIOC_GET_ENTRY: case MTRRIOC_GET_ENTRY:
if (gentry.regnum >= num_var_ranges) if (gentry.regnum >= num_var_ranges)
return -EINVAL; return -EINVAL;
mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
/* Hide entries that go above 4GB */ /* Hide entries that go above 4GB */
if (gentry.base + gentry.size > 0x100000 if (gentry.base + size - 1 >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT))
|| gentry.size == 0x100000) || size >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT)))
gentry.base = gentry.size = gentry.type = 0; gentry.base = gentry.size = gentry.type = 0;
else { else {
gentry.base <<= PAGE_SHIFT; gentry.base <<= PAGE_SHIFT;
gentry.size <<= PAGE_SHIFT; gentry.size = size << PAGE_SHIFT;
gentry.type = type; gentry.type = type;
} }
...@@ -273,8 +273,14 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) ...@@ -273,8 +273,14 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
case MTRRIOC_GET_PAGE_ENTRY: case MTRRIOC_GET_PAGE_ENTRY:
if (gentry.regnum >= num_var_ranges) if (gentry.regnum >= num_var_ranges)
return -EINVAL; return -EINVAL;
mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
/* Hide entries that would overflow */
if (size != (__typeof__(gentry.size))size)
gentry.base = gentry.size = gentry.type = 0;
else {
gentry.size = size;
gentry.type = type; gentry.type = type;
}
break; break;
} }
...@@ -353,8 +359,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset) ...@@ -353,8 +359,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset)
char factor; char factor;
int i, max, len; int i, max, len;
mtrr_type type; mtrr_type type;
unsigned long base; unsigned long base, size;
unsigned int size;
len = 0; len = 0;
max = num_var_ranges; max = num_var_ranges;
...@@ -373,7 +378,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset) ...@@ -373,7 +378,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset)
} }
/* RED-PEN: base can be > 32bit */ /* RED-PEN: base can be > 32bit */
len += seq_printf(seq, len += seq_printf(seq,
"reg%02i: base=0x%05lx000 (%4liMB), size=%4i%cB: %s, count=%d\n", "reg%02i: base=0x%05lx000 (%4luMB), size=%4lu%cB: %s, count=%d\n",
i, base, base >> (20 - PAGE_SHIFT), size, factor, i, base, base >> (20 - PAGE_SHIFT), size, factor,
mtrr_attrib_to_str(type), usage_table[i]); mtrr_attrib_to_str(type), usage_table[i]);
} }
......
...@@ -59,7 +59,11 @@ struct mtrr_ops * mtrr_if = NULL; ...@@ -59,7 +59,11 @@ struct mtrr_ops * mtrr_if = NULL;
static void set_mtrr(unsigned int reg, unsigned long base, static void set_mtrr(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type); unsigned long size, mtrr_type type);
#ifndef CONFIG_X86_64
extern int arr3_protected; extern int arr3_protected;
#else
#define arr3_protected 0
#endif
void set_mtrr_ops(struct mtrr_ops * ops) void set_mtrr_ops(struct mtrr_ops * ops)
{ {
...@@ -168,6 +172,13 @@ static void ipi_handler(void *info) ...@@ -168,6 +172,13 @@ static void ipi_handler(void *info)
#endif #endif
static inline int types_compatible(mtrr_type type1, mtrr_type type2) {
return type1 == MTRR_TYPE_UNCACHABLE ||
type2 == MTRR_TYPE_UNCACHABLE ||
(type1 == MTRR_TYPE_WRTHROUGH && type2 == MTRR_TYPE_WRBACK) ||
(type1 == MTRR_TYPE_WRBACK && type2 == MTRR_TYPE_WRTHROUGH);
}
/** /**
* set_mtrr - update mtrrs on all processors * set_mtrr - update mtrrs on all processors
* @reg: mtrr in question * @reg: mtrr in question
...@@ -263,8 +274,8 @@ static void set_mtrr(unsigned int reg, unsigned long base, ...@@ -263,8 +274,8 @@ static void set_mtrr(unsigned int reg, unsigned long base,
/** /**
* mtrr_add_page - Add a memory type region * mtrr_add_page - Add a memory type region
* @base: Physical base address of region in pages (4 KB) * @base: Physical base address of region in pages (in units of 4 kB!)
* @size: Physical size of region in pages (4 KB) * @size: Physical size of region in pages (4 kB)
* @type: Type of MTRR desired * @type: Type of MTRR desired
* @increment: If this is true do usage counting on the region * @increment: If this is true do usage counting on the region
* *
...@@ -300,11 +311,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, ...@@ -300,11 +311,9 @@ static void set_mtrr(unsigned int reg, unsigned long base,
int mtrr_add_page(unsigned long base, unsigned long size, int mtrr_add_page(unsigned long base, unsigned long size,
unsigned int type, char increment) unsigned int type, char increment)
{ {
int i; int i, replace, error;
mtrr_type ltype; mtrr_type ltype;
unsigned long lbase; unsigned long lbase, lsize;
unsigned int lsize;
int error;
if (!mtrr_if) if (!mtrr_if)
return -ENXIO; return -ENXIO;
...@@ -324,12 +333,18 @@ int mtrr_add_page(unsigned long base, unsigned long size, ...@@ -324,12 +333,18 @@ int mtrr_add_page(unsigned long base, unsigned long size,
return -ENOSYS; return -ENOSYS;
} }
if (!size) {
printk(KERN_WARNING "mtrr: zero sized request\n");
return -EINVAL;
}
if (base & size_or_mask || size & size_or_mask) { if (base & size_or_mask || size & size_or_mask) {
printk(KERN_WARNING "mtrr: base or size exceeds the MTRR width\n"); printk(KERN_WARNING "mtrr: base or size exceeds the MTRR width\n");
return -EINVAL; return -EINVAL;
} }
error = -EINVAL; error = -EINVAL;
replace = -1;
/* No CPU hotplug when we change MTRR entries */ /* No CPU hotplug when we change MTRR entries */
lock_cpu_hotplug(); lock_cpu_hotplug();
...@@ -337,21 +352,28 @@ int mtrr_add_page(unsigned long base, unsigned long size, ...@@ -337,21 +352,28 @@ int mtrr_add_page(unsigned long base, unsigned long size,
mutex_lock(&mtrr_mutex); mutex_lock(&mtrr_mutex);
for (i = 0; i < num_var_ranges; ++i) { for (i = 0; i < num_var_ranges; ++i) {
mtrr_if->get(i, &lbase, &lsize, &ltype); mtrr_if->get(i, &lbase, &lsize, &ltype);
if (base >= lbase + lsize) if (!lsize || base > lbase + lsize - 1 || base + size - 1 < lbase)
continue;
if ((base < lbase) && (base + size <= lbase))
continue; continue;
/* At this point we know there is some kind of overlap/enclosure */ /* At this point we know there is some kind of overlap/enclosure */
if ((base < lbase) || (base + size > lbase + lsize)) { if (base < lbase || base + size - 1 > lbase + lsize - 1) {
if (base <= lbase && base + size - 1 >= lbase + lsize - 1) {
/* New region encloses an existing region */
if (type == ltype) {
replace = replace == -1 ? i : -2;
continue;
}
else if (types_compatible(type, ltype))
continue;
}
printk(KERN_WARNING printk(KERN_WARNING
"mtrr: 0x%lx000,0x%lx000 overlaps existing" "mtrr: 0x%lx000,0x%lx000 overlaps existing"
" 0x%lx000,0x%x000\n", base, size, lbase, " 0x%lx000,0x%lx000\n", base, size, lbase,
lsize); lsize);
goto out; goto out;
} }
/* New region is enclosed by an existing region */ /* New region is enclosed by an existing region */
if (ltype != type) { if (ltype != type) {
if (type == MTRR_TYPE_UNCACHABLE) if (types_compatible(type, ltype))
continue; continue;
printk (KERN_WARNING "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n", printk (KERN_WARNING "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
base, size, mtrr_attrib_to_str(ltype), base, size, mtrr_attrib_to_str(ltype),
...@@ -364,10 +386,18 @@ int mtrr_add_page(unsigned long base, unsigned long size, ...@@ -364,10 +386,18 @@ int mtrr_add_page(unsigned long base, unsigned long size,
goto out; goto out;
} }
/* Search for an empty MTRR */ /* Search for an empty MTRR */
i = mtrr_if->get_free_region(base, size); i = mtrr_if->get_free_region(base, size, replace);
if (i >= 0) { if (i >= 0) {
set_mtrr(i, base, size, type); set_mtrr(i, base, size, type);
if (likely(replace < 0))
usage_table[i] = 1; usage_table[i] = 1;
else {
usage_table[i] = usage_table[replace] + !!increment;
if (unlikely(replace != i)) {
set_mtrr(replace, 0, 0, 0);
usage_table[replace] = 0;
}
}
} else } else
printk(KERN_INFO "mtrr: no more MTRRs available\n"); printk(KERN_INFO "mtrr: no more MTRRs available\n");
error = i; error = i;
...@@ -455,8 +485,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) ...@@ -455,8 +485,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
{ {
int i, max; int i, max;
mtrr_type ltype; mtrr_type ltype;
unsigned long lbase; unsigned long lbase, lsize;
unsigned int lsize;
int error = -EINVAL; int error = -EINVAL;
if (!mtrr_if) if (!mtrr_if)
...@@ -544,9 +573,11 @@ extern void centaur_init_mtrr(void); ...@@ -544,9 +573,11 @@ extern void centaur_init_mtrr(void);
static void __init init_ifs(void) static void __init init_ifs(void)
{ {
#ifndef CONFIG_X86_64
amd_init_mtrr(); amd_init_mtrr();
cyrix_init_mtrr(); cyrix_init_mtrr();
centaur_init_mtrr(); centaur_init_mtrr();
#endif
} }
/* The suspend/resume methods are only for CPU without MTRR. CPU using generic /* The suspend/resume methods are only for CPU without MTRR. CPU using generic
...@@ -555,7 +586,7 @@ static void __init init_ifs(void) ...@@ -555,7 +586,7 @@ static void __init init_ifs(void)
struct mtrr_value { struct mtrr_value {
mtrr_type ltype; mtrr_type ltype;
unsigned long lbase; unsigned long lbase;
unsigned int lsize; unsigned long lsize;
}; };
static struct mtrr_value * mtrr_state; static struct mtrr_value * mtrr_state;
...@@ -565,10 +596,8 @@ static int mtrr_save(struct sys_device * sysdev, pm_message_t state) ...@@ -565,10 +596,8 @@ static int mtrr_save(struct sys_device * sysdev, pm_message_t state)
int i; int i;
int size = num_var_ranges * sizeof(struct mtrr_value); int size = num_var_ranges * sizeof(struct mtrr_value);
mtrr_state = kmalloc(size,GFP_ATOMIC); mtrr_state = kzalloc(size,GFP_ATOMIC);
if (mtrr_state) if (!mtrr_state)
memset(mtrr_state,0,size);
else
return -ENOMEM; return -ENOMEM;
for (i = 0; i < num_var_ranges; i++) { for (i = 0; i < num_var_ranges; i++) {
......
...@@ -43,15 +43,16 @@ struct mtrr_ops { ...@@ -43,15 +43,16 @@ struct mtrr_ops {
void (*set_all)(void); void (*set_all)(void);
void (*get)(unsigned int reg, unsigned long *base, void (*get)(unsigned int reg, unsigned long *base,
unsigned int *size, mtrr_type * type); unsigned long *size, mtrr_type * type);
int (*get_free_region) (unsigned long base, unsigned long size); int (*get_free_region)(unsigned long base, unsigned long size,
int replace_reg);
int (*validate_add_page)(unsigned long base, unsigned long size, int (*validate_add_page)(unsigned long base, unsigned long size,
unsigned int type); unsigned int type);
int (*have_wrcomb)(void); int (*have_wrcomb)(void);
}; };
extern int generic_get_free_region(unsigned long base, unsigned long size); extern int generic_get_free_region(unsigned long base, unsigned long size,
int replace_reg);
extern int generic_validate_add_page(unsigned long base, unsigned long size, extern int generic_validate_add_page(unsigned long base, unsigned long size,
unsigned int type); unsigned int type);
...@@ -62,17 +63,17 @@ extern int positive_have_wrcomb(void); ...@@ -62,17 +63,17 @@ extern int positive_have_wrcomb(void);
/* library functions for processor-specific routines */ /* library functions for processor-specific routines */
struct set_mtrr_context { struct set_mtrr_context {
unsigned long flags; unsigned long flags;
unsigned long deftype_lo;
unsigned long deftype_hi;
unsigned long cr4val; unsigned long cr4val;
unsigned long ccr3; u32 deftype_lo;
u32 deftype_hi;
u32 ccr3;
}; };
struct mtrr_var_range { struct mtrr_var_range {
unsigned long base_lo; u32 base_lo;
unsigned long base_hi; u32 base_hi;
unsigned long mask_lo; u32 mask_lo;
unsigned long mask_hi; u32 mask_hi;
}; };
void set_mtrr_done(struct set_mtrr_context *ctxt); void set_mtrr_done(struct set_mtrr_context *ctxt);
...@@ -92,6 +93,6 @@ extern struct mtrr_ops * mtrr_if; ...@@ -92,6 +93,6 @@ extern struct mtrr_ops * mtrr_if;
extern unsigned int num_var_ranges; extern unsigned int num_var_ranges;
void mtrr_state_warn(void); void mtrr_state_warn(void);
char *mtrr_attrib_to_str(int x); const char *mtrr_attrib_to_str(int x);
void mtrr_wrmsr(unsigned, unsigned, unsigned); void mtrr_wrmsr(unsigned, unsigned, unsigned);
...@@ -152,9 +152,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -152,9 +152,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, " [%d]", i); seq_printf(m, " [%d]", i);
} }
seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n", seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
c->loops_per_jiffy/(500000/HZ), c->loops_per_jiffy/(500000/HZ),
(c->loops_per_jiffy/(5000/HZ)) % 100); (c->loops_per_jiffy/(5000/HZ)) % 100);
seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size);
return 0; return 0;
} }
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <linux/major.h> #include <linux/major.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/fs.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/notifier.h> #include <linux/notifier.h>
......
This diff is collapsed.
...@@ -194,17 +194,24 @@ inline int efi_set_rtc_mmss(unsigned long nowtime) ...@@ -194,17 +194,24 @@ inline int efi_set_rtc_mmss(unsigned long nowtime)
return 0; return 0;
} }
/* /*
* This should only be used during kernel init and before runtime * This is used during kernel init before runtime
* services have been remapped, therefore, we'll need to call in physical * services have been remapped and also during suspend, therefore,
* mode. Note, this call isn't used later, so mark it __init. * we'll need to call both in physical and virtual modes.
*/ */
inline unsigned long __init efi_get_time(void) inline unsigned long efi_get_time(void)
{ {
efi_status_t status; efi_status_t status;
efi_time_t eft; efi_time_t eft;
efi_time_cap_t cap; efi_time_cap_t cap;
if (efi.get_time) {
/* if we are in virtual mode use remapped function */
status = efi.get_time(&eft, &cap);
} else {
/* we are in physical mode */
status = phys_efi_get_time(&eft, &cap); status = phys_efi_get_time(&eft, &cap);
}
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
printk("Oops: efitime: can't read time status: 0x%lx\n",status); printk("Oops: efitime: can't read time status: 0x%lx\n",status);
......
This diff is collapsed.
...@@ -55,6 +55,12 @@ ...@@ -55,6 +55,12 @@
*/ */
ENTRY(startup_32) ENTRY(startup_32)
#ifdef CONFIG_PARAVIRT
movl %cs, %eax
testl $0x3, %eax
jnz startup_paravirt
#endif
/* /*
* Set segments to known values. * Set segments to known values.
*/ */
...@@ -302,6 +308,7 @@ is386: movl $2,%ecx # set MP ...@@ -302,6 +308,7 @@ is386: movl $2,%ecx # set MP
movl %eax,%cr0 movl %eax,%cr0
call check_x87 call check_x87
call setup_pda
lgdt cpu_gdt_descr lgdt cpu_gdt_descr
lidt idt_descr lidt idt_descr
ljmp $(__KERNEL_CS),$1f ljmp $(__KERNEL_CS),$1f
...@@ -312,10 +319,13 @@ is386: movl $2,%ecx # set MP ...@@ -312,10 +319,13 @@ is386: movl $2,%ecx # set MP
movl %eax,%ds movl %eax,%ds
movl %eax,%es movl %eax,%es
xorl %eax,%eax # Clear FS/GS and LDT xorl %eax,%eax # Clear FS and LDT
movl %eax,%fs movl %eax,%fs
movl %eax,%gs
lldt %ax lldt %ax
movl $(__KERNEL_PDA),%eax
mov %eax,%gs
cld # gcc2 wants the direction flag cleared at all times cld # gcc2 wants the direction flag cleared at all times
pushl $0 # fake return address for unwinder pushl $0 # fake return address for unwinder
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -345,6 +355,23 @@ check_x87: ...@@ -345,6 +355,23 @@ check_x87:
.byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */
ret ret
/*
* Point the GDT at this CPU's PDA. On boot this will be
* cpu_gdt_table and boot_pda; for secondary CPUs, these will be
* that CPU's GDT and PDA.
*/
setup_pda:
/* get the PDA pointer */
movl start_pda, %eax
/* slot the PDA address into the GDT */
mov cpu_gdt_descr+2, %ecx
mov %ax, (__KERNEL_PDA+0+2)(%ecx) /* base & 0x0000ffff */
shr $16, %eax
mov %al, (__KERNEL_PDA+4+0)(%ecx) /* base & 0x00ff0000 */
mov %ah, (__KERNEL_PDA+4+3)(%ecx) /* base & 0xff000000 */
ret
/* /*
* setup_idt * setup_idt
* *
...@@ -465,6 +492,33 @@ ignore_int: ...@@ -465,6 +492,33 @@ ignore_int:
#endif #endif
iret iret
#ifdef CONFIG_PARAVIRT
startup_paravirt:
cld
movl $(init_thread_union+THREAD_SIZE),%esp
/* We take pains to preserve all the regs. */
pushl %edx
pushl %ecx
pushl %eax
/* paravirt.o is last in link, and that probe fn never returns */
pushl $__start_paravirtprobe
1:
movl 0(%esp), %eax
pushl (%eax)
movl 8(%esp), %eax
call *(%esp)
popl %eax
movl 4(%esp), %eax
movl 8(%esp), %ecx
movl 12(%esp), %edx
addl $4, (%esp)
jmp 1b
#endif
/* /*
* Real beginning of normal "text" segment * Real beginning of normal "text" segment
*/ */
...@@ -484,6 +538,8 @@ ENTRY(empty_zero_page) ...@@ -484,6 +538,8 @@ ENTRY(empty_zero_page)
* This starts the data section. * This starts the data section.
*/ */
.data .data
ENTRY(start_pda)
.long boot_pda
ENTRY(stack_start) ENTRY(stack_start)
.long init_thread_union+THREAD_SIZE .long init_thread_union+THREAD_SIZE
...@@ -525,7 +581,7 @@ idt_descr: ...@@ -525,7 +581,7 @@ idt_descr:
# boot GDT descriptor (later on used by CPU#0): # boot GDT descriptor (later on used by CPU#0):
.word 0 # 32 bit align gdt_desc.address .word 0 # 32 bit align gdt_desc.address
cpu_gdt_descr: ENTRY(cpu_gdt_descr)
.word GDT_ENTRIES*8-1 .word GDT_ENTRIES*8-1
.long cpu_gdt_table .long cpu_gdt_table
...@@ -584,8 +640,8 @@ ENTRY(cpu_gdt_table) ...@@ -584,8 +640,8 @@ ENTRY(cpu_gdt_table)
.quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */ .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */
.quad 0x004092000000ffff /* 0xc8 APM DS data */ .quad 0x004092000000ffff /* 0xc8 APM DS data */
.quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */ .quad 0x00c0920000000000 /* 0xd0 - ESPFIX SS */
.quad 0x0000000000000000 /* 0xd8 - unused */ .quad 0x00cf92000000ffff /* 0xd8 - PDA */
.quad 0x0000000000000000 /* 0xe0 - unused */ .quad 0x0000000000000000 /* 0xe0 - unused */
.quad 0x0000000000000000 /* 0xe8 - unused */ .quad 0x0000000000000000 /* 0xe8 - unused */
.quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf0 - unused */
......
...@@ -34,6 +34,7 @@ static int __init init_hpet_clocksource(void) ...@@ -34,6 +34,7 @@ static int __init init_hpet_clocksource(void)
unsigned long hpet_period; unsigned long hpet_period;
void __iomem* hpet_base; void __iomem* hpet_base;
u64 tmp; u64 tmp;
int err;
if (!is_hpet_enabled()) if (!is_hpet_enabled())
return -ENODEV; return -ENODEV;
...@@ -61,7 +62,11 @@ static int __init init_hpet_clocksource(void) ...@@ -61,7 +62,11 @@ static int __init init_hpet_clocksource(void)
do_div(tmp, FSEC_PER_NSEC); do_div(tmp, FSEC_PER_NSEC);
clocksource_hpet.mult = (u32)tmp; clocksource_hpet.mult = (u32)tmp;
return clocksource_register(&clocksource_hpet); err = clocksource_register(&clocksource_hpet);
if (err)
iounmap(hpet_base);
return err;
} }
module_init(init_hpet_clocksource); module_init(init_hpet_clocksource);
...@@ -381,7 +381,10 @@ void __init init_ISA_irqs (void) ...@@ -381,7 +381,10 @@ void __init init_ISA_irqs (void)
} }
} }
void __init init_IRQ(void) /* Overridden in paravirt.c */
void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
void __init native_init_IRQ(void)
{ {
int i; int i;
......
...@@ -154,14 +154,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) ...@@ -154,14 +154,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
* the interrupt, and we need to make sure the entry is fully populated * the interrupt, and we need to make sure the entry is fully populated
* before that happens. * before that happens.
*/ */
static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) static void
__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
{ {
unsigned long flags;
union entry_union eu; union entry_union eu;
eu.entry = e; eu.entry = e;
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(apic, 0x11 + 2*pin, eu.w2); io_apic_write(apic, 0x11 + 2*pin, eu.w2);
io_apic_write(apic, 0x10 + 2*pin, eu.w1); io_apic_write(apic, 0x10 + 2*pin, eu.w1);
}
static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
{
unsigned long flags;
spin_lock_irqsave(&ioapic_lock, flags);
__ioapic_write_entry(apic, pin, e);
spin_unlock_irqrestore(&ioapic_lock, flags); spin_unlock_irqrestore(&ioapic_lock, flags);
} }
...@@ -837,8 +843,7 @@ static int __init find_isa_irq_pin(int irq, int type) ...@@ -837,8 +843,7 @@ static int __init find_isa_irq_pin(int irq, int type)
if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
mp_bus_id_to_type[lbus] == MP_BUS_EISA || mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
mp_bus_id_to_type[lbus] == MP_BUS_MCA || mp_bus_id_to_type[lbus] == MP_BUS_MCA
mp_bus_id_to_type[lbus] == MP_BUS_NEC98
) && ) &&
(mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == irq)) (mp_irqs[i].mpc_srcbusirq == irq))
...@@ -857,8 +862,7 @@ static int __init find_isa_irq_apic(int irq, int type) ...@@ -857,8 +862,7 @@ static int __init find_isa_irq_apic(int irq, int type)
if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
mp_bus_id_to_type[lbus] == MP_BUS_EISA || mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
mp_bus_id_to_type[lbus] == MP_BUS_MCA || mp_bus_id_to_type[lbus] == MP_BUS_MCA
mp_bus_id_to_type[lbus] == MP_BUS_NEC98
) && ) &&
(mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == irq)) (mp_irqs[i].mpc_srcbusirq == irq))
...@@ -988,12 +992,6 @@ static int EISA_ELCR(unsigned int irq) ...@@ -988,12 +992,6 @@ static int EISA_ELCR(unsigned int irq)
#define default_MCA_trigger(idx) (1) #define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) (0) #define default_MCA_polarity(idx) (0)
/* NEC98 interrupts are always polarity zero edge triggered,
* when listed as conforming in the MP table. */
#define default_NEC98_trigger(idx) (0)
#define default_NEC98_polarity(idx) (0)
static int __init MPBIOS_polarity(int idx) static int __init MPBIOS_polarity(int idx)
{ {
int bus = mp_irqs[idx].mpc_srcbus; int bus = mp_irqs[idx].mpc_srcbus;
...@@ -1028,11 +1026,6 @@ static int __init MPBIOS_polarity(int idx) ...@@ -1028,11 +1026,6 @@ static int __init MPBIOS_polarity(int idx)
polarity = default_MCA_polarity(idx); polarity = default_MCA_polarity(idx);
break; break;
} }
case MP_BUS_NEC98: /* NEC 98 pin */
{
polarity = default_NEC98_polarity(idx);
break;
}
default: default:
{ {
printk(KERN_WARNING "broken BIOS!!\n"); printk(KERN_WARNING "broken BIOS!!\n");
...@@ -1102,11 +1095,6 @@ static int MPBIOS_trigger(int idx) ...@@ -1102,11 +1095,6 @@ static int MPBIOS_trigger(int idx)
trigger = default_MCA_trigger(idx); trigger = default_MCA_trigger(idx);
break; break;
} }
case MP_BUS_NEC98: /* NEC 98 pin */
{
trigger = default_NEC98_trigger(idx);
break;
}
default: default:
{ {
printk(KERN_WARNING "broken BIOS!!\n"); printk(KERN_WARNING "broken BIOS!!\n");
...@@ -1168,7 +1156,6 @@ static int pin_2_irq(int idx, int apic, int pin) ...@@ -1168,7 +1156,6 @@ static int pin_2_irq(int idx, int apic, int pin)
case MP_BUS_ISA: /* ISA pin */ case MP_BUS_ISA: /* ISA pin */
case MP_BUS_EISA: case MP_BUS_EISA:
case MP_BUS_MCA: case MP_BUS_MCA:
case MP_BUS_NEC98:
{ {
irq = mp_irqs[idx].mpc_srcbusirq; irq = mp_irqs[idx].mpc_srcbusirq;
break; break;
...@@ -1236,7 +1223,7 @@ static inline int IO_APIC_irq_trigger(int irq) ...@@ -1236,7 +1223,7 @@ static inline int IO_APIC_irq_trigger(int irq)
} }
/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }; static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
static int __assign_irq_vector(int irq) static int __assign_irq_vector(int irq)
{ {
...@@ -1361,8 +1348,8 @@ static void __init setup_IO_APIC_irqs(void) ...@@ -1361,8 +1348,8 @@ static void __init setup_IO_APIC_irqs(void)
if (!apic && (irq < 16)) if (!apic && (irq < 16))
disable_8259A_irq(irq); disable_8259A_irq(irq);
} }
ioapic_write_entry(apic, pin, entry);
spin_lock_irqsave(&ioapic_lock, flags); spin_lock_irqsave(&ioapic_lock, flags);
__ioapic_write_entry(apic, pin, entry);
set_native_irq_info(irq, TARGET_CPUS); set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags); spin_unlock_irqrestore(&ioapic_lock, flags);
} }
...@@ -1927,6 +1914,15 @@ static void __init setup_ioapic_ids_from_mpc(void) ...@@ -1927,6 +1914,15 @@ static void __init setup_ioapic_ids_from_mpc(void)
static void __init setup_ioapic_ids_from_mpc(void) { } static void __init setup_ioapic_ids_from_mpc(void) { }
#endif #endif
static int no_timer_check __initdata;
static int __init notimercheck(char *s)
{
no_timer_check = 1;
return 1;
}
__setup("no_timer_check", notimercheck);
/* /*
* There is a nasty bug in some older SMP boards, their mptable lies * There is a nasty bug in some older SMP boards, their mptable lies
* about the timer IRQ. We do the following to work around the situation: * about the timer IRQ. We do the following to work around the situation:
...@@ -1935,10 +1931,13 @@ static void __init setup_ioapic_ids_from_mpc(void) { } ...@@ -1935,10 +1931,13 @@ static void __init setup_ioapic_ids_from_mpc(void) { }
* - if this function detects that timer IRQs are defunct, then we fall * - if this function detects that timer IRQs are defunct, then we fall
* back to ISA timer IRQs * back to ISA timer IRQs
*/ */
static int __init timer_irq_works(void) int __init timer_irq_works(void)
{ {
unsigned long t1 = jiffies; unsigned long t1 = jiffies;
if (no_timer_check)
return 1;
local_irq_enable(); local_irq_enable();
/* Let ten ticks pass... */ /* Let ten ticks pass... */
mdelay((10 * 1000) / HZ); mdelay((10 * 1000) / HZ);
...@@ -2162,9 +2161,15 @@ static inline void unlock_ExtINT_logic(void) ...@@ -2162,9 +2161,15 @@ static inline void unlock_ExtINT_logic(void)
unsigned char save_control, save_freq_select; unsigned char save_control, save_freq_select;
pin = find_isa_irq_pin(8, mp_INT); pin = find_isa_irq_pin(8, mp_INT);
if (pin == -1) {
WARN_ON_ONCE(1);
return;
}
apic = find_isa_irq_apic(8, mp_INT); apic = find_isa_irq_apic(8, mp_INT);
if (pin == -1) if (apic == -1) {
WARN_ON_ONCE(1);
return; return;
}
entry0 = ioapic_read_entry(apic, pin); entry0 = ioapic_read_entry(apic, pin);
clear_IO_APIC_pin(apic, pin); clear_IO_APIC_pin(apic, pin);
...@@ -2209,7 +2214,7 @@ int timer_uses_ioapic_pin_0; ...@@ -2209,7 +2214,7 @@ int timer_uses_ioapic_pin_0;
* is so screwy. Thanks to Brian Perkins for testing/hacking this beast * is so screwy. Thanks to Brian Perkins for testing/hacking this beast
* fanatically on his truly buggy board. * fanatically on his truly buggy board.
*/ */
static inline void check_timer(void) static inline void __init check_timer(void)
{ {
int apic1, pin1, apic2, pin2; int apic1, pin1, apic2, pin2;
int vector; int vector;
...@@ -2857,8 +2862,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a ...@@ -2857,8 +2862,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
if (!ioapic && (irq < 16)) if (!ioapic && (irq < 16))
disable_8259A_irq(irq); disable_8259A_irq(irq);
ioapic_write_entry(ioapic, pin, entry);
spin_lock_irqsave(&ioapic_lock, flags); spin_lock_irqsave(&ioapic_lock, flags);
__ioapic_write_entry(ioapic, pin, entry);
set_native_irq_info(irq, TARGET_CPUS); set_native_irq_info(irq, TARGET_CPUS);
spin_unlock_irqrestore(&ioapic_lock, flags); spin_unlock_irqrestore(&ioapic_lock, flags);
......
...@@ -160,16 +160,14 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) ...@@ -160,16 +160,14 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
{ {
int err; int err;
unsigned long size; unsigned long size;
void *address;
err = 0; err = 0;
address = &default_ldt[0];
size = 5*sizeof(struct desc_struct); size = 5*sizeof(struct desc_struct);
if (size > bytecount) if (size > bytecount)
size = bytecount; size = bytecount;
err = size; err = size;
if (copy_to_user(ptr, address, size)) if (clear_user(ptr, size))
err = -EFAULT; err = -EFAULT;
return err; return err;
......
...@@ -283,10 +283,9 @@ static int __init mca_init(void) ...@@ -283,10 +283,9 @@ static int __init mca_init(void)
bus->f.mca_transform_memory = mca_dummy_transform_memory; bus->f.mca_transform_memory = mca_dummy_transform_memory;
/* get the motherboard device */ /* get the motherboard device */
mca_dev = kmalloc(sizeof(struct mca_device), GFP_KERNEL); mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL);
if(unlikely(!mca_dev)) if(unlikely(!mca_dev))
goto out_nomem; goto out_nomem;
memset(mca_dev, 0, sizeof(struct mca_device));
/* /*
* We do not expect many MCA interrupts during initialization, * We do not expect many MCA interrupts during initialization,
...@@ -310,11 +309,9 @@ static int __init mca_init(void) ...@@ -310,11 +309,9 @@ static int __init mca_init(void)
mca_dev->slot = MCA_MOTHERBOARD; mca_dev->slot = MCA_MOTHERBOARD;
mca_register_device(MCA_PRIMARY_BUS, mca_dev); mca_register_device(MCA_PRIMARY_BUS, mca_dev);
mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC); mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
if(unlikely(!mca_dev)) if(unlikely(!mca_dev))
goto out_unlock_nomem; goto out_unlock_nomem;
memset(mca_dev, 0, sizeof(struct mca_device));
/* Put motherboard into video setup mode, read integrated video /* Put motherboard into video setup mode, read integrated video
* POS registers, and turn motherboard setup off. * POS registers, and turn motherboard setup off.
...@@ -349,10 +346,9 @@ static int __init mca_init(void) ...@@ -349,10 +346,9 @@ static int __init mca_init(void)
} }
if(which_scsi) { if(which_scsi) {
/* found a scsi card */ /* found a scsi card */
mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC); mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
if(unlikely(!mca_dev)) if(unlikely(!mca_dev))
goto out_unlock_nomem; goto out_unlock_nomem;
memset(mca_dev, 0, sizeof(struct mca_device));
for(j = 0; j < 8; j++) for(j = 0; j < 8; j++)
mca_dev->pos[j] = pos[j]; mca_dev->pos[j] = pos[j];
...@@ -378,10 +374,9 @@ static int __init mca_init(void) ...@@ -378,10 +374,9 @@ static int __init mca_init(void)
if(!mca_read_and_store_pos(pos)) if(!mca_read_and_store_pos(pos))
continue; continue;
mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC); mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
if(unlikely(!mca_dev)) if(unlikely(!mca_dev))
goto out_unlock_nomem; goto out_unlock_nomem;
memset(mca_dev, 0, sizeof(struct mca_device));
for(j=0; j<8; j++) for(j=0; j<8; j++)
mca_dev->pos[j]=pos[j]; mca_dev->pos[j]=pos[j];
......
...@@ -108,7 +108,8 @@ int module_finalize(const Elf_Ehdr *hdr, ...@@ -108,7 +108,8 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs, const Elf_Shdr *sechdrs,
struct module *me) struct module *me)
{ {
const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL; const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
*para = NULL;
char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
...@@ -118,6 +119,8 @@ int module_finalize(const Elf_Ehdr *hdr, ...@@ -118,6 +119,8 @@ int module_finalize(const Elf_Ehdr *hdr,
alt = s; alt = s;
if (!strcmp(".smp_locks", secstrings + s->sh_name)) if (!strcmp(".smp_locks", secstrings + s->sh_name))
locks= s; locks= s;
if (!strcmp(".parainstructions", secstrings + s->sh_name))
para = s;
} }
if (alt) { if (alt) {
...@@ -132,6 +135,12 @@ int module_finalize(const Elf_Ehdr *hdr, ...@@ -132,6 +135,12 @@ int module_finalize(const Elf_Ehdr *hdr,
lseg, lseg + locks->sh_size, lseg, lseg + locks->sh_size,
tseg, tseg + text->sh_size); tseg, tseg + text->sh_size);
} }
if (para) {
void *pseg = (void *)para->sh_addr;
apply_paravirt(pseg, pseg + para->sh_size);
}
return 0; return 0;
} }
......
...@@ -249,8 +249,6 @@ static void __init MP_bus_info (struct mpc_config_bus *m) ...@@ -249,8 +249,6 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
mp_current_pci_id++; mp_current_pci_id++;
} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
} else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
} else { } else {
printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
} }
......
...@@ -195,7 +195,6 @@ static ssize_t msr_write(struct file *file, const char __user *buf, ...@@ -195,7 +195,6 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
{ {
const u32 __user *tmp = (const u32 __user *)buf; const u32 __user *tmp = (const u32 __user *)buf;
u32 data[2]; u32 data[2];
size_t rv;
u32 reg = *ppos; u32 reg = *ppos;
int cpu = iminor(file->f_dentry->d_inode); int cpu = iminor(file->f_dentry->d_inode);
int err; int err;
...@@ -203,7 +202,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf, ...@@ -203,7 +202,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
if (count % 8) if (count % 8)
return -EINVAL; /* Invalid chunk size */ return -EINVAL; /* Invalid chunk size */
for (rv = 0; count; count -= 8) { for (; count; count -= 8) {
if (copy_from_user(&data, tmp, 8)) if (copy_from_user(&data, tmp, 8))
return -EFAULT; return -EFAULT;
err = do_wrmsr(cpu, reg, data[0], data[1]); err = do_wrmsr(cpu, reg, data[0], data[1]);
......
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.
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.
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