1 /**
2 * @file op_util.c
3 * Various utility functions
4 *
5 * @remark Copyright 2002 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author John Levon
9 * @author Philippe Elie
10 */
11
12 #include <linux/vmalloc.h>
13 #include <linux/wrapper.h>
14 #include <linux/pagemap.h>
15
16 #include "compat.h"
17
18 #include "op_util.h"
19
20 /* Given PGD from the address space's page table, return the kernel
21 * virtual mapping of the physical memory mapped at ADR.
22 */
uvirt_to_kva(pgd_t * pgd,unsigned long adr)23 static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr)
24 {
25 unsigned long ret = 0UL;
26 pmd_t * pmd;
27 pte_t * ptep, pte;
28
29 if (!pgd_none(*pgd)) {
30 pmd = pmd_offset(pgd, adr);
31 if (!pmd_none(*pmd)) {
32 ptep = pte_offset(pmd, adr);
33 pte = *ptep;
34 if (pte_present(pte)) {
35 ret = (unsigned long) pte_page_address(pte);
36 ret |= adr & (PAGE_SIZE - 1);
37 }
38 }
39 }
40 return ret;
41 }
42
43 /* Here we want the physical address of the memory.
44 * This is used when initializing the contents of the
45 * area and marking the pages as reserved.
46 */
kvirt_to_pa(unsigned long adr)47 unsigned long kvirt_to_pa(unsigned long adr)
48 {
49 unsigned long va, kva, ret;
50
51 va = VMALLOC_VMADDR(adr);
52 kva = uvirt_to_kva(pgd_offset_k(va), va);
53 ret = __pa(kva);
54 return ret;
55 }
56
rvmalloc(signed long size)57 void * rvmalloc(signed long size)
58 {
59 void * mem;
60 unsigned long adr, page;
61
62 mem = VMALLOC_32(size);
63 if (!mem)
64 return NULL;
65
66 memset(mem, 0, size);
67
68 adr=(unsigned long) mem;
69 while (size > 0) {
70 page = kvirt_to_pa(adr);
71 mem_map_reserve(virt_to_page((unsigned long)__va(page)));
72 adr += PAGE_SIZE;
73 size -= PAGE_SIZE;
74 }
75 return mem;
76 }
77
rvfree(void * mem,signed long size)78 void rvfree(void * mem, signed long size)
79 {
80 unsigned long adr, page;
81
82 if (!mem)
83 return;
84
85 adr=(unsigned long) mem;
86 while (size > 0) {
87 page = kvirt_to_pa(adr);
88 mem_map_unreserve(virt_to_page((unsigned long)__va(page)));
89
90 adr += PAGE_SIZE;
91 size -= PAGE_SIZE;
92 }
93 vfree(mem);
94 }
95
check_range(int val,int l,int h,char const * msg)96 int check_range(int val, int l, int h, char const * msg)
97 {
98 if (val < l || val > h) {
99 printk(msg, val, l, h);
100 return -EINVAL;
101 }
102 return 0;
103 }
104