kvmem.h

来自「fsmlabs的real time linux的内核」· C头文件 代码 · 共 144 行

H
144
字号
/*******************************//* Memory management functions *//*******************************/#ifndef _KVMEM_H#define _KVMEM_H#include <linux/version.h>#include <linux/slab.h>#include <linux/wrapper.h>#include <linux/pagemap.h>#include <asm/pgtable.h>#include <asm/io.h>#include "kernel_compat.h"#ifndef INIT_MM_EXPORTED  #define INIT_MM_EXPORTED (((LINUX_VERSION_CODE>=KERNEL_VERSION(2,2,14))&&\(LINUX_VERSION_CODE<KERNEL_VERSION(2,3,0)))||\(LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,40)))#endif#if INIT_MM_EXPORTED /* true since 2.2.14 and 2.3.40 *//* Use new implementation by David Miller. This is taken from bttv.c fromlinux-2.3.47pre6 and edited by me (Tomasz Motylewski) for brevityIt looks like we have 5 types of addresses: physical|phys|pa, bus, kva,uvirt, and kvirt. WOW !*//* [DaveM] I've recoded most of this so that: * 1) It's easier to tell what is happening * 2) It's more portable, especially for translating things *    out of vmalloc mapped areas in the kernel. * 3) Less unnecessary translations happen. * * The code used to assume that the kernel vmalloc mappings * existed in the page tables of every process, this is simply * not guarenteed.  We now use pgd_offset_k which is the * defined way to get at the kernel page tables. *//* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr){	unsigned long ret = 0UL;	pmd_t *pmd;	pte_t pte;	if (!pgd_none(*pgd)) {		pmd = pmd_offset(pgd, adr);		if (!pmd_none(*pmd)) {			pte = *(pte_offset(pmd, adr));			if(pte_present(pte))#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0))				ret  = (unsigned long) page_address(pte_page(pte));				ret |= (adr & (PAGE_SIZE - 1));/*				ret = ( page_address( pte_page(pte)) 					| (adr&(PAGE_SIZE-1))); */#else				ret =  pte_page(pte) | (adr&(PAGE_SIZE-1));#endif		}	}	return ret;}static inline unsigned long uvirt_to_phys(unsigned long adr){	return __pa(uvirt_to_kva(pgd_offset(current->mm, adr),  adr) );}static inline unsigned long uvirt_to_bus(unsigned long adr) {	return virt_to_bus((void *) uvirt_to_kva(		pgd_offset(current->mm, adr), adr) );}static inline unsigned long kvirt_to_bus(unsigned long adr){	adr = VMALLOC_VMADDR(adr);	return virt_to_bus((void *) uvirt_to_kva(pgd_offset_k(adr), adr) );}/* Here we want the physical address of the memory. * This is used when initializing the contents of the * area and marking the pages as reserved. */static inline unsigned long kvirt_to_pa(unsigned long adr){	adr = VMALLOC_VMADDR(adr);	return __pa(uvirt_to_kva(pgd_offset_k(adr), adr));}#define kvirt_to_phys  kvirt_to_pa#else  /* INIT_MM_EXPORTED *//* convert virtual memory address to physical address *//* (virt_to_phys only works for kmalloced kernel memory) */static inline unsigned long uvirt_to_phys(unsigned long adr){	pgd_t *pgd;	pmd_t *pmd;	pte_t *ptep, pte;  /* this just happens to work for kvirt, but see above remarks of DaveM */	pgd = pgd_offset(current->mm, adr);	if (pgd_none(*pgd))		return 0;	pmd = pmd_offset(pgd, adr);	if (pmd_none(*pmd))		return 0;	ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/);	pte = *ptep;	if(pte_present(pte))		return 		  virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1))));	return 0;}static inline unsigned long uvirt_to_bus(unsigned long adr) {	return virt_to_bus(phys_to_virt(uvirt_to_phys(adr)));}/* kvirt_to_phys pauperum */static inline unsigned long kvirt_to_phys(unsigned long adr) {	return uvirt_to_phys(VMALLOC_VMADDR(adr));}static inline unsigned long kvirt_to_bus(unsigned long adr) {	return uvirt_to_bus(VMALLOC_VMADDR(adr));}#endif /* INIT_MM_EXPORTED */extern void * rvmalloc(unsigned long size);extern void rvfree(void * mem, unsigned long size);extern int rvmmap(void *mem, unsigned memsize, struct vm_area_struct *vma);#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?