# HG changeset patch # User Tristan Gingold # Date 1204943233 -3600 # Node ID 5c8da1f449872216bb4cc0b81d153f92b90d97da # Parent 550ba7a6fe535dde3d0c939e83f8c86168264066 Prepare sioemu for SMP and save & restore. Use macros instead of constants. Signed-off-by: Tristan Gingold diff -r 550ba7a6fe53 -r 5c8da1f44987 xen/arch/ia64/vmx/sioemu.c --- a/xen/arch/ia64/vmx/sioemu.c Sat Mar 08 03:08:23 2008 +0100 +++ b/xen/arch/ia64/vmx/sioemu.c Sat Mar 08 03:27:13 2008 +0100 @@ -23,21 +23,14 @@ #include #include #include - -static REGS * -sioemu_deliver (void) -{ - VCPU *vcpu = current; - REGS *regs = vcpu_regs(vcpu); - 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"); - - /* All cleared, but keep BN. */ - vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN)); - - /* Save registers. */ +#include +#include + +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; @@ -56,42 +49,12 @@ sioemu_deliver (void) vcpu->arch.arch_vmx.stub_saved[15] = regs->r31; vcpu->arch.arch_vmx.stub_nats = (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff; - - /* Context. */ - regs->r28 = regs->cr_iip; - regs->r29 = psr; - regs->r30 = regs->cr_ifs; - - 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; - - /* Mask events. */ - vcpu->vcpu_info->evtchn_upcall_mask = 1; - - debugger_event(XEN_IA64_DEBUG_ON_EVENT); - - return regs; -} - -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) - panic_domain (NULL, - "sioemu_callback_return: bad operation (%lx)\n", cmd); +} + +static void +sioemu_restore_regs (VCPU *vcpu) +{ + REGS *regs = vcpu_regs(vcpu); /* First restore registers. */ regs->cr_iip = regs->r28; @@ -118,6 +81,67 @@ sioemu_callback_return (void) regs->r30 = vcpu->arch.arch_vmx.stub_saved[14]; regs->r31 = vcpu->arch.arch_vmx.stub_saved[15]; +} + +static REGS * +sioemu_deliver (void) +{ + VCPU *vcpu = current; + REGS *regs = vcpu_regs(vcpu); + 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"); + + /* 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; + + 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; + + /* Mask events. */ + vcpu->vcpu_info->evtchn_upcall_mask = 1; + + debugger_event(XEN_IA64_DEBUG_ON_EVENT); + + return regs; +} + +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) + panic_domain (NULL, "sioemu_callback_return: bad operation (%lx)\n", + cmd); + + /* First restore registers. */ + regs->cr_iip = regs->r28; + regs->cr_ifs = regs->r30; + vmx_vcpu_set_psr (vcpu, regs->r29); + + sioemu_restore_regs (vcpu); + /* Unmask events. */ vcpu->vcpu_info->evtchn_upcall_mask = 0; @@ -133,8 +157,7 @@ sioemu_deliver_event (void) REGS *regs; regs = sioemu_deliver (); - - regs->r16 = 0; + regs->r16 = SIOEMU_CB_EVENT; } void @@ -144,11 +167,30 @@ sioemu_io_emulate (unsigned long padr, u REGS *regs; regs = sioemu_deliver (); - regs->r16 = 1; + 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; +} + +void +sioemu_sal_assist (struct vcpu *v) +{ + REGS *regs; + + regs = sioemu_deliver(); + regs->r16 = SIOEMU_CB_SAL_ASSIST; } static int @@ -187,7 +229,7 @@ sioemu_hypercall (struct pt_regs *regs) // regs->r2, regs->r8, regs->r9); if (current->vcpu_info->evtchn_upcall_mask == 0) - panic_domain (NULL, "sioemu_hypercall: not in stub mode\n"); + panic_domain(NULL, "sioemu_hypercall: not in stub mode\n"); switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW) { @@ -197,20 +239,40 @@ sioemu_hypercall (struct pt_regs *regs) break; case SIOEMU_HYPERCALL_START_FW: regs->cr_iip = regs->r8; - vmx_vcpu_set_psr (current, regs->r9); + vmx_vcpu_set_psr(current, regs->r9); current->vcpu_info->evtchn_upcall_mask = 0; break; case SIOEMU_HYPERCALL_ADD_IO_PHYSMAP: - regs->r8 = sioemu_add_io_physmap (current->domain, - regs->r8, regs->r9, regs->r10); + regs->r8 = sioemu_add_io_physmap(current->domain, + regs->r8, regs->r9, regs->r10); break; case SIOEMU_HYPERCALL_GET_TIME: { uint64_t sec, nsec; - get_wallclock (&sec, &nsec); + get_wallclock(&sec, &nsec); regs->r8 = (sec << 30) + nsec; 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; + case SIOEMU_HYPERCALL_FREQ_BASE: + regs->r8 = ia64_sal_freq_base(regs->r8, ®s->r9, ®s->r10); + break; + case SIOEMU_HYPERCALL_DELIVER_INT: + regs->r8 = vlsapic_deliver_int(current->domain, + regs->r8, regs->r9, regs->r10); + break; + case SIOEMU_HYPERCALL_CALLBACK_RETURN: + regs->r2 = regs->r27; + sioemu_callback_return (); + break; default: panic_domain (NULL, "bad sioemu hypercall %lx\n", regs->r2); break; diff -r 550ba7a6fe53 -r 5c8da1f44987 xen/arch/ia64/vmx/vmx_fault.c --- a/xen/arch/ia64/vmx/vmx_fault.c Sat Mar 08 03:08:23 2008 +0100 +++ b/xen/arch/ia64/vmx/vmx_fault.c Sat Mar 08 03:27:13 2008 +0100 @@ -208,8 +208,12 @@ vmx_ia64_handle_break (unsigned long ifa vcpu_increment_iip(v); return IA64_NO_FAULT; } else if (iim == DOMN_SAL_REQUEST) { - sal_emul(v); - vcpu_increment_iip(v); + if (d->arch.is_sioemu) + sioemu_sal_assist (v); + else { + sal_emul(v); + vcpu_increment_iip(v); + } return IA64_NO_FAULT; } else if (d->arch.is_sioemu && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) { diff -r 550ba7a6fe53 -r 5c8da1f44987 xen/include/asm-ia64/sioemu.h --- a/xen/include/asm-ia64/sioemu.h Sat Mar 08 03:08:23 2008 +0100 +++ b/xen/include/asm-ia64/sioemu.h Sat Mar 08 03:27:13 2008 +0100 @@ -26,5 +26,6 @@ extern void sioemu_callback_return (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 550ba7a6fe53 -r 5c8da1f44987 xen/include/public/arch-ia64/sioemu.h --- a/xen/include/public/arch-ia64/sioemu.h Sat Mar 08 03:08:23 2008 +0100 +++ b/xen/include/public/arch-ia64/sioemu.h Sat Mar 08 03:27:13 2008 +0100 @@ -22,6 +22,9 @@ #ifndef __XEN_PUBLIC_IA64_SIOEMU_H__ #define __XEN_PUBLIC_IA64_SIOEMU_H__ +/* SIOEMU specific hypercalls. + The numbers are the minor part of FW_HYPERCALL_SIOEMU. */ + /* Defines the callback entry point. r8=ip, r9=data. Must be called per-vcpu. */ #define SIOEMU_HYPERCALL_SET_CALLBACK 0x01 @@ -35,6 +38,39 @@ /* 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 + +/* Get freq base. */ +#define SIOEMU_HYPERCALL_FREQ_BASE 0x08 + +/* Return from callback. */ +#define SIOEMU_HYPERCALL_CALLBACK_RETURN 0x09 + +/* Deliver an interrupt. */ +#define SIOEMU_HYPERCALL_DELIVER_INT 0x0a + +/* SIOEMU callback reason. */ + +/* An event (from event channel) has to be delivered. */ +#define SIOEMU_CB_EVENT 0x00 + +/* Emulate an IO access. */ +#define SIOEMU_CB_IO_EMULATE 0x01 + +/* An IPI is sent to a dead vcpu. */ +#define SIOEMU_CB_WAKEUP_VCPU 0x02 + +/* A SAL hypercall is executed. */ +#define SIOEMU_CB_SAL_ASSIST 0x03 + + +/* SIOEMU firmware mode hypercalls. */ + /* Return from callback. r16=0. Unmask vcpu events. */ #define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01