1#include <stdio.h>
2#include <stdlib.h>
3#include <signal.h>
4#include <sys/mman.h>
5#include "longjmp.h"
6#include "kern_constants.h"
7
8static jmp_buf buf;
9
10static void segfault(int sig)
11{
12 longjmp(buf, 1);
13}
14
15static int page_ok(unsigned long page)
16{
17 unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
18 unsigned long n = ~0UL;
19 void *mapped = NULL;
20 int ok = 0;
21
22
23
24
25
26
27
28
29
30 if (setjmp(buf) == 0)
31 n = *address;
32 else {
33 mapped = mmap(address, UM_KERN_PAGE_SIZE,
34 PROT_READ | PROT_WRITE,
35 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
36 if (mapped == MAP_FAILED)
37 return 0;
38 if (mapped != address)
39 goto out;
40 }
41
42
43
44
45
46
47 if (setjmp(buf) == 0) {
48 *address = n;
49 ok = 1;
50 goto out;
51 } else if (mprotect(address, UM_KERN_PAGE_SIZE,
52 PROT_READ | PROT_WRITE) != 0)
53 goto out;
54
55 if (setjmp(buf) == 0) {
56 *address = n;
57 ok = 1;
58 }
59
60 out:
61 if (mapped != NULL)
62 munmap(mapped, UM_KERN_PAGE_SIZE);
63 return ok;
64}
65
66unsigned long os_get_top_address(void)
67{
68 struct sigaction sa, old;
69 unsigned long bottom = 0;
70
71
72
73
74
75
76
77
78 unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
79 unsigned long test, original;
80
81 printf("Locating the bottom of the address space ... ");
82 fflush(stdout);
83
84
85
86
87
88 sa.sa_handler = segfault;
89 sigemptyset(&sa.sa_mask);
90 sa.sa_flags = SA_NODEFER;
91 if (sigaction(SIGSEGV, &sa, &old)) {
92 perror("os_get_top_address");
93 exit(1);
94 }
95
96
97
98
99 for (bottom = 0; bottom < top; bottom++) {
100 if (page_ok(bottom))
101 break;
102 }
103
104
105 if (bottom == top) {
106 fprintf(stderr, "Unable to determine bottom of address "
107 "space.\n");
108 exit(1);
109 }
110
111 printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
112 printf("Locating the top of the address space ... ");
113 fflush(stdout);
114
115 original = bottom;
116
117
118 if (page_ok(top))
119 goto out;
120
121 do {
122 test = bottom + (top - bottom) / 2;
123 if (page_ok(test))
124 bottom = test;
125 else
126 top = test;
127 } while (top - bottom > 1);
128
129out:
130
131 if (sigaction(SIGSEGV, &old, NULL)) {
132 perror("os_get_top_address");
133 exit(1);
134 }
135 top <<= UM_KERN_PAGE_SHIFT;
136 printf("0x%x\n", top);
137
138 return top;
139}
140