From 6e86084cbc95a19a9fa46f6eeff3a5009699e580 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Thu, 12 Apr 2007 12:48:27 +0100 Subject: [PATCH 01/21] Ensure xenapi create passes in values even if unused signed-off-by: Tom Wilkie --- tools/python/xen/xm/xenapi_create.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py index e441de8026..19ced84460 100644 --- a/tools/python/xen/xm/xenapi_create.py +++ b/tools/python/xen/xm/xenapi_create.py @@ -48,7 +48,7 @@ def get_name_description(node): def get_text_in_child_node(node, child): tag_node = node.getElementsByTagName(child)[0] - return tag_node.nodeValue + return " ".join([child.nodeValue for child in tag_node.childNodes]) def get_child_node_attribute(node, child, attribute): tag_node = node.getElementsByTagName(child)[0] @@ -264,7 +264,23 @@ class xenapi_create: "platform": get_child_nodes_as_dict(vm, "platform", "key", "value"), "other_config": - get_child_nodes_as_dict(vm, "other_config", "key", "value") + get_child_nodes_as_dict(vm, "other_config", "key", "value"), + "PV_bootloader": + "", + "PV_kernel": + "", + "PV_ramdisk": + "", + "PV_args": + "", + "PV_bootloader_args": + "", + "HVM_boot_policy": + "", + "HVM_boot_params": + {}, + "PCI_bus": + "" } if len(vm.getElementsByTagName("pv")) > 0: @@ -494,7 +510,7 @@ class sxp2xml: # Make version tag version = document.createElement("version") - version.appendChild(document.createTextNode("1.0")) + version.appendChild(document.createTextNode("0")) vm.appendChild(version) # Make pv or hvm tag From 833623e78abfbf24956ee374089a13dc4efaaa71 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 12 Apr 2007 15:02:03 +0100 Subject: [PATCH 02/21] [HVM] Save/restore: save HVM GPRs and DRs with the rest of the CPU state and remove the use of xc_vcpu_getcontext() from HVM save/restore. Also fixes loss of CR2, DR6 and DR7 contents across HVM save/restore. Signed-off-by: Tim Deegan --- tools/libxc/xc_domain_restore.c | 20 --------- tools/libxc/xc_domain_save.c | 64 +++++++++------------------ xen/arch/x86/hvm/hvm.c | 76 ++++++++++++++++++++++++++++++++- xen/arch/x86/hvm/svm/svm.c | 19 ++++++--- xen/arch/x86/hvm/vmx/vmx.c | 21 +++++---- xen/include/public/hvm/save.h | 35 +++++++++++++-- 6 files changed, 153 insertions(+), 82 deletions(-) diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 1159776f4f..1b52c90e5b 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -696,26 +696,6 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn); *store_mfn = magic_pfns[2]; - /* Read vcpu contexts */ - for ( i = 0; i <= max_vcpu_id; i++ ) - { - if ( !(vcpumap & (1ULL << i)) ) - continue; - - if ( !read_exact(io_fd, &(ctxt), sizeof(ctxt)) ) - { - ERROR("error read vcpu context.\n"); - goto out; - } - - if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) - { - ERROR("Could not set vcpu context, rc=%d", rc); - goto out; - } - rc = 1; - } - /* Read HVM context */ if ( !read_exact(io_fd, &rec_len, sizeof(uint32_t)) ) { diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index f8b51c2713..ba7e005819 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -378,8 +378,7 @@ static int analysis_phase(int xc_handle, uint32_t domid, int p2m_size, static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, - int dom, xc_dominfo_t *info, - vcpu_guest_context_t *ctxt) + int dom, xc_dominfo_t *info) { int i = 0; @@ -397,10 +396,6 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, return -1; } - if ( xc_vcpu_getcontext(xc_handle, dom, 0, ctxt) ) - ERROR("Could not get vcpu context"); - - if ( info->dying ) { ERROR("domain is dying"); @@ -663,10 +658,11 @@ static xen_pfn_t *xc_map_m2p(int xc_handle, static xen_pfn_t *map_and_save_p2m_table(int xc_handle, int io_fd, uint32_t dom, - vcpu_guest_context_t *ctxt, unsigned long p2m_size, shared_info_t *live_shinfo) { + vcpu_guest_context_t ctxt; + /* Double and single indirect references to the live P2M table */ xen_pfn_t *live_p2m_frame_list_list = NULL; xen_pfn_t *live_p2m_frame_list = NULL; @@ -730,13 +726,19 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle, } } + if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) ) + { + ERROR("Could not get vcpu context"); + goto out; + } + /* * Write an extended-info structure to inform the restore code that * a PAE guest understands extended CR3 (PDPTs above 4GB). Turns off * slow paths in the restore code. */ if ( (pt_levels == 3) && - (ctxt->vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) ) + (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) ) { unsigned long signature = ~0UL; uint32_t tot_sz = sizeof(struct vcpu_guest_context) + 8; @@ -746,7 +748,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle, !write_exact(io_fd, &tot_sz, sizeof(tot_sz)) || !write_exact(io_fd, &chunk_sig, 4) || !write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) || - !write_exact(io_fd, ctxt, sizeof(*ctxt)) ) + !write_exact(io_fd, &ctxt, sizeof(ctxt)) ) { ERROR("write: extended info"); goto out; @@ -853,11 +855,6 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, return 1; } - if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) ) - { - ERROR("Could not get vcpu context"); - goto out; - } shared_info_frame = info.shared_info_frame; /* Map the shared info frame */ @@ -900,7 +897,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, else { /* This is a non-live suspend. Suspend the domain .*/ - if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt) ) + if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) ) { ERROR("Domain appears not to have suspended"); goto out; @@ -999,7 +996,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Map the P2M table, and write the list of P2M frames */ live_p2m = map_and_save_p2m_table(xc_handle, io_fd, dom, - &ctxt, p2m_size, live_shinfo); + p2m_size, live_shinfo); if ( live_p2m == NULL ) { ERROR("Failed to map/save the p2m frame list"); @@ -1304,17 +1301,13 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, DPRINTF("Start last iteration\n"); last_iter = 1; - if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, - &ctxt) ) + if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) ) { ERROR("Domain appears not to have suspended"); goto out; } - DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n", - info.shared_info_frame, - (unsigned long)ctxt.user_regs.eip, - (unsigned long)ctxt.user_regs.edx); + DPRINTF("SUSPEND shinfo %08lx\n", info.shared_info_frame); } if ( xc_shadow_control(xc_handle, dom, @@ -1410,27 +1403,6 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* Save vcpu contexts */ - - for ( i = 0; i <= info.max_vcpu_id; i++ ) - { - if ( !(vcpumap & (1ULL << i)) ) - continue; - - if ( xc_vcpu_getcontext(xc_handle, dom, i, &ctxt) ) - { - ERROR("HVM:Could not get vcpu context"); - goto out; - } - - DPRINTF("write vcpu %d context.\n", i); - if ( !write_exact(io_fd, &(ctxt), sizeof(ctxt)) ) - { - ERROR("write vcpu context failed!\n"); - goto out; - } - } - /* Get HVM context from Xen and save it too */ if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, hvm_buf_size)) == -1 ) @@ -1494,6 +1466,12 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } } + if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) ) + { + ERROR("Could not get vcpu context"); + goto out; + } + /* Canonicalise the suspend-record frame number. */ if ( !translate_mfn_to_pfn(&ctxt.user_regs.edx) ) { diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 5cb283bf2e..7636da5614 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -191,6 +191,7 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) { struct vcpu *v; struct hvm_hw_cpu ctxt; + struct vcpu_guest_context *vc; for_each_vcpu(d, v) { @@ -199,7 +200,40 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) if ( test_bit(_VPF_down, &v->pause_flags) ) continue; + /* Architecture-specific vmcs/vmcb bits */ hvm_funcs.save_cpu_ctxt(v, &ctxt); + + /* Other vcpu register state */ + vc = &v->arch.guest_context; + if ( vc->flags & VGCF_i387_valid ) + memcpy(ctxt.fpu_regs, &vc->fpu_ctxt, sizeof(ctxt.fpu_regs)); + else + memset(ctxt.fpu_regs, 0, sizeof(ctxt.fpu_regs)); + ctxt.rax = vc->user_regs.eax; + ctxt.rbx = vc->user_regs.ebx; + ctxt.rcx = vc->user_regs.ecx; + ctxt.rdx = vc->user_regs.edx; + ctxt.rbp = vc->user_regs.ebp; + ctxt.rsi = vc->user_regs.esi; + ctxt.rdi = vc->user_regs.edi; + /* %rsp handled by arch-specific call above */ +#ifdef __x86_64__ + ctxt.r8 = vc->user_regs.r8; + ctxt.r9 = vc->user_regs.r9; + ctxt.r10 = vc->user_regs.r10; + ctxt.r11 = vc->user_regs.r11; + ctxt.r12 = vc->user_regs.r12; + ctxt.r13 = vc->user_regs.r13; + ctxt.r14 = vc->user_regs.r14; + ctxt.r15 = vc->user_regs.r15; +#endif + ctxt.dr0 = vc->debugreg[0]; + ctxt.dr1 = vc->debugreg[1]; + ctxt.dr2 = vc->debugreg[2]; + ctxt.dr3 = vc->debugreg[3]; + ctxt.dr6 = vc->debugreg[6]; + ctxt.dr7 = vc->debugreg[7]; + if ( hvm_save_entry(CPU, v->vcpu_id, h, &ctxt) != 0 ) return 1; } @@ -208,9 +242,10 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) { - int vcpuid; + int vcpuid, rc; struct vcpu *v; struct hvm_hw_cpu ctxt; + struct vcpu_guest_context *vc; /* Which vcpu is this? */ vcpuid = hvm_load_instance(h); @@ -219,13 +254,52 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) gdprintk(XENLOG_ERR, "HVM restore: domain has no vcpu %u\n", vcpuid); return -EINVAL; } + vc = &v->arch.guest_context; + + /* Need to init this vcpu before loading its contents */ + LOCK_BIGLOCK(d); + if ( !v->is_initialised ) + if ( (rc = boot_vcpu(d, vcpuid, vc)) != 0 ) + return rc; + UNLOCK_BIGLOCK(d); if ( hvm_load_entry(CPU, h, &ctxt) != 0 ) return -EINVAL; + /* Architecture-specific vmcs/vmcb bits */ if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 ) return -EINVAL; + /* Other vcpu register state */ + memcpy(&vc->fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs)); + vc->user_regs.eax = ctxt.rax; + vc->user_regs.ebx = ctxt.rbx; + vc->user_regs.ecx = ctxt.rcx; + vc->user_regs.edx = ctxt.rdx; + vc->user_regs.ebp = ctxt.rbp; + vc->user_regs.esi = ctxt.rsi; + vc->user_regs.edi = ctxt.rdi; + vc->user_regs.esp = ctxt.rsp; +#ifdef __x86_64__ + vc->user_regs.r8; = ctxt.r8; + vc->user_regs.r9; = ctxt.r9; + vc->user_regs.r10 = ctxt.r10; + vc->user_regs.r11 = ctxt.r11; + vc->user_regs.r12 = ctxt.r12; + vc->user_regs.r13 = ctxt.r13; + vc->user_regs.r14 = ctxt.r14; + vc->user_regs.r15 = ctxt.r15; +#endif + vc->debugreg[0] = ctxt.dr0; + vc->debugreg[1] = ctxt.dr1; + vc->debugreg[2] = ctxt.dr2; + vc->debugreg[3] = ctxt.dr3; + vc->debugreg[6] = ctxt.dr6; + vc->debugreg[7] = ctxt.dr7; + + vc->flags = VGCF_i387_valid | VGCF_online; + v->fpu_initialised = 1; + /* Auxiliary processors should be woken immediately. */ if ( test_and_clear_bit(_VPF_down, &v->pause_flags) ) vcpu_wake(v); diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index ae0b42ae66..cf3f9c647f 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -233,7 +233,7 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - c->eip = vmcb->rip; + c->rip = vmcb->rip; #ifdef HVM_DEBUG_SUSPEND printk("%s: eip=0x%"PRIx64".\n", @@ -241,10 +241,11 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) inst_len, c->eip); #endif - c->esp = vmcb->rsp; - c->eflags = vmcb->rflags; + c->rsp = vmcb->rsp; + c->rflags = vmcb->rflags; c->cr0 = v->arch.hvm_svm.cpu_shadow_cr0; + c->cr2 = v->arch.hvm_svm.cpu_cr2; c->cr3 = v->arch.hvm_svm.cpu_cr3; c->cr4 = v->arch.hvm_svm.cpu_shadow_cr4; @@ -315,15 +316,17 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) unsigned long mfn, old_base_mfn; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - vmcb->rip = c->eip; - vmcb->rsp = c->esp; - vmcb->rflags = c->eflags; + vmcb->rip = c->rip; + vmcb->rsp = c->rsp; + vmcb->rflags = c->rflags; v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0; vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET; if ( !paging_mode_hap(v->domain) ) vmcb->cr0 |= X86_CR0_PG; + v->arch.hvm_svm.cpu_cr2 = c->cr2; + #ifdef HVM_DEBUG_SUSPEND printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", __func__, @@ -421,6 +424,9 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmcb->sysenter_esp = c->sysenter_esp; vmcb->sysenter_eip = c->sysenter_eip; + vmcb->dr6 = c->dr6; + vmcb->dr7 = c->dr7; + paging_update_paging_modes(v); return 0; @@ -440,6 +446,7 @@ void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) data->msr_cstar = vmcb->cstar; data->msr_syscall_mask = vmcb->sfmask; data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer; + data->msr_flags = -1ULL; data->tsc = hvm_get_guest_time(v); } diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index b4cfe17b29..1c47aadebc 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -370,11 +370,12 @@ static inline void __restore_debug_registers(struct vcpu *v) int vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) { - c->eip = __vmread(GUEST_RIP); - c->esp = __vmread(GUEST_RSP); - c->eflags = __vmread(GUEST_RFLAGS); + c->rip = __vmread(GUEST_RIP); + c->rsp = __vmread(GUEST_RSP); + c->rflags = __vmread(GUEST_RFLAGS); c->cr0 = v->arch.hvm_vmx.cpu_shadow_cr0; + c->cr2 = v->arch.hvm_vmx.cpu_cr2; c->cr3 = v->arch.hvm_vmx.cpu_cr3; c->cr4 = v->arch.hvm_vmx.cpu_shadow_cr4; @@ -444,13 +445,15 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmx_vmcs_enter(v); - __vmwrite(GUEST_RIP, c->eip); - __vmwrite(GUEST_RSP, c->esp); - __vmwrite(GUEST_RFLAGS, c->eflags); + __vmwrite(GUEST_RIP, c->rip); + __vmwrite(GUEST_RSP, c->rsp); + __vmwrite(GUEST_RFLAGS, c->rflags); v->arch.hvm_vmx.cpu_shadow_cr0 = c->cr0; __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0); + v->arch.hvm_vmx.cpu_cr2 = c->cr2; + #ifdef HVM_DEBUG_SUSPEND printk("vmx_vmcs_restore: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", c->cr3, @@ -555,6 +558,8 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) __vmwrite(GUEST_SYSENTER_ESP, c->sysenter_esp); __vmwrite(GUEST_SYSENTER_EIP, c->sysenter_eip); + __vmwrite(GUEST_DR7, c->dr7); + vmx_vmcs_exit(v); paging_update_paging_modes(v); @@ -590,7 +595,7 @@ void vmx_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) data->shadow_gs = guest_state->shadow_gs; /* save msrs */ - data->flags = guest_flags; + data->msr_flags = guest_flags; data->msr_lstar = guest_state->msrs[VMX_INDEX_MSR_LSTAR]; data->msr_star = guest_state->msrs[VMX_INDEX_MSR_STAR]; data->msr_cstar = guest_state->msrs[VMX_INDEX_MSR_CSTAR]; @@ -607,7 +612,7 @@ void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state; /* restore msrs */ - guest_state->flags = data->flags; + guest_state->flags = data->msr_flags; guest_state->msrs[VMX_INDEX_MSR_LSTAR] = data->msr_lstar; guest_state->msrs[VMX_INDEX_MSR_STAR] = data->msr_star; guest_state->msrs[VMX_INDEX_MSR_CSTAR] = data->msr_cstar; diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h index c921b50a78..14f120f9a6 100644 --- a/xen/include/public/hvm/save.h +++ b/xen/include/public/hvm/save.h @@ -87,13 +87,40 @@ DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header); */ struct hvm_hw_cpu { - uint64_t eip; - uint64_t esp; - uint64_t eflags; + uint8_t fpu_regs[512]; + + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rbp; + uint64_t rsi; + uint64_t rdi; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + + uint64_t rip; + uint64_t rflags; + uint64_t cr0; + uint64_t cr2; uint64_t cr3; uint64_t cr4; + uint64_t dr0; + uint64_t dr1; + uint64_t dr2; + uint64_t dr3; + uint64_t dr6; + uint64_t dr7; + uint32_t cs_sel; uint32_t ds_sel; uint32_t es_sel; @@ -142,9 +169,9 @@ struct hvm_hw_cpu { /* msr for em64t */ uint64_t shadow_gs; - uint64_t flags; /* msr content saved/restored. */ + uint64_t msr_flags; uint64_t msr_lstar; uint64_t msr_star; uint64_t msr_cstar; From 68c5ac07e0e7ed05e80305497cf9dc16b797cdac Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 12 Apr 2007 15:07:20 +0100 Subject: [PATCH 03/21] [HVM] Fix typo that broke x86_64 build Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/hvm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 7636da5614..426eb40471 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -281,8 +281,8 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) vc->user_regs.edi = ctxt.rdi; vc->user_regs.esp = ctxt.rsp; #ifdef __x86_64__ - vc->user_regs.r8; = ctxt.r8; - vc->user_regs.r9; = ctxt.r9; + vc->user_regs.r8 = ctxt.r8; + vc->user_regs.r9 = ctxt.r9; vc->user_regs.r10 = ctxt.r10; vc->user_regs.r11 = ctxt.r11; vc->user_regs.r12 = ctxt.r12; From 8ac66209bed5cc71076c14432e5d2a8e5d1b1db4 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Thu, 12 Apr 2007 15:44:02 +0100 Subject: [PATCH 04/21] Add PyXML requirement for xm via XenAPI to docs signed-off-by: Tom Wilkie --- README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README b/README index c382918db4..705cec5db3 100644 --- a/README +++ b/README @@ -199,3 +199,7 @@ Xend (the Xen daemon) has the following runtime dependencies: * For optional PAM support, PyPAM: URL: http://www.pangalactic.org/PyPAM/ Debian: python-pam + + * For optional XenAPI support in XM, PyXML: + URL: http://pyxml.sourceforge.net + YUM: PyXML From 1db798cdbeea651f5c671c646ee0fc3b15a6dc0e Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 12 Apr 2007 15:54:59 +0100 Subject: [PATCH 05/21] [HVM] Save/restore: catch more error cases in the tools Signed-off-by: Tim Deegan --- tools/libxc/xc_domain_restore.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 1b52c90e5b..aaabed6d42 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -688,12 +688,21 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, ERROR("error zeroing magic pages"); goto out; } - - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, magic_pfns[0]); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, magic_pfns[2]); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae); - xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn); + + if ( (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_IOREQ_PFN, magic_pfns[0])) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1])) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_STORE_PFN, magic_pfns[2])) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_PAE_ENABLED, pae)) + || (rc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_STORE_EVTCHN, store_evtchn)) ) + { + ERROR("error setting HVM params: %i", rc); + goto out; + } *store_mfn = magic_pfns[2]; /* Read HVM context */ From accdf061d4bfd9686417c223000848034dd48dd3 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Thu, 12 Apr 2007 10:27:05 -0500 Subject: [PATCH 06/21] [XEN][POWERPC] Fix xchg macro. Signed-off-by: Jerone Young Signed-off-by: Hollis Blanchard --- xen/include/asm-powerpc/system.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xen/include/asm-powerpc/system.h b/xen/include/asm-powerpc/system.h index 7eb41c9325..c0f21c64d0 100644 --- a/xen/include/asm-powerpc/system.h +++ b/xen/include/asm-powerpc/system.h @@ -28,7 +28,11 @@ #include #include -#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) +#define xchg(ptr,x) \ +({ \ + __typeof__(*(ptr)) _x_ = (x); \ + (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ +}) static __inline__ unsigned long __xchg_u32(volatile int *m, unsigned long val) From 6547cc6bf08dbe6f084986bdd59cca89beaf569e Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Thu, 12 Apr 2007 10:42:43 -0500 Subject: [PATCH 07/21] [XEN][POWERPC] Fix garbage dom0 commandline. Debugged by Amos Waterland . Signed-off-by: Hollis Blanchard --- xen/arch/powerpc/ofd_fixup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xen/arch/powerpc/ofd_fixup.c b/xen/arch/powerpc/ofd_fixup.c index 453ce4be17..2d2ff11244 100644 --- a/xen/arch/powerpc/ofd_fixup.c +++ b/xen/arch/powerpc/ofd_fixup.c @@ -264,7 +264,7 @@ static ofdn_t ofd_chosen_props(void *m, const char *cmdline) ofdn_t n; ofdn_t p; static const char path[] = "/chosen"; - char bootargs[256]; + char bootargs[256] = { 0, }; int bsz; int sz; int rm; @@ -276,7 +276,8 @@ static ofdn_t ofd_chosen_props(void *m, const char *cmdline) &path[1], sizeof (path) - 1); } - strlcpy(bootargs, cmdline, sizeof(bootargs)); + if (cmdline) + strlcpy(bootargs, cmdline, sizeof(bootargs)); bsz = strlen(bootargs) + 1; rm = sizeof (bootargs) - bsz; From a7a2bc1a69ec2b16b984f991817eefcd4f297bc7 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Thu, 12 Apr 2007 13:05:04 -0500 Subject: [PATCH 08/21] [XEN][POWERPC] Fix debug=y build. When debug=y, we use -O0 for single-stepping. This breaks the force-link-error trick used in __xchg(), so we provide a real function to link with. Signed-off-by: Hollis Blanchard --- xen/arch/powerpc/0opt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xen/arch/powerpc/0opt.c b/xen/arch/powerpc/0opt.c index 6d85e63c9e..e029ed11eb 100644 --- a/xen/arch/powerpc/0opt.c +++ b/xen/arch/powerpc/0opt.c @@ -21,6 +21,12 @@ #include #include +extern void __xchg_called_with_bad_pointer(void); +void __xchg_called_with_bad_pointer(void) +{ + BUG(); +} + extern void __cmpxchg_called_with_bad_pointer(void); void __cmpxchg_called_with_bad_pointer(void) { From f27ff037b19a380ebe82c5433eb4995fab2ed3c6 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Thu, 12 Apr 2007 16:37:32 -0500 Subject: [PATCH 09/21] [XEN][POWERPC] Fix dom0 boot when using built-in zImage. We need to respect the ELF entry point. Signed-off-by: Jerone Young Signed-off-by: Hollis Blanchard --- xen/arch/powerpc/domain_build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/powerpc/domain_build.c b/xen/arch/powerpc/domain_build.c index 92e3c20217..d9ff09617c 100644 --- a/xen/arch/powerpc/domain_build.c +++ b/xen/arch/powerpc/domain_build.c @@ -229,7 +229,7 @@ int construct_dom0(struct domain *d, /* Load the dom0 kernel. */ elf.dest = (void *)dst; elf_load_binary(&elf); - v->arch.ctxt.pc = dst - rma; + v->arch.ctxt.pc = dst - rma + (parms.virt_entry - parms.virt_kstart); dst = ALIGN_UP(dst + parms.virt_kend, PAGE_SIZE); /* Load the initrd. */ From 8f1d9b46961a8e3a9084b4e2a9936bf56b97128c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 13 Apr 2007 11:09:58 +0100 Subject: [PATCH 10/21] libxenguest: Remove bogus weak definitions of xc_{set,get}_hvm_param(). Signed-off-by: Keir Fraser --- tools/libxc/xg_private.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index e3e0658842..37bc587477 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -198,18 +198,6 @@ __attribute__((weak)) return -1; } -__attribute__((weak)) int xc_get_hvm_param( - int handle, domid_t dom, int param, unsigned long *value) -{ - return -ENOSYS; -} - -__attribute__((weak)) int xc_set_hvm_param( - int handle, domid_t dom, int param, unsigned long value) -{ - return -ENOSYS; -} - /* * Local variables: * mode: C From 1abe8d9d1ec34d80930bb524cd398da7e6746745 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 13 Apr 2007 11:20:11 +0100 Subject: [PATCH 11/21] hvm svm: Fix nested paging to support domain save/restore. Signed-off-by: Wei Huang --- xen/arch/x86/hvm/svm/svm.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index cf3f9c647f..5f06d09c08 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -321,9 +321,7 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmcb->rflags = c->rflags; v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0; - vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET; - if ( !paging_mode_hap(v->domain) ) - vmcb->cr0 |= X86_CR0_PG; + vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET | X86_CR0_PG; v->arch.hvm_svm.cpu_cr2 = c->cr2; @@ -424,6 +422,16 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmcb->sysenter_esp = c->sysenter_esp; vmcb->sysenter_eip = c->sysenter_eip; + /* update VMCB for nested paging restore */ + if ( paging_mode_hap(v->domain) ) { + vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0; + vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4; + vmcb->cr3 = c->cr3; + vmcb->np_enable = 1; + vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */ + vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); + } + vmcb->dr6 = c->dr6; vmcb->dr7 = c->dr7; From 5e0ae4b087587433571507f711788bde1a83c2d9 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 13 Apr 2007 11:23:26 +0100 Subject: [PATCH 12/21] pygriub: Fix GPT support. - 64 bit support for starting of a GPT partition. - detect partition types precisely. Signed-off-by: KUWAMURA Shin'ya --- tools/pygrub/src/pygrub | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index 0e3cd4701d..76eb313c30 100644 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -61,13 +61,6 @@ def get_active_partition(file): if struct.unpack(" Date: Fri, 13 Apr 2007 11:28:04 +0100 Subject: [PATCH 13/21] linux: netfront contains two locking problems found by lockdep: 1. rx_lock is a normal spinlock, and tx_lock is an irq spinlock. This means that in normal use, tx_lock may be taken by an interrupt routine while rx_lock is held. However, netif_disconnect_backend takes them in the order tx_lock->rx_lock, which could lead to a deadlock. Reverse them. 2. rx_lock can also be used in softirq context, so it should be taken/released with spin_(un)lock_bh. Signed-off-by: Jeremy Fitzhardinge --- .../drivers/xen/netfront/netfront.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index d2abc56fd4..f453337246 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -622,14 +622,14 @@ static int network_open(struct net_device *dev) memset(&np->stats, 0, sizeof(np->stats)); - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); if (netfront_carrier_ok(np)) { network_alloc_rx_buffers(dev); np->rx.sring->rsp_event = np->rx.rsp_cons + 1; if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) netif_rx_schedule(dev); } - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); network_maybe_wake_tx(dev); @@ -1307,10 +1307,10 @@ static int netif_poll(struct net_device *dev, int *pbudget) int pages_flipped = 0; int err; - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); if (unlikely(!netfront_carrier_ok(np))) { - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); return 0; } @@ -1478,7 +1478,7 @@ err: local_irq_restore(flags); } - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); return more_to_do; } @@ -1520,7 +1520,7 @@ static void netif_release_rx_bufs(struct netfront_info *np) skb_queue_head_init(&free_list); - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); for (id = 0; id < NET_RX_RING_SIZE; id++) { if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) { @@ -1588,7 +1588,7 @@ static void netif_release_rx_bufs(struct netfront_info *np) while ((skb = __skb_dequeue(&free_list)) != NULL) dev_kfree_skb(skb); - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); } static int network_close(struct net_device *dev) @@ -1708,8 +1708,8 @@ static int network_connect(struct net_device *dev) IPRINTK("device %s has %sing receive path.\n", dev->name, np->copying_receiver ? "copy" : "flipp"); + spin_lock_bh(&np->rx_lock); spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); /* * Recovery procedure: @@ -1761,7 +1761,7 @@ static int network_connect(struct net_device *dev) network_tx_buf_gc(dev); network_alloc_rx_buffers(dev); - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); spin_unlock_irq(&np->tx_lock); return 0; @@ -1818,7 +1818,7 @@ static ssize_t store_rxbuf_min(struct class_device *cd, if (target > RX_MAX_TARGET) target = RX_MAX_TARGET; - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); if (target > np->rx_max_target) np->rx_max_target = target; np->rx_min_target = target; @@ -1827,7 +1827,7 @@ static ssize_t store_rxbuf_min(struct class_device *cd, network_alloc_rx_buffers(netdev); - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); return len; } @@ -1861,7 +1861,7 @@ static ssize_t store_rxbuf_max(struct class_device *cd, if (target > RX_MAX_TARGET) target = RX_MAX_TARGET; - spin_lock(&np->rx_lock); + spin_lock_bh(&np->rx_lock); if (target < np->rx_min_target) np->rx_min_target = target; np->rx_max_target = target; @@ -1870,7 +1870,7 @@ static ssize_t store_rxbuf_max(struct class_device *cd, network_alloc_rx_buffers(netdev); - spin_unlock(&np->rx_lock); + spin_unlock_bh(&np->rx_lock); return len; } @@ -2033,10 +2033,10 @@ inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr) static void netif_disconnect_backend(struct netfront_info *info) { /* Stop old i/f to prevent errors whilst we rebuild the state. */ + spin_lock_bh(&info->rx_lock); spin_lock_irq(&info->tx_lock); - spin_lock(&info->rx_lock); netfront_carrier_off(info); - spin_unlock(&info->rx_lock); + spin_unlock_bh(&info->rx_lock); spin_unlock_irq(&info->tx_lock); if (info->irq) From bf57189edcfcac5e752611bfaac11f2fc0279078 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Fri, 13 Apr 2007 11:43:50 +0100 Subject: [PATCH 14/21] Simplify code to map interfaces to bridges signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendNode.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 0b4f829d79..8f4e68f3cc 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -150,8 +150,10 @@ class XendNode: # Get a mapping from interface to bridge - if_to_br = dict(reduce(lambda ls,(b,ifs):[(i,b) for i in ifs] + ls, - Brctl.get_state().items(), [])) + if_to_br = dict([(i,b) + for (b,ifs) in Brctl.get_state().items() + for i in ifs]) + # initialise PIFs saved_pifs = self.state_store.load_state('pif') if saved_pifs: From da12cd1e94f238c1a2638b43740d1cf2b5ed28d9 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 13 Apr 2007 12:01:37 +0100 Subject: [PATCH 15/21] Update .hgignore so it doesn't ignore buildconfigs/* only build-* Signed-off-by: Ian Campbell --- .hgignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.hgignore b/.hgignore index e3bca07c23..e44cc82784 100644 --- a/.hgignore +++ b/.hgignore @@ -22,7 +22,7 @@ ^\.pc ^TAGS$ ^tags$ -^build.*$ +^build-.*$ ^dist/.*$ ^docs/.*\.aux$ ^docs/.*\.dvi$ From 20a553aca304db5009e552ffaa5ce42e395ecd2e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 13 Apr 2007 12:29:06 +0100 Subject: [PATCH 16/21] hvm: Xen must take care to hold a reference to ioreq pages, to ensure that domain runs only when it has valid mapped ioreq pages, and to safely drop ioreq page references when a domain dies. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 4 +- xen/arch/x86/hvm/hvm.c | 106 +++++++++++++++++++++--------- xen/arch/x86/x86_32/domain_page.c | 21 ++++++ xen/common/domain.c | 2 +- xen/include/asm-x86/hvm/hvm.h | 1 + xen/include/xen/domain_page.h | 13 +++- 6 files changed, 111 insertions(+), 36 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index af43de2328..612fec0876 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1540,8 +1540,10 @@ void domain_relinquish_resources(struct domain *d) relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table); relinquish_memory(d, &d->page_list, PGT_l2_page_table); - /* Free page used by xen oprofile buffer */ + /* Free page used by xen oprofile buffer. */ free_xenoprof_pages(d); + + hvm_domain_relinquish_resources(d); } void arch_dump_domain_info(struct domain *d) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 426eb40471..a356907079 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -146,6 +146,59 @@ void hvm_do_resume(struct vcpu *v) } } +static void hvm_clear_ioreq_pfn( + struct domain *d, unsigned long *pva) +{ + unsigned long va, mfn; + + BUG_ON(!d->is_dying); + + if ( (va = xchg(pva, 0UL)) == 0UL ) + return; + + mfn = mfn_from_mapped_domain_page((void *)va); + unmap_domain_page_global((void *)va); + put_page_and_type(mfn_to_page(mfn)); +} + +static int hvm_set_ioreq_pfn( + struct domain *d, unsigned long *pva, unsigned long gmfn) +{ + unsigned long mfn; + void *va; + + mfn = gmfn_to_mfn(d, gmfn); + if ( !mfn_valid(mfn) || + !get_page_and_type(mfn_to_page(mfn), d, PGT_writable_page) ) + return -EINVAL; + + va = map_domain_page_global(mfn); + if ( va == NULL ) + { + put_page_and_type(mfn_to_page(mfn)); + return -ENOMEM; + } + + if ( cmpxchg(pva, 0UL, (unsigned long)va) != 0UL ) + { + unmap_domain_page_global(va); + put_page_and_type(mfn_to_page(mfn)); + return -EINVAL; + } + + /* + * Check dying status /after/ setting *pva. cmpxchg() is a barrier. + * We race against hvm_domain_relinquish_resources(). + */ + if ( d->is_dying ) + hvm_clear_ioreq_pfn(d, pva); + + /* Balance the domain_pause() in hvm_domain_initialise(). */ + domain_unpause(d); + + return 0; +} + int hvm_domain_initialise(struct domain *d) { int rc; @@ -161,7 +214,6 @@ int hvm_domain_initialise(struct domain *d) spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); spin_lock_init(&d->arch.hvm_domain.irq_lock); - /* paging support will be determined inside paging.c */ rc = paging_enable(d, PG_refcounts|PG_translate|PG_external); if ( rc != 0 ) return rc; @@ -169,22 +221,25 @@ int hvm_domain_initialise(struct domain *d) vpic_init(d); vioapic_init(d); + /* Do not allow domain to run until it has ioreq shared pages. */ + domain_pause(d); /* HVM_PARAM_IOREQ_PFN */ + domain_pause(d); /* HVM_PARAM_BUFIOREQ_PFN */ + return 0; } +void hvm_domain_relinquish_resources(struct domain *d) +{ + hvm_clear_ioreq_pfn(d, &d->arch.hvm_domain.shared_page_va); + hvm_clear_ioreq_pfn(d, &d->arch.hvm_domain.buffered_io_va); +} + void hvm_domain_destroy(struct domain *d) { pit_deinit(d); rtc_deinit(d); pmtimer_deinit(d); hpet_deinit(d); - - if ( d->arch.hvm_domain.shared_page_va ) - unmap_domain_page_global( - (void *)d->arch.hvm_domain.shared_page_va); - - if ( d->arch.hvm_domain.buffered_io_va ) - unmap_domain_page_global((void *)d->arch.hvm_domain.buffered_io_va); } static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) @@ -928,8 +983,6 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) struct xen_hvm_param a; struct domain *d; struct vcpu *v; - unsigned long mfn; - void *p; if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; @@ -956,30 +1009,19 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) switch ( a.index ) { case HVM_PARAM_IOREQ_PFN: - if ( d->arch.hvm_domain.shared_page_va ) - goto param_fail; - mfn = gmfn_to_mfn(d, a.value); - if ( mfn == INVALID_MFN ) - goto param_fail; - p = map_domain_page_global(mfn); - if ( p == NULL ) - goto param_fail; - d->arch.hvm_domain.shared_page_va = (unsigned long)p; - /* Initialise evtchn port info if VCPUs already created. */ - for_each_vcpu ( d, v ) - get_vio(d, v->vcpu_id)->vp_eport = - v->arch.hvm_vcpu.xen_port; + rc = hvm_set_ioreq_pfn( + d, &d->arch.hvm_domain.shared_page_va, a.value); + if ( rc == 0 ) + { + /* Initialise evtchn port info if VCPUs already created. */ + for_each_vcpu ( d, v ) + get_vio(d, v->vcpu_id)->vp_eport = + v->arch.hvm_vcpu.xen_port; + } break; case HVM_PARAM_BUFIOREQ_PFN: - if ( d->arch.hvm_domain.buffered_io_va ) - goto param_fail; - mfn = gmfn_to_mfn(d, a.value); - if ( mfn == INVALID_MFN ) - goto param_fail; - p = map_domain_page_global(mfn); - if ( p == NULL ) - goto param_fail; - d->arch.hvm_domain.buffered_io_va = (unsigned long)p; + rc = hvm_set_ioreq_pfn( + d, &d->arch.hvm_domain.buffered_io_va, a.value); break; case HVM_PARAM_CALLBACK_IRQ: hvm_set_callback_via(d, a.value); diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 551ce50593..3f21d458ea 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -251,3 +251,24 @@ void unmap_domain_page_global(void *va) idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT; set_bit(idx, garbage); } + +unsigned long mfn_from_mapped_domain_page(void *va) +{ + unsigned long __va = (unsigned long)va; + l2_pgentry_t *pl2e; + l1_pgentry_t *pl1e; + unsigned int idx; + struct mapcache *cache; + + if ( (__va >= MAPCACHE_VIRT_START) && (__va < MAPCACHE_VIRT_END) ) + { + cache = &mapcache_current_vcpu()->domain->arch.mapcache; + idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT; + return l1e_get_pfn(cache->l1tab[idx]); + } + + ASSERT(__va >= IOREMAP_VIRT_START); + pl2e = virt_to_xen_l2e(__va); + pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va); + return l1e_get_pfn(*pl1e); +} diff --git a/xen/common/domain.c b/xen/common/domain.c index b876984869..2ff5ff42ce 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -314,7 +314,7 @@ void domain_kill(struct domain *d) } /* Tear down state /after/ setting the dying flag. */ - smp_wmb(); + smp_mb(); gnttab_release_mappings(d); domain_relinquish_resources(d); diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 60f44194c8..2a3802423f 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -145,6 +145,7 @@ struct hvm_function_table { extern struct hvm_function_table hvm_funcs; int hvm_domain_initialise(struct domain *d); +void hvm_domain_relinquish_resources(struct domain *d); void hvm_domain_destroy(struct domain *d); int hvm_vcpu_initialise(struct vcpu *v); diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index 7067f33ff7..5453323867 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -34,6 +34,13 @@ void unmap_domain_page(void *va); void *map_domain_page_global(unsigned long mfn); void unmap_domain_page_global(void *va); +/* + * Convert a VA (within a page previously mapped in the context of the + * currently-executing VCPU via a call to map_domain_page(), or via a + * previous call to map_domain_page_global()) to the mapped page frame. + */ +unsigned long mfn_from_mapped_domain_page(void *va); + #define DMCACHE_ENTRY_VALID 1U #define DMCACHE_ENTRY_HELD 2U @@ -96,12 +103,14 @@ domain_mmap_cache_destroy(struct domain_mmap_cache *cache) #else /* !CONFIG_DOMAIN_PAGE */ -#define map_domain_page(mfn) maddr_to_virt((mfn)< Date: Fri, 13 Apr 2007 12:30:04 +0100 Subject: [PATCH 17/21] hvm: Fix some bugs in mmio decoder Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require the src immediate operand be sign-extented befere the op is executed, but this is omitted in the current Xcode. The patch fixes this. The patch also fixes an issue in handling address-size override prefix, and fixes an issue in get_immediate(). Signed-off-by: Dexuan Cui --- xen/arch/x86/hvm/platform.c | 40 +++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index d333a92ace..0ab2fb1fe7 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -221,7 +221,6 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst inst++; //skip ModR/M byte if ( ad_size != WORD && mod != 3 && rm == 4 ) { - rm = *inst & 7; inst++; //skip SIB byte } @@ -257,6 +256,33 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst return val; } +/* Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require + * the src immediate operand be sign-extented befere the op is executed. Here + * we always sign-extend the operand to a "unsigned long" variable. + * + * Note: to simplify the logic here, the sign-extension here may be performed + * redundantly against some instructions, like "MOV $imm16, r/m16" -- however + * this is harmless, since we always remember the operand's size. + */ +static inline unsigned long get_immediate_sign_ext(int ad_size, + const unsigned char *inst, + int op_size) +{ + unsigned long result = get_immediate(ad_size, inst, op_size); + + if ( op_size == QUAD ) + op_size = LONG; + + ASSERT( op_size == BYTE || op_size == WORD || op_size == LONG ); + + if ( result & (1UL << ((8*op_size) - 1)) ) + { + unsigned long mask = ~0UL >> (8 * (sizeof(mask) - op_size)); + result = ~mask | (result & mask); + } + return result; +} + static inline int get_index(const unsigned char *inst, unsigned char rex) { int mod, reg, rm; @@ -394,7 +420,9 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, case 8: if ( *op_size == 0 ) *op_size = rex & 0x8 ? QUAD : LONG; - if ( *ad_size == 0 ) + if ( *ad_size == WORD ) + *ad_size = LONG; + else if ( *ad_size == 0 ) *ad_size = QUAD; break; #endif @@ -520,10 +548,10 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, /* opcode 0x83 always has a single byte operand */ if ( opcode[0] == 0x83 ) mmio_op->immediate = - (signed char)get_immediate(*ad_size, opcode + 1, BYTE); + get_immediate_sign_ext(*ad_size, opcode + 1, BYTE); else mmio_op->immediate = - get_immediate(*ad_size, opcode + 1, *op_size); + get_immediate_sign_ext(*ad_size, opcode + 1, *op_size); mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); @@ -677,7 +705,7 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE); mmio_op->immediate = - get_immediate(*ad_size, opcode + 1, *op_size); + get_immediate_sign_ext(*ad_size, opcode + 1, *op_size); mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY); return DECODE_success; @@ -699,7 +727,7 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); mmio_op->immediate = - get_immediate(*ad_size, opcode + 1, *op_size); + get_immediate_sign_ext(*ad_size, opcode + 1, *op_size); mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); return DECODE_success; From 4a507d9105776305edbafca73bdc5e3ad8edda0f Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Fri, 13 Apr 2007 13:55:10 +0100 Subject: [PATCH 18/21] Add VM.migrate to XenAPI, add support to XM signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 12 ++++++++++++ tools/python/xen/xm/migrate.py | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 7e67f491d5..9b03ff9be2 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1304,6 +1304,7 @@ class XendAPI(object): ('set_memory_dynamic_max_live', None), ('set_memory_dynamic_min_live', None), ('send_trigger', None), + ('migrate', None), ('destroy', None)] VM_funcs = [('create', 'VM'), @@ -1823,6 +1824,17 @@ class XendAPI(object): xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu) return xen_api_success_void() + def VM_migrate(self, _, vm_ref, destination_url, live, other_config): + xendom = XendDomain.instance() + xeninfo = xendom.get_vm_by_uuid(vm_ref) + + resource = other_config.get("resource", 0) + port = other_config.get("port", 0) + + xendom.domain_migrate(xeninfo.getDomid(), destination_url, + bool(live), resource, port) + return xen_api_success_void() + def VM_save(self, _, vm_ref, dest, checkpoint): xendom = XendDomain.instance() xeninfo = xendom.get_vm_by_uuid(vm_ref) diff --git a/tools/python/xen/xm/migrate.py b/tools/python/xen/xm/migrate.py index 2b77e6b1ab..5a94f6c4d5 100644 --- a/tools/python/xen/xm/migrate.py +++ b/tools/python/xen/xm/migrate.py @@ -23,7 +23,7 @@ import sys from xen.xm.opts import * -from main import server +from main import server, serverType, get_single_vm, SERVER_XEN_API gopts = Opts(use="""[options] DOM HOST @@ -60,5 +60,16 @@ def main(argv): dom = args[0] dst = args[1] - server.xend.domain.migrate(dom, dst, opts.vals.live, opts.vals.resource, - opts.vals.port) + + if serverType == SERVER_XEN_API: + vm_ref = get_single_vm(dom) + other_config = { + "port": opts.vals.port, + "resource": opts.vals.resource + } + server.xenapi.VM.migrate(vm_ref, dst, bool(opts.vals.live), + other_config) + else: + server.xend.domain.migrate(dom, dst, opts.vals.live, + opts.vals.resource, + opts.vals.port) From 0c8a05c14251778943ed7243bb2c20eb9dcf9b65 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 13 Apr 2007 14:59:06 +0100 Subject: [PATCH 19/21] hvm: Clean up treatment of is_dying per-domain boolean. All critical checks are done under an appropriate lock, allowing the lock-free protocols surrounding this boolean to be removed. Also simplification and fixes to code for setting/zapping the ioreq and buf_ioreq shared pages. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/hvm.c | 118 ++++++++++++++++++------------ xen/arch/x86/hvm/intercept.c | 32 +++----- xen/arch/x86/hvm/io.c | 2 +- xen/arch/x86/hvm/platform.c | 6 +- xen/arch/x86/mm.c | 22 +++--- xen/arch/x86/x86_32/domain_page.c | 21 ------ xen/common/domain.c | 3 - xen/include/asm-x86/hvm/domain.h | 12 ++- xen/include/asm-x86/hvm/support.h | 13 ++-- xen/include/xen/domain_page.h | 9 --- 10 files changed, 114 insertions(+), 124 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index a356907079..d8ef1ae258 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -101,7 +101,7 @@ void hvm_set_guest_time(struct vcpu *v, u64 gtime) u64 hvm_get_guest_time(struct vcpu *v) { - u64 host_tsc; + u64 host_tsc; rdtscll(host_tsc); return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset; @@ -125,7 +125,7 @@ void hvm_do_resume(struct vcpu *v) pt_thaw_time(v); /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */ - p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; + p = &get_ioreq(v)->vp_ioreq; while ( p->state != STATE_IOREQ_NONE ) { switch ( p->state ) @@ -146,54 +146,68 @@ void hvm_do_resume(struct vcpu *v) } } -static void hvm_clear_ioreq_pfn( - struct domain *d, unsigned long *pva) +static void hvm_init_ioreq_page( + struct domain *d, struct hvm_ioreq_page *iorp) { - unsigned long va, mfn; - - BUG_ON(!d->is_dying); - - if ( (va = xchg(pva, 0UL)) == 0UL ) - return; - - mfn = mfn_from_mapped_domain_page((void *)va); - unmap_domain_page_global((void *)va); - put_page_and_type(mfn_to_page(mfn)); + memset(iorp, 0, sizeof(*iorp)); + spin_lock_init(&iorp->lock); + domain_pause(d); } -static int hvm_set_ioreq_pfn( - struct domain *d, unsigned long *pva, unsigned long gmfn) +static void hvm_destroy_ioreq_page( + struct domain *d, struct hvm_ioreq_page *iorp) { + spin_lock(&iorp->lock); + + ASSERT(d->is_dying); + + if ( iorp->va != NULL ) + { + unmap_domain_page_global(iorp->va); + put_page_and_type(iorp->page); + iorp->va = NULL; + } + + spin_unlock(&iorp->lock); +} + +static int hvm_set_ioreq_page( + struct domain *d, struct hvm_ioreq_page *iorp, unsigned long gmfn) +{ + struct page_info *page; unsigned long mfn; void *va; mfn = gmfn_to_mfn(d, gmfn); - if ( !mfn_valid(mfn) || - !get_page_and_type(mfn_to_page(mfn), d, PGT_writable_page) ) + if ( !mfn_valid(mfn) ) + return -EINVAL; + + page = mfn_to_page(mfn); + if ( !get_page_and_type(page, d, PGT_writable_page) ) return -EINVAL; va = map_domain_page_global(mfn); if ( va == NULL ) { - put_page_and_type(mfn_to_page(mfn)); + put_page_and_type(page); return -ENOMEM; } - if ( cmpxchg(pva, 0UL, (unsigned long)va) != 0UL ) + spin_lock(&iorp->lock); + + if ( (iorp->va != NULL) || d->is_dying ) { + spin_unlock(&iorp->lock); unmap_domain_page_global(va); put_page_and_type(mfn_to_page(mfn)); return -EINVAL; } - /* - * Check dying status /after/ setting *pva. cmpxchg() is a barrier. - * We race against hvm_domain_relinquish_resources(). - */ - if ( d->is_dying ) - hvm_clear_ioreq_pfn(d, pva); + iorp->va = va; + iorp->page = page; + + spin_unlock(&iorp->lock); - /* Balance the domain_pause() in hvm_domain_initialise(). */ domain_unpause(d); return 0; @@ -211,7 +225,6 @@ int hvm_domain_initialise(struct domain *d) } spin_lock_init(&d->arch.hvm_domain.pbuf_lock); - spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); spin_lock_init(&d->arch.hvm_domain.irq_lock); rc = paging_enable(d, PG_refcounts|PG_translate|PG_external); @@ -221,17 +234,16 @@ int hvm_domain_initialise(struct domain *d) vpic_init(d); vioapic_init(d); - /* Do not allow domain to run until it has ioreq shared pages. */ - domain_pause(d); /* HVM_PARAM_IOREQ_PFN */ - domain_pause(d); /* HVM_PARAM_BUFIOREQ_PFN */ + hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq); + hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq); return 0; } void hvm_domain_relinquish_resources(struct domain *d) { - hvm_clear_ioreq_pfn(d, &d->arch.hvm_domain.shared_page_va); - hvm_clear_ioreq_pfn(d, &d->arch.hvm_domain.buffered_io_va); + hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.ioreq); + hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq); } void hvm_domain_destroy(struct domain *d) @@ -379,10 +391,20 @@ int hvm_vcpu_initialise(struct vcpu *v) } /* Create ioreq event channel. */ - v->arch.hvm_vcpu.xen_port = alloc_unbound_xen_event_channel(v, 0); - if ( get_sp(v->domain) && get_vio(v->domain, v->vcpu_id) ) - get_vio(v->domain, v->vcpu_id)->vp_eport = - v->arch.hvm_vcpu.xen_port; + rc = alloc_unbound_xen_event_channel(v, 0); + if ( rc < 0 ) + { + hvm_funcs.vcpu_destroy(v); + vlapic_destroy(v); + return rc; + } + + /* Register ioreq event channel. */ + v->arch.hvm_vcpu.xen_port = rc; + spin_lock(&v->domain->arch.hvm_domain.ioreq.lock); + if ( v->domain->arch.hvm_domain.ioreq.va != NULL ) + get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port; + spin_unlock(&v->domain->arch.hvm_domain.ioreq.lock); INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list); @@ -463,7 +485,7 @@ void hvm_send_assist_req(struct vcpu *v) if ( unlikely(!vcpu_start_shutdown_deferral(v)) ) return; /* implicitly bins the i/o operation */ - p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; + p = &get_ioreq(v)->vp_ioreq; if ( unlikely(p->state != STATE_IOREQ_NONE) ) { /* This indicates a bug in the device model. Crash the domain. */ @@ -981,6 +1003,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) case HVMOP_get_param: { struct xen_hvm_param a; + struct hvm_ioreq_page *iorp; struct domain *d; struct vcpu *v; @@ -1009,19 +1032,18 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) switch ( a.index ) { case HVM_PARAM_IOREQ_PFN: - rc = hvm_set_ioreq_pfn( - d, &d->arch.hvm_domain.shared_page_va, a.value); - if ( rc == 0 ) - { + iorp = &d->arch.hvm_domain.ioreq; + rc = hvm_set_ioreq_page(d, iorp, a.value); + spin_lock(&iorp->lock); + if ( (rc == 0) && (iorp->va != NULL) ) /* Initialise evtchn port info if VCPUs already created. */ for_each_vcpu ( d, v ) - get_vio(d, v->vcpu_id)->vp_eport = - v->arch.hvm_vcpu.xen_port; - } + get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port; + spin_unlock(&iorp->lock); break; - case HVM_PARAM_BUFIOREQ_PFN: - rc = hvm_set_ioreq_pfn( - d, &d->arch.hvm_domain.buffered_io_va, a.value); + case HVM_PARAM_BUFIOREQ_PFN: + iorp = &d->arch.hvm_domain.buf_ioreq; + rc = hvm_set_ioreq_page(d, iorp, a.value); break; case HVM_PARAM_CALLBACK_IRQ: hvm_set_callback_via(d, a.value); diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index fb8497a996..91749b676b 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -158,34 +158,26 @@ static inline void hvm_mmio_access(struct vcpu *v, int hvm_buffered_io_send(ioreq_t *p) { struct vcpu *v = current; - spinlock_t *buffered_io_lock; - buffered_iopage_t *buffered_iopage = - (buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va); - unsigned long tmp_write_pointer = 0; + struct hvm_ioreq_page *iorp = &v->domain->arch.hvm_domain.buf_ioreq; + buffered_iopage_t *pg = iorp->va; - buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock; - spin_lock(buffered_io_lock); + spin_lock(&iorp->lock); - if ( buffered_iopage->write_pointer - buffered_iopage->read_pointer == - (unsigned int)IOREQ_BUFFER_SLOT_NUM ) { - /* the queue is full. - * send the iopacket through the normal path. - * NOTE: The arithimetic operation could handle the situation for - * write_pointer overflow. - */ - spin_unlock(buffered_io_lock); + if ( (pg->write_pointer - pg->read_pointer) == IOREQ_BUFFER_SLOT_NUM ) + { + /* The queue is full: send the iopacket through the normal path. */ + spin_unlock(&iorp->lock); return 0; } - tmp_write_pointer = buffered_iopage->write_pointer % IOREQ_BUFFER_SLOT_NUM; + memcpy(&pg->ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM], + p, sizeof(ioreq_t)); - memcpy(&buffered_iopage->ioreq[tmp_write_pointer], p, sizeof(ioreq_t)); - - /*make the ioreq_t visible before write_pointer*/ + /* Make the ioreq_t visible /before/ write_pointer. */ wmb(); - buffered_iopage->write_pointer++; + pg->write_pointer++; - spin_unlock(buffered_io_lock); + spin_unlock(&iorp->lock); return 1; } diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 03820f0ebd..f0f8ea8ecb 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -832,7 +832,7 @@ void hvm_io_assist(void) io_opp = &v->arch.hvm_vcpu.io_op; regs = &io_opp->io_context; - vio = get_vio(d, v->vcpu_id); + vio = get_ioreq(v); p = &vio->vp_ioreq; if ( p->state != STATE_IORESP_READY ) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 0ab2fb1fe7..8bb3e3439b 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -866,7 +866,7 @@ void send_pio_req(unsigned long port, unsigned long count, int size, port, count, size, value, dir, value_is_ptr); } - vio = get_vio(v->domain, v->vcpu_id); + vio = get_ioreq(v); if ( vio == NULL ) { printk("bad shared page: %lx\n", (unsigned long) vio); domain_crash_synchronous(); @@ -915,7 +915,7 @@ static void send_mmio_req(unsigned char type, unsigned long gpa, type, gpa, count, size, value, dir, value_is_ptr); } - vio = get_vio(v->domain, v->vcpu_id); + vio = get_ioreq(v); if (vio == NULL) { printk("bad shared page\n"); domain_crash_synchronous(); @@ -976,7 +976,7 @@ void send_invalidate_req(void) vcpu_iodata_t *vio; ioreq_t *p; - vio = get_vio(v->domain, v->vcpu_id); + vio = get_ioreq(v); if ( vio == NULL ) { printk("bad shared page: %lx\n", (unsigned long) vio); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index fac87bcf02..ce49f743fe 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2041,7 +2041,7 @@ int do_mmuext_op( MEM_LOG("Error while pinning mfn %lx", mfn); break; } - + if ( unlikely(test_and_set_bit(_PGT_pinned, &page->u.inuse.type_info)) ) { @@ -2054,14 +2054,18 @@ int do_mmuext_op( /* A page is dirtied when its pin status is set. */ mark_dirty(d, mfn); - /* - * We can race domain destruction (domain_relinquish_resources). - * NB. The dying-flag test must happen /after/ setting PGT_pinned. - */ - if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) && - this_cpu(percpu_mm_info).foreign->is_dying && - test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) - put_page_and_type(page); + /* We can race domain destruction (domain_relinquish_resources). */ + if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) ) + { + int drop_ref; + spin_lock(&FOREIGNDOM->page_alloc_lock); + drop_ref = (FOREIGNDOM->is_dying && + test_and_clear_bit(_PGT_pinned, + &page->u.inuse.type_info)); + spin_unlock(&FOREIGNDOM->page_alloc_lock); + if ( drop_ref ) + put_page_and_type(page); + } break; diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 3f21d458ea..551ce50593 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -251,24 +251,3 @@ void unmap_domain_page_global(void *va) idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT; set_bit(idx, garbage); } - -unsigned long mfn_from_mapped_domain_page(void *va) -{ - unsigned long __va = (unsigned long)va; - l2_pgentry_t *pl2e; - l1_pgentry_t *pl1e; - unsigned int idx; - struct mapcache *cache; - - if ( (__va >= MAPCACHE_VIRT_START) && (__va < MAPCACHE_VIRT_END) ) - { - cache = &mapcache_current_vcpu()->domain->arch.mapcache; - idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT; - return l1e_get_pfn(cache->l1tab[idx]); - } - - ASSERT(__va >= IOREMAP_VIRT_START); - pl2e = virt_to_xen_l2e(__va); - pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va); - return l1e_get_pfn(*pl1e); -} diff --git a/xen/common/domain.c b/xen/common/domain.c index 2ff5ff42ce..8ade10f4ab 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -313,9 +313,6 @@ void domain_kill(struct domain *d) return; } - /* Tear down state /after/ setting the dying flag. */ - smp_mb(); - gnttab_release_mappings(d); domain_relinquish_resources(d); put_domain(d); diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h index ce1a2fc8ad..880e988b96 100644 --- a/xen/include/asm-x86/hvm/domain.h +++ b/xen/include/asm-x86/hvm/domain.h @@ -28,10 +28,16 @@ #include #include +struct hvm_ioreq_page { + spinlock_t lock; + struct page_info *page; + void *va; +}; + struct hvm_domain { - unsigned long shared_page_va; - unsigned long buffered_io_va; - spinlock_t buffered_io_lock; + struct hvm_ioreq_page ioreq; + struct hvm_ioreq_page buf_ioreq; + s64 tsc_frequency; struct pl_time pl_time; diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index 1d331ef5da..efbc2b39b0 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -32,14 +32,13 @@ #define HVM_DEBUG 1 #endif -static inline shared_iopage_t *get_sp(struct domain *d) +static inline vcpu_iodata_t *get_ioreq(struct vcpu *v) { - return (shared_iopage_t *) d->arch.hvm_domain.shared_page_va; -} - -static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu) -{ - return &get_sp(d)->vcpu_iodata[cpu]; + struct domain *d = v->domain; + shared_iopage_t *p = d->arch.hvm_domain.ioreq.va; + ASSERT((v == current) || spin_is_locked(&d->arch.hvm_domain.ioreq.lock)); + ASSERT(d->arch.hvm_domain.ioreq.va != NULL); + return &p->vcpu_iodata[v->vcpu_id]; } /* XXX these are really VMX specific */ diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index 5453323867..cd2226678b 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -34,13 +34,6 @@ void unmap_domain_page(void *va); void *map_domain_page_global(unsigned long mfn); void unmap_domain_page_global(void *va); -/* - * Convert a VA (within a page previously mapped in the context of the - * currently-executing VCPU via a call to map_domain_page(), or via a - * previous call to map_domain_page_global()) to the mapped page frame. - */ -unsigned long mfn_from_mapped_domain_page(void *va); - #define DMCACHE_ENTRY_VALID 1U #define DMCACHE_ENTRY_HELD 2U @@ -109,8 +102,6 @@ domain_mmap_cache_destroy(struct domain_mmap_cache *cache) #define map_domain_page_global(mfn) mfn_to_virt(mfn) #define unmap_domain_page_global(va) ((void)(va)) -#define mfn_from_mapped_domain_page(va) virt_to_mfn(va) - struct domain_mmap_cache { }; From 6ba466691469da3e50de210a298e66c8653b31f3 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 13 Apr 2007 15:24:42 +0100 Subject: [PATCH 20/21] linux netfront: Fixes to locking after lockdep-derived changes, as suggested by Herbert Xu. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index f453337246..11b8edbfe8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -1307,10 +1307,10 @@ static int netif_poll(struct net_device *dev, int *pbudget) int pages_flipped = 0; int err; - spin_lock_bh(&np->rx_lock); + spin_lock(&np->rx_lock); /* no need for spin_lock_bh() in ->poll() */ if (unlikely(!netfront_carrier_ok(np))) { - spin_unlock_bh(&np->rx_lock); + spin_unlock(&np->rx_lock); return 0; } @@ -1478,7 +1478,7 @@ err: local_irq_restore(flags); } - spin_unlock_bh(&np->rx_lock); + spin_unlock(&np->rx_lock); return more_to_do; } @@ -1761,8 +1761,8 @@ static int network_connect(struct net_device *dev) network_tx_buf_gc(dev); network_alloc_rx_buffers(dev); - spin_unlock_bh(&np->rx_lock); spin_unlock_irq(&np->tx_lock); + spin_unlock_bh(&np->rx_lock); return 0; } @@ -2036,8 +2036,8 @@ static void netif_disconnect_backend(struct netfront_info *info) spin_lock_bh(&info->rx_lock); spin_lock_irq(&info->tx_lock); netfront_carrier_off(info); - spin_unlock_bh(&info->rx_lock); spin_unlock_irq(&info->tx_lock); + spin_unlock_bh(&info->rx_lock); if (info->irq) unbind_from_irqhandler(info->irq, info->netdev); From e52527b9edb707dc3831d3b9b0f8a67c4834fcd7 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Fri, 13 Apr 2007 16:02:41 +0100 Subject: [PATCH 21/21] Fix TypeError with datetime() on old python version signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 9b03ff9be2..89f0265f8b 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -96,7 +96,10 @@ def datetime(when = None): @param when The time in question, given as seconds since the epoch, UTC. May be None, in which case the current time is used. """ - return xmlrpclib.DateTime(time.gmtime(when)) + if when is None: + return xmlrpclib.DateTime(time.gmtime()) + else: + return xmlrpclib.DateTime(time.gmtime(when)) # ---------------------------------------------------