-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathint.c
108 lines (94 loc) · 2.55 KB
/
int.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
#define MODULE
#define __KERNEL__
#define __KERNEL_SYSCALLS__
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sys.h>
#include <linux/unistd.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include "include/kdbg.h"
extern volatile int status;
static struct int_struct *interrupt = 0;
static char *get_idt()
{
char idt_descr[6] = { 0 };
__asm__ volatile ("sidt %0":"=m" (idt_descr));
return (char *) *(int *) &idt_descr[2];
}
static void int_install(int n, short sel, void (*new_int) ())
{
unsigned char *idt;
struct int_struct *cur_int;
if (interrupt) {
cur_int = interrupt;
while (cur_int->next) {
if (cur_int->num == n)
return;
cur_int = cur_int->next;
}
cur_int = cur_int->next =
(void *) kmalloc(sizeof(struct int_struct), GFP_ATOMIC);
} else
cur_int = interrupt =
(void *) kmalloc(sizeof(struct int_struct), GFP_ATOMIC);
cur_int->next = 0;
cur_int->num = n;
idt = get_idt();
cur_int->old_sel = (short) idt[8 * n + 2];
((char *) &cur_int->old_int)[0] = idt[8 * n + 0];
((char *) &cur_int->old_int)[1] = idt[8 * n + 1];
((char *) &cur_int->old_int)[2] = idt[8 * n + 6];
((char *) &cur_int->old_int)[3] = idt[8 * n + 7];
mem_writeb(&idt[8*n+2], ((char *) &sel)[0]);
mem_writeb(&idt[8*n+3], ((char *) &sel)[1]);
mem_writeb(&idt[8*n+0], ((char *) &new_int)[0]);
mem_writeb(&idt[8*n+1], ((char *) &new_int)[1]);
mem_writeb(&idt[8*n+6], ((char *) &new_int)[2]);
mem_writeb(&idt[8*n+7], ((char *) &new_int)[3]);
}
static void int_uninstall(int n)
{
struct int_struct *cur_int, *prev_int;
if (!interrupt)
return;
prev_int = 0;
cur_int = interrupt;
while (cur_int) {
if (cur_int->num == n) {
unsigned char *idt = get_idt();
mem_writeb(&idt[8*n+2], ((char *) &cur_int->old_sel)[0]);
mem_writeb(&idt[8*n+3], ((char *) &cur_int->old_sel)[1]);
mem_writeb(&idt[8*n+0], ((char *) &cur_int->old_int)[0]);
mem_writeb(&idt[8*n+1], ((char *) &cur_int->old_int)[1]);
mem_writeb(&idt[8*n+6], ((char *) &cur_int->old_int)[2]);
mem_writeb(&idt[8*n+7], ((char *) &cur_int->old_int)[3]);
kfree(cur_int);
if (cur_int == interrupt)
interrupt = 0;
else
prev_int->next = 0;
return;
}
prev_int = cur_int;
cur_int = cur_int->next;
}
return;
}
static asmlinkage struct int_struct *int_get(int n)
{
struct int_struct *cur_int = interrupt;
while (cur_int) {
if (cur_int->num == n)
return cur_int;
cur_int = cur_int->next;
}
}
static asmlinkage unsigned int int_get_old(int n)
{
struct int_struct *i = int_get(n);
if (!i)
return 0;
return i->old_int;
}