diff options
| -rw-r--r-- | arch/s390/Kconfig | 7 | ||||
| -rw-r--r-- | arch/s390/mm/Makefile | 1 | ||||
| -rw-r--r-- | arch/s390/mm/init.c | 3 | ||||
| -rw-r--r-- | arch/s390/mm/page-states.c | 79 | ||||
| -rw-r--r-- | include/asm-s390/page.h | 11 | ||||
| -rw-r--r-- | include/asm-s390/system.h | 6 |
6 files changed, 107 insertions, 0 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 29a7940f284f..1d035082e78e 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -430,6 +430,13 @@ config CMM_IUCV | |||
| 430 | Select this option to enable the special message interface to | 430 | Select this option to enable the special message interface to |
| 431 | the cooperative memory management. | 431 | the cooperative memory management. |
| 432 | 432 | ||
| 433 | config PAGE_STATES | ||
| 434 | bool "Unused page notification" | ||
| 435 | help | ||
| 436 | This enables the notification of unused pages to the | ||
| 437 | hypervisor. The ESSA instruction is used to do the states | ||
| 438 | changes between a page that has content and the unused state. | ||
| 439 | |||
| 433 | config VIRT_TIMER | 440 | config VIRT_TIMER |
| 434 | bool "Virtual CPU timer support" | 441 | bool "Virtual CPU timer support" |
| 435 | help | 442 | help |
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile index fb988a48a754..2a7458134544 100644 --- a/arch/s390/mm/Makefile +++ b/arch/s390/mm/Makefile | |||
| @@ -5,3 +5,4 @@ | |||
| 5 | obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o | 5 | obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o |
| 6 | obj-$(CONFIG_CMM) += cmm.o | 6 | obj-$(CONFIG_CMM) += cmm.o |
| 7 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 7 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
| 8 | obj-$(CONFIG_PAGE_STATES) += page-states.o | ||
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index fa31de6ae97a..29f3a63806b9 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
| @@ -126,6 +126,9 @@ void __init mem_init(void) | |||
| 126 | /* clear the zero-page */ | 126 | /* clear the zero-page */ |
| 127 | memset(empty_zero_page, 0, PAGE_SIZE); | 127 | memset(empty_zero_page, 0, PAGE_SIZE); |
| 128 | 128 | ||
| 129 | /* Setup guest page hinting */ | ||
| 130 | cmma_init(); | ||
| 131 | |||
| 129 | /* this will put all low memory onto the freelists */ | 132 | /* this will put all low memory onto the freelists */ |
| 130 | totalram_pages += free_all_bootmem(); | 133 | totalram_pages += free_all_bootmem(); |
| 131 | 134 | ||
diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c new file mode 100644 index 000000000000..fc0ad73ffd90 --- /dev/null +++ b/arch/s390/mm/page-states.c | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | /* | ||
| 2 | * arch/s390/mm/page-states.c | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2008 | ||
| 5 | * | ||
| 6 | * Guest page hinting for unused pages. | ||
| 7 | * | ||
| 8 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/errno.h> | ||
| 13 | #include <linux/types.h> | ||
| 14 | #include <linux/mm.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | |||
| 17 | #define ESSA_SET_STABLE 1 | ||
| 18 | #define ESSA_SET_UNUSED 2 | ||
| 19 | |||
| 20 | static int cmma_flag; | ||
| 21 | |||
| 22 | static int __init cmma(char *str) | ||
| 23 | { | ||
| 24 | char *parm; | ||
| 25 | parm = strstrip(str); | ||
| 26 | if (strcmp(parm, "yes") == 0 || strcmp(parm, "on") == 0) { | ||
| 27 | cmma_flag = 1; | ||
| 28 | return 1; | ||
| 29 | } | ||
| 30 | cmma_flag = 0; | ||
| 31 | if (strcmp(parm, "no") == 0 || strcmp(parm, "off") == 0) | ||
| 32 | return 1; | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | __setup("cmma=", cmma); | ||
| 37 | |||
| 38 | void __init cmma_init(void) | ||
| 39 | { | ||
| 40 | register unsigned long tmp asm("0") = 0; | ||
| 41 | register int rc asm("1") = -EOPNOTSUPP; | ||
| 42 | |||
| 43 | if (!cmma_flag) | ||
| 44 | return; | ||
| 45 | asm volatile( | ||
| 46 | " .insn rrf,0xb9ab0000,%1,%1,0,0\n" | ||
| 47 | "0: la %0,0\n" | ||
| 48 | "1:\n" | ||
| 49 | EX_TABLE(0b,1b) | ||
| 50 | : "+&d" (rc), "+&d" (tmp)); | ||
| 51 | if (rc) | ||
| 52 | cmma_flag = 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | void arch_free_page(struct page *page, int order) | ||
| 56 | { | ||
| 57 | int i, rc; | ||
| 58 | |||
| 59 | if (!cmma_flag) | ||
| 60 | return; | ||
| 61 | for (i = 0; i < (1 << order); i++) | ||
| 62 | asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" | ||
| 63 | : "=&d" (rc) | ||
| 64 | : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), | ||
| 65 | "i" (ESSA_SET_UNUSED)); | ||
| 66 | } | ||
| 67 | |||
| 68 | void arch_alloc_page(struct page *page, int order) | ||
| 69 | { | ||
| 70 | int i, rc; | ||
| 71 | |||
| 72 | if (!cmma_flag) | ||
| 73 | return; | ||
| 74 | for (i = 0; i < (1 << order); i++) | ||
| 75 | asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" | ||
| 76 | : "=&d" (rc) | ||
| 77 | : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), | ||
| 78 | "i" (ESSA_SET_STABLE)); | ||
| 79 | } | ||
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h index f0f4579eac13..12fd9c4f0f15 100644 --- a/include/asm-s390/page.h +++ b/include/asm-s390/page.h | |||
| @@ -125,6 +125,17 @@ page_get_storage_key(unsigned long addr) | |||
| 125 | return skey; | 125 | return skey; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | #ifdef CONFIG_PAGE_STATES | ||
| 129 | |||
| 130 | struct page; | ||
| 131 | void arch_free_page(struct page *page, int order); | ||
| 132 | void arch_alloc_page(struct page *page, int order); | ||
| 133 | |||
| 134 | #define HAVE_ARCH_FREE_PAGE | ||
| 135 | #define HAVE_ARCH_ALLOC_PAGE | ||
| 136 | |||
| 137 | #endif | ||
| 138 | |||
| 128 | #endif /* !__ASSEMBLY__ */ | 139 | #endif /* !__ASSEMBLY__ */ |
| 129 | 140 | ||
| 130 | /* to align the pointer to the (next) page boundary */ | 141 | /* to align the pointer to the (next) page boundary */ |
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index c819ae25a842..e0d4500d5f95 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
| @@ -116,6 +116,12 @@ extern void pfault_fini(void); | |||
| 116 | #define pfault_fini() do { } while (0) | 116 | #define pfault_fini() do { } while (0) |
| 117 | #endif /* CONFIG_PFAULT */ | 117 | #endif /* CONFIG_PFAULT */ |
| 118 | 118 | ||
| 119 | #ifdef CONFIG_PAGE_STATES | ||
| 120 | extern void cmma_init(void); | ||
| 121 | #else | ||
| 122 | static inline void cmma_init(void) { } | ||
| 123 | #endif | ||
| 124 | |||
| 119 | #define finish_arch_switch(prev) do { \ | 125 | #define finish_arch_switch(prev) do { \ |
| 120 | set_fs(current->thread.mm_segment); \ | 126 | set_fs(current->thread.mm_segment); \ |
| 121 | account_vtime(prev); \ | 127 | account_vtime(prev); \ |
