# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1206044949 21600
# Node ID e768be7bf56162347c1facf3b71e88d19f639599
# Parent 6bdb343977010df67469be15bb88dce7d93668bb
[IA64] New SIOEmu interface: pass callback data in memory.
This fixes lost data for callback while hypercall case.
Signed-off-by: Tristan Gingold <tgingold@xxxxxxx>
---
xen/arch/ia64/asm-offsets.c | 2
xen/arch/ia64/vmx/sioemu.c | 206 +++++++++++++---------------------
xen/arch/ia64/vmx/vmx_fault.c | 4
xen/arch/ia64/vmx/vmx_init.c | 4
xen/include/asm-ia64/sioemu.h | 2
xen/include/asm-ia64/vmx_vpd.h | 8 -
xen/include/public/arch-ia64/sioemu.h | 31 +++--
7 files changed, 114 insertions(+), 143 deletions(-)
diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/asm-offsets.c
--- a/xen/arch/ia64/asm-offsets.c Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/asm-offsets.c Thu Mar 20 14:29:09 2008 -0600
@@ -150,6 +150,8 @@ void foo(void)
DEFINE(IA64_VCPU_OPCODE_OFFSET, offsetof (struct vcpu,
arch.arch_vmx.opcode));
DEFINE(SWITCH_MPTA_OFFSET,offsetof(struct vcpu ,arch.arch_vmx.mpta));
DEFINE(IA64_PT_REGS_R16_SLOT, (((offsetof(struct pt_regs,
r16)-sizeof(struct pt_regs))>>3)&0x3f));
+ DEFINE(IA64_PT_REGS_R2_SLOT, (((offsetof(struct pt_regs,
r16)-sizeof(struct pt_regs))>>3)&0x3f));
+ DEFINE(IA64_PT_REGS_R8_SLOT, (((offsetof(struct pt_regs,
r16)-sizeof(struct pt_regs))>>3)&0x3f));
DEFINE(IA64_VCPU_FLAGS_OFFSET,offsetof(struct vcpu
,arch.arch_vmx.flags));
DEFINE(IA64_VCPU_MMU_MODE_OFFSET,offsetof(struct vcpu,
arch.arch_vmx.mmu_mode));
diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/vmx/sioemu.c
--- a/xen/arch/ia64/vmx/sioemu.c Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/vmx/sioemu.c Thu Mar 20 14:29:09 2008 -0600
@@ -26,171 +26,137 @@
#include <asm/sal.h>
#include <asm/vlsapic.h>
-static void
-sioemu_save_regs (VCPU *vcpu)
-{
- REGS *regs = vcpu_regs(vcpu);
-
- vcpu->arch.arch_vmx.stub_saved[0] = regs->r16;
- vcpu->arch.arch_vmx.stub_saved[1] = regs->r17;
- vcpu->arch.arch_vmx.stub_saved[2] = regs->r18;
- vcpu->arch.arch_vmx.stub_saved[3] = regs->r19;
- vcpu->arch.arch_vmx.stub_saved[4] = regs->r20;
- vcpu->arch.arch_vmx.stub_saved[5] = regs->r21;
- vcpu->arch.arch_vmx.stub_saved[6] = regs->r22;
- vcpu->arch.arch_vmx.stub_saved[7] = regs->r23;
- vcpu->arch.arch_vmx.stub_saved[8] = regs->r24;
- vcpu->arch.arch_vmx.stub_saved[9] = regs->r25;
- vcpu->arch.arch_vmx.stub_saved[10] = regs->r26;
- vcpu->arch.arch_vmx.stub_saved[11] = regs->r27;
- vcpu->arch.arch_vmx.stub_saved[12] = regs->r28;
- vcpu->arch.arch_vmx.stub_saved[13] = regs->r29;
- vcpu->arch.arch_vmx.stub_saved[14] = regs->r30;
- vcpu->arch.arch_vmx.stub_saved[15] = regs->r31;
- vcpu->arch.arch_vmx.stub_nats =
- (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff;
-}
-
-static void
-sioemu_restore_regs (VCPU *vcpu)
-{
- REGS *regs = vcpu_regs(vcpu);
-
- /* First restore registers. */
- regs->cr_iip = regs->r28;
- regs->cr_ifs = regs->r30;
- vmx_vcpu_set_psr (vcpu, regs->r29);
-
- regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
- regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT;
-
- regs->r16 = vcpu->arch.arch_vmx.stub_saved[0];
- regs->r17 = vcpu->arch.arch_vmx.stub_saved[1];
- regs->r18 = vcpu->arch.arch_vmx.stub_saved[2];
- regs->r19 = vcpu->arch.arch_vmx.stub_saved[3];
- regs->r20 = vcpu->arch.arch_vmx.stub_saved[4];
- regs->r21 = vcpu->arch.arch_vmx.stub_saved[5];
- regs->r22 = vcpu->arch.arch_vmx.stub_saved[6];
- regs->r23 = vcpu->arch.arch_vmx.stub_saved[7];
- regs->r24 = vcpu->arch.arch_vmx.stub_saved[8];
- regs->r25 = vcpu->arch.arch_vmx.stub_saved[9];
- regs->r26 = vcpu->arch.arch_vmx.stub_saved[10];
- regs->r27 = vcpu->arch.arch_vmx.stub_saved[11];
- regs->r28 = vcpu->arch.arch_vmx.stub_saved[12];
- regs->r29 = vcpu->arch.arch_vmx.stub_saved[13];
- regs->r30 = vcpu->arch.arch_vmx.stub_saved[14];
- regs->r31 = vcpu->arch.arch_vmx.stub_saved[15];
-
-}
-
-static REGS *
+struct sioemu_callback_info *
sioemu_deliver (void)
{
VCPU *vcpu = current;
REGS *regs = vcpu_regs(vcpu);
+ struct sioemu_callback_info *info = vcpu->arch.arch_vmx.sioemu_info_mva;
unsigned long psr = vmx_vcpu_get_psr(vcpu);
if (vcpu->vcpu_info->evtchn_upcall_mask)
panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n");
+ if (info == NULL)
+ panic_domain (NULL, "sioemu_deliver: set_callback not called\n");
/* All cleared, but keep BN. */
vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN));
- /* Save registers. */
- sioemu_save_regs (vcpu);
-
- /* Context. */
- regs->r28 = regs->cr_iip;
- regs->r29 = psr;
- regs->r30 = regs->cr_ifs;
+ /* Set info. */
+ info->ip = regs->cr_iip;
+ info->psr = psr;
+ info->ifs = regs->cr_ifs;
+ info->nats = (((regs->eml_unat >> IA64_PT_REGS_R8_SLOT) & 0x0f) << 8)
+ | (((regs->eml_unat >> IA64_PT_REGS_R2_SLOT) & 1) << 2);
+ info->r8 = regs->r8;
+ info->r9 = regs->r9;
+ info->r10 = regs->r10;
+ info->r11 = regs->r11;
+ info->r2 = regs->r2;
regs->cr_ifs = 0; // pre-cover
-
regs->cr_iip = vcpu->arch.event_callback_ip;
- regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT);
-
- /* Parameters. */
- regs->r16 = 0;
- regs->r17 = vcpu->arch.arch_vmx.stub_buffer;
+ regs->eml_unat &= ~(1UL << IA64_PT_REGS_R8_SLOT);
+ regs->r8 = vcpu->arch.arch_vmx.sioemu_info_gpa;
/* Mask events. */
vcpu->vcpu_info->evtchn_upcall_mask = 1;
debugger_event(XEN_IA64_DEBUG_ON_EVENT);
- return regs;
-}
-
-void
+ return info;
+}
+
+static void
sioemu_callback_return (void)
{
VCPU *vcpu = current;
REGS *regs = vcpu_regs(vcpu);
- u64 cmd = regs->r16;
- u64 arg1 = regs->r19;
- u64 arg2 = regs->r20;
- u64 arg3 = regs->r21;
-
- if ((cmd & ~0x1UL) != 0)
+ struct sioemu_callback_info *info = vcpu->arch.arch_vmx.sioemu_info_mva;
+
+ if (info == NULL)
+ panic_domain (NULL, "sioemu_deliver: set_callback not called\n");
+ if ((info->cause & ~0x1UL) != 0)
panic_domain (NULL, "sioemu_callback_return: bad operation (%lx)\n",
- cmd);
+ info->cause);
/* First restore registers. */
- regs->cr_iip = regs->r28;
- regs->cr_ifs = regs->r30;
- vmx_vcpu_set_psr (vcpu, regs->r29);
-
- sioemu_restore_regs (vcpu);
+ regs->cr_iip = info->ip;
+ regs->cr_ifs = info->ifs;
+ vmx_vcpu_set_psr (vcpu, info->psr);
+ regs->r8 = info->r8;
+ regs->r9 = info->r9;
+ regs->r10 = info->r10;
+ regs->r11 = info->r11;
+ regs->r2 = info->r2;
+ regs->eml_unat &= ~((0x0fUL << IA64_PT_REGS_R8_SLOT)
+ | (1UL << IA64_PT_REGS_R2_SLOT));
+ regs->eml_unat |= (((info->nats >> 8) & 0x0f) << IA64_PT_REGS_R8_SLOT)
+ | (((info->nats >> 2) & 1) << IA64_PT_REGS_R2_SLOT);
/* Unmask events. */
vcpu->vcpu_info->evtchn_upcall_mask = 0;
/* Then apply commands. */
- if (cmd & 1) {
- emulate_io_update (vcpu, arg1, arg2, arg3);
+ if (info->cause & 1) {
+ emulate_io_update (vcpu, info->arg0, info->arg1, info->arg2);
}
}
void
sioemu_deliver_event (void)
{
- REGS *regs;
-
- regs = sioemu_deliver ();
- regs->r16 = SIOEMU_CB_EVENT;
+ struct sioemu_callback_info *info;
+
+ info = sioemu_deliver ();
+ info->cause = SIOEMU_CB_EVENT;
}
void
sioemu_io_emulate (unsigned long padr, unsigned long data,
unsigned long data1, unsigned long word)
{
- REGS *regs;
-
- regs = sioemu_deliver ();
- regs->r16 = SIOEMU_CB_IO_EMULATE;
- regs->r19 = padr;
- regs->r20 = data;
- regs->r21 = data1;
- regs->r22 = word;
-}
-
-void
-sioemu_wakeup_vcpu (int vcpu_id)
-{
- REGS *regs;
-
- regs = sioemu_deliver();
- regs->r16 = SIOEMU_CB_WAKEUP_VCPU;
- regs->r19 = vcpu_id;
+ struct sioemu_callback_info *info;
+
+ info = sioemu_deliver ();
+ info->cause = SIOEMU_CB_IO_EMULATE;
+ info->arg0 = padr;
+ info->arg1 = data;
+ info->arg2 = data1;
+ info->arg3 = word;
}
void
sioemu_sal_assist (struct vcpu *v)
{
- REGS *regs;
-
- regs = sioemu_deliver();
- regs->r16 = SIOEMU_CB_SAL_ASSIST;
+ struct sioemu_callback_info *info;
+
+ info = sioemu_deliver ();
+ info->cause = SIOEMU_CB_SAL_ASSIST;
+}
+
+static int
+sioemu_set_callback (struct vcpu *v, unsigned long cb_ip, unsigned long paddr)
+{
+ struct page_info *page;
+ unsigned long mfn;
+ pte_t pte;
+
+ v->arch.event_callback_ip = cb_ip;
+ if ((paddr & 0xfff) || v->arch.arch_vmx.sioemu_info_mva)
+ return -EINVAL;
+ pte = *lookup_noalloc_domain_pte(v->domain, paddr);
+ if (!pte_present(pte) || !pte_mem(pte))
+ return -EINVAL;
+ mfn = (pte_val(pte) & _PFN_MASK) >> PAGE_SHIFT;
+ ASSERT(mfn_valid(mfn));
+
+ page = mfn_to_page(mfn);
+ if (get_page(page, v->domain) == 0)
+ return -EINVAL;
+ v->arch.arch_vmx.sioemu_info_gpa = paddr;
+ v->arch.arch_vmx.sioemu_info_mva = mfn_to_virt(mfn);
+ return 0;
}
static int
@@ -234,8 +200,7 @@ sioemu_hypercall (struct pt_regs *regs)
switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW)
{
case SIOEMU_HYPERCALL_SET_CALLBACK:
- current->arch.event_callback_ip = regs->r8;
- current->arch.arch_vmx.stub_buffer = regs->r9;
+ regs->r8 = sioemu_set_callback(current, regs->r8, regs->r9);
break;
case SIOEMU_HYPERCALL_START_FW:
regs->cr_iip = regs->r8;
@@ -254,12 +219,6 @@ sioemu_hypercall (struct pt_regs *regs)
regs->r9 = now;
break;
}
- case SIOEMU_HYPERCALL_GET_REGS:
- sioemu_restore_regs(current);
- break;
- case SIOEMU_HYPERCALL_SET_REGS:
- sioemu_save_regs(current);
- break;
case SIOEMU_HYPERCALL_FLUSH_CACHE:
regs->r8 = ia64_sal_cache_flush(regs->r8);
break;
@@ -271,7 +230,6 @@ sioemu_hypercall (struct pt_regs *regs)
regs->r8, regs->r9, regs->r10);
break;
case SIOEMU_HYPERCALL_CALLBACK_RETURN:
- regs->r2 = regs->r27;
sioemu_callback_return ();
vcpu_decrement_iip(current);
break;
diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/vmx/vmx_fault.c
--- a/xen/arch/ia64/vmx/vmx_fault.c Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/vmx/vmx_fault.c Thu Mar 20 14:29:09 2008 -0600
@@ -215,10 +215,6 @@ vmx_ia64_handle_break (unsigned long ifa
vcpu_increment_iip(v);
}
return IA64_NO_FAULT;
- } else if (d->arch.is_sioemu
- && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) {
- sioemu_callback_return ();
- return IA64_NO_FAULT;
}
}
vmx_reflect_interruption(ifa, isr, iim, 11, regs);
diff -r 6bdb34397701 -r e768be7bf561 xen/arch/ia64/vmx/vmx_init.c
--- a/xen/arch/ia64/vmx/vmx_init.c Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/arch/ia64/vmx/vmx_init.c Thu Mar 20 14:29:09 2008 -0600
@@ -540,6 +540,10 @@ vmx_relinquish_vcpu_resources(struct vcp
kill_timer(&vtm->vtm_timer);
+ if (v->arch.arch_vmx.sioemu_info_mva)
+ put_page(virt_to_page((unsigned long)
+ v->arch.arch_vmx.sioemu_info_mva));
+
free_domain_tlb(v);
free_vpd(v);
}
diff -r 6bdb34397701 -r e768be7bf561 xen/include/asm-ia64/sioemu.h
--- a/xen/include/asm-ia64/sioemu.h Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/include/asm-ia64/sioemu.h Thu Mar 20 14:29:09 2008 -0600
@@ -23,9 +23,7 @@
#define __ASM_SIOEMU_H_
extern void sioemu_hypercall (struct pt_regs *regs);
extern void sioemu_deliver_event (void);
-extern void sioemu_callback_return (void);
extern void sioemu_io_emulate (unsigned long padr, unsigned long data,
unsigned long data1, unsigned long word);
-extern void sioemu_wakeup_vcpu (int vcpu_id);
extern void sioemu_sal_assist (struct vcpu *v);
#endif /* __ASM_SIOEMU_H_ */
diff -r 6bdb34397701 -r e768be7bf561 xen/include/asm-ia64/vmx_vpd.h
--- a/xen/include/asm-ia64/vmx_vpd.h Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/include/asm-ia64/vmx_vpd.h Thu Mar 20 14:29:09 2008 -0600
@@ -40,6 +40,8 @@
#include <public/xen.h>
#include <xen/spinlock.h>
+struct sioemu_callback_info;
+
#define VPD_SHIFT 16
#define VPD_SIZE (1 << VPD_SHIFT)
@@ -74,9 +76,9 @@ struct arch_vmx_struct {
unsigned long ivt_current;
struct ivt_debug ivt_debug[IVT_DEBUG_MAX];
#endif
- unsigned long stub_saved[16];
- unsigned long stub_buffer;
- unsigned int stub_nats;
+ /* sioemu info buffer. */
+ unsigned long sioemu_info_gpa;
+ struct sioemu_callback_info *sioemu_info_mva;
};
#define VMX_DOMAIN(v) v->arch.arch_vmx.flags
diff -r 6bdb34397701 -r e768be7bf561 xen/include/public/arch-ia64/sioemu.h
--- a/xen/include/public/arch-ia64/sioemu.h Thu Mar 20 14:12:07 2008 -0600
+++ b/xen/include/public/arch-ia64/sioemu.h Thu Mar 20 14:29:09 2008 -0600
@@ -38,10 +38,6 @@
/* Get wallclock time. */
#define SIOEMU_HYPERCALL_GET_TIME 0x04
-/* Get/Set shadow registers. */
-#define SIOEMU_HYPERCALL_GET_REGS 0x05
-#define SIOEMU_HYPERCALL_SET_REGS 0x06
-
/* Flush cache. */
#define SIOEMU_HYPERCALL_FLUSH_CACHE 0x07
@@ -68,11 +64,26 @@
/* A SAL hypercall is executed. */
#define SIOEMU_CB_SAL_ASSIST 0x03
+#ifndef __ASSEMBLY__
+struct sioemu_callback_info {
+ /* Saved registers. */
+ unsigned long ip;
+ unsigned long psr;
+ unsigned long ifs;
+ unsigned long nats;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long r11;
-/* SIOEMU firmware mode hypercalls. */
-
-/* Return from callback. r16=0.
- Unmask vcpu events. */
-#define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01
-
+ /* Callback parameters. */
+ unsigned long cause;
+ unsigned long arg0;
+ unsigned long arg1;
+ unsigned long arg2;
+ unsigned long arg3;
+ unsigned long _pad2[2];
+ unsigned long r2;
+};
+#endif /* __ASSEMBLY__ */
#endif /* __XEN_PUBLIC_IA64_SIOEMU_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|