ia64/xen-unstable

changeset 9058:5262bd9e9d19

Merged.
author emellor@leeni.uk.xensource.com
date Mon Feb 27 18:44:38 2006 +0100 (2006-02-27)
parents c028ba081c84 b470657718fe
children a2dce576313f
files
line diff
     1.1 --- a/buildconfigs/mk.linux-2.6-xen	Mon Feb 27 17:26:16 2006 +0100
     1.2 +++ b/buildconfigs/mk.linux-2.6-xen	Mon Feb 27 18:44:38 2006 +0100
     1.3 @@ -2,8 +2,8 @@
     1.4  OS           = linux
     1.5  
     1.6  LINUX_SERIES = 2.6
     1.7 -LINUX_VER    = 2.6.16-rc4
     1.8 -LINUX_SRCS = linux-2.6.15.tar.bz2 patch-2.6.16-rc4.bz2
     1.9 +LINUX_VER    = 2.6.16-rc5
    1.10 +LINUX_SRCS = linux-2.6.15.tar.bz2 patch-2.6.16-rc5.bz2
    1.11  LINUX_PDIR = linux-$(LINUX_VER)
    1.12  
    1.13  EXTRAVERSION ?= xen
    1.14 @@ -34,7 +34,7 @@ pristine-$(LINUX_PDIR)/.valid-srcs: $(LI
    1.15  	touch $(@D)/.hgskip
    1.16  	touch $@
    1.17  
    1.18 -pristine-linux-%.16-rc4/.valid-pristine: pristine-$(LINUX_PDIR)/.valid-srcs
    1.19 +pristine-linux-%.16-rc5/.valid-pristine: pristine-$(LINUX_PDIR)/.valid-srcs
    1.20  	touch $@ # update timestamp to avoid rebuild
    1.21  
    1.22  $(LINUX_DIR)/include/linux/autoconf.h: ref-$(OS)-$(LINUX_VER)/.valid-ref
     2.1 --- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Mon Feb 27 17:26:16 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Mon Feb 27 18:44:38 2006 +0100
     2.3 @@ -770,7 +770,7 @@ config PHYSICAL_START
     2.4  
     2.5  config HOTPLUG_CPU
     2.6  	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
     2.7 -	depends on SMP && HOTPLUG && EXPERIMENTAL
     2.8 +	depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
     2.9  	---help---
    2.10  	  Say Y here to experiment with turning CPUs off and on.  CPUs
    2.11  	  can be controlled through /sys/devices/system/cpu.
    2.12 @@ -1122,6 +1122,7 @@ endif
    2.13  
    2.14  config KPROBES
    2.15  	bool "Kprobes (EXPERIMENTAL)"
    2.16 +	depends on EXPERIMENTAL && MODULES
    2.17  	help
    2.18  	  Kprobes allows you to trap at almost any kernel address and
    2.19  	  execute a callback function.  register_kprobe() establishes
     3.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/Makefile	Mon Feb 27 17:26:16 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/Makefile	Mon Feb 27 18:44:38 2006 +0100
     3.3 @@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.ld
     3.4  obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
     3.5  		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
     3.6  		pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
     3.7 -		quirks.o i8237.o
     3.8 +		quirks.o i8237.o topology.o
     3.9  
    3.10  obj-y				+= cpu/
    3.11  obj-y				+= timers/
     4.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/acpi/boot-xen.c	Mon Feb 27 17:26:16 2006 +0100
     4.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/acpi/boot-xen.c	Mon Feb 27 18:44:38 2006 +0100
     4.3 @@ -44,9 +44,6 @@ extern void __init clustered_apic_check(
     4.4  extern int gsi_irq_sharing(int gsi);
     4.5  #include <asm/proto.h>
     4.6  
     4.7 -static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; }
     4.8 -
     4.9 -
    4.10  #else				/* X86 */
    4.11  
    4.12  #ifdef	CONFIG_X86_LOCAL_APIC
     5.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/common-xen.c	Mon Feb 27 17:26:16 2006 +0100
     5.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/common-xen.c	Mon Feb 27 18:44:38 2006 +0100
     5.3 @@ -4,6 +4,7 @@
     5.4  #include <linux/smp.h>
     5.5  #include <linux/module.h>
     5.6  #include <linux/percpu.h>
     5.7 +#include <linux/bootmem.h>
     5.8  #include <asm/semaphore.h>
     5.9  #include <asm/processor.h>
    5.10  #include <asm/i387.h>
    5.11 @@ -19,6 +20,9 @@
    5.12  
    5.13  #include "cpu.h"
    5.14  
    5.15 +DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
    5.16 +EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
    5.17 +
    5.18  #ifndef CONFIG_XEN
    5.19  DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
    5.20  EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
    5.21 @@ -598,6 +602,8 @@ void __cpuinit cpu_init(void)
    5.22  	struct tss_struct * t = &per_cpu(init_tss, cpu);
    5.23  #endif
    5.24  	struct thread_struct *thread = &current->thread;
    5.25 +	struct desc_struct *gdt;
    5.26 +	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
    5.27  
    5.28  	if (cpu_test_and_set(cpu, cpu_initialized)) {
    5.29  		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
    5.30 @@ -614,7 +620,54 @@ void __cpuinit cpu_init(void)
    5.31  		set_in_cr4(X86_CR4_TSD);
    5.32  	}
    5.33  
    5.34 -	cpu_gdt_init(&cpu_gdt_descr[cpu]);
    5.35 +#ifndef CONFIG_XEN
    5.36 +	/*
    5.37 +	 * This is a horrible hack to allocate the GDT.  The problem
    5.38 +	 * is that cpu_init() is called really early for the boot CPU
    5.39 +	 * (and hence needs bootmem) but much later for the secondary
    5.40 +	 * CPUs, when bootmem will have gone away
    5.41 +	 */
    5.42 +	if (NODE_DATA(0)->bdata->node_bootmem_map) {
    5.43 +		gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
    5.44 +		/* alloc_bootmem_pages panics on failure, so no check */
    5.45 +		memset(gdt, 0, PAGE_SIZE);
    5.46 +	} else {
    5.47 +		gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
    5.48 +		if (unlikely(!gdt)) {
    5.49 +			printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
    5.50 +			for (;;)
    5.51 +				local_irq_enable();
    5.52 +		}
    5.53 +	}
    5.54 +
    5.55 +	/*
    5.56 +	 * Initialize the per-CPU GDT with the boot GDT,
    5.57 +	 * and set up the GDT descriptor:
    5.58 +	 */
    5.59 + 	memcpy(gdt, cpu_gdt_table, GDT_SIZE);
    5.60 +
    5.61 +	/* Set up GDT entry for 16bit stack */
    5.62 + 	*(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
    5.63 +		((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
    5.64 +		((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
    5.65 +		(CPU_16BIT_STACK_SIZE - 1);
    5.66 +
    5.67 +	cpu_gdt_descr->size = GDT_SIZE - 1;
    5.68 + 	cpu_gdt_descr->address = (unsigned long)gdt;
    5.69 +#else
    5.70 +	if (cpu == 0 && cpu_gdt_descr->address == 0) {
    5.71 +		gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
    5.72 +		/* alloc_bootmem_pages panics on failure, so no check */
    5.73 +		memset(gdt, 0, PAGE_SIZE);
    5.74 +
    5.75 +		memcpy(gdt, cpu_gdt_table, GDT_SIZE);
    5.76 +		
    5.77 +		cpu_gdt_descr->size = GDT_SIZE;
    5.78 +		cpu_gdt_descr->address = (unsigned long)gdt;
    5.79 +	}
    5.80 +#endif
    5.81 +
    5.82 +	cpu_gdt_init(cpu_gdt_descr);
    5.83  
    5.84  	/*
    5.85  	 * Set up and load the per-CPU TSS and LDT
     6.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S	Mon Feb 27 17:26:16 2006 +0100
     6.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S	Mon Feb 27 18:44:38 2006 +0100
     6.3 @@ -87,19 +87,9 @@ ENTRY(empty_zero_page)
     6.4   */
     6.5  .data
     6.6  
     6.7 -	ALIGN
     6.8 -	.word 0				# 32 bit align gdt_desc.address
     6.9 -	.globl cpu_gdt_descr
    6.10 -cpu_gdt_descr:
    6.11 -	.word GDT_SIZE
    6.12 -	.long cpu_gdt_table
    6.13 -
    6.14 -	.fill NR_CPUS-1,8,0		# space for the other GDT descriptors
    6.15 -
    6.16  /*
    6.17   * The Global Descriptor Table contains 28 quadwords, per-CPU.
    6.18   */
    6.19 -	.align PAGE_SIZE_asm
    6.20  ENTRY(cpu_gdt_table)
    6.21  	.quad 0x0000000000000000	/* NULL descriptor */
    6.22  	.quad 0x0000000000000000	/* 0x0b reserved */
    6.23 @@ -148,10 +138,6 @@ ENTRY(cpu_gdt_table)
    6.24  	.quad 0x0000000000000000	/* 0xf0 - unused */
    6.25  	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
    6.26  
    6.27 -	/* Be sure this is zeroed to avoid false validations in Xen */
    6.28 -	.fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
    6.29 -
    6.30 -
    6.31  /*
    6.32   * __xen_guest information
    6.33   */
     7.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c	Mon Feb 27 17:26:16 2006 +0100
     7.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c	Mon Feb 27 18:44:38 2006 +0100
     7.3 @@ -2634,8 +2634,10 @@ int __init io_apic_get_unique_id (int io
     7.4  		spin_unlock_irqrestore(&ioapic_lock, flags);
     7.5  
     7.6  		/* Sanity check */
     7.7 -		if (reg_00.bits.ID != apic_id)
     7.8 -			panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
     7.9 +		if (reg_00.bits.ID != apic_id) {
    7.10 +			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
    7.11 +			return -1;
    7.12 +		}
    7.13  	}
    7.14  
    7.15  	apic_printk(APIC_VERBOSE, KERN_INFO
     8.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/mpparse-xen.c	Mon Feb 27 17:26:16 2006 +0100
     8.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/mpparse-xen.c	Mon Feb 27 18:44:38 2006 +0100
     8.3 @@ -935,6 +935,7 @@ void __init mp_register_ioapic (
     8.4  	u32			gsi_base)
     8.5  {
     8.6  	int			idx = 0;
     8.7 +	int			tmpid;
     8.8  
     8.9  	if (nr_ioapics >= MAX_IO_APICS) {
    8.10  		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
    8.11 @@ -957,9 +958,14 @@ void __init mp_register_ioapic (
    8.12  	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
    8.13  #endif
    8.14  	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 < 15))
    8.15 -		mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
    8.16 +		tmpid = io_apic_get_unique_id(idx, id);
    8.17  	else
    8.18 -		mp_ioapics[idx].mpc_apicid = id;
    8.19 +		tmpid = id;
    8.20 +	if (tmpid == -1) {
    8.21 +		nr_ioapics--;
    8.22 +		return;
    8.23 +	}
    8.24 +	mp_ioapics[idx].mpc_apicid = tmpid;
    8.25  	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
    8.26  	
    8.27  	/* 
     9.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/smpboot.c	Mon Feb 27 17:26:16 2006 +0100
     9.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/smpboot.c	Mon Feb 27 18:44:38 2006 +0100
     9.3 @@ -898,12 +898,6 @@ static int __devinit do_boot_cpu(int api
     9.4  	unsigned long start_eip;
     9.5  	unsigned short nmi_high = 0, nmi_low = 0;
     9.6  
     9.7 -	if (!cpu_gdt_descr[cpu].address &&
     9.8 -	    !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
     9.9 -		printk("Failed to allocate GDT for CPU %d\n", cpu);
    9.10 -		return 1;
    9.11 -	}
    9.12 -
    9.13  	++cpucount;
    9.14  
    9.15  	/*
    10.1 --- a/linux-2.6-xen-sparse/arch/i386/mach-xen/Makefile	Mon Feb 27 17:26:16 2006 +0100
    10.2 +++ b/linux-2.6-xen-sparse/arch/i386/mach-xen/Makefile	Mon Feb 27 18:44:38 2006 +0100
    10.3 @@ -2,6 +2,4 @@
    10.4  # Makefile for the linux kernel.
    10.5  #
    10.6  
    10.7 -obj-y				:= setup.o topology.o
    10.8 -  
    10.9 -topology-y			:= ../mach-default/topology.o
   10.10 +obj-y				:= setup.o
    11.1 --- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Mon Feb 27 17:26:16 2006 +0100
    11.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Mon Feb 27 18:44:38 2006 +0100
    11.3 @@ -381,21 +381,6 @@ config HPET_TIMER
    11.4  	  as it is off-chip.  You can find the HPET spec at
    11.5  	  <http://www.intel.com/hardwaredesign/hpetspec.htm>.
    11.6  
    11.7 -config X86_PM_TIMER
    11.8 -	bool "PM timer" if EMBEDDED
    11.9 -	depends on ACPI && !X86_64_XEN
   11.10 -	default y
   11.11 -	help
   11.12 -	  Support the ACPI PM timer for time keeping. This is slow,
   11.13 -	  but is useful on some chipsets without HPET on systems with more
   11.14 -	  than one CPU. On a single processor or single socket multi core
   11.15 -	  system it is normally not required.
   11.16 -	  When the PM timer is active 64bit vsyscalls are disabled
   11.17 -	  and should not be enabled (/proc/sys/kernel/vsyscall64 should
   11.18 -	  not be changed).
   11.19 -	  The kernel selects the PM timer only as a last resort, so it is
   11.20 -	  useful to enable just in case.
   11.21 -
   11.22  config HPET_EMULATE_RTC
   11.23  	bool "Provide RTC interrupt"
   11.24  	depends on HPET_TIMER && RTC=y
   11.25 @@ -640,6 +625,7 @@ source "arch/x86_64/oprofile/Kconfig"
   11.26  
   11.27  config KPROBES
   11.28  	bool "Kprobes (EXPERIMENTAL)"
   11.29 +	depends on EXPERIMENTAL && MODULES
   11.30  	help
   11.31  	  Kprobes allows you to trap at almost any kernel address and
   11.32  	  execute a callback function.  register_kprobe() establishes
    12.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile	Mon Feb 27 17:26:16 2006 +0100
    12.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile	Mon Feb 27 18:44:38 2006 +0100
    12.3 @@ -45,7 +45,7 @@ CFLAGS_vsyscall.o		:= $(PROFILING) -g0
    12.4  
    12.5  bootflag-y			+= ../../i386/kernel/bootflag.o
    12.6  cpuid-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/cpuid.o
    12.7 -topology-y                     += ../../i386/mach-default/topology.o
    12.8 +topology-y                     += ../../i386/kernel/topology.o
    12.9  microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
   12.10  intel_cacheinfo-y		+= ../../i386/kernel/cpu/intel_cacheinfo.o
   12.11  quirks-y			+= ../../i386/kernel/quirks.o
    13.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c	Mon Feb 27 17:26:16 2006 +0100
    13.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c	Mon Feb 27 18:44:38 2006 +0100
    13.3 @@ -114,6 +114,8 @@ void smp_apic_timer_interrupt(struct pt_
    13.4  	irq_exit();
    13.5  }
    13.6  
    13.7 +int __initdata unsync_tsc_on_multicluster;
    13.8 +
    13.9  /*
   13.10   * This interrupt should _never_ happen with our APIC/SMP architecture
   13.11   */
    14.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c	Mon Feb 27 17:26:16 2006 +0100
    14.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c	Mon Feb 27 18:44:38 2006 +0100
    14.3 @@ -51,6 +51,8 @@ static int no_timer_check;
    14.4  int disable_timer_pin_1 __initdata;
    14.5  
    14.6  #ifndef CONFIG_XEN
    14.7 +int timer_over_8254 __initdata = 1;
    14.8 +
    14.9  /* Where if anywhere is the i8259 connect in external int mode */
   14.10  static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
   14.11  #endif
   14.12 @@ -301,6 +303,22 @@ static int __init enable_ioapic_setup(ch
   14.13  __setup("noapic", disable_ioapic_setup);
   14.14  __setup("apic", enable_ioapic_setup);
   14.15  
   14.16 +#ifndef CONFIG_XEN
   14.17 +static int __init setup_disable_8254_timer(char *s)
   14.18 +{
   14.19 +	timer_over_8254 = -1;
   14.20 +	return 1;
   14.21 +}
   14.22 +static int __init setup_enable_8254_timer(char *s)
   14.23 +{
   14.24 +	timer_over_8254 = 2;
   14.25 +	return 1;
   14.26 +}
   14.27 +
   14.28 +__setup("disable_8254_timer", setup_disable_8254_timer);
   14.29 +__setup("enable_8254_timer", setup_enable_8254_timer);
   14.30 +#endif /* !CONFIG_XEN */
   14.31 +
   14.32  #include <asm/pci-direct.h>
   14.33  #include <linux/pci_ids.h>
   14.34  #include <linux/pci.h>
   14.35 @@ -360,28 +378,21 @@ void __init check_ioapic(void)
   14.36  					/* RED-PEN skip them on mptables too? */
   14.37  					return;
   14.38  				case PCI_VENDOR_ID_ATI:
   14.39 +
   14.40 +				/* This should be actually default, but
   14.41 +				   for 2.6.16 let's do it for ATI only where
   14.42 +				   it's really needed. */
   14.43  #ifndef CONFIG_XEN
   14.44 -					if (apic_runs_main_timer != 0)
   14.45 -						break;
   14.46 -#ifdef CONFIG_ACPI
   14.47 -					/* Don't do this for laptops right
   14.48 -					   right now because their timer
   14.49 -					   doesn't necessarily tick in C2/3 */
   14.50 -					if (acpi_fadt.revision >= 3 &&
   14.51 -			(acpi_fadt.plvl2_lat + acpi_fadt.plvl3_lat) < 1100) {
   14.52 -						printk(KERN_INFO
   14.53 -"ATI board detected, but seems to be a laptop. Timer might be shakey, sorry\n");
   14.54 -						break;
   14.55 -					}
   14.56 -#endif					
   14.57 +					if (timer_over_8254 == 1) {	
   14.58 +						timer_over_8254 = 0;	
   14.59  					printk(KERN_INFO
   14.60 -	     "ATI board detected. Using APIC/PM timer.\n");
   14.61 -					apic_runs_main_timer = 1;
   14.62 -					nohpet = 1;
   14.63 +		"ATI board detected. Disabling timer routing over 8254.\n");
   14.64 +					}	
   14.65  #endif
   14.66  					return;
   14.67  				} 
   14.68  
   14.69 +
   14.70  				/* No multi-function device? */
   14.71  				type = read_pci_config_byte(num,slot,func,
   14.72  							    PCI_HEADER_TYPE);
   14.73 @@ -1848,6 +1859,8 @@ static inline void unlock_ExtINT_logic(v
   14.74   * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
   14.75   * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
   14.76   * fanatically on his truly buggy board.
   14.77 + *
   14.78 + * FIXME: really need to revamp this for modern platforms only.
   14.79   */
   14.80  static inline void check_timer(void)
   14.81  {
   14.82 @@ -1870,7 +1883,8 @@ static inline void check_timer(void)
   14.83  	 */
   14.84  	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
   14.85  	init_8259A(1);
   14.86 -	enable_8259A_irq(0);
   14.87 +	if (timer_over_8254 > 0)
   14.88 +		enable_8259A_irq(0);
   14.89  
   14.90  	pin1  = find_isa_irq_pin(0, mp_INT);
   14.91  	apic1 = find_isa_irq_apic(0, mp_INT);
   14.92 @@ -1925,7 +1939,7 @@ static inline void check_timer(void)
   14.93  	}
   14.94  	printk(" failed.\n");
   14.95  
   14.96 -	if (nmi_watchdog) {
   14.97 +	if (nmi_watchdog == NMI_IO_APIC) {
   14.98  		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
   14.99  		nmi_watchdog = 0;
  14.100  	}
    15.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Mon Feb 27 17:26:16 2006 +0100
    15.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Mon Feb 27 18:44:38 2006 +0100
    15.3 @@ -462,6 +462,12 @@ static __init void parse_cmdline_early (
    15.4  		else if(!memcmp(from, "elfcorehdr=", 11))
    15.5  			elfcorehdr_addr = memparse(from+11, &from);
    15.6  #endif
    15.7 +
    15.8 +#if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_XEN)
    15.9 +		else if (!memcmp(from, "additional_cpus=", 16))
   15.10 +			setup_additional_cpus(from+16);
   15.11 +#endif
   15.12 +
   15.13  	next_char:
   15.14  		c = *(from++);
   15.15  		if (!c)
    16.1 --- a/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Mon Feb 27 17:26:16 2006 +0100
    16.2 +++ b/linux-2.6-xen-sparse/drivers/acpi/Kconfig	Mon Feb 27 18:44:38 2006 +0100
    16.3 @@ -247,7 +247,7 @@ config ACPI_CUSTOM_DSDT_FILE
    16.4  	  Enter the full path name to the file wich includes the AmlCode declaration.
    16.5  
    16.6  config ACPI_BLACKLIST_YEAR
    16.7 -	int "Disable ACPI for systems before Jan 1st this year" if X86
    16.8 +	int "Disable ACPI for systems before Jan 1st this year" if X86_32
    16.9  	default 0
   16.10  	help
   16.11  	  enter a 4-digit year, eg. 2001 to disable ACPI by default
   16.12 @@ -285,9 +285,9 @@ config ACPI_SYSTEM
   16.13  	  dump your ACPI DSDT table using /proc/acpi/dsdt.
   16.14  
   16.15  config X86_PM_TIMER
   16.16 -	bool "Power Management Timer Support"
   16.17 +	bool "Power Management Timer Support" if EMBEDDED
   16.18  	depends on X86
   16.19 -	depends on !X86_64
   16.20 +	depends on !XEN
   16.21  	default y
   16.22  	help
   16.23  	  The Power Management Timer is available on all ACPI-capable,
   16.24 @@ -298,9 +298,8 @@ config X86_PM_TIMER
   16.25  	  voltage scaling, unlike the commonly used Time Stamp Counter
   16.26  	  (TSC) timing source.
   16.27  
   16.28 -	  So, if you see messages like 'Losing too many ticks!' in the
   16.29 -	  kernel logs, and/or you are using this on a notebook which
   16.30 -	  does not yet have an HPET, you should say "Y" here.
   16.31 +	  You should nearly always say Y here because many modern
   16.32 +	  systems require this timer. 
   16.33  
   16.34  config ACPI_CONTAINER
   16.35  	tristate "ACPI0004,PNP0A05 and PNP0A06 Container Driver (EXPERIMENTAL)"
    17.1 --- a/linux-2.6-xen-sparse/drivers/video/Kconfig	Mon Feb 27 17:26:16 2006 +0100
    17.2 +++ b/linux-2.6-xen-sparse/drivers/video/Kconfig	Mon Feb 27 18:44:38 2006 +0100
    17.3 @@ -520,7 +520,7 @@ config FB_GBE
    17.4  config FB_GBE_MEM
    17.5  	int "Video memory size in MB"
    17.6  	depends on FB_GBE
    17.7 -	default 8
    17.8 +	default 4
    17.9  	help
   17.10  	  This is the amount of memory reserved for the framebuffer,
   17.11  	  which can be any value between 1MB and 8MB.
    18.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c	Mon Feb 27 17:26:16 2006 +0100
    18.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c	Mon Feb 27 18:44:38 2006 +0100
    18.3 @@ -150,6 +150,11 @@ void vcpu_prepare(int vcpu)
    18.4  {
    18.5  	vcpu_guest_context_t ctxt;
    18.6  	struct task_struct *idle = idle_task(vcpu);
    18.7 +#ifdef __x86_64__
    18.8 +	struct desc_ptr *gdt_descr = &cpu_gdt_descr[vcpu];
    18.9 +#else
   18.10 +	struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, vcpu);
   18.11 +#endif
   18.12  
   18.13  	if (vcpu == 0)
   18.14  		return;
   18.15 @@ -171,8 +176,8 @@ void vcpu_prepare(int vcpu)
   18.16  
   18.17  	ctxt.ldt_ents = 0;
   18.18  
   18.19 -	ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[vcpu].address);
   18.20 -	ctxt.gdt_ents      = cpu_gdt_descr[vcpu].size / 8;
   18.21 +	ctxt.gdt_frames[0] = virt_to_mfn(gdt_descr->address);
   18.22 +	ctxt.gdt_ents      = gdt_descr->size / 8;
   18.23  
   18.24  #ifdef __i386__
   18.25  	ctxt.user_regs.cs = __KERNEL_CS;
   18.26 @@ -210,6 +215,11 @@ void __init smp_prepare_cpus(unsigned in
   18.27  {
   18.28  	int cpu;
   18.29  	struct task_struct *idle;
   18.30 +#ifdef __x86_64__
   18.31 +	struct desc_ptr *gdt_descr;
   18.32 +#else
   18.33 +	struct Xgt_desc_struct *gdt_descr;
   18.34 +#endif
   18.35  
   18.36  	cpu_data[0] = boot_cpu_data;
   18.37  
   18.38 @@ -226,6 +236,22 @@ void __init smp_prepare_cpus(unsigned in
   18.39  		if (cpu == 0)
   18.40  			continue;
   18.41  
   18.42 +#ifdef __x86_64__
   18.43 +		gdt_descr = &cpu_gdt_descr[cpu];
   18.44 +#else
   18.45 +		gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
   18.46 +#endif
   18.47 +		gdt_descr->address = get_zeroed_page(GFP_KERNEL);
   18.48 +		if (unlikely(!gdt_descr->address)) {
   18.49 +			printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
   18.50 +			continue;
   18.51 +		}
   18.52 +		gdt_descr->size = GDT_SIZE;
   18.53 +		memcpy((void *)gdt_descr->address, cpu_gdt_table, GDT_SIZE);
   18.54 +		make_page_readonly(
   18.55 +			(void *)gdt_descr->address,
   18.56 +			XENFEAT_writable_descriptor_tables);
   18.57 +
   18.58  		cpu_data[cpu] = boot_cpu_data;
   18.59  		cpu_2_logical_apicid[cpu] = cpu;
   18.60  		x86_cpu_to_apicid[cpu] = cpu;
   18.61 @@ -242,17 +268,6 @@ void __init smp_prepare_cpus(unsigned in
   18.62  
   18.63  		irq_ctx_init(cpu);
   18.64  
   18.65 -		cpu_gdt_descr[cpu].address =
   18.66 -			__get_free_page(GFP_KERNEL|__GFP_ZERO);
   18.67 -		BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
   18.68 -		cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
   18.69 -		memcpy((void *)cpu_gdt_descr[cpu].address,
   18.70 -		       (void *)cpu_gdt_descr[0].address,
   18.71 -		       cpu_gdt_descr[0].size);
   18.72 -		make_page_readonly(
   18.73 -			(void *)cpu_gdt_descr[cpu].address,
   18.74 -			XENFEAT_writable_descriptor_tables);
   18.75 -
   18.76  #ifdef CONFIG_HOTPLUG_CPU
   18.77  		if (xen_start_info->flags & SIF_INITDOMAIN)
   18.78  			cpu_set(cpu, cpu_present_map);
    19.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/desc.h	Mon Feb 27 17:26:16 2006 +0100
    19.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/desc.h	Mon Feb 27 18:44:38 2006 +0100
    19.3 @@ -23,11 +23,13 @@ struct Xgt_desc_struct {
    19.4  	unsigned short pad;
    19.5  } __attribute__ ((packed));
    19.6  
    19.7 -extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
    19.8 +extern struct Xgt_desc_struct idt_descr;
    19.9 +DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
   19.10 +
   19.11  
   19.12  static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
   19.13  {
   19.14 -	return ((struct desc_struct *)cpu_gdt_descr[cpu].address);
   19.15 +	return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
   19.16  }
   19.17  
   19.18  #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
    20.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h	Mon Feb 27 17:26:16 2006 +0100
    20.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h	Mon Feb 27 18:44:38 2006 +0100
    20.3 @@ -19,8 +19,6 @@ extern unsigned int pcibios_assign_all_b
    20.4  #endif
    20.5  #define pcibios_scan_all_fns(a, b)	0
    20.6  
    20.7 -extern int no_iommu, force_iommu;
    20.8 -
    20.9  extern unsigned long pci_mem_start;
   20.10  #define PCIBIOS_MIN_IO		0x1000
   20.11  #define PCIBIOS_MIN_MEM		(pci_mem_start)
    21.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h	Mon Feb 27 17:26:16 2006 +0100
    21.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h	Mon Feb 27 18:44:38 2006 +0100
    21.3 @@ -169,7 +169,7 @@ static inline pte_t ptep_get_and_clear_f
    21.4  #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
    21.5  #define PGDIR_MASK	(~(PGDIR_SIZE-1))
    21.6  
    21.7 -#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
    21.8 +#define USER_PTRS_PER_PGD	((TASK_SIZE-1)/PGDIR_SIZE+1)
    21.9  #define FIRST_USER_ADDRESS	0
   21.10  
   21.11  #ifndef __ASSEMBLY__
    22.1 --- a/linux-2.6-xen-sparse/include/linux/mm.h	Mon Feb 27 17:26:16 2006 +0100
    22.2 +++ b/linux-2.6-xen-sparse/include/linux/mm.h	Mon Feb 27 18:44:38 2006 +0100
    22.3 @@ -1064,7 +1064,11 @@ int shrink_slab(unsigned long scanned, g
    22.4  void drop_pagecache(void);
    22.5  void drop_slab(void);
    22.6  
    22.7 +#ifndef CONFIG_MMU
    22.8 +#define randomize_va_space 0
    22.9 +#else
   22.10  extern int randomize_va_space;
   22.11 +#endif
   22.12  
   22.13  #endif /* __KERNEL__ */
   22.14  #endif /* _LINUX_MM_H */
    23.1 --- a/linux-2.6-xen-sparse/mm/page_alloc.c	Mon Feb 27 17:26:16 2006 +0100
    23.2 +++ b/linux-2.6-xen-sparse/mm/page_alloc.c	Mon Feb 27 18:44:38 2006 +0100
    23.3 @@ -1017,7 +1017,7 @@ rebalance:
    23.4  		if (page)
    23.5  			goto got_pg;
    23.6  
    23.7 -		out_of_memory(gfp_mask, order);
    23.8 +		out_of_memory(zonelist, gfp_mask, order);
    23.9  		goto restart;
   23.10  	}
   23.11  
    24.1 --- a/linux-2.6-xen-sparse/net/core/skbuff.c	Mon Feb 27 17:26:16 2006 +0100
    24.2 +++ b/linux-2.6-xen-sparse/net/core/skbuff.c	Mon Feb 27 18:44:38 2006 +0100
    24.3 @@ -434,6 +434,9 @@ struct sk_buff *skb_clone(struct sk_buff
    24.4  	C(pkt_type);
    24.5  	C(ip_summed);
    24.6  	C(priority);
    24.7 +#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
    24.8 +	C(ipvs_property);
    24.9 +#endif
   24.10  	C(protocol);
   24.11  	n->destructor = NULL;
   24.12  #ifdef CONFIG_NETFILTER
   24.13 @@ -445,13 +448,6 @@ struct sk_buff *skb_clone(struct sk_buff
   24.14  	C(nfct_reasm);
   24.15  	nf_conntrack_get_reasm(skb->nfct_reasm);
   24.16  #endif
   24.17 -#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
   24.18 -	C(ipvs_property);
   24.19 -#endif
   24.20 -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
   24.21 -	C(nfct_reasm);
   24.22 -	nf_conntrack_get_reasm(skb->nfct_reasm);
   24.23 -#endif
   24.24  #ifdef CONFIG_BRIDGE_NETFILTER
   24.25  	C(nf_bridge);
   24.26  	nf_bridge_get(skb->nf_bridge);
    25.1 --- a/patches/linux-2.6.16-rc4/i386-mach-io-check-nmi.patch	Mon Feb 27 17:26:16 2006 +0100
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,45 +0,0 @@
    25.4 -diff -pruN ../pristine-linux-2.6.16-rc3/arch/i386/kernel/traps.c ./arch/i386/kernel/traps.c
    25.5 ---- ../pristine-linux-2.6.16-rc3/arch/i386/kernel/traps.c	2006-02-15 20:38:51.000000000 +0000
    25.6 -+++ ./arch/i386/kernel/traps.c	2006-02-15 20:40:43.000000000 +0000
    25.7 -@@ -567,18 +567,11 @@ static void mem_parity_error(unsigned ch
    25.8 - 
    25.9 - static void io_check_error(unsigned char reason, struct pt_regs * regs)
   25.10 - {
   25.11 --	unsigned long i;
   25.12 --
   25.13 - 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
   25.14 - 	show_registers(regs);
   25.15 - 
   25.16 - 	/* Re-enable the IOCK line, wait for a few seconds */
   25.17 --	reason = (reason & 0xf) | 8;
   25.18 --	outb(reason, 0x61);
   25.19 --	i = 2000;
   25.20 --	while (--i) udelay(1000);
   25.21 --	reason &= ~8;
   25.22 --	outb(reason, 0x61);
   25.23 -+	clear_io_check_error(reason);
   25.24 - }
   25.25 - 
   25.26 - static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
   25.27 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/mach-default/mach_traps.h ./include/asm-i386/mach-default/mach_traps.h
   25.28 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/mach-default/mach_traps.h	2006-01-03 03:21:10.000000000 +0000
   25.29 -+++ ./include/asm-i386/mach-default/mach_traps.h	2006-02-15 20:40:43.000000000 +0000
   25.30 -@@ -15,6 +15,18 @@ static inline void clear_mem_error(unsig
   25.31 - 	outb(reason, 0x61);
   25.32 - }
   25.33 - 
   25.34 -+static inline void clear_io_check_error(unsigned char reason)
   25.35 -+{
   25.36 -+	unsigned long i;
   25.37 -+
   25.38 -+	reason = (reason & 0xf) | 8;
   25.39 -+	outb(reason, 0x61);
   25.40 -+	i = 2000;
   25.41 -+	while (--i) udelay(1000);
   25.42 -+	reason &= ~8;
   25.43 -+	outb(reason, 0x61);
   25.44 -+}
   25.45 -+
   25.46 - static inline unsigned char get_nmi_reason(void)
   25.47 - {
   25.48 - 	return inb(0x61);
    26.1 --- a/patches/linux-2.6.16-rc4/net-csum.patch	Mon Feb 27 17:26:16 2006 +0100
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,41 +0,0 @@
    26.4 -diff -pruN ../pristine-linux-2.6.16-rc1-git4/net/ipv4/netfilter/ip_nat_proto_tcp.c ./net/ipv4/netfilter/ip_nat_proto_tcp.c
    26.5 ---- ../pristine-linux-2.6.16-rc1-git4/net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-02-02 17:39:51.000000000 +0000
    26.6 -+++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-02-02 17:44:18.000000000 +0000
    26.7 -@@ -129,10 +129,14 @@ tcp_manip_pkt(struct sk_buff **pskb,
    26.8 - 	if (hdrsize < sizeof(*hdr))
    26.9 - 		return 1;
   26.10 - 
   26.11 --	hdr->check = ip_nat_cheat_check(~oldip, newip,
   26.12 -+	if ((*pskb)->proto_csum_blank) {
   26.13 -+		hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   26.14 -+	} else {
   26.15 -+		hdr->check = ip_nat_cheat_check(~oldip, newip,
   26.16 - 					ip_nat_cheat_check(oldport ^ 0xFFFF,
   26.17 - 							   newport,
   26.18 - 							   hdr->check));
   26.19 -+	}
   26.20 - 	return 1;
   26.21 - }
   26.22 -
   26.23 -diff -pruN ../pristine-linux-2.6.16-rc1-git4/net/ipv4/netfilter/ip_nat_proto_udp.c ./net/ipv4/netfilter/ip_nat_proto_udp.c
   26.24 ---- ../pristine-linux-2.6.16-rc1-git4/net/ipv4/netfilter/ip_nat_proto_udp.c	2006-02-02 17:39:51.000000000 +0000
   26.25 -+++ ./net/ipv4/netfilter/ip_nat_proto_udp.c	2006-02-02 17:44:18.000000000 +0000
   26.26 -@@ -113,11 +113,16 @@ udp_manip_pkt(struct sk_buff **pskb,
   26.27 - 		newport = tuple->dst.u.udp.port;
   26.28 - 		portptr = &hdr->dest;
   26.29 - 	}
   26.30 --	if (hdr->check) /* 0 is a special case meaning no checksum */
   26.31 --		hdr->check = ip_nat_cheat_check(~oldip, newip,
   26.32 -+	if (hdr->check) { /* 0 is a special case meaning no checksum */
   26.33 -+		if ((*pskb)->proto_csum_blank) {
   26.34 -+			hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   26.35 -+		} else {
   26.36 -+			hdr->check = ip_nat_cheat_check(~oldip, newip,
   26.37 - 					ip_nat_cheat_check(*portptr ^ 0xFFFF,
   26.38 - 							   newport,
   26.39 - 							   hdr->check));
   26.40 -+		}
   26.41 -+	}
   26.42 - 	*portptr = newport;
   26.43 - 	return 1;
   26.44 - }
    27.1 --- a/patches/linux-2.6.16-rc4/pmd-shared.patch	Mon Feb 27 17:26:16 2006 +0100
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,111 +0,0 @@
    27.4 -diff -pruN ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pageattr.c ./arch/i386/mm/pageattr.c
    27.5 ---- ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pageattr.c	2006-02-02 17:39:29.000000000 +0000
    27.6 -+++ ./arch/i386/mm/pageattr.c	2006-02-02 17:45:14.000000000 +0000
    27.7 -@@ -78,7 +78,7 @@ static void set_pmd_pte(pte_t *kpte, uns
    27.8 - 	unsigned long flags;
    27.9 - 
   27.10 - 	set_pte_atomic(kpte, pte); 	/* change init_mm */
   27.11 --	if (PTRS_PER_PMD > 1)
   27.12 -+	if (HAVE_SHARED_KERNEL_PMD)
   27.13 - 		return;
   27.14 - 
   27.15 - 	spin_lock_irqsave(&pgd_lock, flags);
   27.16 -diff -pruN ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pgtable.c ./arch/i386/mm/pgtable.c
   27.17 ---- ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pgtable.c	2006-01-03 03:21:10.000000000 +0000
   27.18 -+++ ./arch/i386/mm/pgtable.c	2006-02-02 17:45:14.000000000 +0000
   27.19 -@@ -215,9 +215,10 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
   27.20 - 		spin_lock_irqsave(&pgd_lock, flags);
   27.21 - 	}
   27.22 - 
   27.23 --	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   27.24 --			swapper_pg_dir + USER_PTRS_PER_PGD,
   27.25 --			KERNEL_PGD_PTRS);
   27.26 -+	if (PTRS_PER_PMD == 1 || HAVE_SHARED_KERNEL_PMD)
   27.27 -+		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   27.28 -+				swapper_pg_dir + USER_PTRS_PER_PGD,
   27.29 -+				KERNEL_PGD_PTRS);
   27.30 - 	if (PTRS_PER_PMD > 1)
   27.31 - 		return;
   27.32 - 
   27.33 -@@ -249,6 +250,30 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
   27.34 - 			goto out_oom;
   27.35 - 		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
   27.36 - 	}
   27.37 -+
   27.38 -+	if (!HAVE_SHARED_KERNEL_PMD) {
   27.39 -+		unsigned long flags;
   27.40 -+
   27.41 -+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   27.42 -+			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
   27.43 -+			if (!pmd)
   27.44 -+				goto out_oom;
   27.45 -+			set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
   27.46 -+		}
   27.47 -+
   27.48 -+		spin_lock_irqsave(&pgd_lock, flags);
   27.49 -+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   27.50 -+			unsigned long v = (unsigned long)i << PGDIR_SHIFT;
   27.51 -+			pgd_t *kpgd = pgd_offset_k(v);
   27.52 -+			pud_t *kpud = pud_offset(kpgd, v);
   27.53 -+			pmd_t *kpmd = pmd_offset(kpud, v);
   27.54 -+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   27.55 -+			memcpy(pmd, kpmd, PAGE_SIZE);
   27.56 -+		}
   27.57 -+		pgd_list_add(pgd);
   27.58 -+		spin_unlock_irqrestore(&pgd_lock, flags);
   27.59 -+	}
   27.60 -+
   27.61 - 	return pgd;
   27.62 - 
   27.63 - out_oom:
   27.64 -@@ -263,9 +288,23 @@ void pgd_free(pgd_t *pgd)
   27.65 - 	int i;
   27.66 - 
   27.67 - 	/* in the PAE case user pgd entries are overwritten before usage */
   27.68 --	if (PTRS_PER_PMD > 1)
   27.69 --		for (i = 0; i < USER_PTRS_PER_PGD; ++i)
   27.70 --			kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
   27.71 -+	if (PTRS_PER_PMD > 1) {
   27.72 -+		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
   27.73 -+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   27.74 -+			kmem_cache_free(pmd_cache, pmd);
   27.75 -+		}
   27.76 -+		if (!HAVE_SHARED_KERNEL_PMD) {
   27.77 -+			unsigned long flags;
   27.78 -+			spin_lock_irqsave(&pgd_lock, flags);
   27.79 -+			pgd_list_del(pgd);
   27.80 -+			spin_unlock_irqrestore(&pgd_lock, flags);
   27.81 -+			for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   27.82 -+				pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   27.83 -+				memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
   27.84 -+				kmem_cache_free(pmd_cache, pmd);
   27.85 -+			}
   27.86 -+		}
   27.87 -+	}
   27.88 - 	/* in the non-PAE case, free_pgtables() clears user pgd entries */
   27.89 - 	kmem_cache_free(pgd_cache, pgd);
   27.90 - }
   27.91 -diff -pruN ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-2level-defs.h ./include/asm-i386/pgtable-2level-defs.h
   27.92 ---- ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-2level-defs.h	2006-01-03 03:21:10.000000000 +0000
   27.93 -+++ ./include/asm-i386/pgtable-2level-defs.h	2006-02-02 17:45:14.000000000 +0000
   27.94 -@@ -1,6 +1,8 @@
   27.95 - #ifndef _I386_PGTABLE_2LEVEL_DEFS_H
   27.96 - #define _I386_PGTABLE_2LEVEL_DEFS_H
   27.97 - 
   27.98 -+#define HAVE_SHARED_KERNEL_PMD 0
   27.99 -+
  27.100 - /*
  27.101 -  * traditional i386 two-level paging structure:
  27.102 -  */
  27.103 -diff -pruN ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-3level-defs.h ./include/asm-i386/pgtable-3level-defs.h
  27.104 ---- ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-3level-defs.h	2006-01-03 03:21:10.000000000 +0000
  27.105 -+++ ./include/asm-i386/pgtable-3level-defs.h	2006-02-02 17:45:14.000000000 +0000
  27.106 -@@ -1,6 +1,8 @@
  27.107 - #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
  27.108 - #define _I386_PGTABLE_3LEVEL_DEFS_H
  27.109 - 
  27.110 -+#define HAVE_SHARED_KERNEL_PMD 1
  27.111 -+
  27.112 - /*
  27.113 -  * PGDIR_SHIFT determines what a top-level page table entry can map
  27.114 -  */
    28.1 --- a/patches/linux-2.6.16-rc4/smp-alts.patch	Mon Feb 27 17:26:16 2006 +0100
    28.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.3 @@ -1,591 +0,0 @@
    28.4 -diff -pruN ../pristine-linux-2.6.16-rc3/arch/i386/Kconfig ./arch/i386/Kconfig
    28.5 ---- ../pristine-linux-2.6.16-rc3/arch/i386/Kconfig	2006-02-15 20:38:51.000000000 +0000
    28.6 -+++ ./arch/i386/Kconfig	2006-02-15 20:45:57.000000000 +0000
    28.7 -@@ -202,6 +202,19 @@ config SMP
    28.8 - 
    28.9 - 	  If you don't know what to do here, say N.
   28.10 - 
   28.11 -+config SMP_ALTERNATIVES
   28.12 -+	bool "SMP alternatives support (EXPERIMENTAL)"
   28.13 -+	depends on SMP && EXPERIMENTAL
   28.14 -+	help
   28.15 -+	  Try to reduce the overhead of running an SMP kernel on a uniprocessor
   28.16 -+	  host slightly by replacing certain key instruction sequences
   28.17 -+	  according to whether we currently have more than one CPU available.
   28.18 -+	  This should provide a noticeable boost to performance when
   28.19 -+	  running SMP kernels on UP machines, and have negligible impact
   28.20 -+	  when running on an true SMP host.
   28.21 -+
   28.22 -+          If unsure, say N.
   28.23 -+	  
   28.24 - config NR_CPUS
   28.25 - 	int "Maximum number of CPUs (2-255)"
   28.26 - 	range 2 255
   28.27 -diff -pruN ../pristine-linux-2.6.16-rc3/arch/i386/kernel/Makefile ./arch/i386/kernel/Makefile
   28.28 ---- ../pristine-linux-2.6.16-rc3/arch/i386/kernel/Makefile	2006-02-15 20:38:51.000000000 +0000
   28.29 -+++ ./arch/i386/kernel/Makefile	2006-02-15 20:45:57.000000000 +0000
   28.30 -@@ -37,6 +37,7 @@ obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
   28.31 - obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault.o
   28.32 - obj-$(CONFIG_VM86)		+= vm86.o
   28.33 - obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
   28.34 -+obj-$(CONFIG_SMP_ALTERNATIVES)  += smpalts.o
   28.35 - 
   28.36 - EXTRA_AFLAGS   := -traditional
   28.37 - 
   28.38 -diff -pruN ../pristine-linux-2.6.16-rc3/arch/i386/kernel/smpalts.c ./arch/i386/kernel/smpalts.c
   28.39 ---- ../pristine-linux-2.6.16-rc3/arch/i386/kernel/smpalts.c	1970-01-01 01:00:00.000000000 +0100
   28.40 -+++ ./arch/i386/kernel/smpalts.c	2006-02-15 20:45:57.000000000 +0000
   28.41 -@@ -0,0 +1,85 @@
   28.42 -+#include <linux/kernel.h>
   28.43 -+#include <asm/system.h>
   28.44 -+#include <asm/smp_alt.h>
   28.45 -+#include <asm/processor.h>
   28.46 -+#include <asm/string.h>
   28.47 -+
   28.48 -+struct smp_replacement_record {
   28.49 -+	unsigned char targ_size;
   28.50 -+	unsigned char smp1_size;
   28.51 -+	unsigned char smp2_size;
   28.52 -+	unsigned char up_size;
   28.53 -+	unsigned char feature;
   28.54 -+	unsigned char data[0];
   28.55 -+};
   28.56 -+
   28.57 -+struct smp_alternative_record {
   28.58 -+	void *targ_start;
   28.59 -+	struct smp_replacement_record *repl;
   28.60 -+};
   28.61 -+
   28.62 -+extern struct smp_alternative_record __start_smp_alternatives_table,
   28.63 -+  __stop_smp_alternatives_table;
   28.64 -+extern unsigned long __init_begin, __init_end;
   28.65 -+
   28.66 -+void prepare_for_smp(void)
   28.67 -+{
   28.68 -+	struct smp_alternative_record *r;
   28.69 -+	printk(KERN_INFO "Enabling SMP...\n");
   28.70 -+	for (r = &__start_smp_alternatives_table;
   28.71 -+	     r != &__stop_smp_alternatives_table;
   28.72 -+	     r++) {
   28.73 -+		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
   28.74 -+		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
   28.75 -+		BUG_ON(r->repl->targ_size < r->repl->up_size);
   28.76 -+               if (system_state == SYSTEM_RUNNING &&
   28.77 -+                   r->targ_start >= (void *)&__init_begin &&
   28.78 -+                   r->targ_start < (void *)&__init_end)
   28.79 -+                       continue;
   28.80 -+		if (r->repl->feature != (unsigned char)-1 &&
   28.81 -+		    boot_cpu_has(r->repl->feature)) {
   28.82 -+			memcpy(r->targ_start,
   28.83 -+			       r->repl->data + r->repl->smp1_size,
   28.84 -+			       r->repl->smp2_size);
   28.85 -+			memset(r->targ_start + r->repl->smp2_size,
   28.86 -+			       0x90,
   28.87 -+			       r->repl->targ_size - r->repl->smp2_size);
   28.88 -+		} else {
   28.89 -+			memcpy(r->targ_start,
   28.90 -+			       r->repl->data,
   28.91 -+			       r->repl->smp1_size);
   28.92 -+			memset(r->targ_start + r->repl->smp1_size,
   28.93 -+			       0x90,
   28.94 -+			       r->repl->targ_size - r->repl->smp1_size);
   28.95 -+		}
   28.96 -+	}
   28.97 -+	/* Paranoia */
   28.98 -+	asm volatile ("jmp 1f\n1:");
   28.99 -+	mb();
  28.100 -+}
  28.101 -+
  28.102 -+void unprepare_for_smp(void)
  28.103 -+{
  28.104 -+	struct smp_alternative_record *r;
  28.105 -+	printk(KERN_INFO "Disabling SMP...\n");
  28.106 -+	for (r = &__start_smp_alternatives_table;
  28.107 -+	     r != &__stop_smp_alternatives_table;
  28.108 -+	     r++) {
  28.109 -+		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
  28.110 -+		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
  28.111 -+		BUG_ON(r->repl->targ_size < r->repl->up_size);
  28.112 -+               if (system_state == SYSTEM_RUNNING &&
  28.113 -+                   r->targ_start >= (void *)&__init_begin &&
  28.114 -+                   r->targ_start < (void *)&__init_end)
  28.115 -+                       continue;
  28.116 -+		memcpy(r->targ_start,
  28.117 -+		       r->repl->data + r->repl->smp1_size + r->repl->smp2_size,
  28.118 -+		       r->repl->up_size);
  28.119 -+		memset(r->targ_start + r->repl->up_size,
  28.120 -+		       0x90,
  28.121 -+		       r->repl->targ_size - r->repl->up_size);
  28.122 -+	}
  28.123 -+	/* Paranoia */
  28.124 -+	asm volatile ("jmp 1f\n1:");
  28.125 -+	mb();
  28.126 -+}
  28.127 -diff -pruN ../pristine-linux-2.6.16-rc3/arch/i386/kernel/smpboot.c ./arch/i386/kernel/smpboot.c
  28.128 ---- ../pristine-linux-2.6.16-rc3/arch/i386/kernel/smpboot.c	2006-02-15 20:38:51.000000000 +0000
  28.129 -+++ ./arch/i386/kernel/smpboot.c	2006-02-15 20:45:57.000000000 +0000
  28.130 -@@ -1214,6 +1214,11 @@ static void __init smp_boot_cpus(unsigne
  28.131 - 		if (max_cpus <= cpucount+1)
  28.132 - 			continue;
  28.133 - 
  28.134 -+#ifdef CONFIG_SMP_ALTERNATIVES
  28.135 -+		if (kicked == 1)
  28.136 -+			prepare_for_smp();
  28.137 -+#endif
  28.138 -+
  28.139 - 		if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
  28.140 - 			printk("CPU #%d not responding - cannot use it.\n",
  28.141 - 								apicid);
  28.142 -@@ -1392,6 +1397,11 @@ int __devinit __cpu_up(unsigned int cpu)
  28.143 - 		return -EIO;
  28.144 - 	}
  28.145 - 
  28.146 -+#ifdef CONFIG_SMP_ALTERNATIVES
  28.147 -+	if (num_online_cpus() == 1)
  28.148 -+		prepare_for_smp();
  28.149 -+#endif
  28.150 -+
  28.151 - 	local_irq_enable();
  28.152 - 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
  28.153 - 	/* Unleash the CPU! */
  28.154 -diff -pruN ../pristine-linux-2.6.16-rc3/arch/i386/kernel/vmlinux.lds.S ./arch/i386/kernel/vmlinux.lds.S
  28.155 ---- ../pristine-linux-2.6.16-rc3/arch/i386/kernel/vmlinux.lds.S	2006-01-03 03:21:10.000000000 +0000
  28.156 -+++ ./arch/i386/kernel/vmlinux.lds.S	2006-02-15 20:45:57.000000000 +0000
  28.157 -@@ -34,6 +34,13 @@ SECTIONS
  28.158 -   __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
  28.159 -   __stop___ex_table = .;
  28.160 - 
  28.161 -+  . = ALIGN(16);
  28.162 -+  __start_smp_alternatives_table = .;
  28.163 -+  __smp_alternatives : { *(__smp_alternatives) }
  28.164 -+  __stop_smp_alternatives_table = .;
  28.165 -+
  28.166 -+  __smp_replacements : { *(__smp_replacements) }
  28.167 -+
  28.168 -   RODATA
  28.169 - 
  28.170 -   /* writeable */
  28.171 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/atomic.h ./include/asm-i386/atomic.h
  28.172 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/atomic.h	2006-02-15 20:38:57.000000000 +0000
  28.173 -+++ ./include/asm-i386/atomic.h	2006-02-15 20:45:57.000000000 +0000
  28.174 -@@ -4,18 +4,13 @@
  28.175 - #include <linux/config.h>
  28.176 - #include <linux/compiler.h>
  28.177 - #include <asm/processor.h>
  28.178 -+#include <asm/smp_alt.h>
  28.179 - 
  28.180 - /*
  28.181 -  * Atomic operations that C can't guarantee us.  Useful for
  28.182 -  * resource counting etc..
  28.183 -  */
  28.184 - 
  28.185 --#ifdef CONFIG_SMP
  28.186 --#define LOCK "lock ; "
  28.187 --#else
  28.188 --#define LOCK ""
  28.189 --#endif
  28.190 --
  28.191 - /*
  28.192 -  * Make sure gcc doesn't try to be clever and move things around
  28.193 -  * on us. We need to use _exactly_ the address the user gave us,
  28.194 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/bitops.h ./include/asm-i386/bitops.h
  28.195 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/bitops.h	2006-02-15 20:38:57.000000000 +0000
  28.196 -+++ ./include/asm-i386/bitops.h	2006-02-15 20:45:57.000000000 +0000
  28.197 -@@ -7,6 +7,7 @@
  28.198 - 
  28.199 - #include <linux/config.h>
  28.200 - #include <linux/compiler.h>
  28.201 -+#include <asm/smp_alt.h>
  28.202 - 
  28.203 - /*
  28.204 -  * These have to be done with inline assembly: that way the bit-setting
  28.205 -@@ -16,12 +17,6 @@
  28.206 -  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  28.207 -  */
  28.208 - 
  28.209 --#ifdef CONFIG_SMP
  28.210 --#define LOCK_PREFIX "lock ; "
  28.211 --#else
  28.212 --#define LOCK_PREFIX ""
  28.213 --#endif
  28.214 --
  28.215 - #define ADDR (*(volatile long *) addr)
  28.216 - 
  28.217 - /**
  28.218 -@@ -41,7 +36,7 @@
  28.219 -  */
  28.220 - static inline void set_bit(int nr, volatile unsigned long * addr)
  28.221 - {
  28.222 --	__asm__ __volatile__( LOCK_PREFIX
  28.223 -+	__asm__ __volatile__( LOCK
  28.224 - 		"btsl %1,%0"
  28.225 - 		:"+m" (ADDR)
  28.226 - 		:"Ir" (nr));
  28.227 -@@ -76,7 +71,7 @@ static inline void __set_bit(int nr, vol
  28.228 -  */
  28.229 - static inline void clear_bit(int nr, volatile unsigned long * addr)
  28.230 - {
  28.231 --	__asm__ __volatile__( LOCK_PREFIX
  28.232 -+	__asm__ __volatile__( LOCK
  28.233 - 		"btrl %1,%0"
  28.234 - 		:"+m" (ADDR)
  28.235 - 		:"Ir" (nr));
  28.236 -@@ -121,7 +116,7 @@ static inline void __change_bit(int nr, 
  28.237 -  */
  28.238 - static inline void change_bit(int nr, volatile unsigned long * addr)
  28.239 - {
  28.240 --	__asm__ __volatile__( LOCK_PREFIX
  28.241 -+	__asm__ __volatile__( LOCK
  28.242 - 		"btcl %1,%0"
  28.243 - 		:"+m" (ADDR)
  28.244 - 		:"Ir" (nr));
  28.245 -@@ -140,7 +135,7 @@ static inline int test_and_set_bit(int n
  28.246 - {
  28.247 - 	int oldbit;
  28.248 - 
  28.249 --	__asm__ __volatile__( LOCK_PREFIX
  28.250 -+	__asm__ __volatile__( LOCK
  28.251 - 		"btsl %2,%1\n\tsbbl %0,%0"
  28.252 - 		:"=r" (oldbit),"+m" (ADDR)
  28.253 - 		:"Ir" (nr) : "memory");
  28.254 -@@ -180,7 +175,7 @@ static inline int test_and_clear_bit(int
  28.255 - {
  28.256 - 	int oldbit;
  28.257 - 
  28.258 --	__asm__ __volatile__( LOCK_PREFIX
  28.259 -+	__asm__ __volatile__( LOCK
  28.260 - 		"btrl %2,%1\n\tsbbl %0,%0"
  28.261 - 		:"=r" (oldbit),"+m" (ADDR)
  28.262 - 		:"Ir" (nr) : "memory");
  28.263 -@@ -231,7 +226,7 @@ static inline int test_and_change_bit(in
  28.264 - {
  28.265 - 	int oldbit;
  28.266 - 
  28.267 --	__asm__ __volatile__( LOCK_PREFIX
  28.268 -+	__asm__ __volatile__( LOCK
  28.269 - 		"btcl %2,%1\n\tsbbl %0,%0"
  28.270 - 		:"=r" (oldbit),"+m" (ADDR)
  28.271 - 		:"Ir" (nr) : "memory");
  28.272 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/futex.h ./include/asm-i386/futex.h
  28.273 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/futex.h	2006-02-15 20:38:57.000000000 +0000
  28.274 -+++ ./include/asm-i386/futex.h	2006-02-15 20:45:57.000000000 +0000
  28.275 -@@ -28,7 +28,7 @@
  28.276 - "1:	movl	%2, %0\n\
  28.277 - 	movl	%0, %3\n"					\
  28.278 - 	insn "\n"						\
  28.279 --"2:	" LOCK_PREFIX "cmpxchgl %3, %2\n\
  28.280 -+"2:	" LOCK "cmpxchgl %3, %2\n\
  28.281 - 	jnz	1b\n\
  28.282 - 3:	.section .fixup,\"ax\"\n\
  28.283 - 4:	mov	%5, %1\n\
  28.284 -@@ -68,7 +68,7 @@ futex_atomic_op_inuser (int encoded_op, 
  28.285 - #endif
  28.286 - 		switch (op) {
  28.287 - 		case FUTEX_OP_ADD:
  28.288 --			__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
  28.289 -+			__futex_atomic_op1(LOCK "xaddl %0, %2", ret,
  28.290 - 					   oldval, uaddr, oparg);
  28.291 - 			break;
  28.292 - 		case FUTEX_OP_OR:
  28.293 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/rwsem.h ./include/asm-i386/rwsem.h
  28.294 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/rwsem.h	2006-01-03 03:21:10.000000000 +0000
  28.295 -+++ ./include/asm-i386/rwsem.h	2006-02-15 20:45:57.000000000 +0000
  28.296 -@@ -40,6 +40,7 @@
  28.297 - 
  28.298 - #include <linux/list.h>
  28.299 - #include <linux/spinlock.h>
  28.300 -+#include <asm/smp_alt.h>
  28.301 - 
  28.302 - struct rwsem_waiter;
  28.303 - 
  28.304 -@@ -99,7 +100,7 @@ static inline void __down_read(struct rw
  28.305 - {
  28.306 - 	__asm__ __volatile__(
  28.307 - 		"# beginning down_read\n\t"
  28.308 --LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  28.309 -+LOCK	        "  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  28.310 - 		"  js        2f\n\t" /* jump if we weren't granted the lock */
  28.311 - 		"1:\n\t"
  28.312 - 		LOCK_SECTION_START("")
  28.313 -@@ -130,7 +131,7 @@ static inline int __down_read_trylock(st
  28.314 - 		"  movl	     %1,%2\n\t"
  28.315 - 		"  addl      %3,%2\n\t"
  28.316 - 		"  jle	     2f\n\t"
  28.317 --LOCK_PREFIX	"  cmpxchgl  %2,%0\n\t"
  28.318 -+LOCK	        "  cmpxchgl  %2,%0\n\t"
  28.319 - 		"  jnz	     1b\n\t"
  28.320 - 		"2:\n\t"
  28.321 - 		"# ending __down_read_trylock\n\t"
  28.322 -@@ -150,7 +151,7 @@ static inline void __down_write(struct r
  28.323 - 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
  28.324 - 	__asm__ __volatile__(
  28.325 - 		"# beginning down_write\n\t"
  28.326 --LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  28.327 -+LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  28.328 - 		"  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
  28.329 - 		"  jnz       2f\n\t" /* jump if we weren't granted the lock */
  28.330 - 		"1:\n\t"
  28.331 -@@ -188,7 +189,7 @@ static inline void __up_read(struct rw_s
  28.332 - 	__s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
  28.333 - 	__asm__ __volatile__(
  28.334 - 		"# beginning __up_read\n\t"
  28.335 --LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  28.336 -+LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  28.337 - 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  28.338 - 		"1:\n\t"
  28.339 - 		LOCK_SECTION_START("")
  28.340 -@@ -214,7 +215,7 @@ static inline void __up_write(struct rw_
  28.341 - 	__asm__ __volatile__(
  28.342 - 		"# beginning __up_write\n\t"
  28.343 - 		"  movl      %2,%%edx\n\t"
  28.344 --LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  28.345 -+LOCK	        "  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  28.346 - 		"  jnz       2f\n\t" /* jump if the lock is being waited upon */
  28.347 - 		"1:\n\t"
  28.348 - 		LOCK_SECTION_START("")
  28.349 -@@ -239,7 +240,7 @@ static inline void __downgrade_write(str
  28.350 - {
  28.351 - 	__asm__ __volatile__(
  28.352 - 		"# beginning __downgrade_write\n\t"
  28.353 --LOCK_PREFIX	"  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  28.354 -+LOCK	        "  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  28.355 - 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  28.356 - 		"1:\n\t"
  28.357 - 		LOCK_SECTION_START("")
  28.358 -@@ -263,7 +264,7 @@ LOCK_PREFIX	"  addl      %2,(%%eax)\n\t"
  28.359 - static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  28.360 - {
  28.361 - 	__asm__ __volatile__(
  28.362 --LOCK_PREFIX	"addl %1,%0"
  28.363 -+LOCK	          "addl %1,%0"
  28.364 - 		: "=m"(sem->count)
  28.365 - 		: "ir"(delta), "m"(sem->count));
  28.366 - }
  28.367 -@@ -276,7 +277,7 @@ static inline int rwsem_atomic_update(in
  28.368 - 	int tmp = delta;
  28.369 - 
  28.370 - 	__asm__ __volatile__(
  28.371 --LOCK_PREFIX	"xadd %0,(%2)"
  28.372 -+LOCK  	          "xadd %0,(%2)"
  28.373 - 		: "+r"(tmp), "=m"(sem->count)
  28.374 - 		: "r"(sem), "m"(sem->count)
  28.375 - 		: "memory");
  28.376 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/smp_alt.h ./include/asm-i386/smp_alt.h
  28.377 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/smp_alt.h	1970-01-01 01:00:00.000000000 +0100
  28.378 -+++ ./include/asm-i386/smp_alt.h	2006-02-15 20:45:57.000000000 +0000
  28.379 -@@ -0,0 +1,32 @@
  28.380 -+#ifndef __ASM_SMP_ALT_H__
  28.381 -+#define __ASM_SMP_ALT_H__
  28.382 -+
  28.383 -+#include <linux/config.h>
  28.384 -+
  28.385 -+#ifdef CONFIG_SMP
  28.386 -+#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  28.387 -+#define LOCK \
  28.388 -+        "6677: nop\n" \
  28.389 -+	".section __smp_alternatives,\"a\"\n" \
  28.390 -+	".long 6677b\n" \
  28.391 -+	".long 6678f\n" \
  28.392 -+	".previous\n" \
  28.393 -+	".section __smp_replacements,\"a\"\n" \
  28.394 -+	"6678: .byte 1\n" \
  28.395 -+	".byte 1\n" \
  28.396 -+	".byte 0\n" \
  28.397 -+        ".byte 1\n" \
  28.398 -+	".byte -1\n" \
  28.399 -+	"lock\n" \
  28.400 -+	"nop\n" \
  28.401 -+	".previous\n"
  28.402 -+void prepare_for_smp(void);
  28.403 -+void unprepare_for_smp(void);
  28.404 -+#else
  28.405 -+#define LOCK "lock ; "
  28.406 -+#endif
  28.407 -+#else
  28.408 -+#define LOCK ""
  28.409 -+#endif
  28.410 -+
  28.411 -+#endif /* __ASM_SMP_ALT_H__ */
  28.412 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/spinlock.h ./include/asm-i386/spinlock.h
  28.413 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/spinlock.h	2006-01-03 03:21:10.000000000 +0000
  28.414 -+++ ./include/asm-i386/spinlock.h	2006-02-15 20:45:57.000000000 +0000
  28.415 -@@ -6,6 +6,7 @@
  28.416 - #include <asm/page.h>
  28.417 - #include <linux/config.h>
  28.418 - #include <linux/compiler.h>
  28.419 -+#include <asm/smp_alt.h>
  28.420 - 
  28.421 - /*
  28.422 -  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  28.423 -@@ -23,7 +24,8 @@
  28.424 - 
  28.425 - #define __raw_spin_lock_string \
  28.426 - 	"\n1:\t" \
  28.427 --	"lock ; decb %0\n\t" \
  28.428 -+	LOCK \
  28.429 -+	"decb %0\n\t" \
  28.430 - 	"jns 3f\n" \
  28.431 - 	"2:\t" \
  28.432 - 	"rep;nop\n\t" \
  28.433 -@@ -34,7 +36,8 @@
  28.434 - 
  28.435 - #define __raw_spin_lock_string_flags \
  28.436 - 	"\n1:\t" \
  28.437 --	"lock ; decb %0\n\t" \
  28.438 -+	LOCK \
  28.439 -+	"decb %0\n\t" \
  28.440 - 	"jns 4f\n\t" \
  28.441 - 	"2:\t" \
  28.442 - 	"testl $0x200, %1\n\t" \
  28.443 -@@ -65,10 +68,34 @@ static inline void __raw_spin_lock_flags
  28.444 - static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  28.445 - {
  28.446 - 	char oldval;
  28.447 -+#ifdef CONFIG_SMP_ALTERNATIVES
  28.448 - 	__asm__ __volatile__(
  28.449 --		"xchgb %b0,%1"
  28.450 -+		"1:movb %1,%b0\n"
  28.451 -+		"movb $0,%1\n"
  28.452 -+		"2:"
  28.453 -+		".section __smp_alternatives,\"a\"\n"
  28.454 -+		".long 1b\n"
  28.455 -+		".long 3f\n"
  28.456 -+		".previous\n"
  28.457 -+		".section __smp_replacements,\"a\"\n"
  28.458 -+		"3: .byte 2b - 1b\n"
  28.459 -+		".byte 5f-4f\n"
  28.460 -+		".byte 0\n"
  28.461 -+		".byte 6f-5f\n"
  28.462 -+		".byte -1\n"
  28.463 -+		"4: xchgb %b0,%1\n"
  28.464 -+		"5: movb %1,%b0\n"
  28.465 -+		"movb $0,%1\n"
  28.466 -+		"6:\n"
  28.467 -+		".previous\n"
  28.468 - 		:"=q" (oldval), "=m" (lock->slock)
  28.469 - 		:"0" (0) : "memory");
  28.470 -+#else
  28.471 -+	__asm__ __volatile__(
  28.472 -+		"xchgb %b0,%1\n"
  28.473 -+		:"=q" (oldval), "=m" (lock->slock)
  28.474 -+		:"0" (0) : "memory");
  28.475 -+#endif
  28.476 - 	return oldval > 0;
  28.477 - }
  28.478 - 
  28.479 -@@ -178,12 +205,12 @@ static inline int __raw_write_trylock(ra
  28.480 - 
  28.481 - static inline void __raw_read_unlock(raw_rwlock_t *rw)
  28.482 - {
  28.483 --	asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
  28.484 -+	asm volatile(LOCK "incl %0" :"=m" (rw->lock) : : "memory");
  28.485 - }
  28.486 - 
  28.487 - static inline void __raw_write_unlock(raw_rwlock_t *rw)
  28.488 - {
  28.489 --	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0"
  28.490 -+	asm volatile(LOCK "addl $" RW_LOCK_BIAS_STR ", %0"
  28.491 - 				 : "=m" (rw->lock) : : "memory");
  28.492 - }
  28.493 - 
  28.494 -diff -pruN ../pristine-linux-2.6.16-rc3/include/asm-i386/system.h ./include/asm-i386/system.h
  28.495 ---- ../pristine-linux-2.6.16-rc3/include/asm-i386/system.h	2006-02-15 20:38:57.000000000 +0000
  28.496 -+++ ./include/asm-i386/system.h	2006-02-15 20:45:57.000000000 +0000
  28.497 -@@ -5,7 +5,7 @@
  28.498 - #include <linux/kernel.h>
  28.499 - #include <asm/segment.h>
  28.500 - #include <asm/cpufeature.h>
  28.501 --#include <linux/bitops.h> /* for LOCK_PREFIX */
  28.502 -+#include <asm/smp_alt.h>
  28.503 - 
  28.504 - #ifdef __KERNEL__
  28.505 - 
  28.506 -@@ -271,19 +271,19 @@ static inline unsigned long __cmpxchg(vo
  28.507 - 	unsigned long prev;
  28.508 - 	switch (size) {
  28.509 - 	case 1:
  28.510 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
  28.511 -+		__asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
  28.512 - 				     : "=a"(prev)
  28.513 - 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
  28.514 - 				     : "memory");
  28.515 - 		return prev;
  28.516 - 	case 2:
  28.517 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
  28.518 -+		__asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
  28.519 - 				     : "=a"(prev)
  28.520 - 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  28.521 - 				     : "memory");
  28.522 - 		return prev;
  28.523 - 	case 4:
  28.524 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
  28.525 -+		__asm__ __volatile__(LOCK "cmpxchgl %1,%2"
  28.526 - 				     : "=a"(prev)
  28.527 - 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  28.528 - 				     : "memory");
  28.529 -@@ -336,7 +336,7 @@ static inline unsigned long long __cmpxc
  28.530 - 				      unsigned long long new)
  28.531 - {
  28.532 - 	unsigned long long prev;
  28.533 --	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
  28.534 -+	__asm__ __volatile__(LOCK "cmpxchg8b %3"
  28.535 - 			     : "=A"(prev)
  28.536 - 			     : "b"((unsigned long)new),
  28.537 - 			       "c"((unsigned long)(new >> 32)),
  28.538 -@@ -503,11 +503,55 @@ struct alt_instr { 
  28.539 - #endif
  28.540 - 
  28.541 - #ifdef CONFIG_SMP
  28.542 -+#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  28.543 -+#define smp_alt_mb(instr)                                           \
  28.544 -+__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
  28.545 -+		     ".section __smp_alternatives,\"a\"\n"          \
  28.546 -+		     ".long 6667b\n"                                \
  28.547 -+                     ".long 6673f\n"                                \
  28.548 -+		     ".previous\n"                                  \
  28.549 -+		     ".section __smp_replacements,\"a\"\n"          \
  28.550 -+		     "6673:.byte 6668b-6667b\n"                     \
  28.551 -+		     ".byte 6670f-6669f\n"                          \
  28.552 -+		     ".byte 6671f-6670f\n"                          \
  28.553 -+                     ".byte 0\n"                                    \
  28.554 -+		     ".byte %c0\n"                                  \
  28.555 -+		     "6669:lock;addl $0,0(%%esp)\n"                 \
  28.556 -+		     "6670:" instr "\n"                             \
  28.557 -+		     "6671:\n"                                      \
  28.558 -+		     ".previous\n"                                  \
  28.559 -+		     :                                              \
  28.560 -+		     : "i" (X86_FEATURE_XMM2)                       \
  28.561 -+		     : "memory")
  28.562 -+#define smp_rmb() smp_alt_mb("lfence")
  28.563 -+#define smp_mb()  smp_alt_mb("mfence")
  28.564 -+#define set_mb(var, value) do {                                     \
  28.565 -+unsigned long __set_mb_temp;                                        \
  28.566 -+__asm__ __volatile__("6667:movl %1, %0\n6668:\n"                    \
  28.567 -+		     ".section __smp_alternatives,\"a\"\n"          \
  28.568 -+		     ".long 6667b\n"                                \
  28.569 -+		     ".long 6673f\n"                                \
  28.570 -+		     ".previous\n"                                  \
  28.571 -+		     ".section __smp_replacements,\"a\"\n"          \
  28.572 -+		     "6673: .byte 6668b-6667b\n"                    \
  28.573 -+		     ".byte 6670f-6669f\n"                          \
  28.574 -+		     ".byte 0\n"                                    \
  28.575 -+		     ".byte 6671f-6670f\n"                          \
  28.576 -+		     ".byte -1\n"                                   \
  28.577 -+		     "6669: xchg %1, %0\n"                          \
  28.578 -+		     "6670:movl %1, %0\n"                           \
  28.579 -+		     "6671:\n"                                      \
  28.580 -+		     ".previous\n"                                  \
  28.581 -+		     : "=m" (var), "=r" (__set_mb_temp)             \
  28.582 -+		     : "1" (value)                                  \
  28.583 -+		     : "memory"); } while (0)
  28.584 -+#else
  28.585 - #define smp_mb()	mb()
  28.586 - #define smp_rmb()	rmb()
  28.587 -+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  28.588 -+#endif
  28.589 - #define smp_wmb()	wmb()
  28.590 - #define smp_read_barrier_depends()	read_barrier_depends()
  28.591 --#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  28.592 - #else
  28.593 - #define smp_mb()	barrier()
  28.594 - #define smp_rmb()	barrier()
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/patches/linux-2.6.16-rc5/i386-mach-io-check-nmi.patch	Mon Feb 27 18:44:38 2006 +0100
    29.3 @@ -0,0 +1,45 @@
    29.4 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/kernel/traps.c ./arch/i386/kernel/traps.c
    29.5 +--- ../pristine-linux-2.6.16-rc5/arch/i386/kernel/traps.c	2006-02-27 15:46:58.000000000 +0000
    29.6 ++++ ./arch/i386/kernel/traps.c	2006-02-27 15:55:23.000000000 +0000
    29.7 +@@ -567,18 +567,11 @@ static void mem_parity_error(unsigned ch
    29.8 + 
    29.9 + static void io_check_error(unsigned char reason, struct pt_regs * regs)
   29.10 + {
   29.11 +-	unsigned long i;
   29.12 +-
   29.13 + 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
   29.14 + 	show_registers(regs);
   29.15 + 
   29.16 + 	/* Re-enable the IOCK line, wait for a few seconds */
   29.17 +-	reason = (reason & 0xf) | 8;
   29.18 +-	outb(reason, 0x61);
   29.19 +-	i = 2000;
   29.20 +-	while (--i) udelay(1000);
   29.21 +-	reason &= ~8;
   29.22 +-	outb(reason, 0x61);
   29.23 ++	clear_io_check_error(reason);
   29.24 + }
   29.25 + 
   29.26 + static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
   29.27 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/mach-default/mach_traps.h ./include/asm-i386/mach-default/mach_traps.h
   29.28 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/mach-default/mach_traps.h	2006-01-03 03:21:10.000000000 +0000
   29.29 ++++ ./include/asm-i386/mach-default/mach_traps.h	2006-02-27 15:55:23.000000000 +0000
   29.30 +@@ -15,6 +15,18 @@ static inline void clear_mem_error(unsig
   29.31 + 	outb(reason, 0x61);
   29.32 + }
   29.33 + 
   29.34 ++static inline void clear_io_check_error(unsigned char reason)
   29.35 ++{
   29.36 ++	unsigned long i;
   29.37 ++
   29.38 ++	reason = (reason & 0xf) | 8;
   29.39 ++	outb(reason, 0x61);
   29.40 ++	i = 2000;
   29.41 ++	while (--i) udelay(1000);
   29.42 ++	reason &= ~8;
   29.43 ++	outb(reason, 0x61);
   29.44 ++}
   29.45 ++
   29.46 + static inline unsigned char get_nmi_reason(void)
   29.47 + {
   29.48 + 	return inb(0x61);
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/patches/linux-2.6.16-rc5/net-csum.patch	Mon Feb 27 18:44:38 2006 +0100
    30.3 @@ -0,0 +1,41 @@
    30.4 +diff -pruN ../pristine-linux-2.6.16-rc5/net/ipv4/netfilter/ip_nat_proto_tcp.c ./net/ipv4/netfilter/ip_nat_proto_tcp.c
    30.5 +--- ../pristine-linux-2.6.16-rc5/net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-02-27 15:47:38.000000000 +0000
    30.6 ++++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-02-27 15:55:25.000000000 +0000
    30.7 +@@ -129,10 +129,14 @@ tcp_manip_pkt(struct sk_buff **pskb,
    30.8 + 	if (hdrsize < sizeof(*hdr))
    30.9 + 		return 1;
   30.10 + 
   30.11 +-	hdr->check = ip_nat_cheat_check(~oldip, newip,
   30.12 ++	if ((*pskb)->proto_csum_blank) {
   30.13 ++		hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   30.14 ++	} else {
   30.15 ++		hdr->check = ip_nat_cheat_check(~oldip, newip,
   30.16 + 					ip_nat_cheat_check(oldport ^ 0xFFFF,
   30.17 + 							   newport,
   30.18 + 							   hdr->check));
   30.19 ++	}
   30.20 + 	return 1;
   30.21 + }
   30.22 + 
   30.23 +diff -pruN ../pristine-linux-2.6.16-rc5/net/ipv4/netfilter/ip_nat_proto_udp.c ./net/ipv4/netfilter/ip_nat_proto_udp.c
   30.24 +--- ../pristine-linux-2.6.16-rc5/net/ipv4/netfilter/ip_nat_proto_udp.c	2006-02-27 15:47:38.000000000 +0000
   30.25 ++++ ./net/ipv4/netfilter/ip_nat_proto_udp.c	2006-02-27 15:55:25.000000000 +0000
   30.26 +@@ -113,11 +113,16 @@ udp_manip_pkt(struct sk_buff **pskb,
   30.27 + 		newport = tuple->dst.u.udp.port;
   30.28 + 		portptr = &hdr->dest;
   30.29 + 	}
   30.30 +-	if (hdr->check) /* 0 is a special case meaning no checksum */
   30.31 +-		hdr->check = ip_nat_cheat_check(~oldip, newip,
   30.32 ++	if (hdr->check) { /* 0 is a special case meaning no checksum */
   30.33 ++		if ((*pskb)->proto_csum_blank) {
   30.34 ++			hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   30.35 ++		} else {
   30.36 ++			hdr->check = ip_nat_cheat_check(~oldip, newip,
   30.37 + 					ip_nat_cheat_check(*portptr ^ 0xFFFF,
   30.38 + 							   newport,
   30.39 + 							   hdr->check));
   30.40 ++		}
   30.41 ++	}
   30.42 + 	*portptr = newport;
   30.43 + 	return 1;
   30.44 + }
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/patches/linux-2.6.16-rc5/pmd-shared.patch	Mon Feb 27 18:44:38 2006 +0100
    31.3 @@ -0,0 +1,111 @@
    31.4 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/mm/pageattr.c ./arch/i386/mm/pageattr.c
    31.5 +--- ../pristine-linux-2.6.16-rc5/arch/i386/mm/pageattr.c	2006-02-27 15:46:58.000000000 +0000
    31.6 ++++ ./arch/i386/mm/pageattr.c	2006-02-27 15:55:31.000000000 +0000
    31.7 +@@ -78,7 +78,7 @@ static void set_pmd_pte(pte_t *kpte, uns
    31.8 + 	unsigned long flags;
    31.9 + 
   31.10 + 	set_pte_atomic(kpte, pte); 	/* change init_mm */
   31.11 +-	if (PTRS_PER_PMD > 1)
   31.12 ++	if (HAVE_SHARED_KERNEL_PMD)
   31.13 + 		return;
   31.14 + 
   31.15 + 	spin_lock_irqsave(&pgd_lock, flags);
   31.16 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/mm/pgtable.c ./arch/i386/mm/pgtable.c
   31.17 +--- ../pristine-linux-2.6.16-rc5/arch/i386/mm/pgtable.c	2006-01-03 03:21:10.000000000 +0000
   31.18 ++++ ./arch/i386/mm/pgtable.c	2006-02-27 15:55:31.000000000 +0000
   31.19 +@@ -215,9 +215,10 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
   31.20 + 		spin_lock_irqsave(&pgd_lock, flags);
   31.21 + 	}
   31.22 + 
   31.23 +-	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   31.24 +-			swapper_pg_dir + USER_PTRS_PER_PGD,
   31.25 +-			KERNEL_PGD_PTRS);
   31.26 ++	if (PTRS_PER_PMD == 1 || HAVE_SHARED_KERNEL_PMD)
   31.27 ++		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   31.28 ++				swapper_pg_dir + USER_PTRS_PER_PGD,
   31.29 ++				KERNEL_PGD_PTRS);
   31.30 + 	if (PTRS_PER_PMD > 1)
   31.31 + 		return;
   31.32 + 
   31.33 +@@ -249,6 +250,30 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
   31.34 + 			goto out_oom;
   31.35 + 		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
   31.36 + 	}
   31.37 ++
   31.38 ++	if (!HAVE_SHARED_KERNEL_PMD) {
   31.39 ++		unsigned long flags;
   31.40 ++
   31.41 ++		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   31.42 ++			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
   31.43 ++			if (!pmd)
   31.44 ++				goto out_oom;
   31.45 ++			set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
   31.46 ++		}
   31.47 ++
   31.48 ++		spin_lock_irqsave(&pgd_lock, flags);
   31.49 ++		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   31.50 ++			unsigned long v = (unsigned long)i << PGDIR_SHIFT;
   31.51 ++			pgd_t *kpgd = pgd_offset_k(v);
   31.52 ++			pud_t *kpud = pud_offset(kpgd, v);
   31.53 ++			pmd_t *kpmd = pmd_offset(kpud, v);
   31.54 ++			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   31.55 ++			memcpy(pmd, kpmd, PAGE_SIZE);
   31.56 ++		}
   31.57 ++		pgd_list_add(pgd);
   31.58 ++		spin_unlock_irqrestore(&pgd_lock, flags);
   31.59 ++	}
   31.60 ++
   31.61 + 	return pgd;
   31.62 + 
   31.63 + out_oom:
   31.64 +@@ -263,9 +288,23 @@ void pgd_free(pgd_t *pgd)
   31.65 + 	int i;
   31.66 + 
   31.67 + 	/* in the PAE case user pgd entries are overwritten before usage */
   31.68 +-	if (PTRS_PER_PMD > 1)
   31.69 +-		for (i = 0; i < USER_PTRS_PER_PGD; ++i)
   31.70 +-			kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
   31.71 ++	if (PTRS_PER_PMD > 1) {
   31.72 ++		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
   31.73 ++			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   31.74 ++			kmem_cache_free(pmd_cache, pmd);
   31.75 ++		}
   31.76 ++		if (!HAVE_SHARED_KERNEL_PMD) {
   31.77 ++			unsigned long flags;
   31.78 ++			spin_lock_irqsave(&pgd_lock, flags);
   31.79 ++			pgd_list_del(pgd);
   31.80 ++			spin_unlock_irqrestore(&pgd_lock, flags);
   31.81 ++			for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   31.82 ++				pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   31.83 ++				memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
   31.84 ++				kmem_cache_free(pmd_cache, pmd);
   31.85 ++			}
   31.86 ++		}
   31.87 ++	}
   31.88 + 	/* in the non-PAE case, free_pgtables() clears user pgd entries */
   31.89 + 	kmem_cache_free(pgd_cache, pgd);
   31.90 + }
   31.91 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/pgtable-2level-defs.h ./include/asm-i386/pgtable-2level-defs.h
   31.92 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/pgtable-2level-defs.h	2006-01-03 03:21:10.000000000 +0000
   31.93 ++++ ./include/asm-i386/pgtable-2level-defs.h	2006-02-27 15:55:31.000000000 +0000
   31.94 +@@ -1,6 +1,8 @@
   31.95 + #ifndef _I386_PGTABLE_2LEVEL_DEFS_H
   31.96 + #define _I386_PGTABLE_2LEVEL_DEFS_H
   31.97 + 
   31.98 ++#define HAVE_SHARED_KERNEL_PMD 0
   31.99 ++
  31.100 + /*
  31.101 +  * traditional i386 two-level paging structure:
  31.102 +  */
  31.103 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/pgtable-3level-defs.h ./include/asm-i386/pgtable-3level-defs.h
  31.104 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/pgtable-3level-defs.h	2006-01-03 03:21:10.000000000 +0000
  31.105 ++++ ./include/asm-i386/pgtable-3level-defs.h	2006-02-27 15:55:31.000000000 +0000
  31.106 +@@ -1,6 +1,8 @@
  31.107 + #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
  31.108 + #define _I386_PGTABLE_3LEVEL_DEFS_H
  31.109 + 
  31.110 ++#define HAVE_SHARED_KERNEL_PMD 1
  31.111 ++
  31.112 + /*
  31.113 +  * PGDIR_SHIFT determines what a top-level page table entry can map
  31.114 +  */
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/patches/linux-2.6.16-rc5/smp-alts.patch	Mon Feb 27 18:44:38 2006 +0100
    32.3 @@ -0,0 +1,591 @@
    32.4 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/Kconfig ./arch/i386/Kconfig
    32.5 +--- ../pristine-linux-2.6.16-rc5/arch/i386/Kconfig	2006-02-27 15:46:58.000000000 +0000
    32.6 ++++ ./arch/i386/Kconfig	2006-02-27 15:55:34.000000000 +0000
    32.7 +@@ -202,6 +202,19 @@ config SMP
    32.8 + 
    32.9 + 	  If you don't know what to do here, say N.
   32.10 + 
   32.11 ++config SMP_ALTERNATIVES
   32.12 ++	bool "SMP alternatives support (EXPERIMENTAL)"
   32.13 ++	depends on SMP && EXPERIMENTAL
   32.14 ++	help
   32.15 ++	  Try to reduce the overhead of running an SMP kernel on a uniprocessor
   32.16 ++	  host slightly by replacing certain key instruction sequences
   32.17 ++	  according to whether we currently have more than one CPU available.
   32.18 ++	  This should provide a noticeable boost to performance when
   32.19 ++	  running SMP kernels on UP machines, and have negligible impact
   32.20 ++	  when running on an true SMP host.
   32.21 ++
   32.22 ++          If unsure, say N.
   32.23 ++	  
   32.24 + config NR_CPUS
   32.25 + 	int "Maximum number of CPUs (2-255)"
   32.26 + 	range 2 255
   32.27 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/kernel/Makefile ./arch/i386/kernel/Makefile
   32.28 +--- ../pristine-linux-2.6.16-rc5/arch/i386/kernel/Makefile	2006-02-27 15:46:58.000000000 +0000
   32.29 ++++ ./arch/i386/kernel/Makefile	2006-02-27 15:55:34.000000000 +0000
   32.30 +@@ -37,6 +37,7 @@ obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
   32.31 + obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault.o
   32.32 + obj-$(CONFIG_VM86)		+= vm86.o
   32.33 + obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
   32.34 ++obj-$(CONFIG_SMP_ALTERNATIVES)  += smpalts.o
   32.35 + 
   32.36 + EXTRA_AFLAGS   := -traditional
   32.37 + 
   32.38 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/kernel/smpalts.c ./arch/i386/kernel/smpalts.c
   32.39 +--- ../pristine-linux-2.6.16-rc5/arch/i386/kernel/smpalts.c	1970-01-01 01:00:00.000000000 +0100
   32.40 ++++ ./arch/i386/kernel/smpalts.c	2006-02-27 15:55:34.000000000 +0000
   32.41 +@@ -0,0 +1,85 @@
   32.42 ++#include <linux/kernel.h>
   32.43 ++#include <asm/system.h>
   32.44 ++#include <asm/smp_alt.h>
   32.45 ++#include <asm/processor.h>
   32.46 ++#include <asm/string.h>
   32.47 ++
   32.48 ++struct smp_replacement_record {
   32.49 ++	unsigned char targ_size;
   32.50 ++	unsigned char smp1_size;
   32.51 ++	unsigned char smp2_size;
   32.52 ++	unsigned char up_size;
   32.53 ++	unsigned char feature;
   32.54 ++	unsigned char data[0];
   32.55 ++};
   32.56 ++
   32.57 ++struct smp_alternative_record {
   32.58 ++	void *targ_start;
   32.59 ++	struct smp_replacement_record *repl;
   32.60 ++};
   32.61 ++
   32.62 ++extern struct smp_alternative_record __start_smp_alternatives_table,
   32.63 ++  __stop_smp_alternatives_table;
   32.64 ++extern unsigned long __init_begin, __init_end;
   32.65 ++
   32.66 ++void prepare_for_smp(void)
   32.67 ++{
   32.68 ++	struct smp_alternative_record *r;
   32.69 ++	printk(KERN_INFO "Enabling SMP...\n");
   32.70 ++	for (r = &__start_smp_alternatives_table;
   32.71 ++	     r != &__stop_smp_alternatives_table;
   32.72 ++	     r++) {
   32.73 ++		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
   32.74 ++		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
   32.75 ++		BUG_ON(r->repl->targ_size < r->repl->up_size);
   32.76 ++               if (system_state == SYSTEM_RUNNING &&
   32.77 ++                   r->targ_start >= (void *)&__init_begin &&
   32.78 ++                   r->targ_start < (void *)&__init_end)
   32.79 ++                       continue;
   32.80 ++		if (r->repl->feature != (unsigned char)-1 &&
   32.81 ++		    boot_cpu_has(r->repl->feature)) {
   32.82 ++			memcpy(r->targ_start,
   32.83 ++			       r->repl->data + r->repl->smp1_size,
   32.84 ++			       r->repl->smp2_size);
   32.85 ++			memset(r->targ_start + r->repl->smp2_size,
   32.86 ++			       0x90,
   32.87 ++			       r->repl->targ_size - r->repl->smp2_size);
   32.88 ++		} else {
   32.89 ++			memcpy(r->targ_start,
   32.90 ++			       r->repl->data,
   32.91 ++			       r->repl->smp1_size);
   32.92 ++			memset(r->targ_start + r->repl->smp1_size,
   32.93 ++			       0x90,
   32.94 ++			       r->repl->targ_size - r->repl->smp1_size);
   32.95 ++		}
   32.96 ++	}
   32.97 ++	/* Paranoia */
   32.98 ++	asm volatile ("jmp 1f\n1:");
   32.99 ++	mb();
  32.100 ++}
  32.101 ++
  32.102 ++void unprepare_for_smp(void)
  32.103 ++{
  32.104 ++	struct smp_alternative_record *r;
  32.105 ++	printk(KERN_INFO "Disabling SMP...\n");
  32.106 ++	for (r = &__start_smp_alternatives_table;
  32.107 ++	     r != &__stop_smp_alternatives_table;
  32.108 ++	     r++) {
  32.109 ++		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
  32.110 ++		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
  32.111 ++		BUG_ON(r->repl->targ_size < r->repl->up_size);
  32.112 ++               if (system_state == SYSTEM_RUNNING &&
  32.113 ++                   r->targ_start >= (void *)&__init_begin &&
  32.114 ++                   r->targ_start < (void *)&__init_end)
  32.115 ++                       continue;
  32.116 ++		memcpy(r->targ_start,
  32.117 ++		       r->repl->data + r->repl->smp1_size + r->repl->smp2_size,
  32.118 ++		       r->repl->up_size);
  32.119 ++		memset(r->targ_start + r->repl->up_size,
  32.120 ++		       0x90,
  32.121 ++		       r->repl->targ_size - r->repl->up_size);
  32.122 ++	}
  32.123 ++	/* Paranoia */
  32.124 ++	asm volatile ("jmp 1f\n1:");
  32.125 ++	mb();
  32.126 ++}
  32.127 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/kernel/smpboot.c ./arch/i386/kernel/smpboot.c
  32.128 +--- ../pristine-linux-2.6.16-rc5/arch/i386/kernel/smpboot.c	2006-02-27 15:46:58.000000000 +0000
  32.129 ++++ ./arch/i386/kernel/smpboot.c	2006-02-27 15:55:34.000000000 +0000
  32.130 +@@ -1208,6 +1208,11 @@ static void __init smp_boot_cpus(unsigne
  32.131 + 		if (max_cpus <= cpucount+1)
  32.132 + 			continue;
  32.133 + 
  32.134 ++#ifdef CONFIG_SMP_ALTERNATIVES
  32.135 ++		if (kicked == 1)
  32.136 ++			prepare_for_smp();
  32.137 ++#endif
  32.138 ++
  32.139 + 		if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
  32.140 + 			printk("CPU #%d not responding - cannot use it.\n",
  32.141 + 								apicid);
  32.142 +@@ -1386,6 +1391,11 @@ int __devinit __cpu_up(unsigned int cpu)
  32.143 + 		return -EIO;
  32.144 + 	}
  32.145 + 
  32.146 ++#ifdef CONFIG_SMP_ALTERNATIVES
  32.147 ++	if (num_online_cpus() == 1)
  32.148 ++		prepare_for_smp();
  32.149 ++#endif
  32.150 ++
  32.151 + 	local_irq_enable();
  32.152 + 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
  32.153 + 	/* Unleash the CPU! */
  32.154 +diff -pruN ../pristine-linux-2.6.16-rc5/arch/i386/kernel/vmlinux.lds.S ./arch/i386/kernel/vmlinux.lds.S
  32.155 +--- ../pristine-linux-2.6.16-rc5/arch/i386/kernel/vmlinux.lds.S	2006-01-03 03:21:10.000000000 +0000
  32.156 ++++ ./arch/i386/kernel/vmlinux.lds.S	2006-02-27 15:55:34.000000000 +0000
  32.157 +@@ -34,6 +34,13 @@ SECTIONS
  32.158 +   __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
  32.159 +   __stop___ex_table = .;
  32.160 + 
  32.161 ++  . = ALIGN(16);
  32.162 ++  __start_smp_alternatives_table = .;
  32.163 ++  __smp_alternatives : { *(__smp_alternatives) }
  32.164 ++  __stop_smp_alternatives_table = .;
  32.165 ++
  32.166 ++  __smp_replacements : { *(__smp_replacements) }
  32.167 ++
  32.168 +   RODATA
  32.169 + 
  32.170 +   /* writeable */
  32.171 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/atomic.h ./include/asm-i386/atomic.h
  32.172 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/atomic.h	2006-02-27 15:47:25.000000000 +0000
  32.173 ++++ ./include/asm-i386/atomic.h	2006-02-27 15:55:34.000000000 +0000
  32.174 +@@ -4,18 +4,13 @@
  32.175 + #include <linux/config.h>
  32.176 + #include <linux/compiler.h>
  32.177 + #include <asm/processor.h>
  32.178 ++#include <asm/smp_alt.h>
  32.179 + 
  32.180 + /*
  32.181 +  * Atomic operations that C can't guarantee us.  Useful for
  32.182 +  * resource counting etc..
  32.183 +  */
  32.184 + 
  32.185 +-#ifdef CONFIG_SMP
  32.186 +-#define LOCK "lock ; "
  32.187 +-#else
  32.188 +-#define LOCK ""
  32.189 +-#endif
  32.190 +-
  32.191 + /*
  32.192 +  * Make sure gcc doesn't try to be clever and move things around
  32.193 +  * on us. We need to use _exactly_ the address the user gave us,
  32.194 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/bitops.h ./include/asm-i386/bitops.h
  32.195 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/bitops.h	2006-02-27 15:47:25.000000000 +0000
  32.196 ++++ ./include/asm-i386/bitops.h	2006-02-27 15:55:34.000000000 +0000
  32.197 +@@ -7,6 +7,7 @@
  32.198 + 
  32.199 + #include <linux/config.h>
  32.200 + #include <linux/compiler.h>
  32.201 ++#include <asm/smp_alt.h>
  32.202 + 
  32.203 + /*
  32.204 +  * These have to be done with inline assembly: that way the bit-setting
  32.205 +@@ -16,12 +17,6 @@
  32.206 +  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  32.207 +  */
  32.208 + 
  32.209 +-#ifdef CONFIG_SMP
  32.210 +-#define LOCK_PREFIX "lock ; "
  32.211 +-#else
  32.212 +-#define LOCK_PREFIX ""
  32.213 +-#endif
  32.214 +-
  32.215 + #define ADDR (*(volatile long *) addr)
  32.216 + 
  32.217 + /**
  32.218 +@@ -41,7 +36,7 @@
  32.219 +  */
  32.220 + static inline void set_bit(int nr, volatile unsigned long * addr)
  32.221 + {
  32.222 +-	__asm__ __volatile__( LOCK_PREFIX
  32.223 ++	__asm__ __volatile__( LOCK
  32.224 + 		"btsl %1,%0"
  32.225 + 		:"+m" (ADDR)
  32.226 + 		:"Ir" (nr));
  32.227 +@@ -76,7 +71,7 @@ static inline void __set_bit(int nr, vol
  32.228 +  */
  32.229 + static inline void clear_bit(int nr, volatile unsigned long * addr)
  32.230 + {
  32.231 +-	__asm__ __volatile__( LOCK_PREFIX
  32.232 ++	__asm__ __volatile__( LOCK
  32.233 + 		"btrl %1,%0"
  32.234 + 		:"+m" (ADDR)
  32.235 + 		:"Ir" (nr));
  32.236 +@@ -121,7 +116,7 @@ static inline void __change_bit(int nr, 
  32.237 +  */
  32.238 + static inline void change_bit(int nr, volatile unsigned long * addr)
  32.239 + {
  32.240 +-	__asm__ __volatile__( LOCK_PREFIX
  32.241 ++	__asm__ __volatile__( LOCK
  32.242 + 		"btcl %1,%0"
  32.243 + 		:"+m" (ADDR)
  32.244 + 		:"Ir" (nr));
  32.245 +@@ -140,7 +135,7 @@ static inline int test_and_set_bit(int n
  32.246 + {
  32.247 + 	int oldbit;
  32.248 + 
  32.249 +-	__asm__ __volatile__( LOCK_PREFIX
  32.250 ++	__asm__ __volatile__( LOCK
  32.251 + 		"btsl %2,%1\n\tsbbl %0,%0"
  32.252 + 		:"=r" (oldbit),"+m" (ADDR)
  32.253 + 		:"Ir" (nr) : "memory");
  32.254 +@@ -180,7 +175,7 @@ static inline int test_and_clear_bit(int
  32.255 + {
  32.256 + 	int oldbit;
  32.257 + 
  32.258 +-	__asm__ __volatile__( LOCK_PREFIX
  32.259 ++	__asm__ __volatile__( LOCK
  32.260 + 		"btrl %2,%1\n\tsbbl %0,%0"
  32.261 + 		:"=r" (oldbit),"+m" (ADDR)
  32.262 + 		:"Ir" (nr) : "memory");
  32.263 +@@ -231,7 +226,7 @@ static inline int test_and_change_bit(in
  32.264 + {
  32.265 + 	int oldbit;
  32.266 + 
  32.267 +-	__asm__ __volatile__( LOCK_PREFIX
  32.268 ++	__asm__ __volatile__( LOCK
  32.269 + 		"btcl %2,%1\n\tsbbl %0,%0"
  32.270 + 		:"=r" (oldbit),"+m" (ADDR)
  32.271 + 		:"Ir" (nr) : "memory");
  32.272 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/futex.h ./include/asm-i386/futex.h
  32.273 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/futex.h	2006-02-27 15:47:25.000000000 +0000
  32.274 ++++ ./include/asm-i386/futex.h	2006-02-27 15:55:34.000000000 +0000
  32.275 +@@ -28,7 +28,7 @@
  32.276 + "1:	movl	%2, %0\n\
  32.277 + 	movl	%0, %3\n"					\
  32.278 + 	insn "\n"						\
  32.279 +-"2:	" LOCK_PREFIX "cmpxchgl %3, %2\n\
  32.280 ++"2:	" LOCK "cmpxchgl %3, %2\n\
  32.281 + 	jnz	1b\n\
  32.282 + 3:	.section .fixup,\"ax\"\n\
  32.283 + 4:	mov	%5, %1\n\
  32.284 +@@ -68,7 +68,7 @@ futex_atomic_op_inuser (int encoded_op, 
  32.285 + #endif
  32.286 + 		switch (op) {
  32.287 + 		case FUTEX_OP_ADD:
  32.288 +-			__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
  32.289 ++			__futex_atomic_op1(LOCK "xaddl %0, %2", ret,
  32.290 + 					   oldval, uaddr, oparg);
  32.291 + 			break;
  32.292 + 		case FUTEX_OP_OR:
  32.293 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/rwsem.h ./include/asm-i386/rwsem.h
  32.294 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/rwsem.h	2006-01-03 03:21:10.000000000 +0000
  32.295 ++++ ./include/asm-i386/rwsem.h	2006-02-27 15:55:34.000000000 +0000
  32.296 +@@ -40,6 +40,7 @@
  32.297 + 
  32.298 + #include <linux/list.h>
  32.299 + #include <linux/spinlock.h>
  32.300 ++#include <asm/smp_alt.h>
  32.301 + 
  32.302 + struct rwsem_waiter;
  32.303 + 
  32.304 +@@ -99,7 +100,7 @@ static inline void __down_read(struct rw
  32.305 + {
  32.306 + 	__asm__ __volatile__(
  32.307 + 		"# beginning down_read\n\t"
  32.308 +-LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  32.309 ++LOCK	        "  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  32.310 + 		"  js        2f\n\t" /* jump if we weren't granted the lock */
  32.311 + 		"1:\n\t"
  32.312 + 		LOCK_SECTION_START("")
  32.313 +@@ -130,7 +131,7 @@ static inline int __down_read_trylock(st
  32.314 + 		"  movl	     %1,%2\n\t"
  32.315 + 		"  addl      %3,%2\n\t"
  32.316 + 		"  jle	     2f\n\t"
  32.317 +-LOCK_PREFIX	"  cmpxchgl  %2,%0\n\t"
  32.318 ++LOCK	        "  cmpxchgl  %2,%0\n\t"
  32.319 + 		"  jnz	     1b\n\t"
  32.320 + 		"2:\n\t"
  32.321 + 		"# ending __down_read_trylock\n\t"
  32.322 +@@ -150,7 +151,7 @@ static inline void __down_write(struct r
  32.323 + 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
  32.324 + 	__asm__ __volatile__(
  32.325 + 		"# beginning down_write\n\t"
  32.326 +-LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  32.327 ++LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  32.328 + 		"  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
  32.329 + 		"  jnz       2f\n\t" /* jump if we weren't granted the lock */
  32.330 + 		"1:\n\t"
  32.331 +@@ -188,7 +189,7 @@ static inline void __up_read(struct rw_s
  32.332 + 	__s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
  32.333 + 	__asm__ __volatile__(
  32.334 + 		"# beginning __up_read\n\t"
  32.335 +-LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  32.336 ++LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  32.337 + 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  32.338 + 		"1:\n\t"
  32.339 + 		LOCK_SECTION_START("")
  32.340 +@@ -214,7 +215,7 @@ static inline void __up_write(struct rw_
  32.341 + 	__asm__ __volatile__(
  32.342 + 		"# beginning __up_write\n\t"
  32.343 + 		"  movl      %2,%%edx\n\t"
  32.344 +-LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  32.345 ++LOCK	        "  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  32.346 + 		"  jnz       2f\n\t" /* jump if the lock is being waited upon */
  32.347 + 		"1:\n\t"
  32.348 + 		LOCK_SECTION_START("")
  32.349 +@@ -239,7 +240,7 @@ static inline void __downgrade_write(str
  32.350 + {
  32.351 + 	__asm__ __volatile__(
  32.352 + 		"# beginning __downgrade_write\n\t"
  32.353 +-LOCK_PREFIX	"  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  32.354 ++LOCK	        "  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  32.355 + 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  32.356 + 		"1:\n\t"
  32.357 + 		LOCK_SECTION_START("")
  32.358 +@@ -263,7 +264,7 @@ LOCK_PREFIX	"  addl      %2,(%%eax)\n\t"
  32.359 + static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  32.360 + {
  32.361 + 	__asm__ __volatile__(
  32.362 +-LOCK_PREFIX	"addl %1,%0"
  32.363 ++LOCK	          "addl %1,%0"
  32.364 + 		: "=m"(sem->count)
  32.365 + 		: "ir"(delta), "m"(sem->count));
  32.366 + }
  32.367 +@@ -276,7 +277,7 @@ static inline int rwsem_atomic_update(in
  32.368 + 	int tmp = delta;
  32.369 + 
  32.370 + 	__asm__ __volatile__(
  32.371 +-LOCK_PREFIX	"xadd %0,(%2)"
  32.372 ++LOCK  	          "xadd %0,(%2)"
  32.373 + 		: "+r"(tmp), "=m"(sem->count)
  32.374 + 		: "r"(sem), "m"(sem->count)
  32.375 + 		: "memory");
  32.376 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/smp_alt.h ./include/asm-i386/smp_alt.h
  32.377 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/smp_alt.h	1970-01-01 01:00:00.000000000 +0100
  32.378 ++++ ./include/asm-i386/smp_alt.h	2006-02-27 15:55:34.000000000 +0000
  32.379 +@@ -0,0 +1,32 @@
  32.380 ++#ifndef __ASM_SMP_ALT_H__
  32.381 ++#define __ASM_SMP_ALT_H__
  32.382 ++
  32.383 ++#include <linux/config.h>
  32.384 ++
  32.385 ++#ifdef CONFIG_SMP
  32.386 ++#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  32.387 ++#define LOCK \
  32.388 ++        "6677: nop\n" \
  32.389 ++	".section __smp_alternatives,\"a\"\n" \
  32.390 ++	".long 6677b\n" \
  32.391 ++	".long 6678f\n" \
  32.392 ++	".previous\n" \
  32.393 ++	".section __smp_replacements,\"a\"\n" \
  32.394 ++	"6678: .byte 1\n" \
  32.395 ++	".byte 1\n" \
  32.396 ++	".byte 0\n" \
  32.397 ++        ".byte 1\n" \
  32.398 ++	".byte -1\n" \
  32.399 ++	"lock\n" \
  32.400 ++	"nop\n" \
  32.401 ++	".previous\n"
  32.402 ++void prepare_for_smp(void);
  32.403 ++void unprepare_for_smp(void);
  32.404 ++#else
  32.405 ++#define LOCK "lock ; "
  32.406 ++#endif
  32.407 ++#else
  32.408 ++#define LOCK ""
  32.409 ++#endif
  32.410 ++
  32.411 ++#endif /* __ASM_SMP_ALT_H__ */
  32.412 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/spinlock.h ./include/asm-i386/spinlock.h
  32.413 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/spinlock.h	2006-01-03 03:21:10.000000000 +0000
  32.414 ++++ ./include/asm-i386/spinlock.h	2006-02-27 15:55:34.000000000 +0000
  32.415 +@@ -6,6 +6,7 @@
  32.416 + #include <asm/page.h>
  32.417 + #include <linux/config.h>
  32.418 + #include <linux/compiler.h>
  32.419 ++#include <asm/smp_alt.h>
  32.420 + 
  32.421 + /*
  32.422 +  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  32.423 +@@ -23,7 +24,8 @@
  32.424 + 
  32.425 + #define __raw_spin_lock_string \
  32.426 + 	"\n1:\t" \
  32.427 +-	"lock ; decb %0\n\t" \
  32.428 ++	LOCK \
  32.429 ++	"decb %0\n\t" \
  32.430 + 	"jns 3f\n" \
  32.431 + 	"2:\t" \
  32.432 + 	"rep;nop\n\t" \
  32.433 +@@ -34,7 +36,8 @@
  32.434 + 
  32.435 + #define __raw_spin_lock_string_flags \
  32.436 + 	"\n1:\t" \
  32.437 +-	"lock ; decb %0\n\t" \
  32.438 ++	LOCK \
  32.439 ++	"decb %0\n\t" \
  32.440 + 	"jns 4f\n\t" \
  32.441 + 	"2:\t" \
  32.442 + 	"testl $0x200, %1\n\t" \
  32.443 +@@ -65,10 +68,34 @@ static inline void __raw_spin_lock_flags
  32.444 + static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  32.445 + {
  32.446 + 	char oldval;
  32.447 ++#ifdef CONFIG_SMP_ALTERNATIVES
  32.448 + 	__asm__ __volatile__(
  32.449 +-		"xchgb %b0,%1"
  32.450 ++		"1:movb %1,%b0\n"
  32.451 ++		"movb $0,%1\n"
  32.452 ++		"2:"
  32.453 ++		".section __smp_alternatives,\"a\"\n"
  32.454 ++		".long 1b\n"
  32.455 ++		".long 3f\n"
  32.456 ++		".previous\n"
  32.457 ++		".section __smp_replacements,\"a\"\n"
  32.458 ++		"3: .byte 2b - 1b\n"
  32.459 ++		".byte 5f-4f\n"
  32.460 ++		".byte 0\n"
  32.461 ++		".byte 6f-5f\n"
  32.462 ++		".byte -1\n"
  32.463 ++		"4: xchgb %b0,%1\n"
  32.464 ++		"5: movb %1,%b0\n"
  32.465 ++		"movb $0,%1\n"
  32.466 ++		"6:\n"
  32.467 ++		".previous\n"
  32.468 + 		:"=q" (oldval), "=m" (lock->slock)
  32.469 + 		:"0" (0) : "memory");
  32.470 ++#else
  32.471 ++	__asm__ __volatile__(
  32.472 ++		"xchgb %b0,%1\n"
  32.473 ++		:"=q" (oldval), "=m" (lock->slock)
  32.474 ++		:"0" (0) : "memory");
  32.475 ++#endif
  32.476 + 	return oldval > 0;
  32.477 + }
  32.478 + 
  32.479 +@@ -178,12 +205,12 @@ static inline int __raw_write_trylock(ra
  32.480 + 
  32.481 + static inline void __raw_read_unlock(raw_rwlock_t *rw)
  32.482 + {
  32.483 +-	asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
  32.484 ++	asm volatile(LOCK "incl %0" :"=m" (rw->lock) : : "memory");
  32.485 + }
  32.486 + 
  32.487 + static inline void __raw_write_unlock(raw_rwlock_t *rw)
  32.488 + {
  32.489 +-	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0"
  32.490 ++	asm volatile(LOCK "addl $" RW_LOCK_BIAS_STR ", %0"
  32.491 + 				 : "=m" (rw->lock) : : "memory");
  32.492 + }
  32.493 + 
  32.494 +diff -pruN ../pristine-linux-2.6.16-rc5/include/asm-i386/system.h ./include/asm-i386/system.h
  32.495 +--- ../pristine-linux-2.6.16-rc5/include/asm-i386/system.h	2006-02-27 15:47:25.000000000 +0000
  32.496 ++++ ./include/asm-i386/system.h	2006-02-27 15:55:34.000000000 +0000
  32.497 +@@ -5,7 +5,7 @@
  32.498 + #include <linux/kernel.h>
  32.499 + #include <asm/segment.h>
  32.500 + #include <asm/cpufeature.h>
  32.501 +-#include <linux/bitops.h> /* for LOCK_PREFIX */
  32.502 ++#include <asm/smp_alt.h>
  32.503 + 
  32.504 + #ifdef __KERNEL__
  32.505 + 
  32.506 +@@ -271,19 +271,19 @@ static inline unsigned long __cmpxchg(vo
  32.507 + 	unsigned long prev;
  32.508 + 	switch (size) {
  32.509 + 	case 1:
  32.510 +-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
  32.511 ++		__asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
  32.512 + 				     : "=a"(prev)
  32.513 + 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
  32.514 + 				     : "memory");
  32.515 + 		return prev;
  32.516 + 	case 2:
  32.517 +-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
  32.518 ++		__asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
  32.519 + 				     : "=a"(prev)
  32.520 + 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  32.521 + 				     : "memory");
  32.522 + 		return prev;
  32.523 + 	case 4:
  32.524 +-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
  32.525 ++		__asm__ __volatile__(LOCK "cmpxchgl %1,%2"
  32.526 + 				     : "=a"(prev)
  32.527 + 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  32.528 + 				     : "memory");
  32.529 +@@ -336,7 +336,7 @@ static inline unsigned long long __cmpxc
  32.530 + 				      unsigned long long new)
  32.531 + {
  32.532 + 	unsigned long long prev;
  32.533 +-	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
  32.534 ++	__asm__ __volatile__(LOCK "cmpxchg8b %3"
  32.535 + 			     : "=A"(prev)
  32.536 + 			     : "b"((unsigned long)new),
  32.537 + 			       "c"((unsigned long)(new >> 32)),
  32.538 +@@ -503,11 +503,55 @@ struct alt_instr { 
  32.539 + #endif
  32.540 + 
  32.541 + #ifdef CONFIG_SMP
  32.542 ++#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  32.543 ++#define smp_alt_mb(instr)                                           \
  32.544 ++__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
  32.545 ++		     ".section __smp_alternatives,\"a\"\n"          \
  32.546 ++		     ".long 6667b\n"                                \
  32.547 ++                     ".long 6673f\n"                                \
  32.548 ++		     ".previous\n"                                  \
  32.549 ++		     ".section __smp_replacements,\"a\"\n"          \
  32.550 ++		     "6673:.byte 6668b-6667b\n"                     \
  32.551 ++		     ".byte 6670f-6669f\n"                          \
  32.552 ++		     ".byte 6671f-6670f\n"                          \
  32.553 ++                     ".byte 0\n"                                    \
  32.554 ++		     ".byte %c0\n"                                  \
  32.555 ++		     "6669:lock;addl $0,0(%%esp)\n"                 \
  32.556 ++		     "6670:" instr "\n"                             \
  32.557 ++		     "6671:\n"                                      \
  32.558 ++		     ".previous\n"                                  \
  32.559 ++		     :                                              \
  32.560 ++		     : "i" (X86_FEATURE_XMM2)                       \
  32.561 ++		     : "memory")
  32.562 ++#define smp_rmb() smp_alt_mb("lfence")
  32.563 ++#define smp_mb()  smp_alt_mb("mfence")
  32.564 ++#define set_mb(var, value) do {                                     \
  32.565 ++unsigned long __set_mb_temp;                                        \
  32.566 ++__asm__ __volatile__("6667:movl %1, %0\n6668:\n"                    \
  32.567 ++		     ".section __smp_alternatives,\"a\"\n"          \
  32.568 ++		     ".long 6667b\n"                                \
  32.569 ++		     ".long 6673f\n"                                \
  32.570 ++		     ".previous\n"                                  \
  32.571 ++		     ".section __smp_replacements,\"a\"\n"          \
  32.572 ++		     "6673: .byte 6668b-6667b\n"                    \
  32.573 ++		     ".byte 6670f-6669f\n"                          \
  32.574 ++		     ".byte 0\n"                                    \
  32.575 ++		     ".byte 6671f-6670f\n"                          \
  32.576 ++		     ".byte -1\n"                                   \
  32.577 ++		     "6669: xchg %1, %0\n"                          \
  32.578 ++		     "6670:movl %1, %0\n"                           \
  32.579 ++		     "6671:\n"                                      \
  32.580 ++		     ".previous\n"                                  \
  32.581 ++		     : "=m" (var), "=r" (__set_mb_temp)             \
  32.582 ++		     : "1" (value)                                  \
  32.583 ++		     : "memory"); } while (0)
  32.584 ++#else
  32.585 + #define smp_mb()	mb()
  32.586 + #define smp_rmb()	rmb()
  32.587 ++#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  32.588 ++#endif
  32.589 + #define smp_wmb()	wmb()
  32.590 + #define smp_read_barrier_depends()	read_barrier_depends()
  32.591 +-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  32.592 + #else
  32.593 + #define smp_mb()	barrier()
  32.594 + #define smp_rmb()	barrier()
    33.1 --- a/tools/libxc/xc_linux_build.c	Mon Feb 27 17:26:16 2006 +0100
    33.2 +++ b/tools/libxc/xc_linux_build.c	Mon Feb 27 18:44:38 2006 +0100
    33.3 @@ -46,6 +46,77 @@
    33.4  #define probe_aout9(image,image_size,load_funcs) 1
    33.5  #endif
    33.6  
    33.7 +static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
    33.8 +    [XENFEAT_writable_page_tables]       = "writable_page_tables",
    33.9 +    [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
   33.10 +    [XENFEAT_auto_translated_physmap]    = "auto_translated_physmap",
   33.11 +    [XENFEAT_supervisor_mode_kernel]     = "supervisor_mode_kernel",
   33.12 +    [XENFEAT_pae_pgdir_above_4gb]        = "pae_pgdir_above_4gb"
   33.13 +};
   33.14 +
   33.15 +static inline void set_feature_bit (int nr, uint32_t *addr)
   33.16 +{
   33.17 +    addr[nr>>5] |= (1<<(nr&31));
   33.18 +}
   33.19 +
   33.20 +static inline int test_feature_bit(int nr, uint32_t *addr)
   33.21 +{
   33.22 +    return !!(addr[nr>>5] & (1<<(nr&31)));
   33.23 +}
   33.24 +
   33.25 +static int parse_features(
   33.26 +    const char *feats,
   33.27 +    uint32_t supported[XENFEAT_NR_SUBMAPS],
   33.28 +    uint32_t required[XENFEAT_NR_SUBMAPS])
   33.29 +{
   33.30 +    const char *end, *p;
   33.31 +    int i, req;
   33.32 +
   33.33 +    if ( (end = strchr(feats, ',')) == NULL )
   33.34 +        end = feats + strlen(feats);
   33.35 +
   33.36 +    while ( feats < end )
   33.37 +    {
   33.38 +        p = strchr(feats, '|');
   33.39 +        if ( (p == NULL) || (p > end) )
   33.40 +            p = end;
   33.41 +
   33.42 +        req = (*feats == '!');
   33.43 +        if ( req )
   33.44 +            feats++;
   33.45 +
   33.46 +        for ( i = 0; i < XENFEAT_NR_SUBMAPS*32; i++ )
   33.47 +        {
   33.48 +            if ( feature_names[i] == NULL )
   33.49 +                continue;
   33.50 +
   33.51 +            if ( strncmp(feature_names[i], feats, p-feats) == 0 )
   33.52 +            {
   33.53 +                set_feature_bit(i, supported);
   33.54 +                if ( required && req )
   33.55 +                    set_feature_bit(i, required);
   33.56 +                break;
   33.57 +            }
   33.58 +        }
   33.59 +
   33.60 +        if ( i == XENFEAT_NR_SUBMAPS*32 )
   33.61 +        {
   33.62 +            ERROR("Unknown feature \"%.*s\".\n", (int)(p-feats), feats);
   33.63 +            if ( req )
   33.64 +            {
   33.65 +                ERROR("Kernel requires an unknown hypervisor feature.\n");
   33.66 +                return -EINVAL;
   33.67 +            }
   33.68 +        }
   33.69 +
   33.70 +        feats = p;
   33.71 +        if ( *feats == '|' )
   33.72 +            feats++;
   33.73 +    }
   33.74 +
   33.75 +    return -EINVAL;
   33.76 +}
   33.77 +
   33.78  static int probeimageformat(char *image,
   33.79                              unsigned long image_size,
   33.80                              struct load_funcs *load_funcs)
   33.81 @@ -344,7 +415,8 @@ static int setup_guest(int xc_handle,
   33.82                         unsigned long shared_info_frame,
   33.83                         unsigned long flags,
   33.84                         unsigned int store_evtchn, unsigned long *store_mfn,
   33.85 -                       unsigned int console_evtchn, unsigned long *console_mfn)
   33.86 +                       unsigned int console_evtchn, unsigned long *console_mfn,
   33.87 +                       uint32_t required_features[XENFEAT_NR_SUBMAPS])
   33.88  {
   33.89      unsigned long *page_array = NULL;
   33.90      struct load_funcs load_funcs;
   33.91 @@ -483,7 +555,8 @@ static int setup_guest(int xc_handle,
   33.92                         unsigned long shared_info_frame,
   33.93                         unsigned long flags,
   33.94                         unsigned int store_evtchn, unsigned long *store_mfn,
   33.95 -                       unsigned int console_evtchn, unsigned long *console_mfn)
   33.96 +                       unsigned int console_evtchn, unsigned long *console_mfn,
   33.97 +                       uint32_t required_features[XENFEAT_NR_SUBMAPS])
   33.98  {
   33.99      unsigned long *page_array = NULL;
  33.100      unsigned long count, i, hypercall_pfn;
  33.101 @@ -515,8 +588,9 @@ static int setup_guest(int xc_handle,
  33.102      unsigned long vpt_start;
  33.103      unsigned long vpt_end;
  33.104      unsigned long v_end;
  33.105 -    unsigned shadow_mode_enabled;
  33.106      unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn;
  33.107 +    unsigned long shadow_mode_enabled;
  33.108 +    uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, };
  33.109  
  33.110      rc = probeimageformat(image, image_size, &load_funcs);
  33.111      if ( rc != 0 )
  33.112 @@ -534,8 +608,6 @@ static int setup_guest(int xc_handle,
  33.113          goto error_out;
  33.114      }
  33.115  
  33.116 -    shadow_mode_enabled = !!strstr(dsi.xen_guest_string,
  33.117 -                                   "SHADOW=translate");
  33.118      /*
  33.119       * Why do we need this? The number of page-table frames depends on the 
  33.120       * size of the bootstrap address space. But the size of the address space 
  33.121 @@ -637,6 +709,35 @@ static int setup_guest(int xc_handle,
  33.122      (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
  33.123                             &dsi);
  33.124  
  33.125 +    /* Parse and validate kernel features. */
  33.126 +    p = strstr(dsi.xen_guest_string, "FEATURES=");
  33.127 +    if ( p != NULL )
  33.128 +    {
  33.129 +        if ( !parse_features(p + strlen("FEATURES="),
  33.130 +                             supported_features,
  33.131 +                             required_features) )
  33.132 +        {
  33.133 +            ERROR("Failed to parse guest kernel features.\n");
  33.134 +            goto error_out;
  33.135 +        }
  33.136 +
  33.137 +        fprintf(stderr, "Supported features  = { %08x }.\n",
  33.138 +                supported_features[0]);
  33.139 +        fprintf(stderr, "Required features   = { %08x }.\n",
  33.140 +                required_features[0]);
  33.141 +    }
  33.142 +
  33.143 +    for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
  33.144 +    {
  33.145 +        if ( (supported_features[i]&required_features[i]) != required_features[i] )
  33.146 +        {
  33.147 +            ERROR("Guest kernel does not support a required feature.\n");
  33.148 +            goto error_out;
  33.149 +        }
  33.150 +    }
  33.151 +
  33.152 +    shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, required_features);
  33.153 +
  33.154      /* Load the initial ramdisk image. */
  33.155      if ( initrd_len != 0 )
  33.156      {
  33.157 @@ -870,6 +971,7 @@ int xc_linux_build(int xc_handle,
  33.158                     const char *image_name,
  33.159                     const char *ramdisk_name,
  33.160                     const char *cmdline,
  33.161 +                   const char *features,
  33.162                     unsigned long flags,
  33.163                     unsigned int store_evtchn,
  33.164                     unsigned long *store_mfn,
  33.165 @@ -886,6 +988,16 @@ int xc_linux_build(int xc_handle,
  33.166      char         *image = NULL;
  33.167      unsigned long image_size, initrd_size=0;
  33.168      unsigned long vstartinfo_start, vkern_entry, vstack_start;
  33.169 +    uint32_t      features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, };
  33.170 +
  33.171 +    if ( features != NULL )
  33.172 +    {
  33.173 +        if ( !parse_features(features, features_bitmap, NULL) )
  33.174 +        {
  33.175 +            PERROR("Failed to parse configured features\n");
  33.176 +            goto error_out;
  33.177 +        }
  33.178 +    }
  33.179  
  33.180      if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 )
  33.181      {
  33.182 @@ -940,7 +1052,8 @@ int xc_linux_build(int xc_handle,
  33.183                       &vstack_start, ctxt, cmdline,
  33.184                       op.u.getdomaininfo.shared_info_frame,
  33.185                       flags, store_evtchn, store_mfn,
  33.186 -                     console_evtchn, console_mfn) < 0 )
  33.187 +                     console_evtchn, console_mfn,
  33.188 +                     features_bitmap) < 0 )
  33.189      {
  33.190          ERROR("Error constructing guest OS");
  33.191          goto error_out;
    34.1 --- a/tools/libxc/xenguest.h	Mon Feb 27 17:26:16 2006 +0100
    34.2 +++ b/tools/libxc/xenguest.h	Mon Feb 27 18:44:38 2006 +0100
    34.3 @@ -47,6 +47,7 @@ int xc_linux_build(int xc_handle,
    34.4                     const char *image_name,
    34.5                     const char *ramdisk_name,
    34.6                     const char *cmdline,
    34.7 +                   const char *features,
    34.8                     unsigned long flags,
    34.9                     unsigned int store_evtchn,
   34.10                     unsigned long *store_mfn,
    35.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Mon Feb 27 17:26:16 2006 +0100
    35.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Mon Feb 27 18:44:38 2006 +0100
    35.3 @@ -326,27 +326,29 @@ static PyObject *pyxc_linux_build(XcObje
    35.4                                    PyObject *kwds)
    35.5  {
    35.6      uint32_t dom;
    35.7 -    char *image, *ramdisk = NULL, *cmdline = "";
    35.8 +    char *image, *ramdisk = NULL, *cmdline = "", *features = NULL;
    35.9      int flags = 0;
   35.10      int store_evtchn, console_evtchn;
   35.11      unsigned long store_mfn = 0;
   35.12      unsigned long console_mfn = 0;
   35.13  
   35.14 -    static char *kwd_list[] = { "dom", "store_evtchn", 
   35.15 -                                "console_evtchn", "image", 
   35.16 +    static char *kwd_list[] = { "dom", "store_evtchn",
   35.17 +                                "console_evtchn", "image",
   35.18  				/* optional */
   35.19 -				"ramdisk", "cmdline", "flags", NULL };
   35.20 +				"ramdisk", "cmdline", "flags",
   35.21 +				"features", NULL };
   35.22  
   35.23 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssi", kwd_list,
   35.24 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssis", kwd_list,
   35.25                                        &dom, &store_evtchn,
   35.26 -				      &console_evtchn, &image, 
   35.27 +				      &console_evtchn, &image,
   35.28  				      /* optional */
   35.29 -				      &ramdisk, &cmdline, &flags) )
   35.30 +				      &ramdisk, &cmdline, &flags,
   35.31 +				      &features) )
   35.32          return NULL;
   35.33  
   35.34      if ( xc_linux_build(self->xc_handle, dom, image,
   35.35 -                        ramdisk, cmdline, flags,
   35.36 -                        store_evtchn, &store_mfn, 
   35.37 +                        ramdisk, cmdline, features, flags,
   35.38 +                        store_evtchn, &store_mfn,
   35.39  			console_evtchn, &console_mfn) != 0 ) {
   35.40          if (!errno)
   35.41               errno = EINVAL;
    36.1 --- a/tools/python/xen/xend/image.py	Mon Feb 27 17:26:16 2006 +0100
    36.2 +++ b/tools/python/xen/xend/image.py	Mon Feb 27 18:44:38 2006 +0100
    36.3 @@ -68,6 +68,7 @@ class ImageHandler:
    36.4          self.kernel = None
    36.5          self.ramdisk = None
    36.6          self.cmdline = None
    36.7 +        self.features = None
    36.8  
    36.9          self.configure(imageConfig, deviceConfig)
   36.10  
   36.11 @@ -89,6 +90,7 @@ class ImageHandler:
   36.12          if args:
   36.13              self.cmdline += " " + args
   36.14          self.ramdisk = get_cfg("ramdisk", '')
   36.15 +        self.features = get_cfg("features", '')
   36.16          
   36.17          self.vm.storeVm(("image/ostype", self.ostype),
   36.18                          ("image/kernel", self.kernel),
   36.19 @@ -175,13 +177,15 @@ class LinuxImageHandler(ImageHandler):
   36.20          log.debug("cmdline        = %s", self.cmdline)
   36.21          log.debug("ramdisk        = %s", self.ramdisk)
   36.22          log.debug("vcpus          = %d", self.vm.getVCpuCount())
   36.23 +        log.debug("features       = %s", self.features)
   36.24  
   36.25          return xc.linux_build(dom            = self.vm.getDomid(),
   36.26                                image          = self.kernel,
   36.27                                store_evtchn   = store_evtchn,
   36.28                                console_evtchn = console_evtchn,
   36.29                                cmdline        = self.cmdline,
   36.30 -                              ramdisk        = self.ramdisk)
   36.31 +                              ramdisk        = self.ramdisk,
   36.32 +                              features       = self.features)
   36.33  
   36.34  class HVMImageHandler(ImageHandler):
   36.35  
    37.1 --- a/tools/python/xen/xm/create.py	Mon Feb 27 17:26:16 2006 +0100
    37.2 +++ b/tools/python/xen/xm/create.py	Mon Feb 27 18:44:38 2006 +0100
    37.3 @@ -137,6 +137,10 @@ gopts.var('ramdisk', val='FILE',
    37.4            fn=set_value, default='',
    37.5            use="Path to ramdisk.")
    37.6  
    37.7 +gopts.var('features', val='FEATURES',
    37.8 +          fn=set_value, default='',
    37.9 +          use="Features to enable in guest kernel")
   37.10 +
   37.11  gopts.var('builder', val='FUNCTION',
   37.12            fn=set_value, default='linux',
   37.13            use="Function to use to build the domain.")
   37.14 @@ -445,6 +449,8 @@ def configure_image(vals):
   37.15          config_image.append(['root', cmdline_root])
   37.16      if vals.extra:
   37.17          config_image.append(['args', vals.extra])
   37.18 +    if vals.features:
   37.19 +        config_image.append(['features', vals.features])
   37.20  
   37.21      if vals.builder == 'hvm':
   37.22          configure_hvm(config_image, vals)
    38.1 --- a/xen/arch/x86/domain_build.c	Mon Feb 27 17:26:16 2006 +0100
    38.2 +++ b/xen/arch/x86/domain_build.c	Mon Feb 27 18:44:38 2006 +0100
    38.3 @@ -802,6 +802,14 @@ int construct_dom0(struct domain *d,
    38.4          v->arch.guest_context.user_regs.fs &= ~3;
    38.5          v->arch.guest_context.user_regs.gs &= ~3;
    38.6          printk("Dom0 runs in ring 0 (supervisor mode)\n");
    38.7 +        if ( !test_bit(XENFEAT_supervisor_mode_kernel,
    38.8 +                       dom0_features_supported) )
    38.9 +            panic("Dom0 does not support supervisor-mode execution\n");
   38.10 +    }
   38.11 +    else
   38.12 +    {
   38.13 +        if ( test_bit(XENFEAT_supervisor_mode_kernel, dom0_features_required) )
   38.14 +            panic("Dom0 requires supervisor-mode execution\n");
   38.15      }
   38.16  
   38.17      rc = 0;
    39.1 --- a/xen/arch/x86/mm.c	Mon Feb 27 17:26:16 2006 +0100
    39.2 +++ b/xen/arch/x86/mm.c	Mon Feb 27 18:44:38 2006 +0100
    39.3 @@ -1570,42 +1570,68 @@ int new_guest_cr3(unsigned long mfn)
    39.4      unsigned long old_base_mfn;
    39.5  
    39.6      if ( shadow_mode_refcounts(d) )
    39.7 +    {
    39.8          okay = get_page_from_pagenr(mfn, d);
    39.9 +        if ( unlikely(!okay) )
   39.10 +        {
   39.11 +            MEM_LOG("Error while installing new baseptr %lx", mfn);
   39.12 +            return 0;
   39.13 +        }
   39.14 +    }
   39.15      else
   39.16 -        okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
   39.17 -
   39.18 -    if ( likely(okay) )
   39.19      {
   39.20 -        invalidate_shadow_ldt(v);
   39.21 -
   39.22 -        old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
   39.23 -        v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
   39.24 -        update_pagetables(v); /* update shadow_table and monitor_table */
   39.25 -
   39.26 -        write_ptbase(v);
   39.27 -
   39.28 +        okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
   39.29 +        if ( unlikely(!okay) )
   39.30 +        {
   39.31 +            /* Switch to idle pagetable: this VCPU has no active p.t. now. */
   39.32 +            old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
   39.33 +            v->arch.guest_table = mk_pagetable(0);
   39.34 +            update_pagetables(v);
   39.35 +            write_cr3(__pa(idle_pg_table));
   39.36 +            if ( old_base_mfn != 0 )
   39.37 +                put_page_and_type(mfn_to_page(old_base_mfn));
   39.38 +
   39.39 +            /* Retry the validation with no active p.t. for this VCPU. */
   39.40 +            okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
   39.41 +            if ( !okay )
   39.42 +            {
   39.43 +                /* Failure here is unrecoverable: the VCPU has no pagetable! */
   39.44 +                MEM_LOG("Fatal error while installing new baseptr %lx", mfn);
   39.45 +                domain_crash(d);
   39.46 +                percpu_info[v->processor].deferred_ops = 0;
   39.47 +                return 0;
   39.48 +            }
   39.49 +        }
   39.50 +    }
   39.51 +
   39.52 +    invalidate_shadow_ldt(v);
   39.53 +
   39.54 +    old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
   39.55 +    v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
   39.56 +    update_pagetables(v); /* update shadow_table and monitor_table */
   39.57 +
   39.58 +    write_ptbase(v);
   39.59 +
   39.60 +    if ( likely(old_base_mfn != 0) )
   39.61 +    {
   39.62          if ( shadow_mode_refcounts(d) )
   39.63              put_page(mfn_to_page(old_base_mfn));
   39.64          else
   39.65              put_page_and_type(mfn_to_page(old_base_mfn));
   39.66 -
   39.67 -        /* CR3 also holds a ref to its shadow... */
   39.68 -        if ( shadow_mode_enabled(d) )
   39.69 -        {
   39.70 -            if ( v->arch.monitor_shadow_ref )
   39.71 -                put_shadow_ref(v->arch.monitor_shadow_ref);
   39.72 -            v->arch.monitor_shadow_ref =
   39.73 -                pagetable_get_pfn(v->arch.monitor_table);
   39.74 -            ASSERT(!page_get_owner(mfn_to_page(v->arch.monitor_shadow_ref)));
   39.75 -            get_shadow_ref(v->arch.monitor_shadow_ref);
   39.76 -        }
   39.77      }
   39.78 -    else
   39.79 +
   39.80 +    /* CR3 also holds a ref to its shadow... */
   39.81 +    if ( shadow_mode_enabled(d) )
   39.82      {
   39.83 -        MEM_LOG("Error while installing new baseptr %lx", mfn);
   39.84 +        if ( v->arch.monitor_shadow_ref )
   39.85 +            put_shadow_ref(v->arch.monitor_shadow_ref);
   39.86 +        v->arch.monitor_shadow_ref =
   39.87 +            pagetable_get_pfn(v->arch.monitor_table);
   39.88 +        ASSERT(!page_get_owner(mfn_to_page(v->arch.monitor_shadow_ref)));
   39.89 +        get_shadow_ref(v->arch.monitor_shadow_ref);
   39.90      }
   39.91  
   39.92 -    return okay;
   39.93 +    return 1;
   39.94  }
   39.95  
   39.96  static void process_deferred_ops(unsigned int cpu)
   39.97 @@ -1625,7 +1651,7 @@ static void process_deferred_ops(unsigne
   39.98          else
   39.99              local_flush_tlb();
  39.100      }
  39.101 -        
  39.102 +
  39.103      if ( deferred_ops & DOP_RELOAD_LDT )
  39.104          (void)map_ldt_shadow_page(0);
  39.105