# HG changeset patch # User Tristan Gingold # Date 1204863502 -3600 # Node ID 99ed430040909e7edd203893a18a72d0d8de1c52 # Parent 687a4068f54284543b52b36b99ea9ea8bdae3ea5 Prepare sioemu for SMP and save & restore. Use macros instead of constants. Signed-off-by: Tristan Gingold diff -r 687a4068f542 -r 99ed43004090 xen/arch/ia64/vmx/sioemu.c --- a/xen/arch/ia64/vmx/sioemu.c Fri Mar 07 05:14:33 2008 +0100 +++ b/xen/arch/ia64/vmx/sioemu.c Fri Mar 07 05:18:22 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,46 +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); - - /* First restore registers. */ - regs->cr_iip = regs->r28; - regs->cr_ifs = regs->r30; - vmx_vcpu_set_psr (vcpu, regs->r29); +} + +static void +sioemu_restore_regs (VCPU *vcpu) +{ + REGS *regs = vcpu_regs(vcpu); regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT); regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT; @@ -117,6 +76,66 @@ 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; @@ -134,7 +153,7 @@ sioemu_deliver_event (void) regs = sioemu_deliver (); - regs->r16 = 0; + regs->r16 = SIOEMU_CB_EVENT; } void @@ -145,11 +164,30 @@ sioemu_io_emulate (unsigned long padr, 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 @@ -191,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) @@ -202,19 +240,39 @@ 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); - regs->r8 = (sec << 30) + nsec; + uint64_t 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); diff -r 687a4068f542 -r 99ed43004090 xen/arch/ia64/vmx/vmx_fault.c --- a/xen/arch/ia64/vmx/vmx_fault.c Fri Mar 07 05:14:33 2008 +0100 +++ b/xen/arch/ia64/vmx/vmx_fault.c Fri Mar 07 05:18:22 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 687a4068f542 -r 99ed43004090 xen/include/asm-ia64/sioemu.h --- a/xen/include/asm-ia64/sioemu.h Fri Mar 07 05:14:33 2008 +0100 +++ b/xen/include/asm-ia64/sioemu.h Fri Mar 07 05:18:22 2008 +0100 @@ -26,6 +26,7 @@ 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 687a4068f542 -r 99ed43004090 xen/include/public/arch-ia64/sioemu.h --- a/xen/include/public/arch-ia64/sioemu.h Fri Mar 07 05:14:33 2008 +0100 +++ b/xen/include/public/arch-ia64/sioemu.h Fri Mar 07 05:18:22 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,38 @@ /* 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. */