Commit 14f966e79445015cd89d0fa0ceb6b33702e951b6

Authored by Robert Jennings
Committed by Benjamin Herrenschmidt
1 parent d69a78d7da

powerpc/pseries: CMO unused page hinting

Adds support for the "unused" page hint which can be used in shared
memory partitions to flag pages not in use, which will then be stolen
before active pages by the hypervisor when memory needs to be moved to
LPARs in need of additional memory.  Failure to mark pages as 'unused'
makes the LPAR slower to give up unused memory to other partitions.

This adds the kernel parameter 'cmo_free_hint' to disable this
functionality.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Showing 3 changed files with 64 additions and 0 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -497,6 +497,13 @@
497 497 Also note the kernel might malfunction if you disable
498 498 some critical bits.
499 499  
  500 + cmo_free_hint= [PPC] Format: { yes | no }
  501 + Specify whether pages are marked as being inactive
  502 + when they are freed. This is used in CMO environments
  503 + to determine OS memory pressure for page stealing by
  504 + a hypervisor.
  505 + Default: yes
  506 +
500 507 code_bytes [X86] How many bytes of object code to print
501 508 in an oops report.
502 509 Range: 0 - 8192
arch/powerpc/include/asm/page.h
... ... @@ -231,6 +231,11 @@
231 231 struct page *p);
232 232 extern int page_is_ram(unsigned long pfn);
233 233  
  234 +#ifdef CONFIG_PPC_SMLPAR
  235 +void arch_free_page(struct page *page, int order);
  236 +#define HAVE_ARCH_FREE_PAGE
  237 +#endif
  238 +
234 239 struct vm_area_struct;
235 240  
236 241 typedef struct page *pgtable_t;
arch/powerpc/platforms/pseries/lpar.c
... ... @@ -609,4 +609,56 @@
609 609 ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
610 610 ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear;
611 611 }
  612 +
  613 +#ifdef CONFIG_PPC_SMLPAR
  614 +#define CMO_FREE_HINT_DEFAULT 1
  615 +static int cmo_free_hint_flag = CMO_FREE_HINT_DEFAULT;
  616 +
  617 +static int __init cmo_free_hint(char *str)
  618 +{
  619 + char *parm;
  620 + parm = strstrip(str);
  621 +
  622 + if (strcasecmp(parm, "no") == 0 || strcasecmp(parm, "off") == 0) {
  623 + printk(KERN_INFO "cmo_free_hint: CMO free page hinting is not active.\n");
  624 + cmo_free_hint_flag = 0;
  625 + return 1;
  626 + }
  627 +
  628 + cmo_free_hint_flag = 1;
  629 + printk(KERN_INFO "cmo_free_hint: CMO free page hinting is active.\n");
  630 +
  631 + if (strcasecmp(parm, "yes") == 0 || strcasecmp(parm, "on") == 0)
  632 + return 1;
  633 +
  634 + return 0;
  635 +}
  636 +
  637 +__setup("cmo_free_hint=", cmo_free_hint);
  638 +
  639 +static void pSeries_set_page_state(struct page *page, int order,
  640 + unsigned long state)
  641 +{
  642 + int i, j;
  643 + unsigned long cmo_page_sz, addr;
  644 +
  645 + cmo_page_sz = cmo_get_page_size();
  646 + addr = __pa((unsigned long)page_address(page));
  647 +
  648 + for (i = 0; i < (1 << order); i++, addr += PAGE_SIZE) {
  649 + for (j = 0; j < PAGE_SIZE; j += cmo_page_sz)
  650 + plpar_hcall_norets(H_PAGE_INIT, state, addr + j, 0);
  651 + }
  652 +}
  653 +
  654 +void arch_free_page(struct page *page, int order)
  655 +{
  656 + if (!cmo_free_hint_flag || !firmware_has_feature(FW_FEATURE_CMO))
  657 + return;
  658 +
  659 + pSeries_set_page_state(page, order, H_PAGE_SET_UNUSED);
  660 +}
  661 +EXPORT_SYMBOL(arch_free_page);
  662 +
  663 +#endif