ia64/xen-unstable

changeset 14253:192b59b472bc

linux 2.6.18: eliminate Xen special: alternative.c

The sole (x86-64 specific) difference of
arch/i386/kernel/alternative-xen.c
over its native original can be eliminated by slightly adjusting
x86-64's make_readonly(), and the Xen special can then be removed.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author kfraser@localhost.localdomain
date Mon Mar 05 13:32:50 2007 +0000 (2007-03-05)
parents c371b6b26753
children ea40e314d8be
files linux-2.6-xen-sparse/arch/i386/kernel/alternative-xen.c linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/alternative-xen.c	Mon Mar 05 13:30:52 2007 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,389 +0,0 @@
     1.4 -#include <linux/module.h>
     1.5 -#include <linux/spinlock.h>
     1.6 -#include <linux/list.h>
     1.7 -#include <asm/alternative.h>
     1.8 -#include <asm/sections.h>
     1.9 -
    1.10 -static int no_replacement    = 0;
    1.11 -static int smp_alt_once      = 0;
    1.12 -static int debug_alternative = 0;
    1.13 -
    1.14 -static int __init noreplacement_setup(char *s)
    1.15 -{
    1.16 -	no_replacement = 1;
    1.17 -	return 1;
    1.18 -}
    1.19 -static int __init bootonly(char *str)
    1.20 -{
    1.21 -	smp_alt_once = 1;
    1.22 -	return 1;
    1.23 -}
    1.24 -static int __init debug_alt(char *str)
    1.25 -{
    1.26 -	debug_alternative = 1;
    1.27 -	return 1;
    1.28 -}
    1.29 -
    1.30 -__setup("noreplacement", noreplacement_setup);
    1.31 -__setup("smp-alt-boot", bootonly);
    1.32 -__setup("debug-alternative", debug_alt);
    1.33 -
    1.34 -#define DPRINTK(fmt, args...) if (debug_alternative) \
    1.35 -	printk(KERN_DEBUG fmt, args)
    1.36 -
    1.37 -#ifdef GENERIC_NOP1
    1.38 -/* Use inline assembly to define this because the nops are defined
    1.39 -   as inline assembly strings in the include files and we cannot
    1.40 -   get them easily into strings. */
    1.41 -asm("\t.data\nintelnops: "
    1.42 -	GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
    1.43 -	GENERIC_NOP7 GENERIC_NOP8);
    1.44 -extern unsigned char intelnops[];
    1.45 -static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
    1.46 -	NULL,
    1.47 -	intelnops,
    1.48 -	intelnops + 1,
    1.49 -	intelnops + 1 + 2,
    1.50 -	intelnops + 1 + 2 + 3,
    1.51 -	intelnops + 1 + 2 + 3 + 4,
    1.52 -	intelnops + 1 + 2 + 3 + 4 + 5,
    1.53 -	intelnops + 1 + 2 + 3 + 4 + 5 + 6,
    1.54 -	intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
    1.55 -};
    1.56 -#endif
    1.57 -
    1.58 -#ifdef K8_NOP1
    1.59 -asm("\t.data\nk8nops: "
    1.60 -	K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
    1.61 -	K8_NOP7 K8_NOP8);
    1.62 -extern unsigned char k8nops[];
    1.63 -static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
    1.64 -	NULL,
    1.65 -	k8nops,
    1.66 -	k8nops + 1,
    1.67 -	k8nops + 1 + 2,
    1.68 -	k8nops + 1 + 2 + 3,
    1.69 -	k8nops + 1 + 2 + 3 + 4,
    1.70 -	k8nops + 1 + 2 + 3 + 4 + 5,
    1.71 -	k8nops + 1 + 2 + 3 + 4 + 5 + 6,
    1.72 -	k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
    1.73 -};
    1.74 -#endif
    1.75 -
    1.76 -#ifdef K7_NOP1
    1.77 -asm("\t.data\nk7nops: "
    1.78 -	K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
    1.79 -	K7_NOP7 K7_NOP8);
    1.80 -extern unsigned char k7nops[];
    1.81 -static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
    1.82 -	NULL,
    1.83 -	k7nops,
    1.84 -	k7nops + 1,
    1.85 -	k7nops + 1 + 2,
    1.86 -	k7nops + 1 + 2 + 3,
    1.87 -	k7nops + 1 + 2 + 3 + 4,
    1.88 -	k7nops + 1 + 2 + 3 + 4 + 5,
    1.89 -	k7nops + 1 + 2 + 3 + 4 + 5 + 6,
    1.90 -	k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
    1.91 -};
    1.92 -#endif
    1.93 -
    1.94 -#ifdef CONFIG_X86_64
    1.95 -
    1.96 -extern char __vsyscall_0;
    1.97 -static inline unsigned char** find_nop_table(void)
    1.98 -{
    1.99 -	return k8_nops;
   1.100 -}
   1.101 -
   1.102 -#else /* CONFIG_X86_64 */
   1.103 -
   1.104 -static struct nop {
   1.105 -	int cpuid;
   1.106 -	unsigned char **noptable;
   1.107 -} noptypes[] = {
   1.108 -	{ X86_FEATURE_K8, k8_nops },
   1.109 -	{ X86_FEATURE_K7, k7_nops },
   1.110 -	{ -1, NULL }
   1.111 -};
   1.112 -
   1.113 -static unsigned char** find_nop_table(void)
   1.114 -{
   1.115 -	unsigned char **noptable = intel_nops;
   1.116 -	int i;
   1.117 -
   1.118 -	for (i = 0; noptypes[i].cpuid >= 0; i++) {
   1.119 -		if (boot_cpu_has(noptypes[i].cpuid)) {
   1.120 -			noptable = noptypes[i].noptable;
   1.121 -			break;
   1.122 -		}
   1.123 -	}
   1.124 -	return noptable;
   1.125 -}
   1.126 -
   1.127 -#endif /* CONFIG_X86_64 */
   1.128 -
   1.129 -extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
   1.130 -extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
   1.131 -extern u8 *__smp_locks[], *__smp_locks_end[];
   1.132 -
   1.133 -extern u8 __smp_alt_begin[], __smp_alt_end[];
   1.134 -
   1.135 -/* Replace instructions with better alternatives for this CPU type.
   1.136 -   This runs before SMP is initialized to avoid SMP problems with
   1.137 -   self modifying code. This implies that assymetric systems where
   1.138 -   APs have less capabilities than the boot processor are not handled.
   1.139 -   Tough. Make sure you disable such features by hand. */
   1.140 -
   1.141 -void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
   1.142 -{
   1.143 -	unsigned char **noptable = find_nop_table();
   1.144 -	struct alt_instr *a;
   1.145 -	u8 *instr;
   1.146 -	int diff, i, k;
   1.147 -
   1.148 -	DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
   1.149 -	for (a = start; a < end; a++) {
   1.150 -		BUG_ON(a->replacementlen > a->instrlen);
   1.151 -		if (!boot_cpu_has(a->cpuid))
   1.152 -			continue;
   1.153 -		instr = a->instr;
   1.154 -#ifdef CONFIG_X86_64
   1.155 -		/* vsyscall code is not mapped yet. resolve it manually. */
   1.156 -		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
   1.157 -			instr -= VSYSCALL_START - (unsigned long)&__vsyscall_0;
   1.158 -			DPRINTK("%s: vsyscall fixup: %p => %p\n",
   1.159 -				__FUNCTION__, a->instr, instr);
   1.160 -		}
   1.161 -#endif
   1.162 -		memcpy(instr, a->replacement, a->replacementlen);
   1.163 -		diff = a->instrlen - a->replacementlen;
   1.164 -		/* Pad the rest with nops */
   1.165 -		for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
   1.166 -			k = diff;
   1.167 -			if (k > ASM_NOP_MAX)
   1.168 -				k = ASM_NOP_MAX;
   1.169 -			memcpy(a->instr + i, noptable[k], k);
   1.170 -		}
   1.171 -	}
   1.172 -}
   1.173 -
   1.174 -#ifdef CONFIG_SMP
   1.175 -
   1.176 -static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end)
   1.177 -{
   1.178 -	struct alt_instr *a;
   1.179 -
   1.180 -	DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end);
   1.181 -	for (a = start; a < end; a++) {
   1.182 -		memcpy(a->replacement + a->replacementlen,
   1.183 -		       a->instr,
   1.184 -		       a->instrlen);
   1.185 -	}
   1.186 -}
   1.187 -
   1.188 -static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end)
   1.189 -{
   1.190 -	struct alt_instr *a;
   1.191 -
   1.192 -	for (a = start; a < end; a++) {
   1.193 -		memcpy(a->instr,
   1.194 -		       a->replacement + a->replacementlen,
   1.195 -		       a->instrlen);
   1.196 -	}
   1.197 -}
   1.198 -
   1.199 -static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
   1.200 -{
   1.201 -	u8 **ptr;
   1.202 -
   1.203 -	for (ptr = start; ptr < end; ptr++) {
   1.204 -		if (*ptr < text)
   1.205 -			continue;
   1.206 -		if (*ptr > text_end)
   1.207 -			continue;
   1.208 -		**ptr = 0xf0; /* lock prefix */
   1.209 -	};
   1.210 -}
   1.211 -
   1.212 -static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
   1.213 -{
   1.214 -	unsigned char **noptable = find_nop_table();
   1.215 -	u8 **ptr;
   1.216 -
   1.217 -	for (ptr = start; ptr < end; ptr++) {
   1.218 -		if (*ptr < text)
   1.219 -			continue;
   1.220 -		if (*ptr > text_end)
   1.221 -			continue;
   1.222 -		**ptr = noptable[1][0];
   1.223 -	};
   1.224 -}
   1.225 -
   1.226 -struct smp_alt_module {
   1.227 -	/* what is this ??? */
   1.228 -	struct module	*mod;
   1.229 -	char		*name;
   1.230 -
   1.231 -	/* ptrs to lock prefixes */
   1.232 -	u8		**locks;
   1.233 -	u8		**locks_end;
   1.234 -
   1.235 -	/* .text segment, needed to avoid patching init code ;) */
   1.236 -	u8		*text;
   1.237 -	u8		*text_end;
   1.238 -
   1.239 -	struct list_head next;
   1.240 -};
   1.241 -static LIST_HEAD(smp_alt_modules);
   1.242 -static DEFINE_SPINLOCK(smp_alt);
   1.243 -
   1.244 -void alternatives_smp_module_add(struct module *mod, char *name,
   1.245 -				 void *locks, void *locks_end,
   1.246 -				 void *text,  void *text_end)
   1.247 -{
   1.248 -	struct smp_alt_module *smp;
   1.249 -	unsigned long flags;
   1.250 -
   1.251 -	if (no_replacement)
   1.252 -		return;
   1.253 -
   1.254 -	if (smp_alt_once) {
   1.255 -		if (boot_cpu_has(X86_FEATURE_UP))
   1.256 -			alternatives_smp_unlock(locks, locks_end,
   1.257 -						text, text_end);
   1.258 -		return;
   1.259 -	}
   1.260 -
   1.261 -	smp = kzalloc(sizeof(*smp), GFP_KERNEL);
   1.262 -	if (NULL == smp)
   1.263 -		return; /* we'll run the (safe but slow) SMP code then ... */
   1.264 -
   1.265 -	smp->mod	= mod;
   1.266 -	smp->name	= name;
   1.267 -	smp->locks	= locks;
   1.268 -	smp->locks_end	= locks_end;
   1.269 -	smp->text	= text;
   1.270 -	smp->text_end	= text_end;
   1.271 -	DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n",
   1.272 -		__FUNCTION__, smp->locks, smp->locks_end,
   1.273 -		smp->text, smp->text_end, smp->name);
   1.274 -
   1.275 -	spin_lock_irqsave(&smp_alt, flags);
   1.276 -	list_add_tail(&smp->next, &smp_alt_modules);
   1.277 -	if (boot_cpu_has(X86_FEATURE_UP))
   1.278 -		alternatives_smp_unlock(smp->locks, smp->locks_end,
   1.279 -					smp->text, smp->text_end);
   1.280 -	spin_unlock_irqrestore(&smp_alt, flags);
   1.281 -}
   1.282 -
   1.283 -void alternatives_smp_module_del(struct module *mod)
   1.284 -{
   1.285 -	struct smp_alt_module *item;
   1.286 -	unsigned long flags;
   1.287 -
   1.288 -	if (no_replacement || smp_alt_once)
   1.289 -		return;
   1.290 -
   1.291 -	spin_lock_irqsave(&smp_alt, flags);
   1.292 -	list_for_each_entry(item, &smp_alt_modules, next) {
   1.293 -		if (mod != item->mod)
   1.294 -			continue;
   1.295 -		list_del(&item->next);
   1.296 -		spin_unlock_irqrestore(&smp_alt, flags);
   1.297 -		DPRINTK("%s: %s\n", __FUNCTION__, item->name);
   1.298 -		kfree(item);
   1.299 -		return;
   1.300 -	}
   1.301 -	spin_unlock_irqrestore(&smp_alt, flags);
   1.302 -}
   1.303 -
   1.304 -void alternatives_smp_switch(int smp)
   1.305 -{
   1.306 -	struct smp_alt_module *mod;
   1.307 -	unsigned long flags;
   1.308 -
   1.309 -#ifdef CONFIG_LOCKDEP
   1.310 -	/*
   1.311 -	 * A not yet fixed binutils section handling bug prevents
   1.312 -	 * alternatives-replacement from working reliably, so turn
   1.313 -	 * it off:
   1.314 -	 */
   1.315 -	printk("lockdep: not fixing up alternatives.\n");
   1.316 -	return;
   1.317 -#endif
   1.318 -
   1.319 -	if (no_replacement || smp_alt_once)
   1.320 -		return;
   1.321 -	BUG_ON(!smp && (num_online_cpus() > 1));
   1.322 -
   1.323 -	spin_lock_irqsave(&smp_alt, flags);
   1.324 -	if (smp) {
   1.325 -		printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
   1.326 -		clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
   1.327 -		clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
   1.328 -		alternatives_smp_apply(__smp_alt_instructions,
   1.329 -				       __smp_alt_instructions_end);
   1.330 -		list_for_each_entry(mod, &smp_alt_modules, next)
   1.331 -			alternatives_smp_lock(mod->locks, mod->locks_end,
   1.332 -					      mod->text, mod->text_end);
   1.333 -	} else {
   1.334 -		printk(KERN_INFO "SMP alternatives: switching to UP code\n");
   1.335 -		set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
   1.336 -		set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
   1.337 -		apply_alternatives(__smp_alt_instructions,
   1.338 -				   __smp_alt_instructions_end);
   1.339 -		list_for_each_entry(mod, &smp_alt_modules, next)
   1.340 -			alternatives_smp_unlock(mod->locks, mod->locks_end,
   1.341 -						mod->text, mod->text_end);
   1.342 -	}
   1.343 -	spin_unlock_irqrestore(&smp_alt, flags);
   1.344 -}
   1.345 -
   1.346 -#endif
   1.347 -
   1.348 -void __init alternative_instructions(void)
   1.349 -{
   1.350 -	if (no_replacement) {
   1.351 -		printk(KERN_INFO "(SMP-)alternatives turned off\n");
   1.352 -		free_init_pages("SMP alternatives",
   1.353 -				(unsigned long)__smp_alt_begin,
   1.354 -				(unsigned long)__smp_alt_end);
   1.355 -		return;
   1.356 -	}
   1.357 -	apply_alternatives(__alt_instructions, __alt_instructions_end);
   1.358 -
   1.359 -	/* switch to patch-once-at-boottime-only mode and free the
   1.360 -	 * tables in case we know the number of CPUs will never ever
   1.361 -	 * change */
   1.362 -#ifdef CONFIG_HOTPLUG_CPU
   1.363 -	if (num_possible_cpus() < 2)
   1.364 -		smp_alt_once = 1;
   1.365 -#else
   1.366 -	smp_alt_once = 1;
   1.367 -#endif
   1.368 -
   1.369 -#ifdef CONFIG_SMP
   1.370 -	if (smp_alt_once) {
   1.371 -		if (1 == num_possible_cpus()) {
   1.372 -			printk(KERN_INFO "SMP alternatives: switching to UP code\n");
   1.373 -			set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
   1.374 -			set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
   1.375 -			apply_alternatives(__smp_alt_instructions,
   1.376 -					   __smp_alt_instructions_end);
   1.377 -			alternatives_smp_unlock(__smp_locks, __smp_locks_end,
   1.378 -						_text, _etext);
   1.379 -		}
   1.380 -		free_init_pages("SMP alternatives",
   1.381 -				(unsigned long)__smp_alt_begin,
   1.382 -				(unsigned long)__smp_alt_end);
   1.383 -	} else {
   1.384 -		alternatives_smp_save(__smp_alt_instructions,
   1.385 -				      __smp_alt_instructions_end);
   1.386 -		alternatives_smp_module_add(NULL, "core kernel",
   1.387 -					    __smp_locks, __smp_locks_end,
   1.388 -					    _text, _etext);
   1.389 -		alternatives_smp_switch(0);
   1.390 -	}
   1.391 -#endif
   1.392 -}
     2.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile	Mon Mar 05 13:30:52 2007 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile	Mon Mar 05 13:32:50 2007 +0000
     2.3 @@ -62,7 +62,6 @@ time-y				+= ../../i386/kernel/time-xen.
     2.4  pci-dma-y			+= ../../i386/kernel/pci-dma-xen.o
     2.5  microcode-$(subst m,y,$(CONFIG_MICROCODE))  := ../../i386/kernel/microcode-xen.o
     2.6  quirks-y			:= ../../i386/kernel/quirks-xen.o
     2.7 -alternative-y			:= ../../i386/kernel/alternative-xen.o
     2.8  
     2.9  n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o
    2.10  
     3.1 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c	Mon Mar 05 13:30:52 2007 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c	Mon Mar 05 13:32:50 2007 +0000
     3.3 @@ -410,6 +410,7 @@ static inline void __set_pte(pte_t *dst,
     3.4  
     3.5  static inline int make_readonly(unsigned long paddr)
     3.6  {
     3.7 +	extern char __vsyscall_0;
     3.8  	int readonly = 0;
     3.9  
    3.10  	/* Make new page tables read-only. */
    3.11 @@ -426,9 +427,12 @@ static inline int make_readonly(unsigned
    3.12  	/*
    3.13  	 * No need for writable mapping of kernel image. This also ensures that
    3.14  	 * page and descriptor tables embedded inside don't have writable
    3.15 -	 * mappings. 
    3.16 +	 * mappings. Exclude the vsyscall area here, allowing alternative
    3.17 +	 * instruction patching to work.
    3.18  	 */
    3.19 -	if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)))
    3.20 +	if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end))
    3.21 +	    && !(paddr >= __pa_symbol(&__vsyscall_0)
    3.22 +	         && paddr < __pa_symbol(&__vsyscall_0) + PAGE_SIZE))
    3.23  		readonly = 1;
    3.24  
    3.25  	return readonly;