direct-io.hg

changeset 15296:8fb8d50272d2

[IA64] memmap: preliminary domain-builder clean up.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Mon May 21 13:14:56 2007 -0600 (2007-05-21)
parents c2768258711d
children 35530f81e638
files xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/dom_fw.c xen/arch/ia64/xen/domain.c xen/include/asm-ia64/dom_fw.h
line diff
     1.1 --- a/xen/arch/ia64/xen/dom0_ops.c	Mon May 21 10:10:31 2007 -0600
     1.2 +++ b/xen/arch/ia64/xen/dom0_ops.c	Mon May 21 13:14:56 2007 -0600
     1.3 @@ -101,21 +101,22 @@ long arch_do_domctl(xen_domctl_t *op, XE
     1.4                  if (!vmx_enabled) {
     1.5                      printk("No VMX hardware feature for vmx domain.\n");
     1.6                      ret = -EINVAL;
     1.7 -                    break;
     1.8 +                } else {
     1.9 +                    d->arch.is_vti = 1;
    1.10 +                    vmx_setup_platform(d);
    1.11                  }
    1.12 -                d->arch.is_vti = 1;
    1.13 -                vmx_setup_platform(d);
    1.14              }
    1.15              else {
    1.16 -                dom_fw_setup(d, ds->bp, ds->maxmem);
    1.17 -                if (ds->xsi_va)
    1.18 -                    d->arch.shared_info_va = ds->xsi_va;
    1.19                  if (ds->hypercall_imm) {
    1.20 +                    /* dom_fw_setup() reads d->arch.breakimm */
    1.21                      struct vcpu *v;
    1.22                      d->arch.breakimm = ds->hypercall_imm;
    1.23                      for_each_vcpu (d, v)
    1.24                          v->arch.breakimm = d->arch.breakimm;
    1.25                  }
    1.26 +                if (ds->xsi_va)
    1.27 +                    d->arch.shared_info_va = ds->xsi_va;
    1.28 +                ret = dom_fw_setup(d, ds->bp, ds->maxmem);
    1.29                  {
    1.30                      /*
    1.31                       * XXX IA64_SHARED_INFO_PADDR
     2.1 --- a/xen/arch/ia64/xen/dom_fw.c	Mon May 21 10:10:31 2007 -0600
     2.2 +++ b/xen/arch/ia64/xen/dom_fw.c	Mon May 21 13:14:56 2007 -0600
     2.3 @@ -3,7 +3,8 @@
     2.4   *  Copyright (C) 2004 Hewlett-Packard Co.
     2.5   *       Dan Magenheimer (dan.magenheimer@hp.com)
     2.6   *
     2.7 - * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
     2.8 + * Copyright (c) 2006, 2007
     2.9 + *                    Isaku Yamahata <yamahata at valinux co jp>
    2.10   *                    VA Linux Systems Japan K.K.
    2.11   *                    dom0 vp model support
    2.12   */
    2.13 @@ -45,7 +46,8 @@ extern unsigned long running_on_sim;
    2.14  
    2.15  #define EFI_HYPERCALL_PATCH(tgt, call)					\
    2.16  	do {								\
    2.17 -		dom_efi_hypercall_patch(d, FW_HYPERCALL_##call##_PADDR,	\
    2.18 +		dom_efi_hypercall_patch(brkimm,				\
    2.19 +					FW_HYPERCALL_##call##_PADDR,	\
    2.20  		                 FW_HYPERCALL_##call, hypercalls_imva);	\
    2.21  		/* Descriptor address.  */                              \
    2.22  		tables->efi_runtime.tgt =                               \
    2.23 @@ -146,7 +148,7 @@ build_pal_hypercall_bundles(u64 *imva, u
    2.24  
    2.25  // builds a hypercall bundle at domain physical address
    2.26  static void
    2.27 -dom_fpswa_hypercall_patch(struct domain *d, unsigned long imva)
    2.28 +dom_fpswa_hypercall_patch(u64 brkimm, unsigned long imva)
    2.29  {
    2.30  	unsigned long *entry_imva, *patch_imva;
    2.31  	const unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR;
    2.32 @@ -161,36 +163,34 @@ dom_fpswa_hypercall_patch(struct domain 
    2.33  	*entry_imva++ = patch_paddr;
    2.34  	*entry_imva   = 0;
    2.35  
    2.36 -	build_hypercall_bundle(patch_imva, d->arch.breakimm,
    2.37 -	                       FW_HYPERCALL_FPSWA, 1);
    2.38 +	build_hypercall_bundle(patch_imva, brkimm, FW_HYPERCALL_FPSWA, 1);
    2.39  }
    2.40  
    2.41  // builds a hypercall bundle at domain physical address
    2.42  static void
    2.43 -dom_efi_hypercall_patch(struct domain *d, unsigned long paddr,
    2.44 +dom_efi_hypercall_patch(u64 brkimm, unsigned long paddr,
    2.45                          unsigned long hypercall, unsigned long imva)
    2.46  {
    2.47  	build_hypercall_bundle((u64 *)(imva + paddr - FW_HYPERCALL_BASE_PADDR),
    2.48 -	                       d->arch.breakimm, hypercall, 1);
    2.49 +	                       brkimm, hypercall, 1);
    2.50  }
    2.51  
    2.52  // builds a hypercall bundle at domain physical address
    2.53  static void
    2.54 -dom_fw_hypercall_patch(struct domain *d, unsigned long paddr,
    2.55 -                       unsigned long hypercall,unsigned long ret,
    2.56 +dom_fw_hypercall_patch(u64 brkimm, unsigned long paddr,
    2.57 +		       unsigned long hypercall,unsigned long ret,
    2.58                         unsigned long imva)
    2.59  {
    2.60  	build_hypercall_bundle((u64 *)(imva + paddr - FW_HYPERCALL_BASE_PADDR),
    2.61 -	                       d->arch.breakimm, hypercall, ret);
    2.62 +	                       brkimm, hypercall, ret);
    2.63  }
    2.64  
    2.65  static void
    2.66 -dom_fw_pal_hypercall_patch(struct domain *d, unsigned long paddr,
    2.67 -                           unsigned long imva)
    2.68 +dom_fw_pal_hypercall_patch(u64 brkimm, unsigned long paddr, unsigned long imva)
    2.69  {
    2.70  	build_pal_hypercall_bundles((u64*)(imva + paddr -
    2.71  	                            FW_HYPERCALL_BASE_PADDR),
    2.72 -	                            d->arch.breakimm, FW_HYPERCALL_PAL_CALL);
    2.73 +	                            brkimm, FW_HYPERCALL_PAL_CALL);
    2.74  }
    2.75  
    2.76  static inline void
    2.77 @@ -241,6 +241,17 @@ acpi_update_lsapic (acpi_table_entry_hea
    2.78  	return 0;
    2.79  }
    2.80  
    2.81 +static u8
    2.82 +generate_acpi_checksum(void *tbl, unsigned long len)
    2.83 +{
    2.84 +	u8 *ptr, sum = 0;
    2.85 +
    2.86 +	for (ptr = tbl; len > 0 ; len--, ptr++)
    2.87 +		sum += *ptr;
    2.88 +
    2.89 +	return 0 - sum;
    2.90 +}
    2.91 +
    2.92  static int __init
    2.93  acpi_patch_plat_int_src (
    2.94  	acpi_table_entry_header *header, const unsigned long end)
    2.95 @@ -258,17 +269,6 @@ acpi_patch_plat_int_src (
    2.96  	return 0;
    2.97  }
    2.98  
    2.99 -static u8
   2.100 -generate_acpi_checksum(void *tbl, unsigned long len)
   2.101 -{
   2.102 -	u8 *ptr, sum = 0;
   2.103 -
   2.104 -	for (ptr = tbl; len > 0 ; len--, ptr++)
   2.105 -		sum += *ptr;
   2.106 -
   2.107 -	return 0 - sum;
   2.108 -}
   2.109 -
   2.110  static int
   2.111  acpi_update_madt_checksum (unsigned long phys_addr, unsigned long size)
   2.112  {
   2.113 @@ -454,6 +454,7 @@ dom_fw_fake_acpi(struct domain *d, struc
   2.114  		lsapic[i].acpi_id = i;
   2.115  		lsapic[i].id = i;
   2.116  		lsapic[i].eid = 0;
   2.117 +		//XXX replace d->vcpu[i] != NULL with XEN_DOMCTL_getvcpuinfo
   2.118  		if (d->vcpu[i] != NULL) {
   2.119  			lsapic[i].flags.enabled = 1;
   2.120  			nbr_cpus++;
   2.121 @@ -509,6 +510,49 @@ struct fw_tables {
   2.122     FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field)
   2.123  
   2.124  static void
   2.125 +efi_systable_init_dom0(struct fw_tables *tables)
   2.126 +{
   2.127 +	int i = 1;
   2.128 +	/* Write messages to the console.  */
   2.129 +	touch_acpi_table();
   2.130 +
   2.131 +	printk("Domain0 EFI passthrough:");
   2.132 +	if (efi.mps) {
   2.133 +		tables->efi_tables[i].guid = MPS_TABLE_GUID;
   2.134 +		tables->efi_tables[i].table = __pa(efi.mps);
   2.135 +		printk(" MPS=0x%lx",tables->efi_tables[i].table);
   2.136 +		i++;
   2.137 +	}
   2.138 +
   2.139 +	if (efi.acpi20) {
   2.140 +		tables->efi_tables[i].guid = ACPI_20_TABLE_GUID;
   2.141 +		tables->efi_tables[i].table = __pa(efi.acpi20);
   2.142 +		printk(" ACPI 2.0=0x%lx",tables->efi_tables[i].table);
   2.143 +		i++;
   2.144 +	}
   2.145 +	if (efi.acpi) {
   2.146 +		tables->efi_tables[i].guid = ACPI_TABLE_GUID;
   2.147 +		tables->efi_tables[i].table = __pa(efi.acpi);
   2.148 +		printk(" ACPI=0x%lx",tables->efi_tables[i].table);
   2.149 +		i++;
   2.150 +	}
   2.151 +	if (efi.smbios) {
   2.152 +		tables->efi_tables[i].guid = SMBIOS_TABLE_GUID;
   2.153 +		tables->efi_tables[i].table = __pa(efi.smbios);
   2.154 +		printk(" SMBIOS=0x%lx",tables->efi_tables[i].table);
   2.155 +		i++;
   2.156 +	}
   2.157 +	if (efi.hcdp) {
   2.158 +		tables->efi_tables[i].guid = HCDP_TABLE_GUID;
   2.159 +		tables->efi_tables[i].table = __pa(efi.hcdp);
   2.160 +		printk(" HCDP=0x%lx",tables->efi_tables[i].table);
   2.161 +		i++;
   2.162 +	}
   2.163 +	printk("\n");
   2.164 +	BUG_ON(i > NUM_EFI_SYS_TABLES);
   2.165 +}
   2.166 +
   2.167 +static void
   2.168  setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables,
   2.169  		       int *num_mds)
   2.170  {
   2.171 @@ -665,7 +709,6 @@ complete_dom0_memmap(struct domain *d,
   2.172  			num_mds++;
   2.173  
   2.174  			dom_mem -= dom_md->num_pages << EFI_PAGE_SHIFT;
   2.175 -			d->arch.convmem_end = end;
   2.176  			break;
   2.177  
   2.178  		case EFI_UNUSABLE_MEMORY:
   2.179 @@ -733,13 +776,27 @@ complete_dom0_memmap(struct domain *d,
   2.180  	return num_mds;
   2.181  }
   2.182  	
   2.183 +static void
   2.184 +efi_systable_init_domu(struct fw_tables *tables)
   2.185 +{
   2.186 +	int i = 1;
   2.187 +	printk(XENLOG_GUEST XENLOG_INFO "DomainU EFI build up:");
   2.188 +
   2.189 +	tables->efi_tables[i].guid = ACPI_20_TABLE_GUID;
   2.190 +	tables->efi_tables[i].table = FW_ACPI_BASE_PADDR;
   2.191 +	printk(" ACPI 2.0=0x%lx",tables->efi_tables[i].table);
   2.192 +	i++;
   2.193 +	printk("\n");
   2.194 +	BUG_ON(i > NUM_EFI_SYS_TABLES);
   2.195 +}
   2.196 +
   2.197  static int
   2.198  complete_domu_memmap(struct domain *d,
   2.199                       struct fw_tables *tables,
   2.200                       unsigned long maxmem,
   2.201                       int num_mds,
   2.202  		     unsigned long memmap_info_pfn,
   2.203 -		     unsigned long memmap_size)
   2.204 +		     unsigned long reserved_size)
   2.205  {
   2.206  	efi_memory_desc_t *md;
   2.207  	int i = num_mds; /* for MAKE_MD */
   2.208 @@ -751,18 +808,18 @@ complete_domu_memmap(struct domain *d,
   2.209  	void *memmap_start;
   2.210  	void *memmap_end;
   2.211  
   2.212 -	if (memmap_info_pfn == 0 || memmap_size == 0) {
   2.213 +	if (memmap_info_pfn == 0 || reserved_size == 0) {
   2.214  		/* old domain builder which doesn't setup
   2.215  		 * memory map. create it for compatibility */
   2.216  		memmap_info_pfn = (maxmem >> PAGE_SHIFT) - 1;
   2.217  		/* 4 = memmap info page, start info page, xenstore page and
   2.218  		   console page */
   2.219 -		memmap_size = 4 << PAGE_SHIFT;
   2.220 +		reserved_size = 4 << PAGE_SHIFT;
   2.221  		create_memmap = 1;
   2.222  	}
   2.223  	paddr_start = memmap_info_pfn << PAGE_SHIFT;
   2.224 -	paddr_end = paddr_start + memmap_size;
   2.225 -	memmap_info = domain_mpa_to_imva(d, paddr_start);
   2.226 +	paddr_end = paddr_start + reserved_size;
   2.227 +	memmap_info = domain_mpa_to_imva(d, paddr_start);//XXX replace this with xc_map_foreign_map_range()
   2.228  	if (memmap_info->efi_memmap_size == 0) {
   2.229  		create_memmap = 1;
   2.230  	} else if (memmap_info->efi_memdesc_size != sizeof(md[0]) ||
   2.231 @@ -778,21 +835,28 @@ complete_domu_memmap(struct domain *d,
   2.232  		       memmap_info->efi_memdesc_size,
   2.233  		       memmap_info->efi_memdesc_version);
   2.234  		create_memmap = 1;
   2.235 -	} else if (max(memmap_size, memmap_info->efi_memmap_size) >
   2.236 +	} else if (reserved_size < memmap_info->efi_memmap_size) {
   2.237 +		printk(XENLOG_WARNING
   2.238 +		       "%s: Warning: too short reserved size %"PRIu64"\n",
   2.239 +		       __func__, reserved_size);
   2.240 +		return -EINVAL;
   2.241 +	} else if (memmap_info->efi_memmap_size >
   2.242  		   PAGE_SIZE - sizeof(*memmap_info)) {
   2.243  		/*
   2.244  		 * curently memmap spanning more than single page isn't
   2.245  		 * supported.
   2.246  		 */
   2.247  		printk(XENLOG_WARNING
   2.248 -		       "%s: Warning: too large memmap_size %"PRIu64"\n",
   2.249 -		       __func__, memmap_size);
   2.250 +		       "%s: Warning: too large reserved_size %"PRIu64"\n",
   2.251 +		       __func__, memmap_info->efi_memmap_size);
   2.252  		return -ENOSYS;
   2.253  	}
   2.254  	
   2.255  	if (create_memmap) {
   2.256 -		/* old domain builder which doesn't setup
   2.257 -		 * memory map. create it for compatibility */
   2.258 +		/*
   2.259 +		 * old domain builder which doesn't setup
   2.260 +		 * memory map. create it for compatibility
   2.261 +		 */
   2.262  		memmap_info->efi_memdesc_size = sizeof(md[0]);
   2.263  		memmap_info->efi_memdesc_version =
   2.264  			EFI_MEMORY_DESCRIPTOR_VERSION;
   2.265 @@ -805,14 +869,6 @@ complete_domu_memmap(struct domain *d,
   2.266  		md[num_mds].num_pages = maxmem >> EFI_PAGE_SHIFT;
   2.267  		md[num_mds].attribute = EFI_MEMORY_WB;
   2.268  	}
   2.269 -	/*
   2.270 -	 * XXX kludge.
   2.271 -	 * when XEN_DOMCTL_arch_setup is called, shared_info can't
   2.272 -	 * be accessed by libxc so that memmap_info_pfn isn't initialized.
   2.273 -	 * But dom_fw_set_convmem_end() requires it, so here we initialize it.
   2.274 -	 */
   2.275 -	d->shared_info->arch.memmap_info_num_pages = 1;
   2.276 -	d->shared_info->arch.memmap_info_pfn = memmap_info_pfn;
   2.277  
   2.278  	memmap_start = &memmap_info->memdesc;
   2.279  	memmap_end = memmap_start + memmap_info->efi_memmap_size;
   2.280 @@ -856,14 +912,11 @@ complete_domu_memmap(struct domain *d,
   2.281  			MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
   2.282  				paddr_end, end);
   2.283  		}
   2.284 -		d->arch.convmem_end = end;
   2.285  	}
   2.286  
   2.287  	/* memmap info page. */
   2.288  	MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB,
   2.289  		paddr_start, paddr_end);
   2.290 -	if (d->arch.convmem_end < paddr_end)
   2.291 -		d->arch.convmem_end = paddr_end;
   2.292  
   2.293  	/* Create an entry for IO ports.  */
   2.294  	MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
   2.295 @@ -875,8 +928,9 @@ complete_domu_memmap(struct domain *d,
   2.296  	return num_mds;
   2.297  }
   2.298  
   2.299 -static void
   2.300 +static int
   2.301  dom_fw_init(struct domain *d,
   2.302 +	    u64 brkimm,
   2.303              struct ia64_boot_param *bp,
   2.304              struct fw_tables *tables,
   2.305              unsigned long hypercalls_imva,
   2.306 @@ -890,11 +944,6 @@ dom_fw_init(struct domain *d,
   2.307  
   2.308  	memset(tables, 0, sizeof(struct fw_tables));
   2.309  
   2.310 -	/* Initialise for EFI_SET_VIRTUAL_ADDRESS_MAP emulation */
   2.311 -	d->arch.efi_runtime = &tables->efi_runtime;
   2.312 -	d->arch.fpswa_inf   = &tables->fpswa_inf;
   2.313 -	d->arch.sal_data    = &tables->sal_data;
   2.314 -
   2.315  	/* EFI systab.  */
   2.316  	tables->efi_systab.hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
   2.317  	tables->efi_systab.hdr.revision  = EFI_SYSTEM_TABLE_REVISION;
   2.318 @@ -933,52 +982,10 @@ dom_fw_init(struct domain *d,
   2.319  		tables->efi_tables[i].guid = NULL_GUID;
   2.320  		tables->efi_tables[i].table = 0;
   2.321  	}
   2.322 -	i = 1;
   2.323  	if (d == dom0) {
   2.324 -		/* Write messages to the console.  */
   2.325 -		touch_acpi_table();
   2.326 -
   2.327 -		printk("Domain0 EFI passthrough:");
   2.328 -		if (efi.mps) {
   2.329 -			tables->efi_tables[i].guid = MPS_TABLE_GUID;
   2.330 -			tables->efi_tables[i].table = __pa(efi.mps);
   2.331 -			printk(" MPS=0x%lx",tables->efi_tables[i].table);
   2.332 -			i++;
   2.333 -		}
   2.334 -
   2.335 -		if (efi.acpi20) {
   2.336 -			tables->efi_tables[i].guid = ACPI_20_TABLE_GUID;
   2.337 -			tables->efi_tables[i].table = __pa(efi.acpi20);
   2.338 -			printk(" ACPI 2.0=0x%lx",tables->efi_tables[i].table);
   2.339 -			i++;
   2.340 -		}
   2.341 -		if (efi.acpi) {
   2.342 -			tables->efi_tables[i].guid = ACPI_TABLE_GUID;
   2.343 -			tables->efi_tables[i].table = __pa(efi.acpi);
   2.344 -			printk(" ACPI=0x%lx",tables->efi_tables[i].table);
   2.345 -			i++;
   2.346 -		}
   2.347 -		if (efi.smbios) {
   2.348 -			tables->efi_tables[i].guid = SMBIOS_TABLE_GUID;
   2.349 -			tables->efi_tables[i].table = __pa(efi.smbios);
   2.350 -			printk(" SMBIOS=0x%lx",tables->efi_tables[i].table);
   2.351 -			i++;
   2.352 -		}
   2.353 -		if (efi.hcdp) {
   2.354 -			tables->efi_tables[i].guid = HCDP_TABLE_GUID;
   2.355 -			tables->efi_tables[i].table = __pa(efi.hcdp);
   2.356 -			printk(" HCDP=0x%lx",tables->efi_tables[i].table);
   2.357 -			i++;
   2.358 -		}
   2.359 -		printk("\n");
   2.360 +		efi_systable_init_dom0(tables);
   2.361  	} else {
   2.362 -		printk(XENLOG_GUEST XENLOG_INFO "DomainU EFI build up:");
   2.363 -
   2.364 -		tables->efi_tables[i].guid = ACPI_20_TABLE_GUID;
   2.365 -		tables->efi_tables[i].table = FW_ACPI_BASE_PADDR;
   2.366 -		printk(" ACPI 2.0=0x%lx", tables->efi_tables[i].table);
   2.367 -		i++;
   2.368 -		printk("\n");
   2.369 +		efi_systable_init_domu(tables);
   2.370  	}
   2.371  
   2.372  	/* fill in the SAL system table: */
   2.373 @@ -994,11 +1001,11 @@ dom_fw_init(struct domain *d,
   2.374  	/* PAL entry point: */
   2.375  	tables->sal_ed.type = SAL_DESC_ENTRY_POINT;
   2.376  	tables->sal_ed.pal_proc = FW_HYPERCALL_PAL_CALL_PADDR;
   2.377 -	dom_fw_pal_hypercall_patch(d, tables->sal_ed.pal_proc, 
   2.378 -	                           hypercalls_imva);
   2.379 +	dom_fw_pal_hypercall_patch(brkimm, tables->sal_ed.pal_proc,
   2.380 +				   hypercalls_imva);
   2.381  	/* SAL entry point.  */
   2.382  	tables->sal_ed.sal_proc = FW_HYPERCALL_SAL_CALL_PADDR;
   2.383 -	dom_fw_hypercall_patch(d, tables->sal_ed.sal_proc,
   2.384 +	dom_fw_hypercall_patch(brkimm, tables->sal_ed.sal_proc,
   2.385  	                       FW_HYPERCALL_SAL_CALL, 1, hypercalls_imva);
   2.386  	tables->sal_ed.gp = 0;  /* will be ignored */
   2.387  
   2.388 @@ -1016,13 +1023,13 @@ dom_fw_init(struct domain *d,
   2.389  	tables->sal_systab.checksum = -checksum;
   2.390  
   2.391  	/* SAL return point.  */
   2.392 -	dom_fw_hypercall_patch(d, FW_HYPERCALL_SAL_RETURN_PADDR,
   2.393 +	dom_fw_hypercall_patch(brkimm, FW_HYPERCALL_SAL_RETURN_PADDR,
   2.394  	                       FW_HYPERCALL_SAL_RETURN, 0, hypercalls_imva);
   2.395  
   2.396  	/* Fill in the FPSWA interface: */
   2.397  	if (fpswa_interface) {
   2.398  		tables->fpswa_inf.revision = fpswa_interface->revision;
   2.399 -		dom_fpswa_hypercall_patch(d, hypercalls_imva);
   2.400 +		dom_fpswa_hypercall_patch(brkimm, hypercalls_imva);
   2.401  		tables->fpswa_inf.fpswa = 
   2.402  		                       (void *)FW_HYPERCALL_FPSWA_ENTRY_PADDR;
   2.403  	}
   2.404 @@ -1058,6 +1065,8 @@ dom_fw_init(struct domain *d,
   2.405  		   as well as IO areas.  */
   2.406  		num_mds = complete_dom0_memmap(d, tables, maxmem, i);
   2.407  	}
   2.408 +	if (num_mds < 0)
   2.409 +		return num_mds;
   2.410  
   2.411  	/* Display memmap.  */
   2.412  	for (i = 0 ; i < num_mds; i++)
   2.413 @@ -1076,10 +1085,74 @@ dom_fw_init(struct domain *d,
   2.414  	bp->console_info.orig_y = 24;
   2.415  	if (fpswa_interface)
   2.416  		bp->fpswa = FW_FIELD_MPA(fpswa_inf);
   2.417 +	return 0;
   2.418 +}
   2.419 +
   2.420 +static void
   2.421 +dom_fw_domain_init(struct domain *d, struct fw_tables *tables)
   2.422 +{
   2.423 +	/* Initialise for EFI_SET_VIRTUAL_ADDRESS_MAP emulation */
   2.424 +	d->arch.efi_runtime = &tables->efi_runtime;
   2.425 +	d->arch.fpswa_inf   = &tables->fpswa_inf;
   2.426 +	d->arch.sal_data    = &tables->sal_data;
   2.427  }
   2.428  
   2.429 -void dom_fw_setup(struct domain *d, unsigned long bp_mpa, unsigned long maxmem)
   2.430 +static int
   2.431 +dom_fw_set_convmem_end(struct domain *d)
   2.432  {
   2.433 +	xen_ia64_memmap_info_t* memmap_info;
   2.434 +	efi_memory_desc_t *md;
   2.435 +	void *p;
   2.436 +	void *memmap_start;
   2.437 +	void *memmap_end;
   2.438 +
   2.439 +	if (d->shared_info->arch.memmap_info_pfn == 0)
   2.440 +		return -EINVAL;
   2.441 +
   2.442 +	memmap_info = domain_mpa_to_imva(d, d->shared_info->arch.memmap_info_pfn << PAGE_SHIFT);
   2.443 +	if (memmap_info->efi_memmap_size == 0 ||
   2.444 +	    memmap_info->efi_memdesc_size != sizeof(*md) ||
   2.445 +	    memmap_info->efi_memdesc_version !=
   2.446 +	    EFI_MEMORY_DESCRIPTOR_VERSION)
   2.447 +		return -EINVAL;
   2.448 +	/* only 1page case is supported */
   2.449 +	if (d->shared_info->arch.memmap_info_num_pages != 1)
   2.450 +		return -ENOSYS;
   2.451 +
   2.452 +	memmap_start = &memmap_info->memdesc;
   2.453 +	memmap_end = memmap_start + memmap_info->efi_memmap_size;
   2.454 +
   2.455 +	/* XXX Currently the table must be in a single page. */
   2.456 +	if ((unsigned long)memmap_end > (unsigned long)memmap_info + PAGE_SIZE)
   2.457 +		return -EINVAL;
   2.458 +
   2.459 +	/* sort it bofore use
   2.460 +	 * XXX: this is created by user space domain builder so that
   2.461 +	 * we should check its integrity */
   2.462 +	sort(&memmap_info->memdesc,
   2.463 +	     memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size,
   2.464 +	     memmap_info->efi_memdesc_size,
   2.465 +	     efi_mdt_cmp, NULL);
   2.466 +
   2.467 +	if (d->arch.convmem_end == 0)
   2.468 +		d->arch.convmem_end = d->max_pages << PAGE_SHIFT;
   2.469 +	for (p = memmap_start; p < memmap_end; p += memmap_info->efi_memdesc_size) {
   2.470 +		unsigned long end;
   2.471 +		md = p;
   2.472 +		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
   2.473 +		if (md->attribute == EFI_MEMORY_WB &&
   2.474 +		    md->type == EFI_CONVENTIONAL_MEMORY &&
   2.475 +		    md->num_pages > 0 &&
   2.476 +		    d->arch.convmem_end < end)
   2.477 +			d->arch.convmem_end = end;
   2.478 +	}
   2.479 +	return 0;
   2.480 +}
   2.481 +
   2.482 +int
   2.483 +dom_fw_setup(struct domain *d, unsigned long bp_mpa, unsigned long maxmem)
   2.484 +{
   2.485 +	int ret = 0;
   2.486  	struct ia64_boot_param *bp;
   2.487  	unsigned long imva_tables_base;
   2.488  	unsigned long imva_hypercall_base;
   2.489 @@ -1112,7 +1185,49 @@ void dom_fw_setup(struct domain *d, unsi
   2.490  	/* Create page for boot_param.  */
   2.491  	assign_new_domain_page_if_dom0(d, bp_mpa);
   2.492  	bp = domain_mpa_to_imva(d, bp_mpa);
   2.493 +	if (d != dom0) {
   2.494 +		/*
   2.495 +		 * XXX kludge.
   2.496 +		 * when XEN_DOMCTL_arch_setup is called, shared_info can't
   2.497 +		 * be accessed by libxc so that memmap_info_pfn isn't
   2.498 +		 * initialized. But dom_fw_set_convmem_end() requires it, 
   2.499 +		 * so here we initialize it.
   2.500 +		 * note:dom_fw_init() overwrites memmap_info_num_pages,
   2.501 +		 *      memmap_info_pfns.
   2.502 +		 */
   2.503 +		if ((bp->efi_memmap_size & ~PAGE_MASK) != 0) {
   2.504 +			printk("%s:%d size 0x%lx 0x%lx 0x%lx\n",
   2.505 +			       __func__, __LINE__,
   2.506 +			       bp->efi_memmap_size,
   2.507 +			       bp->efi_memmap_size & ~PAGE_SIZE,
   2.508 +			       ~PAGE_SIZE);
   2.509 +			return -EINVAL;
   2.510 +		}
   2.511 +		if (bp->efi_memmap_size == 0) {
   2.512 +			/* old domain builder compatibility */
   2.513 +			d->shared_info->arch.memmap_info_num_pages = 1;
   2.514 +			d->shared_info->arch.memmap_info_pfn =
   2.515 +				(maxmem >> PAGE_SHIFT) - 1;
   2.516 +		} else {
   2.517 +			/*
   2.518 +			 * 3: start info page, xenstore page and console page
   2.519 +			 */
   2.520 +			if (bp->efi_memmap_size < 4 * PAGE_SIZE)
   2.521 +				return -EINVAL;
   2.522 +			d->shared_info->arch.memmap_info_num_pages =
   2.523 +				(bp->efi_memmap_size >> PAGE_SHIFT) - 3;
   2.524 +			d->shared_info->arch.memmap_info_pfn = bp->efi_memmap;
   2.525 +			/* currently multi page memmap isn't supported */
   2.526 +			if (d->shared_info->arch.memmap_info_num_pages != 1)
   2.527 +				return -ENOSYS;
   2.528 +		}
   2.529 +	}
   2.530 +	ret = dom_fw_init(d, d->arch.breakimm, bp,
   2.531 +			    (struct fw_tables *)imva_tables_base,
   2.532 +			    imva_hypercall_base, maxmem);
   2.533 +	if (ret < 0)
   2.534 +		return ret;
   2.535  
   2.536 -	dom_fw_init(d, bp, (struct fw_tables *)imva_tables_base,
   2.537 -	            imva_hypercall_base, maxmem);
   2.538 +	dom_fw_domain_init(d, (struct fw_tables *)imva_tables_base);
   2.539 +	return dom_fw_set_convmem_end(d);
   2.540  }
     3.1 --- a/xen/arch/ia64/xen/domain.c	Mon May 21 10:10:31 2007 -0600
     3.2 +++ b/xen/arch/ia64/xen/domain.c	Mon May 21 13:14:56 2007 -0600
     3.3 @@ -1353,7 +1353,9 @@ int construct_dom0(struct domain *d,
     3.4  	   Note: Linux kernel reserve memory used by start_info, so there is
     3.5  	   no need to remove it from MDT.  */
     3.6  	bp_mpa = pstart_info + sizeof(struct start_info);
     3.7 -	dom_fw_setup(d, bp_mpa, max_pages * PAGE_SIZE);
     3.8 +	rc = dom_fw_setup(d, bp_mpa, max_pages * PAGE_SIZE);
     3.9 +	if (rc != 0)
    3.10 +		return rc;
    3.11  
    3.12  	/* Fill boot param.  */
    3.13  	strlcpy((char *)si->cmd_line, dom0_command_line, sizeof(si->cmd_line));
     4.1 --- a/xen/include/asm-ia64/dom_fw.h	Mon May 21 10:10:31 2007 -0600
     4.2 +++ b/xen/include/asm-ia64/dom_fw.h	Mon May 21 13:14:56 2007 -0600
     4.3 @@ -188,4 +188,4 @@ extern struct sal_ret_values sal_emulato
     4.4  extern struct ia64_pal_retval pal_emulator_static (unsigned long);
     4.5  extern efi_status_t efi_emulator (struct pt_regs *regs, unsigned long *fault);
     4.6  
     4.7 -extern void dom_fw_setup (struct domain *, unsigned long bp_mpa, unsigned long maxmem);
     4.8 +extern int dom_fw_setup (struct domain *, unsigned long bp_mpa, unsigned long maxmem);