[S390] guest page hinting light

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>
This commit is contained in:
Martin Schwidefsky 2008-05-07 09:22:59 +02:00
Родитель 74c76c8457
Коммит 45e576b1c3
6 изменённых файлов: 107 добавлений и 0 удалений

Просмотреть файл

@ -430,6 +430,13 @@ config CMM_IUCV
Select this option to enable the special message interface to Select this option to enable the special message interface to
the cooperative memory management. 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 config VIRT_TIMER
bool "Virtual CPU timer support" bool "Virtual CPU timer support"
help help

Просмотреть файл

@ -5,3 +5,4 @@
obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PAGE_STATES) += page-states.o

Просмотреть файл

@ -126,6 +126,9 @@ void __init mem_init(void)
/* clear the zero-page */ /* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE); memset(empty_zero_page, 0, PAGE_SIZE);
/* Setup guest page hinting */
cmma_init();
/* this will put all low memory onto the freelists */ /* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem(); totalram_pages += free_all_bootmem();

Просмотреть файл

@ -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));
}

Просмотреть файл

@ -125,6 +125,17 @@ page_get_storage_key(unsigned long addr)
return skey; 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__ */ #endif /* !__ASSEMBLY__ */
/* to align the pointer to the (next) page boundary */ /* to align the pointer to the (next) page boundary */

Просмотреть файл

@ -116,6 +116,12 @@ extern void pfault_fini(void);
#define pfault_fini() do { } while (0) #define pfault_fini() do { } while (0)
#endif /* CONFIG_PFAULT */ #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 { \ #define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \ set_fs(current->thread.mm_segment); \
account_vtime(prev); \ account_vtime(prev); \