direct-io.hg

changeset 15295:c2768258711d

[IA64] memmap: introduce memmap_info_t

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Mon May 21 10:10:31 2007 -0600 (2007-05-21)
parents caafa45d24b3
children 8fb8d50272d2
files tools/libxc/xc_dom_ia64.c xen/arch/ia64/xen/dom_fw.c xen/include/public/arch-ia64.h
line diff
     1.1 --- a/tools/libxc/xc_dom_ia64.c	Mon May 21 10:09:33 2007 -0600
     1.2 +++ b/tools/libxc/xc_dom_ia64.c	Mon May 21 10:10:31 2007 -0600
     1.3 @@ -77,6 +77,8 @@ static int shared_info_ia64(struct xc_do
     1.4      for (i = 0; i < MAX_VIRT_CPUS; i++)
     1.5          shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
     1.6      shared_info->arch.start_info_pfn = dom->start_info_pfn;
     1.7 +    shared_info->arch.memmap_info_num_pages = 1;
     1.8 +    shared_info->arch.memmap_info_pfn = dom->start_info_pfn - 1;
     1.9      return 0;
    1.10  }
    1.11  
    1.12 @@ -129,6 +131,8 @@ static void __init register_arch_hooks(v
    1.13      xc_dom_register_arch_hooks(&xc_dom_arch_ia64be);
    1.14  }
    1.15  
    1.16 +#include "xc_efi.h"
    1.17 +
    1.18  int arch_setup_meminit(struct xc_dom_image *dom)
    1.19  {
    1.20      xen_pfn_t pfn;
    1.21 @@ -146,6 +150,59 @@ int arch_setup_meminit(struct xc_dom_ima
    1.22      return rc;
    1.23  }
    1.24  
    1.25 +static int ia64_setup_memmap(struct xc_dom_image *dom)
    1.26 +{
    1.27 +    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
    1.28 +    unsigned long memmap_info_pfn;
    1.29 +    xen_ia64_memmap_info_t* memmap_info;
    1.30 +    unsigned int num_mds;
    1.31 +    efi_memory_desc_t *md;
    1.32 +
    1.33 +    char* start_info;
    1.34 +    struct xen_ia64_boot_param* bp;
    1.35 +
    1.36 +    /* setup memmap page */
    1.37 +    memmap_info_pfn = dom->start_info_pfn - 1;
    1.38 +    xc_dom_printf("%s: memmap: mfn 0x%" PRIpfn "\n",
    1.39 +		  __FUNCTION__, memmap_info_pfn);
    1.40 +    memmap_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
    1.41 +                                       page_size,
    1.42 +                                       PROT_READ | PROT_WRITE,
    1.43 +                                       memmap_info_pfn);
    1.44 +    if (NULL == memmap_info)
    1.45 +        return -1;
    1.46 +    /* [0, total_pages) */
    1.47 +    memmap_info->efi_memdesc_size = sizeof(md[0]);
    1.48 +    memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
    1.49 +    num_mds = 0;
    1.50 +    md = (efi_memory_desc_t*)&memmap_info->memdesc;
    1.51 +    md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
    1.52 +    md[num_mds].pad = 0;
    1.53 +    md[num_mds].phys_addr = 0;
    1.54 +    md[num_mds].virt_addr = 0;
    1.55 +    md[num_mds].num_pages = dom->total_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT);
    1.56 +    md[num_mds].attribute = EFI_MEMORY_WB;
    1.57 +    num_mds++;
    1.58 +    memmap_info->efi_memmap_size = num_mds * sizeof(md[0]);
    1.59 +    munmap(memmap_info, page_size);
    1.60 +
    1.61 +    /* kludge: we need to pass memmap_info page's pfn somehow.
    1.62 +     * we use xen_ia64_boot_param::efi_memmap for this purpose */
    1.63 +    start_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
    1.64 +				      page_size,
    1.65 +				      PROT_READ | PROT_WRITE,
    1.66 +				      dom->start_info_pfn);
    1.67 +    if (NULL == start_info)
    1.68 +        return -1;
    1.69 +    bp = (struct xen_ia64_boot_param*)(start_info + sizeof(start_info_t));
    1.70 +    memset(bp, 0, sizeof(*bp));
    1.71 +    bp->efi_memmap = memmap_info_pfn;
    1.72 +    /* 4 = memmap info page, start info page, xenstore page and console page */
    1.73 +    bp->efi_memmap_size = 4 * PAGE_SIZE;
    1.74 +    munmap(start_info, page_size);
    1.75 +    return 0;
    1.76 +}
    1.77 +
    1.78  int arch_setup_bootearly(struct xc_dom_image *dom)
    1.79  {
    1.80      DECLARE_DOMCTL;
    1.81 @@ -153,6 +210,10 @@ int arch_setup_bootearly(struct xc_dom_i
    1.82  
    1.83      xc_dom_printf("%s: setup firmware\n", __FUNCTION__);
    1.84  
    1.85 +    rc = ia64_setup_memmap(dom);
    1.86 +    if (rc)
    1.87 +        return rc;
    1.88 +
    1.89      memset(&domctl, 0, sizeof(domctl));
    1.90      domctl.cmd = XEN_DOMCTL_arch_setup;
    1.91      domctl.domain = dom->guest_domid;
    1.92 @@ -160,8 +221,7 @@ int arch_setup_bootearly(struct xc_dom_i
    1.93  
    1.94      domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT)
    1.95          + sizeof(start_info_t);
    1.96 -    /* 3 = start info page, xenstore page and console page */
    1.97 -    domctl.u.arch_setup.maxmem = (dom->total_pages - 3) << PAGE_SHIFT;
    1.98 +    domctl.u.arch_setup.maxmem = dom->total_pages << PAGE_SHIFT;
    1.99      rc = do_domctl(dom->guest_xc, &domctl);
   1.100      return rc;
   1.101  }
     2.1 --- a/xen/arch/ia64/xen/dom_fw.c	Mon May 21 10:09:33 2007 -0600
     2.2 +++ b/xen/arch/ia64/xen/dom_fw.c	Mon May 21 10:10:31 2007 -0600
     2.3 @@ -508,6 +508,63 @@ struct fw_tables {
     2.4  #define FW_FIELD_MPA(field) \
     2.5     FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field)
     2.6  
     2.7 +static void
     2.8 +setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables,
     2.9 +		       int *num_mds)
    2.10 +{
    2.11 +	int i;
    2.12 +	efi_memory_desc_t *md;
    2.13 +	efi_memory_desc_t *last_mem_md = NULL;
    2.14 +	xen_ia64_memmap_info_t* memmap_info;
    2.15 +	unsigned long paddr_start;
    2.16 +	unsigned long paddr_end;
    2.17 +
    2.18 +	for (i = *num_mds - 1; i >= 0; i--) {
    2.19 +		md = &tables->efi_memmap[i];
    2.20 +		if (md->attribute == EFI_MEMORY_WB &&
    2.21 +		    md->type == EFI_CONVENTIONAL_MEMORY &&
    2.22 +		    md->num_pages >
    2.23 +		    2 * (1UL << (PAGE_SHIFT - EFI_PAGE_SHIFT))) {
    2.24 +			last_mem_md = md;
    2.25 +			break;
    2.26 +		}
    2.27 +	}
    2.28 +
    2.29 +	if (last_mem_md == NULL) {
    2.30 +		printk("%s: warning: "
    2.31 +		       "no dom0 contiguous memory to hold memory map\n",
    2.32 +		       __func__);
    2.33 +		return;
    2.34 +	}
    2.35 +	paddr_end = last_mem_md->phys_addr +
    2.36 +		(last_mem_md->num_pages << EFI_PAGE_SHIFT);
    2.37 +	paddr_start = (paddr_end - PAGE_SIZE) & PAGE_MASK;
    2.38 +	last_mem_md->num_pages -=
    2.39 +		(paddr_end - paddr_start) / (1UL << EFI_PAGE_SHIFT);
    2.40 +
    2.41 +	md = &tables->efi_memmap[*num_mds];
    2.42 +	(*num_mds)++;
    2.43 +	md->type = EFI_RUNTIME_SERVICES_DATA;
    2.44 +	md->phys_addr = paddr_start;
    2.45 +	md->virt_addr = 0;
    2.46 +	md->num_pages = 1UL << (PAGE_SHIFT - EFI_PAGE_SHIFT);
    2.47 +	md->attribute = EFI_MEMORY_WB;
    2.48 +
    2.49 +	memmap_info = domain_mpa_to_imva(d, md->phys_addr);
    2.50 +	BUG_ON(*num_mds > NUM_MEM_DESCS);
    2.51 +
    2.52 +	memmap_info->efi_memdesc_size = sizeof(md[0]);
    2.53 +	memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
    2.54 +	memmap_info->efi_memmap_size = *num_mds * sizeof(md[0]);
    2.55 +	memcpy(&memmap_info->memdesc, &tables->efi_memmap[0],
    2.56 +	       memmap_info->efi_memmap_size);
    2.57 +	d->shared_info->arch.memmap_info_num_pages = 1;
    2.58 +	d->shared_info->arch.memmap_info_pfn = md->phys_addr >> PAGE_SHIFT;
    2.59 +
    2.60 +	sort(tables->efi_memmap, *num_mds, sizeof(efi_memory_desc_t),
    2.61 +	     efi_mdt_cmp, NULL);
    2.62 +}
    2.63 +
    2.64  /* Complete the dom0 memmap.  */
    2.65  static int
    2.66  complete_dom0_memmap(struct domain *d,
    2.67 @@ -672,9 +729,152 @@ complete_dom0_memmap(struct domain *d,
    2.68  						PAGE_SIZE, flags);
    2.69  		}
    2.70  	}
    2.71 +	setup_dom0_memmap_info(d, tables, &num_mds);
    2.72  	return num_mds;
    2.73  }
    2.74  	
    2.75 +static int
    2.76 +complete_domu_memmap(struct domain *d,
    2.77 +                     struct fw_tables *tables,
    2.78 +                     unsigned long maxmem,
    2.79 +                     int num_mds,
    2.80 +		     unsigned long memmap_info_pfn,
    2.81 +		     unsigned long memmap_size)
    2.82 +{
    2.83 +	efi_memory_desc_t *md;
    2.84 +	int i = num_mds; /* for MAKE_MD */
    2.85 +	int create_memmap = 0;
    2.86 +	xen_ia64_memmap_info_t* memmap_info;
    2.87 +	unsigned long paddr_start;
    2.88 +	unsigned long paddr_end;
    2.89 +	void *p;
    2.90 +	void *memmap_start;
    2.91 +	void *memmap_end;
    2.92 +
    2.93 +	if (memmap_info_pfn == 0 || memmap_size == 0) {
    2.94 +		/* old domain builder which doesn't setup
    2.95 +		 * memory map. create it for compatibility */
    2.96 +		memmap_info_pfn = (maxmem >> PAGE_SHIFT) - 1;
    2.97 +		/* 4 = memmap info page, start info page, xenstore page and
    2.98 +		   console page */
    2.99 +		memmap_size = 4 << PAGE_SHIFT;
   2.100 +		create_memmap = 1;
   2.101 +	}
   2.102 +	paddr_start = memmap_info_pfn << PAGE_SHIFT;
   2.103 +	paddr_end = paddr_start + memmap_size;
   2.104 +	memmap_info = domain_mpa_to_imva(d, paddr_start);
   2.105 +	if (memmap_info->efi_memmap_size == 0) {
   2.106 +		create_memmap = 1;
   2.107 +	} else if (memmap_info->efi_memdesc_size != sizeof(md[0]) ||
   2.108 +		   memmap_info->efi_memdesc_version !=
   2.109 +		   EFI_MEMORY_DESCRIPTOR_VERSION) {
   2.110 +		printk(XENLOG_WARNING
   2.111 +		       "%s: Warning: unknown memory map "
   2.112 +		       "memmap size %"PRIu64" "
   2.113 +		       "memdesc size %"PRIu64" "
   2.114 +		       "version %"PRIu32"\n",
   2.115 +		       __func__,
   2.116 +		       memmap_info->efi_memmap_size,
   2.117 +		       memmap_info->efi_memdesc_size,
   2.118 +		       memmap_info->efi_memdesc_version);
   2.119 +		create_memmap = 1;
   2.120 +	} else if (max(memmap_size, memmap_info->efi_memmap_size) >
   2.121 +		   PAGE_SIZE - sizeof(*memmap_info)) {
   2.122 +		/*
   2.123 +		 * curently memmap spanning more than single page isn't
   2.124 +		 * supported.
   2.125 +		 */
   2.126 +		printk(XENLOG_WARNING
   2.127 +		       "%s: Warning: too large memmap_size %"PRIu64"\n",
   2.128 +		       __func__, memmap_size);
   2.129 +		return -ENOSYS;
   2.130 +	}
   2.131 +	
   2.132 +	if (create_memmap) {
   2.133 +		/* old domain builder which doesn't setup
   2.134 +		 * memory map. create it for compatibility */
   2.135 +		memmap_info->efi_memdesc_size = sizeof(md[0]);
   2.136 +		memmap_info->efi_memdesc_version =
   2.137 +			EFI_MEMORY_DESCRIPTOR_VERSION;
   2.138 +		memmap_info->efi_memmap_size = 1 * sizeof(md[0]);
   2.139 +		md = (efi_memory_desc_t*)&memmap_info->memdesc;
   2.140 +		md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
   2.141 +		md[num_mds].pad = 0;
   2.142 +		md[num_mds].phys_addr = 0;
   2.143 +		md[num_mds].virt_addr = 0;
   2.144 +		md[num_mds].num_pages = maxmem >> EFI_PAGE_SHIFT;
   2.145 +		md[num_mds].attribute = EFI_MEMORY_WB;
   2.146 +	}
   2.147 +	/*
   2.148 +	 * XXX kludge.
   2.149 +	 * when XEN_DOMCTL_arch_setup is called, shared_info can't
   2.150 +	 * be accessed by libxc so that memmap_info_pfn isn't initialized.
   2.151 +	 * But dom_fw_set_convmem_end() requires it, so here we initialize it.
   2.152 +	 */
   2.153 +	d->shared_info->arch.memmap_info_num_pages = 1;
   2.154 +	d->shared_info->arch.memmap_info_pfn = memmap_info_pfn;
   2.155 +
   2.156 +	memmap_start = &memmap_info->memdesc;
   2.157 +	memmap_end = memmap_start + memmap_info->efi_memmap_size;
   2.158 +	/* XXX Currently the table must be in a single page. */
   2.159 +	if ((unsigned long)memmap_end > (unsigned long)memmap_info + PAGE_SIZE)
   2.160 +		return -EINVAL;
   2.161 +
   2.162 +	/* sort it bofore use
   2.163 +	 * XXX: this is created by user space domain builder so that
   2.164 +	 * we should check its integrity */
   2.165 +	sort(&memmap_info->memdesc,
   2.166 +	     memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size,
   2.167 +	     memmap_info->efi_memdesc_size,
   2.168 +	     efi_mdt_cmp, NULL);
   2.169 +
   2.170 +	for (p = memmap_start; p < memmap_end; p += memmap_info->efi_memdesc_size) {
   2.171 +		unsigned long start;
   2.172 +		unsigned long end;
   2.173 +		md = p;
   2.174 +		start = md->phys_addr;
   2.175 +		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
   2.176 +
   2.177 +		if (start < FW_END_PADDR)
   2.178 +			start = FW_END_PADDR;
   2.179 +		if (end <= start)
   2.180 +			continue;
   2.181 +
   2.182 +		/* exclude [paddr_start, paddr_end) */
   2.183 +		if (paddr_end <= start || end <= paddr_start) {
   2.184 +			MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
   2.185 +				start, end);
   2.186 +		} else if (paddr_start <= start && paddr_end < end) {
   2.187 +			MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
   2.188 +				paddr_end, end);
   2.189 +		} else if (start < paddr_start && end <= paddr_end) {
   2.190 +			MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
   2.191 +				start, paddr_start);
   2.192 +		} else {
   2.193 +			MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
   2.194 +				start, paddr_start);
   2.195 +			MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
   2.196 +				paddr_end, end);
   2.197 +		}
   2.198 +		d->arch.convmem_end = end;
   2.199 +	}
   2.200 +
   2.201 +	/* memmap info page. */
   2.202 +	MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB,
   2.203 +		paddr_start, paddr_end);
   2.204 +	if (d->arch.convmem_end < paddr_end)
   2.205 +		d->arch.convmem_end = paddr_end;
   2.206 +
   2.207 +	/* Create an entry for IO ports.  */
   2.208 +	MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
   2.209 +		IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE);
   2.210 +
   2.211 +	num_mds = i;
   2.212 +	sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t),
   2.213 +	     efi_mdt_cmp, NULL);
   2.214 +	return num_mds;
   2.215 +}
   2.216 +
   2.217  static void
   2.218  dom_fw_init(struct domain *d,
   2.219              struct ia64_boot_param *bp,
   2.220 @@ -842,18 +1042,17 @@ dom_fw_init(struct domain *d,
   2.221  	if (d != dom0 || running_on_sim) {
   2.222  		/* DomU (or hp-ski).
   2.223  		   Create a continuous memory area.  */
   2.224 -		/* Memory.  */
   2.225 -		MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
   2.226 -		        FW_END_PADDR, maxmem);
   2.227 -		d->arch.convmem_end = maxmem;
   2.228 -		
   2.229 -		/* Create an entry for IO ports.  */
   2.230 -		MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
   2.231 -		        IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE);
   2.232 -
   2.233 -		num_mds = i;
   2.234 -	}
   2.235 -	else {
   2.236 +		/* kludge: bp->efi_memmap is used to pass memmap_info
   2.237 +		 * page's pfn and number of pages to reserve. 
   2.238 +		 * Currently the following pages must be reserved.
   2.239 +		 * memmap info page, start info page, xenstore page
   2.240 +		 * and console page.
   2.241 +		 * see ia64_setup_memmap() @ xc_dom_boot.c
   2.242 +		 */
   2.243 +		num_mds = complete_domu_memmap(d, tables, maxmem, i,
   2.244 +					       bp->efi_memmap,
   2.245 +					       bp->efi_memmap_size);
   2.246 +	} else {
   2.247  		/* Dom0.
   2.248  		   We must preserve ACPI data from real machine,
   2.249  		   as well as IO areas.  */
     3.1 --- a/xen/include/public/arch-ia64.h	Mon May 21 10:09:33 2007 -0600
     3.2 +++ b/xen/include/public/arch-ia64.h	Mon May 21 10:10:31 2007 -0600
     3.3 @@ -339,7 +339,12 @@ struct arch_shared_info {
     3.4      /* Interrupt vector for event channel.  */
     3.5      int evtchn_vector;
     3.6  
     3.7 -    uint64_t pad[32];
     3.8 +    /* PFN of memmap_info page */
     3.9 +    unsigned int memmap_info_num_pages;/* currently only = 1 case is
    3.10 +                                          supported. */
    3.11 +    unsigned long memmap_info_pfn;
    3.12 +
    3.13 +    uint64_t pad[31];
    3.14  };
    3.15  typedef struct arch_shared_info arch_shared_info_t;
    3.16