select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
select HAVE_ARCH_KGDB if !X86_VOYAGER
- --- - - - - - config DEFCONFIG_LIST
+ +++ + + + + + config ARCH_DEFCONFIG
string
- --- - - - - - depends on X86_32
- --- - - - - - option defconfig_list
- --- - - - - - default "arch/x86/configs/i386_defconfig"
- --- - - - - -
- --- - - - - - config DEFCONFIG_LIST
- --- - - - - - string
- --- - - - - - depends on X86_64
- --- - - - - - option defconfig_list
- --- - - - - - default "arch/x86/configs/x86_64_defconfig"
+ +++ + + + + + default "arch/x86/configs/i386_defconfig" if X86_32
+ +++ + + + + + default "arch/x86/configs/x86_64_defconfig" if X86_64
config GENERIC_LOCKBREAK
config X86_VOYAGER
bool "Voyager (NCR)"
------------- ---------- depends on X86_32 && (SMP || BROKEN)
+++++++++++++ ++++++++++ depends on X86_32 && (SMP || BROKEN) && !PCI
help
Voyager is an MCA-based 32-way capable SMP architecture proprietary
to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based.
config X86_NUMAQ
bool "NUMAQ (IBM/Sequent)"
------------- ---------- depends on SMP && X86_32
+++++++++++++ ++++++++++ depends on SMP && X86_32 && PCI
select NUMA
help
This option is used for getting Linux to run on a (IBM/Sequent) NUMA
config X86_VISWS
bool "SGI 320/540 (Visual Workstation)"
------------- ---------- depends on X86_32
+++++++++++++ ++++++++++ depends on X86_32 && !PCI
help
The SGI Visual Workstation series is an IA32-based workstation
based on SGI systems chips with some legacy PC hardware attached.
config X86_VSMP
bool "Support for ScaleMP vSMP"
select PARAVIRT
------------- ---------- depends on X86_64
+++++++++++++ ++++++++++ depends on X86_64 && !PCI
help
Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
supposed to run on these EM64T-based machines. Only choose this option
config KVM_CLOCK
bool "KVM paravirtualized clock"
select PARAVIRT
+ +++ + ++ + ++++ + select PARAVIRT_CLOCK
depends on !(X86_VISWS || X86_VOYAGER)
help
Turning on this option will allow you to run a paravirtualized clock
over full virtualization. However, when run without a hypervisor
the kernel is theoretically slower and slightly larger.
+ +++ + ++ + ++++ + config PARAVIRT_CLOCK
+ +++ + ++ + ++++ + bool
+ +++ + ++ + ++++ + default n
+ +++ + ++ + ++++ +
endif
---------------- -------config MEMTEST_BOOTPARAM
---------------- ------- bool "Memtest boot parameter"
++++++++++++++++ +++++++config MEMTEST
++++++++++++++++ +++++++ bool "Memtest"
depends on X86_64
default y
help
This option adds a kernel parameter 'memtest', which allows memtest
---------------- ------- to be disabled at boot. If this option is selected, memtest
---------------- ------- functionality can be disabled with memtest=0 on the kernel
---------------- ------- command line. The purpose of this option is to allow a single
---------------- ------- kernel image to be distributed with memtest built in, but not
---------------- ------- necessarily enabled.
---------------- -------
++++++++++++++++ +++++++ to be set.
++++++++++++++++ +++++++ memtest=0, mean disabled; -- default
++++++++++++++++ +++++++ memtest=1, mean do 1 test pattern;
++++++++++++++++ +++++++ ...
++++++++++++++++ +++++++ memtest=4, mean do 4 test patterns.
If you are unsure how to answer this question, answer Y.
---------------- -------config MEMTEST_BOOTPARAM_VALUE
---------------- ------- int "Memtest boot parameter default value (0-4)"
---------------- ------- depends on MEMTEST_BOOTPARAM
---------------- ------- range 0 4
---------------- ------- default 0
---------------- ------- help
---------------- ------- This option sets the default value for the kernel parameter
---------------- ------- 'memtest', which allows memtest to be disabled at boot. If this
---------------- ------- option is set to 0 (zero), the memtest kernel parameter will
---------------- ------- default to 0, disabling memtest at bootup. If this option is
---------------- ------- set to 4, the memtest kernel parameter will default to 4,
---------------- ------- enabling memtest at bootup, and use that as pattern number.
---------------- -------
---------------- ------- If you are unsure how to answer this question, answer 0.
---------------- -------
config ACPI_SRAT
def_bool y
depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB)
config NR_CPUS
------------- ---------- int "Maximum number of CPUs (2-255)"
------------- ---------- range 2 255
+++++++++++++ ++++++++++ int "Maximum number of CPUs (2-4096)"
+++++++++++++ ++++++++++ range 2 4096
depends on SMP
default "32" if X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000
default "8"
help
This allows you to specify the maximum number of CPUs which this
------------- ---------- kernel will support. The maximum supported value is 255 and the
+++++++++++++ ++++++++++ kernel will support. The maximum supported value is 4096 and the
minimum value which makes sense is 2.
This is purely to save memory - each supported CPU adds
------------- ---------- approximately eight kilobytes to the kernel image.
+++++++++++++ ++++++++++ approximately one kilobyte to the kernel image.
config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
number of nodes. This is only useful for debugging.
config NODES_SHIFT
- ---- ----- ---------- int "Max num nodes shift(1-15)"
- ---- ----- ---------- range 1 15 if X86_64
+ ++++ +++++ ++++++++++ int "Max num nodes shift(1-9)"
+ ++++ +++++ ++++++++++ range 1 9 if X86_64
default "6" if X86_64
default "4" if X86_NUMAQ
default "3"
menu "Bus options (PCI etc.)"
config PCI
------------- ---------- bool "PCI support" if !X86_VISWS && !X86_VSMP
------------- ---------- depends on !X86_VOYAGER
+++++++++++++ ++++++++++ bool "PCI support"
default y
select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
help
config PCI_GODIRECT
bool "Direct"
- --- - - - - - config PCI_GOANY
- --- - - - - - bool "Any"
- --- - - - - -
config PCI_GOOLPC
bool "OLPC"
depends on OLPC
+ +++ + + + + + config PCI_GOANY
+ +++ + + + + + bool "Any"
+ +++ + + + + +
endchoice
config PCI_BIOS
depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
config PCI_OLPC
- --- - - - - - bool
- --- - - - - - depends on PCI && PCI_GOOLPC
- --- - - - - - default y
+ +++ + + + + + def_bool y
+ +++ + + + + + depends on PCI && OLPC && (PCI_GOOLPC || PCI_GOANY)
config PCI_DOMAINS
def_bool y
obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
obj-y += traps_$(BITS).o irq_$(BITS).o
obj-y += time_$(BITS).o ioport.o ldt.o
---------- -------------obj-y += setup_$(BITS).o i8259_$(BITS).o setup.o
++++++++++ +++++++++++++obj-y += setup_$(BITS).o i8259.o irqinit_$(BITS).o setup.o
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o
obj-y += bootflag.o e820_$(BITS).o
obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
obj-y += alternative.o i8253.o pci-nommu.o
------- ----------------obj-$(CONFIG_X86_64) += bugs_64.o
obj-y += tsc_$(BITS).o io_delay.o rtc.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-$(CONFIG_KVM_GUEST) += kvm.o
obj-$(CONFIG_KVM_CLOCK) += kvmclock.o
obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o
+ +++ + ++ + ++++ + obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o
obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o
/* Local APIC timer verification ok */
static int local_apic_timer_verify_ok;
------- ----------------/* Disable local APIC timer from the kernel commandline or via dmi quirk
------- ---------------- or using CPU MSR check */
------- ----------------int local_apic_timer_disabled;
+++++++ ++++++++++++++++/* Disable local APIC timer from the kernel commandline or via dmi quirk */
+++++++ ++++++++++++++++static int local_apic_timer_disabled;
/* Local APIC timer works in C2 */
int local_apic_timer_c2_ok;
EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
if (l & MSR_IA32_APICBASE_ENABLE)
mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
- ---------------------- if (nmi_watchdog != NMI_NONE && nmi_watchdog != NMI_DISABLED)
- ---------------------- nmi_watchdog = NMI_LOCAL_APIC;
- ----------------------
printk(KERN_INFO "Found and enabled local APIC!\n");
apic_pm_activate();
setup_local_APIC();
+ ++++++++++++++++++++++#ifdef CONFIG_X86_IO_APIC
+ ++++++++++++++++++++++ if (!smp_found_config || skip_ioapic_setup || !nr_ioapics)
+ ++++++++++++++++++++++#endif
+ ++++++++++++++++++++++ localise_nmi_watchdog();
end_local_APIC_setup();
#ifdef CONFIG_X86_IO_APIC
if (smp_found_config)
#include <mach_ipi.h>
#include <mach_apic.h>
------- ----------------int disable_apic_timer __cpuinitdata;
+++++++ ++++++++++++++++static int disable_apic_timer __cpuinitdata;
static int apic_calibrate_pmtmr __initdata;
int disable_apic;
setup_APIC_timer();
}
------- ----------------/*
------- ---------------- * AMD C1E enabled CPUs have a real nasty problem: Some BIOSes set the
------- ---------------- * C1E flag only in the secondary CPU, so when we detect the wreckage
------- ---------------- * we already have enabled the boot CPU local apic timer. Check, if
------- ---------------- * disable_apic_timer is set and the DUMMY flag is cleared. If yes,
------- ---------------- * set the DUMMY flag again and force the broadcast mode in the
------- ---------------- * clockevents layer.
------- ---------------- */
------- ----------------static void __cpuinit check_boot_apic_timer_broadcast(void)
------- ----------------{
------- ---------------- if (!disable_apic_timer ||
------- ---------------- (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY))
------- ---------------- return;
------- ----------------
------- ---------------- printk(KERN_INFO "AMD C1E detected late. Force timer broadcast.\n");
------- ---------------- lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY;
------- ----------------
------- ---------------- local_irq_enable();
------- ---------------- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
------- ---------------- &boot_cpu_physical_apicid);
------- ---------------- local_irq_disable();
------- ----------------}
------- ----------------
void __cpuinit setup_secondary_APIC_clock(void)
{
------- ---------------- check_boot_apic_timer_broadcast();
setup_APIC_timer();
}
*/
void clear_local_APIC(void)
{
- --- - - - - - int maxlvt = lapic_get_maxlvt();
+ +++ + + + + + int maxlvt;
u32 v;
/* APIC hasn't been mapped yet */
void __init early_init_lapic_mapping(void)
{
- ---------------------- unsigned long apic_phys;
+ ++++++++++++++++++++++ unsigned long phys_addr;
/*
* If no local APIC can be found then go out
if (!smp_found_config)
return;
- ---------------------- apic_phys = mp_lapic_addr;
+ ++++++++++++++++++++++ phys_addr = mp_lapic_addr;
- ---------------------- set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+ ++++++++++++++++++++++ set_fixmap_nocache(FIX_APIC_BASE, phys_addr);
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
- ---------------------- APIC_BASE, apic_phys);
+ ++++++++++++++++++++++ APIC_BASE, phys_addr);
/*
* Fetch the APIC ID of the BSP in case we have a
if (!skip_ioapic_setup && nr_ioapics)
enable_IO_APIC();
+ ++++++++++++++++++++++ if (!smp_found_config || skip_ioapic_setup || !nr_ioapics)
+ ++++++++++++++++++++++ localise_nmi_watchdog();
end_local_APIC_setup();
if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
#include <asm/page.h>
#include <asm/msr.h>
#include <asm/cache.h>
+++++ ++++++++++++++++++#include <asm/processor-flags.h>
#ifdef CONFIG_PARAVIRT
#include <asm/asm-offsets.h>
/* Fixup phys_base */
addq %rbp, phys_base(%rip)
- ---- ----------------#ifdef CONFIG_SMP
+ ++++ ++++++++++++++++#ifdef CONFIG_X86_TRAMPOLINE
addq %rbp, trampoline_level4_pgt + 0(%rip)
addq %rbp, trampoline_level4_pgt + (511*8)(%rip)
#endif
*/
/* Enable PAE mode and PGE */
----- ------------------ xorq %rax, %rax
----- ------------------ btsq $5, %rax
----- ------------------ btsq $7, %rax
+++++ ++++++++++++++++++ movl $(X86_CR4_PAE | X86_CR4_PGE), %eax
movq %rax, %cr4
/* Setup early boot stage 4 level pagetables. */
1: wrmsr /* Make changes effective */
/* Setup cr0 */
----- ------------------#define CR0_PM 1 /* protected mode */
----- ------------------#define CR0_MP (1<<1)
----- ------------------#define CR0_ET (1<<4)
----- ------------------#define CR0_NE (1<<5)
----- ------------------#define CR0_WP (1<<16)
----- ------------------#define CR0_AM (1<<18)
----- ------------------#define CR0_PAGING (1<<31)
----- ------------------ movl $CR0_PM|CR0_MP|CR0_ET|CR0_NE|CR0_WP|CR0_AM|CR0_PAGING,%eax
+++++ ++++++++++++++++++#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
+++++ ++++++++++++++++++ X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
+++++ ++++++++++++++++++ X86_CR0_PG)
+++++ ++++++++++++++++++ movl $CR0_STATE, %eax
/* Make changes effective */
movq %rax, %cr0
ENTRY(name)
/* Automate the creation of 1 to 1 mapping pmd entries */
----- ------------------#define PMDS(START, PERM, COUNT) \
----- ------------------ i = 0 ; \
----- ------------------ .rept (COUNT) ; \
----- ------------------ .quad (START) + (i << 21) + (PERM) ; \
----- ------------------ i = i + 1 ; \
+++++ ++++++++++++++++++#define PMDS(START, PERM, COUNT) \
+++++ ++++++++++++++++++ i = 0 ; \
+++++ ++++++++++++++++++ .rept (COUNT) ; \
+++++ ++++++++++++++++++ .quad (START) + (i << PMD_SHIFT) + (PERM) ; \
+++++ ++++++++++++++++++ i = i + 1 ; \
.endr
/*
static DEFINE_SPINLOCK(ioapic_lock);
static DEFINE_SPINLOCK(vector_lock);
- ----------------------int timer_over_8254 __initdata = 1;
+ ++++++++++++++++++++++int timer_through_8259 __initdata;
/*
* Is the SiS APIC rmw bug present ?
}
}
- ----------------------static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable)
+ ++++++++++++++++++++++static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
{
struct irq_pin_list *entry = irq_2_pin + irq;
unsigned int pin, reg;
}
/* mask = 1 */
- ----------------------static void __mask_IO_APIC_irq (unsigned int irq)
+ ++++++++++++++++++++++static void __mask_IO_APIC_irq(unsigned int irq)
{
- ---------------------- __modify_IO_APIC_irq(irq, 0x00010000, 0);
+ ++++++++++++++++++++++ __modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED, 0);
}
/* mask = 0 */
- ----------------------static void __unmask_IO_APIC_irq (unsigned int irq)
+ ++++++++++++++++++++++static void __unmask_IO_APIC_irq(unsigned int irq)
{
- ---------------------- __modify_IO_APIC_irq(irq, 0, 0x00010000);
+ ++++++++++++++++++++++ __modify_IO_APIC_irq(irq, 0, IO_APIC_REDIR_MASKED);
}
/* mask = 1, trigger = 0 */
- ----------------------static void __mask_and_edge_IO_APIC_irq (unsigned int irq)
+ ++++++++++++++++++++++static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
{
- ---------------------- __modify_IO_APIC_irq(irq, 0x00010000, 0x00008000);
+ ++++++++++++++++++++++ __modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED,
+ ++++++++++++++++++++++ IO_APIC_REDIR_LEVEL_TRIGGER);
}
/* mask = 0, trigger = 1 */
- ----------------------static void __unmask_and_level_IO_APIC_irq (unsigned int irq)
+ ++++++++++++++++++++++static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
{
- ---------------------- __modify_IO_APIC_irq(irq, 0x00008000, 0x00010000);
+ ++++++++++++++++++++++ __modify_IO_APIC_irq(irq, IO_APIC_REDIR_LEVEL_TRIGGER,
+ ++++++++++++++++++++++ IO_APIC_REDIR_MASKED);
}
- ----------------------static void mask_IO_APIC_irq (unsigned int irq)
+ ++++++++++++++++++++++static void mask_IO_APIC_irq(unsigned int irq)
{
unsigned long flags;
spin_unlock_irqrestore(&ioapic_lock, flags);
}
- ----------------------static void unmask_IO_APIC_irq (unsigned int irq)
+ ++++++++++++++++++++++static void unmask_IO_APIC_irq(unsigned int irq)
{
unsigned long flags;
static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
- ----------------------
+ ++++++++++++++++++++++
/* Check delivery_mode to be sure we're not clearing an SMI pin */
entry = ioapic_read_entry(apic, pin);
if (entry.delivery_mode == dest_SMI)
ioapic_mask_entry(apic, pin);
}
- ----------------------static void clear_IO_APIC (void)
+ ++++++++++++++++++++++static void clear_IO_APIC(void)
{
int apic, pin;
struct irq_pin_list *entry = irq_2_pin + irq;
unsigned int apicid_value;
cpumask_t tmp;
- ----------------------
+ ++++++++++++++++++++++
cpus_and(tmp, cpumask, cpu_online_map);
if (cpus_empty(tmp))
tmp = TARGET_CPUS;
# include <linux/kernel_stat.h> /* kstat */
# include <linux/slab.h> /* kmalloc() */
# include <linux/timer.h>
- ----------------------
+ ++++++++++++++++++++++
#define IRQBALANCE_CHECK_ARCH -999
#define MAX_BALANCED_IRQ_INTERVAL (5*HZ)
#define MIN_BALANCED_IRQ_INTERVAL (HZ/2)
static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
static struct irq_cpu_info {
- ---------------------- unsigned long * last_irq;
- ---------------------- unsigned long * irq_delta;
+ ++++++++++++++++++++++ unsigned long *last_irq;
+ ++++++++++++++++++++++ unsigned long *irq_delta;
unsigned long irq;
} irq_cpu_data[NR_CPUS];
#define CPU_IRQ(cpu) (irq_cpu_data[cpu].irq)
- ----------------------#define LAST_CPU_IRQ(cpu,irq) (irq_cpu_data[cpu].last_irq[irq])
- ----------------------#define IRQ_DELTA(cpu,irq) (irq_cpu_data[cpu].irq_delta[irq])
+ ++++++++++++++++++++++#define LAST_CPU_IRQ(cpu, irq) (irq_cpu_data[cpu].last_irq[irq])
+ ++++++++++++++++++++++#define IRQ_DELTA(cpu, irq) (irq_cpu_data[cpu].irq_delta[irq])
#define IDLE_ENOUGH(cpu,now) \
(idle_cpu(cpu) && ((now) - per_cpu(irq_stat, (cpu)).idle_timestamp > 1))
if (cpu == -1)
cpu = NR_CPUS-1;
}
- ---------------------- } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
- ---------------------- (search_idle && !IDLE_ENOUGH(cpu,now)));
+ ++++++++++++++++++++++ } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu, allowed_mask) ||
+ ++++++++++++++++++++++ (search_idle && !IDLE_ENOUGH(cpu, now)));
return cpu;
}
unsigned long now = jiffies;
cpumask_t allowed_mask;
unsigned int new_cpu;
- ----------------------
+ ++++++++++++++++++++++
if (irqbalance_disabled)
- ---------------------- return;
+ ++++++++++++++++++++++ return;
cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
new_cpu = move(cpu, allowed_mask, now, 1);
- ---------------------- if (cpu != new_cpu) {
+ ++++++++++++++++++++++ if (cpu != new_cpu)
set_pending_irq(irq, cpumask_of_cpu(new_cpu));
- ---------------------- }
}
static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
if (!irq_desc[j].action)
continue;
/* Is it a significant load ? */
- ---------------------- if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
+ ++++++++++++++++++++++ if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i), j) <
useful_load_threshold)
continue;
balance_irq(i, j);
}
}
balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
- ---------------------- balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ ++++++++++++++++++++++ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
return;
}
/* Is this an active IRQ or balancing disabled ? */
if (!irq_desc[j].action || irq_balancing_disabled(j))
continue;
- ---------------------- if ( package_index == i )
- ---------------------- IRQ_DELTA(package_index,j) = 0;
+ ++++++++++++++++++++++ if (package_index == i)
+ ++++++++++++++++++++++ IRQ_DELTA(package_index, j) = 0;
/* Determine the total count per processor per IRQ */
value_now = (unsigned long) kstat_cpu(i).irqs[j];
/* Determine the activity per processor per IRQ */
- ---------------------- delta = value_now - LAST_CPU_IRQ(i,j);
+ ++++++++++++++++++++++ delta = value_now - LAST_CPU_IRQ(i, j);
/* Update last_cpu_irq[][] for the next time */
- ---------------------- LAST_CPU_IRQ(i,j) = value_now;
+ ++++++++++++++++++++++ LAST_CPU_IRQ(i, j) = value_now;
/* Ignore IRQs whose rate is less than the clock */
if (delta < useful_load_threshold)
continue;
/* update the load for the processor or package total */
- ---------------------- IRQ_DELTA(package_index,j) += delta;
+ ++++++++++++++++++++++ IRQ_DELTA(package_index, j) += delta;
/* Keep track of the higher numbered sibling as well */
if (i != package_index)
max_cpu_irq = ULONG_MAX;
tryanothercpu:
- ---------------------- /* Look for heaviest loaded processor.
+ ++++++++++++++++++++++ /*
+ ++++++++++++++++++++++ * Look for heaviest loaded processor.
* We may come back to get the next heaviest loaded processor.
* Skip processors with trivial loads.
*/
for_each_online_cpu(i) {
if (i != CPU_TO_PACKAGEINDEX(i))
continue;
- ---------------------- if (max_cpu_irq <= CPU_IRQ(i))
+ ++++++++++++++++++++++ if (max_cpu_irq <= CPU_IRQ(i))
continue;
if (tmp_cpu_irq < CPU_IRQ(i)) {
tmp_cpu_irq = CPU_IRQ(i);
}
if (tmp_loaded == -1) {
- ---------------------- /* In the case of small number of heavy interrupt sources,
- ---------------------- * loading some of the cpus too much. We use Ingo's original
+ ++++++++++++++++++++++ /*
+ ++++++++++++++++++++++ * In the case of small number of heavy interrupt sources,
+ ++++++++++++++++++++++ * loading some of the cpus too much. We use Ingo's original
* approach to rotate them around.
*/
if (!first_attempt && imbalance >= useful_load_threshold) {
}
goto not_worth_the_effort;
}
- ----------------------
+ ++++++++++++++++++++++
first_attempt = 0; /* heaviest search */
max_cpu_irq = tmp_cpu_irq; /* load */
max_loaded = tmp_loaded; /* processor */
imbalance = (max_cpu_irq - min_cpu_irq) / 2;
- ----------------------
- ---------------------- /* if imbalance is less than approx 10% of max load, then
+ ++++++++++++++++++++++
+ ++++++++++++++++++++++ /*
+ ++++++++++++++++++++++ * if imbalance is less than approx 10% of max load, then
* observe diminishing returns action. - quit
*/
if (imbalance < (max_cpu_irq >> 3))
/* Is this an active IRQ? */
if (!irq_desc[j].action)
continue;
- ---------------------- if (imbalance <= IRQ_DELTA(max_loaded,j))
+ ++++++++++++++++++++++ if (imbalance <= IRQ_DELTA(max_loaded, j))
continue;
/* Try to find the IRQ that is closest to the imbalance
* without going over.
*/
- ---------------------- if (move_this_load < IRQ_DELTA(max_loaded,j)) {
- ---------------------- move_this_load = IRQ_DELTA(max_loaded,j);
+ ++++++++++++++++++++++ if (move_this_load < IRQ_DELTA(max_loaded, j)) {
+ ++++++++++++++++++++++ move_this_load = IRQ_DELTA(max_loaded, j);
selected_irq = j;
}
}
- ---------------------- if (selected_irq == -1) {
+ ++++++++++++++++++++++ if (selected_irq == -1)
goto tryanothercpu;
- ---------------------- }
imbalance = move_this_load;
- ----------------------
+ ++++++++++++++++++++++
/* For physical_balance case, we accumulated both load
* values in the one of the siblings cpu_irq[],
* to use the same code for physical and logical processors
- ---------------------- * as much as possible.
+ ++++++++++++++++++++++ * as much as possible.
*
* NOTE: the cpu_irq[] array holds the sum of the load for
* sibling A and sibling B in the slot for the lowest numbered
/* mark for change destination */
set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
- ---------------------- /* Since we made a change, come back sooner to
+ ++++++++++++++++++++++ /* Since we made a change, come back sooner to
* check for more variation.
*/
balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
- ---------------------- balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ ++++++++++++++++++++++ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
return;
}
goto tryanotherirq;
* upward
*/
balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
- ---------------------- balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
+ ++++++++++++++++++++++ balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
return;
}
cpumask_t tmp;
cpus_shift_right(tmp, cpu_online_map, 2);
- ---------------------- c = &boot_cpu_data;
+ ++++++++++++++++++++++ c = &boot_cpu_data;
/* When not overwritten by the command line ask subarchitecture. */
if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH)
irqbalance_disabled = NO_BALANCE_IRQ;
if (irqbalance_disabled)
return 0;
- ----------------------
+ ++++++++++++++++++++++
/* disable irqbalance completely if there is only one processor online */
if (num_online_cpus() < 2) {
irqbalance_disabled = 1;
physical_balance = 1;
for_each_online_cpu(i) {
- ---------------------- irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
- ---------------------- irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+ ++++++++++++++++++++++ irq_cpu_data[i].irq_delta = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+ ++++++++++++++++++++++ irq_cpu_data[i].last_irq = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
printk(KERN_ERR "balanced_irq_init: out of memory");
goto failed;
}
- ---------------------- memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS);
- ---------------------- memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS);
}
- ----------------------
+ ++++++++++++++++++++++
printk(KERN_INFO "Starting balanced_irq\n");
if (!IS_ERR(kthread_run(balanced_irq, NULL, "kirqd")))
return 0;
}
if (i < mp_irq_entries) {
int apic;
- ---------------------- for(apic = 0; apic < nr_ioapics; apic++) {
+ ++++++++++++++++++++++ for (apic = 0; apic < nr_ioapics; apic++) {
if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
return apic;
}
!mp_irqs[i].mpc_irqtype &&
(bus == lbus) &&
(slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
- ---------------------- int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
+ ++++++++++++++++++++++ int irq = pin_2_irq(i, apic, mp_irqs[i].mpc_dstirq);
if (!(apic || IO_APIC_IRQ(irq)))
continue;
EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
/*
- ---------------------- * This function currently is only a helper for the i386 smp boot process where
+ ++++++++++++++++++++++ * This function currently is only a helper for the i386 smp boot process where
* we need to reprogram the ioredtbls to cater for the cpus which have come online
* so mask in all cases should simply be TARGET_CPUS
*/
/*
* Determine IRQ line polarity (high active or low active):
*/
- ---------------------- switch (mp_irqs[idx].mpc_irqflag & 3)
+ ++++++++++++++++++++++ switch (mp_irqs[idx].mpc_irqflag & 3) {
+ ++++++++++++++++++++++ case 0: /* conforms, ie. bus-type dependent polarity */
{
- ---------------------- case 0: /* conforms, ie. bus-type dependent polarity */
- ---------------------- {
- ---------------------- polarity = test_bit(bus, mp_bus_not_pci)?
- ---------------------- default_ISA_polarity(idx):
- ---------------------- default_PCI_polarity(idx);
- ---------------------- break;
- ---------------------- }
- ---------------------- case 1: /* high active */
- ---------------------- {
- ---------------------- polarity = 0;
- ---------------------- break;
- ---------------------- }
- ---------------------- case 2: /* reserved */
- ---------------------- {
- ---------------------- printk(KERN_WARNING "broken BIOS!!\n");
- ---------------------- polarity = 1;
- ---------------------- break;
- ---------------------- }
- ---------------------- case 3: /* low active */
- ---------------------- {
- ---------------------- polarity = 1;
- ---------------------- break;
- ---------------------- }
- ---------------------- default: /* invalid */
- ---------------------- {
- ---------------------- printk(KERN_WARNING "broken BIOS!!\n");
- ---------------------- polarity = 1;
- ---------------------- break;
- ---------------------- }
+ ++++++++++++++++++++++ polarity = test_bit(bus, mp_bus_not_pci)?
+ ++++++++++++++++++++++ default_ISA_polarity(idx):
+ ++++++++++++++++++++++ default_PCI_polarity(idx);
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ case 1: /* high active */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ polarity = 0;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ case 2: /* reserved */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ printk(KERN_WARNING "broken BIOS!!\n");
+ ++++++++++++++++++++++ polarity = 1;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ case 3: /* low active */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ polarity = 1;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ default: /* invalid */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ printk(KERN_WARNING "broken BIOS!!\n");
+ ++++++++++++++++++++++ polarity = 1;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
}
return polarity;
}
/*
* Determine IRQ trigger mode (edge or level sensitive):
*/
- ---------------------- switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
+ ++++++++++++++++++++++ switch ((mp_irqs[idx].mpc_irqflag>>2) & 3) {
+ ++++++++++++++++++++++ case 0: /* conforms, ie. bus-type dependent */
{
- ---------------------- case 0: /* conforms, ie. bus-type dependent */
- ---------------------- {
- ---------------------- trigger = test_bit(bus, mp_bus_not_pci)?
- ---------------------- default_ISA_trigger(idx):
- ---------------------- default_PCI_trigger(idx);
+ ++++++++++++++++++++++ trigger = test_bit(bus, mp_bus_not_pci)?
+ ++++++++++++++++++++++ default_ISA_trigger(idx):
+ ++++++++++++++++++++++ default_PCI_trigger(idx);
#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
- ---------------------- switch (mp_bus_id_to_type[bus])
- ---------------------- {
- ---------------------- case MP_BUS_ISA: /* ISA pin */
- ---------------------- {
- ---------------------- /* set before the switch */
- ---------------------- break;
- ---------------------- }
- ---------------------- case MP_BUS_EISA: /* EISA pin */
- ---------------------- {
- ---------------------- trigger = default_EISA_trigger(idx);
- ---------------------- break;
- ---------------------- }
- ---------------------- case MP_BUS_PCI: /* PCI pin */
- ---------------------- {
- ---------------------- /* set before the switch */
- ---------------------- break;
- ---------------------- }
- ---------------------- case MP_BUS_MCA: /* MCA pin */
- ---------------------- {
- ---------------------- trigger = default_MCA_trigger(idx);
- ---------------------- break;
- ---------------------- }
- ---------------------- default:
- ---------------------- {
- ---------------------- printk(KERN_WARNING "broken BIOS!!\n");
- ---------------------- trigger = 1;
- ---------------------- break;
- ---------------------- }
- ---------------------- }
- ----------------------#endif
+ ++++++++++++++++++++++ switch (mp_bus_id_to_type[bus]) {
+ ++++++++++++++++++++++ case MP_BUS_ISA: /* ISA pin */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ /* set before the switch */
break;
}
- ---------------------- case 1: /* edge */
+ ++++++++++++++++++++++ case MP_BUS_EISA: /* EISA pin */
{
- ---------------------- trigger = 0;
+ ++++++++++++++++++++++ trigger = default_EISA_trigger(idx);
break;
}
- ---------------------- case 2: /* reserved */
+ ++++++++++++++++++++++ case MP_BUS_PCI: /* PCI pin */
{
- ---------------------- printk(KERN_WARNING "broken BIOS!!\n");
- ---------------------- trigger = 1;
+ ++++++++++++++++++++++ /* set before the switch */
break;
}
- ---------------------- case 3: /* level */
+ ++++++++++++++++++++++ case MP_BUS_MCA: /* MCA pin */
{
- ---------------------- trigger = 1;
+ ++++++++++++++++++++++ trigger = default_MCA_trigger(idx);
break;
}
- ---------------------- default: /* invalid */
+ ++++++++++++++++++++++ default:
{
printk(KERN_WARNING "broken BIOS!!\n");
- ---------------------- trigger = 0;
+ ++++++++++++++++++++++ trigger = 1;
break;
}
}
+ ++++++++++++++++++++++#endif
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ case 1: /* edge */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ trigger = 0;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ case 2: /* reserved */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ printk(KERN_WARNING "broken BIOS!!\n");
+ ++++++++++++++++++++++ trigger = 1;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ case 3: /* level */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ trigger = 1;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ default: /* invalid */
+ ++++++++++++++++++++++ {
+ ++++++++++++++++++++++ printk(KERN_WARNING "broken BIOS!!\n");
+ ++++++++++++++++++++++ trigger = 0;
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ }
return trigger;
}
for (apic = 0; apic < nr_ioapics; apic++) {
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
- ---------------------- idx = find_irq_entry(apic,pin,mp_INT);
- ---------------------- if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
+ ++++++++++++++++++++++ idx = find_irq_entry(apic, pin, mp_INT);
+ ++++++++++++++++++++++ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
return irq_trigger(idx);
}
}
static int __assign_irq_vector(int irq)
{
- ---------------------- static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+ ++++++++++++++++++++++ static int current_vector = FIRST_DEVICE_VECTOR, current_offset;
int vector, offset;
BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
/*
* add it to the IO-APIC irq-routing table:
*/
- ---------------------- memset(&entry,0,sizeof(entry));
+ ++++++++++++++++++++++ memset(&entry, 0, sizeof(entry));
entry.delivery_mode = INT_DELIVERY_MODE;
entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* enable IRQ */
- ---------------------- entry.dest.logical.logical_dest =
+ ++++++++++++++++++++++ entry.dest.logical.logical_dest =
cpu_mask_to_apicid(TARGET_CPUS);
- ---------------------- idx = find_irq_entry(apic,pin,mp_INT);
+ ++++++++++++++++++++++ idx = find_irq_entry(apic, pin, mp_INT);
if (idx == -1) {
if (first_notcon) {
apic_printk(APIC_VERBOSE, KERN_DEBUG
vector = assign_irq_vector(irq);
entry.vector = vector;
ioapic_register_intr(irq, vector, IOAPIC_AUTO);
- ----------------------
+ ++++++++++++++++++++++
if (!apic && (irq < 16))
disable_8259A_irq(irq);
}
}
/*
- ---------------------- * Set up the 8259A-master output pin:
+ ++++++++++++++++++++++ * Set up the timer pin, possibly with the 8259A-master behind.
*/
- ----------------------static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
+ ++++++++++++++++++++++static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
+ ++++++++++++++++++++++ int vector)
{
struct IO_APIC_route_entry entry;
- ---------------------- memset(&entry,0,sizeof(entry));
- ----------------------
- ---------------------- disable_8259A_irq(0);
- ----------------------
- ---------------------- /* mask LVT0 */
- ---------------------- apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ ++++++++++++++++++++++ memset(&entry, 0, sizeof(entry));
/*
* We use logical delivery to get the timer IRQ
* to the first CPU.
*/
entry.dest_mode = INT_DEST_MODE;
- ---------------------- entry.mask = 0; /* unmask IRQ now */
+ ++++++++++++++++++++++ entry.mask = 1; /* mask IRQ now */
entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
entry.delivery_mode = INT_DELIVERY_MODE;
entry.polarity = 0;
/*
* The timer IRQ doesn't have to know that behind the
- ---------------------- * scene we have a 8259A-master in AEOI mode ...
+ ++++++++++++++++++++++ * scene we may have a 8259A-master in AEOI mode ...
*/
- ---------------------- irq_desc[0].chip = &ioapic_chip;
- ---------------------- set_irq_handler(0, handle_edge_irq);
+ ++++++++++++++++++++++ ioapic_register_intr(0, vector, IOAPIC_EDGE);
/*
* Add it to the IO-APIC irq-routing table:
*/
ioapic_write_entry(apic, pin, entry);
- ----------------------
- ---------------------- enable_8259A_irq(0);
}
void __init print_IO_APIC(void)
if (apic_verbosity == APIC_QUIET)
return;
- ---------------------- printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+ ++++++++++++++++++++++ printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
for (i = 0; i < nr_ioapics; i++)
printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
#if 0
- ----------------------static void print_APIC_bitfield (int base)
+ ++++++++++++++++++++++static void print_APIC_bitfield(int base)
{
unsigned int v;
int i, j;
}
}
- ----------------------void /*__init*/ print_local_APIC(void * dummy)
+ ++++++++++++++++++++++void /*__init*/ print_local_APIC(void *dummy)
{
unsigned int v, ver, maxlvt;
printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
smp_processor_id(), hard_smp_processor_id());
+++++ ++++++++++++++++++ v = apic_read(APIC_ID);
printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v,
GET_APIC_ID(read_apic_id()));
v = apic_read(APIC_LVR);
printk("\n");
}
- ----------------------void print_all_local_APICs (void)
+ ++++++++++++++++++++++void print_all_local_APICs(void)
{
on_each_cpu(print_local_APIC, NULL, 1, 1);
}
v = inb(0xa0) << 8 | inb(0x20);
printk(KERN_DEBUG "... PIC IRR: %04x\n", v);
- ---------------------- outb(0x0b,0xa0);
- ---------------------- outb(0x0b,0x20);
+ ++++++++++++++++++++++ outb(0x0b, 0xa0);
+ ++++++++++++++++++++++ outb(0x0b, 0x20);
v = inb(0xa0) << 8 | inb(0x20);
- ---------------------- outb(0x0a,0xa0);
- ---------------------- outb(0x0a,0x20);
+ ++++++++++++++++++++++ outb(0x0a, 0xa0);
+ ++++++++++++++++++++++ outb(0x0a, 0x20);
spin_unlock_irqrestore(&i8259A_lock, flags);
spin_unlock_irqrestore(&ioapic_lock, flags);
nr_ioapic_registers[apic] = reg_01.bits.entries+1;
}
- ---------------------- for(apic = 0; apic < nr_ioapics; apic++) {
+ ++++++++++++++++++++++ for (apic = 0; apic < nr_ioapics; apic++) {
int pin;
/* See if any of the pins is in ExtINT mode */
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
spin_lock_irqsave(&ioapic_lock, flags);
reg_00.raw = io_apic_read(apic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);
- ----------------------
+ ++++++++++++++++++++++
old_id = mp_ioapics[apic].mpc_apicid;
if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) {
/*
* Read the right value from the MPC table and
* write it into the ID register.
- ---------------------- */
+ ++++++++++++++++++++++ */
apic_printk(APIC_VERBOSE, KERN_INFO
"...changing IO-APIC physical APIC ID to %d ...",
mp_ioapics[apic].mpc_apicid);
ack_APIC_irq();
}
- ----------------------static void mask_lapic_irq (unsigned int irq)
+ ++++++++++++++++++++++static void mask_lapic_irq(unsigned int irq)
{
unsigned long v;
apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
}
- ----------------------static void unmask_lapic_irq (unsigned int irq)
+ ++++++++++++++++++++++static void unmask_lapic_irq(unsigned int irq)
{
unsigned long v;
}
static struct irq_chip lapic_chip __read_mostly = {
- ---------------------- .name = "local-APIC-edge",
+ ++++++++++++++++++++++ .name = "local-APIC",
.mask = mask_lapic_irq,
.unmask = unmask_lapic_irq,
.eoi = ack_apic,
static void __init setup_nmi(void)
{
/*
- ---------------------- * Dirty trick to enable the NMI watchdog ...
+ ++++++++++++++++++++++ * Dirty trick to enable the NMI watchdog ...
* We put the 8259A master into AEOI mode and
* unmask on all local APICs LVT0 as NMI.
*
* The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
* is from Maciej W. Rozycki - so we do not have to EOI from
* the NMI handler or the timer interrupt.
- ---------------------- */
+ ++++++++++++++++++++++ */
apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
enable_NMI_through_LVT0();
static inline void __init check_timer(void)
{
int apic1, pin1, apic2, pin2;
+ ++++++++++++++++++++++ int no_pin1 = 0;
int vector;
+++ ++ ++ ++++ ++ + unsigned int ver;
unsigned long flags;
local_irq_save(flags);
+++ ++ ++ ++++ ++ + ver = apic_read(APIC_LVR);
+++ ++ ++ ++++ ++ + ver = GET_APIC_VERSION(ver);
+++ ++ ++ ++++ ++ +
/*
* get/set the timer IRQ vector:
*/
set_intr_gate(vector, interrupt[0]);
/*
- ---------------------- * Subtle, code in do_timer_interrupt() expects an AEOI
- ---------------------- * mode for the 8259A whenever interrupts are routed
- ---------------------- * through I/O APICs. Also IRQ0 has to be enabled in
- ---------------------- * the 8259A which implies the virtual wire has to be
- --- - - - - - * disabled in the local APIC. Finally timer interrupts
- --- - - - - - * need to be acknowledged manually in the 8259A for
- --- - - - - - * timer_interrupt() and for the i82489DX when using
- --- - - - - - * the NMI watchdog.
--- -- -- ---- -- - * disabled in the local APIC.
+ ++++++++++++++++++++++ * As IRQ0 is to be enabled in the 8259A, the virtual
+ ++++++++++++++++++++++ * wire has to be disabled in the local APIC. Also
+ ++++++++++++++++++++++ * timer interrupts need to be acknowledged manually in
+ ++++++++++++++++++++++ * the 8259A for the i82489DX when using the NMI
+ ++++++++++++++++++++++ * watchdog as that APIC treats NMIs as level-triggered.
+ ++++++++++++++++++++++ * The AEOI mode will finish them in the 8259A
+ ++++++++++++++++++++++ * automatically.
*/
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1);
- --- - - - - - timer_ack = !cpu_has_tsc;
- --- - - - - - timer_ack |= (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
--- -- -- ---- -- - timer_ack = 1;
- ---------------------- if (timer_over_8254 > 0)
- ---------------------- enable_8259A_irq(0);
+ ++++++++++++++++++++++ timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
pin1 = find_isa_irq_pin(0, mp_INT);
apic1 = find_isa_irq_apic(0, mp_INT);
printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
vector, apic1, pin1, apic2, pin2);
+ ++++++++++++++++++++++ /*
+ ++++++++++++++++++++++ * Some BIOS writers are clueless and report the ExtINTA
+ ++++++++++++++++++++++ * I/O APIC input from the cascaded 8259A as the timer
+ ++++++++++++++++++++++ * interrupt input. So just in case, if only one pin
+ ++++++++++++++++++++++ * was found above, try it both directly and through the
+ ++++++++++++++++++++++ * 8259A.
+ ++++++++++++++++++++++ */
+ ++++++++++++++++++++++ if (pin1 == -1) {
+ ++++++++++++++++++++++ pin1 = pin2;
+ ++++++++++++++++++++++ apic1 = apic2;
+ ++++++++++++++++++++++ no_pin1 = 1;
+ ++++++++++++++++++++++ } else if (pin2 == -1) {
+ ++++++++++++++++++++++ pin2 = pin1;
+ ++++++++++++++++++++++ apic2 = apic1;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++
if (pin1 != -1) {
/*
* Ok, does IRQ0 through the IOAPIC work?
*/
+ ++++++++++++++++++++++ if (no_pin1) {
+ ++++++++++++++++++++++ add_pin_to_irq(0, apic1, pin1);
+ ++++++++++++++++++++++ setup_timer_IRQ0_pin(apic1, pin1, vector);
+ ++++++++++++++++++++++ }
unmask_IO_APIC_irq(0);
if (timer_irq_works()) {
if (nmi_watchdog == NMI_IO_APIC) {
- ---------------------- disable_8259A_irq(0);
setup_nmi();
enable_8259A_irq(0);
}
goto out;
}
clear_IO_APIC_pin(apic1, pin1);
- ---------------------- printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
- ---------------------- "IO-APIC\n");
- ---------------------- }
+ ++++++++++++++++++++++ if (!no_pin1)
+ ++++++++++++++++++++++ printk(KERN_ERR "..MP-BIOS bug: "
+ ++++++++++++++++++++++ "8254 timer not connected to IO-APIC\n");
- ---------------------- printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
- ---------------------- if (pin2 != -1) {
+ ++++++++++++++++++++++ printk(KERN_INFO "...trying to set up timer (IRQ0) "
+ ++++++++++++++++++++++ "through the 8259A ... ");
printk("\n..... (found pin %d) ...", pin2);
/*
* legacy devices should be connected to IO APIC #0
*/
- ---------------------- setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
+ ++++++++++++++++++++++ replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
+ ++++++++++++++++++++++ setup_timer_IRQ0_pin(apic2, pin2, vector);
+ ++++++++++++++++++++++ unmask_IO_APIC_irq(0);
+ ++++++++++++++++++++++ enable_8259A_irq(0);
if (timer_irq_works()) {
printk("works.\n");
- ---------------------- if (pin1 != -1)
- ---------------------- replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
- ---------------------- else
- ---------------------- add_pin_to_irq(0, apic2, pin2);
+ ++++++++++++++++++++++ timer_through_8259 = 1;
if (nmi_watchdog == NMI_IO_APIC) {
+ ++++++++++++++++++++++ disable_8259A_irq(0);
setup_nmi();
+ ++++++++++++++++++++++ enable_8259A_irq(0);
}
goto out;
}
/*
* Cleanup, just in case ...
*/
+ ++++++++++++++++++++++ disable_8259A_irq(0);
clear_IO_APIC_pin(apic2, pin2);
+ ++++++++++++++++++++++ printk(" failed.\n");
}
- ---------------------- printk(" failed.\n");
if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
- ---------------------- nmi_watchdog = 0;
+ ++++++++++++++++++++++ nmi_watchdog = NMI_NONE;
}
+ ++++++++++++++++++++++ timer_ack = 0;
printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
- ---------------------- disable_8259A_irq(0);
set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
"fasteoi");
apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */
printk(" works.\n");
goto out;
}
+ ++++++++++++++++++++++ disable_8259A_irq(0);
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
printk(" failed.\n");
printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
- ---------------------- timer_ack = 0;
init_8259A(0);
make_8259A_irq(0);
apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
print_IO_APIC();
}
- ----------------------static int __init setup_disable_8254_timer(char *s)
- ----------------------{
- ---------------------- timer_over_8254 = -1;
- ---------------------- return 1;
- ----------------------}
- ----------------------static int __init setup_enable_8254_timer(char *s)
- ----------------------{
- ---------------------- timer_over_8254 = 2;
- ---------------------- return 1;
- ----------------------}
- ----------------------
- ----------------------__setup("disable_8254_timer", setup_disable_8254_timer);
- ----------------------__setup("enable_8254_timer", setup_enable_8254_timer);
- ----------------------
/*
* Called after all the initialization is done. If we didnt find any
* APIC bugs then we can allow the modify fast path
*/
- ----------------------
+ ++++++++++++++++++++++
static int __init io_apic_bug_finalize(void)
{
- ---------------------- if(sis_apic_bug == -1)
+ ++++++++++++++++++++++ if (sis_apic_bug == -1)
sis_apic_bug = 0;
return 0;
}
struct sys_device dev;
struct IO_APIC_route_entry entry[0];
};
- ----------------------static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+ ++++++++++++++++++++++static struct sysfs_ioapic_data *mp_ioapic_data[MAX_IO_APICS];
static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
{
struct IO_APIC_route_entry *entry;
struct sysfs_ioapic_data *data;
int i;
- ----------------------
+ ++++++++++++++++++++++
data = container_of(dev, struct sysfs_ioapic_data, dev);
entry = data->entry;
- ---------------------- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
+ ++++++++++++++++++++++ for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
entry[i] = ioapic_read_entry(dev->id, i);
return 0;
unsigned long flags;
union IO_APIC_reg_00 reg_00;
int i;
- ----------------------
+ ++++++++++++++++++++++
data = container_of(dev, struct sysfs_ioapic_data, dev);
entry = data->entry;
io_apic_write(dev->id, 0, reg_00.raw);
}
spin_unlock_irqrestore(&ioapic_lock, flags);
- ---------------------- for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
+ ++++++++++++++++++++++ for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
ioapic_write_entry(dev->id, i, entry[i]);
return 0;
static int __init ioapic_init_sysfs(void)
{
- ---------------------- struct sys_device * dev;
+ ++++++++++++++++++++++ struct sys_device *dev;
int i, size, error = 0;
error = sysdev_class_register(&ioapic_sysdev_class);
if (error)
return error;
- ---------------------- for (i = 0; i < nr_ioapics; i++ ) {
- ---------------------- size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+ ++++++++++++++++++++++ for (i = 0; i < nr_ioapics; i++) {
+ ++++++++++++++++++++++ size = sizeof(struct sys_device) + nr_ioapic_registers[i]
* sizeof(struct IO_APIC_route_entry);
- ---------------------- mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
+ ++++++++++++++++++++++ mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
if (!mp_ioapic_data[i]) {
printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
continue;
}
- ---------------------- memset(mp_ioapic_data[i], 0, size);
dev = &mp_ioapic_data[i]->dev;
- ---------------------- dev->id = i;
+ ++++++++++++++++++++++ dev->id = i;
dev->cls = &ioapic_sysdev_class;
error = sysdev_register(dev);
if (error) {
msg->address_lo =
MSI_ADDR_BASE_LO |
((INT_DEST_MODE == 0) ?
- ---------------------- MSI_ADDR_DEST_MODE_PHYSICAL:
+ ++++++++++++++++++++++MSI_ADDR_DEST_MODE_PHYSICAL:
MSI_ADDR_DEST_MODE_LOGICAL) |
((INT_DELIVERY_MODE != dest_LowestPrio) ?
MSI_ADDR_REDIRECTION_CPU:
MSI_DATA_TRIGGER_EDGE |
MSI_DATA_LEVEL_ASSERT |
((INT_DELIVERY_MODE != dest_LowestPrio) ?
- ---------------------- MSI_DATA_DELIVERY_FIXED:
+ ++++++++++++++++++++++MSI_DATA_DELIVERY_FIXED:
MSI_DATA_DELIVERY_LOWPRI) |
MSI_DATA_VECTOR(vector);
}
#endif /* CONFIG_HT_IRQ */
/* --------------------------------------------------------------------------
- ---------------------- ACPI-based IOAPIC Configuration
+ ++++++++++++++++++++++ ACPI-based IOAPIC Configuration
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI
- ----------------------int __init io_apic_get_unique_id (int ioapic, int apic_id)
+ ++++++++++++++++++++++int __init io_apic_get_unique_id(int ioapic, int apic_id)
{
union IO_APIC_reg_00 reg_00;
static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
int i = 0;
/*
- ---------------------- * The P4 platform supports up to 256 APIC IDs on two separate APIC
- ---------------------- * buses (one for LAPICs, one for IOAPICs), where predecessors only
+ ++++++++++++++++++++++ * The P4 platform supports up to 256 APIC IDs on two separate APIC
+ ++++++++++++++++++++++ * buses (one for LAPICs, one for IOAPICs), where predecessors only
* supports up to 16 on one shared APIC bus.
- ---------------------- *
+ ++++++++++++++++++++++ *
* TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
* advantage of new APIC bus architecture.
*/
}
/*
- ---------------------- * Every APIC in a system must have a unique ID or we get lots of nice
+ ++++++++++++++++++++++ * Every APIC in a system must have a unique ID or we get lots of nice
* 'stuck on smp_invalidate_needed IPI wait' messages.
*/
if (check_apicid_used(apic_id_map, apic_id)) {
"trying %d\n", ioapic, apic_id, i);
apic_id = i;
- ---------------------- }
+ ++++++++++++++++++++++ }
tmp = apicid_to_cpu_present(apic_id);
physids_or(apic_id_map, apic_id_map, tmp);
}
- ----------------------int __init io_apic_get_version (int ioapic)
+ ++++++++++++++++++++++int __init io_apic_get_version(int ioapic)
{
union IO_APIC_reg_01 reg_01;
unsigned long flags;
}
- ----------------------int __init io_apic_get_redir_entries (int ioapic)
+ ++++++++++++++++++++++int __init io_apic_get_redir_entries(int ioapic)
{
union IO_APIC_reg_01 reg_01;
unsigned long flags;
}
- ----------------------int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
+ ++++++++++++++++++++++int io_apic_set_pci_routing(int ioapic, int pin, int irq, int edge_level, int active_high_low)
{
struct IO_APIC_route_entry entry;
* corresponding device driver registers for this IRQ.
*/
- ---------------------- memset(&entry,0,sizeof(entry));
+ ++++++++++++++++++++++ memset(&entry, 0, sizeof(entry));
entry.delivery_mode = INT_DELIVERY_MODE;
entry.dest_mode = INT_DEST_MODE;
};
/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
- ----------------------struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
+ ++++++++++++++++++++++static struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
[0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, },
[1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, },
[2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, },
static int disable_timer_pin_1 __initdata;
- ----------------------int timer_over_8254 __initdata = 1;
+ ++++++++++++++++++++++int timer_through_8259 __initdata;
/* Where if anywhere is the i8259 connect in external int mode */
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
break;
reg = io_apic_read(entry->apic, 0x10 + pin*2);
/* Is the remote IRR bit set? */
- ---------------------- if ((reg >> 14) & 1) {
+ ++++++++++++++++++++++ if (reg & IO_APIC_REDIR_REMOTE_IRR) {
spin_unlock_irqrestore(&ioapic_lock, flags);
return true;
}
break;
io_apic_write(apic, 0x11 + pin*2, dest);
reg = io_apic_read(apic, 0x10 + pin*2);
- ---------------------- reg &= ~0x000000ff;
+ ++++++++++++++++++++++ reg &= ~IO_APIC_REDIR_VECTOR_MASK;
reg |= vector;
io_apic_modify(apic, reg);
if (!entry->next)
entry->pin = pin;
}
+ ++++++++++++++++++++++/*
+ ++++++++++++++++++++++ * Reroute an IRQ to a different pin.
+ ++++++++++++++++++++++ */
+ ++++++++++++++++++++++static void __init replace_pin_at_irq(unsigned int irq,
+ ++++++++++++++++++++++ int oldapic, int oldpin,
+ ++++++++++++++++++++++ int newapic, int newpin)
+ ++++++++++++++++++++++{
+ ++++++++++++++++++++++ struct irq_pin_list *entry = irq_2_pin + irq;
+ ++++++++++++++++++++++
+ ++++++++++++++++++++++ while (1) {
+ ++++++++++++++++++++++ if (entry->apic == oldapic && entry->pin == oldpin) {
+ ++++++++++++++++++++++ entry->apic = newapic;
+ ++++++++++++++++++++++ entry->pin = newpin;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++ if (!entry->next)
+ ++++++++++++++++++++++ break;
+ ++++++++++++++++++++++ entry = irq_2_pin + entry->next;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++}
+ ++++++++++++++++++++++
#define DO_ACTION(name,R,ACTION, FINAL) \
\
static void name##_IO_APIC_irq (unsigned int irq) \
__DO_ACTION(R, ACTION, FINAL)
- ----------------------DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) )
- ---------------------- /* mask = 1 */
- ----------------------DO_ACTION( __unmask, 0, &= 0xfffeffff, )
- ---------------------- /* mask = 0 */
+ ++++++++++++++++++++++/* mask = 1 */
+ ++++++++++++++++++++++DO_ACTION(__mask, 0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
+ ++++++++++++++++++++++
+ ++++++++++++++++++++++/* mask = 0 */
+ ++++++++++++++++++++++DO_ACTION(__unmask, 0, &= ~IO_APIC_REDIR_MASKED, )
static void mask_IO_APIC_irq (unsigned int irq)
{
}
__setup("disable_timer_pin_1", disable_timer_pin_setup);
- ----------------------static int __init setup_disable_8254_timer(char *s)
- ----------------------{
- ---------------------- timer_over_8254 = -1;
- ---------------------- return 1;
- ----------------------}
- ----------------------static int __init setup_enable_8254_timer(char *s)
- ----------------------{
- ---------------------- timer_over_8254 = 2;
- ---------------------- return 1;
- ----------------------}
- ----------------------
- ----------------------__setup("disable_8254_timer", setup_disable_8254_timer);
- ----------------------__setup("enable_8254_timer", setup_enable_8254_timer);
- ----------------------
/*
* Find the IRQ entry number of a certain pin.
}
/*
- ---------------------- * Set up the 8259A-master output pin as broadcast to all
- ---------------------- * CPUs.
+ ++++++++++++++++++++++ * Set up the timer pin, possibly with the 8259A-master behind.
*/
- ----------------------static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
+ ++++++++++++++++++++++static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
+ ++++++++++++++++++++++ int vector)
{
struct IO_APIC_route_entry entry;
memset(&entry, 0, sizeof(entry));
- ---------------------- disable_8259A_irq(0);
- ----------------------
- ---------------------- /* mask LVT0 */
- ---------------------- apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
- ----------------------
/*
* We use logical delivery to get the timer IRQ
* to the first CPU.
*/
entry.dest_mode = INT_DEST_MODE;
- ---------------------- entry.mask = 0; /* unmask IRQ now */
+ ++++++++++++++++++++++ entry.mask = 1; /* mask IRQ now */
entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
entry.delivery_mode = INT_DELIVERY_MODE;
entry.polarity = 0;
/*
* The timer IRQ doesn't have to know that behind the
- ---------------------- * scene we have a 8259A-master in AEOI mode ...
+ ++++++++++++++++++++++ * scene we may have a 8259A-master in AEOI mode ...
*/
set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
* Add it to the IO-APIC irq-routing table:
*/
ioapic_write_entry(apic, pin, entry);
- ----------------------
- ---------------------- enable_8259A_irq(0);
}
void __apicdebuginit print_IO_APIC(void)
printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
smp_processor_id(), hard_smp_processor_id());
+++++ ++++++++++++++++++ v = apic_read(APIC_ID);
printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
v = apic_read(APIC_LVR);
printk(KERN_INFO "... APIC VERSION: %08x\n", v);
struct irq_cfg *cfg = irq_cfg + 0;
int apic1, pin1, apic2, pin2;
unsigned long flags;
+ ++++++++++++++++++++++ int no_pin1 = 0;
local_irq_save(flags);
assign_irq_vector(0, TARGET_CPUS);
/*
- ---------------------- * Subtle, code in do_timer_interrupt() expects an AEOI
- ---------------------- * mode for the 8259A whenever interrupts are routed
- ---------------------- * through I/O APICs. Also IRQ0 has to be enabled in
- ---------------------- * the 8259A which implies the virtual wire has to be
- ---------------------- * disabled in the local APIC.
+ ++++++++++++++++++++++ * As IRQ0 is to be enabled in the 8259A, the virtual
+ ++++++++++++++++++++++ * wire has to be disabled in the local APIC.
*/
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1);
- ---------------------- if (timer_over_8254 > 0)
- ---------------------- enable_8259A_irq(0);
pin1 = find_isa_irq_pin(0, mp_INT);
apic1 = find_isa_irq_apic(0, mp_INT);
apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
cfg->vector, apic1, pin1, apic2, pin2);
+ ++++++++++++++++++++++ /*
+ ++++++++++++++++++++++ * Some BIOS writers are clueless and report the ExtINTA
+ ++++++++++++++++++++++ * I/O APIC input from the cascaded 8259A as the timer
+ ++++++++++++++++++++++ * interrupt input. So just in case, if only one pin
+ ++++++++++++++++++++++ * was found above, try it both directly and through the
+ ++++++++++++++++++++++ * 8259A.
+ ++++++++++++++++++++++ */
+ ++++++++++++++++++++++ if (pin1 == -1) {
+ ++++++++++++++++++++++ pin1 = pin2;
+ ++++++++++++++++++++++ apic1 = apic2;
+ ++++++++++++++++++++++ no_pin1 = 1;
+ ++++++++++++++++++++++ } else if (pin2 == -1) {
+ ++++++++++++++++++++++ pin2 = pin1;
+ ++++++++++++++++++++++ apic2 = apic1;
+ ++++++++++++++++++++++ }
+ ++++++++++++++++++++++
+ ++++++++++++++++++++++ replace_pin_at_irq(0, 0, 0, apic1, pin1);
+ ++++++++++++++++++++++ apic1 = 0;
+ ++++++++++++++++++++++ pin1 = 0;
+ ++++++++++++++++++++++ setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
+ ++++++++++++++++++++++
if (pin1 != -1) {
/*
* Ok, does IRQ0 through the IOAPIC work?
*/
+ ++++++++++++++++++++++ if (no_pin1) {
+ ++++++++++++++++++++++ add_pin_to_irq(0, apic1, pin1);
+ ++++++++++++++++++++++ setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
+ ++++++++++++++++++++++ }
unmask_IO_APIC_irq(0);
if (!no_timer_check && timer_irq_works()) {
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
- ---------------------- disable_8259A_irq(0);
setup_nmi();
enable_8259A_irq(0);
}
goto out;
}
clear_IO_APIC_pin(apic1, pin1);
- ---------------------- apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
- ---------------------- "connected to IO-APIC\n");
- ---------------------- }
+ ++++++++++++++++++++++ if (!no_pin1)
+ ++++++++++++++++++++++ apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: "
+ ++++++++++++++++++++++ "8254 timer not connected to IO-APIC\n");
- ---------------------- apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
- ---------------------- "through the 8259A ... ");
- ---------------------- if (pin2 != -1) {
+ ++++++++++++++++++++++ apic_printk(APIC_VERBOSE,KERN_INFO
+ ++++++++++++++++++++++ "...trying to set up timer (IRQ0) "
+ ++++++++++++++++++++++ "through the 8259A ... ");
apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
apic2, pin2);
/*
* legacy devices should be connected to IO APIC #0
*/
- ---------------------- setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector);
+ ++++++++++++++++++++++ replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
+ ++++++++++++++++++++++ setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
+ ++++++++++++++++++++++ unmask_IO_APIC_irq(0);
+ ++++++++++++++++++++++ enable_8259A_irq(0);
if (timer_irq_works()) {
apic_printk(APIC_VERBOSE," works.\n");
+ ++++++++++++++++++++++ timer_through_8259 = 1;
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
+ ++++++++++++++++++++++ disable_8259A_irq(0);
setup_nmi();
+ ++++++++++++++++++++++ enable_8259A_irq(0);
}
goto out;
}
/*
* Cleanup, just in case ...
*/
+ ++++++++++++++++++++++ disable_8259A_irq(0);
clear_IO_APIC_pin(apic2, pin2);
+ ++++++++++++++++++++++ apic_printk(APIC_VERBOSE," failed.\n");
}
- ---------------------- apic_printk(APIC_VERBOSE," failed.\n");
if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
- ---------------------- nmi_watchdog = 0;
+ ++++++++++++++++++++++ nmi_watchdog = NMI_NONE;
}
apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
- ---------------------- disable_8259A_irq(0);
irq_desc[0].chip = &lapic_irq_type;
apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */
enable_8259A_irq(0);
apic_printk(APIC_VERBOSE," works.\n");
goto out;
}
+ ++++++++++++++++++++++ disable_8259A_irq(0);
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
apic_printk(APIC_VERBOSE," failed.\n");
if (end_pfn <= MAX_DMA32_PFN)
return;
+++++++++ ++++++++++++++ /*
+++++++++ ++++++++++++++ * check aperture_64.c allocate_aperture() for reason about
+++++++++ ++++++++++++++ * using 512M as goal
+++++++++ ++++++++++++++ */
align = 64ULL<<20;
size = round_up(dma32_bootmem_size, align);
dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
--------- -------------- __pa(MAX_DMA_ADDRESS));
+++++++++ ++++++++++++++ 512ULL<<20);
if (dma32_bootmem_ptr)
dma32_bootmem_size = size;
else
}
static void __init dma32_free_bootmem(void)
{
--------- -------------- int node;
if (end_pfn <= MAX_DMA32_PFN)
return;
if (!dma32_bootmem_ptr)
return;
--------- -------------- for_each_online_node(node)
--------- -------------- free_bootmem_node(NODE_DATA(node), __pa(dma32_bootmem_ptr),
--------- -------------- dma32_bootmem_size);
+++++++++ ++++++++++++++ free_bootmem(__pa(dma32_bootmem_ptr), dma32_bootmem_size);
dma32_bootmem_ptr = NULL;
dma32_bootmem_size = 0;
EXPORT_SYMBOL(dma_supported);
/* Allocate DMA memory on node near device */
----- ------------------noinline struct page *
+++++ ++++++++++++++++++static noinline struct page *
dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
{
int node;
struct page *page;
unsigned long dma_mask = 0;
dma_addr_t bus;
+ +++ + + + + + int noretry = 0;
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
return memory;
- - - if (!dev)
+ + + if (!dev) {
dev = &fallback_dev;
+ + + gfp |= GFP_DMA;
+ + + }
dma_mask = dev->coherent_dma_mask;
if (dma_mask == 0)
- - - dma_mask = DMA_32BIT_MASK;
+ + + dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK;
/* Device not DMA able */
if (dev->dma_mask == NULL)
return NULL;
- --- - - - - - /* Don't invoke OOM killer */
- --- - - - - - gfp |= __GFP_NORETRY;
+ +++ + + + + + /* Don't invoke OOM killer or retry in lower 16MB DMA zone */
+ +++ + + + + + if (gfp & __GFP_DMA)
+ +++ + + + + + noretry = 1;
#ifdef CONFIG_X86_64
/* Why <=? Even when the mask is smaller than 4GB it is often
larger than 16MB and in this case we have a chance of
finding fitting memory in the next higher zone first. If
not retry with true GFP_DMA. -AK */
- -- - - - if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA))
- - - if (dma_mask <= DMA_32BIT_MASK)
+ +++ + + + + + if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
gfp |= GFP_DMA32;
+ +++ + + + + + if (dma_mask < DMA_32BIT_MASK)
+ +++ + + + + + noretry = 1;
+ +++ + + + + + }
#endif
again:
- --- - - - - - page = dma_alloc_pages(dev, gfp, get_order(size));
+ +++ + + + + + page = dma_alloc_pages(dev,
+ +++ + + + + + noretry ? gfp | __GFP_NORETRY : gfp, get_order(size));
if (page == NULL)
return NULL;
#include <asm/topology.h>
#include <asm/trampoline.h>
#include <asm/pat.h>
+++++ + ++++++++++++++++#include <asm/mmconfig.h>
#include <mach_apic.h>
#ifdef CONFIG_PARAVIRT
#define ARCH_SETUP
#endif
+++++++ ++++++++++++++++#include "cpu/cpu.h"
+++++++ ++++++++++++++++
/*
* Machine setup..
*/
unsigned long saved_video_mode;
------- ----------------int force_mwait __cpuinitdata;
------- ----------------
/*
* Early DMI memory
*/
extern int root_mountflags;
----- ------------------char __initdata command_line[COMMAND_LINE_SIZE];
+++++ ++++++++++++++++++static char __initdata command_line[COMMAND_LINE_SIZE];
static struct resource standard_io_resources[] = {
{ .name = "dma1", .start = 0x00, .end = 0x1f,
.flags = IORESOURCE_RAM,
};
+++++++ ++++++++++++++++static void __init early_cpu_init(void);
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
#ifdef CONFIG_PROC_VMCORE
}
}
----- - ----------------#ifdef CONFIG_PCI_MMCONFIG
----- - ----------------extern void __cpuinit fam10h_check_enable_mmcfg(void);
----- - ----------------extern void __init check_enable_amd_mmconf_dmi(void);
----- - ----------------#else
----- - ----------------void __cpuinit fam10h_check_enable_mmcfg(void)
----- - ----------------{
----- - ----------------}
----- - ----------------void __init check_enable_amd_mmconf_dmi(void)
----- - ----------------{
----- - ----------------}
----- - ----------------#endif
----- - ----------------
/*
* setup_arch - architecture-specific boot-time initializations
*
bss_resource.start = virt_to_phys(&__bss_start);
bss_resource.end = virt_to_phys(&__bss_stop)-1;
+++++++ ++++++++++++++++ early_cpu_init();
early_identify_cpu(&boot_cpu_data);
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
check_enable_amd_mmconf_dmi();
}
------- ----------------static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
+++++++ ++++++++++++++++struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+++++++ ++++++++++++++++
+++++++ ++++++++++++++++static void __cpuinit default_init(struct cpuinfo_x86 *c)
+++++++ ++++++++++++++++{
+++++++ ++++++++++++++++ display_cacheinfo(c);
+++++++ ++++++++++++++++}
+++++++ ++++++++++++++++
+++++++ ++++++++++++++++static struct cpu_dev __cpuinitdata default_cpu = {
+++++++ ++++++++++++++++ .c_init = default_init,
+++++++ ++++++++++++++++ .c_vendor = "Unknown",
+++++++ ++++++++++++++++};
+++++++ ++++++++++++++++static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+++++++ ++++++++++++++++
+++++++ ++++++++++++++++int __cpuinit get_model_name(struct cpuinfo_x86 *c)
{
unsigned int *v;
}
------- ----------------static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+++++++ ++++++++++++++++void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int n, dummy, eax, ebx, ecx, edx;
}
}
------- ----------------#ifdef CONFIG_NUMA
------- ----------------static int __cpuinit nearby_node(int apicid)
------- ----------------{
------- ---------------- int i, node;
------- ----------------
------- ---------------- for (i = apicid - 1; i >= 0; i--) {
------- ---------------- node = apicid_to_node[i];
------- ---------------- if (node != NUMA_NO_NODE && node_online(node))
------- ---------------- return node;
------- ---------------- }
------- ---------------- for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
------- ---------------- node = apicid_to_node[i];
------- ---------------- if (node != NUMA_NO_NODE && node_online(node))
------- ---------------- return node;
------- ---------------- }
------- ---------------- return first_node(node_online_map); /* Shouldn't happen */
------- ----------------}
------- ----------------#endif
------- ----------------
------- ----------------/*
------- ---------------- * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
------- ---------------- * Assumes number of cores is a power of two.
------- ---------------- */
------- ----------------static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
------- ----------------{
------- ----------------#ifdef CONFIG_SMP
------- ---------------- unsigned bits;
------- ----------------#ifdef CONFIG_NUMA
------- ---------------- int cpu = smp_processor_id();
------- ---------------- int node = 0;
------- ---------------- unsigned apicid = hard_smp_processor_id();
------- ----------------#endif
------- ---------------- bits = c->x86_coreid_bits;
------- ----------------
------- ---------------- /* Low order bits define the core id (index of core in socket) */
------- ---------------- c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
------- ---------------- /* Convert the initial APIC ID into the socket ID */
------- ---------------- c->phys_proc_id = c->initial_apicid >> bits;
------- ----------------
------- ----------------#ifdef CONFIG_NUMA
------- ---------------- node = c->phys_proc_id;
------- ---------------- if (apicid_to_node[apicid] != NUMA_NO_NODE)
------- ---------------- node = apicid_to_node[apicid];
------- ---------------- if (!node_online(node)) {
------- ---------------- /* Two possibilities here:
------- ---------------- - The CPU is missing memory and no node was created.
------- ---------------- In that case try picking one from a nearby CPU
------- ---------------- - The APIC IDs differ from the HyperTransport node IDs
------- ---------------- which the K8 northbridge parsing fills in.
------- ---------------- Assume they are all increased by a constant offset,
------- ---------------- but in the same order as the HT nodeids.
------- ---------------- If that doesn't result in a usable node fall back to the
------- ---------------- path for the previous case. */
------- ----------------
------- ---------------- int ht_nodeid = c->initial_apicid;
------- ----------------
------- ---------------- if (ht_nodeid >= 0 &&
------- ---------------- apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
------- ---------------- node = apicid_to_node[ht_nodeid];
------- ---------------- /* Pick a nearby node */
------- ---------------- if (!node_online(node))
------- ---------------- node = nearby_node(apicid);
------- ---------------- }
------- ---------------- numa_set_node(cpu, node);
------- ----------------
------- ---------------- printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
------- ----------------#endif
------- ----------------#endif
------- ----------------}
------- ----------------
------- ----------------static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
------- ----------------{
------- ----------------#ifdef CONFIG_SMP
------- ---------------- unsigned bits, ecx;
------- ----------------
------- ---------------- /* Multi core CPU? */
------- ---------------- if (c->extended_cpuid_level < 0x80000008)
------- ---------------- return;
------- ----------------
------- ---------------- ecx = cpuid_ecx(0x80000008);
------- ----------------
------- ---------------- c->x86_max_cores = (ecx & 0xff) + 1;
------- ----------------
------- ---------------- /* CPU telling us the core id bits shift? */
------- ---------------- bits = (ecx >> 12) & 0xF;
------- ----------------
------- ---------------- /* Otherwise recompute */
------- ---------------- if (bits == 0) {
------- ---------------- while ((1 << bits) < c->x86_max_cores)
------- ---------------- bits++;
------- ---------------- }
------- ----------------
------- ---------------- c->x86_coreid_bits = bits;
------- ----------------
------- ----------------#endif
------- ----------------}
------- ----------------
------- ----------------#define ENABLE_C1E_MASK 0x18000000
------- ----------------#define CPUID_PROCESSOR_SIGNATURE 1
------- ----------------#define CPUID_XFAM 0x0ff00000
------- ----------------#define CPUID_XFAM_K8 0x00000000
------- ----------------#define CPUID_XFAM_10H 0x00100000
------- ----------------#define CPUID_XFAM_11H 0x00200000
------- ----------------#define CPUID_XMOD 0x000f0000
------- ----------------#define CPUID_XMOD_REV_F 0x00040000
------- ----------------
------- ----------------/* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
------- ----------------static __cpuinit int amd_apic_timer_broken(void)
------- ----------------{
------- ---------------- u32 lo, hi, eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
------- ----------------
------- ---------------- switch (eax & CPUID_XFAM) {
------- ---------------- case CPUID_XFAM_K8:
------- ---------------- if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
------- ---------------- break;
------- ---------------- case CPUID_XFAM_10H:
------- ---------------- case CPUID_XFAM_11H:
------- ---------------- rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
------- ---------------- if (lo & ENABLE_C1E_MASK)
------- ---------------- return 1;
------- ---------------- break;
------- ---------------- default:
------- ---------------- /* err on the side of caution */
------- ---------------- return 1;
------- ---------------- }
------- ---------------- return 0;
------- ----------------}
------- ----------------
------- ----------------static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
------- ----------------{
------- ---------------- early_init_amd_mc(c);
------- ----------------
------- ---------------- /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
------- ---------------- if (c->x86_power & (1<<8))
------- ---------------- set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
------- ----------------}
------- ----------------
------- ----------------static void __cpuinit init_amd(struct cpuinfo_x86 *c)
------- ----------------{
------- ---------------- unsigned level;
------- ----------------
------- ----------------#ifdef CONFIG_SMP
------- ---------------- unsigned long value;
------- ----------------
------- ---------------- /*
------- ---------------- * Disable TLB flush filter by setting HWCR.FFDIS on K8
------- ---------------- * bit 6 of msr C001_0015
------- ---------------- *
------- ---------------- * Errata 63 for SH-B3 steppings
------- ---------------- * Errata 122 for all steppings (F+ have it disabled by default)
------- ---------------- */
------- ---------------- if (c->x86 == 15) {
------- ---------------- rdmsrl(MSR_K8_HWCR, value);
------- ---------------- value |= 1 << 6;
------- ---------------- wrmsrl(MSR_K8_HWCR, value);
------- ---------------- }
------- ----------------#endif
------- ----------------
------- ---------------- /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
------- ---------------- 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
------- ---------------- clear_cpu_cap(c, 0*32+31);
------- ----------------
------- ---------------- /* On C+ stepping K8 rep microcode works well for copy/memset */
------- ---------------- level = cpuid_eax(1);
------- ---------------- if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) ||
------- ---------------- level >= 0x0f58))
------- ---------------- set_cpu_cap(c, X86_FEATURE_REP_GOOD);
------- ---------------- if (c->x86 == 0x10 || c->x86 == 0x11)
------- ---------------- set_cpu_cap(c, X86_FEATURE_REP_GOOD);
------- ----------------
------- ---------------- /* Enable workaround for FXSAVE leak */
------- ---------------- if (c->x86 >= 6)
------- ---------------- set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
------- ----------------
------- ---------------- level = get_model_name(c);
------- ---------------- if (!level) {
------- ---------------- switch (c->x86) {
------- ---------------- case 15:
------- ---------------- /* Should distinguish Models here, but this is only
------- ---------------- a fallback anyways. */
------- ---------------- strcpy(c->x86_model_id, "Hammer");
------- ---------------- break;
------- ---------------- }
------- ---------------- }
------- ---------------- display_cacheinfo(c);
------- ----------------
------- ---------------- /* Multi core CPU? */
------- ---------------- if (c->extended_cpuid_level >= 0x80000008)
------- ---------------- amd_detect_cmp(c);
------- ----------------
------- ---------------- if (c->extended_cpuid_level >= 0x80000006 &&
------- ---------------- (cpuid_edx(0x80000006) & 0xf000))
------- ---------------- num_cache_leaves = 4;
------- ---------------- else
------- ---------------- num_cache_leaves = 3;
------- ----------------
------- ---------------- if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
------- ---------------- set_cpu_cap(c, X86_FEATURE_K8);
------- ----------------
------- ---------------- /* MFENCE stops RDTSC speculation */
------- ---------------- set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
------- ----------------
------- ---------------- if (c->x86 == 0x10)
------- ---------------- fam10h_check_enable_mmcfg();
------- ----------------
------- ---------------- if (amd_apic_timer_broken())
------- ---------------- disable_apic_timer = 1;
------- ----------------
------- ---------------- if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
------- ---------------- unsigned long long tseg;
------- ----------------
------- ---------------- /*
------- ---------------- * Split up direct mapping around the TSEG SMM area.
------- ---------------- * Don't do it for gbpages because there seems very little
------- ---------------- * benefit in doing so.
------- ---------------- */
------- ---------------- if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) &&
------- ---------------- (tseg >> PMD_SHIFT) < (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT)))
------- ---------------- set_memory_4k((unsigned long)__va(tseg), 1);
------- ---------------- }
------- ----------------}
------- ----------------
void __cpuinit detect_ht(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
#endif
}
------- ----------------/*
------- ---------------- * find out the number of processor cores on the die
------- ---------------- */
------- ----------------static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
------- ----------------{
------- ---------------- unsigned int eax, t;
------- ----------------
------- ---------------- if (c->cpuid_level < 4)
------- ---------------- return 1;
------- ----------------
------- ---------------- cpuid_count(4, 0, &eax, &t, &t, &t);
------- ----------------
------- ---------------- if (eax & 0x1f)
------- ---------------- return ((eax >> 26) + 1);
------- ---------------- else
------- ---------------- return 1;
------- ----------------}
------- ----------------
------- ----------------static void __cpuinit srat_detect_node(void)
------- ----------------{
------- ----------------#ifdef CONFIG_NUMA
------- ---------------- unsigned node;
------- ---------------- int cpu = smp_processor_id();
------- ---------------- int apicid = hard_smp_processor_id();
------- ----------------
------- ---------------- /* Don't do the funky fallback heuristics the AMD version employs
------- ---------------- for now. */
------- ---------------- node = apicid_to_node[apicid];
------- ---------------- if (node == NUMA_NO_NODE || !node_online(node))
------- ---------------- node = first_node(node_online_map);
------- ---------------- numa_set_node(cpu, node);
------- ----------------
------- ---------------- printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
------- ----------------#endif
------- ----------------}
------- ----------------
------- ----------------static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
------- ----------------{
------- ---------------- if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
------- ---------------- (c->x86 == 0x6 && c->x86_model >= 0x0e))
------- ---------------- set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
------- ----------------}
------- ----------------
------- ----------------static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+++++++ ++++++++++++++++static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
{
------- ---------------- /* Cache sizes */
------- ---------------- unsigned n;
------- ----------------
------- ---------------- init_intel_cacheinfo(c);
------- ---------------- if (c->cpuid_level > 9) {
------- ---------------- unsigned eax = cpuid_eax(10);
------- ---------------- /* Check for version and the number of counters */
------- ---------------- if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
------- ---------------- set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
- }
-
- if (cpu_has_ds) {
- unsigned int l1, l2;
- rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
- if (!(l1 & (1<<11)))
- set_cpu_cap(c, X86_FEATURE_BTS);
- if (!(l1 & (1<<12)))
- set_cpu_cap(c, X86_FEATURE_PEBS);
+++++++ ++++++++++++++++ char *v = c->x86_vendor_id;
+++++++ ++++++++++++++++ int i;
+++++++ ++++++++++++++++ static int printed;
+++++++ ++++++++++++++++
+++++++ ++++++++++++++++ for (i = 0; i < X86_VENDOR_NUM; i++) {
+++++++ ++++++++++++++++ if (cpu_devs[i]) {
+++++++ ++++++++++++++++ if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
+++++++ ++++++++++++++++ (cpu_devs[i]->c_ident[1] &&
+++++++ ++++++++++++++++ !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+++++++ ++++++++++++++++ c->x86_vendor = i;
+++++++ ++++++++++++++++ this_cpu = cpu_devs[i];
+++++++ ++++++++++++++++ return;
+++++++ ++++++++++++++++ }
+++++++ ++++++++++++++++ }
}
------- ----------------
----- - ---------------- if (cpu_has_ds) {
----- - ---------------- unsigned int l1, l2;
----- - ---------------- rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
----- - ---------------- if (!(l1 & (1<<11)))
----- - ---------------- set_cpu_cap(c, X86_FEATURE_BTS);
----- - ---------------- if (!(l1 & (1<<12)))
----- - ---------------- set_cpu_cap(c, X86_FEATURE_PEBS);
-
- if (cpu_has_bts)
- ds_init_intel(c);
-
- n = c->extended_cpuid_level;
- if (n >= 0x80000008) {
- unsigned eax = cpuid_eax(0x80000008);
- c->x86_virt_bits = (eax >> 8) & 0xff;
- c->x86_phys_bits = eax & 0xff;
- /* CPUID workaround for Intel 0F34 CPU */
- if (c->x86_vendor == X86_VENDOR_INTEL &&
- c->x86 == 0xF && c->x86_model == 0x3 &&
- c->x86_mask == 0x4)
- c->x86_phys_bits = 36;
+++++++ ++++++++++++++++ if (!printed) {
+++++++ ++++++++++++++++ printed++;
+++++++ ++++++++++++++++ printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
+++++++ ++++++++++++++++ printk(KERN_ERR "CPU: Your system may be unstable.\n");
}
----- - ----------------
----- - ----------------
----- - ---------------- if (cpu_has_bts)
----- - ---------------- ds_init_intel(c);
----- - ----------------
----- - ---------------- n = c->extended_cpuid_level;
----- - ---------------- if (n >= 0x80000008) {
----- - ---------------- unsigned eax = cpuid_eax(0x80000008);
----- - ---------------- c->x86_virt_bits = (eax >> 8) & 0xff;
----- - ---------------- c->x86_phys_bits = eax & 0xff;
----- - ---------------- /* CPUID workaround for Intel 0F34 CPU */
----- - ---------------- if (c->x86_vendor == X86_VENDOR_INTEL &&
----- - ---------------- c->x86 == 0xF && c->x86_model == 0x3 &&
----- - ---------------- c->x86_mask == 0x4)
----- - ---------------- c->x86_phys_bits = 36;
----- - ---------------- }
------- ----------------
------- ---------------- if (c->x86 == 15)
------- ---------------- c->x86_cache_alignment = c->x86_clflush_size * 2;
------- ---------------- if (c->x86 == 6)
------- ---------------- set_cpu_cap(c, X86_FEATURE_REP_GOOD);
------- ---------------- set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
------- ---------------- c->x86_max_cores = intel_num_cpu_cores(c);
------- ----------------
------- ---------------- srat_detect_node();
------- ----------------}
------- ----------------
------- ----------------static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
------- ----------------{
------- ---------------- if (c->x86 == 0x6 && c->x86_model >= 0xf)
---- -- -- ------------ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
- - - set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+++++++ ++++++++++++++++ c->x86_vendor = X86_VENDOR_UNKNOWN;
}
------- ----------------static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
+++++++ ++++++++++++++++static void __init early_cpu_support_print(void)
{
------- ---------------- /* Cache sizes */
------- ---------------- unsigned n;
------- ----------------
------- ---------------- n = c->extended_cpuid_level;
------- ---------------- if (n >= 0x80000008) {
------- ---------------- unsigned eax = cpuid_eax(0x80000008);
------- ---------------- c->x86_virt_bits = (eax >> 8) & 0xff;
------- ---------------- c->x86_phys_bits = eax & 0xff;
------- ---------------- }
------- ----------------
------- ---------------- if (c->x86 == 0x6 && c->x86_model >= 0xf) {
------- ---------------- c->x86_cache_alignment = c->x86_clflush_size * 2;
------- ---------------- set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
------- ---------------- set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+++++++ ++++++++++++++++ int i,j;
+++++++ ++++++++++++++++ struct cpu_dev *cpu_devx;
+++++++ ++++++++++++++++
+++++++ ++++++++++++++++ printk("KERNEL supported cpus:\n");
+++++++ ++++++++++++++++ for (i = 0; i < X86_VENDOR_NUM; i++) {
+++++++ ++++++++++++++++ cpu_devx = cpu_devs[i];
+++++++ ++++++++++++++++ if (!cpu_devx)
+++++++ ++++++++++++++++ continue;
+++++++ ++++++++++++++++ for (j = 0; j < 2; j++) {
+++++++ ++++++++++++++++ if (!cpu_devx->c_ident[j])
+++++++ ++++++++++++++++ continue;
+++++++ ++++++++++++++++ printk(" %s %s\n", cpu_devx->c_vendor,
+++++++ ++++++++++++++++ cpu_devx->c_ident[j]);
+++++++ ++++++++++++++++ }
}
------- ---------------- set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
}
------- ----------------static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+++++++ ++++++++++++++++static void __init early_cpu_init(void)
{
------- ---------------- char *v = c->x86_vendor_id;
+++++++ ++++++++++++++++ struct cpu_vendor_dev *cvdev;
------- ---------------- if (!strcmp(v, "AuthenticAMD"))
------- ---------------- c->x86_vendor = X86_VENDOR_AMD;
------- ---------------- else if (!strcmp(v, "GenuineIntel"))
------- ---------------- c->x86_vendor = X86_VENDOR_INTEL;
------- ---------------- else if (!strcmp(v, "CentaurHauls"))
------- ---------------- c->x86_vendor = X86_VENDOR_CENTAUR;
------- ---------------- else
------- ---------------- c->x86_vendor = X86_VENDOR_UNKNOWN;
+++++++ ++++++++++++++++ for (cvdev = __x86cpuvendor_start ;
+++++++ ++++++++++++++++ cvdev < __x86cpuvendor_end ;
+++++++ ++++++++++++++++ cvdev++)
+++++++ ++++++++++++++++ cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
+++++++ ++++++++++++++++ early_cpu_support_print();
}
/* Do some early cpuid on the boot CPU to get some parameter that are
if (c->extended_cpuid_level >= 0x80000007)
c->x86_power = cpuid_edx(0x80000007);
------- ---------------- switch (c->x86_vendor) {
------- ---------------- case X86_VENDOR_AMD:
------- ---------------- early_init_amd(c);
------- ---------------- break;
------- ---------------- case X86_VENDOR_INTEL:
------- ---------------- early_init_intel(c);
------- ---------------- break;
------- ---------------- case X86_VENDOR_CENTAUR:
------- ---------------- early_init_centaur(c);
------- ---------------- break;
------- ---------------- }
+++++++ ++++++++++++++++ if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
+++++++ ++++++++++++++++ cpu_devs[c->x86_vendor]->c_early_init)
+++++++ ++++++++++++++++ cpu_devs[c->x86_vendor]->c_early_init(c);
validate_pat_support(c);
}
* At the end of this section, c->x86_capability better
* indicate the features this CPU genuinely supports!
*/
------- ---------------- switch (c->x86_vendor) {
------- ---------------- case X86_VENDOR_AMD:
------- ---------------- init_amd(c);
------- ---------------- break;
------- ----------------
------- ---------------- case X86_VENDOR_INTEL:
------- ---------------- init_intel(c);
------- ---------------- break;
------- ----------------
------- ---------------- case X86_VENDOR_CENTAUR:
------- ---------------- init_centaur(c);
------- ---------------- break;
------- ----------------
------- ---------------- case X86_VENDOR_UNKNOWN:
------- ---------------- default:
------- ---------------- display_cacheinfo(c);
------- ---------------- break;
------- ---------------- }
+++++++ ++++++++++++++++ if (this_cpu->c_init)
+++++++ ++++++++++++++++ this_cpu->c_init(c);
detect_ht(c);
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/mtrr.h>
----- ------------------#include <asm/nmi.h>
#include <asm/vmi.h>
#include <asm/genapic.h>
#include <linux/mc146818rtc.h>
#ifdef CONFIG_X86_32
u8 apicid_2_node[MAX_APICID];
+ + + static int low_mappings;
#endif
/* State of each CPU */
enable_8259A_irq(0);
}
+ + + #ifdef CONFIG_X86_32
+ + + while (low_mappings)
+ + + cpu_relax();
+ + + __flush_tlb_all();
+ + + #endif
+ + +
/* This must be done before setting cpu_online_map */
set_cpu_sibling_map(raw_smp_processor_id());
wmb();
#endif
cpu_clear(cpu, cpu_callout_map); /* was set by do_boot_cpu() */
cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
- ---- ---------------- cpu_clear(cpu, cpu_possible_map);
cpu_clear(cpu, cpu_present_map);
per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
}
#ifdef CONFIG_X86_32
/* init low mem mapping */
clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
- - - min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
+ + + min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
flush_tlb_all();
- - - #endif
+ + + low_mappings = 1;
+ + +
+ + + err = do_boot_cpu(apicid, cpu);
+ + + zap_low_mappings();
+ + + low_mappings = 0;
+ + + #else
err = do_boot_cpu(apicid, cpu);
- - - if (err < 0) {
+ + + #endif
+ + + if (err) {
Dprintk("do_boot_cpu failed %d\n", err);
- - - return err;
+ + + return -EIO;
}
/*
* If SMP should be disabled, then really disable it!
*/
if (!max_cpus) {
- ---------------------- printk(KERN_INFO "SMP mode deactivated,"
- ---------------------- "forcing use of dummy APIC emulation.\n");
+ ++++++++++++++++++++++ printk(KERN_INFO "SMP mode deactivated.\n");
smpboot_clear_io_apic();
+ ++++++++++++++++++++++
+ ++++++++++++++++++++++ localise_nmi_watchdog();
+ ++++++++++++++++++++++
#ifdef CONFIG_X86_32
connect_bsp_APIC();
#endif
*/
void __init native_smp_prepare_cpus(unsigned int max_cpus)
{
+ +++ + + + + + preempt_disable();
nmi_watchdog_default();
smp_cpu_index_default();
current_cpu_data = boot_cpu_data;
if (smp_sanity_check(max_cpus) < 0) {
printk(KERN_INFO "SMP disabled\n");
disable_smp();
- --- - - - - - return;
+ +++ + + + + + goto out;
}
preempt_disable();
printk(KERN_INFO "CPU%d: ", 0);
print_cpu_info(&cpu_data(0));
setup_boot_clock();
+ +++ + + + + + out:
+ +++ + + + + + preempt_enable();
}
/*
* Early setup to make printk work.
setup_ioapic_dest();
#endif
check_nmi_watchdog();
- - - #ifdef CONFIG_X86_32
- - - zap_low_mappings();
- - - #endif
}
#ifdef CONFIG_HOTPLUG_CPU
RODATA
------------------- ---- . = ALIGN(4);
------------------- ---- .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
------------------- ---- __tracedata_start = .;
------------------- ---- *(.tracedata)
------------------- ---- __tracedata_end = .;
------------------- ---- }
------------------- ----
. = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */
/* Data */
.data : AT(ADDR(.data) - LOAD_OFFSET) {
*(.con_initcall.init)
}
__con_initcall_end = .;
+++++++ ++++++++++++++++ . = ALIGN(16);
__x86cpuvendor_start = .;
.x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) {
*(.x86cpuvendor.init)
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
++++++ +++++++++++++++++ unsigned pages_2m = 0, pages_4k = 0;
pgd_idx = pgd_index(PAGE_OFFSET);
pgd = pgd_base + pgd_idx;
is_kernel_text(addr2))
prot = PAGE_KERNEL_LARGE_EXEC;
++++++ +++++++++++++++++ pages_2m++;
set_pmd(pmd, pfn_pmd(pfn, prot));
pfn += PTRS_PER_PTE;
if (is_kernel_text(addr))
prot = PAGE_KERNEL_EXEC;
++++++ +++++++++++++++++ pages_4k++;
set_pte(pte, pfn_pte(pfn, prot));
}
max_pfn_mapped = pfn;
}
}
++++++ +++++++++++++++++ update_page_count(PG_LEVEL_2M, pages_2m);
++++++ +++++++++++++++++ update_page_count(PG_LEVEL_4K, pages_4k);
}
static inline int page_kills_ppro(unsigned long pagenr)
{
int i;
- - - save_pg_dir();
- - -
/*
* Zap initial low-memory mappings.
*
#endif
bad_ppro = ppro_with_ram_bug();
----- ------------------#ifdef CONFIG_HIGHMEM
----- ------------------ /* check that fixmap and pkmap do not overlap */
----- ------------------ if (PKMAP_BASE + LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
----- ------------------ printk(KERN_ERR
----- ------------------ "fixmap and kmap areas overlap - this will crash\n");
----- ------------------ printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
----- ------------------ PKMAP_BASE, PKMAP_BASE + LAST_PKMAP*PAGE_SIZE,
----- ------------------ FIXADDR_START);
----- ------------------ BUG();
----- ------------------ }
----- ------------------#endif
/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem();
(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
);
----- ------------------#if 1 /* double-sanity-check paranoia */
printk(KERN_INFO "virtual kernel memory layout:\n"
" fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
#ifdef CONFIG_HIGHMEM
#endif
BUG_ON(VMALLOC_START > VMALLOC_END);
BUG_ON((unsigned long)high_memory > VMALLOC_START);
----- ------------------#endif /* double-sanity-check paranoia */
if (boot_cpu_data.wp_works_ok < 0)
test_wp_bit();
cpa_init();
- - -
- - - /*
- - - * Subtle. SMP is doing it's boot stuff late (because it has to
- - - * fork idle threads) - but it also needs low mappings for the
- - - * protected-mode entry to work. We zap these entries only after
- - - * the WP-bit has been tested.
- - - */
- - - #ifndef CONFIG_SMP
+ + + save_pg_dir();
zap_low_mappings();
- - - #endif
}
#ifdef CONFIG_MEMORY_HOTPLUG
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/init.h>
+++++ ++++++++++++++++++#include <linux/initrd.h>
#include <linux/pagemap.h>
#include <linux/bootmem.h>
#include <linux/proc_fs.h>
return ptr;
}
- ---- ----------------static void
+ ++++ ++++++++++++++++static __init void
set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
{
pgd_t *pgd;
pmd_t *last_pmd = pmd + PTRS_PER_PMD;
for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
- --- - - - - - if (!pmd_present(*pmd))
+ +++ + + + + + if (pmd_none(*pmd))
continue;
if (vaddr < (unsigned long) _text || vaddr > end)
set_pmd(pmd, __pmd(0));
}
/* NOTE: this is meant to be run only at boot */
- ---- ----------------void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+ ++++ ++++++++++++++++void __init __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
{
unsigned long address = __fix_to_virt(idx);
static unsigned long __meminit
phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
{
++++++ +++++++++++++++++ unsigned long pages = 0;
++++++ +++++++++++++++++
int i = pmd_index(address);
for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
if (pmd_val(*pmd))
continue;
++++++ +++++++++++++++++ pages++;
set_pte((pte_t *)pmd,
pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
}
++++++ +++++++++++++++++ update_page_count(PG_LEVEL_2M, pages);
return address;
}
static unsigned long __meminit
phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
{
++++++ +++++++++++++++++ unsigned long pages = 0;
unsigned long last_map_addr = end;
int i = pud_index(addr);
}
if (direct_gbpages) {
++++++ +++++++++++++++++ pages++;
set_pte((pte_t *)pud,
pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
unmap_low_page(pmd);
}
__flush_tlb_all();
++++++ +++++++++++++++++ update_page_count(PG_LEVEL_1G, pages);
return last_map_addr >> PAGE_SHIFT;
}
direct_gbpages = 0;
}
---------------- -------#ifdef CONFIG_MEMTEST_BOOTPARAM
++++++++++++++++ +++++++#ifdef CONFIG_MEMTEST
static void __init memtest(unsigned long start_phys, unsigned long size,
unsigned pattern)
}
---------------- -------static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE;
++++++++++++++++ +++++++/* default is disabled */
++++++++++++++++ +++++++static int memtest_pattern __initdata;
static int __init parse_memtest(char *arg)
{
static void __init early_memtest(unsigned long start, unsigned long end)
{
- --- - - - - - unsigned long t_start, t_size;
+ +++ + + + + + u64 t_start, t_size;
unsigned pattern;
if (!memtest_pattern)
if (t_start + t_size > end)
t_size = end - t_start;
- --- - - - - - printk(KERN_CONT "\n %016lx - %016lx pattern %d",
- --- - - - - - t_start, t_start + t_size, pattern);
+ +++ + + + + + printk(KERN_CONT "\n %016llx - %016llx pattern %d",
- -- -- ---- -- - t_start, t_start + t_size, pattern);
+ ++++ ++++++++++++++++ (unsigned long long)t_start,
+ ++++ ++++++++++++++++ (unsigned long long)t_start + t_size, pattern);
memtest(t_start, t_size, pattern);
/*
* Don't remap the low PCI/ISA area, it's always mapped..
*/
----------------- ------ if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
+++++++++++++++++ ++++++ if (is_ISA_range(phys_addr, last_addr))
return (__force void __iomem *)phys_to_virt(phys_addr);
/*
{
/*
* Ideally, this should be:
----------------- ------ * pat_wc_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
+++++++++++++++++ ++++++ * pat_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
*
* Till we fix all X drivers to use ioremap_wc(), we will use
* UC MINUS.
*/
void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
{
----------------- ------ if (pat_wc_enabled)
+++++++++++++++++ ++++++ if (pat_enabled)
return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
__builtin_return_address(0));
else
* vm_area and by simply returning an address into the kernel mapping
* of ISA space. So handle that here.
*/
------ ----------------- if (addr >= phys_to_virt(ISA_START_ADDRESS) &&
------ ----------------- addr < phys_to_virt(ISA_END_ADDRESS))
++++++ +++++++++++++++++ if ((void __force *)addr >= phys_to_virt(ISA_START_ADDRESS) &&
++++++ +++++++++++++++++ (void __force *)addr < phys_to_virt(ISA_END_ADDRESS))
return;
addr = (volatile void __iomem *)
cpa takes care of the direct mappings. */
read_lock(&vmlist_lock);
for (p = vmlist; p; p = p->next) {
------ ----------------- if (p->addr == addr)
++++++ +++++++++++++++++ if (p->addr == (void __force *)addr)
break;
}
read_unlock(&vmlist_lock);
free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
/* Finally remove it */
------ ----------------- o = remove_vm_area((void *)addr);
++++++ +++++++++++++++++ o = remove_vm_area((void __force *)addr);
BUG_ON(p != o || o == NULL);
kfree(p);
}
if (page_is_ram(start >> PAGE_SHIFT))
return __va(phys);
------ ----------------- addr = (void *)ioremap(start, PAGE_SIZE);
++++++ +++++++++++++++++ addr = (void __force *)ioremap(start, PAGE_SIZE);
if (addr)
addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
unsigned long offset;
unsigned int nrpages;
enum fixed_addresses idx;
- --- - - - - - unsigned int nesting;
+ +++ + + + + + int nesting;
nesting = --early_ioremap_nested;
- --- - - - - - WARN_ON(nesting < 0);
+ +++ + + + + + if (WARN_ON(nesting < 0))
+ +++ + + + + + return;
if (early_ioremap_debug) {
printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
unsigned force_split : 1;
};
++++++ +++++++++++++++++#ifdef CONFIG_PROC_FS
++++++ +++++++++++++++++static unsigned long direct_pages_count[PG_LEVEL_NUM];
++++++ +++++++++++++++++
++++++ +++++++++++++++++void update_page_count(int level, unsigned long pages)
++++++ +++++++++++++++++{
++++++ +++++++++++++++++ unsigned long flags;
++++++ +++++++++++++++++
++++++ +++++++++++++++++ /* Protect against CPA */
++++++ +++++++++++++++++ spin_lock_irqsave(&pgd_lock, flags);
++++++ +++++++++++++++++ direct_pages_count[level] += pages;
++++++ +++++++++++++++++ spin_unlock_irqrestore(&pgd_lock, flags);
++++++ +++++++++++++++++}
++++++ +++++++++++++++++
++++++ +++++++++++++++++static void split_page_count(int level)
++++++ +++++++++++++++++{
++++++ +++++++++++++++++ direct_pages_count[level]--;
++++++ +++++++++++++++++ direct_pages_count[level - 1] += PTRS_PER_PTE;
++++++ +++++++++++++++++}
++++++ +++++++++++++++++
++++++ +++++++++++++++++int arch_report_meminfo(char *page)
++++++ +++++++++++++++++{
++++++ +++++++++++++++++ int n = sprintf(page, "DirectMap4k: %8lu\n"
++++++ +++++++++++++++++ "DirectMap2M: %8lu\n",
++++++ +++++++++++++++++ direct_pages_count[PG_LEVEL_4K],
++++++ +++++++++++++++++ direct_pages_count[PG_LEVEL_2M]);
++++++ +++++++++++++++++#ifdef CONFIG_X86_64
++++++ +++++++++++++++++ n += sprintf(page + n, "DirectMap1G: %8lu\n",
++++++ +++++++++++++++++ direct_pages_count[PG_LEVEL_1G]);
++++++ +++++++++++++++++#endif
++++++ +++++++++++++++++ return n;
++++++ +++++++++++++++++}
++++++ +++++++++++++++++#else
++++++ +++++++++++++++++static inline void split_page_count(int level) { }
++++++ +++++++++++++++++#endif
++++++ +++++++++++++++++
#ifdef CONFIG_X86_64
static inline unsigned long highmap_start_pfn(void)
for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc)
set_pte(&pbase[i], pfn_pte(pfn, ref_prot));
++++++ +++++++++++++++++ if (address >= (unsigned long)__va(0) &&
++++++ +++++++++++++++++ address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT))
++++++ +++++++++++++++++ split_page_count(level);
++++++ +++++++++++++++++
/*
* Install the new, split up pagetable. Important details here:
*
int set_memory_wc(unsigned long addr, int numpages)
{
----------------- ------ if (!pat_wc_enabled)
+++++++++++++++++ ++++++ if (!pat_enabled)
return set_memory_uc(addr, numpages);
if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
#include "multicalls.h"
#include "mmu.h"
+++++++++++++++++++++++ #define P2M_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
+++++++++++++++++++++++ #define TOP_ENTRIES (MAX_DOMAIN_PAGES / P2M_ENTRIES_PER_PAGE)
+++++++++++++++++++++++
+++++++++++++++++++++++ /* Placeholder for holes in the address space */
+++++++++++++++++++++++ static unsigned long p2m_missing[P2M_ENTRIES_PER_PAGE]
+++++++++++++++++++++++ __attribute__((section(".data.page_aligned"))) =
+++++++++++++++++++++++ { [ 0 ... P2M_ENTRIES_PER_PAGE-1 ] = ~0UL };
+++++++++++++++++++++++
+++++++++++++++++++++++ /* Array of pointers to pages containing p2m entries */
+++++++++++++++++++++++ static unsigned long *p2m_top[TOP_ENTRIES]
+++++++++++++++++++++++ __attribute__((section(".data.page_aligned"))) =
+++++++++++++++++++++++ { [ 0 ... TOP_ENTRIES - 1] = &p2m_missing[0] };
+++++++++++++++++++++++
+++++++++++++++++++++++ /* Arrays of p2m arrays expressed in mfns used for save/restore */
+++++++++++++++++++++++ static unsigned long p2m_top_mfn[TOP_ENTRIES]
+++++++++++++++++++++++ __attribute__((section(".bss.page_aligned")));
+++++++++++++++++++++++
+++++++++++++++++++++++ static unsigned long p2m_top_mfn_list[
+++++++++++++++++++++++ PAGE_ALIGN(TOP_ENTRIES / P2M_ENTRIES_PER_PAGE)]
+++++++++++++++++++++++ __attribute__((section(".bss.page_aligned")));
+++++++++++++++++++++++
+++++++++++++++++++++++ static inline unsigned p2m_top_index(unsigned long pfn)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ BUG_ON(pfn >= MAX_DOMAIN_PAGES);
+++++++++++++++++++++++ return pfn / P2M_ENTRIES_PER_PAGE;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ static inline unsigned p2m_index(unsigned long pfn)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ return pfn % P2M_ENTRIES_PER_PAGE;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ /* Build the parallel p2m_top_mfn structures */
+++++++++++++++++++++++ void xen_setup_mfn_list_list(void)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ unsigned pfn, idx;
+++++++++++++++++++++++
+++++++++++++++++++++++ for(pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_ENTRIES_PER_PAGE) {
+++++++++++++++++++++++ unsigned topidx = p2m_top_index(pfn);
+++++++++++++++++++++++
+++++++++++++++++++++++ p2m_top_mfn[topidx] = virt_to_mfn(p2m_top[topidx]);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ for(idx = 0; idx < ARRAY_SIZE(p2m_top_mfn_list); idx++) {
+++++++++++++++++++++++ unsigned topidx = idx * P2M_ENTRIES_PER_PAGE;
+++++++++++++++++++++++ p2m_top_mfn_list[idx] = virt_to_mfn(&p2m_top_mfn[topidx]);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
+++++++++++++++++++++++
+++++++++++++++++++++++ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+++++++++++++++++++++++ virt_to_mfn(p2m_top_mfn_list);
+++++++++++++++++++++++ HYPERVISOR_shared_info->arch.max_pfn = xen_start_info->nr_pages;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ /* Set up p2m_top to point to the domain-builder provided p2m pages */
+++++++++++++++++++++++ void __init xen_build_dynamic_phys_to_machine(void)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
+++++++++++++++++++++++ unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
+++++++++++++++++++++++ unsigned pfn;
+++++++++++++++++++++++
+++++++++++++++++++++++ for(pfn = 0; pfn < max_pfn; pfn += P2M_ENTRIES_PER_PAGE) {
+++++++++++++++++++++++ unsigned topidx = p2m_top_index(pfn);
+++++++++++++++++++++++
+++++++++++++++++++++++ p2m_top[topidx] = &mfn_list[pfn];
+++++++++++++++++++++++ }
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ unsigned long get_phys_to_machine(unsigned long pfn)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ unsigned topidx, idx;
+++++++++++++++++++++++
+++++++++++++++++++++++ if (unlikely(pfn >= MAX_DOMAIN_PAGES))
+++++++++++++++++++++++ return INVALID_P2M_ENTRY;
+++++++++++++++++++++++
+++++++++++++++++++++++ topidx = p2m_top_index(pfn);
+++++++++++++++++++++++ idx = p2m_index(pfn);
+++++++++++++++++++++++ return p2m_top[topidx][idx];
+++++++++++++++++++++++ }
+++++++++++++++++++++++ EXPORT_SYMBOL_GPL(get_phys_to_machine);
+++++++++++++++++++++++
+++++++++++++++++++++++ static void alloc_p2m(unsigned long **pp, unsigned long *mfnp)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ unsigned long *p;
+++++++++++++++++++++++ unsigned i;
+++++++++++++++++++++++
+++++++++++++++++++++++ p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL);
+++++++++++++++++++++++ BUG_ON(p == NULL);
+++++++++++++++++++++++
+++++++++++++++++++++++ for(i = 0; i < P2M_ENTRIES_PER_PAGE; i++)
+++++++++++++++++++++++ p[i] = INVALID_P2M_ENTRY;
+++++++++++++++++++++++
+++++++++++++++++++++++ if (cmpxchg(pp, p2m_missing, p) != p2m_missing)
+++++++++++++++++++++++ free_page((unsigned long)p);
+++++++++++++++++++++++ else
+++++++++++++++++++++++ *mfnp = virt_to_mfn(p);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ unsigned topidx, idx;
+++++++++++++++++++++++
+++++++++++++++++++++++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+++++++++++++++++++++++ BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+++++++++++++++++++++++ return;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ if (unlikely(pfn >= MAX_DOMAIN_PAGES)) {
+++++++++++++++++++++++ BUG_ON(mfn != INVALID_P2M_ENTRY);
+++++++++++++++++++++++ return;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ topidx = p2m_top_index(pfn);
+++++++++++++++++++++++ if (p2m_top[topidx] == p2m_missing) {
+++++++++++++++++++++++ /* no need to allocate a page to store an invalid entry */
+++++++++++++++++++++++ if (mfn == INVALID_P2M_ENTRY)
+++++++++++++++++++++++ return;
+++++++++++++++++++++++ alloc_p2m(&p2m_top[topidx], &p2m_top_mfn[topidx]);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ idx = p2m_index(pfn);
+++++++++++++++++++++++ p2m_top[topidx][idx] = mfn;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
xmaddr_t arbitrary_virt_to_machine(unsigned long address)
{
unsigned int level;
pte_t *pte = lookup_address(address, &level);
- --- - - - - - unsigned offset = address & PAGE_MASK;
+ +++ + + + + + unsigned offset = address & ~PAGE_MASK;
BUG_ON(pte == NULL);
}
----------------------- void xen_set_pmd(pmd_t *ptr, pmd_t val)
+++++++++++++++++++++++ static bool page_pinned(void *ptr)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ struct page *page = virt_to_page(ptr);
+++++++++++++++++++++++
+++++++++++++++++++++++ return PagePinned(page);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ static void extend_mmu_update(const struct mmu_update *update)
{
struct multicall_space mcs;
struct mmu_update *u;
----------------------- preempt_disable();
+++++++++++++++++++++++ mcs = xen_mc_extend_args(__HYPERVISOR_mmu_update, sizeof(*u));
+++++++++++++++++++++++
+++++++++++++++++++++++ if (mcs.mc != NULL)
+++++++++++++++++++++++ mcs.mc->args[1]++;
+++++++++++++++++++++++ else {
+++++++++++++++++++++++ mcs = __xen_mc_entry(sizeof(*u));
+++++++++++++++++++++++ MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_SELF);
+++++++++++++++++++++++ }
----------------------- mcs = xen_mc_entry(sizeof(*u));
u = mcs.args;
----------------------- u->ptr = virt_to_machine(ptr).maddr;
----------------------- u->val = pmd_val_ma(val);
----------------------- MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
+++++++++++++++++++++++ *u = *update;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ struct mmu_update u;
+++++++++++++++++++++++
+++++++++++++++++++++++ preempt_disable();
+++++++++++++++++++++++
+++++++++++++++++++++++ xen_mc_batch();
+++++++++++++++++++++++
+++++++++++++++++++++++ u.ptr = virt_to_machine(ptr).maddr;
+++++++++++++++++++++++ u.val = pmd_val_ma(val);
+++++++++++++++++++++++ extend_mmu_update(&u);
xen_mc_issue(PARAVIRT_LAZY_MMU);
preempt_enable();
}
+++++++++++++++++++++++ void xen_set_pmd(pmd_t *ptr, pmd_t val)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ /* If page is not pinned, we can just update the entry
+++++++++++++++++++++++ directly */
+++++++++++++++++++++++ if (!page_pinned(ptr)) {
+++++++++++++++++++++++ *ptr = val;
+++++++++++++++++++++++ return;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ xen_set_pmd_hyper(ptr, val);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
/*
* Associate a virtual page frame with a given physical page frame
* and protection flags for that frame.
preempt_enable();
}
- --- - -- - ---- - pteval_t xen_pte_val(pte_t pte)
+++++++++++++++++++++++ pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ +++ ++ + ++ + {
- --- - -- - ---- - pteval_t ret = pte.pte;
+++++++++++++++++++++++ /* Just return the pte as-is. We preserve the bits on commit */
+++++++++++++++++++++++ return *ptep;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
+++++++++++++++++++++++ pte_t *ptep, pte_t pte)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ struct mmu_update u;
+++++++++++++++++++++++
+++++++++++++++++++++++ xen_mc_batch();
+ +++ ++ + ++ +
- --- - -- - ---- - if (ret & _PAGE_PRESENT)
- --- - -- - ---- - ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
+++++++++++++++++++++++ u.ptr = virt_to_machine(ptep).maddr | MMU_PT_UPDATE_PRESERVE_AD;
+++++++++++++++++++++++ u.val = pte_val_ma(pte);
+++++++++++++++++++++++ extend_mmu_update(&u);
+ +++ ++ + ++ +
- --- - -- - ---- - return ret;
+++++++++++++++++++++++ xen_mc_issue(PARAVIRT_LAZY_MMU);
+ +++ ++ + ++ + }
+ +++ ++ + ++ +
- --- - -- - ---- - pgdval_t xen_pgd_val(pgd_t pgd)
+ +++ + ++ + ++++ + /* Assume pteval_t is equivalent to all the other *val_t types. */
+ +++ + ++ + ++++ + static pteval_t pte_mfn_to_pfn(pteval_t val)
{
- --- - -- - ---- - pgdval_t ret = pgd.pgd;
- --- - -- - ---- - if (ret & _PAGE_PRESENT)
- --- - -- - ---- - ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
- --- - -- - ---- - return ret;
+ +++ + ++ + ++++ + if (val & _PAGE_PRESENT) {
+ +++ + ++ + ++++ + unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT;
+ +++ + ++ + ++++ + pteval_t flags = val & ~PTE_MASK;
- -- - -- - - val = (mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+ ++++ ++++++++++++++++ val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+ +++ + ++ + ++++ + }
+ +++ + ++ + ++++ +
+ +++ + ++ + ++++ + return val;
}
- --- - -- - ---- - pte_t xen_make_pte(pteval_t pte)
+ +++ + ++ + ++++ + static pteval_t pte_pfn_to_mfn(pteval_t val)
{
- --- - -- - ---- - if (pte & _PAGE_PRESENT) {
- --- - -- - ---- - pte = phys_to_machine(XPADDR(pte)).maddr;
- --- - -- - ---- - pte &= ~(_PAGE_PCD | _PAGE_PWT);
+ +++ + ++ + ++++ + if (val & _PAGE_PRESENT) {
+ +++ + ++ + ++++ + unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT;
+ +++ + ++ + ++++ + pteval_t flags = val & ~PTE_MASK;
- -- - -- - - val = (pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
+ ++++ ++++++++++++++++ val = ((pteval_t)pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
}
- --- - -- - ---- - return (pte_t){ .pte = pte };
+ +++ + ++ + ++++ + return val;
}
- --- - -- - ---- - pgd_t xen_make_pgd(pgdval_t pgd)
+ +++ + ++ + ++++ + pteval_t xen_pte_val(pte_t pte)
{
- --- - -- - ---- - if (pgd & _PAGE_PRESENT)
- --- - -- - ---- - pgd = phys_to_machine(XPADDR(pgd)).maddr;
+ +++ + ++ + ++++ + return pte_mfn_to_pfn(pte.pte);
+ +++ + ++ + ++++ + }
- --- - -- - ---- - return (pgd_t){ pgd };
+ +++ + ++ + ++++ + pgdval_t xen_pgd_val(pgd_t pgd)
+ +++ + ++ + ++++ + {
+ +++ + ++ + ++++ + return pte_mfn_to_pfn(pgd.pgd);
+ +++ + ++ + ++++ + }
+ +++ + ++ + ++++ +
+ +++ + ++ + ++++ + pte_t xen_make_pte(pteval_t pte)
+ +++ + ++ + ++++ + {
+ +++ + ++ + ++++ + pte = pte_pfn_to_mfn(pte);
+ +++ + ++ + ++++ + return native_make_pte(pte);
+ +++ + ++ + ++++ + }
+ +++ + ++ + ++++ +
+ +++ + ++ + ++++ + pgd_t xen_make_pgd(pgdval_t pgd)
+ +++ + ++ + ++++ + {
+ +++ + ++ + ++++ + pgd = pte_pfn_to_mfn(pgd);
+ +++ + ++ + ++++ + return native_make_pgd(pgd);
}
pmdval_t xen_pmd_val(pmd_t pmd)
{
- --- - -- - ---- - pmdval_t ret = native_pmd_val(pmd);
- --- - -- - ---- - if (ret & _PAGE_PRESENT)
- --- - -- - ---- - ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
- --- - -- - ---- - return ret;
+ +++ + ++ + ++++ + return pte_mfn_to_pfn(pmd.pmd);
}
- --- - -- - ---- - #ifdef CONFIG_X86_PAE
- --- - -- - ---- - void xen_set_pud(pud_t *ptr, pud_t val)
+ +++ + ++ + ++++ +
- --- -- - -- - void xen_set_pud(pud_t *ptr, pud_t val)
+++++++++++++++++++++++ void xen_set_pud_hyper(pud_t *ptr, pud_t val)
{
----------------------- struct multicall_space mcs;
----------------------- struct mmu_update *u;
+++++++++++++++++++++++ struct mmu_update u;
preempt_disable();
----------------------- mcs = xen_mc_entry(sizeof(*u));
----------------------- u = mcs.args;
----------------------- u->ptr = virt_to_machine(ptr).maddr;
----------------------- u->val = pud_val_ma(val);
----------------------- MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
+++++++++++++++++++++++ xen_mc_batch();
+++++++++++++++++++++++
+++++++++++++++++++++++ u.ptr = virt_to_machine(ptr).maddr;
+++++++++++++++++++++++ u.val = pud_val_ma(val);
+++++++++++++++++++++++ extend_mmu_update(&u);
xen_mc_issue(PARAVIRT_LAZY_MMU);
preempt_enable();
}
+++++++++++++++++++++++ void xen_set_pud(pud_t *ptr, pud_t val)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ /* If page is not pinned, we can just update the entry
+++++++++++++++++++++++ directly */
+++++++++++++++++++++++ if (!page_pinned(ptr)) {
+++++++++++++++++++++++ *ptr = val;
+++++++++++++++++++++++ return;
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ xen_set_pud_hyper(ptr, val);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
void xen_set_pte(pte_t *ptep, pte_t pte)
{
ptep->pte_high = pte.pte_high;
void xen_pmd_clear(pmd_t *pmdp)
{
----------------------- xen_set_pmd(pmdp, __pmd(0));
+++++++++++++++++++++++ set_pmd(pmdp, __pmd(0));
}
pmd_t xen_make_pmd(pmdval_t pmd)
{
- --- - -- - ---- - if (pmd & _PAGE_PRESENT)
- --- - -- - ---- - pmd = phys_to_machine(XPADDR(pmd)).maddr;
- --- - -- - ---- -
+ +++ + ++ + ++++ + pmd = pte_pfn_to_mfn(pmd);
return native_make_pmd(pmd);
}
- --- - -- - ---- - #else /* !PAE */
- --- - -- - ---- - void xen_set_pte(pte_t *ptep, pte_t pte)
- --- - -- - ---- - {
- --- - -- - ---- - *ptep = pte;
- --- - -- - ---- - }
- --- - -- - ---- - #endif /* CONFIG_X86_PAE */
/*
(Yet another) pagetable walker. This one is intended for pinning a
read-only, and can be pinned. */
void xen_pgd_pin(pgd_t *pgd)
{
- --- - -- - ---- - unsigned level;
- --- - -- - ---- -
xen_mc_batch();
if (pgd_walk(pgd, pin_page, TASK_SIZE)) {
xen_mc_batch();
}
- --- - -- - ---- - #ifdef CONFIG_X86_PAE
- --- - -- - ---- - level = MMUEXT_PIN_L3_TABLE;
- --- - -- - ---- - #else
- --- - -- - ---- - level = MMUEXT_PIN_L2_TABLE;
- --- - -- - ---- - #endif
+ +++ + ++ + ++++ + xen_do_pin(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(pgd)));
+ +++ + ++ + ++++ + xen_mc_issue(0);
+ +++ + ++ + ++++ + }
+ +++ + ++ + ++++ +
+++++++++++++++++++++++ /*
+++++++++++++++++++++++ * On save, we need to pin all pagetables to make sure they get their
+++++++++++++++++++++++ * mfns turned into pfns. Search the list for any unpinned pgds and pin
+++++++++++++++++++++++ * them (unpinned pgds are not currently in use, probably because the
+++++++++++++++++++++++ * process is under construction or destruction).
+++++++++++++++++++++++ */
+++++++++++++++++++++++ void xen_mm_pin_all(void)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ unsigned long flags;
+++++++++++++++++++++++ struct page *page;
+ +++ ++ + ++ +
- --- - -- - ---- - xen_do_pin(level, PFN_DOWN(__pa(pgd)));
+++++++++++++++++++++++ spin_lock_irqsave(&pgd_lock, flags);
+ +++ ++ + ++ +
- --- - -- - ---- - xen_mc_issue(0);
+++++++++++++++++++++++ list_for_each_entry(page, &pgd_list, lru) {
+++++++++++++++++++++++ if (!PagePinned(page)) {
+++++++++++++++++++++++ xen_pgd_pin((pgd_t *)page_address(page));
+++++++++++++++++++++++ SetPageSavePinned(page);
+++++++++++++++++++++++ }
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ spin_unlock_irqrestore(&pgd_lock, flags);
+ +++ ++ + ++ + }
+ +++ ++ + ++ +
/* The init_mm pagetable is really pinned as soon as its created, but
that's before we have page structures to store the bits. So do all
the book-keeping now. */
xen_mc_issue(0);
}
+++++++++++++++++++++++ /*
+++++++++++++++++++++++ * On resume, undo any pinning done at save, so that the rest of the
+++++++++++++++++++++++ * kernel doesn't see any unexpected pinned pagetables.
+++++++++++++++++++++++ */
+++++++++++++++++++++++ void xen_mm_unpin_all(void)
+++++++++++++++++++++++ {
+++++++++++++++++++++++ unsigned long flags;
+++++++++++++++++++++++ struct page *page;
+++++++++++++++++++++++
+++++++++++++++++++++++ spin_lock_irqsave(&pgd_lock, flags);
+++++++++++++++++++++++
+++++++++++++++++++++++ list_for_each_entry(page, &pgd_list, lru) {
+++++++++++++++++++++++ if (PageSavePinned(page)) {
+++++++++++++++++++++++ BUG_ON(!PagePinned(page));
+++++++++++++++++++++++ printk("unpinning pinned %p\n", page_address(page));
+++++++++++++++++++++++ xen_pgd_unpin((pgd_t *)page_address(page));
+++++++++++++++++++++++ ClearPageSavePinned(page);
+++++++++++++++++++++++ }
+++++++++++++++++++++++ }
+++++++++++++++++++++++
+++++++++++++++++++++++ spin_unlock_irqrestore(&pgd_lock, flags);
+++++++++++++++++++++++ }
+++++++++++++++++++++++
void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
{
spin_lock(&next->page_table_lock);
spin_lock(&mm->page_table_lock);
/* pgd may not be pinned in the error exit path of execve */
----------------------- if (PagePinned(virt_to_page(mm->pgd)))
+++++++++++++++++++++++ if (page_pinned(mm->pgd))
xen_pgd_unpin(mm->pgd);
spin_unlock(&mm->page_table_lock);
return proc_calc_metrics(page, start, off, count, eof, len);
}
++++++ +++++++++++++++++int __attribute__((weak)) arch_report_meminfo(char *page)
++++++ +++++++++++++++++{
++++++ +++++++++++++++++ return 0;
++++++ +++++++++++++++++}
++++++ +++++++++++++++++
static int meminfo_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
#define K(x) ((x) << (PAGE_SHIFT - 10))
si_meminfo(&i);
si_swapinfo(&i);
- --- - - - - - committed = atomic_read(&vm_committed_space);
+ +++ + + + + + committed = atomic_long_read(&vm_committed_space);
allowed = ((totalram_pages - hugetlb_total_pages())
* sysctl_overcommit_ratio / 100) + total_swap_pages;
len += hugetlb_report_meminfo(page + len);
++++++ +++++++++++++++++ len += arch_report_meminfo(page + len);
++++++ +++++++++++++++++
return proc_calc_metrics(page, start, off, count, eof, len);
#undef K
}
};
#endif
++++++++++++ +++++++++++#ifndef arch_irq_stat_cpu
++++++++++++ +++++++++++#define arch_irq_stat_cpu(cpu) 0
++++++++++++ +++++++++++#endif
++++++++++++ +++++++++++#ifndef arch_irq_stat
++++++++++++ +++++++++++#define arch_irq_stat() 0
++++++++++++ +++++++++++#endif
++++++++++++ +++++++++++
static int show_stat(struct seq_file *p, void *v)
{
int i;
sum += temp;
per_irq_sum[j] += temp;
}
++++++++++++ +++++++++++ sum += arch_irq_stat_cpu(i);
}
++++++++++++ +++++++++++ sum += arch_irq_stat();
seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
(unsigned long long)cputime64_to_clock_t(user),
pfn = src / KPMSIZE;
count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
if (src & KPMMASK || count & KPMMASK)
- --- - - - - - return -EIO;
+ +++ + + + + + return -EINVAL;
while (count > 0) {
ppage = NULL;
if (!ppage)
pcount = 0;
else
- --- - - - - - pcount = atomic_read(&ppage->_count);
+ +++ + + + + + pcount = page_mapcount(ppage);
if (put_user(pcount, out++)) {
ret = -EFAULT;
pfn = src / KPMSIZE;
count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
if (src & KPMMASK || count & KPMMASK)
- --- - - - - - return -EIO;
+ +++ + + + + + return -EINVAL;
while (count > 0) {
ppage = NULL;
#ifdef CONFIG_X86_LOCAL_APIC
extern int apic_verbosity;
- ----------------------extern int timer_over_8254;
extern int local_apic_timer_c2_ok;
------- ----------------extern int local_apic_timer_disabled;
------- ----------------extern int apic_runs_main_timer;
extern int ioapic_force;
extern int disable_apic;
------- ----------------extern int disable_apic_timer;
/*
* Basic functions accessing APICs.
*/
int do_nmi_callback(struct pt_regs *regs, int cpu);
----- ------------------#ifdef CONFIG_PM
----- ------------------
----- ------------------/** Replace the PM callback routine for NMI. */
----- ------------------struct pm_dev *set_nmi_pm_callback(pm_callback callback);
----- ------------------
----- ------------------/** Unset the PM callback routine back to the default. */
----- ------------------void unset_nmi_pm_callback(struct pm_dev *dev);
----- ------------------
----- ------------------#else
----- ------------------
----- ------------------static inline struct pm_dev *set_nmi_pm_callback(pm_callback callback)
----- ------------------{
----- ------------------ return 0;
----- ------------------}
----- ------------------
----- ------------------static inline void unset_nmi_pm_callback(struct pm_dev *dev)
----- ------------------{
----- ------------------}
----- ------------------
----- ------------------#endif /* CONFIG_PM */
----- ------------------
#ifdef CONFIG_X86_64
extern void default_do_nmi(struct pt_regs *);
extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
extern int check_nmi_watchdog(void);
extern int nmi_watchdog_enabled;
----- ------------------extern int unknown_nmi_panic;
extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
extern int avail_to_resrv_perfctr_nmi(unsigned int);
extern int reserve_perfctr_nmi(unsigned int);
void __trigger_all_cpu_backtrace(void);
#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
+ ++++++++++++++++++++++static inline void localise_nmi_watchdog(void)
+ ++++++++++++++++++++++{
+ ++++++++++++++++++++++ if (nmi_watchdog == NMI_IO_APIC)
+ ++++++++++++++++++++++ nmi_watchdog = NMI_LOCAL_APIC;
+ ++++++++++++++++++++++}
#endif
void lapic_watchdog_stop(void);
#ifdef __KERNEL__
- - - - #define PHYSICAL_PAGE_MASK (PAGE_MASK & __PHYSICAL_MASK)
- - - - #define PTE_MASK (_AT(long, PHYSICAL_PAGE_MASK))
+ + + + #define __PHYSICAL_MASK ((phys_addr_t)(1ULL << __PHYSICAL_MASK_SHIFT) - 1)
+ + + + #define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
+ + + +
+ + + + /* Cast PAGE_MASK to a signed type so that it is sign-extended if
+ + + + virtual addresses are 32-bits but physical addresses are larger
+ + + + (ie, 32-bit PAE). */
+ + + + #define PHYSICAL_PAGE_MASK (((signed long)PAGE_MASK) & __PHYSICAL_MASK)
+ + + +
+ + + + /* PTE_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
+ + + + #define PTE_MASK ((pteval_t)PHYSICAL_PAGE_MASK)
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
- - - - #define __PHYSICAL_MASK _AT(phys_addr_t, (_AC(1,ULL) << __PHYSICAL_MASK_SHIFT) - 1)
- - - - #define __VIRTUAL_MASK ((_AC(1,UL) << __VIRTUAL_MASK_SHIFT) - 1)
- - - -
#ifndef __ASSEMBLY__
#include <linux/types.h>
#endif
#ifndef __ASSEMBLY__
+++++ ++++++++++++++++++typedef struct { pgdval_t pgd; } pgd_t;
+++++ ++++++++++++++++++typedef struct { pgprotval_t pgprot; } pgprot_t;
+++++ ++++++++++++++++++
extern int page_is_ram(unsigned long pagenr);
extern int devmem_is_allowed(unsigned long pagenr);
+++++ ++++++++++++++++++extern void map_devmem(unsigned long pfn, unsigned long size,
+++++ ++++++++++++++++++ pgprot_t vma_prot);
+++++ ++++++++++++++++++extern void unmap_devmem(unsigned long pfn, unsigned long size,
+++++ ++++++++++++++++++ pgprot_t vma_prot);
extern unsigned long max_pfn_mapped;
alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
----- ------------------typedef struct { pgdval_t pgd; } pgd_t;
----- ------------------typedef struct { pgprotval_t pgprot; } pgprot_t;
----- ------------------
static inline pgd_t native_make_pgd(pgdval_t val)
{
return (pgd_t) { val };
#endif
#define pte_val(x) native_pte_val(x)
+++++++++++++++++++++++ #define pte_flags(x) native_pte_val(x)
#define __pte(x) native_make_pte(x)
#endif /* CONFIG_PARAVIRT */
#define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */
#define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */
------------------ -----/*
------------------ ----- * Note: we use _AC(1, L) instead of _AC(1, UL) so that we get a
------------------ ----- * sign-extended value on 32-bit with all 1's in the upper word,
------------------ ----- * which preserves the upper pte values on 64-bit ptes:
------------------ ----- */
------------------ -----#define _PAGE_PRESENT (_AC(1, L)<<_PAGE_BIT_PRESENT)
------------------ -----#define _PAGE_RW (_AC(1, L)<<_PAGE_BIT_RW)
------------------ -----#define _PAGE_USER (_AC(1, L)<<_PAGE_BIT_USER)
------------------ -----#define _PAGE_PWT (_AC(1, L)<<_PAGE_BIT_PWT)
------------------ -----#define _PAGE_PCD (_AC(1, L)<<_PAGE_BIT_PCD)
------------------ -----#define _PAGE_ACCESSED (_AC(1, L)<<_PAGE_BIT_ACCESSED)
------------------ -----#define _PAGE_DIRTY (_AC(1, L)<<_PAGE_BIT_DIRTY)
------------------ -----#define _PAGE_PSE (_AC(1, L)<<_PAGE_BIT_PSE) /* 2MB page */
------------------ -----#define _PAGE_GLOBAL (_AC(1, L)<<_PAGE_BIT_GLOBAL) /* Global TLB entry */
------------------ -----#define _PAGE_UNUSED1 (_AC(1, L)<<_PAGE_BIT_UNUSED1)
------------------ -----#define _PAGE_UNUSED2 (_AC(1, L)<<_PAGE_BIT_UNUSED2)
------------------ -----#define _PAGE_UNUSED3 (_AC(1, L)<<_PAGE_BIT_UNUSED3)
------------------ -----#define _PAGE_PAT (_AC(1, L)<<_PAGE_BIT_PAT)
------------------ -----#define _PAGE_PAT_LARGE (_AC(1, L)<<_PAGE_BIT_PAT_LARGE)
++++++++++++++++++ +++++#define _PAGE_PRESENT (_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
++++++++++++++++++ +++++#define _PAGE_RW (_AT(pteval_t, 1) << _PAGE_BIT_RW)
++++++++++++++++++ +++++#define _PAGE_USER (_AT(pteval_t, 1) << _PAGE_BIT_USER)
++++++++++++++++++ +++++#define _PAGE_PWT (_AT(pteval_t, 1) << _PAGE_BIT_PWT)
++++++++++++++++++ +++++#define _PAGE_PCD (_AT(pteval_t, 1) << _PAGE_BIT_PCD)
++++++++++++++++++ +++++#define _PAGE_ACCESSED (_AT(pteval_t, 1) << _PAGE_BIT_ACCESSED)
++++++++++++++++++ +++++#define _PAGE_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
++++++++++++++++++ +++++#define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE)
++++++++++++++++++ +++++#define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
++++++++++++++++++ +++++#define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
++++++++++++++++++ +++++#define _PAGE_UNUSED2 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED2)
++++++++++++++++++ +++++#define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
++++++++++++++++++ +++++#define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT)
++++++++++++++++++ +++++#define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
------------------ -----#define _PAGE_NX (_AC(1, ULL) << _PAGE_BIT_NX)
++++++++++++++++++ +++++#define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX)
#else
------------------ -----#define _PAGE_NX 0
++++++++++++++++++ +++++#define _PAGE_NX (_AT(pteval_t, 0))
#endif
/* If _PAGE_PRESENT is clear, we use these: */
#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \
_PAGE_DIRTY)
- - - #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+ + + + /* Set of bits not changed in pte_modify */
+ + + #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_PCD | _PAGE_PWT | \
+ + + _PAGE_ACCESSED | _PAGE_DIRTY)
#define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT)
#define _PAGE_CACHE_WB (0)
*/
static inline int pte_dirty(pte_t pte)
{
----------------------- return pte_val(pte) & _PAGE_DIRTY;
+++++++++++++++++++++++ return pte_flags(pte) & _PAGE_DIRTY;
}
static inline int pte_young(pte_t pte)
{
----------------------- return pte_val(pte) & _PAGE_ACCESSED;
+++++++++++++++++++++++ return pte_flags(pte) & _PAGE_ACCESSED;
}
static inline int pte_write(pte_t pte)
{
----------------------- return pte_val(pte) & _PAGE_RW;
+++++++++++++++++++++++ return pte_flags(pte) & _PAGE_RW;
}
static inline int pte_file(pte_t pte)
{
----------------------- return pte_val(pte) & _PAGE_FILE;
+++++++++++++++++++++++ return pte_flags(pte) & _PAGE_FILE;
}
static inline int pte_huge(pte_t pte)
{
----------------------- return pte_val(pte) & _PAGE_PSE;
+++++++++++++++++++++++ return pte_flags(pte) & _PAGE_PSE;
}
static inline int pte_global(pte_t pte)
{
----------------------- return pte_val(pte) & _PAGE_GLOBAL;
+++++++++++++++++++++++ return pte_flags(pte) & _PAGE_GLOBAL;
}
static inline int pte_exec(pte_t pte)
{
----------------------- return !(pte_val(pte) & _PAGE_NX);
+++++++++++++++++++++++ return !(pte_flags(pte) & _PAGE_NX);
}
static inline int pte_special(pte_t pte)
static inline pte_t pte_mkclean(pte_t pte)
{
------------------ ----- return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY);
++++++++++++++++++ +++++ return __pte(pte_val(pte) & ~_PAGE_DIRTY);
}
static inline pte_t pte_mkold(pte_t pte)
{
------------------ ----- return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED);
++++++++++++++++++ +++++ return __pte(pte_val(pte) & ~_PAGE_ACCESSED);
}
static inline pte_t pte_wrprotect(pte_t pte)
{
------------------ ----- return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW);
++++++++++++++++++ +++++ return __pte(pte_val(pte) & ~_PAGE_RW);
}
static inline pte_t pte_mkexec(pte_t pte)
{
------------------ ----- return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX);
++++++++++++++++++ +++++ return __pte(pte_val(pte) & ~_PAGE_NX);
}
static inline pte_t pte_mkdirty(pte_t pte)
static inline pte_t pte_clrhuge(pte_t pte)
{
------------------ ----- return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE);
++++++++++++++++++ +++++ return __pte(pte_val(pte) & ~_PAGE_PSE);
}
static inline pte_t pte_mkglobal(pte_t pte)
static inline pte_t pte_clrglobal(pte_t pte)
{
------------------ ----- return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL);
++++++++++++++++++ +++++ return __pte(pte_val(pte) & ~_PAGE_GLOBAL);
}
static inline pte_t pte_mkspecial(pte_t pte)
* Chop off the NX bit (if present), and add the NX portion of
* the newprot (if present):
*/
- - - val &= _PAGE_CHG_MASK & ~_PAGE_NX;
- - - val |= pgprot_val(newprot) & __supported_pte_mask;
+ + + val &= _PAGE_CHG_MASK;
+ + + val |= pgprot_val(newprot) & (~_PAGE_CHG_MASK) & __supported_pte_mask;
return __pte(val);
}
- - - #define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX))
+ + + /* mprotect needs to preserve PAT bits when updating vm_page_prot */
+ + + #define pgprot_modify pgprot_modify
+ + + static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+ + + {
+ + + pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK;
+ + + pgprotval_t addbits = pgprot_val(newprot);
+ + + return __pgprot(preservebits | addbits);
+ + + }
+ + +
- #define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX))
--- --- -- ----------- #define pte_pgprot(x) __pgprot(pte_val(x) & ~PTE_MASK)
+++++++++++++++++++++++ #define pte_pgprot(x) __pgprot(pte_flags(x) & ~PTE_MASK)
#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
PG_LEVEL_4K,
PG_LEVEL_2M,
PG_LEVEL_1G,
++++++ +++++++++++++++++ PG_LEVEL_NUM
};
++++++ +++++++++++++++++#ifdef CONFIG_PROC_FS
++++++ +++++++++++++++++extern void update_page_count(int level, unsigned long pages);
++++++ +++++++++++++++++#else
++++++ +++++++++++++++++static inline void update_page_count(int level, unsigned long pages) { }
++++++ +++++++++++++++++#endif
++++++ +++++++++++++++++
/*
* Helper function that returns the kernel pagetable entry controlling
* the virtual address 'address'. NULL means no pagetable entry present.