# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1183616405 -32400 # Node ID abac1f921c6294e81ae12357988c8fc78f652c0b # Parent 8fc1e4759e8710d671728e4a9c55e1bba162ba3e introduce paravirt_alt and implement binary patch for xen hyperprivops PATCHNAME: paravirt_alt Signed-off-by: Isaku Yamahata diff -r 8fc1e4759e87 -r abac1f921c62 arch/ia64/Kconfig --- a/arch/ia64/Kconfig Thu Jul 05 14:24:23 2007 +0900 +++ b/arch/ia64/Kconfig Thu Jul 05 15:20:05 2007 +0900 @@ -85,6 +85,13 @@ config XEN_IA64_EXPOSE_P2M_USE_DTR default y help use dtr to map the exposed p2m table + +config PARAVIRT_ALT + bool "hyperprivop binary patch" + depends on XEN + default y + help + hyperprivop binary patch. config SCHED_NO_NO_OMIT_FRAME_POINTER bool diff -r 8fc1e4759e87 -r abac1f921c62 arch/ia64/kernel/vmlinux.lds.S --- a/arch/ia64/kernel/vmlinux.lds.S Thu Jul 05 14:24:23 2007 +0900 +++ b/arch/ia64/kernel/vmlinux.lds.S Thu Jul 05 15:20:05 2007 +0900 @@ -151,6 +151,16 @@ SECTIONS *(.data.patch.mckinley_e9) __end___mckinley_e9_bundles = .; } + +#if defined(CONFIG_PARAVIRT_ALT) + . = ALIGN(16); + .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) + { + __start_parainstructions = .; + *(.parainstructions) + __stop_parainstructions = .; + } +#endif #if defined(CONFIG_IA64_GENERIC) /* Machine Vector */ diff -r 8fc1e4759e87 -r abac1f921c62 arch/ia64/xen/Makefile --- a/arch/ia64/xen/Makefile Thu Jul 05 14:24:23 2007 +0900 +++ b/arch/ia64/xen/Makefile Thu Jul 05 15:20:05 2007 +0900 @@ -7,3 +7,4 @@ obj-y := hypercall.o xenivt.o xenentry.o xcom_privcmd.o mem.o xen_dma.o obj-$(CONFIG_IA64_GENERIC) += machvec.o +obj-$(CONFIG_PARAVIRT_ALT) += paravirt_alt.o privop.o privop_s.o diff -r 8fc1e4759e87 -r abac1f921c62 arch/ia64/xen/paravirt_alt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arch/ia64/xen/paravirt_alt.c Thu Jul 05 15:20:05 2007 +0900 @@ -0,0 +1,84 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirt_alt.c + * + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include /* for bundle_t */ + +extern const char nop_bundle[]; +extern const unsigned long nop_bundle_size; + +static void __init +fill_nop(void* instr, unsigned long size) +{ + BUG_ON((((unsigned long)instr) % sizeof(bundle_t)) != 0); + BUG_ON((size % nop_bundle_size) != 0); + + while (size >= nop_bundle_size) { + memcpy(instr, nop_bundle, nop_bundle_size); + + instr += nop_bundle_size; + size -= nop_bundle_size; + } +} + +void __init +paravirt_patch_apply(struct paravirt_patch* start, struct paravirt_patch* end, + unsigned long(*patch)(void* instr, unsigned long size, + unsigned long type)) +{ + struct paravirt_patch *p; + + for (p = start; p < end; p++) { + unsigned long used; + unsigned long i; + + used = (*patch)(p->instr, p->size, p->type); + if (used == 0) + continue; + + fill_nop(p->instr + used, p->size - used); + /* + * flush_icache_range() can't be used here. + * we are here before cpu_init() which initializes + * ia64_i_cache_stride_shift. flush_icache_range() uses it. + */ + for (i = 0; i < p->size; i += sizeof(bundle_t)) { + asm volatile ("fc.i %0":: "r"(p->instr + i): "memory"); + } + } + ia64_sync_i(); + ia64_srlz_i(); +} + +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff -r 8fc1e4759e87 -r abac1f921c62 arch/ia64/xen/privop.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arch/ia64/xen/privop.c Thu Jul 05 15:20:05 2007 +0900 @@ -0,0 +1,79 @@ +/****************************************************************************** + * linux/arch/ia64/xen/privop.c + * + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include /* for bundle_t */ + +#ifdef ASM_SUPPORTED +struct xen_privop_patch_elem { + const void* instr; + unsigned long size; + unsigned long type; +}; + +extern const struct xen_privop_patch_elem xen_privop_array[]; +extern const unsigned long xen_privop_array_size; + +static unsigned long __init +__xen_privop_patch(void* instr, unsigned long size, unsigned long type) +{ + unsigned long used = 0; + unsigned long i; + + BUG_ON((((unsigned long)instr) % sizeof(bundle_t)) != 0); + BUG_ON((size % sizeof(bundle_t)) != 0); + + for (i = 0; i < xen_privop_array_size / sizeof (xen_privop_array[0]); i++) { + const struct xen_privop_patch_elem* p = &xen_privop_array[i]; + if (p->type == type) { + BUG_ON(p->size > size); + used = p->size; + memcpy(instr, p->instr, p->size); + break; + } + } + + return used; +} + +void __init +xen_privop_patch(void) +{ + extern struct paravirt_patch __start_parainstructions[]; + extern struct paravirt_patch __stop_parainstructions[]; + + paravirt_patch_apply(__start_parainstructions, + __stop_parainstructions, + &__xen_privop_patch); +} +#else +void __init +xen_privop_patch(void) +{ + /* do nothing */ +} +#endif diff -r 8fc1e4759e87 -r abac1f921c62 arch/ia64/xen/privop_s.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arch/ia64/xen/privop_s.S Thu Jul 05 15:20:05 2007 +0900 @@ -0,0 +1,124 @@ +/****************************************************************************** + * linux/arch/ia64/xen/privop_s.S + * + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include + + + __INIT + .align 32 + .proc nop_bundle + .global nop_bundle +nop_bundle: +nop_bundle_start: + { + nop 0 + nop 0 + nop 0 + } +nop_bundle_end: + .endp nop_bundle + __FINIT + + __INITDATA + .align 8 + .global nop_bundle_size +nop_bundle_size: + data8 nop_bundle_end - nop_bundle_start + +#define DEFINE_PRIVOP(name, instr) \ + .align 32; \ + .proc xen_ ## name ## _instr; \ + xen_ ## name ## _instr:; \ + xen_ ## name ## _instr_start:; \ + instr; \ + xen_ ## name ## _instr_end:; \ + .endp xen_ ## name ## _instr; + + __INIT + DEFINE_PRIVOP(rfi, XEN_HYPER_RFI) + DEFINE_PRIVOP(rsm_psr_dt, XEN_HYPER_RSM_PSR_DT) + DEFINE_PRIVOP(ssm_psr_dt, XEN_HYPER_SSM_PSR_DT) + DEFINE_PRIVOP(cover, XEN_HYPER_COVER) + DEFINE_PRIVOP(itc_d, XEN_HYPER_ITC_D) + DEFINE_PRIVOP(itc_i, XEN_HYPER_ITC_I) + DEFINE_PRIVOP(ssm_i, XEN_HYPER_SSM_I) + DEFINE_PRIVOP(get_ivr, XEN_HYPER_GET_IVR) + DEFINE_PRIVOP(get_tpr, XEN_HYPER_GET_TPR) + DEFINE_PRIVOP(set_tpr, XEN_HYPER_SET_TPR) + DEFINE_PRIVOP(eoi, XEN_HYPER_EOI) + DEFINE_PRIVOP(set_itm, XEN_HYPER_SET_ITM) + DEFINE_PRIVOP(thash, XEN_HYPER_THASH) + DEFINE_PRIVOP(ptc_ga, XEN_HYPER_PTC_GA) + DEFINE_PRIVOP(itr_d, XEN_HYPER_ITR_D) + DEFINE_PRIVOP(get_rr, XEN_HYPER_GET_RR) + DEFINE_PRIVOP(set_rr, XEN_HYPER_SET_RR) + DEFINE_PRIVOP(set_kr, XEN_HYPER_SET_KR) + DEFINE_PRIVOP(fc, XEN_HYPER_FC) + DEFINE_PRIVOP(get_cpuid, XEN_HYPER_GET_CPUID) + DEFINE_PRIVOP(get_pmd, XEN_HYPER_GET_PMD) + DEFINE_PRIVOP(get_eflag, XEN_HYPER_GET_EFLAG) + DEFINE_PRIVOP(set_eflag, XEN_HYPER_SET_EFLAG) + DEFINE_PRIVOP(get_psr, XEN_HYPER_GET_PSR) + __FINIT + + +#define PRIVOP_ELEM(name, type) \ + data8 xen_ ## name ## _instr; \ + data8 xen_ ## name ## _instr_end - xen_ ## name ## _instr_start;\ + data8 type; + + __INITDATA + .align 8 + .global xen_privop_array +xen_privop_array: +xen_privop_array_start: + PRIVOP_ELEM(rfi, HYPERPRIVOP_RFI) + PRIVOP_ELEM(rsm_psr_dt, HYPERPRIVOP_RSM_DT) + PRIVOP_ELEM(ssm_psr_dt, HYPERPRIVOP_SSM_DT) + PRIVOP_ELEM(cover, HYPERPRIVOP_COVER) + PRIVOP_ELEM(itc_d, HYPERPRIVOP_ITC_D) + PRIVOP_ELEM(itc_i, HYPERPRIVOP_ITC_I) + PRIVOP_ELEM(ssm_i, HYPERPRIVOP_SSM_I) + PRIVOP_ELEM(get_ivr, HYPERPRIVOP_GET_IVR) + PRIVOP_ELEM(get_tpr, HYPERPRIVOP_GET_TPR) + PRIVOP_ELEM(set_tpr, HYPERPRIVOP_SET_TPR) + PRIVOP_ELEM(eoi, HYPERPRIVOP_EOI) + PRIVOP_ELEM(set_itm, HYPERPRIVOP_SET_ITM) + PRIVOP_ELEM(thash, HYPERPRIVOP_THASH) + PRIVOP_ELEM(ptc_ga, HYPERPRIVOP_PTC_GA) + PRIVOP_ELEM(itr_d, HYPERPRIVOP_ITR_D) + PRIVOP_ELEM(get_rr, HYPERPRIVOP_GET_RR) + PRIVOP_ELEM(set_rr, HYPERPRIVOP_SET_RR) + PRIVOP_ELEM(set_kr, HYPERPRIVOP_SET_KR) + PRIVOP_ELEM(fc, HYPERPRIVOP_FC) + PRIVOP_ELEM(get_cpuid, HYPERPRIVOP_GET_CPUID) + PRIVOP_ELEM(get_pmd, HYPERPRIVOP_GET_PMD) + PRIVOP_ELEM(get_eflag, HYPERPRIVOP_GET_EFLAG) + PRIVOP_ELEM(set_eflag, HYPERPRIVOP_SET_EFLAG) + PRIVOP_ELEM(get_psr, HYPERPRIVOP_GET_PSR) +xen_privop_array_end: + + .align 8 + .global xen_privop_array_size +xen_privop_array_size: + .long xen_privop_array_end - xen_privop_array_start diff -r 8fc1e4759e87 -r abac1f921c62 arch/ia64/xen/xensetup.S --- a/arch/ia64/xen/xensetup.S Thu Jul 05 14:24:23 2007 +0900 +++ b/arch/ia64/xen/xensetup.S Thu Jul 05 15:20:05 2007 +0900 @@ -35,6 +35,16 @@ GLOBAL_ENTRY(early_xen_setup) (isBP) movl r28=XSI_BASE;; (isBP) break 0x1000;; +#ifdef CONFIG_PARAVIRT_ALT + /* patch privops */ +(isBP) mov r4=rp + ;; +(isBP) br.call.sptk.many rp=xen_privop_patch + ;; +(isBP) mov rp=r4 + ;; +#endif + br.ret.sptk.many rp ;; END(early_xen_setup) diff -r 8fc1e4759e87 -r abac1f921c62 include/asm-ia64/paravirt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/asm-ia64/paravirt.h Thu Jul 05 15:20:05 2007 +0900 @@ -0,0 +1,340 @@ +/****************************************************************************** + * Copyright (c) 2006 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ASM_PARAVIRT_H +#define __ASM_PARAVIRT_H + +#include + +/* for binary patch */ +struct paravirt_patch { + void* instr; + unsigned long size; + unsigned long type; +}; + +/* label means the beginning of new bundle */ +#define paravirt_alt(instr, privop) \ + "\t1:\n" \ + "\t" instr "\n" \ + "\t2:\n" \ + "\t.section .parainstructions, \"a\"\n" \ + "\t.previous\n" \ + "\t.xdata8 \".parainstructions\", 1b, 2b-1b, " \ + __stringify(privop) "\n" + +/************************************************/ +/* Instructions paravirtualized for correctness */ +/************************************************/ +/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" + * is not currently used (though it may be in a long-format VHPT system!) */ +static inline unsigned long +paravirt_fc(unsigned long addr) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __addr asm ("r8") = addr; + asm volatile (paravirt_alt("fc %1", HYPERPRIVOP_THASH): + "=r"(ia64_intri_res): "0"(__addr): "memory"); + return ia64_intri_res; +} +#define paravirt_fc(addr) paravirt_fc((unsigned long)addr) + +static inline unsigned long +paravirt_thash(unsigned long addr) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __addr asm ("r8") = addr; + asm volatile (paravirt_alt("thash %0=%1", HYPERPRIVOP_THASH): + "=r"(ia64_intri_res): "0"(__addr)); + return ia64_intri_res; +} + +static inline unsigned long +paravirt_get_cpuid(int index) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __index asm ("r8") = index; + asm volatile (paravirt_alt("mov %0=cpuid[%r1]", + HYPERPRIVOP_GET_CPUID): + "=r"(ia64_intri_res): "0O"(__index)); + return ia64_intri_res; +} + +static inline unsigned long +paravirt_get_pmd(int index) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __index asm ("r8") = index; + asm volatile (paravirt_alt("mov %0=pmd[%1]", HYPERPRIVOP_GET_PMD): + "=r"(ia64_intri_res): "0"(__index)); + return ia64_intri_res; +} + +static inline unsigned long +paravirt_get_eflag(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile (paravirt_alt("mov %0=ar%1", HYPERPRIVOP_GET_EFLAG): + "=r"(ia64_intri_res): + "i"(_IA64_REG_AR_EFLAG - _IA64_REG_AR_KR0): "memory"); + return ia64_intri_res; +} + +static inline void +paravirt_set_eflag(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile (paravirt_alt("mov ar%0=%1", HYPERPRIVOP_SET_EFLAG):: + "i"(_IA64_REG_AR_EFLAG - _IA64_REG_AR_KR0), "r"(__val): + "memory"); +} + +/************************************************/ +/* Instructions paravirtualized for performance */ +/************************************************/ + +static inline unsigned long +paravirt_get_psr(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile (paravirt_alt("mov %0=psr", HYPERPRIVOP_GET_PSR): + "=r"(ia64_intri_res)); + return ia64_intri_res; +} + +static inline unsigned long +paravirt_get_ivr(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile (paravirt_alt("mov %0=cr%1", HYPERPRIVOP_GET_IVR): + "=r"(ia64_intri_res): + "i" (_IA64_REG_CR_IVR - _IA64_REG_CR_DCR)); + return ia64_intri_res; +} + +static inline unsigned long +paravirt_get_tpr(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile (paravirt_alt("mov %0=cr%1", HYPERPRIVOP_GET_TPR): + "=r"(ia64_intri_res): + "i" (_IA64_REG_CR_TPR - _IA64_REG_CR_DCR)); + return ia64_intri_res; +} + +static inline void +paravirt_set_tpr(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile (paravirt_alt("mov cr%0=%1", HYPERPRIVOP_SET_TPR):: + "i" (_IA64_REG_CR_TPR - _IA64_REG_CR_DCR), "r"(__val): + "memory"); +} + +static inline void +paravirt_eoi(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile (paravirt_alt("mov cr%0=%1", HYPERPRIVOP_EOI):: + "i" (_IA64_REG_CR_EOI - _IA64_REG_CR_DCR), "r"(__val): + "memory"); +} + +static inline void +paravirt_set_itm(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile (paravirt_alt("mov cr%0=%1", HYPERPRIVOP_SET_ITM):: + "i" (_IA64_REG_CR_ITM - _IA64_REG_CR_DCR), "r"(__val): + "memory"); +} + +static inline void +paravirt_ptcga(unsigned long addr, unsigned long size) +{ + register __u64 __addr asm ("r8") = addr; + register __u64 __size asm ("r9") = size; + asm volatile (paravirt_alt("ptc.ga %0,%1", HYPERPRIVOP_PTC_GA):: + "r"(__addr), "r"(__size): "memory"); + ia64_dv_serialize_data(); +} + +static inline unsigned long +paravirt_get_rr(unsigned long index) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __index asm ("r8") = index; + asm volatile (paravirt_alt("mov %0=rr[%1]", HYPERPRIVOP_GET_RR): + "=r"(ia64_intri_res) : "0" (__index)); + return ia64_intri_res; +} + +static inline void +paravirt_set_rr(unsigned long index, unsigned long val) +{ + register __u64 __index asm ("r8") = index; + register __u64 __val asm ("r9") = val; + asm volatile (paravirt_alt("mov rr[%0]=%1", HYPERPRIVOP_SET_RR):: + "r"(__index), "r"(__val): "memory"); +} + +static inline void +paravirt_set_kr(unsigned long index, unsigned long val) +{ + register __u64 __index asm ("r8") = index - _IA64_REG_AR_KR0; + register __u64 __val asm ("r9") = val; + + //asm volatile ("break %0":: + // "i"(HYPERPRIVOP_SET_KR), "r"(__index), "r"(__val)); +#ifndef BUILD_BUG_ON +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) +#endif + BUILD_BUG_ON(!__builtin_constant_p(__index)); + switch (index) { + case _IA64_REG_AR_KR0: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR0 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + case _IA64_REG_AR_KR1: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR1 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + case _IA64_REG_AR_KR2: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR2 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + case _IA64_REG_AR_KR3: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR3 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + case _IA64_REG_AR_KR4: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR4 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + case _IA64_REG_AR_KR5: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR5 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + case _IA64_REG_AR_KR6: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR6 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + case _IA64_REG_AR_KR7: + asm volatile (paravirt_alt("mov ar%0=%2", + HYPERPRIVOP_SET_KR):: + "i" (_IA64_REG_AR_KR7 - _IA64_REG_AR_KR0), + "r"(__index), "r"(__val): + "memory"); + break; + default: { + extern void compile_error_ar_kr_index_must_be_copmile_time_constant(void); + compile_error_ar_kr_index_must_be_copmile_time_constant(); + break; + } + } +} + +static inline unsigned long +paravirt_getreg(unsigned long regnum) +{ + __u64 ia64_intri_res; + + switch(regnum) { + case _IA64_REG_PSR: + ia64_intri_res = paravirt_get_psr(); + break; + case _IA64_REG_CR_IVR: + ia64_intri_res = paravirt_get_ivr(); + break; + case _IA64_REG_CR_TPR: + ia64_intri_res = paravirt_get_tpr(); + break; + case _IA64_REG_AR_EFLAG: + ia64_intri_res = paravirt_get_eflag(); + break; + default: + ia64_intri_res = __ia64_getreg(regnum); + break; + } + return ia64_intri_res; + } + +static inline void +paravirt_setreg(unsigned long regnum, unsigned long val) +{ + switch(regnum) { + case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: + paravirt_set_kr(regnum, val); + break; + case _IA64_REG_CR_ITM: + paravirt_set_itm(val); + break; + case _IA64_REG_CR_TPR: + paravirt_set_tpr(val); + break; + case _IA64_REG_CR_EOI: + paravirt_eoi(val); + break; + case _IA64_REG_AR_EFLAG: + paravirt_set_eflag(val); + break; + default: + __ia64_setreg(regnum,val); + break; + } +} + +void +paravirt_patch_apply(struct paravirt_patch* start, struct paravirt_patch* end, + unsigned long(*patch)(void* instr, unsigned long size, + unsigned long type)); + +#endif /* __ASM_PARAVIRT_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff -r 8fc1e4759e87 -r abac1f921c62 include/asm-ia64/xen/privop.h --- a/include/asm-ia64/xen/privop.h Thu Jul 05 14:24:23 2007 +0900 +++ b/include/asm-ia64/xen/privop.h Thu Jul 05 15:20:05 2007 +0900 @@ -6,6 +6,11 @@ * Dan Magenheimer * * Paravirtualizations of privileged operations for Xen/ia64 + * + * + * inline privop and paravirt_alt support + * Copyright (c) 2007 Isaku Yamahata + * VA Linux Systems Japan K.K. * */ @@ -509,6 +514,32 @@ do { \ #define ia64_ptri __ia64_ptri #define ia64_ptrd __ia64_ptrd +#if defined(ASM_SUPPORTED) && defined(CONFIG_PARAVIRT_ALT) + +#undef ia64_fc +#undef ia64_thash +#undef ia64_get_cpuid +#undef ia64_get_pmd +#undef ia64_ptcga +#undef ia64_set_rr +#undef ia64_get_rr +#undef ia64_getreg +#undef ia64_setreg + +#include + +#define ia64_fc(addr) paravirt_fc(addr) +#define ia64_thash(addr) paravirt_thash(addr) +#define ia64_get_cpuid(i) paravirt_get_cpuid(i) +#define ia64_get_pmd(i) paravirt_get_pmd(i) +#define ia64_ptcga(addr, size) paravirt_ptcga((addr), (size)) +#define ia64_set_rr(index, val) paravirt_set_rr((index), (val)) +#define ia64_get_rr(index) paravirt_get_rr(index) +#define ia64_getreg(regnum) paravirt_getreg(regnum) +#define ia64_setreg(regnum, val) paravirt_setreg((regnum), (val)) + +#endif /* CONFIG_PARAVIRT_ALT */ + #endif /* !__ASSEMBLY__ */ /* these routines utilize privilege-sensitive or performance-sensitive