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: Akio T. <tak...@jp...> - 2008-02-01 03:59:08
|
Hi, Xiantao >+void thash_vhpt_insert(VCPU *v, u64 pte, u64 itir, u64 va, int type) >+{ >+ u64 phy_pte, psr; >+ ia64_rr mrr; >+ >+ mrr.val = ia64_get_rr(va); >+ phy_pte = translate_phy_pte(&pte, itir, va); >+ >+ if (itir_ps(itir) >= mrr.ps) { >+ vhpt_insert(phy_pte, itir, va, pte); >+ } else { >+ phy_pte &= ~PAGE_FLAGS_RV_MASK; >+ psr = ia64_clear_ic(); >+ ia64_itc(type, va, phy_pte, itir_ps(itir)); >+ ia64_set_psr(psr); >+ ia64_srlz_i(); >+ } >+} You add ia64_srlz_i() into ia64_set_psr() with [02]patch. So is this a redundancy if the patch is applied? >+ */ >+int thash_purge_and_insert(VCPU *v, u64 pte, u64 itir, u64 ifa, int >type) >+{ >+ u64 ps; >+ u64 phy_pte; >+ ia64_rr vrr, mrr; >+ int ret = 0; >+ >+ ps = itir_ps(itir); >+ vrr.val = vcpu_get_rr(v, ifa); >+ mrr.val = ia64_get_rr(ifa); >+ >+ phy_pte = translate_phy_pte(&pte, itir, ifa); >+ >+ /* Ensure WB attribute if pte is related to a normal mem page, >+ * which is required by vga acceleration since qemu maps shared >+ * vram buffer with WB. >+ */ >+ if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) != >_PAGE_MA_NAT)) { >+ pte &= ~_PAGE_MA_MASK; >+ phy_pte &= ~_PAGE_MA_MASK; >+ } >+ >+ if (pte & VTLB_PTE_IO) >+ ret = 1; >+ >+ vtlb_purge(v, ifa, ps); >+ vhpt_purge(v, ifa, ps); >+ >+ if (ps == mrr.ps) { >+ if (!(pte&VTLB_PTE_IO)) { >+ vhpt_insert(phy_pte, itir, ifa, pte); >+ } else { >+ vtlb_insert(v, pte, itir, ifa); >+ vcpu_quick_region_set(VMX(v, tc_regions), ifa); >+ } >+ } else if (ps > mrr.ps) { >+ vtlb_insert(v, pte, itir, ifa); >+ vcpu_quick_region_set(VMX(v, tc_regions), ifa); >+ if (!(pte&VTLB_PTE_IO)) >+ vhpt_insert(phy_pte, itir, ifa, pte); >+ } else { >+ u64 psr; >+ phy_pte &= ~PAGE_FLAGS_RV_MASK; >+ psr = ia64_clear_ic(); >+ ia64_itc(type, ifa, phy_pte, ps); >+ ia64_set_psr(psr); >+ ia64_srlz_i(); >+ } >+ >+ return ret; >+} ditto Best Regards, Akio Takebe |
From: Akio T. <tak...@jp...> - 2008-02-01 03:58:39
|
Hi, Xiantao >> Why do you remove ia64_srlz_d()? >> We should need srlz.d if we change PSR bits(e.g. PSR.dt and so on). >> Does srlz.i do also date serialization? >Hi, Akio >Srlz.i implicitly ensures srlz.d per SDM. OK, thanks. Best Regards, Akio Takebe |
From: Zhang, X. <xia...@in...> - 2008-02-01 03:38:14
|
Akio Takebe wrote: > Hi, Xiantao >=20 >> void __init >> diff --git a/include/asm-ia64/processor.h >> b/include/asm-ia64/processor.h index be3b0ae..038642f 100644 --- >> a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h >> @@ -472,7 +472,7 @@ ia64_set_psr (__u64 psr) >> { >> ia64_stop(); >> ia64_setreg(_IA64_REG_PSR_L, psr); >> - ia64_srlz_d(); >> + ia64_srlz_i(); >> } > Why do you remove ia64_srlz_d()? > We should need srlz.d if we change PSR bits(e.g. PSR.dt and so on). > Does srlz.i do also date serialization? Hi, Akio Srlz.i implicitly ensures srlz.d per SDM. =20 Thanks Xiantao |
From: Akio T. <tak...@jp...> - 2008-02-01 02:48:54
|
Hi, Xiantao > void __init >diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h >index be3b0ae..038642f 100644 >--- a/include/asm-ia64/processor.h >+++ b/include/asm-ia64/processor.h >@@ -472,7 +472,7 @@ ia64_set_psr (__u64 psr) > { > ia64_stop(); > ia64_setreg(_IA64_REG_PSR_L, psr); >- ia64_srlz_d(); >+ ia64_srlz_i(); > } Why do you remove ia64_srlz_d()? We should need srlz.d if we change PSR bits(e.g. PSR.dt and so on). Does srlz.i do also date serialization? Best Regards, Akio Takebe |
From: Zhang, X. <xia...@in...> - 2008-02-01 02:44:17
|
Scott Pakin wrote: > Zhang, Xiantao wrote: >> Scott Pakin wrote: >>> The attached patch corrects a bug in qemu/slirp/tcp_var.h that >>> defines the seg_next field in struct tcpcb to be 32 bits wide >>> regardless of 32/64-bitness. seg_next is assigned a pointer value >>> in qemu/slirp/tcp_subr.c, then cast back to a pointer in >>> qemu/slirp/tcp_input.c and dereferenced. That produces a SIGSEGV on >>> my system. >>=20 >>=20 >> I still hit it on IA64 platform with your patch, once configured with >> slirp. Scott With the enhanced patch, IA64 guests works well. Great!! If this fix be picked up, we can remove the configure option which excludes slirp compile for kvm/ia64.=20 Thanks! Xiantao |
From: Zhang, X. <xia...@in...> - 2008-02-01 01:39:23
|
Blue Swirl wrote: > On 1/30/08, Scott Pakin <pa...@la...> wrote: >> Zhang, Xiantao wrote: >>> Scott Pakin wrote: >>>> The attached patch corrects a bug in qemu/slirp/tcp_var.h that >>>> defines the seg_next field in struct tcpcb to be 32 bits wide >>>> regardless of 32/64-bitness. seg_next is assigned a pointer value >>>> in qemu/slirp/tcp_subr.c, then cast back to a pointer in >>>> qemu/slirp/tcp_input.c and dereferenced. That produces a SIGSEGV >>>> on my system. >>>=20 >>>=20 >>> I still hit it on IA64 platform with your patch, once configured >>> with slirp. >>=20 >> Okay, here's a more thorough patch that fixes *all* of the "cast >> from/to pointer to/from integer of a different size" mistakes that >> gcc warns about. Does it also solve the SIGSEGV problem on IA64? >=20 > The SLIRP code is much, much more subtle than that. Please see this > thread: > http://lists.gnu.org/archive/html/qemu-devel/2007-10/msg00542.html=20 Got it. Thank you!=20 Xiantao |
From: Scott P. <pa...@la...> - 2008-02-01 01:37:29
|
I just noticed that my previous patch hit one of the subtleties that Blue Swirl warned about. Changing caddr32_t causes the IP header and IP header overlay to be different sizes, which essentially breaks networking altogether. I humbly offer the following patch, which fixes only the "easy" 32/64-bit bugs but leaves the tricky 32/64-bit bugs in the IP header processing intact for someone abler than I to fix. -- Scott ============= BEGIN tcp_int32_pointer_cast_no_caddr.patch ============== diff -Naur kvm-60-ORIG/qemu/exec-all.h kvm-60/qemu/exec-all.h --- kvm-60-ORIG/qemu/exec-all.h 2008-01-20 05:35:04.000000000 -0700 +++ kvm-60/qemu/exec-all.h 2008-01-31 17:36:34.000000000 -0700 @@ -169,7 +169,7 @@ #ifdef USE_DIRECT_JUMP uint16_t tb_jmp_offset[4]; /* offset of jump instruction */ #else - uint32_t tb_next[2]; /* address of jump generated code */ + uintptr_t tb_next[2]; /* address of jump generated code */ #endif /* list of TBs jumping to this one. This is a circular list using the two least significant bits of the pointers to tell what is diff -Naur kvm-60-ORIG/qemu/slirp/ip.h kvm-60/qemu/slirp/ip.h --- kvm-60-ORIG/qemu/slirp/ip.h 2008-01-20 05:35:04.000000000 -0700 +++ kvm-60/qemu/slirp/ip.h 2008-01-31 17:29:28.000000000 -0700 @@ -193,13 +193,8 @@ #endif #endif -#if SIZEOF_CHAR_P == 4 typedef struct ipq *ipqp_32; typedef struct ipasfrag *ipasfragp_32; -#else -typedef caddr32_t ipqp_32; -typedef caddr32_t ipasfragp_32; -#endif /* * Overlay for ip header used by other protocols (tcp, udp). diff -Naur kvm-60-ORIG/qemu/slirp/misc.c kvm-60/qemu/slirp/misc.c --- kvm-60-ORIG/qemu/slirp/misc.c 2008-01-20 05:35:04.000000000 -0700 +++ kvm-60/qemu/slirp/misc.c 2008-01-31 17:30:14.000000000 -0700 @@ -97,39 +97,6 @@ our_addr.s_addr = loopback_addr.s_addr; } -#if SIZEOF_CHAR_P == 8 - -struct quehead_32 { - u_int32_t qh_link; - u_int32_t qh_rlink; -}; - -inline void -insque_32(a, b) - void *a; - void *b; -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - register struct quehead_32 *head = (struct quehead_32 *) b; - element->qh_link = head->qh_link; - head->qh_link = (u_int32_t)element; - element->qh_rlink = (u_int32_t)head; - ((struct quehead_32 *)(element->qh_link))->qh_rlink - = (u_int32_t)element; -} - -inline void -remque_32(a) - void *a; -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; - ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link; - element->qh_rlink = 0; -} - -#endif /* SIZEOF_CHAR_P == 8 */ - struct quehead { struct quehead *qh_link; struct quehead *qh_rlink; diff -Naur kvm-60-ORIG/qemu/slirp/slirp.h kvm-60/qemu/slirp/slirp.h --- kvm-60-ORIG/qemu/slirp/slirp.h 2008-01-20 05:35:04.000000000 -0700 +++ kvm-60/qemu/slirp/slirp.h 2008-01-31 17:30:58.000000000 -0700 @@ -265,13 +265,8 @@ void lprint _P((const char *, ...)); -#if SIZEOF_CHAR_P == 4 -# define insque_32 insque -# define remque_32 remque -#else - inline void insque_32 _P((void *, void *)); - inline void remque_32 _P((void *)); -#endif +#define insque_32 insque +#define remque_32 remque #ifndef _WIN32 #include <netdb.h> diff -Naur kvm-60-ORIG/qemu/slirp/tcp_var.h kvm-60/qemu/slirp/tcp_var.h --- kvm-60-ORIG/qemu/slirp/tcp_var.h 2008-01-20 05:35:04.000000000 -0700 +++ kvm-60/qemu/slirp/tcp_var.h 2008-01-31 17:35:03.000000000 -0700 @@ -40,11 +40,7 @@ #include "tcpip.h" #include "tcp_timer.h" -#if SIZEOF_CHAR_P == 4 - typedef struct tcpiphdr *tcpiphdrp_32; -#else - typedef u_int32_t tcpiphdrp_32; -#endif +typedef struct tcpiphdr *tcpiphdrp_32; /* * Tcp control block, one per tcp; fields: @@ -178,11 +174,7 @@ * port numbers (which are no longer needed once we've located the * tcpcb) are overlayed with an mbuf pointer. */ -#if SIZEOF_CHAR_P == 4 typedef struct mbuf *mbufp_32; -#else -typedef u_int32_t mbufp_32; -#endif #define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) #ifdef LOG_ENABLED ============== END tcp_int32_pointer_cast_no_caddr.patch =============== |
From: Scott P. <pa...@la...> - 2008-01-31 18:38:36
|
Zhang, Xiantao wrote: > Unfortunately, it can's apply on tip. Could you attach the diff ? It works for me: $ git clone git://git.kernel.org/pub/scm/virt/kvm/kvm-userspace.git remote: Generating pack... remote: Done counting 37449 objects. remote: Deltifying 37449 objects... remote: 100% (37449/37449) done Indexing 37449 objects. remote: Total 37449 (delta 24712), reused 37189 (delta 24506) 100% (37449/37449) done Resolving 24712 deltas. 100% (24712/24712) done Checking files out... 100% (948/948) done $ cd kvm-userspace $ patch -p1 < ~/tcp_int32_pointer_cast.patch patching file qemu/exec-all.h patching file qemu/slirp/ip.h patching file qemu/slirp/misc.c patching file qemu/slirp/slirp.h patching file qemu/slirp/tcp_var.h $ -- Scott |
From: Avi K. <av...@qu...> - 2008-01-31 17:07:21
|
Zhang, Xiantao wrote: > Hi, Avi/Tony > We have rebased kvm/ia64 code to latest kvm. In this version, we > have fixed coding style issues, and all patches can pass checkpatch.pl, > except one assembly header file, which is copyied from kernel, so we > didn't change its issues. > Compared with last version, we implemented smp guest support, and > addressed two stability issues which only take on with smp guests. Now, > based on our own test results, it has good stability, and good > performance. Please review and help to commit them before linux 2.6.25 > merge :) > > I suggest that Tony review, signoff, and push these through the ia64 tree once kvm.git has been pulled (pull request was sent yesterday). Once that's in, incremental updates can go through kvm.git. I am simply not qualified to review ia64 code. -- error compiling committee.c: too many arguments to function |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:34:10
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:34:03 +0800 Subject: [PATCH] kvm/ia64: add processor virtulization support. vcpu.c provides processor virtualization logic. Signed-off-by: Anthony Xu <ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/vcpu.c | 2158 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 2158 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/vcpu.c diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c new file mode 100644 index 0000000..91a6f94 --- /dev/null +++ b/arch/ia64/kvm/vcpu.c @@ -0,0 +1,2158 @@ +/* + * kvm_vcpu.c: handling all virtual cpu related thing. + * Copyright (c) 2005, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Shaofan Li (Susue Li) <sus...@in...> + * Yaozu Dong (Eddie Dong) (Edd...@in...) + * Xuefei Xu (Anthony Xu) (Ant...@in...) + * Xiantao Zhang <xia...@in...> + */ + +#include <linux/kvm_host.h> + +#include <asm/types.h> +#include <asm/processor.h> +#include <asm/ia64regs.h> +#include <asm/gcc_intrin.h> +#include <asm/kregs.h> +#include <asm/pgtable.h> + + +#include "asm-offsets.h" +#include "vcpu.h" + +/* + * Special notes: + * - Index by it/dt/rt sequence + * - Only existing mode transitions are allowed in this table + * - RSE is placed at lazy mode when emulating guest partial mode + * - If gva happens to be rr0 and rr4, only allowed case is identity + * mapping (gva=3Dgpa), or panic! (How?) + */ +int mm_switch_table[8][8] =3D { + /* 2004/09/12(Kevin): Allow switch to self */ + /* + * (it,dt,rt): (0,0,0) -> (1,1,1) + * This kind of transition usually occurs in the very early + * stage of Linux boot up procedure. Another case is in efi + * and pal calls. (see "arch/ia64/kernel/head.S") + * + * (it,dt,rt): (0,0,0) -> (0,1,1) + * This kind of transition is found when OSYa exits efi boot + * service. Due to gva =3D gpa in this case (Same region), + * data access can be satisfied though itlb entry for physical + * emulation is hit. + */ + {SW_SELF, 0, 0, SW_NOP, 0, 0, 0, SW_P2V}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + /* + * (it,dt,rt): (0,1,1) -> (1,1,1) + * This kind of transition is found in OSYa. + * + * (it,dt,rt): (0,1,1) -> (0,0,0) + * This kind of transition is found in OSYa + */ + {SW_NOP, 0, 0, SW_SELF, 0, 0, 0, SW_P2V}, + /* (1,0,0)->(1,1,1) */ + {0, 0, 0, 0, 0, 0, 0, SW_P2V}, + /* + * (it,dt,rt): (1,0,1) -> (1,1,1) + * This kind of transition usually occurs when Linux returns + * from the low level TLB miss handlers. + * (see "arch/ia64/kernel/ivt.S") + */ + {0, 0, 0, 0, 0, SW_SELF, 0, SW_P2V}, + {0, 0, 0, 0, 0, 0, 0, 0}, + /* + * (it,dt,rt): (1,1,1) -> (1,0,1) + * This kind of transition usually occurs in Linux low level + * TLB miss handler. (see "arch/ia64/kernel/ivt.S") + * + * (it,dt,rt): (1,1,1) -> (0,0,0) + * This kind of transition usually occurs in pal and efi calls, + * which requires running in physical mode. + * (see "arch/ia64/kernel/head.S") + * (1,1,1)->(1,0,0) + */ + + {SW_V2P, 0, 0, 0, SW_V2P, SW_V2P, 0, SW_SELF}, +}; + +void physical_mode_init(VCPU *vcpu) +{ + vcpu->arch.mode_flags =3D GUEST_IN_PHY; +} + +extern void kvm_switch_rr6(unsigned long, void *, void *, void *); + + +void switch_to_physical_rid(VCPU *vcpu) +{ + unsigned long psr; + + /* Save original virtual mode rr[0] and rr[4] */ + psr =3D ia64_clear_ic(); + ia64_set_rr(VRN0<<VRN_SHIFT, vcpu->arch.metaphysical_rr0); + ia64_srlz_d(); + ia64_set_rr(VRN4<<VRN_SHIFT, vcpu->arch.metaphysical_rr4); + ia64_srlz_d(); + + ia64_set_psr(psr); + ia64_srlz_i(); + return; +} + + +void switch_to_virtual_rid(VCPU *vcpu) +{ + unsigned long psr; + + psr =3D ia64_clear_ic(); + ia64_set_rr(VRN0 << VRN_SHIFT, vcpu->arch.metaphysical_saved_rr0); + ia64_srlz_d(); + ia64_set_rr(VRN4 << VRN_SHIFT, vcpu->arch.metaphysical_saved_rr4); + ia64_srlz_d(); + ia64_set_psr(psr); + ia64_srlz_i(); + return; +} + +static int mm_switch_action(ia64_psr opsr, ia64_psr npsr) +{ + return mm_switch_table[MODE_IND(opsr)][MODE_IND(npsr)]; +} + +void switch_mm_mode(VCPU *vcpu, ia64_psr old_psr, ia64_psr new_psr) +{ + int act; + act =3D mm_switch_action(old_psr, new_psr); + switch (act) { + case SW_V2P: + /*printk("V -> P mode transition: (0x%lx -> 0x%lx)\n", + old_psr.val, new_psr.val);*/ + switch_to_physical_rid(vcpu); + /* + * Set rse to enforced lazy, to prevent active rse + *save/restor when guest physical mode. + */ + vcpu->arch.mode_flags |=3D GUEST_IN_PHY; + break; + case SW_P2V: + switch_to_virtual_rid(vcpu); + /* + * recover old mode which is saved when entering + * guest physical mode + */ + vcpu->arch.mode_flags &=3D ~GUEST_IN_PHY; + break; + case SW_SELF: + break; + case SW_NOP: + break; + default: + /* Sanity check */ + break; + } + return; +} + + + +/* + * In physical mode, insert tc/tr for region 0 and 4 uses + * RID[0] and RID[4] which is for physical mode emulation. + * However what those inserted tc/tr wants is rid for + * virtual mode. So original virtual rid needs to be restored + * before insert. + * + * Operations which required such switch include: + * - insertions (itc.*, itr.*) + * - purges (ptc.* and ptr.*) + * - tpa + * - tak + * - thash?, ttag? + * All above needs actual virtual rid for destination entry. + */ + +void check_mm_mode_switch(VCPU *vcpu, ia64_psr old_psr, ia64_psr new_psr) +{ + + if ((old_psr.dt !=3D new_psr.dt) + || (old_psr.it !=3D new_psr.it) + || (old_psr.rt !=3D new_psr.rt)) + switch_mm_mode(vcpu, old_psr, new_psr); + + return; +} + + +/* + * In physical mode, insert tc/tr for region 0 and 4 uses + * RID[0] and RID[4] which is for physical mode emulation. + * However what those inserted tc/tr wants is rid for + * virtual mode. So original virtual rid needs to be restored + * before insert. + * + * Operations which required such switch include: + * - insertions (itc.*, itr.*) + * - purges (ptc.* and ptr.*) + * - tpa + * - tak + * - thash?, ttag? + * All above needs actual virtual rid for destination entry. + */ + +void prepare_if_physical_mode(VCPU *vcpu) +{ + if (is_physical_mode(vcpu)) { + vcpu->arch.mode_flags |=3D GUEST_PHY_EMUL; + switch_to_virtual_rid(vcpu); + } + return; +} + +/* Recover always follows prepare */ +void recover_if_physical_mode(VCPU *vcpu) +{ + if (is_physical_mode(vcpu)) + switch_to_physical_rid(vcpu); + vcpu->arch.mode_flags &=3D ~GUEST_PHY_EMUL; + return; +} + +#define RPT(x) ((u16) &((struct kvm_pt_regs *)0)->x) + +static u16 gr_info[32] =3D { + 0, /* r0 is read-only : WE SHOULD NEVER GET THIS */ + RPT(r1), RPT(r2), RPT(r3), + RPT(r4), RPT(r5), RPT(r6), RPT(r7), + RPT(r8), RPT(r9), RPT(r10), RPT(r11), + RPT(r12), RPT(r13), RPT(r14), RPT(r15), + RPT(r16), RPT(r17), RPT(r18), RPT(r19), + RPT(r20), RPT(r21), RPT(r22), RPT(r23), + RPT(r24), RPT(r25), RPT(r26), RPT(r27), + RPT(r28), RPT(r29), RPT(r30), RPT(r31) +}; + +/* + * Return the (rotated) index for floating point register + * be in the REGNUM (REGNUM must range from 32-127, + * result is in the range from 0-95. + */ +static inline unsigned long fph_index(struct kvm_pt_regs *regs, + long regnum) +{ + unsigned long rrb_fr =3D (regs->cr_ifs >> 25) & 0x7f; + return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR)); +} + + +/* + * The inverse of the above: given bspstore and the number of + * registers, calculate ar.bsp. + */ +static inline unsigned long *kvm_rse_skip_regs(unsigned long *addr, + long num_regs) +{ + long delta =3D ia64_rse_slot_num(addr) + num_regs; + int i =3D 0; + + if (num_regs < 0) + delta -=3D 0x3e; + if (delta < 0) { + while (delta <=3D -0x3f) { + i--; + delta +=3D 0x3f; + } + } else { + while (delta >=3D 0x3f) { + i++; + delta -=3D 0x3f; + } + } + + return addr + num_regs + i; +} + +static void get_rse_reg (struct kvm_pt_regs *regs, unsigned long r1, + unsigned long *val, int *nat) +{ + unsigned long *bsp, *addr, *rnat_addr, *bspstore; + unsigned long *kbs =3D (void *) current_vcpu + VMM_RBS_OFFSET; + unsigned long nat_mask; + unsigned long old_rsc, new_rsc; + long sof =3D (regs->cr_ifs) & 0x7f; + long sor =3D (((regs->cr_ifs >> 14) & 0xf) << 3); + long rrb_gr =3D (regs->cr_ifs >> 18) & 0x7f; + long ridx =3D r1 - 32; + + if (ridx < sor) + ridx =3D rotate_reg(sor, rrb_gr, ridx); + + old_rsc =3D ia64_get_rsc(); + new_rsc =3D old_rsc&(~(0x3)); + ia64_set_rsc(new_rsc); + + bspstore =3D (unsigned long *)ia64_get_bspstore(); + bsp =3D kbs + (regs->loadrs >> 19); + + addr =3D kvm_rse_skip_regs(bsp, -sof + ridx); + nat_mask =3D 1UL << ia64_rse_slot_num(addr); + rnat_addr =3D ia64_rse_rnat_addr(addr); + + if (addr >=3D bspstore) { + ia64_flushrs(); + ia64_mf(); + bspstore =3D (unsigned long *)ia64_get_bspstore(); + } + *val =3D *addr; + if (nat) { + if (bspstore < rnat_addr) { + *nat =3D (int)!!(ia64_get_rnat() & nat_mask); + } else { + *nat =3D (int)!!((*rnat_addr) & nat_mask); + } + ia64_set_rsc(old_rsc); + } +} + +void set_rse_reg(struct kvm_pt_regs *regs, unsigned long r1, + unsigned long val, unsigned long nat) +{ + unsigned long *bsp, *bspstore, *addr, *rnat_addr; + unsigned long *kbs =3D (void *) current_vcpu + VMM_RBS_OFFSET; + unsigned long nat_mask; + unsigned long old_rsc, new_rsc, psr; + unsigned long rnat; + long sof =3D (regs->cr_ifs) & 0x7f; + long sor =3D (((regs->cr_ifs >> 14) & 0xf) << 3); + long rrb_gr =3D (regs->cr_ifs >> 18) & 0x7f; + long ridx =3D r1 - 32; + + if (ridx < sor) + ridx =3D rotate_reg(sor, rrb_gr, ridx); + + old_rsc =3D ia64_get_rsc(); + /* put RSC to lazy mode, and set loadrs 0 */ + new_rsc =3D old_rsc & (~0x3fff0003); + ia64_set_rsc(new_rsc); + bsp =3D kbs + (regs->loadrs >> 19); /* 16 + 3 */ + + addr =3D kvm_rse_skip_regs(bsp, -sof + ridx); + nat_mask =3D 1UL << ia64_rse_slot_num(addr); + rnat_addr =3D ia64_rse_rnat_addr(addr); + + local_irq_save(psr); + bspstore =3D (unsigned long *)ia64_get_bspstore(); + if (addr >=3D bspstore) { + + ia64_flushrs(); + ia64_mf(); + *addr =3D val; + bspstore =3D (unsigned long *)ia64_get_bspstore(); + rnat =3D ia64_get_rnat(); + if (bspstore < rnat_addr) { + rnat =3D rnat & (~nat_mask); + } else{ + *rnat_addr =3D (*rnat_addr)&(~nat_mask); + } + ia64_mf(); + ia64_loadrs(); + ia64_set_rnat(rnat); + } else { + rnat =3D ia64_get_rnat(); + *addr =3D val; + if (bspstore < rnat_addr) { + rnat =3D rnat&(~nat_mask); + } else { + *rnat_addr =3D (*rnat_addr) & (~nat_mask); + } + ia64_set_bspstore(bspstore); + ia64_set_rnat(rnat); + } + local_irq_restore(psr); + ia64_set_rsc(old_rsc); +} + +void getreg(unsigned long regnum, unsigned long *val, + int *nat, struct kvm_pt_regs *regs) +{ + unsigned long addr, *unat; + if (regnum >=3D IA64_FIRST_STACKED_GR) { + get_rse_reg(regs, regnum, val, nat); + return; + } + + /* + * Now look at registers in [0-31] range and init correct UNAT + */ + addr =3D (unsigned long)regs; + unat =3D ®s->eml_unat;; + + addr +=3D gr_info[regnum]; + + *val =3D *(unsigned long *)addr; + /* + * do it only when requested + */ + if (nat) + *nat =3D (*unat >> ((addr >> 3) & 0x3f)) & 0x1UL; +} + +void setreg(unsigned long regnum, unsigned long val, + int nat, struct kvm_pt_regs *regs) +{ + unsigned long addr; + unsigned long bitmask; + unsigned long *unat; + + /* + * First takes care of stacked registers + */ + if (regnum >=3D IA64_FIRST_STACKED_GR) { + set_rse_reg(regs, regnum, val, nat); + return; + } + + /* + * Now look at registers in [0-31] range and init correct UNAT + */ + addr =3D (unsigned long)regs; + unat =3D ®s->eml_unat; + /* + * add offset from base of struct + * and do it ! + */ + addr +=3D gr_info[regnum]; + + *(unsigned long *)addr =3D val; + + /* + * We need to clear the corresponding UNAT bit to fully emulate the load + * UNAT bit_pos =3D GR[r3]{8:3} form EAS-2.4 + */ + bitmask =3D 1UL << ((addr >> 3) & 0x3f); + if (nat) { + *unat |=3D bitmask; + } else { + *unat &=3D ~bitmask; + } +} + +u64 vcpu_get_gr(VCPU *vcpu, unsigned long reg) +{ + REGS *regs =3D vcpu_regs(vcpu); + u64 val; + + if (!reg) + return 0; + getreg(reg, &val, 0, regs); + return val; +} + +void vcpu_set_gr(VCPU *vcpu, u64 reg, u64 value, int nat) +{ + REGS *regs =3D vcpu_regs(vcpu); + long sof =3D (regs->cr_ifs) & 0x7f; + + if (!reg) + return; + if (reg >=3D sof + 32) + return; + setreg(reg, value, nat, regs); /* FIXME: handle NATs later*/ +} + +void getfpreg(unsigned long regnum, struct ia64_fpreg *fpval, + struct kvm_pt_regs *regs) +{ + /* Take floating register rotation into consideration*/ + if (regnum >=3D IA64_FIRST_ROTATING_FR) + regnum =3D IA64_FIRST_ROTATING_FR + fph_index(regs, regnum); +#define CASE_FIXED_FP(reg) \ + case (reg) : \ + ia64_stf_spill(fpval, reg); \ + break + + switch (regnum) { + CASE_FIXED_FP(0); + CASE_FIXED_FP(1); + CASE_FIXED_FP(2); + CASE_FIXED_FP(3); + CASE_FIXED_FP(4); + CASE_FIXED_FP(5); + + CASE_FIXED_FP(6); + CASE_FIXED_FP(7); + CASE_FIXED_FP(8); + CASE_FIXED_FP(9); + CASE_FIXED_FP(10); + CASE_FIXED_FP(11); + + CASE_FIXED_FP(12); + CASE_FIXED_FP(13); + CASE_FIXED_FP(14); + CASE_FIXED_FP(15); + CASE_FIXED_FP(16); + CASE_FIXED_FP(17); + CASE_FIXED_FP(18); + CASE_FIXED_FP(19); + CASE_FIXED_FP(20); + CASE_FIXED_FP(21); + CASE_FIXED_FP(22); + CASE_FIXED_FP(23); + CASE_FIXED_FP(24); + CASE_FIXED_FP(25); + CASE_FIXED_FP(26); + CASE_FIXED_FP(27); + CASE_FIXED_FP(28); + CASE_FIXED_FP(29); + CASE_FIXED_FP(30); + CASE_FIXED_FP(31); + CASE_FIXED_FP(32); + CASE_FIXED_FP(33); + CASE_FIXED_FP(34); + CASE_FIXED_FP(35); + CASE_FIXED_FP(36); + CASE_FIXED_FP(37); + CASE_FIXED_FP(38); + CASE_FIXED_FP(39); + CASE_FIXED_FP(40); + CASE_FIXED_FP(41); + CASE_FIXED_FP(42); + CASE_FIXED_FP(43); + CASE_FIXED_FP(44); + CASE_FIXED_FP(45); + CASE_FIXED_FP(46); + CASE_FIXED_FP(47); + CASE_FIXED_FP(48); + CASE_FIXED_FP(49); + CASE_FIXED_FP(50); + CASE_FIXED_FP(51); + CASE_FIXED_FP(52); + CASE_FIXED_FP(53); + CASE_FIXED_FP(54); + CASE_FIXED_FP(55); + CASE_FIXED_FP(56); + CASE_FIXED_FP(57); + CASE_FIXED_FP(58); + CASE_FIXED_FP(59); + CASE_FIXED_FP(60); + CASE_FIXED_FP(61); + CASE_FIXED_FP(62); + CASE_FIXED_FP(63); + CASE_FIXED_FP(64); + CASE_FIXED_FP(65); + CASE_FIXED_FP(66); + CASE_FIXED_FP(67); + CASE_FIXED_FP(68); + CASE_FIXED_FP(69); + CASE_FIXED_FP(70); + CASE_FIXED_FP(71); + CASE_FIXED_FP(72); + CASE_FIXED_FP(73); + CASE_FIXED_FP(74); + CASE_FIXED_FP(75); + CASE_FIXED_FP(76); + CASE_FIXED_FP(77); + CASE_FIXED_FP(78); + CASE_FIXED_FP(79); + CASE_FIXED_FP(80); + CASE_FIXED_FP(81); + CASE_FIXED_FP(82); + CASE_FIXED_FP(83); + CASE_FIXED_FP(84); + CASE_FIXED_FP(85); + CASE_FIXED_FP(86); + CASE_FIXED_FP(87); + CASE_FIXED_FP(88); + CASE_FIXED_FP(89); + CASE_FIXED_FP(90); + CASE_FIXED_FP(91); + CASE_FIXED_FP(92); + CASE_FIXED_FP(93); + CASE_FIXED_FP(94); + CASE_FIXED_FP(95); + CASE_FIXED_FP(96); + CASE_FIXED_FP(97); + CASE_FIXED_FP(98); + CASE_FIXED_FP(99); + CASE_FIXED_FP(100); + CASE_FIXED_FP(101); + CASE_FIXED_FP(102); + CASE_FIXED_FP(103); + CASE_FIXED_FP(104); + CASE_FIXED_FP(105); + CASE_FIXED_FP(106); + CASE_FIXED_FP(107); + CASE_FIXED_FP(108); + CASE_FIXED_FP(109); + CASE_FIXED_FP(110); + CASE_FIXED_FP(111); + CASE_FIXED_FP(112); + CASE_FIXED_FP(113); + CASE_FIXED_FP(114); + CASE_FIXED_FP(115); + CASE_FIXED_FP(116); + CASE_FIXED_FP(117); + CASE_FIXED_FP(118); + CASE_FIXED_FP(119); + CASE_FIXED_FP(120); + CASE_FIXED_FP(121); + CASE_FIXED_FP(122); + CASE_FIXED_FP(123); + CASE_FIXED_FP(124); + CASE_FIXED_FP(125); + CASE_FIXED_FP(126); + CASE_FIXED_FP(127); + } +#undef CASE_FIXED_FP +} + +void setfpreg(unsigned long regnum, struct ia64_fpreg *fpval, + struct kvm_pt_regs *regs) +{ + /* Take floating register rotation into consideration*/ + if (regnum >=3D IA64_FIRST_ROTATING_FR) + regnum =3D IA64_FIRST_ROTATING_FR + fph_index(regs, regnum); + +#define CASE_FIXED_FP(reg) \ + case (reg) : \ + ia64_ldf_fill(reg, fpval); \ + break + + switch (regnum) { + CASE_FIXED_FP(2); + CASE_FIXED_FP(3); + CASE_FIXED_FP(4); + CASE_FIXED_FP(5); + + CASE_FIXED_FP(6); + CASE_FIXED_FP(7); + CASE_FIXED_FP(8); + CASE_FIXED_FP(9); + CASE_FIXED_FP(10); + CASE_FIXED_FP(11); + + CASE_FIXED_FP(12); + CASE_FIXED_FP(13); + CASE_FIXED_FP(14); + CASE_FIXED_FP(15); + CASE_FIXED_FP(16); + CASE_FIXED_FP(17); + CASE_FIXED_FP(18); + CASE_FIXED_FP(19); + CASE_FIXED_FP(20); + CASE_FIXED_FP(21); + CASE_FIXED_FP(22); + CASE_FIXED_FP(23); + CASE_FIXED_FP(24); + CASE_FIXED_FP(25); + CASE_FIXED_FP(26); + CASE_FIXED_FP(27); + CASE_FIXED_FP(28); + CASE_FIXED_FP(29); + CASE_FIXED_FP(30); + CASE_FIXED_FP(31); + CASE_FIXED_FP(32); + CASE_FIXED_FP(33); + CASE_FIXED_FP(34); + CASE_FIXED_FP(35); + CASE_FIXED_FP(36); + CASE_FIXED_FP(37); + CASE_FIXED_FP(38); + CASE_FIXED_FP(39); + CASE_FIXED_FP(40); + CASE_FIXED_FP(41); + CASE_FIXED_FP(42); + CASE_FIXED_FP(43); + CASE_FIXED_FP(44); + CASE_FIXED_FP(45); + CASE_FIXED_FP(46); + CASE_FIXED_FP(47); + CASE_FIXED_FP(48); + CASE_FIXED_FP(49); + CASE_FIXED_FP(50); + CASE_FIXED_FP(51); + CASE_FIXED_FP(52); + CASE_FIXED_FP(53); + CASE_FIXED_FP(54); + CASE_FIXED_FP(55); + CASE_FIXED_FP(56); + CASE_FIXED_FP(57); + CASE_FIXED_FP(58); + CASE_FIXED_FP(59); + CASE_FIXED_FP(60); + CASE_FIXED_FP(61); + CASE_FIXED_FP(62); + CASE_FIXED_FP(63); + CASE_FIXED_FP(64); + CASE_FIXED_FP(65); + CASE_FIXED_FP(66); + CASE_FIXED_FP(67); + CASE_FIXED_FP(68); + CASE_FIXED_FP(69); + CASE_FIXED_FP(70); + CASE_FIXED_FP(71); + CASE_FIXED_FP(72); + CASE_FIXED_FP(73); + CASE_FIXED_FP(74); + CASE_FIXED_FP(75); + CASE_FIXED_FP(76); + CASE_FIXED_FP(77); + CASE_FIXED_FP(78); + CASE_FIXED_FP(79); + CASE_FIXED_FP(80); + CASE_FIXED_FP(81); + CASE_FIXED_FP(82); + CASE_FIXED_FP(83); + CASE_FIXED_FP(84); + CASE_FIXED_FP(85); + CASE_FIXED_FP(86); + CASE_FIXED_FP(87); + CASE_FIXED_FP(88); + CASE_FIXED_FP(89); + CASE_FIXED_FP(90); + CASE_FIXED_FP(91); + CASE_FIXED_FP(92); + CASE_FIXED_FP(93); + CASE_FIXED_FP(94); + CASE_FIXED_FP(95); + CASE_FIXED_FP(96); + CASE_FIXED_FP(97); + CASE_FIXED_FP(98); + CASE_FIXED_FP(99); + CASE_FIXED_FP(100); + CASE_FIXED_FP(101); + CASE_FIXED_FP(102); + CASE_FIXED_FP(103); + CASE_FIXED_FP(104); + CASE_FIXED_FP(105); + CASE_FIXED_FP(106); + CASE_FIXED_FP(107); + CASE_FIXED_FP(108); + CASE_FIXED_FP(109); + CASE_FIXED_FP(110); + CASE_FIXED_FP(111); + CASE_FIXED_FP(112); + CASE_FIXED_FP(113); + CASE_FIXED_FP(114); + CASE_FIXED_FP(115); + CASE_FIXED_FP(116); + CASE_FIXED_FP(117); + CASE_FIXED_FP(118); + CASE_FIXED_FP(119); + CASE_FIXED_FP(120); + CASE_FIXED_FP(121); + CASE_FIXED_FP(122); + CASE_FIXED_FP(123); + CASE_FIXED_FP(124); + CASE_FIXED_FP(125); + CASE_FIXED_FP(126); + CASE_FIXED_FP(127); + } +} + +void vcpu_get_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val) +{ + REGS *regs =3D vcpu_regs(vcpu); + + getfpreg(reg, val, regs); /* FIXME: handle NATs later*/ +} + +void vcpu_set_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val) +{ + REGS *regs =3D vcpu_regs(vcpu); + + if (reg > 1) + setfpreg(reg, val, regs); /* FIXME: handle NATs later*/ +} + + +/********************************************************************** ** + * lsapic timer + ***********************************************************************/ +u64 vcpu_get_itc(VCPU *vcpu) +{ + unsigned long guest_itc; + guest_itc =3D VMX(vcpu, itc_offset) + ia64_get_itc(); + + if (guest_itc >=3D VMX(vcpu, last_itc)) { + VMX(vcpu, last_itc) =3D guest_itc; + return guest_itc; + } else + return VMX(vcpu, last_itc); +} + +static inline void vcpu_set_itm(VCPU *vcpu, u64 val); +static void vcpu_set_itc(VCPU *vcpu, u64 val) +{ + VCPU *v; + int i; + long itc_offset =3D val - ia64_get_itc(); + unsigned long vitv =3D VCPU(vcpu, itv); + + if (vcpu->vcpu_id =3D=3D 0) { + for (i =3D 0; i < MAX_VCPU_NUM; i++) { + v =3D (VCPU *)((char *)vcpu + VCPU_SIZE * i); + VMX(v, itc_offset) =3D itc_offset; + VMX(v, last_itc) =3D 0; + } + } + VMX(vcpu, last_itc) =3D 0; + if (VCPU(vcpu, itm) <=3D val) { + VMX(vcpu, itc_check) =3D 0; + vcpu_unpend_interrupt(vcpu, vitv); + } else { + VMX(vcpu, itc_check) =3D 1; + vcpu_set_itm(vcpu, VCPU(vcpu, itm)); + } + +} + +static inline u64 vcpu_get_itm(VCPU *vcpu) +{ + return ((u64)VCPU(vcpu, itm)); +} + +static inline void vcpu_set_itm(VCPU *vcpu, u64 val) +{ + unsigned long vitv =3D VCPU(vcpu, itv); + VCPU(vcpu, itm) =3D val; + + if (val > vcpu_get_itc(vcpu)) { + VMX(vcpu, itc_check) =3D 1; + vcpu_unpend_interrupt(vcpu, vitv); + VMX(vcpu, timer_pending) =3D 0; + } else + VMX(vcpu, itc_check) =3D 0; +} + +#define ITV_VECTOR(itv) (itv&0xff) +#define ITV_IRQ_MASK(itv) (itv&(1<<16)) + +static inline void vcpu_set_itv(VCPU *vcpu, u64 val) +{ + VCPU(vcpu, itv) =3D val; + if (!ITV_IRQ_MASK(val) && vcpu->arch.timer_pending) { + vcpu_pend_interrupt(vcpu, ITV_VECTOR(val)); + vcpu->arch.timer_pending =3D 0; + } +} + +static inline void vcpu_set_eoi(VCPU *vcpu, u64 val) +{ + int vec; + + vec =3D highest_inservice_irq(vcpu); + if (vec =3D=3D NULL_VECTOR) + return; + VMX(vcpu, insvc[vec >> 6]) &=3D ~(1UL << (vec & 63)); + VCPU(vcpu, eoi) =3D 0; + vcpu->arch.irq_new_pending =3D 1; + +} + +/* See Table 5-8 in SDM vol2 for the definition */ +int irq_masked(VCPU *vcpu, int h_pending, int h_inservice) +{ + ia64_tpr vtpr; + + vtpr.val =3D VCPU(vcpu, tpr); + + if (h_inservice =3D=3D NMI_VECTOR) + return IRQ_MASKED_BY_INSVC; + + if (h_pending =3D=3D NMI_VECTOR) { + /* Non Maskable Interrupt */ + return IRQ_NO_MASKED; + } + + if (h_inservice =3D=3D ExtINT_VECTOR) + return IRQ_MASKED_BY_INSVC; + + if (h_pending =3D=3D ExtINT_VECTOR) { + if (vtpr.mmi) { + /* mask all external IRQ */ + return IRQ_MASKED_BY_VTPR; + } else + return IRQ_NO_MASKED; + } + + if (is_higher_irq(h_pending, h_inservice)) { + if (is_higher_class(h_pending, vtpr.mic + (vtpr.mmi << 4))) + return IRQ_NO_MASKED; + else + return IRQ_MASKED_BY_VTPR; + } else { + return IRQ_MASKED_BY_INSVC; + } +} + +void vcpu_pend_interrupt(VCPU *vcpu, u8 vec) +{ + long spsr; + int ret; + + local_irq_save(spsr); + ret =3D test_and_set_bit(vec, &VCPU(vcpu, irr[0])); + local_irq_restore(spsr); + + vcpu->arch.irq_new_pending =3D 1; +} + +void vcpu_unpend_interrupt(VCPU *vcpu, u8 vec) +{ + long spsr; + int ret; + + local_irq_save(spsr); + ret =3D test_and_clear_bit(vec, &VCPU(vcpu, irr[0])); + local_irq_restore(spsr); + if (ret) { + vcpu->arch.irq_new_pending =3D 1; + wmb(); + } +} + +void update_vhpi(VCPU *vcpu, int vec) +{ + u64 vhpi; + + if (vec =3D=3D NULL_VECTOR) + vhpi =3D 0; + else if (vec =3D=3D NMI_VECTOR) + vhpi =3D 32; + else if (vec =3D=3D ExtINT_VECTOR) + vhpi =3D 16; + else + vhpi =3D vec >> 4; + + VCPU(vcpu, vhpi) =3D vhpi; + if (VCPU(vcpu, vac).a_int) + ia64_call_vsa(PAL_VPS_SET_PENDING_INTERRUPT, + (u64)vcpu->arch.vpd, 0, 0, 0, 0, 0, 0); +} + +u64 vcpu_get_ivr(VCPU *vcpu) +{ + int vec, h_inservice, mask; + + vec =3D highest_pending_irq(vcpu); + h_inservice =3D highest_inservice_irq(vcpu); + mask =3D irq_masked(vcpu, vec, h_inservice); + if (vec =3D=3D NULL_VECTOR || mask =3D=3D IRQ_MASKED_BY_INSVC) { + if (VCPU(vcpu, vhpi)) + update_vhpi(vcpu, NULL_VECTOR); + return IA64_SPURIOUS_INT_VECTOR; + } + if (mask =3D=3D IRQ_MASKED_BY_VTPR) { + update_vhpi(vcpu, vec); + return IA64_SPURIOUS_INT_VECTOR; + } + VMX(vcpu, insvc[vec >> 6]) |=3D (1UL << (vec & 63)); + vcpu_unpend_interrupt(vcpu, vec); + return (u64)vec; +} + +/********************************************************************** **** + Privileged operation emulation routines + ************************************************************************ **/ +u64 vcpu_thash(VCPU *vcpu, u64 vadr) +{ + ia64_pta vpta; + ia64_rr vrr; + u64 pval; + u64 vhpt_offset; + + vpta.val =3D vcpu_get_pta(vcpu); + vrr.val =3D vcpu_get_rr(vcpu, vadr); + vhpt_offset =3D ((vadr >> vrr.ps) << 3) & ((1UL << (vpta.size)) - 1); + if (vpta.vf) { + pval =3D ia64_call_vsa(PAL_VPS_THASH, vadr, vrr.val, + vpta.val, 0, 0, 0, 0); + } else { + pval =3D (vadr & VRN_MASK) | vhpt_offset | + (vpta.val << 3 >> (vpta.size + 3) << (vpta.size)); + } + return pval; +} + +u64 vcpu_ttag(VCPU *vcpu, u64 vadr) +{ + ia64_rr vrr; + ia64_pta vpta; + u64 pval; + + vpta.val =3D vcpu_get_pta(vcpu); + vrr.val =3D vcpu_get_rr(vcpu, vadr); + if (vpta.vf) { + pval =3D ia64_call_vsa(PAL_VPS_TTAG, vadr, vrr.val, + 0, 0, 0, 0, 0); + } else + pval =3D 1; + + return pval; +} + +u64 vcpu_tak(VCPU *vcpu, u64 vadr) +{ + thash_data_t *data; + ia64_pta vpta; + u64 key; + + vpta.val =3D vcpu_get_pta(vcpu); + if (vpta.vf =3D=3D 0) { + key =3D 1; + return key; + } + data =3D vtlb_lookup(vcpu, vadr, D_TLB); + if (!data || !data->p) { + key =3D 1; + } else{ + key =3D data->key; + } + + return key; +} + + + +void kvm_thash(VCPU *vcpu, INST64 inst) +{ + unsigned long thash, vadr; + + vadr =3D vcpu_get_gr(vcpu, inst.M46.r3); + thash =3D vcpu_thash(vcpu, vadr); + vcpu_set_gr(vcpu, inst.M46.r1, thash, 0); +} + + +void kvm_ttag(VCPU *vcpu, INST64 inst) +{ + unsigned long tag, vadr; + + vadr =3D vcpu_get_gr(vcpu, inst.M46.r3); + tag =3D vcpu_ttag(vcpu, vadr); + vcpu_set_gr(vcpu, inst.M46.r1, tag, 0); +} + +int vcpu_tpa(VCPU *vcpu, u64 vadr, u64 *padr) +{ + thash_data_t *data; + ia64_isr visr, pt_isr; + REGS *regs; + ia64_psr vpsr; + + regs =3D vcpu_regs(vcpu); + pt_isr.val =3D VMX(vcpu, cr_isr); + visr.val =3D 0; + visr.ei =3D pt_isr.ei; + visr.ir =3D pt_isr.ir; + vpsr.val =3D VCPU(vcpu, vpsr); + visr.na =3D 1; + + data =3D vhpt_lookup(vadr); + if (data) { + if (data->p =3D=3D 0) { + vcpu_set_isr(vcpu, visr.val); + data_page_not_present(vcpu, vadr); + return IA64_FAULT; + } else if (data->ma =3D=3D VA_MATTR_NATPAGE) { + vcpu_set_isr(vcpu, visr.val); + dnat_page_consumption(vcpu, vadr); + return IA64_FAULT; + } else { + *padr =3D (data->gpaddr >> data->ps << data->ps) | + (vadr & (PSIZE(data->ps) - 1)); + return IA64_NO_FAULT; + } + } + + data =3D vtlb_lookup(vcpu, vadr, D_TLB); + if (data) { + if (data->p =3D=3D 0) { + vcpu_set_isr(vcpu, visr.val); + data_page_not_present(vcpu, vadr); + return IA64_FAULT; + } else if (data->ma =3D=3D VA_MATTR_NATPAGE) { + vcpu_set_isr(vcpu, visr.val); + dnat_page_consumption(vcpu, vadr); + return IA64_FAULT; + } else{ + *padr =3D ((data->ppn >> (data->ps - 12)) << data->ps) + | (vadr & (PSIZE(data->ps) - 1)); + return IA64_NO_FAULT; + } + } + if (!vhpt_enabled(vcpu, vadr, NA_REF)) { + if (vpsr.ic) { + vcpu_set_isr(vcpu, visr.val); + alt_dtlb(vcpu, vadr); + return IA64_FAULT; + } else { + nested_dtlb(vcpu); + return IA64_FAULT; + } + } else { + if (vpsr.ic) { + vcpu_set_isr(vcpu, visr.val); + dvhpt_fault(vcpu, vadr); + return IA64_FAULT; + } else{ + nested_dtlb(vcpu); + return IA64_FAULT; + } + } + + return IA64_NO_FAULT; +} + + +int kvm_tpa(VCPU *vcpu, INST64 inst) +{ + unsigned long r1, r3; + + r3 =3D vcpu_get_gr(vcpu, inst.M46.r3); + + if (vcpu_tpa(vcpu, r3, &r1)) + return IA64_FAULT; + + vcpu_set_gr(vcpu, inst.M46.r1, r1, 0); + return(IA64_NO_FAULT); +} + +void kvm_tak(VCPU *vcpu, INST64 inst) +{ + unsigned long r1, r3; + + r3 =3D vcpu_get_gr(vcpu, inst.M46.r3); + r1 =3D vcpu_tak(vcpu, r3); + vcpu_set_gr(vcpu, inst.M46.r1, r1, 0); +} + + +/************************************ + * Insert/Purge translation register/cache + ************************************/ +void vcpu_itc_i(VCPU *vcpu, u64 pte, u64 itir, u64 ifa) +{ + thash_purge_and_insert(vcpu, pte, itir, ifa, I_TLB); +} + +void vcpu_itc_d(VCPU *vcpu, u64 pte, u64 itir, u64 ifa) +{ + thash_purge_and_insert(vcpu, pte, itir, ifa, D_TLB); +} + +void vcpu_itr_i(VCPU *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa) +{ + u64 ps, va, rid; + thash_data_t *p_itr; + + ps =3D itir_ps(itir); + va =3D PAGEALIGN(ifa, ps); + pte &=3D ~PAGE_FLAGS_RV_MASK; + rid =3D vcpu_get_rr(vcpu, ifa); + rid =3D rid & RR_RID_MASK; + p_itr =3D (thash_data_t *)&vcpu->arch.itrs[slot]; + vcpu_set_tr(p_itr, pte, itir, va, rid); + vcpu_quick_region_set(VMX(vcpu, itr_regions), va); +} + + +void vcpu_itr_d(VCPU *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa) +{ + u64 gpfn; + u64 ps, va, rid; + thash_data_t *p_dtr; + + ps =3D itir_ps(itir); + va =3D PAGEALIGN(ifa, ps); + pte &=3D ~PAGE_FLAGS_RV_MASK; + + /* This is a bad workaround + In Linux, region 7 use 16M pagesize and is identity mapped. + VHPT page size is 16K in XEN. If purge VHPT while guest insert 16M, + it will iteratively purge VHPT 1024 times, which makes XEN/IPF very + slow. XEN doesn't purge VHPT + */ + if (ps !=3D _PAGE_SIZE_16M) + thash_purge_entries(vcpu, va, ps); + gpfn =3D (pte & _PAGE_PPN_MASK) >> PAGE_SHIFT; + if (__gpfn_is_io(gpfn)) + pte |=3D VTLB_PTE_IO; + rid =3D vcpu_get_rr(vcpu, va); + rid =3D rid & RR_RID_MASK; + p_dtr =3D (thash_data_t *)&vcpu->arch.dtrs[slot]; + vcpu_set_tr((thash_data_t *)&vcpu->arch.dtrs[slot], pte, itir, va, rid); + vcpu_quick_region_set(VMX(vcpu, dtr_regions), va); +} + +void vcpu_ptr_d(VCPU *vcpu, u64 ifa, u64 ps) +{ + int index; + u64 va; + + va =3D PAGEALIGN(ifa, ps); + while ((index =3D vtr_find_overlap(vcpu, va, ps, D_TLB)) >=3D 0) + vcpu->arch.dtrs[index].page_flags =3D 0; + + thash_purge_entries(vcpu, va, ps); +} + +void vcpu_ptr_i(VCPU *vcpu, u64 ifa, u64 ps) +{ + int index; + u64 va; + + va =3D PAGEALIGN(ifa, ps); + while ((index =3D vtr_find_overlap(vcpu, va, ps, I_TLB)) >=3D 0) + vcpu->arch.itrs[index].page_flags =3D 0; + + thash_purge_entries(vcpu, va, ps); +} + +void vcpu_ptc_l(VCPU *vcpu, u64 va, u64 ps) +{ + va =3D PAGEALIGN(va, ps); + thash_purge_entries(vcpu, va, ps); +} + +void vcpu_ptc_e(VCPU *vcpu, u64 va) +{ + thash_purge_all(vcpu); +} + +void vcpu_ptc_ga(VCPU *vcpu, u64 va, u64 ps) +{ + struct exit_ctl_data *p =3D &vcpu->arch.exit_data; + long psr; + local_irq_save(psr); + p->exit_reason =3D EXIT_REASON_PTC_G; + + p->u.ptc_g_data.rr =3D vcpu_get_rr(vcpu, va); + p->u.ptc_g_data.vaddr =3D va; + p->u.ptc_g_data.ps =3D ps; + vmm_transition(vcpu); + /* Do Local Purge Here*/ + vcpu_ptc_l(vcpu, va, ps); + local_irq_restore(psr); +} + + +void vcpu_ptc_g(VCPU *vcpu, u64 va, u64 ps) +{ + vcpu_ptc_ga(vcpu, va, ps); +} + +void kvm_ptc_e(VCPU *vcpu, INST64 inst) +{ + unsigned long ifa; + + ifa =3D vcpu_get_gr(vcpu, inst.M45.r3); + vcpu_ptc_e(vcpu, ifa); +} + +void kvm_ptc_g(VCPU *vcpu, INST64 inst) +{ + unsigned long ifa, itir; + + ifa =3D vcpu_get_gr(vcpu, inst.M45.r3); + itir =3D vcpu_get_gr(vcpu, inst.M45.r2); + vcpu_ptc_g(vcpu, ifa, itir_ps(itir)); +} + +void kvm_ptc_ga(VCPU *vcpu, INST64 inst) +{ + unsigned long ifa, itir; + + ifa =3D vcpu_get_gr(vcpu, inst.M45.r3); + itir =3D vcpu_get_gr(vcpu, inst.M45.r2); + vcpu_ptc_ga(vcpu, ifa, itir_ps(itir)); +} + +void kvm_ptc_l(VCPU *vcpu, INST64 inst) +{ + unsigned long ifa, itir; + + ifa =3D vcpu_get_gr(vcpu, inst.M45.r3); + itir =3D vcpu_get_gr(vcpu, inst.M45.r2); + vcpu_ptc_l(vcpu, ifa, itir_ps(itir)); +} + +void kvm_ptr_d(VCPU *vcpu, INST64 inst) +{ + unsigned long ifa, itir; + + ifa =3D vcpu_get_gr(vcpu, inst.M45.r3); + itir =3D vcpu_get_gr(vcpu, inst.M45.r2); + vcpu_ptr_d(vcpu, ifa, itir_ps(itir)); +} + +void kvm_ptr_i(VCPU *vcpu, INST64 inst) +{ + unsigned long ifa, itir; + + ifa =3D vcpu_get_gr(vcpu, inst.M45.r3); + itir =3D vcpu_get_gr(vcpu, inst.M45.r2); + vcpu_ptr_i(vcpu, ifa, itir_ps(itir)); +} + +void kvm_itr_d(VCPU *vcpu, INST64 inst) +{ + unsigned long itir, ifa, pte, slot; + + slot =3D vcpu_get_gr(vcpu, inst.M45.r3); + pte =3D vcpu_get_gr(vcpu, inst.M45.r2); + itir =3D vcpu_get_itir(vcpu); + ifa =3D vcpu_get_ifa(vcpu); + vcpu_itr_d(vcpu, slot, pte, itir, ifa); +} + + + +void kvm_itr_i(VCPU *vcpu, INST64 inst) +{ + unsigned long itir, ifa, pte, slot; + + slot =3D vcpu_get_gr(vcpu, inst.M45.r3); + pte =3D vcpu_get_gr(vcpu, inst.M45.r2); + itir =3D vcpu_get_itir(vcpu); + ifa =3D vcpu_get_ifa(vcpu); + vcpu_itr_i(vcpu, slot, pte, itir, ifa); +} + +void kvm_itc_d(VCPU *vcpu, INST64 inst) +{ + unsigned long itir, ifa, pte; + + itir =3D vcpu_get_itir(vcpu); + ifa =3D vcpu_get_ifa(vcpu); + pte =3D vcpu_get_gr(vcpu, inst.M45.r2); + vcpu_itc_d(vcpu, pte, itir, ifa); +} + +void kvm_itc_i(VCPU *vcpu, INST64 inst) +{ + unsigned long itir, ifa, pte; + + itir =3D vcpu_get_itir(vcpu); + ifa =3D vcpu_get_ifa(vcpu); + pte =3D vcpu_get_gr(vcpu, inst.M45.r2); + vcpu_itc_i(vcpu, pte, itir, ifa); +} + +/************************************* + * Moves to semi-privileged registers + *************************************/ + +void kvm_mov_to_ar_imm(VCPU *vcpu, INST64 inst) +{ + unsigned long imm; + + if (inst.M30.s) { + imm =3D -inst.M30.imm; + } else { + imm =3D inst.M30.imm; + } + + vcpu_set_itc(vcpu, imm); +} + +void kvm_mov_to_ar_reg(VCPU *vcpu, INST64 inst) +{ + unsigned long r2; + + r2 =3D vcpu_get_gr(vcpu, inst.M29.r2); + vcpu_set_itc(vcpu, r2); +} + + +void kvm_mov_from_ar_reg(VCPU *vcpu, INST64 inst) +{ + unsigned long r1; + + r1 =3D vcpu_get_itc(vcpu); + vcpu_set_gr(vcpu, inst.M31.r1, r1, 0); +} +/********************************************************************** **** + VCPU protection key register access routines + ************************************************************************ **/ + +unsigned long vcpu_get_pkr(VCPU *vcpu, unsigned long reg) +{ + return ((unsigned long)ia64_get_pkr(reg)); +} + +void vcpu_set_pkr(VCPU *vcpu, unsigned long reg, unsigned long val) +{ + ia64_set_pkr(reg, val); +} + + +unsigned long vcpu_get_itir_on_fault(VCPU *vcpu, unsigned long ifa) +{ + ia64_rr rr, rr1; + + rr.val =3D vcpu_get_rr(vcpu, ifa); + rr1.val =3D 0; + rr1.ps =3D rr.ps; + rr1.rid =3D rr.rid; + return (rr1.val); +} + + + +/******************************** + * Moves to privileged registers + ********************************/ +unsigned long vcpu_set_rr(VCPU *vcpu, unsigned long reg, unsigned long val) +{ + ia64_rr oldrr, newrr; + unsigned long rrval; + struct exit_ctl_data *p =3D &vcpu->arch.exit_data; + unsigned long psr; + + oldrr.val =3D vcpu_get_rr(vcpu, reg); + newrr.val =3D val; + vcpu->arch.vrr[reg >> VRN_SHIFT] =3D val; + + switch ((unsigned long)(reg >> VRN_SHIFT)) { + case VRN6: + vcpu->arch.vmm_rr =3D vrrtomrr(val); + local_irq_save(psr); + p->exit_reason =3D EXIT_REASON_SWITCH_RR6; + vmm_transition(vcpu); + local_irq_restore(psr); + break; + case VRN4: + rrval =3D vrrtomrr(val); + vcpu->arch.metaphysical_saved_rr4 =3D rrval; + if (!is_physical_mode(vcpu)) + ia64_set_rr(reg, rrval); + break; + case VRN0: + rrval =3D vrrtomrr(val); + vcpu->arch.metaphysical_saved_rr0 =3D rrval; + if (!is_physical_mode(vcpu)) + ia64_set_rr(reg, rrval); + break; + default: + ia64_set_rr(reg, vrrtomrr(val)); + break; + } + + return (IA64_NO_FAULT); +} + + + +void kvm_mov_to_rr(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r2; + + r3 =3D vcpu_get_gr(vcpu, inst.M42.r3); + r2 =3D vcpu_get_gr(vcpu, inst.M42.r2); + vcpu_set_rr(vcpu, r3, r2); +} + +void kvm_mov_to_dbr(VCPU *vcpu, INST64 inst) +{ +} + +void kvm_mov_to_ibr(VCPU *vcpu, INST64 inst) +{ +} + +void kvm_mov_to_pmc(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r2; + + r3 =3D vcpu_get_gr(vcpu, inst.M42.r3); + r2 =3D vcpu_get_gr(vcpu, inst.M42.r2); + vcpu_set_pmc(vcpu, r3, r2); +} + +void kvm_mov_to_pmd(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r2; + + r3 =3D vcpu_get_gr(vcpu, inst.M42.r3); + r2 =3D vcpu_get_gr(vcpu, inst.M42.r2); + vcpu_set_pmd(vcpu, r3, r2); +} + +void kvm_mov_to_pkr(VCPU *vcpu, INST64 inst) +{ + u64 r3, r2; + + r3 =3D vcpu_get_gr(vcpu, inst.M42.r3); + r2 =3D vcpu_get_gr(vcpu, inst.M42.r2); + vcpu_set_pkr(vcpu, r3, r2); +} + + + +void kvm_mov_from_rr(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r1; + + r3 =3D vcpu_get_gr(vcpu, inst.M43.r3); + r1 =3D vcpu_get_rr(vcpu, r3); + vcpu_set_gr(vcpu, inst.M43.r1, r1, 0); +} + +void kvm_mov_from_pkr(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r1; + + r3 =3D vcpu_get_gr(vcpu, inst.M43.r3); + r1 =3D vcpu_get_pkr(vcpu, r3); + vcpu_set_gr(vcpu, inst.M43.r1, r1, 0); +} + +void kvm_mov_from_dbr(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r1; + + r3 =3D vcpu_get_gr(vcpu, inst.M43.r3); + r1 =3D vcpu_get_dbr(vcpu, r3); + vcpu_set_gr(vcpu, inst.M43.r1, r1, 0); +} + +void kvm_mov_from_ibr(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r1; + + r3 =3D vcpu_get_gr(vcpu, inst.M43.r3); + r1 =3D vcpu_get_ibr(vcpu, r3); + vcpu_set_gr(vcpu, inst.M43.r1, r1, 0); +} + +void kvm_mov_from_pmc(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r1; + + r3 =3D vcpu_get_gr(vcpu, inst.M43.r3); + r1 =3D vcpu_get_pmc(vcpu, r3); + vcpu_set_gr(vcpu, inst.M43.r1, r1, 0); +} + + +unsigned long vcpu_get_cpuid(VCPU *vcpu, unsigned long reg) +{ + /* FIXME: This could get called as a result of a rsvd-reg fault */ + if (reg > (ia64_get_cpuid(3) & 0xff)) + return 0; + else + return ia64_get_cpuid(reg); +} + +void kvm_mov_from_cpuid(VCPU *vcpu, INST64 inst) +{ + unsigned long r3, r1; + + r3 =3D vcpu_get_gr(vcpu, inst.M43.r3); + r1 =3D vcpu_get_cpuid(vcpu, r3); + vcpu_set_gr(vcpu, inst.M43.r1, r1, 0); +} + +void vcpu_set_tpr(VCPU *vcpu, unsigned long val) +{ + VCPU(vcpu, tpr) =3D val; + vcpu->arch.irq_check =3D 1; +} + +unsigned long kvm_mov_to_cr(VCPU *vcpu, INST64 inst) +{ + unsigned long r2; + + r2 =3D vcpu_get_gr(vcpu, inst.M32.r2); + VCPU(vcpu, vcr[inst.M32.cr3]) =3D r2; + + switch (inst.M32.cr3) { + case 0: + vcpu_set_dcr(vcpu, r2); + break; + case 1: + vcpu_set_itm(vcpu, r2); + break; + case 66: + vcpu_set_tpr(vcpu, r2); + break; + case 67: + vcpu_set_eoi(vcpu, r2); + break; + default: + break; + } + + return 0; +} + + +unsigned long kvm_mov_from_cr(VCPU *vcpu, INST64 inst) +{ + unsigned long tgt =3D inst.M33.r1; + unsigned long val; + + switch (inst.M33.cr3) { + case 65: + val =3D vcpu_get_ivr(vcpu); + vcpu_set_gr(vcpu, tgt, val, 0); + break; + + case 67: + vcpu_set_gr(vcpu, tgt, 0L, 0); + break; + default: + val =3D VCPU(vcpu, vcr[inst.M33.cr3]); + vcpu_set_gr(vcpu, tgt, val, 0); + break; + } + + return 0; +} + + + +void vcpu_set_psr(VCPU *vcpu, unsigned long val) +{ + + unsigned long mask; + REGS *regs; + ia64_psr old_psr, new_psr; + + old_psr =3D (ia64_psr)VCPU(vcpu, vpsr); + + regs =3D vcpu_regs(vcpu); + /* We only support guest as: + * vpsr.pk =3D 0 + * vpsr.is =3D 0 + * Otherwise panic + */ + if (val & (IA64_PSR_PK | IA64_PSR_IS | IA64_PSR_VM)) + panic_vm(vcpu); + + /* + * For those IA64_PSR bits: id/da/dd/ss/ed/ia + * Since these bits will become 0, after success execution of each + * instruction, we will change set them to mIA64_PSR + */ + VCPU(vcpu, vpsr) =3D val + & (~(IA64_PSR_ID | IA64_PSR_DA | IA64_PSR_DD | + IA64_PSR_SS | IA64_PSR_ED | IA64_PSR_IA)); + + if (!old_psr.i && (val & IA64_PSR_I)) { + /* vpsr.i 0->1 */ + vcpu->arch.irq_check =3D 1; + } + new_psr.val =3D VCPU(vcpu, vpsr); + + /* + * All vIA64_PSR bits shall go to mPSR (v->tf->tf_special.psr) + * , except for the following bits: + * ic/i/dt/si/rt/mc/it/bn/vm + */ + mask =3D IA64_PSR_IC + IA64_PSR_I + IA64_PSR_DT + IA64_PSR_SI + + IA64_PSR_RT + IA64_PSR_MC + IA64_PSR_IT + IA64_PSR_BN + + IA64_PSR_VM; + + regs->cr_ipsr =3D (regs->cr_ipsr & mask) | (val & (~mask)); + + check_mm_mode_switch(vcpu, old_psr, new_psr); + + return ; +} + +unsigned long vcpu_cover(VCPU *vcpu) +{ + ia64_psr vpsr; + + REGS *regs =3D vcpu_regs(vcpu); + vpsr =3D (ia64_psr)VCPU(vcpu, vpsr); + + if (!vpsr.ic) + VCPU(vcpu, ifs) =3D regs->cr_ifs; + regs->cr_ifs =3D IA64_IFS_V; + return (IA64_NO_FAULT); +} + + + +/********************************************************************** **** + VCPU banked general register access routines + ************************************************************************ **/ +#define vcpu_bsw0_unat(i, b0unat, b1unat, runat, VMM_PT_REGS_R16_SLOT) \ + do { \ + __asm__ __volatile__ ( \ + ";;extr.u %0 =3D %3,%6,16;;\n" \ + "dep %1 =3D %0, %1, 0, 16;;\n" \ + "st8 [%4] =3D %1\n" \ + "extr.u %0 =3D %2, 16, 16;;\n" \ + "dep %3 =3D %0, %3, %6, 16;;\n" \ + "st8 [%5] =3D %3\n" \ + ::"r"(i), "r"(*b1unat), "r"(*b0unat), \ + "r"(*runat), "r"(b1unat), "r"(runat), \ + "i"(VMM_PT_REGS_R16_SLOT) : "memory"); \ + } while (0) + +void vcpu_bsw0(VCPU *vcpu) +{ + unsigned long i; + + REGS *regs =3D vcpu_regs(vcpu); + unsigned long *r =3D ®s->r16; + unsigned long *b0 =3D &VCPU(vcpu, vbgr[0]); + unsigned long *b1 =3D &VCPU(vcpu, vgr[0]); + unsigned long *runat =3D ®s->eml_unat; + unsigned long *b0unat =3D &VCPU(vcpu, vbnat); + unsigned long *b1unat =3D &VCPU(vcpu, vnat); + + + if (VCPU(vcpu, vpsr) & IA64_PSR_BN) { + for (i =3D 0; i < 16; i++) { + *b1++ =3D *r; + *r++ =3D *b0++; + } + vcpu_bsw0_unat(i, b0unat, b1unat, runat, + VMM_PT_REGS_R16_SLOT); + VCPU(vcpu, vpsr) &=3D ~IA64_PSR_BN; + } +} + +#define vcpu_bsw1_unat(i, b0unat, b1unat, runat, VMM_PT_REGS_R16_SLOT) \ + do { \ + __asm__ __volatile__ (";;extr.u %0 =3D %3, %6, 16;;\n" \ + "dep %1 =3D %0, %1, 16, 16;;\n" \ + "st8 [%4] =3D %1\n" \ + "extr.u %0 =3D %2, 0, 16;;\n" \ + "dep %3 =3D %0, %3, %6, 16;;\n" \ + "st8 [%5] =3D %3\n" \ + ::"r"(i), "r"(*b0unat), "r"(*b1unat), \ + "r"(*runat), "r"(b0unat), "r"(runat), \ + "i"(VMM_PT_REGS_R16_SLOT) : "memory"); \ + } while (0) + +void vcpu_bsw1(VCPU *vcpu) +{ + /* TODO: Only allowed for current vcpu */ + unsigned long i; + REGS *regs =3D vcpu_regs(vcpu); + unsigned long *r =3D ®s->r16; + unsigned long *b0 =3D &VCPU(vcpu, vbgr[0]); + unsigned long *b1 =3D &VCPU(vcpu, vgr[0]); + unsigned long *runat =3D ®s->eml_unat; + unsigned long *b0unat =3D &VCPU(vcpu, vbnat); + unsigned long *b1unat =3D &VCPU(vcpu, vnat); + + if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) { + for (i =3D 0; i < 16; i++) { + *b0++ =3D *r; + *r++ =3D *b1++; + } + vcpu_bsw1_unat(i, b0unat, b1unat, runat, + VMM_PT_REGS_R16_SLOT); + VCPU(vcpu, vpsr) |=3D IA64_PSR_BN; + } +} + + + + +void vcpu_rfi(VCPU *vcpu) +{ + /* TODO: Only allowed for current vcpu */ + unsigned long ifs, psr; + REGS *regs =3D vcpu_regs(vcpu); + + psr =3D VCPU(vcpu, ipsr); + if (psr & IA64_PSR_BN) + vcpu_bsw1(vcpu); + else + vcpu_bsw0(vcpu); + vcpu_set_psr(vcpu, psr); + ifs =3D VCPU(vcpu, ifs); + if (ifs >> 63) + regs->cr_ifs =3D ifs; + regs->cr_iip =3D VCPU(vcpu, iip); +} + + +/* + VPSR can't keep track of below bits of guest PSR + This function gets guest PSR + */ + +unsigned long vcpu_get_psr(VCPU *vcpu) +{ + unsigned long mask; + REGS *regs =3D vcpu_regs(vcpu); + + mask =3D IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL | + IA64_PSR_MFH | IA64_PSR_CPL | IA64_PSR_RI; + return (VCPU(vcpu, vpsr) & ~mask) | (regs->cr_ipsr & mask); +} + +void kvm_rsm(VCPU *vcpu, INST64 inst) +{ + unsigned long vpsr; + unsigned long imm24 =3D (inst.M44.i<<23) | (inst.M44.i2<<21) + | inst.M44.imm; + + vpsr =3D vcpu_get_psr(vcpu); + vpsr &=3D (~imm24); + vcpu_set_psr(vcpu, vpsr); +} + +void kvm_ssm(VCPU *vcpu, INST64 inst) +{ + unsigned long vpsr; + unsigned long imm24 =3D (inst.M44.i << 23) | (inst.M44.i2 << 21) + | inst.M44.imm; + + vpsr =3D vcpu_get_psr(vcpu); + vpsr |=3D imm24; + vcpu_set_psr(vcpu, vpsr); +} + +void vcpu_set_psr_l(VCPU *vcpu, unsigned long val) +{ + val =3D (val & MASK(0, 32)) | (vcpu_get_psr(vcpu) & MASK(32, 32)); + vcpu_set_psr(vcpu, val); +} + +void kvm_mov_to_psr(VCPU *vcpu, INST64 inst) +{ + unsigned long val; + + val =3D vcpu_get_gr(vcpu, inst.M35.r2); + vcpu_set_psr_l(vcpu, val); +} + +void kvm_mov_from_psr(VCPU *vcpu, INST64 inst) +{ + unsigned long val; + + val =3D vcpu_get_psr(vcpu); + val =3D (val & MASK(0, 32)) | (val & MASK(35, 2)); + vcpu_set_gr(vcpu, inst.M33.r1, val, 0); +} + +void vcpu_increment_iip(VCPU *vcpu) +{ + REGS *regs =3D vcpu_regs(vcpu); + ia64_psr *ipsr =3D (ia64_psr *)®s->cr_ipsr; + if (ipsr->ri =3D=3D 2) { + ipsr->ri =3D 0; + regs->cr_iip +=3D 16; + } else + ipsr->ri++; +} + +void vcpu_decrement_iip(VCPU *vcpu) +{ + REGS *regs =3D vcpu_regs(vcpu); + ia64_psr *ipsr =3D (ia64_psr *)®s->cr_ipsr; + + if (ipsr->ri =3D=3D 0) { + ipsr->ri =3D 2; + regs->cr_iip -=3D 16; + } else + ipsr->ri--; +} + +/** Emulate a privileged operation. + * + * + * @param vcpu virtual cpu + * @cause the reason cause virtualization fault + * @opcode the instruction code which cause virtualization fault + */ + +void kvm_emulate(VCPU *vcpu, REGS *regs) +{ + unsigned long status, cause, opcode ; + INST64 inst; + + status =3D IA64_NO_FAULT; + cause =3D VMX(vcpu, cause); + opcode =3D VMX(vcpu, opcode); + inst.inst =3D opcode; + /* + * Switch to actual virtual rid in rr0 and rr4, + * which is required by some tlb related instructions. + */ + prepare_if_physical_mode(vcpu); + + switch (cause) { + case EVENT_RSM: + kvm_rsm(vcpu, inst); + break; + case EVENT_SSM: + kvm_ssm(vcpu, inst); + break; + case EVENT_MOV_TO_PSR: + kvm_mov_to_psr(vcpu, inst); + break; + case EVENT_MOV_FROM_PSR: + kvm_mov_from_psr(vcpu, inst); + break; + case EVENT_MOV_FROM_CR: + kvm_mov_from_cr(vcpu, inst); + break; + case EVENT_MOV_TO_CR: + kvm_mov_to_cr(vcpu, inst); + break; + case EVENT_BSW_0: + vcpu_bsw0(vcpu); + break; + case EVENT_BSW_1: + vcpu_bsw1(vcpu); + break; + case EVENT_COVER: + vcpu_cover(vcpu); + break; + case EVENT_RFI: + vcpu_rfi(vcpu); + break; + case EVENT_ITR_D: + kvm_itr_d(vcpu, inst); + break; + case EVENT_ITR_I: + kvm_itr_i(vcpu, inst); + break; + case EVENT_PTR_D: + kvm_ptr_d(vcpu, inst); + break; + case EVENT_PTR_I: + kvm_ptr_i(vcpu, inst); + break; + case EVENT_ITC_D: + kvm_itc_d(vcpu, inst); + break; + case EVENT_ITC_I: + kvm_itc_i(vcpu, inst); + break; + case EVENT_PTC_L: + kvm_ptc_l(vcpu, inst); + break; + case EVENT_PTC_G: + kvm_ptc_g(vcpu, inst); + break; + case EVENT_PTC_GA: + kvm_ptc_ga(vcpu, inst); + break; + case EVENT_PTC_E: + kvm_ptc_e(vcpu, inst); + break; + case EVENT_MOV_TO_RR: + kvm_mov_to_rr(vcpu, inst); + break; + case EVENT_MOV_FROM_RR: + kvm_mov_from_rr(vcpu, inst); + break; + case EVENT_THASH: + kvm_thash(vcpu, inst); + break; + case EVENT_TTAG: + kvm_ttag(vcpu, inst); + break; + case EVENT_TPA: + status =3D kvm_tpa(vcpu, inst); + break; + case EVENT_TAK: + kvm_tak(vcpu, inst); + break; + case EVENT_MOV_TO_AR_IMM: + kvm_mov_to_ar_imm(vcpu, inst); + break; + case EVENT_MOV_TO_AR: + kvm_mov_to_ar_reg(vcpu, inst); + break; + case EVENT_MOV_FROM_AR: + kvm_mov_from_ar_reg(vcpu, inst); + break; + case EVENT_MOV_TO_DBR: + kvm_mov_to_dbr(vcpu, inst); + break; + case EVENT_MOV_TO_IBR: + kvm_mov_to_ibr(vcpu, inst); + break; + case EVENT_MOV_TO_PMC: + kvm_mov_to_pmc(vcpu, inst); + break; + case EVENT_MOV_TO_PMD: + kvm_mov_to_pmd(vcpu, inst); + break; + case EVENT_MOV_TO_PKR: + kvm_mov_to_pkr(vcpu, inst); + break; + case EVENT_MOV_FROM_DBR: + kvm_mov_from_dbr(vcpu, inst); + break; + case EVENT_MOV_FROM_IBR: + kvm_mov_from_ibr(vcpu, inst); + break; + case EVENT_MOV_FROM_PMC: + kvm_mov_from_pmc(vcpu, inst); + break; + case EVENT_MOV_FROM_PKR: + kvm_mov_from_pkr(vcpu, inst); + break; + case EVENT_MOV_FROM_CPUID: + kvm_mov_from_cpuid(vcpu, inst); + break; + case EVENT_VMSW: + status =3D IA64_FAULT; + break; + default: + break; + }; + /*Assume all status is NO_FAULT ?*/ + if (status =3D=3D IA64_NO_FAULT && cause !=3D EVENT_RFI) + vcpu_increment_iip(vcpu); + + recover_if_physical_mode(vcpu); +} + +void init_vcpu(VCPU *vcpu) +{ + int i; + VCPU *v; + long itc_offset; + + vcpu->arch.mode_flags =3D GUEST_IN_PHY; + VMX(vcpu, vrr[0]) =3D 0x38; + VMX(vcpu, vrr[1]) =3D 0x38; + VMX(vcpu, vrr[2]) =3D 0x38; + VMX(vcpu, vrr[3]) =3D 0x38; + VMX(vcpu, vrr[4]) =3D 0x38; + VMX(vcpu, vrr[5]) =3D 0x38; + VMX(vcpu, vrr[6]) =3D 0x38; + VMX(vcpu, vrr[7]) =3D 0x38; + VCPU(vcpu, vpsr) =3D IA64_PSR_BN; + VCPU(vcpu, dcr) =3D 0; + /* pta.size must not be 0. The minimum is 15 (32k) */ + VCPU(vcpu, pta) =3D 15 << 2; + if (vcpu->vcpu_id =3D=3D 0) { + itc_offset =3D 0UL - ia64_get_itc(); + for (i =3D 0; i < MAX_VCPU_NUM; i++) { + v =3D (VCPU *)((char *)vcpu + VCPU_SIZE * i); + VMX(v, itc_offset) =3D itc_offset; + VMX(v, last_itc) =3D 0; + } + } + VCPU(vcpu, itv) =3D 0x10000; + VCPU(vcpu, itm) =3D 0; + VMX(vcpu, last_itc) =3D 0; + + VCPU(vcpu, lid) =3D VCPU_LID(vcpu); + VCPU(vcpu, ivr) =3D 0; + VCPU(vcpu, tpr) =3D 0x10000; + VCPU(vcpu, eoi) =3D 0; + VCPU(vcpu, irr[0]) =3D 0; + VCPU(vcpu, irr[1]) =3D 0; + VCPU(vcpu, irr[2]) =3D 0; + VCPU(vcpu, irr[3]) =3D 0; + VCPU(vcpu, pmv) =3D 0x10000; + VCPU(vcpu, cmcv) =3D 0x10000; + VCPU(vcpu, lrr0) =3D 0x10000; /* default reset value? */ + VCPU(vcpu, lrr1) =3D 0x10000; /* default reset value? */ + update_vhpi(vcpu, NULL_VECTOR); + VLSAPIC_XTP(vcpu) =3D 0x80; /* disabled */ + + for (i =3D 0; i < 4; i++) + VLSAPIC_INSVC(vcpu, i) =3D 0; +} + +void kvm_init_all_rr(VCPU *vcpu) +{ + unsigned long psr; + + local_irq_save(psr); + + /* WARNING: not allow co-exist of both virtual mode and physical + * mode in same region + */ + + vcpu->arch.metaphysical_saved_rr0 =3D vrrtomrr(VMX(vcpu, vrr[VRN0])); + vcpu->arch.metaphysical_saved_rr4 =3D vrrtomrr(VMX(vcpu, vrr[VRN4])); + + if (is_physical_mode(vcpu)) { + if (vcpu->arch.mode_flags & GUEST_PHY_EMUL) + panic_vm(vcpu); + + ia64_set_rr((VRN0 << VRN_SHIFT), vcpu->arch.metaphysical_rr0); + ia64_dv_serialize_data(); + ia64_set_rr((VRN4 << VRN_SHIFT), vcpu->arch.metaphysical_rr4); + ia64_dv_serialize_data(); + } else { + ia64_set_rr((VRN0 << VRN_SHIFT), + vcpu->arch.metaphysical_saved_rr0); + ia64_dv_serialize_data(); + ia64_set_rr((VRN4 << VRN_SHIFT), + vcpu->arch.metaphysical_saved_rr4); + ia64_dv_serialize_data(); + } + ia64_set_rr((VRN1 << VRN_SHIFT), + vrrtomrr(VMX(vcpu, vrr[VRN1]))); + ia64_dv_serialize_data(); + ia64_set_rr((VRN2 << VRN_SHIFT), + vrrtomrr(VMX(vcpu, vrr[VRN2]))); + ia64_dv_serialize_data(); + ia64_set_rr((VRN3 << VRN_SHIFT), + vrrtomrr(VMX(vcpu, vrr[VRN3]))); + ia64_dv_serialize_data(); + ia64_set_rr((VRN5 << VRN_SHIFT), + vrrtomrr(VMX(vcpu, vrr[VRN5]))); + ia64_dv_serialize_data(); + ia64_set_rr((VRN7 << VRN_SHIFT), + vrrtomrr(VMX(vcpu, vrr[VRN7]))); + ia64_dv_serialize_data(); + ia64_srlz_d(); + ia64_set_psr(psr); + ia64_srlz_i(); +} + +int vmm_entry(void) +{ + VCPU *v; + v =3D current_vcpu; + + ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)v->arch.vpd, + 0, 0, 0, 0, 0, 0); + kvm_init_vtlb(v); + kvm_init_vhpt(v); + init_vcpu(v); + kvm_init_all_rr(v); + vmm_reset_entry(); + + return 0; +} + +void panic_vm(VCPU *v) +{ + struct exit_ctl_data *p =3D &v->arch.exit_data; + + p->exit_reason =3D EXIT_REASON_VM_PANIC; + vmm_transition(v); + /*Never to return*/ + while (1); +} + + --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:34:09
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:30:36 +0800 Subject: [PATCH] kvm/ia64: Add interruption vector table for vmm. vmm_ivt.S includes an ivt for vmm use. Signed-off-by: Anthony Xu <ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/vmm_ivt.S | 1423 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1423 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/vmm_ivt.S diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S new file mode 100644 index 0000000..5ca8651 --- /dev/null +++ b/arch/ia64/kvm/vmm_ivt.S @@ -0,0 +1,1423 @@ +/* + * /ia64/kvm_ivt.S + * + * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co + * Stephane Eranian <er...@hp...> + * David Mosberger <da...@hp...> + * Copyright (C) 2000, 2002-2003 Intel Co + * Asit Mallick <asi...@in...> + * Suresh Siddha <sur...@in...> + * Kenneth Chen <ken...@in...> + * Fenghua Yu <fen...@in...> + * + * + * 00/08/23 Asit Mallick <asi...@in...> TLB handling + * for SMP + * 00/12/20 David Mosberger-Tang <da...@hp...> DTLB/ITLB + * handler now uses virtual PT. + * + * 07/6/20 Xuefei Xu (Anthony Xu) (ant...@in...) + * Supporting Intel virtualization architecture + * + */ + +/* + * This file defines the interruption vector table used by the CPU. + * It does not include one entry per possible cause of interruption. + * + * The first 20 entries of the table contain 64 bundles each while the + * remaining 48 entries contain only 16 bundles each. + * + * The 64 bundles are used to allow inlining the whole handler for + * critical + * interruptions like TLB misses. + * + * For each entry, the comment is as follows: + * + * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss + * (12,51) + * entry offset ----/ / / / + * / + * entry number ---------/ / / + * / + * size of the entry -------------/ / + * / + * vector name -------------------------------------/ + * / + * interruptions triggering this vector + * ----------------------/ + * + * The table is 32KB in size and must be aligned on 32KB + * boundary. + * (The CPU ignores the 15 lower bits of the address) + * + * Table is based upon EAS2.6 (Oct 1999) + */ + + +#include <asm/asmmacro.h> +#include <asm/cache.h> +#include <asm/pgtable.h> + +#include "asm-offsets.h" +#include "vcpu.h" +#include "kvm_minstate.h" +#include "vti.h" + +#if 1 +# define PSR_DEFAULT_BITS psr.ac +#else +# define PSR_DEFAULT_BITS 0 +#endif + + +#define KVM_FAULT(n) \ + kvm_fault_##n:; \ + mov r19=3Dn;; \ + br.sptk.many kvm_fault_##n; \ + ;; \ + + +#define KVM_REFLECT(n) \ + mov r31=3Dpr; \ + mov r19=3Dn; /* prepare to save predicates */ \ + mov r29=3Dcr.ipsr; \ + ;; \ + tbit.z p6,p7=3Dr29,IA64_PSR_VM_BIT; \ +(p7)br.sptk.many kvm_dispatch_reflection; \ + br.sptk.many kvm_panic; \ + + +GLOBAL_ENTRY(kvm_panic) + br.sptk.many kvm_panic + ;; +END(kvm_panic) + + + + + + .section .text.ivt,"ax" + + .align 32768 // align on 32KB boundary + .global kvm_ia64_ivt +kvm_ia64_ivt: +/////////////////////////////////////////////////////////////// +// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47) +ENTRY(kvm_vhpt_miss) + KVM_FAULT(0) +END(kvm_vhpt_miss) + + + .org kvm_ia64_ivt+0x400 +//////////////////////////////////////////////////////////////// +// 0x0400 Entry 1 (size 64 bundles) ITLB (21) +ENTRY(kvm_itlb_miss) + mov r31 =3D pr + mov r29=3Dcr.ipsr; + ;; + tbit.z p6,p7=3Dr29,IA64_PSR_VM_BIT; + (p6) br.sptk kvm_alt_itlb_miss + mov r19 =3D 1 + br.sptk kvm_itlb_miss_dispatch + KVM_FAULT(1); +END(kvm_itlb_miss) + + .org kvm_ia64_ivt+0x0800 +////////////////////////////////////////////////////////////////// +// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48) +ENTRY(kvm_dtlb_miss) + mov r31 =3D pr + mov r29=3Dcr.ipsr; + ;; + tbit.z p6,p7=3Dr29,IA64_PSR_VM_BIT; +(p6)br.sptk kvm_alt_dtlb_miss + br.sptk kvm_dtlb_miss_dispatch +END(kvm_dtlb_miss) + + .org kvm_ia64_ivt+0x0c00 +//////////////////////////////////////////////////////////////////// +// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19) +ENTRY(kvm_alt_itlb_miss) + mov r16=3Dcr.ifa // get address that caused the TLB miss + ;; + movl r17=3DPAGE_KERNEL + mov r24=3Dcr.ipsr + movl r19=3D(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) + ;; + and r19=3Dr19,r16 // clear ed, reserved bits, and PTE control bits + ;; + or r19=3Dr17,r19 // insert PTE control bits into r19 + ;; + movl r20=3DIA64_GRANULE_SHIFT<<2 + ;; + mov cr.itir=3Dr20 + ;; + itc.i r19 // insert the TLB entry + mov pr=3Dr31,-1 + rfi +END(kvm_alt_itlb_miss) + + .org kvm_ia64_ivt+0x1000 +///////////////////////////////////////////////////////////////////// +// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46) +ENTRY(kvm_alt_dtlb_miss) + mov r16=3Dcr.ifa // get address that caused the TLB miss + ;; + movl r17=3DPAGE_KERNEL + movl r19=3D(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) + mov r24=3Dcr.ipsr + ;; + and r19=3Dr19,r16 // clear ed, reserved bits, and PTE control bits + ;; + or r19=3Dr19,r17 // insert PTE control bits into r19 + ;; + movl r20=3DIA64_GRANULE_SHIFT<<2 + ;; + mov cr.itir=3Dr20 + ;; + itc.d r19 // insert the TLB entry + mov pr=3Dr31,-1 + rfi +END(kvm_alt_dtlb_miss) + + .org kvm_ia64_ivt+0x1400 +////////////////////////////////////////////////////////////////////// +// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45) +ENTRY(kvm_nested_dtlb_miss) + KVM_FAULT(5) +END(kvm_nested_dtlb_miss) + + .org kvm_ia64_ivt+0x1800 +///////////////////////////////////////////////////////////////////// +// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24) +ENTRY(kvm_ikey_miss) + KVM_REFLECT(6) +END(kvm_ikey_miss) + + .org kvm_ia64_ivt+0x1c00 +///////////////////////////////////////////////////////////////////// +// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51) +ENTRY(kvm_dkey_miss) + KVM_REFLECT(7) +END(kvm_dkey_miss) + + .org kvm_ia64_ivt+0x2000 +//////////////////////////////////////////////////////////////////// +// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54) +ENTRY(kvm_dirty_bit) + KVM_REFLECT(8) +END(kvm_dirty_bit) + + .org kvm_ia64_ivt+0x2400 +//////////////////////////////////////////////////////////////////// +// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27) +ENTRY(kvm_iaccess_bit) + KVM_REFLECT(9) +END(kvm_iaccess_bit) + + .org kvm_ia64_ivt+0x2800 +/////////////////////////////////////////////////////////////////// +// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55) +ENTRY(kvm_daccess_bit) + KVM_REFLECT(10) +END(kvm_daccess_bit) + + .org kvm_ia64_ivt+0x2c00 +///////////////////////////////////////////////////////////////// +// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33) +ENTRY(kvm_break_fault) + mov r31=3Dpr + mov r19=3D11 + mov r29=3Dcr.ipsr + ;; + KVM_SAVE_MIN_WITH_COVER_R19 + ;; + alloc r14=3Dar.pfs,0,0,4,0 // now it's safe (must be first in insn group!) + mov out0=3Dcr.ifa + mov out2=3Dcr.isr // FIXME: pity to make this slow access twice + mov out3=3Dcr.iim // FIXME: pity to make this slow access twice + adds r3=3D8,r2 // set up second base pointer + ;; + ssm psr.ic + ;; + srlz.i // guarantee that interruption collection is on + ;; + //(p15)ssm psr.i // restore psr.i + addl r14=3D@gprel(ia64_leave_hypervisor),gp + ;; + KVM_SAVE_REST + mov rp=3Dr14 + ;; + adds out1=3D16,sp + br.call.sptk.many b6=3Dkvm_ia64_handle_break + ;; +END(kvm_break_fault) + + .org kvm_ia64_ivt+0x3000 +///////////////////////////////////////////////////////////////// +// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4) +ENTRY(kvm_interrupt) + mov r31=3Dpr // prepare to save predicates + mov r19=3D12 + mov r29=3Dcr.ipsr + ;; + tbit.z p6,p7=3Dr29,IA64_PSR_VM_BIT + tbit.z p0,p15=3Dr29,IA64_PSR_I_BIT + ;; +(p7) br.sptk kvm_dispatch_interrupt + ;; + mov r27=3Dar.rsc /* M */ + mov r20=3Dr1 /* A */ + mov r25=3Dar.unat /* M */ + mov r26=3Dar.pfs /* I */ + mov r28=3Dcr.iip /* M */ + cover /* B (or nothing) */ + ;; + mov r1=3Dsp + ;; + invala /* M */ + mov r30=3Dcr.ifs + ;; + addl r1=3D-VMM_PT_REGS_SIZE,r1 + ;; + adds r17=3D2*L1_CACHE_BYTES,r1 /* really: biggest cache-line size */ + adds r16=3DPT(CR_IPSR),r1 + ;; + lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES + st8 [r16]=3Dr29 /* save cr.ipsr */ + ;; + lfetch.fault.excl.nt1 [r17] + mov r29=3Db0 + ;; + adds r16=3DPT(R8),r1 /* initialize first base pointer */ + adds r17=3DPT(R9),r1 /* initialize second base pointer */ + mov r18=3Dr0 /* make sure r18 isn't NaT */ + ;; +.mem.offset 0,0; st8.spill [r16]=3Dr8,16 +.mem.offset 8,0; st8.spill [r17]=3Dr9,16 + ;; +.mem.offset 0,0; st8.spill [r16]=3Dr10,24 +.mem.offset 8,0; st8.spill [r17]=3Dr11,24 + ;; + st8 [r16]=3Dr28,16 /* save cr.iip */ + st8 [r17]=3Dr30,16 /* save cr.ifs */ + mov r8=3Dar.fpsr /* M */ + mov r9=3Dar.csd + mov r10=3Dar.ssd + movl r11=3DFPSR_DEFAULT /* L-unit */ + ;; + st8 [r16]=3Dr25,16 /* save ar.unat */ + st8 [r17]=3Dr26,16 /* save ar.pfs */ + shl r18=3Dr18,16 /* compute ar.rsc to be used for "loadrs" */ + ;; + st8 [r16]=3Dr27,16 /* save ar.rsc */ + adds r17=3D16,r17 /* skip over ar_rnat field */ + ;; + st8 [r17]=3Dr31,16 /* save predicates */ + adds r16=3D16,r16 /* skip over ar_bspstore field */ + ;; + st8 [r16]=3Dr29,16 /* save b0 */ + st8 [r17]=3Dr18,16 /* save ar.rsc value for "loadrs" */ + ;; +.mem.offset 0,0; st8.spill [r16]=3Dr20,16 /* save original r1 */ +.mem.offset 8,0; st8.spill [r17]=3Dr12,16 + adds r12=3D-16,r1 + /* switch to kernel memory stack (with 16 bytes of scratch) */ + ;; +.mem.offset 0,0; st8.spill [r16]=3Dr13,16 +.mem.offset 8,0; st8.spill [r17]=3Dr8,16 /* save ar.fpsr */ + ;; +.mem.offset 0,0; st8.spill [r16]=3Dr15,16 +.mem.offset 8,0; st8.spill [r17]=3Dr14,16 + dep r14=3D-1,r0,60,4 + ;; +.mem.offset 0,0; st8.spill [r16]=3Dr2,16 +.mem.offset 8,0; st8.spill [r17]=3Dr3,16 + adds r2=3DVMM_PT_REGS_R16_OFFSET,r1 + adds r14 =3D VMM_VCPU_GP_OFFSET,r13 + ;; + mov r8=3Dar.ccv + ld8 r14 =3D [r14] + ;; + mov r1=3Dr14 /* establish kernel global pointer */ + ;; \ + bsw.1 + ;; + alloc r14=3Dar.pfs,0,0,1,0 // must be first in an insn group + mov out0=3Dr13 + ;; + ssm psr.ic + ;; + srlz.i + ;; + //(p15) ssm psr.i + adds r3=3D8,r2 // set up second base pointer for SAVE_REST + srlz.i // ensure everybody knows psr.ic is back on + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr16,16 +.mem.offset 8,0; st8.spill [r3]=3Dr17,16 + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr18,16 +.mem.offset 8,0; st8.spill [r3]=3Dr19,16 + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr20,16 +.mem.offset 8,0; st8.spill [r3]=3Dr21,16 + mov r18=3Db6 + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr22,16 +.mem.offset 8,0; st8.spill [r3]=3Dr23,16 + mov r19=3Db7 + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr24,16 +.mem.offset 8,0; st8.spill [r3]=3Dr25,16 + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr26,16 +.mem.offset 8,0; st8.spill [r3]=3Dr27,16 + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr28,16 +.mem.offset 8,0; st8.spill [r3]=3Dr29,16 + ;; +.mem.offset 0,0; st8.spill [r2]=3Dr30,16 +.mem.offset 8,0; st8.spill [r3]=3Dr31,32 + ;; + mov ar.fpsr=3Dr11 /* M-unit */ + st8 [r2]=3Dr8,8 /* ar.ccv */ + adds r24=3DPT(B6)-PT(F7),r3 + ;; + stf.spill [r2]=3Df6,32 + stf.spill [r3]=3Df7,32 + ;; + stf.spill [r2]=3Df8,32 + stf.spill [r3]=3Df9,32 + ;; + stf.spill [r2]=3Df10 + stf.spill [r3]=3Df11 + adds r25=3DPT(B7)-PT(F11),r3 + ;; + st8 [r24]=3Dr18,16 /* b6 */ + st8 [r25]=3Dr19,16 /* b7 */ + ;; + st8 [r24]=3Dr9 /* ar.csd */ + st8 [r25]=3Dr10 /* ar.ssd */ + ;; + srlz.d // make sure we see the effect of cr.ivr + addl r14=3D@gprel(ia64_leave_nested),gp + ;; + mov rp=3Dr14 + br.call.sptk.many b6=3Dkvm_ia64_handle_irq + ;; +END(kvm_interrupt) + + .global kvm_dispatch_vexirq + .org kvm_ia64_ivt+0x3400 +////////////////////////////////////////////////////////////////////// +// 0x3400 Entry 13 (size 64 bundles) Reserved +ENTRY(kvm_virtual_exirq) + mov r31=3Dpr + mov r19=3D13 + mov r30 =3Dr0 + ;; +kvm_dispatch_vexirq: + cmp.eq p6,p0 =3D 1,r30 + ;; +(p6)add r29 =3D VMM_VCPU_SAVED_GP_OFFSET,r21 + ;; +(p6)ld8 r1 =3D [r29] + ;; + KVM_SAVE_MIN_WITH_COVER_R19 + alloc r14=3Dar.pfs,0,0,1,0 + mov out0=3Dr13 + + ssm psr.ic + ;; + srlz.i // guarantee that interruption collection is on + ;; + //(p15) ssm psr.i // restore psr.i + adds r3=3D8,r2 // set up second base pointer + ;; + KVM_SAVE_REST + addl r14=3D@gprel(ia64_leave_hypervisor),gp + ;; + mov rp=3Dr14 + br.call.sptk.many b6=3Dkvm_vexirq +END(kvm_virtual_exirq) + + .org kvm_ia64_ivt+0x3800 +///////////////////////////////////////////////////////////////////// +// 0x3800 Entry 14 (size 64 bundles) Reserved + KVM_FAULT(14) + // this code segment is from 2.6.16.13 + + + .org kvm_ia64_ivt+0x3c00 +/////////////////////////////////////////////////////////////////////// +// 0x3c00 Entry 15 (size 64 bundles) Reserved + KVM_FAULT(15) + + + .org kvm_ia64_ivt+0x4000 +/////////////////////////////////////////////////////////////////////// +// 0x4000 Entry 16 (size 64 bundles) Reserved + KVM_FAULT(16) + + .org kvm_ia64_ivt+0x4400 +////////////////////////////////////////////////////////////////////// +// 0x4400 Entry 17 (size 64 bundles) Reserved + KVM_FAULT(17) + + .org kvm_ia64_ivt+0x4800 +////////////////////////////////////////////////////////////////////// +// 0x4800 Entry 18 (size 64 bundles) Reserved + KVM_FAULT(18) + + .org kvm_ia64_ivt+0x4c00 +////////////////////////////////////////////////////////////////////// +// 0x4c00 Entry 19 (size 64 bundles) Reserved + KVM_FAULT(19) + + .org kvm_ia64_ivt+0x5000 +////////////////////////////////////////////////////////////////////// +// 0x5000 Entry 20 (size 16 bundles) Page Not Present +ENTRY(kvm_page_not_present) + KVM_REFLECT(20) +END(kvm_page_not_present) + + .org kvm_ia64_ivt+0x5100 +/////////////////////////////////////////////////////////////////////// +// 0x5100 Entry 21 (size 16 bundles) Key Permission vector +ENTRY(kvm_key_permission) + KVM_REFLECT(21) +END(kvm_key_permission) + + .org kvm_ia64_ivt+0x5200 +////////////////////////////////////////////////////////////////////// +// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26) +ENTRY(kvm_iaccess_rights) + KVM_REFLECT(22) +END(kvm_iaccess_rights) + + .org kvm_ia64_ivt+0x5300 +////////////////////////////////////////////////////////////////////// +// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53) +ENTRY(kvm_daccess_rights) + KVM_REFLECT(23) +END(kvm_daccess_rights) + + .org kvm_ia64_ivt+0x5400 +///////////////////////////////////////////////////////////////////// +// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39) +ENTRY(kvm_general_exception) + KVM_REFLECT(24) + KVM_FAULT(24) +END(kvm_general_exception) + + .org kvm_ia64_ivt+0x5500 +////////////////////////////////////////////////////////////////////// +// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35) +ENTRY(kvm_disabled_fp_reg) + KVM_REFLECT(25) +END(kvm_disabled_fp_reg) + + .org kvm_ia64_ivt+0x5600 +//////////////////////////////////////////////////////////////////// +// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50) +ENTRY(kvm_nat_consumption) + KVM_REFLECT(26) +END(kvm_nat_consumption) + + .org kvm_ia64_ivt+0x5700 +///////////////////////////////////////////////////////////////////// +// 0x5700 Entry 27 (size 16 bundles) Speculation (40) +ENTRY(kvm_speculation_vector) + KVM_REFLECT(27) +END(kvm_speculation_vector) + + .org kvm_ia64_ivt+0x5800 +///////////////////////////////////////////////////////////////////// +// 0x5800 Entry 28 (size 16 bundles) Reserved + KVM_FAULT(28) + + .org kvm_ia64_ivt+0x5900 +/////////////////////////////////////////////////////////////////// +// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56) +ENTRY(kvm_debug_vector) + KVM_FAULT(29) +END(kvm_debug_vector) + + .org kvm_ia64_ivt+0x5a00 +/////////////////////////////////////////////////////////////// +// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57) +ENTRY(kvm_unaligned_access) + KVM_REFLECT(30) +END(kvm_unaligned_access) + + .org kvm_ia64_ivt+0x5b00 +////////////////////////////////////////////////////////////////////// +// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57) +ENTRY(kvm_unsupported_data_reference) + KVM_REFLECT(31) +END(kvm_unsupported_data_reference) + + .org kvm_ia64_ivt+0x5c00 +//////////////////////////////////////////////////////////////////// +// 0x5c00 Entry 32 (size 16 bundles) Floating Point FAULT (65) +ENTRY(kvm_floating_point_fault) + KVM_REFLECT(32) +END(kvm_floating_point_fault) + + .org kvm_ia64_ivt+0x5d00 +///////////////////////////////////////////////////////////////////// +// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66) +ENTRY(kvm_floating_point_trap) + KVM_REFLECT(33) +END(kvm_floating_point_trap) + + .org kvm_ia64_ivt+0x5e00 +////////////////////////////////////////////////////////////////////// +// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66) +ENTRY(kvm_lower_privilege_trap) + KVM_REFLECT(34) +END(kvm_lower_privilege_trap) + + .org kvm_ia64_ivt+0x5f00 +////////////////////////////////////////////////////////////////////// +// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68) +ENTRY(kvm_taken_branch_trap) + KVM_REFLECT(35) +END(kvm_taken_branch_trap) + + .org kvm_ia64_ivt+0x6000 +//////////////////////////////////////////////////////////////////// +// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69) +ENTRY(kvm_single_step_trap) + KVM_REFLECT(36) +END(kvm_single_step_trap) + .global kvm_virtualization_fault_back + .org kvm_ia64_ivt+0x6100 +///////////////////////////////////////////////////////////////////// +// 0x6100 Entry 37 (size 16 bundles) Virtualization Fault +ENTRY(kvm_virtualization_fault) + mov r31=3Dpr + adds r16 =3D VMM_VCPU_SAVED_GP_OFFSET,r21 + ;; + st8 [r16] =3D r1 + adds r17 =3D VMM_VCPU_GP_OFFSET, r21 + ;; + ld8 r1 =3D [r17] + cmp.eq p6,p0=3DEVENT_MOV_FROM_AR,r24 + cmp.eq p7,p0=3DEVENT_MOV_FROM_RR,r24 + cmp.eq p8,p0=3DEVENT_MOV_TO_RR,r24 + cmp.eq p9,p0=3DEVENT_RSM,r24 + cmp.eq p10,p0=3DEVENT_SSM,r24 + cmp.eq p11,p0=3DEVENT_MOV_TO_PSR,r24 + cmp.eq p12,p0=3DEVENT_THASH,r24 + (p6) br.dptk.many kvm_asm_mov_from_ar + (p7) br.dptk.many kvm_asm_mov_from_rr + (p8) br.dptk.many kvm_asm_mov_to_rr + (p9) br.dptk.many kvm_asm_rsm + (p10) br.dptk.many kvm_asm_ssm + (p11) br.dptk.many kvm_asm_mov_to_psr + (p12) br.dptk.many kvm_asm_thash + ;; +kvm_virtualization_fault_back: + adds r16 =3D VMM_VCPU_SAVED_GP_OFFSET,r21 + ;; + ld8 r1 =3D [r16] + ;; + mov r19=3D37 + adds r16 =3D VMM_VCPU_CAUSE_OFFSET,r21 + adds r17 =3D VMM_VCPU_OPCODE_OFFSET,r21 + ;; + st8 [r16] =3D r24 + st8 [r17] =3D r25 + ;; + cmp.ne p6,p0=3DEVENT_RFI, r24 + (p6) br.sptk kvm_dispatch_virtualization_fault + ;; + adds r18=3DVMM_VPD_BASE_OFFSET,r21 + ;; + ld8 r18=3D[r18] + ;; + adds r18=3DVMM_VPD_VIFS_OFFSET,r18 + ;; + ld8 r18=3D[r18] + ;; + tbit.z p6,p0=3Dr18,63 + (p6) br.sptk kvm_dispatch_virtualization_fault + ;; + //if vifs.v=3D1 desert current register frame + alloc r18=3Dar.pfs,0,0,0,0 + br.sptk kvm_dispatch_virtualization_fault +END(kvm_virtualization_fault) + + .org kvm_ia64_ivt+0x6200 +////////////////////////////////////////////////////////////// +// 0x6200 Entry 38 (size 16 bundles) Reserved + KVM_FAULT(38) + + .org kvm_ia64_ivt+0x6300 +///////////////////////////////////////////////////////////////// +// 0x6300 Entry 39 (size 16 bundles) Reserved + KVM_FAULT(39) + + .org kvm_ia64_ivt+0x6400 +///////////////////////////////////////////////////////////////// +// 0x6400 Entry 40 (size 16 bundles) Reserved + KVM_FAULT(40) + + .org kvm_ia64_ivt+0x6500 +////////////////////////////////////////////////////////////////// +// 0x6500 Entry 41 (size 16 bundles) Reserved + KVM_FAULT(41) + + .org kvm_ia64_ivt+0x6600 +////////////////////////////////////////////////////////////////// +// 0x6600 Entry 42 (size 16 bundles) Reserved + KVM_FAULT(42) + + .org kvm_ia64_ivt+0x6700 +////////////////////////////////////////////////////////////////// +// 0x6700 Entry 43 (size 16 bundles) Reserved + KVM_FAULT(43) + + .org kvm_ia64_ivt+0x6800 +////////////////////////////////////////////////////////////////// +// 0x6800 Entry 44 (size 16 bundles) Reserved + KVM_FAULT(44) + + .org kvm_ia64_ivt+0x6900 +/////////////////////////////////////////////////////////////////// +// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception +//(17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77) +ENTRY(kvm_ia32_exception) + KVM_FAULT(45) +END(kvm_ia32_exception) + + .org kvm_ia64_ivt+0x6a00 +//////////////////////////////////////////////////////////////////// +// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) +ENTRY(kvm_ia32_intercept) + KVM_FAULT(47) +END(kvm_ia32_intercept) + + .org kvm_ia64_ivt+0x6c00 +///////////////////////////////////////////////////////////////////// +// 0x6c00 Entry 48 (size 16 bundles) Reserved + KVM_FAULT(48) + + .org kvm_ia64_ivt+0x6d00 +////////////////////////////////////////////////////////////////////// +// 0x6d00 Entry 49 (size 16 bundles) Reserved + KVM_FAULT(49) + + .org kvm_ia64_ivt+0x6e00 +////////////////////////////////////////////////////////////////////// +// 0x6e00 Entry 50 (size 16 bundles) Reserved + KVM_FAULT(50) + + .org kvm_ia64_ivt+0x6f00 +///////////////////////////////////////////////////////////////////// +// 0x6f00 Entry 51 (size 16 bundles) Reserved + KVM_FAULT(52) + + .org kvm_ia64_ivt+0x7100 +//////////////////////////////////////////////////////////////////// +// 0x7100 Entry 53 (size 16 bundles) Reserved + KVM_FAULT(53) + + .org kvm_ia64_ivt+0x7200 +///////////////////////////////////////////////////////////////////// +// 0x7200 Entry 54 (size 16 bundles) Reserved + KVM_FAULT(54) + + .org kvm_ia64_ivt+0x7300 +//////////////////////////////////////////////////////////////////// +// 0x7300 Entry 55 (size 16 bundles) Reserved + KVM_FAULT(55) + + .org kvm_ia64_ivt+0x7400 +//////////////////////////////////////////////////////////////////// +// 0x7400 Entry 56 (size 16 bundles) Reserved + KVM_FAULT(56) + + .org kvm_ia64_ivt+0x7500 +///////////////////////////////////////////////////////////////////// +// 0x7500 Entry 57 (size 16 bundles) Reserved + KVM_FAULT(57) + + .org kvm_ia64_ivt+0x7600 +///////////////////////////////////////////////////////////////////// +// 0x7600 Entry 58 (size 16 bundles) Reserved + KVM_FAULT(58) + + .org kvm_ia64_ivt+0x7700 +//////////////////////////////////////////////////////////////////// +// 0x7700 Entry 59 (size 16 bundles) Reserved + KVM_FAULT(59) + + .org kvm_ia64_ivt+0x7800 +//////////////////////////////////////////////////////////////////// +// 0x7800 Entry 60 (size 16 bundles) Reserved + KVM_FAULT(60) + + .org kvm_ia64_ivt+0x7900 +///////////////////////////////////////////////////////////////////// +// 0x7900 Entry 61 (size 16 bundles) Reserved + KVM_FAULT(61) + + .org kvm_ia64_ivt+0x7a00 +///////////////////////////////////////////////////////////////////// +// 0x7a00 Entry 62 (size 16 bundles) Reserved + KVM_FAULT(62) + + .org kvm_ia64_ivt+0x7b00 +///////////////////////////////////////////////////////////////////// +// 0x7b00 Entry 63 (size 16 bundles) Reserved + KVM_FAULT(63) + + .org kvm_ia64_ivt+0x7c00 +//////////////////////////////////////////////////////////////////// +// 0x7c00 Entry 64 (size 16 bundles) Reserved + KVM_FAULT(64) + + .org kvm_ia64_ivt+0x7d00 +///////////////////////////////////////////////////////////////////// +// 0x7d00 Entry 65 (size 16 bundles) Reserved + KVM_FAULT(65) + + .org kvm_ia64_ivt+0x7e00 +///////////////////////////////////////////////////////////////////// +// 0x7e00 Entry 66 (size 16 bundles) Reserved + KVM_FAULT(66) + + .org kvm_ia64_ivt+0x7f00 +//////////////////////////////////////////////////////////////////// +// 0x7f00 Entry 67 (size 16 bundles) Reserved + KVM_FAULT(67) + + .org kvm_ia64_ivt+0x8000 +// There is no particular reason for this code to be here, other than that +// there happens to be space here that would go unused otherwise. If this +// fault ever gets "unreserved", simply moved the following code to a more +// suitable spot... + + +ENTRY(kvm_dtlb_miss_dispatch) + mov r19 =3D 2 + KVM_SAVE_MIN_WITH_COVER_R19 + alloc r14=3Dar.pfs,0,0,3,0 + mov out0=3Dcr.ifa + mov out1=3Dr15 + adds r3=3D8,r2 // set up second base pointer + ;; + ssm psr.ic + ;; + srlz.i // guarantee that interruption collection is on + ;; + //(p15) ssm psr.i // restore psr.i + addl r14=3D@gprel(ia64_leave_hypervisor_prepare),gp + ;; + KVM_SAVE_REST + KVM_SAVE_EXTRA + mov rp=3Dr14 + ;; + adds out2=3D16,r12 + br.call.sptk.many b6=3Dkvm_page_fault +END(kvm_dtlb_miss_dispatch) + +ENTRY(kvm_itlb_miss_dispatch) + + KVM_SAVE_MIN_WITH_COVER_R19 + alloc r14=3Dar.pfs,0,0,3,0 + mov out0=3Dcr.ifa + mov out1=3Dr15 + adds r3=3D8,r2 // set up second base pointer + ;; + ssm psr.ic + ;; + srlz.i // guarantee that interruption collection is on + ;; + //(p15) ssm psr.i // restore psr.i + addl r14=3D@gprel(ia64_leave_hypervisor),gp + ;; + KVM_SAVE_REST + mov rp=3Dr14 + ;; + adds out2=3D16,r12 + br.call.sptk.many b6=3Dkvm_page_fault +END(kvm_itlb_miss_dispatch) + +ENTRY(kvm_dispatch_reflection) + /* + * Input: + * psr.ic: off + * r19: intr type (offset into ivt, see ia64_int.h) + * r31: contains saved predicates (pr) + */ + KVM_SAVE_MIN_WITH_COVER_R19 + alloc r14=3Dar.pfs,0,0,5,0 + mov out0=3Dcr.ifa + mov out1=3Dcr.isr + mov out2=3Dcr.iim + mov out3=3Dr15 + adds r3=3D8,r2 // set up second base pointer + ;; + ssm psr.ic + ;; + srlz.i // guarantee that interruption collection is on + ;; + //(p15) ssm psr.i // restore psr.i + addl r14=3D@gprel(ia64_leave_hypervisor),gp + ;; + KVM_SAVE_REST + mov rp=3Dr14 + ;; + adds out4=3D16,r12 + br.call.sptk.many b6=3Dreflect_interruption +END(kvm_dispatch_reflection) + +ENTRY(kvm_dispatch_virtualization_fault) + adds r16 =3D VMM_VCPU_CAUSE_OFFSET,r21 + adds r17 =3D VMM_VCPU_OPCODE_OFFSET,r21 + ;; + st8 [r16] =3D r24 + st8 [r17] =3D r25 + ;; + KVM_SAVE_MIN_WITH_COVER_R19 + ;; + alloc r14=3Dar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) + mov out0=3Dr13 //vcpu + adds r3=3D8,r2 // set up second base pointer + ;; + ssm psr.ic + ;; + srlz.i // guarantee that interruption collection is on + ;; + //(p15) ssm psr.i // restore psr.i + addl r14=3D@gprel(ia64_leave_hypervisor_prepare),gp + ;; + KVM_SAVE_REST + KVM_SAVE_EXTRA + mov rp=3Dr14 + ;; + adds out1=3D16,sp //regs + br.call.sptk.many b6=3Dkvm_emulate +END(kvm_dispatch_virtualization_fault) + + +ENTRY(kvm_dispatch_interrupt) + KVM_SAVE_MIN_WITH_COVER_R19 // uses r31; defines r2 and r3 + ;; + alloc r14=3Dar.pfs,0,0,1,0 // must be first in an insn group + //mov out0=3Dcr.ivr // pass cr.ivr as first arg + adds r3=3D8,r2 // set up second base pointer for SAVE_REST + ;; + ssm psr.ic + ;; + srlz.i + ;; + //(p15) ssm psr.i + addl r14=3D@gprel(ia64_leave_hypervisor),gp + ;; + KVM_SAVE_REST + mov rp=3Dr14 + ;; + mov out0=3Dr13 // pass pointer to pt_regs as second arg + br.call.sptk.many b6=3Dkvm_ia64_handle_irq +END(kvm_dispatch_interrupt) + + + + +GLOBAL_ENTRY(ia64_leave_nested) + rsm psr.i + ;; + adds r21=3DPT(PR)+16,r12 + ;; + lfetch [r21],PT(CR_IPSR)-PT(PR) + adds r2=3DPT(B6)+16,r12 + adds r3=3DPT(R16)+16,r12 + ;; + lfetch [r21] + ld8 r28=3D[r2],8 // load b6 + adds r29=3DPT(R24)+16,r12 + + ld8.fill r16=3D[r3] + adds r3=3DPT(AR_CSD)-PT(R16),r3 + adds r30=3DPT(AR_CCV)+16,r12 + ;; + ld8.fill r24=3D[r29] + ld8 r15=3D[r30] // load ar.ccv + ;; + ld8 r29=3D[r2],16 // load b7 + ld8 r30=3D[r3],16 // load ar.csd + ;; + ld8 r31=3D[r2],16 // load ar.ssd + ld8.fill r8=3D[r3],16 + ;; + ld8.fill r9=3D[r2],16 + ld8.fill r10=3D[r3],PT(R17)-PT(R10) + ;; + ld8.fill r11=3D[r2],PT(R18)-PT(R11) + ld8.fill r17=3D[r3],16 + ;; + ld8.fill r18=3D[r2],16 + ld8.fill r19=3D[r3],16 + ;; + ld8.fill r20=3D[r2],16 + ld8.fill r21=3D[r3],16 + mov ar.csd=3Dr30 + mov ar.ssd=3Dr31 + ;; + rsm psr.i | psr.ic + // initiate turning off of interrupt and interruption collection + invala // invalidate ALAT + ;; + ld8.fill r22=3D[r2],24 + ld8.fill r23=3D[r3],24 + mov b6=3Dr28 + ;; + ld8.fill r25=3D[r2],16 + ld8.fill r26=3D[r3],16 + mov b7=3Dr29 + ;; + ld8.fill r27=3D[r2],16 + ld8.fill r28=3D[r3],16 + ;; + ld8.fill r29=3D[r2],16 + ld8.fill r30=3D[r3],24 + ;; + ld8.fill r31=3D[r2],PT(F9)-PT(R31) + adds r3=3DPT(F10)-PT(F6),r3 + ;; + ldf.fill f9=3D[r2],PT(F6)-PT(F9) + ldf.fill f10=3D[r3],PT(F8)-PT(F10) + ;; + ldf.fill f6=3D[r2],PT(F7)-PT(F6) + ;; + ldf.fill f7=3D[r2],PT(F11)-PT(F7) + ldf.fill f8=3D[r3],32 + ;; + srlz.i // ensure interruption collection is off + mov ar.ccv=3Dr15 + ;; + bsw.0 // switch back to bank 0 (no stop bit required beforehand...) + ;; + ldf.fill f11=3D[r2] +// mov r18=3Dr13 +// mov r21=3Dr13 + adds r16=3DPT(CR_IPSR)+16,r12 + adds r17=3DPT(CR_IIP)+16,r12 + ;; + ld8 r29=3D[r16],16 // load cr.ipsr + ld8 r28=3D[r17],16 // load cr.iip + ;; + ld8 r30=3D[r16],16 // load cr.ifs + ld8 r25=3D[r17],16 // load ar.unat + ;; + ld8 r26=3D[r16],16 // load ar.pfs + ld8 r27=3D[r17],16 // load ar.rsc + cmp.eq p9,p0=3Dr0,r0 + // set p9 to indicate that we should restore cr.ifs + ;; + ld8 r24=3D[r16],16 // load ar.rnat (may be garbage) + ld8 r23=3D[r17],16// load ar.bspstore (may be garbage) + ;; + ld8 r31=3D[r16],16 // load predicates + ld8 r22=3D[r17],16 // load b0 + ;; + ld8 r19=3D[r16],16 // load ar.rsc value for "loadrs" + ld8.fill r1=3D[r17],16 // load r1 + ;; + ld8.fill r12=3D[r16],16 + ld8.fill r13=3D[r17],16 + ;; + ld8 r20=3D[r16],16 // ar.fpsr + ld8.fill r15=3D[r17],16 + ;; + ld8.fill r14=3D[r16],16 + ld8.fill r2=3D[r17] + ;; + ld8.fill r3=3D[r16] + ;; + mov r16=3Dar.bsp // get existing backing store pointer + ;; + mov b0=3Dr22 + mov ar.pfs=3Dr26 + mov cr.ifs=3Dr30 + mov cr.ipsr=3Dr29 + mov ar.fpsr=3Dr20 + mov cr.iip=3Dr28 + ;; + mov ar.rsc=3Dr27 + mov ar.unat=3Dr25 + mov pr=3Dr31,-1 + rfi +END(ia64_leave_nested) + + + +GLOBAL_ENTRY(ia64_leave_hypervisor_prepare) + /* + * 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: + */ + adds r2 =3D PT(R4)+16,r12 + adds r3 =3D PT(R5)+16,r12 + adds r8 =3D PT(EML_UNAT)+16,r12 + ;; + ld8 r8 =3D [r8] + ;; + mov ar.unat=3Dr8 + ;; + ld8.fill r4=3D[r2],16 //load r4 + ld8.fill r5=3D[r3],16 //load r5 + ;; + ld8.fill r6=3D[r2] //load r6 + ld8.fill r7=3D[r3] //load r7 + ;; +END(ia64_leave_hypervisor_prepare) +//fall through +GLOBAL_ENTRY(ia64_leave_hypervisor) + rsm psr.i + ;; + br.call.sptk.many b0=3Dleave_hypervisor_tail + ;; + adds r20=3DPT(PR)+16,r12 + adds r8=3DPT(EML_UNAT)+16,r12 + ;; + ld8 r8=3D[r8] + ;; + mov ar.unat=3Dr8 + ;; + lfetch [r20],PT(CR_IPSR)-PT(PR) + adds r2 =3D PT(B6)+16,r12 + adds r3 =3D PT(B7)+16,r12 + ;; + lfetch [r20] + ;; + ld8 r24=3D[r2],16 /* B6 */ + ld8 r25=3D[r3],16 /* B7 */ + ;; + ld8 r26=3D[r2],16 /* ar_csd */ + ld8 r27=3D[r3],16 /* ar_ssd */ + mov b6 =3D r24 + ;; + ld8.fill r8=3D[r2],16 + ld8.fill r9=3D[r3],16 + mov b7 =3D r25 + ;; + mov ar.csd =3D r26 + mov ar.ssd =3D r27 + ;; + ld8.fill r10=3D[r2],PT(R15)-PT(R10) + ld8.fill r11=3D[r3],PT(R14)-PT(R11) + ;; + ld8.fill r15=3D[r2],PT(R16)-PT(R15) + ld8.fill r14=3D[r3],PT(R17)-PT(R14) + ;; + ld8.fill r16=3D[r2],16 + ld8.fill r17=3D[r3],16 + ;; + ld8.fill r18=3D[r2],16 + ld8.fill r19=3D[r3],16 + ;; + ld8.fill r20=3D[r2],16 + ld8.fill r21=3D[r3],16 + ;; + ld8.fill r22=3D[r2],16 + ld8.fill r23=3D[r3],16 + ;; + ld8.fill r24=3D[r2],16 + ld8.fill r25=3D[r3],16 + ;; + ld8.fill r26=3D[r2],16 + ld8.fill r27=3D[r3],16 + ;; + ld8.fill r28=3D[r2],16 + ld8.fill r29=3D[r3],16 + ;; + ld8.fill r30=3D[r2],PT(F6)-PT(R30) + ld8.fill r31=3D[r3],PT(F7)-PT(R31) + ;; + rsm psr.i | psr.ic + // initiate turning off of interrupt and interruption collection + invala // invalidate ALAT + ;; + srlz.i // ensure interruption collection is off + ;; + bsw.0 + ;; + adds r16 =3D PT(CR_IPSR)+16,r12 + adds r17 =3D PT(CR_IIP)+16,r12 + mov r21=3Dr13 // get current + ;; + ld8 r31=3D[r16],16 // load cr.ipsr + ld8 r30=3D[r17],16 // load cr.iip + ;; + ld8 r29=3D[r16],16 // load cr.ifs + ld8 r28=3D[r17],16 // load ar.unat + ;; + ld8 r27=3D[r16],16 // load ar.pfs + ld8 r26=3D[r17],16 // load ar.rsc + ;; + ld8 r25=3D[r16],16 // load ar.rnat + ld8 r24=3D[r17],16 // load ar.bspstore + ;; + ld8 r23=3D[r16],16 // load predicates + ld8 r22=3D[r17],16 // load b0 + ;; + ld8 r20=3D[r16],16 // load ar.rsc value for "loadrs" + ld8.fill r1=3D[r17],16 //load r1 + ;; + ld8.fill r12=3D[r16],16 //load r12 + ld8.fill r13=3D[r17],PT(R2)-PT(R13) //load r13 + ;; + ld8 r19=3D[r16],PT(R3)-PT(AR_FPSR) //load ar_fpsr + ld8.fill r2=3D[r17],PT(AR_CCV)-PT(R2) //load r2 + ;; + ld8.fill r3=3D[r16] //load r3 + ld8 r18=3D[r17] //load ar_ccv + ;; + mov ar.fpsr=3Dr19 + mov ar.ccv=3Dr18 + shr.u r18=3Dr20,16 + ;; +kvm_rbs_switch: + mov r19=3D96 + +kvm_dont_preserve_current_frame: +/* + * To prevent leaking bits between the hypervisor and guest domain, + * we must clear the stacked registers in the "invalid" partition here. + * 5 registers/cycle on McKinley). + */ +# define pRecurse p6 +# define pReturn p7 +# define Nregs 14 + + alloc loc0=3Dar.pfs,2,Nregs-2,2,0 + shr.u loc1=3Dr18,9 // RNaTslots <=3D floor(dirtySize / (64*8)) + sub r19=3Dr19,r18 // r19 =3D (physStackedSize + 8) - dirtySize + ;; + mov ar.rsc=3Dr20 // load ar.rsc to be used for "loadrs" + shladd in0=3Dloc1,3,r19 + mov in1=3D0 + ;; + TEXT_ALIGN(32) +kvm_rse_clear_invalid: + alloc loc0=3Dar.pfs,2,Nregs-2,2,0 + cmp.lt pRecurse,p0=3DNregs*8,in0 + // if more than Nregs regs left to clear, (re)curse + add out0=3D-Nregs*8,in0 + add out1=3D1,in1 // increment recursion count + mov loc1=3D0 + mov loc2=3D0 + ;; + mov loc3=3D0 + mov loc4=3D0 + mov loc5=3D0 + mov loc6=3D0 + mov loc7=3D0 +(pRecurse) br.call.dptk.few b0=3Dkvm_rse_clear_invalid + ;; + mov loc8=3D0 + mov loc9=3D0 + cmp.ne pReturn,p0=3Dr0,in1 + // if recursion count !=3D 0, we need to do a br.ret + mov loc10=3D0 + mov loc11=3D0 +(pReturn) br.ret.dptk.many b0 + +# undef pRecurse +# undef pReturn + +// loadrs has already been shifted + alloc r16=3Dar.pfs,0,0,0,0 // drop current register frame + ;; + loadrs + ;; + mov ar.bspstore=3Dr24 + ;; + mov ar.unat=3Dr28 + mov ar.rnat=3Dr25 + mov ar.rsc=3Dr26 + ;; + mov cr.ipsr=3Dr31 + mov cr.iip=3Dr30 + mov cr.ifs=3Dr29 + mov ar.pfs=3Dr27 + adds r18=3DVMM_VPD_BASE_OFFSET,r21 + ;; + ld8 r18=3D[r18] //vpd + adds r17=3DVMM_VCPU_ISR_OFFSET,r21 + ;; + ld8 r17=3D[r17] + adds r19=3DVMM_VPD_VPSR_OFFSET,r18 + ;; + ld8 r19=3D[r19] //vpsr + adds r20=3DVMM_VCPU_VSA_BASE_OFFSET,r21 + ;; + ld8 r20=3D[r20] + ;; +//vsa_sync_write_start + mov r25=3Dr18 + adds r16=3D VMM_VCPU_GP_OFFSET,r21 + ;; + ld8 r16=3D [r16] // Put gp in r24 + movl r24=3D@gprel(ia64_vmm_entry) // calculate return address + ;; + add r24=3Dr24,r16 + ;; + add r16=3DPAL_VPS_SYNC_WRITE,r20 + ;; + mov b0=3Dr16 + br.cond.sptk b0 // call the service + ;; +END(ia64_leave_hypervisor) +// fall through +GLOBAL_ENTRY(ia64_vmm_entry) +/* + * must be at bank 0 + * parameter: + * r17:cr.isr + * r18:vpd + * r19:vpsr + * r20:__vsa_base + * r22:b0 + * r23:predicate + */ + mov r24=3Dr22 + mov r25=3Dr18 + tbit.nz p1,p2 =3D r19,IA64_PSR_IC_BIT // p1=3Dvpsr.ic + ;; + (p1) add r29=3DPAL_VPS_RESUME_NORMAL,r20 + (p1) br.sptk.many ia64_vmm_entry_out + ;; + tbit.nz p1,p2 =3D r17,IA64_ISR_IR_BIT //p1=3Dcr.isr.ir + ;; + (p1) add r29=3DPAL_VPS_RESUME_NORMAL,r20 + (p2) add r29=3DPAL_VPS_RESUME_HANDLER,r20 + (p2) ld8 r26=3D[r25] + ;; +ia64_vmm_entry_out: + mov pr=3Dr23,-2 + mov b0=3Dr29 + ;; + br.cond.sptk b0 // call pal service +END(ia64_vmm_entry) + + + +/* + * extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2, + * u64 arg3, u64 arg4, u64 arg5, + * u64 arg6, u64 arg7); + * + * XXX: The currently defined services use only 4 args at the max. The + * rest are not consumed. + */ +GLOBAL_ENTRY(ia64_call_vsa) + .regstk 4,4,0,0 + +rpsave =3D loc0 +pfssave =3D loc1 +psrsave =3D loc2 +entry =3D loc3 +hostret =3D r24 + + alloc pfssave=3Dar.pfs,4,4,0,0 + mov rpsave=3Drp + adds entry=3DVMM_VCPU_VSA_BASE_OFFSET, r13 + ;; + ld8 entry=3D[entry] +1: mov hostret=3Dip + mov r25=3Din1 // copy arguments + mov r26=3Din2 + mov r27=3Din3 + mov psrsave=3Dpsr + ;; + tbit.nz p6,p0=3Dpsrsave,14 // IA64_PSR_I + tbit.nz p7,p0=3Dpsrsave,13 // IA64_PSR_IC + ;; + add hostret=3D2f-1b,hostret // calculate return address + add entry=3Dentry,in0 + ;; + rsm psr.i | psr.ic + ;; + srlz.d + mov b6=3Dentry + br.cond.sptk b6 // call the service +2: + // Architectural sequence for enabling interrupts if necessary +(p7) ssm psr.ic + ;; +(p7) srlz.d + ;; +//(p6) ssm psr.i + ;; + mov rp=3Drpsave + mov ar.pfs=3Dpfssave + mov r8=3Dr31 + ;; + srlz.d + br.ret.sptk rp + +END(ia64_call_vsa) + +#define INIT_BSPSTORE ((4<<30)-(12<<20)-0x100) + +GLOBAL_ENTRY(vmm_reset_entry) + //set up ipsr, iip, vpd.vpsr, dcr + // For IPSR: it/dt/rt=3D1, i/ic=3D1, si=3D1, vm/bn=3D1 + // For DCR: all bits 0 + adds r14=3D-VMM_PT_REGS_SIZE, r12 + ;; + movl r6=3D0x501008826000 // IPSR dt/rt/it:1;i/ic:1, si:1, vm/bn:1 + movl r10=3D0x8000000000000000 + adds r16=3DPT(CR_IIP), r14 + adds r20=3DPT(R1), r14 + ;; + rsm psr.ic | psr.i + ;; + srlz.d + ;; + bsw.0 + ;; + mov r21 =3Dr13 + ;; + bsw.1 + ;; + mov ar.rsc =3D 0 + ;; + flushrs + ;; + mov ar.bspstore =3D 0 + // clear BSPSTORE + ;; + mov cr.ipsr=3Dr6 + mov cr.ifs=3Dr10 + ld8 r4 =3D [r16] // Set init iip for first run. + ld8 r1 =3D [r20] + ;; + mov cr.iip=3Dr4 + ;; + adds r16=3DVMM_VPD_BASE_OFFSET,r13 + adds r20=3DVMM_VCPU_VSA_BASE_OFFSET,r13 + ;; + ld8 r18=3D[r16] + ld8 r20=3D[r20] + ;; + adds r19=3DVMM_VPD_VPSR_OFFSET,r18 + ;; + ld8 r19=3D[r19] + mov r17=3Dr0 + mov r22=3Dr0 + mov r23=3Dr0 + br.cond.sptk ia64_vmm_entry + br.ret.sptk b0 +END(vmm_reset_entry) + --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:34:02
|
From: xia...@in... <xia...@in...> Date: Thu, 17 Jan 2008 14:03:04 +0800 Subject: [PATCH] kvm: ia64 : Export some symbols out for module use. Export empty_zero_page, ia64_sal_cache_flush, ia64_sal_freq_base in this patch. Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kernel/ia64_ksyms.c | 3 +++ arch/ia64/kernel/sal.c | 14 ++++++++++++++ include/asm-ia64/sal.h | 14 +++----------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c index c3b4412..43d227f 100644 --- a/arch/ia64/kernel/ia64_ksyms.c +++ b/arch/ia64/kernel/ia64_ksyms.c @@ -12,6 +12,9 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(strlen); =20 +#include<asm/pgtable.h> +EXPORT_SYMBOL(empty_zero_page); + #include <asm/checksum.h> EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */ EXPORT_SYMBOL(csum_ipv6_magic); diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index 27c2ef4..67c1d34 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -284,6 +284,7 @@ ia64_sal_cache_flush (u64 cache_type) SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); return isrv.status; } +EXPORT_SYMBOL(ia64_sal_cache_flush); =20 void __init ia64_sal_init (struct ia64_sal_systab *systab) @@ -372,3 +373,16 @@ ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc, return 0; } EXPORT_SYMBOL(ia64_sal_oemcall_reentrant); + +long +ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, + unsigned long *drift_info) +{ + struct ia64_sal_retval isrv; + + SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0); + *ticks_per_second =3D isrv.v0; + *drift_info =3D isrv.v1; + return isrv.status; +} +EXPORT_SYMBOL(ia64_sal_freq_base); diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index 1f5412d..2251118 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -649,17 +649,6 @@ typedef struct err_rec { * Now define a couple of inline functions for improved type checking * and convenience. */ -static inline long -ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, - unsigned long *drift_info) -{ - struct ia64_sal_retval isrv; - - SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0); - *ticks_per_second =3D isrv.v0; - *drift_info =3D isrv.v1; - return isrv.status; -} =20 extern s64 ia64_sal_cache_flush (u64 cache_type); extern void __init check_sal_cache_flush (void); @@ -841,6 +830,9 @@ extern int ia64_sal_oemcall_nolock(struct ia64_sal_retval *, u64, u64, u64, u64, u64, u64, u64, u64); extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64, u64, u64, u64, u64, u64); +extern long +ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, + unsigned long *drift_info); #ifdef CONFIG_HOTPLUG_CPU /* * System Abstraction Layer Specification --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:34:01
|
Hi, Avi/Tony We have rebased kvm/ia64 code to latest kvm. In this version, we have fixed coding style issues, and all patches can pass checkpatch.pl, except one assembly header file, which is copyied from kernel, so we didn't change its issues.=20 Compared with last version, we implemented smp guest support, and addressed two stability issues which only take on with smp guests. Now, based on our own test results, it has good stability, and good performance. Please review and help to commit them before linux 2.6.25 merge :) =20 [01] Appoint Maintainter for kvm/ia64.=20 [02] Change srlz.d to srlz.i for ia64_set_psr to save unnecessary srlz.d, since kvm need to use it frequently. [03] Export three symbos for module use. [04] Add API for allocating TR resouce.=20 For patch04, We want to add a comment TR resource API for kernel. It is not just used by kvm module. Our idea is that the first two pari of TRs are used as a fixed way, and we don't need to touch them. This API only manages TR resource for dynamic use. =20 Based on Tony's comments, we changed its implementation, and optimized it for checking overlap. Thank you, Tony!. Since the above four patches touch the source code out of kvm world, they need Tony's Ack and Sign-off-by :) [05] Add kvm.h, kvm_host.h kvm_para.h for kvm/ia64 [06] Add kvm arch-specific core code for kvm/ia64. [07] Add kvm sal/pal virtulization support. [08] Add local head files for kvm/ia64 The above four patches implement arch-specific code for kvm/ia64 [09] Add VMM module interfaces. [10] Add TLB virtulization support. [11] Add mmio decoder for kvm/ia64. [12] Add interruption vector table for vmm. [13] Add trampoline for guest/host mode switch. [14] Add processor virtulization support. [15] add optimization for some virtulization faults [16] Generate offset values for assembly code use. [17] Add guest interruption injection support. The above patches implement GVMM code. [18] Add Kconfig for kvm configuration. [19] Add Makefile for kvm files compile. [20] Update IA64 Kconfig and Makefile to include kvm build. [21] Readme for kvm/ia64=20 Update Makefile/Kconfig for kvm build, and write a howto for making kvm/ia64. Thanks Xiantao |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:32:43
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:26:29 +0800 Subject: [PATCH] kvm/ia64: Add TLB virtulization support. vtlb.c includes tlb/VHPT virtulization. Signed-off-by: Anthony Xu <ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/vtlb.c | 606 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 606 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/vtlb.c diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c new file mode 100644 index 0000000..25f9ad6 --- /dev/null +++ b/arch/ia64/kvm/vtlb.c @@ -0,0 +1,606 @@ +/* + * vtlb.c: guest virtual tlb handling module. + * Copyright (c) 2004, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Yaozu Dong (Eddie Dong) (Edd...@in...) + * Xuefei Xu (Anthony Xu) (ant...@in...) + */ + +#include "vcpu.h" + +/* + * Check to see if the address rid:va is translated by the TLB + */ + +static int __is_tr_translated(thash_data_t *trp, u64 rid, u64 va) +{ + return ((trp->p) && (trp->rid =3D=3D rid) + && ((va-trp->vadr) < PSIZE(trp->ps))); +} + +/* + * Only for GUEST TR format. + */ +static int __is_tr_overlap(thash_data_t *trp, u64 rid, u64 sva, u64 eva) +{ + u64 sa1, ea1; + + if (!trp->p || trp->rid !=3D rid) + return 0; + + sa1 =3D trp->vadr; + ea1 =3D sa1 + PSIZE(trp->ps) - 1; + eva -=3D 1; + if ((sva > ea1) || (sa1 > eva)) + return 0; + else + return 1; + +} + +void machine_tlb_purge(u64 va, u64 ps) +{ + ia64_ptcl(va, ps << 2); +} + +void local_flush_tlb_all(void) +{ + int i, j; + unsigned long flags, count0, count1; + unsigned long stride0, stride1, addr; + + addr =3D current_vcpu->arch.ptce_base; + count0 =3D current_vcpu->arch.ptce_count[0]; + count1 =3D current_vcpu->arch.ptce_count[1]; + stride0 =3D current_vcpu->arch.ptce_stride[0]; + stride1 =3D current_vcpu->arch.ptce_stride[1]; + + local_irq_save(flags); + for (i =3D 0; i < count0; ++i) { + for (j =3D 0; j < count1; ++j) { + ia64_ptce(addr); + addr +=3D stride1; + } + addr +=3D stride0; + } + local_irq_restore(flags); + ia64_srlz_i(); /* srlz.i implies srlz.d */ +} + +int vhpt_enabled(VCPU *vcpu, u64 vadr, vhpt_ref_t ref) +{ + ia64_rr vrr; + ia64_pta vpta; + ia64_psr vpsr; + + vpsr.val =3D VCPU(vcpu, vpsr); + vrr.val =3D vcpu_get_rr(vcpu, vadr); + vpta.val =3D vcpu_get_pta(vcpu); + + if (vrr.ve & vpta.ve) { + switch (ref) { + case DATA_REF: + case NA_REF: + return vpsr.dt; + case INST_REF: + return vpsr.dt && vpsr.it && vpsr.ic; + case RSE_REF: + return vpsr.dt && vpsr.rt; + + } + } + return 0; +} + +thash_data_t *vsa_thash(ia64_pta vpta, u64 va, u64 vrr, u64 *tag) +{ + u64 index, pfn, rid, pfn_bits; + + pfn_bits =3D vpta.size - 5 - 8; + pfn =3D REGION_OFFSET(va) >> _REGION_PAGE_SIZE(vrr); + rid =3D _REGION_ID(vrr); + index =3D ((rid & 0xff) << pfn_bits)|(pfn & ((1UL << pfn_bits) - 1)); + *tag =3D ((rid >> 8) & 0xffff) | ((pfn >> pfn_bits) << 16); + + return (thash_data_t *)((vpta.base << PTA_BASE_SHIFT) + (index << 5)); +} + +thash_data_t *__vtr_lookup(VCPU *vcpu, u64 va, int type) +{ + + thash_data_t *trp; + int i; + u64 rid; + + rid =3D vcpu_get_rr(vcpu, va); + rid =3D rid & RR_RID_MASK;; + if (type =3D=3D D_TLB) { + if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) { + for (trp =3D (thash_data_t *)&vcpu->arch.dtrs, i =3D 0; + i < NDTRS; i++, trp++) { + if (__is_tr_translated(trp, rid, va)) + return trp; + } + } + } else { + if (vcpu_quick_region_check(vcpu->arch.itr_regions, va)) { + for (trp =3D (thash_data_t *)&vcpu->arch.itrs, i =3D 0; + i < NITRS; i++, trp++) { + if (__is_tr_translated(trp, rid, va)) + return trp; + } + } + } + + return NULL; +} + +static void vhpt_insert(u64 pte, u64 itir, u64 ifa, u64 gpte) +{ + ia64_rr rr; + thash_data_t *head; + unsigned long ps, gpaddr; + + ps =3D itir_ps(itir); + + gpaddr =3D ((gpte & _PAGE_PPN_MASK) >> ps << ps) | + (ifa & ((1UL << ps) - 1)); + + rr.val =3D ia64_get_rr(ifa); + head =3D (thash_data_t *)ia64_thash(ifa); + head->etag =3D INVALID_TI_TAG; + ia64_mf(); + head->page_flags =3D pte & ~PAGE_FLAGS_RV_MASK; + head->itir =3D rr.ps << 2; + head->etag =3D ia64_ttag(ifa); + head->gpaddr =3D gpaddr; +} + +void thash_vhpt_insert(VCPU *v, u64 pte, u64 itir, u64 va, int type) +{ + u64 phy_pte, psr; + ia64_rr mrr; + + mrr.val =3D ia64_get_rr(va); + phy_pte =3D translate_phy_pte(&pte, itir, va); + + if (itir_ps(itir) >=3D mrr.ps) { + vhpt_insert(phy_pte, itir, va, pte); + } else { + phy_pte &=3D ~PAGE_FLAGS_RV_MASK; + psr =3D ia64_clear_ic(); + ia64_itc(type, va, phy_pte, itir_ps(itir)); + ia64_set_psr(psr); + ia64_srlz_i(); + } +} + +/* + * vhpt lookup + */ +thash_data_t *vhpt_lookup(u64 va) +{ + thash_data_t *head; + u64 tag; + + head =3D (thash_data_t *)ia64_thash(va); + tag =3D ia64_ttag(va); + if (head->etag =3D=3D tag) + return head; + return NULL; +} + +u64 guest_vhpt_lookup(u64 iha, u64 *pte) +{ + u64 ret; + thash_data_t *data; + + data =3D __vtr_lookup(current_vcpu, iha, D_TLB); + if (data !=3D NULL) + thash_vhpt_insert(current_vcpu, data->page_flags, + data->itir, iha, D_TLB); + + asm volatile ("rsm psr.ic|psr.i;;" + "srlz.d;;" + "ld8.s r9=3D[%1];;" + "tnat.nz p6,p7=3Dr9;;" + "(p6) mov %0=3D1;" + "(p6) mov r9=3Dr0;" + "(p7) extr.u r9=3Dr9,0,53;;" + "(p7) mov %0=3Dr0;" + "(p7) st8 [%2]=3Dr9;;" + "ssm psr.ic;;" + "srlz.d;;" + /* "ssm psr.i;;" Once interrupts in vmm open, need fix*/ + : "=3Dr"(ret) : "r"(iha), "r"(pte):"memory"); + + return ret; +} + +/* + * purge software guest tlb + */ + +static void vtlb_purge(VCPU *v, u64 va, u64 ps) +{ + thash_data_t *cur; + u64 start, curadr, size, psbits, tag, rr_ps, num; + ia64_rr vrr; + thash_cb_t *hcb =3D &v->arch.vtlb; + + vrr.val =3D vcpu_get_rr(v, va); + psbits =3D VMX(v, psbits[(va >> 61)]); + start =3D va & ~((1UL << ps) - 1); + while (psbits) { + curadr =3D start; + rr_ps =3D __ffs(psbits); + psbits &=3D ~(1UL << rr_ps); + num =3D 1UL << ((ps < rr_ps) ? 0 : (ps - rr_ps)); + size =3D PSIZE(rr_ps); + vrr.ps =3D rr_ps; + while (num) { + cur =3D vsa_thash(hcb->pta, curadr, vrr.val, &tag); + if (cur->etag =3D=3D tag && cur->ps =3D=3D rr_ps) + cur->etag =3D INVALID_TI_TAG; + curadr +=3D size; + num--; + } + } +} + + +/* + * purge VHPT and machine TLB + */ +static void vhpt_purge(VCPU *v, u64 va, u64 ps) +{ + thash_data_t *cur; + u64 start, size, tag, num; + ia64_rr rr; + + start =3D va & ~((1UL << ps) - 1); + rr.val =3D ia64_get_rr(va); + size =3D PSIZE(rr.ps); + num =3D 1UL << ((ps < rr.ps) ? 0 : (ps - rr.ps)); + while (num) { + cur =3D (thash_data_t *)ia64_thash(start); + tag =3D ia64_ttag(start); + if (cur->etag =3D=3D tag) + cur->etag =3D INVALID_TI_TAG; + start +=3D size; + num--; + } + machine_tlb_purge(va, ps); +} + +/* + * Insert an entry into hash TLB or VHPT. + * NOTES: + * 1: When inserting VHPT to thash, "va" is a must covered + * address by the inserted machine VHPT entry. + * 2: The format of entry is always in TLB. + * 3: The caller need to make sure the new entry will not overlap + * with any existed entry. + */ +void vtlb_insert(VCPU *v, u64 pte, u64 itir, u64 va) +{ + thash_data_t *head; + ia64_rr vrr; + u64 tag; + thash_cb_t *hcb =3D &v->arch.vtlb; + + vrr.val =3D vcpu_get_rr(v, va); + vrr.ps =3D itir_ps(itir); + VMX(v, psbits[va >> 61]) |=3D (1UL << vrr.ps); + head =3D vsa_thash(hcb->pta, va, vrr.val, &tag); + head->page_flags =3D pte; + head->itir =3D itir; + head->etag =3D tag; +} + +int vtr_find_overlap(VCPU *vcpu, u64 va, u64 ps, int type) +{ + thash_data_t *trp; + int i; + u64 end, rid; + + rid =3D vcpu_get_rr(vcpu, va); + rid =3D rid & RR_RID_MASK; + end =3D va + PSIZE(ps); + if (type =3D=3D D_TLB) { + if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) { + for (trp =3D (thash_data_t *)&vcpu->arch.dtrs, i =3D 0; + i < NDTRS; i++, trp++) { + if (__is_tr_overlap(trp, rid, va, end)) + return i; + } + } + } else { + if (vcpu_quick_region_check(vcpu->arch.itr_regions, va)) { + for (trp =3D (thash_data_t *)&vcpu->arch.itrs, i =3D 0; + i < NITRS; i++, trp++) { + if (__is_tr_overlap(trp, rid, va, end)) + return i; + } + } + } + return -1; +} + +/* + * Purge entries in VTLB and VHPT + */ +void thash_purge_entries(VCPU *v, u64 va, u64 ps) +{ + if (vcpu_quick_region_check(v->arch.tc_regions, va)) + vtlb_purge(v, va, ps); + vhpt_purge(v, va, ps); +} + +void thash_purge_entries_remote(VCPU *v, u64 va, u64 ps) +{ + u64 old_va =3D va; + va =3D REGION_OFFSET(va); + if (vcpu_quick_region_check(v->arch.tc_regions, old_va)) + vtlb_purge(v, va, ps); + vhpt_purge(v, va, ps); +} + +u64 translate_phy_pte(u64 *pte, u64 itir, u64 va) +{ + u64 ps, ps_mask, paddr, maddr; + union pte_flags phy_pte; + + ps =3D itir_ps(itir); + ps_mask =3D ~((1UL << ps) - 1); + phy_pte.val =3D *pte; + paddr =3D *pte; + paddr =3D ((paddr & _PAGE_PPN_MASK) & ps_mask) | (va & ~ps_mask); + maddr =3D kvm_lookup_mpa(paddr >> PAGE_SHIFT); + if (maddr & GPFN_IO_MASK) { + *pte |=3D VTLB_PTE_IO; + return -1; + } + maddr =3D ((maddr & _PAGE_PPN_MASK) & PAGE_MASK) | + (paddr & ~PAGE_MASK); + phy_pte.ppn =3D maddr >> ARCH_PAGE_SHIFT; + return phy_pte.val; +} + + +/* + * Purge overlap TCs and then insert the new entry to emulate itc ops. + * Notes: Only TC entry can purge and insert. + * 1 indicates this is MMIO + */ +int thash_purge_and_insert(VCPU *v, u64 pte, u64 itir, u64 ifa, int type) +{ + u64 ps; + u64 phy_pte; + ia64_rr vrr, mrr; + int ret =3D 0; + + ps =3D itir_ps(itir); + vrr.val =3D vcpu_get_rr(v, ifa); + mrr.val =3D ia64_get_rr(ifa); + + phy_pte =3D translate_phy_pte(&pte, itir, ifa); + + /* Ensure WB attribute if pte is related to a normal mem page, + * which is required by vga acceleration since qemu maps shared + * vram buffer with WB. + */ + if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) !=3D _PAGE_MA_NAT)) { + pte &=3D ~_PAGE_MA_MASK; + phy_pte &=3D ~_PAGE_MA_MASK; + } + + if (pte & VTLB_PTE_IO) + ret =3D 1; + + vtlb_purge(v, ifa, ps); + vhpt_purge(v, ifa, ps); + + if (ps =3D=3D mrr.ps) { + if (!(pte&VTLB_PTE_IO)) { + vhpt_insert(phy_pte, itir, ifa, pte); + } else { + vtlb_insert(v, pte, itir, ifa); + vcpu_quick_region_set(VMX(v, tc_regions), ifa); + } + } else if (ps > mrr.ps) { + vtlb_insert(v, pte, itir, ifa); + vcpu_quick_region_set(VMX(v, tc_regions), ifa); + if (!(pte&VTLB_PTE_IO)) + vhpt_insert(phy_pte, itir, ifa, pte); + } else { + u64 psr; + phy_pte &=3D ~PAGE_FLAGS_RV_MASK; + psr =3D ia64_clear_ic(); + ia64_itc(type, ifa, phy_pte, ps); + ia64_set_psr(psr); + ia64_srlz_i(); + } + + return ret; +} + +/* + * Purge all TCs or VHPT entries including those in Hash table. + * + */ + +void thash_purge_all(VCPU *v) +{ + int i; + thash_data_t *head; + thash_cb_t *vtlb, *vhpt; + vtlb =3D &v->arch.vtlb; + vhpt =3D &v->arch.vhpt; + + for (i =3D 0; i < 8; i++) + VMX(v, psbits[i]) =3D 0; + + head =3D vtlb->hash; + for (i =3D 0; i < vtlb->num; i++) { + head->page_flags =3D 0; + head->etag =3D INVALID_TI_TAG; + head->itir =3D 0; + head->next =3D 0; + head++; + }; + + head =3D vhpt->hash; + for (i =3D 0; i < vhpt->num; i++) { + head->page_flags =3D 0; + head->etag =3D INVALID_TI_TAG; + head->itir =3D 0; + head->next =3D 0; + head++; + }; + + local_flush_tlb_all(); +} + + +/* + * Lookup the hash table and its collision chain to find an entry + * covering this address rid:va or the entry. + * + * INPUT: + * in: TLB format for both VHPT & TLB. + */ + +thash_data_t *vtlb_lookup(VCPU *v, u64 va, int is_data) +{ + thash_data_t *cch; + u64 psbits, ps, tag; + ia64_rr vrr; + + thash_cb_t *hcb =3D &v->arch.vtlb; + + cch =3D __vtr_lookup(v, va, is_data);; + if (cch) + return cch; + + if (vcpu_quick_region_check(v->arch.tc_regions, va) =3D=3D 0) + return NULL; + + psbits =3D VMX(v, psbits[(va >> 61)]); + vrr.val =3D vcpu_get_rr(v, va); + while (psbits) { + ps =3D __ffs(psbits); + psbits &=3D ~(1UL << ps); + vrr.ps =3D ps; + cch =3D vsa_thash(hcb->pta, va, vrr.val, &tag); + if (cch->etag =3D=3D tag && cch->ps =3D=3D ps) + return cch; + } + + return NULL; +} + + +/* + * Initialize internal control data before service. + */ +void thash_init(thash_cb_t *hcb, u64 sz) +{ + int i; + thash_data_t *head; + + hcb->pta.val =3D (unsigned long)hcb->hash; + hcb->pta.vf =3D 1; + hcb->pta.ve =3D 1; + hcb->pta.size =3D sz; + head =3D hcb->hash; + for (i =3D 0; i < hcb->num; i++) { + head->page_flags =3D 0; + head->itir =3D 0; + head->etag =3D INVALID_TI_TAG; + head->next =3D 0; + head++; + } +} + +u64 kvm_lookup_mpa(u64 gpfn) +{ + u64 *base =3D (u64 *) KVM_P2M_BASE; + return *(base + gpfn); +} + +u64 kvm_gpa_to_mpa(u64 gpa) +{ + u64 pte =3D kvm_lookup_mpa(gpa >> PAGE_SHIFT); + return (pte >> PAGE_SHIFT << PAGE_SHIFT) | (gpa & ~PAGE_MASK); +} + + +/* + * Fetch guest bundle code. + * INPUT: + * gip: guest ip + * pbundle: used to return fetched bundle. + */ +int fetch_code(VCPU *vcpu, u64 gip, IA64_BUNDLE *pbundle) +{ + u64 gpip =3D 0; /* guest physical IP*/ + u64 *vpa; + thash_data_t *tlb; + u64 maddr; + + if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) { + /* I-side physical mode */ + gpip =3D gip; + } else { + tlb =3D vtlb_lookup(vcpu, gip, I_TLB); + if (tlb) + gpip =3D (tlb->ppn >> (tlb->ps - 12) << tlb->ps) | + (gip & (PSIZE(tlb->ps) - 1)); + } + if (gpip) { + maddr =3D kvm_gpa_to_mpa(gpip); + } else { + tlb =3D vhpt_lookup(gip); + if (tlb =3D=3D NULL) { + ia64_ptcl(gip, ARCH_PAGE_SHIFT << 2); + return IA64_FAULT; + } + maddr =3D (tlb->ppn >> (tlb->ps - 12) << tlb->ps) + | (gip & (PSIZE(tlb->ps) - 1)); + } + vpa =3D (u64 *)__kvm_va(maddr); + + pbundle->i64[0] =3D *vpa++; + pbundle->i64[1] =3D *vpa; + + return IA64_NO_FAULT; +} + + +void kvm_init_vhpt(VCPU *v) +{ + v->arch.vhpt.num =3D VHPT_NUM_ENTRIES; + thash_init(&v->arch.vhpt, VHPT_SHIFT); + ia64_set_pta(v->arch.vhpt.pta.val); + /*Enable VHPT here?*/ +} + +void kvm_init_vtlb(VCPU *v) +{ + v->arch.vtlb.num =3D VTLB_NUM_ENTRIES; + thash_init(&v->arch.vtlb, VTLB_SHIFT); +} --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:32:25
|
From: Zhang Xiantao <xia...@in...> Date: Thu, 31 Jan 2008 17:10:52 +0800 Subject: [PATCH] Add API for allocating TR resouce. Dynamic TR resouce should be managed in an uniform way. Signed-off-by: Xiantao Zhang <xia...@in...> Signed-off-by: Anthony Xu<ant...@in...> --- arch/ia64/kernel/mca.c | 50 +++++++++++++ arch/ia64/kernel/mca_asm.S | 5 ++ arch/ia64/mm/tlb.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/kregs.h | 3 + include/asm-ia64/tlb.h | 12 +++ 5 files changed, 237 insertions(+), 0 deletions(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 6dbf591..4253343 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -89,6 +89,7 @@ =20 #include <asm/irq.h> #include <asm/hw_irq.h> +#include <asm/tlb.h> =20 #include "mca_drv.h" #include "entry.h" @@ -104,8 +105,10 @@ DEFINE_PER_CPU(u64, ia64_mca_data); /* =3D=3D __per_cpu_mca[smp_processor_id()] */ DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */ DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */ DEFINE_PER_CPU(u64, ia64_mca_pal_base); /* vaddr PAL code granule */ +DEFINE_PER_CPU(u64, ia64_mca_tr_reload); /* Flag for TR reload */ =20 unsigned long __per_cpu_mca[NR_CPUS]; +extern struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX]; =20 /* In mca_asm.S */ extern void ia64_os_init_dispatch_monarch (void); @@ -1177,6 +1180,49 @@ all_in: return; } =20 +/* mca_insert_tr + * + * Switch rid when TR reload and needed! + * iord: 1: itr, 2: itr; + * +*/ +static void mca_insert_tr(u64 iord) +{ + + int i; + u64 old_rr; + struct ia64_tr_entry *p; + unsigned long psr; + int cpu =3D smp_processor_id(); + + psr =3D ia64_clear_ic(); + for (i =3D IA64_TR_ALLOC_BASE; i < IA64_TR_ALLOC_MAX; i++) { + p =3D &__per_cpu_idtrs[cpu][iord-1][i]; + if (p->pte&0x1) { + old_rr =3D ia64_get_rr(p->ifa); + if (old_rr !=3D p->rr) { + ia64_set_rr(p->ifa, p->rr); + ia64_srlz_d(); + } + ia64_ptr(iord, p->ifa, p->itir >> 2); + ia64_srlz_i(); + if (iord & 0x1) { + ia64_itr(0x1, i, p->ifa, p->pte, p->itir >> 2); + ia64_srlz_i(); + } + if (iord & 0x2) { + ia64_itr(0x2, i, p->ifa, p->pte, p->itir >> 2); + ia64_srlz_i(); + } + if (old_rr !=3D p->rr) { + ia64_set_rr(p->ifa, old_rr); + ia64_srlz_d(); + } + } + } + ia64_set_psr(psr); +} + /* * ia64_mca_handler * @@ -1266,6 +1312,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, monarch_cpu =3D -1; #endif } + if (__get_cpu_var(ia64_mca_tr_reload)) { + mca_insert_tr(0x1); /*Reload dynamic itrs*/ + mca_insert_tr(0x2); /*Reload dynamic itrs*/ + } if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover) =3D=3D NOTIFY_STOP) ia64_mca_spin(__FUNCTION__); diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 0f5965f..dd37dd0 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -215,8 +215,13 @@ ia64_reload_tr: mov r20=3DIA64_TR_CURRENT_STACK ;; itr.d dtr[r20]=3Dr16 + GET_THIS_PADDR(r2, ia64_mca_tr_reload) + mov r18 =3D 1 ;; srlz.d + ;; + st8 [r2] =3Dr18 + ;; =20 done_tlb_purge_and_reload: =20 diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 655da24..e27e101 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -26,6 +26,8 @@ #include <asm/pal.h> #include <asm/tlbflush.h> #include <asm/dma.h> +#include <asm/processor.h> +#include <asm/tlb.h> =20 static struct { unsigned long mask; /* mask of supported purge page-sizes */ @@ -39,6 +41,10 @@ struct ia64_ctx ia64_ctx =3D { }; =20 DEFINE_PER_CPU(u8, ia64_need_tlb_flush); +DEFINE_PER_CPU(u8, ia64_tr_num); /*Number of TR slots in current processor*/ +DEFINE_PER_CPU(u8, ia64_tr_used); /*Max Slot number used by kernel*/ + +struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX]; =20 /* * Initializes the ia64_ctx.bitmap array based on max_ctx+1. @@ -190,6 +196,9 @@ ia64_tlb_init (void) ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */ unsigned long tr_pgbits; long status; + pal_vm_info_1_u_t vm_info_1; + pal_vm_info_2_u_t vm_info_2; + int cpu =3D smp_processor_id(); =20 if ((status =3D ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) !=3D 0) { printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=3D%ld; " @@ -206,4 +215,162 @@ ia64_tlb_init (void) local_cpu_data->ptce_stride[1] =3D ptce_info.stride[1]; =20 local_flush_tlb_all(); /* nuke left overs from bootstrapping... */ + + if ((status =3D ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=3D 0) { + printk(KERN_ERR "ia64_pal_vm_summary=3D%ld\n", status); + per_cpu(ia64_tr_num, cpu) =3D 8; + return; + } + per_cpu(ia64_tr_num, cpu) =3D vm_info_1.pal_vm_info_1_s.max_itr_entry+1; + if (per_cpu(ia64_tr_num, cpu) >=20 + (vm_info_1.pal_vm_info_1_s.max_dtr_entry+1)) + per_cpu(ia64_tr_num, cpu) =3D vm_info_1.pal_vm_info_1_s.max_dtr_entry+1; +} + +/* + * is_tr_overlap + * + * Check overlap with inserted TRs. + */ +static int is_tr_overlap(struct ia64_tr_entry *p, u64 va, u64 log_size) +{ + u64 tr_log_size; + u64 tr_end; + u64 va_rr =3D ia64_get_rr(va); + u64 va_rid =3D RR_TO_RID(va_rr); + u64 va_end =3D va + (1<<log_size) - 1; + + if (va_rid !=3D RR_TO_RID(p->rr)) + return 0; + tr_log_size =3D (p->itir & 0xff) >> 2; + tr_end =3D p->ifa + (1<<tr_log_size) - 1; + + if (va > tr_end || p->ifa > va_end) + return 0; + return 1; + +} + +/* + * ia64_insert_tr in virtual mode. Allocate a TR slot + * + * target_mask : 0x1 : itr, 0x2 : dtr, 0x3 : idtr + * + * va : virtual address. + * pte : pte entries inserted. + * log_size: range to be covered. + * + * Return value: <0 : error No. + * + * >=3D0 : slot number allocated for TR. + */ +int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size) +{ + int i, r; + unsigned long psr; + struct ia64_tr_entry *p; + int cpu =3D smp_processor_id(); + + r =3D -EINVAL; + /*Check overlap with existing TR entries*/ + if (target_mask&0x1) { + p =3D &__per_cpu_idtrs[cpu][0][0]; + for (i =3D IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_used, cpu); + i++, p++) { + if (p->pte&0x1) + if (is_tr_overlap(p, va, log_size)) + goto out; + } + } + if (target_mask&0x2) { + p =3D &__per_cpu_idtrs[cpu][1][0]; + for (i =3D IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_used, cpu); + i++, p++) { + if (p->pte&0x1) + if (is_tr_overlap(p, va, log_size)) + goto out; + } + } + + for (i =3D IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_num, cpu); i++) { + switch (target_mask & 0x3) { + case 1: + if (!(__per_cpu_idtrs[cpu][0][i].pte&0x1)) + goto found; + continue; + case 2: + if (!(__per_cpu_idtrs[cpu][1][i].pte&0x1)) + goto found; + continue; + case 3: + if (!(__per_cpu_idtrs[cpu][0][i].pte&0x1) && + !(__per_cpu_idtrs[cpu][1][i].pte&0x1)) + goto found; + continue; + default: + r =3D -EINVAL; + goto out; + } + } +found: + /*Record tr info for mca hander use!*/ + if (i > per_cpu(ia64_tr_used, cpu)) + per_cpu(ia64_tr_used, cpu) =3D i; + + psr =3D ia64_clear_ic(); + if (target_mask & 0x1) { + ia64_itr(0x1, i, va, pte, log_size); + ia64_srlz_i(); + p =3D &__per_cpu_idtrs[cpu][0][i]; + p->ifa =3D va; + p->pte =3D pte; + p->itir =3D log_size << 2; + p->rr =3D ia64_get_rr(va); + } + if (target_mask & 0x2) { + ia64_itr(0x2, i, va, pte, log_size); + ia64_srlz_i(); + p =3D &__per_cpu_idtrs[cpu][1][i]; + p->ifa =3D va; + p->pte =3D pte; + p->itir =3D log_size << 2; + p->rr =3D ia64_get_rr(va); + } + ia64_set_psr(psr); + r =3D i; +out: + return r; +} +EXPORT_SYMBOL_GPL(ia64_itr_entry); + +/* + * ia64_purge_tr + * + * target_mask: 0x1: purge itr, 0x2 : purge dtr, 0x3 purge idtr. + * va: begin address to be purged + * log_size: size to purege. + * + */ +void ia64_ptr_entry(u64 target_mask, u64 va, u64 log_size) +{ + int i; + int cpu =3D smp_processor_id(); + struct ia64_tr_entry *p; + + ia64_ptr(target_mask, va, log_size); + ia64_srlz_i(); + + for (i =3D IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_used, cpu); i++) { + if (target_mask&0x1) { + p =3D &__per_cpu_idtrs[cpu][0][i]; + if ((p->pte&0x1) && is_tr_overlap(p, va, log_size)) + p->pte =3D 0; + } + if (target_mask&0x2) { + p =3D &__per_cpu_idtrs[cpu][1][i]; + if ((p->pte&0x1) && is_tr_overlap(p, va, log_size)) + p->pte =3D 0; + } + } } +EXPORT_SYMBOL_GPL(ia64_ptr_entry); diff --git a/include/asm-ia64/kregs.h b/include/asm-ia64/kregs.h index 7e55a58..aefcdfe 100644 --- a/include/asm-ia64/kregs.h +++ b/include/asm-ia64/kregs.h @@ -31,6 +31,9 @@ #define IA64_TR_PALCODE 1 /* itr1: maps PALcode as required by EFI */ #define IA64_TR_CURRENT_STACK 1 /* dtr1: maps kernel's memory- & register-stacks */ =20 +#define IA64_TR_ALLOC_BASE 2 /* itr&dtr: Base of dynamic TR resource*/ +#define IA64_TR_ALLOC_MAX 32 /* Max number for dynamic use*/ + /* Processor status register bits: */ #define IA64_PSR_BE_BIT 1 #define IA64_PSR_UP_BIT 2 diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h index 26edcb7..f57a8c1 100644 --- a/include/asm-ia64/tlb.h +++ b/include/asm-ia64/tlb.h @@ -64,6 +64,18 @@ struct mmu_gather { struct page *pages[FREE_PTE_NR]; }; =20 +struct ia64_tr_entry { + u64 ifa; + u64 itir; + u64 pte; + u64 rr; +}; /*Record for tr entry!*/ + +extern int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size); +extern void ia64_ptr_entry(u64 target_mask, u64 va, u64 log_size); + +#define RR_TO_RID(rr) ((rr)<<32>>40) + /* Users of the generic TLB shootdown code must declare this storage space. */ DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); =20 --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:31:14
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 15:40:27 +0800 Subject: [PATCH] kvm/ia64: Update IA64 Kconfig and Makefile to include kvm build. Update IA64 Kconfig and Makefile to include kvm build. Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/Kconfig | 6 ++++++ arch/ia64/Makefile | 1 + 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index bef4772..4592130 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -99,6 +99,10 @@ config AUDIT_ARCH bool default y =20 +config ARCH_SUPPORTS_KVM + bool + default y + choice prompt "System type" default IA64_GENERIC @@ -568,6 +572,8 @@ config MSPEC =20 source "fs/Kconfig" =20 +source "arch/ia64/kvm/Kconfig" + source "lib/Kconfig" =20 # diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index b916ccf..c8d09be 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -55,6 +55,7 @@ core-$(CONFIG_IA64_GENERIC) +=3D arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) +=3D arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) +=3D arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN2) +=3D arch/ia64/sn/ +core-$(CONFIG_KVM) +=3D arch/ia64/kvm/ =20 drivers-$(CONFIG_PCI) +=3D arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) +=3D arch/ia64/hp/sim/ --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:31:09
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:40:41 +0800 Subject: [PATCH] kvm/ia64: Generate offset values for assembly code use. asm-offsets.c will generate offset values used for assembly code for some fileds of special structures. Signed-off-by: Anthony Xu <ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/asm-offsets.c | 251 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 251 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/asm-offsets.c diff --git a/arch/ia64/kvm/asm-offsets.c b/arch/ia64/kvm/asm-offsets.c new file mode 100644 index 0000000..d9a164d --- /dev/null +++ b/arch/ia64/kvm/asm-offsets.c @@ -0,0 +1,251 @@ +/* + * asm-offsets.c Generate definitions needed by assembly language modules. + * This code generates raw asm output which is post-processed + * to extract and format the required data. + * + * Anthony Xu <ant...@in...> + * Zhang Xiantao <xia...@in...> + * Copyright (c) 2007 Intel Corporation KVM support. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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/autoconf.h> +#include <linux/kvm_host.h> + +#include "vcpu.h" + +#define task_struct kvm_vcpu + +#define DEFINE(sym, val) \ + asm volatile("\n->" #sym " (%0) " #val : : "i" (val)) + +#define BLANK() asm volatile("\n->" : :) + +#define OFFSET(_sym, _str, _mem) \ + DEFINE(_sym, offsetof(_str, _mem)); + +void foo(void) +{ + DEFINE(VMM_TASK_SIZE, sizeof(struct kvm_vcpu)); + DEFINE(VMM_PT_REGS_SIZE, sizeof(struct kvm_pt_regs)); + + BLANK(); + + DEFINE(VMM_VCPU_META_RR0_OFFSET, + offsetof(struct kvm_vcpu, arch.metaphysical_rr0)); + DEFINE(VMM_VCPU_META_SAVED_RR0_OFFSET, + offsetof(struct kvm_vcpu, + arch.metaphysical_saved_rr0)); + DEFINE(VMM_VCPU_VRR0_OFFSET, + offsetof(struct kvm_vcpu, arch.vrr[0])); + DEFINE(VMM_VPD_IRR0_OFFSET, + offsetof(struct vpd, irr[0])); + DEFINE(VMM_VCPU_ITC_CHECK_OFFSET, + offsetof(struct kvm_vcpu, arch.itc_check)); + DEFINE(VMM_VCPU_IRQ_CHECK_OFFSET, + offsetof(struct kvm_vcpu, arch.irq_check)); + DEFINE(VMM_VPD_VHPI_OFFSET, + offsetof(struct vpd, vhpi)); + DEFINE(VMM_VCPU_VSA_BASE_OFFSET, + offsetof(struct kvm_vcpu, arch.vsa_base)); + DEFINE(VMM_VCPU_VPD_OFFSET, + offsetof(struct kvm_vcpu, arch.vpd)); + DEFINE(VMM_VCPU_IRQ_CHECK, + offsetof(struct kvm_vcpu, arch.irq_check)); + DEFINE(VMM_VCPU_TIMER_PENDING, + offsetof(struct kvm_vcpu, arch.timer_pending)); + DEFINE(VMM_VCPU_META_SAVED_RR0_OFFSET, + offsetof(struct kvm_vcpu, arch.metaphysical_saved_rr0)); + DEFINE(VMM_VCPU_MODE_FLAGS_OFFSET, + offsetof(struct kvm_vcpu, arch.mode_flags)); + DEFINE(VMM_VCPU_ITC_OFS_OFFSET, + offsetof(struct kvm_vcpu, arch.itc_offset)); + DEFINE(VMM_VCPU_LAST_ITC_OFFSET, + offsetof(struct kvm_vcpu, arch.last_itc)); + DEFINE(VMM_VCPU_SAVED_GP_OFFSET, + offsetof(struct kvm_vcpu, arch.saved_gp)); + + BLANK(); + + DEFINE(VMM_PT_REGS_B6_OFFSET, + offsetof(struct kvm_pt_regs, b6)); + DEFINE(VMM_PT_REGS_B7_OFFSET, + offsetof(struct kvm_pt_regs, b7)); + DEFINE(VMM_PT_REGS_AR_CSD_OFFSET, + offsetof(struct kvm_pt_regs, ar_csd)); + DEFINE(VMM_PT_REGS_AR_SSD_OFFSET, + offsetof(struct kvm_pt_regs, ar_ssd)); + DEFINE(VMM_PT_REGS_R8_OFFSET, + offsetof(struct kvm_pt_regs, r8)); + DEFINE(VMM_PT_REGS_R9_OFFSET, + offsetof(struct kvm_pt_regs, r9)); + DEFINE(VMM_PT_REGS_R10_OFFSET, + offsetof(struct kvm_pt_regs, r10)); + DEFINE(VMM_PT_REGS_R11_OFFSET, + offsetof(struct kvm_pt_regs, r11)); + DEFINE(VMM_PT_REGS_CR_IPSR_OFFSET, + offsetof(struct kvm_pt_regs, cr_ipsr)); + DEFINE(VMM_PT_REGS_CR_IIP_OFFSET, + offsetof(struct kvm_pt_regs, cr_iip)); + DEFINE(VMM_PT_REGS_CR_IFS_OFFSET, + offsetof(struct kvm_pt_regs, cr_ifs)); + DEFINE(VMM_PT_REGS_AR_UNAT_OFFSET, + offsetof(struct kvm_pt_regs, ar_unat)); + DEFINE(VMM_PT_REGS_AR_PFS_OFFSET, + offsetof(struct kvm_pt_regs, ar_pfs)); + DEFINE(VMM_PT_REGS_AR_RSC_OFFSET, + offsetof(struct kvm_pt_regs, ar_rsc)); + DEFINE(VMM_PT_REGS_AR_RNAT_OFFSET, + offsetof(struct kvm_pt_regs, ar_rnat)); + + DEFINE(VMM_PT_REGS_AR_BSPSTORE_OFFSET, + offsetof(struct kvm_pt_regs, ar_bspstore)); + DEFINE(VMM_PT_REGS_PR_OFFSET, + offsetof(struct kvm_pt_regs, pr)); + DEFINE(VMM_PT_REGS_B0_OFFSET, + offsetof(struct kvm_pt_regs, b0)); + DEFINE(VMM_PT_REGS_LOADRS_OFFSET, + offsetof(struct kvm_pt_regs, loadrs)); + DEFINE(VMM_PT_REGS_R1_OFFSET, + offsetof(struct kvm_pt_regs, r1)); + DEFINE(VMM_PT_REGS_R12_OFFSET, + offsetof(struct kvm_pt_regs, r12)); + DEFINE(VMM_PT_REGS_R13_OFFSET, + offsetof(struct kvm_pt_regs, r13)); + DEFINE(VMM_PT_REGS_AR_FPSR_OFFSET, + offsetof(struct kvm_pt_regs, ar_fpsr)); + DEFINE(VMM_PT_REGS_R15_OFFSET, + offsetof(struct kvm_pt_regs, r15)); + DEFINE(VMM_PT_REGS_R14_OFFSET, + offsetof(struct kvm_pt_regs, r14)); + DEFINE(VMM_PT_REGS_R2_OFFSET, + offsetof(struct kvm_pt_regs, r2)); + DEFINE(VMM_PT_REGS_R3_OFFSET, + offsetof(struct kvm_pt_regs, r3)); + DEFINE(VMM_PT_REGS_R16_OFFSET, + offsetof(struct kvm_pt_regs, r16)); + DEFINE(VMM_PT_REGS_R17_OFFSET, + offsetof(struct kvm_pt_regs, r17)); + DEFINE(VMM_PT_REGS_R18_OFFSET, + offsetof(struct kvm_pt_regs, r18)); + DEFINE(VMM_PT_REGS_R19_OFFSET, + offsetof(struct kvm_pt_regs, r19)); + DEFINE(VMM_PT_REGS_R20_OFFSET, + offsetof(struct kvm_pt_regs, r20)); + DEFINE(VMM_PT_REGS_R21_OFFSET, + offsetof(struct kvm_pt_regs, r21)); + DEFINE(VMM_PT_REGS_R22_OFFSET, + offsetof(struct kvm_pt_regs, r22)); + DEFINE(VMM_PT_REGS_R23_OFFSET, + offsetof(struct kvm_pt_regs, r23)); + DEFINE(VMM_PT_REGS_R24_OFFSET, + offsetof(struct kvm_pt_regs, r24)); + DEFINE(VMM_PT_REGS_R25_OFFSET, + offsetof(struct kvm_pt_regs, r25)); + DEFINE(VMM_PT_REGS_R26_OFFSET, + offsetof(struct kvm_pt_regs, r26)); + DEFINE(VMM_PT_REGS_R27_OFFSET, + offsetof(struct kvm_pt_regs, r27)); + DEFINE(VMM_PT_REGS_R28_OFFSET, + offsetof(struct kvm_pt_regs, r28)); + DEFINE(VMM_PT_REGS_R29_OFFSET, + offsetof(struct kvm_pt_regs, r29)); + DEFINE(VMM_PT_REGS_R30_OFFSET, + offsetof(struct kvm_pt_regs, r30)); + DEFINE(VMM_PT_REGS_R31_OFFSET, + offsetof(struct kvm_pt_regs, r31)); + DEFINE(VMM_PT_REGS_AR_CCV_OFFSET, + offsetof(struct kvm_pt_regs, ar_ccv)); + DEFINE(VMM_PT_REGS_F6_OFFSET, + offsetof(struct kvm_pt_regs, f6)); + DEFINE(VMM_PT_REGS_F7_OFFSET, + offsetof(struct kvm_pt_regs, f7)); + DEFINE(VMM_PT_REGS_F8_OFFSET, + offsetof(struct kvm_pt_regs, f8)); + DEFINE(VMM_PT_REGS_F9_OFFSET, + offsetof(struct kvm_pt_regs, f9)); + DEFINE(VMM_PT_REGS_F10_OFFSET, + offsetof(struct kvm_pt_regs, f10)); + DEFINE(VMM_PT_REGS_F11_OFFSET, + offsetof(struct kvm_pt_regs, f11)); + DEFINE(VMM_PT_REGS_R4_OFFSET, + offsetof(struct kvm_pt_regs, r4)); + DEFINE(VMM_PT_REGS_R5_OFFSET, + offsetof(struct kvm_pt_regs, r5)); + DEFINE(VMM_PT_REGS_R6_OFFSET, + offsetof(struct kvm_pt_regs, r6)); + DEFINE(VMM_PT_REGS_R7_OFFSET, + offsetof(struct kvm_pt_regs, r7)); + DEFINE(VMM_PT_REGS_EML_UNAT_OFFSET, + offsetof(struct kvm_pt_regs, eml_unat)); + DEFINE(VMM_VCPU_IIPA_OFFSET, + offsetof(struct kvm_vcpu, arch.cr_iipa)); + DEFINE(VMM_VCPU_OPCODE_OFFSET, + offsetof(struct kvm_vcpu, arch.opcode)); + DEFINE(VMM_VCPU_CAUSE_OFFSET, offsetof(struct kvm_vcpu, arch.cause)); + DEFINE(VMM_VCPU_ISR_OFFSET, + offsetof(struct kvm_vcpu, arch.cr_isr)); + DEFINE(VMM_PT_REGS_R16_SLOT, + (((offsetof(struct kvm_pt_regs, r16) + - sizeof(struct kvm_pt_regs)) >> 3) & 0x3f)); + DEFINE(VMM_VCPU_MODE_FLAGS_OFFSET, + offsetof(struct kvm_vcpu, arch.mode_flags)); + DEFINE(VMM_VCPU_GP_OFFSET, offsetof(struct kvm_vcpu, arch.__gp)); + BLANK(); + + DEFINE(VMM_VPD_BASE_OFFSET, offsetof(struct kvm_vcpu, arch.vpd)); + DEFINE(VMM_VPD_VIFS_OFFSET, offsetof(struct vpd, ifs)); + DEFINE(VMM_VLSAPIC_INSVC_BASE_OFFSET, + offsetof(struct kvm_vcpu, arch.insvc[0])); + DEFINE(VMM_VPD_VPTA_OFFSET, offsetof(struct vpd, pta)); + DEFINE(VMM_VPD_VPSR_OFFSET, offsetof(struct vpd, vpsr)); + + DEFINE(VMM_CTX_R4_OFFSET, offsetof(context_t, gr[4])); + DEFINE(VMM_CTX_R5_OFFSET, offsetof(context_t, gr[5])); + DEFINE(VMM_CTX_R12_OFFSET, offsetof(context_t, gr[12])); + DEFINE(VMM_CTX_R13_OFFSET, offsetof(context_t, gr[13])); + DEFINE(VMM_CTX_KR0_OFFSET, offsetof(context_t, ar[0])); + DEFINE(VMM_CTX_KR1_OFFSET, offsetof(context_t, ar[1])); + DEFINE(VMM_CTX_B0_OFFSET, offsetof(context_t, br[0])); + DEFINE(VMM_CTX_B1_OFFSET, offsetof(context_t, br[1])); + DEFINE(VMM_CTX_B2_OFFSET, offsetof(context_t, br[2])); + DEFINE(VMM_CTX_RR0_OFFSET, offsetof(context_t, rr[0])); + DEFINE(VMM_CTX_RSC_OFFSET, offsetof(context_t, ar[16])); + DEFINE(VMM_CTX_BSPSTORE_OFFSET, offsetof(context_t, ar[18])); + DEFINE(VMM_CTX_RNAT_OFFSET, offsetof(context_t, ar[19])); + DEFINE(VMM_CTX_FCR_OFFSET, offsetof(context_t, ar[21])); + DEFINE(VMM_CTX_EFLAG_OFFSET, offsetof(context_t, ar[24])); + DEFINE(VMM_CTX_CFLG_OFFSET, offsetof(context_t, ar[27])); + DEFINE(VMM_CTX_FSR_OFFSET, offsetof(context_t, ar[28])); + DEFINE(VMM_CTX_FIR_OFFSET, offsetof(context_t, ar[29])); + DEFINE(VMM_CTX_FDR_OFFSET, offsetof(context_t, ar[30])); + DEFINE(VMM_CTX_UNAT_OFFSET, offsetof(context_t, ar[36])); + DEFINE(VMM_CTX_FPSR_OFFSET, offsetof(context_t, ar[40])); + DEFINE(VMM_CTX_PFS_OFFSET, offsetof(context_t, ar[64])); + DEFINE(VMM_CTX_LC_OFFSET, offsetof(context_t, ar[65])); + DEFINE(VMM_CTX_DCR_OFFSET, offsetof(context_t, cr[0])); + DEFINE(VMM_CTX_IVA_OFFSET, offsetof(context_t, cr[2])); + DEFINE(VMM_CTX_PTA_OFFSET, offsetof(context_t, cr[8])); + DEFINE(VMM_CTX_IBR0_OFFSET, offsetof(context_t, ibr[0])); + DEFINE(VMM_CTX_DBR0_OFFSET, offsetof(context_t, dbr[0])); + DEFINE(VMM_CTX_F2_OFFSET, offsetof(context_t, fr[2])); + DEFINE(VMM_CTX_F3_OFFSET, offsetof(context_t, fr[3])); + DEFINE(VMM_CTX_F32_OFFSET, offsetof(context_t, fr[32])); + DEFINE(VMM_CTX_F33_OFFSET, offsetof(context_t, fr[33])); + DEFINE(VMM_CTX_PKR0_OFFSET, offsetof(context_t, pkr[0])); + DEFINE(VMM_CTX_PSR_OFFSET, offsetof(context_t, psr)); + BLANK(); +} --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:31:09
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 17:27:06 +0800 Subject: [PATCH] README: How to boot up guests on kvm/ia64 Guide: How to boot up guests on kvm/ia64 Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/README | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 72 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/README diff --git a/arch/ia64/kvm/README b/arch/ia64/kvm/README new file mode 100644 index 0000000..22b1db7 --- /dev/null +++ b/arch/ia64/kvm/README @@ -0,0 +1,72 @@ + Guide: How to boot up guests on kvm/ia64 + +1. Get the kvm source from git.kernel.org. + Userspace source: + git clone git://git.kernel.org/pub/scm/virt/kvm/kvm-userspace.git + Kernel Source: + git clone git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm.git +2. Compile the source code. + 2.1 Compile userspace code: + (1)cd ./kvm-userspace + (2)./configure + (3)cd kernel + (4)make sync LINUX=3D $kernel_dir (kernel_dir is the directory of kernel source.) + (5)cd .. + (6)make qemu + (7)cd qemu; make install + 2.2 Compile kernel source code: + (1) cd ./$kernel_dir + (2) Make menuconfig=20 + (3) Enter into virtualization option, and choose kvm. + (4) make=20 + (5) Once (4) done, make modules_install + (6) Make initrd, and use new kernel to reboot up host machine. + (7) Once (6) done, cd $kernel_dir/arch/ia64/kvm + (8) insmod kvm.ko; insmod kvm-intel.ko + +Note: For step 2, please make sure that host page size =3D=3D TARGET_PAGE_SIZE of qemu, otherwise, may fail. + +3. Get Guest Firmware named as Flash.fd, and put it under right place: + (1) If you have the guest firmware (binary)released by Intel Corp for Xen, you can use it directly. + (2) If you want to build a guest firmware form souce code. Please download the source from + hg clone http://xenbits.xensource.com/ext/efi-vfirmware.hg + Use the Guide of the source to build open Guest Firmware. + (3) Rename it to Flash.fd, and copy it to /usr/local/share/qemu +Note: For step 3, kvm use the guest firmware which complies with the one Xen uses. + +4. Boot up Linux or Windows guests: + 4.1 Create or install a image for guest boot. If you have xen experience, it should be easy. + + 4.2 Boot up guests use the following command. + /usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image + (xx is the number of virtual processors for the guest, now the maximum value is 4) + +5. Known possbile issue on some platforms with old Firmware + +If meet strange host crashes, you may try to solve it through either of the following methods. +(1): Upgrade your Firmware to the latest one. + +(2): Applying the below patch to kernel source. +diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S +index 0b53344..f02b0f7 100644 +--- a/arch/ia64/kernel/pal.S ++++ b/arch/ia64/kernel/pal.S +@@ -84,7 +84,8 @@ GLOBAL_ENTRY(ia64_pal_call_static) + mov ar.pfs =3D loc1 + mov rp =3D loc0 + ;; +- srlz.d // seralize restoration of psr.l ++ srlz.i // seralize restoration of psr.l ++ ;; + br.ret.sptk.many b0 + END(ia64_pal_call_static) + +6. Bug report: + If you found any issues when use kvm/ia64, Please post the bug info to kvm-ia64-devel mailing list. + https://lists.sourceforge.net/lists/listinfo/kvm-ia64-devel/ + +Thanks for your interest! Let's work together, and make kvm/ia64 stronger and stronger!=20 + + + Zhang Xiantao <xia...@in...> + 2008.1.28 --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:30:40
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:35:44 +0800 Subject: [PATCH] kvm/ia64: add optimization for some virtulization faults optvfault.S adds optimization for some performance-critical virtualization faults. Signed-off-by: Anthony Xu <ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/optvfault.S | 918 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 918 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/optvfault.S diff --git a/arch/ia64/kvm/optvfault.S b/arch/ia64/kvm/optvfault.S new file mode 100644 index 0000000..5de210e --- /dev/null +++ b/arch/ia64/kvm/optvfault.S @@ -0,0 +1,918 @@ +/* + * arch/ia64/vmx/optvfault.S + * optimize virtualization fault handler + * + * Copyright (C) 2006 Intel Co + * Xuefei Xu (Anthony Xu) <ant...@in...> + */ + +#include <asm/asmmacro.h> +#include <asm/processor.h> + +#include "vti.h" +#include "asm-offsets.h" + +#define ACCE_MOV_FROM_AR +#define ACCE_MOV_FROM_RR +#define ACCE_MOV_TO_RR +#define ACCE_RSM +#define ACCE_SSM +#define ACCE_MOV_TO_PSR +#define ACCE_THASH + +//mov r1=3Dar3 +GLOBAL_ENTRY(kvm_asm_mov_from_ar) +#ifndef ACCE_MOV_FROM_AR + br.many kvm_virtualization_fault_back +#endif + add r18=3DVMM_VCPU_ITC_OFS_OFFSET, r21 + add r16=3DVMM_VCPU_LAST_ITC_OFFSET,r21 + extr.u r17=3Dr25,6,7 + ;; + ld8 r18=3D[r18] + mov r19=3Dar.itc + mov r24=3Db0 + ;; + add r19=3Dr19,r18 + addl r20=3D@gprel(asm_mov_to_reg),gp + ;; + st8 [r16] =3D r19 + adds r30=3Dkvm_resume_to_guest-asm_mov_to_reg,r20 + shladd r17=3Dr17,4,r20 + ;; + mov b0=3Dr17 + br.sptk.few b0 + ;; +END(kvm_asm_mov_from_ar) + + +// mov r1=3Drr[r3] +GLOBAL_ENTRY(kvm_asm_mov_from_rr) +#ifndef ACCE_MOV_FROM_RR + br.many kvm_virtualization_fault_back +#endif + extr.u r16=3Dr25,20,7 + extr.u r17=3Dr25,6,7 + addl r20=3D@gprel(asm_mov_from_reg),gp + ;; + adds r30=3Dkvm_asm_mov_from_rr_back_1-asm_mov_from_reg,r20 + shladd r16=3Dr16,4,r20 + mov r24=3Db0 + ;; + add r27=3DVMM_VCPU_VRR0_OFFSET,r21 + mov b0=3Dr16 + br.many b0 + ;; +kvm_asm_mov_from_rr_back_1: + adds r30=3Dkvm_resume_to_guest-asm_mov_from_reg,r20 + adds r22=3Dasm_mov_to_reg-asm_mov_from_reg,r20 + shr.u r26=3Dr19,61 + ;; + shladd r17=3Dr17,4,r22 + shladd r27=3Dr26,3,r27 + ;; + ld8 r19=3D[r27] + mov b0=3Dr17 + br.many b0 +END(kvm_asm_mov_from_rr) + + +// mov rr[r3]=3Dr2 +GLOBAL_ENTRY(kvm_asm_mov_to_rr) +#ifndef ACCE_MOV_TO_RR + br.many kvm_virtualization_fault_back +#endif + extr.u r16=3Dr25,20,7 + extr.u r17=3Dr25,13,7 + addl r20=3D@gprel(asm_mov_from_reg),gp + ;; + adds r30=3Dkvm_asm_mov_to_rr_back_1-asm_mov_from_reg,r20 + shladd r16=3Dr16,4,r20 + mov r22=3Db0 + ;; + add r27=3DVMM_VCPU_VRR0_OFFSET,r21 + mov b0=3Dr16 + br.many b0 + ;; +kvm_asm_mov_to_rr_back_1: + adds r30=3Dkvm_asm_mov_to_rr_back_2-asm_mov_from_reg,r20 + shr.u r23=3Dr19,61 + shladd r17=3Dr17,4,r20 + ;; + //if rr6, go back + cmp.eq p6,p0=3D6,r23 + mov b0=3Dr22 + (p6) br.cond.dpnt.many kvm_virtualization_fault_back + ;; + mov r28=3Dr19 + mov b0=3Dr17 + br.many b0 +kvm_asm_mov_to_rr_back_2: + adds r30=3Dkvm_resume_to_guest-asm_mov_from_reg,r20 + shladd r27=3Dr23,3,r27 + ;; // vrr.rid<<4 |0xe + st8 [r27]=3Dr19 + mov b0=3Dr30 + ;; + extr.u r16=3Dr19,8,26 + extr.u r18 =3Dr19,2,6 + mov r17 =3D0xe + ;; + shladd r16 =3D r16, 4, r17 + extr.u r19 =3Dr19,0,8 + ;; + shl r16 =3D r16,8 + ;; + add r19 =3D r19, r16 + ;; //set ve 1 + dep r19=3D-1,r19,0,1 + cmp.lt p6,p0=3D14,r18 + ;; + (p6) mov r18=3D14 + ;; + (p6) dep r19=3Dr18,r19,2,6 + ;; + cmp.eq p6,p0=3D0,r23 + ;; + cmp.eq.or p6,p0=3D4,r23 + ;; + adds r16=3DVMM_VCPU_MODE_FLAGS_OFFSET,r21 + (p6) adds r17=3DVMM_VCPU_META_SAVED_RR0_OFFSET,r21 + ;; + ld4 r16=3D[r16] + cmp.eq p7,p0=3Dr0,r0 + (p6) shladd r17=3Dr23,1,r17 + ;; + (p6) st8 [r17]=3Dr19 + (p6) tbit.nz p6,p7=3Dr16,0 + ;; + (p7) mov rr[r28]=3Dr19 + mov r24=3Dr22 + br.many b0 +END(kvm_asm_mov_to_rr) + + +//rsm +GLOBAL_ENTRY(kvm_asm_rsm) +#ifndef ACCE_RSM + br.many kvm_virtualization_fault_back +#endif + add r16=3DVMM_VPD_BASE_OFFSET,r21 + extr.u r26=3Dr25,6,21 + extr.u r27=3Dr25,31,2 + ;; + ld8 r16=3D[r16] + extr.u r28=3Dr25,36,1 + dep r26=3Dr27,r26,21,2 + ;; + add r17=3DVPD_VPSR_START_OFFSET,r16 + add r22=3DVMM_VCPU_MODE_FLAGS_OFFSET,r21 + //r26 is imm24 + dep r26=3Dr28,r26,23,1 + ;; + ld8 r18=3D[r17] + movl r28=3DIA64_PSR_IC+IA64_PSR_I+IA64_PSR_DT+IA64_PSR_SI + ld4 r23=3D[r22] + sub r27=3D-1,r26 + mov r24=3Db0 + ;; + mov r20=3Dcr.ipsr + or r28=3Dr27,r28 + and r19=3Dr18,r27 + ;; + st8 [r17]=3Dr19 + and r20=3Dr20,r28 + /* Comment it out due to short of fp lazy alorgithm support + adds r27=3DIA64_VCPU_FP_PSR_OFFSET,r21 + ;; + ld8 r27=3D[r27] + ;; + tbit.nz p8,p0=3D r27,IA64_PSR_DFH_BIT + ;; + (p8) dep r20=3D-1,r20,IA64_PSR_DFH_BIT,1 + */ + ;; + mov cr.ipsr=3Dr20 + tbit.nz p6,p0=3Dr23,0 + ;; + tbit.z.or p6,p0=3Dr26,IA64_PSR_DT_BIT + (p6) br.dptk kvm_resume_to_guest + ;; + add r26=3DVMM_VCPU_META_RR0_OFFSET,r21 + add r27=3DVMM_VCPU_META_RR0_OFFSET+8,r21 + dep r23=3D-1,r23,0,1 + ;; + ld8 r26=3D[r26] + ld8 r27=3D[r27] + st4 [r22]=3Dr23 + dep.z r28=3D4,61,3 + ;; + mov rr[r0]=3Dr26 + ;; + mov rr[r28]=3Dr27 + ;; + srlz.d + br.many kvm_resume_to_guest +END(kvm_asm_rsm) + + +//ssm +GLOBAL_ENTRY(kvm_asm_ssm) +#ifndef ACCE_SSM + br.many kvm_virtualization_fault_back +#endif + add r16=3DVMM_VPD_BASE_OFFSET,r21 + extr.u r26=3Dr25,6,21 + extr.u r27=3Dr25,31,2 + ;; + ld8 r16=3D[r16] + extr.u r28=3Dr25,36,1 + dep r26=3Dr27,r26,21,2 + ;; //r26 is imm24 + add r27=3DVPD_VPSR_START_OFFSET,r16 + dep r26=3Dr28,r26,23,1 + ;; //r19 vpsr + ld8 r29=3D[r27] + mov r24=3Db0 + ;; + add r22=3DVMM_VCPU_MODE_FLAGS_OFFSET,r21 + mov r20=3Dcr.ipsr + or r19=3Dr29,r26 + ;; + ld4 r23=3D[r22] + st8 [r27]=3Dr19 + or r20=3Dr20,r26 + ;; + mov cr.ipsr=3Dr20 + movl r28=3DIA64_PSR_DT+IA64_PSR_RT+IA64_PSR_IT + ;; + and r19=3Dr28,r19 + tbit.z p6,p0=3Dr23,0 + ;; + cmp.ne.or p6,p0=3Dr28,r19 + (p6) br.dptk kvm_asm_ssm_1 + ;; + add r26=3DVMM_VCPU_META_SAVED_RR0_OFFSET,r21 + add r27=3DVMM_VCPU_META_SAVED_RR0_OFFSET+8,r21 + dep r23=3D0,r23,0,1 + ;; + ld8 r26=3D[r26] + ld8 r27=3D[r27] + st4 [r22]=3Dr23 + dep.z r28=3D4,61,3 + ;; + mov rr[r0]=3Dr26 + ;; + mov rr[r28]=3Dr27 + ;; + srlz.d + ;; +kvm_asm_ssm_1: + tbit.nz p6,p0=3Dr29,IA64_PSR_I_BIT + ;; + tbit.z.or p6,p0=3Dr19,IA64_PSR_I_BIT + (p6) br.dptk kvm_resume_to_guest + ;; + add r29=3DVPD_VTPR_START_OFFSET,r16 + add r30=3DVPD_VHPI_START_OFFSET,r16 + ;; + ld8 r29=3D[r29] + ld8 r30=3D[r30] + ;; + extr.u r17=3Dr29,4,4 + extr.u r18=3Dr29,16,1 + ;; + dep r17=3Dr18,r17,4,1 + ;; + cmp.gt p6,p0=3Dr30,r17 + (p6) br.dpnt.few kvm_asm_dispatch_vexirq + br.many kvm_resume_to_guest +END(kvm_asm_ssm) + + +//mov psr.l=3Dr2 +GLOBAL_ENTRY(kvm_asm_mov_to_psr) +#ifndef ACCE_MOV_TO_PSR + br.many kvm_virtualization_fault_back +#endif + add r16=3DVMM_VPD_BASE_OFFSET,r21 + extr.u r26=3Dr25,13,7 //r2 + ;; + ld8 r16=3D[r16] + addl r20=3D@gprel(asm_mov_from_reg),gp + ;; + adds r30=3Dkvm_asm_mov_to_psr_back-asm_mov_from_reg,r20 + shladd r26=3Dr26,4,r20 + mov r24=3Db0 + ;; + add r27=3DVPD_VPSR_START_OFFSET,r16 + mov b0=3Dr26 + br.many b0 + ;; +kvm_asm_mov_to_psr_back: + ld8 r17=3D[r27] + add r22=3DVMM_VCPU_MODE_FLAGS_OFFSET,r21 + dep r19=3D0,r19,32,32 + ;; + ld4 r23=3D[r22] + dep r18=3D0,r17,0,32 + ;; + add r30=3Dr18,r19 + movl r28=3DIA64_PSR_DT+IA64_PSR_RT+IA64_PSR_IT + ;; + st8 [r27]=3Dr30 + and r27=3Dr28,r30 + and r29=3Dr28,r17 + ;; + cmp.eq p5,p0=3Dr29,r27 + cmp.eq p6,p7=3Dr28,r27 + (p5) br.many kvm_asm_mov_to_psr_1 + ;; + //virtual to physical + (p7) add r26=3DVMM_VCPU_META_RR0_OFFSET,r21 + (p7) add r27=3DVMM_VCPU_META_RR0_OFFSET+8,r21 + (p7) dep r23=3D-1,r23,0,1 + ;; + //physical to virtual + (p6) add r26=3DVMM_VCPU_META_SAVED_RR0_OFFSET,r21 + (p6) add r27=3DVMM_VCPU_META_SAVED_RR0_OFFSET+8,r21 + (p6) dep r23=3D0,r23,0,1 + ;; + ld8 r26=3D[r26] + ld8 r27=3D[r27] + st4 [r22]=3Dr23 + dep.z r28=3D4,61,3 + ;; + mov rr[r0]=3Dr26 + ;; + mov rr[r28]=3Dr27 + ;; + srlz.d + ;; +kvm_asm_mov_to_psr_1: + mov r20=3Dcr.ipsr + movl = r28=3DIA64_PSR_IC+IA64_PSR_I+IA64_PSR_DT+IA64_PSR_SI+IA64_PSR_RT + ;; + or r19=3Dr19,r28 + dep r20=3D0,r20,0,32 + ;; + add r20=3Dr19,r20 + mov b0=3Dr24 + ;; + /* Comment it out due to short of fp lazy algorithm support + adds r27=3DIA64_VCPU_FP_PSR_OFFSET,r21 + ;; + ld8 r27=3D[r27] + ;; + tbit.nz p8,p0=3Dr27,IA64_PSR_DFH_BIT + ;; + (p8) dep r20=3D-1,r20,IA64_PSR_DFH_BIT,1 + ;; + */ + mov cr.ipsr=3Dr20 + cmp.ne p6,p0=3Dr0,r0 + ;; + tbit.nz.or p6,p0=3Dr17,IA64_PSR_I_BIT + tbit.z.or p6,p0=3Dr30,IA64_PSR_I_BIT + (p6) br.dpnt.few kvm_resume_to_guest + ;; + add r29=3DVPD_VTPR_START_OFFSET,r16 + add r30=3DVPD_VHPI_START_OFFSET,r16 + ;; + ld8 r29=3D[r29] + ld8 r30=3D[r30] + ;; + extr.u r17=3Dr29,4,4 + extr.u r18=3Dr29,16,1 + ;; + dep r17=3Dr18,r17,4,1 + ;; + cmp.gt p6,p0=3Dr30,r17 + (p6) br.dpnt.few kvm_asm_dispatch_vexirq + br.many kvm_resume_to_guest +END(kvm_asm_mov_to_psr) + + +ENTRY(kvm_asm_dispatch_vexirq) +//increment iip + mov r16=3Dcr.ipsr + ;; + extr.u r17=3Dr16,IA64_PSR_RI_BIT,2 + tbit.nz p6,p7=3Dr16,IA64_PSR_RI_BIT+1 + ;; + (p6) mov r18=3Dcr.iip + (p6) mov r17=3Dr0 + (p7) add r17=3D1,r17 + ;; + (p6) add r18=3D0x10,r18 + dep r16=3Dr17,r16,IA64_PSR_RI_BIT,2 + ;; + (p6) mov cr.iip=3Dr18 + mov cr.ipsr=3Dr16 + mov r30 =3D1 + br.many kvm_dispatch_vexirq +END(kvm_asm_dispatch_vexirq) + +// thash +// TODO: add support when pta.vf =3D 1 +GLOBAL_ENTRY(kvm_asm_thash) +#ifndef ACCE_THASH + br.many kvm_virtualization_fault_back +#endif + extr.u r17=3Dr25,20,7 // get r3 from opcode in r25 + extr.u r18=3Dr25,6,7 // get r1 from opcode in r25 + addl r20=3D@gprel(asm_mov_from_reg),gp + ;; + adds r30=3Dkvm_asm_thash_back1-asm_mov_from_reg,r20 + shladd r17=3Dr17,4,r20 // get addr of MOVE_FROM_REG(r17) + adds r16=3DVMM_VPD_BASE_OFFSET,r21 // get vcpu.arch.priveregs + ;; + mov r24=3Db0 + ;; + ld8 r16=3D[r16] // get VPD addr + mov b0=3Dr17 + br.many b0 // r19 return value + ;; +kvm_asm_thash_back1: + shr.u r23=3Dr19,61 // get RR number + adds r25=3DVMM_VCPU_VRR0_OFFSET,r21 // get vcpu->arch.vrr[0]'s addr + adds r16=3DVMM_VPD_VPTA_OFFSET,r16 // get vpta + ;; + shladd r27=3Dr23,3,r25 // get vcpu->arch.vrr[r23]'s addr + ld8 r17=3D[r16] // get PTA + mov r26=3D1 + ;; + extr.u r29=3Dr17,2,6 // get pta.size + ld8 r25=3D[r27] // get vcpu->arch.vrr[r23]'s value + ;; + extr.u r25=3Dr25,2,6 // get rr.ps + shl r22=3Dr26,r29 // 1UL << pta.size + ;; + shr.u r23=3Dr19,r25 // vaddr >> rr.ps + adds r26=3D3,r29 // pta.size + 3 + shl r27=3Dr17,3 // pta << 3 + ;; + shl r23=3Dr23,3 // (vaddr >> rr.ps) << 3 + shr.u r27=3Dr27,r26 // (pta << 3) >> (pta.size+3) + movl r16=3D7<<61 + ;; + adds r22=3D-1,r22 // (1UL << pta.size) - 1 + shl r27=3Dr27,r29 // ((pta<<3)>>(pta.size+3))<<pta.size + and r19=3Dr19,r16 // vaddr & VRN_MASK + ;; + and r22=3Dr22,r23 // vhpt_offset + or r19=3Dr19,r27 // (vadr&VRN_MASK) |(((pta<<3)>>(pta.size + 3))<<pta.size) + adds r26=3Dasm_mov_to_reg-asm_mov_from_reg,r20 + ;; + or r19=3Dr19,r22 // calc pval + shladd r17=3Dr18,4,r26 + adds r30=3Dkvm_resume_to_guest-asm_mov_from_reg,r20 + ;; + mov b0=3Dr17 + br.many b0 +END(kvm_asm_thash) + +#define MOV_TO_REG0 \ +{; \ + nop.b 0x0; \ + nop.b 0x0; \ + nop.b 0x0; \ + ;; \ +}; + + +#define MOV_TO_REG(n) \ +{; \ + mov r##n##=3Dr19; \ + mov b0=3Dr30; \ + br.sptk.many b0; \ + ;; \ +}; + + +#define MOV_FROM_REG(n) \ +{; \ + mov r19=3Dr##n##; \ + mov b0=3Dr30; \ + br.sptk.many b0; \ + ;; \ +}; + + +#define MOV_TO_BANK0_REG(n) \ +ENTRY_MIN_ALIGN(asm_mov_to_bank0_reg##n##); \ +{; \ + mov r26=3Dr2; \ + mov r2=3Dr19; \ + bsw.1; \ + ;; \ +}; \ +{; \ + mov r##n##=3Dr2; \ + nop.b 0x0; \ + bsw.0; \ + ;; \ +}; \ +{; \ + mov r2=3Dr26; \ + mov b0=3Dr30; \ + br.sptk.many b0; \ + ;; \ +}; \ +END(asm_mov_to_bank0_reg##n##) + + +#define MOV_FROM_BANK0_REG(n) \ +ENTRY_MIN_ALIGN(asm_mov_from_bank0_reg##n##); \ +{; \ + mov r26=3Dr2; \ + nop.b 0x0; \ + bsw.1; \ + ;; \ +}; \ +{; \ + mov r2=3Dr##n##; \ + nop.b 0x0; \ + bsw.0; \ + ;; \ +}; \ +{; \ + mov r19=3Dr2; \ + mov r2=3Dr26; \ + mov b0=3Dr30; \ +}; \ +{; \ + nop.b 0x0; \ + nop.b 0x0; \ + br.sptk.many b0; \ + ;; \ +}; \ +END(asm_mov_from_bank0_reg##n##) + + +#define JMP_TO_MOV_TO_BANK0_REG(n) \ +{; \ + nop.b 0x0; \ + nop.b 0x0; \ + br.sptk.many asm_mov_to_bank0_reg##n##; \ + ;; \ +} + + +#define JMP_TO_MOV_FROM_BANK0_REG(n) \ +{; \ + nop.b 0x0; \ + nop.b 0x0; \ + br.sptk.many asm_mov_from_bank0_reg##n##; \ + ;; \ +} + + +MOV_FROM_BANK0_REG(16) +MOV_FROM_BANK0_REG(17) +MOV_FROM_BANK0_REG(18) +MOV_FROM_BANK0_REG(19) +MOV_FROM_BANK0_REG(20) +MOV_FROM_BANK0_REG(21) +MOV_FROM_BANK0_REG(22) +MOV_FROM_BANK0_REG(23) +MOV_FROM_BANK0_REG(24) +MOV_FROM_BANK0_REG(25) +MOV_FROM_BANK0_REG(26) +MOV_FROM_BANK0_REG(27) +MOV_FROM_BANK0_REG(28) +MOV_FROM_BANK0_REG(29) +MOV_FROM_BANK0_REG(30) +MOV_FROM_BANK0_REG(31) + + +// mov from reg table +ENTRY(asm_mov_from_reg) + MOV_FROM_REG(0) + MOV_FROM_REG(1) + MOV_FROM_REG(2) + MOV_FROM_REG(3) + MOV_FROM_REG(4) + MOV_FROM_REG(5) + MOV_FROM_REG(6) + MOV_FROM_REG(7) + MOV_FROM_REG(8) + MOV_FROM_REG(9) + MOV_FROM_REG(10) + MOV_FROM_REG(11) + MOV_FROM_REG(12) + MOV_FROM_REG(13) + MOV_FROM_REG(14) + MOV_FROM_REG(15) + JMP_TO_MOV_FROM_BANK0_REG(16) + JMP_TO_MOV_FROM_BANK0_REG(17) + JMP_TO_MOV_FROM_BANK0_REG(18) + JMP_TO_MOV_FROM_BANK0_REG(19) + JMP_TO_MOV_FROM_BANK0_REG(20) + JMP_TO_MOV_FROM_BANK0_REG(21) + JMP_TO_MOV_FROM_BANK0_REG(22) + JMP_TO_MOV_FROM_BANK0_REG(23) + JMP_TO_MOV_FROM_BANK0_REG(24) + JMP_TO_MOV_FROM_BANK0_REG(25) + JMP_TO_MOV_FROM_BANK0_REG(26) + JMP_TO_MOV_FROM_BANK0_REG(27) + JMP_TO_MOV_FROM_BANK0_REG(28) + JMP_TO_MOV_FROM_BANK0_REG(29) + JMP_TO_MOV_FROM_BANK0_REG(30) + JMP_TO_MOV_FROM_BANK0_REG(31) + MOV_FROM_REG(32) + MOV_FROM_REG(33) + MOV_FROM_REG(34) + MOV_FROM_REG(35) + MOV_FROM_REG(36) + MOV_FROM_REG(37) + MOV_FROM_REG(38) + MOV_FROM_REG(39) + MOV_FROM_REG(40) + MOV_FROM_REG(41) + MOV_FROM_REG(42) + MOV_FROM_REG(43) + MOV_FROM_REG(44) + MOV_FROM_REG(45) + MOV_FROM_REG(46) + MOV_FROM_REG(47) + MOV_FROM_REG(48) + MOV_FROM_REG(49) + MOV_FROM_REG(50) + MOV_FROM_REG(51) + MOV_FROM_REG(52) + MOV_FROM_REG(53) + MOV_FROM_REG(54) + MOV_FROM_REG(55) + MOV_FROM_REG(56) + MOV_FROM_REG(57) + MOV_FROM_REG(58) + MOV_FROM_REG(59) + MOV_FROM_REG(60) + MOV_FROM_REG(61) + MOV_FROM_REG(62) + MOV_FROM_REG(63) + MOV_FROM_REG(64) + MOV_FROM_REG(65) + MOV_FROM_REG(66) + MOV_FROM_REG(67) + MOV_FROM_REG(68) + MOV_FROM_REG(69) + MOV_FROM_REG(70) + MOV_FROM_REG(71) + MOV_FROM_REG(72) + MOV_FROM_REG(73) + MOV_FROM_REG(74) + MOV_FROM_REG(75) + MOV_FROM_REG(76) + MOV_FROM_REG(77) + MOV_FROM_REG(78) + MOV_FROM_REG(79) + MOV_FROM_REG(80) + MOV_FROM_REG(81) + MOV_FROM_REG(82) + MOV_FROM_REG(83) + MOV_FROM_REG(84) + MOV_FROM_REG(85) + MOV_FROM_REG(86) + MOV_FROM_REG(87) + MOV_FROM_REG(88) + MOV_FROM_REG(89) + MOV_FROM_REG(90) + MOV_FROM_REG(91) + MOV_FROM_REG(92) + MOV_FROM_REG(93) + MOV_FROM_REG(94) + MOV_FROM_REG(95) + MOV_FROM_REG(96) + MOV_FROM_REG(97) + MOV_FROM_REG(98) + MOV_FROM_REG(99) + MOV_FROM_REG(100) + MOV_FROM_REG(101) + MOV_FROM_REG(102) + MOV_FROM_REG(103) + MOV_FROM_REG(104) + MOV_FROM_REG(105) + MOV_FROM_REG(106) + MOV_FROM_REG(107) + MOV_FROM_REG(108) + MOV_FROM_REG(109) + MOV_FROM_REG(110) + MOV_FROM_REG(111) + MOV_FROM_REG(112) + MOV_FROM_REG(113) + MOV_FROM_REG(114) + MOV_FROM_REG(115) + MOV_FROM_REG(116) + MOV_FROM_REG(117) + MOV_FROM_REG(118) + MOV_FROM_REG(119) + MOV_FROM_REG(120) + MOV_FROM_REG(121) + MOV_FROM_REG(122) + MOV_FROM_REG(123) + MOV_FROM_REG(124) + MOV_FROM_REG(125) + MOV_FROM_REG(126) + MOV_FROM_REG(127) +END(asm_mov_from_reg) + + +/* must be in bank 0 + * parameter: + * r31: pr + * r24: b0 + */ +ENTRY(kvm_resume_to_guest) + adds r16 =3D VMM_VCPU_SAVED_GP_OFFSET,r21 + ;; + ld8 r1 =3D[r16] + adds r20 =3D VMM_VCPU_VSA_BASE_OFFSET,r21 + ;; + mov r16=3Dcr.ipsr + ;; + ld8 r20 =3D [r20] + adds r19=3DVMM_VPD_BASE_OFFSET,r21 + ;; + ld8 r25=3D[r19] + extr.u r17=3Dr16,IA64_PSR_RI_BIT,2 + tbit.nz p6,p7=3Dr16,IA64_PSR_RI_BIT+1 + ;; + (p6) mov r18=3Dcr.iip + (p6) mov r17=3Dr0 + ;; + (p6) add r18=3D0x10,r18 + (p7) add r17=3D1,r17 + ;; + (p6) mov cr.iip=3Dr18 + dep r16=3Dr17,r16,IA64_PSR_RI_BIT,2 + ;; + mov cr.ipsr=3Dr16 + adds r19=3D VPD_VPSR_START_OFFSET,r25 + add r28=3DPAL_VPS_RESUME_NORMAL,r20 + add r29=3DPAL_VPS_RESUME_HANDLER,r20 + ;; + ld8 r19=3D[r19] + mov b0=3Dr29 + cmp.ne p6,p7 =3D r0,r0 + ;; + tbit.z p6,p7 =3D r19,IA64_PSR_IC_BIT // p1=3Dvpsr.ic + ;; + (p6) ld8 r26=3D[r25] + (p7) mov b0=3Dr28 + mov pr=3Dr31,-2 + br.sptk.many b0 // call pal service + ;; +END(kvm_resume_to_guest) + + +MOV_TO_BANK0_REG(16) +MOV_TO_BANK0_REG(17) +MOV_TO_BANK0_REG(18) +MOV_TO_BANK0_REG(19) +MOV_TO_BANK0_REG(20) +MOV_TO_BANK0_REG(21) +MOV_TO_BANK0_REG(22) +MOV_TO_BANK0_REG(23) +MOV_TO_BANK0_REG(24) +MOV_TO_BANK0_REG(25) +MOV_TO_BANK0_REG(26) +MOV_TO_BANK0_REG(27) +MOV_TO_BANK0_REG(28) +MOV_TO_BANK0_REG(29) +MOV_TO_BANK0_REG(30) +MOV_TO_BANK0_REG(31) + + +// mov to reg table +ENTRY(asm_mov_to_reg) + MOV_TO_REG0 + MOV_TO_REG(1) + MOV_TO_REG(2) + MOV_TO_REG(3) + MOV_TO_REG(4) + MOV_TO_REG(5) + MOV_TO_REG(6) + MOV_TO_REG(7) + MOV_TO_REG(8) + MOV_TO_REG(9) + MOV_TO_REG(10) + MOV_TO_REG(11) + MOV_TO_REG(12) + MOV_TO_REG(13) + MOV_TO_REG(14) + MOV_TO_REG(15) + JMP_TO_MOV_TO_BANK0_REG(16) + JMP_TO_MOV_TO_BANK0_REG(17) + JMP_TO_MOV_TO_BANK0_REG(18) + JMP_TO_MOV_TO_BANK0_REG(19) + JMP_TO_MOV_TO_BANK0_REG(20) + JMP_TO_MOV_TO_BANK0_REG(21) + JMP_TO_MOV_TO_BANK0_REG(22) + JMP_TO_MOV_TO_BANK0_REG(23) + JMP_TO_MOV_TO_BANK0_REG(24) + JMP_TO_MOV_TO_BANK0_REG(25) + JMP_TO_MOV_TO_BANK0_REG(26) + JMP_TO_MOV_TO_BANK0_REG(27) + JMP_TO_MOV_TO_BANK0_REG(28) + JMP_TO_MOV_TO_BANK0_REG(29) + JMP_TO_MOV_TO_BANK0_REG(30) + JMP_TO_MOV_TO_BANK0_REG(31) + MOV_TO_REG(32) + MOV_TO_REG(33) + MOV_TO_REG(34) + MOV_TO_REG(35) + MOV_TO_REG(36) + MOV_TO_REG(37) + MOV_TO_REG(38) + MOV_TO_REG(39) + MOV_TO_REG(40) + MOV_TO_REG(41) + MOV_TO_REG(42) + MOV_TO_REG(43) + MOV_TO_REG(44) + MOV_TO_REG(45) + MOV_TO_REG(46) + MOV_TO_REG(47) + MOV_TO_REG(48) + MOV_TO_REG(49) + MOV_TO_REG(50) + MOV_TO_REG(51) + MOV_TO_REG(52) + MOV_TO_REG(53) + MOV_TO_REG(54) + MOV_TO_REG(55) + MOV_TO_REG(56) + MOV_TO_REG(57) + MOV_TO_REG(58) + MOV_TO_REG(59) + MOV_TO_REG(60) + MOV_TO_REG(61) + MOV_TO_REG(62) + MOV_TO_REG(63) + MOV_TO_REG(64) + MOV_TO_REG(65) + MOV_TO_REG(66) + MOV_TO_REG(67) + MOV_TO_REG(68) + MOV_TO_REG(69) + MOV_TO_REG(70) + MOV_TO_REG(71) + MOV_TO_REG(72) + MOV_TO_REG(73) + MOV_TO_REG(74) + MOV_TO_REG(75) + MOV_TO_REG(76) + MOV_TO_REG(77) + MOV_TO_REG(78) + MOV_TO_REG(79) + MOV_TO_REG(80) + MOV_TO_REG(81) + MOV_TO_REG(82) + MOV_TO_REG(83) + MOV_TO_REG(84) + MOV_TO_REG(85) + MOV_TO_REG(86) + MOV_TO_REG(87) + MOV_TO_REG(88) + MOV_TO_REG(89) + MOV_TO_REG(90) + MOV_TO_REG(91) + MOV_TO_REG(92) + MOV_TO_REG(93) + MOV_TO_REG(94) + MOV_TO_REG(95) + MOV_TO_REG(96) + MOV_TO_REG(97) + MOV_TO_REG(98) + MOV_TO_REG(99) + MOV_TO_REG(100) + MOV_TO_REG(101) + MOV_TO_REG(102) + MOV_TO_REG(103) + MOV_TO_REG(104) + MOV_TO_REG(105) + MOV_TO_REG(106) + MOV_TO_REG(107) + MOV_TO_REG(108) + MOV_TO_REG(109) + MOV_TO_REG(110) + MOV_TO_REG(111) + MOV_TO_REG(112) + MOV_TO_REG(113) + MOV_TO_REG(114) + MOV_TO_REG(115) + MOV_TO_REG(116) + MOV_TO_REG(117) + MOV_TO_REG(118) + MOV_TO_REG(119) + MOV_TO_REG(120) + MOV_TO_REG(121) + MOV_TO_REG(122) + MOV_TO_REG(123) + MOV_TO_REG(124) + MOV_TO_REG(125) + MOV_TO_REG(126) + MOV_TO_REG(127) +END(asm_mov_to_reg) --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:30:39
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:43:32 +0800 Subject: [PATCH] kvm/ia64: Add Makefile for kvm files compile. Adds Makefile for kvm compile. Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/Makefile | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 61 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/Makefile diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile new file mode 100644 index 0000000..cde7d8e --- /dev/null +++ b/arch/ia64/kvm/Makefile @@ -0,0 +1,61 @@ +#This Make file is to generate asm-offsets.h and build source. +# =20 + +#Generate asm-offsets.h for vmm module build +offsets-file :=3D asm-offsets.h + +always :=3D $(offsets-file) +targets :=3D $(offsets-file) +targets +=3D arch/ia64/kvm/asm-offsets.s +clean-files :=3D $(addprefix $(objtree)/,$(targets) $(obj)/memcpy.S $(obj)/memset.S) + +# Default sed regexp - multiline due to syntax constraints +define sed-y + "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}" +endef + +quiet_cmd_offsets =3D GEN $@ +define cmd_offsets + (set -e; \ + echo "#ifndef __ASM_KVM_OFFSETS_H__"; \ + echo "#define __ASM_KVM_OFFSETS_H__"; \ + echo "/*"; \ + echo " * DO NOT MODIFY."; \ + echo " *"; \ + echo " * This file was generated by Makefile"; \ + echo " *"; \ + echo " */"; \ + echo ""; \ + sed -ne $(sed-y) $<; \ + echo ""; \ + echo "#endif" ) > $@ +endef +# We use internal rules to avoid the "is up to date" message from make +arch/ia64/kvm/asm-offsets.s: arch/ia64/kvm/asm-offsets.c + $(call if_changed_dep,cc_s_c) + +$(obj)/$(offsets-file): arch/ia64/kvm/asm-offsets.s + $(call cmd,offsets) + +# +# Makefile for Kernel-based Virtual Machine module +# + +EXTRA_CFLAGS +=3D -Ivirt/kvm -Iarch/ia64/kvm/ + +$(addprefix $(objtree)/,$(obj)/memcpy.S $(obj)/memset.S):=20 + $(shell ln -snf ../lib/memcpy.S $(src)/memcpy.S) + $(shell ln -snf ../lib/memset.S $(src)/memset.S) + +common-objs =3D $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o) + +kvm-objs :=3D $(common-objs) kvm_ia64.o kvm_fw.o +obj-$(CONFIG_KVM) +=3D kvm.o + +FORCE : $(obj)/$(offsets-file) +EXTRA_CFLAGS_vcpu.o +=3D -mfixed-range=3Df2-f5,f12-f127 +kvm-intel-objs =3D vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o = mmio.o \ + vtlb.o process.o +#Add link memcpy and memset to avoid possible structure assignment error +kvm-intel-objs +=3D memset.o memcpy.o +obj-$(CONFIG_KVM_INTEL) +=3D kvm-intel.o --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:30:34
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:42:44 +0800 Subject: [PATCH] kvm/ia64: add Kconfig for kvm configuration. Kconfig adds kvm/ia64 configurations at kernel configuration time. Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/Kconfig | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/Kconfig diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig new file mode 100644 index 0000000..aaeb7f1 --- /dev/null +++ b/arch/ia64/kvm/Kconfig @@ -0,0 +1,43 @@ +# +# KVM configuration +# +menuconfig VIRTUALIZATION + bool "Virtualization" + depends on ARCH_SUPPORTS_KVM || IA64 + default y + ---help--- + Say Y here to get to see options for using your Linux host to run other + operating systems inside virtual machines (guests). + This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and disabled. + +if VIRTUALIZATION + +config KVM + tristate "Kernel-based Virtual Machine (KVM) support" + depends on ARCH_SUPPORTS_KVM && EXPERIMENTAL + select PREEMPT_NOTIFIERS + select ANON_INODES + ---help--- + Support hosting fully virtualized guest machines using hardware + virtualization extensions. You will need a fairly recent + processor equipped with virtualization extensions. You will also + need to select one or more of the processor modules below. + + This module provides access to the hardware capabilities through + a character device node named /dev/kvm. + + To compile this as a module, choose M here: the module + will be called kvm. + + If unsure, say N. + +config KVM_INTEL + tristate "KVM for Intel Itanium 2 processors support" + depends on KVM && m + ---help--- + Provides support for KVM on Itanium 2 processors equipped with the VT + extensions. + +endif # VIRTUALIZATION --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:30:32
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:42:03 +0800 Subject: [PATCH] kvm/ia64: Add guest interruption injection support. process.c mainly handle interruption injection, and some faults handling. Signed-off-by: Anthony Xu <ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/process.c | 964 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 964 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/process.c diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c new file mode 100644 index 0000000..d6a374d --- /dev/null +++ b/arch/ia64/kvm/process.c @@ -0,0 +1,964 @@ +/* + * process.c: handle interruption inject for guests. + * Copyright (c) 2005, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * Shaofan Li (Susue Li) <sus...@in...> + * Xiaoyan Feng (Fleming Feng) <fle...@in...> + * Xuefei Xu (Anthony Xu) (Ant...@in...) + * Xiantao Zhang (xia...@in...) + */ +#include "vcpu.h" + +#include <asm/pal.h> +#include <asm/sal.h> +#include <asm/fpswa.h> + +fpswa_interface_t *vmm_fpswa_interface; + +#define IA64_VHPT_TRANS_VECTOR 0x0000 +#define IA64_INST_TLB_VECTOR 0x0400 +#define IA64_DATA_TLB_VECTOR 0x0800 +#define IA64_ALT_INST_TLB_VECTOR 0x0c00 +#define IA64_ALT_DATA_TLB_VECTOR 0x1000 +#define IA64_DATA_NESTED_TLB_VECTOR 0x1400 +#define IA64_INST_KEY_MISS_VECTOR 0x1800 +#define IA64_DATA_KEY_MISS_VECTOR 0x1c00 +#define IA64_DIRTY_BIT_VECTOR 0x2000 +#define IA64_INST_ACCESS_BIT_VECTOR 0x2400 +#define IA64_DATA_ACCESS_BIT_VECTOR 0x2800 +#define IA64_BREAK_VECTOR 0x2c00 +#define IA64_EXTINT_VECTOR 0x3000 +#define IA64_PAGE_NOT_PRESENT_VECTOR 0x5000 +#define IA64_KEY_PERMISSION_VECTOR 0x5100 +#define IA64_INST_ACCESS_RIGHTS_VECTOR 0x5200 +#define IA64_DATA_ACCESS_RIGHTS_VECTOR 0x5300 +#define IA64_GENEX_VECTOR 0x5400 +#define IA64_DISABLED_FPREG_VECTOR 0x5500 +#define IA64_NAT_CONSUMPTION_VECTOR 0x5600 +#define IA64_SPECULATION_VECTOR 0x5700 /* UNUSED */ +#define IA64_DEBUG_VECTOR 0x5900 +#define IA64_UNALIGNED_REF_VECTOR 0x5a00 +#define IA64_UNSUPPORTED_DATA_REF_VECTOR 0x5b00 +#define IA64_FP_FAULT_VECTOR 0x5c00 +#define IA64_FP_TRAP_VECTOR 0x5d00 +#define IA64_LOWERPRIV_TRANSFER_TRAP_VECTOR 0x5e00 +#define IA64_TAKEN_BRANCH_TRAP_VECTOR 0x5f00 +#define IA64_SINGLE_STEP_TRAP_VECTOR 0x6000 + +/* SDM vol2 5.5 - IVA based interruption handling */ +#define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034 + +#define DOMN_PAL_REQUEST 0x110000 +#define DOMN_SAL_REQUEST 0x110001 + +static u64 vec2off[68] =3D {0x0, 0x400, 0x800, 0xc00, 0x1000, 0x1400, 0x1800, + 0x1c00, 0x2000, 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00, + 0x4000, 0x4400, 0x4800, 0x4c00, 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, + 0x5500, 0x5600, 0x5700, 0x5800, 0x5900, 0x5a00, 0x5b00, 0x5c00, 0x5d00, + 0x5e00, 0x5f00, 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, + 0x6700, 0x6800, 0x6900, 0x6a00, 0x6b00, 0x6c00, 0x6d00, 0x6e00, 0x6f00, + 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, 0x7800, + 0x7900, 0x7a00, 0x7b00, 0x7c00, 0x7d00, 0x7e00, 0x7f00 +}; + +static void collect_interruption(VCPU *vcpu) +{ + u64 ipsr; + u64 vdcr; + u64 vifs; + ia64_psr vpsr; + REGS *regs =3D vcpu_regs(vcpu); + + vpsr.val =3D vcpu_get_psr(vcpu); + vcpu_bsw0(vcpu); + if (vpsr.ic) { + + /* Sync mpsr id/da/dd/ss/ed bits to vipsr + * since after guest do rfi, we still want these bits on in + * mpsr + */ + + ipsr =3D regs->cr_ipsr; + vpsr.val =3D vpsr.val | (ipsr & (IA64_PSR_ID | IA64_PSR_DA + | IA64_PSR_DD | IA64_PSR_SS + | IA64_PSR_ED)); + vcpu_set_ipsr(vcpu, vpsr.val); + + /* Currently, for trap, we do not advance IIP to next + * instruction. That's because we assume caller already + * set up IIP correctly + */ + + vcpu_set_iip(vcpu , regs->cr_iip); + + /* set vifs.v to zero */ + vifs =3D VCPU(vcpu, ifs); + vifs &=3D ~IA64_IFS_V; + vcpu_set_ifs(vcpu, vifs); + + vcpu_set_iipa(vcpu, VMX(vcpu, cr_iipa)); + } + + vdcr =3D VCPU(vcpu, dcr); + + /* Set guest psr + * up/mfl/mfh/pk/dt/rt/mc/it keeps unchanged + * be: set to the value of dcr.be + * pp: set to the value of dcr.pp + */ + vpsr.val &=3D INITIAL_PSR_VALUE_AT_INTERRUPTION; + vpsr.val |=3D (vdcr & IA64_DCR_BE); + + /* VDCR pp bit position is different from VPSR pp bit */ + if (vdcr & IA64_DCR_PP) { + vpsr.val |=3D IA64_PSR_PP; + } else { + vpsr.val &=3D ~IA64_PSR_PP;; + } + + vcpu_set_psr(vcpu, vpsr.val); + +} + +void inject_guest_interruption(VCPU *vcpu, u64 vec) +{ + u64 viva; + REGS *regs; + ia64_isr pt_isr; + + regs =3D vcpu_regs(vcpu); + + /* clear cr.isr.ir (incomplete register frame)*/ + pt_isr.val =3D VMX(vcpu, cr_isr); + pt_isr.ir =3D 0; + VMX(vcpu, cr_isr) =3D pt_isr.val; + + collect_interruption(vcpu); + + viva =3D vcpu_get_iva(vcpu); + regs->cr_iip =3D viva + vec; +} + +static u64 vcpu_get_itir_on_fault(VCPU *vcpu, u64 ifa) +{ + ia64_rr rr, rr1; + + rr.val =3D vcpu_get_rr(vcpu, ifa); + rr1.val =3D 0; + rr1.ps =3D rr.ps; + rr1.rid =3D rr.rid; + return (rr1.val); +} + + +/* + * Set vIFA & vITIR & vIHA, when vPSR.ic =3D1 + * Parameter: + * set_ifa: if true, set vIFA + * set_itir: if true, set vITIR + * set_iha: if true, set vIHA + */ +void set_ifa_itir_iha(VCPU *vcpu, u64 vadr, + int set_ifa, int set_itir, int set_iha) +{ + ia64_psr vpsr; + u64 value; + + vpsr.val =3D VCPU(vcpu, vpsr); + /* Vol2, Table 8-1 */ + if (vpsr.ic) { + if (set_ifa) { + vcpu_set_ifa(vcpu, vadr); + } + if (set_itir) { + value =3D vcpu_get_itir_on_fault(vcpu, vadr); + vcpu_set_itir(vcpu, value); + } + + if (set_iha) { + value =3D vcpu_thash(vcpu, vadr); + vcpu_set_iha(vcpu, value); + } + } +} + +/* + * Data TLB Fault + * @ Data TLB vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void dtlb_fault(VCPU *vcpu, u64 vadr) +{ + /* If vPSR.ic, IFA, ITIR, IHA */ + set_ifa_itir_iha(vcpu, vadr, 1, 1, 1); + inject_guest_interruption(vcpu, IA64_DATA_TLB_VECTOR); +} + +/* + * Instruction TLB Fault + * @ Instruction TLB vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void itlb_fault (VCPU *vcpu, u64 vadr) +{ + /* If vPSR.ic, IFA, ITIR, IHA */ + set_ifa_itir_iha(vcpu, vadr, 1, 1, 1); + inject_guest_interruption(vcpu, IA64_INST_TLB_VECTOR); +} + + + +/* + * Data Nested TLB Fault + * @ Data Nested TLB Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void nested_dtlb(VCPU *vcpu) +{ + inject_guest_interruption(vcpu, IA64_DATA_NESTED_TLB_VECTOR); +} + +/* + * Alternate Data TLB Fault + * @ Alternate Data TLB vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void alt_dtlb(VCPU *vcpu, u64 vadr) +{ + set_ifa_itir_iha(vcpu, vadr, 1, 1, 0); + inject_guest_interruption(vcpu, IA64_ALT_DATA_TLB_VECTOR); +} + + +/* + * Data TLB Fault + * @ Data TLB vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void alt_itlb(VCPU *vcpu, u64 vadr) +{ + set_ifa_itir_iha(vcpu, vadr, 1, 1, 0); + inject_guest_interruption(vcpu, IA64_ALT_INST_TLB_VECTOR); +} + +/* Deal with: + * VHPT Translation Vector + */ +static void _vhpt_fault(VCPU *vcpu, u64 vadr) +{ + /* If vPSR.ic, IFA, ITIR, IHA*/ + set_ifa_itir_iha(vcpu, vadr, 1, 1, 1); + inject_guest_interruption(vcpu, IA64_VHPT_TRANS_VECTOR); + + +} + +/* + * VHPT Instruction Fault + * @ VHPT Translation vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void ivhpt_fault(VCPU *vcpu, u64 vadr) +{ + _vhpt_fault(vcpu, vadr); +} + + +/* + * VHPT Data Fault + * @ VHPT Translation vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void dvhpt_fault(VCPU *vcpu, u64 vadr) +{ + _vhpt_fault(vcpu, vadr); +} + + + +/* + * Deal with: + * General Exception vector + */ +void _general_exception(VCPU *vcpu) +{ + inject_guest_interruption(vcpu, IA64_GENEX_VECTOR); +} + + +/* + * Illegal Operation Fault + * @ General Exception Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void illegal_op(VCPU *vcpu) +{ + _general_exception(vcpu); +} + +/* + * Illegal Dependency Fault + * @ General Exception Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void illegal_dep(VCPU *vcpu) +{ + _general_exception(vcpu); +} + +/* + * Reserved Register/Field Fault + * @ General Exception Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void rsv_reg_field(VCPU *vcpu) +{ + _general_exception(vcpu); +} +/* + * Privileged Operation Fault + * @ General Exception Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ + +void privilege_op(VCPU *vcpu) +{ + _general_exception(vcpu); +} + +/* + * Unimplement Data Address Fault + * @ General Exception Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void unimpl_daddr(VCPU *vcpu) +{ + _general_exception(vcpu); +} + +/* + * Privileged Register Fault + * @ General Exception Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void privilege_reg(VCPU *vcpu) +{ + _general_exception(vcpu); +} + +/* Deal with + * Nat consumption vector + * Parameter: + * vaddr: Optional, if t =3D=3D REGISTER + */ +static void _nat_consumption_fault(VCPU *vcpu, u64 vadr, miss_type t) +{ + /* If vPSR.ic && t =3D=3D DATA/INST, IFA */ + if (t =3D=3D DATA || t =3D=3D INSTRUCTION) { + /* IFA */ + set_ifa_itir_iha(vcpu, vadr, 1, 0, 0); + } + + inject_guest_interruption(vcpu, IA64_NAT_CONSUMPTION_VECTOR); +} + +/* + * IR Data Nat Page Consumption Fault + * @ Nat Consumption Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +#if 0 + static void +ir_nat_page_consumption(VCPU *vcpu, u64 vadr) +{ + _nat_consumption_fault(vcpu, vadr, DATA); +} +#endif /*shadow it due to no use currently*/ + +/* + * Instruction Nat Page Consumption Fault + * @ Nat Consumption Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void inat_page_consumption(VCPU *vcpu, u64 vadr) +{ + _nat_consumption_fault(vcpu, vadr, INSTRUCTION); +} + +/* + * Register Nat Consumption Fault + * @ Nat Consumption Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void rnat_consumption(VCPU *vcpu) +{ + _nat_consumption_fault(vcpu, 0, REGISTER); +} + +/* + * Data Nat Page Consumption Fault + * @ Nat Consumption Vector + * Refer to SDM Vol2 Table 5-6 & 8-1 + */ +void dnat_page_consumption(VCPU *vcpu, u64 vadr) +{ + _nat_consumption_fault(vcpu, vadr, DATA); +} + +/* Deal with + * Page not present vector + */ +static void __page_not_present(VCPU *vcpu, u64 vadr) +{ + /* If vPSR.ic, IFA, ITIR */ + set_ifa_itir_iha(vcpu, vadr, 1, 1, 0); + inject_guest_interruption(vcpu, IA64_PAGE_NOT_PRESENT_VECTOR); +} + + +void data_page_not_present(VCPU *vcpu, u64 vadr) +{ + __page_not_present(vcpu, vadr); +} + + +void inst_page_not_present(VCPU *vcpu, u64 vadr) +{ + __page_not_present(vcpu, vadr); +} + + +/* Deal with + * Data access rights vector + */ +void data_access_rights(VCPU *vcpu, u64 vadr) +{ + /* If vPSR.ic, IFA, ITIR */ + set_ifa_itir_iha(vcpu, vadr, 1, 1, 0); + inject_guest_interruption(vcpu, IA64_DATA_ACCESS_RIGHTS_VECTOR); +} + +fpswa_ret_t vmm_fp_emulate(int fp_fault, void *bundle, unsigned long *ipsr, + unsigned long *fpsr, unsigned long *isr, unsigned long *pr, + unsigned long *ifs, REGS *regs) +{ + fp_state_t fp_state; + fpswa_ret_t ret; + struct kvm_vcpu *vcpu =3D current_vcpu; + + uint64_t old_rr7 =3D ia64_get_rr(7UL<<61); + + if (!vmm_fpswa_interface) + return (fpswa_ret_t) {-1, 0, 0, 0}; + + /* + * Just let fpswa driver to use hardware fp registers. + * No fp register is valid in memory. + */ + memset(&fp_state, 0, sizeof(fp_state_t)); + + /* + * unsigned long (*EFI_FPSWA) ( + * unsigned long trap_type, + * void *Bundle, + * unsigned long *pipsr, + * unsigned long *pfsr, + * unsigned long *pisr, + * unsigned long *ppreds, + * unsigned long *pifs, + * void *fp_state); + */ + /*Call host fpswa interface directly to virtualize + *guest fpswa request! + */ + ia64_set_rr(7UL << 61, vcpu->arch.host.rr[7]); + ia64_srlz_d(); + + ret =3D (*vmm_fpswa_interface->fpswa) (fp_fault, bundle, + ipsr, fpsr, isr, pr, ifs, &fp_state); + ia64_set_rr(7UL << 61, old_rr7); + ia64_srlz_d(); + return ret; +} + +/* + * Handle floating-point assist faults and traps for domain. + */ +unsigned long vmm_handle_fpu_swa(int fp_fault, REGS *regs, unsigned long isr) +{ + struct kvm_vcpu *v =3D current_vcpu; + IA64_BUNDLE bundle; + unsigned long fault_ip; + fpswa_ret_t ret; + + fault_ip =3D regs->cr_iip; + /* + * When the FP trap occurs, the trapping instruction is completed. + * If ipsr.ri =3D=3D 0, there is the trapping instruction in previous + * bundle. + */ + if (!fp_fault && (ia64_psr(regs)->ri =3D=3D 0)) + fault_ip -=3D 16; + + if (fetch_code(v, fault_ip, &bundle)) + return -EAGAIN; + + if (!bundle.i64[0] && !bundle.i64[1]) { + return -EACCES; + } + + ret =3D vmm_fp_emulate(fp_fault, &bundle, ®s->cr_ipsr, ®s->ar_fpsr, + &isr, ®s->pr, ®s->cr_ifs, regs); + return ret.status; +} + +void reflect_interruption(u64 ifa, u64 isr, u64 iim, + u64 vec, REGS *regs) +{ + u64 vector; + int status ; + VCPU *vcpu =3D current_vcpu; + u64 vpsr =3D VCPU(vcpu, vpsr); + + vector =3D vec2off[vec]; + + if (!(vpsr & IA64_PSR_IC) && (vector !=3D IA64_DATA_NESTED_TLB_VECTOR)) { + panic_vm(vcpu); + return; + } + + switch (vec) { + case 32: + status =3D vmm_handle_fpu_swa(1, regs, isr); + if (!status) { + vcpu_increment_iip(vcpu); + return; + } else if (-EAGAIN =3D=3D status) + return; + break; + case 33: + status =3D vmm_handle_fpu_swa(0, regs, isr); + if (!status) + return ; + else if (-EAGAIN =3D=3D status) { + vcpu_decrement_iip(vcpu); + return ; + } + break; + } + + VCPU(vcpu, isr) =3D isr; + VCPU(vcpu, iipa) =3D regs->cr_iip; + if (vector =3D=3D IA64_BREAK_VECTOR || vector =3D=3D IA64_SPECULATION_VECTOR) + VCPU(vcpu, iim) =3D iim; + else { + set_ifa_itir_iha(vcpu, ifa, 1, 1, 1); + } + inject_guest_interruption(vcpu, vector); +} + +static void set_pal_call_data(VCPU *vcpu) +{ + struct exit_ctl_data *p =3D &vcpu->arch.exit_data; + + /*FIXME:For static and stacked convention, firmware + * has put the parameters in gr28-gr31 before + * break to vmm !!*/ + + p->u.pal_data.gr28 =3D vcpu_get_gr(vcpu, 28); + p->u.pal_data.gr29 =3D vcpu_get_gr(vcpu, 29); + p->u.pal_data.gr30 =3D vcpu_get_gr(vcpu, 30); + p->u.pal_data.gr31 =3D vcpu_get_gr(vcpu, 31); + p->exit_reason =3D EXIT_REASON_PAL_CALL; +} + +static void set_pal_call_result(VCPU *vcpu) +{ + struct exit_ctl_data *p =3D &vcpu->arch.exit_data; + + if (p->exit_reason =3D=3D EXIT_REASON_PAL_CALL) { + vcpu_set_gr(vcpu, 8, p->u.pal_data.ret.status, 0); + vcpu_set_gr(vcpu, 9, p->u.pal_data.ret.v0, 0); + vcpu_set_gr(vcpu, 10, p->u.pal_data.ret.v1, 0); + vcpu_set_gr(vcpu, 11, p->u.pal_data.ret.v2, 0); + } else + panic_vm(vcpu); +} + +static void set_sal_call_data(VCPU *vcpu) +{ + struct exit_ctl_data *p =3D &vcpu->arch.exit_data; + + p->u.sal_data.in0 =3D vcpu_get_gr(vcpu, 32); + p->u.sal_data.in1 =3D vcpu_get_gr(vcpu, 33); + p->u.sal_data.in2 =3D vcpu_get_gr(vcpu, 34); + p->u.sal_data.in3 =3D vcpu_get_gr(vcpu, 35); + p->u.sal_data.in4 =3D vcpu_get_gr(vcpu, 36); + p->u.sal_data.in5 =3D vcpu_get_gr(vcpu, 37); + p->u.sal_data.in6 =3D vcpu_get_gr(vcpu, 38); + p->u.sal_data.in7 =3D vcpu_get_gr(vcpu, 39); + p->exit_reason =3D EXIT_REASON_SAL_CALL; +} + +static void set_sal_call_result(VCPU *vcpu) +{ + struct exit_ctl_data *p =3D &vcpu->arch.exit_data; + + if (p->exit_reason =3D=3D EXIT_REASON_SAL_CALL) { + vcpu_set_gr(vcpu, 8, p->u.sal_data.ret.r8, 0); + vcpu_set_gr(vcpu, 9, p->u.sal_data.ret.r9, 0); + vcpu_set_gr(vcpu, 10, p->u.sal_data.ret.r10, 0); + vcpu_set_gr(vcpu, 11, p->u.sal_data.ret.r11, 0); + } else + panic_vm(vcpu); +} + +void kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs, + unsigned long isr, unsigned long iim) +{ + VCPU *v =3D current_vcpu; + + if (ia64_psr(regs)->cpl =3D=3D 0) { + /* Allow hypercalls only when cpl =3D 0. */ + if (iim =3D=3D DOMN_PAL_REQUEST) { + set_pal_call_data(v); + vmm_transition(v); + set_pal_call_result(v); + vcpu_increment_iip(v); + return; + } else if (iim =3D=3D DOMN_SAL_REQUEST) { + set_sal_call_data(v); + vmm_transition(v); + set_sal_call_result(v); + vcpu_increment_iip(v); + return; + } + } + reflect_interruption(ifa, isr, iim, 11, regs); +} + +void check_pending_irq(VCPU *vcpu) +{ + int mask, h_pending, h_inservice; + u64 isr; + ia64_psr vpsr; + REGS *regs =3D vcpu_regs(vcpu); + + h_pending =3D highest_pending_irq(vcpu); + if (h_pending =3D=3D NULL_VECTOR) { + update_vhpi(vcpu, NULL_VECTOR); + return; + } + h_inservice =3D highest_inservice_irq(vcpu); + + vpsr.val =3D VCPU(vcpu, vpsr); + mask =3D irq_masked(vcpu, h_pending, h_inservice); + if (vpsr.i && IRQ_NO_MASKED =3D=3D mask) { + isr =3D vpsr.val & IA64_PSR_RI; + update_vhpi(vcpu, h_pending); + reflect_interruption(0, isr, 0, 12, regs); /* EXT IRQ */ + } else if (mask =3D=3D IRQ_MASKED_BY_INSVC) { + if (VCPU(vcpu, vhpi)) + update_vhpi(vcpu, NULL_VECTOR); + } else { + /* masked by vpsr.i or vtpr.*/ + update_vhpi(vcpu, h_pending); + } +} + +static void generate_exirq(VCPU *vcpu) +{ + ia64_psr vpsr; + uint64_t isr; + + REGS *regs =3D vcpu_regs(vcpu); + + vpsr.val =3D VCPU(vcpu, vpsr); + isr =3D vpsr.val & IA64_PSR_RI; + if (!vpsr.ic) + panic_vm(vcpu); + reflect_interruption(0, isr, 0, 12, regs); /* EXT IRQ */ +} + +void vhpi_detection(VCPU *vcpu) +{ + uint64_t threshold, vhpi; + tpr_t vtpr; + ia64_psr vpsr; + + vpsr.val =3D VCPU(vcpu, vpsr); + vtpr.val =3D VCPU(vcpu, tpr); + + threshold =3D ((!vpsr.i) << 5) | (vtpr.mmi << 4) | vtpr.mic; + vhpi =3D VCPU(vcpu, vhpi); + if (vhpi > threshold) { + /* interrupt actived*/ + generate_exirq(vcpu); + } +} + + +void leave_hypervisor_tail(void) +{ + VCPU *v =3D current_vcpu; + + if (VMX(v, timer_check)) { + VMX(v, timer_check) =3D 0; + if (VMX(v, itc_check)) { + if (vcpu_get_itc(v) > VCPU(v, itm)) { + if (!(VCPU(v, itv) & (1 << 16))) { + vcpu_pend_interrupt(v, VCPU(v, itv) + & 0xff); + VMX(v, itc_check) =3D 0; + } else { + v->arch.timer_pending =3D 1; + } + VMX(v, last_itc) =3D VCPU(v, itm) + 1; + } + } + } + + rmb(); + if (v->arch.irq_new_pending) { + v->arch.irq_new_pending =3D 0; + VMX(v, irq_check) =3D 0; + check_pending_irq(v); + return; + } + if (VMX(v, irq_check)) { + VMX(v, irq_check) =3D 0; + vhpi_detection(v); + } +} + + +static inline void handle_lds(REGS *regs) +{ + regs->cr_ipsr |=3D IA64_PSR_ED; +} + +void physical_tlb_miss(VCPU *vcpu, unsigned long vadr, int type) +{ + unsigned long pte; + ia64_rr rr; + + rr.val =3D ia64_get_rr(vadr); + pte =3D vadr & _PAGE_PPN_MASK; + pte =3D pte | PHY_PAGE_WB; + thash_vhpt_insert(vcpu, pte, (u64)(rr.ps << 2), vadr, type); + return; +} + +void kvm_page_fault(u64 vadr , u64 vec, REGS *regs) +{ + ia64_psr vpsr; + int type; + + u64 vhpt_adr, gppa, pteval, rr, itir; + ia64_isr misr; + ia64_pta vpta; + thash_data_t *data; + VCPU *v =3D current_vcpu; + + vpsr.val =3D VCPU(v, vpsr); + misr.val =3D VMX(v, cr_isr); + + type =3D vec; + + if (is_physical_mode(v) && (!(vadr << 1 >> 62))) { + if (vec =3D=3D 2) { + if (__gpfn_is_io((vadr << 1) >> (PAGE_SHIFT + 1))) { + emulate_io_inst(v, ((vadr << 1) >> 1), 4); + return; + } + } + physical_tlb_miss(v, vadr, type); + return; + } + data =3D vtlb_lookup(v, vadr, type); + if (data !=3D 0) { + if (type =3D=3D D_TLB) { + gppa =3D (vadr & ((1UL << data->ps) - 1)) + + (data->ppn >> (data->ps - 12) << data->ps); + if (__gpfn_is_io(gppa >> PAGE_SHIFT)) { + if (data->pl >=3D ((regs->cr_ipsr >> + IA64_PSR_CPL0_BIT) & 3)) + emulate_io_inst(v, gppa, data->ma); + else { + vcpu_set_isr(v, misr.val); + data_access_rights(v, vadr); + } + return ; + } + } + thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type); + + } else if (type =3D=3D D_TLB) { + if (misr.sp) { + handle_lds(regs); + return; + } + + rr =3D vcpu_get_rr(v, vadr); + itir =3D rr & (RR_RID_MASK | RR_PS_MASK); + + if (!vhpt_enabled(v, vadr, misr.rs ? RSE_REF : DATA_REF)) { + if (vpsr.ic) { + vcpu_set_isr(v, misr.val); + alt_dtlb(v, vadr); + } else { + nested_dtlb(v); + } + return ; + } + + vpta.val =3D vcpu_get_pta(v); + /* avoid recursively walking (short format) VHPT */ + + vhpt_adr =3D vcpu_thash(v, vadr); + if (!guest_vhpt_lookup(vhpt_adr, &pteval)) { + /* VHPT successfully read. */ + if (!(pteval & _PAGE_P)) { + if (vpsr.ic) { + vcpu_set_isr(v, misr.val); + dtlb_fault(v, vadr); + } else { + nested_dtlb(v); + } + } else if ((pteval & _PAGE_MA_MASK) !=3D _PAGE_MA_ST) { + thash_purge_and_insert(v, pteval, itir, + vadr, D_TLB); + } else if (vpsr.ic) { + vcpu_set_isr(v, misr.val); + dtlb_fault(v, vadr); + } else { + nested_dtlb(v); + } + } else { + /* Can't read VHPT. */ + if (vpsr.ic) { + vcpu_set_isr(v, misr.val); + dvhpt_fault(v, vadr); + } else { + nested_dtlb(v); + } + } + } else if (type =3D=3D I_TLB) { + if (!vpsr.ic) + misr.ni =3D 1; + if (!vhpt_enabled(v, vadr, INST_REF)) { + vcpu_set_isr(v, misr.val); + alt_itlb(v, vadr); + return; + } + + vpta.val =3D vcpu_get_pta(v); + + vhpt_adr =3D vcpu_thash(v, vadr); + if (!guest_vhpt_lookup(vhpt_adr, &pteval)) { + /* VHPT successfully read. */ + if (pteval & _PAGE_P) { + if ((pteval & _PAGE_MA_MASK) =3D=3D _PAGE_MA_ST) { + vcpu_set_isr(v, misr.val); + itlb_fault(v, vadr); + return ; + } + rr =3D vcpu_get_rr(v, vadr); + itir =3D rr & (RR_RID_MASK | RR_PS_MASK); + thash_purge_and_insert(v, pteval, itir, + vadr, I_TLB); + } else { + vcpu_set_isr(v, misr.val); + inst_page_not_present(v, vadr); + } + } else { + vcpu_set_isr(v, misr.val); + ivhpt_fault(v, vadr); + } + } +} + +void kvm_vexirq(VCPU *vcpu) +{ + u64 vpsr, isr; + REGS *regs; + + regs =3D vcpu_regs(vcpu); + vpsr =3D VCPU(vcpu, vpsr); + isr =3D vpsr & IA64_PSR_RI; + reflect_interruption(0, isr, 0, 12, regs); /*EXT IRQ*/ +} + +void kvm_ia64_handle_irq(VCPU *v) +{ + struct exit_ctl_data *p =3D &v->arch.exit_data; + long psr; + + local_irq_save(psr); + p->exit_reason =3D EXIT_REASON_EXTERNAL_INTERRUPT; + vmm_transition(v); + local_irq_restore(psr); + + VMX(v, timer_check) =3D 1; + +} + +static void ptc_ga_remote_func(struct kvm_vcpu *v, int pos) +{ + u64 oldrid, moldrid, oldpsbits, vaddr; + struct kvm_ptc_g *p =3D &v->arch.ptc_g_data[pos]; + vaddr =3D p->vaddr; + + oldrid =3D VMX(v, vrr[0]); + VMX(v, vrr[0]) =3D p->rr; + oldpsbits =3D VMX(v, psbits[0]); + VMX(v, psbits[0]) =3D VMX(v, psbits[REGION_NUMBER(vaddr)]); + moldrid =3D ia64_get_rr(0x0); + ia64_set_rr(0x0, vrrtomrr(p->rr)); + ia64_srlz_d(); + + vaddr =3D PAGEALIGN(vaddr, p->ps); + thash_purge_entries_remote(v, vaddr, p->ps); + + VMX(v, vrr[0]) =3D oldrid; + VMX(v, psbits[0]) =3D oldpsbits; + ia64_set_rr(0x0, moldrid); + ia64_dv_serialize_data(); +} + +static void do_ptc_g_emul(struct kvm_vcpu *vcpu) +{ + + if (unlikely(test_and_clear_bit(KVM_REQ_FLUSH_ALL, &vcpu->requests))) { + thash_purge_all(vcpu); + return; + } + + if (test_and_clear_bit(KVM_REQ_PTC_G, &vcpu->requests)) { + while (vcpu->arch.ptc_g_count > 0) + ptc_ga_remote_func(vcpu, --vcpu->arch.ptc_g_count); + } +} + +void vmm_transition(struct kvm_vcpu *vcpu) +{ + ia64_call_vsa(PAL_VPS_SAVE, (unsigned long)vcpu->arch.vpd, + 0, 0, 0, 0, 0, 0); + vmm_trampoline(&vcpu->arch.guest, &vcpu->arch.host); + ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)vcpu->arch.vpd, + 0, 0, 0, 0, 0, 0); + do_ptc_g_emul(vcpu); +} --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:30:14
|
From: Zhang Xiantao <xia...@in...> Date: Tue, 29 Jan 2008 14:32:14 +0800 Subject: [PATCH] kvm/ia64: Add trampoline for guest/host mode switch. trampoline.S is for guest/host mode switch. Signed-off-by: Anthony Xu <ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/trampoline.S | 1040 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1040 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/trampoline.S diff --git a/arch/ia64/kvm/trampoline.S b/arch/ia64/kvm/trampoline.S new file mode 100644 index 0000000..d3232b5 --- /dev/null +++ b/arch/ia64/kvm/trampoline.S @@ -0,0 +1,1040 @@ +/* Save all processor states + * + * Copyright (c) 2007 Fleming Feng <fle...@in...> + * Copyright (c) 2007 Anthony Xu <ant...@in...> + */ + +#include <asm/asmmacro.h> +#include "asm-offsets.h" + + +#define CTX(name) VMM_CTX_##name##_OFFSET + + /* + * r32: context_t base address + */ +#define SAVE_BRANCH_REGS \ + add r2 =3D CTX(B0),r32; \ + add r3 =3D CTX(B1),r32; \ + mov r16 =3D b0; \ + mov r17 =3D b1; \ + ;; \ + st8 [r2]=3Dr16,16; \ + st8 [r3]=3Dr17,16; \ + ;; \ + mov r16 =3D b2; \ + mov r17 =3D b3; \ + ;; \ + st8 [r2]=3Dr16,16; \ + st8 [r3]=3Dr17,16; \ + ;; \ + mov r16 =3D b4; \ + mov r17 =3D b5; \ + ;; \ + st8 [r2]=3Dr16; \ + st8 [r3]=3Dr17; \ + ;; + + /* + * r33: context_t base address + */ +#define RESTORE_BRANCH_REGS \ + add r2 =3D CTX(B0),r33; \ + add r3 =3D CTX(B1),r33; \ + ;; \ + ld8 r16=3D[r2],16; \ + ld8 r17=3D[r3],16; \ + ;; \ + mov b0 =3D r16; \ + mov b1 =3D r17; \ + ;; \ + ld8 r16=3D[r2],16; \ + ld8 r17=3D[r3],16; \ + ;; \ + mov b2 =3D r16; \ + mov b3 =3D r17; \ + ;; \ + ld8 r16=3D[r2]; \ + ld8 r17=3D[r3]; \ + ;; \ + mov b4=3Dr16; \ + mov b5=3Dr17; \ + ;; + + + /* + * r32: context_t base address + * bsw =3D=3D 1 + * Save all bank1 general registers, r4 ~ r7 + */ +#define SAVE_GENERAL_REGS \ + add r2=3DCTX(R4),r32; \ + add r3=3DCTX(R5),r32; \ + ;; \ +.mem.offset 0,0; \ + st8.spill [r2]=3Dr4,16; \ +.mem.offset 8,0; \ + st8.spill [r3]=3Dr5,16; \ + ;; \ +.mem.offset 0,0; \ + st8.spill [r2]=3Dr6,48; \ +.mem.offset 8,0; \ + st8.spill [r3]=3Dr7,48; \ + ;; \ +.mem.offset 0,0; \ + st8.spill [r2]=3Dr12; \ +.mem.offset 8,0; \ + st8.spill [r3]=3Dr13; \ + ;; + + /* + * r33: context_t base address + * bsw =3D=3D 1 + */ +#define RESTORE_GENERAL_REGS \ + add r2=3DCTX(R4),r33; \ + add r3=3DCTX(R5),r33; \ + ;; \ + ld8.fill r4=3D[r2],16; \ + ld8.fill r5=3D[r3],16; \ + ;; \ + ld8.fill r6=3D[r2],48; \ + ld8.fill r7=3D[r3],48; \ + ;; \ + ld8.fill r12=3D[r2]; \ + ld8.fill r13 =3D[r3]; \ + ;; + + + + + /* + * r32: context_t base address + */ +#define SAVE_KERNEL_REGS \ + add r2 =3D CTX(KR0),r32; \ + add r3 =3D CTX(KR1),r32; \ + mov r16 =3D ar.k0; \ + mov r17 =3D ar.k1; \ + ;; \ + st8 [r2] =3D r16,16; \ + st8 [r3] =3D r17,16; \ + ;; \ + mov r16 =3D ar.k2; \ + mov r17 =3D ar.k3; \ + ;; \ + st8 [r2] =3D r16,16; \ + st8 [r3] =3D r17,16; \ + ;; \ + mov r16 =3D ar.k4; \ + mov r17 =3D ar.k5; \ + ;; \ + st8 [r2] =3D r16,16; \ + st8 [r3] =3D r17,16; \ + ;; \ + mov r16 =3D ar.k6; \ + mov r17 =3D ar.k7; \ + ;; \ + st8 [r2] =3D r16; \ + st8 [r3] =3D r17; \ + ;; + + + + /* + * r33: context_t base address + */ +#define RESTORE_KERNEL_REGS \ + add r2 =3D CTX(KR0),r33; \ + add r3 =3D CTX(KR1),r33; \ + ;; \ + ld8 r16=3D[r2],16; \ + ld8 r17=3D[r3],16; \ + ;; \ + mov ar.k0=3Dr16; \ + mov ar.k1=3Dr17; \ + ;; \ + ld8 r16=3D[r2],16; \ + ld8 r17=3D[r3],16; \ + ;; \ + mov ar.k2=3Dr16; \ + mov ar.k3=3Dr17; \ + ;; \ + ld8 r16=3D[r2],16; \ + ld8 r17=3D[r3],16; \ + ;; \ + mov ar.k4=3Dr16; \ + mov ar.k5=3Dr17; \ + ;; \ + ld8 r16=3D[r2],16; \ + ld8 r17=3D[r3],16; \ + ;; \ + mov ar.k6=3Dr16; \ + mov ar.k7=3Dr17; \ + ;; + + + + /* + * r32: context_t base address + */ +#define SAVE_APP_REGS \ + add r2 =3D CTX(BSPSTORE),r32; \ + mov r16 =3D ar.bspstore; \ + ;; \ + st8 [r2] =3D r16,CTX(RNAT)-CTX(BSPSTORE);\ + mov r16 =3D ar.rnat; \ + ;; \ + st8 [r2] =3D r16,CTX(FCR)-CTX(RNAT); \ + mov r16 =3D ar.fcr; \ + ;; \ + st8 [r2] =3D r16,CTX(EFLAG)-CTX(FCR); \ + mov r16 =3D ar.eflag; \ + ;; \ + st8 [r2] =3D r16,CTX(CFLG)-CTX(EFLAG); \ + mov r16 =3D ar.cflg; \ + ;; \ + st8 [r2] =3D r16,CTX(FSR)-CTX(CFLG); \ + mov r16 =3D ar.fsr; \ + ;; \ + st8 [r2] =3D r16,CTX(FIR)-CTX(FSR); \ + mov r16 =3D ar.fir; \ + ;; \ + st8 [r2] =3D r16,CTX(FDR)-CTX(FIR); \ + mov r16 =3D ar.fdr; \ + ;; \ + st8 [r2] =3D r16,CTX(UNAT)-CTX(FDR); \ + mov r16 =3D ar.unat; \ + ;; \ + st8 [r2] =3D r16,CTX(FPSR)-CTX(UNAT); \ + mov r16 =3D ar.fpsr; \ + ;; \ + st8 [r2] =3D r16,CTX(PFS)-CTX(FPSR); \ + mov r16 =3D ar.pfs; \ + ;; \ + st8 [r2] =3D r16,CTX(LC)-CTX(PFS); \ + mov r16 =3D ar.lc; \ + ;; \ + st8 [r2] =3D r16; \ + ;; + + /* + * r33: context_t base address + */ +#define RESTORE_APP_REGS \ + add r2=3DCTX(BSPSTORE),r33; \ + ;; \ + ld8 r16=3D[r2],CTX(RNAT)-CTX(BSPSTORE); \ + ;; \ + mov ar.bspstore=3Dr16; \ + ld8 r16=3D[r2],CTX(FCR)-CTX(RNAT); \ + ;; \ + mov ar.rnat=3Dr16; \ + ld8 r16=3D[r2],CTX(EFLAG)-CTX(FCR); \ + ;; \ + mov ar.fcr=3Dr16; \ + ld8 r16=3D[r2],CTX(CFLG)-CTX(EFLAG); \ + ;; \ + mov ar.eflag=3Dr16; \ + ld8 r16=3D[r2],CTX(FSR)-CTX(CFLG); \ + ;; \ + mov ar.cflg=3Dr16; \ + ld8 r16=3D[r2],CTX(FIR)-CTX(FSR); \ + ;; \ + mov ar.fsr=3Dr16; \ + ld8 r16=3D[r2],CTX(FDR)-CTX(FIR); \ + ;; \ + mov ar.fir=3Dr16; \ + ld8 r16=3D[r2],CTX(UNAT)-CTX(FDR); \ + ;; \ + mov ar.fdr=3Dr16; \ + ld8 r16=3D[r2],CTX(FPSR)-CTX(UNAT); \ + ;; \ + mov ar.unat=3Dr16; \ + ld8 r16=3D[r2],CTX(PFS)-CTX(FPSR); \ + ;; \ + mov ar.fpsr=3Dr16; \ + ld8 r16=3D[r2],CTX(LC)-CTX(PFS); \ + ;; \ + mov ar.pfs=3Dr16; \ + ld8 r16=3D[r2]; \ + ;; \ + mov ar.lc=3Dr16; \ + ;; + + /* + * r32: context_t base address + */ +#define SAVE_CTL_REGS \ + add r2 =3D CTX(DCR),r32; \ + mov r16 =3D cr.dcr; \ + ;; \ + st8 [r2] =3D r16,CTX(IVA)-CTX(DCR); \ + ;; \ + mov r16 =3D cr.iva; \ + ;; \ + st8 [r2] =3D r16,CTX(PTA)-CTX(IVA); \ + ;; \ + mov r16 =3D cr.pta; \ + ;; \ + st8 [r2] =3D r16 ; \ + ;; + + /* + * r33: context_t base address + */ +#define RESTORE_CTL_REGS \ + add r2 =3D CTX(DCR),r33; \ + ;; \ + ld8 r16 =3D [r2],CTX(IVA)-CTX(DCR); \ + ;; \ + mov cr.dcr =3D r16; \ + dv_serialize_data; \ + ;; \ + ld8 r16 =3D [r2],CTX(PTA)-CTX(IVA); \ + ;; \ + mov cr.iva =3D r16; \ + dv_serialize_data; \ + ;; \ + ld8 r16 =3D [r2]; \ + ;; \ + mov cr.pta =3D r16; \ + dv_serialize_data; \ + ;; + + + /* + * r32: context_t base address + */ +#define SAVE_REGION_REGS \ + add r2=3DCTX(RR0),r32; \ + mov r16=3Drr[r0]; \ + dep.z r18=3D1,61,3; \ + ;; \ + st8 [r2]=3Dr16,8; \ + mov r17=3Drr[r18]; \ + dep.z r18=3D2,61,3; \ + ;; \ + st8 [r2]=3Dr17,8; \ + mov r16=3Drr[r18]; \ + dep.z r18=3D3,61,3; \ + ;; \ + st8 [r2]=3Dr16,8; \ + mov r17=3Drr[r18]; \ + dep.z r18=3D4,61,3; \ + ;; \ + st8 [r2]=3Dr17,8; \ + mov r16=3Drr[r18]; \ + dep.z r18=3D5,61,3; \ + ;; \ + st8 [r2]=3Dr16,8; \ + mov r17=3Drr[r18]; \ + dep.z r18=3D7,61,3; \ + ;; \ + st8 [r2]=3Dr17,16; \ + mov r16=3Drr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + ;; + + /* + * r33:context_t base address + */ +#define RESTORE_REGION_REGS \ + add r2=3DCTX(RR0),r33;\ + mov r18=3Dr0; \ + ;; \ + ld8 r20=3D[r2],8; \ + ;; /* rr0 */ \ + ld8 r21=3D[r2],8; \ + ;; /* rr1 */ \ + ld8 r22=3D[r2],8; \ + ;; /* rr2 */ \ + ld8 r23=3D[r2],8; \ + ;; /* rr3 */ \ + ld8 r24=3D[r2],8; \ + ;; /* rr4 */ \ + ld8 r25=3D[r2],16; \ + ;; /* rr5 */ \ + ld8 r27=3D[r2]; \ + ;; /* rr7 */ \ + mov rr[r18]=3Dr20; \ + dep.z r18=3D1,61,3; \ + ;; /* rr1 */ \ + mov rr[r18]=3Dr21; \ + dep.z r18=3D2,61,3; \ + ;; /* rr2 */ \ + mov rr[r18]=3Dr22; \ + dep.z r18=3D3,61,3; \ + ;; /* rr3 */ \ + mov rr[r18]=3Dr23; \ + dep.z r18=3D4,61,3; \ + ;; /* rr4 */ \ + mov rr[r18]=3Dr24; \ + dep.z r18=3D5,61,3; \ + ;; /* rr5 */ \ + mov rr[r18]=3Dr25; \ + dep.z r18=3D7,61,3; \ + ;; /* rr7 */ \ + mov rr[r18]=3Dr27; \ + ;; \ + srlz.i; \ + ;; + + + + /* + * r32: context_t base address + * r36~r39:scratch registers + */ +#define SAVE_DEBUG_REGS \ + add r2=3DCTX(IBR0),r32; \ + add r3=3DCTX(DBR0),r32; \ + mov r16=3Dibr[r0]; \ + mov r17=3Ddbr[r0]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D1,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D2,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D2,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D3,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D4,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D5,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D6,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + add r18=3D7,r0; \ + ;; \ + mov r16=3Dibr[r18]; \ + mov r17=3Ddbr[r18]; \ + ;; \ + st8 [r2]=3Dr16,8; \ + st8 [r3]=3Dr17,8; \ + ;; + + +/* + * r33: point to context_t structure + * ar.lc are corrupted. + */ +#define RESTORE_DEBUG_REGS \ + add r2=3DCTX(IBR0),r33; \ + add r3=3DCTX(DBR0),r33; \ + mov r16=3D7; \ + mov r17=3Dr0; \ + ;; \ + mov ar.lc =3D r16; \ + ;; \ +1: \ + ld8 r18=3D[r2],8; \ + ld8 r19=3D[r3],8; \ + ;; \ + mov ibr[r17]=3Dr18; \ + mov dbr[r17]=3Dr19; \ + ;; \ + srlz.i; \ + ;; \ + add r17=3D1,r17; \ + br.cloop.sptk 1b; \ + ;; + + + /* + * r32: context_t base address + */ +#define SAVE_FPU_LOW \ + add r2=3DCTX(F2),r32; \ + add r3=3DCTX(F3),r32; \ + ;; \ + stf.spill.nta [r2]=3Df2,32; \ + stf.spill.nta [r3]=3Df3,32; \ + ;; \ + stf.spill.nta [r2]=3Df4,32; \ + stf.spill.nta [r3]=3Df5,32; \ + ;; \ + stf.spill.nta [r2]=3Df6,32; \ + stf.spill.nta [r3]=3Df7,32; \ + ;; \ + stf.spill.nta [r2]=3Df8,32; \ + stf.spill.nta [r3]=3Df9,32; \ + ;; \ + stf.spill.nta [r2]=3Df10,32; \ + stf.spill.nta [r3]=3Df11,32; \ + ;; \ + stf.spill.nta [r2]=3Df12,32; \ + stf.spill.nta [r3]=3Df13,32; \ + ;; \ + stf.spill.nta [r2]=3Df14,32; \ + stf.spill.nta [r3]=3Df15,32; \ + ;; \ + stf.spill.nta [r2]=3Df16,32; \ + stf.spill.nta [r3]=3Df17,32; \ + ;; \ + stf.spill.nta [r2]=3Df18,32; \ + stf.spill.nta [r3]=3Df19,32; \ + ;; \ + stf.spill.nta [r2]=3Df20,32; \ + stf.spill.nta [r3]=3Df21,32; \ + ;; \ + stf.spill.nta [r2]=3Df22,32; \ + stf.spill.nta [r3]=3Df23,32; \ + ;; \ + stf.spill.nta [r2]=3Df24,32; \ + stf.spill.nta [r3]=3Df25,32; \ + ;; \ + stf.spill.nta [r2]=3Df26,32; \ + stf.spill.nta [r3]=3Df27,32; \ + ;; \ + stf.spill.nta [r2]=3Df28,32; \ + stf.spill.nta [r3]=3Df29,32; \ + ;; \ + stf.spill.nta [r2]=3Df30; \ + stf.spill.nta [r3]=3Df31; \ + ;; + + /* + * r32: context_t base address + */ +#define SAVE_FPU_HIGH \ + add r2=3DCTX(F32),r32; \ + add r3=3DCTX(F33),r32; \ + ;; \ + stf.spill.nta [r2]=3Df32,32; \ + stf.spill.nta [r3]=3Df33,32; \ + ;; \ + stf.spill.nta [r2]=3Df34,32; \ + stf.spill.nta [r3]=3Df35,32; \ + ;; \ + stf.spill.nta [r2]=3Df36,32; \ + stf.spill.nta [r3]=3Df37,32; \ + ;; \ + stf.spill.nta [r2]=3Df38,32; \ + stf.spill.nta [r3]=3Df39,32; \ + ;; \ + stf.spill.nta [r2]=3Df40,32; \ + stf.spill.nta [r3]=3Df41,32; \ + ;; \ + stf.spill.nta [r2]=3Df42,32; \ + stf.spill.nta [r3]=3Df43,32; \ + ;; \ + stf.spill.nta [r2]=3Df44,32; \ + stf.spill.nta [r3]=3Df45,32; \ + ;; \ + stf.spill.nta [r2]=3Df46,32; \ + stf.spill.nta [r3]=3Df47,32; \ + ;; \ + stf.spill.nta [r2]=3Df48,32; \ + stf.spill.nta [r3]=3Df49,32; \ + ;; \ + stf.spill.nta [r2]=3Df50,32; \ + stf.spill.nta [r3]=3Df51,32; \ + ;; \ + stf.spill.nta [r2]=3Df52,32; \ + stf.spill.nta [r3]=3Df53,32; \ + ;; \ + stf.spill.nta [r2]=3Df54,32; \ + stf.spill.nta [r3]=3Df55,32; \ + ;; \ + stf.spill.nta [r2]=3Df56,32; \ + stf.spill.nta [r3]=3Df57,32; \ + ;; \ + stf.spill.nta [r2]=3Df58,32; \ + stf.spill.nta [r3]=3Df59,32; \ + ;; \ + stf.spill.nta [r2]=3Df60,32; \ + stf.spill.nta [r3]=3Df61,32; \ + ;; \ + stf.spill.nta [r2]=3Df62,32; \ + stf.spill.nta [r3]=3Df63,32; \ + ;; \ + stf.spill.nta [r2]=3Df64,32; \ + stf.spill.nta [r3]=3Df65,32; \ + ;; \ + stf.spill.nta [r2]=3Df66,32; \ + stf.spill.nta [r3]=3Df67,32; \ + ;; \ + stf.spill.nta [r2]=3Df68,32; \ + stf.spill.nta [r3]=3Df69,32; \ + ;; \ + stf.spill.nta [r2]=3Df70,32; \ + stf.spill.nta [r3]=3Df71,32; \ + ;; \ + stf.spill.nta [r2]=3Df72,32; \ + stf.spill.nta [r3]=3Df73,32; \ + ;; \ + stf.spill.nta [r2]=3Df74,32; \ + stf.spill.nta [r3]=3Df75,32; \ + ;; \ + stf.spill.nta [r2]=3Df76,32; \ + stf.spill.nta [r3]=3Df77,32; \ + ;; \ + stf.spill.nta [r2]=3Df78,32; \ + stf.spill.nta [r3]=3Df79,32; \ + ;; \ + stf.spill.nta [r2]=3Df80,32; \ + stf.spill.nta [r3]=3Df81,32; \ + ;; \ + stf.spill.nta [r2]=3Df82,32; \ + stf.spill.nta [r3]=3Df83,32; \ + ;; \ + stf.spill.nta [r2]=3Df84,32; \ + stf.spill.nta [r3]=3Df85,32; \ + ;; \ + stf.spill.nta [r2]=3Df86,32; \ + stf.spill.nta [r3]=3Df87,32; \ + ;; \ + stf.spill.nta [r2]=3Df88,32; \ + stf.spill.nta [r3]=3Df89,32; \ + ;; \ + stf.spill.nta [r2]=3Df90,32; \ + stf.spill.nta [r3]=3Df91,32; \ + ;; \ + stf.spill.nta [r2]=3Df92,32; \ + stf.spill.nta [r3]=3Df93,32; \ + ;; \ + stf.spill.nta [r2]=3Df94,32; \ + stf.spill.nta [r3]=3Df95,32; \ + ;; \ + stf.spill.nta [r2]=3Df96,32; \ + stf.spill.nta [r3]=3Df97,32; \ + ;; \ + stf.spill.nta [r2]=3Df98,32; \ + stf.spill.nta [r3]=3Df99,32; \ + ;; \ + stf.spill.nta [r2]=3Df100,32; \ + stf.spill.nta [r3]=3Df101,32; \ + ;; \ + stf.spill.nta [r2]=3Df102,32; \ + stf.spill.nta [r3]=3Df103,32; \ + ;; \ + stf.spill.nta [r2]=3Df104,32; \ + stf.spill.nta [r3]=3Df105,32; \ + ;; \ + stf.spill.nta [r2]=3Df106,32; \ + stf.spill.nta [r3]=3Df107,32; \ + ;; \ + stf.spill.nta [r2]=3Df108,32; \ + stf.spill.nta [r3]=3Df109,32; \ + ;; \ + stf.spill.nta [r2]=3Df110,32; \ + stf.spill.nta [r3]=3Df111,32; \ + ;; \ + stf.spill.nta [r2]=3Df112,32; \ + stf.spill.nta [r3]=3Df113,32; \ + ;; \ + stf.spill.nta [r2]=3Df114,32; \ + stf.spill.nta [r3]=3Df115,32; \ + ;; \ + stf.spill.nta [r2]=3Df116,32; \ + stf.spill.nta [r3]=3Df117,32; \ + ;; \ + stf.spill.nta [r2]=3Df118,32; \ + stf.spill.nta [r3]=3Df119,32; \ + ;; \ + stf.spill.nta [r2]=3Df120,32; \ + stf.spill.nta [r3]=3Df121,32; \ + ;; \ + stf.spill.nta [r2]=3Df122,32; \ + stf.spill.nta [r3]=3Df123,32; \ + ;; \ + stf.spill.nta [r2]=3Df124,32; \ + stf.spill.nta [r3]=3Df125,32; \ + ;; \ + stf.spill.nta [r2]=3Df126; \ + stf.spill.nta [r3]=3Df127; \ + ;; + + /* + * r33: point to context_t structure + */ +#define RESTORE_FPU_LOW \ + add r2 =3D CTX(F2), r33; \ + add r3 =3D CTX(F3), r33; \ + ;; \ + ldf.fill.nta f2 =3D [r2], 32; \ + ldf.fill.nta f3 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f4 =3D [r2], 32; \ + ldf.fill.nta f5 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f6 =3D [r2], 32; \ + ldf.fill.nta f7 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f8 =3D [r2], 32; \ + ldf.fill.nta f9 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f10 =3D [r2], 32; \ + ldf.fill.nta f11 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f12 =3D [r2], 32; \ + ldf.fill.nta f13 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f14 =3D [r2], 32; \ + ldf.fill.nta f15 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f16 =3D [r2], 32; \ + ldf.fill.nta f17 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f18 =3D [r2], 32; \ + ldf.fill.nta f19 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f20 =3D [r2], 32; \ + ldf.fill.nta f21 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f22 =3D [r2], 32; \ + ldf.fill.nta f23 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f24 =3D [r2], 32; \ + ldf.fill.nta f25 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f26 =3D [r2], 32; \ + ldf.fill.nta f27 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f28 =3D [r2], 32; \ + ldf.fill.nta f29 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f30 =3D [r2], 32; \ + ldf.fill.nta f31 =3D [r3], 32; \ + ;; + + + + /* + * r33: point to context_t structure + */ +#define RESTORE_FPU_HIGH \ + add r2 =3D CTX(F32), r33; \ + add r3 =3D CTX(F33), r33; \ + ;; \ + ldf.fill.nta f32 =3D [r2], 32; \ + ldf.fill.nta f33 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f34 =3D [r2], 32; \ + ldf.fill.nta f35 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f36 =3D [r2], 32; \ + ldf.fill.nta f37 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f38 =3D [r2], 32; \ + ldf.fill.nta f39 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f40 =3D [r2], 32; \ + ldf.fill.nta f41 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f42 =3D [r2], 32; \ + ldf.fill.nta f43 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f44 =3D [r2], 32; \ + ldf.fill.nta f45 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f46 =3D [r2], 32; \ + ldf.fill.nta f47 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f48 =3D [r2], 32; \ + ldf.fill.nta f49 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f50 =3D [r2], 32; \ + ldf.fill.nta f51 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f52 =3D [r2], 32; \ + ldf.fill.nta f53 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f54 =3D [r2], 32; \ + ldf.fill.nta f55 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f56 =3D [r2], 32; \ + ldf.fill.nta f57 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f58 =3D [r2], 32; \ + ldf.fill.nta f59 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f60 =3D [r2], 32; \ + ldf.fill.nta f61 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f62 =3D [r2], 32; \ + ldf.fill.nta f63 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f64 =3D [r2], 32; \ + ldf.fill.nta f65 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f66 =3D [r2], 32; \ + ldf.fill.nta f67 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f68 =3D [r2], 32; \ + ldf.fill.nta f69 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f70 =3D [r2], 32; \ + ldf.fill.nta f71 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f72 =3D [r2], 32; \ + ldf.fill.nta f73 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f74 =3D [r2], 32; \ + ldf.fill.nta f75 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f76 =3D [r2], 32; \ + ldf.fill.nta f77 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f78 =3D [r2], 32; \ + ldf.fill.nta f79 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f80 =3D [r2], 32; \ + ldf.fill.nta f81 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f82 =3D [r2], 32; \ + ldf.fill.nta f83 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f84 =3D [r2], 32; \ + ldf.fill.nta f85 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f86 =3D [r2], 32; \ + ldf.fill.nta f87 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f88 =3D [r2], 32; \ + ldf.fill.nta f89 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f90 =3D [r2], 32; \ + ldf.fill.nta f91 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f92 =3D [r2], 32; \ + ldf.fill.nta f93 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f94 =3D [r2], 32; \ + ldf.fill.nta f95 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f96 =3D [r2], 32; \ + ldf.fill.nta f97 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f98 =3D [r2], 32; \ + ldf.fill.nta f99 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f100 =3D [r2], 32; \ + ldf.fill.nta f101 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f102 =3D [r2], 32; \ + ldf.fill.nta f103 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f104 =3D [r2], 32; \ + ldf.fill.nta f105 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f106 =3D [r2], 32; \ + ldf.fill.nta f107 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f108 =3D [r2], 32; \ + ldf.fill.nta f109 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f110 =3D [r2], 32; \ + ldf.fill.nta f111 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f112 =3D [r2], 32; \ + ldf.fill.nta f113 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f114 =3D [r2], 32; \ + ldf.fill.nta f115 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f116 =3D [r2], 32; \ + ldf.fill.nta f117 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f118 =3D [r2], 32; \ + ldf.fill.nta f119 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f120 =3D [r2], 32; \ + ldf.fill.nta f121 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f122 =3D [r2], 32; \ + ldf.fill.nta f123 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f124 =3D [r2], 32; \ + ldf.fill.nta f125 =3D [r3], 32; \ + ;; \ + ldf.fill.nta f126 =3D [r2], 32; \ + ldf.fill.nta f127 =3D [r3], 32; \ + ;; + + /* + * r32: context_t base address + */ +#define SAVE_PTK_REGS \ + add r2=3DCTX(PKR0), r32; \ + mov r16=3D7; \ + ;; \ + mov ar.lc=3Dr16; \ + mov r17=3Dr0; \ + ;; \ +1: \ + mov r18=3Dpkr[r17]; \ + ;; \ + srlz.i; \ + ;; \ + st8 [r2]=3Dr18, 8; \ + ;; \ + add r17 =3D1,r17; \ + ;; \ + br.cloop.sptk 1b; \ + ;; + +/* + * r33: point to context_t structure + * ar.lc are corrupted. + */ +#define RESTORE_PTK_REGS \ + add r2=3DCTX(PKR0), r33; \ + mov r16=3D7; \ + ;; \ + mov ar.lc=3Dr16; \ + mov r17=3Dr0; \ + ;; \ +1: \ + ld8 r18=3D[r2], 8; \ + ;; \ + mov pkr[r17]=3Dr18; \ + ;; \ + srlz.i; \ + ;; \ + add r17 =3D1,r17; \ + ;; \ + br.cloop.sptk 1b; \ + ;; + + +/* + * void vmm_trampoline( context_t * from, + * context_t * to) + * + * from: r32 + * to: r33 + * note: interrupt disabled before call this function. + */ +GLOBAL_ENTRY(vmm_trampoline) + mov r16 =3D psr + adds r2 =3D CTX(PSR), r32 + ;; + st8 [r2] =3D r16, 8 // psr + mov r17 =3D pr + ;; + st8 [r2] =3D r17, 8 // pr + mov r18 =3D ar.unat + ;; + st8 [r2] =3D r18 + mov r17 =3D ar.rsc + ;; + adds r2 =3D CTX(RSC),r32 + ;; + st8 [r2]=3D r17 + mov ar.rsc =3D0 + flushrs + ;; + SAVE_GENERAL_REGS + ;; + SAVE_KERNEL_REGS + ;; + SAVE_APP_REGS + ;; + SAVE_BRANCH_REGS + ;; + SAVE_CTL_REGS + ;; + SAVE_REGION_REGS + ;; + //SAVE_DEBUG_REGS + ;; + rsm psr.dfl + ;; + srlz.d + ;; + SAVE_FPU_LOW + ;; + rsm psr.dfh + ;; + srlz.d + ;; + SAVE_FPU_HIGH + ;; + SAVE_PTK_REGS + ;; + RESTORE_PTK_REGS + ;; + RESTORE_FPU_HIGH + ;; + RESTORE_FPU_LOW + ;; + //RESTORE_DEBUG_REGS + ;; + RESTORE_REGION_REGS + ;; + RESTORE_CTL_REGS + ;; + RESTORE_BRANCH_REGS + ;; + RESTORE_APP_REGS + ;; + RESTORE_KERNEL_REGS + ;; + RESTORE_GENERAL_REGS + ;; + adds r2=3DCTX(PSR), r33 + ;; + ld8 r16=3D[r2], 8 // psr + ;; + mov psr.l=3Dr16 + ;; + srlz.d + ;; + ld8 r16=3D[r2], 8 // pr + ;; + mov pr =3Dr16,-1 + ld8 r16=3D[r2] // unat + ;; + mov ar.unat=3Dr16 + ;; + adds r2=3DCTX(RSC),r33 + ;; + ld8 r16 =3D[r2] + ;; + mov ar.rsc =3D r16 + ;; + br.ret.sptk.few b0 +END(vmm_trampoline) + + --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:30:14
|
From: Xiantao Zhang <xia...@in...> Date: Thu, 31 Jan 2008 15:45:48 +0800 Subject: [PATCH] kvm/ia64: Add mmio decoder for kvm/ia64. mmio.c includes mmio decoder routines. Signed-off-by: Anthony Xu <Ant...@in...> Signed-off-by: Xiantao Zhang <xia...@in...> --- arch/ia64/kvm/mmio.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 349 insertions(+), 0 deletions(-) create mode 100644 arch/ia64/kvm/mmio.c diff --git a/arch/ia64/kvm/mmio.c b/arch/ia64/kvm/mmio.c new file mode 100644 index 0000000..3f8027a --- /dev/null +++ b/arch/ia64/kvm/mmio.c @@ -0,0 +1,349 @@ +/* + * mmio.c: MMIO emulation components. + * Copyright (c) 2004, Intel Corporation. + * Yaozu Dong (Eddie Dong) (Edd...@in...) + * Kun Tian (Kevin Tian) (Kev...@in...) + * + * Copyright (c) 2007 Intel Corporation KVM support. + * Xuefei Xu (Anthony Xu) (ant...@in...) + * Xiantao Zhang (xia...@in...) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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/kvm_host.h> + +#include "vcpu.h" + +static void vlsapic_write_xtp(VCPU *v, uint8_t val) +{ + VLSAPIC_XTP(v) =3D val; +} + +/* + * LSAPIC OFFSET + */ +#define PIB_LOW_HALF(ofst) !(ofst & (1 << 20)) +#define PIB_OFST_INTA 0x1E0000 +#define PIB_OFST_XTP 0x1E0008 + +/* + * execute write IPI op. + */ +static void vlsapic_write_ipi(VCPU *vcpu, uint64_t addr, uint64_t data) +{ + struct exit_ctl_data *p =3D ¤t_vcpu->arch.exit_data; + unsigned long psr; + + local_irq_save(psr); + + p->exit_reason =3D EXIT_REASON_IPI; + p->u.ipi_data.addr.val =3D addr; + p->u.ipi_data.data.val =3D data; + vmm_transition(current_vcpu); + + local_irq_restore(psr); + +} + +void lsapic_write(VCPU *v, unsigned long addr, unsigned long length, + unsigned long val) +{ + addr &=3D (PIB_SIZE - 1); + + switch (addr) { + case PIB_OFST_INTA: + /*panic_domain(NULL, "Undefined write on PIB INTA\n");*/ + panic_vm(v); + break; + case PIB_OFST_XTP: + if (length =3D=3D 1) { + vlsapic_write_xtp(v, val); + } else { + /*panic_domain(NULL, + "Undefined write on PIB XTP\n");*/ + panic_vm(v); + } + break; + default: + if (PIB_LOW_HALF(addr)) { + /*lower half */ + if (length !=3D 8) + /*panic_domain(NULL, + "Can't LHF write with size %ld!\n", + length);*/ + panic_vm(v); + else + vlsapic_write_ipi(v, addr, val); + } else { /* upper half + printk("IPI-UHF write %lx\n",addr);*/ + panic_vm(v); + } + break; + } +} + +unsigned long lsapic_read(VCPU *v, unsigned long addr, + unsigned long length) +{ + uint64_t result =3D 0; + + addr &=3D (PIB_SIZE - 1); + + switch (addr) { + case PIB_OFST_INTA: + if (length =3D=3D 1) /* 1 byte load */ + ; /* There is no i8259, there is no INTA access*/ + else + /*panic_domain(NULL,"Undefined read on PIB INTA\n"); */ + panic_vm(v); + + break; + case PIB_OFST_XTP: + if (length =3D=3D 1) { + result =3D VLSAPIC_XTP(v); + /* printk("read xtp %lx\n", result); */ + } else { + /*panic_domain(NULL, + "Undefined read on PIB XTP\n");*/ + panic_vm(v); + } + break; + default: + panic_vm(v); + break; + } + return result; +} + +static void mmio_access(VCPU *vcpu, u64 src_pa, u64 *dest, + u16 s, int ma, int dir) +{ + unsigned long iot; + struct exit_ctl_data *p =3D &vcpu->arch.exit_data; + unsigned long psr; + + iot =3D __gpfn_is_io(src_pa >> PAGE_SHIFT); + + local_irq_save(psr); + + /*Intercept the acces for PIB range*/ + if (iot =3D=3D GPFN_PIB) { + if (!dir) + lsapic_write(vcpu, src_pa, s, *dest); + else + *dest =3D lsapic_read(vcpu, src_pa, s); + goto out; + } + p->exit_reason =3D EXIT_REASON_MMIO_INSTRUCTION; + p->u.ioreq.addr =3D src_pa; + p->u.ioreq.size =3D s; + p->u.ioreq.dir =3D dir; + if (dir =3D=3D IOREQ_WRITE) + p->u.ioreq.data =3D *dest; + p->u.ioreq.state =3D STATE_IOREQ_READY; + vmm_transition(vcpu); + + if (p->u.ioreq.state =3D=3D STATE_IORESP_READY) { + if (dir =3D=3D IOREQ_READ) + *dest =3D p->u.ioreq.data; + } else + panic_vm(vcpu); +out: + local_irq_restore(psr); + return ; +} + +/* + dir 1: read 0:write + inst_type 0:integer 1:floating point + */ +#define SL_INTEGER 0 /* store/load interger*/ +#define SL_FLOATING 1 /* store/load floating*/ + +void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma) +{ + REGS *regs; + IA64_BUNDLE bundle; + int slot, dir =3D 0; + int inst_type =3D -1; + u16 size =3D 0; + u64 data, post_update, slot1a, slot1b, temp; + INST64 inst; + + regs =3D vcpu_regs(vcpu); + + if (fetch_code(vcpu, regs->cr_iip, &bundle)) { + /* if fetch code fail, return and try again */ + return; + } + slot =3D ((ia64_psr *)&(regs->cr_ipsr))->ri; + if (!slot) + inst.inst =3D bundle.slot0; + else if (slot =3D=3D 1) { + slot1a =3D bundle.slot1a; + slot1b =3D bundle.slot1b; + inst.inst =3D slot1a + (slot1b << 18); + } else if (slot =3D=3D 2) + inst.inst =3D bundle.slot2; + + /* Integer Load/Store */ + if (inst.M1.major =3D=3D 4 && inst.M1.m =3D=3D 0 && inst.M1.x =3D=3D = 0) { + inst_type =3D SL_INTEGER; + size =3D (inst.M1.x6 & 0x3); + if ((inst.M1.x6 >> 2) > 0xb) { + /*write*/ + dir =3D IOREQ_WRITE; + data =3D vcpu_get_gr(vcpu, inst.M4.r2); + } else if ((inst.M1.x6 >> 2) < 0xb) { + /*read*/ + dir =3D IOREQ_READ; + } + } else if (inst.M2.major =3D=3D 4 && inst.M2.m =3D=3D 1 && inst.M2.x = =3D=3D 0) { + /* Integer Load + Reg update */ + inst_type =3D SL_INTEGER; + dir =3D IOREQ_READ; + size =3D (inst.M2.x6 & 0x3); + temp =3D vcpu_get_gr(vcpu, inst.M2.r3); + post_update =3D vcpu_get_gr(vcpu, inst.M2.r2); + temp +=3D post_update; + vcpu_set_gr(vcpu, inst.M2.r3, temp, 0); + } else if (inst.M3.major =3D=3D 5) { + /*Integer Load/Store + Imm update*/ + inst_type =3D SL_INTEGER; + size =3D (inst.M3.x6&0x3); + if ((inst.M5.x6 >> 2) > 0xb) { + /*write*/ + dir =3D IOREQ_WRITE; + data =3D vcpu_get_gr(vcpu, inst.M5.r2); + temp =3D vcpu_get_gr(vcpu, inst.M5.r3); + post_update =3D (inst.M5.i << 7) + inst.M5.imm7; + if (inst.M5.s) + temp -=3D post_update; + else + temp +=3D post_update; + vcpu_set_gr(vcpu, inst.M5.r3, temp, 0); + + } else if ((inst.M3.x6 >> 2) < 0xb) { + /*read*/ + dir =3D IOREQ_READ; + temp =3D vcpu_get_gr(vcpu, inst.M3.r3); + post_update =3D (inst.M3.i << 7) + inst.M3.imm7; + if (inst.M3.s) + temp -=3D post_update; + else + temp +=3D post_update; + vcpu_set_gr(vcpu, inst.M3.r3, temp, 0); + + } + } else if (inst.M9.major =3D=3D 6 && inst.M9.x6 =3D=3D 0x3B + && inst.M9.m =3D=3D 0 && inst.M9.x =3D=3D 0) { + /* Floating-point spill*/ + struct ia64_fpreg v; + + inst_type =3D SL_FLOATING; + dir =3D IOREQ_WRITE; + vcpu_get_fpreg(vcpu, inst.M9.f2, &v); + /* Write high word. FIXME: this is a kludge! */ + v.u.bits[1] &=3D 0x3ffff; + mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE); + data =3D v.u.bits[0]; + size =3D 3; + } else if (inst.M10.major =3D=3D 7 && inst.M10.x6 =3D=3D 0x3B) { + /* Floating-point spill + Imm update */ + struct ia64_fpreg v; + + inst_type =3D SL_FLOATING; + dir =3D IOREQ_WRITE; + vcpu_get_fpreg(vcpu, inst.M10.f2, &v); + temp =3D vcpu_get_gr(vcpu, inst.M10.r3); + post_update =3D (inst.M10.i << 7) + inst.M10.imm7; + if (inst.M10.s) + temp -=3D post_update; + else + temp +=3D post_update; + vcpu_set_gr(vcpu, inst.M10.r3, temp, 0); + + /* Write high word.FIXME: this is a kludge! */ + v.u.bits[1] &=3D 0x3ffff; + mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE); + data =3D v.u.bits[0]; + size =3D 3; + } else if (inst.M10.major =3D=3D 7 && inst.M10.x6 =3D=3D 0x31) { + /* Floating-point stf8 + Imm update */ + struct ia64_fpreg v; + inst_type =3D SL_FLOATING; + dir =3D IOREQ_WRITE; + size =3D 3; + vcpu_get_fpreg(vcpu, inst.M10.f2, &v); + data =3D v.u.bits[0]; /* Significand. */ + temp =3D vcpu_get_gr(vcpu, inst.M10.r3); + post_update =3D (inst.M10.i << 7) + inst.M10.imm7; + if (inst.M10.s) + temp -=3D post_update; + else + temp +=3D post_update; + vcpu_set_gr(vcpu, inst.M10.r3, temp, 0); + } else if (inst.M15.major =3D=3D 7 && inst.M15.x6 >=3D 0x2c + && inst.M15.x6 <=3D 0x2f) { + temp =3D vcpu_get_gr(vcpu, inst.M15.r3); + post_update =3D (inst.M15.i << 7) + inst.M15.imm7; + if (inst.M15.s) + temp -=3D post_update; + else + temp +=3D post_update; + vcpu_set_gr(vcpu, inst.M15.r3, temp, 0); + + vcpu_increment_iip(vcpu); + return; + } else if (inst.M12.major =3D=3D 6 && inst.M12.m =3D=3D 1 + && inst.M12.x =3D=3D 1 && inst.M12.x6 =3D=3D 1) { + /* Floating-point Load Pair + Imm ldfp8 M12*/ + struct ia64_fpreg v; + + inst_type =3D SL_FLOATING; + dir =3D IOREQ_READ; + size =3D 8; /*ldfd*/ + mmio_access(vcpu, padr, &data, size, ma, dir); + v.u.bits[0] =3D data; + v.u.bits[1] =3D 0x1003E; + vcpu_set_fpreg(vcpu, inst.M12.f1, &v); + padr +=3D 8; + mmio_access(vcpu, padr, &data, size, ma, dir); + v.u.bits[0] =3D data; + v.u.bits[1] =3D 0x1003E; + vcpu_set_fpreg(vcpu, inst.M12.f2, &v); + padr +=3D 8; + vcpu_set_gr(vcpu, inst.M12.r3, padr, 0); + vcpu_increment_iip(vcpu); + return; + } else { + inst_type =3D -1; + panic_vm(vcpu); + } + + size =3D 1 << size; + if (dir =3D=3D IOREQ_WRITE) { + mmio_access(vcpu, padr, &data, size, ma, dir); + } else { + mmio_access(vcpu, padr, &data, size, ma, dir); + if (inst_type =3D=3D SL_INTEGER) { + vcpu_set_gr(vcpu, inst.M1.r1, data, 0); + } else { + panic_vm(vcpu); + } + } + vcpu_increment_iip(vcpu); +} --=20 1.5.1 |
From: Zhang, X. <xia...@in...> - 2008-01-31 10:29:55
|
From: Xiantao Zhang <xia...@in...> Date: Thu, 31 Jan 2008 15:38:36 +0800 Subject: [PATCH] kvm/ia64: Add header files for kvm/ia64. Three header files are added: asm-ia64/kvm.h asm-ia64/kvm_host.h asm-ia64/kvm_para.h Signed-off-by: Xiantao Zhang <xia...@in...> --- include/asm-ia64/kvm.h | 69 +++++ include/asm-ia64/kvm_host.h | 610 +++++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/kvm_para.h | 29 ++ 3 files changed, 708 insertions(+), 0 deletions(-) create mode 100644 include/asm-ia64/kvm.h create mode 100644 include/asm-ia64/kvm_host.h create mode 100644 include/asm-ia64/kvm_para.h diff --git a/include/asm-ia64/kvm.h b/include/asm-ia64/kvm.h new file mode 100644 index 0000000..1822335 --- /dev/null +++ b/include/asm-ia64/kvm.h @@ -0,0 +1,69 @@ +#ifndef __ASM_KVM_IA64_H +#define __ASM_KVM_IA64_H + +/* + * asm-ia64/kvm.h: kvm structure definitions for ia64 + * + * Copyright (C) 2007 Zhang Xiantao <xia...@in...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 <linux/ioctl.h> + +/* Architectural interrupt line count. */ +#define KVM_NR_INTERRUPTS 256 + +#define KVM_IOAPIC_NUM_PINS 24 + +struct kvm_ioapic_state { + __u64 base_address; + __u32 ioregsel; + __u32 id; + __u32 irr; + __u32 pad; + union { + __u64 bits; + struct { + __u8 vector; + __u8 delivery_mode:3; + __u8 dest_mode:1; + __u8 delivery_status:1; + __u8 polarity:1; + __u8 remote_irr:1; + __u8 trig_mode:1; + __u8 mask:1; + __u8 reserve:7; + __u8 reserved[4]; + __u8 dest_id; + } fields; + } redirtbl[KVM_IOAPIC_NUM_PINS]; +}; + +#define KVM_IRQCHIP_PIC_MASTER 0 +#define KVM_IRQCHIP_PIC_SLAVE 1 +#define KVM_IRQCHIP_IOAPIC 2 + +struct kvm_regs { +}; + +struct kvm_sregs { +}; + +struct kvm_fpu { +}; + +#endif diff --git a/include/asm-ia64/kvm_host.h b/include/asm-ia64/kvm_host.h new file mode 100644 index 0000000..200a870 --- /dev/null +++ b/include/asm-ia64/kvm_host.h @@ -0,0 +1,610 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */ +/* + * ia64.h: used for kvm module, and hold ia64-specific sections. + * + * Copyright (C) 2007, Intel Corporation. + * + * Zhang Xiantao <xia...@in...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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_KVM_HOST_H +#define __ASM_KVM_HOST_H + + +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/kvm.h> +#include <linux/kvm_para.h> +#include <linux/kvm_types.h> + +#include <asm/pal.h> +#include <asm/sal.h> +#include <asm/fpu.h> + +/* define exit reasons from vmm to kvm*/ +#define EXIT_REASON_VM_PANIC 0 +#define EXIT_REASON_MMIO_INSTRUCTION 1 +#define EXIT_REASON_PAL_CALL 2 +#define EXIT_REASON_SAL_CALL 3 +#define EXIT_REASON_SWITCH_RR6 4 +#define EXIT_REASON_VM_DESTROY 5 +#define EXIT_REASON_EXTERNAL_INTERRUPT 6 +#define EXIT_REASON_IPI 7 +#define EXIT_REASON_PTC_G 8 + +/*Define vmm address space and vm data space.*/ +#define KVM_VMM_SIZE (16UL<<20) +#define KVM_VMM_SHIFT 24 +#define KVM_VMM_BASE 0xD000000000000000UL +#define VMM_SIZE (8UL<<20) + +/* + * Define vm_buffer, used by PAL Services, base address. + * Note: vmbuffer is in the VMM-BLOCK, the size must be < 8M + */ +#define KVM_VM_BUFFER_BASE (KVM_VMM_BASE + VMM_SIZE) +#define KVM_VM_BUFFER_SIZE (8UL<<20) + +/*Define Virtual machine data layout.*/ +#define KVM_VM_DATA_SHIFT 24 +#define KVM_VM_DATA_SIZE (1UL << KVM_VM_DATA_SHIFT) +#define KVM_VM_DATA_BASE (KVM_VMM_BASE + KVM_VMM_SIZE) + + +#define KVM_P2M_BASE KVM_VM_DATA_BASE +#define KVM_P2M_OFS 0 +#define KVM_P2M_SIZE (8UL << 20) + +#define KVM_VHPT_BASE (KVM_P2M_BASE + KVM_P2M_SIZE) +#define KVM_VHPT_OFS KVM_P2M_SIZE +#define KVM_VHPT_BLOCK_SIZE (2UL << 20) +#define VHPT_SHIFT 18 +#define VHPT_SIZE (1UL << VHPT_SHIFT) +#define VHPT_NUM_ENTRIES (1<<(VHPT_SHIFT-5)) + +#define KVM_VTLB_BASE (KVM_VHPT_BASE+KVM_VHPT_BLOCK_SIZE) +#define KVM_VTLB_OFS (KVM_VHPT_OFS+KVM_VHPT_BLOCK_SIZE) +#define KVM_VTLB_BLOCK_SIZE (1UL<<20) +#define VTLB_SHIFT 17 +#define VTLB_SIZE (1UL<<VTLB_SHIFT) +#define VTLB_NUM_ENTRIES (1<<(VTLB_SHIFT-5)) + +#define KVM_VPD_BASE (KVM_VTLB_BASE+KVM_VTLB_BLOCK_SIZE) +#define KVM_VPD_OFS (KVM_VTLB_OFS+KVM_VTLB_BLOCK_SIZE) +#define KVM_VPD_BLOCK_SIZE (2UL<<20) +#define VPD_SHIFT 16 +#define VPD_SIZE (1UL<<VPD_SHIFT) + +#define KVM_VCPU_BASE (KVM_VPD_BASE+KVM_VPD_BLOCK_SIZE) +#define KVM_VCPU_OFS (KVM_VPD_OFS+KVM_VPD_BLOCK_SIZE) +#define KVM_VCPU_BLOCK_SIZE (2UL<<20) +#define VCPU_SHIFT 18 +#define VCPU_SIZE (1UL<<VCPU_SHIFT) +#define MAX_VCPU_NUM KVM_VCPU_BLOCK_SIZE/VCPU_SIZE + +#define KVM_VM_BASE (KVM_VCPU_BASE+KVM_VCPU_BLOCK_SIZE) +#define KVM_VM_OFS (KVM_VCPU_OFS+KVM_VCPU_BLOCK_SIZE) +#define KVM_VM_BLOCK_SIZE (1UL<<20) + +/* Get vpd, vhpt, tlb, vcpu, base*/ +#define VPD_ADDR(n) (KVM_VPD_BASE+n*VPD_SIZE) +#define VHPT_ADDR(n) (KVM_VHPT_BASE+n*VHPT_SIZE) +#define VTLB_ADDR(n) (KVM_VTLB_BASE+n*VTLB_SIZE) +#define VCPU_ADDR(n) (KVM_VCPU_BASE+n*VCPU_SIZE) + +/*IO section definitions*/ +#define IOREQ_READ 1 +#define IOREQ_WRITE 0 + +#define STATE_IOREQ_NONE 0 +#define STATE_IOREQ_READY 1 +#define STATE_IOREQ_INPROCESS 2 +#define STATE_IORESP_READY 3 + +/*Guest Physical address layout.*/ +#define GPFN_MEM (0UL << 60) /* Guest pfn is normal mem */ +#define GPFN_FRAME_BUFFER (1UL << 60) /* VGA framebuffer */ +#define GPFN_LOW_MMIO (2UL << 60) /* Low MMIO range */ +#define GPFN_PIB (3UL << 60) /* PIB base */ +#define GPFN_IOSAPIC (4UL << 60) /* IOSAPIC base */ +#define GPFN_LEGACY_IO (5UL << 60) /* Legacy I/O base */ +#define GPFN_GFW (6UL << 60) /* Guest Firmware */ +#define GPFN_HIGH_MMIO (7UL << 60) /* High MMIO range */ + +#define GPFN_IO_MASK (7UL << 60) /* Guest pfn is I/O type */ +#define GPFN_INV_MASK (1UL << 63) /* Guest pfn is invalid */ +#define INVALID_MFN (~0UL) +#define MEM_G (1UL << 30) +#define MEM_M (1UL << 20) +#define MMIO_START (3 * MEM_G) +#define MMIO_SIZE (512 * MEM_M) +#define VGA_IO_START 0xA0000UL +#define VGA_IO_SIZE 0x20000 +#define LEGACY_IO_START (MMIO_START + MMIO_SIZE) +#define LEGACY_IO_SIZE (64*MEM_M) +#define IO_SAPIC_START 0xfec00000UL +#define IO_SAPIC_SIZE 0x100000 +#define PIB_START 0xfee00000UL +#define PIB_SIZE 0x200000 +#define GFW_START (4*MEM_G-16*MEM_M) +#define GFW_SIZE (16*MEM_M) + +/*Deliver mode, defined for ioapic.c*/ +#define dest_Fixed IOSAPIC_FIXED +#define dest_LowestPrio IOSAPIC_LOWEST_PRIORITY + +#define NMI_VECTOR 2 +#define ExtINT_VECTOR 0 +#define NULL_VECTOR -1 +#define IA64_SPURIOUS_INT_VECTOR 0x0f + +#define VCPU_LID(v) (((u64)(v)->vcpu_id)<<24) + +/* + *Delivery mode + */ +#define SAPIC_DELIV_SHIFT 8 +#define SAPIC_FIXED 0x0 +#define SAPIC_LOWEST_PRIORITY 0x1 +#define SAPIC_PMI 0x2 +#define SAPIC_NMI 0x4 +#define SAPIC_INIT 0x5 +#define SAPIC_EXTINT 0x7 + +/* + * vcpu->requests bit members for arch + */ +#define KVM_REQ_PTC_G 32 +#define KVM_REQ_FLUSH_ALL 33 + +struct kvm; +struct kvm_vcpu; + +struct kvm_ioreq { + uint64_t addr; /* physical address */ + uint64_t size; /* size in bytes */ + uint64_t data; /* data (or paddr of data) */ + uint8_t state:4; + uint8_t dir:1; /* 1=3Dread, 0=3Dwrite */ +}; +typedef struct kvm_ioreq ioreq_t; + +/*Pal data struct */ +typedef struct pal_call{ + /*In area*/ + uint64_t gr28; + uint64_t gr29; + uint64_t gr30; + uint64_t gr31; + /*Out area*/ + struct ia64_pal_retval ret; +} pal_call_t; + +/* Sal data structure */ +typedef struct sal_call{ + /*In area*/ + uint64_t in0; + uint64_t in1; + uint64_t in2; + uint64_t in3; + uint64_t in4; + uint64_t in5; + uint64_t in6; + uint64_t in7; + /*Our area*/ + struct sal_ret_values ret; +} sal_call_t; + +/*Guest change rr6*/ +typedef struct switch_rr6 { + uint64_t old_rr; + uint64_t new_rr; +} switch_rr6_t; + +typedef union{ + unsigned long val; + struct { + unsigned long rv : 3; + unsigned long ir : 1; + unsigned long eid : 8; + unsigned long id : 8; + unsigned long ib_base : 44; + }; +} ia64_ipi_a; + +typedef union{ + unsigned long val; + struct { + unsigned long vector : 8; + unsigned long dm : 3; + unsigned long ig : 53; + }; +} ia64_ipi_d; + +/*ipi check exit data*/ +typedef struct ipi_data{ + ia64_ipi_a addr; + ia64_ipi_d data; +} ipi_data_t; + +/*global purge data*/ +typedef struct kvm_ptc_g { + unsigned long vaddr; + unsigned long rr; + unsigned long ps; + struct kvm_vcpu *vcpu; +} ptc_g_t; + +/*Exit control data */ +struct exit_ctl_data{ + uint32_t exit_reason; + uint32_t vm_status; + union { + ioreq_t ioreq; + pal_call_t pal_data; + sal_call_t sal_data; + switch_rr6_t rr_data; + ipi_data_t ipi_data; + ptc_g_t ptc_g_data; + } u; +}; + +union pte_flags { + struct { + unsigned long p : 1; /*0 */ + unsigned long : 1; /* 1 */ + unsigned long ma : 3; /* 2-4 */ + unsigned long a : 1; /* 5 */ + unsigned long d : 1; /* 6 */ + unsigned long pl : 2; /* 7-8 */ + unsigned long ar : 3; /* 9-11 */ + unsigned long ppn : 38; /* 12-49 */ + unsigned long : 2; /* 50-51 */ + unsigned long ed : 1; /* 52 */ + }; + unsigned long val; +}; + + +typedef struct thash_data { + union { + struct { + unsigned long p : 1; /* 0 */ + unsigned long rv1 : 1; /* 1 */ + unsigned long ma : 3; /* 2-4 */ + unsigned long a : 1; /* 5 */ + unsigned long d : 1; /* 6 */ + unsigned long pl : 2; /* 7-8 */ + unsigned long ar : 3; /* 9-11 */ + unsigned long ppn : 38; /* 12-49 */ + unsigned long rv2 : 2; /* 50-51 */ + unsigned long ed : 1; /* 52 */ + unsigned long ig1 : 11; /* 53-63 */ + }; + struct { + unsigned long __rv1 : 53; /* 0-52 */ + unsigned long contiguous : 1; /*53 */ + unsigned long tc : 1; /* 54 TR or TC */ + unsigned long cl : 1; + /* 55 I side or D side cache line */ + unsigned long len : 4; /* 56-59 */ + unsigned long io : 1; /* 60 entry is for io or not */ + unsigned long nomap : 1; + /* 61 entry cann't be inserted into machine TLB.*/ + unsigned long checked : 1; + /* 62 for VTLB/VHPT sanity check */ + unsigned long invalid : 1; + /* 63 invalid entry */ + }; + unsigned long page_flags; + }; /* same for VHPT and TLB */ + + union { + struct { + unsigned long rv3 : 2; + unsigned long ps : 6; + unsigned long key : 24; + unsigned long rv4 : 32; + }; + unsigned long itir; + }; + union { + struct { + unsigned long ig2 : 12; + unsigned long vpn : 49; + unsigned long vrn : 3; + }; + unsigned long ifa; + unsigned long vadr; + struct { + unsigned long tag : 63; + unsigned long ti : 1; + }; + unsigned long etag; + }; + union { + struct thash_data *next; + unsigned long rid; + unsigned long gpaddr; + }; +} thash_data_t; + +typedef union { + unsigned long val; + struct { + unsigned long ve : 1; + unsigned long reserved0 : 1; + unsigned long size : 6; + unsigned long vf : 1; + unsigned long reserved1 : 6; + unsigned long base : 49; + }; +} ia64_pta; + +typedef struct thash_cb { + /* THASH base information */ + thash_data_t *hash; /* hash table pointer, aligned at thash_sz.*/ + ia64_pta pta; + int num; +} thash_cb_t; + +typedef union context { + /* 8K size */ + unsigned long dummy[1024]; + struct { + unsigned long psr; + unsigned long pr; + unsigned long caller_unat; + unsigned long pad; + unsigned long gr[32]; + unsigned long ar[128]; + unsigned long br[8]; + unsigned long cr[128]; + unsigned long rr[8]; + unsigned long ibr[8]; + unsigned long dbr[8]; + unsigned long pkr[8]; + struct ia64_fpreg fr[128]; + }; +} context_t; + +#define NITRS 8 +#define NDTRS 8 + +struct kvm_vcpu_stat { +}; +struct kvm_vcpu_arch { + int launched; + int last_exit; + int last_run_cpu; + +#define VCPU_MP_STATE_RUNNABLE 0 +#define VCPU_MP_STATE_UNINITIALIZED 1 +#define VCPU_MP_STATE_INIT_RECEIVED 2 +#define VCPU_MP_STATE_HALTED 3 + int mp_state; + +#define MAX_PTC_G_NUM 3 + int ptc_g_count; + struct kvm_ptc_g ptc_g_data[MAX_PTC_G_NUM]; + + /*halt timer to wake up sleepy vcpus*/ + struct hrtimer hlt_timer; + long ht_active; + + void *pio_data; + struct kvm_pio_request pio; + struct kvm_lapic *apic; /* kernel irqchip context */ + struct vpd *vpd; + + /* Exit data for vmm_transition*/ + struct exit_ctl_data exit_data; + + cpumask_t cache_coherent_map; + + unsigned long vmm_rr; + unsigned long host_rr6; + unsigned long psbits[8]; + unsigned long cr_iipa; + unsigned long cr_isr; + unsigned long vsa_base; + unsigned long __gp; + /* TR and TC. */ + thash_data_t itrs[NITRS]; + thash_data_t dtrs[NDTRS]; + /* Bit is set if there is a tr/tc for the region. */ + unsigned char itr_regions; + unsigned char dtr_regions; + unsigned char tc_regions; + /* purge all */ + unsigned long ptce_base; + unsigned long ptce_count[2]; + unsigned long ptce_stride[2]; + /* itc/itm */ + unsigned long last_itc; + long itc_offset; + unsigned long itc_check; + unsigned long timer_check; + unsigned long timer_pending; + + + unsigned long vrr[8]; + unsigned long ibr[8]; + unsigned long dbr[8]; + unsigned long insvc[4]; /* Interrupt in service. */ + unsigned long xtp; + + /* These fields are copied from arch_domain to make access + easier/faster in assembly code. */ + unsigned long metaphysical_rr0; /* from kvm_arch (so is pinned) */ + unsigned long metaphysical_rr4; /* from kvm_arch (so is pinned) */ + unsigned long metaphysical_saved_rr0; /* from kvm_arch */ + unsigned long metaphysical_saved_rr4; /* from kvm_arch */ + unsigned long fp_psr; /*used for lazy float register */ + unsigned long saved_gp; + /*for phycial emulation */ + int mode_flags; + thash_cb_t vtlb; + thash_cb_t vhpt; + char irq_check; + char irq_new_pending; + + unsigned long opcode; + unsigned long cause; + context_t host; + context_t guest; + +}; + +struct kvm_vm_stat { + u64 remote_tlb_flush; +}; + +struct kvm_sal_data { + unsigned long boot_ip; + unsigned long boot_gp; +}; + +struct kvm_arch { + unsigned long vm_base; + unsigned long metaphysical_rr0; + unsigned long metaphysical_rr4; + unsigned long vmm_init_rr; + unsigned long vhpt_base; + unsigned long vtlb_base; + unsigned long vpd_base; + struct kvm_ioapic *vioapic; + struct kvm_vm_stat stat; + struct kvm_sal_data rdv_sal_data; +}; + +typedef union { + u64 value; + struct { + u64 number : 8; + u64 revision : 8; + u64 model : 8; + u64 family : 8; + u64 archrev : 8; + u64 rv : 24; + }; +} cpuid3_t; + +struct kvm_pt_regs { + /* The following registers are saved by SAVE_MIN: */ + unsigned long b6; /* scratch */ + unsigned long b7; /* scratch */ + + unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */ + unsigned long ar_ssd; /* reserved for future use (scratch) */ + + unsigned long r8; /* scratch (return value register 0) */ + unsigned long r9; /* scratch (return value register 1) */ + unsigned long r10; /* scratch (return value register 2) */ + unsigned long r11; /* scratch (return value register 3) */ + + unsigned long cr_ipsr; /* interrupted task's psr */ + unsigned long cr_iip; /* interrupted task's instruction pointer */ + unsigned long cr_ifs; /* interrupted task's function state */ + + unsigned long ar_unat; /* interrupted task's NaT register (preserved) */ + unsigned long ar_pfs; /* prev function state */ + unsigned long ar_rsc; /* RSE configuration */ + /* The following two are valid only if cr_ipsr.cpl > 0: */ + unsigned long ar_rnat; /* RSE NaT */ + unsigned long ar_bspstore; /* RSE bspstore */ + + unsigned long pr; /* 64 predicate registers (1 bit each) */ + unsigned long b0; /* return pointer (bp) */ + unsigned long loadrs; /* size of dirty partition << 16 */ + + unsigned long r1; /* the gp pointer */ + unsigned long r12; /* interrupted task's memory stack pointer */ + unsigned long r13; /* thread pointer */ + + unsigned long ar_fpsr; /* floating point status (preserved) */ + unsigned long r15; /* scratch */ + + /* The remaining registers are NOT saved for system calls. */ + + unsigned long r14; /* scratch */ + unsigned long r2; /* scratch */ + unsigned long r3; /* scratch */ + unsigned long r16; /* scratch */ + unsigned long r17; /* scratch */ + unsigned long r18; /* scratch */ + unsigned long r19; /* scratch */ + unsigned long r20; /* scratch */ + unsigned long r21; /* scratch */ + unsigned long r22; /* scratch */ + unsigned long r23; /* scratch */ + unsigned long r24; /* scratch */ + unsigned long r25; /* scratch */ + unsigned long r26; /* scratch */ + unsigned long r27; /* scratch */ + unsigned long r28; /* scratch */ + unsigned long r29; /* scratch */ + unsigned long r30; /* scratch */ + unsigned long r31; /* scratch */ + unsigned long ar_ccv; /* compare/exchange value (scratch) */ + + + /* + * Floating point registers that the kernel considers scratch: + */ + struct ia64_fpreg f6; /* scratch */ + struct ia64_fpreg f7; /* scratch */ + struct ia64_fpreg f8; /* scratch */ + struct ia64_fpreg f9; /* scratch */ + struct ia64_fpreg f10; /* scratch */ + struct ia64_fpreg f11; /* scratch */ + + unsigned long r4; /* preserved */ + unsigned long r5; /* preserved */ + unsigned long r6; /* preserved */ + unsigned long r7; /* preserved */ + unsigned long eml_unat; /* used for emulating instruction */ + unsigned long pad0; /* alignment pad */ + +}; + +static inline struct kvm_pt_regs *vcpu_regs(struct kvm_vcpu *v) +{ + return (struct kvm_pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; +} + +typedef int kvm_vmm_entry(void); +typedef void kvm_tramp_entry(context_t *host, context_t *guest); + +struct kvm_vmm_info{ + struct module *module; + kvm_vmm_entry *vmm_entry; + kvm_tramp_entry *tramp_entry; + unsigned long vmm_ivt; +}; + +int kvm_highest_pending_irq(struct kvm_vcpu *vcpu); +int kvm_emulate_halt(struct kvm_vcpu *vcpu); +int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); +void kvm_sal_emul(struct kvm_vcpu *vcpu); + +/*Currently, this macro is not used by kvm/ia64, Once necessary, + it should be implemented later!!*/ +#define smp_call_function_mask(cpus_mask, func, info, wait)\ + smp_call_function(func, info, 0, wait) + +#endif diff --git a/include/asm-ia64/kvm_para.h b/include/asm-ia64/kvm_para.h new file mode 100644 index 0000000..90d5658 --- /dev/null +++ b/include/asm-ia64/kvm_para.h @@ -0,0 +1,29 @@ +#ifndef __IA64_KVM_PARA_H +#define __IA64_KVM_PARA_H + +/* + * asm-ia64/kvm_para.h + * + * Copyright (C) 2007 Zhang Xiantao <xia...@in...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ + +static inline unsigned int kvm_arch_para_features(void) +{ + return 0; +} + +#endif --=20 1.5.1 |