ia64/xen-unstable
changeset 17072:430a036ab261
[IA64] Self IO EMUlator (sioemu) - Hypervisor part
Implements Self IO-EMUlator. It's an hybrid domain: looks
like PV from an external point of view but runs with VTI enabled.
All MMIO/IO writes/reads are reflected to the firmware, which converts the
access to PV drivers requests.
Signed-off-by: Tristan Gingold <tgingold@free.fr>
Implements Self IO-EMUlator. It's an hybrid domain: looks
like PV from an external point of view but runs with VTI enabled.
All MMIO/IO writes/reads are reflected to the firmware, which converts the
access to PV drivers requests.
Signed-off-by: Tristan Gingold <tgingold@free.fr>
author | Alex Williamson <alex.williamson@hp.com> |
---|---|
date | Tue Feb 19 08:11:22 2008 -0700 (2008-02-19) |
parents | c750c7177d63 |
children | 031c8f407e01 |
files | xen/arch/ia64/vmx/Makefile xen/arch/ia64/vmx/mmio.c xen/arch/ia64/vmx/sioemu.c xen/arch/ia64/vmx/vmx_fault.c xen/arch/ia64/vmx/vmx_hypercall.c xen/arch/ia64/vmx/vmx_init.c xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/hypercall.c xen/arch/ia64/xen/xensetup.c xen/arch/ia64/xen/xentime.c xen/include/asm-ia64/dom_fw.h xen/include/asm-ia64/domain.h xen/include/asm-ia64/sioemu.h xen/include/asm-ia64/time.h xen/include/asm-ia64/vmmu.h xen/include/asm-ia64/vmx_vpd.h xen/include/public/arch-ia64/sioemu.h xen/include/public/domctl.h |
line diff
1.1 --- a/xen/arch/ia64/vmx/Makefile Tue Feb 19 07:51:25 2008 -0700 1.2 +++ b/xen/arch/ia64/vmx/Makefile Tue Feb 19 08:11:22 2008 -0700 1.3 @@ -21,3 +21,4 @@ obj-y += optvfault.o 1.4 obj-y += vacpi.o 1.5 obj-y += vmx_vcpu_save.o 1.6 obj-y += save.o 1.7 +obj-y += sioemu.o
2.1 --- a/xen/arch/ia64/vmx/mmio.c Tue Feb 19 07:51:25 2008 -0700 2.2 +++ b/xen/arch/ia64/vmx/mmio.c Tue Feb 19 08:11:22 2008 -0700 2.3 @@ -39,6 +39,8 @@ 2.4 #include <asm/hvm/vacpi.h> 2.5 #include <asm/hvm/support.h> 2.6 #include <public/hvm/save.h> 2.7 +#include <public/arch-ia64/sioemu.h> 2.8 +#include <asm/sioemu.h> 2.9 2.10 #define HVM_BUFFERED_IO_RANGE_NR 1 2.11 2.12 @@ -388,6 +390,8 @@ static void mmio_access(VCPU *vcpu, u64 2.13 return; 2.14 } 2.15 2.16 +enum inst_type_en { SL_INTEGER, SL_FLOATING, SL_FLOATING_FP8 }; 2.17 + 2.18 /* 2.19 dir 1: read 0:write 2.20 */ 2.21 @@ -396,11 +400,12 @@ void emulate_io_inst(VCPU *vcpu, u64 pad 2.22 REGS *regs; 2.23 IA64_BUNDLE bundle; 2.24 int slot, dir=0; 2.25 - enum { SL_INTEGER, SL_FLOATING, SL_FLOATING_FP8 } inst_type; 2.26 + enum inst_type_en inst_type; 2.27 size_t size; 2.28 u64 data, data1, temp, update_reg; 2.29 s32 imm; 2.30 INST64 inst; 2.31 + unsigned long update_word; 2.32 2.33 regs = vcpu_regs(vcpu); 2.34 if (IA64_RETRY == __vmx_get_domain_bundle(regs->cr_iip, &bundle)) { 2.35 @@ -523,24 +528,53 @@ void emulate_io_inst(VCPU *vcpu, u64 pad 2.36 inst.inst, regs->cr_iip); 2.37 } 2.38 2.39 + update_word = size | (dir << 7) | (ma << 8) | (inst_type << 12); 2.40 + if (dir == IOREQ_READ) { 2.41 + if (inst_type == SL_INTEGER) 2.42 + update_word |= (inst.M1.r1 << 16); 2.43 + else if (inst_type == SL_FLOATING_FP8) 2.44 + update_word |= (inst.M12.f1 << 16) | (inst.M12.f2 << 24); 2.45 + } 2.46 + 2.47 + if (vcpu->domain->arch.is_sioemu) { 2.48 + unsigned long iot = __gpfn_is_io(vcpu->domain, padr >> PAGE_SHIFT); 2.49 + 2.50 + if (iot != GPFN_PIB && iot != GPFN_IOSAPIC) { 2.51 + sioemu_io_emulate(padr, data, data1, update_word); 2.52 + return; 2.53 + } 2.54 + } 2.55 + 2.56 if (size == 4) { 2.57 mmio_access(vcpu, padr + 8, &data1, 1 << 3, ma, dir); 2.58 size = 3; 2.59 } 2.60 mmio_access(vcpu, padr, &data, 1 << size, ma, dir); 2.61 2.62 + emulate_io_update(vcpu, update_word, data, data1); 2.63 +} 2.64 + 2.65 +void 2.66 +emulate_io_update(VCPU *vcpu, u64 word, u64 data, u64 data1) 2.67 +{ 2.68 + int dir = (word >> 7) & 1; 2.69 + 2.70 if (dir == IOREQ_READ) { 2.71 + int r1 = (word >> 16) & 0xff; 2.72 + int r2 = (word >> 24) & 0xff; 2.73 + enum inst_type_en inst_type = (word >> 12) & 0x0f; 2.74 + 2.75 if (inst_type == SL_INTEGER) { 2.76 - vcpu_set_gr(vcpu, inst.M1.r1, data, 0); 2.77 + vcpu_set_gr(vcpu, r1, data, 0); 2.78 } else if (inst_type == SL_FLOATING_FP8) { 2.79 struct ia64_fpreg v; 2.80 2.81 v.u.bits[0] = data; 2.82 v.u.bits[1] = 0x1003E; 2.83 - vcpu_set_fpreg(vcpu, inst.M12.f1, &v); 2.84 + vcpu_set_fpreg(vcpu, r1, &v); 2.85 v.u.bits[0] = data1; 2.86 v.u.bits[1] = 0x1003E; 2.87 - vcpu_set_fpreg(vcpu, inst.M12.f2, &v); 2.88 + vcpu_set_fpreg(vcpu, r2, &v); 2.89 } else { 2.90 panic_domain(NULL, "Don't support ldfd now !"); 2.91 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/xen/arch/ia64/vmx/sioemu.c Tue Feb 19 08:11:22 2008 -0700 3.3 @@ -0,0 +1,219 @@ 3.4 +/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */ 3.5 +/* 3.6 + * sioemu.c: Self IO emulation - hypercall and return. 3.7 + * Copyright (c) 2008, Tristan Gingold <tgingold@free.fr> 3.8 + * 3.9 + * This program is free software; you can redistribute it and/or modify it 3.10 + * under the terms and conditions of the GNU General Public License, 3.11 + * version 2, as published by the Free Software Foundation. 3.12 + * 3.13 + * This program is distributed in the hope it will be useful, but WITHOUT 3.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 3.16 + * more details. 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License along with 3.19 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 3.20 + * Place - Suite 330, Boston, MA 02111-1307 USA. 3.21 + */ 3.22 + 3.23 +#include <asm/vcpu.h> 3.24 +#include <asm/vmx_vcpu.h> 3.25 +#include <asm/sioemu.h> 3.26 +#include <public/arch-ia64/sioemu.h> 3.27 +#include <asm/dom_fw.h> 3.28 +#include <asm/debugger.h> 3.29 + 3.30 +static REGS * 3.31 +sioemu_deliver (void) 3.32 +{ 3.33 + VCPU *vcpu = current; 3.34 + REGS *regs = vcpu_regs(vcpu); 3.35 + unsigned long psr = vmx_vcpu_get_psr(vcpu); 3.36 + 3.37 + if (vcpu->vcpu_info->evtchn_upcall_mask) 3.38 + panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n"); 3.39 + 3.40 + /* All cleared, but keep BN. */ 3.41 + vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN)); 3.42 + 3.43 + /* Save registers. */ 3.44 + vcpu->arch.arch_vmx.stub_saved[0] = regs->r16; 3.45 + vcpu->arch.arch_vmx.stub_saved[1] = regs->r17; 3.46 + vcpu->arch.arch_vmx.stub_saved[2] = regs->r18; 3.47 + vcpu->arch.arch_vmx.stub_saved[3] = regs->r19; 3.48 + vcpu->arch.arch_vmx.stub_saved[4] = regs->r20; 3.49 + vcpu->arch.arch_vmx.stub_saved[5] = regs->r21; 3.50 + vcpu->arch.arch_vmx.stub_saved[6] = regs->r22; 3.51 + vcpu->arch.arch_vmx.stub_saved[7] = regs->r23; 3.52 + vcpu->arch.arch_vmx.stub_saved[8] = regs->r24; 3.53 + vcpu->arch.arch_vmx.stub_saved[9] = regs->r25; 3.54 + vcpu->arch.arch_vmx.stub_saved[10] = regs->r26; 3.55 + vcpu->arch.arch_vmx.stub_saved[11] = regs->r27; 3.56 + vcpu->arch.arch_vmx.stub_saved[12] = regs->r28; 3.57 + vcpu->arch.arch_vmx.stub_saved[13] = regs->r29; 3.58 + vcpu->arch.arch_vmx.stub_saved[14] = regs->r30; 3.59 + vcpu->arch.arch_vmx.stub_saved[15] = regs->r31; 3.60 + vcpu->arch.arch_vmx.stub_nats = 3.61 + (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff; 3.62 + 3.63 + /* Context. */ 3.64 + regs->r28 = regs->cr_iip; 3.65 + regs->r29 = psr; 3.66 + regs->r30 = regs->cr_ifs; 3.67 + 3.68 + regs->cr_ifs = 0; // pre-cover 3.69 + 3.70 + regs->cr_iip = vcpu->arch.event_callback_ip; 3.71 + regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT); 3.72 + 3.73 + /* Parameters. */ 3.74 + regs->r16 = 0; 3.75 + regs->r17 = vcpu->arch.arch_vmx.stub_buffer; 3.76 + 3.77 + /* Mask events. */ 3.78 + vcpu->vcpu_info->evtchn_upcall_mask = 1; 3.79 + 3.80 + debugger_event(XEN_IA64_DEBUG_ON_EVENT); 3.81 + 3.82 + return regs; 3.83 +} 3.84 + 3.85 +void 3.86 +sioemu_callback_return (void) 3.87 +{ 3.88 + VCPU *vcpu = current; 3.89 + REGS *regs = vcpu_regs(vcpu); 3.90 + u64 cmd = regs->r16; 3.91 + u64 arg1 = regs->r19; 3.92 + u64 arg2 = regs->r20; 3.93 + u64 arg3 = regs->r21; 3.94 + 3.95 + if ((cmd & ~0x1UL) != 0) 3.96 + panic_domain (NULL, 3.97 + "sioemu_callback_return: bad operation (%lx)\n", cmd); 3.98 + 3.99 + /* First restore registers. */ 3.100 + regs->cr_iip = regs->r28; 3.101 + regs->cr_ifs = regs->r30; 3.102 + vmx_vcpu_set_psr (vcpu, regs->r29); 3.103 + 3.104 + regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT); 3.105 + regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT; 3.106 + 3.107 + regs->r16 = vcpu->arch.arch_vmx.stub_saved[0]; 3.108 + regs->r17 = vcpu->arch.arch_vmx.stub_saved[1]; 3.109 + regs->r18 = vcpu->arch.arch_vmx.stub_saved[2]; 3.110 + regs->r19 = vcpu->arch.arch_vmx.stub_saved[3]; 3.111 + regs->r20 = vcpu->arch.arch_vmx.stub_saved[4]; 3.112 + regs->r21 = vcpu->arch.arch_vmx.stub_saved[5]; 3.113 + regs->r22 = vcpu->arch.arch_vmx.stub_saved[6]; 3.114 + regs->r23 = vcpu->arch.arch_vmx.stub_saved[7]; 3.115 + regs->r24 = vcpu->arch.arch_vmx.stub_saved[8]; 3.116 + regs->r25 = vcpu->arch.arch_vmx.stub_saved[9]; 3.117 + regs->r26 = vcpu->arch.arch_vmx.stub_saved[10]; 3.118 + regs->r27 = vcpu->arch.arch_vmx.stub_saved[11]; 3.119 + regs->r28 = vcpu->arch.arch_vmx.stub_saved[12]; 3.120 + regs->r29 = vcpu->arch.arch_vmx.stub_saved[13]; 3.121 + regs->r30 = vcpu->arch.arch_vmx.stub_saved[14]; 3.122 + regs->r31 = vcpu->arch.arch_vmx.stub_saved[15]; 3.123 + 3.124 + /* Unmask events. */ 3.125 + vcpu->vcpu_info->evtchn_upcall_mask = 0; 3.126 + 3.127 + /* Then apply commands. */ 3.128 + if (cmd & 1) { 3.129 + emulate_io_update (vcpu, arg1, arg2, arg3); 3.130 + } 3.131 +} 3.132 + 3.133 +void 3.134 +sioemu_deliver_event (void) 3.135 +{ 3.136 + REGS *regs; 3.137 + 3.138 + regs = sioemu_deliver (); 3.139 + 3.140 + regs->r16 = 0; 3.141 +} 3.142 + 3.143 +void 3.144 +sioemu_io_emulate (unsigned long padr, unsigned long data, 3.145 + unsigned long data1, unsigned long word) 3.146 +{ 3.147 + REGS *regs; 3.148 + 3.149 + regs = sioemu_deliver (); 3.150 + regs->r16 = 1; 3.151 + regs->r19 = padr; 3.152 + regs->r20 = data; 3.153 + regs->r21 = data1; 3.154 + regs->r22 = word; 3.155 +} 3.156 + 3.157 +static int 3.158 +sioemu_add_io_physmap (struct domain *d, unsigned long start, 3.159 + unsigned long size, unsigned long type) 3.160 +{ 3.161 + unsigned long i; 3.162 + int res; 3.163 + 3.164 + /* Check type. */ 3.165 + if (type == 0 || (type & GPFN_IO_MASK) != type) 3.166 + return -EINVAL; 3.167 + if ((start & (PAGE_SIZE -1)) || (size & (PAGE_SIZE - 1))) 3.168 + return -EINVAL; 3.169 + 3.170 + /* Check area is currently unassigned. */ 3.171 + for (i = start; i < start + size; i += PAGE_SIZE) { 3.172 + unsigned long mpa = ____lookup_domain_mpa(d, i); 3.173 + if (mpa != GPFN_INV_MASK && mpa != INVALID_MFN) 3.174 + return -EBUSY; 3.175 + } 3.176 + 3.177 + /* Set. */ 3.178 + for (i = start; i < start + size; i += PAGE_SIZE) { 3.179 + res = __assign_domain_page(d, i, type, ASSIGN_writable); 3.180 + if (res != 0) 3.181 + return res; 3.182 + } 3.183 + 3.184 + return 0; 3.185 +} 3.186 + 3.187 +void 3.188 +sioemu_hypercall (struct pt_regs *regs) 3.189 +{ 3.190 + //printk ("sioemu_hypercall: r2=%lx r8=%lx r9=%lx\n", 3.191 + // regs->r2, regs->r8, regs->r9); 3.192 + 3.193 + if (current->vcpu_info->evtchn_upcall_mask == 0) 3.194 + panic_domain (NULL, "sioemu_hypercall: not in stub mode\n"); 3.195 + 3.196 + switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW) 3.197 + { 3.198 + case SIOEMU_HYPERCALL_SET_CALLBACK: 3.199 + current->arch.event_callback_ip = regs->r8; 3.200 + current->arch.arch_vmx.stub_buffer = regs->r9; 3.201 + break; 3.202 + case SIOEMU_HYPERCALL_START_FW: 3.203 + regs->cr_iip = regs->r8; 3.204 + vmx_vcpu_set_psr (current, regs->r9); 3.205 + current->vcpu_info->evtchn_upcall_mask = 0; 3.206 + break; 3.207 + case SIOEMU_HYPERCALL_ADD_IO_PHYSMAP: 3.208 + regs->r8 = sioemu_add_io_physmap (current->domain, 3.209 + regs->r8, regs->r9, regs->r10); 3.210 + break; 3.211 + case SIOEMU_HYPERCALL_GET_TIME: 3.212 + { 3.213 + uint64_t sec, nsec; 3.214 + get_wallclock (&sec, &nsec); 3.215 + regs->r8 = (sec << 30) + nsec; 3.216 + break; 3.217 + } 3.218 + default: 3.219 + panic_domain (NULL, "bad sioemu hypercall %lx\n", regs->r2); 3.220 + break; 3.221 + } 3.222 +}
4.1 --- a/xen/arch/ia64/vmx/vmx_fault.c Tue Feb 19 07:51:25 2008 -0700 4.2 +++ b/xen/arch/ia64/vmx/vmx_fault.c Tue Feb 19 08:11:22 2008 -0700 4.3 @@ -42,7 +42,6 @@ 4.4 #include <asm/privop.h> 4.5 #include <asm/ia64_int.h> 4.6 #include <asm/debugger.h> 4.7 -//#include <asm/hpsim_ssc.h> 4.8 #include <asm/dom_fw.h> 4.9 #include <asm/vmx_vcpu.h> 4.10 #include <asm/kregs.h> 4.11 @@ -53,6 +52,9 @@ 4.12 #include <xen/mm.h> 4.13 #include <asm/vmx_pal.h> 4.14 #include <asm/shadow.h> 4.15 +#include <asm/sioemu.h> 4.16 +#include <public/arch-ia64/sioemu.h> 4.17 + 4.18 /* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */ 4.19 #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034 4.20 4.21 @@ -178,34 +180,44 @@ vmx_ia64_handle_break (unsigned long ifa 4.22 show_registers(regs); 4.23 debugger_trap_fatal(0 /* don't care */, regs); 4.24 regs_increment_iip(regs); 4.25 - } else 4.26 + return IA64_NO_FAULT; 4.27 + } 4.28 #endif 4.29 - { 4.30 - if (!vmx_user_mode(regs)) { 4.31 - show_registers(regs); 4.32 - gdprintk(XENLOG_DEBUG, "%s:%d imm %lx\n", __func__, __LINE__, iim); 4.33 - ia64_fault(11 /* break fault */, isr, ifa, iim, 4.34 - 0 /* cr.itir */, 0, 0, 0, (unsigned long)regs); 4.35 + if (!vmx_user_mode(regs)) { 4.36 + show_registers(regs); 4.37 + gdprintk(XENLOG_DEBUG, "%s:%d imm %lx\n", __func__, __LINE__, iim); 4.38 + ia64_fault(11 /* break fault */, isr, ifa, iim, 4.39 + 0 /* cr.itir */, 0, 0, 0, (unsigned long)regs); 4.40 + } 4.41 + 4.42 + if (ia64_psr(regs)->cpl == 0) { 4.43 + /* Allow hypercalls only when cpl = 0. */ 4.44 + 4.45 + /* Only common hypercalls are handled by vmx_break_fault. */ 4.46 + if (iim == d->arch.breakimm) { 4.47 + ia64_hypercall(regs); 4.48 + vcpu_increment_iip(v); 4.49 + return IA64_NO_FAULT; 4.50 } 4.51 4.52 - if (ia64_psr(regs)->cpl == 0) { 4.53 - /* Allow hypercalls only when cpl = 0. */ 4.54 - 4.55 - /* normal hypercalls are handled by vmx_break_fault */ 4.56 - BUG_ON(iim == d->arch.breakimm); 4.57 - 4.58 - if (iim == DOMN_PAL_REQUEST) { 4.59 - pal_emul(v); 4.60 - vcpu_increment_iip(v); 4.61 - return IA64_NO_FAULT; 4.62 - } else if (iim == DOMN_SAL_REQUEST) { 4.63 - sal_emul(v); 4.64 - vcpu_increment_iip(v); 4.65 - return IA64_NO_FAULT; 4.66 - } 4.67 + /* normal hypercalls are handled by vmx_break_fault */ 4.68 + BUG_ON(iim == d->arch.breakimm); 4.69 + 4.70 + if (iim == DOMN_PAL_REQUEST) { 4.71 + pal_emul(v); 4.72 + vcpu_increment_iip(v); 4.73 + return IA64_NO_FAULT; 4.74 + } else if (iim == DOMN_SAL_REQUEST) { 4.75 + sal_emul(v); 4.76 + vcpu_increment_iip(v); 4.77 + return IA64_NO_FAULT; 4.78 + } else if (d->arch.is_sioemu 4.79 + && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) { 4.80 + sioemu_callback_return (); 4.81 + return IA64_NO_FAULT; 4.82 } 4.83 - vmx_reflect_interruption(ifa, isr, iim, 11, regs); 4.84 } 4.85 + vmx_reflect_interruption(ifa, isr, iim, 11, regs); 4.86 return IA64_NO_FAULT; 4.87 } 4.88 4.89 @@ -214,10 +226,11 @@ void save_banked_regs_to_vpd(VCPU *v, RE 4.90 { 4.91 unsigned long i=0UL, * src,* dst, *sunat, *dunat; 4.92 IA64_PSR vpsr; 4.93 - src=®s->r16; 4.94 - sunat=®s->eml_unat; 4.95 + 4.96 + src = ®s->r16; 4.97 + sunat = ®s->eml_unat; 4.98 vpsr.val = VCPU(v, vpsr); 4.99 - if(vpsr.bn){ 4.100 + if (vpsr.bn) { 4.101 dst = &VCPU(v, vgr[0]); 4.102 dunat =&VCPU(v, vnat); 4.103 __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;; \ 4.104 @@ -225,7 +238,7 @@ void save_banked_regs_to_vpd(VCPU *v, RE 4.105 st8 [%3] = %2;;" 4.106 ::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); 4.107 4.108 - }else{ 4.109 + } else { 4.110 dst = &VCPU(v, vbgr[0]); 4.111 // dunat =&VCPU(v, vbnat); 4.112 // __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;; 4.113 @@ -234,7 +247,7 @@ void save_banked_regs_to_vpd(VCPU *v, RE 4.114 // ::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); 4.115 4.116 } 4.117 - for(i=0; i<16; i++) 4.118 + for (i = 0; i < 16; i++) 4.119 *dst++ = *src++; 4.120 } 4.121 4.122 @@ -247,59 +260,62 @@ void leave_hypervisor_tail(void) 4.123 struct domain *d = current->domain; 4.124 struct vcpu *v = current; 4.125 4.126 - // FIXME: Will this work properly if doing an RFI??? 4.127 - if (!is_idle_domain(d) ) { // always comes from guest 4.128 -// struct pt_regs *user_regs = vcpu_regs(current); 4.129 - local_irq_enable(); 4.130 - do_softirq(); 4.131 - local_irq_disable(); 4.132 + /* FIXME: can this happen ? */ 4.133 + if (is_idle_domain(current->domain)) 4.134 + return; 4.135 4.136 - if (v->vcpu_id == 0) { 4.137 - unsigned long callback_irq = 4.138 - d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; 4.139 - 4.140 - if ( v->arch.arch_vmx.pal_init_pending ) { 4.141 - /*inject INIT interruption to guest pal*/ 4.142 - v->arch.arch_vmx.pal_init_pending = 0; 4.143 - deliver_pal_init(v); 4.144 - return; 4.145 - } 4.146 + // A softirq may generate an interrupt. So call softirq early. 4.147 + local_irq_enable(); 4.148 + do_softirq(); 4.149 + local_irq_disable(); 4.150 4.151 - /* 4.152 - * val[63:56] == 1: val[55:0] is a delivery PCI INTx line: 4.153 - * Domain = val[47:32], Bus = val[31:16], 4.154 - * DevFn = val[15: 8], IntX = val[ 1: 0] 4.155 - * val[63:56] == 0: val[55:0] is a delivery as GSI 4.156 - */ 4.157 - if (callback_irq != 0 && local_events_need_delivery()) { 4.158 - /* change level for para-device callback irq */ 4.159 - /* use level irq to send discrete event */ 4.160 - if ((uint8_t)(callback_irq >> 56) == 1) { 4.161 - /* case of using PCI INTx line as callback irq */ 4.162 - int pdev = (callback_irq >> 11) & 0x1f; 4.163 - int pintx = callback_irq & 3; 4.164 - viosapic_set_pci_irq(d, pdev, pintx, 1); 4.165 - viosapic_set_pci_irq(d, pdev, pintx, 0); 4.166 - } else { 4.167 - /* case of using GSI as callback irq */ 4.168 - viosapic_set_irq(d, callback_irq, 1); 4.169 - viosapic_set_irq(d, callback_irq, 0); 4.170 - } 4.171 - } 4.172 + // FIXME: Will this work properly if doing an RFI??? 4.173 + if (d->arch.is_sioemu) { 4.174 + if (local_events_need_delivery()) { 4.175 + sioemu_deliver_event(); 4.176 } 4.177 - 4.178 - rmb(); 4.179 - if (xchg(&v->arch.irq_new_pending, 0)) { 4.180 - v->arch.irq_new_condition = 0; 4.181 - vmx_check_pending_irq(v); 4.182 + } else if (v->vcpu_id == 0) { 4.183 + unsigned long callback_irq = 4.184 + d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; 4.185 + 4.186 + if (v->arch.arch_vmx.pal_init_pending) { 4.187 + /* inject INIT interruption to guest pal */ 4.188 + v->arch.arch_vmx.pal_init_pending = 0; 4.189 + deliver_pal_init(v); 4.190 return; 4.191 } 4.192 4.193 - if (v->arch.irq_new_condition) { 4.194 - v->arch.irq_new_condition = 0; 4.195 - vhpi_detection(v); 4.196 + /* 4.197 + * val[63:56] == 1: val[55:0] is a delivery PCI INTx line: 4.198 + * Domain = val[47:32], Bus = val[31:16], 4.199 + * DevFn = val[15: 8], IntX = val[ 1: 0] 4.200 + * val[63:56] == 0: val[55:0] is a delivery as GSI 4.201 + */ 4.202 + if (callback_irq != 0 && local_events_need_delivery()) { 4.203 + /* change level for para-device callback irq */ 4.204 + /* use level irq to send discrete event */ 4.205 + if ((uint8_t)(callback_irq >> 56) == 1) { 4.206 + /* case of using PCI INTx line as callback irq */ 4.207 + int pdev = (callback_irq >> 11) & 0x1f; 4.208 + int pintx = callback_irq & 3; 4.209 + viosapic_set_pci_irq(d, pdev, pintx, 1); 4.210 + viosapic_set_pci_irq(d, pdev, pintx, 0); 4.211 + } else { 4.212 + /* case of using GSI as callback irq */ 4.213 + viosapic_set_irq(d, callback_irq, 1); 4.214 + viosapic_set_irq(d, callback_irq, 0); 4.215 + } 4.216 } 4.217 } 4.218 + 4.219 + rmb(); 4.220 + if (xchg(&v->arch.irq_new_pending, 0)) { 4.221 + v->arch.irq_new_condition = 0; 4.222 + vmx_check_pending_irq(v); 4.223 + } else if (v->arch.irq_new_condition) { 4.224 + v->arch.irq_new_condition = 0; 4.225 + vhpi_detection(v); 4.226 + } 4.227 } 4.228 4.229 static int vmx_handle_lds(REGS* regs)
5.1 --- a/xen/arch/ia64/vmx/vmx_hypercall.c Tue Feb 19 07:51:25 2008 -0700 5.2 +++ b/xen/arch/ia64/vmx/vmx_hypercall.c Tue Feb 19 08:11:22 2008 -0700 5.3 @@ -50,12 +50,15 @@ static int hvmop_set_isa_irq_level( 5.4 if ( op.isa_irq > 15 ) 5.5 return -EINVAL; 5.6 5.7 + if ( op.domid == DOMID_SELF ) 5.8 + op.domid = current->domain->domain_id; 5.9 + 5.10 d = rcu_lock_domain_by_id(op.domid); 5.11 if ( d == NULL ) 5.12 return -ESRCH; 5.13 5.14 rc = -EPERM; 5.15 - if ( !IS_PRIV_FOR(current->domain, d) ) 5.16 + if ( !IS_PRIV_FOR(current->domain, d) && d != current->domain ) 5.17 goto out; 5.18 5.19 rc = -EINVAL; 5.20 @@ -83,12 +86,15 @@ static int hvmop_set_pci_intx_level( 5.21 if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) ) 5.22 return -EINVAL; 5.23 5.24 + if ( op.domid == DOMID_SELF ) 5.25 + op.domid = current->domain->domain_id; 5.26 + 5.27 d = rcu_lock_domain_by_id(op.domid); 5.28 if ( d == NULL ) 5.29 return -ESRCH; 5.30 5.31 rc = -EPERM; 5.32 - if ( !IS_PRIV_FOR(current->domain, d) ) 5.33 + if ( !IS_PRIV_FOR(current->domain, d) && d != current->domain ) 5.34 goto out; 5.35 5.36 rc = -EINVAL;
6.1 --- a/xen/arch/ia64/vmx/vmx_init.c Tue Feb 19 07:51:25 2008 -0700 6.2 +++ b/xen/arch/ia64/vmx/vmx_init.c Tue Feb 19 08:11:22 2008 -0700 6.3 @@ -494,9 +494,11 @@ vmx_final_setup_guest(struct vcpu *v) 6.4 if (rc) 6.5 return rc; 6.6 6.7 - rc = vmx_create_event_channels(v); 6.8 - if (rc) 6.9 - return rc; 6.10 + if (!v->domain->arch.is_sioemu) { 6.11 + rc = vmx_create_event_channels(v); 6.12 + if (rc) 6.13 + return rc; 6.14 + } 6.15 6.16 /* v->arch.schedule_tail = arch_vmx_do_launch; */ 6.17 vmx_create_vp(v); 6.18 @@ -524,6 +526,9 @@ vmx_relinquish_guest_resources(struct do 6.19 { 6.20 struct vcpu *v; 6.21 6.22 + if (d->arch.is_sioemu) 6.23 + return; 6.24 + 6.25 for_each_vcpu(d, v) 6.26 vmx_release_assist_channel(v); 6.27 6.28 @@ -579,12 +584,13 @@ int vmx_setup_platform(struct domain *d) 6.29 { 6.30 ASSERT(d != dom0); /* only for non-privileged vti domain */ 6.31 6.32 - vmx_build_io_physmap_table(d); 6.33 + if (!d->arch.is_sioemu) { 6.34 + vmx_build_io_physmap_table(d); 6.35 6.36 - vmx_init_ioreq_page(d, &d->arch.vmx_platform.ioreq); 6.37 - vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_ioreq); 6.38 - vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_pioreq); 6.39 - 6.40 + vmx_init_ioreq_page(d, &d->arch.vmx_platform.ioreq); 6.41 + vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_ioreq); 6.42 + vmx_init_ioreq_page(d, &d->arch.vmx_platform.buf_pioreq); 6.43 + } 6.44 /* TEMP */ 6.45 d->arch.vmx_platform.pib_base = 0xfee00000UL; 6.46 6.47 @@ -599,7 +605,14 @@ int vmx_setup_platform(struct domain *d) 6.48 /* Initialize iosapic model within hypervisor */ 6.49 viosapic_init(d); 6.50 6.51 - vacpi_init(d); 6.52 + if (!d->arch.is_sioemu) 6.53 + vacpi_init(d); 6.54 + 6.55 + if (d->arch.is_sioemu) { 6.56 + int i; 6.57 + for (i = 1; i < MAX_VIRT_CPUS; i++) 6.58 + d->shared_info->vcpu_info[i].evtchn_upcall_mask = 1; 6.59 + } 6.60 6.61 return 0; 6.62 } 6.63 @@ -610,6 +623,9 @@ void vmx_do_resume(struct vcpu *v) 6.64 6.65 vmx_load_state(v); 6.66 6.67 + if (v->domain->arch.is_sioemu) 6.68 + return; 6.69 + 6.70 /* stolen from hvm_do_resume() in arch/x86/hvm/hvm.c */ 6.71 /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */ 6.72 p = &get_vio(v)->vp_ioreq;
7.1 --- a/xen/arch/ia64/xen/dom0_ops.c Tue Feb 19 07:51:25 2008 -0700 7.2 +++ b/xen/arch/ia64/xen/dom0_ops.c Tue Feb 19 08:11:22 2008 -0700 7.3 @@ -114,12 +114,16 @@ long arch_do_domctl(xen_domctl_t *op, XE 7.4 ret = -EFAULT; 7.5 } 7.6 else { 7.7 - if (is_hvm_domain(d) || (ds->flags & XEN_DOMAINSETUP_hvm_guest)) { 7.8 + if (is_hvm_domain(d) 7.9 + || (ds->flags & (XEN_DOMAINSETUP_hvm_guest 7.10 + | XEN_DOMAINSETUP_sioemu_guest))) { 7.11 if (!vmx_enabled) { 7.12 printk("No VMX hardware feature for vmx domain.\n"); 7.13 ret = -EINVAL; 7.14 } else { 7.15 d->is_hvm = 1; 7.16 + if (ds->flags & XEN_DOMAINSETUP_sioemu_guest) 7.17 + d->arch.is_sioemu = 1; 7.18 xen_ia64_set_convmem_end(d, ds->maxmem); 7.19 ret = vmx_setup_platform(d); 7.20 }
8.1 --- a/xen/arch/ia64/xen/hypercall.c Tue Feb 19 07:51:25 2008 -0700 8.2 +++ b/xen/arch/ia64/xen/hypercall.c Tue Feb 19 08:11:22 2008 -0700 8.3 @@ -33,6 +33,8 @@ 8.4 #include <xen/event.h> 8.5 #include <xen/perfc.h> 8.6 #include <public/arch-ia64/debug_op.h> 8.7 +#include <asm/sioemu.h> 8.8 +#include <public/arch-ia64/sioemu.h> 8.9 8.10 static IA64FAULT 8.11 xen_hypercall (struct pt_regs *regs) 8.12 @@ -222,7 +224,8 @@ ia64_hypercall(struct pt_regs *regs) 8.13 regs->r10 = fpswa_ret.err1; 8.14 regs->r11 = fpswa_ret.err2; 8.15 break; 8.16 - case __HYPERVISOR_opt_feature: { 8.17 + case __HYPERVISOR_opt_feature: 8.18 + { 8.19 XEN_GUEST_HANDLE(void) arg; 8.20 struct xen_ia64_opt_feature optf; 8.21 set_xen_guest_handle(arg, (void*)(vcpu_get_gr(v, 32))); 8.22 @@ -232,6 +235,9 @@ ia64_hypercall(struct pt_regs *regs) 8.23 regs->r8 = -EFAULT; 8.24 break; 8.25 } 8.26 + case FW_HYPERCALL_SIOEMU: 8.27 + sioemu_hypercall(regs); 8.28 + break; 8.29 default: 8.30 printk("unknown ia64 fw hypercall %lx\n", regs->r2); 8.31 regs->r8 = do_ni_hypercall();
9.1 --- a/xen/arch/ia64/xen/xensetup.c Tue Feb 19 07:51:25 2008 -0700 9.2 +++ b/xen/arch/ia64/xen/xensetup.c Tue Feb 19 08:11:22 2008 -0700 9.3 @@ -693,6 +693,9 @@ void arch_get_xen_caps(xen_capabilities_ 9.4 { 9.5 snprintf(s, sizeof(s), "hvm-%d.%d-ia64 ", major, minor); 9.6 safe_strcat(*info, s); 9.7 + 9.8 + snprintf(s, sizeof(s), "hvm-%d.%d-ia64-sioemu ", major, minor); 9.9 + safe_strcat(*info, s); 9.10 } 9.11 } 9.12
10.1 --- a/xen/arch/ia64/xen/xentime.c Tue Feb 19 07:51:25 2008 -0700 10.2 +++ b/xen/arch/ia64/xen/xentime.c Tue Feb 19 08:11:22 2008 -0700 10.3 @@ -252,3 +252,10 @@ struct tm wallclock_time(void) 10.4 do_div(seconds, NSEC_PER_SEC); 10.5 return gmtime(seconds); 10.6 } 10.7 + 10.8 +void get_wallclock(uint64_t *sec, uint64_t *nsec) 10.9 +{ 10.10 + uint64_t nano = NOW() + wc_nsec; 10.11 + *sec = wc_sec + nano / NSEC_PER_SEC; 10.12 + *nsec = nano % NSEC_PER_SEC; 10.13 +}
11.1 --- a/xen/include/asm-ia64/dom_fw.h Tue Feb 19 07:51:25 2008 -0700 11.2 +++ b/xen/include/asm-ia64/dom_fw.h Tue Feb 19 08:11:22 2008 -0700 11.3 @@ -168,6 +168,9 @@ 11.4 /* Set the shared_info base virtual address. */ 11.5 #define FW_HYPERCALL_SET_SHARED_INFO_VA 0x600UL 11.6 11.7 +/* Hvmstub hypercalls. See details in hvm_stub.h */ 11.8 +#define FW_HYPERCALL_SIOEMU 0x800UL 11.9 + 11.10 /* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above 11.11 are for the architecture. 11.12 Note: this limit was defined by Xen/ia64 (and not by Xen).
12.1 --- a/xen/include/asm-ia64/domain.h Tue Feb 19 07:51:25 2008 -0700 12.2 +++ b/xen/include/asm-ia64/domain.h Tue Feb 19 08:11:22 2008 -0700 12.3 @@ -133,12 +133,13 @@ struct arch_domain { 12.4 /* Flags. */ 12.5 union { 12.6 unsigned long flags; 12.7 + struct { 12.8 + unsigned int is_sioemu : 1; 12.9 #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT 12.10 - struct { 12.11 unsigned int has_pervcpu_vhpt : 1; 12.12 unsigned int vhpt_size_log2 : 6; 12.13 +#endif 12.14 }; 12.15 -#endif 12.16 }; 12.17 12.18 /* maximum metaphysical address of conventional memory */
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/xen/include/asm-ia64/sioemu.h Tue Feb 19 08:11:22 2008 -0700 13.3 @@ -0,0 +1,30 @@ 13.4 +/****************************************************************************** 13.5 + * sioemu.h 13.6 + * 13.7 + * Copyright (c) 2008 Tristan Gingold <tgingold@free.fr> 13.8 + * 13.9 + * This program is free software; you can redistribute it and/or modify 13.10 + * it under the terms of the GNU General Public License as published by 13.11 + * the Free Software Foundation; either version 2 of the License, or 13.12 + * (at your option) any later version. 13.13 + * 13.14 + * This program is distributed in the hope that it will be useful, 13.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13.17 + * GNU General Public License for more details. 13.18 + * 13.19 + * You should have received a copy of the GNU General Public License 13.20 + * along with this program; if not, write to the Free Software 13.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 13.22 + * 13.23 + */ 13.24 + 13.25 +#ifndef __ASM_SIOEMU_H_ 13.26 +#define __ASM_SIOEMU_H_ 13.27 +extern void sioemu_hypercall (struct pt_regs *regs); 13.28 +extern void sioemu_deliver_event (void); 13.29 +extern void sioemu_callback_return (void); 13.30 +extern void sioemu_io_emulate (unsigned long padr, unsigned long data, 13.31 + unsigned long data1, unsigned long word); 13.32 + 13.33 +#endif /* __ASM_SIOEMU_H_ */
14.1 --- a/xen/include/asm-ia64/time.h Tue Feb 19 07:51:25 2008 -0700 14.2 +++ b/xen/include/asm-ia64/time.h Tue Feb 19 08:11:22 2008 -0700 14.3 @@ -7,4 +7,6 @@ 14.4 struct tm; 14.5 struct tm wallclock_time(void); 14.6 14.7 +void get_wallclock(uint64_t *sec, uint64_t *nsec); 14.8 + 14.9 #endif /* _ASM_TIME_H_ */
15.1 --- a/xen/include/asm-ia64/vmmu.h Tue Feb 19 07:51:25 2008 -0700 15.2 +++ b/xen/include/asm-ia64/vmmu.h Tue Feb 19 08:11:22 2008 -0700 15.3 @@ -197,6 +197,7 @@ extern void free_domain_tlb(struct vcpu 15.4 extern thash_data_t * vhpt_lookup(u64 va); 15.5 extern unsigned long fetch_code(struct vcpu *vcpu, u64 gip, IA64_BUNDLE *pbundle); 15.6 extern void emulate_io_inst(struct vcpu *vcpu, u64 padr, u64 ma); 15.7 +extern void emulate_io_update(struct vcpu *vcpu, u64 word, u64 d, u64 d1); 15.8 extern int vhpt_enabled(struct vcpu *vcpu, uint64_t vadr, vhpt_ref_t ref); 15.9 extern void thash_vhpt_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa, 15.10 int type);
16.1 --- a/xen/include/asm-ia64/vmx_vpd.h Tue Feb 19 07:51:25 2008 -0700 16.2 +++ b/xen/include/asm-ia64/vmx_vpd.h Tue Feb 19 08:11:22 2008 -0700 16.3 @@ -74,6 +74,9 @@ struct arch_vmx_struct { 16.4 unsigned long ivt_current; 16.5 struct ivt_debug ivt_debug[IVT_DEBUG_MAX]; 16.6 #endif 16.7 + unsigned long stub_saved[16]; 16.8 + unsigned long stub_buffer; 16.9 + unsigned int stub_nats; 16.10 }; 16.11 16.12 #define VMX_DOMAIN(v) v->arch.arch_vmx.flags
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/xen/include/public/arch-ia64/sioemu.h Tue Feb 19 08:11:22 2008 -0700 17.3 @@ -0,0 +1,42 @@ 17.4 +/****************************************************************************** 17.5 + * sioemu.h 17.6 + * 17.7 + * Copyright (c) 2008 Tristan Gingold <tgingold@free.fr> 17.8 + * 17.9 + * This program is free software; you can redistribute it and/or modify 17.10 + * it under the terms of the GNU General Public License as published by 17.11 + * the Free Software Foundation; either version 2 of the License, or 17.12 + * (at your option) any later version. 17.13 + * 17.14 + * This program is distributed in the hope that it will be useful, 17.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17.17 + * GNU General Public License for more details. 17.18 + * 17.19 + * You should have received a copy of the GNU General Public License 17.20 + * along with this program; if not, write to the Free Software 17.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17.22 + * 17.23 + */ 17.24 + 17.25 +#ifndef __XEN_PUBLIC_IA64_SIOEMU_H__ 17.26 +#define __XEN_PUBLIC_IA64_SIOEMU_H__ 17.27 + 17.28 +/* Defines the callback entry point. r8=ip, r9=data. 17.29 + Must be called per-vcpu. */ 17.30 +#define SIOEMU_HYPERCALL_SET_CALLBACK 0x01 17.31 + 17.32 +/* Finish sioemu fw initialization and start firmware. r8=ip. */ 17.33 +#define SIOEMU_HYPERCALL_START_FW 0x02 17.34 + 17.35 +/* Add IO pages in physmap. */ 17.36 +#define SIOEMU_HYPERCALL_ADD_IO_PHYSMAP 0x03 17.37 + 17.38 +/* Get wallclock time. */ 17.39 +#define SIOEMU_HYPERCALL_GET_TIME 0x04 17.40 + 17.41 +/* Return from callback. r16=0. 17.42 + Unmask vcpu events. */ 17.43 +#define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01 17.44 + 17.45 +#endif /* __XEN_PUBLIC_IA64_SIOEMU_H__ */
18.1 --- a/xen/include/public/domctl.h Tue Feb 19 07:51:25 2008 -0700 18.2 +++ b/xen/include/public/domctl.h Tue Feb 19 08:11:22 2008 -0700 18.3 @@ -376,6 +376,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_hyper 18.4 #define XEN_DOMAINSETUP_hvm_guest (1UL<<_XEN_DOMAINSETUP_hvm_guest) 18.5 #define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save) */ 18.6 #define XEN_DOMAINSETUP_query (1UL<<_XEN_DOMAINSETUP_query) 18.7 +#define _XEN_DOMAINSETUP_sioemu_guest 2 18.8 +#define XEN_DOMAINSETUP_sioemu_guest (1UL<<_XEN_DOMAINSETUP_sioemu_guest) 18.9 typedef struct xen_domctl_arch_setup { 18.10 uint64_aligned_t flags; /* XEN_DOMAINSETUP_* */ 18.11 #ifdef __ia64__