Skip to content

Commit

Permalink
[S390] guest page hinting light
Browse files Browse the repository at this point in the history
Use the existing arch_alloc_page/arch_free_page callbacks to do
the guest page state transitions between stable and unused.

Acked-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Martin Schwidefsky committed May 7, 2008
1 parent 74c76c8 commit 45e576b
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 0 deletions.
7 changes: 7 additions & 0 deletions arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,13 @@ config CMM_IUCV
Select this option to enable the special message interface to
the cooperative memory management.

config PAGE_STATES
bool "Unused page notification"
help
This enables the notification of unused pages to the
hypervisor. The ESSA instruction is used to do the states
changes between a page that has content and the unused state.

config VIRT_TIMER
bool "Virtual CPU timer support"
help
Expand Down
1 change: 1 addition & 0 deletions arch/s390/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PAGE_STATES) += page-states.o
3 changes: 3 additions & 0 deletions arch/s390/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ void __init mem_init(void)
/* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE);

/* Setup guest page hinting */
cmma_init();

/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem();

Expand Down
79 changes: 79 additions & 0 deletions arch/s390/mm/page-states.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* arch/s390/mm/page-states.c
*
* Copyright IBM Corp. 2008
*
* Guest page hinting for unused pages.
*
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/init.h>

#define ESSA_SET_STABLE 1
#define ESSA_SET_UNUSED 2

static int cmma_flag;

static int __init cmma(char *str)
{
char *parm;
parm = strstrip(str);
if (strcmp(parm, "yes") == 0 || strcmp(parm, "on") == 0) {
cmma_flag = 1;
return 1;
}
cmma_flag = 0;
if (strcmp(parm, "no") == 0 || strcmp(parm, "off") == 0)
return 1;
return 0;
}

__setup("cmma=", cmma);

void __init cmma_init(void)
{
register unsigned long tmp asm("0") = 0;
register int rc asm("1") = -EOPNOTSUPP;

if (!cmma_flag)
return;
asm volatile(
" .insn rrf,0xb9ab0000,%1,%1,0,0\n"
"0: la %0,0\n"
"1:\n"
EX_TABLE(0b,1b)
: "+&d" (rc), "+&d" (tmp));
if (rc)
cmma_flag = 0;
}

void arch_free_page(struct page *page, int order)
{
int i, rc;

if (!cmma_flag)
return;
for (i = 0; i < (1 << order); i++)
asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
: "=&d" (rc)
: "a" ((page_to_pfn(page) + i) << PAGE_SHIFT),
"i" (ESSA_SET_UNUSED));
}

void arch_alloc_page(struct page *page, int order)
{
int i, rc;

if (!cmma_flag)
return;
for (i = 0; i < (1 << order); i++)
asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0"
: "=&d" (rc)
: "a" ((page_to_pfn(page) + i) << PAGE_SHIFT),
"i" (ESSA_SET_STABLE));
}
11 changes: 11 additions & 0 deletions include/asm-s390/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ page_get_storage_key(unsigned long addr)
return skey;
}

#ifdef CONFIG_PAGE_STATES

struct page;
void arch_free_page(struct page *page, int order);
void arch_alloc_page(struct page *page, int order);

#define HAVE_ARCH_FREE_PAGE
#define HAVE_ARCH_ALLOC_PAGE

#endif

#endif /* !__ASSEMBLY__ */

/* to align the pointer to the (next) page boundary */
Expand Down
6 changes: 6 additions & 0 deletions include/asm-s390/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ extern void pfault_fini(void);
#define pfault_fini() do { } while (0)
#endif /* CONFIG_PFAULT */

#ifdef CONFIG_PAGE_STATES
extern void cmma_init(void);
#else
static inline void cmma_init(void) { }
#endif

#define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \
account_vtime(prev); \
Expand Down

0 comments on commit 45e576b

Please sign in to comment.