# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1179763831 21600
# Node ID c2768258711da6dadd021a5aad883fff949e255d
# Parent caafa45d24b3cbf05ab97ab33235e5b91ac44323
[IA64] memmap: introduce memmap_info_t
Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
tools/libxc/xc_dom_ia64.c | 64 +++++++++++
xen/arch/ia64/xen/dom_fw.c | 223 ++++++++++++++++++++++++++++++++++++++---
xen/include/public/arch-ia64.h | 7 +
3 files changed, 279 insertions(+), 15 deletions(-)
diff -r caafa45d24b3 -r c2768258711d tools/libxc/xc_dom_ia64.c
--- a/tools/libxc/xc_dom_ia64.c Mon May 21 10:09:33 2007 -0600
+++ b/tools/libxc/xc_dom_ia64.c Mon May 21 10:10:31 2007 -0600
@@ -77,6 +77,8 @@ static int shared_info_ia64(struct xc_do
for (i = 0; i < MAX_VIRT_CPUS; i++)
shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
shared_info->arch.start_info_pfn = dom->start_info_pfn;
+ shared_info->arch.memmap_info_num_pages = 1;
+ shared_info->arch.memmap_info_pfn = dom->start_info_pfn - 1;
return 0;
}
@@ -129,6 +131,8 @@ static void __init register_arch_hooks(v
xc_dom_register_arch_hooks(&xc_dom_arch_ia64be);
}
+#include "xc_efi.h"
+
int arch_setup_meminit(struct xc_dom_image *dom)
{
xen_pfn_t pfn;
@@ -146,12 +150,69 @@ int arch_setup_meminit(struct xc_dom_ima
return rc;
}
+static int ia64_setup_memmap(struct xc_dom_image *dom)
+{
+ unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+ unsigned long memmap_info_pfn;
+ xen_ia64_memmap_info_t* memmap_info;
+ unsigned int num_mds;
+ efi_memory_desc_t *md;
+
+ char* start_info;
+ struct xen_ia64_boot_param* bp;
+
+ /* setup memmap page */
+ memmap_info_pfn = dom->start_info_pfn - 1;
+ xc_dom_printf("%s: memmap: mfn 0x%" PRIpfn "\n",
+ __FUNCTION__, memmap_info_pfn);
+ memmap_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
+ page_size,
+ PROT_READ | PROT_WRITE,
+ memmap_info_pfn);
+ if (NULL == memmap_info)
+ return -1;
+ /* [0, total_pages) */
+ memmap_info->efi_memdesc_size = sizeof(md[0]);
+ memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
+ num_mds = 0;
+ md = (efi_memory_desc_t*)&memmap_info->memdesc;
+ md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
+ md[num_mds].pad = 0;
+ md[num_mds].phys_addr = 0;
+ md[num_mds].virt_addr = 0;
+ md[num_mds].num_pages = dom->total_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT);
+ md[num_mds].attribute = EFI_MEMORY_WB;
+ num_mds++;
+ memmap_info->efi_memmap_size = num_mds * sizeof(md[0]);
+ munmap(memmap_info, page_size);
+
+ /* kludge: we need to pass memmap_info page's pfn somehow.
+ * we use xen_ia64_boot_param::efi_memmap for this purpose */
+ start_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
+ page_size,
+ PROT_READ | PROT_WRITE,
+ dom->start_info_pfn);
+ if (NULL == start_info)
+ return -1;
+ bp = (struct xen_ia64_boot_param*)(start_info + sizeof(start_info_t));
+ memset(bp, 0, sizeof(*bp));
+ bp->efi_memmap = memmap_info_pfn;
+ /* 4 = memmap info page, start info page, xenstore page and console page */
+ bp->efi_memmap_size = 4 * PAGE_SIZE;
+ munmap(start_info, page_size);
+ return 0;
+}
+
int arch_setup_bootearly(struct xc_dom_image *dom)
{
DECLARE_DOMCTL;
int rc;
xc_dom_printf("%s: setup firmware\n", __FUNCTION__);
+
+ rc = ia64_setup_memmap(dom);
+ if (rc)
+ return rc;
memset(&domctl, 0, sizeof(domctl));
domctl.cmd = XEN_DOMCTL_arch_setup;
@@ -160,8 +221,7 @@ int arch_setup_bootearly(struct xc_dom_i
domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT)
+ sizeof(start_info_t);
- /* 3 = start info page, xenstore page and console page */
- domctl.u.arch_setup.maxmem = (dom->total_pages - 3) << PAGE_SHIFT;
+ domctl.u.arch_setup.maxmem = dom->total_pages << PAGE_SHIFT;
rc = do_domctl(dom->guest_xc, &domctl);
return rc;
}
diff -r caafa45d24b3 -r c2768258711d xen/arch/ia64/xen/dom_fw.c
--- a/xen/arch/ia64/xen/dom_fw.c Mon May 21 10:09:33 2007 -0600
+++ b/xen/arch/ia64/xen/dom_fw.c Mon May 21 10:10:31 2007 -0600
@@ -508,6 +508,63 @@ struct fw_tables {
#define FW_FIELD_MPA(field) \
FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field)
+static void
+setup_dom0_memmap_info(struct domain *d, struct fw_tables *tables,
+ int *num_mds)
+{
+ int i;
+ efi_memory_desc_t *md;
+ efi_memory_desc_t *last_mem_md = NULL;
+ xen_ia64_memmap_info_t* memmap_info;
+ unsigned long paddr_start;
+ unsigned long paddr_end;
+
+ for (i = *num_mds - 1; i >= 0; i--) {
+ md = &tables->efi_memmap[i];
+ if (md->attribute == EFI_MEMORY_WB &&
+ md->type == EFI_CONVENTIONAL_MEMORY &&
+ md->num_pages >
+ 2 * (1UL << (PAGE_SHIFT - EFI_PAGE_SHIFT))) {
+ last_mem_md = md;
+ break;
+ }
+ }
+
+ if (last_mem_md == NULL) {
+ printk("%s: warning: "
+ "no dom0 contiguous memory to hold memory map\n",
+ __func__);
+ return;
+ }
+ paddr_end = last_mem_md->phys_addr +
+ (last_mem_md->num_pages << EFI_PAGE_SHIFT);
+ paddr_start = (paddr_end - PAGE_SIZE) & PAGE_MASK;
+ last_mem_md->num_pages -=
+ (paddr_end - paddr_start) / (1UL << EFI_PAGE_SHIFT);
+
+ md = &tables->efi_memmap[*num_mds];
+ (*num_mds)++;
+ md->type = EFI_RUNTIME_SERVICES_DATA;
+ md->phys_addr = paddr_start;
+ md->virt_addr = 0;
+ md->num_pages = 1UL << (PAGE_SHIFT - EFI_PAGE_SHIFT);
+ md->attribute = EFI_MEMORY_WB;
+
+ memmap_info = domain_mpa_to_imva(d, md->phys_addr);
+ BUG_ON(*num_mds > NUM_MEM_DESCS);
+
+ memmap_info->efi_memdesc_size = sizeof(md[0]);
+ memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
+ memmap_info->efi_memmap_size = *num_mds * sizeof(md[0]);
+ memcpy(&memmap_info->memdesc, &tables->efi_memmap[0],
+ memmap_info->efi_memmap_size);
+ d->shared_info->arch.memmap_info_num_pages = 1;
+ d->shared_info->arch.memmap_info_pfn = md->phys_addr >> PAGE_SHIFT;
+
+ sort(tables->efi_memmap, *num_mds, sizeof(efi_memory_desc_t),
+ efi_mdt_cmp, NULL);
+}
+
/* Complete the dom0 memmap. */
static int
complete_dom0_memmap(struct domain *d,
@@ -672,9 +729,152 @@ complete_dom0_memmap(struct domain *d,
PAGE_SIZE, flags);
}
}
+ setup_dom0_memmap_info(d, tables, &num_mds);
return num_mds;
}
+static int
+complete_domu_memmap(struct domain *d,
+ struct fw_tables *tables,
+ unsigned long maxmem,
+ int num_mds,
+ unsigned long memmap_info_pfn,
+ unsigned long memmap_size)
+{
+ efi_memory_desc_t *md;
+ int i = num_mds; /* for MAKE_MD */
+ int create_memmap = 0;
+ xen_ia64_memmap_info_t* memmap_info;
+ unsigned long paddr_start;
+ unsigned long paddr_end;
+ void *p;
+ void *memmap_start;
+ void *memmap_end;
+
+ if (memmap_info_pfn == 0 || memmap_size == 0) {
+ /* old domain builder which doesn't setup
+ * memory map. create it for compatibility */
+ memmap_info_pfn = (maxmem >> PAGE_SHIFT) - 1;
+ /* 4 = memmap info page, start info page, xenstore page and
+ console page */
+ memmap_size = 4 << PAGE_SHIFT;
+ create_memmap = 1;
+ }
+ paddr_start = memmap_info_pfn << PAGE_SHIFT;
+ paddr_end = paddr_start + memmap_size;
+ memmap_info = domain_mpa_to_imva(d, paddr_start);
+ if (memmap_info->efi_memmap_size == 0) {
+ create_memmap = 1;
+ } else if (memmap_info->efi_memdesc_size != sizeof(md[0]) ||
+ memmap_info->efi_memdesc_version !=
+ EFI_MEMORY_DESCRIPTOR_VERSION) {
+ printk(XENLOG_WARNING
+ "%s: Warning: unknown memory map "
+ "memmap size %"PRIu64" "
+ "memdesc size %"PRIu64" "
+ "version %"PRIu32"\n",
+ __func__,
+ memmap_info->efi_memmap_size,
+ memmap_info->efi_memdesc_size,
+ memmap_info->efi_memdesc_version);
+ create_memmap = 1;
+ } else if (max(memmap_size, memmap_info->efi_memmap_size) >
+ PAGE_SIZE - sizeof(*memmap_info)) {
+ /*
+ * curently memmap spanning more than single page isn't
+ * supported.
+ */
+ printk(XENLOG_WARNING
+ "%s: Warning: too large memmap_size %"PRIu64"\n",
+ __func__, memmap_size);
+ return -ENOSYS;
+ }
+
+ if (create_memmap) {
+ /* old domain builder which doesn't setup
+ * memory map. create it for compatibility */
+ memmap_info->efi_memdesc_size = sizeof(md[0]);
+ memmap_info->efi_memdesc_version =
+ EFI_MEMORY_DESCRIPTOR_VERSION;
+ memmap_info->efi_memmap_size = 1 * sizeof(md[0]);
+ md = (efi_memory_desc_t*)&memmap_info->memdesc;
+ md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
+ md[num_mds].pad = 0;
+ md[num_mds].phys_addr = 0;
+ md[num_mds].virt_addr = 0;
+ md[num_mds].num_pages = maxmem >> EFI_PAGE_SHIFT;
+ md[num_mds].attribute = EFI_MEMORY_WB;
+ }
+ /*
+ * XXX kludge.
+ * when XEN_DOMCTL_arch_setup is called, shared_info can't
+ * be accessed by libxc so that memmap_info_pfn isn't initialized.
+ * But dom_fw_set_convmem_end() requires it, so here we initialize it.
+ */
+ d->shared_info->arch.memmap_info_num_pages = 1;
+ d->shared_info->arch.memmap_info_pfn = memmap_info_pfn;
+
+ memmap_start = &memmap_info->memdesc;
+ memmap_end = memmap_start + memmap_info->efi_memmap_size;
+ /* XXX Currently the table must be in a single page. */
+ if ((unsigned long)memmap_end > (unsigned long)memmap_info + PAGE_SIZE)
+ return -EINVAL;
+
+ /* sort it bofore use
+ * XXX: this is created by user space domain builder so that
+ * we should check its integrity */
+ sort(&memmap_info->memdesc,
+ memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size,
+ memmap_info->efi_memdesc_size,
+ efi_mdt_cmp, NULL);
+
+ for (p = memmap_start; p < memmap_end; p +=
memmap_info->efi_memdesc_size) {
+ unsigned long start;
+ unsigned long end;
+ md = p;
+ start = md->phys_addr;
+ end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+
+ if (start < FW_END_PADDR)
+ start = FW_END_PADDR;
+ if (end <= start)
+ continue;
+
+ /* exclude [paddr_start, paddr_end) */
+ if (paddr_end <= start || end <= paddr_start) {
+ MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+ start, end);
+ } else if (paddr_start <= start && paddr_end < end) {
+ MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+ paddr_end, end);
+ } else if (start < paddr_start && end <= paddr_end) {
+ MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+ start, paddr_start);
+ } else {
+ MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+ start, paddr_start);
+ MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+ paddr_end, end);
+ }
+ d->arch.convmem_end = end;
+ }
+
+ /* memmap info page. */
+ MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB,
+ paddr_start, paddr_end);
+ if (d->arch.convmem_end < paddr_end)
+ d->arch.convmem_end = paddr_end;
+
+ /* Create an entry for IO ports. */
+ MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
+ IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE);
+
+ num_mds = i;
+ sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t),
+ efi_mdt_cmp, NULL);
+ return num_mds;
+}
+
static void
dom_fw_init(struct domain *d,
struct ia64_boot_param *bp,
@@ -842,18 +1042,17 @@ dom_fw_init(struct domain *d,
if (d != dom0 || running_on_sim) {
/* DomU (or hp-ski).
Create a continuous memory area. */
- /* Memory. */
- MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
- FW_END_PADDR, maxmem);
- d->arch.convmem_end = maxmem;
-
- /* Create an entry for IO ports. */
- MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
- IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE);
-
- num_mds = i;
- }
- else {
+ /* kludge: bp->efi_memmap is used to pass memmap_info
+ * page's pfn and number of pages to reserve.
+ * Currently the following pages must be reserved.
+ * memmap info page, start info page, xenstore page
+ * and console page.
+ * see ia64_setup_memmap() @ xc_dom_boot.c
+ */
+ num_mds = complete_domu_memmap(d, tables, maxmem, i,
+ bp->efi_memmap,
+ bp->efi_memmap_size);
+ } else {
/* Dom0.
We must preserve ACPI data from real machine,
as well as IO areas. */
diff -r caafa45d24b3 -r c2768258711d xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h Mon May 21 10:09:33 2007 -0600
+++ b/xen/include/public/arch-ia64.h Mon May 21 10:10:31 2007 -0600
@@ -339,7 +339,12 @@ struct arch_shared_info {
/* Interrupt vector for event channel. */
int evtchn_vector;
- uint64_t pad[32];
+ /* PFN of memmap_info page */
+ unsigned int memmap_info_num_pages;/* currently only = 1 case is
+ supported. */
+ unsigned long memmap_info_pfn;
+
+ uint64_t pad[31];
};
typedef struct arch_shared_info arch_shared_info_t;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|