12f2f371fSMichal Simek /* 22f2f371fSMichal Simek * highmem.h: virtual kernel memory mappings for high memory 32f2f371fSMichal Simek * 42f2f371fSMichal Simek * Used in CONFIG_HIGHMEM systems for memory pages which 52f2f371fSMichal Simek * are not addressable by direct kernel virtual addresses. 62f2f371fSMichal Simek * 72f2f371fSMichal Simek * Copyright (C) 1999 Gerhard Wichert, Siemens AG 82f2f371fSMichal Simek * Gerhard.Wichert@pdb.siemens.de 92f2f371fSMichal Simek * 102f2f371fSMichal Simek * 112f2f371fSMichal Simek * Redesigned the x86 32-bit VM architecture to deal with 122f2f371fSMichal Simek * up to 16 Terabyte physical memory. With current x86 CPUs 132f2f371fSMichal Simek * we now support up to 64 Gigabytes physical RAM. 142f2f371fSMichal Simek * 152f2f371fSMichal Simek * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> 162f2f371fSMichal Simek */ 172f2f371fSMichal Simek #ifndef _ASM_HIGHMEM_H 182f2f371fSMichal Simek #define _ASM_HIGHMEM_H 192f2f371fSMichal Simek 202f2f371fSMichal Simek #ifdef __KERNEL__ 212f2f371fSMichal Simek 222f2f371fSMichal Simek #include <linux/init.h> 232f2f371fSMichal Simek #include <linux/interrupt.h> 242f2f371fSMichal Simek #include <linux/uaccess.h> 252f2f371fSMichal Simek #include <asm/fixmap.h> 262f2f371fSMichal Simek 272f2f371fSMichal Simek extern pte_t *kmap_pte; 282f2f371fSMichal Simek extern pgprot_t kmap_prot; 292f2f371fSMichal Simek extern pte_t *pkmap_page_table; 302f2f371fSMichal Simek 312f2f371fSMichal Simek /* 322f2f371fSMichal Simek * Right now we initialize only a single pte table. It can be extended 332f2f371fSMichal Simek * easily, subsequent pte tables have to be allocated in one physical 342f2f371fSMichal Simek * chunk of RAM. 352f2f371fSMichal Simek */ 362f2f371fSMichal Simek /* 372f2f371fSMichal Simek * We use one full pte table with 4K pages. And with 16K/64K/256K pages pte 382f2f371fSMichal Simek * table covers enough memory (32MB/512MB/2GB resp.), so that both FIXMAP 392f2f371fSMichal Simek * and PKMAP can be placed in a single pte table. We use 512 pages for PKMAP 402f2f371fSMichal Simek * in case of 16K/64K/256K page sizes. 412f2f371fSMichal Simek */ 422f2f371fSMichal Simek 432f2f371fSMichal Simek #define PKMAP_ORDER PTE_SHIFT 442f2f371fSMichal Simek #define LAST_PKMAP (1 << PKMAP_ORDER) 452f2f371fSMichal Simek 462f2f371fSMichal Simek #define PKMAP_BASE ((FIXADDR_START - PAGE_SIZE * (LAST_PKMAP + 1)) \ 472f2f371fSMichal Simek & PMD_MASK) 482f2f371fSMichal Simek 492f2f371fSMichal Simek #define LAST_PKMAP_MASK (LAST_PKMAP - 1) 502f2f371fSMichal Simek #define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT) 512f2f371fSMichal Simek #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) 522f2f371fSMichal Simek 532f2f371fSMichal Simek extern void *kmap_high(struct page *page); 542f2f371fSMichal Simek extern void kunmap_high(struct page *page); 552f2f371fSMichal Simek extern void *kmap_atomic_prot(struct page *page, pgprot_t prot); 562f2f371fSMichal Simek extern void __kunmap_atomic(void *kvaddr); 572f2f371fSMichal Simek 582f2f371fSMichal Simek static inline void *kmap(struct page *page) 592f2f371fSMichal Simek { 602f2f371fSMichal Simek might_sleep(); 612f2f371fSMichal Simek if (!PageHighMem(page)) 622f2f371fSMichal Simek return page_address(page); 632f2f371fSMichal Simek return kmap_high(page); 642f2f371fSMichal Simek } 652f2f371fSMichal Simek 662f2f371fSMichal Simek static inline void kunmap(struct page *page) 672f2f371fSMichal Simek { 682f2f371fSMichal Simek BUG_ON(in_interrupt()); 692f2f371fSMichal Simek if (!PageHighMem(page)) 702f2f371fSMichal Simek return; 712f2f371fSMichal Simek kunmap_high(page); 722f2f371fSMichal Simek } 732f2f371fSMichal Simek 742f2f371fSMichal Simek static inline void *__kmap_atomic(struct page *page) 752f2f371fSMichal Simek { 762f2f371fSMichal Simek return kmap_atomic_prot(page, kmap_prot); 772f2f371fSMichal Simek } 782f2f371fSMichal Simek 792f2f371fSMichal Simek static inline struct page *kmap_atomic_to_page(void *ptr) 802f2f371fSMichal Simek { 812f2f371fSMichal Simek unsigned long idx, vaddr = (unsigned long) ptr; 822f2f371fSMichal Simek pte_t *pte; 832f2f371fSMichal Simek 842f2f371fSMichal Simek if (vaddr < FIXADDR_START) 852f2f371fSMichal Simek return virt_to_page(ptr); 862f2f371fSMichal Simek 872f2f371fSMichal Simek idx = virt_to_fix(vaddr); 882f2f371fSMichal Simek pte = kmap_pte - (idx - FIX_KMAP_BEGIN); 892f2f371fSMichal Simek return pte_page(*pte); 902f2f371fSMichal Simek } 912f2f371fSMichal Simek 922f2f371fSMichal Simek #define flush_cache_kmaps() { flush_icache(); flush_dcache(); } 932f2f371fSMichal Simek 942f2f371fSMichal Simek #endif /* __KERNEL__ */ 952f2f371fSMichal Simek 962f2f371fSMichal Simek #endif /* _ASM_HIGHMEM_H */ 97