diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index e61d2d53ba..ec29bd302c 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -494,8 +494,17 @@ static bool __init append_static_memory_to_bank(struct domain *d, { int res; unsigned int nr_pages = PFN_DOWN(size); - /* Infer next GFN. */ - gfn_t sgfn = gaddr_to_gfn(bank->start + bank->size); + gfn_t sgfn; + + /* + * For direct-mapped domain, the GFN match the MFN. + * Otherwise, this is inferred on what has already been allocated + * in the bank. + */ + if ( !is_domain_direct_mapped(d) ) + sgfn = gaddr_to_gfn(bank->start + bank->size); + else + sgfn = gaddr_to_gfn(mfn_to_maddr(smfn)); res = guest_physmap_add_pages(d, sgfn, smfn, nr_pages); if ( res ) @@ -668,12 +677,92 @@ static void __init allocate_static_memory(struct domain *d, fail: panic("Failed to allocate requested static memory for domain %pd.", d); } + +/* + * Allocate static memory as RAM for one specific domain d. + * The static memory will be directly mapped in the guest(Guest Physical + * Address == Physical Address). + */ +static void __init assign_static_memory_11(struct domain *d, + struct kernel_info *kinfo, + const struct dt_device_node *node) +{ + u32 addr_cells, size_cells, reg_cells; + unsigned int nr_banks, bank = 0; + const __be32 *cell; + paddr_t pbase, psize; + mfn_t smfn; + int length; + + if ( parse_static_mem_prop(node, &addr_cells, &size_cells, &length, &cell) ) + { + printk(XENLOG_ERR + "%pd: failed to parse \"xen,static-mem\" property.\n", d); + goto fail; + } + reg_cells = addr_cells + size_cells; + nr_banks = length / (reg_cells * sizeof(u32)); + + if ( nr_banks > NR_MEM_BANKS ) + { + printk(XENLOG_ERR + "%pd: exceed max number of supported guest memory banks.\n", d); + goto fail; + } + + for ( ; bank < nr_banks; bank++ ) + { + smfn = acquire_static_memory_bank(d, &cell, addr_cells, size_cells, + &pbase, &psize); + if ( mfn_eq(smfn, INVALID_MFN) ) + goto fail; + + printk(XENLOG_INFO "%pd: STATIC BANK[%u] %#"PRIpaddr"-%#"PRIpaddr"\n", + d, bank, pbase, pbase + psize); + + /* One guest memory bank is matched with one physical memory bank. */ + kinfo->mem.bank[bank].start = pbase; + if ( !append_static_memory_to_bank(d, &kinfo->mem.bank[bank], + smfn, psize) ) + goto fail; + + kinfo->unassigned_mem -= psize; + } + + kinfo->mem.nr_banks = nr_banks; + + /* + * The property 'memory' should match the amount of memory given to + * the guest. + * Currently, it is only possible to either acquire static memory or + * let Xen allocate. *Mixing* is not supported. + */ + if ( kinfo->unassigned_mem != 0 ) + { + printk(XENLOG_ERR + "Size of \"memory\" property doesn't match up with the sum-up of \"xen,static-mem\".\n"); + goto fail; + } + + return; + + fail: + panic("Failed to assign requested static memory for direct-map domain %pd.", + d); +} #else static void __init allocate_static_memory(struct domain *d, struct kernel_info *kinfo, const struct dt_device_node *node) { } + +static void __init assign_static_memory_11(struct domain *d, + struct kernel_info *kinfo, + const struct dt_device_node *node) +{ + ASSERT_UNREACHABLE(); +} #endif /* @@ -3023,8 +3112,10 @@ static int __init construct_domU(struct domain *d, #endif if ( !dt_find_property(node, "xen,static-mem", NULL) ) allocate_memory(d, &kinfo); - else + else if ( !is_domain_direct_mapped(d) ) allocate_static_memory(d, &kinfo, node); + else + assign_static_memory_11(d, &kinfo, node); rc = prepare_dtb_domU(d, &kinfo); if ( rc < 0 )