1c6557e7fSMartin Schwidefsky /* 2c6557e7fSMartin Schwidefsky * S390 version 3a53c8fabSHeiko Carstens * Copyright IBM Corp. 1999, 2000 4c6557e7fSMartin Schwidefsky * Author(s): Hartmut Penner (hp@de.ibm.com) 5c6557e7fSMartin Schwidefsky */ 6c6557e7fSMartin Schwidefsky 7c6557e7fSMartin Schwidefsky #ifndef _S390_PAGE_H 8c6557e7fSMartin Schwidefsky #define _S390_PAGE_H 9c6557e7fSMartin Schwidefsky 10c6557e7fSMartin Schwidefsky #include <linux/const.h> 11c6557e7fSMartin Schwidefsky #include <asm/types.h> 12c6557e7fSMartin Schwidefsky 13c6557e7fSMartin Schwidefsky /* PAGE_SHIFT determines the page size */ 14c6557e7fSMartin Schwidefsky #define PAGE_SHIFT 12 15c6557e7fSMartin Schwidefsky #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) 16c6557e7fSMartin Schwidefsky #define PAGE_MASK (~(PAGE_SIZE-1)) 17c6557e7fSMartin Schwidefsky #define PAGE_DEFAULT_ACC 0 18c6557e7fSMartin Schwidefsky #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) 19c6557e7fSMartin Schwidefsky 20c6557e7fSMartin Schwidefsky #define HPAGE_SHIFT 20 21c6557e7fSMartin Schwidefsky #define HPAGE_SIZE (1UL << HPAGE_SHIFT) 22c6557e7fSMartin Schwidefsky #define HPAGE_MASK (~(HPAGE_SIZE - 1)) 23c6557e7fSMartin Schwidefsky #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) 24c6557e7fSMartin Schwidefsky 25c6557e7fSMartin Schwidefsky #define ARCH_HAS_SETCLEAR_HUGE_PTE 26c6557e7fSMartin Schwidefsky #define ARCH_HAS_HUGE_PTE_TYPE 27c6557e7fSMartin Schwidefsky #define ARCH_HAS_PREPARE_HUGEPAGE 28c6557e7fSMartin Schwidefsky #define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH 29c6557e7fSMartin Schwidefsky 30c6557e7fSMartin Schwidefsky #include <asm/setup.h> 31c6557e7fSMartin Schwidefsky #ifndef __ASSEMBLY__ 32c6557e7fSMartin Schwidefsky 336b70a920SHeiko Carstens void storage_key_init_range(unsigned long start, unsigned long end); 346b70a920SHeiko Carstens 3585e9d0e5SHeiko Carstens static unsigned long pfmf(unsigned long function, unsigned long address) 3685e9d0e5SHeiko Carstens { 3785e9d0e5SHeiko Carstens asm volatile( 3885e9d0e5SHeiko Carstens " .insn rre,0xb9af0000,%[function],%[address]" 3985e9d0e5SHeiko Carstens : [address] "+a" (address) 4085e9d0e5SHeiko Carstens : [function] "d" (function) 4185e9d0e5SHeiko Carstens : "memory"); 4285e9d0e5SHeiko Carstens return address; 4385e9d0e5SHeiko Carstens } 4485e9d0e5SHeiko Carstens 45c6557e7fSMartin Schwidefsky static inline void clear_page(void *page) 46c6557e7fSMartin Schwidefsky { 47c6557e7fSMartin Schwidefsky if (MACHINE_HAS_PFMF) { 4885e9d0e5SHeiko Carstens pfmf(0x10000, (unsigned long)page); 49c6557e7fSMartin Schwidefsky } else { 50c6557e7fSMartin Schwidefsky register unsigned long reg1 asm ("1") = 0; 51c6557e7fSMartin Schwidefsky register void *reg2 asm ("2") = page; 52c6557e7fSMartin Schwidefsky register unsigned long reg3 asm ("3") = 4096; 53c6557e7fSMartin Schwidefsky asm volatile( 54c6557e7fSMartin Schwidefsky " mvcl 2,0" 55c6557e7fSMartin Schwidefsky : "+d" (reg2), "+d" (reg3) : "d" (reg1) 56c6557e7fSMartin Schwidefsky : "memory", "cc"); 57c6557e7fSMartin Schwidefsky } 58c6557e7fSMartin Schwidefsky } 59c6557e7fSMartin Schwidefsky 60c6557e7fSMartin Schwidefsky static inline void copy_page(void *to, void *from) 61c6557e7fSMartin Schwidefsky { 62c6557e7fSMartin Schwidefsky if (MACHINE_HAS_MVPG) { 63c6557e7fSMartin Schwidefsky register unsigned long reg0 asm ("0") = 0; 64c6557e7fSMartin Schwidefsky asm volatile( 65c6557e7fSMartin Schwidefsky " mvpg %0,%1" 66c6557e7fSMartin Schwidefsky : : "a" (to), "a" (from), "d" (reg0) 67c6557e7fSMartin Schwidefsky : "memory", "cc"); 68c6557e7fSMartin Schwidefsky } else 69c6557e7fSMartin Schwidefsky asm volatile( 70c6557e7fSMartin Schwidefsky " mvc 0(256,%0),0(%1)\n" 71c6557e7fSMartin Schwidefsky " mvc 256(256,%0),256(%1)\n" 72c6557e7fSMartin Schwidefsky " mvc 512(256,%0),512(%1)\n" 73c6557e7fSMartin Schwidefsky " mvc 768(256,%0),768(%1)\n" 74c6557e7fSMartin Schwidefsky " mvc 1024(256,%0),1024(%1)\n" 75c6557e7fSMartin Schwidefsky " mvc 1280(256,%0),1280(%1)\n" 76c6557e7fSMartin Schwidefsky " mvc 1536(256,%0),1536(%1)\n" 77c6557e7fSMartin Schwidefsky " mvc 1792(256,%0),1792(%1)\n" 78c6557e7fSMartin Schwidefsky " mvc 2048(256,%0),2048(%1)\n" 79c6557e7fSMartin Schwidefsky " mvc 2304(256,%0),2304(%1)\n" 80c6557e7fSMartin Schwidefsky " mvc 2560(256,%0),2560(%1)\n" 81c6557e7fSMartin Schwidefsky " mvc 2816(256,%0),2816(%1)\n" 82c6557e7fSMartin Schwidefsky " mvc 3072(256,%0),3072(%1)\n" 83c6557e7fSMartin Schwidefsky " mvc 3328(256,%0),3328(%1)\n" 84c6557e7fSMartin Schwidefsky " mvc 3584(256,%0),3584(%1)\n" 85c6557e7fSMartin Schwidefsky " mvc 3840(256,%0),3840(%1)\n" 86c6557e7fSMartin Schwidefsky : : "a" (to), "a" (from) : "memory"); 87c6557e7fSMartin Schwidefsky } 88c6557e7fSMartin Schwidefsky 89c6557e7fSMartin Schwidefsky #define clear_user_page(page, vaddr, pg) clear_page(page) 90c6557e7fSMartin Schwidefsky #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 91c6557e7fSMartin Schwidefsky 92c6557e7fSMartin Schwidefsky #define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ 93c6557e7fSMartin Schwidefsky alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) 94c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 95c6557e7fSMartin Schwidefsky 96c6557e7fSMartin Schwidefsky /* 97c6557e7fSMartin Schwidefsky * These are used to make use of C type-checking.. 98c6557e7fSMartin Schwidefsky */ 99c6557e7fSMartin Schwidefsky 100c6557e7fSMartin Schwidefsky typedef struct { unsigned long pgprot; } pgprot_t; 101b2fa47e6SMartin Schwidefsky typedef struct { unsigned long pgste; } pgste_t; 102c6557e7fSMartin Schwidefsky typedef struct { unsigned long pte; } pte_t; 103c6557e7fSMartin Schwidefsky typedef struct { unsigned long pmd; } pmd_t; 104c6557e7fSMartin Schwidefsky typedef struct { unsigned long pud; } pud_t; 105c6557e7fSMartin Schwidefsky typedef struct { unsigned long pgd; } pgd_t; 106c6557e7fSMartin Schwidefsky typedef pte_t *pgtable_t; 107c6557e7fSMartin Schwidefsky 108c6557e7fSMartin Schwidefsky #define pgprot_val(x) ((x).pgprot) 109b2fa47e6SMartin Schwidefsky #define pgste_val(x) ((x).pgste) 110c6557e7fSMartin Schwidefsky #define pte_val(x) ((x).pte) 111c6557e7fSMartin Schwidefsky #define pmd_val(x) ((x).pmd) 112c6557e7fSMartin Schwidefsky #define pud_val(x) ((x).pud) 113c6557e7fSMartin Schwidefsky #define pgd_val(x) ((x).pgd) 114c6557e7fSMartin Schwidefsky 115b2fa47e6SMartin Schwidefsky #define __pgste(x) ((pgste_t) { (x) } ) 116c6557e7fSMartin Schwidefsky #define __pte(x) ((pte_t) { (x) } ) 117c6557e7fSMartin Schwidefsky #define __pmd(x) ((pmd_t) { (x) } ) 118b2fa47e6SMartin Schwidefsky #define __pud(x) ((pud_t) { (x) } ) 119c6557e7fSMartin Schwidefsky #define __pgd(x) ((pgd_t) { (x) } ) 120c6557e7fSMartin Schwidefsky #define __pgprot(x) ((pgprot_t) { (x) } ) 121c6557e7fSMartin Schwidefsky 1222d42552dSMartin Schwidefsky static inline void page_set_storage_key(unsigned long addr, 1232d42552dSMartin Schwidefsky unsigned char skey, int mapped) 124c6557e7fSMartin Schwidefsky { 125e2b8d7afSMartin Schwidefsky if (!mapped) 126e2b8d7afSMartin Schwidefsky asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" 127e2b8d7afSMartin Schwidefsky : : "d" (skey), "a" (addr)); 128e2b8d7afSMartin Schwidefsky else 129c6557e7fSMartin Schwidefsky asm volatile("sske %0,%1" : : "d" (skey), "a" (addr)); 130c6557e7fSMartin Schwidefsky } 131c6557e7fSMartin Schwidefsky 1322d42552dSMartin Schwidefsky static inline unsigned char page_get_storage_key(unsigned long addr) 133c6557e7fSMartin Schwidefsky { 1342d42552dSMartin Schwidefsky unsigned char skey; 135c6557e7fSMartin Schwidefsky 1362d42552dSMartin Schwidefsky asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr)); 137c6557e7fSMartin Schwidefsky return skey; 138c6557e7fSMartin Schwidefsky } 139c6557e7fSMartin Schwidefsky 1402d42552dSMartin Schwidefsky static inline int page_reset_referenced(unsigned long addr) 1412d42552dSMartin Schwidefsky { 1422d42552dSMartin Schwidefsky unsigned int ipm; 1432d42552dSMartin Schwidefsky 1442d42552dSMartin Schwidefsky asm volatile( 1452d42552dSMartin Schwidefsky " rrbe 0,%1\n" 1462d42552dSMartin Schwidefsky " ipm %0\n" 1472d42552dSMartin Schwidefsky : "=d" (ipm) : "a" (addr) : "cc"); 1482d42552dSMartin Schwidefsky return !!(ipm & 0x20000000); 1492d42552dSMartin Schwidefsky } 1502d42552dSMartin Schwidefsky 1512d42552dSMartin Schwidefsky /* Bits int the storage key */ 1522d42552dSMartin Schwidefsky #define _PAGE_CHANGED 0x02 /* HW changed bit */ 1532d42552dSMartin Schwidefsky #define _PAGE_REFERENCED 0x04 /* HW referenced bit */ 1542d42552dSMartin Schwidefsky #define _PAGE_FP_BIT 0x08 /* HW fetch protection bit */ 1552d42552dSMartin Schwidefsky #define _PAGE_ACC_BITS 0xf0 /* HW access control bits */ 1562d42552dSMartin Schwidefsky 1572d42552dSMartin Schwidefsky /* 1582d42552dSMartin Schwidefsky * Test and clear dirty bit in storage key. 1592d42552dSMartin Schwidefsky * We can't clear the changed bit atomically. This is a potential 1602d42552dSMartin Schwidefsky * race against modification of the referenced bit. This function 1612d42552dSMartin Schwidefsky * should therefore only be called if it is not mapped in any 1622d42552dSMartin Schwidefsky * address space. 1632d42552dSMartin Schwidefsky */ 1642d42552dSMartin Schwidefsky #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY 1652d42552dSMartin Schwidefsky static inline int page_test_and_clear_dirty(unsigned long pfn, int mapped) 1662d42552dSMartin Schwidefsky { 1672d42552dSMartin Schwidefsky unsigned char skey; 1682d42552dSMartin Schwidefsky 1692d42552dSMartin Schwidefsky skey = page_get_storage_key(pfn << PAGE_SHIFT); 1702d42552dSMartin Schwidefsky if (!(skey & _PAGE_CHANGED)) 1712d42552dSMartin Schwidefsky return 0; 1722d42552dSMartin Schwidefsky page_set_storage_key(pfn << PAGE_SHIFT, skey & ~_PAGE_CHANGED, mapped); 1732d42552dSMartin Schwidefsky return 1; 1742d42552dSMartin Schwidefsky } 1752d42552dSMartin Schwidefsky 1762d42552dSMartin Schwidefsky /* 1772d42552dSMartin Schwidefsky * Test and clear referenced bit in storage key. 1782d42552dSMartin Schwidefsky */ 1792d42552dSMartin Schwidefsky #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG 1802d42552dSMartin Schwidefsky static inline int page_test_and_clear_young(unsigned long pfn) 1812d42552dSMartin Schwidefsky { 1822d42552dSMartin Schwidefsky return page_reset_referenced(pfn << PAGE_SHIFT); 1832d42552dSMartin Schwidefsky } 1842d42552dSMartin Schwidefsky 185c6557e7fSMartin Schwidefsky struct page; 186c6557e7fSMartin Schwidefsky void arch_free_page(struct page *page, int order); 187c6557e7fSMartin Schwidefsky void arch_alloc_page(struct page *page, int order); 188638ad34aSMartin Schwidefsky void arch_set_page_states(int make_stable); 189c6557e7fSMartin Schwidefsky 190ec6743bbSHendrik Brueckner static inline int devmem_is_allowed(unsigned long pfn) 191ec6743bbSHendrik Brueckner { 192ec6743bbSHendrik Brueckner return 0; 193ec6743bbSHendrik Brueckner } 194ec6743bbSHendrik Brueckner 195c6557e7fSMartin Schwidefsky #define HAVE_ARCH_FREE_PAGE 196c6557e7fSMartin Schwidefsky #define HAVE_ARCH_ALLOC_PAGE 197c6557e7fSMartin Schwidefsky 198c6557e7fSMartin Schwidefsky #endif /* !__ASSEMBLY__ */ 199c6557e7fSMartin Schwidefsky 200c6557e7fSMartin Schwidefsky #define __PAGE_OFFSET 0x0UL 201c6557e7fSMartin Schwidefsky #define PAGE_OFFSET 0x0UL 202c6557e7fSMartin Schwidefsky #define __pa(x) (unsigned long)(x) 203c6557e7fSMartin Schwidefsky #define __va(x) (void *)(unsigned long)(x) 204c6557e7fSMartin Schwidefsky #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) 205c6557e7fSMartin Schwidefsky #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) 206c6557e7fSMartin Schwidefsky #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) 207c6557e7fSMartin Schwidefsky 208c6557e7fSMartin Schwidefsky #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \ 209c6557e7fSMartin Schwidefsky VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 210c6557e7fSMartin Schwidefsky 211c6557e7fSMartin Schwidefsky #include <asm-generic/memory_model.h> 2125b17e1cdSArnd Bergmann #include <asm-generic/getorder.h> 213c6557e7fSMartin Schwidefsky 214b020632eSMartin Schwidefsky #define __HAVE_ARCH_GATE_AREA 1 215b020632eSMartin Schwidefsky 216c6557e7fSMartin Schwidefsky #endif /* _S390_PAGE_H */ 217