/**
* @file op_util.c
* Various utility functions
*
* @remark Copyright 2002 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon
* @author Philippe Elie
*/
#include <linux/vmalloc.h>
#include <linux/wrapper.h>
#include <linux/pagemap.h>
#include "compat.h"
#include "op_util.h"
/* 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 * ptep, pte;
if (!pgd_none(*pgd)) {
pmd = pmd_offset(pgd, adr);
if (!pmd_none(*pmd)) {
ptep = pte_offset(pmd, adr);
pte = *ptep;
if (pte_present(pte)) {
ret = (unsigned long) pte_page_address(pte);
ret |= adr & (PAGE_SIZE - 1);
}
}
}
return ret;
}
/* 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.
*/
unsigned long kvirt_to_pa(unsigned long adr)
{
unsigned long va, kva, ret;
va = VMALLOC_VMADDR(adr);
kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = __pa(kva);
return ret;
}
void * rvmalloc(signed long size)
{
void * mem;
unsigned long adr, page;
mem = VMALLOC_32(size);
if (!mem)
return NULL;
memset(mem, 0, size);
adr=(unsigned long) mem;
while (size > 0) {
page = kvirt_to_pa(adr);
mem_map_reserve(virt_to_page((unsigned long)__va(page)));
adr += PAGE_SIZE;
size -= PAGE_SIZE;
}
return mem;
}
void rvfree(void * mem, signed long size)
{
unsigned long adr, page;
if (!mem)
return;
adr=(unsigned long) mem;
while (size > 0) {
page = kvirt_to_pa(adr);
mem_map_unreserve(virt_to_page((unsigned long)__va(page)));
adr += PAGE_SIZE;
size -= PAGE_SIZE;
}
vfree(mem);
}
int check_range(int val, int l, int h, char const * msg)
{
if (val < l || val > h) {
printk(msg, val, l, h);
return -EINVAL;
}
return 0;
}