# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1183663482 21600
# Node ID 5927f10462cd4ed7c71671aebc075a750ff77604
# Parent a8aeffcc06aa6b6553d4039f3834fed1f45d1494
[IA64] Renames vmx_process.c into vmx_fault.c
Signed-off-by: Tristan Gingold <tgingold@xxxxxxx>
---
xen/arch/ia64/vmx/vmx_process.c | 528 ----------------------------------------
xen/arch/ia64/vmx/Makefile | 2
xen/arch/ia64/vmx/vmx_fault.c | 528 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 529 insertions(+), 529 deletions(-)
diff -r a8aeffcc06aa -r 5927f10462cd xen/arch/ia64/vmx/Makefile
--- a/xen/arch/ia64/vmx/Makefile Thu Jul 05 13:17:30 2007 -0600
+++ b/xen/arch/ia64/vmx/Makefile Thu Jul 05 13:24:42 2007 -0600
@@ -10,7 +10,7 @@ obj-y += vmx_interrupt.o
obj-y += vmx_interrupt.o
obj-y += vmx_ivt.o
obj-y += vmx_phy_mode.o
-obj-y += vmx_process.o
+obj-y += vmx_fault.o
obj-y += vmx_support.o
obj-y += vmx_utility.o
obj-y += vmx_vcpu.o
diff -r a8aeffcc06aa -r 5927f10462cd xen/arch/ia64/vmx/vmx_fault.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/vmx/vmx_fault.c Thu Jul 05 13:24:42 2007 -0600
@@ -0,0 +1,528 @@
+/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
+/*
+ * vmx_process.c: handling VMX architecture-related VM exits
+ * 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.
+ *
+ * Xiaoyan Feng (Fleming Feng) <fleming.feng@xxxxxxxxx>
+ * Xuefei Xu (Anthony Xu) (Anthony.xu@xxxxxxxxx)
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+#include <xen/smp.h>
+#include <asm/ptrace.h>
+#include <xen/delay.h>
+
+#include <linux/efi.h> /* FOR EFI_UNIMPLEMENTED */
+#include <asm/sal.h> /* FOR struct ia64_sal_retval */
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/desc.h>
+#include <asm/vlsapic.h>
+#include <xen/irq.h>
+#include <xen/event.h>
+#include <asm/regionreg.h>
+#include <asm/privop.h>
+#include <asm/ia64_int.h>
+#include <asm/debugger.h>
+//#include <asm/hpsim_ssc.h>
+#include <asm/dom_fw.h>
+#include <asm/vmx_vcpu.h>
+#include <asm/kregs.h>
+#include <asm/vmx.h>
+#include <asm/vmmu.h>
+#include <asm/vmx_mm_def.h>
+#include <asm/vmx_phy_mode.h>
+#include <xen/mm.h>
+#include <asm/vmx_pal.h>
+/* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */
+#define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
+
+
+extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
+extern void rnat_consumption (VCPU *vcpu);
+extern void alt_itlb (VCPU *vcpu, u64 vadr);
+extern void itlb_fault (VCPU *vcpu, u64 vadr);
+extern void ivhpt_fault (VCPU *vcpu, u64 vadr);
+extern unsigned long handle_fpu_swa (int fp_fault, struct pt_regs *regs,
unsigned long isr);
+
+#define DOMN_PAL_REQUEST 0x110000
+#define DOMN_SAL_REQUEST 0x110001
+
+static u64 vec2off[68] = {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
+};
+
+
+
+void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim,
+ u64 vec, REGS *regs)
+{
+ u64 status, vector;
+ VCPU *vcpu = current;
+ u64 vpsr = VCPU(vcpu, vpsr);
+
+ vector = vec2off[vec];
+
+ switch (vec) {
+ case 5: // IA64_DATA_NESTED_TLB_VECTOR
+ break;
+ case 22: // IA64_INST_ACCESS_RIGHTS_VECTOR
+ if (!(vpsr & IA64_PSR_IC))
+ goto nested_fault;
+ if (vhpt_access_rights_fixup(vcpu, ifa, 0))
+ return;
+ break;
+
+ case 25: // IA64_DISABLED_FPREG_VECTOR
+ if (!(vpsr & IA64_PSR_IC))
+ goto nested_fault;
+ if (FP_PSR(vcpu) & IA64_PSR_DFH) {
+ FP_PSR(vcpu) = IA64_PSR_MFH;
+ if (__ia64_per_cpu_var(fp_owner) != vcpu)
+ __ia64_load_fpu(vcpu->arch._thread.fph);
+ }
+ if (!(VCPU(vcpu, vpsr) & IA64_PSR_DFH)) {
+ regs->cr_ipsr &= ~IA64_PSR_DFH;
+ return;
+ }
+
+ break;
+
+ case 32: // IA64_FP_FAULT_VECTOR
+ if (!(vpsr & IA64_PSR_IC))
+ goto nested_fault;
+ // handle fpswa emulation
+ // fp fault
+ status = handle_fpu_swa(1, regs, isr);
+ if (!status) {
+ vcpu_increment_iip(vcpu);
+ return;
+ } else if (IA64_RETRY == status)
+ return;
+ break;
+
+ case 33: // IA64_FP_TRAP_VECTOR
+ if (!(vpsr & IA64_PSR_IC))
+ goto nested_fault;
+ //fp trap
+ status = handle_fpu_swa(0, regs, isr);
+ if (!status)
+ return;
+ else if (IA64_RETRY == status) {
+ vcpu_decrement_iip(vcpu);
+ return;
+ }
+ break;
+
+ case 29: // IA64_DEBUG_VECTOR
+ case 35: // IA64_TAKEN_BRANCH_TRAP_VECTOR
+ case 36: // IA64_SINGLE_STEP_TRAP_VECTOR
+ if (vmx_guest_kernel_mode(regs)
+ && current->domain->debugger_attached) {
+ domain_pause_for_debugger();
+ return;
+ }
+ if (!(vpsr & IA64_PSR_IC))
+ goto nested_fault;
+ break;
+
+ default:
+ if (!(vpsr & IA64_PSR_IC))
+ goto nested_fault;
+ break;
+ }
+ VCPU(vcpu,isr)=isr;
+ VCPU(vcpu,iipa) = regs->cr_iip;
+ if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
+ VCPU(vcpu,iim) = iim;
+ else {
+ set_ifa_itir_iha(vcpu,ifa,1,1,1);
+ }
+ inject_guest_interruption(vcpu, vector);
+ return;
+
+ nested_fault:
+ panic_domain(regs, "Guest nested fault vector=%lx!\n", vector);
+}
+
+
+IA64FAULT
+vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long
isr, unsigned long iim)
+{
+ struct domain *d = current->domain;
+ struct vcpu *v = current;
+
+ perfc_incr(vmx_ia64_handle_break);
+#ifdef CRASH_DEBUG
+ if ((iim == 0 || iim == CDB_BREAK_NUM) && !guest_mode(regs) &&
+ IS_VMM_ADDRESS(regs->cr_iip)) {
+ if (iim == 0)
+ show_registers(regs);
+ debugger_trap_fatal(0 /* don't care */, regs);
+ } else
+#endif
+ {
+ if (iim == 0)
+ vmx_die_if_kernel("Break 0 in Hypervisor.", regs, iim);
+
+ if (ia64_psr(regs)->cpl == 0) {
+ /* Allow hypercalls only when cpl = 0. */
+ if (iim == d->arch.breakimm) {
+ ia64_hypercall(regs);
+ vcpu_increment_iip(v);
+ return IA64_NO_FAULT;
+ }
+ else if(iim == DOMN_PAL_REQUEST){
+ pal_emul(v);
+ vcpu_increment_iip(v);
+ return IA64_NO_FAULT;
+ }else if(iim == DOMN_SAL_REQUEST){
+ sal_emul(v);
+ vcpu_increment_iip(v);
+ return IA64_NO_FAULT;
+ }
+ }
+ vmx_reflect_interruption(ifa,isr,iim,11,regs);
+ }
+ return IA64_NO_FAULT;
+}
+
+
+void save_banked_regs_to_vpd(VCPU *v, REGS *regs)
+{
+ unsigned long i=0UL, * src,* dst, *sunat, *dunat;
+ IA64_PSR vpsr;
+ src=®s->r16;
+ sunat=®s->eml_unat;
+ vpsr.val = VCPU(v, vpsr);
+ if(vpsr.bn){
+ dst = &VCPU(v, vgr[0]);
+ dunat =&VCPU(v, vnat);
+ __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;; \
+ dep %2 = %0, %2, 0, 16;; \
+ st8 [%3] = %2;;"
+
::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
+
+ }else{
+ dst = &VCPU(v, vbgr[0]);
+// dunat =&VCPU(v, vbnat);
+// __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;;
+// dep %2 = %0, %2, 16, 16;;
+// st8 [%3] = %2;;"
+//
::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
+
+ }
+ for(i=0; i<16; i++)
+ *dst++ = *src++;
+}
+
+
+// ONLY gets called from ia64_leave_kernel
+// ONLY call with interrupts disabled?? (else might miss one?)
+// NEVER successful if already reflecting a trap/fault because psr.i==0
+void leave_hypervisor_tail(void)
+{
+ struct domain *d = current->domain;
+ struct vcpu *v = current;
+
+ // FIXME: Will this work properly if doing an RFI???
+ if (!is_idle_domain(d) ) { // always comes from guest
+// struct pt_regs *user_regs = vcpu_regs(current);
+ local_irq_enable();
+ do_softirq();
+ local_irq_disable();
+
+ if (v->vcpu_id == 0) {
+ unsigned long callback_irq =
+ d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
+
+ if ( v->arch.arch_vmx.pal_init_pending ) {
+ /*inject INIT interruption to guest pal*/
+ v->arch.arch_vmx.pal_init_pending = 0;
+ deliver_pal_init(v);
+ return;
+ }
+
+ /*
+ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line:
+ * Domain = val[47:32], Bus = val[31:16],
+ * DevFn = val[15: 8], IntX = val[ 1: 0]
+ * val[63:56] == 0: val[55:0] is a delivery as GSI
+ */
+ if (callback_irq != 0 && local_events_need_delivery()) {
+ /* change level for para-device callback irq */
+ /* use level irq to send discrete event */
+ if ((uint8_t)(callback_irq >> 56) == 1) {
+ /* case of using PCI INTx line as callback irq */
+ int pdev = (callback_irq >> 11) & 0x1f;
+ int pintx = callback_irq & 3;
+ viosapic_set_pci_irq(d, pdev, pintx, 1);
+ viosapic_set_pci_irq(d, pdev, pintx, 0);
+ } else {
+ /* case of using GSI as callback irq */
+ viosapic_set_irq(d, callback_irq, 1);
+ viosapic_set_irq(d, callback_irq, 0);
+ }
+ }
+ }
+
+ rmb();
+ if (xchg(&v->arch.irq_new_pending, 0)) {
+ v->arch.irq_new_condition = 0;
+ vmx_check_pending_irq(v);
+ return;
+ }
+
+ if (v->arch.irq_new_condition) {
+ v->arch.irq_new_condition = 0;
+ vhpi_detection(v);
+ }
+ }
+}
+
+extern ia64_rr vmx_vcpu_rr(VCPU *vcpu, u64 vadr);
+
+static int vmx_handle_lds(REGS* regs)
+{
+ regs->cr_ipsr |=IA64_PSR_ED;
+ return IA64_FAULT;
+}
+
+/* We came here because the H/W VHPT walker failed to find an entry */
+IA64FAULT
+vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
+{
+ IA64_PSR vpsr;
+ int type;
+ u64 vhpt_adr, gppa, pteval, rr, itir;
+ ISR misr;
+ PTA vpta;
+ thash_data_t *data;
+ VCPU *v = current;
+
+ vpsr.val = VCPU(v, vpsr);
+ misr.val = VMX(v,cr_isr);
+
+ if (vec == 1)
+ type = ISIDE_TLB;
+ else if (vec == 2)
+ type = DSIDE_TLB;
+ else
+ panic_domain(regs, "wrong vec:%lx\n", vec);
+
+ if(is_physical_mode(v)&&(!(vadr<<1>>62))){
+ if(vec==2){
+ if (misr.sp) /* Refer to SDM Vol2 Table 4-11,4-12 */
+ return vmx_handle_lds(regs);
+ if (v->domain != dom0
+ && __gpfn_is_io(v->domain, (vadr << 1) >> (PAGE_SHIFT + 1))) {
+ emulate_io_inst(v,((vadr<<1)>>1),4); // UC
+ return IA64_FAULT;
+ }
+ }
+ physical_tlb_miss(v, vadr, type);
+ return IA64_FAULT;
+ }
+
+try_again:
+ if((data=vtlb_lookup(v, vadr,type))!=0){
+ if (v->domain != dom0 && type == DSIDE_TLB) {
+ if (misr.sp) { /* Refer to SDM Vol2 Table 4-10,4-12 */
+ if ((data->ma == VA_MATTR_UC) || (data->ma == VA_MATTR_UCE))
+ return vmx_handle_lds(regs);
+ }
+ gppa = (vadr & ((1UL << data->ps) - 1)) +
+ (data->ppn >> (data->ps - 12) << data->ps);
+ if (__gpfn_is_io(v->domain, gppa >> PAGE_SHIFT)) {
+ if (misr.sp)
+ panic_domain(NULL, "ld.s on I/O page not with UC attr."
+ " pte=0x%lx\n", data->page_flags);
+ if (data->pl >= ((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 IA64_FAULT;
+ }
+ }
+ thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type);
+
+ }else if(type == DSIDE_TLB){
+
+ if (misr.sp)
+ return vmx_handle_lds(regs);
+
+ vcpu_get_rr(v, vadr, &rr);
+ itir = rr & (RR_RID_MASK | RR_PS_MASK);
+
+ if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
+ if (GOS_WINDOWS(v)) {
+ /* windows use region 4 and 5 for identity mapping */
+ if (REGION_NUMBER(vadr) == 4 && !(regs->cr_ipsr & IA64_PSR_CPL)
+ && (REGION_OFFSET(vadr)<= _PAGE_PPN_MASK)) {
+
+ pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
+ (_PAGE_P | _PAGE_A | _PAGE_D |
+ _PAGE_MA_WB | _PAGE_AR_RW);
+
+ if (thash_purge_and_insert(v, pteval, itir, vadr, type))
+ goto try_again;
+
+ return IA64_NO_FAULT;
+ }
+
+ if (REGION_NUMBER(vadr) == 5 && !(regs->cr_ipsr & IA64_PSR_CPL)
+ && (REGION_OFFSET(vadr)<= _PAGE_PPN_MASK)) {
+
+ pteval = PAGEALIGN(REGION_OFFSET(vadr),itir_ps(itir)) |
+ (_PAGE_P | _PAGE_A | _PAGE_D |
+ _PAGE_MA_UC | _PAGE_AR_RW);
+
+ if (thash_purge_and_insert(v, pteval, itir, vadr, type))
+ goto try_again;
+
+ return IA64_NO_FAULT;
+ }
+ }
+
+ if(vpsr.ic){
+ vcpu_set_isr(v, misr.val);
+ alt_dtlb(v, vadr);
+ return IA64_FAULT;
+ } else{
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ }
+
+ vpta.val = vmx_vcpu_get_pta(v);
+ if (vpta.vf) {
+ /* Long format is not yet supported. */
+ if (vpsr.ic) {
+ vcpu_set_isr(v, misr.val);
+ dtlb_fault(v, vadr);
+ return IA64_FAULT;
+ } else {
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ }
+
+ /* avoid recursively walking (short format) VHPT */
+ if (!GOS_WINDOWS(v) &&
+ (((vadr ^ vpta.val) << 3) >> (vpta.size + 3)) == 0) {
+
+ if (vpsr.ic) {
+ vcpu_set_isr(v, misr.val);
+ dtlb_fault(v, vadr);
+ return IA64_FAULT;
+ } else {
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ }
+
+ vhpt_adr = vmx_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);
+ return IA64_FAULT;
+ } else {
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ } else if ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST) {
+ thash_purge_and_insert(v, pteval, itir, vadr, DSIDE_TLB);
+ return IA64_NO_FAULT;
+ } else if (vpsr.ic) {
+ vcpu_set_isr(v, misr.val);
+ dtlb_fault(v, vadr);
+ return IA64_FAULT;
+ }else{
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ } else {
+ /* Can't read VHPT. */
+ if (vpsr.ic) {
+ vcpu_set_isr(v, misr.val);
+ dvhpt_fault(v, vadr);
+ return IA64_FAULT;
+ } else {
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ }
+ }else if(type == ISIDE_TLB){
+
+ if (!vpsr.ic)
+ misr.ni = 1;
+ if (!vhpt_enabled(v, vadr, INST_REF)) {
+ vcpu_set_isr(v, misr.val);
+ alt_itlb(v, vadr);
+ return IA64_FAULT;
+ }
+
+ vpta.val = vmx_vcpu_get_pta(v);
+ if (vpta.vf) {
+ /* Long format is not yet supported. */
+ vcpu_set_isr(v, misr.val);
+ itlb_fault(v, vadr);
+ return IA64_FAULT;
+ }
+
+
+ vhpt_adr = vmx_vcpu_thash(v, vadr);
+ if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
+ /* VHPT successfully read. */
+ if (pteval & _PAGE_P) {
+ if ((pteval & _PAGE_MA_MASK) == _PAGE_MA_ST) {
+ vcpu_set_isr(v, misr.val);
+ itlb_fault(v, vadr);
+ return IA64_FAULT;
+ }
+ vcpu_get_rr(v, vadr, &rr);
+ itir = rr & (RR_RID_MASK | RR_PS_MASK);
+ thash_purge_and_insert(v, pteval, itir, vadr, ISIDE_TLB);
+ return IA64_NO_FAULT;
+ } else {
+ vcpu_set_isr(v, misr.val);
+ inst_page_not_present(v, vadr);
+ return IA64_FAULT;
+ }
+ } else {
+ vcpu_set_isr(v, misr.val);
+ ivhpt_fault(v, vadr);
+ return IA64_FAULT;
+ }
+ }
+ return IA64_NO_FAULT;
+}
diff -r a8aeffcc06aa -r 5927f10462cd xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c Thu Jul 05 13:17:30 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,528 +0,0 @@
-/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
-/*
- * vmx_process.c: handling VMX architecture-related VM exits
- * 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.
- *
- * Xiaoyan Feng (Fleming Feng) <fleming.feng@xxxxxxxxx>
- * Xuefei Xu (Anthony Xu) (Anthony.xu@xxxxxxxxx)
- */
-
-#include <xen/config.h>
-#include <xen/lib.h>
-#include <xen/errno.h>
-#include <xen/sched.h>
-#include <xen/smp.h>
-#include <asm/ptrace.h>
-#include <xen/delay.h>
-
-#include <linux/efi.h> /* FOR EFI_UNIMPLEMENTED */
-#include <asm/sal.h> /* FOR struct ia64_sal_retval */
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/desc.h>
-#include <asm/vlsapic.h>
-#include <xen/irq.h>
-#include <xen/event.h>
-#include <asm/regionreg.h>
-#include <asm/privop.h>
-#include <asm/ia64_int.h>
-#include <asm/debugger.h>
-//#include <asm/hpsim_ssc.h>
-#include <asm/dom_fw.h>
-#include <asm/vmx_vcpu.h>
-#include <asm/kregs.h>
-#include <asm/vmx.h>
-#include <asm/vmmu.h>
-#include <asm/vmx_mm_def.h>
-#include <asm/vmx_phy_mode.h>
-#include <xen/mm.h>
-#include <asm/vmx_pal.h>
-/* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */
-#define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
-
-
-extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
-extern void rnat_consumption (VCPU *vcpu);
-extern void alt_itlb (VCPU *vcpu, u64 vadr);
-extern void itlb_fault (VCPU *vcpu, u64 vadr);
-extern void ivhpt_fault (VCPU *vcpu, u64 vadr);
-extern unsigned long handle_fpu_swa (int fp_fault, struct pt_regs *regs,
unsigned long isr);
-
-#define DOMN_PAL_REQUEST 0x110000
-#define DOMN_SAL_REQUEST 0x110001
-
-static u64 vec2off[68] = {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
-};
-
-
-
-void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim,
- u64 vec, REGS *regs)
-{
- u64 status, vector;
- VCPU *vcpu = current;
- u64 vpsr = VCPU(vcpu, vpsr);
-
- vector = vec2off[vec];
-
- switch (vec) {
- case 5: // IA64_DATA_NESTED_TLB_VECTOR
- break;
- case 22: // IA64_INST_ACCESS_RIGHTS_VECTOR
- if (!(vpsr & IA64_PSR_IC))
- goto nested_fault;
- if (vhpt_access_rights_fixup(vcpu, ifa, 0))
- return;
- break;
-
- case 25: // IA64_DISABLED_FPREG_VECTOR
- if (!(vpsr & IA64_PSR_IC))
- goto nested_fault;
- if (FP_PSR(vcpu) & IA64_PSR_DFH) {
- FP_PSR(vcpu) = IA64_PSR_MFH;
- if (__ia64_per_cpu_var(fp_owner) != vcpu)
- __ia64_load_fpu(vcpu->arch._thread.fph);
- }
- if (!(VCPU(vcpu, vpsr) & IA64_PSR_DFH)) {
- regs->cr_ipsr &= ~IA64_PSR_DFH;
- return;
- }
-
- break;
-
- case 32: // IA64_FP_FAULT_VECTOR
- if (!(vpsr & IA64_PSR_IC))
- goto nested_fault;
- // handle fpswa emulation
- // fp fault
- status = handle_fpu_swa(1, regs, isr);
- if (!status) {
- vcpu_increment_iip(vcpu);
- return;
- } else if (IA64_RETRY == status)
- return;
- break;
-
- case 33: // IA64_FP_TRAP_VECTOR
- if (!(vpsr & IA64_PSR_IC))
- goto nested_fault;
- //fp trap
- status = handle_fpu_swa(0, regs, isr);
- if (!status)
- return;
- else if (IA64_RETRY == status) {
- vcpu_decrement_iip(vcpu);
- return;
- }
- break;
-
- case 29: // IA64_DEBUG_VECTOR
- case 35: // IA64_TAKEN_BRANCH_TRAP_VECTOR
- case 36: // IA64_SINGLE_STEP_TRAP_VECTOR
- if (vmx_guest_kernel_mode(regs)
- && current->domain->debugger_attached) {
- domain_pause_for_debugger();
- return;
- }
- if (!(vpsr & IA64_PSR_IC))
- goto nested_fault;
- break;
-
- default:
- if (!(vpsr & IA64_PSR_IC))
- goto nested_fault;
- break;
- }
- VCPU(vcpu,isr)=isr;
- VCPU(vcpu,iipa) = regs->cr_iip;
- if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
- VCPU(vcpu,iim) = iim;
- else {
- set_ifa_itir_iha(vcpu,ifa,1,1,1);
- }
- inject_guest_interruption(vcpu, vector);
- return;
-
- nested_fault:
- panic_domain(regs, "Guest nested fault vector=%lx!\n", vector);
-}
-
-
-IA64FAULT
-vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long
isr, unsigned long iim)
-{
- struct domain *d = current->domain;
- struct vcpu *v = current;
-
- perfc_incr(vmx_ia64_handle_break);
-#ifdef CRASH_DEBUG
- if ((iim == 0 || iim == CDB_BREAK_NUM) && !guest_mode(regs) &&
- IS_VMM_ADDRESS(regs->cr_iip)) {
- if (iim == 0)
- show_registers(regs);
- debugger_trap_fatal(0 /* don't care */, regs);
- } else
-#endif
- {
- if (iim == 0)
- vmx_die_if_kernel("Break 0 in Hypervisor.", regs, iim);
-
- if (ia64_psr(regs)->cpl == 0) {
- /* Allow hypercalls only when cpl = 0. */
- if (iim == d->arch.breakimm) {
- ia64_hypercall(regs);
- vcpu_increment_iip(v);
- return IA64_NO_FAULT;
- }
- else if(iim == DOMN_PAL_REQUEST){
- pal_emul(v);
- vcpu_increment_iip(v);
- return IA64_NO_FAULT;
- }else if(iim == DOMN_SAL_REQUEST){
- sal_emul(v);
- vcpu_increment_iip(v);
- return IA64_NO_FAULT;
- }
- }
- vmx_reflect_interruption(ifa,isr,iim,11,regs);
- }
- return IA64_NO_FAULT;
-}
-
-
-void save_banked_regs_to_vpd(VCPU *v, REGS *regs)
-{
- unsigned long i=0UL, * src,* dst, *sunat, *dunat;
- IA64_PSR vpsr;
- src=®s->r16;
- sunat=®s->eml_unat;
- vpsr.val = VCPU(v, vpsr);
- if(vpsr.bn){
- dst = &VCPU(v, vgr[0]);
- dunat =&VCPU(v, vnat);
- __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;; \
- dep %2 = %0, %2, 0, 16;; \
- st8 [%3] = %2;;"
-
::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
-
- }else{
- dst = &VCPU(v, vbgr[0]);
-// dunat =&VCPU(v, vbnat);
-// __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;;
-// dep %2 = %0, %2, 16, 16;;
-// st8 [%3] = %2;;"
-//
::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
-
- }
- for(i=0; i<16; i++)
- *dst++ = *src++;
-}
-
-
-// ONLY gets called from ia64_leave_kernel
-// ONLY call with interrupts disabled?? (else might miss one?)
-// NEVER successful if already reflecting a trap/fault because psr.i==0
-void leave_hypervisor_tail(void)
-{
- struct domain *d = current->domain;
- struct vcpu *v = current;
-
- // FIXME: Will this work properly if doing an RFI???
- if (!is_idle_domain(d) ) { // always comes from guest
-// struct pt_regs *user_regs = vcpu_regs(current);
- local_irq_enable();
- do_softirq();
- local_irq_disable();
-
- if (v->vcpu_id == 0) {
- unsigned long callback_irq =
- d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
-
- if ( v->arch.arch_vmx.pal_init_pending ) {
- /*inject INIT interruption to guest pal*/
- v->arch.arch_vmx.pal_init_pending = 0;
- deliver_pal_init(v);
- return;
- }
-
- /*
- * val[63:56] == 1: val[55:0] is a delivery PCI INTx line:
- * Domain = val[47:32], Bus = val[31:16],
- * DevFn = val[15: 8], IntX = val[ 1: 0]
- * val[63:56] == 0: val[55:0] is a delivery as GSI
- */
- if (callback_irq != 0 && local_events_need_delivery()) {
- /* change level for para-device callback irq */
- /* use level irq to send discrete event */
- if ((uint8_t)(callback_irq >> 56) == 1) {
- /* case of using PCI INTx line as callback irq */
- int pdev = (callback_irq >> 11) & 0x1f;
- int pintx = callback_irq & 3;
- viosapic_set_pci_irq(d, pdev, pintx, 1);
- viosapic_set_pci_irq(d, pdev, pintx, 0);
- } else {
- /* case of using GSI as callback irq */
- viosapic_set_irq(d, callback_irq, 1);
- viosapic_set_irq(d, callback_irq, 0);
- }
- }
- }
-
- rmb();
- if (xchg(&v->arch.irq_new_pending, 0)) {
- v->arch.irq_new_condition = 0;
- vmx_check_pending_irq(v);
- return;
- }
-
- if (v->arch.irq_new_condition) {
- v->arch.irq_new_condition = 0;
- vhpi_detection(v);
- }
- }
-}
-
-extern ia64_rr vmx_vcpu_rr(VCPU *vcpu, u64 vadr);
-
-static int vmx_handle_lds(REGS* regs)
-{
- regs->cr_ipsr |=IA64_PSR_ED;
- return IA64_FAULT;
-}
-
-/* We came here because the H/W VHPT walker failed to find an entry */
-IA64FAULT
-vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
-{
- IA64_PSR vpsr;
- int type;
- u64 vhpt_adr, gppa, pteval, rr, itir;
- ISR misr;
- PTA vpta;
- thash_data_t *data;
- VCPU *v = current;
-
- vpsr.val = VCPU(v, vpsr);
- misr.val = VMX(v,cr_isr);
-
- if (vec == 1)
- type = ISIDE_TLB;
- else if (vec == 2)
- type = DSIDE_TLB;
- else
- panic_domain(regs, "wrong vec:%lx\n", vec);
-
- if(is_physical_mode(v)&&(!(vadr<<1>>62))){
- if(vec==2){
- if (misr.sp) /* Refer to SDM Vol2 Table 4-11,4-12 */
- return vmx_handle_lds(regs);
- if (v->domain != dom0
- && __gpfn_is_io(v->domain, (vadr << 1) >> (PAGE_SHIFT + 1))) {
- emulate_io_inst(v,((vadr<<1)>>1),4); // UC
- return IA64_FAULT;
- }
- }
- physical_tlb_miss(v, vadr, type);
- return IA64_FAULT;
- }
-
-try_again:
- if((data=vtlb_lookup(v, vadr,type))!=0){
- if (v->domain != dom0 && type == DSIDE_TLB) {
- if (misr.sp) { /* Refer to SDM Vol2 Table 4-10,4-12 */
- if ((data->ma == VA_MATTR_UC) || (data->ma == VA_MATTR_UCE))
- return vmx_handle_lds(regs);
- }
- gppa = (vadr & ((1UL << data->ps) - 1)) +
- (data->ppn >> (data->ps - 12) << data->ps);
- if (__gpfn_is_io(v->domain, gppa >> PAGE_SHIFT)) {
- if (misr.sp)
- panic_domain(NULL, "ld.s on I/O page not with UC attr."
- " pte=0x%lx\n", data->page_flags);
- if (data->pl >= ((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 IA64_FAULT;
- }
- }
- thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type);
-
- }else if(type == DSIDE_TLB){
-
- if (misr.sp)
- return vmx_handle_lds(regs);
-
- vcpu_get_rr(v, vadr, &rr);
- itir = rr & (RR_RID_MASK | RR_PS_MASK);
-
- if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
- if (GOS_WINDOWS(v)) {
- /* windows use region 4 and 5 for identity mapping */
- if (REGION_NUMBER(vadr) == 4 && !(regs->cr_ipsr & IA64_PSR_CPL)
- && (REGION_OFFSET(vadr)<= _PAGE_PPN_MASK)) {
-
- pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) |
- (_PAGE_P | _PAGE_A | _PAGE_D |
- _PAGE_MA_WB | _PAGE_AR_RW);
-
- if (thash_purge_and_insert(v, pteval, itir, vadr, type))
- goto try_again;
-
- return IA64_NO_FAULT;
- }
-
- if (REGION_NUMBER(vadr) == 5 && !(regs->cr_ipsr & IA64_PSR_CPL)
- && (REGION_OFFSET(vadr)<= _PAGE_PPN_MASK)) {
-
- pteval = PAGEALIGN(REGION_OFFSET(vadr),itir_ps(itir)) |
- (_PAGE_P | _PAGE_A | _PAGE_D |
- _PAGE_MA_UC | _PAGE_AR_RW);
-
- if (thash_purge_and_insert(v, pteval, itir, vadr, type))
- goto try_again;
-
- return IA64_NO_FAULT;
- }
- }
-
- if(vpsr.ic){
- vcpu_set_isr(v, misr.val);
- alt_dtlb(v, vadr);
- return IA64_FAULT;
- } else{
- nested_dtlb(v);
- return IA64_FAULT;
- }
- }
-
- vpta.val = vmx_vcpu_get_pta(v);
- if (vpta.vf) {
- /* Long format is not yet supported. */
- if (vpsr.ic) {
- vcpu_set_isr(v, misr.val);
- dtlb_fault(v, vadr);
- return IA64_FAULT;
- } else {
- nested_dtlb(v);
- return IA64_FAULT;
- }
- }
-
- /* avoid recursively walking (short format) VHPT */
- if (!GOS_WINDOWS(v) &&
- (((vadr ^ vpta.val) << 3) >> (vpta.size + 3)) == 0) {
-
- if (vpsr.ic) {
- vcpu_set_isr(v, misr.val);
- dtlb_fault(v, vadr);
- return IA64_FAULT;
- } else {
- nested_dtlb(v);
- return IA64_FAULT;
- }
- }
-
- vhpt_adr = vmx_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);
- return IA64_FAULT;
- } else {
- nested_dtlb(v);
- return IA64_FAULT;
- }
- } else if ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST) {
- thash_purge_and_insert(v, pteval, itir, vadr, DSIDE_TLB);
- return IA64_NO_FAULT;
- } else if (vpsr.ic) {
- vcpu_set_isr(v, misr.val);
- dtlb_fault(v, vadr);
- return IA64_FAULT;
- }else{
- nested_dtlb(v);
- return IA64_FAULT;
- }
- } else {
- /* Can't read VHPT. */
- if (vpsr.ic) {
- vcpu_set_isr(v, misr.val);
- dvhpt_fault(v, vadr);
- return IA64_FAULT;
- } else {
- nested_dtlb(v);
- return IA64_FAULT;
- }
- }
- }else if(type == ISIDE_TLB){
-
- if (!vpsr.ic)
- misr.ni = 1;
- if (!vhpt_enabled(v, vadr, INST_REF)) {
- vcpu_set_isr(v, misr.val);
- alt_itlb(v, vadr);
- return IA64_FAULT;
- }
-
- vpta.val = vmx_vcpu_get_pta(v);
- if (vpta.vf) {
- /* Long format is not yet supported. */
- vcpu_set_isr(v, misr.val);
- itlb_fault(v, vadr);
- return IA64_FAULT;
- }
-
-
- vhpt_adr = vmx_vcpu_thash(v, vadr);
- if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
- /* VHPT successfully read. */
- if (pteval & _PAGE_P) {
- if ((pteval & _PAGE_MA_MASK) == _PAGE_MA_ST) {
- vcpu_set_isr(v, misr.val);
- itlb_fault(v, vadr);
- return IA64_FAULT;
- }
- vcpu_get_rr(v, vadr, &rr);
- itir = rr & (RR_RID_MASK | RR_PS_MASK);
- thash_purge_and_insert(v, pteval, itir, vadr, ISIDE_TLB);
- return IA64_NO_FAULT;
- } else {
- vcpu_set_isr(v, misr.val);
- inst_page_not_present(v, vadr);
- return IA64_FAULT;
- }
- } else {
- vcpu_set_isr(v, misr.val);
- ivhpt_fault(v, vadr);
- return IA64_FAULT;
- }
- }
- return IA64_NO_FAULT;
-}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|