18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Page management definitions for the Hexagon architecture 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _ASM_PAGE_H 98c2ecf20Sopenharmony_ci#define _ASM_PAGE_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/const.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* This is probably not the most graceful way to handle this. */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifdef CONFIG_PAGE_SIZE_4KB 168c2ecf20Sopenharmony_ci#define PAGE_SHIFT 12 178c2ecf20Sopenharmony_ci#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_4KB 188c2ecf20Sopenharmony_ci#endif 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#ifdef CONFIG_PAGE_SIZE_16KB 218c2ecf20Sopenharmony_ci#define PAGE_SHIFT 14 228c2ecf20Sopenharmony_ci#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_16KB 238c2ecf20Sopenharmony_ci#endif 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#ifdef CONFIG_PAGE_SIZE_64KB 268c2ecf20Sopenharmony_ci#define PAGE_SHIFT 16 278c2ecf20Sopenharmony_ci#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_64KB 288c2ecf20Sopenharmony_ci#endif 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#ifdef CONFIG_PAGE_SIZE_256KB 318c2ecf20Sopenharmony_ci#define PAGE_SHIFT 18 328c2ecf20Sopenharmony_ci#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_256KB 338c2ecf20Sopenharmony_ci#endif 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#ifdef CONFIG_PAGE_SIZE_1MB 368c2ecf20Sopenharmony_ci#define PAGE_SHIFT 20 378c2ecf20Sopenharmony_ci#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_1MB 388c2ecf20Sopenharmony_ci#endif 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * These should be defined in hugetlb.h, but apparently not. 428c2ecf20Sopenharmony_ci * "Huge" for us should be 4MB or 16MB, which are both represented 438c2ecf20Sopenharmony_ci * in L1 PTE's. Right now, it's set up for 4MB. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE 468c2ecf20Sopenharmony_ci#define HPAGE_SHIFT 22 478c2ecf20Sopenharmony_ci#define HPAGE_SIZE (1UL << HPAGE_SHIFT) 488c2ecf20Sopenharmony_ci#define HPAGE_MASK (~(HPAGE_SIZE-1)) 498c2ecf20Sopenharmony_ci#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT) 508c2ecf20Sopenharmony_ci#define HVM_HUGEPAGE_SIZE 0x5 518c2ecf20Sopenharmony_ci#endif 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define PAGE_SIZE (1UL << PAGE_SHIFT) 548c2ecf20Sopenharmony_ci#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 578c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* 608c2ecf20Sopenharmony_ci * This is for PFN_DOWN, which mm.h needs. Seems the right place to pull it in. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci#include <linux/pfn.h> 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * We implement a two-level architecture-specific page table structure. 668c2ecf20Sopenharmony_ci * Null intermediate page table level (pmd, pud) definitions will come from 678c2ecf20Sopenharmony_ci * asm-generic/pagetable-nopmd.h and asm-generic/pagetable-nopud.h 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_citypedef struct { unsigned long pte; } pte_t; 708c2ecf20Sopenharmony_citypedef struct { unsigned long pgd; } pgd_t; 718c2ecf20Sopenharmony_citypedef struct { unsigned long pgprot; } pgprot_t; 728c2ecf20Sopenharmony_citypedef struct page *pgtable_t; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#define pte_val(x) ((x).pte) 758c2ecf20Sopenharmony_ci#define pgd_val(x) ((x).pgd) 768c2ecf20Sopenharmony_ci#define pgprot_val(x) ((x).pgprot) 778c2ecf20Sopenharmony_ci#define __pte(x) ((pte_t) { (x) }) 788c2ecf20Sopenharmony_ci#define __pgd(x) ((pgd_t) { (x) }) 798c2ecf20Sopenharmony_ci#define __pgprot(x) ((pgprot_t) { (x) }) 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* 828c2ecf20Sopenharmony_ci * We need a __pa and a __va routine for kernel space. 838c2ecf20Sopenharmony_ci * MIPS says they're only used during mem_init. 848c2ecf20Sopenharmony_ci * also, check if we need a PHYS_OFFSET. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) 878c2ecf20Sopenharmony_ci#define __va(x) ((void *)((unsigned long)(x) - PHYS_OFFSET + PAGE_OFFSET)) 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* The "page frame" descriptor is defined in linux/mm.h */ 908c2ecf20Sopenharmony_cistruct page; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/* Returns page frame descriptor for virtual address. */ 938c2ecf20Sopenharmony_ci#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(__pa(kaddr))) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* Default vm area behavior is non-executable. */ 968c2ecf20Sopenharmony_ci#define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_NON_EXEC 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define pfn_valid(pfn) ((pfn) < max_mapnr) 998c2ecf20Sopenharmony_ci#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* Need to not use a define for linesize; may move this to another file. */ 1028c2ecf20Sopenharmony_cistatic inline void clear_page(void *page) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci /* This can only be done on pages with L1 WB cache */ 1058c2ecf20Sopenharmony_ci asm volatile( 1068c2ecf20Sopenharmony_ci " loop0(1f,%1);\n" 1078c2ecf20Sopenharmony_ci "1: { dczeroa(%0);\n" 1088c2ecf20Sopenharmony_ci " %0 = add(%0,#32); }:endloop0\n" 1098c2ecf20Sopenharmony_ci : "+r" (page) 1108c2ecf20Sopenharmony_ci : "r" (PAGE_SIZE/32) 1118c2ecf20Sopenharmony_ci : "lc0", "sa0", "memory" 1128c2ecf20Sopenharmony_ci ); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* 1188c2ecf20Sopenharmony_ci * Under assumption that kernel always "sees" user map... 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_ci#define clear_user_page(page, vaddr, pg) clear_page(page) 1218c2ecf20Sopenharmony_ci#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/* 1248c2ecf20Sopenharmony_ci * page_to_phys - convert page to physical address 1258c2ecf20Sopenharmony_ci * @page - pointer to page entry in mem_map 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) 1308c2ecf20Sopenharmony_ci#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#define page_to_virt(page) __va(page_to_phys(page)) 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* 1358c2ecf20Sopenharmony_ci * For port to Hexagon Virtual Machine, MAYBE we check for attempts 1368c2ecf20Sopenharmony_ci * to reference reserved HVM space, but in any case, the VM will be 1378c2ecf20Sopenharmony_ci * protected. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci#define kern_addr_valid(addr) (1) 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci#include <asm/mem-layout.h> 1428c2ecf20Sopenharmony_ci#include <asm-generic/memory_model.h> 1438c2ecf20Sopenharmony_ci/* XXX Todo: implement assembly-optimized version of getorder. */ 1448c2ecf20Sopenharmony_ci#include <asm-generic/getorder.h> 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci#endif /* ifdef __ASSEMBLY__ */ 1478c2ecf20Sopenharmony_ci#endif /* ifdef __KERNEL__ */ 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#endif 150