| /** |
| * @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; |
| } |