X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fkernel%2Fpatch.c;h=6f221688c3598147d6fec08ad59b3116f8cf3360;hb=a2f44b27303a5353859d77a3e96a1d3f33f56ab7;hp=6a4ac7d70b357e34901faec54e77009d9d9cd505;hpb=134734d875a0a48d994ef20b9905209b4b8b6f75;p=linux-2.6.git diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c index 6a4ac7d70..6f221688c 100644 --- a/arch/ia64/kernel/patch.c +++ b/arch/ia64/kernel/patch.c @@ -115,7 +115,7 @@ ia64_patch_vtop (unsigned long start, unsigned long end) ia64_srlz_i(); } -void +void __init ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) { static int first_time = 1; @@ -149,7 +149,7 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) ia64_srlz_i(); } -static void +static void __init patch_fsyscall_table (unsigned long start, unsigned long end) { extern unsigned long fsyscall_table[NR_syscalls]; @@ -166,7 +166,7 @@ patch_fsyscall_table (unsigned long start, unsigned long end) ia64_srlz_i(); } -static void +static void __init patch_brl_fsys_bubble_down (unsigned long start, unsigned long end) { extern char fsys_bubble_down[]; @@ -184,7 +184,74 @@ patch_brl_fsys_bubble_down (unsigned long start, unsigned long end) ia64_srlz_i(); } -void +#ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT +extern char __start_gate_running_on_xen_patchlist[]; +extern char __end_gate_running_on_xen_patchlist[]; + +void __init +patch_running_on_xen(unsigned long start, unsigned long end) +{ + extern int running_on_xen; + s32 *offp = (s32 *)start; + u64 ip; + + while (offp < (s32 *)end) { + ip = (u64)ia64_imva((char *)offp + *offp); + ia64_patch_imm64(ip, (u64)&running_on_xen); + ia64_fc((void *)ip); + ++offp; + } + ia64_sync_i(); + ia64_srlz_i(); +} + +static void __init +patch_brl_symaddr(unsigned long start, unsigned long end, + unsigned long symaddr) +{ + s32 *offp = (s32 *)start; + u64 ip; + + while (offp < (s32 *)end) { + ip = (u64)offp + *offp; + ia64_patch_imm60((u64)ia64_imva((void *)ip), + (u64)(symaddr - (ip & -16)) / 16); + ia64_fc((void *)ip); + ++offp; + } + ia64_sync_i(); + ia64_srlz_i(); +} + +#define EXTERN_PATCHLIST(name) \ + extern char __start_gate_brl_##name##_patchlist[]; \ + extern char __end_gate_brl_##name##_patchlist[]; \ + extern char name[] + +#define PATCH_BRL_SYMADDR(name) \ + patch_brl_symaddr((unsigned long)__start_gate_brl_##name##_patchlist, \ + (unsigned long)__end_gate_brl_##name##_patchlist, \ + (unsigned long)name) + +static void __init +patch_brl_in_vdso(void) +{ + EXTERN_PATCHLIST(xen_rsm_be_i); + EXTERN_PATCHLIST(xen_get_psr); + EXTERN_PATCHLIST(xen_ssm_i_0); + EXTERN_PATCHLIST(xen_ssm_i_1); + + PATCH_BRL_SYMADDR(xen_rsm_be_i); + PATCH_BRL_SYMADDR(xen_get_psr); + PATCH_BRL_SYMADDR(xen_ssm_i_0); + PATCH_BRL_SYMADDR(xen_ssm_i_1); +} +#else +#define patch_running_on_xen(start, end) do { } while (0) +#define patch_brl_in_vdso() do { } while (0) +#endif + +void __init ia64_patch_gate (void) { # define START(name) ((unsigned long) __start_gate_##name##_patchlist) @@ -192,6 +259,10 @@ ia64_patch_gate (void) patch_fsyscall_table(START(fsyscall), END(fsyscall)); patch_brl_fsys_bubble_down(START(brl_fsys_bubble_down), END(brl_fsys_bubble_down)); +#ifdef CONFIG_XEN + patch_running_on_xen(START(running_on_xen), END(running_on_xen)); + patch_brl_in_vdso(); +#endif ia64_patch_vtop(START(vtop), END(vtop)); ia64_patch_mckinley_e9(START(mckinley_e9), END(mckinley_e9)); }