debuggers.hg

changeset 20666:a50c1cbf08ec

memory hotadd 7/7: hypercall support

The basic work flow to handle the memory hotadd is:
Update node information
Map new pages to xen 1:1 mapping
Setup frametable for new memory range
Setup m2p table for new memory range
Put the new pages to domheap

Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Dec 11 08:58:06 2009 +0000 (2009-12-11)
parents 7d7e221370ea
children f9392f6eda79
files xen/arch/x86/platform_hypercall.c xen/arch/x86/x86_64/mm.c xen/include/asm-x86/mm.h xen/include/public/platform.h
line diff
     1.1 --- a/xen/arch/x86/platform_hypercall.c	Fri Dec 11 08:57:30 2009 +0000
     1.2 +++ b/xen/arch/x86/platform_hypercall.c	Fri Dec 11 08:58:06 2009 +0000
     1.3 @@ -469,6 +469,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe
     1.4                        op->u.cpu_add.pxm);
     1.5      break;
     1.6  
     1.7 +    case XENPF_mem_hotadd:
     1.8 +        ret = memory_add(op->u.mem_add.spfn,
     1.9 +                      op->u.mem_add.epfn,
    1.10 +                      op->u.mem_add.pxm);
    1.11 +        break;
    1.12      default:
    1.13          ret = -ENOSYS;
    1.14          break;
     2.1 --- a/xen/arch/x86/x86_64/mm.c	Fri Dec 11 08:57:30 2009 +0000
     2.2 +++ b/xen/arch/x86/x86_64/mm.c	Fri Dec 11 08:58:06 2009 +0000
     2.3 @@ -23,6 +23,7 @@
     2.4  #include <xen/mm.h>
     2.5  #include <xen/sched.h>
     2.6  #include <xen/numa.h>
     2.7 +#include <xen/nodemask.h>
     2.8  #include <xen/guest_access.h>
     2.9  #include <asm/current.h>
    2.10  #include <asm/asm_defns.h>
    2.11 @@ -32,6 +33,7 @@
    2.12  #include <asm/hypercall.h>
    2.13  #include <asm/msr.h>
    2.14  #include <asm/setup.h>
    2.15 +#include <asm/numa.h>
    2.16  #include <public/memory.h>
    2.17  
    2.18  /* Parameters for PFN/MADDR compression. */
    2.19 @@ -1309,6 +1311,126 @@ unsigned int domain_clamp_alloc_bitsize(
    2.20      return min(d->arch.physaddr_bitsize, bits);
    2.21  }
    2.22  
    2.23 +int transfer_pages_to_heap(struct mem_hotadd_info *info)
    2.24 +{
    2.25 +    unsigned long i;
    2.26 +    struct page_info *pg;
    2.27 +
    2.28 +    /*
    2.29 +     * Mark the allocated page before put free pages to buddy allocator
    2.30 +     * to avoid merge in free_heap_pages
    2.31 +     */
    2.32 +    for (i = info->spfn; i < info->cur; i++)
    2.33 +    {
    2.34 +        pg = mfn_to_page(i);
    2.35 +        pg->count_info = PGC_state_inuse;
    2.36 +    }
    2.37 +
    2.38 +    init_domheap_pages(pfn_to_paddr(info->cur), pfn_to_paddr(info->epfn));
    2.39 +
    2.40 +    return 0;
    2.41 +}
    2.42 +
    2.43 +int mem_hotadd_check(unsigned long spfn, unsigned long epfn)
    2.44 +{
    2.45 +    /* TBD: Need make sure cover to m2p/ft page table */
    2.46 +    return 1;
    2.47 +}
    2.48 +
    2.49 +int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
    2.50 +{
    2.51 +    struct mem_hotadd_info info;
    2.52 +    int ret, node;
    2.53 +    unsigned long old_max = max_page, old_total = total_pages;
    2.54 +    unsigned long i;
    2.55 +
    2.56 +    printk("memory_add %lx ~ %lx with pxm %x\n", spfn, epfn, pxm);
    2.57 +
    2.58 +    /* the memory range should at least be 2M aligned */
    2.59 +    if ( (spfn | epfn) & ((1UL << PAGETABLE_ORDER) - 1) )
    2.60 +        return -EINVAL;
    2.61 +
    2.62 +    if ( (spfn | epfn) & pfn_hole_mask)
    2.63 +        return -EINVAL;
    2.64 +
    2.65 +    if ( epfn < max_page )
    2.66 +        return -EINVAL;
    2.67 +
    2.68 +    if ( (node = setup_node(pxm)) == -1 )
    2.69 +        return -EINVAL;
    2.70 +
    2.71 +    if ( !valid_numa_range(spfn << PAGE_SHIFT, epfn << PAGE_SHIFT, node) )
    2.72 +    {
    2.73 +        dprintk(XENLOG_WARNING, "spfn %lx ~ epfn %lx pxm %x node %x"
    2.74 +            "is not numa valid", spfn, epfn, pxm, node);
    2.75 +        return -EINVAL;
    2.76 +    }
    2.77 +
    2.78 +    if ( !mem_hotadd_check(spfn, epfn) )
    2.79 +        return -EINVAL;
    2.80 +
    2.81 +    if ( !node_online(node) )
    2.82 +    {
    2.83 +        dprintk(XENLOG_WARNING, "node %x pxm %x is not online\n",node, pxm);
    2.84 +        NODE_DATA(node)->node_id = node;
    2.85 +        NODE_DATA(node)->node_start_pfn = spfn;
    2.86 +        NODE_DATA(node)->node_spanned_pages =
    2.87 +                epfn - node_start_pfn(node);
    2.88 +        node_set_online(node);
    2.89 +    }else
    2.90 +    {
    2.91 +        if (NODE_DATA(node)->node_start_pfn > spfn)
    2.92 +            NODE_DATA(node)->node_start_pfn = spfn;
    2.93 +        if (node_end_pfn(node) < epfn)
    2.94 +            NODE_DATA(node)->node_spanned_pages = epfn - node_start_pfn(node);
    2.95 +    }
    2.96 +    ret =  map_pages_to_xen((unsigned long)mfn_to_virt(spfn), spfn,
    2.97 +                            epfn - spfn, PAGE_HYPERVISOR);
    2.98 +
    2.99 +     if ( ret )
   2.100 +        return ret;
   2.101 +
   2.102 +    ret = -EINVAL;
   2.103 +    info.spfn = spfn;
   2.104 +    info.epfn = epfn;
   2.105 +    info.cur = spfn;
   2.106 +
   2.107 +    ret = extend_frame_table(&info);
   2.108 +    if (ret)
   2.109 +        goto destroy_frametable;
   2.110 +    /* Set max_page as setup_m2p_table will use it*/
   2.111 +    max_page = epfn;
   2.112 +    max_pdx = pfn_to_pdx(max_page - 1) + 1;
   2.113 +    total_pages += epfn - spfn;
   2.114 +
   2.115 +    set_pdx_range(spfn, epfn);
   2.116 +    ret = setup_m2p_table(&info);
   2.117 +
   2.118 +    if ( ret )
   2.119 +        goto destroy_m2p;
   2.120 +
   2.121 +    for ( i = old_max; i < epfn; i++ )
   2.122 +        iommu_map_page(dom0, i, i);
   2.123 +
   2.124 +    /* We can't revert any more */
   2.125 +    transfer_pages_to_heap(&info);
   2.126 +
   2.127 +    share_hotadd_m2p_table(&info);
   2.128 +
   2.129 +    return 0;
   2.130 +
   2.131 +destroy_m2p:
   2.132 +    destroy_m2p_mapping(&info);
   2.133 +destroy_frametable:
   2.134 +    cleanup_frame_table(&info);
   2.135 +    destroy_xen_mappings((unsigned long)mfn_to_virt(spfn),
   2.136 +                         (unsigned long)mfn_to_virt(epfn));
   2.137 +    max_page = old_max;
   2.138 +    total_pages = old_total;
   2.139 +    max_pdx = pfn_to_pdx(max_page - 1) + 1;
   2.140 +    return ret;
   2.141 +}
   2.142 +
   2.143  #include "compat/mm.c"
   2.144  
   2.145  /*
     3.1 --- a/xen/include/asm-x86/mm.h	Fri Dec 11 08:57:30 2009 +0000
     3.2 +++ b/xen/include/asm-x86/mm.h	Fri Dec 11 08:58:06 2009 +0000
     3.3 @@ -530,6 +530,12 @@ int donate_page(
     3.4  
     3.5  int map_ldt_shadow_page(unsigned int);
     3.6  
     3.7 +#ifdef CONFIG_X86_64
     3.8 +extern int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm);
     3.9 +#else
    3.10 +int memory_add(uint64_t spfn, uint64_t epfn, uint32_t pxm) {return -ENOSYS};
    3.11 +#endif
    3.12 +
    3.13  #ifdef CONFIG_COMPAT
    3.14  void domain_set_alloc_bitsize(struct domain *d);
    3.15  unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits);
     4.1 --- a/xen/include/public/platform.h	Fri Dec 11 08:57:30 2009 +0000
     4.2 +++ b/xen/include/public/platform.h	Fri Dec 11 08:58:06 2009 +0000
     4.3 @@ -346,6 +346,15 @@ struct xenpf_cpu_hotadd
     4.4  	uint32_t pxm;
     4.5  };
     4.6  
     4.7 +#define XENPF_mem_hotadd    59
     4.8 +struct xenpf_mem_hotadd
     4.9 +{
    4.10 +    uint64_t spfn;
    4.11 +    uint64_t epfn;
    4.12 +    uint32_t pxm;
    4.13 +    uint32_t flags;
    4.14 +};
    4.15 +
    4.16  struct xen_platform_op {
    4.17      uint32_t cmd;
    4.18      uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
    4.19 @@ -364,6 +373,7 @@ struct xen_platform_op {
    4.20          struct xenpf_pcpuinfo          pcpu_info;
    4.21          struct xenpf_cpu_ol            cpu_ol;
    4.22          struct xenpf_cpu_hotadd        cpu_add;
    4.23 +        struct xenpf_mem_hotadd        mem_add;
    4.24          uint8_t                        pad[128];
    4.25      } u;
    4.26  };