s390/mm: make hugepages_supported a boot time decision

There is a potential bug with KVM and hugetlbfs if the hardware does not
support hugepages (EDAT1).  We fix this by making EDAT1 a hard requirement
for hugepages and therefore removing and simplifying code.

As s390, with the sw-emulated hugepages, was the only user of
arch_prepare/release_hugepage I also removed theses calls from common and
other architecture code.

This patch (of 5):

By dropping support for hugepages on machines which do not have the
hardware feature EDAT1, we fix a potential s390 KVM bug.

The bug would happen if a guest is backed by hugetlbfs (not supported
currently), but does not get pagetables with PGSTE.  This would lead to
random memory overwrites.

Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Dominik Dingel 2015-06-25 14:59:39 -07:00 committed by Linus Torvalds
parent aefbef10e3
commit bea41197ea
3 changed files with 8 additions and 4 deletions

View File

@ -17,7 +17,10 @@
#define PAGE_DEFAULT_ACC 0 #define PAGE_DEFAULT_ACC 0
#define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4)
#define HPAGE_SHIFT 20 #include <asm/setup.h>
#ifndef __ASSEMBLY__
extern unsigned int HPAGE_SHIFT;
#define HPAGE_SIZE (1UL << HPAGE_SHIFT) #define HPAGE_SIZE (1UL << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1)) #define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
@ -27,9 +30,6 @@
#define ARCH_HAS_PREPARE_HUGEPAGE #define ARCH_HAS_PREPARE_HUGEPAGE
#define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH #define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH
#include <asm/setup.h>
#ifndef __ASSEMBLY__
static inline void storage_key_init_range(unsigned long start, unsigned long end) static inline void storage_key_init_range(unsigned long start, unsigned long end)
{ {
#if PAGE_DEFAULT_KEY #if PAGE_DEFAULT_KEY

View File

@ -880,6 +880,8 @@ void __init setup_arch(char **cmdline_p)
*/ */
setup_hwcaps(); setup_hwcaps();
HPAGE_SHIFT = MACHINE_HAS_HPAGE ? 20 : 0;
/* /*
* Create kernel page tables and switch to virtual addressing. * Create kernel page tables and switch to virtual addressing.
*/ */

View File

@ -31,6 +31,8 @@
#define ALLOC_ORDER 2 #define ALLOC_ORDER 2
#define FRAG_MASK 0x03 #define FRAG_MASK 0x03
unsigned int HPAGE_SHIFT;
unsigned long *crst_table_alloc(struct mm_struct *mm) unsigned long *crst_table_alloc(struct mm_struct *mm)
{ {
struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER); struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);