You can subscribe to this list here.
2008 |
Jan
(41) |
Feb
(101) |
Mar
(164) |
Apr
(94) |
May
(27) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
---|
From: Isaku Y. <yam...@va...> - 2008-02-25 03:16:48
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/xen/xenentry.S | 798 +++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/xen/privop.h | 22 ++ 2 files changed, 820 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/xen/xenentry.S diff --git a/arch/ia64/xen/xenentry.S b/arch/ia64/xen/xenentry.S new file mode 100644 index 0000000..38a509d --- /dev/null +++ b/arch/ia64/xen/xenentry.S @@ -0,0 +1,798 @@ +/* + * ia64/xen/entry.S + * + * Alternate kernel routines for Xen. Heavily leveraged from + * ia64/kernel/entry.S + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@.hp.com> + */ + +#include <asm/asmmacro.h> +#include <asm/cache.h> +#include <asm/errno.h> +#include <asm/kregs.h> +#include <asm/asm-offsets.h> +#include <asm/pgtable.h> +#include <asm/percpu.h> +#include <asm/processor.h> +#include <asm/thread_info.h> +#include <asm/unistd.h> + +#ifdef CONFIG_XEN +#include "xenminstate.h" +#include <asm/paravirt_nop.h> +#else +#include "minstate.h" +#endif + +/* + * prev_task <- ia64_switch_to(struct task_struct *next) + * With Ingo's new scheduler, interrupts are disabled when this routine gets + * called. The code starting at .map relies on this. The rest of the code + * doesn't care about the interrupt masking status. + */ +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_switch_to) + BR_IF_NATIVE(__ia64_switch_to, r22, p7) +#else +GLOBAL_ENTRY(ia64_switch_to) +#endif + .prologue + alloc r16=ar.pfs,1,0,0,0 + DO_SAVE_SWITCH_STACK + .body + + adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13 + movl r25=init_task + mov r27=IA64_KR(CURRENT_STACK) + adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0 + dep r20=0,in0,61,3 // physical address of "next" + ;; + st8 [r22]=sp // save kernel stack pointer of old task + shr.u r26=r20,IA64_GRANULE_SHIFT + cmp.eq p7,p6=r25,in0 + ;; + /* + * If we've already mapped this task's page, we can skip doing it again. + */ +(p6) cmp.eq p7,p6=r26,r27 +(p6) br.cond.dpnt .map + ;; +.done: + ld8 sp=[r21] // load kernel stack pointer of new task +#ifdef CONFIG_XEN + // update "current" application register + mov r8=IA64_KR_CURRENT + mov r9=in0;; + XEN_HYPER_SET_KR +#else + mov IA64_KR(CURRENT)=in0 // update "current" application register +#endif + mov r8=r13 // return pointer to previously running task + mov r13=in0 // set "current" pointer + ;; + DO_LOAD_SWITCH_STACK + +#ifdef CONFIG_SMP + sync.i // ensure "fc"s done by this CPU are visible on other CPUs +#endif + br.ret.sptk.many rp // boogie on out in new context + +.map: +#ifdef CONFIG_XEN + movl r25=XSI_PSR_IC // clear psr.ic + ;; + st4 [r25]=r0 + ;; +#else + rsm psr.ic // interrupts (psr.i) are already disabled here +#endif + movl r25=PAGE_KERNEL + ;; + srlz.d + or r23=r25,r20 // construct PA | page properties + mov r25=IA64_GRANULE_SHIFT<<2 + ;; +#ifdef CONFIG_XEN + movl r8=XSI_ITIR + ;; + st8 [r8]=r25 + ;; + movl r8=XSI_IFA + ;; + st8 [r8]=in0 // VA of next task... + ;; + mov r25=IA64_TR_CURRENT_STACK + // remember last page we mapped... + mov r8=IA64_KR_CURRENT_STACK + mov r9=r26;; + XEN_HYPER_SET_KR;; +#else + mov cr.itir=r25 + mov cr.ifa=in0 // VA of next task... + ;; + mov r25=IA64_TR_CURRENT_STACK + mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped... +#endif + ;; + itr.d dtr[r25]=r23 // wire in new mapping... +#ifdef CONFIG_XEN + ;; + srlz.d + mov r9=1 + movl r8=XSI_PSR_IC + ;; + st4 [r8]=r9 + ;; +#else + ssm psr.ic // reenable the psr.ic bit + ;; + srlz.d +#endif + br.cond.sptk .done +#ifdef CONFIG_XEN +END(xen_switch_to) +#else +END(ia64_switch_to) +#endif + +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_work_processed_syscall_with_check) + BR_IF_NATIVE(__ia64_work_processed_syscall, r2, p7) + br.cond.sptk xen_work_processed_syscall +END(xen_work_processed_syscall_with_check) +#endif + +/* + * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't + * need to switch to bank 0 and doesn't restore the scratch registers. + * To avoid leaking kernel bits, the scratch registers are set to + * the following known-to-be-safe values: + * + * r1: restored (global pointer) + * r2: cleared + * r3: 1 (when returning to user-level) + * r8-r11: restored (syscall return value(s)) + * r12: restored (user-level stack pointer) + * r13: restored (user-level thread pointer) + * r14: set to __kernel_syscall_via_epc + * r15: restored (syscall #) + * r16-r17: cleared + * r18: user-level b6 + * r19: cleared + * r20: user-level ar.fpsr + * r21: user-level b0 + * r22: cleared + * r23: user-level ar.bspstore + * r24: user-level ar.rnat + * r25: user-level ar.unat + * r26: user-level ar.pfs + * r27: user-level ar.rsc + * r28: user-level ip + * r29: user-level psr + * r30: user-level cfm + * r31: user-level pr + * f6-f11: cleared + * pr: restored (user-level pr) + * b0: restored (user-level rp) + * b6: restored + * b7: set to __kernel_syscall_via_epc + * ar.unat: restored (user-level ar.unat) + * ar.pfs: restored (user-level ar.pfs) + * ar.rsc: restored (user-level ar.rsc) + * ar.rnat: restored (user-level ar.rnat) + * ar.bspstore: restored (user-level ar.bspstore) + * ar.fpsr: restored (user-level ar.fpsr) + * ar.ccv: cleared + * ar.csd: cleared + * ar.ssd: cleared + */ +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_leave_syscall) + BR_IF_NATIVE(__ia64_leave_syscall, r22, p7) +#else +ENTRY(ia64_leave_syscall) +#endif + PT_REGS_UNWIND_INFO(0) + /* + * work.need_resched etc. mustn't get changed by this CPU before it returns to + * user- or fsys-mode, hence we disable interrupts early on. + * + * p6 controls whether current_thread_info()->flags needs to be check for + * extra work. We always check for extra work when returning to user-level. + * With CONFIG_PREEMPT, we also check for extra work when the preempt_count + * is 0. After extra work processing has been completed, execution + * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check + * needs to be redone. + */ +#ifdef CONFIG_PREEMPT + rsm psr.i // disable interrupts + cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; + .pred.rel.mutex pUStk,pKStk +(pKStk) ld4 r21=[r20] // r21 <- preempt_count +(pUStk) mov r21=0 // r21 <- 0 + ;; + cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0) +#else /* !CONFIG_PREEMPT */ +#ifdef CONFIG_XEN + movl r2=XSI_PSR_I_ADDR + mov r18=1 + ;; + ld8 r2=[r2] + ;; +(pUStk) st1 [r2]=r18 +#else +(pUStk) rsm psr.i +#endif + cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk +#endif +#ifdef CONFIG_XEN +.global xen_work_processed_syscall; +xen_work_processed_syscall: +#else +.work_processed_syscall: +#endif + adds r2=PT(LOADRS)+16,r12 + adds r3=PT(AR_BSPSTORE)+16,r12 + adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 + ;; +(p6) ld4 r31=[r18] // load current_thread_info()->flags + ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" + nop.i 0 + ;; + mov r16=ar.bsp // M2 get existing backing store pointer + ld8 r18=[r2],PT(R9)-PT(B6) // load b6 +(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? + ;; + ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage) +(p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending? +(p6) br.cond.spnt .work_pending_syscall + ;; + // start restoring the state saved on the kernel stack (struct pt_regs): + ld8 r9=[r2],PT(CR_IPSR)-PT(R9) + ld8 r11=[r3],PT(CR_IIP)-PT(R11) +(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE! + ;; + invala // M0|1 invalidate ALAT +#ifdef CONFIG_XEN + movl r28=XSI_PSR_I_ADDR + movl r29=XSI_PSR_IC + ;; + ld8 r28=[r28] + mov r30=1 + ;; + st1 [r28]=r30 + st4 [r29]=r0 // note: clears both vpsr.i and vpsr.ic! + ;; +#else + rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection +#endif + cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs + + ld8 r29=[r2],16 // M0|1 load cr.ipsr + ld8 r28=[r3],16 // M0|1 load cr.iip + mov r22=r0 // A clear r22 + ;; + ld8 r30=[r2],16 // M0|1 load cr.ifs + ld8 r25=[r3],16 // M0|1 load ar.unat +(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 + ;; + ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs +#ifdef CONFIG_XEN +(pKStk) mov r21=r8 +(pKStk) XEN_HYPER_GET_PSR + ;; +(pKStk) mov r22=r8 +(pKStk) mov r8=r21 + ;; +#else +(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled +#endif + nop 0 + ;; + ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0 + ld8 r27=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc + mov f6=f0 // F clear f6 + ;; + ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage) + ld8 r31=[r3],PT(R1)-PT(PR) // M0|1 load predicates + mov f7=f0 // F clear f7 + ;; + ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr + ld8.fill r1=[r3],16 // M0|1 load r1 +(pUStk) mov r17=1 // A + ;; +(pUStk) st1 [r14]=r17 // M2|3 + ld8.fill r13=[r3],16 // M0|1 + mov f8=f0 // F clear f8 + ;; + ld8.fill r12=[r2] // M0|1 restore r12 (sp) + ld8.fill r15=[r3] // M0|1 restore r15 + mov b6=r18 // I0 restore b6 + + LOAD_PHYS_STACK_REG_SIZE(r17) + mov f9=f0 // F clear f9 +(pKStk) br.cond.dpnt.many skip_rbs_switch // B + + srlz.d // M0 ensure interruption collection is off (for cover) + shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition +#ifdef CONFIG_XEN + XEN_HYPER_COVER; +#else + cover // B add current frame into dirty partition & set cr.ifs +#endif + ;; + mov r19=ar.bsp // M2 get new backing store pointer + mov f10=f0 // F clear f10 + + nop.m 0 + movl r14=__kernel_syscall_via_epc // X + ;; + mov.m ar.csd=r0 // M2 clear ar.csd + mov.m ar.ccv=r0 // M2 clear ar.ccv + mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) + + mov.m ar.ssd=r0 // M2 clear ar.ssd + mov f11=f0 // F clear f11 + br.cond.sptk.many rbs_switch // B +#ifdef CONFIG_XEN +END(xen_leave_syscall) +#else +END(ia64_leave_syscall) +#endif + +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_leave_kernel) + BR_IF_NATIVE(__ia64_leave_kernel, r22, p7) +#else +GLOBAL_ENTRY(ia64_leave_kernel) +#endif + PT_REGS_UNWIND_INFO(0) + /* + * work.need_resched etc. mustn't get changed by this CPU before it returns to + * user- or fsys-mode, hence we disable interrupts early on. + * + * p6 controls whether current_thread_info()->flags needs to be check for + * extra work. We always check for extra work when returning to user-level. + * With CONFIG_PREEMPT, we also check for extra work when the preempt_count + * is 0. After extra work processing has been completed, execution + * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check + * needs to be redone. + */ +#ifdef CONFIG_PREEMPT + rsm psr.i // disable interrupts + cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; + .pred.rel.mutex pUStk,pKStk +(pKStk) ld4 r21=[r20] // r21 <- preempt_count +(pUStk) mov r21=0 // r21 <- 0 + ;; + cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0) +#else +#ifdef CONFIG_XEN +(pUStk) movl r17=XSI_PSR_I_ADDR +(pUStk) mov r31=1 + ;; +(pUStk) ld8 r17=[r17] + ;; +(pUStk) st1 [r17]=r31 + ;; +#else +(pUStk) rsm psr.i +#endif + cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk +#endif +.work_processed_kernel: + adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 + ;; +(p6) ld4 r31=[r17] // load current_thread_info()->flags + adds r21=PT(PR)+16,r12 + ;; + + lfetch [r21],PT(CR_IPSR)-PT(PR) + adds r2=PT(B6)+16,r12 + adds r3=PT(R16)+16,r12 + ;; + lfetch [r21] + ld8 r28=[r2],8 // load b6 + adds r29=PT(R24)+16,r12 + + ld8.fill r16=[r3],PT(AR_CSD)-PT(R16) + adds r30=PT(AR_CCV)+16,r12 +(p6) and r19=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? + ;; + ld8.fill r24=[r29] + ld8 r15=[r30] // load ar.ccv +(p6) cmp4.ne.unc p6,p0=r19, r0 // any special work pending? + ;; + ld8 r29=[r2],16 // load b7 + ld8 r30=[r3],16 // load ar.csd +(p6) br.cond.spnt .work_pending + ;; + ld8 r31=[r2],16 // load ar.ssd + ld8.fill r8=[r3],16 + ;; + ld8.fill r9=[r2],16 + ld8.fill r10=[r3],PT(R17)-PT(R10) + ;; + ld8.fill r11=[r2],PT(R18)-PT(R11) + ld8.fill r17=[r3],16 + ;; + ld8.fill r18=[r2],16 + ld8.fill r19=[r3],16 + ;; + ld8.fill r20=[r2],16 + ld8.fill r21=[r3],16 + mov ar.csd=r30 + mov ar.ssd=r31 + ;; +#ifdef CONFIG_XEN + movl r23=XSI_PSR_I_ADDR + movl r22=XSI_PSR_IC + ;; + ld8 r23=[r23] + mov r25=1 + ;; + st1 [r23]=r25 + st4 [r22]=r0 // note: clears both vpsr.i and vpsr.ic! + ;; +#else + rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection +#endif + invala // invalidate ALAT + ;; + ld8.fill r22=[r2],24 + ld8.fill r23=[r3],24 + mov b6=r28 + ;; + ld8.fill r25=[r2],16 + ld8.fill r26=[r3],16 + mov b7=r29 + ;; + ld8.fill r27=[r2],16 + ld8.fill r28=[r3],16 + ;; + ld8.fill r29=[r2],16 + ld8.fill r30=[r3],24 + ;; + ld8.fill r31=[r2],PT(F9)-PT(R31) + adds r3=PT(F10)-PT(F6),r3 + ;; + ldf.fill f9=[r2],PT(F6)-PT(F9) + ldf.fill f10=[r3],PT(F8)-PT(F10) + ;; + ldf.fill f6=[r2],PT(F7)-PT(F6) + ;; + ldf.fill f7=[r2],PT(F11)-PT(F7) + ldf.fill f8=[r3],32 + ;; + srlz.d // ensure that inter. collection is off (VHPT is don't care, since text is pinned) + mov ar.ccv=r15 + ;; + ldf.fill f11=[r2] +#ifdef CONFIG_XEN + ;; + // r16-r31 all now hold bank1 values + mov r15=ar.unat + movl r2=XSI_BANK1_R16 + movl r3=XSI_BANK1_R16+8 + ;; +.mem.offset 0,0; st8.spill [r2]=r16,16 +.mem.offset 8,0; st8.spill [r3]=r17,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r18,16 +.mem.offset 8,0; st8.spill [r3]=r19,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r20,16 +.mem.offset 8,0; st8.spill [r3]=r21,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r22,16 +.mem.offset 8,0; st8.spill [r3]=r23,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r24,16 +.mem.offset 8,0; st8.spill [r3]=r25,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r26,16 +.mem.offset 8,0; st8.spill [r3]=r27,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r28,16 +.mem.offset 8,0; st8.spill [r3]=r29,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r30,16 +.mem.offset 8,0; st8.spill [r3]=r31,16 + ;; + mov r3=ar.unat + movl r2=XSI_B1NAT + ;; + st8 [r2]=r3 + mov ar.unat=r15 + movl r2=XSI_BANKNUM;; + st4 [r2]=r0; +#else + bsw.0 // switch back to bank 0 (no stop bit required beforehand...) +#endif + ;; +(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency) + adds r16=PT(CR_IPSR)+16,r12 + adds r17=PT(CR_IIP)+16,r12 + +#ifdef CONFIG_XEN +(pKStk) mov r29=r8 +(pKStk) XEN_HYPER_GET_PSR + ;; +(pKStk) mov r22=r8 +(pKStk) mov r8=r29 + ;; +#else +(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled +#endif + nop.i 0 + nop.i 0 + ;; + ld8 r29=[r16],16 // load cr.ipsr + ld8 r28=[r17],16 // load cr.iip + ;; + ld8 r30=[r16],16 // load cr.ifs + ld8 r25=[r17],16 // load ar.unat + ;; + ld8 r26=[r16],16 // load ar.pfs + ld8 r27=[r17],16 // load ar.rsc + cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs + ;; + ld8 r24=[r16],16 // load ar.rnat (may be garbage) + ld8 r23=[r17],16 // load ar.bspstore (may be garbage) + ;; + ld8 r31=[r16],16 // load predicates + ld8 r21=[r17],16 // load b0 + ;; + ld8 r19=[r16],16 // load ar.rsc value for "loadrs" + ld8.fill r1=[r17],16 // load r1 + ;; + ld8.fill r12=[r16],16 + ld8.fill r13=[r17],16 +(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 + ;; + ld8 r20=[r16],16 // ar.fpsr + ld8.fill r15=[r17],16 + ;; + ld8.fill r14=[r16],16 + ld8.fill r2=[r17] +(pUStk) mov r17=1 + ;; + ld8.fill r3=[r16] +(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack + shr.u r18=r19,16 // get byte size of existing "dirty" partition + ;; + mov r16=ar.bsp // get existing backing store pointer + LOAD_PHYS_STACK_REG_SIZE(r17) +(pKStk) br.cond.dpnt skip_rbs_switch + + /* + * Restore user backing store. + * + * NOTE: alloc, loadrs, and cover can't be predicated. + */ +(pNonSys) br.cond.dpnt dont_preserve_current_frame + +#ifdef CONFIG_XEN + XEN_HYPER_COVER; +#else + cover // add current frame into dirty partition and set cr.ifs +#endif + ;; + mov r19=ar.bsp // get new backing store pointer +rbs_switch: + sub r16=r16,r18 // krbs = old bsp - size of dirty partition + cmp.ne p9,p0=r0,r0 // clear p9 to skip restore of cr.ifs + ;; + sub r19=r19,r16 // calculate total byte size of dirty partition + add r18=64,r18 // don't force in0-in7 into memory... + ;; + shl r19=r19,16 // shift size of dirty partition into loadrs position + ;; +dont_preserve_current_frame: + /* + * To prevent leaking bits between the kernel and user-space, + * we must clear the stacked registers in the "invalid" partition here. + * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium, + * 5 registers/cycle on McKinley). + */ +# define pRecurse p6 +# define pReturn p7 +#ifdef CONFIG_ITANIUM +# define Nregs 10 +#else +# define Nregs 14 +#endif + alloc loc0=ar.pfs,2,Nregs-2,2,0 + shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8)) + sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize + ;; + mov ar.rsc=r19 // load ar.rsc to be used for "loadrs" + shladd in0=loc1,3,r17 + mov in1=0 + ;; + TEXT_ALIGN(32) +rse_clear_invalid: +#ifdef CONFIG_ITANIUM + // cycle 0 + { .mii + alloc loc0=ar.pfs,2,Nregs-2,2,0 + cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse + add out0=-Nregs*8,in0 +}{ .mfb + add out1=1,in1 // increment recursion count + nop.f 0 + nop.b 0 // can't do br.call here because of alloc (WAW on CFM) + ;; +}{ .mfi // cycle 1 + mov loc1=0 + nop.f 0 + mov loc2=0 +}{ .mib + mov loc3=0 + mov loc4=0 +(pRecurse) br.call.sptk.many b0=rse_clear_invalid + +}{ .mfi // cycle 2 + mov loc5=0 + nop.f 0 + cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret +}{ .mib + mov loc6=0 + mov loc7=0 +(pReturn) br.ret.sptk.many b0 +} +#else /* !CONFIG_ITANIUM */ + alloc loc0=ar.pfs,2,Nregs-2,2,0 + cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse + add out0=-Nregs*8,in0 + add out1=1,in1 // increment recursion count + mov loc1=0 + mov loc2=0 + ;; + mov loc3=0 + mov loc4=0 + mov loc5=0 + mov loc6=0 + mov loc7=0 +(pRecurse) br.call.dptk.few b0=rse_clear_invalid + ;; + mov loc8=0 + mov loc9=0 + cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret + mov loc10=0 + mov loc11=0 +(pReturn) br.ret.dptk.many b0 +#endif /* !CONFIG_ITANIUM */ +# undef pRecurse +# undef pReturn + ;; + alloc r17=ar.pfs,0,0,0,0 // drop current register frame + ;; + loadrs + ;; +skip_rbs_switch: + mov ar.unat=r25 // M2 +(pKStk) extr.u r22=r22,21,1 // I0 extract current value of psr.pp from r22 +(pLvSys)mov r19=r0 // A clear r19 for leave_syscall, no-op otherwise + ;; +(pUStk) mov ar.bspstore=r23 // M2 +(pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp +(pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise + ;; +#ifdef CONFIG_XEN + movl r25=XSI_IPSR + ;; + st8[r25]=r29,XSI_IFS_OFS-XSI_IPSR_OFS + ;; +#else + mov cr.ipsr=r29 // M2 +#endif + mov ar.pfs=r26 // I0 +(pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise + +#ifdef CONFIG_XEN +(p9) st8 [r25]=r30 + ;; + adds r25=XSI_IIP_OFS-XSI_IFS_OFS,r25 + ;; +#else +(p9) mov cr.ifs=r30 // M2 +#endif + mov b0=r21 // I0 +(pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise + + mov ar.fpsr=r20 // M2 +#ifdef CONFIG_XEN + st8 [r25]=r28 +#else + mov cr.iip=r28 // M2 +#endif + nop 0 + ;; +(pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode + nop 0 +(pLvSys)mov r2=r0 + + mov ar.rsc=r27 // M2 + mov pr=r31,-1 // I0 +#ifdef CONFIG_XEN + ;; + XEN_HYPER_RFI; +#else + rfi // B +#endif + + /* + * On entry: + * r20 = ¤t->thread_info->pre_count (if CONFIG_PREEMPT) + * r31 = current->thread_info->flags + * On exit: + * p6 = TRUE if work-pending-check needs to be redone + */ +.work_pending_syscall: + add r2=-8,r2 + add r3=-8,r3 + ;; + st8 [r2]=r8 + st8 [r3]=r10 +.work_pending: + tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? +(p6) br.cond.sptk.few .notify +#ifdef CONFIG_PREEMPT +(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 + ;; +(pKStk) st4 [r20]=r21 + ssm psr.i // enable interrupts +#endif + br.call.spnt.many rp=schedule +.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 +#ifdef CONFIG_XEN + movl r2=XSI_PSR_I_ADDR + mov r20=1 + ;; + ld8 r2=[r2] + ;; + st1 [r2]=r20 +#else + rsm psr.i // disable interrupts +#endif + ;; +#ifdef CONFIG_PREEMPT +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; +(pKStk) st4 [r20]=r0 // preempt_count() <- 0 +#endif +(pLvSys)br.cond.sptk.few .work_pending_syscall_end + br.cond.sptk.many .work_processed_kernel // re-check + +.notify: +(pUStk) br.call.spnt.many rp=notify_resume_user +.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 +(pLvSys)br.cond.sptk.few .work_pending_syscall_end + br.cond.sptk.many .work_processed_kernel // don't re-check + +.work_pending_syscall_end: + adds r2=PT(R8)+16,r12 + adds r3=PT(R10)+16,r12 + ;; + ld8 r8=[r2] + ld8 r10=[r3] +#ifdef CONFIG_XEN + br.cond.sptk.many xen_work_processed_syscall // re-check +#else + br.cond.sptk.many .work_processed_syscall // re-check +#endif + +#ifdef CONFIG_XEN +END(xen_leave_kernel) +#else +END(ia64_leave_kernel) +#endif diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h index dd3e5ec..c8a5a0d 100644 --- a/include/asm-ia64/xen/privop.h +++ b/include/asm-ia64/xen/privop.h @@ -70,4 +70,26 @@ #define XSI_IHA (XSI_BASE + XSI_IHA_OFS) #endif +/* these routines utilize privilege-sensitive or performance-sensitive + * privileged instructions so the code must be replaced with + * paravirtualized versions */ +#ifndef CONFIG_PARAVIRT_ENTRY +#define IA64_PARAVIRTUALIZED_ENTRY +#define ia64_switch_to xen_switch_to +#define ia64_leave_syscall xen_leave_syscall +#define ia64_work_processed_syscall xen_work_processed_syscall_with_check +#define ia64_leave_kernel xen_leave_kernel +#endif /* !CONFIG_PARAVIRT_ENTRY */ + +#ifdef CONFIG_XEN +#ifdef __ASSEMBLY__ +#define BR_IF_NATIVE(target, reg, pred) \ + .body ; \ + movl reg=running_on_xen;; ; \ + ld4 reg=[reg];; ; \ + cmp.eq pred,p0=reg,r0 ; \ + (pred) br.cond.sptk.many target;; +#endif /* __ASSEMBLY__ */ +#endif + #endif /* _ASM_IA64_XEN_PRIVOP_H */ -- 1.5.3 |
From: Isaku Y. <yam...@va...> - 2008-02-22 03:57:42
|
On Thu, Feb 21, 2008 at 03:11:04PM -0800, Jeremy Fitzhardinge wrote: > yam...@va... wrote: > >diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c > >index 17fda52..1bb0362 100644 > >--- a/arch/ia64/kernel/time.c > >+++ b/arch/ia64/kernel/time.c > >@@ -29,6 +29,14 @@ > > #include <asm/sections.h> > > #include <asm/system.h> > > > >+#include <asm/xen/hypervisor.h> > >+#ifdef CONFIG_XEN > >+#include <linux/kernel_stat.h> > >+#include <linux/posix-timers.h> > >+#include <xen/interface/vcpu.h> > >+#include <asm/percpu.h> > >+#endif > >+ > > ia64 doesn't use clocksources yet? Couldn't you share a lot of this > with the 32-bit Xen time code (esp stolen time accounting)? It does. I'll look into sharing code. (Probably after cpu paravirtualization) -- yamahata |
From: Isaku Y. <yam...@va...> - 2008-02-22 03:54:57
|
On Thu, Feb 21, 2008 at 03:47:10PM -0800, Jeremy Fitzhardinge wrote: > yam...@va... wrote: > >+static inline unsigned long > >+HYPERVISOR_machtophys(unsigned long mfn) > >+{ > >+ unsigned long ret = mfn; > >+ if (is_running_on_xen()) > > > > Do you often call hypercalls when not booting under Xen? It seems to me > this check should have already been done at a higher layer, and it > needn't be repeated here. IA64 pv_ops frame work doesn't exist yet so that xen code does in order to boot on both native and xen for now. I expect those check will be eliminated during developing ia64 pv_ops. -- yamahata |
From: Jeremy F. <je...@go...> - 2008-02-21 23:49:28
|
yam...@va... wrote: > +static inline unsigned long > +HYPERVISOR_machtophys(unsigned long mfn) > +{ > + unsigned long ret = mfn; > + if (is_running_on_xen()) > Do you often call hypercalls when not booting under Xen? It seems to me this check should have already been done at a higher layer, and it needn't be repeated here. > + ret = __HYPERVISOR_machtophys(mfn); > + return ret; > +} J |
From: Jeremy F. <je...@go...> - 2008-02-21 23:48:04
|
yam...@va... wrote: > diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h > index 4999a6c..effd2af 100644 > --- a/include/asm-ia64/page.h > +++ b/include/asm-ia64/page.h > @@ -227,4 +227,15 @@ get_order (unsigned long size) > (((current->personality & READ_IMPLIES_EXEC) != 0) \ > ? VM_EXEC : 0)) > > +#ifndef __ASSEMBLY__ > + > +#include <linux/kernel.h> > Why? asm-ia64/xen/page.h already includes this. > + > +#ifdef CONFIG_XEN > + > +#include <asm/xen/page.h> > This shouldn't be necessary; anyone wanting Xen-specific definitions should explicitly include <xen/page.h>. > + > +#endif /* CONFIG_XEN */ > +#endif /* __ASSEMBLY__ */ > + > #endif /* _ASM_IA64_PAGE_H */ > diff --git a/include/asm-ia64/xen/page.h b/include/asm-ia64/xen/page.h > new file mode 100644 > index 0000000..9ab8148 > --- /dev/null > +++ b/include/asm-ia64/xen/page.h > @@ -0,0 +1,19 @@ > +#ifndef _ASM_IA64_MADDR_H > +#define _ASM_IA64_MADDR_H > + > +#include <linux/kernel.h> > +#include <asm/xen/hypervisor.h> > +#include <asm/xen/hypercall.h> > +#include <xen/features.h> > +#include <xen/interface/xen.h> > + > +#define mfn_to_pfn(mfn) (mfn) > +#define pfn_to_mfn(pfn) (pfn) > + > +#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) > +#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) > +#define virt_to_machine(virt) __pa(virt) /* for tpmfront.c */ > + > +#define set_phys_to_machine(pfn, mfn) do { } while (0) > Probably worth turning these into inlines so that they get properly typechecked. Especially things like set_phys_to_machine(), which doesn't use its arguments. J |
From: Jeremy F. <je...@go...> - 2008-02-21 23:26:12
|
yam...@va... wrote: > diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c > index 0b52f19..b5dcb49 100644 > --- a/arch/ia64/kernel/irq_ia64.c > +++ b/arch/ia64/kernel/irq_ia64.c > @@ -30,6 +30,9 @@ > #include <linux/threads.h> > #include <linux/bitops.h> > #include <linux/irq.h> > +#ifdef CONFIG_XEN > +#include <linux/cpu.h> > +#endif > > #include <asm/delay.h> > #include <asm/intrinsics.h> > @@ -204,6 +207,13 @@ assign_irq_vector (int irq) > > vector = -ENOSPC; > > +#ifdef CONFIG_XEN > + if (is_running_on_xen()) { > + extern int xen_assign_irq_vector(int); > + return xen_assign_irq_vector(irq); > + } > +#endif > No extern prototypes in .c files; definitely not nested in block scope (here and elsewhere in the series). > +static char timer_name[NR_CPUS][15]; > +static char ipi_name[NR_CPUS][15]; > +static char resched_name[NR_CPUS][15]; > +static char cmc_name[NR_CPUS][15]; > +static char cmcp_name[NR_CPUS][15]; > +static char cpep_name[NR_CPUS][15]; Why not use percpu? > +/* FIXME: There's no obvious point to check whether slab is ready. So > + * a hack is used here by utilizing a late time hook. > + */ Could you hook onto paravirt_post_allocator_init()? J |
From: Jeremy F. <je...@go...> - 2008-02-21 23:14:01
|
yam...@va... wrote: > diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c > index 17fda52..1bb0362 100644 > --- a/arch/ia64/kernel/time.c > +++ b/arch/ia64/kernel/time.c > @@ -29,6 +29,14 @@ > #include <asm/sections.h> > #include <asm/system.h> > > +#include <asm/xen/hypervisor.h> > +#ifdef CONFIG_XEN > +#include <linux/kernel_stat.h> > +#include <linux/posix-timers.h> > +#include <xen/interface/vcpu.h> > +#include <asm/percpu.h> > +#endif > + ia64 doesn't use clocksources yet? Couldn't you share a lot of this with the 32-bit Xen time code (esp stolen time accounting)? J |
From: Jeremy F. <je...@go...> - 2008-02-21 23:11:13
|
yam...@va... wrote: > diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c > index 78f28d8..9c17a46 100644 > --- a/arch/ia64/kernel/acpi.c > +++ b/arch/ia64/kernel/acpi.c > @@ -118,6 +118,10 @@ acpi_get_sysname(void) > return "hpzx1"; > } else if (!strcmp(hdr->oem_id, "SGI")) { > return "sn2"; > +#ifdef CONFIG_XEN > + } else if (is_running_on_xen() && !strcmp(hdr->oem_id, "XEN")) { > + return "xen"; > +#endif > } Is the #ifdef necessary? Couldn't you make is_running_on_xen() just evaluate to 0 in the non-Xen case? J |
From: <yam...@va...> - 2008-02-21 22:31:58
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/Kconfig | 72 +++++++++++++ arch/ia64/kernel/Makefile | 5 + arch/ia64/kernel/paravirt_alt.c | 118 ++++++++++++++++++++++ arch/ia64/kernel/paravirt_core.c | 201 +++++++++++++++++++++++++++++++++++++ arch/ia64/kernel/paravirt_entry.c | 99 ++++++++++++++++++ arch/ia64/kernel/paravirt_nop.c | 49 +++++++++ arch/ia64/kernel/vmlinux.lds.S | 35 +++++++ include/asm-ia64/module.h | 6 + include/asm-ia64/paravirt_alt.h | 82 +++++++++++++++ include/asm-ia64/paravirt_core.h | 54 ++++++++++ include/asm-ia64/paravirt_entry.h | 62 +++++++++++ include/asm-ia64/paravirt_nop.h | 46 +++++++++ 12 files changed, 829 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kernel/paravirt_alt.c create mode 100644 arch/ia64/kernel/paravirt_core.c create mode 100644 arch/ia64/kernel/paravirt_entry.c create mode 100644 arch/ia64/kernel/paravirt_nop.c create mode 100644 include/asm-ia64/paravirt_alt.h create mode 100644 include/asm-ia64/paravirt_core.h create mode 100644 include/asm-ia64/paravirt_entry.h create mode 100644 include/asm-ia64/paravirt_nop.h diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index dff9edf..bc84008 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -110,6 +110,78 @@ config AUDIT_ARCH bool default y +menuconfig PARAVIRT_GUEST + bool "Paravirtualized guest support" + help + Say Y here to get to see options related to running Linux under + various hypervisors. This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and disabled. + +if PARAVIRT_GUEST + +config PARAVIRT + bool + default y + help + This changes the kernel so it can modify itself when it is run + under a hypervisor, potentially improving performance significantly + over full virtualization. However, when run without a hypervisor + the kernel is theoretically slower and slightly larger. + +config PARAVIRT_ALT + bool "paravirt_alt binary patching infrastructure" + depends on PARAVIRT + default y + help + The binary patching infratstructure to replace some privileged + instructions with hypervisor specific instrutions. + There are several sensitive(i.e. non-virtualizable) instructions and + performance critical privileged instructions which Xen + paravirtualize as hyperprivops. + For transparent paravirtualization (i.e. single binary should run + on both baremetal and xen environment), xenLinux/IA64 needs + something like "if (is_running_on_xen()) {} else {}" where + is_running_on_xen() is determined at boot time. + This configuration tries to eliminate the overheads for hyperprivops + by annotating such instructions and replacing them with hyperprivops + at boot time. + +config PARAVIRT_ENTRY + bool "paravirt entry" + depends on PARAVIRT + default y + help + The entry point hooking infrastructure to change the execution path + at the boot time. + There are several paravirtualized paths in hand coded assembly code + which isn't binary patched easily by the paravirt_alt infrastructure. + E.g. ia64_switch_to, ia64_leave_syscall, ia64_leave_kernel and + ia64_pal_call_static. + For those hand written assembly code, change the execution path + by hooking them and jumping to hand paravirtualized code. + +config PARAVIRT_NOP_B_PATCH + bool "paravirt branch if native" + depends on PARAVIRT + default y + help + paravirt branch if native + There are several paravirtualized paths in hand coded assembly code. + For transparent paravirtualization, there are codes like + GLOBAL_ENTRY(xen_xxx) + 'movl reg=running_on_xen;;' + 'ld4 reg=[reg];;' + 'cmp.e1 pred,p0=reg,r0' + '(pred) br.cond.sptk.many <native_xxx>;;' + To reduce overhead when running on bare metal, just + "br.cond.sptk.many <native_xxx>" and replace it with 'nop.b 0' + when running on xen. + +#source "arch/ia64/xen/Kconfig" + +endif + choice prompt "System type" default IA64_GENERIC diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 33e5a59..d0e22bb 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -36,6 +36,11 @@ obj-$(CONFIG_PCI_MSI) += msi_ia64.o mca_recovery-y += mca_drv.o mca_drv_asm.o obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o +obj-$(CONFIG_PARAVIRT) += paravirt_core.o +obj-$(CONFIG_PARAVIRT_ALT) += paravirt_alt.o +obj-$(CONFIG_PARAVIRT_ENTRY) += paravirt_entry.o paravirtentry.o +obj-$(CONFIG_PARAVIRT_NOP_B_PATCH) += paravirt_nop.o + obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) obj-y += esi_stub.o # must be in kernel proper diff --git a/arch/ia64/kernel/paravirt_alt.c b/arch/ia64/kernel/paravirt_alt.c new file mode 100644 index 0000000..d0a34a7 --- /dev/null +++ b/arch/ia64/kernel/paravirt_alt.c @@ -0,0 +1,118 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirt_alt.c + * + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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 <asm/paravirt_core.h> + +extern const char nop_bundle[]; +extern const unsigned long nop_bundle_size; + +static void __init_or_module +fill_nop(void *sbundle, void *ebundle) +{ + void *bundle = sbundle; + BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0); + BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0); + + while (bundle < ebundle) { + memcpy(bundle, nop_bundle, nop_bundle_size); + + bundle += nop_bundle_size; + } +} + +void __init_or_module +paravirt_alt_bundle_patch_apply(struct paravirt_alt_bundle_patch *start, + struct paravirt_alt_bundle_patch *end, + unsigned long(*patch)(void *sbundle, + void *ebundle, + unsigned long type)) +{ + struct paravirt_alt_bundle_patch *p; + + for (p = start; p < end; p++) { + unsigned long used; + + used = (*patch)(p->sbundle, p->ebundle, p->type); + if (used == 0) + continue; + + fill_nop(p->sbundle + used, p->ebundle); + paravirt_flush_i_cache_range(p->sbundle, + p->ebundle - p->sbundle); + } + ia64_sync_i(); + ia64_srlz_i(); +} + +/* + * nop.i, nop.m, nop.f instruction are same format. + * but nop.b has differennt format. + * This doesn't support nop.b for now. + */ +static void __init_or_module +fill_nop_inst(unsigned long stag, unsigned long etag) +{ + extern const bundle_t nop_mfi_inst_bundle[]; + unsigned long tag; + const cmp_inst_t nop_inst = paravirt_read_slot0(nop_mfi_inst_bundle); + + for (tag = stag; tag < etag; tag = paravirt_get_next_tag(tag)) + paravirt_write_inst(tag, nop_inst); +} + +void __init_or_module +paravirt_alt_inst_patch_apply(struct paravirt_alt_inst_patch *start, + struct paravirt_alt_inst_patch *end, + unsigned long (*patch)(unsigned long stag, + unsigned long etag, + unsigned long type)) +{ + struct paravirt_alt_inst_patch *p; + + for (p = start; p < end; p++) { + unsigned long tag; + bundle_t *sbundle; + bundle_t *ebundle; + + tag = (*patch)(p->stag, p->etag, p->type); + if (tag == p->stag) + continue; + + fill_nop_inst(tag, p->etag); + sbundle = paravirt_get_bundle(p->stag); + ebundle = paravirt_get_bundle(p->etag) + 1; + paravirt_flush_i_cache_range(sbundle, (ebundle - sbundle) * + sizeof(bundle_t)); + } + 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 --git a/arch/ia64/kernel/paravirt_core.c b/arch/ia64/kernel/paravirt_core.c new file mode 100644 index 0000000..6b7c70f --- /dev/null +++ b/arch/ia64/kernel/paravirt_core.c @@ -0,0 +1,201 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirt_core.c + * + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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 <asm/paravirt_core.h> + +/* + * 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. + */ +void __init_or_module +paravirt_flush_i_cache_range(const void *instr, unsigned long size) +{ + unsigned long i; + + for (i = 0; i < size; i += sizeof(bundle_t)) + asm volatile ("fc.i %0":: "r"(instr + i): "memory"); +} + +bundle_t* __init_or_module +paravirt_get_bundle(unsigned long tag) +{ + return (bundle_t *)(tag & ~3UL); +} + +unsigned long __init_or_module +paravirt_get_slot(unsigned long tag) +{ + return tag & 3UL; +} + +#if 0 +unsigned long __init_or_module +paravirt_get_num_inst(unsigned long stag, unsigned long etag) +{ + bundle_t *sbundle = paravirt_get_bundle(stag); + unsigned long sslot = paravirt_get_slot(stag); + bundle_t *ebundle = paravirt_get_bundle(etag); + unsigned long eslot = paravirt_get_slot(etag); + + return (ebundle - sbundle) * 3 + eslot - sslot + 1; +} +#endif + +unsigned long __init_or_module +paravirt_get_next_tag(unsigned long tag) +{ + unsigned long slot = paravirt_get_slot(tag); + + switch (slot) { + case 0: + case 1: + return tag + 1; + case 2: { + bundle_t *bundle = paravirt_get_bundle(tag); + return (unsigned long)(bundle + 1); + } + default: + BUG(); + } + /* NOTREACHED */ +} + +cmp_inst_t __init_or_module +paravirt_read_slot0(const bundle_t *bundle) +{ + cmp_inst_t inst; + inst.l = bundle->quad0.slot0; + return inst; +} + +cmp_inst_t __init_or_module +paravirt_read_slot1(const bundle_t *bundle) +{ + cmp_inst_t inst; + inst.l = bundle->quad0.slot1_p0 | + ((unsigned long long)bundle->quad1.slot1_p1 << 18UL); + return inst; +} + +cmp_inst_t __init_or_module +paravirt_read_slot2(const bundle_t *bundle) +{ + cmp_inst_t inst; + inst.l = bundle->quad1.slot2; + return inst; +} + +cmp_inst_t __init_or_module +paravirt_read_inst(unsigned long tag) +{ + bundle_t *bundle = paravirt_get_bundle(tag); + unsigned long slot = paravirt_get_slot(tag); + + switch (slot) { + case 0: + return paravirt_read_slot0(bundle); + case 1: + return paravirt_read_slot1(bundle); + case 2: + return paravirt_read_slot2(bundle); + default: + BUG(); + } + /* NOTREACHED */ +} + +void __init_or_module +paravirt_write_slot0(bundle_t *bundle, cmp_inst_t inst) +{ + bundle->quad0.slot0 = inst.l; +} + +void __init_or_module +paravirt_write_slot1(bundle_t *bundle, cmp_inst_t inst) +{ + bundle->quad0.slot1_p0 = inst.l; + bundle->quad1.slot1_p1 = inst.l >> 18UL; +} + +void __init_or_module +paravirt_write_slot2(bundle_t *bundle, cmp_inst_t inst) +{ + bundle->quad1.slot2 = inst.l; +} + +void __init_or_module +paravirt_write_inst(unsigned long tag, cmp_inst_t inst) +{ + bundle_t *bundle = paravirt_get_bundle(tag); + unsigned long slot = paravirt_get_slot(tag); + + switch (slot) { + case 0: + paravirt_write_slot0(bundle, inst); + break; + case 1: + paravirt_write_slot1(bundle, inst); + break; + case 2: + paravirt_write_slot2(bundle, inst); + break; + default: + BUG(); + } + paravirt_flush_i_cache_range(bundle, sizeof(*bundle)); +} + +/* for debug */ +void +print_bundle(const bundle_t *bundle) +{ + const unsigned long *quad = (const unsigned long *)bundle; + cmp_inst_t slot0 = paravirt_read_slot0(bundle); + cmp_inst_t slot1 = paravirt_read_slot1(bundle); + cmp_inst_t slot2 = paravirt_read_slot2(bundle); + + printk(KERN_DEBUG + "bundle 0x%p 0x%016lx 0x%016lx\n", bundle, quad[0], quad[1]); + printk(KERN_DEBUG + "bundle template 0x%x\n", + bundle->quad0.template); + printk(KERN_DEBUG + "slot0 0x%lx slot1_p0 0x%lx slot1_p1 0x%lx slot2 0x%lx\n", + (unsigned long)bundle->quad0.slot0, + (unsigned long)bundle->quad0.slot1_p0, + (unsigned long)bundle->quad1.slot1_p1, + (unsigned long)bundle->quad1.slot2); + printk(KERN_DEBUG + "slot0 0x%016llx slot1 0x%016llx slot2 0x%016llx\n", + slot0.l, slot1.l, slot2.l); +} + +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/arch/ia64/kernel/paravirt_entry.c b/arch/ia64/kernel/paravirt_entry.c new file mode 100644 index 0000000..708287a --- /dev/null +++ b/arch/ia64/kernel/paravirt_entry.c @@ -0,0 +1,99 @@ +/****************************************************************************** + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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 <asm/paravirt_core.h> +#include <asm/paravirt_entry.h> + +/* br.cond.sptk.many <target25> B1 */ +typedef union inst_b1 { + cmp_inst_t inst; + struct { + unsigned long qp: 6; + unsigned long btype: 3; + unsigned long unused: 3; + unsigned long p: 1; + unsigned long imm20b: 20; + unsigned long wh: 2; + unsigned long d: 1; + unsigned long s: 1; + unsigned long opcode: 4; + }; + unsigned long l; +} inst_b1_t; + +static void __init +__paravirt_entry_apply(unsigned long tag, const void *target) +{ + bundle_t *bundle = paravirt_get_bundle(tag); + cmp_inst_t inst = paravirt_read_inst(tag); + unsigned long target25 = (unsigned long)target - (unsigned long)bundle; + inst_b1_t inst_b1; + + inst_b1.l = inst.l; + if (target25 & (1UL << 63)) + inst_b1.s = 1; + else + inst_b1.s = 0; + + inst_b1.imm20b = target25 >> 4; + inst.l = inst_b1.l; + + paravirt_write_inst(tag, inst); + paravirt_flush_i_cache_range(bundle, sizeof(*bundle)); +} + +static void __init +paravirt_entry_apply(const struct paravirt_entry_patch *entry_patch, + const struct paravirt_entry *entries, + unsigned int nr_entries) +{ + unsigned int i; + for (i = 0; i < nr_entries; i++) { + if (entry_patch->type == entries[i].type) { + __paravirt_entry_apply(entry_patch->tag, + entries[i].entry); + break; + } + } +} + +void __init +paravirt_entry_patch_apply(const struct paravirt_entry_patch *start, + const struct paravirt_entry_patch *end, + const struct paravirt_entry *entries, + unsigned int nr_entries) +{ + const struct paravirt_entry_patch *p; + for (p = start; p < end; p++) + paravirt_entry_apply(p, entries, nr_entries); + + 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 --git a/arch/ia64/kernel/paravirt_nop.c b/arch/ia64/kernel/paravirt_nop.c new file mode 100644 index 0000000..ee5a204 --- /dev/null +++ b/arch/ia64/kernel/paravirt_nop.c @@ -0,0 +1,49 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirt_nop.c + * + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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 <asm/paravirt_core.h> +#include <asm/paravirt_nop.h> + +void __init_or_module +paravirt_nop_b_patch_apply(const struct paravirt_nop_patch *start, + const struct paravirt_nop_patch *end) +{ + extern const bundle_t nop_b_inst_bundle; + const cmp_inst_t nop_b_inst = paravirt_read_slot0(&nop_b_inst_bundle); + const struct paravirt_nop_patch *p; + + for (p = start; p < end; p++) + paravirt_write_inst(p->tag, nop_b_inst); + + 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 --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 80622ac..0cbe0a1 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -163,6 +163,41 @@ SECTIONS __end___mckinley_e9_bundles = .; } +#if defined(CONFIG_PARAVIRT_ALT) + . = ALIGN(16); + .paravirt_bundles : AT(ADDR(.paravirt_bundles) - LOAD_OFFSET) + { + __start_paravirt_bundles = .; + *(.paravirt_bundles) + __stop_paravirt_bundles = .; + } + . = ALIGN(16); + .paravirt_insts : AT(ADDR(.paravirt_insts) - LOAD_OFFSET) + { + __start_paravirt_insts = .; + *(.paravirt_insts) + __stop_paravirt_insts = .; + } +#endif +#if defined(CONFIG_PARAVIRT_NOP_B_PATCH) + . = ALIGN(16); + .paravirt_nop_b : AT(ADDR(.paravirt_nop_b) - LOAD_OFFSET) + { + __start_paravirt_nop_b = .; + *(.paravirt_nop_b) + __stop_paravirt_nop_b = .; + } +#endif +#if defined(CONFIG_PARAVIRT_ENTRY) + . = ALIGN(16); + .paravirt_entry : AT(ADDR(.paravirt_entry) - LOAD_OFFSET) + { + __start_paravirt_entry = .; + *(.paravirt_entry) + __stop_paravirt_entry = .; + } +#endif + #if defined(CONFIG_IA64_GENERIC) /* Machine Vector */ . = ALIGN(16); diff --git a/include/asm-ia64/module.h b/include/asm-ia64/module.h index d2da61e..44f63ff 100644 --- a/include/asm-ia64/module.h +++ b/include/asm-ia64/module.h @@ -16,6 +16,12 @@ struct mod_arch_specific { struct elf64_shdr *got; /* global offset table */ struct elf64_shdr *opd; /* official procedure descriptors */ struct elf64_shdr *unwind; /* unwind-table section */ +#ifdef CONFIG_PARAVIRT_ALT + struct elf64_shdr *paravirt_bundles; + /* paravirt_alt_bundle_patch table */ + struct elf64_shdr *paravirt_insts; + /* paravirt_alt_inst_patch table */ +#endif unsigned long gp; /* global-pointer for module */ void *core_unw_table; /* core unwind-table cookie returned by unwinder */ diff --git a/include/asm-ia64/paravirt_alt.h b/include/asm-ia64/paravirt_alt.h new file mode 100644 index 0000000..34c5473 --- /dev/null +++ b/include/asm-ia64/paravirt_alt.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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_ALT_H +#define __ASM_PARAVIRT_ALT_H + +#ifndef __ASSEMBLER__ +/* for binary patch */ +struct paravirt_alt_bundle_patch { + void *sbundle; + void *ebundle; + unsigned long type; +}; + +/* label means the beginning of new bundle */ +#define paravirt_alt_bundle(instr, privop) \ + "\t1:\n" \ + "\t" instr "\n" \ + "\t2:\n" \ + "\t.section .paravirt_bundles, \"a\"\n" \ + "\t.previous\n" \ + "\t.xdata8 \".paravirt_bundles\", 1b, 2b, " \ + __stringify(privop) "\n" + +struct paravirt_alt_inst_patch { + unsigned long stag; + unsigned long etag; + unsigned long type; +}; + +#define paravirt_alt_inst(instr, privop) \ + "\t[1:]\n" \ + "\t" instr "\n" \ + "\t[2:]\n" \ + "\t.section .paravirt_insts, \"a\"\n" \ + "\t.previous\n" \ + "\t.xdata8 \".paravirt_insts\", 1b, 2b, " \ + __stringify(privop) "\n" + +void +paravirt_alt_bundle_patch_apply(struct paravirt_alt_bundle_patch *start, + struct paravirt_alt_bundle_patch *end, + unsigned long(*patch)(void *sbundle, + void *ebundle, + unsigned long type)); + +void +paravirt_alt_inst_patch_apply(struct paravirt_alt_inst_patch *start, + struct paravirt_alt_inst_patch *end, + unsigned long (*patch)(unsigned long stag, + unsigned long etag, + unsigned long type)); +#endif /* __ASSEMBLER__ */ + +#endif /* __ASM_PARAVIRT_ALT_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/include/asm-ia64/paravirt_core.h b/include/asm-ia64/paravirt_core.h new file mode 100644 index 0000000..9979740 --- /dev/null +++ b/include/asm-ia64/paravirt_core.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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_CORE_H +#define __ASM_PARAVIRT_CORE_H + +#include <asm/kprobes.h> + +void paravirt_flush_i_cache_range(const void *instr, unsigned long size); + +bundle_t *paravirt_get_bundle(unsigned long tag); +unsigned long paravirt_get_slot(unsigned long tag); +unsigned long paravirt_get_next_tag(unsigned long tag); + +cmp_inst_t paravirt_read_slot0(const bundle_t *bundle); +cmp_inst_t paravirt_read_slot1(const bundle_t *bundle); +cmp_inst_t paravirt_read_slot2(const bundle_t *bundle); +cmp_inst_t paravirt_read_inst(unsigned long tag); + +void paravirt_write_slot0(bundle_t *bundle, cmp_inst_t inst); +void paravirt_write_slot1(bundle_t *bundle, cmp_inst_t inst); +void paravirt_write_slot2(bundle_t *bundle, cmp_inst_t inst); +void paravirt_write_inst(unsigned long tag, cmp_inst_t inst); + +void print_bundle(const bundle_t *bundle); + +#endif /* __ASM_PARAVIRT_CORE_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/include/asm-ia64/paravirt_entry.h b/include/asm-ia64/paravirt_entry.h new file mode 100644 index 0000000..857fd37 --- /dev/null +++ b/include/asm-ia64/paravirt_entry.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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_ENTRY_H +#define __ASM_PARAVIRT_ENTRY_H + +#ifdef __ASSEMBLY__ + +#define BR_COND_SPTK_MANY(target, type) \ + [1:] ; \ + br.cond.sptk.many target;; ; \ + .section .paravirt_entry, "a" ; \ + .previous ; \ + .xdata8 ".paravirt_entry", 1b, type + +#else /* __ASSEMBLY__ */ + +struct paravirt_entry_patch { + unsigned long tag; + unsigned long type; +}; + +struct paravirt_entry { + void *entry; + unsigned long type; +}; + +void +paravirt_entry_patch_apply(const struct paravirt_entry_patch *start, + const struct paravirt_entry_patch *end, + const struct paravirt_entry *entries, + unsigned int nr_entries); + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_PARAVIRT_ENTRY_H */ +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/include/asm-ia64/paravirt_nop.h b/include/asm-ia64/paravirt_nop.h new file mode 100644 index 0000000..2b05430 --- /dev/null +++ b/include/asm-ia64/paravirt_nop.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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_OPS_H +#define __ASM_PARAVIRT_OPS_H + +#ifndef __ASSEMBLY__ + +struct paravirt_nop_patch { + unsigned long tag; +}; + +void +paravirt_nop_b_patch_apply(const struct paravirt_nop_patch *start, + const struct paravirt_nop_patch *end); + +#endif /* !__ASSEMBLEY__ */ + +#endif /* __ASM_PARAVIRT_OPS_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:58
|
import ia64 specific part of xencomm which converts hypercall argument in virtual address into pseudo physical address (guest physical address). Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/xen/xcom_asm.S | 27 +++ arch/ia64/xen/xcom_hcall.c | 458 +++++++++++++++++++++++++++++++++++++ arch/ia64/xen/xencomm.c | 108 +++++++++ include/asm-ia64/xen/xcom_hcall.h | 55 +++++ include/asm-ia64/xen/xencomm.h | 33 +++ 5 files changed, 681 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/xen/xcom_asm.S create mode 100644 arch/ia64/xen/xcom_hcall.c create mode 100644 arch/ia64/xen/xencomm.c create mode 100644 include/asm-ia64/xen/xcom_hcall.h create mode 100644 include/asm-ia64/xen/xencomm.h diff --git a/arch/ia64/xen/xcom_asm.S b/arch/ia64/xen/xcom_asm.S new file mode 100644 index 0000000..8747908 --- /dev/null +++ b/arch/ia64/xen/xcom_asm.S @@ -0,0 +1,27 @@ +/* + * xencomm suspend support + * Support routines for Xen + * + * Copyright (C) 2005 Dan Magenheimer <dan...@hp...> + */ +#include <asm/asmmacro.h> +#include <xen/interface/xen.h> + +/* + * Stub for suspend. + * Just force the stacked registers to be written in memory. + */ +GLOBAL_ENTRY(xencomm_arch_hypercall_suspend) + ;; + alloc r20=ar.pfs,0,0,6,0 + mov r2=__HYPERVISOR_sched_op + ;; + /* We don't want to deal with RSE. */ + flushrs + mov r33=r32 + mov r32=2 // SCHEDOP_shutdown + ;; + break 0x1000 + ;; + br.ret.sptk.many b0 +END(xencomm_arch_hypercall_suspend) diff --git a/arch/ia64/xen/xcom_hcall.c b/arch/ia64/xen/xcom_hcall.c new file mode 100644 index 0000000..8cd9cdc --- /dev/null +++ b/arch/ia64/xen/xcom_hcall.c @@ -0,0 +1,458 @@ +/* + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Tristan Gingold <tri...@bu...> + * + * Copyright (c) 2007 + * Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * consolidate mini and inline version. + */ +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/gfp.h> +#include <linux/module.h> +#include <xen/interface/xen.h> +#include <xen/interface/memory.h> +#include <xen/interface/xencomm.h> +#include <xen/interface/version.h> +#include <xen/interface/sched.h> +#include <xen/interface/event_channel.h> +#include <xen/interface/physdev.h> +#include <xen/interface/grant_table.h> +#include <xen/interface/callback.h> +#include <xen/interface/vcpu.h> +#include <asm/xen/hypervisor.h> +#include <asm/page.h> +#include <asm/uaccess.h> +#include <asm/xen/xencomm.h> + +/* Xencomm notes: + * This file defines hypercalls to be used by xencomm. The hypercalls simply + * create inlines or mini descriptors for pointers and then call the raw arch + * hypercall xencomm_arch_hypercall_XXX + * + * If the arch wants to directly use these hypercalls, simply define macros + * in asm/xen/hypercall.h, eg: + * #define HYPERVISOR_sched_op xencomm_hypercall_sched_op + * + * The arch may also define HYPERVISOR_xxx as a function and do more operations + * before/after doing the hypercall. + * + * Note: because only inline or mini descriptors are created these functions + * must only be called with in kernel memory parameters. + */ + +int +xencomm_hypercall_console_io(int cmd, int count, char *str) +{ + return xencomm_arch_hypercall_console_io + (cmd, count, xencomm_map_no_alloc(str, count)); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io); + +int +xencomm_hypercall_event_channel_op(int cmd, void *op) +{ + struct xencomm_handle *desc; + desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op)); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_event_channel_op(cmd, desc); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op); + +int +xencomm_hypercall_xen_version(int cmd, void *arg) +{ + struct xencomm_handle *desc; + unsigned int argsize; + + switch (cmd) { + case XENVER_version: + /* do not actually pass an argument */ + return xencomm_arch_hypercall_xen_version(cmd, 0); + case XENVER_extraversion: + argsize = sizeof(struct xen_extraversion); + break; + case XENVER_compile_info: + argsize = sizeof(struct xen_compile_info); + break; + case XENVER_capabilities: + argsize = sizeof(struct xen_capabilities_info); + break; + case XENVER_changeset: + argsize = sizeof(struct xen_changeset_info); + break; + case XENVER_platform_parameters: + argsize = sizeof(struct xen_platform_parameters); + break; + case XENVER_get_features: + argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info); + break; + + default: + printk(KERN_DEBUG + "%s: unknown version op %d\n", __func__, cmd); + return -ENOSYS; + } + + desc = xencomm_map_no_alloc(arg, argsize); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_xen_version(cmd, desc); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version); + +int +xencomm_hypercall_physdev_op(int cmd, void *op) +{ + unsigned int argsize; + + switch (cmd) { + case PHYSDEVOP_apic_read: + case PHYSDEVOP_apic_write: + argsize = sizeof(struct physdev_apic); + break; + case PHYSDEVOP_alloc_irq_vector: + case PHYSDEVOP_free_irq_vector: + argsize = sizeof(struct physdev_irq); + break; + case PHYSDEVOP_irq_status_query: + argsize = sizeof(struct physdev_irq_status_query); + break; + + default: + printk(KERN_DEBUG + "%s: unknown physdev op %d\n", __func__, cmd); + return -ENOSYS; + } + + return xencomm_arch_hypercall_physdev_op + (cmd, xencomm_map_no_alloc(op, argsize)); +} + +static int +xencommize_grant_table_op(struct xencomm_mini **xc_area, + unsigned int cmd, void *op, unsigned int count, + struct xencomm_handle **desc) +{ + struct xencomm_handle *desc1; + unsigned int argsize; + + switch (cmd) { + case GNTTABOP_map_grant_ref: + argsize = sizeof(struct gnttab_map_grant_ref); + break; + case GNTTABOP_unmap_grant_ref: + argsize = sizeof(struct gnttab_unmap_grant_ref); + break; + case GNTTABOP_setup_table: + { + struct gnttab_setup_table *setup = op; + + argsize = sizeof(*setup); + + if (count != 1) + return -EINVAL; + desc1 = __xencomm_map_no_alloc + (xen_guest_handle(setup->frame_list), + setup->nr_frames * + sizeof(*xen_guest_handle(setup->frame_list)), + *xc_area); + if (desc1 == NULL) + return -EINVAL; + (*xc_area)++; + set_xen_guest_handle(setup->frame_list, (void *)desc1); + break; + } + case GNTTABOP_dump_table: + argsize = sizeof(struct gnttab_dump_table); + break; + case GNTTABOP_transfer: + argsize = sizeof(struct gnttab_transfer); + break; + case GNTTABOP_copy: + argsize = sizeof(struct gnttab_copy); + break; + case GNTTABOP_query_size: + argsize = sizeof(struct gnttab_query_size); + break; + default: + printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n", + __func__, cmd); + BUG(); + } + + *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area); + if (*desc == NULL) + return -EINVAL; + (*xc_area)++; + + return 0; +} + +int +xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, + unsigned int count) +{ + int rc; + struct xencomm_handle *desc; + XENCOMM_MINI_ALIGNED(xc_area, 2); + + rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc); + if (rc) + return rc; + + return xencomm_arch_hypercall_grant_table_op(cmd, desc, count); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op); + +int +xencomm_hypercall_sched_op(int cmd, void *arg) +{ + struct xencomm_handle *desc; + unsigned int argsize; + + switch (cmd) { + case SCHEDOP_yield: + case SCHEDOP_block: + argsize = 0; + break; + case SCHEDOP_shutdown: + argsize = sizeof(struct sched_shutdown); + break; + case SCHEDOP_poll: + { + struct sched_poll *poll = arg; + struct xencomm_handle *ports; + + argsize = sizeof(struct sched_poll); + ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports), + sizeof(*xen_guest_handle(poll->ports))); + + set_xen_guest_handle(poll->ports, (void *)ports); + break; + } + default: + printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd); + return -ENOSYS; + } + + desc = xencomm_map_no_alloc(arg, argsize); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_sched_op(cmd, desc); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op); + +int +xencomm_hypercall_multicall(void *call_list, int nr_calls) +{ + int rc; + int i; + struct multicall_entry *mce; + struct xencomm_handle *desc; + XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2); + + for (i = 0; i < nr_calls; i++) { + mce = (struct multicall_entry *)call_list + i; + + switch (mce->op) { + case __HYPERVISOR_update_va_mapping: + case __HYPERVISOR_mmu_update: + /* No-op on ia64. */ + break; + case __HYPERVISOR_grant_table_op: + rc = xencommize_grant_table_op + (&xc_area, + mce->args[0], (void *)mce->args[1], + mce->args[2], &desc); + if (rc) + return rc; + mce->args[1] = (unsigned long)desc; + break; + case __HYPERVISOR_memory_op: + default: + printk(KERN_DEBUG + "%s: unhandled multicall op entry op %lu\n", + __func__, mce->op); + return -ENOSYS; + } + } + + desc = xencomm_map_no_alloc(call_list, + nr_calls * sizeof(struct multicall_entry)); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_multicall(desc, nr_calls); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall); + +int +xencomm_hypercall_callback_op(int cmd, void *arg) +{ + unsigned int argsize; + switch (cmd) { + case CALLBACKOP_register: + argsize = sizeof(struct callback_register); + break; + case CALLBACKOP_unregister: + argsize = sizeof(struct callback_unregister); + break; + default: + printk(KERN_DEBUG + "%s: unknown callback op %d\n", __func__, cmd); + return -ENOSYS; + } + + return xencomm_arch_hypercall_callback_op + (cmd, xencomm_map_no_alloc(arg, argsize)); +} + +static int +xencommize_memory_reservation(struct xencomm_mini *xc_area, + struct xen_memory_reservation *mop) +{ + struct xencomm_handle *desc; + + desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start), + mop->nr_extents * + sizeof(*xen_guest_handle(mop->extent_start)), + xc_area); + if (desc == NULL) + return -EINVAL; + + set_xen_guest_handle(mop->extent_start, (void *)desc); + return 0; +} + +int +xencomm_hypercall_memory_op(unsigned int cmd, void *arg) +{ + XEN_GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = {{NULL}, {NULL}}; + struct xen_memory_reservation *xmr = NULL; + int rc; + struct xencomm_handle *desc; + unsigned int argsize; + XENCOMM_MINI_ALIGNED(xc_area, 2); + + switch (cmd) { + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + xmr = (struct xen_memory_reservation *)arg; + set_xen_guest_handle(extent_start_va[0], + xen_guest_handle(xmr->extent_start)); + + argsize = sizeof(*xmr); + rc = xencommize_memory_reservation(xc_area, xmr); + if (rc) + return rc; + xc_area++; + break; + + case XENMEM_maximum_ram_page: + argsize = 0; + break; + + case XENMEM_add_to_physmap: + argsize = sizeof(struct xen_add_to_physmap); + break; + + default: + printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd); + return -ENOSYS; + } + + desc = xencomm_map_no_alloc(arg, argsize); + if (desc == NULL) + return -EINVAL; + + rc = xencomm_arch_hypercall_memory_op(cmd, desc); + + switch (cmd) { + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + set_xen_guest_handle(xmr->extent_start, + xen_guest_handle(extent_start_va[0])); + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op); + +int +xencomm_hypercall_suspend(unsigned long srec) +{ + struct sched_shutdown arg; + + arg.reason = SHUTDOWN_suspend; + + return xencomm_arch_hypercall_suspend( + xencomm_map_no_alloc(&arg, sizeof(arg))); +} + +long +xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg) +{ + unsigned int argsize; + switch (cmd) { + case VCPUOP_register_runstate_memory_area: { + struct vcpu_register_runstate_memory_area *area = + (struct vcpu_register_runstate_memory_area *)arg; + argsize = sizeof(*arg); + set_xen_guest_handle(area->addr.h, + (void *)xencomm_map_no_alloc(area->addr.v, + sizeof(area->addr.v))); + break; + } + + default: + printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd); + return -ENOSYS; + } + + return xencomm_arch_hypercall_vcpu_op(cmd, cpu, + xencomm_map_no_alloc(arg, argsize)); +} + +long +xencomm_hypercall_opt_feature(void *arg) +{ + return xencomm_arch_hypercall_opt_feature( + xencomm_map_no_alloc(arg, + sizeof(struct xen_ia64_opt_feature))); +} + +int +xencomm_hypercall_fpswa_revision(unsigned int *revision) +{ + struct xencomm_handle *desc; + + desc = xencomm_map_no_alloc(revision, sizeof(*revision)); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_fpswa_revision(desc); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_fpswa_revision); diff --git a/arch/ia64/xen/xencomm.c b/arch/ia64/xen/xencomm.c new file mode 100644 index 0000000..6e9da66 --- /dev/null +++ b/arch/ia64/xen/xencomm.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2006 Hollis Blanchard <ho...@us...>, IBM Corporation + * + * 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 <linux/gfp.h> +#include <linux/mm.h> +#include <xen/interface/xen.h> +#include <asm/page.h> + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + +#include <asm/xen/xencomm.h> + +static unsigned long kernel_start_pa; + +void +xencomm_initialize(void) +{ + kernel_start_pa = KERNEL_START - ia64_tpa(KERNEL_START); +} + +/* Translate virtual address to physical address. */ +unsigned long +xencomm_vtop(unsigned long vaddr) +{ +#ifndef CONFIG_VMX_GUEST + struct page *page; + struct vm_area_struct *vma; +#endif + + if (vaddr == 0) + return 0; + +#ifdef __ia64__ + if (REGION_NUMBER(vaddr) == 5) { + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *ptep; + + /* On ia64, TASK_SIZE refers to current. It is not initialized + during boot. + Furthermore the kernel is relocatable and __pa() doesn't + work on addresses. */ + if (vaddr >= KERNEL_START + && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) + return vaddr - kernel_start_pa; + + /* In kernel area -- virtually mapped. */ + pgd = pgd_offset_k(vaddr); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return ~0UL; + + pud = pud_offset(pgd, vaddr); + if (pud_none(*pud) || pud_bad(*pud)) + return ~0UL; + + pmd = pmd_offset(pud, vaddr); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + return ~0UL; + + ptep = pte_offset_kernel(pmd, vaddr); + if (!ptep) + return ~0UL; + + return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK); + } +#endif + + if (vaddr > TASK_SIZE) { + /* kernel address */ + return __pa(vaddr); + } + + +#ifdef CONFIG_VMX_GUEST + /* No privcmd within vmx guest. */ + return ~0UL; +#else + /* XXX double-check (lack of) locking */ + vma = find_extend_vma(current->mm, vaddr); + if (!vma) + return ~0UL; + + /* We assume the page is modified. */ + page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH); + if (!page) + return ~0UL; + + return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK); +#endif +} diff --git a/include/asm-ia64/xen/xcom_hcall.h b/include/asm-ia64/xen/xcom_hcall.h new file mode 100644 index 0000000..adf4ba2 --- /dev/null +++ b/include/asm-ia64/xen/xcom_hcall.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2006 Tristan Gingold <tri...@bu...>, Bull SAS + * + * 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 _LINUX_XENCOMM_HCALL_H_ +#define _LINUX_XENCOMM_HCALL_H_ + +/* These function creates inline or mini descriptor for the parameters and + calls the corresponding xencomm_arch_hypercall_X. + Architectures should defines HYPERVISOR_xxx as xencomm_hypercall_xxx unless + they want to use their own wrapper. */ +extern int xencomm_hypercall_console_io(int cmd, int count, char *str); + +extern int xencomm_hypercall_event_channel_op(int cmd, void *op); + +extern int xencomm_hypercall_xen_version(int cmd, void *arg); + +extern int xencomm_hypercall_physdev_op(int cmd, void *op); + +extern int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, + unsigned int count); + +extern int xencomm_hypercall_sched_op(int cmd, void *arg); + +extern int xencomm_hypercall_multicall(void *call_list, int nr_calls); + +extern int xencomm_hypercall_callback_op(int cmd, void *arg); + +extern int xencomm_hypercall_memory_op(unsigned int cmd, void *arg); + +extern unsigned long xencomm_hypercall_hvm_op(int cmd, void *arg); + +extern int xencomm_hypercall_suspend(unsigned long srec); + +extern long xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg); + +extern long xencomm_hypercall_opt_feature(void *arg); + +extern int xencomm_hypercall_kexec_op(int cmd, void *arg); + +#endif /* _LINUX_XENCOMM_HCALL_H_ */ diff --git a/include/asm-ia64/xen/xencomm.h b/include/asm-ia64/xen/xencomm.h new file mode 100644 index 0000000..cc27a5f --- /dev/null +++ b/include/asm-ia64/xen/xencomm.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 Hollis Blanchard <ho...@us...>, IBM Corporation + * + * 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_IA64_XENCOMM_H_ +#define _ASM_IA64_XENCOMM_H_ + +#define is_kernel_addr(x) \ + ((PAGE_OFFSET <= (x) && \ + (x) < (PAGE_OFFSET + (1UL << IA64_MAX_PHYS_BITS))) || \ + (KERNEL_START <= (x) && \ + (x) < KERNEL_START + KERNEL_TR_PAGE_SIZE)) + +/* Must be called before any hypercall. */ +extern void xencomm_initialize(void); + +#include <xen/xencomm.h> + +#endif /* _ASM_IA64_XENCOMM_H_ */ -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:58
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/xen/hypercall.S | 7 + include/asm-ia64/xen/hypercall.h | 426 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 433 insertions(+), 0 deletions(-) create mode 100644 include/asm-ia64/xen/hypercall.h diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S index a96f278..7c5242b 100644 --- a/arch/ia64/xen/hypercall.S +++ b/arch/ia64/xen/hypercall.S @@ -122,3 +122,10 @@ GLOBAL_ENTRY(xen_set_eflag) END(xen_set_eflag) #endif /* CONFIG_IA32_SUPPORT */ #endif /* ASM_SUPPORTED */ + +GLOBAL_ENTRY(__hypercall) + mov r2=r37 + break 0x1000 + br.ret.sptk.many b0 + ;; +END(__hypercall) diff --git a/include/asm-ia64/xen/hypercall.h b/include/asm-ia64/xen/hypercall.h new file mode 100644 index 0000000..8ea2060 --- /dev/null +++ b/include/asm-ia64/xen/hypercall.h @@ -0,0 +1,426 @@ +/****************************************************************************** + * hypercall.h + * + * Linux-specific hypervisor handling. + * + * Copyright (c) 2002-2004, K A Fraser + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __HYPERCALL_H__ +#define __HYPERCALL_H__ + +#ifndef __HYPERVISOR_H__ +# error "please don't include this file directly" +#endif + +#include <asm/xen/xcom_hcall.h> +struct xencomm_handle; +extern unsigned long __hypercall(unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long cmd); + +/* + * Assembler stubs for hyper-calls. + */ + +#define _hypercall0(type, name) \ +({ \ + long __res; \ + __res = __hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);\ + (type)__res; \ +}) + +#define _hypercall1(type, name, a1) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + 0, 0, 0, 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall2(type, name, a1, a2) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + 0, 0, 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall3(type, name, a1, a2, a3) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + 0, 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall4(type, name, a1, a2, a3, a4) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + (unsigned long)a4, \ + 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + (unsigned long)a4, \ + (unsigned long)a5, \ + __HYPERVISOR_##name); \ + (type)__res; \ +}) + + +static inline int +xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, sched_op, cmd, arg); +} + +static inline long +HYPERVISOR_set_timer_op(u64 timeout) +{ + unsigned long timeout_hi = (unsigned long)(timeout >> 32); + unsigned long timeout_lo = (unsigned long)timeout; + return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); +} + +static inline int +xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list, + int nr_calls) +{ + return _hypercall2(int, multicall, call_list, nr_calls); +} + +static inline int +xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, memory_op, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, event_channel_op, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, xen_version, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_console_io(int cmd, int count, + struct xencomm_handle *str) +{ + return _hypercall3(int, console_io, cmd, count, str); +} + +static inline int +xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, physdev_op, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_grant_table_op(unsigned int cmd, + struct xencomm_handle *uop, + unsigned int count) +{ + return _hypercall3(int, grant_table_op, cmd, uop, count); +} + +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); + +extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg); + +static inline int +xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, callback_op, cmd, arg); +} + +static inline unsigned long +xencomm_arch_hypercall_hvm_op(int cmd, void *arg) +{ + return _hypercall2(unsigned long, hvm_op, cmd, arg); +} + +static inline long +xencomm_arch_hypercall_vcpu_op(int cmd, int cpu, void *arg) +{ + return _hypercall3(long, vcpu_op, cmd, cpu, arg); +} + +static inline int +HYPERVISOR_physdev_op(int cmd, void *arg) +{ + switch (cmd) { + case PHYSDEVOP_eoi: + return _hypercall1(int, ia64_fast_eoi, + ((struct physdev_eoi *)arg)->irq); + default: + return xencomm_hypercall_physdev_op(cmd, arg); + } +} + +static inline int +xencomm_arch_hypercall_xenoprof_op(int op, struct xencomm_handle *arg) +{ + return _hypercall2(int, xenoprof_op, op, arg); +} + +static inline long +xencomm_arch_hypercall_opt_feature(struct xencomm_handle *arg) +{ + return _hypercall1(long, opt_feature, arg); +} + +#define xen_do_IRQ(irq, regs) \ +do { \ + struct pt_regs *old_regs; \ + old_regs = set_irq_regs(regs); \ + irq_enter(); \ + __do_IRQ(irq); \ + irq_exit(); \ + set_irq_regs(old_regs); \ +} while (0) +#define irq_ctx_init(cpu) do { } while (0) + +#include <linux/err.h> +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + +static inline unsigned long +__HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) +{ + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_ioremap, ioaddr, size); +} + +static inline unsigned long +HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) +{ + unsigned long ret = ioaddr; + if (is_running_on_xen()) { + ret = __HYPERVISOR_ioremap(ioaddr, size); + if (unlikely(ret == -ENOSYS)) + panic("hypercall %s failed with %ld. " + "Please check Xen and Linux config mismatch\n", + __func__, -ret); + else if (unlikely(IS_ERR_VALUE(ret))) + ret = ioaddr; + } + return ret; +} + +static inline unsigned long +__HYPERVISOR_phystomach(unsigned long gpfn) +{ + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_phystomach, gpfn); +} + +static inline unsigned long +HYPERVISOR_phystomach(unsigned long gpfn) +{ + unsigned long ret = gpfn; + if (is_running_on_xen()) + ret = __HYPERVISOR_phystomach(gpfn); + return ret; +} + +static inline unsigned long +__HYPERVISOR_machtophys(unsigned long mfn) +{ + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_machtophys, mfn); +} + +static inline unsigned long +HYPERVISOR_machtophys(unsigned long mfn) +{ + unsigned long ret = mfn; + if (is_running_on_xen()) + ret = __HYPERVISOR_machtophys(mfn); + return ret; +} + +static inline unsigned long +__HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order) +{ + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_zap_physmap, gpfn, extent_order); +} + +static inline unsigned long +HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order) +{ + unsigned long ret = 0; + if (is_running_on_xen()) + ret = __HYPERVISOR_zap_physmap(gpfn, extent_order); + return ret; +} + +static inline unsigned long +__HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn, + unsigned long flags, domid_t domid) +{ + return _hypercall5(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid); +} + +static inline unsigned long +HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn, + unsigned long flags, domid_t domid) +{ + unsigned long ret = 0; + BUG_ON(!is_running_on_xen()); + if (is_running_on_xen()) + ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid); + return ret; +} + +static inline unsigned long +__HYPERVISOR_add_physmap_with_gmfn(unsigned long gpfn, unsigned long gmfn, + unsigned long flags, domid_t domid) +{ + return _hypercall5(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_add_physmap_with_gmfn, + gpfn, gmfn, flags, domid); +} + +static inline unsigned long +HYPERVISOR_add_physmap_with_gmfn(unsigned long gpfn, unsigned long gmfn, + unsigned long flags, domid_t domid) +{ + unsigned long ret = 0; + BUG_ON(!is_running_on_xen()); + if (is_running_on_xen()) + ret = __HYPERVISOR_add_physmap_with_gmfn(gpfn, gmfn, + flags, domid); + return ret; +} + +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M +static inline unsigned long +HYPERVISOR_expose_p2m(unsigned long conv_start_gpfn, + unsigned long assign_start_gpfn, + unsigned long expose_size, unsigned long granule_pfn) +{ + return _hypercall5(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_expose_p2m, conv_start_gpfn, + assign_start_gpfn, expose_size, granule_pfn); +} + +static inline int +xencomm_arch_expose_foreign_p2m(unsigned long gpfn, + domid_t domid, struct xencomm_handle *arg, + unsigned long flags) +{ + return _hypercall5(int, ia64_dom0vp_op, + IA64_DOM0VP_expose_foreign_p2m, + gpfn, domid, arg, flags); +} + +static inline int +HYPERVISOR_unexpose_foreign_p2m(unsigned long gpfn, domid_t domid) +{ + return _hypercall3(int, ia64_dom0vp_op, + IA64_DOM0VP_unexpose_foreign_p2m, gpfn, domid); +} +#endif + +static inline int +xencomm_arch_hypercall_perfmon_op(unsigned long cmd, + struct xencomm_handle *arg, + unsigned long count) +{ + return _hypercall4(int, ia64_dom0vp_op, + IA64_DOM0VP_perfmon, cmd, arg, count); +} + +static inline int +xencomm_arch_hypercall_fpswa_revision(struct xencomm_handle *arg) +{ + return _hypercall2(int, ia64_dom0vp_op, + IA64_DOM0VP_fpswa_revision, arg); +} + +static inline int +xencomm_arch_hypercall_ia64_debug_op(unsigned long cmd, + unsigned long domain, + struct xencomm_handle *arg) +{ + return _hypercall3(int, ia64_debug_op, cmd, domain, arg); +} + +static inline int +HYPERVISOR_add_io_space(unsigned long phys_base, + unsigned long sparse, + unsigned long space_number) +{ + return _hypercall4(int, ia64_dom0vp_op, IA64_DOM0VP_add_io_space, + phys_base, sparse, space_number); +} + +/* for balloon driver */ +#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0) + +/* Use xencomm to do hypercalls. */ +#define HYPERVISOR_sched_op xencomm_hypercall_sched_op +#define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op +#define HYPERVISOR_callback_op xencomm_hypercall_callback_op +#define HYPERVISOR_multicall xencomm_hypercall_multicall +#define HYPERVISOR_xen_version xencomm_hypercall_xen_version +#define HYPERVISOR_console_io xencomm_hypercall_console_io +#define HYPERVISOR_hvm_op xencomm_hypercall_hvm_op +#define HYPERVISOR_memory_op xencomm_hypercall_memory_op +#define HYPERVISOR_xenoprof_op xencomm_hypercall_xenoprof_op +#define HYPERVISOR_perfmon_op xencomm_hypercall_perfmon_op +#define HYPERVISOR_fpswa_revision xencomm_hypercall_fpswa_revision +#define HYPERVISOR_suspend xencomm_hypercall_suspend +#define HYPERVISOR_vcpu_op xencomm_hypercall_vcpu_op +#define HYPERVISOR_opt_feature xencomm_hypercall_opt_feature +#define HYPERVISOR_kexec_op xencomm_hypercall_kexec_op + +/* to compile gnttab_copy_grant_page() in drivers/xen/core/gnttab.c */ +#define HYPERVISOR_mmu_update(req, count, success_count, domid) ({ BUG(); 0; }) + +#endif /* __HYPERCALL_H__ */ -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:58
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/irq_ia64.c | 363 ++++++++++++++++++++++++++++++++++++++++++- arch/ia64/xen/hypercall.S | 10 ++ include/asm-ia64/hw_irq.h | 10 ++ include/asm-ia64/irq.h | 33 ++++ 4 files changed, 414 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 0b52f19..b5dcb49 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -30,6 +30,9 @@ #include <linux/threads.h> #include <linux/bitops.h> #include <linux/irq.h> +#ifdef CONFIG_XEN +#include <linux/cpu.h> +#endif #include <asm/delay.h> #include <asm/intrinsics.h> @@ -204,6 +207,13 @@ assign_irq_vector (int irq) vector = -ENOSPC; +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + extern int xen_assign_irq_vector(int); + return xen_assign_irq_vector(irq); + } +#endif + spin_lock_irqsave(&vector_lock, flags); for_each_online_cpu(cpu) { domain = vector_allocation_domain(cpu); @@ -227,6 +237,14 @@ free_irq_vector (int vector) if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR) return; + +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + extern void xen_free_irq_vector(int); + xen_free_irq_vector(vector); + return; + } +#endif clear_irq_vector(vector); } @@ -555,12 +573,343 @@ static struct irqaction tlb_irqaction = { #endif +#ifdef CONFIG_XEN +#include <xen/events.h> +#include <xen/interface/callback.h> + +static DEFINE_PER_CPU(int, timer_irq) = -1; +static DEFINE_PER_CPU(int, ipi_irq) = -1; +static DEFINE_PER_CPU(int, resched_irq) = -1; +static DEFINE_PER_CPU(int, cmc_irq) = -1; +static DEFINE_PER_CPU(int, cmcp_irq) = -1; +static DEFINE_PER_CPU(int, cpep_irq) = -1; +static char timer_name[NR_CPUS][15]; +static char ipi_name[NR_CPUS][15]; +static char resched_name[NR_CPUS][15]; +static char cmc_name[NR_CPUS][15]; +static char cmcp_name[NR_CPUS][15]; +static char cpep_name[NR_CPUS][15]; + +struct saved_irq { + unsigned int irq; + struct irqaction *action; +}; +/* 16 should be far optimistic value, since only several percpu irqs + * are registered early. + */ +#define MAX_LATE_IRQ 16 +static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ]; +static unsigned short late_irq_cnt = 0; +static unsigned short saved_irq_cnt = 0; +static int xen_slab_ready = 0; + +#ifdef CONFIG_SMP +/* Dummy stub. Though we may check RESCHEDULE_VECTOR before __do_IRQ, + * it ends up to issue several memory accesses upon percpu data and + * thus adds unnecessary traffic to other paths. + */ +static irqreturn_t +xen_dummy_handler(int irq, void *dev_id) +{ + + return IRQ_HANDLED; +} + +static struct irqaction xen_resched_irqaction = { + .handler = xen_dummy_handler, + .flags = IRQF_DISABLED, + .name = "resched" +}; + +static struct irqaction xen_tlb_irqaction = { + .handler = xen_dummy_handler, + .flags = IRQF_DISABLED, + .name = "tlb_flush" +}; +#endif + +/* + * This is xen version percpu irq registration, which needs bind + * to xen specific evtchn sub-system. One trick here is that xen + * evtchn binding interface depends on kmalloc because related + * port needs to be freed at device/cpu down. So we cache the + * registration on BSP before slab is ready and then deal them + * at later point. For rest instances happening after slab ready, + * we hook them to xen evtchn immediately. + * + * FIXME: MCA is not supported by far, and thus "nomca" boot param is + * required. + */ +static void +xen_register_percpu_irq(unsigned int cpu, unsigned int vec, + struct irqaction *action, int save) +{ + irq_desc_t *desc; + int irq = 0; + + if (xen_slab_ready) { + switch (vec) { + case IA64_TIMER_VECTOR: + sprintf(timer_name[cpu], "%s%d", action->name, cpu); + irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu, + action->handler, action->flags, + timer_name[cpu], action->dev_id); + per_cpu(timer_irq, cpu) = irq; + break; + case IA64_IPI_RESCHEDULE: + sprintf(resched_name[cpu], "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu, + action->handler, action->flags, + resched_name[cpu], action->dev_id); + per_cpu(resched_irq, cpu) = irq; + break; + case IA64_IPI_VECTOR: + sprintf(ipi_name[cpu], "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(IPI_VECTOR, cpu, + action->handler, action->flags, + ipi_name[cpu], action->dev_id); + per_cpu(ipi_irq, cpu) = irq; + break; + case IA64_CMC_VECTOR: + sprintf(cmc_name[cpu], "%s%d", action->name, cpu); + irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, + action->handler, + action->flags, + cmc_name[cpu], + action->dev_id); + per_cpu(cmc_irq, cpu) = irq; + break; + case IA64_CMCP_VECTOR: + sprintf(cmcp_name[cpu], "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(CMCP_VECTOR, cpu, + action->handler, + action->flags, + cmcp_name[cpu], + action->dev_id); + per_cpu(cmcp_irq, cpu) = irq; + break; + case IA64_CPEP_VECTOR: + sprintf(cpep_name[cpu], "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(CPEP_VECTOR, cpu, + action->handler, + action->flags, + cpep_name[cpu], + action->dev_id); + per_cpu(cpep_irq, cpu) = irq; + break; + case IA64_CPE_VECTOR: + case IA64_MCA_RENDEZ_VECTOR: + case IA64_PERFMON_VECTOR: + case IA64_MCA_WAKEUP_VECTOR: + case IA64_SPURIOUS_INT_VECTOR: + /* No need to complain, these aren't supported. */ + break; + default: + printk(KERN_WARNING "Percpu irq %d is unsupported " + "by xen!\n", vec); + break; + } + BUG_ON(irq < 0); + + if (irq > 0) { + /* + * Mark percpu. Without this, migrate_irqs() will + * mark the interrupt for migrations and trigger it + * on cpu hotplug. + */ + desc = irq_desc + irq; + desc->status |= IRQ_PER_CPU; + } + } + + /* For BSP, we cache registered percpu irqs, and then re-walk + * them when initializing APs + */ + if (!cpu && save) { + BUG_ON(saved_irq_cnt == MAX_LATE_IRQ); + saved_percpu_irqs[saved_irq_cnt].irq = vec; + saved_percpu_irqs[saved_irq_cnt].action = action; + saved_irq_cnt++; + if (!xen_slab_ready) + late_irq_cnt++; + } +} + +static void +xen_bind_early_percpu_irq(void) +{ + int i; + + xen_slab_ready = 1; + /* There's no race when accessing this cached array, since only + * BSP will face with such step shortly + */ + for (i = 0; i < late_irq_cnt; i++) + xen_register_percpu_irq(smp_processor_id(), + saved_percpu_irqs[i].irq, + saved_percpu_irqs[i].action, 0); +} + +/* FIXME: There's no obvious point to check whether slab is ready. So + * a hack is used here by utilizing a late time hook. + */ +extern void (*late_time_init)(void); +extern char xen_event_callback; +extern void xen_init_IRQ(void); + +#ifdef CONFIG_HOTPLUG_CPU +static int __devinit +unbind_evtchn_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + if (action == CPU_DEAD) { + /* Unregister evtchn. */ + if (per_cpu(cpep_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(cpep_irq, cpu), NULL); + per_cpu(cpep_irq, cpu) = -1; + } + if (per_cpu(cmcp_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(cmcp_irq, cpu), NULL); + per_cpu(cmcp_irq, cpu) = -1; + } + if (per_cpu(cmc_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(cmc_irq, cpu), NULL); + per_cpu(cmc_irq, cpu) = -1; + } + if (per_cpu(ipi_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(ipi_irq, cpu), NULL); + per_cpu(ipi_irq, cpu) = -1; + } + if (per_cpu(resched_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(resched_irq, cpu), + NULL); + per_cpu(resched_irq, cpu) = -1; + } + if (per_cpu(timer_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL); + per_cpu(timer_irq, cpu) = -1; + } + } + return NOTIFY_OK; +} + +static struct notifier_block unbind_evtchn_notifier = { + .notifier_call = unbind_evtchn_callback, + .priority = 0 +}; +#endif + +DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]); +void xen_smp_intr_init_early(unsigned int cpu) +{ +#ifdef CONFIG_SMP + unsigned int i; + + for (i = 0; i < saved_irq_cnt; i++) + xen_register_percpu_irq(cpu, saved_percpu_irqs[i].irq, + saved_percpu_irqs[i].action, 0); +#endif +} + +void xen_smp_intr_init(void) +{ +#ifdef CONFIG_SMP + unsigned int cpu = smp_processor_id(); + struct callback_register event = { + .type = CALLBACKTYPE_event, + .address = (unsigned long)&xen_event_callback, + }; + + if (cpu == 0) { + /* Initialization was already done for boot cpu. */ +#ifdef CONFIG_HOTPLUG_CPU + /* Register the notifier only once. */ + register_cpu_notifier(&unbind_evtchn_notifier); +#endif + return; + } + + /* This should be piggyback when setup vcpu guest context */ + BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); +#endif /* CONFIG_SMP */ +} + +void __init +xen_irq_init(void) +{ + struct callback_register event = { + .type = CALLBACKTYPE_event, + .address = (unsigned long)&xen_event_callback, + }; + + xen_init_IRQ(); + BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); + late_time_init = xen_bind_early_percpu_irq; +} + +void +xen_platform_send_ipi(int cpu, int vector, int delivery_mode, int redirect) +{ + int irq = -1; + +#ifdef CONFIG_SMP + /* TODO: we need to call vcpu_up here */ + if (unlikely(vector == ap_wakeup_vector)) { + extern void xen_send_ipi(int cpu, int vec); + + /* XXX + * This should be in __cpu_up(cpu) in ia64 smpboot.c + * like x86. But don't want to modify it, + * keep it untouched. + */ + xen_smp_intr_init_early(cpu); + + xen_send_ipi(cpu, vector); + /* vcpu_prepare_and_up(cpu); */ + return; + } +#endif + + switch (vector) { + case IA64_IPI_VECTOR: + irq = per_cpu(ipi_to_irq, cpu)[IPI_VECTOR]; + break; + case IA64_IPI_RESCHEDULE: + irq = per_cpu(ipi_to_irq, cpu)[RESCHEDULE_VECTOR]; + break; + case IA64_CMCP_VECTOR: + irq = per_cpu(ipi_to_irq, cpu)[CMCP_VECTOR]; + break; + case IA64_CPEP_VECTOR: + irq = per_cpu(ipi_to_irq, cpu)[CPEP_VECTOR]; + break; + default: + printk(KERN_WARNING "Unsupported IPI type 0x%x\n", + vector); + irq = 0; + break; + } + + BUG_ON(irq < 0); + notify_remote_via_irq(irq); + return; +} +#endif /* CONFIG_XEN */ + void register_percpu_irq (ia64_vector vec, struct irqaction *action) { irq_desc_t *desc; unsigned int irq; +#ifdef CONFIG_XEN + if (is_running_on_xen()) + return xen_register_percpu_irq(smp_processor_id(), + vec, action, 1); +#endif + irq = vec; BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL)); desc = irq_desc + irq; @@ -576,8 +925,18 @@ init_IRQ (void) register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); - register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); - register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction); +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + register_percpu_irq(IA64_IPI_RESCHEDULE, + &xen_resched_irqaction); + register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, + &xen_tlb_irqaction); + } else +#endif + { + register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); + register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction); + } #endif #ifdef CONFIG_PERFMON pfm_init_percpu(); diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S index 7c5242b..3fad2fe 100644 --- a/arch/ia64/xen/hypercall.S +++ b/arch/ia64/xen/hypercall.S @@ -123,6 +123,16 @@ END(xen_set_eflag) #endif /* CONFIG_IA32_SUPPORT */ #endif /* ASM_SUPPORTED */ +GLOBAL_ENTRY(xen_send_ipi) + mov r14=r32 + mov r15=r33 + mov r2=0x400 + break 0x1000 + ;; + br.ret.sptk.many rp + ;; +END(xen_send_ipi) + GLOBAL_ENTRY(__hypercall) mov r2=r37 break 0x1000 diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index 7e6e377..357f5a8 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h @@ -15,7 +15,11 @@ #include <asm/ptrace.h> #include <asm/smp.h> +#ifndef CONFIG_XEN typedef u8 ia64_vector; +#else +typedef u16 ia64_vector; +#endif /* * 0 special @@ -114,6 +118,12 @@ extern void destroy_and_reserve_irq (unsigned int irq); static inline void ia64_resend_irq(unsigned int vector) { +#ifdef CONFIG_XEN + extern int resend_irq_on_evtchn(unsigned int i); + if (is_running_on_xen()) + resend_irq_on_evtchn(vector); + else +#endif /* CONFIG_XEN */ platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); } diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h index a66d268..aead249 100644 --- a/include/asm-ia64/irq.h +++ b/include/asm-ia64/irq.h @@ -14,6 +14,7 @@ #include <linux/types.h> #include <linux/cpumask.h> +#ifndef CONFIG_XEN #define NR_VECTORS 256 #if (NR_VECTORS + 32 * NR_CPUS) < 1024 @@ -21,6 +22,38 @@ #else #define NR_IRQS 1024 #endif +#else +/* + * The flat IRQ space is divided into two regions: + * 1. A one-to-one mapping of real physical IRQs. This space is only used + * if we have physical device-access privilege. This region is at the + * start of the IRQ space so that existing device drivers do not need + * to be modified to translate physical IRQ numbers into our IRQ space. + * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These + * are bound using the provided bind/unbind functions. + */ + +#define PIRQ_BASE 0 +#define NR_PIRQS 256 + +#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS) +#define NR_DYNIRQS (CONFIG_NR_CPUS * 8) + +#define NR_IRQS (NR_PIRQS + NR_DYNIRQS) +#define NR_IRQ_VECTORS NR_IRQS + +#define pirq_to_irq(_x) ((_x) + PIRQ_BASE) +#define irq_to_pirq(_x) ((_x) - PIRQ_BASE) + +#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE) +#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE) + +#define RESCHEDULE_VECTOR 0 +#define IPI_VECTOR 1 +#define CMCP_VECTOR 2 +#define CPEP_VECTOR 3 +#define NR_IPIS 4 +#endif /* CONFIG_XEN */ static __inline__ int irq_canonicalize (int irq) -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/Makefile | 12 ++++- arch/ia64/kernel/setup.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ arch/ia64/kernel/smpboot.c | 4 ++ arch/ia64/xen/Makefile | 4 ++ 4 files changed, 139 insertions(+), 2 deletions(-) diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index b916ccf..36be3bf 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -45,6 +45,12 @@ ifeq ($(call cc-version),0304) endif KBUILD_CFLAGS += $(cflags-y) + +cppflags-$(CONFIG_XEN) += \ + -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) + +KBUILD_CPPFLAGS += $(cppflags-y) + head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o libs-y += arch/ia64/lib/ @@ -54,7 +60,9 @@ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/ +core-$(CONFIG_IA64_XEN) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/ +core-$(CONFIG_XEN) += arch/ia64/xen/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ @@ -87,8 +95,8 @@ CLEAN_FILES += vmlinux.gz bootloader boot: lib/lib.a vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ -install: vmlinux.gz - sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)" +install: + -yes | sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)" define archhelp echo '* compressed - Build compressed kernel image' diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index ebd1a09..0c103b5 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -61,6 +61,12 @@ #include <asm/system.h> #include <asm/unistd.h> #include <asm/hpsim.h> +#ifdef CONFIG_XEN +#include <xen/features.h> +#include <asm/xen/hypervisor.h> +#include <asm/xen/xencomm.h> +#endif +#include <linux/dma-mapping.h> #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE) # error "struct cpuinfo_ia64 too big!" @@ -71,6 +77,34 @@ unsigned long __per_cpu_offset[NR_CPUS]; EXPORT_SYMBOL(__per_cpu_offset); #endif +#ifdef CONFIG_XEN +static void +xen_panic_hypercall(struct unw_frame_info *info, void *arg) +{ + current->thread.ksp = (__u64)info->sw - 16; + HYPERVISOR_shutdown(SHUTDOWN_crash); + /* we're never actually going to get here... */ +} + +static int +xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + unw_init_running(xen_panic_hypercall, NULL); + /* we're never actually going to get here... */ + return NOTIFY_DONE; +} + +static struct notifier_block xen_panic_block = { + xen_panic_event, NULL, 0 /* try to go last */ +}; + +void xen_pm_power_off(void) +{ + local_irq_disable(); + HYPERVISOR_shutdown(SHUTDOWN_poweroff); +} +#endif + DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info); DEFINE_PER_CPU(unsigned long, local_per_cpu_offset); unsigned long ia64_cycles_per_usec; @@ -288,6 +322,14 @@ reserve_memory (void) rsvd_region[n].end = (unsigned long) ia64_imva(_end); n++; +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + rsvd_region[n].start = (unsigned long)__va((HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT)); + rsvd_region[n].end = rsvd_region[n].start + PAGE_SIZE; + n++; + } +#endif + #ifdef CONFIG_BLK_DEV_INITRD if (ia64_boot_param->initrd_start) { rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start); @@ -466,6 +508,24 @@ setup_arch (char **cmdline_p) { unw_init(); +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + struct shared_info *s = HYPERVISOR_shared_info; + xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT); + + /* Must be done before any hypercall. */ + xencomm_initialize(); + + xen_setup_features(); + /* Register a call for panic conditions. */ + atomic_notifier_chain_register(&panic_notifier_list, + &xen_panic_block); + pm_power_off = xen_pm_power_off; + + xen_ia64_enable_opt_feature(); + } +#endif + ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist); *cmdline_p = __va(ia64_boot_param->command_line); @@ -518,6 +578,59 @@ setup_arch (char **cmdline_p) acpi_boot_init(); #endif +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + printk(KERN_INFO + "Running on Xen! start_info_pfn=0x%lx nr_pages=%ld " + "flags=0x%x\n", + HYPERVISOR_shared_info->arch.start_info_pfn, + xen_start_info->nr_pages, xen_start_info->flags); + + /* + * If a console= is NOT specified, we assume using the + * xencons console is desired. By default, this is xvc0 + * for both dom0 and domU. + */ + if (!strstr(*cmdline_p, "console=")) { + char *p, *q, name[5] = "xvc"; + int offset = 0; + +#if defined(CONFIG_VGA_CONSOLE) + /* + * conswitchp might be set intelligently from the + * PCDP code. If set to VGA console, use it. + */ + if (is_initial_xendomain() && conswitchp == &vga_con) + strncpy(name, "tty", 3); +#endif + + p = strstr(*cmdline_p, "xencons="); + + if (p) { + p += 8; + if (!strncmp(p, "ttyS", 4)) { + strncpy(name, p, 4); + p += 4; + offset = simple_strtol(p, &q, 10); + if (p == q) + offset = 0; + } else if (!strncmp(p, "tty", 3) || + !strncmp(p, "xvc", 3)) { + strncpy(name, p, 3); + p += 3; + offset = simple_strtol(p, &q, 10); + if (p == q) + offset = 0; + } else if (!strncmp(p, "off", 3)) + offset = -1; + } + + if (offset >= 0) + add_preferred_console(name, offset, NULL); + } + } +#endif + #ifdef CONFIG_VT if (!conswitchp) { # if defined(CONFIG_DUMMY_CONSOLE) @@ -537,6 +650,14 @@ setup_arch (char **cmdline_p) #endif /* enable IA-64 Machine Check Abort Handling unless disabled */ +#ifdef CONFIG_XEN + if (is_running_on_xen() && !is_initial_xendomain()) { + nomca = 1; +#if !defined(CONFIG_VT) || !defined(CONFIG_DUMMY_CONSOLE) + conswitchp = NULL; +#endif + } +#endif if (!nomca) ia64_mca_init(); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 32ee597..2da0a00 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -642,6 +642,10 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(smp_processor_id(), cpu_online_map); cpu_set(smp_processor_id(), cpu_callin_map); per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; +#ifdef CONFIG_XEN + if (is_running_on_xen()) + xen_setup_vcpu_info_placement(); +#endif } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile index c219358..91ffafe 100644 --- a/arch/ia64/xen/Makefile +++ b/arch/ia64/xen/Makefile @@ -2,6 +2,10 @@ # Makefile for Xen components # +obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o \ + hypervisor.o util.o xencomm.o xcom_hcall.o xcom_asm.o + +obj-$(CONFIG_IA64_GENERIC) += machvec.o obj-$(CONFIG_PARAVIRT_ALT) += paravirt_xen.o privops_asm.o privops_c.o obj-$(CONFIG_PARAVIRT_NOP_B_PATCH) += paravirt_xen.o obj-$(CONFIG_PARAVIRT_ENTRY) += paravirt_xen.o -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/xen/util.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 101 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/xen/util.c diff --git a/arch/ia64/xen/util.c b/arch/ia64/xen/util.c new file mode 100644 index 0000000..242a1a4 --- /dev/null +++ b/arch/ia64/xen/util.c @@ -0,0 +1,101 @@ +/****************************************************************************** + * arch/ia64/xen/util.c + * This file is the ia64 counterpart of drivers/xen/util.c + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * 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 <linux/mm.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <xen/interface/memory.h> +#include <asm/xen/hypercall.h> + +struct vm_struct *xen_alloc_vm_area(unsigned long size) +{ + int order; + unsigned long virt; + unsigned long nr_pages; + struct vm_struct *area; + + order = get_order(size); + virt = __get_free_pages(GFP_KERNEL, order); + if (virt == 0) + goto err0; + nr_pages = 1 << order; + scrub_pages(virt, nr_pages); + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (area == NULL) + goto err1; + + area->flags = VM_IOREMAP; + area->addr = (void *)virt; + area->size = size; + area->pages = NULL; + area->nr_pages = nr_pages; + area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */ + + return area; + +err1: + free_pages(virt, order); +err0: + return NULL; +} +EXPORT_SYMBOL_GPL(xen_alloc_vm_area); + +void xen_free_vm_area(struct vm_struct *area) +{ + unsigned int order = get_order(area->size); + unsigned long i; + unsigned long phys_addr = __pa(area->addr); + + /* This area is used for foreign page mappping. + * So underlying machine page may not be assigned. */ + for (i = 0; i < (1 << order); i++) { + unsigned long ret; + unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i; + struct xen_memory_reservation reservation = { + .nr_extents = 1, + .address_bits = 0, + .extent_order = 0, + .domid = DOMID_SELF + }; + set_xen_guest_handle(reservation.extent_start, &gpfn); + ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, + &reservation); + BUG_ON(ret != 1); + } + free_pages((unsigned long)area->addr, order); + kfree(area); +} +EXPORT_SYMBOL_GPL(xen_free_vm_area); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/Kconfig | 6 +++++- arch/ia64/xen/Kconfig | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletions(-) create mode 100644 arch/ia64/xen/Kconfig diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index bc84008..31313bc 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -178,7 +178,7 @@ config PARAVIRT_NOP_B_PATCH "br.cond.sptk.many <native_xxx>" and replace it with 'nop.b 0' when running on xen. -#source "arch/ia64/xen/Kconfig" +source "arch/ia64/xen/Kconfig" endif @@ -238,6 +238,10 @@ config IA64_HP_SIM bool "Ski-simulator" select SWIOTLB +config IA64_XEN + bool "Xen guest" + depends on XEN + endchoice choice diff --git a/arch/ia64/xen/Kconfig b/arch/ia64/xen/Kconfig new file mode 100644 index 0000000..30f54c3 --- /dev/null +++ b/arch/ia64/xen/Kconfig @@ -0,0 +1,29 @@ +# +# This Kconfig describes xen/ia64 options +# + +config XEN + bool "Xen hypervisor support" + default y + select PARAVIRT + select PARAVIRT_ALT + select PARAVIRT_ENTRY + select PARAVIRT_NOP_B_PATCH + select XEN_XENCOMM + select IA64_XEN + help + Enable Xen hypervisor support. Resulting kernel runs + both as a guest OS on Xen and natively on hardware. + +if XEN +config XEN_INTERFACE_VERSION + hex + default 0x00030207 + +config XEN_XENCOMM + def_bool y + +config NO_IDLE_HZ + def_bool y + +endif -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/fsys.S | 41 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 41 insertions(+), 0 deletions(-) diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 4484197..7d97e37 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -570,11 +570,34 @@ ENTRY(fsys_fallback_syscall) adds r17=-1024,r15 movl r14=sys_call_table ;; +#ifdef CONFIG_XEN + movl r18=running_on_xen;; + ld4 r18=[r18];; + // p14 = running_on_xen + // p15 = !running_on_xen + cmp.ne p14,p15=r0,r18 + ;; +(p14) movl r18=XSI_PSR_I_ADDR;; +(p14) ld8 r18=[r18] +(p14) mov r29=1;; +(p14) st1 [r18]=r29 +(p15) rsm psr.i +#else rsm psr.i +#endif shladd r18=r17,3,r14 ;; ld8 r18=[r18] // load normal (heavy-weight) syscall entry-point +#ifdef CONFIG_XEN +(p14) mov r27=r8 +(p14) XEN_HYPER_GET_PSR + ;; +(p14) mov r29=r8 +(p14) mov r8=r27 +(p15) mov r29=psr // read psr (12 cyc load latency) +#else mov r29=psr // read psr (12 cyc load latency) +#endif mov r27=ar.rsc mov r21=ar.fpsr mov r26=ar.pfs @@ -686,7 +709,25 @@ GLOBAL_ENTRY(fsys_bubble_down) mov rp=r14 // I0 set the real return addr and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A ;; +#ifdef CONFIG_XEN + movl r14=running_on_xen;; + ld4 r14=[r14];; + // p14 = running_on_xen + // p15 = !running_on_xen + cmp.ne p14,p15=r0,r14 + ;; +(p14) movl r28=XSI_PSR_I_ADDR;; +(p14) ld8 r28=[r28];; +(p14) adds r28=-1,r28;; // event_pending +(p14) ld1 r14=[r28];; +(p14) cmp.ne.unc p13,p14=r14,r0;; +(p13) XEN_HYPER_SSM_I +(p14) adds r28=1,r28;; // event_mask +(p14) st1 [r28]=r0;; +(p15) ssm psr.i +#else ssm psr.i // M2 we're on kernel stacks now, reenable irqs +#endif cmp.eq p8,p0=r3,r0 // A (p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/configs/xen_domu_wip_defconfig | 854 ++++++++++++++++++++++++++++++ 1 files changed, 854 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/configs/xen_domu_wip_defconfig diff --git a/arch/ia64/configs/xen_domu_wip_defconfig b/arch/ia64/configs/xen_domu_wip_defconfig new file mode 100644 index 0000000..f6f6171 --- /dev/null +++ b/arch/ia64/configs/xen_domu_wip_defconfig @@ -0,0 +1,854 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.25-rc1 +# Thu Feb 14 10:38:56 2008 +# +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="xen-ia64" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=20 +# CONFIG_CGROUPS is not set +# CONFIG_FAIR_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_RCU is not set + +# +# Processor type and features +# +CONFIG_IA64=y +CONFIG_64BIT=y +CONFIG_ZONE_DMA=y +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_SWIOTLB=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_DMI=y +CONFIG_EFI=y +CONFIG_GENERIC_IOMAP=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_AUDIT_ARCH=y +CONFIG_PARAVIRT_GUEST=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_ALT=y +CONFIG_PARAVIRT_ENTRY=y +CONFIG_PARAVIRT_NOP_B_PATCH=y +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030207 +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_IA64_EXPOSE_P2M is not set +CONFIG_XEN_XENCOMM=y +CONFIG_NO_IDLE_HZ=y +CONFIG_IA64_GENERIC=y +# CONFIG_IA64_DIG is not set +# CONFIG_IA64_HP_ZX1 is not set +# CONFIG_IA64_HP_ZX1_SWIOTLB is not set +# CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_HP_SIM is not set +# CONFIG_IA64_XEN is not set +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y +# CONFIG_IA64_PAGE_SIZE_4KB is not set +# CONFIG_IA64_PAGE_SIZE_8KB is not set +CONFIG_IA64_PAGE_SIZE_16KB=y +# CONFIG_IA64_PAGE_SIZE_64KB is not set +CONFIG_PGTABLE_3=y +# CONFIG_PGTABLE_4 is not set +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_SCHED_HRTICK is not set +CONFIG_IA64_L1_CACHE_SHIFT=7 +# CONFIG_IA64_CYCLONE is not set +CONFIG_IOSAPIC=y +# CONFIG_IA64_SGI_SN_XP is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_SMP=y +CONFIG_NR_CPUS=16 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +# CONFIG_SCHED_SMT is not set +# CONFIG_PERMIT_BSP_REMOVE is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_RCU_TRACE is not set +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_DISCONTIGMEM_MANUAL=y +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_DISCONTIGMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_NEED_MULTIPLE_NODES=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_MIGRATION is not set +CONFIG_RESOURCES_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_NR_QUICK=1 +CONFIG_VIRT_TO_BUS=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=10 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_VIRTUAL_MEM_MAP=y +CONFIG_HOLES_IN_ZONE=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y +# CONFIG_IA32_SUPPORT is not set +# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set +CONFIG_IA64_MCA_RECOVERY=y +# CONFIG_PERFMON is not set +CONFIG_IA64_PALINFO=y +# CONFIG_IA64_MC_ERR_INJECT is not set +CONFIG_SGI_SN=y +# CONFIG_IA64_ESI is not set +# CONFIG_IA64_HP_AML_NFW is not set + +# +# SN Devices +# +# CONFIG_SGI_IOC3 is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set + +# +# Firmware Drivers +# +CONFIG_EFI_VARS=y +CONFIG_EFI_PCDP=y +# CONFIG_DMIID is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y + +# +# Power management and ACPI +# +CONFIG_PM=y +# CONFIG_PM_LEGACY is not set +# CONFIG_PM_DEBUG is not set +CONFIG_ACPI=y +# CONFIG_ACPI_PROCFS is not set +# CONFIG_ACPI_PROCFS_POWER is not set +# CONFIG_ACPI_SYSFS_POWER is not set +# CONFIG_ACPI_PROC_EVENT is not set +# CONFIG_ACPI_BUTTON is not set +# CONFIG_ACPI_FAN is not set +# CONFIG_ACPI_DOCK is not set +# CONFIG_ACPI_PROCESSOR is not set +CONFIG_ACPI_NUMA=y +# CONFIG_ACPI_CUSTOM_DSDT_INITRD is not set +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +# CONFIG_ACPI_CONTAINER is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# Bus options (PCI, PCMCIA) +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCIEPORTBUS is not set +CONFIG_ARCH_SUPPORTS_MSI=y +# CONFIG_PCI_MSI is not set +# CONFIG_PCI_LEGACY is not set +# CONFIG_PCI_DEBUG is not set +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_PCCARD is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_ADVANCED is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_BRIDGE=y +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_XEN_BLKDEV_FRONTEND=y +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_NET_SB1000 is not set +# CONFIG_ARCNET is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_WAN is not set +CONFIG_XEN_NETDEV_FRONTEND=y +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_NETCONSOLE=y +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_SGI_SNSC is not set +# CONFIG_SGI_TIOCX is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SGI_L1_CONSOLE is not set +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_HVC_DRIVER=y +CONFIG_HVC_XEN=y +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +CONFIG_EFI_RTC=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +# CONFIG_HANGCHECK_TIMER is not set +# CONFIG_MMTIMER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_INFINIBAND is not set +# CONFIG_RTC_CLASS is not set + +# +# Userspace I/O +# +# CONFIG_UIO is not set +# CONFIG_MSPEC is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=y +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y + +# +# HP Simulator drivers +# +# CONFIG_HP_SIMETH is not set +# CONFIG_HP_SIMSERIAL is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +CONFIG_DEBUG_SLAB=y +# CONFIG_DEBUG_SLAB_LEAK is not set +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_PI_LIST=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set +CONFIG_IA64_GRANULE_16MB=y +# CONFIG_IA64_GRANULE_64MB is not set +CONFIG_IA64_PRINT_HAZARDS=y +# CONFIG_DISABLE_VHPT is not set +# CONFIG_IA64_DEBUG_CMPXCHG is not set +# CONFIG_IA64_DEBUG_IRQ is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +# CONFIG_CRYPTO_SEQIV is not set +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_HW is not set -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/salinfo.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/sal.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 0 deletions(-) diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 779c3cc..91bc631 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -378,6 +378,25 @@ salinfo_log_open(struct inode *inode, struct file *file) data->open = 0; return -ENOMEM; } +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + ia64_mca_xencomm_t *entry; + unsigned long flags; + + entry = vmalloc(sizeof(ia64_mca_xencomm_t)); + if (!entry) { + data->open = 0; + vfree(data->log_buffer); + return -ENOMEM; + } + entry->record = data->log_buffer; + entry->handle = xencomm_map(data->log_buffer, + ia64_sal_get_state_info_size(data->type)); + spin_lock_irqsave(&ia64_mca_xencomm_lock, flags); + list_add(&entry->list, &ia64_mca_xencomm_list); + spin_unlock_irqrestore(&ia64_mca_xencomm_lock, flags); + } +#endif return 0; } @@ -389,6 +408,31 @@ salinfo_log_release(struct inode *inode, struct file *file) struct salinfo_data *data = entry->data; if (data->state == STATE_NO_DATA) { +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + struct list_head *pos, *n; + ia64_mca_xencomm_t *found_entry = NULL; + unsigned long flags; + + spin_lock_irqsave(&ia64_mca_xencomm_lock, flags); + list_for_each_safe(pos, n, &ia64_mca_xencomm_list) { + ia64_mca_xencomm_t *entry; + + entry = list_entry(pos, ia64_mca_xencomm_t, + list); + if (entry->record == data->log_buffer) { + list_del(&entry->list); + found_entry = entry; + break; + } + } + spin_unlock_irqrestore(&ia64_mca_xencomm_lock, flags); + if (found_entry) { + xencomm_free(found_entry->handle); + vfree(found_entry); + } + } +#endif vfree(data->log_buffer); vfree(data->oemdata); data->log_buffer = NULL; diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index 2251118..3c20a58 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -42,6 +42,9 @@ #include <asm/pal.h> #include <asm/system.h> #include <asm/fpu.h> +#ifdef CONFIG_XEN +#include <asm/xen/xencomm.h> +#endif extern spinlock_t sal_lock; @@ -679,10 +682,43 @@ ia64_sal_clear_state_info (u64 sal_info_type) /* Get the processor and platform information logged by SAL with respect to the machine * state at the time of the MCAs, INITs, CMCs, or CPEs. */ +#ifdef CONFIG_XEN +static inline u64 ia64_sal_get_state_info_size (u64 sal_info_type); +typedef struct ia64_mca_xencomm_t { + void *record; + struct xencomm_handle *handle; + struct list_head list; +} ia64_mca_xencomm_t; +extern struct list_head ia64_mca_xencomm_list; +extern spinlock_t ia64_mca_xencomm_lock; +#endif + static inline u64 ia64_sal_get_state_info (u64 sal_info_type, u64 *sal_info) { struct ia64_sal_retval isrv; +#ifdef CONFIG_XEN + if (is_running_on_xen()) { + ia64_mca_xencomm_t *entry; + struct xencomm_handle *desc = NULL; + unsigned long flags; + + spin_lock_irqsave(&ia64_mca_xencomm_lock, flags); + list_for_each_entry(entry, &ia64_mca_xencomm_list, list) { + if (entry->record == sal_info) { + desc = entry->handle; + break; + } + } + spin_unlock_irqrestore(&ia64_mca_xencomm_lock, flags); + + if (desc == NULL) + return 0; + + SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO, sal_info_type, 0, + desc, 0, 0, 0, 0); + } else +#endif SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO, sal_info_type, 0, sal_info, 0, 0, 0, 0); if (isrv.status) -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/Makefile | 58 +++++++++++++++++++++++++++++++++++++++ arch/ia64/kernel/gate.S | 55 +++++++++++++++++++++++++++++++++++++ arch/ia64/kernel/gate.lds.S | 18 ++++++++++++ arch/ia64/kernel/patch.c | 28 +++++++++++++++++++ arch/ia64/kernel/vmlinux.lds.S | 6 ++++ arch/ia64/kernel/xengate-data.S | 3 ++ arch/ia64/mm/init.c | 22 +++++++++++++- 7 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 arch/ia64/kernel/xengate-data.S diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index d0e22bb..661619c 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -75,3 +75,61 @@ $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE # We must build gate.so before we can assemble it. # Note: kbuild does not track this dependency due to usage of .incbin $(obj)/gate-data.o: $(obj)/gate.so + +# +# gate page paravirtualization for xen +# +obj-$(CONFIG_XEN) += xengate-data.o + +ifeq ($(CONFIG_XEN), y) +# The gate DSO image is built using a special linker script. +targets += xengate.so xengate-syms.o +endif + +extra-$(CONFIG_XEN) += xengate.so xengate.lds xengate.o + +AFLAGS_xengate.o += -D__XEN_IA64_VDSO_PARAVIRT +$(obj)/xengate.o: $(src)/gate.S FORCE + $(call if_changed_dep,as_o_S) + +CPPFLAGS_xengate.lds := -P -C -U$(ARCH) -D__XEN_IA64_VDSO_PARAVIRT +$(obj)/xengate.lds: $(src)/gate.lds.S + $(call if_changed_dep,cpp_lds_S) + +GATECFLAGS_xengate.so = -shared -s -Wl,-soname=linux-gate.so.1 \ + $(call ld-option, -Wl$(comma)--hash-style=sysv) +$(obj)/xengate.so: $(obj)/xengate.lds $(obj)/xengate.o FORCE + $(call if_changed,gate) + +ifeq ($(CONFIG_XEN), y) +$(obj)/built-in.o: $(obj)/xengate-syms.o +$(obj)/built-in.o: ld_flags += -R $(obj)/xengate-syms.o +$(obj)/mca_recovery.o: $(obj)/gate-syms.o $(obj)/xengate-syms.o +endif + +GATECFLAGS_xengate-syms.o = -r +$(obj)/xengate-syms.o: $(obj)/xengate.lds $(obj)/xengate.o FORCE + $(call if_changed,gate) +$(obj)/xengate-data.o: $(obj)/xengate.so + +# +# .tmp_gate.o to calculate padding size for __kernel_syscall_via_epc +# +extra-$(CONFIG_XEN) += gate-skip.s .tmp_gate.o + +ifeq ($(CONFIG_XEN), y) +AFLAGS_gate.o += -D__KERNEL_SYSCALL_VIA_EPC_PADDING +$(obj)/gate.o: $(obj)/gate-skip.s FORCE +endif + +$(obj)/.tmp_gate.o: $(src)/gate.S FORCE + $(call if_changed_dep,as_o_S) + +quiet_cmd_gate_size = GATE_SIZE $@ + cmd_gate_size = $(NM) --extern-only --print-size $(obj)/xengate.o | \ + $(AWK) '/__kernel_syscall_via_epc/{printf "\t.skip 0x"$$2" - "}' > $@; \ + $(NM) --extern-only --print-size $(obj)/.tmp_gate.o | \ + $(AWK) '/__kernel_syscall_via_epc/{printf "0x"$$2"\n"}' >> $@ + +$(obj)/gate-skip.s: $(obj)/xengate.o $(obj)/.tmp_gate.o FORCE + $(call if_changed,gate_size) diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S index 74b1ccc..7c62417 100644 --- a/arch/ia64/kernel/gate.S +++ b/arch/ia64/kernel/gate.S @@ -77,15 +77,40 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc) epc // B causes split-issue } ;; +#ifdef __XEN_IA64_VDSO_PARAVIRT + // r20 = 1 + // r22 = &vcpu->vcpu_info->evtchn_upcall_mask + // r24 = &vcpu->vcpu_info->evtchn_upcall_pending + // r25 = tmp + // r31 = tmp + // p11 = tmp + // p14 = tmp + mov r20=1 + movl r22=XSI_PSR_I_ADDR + ;; + ld8 r22=[r22] + ;; + st1 [r22]=r20 + rum psr.be + adds r24=-1,r22 +#else rsm psr.be | psr.i // M2 (5 cyc to srlz.d) +#endif LOAD_FSYSCALL_TABLE(r14) // X ;; mov r16=IA64_KR(CURRENT) // M2 (12 cyc) shladd r18=r17,3,r14 // A mov r19=NR_syscalls-1 // A +#ifdef __XEN_IA64_VDSO_PARAVIRT + XEN_HYPER_GET_PSR + ;; + lfetch [r18] // M0|1 + mov r29=r8 +#else ;; lfetch [r18] // M0|1 mov r29=psr // M2 (12 cyc) +#endif // If r17 is a NaT, p6 will be zero cmp.geu p6,p7=r19,r17 // A (sysnr > 0 && sysnr < 1024+NR_syscalls)? ;; @@ -99,9 +124,27 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc) ;; nop.m 0 (p6) tbit.z.unc p8,p0=r18,0 // I0 (dual-issues with "mov b7=r18"!) +#ifdef __XEN_IA64_VDSO_PARAVIRT + +#define XEN_SET_PSR_I(pred) \ +(pred) ld1 r31=[r22]; \ + ;; ; \ +(pred) st1 [r22]=r0; \ +(pred) cmp.ne.unc p14,p0=r0,r31; \ + ;; ; \ +(p14) ld1 r25=[r24]; \ + ;; ; \ +(p14) cmp.ne.unc p11,p0=r0,r25; \ + ;; ; \ +(p11) XEN_HYPER_SSM_I; + + ;; + XEN_SET_PSR_I(p8) +#else nop.i 0 ;; (p8) ssm psr.i +#endif (p6) mov b7=r18 // I0 (p8) br.dptk.many b7 // B @@ -122,11 +165,23 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc) #else BRL_COND_FSYS_BUBBLE_DOWN(p6) #endif +#ifdef __XEN_IA64_VDSO_PARAVIRT + XEN_SET_PSR_I(p0) +#else ssm psr.i +#endif mov r10=-1 (p10) mov r8=EINVAL (p9) mov r8=ENOSYS FSYS_RETURN +#ifdef __KERNEL_SYSCALL_VIA_EPC_PADDING + /* + * All values/sizes of __kernel_xxx symbol in gate.so and xengate.so + * must be same to each other. + * Adjust symbol size in gate.so to be same to the one in xengate.so. + */ +.include "arch/ia64/kernel/gate-skip.s" +#endif END(__kernel_syscall_via_epc) # define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET) diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S index 3cb1abc..b9615cf 100644 --- a/arch/ia64/kernel/gate.lds.S +++ b/arch/ia64/kernel/gate.lds.S @@ -33,6 +33,24 @@ SECTIONS . = GATE_ADDR + 0x600; .data.patch : { +#ifdef __XEN_IA64_VDSO_PARAVIRT +#define __start_gate_mckinley_e9_patchlist \ + __start_gate_mckinley_e9_patchlist_xen +#define __end_gate_mckinley_e9_patchlist \ + __end_gate_mckinley_e9_patchlist_xen +#define __start_gate_vtop_patchlist \ + __start_gate_vtop_patchlist_xen +#define __end_gate_vtop_patchlist \ + __end_gate_vtop_patchlist_xen +#define __start_gate_fsyscall_patchlist \ + __start_gate_fsyscall_patchlist_xen +#define __end_gate_fsyscall_patchlist \ + __end_gate_fsyscall_patchlist_xen +#define __start_gate_brl_fsys_bubble_down_patchlist \ + __start_gate_brl_fsys_bubble_down_patchlist_xen +#define __end_gate_brl_fsys_bubble_down_patchlist \ + __end_gate_brl_fsys_bubble_down_patchlist_xen +#endif __start_gate_mckinley_e9_patchlist = .; *(.data.patch.mckinley_e9) __end_gate_mckinley_e9_patchlist = .; diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c index 2cb9425..4676ac4 100644 --- a/arch/ia64/kernel/patch.c +++ b/arch/ia64/kernel/patch.c @@ -181,9 +181,37 @@ patch_brl_fsys_bubble_down (unsigned long start, unsigned long end) ia64_srlz_i(); } +#ifdef CONFIG_XEN +void __init +ia64_patch_gate_xen (void) +{ + extern char __start_gate_mckinley_e9_patchlist_xen[], __end_gate_mckinley_e9_patchlist_xen[]; + extern char __start_gate_vtop_patchlist_xen[], __end_gate_vtop_patchlist_xen[]; + extern char __start_gate_fsyscall_patchlist_xen[], __end_gate_fsyscall_patchlist_xen[]; + extern char __start_gate_brl_fsys_bubble_down_patchlist_xen[], __end_gate_brl_fsys_bubble_down_patchlist_xen[]; +# define START(name) ((unsigned long) __start_gate_##name##_patchlist_xen) +# define END(name) ((unsigned long)__end_gate_##name##_patchlist_xen) + + patch_fsyscall_table(START(fsyscall), END(fsyscall)); + patch_brl_fsys_bubble_down(START(brl_fsys_bubble_down), END(brl_fsys_bubble_down)); + ia64_patch_vtop(START(vtop), END(vtop)); + ia64_patch_mckinley_e9(START(mckinley_e9), END(mckinley_e9)); + +# undef START +# undef END +} +#else +#define ia64_patch_gate_xen() do { } while (0) +#endif + void __init ia64_patch_gate (void) { + if (is_running_on_xen()) { + ia64_patch_gate_xen(); + return; + } + # define START(name) ((unsigned long) __start_gate_##name##_patchlist) # define END(name) ((unsigned long)__end_gate_##name##_patchlist) diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 0cbe0a1..0cedc30 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -230,6 +230,12 @@ SECTIONS __start_gate_section = .; *(.data.gate) __stop_gate_section = .; +#if defined(CONFIG_XEN) + . = ALIGN(PAGE_SIZE); + __start_xen_gate_section = .; + *(.data.gate.xen) + __stop_xen_gate_section = .; +#endif } . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose * kernel data diff --git a/arch/ia64/kernel/xengate-data.S b/arch/ia64/kernel/xengate-data.S new file mode 100644 index 0000000..122bb5f --- /dev/null +++ b/arch/ia64/kernel/xengate-data.S @@ -0,0 +1,3 @@ + .section .data.gate.xen, "aw" + + .incbin "arch/ia64/kernel/xengate.so" diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 25aef62..5e327ac 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -267,16 +267,34 @@ static void __init setup_gate (void) { struct page *page; + void *gate_page_addr = __start_gate_section; + +#ifdef CONFIG_XEN + unsigned long unused_gate; + extern char __start_xen_gate_section[]; + if (is_running_on_xen()) { + gate_page_addr = __start_xen_gate_section; + unused_gate = (unsigned long)ia64_imva(__start_gate_section); + } else + unused_gate = + (unsigned long)ia64_imva(__start_xen_gate_section); +#ifndef HAVE_BUGGY_SEGREL + ClearPageReserved(virt_to_page(unused_gate)); + init_page_count(virt_to_page(unused_gate)); + free_page(unused_gate); + ++totalram_pages; +#endif +#endif /* * Map the gate page twice: once read-only to export the ELF * headers etc. and once execute-only page to enable * privilege-promotion via "epc": */ - page = virt_to_page(ia64_imva(__start_gate_section)); + page = virt_to_page(ia64_imva(gate_page_addr)); put_kernel_page(page, GATE_ADDR, PAGE_READONLY); #ifdef HAVE_BUGGY_SEGREL - page = virt_to_page(ia64_imva(__start_gate_section + PAGE_SIZE)); + page = virt_to_page(ia64_imva(gate_page_addr + PAGE_SIZE)); put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE); #else put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE); -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/mca.c | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 6e17aed..94f1023 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -339,11 +339,33 @@ typedef struct ia64_state_log_s static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; +#ifdef CONFIG_XEN +DEFINE_SPINLOCK(ia64_mca_xencomm_lock); +LIST_HEAD(ia64_mca_xencomm_list); + +#define IA64_MCA_XENCOMM_ALLOCATE(rec, desc) \ + if (is_running_on_xen()) { \ + ia64_mca_xencomm_t *entry; \ + entry = alloc_bootmem(sizeof(ia64_mca_xencomm_t)); \ + entry->record = rec; \ + entry->handle = desc; \ + list_add(&entry->list, &ia64_mca_xencomm_list); \ + } +#define IA64_LOG_ALLOCATE(it, size) \ + {ia64_err_rec_t *rec; \ + ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = rec = \ + (ia64_err_rec_t *)alloc_bootmem(size); \ + IA64_MCA_XENCOMM_ALLOCATE(rec, xencomm_map(rec, size)); \ + ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = rec = \ + (ia64_err_rec_t *)alloc_bootmem(size); \ + IA64_MCA_XENCOMM_ALLOCATE(rec, xencomm_map(rec, size));} +#else #define IA64_LOG_ALLOCATE(it, size) \ {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \ (ia64_err_rec_t *)alloc_bootmem(size); \ ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \ (ia64_err_rec_t *)alloc_bootmem(size);} +#endif #define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock) #define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s) #define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s) -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- include/asm-ia64/page.h | 11 +++++++++++ include/asm-ia64/xen/page.h | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 0 deletions(-) create mode 100644 include/asm-ia64/xen/page.h diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 4999a6c..effd2af 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -227,4 +227,15 @@ get_order (unsigned long size) (((current->personality & READ_IMPLIES_EXEC) != 0) \ ? VM_EXEC : 0)) +#ifndef __ASSEMBLY__ + +#include <linux/kernel.h> + +#ifdef CONFIG_XEN + +#include <asm/xen/page.h> + +#endif /* CONFIG_XEN */ +#endif /* __ASSEMBLY__ */ + #endif /* _ASM_IA64_PAGE_H */ diff --git a/include/asm-ia64/xen/page.h b/include/asm-ia64/xen/page.h new file mode 100644 index 0000000..9ab8148 --- /dev/null +++ b/include/asm-ia64/xen/page.h @@ -0,0 +1,19 @@ +#ifndef _ASM_IA64_MADDR_H +#define _ASM_IA64_MADDR_H + +#include <linux/kernel.h> +#include <asm/xen/hypervisor.h> +#include <asm/xen/hypercall.h> +#include <xen/features.h> +#include <xen/interface/xen.h> + +#define mfn_to_pfn(mfn) (mfn) +#define pfn_to_mfn(pfn) (pfn) + +#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) +#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) +#define virt_to_machine(virt) __pa(virt) /* for tpmfront.c */ + +#define set_phys_to_machine(pfn, mfn) do { } while (0) + +#endif /* _ASM_IA64_MADDR_H */ -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:57
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/iosapic.c | 89 ++++++++++++++++++++++++++++++++++++++++--- include/asm-ia64/iosapic.h | 2 + 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 398e2fd..5915d7e 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -157,6 +157,79 @@ static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ static int iosapic_kmalloc_ok; static LIST_HEAD(free_rte_list); +#ifdef CONFIG_XEN +#include <xen/interface/xen.h> +#include <xen/interface/physdev.h> +#include <asm/xen/hypervisor.h> +static inline unsigned int +xen_iosapic_read(char __iomem *iosapic, unsigned int reg) +{ + struct physdev_apic apic_op; + int ret; + + apic_op.apic_physbase = (unsigned long)iosapic - + __IA64_UNCACHED_OFFSET; + apic_op.reg = reg; + ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op); + if (ret) + return ret; + return apic_op.value; +} + +static inline void +xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +{ + struct physdev_apic apic_op; + + apic_op.apic_physbase = (unsigned long)iosapic - + __IA64_UNCACHED_OFFSET; + apic_op.reg = reg; + apic_op.value = val; + HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op); +} + +static inline unsigned int +__iosapic_read(char __iomem *iosapic, unsigned int reg) +{ + if (!is_running_on_xen()) { + writel(reg, iosapic + IOSAPIC_REG_SELECT); + return readl(iosapic + IOSAPIC_WINDOW); + } else + return xen_iosapic_read(iosapic, reg); +} + +static inline void +__iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +{ + if (!is_running_on_xen()) { + writel(reg, iosapic + IOSAPIC_REG_SELECT); + writel(val, iosapic + IOSAPIC_WINDOW); + } else + xen_iosapic_write(iosapic, reg, val); +} + +int xen_assign_irq_vector(int irq) +{ + struct physdev_irq irq_op; + + irq_op.irq = irq; + if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) + return -ENOSPC; + + return irq_op.vector; +} + +void xen_free_irq_vector(int vector) +{ + struct physdev_irq irq_op; + + irq_op.vector = vector; + if (HYPERVISOR_physdev_op(PHYSDEVOP_free_irq_vector, &irq_op)) + printk(KERN_WARNING "%s: xen_free_irq_vecotr fail vector=%d\n", + __func__, vector); +} +#endif /* XEN */ + static inline void iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val) { @@ -269,19 +342,15 @@ nop (unsigned int irq) /* do nothing... */ } - #ifdef CONFIG_KEXEC void kexec_disable_iosapic(void) { struct iosapic_intr_info *info; struct iosapic_rte_info *rte; - ia64_vector vec; - int irq; - - for (irq = 0; irq < NR_IRQS; irq++) { - info = &iosapic_intr_info[irq]; - vec = irq_to_vector(irq); + u8 vec = 0; + for (info = iosapic_intr_info; info < + iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { list_for_each_entry(rte, &info->rtes, rte_list) { iosapic_write(rte->iosapic, @@ -635,6 +704,9 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery, iosapic_intr_info[irq].dmode = delivery; iosapic_intr_info[irq].trigger = trigger; + if (is_running_on_xen()) + return 0; + if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; else @@ -987,6 +1059,9 @@ iosapic_system_init (int system_pcat_compat) } pcat_compat = system_pcat_compat; + if (is_running_on_xen()) + return; + if (pcat_compat) { /* * Disable the compatibility mode interrupts (8259 style), diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h index a3a4288..7ed8e4f 100644 --- a/include/asm-ia64/iosapic.h +++ b/include/asm-ia64/iosapic.h @@ -55,6 +55,7 @@ #define NR_IOSAPICS 256 +#ifndef CONFIG_XEN static inline unsigned int __iosapic_read(char __iomem *iosapic, unsigned int reg) { writel(reg, iosapic + IOSAPIC_REG_SELECT); @@ -66,6 +67,7 @@ static inline void __iosapic_write(char __iomem *iosapic, unsigned int reg, u32 writel(reg, iosapic + IOSAPIC_REG_SELECT); writel(val, iosapic + IOSAPIC_WINDOW); } +#endif static inline void iosapic_eoi(char __iomem *iosapic, u32 vector) { -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:53
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/xen/hypercall.S | 124 ++++++++++ include/asm-ia64/gcc_intrin.h | 58 +++--- include/asm-ia64/intel_intrin.h | 64 +++--- include/asm-ia64/intrinsics.h | 14 +- include/asm-ia64/privop.h | 36 +++ include/asm-ia64/xen/privop.h | 489 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 717 insertions(+), 68 deletions(-) create mode 100644 arch/ia64/xen/hypercall.S diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S new file mode 100644 index 0000000..a96f278 --- /dev/null +++ b/arch/ia64/xen/hypercall.S @@ -0,0 +1,124 @@ +/* + * Support routines for Xen hypercalls + * + * Copyright (C) 2005 Dan Magenheimer <dan...@hp...> + */ + +#include <asm/asmmacro.h> +#include <asm/intrinsics.h> + +#ifdef __INTEL_COMPILER +# undef ASM_SUPPORTED +#else +# define ASM_SUPPORTED +#endif + +#ifndef ASM_SUPPORTED +GLOBAL_ENTRY(xen_get_psr) + XEN_HYPER_GET_PSR + br.ret.sptk.many rp + ;; +END(xen_get_psr) + +GLOBAL_ENTRY(xen_get_ivr) + XEN_HYPER_GET_IVR + br.ret.sptk.many rp + ;; +END(xen_get_ivr) + +GLOBAL_ENTRY(xen_get_tpr) + XEN_HYPER_GET_TPR + br.ret.sptk.many rp + ;; +END(xen_get_tpr) + +GLOBAL_ENTRY(xen_set_tpr) + mov r8=r32 + XEN_HYPER_SET_TPR + br.ret.sptk.many rp + ;; +END(xen_set_tpr) + +GLOBAL_ENTRY(xen_eoi) + mov r8=r32 + XEN_HYPER_EOI + br.ret.sptk.many rp + ;; +END(xen_eoi) + +GLOBAL_ENTRY(xen_thash) + mov r8=r32 + XEN_HYPER_THASH + br.ret.sptk.many rp + ;; +END(xen_thash) + +GLOBAL_ENTRY(xen_set_itm) + mov r8=r32 + XEN_HYPER_SET_ITM + br.ret.sptk.many rp + ;; +END(xen_set_itm) + +GLOBAL_ENTRY(xen_ptcga) + mov r8=r32 + mov r9=r33 + XEN_HYPER_PTC_GA + br.ret.sptk.many rp + ;; +END(xen_ptcga) + +GLOBAL_ENTRY(xen_get_rr) + mov r8=r32 + XEN_HYPER_GET_RR + br.ret.sptk.many rp + ;; +END(xen_get_rr) + +GLOBAL_ENTRY(xen_set_rr) + mov r8=r32 + mov r9=r33 + XEN_HYPER_SET_RR + br.ret.sptk.many rp + ;; +END(xen_set_rr) + +GLOBAL_ENTRY(xen_set_kr) + mov r8=r32 + mov r9=r33 + XEN_HYPER_SET_KR + br.ret.sptk.many rp +END(xen_set_kr) + +GLOBAL_ENTRY(xen_fc) + mov r8=r32 + XEN_HYPER_FC + br.ret.sptk.many rp +END(xen_fc) + +GLOBAL_ENTRY(xen_get_cpuid) + mov r8=r32 + XEN_HYPER_GET_CPUID + br.ret.sptk.many rp +END(xen_get_cpuid) + +GLOBAL_ENTRY(xen_get_pmd) + mov r8=r32 + XEN_HYPER_GET_PMD + br.ret.sptk.many rp +END(xen_get_pmd) + +#ifdef CONFIG_IA32_SUPPORT +GLOBAL_ENTRY(xen_get_eflag) + XEN_HYPER_GET_EFLAG + br.ret.sptk.many rp +END(xen_get_eflag) + +// some bits aren't set if pl!=0, see SDM vol1 3.1.8 +GLOBAL_ENTRY(xen_set_eflag) + mov r8=r32 + XEN_HYPER_SET_EFLAG + br.ret.sptk.many rp +END(xen_set_eflag) +#endif /* CONFIG_IA32_SUPPORT */ +#endif /* ASM_SUPPORTED */ diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h index de2ed2c..5fe2932 100644 --- a/include/asm-ia64/gcc_intrin.h +++ b/include/asm-ia64/gcc_intrin.h @@ -28,7 +28,7 @@ extern void ia64_bad_param_for_getreg (void); register unsigned long ia64_r13 asm ("r13") __used; #endif -#define ia64_setreg(regnum, val) \ +#define __ia64_setreg(regnum, val) \ ({ \ switch (regnum) { \ case _IA64_REG_PSR_L: \ @@ -57,7 +57,7 @@ register unsigned long ia64_r13 asm ("r13") __used; } \ }) -#define ia64_getreg(regnum) \ +#define __ia64_getreg(regnum) \ ({ \ __u64 ia64_intri_res; \ \ @@ -94,7 +94,7 @@ register unsigned long ia64_r13 asm ("r13") __used; #define ia64_hint_pause 0 -#define ia64_hint(mode) \ +#define __ia64_hint(mode) \ ({ \ switch (mode) { \ case ia64_hint_pause: \ @@ -381,7 +381,7 @@ register unsigned long ia64_r13 asm ("r13") __used; #define ia64_invala() asm volatile ("invala" ::: "memory") -#define ia64_thash(addr) \ +#define __ia64_thash(addr) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \ @@ -401,18 +401,18 @@ register unsigned long ia64_r13 asm ("r13") __used; #define ia64_nop(x) asm volatile ("nop %0"::"i"(x)); -#define ia64_itci(addr) asm volatile ("itc.i %0;;" :: "r"(addr) : "memory") +#define __ia64_itci(addr) asm volatile ("itc.i %0;;" :: "r"(addr) : "memory") -#define ia64_itcd(addr) asm volatile ("itc.d %0;;" :: "r"(addr) : "memory") +#define __ia64_itcd(addr) asm volatile ("itc.d %0;;" :: "r"(addr) : "memory") -#define ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1" \ +#define __ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1" \ :: "r"(trnum), "r"(addr) : "memory") -#define ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1" \ +#define __ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1" \ :: "r"(trnum), "r"(addr) : "memory") -#define ia64_tpa(addr) \ +#define __ia64_tpa(addr) \ ({ \ __u64 ia64_pa; \ asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory"); \ @@ -422,22 +422,22 @@ register unsigned long ia64_r13 asm ("r13") __used; #define __ia64_set_dbr(index, val) \ asm volatile ("mov dbr[%0]=%1" :: "r"(index), "r"(val) : "memory") -#define ia64_set_ibr(index, val) \ +#define __ia64_set_ibr(index, val) \ asm volatile ("mov ibr[%0]=%1" :: "r"(index), "r"(val) : "memory") -#define ia64_set_pkr(index, val) \ +#define __ia64_set_pkr(index, val) \ asm volatile ("mov pkr[%0]=%1" :: "r"(index), "r"(val) : "memory") -#define ia64_set_pmc(index, val) \ +#define __ia64_set_pmc(index, val) \ asm volatile ("mov pmc[%0]=%1" :: "r"(index), "r"(val) : "memory") -#define ia64_set_pmd(index, val) \ +#define __ia64_set_pmd(index, val) \ asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory") -#define ia64_set_rr(index, val) \ +#define __ia64_set_rr(index, val) \ asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory"); -#define ia64_get_cpuid(index) \ +#define __ia64_get_cpuid(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index)); \ @@ -451,21 +451,21 @@ register unsigned long ia64_r13 asm ("r13") __used; ia64_intri_res; \ }) -#define ia64_get_ibr(index) \ +#define __ia64_get_ibr(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \ ia64_intri_res; \ }) -#define ia64_get_pkr(index) \ +#define __ia64_get_pkr(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \ ia64_intri_res; \ }) -#define ia64_get_pmc(index) \ +#define __ia64_get_pmc(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index)); \ @@ -473,48 +473,48 @@ register unsigned long ia64_r13 asm ("r13") __used; }) -#define ia64_get_pmd(index) \ +#define __ia64_get_pmd(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index)); \ ia64_intri_res; \ }) -#define ia64_get_rr(index) \ +#define __ia64_get_rr(index) \ ({ \ __u64 ia64_intri_res; \ asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index)); \ ia64_intri_res; \ }) -#define ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory") +#define __ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory") #define ia64_sync_i() asm volatile (";; sync.i" ::: "memory") -#define ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory") -#define ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory") +#define __ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory") +#define __ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory") #define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory") #define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory") -#define ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr)) +#define __ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr)) -#define ia64_ptcga(addr, size) \ +#define __ia64_ptcga(addr, size) \ do { \ asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory"); \ ia64_dv_serialize_data(); \ } while (0) -#define ia64_ptcl(addr, size) \ +#define __ia64_ptcl(addr, size) \ do { \ asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory"); \ ia64_dv_serialize_data(); \ } while (0) -#define ia64_ptri(addr, size) \ +#define __ia64_ptri(addr, size) \ asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory") -#define ia64_ptrd(addr, size) \ +#define __ia64_ptrd(addr, size) \ asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory") /* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */ @@ -596,7 +596,7 @@ do { \ } \ }) -#define ia64_intrin_local_irq_restore(x) \ +#define __ia64_intrin_local_irq_restore(x) \ do { \ asm volatile (";; cmp.ne p6,p7=%0,r0;;" \ "(p6) ssm psr.i;" \ diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h index a520d10..83ee398 100644 --- a/include/asm-ia64/intel_intrin.h +++ b/include/asm-ia64/intel_intrin.h @@ -16,8 +16,8 @@ * intrinsic */ -#define ia64_getreg __getReg -#define ia64_setreg __setReg +#define __ia64_getreg __getReg +#define __ia64_setreg __setReg #define ia64_hint __hint #define ia64_hint_pause __hint_pause @@ -33,16 +33,16 @@ #define ia64_getf_exp __getf_exp #define ia64_shrp _m64_shrp -#define ia64_tpa __tpa +#define __ia64_tpa __tpa #define ia64_invala __invala #define ia64_invala_gr __invala_gr #define ia64_invala_fr __invala_fr #define ia64_nop __nop #define ia64_sum __sum -#define ia64_ssm __ssm +#define __ia64_ssm __ssm #define ia64_rum __rum -#define ia64_rsm __rsm -#define ia64_fc __fc +#define __ia64_rsm __rsm +#define __ia64_fc __fc #define ia64_ldfs __ldfs #define ia64_ldfd __ldfd @@ -80,24 +80,24 @@ #define __ia64_set_dbr(index, val) \ __setIndReg(_IA64_REG_INDR_DBR, index, val) -#define ia64_set_ibr(index, val) \ +#define __ia64_set_ibr(index, val) \ __setIndReg(_IA64_REG_INDR_IBR, index, val) -#define ia64_set_pkr(index, val) \ +#define __ia64_set_pkr(index, val) \ __setIndReg(_IA64_REG_INDR_PKR, index, val) -#define ia64_set_pmc(index, val) \ +#define __ia64_set_pmc(index, val) \ __setIndReg(_IA64_REG_INDR_PMC, index, val) -#define ia64_set_pmd(index, val) \ +#define __ia64_set_pmd(index, val) \ __setIndReg(_IA64_REG_INDR_PMD, index, val) -#define ia64_set_rr(index, val) \ +#define __ia64_set_rr(index, val) \ __setIndReg(_IA64_REG_INDR_RR, index, val) -#define ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index) +#define __ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index) #define __ia64_get_dbr(index) __getIndReg(_IA64_REG_INDR_DBR, index) -#define ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index) -#define ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index) -#define ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index) -#define ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index) -#define ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index) +#define __ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index) +#define __ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index) +#define __ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index) +#define __ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index) +#define __ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index) #define ia64_srlz_d __dsrlz #define ia64_srlz_i __isrlz @@ -119,18 +119,18 @@ #define ia64_ld8_acq __ld8_acq #define ia64_sync_i __synci -#define ia64_thash __thash -#define ia64_ttag __ttag -#define ia64_itcd __itcd -#define ia64_itci __itci -#define ia64_itrd __itrd -#define ia64_itri __itri -#define ia64_ptce __ptce -#define ia64_ptcl __ptcl -#define ia64_ptcg __ptcg -#define ia64_ptcga __ptcga -#define ia64_ptri __ptri -#define ia64_ptrd __ptrd +#define __ia64_thash __thash +#define __ia64_ttag __ttag +#define __ia64_itcd __itcd +#define __ia64_itci __itci +#define __ia64_itrd __itrd +#define __ia64_itri __itri +#define __ia64_ptce __ptce +#define __ia64_ptcl __ptcl +#define __ia64_ptcg __ptcg +#define __ia64_ptcga __ptcga +#define __ia64_ptri __ptri +#define __ia64_ptrd __ptrd #define ia64_dep_mi _m64_dep_mi /* Values for lfhint in __lfetch and __lfetch_fault */ @@ -145,13 +145,13 @@ #define ia64_lfetch_fault __lfetch_fault #define ia64_lfetch_fault_excl __lfetch_fault_excl -#define ia64_intrin_local_irq_restore(x) \ +#define __ia64_intrin_local_irq_restore(x) \ do { \ if ((x) != 0) { \ - ia64_ssm(IA64_PSR_I); \ + __ia64_ssm(IA64_PSR_I); \ ia64_srlz_d(); \ } else { \ - ia64_rsm(IA64_PSR_I); \ + __ia64_rsm(IA64_PSR_I); \ } \ } while (0) diff --git a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h index 5800ad0..4edf6de 100644 --- a/include/asm-ia64/intrinsics.h +++ b/include/asm-ia64/intrinsics.h @@ -18,15 +18,15 @@ # include <asm/gcc_intrin.h> #endif -#define ia64_get_psr_i() (ia64_getreg(_IA64_REG_PSR) & IA64_PSR_I) +#define __ia64_get_psr_i() (__ia64_getreg(_IA64_REG_PSR) & IA64_PSR_I) -#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \ +#define __ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \ do { \ - ia64_set_rr(0x0000000000000000UL, (val0)); \ - ia64_set_rr(0x2000000000000000UL, (val1)); \ - ia64_set_rr(0x4000000000000000UL, (val2)); \ - ia64_set_rr(0x6000000000000000UL, (val3)); \ - ia64_set_rr(0x8000000000000000UL, (val4)); \ + __ia64_set_rr(0x0000000000000000UL, (val0)); \ + __ia64_set_rr(0x2000000000000000UL, (val1)); \ + __ia64_set_rr(0x4000000000000000UL, (val2)); \ + __ia64_set_rr(0x6000000000000000UL, (val3)); \ + __ia64_set_rr(0x8000000000000000UL, (val4)); \ } while (0) /* diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h index 09c14ae..8261dad 100644 --- a/include/asm-ia64/privop.h +++ b/include/asm-ia64/privop.h @@ -16,6 +16,42 @@ /* fallback for native case */ +#ifndef IA64_PARAVIRTUALIZED_PRIVOP +#ifndef __ASSEMBLY +#define ia64_getreg __ia64_getreg +#define ia64_setreg __ia64_setreg +#define ia64_hint __ia64_hint +#define ia64_thash __ia64_thash +#define ia64_itci __ia64_itci +#define ia64_itcd __ia64_itcd +#define ia64_itri __ia64_itri +#define ia64_itrd __ia64_itrd +#define ia64_tpa __ia64_tpa +#define ia64_set_ibr __ia64_set_ibr +#define ia64_set_pkr __ia64_set_pkr +#define ia64_set_pmc __ia64_set_pmc +#define ia64_set_pmd __ia64_set_pmd +#define ia64_set_rr __ia64_set_rr +#define ia64_get_cpuid __ia64_get_cpuid +#define ia64_get_ibr __ia64_get_ibr +#define ia64_get_pkr __ia64_get_pkr +#define ia64_get_pmc __ia64_get_pmc +#define ia64_get_pmd __ia64_get_pmd +#define ia64_get_rr __ia64_get_rr +#define ia64_fc __ia64_fc +#define ia64_ssm __ia64_ssm +#define ia64_rsm __ia64_rsm +#define ia64_ptce __ia64_ptce +#define ia64_ptcga __ia64_ptcga +#define ia64_ptcl __ia64_ptcl +#define ia64_ptri __ia64_ptri +#define ia64_ptrd __ia64_ptrd +#define ia64_get_psr_i __ia64_get_psr_i +#define ia64_intrin_local_irq_restore __ia64_intrin_local_irq_restore +#define ia64_set_rr0_to_rr4 __ia64_set_rr0_to_rr4 +#endif /* !__ASSEMBLY */ +#endif /* !IA64_PARAVIRTUALIZED_PRIVOP */ + #ifndef IA64_PARAVIRTUALIZED_ENTRY #define ia64_switch_to __ia64_switch_to #define ia64_leave_syscall __ia64_leave_syscall diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h index 0fa8aa6..3caa7e9 100644 --- a/include/asm-ia64/xen/privop.h +++ b/include/asm-ia64/xen/privop.h @@ -70,6 +70,495 @@ #define XSI_IHA (XSI_BASE + XSI_IHA_OFS) #endif +#ifndef __ASSEMBLY__ +#define XEN_HYPER_SSM_I asm("break %0" : : "i" (HYPERPRIVOP_SSM_I)) +#define XEN_HYPER_GET_IVR asm("break %0" : : "i" (HYPERPRIVOP_GET_IVR)) + +/************************************************/ +/* Instructions paravirtualized for correctness */ +/************************************************/ + +/* "fc" and "thash" are privilege-sensitive instructions, meaning they + * may have different semantics depending on whether they are executed + * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't + * be allowed to execute directly, lest incorrect semantics result. */ +#ifdef ASM_SUPPORTED +static inline void +xen_fc(unsigned long addr) +{ + register __u64 __addr asm ("r8") = addr; + asm volatile ("break %0":: "i"(HYPERPRIVOP_FC), "r"(__addr)); +} + +static inline unsigned long +xen_thash(unsigned long addr) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __addr asm ("r8") = addr; + asm volatile ("break %1": + "=r"(ia64_intri_res): + "i"(HYPERPRIVOP_THASH), "0"(__addr)); + return ia64_intri_res; +} +#else +extern void xen_fc(unsigned long addr); +extern unsigned long xen_thash(unsigned long addr); +#endif + +/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" + * is not currently used (though it may be in a long-format VHPT system!) + * and the semantics of cover only change if psr.ic is off which is very + * rare (and currently non-existent outside of assembly code */ + +/* There are also privilege-sensitive registers. These registers are + * readable at any privilege level but only writable at PL0. */ +#ifdef ASM_SUPPORTED +static inline unsigned long +xen_get_cpuid(int index) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __index asm ("r8") = index; + asm volatile ("break %1": + "=r"(ia64_intri_res): + "i"(HYPERPRIVOP_GET_CPUID), "0"(__index)); + return ia64_intri_res; +} + +static inline unsigned long +xen_get_pmd(int index) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __index asm ("r8") = index; + asm volatile ("break %1": + "=r"(ia64_intri_res): + "i"(HYPERPRIVOP_GET_PMD), "0O"(__index)); + return ia64_intri_res; +} +#else +extern unsigned long xen_get_cpuid(int index); +extern unsigned long xen_get_pmd(int index); +#endif + +#ifdef ASM_SUPPORTED +static inline unsigned long +xen_get_eflag(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile ("break %1": + "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_EFLAG)); + return ia64_intri_res; +} + +static inline void +xen_set_eflag(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_EFLAG), "r"(__val)); +} +#else +extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */ +extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */ +#endif + +/************************************************/ +/* Instructions paravirtualized for performance */ +/************************************************/ + +/* Xen uses memory-mapped virtual privileged registers for access to many + * performance-sensitive privileged registers. Some, like the processor + * status register (psr), are broken up into multiple memory locations. + * Others, like "pend", are abstractions based on privileged registers. + * "Pend" is guaranteed to be set if reading cr.ivr would return a + * (non-spurious) interrupt. */ +#define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE) + +#define XSI_PSR_I \ + (*XEN_MAPPEDREGS->interrupt_mask_addr) +#define xen_get_virtual_psr_i() \ + (!XSI_PSR_I) +#define xen_set_virtual_psr_i(_val) \ + ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; }) +#define xen_set_virtual_psr_ic(_val) \ + ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; }) +#define xen_get_virtual_pend() \ + (*(((uint8_t *)XEN_MAPPEDREGS->interrupt_mask_addr) - 1)) + +/* Hyperprivops are "break" instructions with a well-defined API. + * In particular, the virtual psr.ic bit must be off; in this way + * it is guaranteed to never conflict with a linux break instruction. + * Normally, this is done in a xen stub but this one is frequent enough + * that we inline it */ +#define xen_hyper_ssm_i() \ +({ \ + XEN_HYPER_SSM_I; \ +}) + +/* turning off interrupts can be paravirtualized simply by writing + * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */ +#define xen_rsm_i() \ +do { \ + xen_set_virtual_psr_i(0); \ + barrier(); \ +} while (0) + +/* turning on interrupts is a bit more complicated.. write to the + * memory-mapped virtual psr.i bit first (to avoid race condition), + * then if any interrupts were pending, we have to execute a hyperprivop + * to ensure the pending interrupt gets delivered; else we're done! */ +#define xen_ssm_i() \ +do { \ + int old = xen_get_virtual_psr_i(); \ + xen_set_virtual_psr_i(1); \ + barrier(); \ + if (!old && xen_get_virtual_pend()) \ + xen_hyper_ssm_i(); \ +} while (0) + +#define xen_ia64_intrin_local_irq_restore(x) \ +do { \ + if (is_running_on_xen()) { \ + if ((x) & IA64_PSR_I) \ + xen_ssm_i(); \ + else \ + xen_rsm_i(); \ + } else { \ + __ia64_intrin_local_irq_restore((x)); \ + } \ +} while (0) + +#define xen_get_psr_i() \ +({ \ + \ + (is_running_on_xen()) ? \ + (xen_get_virtual_psr_i() ? IA64_PSR_I : 0) \ + : __ia64_get_psr_i() \ +}) + +#define xen_ia64_ssm(mask) \ +do { \ + if ((mask) == IA64_PSR_I) { \ + if (is_running_on_xen()) \ + xen_ssm_i(); \ + else \ + __ia64_ssm(mask); \ + } else { \ + __ia64_ssm(mask); \ + } \ +} while (0) + +#define xen_ia64_rsm(mask) \ +do { \ + if ((mask) == IA64_PSR_I) { \ + if (is_running_on_xen()) \ + xen_rsm_i(); \ + else \ + __ia64_rsm(mask); \ + } else { \ + __ia64_rsm(mask); \ + } \ +} while (0) + +/* Although all privileged operations can be left to trap and will + * be properly handled by Xen, some are frequent enough that we use + * hyperprivops for performance. */ + +#ifndef ASM_SUPPORTED +extern unsigned long xen_get_psr(void); +extern unsigned long xen_get_ivr(void); +extern unsigned long xen_get_tpr(void); +extern void xen_set_itm(unsigned long); +extern void xen_set_tpr(unsigned long); +extern void xen_eoi(unsigned long); +extern void xen_set_rr(unsigned long index, unsigned long val); +extern unsigned long xen_get_rr(unsigned long index); +extern void xen_set_kr(unsigned long index, unsigned long val); +extern void xen_ptcga(unsigned long addr, unsigned long size); +#else +static inline unsigned long +xen_get_psr(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile ("break %1": + "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_PSR)); + return ia64_intri_res; +} + +static inline unsigned long +xen_get_ivr(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile ("break %1": + "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_IVR)); + return ia64_intri_res; +} + +static inline unsigned long +xen_get_tpr(void) +{ + register __u64 ia64_intri_res asm ("r8"); + asm volatile ("break %1": + "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_TPR)); + return ia64_intri_res; +} + +static inline void +xen_set_tpr(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile ("break %0":: + "i"(HYPERPRIVOP_GET_TPR), "r"(__val)); +} + +static inline void +xen_eoi(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile ("break %0":: + "i"(HYPERPRIVOP_EOI), "r"(__val)); +} + +static inline void +xen_set_itm(unsigned long val) +{ + register __u64 __val asm ("r8") = val; + asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_ITM), "r"(__val)); +} + +static inline void +xen_ptcga(unsigned long addr, unsigned long size) +{ + register __u64 __addr asm ("r8") = addr; + register __u64 __size asm ("r9") = size; + asm volatile ("break %0":: + "i"(HYPERPRIVOP_PTC_GA), "r"(__addr), "r"(__size)); +} + +static inline unsigned long +xen_get_rr(unsigned long index) +{ + register __u64 ia64_intri_res asm ("r8"); + register __u64 __index asm ("r8") = index; + asm volatile ("break %1": + "=r"(ia64_intri_res): + "i"(HYPERPRIVOP_GET_RR), "0"(__index)); + return ia64_intri_res; +} + +static inline void +xen_set_rr(unsigned long index, unsigned long val) +{ + register __u64 __index asm ("r8") = index; + register __u64 __val asm ("r9") = val; + asm volatile ("break %0":: + "i"(HYPERPRIVOP_SET_RR), "r"(__index), "r"(__val)); +} + +static inline void +xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1, + unsigned long val2, unsigned long val3, unsigned long val4) +{ + register __u64 __val0 asm ("r8") = val0; + register __u64 __val1 asm ("r9") = val1; + register __u64 __val2 asm ("r10") = val2; + register __u64 __val3 asm ("r11") = val3; + register __u64 __val4 asm ("r14") = val4; + asm volatile ("break %0" :: + "i"(HYPERPRIVOP_SET_RR0_TO_RR4), + "r"(__val0), "r"(__val1), + "r"(__val2), "r"(__val3), "r"(__val4)); +} + +static inline void +xen_set_kr(unsigned long index, unsigned long val) +{ + register __u64 __index asm ("r8") = index; + register __u64 __val asm ("r9") = val; + asm volatile ("break %0":: + "i"(HYPERPRIVOP_SET_KR), "r"(__index), "r"(__val)); +} +#endif + +/* Note: It may look wrong to test for is_running_on_xen() in each case. + * However regnum is always a constant so, as written, the compiler + * eliminates the switch statement, whereas is_running_on_xen() must be + * tested dynamically. */ +#define xen_ia64_getreg(regnum) \ +({ \ + __u64 ia64_intri_res; \ + \ + switch (regnum) { \ + case _IA64_REG_PSR: \ + ia64_intri_res = (is_running_on_xen()) ? \ + xen_get_psr() : \ + __ia64_getreg(regnum); \ + break; \ + case _IA64_REG_CR_IVR: \ + ia64_intri_res = (is_running_on_xen()) ? \ + xen_get_ivr() : \ + __ia64_getreg(regnum); \ + break; \ + case _IA64_REG_CR_TPR: \ + ia64_intri_res = (is_running_on_xen()) ? \ + xen_get_tpr() : \ + __ia64_getreg(regnum); \ + break; \ + case _IA64_REG_AR_EFLAG: \ + ia64_intri_res = (is_running_on_xen()) ? \ + xen_get_eflag() : \ + __ia64_getreg(regnum); \ + break; \ + default: \ + ia64_intri_res = __ia64_getreg(regnum); \ + break; \ + } \ + ia64_intri_res; \ +}) + +#define xen_ia64_setreg(regnum, val) \ +({ \ + switch (regnum) { \ + case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: \ + (is_running_on_xen()) ? \ + xen_set_kr(((regnum)-_IA64_REG_AR_KR0), (val)) :\ + __ia64_setreg((regnum), (val)); \ + break; \ + case _IA64_REG_CR_ITM: \ + (is_running_on_xen()) ? \ + xen_set_itm(val) : \ + __ia64_setreg((regnum), (val)); \ + break; \ + case _IA64_REG_CR_TPR: \ + (is_running_on_xen()) ? \ + xen_set_tpr(val) : \ + __ia64_setreg((regnum), (val)); \ + break; \ + case _IA64_REG_CR_EOI: \ + (is_running_on_xen()) ? \ + xen_eoi(val) : \ + __ia64_setreg((regnum), (val)); \ + break; \ + case _IA64_REG_AR_EFLAG: \ + (is_running_on_xen()) ? \ + xen_set_eflag(val) : \ + __ia64_setreg((regnum), (val)); \ + break; \ + default: \ + __ia64_setreg((regnum), (val)); \ + break; \ + } \ +}) + +#if defined(ASM_SUPPORTED) && !defined(CONFIG_PARAVIRT_ALT) + +#define IA64_PARAVIRTUALIZED_PRIVOP + +#define ia64_fc(addr) \ +do { \ + if (is_running_on_xen()) \ + xen_fc((unsigned long)(addr)); \ + else \ + __ia64_fc(addr); \ +} while (0) + +#define ia64_thash(addr) \ +({ \ + unsigned long ia64_intri_res; \ + if (is_running_on_xen()) \ + ia64_intri_res = \ + xen_thash((unsigned long)(addr)); \ + else \ + ia64_intri_res = __ia64_thash(addr); \ + ia64_intri_res; \ +}) + +#define ia64_get_cpuid(i) \ +({ \ + unsigned long ia64_intri_res; \ + if (is_running_on_xen()) \ + ia64_intri_res = xen_get_cpuid(i); \ + else \ + ia64_intri_res = __ia64_get_cpuid(i); \ + ia64_intri_res; \ +}) + +#define ia64_get_pmd(i) \ +({ \ + unsigned long ia64_intri_res; \ + if (is_running_on_xen()) \ + ia64_intri_res = xen_get_pmd(i); \ + else \ + ia64_intri_res = __ia64_get_pmd(i); \ + ia64_intri_res; \ +}) + + +#define ia64_ptcga(addr, size) \ +do { \ + if (is_running_on_xen()) \ + xen_ptcga((addr), (size)); \ + else \ + __ia64_ptcga((addr), (size)); \ +} while (0) + +#define ia64_set_rr(index, val) \ +do { \ + if (is_running_on_xen()) \ + xen_set_rr((index), (val)); \ + else \ + __ia64_set_rr((index), (val)); \ +} while (0) + +#define ia64_get_rr(index) \ +({ \ + __u64 ia64_intri_res; \ + if (is_running_on_xen()) \ + ia64_intri_res = xen_get_rr((index)); \ + else \ + ia64_intri_res = __ia64_get_rr((index)); \ + ia64_intri_res; \ +}) + +#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \ +do { \ + if (is_running_on_xen()) \ + xen_set_rr0_to_rr4((val0), (val1), (val2), \ + (val3), (val4)); \ + else \ + __ia64_set_rr0_to_rr4((val0), (val1), (val2), \ + (val3), (val4)); \ +} while (0) + +#define ia64_getreg xen_ia64_getreg +#define ia64_setreg xen_ia64_setreg +#define ia64_ssm xen_ia64_ssm +#define ia64_rsm xen_ia64_rsm +#define ia64_intrin_local_irq_restore xen_ia64_intrin_local_irq_restore +#define ia64_get_psr_i xen_get_psr_i + +/* the remainder of these are not performance-sensitive so its + * OK to not paravirtualize and just take a privop trap and emulate */ +#define ia64_hint __ia64_hint +#define ia64_set_pmd __ia64_set_pmd +#define ia64_itci __ia64_itci +#define ia64_itcd __ia64_itcd +#define ia64_itri __ia64_itri +#define ia64_itrd __ia64_itrd +#define ia64_tpa __ia64_tpa +#define ia64_set_ibr __ia64_set_ibr +#define ia64_set_pkr __ia64_set_pkr +#define ia64_set_pmc __ia64_set_pmc +#define ia64_get_ibr __ia64_get_ibr +#define ia64_get_pkr __ia64_get_pkr +#define ia64_get_pmc __ia64_get_pmc +#define ia64_ptce __ia64_ptce +#define ia64_ptcl __ia64_ptcl +#define ia64_ptri __ia64_ptri +#define ia64_ptrd __ia64_ptrd + +#endif /* ASM_SUPPORTED && !CONFIG_PARAVIRT_ALT */ + +#endif /* !__ASSEMBLY__ */ + /* these routines utilize privilege-sensitive or performance-sensitive * privileged instructions so the code must be replaced with * paravirtualized versions */ -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:52
|
Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/pal.S | 5 ++- arch/ia64/xen/xenpal.S | 76 +++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/privop.h | 1 + include/asm-ia64/xen/privop.h | 1 + 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 arch/ia64/xen/xenpal.S diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S index 0b53344..de7252d 100644 --- a/arch/ia64/kernel/pal.S +++ b/arch/ia64/kernel/pal.S @@ -16,6 +16,7 @@ #include <asm/processor.h> .data + .globl pal_entry_point pal_entry_point: data8 ia64_pal_default_handler .text @@ -52,7 +53,7 @@ END(ia64_pal_default_handler) * in0 Index of PAL service * in1 - in3 Remaining PAL arguments */ -GLOBAL_ENTRY(ia64_pal_call_static) +GLOBAL_ENTRY(__ia64_pal_call_static) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4) alloc loc1 = ar.pfs,4,5,0,0 movl loc2 = pal_entry_point @@ -86,7 +87,7 @@ GLOBAL_ENTRY(ia64_pal_call_static) ;; srlz.d // seralize restoration of psr.l br.ret.sptk.many b0 -END(ia64_pal_call_static) +END(__ia64_pal_call_static) /* * Make a PAL call using the stacked registers calling convention. diff --git a/arch/ia64/xen/xenpal.S b/arch/ia64/xen/xenpal.S new file mode 100644 index 0000000..cf8dff9 --- /dev/null +++ b/arch/ia64/xen/xenpal.S @@ -0,0 +1,76 @@ +/* + * ia64/xen/xenpal.S + * + * Alternate PAL routines for Xen. Heavily leveraged from + * ia64/kernel/pal.S + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@.hp.com> + */ + +#include <asm/asmmacro.h> +#include <asm/processor.h> +#include <asm/paravirt_nop.h> + +GLOBAL_ENTRY(xen_pal_call_static) +#ifdef CONFIG_XEN + BR_IF_NATIVE(__ia64_pal_call_static, r22, p7) +#endif + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) + alloc loc1 = ar.pfs,4,5,0,0 + movl loc2 = pal_entry_point +1: { + mov r28 = in0 + mov r29 = in1 + mov r8 = ip + } + ;; + ld8 loc2 = [loc2] // loc2 <- entry point + adds r8 = 1f-1b,r8 + mov loc4=ar.rsc // save RSE configuration + ;; + mov ar.rsc=0 // put RSE in enforced lazy, LE mode +#ifdef CONFIG_XEN + mov r9 = r8 + XEN_HYPER_GET_PSR + ;; + mov loc3 = r8 + mov r8 = r9 + ;; +#else + mov loc3 = psr +#endif + mov loc0 = rp + .body + mov r30 = in2 + +#ifdef CONFIG_XEN + // this is low priority for paravirtualization, but is called + // from the idle loop so confuses privop counting + movl r31=XSI_PSR_I_ADDR + ;; + ld8 r31=[r31] + mov r22=1 + ;; + st1 [r31]=r22 + ;; + mov r31 = in3 + mov b7 = loc2 + ;; +#else + mov r31 = in3 + mov b7 = loc2 + +(p7) rsm psr.i + ;; +#endif + mov rp = r8 + br.cond.sptk.many b7 +1: mov psr.l = loc3 + mov ar.rsc = loc4 // restore RSE configuration + mov ar.pfs = loc1 + mov rp = loc0 + ;; + srlz.d // seralize restoration of psr.l + br.ret.sptk.many b0 +END(xen_pal_call_static) diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h index b8dce79..09c14ae 100644 --- a/include/asm-ia64/privop.h +++ b/include/asm-ia64/privop.h @@ -21,6 +21,7 @@ #define ia64_leave_syscall __ia64_leave_syscall #define ia64_work_processed_syscall __ia64_work_processed_syscall #define ia64_leave_kernel __ia64_leave_kernel +#define ia64_pal_call_static __ia64_pal_call_static #endif /* !IA64_PARAVIRTUALIZED_ENTRY */ #endif /* _ASM_IA64_PRIVOP_H */ diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h index c8a5a0d..0fa8aa6 100644 --- a/include/asm-ia64/xen/privop.h +++ b/include/asm-ia64/xen/privop.h @@ -79,6 +79,7 @@ #define ia64_leave_syscall xen_leave_syscall #define ia64_work_processed_syscall xen_work_processed_syscall_with_check #define ia64_leave_kernel xen_leave_kernel +#define ia64_pal_call_static xen_pal_call_static #endif /* !CONFIG_PARAVIRT_ENTRY */ #ifdef CONFIG_XEN -- 1.5.3 -- yamahata |
From: <yam...@va...> - 2008-02-21 22:31:50
|
With binary patching, make intrinsics paravirtualization hypervisor neutral. So far xen intrinsics doesn't allow another hypervisor. Mark privileged operations which needs paravirtualization and binary patch if running on xen at early boot time. Signed-off-by: Isaku Yamahata <yam...@va...> --- arch/ia64/kernel/module.c | 32 ++ arch/ia64/kernel/paravirtentry.S | 37 +++ arch/ia64/xen/Makefile | 7 + arch/ia64/xen/paravirt_xen.c | 242 +++++++++++++++ arch/ia64/xen/privops_asm.S | 221 ++++++++++++++ arch/ia64/xen/privops_c.c | 279 +++++++++++++++++ arch/ia64/xen/xensetup.S | 10 + include/asm-ia64/privop.h | 4 + include/asm-ia64/privop_paravirt.h | 587 ++++++++++++++++++++++++++++++++++++ include/asm-ia64/xen/privop.h | 24 ++ 10 files changed, 1443 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kernel/paravirtentry.S create mode 100644 arch/ia64/xen/Makefile create mode 100644 arch/ia64/xen/paravirt_xen.c create mode 100644 arch/ia64/xen/privops_asm.S create mode 100644 arch/ia64/xen/privops_c.c create mode 100644 include/asm-ia64/privop_paravirt.h diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index e58f436..2806f70 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -454,6 +454,14 @@ module_frob_arch_sections (Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, char *secstrings, mod->arch.opd = s; else if (strcmp(".IA_64.unwind", secstrings + s->sh_name) == 0) mod->arch.unwind = s; +#ifdef CONFIG_PARAVIRT_ALT + else if (strcmp(".paravirt_bundles", + secstrings + s->sh_name) == 0) + mod->arch.paravirt_bundles = s; + else if (strcmp(".paravirt_insts", + secstrings + s->sh_name) == 0) + mod->arch.paravirt_insts = s; +#endif if (!mod->arch.core_plt || !mod->arch.init_plt || !mod->arch.got || !mod->arch.opd) { printk(KERN_ERR "%s: sections missing\n", mod->name); @@ -929,6 +937,30 @@ module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mo DEBUGP("%s: init: entry=%p\n", __FUNCTION__, mod->init); if (mod->arch.unwind) register_unwind_table(mod); +#ifdef CONFIG_PARAVIRT_ALT + if (mod->arch.paravirt_bundles) { + struct paravirt_alt_bundle_patch *start = + (struct paravirt_alt_bundle_patch *) + mod->arch.paravirt_bundles->sh_addr; + struct paravirt_alt_bundle_patch *end = + (struct paravirt_alt_bundle_patch *) + (mod->arch.paravirt_bundles->sh_addr + + mod->arch.paravirt_bundles->sh_size); + + xen_alt_bundle_patch_module(start, end); + } + if (mod->arch.paravirt_insts) { + struct paravirt_alt_inst_patch *start = + (struct paravirt_alt_inst_patch *) + mod->arch.paravirt_insts->sh_addr; + struct paravirt_alt_inst_patch *end = + (struct paravirt_alt_inst_patch *) + (mod->arch.paravirt_insts->sh_addr + + mod->arch.paravirt_insts->sh_size); + + xen_alt_inst_patch_module(start, end); + } +#endif return 0; } diff --git a/arch/ia64/kernel/paravirtentry.S b/arch/ia64/kernel/paravirtentry.S new file mode 100644 index 0000000..99606d0 --- /dev/null +++ b/arch/ia64/kernel/paravirtentry.S @@ -0,0 +1,37 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirtentry.S + * + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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 <asm/types.h> +#include <asm/asmmacro.h> +#include <asm/paravirt_entry.h> +#include <asm/privop_paravirt.h> + +#define BRANCH(sym, type) \ + GLOBAL_ENTRY(paravirt_ ## sym) ; \ + BR_COND_SPTK_MANY(__ia64_ ## sym, type) ; \ + END(paravirt_ ## sym) + + BRANCH(switch_to, PARAVIRT_ENTRY_SWITCH_TO) + BRANCH(leave_syscall, PARAVIRT_ENTRY_LEAVE_SYSCALL) + BRANCH(work_processed_syscall, PARAVIRT_ENTRY_WORK_PROCESSED_SYSCALL) + BRANCH(leave_kernel, PARAVIRT_ENTRY_LEAVE_KERNEL) + BRANCH(pal_call_static, PARAVIRT_ENTRY_PAL_CALL_STATIC) diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile new file mode 100644 index 0000000..c219358 --- /dev/null +++ b/arch/ia64/xen/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Xen components +# + +obj-$(CONFIG_PARAVIRT_ALT) += paravirt_xen.o privops_asm.o privops_c.o +obj-$(CONFIG_PARAVIRT_NOP_B_PATCH) += paravirt_xen.o +obj-$(CONFIG_PARAVIRT_ENTRY) += paravirt_xen.o diff --git a/arch/ia64/xen/paravirt_xen.c b/arch/ia64/xen/paravirt_xen.c new file mode 100644 index 0000000..57b9dfd --- /dev/null +++ b/arch/ia64/xen/paravirt_xen.c @@ -0,0 +1,242 @@ +/****************************************************************************** + * linux/arch/ia64/xen/paravirt_xen.c + * + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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 <linux/types.h> +#include <linux/string.h> +#include <linux/init.h> +#include <asm/intrinsics.h> +#include <asm/bugs.h> +#include <asm/kprobes.h> /* for bundle_t */ +#include <asm/paravirt_core.h> + +#ifdef CONFIG_PARAVIRT_ALT +struct xen_alt_bundle_patch_elem { + const void *sbundle; + const void *ebundle; + unsigned long type; +}; + +static unsigned long __init_or_module +__xen_alt_bundle_patch(void *sbundle, void *ebundle, unsigned long type) +{ + extern const struct xen_alt_bundle_patch_elem xen_alt_bundle_array[]; + extern const unsigned long xen_alt_bundle_array_size; + + unsigned long used = 0; + unsigned long i; + + BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0); + BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0); + + for (i = 0; + i < xen_alt_bundle_array_size / sizeof(xen_alt_bundle_array[0]); + i++) { + const struct xen_alt_bundle_patch_elem *p = + &xen_alt_bundle_array[i]; + if (p->type == type) { + used = p->ebundle - p->sbundle; + BUG_ON(used > ebundle - sbundle); + memcpy(sbundle, p->sbundle, used); + break; + } + } + + return used; +} + +static void __init +xen_alt_bundle_patch(void) +{ + extern struct paravirt_alt_bundle_patch __start_paravirt_bundles[]; + extern struct paravirt_alt_bundle_patch __stop_paravirt_bundles[]; + + paravirt_alt_bundle_patch_apply(__start_paravirt_bundles, + __stop_paravirt_bundles, + &__xen_alt_bundle_patch); +} + +#ifdef CONFIG_MODULES +void +xen_alt_bundle_patch_module(struct paravirt_alt_bundle_patch *start, + struct paravirt_alt_bundle_patch *end) +{ + if (is_running_on_xen()) + paravirt_alt_bundle_patch_apply(start, end, + &__xen_alt_bundle_patch); +} +#endif /* CONFIG_MODULES */ + + +/* + * all the native instructions of hyperprivops are M-form or I-form + * mov ar.<imm>=r1 I26, M29 + * mov r1=ar.<imm> I28, M31 + * mov r1=cr.<imm> M32 + * mov cr.<imm>=r1 M33 + * mov r1=psr M36 + * mov indirect<r1>=r2 M42 + * mov r1=indirect<r2> M43 + * ptc.ga M45 + * thash r1=r2 M46 + * + * break.{m, i} instrucitions format are same. + * So we can safely replace all signle instruction which is target of + * hyperpviops with break.{m, i} imm21 hyperprivops. + */ + +struct xen_alt_inst_patch_elem { + unsigned long stag; + unsigned long etag; + unsigned long type; +}; + +unsigned long +__xen_alt_inst_patch(unsigned long stag, unsigned long etag, + unsigned long type) +{ + extern const struct xen_alt_inst_patch_elem xen_alt_inst_array[]; + extern const unsigned long xen_alt_inst_array_size; + + unsigned long dest_tag = stag; + unsigned long i; + + for (i = 0; + i < xen_alt_inst_array_size / sizeof(xen_alt_inst_array[0]); + i++) { + const struct xen_alt_inst_patch_elem *p = + &xen_alt_inst_array[i]; + if (p->type == type) { + unsigned long src_tag; + + for (src_tag = p->stag; + src_tag < p->etag; + src_tag = paravirt_get_next_tag(src_tag)) { + const cmp_inst_t inst = + paravirt_read_inst(src_tag); + paravirt_write_inst(dest_tag, inst); + + BUG_ON(dest_tag >= etag); + dest_tag = paravirt_get_next_tag(dest_tag); + } + break; + } + } + + return dest_tag; +} + +void +xen_alt_inst_patch(void) +{ + extern struct paravirt_alt_inst_patch __start_paravirt_insts[]; + extern struct paravirt_alt_inst_patch __stop_paravirt_insts[]; + + paravirt_alt_inst_patch_apply(__start_paravirt_insts, + __stop_paravirt_insts, + &__xen_alt_inst_patch); +} + +#ifdef CONFIG_MODULES +void +xen_alt_inst_patch_module(struct paravirt_alt_inst_patch *start, + struct paravirt_alt_inst_patch *end) +{ + if (is_running_on_xen()) + paravirt_alt_inst_patch_apply(start, end, + &__xen_alt_inst_patch); +} +#endif + +#else +#define xen_alt_bundle_patch() do { } while (0) +#define xen_alt_inst_patch() do { } while (0) +#endif /* CONFIG_PARAVIRT_ALT */ + + +#ifdef CONFIG_PARAVIRT_NOP_B_PATCH +#include <asm/paravirt_nop.h> +static void __init +xen_nop_b_patch(void) +{ + extern const struct paravirt_nop_patch __start_paravirt_nop_b[]; + extern const struct paravirt_nop_patch __stop_paravirt_nop_b[]; + + paravirt_nop_b_patch_apply(__start_paravirt_nop_b, + __stop_paravirt_nop_b); +} +#else +#define xen_nop_b_patch() do { } while (0) +#endif + + +#ifdef CONFIG_PARAVIRT_ENTRY + +#include <asm/paravirt_entry.h> + +extern void *xen_switch_to; +extern void *xen_leave_syscall; +extern void *xen_leave_kernel; +extern void *xen_pal_call_static; +extern void *xen_work_processed_syscall; + +const static struct paravirt_entry xen_entries[] __initdata = { + {&xen_switch_to, PARAVIRT_ENTRY_SWITCH_TO}, + {&xen_leave_syscall, PARAVIRT_ENTRY_LEAVE_SYSCALL}, + {&xen_leave_kernel, PARAVIRT_ENTRY_LEAVE_KERNEL}, + {&xen_pal_call_static, PARAVIRT_ENTRY_PAL_CALL_STATIC}, + {&xen_work_processed_syscall, PARAVIRT_ENTRY_WORK_PROCESSED_SYSCALL}, +}; + +void __init +xen_entry_patch(void) +{ + extern const struct paravirt_entry_patch __start_paravirt_entry[]; + extern const struct paravirt_entry_patch __stop_paravirt_entry[]; + + paravirt_entry_patch_apply(__start_paravirt_entry, + __stop_paravirt_entry, + xen_entries, + sizeof(xen_entries)/sizeof(xen_entries[0])); +} +#else +#define xen_entry_patch() do { } while (0) +#endif + + +void __init +xen_paravirt_patch(void) +{ + xen_alt_bundle_patch(); + xen_alt_inst_patch(); + xen_nop_b_patch(); + xen_entry_patch(); +} + +/* + * Local variables: + * mode: C + * c-set-style: "linux" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/arch/ia64/xen/privops_asm.S b/arch/ia64/xen/privops_asm.S new file mode 100644 index 0000000..40e400e --- /dev/null +++ b/arch/ia64/xen/privops_asm.S @@ -0,0 +1,221 @@ +/****************************************************************************** + * linux/arch/ia64/xen/privop_s.S + * + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * 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 <asm/intrinsics.h> +#include <linux/init.h> +#include <asm/paravirt_alt.h> + +#ifdef CONFIG_MODULES +#define __INIT_OR_MODULE .text +#define __INITDATA_OR_MODULE .data +#else +#define __INIT_OR_MODULE __INIT +#define __INITDATA_OR_MODULE __INITDATA +#endif /* CONFIG_MODULES */ + + __INIT_OR_MODULE + .align 32 + .proc nop_b_inst_bundle + .global nop_b_inst_bundle +nop_b_inst_bundle: + { + nop.b 0 + nop.b 0 + nop.b 0 + } + .endp nop_b_inst_bundle + __FINIT + + /* NOTE: nop.[mfi] has same format */ + __INIT_OR_MODULE + .align 32 + .proc nop_mfi_inst_bundle + .global nop_mfi_inst_bundle +nop_mfi_inst_bundle: + { + nop.m 0 + nop.f 0 + nop.i 0 + } + .endp nop_mfi_inst_bundle + __FINIT + + __INIT_OR_MODULE + .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_OR_MODULE + .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:; \ + {; \ + [xen_ ## name ## _stag:] \ + instr; \ + [xen_ ## name ## _etag:] \ + nop 0; \ + nop 0; \ + }; \ + xen_ ## name ## _instr_end:; \ + .endp xen_ ## name ## _instr; + + __INIT_OR_MODULE + 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) + DEFINE_PRIVOP(set_rr0_to_rr4, XEN_HYPER_SET_RR0_TO_RR4) + __FINIT + + +#define PARAVIRT_ALT_BUNDLE_ELEM(name, type) \ + data8 xen_ ## name ## _instr_start; \ + data8 xen_ ## name ## _instr_end; \ + data8 type; + + __INITDATA_OR_MODULE + .align 8 + .global xen_alt_bundle_array +xen_alt_bundle_array: +xen_alt_bundle_array_start: + PARAVIRT_ALT_BUNDLE_ELEM(rfi, PARAVIRT_INST_RFI) + PARAVIRT_ALT_BUNDLE_ELEM(rsm_psr_dt, PARAVIRT_INST_RSM_DT) + PARAVIRT_ALT_BUNDLE_ELEM(ssm_psr_dt, PARAVIRT_INST_SSM_DT) + PARAVIRT_ALT_BUNDLE_ELEM(cover, PARAVIRT_INST_COVER) + PARAVIRT_ALT_BUNDLE_ELEM(itc_d, PARAVIRT_INST_ITC_D) + PARAVIRT_ALT_BUNDLE_ELEM(itc_i, PARAVIRT_INST_ITC_I) + PARAVIRT_ALT_BUNDLE_ELEM(ssm_i, PARAVIRT_INST_SSM_I) + PARAVIRT_ALT_BUNDLE_ELEM(get_ivr, PARAVIRT_INST_GET_IVR) + PARAVIRT_ALT_BUNDLE_ELEM(get_tpr, PARAVIRT_INST_GET_TPR) + PARAVIRT_ALT_BUNDLE_ELEM(set_tpr, PARAVIRT_INST_SET_TPR) + PARAVIRT_ALT_BUNDLE_ELEM(eoi, PARAVIRT_INST_EOI) + PARAVIRT_ALT_BUNDLE_ELEM(set_itm, PARAVIRT_INST_SET_ITM) + PARAVIRT_ALT_BUNDLE_ELEM(thash, PARAVIRT_INST_THASH) + PARAVIRT_ALT_BUNDLE_ELEM(ptc_ga, PARAVIRT_INST_PTC_GA) + PARAVIRT_ALT_BUNDLE_ELEM(itr_d, PARAVIRT_INST_ITR_D) + PARAVIRT_ALT_BUNDLE_ELEM(get_rr, PARAVIRT_INST_GET_RR) + PARAVIRT_ALT_BUNDLE_ELEM(set_rr, PARAVIRT_INST_SET_RR) + PARAVIRT_ALT_BUNDLE_ELEM(set_kr, PARAVIRT_INST_SET_KR) + PARAVIRT_ALT_BUNDLE_ELEM(fc, PARAVIRT_INST_FC) + PARAVIRT_ALT_BUNDLE_ELEM(get_cpuid, PARAVIRT_INST_GET_CPUID) + PARAVIRT_ALT_BUNDLE_ELEM(get_pmd, PARAVIRT_INST_GET_PMD) + PARAVIRT_ALT_BUNDLE_ELEM(get_eflag, PARAVIRT_INST_GET_EFLAG) + PARAVIRT_ALT_BUNDLE_ELEM(set_eflag, PARAVIRT_INST_SET_EFLAG) + PARAVIRT_ALT_BUNDLE_ELEM(get_psr, PARAVIRT_INST_GET_PSR) + + PARAVIRT_ALT_BUNDLE_ELEM(ssm_i, PARAVIRT_BNDL_SSM_I) + PARAVIRT_ALT_BUNDLE_ELEM(rsm_i, PARAVIRT_BNDL_RSM_I) + PARAVIRT_ALT_BUNDLE_ELEM(get_psr_i, PARAVIRT_BNDL_GET_PSR_I) + PARAVIRT_ALT_BUNDLE_ELEM(intrin_local_irq_restore, + PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE) +xen_alt_bundle_array_end: + + .align 8 + .global xen_alt_bundle_array_size +xen_alt_bundle_array_size: + .long xen_alt_bundle_array_end - xen_alt_bundle_array_start + + +#define PARAVIRT_ALT_INST_ELEM(name, type) \ + data8 xen_ ## name ## _stag ; \ + data8 xen_ ## name ## _etag ; \ + data8 type + + __INITDATA_OR_MODULE + .align 8 + .global xen_alt_inst_array +xen_alt_inst_array: +xen_alt_inst_array_start: + PARAVIRT_ALT_INST_ELEM(rfi, PARAVIRT_INST_RFI) + PARAVIRT_ALT_INST_ELEM(rsm_psr_dt, PARAVIRT_INST_RSM_DT) + PARAVIRT_ALT_INST_ELEM(ssm_psr_dt, PARAVIRT_INST_SSM_DT) + PARAVIRT_ALT_INST_ELEM(cover, PARAVIRT_INST_COVER) + PARAVIRT_ALT_INST_ELEM(itc_d, PARAVIRT_INST_ITC_D) + PARAVIRT_ALT_INST_ELEM(itc_i, PARAVIRT_INST_ITC_I) + PARAVIRT_ALT_INST_ELEM(ssm_i, PARAVIRT_INST_SSM_I) + PARAVIRT_ALT_INST_ELEM(get_ivr, PARAVIRT_INST_GET_IVR) + PARAVIRT_ALT_INST_ELEM(get_tpr, PARAVIRT_INST_GET_TPR) + PARAVIRT_ALT_INST_ELEM(set_tpr, PARAVIRT_INST_SET_TPR) + PARAVIRT_ALT_INST_ELEM(eoi, PARAVIRT_INST_EOI) + PARAVIRT_ALT_INST_ELEM(set_itm, PARAVIRT_INST_SET_ITM) + PARAVIRT_ALT_INST_ELEM(thash, PARAVIRT_INST_THASH) + PARAVIRT_ALT_INST_ELEM(ptc_ga, PARAVIRT_INST_PTC_GA) + PARAVIRT_ALT_INST_ELEM(itr_d, PARAVIRT_INST_ITR_D) + PARAVIRT_ALT_INST_ELEM(get_rr, PARAVIRT_INST_GET_RR) + PARAVIRT_ALT_INST_ELEM(set_rr, PARAVIRT_INST_SET_RR) + PARAVIRT_ALT_INST_ELEM(set_kr, PARAVIRT_INST_SET_KR) + PARAVIRT_ALT_INST_ELEM(fc, PARAVIRT_INST_FC) + PARAVIRT_ALT_INST_ELEM(get_cpuid, PARAVIRT_INST_GET_CPUID) + PARAVIRT_ALT_INST_ELEM(get_pmd, PARAVIRT_INST_GET_PMD) + PARAVIRT_ALT_INST_ELEM(get_eflag, PARAVIRT_INST_GET_EFLAG) + PARAVIRT_ALT_INST_ELEM(set_eflag, PARAVIRT_INST_SET_EFLAG) + PARAVIRT_ALT_INST_ELEM(get_psr, PARAVIRT_INST_GET_PSR) + PARAVIRT_ALT_INST_ELEM(set_rr0_to_rr4, PARAVIRT_INST_SET_RR0_TO_RR4) + + PARAVIRT_ALT_INST_ELEM(ssm_i, PARAVIRT_BNDL_SSM_I) + PARAVIRT_ALT_INST_ELEM(rsm_i, PARAVIRT_BNDL_RSM_I) + PARAVIRT_ALT_INST_ELEM(get_psr_i, PARAVIRT_BNDL_GET_PSR_I) + PARAVIRT_ALT_INST_ELEM(intrin_local_irq_restore, + PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE) +xen_alt_inst_array_end: + + .align 8 + .global xen_alt_inst_array_size +xen_alt_inst_array_size: + .long xen_alt_inst_array_end - xen_alt_inst_array_start diff --git a/arch/ia64/xen/privops_c.c b/arch/ia64/xen/privops_c.c new file mode 100644 index 0000000..0fa2e23 --- /dev/null +++ b/arch/ia64/xen/privops_c.c @@ -0,0 +1,279 @@ +/****************************************************************************** + * arch/ia64/xen/privops_c.c + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * 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 <linux/linkage.h> +#include <linux/init.h> +#include <linux/module.h> + +#include <xen/interface/xen.h> + +#include <asm/asm-offsets.h> +#define XEN_PSR_I_ADDR_ADDR ((uint8_t **)(XSI_BASE + XSI_PSR_I_ADDR_OFS)) + + +void __init_or_module +xen_privop_ssm_i(void) +{ + /* + * int masked = !xen_get_virtual_psr_i(); + * // masked = *(*XEN_MAPPEDREGS->interrupt_mask_addr) + * xen_set_virtual_psr_i(1) + * // *(*XEN_MAPPEDREGS->interrupt_mask_addr) = 0 + * // compiler barrier + * if (masked) { + * uint8_t* pend_int_addr = + * (uint8_t*)(*XEN_MAPPEDREGS->interrupt_mask_addr) - 1; + * uint8_t pending = *pend_int_addr; + * if (pending) + * XEN_HYPER_SSM_I + * } + */ + register uint8_t *tmp asm ("r8"); + register int masked asm ("r9"); + register uint8_t *pending_intr_addr asm ("r10"); + + asm volatile(".global xen_ssm_i_instr\n\t" + "xen_ssm_i_instr:\n\t" + ".global xen_ssm_i_instr_start\n\t" + "xen_ssm_i_instr_start:\n\t" + ".global xen_ssm_i_stag\n\t" + "[xen_ssm_i_stag:]\n\t" + /* tmp = &XEN_MAPPEDREGS->interrupt_mask_addr */ + "mov %[tmp]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t" + ";;\n\t" + /* tmp = *XEN_MAPPEDREGS->interrupt_mask_addr */ + "ld8 %[tmp]=[%[tmp]]\n\t" + ";;\n\t" + /* pending_intr_addr = tmp - 1 */ + "add %[pending_intr_addr]=-1,%[tmp]\n\t" + /* masked = *tmp */ + "ld1 %[masked]=[%[tmp]]\n\t" + ";;\n\t" + /* *tmp = 0 */ + "st1 [%[tmp]]=r0\n\t" + /* p6 = !masked */ + "cmp.ne.unc p6,p0=%[masked],r0\n\t" + ";;\n\t" + /* tmp = *pending_intr_addr */ + "(p6) ld1 %[tmp]=[%[pending_intr_addr]]\n\t" + ";;\n\t" + /* p7 = p6 && !tmp */ + "(p6) cmp.ne.unc p7,p0=%[tmp],r0\n\t" + ";;\n\t" + "(p7) break %[HYPERPRIVOP_SSM_I_IMM]\n\t" + ".global xen_ssm_i_etag\n\t" + "[xen_ssm_i_etag:]\n\t" + ".global xen_ssm_i_instr_end\n\t" + "xen_ssm_i_instr_end:\n\t" + : + [tmp] "=r"(tmp), + [pending_intr_addr] "=r"(pending_intr_addr), + [masked] "=r"(masked), + + "=m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)) + : + [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR), + [HYPERPRIVOP_SSM_I_IMM] "i"(HYPERPRIVOP_SSM_I), + + "m"(*((uint8_t *)XEN_PSR_I_ADDR_ADDR)), + "m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)), + "m"(*(*((uint8_t **)XEN_PSR_I_ADDR_ADDR) - 1)) + : + "memory", + /* + * predicate registers can't be specified as C variables + * so that we use p6, p7, p8 here. + */ + "p6", /* is_old */ + "p7" /* is_pending */ + ); +} + +void __init_or_module +xen_privop_rsm_i(void) +{ + /* + * psr_i_addr_addr = XEN_MAPPEDREGS->interrupt_mask_addr + * = XEN_PSR_I_ADDR_ADDR; + * psr_i_addr = *psr_i_addr_addr; + * *psr_i_addr = 1; + */ + register unsigned long psr_i_addr asm("r8"); + register uint8_t mask asm ("r9"); + asm volatile (".global xen_rsm_i_instr\n\t" + "xen_rsm_i_instr:\n\t" + ".global xen_rsm_i_instr_start\n\t" + "xen_rsm_i_instr_start:\n\t" + ".global xen_rsm_i_stag\n\t" + "[xen_rsm_i_stag:]\n\t" + "mov %[psr_i_addr]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t" + "mov %[mask]=%[ONE_IMM]\n\t" + ";;\n\t" + "ld8 %[psr_i_addr]=[%[psr_i_addr]]\n\t" + ";;\n\t" + "st1 [%[psr_i_addr]]=%[mask]\n\t" + ".global xen_rsm_i_etag\n\t" + "[xen_rsm_i_etag:]\n\t" + ".global xen_rsm_i_instr_end\n\t" + "xen_rsm_i_instr_end:\n\t" + : + [psr_i_addr] "=r"(psr_i_addr), + [mask] "=r"(mask), + "=m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)): + [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR), + [ONE_IMM] "i"(1), + "m"(*((uint8_t **)XEN_PSR_I_ADDR_ADDR)): + "memory"); +} + +void __init_or_module +xen_privop_ia64_intrin_local_irq_restore(unsigned long val) +{ + /* + * psr_i_addr_addr = XEN_PSR_I_ADDR_ADDR + * psr_i_addr = *psr_i_addr_addr + * pending_intr_addr = psr_i_addr - 1 + * if (val & IA64_PSR_I) { + * masked = *psr_i_addr + * *psr_i_addr = 0 + * compiler barrier + * if (masked) { + * uint8_t pending = *pending_intr_addr; + * if (pending) + * XEN_HYPER_SSM_I + * } + * } else { + * *psr_i_addr = 1 + * } + */ + + register unsigned long __val asm("r8") = val; + register uint8_t *psr_i_addr asm ("r9"); + register uint8_t *pending_intr_addr asm ("r10"); + register uint8_t masked asm ("r11"); + register unsigned long one_or_pending asm ("r8"); + + asm volatile ( + ".global xen_intrin_local_irq_restore_instr\n\t" + "xen_intrin_local_irq_restore_instr:\n\t" + ".global xen_intrin_local_irq_restore_instr_start\n\t" + "xen_intrin_local_irq_restore_instr_start:\n\t" + ".global xen_intrin_local_irq_restore_stag\n\t" + "[xen_intrin_local_irq_restore_stag:]\n\t" + "tbit.nz p6,p7=%[val],%[IA64_PSR_I_BIT_IMM]\n\t" + "mov %[psr_i_addr]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t" + ";;\n\t" + "ld8 %[psr_i_addr]=[%[psr_i_addr]]\n\t" + "(p7)mov %[one_or_pending]=%[ONE_IMM]\n\t" + ";;\n\t" + "add %[pending_intr_addr]=-1,%[psr_i_addr]\n\t" + ";;\n\t" + "(p6) ld1 %[masked]=[%[psr_i_addr]]\n\t" + "(p7) st1 [%[psr_i_addr]]=%[one_or_pending]\n\t" + ";;\n\t" + "(p6) st1 [%[psr_i_addr]]=r0\n\t" + "(p6) cmp.ne.unc p8,p0=%[masked],r0\n\t" + "(p6) ld1 %[one_or_pending]=[%[pending_intr_addr]]\n\t" + ";;\n\t" + "(p8) cmp.eq.unc p9,p0=%[one_or_pending],r0\n\t" + ";;\n\t" + "(p9) break %[HYPERPRIVOP_SSM_I_IMM]\n\t" + ".global xen_intrin_local_irq_restore_etag\n\t" + "[xen_intrin_local_irq_restore_etag:]\n\t" + ".global xen_intrin_local_irq_restore_instr_end\n\t" + "xen_intrin_local_irq_restore_instr_end:\n\t" + : + [psr_i_addr] "=r"(psr_i_addr), + [pending_intr_addr] "=r"(pending_intr_addr), + [masked] "=r"(masked), + [one_or_pending] "=r"(one_or_pending), + + "=m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)) + : + [val] "r"(__val), + [IA64_PSR_I_BIT_IMM] "i"(IA64_PSR_I_BIT), + [ONE_IMM] "i"(1), + + [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR), + [HYPERPRIVOP_SSM_I_IMM] "i"(HYPERPRIVOP_SSM_I), + + "m"(*((uint8_t *)XEN_PSR_I_ADDR_ADDR)), + "m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)), + "m"(*(*((uint8_t **)XEN_PSR_I_ADDR_ADDR) - 1)) + : + "memory", + "p6", /* is_psr_i_set */ + "p7", /* not_psr_i_set */ + "p8", /* is_masked && is_psr_i_set */ + "p9" /* is_pending && is_masked && is_psr_i_set */ + ); +} + +unsigned long __init_or_module +xen_privop_get_psr_i(void) +{ + /* + * tmp = XEN_MAPPEDREGS->interrupt_mask_addr = XEN_PSR_I_ADDR_ADDR; + * tmp = *tmp + * tmp = *tmp; + * psr_i = tmp? 0: IA64_PSR_I; + */ + register unsigned long psr_i asm ("r8"); + register unsigned long tmp asm ("r9"); + + asm volatile (".global xen_get_psr_i_instr\n\t" + "xen_get_psr_i_instr:\n\t" + ".global xen_get_psr_i_instr_start\n\t" + "xen_get_psr_i_instr_start:\n\t" + ".global xen_get_psr_i_stag\n\t" + "[xen_get_psr_i_stag:]\n\t" + /* tmp = XEN_PSR_I_ADDR_ADDR */ + "mov %[tmp]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t" + ";;\n\t" + /* tmp = *tmp = *XEN_PSR_I_ADDR_ADDR */ + "ld8 %[tmp]=[%[tmp]]\n\t" + /* psr_i = 0 */ + "mov %[psr_i]=0\n\t" + ";;\n\t" + /* tmp = *(uint8_t*)tmp */ + "ld1 %[tmp]=[%[tmp]]\n\t" + ";;\n\t" + /* if (!tmp) psr_i = IA64_PSR_I */ + "cmp.eq.unc p6,p0=%[tmp],r0\n\t" + ";;\n\t" + "(p6) mov %[psr_i]=%[IA64_PSR_I_IMM]\n\t" + ".global xen_get_psr_i_etag\n\t" + "[xen_get_psr_i_etag:]\n\t" + ".global xen_get_psr_i_instr_end\n\t" + "xen_get_psr_i_instr_end:\n\t" + : + [tmp] "=r"(tmp), + [psr_i] "=r"(psr_i) + : + [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR), + [IA64_PSR_I_IMM] "i"(IA64_PSR_I), + "m"(*((uint8_t **)XEN_PSR_I_ADDR_ADDR)), + "m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)) + : + "p6"); + return psr_i; +} diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S index 17ad297..2d3d5d4 100644 --- a/arch/ia64/xen/xensetup.S +++ b/arch/ia64/xen/xensetup.S @@ -35,6 +35,16 @@ GLOBAL_ENTRY(early_xen_setup) (isBP) movl r28=XSI_BASE;; (isBP) break 0x1000;; +#ifdef CONFIG_PARAVIRT + /* patch privops */ +(isBP) mov r4=rp + ;; +(isBP) br.call.sptk.many rp=xen_paravirt_patch + ;; +(isBP) mov rp=r4 + ;; +#endif + br.ret.sptk.many rp ;; END(early_xen_setup) diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h index 8261dad..fcca3f4 100644 --- a/include/asm-ia64/privop.h +++ b/include/asm-ia64/privop.h @@ -10,6 +10,10 @@ * */ +#ifdef CONFIG_PARAVIRT +#include <asm/privop_paravirt.h> +#endif + #ifdef CONFIG_XEN #include <asm/xen/privop.h> #endif diff --git a/include/asm-ia64/privop_paravirt.h b/include/asm-ia64/privop_paravirt.h new file mode 100644 index 0000000..00e4f03 --- /dev/null +++ b/include/asm-ia64/privop_paravirt.h @@ -0,0 +1,587 @@ +/****************************************************************************** + * privops_paravirt.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * 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_IA64_PRIVOP_PARAVIRT_H +#define _ASM_IA64_PRIVOP_PARAVIRT_H + +#define PARAVIRT_INST_START 0x1 +#define PARAVIRT_INST_RFI (PARAVIRT_INST_START + 0x0) +#define PARAVIRT_INST_RSM_DT (PARAVIRT_INST_START + 0x1) +#define PARAVIRT_INST_SSM_DT (PARAVIRT_INST_START + 0x2) +#define PARAVIRT_INST_COVER (PARAVIRT_INST_START + 0x3) +#define PARAVIRT_INST_ITC_D (PARAVIRT_INST_START + 0x4) +#define PARAVIRT_INST_ITC_I (PARAVIRT_INST_START + 0x5) +#define PARAVIRT_INST_SSM_I (PARAVIRT_INST_START + 0x6) +#define PARAVIRT_INST_GET_IVR (PARAVIRT_INST_START + 0x7) +#define PARAVIRT_INST_GET_TPR (PARAVIRT_INST_START + 0x8) +#define PARAVIRT_INST_SET_TPR (PARAVIRT_INST_START + 0x9) +#define PARAVIRT_INST_EOI (PARAVIRT_INST_START + 0xa) +#define PARAVIRT_INST_SET_ITM (PARAVIRT_INST_START + 0xb) +#define PARAVIRT_INST_THASH (PARAVIRT_INST_START + 0xc) +#define PARAVIRT_INST_PTC_GA (PARAVIRT_INST_START + 0xd) +#define PARAVIRT_INST_ITR_D (PARAVIRT_INST_START + 0xe) +#define PARAVIRT_INST_GET_RR (PARAVIRT_INST_START + 0xf) +#define PARAVIRT_INST_SET_RR (PARAVIRT_INST_START + 0x10) +#define PARAVIRT_INST_SET_KR (PARAVIRT_INST_START + 0x11) +#define PARAVIRT_INST_FC (PARAVIRT_INST_START + 0x12) +#define PARAVIRT_INST_GET_CPUID (PARAVIRT_INST_START + 0x13) +#define PARAVIRT_INST_GET_PMD (PARAVIRT_INST_START + 0x14) +#define PARAVIRT_INST_GET_EFLAG (PARAVIRT_INST_START + 0x15) +#define PARAVIRT_INST_SET_EFLAG (PARAVIRT_INST_START + 0x16) +#define PARAVIRT_INST_RSM_BE (PARAVIRT_INST_START + 0x17) +#define PARAVIRT_INST_GET_PSR (PARAVIRT_INST_START + 0x18) +#define PARAVIRT_INST_SET_RR0_TO_RR4 (PARAVIRT_INST_START + 0x19) + +#define PARAVIRT_BNDL_START 0x10000000 +#define PARAVIRT_BNDL_SSM_I (PARAVIRT_BNDL_START + 0x0) +#define PARAVIRT_BNDL_RSM_I (PARAVIRT_BNDL_START + 0x1) +#define PARAVIRT_BNDL_GET_PSR_I (PARAVIRT_BNDL_START + 0x2) +#define PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE (PARAVIRT_BNDL_START + 0x3) + +/* + * struct task_struct* (*ia64_switch_to)(void* next_task); + * void *ia64_leave_syscall; + * void *ia64_work_processed_syscall + * void *ia64_leave_kernel; + * struct ia64_pal_retval (*pal_call_static)(u64, u64, u64, u64, u64); + */ + +#define PARAVIRT_ENTRY_START 0x20000000 +#define PARAVIRT_ENTRY_SWITCH_TO (PARAVIRT_ENTRY_START + 0) +#define PARAVIRT_ENTRY_LEAVE_SYSCALL (PARAVIRT_ENTRY_START + 1) +#define PARAVIRT_ENTRY_WORK_PROCESSED_SYSCALL (PARAVIRT_ENTRY_START + 2) +#define PARAVIRT_ENTRY_LEAVE_KERNEL (PARAVIRT_ENTRY_START + 3) +#define PARAVIRT_ENTRY_PAL_CALL_STATIC (PARAVIRT_ENTRY_START + 4) + + +#ifndef __ASSEMBLER__ + +#include <linux/stringify.h> +#include <linux/types.h> +#include <asm/paravirt_alt.h> +#include <asm/kregs.h> /* for IA64_PSR_I */ +#include <asm/xen/interface.h> + +/************************************************/ +/* 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!) */ +#ifdef ASM_SUPPORTED +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_inst("fc %1", PARAVIRT_INST_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_inst("thash %0=%1", PARAVIRT_INST_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_inst("mov %0=cpuid[%r1]", + PARAVIRT_INST_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_inst("mov %0=pmd[%1]", + PARAVIRT_INST_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_inst("mov %0=ar%1", + PARAVIRT_INST_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_inst("mov ar%0=%1", + PARAVIRT_INST_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_inst("mov %0=psr", PARAVIRT_INST_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_inst("mov %0=cr%1", PARAVIRT_INST_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_inst("mov %0=cr%1", PARAVIRT_INST_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_inst("mov cr%0=%1", PARAVIRT_INST_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_inst("mov cr%0=%1", PARAVIRT_INST_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_inst("mov cr%0=%1", PARAVIRT_INST_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_inst("ptc.ga %0,%1", PARAVIRT_INST_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_inst("mov %0=rr[%1]", PARAVIRT_INST_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_inst("mov rr[%0]=%1", PARAVIRT_INST_SET_RR):: + "r"(__index), "r"(__val): "memory"); +} + +static inline void +paravirt_set_rr0_to_rr4(unsigned long val0, unsigned long val1, + unsigned long val2, unsigned long val3, + unsigned long val4) +{ + register __u64 __val0 asm ("r8") = val0; + register __u64 __val1 asm ("r9") = val1; + register __u64 __val2 asm ("r10") = val2; + register __u64 __val3 asm ("r11") = val3; + register __u64 __val4 asm ("r14") = val4; + asm volatile (paravirt_alt_inst("\t;;\n" + "\t{.mmi\n" + "\tmov rr[%0]=%1\n" + /* + * without this stop bit + * assembler complains. + */ + "\t;;\n" + "\tmov rr[%2]=%3\n" + "\tnop.i 0\n" + "\t}\n" + "\t{.mmi\n" + "\tmov rr[%4]=%5\n" + "\tmov rr[%6]=%7\n" + "\tnop.i 0\n" + "\t}\n" + "\tmov rr[%8]=%9;;\n", + PARAVIRT_INST_SET_RR0_TO_RR4):: + "r"(0x0000000000000000UL), "r"(__val0), + "r"(0x2000000000000000UL), "r"(__val1), + "r"(0x4000000000000000UL), "r"(__val2), + "r"(0x6000000000000000UL), "r"(__val3), + "r"(0x8000000000000000UL), "r"(__val4) : + "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"(PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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_inst("mov ar%0=%2", + PARAVIRT_INST_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; + } + } +} +#endif /* ASM_SUPPORTED */ + +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; + } +} + +#ifdef ASM_SUPPORTED + +#define NOP_BUNDLE \ + "{\n\t" \ + "nop 0\n\t" \ + "nop 0\n\t" \ + "nop 0\n\t" \ + "}\n\t" + +static inline void +paravirt_ssm_i(void) +{ + /* five bundles */ + asm volatile (paravirt_alt_bundle("{\n\t" + "ssm psr.i\n\t" + "nop 0\n\t" + "nop 0\n\t" + "}\n\t" + NOP_BUNDLE + NOP_BUNDLE + NOP_BUNDLE + NOP_BUNDLE, + PARAVIRT_BNDL_SSM_I)::: + "r8", "r9", "r10", + "p6", "p7", + "memory"); +} + +static inline void +paravirt_rsm_i(void) +{ + /* two budles */ + asm volatile (paravirt_alt_bundle("{\n\t" + "rsm psr.i\n\t" + "nop 0\n\t" + "nop 0\n\t" + "}\n\t" + NOP_BUNDLE, + PARAVIRT_BNDL_RSM_I)::: + "r8", "r9", + "memory"); +} + +static inline unsigned long +paravirt_get_psr_i(void) +{ + register unsigned long psr_i asm ("r8"); + register unsigned long mask asm ("r9"); + + /* three bundles */ + asm volatile (paravirt_alt_bundle("{\n\t" + "mov %0=psr\n\t" + "mov %1=%2\n\t" + ";;\n\t" + "and %0=%0,%1\n\t" + "}\n\t" + NOP_BUNDLE + NOP_BUNDLE, + PARAVIRT_BNDL_GET_PSR_I): + "=r"(psr_i), + "=r"(mask) + : + "i"(IA64_PSR_I) + : + /* "r8", "r9", */ + "p6"); + return psr_i; +} + +static inline void +paravirt_intrin_local_irq_restore(unsigned long flags) +{ + register unsigned long __flags asm ("r8") = flags; + + /* six bundles */ + asm volatile (paravirt_alt_bundle(";;\n\t" + "{\n\t" + "cmp.ne p6,p7=%0,r0;;\n\t" + "(p6) ssm psr.i;\n\t" + "nop 0\n\t" + "}\n\t" + "{\n\t" + "(p7) rsm psr.i;;\n\t" + "(p6) srlz.d\n\t" + "nop 0\n\t" + "}\n\t" + NOP_BUNDLE + NOP_BUNDLE + NOP_BUNDLE + NOP_BUNDLE, + PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE):: + "r"(__flags) : + /* "r8",*/ "r9", "r10", "r11", + "p6", "p7", "p8", "p9", + "memory"); + +} + +#undef NOP_BUNDLE + +#endif /* ASM_SUPPORTED */ + +static inline void +paravirt_ssm(unsigned long mask) +{ + if (mask == IA64_PSR_I) + paravirt_ssm_i(); + else + __ia64_ssm(mask); +} + +static inline void +paravirt_rsm(unsigned long mask) +{ + if (mask == IA64_PSR_I) + paravirt_rsm_i(); + else + __ia64_rsm(mask); +} + +#if defined(ASM_SUPPORTED) && defined(CONFIG_PARAVIRT_ALT) + +#define IA64_PARAVIRTUALIZED_PRIVOP + +#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)) +#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \ + paravirt_set_rr0_to_rr4((val0), (val1), (val2), (val3), (val4)) + +#define ia64_ssm(mask) paravirt_ssm(mask) +#define ia64_rsm(mask) paravirt_rsm(mask) +#define ia64_get_psr_i() paravirt_get_psr_i() +#define ia64_intrin_local_irq_restore(x) \ + paravirt_intrin_local_irq_restore(x) + +/* the remainder of these are not performance-sensitive so its + * OK to not paravirtualize and just take a privop trap and emulate */ +#define ia64_hint __ia64_hint +#define ia64_set_pmd __ia64_set_pmd +#define ia64_itci __ia64_itci +#define ia64_itcd __ia64_itcd +#define ia64_itri __ia64_itri +#define ia64_itrd __ia64_itrd +#define ia64_tpa __ia64_tpa +#define ia64_set_ibr __ia64_set_ibr +#define ia64_set_pkr __ia64_set_pkr +#define ia64_set_pmc __ia64_set_pmc +#define ia64_get_ibr __ia64_get_ibr +#define ia64_get_pkr __ia64_get_pkr +#define ia64_get_pmc __ia64_get_pmc +#define ia64_ptce __ia64_ptce +#define ia64_ptcl __ia64_ptcl +#define ia64_ptri __ia64_ptri +#define ia64_ptrd __ia64_ptrd + +#endif /* ASM_SUPPORTED && CONFIG_PARAVIRT_ALT */ + +#endif /* __ASSEMBLER__*/ + +/* these routines utilize privilege-sensitive or performance-sensitive + * privileged instructions so the code must be replaced with + * paravirtualized versions */ +#ifdef CONFIG_PARAVIRT_ENTRY +#define IA64_PARAVIRTUALIZED_ENTRY +#define ia64_switch_to paravirt_switch_to +#define ia64_work_processed_syscall paravirt_work_processed_syscall +#define ia64_leave_syscall paravirt_leave_syscall +#define ia64_leave_kernel paravirt_leave_kernel +#define ia64_pal_call_static paravirt_pal_call_static +#endif /* CONFIG_PARAVIRT_ENTRY */ + +#endif /* _ASM_IA64_PRIVOP_PARAVIRT_H */ diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h index 3caa7e9..2c70988 100644 --- a/include/asm-ia64/xen/privop.h +++ b/include/asm-ia64/xen/privop.h @@ -557,6 +557,18 @@ do { \ #endif /* ASM_SUPPORTED && !CONFIG_PARAVIRT_ALT */ +#ifdef CONFIG_PARAVIRT_ALT +#if defined(CONFIG_MODULES) && defined(CONFIG_XEN) +void xen_alt_bundle_patch_module(struct paravirt_alt_bundle_patch *start, + struct paravirt_alt_bundle_patch *end); +void xen_alt_inst_patch_module(struct paravirt_alt_inst_patch *start, + struct paravirt_alt_inst_patch *end); +#else +#define xen_alt_bundle_patch_module(start, end) do { } while (0) +#define xen_alt_inst_patch_module(start, end) do { } while (0) +#endif +#endif /* CONFIG_PARAVIRT_ALT */ + #endif /* !__ASSEMBLY__ */ /* these routines utilize privilege-sensitive or performance-sensitive @@ -573,12 +585,24 @@ do { \ #ifdef CONFIG_XEN #ifdef __ASSEMBLY__ +#ifdef CONFIG_PARAVIRT_ENTRY +#define BR_IF_NATIVE(target, reg_unused, pred_unused) /* nothing */ +#elif defined(CONFIG_PARAVIRT_NOP_B_PATCH) +#define BR_IF_NATIVE(target, reg_unused, pred_unused) \ + .body ; \ + [1:] ; \ + br.cond.sptk.many target;; ; \ + .section .paravirt_nop_b, "a" ; \ + .previous ; \ + .xdata8 ".paravirt_nop_b", 1b +#else #define BR_IF_NATIVE(target, reg, pred) \ .body ; \ movl reg=running_on_xen;; ; \ ld4 reg=[reg];; ; \ cmp.eq pred,p0=reg,r0 ; \ (pred) br.cond.sptk.many target;; +#endif #endif /* __ASSEMBLY__ */ #endif -- 1.5.3 -- yamahata |