# HG changeset patch # User Tim Deegan # Date 1233765266 0 # Node ID 11211b210f926f270aee41827e121b35b1753aa6 # Parent f7142816164dee4a9c60c3e2fc1846d703e39d35 libxc support for the new partial-HVM-save domctl. This includes making the pagetable walker in xc_pagetab.c behave correctly for 32-bit and 64-bit HVM guests. Signed-off-by: Tim Deegan diff -r f7142816164d -r 11211b210f92 tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Wed Feb 04 16:26:51 2009 +0000 +++ b/tools/libxc/xc_domain.c Wed Feb 04 16:34:26 2009 +0000 @@ -269,6 +269,38 @@ unlock_pages(ctxt_buf, size); return (ret < 0 ? -1 : domctl.u.hvmcontext.size); +} + +/* Get just one element of the HVM guest context. + * size must be >= HVM_SAVE_LENGTH(type) */ +int xc_domain_hvm_getcontext_partial(int xc_handle, + uint32_t domid, + uint16_t typecode, + uint16_t instance, + void *ctxt_buf, + uint32_t size) +{ + int ret; + DECLARE_DOMCTL; + + if ( !ctxt_buf ) + return -EINVAL; + + domctl.cmd = XEN_DOMCTL_gethvmcontext_partial; + domctl.domain = (domid_t) domid; + domctl.u.hvmcontext_partial.type = typecode; + domctl.u.hvmcontext_partial.instance = instance; + set_xen_guest_handle(domctl.u.hvmcontext_partial.buffer, ctxt_buf); + + if ( (ret = lock_pages(ctxt_buf, size)) != 0 ) + return ret; + + ret = do_domctl(xc_handle, &domctl); + + if ( ctxt_buf ) + unlock_pages(ctxt_buf, size); + + return ret ? -1 : 0; } /* set info to hvm guest for restore */ diff -r f7142816164d -r 11211b210f92 tools/libxc/xc_pagetab.c --- a/tools/libxc/xc_pagetab.c Wed Feb 04 16:26:51 2009 +0000 +++ b/tools/libxc/xc_pagetab.c Wed Feb 04 16:34:26 2009 +0000 @@ -4,50 +4,42 @@ * Function to translate virtual to physical addresses. */ #include "xc_private.h" +#include #define CR0_PG 0x80000000 #define CR4_PAE 0x20 #define PTE_PSE 0x80 +#define EFER_LMA 0x400 + unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom, int vcpu, unsigned long long virt) { xc_dominfo_t dominfo; - vcpu_guest_context_any_t ctx; uint64_t paddr, mask, pte = 0; int size, level, pt_levels = 2; void *map; if (xc_domain_getinfo(xc_handle, dom, 1, &dominfo) != 1 - || dominfo.domid != dom - || xc_vcpu_getcontext(xc_handle, dom, vcpu, &ctx) != 0) + || dominfo.domid != dom) return 0; /* What kind of paging are we dealing with? */ if (dominfo.hvm) { - unsigned long cr0, cr3, cr4; - xen_capabilities_info_t xen_caps = ""; - if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) + struct hvm_hw_cpu ctx; + if (xc_domain_hvm_getcontext_partial(xc_handle, dom, + HVM_SAVE_CODE(CPU), vcpu, + &ctx, sizeof ctx) != 0) return 0; - /* HVM context records are always host-sized */ - if (strstr(xen_caps, "xen-3.0-x86_64")) { - cr0 = ctx.x64.ctrlreg[0]; - cr3 = ctx.x64.ctrlreg[3]; - cr4 = ctx.x64.ctrlreg[4]; - } else { - cr0 = ctx.x32.ctrlreg[0]; - cr3 = ctx.x32.ctrlreg[3]; - cr4 = ctx.x32.ctrlreg[4]; - } - if (!(cr0 & CR0_PG)) + if (!(ctx.cr0 & CR0_PG)) return virt; - if (0 /* XXX how to get EFER.LMA? */) - pt_levels = 4; - else - pt_levels = (cr4 & CR4_PAE) ? 3 : 2; - paddr = cr3 & ((pt_levels == 3) ? ~0x1full : ~0xfffull); + pt_levels = (ctx.msr_efer&EFER_LMA) ? 4 : (ctx.cr4&CR4_PAE) ? 3 : 2; + paddr = ctx.cr3 & ((pt_levels == 3) ? ~0x1full : ~0xfffull); } else { DECLARE_DOMCTL; + vcpu_guest_context_any_t ctx; + if (xc_vcpu_getcontext(xc_handle, dom, vcpu, &ctx) != 0) + return 0; domctl.domain = dom; domctl.cmd = XEN_DOMCTL_get_address_size; if ( do_domctl(xc_handle, &domctl) != 0 ) diff -r f7142816164d -r 11211b210f92 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Wed Feb 04 16:26:51 2009 +0000 +++ b/tools/libxc/xenctrl.h Wed Feb 04 16:34:26 2009 +0000 @@ -374,6 +374,25 @@ uint32_t domid, uint8_t *ctxt_buf, uint32_t size); + + +/** + * This function returns one element of the context of a hvm domain + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the domain to get information from + * @parm typecode which type of elemnt required + * @parm instance which instance of the type + * @parm ctxt_buf a pointer to a structure to store the execution context of + * the hvm domain + * @parm size the size of ctxt_buf (must be >= HVM_SAVE_LENGTH(typecode)) + * @return 0 on success, -1 on failure + */ +int xc_domain_hvm_getcontext_partial(int xc_handle, + uint32_t domid, + uint16_t typecode, + uint16_t instance, + void *ctxt_buf, + uint32_t size); /** * This function will set the context for hvm domain