From: kfraser@localhost.localdomain Date: Wed, 1 Nov 2006 11:18:29 +0000 (+0000) Subject: [XEN] Extend dom0_mem syntax to support min/max clamps. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15567^2~155 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=7ffcc43b02744f2ec9a064635ff09ea17c0a7253;p=xen.git [XEN] Extend dom0_mem syntax to support min/max clamps. dom0_mem=[min:,][max:,][] : The minimum amount of memory which should be allocated for dom0. : The maximum amount of memory which should be allocated for dom0. : The precise amount of memory to allocate for dom0. Notes: 1. is clamped from below by and from above by available memory and 2. is clamped from above by available memory and 3. is ignored if it is greater than 4. If is not specified, it is calculated as follows: "All of memory is allocated to domain 0, minus 1/16th which is reserved for uses such as DMA buffers (the reservation is clamped to 128MB)." Each value can be specified as positive or negative: If +ve: The specified amount is an absolute value. If -ve: The specified amount is subtracted from total available memory. Signed-off-by: Keir Fraser --- diff --git a/docs/src/user.tex b/docs/src/user.tex index 6b4e5cfa72..768b22165a 100644 --- a/docs/src/user.tex +++ b/docs/src/user.tex @@ -3202,12 +3202,21 @@ editing \path{grub.conf}. ignored. This parameter may be specified with a B, K, M or G suffix, representing bytes, kilobytes, megabytes and gigabytes respectively. The default unit, if no suffix is specified, is kilobytes. -\item [ dom0\_mem=xxx ] Set the amount of memory to be allocated to - domain0. In Xen 3.x the parameter may be specified with a B, K, M or +\item [ dom0\_mem=$<$specifier list$>$ ] Set the amount of memory to + be allocated to domain 0. This is a comma-separated list containing + the following optional components: + \begin{description} + \item[ min:$<$min\_amt$>$ ] Minimum amount to allocate to domain 0 + \item[ max:$<$min\_amt$>$ ] Maximum amount to allocate to domain 0 + \item[ $<$amt$>$ ] Precise amount to allocate to domain 0 + \end{description} + Each numeric parameter may be specified with a B, K, M or G suffix, representing bytes, kilobytes, megabytes and gigabytes respectively; if no suffix is specified, the parameter defaults to - kilobytes. In previous versions of Xen, suffixes were not supported - and the value is always interpreted as kilobytes. + kilobytes. Negative values are subtracted from total available + memory. If $<$amt$>$ is not specified, it defaults to all available + memory less a small amount (clamped to 128MB) for uses such as DMA + buffers. \item [ dom0\_vcpus\_pin ] Pins domain 0 VCPUs on their respective physical CPUS (default=false). \item [ tbuf\_size=xxx ] Set the size of the per-cpu trace buffers, in diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index cadd3793b7..7aada5b9bb 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -1177,6 +1177,6 @@ void sync_vcpu_execstate(struct vcpu *v) static void parse_dom0_mem(char *s) { - dom0_size = parse_size_and_unit(s); + dom0_size = parse_size_and_unit(s, NULL); } custom_param("dom0_mem", parse_dom0_mem); diff --git a/xen/arch/powerpc/domain_build.c b/xen/arch/powerpc/domain_build.c index 7858cb3c50..cc439ae51d 100644 --- a/xen/arch/powerpc/domain_build.c +++ b/xen/arch/powerpc/domain_build.c @@ -40,7 +40,7 @@ static void parse_dom0_mem(char *s) { unsigned long long bytes; - bytes = parse_size_and_unit(s); + bytes = parse_size_and_unit(s, NULL); dom0_nrpages = bytes >> PAGE_SHIFT; } custom_param("dom0_mem", parse_dom0_mem); diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index b8765be263..110d642a15 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -33,28 +33,45 @@ extern unsigned long initial_images_nrpages(void); extern void discard_initial_images(void); -static long dom0_nrpages; +static long dom0_nrpages, dom0_min_nrpages, dom0_max_nrpages = LONG_MAX; /* - * dom0_mem: - * If +ve: - * * The specified amount of memory is allocated to domain 0. - * If -ve: - * * All of memory is allocated to domain 0, minus the specified amount. - * If not specified: - * * All of memory is allocated to domain 0, minus 1/16th which is reserved - * for uses such as DMA buffers (the reservation is clamped to 128MB). + * dom0_mem=[min:,][max:,][] + * + * : The minimum amount of memory which should be allocated for dom0. + * : The maximum amount of memory which should be allocated for dom0. + * : The precise amount of memory to allocate for dom0. + * + * Notes: + * 1. is clamped from below by and from above by available + * memory and + * 2. is clamped from above by available memory and + * 3. is ignored if it is greater than + * 4. If is not specified, it is calculated as follows: + * "All of memory is allocated to domain 0, minus 1/16th which is reserved + * for uses such as DMA buffers (the reservation is clamped to 128MB)." + * + * Each value can be specified as positive or negative: + * If +ve: The specified amount is an absolute value. + * If -ve: The specified amount is subtracted from total available memory. */ +static long parse_amt(char *s, char **ps) +{ + long pages = parse_size_and_unit((*s == '-') ? s+1 : s, ps) >> PAGE_SHIFT; + return (*s == '-') ? -pages : pages; +} static void parse_dom0_mem(char *s) { - unsigned long long bytes; - char *t = s; - if ( *s == '-' ) - t++; - bytes = parse_size_and_unit(t); - dom0_nrpages = bytes >> PAGE_SHIFT; - if ( *s == '-' ) - dom0_nrpages = -dom0_nrpages; + do { + if ( !strncmp(s, "min:", 4) ) + dom0_min_nrpages = parse_amt(s+4, &s); + else if ( !strncmp(s, "max:", 4) ) + dom0_max_nrpages = parse_amt(s+4, &s); + else + dom0_nrpages = parse_amt(s, &s); + if ( *s != ',' ) + break; + } while ( *s++ == ',' ); } custom_param("dom0_mem", parse_dom0_mem); @@ -103,6 +120,35 @@ static struct page_info *alloc_chunk(struct domain *d, unsigned long max_pages) return page; } +static unsigned long compute_dom0_nr_pages(void) +{ + unsigned long avail = avail_domheap_pages() + initial_images_nrpages(); + + /* + * If domain 0 allocation isn't specified, reserve 1/16th of available + * memory for things like DMA buffers. This reservation is clamped to + * a maximum of 128MB. + */ + if ( dom0_nrpages == 0 ) + { + dom0_nrpages = avail; + dom0_nrpages = min(dom0_nrpages / 16, 128L << (20 - PAGE_SHIFT)); + dom0_nrpages = -dom0_nrpages; + } + + /* Negative memory specification means "all memory - specified amount". */ + if ( dom0_nrpages < 0 ) dom0_nrpages += avail; + if ( dom0_min_nrpages < 0 ) dom0_min_nrpages += avail; + if ( dom0_max_nrpages < 0 ) dom0_max_nrpages += avail; + + /* Clamp dom0 memory according to min/max limits and available memory. */ + dom0_nrpages = max(dom0_nrpages, dom0_min_nrpages); + dom0_nrpages = min(dom0_nrpages, dom0_max_nrpages); + dom0_nrpages = min(dom0_nrpages, (long)avail); + + return dom0_nrpages; +} + static void process_dom0_ioports_disable(void) { unsigned long io_from, io_to; @@ -269,25 +315,7 @@ int construct_dom0(struct domain *d, d->max_pages = ~0U; - /* - * If domain 0 allocation isn't specified, reserve 1/16th of available - * memory for things like DMA buffers. This reservation is clamped to - * a maximum of 128MB. - */ - if ( dom0_nrpages == 0 ) - { - dom0_nrpages = avail_domheap_pages() + initial_images_nrpages(); - dom0_nrpages = min(dom0_nrpages / 16, 128L << (20 - PAGE_SHIFT)); - dom0_nrpages = -dom0_nrpages; - } - - /* Negative memory specification means "all memory - specified amount". */ - if ( dom0_nrpages < 0 ) - nr_pages = avail_domheap_pages() + initial_images_nrpages() + - dom0_nrpages; - else - nr_pages = min(avail_domheap_pages() + initial_images_nrpages(), - (unsigned long)dom0_nrpages); + nr_pages = compute_dom0_nr_pages(); if ( (rc = parseelfimage(&dsi)) != 0 ) return rc; diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c index bbc147139c..b12eb68c87 100644 --- a/xen/arch/x86/e820.c +++ b/xen/arch/x86/e820.c @@ -6,7 +6,7 @@ /* opt_mem: Limit of physical RAM. Any RAM beyond this point is ignored. */ unsigned long long opt_mem; -static void parse_mem(char *s) { opt_mem = parse_size_and_unit(s); } +static void parse_mem(char *s) { opt_mem = parse_size_and_unit(s, NULL); } custom_param("mem", parse_mem); struct e820map e820; diff --git a/xen/common/lib.c b/xen/common/lib.c index 408e8eefe6..0eb58f19d2 100644 --- a/xen/common/lib.c +++ b/xen/common/lib.c @@ -439,21 +439,28 @@ s64 __moddi3(s64 a, s64 b) #endif /* BITS_PER_LONG == 32 */ -unsigned long long parse_size_and_unit(char *s) +unsigned long long parse_size_and_unit(const char *s, char **ps) { - unsigned long long ret = simple_strtoull(s, &s, 0); + unsigned long long ret = simple_strtoull(s, (char **)&s, 0); switch (*s) { case 'G': case 'g': ret <<= 10; case 'M': case 'm': ret <<= 10; - case 'K': case 'k': default: + case 'K': case 'k': ret <<= 10; case 'B': case 'b': + s++; + break; + default: + ret <<= 10; /* default to kB */ break; } + if (ps != NULL) + *ps = (char *)s; + return ret; } diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index bfb055f5e0..93fc193e17 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -54,7 +54,7 @@ static unsigned long lowmem_emergency_pool_pages; static void parse_lowmem_emergency_pool(char *s) { unsigned long long bytes; - bytes = parse_size_and_unit(s); + bytes = parse_size_and_unit(s, NULL); lowmem_emergency_pool_pages = bytes >> PAGE_SHIFT; } custom_param("lowmem_emergency_pool", parse_lowmem_emergency_pool); diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index 18eaf96a95..6327f3106e 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -86,7 +86,7 @@ long long simple_strtoll( unsigned long long simple_strtoull( const char *cp,char **endp, unsigned int base); -unsigned long long parse_size_and_unit(char *s); +unsigned long long parse_size_and_unit(const char *s, char **ps); #define TAINT_UNSAFE_SMP (1<<0) #define TAINT_MACHINE_CHECK (1<<1)