22 |
#include <rtmk/vm-param.h> |
#include <rtmk/vm-param.h> |
23 |
#include <rtmk/vm-types.h> |
#include <rtmk/vm-types.h> |
24 |
#include "queue.h" |
#include "queue.h" |
25 |
|
#include "thread-lock.h" |
26 |
|
|
27 |
struct vm_object; |
struct vm_object; |
28 |
|
|
29 |
#define MAX_VM_PHYSSEGS 32 |
#define MAX_VM_PHYSSEGS 32 |
30 |
|
|
31 |
/* Structure describes a segment of physical memory. */ |
/* Structure describes a segment of physical memory. */ |
|
|
|
32 |
struct vm_physseg |
struct vm_physseg |
33 |
{ |
{ |
34 |
vm_offset_t start; /* Start of physical memory. */ |
vm_offset_t start; /* Start of physical memory. */ |
39 |
|
|
40 |
/* Array of available physical segments, and counter of |
/* Array of available physical segments, and counter of |
41 |
available physical segments. */ |
available physical segments. */ |
|
|
|
42 |
extern struct vm_physseg vm_physmem [MAX_VM_PHYSSEGS]; |
extern struct vm_physseg vm_physmem [MAX_VM_PHYSSEGS]; |
43 |
extern unsigned int vm_physmem_count; |
extern unsigned int vm_physmem_count; |
44 |
|
|
50 |
. if TABLED_P is true, the page is inserted in the |
. if TABLED_P is true, the page is inserted in the |
51 |
hash lookup table. This means also that the page |
hash lookup table. This means also that the page |
52 |
belongs to a object (ignoring values for OBJECT). */ |
belongs to a object (ignoring values for OBJECT). */ |
|
|
|
53 |
struct vm_page |
struct vm_page |
54 |
{ |
{ |
55 |
struct queue_entry pageq; /* Link in object resident page list. */ |
struct queue_entry pageq; /* Link in object resident page list. */ |
61 |
struct vm_object *object; /* Object page belongs to. */ |
struct vm_object *object; /* Object page belongs to. */ |
62 |
vm_offset_t offset; /* Offset in object. */ |
vm_offset_t offset; /* Offset in object. */ |
63 |
|
|
64 |
|
vm_prot_t prot_lock; /* Lock for this page. */ |
65 |
|
vm_prot_t unlock_request; |
66 |
|
|
67 |
bool tabled_p : 1; /* If page is inserted in a object. */ |
bool tabled_p : 1; /* If page is inserted in a object. */ |
68 |
bool fictitious_p : 1; /* If page is a real page or not. */ |
bool fictitious_p : 1; /* If page is a real page or not. */ |
69 |
|
bool busy_p : 1; /* If page is busy. */ |
70 |
|
bool absent_p : 1; /* If page is absent. */ |
71 |
|
bool error_p : 1; /* If page has error. */ |
72 |
|
bool wanted_p : 1; /* Someone is waiting for page. */ |
73 |
|
bool free_p : 1; /* This page is free. */ |
74 |
bool active_p : 1; /* If page is active. */ |
bool active_p : 1; /* If page is active. */ |
75 |
|
bool inactive_p : 1; /* If page is inactive. */ |
76 |
|
bool dirty_p : 1; /* If page is dirty. */ |
77 |
|
bool reference_p : 1; /* If page is referenced. */ |
78 |
|
bool precious_p : 1; /* If page is precious. */ |
79 |
}; |
}; |
80 |
|
|
81 |
/* This is true if we have initialized the resident pages module. */ |
/* This is true if we have initialized the resident pages module. */ |
|
|
|
82 |
extern bool vm_resident_pages_init; |
extern bool vm_resident_pages_init; |
83 |
|
|
84 |
/* Initialize all resident pages. After this function is called |
/* Initialize all resident pages. After this function is called |
85 |
the system can not steal more memory. */ |
the system can not steal more memory. */ |
|
|
|
86 |
extern void vm_page_resident_pages_init (vm_offset_t *vstartp, |
extern void vm_page_resident_pages_init (vm_offset_t *vstartp, |
87 |
vm_offset_t *vendp); |
vm_offset_t *vendp); |
88 |
|
|
89 |
/* Initialize page stuff that is needed after the VM system is bootstrapped. */ |
/* Initialize page stuff that is needed after the VM system is bootstrapped. */ |
|
|
|
90 |
extern void vm_page_module_init (void); |
extern void vm_page_module_init (void); |
91 |
|
|
92 |
/* Allocate memory at bootstrap time. SIZE is rounded up to |
/* Allocate memory at bootstrap time. SIZE is rounded up to |
93 |
page size. Return pointer to memory block (what else?). */ |
page size. Return pointer to memory block (what else?). */ |
|
|
|
94 |
extern vm_offset_t vm_page_bootalloc (vm_size_t size); |
extern vm_offset_t vm_page_bootalloc (vm_size_t size); |
95 |
|
|
96 |
/* Load [START, END) physical memory into the VM system, |
/* Load [START, END) physical memory into the VM system, |
97 |
of which [AVAIL_START, AVAIL_END) is available. */ |
of which [AVAIL_START, AVAIL_END) is available. */ |
|
|
|
98 |
extern void vm_page_load (vm_offset_t start, vm_offset_t end, |
extern void vm_page_load (vm_offset_t start, vm_offset_t end, |
99 |
vm_offset_t avail_start, vm_offset_t avail_end); |
vm_offset_t avail_start, vm_offset_t avail_end); |
100 |
|
|
101 |
|
|
102 |
|
|
103 |
|
/* Page creation. */ |
104 |
|
|
105 |
/* Initialize a new page structure. Used when bootstraping the system |
/* Initialize a new page structure. Used when bootstraping the system |
106 |
and when memory have been released back to system after startup. |
and when memory have been released back to system after startup. |
107 |
PAGE is the VM page structure that we will initialize. PHYS_ADDR is |
PAGE is the VM page structure that we will initialize. PHYS_ADDR is |
108 |
the physical address of the page. */ |
the physical address of the page. */ |
109 |
|
extern void vm_page_init (struct vm_page *page, vm_offset_t phys_addr); |
110 |
|
|
111 |
extern void vm_page_init (struct vm_page *page, void *phys_addr); |
/* After the VM system is up, machine-dependent code |
112 |
|
may stumble across more physical memory. For example, |
113 |
|
memory that it was reserving for a frame buffer. |
114 |
|
vm_page_create turns this memory into available pages. */ |
115 |
|
extern void vm_page_create (vm_offset_t start, vm_offset_t end); |
116 |
|
|
117 |
|
/* Assign a physical address, PA, to PAGE. */ |
118 |
|
extern void vm_page_assign (struct vm_page *page, vm_offset_t pa); |
119 |
|
|
120 |
|
|
121 |
|
/* Page queue manipulation. */ |
122 |
|
|
123 |
/* Release PAGE. Put it on the free list. */ |
/* Allocate a new page from the free list. This may start the |
124 |
|
pageout daemon of the go below the used-pages threshold. */ |
125 |
|
extern struct vm_page *vm_page_allocate (void); |
126 |
|
|
127 |
|
/* Release PAGE. Put it on the free list. */ |
128 |
extern void vm_page_release (struct vm_page *page); |
extern void vm_page_release (struct vm_page *page); |
129 |
|
|
130 |
|
/* Returns the given page to the free list, disassociating |
131 |
|
it with any VM object. Object must be locked prior to entry. */ |
132 |
|
extern void vm_page_free (struct vm_page *mem); |
133 |
|
|
134 |
/* Grab a physical page. The physical page address is returned. */ |
/* Grab a physical page. The physical page address is returned. */ |
|
|
|
135 |
extern void *vm_page_grab_physical (void); |
extern void *vm_page_grab_physical (void); |
136 |
|
|
137 |
|
/* Put the specified page on the active list. */ |
138 |
|
extern void vm_page_activate (struct vm_page *m); |
139 |
|
|
140 |
|
/* Returns the given page to the inactive list, |
141 |
|
indicating that no physical maps have access. */ |
142 |
|
extern void vm_page_deactivate (struct vm_page *m); |
143 |
|
|
144 |
|
|
145 |
|
|
146 |
/* Locking protocol; the OBJECT and PAGE must be locked if nothing |
/* Locking protocol; the OBJECT and PAGE must be locked if nothing |
147 |
else is stated. */ |
else is stated. */ |
148 |
|
|
149 |
/* Insert PAGE into OBJECT at OFFSET. PAGE can not be inserted in |
/* Insert PAGE into OBJECT at OFFSET. PAGE can not be inserted in |
150 |
any other object. */ |
any other object. */ |
|
|
|
151 |
extern void vm_page_insert (struct vm_page *page, struct vm_object *object, |
extern void vm_page_insert (struct vm_page *page, struct vm_object *object, |
152 |
vm_offset_t offset); |
vm_offset_t offset); |
153 |
|
|
154 |
/* Lookup page in OBJECT at OFFSET. */ |
/* Lookup page in OBJECT at OFFSET. */ |
|
|
|
155 |
extern struct vm_page *vm_page_lookup (struct vm_object *object, |
extern struct vm_page *vm_page_lookup (struct vm_object *object, |
156 |
vm_offset_t offset); |
vm_offset_t offset); |
157 |
|
|
158 |
/* Remove PAGE from object that it has been tabled in. Remove it |
/* Remove PAGE from object that it has been tabled in. Remove it |
159 |
from the page hash table aswell. */ |
from the page hash table aswell. */ |
|
|
|
160 |
extern void vm_page_remove (struct vm_page *page); |
extern void vm_page_remove (struct vm_page *page); |
161 |
|
|
162 |
/* Exactly as vm_page_insert, except that we remove the page from |
/* Exactly as vm_page_insert, except that we remove the page from |
163 |
the previous object (if there is one). */ |
the previous object (if there is one). */ |
|
|
|
164 |
extern void vm_page_replace (struct vm_page *page, struct vm_object *object, |
extern void vm_page_replace (struct vm_page *page, struct vm_object *object, |
165 |
vm_offset_t offset); |
vm_offset_t offset); |
166 |
|
|
167 |
/* Allocate a new page from the free list. This may start the |
/* Allocate and return a memory cell associated with this |
168 |
pageout daemon of the go below the used-pages threshold. */ |
VM object/offset pair. Object must be locked. */ |
169 |
|
extern struct vm_page *vm_page_alloc (struct vm_object *object, |
170 |
|
vm_offset_t offset); |
171 |
|
|
172 |
extern struct vm_page *vm_page_allocate (void); |
|
173 |
|
/* Page data manipulation. */ |
174 |
|
|
175 |
/* Copy page SRC_PAGE to DST_PAGE. */ |
/* Copy page SRC_PAGE to DST_PAGE. */ |
|
|
|
176 |
extern void vm_page_copy (struct vm_page *dst_page, struct vm_page *src_page); |
extern void vm_page_copy (struct vm_page *dst_page, struct vm_page *src_page); |
177 |
|
|
178 |
/* Allocate a fictitious page. We returned page have no |
/* Fill PAGE will zerors. */ |
179 |
physical page assigned. On failure NULL is returned. */ |
extern void vm_page_zero_fill (struct vm_page *page); |
|
|
|
|
extern struct vm_page *vm_page_fictitious_allocate (void); |
|
180 |
|
|
181 |
/* Assign a physical address, PA, to PAGE. */ |
|
182 |
|
/* Fictitious pages. */ |
183 |
|
|
184 |
extern void vm_page_assign (struct vm_page *page, vm_offset_t pa); |
/* Remove a fictitious page from the free list. |
185 |
|
Returns NULL if there are no free pages. */ |
186 |
|
extern struct vm_page *vm_page_grab_fictitious (void); |
187 |
|
|
188 |
|
/* Release a fictitious page to the free list. */ |
189 |
|
extern void vm_page_release_fictitious (struct vm_page *m); |
190 |
|
|
191 |
|
/* Add more fictitious pages to the free list. |
192 |
|
Allowed to block. */ |
193 |
|
extern void vm_page_more_fictitious (void); |
194 |
|
|
195 |
|
/* Attempt to convert fictitious page M into a real page. |
196 |
|
Return true if we succeded, otherwise return false. */ |
197 |
|
extern int vm_page_convert (struct vm_page *m); |
198 |
|
|
199 |
|
/* Lock for the page queues. */ |
200 |
|
extern struct thread_lock vm_page_queue_lock; |
201 |
|
|
202 |
|
/* List of all free pages. This is protected by the global lock. |
203 |
|
We also maintain a counter of number of free pages on queue. */ |
204 |
|
extern struct queue_entry vm_page_free_queue; |
205 |
|
extern int vm_page_free_count; |
206 |
|
|
207 |
|
/* List if all active pages. This is protected by the global lock. |
208 |
|
We also maintain a counter of number of pages on queue. */ |
209 |
|
extern struct queue_entry vm_page_active_queue; |
210 |
|
extern int vm_page_active_count; |
211 |
|
|
212 |
|
/* List of all inactive pages. This is protected by the global lock. |
213 |
|
We also maintain a counter of number of pages on queue. */ |
214 |
|
extern struct queue_entry vm_page_inactive_queue; |
215 |
|
extern int vm_page_inactive_count; |
216 |
|
|
217 |
|
/* List of free fictitious pages. Protected by the global lock. |
218 |
|
We also maintain a counter of number of free pages on queue. */ |
219 |
|
extern struct queue_entry vm_page_fictitious_free_queue; |
220 |
|
extern int vm_page_fictitious_free_count; |
221 |
|
|
222 |
|
#define vm_page_lock_queues() thread_lock_write (& vm_page_queue_lock) |
223 |
|
#define vm_page_unlock_queues() thread_lock_unlock (& vm_page_queue_lock) |
224 |
|
|
225 |
|
/* Wait for PAGE to become not busy. */ |
226 |
|
#define VM_PAGE_WAIT(PAGE) \ |
227 |
|
do \ |
228 |
|
{ \ |
229 |
|
(PAGE)->wanted_p = 1; \ |
230 |
|
thread_sleep ((int) PAGE, 0, 0); \ |
231 |
|
} \ |
232 |
|
while (0) |
233 |
|
|
234 |
|
/* Signal that we're done with PAGE. It is no longer busy. */ |
235 |
|
#define VM_PAGE_WAKEUP_DONE(PAGE) \ |
236 |
|
do \ |
237 |
|
{ \ |
238 |
|
(PAGE)->busy_p = 0; \ |
239 |
|
if ((PAGE)->wanted_p) \ |
240 |
|
{ \ |
241 |
|
(PAGE)->wanted_p = 0; \ |
242 |
|
thread_wakeup ((int) PAGE); \ |
243 |
|
} \ |
244 |
|
} \ |
245 |
|
while (0) |
246 |
|
|
247 |
|
/* Wakeup all threads waiting for PAGE. */ |
248 |
|
#define VM_PAGE_WAKEUP(PAGE) \ |
249 |
|
do \ |
250 |
|
{ \ |
251 |
|
if ((PAGE)->wanted_p) \ |
252 |
|
{ \ |
253 |
|
(PAGE)->wanted_p = 0; \ |
254 |
|
thread_wakeup ((int) PAGE); \ |
255 |
|
} \ |
256 |
|
} \ |
257 |
|
while (0) |
258 |
|
|
259 |
|
/* Remove MEM from either list (active or inactive) it is on. |
260 |
|
This takes the page lock, no need for pre-locked queues. */ |
261 |
|
#define VM_PAGE_QUEUES_REMOVE(mem) \ |
262 |
|
do \ |
263 |
|
{ \ |
264 |
|
if (mem->active_p) \ |
265 |
|
{ \ |
266 |
|
vm_page_lock_queues (); \ |
267 |
|
queue_remove (& vm_page_active_queue, \ |
268 |
|
mem, struct vm_page *, listq); \ |
269 |
|
mem->active_p = 0; \ |
270 |
|
vm_page_unlock_queues (); \ |
271 |
|
} \ |
272 |
|
if (mem->inactive_p) \ |
273 |
|
{ \ |
274 |
|
vm_page_lock_queues (); \ |
275 |
|
queue_remove (& vm_page_inactive_queue, \ |
276 |
|
mem, struct vm_page *, listq); \ |
277 |
|
mem->inactive_p = 0; \ |
278 |
|
vm_page_unlock_queues (); \ |
279 |
|
} \ |
280 |
|
} \ |
281 |
|
while (0) |
282 |
|
|
283 |
#endif /* vm-page.h */ |
#endif /* vm-page.h */ |