Merge phase #1 of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

This merges phase 1 of the x86 tree, which is a collection of branches:

  x86/alternatives, x86/cleanups, x86/commandline, x86/crashdump,
  x86/debug, x86/defconfig, x86/doc, x86/exports, x86/fpu, x86/gart,
  x86/idle, x86/mm, x86/mtrr, x86/nmi-watchdog, x86/oprofile,
  x86/paravirt, x86/reboot, x86/sparse-fixes, x86/tsc, x86/urgent and
  x86/vmalloc

and as Ingo says: "these are the easiest, purely independent x86 topics
with no conflicts, in one nice Octopus merge".

* 'x86-v28-for-linus-phase1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (147 commits)
  x86: mtrr_cleanup: treat WRPROT as UNCACHEABLE
  x86: mtrr_cleanup: first 1M may be covered in var mtrrs
  x86: mtrr_cleanup: print out correct type v2
  x86: trivial printk fix in efi.c
  x86, debug: mtrr_cleanup print out var mtrr before change it
  x86: mtrr_cleanup try gran_size to less than 1M, v3
  x86: mtrr_cleanup try gran_size to less than 1M, cleanup
  x86: change MTRR_SANITIZER to def_bool y
  x86, debug printouts: IOMMU setup failures should not be KERN_ERR
  x86: export set_memory_ro and set_memory_rw
  x86: mtrr_cleanup try gran_size to less than 1M
  x86: mtrr_cleanup prepare to make gran_size to less 1M
  x86: mtrr_cleanup safe to get more spare regs now
  x86_64: be less annoying on boot, v2
  x86: mtrr_cleanup hole size should be less than half of chunk_size, v2
  x86: add mtrr_cleanup_debug command line
  x86: mtrr_cleanup optimization, v2
  x86: don't need to go to chunksize to 4G
  x86_64: be less annoying on boot
  x86, olpc: fix endian bug in openfirmware workaround
  ...
This commit is contained in:
Linus Torvalds
2008-10-10 08:07:53 -07:00
374 changed files with 3927 additions and 2278 deletions

View File

@@ -251,8 +251,6 @@ mono.txt
- how to execute Mono-based .NET binaries with the help of BINFMT_MISC. - how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
moxa-smartio moxa-smartio
- file with info on installing/using Moxa multiport serial driver. - file with info on installing/using Moxa multiport serial driver.
mtrr.txt
- how to use PPro Memory Type Range Registers to increase performance.
mutex-design.txt mutex-design.txt
- info on the generic mutex subsystem. - info on the generic mutex subsystem.
namespaces/ namespaces/

View File

@@ -463,12 +463,6 @@ and is between 256 and 4096 characters. It is defined in the file
Range: 0 - 8192 Range: 0 - 8192
Default: 64 Default: 64
disable_8254_timer
enable_8254_timer
[IA32/X86_64] Disable/Enable interrupt 0 timer routing
over the 8254 in addition to over the IO-APIC. The
kernel tries to set a sensible default.
hpet= [X86-32,HPET] option to control HPET usage hpet= [X86-32,HPET] option to control HPET usage
Format: { enable (default) | disable | force } Format: { enable (default) | disable | force }
disable: disable HPET and use PIT instead disable: disable HPET and use PIT instead
@@ -1882,6 +1876,12 @@ and is between 256 and 4096 characters. It is defined in the file
shapers= [NET] shapers= [NET]
Maximal number of shapers. Maximal number of shapers.
show_msr= [x86] show boot-time MSR settings
Format: { <integer> }
Show boot-time (BIOS-initialized) MSR settings.
The parameter means the number of CPUs to show,
for example 1 means boot CPU only.
sim710= [SCSI,HW] sim710= [SCSI,HW]
See header of drivers/scsi/sim710.c. See header of drivers/scsi/sim710.c.

View File

@@ -0,0 +1,4 @@
00-INDEX
- this file
mtrr.txt
- how to use x86 Memory Type Range Registers to increase performance

View File

@@ -308,7 +308,7 @@ Protocol: 2.00+
Field name: start_sys Field name: start_sys
Type: read Type: read
Offset/size: 0x20c/4 Offset/size: 0x20c/2
Protocol: 2.00+ Protocol: 2.00+
The load low segment (0x1000). Obsolete. The load low segment (0x1000). Obsolete.

View File

@@ -14,6 +14,10 @@ PAT allows for different types of memory attributes. The most commonly used
ones that will be supported at this time are Write-back, Uncached, ones that will be supported at this time are Write-back, Uncached,
Write-combined and Uncached Minus. Write-combined and Uncached Minus.
PAT APIs
--------
There are many different APIs in the kernel that allows setting of memory There are many different APIs in the kernel that allows setting of memory
attributes at the page level. In order to avoid aliasing, these interfaces attributes at the page level. In order to avoid aliasing, these interfaces
should be used thoughtfully. Below is a table of interfaces available, should be used thoughtfully. Below is a table of interfaces available,
@@ -26,38 +30,38 @@ address range to avoid any aliasing.
API | RAM | ACPI,... | Reserved/Holes | API | RAM | ACPI,... | Reserved/Holes |
-----------------------|----------|------------|------------------| -----------------------|----------|------------|------------------|
| | | | | | | |
ioremap | -- | UC | UC | ioremap | -- | UC- | UC- |
| | | | | | | |
ioremap_cache | -- | WB | WB | ioremap_cache | -- | WB | WB |
| | | | | | | |
ioremap_nocache | -- | UC | UC | ioremap_nocache | -- | UC- | UC- |
| | | | | | | |
ioremap_wc | -- | -- | WC | ioremap_wc | -- | -- | WC |
| | | | | | | |
set_memory_uc | UC | -- | -- | set_memory_uc | UC- | -- | -- |
set_memory_wb | | | | set_memory_wb | | | |
| | | | | | | |
set_memory_wc | WC | -- | -- | set_memory_wc | WC | -- | -- |
set_memory_wb | | | | set_memory_wb | | | |
| | | | | | | |
pci sysfs resource | -- | -- | UC | pci sysfs resource | -- | -- | UC- |
| | | | | | | |
pci sysfs resource_wc | -- | -- | WC | pci sysfs resource_wc | -- | -- | WC |
is IORESOURCE_PREFETCH| | | | is IORESOURCE_PREFETCH| | | |
| | | | | | | |
pci proc | -- | -- | UC | pci proc | -- | -- | UC- |
!PCIIOC_WRITE_COMBINE | | | | !PCIIOC_WRITE_COMBINE | | | |
| | | | | | | |
pci proc | -- | -- | WC | pci proc | -- | -- | WC |
PCIIOC_WRITE_COMBINE | | | | PCIIOC_WRITE_COMBINE | | | |
| | | | | | | |
/dev/mem | -- | UC | UC | /dev/mem | -- | WB/WC/UC- | WB/WC/UC- |
read-write | | | | read-write | | | |
| | | | | | | |
/dev/mem | -- | UC | UC | /dev/mem | -- | UC- | UC- |
mmap SYNC flag | | | | mmap SYNC flag | | | |
| | | | | | | |
/dev/mem | -- | WB/WC/UC | WB/WC/UC | /dev/mem | -- | WB/WC/UC- | WB/WC/UC- |
mmap !SYNC flag | |(from exist-| (from exist- | mmap !SYNC flag | |(from exist-| (from exist- |
and | | ing alias)| ing alias) | and | | ing alias)| ing alias) |
any alias to this area| | | | any alias to this area| | | |
@@ -68,7 +72,7 @@ pci proc | -- | -- | WC |
and | | | | and | | | |
MTRR says WB | | | | MTRR says WB | | | |
| | | | | | | |
/dev/mem | -- | -- | UC_MINUS | /dev/mem | -- | -- | UC- |
mmap !SYNC flag | | | | mmap !SYNC flag | | | |
no alias to this area | | | | no alias to this area | | | |
and | | | | and | | | |
@@ -98,3 +102,35 @@ types.
Drivers should use set_memory_[uc|wc] to set access type for RAM ranges. Drivers should use set_memory_[uc|wc] to set access type for RAM ranges.
PAT debugging
-------------
With CONFIG_DEBUG_FS enabled, PAT memtype list can be examined by
# mount -t debugfs debugfs /sys/kernel/debug
# cat /sys/kernel/debug/x86/pat_memtype_list
PAT memtype list:
uncached-minus @ 0x7fadf000-0x7fae0000
uncached-minus @ 0x7fb19000-0x7fb1a000
uncached-minus @ 0x7fb1a000-0x7fb1b000
uncached-minus @ 0x7fb1b000-0x7fb1c000
uncached-minus @ 0x7fb1c000-0x7fb1d000
uncached-minus @ 0x7fb1d000-0x7fb1e000
uncached-minus @ 0x7fb1e000-0x7fb25000
uncached-minus @ 0x7fb25000-0x7fb26000
uncached-minus @ 0x7fb26000-0x7fb27000
uncached-minus @ 0x7fb27000-0x7fb28000
uncached-minus @ 0x7fb28000-0x7fb2e000
uncached-minus @ 0x7fb2e000-0x7fb2f000
uncached-minus @ 0x7fb2f000-0x7fb30000
uncached-minus @ 0x7fb31000-0x7fb32000
uncached-minus @ 0x80000000-0x90000000
This list shows physical address ranges and various PAT settings used to
access those physical address ranges.
Another, more verbose way of getting PAT related debug messages is with
"debugpat" boot parameter. With this parameter, various debug messages are
printed to dmesg log.

View File

@@ -54,10 +54,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

View File

@@ -29,6 +29,7 @@ config X86
select HAVE_FTRACE select HAVE_FTRACE
select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
select HAVE_ARCH_KGDB if !X86_VOYAGER select HAVE_ARCH_KGDB if !X86_VOYAGER
select HAVE_ARCH_TRACEHOOK
select HAVE_GENERIC_DMA_COHERENT if X86_32 select HAVE_GENERIC_DMA_COHERENT if X86_32
select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_EFFICIENT_UNALIGNED_ACCESS
@@ -1020,7 +1021,7 @@ config HAVE_ARCH_ALLOC_REMAP
config ARCH_FLATMEM_ENABLE config ARCH_FLATMEM_ENABLE
def_bool y def_bool y
depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC && !NUMA depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && !NUMA
config ARCH_DISCONTIGMEM_ENABLE config ARCH_DISCONTIGMEM_ENABLE
def_bool y def_bool y
@@ -1036,7 +1037,7 @@ config ARCH_SPARSEMEM_DEFAULT
config ARCH_SPARSEMEM_ENABLE config ARCH_SPARSEMEM_ENABLE
def_bool y def_bool y
depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) || X86_GENERICARCH
select SPARSEMEM_STATIC if X86_32 select SPARSEMEM_STATIC if X86_32
select SPARSEMEM_VMEMMAP_ENABLE if X86_64 select SPARSEMEM_VMEMMAP_ENABLE if X86_64
@@ -1117,10 +1118,10 @@ config MTRR
You can safely say Y even if your machine doesn't have MTRRs, you'll You can safely say Y even if your machine doesn't have MTRRs, you'll
just add about 9 KB to your kernel. just add about 9 KB to your kernel.
See <file:Documentation/mtrr.txt> for more information. See <file:Documentation/x86/mtrr.txt> for more information.
config MTRR_SANITIZER config MTRR_SANITIZER
bool def_bool y
prompt "MTRR cleanup support" prompt "MTRR cleanup support"
depends on MTRR depends on MTRR
help help
@@ -1131,7 +1132,7 @@ config MTRR_SANITIZER
The largest mtrr entry size for a continous block can be set with The largest mtrr entry size for a continous block can be set with
mtrr_chunk_size. mtrr_chunk_size.
If unsure, say N. If unsure, say Y.
config MTRR_SANITIZER_ENABLE_DEFAULT config MTRR_SANITIZER_ENABLE_DEFAULT
int "MTRR cleanup enable value (0-1)" int "MTRR cleanup enable value (0-1)"
@@ -1191,7 +1192,6 @@ config IRQBALANCE
config SECCOMP config SECCOMP
def_bool y def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode" prompt "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
help help
This kernel feature is useful for number crunching applications This kernel feature is useful for number crunching applications
that may need to compute untrusted bytecode during their that may need to compute untrusted bytecode during their
@@ -1199,7 +1199,7 @@ config SECCOMP
the process as file descriptors supporting the read/write the process as file descriptors supporting the read/write
syscalls, it's possible to isolate those applications in syscalls, it's possible to isolate those applications in
their own address space using seccomp. Once seccomp is their own address space using seccomp. Once seccomp is
enabled via /proc/<pid>/seccomp, it cannot be disabled enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
and the task is only allowed to execute a few safe syscalls and the task is only allowed to execute a few safe syscalls
defined by each seccomp mode. defined by each seccomp mode.
@@ -1356,14 +1356,14 @@ config PHYSICAL_ALIGN
Don't change this unless you know what you are doing. Don't change this unless you know what you are doing.
config HOTPLUG_CPU config HOTPLUG_CPU
bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" bool "Support for hot-pluggable CPUs"
depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER depends on SMP && HOTPLUG && !X86_VOYAGER
---help--- ---help---
Say Y here to experiment with turning CPUs off and on, and to Say Y here to allow turning CPUs off and on. CPUs can be
enable suspend on SMP systems. CPUs can be controlled through controlled through /sys/devices/system/cpu.
/sys/devices/system/cpu. ( Note: power management support will enable this option
Say N if you want to disable CPU hotplug and don't need to automatically on SMP systems. )
suspend. Say N if you want to disable CPU hotplug.
config COMPAT_VDSO config COMPAT_VDSO
def_bool y def_bool y
@@ -1378,6 +1378,51 @@ config COMPAT_VDSO
If unsure, say Y. If unsure, say Y.
config CMDLINE_BOOL
bool "Built-in kernel command line"
default n
help
Allow for specifying boot arguments to the kernel at
build time. On some systems (e.g. embedded ones), it is
necessary or convenient to provide some or all of the
kernel boot arguments with the kernel itself (that is,
to not rely on the boot loader to provide them.)
To compile command line arguments into the kernel,
set this option to 'Y', then fill in the
the boot arguments in CONFIG_CMDLINE.
Systems with fully functional boot loaders (i.e. non-embedded)
should leave this option set to 'N'.
config CMDLINE
string "Built-in kernel command string"
depends on CMDLINE_BOOL
default ""
help
Enter arguments here that should be compiled into the kernel
image and used at boot time. If the boot loader provides a
command line at boot time, it is appended to this string to
form the full kernel command line, when the system boots.
However, you can use the CONFIG_CMDLINE_OVERRIDE option to
change this behavior.
In most cases, the command line (whether built-in or provided
by the boot loader) should specify the device for the root
file system.
config CMDLINE_OVERRIDE
bool "Built-in command line overrides boot loader arguments"
default n
depends on CMDLINE_BOOL
help
Set this option to 'Y' to have the kernel ignore the boot loader
command line, and use ONLY the built-in command line.
This is used to work around broken boot loaders. This should
be set to 'N' under normal conditions.
endmenu endmenu
config ARCH_ENABLE_MEMORY_HOTPLUG config ARCH_ENABLE_MEMORY_HOTPLUG
@@ -1773,7 +1818,7 @@ config COMPAT_FOR_U64_ALIGNMENT
config SYSVIPC_COMPAT config SYSVIPC_COMPAT
def_bool y def_bool y
depends on X86_64 && COMPAT && SYSVIPC depends on COMPAT && SYSVIPC
endmenu endmenu

View File

@@ -418,3 +418,21 @@ config X86_MINIMUM_CPU_FAMILY
config X86_DEBUGCTLMSR config X86_DEBUGCTLMSR
def_bool y def_bool y
depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
config X86_DS
bool "Debug Store support"
default y
help
Add support for Debug Store.
This allows the kernel to provide a memory buffer to the hardware
to store various profiling and tracing events.
config X86_PTRACE_BTS
bool "ptrace interface to Branch Trace Store"
default y
depends on (X86_DS && X86_DEBUGCTLMSR)
help
Add a ptrace interface to allow collecting an execution trace
of the traced task.
This collects control flow changes in a (cyclic) buffer and allows
debuggers to fill in the gaps and show an execution trace of the debuggee.

View File

@@ -137,14 +137,15 @@ relocated:
*/ */
movl output_len(%ebx), %eax movl output_len(%ebx), %eax
pushl %eax pushl %eax
# push arguments for decompress_kernel:
pushl %ebp # output address pushl %ebp # output address
movl input_len(%ebx), %eax movl input_len(%ebx), %eax
pushl %eax # input_len pushl %eax # input_len
leal input_data(%ebx), %eax leal input_data(%ebx), %eax
pushl %eax # input_data pushl %eax # input_data
leal boot_heap(%ebx), %eax leal boot_heap(%ebx), %eax
pushl %eax # heap area as third argument pushl %eax # heap area
pushl %esi # real mode pointer as second arg pushl %esi # real mode pointer
call decompress_kernel call decompress_kernel
addl $20, %esp addl $20, %esp
popl %ecx popl %ecx

View File

@@ -16,7 +16,7 @@
*/ */
#undef CONFIG_PARAVIRT #undef CONFIG_PARAVIRT
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
#define _ASM_DESC_H_ 1 #define ASM_X86__DESC_H 1
#endif #endif
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
@@ -27,7 +27,7 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/screen_info.h> #include <linux/screen_info.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <asm/io.h> #include <linux/io.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/boot.h> #include <asm/boot.h>
#include <asm/bootparam.h> #include <asm/bootparam.h>
@@ -277,7 +277,8 @@ static void *memset(void *s, int c, unsigned n)
int i; int i;
char *ss = s; char *ss = s;
for (i = 0; i < n; i++) ss[i] = c; for (i = 0; i < n; i++)
ss[i] = c;
return s; return s;
} }
@@ -287,7 +288,8 @@ static void *memcpy(void *dest, const void *src, unsigned n)
const char *s = src; const char *s = src;
char *d = dest; char *d = dest;
for (i = 0; i < n; i++) d[i] = s[i]; for (i = 0; i < n; i++)
d[i] = s[i];
return dest; return dest;
} }

View File

@@ -30,7 +30,6 @@ SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */
SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */
/* to be loaded */ /* to be loaded */
ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
#ifndef SVGA_MODE #ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA #define SVGA_MODE ASK_VGA

View File

@@ -1,7 +1,7 @@
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.27-rc4 # Linux kernel version: 2.6.27-rc5
# Mon Aug 25 15:04:00 2008 # Wed Sep 3 17:23:09 2008
# #
# CONFIG_64BIT is not set # CONFIG_64BIT is not set
CONFIG_X86_32=y CONFIG_X86_32=y
@@ -202,7 +202,7 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_M586 is not set # CONFIG_M586 is not set
# CONFIG_M586TSC is not set # CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set # CONFIG_M586MMX is not set
# CONFIG_M686 is not set CONFIG_M686=y
# CONFIG_MPENTIUMII is not set # CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set # CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set # CONFIG_MPENTIUMM is not set
@@ -221,13 +221,14 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set # CONFIG_MVIAC7 is not set
# CONFIG_MPSC is not set # CONFIG_MPSC is not set
CONFIG_MCORE2=y # CONFIG_MCORE2 is not set
# CONFIG_GENERIC_CPU is not set # CONFIG_GENERIC_CPU is not set
CONFIG_X86_GENERIC=y CONFIG_X86_GENERIC=y
CONFIG_X86_CPU=y CONFIG_X86_CPU=y
CONFIG_X86_CMPXCHG=y CONFIG_X86_CMPXCHG=y
CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_L1_CACHE_SHIFT=7
CONFIG_X86_XADD=y CONFIG_X86_XADD=y
# CONFIG_X86_PPRO_FENCE is not set
CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INVLPG=y CONFIG_X86_INVLPG=y
CONFIG_X86_BSWAP=y CONFIG_X86_BSWAP=y
@@ -235,14 +236,15 @@ CONFIG_X86_POPAD_OK=y
CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_TSC=y CONFIG_X86_TSC=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=4 CONFIG_X86_MINIMUM_CPU_FAMILY=4
CONFIG_X86_DEBUGCTLMSR=y CONFIG_X86_DEBUGCTLMSR=y
CONFIG_HPET_TIMER=y CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y CONFIG_HPET_EMULATE_RTC=y
CONFIG_DMI=y CONFIG_DMI=y
# CONFIG_IOMMU_HELPER is not set # CONFIG_IOMMU_HELPER is not set
CONFIG_NR_CPUS=4 CONFIG_NR_CPUS=64
# CONFIG_SCHED_SMT is not set CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y CONFIG_PREEMPT_VOLUNTARY=y
@@ -254,7 +256,8 @@ CONFIG_VM86=y
# CONFIG_TOSHIBA is not set # CONFIG_TOSHIBA is not set
# CONFIG_I8K is not set # CONFIG_I8K is not set
CONFIG_X86_REBOOTFIXUPS=y CONFIG_X86_REBOOTFIXUPS=y
# CONFIG_MICROCODE is not set CONFIG_MICROCODE=y
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_X86_MSR=y CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y CONFIG_X86_CPUID=y
# CONFIG_NOHIGHMEM is not set # CONFIG_NOHIGHMEM is not set
@@ -2115,7 +2118,7 @@ CONFIG_IO_DELAY_0X80=y
CONFIG_DEFAULT_IO_DELAY_TYPE=0 CONFIG_DEFAULT_IO_DELAY_TYPE=0
CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_DEBUG_BOOT_PARAMS=y
# CONFIG_CPA_DEBUG is not set # CONFIG_CPA_DEBUG is not set
# CONFIG_OPTIMIZE_INLINING is not set CONFIG_OPTIMIZE_INLINING=y
# #
# Security options # Security options

View File

@@ -1,7 +1,7 @@
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.27-rc4 # Linux kernel version: 2.6.27-rc5
# Mon Aug 25 14:40:46 2008 # Wed Sep 3 17:13:39 2008
# #
CONFIG_64BIT=y CONFIG_64BIT=y
# CONFIG_X86_32 is not set # CONFIG_X86_32 is not set
@@ -218,17 +218,14 @@ CONFIG_X86_PC=y
# CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set # CONFIG_MVIAC7 is not set
# CONFIG_MPSC is not set # CONFIG_MPSC is not set
CONFIG_MCORE2=y # CONFIG_MCORE2 is not set
# CONFIG_GENERIC_CPU is not set CONFIG_GENERIC_CPU=y
CONFIG_X86_CPU=y CONFIG_X86_CPU=y
CONFIG_X86_L1_CACHE_BYTES=64 CONFIG_X86_L1_CACHE_BYTES=128
CONFIG_X86_INTERNODE_CACHE_BYTES=64 CONFIG_X86_INTERNODE_CACHE_BYTES=128
CONFIG_X86_CMPXCHG=y CONFIG_X86_CMPXCHG=y
CONFIG_X86_L1_CACHE_SHIFT=6 CONFIG_X86_L1_CACHE_SHIFT=7
CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_P6_NOP=y
CONFIG_X86_TSC=y CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y CONFIG_X86_CMPXCHG64=y
CONFIG_X86_CMOV=y CONFIG_X86_CMOV=y
@@ -243,9 +240,8 @@ CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y
CONFIG_AMD_IOMMU=y CONFIG_AMD_IOMMU=y
CONFIG_SWIOTLB=y CONFIG_SWIOTLB=y
CONFIG_IOMMU_HELPER=y CONFIG_IOMMU_HELPER=y
# CONFIG_MAXSMP is not set CONFIG_NR_CPUS=64
CONFIG_NR_CPUS=4 CONFIG_SCHED_SMT=y
# CONFIG_SCHED_SMT is not set
CONFIG_SCHED_MC=y CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y CONFIG_PREEMPT_VOLUNTARY=y
@@ -254,7 +250,8 @@ CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y CONFIG_X86_IO_APIC=y
# CONFIG_X86_MCE is not set # CONFIG_X86_MCE is not set
# CONFIG_I8K is not set # CONFIG_I8K is not set
# CONFIG_MICROCODE is not set CONFIG_MICROCODE=y
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_X86_MSR=y CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y CONFIG_X86_CPUID=y
CONFIG_NUMA=y CONFIG_NUMA=y
@@ -290,7 +287,7 @@ CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y CONFIG_VIRT_TO_BUS=y
CONFIG_MTRR=y CONFIG_MTRR=y
# CONFIG_MTRR_SANITIZER is not set # CONFIG_MTRR_SANITIZER is not set
# CONFIG_X86_PAT is not set CONFIG_X86_PAT=y
CONFIG_EFI=y CONFIG_EFI=y
CONFIG_SECCOMP=y CONFIG_SECCOMP=y
# CONFIG_HZ_100 is not set # CONFIG_HZ_100 is not set
@@ -2089,7 +2086,7 @@ CONFIG_IO_DELAY_0X80=y
CONFIG_DEFAULT_IO_DELAY_TYPE=0 CONFIG_DEFAULT_IO_DELAY_TYPE=0
CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_DEBUG_BOOT_PARAMS=y
# CONFIG_CPA_DEBUG is not set # CONFIG_CPA_DEBUG is not set
# CONFIG_OPTIMIZE_INLINING is not set CONFIG_OPTIMIZE_INLINING=y
# #
# Security options # Security options

View File

@@ -85,8 +85,10 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
dump->regs.ax = regs->ax; dump->regs.ax = regs->ax;
dump->regs.ds = current->thread.ds; dump->regs.ds = current->thread.ds;
dump->regs.es = current->thread.es; dump->regs.es = current->thread.es;
asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs; savesegment(fs, fs);
asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; dump->regs.fs = fs;
savesegment(gs, gs);
dump->regs.gs = gs;
dump->regs.orig_ax = regs->orig_ax; dump->regs.orig_ax = regs->orig_ax;
dump->regs.ip = regs->ip; dump->regs.ip = regs->ip;
dump->regs.cs = regs->cs; dump->regs.cs = regs->cs;
@@ -430,8 +432,9 @@ beyond_if:
current->mm->start_stack = current->mm->start_stack =
(unsigned long)create_aout_tables((char __user *)bprm->p, bprm); (unsigned long)create_aout_tables((char __user *)bprm->p, bprm);
/* start thread */ /* start thread */
asm volatile("movl %0,%%fs" :: "r" (0)); \ loadsegment(fs, 0);
asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); loadsegment(ds, __USER32_DS);
loadsegment(es, __USER32_DS);
load_gs_index(0); load_gs_index(0);
(regs)->ip = ex.a_entry; (regs)->ip = ex.a_entry;
(regs)->sp = current->mm->start_stack; (regs)->sp = current->mm->start_stack;

View File

@@ -206,7 +206,7 @@ struct rt_sigframe
{ unsigned int cur; \ { unsigned int cur; \
unsigned short pre; \ unsigned short pre; \
err |= __get_user(pre, &sc->seg); \ err |= __get_user(pre, &sc->seg); \
asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \ savesegment(seg, cur); \
pre |= mask; \ pre |= mask; \
if (pre != cur) loadsegment(seg, pre); } if (pre != cur) loadsegment(seg, pre); }
@@ -235,7 +235,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
*/ */
err |= __get_user(gs, &sc->gs); err |= __get_user(gs, &sc->gs);
gs |= 3; gs |= 3;
asm("movl %%gs,%0" : "=r" (oldgs)); savesegment(gs, oldgs);
if (gs != oldgs) if (gs != oldgs)
load_gs_index(gs); load_gs_index(gs);
@@ -355,14 +355,13 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
{ {
int tmp, err = 0; int tmp, err = 0;
tmp = 0; savesegment(gs, tmp);
__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
err |= __put_user(tmp, (unsigned int __user *)&sc->gs); err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
__asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); savesegment(fs, tmp);
err |= __put_user(tmp, (unsigned int __user *)&sc->fs); err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
__asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp)); savesegment(ds, tmp);
err |= __put_user(tmp, (unsigned int __user *)&sc->ds); err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
__asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp)); savesegment(es, tmp);
err |= __put_user(tmp, (unsigned int __user *)&sc->es); err |= __put_user(tmp, (unsigned int __user *)&sc->es);
err |= __put_user((u32)regs->di, &sc->di); err |= __put_user((u32)regs->di, &sc->di);
@@ -498,8 +497,8 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
regs->dx = 0; regs->dx = 0;
regs->cx = 0; regs->cx = 0;
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); loadsegment(ds, __USER32_DS);
asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); loadsegment(es, __USER32_DS);
regs->cs = __USER32_CS; regs->cs = __USER32_CS;
regs->ss = __USER32_DS; regs->ss = __USER32_DS;
@@ -591,8 +590,8 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->dx = (unsigned long) &frame->info; regs->dx = (unsigned long) &frame->info;
regs->cx = (unsigned long) &frame->uc; regs->cx = (unsigned long) &frame->uc;
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); loadsegment(ds, __USER32_DS);
asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); loadsegment(es, __USER32_DS);
regs->cs = __USER32_CS; regs->cs = __USER32_CS;
regs->ss = __USER32_DS; regs->ss = __USER32_DS;

View File

@@ -556,15 +556,6 @@ asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig,
return ret; return ret;
} }
/* These are here just in case some old ia32 binary calls it. */
asmlinkage long sys32_pause(void)
{
current->state = TASK_INTERRUPTIBLE;
schedule();
return -ERESTARTNOHAND;
}
#ifdef CONFIG_SYSCTL_SYSCALL #ifdef CONFIG_SYSCTL_SYSCALL
struct sysctl_ia32 { struct sysctl_ia32 {
unsigned int name; unsigned int name;

View File

@@ -58,7 +58,6 @@ EXPORT_SYMBOL(acpi_disabled);
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/genapic.h>
#else /* X86 */ #else /* X86 */
@@ -97,8 +96,6 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#warning ACPI uses CMPXCHG, i486 and later hardware #warning ACPI uses CMPXCHG, i486 and later hardware
#endif #endif
static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Boot-time Configuration Boot-time Configuration
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
@@ -160,6 +157,8 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
struct acpi_mcfg_allocation *pci_mmcfg_config; struct acpi_mcfg_allocation *pci_mmcfg_config;
int pci_mmcfg_config_num; int pci_mmcfg_config_num;
static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg) static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
{ {
if (!strcmp(mcfg->header.oem_id, "SGI")) if (!strcmp(mcfg->header.oem_id, "SGI"))

View File

@@ -231,25 +231,25 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
continue; continue;
if (*ptr > text_end) if (*ptr > text_end)
continue; continue;
text_poke(*ptr, ((unsigned char []){0xf0}), 1); /* add lock prefix */ /* turn DS segment override prefix into lock prefix */
text_poke(*ptr, ((unsigned char []){0xf0}), 1);
}; };
} }
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)
{ {
u8 **ptr; u8 **ptr;
char insn[1];
if (noreplace_smp) if (noreplace_smp)
return; return;
add_nops(insn, 1);
for (ptr = start; ptr < end; ptr++) { for (ptr = start; ptr < end; ptr++) {
if (*ptr < text) if (*ptr < text)
continue; continue;
if (*ptr > text_end) if (*ptr > text_end)
continue; continue;
text_poke(*ptr, insn, 1); /* turn lock prefix into DS segment override prefix */
text_poke(*ptr, ((unsigned char []){0x3E}), 1);
}; };
} }

View File

@@ -455,11 +455,11 @@ out:
force_iommu || force_iommu ||
valid_agp || valid_agp ||
fallback_aper_force) { fallback_aper_force) {
printk(KERN_ERR printk(KERN_INFO
"Your BIOS doesn't leave a aperture memory hole\n"); "Your BIOS doesn't leave a aperture memory hole\n");
printk(KERN_ERR printk(KERN_INFO
"Please enable the IOMMU option in the BIOS setup\n"); "Please enable the IOMMU option in the BIOS setup\n");
printk(KERN_ERR printk(KERN_INFO
"This costs you %d MB of RAM\n", "This costs you %d MB of RAM\n",
32 << fallback_aper_order); 32 << fallback_aper_order);

View File

@@ -228,7 +228,6 @@
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/smp_lock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>

View File

@@ -22,7 +22,7 @@
#define __NO_STUBS 1 #define __NO_STUBS 1
#undef __SYSCALL #undef __SYSCALL
#undef _ASM_X86_64_UNISTD_H_ #undef ASM_X86__UNISTD_64_H
#define __SYSCALL(nr, sym) [nr] = 1, #define __SYSCALL(nr, sym) [nr] = 1,
static char syscalls[] = { static char syscalls[] = {
#include <asm/unistd.h> #include <asm/unistd.h>

View File

@@ -430,6 +430,49 @@ static __init int setup_noclflush(char *arg)
} }
__setup("noclflush", setup_noclflush); __setup("noclflush", setup_noclflush);
struct msr_range {
unsigned min;
unsigned max;
};
static struct msr_range msr_range_array[] __cpuinitdata = {
{ 0x00000000, 0x00000418},
{ 0xc0000000, 0xc000040b},
{ 0xc0010000, 0xc0010142},
{ 0xc0011000, 0xc001103b},
};
static void __cpuinit print_cpu_msr(void)
{
unsigned index;
u64 val;
int i;
unsigned index_min, index_max;
for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
index_min = msr_range_array[i].min;
index_max = msr_range_array[i].max;
for (index = index_min; index < index_max; index++) {
if (rdmsrl_amd_safe(index, &val))
continue;
printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
}
}
}
static int show_msr __cpuinitdata;
static __init int setup_show_msr(char *arg)
{
int num;
get_option(&arg, &num);
if (num > 0)
show_msr = num;
return 1;
}
__setup("show_msr=", setup_show_msr);
void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
{ {
if (c->x86_model_id[0]) if (c->x86_model_id[0])
@@ -439,6 +482,14 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
printk(KERN_CONT " stepping %02x\n", c->x86_mask); printk(KERN_CONT " stepping %02x\n", c->x86_mask);
else else
printk(KERN_CONT "\n"); printk(KERN_CONT "\n");
#ifdef CONFIG_SMP
if (c->cpu_index < show_msr)
print_cpu_msr();
#else
if (show_msr)
print_cpu_msr();
#endif
} }
static __init int setup_disablecpuid(char *arg) static __init int setup_disablecpuid(char *arg)

View File

@@ -222,10 +222,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_BTS); set_cpu_cap(c, X86_FEATURE_BTS);
if (!(l1 & (1<<12))) if (!(l1 & (1<<12)))
set_cpu_cap(c, X86_FEATURE_PEBS); set_cpu_cap(c, X86_FEATURE_PEBS);
ds_init_intel(c);
} }
if (cpu_has_bts) if (cpu_has_bts)
ds_init_intel(c); ptrace_bts_init_intel(c);
/* /*
* See if we have a good local APIC by checking for buggy Pentia, * See if we have a good local APIC by checking for buggy Pentia,

View File

@@ -401,12 +401,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
tmp |= ~((1<<(hi - 1)) - 1); tmp |= ~((1<<(hi - 1)) - 1);
if (tmp != mask_lo) { if (tmp != mask_lo) {
static int once = 1; WARN_ONCE(1, KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n");
if (once) {
printk(KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n");
once = 0;
}
mask_lo = tmp; mask_lo = tmp;
} }
} }

View File

@@ -405,9 +405,9 @@ 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 (%4luMB), size=%4lu%cB: %s, count=%d\n", "reg%02i: base=0x%06lx000 (%5luMB), size=%5lu%cB, count=%d: %s\n",
i, base, base >> (20 - PAGE_SHIFT), size, factor, i, base, base >> (20 - PAGE_SHIFT), size, factor,
mtrr_attrib_to_str(type), mtrr_usage_table[i]); mtrr_usage_table[i], mtrr_attrib_to_str(type));
} }
} }
return 0; return 0;

View File

@@ -729,7 +729,7 @@ struct var_mtrr_range_state {
mtrr_type type; mtrr_type type;
}; };
struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; static struct var_mtrr_range_state __initdata range_state[RANGE_NUM];
static int __initdata debug_print; static int __initdata debug_print;
static int __init static int __init
@@ -759,7 +759,8 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range,
/* take out UC ranges */ /* take out UC ranges */
for (i = 0; i < num_var_ranges; i++) { for (i = 0; i < num_var_ranges; i++) {
type = range_state[i].type; type = range_state[i].type;
if (type != MTRR_TYPE_UNCACHABLE) if (type != MTRR_TYPE_UNCACHABLE &&
type != MTRR_TYPE_WRPROT)
continue; continue;
size = range_state[i].size_pfn; size = range_state[i].size_pfn;
if (!size) if (!size)
@@ -836,6 +837,13 @@ static int __init enable_mtrr_cleanup_setup(char *str)
} }
early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup); early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
static int __init mtrr_cleanup_debug_setup(char *str)
{
debug_print = 1;
return 0;
}
early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup);
struct var_mtrr_state { struct var_mtrr_state {
unsigned long range_startk; unsigned long range_startk;
unsigned long range_sizek; unsigned long range_sizek;
@@ -898,6 +906,27 @@ set_var_mtrr_all(unsigned int address_bits)
} }
} }
static unsigned long to_size_factor(unsigned long sizek, char *factorp)
{
char factor;
unsigned long base = sizek;
if (base & ((1<<10) - 1)) {
/* not MB alignment */
factor = 'K';
} else if (base & ((1<<20) - 1)){
factor = 'M';
base >>= 10;
} else {
factor = 'G';
base >>= 20;
}
*factorp = factor;
return base;
}
static unsigned int __init static unsigned int __init
range_to_mtrr(unsigned int reg, unsigned long range_startk, range_to_mtrr(unsigned int reg, unsigned long range_startk,
unsigned long range_sizek, unsigned char type) unsigned long range_sizek, unsigned char type)
@@ -919,13 +948,21 @@ range_to_mtrr(unsigned int reg, unsigned long range_startk,
align = max_align; align = max_align;
sizek = 1 << align; sizek = 1 << align;
if (debug_print) if (debug_print) {
char start_factor = 'K', size_factor = 'K';
unsigned long start_base, size_base;
start_base = to_size_factor(range_startk, &start_factor),
size_base = to_size_factor(sizek, &size_factor),
printk(KERN_DEBUG "Setting variable MTRR %d, " printk(KERN_DEBUG "Setting variable MTRR %d, "
"base: %ldMB, range: %ldMB, type %s\n", "base: %ld%cB, range: %ld%cB, type %s\n",
reg, range_startk >> 10, sizek >> 10, reg, start_base, start_factor,
size_base, size_factor,
(type == MTRR_TYPE_UNCACHABLE)?"UC": (type == MTRR_TYPE_UNCACHABLE)?"UC":
((type == MTRR_TYPE_WRBACK)?"WB":"Other") ((type == MTRR_TYPE_WRBACK)?"WB":"Other")
); );
}
save_var_mtrr(reg++, range_startk, sizek, type); save_var_mtrr(reg++, range_startk, sizek, type);
range_startk += sizek; range_startk += sizek;
range_sizek -= sizek; range_sizek -= sizek;
@@ -970,6 +1007,8 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
/* try to append some small hole */ /* try to append some small hole */
range0_basek = state->range_startk; range0_basek = state->range_startk;
range0_sizek = ALIGN(state->range_sizek, chunk_sizek); range0_sizek = ALIGN(state->range_sizek, chunk_sizek);
/* no increase */
if (range0_sizek == state->range_sizek) { if (range0_sizek == state->range_sizek) {
if (debug_print) if (debug_print)
printk(KERN_DEBUG "rangeX: %016lx - %016lx\n", printk(KERN_DEBUG "rangeX: %016lx - %016lx\n",
@@ -980,15 +1019,42 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
return 0; return 0;
} }
range0_sizek -= chunk_sizek; /* only cut back, when it is not the last */
if (range0_sizek && sizek) { if (sizek) {
while (range0_basek + range0_sizek > (basek + sizek)) { while (range0_basek + range0_sizek > (basek + sizek)) {
if (range0_sizek >= chunk_sizek)
range0_sizek -= chunk_sizek; range0_sizek -= chunk_sizek;
else
range0_sizek = 0;
if (!range0_sizek) if (!range0_sizek)
break; break;
} }
} }
second_try:
range_basek = range0_basek + range0_sizek;
/* one hole in the middle */
if (range_basek > basek && range_basek <= (basek + sizek))
second_sizek = range_basek - basek;
if (range0_sizek > state->range_sizek) {
/* one hole in middle or at end */
hole_sizek = range0_sizek - state->range_sizek - second_sizek;
/* hole size should be less than half of range0 size */
if (hole_sizek >= (range0_sizek >> 1) &&
range0_sizek >= chunk_sizek) {
range0_sizek -= chunk_sizek;
second_sizek = 0;
hole_sizek = 0;
goto second_try;
}
}
if (range0_sizek) { if (range0_sizek) {
if (debug_print) if (debug_print)
printk(KERN_DEBUG "range0: %016lx - %016lx\n", printk(KERN_DEBUG "range0: %016lx - %016lx\n",
@@ -996,50 +1062,28 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
(range0_basek + range0_sizek)<<10); (range0_basek + range0_sizek)<<10);
state->reg = range_to_mtrr(state->reg, range0_basek, state->reg = range_to_mtrr(state->reg, range0_basek,
range0_sizek, MTRR_TYPE_WRBACK); range0_sizek, MTRR_TYPE_WRBACK);
} }
range_basek = range0_basek + range0_sizek; if (range0_sizek < state->range_sizek) {
range_sizek = chunk_sizek; /* need to handle left over */
if (range_basek + range_sizek > basek &&
range_basek + range_sizek <= (basek + sizek)) {
/* one hole */
second_basek = basek;
second_sizek = range_basek + range_sizek - basek;
}
/* if last piece, only could one hole near end */
if ((second_basek || !basek) &&
range_sizek - (state->range_sizek - range0_sizek) - second_sizek <
(chunk_sizek >> 1)) {
/*
* one hole in middle (second_sizek is 0) or at end
* (second_sizek is 0 )
*/
hole_sizek = range_sizek - (state->range_sizek - range0_sizek)
- second_sizek;
hole_basek = range_basek + range_sizek - hole_sizek
- second_sizek;
} else {
/* fallback for big hole, or several holes */
range_sizek = state->range_sizek - range0_sizek; range_sizek = state->range_sizek - range0_sizek;
second_basek = 0;
second_sizek = 0;
}
if (debug_print) if (debug_print)
printk(KERN_DEBUG "range: %016lx - %016lx\n", range_basek<<10, printk(KERN_DEBUG "range: %016lx - %016lx\n",
range_basek<<10,
(range_basek + range_sizek)<<10); (range_basek + range_sizek)<<10);
state->reg = range_to_mtrr(state->reg, range_basek, range_sizek, state->reg = range_to_mtrr(state->reg, range_basek,
MTRR_TYPE_WRBACK); range_sizek, MTRR_TYPE_WRBACK);
}
if (hole_sizek) { if (hole_sizek) {
hole_basek = range_basek - hole_sizek - second_sizek;
if (debug_print) if (debug_print)
printk(KERN_DEBUG "hole: %016lx - %016lx\n", printk(KERN_DEBUG "hole: %016lx - %016lx\n",
hole_basek<<10, (hole_basek + hole_sizek)<<10); hole_basek<<10,
state->reg = range_to_mtrr(state->reg, hole_basek, hole_sizek, (hole_basek + hole_sizek)<<10);
MTRR_TYPE_UNCACHABLE); state->reg = range_to_mtrr(state->reg, hole_basek,
hole_sizek, MTRR_TYPE_UNCACHABLE);
} }
return second_sizek; return second_sizek;
@@ -1154,11 +1198,11 @@ struct mtrr_cleanup_result {
}; };
/* /*
* gran_size: 1M, 2M, ..., 2G * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G
* chunk size: gran_size, ..., 4G * chunk size: gran_size, ..., 2G
* so we need (2+13)*6 * so we need (1+16)*8
*/ */
#define NUM_RESULT 90 #define NUM_RESULT 136
#define PSHIFT (PAGE_SHIFT - 10) #define PSHIFT (PAGE_SHIFT - 10)
static struct mtrr_cleanup_result __initdata result[NUM_RESULT]; static struct mtrr_cleanup_result __initdata result[NUM_RESULT];
@@ -1168,13 +1212,14 @@ static unsigned long __initdata min_loss_pfn[RANGE_NUM];
static int __init mtrr_cleanup(unsigned address_bits) static int __init mtrr_cleanup(unsigned address_bits)
{ {
unsigned long extra_remove_base, extra_remove_size; unsigned long extra_remove_base, extra_remove_size;
unsigned long i, base, size, def, dummy; unsigned long base, size, def, dummy;
mtrr_type type; mtrr_type type;
int nr_range, nr_range_new; int nr_range, nr_range_new;
u64 chunk_size, gran_size; u64 chunk_size, gran_size;
unsigned long range_sums, range_sums_new; unsigned long range_sums, range_sums_new;
int index_good; int index_good;
int num_reg_good; int num_reg_good;
int i;
/* extra one for all 0 */ /* extra one for all 0 */
int num[MTRR_NUM_TYPES + 1]; int num[MTRR_NUM_TYPES + 1];
@@ -1204,6 +1249,8 @@ static int __init mtrr_cleanup(unsigned address_bits)
continue; continue;
if (!size) if (!size)
type = MTRR_NUM_TYPES; type = MTRR_NUM_TYPES;
if (type == MTRR_TYPE_WRPROT)
type = MTRR_TYPE_UNCACHABLE;
num[type]++; num[type]++;
} }
@@ -1216,23 +1263,57 @@ static int __init mtrr_cleanup(unsigned address_bits)
num_var_ranges - num[MTRR_NUM_TYPES]) num_var_ranges - num[MTRR_NUM_TYPES])
return 0; return 0;
/* print original var MTRRs at first, for debugging: */
printk(KERN_DEBUG "original variable MTRRs\n");
for (i = 0; i < num_var_ranges; i++) {
char start_factor = 'K', size_factor = 'K';
unsigned long start_base, size_base;
size_base = range_state[i].size_pfn << (PAGE_SHIFT - 10);
if (!size_base)
continue;
size_base = to_size_factor(size_base, &size_factor),
start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10);
start_base = to_size_factor(start_base, &start_factor),
type = range_state[i].type;
printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
i, start_base, start_factor,
size_base, size_factor,
(type == MTRR_TYPE_UNCACHABLE) ? "UC" :
((type == MTRR_TYPE_WRPROT) ? "WP" :
((type == MTRR_TYPE_WRBACK) ? "WB" : "Other"))
);
}
memset(range, 0, sizeof(range)); memset(range, 0, sizeof(range));
extra_remove_size = 0; extra_remove_size = 0;
if (mtrr_tom2) {
extra_remove_base = 1 << (32 - PAGE_SHIFT); extra_remove_base = 1 << (32 - PAGE_SHIFT);
if (mtrr_tom2)
extra_remove_size = extra_remove_size =
(mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base; (mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base;
}
nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base, nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base,
extra_remove_size); extra_remove_size);
/*
* [0, 1M) should always be coverred by var mtrr with WB
* and fixed mtrrs should take effective before var mtrr for it
*/
nr_range = add_range_with_merge(range, nr_range, 0,
(1ULL<<(20 - PAGE_SHIFT)) - 1);
/* sort the ranges */
sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
range_sums = sum_ranges(range, nr_range); range_sums = sum_ranges(range, nr_range);
printk(KERN_INFO "total RAM coverred: %ldM\n", printk(KERN_INFO "total RAM coverred: %ldM\n",
range_sums >> (20 - PAGE_SHIFT)); range_sums >> (20 - PAGE_SHIFT));
if (mtrr_chunk_size && mtrr_gran_size) { if (mtrr_chunk_size && mtrr_gran_size) {
int num_reg; int num_reg;
char gran_factor, chunk_factor, lose_factor;
unsigned long gran_base, chunk_base, lose_base;
debug_print = 1; debug_print++;
/* convert ranges to var ranges state */ /* convert ranges to var ranges state */
num_reg = x86_setup_var_mtrrs(range, nr_range, mtrr_chunk_size, num_reg = x86_setup_var_mtrrs(range, nr_range, mtrr_chunk_size,
mtrr_gran_size); mtrr_gran_size);
@@ -1256,34 +1337,48 @@ static int __init mtrr_cleanup(unsigned address_bits)
result[i].lose_cover_sizek = result[i].lose_cover_sizek =
(range_sums - range_sums_new) << PSHIFT; (range_sums - range_sums_new) << PSHIFT;
printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", gran_base = to_size_factor(result[i].gran_sizek, &gran_factor),
result[i].bad?"*BAD*":" ", result[i].gran_sizek >> 10, chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor),
result[i].chunk_sizek >> 10); lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor),
printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ldM \n", printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t",
result[i].bad?"*BAD*":" ",
gran_base, gran_factor, chunk_base, chunk_factor);
printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n",
result[i].num_reg, result[i].bad?"-":"", result[i].num_reg, result[i].bad?"-":"",
result[i].lose_cover_sizek >> 10); lose_base, lose_factor);
if (!result[i].bad) { if (!result[i].bad) {
set_var_mtrr_all(address_bits); set_var_mtrr_all(address_bits);
return 1; return 1;
} }
printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, " printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, "
"will find optimal one\n"); "will find optimal one\n");
debug_print = 0; debug_print--;
memset(result, 0, sizeof(result[0])); memset(result, 0, sizeof(result[0]));
} }
i = 0; i = 0;
memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn)); memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn));
memset(result, 0, sizeof(result)); memset(result, 0, sizeof(result));
for (gran_size = (1ULL<<20); gran_size < (1ULL<<32); gran_size <<= 1) { for (gran_size = (1ULL<<16); gran_size < (1ULL<<32); gran_size <<= 1) {
for (chunk_size = gran_size; chunk_size < (1ULL<<33); char gran_factor;
unsigned long gran_base;
if (debug_print)
gran_base = to_size_factor(gran_size >> 10, &gran_factor);
for (chunk_size = gran_size; chunk_size < (1ULL<<32);
chunk_size <<= 1) { chunk_size <<= 1) {
int num_reg; int num_reg;
if (debug_print) if (debug_print) {
printk(KERN_INFO char chunk_factor;
"\ngran_size: %lldM chunk_size_size: %lldM\n", unsigned long chunk_base;
gran_size >> 20, chunk_size >> 20);
chunk_base = to_size_factor(chunk_size>>10, &chunk_factor),
printk(KERN_INFO "\n");
printk(KERN_INFO "gran_size: %ld%c chunk_size: %ld%c \n",
gran_base, gran_factor, chunk_base, chunk_factor);
}
if (i >= NUM_RESULT) if (i >= NUM_RESULT)
continue; continue;
@@ -1326,12 +1421,18 @@ static int __init mtrr_cleanup(unsigned address_bits)
/* print out all */ /* print out all */
for (i = 0; i < NUM_RESULT; i++) { for (i = 0; i < NUM_RESULT; i++) {
printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", char gran_factor, chunk_factor, lose_factor;
result[i].bad?"*BAD* ":" ", result[i].gran_sizek >> 10, unsigned long gran_base, chunk_base, lose_base;
result[i].chunk_sizek >> 10);
printk(KERN_CONT "num_reg: %d \tlose RAM: %s%ldM\n", gran_base = to_size_factor(result[i].gran_sizek, &gran_factor),
chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor),
lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor),
printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t",
result[i].bad?"*BAD*":" ",
gran_base, gran_factor, chunk_base, chunk_factor);
printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n",
result[i].num_reg, result[i].bad?"-":"", result[i].num_reg, result[i].bad?"-":"",
result[i].lose_cover_sizek >> 10); lose_base, lose_factor);
} }
/* try to find the optimal index */ /* try to find the optimal index */
@@ -1339,10 +1440,8 @@ static int __init mtrr_cleanup(unsigned address_bits)
nr_mtrr_spare_reg = num_var_ranges - 1; nr_mtrr_spare_reg = num_var_ranges - 1;
num_reg_good = -1; num_reg_good = -1;
for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) { for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) {
if (!min_loss_pfn[i]) { if (!min_loss_pfn[i])
num_reg_good = i; num_reg_good = i;
break;
}
} }
index_good = -1; index_good = -1;
@@ -1358,21 +1457,26 @@ static int __init mtrr_cleanup(unsigned address_bits)
} }
if (index_good != -1) { if (index_good != -1) {
char gran_factor, chunk_factor, lose_factor;
unsigned long gran_base, chunk_base, lose_base;
printk(KERN_INFO "Found optimal setting for mtrr clean up\n"); printk(KERN_INFO "Found optimal setting for mtrr clean up\n");
i = index_good; i = index_good;
printk(KERN_INFO "gran_size: %ldM \tchunk_size: %ldM \t", gran_base = to_size_factor(result[i].gran_sizek, &gran_factor),
result[i].gran_sizek >> 10, chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor),
result[i].chunk_sizek >> 10); lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor),
printk(KERN_CONT "num_reg: %d \tlose RAM: %ldM\n", printk(KERN_INFO "gran_size: %ld%c \tchunk_size: %ld%c \t",
result[i].num_reg, gran_base, gran_factor, chunk_base, chunk_factor);
result[i].lose_cover_sizek >> 10); printk(KERN_CONT "num_reg: %d \tlose RAM: %ld%c\n",
result[i].num_reg, lose_base, lose_factor);
/* convert ranges to var ranges state */ /* convert ranges to var ranges state */
chunk_size = result[i].chunk_sizek; chunk_size = result[i].chunk_sizek;
chunk_size <<= 10; chunk_size <<= 10;
gran_size = result[i].gran_sizek; gran_size = result[i].gran_sizek;
gran_size <<= 10; gran_size <<= 10;
debug_print = 1; debug_print++;
x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size); x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size);
debug_print--;
set_var_mtrr_all(address_bits); set_var_mtrr_all(address_bits);
return 1; return 1;
} }

View File

@@ -295,13 +295,19 @@ static int setup_k7_watchdog(unsigned nmi_hz)
/* setup the timer */ /* setup the timer */
wrmsr(evntsel_msr, evntsel, 0); wrmsr(evntsel_msr, evntsel, 0);
write_watchdog_counter(perfctr_msr, "K7_PERFCTR0",nmi_hz); write_watchdog_counter(perfctr_msr, "K7_PERFCTR0",nmi_hz);
/* initialize the wd struct before enabling */
wd->perfctr_msr = perfctr_msr;
wd->evntsel_msr = evntsel_msr;
wd->cccr_msr = 0; /* unused */
/* ok, everything is initialized, announce that we're set */
cpu_nmi_set_wd_enabled();
apic_write(APIC_LVTPC, APIC_DM_NMI); apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE; evntsel |= K7_EVNTSEL_ENABLE;
wrmsr(evntsel_msr, evntsel, 0); wrmsr(evntsel_msr, evntsel, 0);
wd->perfctr_msr = perfctr_msr;
wd->evntsel_msr = evntsel_msr;
wd->cccr_msr = 0; /* unused */
return 1; return 1;
} }
@@ -379,13 +385,19 @@ static int setup_p6_watchdog(unsigned nmi_hz)
wrmsr(evntsel_msr, evntsel, 0); wrmsr(evntsel_msr, evntsel, 0);
nmi_hz = adjust_for_32bit_ctr(nmi_hz); nmi_hz = adjust_for_32bit_ctr(nmi_hz);
write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0",nmi_hz); write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0",nmi_hz);
/* initialize the wd struct before enabling */
wd->perfctr_msr = perfctr_msr;
wd->evntsel_msr = evntsel_msr;
wd->cccr_msr = 0; /* unused */
/* ok, everything is initialized, announce that we're set */
cpu_nmi_set_wd_enabled();
apic_write(APIC_LVTPC, APIC_DM_NMI); apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= P6_EVNTSEL0_ENABLE; evntsel |= P6_EVNTSEL0_ENABLE;
wrmsr(evntsel_msr, evntsel, 0); wrmsr(evntsel_msr, evntsel, 0);
wd->perfctr_msr = perfctr_msr;
wd->evntsel_msr = evntsel_msr;
wd->cccr_msr = 0; /* unused */
return 1; return 1;
} }
@@ -432,6 +444,27 @@ static const struct wd_ops p6_wd_ops = {
#define P4_CCCR_ENABLE (1 << 12) #define P4_CCCR_ENABLE (1 << 12)
#define P4_CCCR_OVF (1 << 31) #define P4_CCCR_OVF (1 << 31)
#define P4_CONTROLS 18
static unsigned int p4_controls[18] = {
MSR_P4_BPU_CCCR0,
MSR_P4_BPU_CCCR1,
MSR_P4_BPU_CCCR2,
MSR_P4_BPU_CCCR3,
MSR_P4_MS_CCCR0,
MSR_P4_MS_CCCR1,
MSR_P4_MS_CCCR2,
MSR_P4_MS_CCCR3,
MSR_P4_FLAME_CCCR0,
MSR_P4_FLAME_CCCR1,
MSR_P4_FLAME_CCCR2,
MSR_P4_FLAME_CCCR3,
MSR_P4_IQ_CCCR0,
MSR_P4_IQ_CCCR1,
MSR_P4_IQ_CCCR2,
MSR_P4_IQ_CCCR3,
MSR_P4_IQ_CCCR4,
MSR_P4_IQ_CCCR5,
};
/* /*
* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
* CRU_ESCR0 (with any non-null event selector) through a complemented * CRU_ESCR0 (with any non-null event selector) through a complemented
@@ -473,6 +506,26 @@ static int setup_p4_watchdog(unsigned nmi_hz)
evntsel_msr = MSR_P4_CRU_ESCR0; evntsel_msr = MSR_P4_CRU_ESCR0;
cccr_msr = MSR_P4_IQ_CCCR0; cccr_msr = MSR_P4_IQ_CCCR0;
cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4); cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
/*
* If we're on the kdump kernel or other situation, we may
* still have other performance counter registers set to
* interrupt and they'll keep interrupting forever because
* of the P4_CCCR_OVF quirk. So we need to ACK all the
* pending interrupts and disable all the registers here,
* before reenabling the NMI delivery. Refer to p4_rearm()
* about the P4_CCCR_OVF quirk.
*/
if (reset_devices) {
unsigned int low, high;
int i;
for (i = 0; i < P4_CONTROLS; i++) {
rdmsr(p4_controls[i], low, high);
low &= ~(P4_CCCR_ENABLE | P4_CCCR_OVF);
wrmsr(p4_controls[i], low, high);
}
}
} else { } else {
/* logical cpu 1 */ /* logical cpu 1 */
perfctr_msr = MSR_P4_IQ_PERFCTR1; perfctr_msr = MSR_P4_IQ_PERFCTR1;
@@ -499,12 +552,17 @@ static int setup_p4_watchdog(unsigned nmi_hz)
wrmsr(evntsel_msr, evntsel, 0); wrmsr(evntsel_msr, evntsel, 0);
wrmsr(cccr_msr, cccr_val, 0); wrmsr(cccr_msr, cccr_val, 0);
write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0", nmi_hz); write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0", nmi_hz);
apic_write(APIC_LVTPC, APIC_DM_NMI);
cccr_val |= P4_CCCR_ENABLE;
wrmsr(cccr_msr, cccr_val, 0);
wd->perfctr_msr = perfctr_msr; wd->perfctr_msr = perfctr_msr;
wd->evntsel_msr = evntsel_msr; wd->evntsel_msr = evntsel_msr;
wd->cccr_msr = cccr_msr; wd->cccr_msr = cccr_msr;
/* ok, everything is initialized, announce that we're set */
cpu_nmi_set_wd_enabled();
apic_write(APIC_LVTPC, APIC_DM_NMI);
cccr_val |= P4_CCCR_ENABLE;
wrmsr(cccr_msr, cccr_val, 0);
return 1; return 1;
} }
@@ -620,13 +678,17 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz)
wrmsr(evntsel_msr, evntsel, 0); wrmsr(evntsel_msr, evntsel, 0);
nmi_hz = adjust_for_32bit_ctr(nmi_hz); nmi_hz = adjust_for_32bit_ctr(nmi_hz);
write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0", nmi_hz); write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0", nmi_hz);
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
wrmsr(evntsel_msr, evntsel, 0);
wd->perfctr_msr = perfctr_msr; wd->perfctr_msr = perfctr_msr;
wd->evntsel_msr = evntsel_msr; wd->evntsel_msr = evntsel_msr;
wd->cccr_msr = 0; /* unused */ wd->cccr_msr = 0; /* unused */
/* ok, everything is initialized, announce that we're set */
cpu_nmi_set_wd_enabled();
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
wrmsr(evntsel_msr, evntsel, 0);
intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1); intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1);
return 1; return 1;
} }

View File

@@ -36,7 +36,6 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/smp_lock.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>

View File

@@ -7,9 +7,8 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h> #include <linux/io.h>
#include <asm/io.h>
/** /**
* copy_oldmem_page - copy one page from "oldmem" * copy_oldmem_page - copy one page from "oldmem"
@@ -33,14 +32,16 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
return 0; return 0;
vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
if (!vaddr)
return -ENOMEM;
if (userbuf) { if (userbuf) {
if (copy_to_user(buf, (vaddr + offset), csize)) { if (copy_to_user(buf, vaddr + offset, csize)) {
iounmap(vaddr); iounmap(vaddr);
return -EFAULT; return -EFAULT;
} }
} else } else
memcpy(buf, (vaddr + offset), csize); memcpy(buf, vaddr + offset, csize);
iounmap(vaddr); iounmap(vaddr);
return csize; return csize;

File diff suppressed because it is too large Load Diff

View File

@@ -414,9 +414,11 @@ void __init efi_init(void)
if (memmap.map == NULL) if (memmap.map == NULL)
printk(KERN_ERR "Could not map the EFI memory map!\n"); printk(KERN_ERR "Could not map the EFI memory map!\n");
memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
if (memmap.desc_size != sizeof(efi_memory_desc_t)) if (memmap.desc_size != sizeof(efi_memory_desc_t))
printk(KERN_WARNING "Kernel-defined memdesc" printk(KERN_WARNING
"doesn't match the one from EFI!\n"); "Kernel-defined memdesc doesn't match the one from EFI!\n");
if (add_efi_memmap) if (add_efi_memmap)
do_add_efi_memmap(); do_add_efi_memmap();

View File

@@ -275,9 +275,9 @@ ENTRY(native_usergs_sysret64)
ENTRY(ret_from_fork) ENTRY(ret_from_fork)
CFI_DEFAULT_STACK CFI_DEFAULT_STACK
push kernel_eflags(%rip) push kernel_eflags(%rip)
CFI_ADJUST_CFA_OFFSET 4 CFI_ADJUST_CFA_OFFSET 8
popf # reset kernel eflags popf # reset kernel eflags
CFI_ADJUST_CFA_OFFSET -4 CFI_ADJUST_CFA_OFFSET -8
call schedule_tail call schedule_tail
GET_THREAD_INFO(%rcx) GET_THREAD_INFO(%rcx)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx)

View File

@@ -108,12 +108,11 @@ void __init x86_64_start_kernel(char * real_mode_data)
} }
load_idt((const struct desc_ptr *)&idt_descr); load_idt((const struct desc_ptr *)&idt_descr);
if (console_loglevel == 10)
early_printk("Kernel alive\n"); early_printk("Kernel alive\n");
x86_64_init_pda(); x86_64_init_pda();
early_printk("Kernel really alive\n");
x86_64_start_reservations(real_mode_data); x86_64_start_reservations(real_mode_data);
} }

View File

@@ -14,6 +14,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <asm/syscalls.h>
/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
static void set_bitmap(unsigned long *bitmap, unsigned int base, static void set_bitmap(unsigned long *bitmap, unsigned int base,

View File

@@ -20,6 +20,8 @@
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
#include <mach_apic.h> #include <mach_apic.h>
#include <mach_ipi.h>
/* /*
* the following functions deal with sending IPIs between CPUs. * the following functions deal with sending IPIs between CPUs.
* *
@@ -147,7 +149,6 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector)
} }
/* must come after the send_IPI functions above for inlining */ /* must come after the send_IPI functions above for inlining */
#include <mach_ipi.h>
static int convert_apicid_to_cpu(int apic_id) static int convert_apicid_to_cpu(int apic_id)
{ {
int i; int i;

View File

@@ -325,7 +325,7 @@ skip:
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", seq_printf(p, "%10u ",
per_cpu(irq_stat,j).irq_call_count); per_cpu(irq_stat,j).irq_call_count);
seq_printf(p, " function call interrupts\n"); seq_printf(p, " Function call interrupts\n");
seq_printf(p, "TLB: "); seq_printf(p, "TLB: ");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", seq_printf(p, "%10u ",

View File

@@ -129,7 +129,7 @@ skip:
seq_printf(p, "CAL: "); seq_printf(p, "CAL: ");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count); seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count);
seq_printf(p, " function call interrupts\n"); seq_printf(p, " Function call interrupts\n");
seq_printf(p, "TLB: "); seq_printf(p, "TLB: ");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count); seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count);

View File

@@ -178,7 +178,7 @@ static void kvm_flush_tlb(void)
kvm_deferred_mmu_op(&ftlb, sizeof ftlb); kvm_deferred_mmu_op(&ftlb, sizeof ftlb);
} }
static void kvm_release_pt(u32 pfn) static void kvm_release_pt(unsigned long pfn)
{ {
struct kvm_mmu_op_release_pt rpt = { struct kvm_mmu_op_release_pt rpt = {
.header.op = KVM_MMU_OP_RELEASE_PT, .header.op = KVM_MMU_OP_RELEASE_PT,

View File

@@ -18,6 +18,7 @@
#include <asm/ldt.h> #include <asm/ldt.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/syscalls.h>
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void flush_ldt(void *current_mm) static void flush_ldt(void *current_mm)

View File

@@ -299,6 +299,15 @@ void acpi_nmi_disable(void)
on_each_cpu(__acpi_nmi_disable, NULL, 1); on_each_cpu(__acpi_nmi_disable, NULL, 1);
} }
/*
* This function is called as soon the LAPIC NMI watchdog driver has everything
* in place and it's ready to check if the NMIs belong to the NMI watchdog
*/
void cpu_nmi_set_wd_enabled(void)
{
__get_cpu_var(wd_enabled) = 1;
}
void setup_apic_nmi_watchdog(void *unused) void setup_apic_nmi_watchdog(void *unused)
{ {
if (__get_cpu_var(wd_enabled)) if (__get_cpu_var(wd_enabled))
@@ -311,8 +320,6 @@ void setup_apic_nmi_watchdog(void *unused)
switch (nmi_watchdog) { switch (nmi_watchdog) {
case NMI_LOCAL_APIC: case NMI_LOCAL_APIC:
/* enable it before to avoid race with handler */
__get_cpu_var(wd_enabled) = 1;
if (lapic_watchdog_init(nmi_hz) < 0) { if (lapic_watchdog_init(nmi_hz) < 0) {
__get_cpu_var(wd_enabled) = 0; __get_cpu_var(wd_enabled) = 0;
return; return;

View File

@@ -190,12 +190,12 @@ EXPORT_SYMBOL_GPL(olpc_ec_cmd);
static void __init platform_detect(void) static void __init platform_detect(void)
{ {
size_t propsize; size_t propsize;
u32 rev; __be32 rev;
if (ofw("getprop", 4, 1, NULL, "board-revision-int", &rev, 4, if (ofw("getprop", 4, 1, NULL, "board-revision-int", &rev, 4,
&propsize) || propsize != 4) { &propsize) || propsize != 4) {
printk(KERN_ERR "ofw: getprop call failed!\n"); printk(KERN_ERR "ofw: getprop call failed!\n");
rev = 0; rev = cpu_to_be32(0);
} }
olpc_platform_info.boardrev = be32_to_cpu(rev); olpc_platform_info.boardrev = be32_to_cpu(rev);
} }
@@ -203,7 +203,7 @@ static void __init platform_detect(void)
static void __init platform_detect(void) static void __init platform_detect(void)
{ {
/* stopgap until OFW support is added to the kernel */ /* stopgap until OFW support is added to the kernel */
olpc_platform_info.boardrev = be32_to_cpu(0xc2); olpc_platform_info.boardrev = 0xc2;
} }
#endif #endif

View File

@@ -330,6 +330,7 @@ struct pv_cpu_ops pv_cpu_ops = {
#endif #endif
.wbinvd = native_wbinvd, .wbinvd = native_wbinvd,
.read_msr = native_read_msr_safe, .read_msr = native_read_msr_safe,
.read_msr_amd = native_read_msr_amd_safe,
.write_msr = native_write_msr_safe, .write_msr = native_write_msr_safe,
.read_tsc = native_read_tsc, .read_tsc = native_read_tsc,
.read_pmc = native_read_pmc, .read_pmc = native_read_pmc,

View File

@@ -82,7 +82,7 @@ void __init dma32_reserve_bootmem(void)
* using 512M as goal * using 512M as goal
*/ */
align = 64ULL<<20; align = 64ULL<<20;
size = round_up(dma32_bootmem_size, align); size = roundup(dma32_bootmem_size, align);
dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align, dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
512ULL<<20); 512ULL<<20);
if (dma32_bootmem_ptr) if (dma32_bootmem_ptr)

View File

@@ -82,7 +82,8 @@ AGPEXTERN __u32 *agp_gatt_table;
static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static unsigned long next_bit; /* protected by iommu_bitmap_lock */
static int need_flush; /* global flush state. set for each gart wrap */ static int need_flush; /* global flush state. set for each gart wrap */
static unsigned long alloc_iommu(struct device *dev, int size) static unsigned long alloc_iommu(struct device *dev, int size,
unsigned long align_mask)
{ {
unsigned long offset, flags; unsigned long offset, flags;
unsigned long boundary_size; unsigned long boundary_size;
@@ -90,16 +91,17 @@ static unsigned long alloc_iommu(struct device *dev, int size)
base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
PAGE_SIZE) >> PAGE_SHIFT; PAGE_SIZE) >> PAGE_SHIFT;
boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1,
PAGE_SIZE) >> PAGE_SHIFT; PAGE_SIZE) >> PAGE_SHIFT;
spin_lock_irqsave(&iommu_bitmap_lock, flags); spin_lock_irqsave(&iommu_bitmap_lock, flags);
offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit,
size, base_index, boundary_size, 0); size, base_index, boundary_size, align_mask);
if (offset == -1) { if (offset == -1) {
need_flush = 1; need_flush = 1;
offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0,
size, base_index, boundary_size, 0); size, base_index, boundary_size,
align_mask);
} }
if (offset != -1) { if (offset != -1) {
next_bit = offset+size; next_bit = offset+size;
@@ -236,10 +238,10 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
* Caller needs to check if the iommu is needed and flush. * Caller needs to check if the iommu is needed and flush.
*/ */
static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
size_t size, int dir) size_t size, int dir, unsigned long align_mask)
{ {
unsigned long npages = iommu_num_pages(phys_mem, size); unsigned long npages = iommu_num_pages(phys_mem, size);
unsigned long iommu_page = alloc_iommu(dev, npages); unsigned long iommu_page = alloc_iommu(dev, npages, align_mask);
int i; int i;
if (iommu_page == -1) { if (iommu_page == -1) {
@@ -262,7 +264,11 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
static dma_addr_t static dma_addr_t
gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir) gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir)
{ {
dma_addr_t map = dma_map_area(dev, paddr, size, dir); dma_addr_t map;
unsigned long align_mask;
align_mask = (1UL << get_order(size)) - 1;
map = dma_map_area(dev, paddr, size, dir, align_mask);
flush_gart(); flush_gart();
@@ -281,7 +287,8 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir)
if (!need_iommu(dev, paddr, size)) if (!need_iommu(dev, paddr, size))
return paddr; return paddr;
bus = gart_map_simple(dev, paddr, size, dir); bus = dma_map_area(dev, paddr, size, dir, 0);
flush_gart();
return bus; return bus;
} }
@@ -340,7 +347,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
unsigned long addr = sg_phys(s); unsigned long addr = sg_phys(s);
if (nonforced_iommu(dev, addr, s->length)) { if (nonforced_iommu(dev, addr, s->length)) {
addr = dma_map_area(dev, addr, s->length, dir); addr = dma_map_area(dev, addr, s->length, dir, 0);
if (addr == bad_dma_address) { if (addr == bad_dma_address) {
if (i > 0) if (i > 0)
gart_unmap_sg(dev, sg, i, dir); gart_unmap_sg(dev, sg, i, dir);
@@ -362,7 +369,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
int nelems, struct scatterlist *sout, int nelems, struct scatterlist *sout,
unsigned long pages) unsigned long pages)
{ {
unsigned long iommu_start = alloc_iommu(dev, pages); unsigned long iommu_start = alloc_iommu(dev, pages, 0);
unsigned long iommu_page = iommu_start; unsigned long iommu_page = iommu_start;
struct scatterlist *s; struct scatterlist *s;
int i; int i;

View File

@@ -1,20 +1,13 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/errno.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
static __init int add_pcspkr(void) static __init int add_pcspkr(void)
{ {
struct platform_device *pd; struct platform_device *pd;
int ret;
pd = platform_device_alloc("pcspkr", -1); pd = platform_device_register_simple("pcspkr", -1, NULL, 0);
if (!pd)
return -ENOMEM;
ret = platform_device_add(pd); return IS_ERR(pd) ? PTR_ERR(pd) : 0;
if (ret)
platform_device_put(pd);
return ret;
} }
device_initcall(add_pcspkr); device_initcall(add_pcspkr);

View File

@@ -185,6 +185,7 @@ static void mwait_idle(void)
static void poll_idle(void) static void poll_idle(void)
{ {
local_irq_enable(); local_irq_enable();
while (!need_resched())
cpu_relax(); cpu_relax();
} }

View File

@@ -37,6 +37,7 @@
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/prctl.h> #include <linux/prctl.h>
#include <linux/dmi.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
@@ -56,6 +57,8 @@
#include <asm/cpu.h> #include <asm/cpu.h>
#include <asm/kdebug.h> #include <asm/kdebug.h>
#include <asm/idle.h> #include <asm/idle.h>
#include <asm/syscalls.h>
#include <asm/smp.h>
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
@@ -161,6 +164,7 @@ void __show_registers(struct pt_regs *regs, int all)
unsigned long d0, d1, d2, d3, d6, d7; unsigned long d0, d1, d2, d3, d6, d7;
unsigned long sp; unsigned long sp;
unsigned short ss, gs; unsigned short ss, gs;
const char *board;
if (user_mode_vm(regs)) { if (user_mode_vm(regs)) {
sp = regs->sp; sp = regs->sp;
@@ -173,11 +177,15 @@ void __show_registers(struct pt_regs *regs, int all)
} }
printk("\n"); printk("\n");
printk("Pid: %d, comm: %s %s (%s %.*s)\n",
board = dmi_get_system_info(DMI_PRODUCT_NAME);
if (!board)
board = "";
printk("Pid: %d, comm: %s %s (%s %.*s) %s\n",
task_pid_nr(current), current->comm, task_pid_nr(current), current->comm,
print_tainted(), init_utsname()->release, print_tainted(), init_utsname()->release,
(int)strcspn(init_utsname()->version, " "), (int)strcspn(init_utsname()->version, " "),
init_utsname()->version); init_utsname()->version, board);
printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
(u16)regs->cs, regs->ip, regs->flags, (u16)regs->cs, regs->ip, regs->flags,
@@ -277,6 +285,14 @@ void exit_thread(void)
tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
put_cpu(); put_cpu();
} }
#ifdef CONFIG_X86_DS
/* Free any DS contexts that have not been properly released. */
if (unlikely(current->thread.ds_ctx)) {
/* we clear debugctl to make sure DS is not used. */
update_debugctlmsr(0);
ds_free(current->thread.ds_ctx);
}
#endif /* CONFIG_X86_DS */
} }
void flush_thread(void) void flush_thread(void)
@@ -438,6 +454,35 @@ int set_tsc_mode(unsigned int val)
return 0; return 0;
} }
#ifdef CONFIG_X86_DS
static int update_debugctl(struct thread_struct *prev,
struct thread_struct *next, unsigned long debugctl)
{
unsigned long ds_prev = 0;
unsigned long ds_next = 0;
if (prev->ds_ctx)
ds_prev = (unsigned long)prev->ds_ctx->ds;
if (next->ds_ctx)
ds_next = (unsigned long)next->ds_ctx->ds;
if (ds_next != ds_prev) {
/* we clear debugctl to make sure DS
* is not in use when we change it */
debugctl = 0;
update_debugctlmsr(0);
wrmsr(MSR_IA32_DS_AREA, ds_next, 0);
}
return debugctl;
}
#else
static int update_debugctl(struct thread_struct *prev,
struct thread_struct *next, unsigned long debugctl)
{
return debugctl;
}
#endif /* CONFIG_X86_DS */
static noinline void static noinline void
__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
struct tss_struct *tss) struct tss_struct *tss)
@@ -448,14 +493,7 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
prev = &prev_p->thread; prev = &prev_p->thread;
next = &next_p->thread; next = &next_p->thread;
debugctl = prev->debugctlmsr; debugctl = update_debugctl(prev, next, prev->debugctlmsr);
if (next->ds_area_msr != prev->ds_area_msr) {
/* we clear debugctl to make sure DS
* is not in use when we change it */
debugctl = 0;
update_debugctlmsr(0);
wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
}
if (next->debugctlmsr != debugctl) if (next->debugctlmsr != debugctl)
update_debugctlmsr(next->debugctlmsr); update_debugctlmsr(next->debugctlmsr);
@@ -479,13 +517,13 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
hard_enable_TSC(); hard_enable_TSC();
} }
#ifdef X86_BTS #ifdef CONFIG_X86_PTRACE_BTS
if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
#endif #endif /* CONFIG_X86_PTRACE_BTS */
if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {

View File

@@ -37,11 +37,11 @@
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/prctl.h> #include <linux/prctl.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
@@ -51,6 +51,7 @@
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/ia32.h> #include <asm/ia32.h>
#include <asm/idle.h> #include <asm/idle.h>
#include <asm/syscalls.h>
asmlinkage extern void ret_from_fork(void); asmlinkage extern void ret_from_fork(void);
@@ -88,7 +89,7 @@ void exit_idle(void)
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
DECLARE_PER_CPU(int, cpu_state); DECLARE_PER_CPU(int, cpu_state);
#include <asm/nmi.h> #include <linux/nmi.h>
/* We halt the CPU with physical CPU hotplug */ /* We halt the CPU with physical CPU hotplug */
static inline void play_dead(void) static inline void play_dead(void)
{ {
@@ -162,24 +163,24 @@ void __show_regs(struct pt_regs * regs)
printk("\n"); printk("\n");
print_modules(); print_modules();
printk("Pid: %d, comm: %.20s %s %s %.*s\n", printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n",
current->pid, current->comm, print_tainted(), current->pid, current->comm, print_tainted(),
init_utsname()->release, init_utsname()->release,
(int)strcspn(init_utsname()->version, " "), (int)strcspn(init_utsname()->version, " "),
init_utsname()->version); init_utsname()->version);
printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
printk_address(regs->ip, 1); printk_address(regs->ip, 1);
printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->sp, printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss,
regs->flags); regs->sp, regs->flags);
printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
regs->ax, regs->bx, regs->cx); regs->ax, regs->bx, regs->cx);
printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
regs->dx, regs->si, regs->di); regs->dx, regs->si, regs->di);
printk("RBP: %016lx R08: %016lx R09: %016lx\n", printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
regs->bp, regs->r8, regs->r9); regs->bp, regs->r8, regs->r9);
printk("R10: %016lx R11: %016lx R12: %016lx\n", printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
regs->r10, regs->r11, regs->r12); regs->r10, regs->r11, regs->r12);
printk("R13: %016lx R14: %016lx R15: %016lx\n", printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
regs->r13, regs->r14, regs->r15); regs->r13, regs->r14, regs->r15);
asm("movl %%ds,%0" : "=r" (ds)); asm("movl %%ds,%0" : "=r" (ds));
@@ -197,24 +198,26 @@ void __show_regs(struct pt_regs * regs)
cr3 = read_cr3(); cr3 = read_cr3();
cr4 = read_cr4(); cr4 = read_cr4();
printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", printk(KERN_INFO "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
fs, fsindex, gs, gsindex, shadowgs); fs, fsindex, gs, gsindex, shadowgs);
printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); printk(KERN_INFO "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); es, cr0);
printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
cr4);
get_debugreg(d0, 0); get_debugreg(d0, 0);
get_debugreg(d1, 1); get_debugreg(d1, 1);
get_debugreg(d2, 2); get_debugreg(d2, 2);
printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
get_debugreg(d3, 3); get_debugreg(d3, 3);
get_debugreg(d6, 6); get_debugreg(d6, 6);
get_debugreg(d7, 7); get_debugreg(d7, 7);
printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
} }
void show_regs(struct pt_regs *regs) void show_regs(struct pt_regs *regs)
{ {
printk("CPU %d:", smp_processor_id()); printk(KERN_INFO "CPU %d:", smp_processor_id());
__show_regs(regs); __show_regs(regs);
show_trace(NULL, regs, (void *)(regs + 1), regs->bp); show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
} }
@@ -240,6 +243,14 @@ void exit_thread(void)
t->io_bitmap_max = 0; t->io_bitmap_max = 0;
put_cpu(); put_cpu();
} }
#ifdef CONFIG_X86_DS
/* Free any DS contexts that have not been properly released. */
if (unlikely(t->ds_ctx)) {
/* we clear debugctl to make sure DS is not used. */
update_debugctlmsr(0);
ds_free(t->ds_ctx);
}
#endif /* CONFIG_X86_DS */
} }
void flush_thread(void) void flush_thread(void)
@@ -473,13 +484,27 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
next = &next_p->thread; next = &next_p->thread;
debugctl = prev->debugctlmsr; debugctl = prev->debugctlmsr;
if (next->ds_area_msr != prev->ds_area_msr) {
/* we clear debugctl to make sure DS #ifdef CONFIG_X86_DS
* is not in use when we change it */ {
unsigned long ds_prev = 0, ds_next = 0;
if (prev->ds_ctx)
ds_prev = (unsigned long)prev->ds_ctx->ds;
if (next->ds_ctx)
ds_next = (unsigned long)next->ds_ctx->ds;
if (ds_next != ds_prev) {
/*
* We clear debugctl to make sure DS
* is not in use when we change it:
*/
debugctl = 0; debugctl = 0;
update_debugctlmsr(0); update_debugctlmsr(0);
wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr); wrmsrl(MSR_IA32_DS_AREA, ds_next);
} }
}
#endif /* CONFIG_X86_DS */
if (next->debugctlmsr != debugctl) if (next->debugctlmsr != debugctl)
update_debugctlmsr(next->debugctlmsr); update_debugctlmsr(next->debugctlmsr);
@@ -517,13 +542,13 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
} }
#ifdef X86_BTS #ifdef CONFIG_X86_PTRACE_BTS
if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
#endif #endif /* CONFIG_X86_PTRACE_BTS */
} }
/* /*
@@ -825,8 +850,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
rdmsrl(MSR_KERNEL_GS_BASE, base); rdmsrl(MSR_KERNEL_GS_BASE, base);
else else
base = task->thread.gs; base = task->thread.gs;
} } else
else
base = task->thread.gs; base = task->thread.gs;
ret = put_user(base, (unsigned long __user *)addr); ret = put_user(base, (unsigned long __user *)addr);
break; break;

View File

@@ -14,6 +14,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/regset.h> #include <linux/regset.h>
#include <linux/tracehook.h>
#include <linux/user.h> #include <linux/user.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/security.h> #include <linux/security.h>
@@ -69,7 +70,7 @@ static inline bool invalid_selector(u16 value)
#define FLAG_MASK FLAG_MASK_32 #define FLAG_MASK FLAG_MASK_32
static long *pt_regs_access(struct pt_regs *regs, unsigned long regno) static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno)
{ {
BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0);
regno >>= 2; regno >>= 2;
@@ -554,45 +555,115 @@ static int ptrace_set_debugreg(struct task_struct *child,
return 0; return 0;
} }
#ifdef X86_BTS #ifdef CONFIG_X86_PTRACE_BTS
/*
* The configuration for a particular BTS hardware implementation.
*/
struct bts_configuration {
/* the size of a BTS record in bytes; at most BTS_MAX_RECORD_SIZE */
unsigned char sizeof_bts;
/* the size of a field in the BTS record in bytes */
unsigned char sizeof_field;
/* a bitmask to enable/disable BTS in DEBUGCTL MSR */
unsigned long debugctl_mask;
};
static struct bts_configuration bts_cfg;
static int ptrace_bts_get_size(struct task_struct *child) #define BTS_MAX_RECORD_SIZE (8 * 3)
/*
* Branch Trace Store (BTS) uses the following format. Different
* architectures vary in the size of those fields.
* - source linear address
* - destination linear address
* - flags
*
* Later architectures use 64bit pointers throughout, whereas earlier
* architectures use 32bit pointers in 32bit mode.
*
* We compute the base address for the first 8 fields based on:
* - the field size stored in the DS configuration
* - the relative field position
*
* In order to store additional information in the BTS buffer, we use
* a special source address to indicate that the record requires
* special interpretation.
*
* Netburst indicated via a bit in the flags field whether the branch
* was predicted; this is ignored.
*/
enum bts_field {
bts_from = 0,
bts_to,
bts_flags,
bts_escape = (unsigned long)-1,
bts_qual = bts_to,
bts_jiffies = bts_flags
};
static inline unsigned long bts_get(const char *base, enum bts_field field)
{ {
if (!child->thread.ds_area_msr) base += (bts_cfg.sizeof_field * field);
return -ENXIO; return *(unsigned long *)base;
return ds_get_bts_index((void *)child->thread.ds_area_msr);
} }
static int ptrace_bts_read_record(struct task_struct *child, static inline void bts_set(char *base, enum bts_field field, unsigned long val)
long index, {
base += (bts_cfg.sizeof_field * field);;
(*(unsigned long *)base) = val;
}
/*
* Translate a BTS record from the raw format into the bts_struct format
*
* out (out): bts_struct interpretation
* raw: raw BTS record
*/
static void ptrace_bts_translate_record(struct bts_struct *out, const void *raw)
{
memset(out, 0, sizeof(*out));
if (bts_get(raw, bts_from) == bts_escape) {
out->qualifier = bts_get(raw, bts_qual);
out->variant.jiffies = bts_get(raw, bts_jiffies);
} else {
out->qualifier = BTS_BRANCH;
out->variant.lbr.from_ip = bts_get(raw, bts_from);
out->variant.lbr.to_ip = bts_get(raw, bts_to);
}
}
static int ptrace_bts_read_record(struct task_struct *child, size_t index,
struct bts_struct __user *out) struct bts_struct __user *out)
{ {
struct bts_struct ret; struct bts_struct ret;
int retval; const void *bts_record;
int bts_end; size_t bts_index, bts_end;
int bts_index; int error;
if (!child->thread.ds_area_msr) error = ds_get_bts_end(child, &bts_end);
return -ENXIO; if (error < 0)
return error;
if (index < 0)
return -EINVAL;
bts_end = ds_get_bts_end((void *)child->thread.ds_area_msr);
if (bts_end <= index) if (bts_end <= index)
return -EINVAL; return -EINVAL;
/* translate the ptrace bts index into the ds bts index */ error = ds_get_bts_index(child, &bts_index);
bts_index = ds_get_bts_index((void *)child->thread.ds_area_msr); if (error < 0)
bts_index -= (index + 1); return error;
if (bts_index < 0)
bts_index += bts_end;
retval = ds_read_bts((void *)child->thread.ds_area_msr, /* translate the ptrace bts index into the ds bts index */
bts_index, &ret); bts_index += bts_end - (index + 1);
if (retval < 0) if (bts_end <= bts_index)
return retval; bts_index -= bts_end;
error = ds_access_bts(child, bts_index, &bts_record);
if (error < 0)
return error;
ptrace_bts_translate_record(&ret, bts_record);
if (copy_to_user(out, &ret, sizeof(ret))) if (copy_to_user(out, &ret, sizeof(ret)))
return -EFAULT; return -EFAULT;
@@ -600,101 +671,106 @@ static int ptrace_bts_read_record(struct task_struct *child,
return sizeof(ret); return sizeof(ret);
} }
static int ptrace_bts_clear(struct task_struct *child)
{
if (!child->thread.ds_area_msr)
return -ENXIO;
return ds_clear((void *)child->thread.ds_area_msr);
}
static int ptrace_bts_drain(struct task_struct *child, static int ptrace_bts_drain(struct task_struct *child,
long size, long size,
struct bts_struct __user *out) struct bts_struct __user *out)
{ {
int end, i; struct bts_struct ret;
void *ds = (void *)child->thread.ds_area_msr; const unsigned char *raw;
size_t end, i;
int error;
if (!ds) error = ds_get_bts_index(child, &end);
return -ENXIO; if (error < 0)
return error;
end = ds_get_bts_index(ds);
if (end <= 0)
return end;
if (size < (end * sizeof(struct bts_struct))) if (size < (end * sizeof(struct bts_struct)))
return -EIO; return -EIO;
for (i = 0; i < end; i++, out++) { error = ds_access_bts(child, 0, (const void **)&raw);
struct bts_struct ret; if (error < 0)
int retval; return error;
retval = ds_read_bts(ds, i, &ret); for (i = 0; i < end; i++, out++, raw += bts_cfg.sizeof_bts) {
if (retval < 0) ptrace_bts_translate_record(&ret, raw);
return retval;
if (copy_to_user(out, &ret, sizeof(ret))) if (copy_to_user(out, &ret, sizeof(ret)))
return -EFAULT; return -EFAULT;
} }
ds_clear(ds); error = ds_clear_bts(child);
if (error < 0)
return error;
return end; return end;
} }
static void ptrace_bts_ovfl(struct task_struct *child)
{
send_sig(child->thread.bts_ovfl_signal, child, 0);
}
static int ptrace_bts_config(struct task_struct *child, static int ptrace_bts_config(struct task_struct *child,
long cfg_size, long cfg_size,
const struct ptrace_bts_config __user *ucfg) const struct ptrace_bts_config __user *ucfg)
{ {
struct ptrace_bts_config cfg; struct ptrace_bts_config cfg;
int bts_size, ret = 0; int error = 0;
void *ds;
if (cfg_size < sizeof(cfg)) error = -EOPNOTSUPP;
return -EIO; if (!bts_cfg.sizeof_bts)
if (copy_from_user(&cfg, ucfg, sizeof(cfg)))
return -EFAULT;
if ((int)cfg.size < 0)
return -EINVAL;
bts_size = 0;
ds = (void *)child->thread.ds_area_msr;
if (ds) {
bts_size = ds_get_bts_size(ds);
if (bts_size < 0)
return bts_size;
}
cfg.size = PAGE_ALIGN(cfg.size);
if (bts_size != cfg.size) {
ret = ptrace_bts_realloc(child, cfg.size,
cfg.flags & PTRACE_BTS_O_CUT_SIZE);
if (ret < 0)
goto errout; goto errout;
ds = (void *)child->thread.ds_area_msr; error = -EIO;
if (cfg_size < sizeof(cfg))
goto errout;
error = -EFAULT;
if (copy_from_user(&cfg, ucfg, sizeof(cfg)))
goto errout;
error = -EINVAL;
if ((cfg.flags & PTRACE_BTS_O_SIGNAL) &&
!(cfg.flags & PTRACE_BTS_O_ALLOC))
goto errout;
if (cfg.flags & PTRACE_BTS_O_ALLOC) {
ds_ovfl_callback_t ovfl = NULL;
unsigned int sig = 0;
/* we ignore the error in case we were not tracing child */
(void)ds_release_bts(child);
if (cfg.flags & PTRACE_BTS_O_SIGNAL) {
if (!cfg.signal)
goto errout;
sig = cfg.signal;
ovfl = ptrace_bts_ovfl;
} }
if (cfg.flags & PTRACE_BTS_O_SIGNAL) error = ds_request_bts(child, /* base = */ NULL, cfg.size, ovfl);
ret = ds_set_overflow(ds, DS_O_SIGNAL); if (error < 0)
else goto errout;
ret = ds_set_overflow(ds, DS_O_WRAP);
if (ret < 0) child->thread.bts_ovfl_signal = sig;
}
error = -EINVAL;
if (!child->thread.ds_ctx && cfg.flags)
goto errout; goto errout;
if (cfg.flags & PTRACE_BTS_O_TRACE) if (cfg.flags & PTRACE_BTS_O_TRACE)
child->thread.debugctlmsr |= ds_debugctl_mask(); child->thread.debugctlmsr |= bts_cfg.debugctl_mask;
else else
child->thread.debugctlmsr &= ~ds_debugctl_mask(); child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask;
if (cfg.flags & PTRACE_BTS_O_SCHED) if (cfg.flags & PTRACE_BTS_O_SCHED)
set_tsk_thread_flag(child, TIF_BTS_TRACE_TS); set_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
else else
clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
ret = sizeof(cfg); error = sizeof(cfg);
out: out:
if (child->thread.debugctlmsr) if (child->thread.debugctlmsr)
@@ -702,10 +778,10 @@ out:
else else
clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
return ret; return error;
errout: errout:
child->thread.debugctlmsr &= ~ds_debugctl_mask(); child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask;
clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
goto out; goto out;
} }
@@ -714,29 +790,40 @@ static int ptrace_bts_status(struct task_struct *child,
long cfg_size, long cfg_size,
struct ptrace_bts_config __user *ucfg) struct ptrace_bts_config __user *ucfg)
{ {
void *ds = (void *)child->thread.ds_area_msr;
struct ptrace_bts_config cfg; struct ptrace_bts_config cfg;
size_t end;
const void *base, *max;
int error;
if (cfg_size < sizeof(cfg)) if (cfg_size < sizeof(cfg))
return -EIO; return -EIO;
error = ds_get_bts_end(child, &end);
if (error < 0)
return error;
error = ds_access_bts(child, /* index = */ 0, &base);
if (error < 0)
return error;
error = ds_access_bts(child, /* index = */ end, &max);
if (error < 0)
return error;
memset(&cfg, 0, sizeof(cfg)); memset(&cfg, 0, sizeof(cfg));
cfg.size = (max - base);
cfg.signal = child->thread.bts_ovfl_signal;
cfg.bts_size = sizeof(struct bts_struct);
if (ds) { if (cfg.signal)
cfg.size = ds_get_bts_size(ds);
if (ds_get_overflow(ds) == DS_O_SIGNAL)
cfg.flags |= PTRACE_BTS_O_SIGNAL; cfg.flags |= PTRACE_BTS_O_SIGNAL;
if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) &&
child->thread.debugctlmsr & ds_debugctl_mask()) child->thread.debugctlmsr & bts_cfg.debugctl_mask)
cfg.flags |= PTRACE_BTS_O_TRACE; cfg.flags |= PTRACE_BTS_O_TRACE;
if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS))
cfg.flags |= PTRACE_BTS_O_SCHED; cfg.flags |= PTRACE_BTS_O_SCHED;
}
cfg.bts_size = sizeof(struct bts_struct);
if (copy_to_user(ucfg, &cfg, sizeof(cfg))) if (copy_to_user(ucfg, &cfg, sizeof(cfg)))
return -EFAULT; return -EFAULT;
@@ -744,89 +831,38 @@ static int ptrace_bts_status(struct task_struct *child,
return sizeof(cfg); return sizeof(cfg);
} }
static int ptrace_bts_write_record(struct task_struct *child, static int ptrace_bts_write_record(struct task_struct *child,
const struct bts_struct *in) const struct bts_struct *in)
{ {
int retval; unsigned char bts_record[BTS_MAX_RECORD_SIZE];
if (!child->thread.ds_area_msr) BUG_ON(BTS_MAX_RECORD_SIZE < bts_cfg.sizeof_bts);
return -ENXIO;
retval = ds_write_bts((void *)child->thread.ds_area_msr, in); memset(bts_record, 0, bts_cfg.sizeof_bts);
if (retval) switch (in->qualifier) {
return retval; case BTS_INVALID:
break;
return sizeof(*in); case BTS_BRANCH:
} bts_set(bts_record, bts_from, in->variant.lbr.from_ip);
bts_set(bts_record, bts_to, in->variant.lbr.to_ip);
break;
static int ptrace_bts_realloc(struct task_struct *child, case BTS_TASK_ARRIVES:
int size, int reduce_size) case BTS_TASK_DEPARTS:
{ bts_set(bts_record, bts_from, bts_escape);
unsigned long rlim, vm; bts_set(bts_record, bts_qual, in->qualifier);
int ret, old_size; bts_set(bts_record, bts_jiffies, in->variant.jiffies);
break;
if (size < 0) default:
return -EINVAL; return -EINVAL;
old_size = ds_get_bts_size((void *)child->thread.ds_area_msr);
if (old_size < 0)
return old_size;
ret = ds_free((void **)&child->thread.ds_area_msr);
if (ret < 0)
goto out;
size >>= PAGE_SHIFT;
old_size >>= PAGE_SHIFT;
current->mm->total_vm -= old_size;
current->mm->locked_vm -= old_size;
if (size == 0)
goto out;
rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
vm = current->mm->total_vm + size;
if (rlim < vm) {
ret = -ENOMEM;
if (!reduce_size)
goto out;
size = rlim - current->mm->total_vm;
if (size <= 0)
goto out;
} }
rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; /* The writing task will be the switched-to task on a context
vm = current->mm->locked_vm + size; * switch. It needs to write into the switched-from task's BTS
if (rlim < vm) { * buffer. */
ret = -ENOMEM; return ds_unchecked_write_bts(child, bts_record, bts_cfg.sizeof_bts);
if (!reduce_size)
goto out;
size = rlim - current->mm->locked_vm;
if (size <= 0)
goto out;
}
ret = ds_allocate((void **)&child->thread.ds_area_msr,
size << PAGE_SHIFT);
if (ret < 0)
goto out;
current->mm->total_vm += size;
current->mm->locked_vm += size;
out:
if (child->thread.ds_area_msr)
set_tsk_thread_flag(child, TIF_DS_AREA_MSR);
else
clear_tsk_thread_flag(child, TIF_DS_AREA_MSR);
return ret;
} }
void ptrace_bts_take_timestamp(struct task_struct *tsk, void ptrace_bts_take_timestamp(struct task_struct *tsk,
@@ -839,7 +875,66 @@ void ptrace_bts_take_timestamp(struct task_struct *tsk,
ptrace_bts_write_record(tsk, &rec); ptrace_bts_write_record(tsk, &rec);
} }
#endif /* X86_BTS */
static const struct bts_configuration bts_cfg_netburst = {
.sizeof_bts = sizeof(long) * 3,
.sizeof_field = sizeof(long),
.debugctl_mask = (1<<2)|(1<<3)|(1<<5)
};
static const struct bts_configuration bts_cfg_pentium_m = {
.sizeof_bts = sizeof(long) * 3,
.sizeof_field = sizeof(long),
.debugctl_mask = (1<<6)|(1<<7)
};
static const struct bts_configuration bts_cfg_core2 = {
.sizeof_bts = 8 * 3,
.sizeof_field = 8,
.debugctl_mask = (1<<6)|(1<<7)|(1<<9)
};
static inline void bts_configure(const struct bts_configuration *cfg)
{
bts_cfg = *cfg;
}
void __cpuinit ptrace_bts_init_intel(struct cpuinfo_x86 *c)
{
switch (c->x86) {
case 0x6:
switch (c->x86_model) {
case 0xD:
case 0xE: /* Pentium M */
bts_configure(&bts_cfg_pentium_m);
break;
case 0xF: /* Core2 */
case 0x1C: /* Atom */
bts_configure(&bts_cfg_core2);
break;
default:
/* sorry, don't know about them */
break;
}
break;
case 0xF:
switch (c->x86_model) {
case 0x0:
case 0x1:
case 0x2: /* Netburst */
bts_configure(&bts_cfg_netburst);
break;
default:
/* sorry, don't know about them */
break;
}
break;
default:
/* sorry, don't know about them */
break;
}
}
#endif /* CONFIG_X86_PTRACE_BTS */
/* /*
* Called by kernel/ptrace.c when detaching.. * Called by kernel/ptrace.c when detaching..
@@ -852,15 +947,15 @@ void ptrace_disable(struct task_struct *child)
#ifdef TIF_SYSCALL_EMU #ifdef TIF_SYSCALL_EMU
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
#endif #endif
if (child->thread.ds_area_msr) { #ifdef CONFIG_X86_PTRACE_BTS
#ifdef X86_BTS (void)ds_release_bts(child);
ptrace_bts_realloc(child, 0, 0);
#endif child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask;
child->thread.debugctlmsr &= ~ds_debugctl_mask();
if (!child->thread.debugctlmsr) if (!child->thread.debugctlmsr)
clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
} #endif /* CONFIG_X86_PTRACE_BTS */
} }
#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
@@ -980,7 +1075,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* /*
* These bits need more cooking - not enabled yet: * These bits need more cooking - not enabled yet:
*/ */
#ifdef X86_BTS #ifdef CONFIG_X86_PTRACE_BTS
case PTRACE_BTS_CONFIG: case PTRACE_BTS_CONFIG:
ret = ptrace_bts_config ret = ptrace_bts_config
(child, data, (struct ptrace_bts_config __user *)addr); (child, data, (struct ptrace_bts_config __user *)addr);
@@ -992,7 +1087,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_BTS_SIZE: case PTRACE_BTS_SIZE:
ret = ptrace_bts_get_size(child); ret = ds_get_bts_index(child, /* pos = */ NULL);
break; break;
case PTRACE_BTS_GET: case PTRACE_BTS_GET:
@@ -1001,14 +1096,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_BTS_CLEAR: case PTRACE_BTS_CLEAR:
ret = ptrace_bts_clear(child); ret = ds_clear_bts(child);
break; break;
case PTRACE_BTS_DRAIN: case PTRACE_BTS_DRAIN:
ret = ptrace_bts_drain ret = ptrace_bts_drain
(child, data, (struct bts_struct __user *) addr); (child, data, (struct bts_struct __user *) addr);
break; break;
#endif #endif /* CONFIG_X86_PTRACE_BTS */
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
@@ -1375,30 +1470,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
force_sig_info(SIGTRAP, &info, tsk); force_sig_info(SIGTRAP, &info, tsk);
} }
static void syscall_trace(struct pt_regs *regs)
{
if (!(current->ptrace & PT_PTRACED))
return;
#if 0
printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
current->comm,
regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0),
current_thread_info()->flags, current->ptrace);
#endif
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (current->exit_code) {
send_sig(current->exit_code, current, 1);
current->exit_code = 0;
}
}
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
# define IS_IA32 1 # define IS_IA32 1
@@ -1432,8 +1503,9 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs)
if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
ret = -1L; ret = -1L;
if (ret || test_thread_flag(TIF_SYSCALL_TRACE)) if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
syscall_trace(regs); tracehook_report_syscall_entry(regs))
ret = -1L;
if (unlikely(current->audit_context)) { if (unlikely(current->audit_context)) {
if (IS_IA32) if (IS_IA32)
@@ -1459,7 +1531,7 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs)
audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
if (test_thread_flag(TIF_SYSCALL_TRACE)) if (test_thread_flag(TIF_SYSCALL_TRACE))
syscall_trace(regs); tracehook_report_syscall_exit(regs, 0);
/* /*
* If TIF_SYSCALL_EMU is set, we only get here because of * If TIF_SYSCALL_EMU is set, we only get here because of
@@ -1475,6 +1547,6 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs)
* system call instruction. * system call instruction.
*/ */
if (test_thread_flag(TIF_SINGLESTEP) && if (test_thread_flag(TIF_SINGLESTEP) &&
(current->ptrace & PT_PTRACED)) tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL))
send_sigtrap(current, regs, 0); send_sigtrap(current, regs, 0);
} }

View File

@@ -29,7 +29,11 @@ EXPORT_SYMBOL(pm_power_off);
static const struct desc_ptr no_idt = {}; static const struct desc_ptr no_idt = {};
static int reboot_mode; static int reboot_mode;
enum reboot_type reboot_type = BOOT_KBD; /*
* Keyboard reset and triple fault may result in INIT, not RESET, which
* doesn't work when we're in vmx root mode. Try ACPI first.
*/
enum reboot_type reboot_type = BOOT_ACPI;
int reboot_force; int reboot_force;
#if defined(CONFIG_X86_32) && defined(CONFIG_SMP) #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)

View File

@@ -223,6 +223,9 @@ unsigned long saved_video_mode;
#define RAMDISK_LOAD_FLAG 0x4000 #define RAMDISK_LOAD_FLAG 0x4000
static char __initdata command_line[COMMAND_LINE_SIZE]; static char __initdata command_line[COMMAND_LINE_SIZE];
#ifdef CONFIG_CMDLINE_BOOL
static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
#endif
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd; struct edd edd;
@@ -665,6 +668,19 @@ void __init setup_arch(char **cmdline_p)
bss_resource.start = virt_to_phys(&__bss_start); bss_resource.start = virt_to_phys(&__bss_start);
bss_resource.end = virt_to_phys(&__bss_stop)-1; bss_resource.end = virt_to_phys(&__bss_stop)-1;
#ifdef CONFIG_CMDLINE_BOOL
#ifdef CONFIG_CMDLINE_OVERRIDE
strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else
if (builtin_cmdline[0]) {
/* append boot loader cmdline to builtin */
strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
}
#endif
#endif
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line; *cmdline_p = command_line;

View File

@@ -162,9 +162,16 @@ void __init setup_per_cpu_areas(void)
printk(KERN_INFO printk(KERN_INFO
"cpu %d has no node %d or node-local memory\n", "cpu %d has no node %d or node-local memory\n",
cpu, node); cpu, node);
if (ptr)
printk(KERN_DEBUG "per cpu data for cpu%d at %016lx\n",
cpu, __pa(ptr));
} }
else else {
ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
if (ptr)
printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n",
cpu, node, __pa(ptr));
}
#endif #endif
per_cpu_offset(cpu) = ptr - __per_cpu_start; per_cpu_offset(cpu) = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);

View File

@@ -24,4 +24,9 @@ struct rt_sigframe {
struct ucontext uc; struct ucontext uc;
struct siginfo info; struct siginfo info;
}; };
int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs);
int ia32_setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs);
#endif #endif

View File

@@ -17,6 +17,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/tracehook.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/mm.h> #include <linux/mm.h>
@@ -26,6 +27,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/syscalls.h>
#include "sigframe.h" #include "sigframe.h"
@@ -558,8 +560,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
* handler too. * handler too.
*/ */
regs->flags &= ~X86_EFLAGS_TF; regs->flags &= ~X86_EFLAGS_TF;
if (test_thread_flag(TIF_SINGLESTEP))
ptrace_notify(SIGTRAP);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask); sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
@@ -568,6 +568,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return 0; return 0;
} }
@@ -661,5 +664,10 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
if (thread_info_flags & _TIF_SIGPENDING) if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs); do_signal(regs);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
}
clear_thread_flag(TIF_IRET); clear_thread_flag(TIF_IRET);
} }

View File

@@ -15,17 +15,21 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/ia32_unistd.h> #include <asm/ia32_unistd.h>
#include <asm/mce.h> #include <asm/mce.h>
#include <asm/syscall.h>
#include <asm/syscalls.h>
#include "sigframe.h" #include "sigframe.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -41,11 +45,6 @@
# define FIX_EFLAGS __FIX_EFLAGS # define FIX_EFLAGS __FIX_EFLAGS
#endif #endif
int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs);
int ia32_setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs * regs);
asmlinkage long asmlinkage long
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
struct pt_regs *regs) struct pt_regs *regs)
@@ -128,7 +127,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
/* Always make any pending restarted system calls return -EINTR */ /* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall; current_thread_info()->restart_block.fn = do_no_restart_syscall;
#define COPY(x) err |= __get_user(regs->x, &sc->x) #define COPY(x) (err |= __get_user(regs->x, &sc->x))
COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
COPY(dx); COPY(cx); COPY(ip); COPY(dx); COPY(cx); COPY(ip);
@@ -217,7 +216,8 @@ badframe:
*/ */
static inline int static inline int
setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
unsigned long mask, struct task_struct *me)
{ {
int err = 0; int err = 0;
@@ -354,35 +354,6 @@ give_sigsegv:
return -EFAULT; return -EFAULT;
} }
/*
* Return -1L or the syscall number that @regs is executing.
*/
static long current_syscall(struct pt_regs *regs)
{
/*
* We always sign-extend a -1 value being set here,
* so this is always either -1L or a syscall number.
*/
return regs->orig_ax;
}
/*
* Return a value that is -EFOO if the system call in @regs->orig_ax
* returned an error. This only works for @regs from @current.
*/
static long current_syscall_ret(struct pt_regs *regs)
{
#ifdef CONFIG_IA32_EMULATION
if (test_thread_flag(TIF_IA32))
/*
* Sign-extend the value so (int)-EFOO becomes (long)-EFOO
* and will match correctly in comparisons.
*/
return (int) regs->ax;
#endif
return regs->ax;
}
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
@@ -394,9 +365,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
if (current_syscall(regs) >= 0) { if (syscall_get_nr(current, regs) >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
switch (current_syscall_ret(regs)) { switch (syscall_get_error(current, regs)) {
case -ERESTART_RESTARTBLOCK: case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
regs->ax = -EINTR; regs->ax = -EINTR;
@@ -453,8 +424,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
* handler too. * handler too.
*/ */
regs->flags &= ~X86_EFLAGS_TF; regs->flags &= ~X86_EFLAGS_TF;
if (test_thread_flag(TIF_SINGLESTEP))
ptrace_notify(SIGTRAP);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask); sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
@@ -462,6 +431,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
sigaddset(&current->blocked, sig); sigaddset(&current->blocked, sig);
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
return ret; return ret;
@@ -518,9 +490,9 @@ static void do_signal(struct pt_regs *regs)
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
if (current_syscall(regs) >= 0) { if (syscall_get_nr(current, regs) >= 0) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
switch (current_syscall_ret(regs)) { switch (syscall_get_error(current, regs)) {
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
case -ERESTARTSYS: case -ERESTARTSYS:
case -ERESTARTNOINTR: case -ERESTARTNOINTR:
@@ -558,6 +530,11 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING) if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs); do_signal(regs);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
}
} }
void signal_fault(struct pt_regs *regs, void __user *frame, char *where) void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
@@ -565,7 +542,8 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
struct task_struct *me = current; struct task_struct *me = current;
if (show_unhandled_signals && printk_ratelimit()) { if (show_unhandled_signals && printk_ratelimit()) {
printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx",
me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); me->comm, me->pid, where, frame, regs->ip,
regs->sp, regs->orig_ax);
print_vma_addr(" in ", regs->ip); print_vma_addr(" in ", regs->ip);
printk("\n"); printk("\n");
} }

View File

@@ -88,7 +88,7 @@ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))
#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p))
#else #else
struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
#define get_idle_for_cpu(x) (idle_thread_array[(x)]) #define get_idle_for_cpu(x) (idle_thread_array[(x)])
#define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p))
#endif #endif
@@ -129,7 +129,7 @@ static int boot_cpu_logical_apicid;
static cpumask_t cpu_sibling_setup_map; static cpumask_t cpu_sibling_setup_map;
/* Set if we find a B stepping CPU */ /* Set if we find a B stepping CPU */
int __cpuinitdata smp_b_stepping; static int __cpuinitdata smp_b_stepping;
#if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32)
@@ -1313,16 +1313,13 @@ __init void prefill_possible_map(void)
if (!num_processors) if (!num_processors)
num_processors = 1; num_processors = 1;
#ifdef CONFIG_HOTPLUG_CPU
if (additional_cpus == -1) { if (additional_cpus == -1) {
if (disabled_cpus > 0) if (disabled_cpus > 0)
additional_cpus = disabled_cpus; additional_cpus = disabled_cpus;
else else
additional_cpus = 0; additional_cpus = 0;
} }
#else
additional_cpus = 0;
#endif
possible = num_processors + additional_cpus; possible = num_processors + additional_cpus;
if (possible > NR_CPUS) if (possible > NR_CPUS)
possible = NR_CPUS; possible = NR_CPUS;

View File

@@ -22,6 +22,8 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <asm/syscalls.h>
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff) unsigned long fd, unsigned long pgoff)

View File

@@ -13,11 +13,13 @@
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
#include <asm/ia32.h> #include <asm/ia32.h>
#include <asm/syscalls.h>
asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long off) unsigned long fd, unsigned long off)
{ {
long error; long error;
@@ -177,7 +179,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
vma = find_vma(mm, addr-len); vma = find_vma(mm, addr-len);
if (!vma || addr <= vma->vm_start) if (!vma || addr <= vma->vm_start)
/* remember the address as a hint for next time */ /* remember the address as a hint for next time */
return (mm->free_area_cache = addr-len); return mm->free_area_cache = addr-len;
} }
if (mm->mmap_base < len) if (mm->mmap_base < len)
@@ -194,7 +196,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
vma = find_vma(mm, addr); vma = find_vma(mm, addr);
if (!vma || addr+len <= vma->vm_start) if (!vma || addr+len <= vma->vm_start)
/* remember the address as a hint for next time */ /* remember the address as a hint for next time */
return (mm->free_area_cache = addr); return mm->free_area_cache = addr;
/* remember the largest hole we saw so far */ /* remember the largest hole we saw so far */
if (addr + mm->cached_hole_size < vma->vm_start) if (addr + mm->cached_hole_size < vma->vm_start)

View File

@@ -8,12 +8,12 @@
#define __NO_STUBS #define __NO_STUBS
#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
#undef _ASM_X86_64_UNISTD_H_ #undef ASM_X86__UNISTD_64_H
#include <asm/unistd_64.h> #include <asm/unistd_64.h>
#undef __SYSCALL #undef __SYSCALL
#define __SYSCALL(nr, sym) [nr] = sym, #define __SYSCALL(nr, sym) [nr] = sym,
#undef _ASM_X86_64_UNISTD_H_ #undef ASM_X86__UNISTD_64_H
typedef void (*sys_call_ptr_t)(void); typedef void (*sys_call_ptr_t)(void);

View File

@@ -36,6 +36,7 @@
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
#include <asm/hpet.h> #include <asm/hpet.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/timer.h>
#include "do_timer.h" #include "do_timer.h"

View File

@@ -10,6 +10,7 @@
#include <asm/ldt.h> #include <asm/ldt.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/syscalls.h>
#include "tls.h" #include "tls.h"

View File

@@ -32,6 +32,8 @@
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/nmi.h> #include <linux/nmi.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/io.h>
#if defined(CONFIG_EDAC) #if defined(CONFIG_EDAC)
#include <linux/edac.h> #include <linux/edac.h>
@@ -45,9 +47,6 @@
#include <asm/unwind.h> #include <asm/unwind.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/nmi.h>
#include <asm/smp.h>
#include <asm/io.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/pda.h> #include <asm/pda.h>
@@ -85,7 +84,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
void printk_address(unsigned long address, int reliable) void printk_address(unsigned long address, int reliable)
{ {
printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address); printk(" [<%016lx>] %s%pS\n",
address, reliable ? "" : "? ", (void *) address);
} }
static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
@@ -98,7 +98,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
[STACKFAULT_STACK - 1] = "#SS", [STACKFAULT_STACK - 1] = "#SS",
[MCE_STACK - 1] = "#MC", [MCE_STACK - 1] = "#MC",
#if DEBUG_STKSZ > EXCEPTION_STKSZ #if DEBUG_STKSZ > EXCEPTION_STKSZ
[N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" [N_EXCEPTION_STACKS ...
N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
#endif #endif
}; };
unsigned k; unsigned k;
@@ -339,9 +340,8 @@ static void
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long bp, char *log_lvl) unsigned long *stack, unsigned long bp, char *log_lvl)
{ {
printk("\nCall Trace:\n"); printk("Call Trace:\n");
dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
printk("\n");
} }
void show_trace(struct task_struct *task, struct pt_regs *regs, void show_trace(struct task_struct *task, struct pt_regs *regs,
@@ -357,11 +357,15 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack; unsigned long *stack;
int i; int i;
const int cpu = smp_processor_id(); const int cpu = smp_processor_id();
unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr); unsigned long *irqstack_end =
unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); (unsigned long *) (cpu_pda(cpu)->irqstackptr);
unsigned long *irqstack =
(unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
// debugging aid: "show_stack(NULL, NULL);" prints the /*
// back trace for this cpu. * debugging aid: "show_stack(NULL, NULL);" prints the
* back trace for this cpu.
*/
if (sp == NULL) { if (sp == NULL) {
if (task) if (task)
@@ -386,6 +390,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
printk(" %016lx", *stack++); printk(" %016lx", *stack++);
touch_nmi_watchdog(); touch_nmi_watchdog();
} }
printk("\n");
show_trace_log_lvl(task, regs, sp, bp, log_lvl); show_trace_log_lvl(task, regs, sp, bp, log_lvl);
} }
@@ -414,7 +419,6 @@ void dump_stack(void)
init_utsname()->version); init_utsname()->version);
show_trace(NULL, NULL, &stack, bp); show_trace(NULL, NULL, &stack, bp);
} }
EXPORT_SYMBOL(dump_stack); EXPORT_SYMBOL(dump_stack);
void show_registers(struct pt_regs *regs) void show_registers(struct pt_regs *regs)
@@ -443,7 +447,6 @@ void show_registers(struct pt_regs *regs)
printk("Stack: "); printk("Stack: ");
show_stack_log_lvl(NULL, regs, (unsigned long *)sp, show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
regs->bp, ""); regs->bp, "");
printk("\n");
printk(KERN_EMERG "Code: "); printk(KERN_EMERG "Code: ");
@@ -780,7 +783,8 @@ io_check_error(unsigned char reason, struct pt_regs *regs)
static notrace __kprobes void static notrace __kprobes void
unknown_nmi_error(unsigned char reason, struct pt_regs *regs) unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
{ {
if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
NOTIFY_STOP)
return; return;
printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n", printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
reason); reason);
@@ -1149,8 +1153,10 @@ void __init trap_init(void)
set_intr_gate(0, &divide_error); set_intr_gate(0, &divide_error);
set_intr_gate_ist(1, &debug, DEBUG_STACK); set_intr_gate_ist(1, &debug, DEBUG_STACK);
set_intr_gate_ist(2, &nmi, NMI_STACK); set_intr_gate_ist(2, &nmi, NMI_STACK);
set_system_gate_ist(3, &int3, DEBUG_STACK); /* int3 can be called from all */ /* int3 can be called from all */
set_system_gate(4, &overflow); /* int4 can be called from all */ set_system_gate_ist(3, &int3, DEBUG_STACK);
/* int4 can be called from all */
set_system_gate(4, &overflow);
set_intr_gate(5, &bounds); set_intr_gate(5, &bounds);
set_intr_gate(6, &invalid_op); set_intr_gate(6, &invalid_op);
set_intr_gate(7, &device_not_available); set_intr_gate(7, &device_not_available);

View File

@@ -104,7 +104,7 @@ __setup("notsc", notsc_setup);
/* /*
* Read TSC and the reference counters. Take care of SMI disturbance * Read TSC and the reference counters. Take care of SMI disturbance
*/ */
static u64 tsc_read_refs(u64 *pm, u64 *hpet) static u64 tsc_read_refs(u64 *p, int hpet)
{ {
u64 t1, t2; u64 t1, t2;
int i; int i;
@@ -112,9 +112,9 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet)
for (i = 0; i < MAX_RETRIES; i++) { for (i = 0; i < MAX_RETRIES; i++) {
t1 = get_cycles(); t1 = get_cycles();
if (hpet) if (hpet)
*hpet = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF; *p = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF;
else else
*pm = acpi_pm_read_early(); *p = acpi_pm_read_early();
t2 = get_cycles(); t2 = get_cycles();
if ((t2 - t1) < SMI_TRESHOLD) if ((t2 - t1) < SMI_TRESHOLD)
return t2; return t2;
@@ -122,6 +122,52 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet)
return ULLONG_MAX; return ULLONG_MAX;
} }
/*
* Calculate the TSC frequency from HPET reference
*/
static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2)
{
u64 tmp;
if (hpet2 < hpet1)
hpet2 += 0x100000000ULL;
hpet2 -= hpet1;
tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
do_div(tmp, 1000000);
do_div(deltatsc, tmp);
return (unsigned long) deltatsc;
}
/*
* Calculate the TSC frequency from PMTimer reference
*/
static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2)
{
u64 tmp;
if (!pm1 && !pm2)
return ULONG_MAX;
if (pm2 < pm1)
pm2 += (u64)ACPI_PM_OVRRUN;
pm2 -= pm1;
tmp = pm2 * 1000000000LL;
do_div(tmp, PMTMR_TICKS_PER_SEC);
do_div(deltatsc, tmp);
return (unsigned long) deltatsc;
}
#define CAL_MS 10
#define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS))
#define CAL_PIT_LOOPS 1000
#define CAL2_MS 50
#define CAL2_LATCH (CLOCK_TICK_RATE / (1000 / CAL2_MS))
#define CAL2_PIT_LOOPS 5000
/* /*
* Try to calibrate the TSC against the Programmable * Try to calibrate the TSC against the Programmable
* Interrupt Timer and return the frequency of the TSC * Interrupt Timer and return the frequency of the TSC
@@ -129,7 +175,7 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet)
* *
* Return ULONG_MAX on failure to calibrate. * Return ULONG_MAX on failure to calibrate.
*/ */
static unsigned long pit_calibrate_tsc(void) static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
{ {
u64 tsc, t1, t2, delta; u64 tsc, t1, t2, delta;
unsigned long tscmin, tscmax; unsigned long tscmin, tscmax;
@@ -144,8 +190,8 @@ static unsigned long pit_calibrate_tsc(void)
* (LSB then MSB) to begin countdown. * (LSB then MSB) to begin countdown.
*/ */
outb(0xb0, 0x43); outb(0xb0, 0x43);
outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42); outb(latch & 0xff, 0x42);
outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42); outb(latch >> 8, 0x42);
tsc = t1 = t2 = get_cycles(); tsc = t1 = t2 = get_cycles();
@@ -166,31 +212,154 @@ static unsigned long pit_calibrate_tsc(void)
/* /*
* Sanity checks: * Sanity checks:
* *
* If we were not able to read the PIT more than 5000 * If we were not able to read the PIT more than loopmin
* times, then we have been hit by a massive SMI * times, then we have been hit by a massive SMI
* *
* If the maximum is 10 times larger than the minimum, * If the maximum is 10 times larger than the minimum,
* then we got hit by an SMI as well. * then we got hit by an SMI as well.
*/ */
if (pitcnt < 5000 || tscmax > 10 * tscmin) if (pitcnt < loopmin || tscmax > 10 * tscmin)
return ULONG_MAX; return ULONG_MAX;
/* Calculate the PIT value */ /* Calculate the PIT value */
delta = t2 - t1; delta = t2 - t1;
do_div(delta, 50); do_div(delta, ms);
return delta; return delta;
} }
/*
* This reads the current MSB of the PIT counter, and
* checks if we are running on sufficiently fast and
* non-virtualized hardware.
*
* Our expectations are:
*
* - the PIT is running at roughly 1.19MHz
*
* - each IO is going to take about 1us on real hardware,
* but we allow it to be much faster (by a factor of 10) or
* _slightly_ slower (ie we allow up to a 2us read+counter
* update - anything else implies a unacceptably slow CPU
* or PIT for the fast calibration to work.
*
* - with 256 PIT ticks to read the value, we have 214us to
* see the same MSB (and overhead like doing a single TSC
* read per MSB value etc).
*
* - We're doing 2 reads per loop (LSB, MSB), and we expect
* them each to take about a microsecond on real hardware.
* So we expect a count value of around 100. But we'll be
* generous, and accept anything over 50.
*
* - if the PIT is stuck, and we see *many* more reads, we
* return early (and the next caller of pit_expect_msb()
* then consider it a failure when they don't see the
* next expected value).
*
* These expectations mean that we know that we have seen the
* transition from one expected value to another with a fairly
* high accuracy, and we didn't miss any events. We can thus
* use the TSC value at the transitions to calculate a pretty
* good value for the TSC frequencty.
*/
static inline int pit_expect_msb(unsigned char val)
{
int count = 0;
for (count = 0; count < 50000; count++) {
/* Ignore LSB */
inb(0x42);
if (inb(0x42) != val)
break;
}
return count > 50;
}
/*
* How many MSB values do we want to see? We aim for a
* 15ms calibration, which assuming a 2us counter read
* error should give us roughly 150 ppm precision for
* the calibration.
*/
#define QUICK_PIT_MS 15
#define QUICK_PIT_ITERATIONS (QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
static unsigned long quick_pit_calibrate(void)
{
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
/*
* Counter 2, mode 0 (one-shot), binary count
*
* NOTE! Mode 2 decrements by two (and then the
* output is flipped each time, giving the same
* final output frequency as a decrement-by-one),
* so mode 0 is much better when looking at the
* individual counts.
*/
outb(0xb0, 0x43);
/* Start at 0xffff */
outb(0xff, 0x42);
outb(0xff, 0x42);
if (pit_expect_msb(0xff)) {
int i;
u64 t1, t2, delta;
unsigned char expect = 0xfe;
t1 = get_cycles();
for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) {
if (!pit_expect_msb(expect))
goto failed;
}
t2 = get_cycles();
/*
* Make sure we can rely on the second TSC timestamp:
*/
if (!pit_expect_msb(expect))
goto failed;
/*
* Ok, if we get here, then we've seen the
* MSB of the PIT decrement QUICK_PIT_ITERATIONS
* times, and each MSB had many hits, so we never
* had any sudden jumps.
*
* As a result, we can depend on there not being
* any odd delays anywhere, and the TSC reads are
* reliable.
*
* kHz = ticks / time-in-seconds / 1000;
* kHz = (t2 - t1) / (QPI * 256 / PIT_TICK_RATE) / 1000
* kHz = ((t2 - t1) * PIT_TICK_RATE) / (QPI * 256 * 1000)
*/
delta = (t2 - t1)*PIT_TICK_RATE;
do_div(delta, QUICK_PIT_ITERATIONS*256*1000);
printk("Fast TSC calibration using PIT\n");
return delta;
}
failed:
return 0;
}
/** /**
* native_calibrate_tsc - calibrate the tsc on boot * native_calibrate_tsc - calibrate the tsc on boot
*/ */
unsigned long native_calibrate_tsc(void) unsigned long native_calibrate_tsc(void)
{ {
u64 tsc1, tsc2, delta, pm1, pm2, hpet1, hpet2; u64 tsc1, tsc2, delta, ref1, ref2;
unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
unsigned long flags; unsigned long flags, latch, ms, fast_calibrate;
int hpet = is_hpet_enabled(), i; int hpet = is_hpet_enabled(), i, loopmin;
local_irq_save(flags);
fast_calibrate = quick_pit_calibrate();
local_irq_restore(flags);
if (fast_calibrate)
return fast_calibrate;
/* /*
* Run 5 calibration loops to get the lowest frequency value * Run 5 calibration loops to get the lowest frequency value
@@ -216,7 +385,13 @@ unsigned long native_calibrate_tsc(void)
* calibration delay loop as we have to wait for a certain * calibration delay loop as we have to wait for a certain
* amount of time anyway. * amount of time anyway.
*/ */
for (i = 0; i < 5; i++) {
/* Preset PIT loop values */
latch = CAL_LATCH;
ms = CAL_MS;
loopmin = CAL_PIT_LOOPS;
for (i = 0; i < 3; i++) {
unsigned long tsc_pit_khz; unsigned long tsc_pit_khz;
/* /*
@@ -226,16 +401,16 @@ unsigned long native_calibrate_tsc(void)
* read the end value. * read the end value.
*/ */
local_irq_save(flags); local_irq_save(flags);
tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL); tsc1 = tsc_read_refs(&ref1, hpet);
tsc_pit_khz = pit_calibrate_tsc(); tsc_pit_khz = pit_calibrate_tsc(latch, ms, loopmin);
tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL); tsc2 = tsc_read_refs(&ref2, hpet);
local_irq_restore(flags); local_irq_restore(flags);
/* Pick the lowest PIT TSC calibration so far */ /* Pick the lowest PIT TSC calibration so far */
tsc_pit_min = min(tsc_pit_min, tsc_pit_khz); tsc_pit_min = min(tsc_pit_min, tsc_pit_khz);
/* hpet or pmtimer available ? */ /* hpet or pmtimer available ? */
if (!hpet && !pm1 && !pm2) if (!hpet && !ref1 && !ref2)
continue; continue;
/* Check, whether the sampling was disturbed by an SMI */ /* Check, whether the sampling was disturbed by an SMI */
@@ -243,23 +418,41 @@ unsigned long native_calibrate_tsc(void)
continue; continue;
tsc2 = (tsc2 - tsc1) * 1000000LL; tsc2 = (tsc2 - tsc1) * 1000000LL;
if (hpet)
tsc2 = calc_hpet_ref(tsc2, ref1, ref2);
else
tsc2 = calc_pmtimer_ref(tsc2, ref1, ref2);
if (hpet) { tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2);
if (hpet2 < hpet1)
hpet2 += 0x100000000ULL; /* Check the reference deviation */
hpet2 -= hpet1; delta = ((u64) tsc_pit_min) * 100;
tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); do_div(delta, tsc_ref_min);
do_div(tsc1, 1000000);
} else { /*
if (pm2 < pm1) * If both calibration results are inside a 10% window
pm2 += (u64)ACPI_PM_OVRRUN; * then we can be sure, that the calibration
pm2 -= pm1; * succeeded. We break out of the loop right away. We
tsc1 = pm2 * 1000000000LL; * use the reference value, as it is more precise.
do_div(tsc1, PMTMR_TICKS_PER_SEC); */
if (delta >= 90 && delta <= 110) {
printk(KERN_INFO
"TSC: PIT calibration matches %s. %d loops\n",
hpet ? "HPET" : "PMTIMER", i + 1);
return tsc_ref_min;
} }
do_div(tsc2, tsc1); /*
tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); * Check whether PIT failed more than once. This
* happens in virtualized environments. We need to
* give the virtual PC a slightly longer timeframe for
* the HPET/PMTIMER to make the result precise.
*/
if (i == 1 && tsc_pit_min == ULONG_MAX) {
latch = CAL2_LATCH;
ms = CAL2_MS;
loopmin = CAL2_PIT_LOOPS;
}
} }
/* /*
@@ -270,7 +463,7 @@ unsigned long native_calibrate_tsc(void)
printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n"); printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n");
/* We don't have an alternative source, disable TSC */ /* We don't have an alternative source, disable TSC */
if (!hpet && !pm1 && !pm2) { if (!hpet && !ref1 && !ref2) {
printk("TSC: No reference (HPET/PMTIMER) available\n"); printk("TSC: No reference (HPET/PMTIMER) available\n");
return 0; return 0;
} }
@@ -278,7 +471,7 @@ unsigned long native_calibrate_tsc(void)
/* The alternative source failed as well, disable TSC */ /* The alternative source failed as well, disable TSC */
if (tsc_ref_min == ULONG_MAX) { if (tsc_ref_min == ULONG_MAX) {
printk(KERN_WARNING "TSC: HPET/PMTIMER calibration " printk(KERN_WARNING "TSC: HPET/PMTIMER calibration "
"failed due to SMI disturbance.\n"); "failed.\n");
return 0; return 0;
} }
@@ -290,44 +483,25 @@ unsigned long native_calibrate_tsc(void)
} }
/* We don't have an alternative source, use the PIT calibration value */ /* We don't have an alternative source, use the PIT calibration value */
if (!hpet && !pm1 && !pm2) { if (!hpet && !ref1 && !ref2) {
printk(KERN_INFO "TSC: Using PIT calibration value\n"); printk(KERN_INFO "TSC: Using PIT calibration value\n");
return tsc_pit_min; return tsc_pit_min;
} }
/* The alternative source failed, use the PIT calibration value */ /* The alternative source failed, use the PIT calibration value */
if (tsc_ref_min == ULONG_MAX) { if (tsc_ref_min == ULONG_MAX) {
printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed due " printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. "
"to SMI disturbance. Using PIT calibration\n"); "Using PIT calibration\n");
return tsc_pit_min; return tsc_pit_min;
} }
/* Check the reference deviation */
delta = ((u64) tsc_pit_min) * 100;
do_div(delta, tsc_ref_min);
/*
* If both calibration results are inside a 5% window, the we
* use the lower frequency of those as it is probably the
* closest estimate.
*/
if (delta >= 95 && delta <= 105) {
printk(KERN_INFO "TSC: PIT calibration confirmed by %s.\n",
hpet ? "HPET" : "PMTIMER");
printk(KERN_INFO "TSC: using %s calibration value\n",
tsc_pit_min <= tsc_ref_min ? "PIT" :
hpet ? "HPET" : "PMTIMER");
return tsc_pit_min <= tsc_ref_min ? tsc_pit_min : tsc_ref_min;
}
printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
/* /*
* The calibration values differ too much. In doubt, we use * The calibration values differ too much. In doubt, we use
* the PIT value as we know that there are PMTIMERs around * the PIT value as we know that there are PMTIMERs around
* running at double speed. * running at double speed. At least we let the user know:
*/ */
printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
printk(KERN_INFO "TSC: Using PIT calibration value\n"); printk(KERN_INFO "TSC: Using PIT calibration value\n");
return tsc_pit_min; return tsc_pit_min;
} }

View File

@@ -25,45 +25,31 @@
#include <asm/visws/cobalt.h> #include <asm/visws/cobalt.h>
#include <asm/visws/piix4.h> #include <asm/visws/piix4.h>
#include <asm/arch_hooks.h> #include <asm/arch_hooks.h>
#include <asm/io_apic.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/smp.h>
#include <asm/io.h> #include <asm/io.h>
#include <mach_ipi.h> #include <mach_ipi.h>
#include "mach_apic.h" #include "mach_apic.h"
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/apic.h>
#include <asm/i8259.h> #include <asm/i8259.h>
#include <asm/irq_vectors.h> #include <asm/irq_vectors.h>
#include <asm/visws/cobalt.h>
#include <asm/visws/lithium.h> #include <asm/visws/lithium.h>
#include <asm/visws/piix4.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
extern int no_broadcast; extern int no_broadcast;
#include <asm/io.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/arch_hooks.h>
#include <asm/visws/cobalt.h>
#include <asm/visws/lithium.h>
char visws_board_type = -1; char visws_board_type = -1;
char visws_board_rev = -1; char visws_board_rev = -1;

View File

@@ -46,6 +46,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/syscalls.h>
/* /*
* Known problems: * Known problems:

View File

@@ -393,13 +393,13 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type)
} }
#endif #endif
static void vmi_allocate_pte(struct mm_struct *mm, u32 pfn) static void vmi_allocate_pte(struct mm_struct *mm, unsigned long pfn)
{ {
vmi_set_page_type(pfn, VMI_PAGE_L1); vmi_set_page_type(pfn, VMI_PAGE_L1);
vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0); vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
} }
static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn) static void vmi_allocate_pmd(struct mm_struct *mm, unsigned long pfn)
{ {
/* /*
* This call comes in very early, before mem_map is setup. * This call comes in very early, before mem_map is setup.
@@ -410,20 +410,20 @@ static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn)
vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0); vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
} }
static void vmi_allocate_pmd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count) static void vmi_allocate_pmd_clone(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count)
{ {
vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE); vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE);
vmi_check_page_type(clonepfn, VMI_PAGE_L2); vmi_check_page_type(clonepfn, VMI_PAGE_L2);
vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count); vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
} }
static void vmi_release_pte(u32 pfn) static void vmi_release_pte(unsigned long pfn)
{ {
vmi_ops.release_page(pfn, VMI_PAGE_L1); vmi_ops.release_page(pfn, VMI_PAGE_L1);
vmi_set_page_type(pfn, VMI_PAGE_NORMAL); vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
} }
static void vmi_release_pmd(u32 pfn) static void vmi_release_pmd(unsigned long pfn)
{ {
vmi_ops.release_page(pfn, VMI_PAGE_L2); vmi_ops.release_page(pfn, VMI_PAGE_L2);
vmi_set_page_type(pfn, VMI_PAGE_NORMAL); vmi_set_page_type(pfn, VMI_PAGE_NORMAL);

View File

@@ -16,37 +16,46 @@ static void __rdmsr_on_cpu(void *info)
rdmsr(rv->msr_no, rv->l, rv->h); rdmsr(rv->msr_no, rv->l, rv->h);
} }
static void __rdmsr_safe_on_cpu(void *info) static void __wrmsr_on_cpu(void *info)
{ {
struct msr_info *rv = info; struct msr_info *rv = info;
rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); wrmsr(rv->msr_no, rv->l, rv->h);
} }
static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
{ {
int err = 0; int err;
struct msr_info rv; struct msr_info rv;
rv.msr_no = msr_no; rv.msr_no = msr_no;
if (safe) {
err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu,
&rv, 1);
err = err ? err : rv.err;
} else {
err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
}
*l = rv.l; *l = rv.l;
*h = rv.h; *h = rv.h;
return err; return err;
} }
static void __wrmsr_on_cpu(void *info) int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
int err;
struct msr_info rv;
rv.msr_no = msr_no;
rv.l = l;
rv.h = h;
err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
return err;
}
/* These "safe" variants are slower and should be used when the target MSR
may not actually exist. */
static void __rdmsr_safe_on_cpu(void *info)
{ {
struct msr_info *rv = info; struct msr_info *rv = info;
wrmsr(rv->msr_no, rv->l, rv->h); rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h);
} }
static void __wrmsr_safe_on_cpu(void *info) static void __wrmsr_safe_on_cpu(void *info)
@@ -56,45 +65,30 @@ static void __wrmsr_safe_on_cpu(void *info)
rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h); rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h);
} }
static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
{ {
int err = 0; int err;
struct msr_info rv;
rv.msr_no = msr_no;
err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
*l = rv.l;
*h = rv.h;
return err ? err : rv.err;
}
int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
int err;
struct msr_info rv; struct msr_info rv;
rv.msr_no = msr_no; rv.msr_no = msr_no;
rv.l = l; rv.l = l;
rv.h = h; rv.h = h;
if (safe) { err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu,
&rv, 1);
err = err ? err : rv.err;
} else {
err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
}
return err; return err ? err : rv.err;
}
int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
return _wrmsr_on_cpu(cpu, msr_no, l, h, 0);
}
int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
{
return _rdmsr_on_cpu(cpu, msr_no, l, h, 0);
}
/* These "safe" variants are slower and should be used when the target MSR
may not actually exist. */
int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
{
return _wrmsr_on_cpu(cpu, msr_no, l, h, 1);
}
int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
{
return _rdmsr_on_cpu(cpu, msr_no, l, h, 1);
} }
EXPORT_SYMBOL(rdmsr_on_cpu); EXPORT_SYMBOL(rdmsr_on_cpu);

View File

@@ -10,6 +10,8 @@
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <mach_ipi.h>
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
#define DEFAULT_SEND_IPI (1) #define DEFAULT_SEND_IPI (1)
#else #else

View File

@@ -328,7 +328,7 @@ void __init initmem_init(unsigned long start_pfn,
get_memcfg_numa(); get_memcfg_numa();
kva_pages = round_up(calculate_numa_remap_pages(), PTRS_PER_PTE); kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE);
kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE); kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
do { do {

View File

@@ -148,8 +148,8 @@ static void note_page(struct seq_file *m, struct pg_state *st,
* we have now. "break" is either changing perms, levels or * we have now. "break" is either changing perms, levels or
* address space marker. * address space marker.
*/ */
prot = pgprot_val(new_prot) & ~(PTE_PFN_MASK); prot = pgprot_val(new_prot) & PTE_FLAGS_MASK;
cur = pgprot_val(st->current_prot) & ~(PTE_PFN_MASK); cur = pgprot_val(st->current_prot) & PTE_FLAGS_MASK;
if (!st->level) { if (!st->level) {
/* First entry */ /* First entry */

View File

@@ -35,6 +35,7 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/proto.h> #include <asm/proto.h>
#include <asm-generic/sections.h> #include <asm-generic/sections.h>
#include <asm/traps.h>
/* /*
* Page fault error code bits * Page fault error code bits
@@ -357,8 +358,6 @@ static int is_errata100(struct pt_regs *regs, unsigned long address)
return 0; return 0;
} }
void do_invalid_op(struct pt_regs *, unsigned long);
static int is_f00f_bug(struct pt_regs *regs, unsigned long address) static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
{ {
#ifdef CONFIG_X86_F00F_BUG #ifdef CONFIG_X86_F00F_BUG

View File

@@ -47,6 +47,7 @@
#include <asm/paravirt.h> #include <asm/paravirt.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/smp.h>
unsigned int __VMALLOC_RESERVE = 128 << 20; unsigned int __VMALLOC_RESERVE = 128 << 20;

View File

@@ -225,7 +225,7 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size)
void __init cleanup_highmap(void) void __init cleanup_highmap(void)
{ {
unsigned long vaddr = __START_KERNEL_map; unsigned long vaddr = __START_KERNEL_map;
unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1; unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1;
pmd_t *pmd = level2_kernel_pgt; pmd_t *pmd = level2_kernel_pgt;
pmd_t *last_pmd = pmd + PTRS_PER_PMD; pmd_t *last_pmd = pmd + PTRS_PER_PMD;
@@ -451,14 +451,14 @@ static void __init find_early_table_space(unsigned long end)
unsigned long puds, pmds, ptes, tables, start; unsigned long puds, pmds, ptes, tables, start;
puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
if (direct_gbpages) { if (direct_gbpages) {
unsigned long extra; unsigned long extra;
extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
} else } else
pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
if (cpu_has_pse) { if (cpu_has_pse) {
unsigned long extra; unsigned long extra;
@@ -466,7 +466,7 @@ static void __init find_early_table_space(unsigned long end)
ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
} else } else
ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE); tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
/* /*
* RED-PEN putting page tables only on node 0 could * RED-PEN putting page tables only on node 0 could

View File

@@ -421,7 +421,7 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
return; return;
} }
int __initdata early_ioremap_debug; static int __initdata early_ioremap_debug;
static int __init early_ioremap_debug_setup(char *str) static int __init early_ioremap_debug_setup(char *str)
{ {
@@ -547,7 +547,7 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx)
} }
int __initdata early_ioremap_nested; static int __initdata early_ioremap_nested;
static int __init check_early_ioremap_leak(void) static int __init check_early_ioremap_leak(void)
{ {

View File

@@ -79,7 +79,7 @@ static int __init allocate_cachealigned_memnodemap(void)
return 0; return 0;
addr = 0x8000; addr = 0x8000;
nodemap_size = round_up(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
nodemap_addr = find_e820_area(addr, max_pfn<<PAGE_SHIFT, nodemap_addr = find_e820_area(addr, max_pfn<<PAGE_SHIFT,
nodemap_size, L1_CACHE_BYTES); nodemap_size, L1_CACHE_BYTES);
if (nodemap_addr == -1UL) { if (nodemap_addr == -1UL) {
@@ -176,10 +176,10 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
unsigned long start_pfn, last_pfn, bootmap_pages, bootmap_size; unsigned long start_pfn, last_pfn, bootmap_pages, bootmap_size;
unsigned long bootmap_start, nodedata_phys; unsigned long bootmap_start, nodedata_phys;
void *bootmap; void *bootmap;
const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
int nid; int nid;
start = round_up(start, ZONE_ALIGN); start = roundup(start, ZONE_ALIGN);
printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid, printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid,
start, end); start, end);
@@ -210,9 +210,9 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn); bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn);
nid = phys_to_nid(nodedata_phys); nid = phys_to_nid(nodedata_phys);
if (nid == nodeid) if (nid == nodeid)
bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE);
else else
bootmap_start = round_up(start, PAGE_SIZE); bootmap_start = roundup(start, PAGE_SIZE);
/* /*
* SMP_CACHE_BYTES could be enough, but init_bootmem_node like * SMP_CACHE_BYTES could be enough, but init_bootmem_node like
* to use that to align to PAGE_SIZE * to use that to align to PAGE_SIZE

View File

@@ -84,7 +84,7 @@ static inline unsigned long highmap_start_pfn(void)
static inline unsigned long highmap_end_pfn(void) static inline unsigned long highmap_end_pfn(void)
{ {
return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT;
} }
#endif #endif
@@ -906,11 +906,13 @@ int set_memory_ro(unsigned long addr, int numpages)
{ {
return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW));
} }
EXPORT_SYMBOL_GPL(set_memory_ro);
int set_memory_rw(unsigned long addr, int numpages) int set_memory_rw(unsigned long addr, int numpages)
{ {
return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW));
} }
EXPORT_SYMBOL_GPL(set_memory_rw);
int set_memory_np(unsigned long addr, int numpages) int set_memory_np(unsigned long addr, int numpages)
{ {

View File

@@ -63,10 +63,8 @@ static inline void pgd_list_del(pgd_t *pgd)
#define UNSHARED_PTRS_PER_PGD \ #define UNSHARED_PTRS_PER_PGD \
(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD) (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
static void pgd_ctor(void *p) static void pgd_ctor(pgd_t *pgd)
{ {
pgd_t *pgd = p;
/* If the pgd points to a shared pagetable level (either the /* If the pgd points to a shared pagetable level (either the
ptes in non-PAE, or shared PMD in PAE), then just copy the ptes in non-PAE, or shared PMD in PAE), then just copy the
references from swapper_pg_dir. */ references from swapper_pg_dir. */
@@ -87,7 +85,7 @@ static void pgd_ctor(void *p)
pgd_list_add(pgd); pgd_list_add(pgd);
} }
static void pgd_dtor(void *pgd) static void pgd_dtor(pgd_t *pgd)
{ {
unsigned long flags; /* can be called from interrupt context */ unsigned long flags; /* can be called from interrupt context */

View File

@@ -123,7 +123,8 @@ static int __init parse_vmalloc(char *arg)
if (!arg) if (!arg)
return -EINVAL; return -EINVAL;
__VMALLOC_RESERVE = memparse(arg, &arg); /* Add VMALLOC_OFFSET to the parsed value due to vm area guard hole*/
__VMALLOC_RESERVE = memparse(arg, &arg) + VMALLOC_OFFSET;
return 0; return 0;
} }
early_param("vmalloc", parse_vmalloc); early_param("vmalloc", parse_vmalloc);

View File

@@ -10,11 +10,12 @@
#include <linux/oprofile.h> #include <linux/oprofile.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/nmi.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/ptrace.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/nmi.h>
#include "op_x86_model.h" #include "op_x86_model.h"
#include "op_counter.h" #include "op_counter.h"
@@ -97,7 +98,7 @@ static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = {
{ CTR_IQ_5, MSR_P4_IQ_PERFCTR5, MSR_P4_IQ_CCCR5 } { CTR_IQ_5, MSR_P4_IQ_PERFCTR5, MSR_P4_IQ_CCCR5 }
}; };
#define NUM_UNUSED_CCCRS NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT #define NUM_UNUSED_CCCRS (NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT)
/* p4 event codes in libop/op_event.h are indices into this table. */ /* p4 event codes in libop/op_event.h are indices into this table. */
@@ -402,12 +403,10 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs)
stag = get_stagger(); stag = get_stagger();
/* initialize some registers */ /* initialize some registers */
for (i = 0; i < num_counters; ++i) { for (i = 0; i < num_counters; ++i)
msrs->counters[i].addr = 0; msrs->counters[i].addr = 0;
} for (i = 0; i < num_controls; ++i)
for (i = 0; i < num_controls; ++i) {
msrs->controls[i].addr = 0; msrs->controls[i].addr = 0;
}
/* the counter & cccr registers we pay attention to */ /* the counter & cccr registers we pay attention to */
for (i = 0; i < num_counters; ++i) { for (i = 0; i < num_counters; ++i) {
@@ -534,11 +533,10 @@ static void pmc_setup_one_p4_counter(unsigned int ctr)
CCCR_CLEAR(cccr); CCCR_CLEAR(cccr);
CCCR_SET_REQUIRED_BITS(cccr); CCCR_SET_REQUIRED_BITS(cccr);
CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); CCCR_SET_ESCR_SELECT(cccr, ev->escr_select);
if (stag == 0) { if (stag == 0)
CCCR_SET_PMI_OVF_0(cccr); CCCR_SET_PMI_OVF_0(cccr);
} else { else
CCCR_SET_PMI_OVF_1(cccr); CCCR_SET_PMI_OVF_1(cccr);
}
CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr)); CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr));
return; return;
} }
@@ -686,7 +684,8 @@ static void p4_shutdown(struct op_msrs const * const msrs)
if (CTR_IS_RESERVED(msrs, i)) if (CTR_IS_RESERVED(msrs, i))
release_perfctr_nmi(msrs->counters[i].addr); release_perfctr_nmi(msrs->counters[i].addr);
} }
/* some of the control registers are specially reserved in /*
* some of the control registers are specially reserved in
* conjunction with the counter registers (hence the starting offset). * conjunction with the counter registers (hence the starting offset).
* This saves a few bits. * This saves a few bits.
*/ */

View File

@@ -1043,37 +1043,46 @@ static void __init pcibios_fixup_irqs(void)
if (io_apic_assign_pci_irqs) { if (io_apic_assign_pci_irqs) {
int irq; int irq;
if (pin) { if (!pin)
continue;
/* /*
* interrupt pins are numbered starting * interrupt pins are numbered starting from 1
* from 1
*/ */
pin--; pin--;
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
PCI_SLOT(dev->devfn), pin); PCI_SLOT(dev->devfn), pin);
/* /*
* Busses behind bridges are typically not listed in the MP-table. * Busses behind bridges are typically not listed in the
* In this case we have to look up the IRQ based on the parent bus, * MP-table. In this case we have to look up the IRQ
* parent slot, and pin number. The SMP code detects such bridged * based on the parent bus, parent slot, and pin number.
* busses itself so we should get into this branch reliably. * The SMP code detects such bridged busses itself so we
* should get into this branch reliably.
*/ */
if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ if (irq < 0 && dev->bus->parent) {
/* go back to the bridge */
struct pci_dev *bridge = dev->bus->self; struct pci_dev *bridge = dev->bus->self;
int bus;
pin = (pin + PCI_SLOT(dev->devfn)) % 4; pin = (pin + PCI_SLOT(dev->devfn)) % 4;
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, bus = bridge->bus->number;
irq = IO_APIC_get_PCI_irq_vector(bus,
PCI_SLOT(bridge->devfn), pin); PCI_SLOT(bridge->devfn), pin);
if (irq >= 0) if (irq >= 0)
dev_warn(&dev->dev, "using bridge %s INT %c to get IRQ %d\n", dev_warn(&dev->dev,
"using bridge %s INT %c to "
"get IRQ %d\n",
pci_name(bridge), pci_name(bridge),
'A' + pin, irq); 'A' + pin, irq);
} }
if (irq >= 0) { if (irq >= 0) {
dev_info(&dev->dev, "PCI->APIC IRQ transform: INT %c -> IRQ %d\n", 'A' + pin, irq); dev_info(&dev->dev,
"PCI->APIC IRQ transform: INT %c "
"-> IRQ %d\n",
'A' + pin, irq);
dev->irq = irq; dev->irq = irq;
} }
} }
}
#endif #endif
/* /*
* Still no IRQ? Try to lookup one... * Still no IRQ? Try to lookup one...

View File

@@ -1,5 +1,3 @@
.text
/* /*
* This may not use any stack, nor any variable that is not "NoSave": * This may not use any stack, nor any variable that is not "NoSave":
* *
@@ -12,17 +10,18 @@
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/processor-flags.h>
.text .text
ENTRY(swsusp_arch_suspend) ENTRY(swsusp_arch_suspend)
movl %esp, saved_context_esp movl %esp, saved_context_esp
movl %ebx, saved_context_ebx movl %ebx, saved_context_ebx
movl %ebp, saved_context_ebp movl %ebp, saved_context_ebp
movl %esi, saved_context_esi movl %esi, saved_context_esi
movl %edi, saved_context_edi movl %edi, saved_context_edi
pushfl ; popl saved_context_eflags pushfl
popl saved_context_eflags
call swsusp_save call swsusp_save
ret ret
@@ -59,7 +58,7 @@ done:
movl mmu_cr4_features, %ecx movl mmu_cr4_features, %ecx
jecxz 1f # cr4 Pentium and higher, skip if zero jecxz 1f # cr4 Pentium and higher, skip if zero
movl %ecx, %edx movl %ecx, %edx
andl $~(1<<7), %edx; # PGE andl $~(X86_CR4_PGE), %edx
movl %edx, %cr4; # turn off PGE movl %edx, %cr4; # turn off PGE
1: 1:
movl %cr3, %eax; # flush TLB movl %cr3, %eax; # flush TLB
@@ -74,7 +73,8 @@ done:
movl saved_context_esi, %esi movl saved_context_esi, %esi
movl saved_context_edi, %edi movl saved_context_edi, %edi
pushl saved_context_eflags ; popfl pushl saved_context_eflags
popfl
xorl %eax, %eax xorl %eax, %eax

View File

@@ -812,7 +812,7 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
/* Early in boot, while setting up the initial pagetable, assume /* Early in boot, while setting up the initial pagetable, assume
everything is pinned. */ everything is pinned. */
static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn) static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn)
{ {
#ifdef CONFIG_FLATMEM #ifdef CONFIG_FLATMEM
BUG_ON(mem_map); /* should only be used early */ BUG_ON(mem_map); /* should only be used early */
@@ -822,7 +822,7 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn)
/* Early release_pte assumes that all pts are pinned, since there's /* Early release_pte assumes that all pts are pinned, since there's
only init_mm and anything attached to that is pinned. */ only init_mm and anything attached to that is pinned. */
static void xen_release_pte_init(u32 pfn) static void xen_release_pte_init(unsigned long pfn)
{ {
make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
} }
@@ -838,7 +838,7 @@ static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
/* This needs to make sure the new pte page is pinned iff its being /* This needs to make sure the new pte page is pinned iff its being
attached to a pinned pagetable. */ attached to a pinned pagetable. */
static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level)
{ {
struct page *page = pfn_to_page(pfn); struct page *page = pfn_to_page(pfn);
@@ -856,12 +856,12 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level)
} }
} }
static void xen_alloc_pte(struct mm_struct *mm, u32 pfn) static void xen_alloc_pte(struct mm_struct *mm, unsigned long pfn)
{ {
xen_alloc_ptpage(mm, pfn, PT_PTE); xen_alloc_ptpage(mm, pfn, PT_PTE);
} }
static void xen_alloc_pmd(struct mm_struct *mm, u32 pfn) static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn)
{ {
xen_alloc_ptpage(mm, pfn, PT_PMD); xen_alloc_ptpage(mm, pfn, PT_PMD);
} }
@@ -909,7 +909,7 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
} }
/* This should never happen until we're OK to use struct page */ /* This should never happen until we're OK to use struct page */
static void xen_release_ptpage(u32 pfn, unsigned level) static void xen_release_ptpage(unsigned long pfn, unsigned level)
{ {
struct page *page = pfn_to_page(pfn); struct page *page = pfn_to_page(pfn);
@@ -923,23 +923,23 @@ static void xen_release_ptpage(u32 pfn, unsigned level)
} }
} }
static void xen_release_pte(u32 pfn) static void xen_release_pte(unsigned long pfn)
{ {
xen_release_ptpage(pfn, PT_PTE); xen_release_ptpage(pfn, PT_PTE);
} }
static void xen_release_pmd(u32 pfn) static void xen_release_pmd(unsigned long pfn)
{ {
xen_release_ptpage(pfn, PT_PMD); xen_release_ptpage(pfn, PT_PMD);
} }
#if PAGETABLE_LEVELS == 4 #if PAGETABLE_LEVELS == 4
static void xen_alloc_pud(struct mm_struct *mm, u32 pfn) static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn)
{ {
xen_alloc_ptpage(mm, pfn, PT_PUD); xen_alloc_ptpage(mm, pfn, PT_PUD);
} }
static void xen_release_pud(u32 pfn) static void xen_release_pud(unsigned long pfn)
{ {
xen_release_ptpage(pfn, PT_PUD); xen_release_ptpage(pfn, PT_PUD);
} }

View File

@@ -9,8 +9,8 @@
* 2 of the Licence, or (at your option) any later version. * 2 of the Licence, or (at your option) any later version.
*/ */
#ifndef _ASM_A_OUT_CORE_H #ifndef ASM_X86__A_OUT_CORE_H
#define _ASM_A_OUT_CORE_H #define ASM_X86__A_OUT_CORE_H
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
@@ -70,4 +70,4 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
#endif /* CONFIG_X86_32 */ #endif /* CONFIG_X86_32 */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_A_OUT_CORE_H */ #endif /* ASM_X86__A_OUT_CORE_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_A_OUT_H #ifndef ASM_X86__A_OUT_H
#define _ASM_X86_A_OUT_H #define ASM_X86__A_OUT_H
struct exec struct exec
{ {
@@ -17,4 +17,4 @@ struct exec
#define N_DRSIZE(a) ((a).a_drsize) #define N_DRSIZE(a) ((a).a_drsize)
#define N_SYMSIZE(a) ((a).a_syms) #define N_SYMSIZE(a) ((a).a_syms)
#endif /* _ASM_X86_A_OUT_H */ #endif /* ASM_X86__A_OUT_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_ACPI_H #ifndef ASM_X86__ACPI_H
#define _ASM_X86_ACPI_H #define ASM_X86__ACPI_H
/* /*
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -175,4 +175,4 @@ static inline void acpi_fake_nodes(const struct bootnode *fake_nodes,
#define acpi_unlazy_tlb(x) leave_mm(x) #define acpi_unlazy_tlb(x) leave_mm(x)
#endif /*__X86_ASM_ACPI_H*/ #endif /* ASM_X86__ACPI_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_AGP_H #ifndef ASM_X86__AGP_H
#define _ASM_X86_AGP_H #define ASM_X86__AGP_H
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
@@ -32,4 +32,4 @@
#define free_gatt_pages(table, order) \ #define free_gatt_pages(table, order) \
free_pages((unsigned long)(table), (order)) free_pages((unsigned long)(table), (order))
#endif #endif /* ASM_X86__AGP_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_ALTERNATIVE_H #ifndef ASM_X86__ALTERNATIVE_H
#define _ASM_X86_ALTERNATIVE_H #define ASM_X86__ALTERNATIVE_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/stddef.h> #include <linux/stddef.h>
@@ -180,4 +180,4 @@ extern void add_nops(void *insns, unsigned int len);
extern void *text_poke(void *addr, const void *opcode, size_t len); extern void *text_poke(void *addr, const void *opcode, size_t len);
extern void *text_poke_early(void *addr, const void *opcode, size_t len); extern void *text_poke_early(void *addr, const void *opcode, size_t len);
#endif /* _ASM_X86_ALTERNATIVE_H */ #endif /* ASM_X86__ALTERNATIVE_H */

View File

@@ -17,8 +17,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef _ASM_X86_AMD_IOMMU_H #ifndef ASM_X86__AMD_IOMMU_H
#define _ASM_X86_AMD_IOMMU_H #define ASM_X86__AMD_IOMMU_H
#ifdef CONFIG_AMD_IOMMU #ifdef CONFIG_AMD_IOMMU
extern int amd_iommu_init(void); extern int amd_iommu_init(void);
@@ -29,4 +29,4 @@ static inline int amd_iommu_init(void) { return -ENODEV; }
static inline void amd_iommu_detect(void) { } static inline void amd_iommu_detect(void) { }
#endif #endif
#endif #endif /* ASM_X86__AMD_IOMMU_H */

View File

@@ -17,8 +17,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef __AMD_IOMMU_TYPES_H__ #ifndef ASM_X86__AMD_IOMMU_TYPES_H
#define __AMD_IOMMU_TYPES_H__ #define ASM_X86__AMD_IOMMU_TYPES_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
@@ -341,4 +341,4 @@ static inline u16 calc_devid(u8 bus, u8 devfn)
return (((u16)bus) << 8) | devfn; return (((u16)bus) << 8) | devfn;
} }
#endif #endif /* ASM_X86__AMD_IOMMU_TYPES_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_APIC_H #ifndef ASM_X86__APIC_H
#define _ASM_X86_APIC_H #define ASM_X86__APIC_H
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/delay.h> #include <linux/delay.h>
@@ -54,6 +54,11 @@ extern int disable_apic;
#endif #endif
extern int is_vsmp_box(void); extern int is_vsmp_box(void);
extern void xapic_wait_icr_idle(void);
extern u32 safe_xapic_wait_icr_idle(void);
extern u64 xapic_icr_read(void);
extern void xapic_icr_write(u32, u32);
extern int setup_profiling_timer(unsigned int);
static inline void native_apic_write(unsigned long reg, u32 v) static inline void native_apic_write(unsigned long reg, u32 v)
{ {
@@ -76,9 +81,7 @@ extern int get_physical_broadcast(void);
static inline void ack_APIC_irq(void) static inline void ack_APIC_irq(void)
{ {
/* /*
* ack_APIC_irq() actually gets compiled as a single instruction: * ack_APIC_irq() actually gets compiled as a single instruction
* - a single rmw on Pentium/82489DX
* - a single write on P6+ cores (CONFIG_X86_GOOD_APIC)
* ... yummie. * ... yummie.
*/ */
@@ -128,4 +131,4 @@ static inline void init_apic_mappings(void) { }
#endif /* !CONFIG_X86_LOCAL_APIC */ #endif /* !CONFIG_X86_LOCAL_APIC */
#endif /* __ASM_APIC_H */ #endif /* ASM_X86__APIC_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_APICDEF_H #ifndef ASM_X86__APICDEF_H
#define _ASM_X86_APICDEF_H #define ASM_X86__APICDEF_H
/* /*
* Constants for various Intel APICs. (local APIC, IOAPIC, etc.) * Constants for various Intel APICs. (local APIC, IOAPIC, etc.)
@@ -411,4 +411,4 @@ struct local_apic {
#else #else
#define BAD_APICID 0xFFFFu #define BAD_APICID 0xFFFFu
#endif #endif
#endif #endif /* ASM_X86__APICDEF_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_ARCH_HOOKS_H #ifndef ASM_X86__ARCH_HOOKS_H
#define _ASM_ARCH_HOOKS_H #define ASM_X86__ARCH_HOOKS_H
#include <linux/interrupt.h> #include <linux/interrupt.h>
@@ -25,4 +25,4 @@ extern void pre_time_init_hook(void);
extern void time_init_hook(void); extern void time_init_hook(void);
extern void mca_nmi_hook(void); extern void mca_nmi_hook(void);
#endif #endif /* ASM_X86__ARCH_HOOKS_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_ASM_H #ifndef ASM_X86__ASM_H
#define _ASM_X86_ASM_H #define ASM_X86__ASM_H
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
# define __ASM_FORM(x) x # define __ASM_FORM(x) x
@@ -20,17 +20,22 @@
#define _ASM_PTR __ASM_SEL(.long, .quad) #define _ASM_PTR __ASM_SEL(.long, .quad)
#define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8) #define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8)
#define _ASM_MOV_UL __ASM_SIZE(mov)
#define _ASM_MOV __ASM_SIZE(mov)
#define _ASM_INC __ASM_SIZE(inc) #define _ASM_INC __ASM_SIZE(inc)
#define _ASM_DEC __ASM_SIZE(dec) #define _ASM_DEC __ASM_SIZE(dec)
#define _ASM_ADD __ASM_SIZE(add) #define _ASM_ADD __ASM_SIZE(add)
#define _ASM_SUB __ASM_SIZE(sub) #define _ASM_SUB __ASM_SIZE(sub)
#define _ASM_XADD __ASM_SIZE(xadd) #define _ASM_XADD __ASM_SIZE(xadd)
#define _ASM_AX __ASM_REG(ax) #define _ASM_AX __ASM_REG(ax)
#define _ASM_BX __ASM_REG(bx) #define _ASM_BX __ASM_REG(bx)
#define _ASM_CX __ASM_REG(cx) #define _ASM_CX __ASM_REG(cx)
#define _ASM_DX __ASM_REG(dx) #define _ASM_DX __ASM_REG(dx)
#define _ASM_SP __ASM_REG(sp)
#define _ASM_BP __ASM_REG(bp)
#define _ASM_SI __ASM_REG(si)
#define _ASM_DI __ASM_REG(di)
/* Exception table entry */ /* Exception table entry */
# define _ASM_EXTABLE(from,to) \ # define _ASM_EXTABLE(from,to) \
@@ -39,4 +44,4 @@
_ASM_PTR #from "," #to "\n" \ _ASM_PTR #from "," #to "\n" \
" .previous\n" " .previous\n"
#endif /* _ASM_X86_ASM_H */ #endif /* ASM_X86__ASM_H */

View File

@@ -1,5 +1,5 @@
#ifndef __ARCH_I386_ATOMIC__ #ifndef ASM_X86__ATOMIC_32_H
#define __ARCH_I386_ATOMIC__ #define ASM_X86__ATOMIC_32_H
#include <linux/compiler.h> #include <linux/compiler.h>
#include <asm/processor.h> #include <asm/processor.h>
@@ -256,4 +256,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__after_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier()
#include <asm-generic/atomic.h> #include <asm-generic/atomic.h>
#endif #endif /* ASM_X86__ATOMIC_32_H */

View File

@@ -1,5 +1,5 @@
#ifndef __ARCH_X86_64_ATOMIC__ #ifndef ASM_X86__ATOMIC_64_H
#define __ARCH_X86_64_ATOMIC__ #define ASM_X86__ATOMIC_64_H
#include <asm/alternative.h> #include <asm/alternative.h>
#include <asm/cmpxchg.h> #include <asm/cmpxchg.h>
@@ -470,4 +470,4 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2)
#define smp_mb__after_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier()
#include <asm-generic/atomic.h> #include <asm-generic/atomic.h>
#endif #endif /* ASM_X86__ATOMIC_64_H */

View File

@@ -1,5 +1,5 @@
#ifndef _ASM_X86_AUXVEC_H #ifndef ASM_X86__AUXVEC_H
#define _ASM_X86_AUXVEC_H #define ASM_X86__AUXVEC_H
/* /*
* Architecture-neutral AT_ values in 0-17, leave some room * Architecture-neutral AT_ values in 0-17, leave some room
* for more of them, start the x86-specific ones at 32. * for more of them, start the x86-specific ones at 32.
@@ -9,4 +9,4 @@
#endif #endif
#define AT_SYSINFO_EHDR 33 #define AT_SYSINFO_EHDR 33
#endif #endif /* ASM_X86__AUXVEC_H */

View File

@@ -1,5 +1,5 @@
#ifndef _MACH_BIOS_EBDA_H #ifndef ASM_X86__BIOS_EBDA_H
#define _MACH_BIOS_EBDA_H #define ASM_X86__BIOS_EBDA_H
#include <asm/io.h> #include <asm/io.h>
@@ -16,4 +16,4 @@ static inline unsigned int get_bios_ebda(void)
void reserve_ebda_region(void); void reserve_ebda_region(void);
#endif /* _MACH_BIOS_EBDA_H */ #endif /* ASM_X86__BIOS_EBDA_H */

Some files were not shown because too many files have changed in this diff Show More