mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
xen/arm: permit non direct-mapped Dom0 construction
Cache coloring requires Dom0 not to be direct-mapped because of its non
contiguous mapping nature, so allocate_memory() is needed in this case.
8d2c3ab18c ("arm/dom0less: put dom0less feature code in a separate module")
moved allocate_memory() in dom0less_build.c. In order to use it
in Dom0 construction bring it back to domain_build.c and declare it in
domain_build.h.
Adapt the implementation of allocate_memory() so that it uses the host
layout when called on the hwdom, via find_unallocated_memory().
Since gnttab information are needed in the process, move find_gnttab_region()
before allocate_memory() in construct_dom0().
Introduce add_hwdom_free_regions() callback to add hwdom banks in descending
order.
Signed-off-by: Carlo Nonato <carlo.nonato@minervasys.tech>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
This commit is contained in:
1 parent
f4985fce6f
commit
02975cc383
3 files changed
+153
-48
No files matched your search
@@ -49,50 +49,6 @@ bool __init is_dom0less_mode(void)
|
||||
return ( !dom0found && domUfound );
|
||||
}
|
||||
|
||||
static void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
|
||||
{
|
||||
struct membanks *mem = kernel_info_get_mem(kinfo);
|
||||
unsigned int i;
|
||||
paddr_t bank_size;
|
||||
|
||||
printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
|
||||
/* Don't want format this as PRIpaddr (16 digit hex) */
|
||||
(unsigned long)(kinfo->unassigned_mem >> 20), d);
|
||||
|
||||
mem->nr_banks = 0;
|
||||
bank_size = MIN(GUEST_RAM0_SIZE, kinfo->unassigned_mem);
|
||||
if ( !allocate_bank_memory(kinfo, gaddr_to_gfn(GUEST_RAM0_BASE),
|
||||
bank_size) )
|
||||
goto fail;
|
||||
|
||||
bank_size = MIN(GUEST_RAM1_SIZE, kinfo->unassigned_mem);
|
||||
if ( !allocate_bank_memory(kinfo, gaddr_to_gfn(GUEST_RAM1_BASE),
|
||||
bank_size) )
|
||||
goto fail;
|
||||
|
||||
if ( kinfo->unassigned_mem )
|
||||
goto fail;
|
||||
|
||||
for( i = 0; i < mem->nr_banks; i++ )
|
||||
{
|
||||
printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
|
||||
d,
|
||||
i,
|
||||
mem->bank[i].start,
|
||||
mem->bank[i].start + mem->bank[i].size,
|
||||
/* Don't want format this as PRIpaddr (16 digit hex) */
|
||||
(unsigned long)(mem->bank[i].size >> 20));
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
panic("Failed to allocate requested domain memory."
|
||||
/* Don't want format this as PRIpaddr (16 digit hex) */
|
||||
" %ldKB unallocated. Fix the VMs configurations.\n",
|
||||
(unsigned long)kinfo->unassigned_mem >> 10);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VGICV2
|
||||
static int __init make_gicv2_domU_node(struct kernel_info *kinfo)
|
||||
{
|
||||
|
||||
+152
-4
@@ -2,6 +2,7 @@
|
||||
#include <xen/init.h>
|
||||
#include <xen/compile.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/llc-coloring.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/param.h>
|
||||
#include <xen/domain_page.h>
|
||||
@@ -416,7 +417,6 @@ static void __init allocate_memory_11(struct domain *d,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DOM0LESS_BOOT
|
||||
bool __init allocate_domheap_memory(struct domain *d, paddr_t tot_size,
|
||||
alloc_domheap_mem_cb cb, void *extra)
|
||||
{
|
||||
@@ -508,7 +508,6 @@ bool __init allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When PCI passthrough is available we want to keep the
|
||||
@@ -900,6 +899,52 @@ int __init add_ext_regions(unsigned long s_gfn, unsigned long e_gfn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init add_hwdom_free_regions(unsigned long s_gfn,
|
||||
unsigned long e_gfn, void *data)
|
||||
{
|
||||
struct membanks *free_regions = data;
|
||||
paddr_t start, size;
|
||||
paddr_t s = pfn_to_paddr(s_gfn);
|
||||
paddr_t e = pfn_to_paddr(e_gfn);
|
||||
unsigned int i, j;
|
||||
|
||||
if ( free_regions->nr_banks >= free_regions->max_banks )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Both start and size of the free region should be 2MB aligned to
|
||||
* potentially allow superpage mapping.
|
||||
*/
|
||||
start = (s + SZ_2M - 1) & ~(SZ_2M - 1);
|
||||
if ( start > e )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* e is actually "end-1" because it is called by rangeset functions
|
||||
* which are inclusive of the last address.
|
||||
*/
|
||||
e += 1;
|
||||
size = (e - start) & ~(SZ_2M - 1);
|
||||
|
||||
/* Find the insert position (descending order). */
|
||||
for ( i = 0; i < free_regions->nr_banks ; i++ )
|
||||
if ( size > free_regions->bank[i].size )
|
||||
break;
|
||||
|
||||
/* Move the other banks to make space. */
|
||||
for ( j = free_regions->nr_banks; j > i ; j-- )
|
||||
{
|
||||
free_regions->bank[j].start = free_regions->bank[j - 1].start;
|
||||
free_regions->bank[j].size = free_regions->bank[j - 1].size;
|
||||
}
|
||||
|
||||
free_regions->bank[i].start = start;
|
||||
free_regions->bank[i].size = size;
|
||||
free_regions->nr_banks++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find unused regions of Host address space which can be exposed to domain
|
||||
* using the host memory layout. In order to calculate regions we exclude every
|
||||
@@ -977,6 +1022,106 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
|
||||
{
|
||||
struct membanks *mem = kernel_info_get_mem(kinfo);
|
||||
unsigned int i, nr_banks = GUEST_RAM_BANKS;
|
||||
struct membanks *hwdom_free_mem = NULL;
|
||||
|
||||
printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
|
||||
/* Don't want format this as PRIpaddr (16 digit hex) */
|
||||
(unsigned long)(kinfo->unassigned_mem >> 20), d);
|
||||
|
||||
mem->nr_banks = 0;
|
||||
/*
|
||||
* Use host memory layout for hwdom. Only case for this is when LLC coloring
|
||||
* is enabled.
|
||||
*/
|
||||
if ( is_hardware_domain(d) )
|
||||
{
|
||||
struct membanks *gnttab = xzalloc_flex_struct(struct membanks, bank, 1);
|
||||
/*
|
||||
* Exclude the following regions:
|
||||
* 1) Remove reserved memory
|
||||
* 2) Grant table assigned to hwdom
|
||||
*/
|
||||
const struct membanks *mem_banks[] = {
|
||||
bootinfo_get_reserved_mem(),
|
||||
gnttab,
|
||||
};
|
||||
|
||||
if ( !gnttab )
|
||||
goto fail;
|
||||
|
||||
gnttab->nr_banks = 1;
|
||||
gnttab->bank[0].start = kinfo->gnttab_start;
|
||||
gnttab->bank[0].size = kinfo->gnttab_size;
|
||||
|
||||
hwdom_free_mem = xzalloc_flex_struct(struct membanks, bank,
|
||||
NR_MEM_BANKS);
|
||||
if ( !hwdom_free_mem )
|
||||
goto fail;
|
||||
|
||||
hwdom_free_mem->max_banks = NR_MEM_BANKS;
|
||||
|
||||
if ( find_unallocated_memory(kinfo, mem_banks, ARRAY_SIZE(mem_banks),
|
||||
hwdom_free_mem, add_hwdom_free_regions) )
|
||||
goto fail;
|
||||
|
||||
nr_banks = hwdom_free_mem->nr_banks;
|
||||
xfree(gnttab);
|
||||
}
|
||||
|
||||
for ( i = 0; kinfo->unassigned_mem > 0 && nr_banks > 0; i++, nr_banks-- )
|
||||
{
|
||||
paddr_t bank_start, bank_size;
|
||||
|
||||
if ( is_hardware_domain(d) )
|
||||
{
|
||||
bank_start = hwdom_free_mem->bank[i].start;
|
||||
bank_size = hwdom_free_mem->bank[i].size;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
|
||||
const uint64_t banksize[] = GUEST_RAM_BANK_SIZES;
|
||||
|
||||
if ( i >= GUEST_RAM_BANKS )
|
||||
goto fail;
|
||||
|
||||
bank_start = bankbase[i];
|
||||
bank_size = banksize[i];
|
||||
}
|
||||
|
||||
bank_size = MIN(bank_size, kinfo->unassigned_mem);
|
||||
if ( !allocate_bank_memory(kinfo, gaddr_to_gfn(bank_start), bank_size) )
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( kinfo->unassigned_mem )
|
||||
goto fail;
|
||||
|
||||
for( i = 0; i < mem->nr_banks; i++ )
|
||||
{
|
||||
printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
|
||||
d,
|
||||
i,
|
||||
mem->bank[i].start,
|
||||
mem->bank[i].start + mem->bank[i].size,
|
||||
/* Don't want format this as PRIpaddr (16 digit hex) */
|
||||
(unsigned long)(mem->bank[i].size >> 20));
|
||||
}
|
||||
|
||||
xfree(hwdom_free_mem);
|
||||
return;
|
||||
|
||||
fail:
|
||||
panic("Failed to allocate requested domain memory."
|
||||
/* Don't want format this as PRIpaddr (16 digit hex) */
|
||||
" %ldKB unallocated. Fix the VMs configurations.\n",
|
||||
(unsigned long)kinfo->unassigned_mem >> 10);
|
||||
}
|
||||
|
||||
static int __init handle_pci_range(const struct dt_device_node *dev,
|
||||
uint64_t addr, uint64_t len, void *data)
|
||||
{
|
||||
@@ -1235,7 +1380,7 @@ int __init make_hypervisor_node(struct domain *d,
|
||||
|
||||
ext_regions->max_banks = NR_MEM_BANKS;
|
||||
|
||||
if ( is_domain_direct_mapped(d) )
|
||||
if ( domain_use_host_layout(d) )
|
||||
{
|
||||
if ( !is_iommu_enabled(d) )
|
||||
res = find_host_extended_regions(kinfo, ext_regions);
|
||||
@@ -2164,8 +2309,11 @@ static int __init construct_dom0(struct domain *d)
|
||||
/* type must be set before allocate_memory */
|
||||
d->arch.type = kinfo.type;
|
||||
#endif
|
||||
allocate_memory_11(d, &kinfo);
|
||||
find_gnttab_region(d, &kinfo);
|
||||
if ( is_domain_direct_mapped(d) )
|
||||
allocate_memory_11(d, &kinfo);
|
||||
else
|
||||
allocate_memory(d, &kinfo);
|
||||
|
||||
rc = process_shm_chosen(d, &kinfo);
|
||||
if ( rc < 0 )
|
||||
|
||||
@@ -11,6 +11,7 @@ bool allocate_domheap_memory(struct domain *d, paddr_t tot_size,
|
||||
alloc_domheap_mem_cb cb, void *extra);
|
||||
bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
|
||||
paddr_t tot_size);
|
||||
void allocate_memory(struct domain *d, struct kernel_info *kinfo);
|
||||
int construct_domain(struct domain *d, struct kernel_info *kinfo);
|
||||
int domain_fdt_begin_node(void *fdt, const char *name, uint64_t unit);
|
||||
int make_chosen_node(const struct kernel_info *kinfo);
|
||||
|
||||