ia64/xen-unstable

changeset 11726:0bb486157ff5

[IA64] expose p2m table. xen side part.

This patch introduces xen compile time option, xen_ia64_expose_p2m=y.
default is enabled.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Wed Oct 04 22:12:25 2006 -0600 (2006-10-04)
parents 7cfc7cb7cea7
children d1d9f3f6ca09
files xen/arch/ia64/Rules.mk xen/arch/ia64/vmx/vmx_init.c xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/mm.c xen/arch/ia64/xen/xensetup.c xen/include/asm-ia64/mm.h xen/include/public/arch-ia64.h
line diff
     1.1 --- a/xen/arch/ia64/Rules.mk	Wed Oct 04 22:12:14 2006 -0600
     1.2 +++ b/xen/arch/ia64/Rules.mk	Wed Oct 04 22:12:25 2006 -0600
     1.3 @@ -5,6 +5,7 @@ HAS_ACPI := y
     1.4  HAS_VGA  := y
     1.5  VALIDATE_VT	?= n
     1.6  no_warns ?= n
     1.7 +xen_ia64_expose_p2m	?= y
     1.8  
     1.9  ifneq ($(COMPILE_ARCH),$(TARGET_ARCH))
    1.10  CROSS_COMPILE ?= /usr/local/sp_env/v2.2.5/i686/bin/ia64-unknown-linux-
    1.11 @@ -36,6 +37,9 @@ CFLAGS	+= -g
    1.12  ifeq ($(VALIDATE_VT),y)
    1.13  CFLAGS  += -DVALIDATE_VT
    1.14  endif
    1.15 +ifeq ($(xen_ia64_expose_p2m),y)
    1.16 +CFLAGS	+= -DCONFIG_XEN_IA64_EXPOSE_P2M
    1.17 +endif
    1.18  ifeq ($(no_warns),y)
    1.19  CFLAGS	+= -Wa,--fatal-warnings -Werror -Wno-uninitialized
    1.20  endif
     2.1 --- a/xen/arch/ia64/vmx/vmx_init.c	Wed Oct 04 22:12:14 2006 -0600
     2.2 +++ b/xen/arch/ia64/vmx/vmx_init.c	Wed Oct 04 22:12:25 2006 -0600
     2.3 @@ -378,7 +378,8 @@ static void vmx_build_physmap_table(stru
     2.4  	    for (j = io_ranges[i].start;
     2.5  		j < io_ranges[i].start + io_ranges[i].size;
     2.6  		j += PAGE_SIZE)
     2.7 -		__assign_domain_page(d, j, io_ranges[i].type, ASSIGN_writable);
     2.8 +		(void)__assign_domain_page(d, j, io_ranges[i].type,
     2.9 +		                           ASSIGN_writable);
    2.10  	}
    2.11  
    2.12  	/* Map normal memory below 3G */
     3.1 --- a/xen/arch/ia64/xen/dom0_ops.c	Wed Oct 04 22:12:14 2006 -0600
     3.2 +++ b/xen/arch/ia64/xen/dom0_ops.c	Wed Oct 04 22:12:25 2006 -0600
     3.3 @@ -273,6 +273,9 @@ do_dom0vp_op(unsigned long cmd,
     3.4          ret = dom0vp_add_physmap(d, arg0, arg1, (unsigned int)arg2,
     3.5                                   (domid_t)arg3);
     3.6          break;
     3.7 +    case IA64_DOM0VP_expose_p2m:
     3.8 +        ret = dom0vp_expose_p2m(d, arg0, arg1, arg2, arg3);
     3.9 +        break;
    3.10      default:
    3.11          ret = -1;
    3.12  		printf("unknown dom0_vp_op 0x%lx\n", cmd);
     4.1 --- a/xen/arch/ia64/xen/mm.c	Wed Oct 04 22:12:14 2006 -0600
     4.2 +++ b/xen/arch/ia64/xen/mm.c	Wed Oct 04 22:12:25 2006 -0600
     4.3 @@ -806,7 +806,7 @@ flags_to_prot (unsigned long flags)
     4.4  // flags: currently only ASSIGN_readonly, ASSIGN_nocache
     4.5  // This is called by assign_domain_mmio_page().
     4.6  // So accessing to pte is racy.
     4.7 -void
     4.8 +int
     4.9  __assign_domain_page(struct domain *d,
    4.10                       unsigned long mpaddr, unsigned long physaddr,
    4.11                       unsigned long flags)
    4.12 @@ -822,8 +822,11 @@ void
    4.13      old_pte = __pte(0);
    4.14      new_pte = pfn_pte(physaddr >> PAGE_SHIFT, __pgprot(prot));
    4.15      ret_pte = ptep_cmpxchg_rel(&d->arch.mm, mpaddr, pte, old_pte, new_pte);
    4.16 -    if (pte_val(ret_pte) == pte_val(old_pte))
    4.17 +    if (pte_val(ret_pte) == pte_val(old_pte)) {
    4.18          smp_mb();
    4.19 +        return 0;
    4.20 +    }
    4.21 +    return -EAGAIN;
    4.22  }
    4.23  
    4.24  /* get_page() and map a physical address to the specified metaphysical addr */
    4.25 @@ -840,7 +843,7 @@ assign_domain_page(struct domain *d,
    4.26      set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
    4.27      // because __assign_domain_page() uses set_pte_rel() which has
    4.28      // release semantics, smp_mb() isn't needed.
    4.29 -    __assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
    4.30 +    (void)__assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
    4.31  }
    4.32  
    4.33  int
    4.34 @@ -863,8 +866,8 @@ ioports_permit_access(struct domain *d, 
    4.35      lp_offset = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp));
    4.36  
    4.37      for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE)
    4.38 -        __assign_domain_page(d, IO_PORTS_PADDR + off,
    4.39 -                             __pa(ia64_iobase) + off, ASSIGN_nocache);
    4.40 +        (void)__assign_domain_page(d, IO_PORTS_PADDR + off,
    4.41 +                                   __pa(ia64_iobase) + off, ASSIGN_nocache);
    4.42  
    4.43      return 0;
    4.44  }
    4.45 @@ -933,7 +936,7 @@ assign_domain_same_page(struct domain *d
    4.46      //XXX optimization
    4.47      unsigned long end = PAGE_ALIGN(mpaddr + size);
    4.48      for (mpaddr &= PAGE_MASK; mpaddr < end; mpaddr += PAGE_SIZE) {
    4.49 -        __assign_domain_page(d, mpaddr, mpaddr, flags);
    4.50 +        (void)__assign_domain_page(d, mpaddr, mpaddr, flags);
    4.51      }
    4.52  }
    4.53  
    4.54 @@ -1256,6 +1259,126 @@ out1:
    4.55      return error;
    4.56  }
    4.57  
    4.58 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
    4.59 +static struct page_info* p2m_pte_zero_page = NULL;
    4.60 +
    4.61 +void
    4.62 +expose_p2m_init(void)
    4.63 +{
    4.64 +    pte_t* pte;
    4.65 +
    4.66 +    pte = pte_alloc_one_kernel(NULL, 0);
    4.67 +    BUG_ON(pte == NULL);
    4.68 +    smp_mb();// make contents of the page visible.
    4.69 +    p2m_pte_zero_page = virt_to_page(pte);
    4.70 +}
    4.71 +
    4.72 +static int
    4.73 +expose_p2m_page(struct domain* d, unsigned long mpaddr, struct page_info* page)
    4.74 +{
    4.75 +    // we can't get_page(page) here.
    4.76 +    // pte page is allocated form xen heap.(see pte_alloc_one_kernel().)
    4.77 +    // so that the page has NULL page owner and it's reference count
    4.78 +    // is useless.
    4.79 +    // see also relinquish_pte()'s page_get_owner() == NULL check.
    4.80 +    BUG_ON(page_get_owner(page) != NULL);
    4.81 +
    4.82 +    return __assign_domain_page(d, mpaddr, page_to_maddr(page),
    4.83 +                                ASSIGN_readonly);
    4.84 +}
    4.85 +
    4.86 +// It is possible to optimize loop, But this isn't performance critical.
    4.87 +unsigned long
    4.88 +dom0vp_expose_p2m(struct domain* d,
    4.89 +                  unsigned long conv_start_gpfn,
    4.90 +                  unsigned long assign_start_gpfn,
    4.91 +                  unsigned long expose_size, unsigned long granule_pfn)
    4.92 +{
    4.93 +    unsigned long expose_num_pfn = expose_size >> PAGE_SHIFT;
    4.94 +    unsigned long i;
    4.95 +    volatile pte_t* conv_pte;
    4.96 +    volatile pte_t* assign_pte;
    4.97 +
    4.98 +    if ((expose_size % PAGE_SIZE) != 0 ||
    4.99 +        (granule_pfn % PTRS_PER_PTE) != 0 ||
   4.100 +        (expose_num_pfn % PTRS_PER_PTE) != 0 ||
   4.101 +        (conv_start_gpfn % granule_pfn) != 0 ||
   4.102 +        (assign_start_gpfn % granule_pfn) != 0 ||
   4.103 +        (expose_num_pfn % granule_pfn) != 0) {
   4.104 +        DPRINTK("%s conv_start_gpfn 0x%016lx assign_start_gpfn 0x%016lx "
   4.105 +                "expose_size 0x%016lx granulte_pfn 0x%016lx\n", __func__, 
   4.106 +                conv_start_gpfn, assign_start_gpfn, expose_size, granule_pfn);
   4.107 +        return -EINVAL;
   4.108 +    }
   4.109 +
   4.110 +    if (granule_pfn != PTRS_PER_PTE) {
   4.111 +        DPRINTK("%s granule_pfn 0x%016lx PTRS_PER_PTE 0x%016lx\n",
   4.112 +                __func__, granule_pfn, PTRS_PER_PTE);
   4.113 +        return -ENOSYS;
   4.114 +    }
   4.115 +
   4.116 +    // allocate pgd, pmd.
   4.117 +    i = conv_start_gpfn;
   4.118 +    while (i < expose_num_pfn) {
   4.119 +        conv_pte = lookup_noalloc_domain_pte(d, (conv_start_gpfn + i) <<
   4.120 +                                             PAGE_SHIFT);
   4.121 +        if (conv_pte == NULL) {
   4.122 +            i++;
   4.123 +            continue;
   4.124 +        }
   4.125 +        
   4.126 +        assign_pte = lookup_alloc_domain_pte(d, (assign_start_gpfn <<
   4.127 +                                             PAGE_SHIFT) + i * sizeof(pte_t));
   4.128 +        if (assign_pte == NULL) {
   4.129 +            DPRINTK("%s failed to allocate pte page\n", __func__);
   4.130 +            return -ENOMEM;
   4.131 +        }
   4.132 +
   4.133 +        // skip to next pte page
   4.134 +        i += PTRS_PER_PTE;
   4.135 +        i &= ~(PTRS_PER_PTE - 1);
   4.136 +    }
   4.137 +
   4.138 +    // expose pte page
   4.139 +    i = 0;
   4.140 +    while (i < expose_num_pfn) {
   4.141 +        conv_pte = lookup_noalloc_domain_pte(d, (conv_start_gpfn + i) <<
   4.142 +                                             PAGE_SHIFT);
   4.143 +        if (conv_pte == NULL) {
   4.144 +            i++;
   4.145 +            continue;
   4.146 +        }
   4.147 +
   4.148 +        if (expose_p2m_page(d, (assign_start_gpfn << PAGE_SHIFT) +
   4.149 +                            i * sizeof(pte_t), virt_to_page(conv_pte)) < 0) {
   4.150 +            DPRINTK("%s failed to assign page\n", __func__);
   4.151 +            return -EAGAIN;
   4.152 +        }
   4.153 +
   4.154 +        // skip to next pte page
   4.155 +        i += PTRS_PER_PTE;
   4.156 +        i &= ~(PTRS_PER_PTE - 1);
   4.157 +    }
   4.158 +
   4.159 +    // expose p2m_pte_zero_page 
   4.160 +    for (i = 0; i < expose_num_pfn / PTRS_PER_PTE + 1; i++) {
   4.161 +        assign_pte = lookup_noalloc_domain_pte(d, (assign_start_gpfn + i) <<
   4.162 +                                               PAGE_SHIFT);
   4.163 +        BUG_ON(assign_pte == NULL);
   4.164 +        if (pte_present(*assign_pte)) {
   4.165 +            continue;
   4.166 +        }
   4.167 +        if (expose_p2m_page(d, (assign_start_gpfn + i) << PAGE_SHIFT,
   4.168 +                            p2m_pte_zero_page) < 0) {
   4.169 +            DPRINTK("%s failed to assign zero-pte page\n", __func__);
   4.170 +            return -EAGAIN;
   4.171 +        }
   4.172 +    }
   4.173 +    
   4.174 +    return 0;
   4.175 +}
   4.176 +#endif
   4.177 +
   4.178  // grant table host mapping
   4.179  // mpaddr: host_addr: pseudo physical address
   4.180  // mfn: frame: machine page frame
     5.1 --- a/xen/arch/ia64/xen/xensetup.c	Wed Oct 04 22:12:14 2006 -0600
     5.2 +++ b/xen/arch/ia64/xen/xensetup.c	Wed Oct 04 22:12:25 2006 -0600
     5.3 @@ -499,6 +499,8 @@ printk("num_online_cpus=%d, max_cpus=%d\
     5.4          efi.hcdp = NULL;
     5.5      }
     5.6  
     5.7 +    expose_p2m_init();
     5.8 +
     5.9      /* Create initial domain 0. */
    5.10      dom0 = domain_create(0);
    5.11      if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
     6.1 --- a/xen/include/asm-ia64/mm.h	Wed Oct 04 22:12:14 2006 -0600
     6.2 +++ b/xen/include/asm-ia64/mm.h	Wed Oct 04 22:12:25 2006 -0600
     6.3 @@ -424,7 +424,7 @@ extern void alloc_dom_xen_and_dom_io(voi
     6.4  extern void relinquish_mm(struct domain* d);
     6.5  extern struct page_info * assign_new_domain_page(struct domain *d, unsigned long mpaddr);
     6.6  extern void assign_new_domain0_page(struct domain *d, unsigned long mpaddr);
     6.7 -extern void __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags);
     6.8 +extern int __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags);
     6.9  extern void assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr);
    6.10  extern void assign_domain_io_page(struct domain *d, unsigned long mpaddr, unsigned long flags);
    6.11  struct p2m_entry;
    6.12 @@ -439,6 +439,13 @@ extern unsigned long ____lookup_domain_m
    6.13  extern unsigned long do_dom0vp_op(unsigned long cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3);
    6.14  extern unsigned long dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order);
    6.15  extern unsigned long dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid);
    6.16 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
    6.17 +extern void expose_p2m_init(void);
    6.18 +extern unsigned long dom0vp_expose_p2m(struct domain* d, unsigned long conv_start_gpfn, unsigned long assign_start_gpfn, unsigned long expose_size, unsigned long granule_pfn);
    6.19 +#else
    6.20 +#define expose_p2m_init()       do { } while (0)
    6.21 +#define dom0vp_expose_p2m(d, conv_start_gpfn, assign_start_gpfn, expose_size, granule_pfn)	(-ENOSYS)
    6.22 +#endif
    6.23  
    6.24  extern volatile unsigned long *mpt_table;
    6.25  extern unsigned long gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
     7.1 --- a/xen/include/public/arch-ia64.h	Wed Oct 04 22:12:14 2006 -0600
     7.2 +++ b/xen/include/public/arch-ia64.h	Wed Oct 04 22:12:25 2006 -0600
     7.3 @@ -348,6 +348,9 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_conte
     7.4  /* Assign machine page frame to dom0's pseudo physical address space.  */
     7.5  #define IA64_DOM0VP_add_physmap         6
     7.6  
     7.7 +/* expose the p2m table into domain */
     7.8 +#define IA64_DOM0VP_expose_p2m          7
     7.9 +
    7.10  // flags for page assignement to pseudo physical address space
    7.11  #define _ASSIGN_readonly                0
    7.12  #define ASSIGN_readonly                 (1UL << _ASSIGN_readonly)