op_util.c revision cc2ee177dbb3befca43e36cfc56778b006c3d050
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 */
23static 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 */
47unsigned 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
57void * 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
78void 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
96int 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