-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.c
141 lines (126 loc) · 3.52 KB
/
utils.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <utils.h>
#include <types.h>
#include <mm_address.h>
int zeos_ticks;
void copy_data(void *start, void *dest, int size)
{
DWord *p = start, *q = dest;
Byte *p1, *q1;
while(size > 4) {
*q++ = *p++;
size -= 4;
}
p1=(Byte*)p;
q1=(Byte*)q;
while(size > 0) {
*q1++ = *p1++;
size --;
}
}
/* Copia de espacio de usuario a espacio de kernel, devuelve 0 si ok y -1 si error*/
int copy_from_user(void *start, void *dest, int size)
{
DWord *p = start, *q = dest;
Byte *p1, *q1;
while(size > 4) {
*q++ = *p++;
size -= 4;
}
p1=(Byte*)p;
q1=(Byte*)q;
while(size > 0) {
*q1++ = *p1++;
size --;
}
return 0;
}
/* Copia de espacio de kernel a espacio de usuario, devuelve 0 si ok y -1 si error*/
int copy_to_user(void *start, void *dest, int size)
{
DWord *p = start, *q = dest;
Byte *p1, *q1;
while(size > 4) {
*q++ = *p++;
size -= 4;
}
p1=(Byte*)p;
q1=(Byte*)q;
while(size > 0) {
*q1++ = *p1++;
size --;
}
return 0;
}
/* access_ok: Checks if a user space pointer is valid
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
* %VERIFY_WRITE is a superset of %VERIFY_READ: if it is safe
* to write to a block, it is always safe to read from it
* @addr: User space pointer to start of block to check
* @size: Size of block to check
* Returns true (nonzero) if the memory block may be valid,
* false (zero) if it is definitely invalid
*/
int access_ok(int type, const void * addr, unsigned long size)
{
unsigned long addr_ini, addr_fin;
addr_ini=(((unsigned long)addr)>>12);
addr_fin=((((unsigned long)addr)+size)>>12);
if (addr_fin < addr_ini) return 0; //This looks like an overflow ... deny access
switch(type)
{
case VERIFY_WRITE:
/* Should suppose no support for automodifyable code */
if ((addr_ini>=USER_FIRST_PAGE+NUM_PAG_CODE)&&
(addr_fin<=USER_FIRST_PAGE+NUM_PAG_CODE+NUM_PAG_DATA))
return 1;
default:
if ((addr_ini>=USER_FIRST_PAGE)&&
(addr_fin<=(USER_FIRST_PAGE+NUM_PAG_CODE+NUM_PAG_DATA)))
return 1;
}
return 0;
}
#define CYCLESPERTICK 109000
/*
* do_div() is NOT a C function. It wants to return
* two values (the quotient and the remainder), but
* since that doesn't work very well in C, what it
* does is:
*
* - modifies the 64-bit dividend _in_place_
* - returns the 32-bit remainder
*
* This ends up being the most efficient "calling
* convention" on x86.
*/
#define do_div(n,base) ({ \
unsigned long __upper, __low, __high, __mod, __base; \
__base = (base); \
asm("":"=a" (__low), "=d" (__high):"A" (n)); \
__upper = __high; \
if (__high) { \
__upper = __high % (__base); \
__high = __high / (__base); \
} \
asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \
asm("":"=A" (n):"a" (__low),"d" (__high)); \
__mod; \
})
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
unsigned long get_ticks(void) {
unsigned long eax;
unsigned long edx;
unsigned long long ticks;
rdtsc(eax,edx);
ticks=((unsigned long long) edx << 32) + eax;
do_div(ticks,CYCLESPERTICK);
return ticks;
}
void memset(void *a, int c, int size){
unsigned char * p;
for(p = a; size; size--){
*p = c;
p++;
}
}