Linux Audio

Check our new training course

Loading...
  1/* MN10300 Virtual kernel memory mappings for high memory
  2 *
  3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  4 * Written by David Howells (dhowells@redhat.com)
  5 * - Derived from include/asm-i386/highmem.h
  6 *
  7 * This program is free software; you can redistribute it and/or
  8 * modify it under the terms of the GNU General Public Licence
  9 * as published by the Free Software Foundation; either version
 10 * 2 of the Licence, or (at your option) any later version.
 11 */
 12#ifndef _ASM_HIGHMEM_H
 13#define _ASM_HIGHMEM_H
 14
 15#ifdef __KERNEL__
 16
 17#include <linux/init.h>
 18#include <linux/interrupt.h>
 19#include <linux/highmem.h>
 20#include <asm/kmap_types.h>
 21#include <asm/pgtable.h>
 22
 23/* undef for production */
 24#undef HIGHMEM_DEBUG
 25
 26/* declarations for highmem.c */
 27extern unsigned long highstart_pfn, highend_pfn;
 28
 29extern pte_t *kmap_pte;
 30extern pgprot_t kmap_prot;
 31extern pte_t *pkmap_page_table;
 32
 33extern void __init kmap_init(void);
 34
 35/*
 36 * Right now we initialize only a single pte table. It can be extended
 37 * easily, subsequent pte tables have to be allocated in one physical
 38 * chunk of RAM.
 39 */
 40#define PKMAP_BASE	0xfe000000UL
 41#define LAST_PKMAP	1024
 42#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
 43#define PKMAP_NR(virt)  ((virt - PKMAP_BASE) >> PAGE_SHIFT)
 44#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
 45
 46extern unsigned long kmap_high(struct page *page);
 47extern void kunmap_high(struct page *page);
 48
 49static inline unsigned long kmap(struct page *page)
 50{
 51	if (in_interrupt())
 52		BUG();
 53	if (page < highmem_start_page)
 54		return page_address(page);
 55	return kmap_high(page);
 56}
 57
 58static inline void kunmap(struct page *page)
 59{
 60	if (in_interrupt())
 61		BUG();
 62	if (page < highmem_start_page)
 63		return;
 64	kunmap_high(page);
 65}
 66
 67/*
 68 * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
 69 * gives a more generic (and caching) interface. But kmap_atomic can
 70 * be used in IRQ contexts, so in some (very limited) cases we need
 71 * it.
 72 */
 73static inline unsigned long kmap_atomic(struct page *page)
 74{
 75	unsigned long vaddr;
 76	int idx, type;
 77
 78	pagefault_disable();
 79	if (page < highmem_start_page)
 80		return page_address(page);
 81
 82	type = kmap_atomic_idx_push();
 83	idx = type + KM_TYPE_NR * smp_processor_id();
 84	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 85#if HIGHMEM_DEBUG
 86	if (!pte_none(*(kmap_pte - idx)))
 87		BUG();
 88#endif
 89	set_pte(kmap_pte - idx, mk_pte(page, kmap_prot));
 90	local_flush_tlb_one(vaddr);
 91
 92	return vaddr;
 93}
 94
 95static inline void __kunmap_atomic(unsigned long vaddr)
 96{
 97	int type;
 98
 99	if (vaddr < FIXADDR_START) { /* FIXME */
100		pagefault_enable();
101		return;
102	}
103
104	type = kmap_atomic_idx();
105
106#if HIGHMEM_DEBUG
107	{
108		unsigned int idx;
109		idx = type + KM_TYPE_NR * smp_processor_id();
110
111		if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx))
112			BUG();
113
114		/*
115		 * force other mappings to Oops if they'll try to access
116		 * this pte without first remap it
117		 */
118		pte_clear(kmap_pte - idx);
119		local_flush_tlb_one(vaddr);
120	}
121#endif
122
123	kmap_atomic_idx_pop();
124	pagefault_enable();
125}
126#endif /* __KERNEL__ */
127
128#endif /* _ASM_HIGHMEM_H */