]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: olh@suse.de |
2 | Subject: vanilla sources from www.maconlinux.org | |
3 | Patch-mainline: never | |
4 | ||
5 | to avoid the km_ mess | |
6 | ||
7 | Never modify this patch! Create new patches for build fixes. | |
8 | ||
9 | --- | |
10 | drivers/macintosh/mol/_dev.c | 376 ++++++++++ | |
11 | drivers/macintosh/mol/_fault.c | 159 ++++ | |
12 | drivers/macintosh/mol/_hostirq.c | 116 +++ | |
13 | drivers/macintosh/mol/_kuname.c | 48 + | |
14 | drivers/macintosh/mol/_misc.c | 147 +++ | |
15 | drivers/macintosh/mol/_mmu.c | 41 + | |
16 | drivers/macintosh/mol/actions.c | 548 ++++++++++++++ | |
17 | drivers/macintosh/mol/asm-files/603.S | 218 +++++ | |
18 | drivers/macintosh/mol/asm-files/dec.S | 228 ++++++ | |
19 | drivers/macintosh/mol/asm-files/emuaccel.S | 188 +++++ | |
20 | drivers/macintosh/mol/asm-files/emulation.S | 714 +++++++++++++++++++ | |
21 | drivers/macintosh/mol/asm-files/entry.S | 433 +++++++++++ | |
22 | drivers/macintosh/mol/asm-files/iopage.S | 89 ++ | |
23 | drivers/macintosh/mol/asm-files/linux.S | 129 +++ | |
24 | drivers/macintosh/mol/asm-files/ptintercept.S | 303 ++++++++ | |
25 | drivers/macintosh/mol/asm-files/splitmode.S | 428 +++++++++++ | |
26 | drivers/macintosh/mol/asm-files/traps.S | 501 +++++++++++++ | |
27 | drivers/macintosh/mol/asm-files/vsid.S | 123 +++ | |
28 | drivers/macintosh/mol/asm_offsets.c | 161 ++++ | |
29 | drivers/macintosh/mol/context.c | 99 ++ | |
30 | drivers/macintosh/mol/emu.c | 228 ++++++ | |
31 | drivers/macintosh/mol/fault.c | 601 ++++++++++++++++ | |
32 | drivers/macintosh/mol/hash.c | 126 +++ | |
33 | drivers/macintosh/mol/include/actions.h | 177 ++++ | |
34 | drivers/macintosh/mol/include/alloc.h | 70 + | |
35 | drivers/macintosh/mol/include/archinclude.h | 77 ++ | |
36 | drivers/macintosh/mol/include/asm.m4 | 141 +++ | |
37 | drivers/macintosh/mol/include/asm_offsets.inc | 136 +++ | |
38 | drivers/macintosh/mol/include/asmdbg.h | 184 ++++ | |
39 | drivers/macintosh/mol/include/asmdefs.h | 397 ++++++++++ | |
40 | drivers/macintosh/mol/include/asmfuncs.h | 80 ++ | |
41 | drivers/macintosh/mol/include/atomic.h | 26 | |
42 | drivers/macintosh/mol/include/config.h | 90 ++ | |
43 | drivers/macintosh/mol/include/constants.h | 36 | |
44 | drivers/macintosh/mol/include/context.h | 62 + | |
45 | drivers/macintosh/mol/include/dbg.h | 31 | |
46 | drivers/macintosh/mol/include/debugger.h | 96 ++ | |
47 | drivers/macintosh/mol/include/emu.h | 29 | |
48 | drivers/macintosh/mol/include/emuaccel_sh.h | 41 + | |
49 | drivers/macintosh/mol/include/extralib.h | 70 + | |
50 | drivers/macintosh/mol/include/hash.h | 36 | |
51 | drivers/macintosh/mol/include/kernel_vars.h | 225 ++++++ | |
52 | drivers/macintosh/mol/include/locks.h | 39 + | |
53 | drivers/macintosh/mol/include/mac_registers.h | 168 ++++ | |
54 | drivers/macintosh/mol/include/map.h | 43 + | |
55 | drivers/macintosh/mol/include/misc.h | 105 ++ | |
56 | drivers/macintosh/mol/include/mmu.h | 102 ++ | |
57 | drivers/macintosh/mol/include/mmu_contexts.h | 55 + | |
58 | drivers/macintosh/mol/include/mmu_mappings.h | 48 + | |
59 | drivers/macintosh/mol/include/mmutypes.h | 76 ++ | |
60 | drivers/macintosh/mol/include/mol-ioctl.h | 121 +++ | |
61 | drivers/macintosh/mol/include/mol_config.h | 76 ++ | |
62 | drivers/macintosh/mol/include/molasm.h | 138 +++ | |
63 | drivers/macintosh/mol/include/molversion.h | 6 | |
64 | drivers/macintosh/mol/include/mtable.h | 71 + | |
65 | drivers/macintosh/mol/include/osi.h | 170 ++++ | |
66 | drivers/macintosh/mol/include/osi_calls.h | 475 ++++++++++++ | |
67 | drivers/macintosh/mol/include/performance.h | 71 + | |
68 | drivers/macintosh/mol/include/platform.h | 73 + | |
69 | drivers/macintosh/mol/include/processor.h | 409 +++++++++++ | |
70 | drivers/macintosh/mol/include/prom.h | 46 + | |
71 | drivers/macintosh/mol/include/rvec.h | 147 +++ | |
72 | drivers/macintosh/mol/include/skiplist.h | 87 ++ | |
73 | drivers/macintosh/mol/include/tlbie.h | 102 ++ | |
74 | drivers/macintosh/mol/include/uaccess.h | 36 | |
75 | drivers/macintosh/mol/include/vector.h | 189 +++++ | |
76 | drivers/macintosh/mol/include/version.h | 11 | |
77 | drivers/macintosh/mol/include/weaksym.h | 39 + | |
78 | drivers/macintosh/mol/init.c | 191 +++++ | |
79 | drivers/macintosh/mol/misc.c | 255 ++++++ | |
80 | drivers/macintosh/mol/mmu.c | 251 ++++++ | |
81 | drivers/macintosh/mol/mmu_fb.c | 186 +++++ | |
82 | drivers/macintosh/mol/mmu_io.c | 470 ++++++++++++ | |
83 | drivers/macintosh/mol/mmu_tracker.c | 128 +++ | |
84 | drivers/macintosh/mol/mtable.c | 960 ++++++++++++++++++++++++++ | |
85 | drivers/macintosh/mol/ptaccess.c | 153 ++++ | |
86 | drivers/macintosh/mol/sheep.c | 701 ++++++++++++++++++ | |
87 | drivers/macintosh/mol/skiplist.c | 222 ++++++ | |
88 | 78 files changed, 14428 insertions(+) | |
89 | ||
90 | --- /dev/null | |
91 | +++ b/drivers/macintosh/mol/_dev.c | |
92 | @@ -0,0 +1,376 @@ | |
93 | +/* | |
94 | + * Creation Date: <2003/08/20 17:31:44 samuel> | |
95 | + * Time-stamp: <2004/02/14 14:43:13 samuel> | |
96 | + * | |
97 | + * <dev.c> | |
98 | + * | |
99 | + * misc device | |
100 | + * | |
101 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
102 | + * | |
103 | + * This program is free software; you can redistribute it and/or | |
104 | + * modify it under the terms of the GNU General Public License | |
105 | + * version 2 | |
106 | + * | |
107 | + */ | |
108 | + | |
109 | +#include "archinclude.h" | |
110 | +#include <linux/module.h> | |
111 | +#include <linux/miscdevice.h> | |
112 | +#include <linux/spinlock.h> | |
113 | +#include <linux/init.h> | |
114 | +#include <linux/interrupt.h> | |
115 | +#include <linux/irq.h> | |
116 | +#include <linux/bitops.h> | |
117 | +#include <asm/prom.h> | |
118 | +#include <asm/machdep.h> | |
119 | +#include <asm/atomic.h> | |
120 | +#include "kernel_vars.h" | |
121 | +#include "mol-ioctl.h" | |
122 | +#include "version.h" | |
123 | +#include "mmu.h" | |
124 | +#include "misc.h" | |
125 | +#include "mtable.h" | |
126 | +#include "atomic.h" | |
127 | + | |
128 | +MODULE_AUTHOR("Samuel Rydh <samuel@ibrium.se>"); | |
129 | +MODULE_DESCRIPTION("Mac-on-Linux kernel module"); | |
130 | +MODULE_LICENSE("GPL"); | |
131 | + | |
132 | +static DECLARE_MUTEX( initmutex ); | |
133 | +static int opencnt; | |
134 | + | |
135 | + | |
136 | +/************************************************************************/ | |
137 | +/* misc */ | |
138 | +/************************************************************************/ | |
139 | + | |
140 | +#ifdef CONFIG_SMP | |
141 | +#define HAS_SMP 1 | |
142 | + | |
143 | +static void | |
144 | +dummy_ipi( void *dummy ) | |
145 | +{ | |
146 | + /* we don't need to _do_ anything, the exception itself is sufficient */ | |
147 | +} | |
148 | +static inline void | |
149 | +send_ipi( void ) | |
150 | +{ | |
151 | + smp_call_function( dummy_ipi, NULL, 1, 0 ); | |
152 | +} | |
153 | +#else /* CONFIG_SMP */ | |
154 | + | |
155 | +#define HAS_SMP 0 | |
156 | +#define send_ipi() do {} while(0) | |
157 | + | |
158 | +#endif /* CONFIG_SMP */ | |
159 | + | |
160 | + | |
161 | +static int | |
162 | +find_physical_rom( int *base, int *size ) | |
163 | +{ | |
164 | +#ifndef CONFIG_AMIGAONE | |
165 | + struct device_node *dn; | |
166 | + int len, *p; | |
167 | + int by_type = 0; | |
168 | + | |
169 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) | |
170 | + if( !(dn=find_devices("boot-rom")) && !(dn=find_type_devices("rom")) ) | |
171 | + return 0; | |
172 | +#else | |
173 | + if (! (dn = of_find_node_by_name(NULL, "boot-rom"))) { | |
174 | + by_type = 1; | |
175 | + if (! (dn = of_find_node_by_type(NULL, "rom"))) | |
176 | + return 0; | |
177 | + } | |
178 | +#endif /* < Linux 2.6.21 */ | |
179 | + do { | |
180 | + if( !(p=(int*)get_property(dn, "reg", &len)) || len != sizeof(int[2]) ) { | |
181 | + of_node_put(dn); | |
182 | + return 0; | |
183 | + } | |
184 | + if( (unsigned int)(0xfff00100 - p[0]) < (unsigned int)p[1] ) { | |
185 | + *base = p[0]; | |
186 | + *size = p[1]; | |
187 | + of_node_put(dn); | |
188 | + return 1; | |
189 | + } | |
190 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) | |
191 | + dn = dn->next; | |
192 | +#else | |
193 | + dn = by_type ? of_find_node_by_type(dn, "rom") : | |
194 | + of_find_node_by_name(dn, "boot-rom"); | |
195 | +#endif /* < Linux 2.6.21 */ | |
196 | + } while( dn ); | |
197 | +#endif /* CONFIG_AMIGA_ONE */ | |
198 | + return 0; | |
199 | +} | |
200 | + | |
201 | +static int | |
202 | +get_info( mol_kmod_info_t *user_retinfo, int size ) | |
203 | +{ | |
204 | + mol_kmod_info_t info; | |
205 | + | |
206 | + memset( &info, 0, sizeof(info) ); | |
207 | + asm volatile("mfpvr %0" : "=r" (info.pvr) : ); | |
208 | + info.version = MOL_VERSION; | |
209 | + find_physical_rom( &info.rombase, &info.romsize ); | |
210 | + info.tb_freq = HZ * tb_ticks_per_jiffy; | |
211 | + info.smp_kernel = HAS_SMP; | |
212 | + | |
213 | + if( (uint)size > sizeof(info) ) | |
214 | + size = sizeof(info); | |
215 | + | |
216 | + if( copy_to_user(user_retinfo, &info, size) ) | |
217 | + return -EFAULT; | |
218 | + return 0; | |
219 | +} | |
220 | + | |
221 | + | |
222 | +void | |
223 | +prevent_mod_unload( void ) | |
224 | +{ | |
225 | +#ifndef LINUX_26 | |
226 | + MOD_INC_USE_COUNT; | |
227 | +#else | |
228 | + __module_get( THIS_MODULE ); | |
229 | +#endif | |
230 | +} | |
231 | + | |
232 | +int | |
233 | +get_irqs( kernel_vars_t *kv, irq_bitfield_t *irq_info_p ) | |
234 | +{ | |
235 | + irq_bitfield_t irq_mask; | |
236 | + int i; | |
237 | + | |
238 | + /* copy the interrupt mask from userspace */ | |
239 | + if (copy_from_user(&irq_mask, irq_info_p, sizeof(irq_mask))) | |
240 | + return -EFAULT; | |
241 | + | |
242 | + /* see which of the mapped interrupts need to be enabled */ | |
243 | + for (i = 0; i < NR_HOST_IRQS; i++) { | |
244 | + if (check_bit_mol(i, (char *) kv->mregs.mapped_irqs.irqs) | |
245 | + && check_bit_mol(i, (char *) irq_mask.irqs) | |
246 | + && check_bit_mol(i, (char *) kv->mregs.active_irqs.irqs)) { | |
247 | + if (test_and_clear_bit(i, kv->mregs.active_irqs.irqs)) | |
248 | + atomic_dec_mol((mol_atomic_t *) &(kv->mregs.hostirq_active_cnt)); | |
249 | + enable_irq(i); | |
250 | + } | |
251 | + } | |
252 | + | |
253 | + /* if one of the enabled interrupts was pending, it should have fired | |
254 | + * now, updating active_irqs */ | |
255 | + if (copy_to_user(irq_info_p, &(kv->mregs.active_irqs), sizeof(kv->mregs.active_irqs))) | |
256 | + return -EFAULT; | |
257 | + | |
258 | + return 0; | |
259 | +} | |
260 | + | |
261 | +/************************************************************************/ | |
262 | +/* ioctl */ | |
263 | +/************************************************************************/ | |
264 | + | |
265 | +static int | |
266 | +debugger_op( kernel_vars_t *kv, dbg_op_params_t *upb ) | |
267 | +{ | |
268 | + dbg_op_params_t pb; | |
269 | + int ret; | |
270 | + | |
271 | + if( copy_from_user(&pb, upb, sizeof(pb)) ) | |
272 | + return -EFAULT; | |
273 | + | |
274 | + switch( pb.operation ) { | |
275 | + case DBG_OP_GET_PHYS_PAGE: | |
276 | + ret = dbg_get_linux_page( pb.ea, &pb.ret.page ); | |
277 | + break; | |
278 | + default: | |
279 | + ret = do_debugger_op( kv, &pb ); | |
280 | + break; | |
281 | + } | |
282 | + | |
283 | + if( copy_to_user(upb, &pb, sizeof(pb)) ) | |
284 | + return -EFAULT; | |
285 | + return ret; | |
286 | +} | |
287 | + | |
288 | +static int | |
289 | +arch_handle_ioctl( kernel_vars_t *kv, int cmd, int p1, int p2, int p3 ) | |
290 | +{ | |
291 | + char *rompage; | |
292 | + int ret = -EFAULT; | |
293 | + | |
294 | + switch( cmd ) { | |
295 | + case MOL_IOCTL_GET_IRQS: | |
296 | + return get_irqs( kv, (irq_bitfield_t *) p1 ); | |
297 | + | |
298 | + case MOL_IOCTL_GET_DIRTY_FBLINES: /* short *retbuf, int size -- npairs */ | |
299 | + if( compat_verify_area(VERIFY_WRITE, (short*)p1, p2) ) | |
300 | + break; | |
301 | + ret = get_dirty_fb_lines( kv, (short*)p1, p2 ); | |
302 | + break; | |
303 | + | |
304 | + case MOL_IOCTL_DEBUGGER_OP: | |
305 | + ret = debugger_op( kv, (dbg_op_params_t*)p1 ); | |
306 | + break; | |
307 | + | |
308 | + case MOL_IOCTL_GRAB_IRQ: | |
309 | + ret = grab_host_irq(kv, p1); | |
310 | + break; | |
311 | + | |
312 | + case MOL_IOCTL_RELEASE_IRQ: | |
313 | + ret = release_host_irq(kv, p1); | |
314 | + break; | |
315 | + | |
316 | + case MOL_IOCTL_COPY_LAST_ROMPAGE: /* p1 = dest */ | |
317 | + ret = -ENODEV; | |
318 | + if( (rompage=ioremap(0xfffff000, 0x1000)) ) { | |
319 | + ret = copy_to_user( (char*)p1, rompage, 0x1000 ); | |
320 | + iounmap( rompage ); | |
321 | + } | |
322 | + break; | |
323 | + | |
324 | + case MOL_IOCTL_SET_RAM: /* void ( char *lvbase, size_t size ) */ | |
325 | + if( compat_verify_area(VERIFY_WRITE, (char*)p1, p2) ) | |
326 | + break; | |
327 | + ret = 0; | |
328 | + kv->mmu.userspace_ram_base = p1; | |
329 | + kv->mmu.ram_size = p2; | |
330 | + mtable_tune_alloc_limit( kv, p2/(1024 * 1024) ); | |
331 | + break; | |
332 | + | |
333 | + case MOL_IOCTL_GET_MREGS_PHYS: | |
334 | + ret = virt_to_phys( &kv->mregs ); | |
335 | + break; | |
336 | + | |
337 | + default: | |
338 | + ret = handle_ioctl( kv, cmd, p1, p2, p3 ); | |
339 | + break; | |
340 | + } | |
341 | + return ret; | |
342 | +} | |
343 | + | |
344 | + | |
345 | +/************************************************************************/ | |
346 | +/* device interface */ | |
347 | +/************************************************************************/ | |
348 | + | |
349 | +static int | |
350 | +mol_open( struct inode *inode, struct file *file ) | |
351 | +{ | |
352 | + int ret=0; | |
353 | + | |
354 | + if( !(file->f_mode & FMODE_READ) ) | |
355 | + return -EPERM; | |
356 | + | |
357 | + down( &initmutex ); | |
358 | + if( !opencnt++ ) { | |
359 | + if( common_init() ) { | |
360 | + ret = -ENOMEM; | |
361 | + opencnt = 0; | |
362 | + } | |
363 | + } | |
364 | + up( &initmutex ); | |
365 | + | |
366 | + file->private_data = NULL; | |
367 | + return ret; | |
368 | +} | |
369 | + | |
370 | +static int | |
371 | +mol_release( struct inode *inode, struct file *file ) | |
372 | +{ | |
373 | + kernel_vars_t *kv = (kernel_vars_t*)file->private_data; | |
374 | + | |
375 | + down( &initmutex ); | |
376 | + if( kv ) | |
377 | + destroy_session( kv->session_index ); | |
378 | + | |
379 | + if( !--opencnt ) | |
380 | + common_cleanup(); | |
381 | + up( &initmutex ); | |
382 | + return 0; | |
383 | +} | |
384 | + | |
385 | +static int | |
386 | +mol_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg ) | |
387 | +{ | |
388 | + mol_ioctl_pb_t pb; | |
389 | + kernel_vars_t *kv; | |
390 | + int ret; | |
391 | + uint session; | |
392 | + | |
393 | + /* fast path */ | |
394 | + if( cmd == MOL_IOCTL_SMP_SEND_IPI ) { | |
395 | + send_ipi(); | |
396 | + return 0; | |
397 | + } | |
398 | + | |
399 | + if( copy_from_user(&pb, (void*)arg, sizeof(pb)) ) | |
400 | + return -EFAULT; | |
401 | + | |
402 | + switch( cmd ) { | |
403 | + case MOL_IOCTL_GET_INFO: | |
404 | + return get_info( (mol_kmod_info_t*)pb.arg1, pb.arg2 ); | |
405 | + | |
406 | + case MOL_IOCTL_CREATE_SESSION: | |
407 | + if( !(file->f_mode & FMODE_WRITE) || !capable(CAP_SYS_ADMIN) ) | |
408 | + return -EPERM; | |
409 | + ret = -EINVAL; | |
410 | + down( &initmutex ); | |
411 | + if( (uint)pb.arg1 < MAX_NUM_SESSIONS && !file->private_data ) { | |
412 | + if( !(ret=initialize_session(pb.arg1)) ) { | |
413 | + kv = g_sesstab->kvars[pb.arg1]; | |
414 | + init_MUTEX( &kv->ioctl_sem ); | |
415 | + file->private_data = kv; | |
416 | + } | |
417 | + } | |
418 | + up( &initmutex ); | |
419 | + return ret; | |
420 | + | |
421 | + case MOL_IOCTL_DBG_COPY_KVARS: | |
422 | + session = pb.arg1; | |
423 | + ret = -EINVAL; | |
424 | + down( &initmutex ); | |
425 | + if( session < MAX_NUM_SESSIONS && (kv=g_sesstab->kvars[session]) ) | |
426 | + ret = copy_to_user( (char*)pb.arg2, kv, sizeof(*kv) ); | |
427 | + up( &initmutex ); | |
428 | + return ret; | |
429 | + } | |
430 | + | |
431 | + if( !(kv=(kernel_vars_t*)file->private_data) ) | |
432 | + return -EINVAL; | |
433 | + | |
434 | + down( &kv->ioctl_sem ); | |
435 | + ret = arch_handle_ioctl( kv, cmd, pb.arg1, pb.arg2, pb.arg3 ); | |
436 | + up( &kv->ioctl_sem ); | |
437 | + | |
438 | + return ret; | |
439 | +} | |
440 | + | |
441 | +static struct file_operations mol_device_fops = { | |
442 | + .owner = THIS_MODULE, | |
443 | + .open = mol_open, | |
444 | + .release = mol_release, | |
445 | + .ioctl = mol_ioctl, | |
446 | +// .poll = mol_poll, | |
447 | +// .mmap: = mol_mmap, | |
448 | +}; | |
449 | + | |
450 | +static struct miscdevice mol_device = { | |
451 | + MISC_DYNAMIC_MINOR, "mol", &mol_device_fops | |
452 | +}; | |
453 | + | |
454 | +static int __init | |
455 | +dev_register( void ) | |
456 | +{ | |
457 | + printk("MOL %s kernel module loaded\n", MOL_RELEASE ); | |
458 | + return misc_register( &mol_device ); | |
459 | +} | |
460 | + | |
461 | +static void __exit | |
462 | +dev_unregister( void ) | |
463 | +{ | |
464 | + misc_deregister( &mol_device ); | |
465 | +} | |
466 | + | |
467 | +module_init( dev_register ); | |
468 | +module_exit( dev_unregister ); | |
469 | --- /dev/null | |
470 | +++ b/drivers/macintosh/mol/_fault.c | |
471 | @@ -0,0 +1,159 @@ | |
472 | +/* | |
473 | + * Creation Date: <2002/06/08 21:01:54 samuel> | |
474 | + * Time-stamp: <2004/02/19 11:54:33 samuel> | |
475 | + * | |
476 | + * <fault.c> | |
477 | + * | |
478 | + * Linux part | |
479 | + * | |
480 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
481 | + * | |
482 | + * This program is free software; you can redistribute it and/or | |
483 | + * modify it under the terms of the GNU General Public License | |
484 | + * as published by the Free Software Foundation | |
485 | + * | |
486 | + */ | |
487 | + | |
488 | +#include "archinclude.h" | |
489 | +#include "alloc.h" | |
490 | +#include "kernel_vars.h" | |
491 | +#include "mmu.h" | |
492 | +#include "mmu_contexts.h" | |
493 | +#include "asmfuncs.h" | |
494 | +#include "emu.h" | |
495 | +#include "misc.h" | |
496 | +#include "rvec.h" | |
497 | +#include "performance.h" | |
498 | +#include "mol-ioctl.h" | |
499 | +#include "mtable.h" | |
500 | + | |
501 | +#ifdef CONFIG_HIGHPTE | |
502 | +#error "MOL is currently incompatible with CONFIG_HIGHPTE" | |
503 | +#endif | |
504 | + | |
505 | +static inline ulong | |
506 | +fix_pte( ulong *p, ulong set, ulong flags ) | |
507 | +{ | |
508 | + unsigned long ret, tmp; | |
509 | + | |
510 | + __asm__ __volatile__("\n" | |
511 | + "1: lwarx %0,0,%3 \n" | |
512 | + " andc. %1,%5,%0 \n" | |
513 | + " addi %1,0,0 \n" | |
514 | + " bne- 2f \n" | |
515 | + " or %1,%0,%4 \n" | |
516 | + " stwcx. %1,0,%3 \n" | |
517 | + " bne- 1b \n" | |
518 | + "2: \n" | |
519 | + : "=&r" (tmp), "=&r" (ret), "=m" (*p) | |
520 | + : "r" (p), "r" (set), "r" (flags), "m" (*p) | |
521 | + : "cc" ); | |
522 | + return ret; | |
523 | +} | |
524 | + | |
525 | +/* | |
526 | + * Get physical page corresponding to linux virtual address. Invokes linux page | |
527 | + * fault handler if the page is missing. This function never fails since we | |
528 | + * know there is a valid mapping... | |
529 | + */ | |
530 | +#define PAGE_BITS_WRITE (_PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HASHPTE ) | |
531 | +#define PAGE_BITS_READ (_PAGE_ACCESSED | _PAGE_HASHPTE ) | |
532 | + | |
533 | +ulong | |
534 | +get_phys_page( kernel_vars_t *kv, ulong va, int request_rw ) | |
535 | +{ | |
536 | + char *lvptr = (char*)va; | |
537 | + ulong lpte, uptr, *ptr; | |
538 | + ulong flags; | |
539 | + struct mm_struct *mm; | |
540 | + struct vm_area_struct *vma; | |
541 | + | |
542 | + /* pte bits that must be set */ | |
543 | + flags = request_rw ? (_PAGE_USER | _PAGE_RW | _PAGE_PRESENT) | |
544 | + : (_PAGE_USER | _PAGE_PRESENT); | |
545 | + | |
546 | + uptr = ((ulong*)current->thread.pgdir)[va>>22]; /* top 10 bits */ | |
547 | + ptr = (ulong*)(uptr & ~0xfff); | |
548 | + if( !ptr ) | |
549 | + goto no_page; | |
550 | +#ifdef LINUX_26 | |
551 | + ptr = phys_to_virt( (int)ptr ); | |
552 | +#endif | |
553 | + ptr = ptr + ((va>>12) & 0x3ff); /* next 10 bits */ | |
554 | + | |
555 | + /* this allows us to keep track of this page until we have | |
556 | + * added a full mtable entry for it. The reservation is lost if | |
557 | + * a TLB invalidation occurs. | |
558 | + */ | |
559 | + make_lvptr_reservation( kv, lvptr ); | |
560 | + | |
561 | + /* we atomically set _PAGE_HASHPTE after checking PAGE_PRESENT and PAGE_RW. | |
562 | + * We are then guaranteed to be notified about a TLB invalidation through the | |
563 | + * flush_hash_page hook. | |
564 | + */ | |
565 | + lpte = fix_pte( ptr, (request_rw? PAGE_BITS_WRITE : PAGE_BITS_READ), flags ); | |
566 | + | |
567 | + /* permissions violation */ | |
568 | + if( !lpte ) | |
569 | + goto no_page; | |
570 | + | |
571 | + return lpte & ~0xfff; | |
572 | + | |
573 | +no_page: | |
574 | + BUMP( page_missing ); | |
575 | + | |
576 | + /* no mac page found... */ | |
577 | + mm = current->mm; | |
578 | + down_read( &mm->mmap_sem ); | |
579 | + | |
580 | + if( !(vma=find_vma(mm,va)) || vma->vm_start > va ) | |
581 | + goto bad_area; | |
582 | + if( !(vma->vm_flags & (request_rw ? VM_WRITE : (VM_READ | VM_EXEC))) ) | |
583 | + goto bad_area; | |
584 | + | |
585 | + handle_mm_fault( mm, vma, va, request_rw ); | |
586 | + | |
587 | + up_read( &mm->mmap_sem ); | |
588 | + return get_phys_page(kv, va, request_rw); | |
589 | + | |
590 | +bad_area: | |
591 | + up_read( &mm->mmap_sem ); | |
592 | + printk("get_phys_page: BAD AREA, lvptr = %08lx\n", va ); | |
593 | + force_sig(SIGSEGV, current); | |
594 | + return 0; | |
595 | +} | |
596 | + | |
597 | + | |
598 | +/************************************************************************/ | |
599 | +/* Debugger functions */ | |
600 | +/************************************************************************/ | |
601 | + | |
602 | +int | |
603 | +dbg_get_linux_page( ulong va, dbg_page_info_t *r ) | |
604 | +{ | |
605 | + ulong val, uptr, *ptr; | |
606 | + | |
607 | + uptr = ((ulong*)current->thread.pgdir)[va>>22]; /* top 10 bits */ | |
608 | + ptr = (ulong*)(uptr & ~0xfff); | |
609 | + if( !ptr ) | |
610 | + return 1; | |
611 | +#ifdef LINUX_26 | |
612 | + ptr = phys_to_virt( (int)ptr ); | |
613 | +#endif | |
614 | + val = ptr[ (va>>12)&0x3ff ]; /* next 10 bits */ | |
615 | + | |
616 | + r->phys = val & ~0xfff; | |
617 | + r->mflags = | |
618 | + DBG_TRANSL_PAGE_FLAG( val, _PAGE_PRESENT ) | |
619 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_USER ) | |
620 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_GUARDED ) | |
621 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_COHERENT ) | |
622 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_NO_CACHE ) | |
623 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_WRITETHRU ) | |
624 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_DIRTY ) | |
625 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_ACCESSED ) | |
626 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_RW ) | |
627 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_HASHPTE ) | |
628 | + | DBG_TRANSL_PAGE_FLAG( val, _PAGE_EXEC ); | |
629 | + return 0; | |
630 | +} | |
631 | --- /dev/null | |
632 | +++ b/drivers/macintosh/mol/_hostirq.c | |
633 | @@ -0,0 +1,116 @@ | |
634 | +/* | |
635 | + * <hostirq.c> | |
636 | + * | |
637 | + * host IRQ handling (for pciproxied devices) | |
638 | + * | |
639 | + * Copyright (C) 2005 Mattias Nissler <mattias.nissler@gmx.de> | |
640 | + * | |
641 | + * This program is free software; you can redistribute it and/or | |
642 | + * modify it under the terms of the GNU General Public License | |
643 | + * version 2 | |
644 | + * | |
645 | + */ | |
646 | +#include <linux/version.h> | |
647 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) | |
648 | +#include <linux/threads.h> | |
649 | +#include <linux/spinlock.h> | |
650 | +#endif | |
651 | +#include <linux/interrupt.h> | |
652 | +#include <linux/irq.h> | |
653 | +#include <linux/sched.h> | |
654 | +#include <linux/bitops.h> | |
655 | +#include <asm/atomic.h> | |
656 | + | |
657 | +#include "archinclude.h" | |
658 | +#include "kernel_vars.h" | |
659 | +#include "misc.h" | |
660 | +#include "atomic.h" | |
661 | + | |
662 | +irqreturn_t | |
663 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) | |
664 | +hostirq_handler(int irq, void *pkv) | |
665 | +#else | |
666 | +hostirq_handler(int irq, void *pkv, struct pt_regs *regs) | |
667 | +#endif | |
668 | +{ | |
669 | + siginfo_t si; | |
670 | + kernel_vars_t *kv = (kernel_vars_t *) pkv; | |
671 | + | |
672 | + /* disable the irq */ | |
673 | + disable_irq_nosync(irq); | |
674 | + /* have the interrupt handled */ | |
675 | + if (!test_and_set_bit(irq, kv->mregs.active_irqs.irqs)) | |
676 | + atomic_inc_mol((mol_atomic_t *) &(kv->mregs.hostirq_active_cnt)); | |
677 | + kv->mregs.hostirq_update = 1; | |
678 | + kv->mregs.interrupt = 1; | |
679 | + /* signal the main thread (it might be DOZEing) */ | |
680 | + if (kv->main_thread != NULL) { | |
681 | + memset(&si, 0, sizeof(si)); | |
682 | + si.si_signo = SIGHUP; | |
683 | + si.si_code = irq; | |
684 | + send_sig_info(SIGHUP, &si, kv->main_thread); | |
685 | + } | |
686 | + | |
687 | + return IRQ_HANDLED; | |
688 | +} | |
689 | + | |
690 | +static char *molirqdescstring = "MOL irq mapping"; | |
691 | + | |
692 | +int | |
693 | +grab_host_irq(kernel_vars_t *kv, int irq) | |
694 | +{ | |
695 | + int ret; | |
696 | + | |
697 | + /* sanity check */ | |
698 | + if (irq < 0 || irq >= NR_HOST_IRQS | |
699 | + || check_bit_mol(irq, (char *) kv->mregs.mapped_irqs.irqs)) | |
700 | + return 0; | |
701 | + | |
702 | + /* request the irq */ | |
703 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) | |
704 | + ret = request_irq(irq, hostirq_handler, IRQF_DISABLED | IRQF_SHARED, molirqdescstring, kv); | |
705 | +#else | |
706 | + ret = request_irq(irq, hostirq_handler, SA_INTERRUPT | SA_SHIRQ, molirqdescstring, kv); | |
707 | +#endif | |
708 | + if (!ret) { | |
709 | +// printk(KERN_INFO "mapped irq line %d\n", irq); | |
710 | + set_bit_mol(irq, (char *) kv->mregs.mapped_irqs.irqs); | |
711 | + } | |
712 | + | |
713 | + return ret; | |
714 | +} | |
715 | + | |
716 | +int | |
717 | +release_host_irq(kernel_vars_t *kv, int irq) | |
718 | +{ | |
719 | + /* sanity check */ | |
720 | + if (irq < 0 || irq >= NR_HOST_IRQS | |
721 | + || !check_bit_mol(irq, (char *) kv->mregs.mapped_irqs.irqs)) | |
722 | + return 0; | |
723 | + | |
724 | + clear_bit_mol(irq, (char *) kv->mregs.mapped_irqs.irqs); | |
725 | + disable_irq(irq); | |
726 | + free_irq(irq, kv); | |
727 | + | |
728 | + return 1; | |
729 | +} | |
730 | + | |
731 | +void | |
732 | +init_host_irqs(kernel_vars_t *kv) | |
733 | +{ | |
734 | + memset(&(kv->mregs.mapped_irqs), 0, sizeof(kv->mregs.mapped_irqs)); | |
735 | + kv->main_thread = current; | |
736 | + kv->mregs.hostirq_update = 0; | |
737 | +} | |
738 | + | |
739 | +void | |
740 | +cleanup_host_irqs(kernel_vars_t *kv) | |
741 | +{ | |
742 | + int n; | |
743 | + | |
744 | + for (n = 0; n < NR_HOST_IRQS; n++) { | |
745 | + if (check_bit_mol(n, (char *) kv->mregs.mapped_irqs.irqs)) | |
746 | + release_host_irq(kv, n); | |
747 | + } | |
748 | +} | |
749 | + | |
750 | --- /dev/null | |
751 | +++ b/drivers/macintosh/mol/_kuname.c | |
752 | @@ -0,0 +1,48 @@ | |
753 | +/* | |
754 | + * Creation Date: <2001/08/15 01:11:01 samuel> | |
755 | + * Time-stamp: <2003/10/24 10:22:00 samuel> | |
756 | + * | |
757 | + * <kuname.c> | |
758 | + * | |
759 | + * Extract from the kernel source | |
760 | + * | |
761 | + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) | |
762 | + * | |
763 | + * This program is free software; you can redistribute it and/or | |
764 | + * modify it under the terms of the GNU General Public License | |
765 | + * as published by the Free Software Foundation | |
766 | + * | |
767 | + */ | |
768 | + | |
769 | +#include <linux/version.h> | |
770 | + | |
771 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) | |
772 | +#include <linux/utsrelease.h> | |
773 | +#endif | |
774 | + | |
775 | +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) | |
776 | +#include <linux/config.h> | |
777 | +#else | |
778 | +#include <linux/autoconf.h> | |
779 | +#endif | |
780 | + | |
781 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) | |
782 | + | |
783 | +#ifdef CONFIG_SMP | |
784 | +#define SMP_STRING "-smp" | |
785 | +#else | |
786 | +#define SMP_STRING "" | |
787 | +#endif | |
788 | + | |
789 | +#ifndef CONFIG_ALTIVEC | |
790 | +#define ALTIVEC_STRING "-noav" | |
791 | +#else | |
792 | +#define ALTIVEC_STRING "" | |
793 | +#endif | |
794 | + | |
795 | +#else | |
796 | +#define SMP_STRING "" | |
797 | +#define ALTIVEC_STRING "" | |
798 | +#endif | |
799 | + | |
800 | +char *cross_compiling_magic = "-MAGIC-" UTS_RELEASE SMP_STRING ALTIVEC_STRING ; | |
801 | --- /dev/null | |
802 | +++ b/drivers/macintosh/mol/_misc.c | |
803 | @@ -0,0 +1,147 @@ | |
804 | +/* | |
805 | + * Creation Date: <97/05/26 02:10:43 samuel> | |
806 | + * Time-stamp: <2004/03/13 14:14:20 samuel> | |
807 | + * | |
808 | + * <misc.c> | |
809 | + * | |
810 | + * Kernel interface | |
811 | + * | |
812 | + * Copyright (C) 1997-2004 Samuel Rydh (samuel@ibrium.se) | |
813 | + * | |
814 | + * This program is free software; you can redistribute it and/or | |
815 | + * modify it under the terms of the GNU General Public License | |
816 | + * as published by the Free Software Foundation | |
817 | + * | |
818 | + */ | |
819 | + | |
820 | +#include "archinclude.h" | |
821 | +#include <linux/vmalloc.h> | |
822 | +#include <linux/sched.h> | |
823 | +#include <asm/uaccess.h> | |
824 | +#include <asm/prom.h> | |
825 | +#include "kernel_vars.h" | |
826 | +#include "misc.h" | |
827 | +#include "performance.h" | |
828 | +#include "map.h" | |
829 | + | |
830 | +#define MMU kv->mmu | |
831 | + | |
832 | +kernel_vars_t * | |
833 | +alloc_kvar_pages( void ) | |
834 | +{ | |
835 | + kernel_vars_t *kv; | |
836 | + int i, order; | |
837 | + char *ptr; | |
838 | + | |
839 | + for( i=1, order=0; i<NUM_KVARS_PAGES; i=i<<1, order++ ) | |
840 | + ; | |
841 | + if( !(kv=(kernel_vars_t*)__get_free_pages(GFP_KERNEL, order)) ) | |
842 | + return NULL; | |
843 | + | |
844 | + /* To be able to export the kernel variables to user space, we | |
845 | + * must set the PG_reserved bit. This is due to a check | |
846 | + * in remap_pte_range() in kernel/memory.c (is this bug or a feature?). | |
847 | + */ | |
848 | + for( ptr=(char*)kv, i=0; i<NUM_KVARS_PAGES; i++, ptr+=0x1000 ) | |
849 | + SetPageReserved( virt_to_page(ptr) ); | |
850 | + | |
851 | + return kv; | |
852 | +} | |
853 | + | |
854 | +void | |
855 | +free_kvar_pages( kernel_vars_t *kv ) | |
856 | +{ | |
857 | + char *ptr = (char*)kv; | |
858 | + int i, order; | |
859 | + | |
860 | + for( i=0; i<NUM_KVARS_PAGES; i++, ptr+=0x1000 ) | |
861 | + ClearPageReserved( virt_to_page(ptr) ); | |
862 | + | |
863 | + for( i=1, order=0; i<NUM_KVARS_PAGES; i=i<<1, order++ ) | |
864 | + ; | |
865 | + free_pages( (ulong)kv, order ); | |
866 | +} | |
867 | + | |
868 | + | |
869 | +/************************************************************************/ | |
870 | +/* hash access */ | |
871 | +/************************************************************************/ | |
872 | + | |
873 | +ulong * | |
874 | +map_emulated_hash( kernel_vars_t *kv, ulong mbase, ulong size ) | |
875 | +{ | |
876 | + return (ulong*)(MMU.userspace_ram_base + mbase); | |
877 | +} | |
878 | + | |
879 | +void | |
880 | +unmap_emulated_hash( kernel_vars_t *kv ) | |
881 | +{ | |
882 | + /* nothing */ | |
883 | +} | |
884 | + | |
885 | +/************************************************************************/ | |
886 | +/* kernel lowmem asm <-> kernel C-code switching */ | |
887 | +/************************************************************************/ | |
888 | + | |
889 | +typedef int (*kernelfunc_t)( kernel_vars_t *, ulong, ulong, ulong ); | |
890 | +typedef void (*trampoline_t)( struct pt_regs *regs ); | |
891 | +static trampoline_t old_trampoline; | |
892 | + | |
893 | +static void | |
894 | +mol_trampoline_vector( struct pt_regs *r ) | |
895 | +{ | |
896 | + kernel_vars_t *kv = (kernel_vars_t*)r->gpr[8]; | |
897 | + | |
898 | +#ifndef LINUX_26 | |
899 | + /* the 0x2f00 trap does not enable MSR_EE */ | |
900 | + local_irq_enable(); | |
901 | +#endif | |
902 | + TICK_CNTR_PUSH( kv ); | |
903 | + r->gpr[3] = (*(kernelfunc_t)r->gpr[3])( kv, r->gpr[4], r->gpr[5], r->gpr[6] ); | |
904 | + TICK_CNTR_POP( kv, in_kernel ); | |
905 | +} | |
906 | + | |
907 | +static trampoline_t | |
908 | +set_trampoline( trampoline_t tramp ) | |
909 | +{ | |
910 | + trampoline_t old; | |
911 | +#ifdef LINUX_26 | |
912 | + extern trampoline_t mol_trampoline; | |
913 | + old = mol_trampoline; | |
914 | + mol_trampoline = tramp; | |
915 | +#else | |
916 | + /* we steal the unused 0x2f00 exception vector... */ | |
917 | + u32 *p = (u32*)(KERNELBASE + 0x2f00); | |
918 | + static trampoline_t *tptr = NULL; | |
919 | + int i; | |
920 | + | |
921 | + /* look for bl xxxx ; .long vector; .long exception_return */ | |
922 | + for( i=0; !tptr && i<0x100/4; i++ ) { | |
923 | + if( (p[i] & ~0xffff) != 0x48000000 ) | |
924 | + continue; | |
925 | + if( (p[i+1] & ~0x7fffff) != KERNELBASE || (p[i+2] & ~0x0fffff) != KERNELBASE ) | |
926 | + continue; | |
927 | + tptr = (trampoline_t*)&p[i+1]; | |
928 | + } | |
929 | + if( !tptr ) { | |
930 | + printk("MOL trampoline not found!\n"); | |
931 | + return NULL; | |
932 | + } | |
933 | + old = *tptr; | |
934 | + *tptr = tramp; | |
935 | +#endif | |
936 | + return old; | |
937 | +} | |
938 | + | |
939 | +int | |
940 | +arch_common_init( void ) | |
941 | +{ | |
942 | + old_trampoline = set_trampoline( mol_trampoline_vector ); | |
943 | + return !old_trampoline; | |
944 | +} | |
945 | + | |
946 | +void | |
947 | +arch_common_cleanup( void ) | |
948 | +{ | |
949 | + set_trampoline( old_trampoline ); | |
950 | +} | |
951 | --- /dev/null | |
952 | +++ b/drivers/macintosh/mol/_mmu.c | |
953 | @@ -0,0 +1,41 @@ | |
954 | +/* | |
955 | + * Creation Date: <2002/07/13 13:58:00 samuel> | |
956 | + * Time-stamp: <2004/02/14 12:47:09 samuel> | |
957 | + * | |
958 | + * <mmu.c> | |
959 | + * | |
960 | + * | |
961 | + * | |
962 | + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) | |
963 | + * | |
964 | + * This program is free software; you can redistribute it and/or | |
965 | + * modify it under the terms of the GNU General Public License | |
966 | + * as published by the Free Software Foundation | |
967 | + * | |
968 | + */ | |
969 | + | |
970 | +#include "archinclude.h" | |
971 | +#include "alloc.h" | |
972 | +#include "kernel_vars.h" | |
973 | +#include "mmu.h" | |
974 | +#include "asmfuncs.h" | |
975 | + | |
976 | +#define MMU (kv->mmu) | |
977 | + | |
978 | +#ifdef CONFIG_SMP | |
979 | +void (*xx_tlbie_lowmem)( void ); | |
980 | +void (*xx_store_pte_lowmem)( void ); | |
981 | +#else | |
982 | +void (*xx_store_pte_lowmem)( ulong *slot, int pte0, int pte1 ); | |
983 | +#endif | |
984 | + | |
985 | +int | |
986 | +arch_mmu_init( kernel_vars_t *kv ) | |
987 | +{ | |
988 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) | |
989 | + MMU.emulator_context = current->mm->context.id; | |
990 | +#else | |
991 | + MMU.emulator_context = current->mm->context; | |
992 | +#endif | |
993 | + return 0; | |
994 | +} | |
995 | --- /dev/null | |
996 | +++ b/drivers/macintosh/mol/actions.c | |
997 | @@ -0,0 +1,548 @@ | |
998 | +/* | |
999 | + * Creation Date: <2001/04/07 17:33:52 samuel> | |
1000 | + * Time-stamp: <2004/03/13 14:17:40 samuel> | |
1001 | + * | |
1002 | + * <actions.c> | |
1003 | + * | |
1004 | + * Handle assambly actions (relocations, exception vector | |
1005 | + * hooking, lowmem relocations and other stuff) | |
1006 | + * | |
1007 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
1008 | + * | |
1009 | + * This program is free software; you can redistribute it and/or | |
1010 | + * modify it under the terms of the GNU General Public License | |
1011 | + * as published by the Free Software Foundation | |
1012 | + * | |
1013 | + */ | |
1014 | + | |
1015 | +#include "archinclude.h" | |
1016 | +#include "alloc.h" | |
1017 | +#include "kernel_vars.h" | |
1018 | +#include "misc.h" | |
1019 | +#include "asmfuncs.h" | |
1020 | +#include "actions.h" | |
1021 | +#include "map.h" | |
1022 | + | |
1023 | + | |
1024 | +/* globals */ | |
1025 | +int reloc_virt_offs; | |
1026 | + | |
1027 | +static char *code_base; | |
1028 | +static uint code_size; | |
1029 | + | |
1030 | +/* some opcodes */ | |
1031 | +#define OPCODE_ADDIS( dreg, sreg, hi_val ) ((15<<26) | ((dreg)<<21) | ((sreg)<<16) | (hi_val)) | |
1032 | +#define OPCODE_LIS( dreg, hi_val ) OPCODE_ADDIS( dreg, 0, hi_val ) | |
1033 | +#define OPCODE_ORI( dreg, sreg, val ) ((24<<26) | ((dreg)<<16) | ((sreg)<<21) | (val)) | |
1034 | +#define OPCODE_MTSPRG2( sreg ) (0x7c1243a6 + ((sreg)<<21)) | |
1035 | + | |
1036 | + | |
1037 | +/************************************************************************/ | |
1038 | +/* lowmem allocations (allocates within the first 32 MB of RAM) */ | |
1039 | +/************************************************************************/ | |
1040 | + | |
1041 | +/* The low-level assembly code need to be located in memory which is | |
1042 | + * physically continuous. The kernel exception vector are patched | |
1043 | + * through pseudo symbols (action symbols). | |
1044 | + */ | |
1045 | + | |
1046 | +#define MAX_NUM_CLEANUP_HANDLERS 32 | |
1047 | + | |
1048 | +typedef struct { | |
1049 | + char *lowmem_addr; | |
1050 | + int alloc_size; | |
1051 | + int alloc_method; | |
1052 | + | |
1053 | + ulong *inst_addr; /* these fields are used */ | |
1054 | + ulong opcode; /* be the hook code */ | |
1055 | +} cleanup_entry_t; | |
1056 | + | |
1057 | +static int num_cleanup_entries; | |
1058 | +static cleanup_entry_t cleanup_table[ MAX_NUM_CLEANUP_HANDLERS ]; | |
1059 | +static ulong lowmem_phys_cursor; | |
1060 | + | |
1061 | +/* Memory mapping of exception vectors */ | |
1062 | +static ulong lowmem_phys_base; | |
1063 | +static char *lowmem_virt_base; | |
1064 | +static void *lowmem_mapping; | |
1065 | + | |
1066 | + | |
1067 | +static inline ulong * | |
1068 | +lowmem_phys_to_virt( ulong paddr ) { | |
1069 | + return (ulong*)(lowmem_virt_base + (paddr - lowmem_phys_base)); | |
1070 | +} | |
1071 | + | |
1072 | +static inline ulong | |
1073 | +lowmem_tophys( void *vaddr ) { | |
1074 | + return lowmem_phys_base + ((ulong)vaddr - (ulong)lowmem_virt_base); | |
1075 | +} | |
1076 | + | |
1077 | + | |
1078 | +static void | |
1079 | +lowmem_initialize( void ) | |
1080 | +{ | |
1081 | + if( num_cleanup_entries ) { | |
1082 | + printk("Internal error in lowmem_initialize\n"); | |
1083 | + return; | |
1084 | + } | |
1085 | + lowmem_phys_cursor = 0x100; | |
1086 | + | |
1087 | + /* In Darwin, the mapping will fail if we put lowmem_phys_base to zero */ | |
1088 | + lowmem_phys_base = 0x100; | |
1089 | + lowmem_mapping = map_phys_range( lowmem_phys_base, 0x4000, &lowmem_virt_base ); | |
1090 | +} | |
1091 | + | |
1092 | +static char * | |
1093 | +lowmem_alloc( int size, cleanup_entry_t **ret_ce ) | |
1094 | +{ | |
1095 | + ulong *pstart; | |
1096 | + cleanup_entry_t ce; | |
1097 | + int found=0; | |
1098 | + | |
1099 | + memset( &ce, 0, sizeof(ce) ); | |
1100 | + if( ret_ce ) | |
1101 | + *ret_ce = NULL; | |
1102 | + | |
1103 | + if( num_cleanup_entries >= MAX_NUM_CLEANUP_HANDLERS ) { | |
1104 | + printk("MOL: Need more cleanup slots!\n"); | |
1105 | + return NULL; | |
1106 | + } | |
1107 | + | |
1108 | + /* Find big enough empty piece of memory */ | |
1109 | + if( size < 0x10 ) | |
1110 | + size = 0x10; | |
1111 | + | |
1112 | + pstart = lowmem_phys_to_virt(lowmem_phys_cursor); | |
1113 | + pstart = (ulong*)(((ulong)pstart + 0xf) & ~0xf); | |
1114 | + for( ; lowmem_phys_cursor < 0x3000; lowmem_phys_cursor+=4 ) { | |
1115 | + ulong *p = lowmem_phys_to_virt(lowmem_phys_cursor); | |
1116 | + if( ((int)p - (int)pstart) >= size ) { | |
1117 | + found = 1; | |
1118 | + break; | |
1119 | + } | |
1120 | + if( *p ) { | |
1121 | + pstart = (ulong*)(((ulong)p + sizeof(ulong) + 0xf) & ~0xf); | |
1122 | + continue; | |
1123 | + } | |
1124 | + } | |
1125 | + if( !found ) { | |
1126 | + printk("MOL: Did not find an empty piece of lowmem memory!\n"); | |
1127 | + return NULL; | |
1128 | + } | |
1129 | + /* printk("lowmem alloc: %08lX\n", pstart ); */ | |
1130 | + | |
1131 | + ce.lowmem_addr = (char*)pstart; | |
1132 | + ce.alloc_method = 0; | |
1133 | + ce.alloc_size = size; | |
1134 | + /* printk("lowmem-alloc SPACE %X bytes at %08lX\n", size, (ulong)pstart ); */ | |
1135 | + | |
1136 | + cleanup_table[num_cleanup_entries] = ce; | |
1137 | + if( ret_ce ) | |
1138 | + *ret_ce = &cleanup_table[num_cleanup_entries]; | |
1139 | + num_cleanup_entries++; | |
1140 | + | |
1141 | + return ce.lowmem_addr; | |
1142 | +} | |
1143 | + | |
1144 | +static void | |
1145 | +lowmem_free_all( void ) | |
1146 | +{ | |
1147 | + cleanup_entry_t *ce = &cleanup_table[0]; | |
1148 | + int i; | |
1149 | + | |
1150 | + for(i=0; i<num_cleanup_entries; i++, ce++ ) | |
1151 | + memset( ce->lowmem_addr, 0, ce->alloc_size ); | |
1152 | + | |
1153 | + num_cleanup_entries = 0; | |
1154 | + | |
1155 | + if( lowmem_mapping ) { | |
1156 | + unmap_phys_range( lowmem_mapping ); | |
1157 | + lowmem_mapping = NULL; | |
1158 | + } | |
1159 | +} | |
1160 | + | |
1161 | + | |
1162 | +/************************************************************************/ | |
1163 | +/* helper functions */ | |
1164 | +/************************************************************************/ | |
1165 | + | |
1166 | +static action_pb_t * | |
1167 | +find_action( int action, int index ) | |
1168 | +{ | |
1169 | + extern int r__actions_offs_section[], r__actions_offs_section_end[]; | |
1170 | + extern char *r__actions_section[]; | |
1171 | + const int n = ((int)r__actions_offs_section_end - (int)r__actions_offs_section)/sizeof(int); | |
1172 | + int i, *op = r__actions_offs_section; | |
1173 | + | |
1174 | + for( i=0; i<n; i++ ) { | |
1175 | + action_pb_t *p = (action_pb_t*)((char*)r__actions_section + op[i]); | |
1176 | + | |
1177 | + if( p->action != action || index-- ) | |
1178 | + continue; | |
1179 | + return p; | |
1180 | + } | |
1181 | + return NULL; | |
1182 | +} | |
1183 | + | |
1184 | +static int | |
1185 | +relocate_inst( ulong *opc_ptr, ulong from, ulong to ) | |
1186 | +{ | |
1187 | + ulong opcode = *opc_ptr; | |
1188 | + int offs=-1; | |
1189 | + | |
1190 | + /* XXX: UNTESTED if target instruction is a branch */ | |
1191 | + | |
1192 | + /* Since we use this on the _first_ instruction of the | |
1193 | + * exception vector, it can't touch LR/CR. Thus, we | |
1194 | + * only look for unconditional, relative branches. | |
1195 | + */ | |
1196 | + | |
1197 | + /* relativ branch b */ | |
1198 | + if( (opcode & 0xfc000003) == (18<<26) ){ | |
1199 | + offs = (opcode & 0x03fffffc); | |
1200 | + /* sign extend */ | |
1201 | + if( offs & 0x03000000 ) | |
1202 | + offs |= ~0x03ffffff; | |
1203 | + } | |
1204 | + /* unconditional, relativ bc branch (b 0100 001z1zz ...) */ | |
1205 | + if( (opcode & 0xfe800003) == 0x42800000 ){ | |
1206 | + offs = (opcode & 0xfffc); | |
1207 | + if( offs & 0x8000 ) | |
1208 | + offs |= ~0xffff; | |
1209 | + } | |
1210 | + /* construct the absolute branch */ | |
1211 | + if( offs != -1 ) { | |
1212 | + int dest = from + offs; | |
1213 | + if( dest < 0 || dest > 33554431 ) { | |
1214 | + printk("relocation of branch at %08lX to %08lX failed\n", from, to); | |
1215 | + return 1; | |
1216 | + } | |
1217 | + /* absolute branch */ | |
1218 | + *opc_ptr = ((18<<26) + 2) | dest; | |
1219 | + } | |
1220 | + return 0; | |
1221 | +} | |
1222 | + | |
1223 | + | |
1224 | +/************************************************************************/ | |
1225 | +/* actions */ | |
1226 | +/************************************************************************/ | |
1227 | + | |
1228 | +typedef int (*action_func_t)( int action, ulong *target, const int *pb ); | |
1229 | + | |
1230 | +static int | |
1231 | +action_li_phys( int action, ulong *target, const int *pb ) | |
1232 | +{ | |
1233 | + int r = pb[0] & 0x1f; | |
1234 | + ulong addr = pb[1] + tophys_mol( code_base ); | |
1235 | + | |
1236 | + /* target[0] = addis r,0,addr@h ; target[1] = ori r,r,addr@l */ | |
1237 | + target[0] = (15 << 26) | (r << 21) | (addr >> 16); | |
1238 | + target[1] = (24 << 26) | (r << 21) | (r << 16) | (addr & 0xffff); | |
1239 | + | |
1240 | + /* printk("ACTION_LI_PHYS %d %08lX\n", dreg, addr ); */ | |
1241 | + return 0; | |
1242 | +} | |
1243 | + | |
1244 | +static int | |
1245 | +action_lwz_physaddr_r( int action, ulong *target, const int *pb ) | |
1246 | +{ | |
1247 | + ulong addr = pb[1] + tophys_mol( code_base ); | |
1248 | + int dr = (pb[0] >> 5) & 0x1f; | |
1249 | + int r = pb[0] & 0x1f; | |
1250 | + short low = (addr & 0xffff); | |
1251 | + | |
1252 | + /* target[0] = addis dr,r,addr@h ; target[1] = lwz dr,addr@l(dr) */ | |
1253 | + target[0] = (15 << 26) | (dr << 21) | (r << 16) | ((addr - low) >> 16); | |
1254 | + target[1] = (32 << 26) | (dr << 21) | (dr << 16) | ((int)low & 0xffff); | |
1255 | + | |
1256 | + /* printk("ACTION_LI_PHYS %d %08lX\n", dreg, addr ); */ | |
1257 | + return 0; | |
1258 | +} | |
1259 | + | |
1260 | +static int | |
1261 | +action_specvar( int action, ulong *target, const int *pb ) | |
1262 | +{ | |
1263 | + int r = pb[0] & 0x1f; | |
1264 | + ulong addr; | |
1265 | + | |
1266 | + switch( pb[1] ) { | |
1267 | + case SPECVAR_SESSION_TABLE: | |
1268 | + addr = tophys_mol(g_sesstab); | |
1269 | + break; | |
1270 | + default: | |
1271 | + return 1; | |
1272 | + } | |
1273 | + | |
1274 | + if( action == ACTION_LIS_SPECVAR_H ) { | |
1275 | + /* target[0] = addis r,0,addr@h */ | |
1276 | + target[0] = OPCODE_LIS( r, (addr >> 16) & 0xffff ); | |
1277 | + return 0; | |
1278 | + } | |
1279 | + if( action == ACTION_ORI_SPECVAR_L ) { | |
1280 | + /* target[0] = ori rD,rS,addr@l */ | |
1281 | + int rD = (pb[0] >> 5) & 0x1f; | |
1282 | + target[0] = OPCODE_ORI( rD, r, (addr & 0xffff)); | |
1283 | + return 0; | |
1284 | + } | |
1285 | + return 1; | |
1286 | +} | |
1287 | + | |
1288 | + | |
1289 | +/* Note: this only works under linux */ | |
1290 | +static int | |
1291 | +action_tophysvirt( int action, ulong *target, const int *pb ) | |
1292 | +{ | |
1293 | + ulong addr = tophys_mol(0); | |
1294 | + int dr = (pb[0] >> 5) & 0x1f; | |
1295 | + int sr = pb[0] & 0x1f; | |
1296 | + | |
1297 | + if( action == ACTION_TOVIRT ) | |
1298 | + addr = -addr; | |
1299 | + | |
1300 | + /* target[0] = addis dr,sr,(tophys(0))@hi */ | |
1301 | + target[0] = OPCODE_ADDIS( dr, sr, (addr >> 16) & 0xffff ); | |
1302 | + return 0; | |
1303 | +} | |
1304 | + | |
1305 | +/* pb[] = { vector, size, vret_offs, ...hook_code... } */ | |
1306 | +static int | |
1307 | +action_reloc_hook( int action, ulong *hookcode, const int *pb ) | |
1308 | +{ | |
1309 | + ulong addr, inst, vector=pb[0], size=pb[1], vret_offs=pb[2]; | |
1310 | + cleanup_entry_t *clean; | |
1311 | + ulong *vector_virt, *target; | |
1312 | + action_pb_t *apb; | |
1313 | + char *lowmem; | |
1314 | + int i; | |
1315 | + | |
1316 | + /* Virtual address of exception vector */ | |
1317 | + vector_virt = lowmem_phys_to_virt(vector); | |
1318 | + | |
1319 | + /* address of the vector hook code */ | |
1320 | + addr = tophys_mol( (char*)hookcode ); | |
1321 | + | |
1322 | + /* allocate lowmem and add cleanup handler */ | |
1323 | + if( !(lowmem=lowmem_alloc(size, &clean)) ) | |
1324 | + return 1; | |
1325 | + | |
1326 | + /* printk("ACTION_RELOC_HOOK: %lx, %lx, %lx, %lx %p\n", vector, size, vret_action, vret_offs, lowmem); */ | |
1327 | + | |
1328 | + memcpy( lowmem, &pb[3], size ); | |
1329 | + | |
1330 | + /* perform the vret_action */ | |
1331 | + for( i=0; (apb=find_action(ACTION_VRET, i)); i++ ) { | |
1332 | + if( apb->params[0] != vector ) | |
1333 | + continue; | |
1334 | + | |
1335 | + /* insert the absolut branch */ | |
1336 | + target = (ulong*)(code_base + apb->offs); | |
1337 | + *target = ((18<<26) + 2) | lowmem_tophys(lowmem + vret_offs); | |
1338 | + flush_icache_mol( (ulong)target, (ulong)target + 4 ); | |
1339 | + /* printk("'ba xxx' added (opcode %08lX at %p)\n", *target, target ); */ | |
1340 | + } | |
1341 | + | |
1342 | + /* fix the hook address in the glue code */ | |
1343 | + target = (ulong*)lowmem; | |
1344 | + target[1] = (target[1] & ~0xffff) | (addr >> 16); /* target[0] = addis r3,0,0 */ | |
1345 | + target[3] = (target[3] & ~0xffff) | (addr & 0xffff); /* target[1] = ori r3,r3,0 */ | |
1346 | + | |
1347 | + /* relocate instruction to be overwritten with a branch */ | |
1348 | + inst = *vector_virt; | |
1349 | + clean->opcode = inst; | |
1350 | + if( relocate_inst( &inst, vector, lowmem_tophys(lowmem+vret_offs) )) | |
1351 | + return 1; | |
1352 | + *(ulong*)(lowmem + vret_offs) = inst; | |
1353 | + flush_icache_mol( (ulong)lowmem, (ulong)lowmem + size ); | |
1354 | + | |
1355 | + /* insert branch, 'ba lowmem_ph' */ | |
1356 | + *(volatile ulong*)vector_virt = 0x48000002 + lowmem_tophys(lowmem); | |
1357 | + flush_icache_mol( (ulong)vector_virt, (ulong)vector_virt+4 ); | |
1358 | + | |
1359 | + /* we are in business! */ | |
1360 | + clean->inst_addr = vector_virt; | |
1361 | + return 0; | |
1362 | +} | |
1363 | + | |
1364 | + | |
1365 | +/* pb = { size, where_to_store_lowmem_addr, ...code... } */ | |
1366 | +static int | |
1367 | +action_reloc_low( int action, ulong *dummy, const int *pb ) | |
1368 | +{ | |
1369 | + int size = pb[0]; | |
1370 | + char **func_ptr = (char**)pb[1]; | |
1371 | + char *lowmem; | |
1372 | + | |
1373 | + if( !(lowmem=lowmem_alloc(size, NULL)) ) | |
1374 | + return 1; | |
1375 | + memcpy( lowmem, (char*)&pb[2], size ); | |
1376 | + | |
1377 | + flush_icache_mol( (ulong)lowmem, (ulong)lowmem+size ); | |
1378 | + *func_ptr = lowmem; | |
1379 | + return 0; | |
1380 | +} | |
1381 | + | |
1382 | +/* pb = { symind, size, fret_offset, codeglue... } */ | |
1383 | +static int | |
1384 | +action_hook_function( int action, ulong *hookcode, const int *pb ) | |
1385 | +{ | |
1386 | + ulong addr, fhook=pb[0], size=pb[1], fret_offs=pb[2]; | |
1387 | + ulong *target, inst; | |
1388 | + char *lowmem, *func_addr=NULL; | |
1389 | + cleanup_entry_t *clean; | |
1390 | + | |
1391 | + switch( fhook ) { | |
1392 | +#ifdef __linux__ | |
1393 | + case FHOOK_FLUSH_HASH_PAGE: | |
1394 | + func_addr = (char*)compat_flush_hash_pages; | |
1395 | + break; | |
1396 | +#endif | |
1397 | + default: | |
1398 | + printk("Bad fhook index %ld\n", fhook ); | |
1399 | + return 1; | |
1400 | + } | |
1401 | + | |
1402 | + /* this does not have to be in lowmem, but it is simpler with a unified approach */ | |
1403 | + if( !(lowmem=lowmem_alloc(size, &clean)) ) | |
1404 | + return 1; | |
1405 | + | |
1406 | + /* printk("ACTION_HOOK_FUNCTION: %lx, %lx, %lx %p\n", fhook, size, fret_offs, lowmem); */ | |
1407 | + | |
1408 | + memcpy( lowmem, &pb[3], size ); | |
1409 | + | |
1410 | + /* fix the hook address in the glue code */ | |
1411 | + target = (ulong*)lowmem; | |
1412 | + addr = (ulong)hookcode; | |
1413 | + target[1] = (target[1] & ~0xffff) | (addr >> 16); /* target[1] = addis rX,0,0 */ | |
1414 | + target[2] = (target[2] & ~0xffff) | (addr & 0xffff); /* target[2] = ori rX,rX,0 */ | |
1415 | + | |
1416 | + /* relocate overwritten instruction and add relative return branch */ | |
1417 | + inst = *(ulong*)func_addr; | |
1418 | + clean->opcode = inst; | |
1419 | + if( relocate_inst(&inst, (ulong)func_addr, (ulong)lowmem + fret_offs) ) | |
1420 | + return 1; | |
1421 | + target = (ulong*)(lowmem + fret_offs); | |
1422 | + target[0] = inst; | |
1423 | + target[1] = (18<<26) | (((ulong)func_addr - (ulong)&target[1] + sizeof(long)) & 0x03fffffc); | |
1424 | + flush_icache_mol( (ulong)lowmem, (ulong)lowmem + size ); | |
1425 | + _sync(); | |
1426 | + | |
1427 | + /* insert relative branch, 'b lowmem' */ | |
1428 | + *(volatile ulong*)func_addr = (18<<26) | ((lowmem - func_addr) & 0x03fffffc); | |
1429 | + flush_icache_mol( (ulong)func_addr, (ulong)func_addr+4 ); | |
1430 | + | |
1431 | + _sync(); | |
1432 | + | |
1433 | + /* we are in business! */ | |
1434 | + clean->inst_addr = (ulong*)func_addr; | |
1435 | + return 0; | |
1436 | +} | |
1437 | + | |
1438 | +static int | |
1439 | +action_fix_sprg2( int action, ulong *target, const int *pb ) | |
1440 | +{ | |
1441 | +#ifdef __darwin__ | |
1442 | + int sprg2; | |
1443 | + int r = pb[0] & 0x1f; | |
1444 | + asm volatile("mfspr %0,274" : "=r" (sprg2) ); | |
1445 | + target[0] = OPCODE_LIS( r, (sprg2 >> 16) & 0xffff ); | |
1446 | + target[1] = OPCODE_ORI( r, r, (sprg2 & 0xffff) ); | |
1447 | + target[2] = OPCODE_MTSPRG2( r ); | |
1448 | +#endif | |
1449 | + return 0; | |
1450 | +} | |
1451 | + | |
1452 | +static int | |
1453 | +action_noaction( int action, ulong *hookcode, const int *pb ) | |
1454 | +{ | |
1455 | + return 0; | |
1456 | +} | |
1457 | + | |
1458 | +static action_func_t actiontable[MAX_NUM_ACTIONS] = { | |
1459 | + [ACTION_LI_PHYS] = action_li_phys, | |
1460 | + [ACTION_LWZ_PHYSADDR_R] = action_lwz_physaddr_r, | |
1461 | + [ACTION_TOPHYS] = action_tophysvirt, | |
1462 | + [ACTION_TOVIRT] = action_tophysvirt, | |
1463 | + [ACTION_RELOC_HOOK] = action_reloc_hook, | |
1464 | + [ACTION_RELOCATE_LOW] = action_reloc_low, | |
1465 | + [ACTION_HOOK_FUNCTION] = action_hook_function, | |
1466 | + [ACTION_VRET] = action_noaction, | |
1467 | + [ACTION_FIX_SPRG2] = action_fix_sprg2, | |
1468 | + | |
1469 | + [ACTION_LIS_SPECVAR_H] = action_specvar, | |
1470 | + [ACTION_ORI_SPECVAR_L] = action_specvar, | |
1471 | +}; | |
1472 | + | |
1473 | + | |
1474 | +/************************************************************************/ | |
1475 | +/* write/remove hooks */ | |
1476 | +/************************************************************************/ | |
1477 | + | |
1478 | +static int | |
1479 | +relocate_code( void ) | |
1480 | +{ | |
1481 | + extern char r__reloctable_start[], r__reloctable_end[]; | |
1482 | + | |
1483 | + code_size = r__reloctable_end - r__reloctable_start; | |
1484 | + | |
1485 | + if( !(code_base=kmalloc_cont_mol(code_size)) ) | |
1486 | + return 1; | |
1487 | + | |
1488 | + memcpy( code_base, r__reloctable_start, code_size ); | |
1489 | + reloc_virt_offs = (int)code_base - (int)r__reloctable_start; | |
1490 | + return 0; | |
1491 | +} | |
1492 | + | |
1493 | +int | |
1494 | +perform_actions( void ) | |
1495 | +{ | |
1496 | + action_pb_t *pb; | |
1497 | + int action, i; | |
1498 | + | |
1499 | + if( relocate_code() ) | |
1500 | + return 1; | |
1501 | + lowmem_initialize(); | |
1502 | + | |
1503 | + for( action=0; action < MAX_NUM_ACTIONS; action++ ) { | |
1504 | + for( i=0; (pb=find_action(action,i)); i++ ) { | |
1505 | + ulong *target = (ulong*)(code_base + pb->offs); | |
1506 | + | |
1507 | + if( pb->offs > code_size ) { | |
1508 | + printk("OFFSET ERROR!\n"); | |
1509 | + goto error; | |
1510 | + } | |
1511 | + | |
1512 | + if( !actiontable[action] ) | |
1513 | + goto error; | |
1514 | + if( (*actiontable[action])(action, target, pb->params) ) | |
1515 | + goto error; | |
1516 | + } | |
1517 | + | |
1518 | + /* we need to flush the icache before the hook actions are performed */ | |
1519 | + if( action == FLUSH_CACHE_ACTION ) | |
1520 | + flush_icache_mol( (ulong)code_base, (ulong)code_base + code_size ); | |
1521 | + } | |
1522 | + /* to be on the safe side, flush the cache once more */ | |
1523 | + flush_icache_mol( (ulong)code_base, (ulong)code_base + code_size ); | |
1524 | + return 0; | |
1525 | + error: | |
1526 | + printk("MOL: action %d error\n", action ); | |
1527 | + cleanup_actions(); | |
1528 | + return 1; | |
1529 | +} | |
1530 | + | |
1531 | +void | |
1532 | +cleanup_actions( void ) | |
1533 | +{ | |
1534 | + cleanup_entry_t *ce = &cleanup_table[0]; | |
1535 | + int i; | |
1536 | + | |
1537 | + for( i=0; i<num_cleanup_entries; i++, ce++ ) { | |
1538 | + if( ce->inst_addr ) { | |
1539 | + *(volatile ulong*)ce->inst_addr = cleanup_table[i].opcode; | |
1540 | + flush_icache_mol( (ulong)ce->inst_addr, (ulong)ce->inst_addr + 4 ); | |
1541 | + } | |
1542 | + } | |
1543 | + lowmem_free_all(); | |
1544 | + kfree_cont_mol( code_base ); | |
1545 | +} | |
1546 | --- /dev/null | |
1547 | +++ b/drivers/macintosh/mol/asm-files/603.S | |
1548 | @@ -0,0 +1,218 @@ | |
1549 | +/* | |
1550 | + * Creation Date: <2001/06/15 20:10:49 samuel> | |
1551 | + * Time-stamp: <2001/06/16 15:35:22 samuel> | |
1552 | + * | |
1553 | + * <603.S> | |
1554 | + * | |
1555 | + * 603 MMU support | |
1556 | + * | |
1557 | + * Copyright (C) 2001 Samuel Rydh (samuel@ibrium.se) | |
1558 | + * | |
1559 | + * This program is free software; you can redistribute it and/or | |
1560 | + * modify it under the terms of the GNU General Public License | |
1561 | + * as published by the Free Software Foundation | |
1562 | + * | |
1563 | + */ | |
1564 | + | |
1565 | +#define P603_USE_G_BIT | |
1566 | +#define P603_USE_R_BIT | |
1567 | +#define P603_USE_C_BIT | |
1568 | + | |
1569 | +/* NOTE: The 603 vectors are called with ctr saved in r0. | |
1570 | + * Secondary interrupts are not detected automatically. | |
1571 | + */ | |
1572 | + | |
1573 | +/************************************************************************/ | |
1574 | +/* Instruction TLB Miss (603 specific vector) */ | |
1575 | +/************************************************************************/ | |
1576 | + | |
1577 | +VECTOR_603( 0x1000, "Instruction TLB Miss - 603" ) | |
1578 | +// mfctr r0 // Need to save this - CTR can't be touched! | |
1579 | + mfspr r2,HASH1 // Get PTE pointer | |
1580 | + mfspr r3,ICMP // Partial item compare value | |
1581 | +00: li r1,8 // 8 items / bucket | |
1582 | + mtctr r1 | |
1583 | + subi r2,r2,8 // Preset pointer | |
1584 | +10: lwzu r1,8(r2) // Get next PTE | |
1585 | + cmp 0,r1,r3 // Found entry yet? | |
1586 | + bdnzf 2,10b // Jump back if not, until CTR==0 | |
1587 | + bne 30f // Try secondary hash if CTR==0 | |
1588 | + lwz r1,4(r2) // Get second word of entry | |
1589 | +#ifdef P603_USE_G_BIT | |
1590 | + andi. r3,r1,8 // check G-bit | |
1591 | + bne DoISI_603_G // if guarded, take an ISI | |
1592 | +#endif | |
1593 | + mtctr r0 // Restore CTR | |
1594 | + mfspr r3,SRR1 // Need to restore CR0 | |
1595 | + mtcrf 0x80,r3 | |
1596 | + mfspr r0,IMISS // Set to update TLB | |
1597 | + mtspr RPA,r1 | |
1598 | +#ifdef P603_USE_R_BIT | |
1599 | + ori r1,r1,0x100 // Set reference bit | |
1600 | + srwi r1,r1,8 // Get byte 7 of pte | |
1601 | + tlbli r0 // Load the ITLB | |
1602 | + stb r1,6(r2) // update page table | |
1603 | +#else | |
1604 | + tlbli r0 // Load the ITLB | |
1605 | +#endif | |
1606 | + rfi // All done | |
1607 | + | |
1608 | + // Secondary hash | |
1609 | +30: andi. r1,r3,0x40 // Already doing secondary hash? | |
1610 | + bne DoISI_603 // Yes - item not in hash table | |
1611 | + mfspr r2,HASH2 // Get hash table pointer | |
1612 | + ori r3,r3,0x40 // Set secondary hash | |
1613 | + b 00b // Try lookup again | |
1614 | + | |
1615 | + | |
1616 | +/************************************************************************/ | |
1617 | +/* Data Store TLB Miss (603 specific vector) */ | |
1618 | +/************************************************************************/ | |
1619 | + | |
1620 | +VECTOR_603( 0x1200, "Data Store TLB Miss - 603" ) | |
1621 | +// mfctr r0 // Need to save this - CTR can't be touched! | |
1622 | + mfspr r2,HASH1 // Get PTE pointer | |
1623 | + mfspr r3,DCMP // Partial item compare value | |
1624 | +00: li r1,8 // 8 items / bucket | |
1625 | + mtctr r1 | |
1626 | + subi r2,r2,8 // Preset pointer | |
1627 | +10: lwzu r1,8(r2) // Get next PTE | |
1628 | + cmp 0,r1,r3 // Found entry yet? | |
1629 | + bdnzf 2,10b // Jump back if not, until CTR==0 | |
1630 | + bne 30f // Try secondary hash if CTR==0 | |
1631 | + lwz r1,4(r2) // Get second word of entry | |
1632 | +#ifdef P603_USE_C_BIT | |
1633 | + andi. r3,r1,0x80 // Check the C-bit | |
1634 | + beq CheckProt_603 | |
1635 | +16: | |
1636 | +#endif | |
1637 | +20: mtctr r0 // Restore CTR | |
1638 | + mfspr r3,SRR1 // Need to restore CR0 | |
1639 | + mtcrf 0x80,r3 | |
1640 | + mfspr r0,DMISS // Set to update TLB | |
1641 | + mtspr RPA,r1 | |
1642 | + tlbld r0 | |
1643 | + rfi // All done | |
1644 | + | |
1645 | + // Secondary hash | |
1646 | +30: andi. r1,r3,0x40 // Already doing secondary hash? | |
1647 | + bne DoDSI_603 // Yes - item not in hash table | |
1648 | + mfspr r2,HASH2 // Get hash table pointer | |
1649 | + ori r3,r3,0x40 // Set secondary hash | |
1650 | + b 00b // Try lookup again | |
1651 | + | |
1652 | +#ifdef P603_USE_C_BIT | |
1653 | + // Entry found and PTE[c] == 0. Check protection before setting PTE[c] | |
1654 | + // r0 = saved ctr, r1 = second word of PTE, r2 = pointer to pteg, r3 = trash | |
1655 | +CheckProt_603: | |
1656 | + rlwinm. r3,r1,30,0,1 // test PP | |
1657 | + bge- 50f // if (PP == 00 or PP == 01) goto 50 | |
1658 | + andi. r3,r1,1 // test PP[0] | |
1659 | + beq+ 60f // return if PP[0] == 0 | |
1660 | + b DoDSI_603_P // else DSI_P, (PP==11, read-only) | |
1661 | + | |
1662 | +50: mfspr r3,SRR1 // get old msr | |
1663 | + andis. r3,r3,0x0008 // test the KEY bit (SRR1-bit 12) | |
1664 | + beq 60f // if KEY==0, goto 60 | |
1665 | + b DoDSI_603_P // else DSI_P | |
1666 | + | |
1667 | +60: ori r1,r1,0x180 // set reference and change bit | |
1668 | + sth r1,6(r2) // update page table | |
1669 | + b 16b // and back we go | |
1670 | +#endif | |
1671 | + | |
1672 | + | |
1673 | +/************************************************************************/ | |
1674 | +/* Data Load TLB Miss (603 specific vector) */ | |
1675 | +/************************************************************************/ | |
1676 | + | |
1677 | +VECTOR_603( 0x1100, "Data Load TLB Miss - 603" ) | |
1678 | +// mfctr r0 // Need to save this - CTR can't be touched! | |
1679 | + mfspr r2,HASH1 // Get PTE pointer | |
1680 | + mfspr r3,DCMP // Partial item compare value | |
1681 | +00: li r1,8 // 8 items / bucket | |
1682 | + mtctr r1 | |
1683 | + subi r2,r2,8 // Preset pointer | |
1684 | +10: lwzu r1,8(r2) // Get next PTE | |
1685 | + cmp 0,r1,r3 // Found entry yet? | |
1686 | + bdnzf 2,10b // Jump back if not, until CTR==0 | |
1687 | + bne 30f // Try secondary hash if CTR==0 | |
1688 | + lwz r1,4(r2) // Get second word of entry | |
1689 | +20: mtctr r0 // Restore CTR | |
1690 | + mfspr r3,SRR1 // Need to restore CR0 | |
1691 | + mtcrf 0x80,r3 | |
1692 | + mfspr r0,DMISS // Set to update TLB | |
1693 | + mtspr RPA,r1 | |
1694 | +#ifdef P603_USE_R_BIT | |
1695 | + ori r1,r1,0x100 // set reference bit | |
1696 | + srwi r1,r1,8 | |
1697 | + tlbld r0 | |
1698 | + stb r1,6(r2) | |
1699 | +#else | |
1700 | + tlbld r0 | |
1701 | +#endif | |
1702 | + rfi // All done | |
1703 | + | |
1704 | +// Secondary hash | |
1705 | +30: andi. r1,r3,0x40 // Already doing secondary hash? | |
1706 | + bne DoDSI_603 // Yes - item not in hash table | |
1707 | + mfspr r2,HASH2 // Get hash table pointer | |
1708 | + ori r3,r3,0x40 // Set secondary hash | |
1709 | + b 00b // Try lookup again | |
1710 | + | |
1711 | + | |
1712 | +/************************************************************************/ | |
1713 | +/* Synthesize an ISI Exception */ | |
1714 | +/************************************************************************/ | |
1715 | + | |
1716 | +DoISI_603: | |
1717 | + mfspr r3,SRR1 | |
1718 | + andi. r2,r3,0xFFFF // Clear upper bits of SRR1 | |
1719 | + addis r2,r2,0x4000 // Set bit 1 -> PTE not found (in HTAB) | |
1720 | + mtctr r0 // Restore CTR | |
1721 | +40: mtspr SRR1,r2 | |
1722 | + mfmsr r0 // Restore "normal" registers | |
1723 | + xoris r0,r0,MSR_TGPR>>16 | |
1724 | + mtcrf 0x80,r3 // Restore CR0 | |
1725 | + sync // Some chip revs have problems here... | |
1726 | + mtmsr r0 | |
1727 | + SOFT_VECTOR_ENTRY_603( 0x400 ) // Jump to the ISI vector | |
1728 | + | |
1729 | + | |
1730 | +#ifdef P603_USE_G_BIT | |
1731 | +DoISI_603_G: | |
1732 | + mfspr r3,SRR1 | |
1733 | + andi. r2,r3,0xFFFF // Clear upper bits of SRR1 | |
1734 | +// addis r2,r2,0x0800 // Page protection violation | |
1735 | + addis r2,r2,0x1000 // Guarded memory access | |
1736 | + b 40b | |
1737 | +#endif | |
1738 | + | |
1739 | + | |
1740 | +/************************************************************************/ | |
1741 | +/* Synthesize a DSI exception */ | |
1742 | +/************************************************************************/ | |
1743 | + | |
1744 | +DoDSI_603: | |
1745 | + mfspr r3,SRR1 | |
1746 | + rlwinm r1,r3,9,6,6 // Get load/store bit | |
1747 | + addis r1,r1,0x4000 // Set bit 1 -> PTE not found | |
1748 | + | |
1749 | +10: mtspr DSISR,r1 | |
1750 | + mtctr r0 // Restore CTR | |
1751 | + andi. r2,r3,0xFFFF // Clear upper bits of SRR1 | |
1752 | + mtspr SRR1,r2 | |
1753 | + mfspr r1,DMISS // Get failing address | |
1754 | + mtspr DAR,r1 // Set fault address | |
1755 | + mfmsr r0 // Restore "normal" registers | |
1756 | + xoris r0,r0,MSR_TGPR>>16 | |
1757 | + mtcrf 0x80,r3 // Restore CR0 | |
1758 | + sync // Some chip revs have problems here... | |
1759 | + mtmsr r0 | |
1760 | + SOFT_VECTOR_ENTRY_603( 0x300 ) // Jump to the DSI vector | |
1761 | + | |
1762 | +DoDSI_603_P: | |
1763 | + mfspr r3,SRR1 | |
1764 | + rlwinm r1,r3,9,6,6 // get load/store bit | |
1765 | + addis r1,r1,0x800 // Set bit 4 (prot. violation) | |
1766 | + b 10b | |
1767 | --- /dev/null | |
1768 | +++ b/drivers/macintosh/mol/asm-files/dec.S | |
1769 | @@ -0,0 +1,228 @@ | |
1770 | +/* | |
1771 | + * Creation Date: <2001/06/21 17:10:35 samuel> | |
1772 | + * Time-stamp: <2004/03/07 13:16:58 samuel> | |
1773 | + * | |
1774 | + * <dec.S> | |
1775 | + * | |
1776 | + * DEC / TimeBase stuff | |
1777 | + * | |
1778 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
1779 | + * | |
1780 | + * This program is free software; you can redistribute it and/or | |
1781 | + * modify it under the terms of the GNU General Public License | |
1782 | + * as published by the Free Software Foundation | |
1783 | + * | |
1784 | + */ | |
1785 | + | |
1786 | +/************************************************************************/ | |
1787 | +/* TBWU / TBWL */ | |
1788 | +/************************************************************************/ | |
1789 | + | |
1790 | +#if 0 | |
1791 | +spr_tbwu: | |
1792 | + blr // read (won't come here) | |
1793 | + mr r3,r0 | |
1794 | + mftb r4 | |
1795 | + b update_tb | |
1796 | + | |
1797 | +spr_tbwl: | |
1798 | + blr // read (won't come here) | |
1799 | + mftbu r3 | |
1800 | + mr r4,r0 | |
1801 | + // ...fall through... | |
1802 | + | |
1803 | +// r3 = tbu, r4 = tbl, r0,r2,r5 free. | |
1804 | +update_tb: | |
1805 | + lwz r5,K_LOADED_DEC(r1) | |
1806 | + mfdec r2 | |
1807 | + sub r5,r5,r2 // r5 = elapsed ticks | |
1808 | + | |
1809 | + li r2,0 // Set timebase | |
1810 | + mttbl r4 | |
1811 | + mttbu r3 | |
1812 | + mttbl r4 | |
1813 | + | |
1814 | + mfxer r2 | |
1815 | + subfc r4,r5,r4 | |
1816 | + addme r3,r3 | |
1817 | + stw r4,xTBL(r1) | |
1818 | + stw r3,xTBU(r1) | |
1819 | + mtxer r2 | |
1820 | + b emulation_done | |
1821 | +#endif | |
1822 | + | |
1823 | + | |
1824 | +/************************************************************************/ | |
1825 | +/* Load/restore DEC and TB */ | |
1826 | +/************************************************************************/ | |
1827 | + | |
1828 | + ////////////////////////////////////////////////////////////// | |
1829 | + // recalc_int_stamp | |
1830 | + // | |
1831 | + // May modify: r0,r2-r5 | |
1832 | + // | |
1833 | + | |
1834 | +recalc_int_stamp: | |
1835 | + crclr FBIT_RecalcDecInt | |
1836 | + | |
1837 | + lwz r5,xTIMER_STAMP(r1) | |
1838 | + bf FBIT_DecSeenZero, 1f // FBIT_DecSeenZero must be set when DEC is loaded | |
1839 | + bt FBIT_DecINT, 1f // interrupt might already be flagged... | |
1840 | + mftb r3 | |
1841 | + lwz r4,xDEC_STAMP(r1) // Has the xDEC overflown already? | |
1842 | + sub. r0,r4,r3 | |
1843 | + blt 2f // branch if xDEC < 0 | |
1844 | + sub. r0,r4,r5 | |
1845 | + blt 2f // branch if xDEC < xTIMER | |
1846 | +1: mr r4,r5 | |
1847 | +2: stw r4,K_INT_STAMP(r1) // dec = xTIMER | |
1848 | + blr | |
1849 | + | |
1850 | + | |
1851 | + ////////////////////////////////////////////////////////////// | |
1852 | + // set_mol_dec | |
1853 | + // | |
1854 | + // May modify: r0,r2-r5 | |
1855 | + // | |
1856 | + // Old 2.4 kernels assume that linux-DEC never ticks faster | |
1857 | + // than the DEC interval measured from TB. Unfortunately, | |
1858 | + // it is virtually impossible to keep DEC/TB in sync. | |
1859 | + // | |
1860 | + // Experimentally, the "worst case" senario is a linux DEC tick | |
1861 | + // beeing delayed 0.04 ms (to be compare with the 20 ms period). | |
1862 | + // | |
1863 | + // Sequences similar to | |
1864 | + // | |
1865 | + // 1: mftb r2; mfdec r3; mftb r4; cmp r2,r4; bne 1b | |
1866 | + // | |
1867 | + // do *not* work - DEC and TB probably ticks on different edges. | |
1868 | + | |
1869 | +set_mol_dec: | |
1870 | + lwz r5,K_INT_STAMP(r1) // DEC = K_INT_STAMP - tbl | |
1871 | + mfdec r3 // Make sure linux interrupts *never* | |
1872 | + mftb r2 // occur too fast | |
1873 | + | |
1874 | + sub r4,r5,r2 | |
1875 | + cmpw r4,r3 | |
1876 | + bgtlr | |
1877 | + add r5,r3,r2 // K_DEC_STAMP = DEC + tbl | |
1878 | + mtdec r4 | |
1879 | + | |
1880 | + stw r5,K_DEC_STAMP(r1) | |
1881 | + crset FBIT_MolDecLoaded | |
1882 | + blr | |
1883 | + | |
1884 | + /////////////////////////////////////////////////////////////// | |
1885 | + // set_kernel_dec | |
1886 | + // | |
1887 | + // May modify: r0,r2, cr | |
1888 | + // | |
1889 | + | |
1890 | +set_kernel_dec: | |
1891 | + lwz r0,K_DEC_STAMP(r1) | |
1892 | + crclr FBIT_MolDecLoaded | |
1893 | + mftb r2 // Keep linux-DEC coherent | |
1894 | + sub r2,r0,r2 // DEC = stamp - tbl | |
1895 | + mtdec r2 | |
1896 | + blr | |
1897 | + | |
1898 | + | |
1899 | + | |
1900 | +/************************************************************************/ | |
1901 | +/* DEC read/write */ | |
1902 | +/************************************************************************/ | |
1903 | + | |
1904 | +_dec_read: | |
1905 | + lwz r4,xDEC_STAMP(r1) | |
1906 | + mftb r3 | |
1907 | + sub r0,r4,r3 | |
1908 | + | |
1909 | + BUMP("dec_read") | |
1910 | + GET_TICK_CNT(entry,"dec_read") | |
1911 | + b simple_mfspr | |
1912 | + | |
1913 | +spr_dec: | |
1914 | + b _dec_read | |
1915 | + | |
1916 | + // dec write. r0 = spr_value | |
1917 | + BUMP("mtdec") | |
1918 | + rlwinm. r5,r0,0,0,0 // seen zero? | |
1919 | + mftb r4 | |
1920 | + cror FBIT_DecSeenZero,FBIT_DecSeenZero,eq | |
1921 | + add r5,r4,r0 | |
1922 | + stw r5,xDEC_STAMP(r1) // set new dec value | |
1923 | + bf FBIT_DecSeenZero, emulation_done | |
1924 | + bl recalc_int_stamp // M: r0,r2-r5 | |
1925 | + btl FBIT_MolDecLoaded, set_kernel_dec // M: r0,r2 | |
1926 | + bl set_mol_dec // M: r0,r2-r5 | |
1927 | + b emulation_done | |
1928 | + | |
1929 | + | |
1930 | +/************************************************************************/ | |
1931 | +/* Decrementer Exception */ | |
1932 | +/************************************************************************/ | |
1933 | + | |
1934 | + // __dec_VECTOR (non-MOL dec exception) | |
1935 | + // | |
1936 | + // r3=cr, sprg1=saved_r1, sprg0=saved_r3 | |
1937 | + // | |
1938 | + // An exception with DEC>=0 can occur if a mac-DEC overflows occurs | |
1939 | + // just prior to a context switch. These exceptions should be | |
1940 | + // dropped silently. | |
1941 | + | |
1942 | +__dec_VECTOR: | |
1943 | + mfdec r1 | |
1944 | + cmpwi r1,0 | |
1945 | + blt+ 1f | |
1946 | + mtcr r3 // Restore and exit | |
1947 | + ABORT_TRAP( 0x900 ) | |
1948 | +1: | |
1949 | + mtcr r3 // Restore and continue trap | |
1950 | + CONTINUE_TRAP( 0x900 ) | |
1951 | + | |
1952 | +VECTOR_( 0x900, "Decrementer", secint_bad, __dec_VECTOR ) | |
1953 | + EXCEPTION_PREAMBLE // r0-r5, CR, LR, r6/r7 = msr/nip | |
1954 | + TRACE(0x900, "Decrementer") | |
1955 | + mfdec r4 | |
1956 | + cmpwi r4,0 | |
1957 | + bge exception_return | |
1958 | + bf FBIT_MolDecLoaded, take_linux_dec_exception | |
1959 | + | |
1960 | + mftb r3 | |
1961 | + lis r2,0x1000 // r2 = DEC rearm constant | |
1962 | + | |
1963 | + bf FBIT_DecSeenZero, 1f // check for xDEC overflow | |
1964 | + lwz r4,xDEC_STAMP(r1) | |
1965 | + sub. r0,r4,r3 // lt set if xDEC has overflown | |
1966 | + cror FBIT_DecINT, FBIT_DecINT, lt // dec_int |= lt | |
1967 | + crandc FBIT_DecSeenZero, FBIT_DecSeenZero, lt // szero &= ~lt | |
1968 | +1: | |
1969 | + lwz r5,xTIMER_STAMP(r1) // r5 = xTIMER_STAMP | |
1970 | + sub. r0,r5,r3 // lt set if xTIMER has overflown | |
1971 | + mtdec r2 // rearm DEC | |
1972 | + blt- 2f // xTIMER has higher priority... | |
1973 | + | |
1974 | + // mac-dec interrupt | |
1975 | + BUMP("DEC-overflow") | |
1976 | + bl set_kernel_dec | |
1977 | + bl recalc_int_stamp | |
1978 | + bl set_mol_dec | |
1979 | + GET_TICK_CNT(entry,"dec-overflow") | |
1980 | + bf- FBIT_DecINT,exception_return // could occur if xTIMER has changed on us | |
1981 | + lwz r4,xMSR(r1) | |
1982 | + rlwinm. r0,r4,0,MSR_EE | |
1983 | + beq- exception_return // no... simply return | |
1984 | + BUMP("DEC-exception") | |
1985 | + b mac_dec_trap | |
1986 | + | |
1987 | + // timer interrupt | |
1988 | +2: BUMP("Timer-interrupt") | |
1989 | + crset FBIT_RecalcDecInt // dec must be recalced | |
1990 | + GET_TICK_CNT(entry,"timer-overflow") | |
1991 | + MAC_EXIT_SAVE( RVEC_TIMER ) | |
1992 | + | |
1993 | + | |
1994 | +take_linux_dec_exception: | |
1995 | + BUMP("Linux-DEC") | |
1996 | + bl save_middle_regs | |
1997 | + TAKE_EXCEPTION( 0x900 ) | |
1998 | --- /dev/null | |
1999 | +++ b/drivers/macintosh/mol/asm-files/emuaccel.S | |
2000 | @@ -0,0 +1,188 @@ | |
2001 | +/* | |
2002 | + * Creation Date: <2003/01/24 13:54:52 samuel> | |
2003 | + * Time-stamp: <2003/08/14 03:12:00 samuel> | |
2004 | + * | |
2005 | + * <emuaccel.S> | |
2006 | + * | |
2007 | + * Emulation acceleration | |
2008 | + * | |
2009 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
2010 | + * | |
2011 | + * This program is free software; you can redistribute it and/or | |
2012 | + * modify it under the terms of the GNU General Public License | |
2013 | + * as published by the Free Software Foundation | |
2014 | + * | |
2015 | + */ | |
2016 | + | |
2017 | +#include "emuaccel_sh.h" | |
2018 | + | |
2019 | + // emuaccel registers: | |
2020 | + // | |
2021 | + // r2 = emuaccel_slot | |
2022 | + // r6,r7 = nip(return address)/mregs | |
2023 | + // | |
2024 | + | |
2025 | + balign_8 | |
2026 | +emuaccel_mtmsr_rNN: | |
2027 | +mFORLOOP([i],0,31,[ | |
2028 | + LOAD_EMUGPR_IM r0,i | |
2029 | + b emulate_mtmsr_accel | |
2030 | +]) | |
2031 | +emuaccel_mtsrr0_rNN: | |
2032 | +mFORLOOP([i],0,31,[ | |
2033 | + .if (i <= 7) | |
2034 | + LOAD_EMUGPR_IM r0,i | |
2035 | + b emulate_mtsrr0_accel | |
2036 | + .else | |
2037 | + stw rPREFIX[]i,xSRR0(r1) | |
2038 | + b emulation_done_noinc | |
2039 | + .endif | |
2040 | +]) | |
2041 | +emuaccel_mtsrr1_rNN: | |
2042 | +mFORLOOP([i],0,31,[ | |
2043 | + .if (i <= 7) | |
2044 | + LOAD_EMUGPR_IM r0,i | |
2045 | + b emulate_mtsrr1_accel | |
2046 | + .else | |
2047 | + stw rPREFIX[]i,xSRR1(r1) | |
2048 | + b emulation_done_noinc | |
2049 | + .endif | |
2050 | +]) | |
2051 | +emuaccel_mtsprg0_rNN: | |
2052 | +mFORLOOP([i],0,31,[ | |
2053 | + .if (i <= 7) | |
2054 | + LOAD_EMUGPR_IM r0,i | |
2055 | + b emulate_mtsprg0_accel | |
2056 | + .else | |
2057 | + stw rPREFIX[]i,xSPRG0(r1) | |
2058 | + b emulation_done_noinc | |
2059 | + .endif | |
2060 | +]) | |
2061 | +emuaccel_mtsprg1_rNN: | |
2062 | +mFORLOOP([i],0,31,[ | |
2063 | + .if (i <= 7) | |
2064 | + LOAD_EMUGPR_IM r0,i | |
2065 | + b emulate_mtsprg1_accel | |
2066 | + .else | |
2067 | + stw rPREFIX[]i,xSPRG1(r1) | |
2068 | + b emulation_done_noinc | |
2069 | + .endif | |
2070 | +]) | |
2071 | +emuaccel_mtsprg2_rNN: | |
2072 | +mFORLOOP([i],0,31,[ | |
2073 | + .if (i <= 7) | |
2074 | + LOAD_EMUGPR_IM r0,i | |
2075 | + b emulate_mtsprg2_accel | |
2076 | + .else | |
2077 | + stw rPREFIX[]i,xSPRG2(r1) | |
2078 | + b emulation_done_noinc | |
2079 | + .endif | |
2080 | +]) | |
2081 | +emuaccel_mtsprg3_rNN: | |
2082 | +mFORLOOP([i],0,31,[ | |
2083 | + .if (i <= 7) | |
2084 | + LOAD_EMUGPR_IM r0,i | |
2085 | + b emulate_mtsprg3_accel | |
2086 | + .else | |
2087 | + stw rPREFIX[]i,xSPRG3(r1) | |
2088 | + b emulation_done_noinc | |
2089 | + .endif | |
2090 | +]) | |
2091 | +emuaccel_mthid0_rNN: | |
2092 | +mFORLOOP([i],0,31,[ | |
2093 | + .if (i <= 7) | |
2094 | + LOAD_EMUGPR_IM r0,i | |
2095 | + b emulate_mthid0_accel | |
2096 | + .else | |
2097 | + stw rPREFIX[]i,xHID0(r1) | |
2098 | + b emulation_done_noinc | |
2099 | + .endif | |
2100 | +]) | |
2101 | + | |
2102 | +emuaccel_nop: | |
2103 | + b emulation_done_noinc | |
2104 | + | |
2105 | +emuaccel_rfi: | |
2106 | + addi r6,r6,-4 // point nip to the rfi instruction | |
2107 | + b emulate_rfi | |
2108 | + | |
2109 | +emuaccel_update_dec: | |
2110 | + lwz r4,xDEC_STAMP(r1) | |
2111 | + mftb r3 | |
2112 | + sub r0,r4,r3 | |
2113 | + stw r0,xDEC(r1) | |
2114 | + b emulation_done_noinc | |
2115 | + | |
2116 | + balign_8 | |
2117 | +emuaccel_mtsr: | |
2118 | + lwz r4,12(r2) // emuaccel paramamter (opcode) | |
2119 | + addi r6,r6,-4 // back NIP | |
2120 | + rlwinm r5,r4,14,24,28 // reg_num << 3 | |
2121 | + b emulate_mtsr | |
2122 | + | |
2123 | + | |
2124 | +/************************************************************************/ | |
2125 | +/* implementation */ | |
2126 | +/************************************************************************/ | |
2127 | + | |
2128 | +emulate_mtsrr0_accel: | |
2129 | + stw r0,xSRR0(r1) | |
2130 | + b emulation_done_noinc | |
2131 | +emulate_mtsrr1_accel: | |
2132 | + stw r0,xSRR1(r1) | |
2133 | + b emulation_done_noinc | |
2134 | +emulate_mtsprg0_accel: | |
2135 | + stw r0,xSPRG0(r1) | |
2136 | + b emulation_done_noinc | |
2137 | +emulate_mtsprg1_accel: | |
2138 | + stw r0,xSPRG1(r1) | |
2139 | + b emulation_done_noinc | |
2140 | +emulate_mtsprg2_accel: | |
2141 | + stw r0,xSPRG2(r1) | |
2142 | + b emulation_done_noinc | |
2143 | +emulate_mtsprg3_accel: | |
2144 | + stw r0,xSPRG3(r1) | |
2145 | + b emulation_done_noinc | |
2146 | +emulate_mthid0_accel: | |
2147 | + stw r0,xHID0(r1) | |
2148 | + b emulation_done_noinc | |
2149 | + | |
2150 | + balign_32 | |
2151 | +emulate_mtmsr_accel: | |
2152 | + lwz r3,xMSR(r1) // r3 = old MSR | |
2153 | + bl msr_altered | |
2154 | + | |
2155 | + GET_TICK_CNT(entry, "mtmsr-accel") | |
2156 | + BUMP("emulate_mtmsr-accel") | |
2157 | + | |
2158 | + beq+ cr1,emulation_done_noinc // no doze... we are done | |
2159 | + MAC_EXIT_SAVE( RVEC_MSR_POW ) // doze | |
2160 | + | |
2161 | + | |
2162 | + | |
2163 | +/************************************************************************/ | |
2164 | +/* setup */ | |
2165 | +/************************************************************************/ | |
2166 | + | |
2167 | +#define EMUACCEL_REL(s) s - emuaccel_table | |
2168 | + | |
2169 | +#ifdef __linux__ | |
2170 | + .text 70 /* this table does not need to be relocated */ | |
2171 | +#endif | |
2172 | + // format: emuaccel_inst, offset, table_index_mask | |
2173 | +GLOBAL_SYMBOL(emuaccel_table): | |
2174 | + .long EMUACCEL_MTMSR, EMUACCEL_REL( emuaccel_mtmsr_rNN ), 0x1f | |
2175 | + .long EMUACCEL_MTSRR0, EMUACCEL_REL( emuaccel_mtsrr0_rNN ), 0x1f | |
2176 | + .long EMUACCEL_MTSRR1, EMUACCEL_REL( emuaccel_mtsrr1_rNN ), 0x1f | |
2177 | + .long EMUACCEL_MTSPRG0, EMUACCEL_REL( emuaccel_mtsprg0_rNN ), 0x1f | |
2178 | + .long EMUACCEL_MTSPRG1, EMUACCEL_REL( emuaccel_mtsprg1_rNN ), 0x1f | |
2179 | + .long EMUACCEL_MTSPRG2, EMUACCEL_REL( emuaccel_mtsprg2_rNN ), 0x1f | |
2180 | + .long EMUACCEL_MTSPRG3, EMUACCEL_REL( emuaccel_mtsprg3_rNN ), 0x1f | |
2181 | + .long EMUACCEL_MTHID0, EMUACCEL_REL( emuaccel_mthid0_rNN ), 0x1f | |
2182 | + .long EMUACCEL_RFI, EMUACCEL_REL( emuaccel_rfi ), 0 | |
2183 | + .long EMUACCEL_UPDATE_DEC, EMUACCEL_REL( emuaccel_update_dec ), 0 | |
2184 | + .long EMUACCEL_MTSR, EMUACCEL_REL( emuaccel_mtsr ), 0 | |
2185 | + .long EMUACCEL_NOP, EMUACCEL_REL( emuaccel_nop ), 0 | |
2186 | + .long 0, 0, 0 /* end marker */ | |
2187 | + | |
2188 | + .text | |
2189 | --- /dev/null | |
2190 | +++ b/drivers/macintosh/mol/asm-files/emulation.S | |
2191 | @@ -0,0 +1,714 @@ | |
2192 | +/* | |
2193 | + * Creation Date: <97/07/26 18:23:02 samuel> | |
2194 | + * Time-stamp: <2004/02/22 13:12:14 samuel> | |
2195 | + * | |
2196 | + * <emulation.S> | |
2197 | + * | |
2198 | + * Low-level emulation of some privileged instructions | |
2199 | + * | |
2200 | + * Copyright (C) 1997-2004 Samuel Rydh (samuel@ibrium.se) | |
2201 | + * | |
2202 | + * This program is free software; you can redistribute it and/or | |
2203 | + * modify it under the terms of the GNU General Public License | |
2204 | + * as published by the Free Software Foundation | |
2205 | + * | |
2206 | + */ | |
2207 | + | |
2208 | +MACRO_0(INC_NIP, [ | |
2209 | + addi r6,r6,4 | |
2210 | +]) | |
2211 | + | |
2212 | + | |
2213 | +/************************************************************************/ | |
2214 | +/* program exception vector */ | |
2215 | +/************************************************************************/ | |
2216 | + | |
2217 | + ////////////////////////////////////////////////////////////// | |
2218 | + // exception preamble | |
2219 | + // r1 stack (mregs) | |
2220 | + // r6,r7 nip / srr1 | |
2221 | + // cr4-7 flag_bits | |
2222 | + // | |
2223 | + // Saved r0-r5 (NOT SAVED: ctr, xer) | |
2224 | + | |
2225 | +VECTOR_( 0x700, "Program", secint_bad, mac_entry ) | |
2226 | + EXCEPTION_PREAMBLE // 46 cycles on a G3 | |
2227 | + TRACE(0x700, "Program") | |
2228 | + | |
2229 | + mtcrf 0x10,r7 // put srr1 bits (12-15) into cr3 | |
2230 | + bt 14,mac_program_trap | |
2231 | + GET_INSTR_OPCODE // r6=nip, r2-r3, r4=opcode (cr not touched) | |
2232 | + bt+ 13,emulate_priv_instr | |
2233 | + bt+ 12,emulate_illegal_instr | |
2234 | + mtcrf 0x20,r7 // put srr1 bits (8-11) into cr2 | |
2235 | + bt+ 11,mac_program_trap // bit 11 = fpu_exception | |
2236 | + | |
2237 | + // we should not come here | |
2238 | + MAC_EXIT_SAVE( RVEC_UNUSUAL_PROGRAM_EXCEP ) | |
2239 | + | |
2240 | +unhandled_priv_inst: | |
2241 | + MAC_EXIT_SAVE( RVEC_PRIV_INST ) // r4 = opcode | |
2242 | + | |
2243 | +emulate_illegal_instr: | |
2244 | + rlwinm r2,r4,32-1,22,31 | |
2245 | + lwz r3,xMSR(r1) | |
2246 | + rlwinm r5,r4,14,24,28 // r5 = reg_num << 3 (instr. bits 6-10) | |
2247 | + rlwimi r2,r4,16,16,21 // r2 = opcode | |
2248 | + | |
2249 | + rlwinm r0,r2,0,~0x80 // clear mtspr/mfspr bit | |
2250 | + cmpwi r0,OPCODE(31,339) // mfspr/mtspr | |
2251 | + bne 1f | |
2252 | + | |
2253 | + rlwinm r7,r7,0,14,10 // clear srr1 bit 11-13 | |
2254 | + cmpwi cr1,r2,OPCODE(31,339) // mfspr | |
2255 | + oris r7,r7,0x4 // set bit 13 (privileged instr) | |
2256 | + | |
2257 | + beq- cr1,emulate_mfspr // r3=xMSR, r4=opcode, r5=reg_num | |
2258 | + b emulate_mtspr // must be mtspr | |
2259 | +1: | |
2260 | +#ifdef EMULATE_603 | |
2261 | + bl emulate_603_instr | |
2262 | +#endif | |
2263 | + MAC_EXIT_SAVE( RVEC_ILLEGAL_INST ) // r4 = opcode | |
2264 | + | |
2265 | + | |
2266 | +/************************************************************************/ | |
2267 | +/* mac exceptions */ | |
2268 | +/************************************************************************/ | |
2269 | + | |
2270 | + ///////////////////////////////////////////////////////////// | |
2271 | + // mac_trap | |
2272 | + // | |
2273 | + // r2 exception vector | |
2274 | + // r6 nip | |
2275 | + // r7 reason bits (0-15) | |
2276 | + // | |
2277 | + // r0,r2-r5 may be modified | |
2278 | + | |
2279 | +mac_irq_trap: | |
2280 | + li r2,0x500 | |
2281 | + li r7,0 // no reason bits | |
2282 | + b mac_trap | |
2283 | + | |
2284 | +mac_dec_trap: | |
2285 | + li r2,0x900 | |
2286 | + crclr FBIT_DecINT | |
2287 | + li r7,0 // no reason bits | |
2288 | + b mac_trap | |
2289 | + | |
2290 | + balign_32 | |
2291 | +mac_program_trap: // the reason bits already in r7 are used | |
2292 | + __BUMP("mac_trap") | |
2293 | + li r2,0x700 | |
2294 | +mac_trap: | |
2295 | + lwz r3,xMSR(r1) | |
2296 | + stw r6,xSRR0(r1) // mac-srr0 = nip | |
2297 | + mr r4,r3 // copy xMSR to SRR1 | |
2298 | + mr r6,r2 // new nip | |
2299 | + rlwinm r5,r3,25+1,31,31 // put MSR_IP (bit 25) in r5[31] | |
2300 | + rlwimi r4,r7,0,0,15 // copy reason bits from r7 to SRR1 | |
2301 | + rlwimi r4,r3,0,6,6 // copy MSR_VEC bit of xMSR to SRR1 | |
2302 | + stw r4,xSRR1(r1) // srr1 = (msr & (0xffff|MSR_VEC)) | (srr1 & ~(0xffff|MSR_VEC)) | |
2303 | + rlwinm r4,r3,0,25,25 // copy MSR_IP to xMSR | |
2304 | + neg r5,r5 // r5 = 0xffffffff * MSR_IP | |
2305 | + rlwimi r4,r3,0,19,19 // copy MSR_ME to xMSR | |
2306 | + rlwimi r6,r5,0,0,11 // insert exception prefix | |
2307 | + stw r4,xMSR(r1) | |
2308 | + GET_TICK_CNT(entry,"mac-expception") | |
2309 | + b msr_exception_return | |
2310 | + | |
2311 | +rvec_trace_trap: | |
2312 | + MAC_EXIT_SAVE( RVEC_TRACE_TRAP ) | |
2313 | + | |
2314 | + | |
2315 | +/************************************************************************/ | |
2316 | +/* decode privileged instruction */ | |
2317 | +/************************************************************************/ | |
2318 | + | |
2319 | + ///////////////////////////////////////////////////////////// | |
2320 | + // emulate_priv_instr | |
2321 | + // r4 opcode | |
2322 | + // r6,r7 nip/srr1 | |
2323 | + // | |
2324 | + // r0,r2-r5,lr free | |
2325 | + | |
2326 | + balign_32 | |
2327 | +emulate_priv_instr: | |
2328 | + rlwinm r2,r4,32-1,22,31 | |
2329 | + lwz r3,xMSR(r1) | |
2330 | + rlwinm r5,r4,14,24,28 // r5 = reg_num << 3 (instr. bits 6-10) | |
2331 | + rlwimi r2,r4,16,16,21 // r2 = opcode | |
2332 | + | |
2333 | + GET_TICK_CNT(entry,"get_inst") | |
2334 | + BUMP("decode_priv_inst") | |
2335 | + | |
2336 | + cmpwi cr1,r2,OPCODE(31,339) // mfspr (both user and supervisor mode) | |
2337 | + beq- cr1,emulate_mfspr // r3=xMSR, r4=opcode, r5=reg_num | |
2338 | + | |
2339 | + cmpwi cr2,r2,OPCODE(31,467) // mtspr (both user and supervisor mode) | |
2340 | + beq- cr2,emulate_mtspr | |
2341 | + | |
2342 | + andi. r3,r3,MSR_PR // only emulate in supervisor mode | |
2343 | + bne- mac_program_trap | |
2344 | + | |
2345 | + cmpwi cr3,r2,OPCODE(31,83) // mfmsr | |
2346 | + beq- cr3,emulate_mfmsr | |
2347 | + | |
2348 | + cmpwi cr0,r2,OPCODE(31,146) // mtmsr | |
2349 | + beq- cr0,emulate_mtmsr | |
2350 | + | |
2351 | + cmpwi cr1,r2,OPCODE(19,50) // rfi | |
2352 | + beq- cr1,emulate_rfi | |
2353 | + | |
2354 | + cmpwi cr2,r2,OPCODE(31,595) // mfsr | |
2355 | + beq- cr2,emulate_mfsr | |
2356 | + | |
2357 | + cmpwi cr3,r2,OPCODE(31,659) // mfsrin | |
2358 | + beq- cr3,emulate_mfsrin | |
2359 | + | |
2360 | + cmpwi cr0,r2,OPCODE(31,210) // mtsr | |
2361 | + beq- cr0,emulate_mtsr | |
2362 | + | |
2363 | + cmpwi cr1,r2,OPCODE(31,242) // mtsrin | |
2364 | + beq- cr1,emulate_mtsrin | |
2365 | + | |
2366 | + cmpwi cr2,r2,OPCODE(31,306) // tlbie | |
2367 | + beq- cr2,emulate_tlbie | |
2368 | + | |
2369 | + cmpwi cr3,r2,OPCODE(31,566) // tlbsync | |
2370 | + beq- cr3,emulate_tlbsync | |
2371 | + | |
2372 | + cmpwi cr0,r2,OPCODE(31,467) // dcbi | |
2373 | + beq- cr0,emulate_dcbi | |
2374 | +#ifdef EMULATE_603 | |
2375 | + cmpwi cr1,r2,OPCODE(31,978) // tlbld | |
2376 | + beq- cr1,emulate_tlbld | |
2377 | + | |
2378 | + cmpwi cr2,r2,OPCODE(31,1010) // tlbli | |
2379 | + beq- cr2,emulate_tlbli | |
2380 | +#endif | |
2381 | + // Program-trap, illegal instruction | |
2382 | + b unhandled_priv_inst // r4 = opcode | |
2383 | + | |
2384 | + | |
2385 | +#ifdef EMULATE_603 | |
2386 | +emulate_603_instr: | |
2387 | + rlwinm r2,r4,32-1,22,31 | |
2388 | + rlwimi r2,r4,16,16,21 // r2 = opcode | |
2389 | + | |
2390 | + cmpwi cr0,r2,OPCODE(31,978) // tlbld | |
2391 | + beq cr0,2f | |
2392 | + cmpwi cr1,r2,OPCODE(31,1010) // tlbli | |
2393 | + beq cr1,2f | |
2394 | + cmpwi cr2,r2,OPCODE(31,339) // mfspr | |
2395 | + beq cr2,1f | |
2396 | + cmpwi cr3,r2,OPCODE(31,467) // mtspr | |
2397 | + bnelr cr3 | |
2398 | +1: rlwinm r3,r4,32-16,27,31 | |
2399 | + rlwimi r3,r4,32-6,22,26 // r3 = spr# | |
2400 | + cmpwi r3,976 // first 603 SPR | |
2401 | + bltlr | |
2402 | + cmpwi r3,982 // last 603 SPR | |
2403 | + bgtlr | |
2404 | +2: | |
2405 | + rlwinm r7,r7,0,14,10 // clear bit 11-13 | |
2406 | + oris r7,r7,0x4 // set bit 13 | |
2407 | + b emulate_priv_instr | |
2408 | + | |
2409 | +#endif /* EMULATE_603 */ | |
2410 | + | |
2411 | + | |
2412 | +/************************************************************************/ | |
2413 | +/* mac register access */ | |
2414 | +/************************************************************************/ | |
2415 | + | |
2416 | +MACRO(LOAD_EMUGPR_IM, [dreg,ereg], [ | |
2417 | +.if _ereg <= 7 | |
2418 | + lwz _dreg,xGPR0+_ereg[]*4(r1) | |
2419 | +.else | |
2420 | + mr _dreg,rPREFIX[]_ereg | |
2421 | +.endif | |
2422 | +]) | |
2423 | + | |
2424 | +MACRO(STORE_EMUGPR_IM, [sreg,ereg], [ | |
2425 | +.if _ereg <= 7 | |
2426 | + stw _sreg,xGPR0+_ereg[]*4(r1) | |
2427 | +.else | |
2428 | + mr rPREFIX[]_ereg, _sreg | |
2429 | +.endif | |
2430 | +]) | |
2431 | + | |
2432 | + balign_32 | |
2433 | +store_gpr_table: | |
2434 | +mFORLOOP([i],0,31,[ | |
2435 | + STORE_EMUGPR_IM r0,i | |
2436 | + blr | |
2437 | +]) | |
2438 | + | |
2439 | +load_gpr_table: | |
2440 | +mFORLOOP([i],0,31,[ | |
2441 | + LOAD_EMUGPR_IM r0,i | |
2442 | + blr | |
2443 | +]) | |
2444 | + | |
2445 | +MACRO(EMU_LOAD_GPR, [reg, scr], [ | |
2446 | + LI_PHYS( _scr, load_gpr_table ) | |
2447 | + add rPREFIX[]_scr,_reg,rPREFIX[]_scr | |
2448 | + mtlr rPREFIX[]_scr | |
2449 | + blrl | |
2450 | +]) | |
2451 | + | |
2452 | +MACRO(EMU_STORE_GPR, [reg, scr], [ | |
2453 | + LI_PHYS( _scr, store_gpr_table ) | |
2454 | + add rPREFIX[]_scr,_reg,rPREFIX[]_scr | |
2455 | + mtlr rPREFIX[]_scr | |
2456 | + blrl | |
2457 | +]) | |
2458 | + | |
2459 | + | |
2460 | + | |
2461 | +/************************************************************************/ | |
2462 | +/* instruction emulation */ | |
2463 | +/************************************************************************/ | |
2464 | + | |
2465 | + ////////////////////////////////////////////////////////// | |
2466 | + // emulate_xxxxx | |
2467 | + // r3 xMSR | |
2468 | + // r4 opcode | |
2469 | + // r5 regnum<<3 (from opcode bits 6-10) | |
2470 | + // | |
2471 | + // May modify: r0,r2-r5 (lr) | |
2472 | + | |
2473 | +/********************************************************************/ | |
2474 | +emulate_mfmsr: | |
2475 | + lwz r0,xMSR(r1) | |
2476 | + EMU_STORE_GPR r5, /**/ R2 | |
2477 | + GET_TICK_CNT( entry, "mfmsr" ) | |
2478 | + b emulation_done | |
2479 | + | |
2480 | +/********************************************************************/ | |
2481 | +emulate_mfspr: // r3 = xMSR | |
2482 | + BUMP("emulate_mfspr") | |
2483 | + rlwimi r4,r4,32-10,21,25 // flip spr | |
2484 | + rlwinm r0,r3,32-14,31,31 // r0(bit31) = MSR_PR | |
2485 | + addi r3,r1,K_SPR_HOOKS | |
2486 | + rlwinm r2,r4,32-4,20,29 // r2 = spr# << 2 | |
2487 | + addi r4,r1,xSPR_BASE | |
2488 | + lwzx r3,r2,r3 // hook in r3 | |
2489 | + and. r0,r0,r3 // privileged SPR? | |
2490 | + bne- mac_program_trap | |
2491 | + lwzx r0,r2,r4 // value in r0 | |
2492 | + mtlr r3 | |
2493 | + blr // call hook | |
2494 | + | |
2495 | +/********************************************************************/ | |
2496 | +emulate_mtspr: // r3 = xMSR | |
2497 | + BUMP("emulate_mtspr") | |
2498 | + rlwimi r4,r4,32-10,21,25 // flip spr | |
2499 | + EMU_LOAD_GPR r5, /**/ R2 // value in r0 | |
2500 | + rlwinm r2,r4,32-4,20,29 // r2 = spr# << 2 | |
2501 | + addi r4,r1,K_SPR_HOOKS | |
2502 | + rlwinm r3,r3,32-14,31,31 // r3(bit31) = MSR_PR | |
2503 | + lwzx r4,r2,r4 // hook in r4 | |
2504 | + addi r5,r2,xSPR_BASE // r5+r1 points to SPR reg | |
2505 | + addi r4,r4,4 // branch to hook +4 | |
2506 | + and. r3,r3,r4 // privileged SPR? | |
2507 | + bne- mac_program_trap // privileged exception | |
2508 | + mtlr r4 // lsb is discarded... | |
2509 | + blr // call hook | |
2510 | + | |
2511 | + | |
2512 | +/********************************************************************/ | |
2513 | + balign_32 | |
2514 | +emulate_mtmsr: | |
2515 | + lwz r3,xMSR(r1) // r3 = old MSR | |
2516 | + LI_PHYS( R2, load_gpr_table ) | |
2517 | + add r2,r5,r2 | |
2518 | + mtlr r2 | |
2519 | + blrl // r0 = new MSR | |
2520 | + | |
2521 | + INC_NIP | |
2522 | + bl msr_altered | |
2523 | + | |
2524 | + GET_TICK_CNT(entry, "mtmsr") | |
2525 | + BUMP("emulate_mtmsr") | |
2526 | + | |
2527 | + beq+ cr1,emulation_done_noinc | |
2528 | + MAC_EXIT_SAVE( RVEC_MSR_POW ) // POW 1 => doze | |
2529 | + | |
2530 | + | |
2531 | +/********************************************************************/ | |
2532 | +emulate_rfi: | |
2533 | + BUMP("rfi") | |
2534 | + lis r4,(MSR_VEC)>>16 | |
2535 | + lwz r0,xSRR1(r1) | |
2536 | + ori r4,r4,0xffff | |
2537 | +#ifdef EMULATE_603 | |
2538 | + oris r4,r4,(MSR_TGPR)>>16 | |
2539 | +#endif | |
2540 | + lwz r3,xMSR(r1) // r3 = old MSR | |
2541 | + and r0,r0,r4 | |
2542 | + andc r5,r3,r4 | |
2543 | + lwz r6,xSRR0(r1) // new nip = SRR0 | |
2544 | + or r0,r0,r5 | |
2545 | + | |
2546 | + bl msr_altered // r0,r2-r5, r7 [srr1] updated | |
2547 | + | |
2548 | + GET_TICK_CNT(entry,"rfi") | |
2549 | + | |
2550 | + lwz r3,K_BREAK_FLAGS(r1) // break at rfi support | |
2551 | + andi. r3,r3,BREAK_RFI | |
2552 | + beq+ exception_return | |
2553 | + li r4,BREAK_RFI // r4 = flag causing the break | |
2554 | + MAC_EXIT_SAVE( RVEC_BREAK ) | |
2555 | + | |
2556 | + | |
2557 | +/********************************************************************/ | |
2558 | +#ifdef EMULATE_603 | |
2559 | +emulate_tlbli: | |
2560 | + LOADI r3,EXTERN(do_tlbli) | |
2561 | + b 1f | |
2562 | +emulate_tlbld: | |
2563 | + LOADI r3,EXTERN(do_tlbld) | |
2564 | + b 1f | |
2565 | +emulate_tlbie: | |
2566 | + LOADI r3,EXTERN(do_tlbie) | |
2567 | +1: INC_NIP | |
2568 | + rlwinm r5,r4,32-8,24,28 // r5 = #B << 3 | |
2569 | + EMU_LOAD_GPR r5, /**/ R2 // value ret. in r0 | |
2570 | + mr r4,r0 // r4 = ea | |
2571 | + b call_kernel_save | |
2572 | +#else | |
2573 | +emulate_tlbie: | |
2574 | + b emulation_done | |
2575 | +#endif /* EMULATE_603 */ | |
2576 | + | |
2577 | +/********************************************************************/ | |
2578 | +emulate_tlbsync: | |
2579 | + b emulation_done | |
2580 | + | |
2581 | +/********************************************************************/ | |
2582 | +emulate_dcbi: | |
2583 | + b unhandled_priv_inst // r4 = opcode | |
2584 | + | |
2585 | +/********************************************************************/ | |
2586 | +emulate_mfsrin: | |
2587 | + rlwinm r2,r4,32-8,24,28 // r2 = #B << 3 | |
2588 | + EMU_LOAD_GPR r2, /**/ R3 // r0 = reg B | |
2589 | + rlwinm r3,r0,6,26,29 // r3 = #sr << 2 | |
2590 | + b 1f | |
2591 | +emulate_mfsr: | |
2592 | + rlwinm r3,r4,32-14,26,29 // r3 = #sr << 2 | |
2593 | +1: addi r2,r1,xSEGR_BASE | |
2594 | + lwzx r0,r3,r2 | |
2595 | + EMU_STORE_GPR r5, /**/ R2 | |
2596 | + GET_TICK_CNT(entry, "mfsr") | |
2597 | + BUMP("mfsr_") | |
2598 | + b emulation_done | |
2599 | + | |
2600 | + | |
2601 | + | |
2602 | +/************************************************************************/ | |
2603 | +/* SPR - emulation */ | |
2604 | +/************************************************************************/ | |
2605 | + | |
2606 | + //////////////////////////////////////////////////////////// | |
2607 | + // read (offset 0) | |
2608 | + // r0 spr_value | |
2609 | + // r2 spr << 2 | |
2610 | + // r5 dreg << 3 | |
2611 | + // | |
2612 | + // write (offset 4) | |
2613 | + // r0 gpr_value | |
2614 | + // r2 spr << 2 | |
2615 | + // r5 spr offset (relative r1) | |
2616 | + // | |
2617 | + // Safe to modify: r2-r5, lr | |
2618 | + // NOT SAVED: ctr, xer | |
2619 | + | |
2620 | +/********************************************************************/ | |
2621 | +simple_mfspr: | |
2622 | + EMU_STORE_GPR r5, /**/ R3 | |
2623 | + GET_TICK_CNT(entry,"simple_mfspr") | |
2624 | + b emulation_done | |
2625 | + | |
2626 | +GLOBAL_SYMBOL(r__spr_read_write): | |
2627 | +spr_read_write: | |
2628 | + b simple_mfspr | |
2629 | + stwx r0,r5,r1 // value in r0 | |
2630 | + GET_TICK_CNT(entry,"simple_mtspr") | |
2631 | + b emulation_done | |
2632 | + | |
2633 | + | |
2634 | +/********************************************************************/ | |
2635 | +GLOBAL_SYMBOL(r__spr_read_only): | |
2636 | +spr_read_only: | |
2637 | + b simple_mfspr // allow read | |
2638 | + b emulation_done // ignore write | |
2639 | + | |
2640 | +/********************************************************************/ | |
2641 | +GLOBAL_SYMBOL(r__spr_illegal): | |
2642 | +spr_illegal: | |
2643 | + nop // spr read entry | |
2644 | + rlwinm r7,r7,0,15,10 // clear srr1 bit 11-14 | |
2645 | + oris r7,r7,0x8 // set bit 12 (privileged instr) | |
2646 | + b mac_program_trap | |
2647 | + | |
2648 | + | |
2649 | +/********************************************************************/ | |
2650 | +unhandled_spr_read: | |
2651 | + srwi r4,r2,2 | |
2652 | + srwi r5,r5,3 | |
2653 | + // r4 = spr# | |
2654 | + // r5 = dest gpr | |
2655 | + MAC_EXIT_SAVE( RVEC_SPR_READ ) | |
2656 | + | |
2657 | +unhandled_spr: | |
2658 | + b unhandled_spr_read // read hook (offs 0) | |
2659 | +unhandled_spr_write: // write hook (offs 4) | |
2660 | + srwi r4,r2,2 | |
2661 | + mr r5,r0 | |
2662 | + // r4 = spr# | |
2663 | + // r5 = register-value | |
2664 | + MAC_EXIT_SAVE( RVEC_SPR_WRITE ) | |
2665 | + | |
2666 | +/********************************************************************/ | |
2667 | +spr_bat: | |
2668 | + b simple_mfspr // read has no side-effects | |
2669 | + INC_NIP | |
2670 | + LOADI r3,EXTERN(do_mtbat) | |
2671 | + bl save_middle_regs // Must do this before touching r6-r12 | |
2672 | + srwi r4,r2,2 // r4 = spr# | |
2673 | + mr r5,r0 // r5 = value | |
2674 | + li r6,0 // not forced | |
2675 | + b call_kernel | |
2676 | + | |
2677 | +/********************************************************************/ | |
2678 | +spr_sdr1: | |
2679 | + b simple_mfspr // read has no side-effects | |
2680 | + INC_NIP | |
2681 | + LOADI r3,EXTERN(do_mtsdr1) | |
2682 | + mr r4,r0 // r4 = value | |
2683 | + b call_kernel_save | |
2684 | + | |
2685 | + | |
2686 | + | |
2687 | + | |
2688 | +/************************************************************************/ | |
2689 | +/* handle MSR changes */ | |
2690 | +/************************************************************************/ | |
2691 | + | |
2692 | + //////////////////////////////////////////////////////////// | |
2693 | + // msr_exception_return (exception taken) | |
2694 | + // | |
2695 | + // r6, r7: nip / srr1 | |
2696 | + // | |
2697 | + // modifies: r0,r2-r5 (r7 updated) | |
2698 | + | |
2699 | + balign_16 | |
2700 | +msr_exception_return: | |
2701 | + addi r3,r1,K_UNMAPPED_SR_BASE // set unmapped context | |
2702 | + li r7,(MSR_ME | MSR_SE | MSR_IR | MSR_DR | MSR_PR) | |
2703 | + stw r3,K_CUR_SR_BASE(r1) | |
2704 | + li r5,(fb_DbgTrace | fb_Trace) | |
2705 | + ori r7,r7,MSR_EE | |
2706 | + | |
2707 | + bt+ FBIT_DbgTrace, 1f | |
2708 | + li r5,0 | |
2709 | + rlwinm r7,r7,0,~MSR_SE | |
2710 | +1: | |
2711 | + stw r3,K_SR_DATA(r1) | |
2712 | + li r4,fb_LoadSegreg | |
2713 | + | |
2714 | + stw r3,K_SR_INST(r1) | |
2715 | + mtcrf TRACE_CR_FIELD,r5 // set singlestep bits [cr6] | |
2716 | + mtcrf MMU_CR_FIELD,r4 | |
2717 | + | |
2718 | + stw r7,K_MSR(r1) | |
2719 | + b exception_return | |
2720 | + | |
2721 | + | |
2722 | + //////////////////////////////////////////////////////////// | |
2723 | + // msr_altered | |
2724 | + // | |
2725 | + // r6, r7: nip / srr1 | |
2726 | + // | |
2727 | + // r0 = new msr | |
2728 | + // r3 = old msr | |
2729 | + // | |
2730 | + // Sets cr1.ne if we MSR_POW is set | |
2731 | + // | |
2732 | + // M: r2-r5 (r7 updated). | |
2733 | + // r0 may _NOT_ be modified | |
2734 | + | |
2735 | +#define MSR_CLEARBITS (MSR_FP | MSR_FE0 | MSR_FE1 | MSR_BE | MSR_SE) | |
2736 | +#define MSR_COPYBITS (MSR_BE | MSR_SE) | |
2737 | + | |
2738 | + balign_32 | |
2739 | +msr_altered: | |
2740 | +#ifdef EMULATE_603 | |
2741 | + bf+ FBIT_603_AltGPR,7f // 603 alternate GPR support | |
2742 | + rlwinm. r5,r0,0,MSR_TGPR | |
2743 | + bne+ 7f | |
2744 | + lwz r2,xGPRSAVE0_603(r1) // MSR_TGPR cleared... | |
2745 | + lwz r4,xGPRSAVE1_603(r1) | |
2746 | + lwz r5,xGPRSAVE2_603(r1) | |
2747 | + stw r2,xGPR0(r1) | |
2748 | + lwz r2,xGPRSAVE3_603(r1) | |
2749 | + stw r4,xGPR1(r1) | |
2750 | + stw r5,xGPR2(r1) | |
2751 | + stw r2,xGPR3(r1) | |
2752 | + crclr FBIT_603_AltGPR | |
2753 | +7: | |
2754 | +#endif | |
2755 | + li r7,(MSR_ME | MSR_SE | MSR_IR | MSR_DR | MSR_PR) | |
2756 | + stw r0,xMSR(r1) | |
2757 | + xor r3,r3,r0 // r3 == MSR bit toggle | |
2758 | + bt- FBIT_IRQPending,test_for_irq // M: r2 | |
2759 | +irq_test_ret: | |
2760 | + rlwinm r4,r0,0,MSR_POW // MSR_POW | |
2761 | + ori r7,r7,MSR_EE | |
2762 | + andi. r3,r3,(MSR_DR|MSR_IR|MSR_PR) // MMU change (cr unused)? | |
2763 | + bt- FBIT_DecINT,test_for_dec // M: r2 | |
2764 | +dec_test_ret: | |
2765 | + cmpwi cr1,r4,0 // MSR_POW set? | |
2766 | + li r2,(fb_DbgTrace | fb_Trace) | |
2767 | + cmpwi cr2,r3,0 | |
2768 | + bt- FBIT_DbgTrace,1f | |
2769 | + rlwinm r2,r0,(21+32-FBIT_Trace),fb_Trace // MSR_SE[21] -> FBIT_Trace | |
2770 | + rlwimi r7,r0,0,(MSR_SE|MSR_BE) // no debugger; copy MSR_SE and MSR_BE | |
2771 | +1: | |
2772 | + stw r7,K_MSR(r1) | |
2773 | + mtcrf TRACE_CR_FIELD,r2 // set singlestep bits [cr6] | |
2774 | + | |
2775 | + bne cr2,1f // bnelr is slower... | |
2776 | + blr | |
2777 | +1: | |
2778 | + /* MMU change */ | |
2779 | + BUMP("MMU-change") | |
2780 | + | |
2781 | + andi. r3,r0,(MSR_IR | MSR_DR) // IR DR part of index | |
2782 | + addi r5,r1,K_MSR_SR_TABLE | |
2783 | + addi r4,r3,MSR_DR // splitmode (MSR_DR != MSR_IR) testing | |
2784 | + rlwimi r3,r0,32-8,25,25 // [PR IR DR] index to K_MSR_SR_TABLE | |
2785 | + lwzux r3,r5,r3 // set sr bases from K_MSR_SR_TABLE | |
2786 | + andi. r4,r4,MSR_IR // non-zero if in splitmode | |
2787 | + lwz r2,4(r5) | |
2788 | + li r4,(fb_InSplitmode | fb_LoadSegreg | fb_PrepareSplitmode) | |
2789 | + lwz r5,8(r5) | |
2790 | + stw r3,K_CUR_SR_BASE(r1) // new sr base in r3 (used below) | |
2791 | + stw r2,K_SR_DATA(r1) | |
2792 | + bne- 1f | |
2793 | + li r4,fb_LoadSegreg // cur_sr_base changed | |
2794 | +1: stw r5,K_SR_INST(r1) | |
2795 | + mtcrf MMU_CR_FIELD,r4 | |
2796 | + blr | |
2797 | + | |
2798 | +test_for_irq: | |
2799 | + BUMP("test-for-irq") | |
2800 | + and r2,r3,r0 // check whether we are turning external interrupts on | |
2801 | + andi. r2,r2,MSR_EE // we need to recheck IRQs in userspace then | |
2802 | + beq+ 1f | |
2803 | + lwz r4,xHOSTIRQ_ACTIVE_CNT(r1) | |
2804 | + cmpwi r4,0 // only return if some host irq is up | |
2805 | + beq+ 1f | |
2806 | + MAC_EXIT_SAVE(RVEC_CHECK_IRQS) | |
2807 | + | |
2808 | +1: andi. r2,r0,MSR_EE | |
2809 | + beq irq_test_ret | |
2810 | + b mac_irq_trap | |
2811 | + | |
2812 | +test_for_dec: | |
2813 | + BUMP("test-for-dec") | |
2814 | + andi. r2,r0,MSR_EE | |
2815 | + beq dec_test_ret | |
2816 | + b mac_dec_trap | |
2817 | + | |
2818 | +force_msr_altered: | |
2819 | + BUMP("force-msr-altered") | |
2820 | + lwz r0,xMSR(r1) // r0 = new MSR | |
2821 | + xori r3,r0,(MSR_DR|MSR_IR) // r3 = faked old MSR | |
2822 | + b msr_altered // might throw an exception... | |
2823 | + | |
2824 | + // msr_altered( kv ) | |
2825 | +GLOBAL_SYMBOL(r__msr_altered): | |
2826 | + lwz r5,xFLAG_BITS(r3) | |
2827 | + ori r5,r5,fb_MsrModified | |
2828 | + stw r5,xFLAG_BITS(r3) | |
2829 | + blr | |
2830 | + | |
2831 | + | |
2832 | +/************************************************************************/ | |
2833 | +/* initialize special purpose register table */ | |
2834 | +/************************************************************************/ | |
2835 | + | |
2836 | +MACRO(SPR_HOOK, [spr, hook], [ LI_PHYS( R8, _hook ) ; stw r8,(((_spr)*4)+K_SPR_HOOKS)(r3) ]) | |
2837 | + | |
2838 | +// The LSB of a SPR hook specifies that the SPR is privileged (these bits are | |
2839 | +// set from C-code). | |
2840 | + | |
2841 | + // r3 = kvars | |
2842 | +GLOBAL_SYMBOL(r__initialize_spr_table): | |
2843 | + LI_PHYS( R7, unhandled_spr ) | |
2844 | + addi r8,r3,K_SPR_HOOKS-4 | |
2845 | + li r9,1024 | |
2846 | + mtctr r9 | |
2847 | +1: stwu r7,4(r8) | |
2848 | + bdnz 1b | |
2849 | + | |
2850 | + // XXX for now... | |
2851 | + SPR_HOOK TBWU, spr_read_write | |
2852 | + SPR_HOOK TBWL, spr_read_write | |
2853 | + | |
2854 | + // SPRs that have side effects | |
2855 | + SPR_HOOK SDR1, spr_sdr1 | |
2856 | + SPR_HOOK DEC, spr_dec | |
2857 | + | |
2858 | + // BATs | |
2859 | + mFORLOOP([nn],0,15,[ | |
2860 | + SPR_HOOK eval(nn+IBAT0U), spr_bat | |
2861 | + ]) | |
2862 | + blr | |
2863 | + | |
2864 | + | |
2865 | +/************************************************************************/ | |
2866 | +/* initialize msr segment register table */ | |
2867 | +/************************************************************************/ | |
2868 | + | |
2869 | + ///////////////////////////////////////////////////////////// | |
2870 | + // initialize_sr_offs_table | |
2871 | + // | |
2872 | + // Copy sr_offs_table to K_MSR_SR_TABLE | |
2873 | + // r1 is added to each element | |
2874 | + | |
2875 | +initialize_msr_sr_table: | |
2876 | + mflr r8 // Get address of table | |
2877 | + bl sr_offs_table | |
2878 | + mflr r3 | |
2879 | + mtlr r8 | |
2880 | + | |
2881 | + li r5,4*8 // #words in table | |
2882 | + mtctr r5 | |
2883 | + addi r3,r3,-4 | |
2884 | + addi r4,r1,K_MSR_SR_TABLE-4 | |
2885 | +1: | |
2886 | + lwzu r6,4(r3) | |
2887 | + add r6,r6,r1 // And add r1 | |
2888 | + stwu r6,4(r4) | |
2889 | + bdnz 1b | |
2890 | + blr | |
2891 | + | |
2892 | + // Used to construct msr_sr_table (mbase is added) | |
2893 | +sr_offs_table: | |
2894 | + blrl | |
2895 | + /* K_CUR_SR_BASE, K_SR_DATA_BASE, K_SR_INST_BASE, dummy */ | |
2896 | + | |
2897 | + .long K_UNMAPPED_SR_BASE, K_UNMAPPED_SR_BASE, K_UNMAPPED_SR_BASE, 0 | |
2898 | + .long K_SPLIT_SR_BASE, K_SV_SR_BASE, K_UNMAPPED_SR_BASE, 0 /* DR */ | |
2899 | + .long K_SPLIT_SR_BASE, K_UNMAPPED_SR_BASE, K_SV_SR_BASE, 0 /* IR */ | |
2900 | + .long K_SV_SR_BASE, K_SV_SR_BASE, K_SV_SR_BASE, 0 /* DR|IR */ | |
2901 | + | |
2902 | + .long K_UNMAPPED_SR_BASE, K_UNMAPPED_SR_BASE, K_UNMAPPED_SR_BASE, 0 /* PR */ | |
2903 | + .long K_SPLIT_SR_BASE, K_USER_SR_BASE, K_UNMAPPED_SR_BASE, 0 /* PR|DR */ | |
2904 | + .long K_SPLIT_SR_BASE, K_UNMAPPED_SR_BASE, K_USER_SR_BASE, 0 /* PR|IR */ | |
2905 | + .long K_USER_SR_BASE, K_USER_SR_BASE, K_USER_SR_BASE, 0 /* PR|DR|IR */ | |
2906 | --- /dev/null | |
2907 | +++ b/drivers/macintosh/mol/asm-files/entry.S | |
2908 | @@ -0,0 +1,433 @@ | |
2909 | +/* | |
2910 | + * Creation Date: <2001/01/30 00:22:35 samuel> | |
2911 | + * Time-stamp: <2004/03/07 13:33:39 samuel> | |
2912 | + * | |
2913 | + * <entry.S> | |
2914 | + * | |
2915 | + * Emulator/mac switching | |
2916 | + * | |
2917 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
2918 | + * | |
2919 | + * This program is free software; you can redistribute it and/or | |
2920 | + * modify it under the terms of the GNU General Public License | |
2921 | + * as published by the Free Software Foundation | |
2922 | + * | |
2923 | + */ | |
2924 | + | |
2925 | +/* Short note about DEC. Due to the kernel implementation of the DEC | |
2926 | + * exception handler (and get_time_of_day) in the 2.3/2.4 kernel, we | |
2927 | + * must try to maintain coherency between DEC and TB. In any case, | |
2928 | + * we must NEVER let DEC tick faster than TB, or get_time_of_day will | |
2929 | + * occasionally return bogus values (the result is usually | |
2930 | + * misbehaving X). | |
2931 | + */ | |
2932 | + | |
2933 | +/************************************************************************/ | |
2934 | +/* Mac Entry */ | |
2935 | +/************************************************************************/ | |
2936 | + | |
2937 | + ////////////////////////////////////////////////////////// | |
2938 | + // mac_entry_initialize | |
2939 | + // | |
2940 | + // Run once in order to store certain things (segment | |
2941 | + // registers and NIP) | |
2942 | + // | |
2943 | + // sprg1 userspace stack | |
2944 | + // r6 emulator return point after 'call_kernel' | |
2945 | + // | |
2946 | + // Safe to modify: r0-r12, lr, ctr | |
2947 | + | |
2948 | +mac_entry_initialize: | |
2949 | + __ZERO_TICK_CNT(entry) | |
2950 | + | |
2951 | + // Save emulator return point (skip over illegal inst) | |
2952 | + mfsrr0 r5 | |
2953 | + addi r5,r5,4 | |
2954 | + stw r5,K_EMULATOR_NIP(r1) // This sets the return point once and for all | |
2955 | + stw r2,K_EMULATOR_TOC(r1) // r2==TOC (not on linux though) | |
2956 | + stw r6,K_EMULATOR_KCALL_NIP(r1) // Return point after 'call_kernel' | |
2957 | + mfsrr1 r6 | |
2958 | + mfsprg_a1 r3 | |
2959 | + stw r6,K_EMULATOR_MSR(r1) // we want to return through mac_exit | |
2960 | + stw r3,K_EMULATOR_STACK(r1) | |
2961 | + | |
2962 | + lwz r3,xFLAG_BITS(r1) // Best to initialize the flag bits | |
2963 | + mtcr r3 | |
2964 | + | |
2965 | + // msr to be used in mac-mode | |
2966 | + LOADI r3,(MSR_ME | MSR_IR | MSR_DR | MSR_PR | MSR_EE) | |
2967 | + stw r3,K_MSR(r1) | |
2968 | + | |
2969 | + PERF_MONITOR_SETUP /**/ r4 | |
2970 | + | |
2971 | + addi r3,r1,K_EMULATOR_SR // Save segment registers | |
2972 | + SAVE_SEGMENT_REGS r3, /**/ r4,r5 | |
2973 | + SAVE_IBATS K_IBAT0U_SAVE, /**/ r3 // And save linux BAT registers | |
2974 | + SAVE_DBATS K_DBAT0U_SAVE, /**/ r3 | |
2975 | + | |
2976 | + bl initialize_msr_sr_table | |
2977 | + | |
2978 | + addi r3,r1,K_EMULATOR_SR | |
2979 | + LOAD_SEGMENT_REGS r3, /**/ r4,r5 | |
2980 | + | |
2981 | + li r3,RVEC_EXIT | |
2982 | + b exit_ | |
2983 | + | |
2984 | + | |
2985 | + //////////////////////////////////////////////////////////////////// | |
2986 | + // mac_entry [ENTRYPOINT] | |
2987 | + // | |
2988 | + // sprg1 userspace stack | |
2989 | + // r4 MOL_ENTRY_R4_MAGIC | |
2990 | + // r5 magic | |
2991 | + // r6 call_kernel return point (if initializing) | |
2992 | + // r7 session number | initialize flag | |
2993 | + // | |
2994 | + // srr1 emulator msr | |
2995 | + // r13-r31 mac gprs | |
2996 | + // fr14-fr31 mac fp registers | |
2997 | + // fr0-fr12 mac fp registers (see xFPU_STATE) | |
2998 | + | |
2999 | +1: li r4,1 | |
3000 | + stw r4,ST_MAGIC(r1) | |
3001 | +2: mtcr r3 // restore registers | |
3002 | + CONTINUE_TRAP( 0x700 ) // not MOL, take the trap | |
3003 | + | |
3004 | + balign_32 | |
3005 | +mac_entry: | |
3006 | + lis_svh R1,SPECVAR_SESSION_TABLE | |
3007 | + cmpwi r4,MOL_ENTRY_R4_MAGIC // MOL switch magic. | |
3008 | + ori_svl R1,R1,SPECVAR_SESSION_TABLE | |
3009 | + bne- 2b | |
3010 | + lwz r4,ST_MAGIC(r1) // check that the magic match | |
3011 | + cmplwi r5,1 // and is greater than 1 | |
3012 | + cmpw cr1,r5,r4 | |
3013 | + ble- 2b | |
3014 | + addi r5,r1,ST_KVARS_PH // get kvars for this session | |
3015 | + rlwinm r4,r7,2,((MAX_NUM_SESSIONS-1)*4) | |
3016 | + bne- cr1,1b // r1 must point to session table | |
3017 | + lwzx r1,r4,r5 // set r1 to kvars | |
3018 | + cmpwi cr1,r1,0 | |
3019 | + cmplwi r7,MAX_NUM_SESSIONS | |
3020 | + beq- cr1,2b // kvars == NULL | |
3021 | + bge- mac_entry_initialize // initialize flag set | |
3022 | + | |
3023 | + // ===================================================================== | |
3024 | + // entrypoint | |
3025 | + // ===================================================================== | |
3026 | + | |
3027 | + __ZERO_TICK_CNT(entry) | |
3028 | + TRACE(0x1111, "mac_entry") | |
3029 | + | |
3030 | + // Save emulator registers (r1,msr) and restore flag bits | |
3031 | + mfsprg_a1 r3 | |
3032 | + lwz r4,xFLAG_BITS(r1) | |
3033 | + stw r3,K_EMULATOR_STACK(r1) | |
3034 | + mfsrr1 r6 | |
3035 | + mtcr r4 | |
3036 | + stw r6,K_EMULATOR_MSR(r1) // The MSR_FP/MSR_VEC bits are of interest... | |
3037 | + | |
3038 | + // Setup mac-environment | |
3039 | + | |
3040 | + btl FBIT_RecalcDecInt, recalc_int_stamp // M: r0,r2-r5 | |
3041 | + bl set_mac_context // M: r0,r2-r12,XER | |
3042 | + bl set_mol_dec // M: r0,r2-r5 | |
3043 | + | |
3044 | + crset FBIT_LoadSegreg // Load segment registers below | |
3045 | + | |
3046 | + RESTORE_MIDDLE_REGS // Loads r6,r7 (nip/msr) r8-r12, ctr, xer, | |
3047 | + | |
3048 | + rlwinm r7,r7,0,~MSR_VEC // We always clear MSR_VEC (MSR_FP should be off already) | |
3049 | + stw r7,K_MSR(r1) // (enabling MSR_VEC is relatively cheap) | |
3050 | + btl- FBIT_MsrModified,msr_altered_entry | |
3051 | + | |
3052 | + GET_TICK_CNT(entry, "mac_entry") | |
3053 | + | |
3054 | + bt- FBIT_DecINT,test_for_dec_int // check for DEC interrupts | |
3055 | + b exception_return | |
3056 | + | |
3057 | +test_for_dec_int: | |
3058 | + lwz r3,xMSR(r1) | |
3059 | + rlwinm. r3,r3,0,MSR_EE // MSR_EE is set? | |
3060 | + bne mac_dec_trap // if so take a DEC interrupt | |
3061 | + b exception_return | |
3062 | + | |
3063 | +msr_altered_entry: | |
3064 | + crclr FBIT_MsrModified | |
3065 | + b force_msr_altered | |
3066 | + | |
3067 | + | |
3068 | + ///////////////////////////////////////////////////////////// | |
3069 | + // All paths back to mac-mode goes through one of these | |
3070 | + // functions. | |
3071 | + // | |
3072 | + // emulation_done | |
3073 | + // emulation_done_noinc | |
3074 | + // exception_return | |
3075 | + | |
3076 | + balign_32 | |
3077 | +emulation_done: | |
3078 | + addi r6,r6,4 // increase NIP | |
3079 | +emulation_done_noinc: | |
3080 | + bt- FBIT_Trace, rvec_trace_trap | |
3081 | + GET_TICK_CNT(entry,"emulation_done") | |
3082 | +exception_return: | |
3083 | + btl- FBIT_LoadSegreg,reload_sr // M: r3-r5, r6=nip | |
3084 | + mtsrr1 r7 // setup SRR1 | |
3085 | + lwz r0,xCR(r1) | |
3086 | + lwz r3,xLINK(r1) | |
3087 | + mtsrr0 r6 | |
3088 | + lwz r4,xGPR4(r1) | |
3089 | + lwz r5,xGPR5(r1) | |
3090 | + mfcr r2 // Save flag bits | |
3091 | + lwz r6,xGPR6(r1) | |
3092 | + lwz r7,xGPR7(r1) | |
3093 | + mtlr r3 | |
3094 | + stw r2,xFLAG_BITS(r1) | |
3095 | + lwz r2,xGPR2(r1) | |
3096 | + lwz r3,xGPR3(r1) | |
3097 | + mtcr r0 | |
3098 | + lwz r0,xGPR0(r1) | |
3099 | + __GET_TICK_CNT(entry,"asm-all") // performance measurements | |
3100 | + __BUMP("asm-all") | |
3101 | + lwz r1,xGPR1(r1) | |
3102 | + rfi | |
3103 | + | |
3104 | + | |
3105 | +/************************************************************************/ | |
3106 | +/* Exit Mac-Mode Paths */ | |
3107 | +/************************************************************************/ | |
3108 | + | |
3109 | + // THESE ARE _ALL_ THE POSSIBLE EXIT PATHS. KEEP IT THAT WAY | |
3110 | + // OR HAVE A *VERY GOOD* REASON TO INTRODUCE A NEW ONE. | |
3111 | + | |
3112 | + ///////////////////////////////////////////////////////// | |
3113 | + // giveup_fpu | |
3114 | + // | |
3115 | + // Save fpscr and fpr13 and clear the MSR_FP bit. | |
3116 | + // Restore the emulator fpscr value. | |
3117 | + // | |
3118 | + // IMPORTANT: Call this function only if FBIT_FPUInUse is set | |
3119 | + // | |
3120 | + // modifies: r7,r8 (turns on MSR_FP if FP is set in K_MSR) | |
3121 | + | |
3122 | +giveup_fpu: | |
3123 | + li r8,MSR_FP | MSR_FE0 | MSR_FE1 | |
3124 | + lwz r7,K_MSR(r1) | |
3125 | + andc r8,r7,r8 // Clear MSR_FEx bits | |
3126 | + stw r8,K_MSR(r1) | |
3127 | + | |
3128 | + mfmsr r7 // Temporary enable FPU in order to | |
3129 | + ori r8,r7,MSR_FP // save fpscr and fpr13 | |
3130 | + mtmsr r8 | |
3131 | + isync | |
3132 | + stfd fr13,xFPR13(r1) | |
3133 | + mffs fr13 | |
3134 | + stfd fr13,xFPSCR-4(r1) | |
3135 | + li r7,FPU_STATE_DIRTY | |
3136 | + lfd fr13,xEMULATOR_FPSCR-4(r1) // We must restore FPSCR before since the emulator might | |
3137 | + mtfsf 0xff,fr13 // use the FPU at any time, for instance in a signal handler. | |
3138 | + stw r7,xFPU_STATE(r1) // Go to FPU_STATE_DIRTY | |
3139 | + | |
3140 | + crclr FBIT_FPUInUse // FPU no longer in use | |
3141 | + blr | |
3142 | + | |
3143 | + | |
3144 | + //////////////////////////////////////////////////////// | |
3145 | + // PREPARE_ERET | |
3146 | + // | |
3147 | + // M: r0,r2, r9-r11 | |
3148 | + | |
3149 | +MACRO(PREP_ERET,[nip_variable], [ | |
3150 | + btl FBIT_MolDecLoaded, set_kernel_dec // M: r0,r2,r9-r11 | |
3151 | + | |
3152 | + lwz r10,_nip_variable[](r1) | |
3153 | + mfcr r9 | |
3154 | + lwz r11,K_EMULATOR_MSR(r1) | |
3155 | + mtsrr0 r10 | |
3156 | + lwz r2,K_EMULATOR_TOC(r1) | |
3157 | + stw r9,xFLAG_BITS(r1) | |
3158 | + mtsrr1 r11 | |
3159 | +]) | |
3160 | + | |
3161 | + //////////////////////////////////////////////////////// | |
3162 | + // mac_exit (return to emulator) | |
3163 | + // r3 RVEC return code | |
3164 | + // | |
3165 | + // On stack: nip, ctr, lr, xer, r0-r12 | |
3166 | + // In registers: r13-r31 | |
3167 | + | |
3168 | +mac_exit: | |
3169 | + TRACE(0x2220, "mac_exit") | |
3170 | + bl set_emulator_context // M: r0,r2,r7-r11,XER | |
3171 | +exit_: | |
3172 | + PREP_ERET K_EMULATOR_NIP // M: r0-r2,r9-r11 | |
3173 | + GET_TICK_CNT(entry, "mac_exit") | |
3174 | + lwz r1,K_EMULATOR_STACK(r1) | |
3175 | + rfi | |
3176 | + | |
3177 | + | |
3178 | + //////////////////////////////////////////////////////// | |
3179 | + // take_exception (take a linux exception) | |
3180 | + // | |
3181 | + // On stack: nip, ctr, lr, xer, r0-r12 | |
3182 | + // In registers: r13-r31 | |
3183 | + | |
3184 | +take_exception: | |
3185 | + TRACE(0x2221, "take_exception") | |
3186 | + | |
3187 | + mflr r12 | |
3188 | + bl set_emulator_context // M: r0,r2,r7-r11,XER | |
3189 | + | |
3190 | + PREP_ERET K_EMULATOR_NIP // M: r0,r2,r9-r11 | |
3191 | + GET_TICK_CNT(entry, "take_exception") | |
3192 | + lwz r1,K_EMULATOR_STACK(r1) | |
3193 | + mtlr r12 | |
3194 | + li r3,RVEC_NOP | |
3195 | + blr | |
3196 | + | |
3197 | + | |
3198 | + ////////////////////////////////////////////////////////////// | |
3199 | + // call_kernel (call mol kernel routine) | |
3200 | + // r3 kernel routine | |
3201 | + // r4..r6 args | |
3202 | + // | |
3203 | + // On stack: nip, ctr, lr, xer, r0-r12 | |
3204 | + // In registers: r13-r31 | |
3205 | + | |
3206 | +#ifdef __linux__ | |
3207 | +call_kernel_save: | |
3208 | + bl save_middle_regs // saves r8-r11, nip, ctr, xer | |
3209 | +call_kernel: | |
3210 | + bl set_emulator_context // M: r0,r2,r7-r11,XER | |
3211 | + | |
3212 | + TRACE(0x2222, "call_kernel") | |
3213 | + | |
3214 | + lwz r8,K_KERNEL_VARS(r1) // r8 = kvars (lvptr) | |
3215 | + PREP_ERET K_EMULATOR_KCALL_NIP // M: r0,r2,r9-r11 | |
3216 | + GET_TICK_CNT(entry, "call_kernel_save") | |
3217 | + lwz r1,K_EMULATOR_STACK(r1) | |
3218 | + ba 0x2f00 // MOL trampoline | |
3219 | +#endif | |
3220 | + | |
3221 | +/************************************************************************/ | |
3222 | +/* Set Mac/Emulator Context */ | |
3223 | +/************************************************************************/ | |
3224 | + | |
3225 | + ////////////////////////////////////////////////////////////// | |
3226 | + // set_mac_context [r0,r2-r12, ctr, --->XER<---] | |
3227 | + // | |
3228 | + // - clear BATs (except DBAT0) | |
3229 | + // - setup sprgs | |
3230 | + // - reload_sr loads segment registers later on | |
3231 | + // | |
3232 | + // Currently unmodified r8-r12, ctr | |
3233 | + | |
3234 | +set_mac_context: | |
3235 | + // Save and setup SPRG2 (magic) and SPRG3 (mol stack) | |
3236 | + mfsprg_a2 r6 | |
3237 | + mfsprg_a3 r7 | |
3238 | + stw r6,K_EMULATOR_SPRG2(r1) | |
3239 | + stw r7,K_EMULATOR_SPRG3(r1) | |
3240 | + li r2,MOL_SPRG2_MAGIC | |
3241 | + mtsprg_a3 r1 | |
3242 | + mtsprg_a2 r2 | |
3243 | + | |
3244 | + li r4,0 | |
3245 | + mtspr IBAT0U,r4 | |
3246 | + mtspr IBAT1U,r4 | |
3247 | + mtspr IBAT2U,r4 | |
3248 | + mtspr IBAT3U,r4 | |
3249 | + // DBAT0 set from reload_sr | |
3250 | + mtspr DBAT1U,r4 | |
3251 | + mtspr DBAT2U,r4 | |
3252 | + mtspr DBAT3U,r4 | |
3253 | +#ifdef __darwin__ | |
3254 | + lwz r4,K_MOL_SDR1(r1) | |
3255 | + mtsdr1 r4 | |
3256 | +#endif | |
3257 | + blr | |
3258 | + | |
3259 | + | |
3260 | + /////////////////////////////////////////////////////////////// | |
3261 | + // set_emulator_context [r0,r2,r7-r11,cr, --->XER<---] | |
3262 | + // | |
3263 | + // - load segr 0-15 with emulator context | |
3264 | + // - restore BATs | |
3265 | + // - restore DEC register | |
3266 | + | |
3267 | +set_emulator_context: | |
3268 | + lwz r0,K_EMULATOR_SPRG2(r1) | |
3269 | + lwz r2,K_EMULATOR_SPRG3(r1) | |
3270 | + mtsprg_a2 r0 | |
3271 | + mtsprg_a3 r2 | |
3272 | + | |
3273 | + // Restore segment registers | |
3274 | + addi r8,r1,K_EMULATOR_SR | |
3275 | + LOAD_SEGMENT_REGS r8, /**/ r2,r10 | |
3276 | + | |
3277 | + // BATS, r11 = linux DEC | |
3278 | + | |
3279 | + lwz r7,K_IBAT0U_SAVE(r1) | |
3280 | + mtspr IBAT0U,r7 | |
3281 | + lwz r2,K_IBAT1U_SAVE(r1) | |
3282 | + mtspr IBAT1U,r2 | |
3283 | + lwz r7,K_IBAT2U_SAVE(r1) | |
3284 | + mtspr IBAT2U,r7 | |
3285 | + lwz r2,K_IBAT3U_SAVE(r1) | |
3286 | + mtspr IBAT3U,r2 | |
3287 | + | |
3288 | + lwz r7,K_DBAT0U_SAVE(r1) | |
3289 | + mtspr DBAT0U,r7 | |
3290 | + lwz r7,K_DBAT0L_SAVE(r1) // must also restore lower bat... | |
3291 | + mtspr DBAT0L,r7 | |
3292 | + lwz r2,K_DBAT1U_SAVE(r1) | |
3293 | + mtspr DBAT1U,r2 | |
3294 | + lwz r7,K_DBAT2U_SAVE(r1) | |
3295 | + mtspr DBAT2U,r7 | |
3296 | + lwz r2,K_DBAT3U_SAVE(r1) | |
3297 | + mtspr DBAT3U,r2 | |
3298 | +#ifdef __darwin__ | |
3299 | + lwz r2,K_OS_SDR1(r1) | |
3300 | + mtsdr1 r2 | |
3301 | + fix_sprg2 /**/ R2 // must not modify sprg2 (i.e. sprg_a0) under OSX 10.3 | |
3302 | +#endif | |
3303 | + blr | |
3304 | + | |
3305 | + | |
3306 | +/************************************************************************/ | |
3307 | +/* Reload Segment Registers */ | |
3308 | +/************************************************************************/ | |
3309 | + | |
3310 | + ////////////////////////////////////////////////////////////// | |
3311 | + // reload_sr | |
3312 | + // | |
3313 | + // r6 = mac-nip | |
3314 | + // | |
3315 | + // - loads segr 0-15 with mac context [modifies r3-r5] | |
3316 | + // - reloads DBAT0 (used for splitmode) | |
3317 | + // | |
3318 | + // Modifies: r3-r5 | |
3319 | + | |
3320 | +reload_sr: | |
3321 | + bt FBIT_InSplitmode,prepare_splitmode // M: r0,r3-r5, r6=mac-nip | |
3322 | + | |
3323 | + lwz r3,K_TRANSL_DBAT0L(r1) | |
3324 | + lwz r4,K_TRANSL_DBAT0U(r1) | |
3325 | + li r5,0 | |
3326 | + mtspr DBAT0L,r3 | |
3327 | + mtcrf MMU_CR_FIELD,r5 // clear FBIT_LoadSegreg (and splitmode stuff) | |
3328 | + mtspr DBAT0U,r4 | |
3329 | +1: | |
3330 | + lwz r4,K_CUR_SR_BASE(r1) | |
3331 | + LOAD_SEGMENT_REGS r4, /**/ r3,r5 | |
3332 | + blr | |
3333 | + | |
3334 | +ret_from_prep_splitmode: | |
3335 | + lwz r3,K_SPLIT_DBAT0L(r1) | |
3336 | + lwz r4,K_SPLIT_DBAT0U(r1) | |
3337 | + li r5,fb_InSplitmode | |
3338 | + mtspr DBAT0L,r3 | |
3339 | + mtcrf MMU_CR_FIELD,r5 // clear FBIT_LoadSegreg and FBIT_PrepareSplitmode | |
3340 | + mtspr DBAT0U,r4 | |
3341 | + b 1b | |
3342 | --- /dev/null | |
3343 | +++ b/drivers/macintosh/mol/asm-files/iopage.S | |
3344 | @@ -0,0 +1,89 @@ | |
3345 | +/* | |
3346 | + * Creation Date: <97/07/26 18:23:02 samuel> | |
3347 | + * Time-stamp: <2002/07/06 12:12:10 samuel> | |
3348 | + * | |
3349 | + * <iopage.S> | |
3350 | + * | |
3351 | + * IO low-level support | |
3352 | + * | |
3353 | + * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se) | |
3354 | + * | |
3355 | + * This program is free software; you can redistribute it and/or | |
3356 | + * modify it under the terms of the GNU General Public License | |
3357 | + * as published by the Free Software Foundation | |
3358 | + * | |
3359 | + */ | |
3360 | + | |
3361 | + // NOTE: This function is also called from the splitmode secondary interrupt | |
3362 | + // handler (splitmode segment registers are resetup at return). | |
3363 | + | |
3364 | + | |
3365 | + /////////////////////////////////////////////////////////////////// | |
3366 | + // check_io_page | |
3367 | + // | |
3368 | + // xINST_OPCODE is always valid at this point | |
3369 | + // | |
3370 | + // Examine if the page (which DAR points to) is an I/O page. | |
3371 | + // Safe to modify: r0,r2-r12 | |
3372 | + | |
3373 | +check_io_page: | |
3374 | + // Is this is an IO-page? IMPORTANT: we must *never* insert mappings | |
3375 | + // that are unreadable by supervisor (will cause a freeze right here). | |
3376 | + | |
3377 | + mfdsisr r10 // r10 = DSISR | |
3378 | + rlwinm. r3,r10,0,1,1 // BIT 1 set if no PTE (or BAT mapping) | |
3379 | + bnelr | |
3380 | + mfdar r8 | |
3381 | + | |
3382 | + mfmsr r7 | |
3383 | + ori r3,r7,MSR_DR // set MSR_DR | |
3384 | + mtmsr r3 | |
3385 | + isync | |
3386 | + | |
3387 | + rlwinm r5,r8,0,0,19 // mask page index | |
3388 | + | |
3389 | + // XXX: TO BE FIXED. These instruction will _never_ cause an exceptions on a | |
3390 | + // single processor system. However, on a SMP machine we *could* receive a | |
3391 | + // tlbie invalidate broadcast. Thus we must implement a secondary | |
3392 | + // interrupt handler to cover that case. | |
3393 | + | |
3394 | + lwz r2,IOP_MAGIC(r5) | |
3395 | + lwz r3,IOP_MAGIC2(r5) // These should _never_ cause any exceptions | |
3396 | + lwz r9,IOP_ME_PHYS(r5) // r9 = physical addr of iopage | |
3397 | + | |
3398 | + mtmsr r7 // restore MSR | |
3399 | + isync | |
3400 | + | |
3401 | + lis r6,HI(IO_PAGE_MAGIC_1) // check MAGIC 1 | |
3402 | + ori r6,r6,LO(IO_PAGE_MAGIC_1) | |
3403 | + cmplw r6,r2 | |
3404 | + bnelr | |
3405 | + | |
3406 | + lis r7,HI(IO_PAGE_MAGIC_2) // check MAGIC 2 | |
3407 | + ori r7,r7,LO(IO_PAGE_MAGIC_2) | |
3408 | + cmplw r7,r3 | |
3409 | + bnelr | |
3410 | + | |
3411 | + // Obtain translation info from the iopage: | |
3412 | + // | |
3413 | + // r4 = mphys_ioaddr = iop->mphys | (dar & 0xfff); | |
3414 | + // r5 = usr_data = iop->usr_data[ (dar & 0xfff) >> 3 ]; | |
3415 | + // | |
3416 | + lwz r4,IOP_MPHYS(r9) | |
3417 | + rlwimi r4,r8,0,20,31 // insert page offset | |
3418 | + | |
3419 | + rlwinm r7,r8,32-1,21,29 // grain = double word | |
3420 | + addi r7,r7,IOP_USR_DATA // usr_data[ (dar&0xfff) ] | |
3421 | + lwzx r5,r9,r7 // r5 = usr_data | |
3422 | + | |
3423 | + rlwinm. r2,r10,0,6,6 // was it a write? (r10=DSISR) | |
3424 | + bne handle_write | |
3425 | + | |
3426 | + // r4 = mphys_ioaddr | |
3427 | + // r5 = usr_data | |
3428 | + MAC_EXIT( RVEC_IO_READ ) | |
3429 | + | |
3430 | +handle_write: | |
3431 | + // r4 = mphys_ioaddr | |
3432 | + // r5 = usr_data | |
3433 | + MAC_EXIT( RVEC_IO_WRITE ) | |
3434 | --- /dev/null | |
3435 | +++ b/drivers/macintosh/mol/asm-files/linux.S | |
3436 | @@ -0,0 +1,129 @@ | |
3437 | +/* | |
3438 | + * Creation Date: <2001/02/24 14:08:28 samuel> | |
3439 | + * Time-stamp: <2003/09/03 12:34:20 samuel> | |
3440 | + * | |
3441 | + * <platform.S> | |
3442 | + * | |
3443 | + * Linux Kernel Hooks | |
3444 | + * | |
3445 | + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) | |
3446 | + * | |
3447 | + * This program is free software; you can redistribute it and/or | |
3448 | + * modify it under the terms of the GNU General Public License | |
3449 | + * as published by the Free Software Foundation | |
3450 | + * | |
3451 | + */ | |
3452 | + | |
3453 | + //////////////////////////////////////////////////////// | |
3454 | + // flush_hash_page_hook | |
3455 | + // | |
3456 | + // Kernel hook | |
3457 | + // | |
3458 | + // r3: context | |
3459 | + // r4: virtual address | |
3460 | + // r5: 2.4.6 pointer to linux PTE (2.4.6 or later) | |
3461 | + // 2.6 pmdval | |
3462 | + // r6: 2.6 count | |
3463 | + // r10: return address | |
3464 | + // | |
3465 | + // [must not modify: r3-r5,r10 - otherwise normal C-function] | |
3466 | + // MMU is ON | |
3467 | + | |
3468 | +.set STACK_SPACE, 32 | |
3469 | +.set STACK_LR, STACK_SPACE+4 | |
3470 | +.set STACK_V0, 8 | |
3471 | +.set STACK_V1, 12 | |
3472 | +.set STACK_V2, 16 | |
3473 | +.set STACK_V3, 20 | |
3474 | +.set STACK_V4, 24 | |
3475 | +.set STACK_V5, 28 | |
3476 | + | |
3477 | +FHOOK( FHOOK_FLUSH_HASH_PAGE ) | |
3478 | +GLOBAL_SYMBOL( r__flush_hash_page_hook ): | |
3479 | + stwu r1,-STACK_SPACE(r1) // Push stackframe | |
3480 | + mflr r0 | |
3481 | + stw r0,STACK_LR(r1) | |
3482 | + | |
3483 | + LOADI r7,EXTERN(do_flush) | |
3484 | + mtctr r7 | |
3485 | + | |
3486 | + stw r10,STACK_V1(r1) // Save registers | |
3487 | + stw r3,STACK_V2(r1) | |
3488 | + stw r4,STACK_V3(r1) | |
3489 | + stw r5,STACK_V4(r1) | |
3490 | +#ifdef LINUX_26 | |
3491 | + stw r6,STACK_V5(r1) | |
3492 | +#else | |
3493 | + li r6,1 | |
3494 | +#endif | |
3495 | + bctrl | |
3496 | + | |
3497 | + lwz r10,STACK_V1(r1) // Restore registers | |
3498 | + lwz r3,STACK_V2(r1) | |
3499 | + lwz r4,STACK_V3(r1) | |
3500 | + lwz r5,STACK_V4(r1) | |
3501 | +#ifdef LINUX_26 | |
3502 | + lwz r6,STACK_V5(r1) | |
3503 | +#endif | |
3504 | + | |
3505 | + lwz r0,STACK_LR(r1) // Pop stackframe | |
3506 | + addi r1,r1,STACK_SPACE | |
3507 | + mtlr r0 | |
3508 | + blr | |
3509 | + | |
3510 | + | |
3511 | +/************************************************************************/ | |
3512 | +/* lowmem reallocations */ | |
3513 | +/************************************************************************/ | |
3514 | + | |
3515 | +#ifdef CONFIG_SMP | |
3516 | + | |
3517 | + /* r3=ea, r4=pte_slot, r5=pte1, r6=pte2, r7=lock, r8=lockval, M: r0 */ | |
3518 | +RELOC_LOW(xx_store_pte_lowmem) | |
3519 | +1: lwarx r0,0,r7 | |
3520 | + cmpwi r0,0 | |
3521 | + bne- 1b | |
3522 | + stwcx. r8,0,r7 // take hash lock | |
3523 | + bne- 1b | |
3524 | + // isync // sync below is sufficient | |
3525 | + stw r0,0(r4) // clear old PTE[V] (if we evict something) | |
3526 | + sync // probably not needed - no other CPU uses this PTE | |
3527 | + stw r6,4(r4) // store PTE2 | |
3528 | + eieio | |
3529 | + stw r5,0(r4) // store PTE1 | |
3530 | + tlbie r3 // flush old pte | |
3531 | + eieio // order tlbie before tlbsync | |
3532 | + tlbsync // ensure tlbie finish on all processors | |
3533 | + sync // ensure tlbsync completed | |
3534 | + stw r0,0(r7) // release hash lock | |
3535 | + blr | |
3536 | +RELOC_LOW_END(xx_store_pte_lowmem) | |
3537 | + | |
3538 | + | |
3539 | + /* r3=ea, r7=lock, r8=lockval, M: r0 */ | |
3540 | +RELOC_LOW(xx_tlbie_lowmem) | |
3541 | +1: lwarx r0,0,r7 | |
3542 | + cmpwi r0,0 | |
3543 | + bne- 1b | |
3544 | + stwcx. r8,0,r7 // take hash lock | |
3545 | + bne- 1b | |
3546 | + //isync // needed if we get rid of the sync | |
3547 | + sync // make sure any PTE zero-outs have finished | |
3548 | + tlbie r3 // flush old pte | |
3549 | + eieio // order tlbie before tlbsync | |
3550 | + tlbsync // ensure tlbie finish on all processors | |
3551 | + sync // ensure tlbsync completed | |
3552 | + stw r0,0(r7) // release hash lock | |
3553 | + blr | |
3554 | +RELOC_LOW_END(xx_tlbie_lowmem) | |
3555 | + | |
3556 | +#else | |
3557 | + | |
3558 | + /* r3=pte_slot, r4=pte0, r5=pte1 */ | |
3559 | +RELOC_LOW(xx_store_pte_lowmem) | |
3560 | + stw r4,0(r3) // interrupts are off and we won't take a page fault | |
3561 | + stw r5,4(r3) // so this is safe... | |
3562 | + blr | |
3563 | +RELOC_LOW_END(xx_store_pte_lowmem) | |
3564 | + | |
3565 | +#endif | |
3566 | --- /dev/null | |
3567 | +++ b/drivers/macintosh/mol/asm-files/ptintercept.S | |
3568 | @@ -0,0 +1,303 @@ | |
3569 | +/* | |
3570 | + * Creation Date: <2001/03/17 18:00:05 samuel> | |
3571 | + * Time-stamp: <2003/05/26 00:08:48 samuel> | |
3572 | + * | |
3573 | + * <ptintercept.S> | |
3574 | + * | |
3575 | + * Handles writes to the (mac) hash table | |
3576 | + * | |
3577 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
3578 | + * | |
3579 | + * This program is free software; you can redistribute it and/or | |
3580 | + * modify it under the terms of the GNU General Public License | |
3581 | + * as published by the Free Software Foundation | |
3582 | + * | |
3583 | + */ | |
3584 | + | |
3585 | +////////////////////////////////////////////////////////////////////// | |
3586 | +// Implementing the tlbie instruction properly is tricky. | |
3587 | +// The tlbie is supposed to invalidate an equivalence | |
3588 | +// class of PTEs and this does not map well to the huge TLB | |
3589 | +// MOL uses (the linux PTE hash, a lot bigger than the 2x64 | |
3590 | +// table found in most CPUs). | |
3591 | +// | |
3592 | +// The solution is intercepting PTE writes and maintain | |
3593 | +// coherence without relying on the tlbie instruction (which | |
3594 | +// can safely be replaced by a nop). | |
3595 | +// | |
3596 | +// Splitmode: The instruction sr might be active. DBAT0 does | |
3597 | +// _not_ have the supervisor valid bit set so we have to load | |
3598 | +// the data segment register. | |
3599 | +////////////////////////////////////////////////////////////////////// | |
3600 | + | |
3601 | +MACRO(SET_MSR_DR, [scr], [ | |
3602 | + li _scr,MSR_DR | |
3603 | + mtmsr _scr | |
3604 | + isync | |
3605 | +]) | |
3606 | +MACRO(CLEAR_MSR_DR, [scr], [ | |
3607 | + li _scr,0 | |
3608 | + mtmsr _scr | |
3609 | + isync | |
3610 | +]) | |
3611 | + | |
3612 | + // r3 = exception vector | |
3613 | +secint_pt_store: | |
3614 | + bf+ FBIT_InSplitmode,1f | |
3615 | + mfdar r2 | |
3616 | + lwz r4,K_TMP_SCRATCH0(r1) // in splitmode (might be | |
3617 | + mtsrin r4,r2 // the instrucion sr) | |
3618 | +1: | |
3619 | + lwz r6,xNIP(r1) // restore NIP & MSR | |
3620 | + lwz r7,K_MSR(r1) | |
3621 | + cmpwi r3,0x300 | |
3622 | + beq 1f | |
3623 | + cmpwi r3,0x600 // Alignment | |
3624 | + beq 2f | |
3625 | + DEBUGGER_SAVE( 0x6909 ) | |
3626 | +1: bl save_middle_regs | |
3627 | + b dsi_cont | |
3628 | +2: bl save_middle_regs | |
3629 | + b alignment_cont | |
3630 | + | |
3631 | + //////////////////////////////////////////////////////////////////////// | |
3632 | + // check_pthash_hit | |
3633 | + // | |
3634 | + // m: r0,r2-r5, cr | |
3635 | + | |
3636 | +check_pthash_hit: | |
3637 | + mfdsisr r3 | |
3638 | + rlwinm. r4,r3,0,4,4 // Is this a protection violation? | |
3639 | + beqlr | |
3640 | + rlwinm. r4,r3,0,6,6 // and a write? | |
3641 | + beqlr- | |
3642 | + | |
3643 | + mfdar r2 // Is this a pthash hit? | |
3644 | + lwz r3,K_TLBHASH_BASE_EA(r1) // First check EA... | |
3645 | + lwz r4,K_HASH_MASK(r1) | |
3646 | + sub r5,r2,r3 | |
3647 | + cmplw r5,r4 | |
3648 | + bgtlr+ | |
3649 | + | |
3650 | + lwz r5,K_SR_DATA(r1) // Correct context for EA? | |
3651 | + rlwinm r3,r2,4+2,26,29 // #sr << 2 | |
3652 | + lwz r4,K_TLBHASH_SR(r1) | |
3653 | + lwzx r3,r3,r5 | |
3654 | + cmpw r3,r4 | |
3655 | + bnelr- | |
3656 | + | |
3657 | + ///////////////////////////////////////////////// | |
3658 | + // Handle page table write, r2=dar, r4=segreg | |
3659 | + ///////////////////////////////////////////////// | |
3660 | + | |
3661 | + bf+ FBIT_InSplitmode,1f | |
3662 | + mfsrin r3,r2 // save old segment register | |
3663 | + stw r3,K_TMP_SCRATCH0(r1) // in splitmode (might be | |
3664 | + mtsrin r4,r2 // the instrucion sr) | |
3665 | +1: | |
3666 | + lwz r3,xINST_OPCODE(r1) | |
3667 | + LI_PHYS( R4,secint_pt_store ) // r4 = secondary exception handler | |
3668 | + stw r6,xNIP(r1) | |
3669 | + | |
3670 | + // r2 = dar, r3 = opcode | |
3671 | + rlwinm r0,r3,6,0x3e // primary opcode & ~1 | |
3672 | + rlwinm r5,r3,6+5+3,(0x1f<<3) // r5 = rS << 3 | |
3673 | + cmpwi r0,30 // 31 & ~1 | |
3674 | + beq- do_opcode_31 | |
3675 | + mtcrf 0x40,r3 // cr[5] = update bit | |
3676 | + cmpwi r0,36 // 36, stw/stwu | |
3677 | + beq do_stw | |
3678 | + cmpwi r0,38 // 38, stb/stbu | |
3679 | + beq do_stb | |
3680 | + cmpwi r0,44 // 44, stb/stbu | |
3681 | + beq do_sth | |
3682 | + cmpwi r0,52 // 52, stfs/stsu | |
3683 | + beq do_stfs | |
3684 | + cmpwi r0,54 // 54, stfd/stfdu | |
3685 | + beq do_stfd | |
3686 | + cmpwi r0,46 // 47, stmw | |
3687 | + beq do_stmw | |
3688 | + b do_st_bad // ??? | |
3689 | + | |
3690 | +do_opcode_31: | |
3691 | + rlwinm r0,r3,32-1,22,31 // secondary opcode | |
3692 | + rlwinm. r6,r3,0,(32<<1) // update form? | |
3693 | + rlwinm r0,r0,0,~32 // clear update bit | |
3694 | + crnot 5,eq | |
3695 | + | |
3696 | + cmpwi r0,151 // stwx/stwxu | |
3697 | + beq+ do_stw | |
3698 | + cmpwi r0,215 // stbx / stbxu | |
3699 | + beq- do_stb | |
3700 | + cmpwi r0,150 // stwcx. | |
3701 | + beq- do_stwcx | |
3702 | + cmpwi r0,407 // sthx / sthxu | |
3703 | + beq- do_sth | |
3704 | + cmpwi r0,727 // stfdx / stfdxu | |
3705 | + beq- do_stfd | |
3706 | + cmpwi r0,663 // stfsx / stfsxu | |
3707 | + beq- do_stfs | |
3708 | + crclr 5 | |
3709 | + rlwinm r0,r3,32-1,22,31 // unmasked secondary opcode | |
3710 | + cmpwi r0,470 // dcbi | |
3711 | + beq- do_dcbi | |
3712 | + cmpwi r0,1014 // dcbz | |
3713 | + beq- do_dcbz | |
3714 | + cmpwi r0,983 // stfiwx [optional] | |
3715 | + beq- do_stfiw | |
3716 | + cmpwi r0,725 // stswi | |
3717 | + beq- do_stswi | |
3718 | + cmpwi r0,661 | |
3719 | + beq- do_stswx | |
3720 | + b do_st_bad // float, cache or altivec | |
3721 | + | |
3722 | +do_st_bad: | |
3723 | +do_stfd: | |
3724 | +do_stfs: | |
3725 | +do_stfiw: | |
3726 | +do_stswi: | |
3727 | +do_stswx: | |
3728 | + lwz r6,xNIP(r1) | |
3729 | + DEBUGGER_SAVE(0x1882) // unimplemented store instruction | |
3730 | + | |
3731 | + // r2=dar, r3=opcode, r4=secint_handler, r5=rS_offs | |
3732 | +do_dcbi: | |
3733 | +do_dcbz: | |
3734 | + mtlr r4 | |
3735 | + SET_MSR_DR /**/ r6 | |
3736 | + rlwinm r6,r2,0,~0x7 | |
3737 | + lwz r4,0(r6) | |
3738 | + lwz r5,4(r6) | |
3739 | + dcbz 0,r2 | |
3740 | + CLEAR_MSR_DR /**/ r0 | |
3741 | + b st_continue_2 | |
3742 | +do_stwcx: | |
3743 | + EMU_LOAD_GPR r5, /**/ R6 // r0 = value | |
3744 | + mtlr r4 | |
3745 | + SET_MSR_DR /**/ r6 | |
3746 | + rlwinm r6,r2,0,~0x7 | |
3747 | + lwz r4,0(r6) | |
3748 | + lwz r5,4(r6) | |
3749 | + stwcx. r0,0,r2 | |
3750 | + CLEAR_MSR_DR /**/ r0 | |
3751 | + lwz r6,xCR(r1) | |
3752 | + mfcr r0 | |
3753 | + rlwimi r6,r0,0,0,3 | |
3754 | + stw r6,xCR(r1) | |
3755 | + b st_continue_2 | |
3756 | +do_sth: | |
3757 | + EMU_LOAD_GPR r5, /**/ R6 // r0 = value | |
3758 | + mtlr r4 | |
3759 | + SET_MSR_DR /**/ r6 | |
3760 | + rlwinm r6,r2,0,~0x7 | |
3761 | + lwz r4,0(r6) | |
3762 | + lwz r5,4(r6) | |
3763 | + sth r0,0(r2) | |
3764 | + b st_continue | |
3765 | +do_stb: | |
3766 | + EMU_LOAD_GPR r5, /**/ R6 // r0 = value | |
3767 | + mtlr r4 | |
3768 | + SET_MSR_DR /**/ r6 | |
3769 | + rlwinm r6,r2,0,~0x7 | |
3770 | + lwz r4,0(r6) | |
3771 | + lwz r5,4(r6) | |
3772 | + stb r0,0(r2) | |
3773 | + b st_continue | |
3774 | +do_stw: | |
3775 | + EMU_LOAD_GPR r5, /**/ R6 // r0 = value | |
3776 | + mtlr r4 | |
3777 | + SET_MSR_DR /**/ r6 | |
3778 | + rlwinm r6,r2,0,~0x7 | |
3779 | + lwz r4,0(r6) | |
3780 | + lwz r5,4(r6) | |
3781 | + stw r0,0(r2) | |
3782 | + b st_continue | |
3783 | + | |
3784 | + // r4=PTE0, r5=PTE1, r3=opcode, r2=dar, scratch: r0 | |
3785 | +st_continue: | |
3786 | + CLEAR_MSR_DR /**/ r0 | |
3787 | + bf+ 5,st_continue_2 // update form? | |
3788 | + rlwinm r3,r3,6+5+5+3,(31<<3) | |
3789 | + mr r0,r2 | |
3790 | + EMU_STORE_GPR r3, /**/ R6 // r0 = value | |
3791 | +st_continue_2: | |
3792 | + // check if the old PTE has been used (r2=dar,r4/r5=PTE) | |
3793 | + lwz r3,K_TLBHASH_BASE_EA(r1) // Calculate tlb offset | |
3794 | + sub r0,r2,r3 // r0 = pte_nr * 8 | |
3795 | + lwz r6,K_PTHASH_INUSE_PH(r1) | |
3796 | + rlwinm r3,r0,32-6,6,29 // r3 = word offset | |
3797 | + cmpwi r6,0 | |
3798 | + beq- 1f | |
3799 | + lwzx r3,r3,r6 | |
3800 | + rlwinm r6,r2,32-3,27,31 // pte_nr & 0x1f | |
3801 | + li r0,1 | |
3802 | + slw r6,r0,r6 // r6 = bit | |
3803 | + and. r6,r6,r3 | |
3804 | + GET_TICK_CNT(entry,"ptintercept-1") | |
3805 | + bne- pt_intercept | |
3806 | +1: | |
3807 | + BUMP("pt_intercept_not_taken") | |
3808 | + // return from exception [r2=dar] | |
3809 | + lwz r6,xNIP(r1) // restore r6 | |
3810 | + bf+ FBIT_InSplitmode,emulation_done | |
3811 | + lwz r3,K_TMP_SCRATCH0(r1) // in splitmode (might be | |
3812 | + mtsrin r3,r2 // the instrucion sr) | |
3813 | + b emulation_done | |
3814 | + | |
3815 | + // transfer to C-function [r2=dar, r3/r4=pte] | |
3816 | +pt_intercept: | |
3817 | + BUMP("pt_intercept_taken") | |
3818 | + lwz r6,xNIP(r1) // restore r6 | |
3819 | + lwz r3,K_TLBHASH_BASE_EA(r1) // calculate tlb offset | |
3820 | + addi r6,r6,4 // inc NIP | |
3821 | + bl save_middle_regs | |
3822 | + sub r6,r2,r3 | |
3823 | + rlwinm r6,r6,0,0,28 // argument pteoffs (dword aligned) | |
3824 | + | |
3825 | + // r4=PTE0, r5=PTE1 | |
3826 | + LOADI r3,EXTERN(do_intercept_tlbie) | |
3827 | + b call_kernel | |
3828 | + | |
3829 | + // stmw uses another emulator entry point because it might overwrite a bunch of PTEs | |
3830 | +do_stmw: | |
3831 | + mtlr r4 | |
3832 | + | |
3833 | + // save some debugging info | |
3834 | +// stw r2,xDBG_TRACE_SPACE(r1) | |
3835 | + | |
3836 | + SET_MSR_DR /**/ r6 | |
3837 | + | |
3838 | + // now do the stmw. we do that manually since we have to access emulator regs. | |
3839 | + mr r4,r2 // r4: memory pointer | |
3840 | + srwi r6,r5,3 // r6: rS | |
3841 | +1: cmpwi r5,32 << 3 // loop condition | |
3842 | + bge 2f | |
3843 | + EMU_LOAD_GPR r5, /**/ R3 // r0 = value | |
3844 | + stw r0,0(r4) // store the value | |
3845 | + addi r5,r5,1 << 3 // update register counter | |
3846 | + addi r4,r4,4 // and memory pointer | |
3847 | + b 1b | |
3848 | + | |
3849 | +2: CLEAR_MSR_DR /**/ r0 | |
3850 | + | |
3851 | + // load up r4 and r5 for do_intercept_tlbie_block (see below) | |
3852 | + subfic r5,r6,32 // number of registers (=words) stored | |
3853 | + slwi r5,r5,2 // number of bytes stored | |
3854 | + add r4,r2,r5 // last byte stored | |
3855 | + addi r4,r4,7 // alignment to | |
3856 | + rlwinm r5,r4,0,~0x7 // PTE size | |
3857 | + rlwinm r4,r2,0,~0x7 // pte block pointer | |
3858 | + sub r5,r5,r4 // substract block pointer -> length (in bytes) | |
3859 | + lwz r3,K_TLBHASH_BASE_EA(r1) // calculate tlb offset | |
3860 | + sub r4,r4,r3 // tlb offset | |
3861 | + b st_block_continue | |
3862 | + | |
3863 | + // transfer to C-function [r2=dar, r4=pte block offset, r5=pte block length] | |
3864 | +st_block_continue: | |
3865 | + BUMP("pt_intercept_taken") | |
3866 | + lwz r6,xNIP(r1) | |
3867 | + addi r6,r6,4 // inc NIP | |
3868 | + bl save_middle_regs | |
3869 | + | |
3870 | + LOADI r3,EXTERN(do_intercept_tlbie_block) | |
3871 | + b call_kernel | |
3872 | --- /dev/null | |
3873 | +++ b/drivers/macintosh/mol/asm-files/splitmode.S | |
3874 | @@ -0,0 +1,428 @@ | |
3875 | +/* | |
3876 | + * Creation Date: <2000/07/11 03:38:32 samuel> | |
3877 | + * Time-stamp: <2003/08/20 16:37:04 samuel> | |
3878 | + * | |
3879 | + * <splitmode.S> | |
3880 | + * | |
3881 | + * Handles splitmode (MSR_IR != MSR_DR) | |
3882 | + * | |
3883 | + * Copyright (C) 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
3884 | + * | |
3885 | + * This program is free software; you can redistribute it and/or | |
3886 | + * modify it under the terms of the GNU General Public License | |
3887 | + * as published by the Free Software Foundation | |
3888 | + * | |
3889 | + */ | |
3890 | + | |
3891 | +MACRO(SM_SET_MSR_DR, [scr], [ | |
3892 | + li _scr,MSR_DR | |
3893 | + mtmsr _scr | |
3894 | + isync | |
3895 | +]) | |
3896 | +MACRO(SM_CLEAR_MSR_DR, [scr], [ | |
3897 | + li _scr,0 | |
3898 | + mtmsr _scr | |
3899 | + isync | |
3900 | +]) | |
3901 | +MACRO(SPLITMODE_SMP_LOCK, [scr1,scr2], [ | |
3902 | +#ifdef CONFIG_SMP | |
3903 | + LI_PHYS( _scr1,splitmode_lock ) | |
3904 | +7: lwarx _scr2,0,_scr1 | |
3905 | + cmpwi _scr2,0 | |
3906 | + li _scr2,1 | |
3907 | + bne- 7b | |
3908 | + stwcx. _scr2,0,_scr1 | |
3909 | + bne- 7b | |
3910 | + isync | |
3911 | +#endif | |
3912 | +]) | |
3913 | +MACRO(SPLITMODE_SMP_UNLOCK, [scr1,scr2], [ | |
3914 | +#ifdef CONFIG_SMP | |
3915 | + LI_PHYS( _scr1,splitmode_lock ) | |
3916 | + li _scr2,0 | |
3917 | + stw _scr2,0(_scr1) | |
3918 | +#endif | |
3919 | +]) | |
3920 | + | |
3921 | + ///////////////////////////////////////////////////////////// | |
3922 | + // prepare_splitmode | |
3923 | + // | |
3924 | + // r6,r7: nip/srr1 | |
3925 | + // | |
3926 | + // M: r0,r3-r5 | |
3927 | + // | |
3928 | + // Fill in splitmode segment register table. The segment register | |
3929 | + // containing xNIP is set up for instruction access (if xNIP does | |
3930 | + // not hold nip, an extra ISI exception will occur). The instruction | |
3931 | + // segment is protected from data access through the use of a DBAT | |
3932 | + // register. | |
3933 | + // | |
3934 | + // It MUST be safe to call this function even if we are *not* in | |
3935 | + // splitmode. | |
3936 | + | |
3937 | +prepare_splitmode: | |
3938 | + bf FBIT_PrepareSplitmode, ret_from_prep_splitmode | |
3939 | + | |
3940 | + ZERO_TICK_CNT(splitmode_prep) | |
3941 | + | |
3942 | + // fill split mode table with data segment registers | |
3943 | + lwz r3,K_SR_DATA(r1) // physical addr | |
3944 | + addi r4,r1,K_SPLIT_SR_BASE-4 | |
3945 | + li r5,16 | |
3946 | + mfctr r0 // save ctr in r0 | |
3947 | + mtctr r5 | |
3948 | + addi r3,r3,-4 | |
3949 | +1: lwzu r5,4(r3) | |
3950 | + oris r5,r5,0x1000 // no-execute segment bit | |
3951 | + stwu r5,4(r4) | |
3952 | + bdnz 1b | |
3953 | + mtctr r0 // restore ctr | |
3954 | + | |
3955 | + // insert instruction mode segment | |
3956 | + rlwinm r3,r6,0,0,3 | |
3957 | + stw r3,K_SPLIT_NIP_SEGMENT(r1) | |
3958 | + rlwinm r3,r6,4+2,26,29 // r3 = offset, ((sr & 0xf000000) >> 28 ) * 4 | |
3959 | + lwz r5,K_SR_INST(r1) | |
3960 | + lwzx r5,r3,r5 // segment register for instructions | |
3961 | + addi r4,r1,K_SPLIT_SR_BASE | |
3962 | + stwx r5,r3,r4 | |
3963 | + | |
3964 | + // and protect it with DBAT0. | |
3965 | + // | |
3966 | + // The supervisor valid bit must be cleared | |
3967 | + // - we don't want to block get_opcode. | |
3968 | + | |
3969 | + rlwinm r3,r6,0,0,3 // segment base | |
3970 | + ori r3,r3,0x1ffd // user valid bit | 256MB mask | |
3971 | + stw r3,K_SPLIT_DBAT0U(r1) | |
3972 | + li r4,0 | |
3973 | + stw r4,K_SPLIT_DBAT0L(r1) // pp=0, wimg=0 | |
3974 | + GET_TICK_CNT(splitmode_prep, "splitmode_prep") | |
3975 | + b ret_from_prep_splitmode | |
3976 | + | |
3977 | + | |
3978 | + /////////////////////////////////////////////////////////////////// | |
3979 | + // split_sr_no_execute | |
3980 | + // | |
3981 | + // r6,r7: nip/srr1 | |
3982 | + // | |
3983 | + // An instruction is to be fetched from one of the no-execute | |
3984 | + // segments. This function reinitializes the segment registers. | |
3985 | + // | |
3986 | + // M: r0, r3-r5 | |
3987 | + | |
3988 | +split_sr_no_execute: | |
3989 | + rlwinm. r0,r7,0,3,3 // Guarded access or no-execute? | |
3990 | + beqlr | |
3991 | + | |
3992 | + rlwinm r3,r6,0,0,3 // segment | |
3993 | + lwz r4,K_SPLIT_NIP_SEGMENT(r1) | |
3994 | + cmpw r3,r4 | |
3995 | + beqlr // guarded PTE/mac-guarded segment | |
3996 | + | |
3997 | + crset FBIT_PrepareSplitmode | |
3998 | + crset FBIT_LoadSegreg | |
3999 | + b exception_return | |
4000 | + | |
4001 | + | |
4002 | + | |
4003 | + ////////////////////////////////////////////////////////////////// | |
4004 | + // splitmode_dsi | |
4005 | + // | |
4006 | + // r6/r7: nip/srr1 | |
4007 | + // | |
4008 | + // An DSI exception occured (DBAT protection violation). | |
4009 | + // That is, a load/store instruction targeted the segment | |
4010 | + // instructions was fetched from. | |
4011 | + // | |
4012 | + // Safe to modify: r0,r2-r5, (lr) | |
4013 | + | |
4014 | +splitmode_dsi: | |
4015 | + mfdsisr r3 // DBAT/page protection violation? | |
4016 | + rlwinm. r0,r3,0,4,4 | |
4017 | + beqlr- // If not, it does not concern us | |
4018 | + | |
4019 | + mfdar r2 // Normal page protected exception? | |
4020 | + lwz r4,K_SPLIT_NIP_SEGMENT(r1) // the instruction segment? | |
4021 | + rlwinm r5,r2,0,0,3 // data segment | |
4022 | + cmpw r4,r5 | |
4023 | + bnelr // exit - not in the instruction segment | |
4024 | + | |
4025 | + // splitmode write, r2=dar | |
4026 | + mfsrin r0,r2 // r0 = old segment register | |
4027 | + stw r6,xNIP(r1) // need one additional reg | |
4028 | + rlwinm r4,r2,4+2,26,29 // sr_offset = sr_num * 4 | |
4029 | + lwz r5,K_SR_DATA(r1) | |
4030 | + lwzx r4,r4,r5 | |
4031 | + stw r0,K_TMP_SCRATCH0(r1) // save old segment register | |
4032 | + oris r4,r4,0x4000 // set supervisor key bit (Ks) | |
4033 | + mtsrin r4,r2 | |
4034 | + | |
4035 | + rlwinm. r3,r3,0,6,6 // cr[eq] set if this a read | |
4036 | + lwz r3,xINST_OPCODE(r1) | |
4037 | + LI_PHYS( R4, secint_splitm ) // r4 = secint handler | |
4038 | + | |
4039 | + // handle simple stores r2=seg#, r3=opcode, r4=secint | |
4040 | + beq splitm_load | |
4041 | + | |
4042 | + rlwinm r5,r3,6+5+3,(0x1f<<3) // r5 = rS << 3 | |
4043 | + EMU_LOAD_GPR r5, /**/ R6 // r0 = value | |
4044 | + mtlr r4 // secint handler | |
4045 | + SM_SET_MSR_DR /**/ r5 | |
4046 | + | |
4047 | + rlwinm r6,r3,6,0x3e // primary opcode & ~1 | |
4048 | + mtcrf 0x40,r3 // cr[5] = update bit (if opcode != 31) | |
4049 | + cmpwi r6,30 // 31 & ~1 | |
4050 | + beq- splitm_store_op31 | |
4051 | + cmpwi r6,36 // 36, stw/stwu | |
4052 | + beq splitm_stw | |
4053 | + cmpwi r6,38 // 38, stb/stbu | |
4054 | + beq splitm_stb | |
4055 | + cmpwi r6,44 // 44, stb/stbu | |
4056 | + beq splitm_sth | |
4057 | + b splitm_fallback | |
4058 | +splitm_store_op31: | |
4059 | + rlwinm. r6,r3,0,(32<<1) // update form? | |
4060 | + rlwinm r6,r3,32-1,22,31 // secondary opcode | |
4061 | + rlwinm r6,r6,0,~32 // clear update bit | |
4062 | + crnot 5,eq | |
4063 | + cmpwi r6,151 // stwx/stwxu | |
4064 | + beq+ splitm_stw | |
4065 | + cmpwi r6,215 // stbx / stbxu | |
4066 | + beq- splitm_stb | |
4067 | + cmpwi r6,407 // sthx / sthxu | |
4068 | + beq- splitm_sth | |
4069 | + rlwinm r6,r3,32-1,22,31 // secondary opcode | |
4070 | + cmpwi r6,150 // stwcx. | |
4071 | + beq- splitm_stwcx | |
4072 | + cmpwi r6,1014 // 1014, dcbz | |
4073 | + beq- splitm_dcbz | |
4074 | + cmpwi r6,662 // 662, stwbrx | |
4075 | + beq- splitm_stwbrx | |
4076 | + b splitm_fallback | |
4077 | + | |
4078 | +splitm_load: | |
4079 | + mtlr r4 // secint handler | |
4080 | + SM_SET_MSR_DR /**/ r5 | |
4081 | + rlwinm r6,r3,6,0x3e // primary opcode & ~1 | |
4082 | + mtcrf 0x40,r3 // cr[5] = update bit (if opcode != 31) | |
4083 | + cmpwi r6,30 // 31 & ~1 | |
4084 | + beq- splitm_load_op31 | |
4085 | + cmpwi r6,32 // 32, lwz/lwzu | |
4086 | + beq+ splitm_lwz | |
4087 | + cmpwi r6,34 // 34, lbz/lbzu | |
4088 | + beq- splitm_lbz | |
4089 | + cmpwi r6,40 // 40, lhz/lhzu | |
4090 | + beq- splitm_lhz | |
4091 | + b splitm_fallback | |
4092 | +splitm_load_op31: | |
4093 | + rlwinm. r6,r3,0,(32<<1) // update form? | |
4094 | + rlwinm r6,r3,32-1,22,31 // secondary opcode | |
4095 | + rlwinm r6,r6,0,~32 // clear update bit | |
4096 | + crnot 5,eq | |
4097 | + cmpwi r6,23 // 23, lwzx/lwzux | |
4098 | + beq+ splitm_lwz | |
4099 | + cmpwi r6,87 // 87, lbzx/lbzux | |
4100 | + beq- splitm_lbz | |
4101 | + cmpwi r6,279 // 279, lhzx/lhzux | |
4102 | + beq- splitm_lhz | |
4103 | + rlwinm r6,r3,32-1,22,31 // secondary opcode | |
4104 | + crclr 5 | |
4105 | + cmpwi r6,20 // 20, lwarx | |
4106 | + beq- splitm_lwarx | |
4107 | + cmpwi r6,86 // 86, dcbf | |
4108 | + beq- splitm_dcbf | |
4109 | + cmpwi r6,982 // 982, icbi | |
4110 | + beq- splitm_icbi | |
4111 | + cmpwi r6,534 // 534, lwbrx | |
4112 | + beq- splitm_lwbrx | |
4113 | + b splitm_fallback | |
4114 | + | |
4115 | + | |
4116 | + // r0=value, r2=ea, r3=opcode | |
4117 | +splitm_stwcx: | |
4118 | + stwcx. r0,0,r2 | |
4119 | + SM_CLEAR_MSR_DR /**/ r0 | |
4120 | + lwz r6,xCR(r1) | |
4121 | + mfcr r0 | |
4122 | + rlwimi r6,r0,0,0,3 | |
4123 | + stw r6,xCR(r1) | |
4124 | + b splitm_done2 | |
4125 | +splitm_sth: | |
4126 | + sth r0,0(r2) | |
4127 | + b splitm_store_continue | |
4128 | +splitm_stb: | |
4129 | + stb r0,0(r2) | |
4130 | + b splitm_store_continue | |
4131 | +splitm_stw: | |
4132 | + stw r0,0(r2) | |
4133 | + b splitm_store_continue | |
4134 | +splitm_lwz: | |
4135 | + lwz r0,0(r2) | |
4136 | + b splitm_load_continue | |
4137 | +splitm_lhz: | |
4138 | + lhz r0,0(r2) | |
4139 | + b splitm_load_continue | |
4140 | +splitm_lbz: | |
4141 | + lbz r0,0(r2) | |
4142 | + b splitm_load_continue | |
4143 | +splitm_lwarx: | |
4144 | + lwarx r0,0,r2 | |
4145 | + b splitm_load_continue | |
4146 | +splitm_lwbrx: | |
4147 | + lwbrx r0,0,r2 | |
4148 | + b splitm_load_continue | |
4149 | +splitm_dcbz: | |
4150 | + dcbz 0,r2 | |
4151 | + b splitm_done | |
4152 | +splitm_icbi: | |
4153 | + icbi 0,r2 | |
4154 | + b splitm_done | |
4155 | +splitm_dcbf: | |
4156 | + dcbf 0,r2 | |
4157 | + b splitm_done | |
4158 | +splitm_stwbrx: | |
4159 | + stwbrx r0,0,r2 | |
4160 | + b splitm_done | |
4161 | + | |
4162 | +splitm_load_continue: | |
4163 | + SM_CLEAR_MSR_DR /**/ r4 | |
4164 | + BUMP("splitm_load") | |
4165 | + rlwinm r4,r3,6+5+3,(0x1f<<3) // r5 = rS << 3 | |
4166 | + EMU_STORE_GPR r4, /**/ R6 // r0 = value | |
4167 | + bf+ 5,splitm_done2 // update form? | |
4168 | + b 1f | |
4169 | + | |
4170 | +splitm_store_continue: | |
4171 | + SM_CLEAR_MSR_DR /**/ r0 | |
4172 | + BUMP("splitm_store") | |
4173 | + bf+ 5,splitm_done2 // update form? | |
4174 | +1: rlwinm r3,r3,6+5+5+3,(31<<3) | |
4175 | + mr r0,r2 | |
4176 | + EMU_STORE_GPR r3, /**/ R6 // r0 = value | |
4177 | + b splitm_done2 | |
4178 | +splitm_done: | |
4179 | + SM_CLEAR_MSR_DR /**/ r0 | |
4180 | +splitm_done2: | |
4181 | + lwz r3,K_TMP_SCRATCH0(r1) | |
4182 | + lwz r6,xNIP(r1) // restore NIP | |
4183 | + mtsrin r3,r2 | |
4184 | + b emulation_done | |
4185 | + | |
4186 | + | |
4187 | + // fallback, store and execute the instruction, r3=opcode | |
4188 | +splitm_fallback: | |
4189 | + SM_CLEAR_MSR_DR /**/ r0 | |
4190 | +#if 0 | |
4191 | + stw r3,xDEBUG1(r1) | |
4192 | + stw r6,xDEBUG0(r1) | |
4193 | + lwz r6,xNIP(r1) | |
4194 | + DEBUGGER_SAVE(0x1111) | |
4195 | +#endif | |
4196 | + SPLITMODE_SMP_LOCK /**/ r0,r2 | |
4197 | + | |
4198 | + BUMP("splitm_fallback") | |
4199 | + bl secint_splitm_fallback // set secondary exception handler | |
4200 | + | |
4201 | + LI_PHYS( R2,split_store_patch ) // r2 = addr of split_store_patch | |
4202 | + stw r3,0(r2) // store instruction | |
4203 | + dcbst 0,r2 | |
4204 | + sync | |
4205 | + icbi 0,r2 | |
4206 | + sync // 74xx needs this | |
4207 | + | |
4208 | + mtsrr0 r2 // The simplest thing is to do an RFI | |
4209 | + LOADI r3,(MSR_EE | MSR_PR | MSR_IR | MSR_SE | MSR_BE) | |
4210 | + andc r4,r7,r3 // Clear msr bits (r7=srr1) | |
4211 | + xGPR_LOAD R6 | |
4212 | + xGPR_LOAD R7 | |
4213 | + mtsrr1 r4 | |
4214 | + xGPR_LOAD_RANGE R2,R5,r1 // Restore registers (except r1) | |
4215 | + xGPR_LOAD R0 | |
4216 | + xGPR_LOAD R1 | |
4217 | + rfi | |
4218 | + | |
4219 | +split_store_patch: | |
4220 | + nop | |
4221 | + | |
4222 | + mtsprg_a0 r1 // restore MSR | |
4223 | + li r1,MSR_ME | |
4224 | + mtmsr r1 | |
4225 | + isync | |
4226 | + mfsprg_a3 r1 // and stack pointer | |
4227 | + | |
4228 | + xGPR_SAVE_RANGE R2,R7,r1 | |
4229 | + SPLITMODE_SMP_UNLOCK /**/ r3,r4 | |
4230 | + | |
4231 | + mfsprg_a0 r2 // r1 - to be saved | |
4232 | + lwz r6,xNIP(r1) // restore r6,r7 and segment register | |
4233 | + lwz r7,K_MSR(r1) | |
4234 | + stw r0,xGPR0(r1) | |
4235 | + stw r2,xGPR1(r1) | |
4236 | + lwz r2,K_TMP_SCRATCH0(r1) | |
4237 | + mtsrin r2,r6 | |
4238 | + | |
4239 | + GET_TICK_CNT( entry, "splitmode_dsi" ) | |
4240 | + b emulation_done | |
4241 | + | |
4242 | + | |
4243 | + ////////////////////////////////////////////////////////////////////// | |
4244 | + // secint_splitm / secint_splitm_fallback | |
4245 | + // r1: stack (sprg1 = old r1) | |
4246 | + // r3: vector index (sprg0 = old r3) | |
4247 | + // srr0/srr1: kernel nip/msr | |
4248 | + // | |
4249 | + // xGPR(0-5) are valid (unless this is a trace exception) | |
4250 | + | |
4251 | +secint_splitm_fallback: | |
4252 | + blrl | |
4253 | + SPLITMODE_SMP_UNLOCK /**/ R2,R4 | |
4254 | + | |
4255 | +secint_splitm: | |
4256 | + lwz r6,xNIP(r1) // Restore nip/msr | |
4257 | + lwz r7,K_MSR(r1) | |
4258 | + | |
4259 | + cmpwi r3,0x300 // ** DSI ** | |
4260 | + bne- 1f | |
4261 | + mfsrin r2,r6 // r6 = NIP | |
4262 | + rlwinm r2,r2,0,2,0 // Clear Ks [bit1] (supervisor key bit) | |
4263 | + mtsrin r2,r6 | |
4264 | + bl save_middle_regs // Note: If dsi_cont ever returns immediately, | |
4265 | + bl check_io_page // we will need to fix the segment registers before | |
4266 | + b dsi_cont // the last dsi_cont branch. | |
4267 | + | |
4268 | +1: lwz r2,K_TMP_SCRATCH0(r1) // We might return immediately... | |
4269 | + mtsrin r2,r6 | |
4270 | + | |
4271 | + cmpwi r3,0x600 // ** Alignment ** | |
4272 | + bne 2f | |
4273 | + bl save_middle_regs | |
4274 | + b alignment_cont | |
4275 | + | |
4276 | +2: cmpwi r3,0x800 // ** FPU Unavailable ** | |
4277 | + beq fpu_cont | |
4278 | + cmpwi r3,0xf20 // ** AltiVec Unavailable ** | |
4279 | + beq altivec_cont | |
4280 | + | |
4281 | + DEBUGGER_SAVE( 0x5918 ) // ERROR... | |
4282 | + | |
4283 | + | |
4284 | + //////////////////////////////////////////////////////////////////////// | |
4285 | + // invalidate_splitmode( kernel_vars_t *kv ) | |
4286 | + // | |
4287 | + // This function must be called whenever the segment registers are | |
4288 | + // modified. A flag is set which will force a refresh of the slitmode | |
4289 | + // segment registers (at mac context switch in). We could rewrite this | |
4290 | + // in C but it might be better to keep things centralized. | |
4291 | + | |
4292 | +GLOBAL_SYMBOL(r__invalidate_splitmode_sr): | |
4293 | + // this will have no effect if fb_InSplitmode is not set | |
4294 | + lwz r4,xFLAG_BITS(r3) | |
4295 | + ori r4,r4,fb_PrepareSplitmode | fb_LoadSegreg | |
4296 | + stw r4,xFLAG_BITS(r3) | |
4297 | + blr | |
4298 | + | |
4299 | +#ifdef CONFIG_SMP | |
4300 | +splitmode_lock: | |
4301 | + .long 0 | |
4302 | +#endif | |
4303 | --- /dev/null | |
4304 | +++ b/drivers/macintosh/mol/asm-files/traps.S | |
4305 | @@ -0,0 +1,501 @@ | |
4306 | +/* | |
4307 | + * Creation Date: <2001/01/27 16:25:14 samuel> | |
4308 | + * Time-stamp: <2004/03/07 21:58:48 samuel> | |
4309 | + * | |
4310 | + * <traps.S> | |
4311 | + * | |
4312 | + * Exception Vectors | |
4313 | + * | |
4314 | + * Copyright (C) 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
4315 | + * | |
4316 | + * This program is free software; you can redistribute it and/or | |
4317 | + * modify it under the terms of the GNU General Public License | |
4318 | + * as published by the Free Software Foundation | |
4319 | + * | |
4320 | + */ | |
4321 | + | |
4322 | +#define DBG_TRACE 0 // enable TRACE macro? | |
4323 | + | |
4324 | +#include "archinclude.h" | |
4325 | +#include "processor.h" /* avoid <asm/processor.h> (bogus SPRN_TBWU/L) */ | |
4326 | +#include "asm_offsets.h" | |
4327 | +#include "asmdefs.h" | |
4328 | +#include "molasm.h" | |
4329 | +#include "asmdbg.h" | |
4330 | +#include "actions.h" | |
4331 | +#include "vector.h" | |
4332 | +#include "rvec.h" | |
4333 | +#include "constants.h" | |
4334 | +#include "mac_registers.h" | |
4335 | +#include "mmu.h" | |
4336 | +#include "osi.h" | |
4337 | +#include "kernel_vars.h" | |
4338 | + | |
4339 | + | |
4340 | +/************************************************************************/ | |
4341 | +/* Exception Vector Definitions */ | |
4342 | +/************************************************************************/ | |
4343 | + | |
4344 | + ACTIONS_SECTION | |
4345 | +GLOBAL_SYMBOL(r__actions_section): | |
4346 | + ACTIONS_OFFS_SECTION | |
4347 | +GLOBAL_SYMBOL(r__actions_offs_section): | |
4348 | + | |
4349 | + .text | |
4350 | +GLOBAL_SYMBOL(r__reloctable_start): | |
4351 | + | |
4352 | +MACRO_0(EXCEPTION_PREAMBLE, [ | |
4353 | + // SPRG1 = r1, SPRG0 = r3, r3=CR, r1=MOL_STACK | |
4354 | + __ZERO_TICK_CNT(entry) | |
4355 | + stw r4,xGPR4(r1) // store instruction are store serializing | |
4356 | + lwz r4,xFLAG_BITS(r1) | |
4357 | + stw r5,xGPR5(r1) // and mix very badly with execution serializing | |
4358 | + stw r6,xGPR6(r1) // instructions (like mfspr) | |
4359 | + mfsrr0 r6 | |
4360 | + stw r7,xGPR7(r1) | |
4361 | + mfsrr1 r7 | |
4362 | + stw r0,xGPR0(r1) | |
4363 | + mtcr r4 | |
4364 | + stw r2,xGPR2(r1) | |
4365 | + mflr r2 | |
4366 | + stw r3,xCR(r1) | |
4367 | + mfsprg_a1 r5 // SPRG1 = r1 | |
4368 | + stw r2,xLINK(r1) | |
4369 | + mfsprg_a0 r3 // SPRG0 = r3 | |
4370 | + stw r5,xGPR1(r1) | |
4371 | + stw r3,xGPR3(r1) | |
4372 | + | |
4373 | + // saved: r0-r7, cr, lr | |
4374 | + // r1 = stack, cr5-7=flag_bits, r6/r7 = nip/msr | |
4375 | +]) | |
4376 | + | |
4377 | + balign_32 | |
4378 | +save_middle_regs: // save r8-r12 and nip (r13-r31 should always be in regs) | |
4379 | + stw r6,xNIP(r1) | |
4380 | + mfxer r7 | |
4381 | + mfctr r6 | |
4382 | + stw r8,xGPR8(r1) | |
4383 | + stw r9,xGPR9(r1) | |
4384 | + stw r10,xGPR10(r1) | |
4385 | + stw r11,xGPR11(r1) | |
4386 | + stw r12,xGPR12(r1) | |
4387 | + stw r6,xCTR(r1) | |
4388 | + stw r7,xXER(r1) | |
4389 | + bt- FBIT_FPUInUse,giveup_fpu // modifies r7/r8 | |
4390 | + blr | |
4391 | + | |
4392 | +MACRO_0(RESTORE_MIDDLE_REGS, [ // reverse save_middle_regs, restores registers | |
4393 | + lwz r11,xCTR(r1) // r8-r12, ctr, xer, r6/r7 = nip/msr | |
4394 | + lwz r12,xXER(r1) | |
4395 | + lwz r8,xGPR8(r1) | |
4396 | + lwz r9,xGPR9(r1) | |
4397 | + mtctr r11 | |
4398 | + lwz r10,xGPR10(r1) | |
4399 | + lwz r11,xGPR11(r1) | |
4400 | + mtxer r12 | |
4401 | + lwz r12,xGPR12(r1) | |
4402 | + lwz r6,xNIP(r1) | |
4403 | + lwz r7,K_MSR(r1) | |
4404 | +]) | |
4405 | + | |
4406 | +#define EXCEPTION_SAVE_ALL \ | |
4407 | + EXCEPTION_PREAMBLE ;\ | |
4408 | + bl save_middle_regs ; | |
4409 | + | |
4410 | +#define VECTOR_KERNEL( v, dummy_name, secint ) \ | |
4411 | + VECTOR( v, dummy_name, secint ) ;\ | |
4412 | + EXCEPTION_SAVE_ALL ;\ | |
4413 | + TAKE_EXCEPTION( v ) ; | |
4414 | + | |
4415 | +#define VECTOR_RESERVED( v, dummy_name, secint ) \ | |
4416 | + VECTOR( v, dummy_name, secint ) ;\ | |
4417 | + DEBUGGER_SAVE( v ) ; | |
4418 | + | |
4419 | +#define MAC_EXIT( rvec_code ) \ | |
4420 | + li r3,rvec_code ;\ | |
4421 | + b mac_exit ; | |
4422 | + | |
4423 | +#define MAC_EXIT_SAVE( rvec_code ) \ | |
4424 | + bl save_middle_regs ;\ | |
4425 | + li r3,rvec_code ;\ | |
4426 | + b mac_exit ; | |
4427 | + | |
4428 | +#define MAC_TRAP( trap_num ) \ | |
4429 | + li r2,trap_num ;\ | |
4430 | + b mac_trap ; | |
4431 | + | |
4432 | +#define DEBUGGER(n) li r4,n ; MAC_EXIT( RVEC_DEBUGGER ); | |
4433 | +#define DEBUGGER_SAVE(n) li r4,n ; MAC_EXIT_SAVE( RVEC_DEBUGGER ); | |
4434 | + | |
4435 | + | |
4436 | +/************************************************************************/ | |
4437 | +/* Misc macros */ | |
4438 | +/************************************************************************/ | |
4439 | + | |
4440 | + ////////////////////////////////////////////////////////////// | |
4441 | + // _get_instr_opcode | |
4442 | + // r6 nip | |
4443 | + // ret: r4 opcode | |
4444 | + // | |
4445 | + // Modifies: r2,r3. | |
4446 | + // Side-effects: Might return from the exception | |
4447 | + | |
4448 | +MACRO(GET_INSTR_OPCODE, [dummy], [ | |
4449 | + mfmsr r3 // r3 = exception MSR | |
4450 | + ori r2,r3,MSR_DR | |
4451 | + bl 8f | |
4452 | + | |
4453 | + // secondary interrupt entry (we _know_ this must be a DSI) | |
4454 | +#ifdef CONFIG_SMP | |
4455 | + LOADI r5,EXTERN(compat_hash_table_lock) | |
4456 | + li r4,1 | |
4457 | + tophys r5,r5 | |
4458 | +7: lwarx r0,0,r5 // lock | |
4459 | + cmpwi r0,0 | |
4460 | + bne- 7b | |
4461 | + stwcx. r4,0,r5 | |
4462 | + bne- 7b | |
4463 | + isync | |
4464 | + tlbie r6 | |
4465 | + eieio | |
4466 | + tlbsync | |
4467 | + sync | |
4468 | + stw r0,0(r5) // release lock | |
4469 | +#else | |
4470 | + tlbie r6 // flush PTE from ITLB | |
4471 | +#endif | |
4472 | + b exception_return | |
4473 | +8: | |
4474 | + mtmsr r2 | |
4475 | + isync | |
4476 | + | |
4477 | + lwz r4,0(r6) // get opcode | |
4478 | + | |
4479 | + mtmsr r3 // restore exception MSR | |
4480 | + isync | |
4481 | +]) | |
4482 | + | |
4483 | +/************************************************************************/ | |
4484 | +/* Reserved / Kernel Vectors */ | |
4485 | +/************************************************************************/ | |
4486 | + | |
4487 | +VECTOR_KERNEL( 0x100, "System Reset", secint_bad ) | |
4488 | +VECTOR_KERNEL( 0x500, "External Interrupt", secint_bad ) | |
4489 | +VECTOR_KERNEL( 0x1400, "System Management Interrupt", secint_bad ) | |
4490 | +VECTOR_KERNEL( 0x1700, "Thermal Management Interrupt", secint_bad ) | |
4491 | + | |
4492 | +VECTOR_RESERVED( 0x200, "Machine Check", secint_bad ) | |
4493 | +VECTOR_RESERVED( 0xa00, "Reserved", secint_bad ) | |
4494 | +VECTOR_RESERVED( 0xb00, "Reserved", secint_bad ) | |
4495 | +VECTOR_RESERVED( 0xe00, "FPU Assist", secint_bad ) | |
4496 | + | |
4497 | +PERFMON_VECTOR_RELOCATION( PERFMON_VECTOR ) | |
4498 | +VECTOR_RESERVED( PERFMON_VECTOR, "Performance Monitor Interrupt", secint_bad ) | |
4499 | + | |
4500 | +//VECTOR_RESERVED( 0x1000, "InstructionTLBMiss-603", secint_bad ) | |
4501 | +//VECTOR_RESERVED( 0x1100, "DataLoadTLBMiss-603", secint_bad ) | |
4502 | +//VECTOR_RESERVED( 0x1200, "DataLoadTLBMiss-603", secint_bad ) | |
4503 | + | |
4504 | +/************************************************************************/ | |
4505 | +/* DSI Exceptions */ | |
4506 | +/************************************************************************/ | |
4507 | + | |
4508 | +VECTOR( 0x300, "DSI", secint_lr_call ) | |
4509 | + EXCEPTION_PREAMBLE | |
4510 | + TRACE(0x300, "DSI") | |
4511 | + | |
4512 | + GET_INSTR_OPCODE // m: r2-r3, ret: r4=opcode, r6=nip | |
4513 | + stw r4,xINST_OPCODE(r1) | |
4514 | + bl check_pthash_hit // m: r0,r2-r5 | |
4515 | + btl- FBIT_InSplitmode,splitmode_dsi | |
4516 | + bl save_middle_regs | |
4517 | + bl check_io_page | |
4518 | + | |
4519 | +dsi_cont: | |
4520 | + LOADI r3,EXTERN(dsi_exception) | |
4521 | + mfdar r4 // We might need to do this earlier | |
4522 | + mfdsisr r5 // when the splitmode code is activated... | |
4523 | + b call_kernel | |
4524 | + | |
4525 | + | |
4526 | +/************************************************************************/ | |
4527 | +/* ISI Exceptions */ | |
4528 | +/************************************************************************/ | |
4529 | + | |
4530 | +VECTOR( 0x400, "ISI", secint_bad ) | |
4531 | + EXCEPTION_PREAMBLE | |
4532 | + TRACE(0x400, "ISI") | |
4533 | + | |
4534 | + // emuaccel engine | |
4535 | + rlwinm. r0,r7,0,4,4 // protection violation | |
4536 | + beq- 1f | |
4537 | + lwz r3,K_EMUACCEL_MPHYS(r1) | |
4538 | + rlwinm r4,r6,0,~0x0fff // nip page | |
4539 | + rlwinm r2,r6,0,0x0ff8 // nip offset (dword align) | |
4540 | + lwz r5,K_EMUACCEL_PAGE_PHYS(r1) | |
4541 | + cmpw r3,r4 | |
4542 | + bne- 1f | |
4543 | + lwzux r0,r2,r5 // r0 = handler | |
4544 | + mtlr r0 | |
4545 | + lwz r6,4(r2) // address of next instruction | |
4546 | + blr // parameters: r2 == emuaccel_slot | |
4547 | +1: | |
4548 | + btl- FBIT_InSplitmode, split_sr_no_execute | |
4549 | + bl save_middle_regs | |
4550 | + | |
4551 | + LOADI r3,EXTERN(isi_exception) | |
4552 | + mfsrr0 r4 | |
4553 | + mfsrr1 r5 | |
4554 | + b call_kernel | |
4555 | + | |
4556 | + | |
4557 | +/************************************************************************/ | |
4558 | +/* Alignement Exception */ | |
4559 | +/************************************************************************/ | |
4560 | + | |
4561 | +VECTOR( 0x600, "Alignment", secint_lr_call ) | |
4562 | + EXCEPTION_SAVE_ALL | |
4563 | + TRACE(0x400, "Alignment") | |
4564 | + | |
4565 | +alignment_cont: | |
4566 | + mfdar r4 | |
4567 | + mfdsisr r5 | |
4568 | + MAC_EXIT( RVEC_ALIGNMENT_TRAP ) | |
4569 | + | |
4570 | + | |
4571 | +/************************************************************************/ | |
4572 | +/* FPU Unavailable Exception */ | |
4573 | +/************************************************************************/ | |
4574 | + | |
4575 | + // xFPU_STATE has only meaning when FBIT_FPUInUse is not set | |
4576 | + // | |
4577 | + // FPU_STATE_DIRTY - fr13 & fpscr are not loaded (everything else is). | |
4578 | + // FPU_STATE_HALF_SAVED - fr14-fr31 are loaded. | |
4579 | + // FPU_STATE_SAVED - fr14-fr31 are loaded (but also saved in mregs). | |
4580 | + // | |
4581 | + // FPU_STATE_DIRTY in the *emulator* means that all floating point | |
4582 | + // registers *EXCEPT* fr13 and fpscr are valid. | |
4583 | + // | |
4584 | + // Implementation note: When we do not own the fpu, the MSR_FEx bits | |
4585 | + // must be cleared. Otherwise we might experience bogus FPU exceptions. | |
4586 | + // | |
4587 | + // MOL will never throw FPU exceptions went the FP bit is off. This | |
4588 | + // is a small violation of the standard but the alternative would be | |
4589 | + // always loading FPSCR (which requires FPU ownership...) | |
4590 | + // | |
4591 | + | |
4592 | +VECTOR( 0x800, "FPU Unavailable", secint_lr_call ) | |
4593 | + EXCEPTION_PREAMBLE | |
4594 | + TRACE(0x800, "FPU Unavailable") | |
4595 | +fpu_cont: | |
4596 | + | |
4597 | + lwz r2,xMSR(r1) // r2 = xMSR (used below too) | |
4598 | + andi. r4,r2,MSR_FP | |
4599 | + beq- mac_fpu_unavailable // mac trap? | |
4600 | + bt FBIT_FPUInUse,2f // FPU ready for use? | |
4601 | + | |
4602 | + lwz r3,K_EMULATOR_MSR(r1) // FPU owned by our userland process? | |
4603 | + andi. r4,r3,MSR_FP | |
4604 | + bne+ 1f | |
4605 | + MAC_EXIT_SAVE( RVEC_ENABLE_FPU ) // No... grab FPU in userspace | |
4606 | + | |
4607 | +mac_fpu_unavailable: | |
4608 | + BUMP( "mac-fpu-trap" ) | |
4609 | + MAC_TRAP( 0x800 ) | |
4610 | + | |
4611 | + // userland process owns FPU | |
4612 | +1: BUMP( "enable-fpu" ) | |
4613 | + ENABLE_MSR_FP /**/ r4 // enable kernel FPU | |
4614 | + // flag the fpu dirty | |
4615 | + lwz r3,xFPU_STATE(r1) | |
4616 | + lfd fr13,xFPSCR-4(r1) // fp13 and fpscr are *ALWAYS* saved | |
4617 | + crset FBIT_FPUInUse // we own the FPU now | |
4618 | + cmpwi r3,FPU_STATE_HALF_SAVED | |
4619 | + mtfsf 0xff,fr13 | |
4620 | + lfd fr13,xFPR13(r1) | |
4621 | + bne 2f | |
4622 | + xLOAD_LOW_FPU r1 // load fr0-fr12 | |
4623 | +2: | |
4624 | + li r3,MSR_FP| MSR_FE0 | MSR_FE1 // FPU bits | |
4625 | + lwz r7,K_MSR(r1) // enable MSR_FP | |
4626 | + and r2,r2,r3 // r2 = (xMSR & MSR_FEx) | |
4627 | + andc r7,r7,r3 // K_MSR &= ~MSR_FEx | |
4628 | + or r7,r7,r2 // K_MSR |= (xMSR & MSR_FEx) | |
4629 | + stw r7,K_MSR(r1) | |
4630 | + GET_TICK_CNT(entry,"enable_fpu") | |
4631 | + b exception_return | |
4632 | + | |
4633 | + | |
4634 | +/************************************************************************/ | |
4635 | +/* Decrementer Exception */ | |
4636 | +/************************************************************************/ | |
4637 | + | |
4638 | +// The 0x900 decrementer vector is in dec.S | |
4639 | + | |
4640 | +/************************************************************************/ | |
4641 | +/* System Call Exception */ | |
4642 | +/************************************************************************/ | |
4643 | + | |
4644 | +VECTOR( 0xc00, "System Call", secint_bad ) | |
4645 | + EXCEPTION_PREAMBLE | |
4646 | + TRACE( 0xc00, "System Call") | |
4647 | + | |
4648 | + lwz r3,xGPR3(r1) | |
4649 | + LOADI r5,OSI_SC_MAGIC_R3 | |
4650 | + lwz r4,xGPR4(r1) | |
4651 | + LOADI r2,OSI_SC_MAGIC_R4 | |
4652 | + cmpw cr1,r3,r5 | |
4653 | + cmpw cr0,r4,r2 | |
4654 | + crand eq,eq,cr1_eq | |
4655 | + beq+ 2f | |
4656 | + | |
4657 | + MAC_TRAP(0xc00) // r7 reason bits used (zero) | |
4658 | +2: | |
4659 | + MAC_EXIT_SAVE( RVEC_OSI_SYSCALL ) | |
4660 | + | |
4661 | + | |
4662 | +/************************************************************************/ | |
4663 | +/* Trace Exception */ | |
4664 | +/************************************************************************/ | |
4665 | + | |
4666 | +VECTOR( 0xd00, "Trace", secint_bad ) | |
4667 | +trace_vector: | |
4668 | + EXCEPTION_PREAMBLE | |
4669 | + TRACE(0xd00, "Trace") | |
4670 | + | |
4671 | + MAC_EXIT_SAVE( RVEC_TRACE_TRAP ); | |
4672 | + | |
4673 | + | |
4674 | +/************************************************************************/ | |
4675 | +/* AltiVec Exception */ | |
4676 | +/************************************************************************/ | |
4677 | + | |
4678 | +VECTOR( 0xf20, "AltiVec", secint_lr_call ) | |
4679 | + EXCEPTION_PREAMBLE | |
4680 | + TRACE(0xf20, "AltiVec") | |
4681 | +altivec_cont: | |
4682 | + | |
4683 | + lwz r4,xNO_ALTIVEC(r1) // AltiVec support disabled? | |
4684 | + cmpwi r4,0 | |
4685 | + bne- mac_altivec_unavailable | |
4686 | + | |
4687 | + lwz r2,xMSR(r1) | |
4688 | + rlwinm. r4,r2,0,6,6 // bit 6 = MSR_VEC | |
4689 | + beq- mac_altivec_unavailable | |
4690 | + | |
4691 | + lwz r3,K_EMULATOR_MSR(r1) | |
4692 | + rlwinm. r4,r3,0,6,6 // bit 6 = MSR_VEC | |
4693 | + bne+ enable_altivec | |
4694 | + MAC_EXIT_SAVE( RVEC_ENABLE_ALTIVEC ) | |
4695 | + | |
4696 | +mac_altivec_unavailable: | |
4697 | + MAC_EXIT_SAVE( RVEC_ALTIVEC_UNAVAIL_TRAP ) | |
4698 | + | |
4699 | +enable_altivec: | |
4700 | + // We don't need to load any registers since the emulator | |
4701 | + // won't touch the altivec unit (at least for now). | |
4702 | + | |
4703 | + lwz r7,K_MSR(r1) | |
4704 | + oris r7,r7,HI(MSR_VEC) | |
4705 | + stw r7,K_MSR(r1) | |
4706 | + b exception_return | |
4707 | + | |
4708 | + | |
4709 | +VECTOR( 0x1600, "AltiVec Assist", secint_bad ) | |
4710 | + EXCEPTION_SAVE_ALL | |
4711 | + TRACE(0x1600, "AltiVec Assist") | |
4712 | + | |
4713 | + mr r4,r7 | |
4714 | + MAC_EXIT( RVEC_ALTIVEC_ASSIST ) // r4 = srr1 | |
4715 | + | |
4716 | + | |
4717 | +/************************************************************************/ | |
4718 | +/* Instruction Breakpoint */ | |
4719 | +/************************************************************************/ | |
4720 | + | |
4721 | +VECTOR( 0x1300, "Instruction Breakpoint", secint_bad ) | |
4722 | + EXCEPTION_SAVE_ALL | |
4723 | + TRACE(0x1300, "IABR") | |
4724 | + | |
4725 | + DEBUGGER(0x1300) | |
4726 | + | |
4727 | + | |
4728 | +/************************************************************************/ | |
4729 | +/* RunMode-601 (trace) */ | |
4730 | +/************************************************************************/ | |
4731 | + | |
4732 | +VECTOR( 0x2000, "RunMode-601", secint_bad ) | |
4733 | + b trace_vector | |
4734 | + | |
4735 | + | |
4736 | +/************************************************************************/ | |
4737 | +/* Secondary Interrupt Handlers */ | |
4738 | +/************************************************************************/ | |
4739 | + | |
4740 | + ////////////////////////////////////////////////////////////////////// | |
4741 | + // secint_xxx | |
4742 | + // | |
4743 | + // r1: stack (sprg1 = old r1) | |
4744 | + // r3: vector addr (sprg0 = old r3) | |
4745 | + // srr0/srr1: kernel nip/msr | |
4746 | + // | |
4747 | + // secint_lr_call: | |
4748 | + // lr secondary interrupt handler | |
4749 | + | |
4750 | +secint_bad: | |
4751 | + TRACE(0xbad, "secint_bad") | |
4752 | + mr r4,r3 | |
4753 | + MAC_EXIT( RVEC_INTERNAL_ERROR ) | |
4754 | + | |
4755 | +secint_lr_call: | |
4756 | + blrl | |
4757 | + li r4,0x6666 | |
4758 | + MAC_EXIT( RVEC_INTERNAL_ERROR ) | |
4759 | + | |
4760 | + | |
4761 | +/************************************************************** | |
4762 | +* Includes | |
4763 | +**************************************************************/ | |
4764 | + | |
4765 | +// We need to be sure this code is contiguous, the simplest/safest | |
4766 | +// method is using only a single file. This will also effectively | |
4767 | +// reduce the size of the relocation table. | |
4768 | + | |
4769 | +#ifdef __darwin__ | |
4770 | +#include "darwin.S" | |
4771 | +#endif | |
4772 | +#include "entry.S" | |
4773 | +#include "dec.S" | |
4774 | +#include "emulation.S" | |
4775 | +#include "emuaccel.S" | |
4776 | +#include "iopage.S" | |
4777 | +#include "splitmode.S" | |
4778 | +#include "ptintercept.S" | |
4779 | +#include "vsid.S" | |
4780 | +#ifdef __MPC107__ | |
4781 | +#include "./mpc107/mpc107.S" | |
4782 | +#else | |
4783 | +#ifdef __linux__ | |
4784 | +#include "linux.S" | |
4785 | +#include "603.S" | |
4786 | +#endif | |
4787 | +#endif | |
4788 | + | |
4789 | +#ifdef __linux__ | |
4790 | + .text 50 | |
4791 | +#endif | |
4792 | +GLOBAL_SYMBOL(r__reloctable_end): | |
4793 | + | |
4794 | + ACTIONS_OFFS_SECTION | |
4795 | +GLOBAL_SYMBOL(r__actions_offs_section_end): | |
4796 | + | |
4797 | +// The BUMP("counter") macro adds entries to text subsection 90. | |
4798 | +// This adds labels before the counter entries. | |
4799 | + | |
4800 | +#ifdef __linux__ | |
4801 | + .text 89 | |
4802 | +GLOBAL_SYMBOL(__start_bumptable): | |
4803 | + .text 91 | |
4804 | +GLOBAL_SYMBOL(__end_bumptable): | |
4805 | + .text | |
4806 | +#endif | |
4807 | --- /dev/null | |
4808 | +++ b/drivers/macintosh/mol/asm-files/vsid.S | |
4809 | @@ -0,0 +1,123 @@ | |
4810 | +/* | |
4811 | + * Creation Date: <2003/03/06 22:03:59 samuel> | |
4812 | + * Time-stamp: <2004/02/21 16:30:45 samuel> | |
4813 | + * | |
4814 | + * <vsid.S> | |
4815 | + * | |
4816 | + * VSID lookup (skiplist search) | |
4817 | + * | |
4818 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
4819 | + * | |
4820 | + * This program is free software; you can redistribute it and/or | |
4821 | + * modify it under the terms of the GNU General Public License | |
4822 | + * as published by the Free Software Foundation | |
4823 | + * | |
4824 | + */ | |
4825 | + | |
4826 | +#include "mtable.h" | |
4827 | + | |
4828 | +#if (SKIPLIST_LEVELSIZE == 4) | |
4829 | +#define SLEVEL_SHIFT 2 | |
4830 | +#endif | |
4831 | +#if (SKIPLIST_LEVELSIZE == 8) | |
4832 | +#define SLEVEL_SHIFT 3 | |
4833 | +#endif | |
4834 | + | |
4835 | +emulate_mtsrin: | |
4836 | + rlwinm r2,r4,32-8,24,28 // r2 = #B << 8 | |
4837 | + EMU_LOAD_GPR r2, /**/ R3 // r0 = reg B | |
4838 | + rlwinm r4,r0,0,0,3 // #sr top 4 bits of r4 | |
4839 | + b 1f | |
4840 | +emulate_mtsr: | |
4841 | + rlwinm r4,r4,12,0,3 // #sr in top 4 bits of r4 | |
4842 | +1: EMU_LOAD_GPR r5, /**/ R2 // r0 = new segr value | |
4843 | + | |
4844 | + stw r8,xGPR8(r1) // save r8 | |
4845 | + rlwinm r8,r4,6,26,29 // r8 = #sr << 2 | |
4846 | + stw r9,xGPR9(r1) // save r9 | |
4847 | + add r8,r8,r1 // r8 = r1 + sr_offset | |
4848 | + stw r6,xNIP(r1) // save r6 (need more registers) | |
4849 | + rlwinm r9,r0,0,0,3 // r9 = [T Ks Kp N] | |
4850 | + stw r0,xSEGR_BASE(r8) // store new value | |
4851 | + rlwinm r0,r0,0,8,31 // mask VSID | |
4852 | + | |
4853 | + /******* vsid lookup (skiplist search) *******/ | |
4854 | + | |
4855 | + lwz r2,K_VSID_SL_SLEVEL(r1) // n = search level (0..15) | |
4856 | + rlwinm r2,r2,SLEVEL_SHIFT,0,29 // n *= 4 (or n *= 8 on darwin) | |
4857 | + | |
4858 | + addi r3,r1,K_VSID_SL_ROOT_ELEM // p = root element | |
4859 | +1: add r5,r2,r3 // | |
4860 | +2: lwz r3,SKIPLIST_NEXT(r5) // r3 = p->next[n] | |
4861 | +#ifdef __linux__ | |
4862 | + tophys R3,R3 | |
4863 | +#endif | |
4864 | + lwz r4,SKIPLIST_KEY(r3) // r0 = p->next[n].key | |
4865 | + cmpw cr1,r4,r0 | |
4866 | + bge- cr1,3f | |
4867 | + b 1b | |
4868 | +3: | |
4869 | + addi r2,r2,-SKIPLIST_LEVELSIZE // r2 -= 4|8 | |
4870 | + beq- cr1,vsid_found // jump if key matches | |
4871 | + cmpwi r2,0 | |
4872 | + addi r5,r5,-SKIPLIST_LEVELSIZE // r5 -= 4|8 | |
4873 | + bge+ 2b | |
4874 | + | |
4875 | + /******* vsid missing *******/ | |
4876 | + BUMP("vsid_missing") | |
4877 | + // r8 used | |
4878 | + lwz r2,K_ILLEGAL_SR(r1) // vsid unallocated... | |
4879 | + li r4,0 // no entry... | |
4880 | + stw r2,K_SV_SR_BASE(r8) | |
4881 | + stw r2,K_USER_SR_BASE(r8) | |
4882 | + stw r2,K_SPLIT_SR_BASE(r8) // this way we can forget the splitmode case | |
4883 | + stw r4,K_VSID_ENT_BASE(r8) | |
4884 | + sub r5,r8,r1 // r5 = VSID offset | |
4885 | + lwz r0,K_CUR_SR_BASE(r1) // r0 = cur_sr_table | |
4886 | + b 6f | |
4887 | + | |
4888 | + /******* vsid found *******/ | |
4889 | +vsid_found: | |
4890 | + | |
4891 | + BUMP("vsid_found") | |
4892 | + // match, r3 points to the skiplist element | |
4893 | + addi r4,r3,-SIZEOF_VSID_ENT // sizeof(vsid_ent_t) | |
4894 | + lwz r2,VSID_USER_OFFS(r4) // vsid_user | |
4895 | + lwz r3,VSID_SV_OFFS(r4) // vsid_sv | |
4896 | +#ifdef __linux__ | |
4897 | + tovirt R4,R4 // r4 = vsid_element | |
4898 | +#else | |
4899 | + lwz r4,VSID_MYSELF_VIRT(r4) | |
4900 | +#endif | |
4901 | + rlwinm r6,r9,2,31,31 // r6 = Ks ? 1:0 | |
4902 | + stw r4,K_VSID_ENT_BASE(r8) // store vsid entry (possibly NULL) | |
4903 | + rlwinm r4,r9,3,31,31 // r4 = Kp ? 1:0 | |
4904 | + rlwimi r2,r9,0,3,3 // copy the N-bit (no-execute) | |
4905 | + rlwimi r3,r9,0,3,3 // copy the N-bit (no-execute) | |
4906 | + cror FBIT_LoadSegreg, FBIT_LoadSegreg, FBIT_InSplitmode | |
4907 | + addi r6,r6,-1 // r6 = Ks-mask | |
4908 | + addi r4,r4,-1 // r4 = Kp-mask | |
4909 | + andc r0,r2,r6 // Kp == 1 case | |
4910 | + and r6,r3,r6 // Kp == 0 case | |
4911 | + crmove FBIT_PrepareSplitmode, FBIT_InSplitmode | |
4912 | + andc r9,r2,r4 // Ks == 1 case | |
4913 | + or r6,r6,r0 | |
4914 | + lwz r0,K_CUR_SR_BASE(r1) // r0 = cur_sr_table | |
4915 | + and r4,r3,r4 // Ks == 0 case | |
4916 | + stw r6,K_SV_SR_BASE(r8) // sv_sr set | |
4917 | + or r4,r4,r9 | |
4918 | + sub r5,r8,r1 // r5 = VSID offset | |
4919 | + stw r4,K_USER_SR_BASE(r8) // user_sr set | |
4920 | +6: | |
4921 | + // r0,r5 used | |
4922 | + rlwinm r2,r5,32-6,0,3 // r2 = sr# in bits 0-3 | |
4923 | + lwzx r3,r5,r0 // r3 = sr to be loaded into sr# | |
4924 | + mtsrin r3,r2 // update segment register | |
4925 | + | |
4926 | + lwz r6,xNIP(r1) // restore r6 | |
4927 | + lwz r8,xGPR8(r1) // restore r8 | |
4928 | + lwz r9,xGPR9(r1) // restore r9 | |
4929 | + GET_TICK_CNT(entry, "mtsr") | |
4930 | + BUMP("mtsr_") | |
4931 | + b emulation_done | |
4932 | + | |
4933 | --- /dev/null | |
4934 | +++ b/drivers/macintosh/mol/asm_offsets.c | |
4935 | @@ -0,0 +1,161 @@ | |
4936 | +/* | |
4937 | + * This program is used to generate definitions needed by | |
4938 | + * some assembly functions. | |
4939 | + * | |
4940 | + * We use the technique used in the OSF Mach kernel code: | |
4941 | + * generate asm statements containing #defines, | |
4942 | + * compile this file to assembler, and then extract the | |
4943 | + * #defines from the assembly-language output. | |
4944 | + */ | |
4945 | + | |
4946 | +#ifdef __KERNEL__ | |
4947 | +#include "archinclude.h" | |
4948 | +#include "kernel_vars.h" | |
4949 | +#include "mmu.h" | |
4950 | +#else | |
4951 | +#include "mol_config.h" | |
4952 | +#include <stddef.h> | |
4953 | +#include "mac_registers.h" | |
4954 | +#endif | |
4955 | + | |
4956 | +#include "processor.h" | |
4957 | + | |
4958 | +#define DEFINE(sym, val) \ | |
4959 | + asm volatile("\n#define\t" #sym "\t%0" : : "i" (val)) | |
4960 | + | |
4961 | +#define K_DEF(sym, val ) \ | |
4962 | + DEFINE(sym, offsetof(kernel_vars_t, val )) | |
4963 | + | |
4964 | +#define ST_DEF(sym, val ) \ | |
4965 | + DEFINE(sym, offsetof(session_table_t, val )) | |
4966 | + | |
4967 | +#define M_DEF(sym, val ) \ | |
4968 | + DEFINE(sym, XOFFS + offsetof(mac_regs_t, val )) | |
4969 | + | |
4970 | +#define IO_DEF(sym, val) \ | |
4971 | + DEFINE(sym, offsetof(struct io_page, val )) | |
4972 | + | |
4973 | +int main( void ) | |
4974 | +{ | |
4975 | +#ifdef __KERNEL__ | |
4976 | + #define XOFFS offsetof(kernel_vars_t, mregs) | |
4977 | +#else | |
4978 | + #define XOFFS 0 | |
4979 | +#endif | |
4980 | + /* --- mac_regs offsets --- */ | |
4981 | + | |
4982 | + M_DEF( xVEC_BASE, vec[0] ); | |
4983 | + M_DEF( xVEC0, vec[0] ); | |
4984 | + M_DEF( xVEC1, vec[1] ); | |
4985 | + M_DEF( xVEC2, vec[2] ); | |
4986 | + M_DEF( xVSCR, vscr ); | |
4987 | + M_DEF( xVRSAVE, spr[S_VRSAVE] ); | |
4988 | + | |
4989 | + M_DEF( xGPR_BASE, gpr[0] ); | |
4990 | + M_DEF( xGPR0, gpr[0] ); | |
4991 | + M_DEF( xGPR1, gpr[1] ); | |
4992 | + M_DEF( xGPR2, gpr[2] ); | |
4993 | + M_DEF( xGPR3, gpr[3] ); | |
4994 | + M_DEF( xGPR4, gpr[4] ); | |
4995 | + M_DEF( xGPR5, gpr[5] ); | |
4996 | + M_DEF( xGPR6, gpr[6] ); | |
4997 | + M_DEF( xGPR7, gpr[7] ); | |
4998 | + M_DEF( xGPR8, gpr[8] ); | |
4999 | + M_DEF( xGPR9, gpr[9] ); | |
5000 | + M_DEF( xGPR10, gpr[10] ); | |
5001 | + M_DEF( xGPR11, gpr[11] ); | |
5002 | + M_DEF( xGPR12, gpr[12] ); | |
5003 | + M_DEF( xGPR13, gpr[13] ); | |
5004 | + M_DEF( xGPR14, gpr[14] ); | |
5005 | + M_DEF( xGPR15, gpr[15] ); | |
5006 | + M_DEF( xGPR16, gpr[16] ); | |
5007 | + M_DEF( xGPR17, gpr[17] ); | |
5008 | + M_DEF( xGPR18, gpr[18] ); | |
5009 | + M_DEF( xGPR19, gpr[19] ); | |
5010 | + M_DEF( xGPR20, gpr[20] ); | |
5011 | + M_DEF( xGPR21, gpr[21] ); | |
5012 | + M_DEF( xGPR22, gpr[22] ); | |
5013 | + M_DEF( xGPR23, gpr[23] ); | |
5014 | + M_DEF( xGPR24, gpr[24] ); | |
5015 | + M_DEF( xGPR25, gpr[25] ); | |
5016 | + M_DEF( xGPR26, gpr[26] ); | |
5017 | + M_DEF( xGPR27, gpr[27] ); | |
5018 | + M_DEF( xGPR28, gpr[28] ); | |
5019 | + M_DEF( xGPR29, gpr[29] ); | |
5020 | + M_DEF( xGPR30, gpr[30] ); | |
5021 | + M_DEF( xGPR31, gpr[31] ); | |
5022 | + | |
5023 | + M_DEF( xNIP, nip); | |
5024 | + M_DEF( xCR, cr); | |
5025 | + M_DEF( xFPR_BASE, fpr[0]); | |
5026 | + M_DEF( xFPR13, fpr[13]); | |
5027 | + M_DEF( xFPSCR, fpscr ); | |
5028 | + M_DEF( xEMULATOR_FPSCR, emulator_fpscr ); | |
5029 | + M_DEF( xFPU_STATE, fpu_state ); | |
5030 | + | |
5031 | + M_DEF( xLINK, link); | |
5032 | + M_DEF( xXER, xer); | |
5033 | + M_DEF( xCTR, ctr); | |
5034 | + M_DEF( xFLAG_BITS, flag_bits ); | |
5035 | + M_DEF( xDEC, spr[S_DEC]); | |
5036 | + M_DEF( xDEC_STAMP, dec_stamp); | |
5037 | + M_DEF( xTIMER_STAMP, timer_stamp); | |
5038 | + M_DEF( xMSR, msr); | |
5039 | + M_DEF( xSPR_BASE, spr[0]); | |
5040 | + | |
5041 | + M_DEF( xHID0, spr[S_HID0]); | |
5042 | + | |
5043 | + M_DEF( xSRR0, spr[S_SRR0]); | |
5044 | + M_DEF( xSRR1, spr[S_SRR1]); | |
5045 | + | |
5046 | + M_DEF( xSPRG0, spr[S_SPRG0]); | |
5047 | + M_DEF( xSPRG1, spr[S_SPRG1]); | |
5048 | + M_DEF( xSPRG2, spr[S_SPRG2]); | |
5049 | + M_DEF( xSPRG3, spr[S_SPRG3]); | |
5050 | + | |
5051 | + M_DEF( xSEGR_BASE, segr[0]); | |
5052 | + M_DEF( xIBAT_BASE, spr[S_IBAT0U] ); | |
5053 | + M_DEF( xSDR1, spr[S_SDR1] ); | |
5054 | + | |
5055 | + M_DEF( xINST_OPCODE, inst_opcode ); | |
5056 | + M_DEF( xALTIVEC_USED, altivec_used ); | |
5057 | + M_DEF( xNO_ALTIVEC, no_altivec ); | |
5058 | + | |
5059 | + M_DEF( xINTERRUPT, interrupt ); | |
5060 | + M_DEF( xIN_VIRTUAL_MODE, in_virtual_mode ); | |
5061 | + | |
5062 | + M_DEF( xRVEC_PARAM0, rvec_param[0] ); | |
5063 | + M_DEF( xRVEC_PARAM1, rvec_param[1] ); | |
5064 | + M_DEF( xRVEC_PARAM2, rvec_param[2] ); | |
5065 | + | |
5066 | +#ifdef EMULATE_603 | |
5067 | + M_DEF( xGPRSAVE0_603, gprsave_603[0] ); | |
5068 | + M_DEF( xGPRSAVE1_603, gprsave_603[1] ); | |
5069 | + M_DEF( xGPRSAVE2_603, gprsave_603[2] ); | |
5070 | + M_DEF( xGPRSAVE3_603, gprsave_603[3] ); | |
5071 | +#endif | |
5072 | + | |
5073 | + M_DEF( xDEBUG0, debug[0] ); | |
5074 | + M_DEF( xDEBUG1, debug[1] ); | |
5075 | + M_DEF( xDEBUG2, debug[2] ); | |
5076 | + M_DEF( xDEBUG3, debug[3] ); | |
5077 | + M_DEF( xDEBUG4, debug[4] ); | |
5078 | + M_DEF( xDEBUG5, debug[5] ); | |
5079 | + M_DEF( xDEBUG6, debug[6] ); | |
5080 | + M_DEF( xDEBUG7, debug[7] ); | |
5081 | + M_DEF( xDEBUG8, debug[8] ); | |
5082 | + M_DEF( xDEBUG9, debug[9] ); | |
5083 | + | |
5084 | + M_DEF( xDEBUG_SCR1, debug_scr1 ); | |
5085 | + M_DEF( xDEBUG_SCR2, debug_scr2 ); | |
5086 | + M_DEF( xDEBUG_TRACE, debug_trace ); | |
5087 | + M_DEF( xDBG_TRACE_SPACE, dbg_trace_space[0] ); | |
5088 | + M_DEF( xDBG_LAST_RVEC, dbg_last_rvec ); | |
5089 | + | |
5090 | + M_DEF( xKERNEL_DBG_STOP, kernel_dbg_stop ); | |
5091 | + | |
5092 | + M_DEF( xHOSTIRQ_ACTIVE_CNT, hostirq_active_cnt ); | |
5093 | + | |
5094 | + return 0; | |
5095 | +} | |
5096 | + | |
5097 | --- /dev/null | |
5098 | +++ b/drivers/macintosh/mol/context.c | |
5099 | @@ -0,0 +1,99 @@ | |
5100 | +/* | |
5101 | + * Creation Date: <1998-11-20 16:18:20 samuel> | |
5102 | + * Time-stamp: <2004/02/28 19:16:44 samuel> | |
5103 | + * | |
5104 | + * <context.c> | |
5105 | + * | |
5106 | + * MMU context allocation | |
5107 | + * | |
5108 | + * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se) | |
5109 | + * | |
5110 | + * This program is free software; you can redistribute it and/or | |
5111 | + * modify it under the terms of the GNU General Public License | |
5112 | + * as published by the Free Software Foundation | |
5113 | + * | |
5114 | + */ | |
5115 | + | |
5116 | +#include "archinclude.h" | |
5117 | +#include "alloc.h" | |
5118 | +#include "mmu.h" | |
5119 | +#include "mmu_contexts.h" | |
5120 | +#include "misc.h" | |
5121 | +#include "asmfuncs.h" | |
5122 | +#include "emu.h" | |
5123 | +#include "mtable.h" | |
5124 | +#include "performance.h" | |
5125 | +#include "context.h" | |
5126 | +#include "hash.h" | |
5127 | + | |
5128 | +#define MMU (kv->mmu) | |
5129 | + | |
5130 | + | |
5131 | +static int | |
5132 | +flush_all_PTEs( kernel_vars_t *kv ) | |
5133 | +{ | |
5134 | + int i, count=0, npte=(ptehash.pte_mask + 8)/8; | |
5135 | + ulong *pte, ea, v; | |
5136 | + | |
5137 | + for( pte=ptehash.base, i=0; i<npte; i++, pte+=2 ) { | |
5138 | + v = *pte; | |
5139 | + if( !(v & BIT(0)) ) /* test V-bit */ | |
5140 | + continue; | |
5141 | + v = (v & ~BIT(0)) >> 7; | |
5142 | + v = (v - ((v & 0xf) * MUNGE_ESID_ADD)) * MUNGE_MUL_INVERSE; | |
5143 | + v = (v>>4) & CTX_MASK; | |
5144 | + | |
5145 | + if( v >= MMU.first_mol_context && v <= MMU.last_mol_context ) { | |
5146 | + *pte = 0; | |
5147 | + count++; | |
5148 | + } | |
5149 | + } | |
5150 | + | |
5151 | + /* perform a tlbia */ | |
5152 | + for( ea=0; ea <= (0x3f << 12); ea += 0x1000 ) | |
5153 | + __tlbie( ea ); | |
5154 | + | |
5155 | + if( count ) | |
5156 | + printk("%d stale PTEs flushed (something is wrong)\n", count ); | |
5157 | + return count; | |
5158 | +} | |
5159 | + | |
5160 | +int | |
5161 | +init_contexts( kernel_vars_t *kv ) | |
5162 | +{ | |
5163 | + MMU.first_mol_context = FIRST_MOL_CONTEXT( kv->session_index ); | |
5164 | + MMU.last_mol_context = LAST_MOL_CONTEXT( kv->session_index ); | |
5165 | + MMU.next_mol_context = MMU.first_mol_context; | |
5166 | + | |
5167 | + MMU.illegal_sr = alloc_context(kv) | VSID_Kp | VSID_N; | |
5168 | + | |
5169 | + flush_all_PTEs( kv ); | |
5170 | + return 0; | |
5171 | +} | |
5172 | + | |
5173 | +void | |
5174 | +cleanup_contexts( kernel_vars_t *kv ) | |
5175 | +{ | |
5176 | + flush_all_PTEs( kv ); | |
5177 | +} | |
5178 | + | |
5179 | +void | |
5180 | +handle_context_wrap( kernel_vars_t *kv, int n ) | |
5181 | +{ | |
5182 | + if( MMU.next_mol_context + n > MMU.last_mol_context ) { | |
5183 | + printk("MOL context wrap\n"); | |
5184 | + | |
5185 | + clear_all_vsids( kv ); | |
5186 | + init_contexts( kv ); | |
5187 | + } | |
5188 | +} | |
5189 | + | |
5190 | +int | |
5191 | +alloc_context( kernel_vars_t *kv ) | |
5192 | +{ | |
5193 | + int mol_context = MMU.next_mol_context++; | |
5194 | + int vsid = MUNGE_CONTEXT(mol_context >> 4); | |
5195 | + | |
5196 | + vsid += MUNGE_ESID_ADD * (mol_context & 0xf); | |
5197 | + return (vsid & VSID_MASK); | |
5198 | +} | |
5199 | --- /dev/null | |
5200 | +++ b/drivers/macintosh/mol/emu.c | |
5201 | @@ -0,0 +1,228 @@ | |
5202 | +/* | |
5203 | + * Creation Date: <1998-11-21 16:07:47 samuel> | |
5204 | + * Time-stamp: <2004/03/13 14:08:18 samuel> | |
5205 | + * | |
5206 | + * <emu.c> | |
5207 | + * | |
5208 | + * Emulation of some assembly instructions | |
5209 | + * | |
5210 | + * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se) | |
5211 | + * | |
5212 | + * This program is free software; you can redistribute it and/or | |
5213 | + * modify it under the terms of the GNU General Public License | |
5214 | + * as published by the Free Software Foundation | |
5215 | + * | |
5216 | + */ | |
5217 | + | |
5218 | +#include "archinclude.h" | |
5219 | +#include "alloc.h" | |
5220 | +#include "mmu.h" | |
5221 | +#include "kernel_vars.h" | |
5222 | +#include "emu.h" | |
5223 | +#include "asmfuncs.h" | |
5224 | +#include "rvec.h" | |
5225 | +#include "processor.h" | |
5226 | +#include "mtable.h" | |
5227 | +#include "performance.h" | |
5228 | +#include "emuaccel_sh.h" | |
5229 | +#include "misc.h" | |
5230 | +#include "map.h" | |
5231 | + | |
5232 | +#define BAT_PERFORMANCE_HACK | |
5233 | +// #define DEBUG | |
5234 | + | |
5235 | +/* If BAT_PERFORMANCE_HACK is defined, PTEs corresponding to a mac bat | |
5236 | + * mapping will not necessary be flushed when the bat registers are | |
5237 | + * touched. This gives a huge performance gain in MacOS 9.1 (which | |
5238 | + * clears the bat registers in the idle loop). Of course, this break | |
5239 | + * compatibility (although most operating systems initializes the | |
5240 | + * BATs once and for all). | |
5241 | + */ | |
5242 | + | |
5243 | +#ifdef BAT_PERFORMANCE_HACK | |
5244 | + #define BAT_HACK(kv) (!MREGS.use_bat_hack || kv->mmu.bat_hack_count++ < 0x100) | |
5245 | +#else | |
5246 | + #define BAT_HACK(kv) 1 | |
5247 | +#endif | |
5248 | + | |
5249 | +#define MREGS (kv->mregs) | |
5250 | +#define MMU (kv->mmu) | |
5251 | + | |
5252 | + | |
5253 | +int | |
5254 | +do_mtsdr1( kernel_vars_t *kv, ulong value ) | |
5255 | +{ | |
5256 | + ulong mbase, mask; | |
5257 | + int s; | |
5258 | + | |
5259 | + MREGS.spr[S_SDR1] = value; | |
5260 | + | |
5261 | + /* the mask must be a valid one; we hade better make sure we are | |
5262 | + * not tricked by a bogus sdr1 value | |
5263 | + */ | |
5264 | + for( mask=BIT(23); mask && !(mask & value) ; mask=mask>>1 ) | |
5265 | + ; | |
5266 | + mask = mask? ((mask | (mask-1)) << 16) | 0xffff : 0xffff; | |
5267 | + mbase = value & ~mask; | |
5268 | + | |
5269 | + if( mbase + mask >= MMU.ram_size ) { | |
5270 | + /* S_SDR1 out of range, fallback to a safe setting */ | |
5271 | + printk("WARNING, S_SDR1, %08lX is out of range\n", value); | |
5272 | + mbase = 0; | |
5273 | + mask = 0xffff; | |
5274 | + } | |
5275 | + | |
5276 | + MMU.hash_mbase = mbase; | |
5277 | + MMU.hash_mask = mask; | |
5278 | + MMU.pthash_sr = -1; /* clear old tlbhash matching */ | |
5279 | + | |
5280 | + if( MMU.hash_base ) | |
5281 | + unmap_emulated_hash( kv ); | |
5282 | + MMU.hash_base = map_emulated_hash( kv, MMU.hash_mbase, mask+1 ); | |
5283 | + | |
5284 | + /* try to allocate the PTE bitfield table (16K/128 MB ram). The worst | |
5285 | + * case is 512K which will fail since the kmalloc limit is 128K. | |
5286 | + * If the allocation fails, we simply don't use the bitfield table. | |
5287 | + */ | |
5288 | + s = (mask+1)/8/8; | |
5289 | + if( MMU.pthash_inuse_bits ) | |
5290 | + kfree_cont_mol( MMU.pthash_inuse_bits ); | |
5291 | + if( !(MMU.pthash_inuse_bits=kmalloc_cont_mol(s)) ) | |
5292 | + MMU.pthash_inuse_bits_ph = 0; | |
5293 | + else { | |
5294 | + memset( MMU.pthash_inuse_bits, 0, s ); | |
5295 | + MMU.pthash_inuse_bits_ph = tophys_mol( MMU.pthash_inuse_bits ); | |
5296 | + } | |
5297 | + | |
5298 | + /* make sure the unmapped ram range is flushed... */ | |
5299 | + flush_lv_range( kv, MMU.userspace_ram_base + mbase, mask+1 ); | |
5300 | + | |
5301 | + /* ...as well as any MMU mappings */ | |
5302 | + clear_pte_hash_table( kv ); | |
5303 | + | |
5304 | + BUMP(do_mtsdr1); | |
5305 | + return RVEC_NOP; | |
5306 | +} | |
5307 | + | |
5308 | +/* This function is _very_ slow, since it must destroy a lot of PTEs. | |
5309 | + * Fortunately, BAT-maps are normally static. | |
5310 | + */ | |
5311 | +int | |
5312 | +do_mtbat( kernel_vars_t *kv, int sprnum, ulong value, int force ) | |
5313 | +{ | |
5314 | + mac_bat_t *d; | |
5315 | + int batnum; | |
5316 | + mBAT *p; | |
5317 | + | |
5318 | + BUMP(do_mtbat); | |
5319 | + | |
5320 | + if( !force && MREGS.spr[sprnum] == value ) | |
5321 | + return RVEC_NOP; | |
5322 | + | |
5323 | + /* printk("do_mtbat %d %08lX\n", sprnum, value); */ | |
5324 | + | |
5325 | + MREGS.spr[sprnum] = value; | |
5326 | + | |
5327 | + /* upper bat register have an even number */ | |
5328 | + batnum = (sprnum - S_IBAT0U) >>1; | |
5329 | + d = &MMU.bats[batnum]; | |
5330 | + | |
5331 | + /* First we must make sure that all PTEs corresponding to | |
5332 | + * the old BAT-mapping are purged from the hash table. | |
5333 | + */ | |
5334 | + if( BAT_HACK(kv) && d->valid ) | |
5335 | + flush_ea_range(kv, d->base & ~0xf0000000, d->size ); | |
5336 | + | |
5337 | + p = (mBAT*)&MREGS.spr[sprnum & ~1]; | |
5338 | + d->valid = p->batu.vs | p->batu.vp; | |
5339 | + d->vs = p->batu.vs; | |
5340 | + d->vp = p->batu.vp; | |
5341 | + d->wimg = (p->batl.w<<3) | (p->batl.i<<2) | (p->batl.m<<1) | p->batl.g; | |
5342 | + d->ks = d->ku = 1; /* IBAT/DBATs, behaves as if key==1 */ | |
5343 | + d->pp = p->batl.pp; | |
5344 | + d->size = (p->batu.bl+1)<<17; | |
5345 | + d->base = (p->batu.bepi & ~p->batu.bl)<<17; | |
5346 | + d->mbase = (p->batl.brpn & ~p->batu.bl)<<17; | |
5347 | + | |
5348 | + /* Next, we must make sure that no PTEs refer to the new | |
5349 | + * BAT-mapped area. | |
5350 | + */ | |
5351 | + | |
5352 | + if( BAT_HACK(kv) && d->valid ) | |
5353 | + flush_ea_range( kv, d->base & ~0xf0000000, d->size ); | |
5354 | + | |
5355 | + return RVEC_NOP; | |
5356 | +} | |
5357 | + | |
5358 | + | |
5359 | +/************************************************************************/ | |
5360 | +/* Emulation acceleration */ | |
5361 | +/************************************************************************/ | |
5362 | + | |
5363 | +static ulong | |
5364 | +lookup_emuaccel_handler( int emuaccel ) | |
5365 | +{ | |
5366 | + extern ulong emuaccel_table[]; | |
5367 | + ulong handler, *p = emuaccel_table; | |
5368 | + | |
5369 | + for( ; p[0]; p+=3 ) { | |
5370 | + if( (emuaccel & EMUACCEL_INST_MASK) != p[0] ) | |
5371 | + continue; | |
5372 | + emuaccel &= p[2]; /* offset mask */ | |
5373 | + handler = p[1] + (ulong)emuaccel_table + emuaccel * 8; | |
5374 | + return tophys_mol( (ulong*)reloc_ptr(handler) ); | |
5375 | + } | |
5376 | + return 0; | |
5377 | +} | |
5378 | + | |
5379 | +int | |
5380 | +alloc_emuaccel_slot( kernel_vars_t *kv, int emuaccel, int param, int inst_addr ) | |
5381 | +{ | |
5382 | + ulong *p = (ulong*)((char*)kv->emuaccel_page + kv->emuaccel_size); | |
5383 | + ulong handler = lookup_emuaccel_handler( emuaccel ); | |
5384 | + int size, ret; | |
5385 | + | |
5386 | + size = (emuaccel & EMUACCEL_HAS_PARAM)? 16 : 8; | |
5387 | + if( !handler || !p || kv->emuaccel_size + size > 0x1000 ) | |
5388 | + return 0; | |
5389 | + | |
5390 | + ret = kv->emuaccel_mphys + kv->emuaccel_size; | |
5391 | + p[0] = handler; | |
5392 | + p[1] = inst_addr + 4; | |
5393 | + | |
5394 | + if( emuaccel & EMUACCEL_HAS_PARAM ) { | |
5395 | + /* p[2] is already EMUACCEL_NOP */ | |
5396 | + p[3] = param; | |
5397 | + } | |
5398 | + | |
5399 | + kv->emuaccel_size += size; | |
5400 | + return ret; | |
5401 | +} | |
5402 | + | |
5403 | +int | |
5404 | +mapin_emuaccel_page( kernel_vars_t *kv, int mphys ) | |
5405 | +{ | |
5406 | + int i, handler; | |
5407 | + ulong *p; | |
5408 | + | |
5409 | + if( kv->emuaccel_page || (mphys & 0xfff) ) | |
5410 | + return 0; | |
5411 | + | |
5412 | + if( !(kv->emuaccel_page=alloc_page_mol()) ) | |
5413 | + return 0; | |
5414 | + | |
5415 | + kv->emuaccel_page_phys = tophys_mol( (char*)kv->emuaccel_page ); | |
5416 | + kv->emuaccel_mphys = mphys; | |
5417 | + p = (ulong*)kv->emuaccel_page; | |
5418 | + | |
5419 | + handler = lookup_emuaccel_handler( EMUACCEL_NOP ); | |
5420 | + for( i=0; i<0x1000/sizeof(int); i+=2 ) { | |
5421 | + p[i] = handler; | |
5422 | + p[i+1] = 0; | |
5423 | + } | |
5424 | + | |
5425 | + /* flush translations - an old translation is overridden */ | |
5426 | + clear_pte_hash_table( kv ); | |
5427 | + /* printk("emuaccel_mapin: %08x\n", mphys ); */ | |
5428 | + return mphys; | |
5429 | +} | |
5430 | --- /dev/null | |
5431 | +++ b/drivers/macintosh/mol/fault.c | |
5432 | @@ -0,0 +1,601 @@ | |
5433 | +/* | |
5434 | + * Creation Date: <2002/06/08 20:53:20 samuel> | |
5435 | + * Time-stamp: <2004/02/22 13:07:50 samuel> | |
5436 | + * | |
5437 | + * <fault.c> | |
5438 | + * | |
5439 | + * Page fault handler | |
5440 | + * | |
5441 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
5442 | + * | |
5443 | + * This program is free software; you can redistribute it and/or | |
5444 | + * modify it under the terms of the GNU General Public License | |
5445 | + * as published by the Free Software Foundation | |
5446 | + * | |
5447 | + */ | |
5448 | + | |
5449 | +#include "archinclude.h" | |
5450 | +#include "alloc.h" | |
5451 | + | |
5452 | +#include "kernel_vars.h" | |
5453 | +#include "mmu.h" | |
5454 | +#include "mmu_contexts.h" | |
5455 | +#include "asmfuncs.h" | |
5456 | +#include "emu.h" | |
5457 | +#include "misc.h" | |
5458 | +#include "constants.h" | |
5459 | +#include "rvec.h" | |
5460 | +#include "mtable.h" | |
5461 | +#include "performance.h" | |
5462 | +#include "processor.h" | |
5463 | +#include "hash.h" | |
5464 | + | |
5465 | +/* exception bits (srr1/dsisr and a couple of mol defined bits) */ | |
5466 | +#define EBIT_PAGE_FAULT BIT(1) /* I/D, PTE missing */ | |
5467 | +#define EBIT_NO_EXEC BIT(3) /* I, no-execute or guarded */ | |
5468 | +#define EBIT_PROT_VIOL BIT(4) /* I/D, protection violation */ | |
5469 | +#define EBIT_IS_WRITE BIT(6) /* D */ | |
5470 | +#define EBIT_IS_DSI 1 /* D, virtual bit */ | |
5471 | +#define EBIT_USE_MMU 2 /* I/D, virtual bit */ | |
5472 | + | |
5473 | +#define use_mmu(ebits) ((ebits) & EBIT_USE_MMU) | |
5474 | +#define is_write(ebits) ((ebits) & EBIT_IS_WRITE) | |
5475 | +#define is_dsi(ebits) ((ebits) & EBIT_IS_DSI) | |
5476 | +#define is_prot_viol(ebits) ((ebits) & EBIT_PROT_VIOL) | |
5477 | +#define is_page_fault(ebits) ((ebits) & EBIT_PAGE_FAULT) | |
5478 | + | |
5479 | +typedef struct { | |
5480 | + /* filled in by exception handler */ | |
5481 | + ulong ea; | |
5482 | + ulong *sr_base; | |
5483 | + struct vsid_ent **vsid_eptr; /* pointer to MMU.vsid or MMU.unmapped_vsid */ | |
5484 | + | |
5485 | + /* filled in by lookup_mphys */ | |
5486 | + mPTE_t *mpte; /* lvptr to mac-pte (if != NULL) */ | |
5487 | + ulong mphys_page; /* ea of mphys page */ | |
5488 | + int pte1; /* RPN | 000 | R | C | WIMG | 00 | PP */ | |
5489 | + int key; /* pp key bit */ | |
5490 | +} fault_param_t; | |
5491 | + | |
5492 | +static const char priv_viol_table[16] = { /* [is_write | key | PP] */ | |
5493 | + 0,0,0,0,1,0,0,0, /* read (1 == violation) */ | |
5494 | + 0,0,0,1,1,1,0,1 /* write */ | |
5495 | +}; | |
5496 | + | |
5497 | +#define NO_MMU_PTE1 (PTE1_R | PTE1_C /*| PTE1_M*/ | 0x2 /*pp*/ ) | |
5498 | + | |
5499 | +#define MREGS (kv->mregs) | |
5500 | +#define MMU (kv->mmu) | |
5501 | + | |
5502 | +#ifdef CONFIG_SMP | |
5503 | +#define SMP_PTE1_M PTE1_M | |
5504 | +#else | |
5505 | +#define SMP_PTE1_M 0 | |
5506 | +#endif | |
5507 | + | |
5508 | + | |
5509 | +/************************************************************************/ | |
5510 | +/* Debugging */ | |
5511 | +/************************************************************************/ | |
5512 | + | |
5513 | +static inline void | |
5514 | +DEBUG_print_inserted_pte( ulong *slot, ulong pte0, ulong pte1, ulong ea ) | |
5515 | +{ | |
5516 | +#if 0 | |
5517 | + mPTE_t pte; | |
5518 | + ulong *p = (ulong)&pte; | |
5519 | + p[0] = pte0; | |
5520 | + p[1] = pte1; | |
5521 | + | |
5522 | + printk("[%p] ", slot ); | |
5523 | + printk("RPN %08X API %08X EA %08lX ", pte.rpn << 12, pte.api<<12, ea ); | |
5524 | + printk("%c%c %c%c; PP %d\n", | |
5525 | + pte.h ? 'H' : 'h', | |
5526 | + pte.v ? 'V' : 'v', | |
5527 | + pte.r ? 'R' : 'r', | |
5528 | + pte.c ? 'C' : 'c', pte.pp ); | |
5529 | +#endif | |
5530 | +} | |
5531 | + | |
5532 | + | |
5533 | +/************************************************************************/ | |
5534 | +/* MMU virtualization and page fault handling */ | |
5535 | +/************************************************************************/ | |
5536 | + | |
5537 | +#ifdef EMULATE_603 | |
5538 | +static inline int | |
5539 | +lookup_603_pte( kernel_vars_t *kv, ulong vsid, ulong ea, int is_dsi, mPTE_t **ret_pte ) | |
5540 | +{ | |
5541 | + int ind = (ea >> 12) & 0x1f; /* 32x2 PTEs */ | |
5542 | + ulong mask, phash, cmp, pteg, cmp_ea, *eap; | |
5543 | + mPTE_t *p; | |
5544 | + | |
5545 | + // printk("lookup_603_pte %08lX\n", ea); | |
5546 | + | |
5547 | + if( is_dsi ) { | |
5548 | + p = &MMU.ptes_d_603[ind]; | |
5549 | + eap = &MMU.ptes_d_ea_603[ind]; | |
5550 | + } else { | |
5551 | + p = &MMU.ptes_i_603[ind]; | |
5552 | + eap = &MMU.ptes_i_ea_603[ind]; | |
5553 | + } | |
5554 | + cmp_ea = ea & 0x0ffff000; | |
5555 | + for( ; ind < 64 ; ind += 32, p += 32, eap += 32 ) { | |
5556 | + if( *eap == cmp_ea && p->vsid == vsid ) { | |
5557 | + *ret_pte = p; | |
5558 | + return 0; | |
5559 | + } | |
5560 | + } | |
5561 | + mask = MMU.hash_mask >> 6; | |
5562 | + | |
5563 | + /* calculate primary and secondary PTEG */ | |
5564 | + phash = (cmp_ea >> 12) ^ (vsid & 0x7ffff); | |
5565 | + pteg = ((phash & mask) << 6); | |
5566 | + MREGS.spr[S_HASH1] = MMU.hash_mbase + pteg; | |
5567 | + MREGS.spr[S_HASH2] = MMU.hash_mbase + (pteg ^ (mask << 6)); | |
5568 | + | |
5569 | + /* construct compare word */ | |
5570 | + cmp = BIT(0) | (vsid <<7) | (cmp_ea >> 22); | |
5571 | + if( is_dsi ) { | |
5572 | + MREGS.spr[S_DCMP] = cmp; | |
5573 | + MREGS.spr[S_DMISS] = ea; | |
5574 | + } else { | |
5575 | + MREGS.spr[S_ICMP] = cmp; | |
5576 | + MREGS.spr[S_IMISS] = ea; | |
5577 | + } | |
5578 | + return 1; | |
5579 | +} | |
5580 | +#endif | |
5581 | + | |
5582 | +static inline mPTE_t * | |
5583 | +lookup_mac_pte( kernel_vars_t *kv, ulong vsid, ulong ea ) | |
5584 | +{ | |
5585 | + ulong phash, cmp, pteg, *p; | |
5586 | + ulong mask; | |
5587 | + int i; | |
5588 | + | |
5589 | + /* make sure the hash is mapped... */ | |
5590 | + if( !MMU.hash_base ) | |
5591 | + return NULL; | |
5592 | + | |
5593 | + /* we are only interested in the page index */ | |
5594 | + ea &= 0x0ffff000; | |
5595 | + mask = MMU.hash_mask>>6; | |
5596 | + | |
5597 | + /* calculate primary hash function */ | |
5598 | + phash = (ea >> 12) ^ (vsid & 0x7ffff); | |
5599 | + pteg = ((phash & mask) << 6); | |
5600 | + | |
5601 | + /* construct compare word */ | |
5602 | + cmp = BIT(0) | (vsid <<7) | ((ea&0x0fffffff)>>22); | |
5603 | + | |
5604 | + /* look in primary PTEG */ | |
5605 | + p = (ulong*)((ulong)MMU.hash_base + pteg); | |
5606 | + for( i=0; i<8; i++, p+=2 ) | |
5607 | + if( cmp == *p ) | |
5608 | + return (mPTE_t*)p; | |
5609 | + | |
5610 | + /* look in secondary PTEG */ | |
5611 | + p = (ulong*)( (ulong)MMU.hash_base + (pteg ^ (mask << 6)) ); | |
5612 | + cmp |= BIT(25); | |
5613 | + | |
5614 | + for( i=0; i<8; i++,p+=2 ) | |
5615 | + if( cmp == *p ) | |
5616 | + return (mPTE_t*)p; | |
5617 | + return NULL; | |
5618 | +} | |
5619 | + | |
5620 | +static int | |
5621 | +lookup_mphys( kernel_vars_t *kv, fault_param_t *pb, const int ebits ) | |
5622 | +{ | |
5623 | + ulong ea = (pb->ea & ~0xfff); | |
5624 | + mSEGREG segr; | |
5625 | + mac_bat_t *bp; | |
5626 | + int sv_mode, i, sbits; | |
5627 | + mPTE_t *mpte; | |
5628 | + | |
5629 | + pb->mpte = NULL; | |
5630 | + | |
5631 | + if( !use_mmu(ebits) ) { | |
5632 | + pb->mphys_page = ea; | |
5633 | + pb->pte1 = NO_MMU_PTE1; | |
5634 | + pb->key = 0; | |
5635 | + return 0; | |
5636 | + } | |
5637 | + | |
5638 | + segr = *(mSEGREG*)&MREGS.segr[ea>>28]; | |
5639 | + sv_mode = !(MREGS.msr & MSR_PR); | |
5640 | + | |
5641 | + /* I/O segment? */ | |
5642 | + if( segr.t ) { | |
5643 | + /* Memory forced (601/604)? Note that the 601 uses I/O segments | |
5644 | + * even if translation is off(!). We don't implement this though. | |
5645 | + */ | |
5646 | + ulong sr = MREGS.segr[ea>>28]; | |
5647 | + BUMP( memory_forced_segment ); | |
5648 | + | |
5649 | + if( ((sr >> 20) & 0x1ff) != 0x7f ) | |
5650 | + return RVEC_MMU_IO_SEG_ACCESS; | |
5651 | + pb->mphys_page = (ea & 0x0ffff000) | ((sr & 0xf)<<28); | |
5652 | + pb->pte1 = NO_MMU_PTE1; | |
5653 | + pb->key = 0; | |
5654 | + return 0; | |
5655 | + } | |
5656 | + | |
5657 | + /* BAT translation? 0-3 = IBATs, 4-7 = DBATs. Separated I/D BATS, hace 3/8/99 */ | |
5658 | + bp = is_dsi(ebits) ? &MMU.bats[4] : &MMU.bats[0]; | |
5659 | + for( i=0; i<4; i++, bp++ ) { | |
5660 | + if( !bp->valid ) | |
5661 | + continue; | |
5662 | + if( (sv_mode && !bp->vs) || (!sv_mode && !bp->vp) ) | |
5663 | + continue; | |
5664 | + if( ea < bp->base || ea > bp->base+bp->size-1 ) | |
5665 | + continue; | |
5666 | + | |
5667 | + pb->mphys_page = ea - bp->base + bp->mbase; | |
5668 | + pb->pte1 = bp->pp | (bp->wimg << 3) | PTE1_R | PTE1_C; | |
5669 | + pb->key = sv_mode ? bp->ks : bp->ku; | |
5670 | + return 0; | |
5671 | + } | |
5672 | + | |
5673 | +#ifdef EMULATE_603 | |
5674 | + if( (MREGS.spr[S_PVR] >> 16) == 3 ) { | |
5675 | + if( lookup_603_pte(kv, segr.vsid, ea, is_dsi(ebits), &mpte) ) | |
5676 | + return is_dsi(ebits) ? (is_write(ebits) ? RVEC_DMISS_STORE_TRAP : | |
5677 | + RVEC_DMISS_LOAD_TRAP) : RVEC_IMISS_TRAP; | |
5678 | + | |
5679 | + pb->mpte = NULL; /* imporant */ | |
5680 | + pb->mphys_page = (mpte->rpn << 12); | |
5681 | + pb->pte1 = ((ulong*)mpte)[1] & (PTE1_PP | PTE1_WIMG | PTE1_R | PTE1_C); | |
5682 | + pb->key = sv_mode ? segr.ks : segr.kp; | |
5683 | + return 0; | |
5684 | + } | |
5685 | +#endif | |
5686 | + /* mac page table lookup */ | |
5687 | + if( (mpte=lookup_mac_pte(kv, segr.vsid, ea)) ) { | |
5688 | + pb->mpte = mpte; | |
5689 | + pb->mphys_page = (mpte->rpn << 12); | |
5690 | + pb->pte1 = ((ulong*)mpte)[1] & (PTE1_PP | PTE1_WIMG | PTE1_R | PTE1_C); | |
5691 | + pb->key = sv_mode ? segr.ks : segr.kp; | |
5692 | + return 0; | |
5693 | + } | |
5694 | + /* mac page fault */ | |
5695 | + sbits = EBIT_PAGE_FAULT | (ebits & EBIT_IS_WRITE); /* r/w bit + page_fault */ | |
5696 | + RVEC_RETURN_2( &MREGS, is_dsi(ebits) ? RVEC_DSI_TRAP : RVEC_ISI_TRAP, pb->ea, sbits ); | |
5697 | +} | |
5698 | + | |
5699 | + | |
5700 | +/* PTE0 must be fully initialized on entry (with V=1 and H=0). | |
5701 | + * The pte_present flag should be set from srr1/dsisr bit and indicates | |
5702 | + * that a valid PTE might already be present in the hash table. | |
5703 | + */ | |
5704 | +static inline ulong * | |
5705 | +find_pte_slot( ulong ea, ulong *pte0, int pte_present, int *pte_replaced ) | |
5706 | +{ | |
5707 | + static int grab_add=0; | |
5708 | + ulong phash, pteg, *p, cmp = *pte0; | |
5709 | + ulong *primary, *secondary; | |
5710 | + int i; | |
5711 | + | |
5712 | + /* we are only interested in the page index */ | |
5713 | + ea &= 0x0ffff000; | |
5714 | + | |
5715 | + /* primary hash function */ | |
5716 | + phash = (ea >> 12) ^ (PTE0_VSID(cmp) & 0x7ffff); | |
5717 | + | |
5718 | + pteg = (phash << 6) & ptehash.pteg_mask; | |
5719 | + primary = (ulong*)((ulong)ptehash.base + pteg); | |
5720 | + | |
5721 | + pteg = pteg ^ ptehash.pteg_mask; | |
5722 | + secondary = (ulong*)((ulong)ptehash.base + pteg); | |
5723 | + | |
5724 | + if( pte_present ) { | |
5725 | + *pte_replaced = 1; | |
5726 | + | |
5727 | + /* look in primary PTEG */ | |
5728 | + p = primary; | |
5729 | + for( i=0; i<8; i++, p+=2 ) | |
5730 | + if( cmp == *p ) | |
5731 | + return p; | |
5732 | + | |
5733 | + /* look in secondary PTEG */ | |
5734 | + p = secondary; | |
5735 | + cmp |= BIT(25); | |
5736 | + for( i=0; i<8; i++, p+=2 ) | |
5737 | + if( cmp == *p ) { | |
5738 | + *pte0 |= PTE0_H; | |
5739 | + return p; | |
5740 | + } | |
5741 | + /* we will actually come here if the previous PTE | |
5742 | + * was only available in the on-chip cache. | |
5743 | + */ | |
5744 | + } | |
5745 | + *pte_replaced = 0; | |
5746 | + | |
5747 | + /* free slot in primary PTEG? */ | |
5748 | + for( p=primary, i=0; i<8; i++, p+=2 ) | |
5749 | + if( !(*p & BIT(0)) ) | |
5750 | + return p; | |
5751 | + | |
5752 | + /* free slot in secondary PTEG? */ | |
5753 | + for( p=secondary, i=0; i<8; i++, p+=2 ) | |
5754 | + if( !(*p & BIT(0)) ) { | |
5755 | + *pte0 |= PTE0_H; | |
5756 | + return p; | |
5757 | + } | |
5758 | + | |
5759 | + /* steal a primary PTEG slot */ | |
5760 | + grab_add = (grab_add+1) & 0x7; | |
5761 | + | |
5762 | + /* printk("Grabbing slot %d, EA %08X\n",grab_add, ea ); */ | |
5763 | + return (ulong*)((ulong)primary + grab_add * sizeof(ulong[2])); | |
5764 | +} | |
5765 | + | |
5766 | +static inline int | |
5767 | +insert_pte( kernel_vars_t *kv, fault_param_t *pb, const int ebits ) | |
5768 | +{ | |
5769 | + ulong ea=pb->ea, mphys=pb->mphys_page; | |
5770 | + ulong sr=pb->sr_base[ea>>28]; | |
5771 | + int status, pte_replaced; | |
5772 | + pte_lvrange_t *lvrange; | |
5773 | + ulong pte0, pte1, *slot; | |
5774 | + ulong lvptr; | |
5775 | + | |
5776 | +#ifdef CONFIG_AMIGAONE | |
5777 | + pte1 = PTE1_R | (pb->pte1 & (PTE1_R | PTE1_C | PTE1_WIMG)) | |
5778 | + | (is_write(ebits) ? 2:3); | |
5779 | +#else | |
5780 | + pte1 = PTE1_M | PTE1_R | (pb->pte1 & (PTE1_R | PTE1_C | PTE1_WIMG)) | |
5781 | + | (is_write(ebits) ? 2:3); | |
5782 | +#endif | |
5783 | + | |
5784 | + /* PP and WIMG bits must set before the call to mphys_to_pte */ | |
5785 | + status = mphys_to_pte( kv, mphys, &pte1, is_write(ebits), &lvrange ); | |
5786 | + | |
5787 | + if( !status || (is_write(ebits) && (status & MAPPING_RO)) ) { | |
5788 | + ulong addr = (mphys | (ea & 0xfff)); | |
5789 | + if( is_dsi(ebits) ) { | |
5790 | + int rvec = is_write(ebits) ? RVEC_IO_WRITE : RVEC_IO_READ; | |
5791 | + BUMP( io_read_write ); | |
5792 | + RVEC_RETURN_2( &MREGS, rvec, addr, NULL ); | |
5793 | + } else { | |
5794 | + RVEC_RETURN_1( &MREGS, RVEC_BAD_NIP, addr ); | |
5795 | + } | |
5796 | + } | |
5797 | + | |
5798 | + /* tlbhash table hit? */ | |
5799 | + if( (ulong)(pb->mphys_page - MMU.hash_mbase) < (ulong)MMU.hash_mask ) { | |
5800 | + /* printk("hash_table_hit at %08lX\n", pb->ea ); */ | |
5801 | + MMU.pthash_sr = sr; | |
5802 | + MMU.pthash_ea_base = ea & ~MMU.hash_mask; | |
5803 | + | |
5804 | + /* user read (always), superuser r/w */ | |
5805 | + pte1 &= ~PTE1_PP; | |
5806 | + pte1 |= is_write(ebits) ? 1:3; | |
5807 | + /* write accesses of the page table are handled in ptintercept.S */ | |
5808 | + } | |
5809 | + | |
5810 | + pte0 = PTE0_V | (sr << 7) | ((ea>>22) & PTE0_API); | |
5811 | + slot = find_pte_slot( ea, &pte0, !is_page_fault(ebits), &pte_replaced ); | |
5812 | + | |
5813 | + lvptr = (status & MAPPING_PHYSICAL) ? 0 : (pte1 & PTE1_RPN); | |
5814 | + | |
5815 | + /* the RC bits should correspond to the is_write flag; this prevents the | |
5816 | + * CPU from stamping RC bits unnecessary (besides, the kernel seems to | |
5817 | + * assume no RC-stamps will ever occur so RC-stamping is unsafe). | |
5818 | + */ | |
5819 | + if( is_write(ebits) ) | |
5820 | + pte1 |= PTE1_C; | |
5821 | + pte1 |= SMP_PTE1_M; | |
5822 | + | |
5823 | + /* if a page-out occurs between prepare_pte_insert() and the pte_inserted() | |
5824 | + * call, then the PTE slot is zeroed out. | |
5825 | + */ | |
5826 | + if( !(status & MAPPING_PHYSICAL) ) { | |
5827 | +#if 0 | |
5828 | + if( is_write(ebits) ) | |
5829 | + lvpage_dirty( kv, lvptr ); | |
5830 | +#endif | |
5831 | + pte1 &= ~PTE1_RPN; | |
5832 | + | |
5833 | + /* zero pages should work just fine now... */ | |
5834 | + pte1 |= get_phys_page( kv, lvptr, is_write(ebits) ); | |
5835 | + /* pte1 |= get_phys_page( kv, lvptr, !(status & MAPPING_RO) ); */ | |
5836 | + } | |
5837 | + | |
5838 | + if( status & MAPPING_FB_ACCEL ) | |
5839 | + video_pte_inserted( kv, lvptr, slot, pte0, pte1, ea ); | |
5840 | + | |
5841 | + BUMP( page_fault_ctr ); | |
5842 | + DEBUG_print_inserted_pte( slot, pte0, pte1, ea ); | |
5843 | + | |
5844 | + __store_PTE( ea, slot, pte0, pte1 ); | |
5845 | + | |
5846 | + pte_inserted( kv, ea, (char*)lvptr, lvrange, slot, pb->vsid_eptr[ea>>28], sr ); | |
5847 | + | |
5848 | + /* debugger support */ | |
5849 | + if( (kv->break_flags & BREAK_EA_PAGE) && (ea & ~0xfff) == MREGS.mdbg_ea_break ) | |
5850 | + RVEC_RETURN_1( &MREGS, RVEC_BREAK, BREAK_EA_PAGE ); | |
5851 | + | |
5852 | + return RVEC_NOP; | |
5853 | +} | |
5854 | + | |
5855 | +static int | |
5856 | +page_fault( kernel_vars_t *kv, fault_param_t *pb, const int ebits ) | |
5857 | +{ | |
5858 | + int topind = pb->ea >> 28; | |
5859 | + int ind, ret; | |
5860 | + | |
5861 | + BUMP( access_exception_ctr ); | |
5862 | + | |
5863 | + if( (ret=lookup_mphys(kv, pb, ebits)) ) { | |
5864 | + BUMP(mac_page_fault); | |
5865 | + return ret; | |
5866 | + } | |
5867 | + | |
5868 | + /* printk("MPHYS_PAGE: %08lX, pp %d, key %d, wimg %d, mpte %p\n", | |
5869 | + pb->mphys_page, (pb->pte1 & 3), pb->key, ((pb->pte1 >> 3) & 0xf), pb->mpte ); */ | |
5870 | + | |
5871 | + /* check privileges */ | |
5872 | + ind = (is_write(ebits) ? 8:0) | (pb->pte1 & PTE1_PP) | (pb->key?4:0); | |
5873 | + if( priv_viol_table[ind] ) { | |
5874 | + /* r/w bit + priv. violation */ | |
5875 | + int sbits = EBIT_PROT_VIOL | (ebits & EBIT_IS_WRITE); | |
5876 | + BUMP(mac_priv_violation); | |
5877 | + RVEC_RETURN_2( &MREGS, is_dsi(ebits) ? RVEC_DSI_TRAP : RVEC_ISI_TRAP, pb->ea, sbits ); | |
5878 | + } | |
5879 | + | |
5880 | + /* stamp R/C bits (mpte is NULL if this is not a page translation). */ | |
5881 | + if( pb->mpte ) { | |
5882 | + pb->mpte->r = 1; | |
5883 | + if( is_write(ebits) ) | |
5884 | + pb->mpte->c = 1; | |
5885 | + | |
5886 | + /* stamp pthash_inuse_bit */ | |
5887 | + if( MMU.pthash_inuse_bits ) { | |
5888 | + int nr = ((int)pb->mpte - (int)MMU.hash_base) >> 3; | |
5889 | + set_bit_mol( nr, MMU.pthash_inuse_bits ); | |
5890 | + } | |
5891 | + } | |
5892 | + | |
5893 | + /* perform memory allocations if necessary; we are not allowed to | |
5894 | + * do this later (the mtable insertion must be atomic) | |
5895 | + */ | |
5896 | + if( mtable_memory_check(kv) ) | |
5897 | + return RVEC_NOP; /* out of memory */ | |
5898 | + | |
5899 | + /* the vsid entry might have been released */ | |
5900 | + if( !pb->vsid_eptr[topind] ) | |
5901 | + return RVEC_NOP; | |
5902 | + | |
5903 | + return insert_pte( kv, pb, ebits ); | |
5904 | +} | |
5905 | + | |
5906 | + | |
5907 | +/************************************************************************/ | |
5908 | +/* VSID allocation (the normal VSID lookup occurs in vsid.S) */ | |
5909 | +/************************************************************************/ | |
5910 | + | |
5911 | +static void | |
5912 | +fix_sr( kernel_vars_t *kv, int sr, int mapped ) | |
5913 | +{ | |
5914 | + int macvsid = mapped ? (MREGS.segr[sr] & VSID_MASK) : VSID_MASK + 1 + sr; | |
5915 | + ulong user_sr, sv_sr; | |
5916 | + vsid_ent_t *r = vsid_get_user_sv( kv, macvsid, &user_sr, &sv_sr ); | |
5917 | + | |
5918 | + BUMP(fix_sr); | |
5919 | + if( !r ) | |
5920 | + return; | |
5921 | + | |
5922 | + if( mapped ) { | |
5923 | + int value = MREGS.segr[sr]; | |
5924 | + int nbit = value & VSID_N; | |
5925 | + MMU.vsid[sr] = r; | |
5926 | + MMU.user_sr[sr] = ((value & VSID_Kp) ? user_sr : sv_sr) | nbit; | |
5927 | + MMU.sv_sr[sr] = ((value & VSID_Ks) ? user_sr : sv_sr) | nbit; | |
5928 | + } else { | |
5929 | + MMU.unmapped_vsid[sr] = r; | |
5930 | + MMU.unmapped_sr[sr] = user_sr; | |
5931 | + } | |
5932 | + invalidate_splitmode_sr( kv ); | |
5933 | +} | |
5934 | + | |
5935 | + | |
5936 | +/************************************************************************/ | |
5937 | +/* Exception entrypoints (called from assembly) */ | |
5938 | +/************************************************************************/ | |
5939 | + | |
5940 | +extern int dsi_exception( kernel_vars_t *kv, ulong dar, ulong dsisr ); | |
5941 | +extern int isi_exception( kernel_vars_t *kv, ulong nip, ulong srr1 ); | |
5942 | + | |
5943 | +int | |
5944 | +dsi_exception( kernel_vars_t *kv, ulong dar, ulong dsisr ) | |
5945 | +{ | |
5946 | + int ebits, topind = dar >> 28; | |
5947 | + fault_param_t pb; | |
5948 | + | |
5949 | + /* printk("DSI: EA %08lX, DSISR %08lX\n", dar, dsisr ); */ | |
5950 | + if( dsisr & 0x84500000 ) /* 0,5,9,11 */ | |
5951 | + RVEC_RETURN_2( &MREGS, RVEC_UNUSUAL_DSISR_BITS, dar, dsisr ); | |
5952 | + | |
5953 | + pb.ea = dar; | |
5954 | + ebits = EBIT_IS_DSI | (dsisr & (EBIT_PAGE_FAULT | EBIT_PROT_VIOL | EBIT_IS_WRITE)) | |
5955 | + | ((MREGS.msr & MSR_DR) ? EBIT_USE_MMU : 0); | |
5956 | + | |
5957 | + pb.vsid_eptr = (MREGS.msr & MSR_DR) ? MMU.vsid : MMU.unmapped_vsid; | |
5958 | + pb.sr_base = (ulong*)((ulong)MMU.sr_data - kv->kvars_tophys_offs); | |
5959 | + | |
5960 | + /* segment register switch-in required? */ | |
5961 | + if( !pb.vsid_eptr[topind] ) { | |
5962 | + fix_sr( kv, topind, use_mmu(ebits) ); | |
5963 | + return RVEC_NOP; | |
5964 | + } | |
5965 | + BUMP(dsi); | |
5966 | + return page_fault( kv, &pb, ebits ); | |
5967 | +} | |
5968 | + | |
5969 | +int | |
5970 | +isi_exception( kernel_vars_t *kv, ulong nip, ulong srr1 ) | |
5971 | +{ | |
5972 | + fault_param_t pb; | |
5973 | + /* printk("ISI: NIP %08lX, SRR1 %08lX\n", nip, srr1 ); */ | |
5974 | + | |
5975 | + pb.vsid_eptr = (MREGS.msr & MSR_IR) ? MMU.vsid : MMU.unmapped_vsid; | |
5976 | + | |
5977 | + if( srr1 & EBIT_PAGE_FAULT ) { | |
5978 | + int ebits = EBIT_PAGE_FAULT | ((MREGS.msr & MSR_IR) ? EBIT_USE_MMU : 0); | |
5979 | + pb.ea = nip; | |
5980 | + pb.sr_base = (ulong*)((ulong)MMU.sr_inst - kv->kvars_tophys_offs); | |
5981 | + BUMP(isi_page_fault); | |
5982 | + return page_fault( kv, &pb, ebits ); | |
5983 | + } | |
5984 | + if( srr1 & EBIT_NO_EXEC ) { | |
5985 | + int sr = nip >> 28; | |
5986 | + if( !pb.vsid_eptr[sr] ) { | |
5987 | + fix_sr( kv, sr, (MREGS.msr & MSR_IR) ); | |
5988 | + return RVEC_NOP; | |
5989 | + } | |
5990 | + /* printk("Guarded memory access at %08lX\n", nip ); */ | |
5991 | + RVEC_RETURN_2( &MREGS, RVEC_ISI_TRAP, nip, EBIT_NO_EXEC ); | |
5992 | + } | |
5993 | + | |
5994 | + BUMP(isi_prot_violation); | |
5995 | + /* must be privileges violation */ | |
5996 | + RVEC_RETURN_2( &MREGS, RVEC_ISI_TRAP, nip, EBIT_PROT_VIOL ); | |
5997 | +} | |
5998 | + | |
5999 | + | |
6000 | +/************************************************************************/ | |
6001 | +/* debugger functions */ | |
6002 | +/************************************************************************/ | |
6003 | + | |
6004 | +int | |
6005 | +dbg_translate_ea( kernel_vars_t *kv, int context, ulong va, int *ret_mphys, int data_access ) | |
6006 | +{ | |
6007 | + int ebits = data_access ? EBIT_IS_DSI : 0; | |
6008 | + fault_param_t pb; | |
6009 | + | |
6010 | + memset( &pb, 0, sizeof(pb) ); | |
6011 | + pb.ea = va; | |
6012 | + | |
6013 | + switch( context ) { | |
6014 | + case kContextUnmapped: | |
6015 | + pb.sr_base = MMU.unmapped_sr; | |
6016 | + break; | |
6017 | + case kContextMapped_S: | |
6018 | + pb.sr_base = MMU.sv_sr; | |
6019 | + ebits |= EBIT_USE_MMU; | |
6020 | + break; | |
6021 | + case kContextMapped_U: | |
6022 | + pb.sr_base = MMU.user_sr; | |
6023 | + ebits |= EBIT_USE_MMU; | |
6024 | + break; | |
6025 | + default: | |
6026 | + return 1; | |
6027 | + } | |
6028 | + | |
6029 | + if( lookup_mphys(kv, &pb, ebits) ) | |
6030 | + return 1; | |
6031 | + *ret_mphys = pb.mphys_page | (va & 0xfff); | |
6032 | + return 0; | |
6033 | +} | |
6034 | --- /dev/null | |
6035 | +++ b/drivers/macintosh/mol/hash.c | |
6036 | @@ -0,0 +1,126 @@ | |
6037 | +/* | |
6038 | + * Creation Date: <2004/02/14 11:42:19 samuel> | |
6039 | + * Time-stamp: <2004/03/13 14:25:00 samuel> | |
6040 | + * | |
6041 | + * <hash.c> | |
6042 | + * | |
6043 | + * CPU PTE hash handling | |
6044 | + * | |
6045 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
6046 | + * | |
6047 | + * This program is free software; you can redistribute it and/or | |
6048 | + * modify it under the terms of the GNU General Public License | |
6049 | + * as published by the Free Software Foundation | |
6050 | + * | |
6051 | + */ | |
6052 | + | |
6053 | +#include "archinclude.h" | |
6054 | +#include "alloc.h" | |
6055 | +#include "kernel_vars.h" | |
6056 | +#include "mmu.h" | |
6057 | +#include "mmu_contexts.h" | |
6058 | +#include "asmfuncs.h" | |
6059 | +#include "emu.h" | |
6060 | +#include "misc.h" | |
6061 | +#include "mtable.h" | |
6062 | +#include "performance.h" | |
6063 | +#include "context.h" | |
6064 | +#include "hash.h" | |
6065 | +#include "map.h" | |
6066 | + | |
6067 | +/* GLOBALS */ | |
6068 | +hash_info_t ptehash; | |
6069 | + | |
6070 | +static struct { | |
6071 | + int hash_mapped; | |
6072 | + int sdr1_loaded; | |
6073 | + char *allocation; | |
6074 | +} hs; | |
6075 | + | |
6076 | + | |
6077 | +static int | |
6078 | +create_pte_hash( void ) | |
6079 | +{ | |
6080 | + ulong size = 1024*128; /* 128K is the kmalloc limit */ | |
6081 | + ulong sdr1, mask, base, physbase; | |
6082 | + char *p; | |
6083 | + | |
6084 | + if( !(p=kmalloc_cont_mol(size)) ) | |
6085 | + return 1; | |
6086 | + memset( p, 0, size ); | |
6087 | + base = (ulong)p; | |
6088 | + physbase = tophys_mol( (char*)base ); | |
6089 | + | |
6090 | + if( (physbase & (size-1)) ) { | |
6091 | + int offs; | |
6092 | + printk("Badly aligned SDR1 allocation - 64K wasted\n"); | |
6093 | + size /= 2; | |
6094 | + offs = ((physbase + size) & ~(size-1)) - physbase; | |
6095 | + physbase += offs; | |
6096 | + base += offs; | |
6097 | + } | |
6098 | + mask = (size-1) >> 6; | |
6099 | + sdr1 = mask >> 10; | |
6100 | + sdr1 |= physbase; | |
6101 | + | |
6102 | + hs.allocation = p; | |
6103 | + ptehash.sdr1 = sdr1; | |
6104 | + ptehash.base = (ulong*)base; | |
6105 | + | |
6106 | + printk("SDR1 = %08lX\n", sdr1 ); | |
6107 | + return 0; | |
6108 | +} | |
6109 | + | |
6110 | +int | |
6111 | +init_hash( void ) | |
6112 | +{ | |
6113 | + ulong sdr1; | |
6114 | + | |
6115 | + memset( &ptehash, 0, sizeof(ptehash) ); | |
6116 | + | |
6117 | + if( IS_LINUX ) { | |
6118 | + sdr1 = _get_sdr1(); | |
6119 | + | |
6120 | + /* linux does not use SDR1 on the 603[e] */ | |
6121 | + if( !sdr1 ) { | |
6122 | + create_pte_hash(); | |
6123 | + sdr1 = ptehash.sdr1; | |
6124 | + _set_sdr1( sdr1 ); | |
6125 | + hs.sdr1_loaded = 1; | |
6126 | + } | |
6127 | + } else { | |
6128 | + /* sharing the hash under darwin is too complicated */ | |
6129 | + create_pte_hash(); | |
6130 | + sdr1 = ptehash.sdr1; | |
6131 | + } | |
6132 | + | |
6133 | + if( !sdr1 ) | |
6134 | + return 1; | |
6135 | + | |
6136 | + ptehash.sdr1 = sdr1; | |
6137 | + ptehash.pteg_mask = (((sdr1 & 0x1ff) << 10) | 0x3ff) << 6; | |
6138 | + ptehash.pte_mask = ptehash.pteg_mask | 0x38; | |
6139 | + ptehash.physbase = sdr1 & ~0xffff; | |
6140 | + | |
6141 | + if( !ptehash.base ) { | |
6142 | + hs.hash_mapped = 1; | |
6143 | + ptehash.base = map_hw_hash( ptehash.physbase, ptehash.pte_mask + 8 ); | |
6144 | + } | |
6145 | + | |
6146 | + return !ptehash.base; | |
6147 | +} | |
6148 | + | |
6149 | +void | |
6150 | +cleanup_hash( void ) | |
6151 | +{ | |
6152 | + if( hs.hash_mapped ) | |
6153 | + unmap_hw_hash( ptehash.base ); | |
6154 | + | |
6155 | + if( hs.sdr1_loaded ) | |
6156 | + _set_sdr1( 0 ); | |
6157 | + if( hs.allocation ) | |
6158 | + kfree_cont_mol( hs.allocation ); | |
6159 | + | |
6160 | + memset( &ptehash, 0, sizeof(ptehash) ); | |
6161 | + memset( &hs, 0, sizeof(hs) ); | |
6162 | +} | |
6163 | --- /dev/null | |
6164 | +++ b/drivers/macintosh/mol/include/actions.h | |
6165 | @@ -0,0 +1,177 @@ | |
6166 | +/* | |
6167 | + * Creation Date: <2004/01/31 13:08:42 samuel> | |
6168 | + * Time-stamp: <2004/03/07 14:25:23 samuel> | |
6169 | + * | |
6170 | + * <actions.h> | |
6171 | + * | |
6172 | + * | |
6173 | + * | |
6174 | + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
6175 | + * | |
6176 | + * This program is free software; you can redistribute it and/or | |
6177 | + * modify it under the terms of the GNU General Public License | |
6178 | + * version 2 | |
6179 | + * | |
6180 | + */ | |
6181 | + | |
6182 | +#ifndef _H_ACTIONS | |
6183 | +#define _H_ACTIONS | |
6184 | + | |
6185 | +/* Certain assembly macros (like LI_PHYS) adds meta information to a special | |
6186 | + * ELF segment. This information is parsed when the module is loaded/used and | |
6187 | + * the appropriate action is performed (a few assembly instruction are typically | |
6188 | + * modified). | |
6189 | + * | |
6190 | + * Actions with lower opcodes are performed before actions with higher opcodes. | |
6191 | + */ | |
6192 | + | |
6193 | +#define ACTION_LIS_SPECVAR_H 1 /* dreg, special_var_index */ | |
6194 | +#define ACTION_ORI_SPECVAR_L 2 /* dreg*32 + sreg, special_var_index */ | |
6195 | +#define ACTION_LI_PHYS 3 /* dreg, addr_offs */ | |
6196 | +#define ACTION_LWZ_PHYSADDR_R 4 /* dreg*32 + reg, addr_offs */ | |
6197 | +#define ACTION_TOPHYS 5 /* dreg*32 + sreg */ | |
6198 | +#define ACTION_TOVIRT 6 /* dreg*32 + sreg */ | |
6199 | +#define ACTION_RELOCATE_LOW 7 /* code_size, destvar, code... */ | |
6200 | +#define ACTION_VRET 8 /* vector [special, used by RELOC_HOOK] */ | |
6201 | +#define ACTION_FIX_SPRG2 9 /* scratch_reg */ | |
6202 | + | |
6203 | +#define FLUSH_CACHE_ACTION 9 /* flush the icache at this point */ | |
6204 | + | |
6205 | +#define ACTION_HOOK_FUNCTION 10 | |
6206 | +#define ACTION_RELOC_HOOK 11 /* trigger, size, vret_action#, vret_offs */ | |
6207 | +#define MAX_NUM_ACTIONS 12 | |
6208 | + | |
6209 | +/* Special vars (ACTION_*_SPECVAR) */ | |
6210 | +#define SPECVAR_SESSION_TABLE 1 | |
6211 | + | |
6212 | +/* Function hooks (ACTION_HOOK_FUNCTION) */ | |
6213 | +#define FHOOK_FLUSH_HASH_PAGE 1 | |
6214 | + | |
6215 | +#ifndef __ASSEMBLY__ | |
6216 | +typedef struct { | |
6217 | + int action; /* ACTION_xxx */ | |
6218 | + int offs; /* target instruction offset (from r__reloctable_start) */ | |
6219 | + int params[1]; /* parameters */ | |
6220 | +} action_pb_t; | |
6221 | +#endif /* __ASSEMBLY__ */ | |
6222 | + | |
6223 | + | |
6224 | +/************************************************************************/ | |
6225 | +/* assembly macros */ | |
6226 | +/************************************************************************/ | |
6227 | + | |
6228 | +/* | |
6229 | + * WARNING: These macros uses the 9 label (the OSX assembler | |
6230 | + * can only use labels (0-9). | |
6231 | + */ | |
6232 | + | |
6233 | +#ifdef __ASSEMBLY__ | |
6234 | + | |
6235 | +#ifdef __linux__ | |
6236 | +#define ACTIONS_SECTION .text 95 | |
6237 | +#define ACTIONS_OFFS_SECTION .text 96 | |
6238 | +#endif | |
6239 | +#ifdef __darwin__ | |
6240 | +#define ACTIONS_SECTION .section __TEXT,__areloc | |
6241 | +#define ACTIONS_OFFS_SECTION .section __DATA,__areloc_offs | |
6242 | +#endif | |
6243 | + | |
6244 | +mDEFINE(ACTION_PB, [action], [ | |
6245 | + .text | |
6246 | +9: | |
6247 | + ACTIONS_SECTION | |
6248 | + .long _action /* action */ | |
6249 | + .long (9b - r__reloctable_start) /* target PC */ | |
6250 | +9: | |
6251 | + ACTIONS_OFFS_SECTION | |
6252 | + .long (9b - r__actions_section - 8) /* store pointer to PB */ | |
6253 | + ACTIONS_SECTION | |
6254 | +]) | |
6255 | + | |
6256 | +mDEFINE(ACTION_1, [action, p1], [ | |
6257 | + ACTION_PB( _action ) | |
6258 | + .long _p1 | |
6259 | + .text | |
6260 | + nop /* replaced */ | |
6261 | +]) | |
6262 | + | |
6263 | +mDEFINE(ACTION_21, [action, p1, p2], [ | |
6264 | + ACTION_PB( _action ) | |
6265 | + .long _p1, _p2 | |
6266 | + .text | |
6267 | + nop /* replaced */ | |
6268 | +]) | |
6269 | + | |
6270 | +mDEFINE(ACTION_2, [action, p1, p2], [ | |
6271 | + ACTION_PB( _action ) | |
6272 | + .long _p1, _p2 | |
6273 | + .text | |
6274 | + nop /* replaced */ | |
6275 | + nop /* replaced */ | |
6276 | +]) | |
6277 | + | |
6278 | +mDEFINE(ACTION_13, [action, p1], [ | |
6279 | + ACTION_PB( _action ) | |
6280 | + .long _p1 | |
6281 | + .text | |
6282 | + nop /* replaced */ | |
6283 | + nop /* replaced */ | |
6284 | + nop /* replaced */ | |
6285 | +]) | |
6286 | + | |
6287 | + | |
6288 | + /* replaced with lis dreg,addr@ha ; addi dreg,dreg,addr@l */ | |
6289 | +#define LI_PHYS( dreg, addr ) \ | |
6290 | + ACTION_2( ACTION_LI_PHYS, dreg, (addr - r__reloctable_start) ) | |
6291 | + | |
6292 | + /* replaced with addis dreg,reg,addr@ha ; lwz dreg,addr@lo(dreg). */ | |
6293 | +#define LWZ_PHYSADDR_R( dreg, addr, reg ) \ | |
6294 | + ACTION_2( ACTION_LWZ_PHYSADDR_R, (dreg*32 + reg), (addr - r__reloctable_start) ) | |
6295 | + | |
6296 | +#define LWZ_PHYS( dreg, addr ) \ | |
6297 | + LWZ_PHYSADDR_R( dreg, addr, 0 ); | |
6298 | + | |
6299 | + /* syntax: tophys rD,rS */ | |
6300 | +MACRO(tophys, [dreg, sreg], [ | |
6301 | + ACTION_1( ACTION_TOPHYS, (_dreg * 32 + _sreg) ) | |
6302 | +]) | |
6303 | + /* syntax: tovirt rD,rS */ | |
6304 | +MACRO(tovirt, [dreg, sreg], [ | |
6305 | + ACTION_1( ACTION_TOVIRT, (_dreg * 32 + _sreg) ) | |
6306 | +]) | |
6307 | + | |
6308 | + /* syntax: lis_specvar_ha rD,SPECIAL_VAR */ | |
6309 | +MACRO(lis_svh, [dreg, specvariable], [ | |
6310 | + ACTION_21( ACTION_LIS_SPECVAR_H, _dreg, _specvariable ) | |
6311 | +]) | |
6312 | + | |
6313 | + /* syntax: addi_specvar_ha rD,rS,SPECIAL_VAR */ | |
6314 | +MACRO(ori_svl, [dreg, sreg, specvariable], [ | |
6315 | + ACTION_21( ACTION_ORI_SPECVAR_L, (_dreg * 32)+_sreg, _specvariable ) | |
6316 | +]) | |
6317 | + | |
6318 | + /* syntax: FIX_SPRG2 rN */ | |
6319 | +MACRO(fix_sprg2, [reg], [ | |
6320 | + /* only darwin needs this (sprg_a0 holds bits describing the CPU) */ | |
6321 | +#ifdef __darwin__ | |
6322 | + ACTION_13( ACTION_FIX_SPRG2, _reg ) | |
6323 | +#endif | |
6324 | +]) | |
6325 | + | |
6326 | +mDEFINE(RELOC_LOW, [destvar], [ | |
6327 | + ACTION_PB( ACTION_RELOCATE_LOW ) | |
6328 | + .long _destvar[]_end - _destvar[]_start | |
6329 | + .long EXTERN([]_destvar) | |
6330 | +_destvar[]_start: | |
6331 | +]) | |
6332 | + | |
6333 | +mDEFINE(RELOC_LOW_END, [destvar], [ | |
6334 | +_destvar[]_end: | |
6335 | + .text | |
6336 | +]) | |
6337 | + | |
6338 | + | |
6339 | +#endif /* __ASSEMBLY__ */ | |
6340 | + | |
6341 | + | |
6342 | +#endif /* _H_ACTIONS */ | |
6343 | --- /dev/null | |
6344 | +++ b/drivers/macintosh/mol/include/alloc.h | |
6345 | @@ -0,0 +1,70 @@ | |
6346 | +/* | |
6347 | + * Creation Date: <2002/01/13 16:35:18 samuel> | |
6348 | + * Time-stamp: <2004/01/25 17:36:49 samuel> | |
6349 | + * | |
6350 | + * <alloc.h> | |
6351 | + * | |
6352 | + * Memory allocation and mappings | |
6353 | + * | |
6354 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
6355 | + * | |
6356 | + * This program is free software; you can redistribute it and/or | |
6357 | + * modify it under the terms of the GNU General Public License | |
6358 | + * version 2 | |
6359 | + * | |
6360 | + */ | |
6361 | + | |
6362 | +#ifndef _H_ALLOC | |
6363 | +#define _H_ALLOC | |
6364 | + | |
6365 | +#include <linux/slab.h> | |
6366 | +#include <linux/vmalloc.h> | |
6367 | +#include <linux/mm.h> | |
6368 | +#include <asm/uaccess.h> | |
6369 | + | |
6370 | +#ifdef LINUX_26 | |
6371 | +#include <asm/cacheflush.h> | |
6372 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
6373 | +#include <asm/io.h> | |
6374 | +#endif | |
6375 | +#endif | |
6376 | + | |
6377 | +static inline void *kmalloc_mol( int size ) { | |
6378 | + return kmalloc( size, GFP_KERNEL ); | |
6379 | +} | |
6380 | +static inline void kfree_mol( void *p ) { | |
6381 | + kfree( p ); | |
6382 | +} | |
6383 | +static inline void *vmalloc_mol( int size ) { | |
6384 | + return vmalloc( size ); | |
6385 | +} | |
6386 | +static inline void vfree_mol( void *p ) { | |
6387 | + vfree( p ); | |
6388 | +} | |
6389 | +static inline ulong alloc_page_mol( void ) { | |
6390 | + return get_zeroed_page( GFP_KERNEL ); | |
6391 | +} | |
6392 | +static inline void free_page_mol( ulong addr ) { | |
6393 | + free_page( addr ); | |
6394 | +} | |
6395 | +static inline void *kmalloc_cont_mol( int size ) { | |
6396 | + return kmalloc( size, GFP_KERNEL ); | |
6397 | +} | |
6398 | +static inline void kfree_cont_mol( void *addr ) { | |
6399 | + kfree( addr ); | |
6400 | +} | |
6401 | +static inline ulong tophys_mol( void *addr ) { | |
6402 | + return virt_to_phys(addr); | |
6403 | +} | |
6404 | +static inline void flush_icache_mol( ulong start, ulong stop ) { | |
6405 | + flush_icache_range( start, stop ); | |
6406 | +} | |
6407 | +static inline void *map_phys_range( ulong paddr, ulong size, char **ret_addr ) { | |
6408 | + /* Warning: This works only for certain addresses... */ | |
6409 | + *ret_addr = phys_to_virt(paddr); | |
6410 | + return (void*)(-2); /* dummy */ | |
6411 | +} | |
6412 | +static inline void unmap_phys_range( void *handle ) {} | |
6413 | + | |
6414 | + | |
6415 | +#endif /* _H_ALLOC */ | |
6416 | --- /dev/null | |
6417 | +++ b/drivers/macintosh/mol/include/archinclude.h | |
6418 | @@ -0,0 +1,77 @@ | |
6419 | +/* | |
6420 | + * Creation Date: <2002/01/12 22:11:51 samuel> | |
6421 | + * Time-stamp: <2004/04/10 22:27:41 samuel> | |
6422 | + * | |
6423 | + * <archinclude.h> | |
6424 | + * | |
6425 | + * | |
6426 | + * | |
6427 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
6428 | + * | |
6429 | + * This program is free software; you can redistribute it and/or | |
6430 | + * modify it under the terms of the GNU General Public License | |
6431 | + * as published by the Free Software Foundation | |
6432 | + * | |
6433 | + */ | |
6434 | + | |
6435 | +#ifndef _H_ARCHINCLUDE | |
6436 | +#define _H_ARCHINCLUDE | |
6437 | + | |
6438 | +//#define PERF_MONITOR | |
6439 | +//#define PERFORMANCE_INFO /* collect performance statistics */ | |
6440 | +//#define PERFORMANCE_INFO_LIGHT /* sample only the most important counters */ | |
6441 | + | |
6442 | +#include "mol_config.h" | |
6443 | +#include "kconfig.h" | |
6444 | + | |
6445 | +#include <linux/version.h> | |
6446 | + | |
6447 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) | |
6448 | +#include <linux/utsrelease.h> | |
6449 | +#endif | |
6450 | + | |
6451 | +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) | |
6452 | +#include <linux/config.h> | |
6453 | +#else | |
6454 | +#include <linux/autoconf.h> | |
6455 | +#endif | |
6456 | + | |
6457 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | |
6458 | +#define LINUX_26 | |
6459 | +#endif | |
6460 | + | |
6461 | +#ifndef __ASSEMBLY__ | |
6462 | +#include <linux/kernel.h> | |
6463 | +#include <asm/atomic.h> | |
6464 | +#include <linux/sched.h> /* needed by <asm/mmu_context.h> */ | |
6465 | +#include <asm/mmu_context.h> | |
6466 | +#include <asm/time.h> | |
6467 | + | |
6468 | +#include "dbg.h" | |
6469 | + | |
6470 | +/* these are declared, but we just want to be sure the definition does not change */ | |
6471 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | |
6472 | +extern int flush_hash_pages( unsigned context, unsigned long va, unsigned long pmdval, int count ); /* 2.6 */ | |
6473 | +#else | |
6474 | +extern int flush_hash_page( unsigned context, unsigned long va, pte_t *ptep ); /* 2.5 */ | |
6475 | +#endif /* Linux 2.6 */ | |
6476 | + | |
6477 | +#endif /* __ASSEMBLY__ */ | |
6478 | + | |
6479 | +#ifdef LINUX_26 | |
6480 | +#define compat_flush_hash_pages flush_hash_pages | |
6481 | +#define compat_hash_table_lock mmu_hash_lock | |
6482 | +#else | |
6483 | +#define compat_flush_hash_pages flush_hash_page | |
6484 | +#define compat_hash_table_lock hash_table_lock | |
6485 | +#endif | |
6486 | + | |
6487 | + | |
6488 | +#define ENOSYS_MOL ENOSYS | |
6489 | +#define EFAULT_MOL EFAULT | |
6490 | + | |
6491 | +#define IS_LINUX 1 | |
6492 | +#define IS_DARWIN 0 | |
6493 | + | |
6494 | + | |
6495 | +#endif /* _H_ARCHINCLUDE */ | |
6496 | --- /dev/null | |
6497 | +++ b/drivers/macintosh/mol/include/asm.m4 | |
6498 | @@ -0,0 +1,141 @@ | |
6499 | +/* -*- asm -*- | |
6500 | + * Creation Date: <2001/12/30 20:08:53 samuel> | |
6501 | + * Time-stamp: <2002/01/14 00:48:09 samuel> | |
6502 | + * | |
6503 | + * <asm.m4> | |
6504 | + * | |
6505 | + * m4 initialization (m4 is used as an assembly preprocessor) | |
6506 | + * | |
6507 | + * Copyright (C) 2001, 2002, 2004 Samuel Rydh (samuel@ibrium.se) | |
6508 | + * | |
6509 | + * This program is free software; you can redistribute it and/or | |
6510 | + * modify it under the terms of the GNU General Public License | |
6511 | + * as published by the Free Software Foundation | |
6512 | + * | |
6513 | + */ | |
6514 | + | |
6515 | +/* This end-of-quote matches the start-of-quote in mol_config.h */ | |
6516 | +]]]]] | |
6517 | +divert(-1) | |
6518 | +changequote([,]) | |
6519 | + | |
6520 | +dnl m4 macros to avoid in header files (we can not rename these) | |
6521 | +dnl ========================================================== | |
6522 | +dnl shift, eval, expr, decr, incr, ifelse, popdef, pushdef | |
6523 | + | |
6524 | + | |
6525 | +dnl ************************************************************** | |
6526 | +dnl * Rename to reduce namespace conflicts | |
6527 | +dnl ************************************************************** | |
6528 | + | |
6529 | +dnl *** Changing the name of built-in macros using defn does not always work *** | |
6530 | + | |
6531 | +undefine([changecom]) | |
6532 | +undefine([changequote]) | |
6533 | +dnl undefine([decr]) | |
6534 | +undefine([defn]) | |
6535 | +dnl undefine([divert]) | |
6536 | +undefine([divnum]) | |
6537 | +undefine([errprint]) | |
6538 | +dnl undefine([eval]) | |
6539 | +dnl undefine([expr]) | |
6540 | +undefine([file]) | |
6541 | +undefine([format]) | |
6542 | +undefine([len]) | |
6543 | +undefine([line]) | |
6544 | +dnl undefine([ifelse]) | |
6545 | +dnl undefine([incr]) | |
6546 | +undefine([indir]) | |
6547 | +undefine([include]) | |
6548 | +undefine([index]) | |
6549 | +undefine([maketemp]) | |
6550 | +undefine([paste]) | |
6551 | +undefine([patsubst]) | |
6552 | +dnl undefine([popdef]) | |
6553 | +dnl undefine([pushdef]) | |
6554 | +undefine([regexp]) | |
6555 | +dnl undefine([shift]) | |
6556 | +undefine([sinclude]) | |
6557 | +undefine([spaste]) | |
6558 | +undefine([substr]) | |
6559 | +undefine([syscmd]) | |
6560 | +undefine([sysval]) | |
6561 | +undefine([translit]) | |
6562 | +undefine([traceoff]) | |
6563 | +undefine([traceon]) | |
6564 | +undefine([undivert]) | |
6565 | +undefine([unix]) | |
6566 | +dnl undefine([__gnu__]) | |
6567 | +dnl undefine([__unix__]) | |
6568 | + | |
6569 | +dnl Uncomment to list m4 definitions | |
6570 | +dnl dumpdef m4exit | |
6571 | + | |
6572 | +/************************************************************************/ | |
6573 | +/* M4 Macros */ | |
6574 | +/************************************************************************/ | |
6575 | + | |
6576 | +dnl | |
6577 | +dnl WARNING - M4 BUG IN MacOS X (10.1.2): | |
6578 | +dnl eval() in MacOS X (10.1.2) handles '&' as '&&' and '|' as '||'. | |
6579 | +dnl | |
6580 | + | |
6581 | +/* FORLOOP(var, from, to, [body var...]) */ | |
6582 | +define([mFORLOOP], [pushdef([$1], [$2])_mFORLOOP([$1], [$2], [$3], [$4])popdef([$1])]) | |
6583 | +define([_mFORLOOP], [$4[]ifelse($1, [$3], , | |
6584 | + [define([$1], incr($1))_mFORLOOP([$1], [$2], [$3], [$4])])]) | |
6585 | + | |
6586 | +define([mFIRST],[$1]) | |
6587 | +define([mCONCAT_C],[ [$@] ]) | |
6588 | + | |
6589 | +/* FOREACH(var, [item1, ...], [body var ...]) */ | |
6590 | +define([mFOREACH],[pushdef([$1],mFIRST($2))_mFOREACH([$1],[shift($2)],[$3])popdef([$1])]) | |
6591 | +define([_mFOREACH],[$3] [ifelse(mFIRST($2),,,[define([$1],mFIRST($2)) _mFOREACH([$1],[shift($2)],[$3])])]) | |
6592 | + | |
6593 | + | |
6594 | +/******************** Nice macro definitions **************************/ | |
6595 | + | |
6596 | +/* MACRO(name, [param1, ...], [body _param1 ...]) */ | |
6597 | +#ifdef __linux__ | |
6598 | +define([MACRO], [ | |
6599 | + .macro [$1] $2 | |
6600 | + mFOREACH([i],[$2],[ pushdef(_[]i,\i) ]) | |
6601 | + $3 | |
6602 | + .endm | |
6603 | + mFOREACH([i],[$2],[ popdef(_[]i) ]) | |
6604 | +]) | |
6605 | +#else | |
6606 | +define([MACRO], [ | |
6607 | + .macro [$1] | |
6608 | + pushdef([_n],0) | |
6609 | + mFOREACH([i],[$2],[ pushdef(_[]i,[$[]]_n) define([_n],incr(_n)) ]) | |
6610 | + $3 | |
6611 | + .endmacro | |
6612 | + mFOREACH([i],[$2],[ popdef(_[]i) ]) | |
6613 | + popdef([_n]) | |
6614 | +]) | |
6615 | +#endif | |
6616 | +define([MACRO_0], [MACRO([$1],[_dummy_param_],[$2])]) | |
6617 | + | |
6618 | + | |
6619 | +/* mDEFINE(name, [param1, ...], [body _param1 ...]) */ | |
6620 | +define([mDEFINE], [ | |
6621 | + pushdef([_n],1) | |
6622 | + mFOREACH([i],[$2],[ pushdef(_[]i,[$[]]_n) define([_n],incr(_n)) ]) | |
6623 | + define([$1], mCONCAT_C($3) ) | |
6624 | + mFOREACH([i],[$2],[ popdef(_[]i) ]) | |
6625 | + popdef([_n]) | |
6626 | +]) | |
6627 | + | |
6628 | + | |
6629 | +/* rLABEL(label): b label_b ; b label_f */ | |
6630 | +define(rLABEL,[dnl | |
6631 | +ifdef([$1]_curnum,,[$1[]f:])dnl | |
6632 | + define([_tmp_curnum],ifdef($1[]_curnum, [eval($1_curnum+1)], 1)) dnl | |
6633 | + define([$1]_curnum,_tmp_curnum)dnl | |
6634 | + define([$1]f,$1_[]eval($1_curnum[]+1) )dnl | |
6635 | + define([$1]b,$1_[]$1_curnum[] ) | |
6636 | +$1[]_[]$1_curnum[]dnl | |
6637 | +]) | |
6638 | + | |
6639 | +divert(0)dnl | |
6640 | --- /dev/null | |
6641 | +++ b/drivers/macintosh/mol/include/asm_offsets.inc | |
6642 | @@ -0,0 +1,136 @@ | |
6643 | +/* -*-c-*- | |
6644 | + * Creation Date: <2001/10/20 17:51:10 samuel> | |
6645 | + * Time-stamp: <2004/02/21 21:38:27 samuel> | |
6646 | + * | |
6647 | + * <asm_offsets.inc> | |
6648 | + * | |
6649 | + * Extra offsets (included from asm_offsets.c) | |
6650 | + * | |
6651 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
6652 | + * | |
6653 | + * This program is free software; you can redistribute it and/or | |
6654 | + * modify it under the terms of the GNU General Public License | |
6655 | + * as published by the Free Software Foundation | |
6656 | + * | |
6657 | + */ | |
6658 | + | |
6659 | +extern void extra( void ); | |
6660 | + | |
6661 | +void | |
6662 | +extra( void ) | |
6663 | +{ | |
6664 | + DEFINE(SIZE_OF_KERNEL_VARS, sizeof( kernel_vars_t )); | |
6665 | + | |
6666 | + ST_DEF( ST_MAGIC, magic ); | |
6667 | + ST_DEF( ST_KVARS_PH, kvars_ph ); | |
6668 | + | |
6669 | + K_DEF( K_EMUACCEL_PAGE, emuaccel_page ); | |
6670 | + K_DEF( K_EMUACCEL_PAGE_PHYS, emuaccel_page_phys ); | |
6671 | + K_DEF( K_EMUACCEL_MPHYS, emuaccel_mphys ); | |
6672 | + K_DEF( K_EMUACCEL_SIZE, emuaccel_size ); | |
6673 | + | |
6674 | + K_DEF( K_KERNEL_VARS, kvars_virt ); | |
6675 | + K_DEF( K_BREAK_FLAGS, break_flags ); | |
6676 | +#ifdef PERFORMANCE_INFO | |
6677 | + K_DEF( K_ASM_BUMP_CNTRS, asm_bump_cntr ); | |
6678 | + K_DEF( K_ASM_TICK_STAMPS, asm_tick_stamp ); | |
6679 | +#endif | |
6680 | + /* MMU */ | |
6681 | + K_DEF( K_ILLEGAL_SR, mmu.illegal_sr ); | |
6682 | + K_DEF( K_CUR_SR_BASE, mmu.cur_sr_base ); | |
6683 | + K_DEF( K_SR_DATA, mmu.sr_data ); | |
6684 | + K_DEF( K_SR_INST, mmu.sr_inst ); | |
6685 | + | |
6686 | + K_DEF( K_UNMAPPED_SR_BASE, mmu.unmapped_sr[0] ); | |
6687 | + K_DEF( K_USER_SR_BASE, mmu.user_sr[0] ); | |
6688 | + K_DEF( K_SV_SR_BASE, mmu.sv_sr[0] ); | |
6689 | + K_DEF( K_SPLIT_SR_BASE, mmu.split_sr[0] ); | |
6690 | + K_DEF( K_VSID_ENT_BASE, mmu.vsid[0] ); | |
6691 | + | |
6692 | +#ifdef __darwin__ | |
6693 | + K_DEF( K_OS_SDR1, mmu.os_sdr1 ); | |
6694 | + K_DEF( K_MOL_SDR1, mmu.mol_sdr1 ); | |
6695 | + DEFINE( SKIPLIST_NEXT, offsetof(skiplist_el_t, level[0].next_phys) ); | |
6696 | +#endif | |
6697 | +#ifdef __linux__ | |
6698 | + DEFINE( SKIPLIST_NEXT, offsetof(skiplist_el_t, level[0].next) ); | |
6699 | +#endif | |
6700 | + DEFINE( SKIPLIST_LEVELSIZE, sizeof(skiplist_level_t) ); | |
6701 | + DEFINE( SKIPLIST_KEY, offsetof(skiplist_el_t, key) ); | |
6702 | + DEFINE( K_VSID_SL_ROOT_ELEM, offsetof(kernel_vars_t, mmu.vsid_sl.root) | |
6703 | + - offsetof(skiplist_el_t, level)); | |
6704 | + K_DEF( K_VSID_SL_SLEVEL, mmu.vsid_sl.slevel ); | |
6705 | + | |
6706 | + K_DEF( K_IBAT0U_SAVE, _bp.ibat_save[0].word[0] ); | |
6707 | + K_DEF( K_IBAT0L_SAVE, _bp.ibat_save[0].word[1] ); | |
6708 | + K_DEF( K_IBAT1U_SAVE, _bp.ibat_save[1].word[0] ); | |
6709 | + K_DEF( K_IBAT1L_SAVE, _bp.ibat_save[1].word[1] ); | |
6710 | + K_DEF( K_IBAT2U_SAVE, _bp.ibat_save[2].word[0] ); | |
6711 | + K_DEF( K_IBAT2L_SAVE, _bp.ibat_save[2].word[1] ); | |
6712 | + K_DEF( K_IBAT3U_SAVE, _bp.ibat_save[3].word[0] ); | |
6713 | + K_DEF( K_IBAT3L_SAVE, _bp.ibat_save[3].word[1] ); | |
6714 | + | |
6715 | + K_DEF( K_DBAT0U_SAVE, _bp.dbat_save[0].word[0] ); | |
6716 | + K_DEF( K_DBAT0L_SAVE, _bp.dbat_save[0].word[1] ); | |
6717 | + K_DEF( K_DBAT1U_SAVE, _bp.dbat_save[1].word[0] ); | |
6718 | + K_DEF( K_DBAT1L_SAVE, _bp.dbat_save[1].word[1] ); | |
6719 | + K_DEF( K_DBAT2U_SAVE, _bp.dbat_save[2].word[0] ); | |
6720 | + K_DEF( K_DBAT2L_SAVE, _bp.dbat_save[2].word[1] ); | |
6721 | + K_DEF( K_DBAT3U_SAVE, _bp.dbat_save[3].word[0] ); | |
6722 | + K_DEF( K_DBAT3L_SAVE, _bp.dbat_save[3].word[1] ); | |
6723 | + | |
6724 | + K_DEF( K_SPLIT_DBAT0U, mmu.split_dbat0.word[0] ); | |
6725 | + K_DEF( K_SPLIT_DBAT0L, mmu.split_dbat0.word[1] ); | |
6726 | + K_DEF( K_TRANSL_DBAT0U, mmu.transl_dbat0.word[0] ); | |
6727 | + K_DEF( K_TRANSL_DBAT0L, mmu.transl_dbat0.word[1] ); | |
6728 | + | |
6729 | + K_DEF( K_TLBHASH_SR, mmu.pthash_sr ); | |
6730 | + K_DEF( K_TLBHASH_BASE_EA, mmu.pthash_ea_base ); | |
6731 | + K_DEF( K_HASH_MASK, mmu.hash_mask ); | |
6732 | + K_DEF( K_PTHASH_INUSE_PH, mmu.pthash_inuse_bits_ph ); | |
6733 | + | |
6734 | + /* fields private to the assembly files */ | |
6735 | + K_DEF( K_MSR, _bp._msr ); | |
6736 | + | |
6737 | + K_DEF( K_DEC_STAMP, _bp.dec_stamp ); | |
6738 | + K_DEF( K_INT_STAMP, _bp.int_stamp); | |
6739 | + | |
6740 | + K_DEF( K_TMP_SCRATCH0, _bp.tmp_scratch[0] ); | |
6741 | + K_DEF( K_TMP_SCRATCH1, _bp.tmp_scratch[1] ); | |
6742 | + K_DEF( K_TMP_SCRATCH2, _bp.tmp_scratch[2] ); | |
6743 | + K_DEF( K_TMP_SCRATCH3, _bp.tmp_scratch[3] ); | |
6744 | + | |
6745 | + K_DEF( K_SPLIT_NIP_SEGMENT, _bp.split_nip_segment ); | |
6746 | + | |
6747 | + K_DEF( K_SPR_HOOKS, _bp.spr_hooks ); | |
6748 | + | |
6749 | + /* private to emulation.S */ | |
6750 | + K_DEF( K_MSR_SR_TABLE, _bp.msr_sr_table[0] ); | |
6751 | + | |
6752 | + /* io_page_t type */ | |
6753 | + IO_DEF( IOP_MAGIC, magic ); | |
6754 | + IO_DEF( IOP_MAGIC2, magic2 ); | |
6755 | + IO_DEF( IOP_MPHYS, mphys ); | |
6756 | + IO_DEF( IOP_ME_PHYS, me_phys ); | |
6757 | + IO_DEF( IOP_NEXT, next ); | |
6758 | + IO_DEF( IOP_USR_DATA, usr_data ); | |
6759 | + | |
6760 | + /****** New Low-level assembly implementation ***********/ | |
6761 | + | |
6762 | + K_DEF( K_EMULATOR_STACK, _bp.emulator_stack ); | |
6763 | + K_DEF( K_EMULATOR_TOC, _bp.emulator_toc ); | |
6764 | + K_DEF( K_EMULATOR_NIP, _bp.emulator_nip ); | |
6765 | + K_DEF( K_EMULATOR_MSR, _bp.emulator_msr ); | |
6766 | + K_DEF( K_EMULATOR_SPRG2, _bp.emulator_sprg2 ); | |
6767 | + K_DEF( K_EMULATOR_SPRG3, _bp.emulator_sprg3 ); | |
6768 | + K_DEF( K_EMULATOR_KCALL_NIP, _bp.emulator_kcall_nip ); | |
6769 | + | |
6770 | + K_DEF( K_EMULATOR_SR, mmu.emulator_sr ); | |
6771 | + | |
6772 | +#ifdef __darwin__ | |
6773 | + K_DEF( K_KCALL_ROUTINE, kcall_routine ); | |
6774 | + K_DEF( K_KCALL_ARG0, kcall_args[0] ); | |
6775 | + K_DEF( K_KCALL_ARG1, kcall_args[1] ); | |
6776 | + K_DEF( K_KCALL_ARG2, kcall_args[2] ); | |
6777 | +#endif | |
6778 | +} | |
6779 | --- /dev/null | |
6780 | +++ b/drivers/macintosh/mol/include/asmdbg.h | |
6781 | @@ -0,0 +1,184 @@ | |
6782 | +/* | |
6783 | + * Creation Date: <2004/01/29 20:12:41 samuel> | |
6784 | + * Time-stamp: <2004/03/06 13:17:36 samuel> | |
6785 | + * | |
6786 | + * <asmdbg.h> | |
6787 | + * | |
6788 | + * debug support | |
6789 | + * | |
6790 | + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) | |
6791 | + * | |
6792 | + * This program is free software; you can redistribute it and/or | |
6793 | + * modify it under the terms of the GNU General Public License | |
6794 | + * version 2 | |
6795 | + * | |
6796 | + */ | |
6797 | + | |
6798 | +#ifndef _H_ASMDBG | |
6799 | +#define _H_ASMDBG | |
6800 | + | |
6801 | + | |
6802 | +/************************************************************************/ | |
6803 | +/* Performance Statistics */ | |
6804 | +/************************************************************************/ | |
6805 | + | |
6806 | +#ifdef PERFORMANCE_INFO | |
6807 | + define([_bump_ind_], 0) | |
6808 | + | |
6809 | +#define __BUMP( str ) \ | |
6810 | + .text 92 ;\ | |
6811 | +debug_str_[]_bump_ind_: ;\ | |
6812 | + .if (_bump_ind_ >= NUM_ASM_BUMP_CNTRS) ;\ | |
6813 | + .print "** too many BUMP counters **" ; .fail 1 ;\ | |
6814 | + .endif ;\ | |
6815 | + .ascii str "\0" ;\ | |
6816 | + balign_4 ;\ | |
6817 | + .text 90 ;\ | |
6818 | + .long (debug_str_[]_bump_ind_-__start_bumptable) ;\ | |
6819 | + .text ;\ | |
6820 | + stw r3,xDEBUG_SCR1(r1) ;\ | |
6821 | + lwz r3,(K_ASM_BUMP_CNTRS+4*_bump_ind_)(r1) ;\ | |
6822 | + addi r3,r3,1 ;\ | |
6823 | + stw r3,(K_ASM_BUMP_CNTRS+4*_bump_ind_)(r1) ;\ | |
6824 | + lwz r3,xDEBUG_SCR1(r1) ;\ | |
6825 | + define([_bump_ind_],eval(_bump_ind_+1)) | |
6826 | + | |
6827 | + | |
6828 | + define([_tick_ind_], 0) | |
6829 | + | |
6830 | +#define __ZERO_TICK_CNT(cntr) \ | |
6831 | + ifdef([##cntr##_ind_],[],[ \ | |
6832 | + define([##cntr##_ind_], _tick_ind_) \ | |
6833 | + define([_tick_ind_], eval(_tick_ind_+1)) \ | |
6834 | + ]) \ | |
6835 | + .if (_tick_ind_ > NUM_ASM_TICK_CNTRS) ;\ | |
6836 | + .print "** too many TICK counters **" ; .fail 1 ;\ | |
6837 | + .endif ;\ | |
6838 | + stw r3,xDEBUG_SCR1(r1) ;\ | |
6839 | + mftb r3 ;\ | |
6840 | + stw r3,(K_ASM_TICK_STAMPS + 4*cntr##_ind_)(r1) ;\ | |
6841 | + lwz r3,xDEBUG_SCR1(r1) | |
6842 | + | |
6843 | +#define __GET_TICK_CNT(cntr, name) \ | |
6844 | + .text 92 ;\ | |
6845 | +debug_str_[]_bump_ind_: ;\ | |
6846 | + .if (_bump_ind_ >= NUM_ASM_BUMP_CNTRS) ;\ | |
6847 | + .print "** too many BUMP counters **" ; .fail 1 ;\ | |
6848 | + .endif ;\ | |
6849 | + .ascii name "_ticks\0" ;\ | |
6850 | + balign_4 ;\ | |
6851 | + .text 90 ;\ | |
6852 | + .long (debug_str_[]_bump_ind_-__start_bumptable) ;\ | |
6853 | + .text ;\ | |
6854 | + ifdef([##cntr##_ind_],[],[ \ | |
6855 | + define([##cntr##_ind_], _tick_ind_) \ | |
6856 | + define([_tick_ind_], eval(_tick_ind_+1)) \ | |
6857 | + ]) \ | |
6858 | + .if (_tick_ind_ > NUM_ASM_TICK_CNTRS) ;\ | |
6859 | + .print "** too many TICK counters **" ; .fail 1 ;\ | |
6860 | + .endif ;\ | |
6861 | + stw r3,xDEBUG_SCR1(r1) ;\ | |
6862 | + mftb r3 ;\ | |
6863 | + stw r4,xDEBUG_SCR2(r1) ;\ | |
6864 | + lwz r4,(K_ASM_TICK_STAMPS + 4*cntr##_ind_)(r1) ;\ | |
6865 | + sub r3,r3,r4 ;\ | |
6866 | + lwz r4,(K_ASM_BUMP_CNTRS+4*_bump_ind_)(r1) ;\ | |
6867 | + add r4,r4,r3 ;\ | |
6868 | + stw r4,(K_ASM_BUMP_CNTRS+4*_bump_ind_)(r1) ;\ | |
6869 | + lwz r3,xDEBUG_SCR1(r1) ;\ | |
6870 | + mftb r4 ;\ | |
6871 | + stw r4,(K_ASM_TICK_STAMPS + 4*cntr##_ind_)(r1) ;\ | |
6872 | + lwz r4,xDEBUG_SCR2(r1) ;\ | |
6873 | + define([_bump_ind_],eval(_bump_ind_+1)) | |
6874 | + | |
6875 | +#endif /* PERFORMANCE_INFO */ | |
6876 | + | |
6877 | +#ifndef PERFORMANCE_INFO_LIGHT | |
6878 | +#define BUMP(s) __BUMP(s) | |
6879 | +#define ZERO_TICK_CNT(c) __ZERO_TICK_CNT(c) | |
6880 | +#define GET_TICK_CNT(c, name) __GET_TICK_CNT(c,name) | |
6881 | +#else | |
6882 | +#define BUMP(s) | |
6883 | +#define ZERO_TICK_CNT(c) | |
6884 | +#define GET_TICK_CNT(c, name) | |
6885 | +#endif | |
6886 | + | |
6887 | +#ifndef __BUMP | |
6888 | +#define __BUMP(str) | |
6889 | +#define __ZERO_TICK_CNT(cntr) | |
6890 | +#define __GET_TICK_CNT(cntr, name) | |
6891 | +#endif | |
6892 | + | |
6893 | +#ifdef PERF_MONITOR | |
6894 | +MACRO(PERF_MONITOR_GET, [ | |
6895 | + stw r5,xDEBUG_SCR1(r1) | |
6896 | + mfspr r5,S_PMC2 | |
6897 | + stw r4,xDEBUG_SCR2(r1) | |
6898 | + mfmsr r4 | |
6899 | + ori r4,r4,MSR_PE | |
6900 | + mtmsr r4 | |
6901 | + stw r5,xDEBUG0(r1) | |
6902 | + li r5,0 | |
6903 | + mtspr S_PMC2,r5 | |
6904 | + lwz r4,xDEBUG_SCR2(r1) | |
6905 | + lwz r5,xDEBUG_SCR1(r1) | |
6906 | +]) | |
6907 | +MACRO(PERF_MONITOR_SETUP, [scr], [ | |
6908 | + LOADI _scr,BIT(2) | BIT(3) | BIT(31) // count in SV-mode if PM is zero. | |
6909 | + mtspr S_MMCR0,_scr | |
6910 | + li _scr,0 | |
6911 | + mtspr S_MMCR1,_scr | |
6912 | + li _scr,0 | |
6913 | + mtspr S_PMC2,_scr | |
6914 | +]) | |
6915 | +#else /* PERF_MONITOR */ | |
6916 | +#define PERF_MONITOR_GET | |
6917 | +MACRO(PERF_MONITOR_SETUP, [scr], []) | |
6918 | +#endif | |
6919 | + | |
6920 | + | |
6921 | +/************************************************************************/ | |
6922 | +/* debug */ | |
6923 | +/************************************************************************/ | |
6924 | + | |
6925 | +MACRO(STOP_EMULATION, [val], [ | |
6926 | + stw r3,xDEBUG_SCR1(r1) | |
6927 | + li r3,_val | |
6928 | + stw r3,xKERNEL_DBG_STOP(r1) | |
6929 | + li r3,1 | |
6930 | + stw r3,xINTERRUPT(r1) | |
6931 | + lwz r3,xDEBUG_SCR1(r1) | |
6932 | +]) | |
6933 | + | |
6934 | +MACRO(DEBUG_TRACE, [num, dummy], [ | |
6935 | + stw r3,xDEBUG_SCR1(r1) | |
6936 | + lwz r3,xDEBUG_TRACE(r1) | |
6937 | + addi r3,r3,1 | |
6938 | + stw r3,xDEBUG_TRACE(r1) | |
6939 | + stw r3,(xDEBUG0+4*_num)(r1) | |
6940 | + lwz r3,xDEBUG_SCR1(r1) | |
6941 | +]) | |
6942 | + | |
6943 | +MACRO(TRACE_VAL, [val, dummy], [ | |
6944 | +#if DBG_TRACE | |
6945 | + stw r30,xDEBUG_SCR1(r1) | |
6946 | + stw r29,xDEBUG_SCR2(r1) | |
6947 | + lwz r30,xDEBUG_TRACE(r1) | |
6948 | + rlwinm r30,r30,0,24,31 // 256 entries | |
6949 | + rlwinm r30,r30,2,22,29 | |
6950 | + addi r30,r30,xDBG_TRACE_SPACE | |
6951 | + lis r29,HA(_val) | |
6952 | + addi r29,r29,LO(_val) | |
6953 | + stwx r29,r30,r1 | |
6954 | + lwz r30,xDEBUG_TRACE(r1) | |
6955 | + addi r30,r30,1 | |
6956 | + rlwinm r30,r30,0,24,31 // 256 entries | |
6957 | + stw r30,xDEBUG_TRACE(r1) | |
6958 | + lwz r29,xDEBUG_SCR2(r1) | |
6959 | + lwz r30,xDEBUG_SCR1(r1) | |
6960 | +#endif | |
6961 | +]) | |
6962 | +#define TRACE( a,b ) TRACE_VAL a,b | |
6963 | + | |
6964 | + | |
6965 | +#endif /* _H_ASMDBG */ | |
6966 | --- /dev/null | |
6967 | +++ b/drivers/macintosh/mol/include/asmdefs.h | |
6968 | @@ -0,0 +1,397 @@ | |
6969 | +/* -*- asm -*- | |
6970 | + * | |
6971 | + * Creation Date: <2001/02/03 19:38:07 samuel> | |
6972 | + * Time-stamp: <2004/02/22 15:36:20 samuel> | |
6973 | + * | |
6974 | + * <asmdefs.h> | |
6975 | + * | |
6976 | + * Common assembly definitions | |
6977 | + * | |
6978 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
6979 | + * | |
6980 | + * This program is free software; you can redistribute it and/or | |
6981 | + * modify it under the terms of the GNU General Public License | |
6982 | + * as published by the Free Software Foundation | |
6983 | + * | |
6984 | + */ | |
6985 | + | |
6986 | +#ifndef _H_ASMDEFS | |
6987 | +#define _H_ASMDEFS | |
6988 | + | |
6989 | +#include "asm.m4" | |
6990 | + | |
6991 | +#ifndef __ASSEMBLY__ | |
6992 | +#error This file is only to be included from assembler code! | |
6993 | +#endif | |
6994 | + | |
6995 | + | |
6996 | +/************************************************************************/ | |
6997 | +/* High/low halfword compatibility macros */ | |
6998 | +/************************************************************************/ | |
6999 | + | |
7000 | +#ifdef __linux__ | |
7001 | +#define ha16( v ) (v)##@ha | |
7002 | +#define hi16( v ) (v)##@h | |
7003 | +#define lo16( v ) (v)##@l | |
7004 | +#endif | |
7005 | +#define HA(v) ha16(v) | |
7006 | +#define HI(v) hi16(v) | |
7007 | +#define LO(v) lo16(v) | |
7008 | + | |
7009 | +/************************************************************************/ | |
7010 | +/* Stack Frame */ | |
7011 | +/************************************************************************/ | |
7012 | + | |
7013 | +#ifdef __linux__ | |
7014 | +#define STACK_LR_OFFSET 4 | |
7015 | +#endif | |
7016 | + | |
7017 | +#ifdef __darwin__ | |
7018 | +#define STACK_LR_OFFSET 8 /* 4 is the CR offset */ | |
7019 | +#endif | |
7020 | + | |
7021 | +/************************************************************************/ | |
7022 | +/* Register name prefix */ | |
7023 | +/************************************************************************/ | |
7024 | + | |
7025 | +#ifdef __linux__ | |
7026 | +define([rPREFIX], []) | |
7027 | +define([fPREFIX], []) | |
7028 | +define([srPREFIX], []) | |
7029 | +#else | |
7030 | +define([rPREFIX], [r]) | |
7031 | +define([fPREFIX], [f]) | |
7032 | +define([srPREFIX], [sr]) | |
7033 | +/* frN -> fN */ | |
7034 | +mFORLOOP([i],0,31,[define(fr[]i,f[]i)]) | |
7035 | +#endif | |
7036 | + | |
7037 | +/************************************************************************/ | |
7038 | +/* Macros and definitions */ | |
7039 | +/************************************************************************/ | |
7040 | + | |
7041 | +#ifdef __darwin__ | |
7042 | +#define balign_4 .align 2,0 | |
7043 | +#define balign_8 .align 3,0 | |
7044 | +#define balign_16 .align 4,0 | |
7045 | +#define balign_32 .align 5,0 | |
7046 | +#endif | |
7047 | + | |
7048 | +#ifdef __linux__ | |
7049 | +#define balign_4 .balign 4,0 | |
7050 | +#define balign_8 .balign 8,0 | |
7051 | +#define balign_16 .balign 16,0 | |
7052 | +#define balign_32 .balign 32,0 | |
7053 | +#endif | |
7054 | + | |
7055 | +MACRO(LOADVAR, [dreg, variable], [ | |
7056 | + lis _dreg,HA(_variable) | |
7057 | + lwz _dreg,LO(_variable)(_dreg) | |
7058 | +]) | |
7059 | + | |
7060 | +MACRO(LOADI, [dreg, addr], [ | |
7061 | + lis _dreg,HA(_addr) | |
7062 | + addi _dreg,_dreg,LO(_addr) | |
7063 | +]) | |
7064 | + | |
7065 | +MACRO(LOAD_GPR_RANGE, [start, endx, offs, base], [ | |
7066 | + mFORLOOP([i],0,31,[ .if (i >= _start) & (i <= _endx) | |
7067 | + lwz rPREFIX[]i,_offs+i[]*4(_base) | |
7068 | + .endif | |
7069 | +])]) | |
7070 | + | |
7071 | +MACRO(STORE_GPR_RANGE, [start, endx, offs, base], [ | |
7072 | + mFORLOOP([i],0,31,[ .if (i >= _start) & (i <= _endx) | |
7073 | + stw rPREFIX[]i,_offs+i[]*4(_base) | |
7074 | + .endif | |
7075 | +])]) | |
7076 | + | |
7077 | +MACRO(LOAD_FPR_RANGE, [start, endx, offs, base], [ | |
7078 | + mFORLOOP([i],0,31,[ .if (i >= _start) & (i <= _endx) | |
7079 | + lfd fPREFIX[]i,_offs+i[]*8(_base) | |
7080 | + .endif | |
7081 | +])]) | |
7082 | + | |
7083 | +MACRO(STORE_FPR_RANGE, [start, endx, offs, base], [ | |
7084 | + mFORLOOP([i],0,31,[ .if (i >= _start) & (i <= _endx) | |
7085 | + stfd fPREFIX[]i,_offs+i[]*8(_base) | |
7086 | + .endif | |
7087 | +])]) | |
7088 | + | |
7089 | +/************************************************************************/ | |
7090 | +/* FPU load/save macros */ | |
7091 | +/************************************************************************/ | |
7092 | + | |
7093 | + // The FPU macros are used both in the kernel and in | |
7094 | + // mainloop_asm.h. | |
7095 | + | |
7096 | +MACRO(xFPR_LOAD_RANGE, [from, to, mbase], [ | |
7097 | + LOAD_FPR_RANGE _from,_to,xFPR_BASE,_mbase | |
7098 | +]) | |
7099 | +MACRO(xFPR_SAVE_RANGE, [from, to, mbase], [ | |
7100 | + STORE_FPR_RANGE _from,_to,xFPR_BASE,_mbase | |
7101 | +]) | |
7102 | + // The low half of the fpu is fr0-fr12. I.e. the FPU registers | |
7103 | + // that might be overwritten when a function call is taken | |
7104 | + // (fr13 and fpscr are treated specially). | |
7105 | + | |
7106 | +MACRO(xLOAD_LOW_FPU, [mbase], [ | |
7107 | + xFPR_LOAD_RANGE 0,12,_mbase | |
7108 | +]) | |
7109 | + | |
7110 | +MACRO(xLOAD_TOPHALF_FPU, [mbase], [ | |
7111 | + xFPR_LOAD_RANGE 14,31,_mbase | |
7112 | +]) | |
7113 | +MACRO(xLOAD_FULL_FPU, [mbase], [ | |
7114 | + xLOAD_LOW_FPU _mbase | |
7115 | + xLOAD_TOPHALF_FPU _mbase | |
7116 | +]) | |
7117 | + | |
7118 | +MACRO(xSAVE_LOW_FPU, [mbase], [ | |
7119 | + xFPR_SAVE_RANGE 0,12,_mbase | |
7120 | +]) | |
7121 | +MACRO(xSAVE_TOPHALF_FPU, [mbase], [ | |
7122 | + xFPR_SAVE_RANGE 14,31,_mbase | |
7123 | +]) | |
7124 | +MACRO(xSAVE_FULL_FPU, [mbase], [ | |
7125 | + xSAVE_LOW_FPU _mbase | |
7126 | + xSAVE_TOPHALF_FPU _mbase | |
7127 | +]) | |
7128 | + | |
7129 | + | |
7130 | +/************************************************************************/ | |
7131 | +/* GPR load/save macros */ | |
7132 | +/************************************************************************/ | |
7133 | + | |
7134 | +MACRO(xGPR_SAVE_RANGE, [from, to, mbase], [ | |
7135 | + STORE_GPR_RANGE _from, _to, xGPR0, _mbase | |
7136 | +]) | |
7137 | + | |
7138 | +MACRO(xGPR_LOAD_RANGE, [from, to, mbase], [ | |
7139 | + LOAD_GPR_RANGE _from, _to, xGPR0, _mbase | |
7140 | +]) | |
7141 | + | |
7142 | + | |
7143 | +/************************************************************************/ | |
7144 | +/* AltiVec */ | |
7145 | +/************************************************************************/ | |
7146 | + | |
7147 | +#ifdef __linux__ | |
7148 | + | |
7149 | +define(vPREFIX,[]) | |
7150 | + | |
7151 | +#ifndef HAVE_ALTIVEC | |
7152 | +#define VEC_OPCODE( op1,op2,A,B,C ) \ | |
7153 | + .long (((op1) << (32-6)) | (op2) | ((A) << (32-11)) | ((B) << (32-16)) | ((C) << (32-21))) ; | |
7154 | + | |
7155 | +#define __stvx( vS,rA,rB ) VEC_OPCODE( 31,0x1ce,vS,rA,rB ) | |
7156 | +#define __lvx( vD,rA,rB ) VEC_OPCODE( 31,0xce, vD,rA,rB ) | |
7157 | +#define __mfvscr( vD ) VEC_OPCODE( 4,1540,vD,0,0 ) | |
7158 | +#define __mtvscr( vB ) VEC_OPCODE( 4,1604,0,0,vB ) | |
7159 | +#define __stvewx( vS,rA,rB ) VEC_OPCODE( 31,(199<<1), vS,rA,rB ) | |
7160 | + | |
7161 | +mFORLOOP([i],0,31,[define(v[]i,[]i)]) | |
7162 | +MACRO(stvx, [vS,rA,rB], [ __stvx( _vS,_rA,_rB ) ; ]) | |
7163 | +MACRO(lvx, [vD,rA,rB], [ __lvx( _vD,_rA,_rB ) ; ]) | |
7164 | +MACRO(mfvscr, [vD], [ __mfvscr( _vD ) ; ]) | |
7165 | +MACRO(mtvscr, [vB], [ __mtvscr( _vB ) ; ]) | |
7166 | +MACRO(stvewx, [vS,rA,rB], [ __stvewx( _vS,_rA,_rB ) ; ]) | |
7167 | +#endif | |
7168 | +#else /* __linux__ */ | |
7169 | + | |
7170 | +define(vPREFIX,[v]) | |
7171 | + | |
7172 | +#endif /* __linux__ */ | |
7173 | + | |
7174 | + | |
7175 | +// NOTE: Writing to VSCR won't cause exceptions (this | |
7176 | +// is different compared to FPSCR). | |
7177 | + | |
7178 | +MACRO(xVEC_SAVE, [mbase, scr], [ | |
7179 | + addi _scr,_mbase,xVEC_BASE | |
7180 | + mFORLOOP([i],0,31,[ | |
7181 | + stvx vPREFIX[]i,0,_scr | |
7182 | + addi _scr,_scr,16 | |
7183 | + ]) | |
7184 | + addi _scr,_mbase,xVSCR-12 | |
7185 | + mfvscr v0 | |
7186 | + stvx v0,0,_scr | |
7187 | + addi _scr,_mbase,xVEC0 | |
7188 | + lvx v0,0,_scr | |
7189 | + mfspr _scr,S_VRSAVE | |
7190 | + stw _scr,xVRSAVE(_mbase) | |
7191 | +]) | |
7192 | + | |
7193 | +MACRO(xVEC_LOAD, [mbase, scr], [ | |
7194 | + addi _scr,_mbase,xVSCR-12 | |
7195 | + lvx v0,0,_scr | |
7196 | + mtvscr v0 | |
7197 | + addi _scr,_mbase,xVEC_BASE | |
7198 | + mFORLOOP([i],0,31,[ | |
7199 | + lvx vPREFIX[]i,0,_scr | |
7200 | + addi _scr,_scr,16 | |
7201 | + ]) | |
7202 | + lwz _scr,xVRSAVE(_mbase) | |
7203 | + mtspr S_VRSAVE,_scr | |
7204 | +]) | |
7205 | + | |
7206 | +/************************************************************************/ | |
7207 | +/* Instructions */ | |
7208 | +/************************************************************************/ | |
7209 | + | |
7210 | +#ifdef __darwin__ | |
7211 | +MACRO(mtsprg0, [reg], [mtspr SPRG0,_reg] ) | |
7212 | +MACRO(mtsprg1, [reg], [mtspr SPRG1,_reg] ) | |
7213 | +MACRO(mtsprg2, [reg], [mtspr SPRG2,_reg] ) | |
7214 | +MACRO(mtsprg3, [reg], [mtspr SPRG3,_reg] ) | |
7215 | +MACRO(mfsprg0, [reg], [mfspr _reg,SPRG0] ) | |
7216 | +MACRO(mfsprg1, [reg], [mfspr _reg,SPRG1] ) | |
7217 | +MACRO(mfsprg2, [reg], [mfspr _reg,SPRG2] ) | |
7218 | +MACRO(mfsprg3, [reg], [mfspr _reg,SPRG3] ) | |
7219 | +#endif | |
7220 | + | |
7221 | +/************************************************************************/ | |
7222 | +/* Register names */ | |
7223 | +/************************************************************************/ | |
7224 | + | |
7225 | +#define cr0_lt 0 | |
7226 | +#define cr0_gt 1 | |
7227 | +#define cr0_eq 2 | |
7228 | +#define cr0_so 3 | |
7229 | + | |
7230 | +#define cr1_lt 4 | |
7231 | +#define cr1_gt 5 | |
7232 | +#define cr1_eq 6 | |
7233 | +#define cr1_so 7 | |
7234 | + | |
7235 | +#define cr2_lt 8 | |
7236 | +#define cr2_gt 9 | |
7237 | +#define cr2_eq 10 | |
7238 | +#define cr2_so 11 | |
7239 | + | |
7240 | +#define cr3_lt 12 | |
7241 | +#define cr3_gt 13 | |
7242 | +#define cr3_eq 14 | |
7243 | +#define cr3_so 15 | |
7244 | + | |
7245 | +#ifdef __darwin__ | |
7246 | +/* IMPORTANT: we may *not* define crN on darwin; If we do, the | |
7247 | + * assembler will generate bogus code. For instance, | |
7248 | + * bne cr1,1f is not equivalent to bne 1,1f but to | |
7249 | + * bne 4,1f... | |
7250 | + */ | |
7251 | +#define lt 0 /* Less than */ | |
7252 | +#define gt 1 /* Greater than */ | |
7253 | +#define eq 2 /* Equal */ | |
7254 | +#define so 3 /* Summary Overflow */ | |
7255 | +#define un 3 /* Unordered (after floating point) */ | |
7256 | +#endif | |
7257 | + | |
7258 | +/* FPU register names (to be used as macro arguments) */ | |
7259 | +#define FR0 0 | |
7260 | +#define FR1 1 | |
7261 | +#define FR2 2 | |
7262 | +#define FR3 3 | |
7263 | +#define FR4 4 | |
7264 | +#define FR5 5 | |
7265 | +#define FR6 6 | |
7266 | +#define FR7 7 | |
7267 | +#define FR8 8 | |
7268 | +#define FR9 9 | |
7269 | +#define FR10 10 | |
7270 | +#define FR11 11 | |
7271 | +#define FR12 12 | |
7272 | +#define FR13 13 | |
7273 | +#define FR14 14 | |
7274 | +#define FR15 15 | |
7275 | +#define FR16 16 | |
7276 | +#define FR17 17 | |
7277 | +#define FR18 18 | |
7278 | +#define FR19 19 | |
7279 | +#define FR20 20 | |
7280 | +#define FR21 21 | |
7281 | +#define FR22 22 | |
7282 | +#define FR23 23 | |
7283 | +#define FR24 24 | |
7284 | +#define FR25 25 | |
7285 | +#define FR26 26 | |
7286 | +#define FR27 27 | |
7287 | +#define FR28 28 | |
7288 | +#define FR29 29 | |
7289 | +#define FR30 30 | |
7290 | +#define FR31 31 | |
7291 | + | |
7292 | +/* GPR register names (to be used as macro arguments) */ | |
7293 | +#define R0 0 | |
7294 | +#define R1 1 | |
7295 | +#define R2 2 | |
7296 | +#define R3 3 | |
7297 | +#define R4 4 | |
7298 | +#define R5 5 | |
7299 | +#define R6 6 | |
7300 | +#define R7 7 | |
7301 | +#define R8 8 | |
7302 | +#define R9 9 | |
7303 | +#define R10 10 | |
7304 | +#define R11 11 | |
7305 | +#define R12 12 | |
7306 | +#define R13 13 | |
7307 | +#define R14 14 | |
7308 | +#define R15 15 | |
7309 | +#define R16 16 | |
7310 | +#define R17 17 | |
7311 | +#define R18 18 | |
7312 | +#define R19 19 | |
7313 | +#define R20 20 | |
7314 | +#define R21 21 | |
7315 | +#define R22 22 | |
7316 | +#define R23 23 | |
7317 | +#define R24 24 | |
7318 | +#define R25 25 | |
7319 | +#define R26 26 | |
7320 | +#define R27 27 | |
7321 | +#define R28 28 | |
7322 | +#define R29 29 | |
7323 | +#define R30 30 | |
7324 | +#define R31 31 | |
7325 | + | |
7326 | +#ifndef __darwin__ | |
7327 | + | |
7328 | +/* GPR register names, rN -> N, frN -> N, vN -> N */ | |
7329 | +mFORLOOP([i],0,31,[define(r[]i,[]i)]) | |
7330 | +mFORLOOP([i],0,31,[define(fr[]i,[]i)]) | |
7331 | +mFORLOOP([i],0,31,[define(v[]i,[]i)]) | |
7332 | + | |
7333 | +#endif /* __darwin__ */ | |
7334 | + | |
7335 | + | |
7336 | +/************************************************************************/ | |
7337 | +/* useful macros */ | |
7338 | +/************************************************************************/ | |
7339 | + | |
7340 | +MACRO(ori_, [reg1, reg2, value], [ | |
7341 | + .if (_value & 0xffff) | |
7342 | + ori _reg1, _reg2, (_value) & 0xffff | |
7343 | + .endif | |
7344 | + .if (_value & ~0xffff) | |
7345 | + oris _reg1, _reg2, (_value) >> 16 | |
7346 | + .endif | |
7347 | +]) | |
7348 | + | |
7349 | +/************************************************************************/ | |
7350 | +/* MISC */ | |
7351 | +/************************************************************************/ | |
7352 | + | |
7353 | +#ifdef __linux__ | |
7354 | +#define GLOBL( name ) .globl name ; name | |
7355 | +#define EXTERN( name ) name | |
7356 | +#else | |
7357 | +/* an underscore is needed on Darwin */ | |
7358 | +#define GLOBL( name ) .globl _##name ; name: ; _##name | |
7359 | +#define EXTERN( name ) _##name | |
7360 | +#endif | |
7361 | + | |
7362 | +#define BIT(n) (1<<(31-(n))) | |
7363 | + | |
7364 | +#endif /* _H_ASMDEFS */ | |
7365 | + | |
7366 | --- /dev/null | |
7367 | +++ b/drivers/macintosh/mol/include/asmfuncs.h | |
7368 | @@ -0,0 +1,80 @@ | |
7369 | +/* | |
7370 | + * Creation Date: <1999/09/26 01:02:58 samuel> | |
7371 | + * Time-stamp: <2003/07/27 19:20:24 samuel> | |
7372 | + * | |
7373 | + * <asmfuncs.h> | |
7374 | + * | |
7375 | + * Exports from <base.S> | |
7376 | + * | |
7377 | + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
7378 | + * | |
7379 | + * This program is free software; you can redistribute it and/or | |
7380 | + * modify it under the terms of the GNU General Public License | |
7381 | + * as published by the Free Software Foundation | |
7382 | + * | |
7383 | + */ | |
7384 | + | |
7385 | +#ifndef _H_ASMFUNCS | |
7386 | +#define _H_ASMFUNCS | |
7387 | + | |
7388 | +#include "kernel_vars.h" | |
7389 | +#include "tlbie.h" | |
7390 | + | |
7391 | + | |
7392 | +/* globl variable defined in actions.c */ | |
7393 | +extern int reloc_virt_offs; | |
7394 | +#define reloc_ptr( v ) ((ulong)(v) + (ulong)reloc_virt_offs) | |
7395 | + | |
7396 | + | |
7397 | +/* The code in base.o (all low-level assembly) are copied to a physically | |
7398 | + * continuous memory area. The following inline functions maps function calls | |
7399 | + * to the relocated area. | |
7400 | + */ | |
7401 | + | |
7402 | +static inline void msr_altered( kernel_vars_t *kv ) { | |
7403 | + typedef void ftype( kernel_vars_t * ); | |
7404 | + extern ftype r__msr_altered; | |
7405 | + (*(ftype*)reloc_ptr( r__msr_altered ))( kv ); | |
7406 | +} | |
7407 | + | |
7408 | +static inline void invalidate_splitmode_sr( kernel_vars_t *kv ) { | |
7409 | + typedef void ftype( kernel_vars_t *); | |
7410 | + extern ftype r__invalidate_splitmode_sr; | |
7411 | + (*(ftype*)reloc_ptr( r__invalidate_splitmode_sr ))( kv ); | |
7412 | +} | |
7413 | + | |
7414 | +static inline void initialize_spr_table( kernel_vars_t *kv ) { | |
7415 | + typedef void ftype( kernel_vars_t *); | |
7416 | + extern ftype r__initialize_spr_table; | |
7417 | + (*(ftype*)reloc_ptr( r__initialize_spr_table ))( kv ); | |
7418 | +} | |
7419 | + | |
7420 | + | |
7421 | +/************************************************************************/ | |
7422 | +/* misc inlines */ | |
7423 | +/************************************************************************/ | |
7424 | + | |
7425 | +#define _sync() ({ asm volatile("sync ;\n isync" : : ); }) | |
7426 | + | |
7427 | +static inline ulong _get_sdr1( void ) { | |
7428 | + ulong sdr1; | |
7429 | + asm volatile("mfsdr1 %0" : "=r" (sdr1) : ); | |
7430 | + return sdr1; | |
7431 | +} | |
7432 | +static inline void _set_sdr1( ulong sdr1 ) { | |
7433 | + asm volatile("mtsdr1 %0" : : "r" (sdr1) ); | |
7434 | +} | |
7435 | + | |
7436 | +static inline int cpu_is_601( void ) { | |
7437 | + ulong pvr; | |
7438 | + asm volatile("mfpvr %0" : "=r" (pvr) : ); | |
7439 | + return (pvr>>16)==1; | |
7440 | +} | |
7441 | + | |
7442 | +static inline int cpu_is_603( void ) { | |
7443 | + ulong pvr; | |
7444 | + asm volatile("mfpvr %0" : "=r" (pvr) : ); | |
7445 | + pvr = pvr >> 16; | |
7446 | + return pvr==3 || pvr==6 || pvr==7; /* 603, 603e, 603ev */ | |
7447 | +} | |
7448 | +#endif /* _H_ASMFUNCS */ | |
7449 | --- /dev/null | |
7450 | +++ b/drivers/macintosh/mol/include/atomic.h | |
7451 | @@ -0,0 +1,26 @@ | |
7452 | +/* | |
7453 | + * Creation Date: <2004/01/25 17:00:12 samuel> | |
7454 | + * Time-stamp: <2004/01/29 22:32:30 samuel> | |
7455 | + * | |
7456 | + * <atomic.h> | |
7457 | + * | |
7458 | + * | |
7459 | + * | |
7460 | + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) | |
7461 | + * | |
7462 | + * This program is free software; you can redistribute it and/or | |
7463 | + * modify it under the terms of the GNU General Public License | |
7464 | + * version 2 | |
7465 | + * | |
7466 | + */ | |
7467 | + | |
7468 | +#ifndef _H_ATOMIC | |
7469 | +#define _H_ATOMIC | |
7470 | + | |
7471 | +#define mol_atomic_t atomic_t | |
7472 | +#define atomic_inc_return_mol(x) atomic_inc_return(x) | |
7473 | +#define atomic_inc_mol(x) atomic_inc(x) | |
7474 | +#define atomic_dec_mol(x) atomic_dec(x) | |
7475 | +#define atomic_read_mol(x) atomic_read(x) | |
7476 | + | |
7477 | +#endif /* _H_ATOMIC */ | |
7478 | --- /dev/null | |
7479 | +++ b/drivers/macintosh/mol/include/config.h | |
7480 | @@ -0,0 +1,90 @@ | |
7481 | +/* config.h. Generated from config.h.in by configure. */ | |
7482 | +/* config.h.in. Generated from configure.in by autoheader. */ | |
7483 | + | |
7484 | +/* Define if _syscall macro is borken */ | |
7485 | +#define BROKEN_SYSCALL 1 | |
7486 | + | |
7487 | +/* Defined if ALSA support is available */ | |
7488 | +#define HAVE_ALSA 1 | |
7489 | + | |
7490 | +/* Define if clearenv is available */ | |
7491 | +#define HAVE_CLEARENV 1 | |
7492 | + | |
7493 | +/* Define to 1 if you have the <getopt.h> header file. */ | |
7494 | +#define HAVE_GETOPT_H 1 | |
7495 | + | |
7496 | +/* Define to 1 if you have the <inttypes.h> header file. */ | |
7497 | +#define HAVE_INTTYPES_H 1 | |
7498 | + | |
7499 | +/* Define to 1 if you have the <memory.h> header file. */ | |
7500 | +#define HAVE_MEMORY_H 1 | |
7501 | + | |
7502 | +/* Define to 1 if you have the <obstack.h> header file. */ | |
7503 | +#define HAVE_OBSTACK_H 1 | |
7504 | + | |
7505 | +/* Define if libpng support is to be included */ | |
7506 | +#define HAVE_PNG 1 | |
7507 | + | |
7508 | +/* Define to 1 if you have the <poll.h> header file. */ | |
7509 | +#define HAVE_POLL_H 1 | |
7510 | + | |
7511 | +/* Define to 1 if you have the <stdint.h> header file. */ | |
7512 | +#define HAVE_STDINT_H 1 | |
7513 | + | |
7514 | +/* Define to 1 if you have the <stdlib.h> header file. */ | |
7515 | +#define HAVE_STDLIB_H 1 | |
7516 | + | |
7517 | +/* Define to 1 if you have the <strings.h> header file. */ | |
7518 | +#define HAVE_STRINGS_H 1 | |
7519 | + | |
7520 | +/* Define to 1 if you have the <string.h> header file. */ | |
7521 | +#define HAVE_STRING_H 1 | |
7522 | + | |
7523 | +/* Define to 1 if you have the <sys/stat.h> header file. */ | |
7524 | +#define HAVE_SYS_STAT_H 1 | |
7525 | + | |
7526 | +/* Define to 1 if you have the <sys/types.h> header file. */ | |
7527 | +#define HAVE_SYS_TYPES_H 1 | |
7528 | + | |
7529 | +/* Define to 1 if you have the <unistd.h> header file. */ | |
7530 | +#define HAVE_UNISTD_H 1 | |
7531 | + | |
7532 | +/* Define if X11 is available */ | |
7533 | +#define HAVE_X11 1 | |
7534 | + | |
7535 | +/* Define if XDGA support is to be included */ | |
7536 | +#define HAVE_XDGA 1 | |
7537 | + | |
7538 | +/* Defined for the MOL user binary */ | |
7539 | +#define MOL_PROPER 1 | |
7540 | + | |
7541 | +/* Define if off_t is known to be 64-bit */ | |
7542 | +#define OFF_T_IS_64 1 | |
7543 | + | |
7544 | +/* Define to the address where bug reports for this package should be sent. */ | |
7545 | +#define PACKAGE_BUGREPORT "" | |
7546 | + | |
7547 | +/* Define to the full name of this package. */ | |
7548 | +#define PACKAGE_NAME "" | |
7549 | + | |
7550 | +/* Define to the full name and version of this package. */ | |
7551 | +#define PACKAGE_STRING "" | |
7552 | + | |
7553 | +/* Define to the one symbol short name of this package. */ | |
7554 | +#define PACKAGE_TARNAME "" | |
7555 | + | |
7556 | +/* Define to the version of this package. */ | |
7557 | +#define PACKAGE_VERSION "" | |
7558 | + | |
7559 | +/* Define to 1 if you have the ANSI C header files. */ | |
7560 | +#define STDC_HEADERS 1 | |
7561 | + | |
7562 | +/* Define if uc_context has gregs field */ | |
7563 | +/* #undef UCCONTEXT_HAS_GREGS */ | |
7564 | + | |
7565 | +/* Define to 1 if the X Window System is missing or not being used. */ | |
7566 | +/* #undef X_DISPLAY_MISSING */ | |
7567 | + | |
7568 | +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a | |
7569 | + `char[]'. */ | |
7570 | +#define YYTEXT_POINTER 1 | |
7571 | --- /dev/null | |
7572 | +++ b/drivers/macintosh/mol/include/constants.h | |
7573 | @@ -0,0 +1,36 @@ | |
7574 | +/* | |
7575 | + * Creation Date: <2001/02/11 18:19:42 samuel> | |
7576 | + * Time-stamp: <2003/07/27 18:58:35 samuel> | |
7577 | + * | |
7578 | + * <constants.h> | |
7579 | + * | |
7580 | + * Constants used both in the kernel module and in the emulator | |
7581 | + * | |
7582 | + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) | |
7583 | + * | |
7584 | + * This program is free software; you can redistribute it and/or | |
7585 | + * modify it under the terms of the GNU General Public License | |
7586 | + * as published by the Free Software Foundation | |
7587 | + * | |
7588 | + */ | |
7589 | + | |
7590 | +#ifndef _H_CONSTANTS | |
7591 | +#define _H_CONSTANTS | |
7592 | + | |
7593 | +/* flags for _breakpoint_flags() */ | |
7594 | +#define BREAK_RFI 1 /* break at next rfi */ | |
7595 | +#define BREAK_SINGLE_STEP 2 /* singlestep */ | |
7596 | +#define BREAK_EA_PAGE 4 /* break when mdbg_break_ea is mapped */ | |
7597 | +#define BREAK_USER 8 /* break when MSR_PR is set */ | |
7598 | +#define BREAK_SINGLE_STEP_CONT 16 /* single step (but don't continue running) */ | |
7599 | + | |
7600 | +/* action for _tune_spr() */ | |
7601 | +#define kTuneSPR_Illegal 1 /* SPR is illegal */ | |
7602 | +#define kTuneSPR_Privileged 2 /* SPR is privileged */ | |
7603 | +#define kTuneSPR_Unprivileged 3 /* SPR is unprivileged */ | |
7604 | +#define kTuneSPR_ReadWrite 4 /* SPR is read-write */ | |
7605 | +#define kTuneSPR_ReadOnly 5 /* SPR is read-only */ | |
7606 | + | |
7607 | +#endif /* _H_CONSTANTS */ | |
7608 | + | |
7609 | + | |
7610 | --- /dev/null | |
7611 | +++ b/drivers/macintosh/mol/include/context.h | |
7612 | @@ -0,0 +1,62 @@ | |
7613 | +/* | |
7614 | + * Creation Date: <2004/01/25 17:48:51 samuel> | |
7615 | + * Time-stamp: <2004/01/25 22:12:13 samuel> | |
7616 | + * | |
7617 | + * <context.h> | |
7618 | + * | |
7619 | + * | |
7620 | + * | |
7621 | + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) | |
7622 | + * | |
7623 | + * This program is free software; you can redistribute it and/or | |
7624 | + * modify it under the terms of the GNU General Public License | |
7625 | + * version 2 | |
7626 | + * | |
7627 | + */ | |
7628 | + | |
7629 | +#ifndef _H_CONTEXT | |
7630 | +#define _H_CONTEXT | |
7631 | + | |
7632 | +#define CTX_MASK 0xfffff /* VSID_MASK >> 4 */ | |
7633 | + | |
7634 | +/* | |
7635 | + * Three types of contexts are used: | |
7636 | + * | |
7637 | + * VSIDs (24 bit, loaded into the CPU register) | |
7638 | + * mol_contexts (number between FIRST_ and LAST_MOL_CONTEXT) | |
7639 | + * arch_contexts (context number used by the kernel) | |
7640 | + * | |
7641 | + * The relation between them is | |
7642 | + * | |
7643 | + * mol_context = (os_context << 4) + segment# | |
7644 | + * VSID_context = MUNGE_CONTEXT(mol_context>>4) + ESID_ADD * (mol_context & 0xf) | |
7645 | + */ | |
7646 | + | |
7647 | +/* | |
7648 | + * The new MM implementation (about 2.4.14 (?)) uses the following algorithm | |
7649 | + * | |
7650 | + * VSID = (((context * 897) << 4) + ((va>>28) * 0x111)) & 0xffffff | |
7651 | + * | |
7652 | + * Only context 0..32767 are used. We can use context 32768..0xfffff. | |
7653 | + * The old MM implementation used | |
7654 | + * | |
7655 | + * VSID = (((context * 897) << 4) + (va>>28)) & 0xffffff | |
7656 | + */ | |
7657 | + | |
7658 | +#define MUNGE_ADD_NEXT 897 | |
7659 | +#define MUNGE_MUL_INVERSE 2899073 /* Multiplicative inverse of 897 (modulo VSID_MASK+1) */ | |
7660 | +#define MUNGE_ESID_ADD 0x111 | |
7661 | +#define MUNGE_CONTEXT(c) (((c) * (MUNGE_ADD_NEXT * 16)) & (CTX_MASK <<4)) | |
7662 | + | |
7663 | +/* mol_contexts == linux_context * 16 + esid */ | |
7664 | +#define PER_SESSION_CONTEXTS 0x10000 /* more than we will need (10^6) */ | |
7665 | +#define FIRST_MOL_CONTEXT(sess) ((CTX_MASK - PER_SESSION_CONTEXTS*((sess)+1)) << 4) | |
7666 | +#define LAST_MOL_CONTEXT(sess) (((CTX_MASK - PER_SESSION_CONTEXTS*(sess)) << 4) | 0xf) | |
7667 | + | |
7668 | + | |
7669 | +#if FIRST_MOL_CONTEXT(MAX_NUM_SESSIONS-1) < (32768 << 4) | |
7670 | +#error "Too many MOL contexts..." | |
7671 | +#endif | |
7672 | + | |
7673 | + | |
7674 | +#endif /* _H_CONTEXT */ | |
7675 | --- /dev/null | |
7676 | +++ b/drivers/macintosh/mol/include/dbg.h | |
7677 | @@ -0,0 +1,31 @@ | |
7678 | +/* | |
7679 | + * Creation Date: <2004/04/10 22:14:43 samuel> | |
7680 | + * Time-stamp: <2004/04/10 22:26:24 samuel> | |
7681 | + * | |
7682 | + * <dbg.h> | |
7683 | + * | |
7684 | + * | |
7685 | + * | |
7686 | + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) | |
7687 | + * | |
7688 | + * This program is free software; you can redistribute it and/or | |
7689 | + * modify it under the terms of the GNU General Public License | |
7690 | + * version 2 | |
7691 | + */ | |
7692 | + | |
7693 | +#ifndef _H_DBG | |
7694 | +#define _H_DBG | |
7695 | + | |
7696 | +#ifdef CONFIG_MOL_HOSTED | |
7697 | + | |
7698 | +#ifdef printk | |
7699 | +#undef printk | |
7700 | +#endif | |
7701 | + | |
7702 | +#define printk printm | |
7703 | +extern int printm( const char *fmt, ... ); | |
7704 | +extern void debugger( int n ); | |
7705 | + | |
7706 | +#endif /* CONFIG_MOL_HOSTED */ | |
7707 | + | |
7708 | +#endif /* _H_DBG */ | |
7709 | --- /dev/null | |
7710 | +++ b/drivers/macintosh/mol/include/debugger.h | |
7711 | @@ -0,0 +1,96 @@ | |
7712 | +/* | |
7713 | + * Creation Date: <1999/02/22 22:46:22 samuel> | |
7714 | + * Time-stamp: <2003/07/27 14:42:05 samuel> | |
7715 | + * | |
7716 | + * <debugger.h> | |
7717 | + * | |
7718 | + * World interface of the debugger | |
7719 | + * | |
7720 | + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
7721 | + * | |
7722 | + * This program is free software; you can redistribute it and/or | |
7723 | + * modify it under the terms of the GNU General Public License | |
7724 | + * as published by the Free Software Foundation | |
7725 | + * | |
7726 | + */ | |
7727 | + | |
7728 | +#ifndef _H_DEBUGGER | |
7729 | +#define _H_DEBUGGER | |
7730 | + | |
7731 | +#ifdef CONFIG_DEBUGGER | |
7732 | +extern void debugger_init( void ); | |
7733 | +extern void debugger_cleanup( void ); | |
7734 | +extern int debugger_enabled( void ); | |
7735 | +extern int debugger_attached( void ); | |
7736 | +#else | |
7737 | +static inline int debugger_enabled( void ) { return 0; } | |
7738 | +static inline int debugger_attached( void ) { return 0; } | |
7739 | +static inline void debugger_init( void ) {} | |
7740 | +static inline void debugger_cleanup( void ) {} | |
7741 | +#endif | |
7742 | + | |
7743 | +/*******************************************/ | |
7744 | +/* montior.c / nub.c */ | |
7745 | +/*******************************************/ | |
7746 | + | |
7747 | +extern void refresh_debugger_window( void ); | |
7748 | +extern void refresh_debugger( void ); | |
7749 | +extern void redraw_inst_win( void ); | |
7750 | +extern int debugger_in_68k_mode( void ); | |
7751 | +extern void debugger_nub_poll( void ); | |
7752 | + | |
7753 | +/* debug actions */ | |
7754 | +enum{ | |
7755 | + kDbgNOP=0, kDbgGo, kDbgGoRFI, kDbgStep, kDbgExit, kDbgStop, kDbgGoUser | |
7756 | +}; | |
7757 | + | |
7758 | + | |
7759 | +/*******************************************/ | |
7760 | +/* cmdline.c / nub.c */ | |
7761 | +/*******************************************/ | |
7762 | + | |
7763 | +/* put functions used exclusively in debugger mode in the dbg section */ | |
7764 | +#ifdef __linux__ | |
7765 | +#ifdef CONFIG_DEBUGGER | |
7766 | +#define __dbg __attribute__ ((__section__ (".moldbg"))) | |
7767 | +#define __dcmd __dbg | |
7768 | +#else | |
7769 | +#define __dbg __attribute__ ((__section__ (".moldbg"))) | |
7770 | +#define __dcmd inline __attribute__ ((__section__ (".moldbg"))) | |
7771 | +#endif | |
7772 | +#else | |
7773 | +#define __dbg | |
7774 | +#define __dcmd inline | |
7775 | +#endif | |
7776 | + | |
7777 | +typedef struct { | |
7778 | + const char *name; | |
7779 | + int (*func)( int argc, char **argv ); | |
7780 | + const char *help; | |
7781 | +} dbg_cmd_t; | |
7782 | + | |
7783 | +typedef int (*dbg_cmd_fp)( int argc, char **argv ); | |
7784 | + | |
7785 | +#ifdef CONFIG_DEBUGGER | |
7786 | +extern void add_cmd( const char *cmdname, const char *help, | |
7787 | + int dummy, dbg_cmd_fp func ); | |
7788 | +extern void add_dbg_cmds( dbg_cmd_t *table, int tablesize ); | |
7789 | +#else | |
7790 | +#define add_cmd( a,b,c,d ) do {} while(0) | |
7791 | +static inline void add_dbg_cmds( dbg_cmd_t *table, int tablesize ) {} | |
7792 | +#endif | |
7793 | + | |
7794 | +/* for debugging */ | |
7795 | +#define HARD_BREAKPOINT \ | |
7796 | + ({ printm("Hardcoded breakpoint in '"__FILE__"'\n"); stop_emulation(); }) | |
7797 | + | |
7798 | + | |
7799 | +/*******************************************/ | |
7800 | +/* mmu_cmds.c */ | |
7801 | +/*******************************************/ | |
7802 | + | |
7803 | +extern int __dbg get_inst_context( void ); | |
7804 | +extern int __dbg get_data_context( void ); | |
7805 | +extern int __dbg ea_to_lvptr( ulong ea, int context, char **lvptr, int data_access ); | |
7806 | + | |
7807 | +#endif /* _H_DEBUGGER */ | |
7808 | --- /dev/null | |
7809 | +++ b/drivers/macintosh/mol/include/emu.h | |
7810 | @@ -0,0 +1,29 @@ | |
7811 | +/* | |
7812 | + * Creation Date: <2003/01/26 00:45:55 samuel> | |
7813 | + * Time-stamp: <2003/01/27 01:26:25 samuel> | |
7814 | + * | |
7815 | + * <emu.h> | |
7816 | + * | |
7817 | + * Emulation of some assembly functions | |
7818 | + * | |
7819 | + * Copyright (C) 1998, 2000, 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) | |
7820 | + * | |
7821 | + * This program is free software; you can redistribute it and/or | |
7822 | + * modify it under the terms of the GNU General Public License | |
7823 | + * as published by the Free Software Foundation | |
7824 | + * | |
7825 | + */ | |
7826 | + | |
7827 | +#ifndef _H_EMU | |
7828 | +#define _H_EMU | |
7829 | + | |
7830 | +#include "mmu.h" | |
7831 | + | |
7832 | +extern int do_mtsdr1( kernel_vars_t *kv, ulong value ); | |
7833 | +extern int do_mtbat( kernel_vars_t *kv, int sprnum, ulong value, int force ); | |
7834 | + | |
7835 | +extern int alloc_emuaccel_slot( kernel_vars_t *kv, int inst_flags, int param, int inst_addr ); | |
7836 | +extern int mapin_emuaccel_page( kernel_vars_t *kv, int mphys ); | |
7837 | + | |
7838 | + | |
7839 | +#endif /* _H_EMU */ | |
7840 | --- /dev/null | |
7841 | +++ b/drivers/macintosh/mol/include/emuaccel_sh.h | |
7842 | @@ -0,0 +1,41 @@ | |
7843 | +/* | |
7844 | + * Creation Date: <2003/01/25 14:57:36 samuel> | |
7845 | + * Time-stamp: <2003/01/27 23:11:29 samuel> | |
7846 | + * | |
7847 | + * <emuaccel.h> | |
7848 | + * | |
7849 | + * Acceleration of the emulation of certain privileged instructions | |
7850 | + * | |
7851 | + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) | |
7852 | + * | |
7853 | + * This program is free software; you can redistribute it and/or | |
7854 | + * modify it under the terms of the GNU General Public License | |
7855 | + * as published by the Free Software Foundation | |
7856 | + * | |
7857 | + */ | |
7858 | + | |
7859 | +#ifndef _H_EMUACCEL | |
7860 | +#define _H_EMUACCEL | |
7861 | + | |
7862 | +/* OSI_AllocInstAccelSlot( EMULATE_xxx + source_reg, NIP ) */ | |
7863 | + | |
7864 | +#define EMUACCEL_MAPIN_PAGE 0 | |
7865 | +#define EMUACCEL_MTSRR0 (1 << 5) | |
7866 | +#define EMUACCEL_MTSRR1 (2 << 5) | |
7867 | +#define EMUACCEL_MTSPRG0 (3 << 5) | |
7868 | +#define EMUACCEL_MTSPRG1 (4 << 5) | |
7869 | +#define EMUACCEL_MTSPRG2 (5 << 5) | |
7870 | +#define EMUACCEL_MTSPRG3 (6 << 5) | |
7871 | +#define EMUACCEL_MTMSR (7 << 5) | |
7872 | +#define EMUACCEL_RFI (8 << 5) | |
7873 | +#define EMUACCEL_UPDATE_DEC (9 << 5) /* update xDEC */ | |
7874 | +#define EMUACCEL_MTSR ((10 << 5) | EMUACCEL_HAS_PARAM) | |
7875 | +#define EMUACCEL_NOP (11 << 5) | |
7876 | +#define EMUACCEL_MTHID0 (12 << 5) | |
7877 | + | |
7878 | +#define EMUACCEL_HAS_PARAM (1 << 10) | |
7879 | +#define EMUACCEL_INST_MASK 0xffe0 | |
7880 | +#define EMUACCEL_DESTREG_MASK 0x1f | |
7881 | + | |
7882 | + | |
7883 | +#endif /* _H_EMUACCEL */ | |
7884 | --- /dev/null | |
7885 | +++ b/drivers/macintosh/mol/include/extralib.h | |
7886 | @@ -0,0 +1,70 @@ | |
7887 | +/* | |
7888 | + * Creation Date: <1997/07/02 19:52:18 samuel> | |
7889 | + * Time-stamp: <2004/04/03 18:29:26 samuel> | |
7890 | + * | |
7891 | + * <extralib.h> | |
7892 | + * | |
7893 | + * | |
7894 | + * | |
7895 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
7896 | + * | |
7897 | + * This program is free software; you can redistribute it and/or | |
7898 | + * modify it under the terms of the GNU General Public License | |
7899 | + * as published by the Free Software Foundation | |
7900 | + * | |
7901 | + */ | |
7902 | + | |
7903 | +#ifndef _H_EXTRALIB | |
7904 | +#define _H_EXTRALIB | |
7905 | + | |
7906 | +#define CLEAR( x ) memset( &x, 0, sizeof(x)) | |
7907 | + | |
7908 | +/* in extralib.h */ | |
7909 | +extern int ilog2( int val ); | |
7910 | + | |
7911 | +extern char *num_to_string( ulong num ); | |
7912 | +extern int is_number_str( char *str ); | |
7913 | +extern ulong string_to_ulong( char * ); | |
7914 | +extern ulong hexbin( int num ); | |
7915 | + | |
7916 | +extern char *strncpy0( char *dest, const char *str, size_t n ); | |
7917 | +extern char *strncat0( char *dest, const char *str, size_t n ); | |
7918 | +extern char *strncat3( char *dest, const char *s1, const char *s2, size_t n ); | |
7919 | +extern char *strnpad( char *dest, const char *s1, size_t n ); | |
7920 | + | |
7921 | +struct iovec; | |
7922 | +extern int memcpy_tovec( const struct iovec *vec, size_t nvec, const char *src, unsigned int len ); | |
7923 | +extern int memcpy_fromvec( char *dst, const struct iovec *vec, size_t nvec, unsigned int len ); | |
7924 | +extern int iovec_getbyte( int offs, const struct iovec *vec, size_t nvec ); | |
7925 | +extern int iovec_skip( int skip, struct iovec *vec, size_t nvec ); | |
7926 | + | |
7927 | +extern void open_logfile( const char *filename ); | |
7928 | +extern void close_logfile( void ); | |
7929 | + | |
7930 | +#define __printf_format __attribute__ ((format (printf, 1, 2))) | |
7931 | +extern int printm( const char *fmt,...) __printf_format; | |
7932 | +extern int aprint( const char *fmt,... ) __printf_format; | |
7933 | +extern void perrorm(const char *fmt,... ) __printf_format; | |
7934 | +extern void fatal(const char *fmt,... ) __printf_format __attribute__((noreturn)); | |
7935 | +#define fatal_err(fmt, args...) \ | |
7936 | + do { printm("Fatal error: "); perrorm(fmt, ## args ); exit(1); } while(0) | |
7937 | +extern void fail_nil( void *p ); | |
7938 | +extern void set_print_hook( int (*hook)(char *buf) ); | |
7939 | +extern void set_print_guard( void (*hook)(void) ); | |
7940 | + | |
7941 | +extern int script_exec( char *name, char *arg1, char *arg2 ); | |
7942 | + | |
7943 | +/* in unicode.c */ | |
7944 | +extern int asc2uni( unsigned char *ustr, const char *astr, int maxlen ); | |
7945 | +extern int uni2asc( char *astr, const unsigned char *ustr, int ustrlen, int maxlen ); | |
7946 | + | |
7947 | +/* in backtrace.c */ | |
7948 | +extern void print_btrace_sym( ulong addr, const char *sym_filename ); | |
7949 | + | |
7950 | +/* color output support */ | |
7951 | +#define C_GREEN "\33[1;32m" | |
7952 | +#define C_YELLOW "\33[1;33m" | |
7953 | +#define C_NORMAL "\33[0;39m" | |
7954 | +#define C_RED "\33[1;31m" | |
7955 | + | |
7956 | +#endif /* _H_EXTRALIB */ | |
7957 | --- /dev/null | |
7958 | +++ b/drivers/macintosh/mol/include/hash.h | |
7959 | @@ -0,0 +1,36 @@ | |
7960 | +/* | |
7961 | + * Creation Date: <2004/02/14 11:45:23 samuel> | |
7962 | + * Time-stamp: <2004/02/21 21:24:46 samuel> | |
7963 | + * | |
7964 | + * <hash.h> | |
7965 | + * | |
7966 | + * | |
7967 | + * | |
7968 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
7969 | + * | |
7970 | + * This program is free software; you can redistribute it and/or | |
7971 | + * modify it under the terms of the GNU General Public License | |
7972 | + * as published by the Free Software Foundation | |
7973 | + * | |
7974 | + */ | |
7975 | + | |
7976 | +#ifndef _H_HASH | |
7977 | +#define _H_HASH | |
7978 | + | |
7979 | +typedef struct { | |
7980 | + ulong sdr1; /* sdr1 used by MOL */ | |
7981 | + | |
7982 | + ulong pteg_mask; /* pteg offset mask (e.g. 0xffc0) */ | |
7983 | + ulong pte_mask; /* pte offset mask (e.g. 0xfff8) */ | |
7984 | + | |
7985 | + ulong *base; /* kernel mapping of hash */ | |
7986 | + ulong physbase; /* physical address of hash */ | |
7987 | +} hash_info_t; | |
7988 | + | |
7989 | +extern hash_info_t ptehash; | |
7990 | + | |
7991 | +extern int init_hash( void ); | |
7992 | +extern void cleanup_hash( void ); | |
7993 | + | |
7994 | + | |
7995 | +#endif /* _H_HASH */ | |
7996 | --- /dev/null | |
7997 | +++ b/drivers/macintosh/mol/include/kernel_vars.h | |
7998 | @@ -0,0 +1,225 @@ | |
7999 | +/* | |
8000 | + * Creation Date: <97/07/14 15:53:06 samuel> | |
8001 | + * Time-stamp: <2004/02/21 21:37:37 samuel> | |
8002 | + * | |
8003 | + * <kernel_vars.h> | |
8004 | + * | |
8005 | + * Variables used by the kernel | |
8006 | + * | |
8007 | + * Copyright (C) 1997-2004 Samuel Rydh (samuel@ibrium.se) | |
8008 | + * | |
8009 | + * This program is free software; you can redistribute it and/or | |
8010 | + * modify it under the terms of the GNU General Public License | |
8011 | + * as published by the Free Software Foundation | |
8012 | + * | |
8013 | + */ | |
8014 | + | |
8015 | +#ifndef H_KERNEL_VARS | |
8016 | +#define H_KERNEL_VARS | |
8017 | + | |
8018 | +#define MAX_NUM_SESSIONS 8 | |
8019 | + | |
8020 | +#include "mac_registers.h" | |
8021 | + | |
8022 | +#ifdef PERFORMANCE_INFO | |
8023 | +#define NUM_ASM_BUMP_CNTRS 64 | |
8024 | +#define NUM_ASM_TICK_CNTRS 6 | |
8025 | +#endif | |
8026 | + | |
8027 | +#ifndef __ASSEMBLY__ | |
8028 | +#include "mmu_mappings.h" | |
8029 | +#include "skiplist.h" | |
8030 | + | |
8031 | +#ifndef DUMPVARS | |
8032 | +#include "alloc.h" | |
8033 | +#include "locks.h" | |
8034 | +#include "atomic.h" | |
8035 | +#else | |
8036 | +typedef int mol_mutex_t; | |
8037 | +typedef int mol_atomic_t; | |
8038 | +#endif | |
8039 | + | |
8040 | +typedef struct { | |
8041 | + ulong word[2]; /* upper, lower */ | |
8042 | +} ppc_bat_t; | |
8043 | + | |
8044 | +typedef struct mac_bat { | |
8045 | + int valid; /* record in use */ | |
8046 | + ulong base; | |
8047 | + ulong mbase; | |
8048 | + ulong size; | |
8049 | + | |
8050 | + ulong wimg:4; /* WIMG-bits */ | |
8051 | + ulong vs:1; /* valid supervisor mode */ | |
8052 | + ulong vp:1; /* valid user mode */ | |
8053 | + ulong ks:1; /* key superuser */ | |
8054 | + ulong ku:1; /* key user */ | |
8055 | + ulong pp:2; /* page protection */ | |
8056 | + | |
8057 | + /* possibly we should track inserted PTEs here... */ | |
8058 | +} mac_bat_t; | |
8059 | + | |
8060 | +typedef struct { | |
8061 | + struct vsid_ent *vsid[16]; /* entries might be NULL */ | |
8062 | + struct vsid_ent *unmapped_vsid[16]; /* entries might be NULL, linux_vsid_sv used */ | |
8063 | + | |
8064 | + ulong emulator_sr[16]; /* segment registers used by the userspace process */ | |
8065 | + | |
8066 | + ulong user_sr[16]; /* segment registers for MSR=user */ | |
8067 | + ulong sv_sr[16]; /* segment registers for MSR=sv */ | |
8068 | + ulong unmapped_sr[16]; /* segment registers for unmapped mode */ | |
8069 | + ulong split_sr[16]; /* segment registers used in split mode */ | |
8070 | + | |
8071 | + ulong cur_sr_base; /* (physical) pointer to user_sr or sv_sr */ | |
8072 | + ulong sr_inst; /* (physical) pointer to us user_sr or sv_sr */ | |
8073 | + ulong sr_data; /* (physical) pointer to us user_sr or sv_sr */ | |
8074 | + | |
8075 | + ulong illegal_sr; /* used for the lazy segment register impl. */ | |
8076 | + | |
8077 | + ppc_bat_t split_dbat0; /* loaded to DBAT0 (used in splitmode) */ | |
8078 | + ppc_bat_t transl_dbat0; /* DBAT0 mapping the framebuffer */ | |
8079 | + | |
8080 | + ulong emulator_context; /* context of emulator (equals VSID >> 4) in Linux */ | |
8081 | + | |
8082 | + ulong userspace_ram_base; /* userspace RAM base */ | |
8083 | + size_t ram_size; | |
8084 | + | |
8085 | + ulong bat_hack_count; /* HACK to speed up MacOS 9.1 */ | |
8086 | + mac_bat_t bats[8]; /* 4 IBAT + 4 DBAT */ | |
8087 | + | |
8088 | +#ifdef EMULATE_603 | |
8089 | + ulong ptes_d_ea_603[64]; /* EA4-EA19 of dPTE */ | |
8090 | + mPTE_t ptes_d_603[64]; /* Data on-chip PTEs (603-emulation) */ | |
8091 | + ulong ptes_i_ea_603[64]; /* EA4-EA19 of iPTE */ | |
8092 | + mPTE_t ptes_i_603[64]; /* Instruction on-chip PTEs (603-emulation) */ | |
8093 | +#endif | |
8094 | + /* emulated PTE hash */ | |
8095 | + ulong hash_mbase; /* mac physical hash base */ | |
8096 | + ulong *hash_base; /* kernel pointer to mac hash */ | |
8097 | + ulong hash_mask; /* hash mask (0x000fffff etc) */ | |
8098 | + | |
8099 | + /* context number allocation */ | |
8100 | + int next_mol_context; /* in the range FIRST .. LAST_MOL_CONTEXT(n) */ | |
8101 | + int first_mol_context; /* first context number this session may use */ | |
8102 | + int last_mol_context; /* last context number this session may use */ | |
8103 | + | |
8104 | + ulong pthash_sr; /* segment register corresponding to */ | |
8105 | + ulong pthash_ea_base; /* pthash_ea_base */ | |
8106 | + void *pthash_inuse_bits; /* bitvector (one bit per PTE) */ | |
8107 | + ulong pthash_inuse_bits_ph; /* physical base address */ | |
8108 | + | |
8109 | + /* various tables */ | |
8110 | + struct io_data *io_data; /* translation info */ | |
8111 | + struct fb_data *fb_data; /* ea -> PTE table */ | |
8112 | + struct tracker_data *tracker_data; /* Keeps track of modified pages */ | |
8113 | + | |
8114 | + /* mtable stuff */ | |
8115 | + skiplist_t vsid_sl; /* skiplist (with vsid_ent_t objects) */ | |
8116 | + struct vsid_info *vsid_info; /* mtable data */ | |
8117 | + | |
8118 | + char *lvptr_reservation; /* lvptr associated with PTE to be inserted */ | |
8119 | + int lvptr_reservation_lost; /* set if reservation is lost (page out) */ | |
8120 | + | |
8121 | +#ifdef __darwin__ | |
8122 | + ulong os_sdr1; /* SDR1 used by the host OS */ | |
8123 | + ulong mol_sdr1; /* SDR1 used by MOL */ | |
8124 | +#endif | |
8125 | +} mmu_vars_t; | |
8126 | + | |
8127 | + | |
8128 | +/* variables which are private to the low level assembly code */ | |
8129 | +typedef struct { | |
8130 | + ulong spr_hooks[NUM_SPRS]; /* hooks */ | |
8131 | + | |
8132 | + ppc_bat_t ibat_save[4]; /* kernel values of the BAT-registers */ | |
8133 | + ppc_bat_t dbat_save[4]; | |
8134 | + | |
8135 | + ulong _msr; /* MSR used in mac-mode (_not_ the emulated msr) */ | |
8136 | + | |
8137 | + /* saved kernel/emulator registers */ | |
8138 | + ulong emulator_nip; | |
8139 | + ulong emulator_msr; | |
8140 | + ulong emulator_sprg2; | |
8141 | + ulong emulator_sprg3; | |
8142 | + ulong emulator_kcall_nip; | |
8143 | + ulong emulator_stack; | |
8144 | + ulong emulator_toc; /* == r2 on certain systems */ | |
8145 | + | |
8146 | + /* DEC and timebase */ | |
8147 | + ulong dec_stamp; /* linux DEC = dec_stamp - tbl */ | |
8148 | + ulong int_stamp; /* next DEC event = int_stamp - tbl */ | |
8149 | + | |
8150 | + /* splitmode */ | |
8151 | + int split_nip_segment; /* segment (top 4) used for inst. fetches */ | |
8152 | + | |
8153 | + /* segment register offset table */ | |
8154 | + ulong msr_sr_table[ 4*8 ]; /* see emulation.S */ | |
8155 | + | |
8156 | + ulong tmp_scratch[4]; /* temporary storage */ | |
8157 | +} base_private_t; | |
8158 | + | |
8159 | + | |
8160 | +#ifdef PERFORMANCE_INFO | |
8161 | +#define MAX_ACC_CNTR_DEPTH 8 | |
8162 | +typedef struct acc_counter { | |
8163 | + ulong stamp; | |
8164 | + ulong subticks; | |
8165 | +} acc_counter_t; | |
8166 | +#endif | |
8167 | + | |
8168 | +typedef struct kernel_vars { | |
8169 | + struct mac_regs mregs; /* must go first */ | |
8170 | + char page_filler[0x1000 - (sizeof(mac_regs_t)&0xfff) ]; | |
8171 | + | |
8172 | + base_private_t _bp; | |
8173 | + char aligner[32 - (sizeof(base_private_t)&0x1f) ]; | |
8174 | + mmu_vars_t mmu; | |
8175 | + char aligner2[16 - (sizeof(mmu_vars_t)&0xf) ]; | |
8176 | + | |
8177 | + ulong emuaccel_mphys; /* mphys address of emuaccel_page */ | |
8178 | + int emuaccel_size; /* size used */ | |
8179 | + ulong emuaccel_page_phys; /* phys address of page */ | |
8180 | + ulong emuaccel_page; /* page used for instruction acceleration */ | |
8181 | + | |
8182 | + int break_flags; | |
8183 | + ulong kvars_tophys_offs; /* physical - virtual address of kvars */ | |
8184 | + struct kernel_vars *kvars_virt; /* me */ | |
8185 | + int session_index; | |
8186 | + | |
8187 | + mol_mutex_t ioctl_sem; /* ioctl lock */ | |
8188 | +#ifdef __darwin__ | |
8189 | + void *kcall_routine; | |
8190 | + int kcall_args[3]; | |
8191 | + char *mregs_virtual; /* mregs address used by client */ | |
8192 | + | |
8193 | +#endif | |
8194 | + | |
8195 | +#ifdef PERFORMANCE_INFO | |
8196 | + ulong asm_bump_cntr[NUM_ASM_BUMP_CNTRS]; | |
8197 | + ulong asm_tick_stamp[NUM_ASM_TICK_CNTRS]; | |
8198 | + int num_acntrs; | |
8199 | + acc_counter_t acntrs[MAX_ACC_CNTR_DEPTH]; | |
8200 | +#endif | |
8201 | + | |
8202 | + void *main_thread; /* pointer to the main thread task_struct */ | |
8203 | + | |
8204 | +} kernel_vars_t; | |
8205 | + | |
8206 | +#define NUM_KVARS_PAGES ((sizeof(kernel_vars_t)+0xfff)/0x1000) | |
8207 | + | |
8208 | +typedef struct { | |
8209 | + kernel_vars_t *kvars[MAX_NUM_SESSIONS]; | |
8210 | + int magic; | |
8211 | + ulong kvars_ph[MAX_NUM_SESSIONS]; | |
8212 | + mol_mutex_t lock; | |
8213 | + mol_atomic_t external_thread_cnt; | |
8214 | +} session_table_t; | |
8215 | + | |
8216 | +#define SESSION_LOCK down_mol( &g_sesstab->lock ) | |
8217 | +#define SESSION_UNLOCK up_mol( &g_sesstab->lock ) | |
8218 | + | |
8219 | +extern session_table_t *g_sesstab; | |
8220 | + | |
8221 | + | |
8222 | +#endif /* __ASSEMBLY__ */ | |
8223 | +#endif | |
8224 | --- /dev/null | |
8225 | +++ b/drivers/macintosh/mol/include/locks.h | |
8226 | @@ -0,0 +1,39 @@ | |
8227 | +/* | |
8228 | + * Creation Date: <2004/01/25 16:31:13 samuel> | |
8229 | + * Time-stamp: <2004/01/29 22:33:29 samuel> | |
8230 | + * | |
8231 | + * <locks.h> | |
8232 | + * | |
8233 | + * | |
8234 | + * | |
8235 | + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) | |
8236 | + * | |
8237 | + * This program is free software; you can redistribute it and/or | |
8238 | + * modify it under the terms of the GNU General Public License | |
8239 | + * version 2 | |
8240 | + * | |
8241 | + */ | |
8242 | + | |
8243 | +#ifndef _H_LOCKS | |
8244 | +#define _H_LOCKS | |
8245 | + | |
8246 | +/* mutex locks */ | |
8247 | + | |
8248 | +typedef struct semaphore mol_mutex_t; | |
8249 | +#define init_MUTEX_mol(mu) init_MUTEX( mu ) | |
8250 | +#define free_MUTEX_mol(mu) do {} while(0) | |
8251 | +#define down_mol(x) down(x) | |
8252 | +#define up_mol(x) up(x) | |
8253 | + | |
8254 | + | |
8255 | +/* spinlocks */ | |
8256 | + | |
8257 | +typedef spinlock_t mol_spinlock_t; | |
8258 | +#define spin_lock_mol(x) spin_lock(x) | |
8259 | +#define spin_unlock_mol(x) spin_unlock(x) | |
8260 | +//#define spin_lock_irqsave_mol(x, flags) spin_lock_irqsave(x, flags) | |
8261 | +//#define spin_unlock_irqrestore_mol(x,flags) spin_unlock_irqrestore(x, flags) | |
8262 | +#define spin_lock_init_mol(x) spin_lock_init(x) | |
8263 | + | |
8264 | + | |
8265 | +#endif /* _H_LOCKS */ | |
8266 | --- /dev/null | |
8267 | +++ b/drivers/macintosh/mol/include/mac_registers.h | |
8268 | @@ -0,0 +1,168 @@ | |
8269 | +/* | |
8270 | + * Creation Date: <97/06/24 22:25:04 samuel> | |
8271 | + * Time-stamp: <2004/02/08 20:32:59 samuel> | |
8272 | + * | |
8273 | + * <mac_registers.h> | |
8274 | + * | |
8275 | + * | |
8276 | + * | |
8277 | + * Copyright (C) 1997-2004 Samuel Rydh (samuel@ibrium.se) | |
8278 | + * | |
8279 | + * This program is free software; you can redistribute it and/or | |
8280 | + * modify it under the terms of the GNU General Public License | |
8281 | + * as published by the Free Software Foundation | |
8282 | + * | |
8283 | + */ | |
8284 | + | |
8285 | +#ifndef _MAC_REGISTERS_H | |
8286 | +#define _MAC_REGISTERS_H | |
8287 | + | |
8288 | +#ifndef __ASSEMBLY__ | |
8289 | + | |
8290 | +#include "mmutypes.h" | |
8291 | +#include "processor.h" | |
8292 | + | |
8293 | +typedef struct { | |
8294 | + unsigned long h,l; | |
8295 | +} fpu_register; | |
8296 | + | |
8297 | +#define NUM_DEBUG_REGS 10 | |
8298 | + | |
8299 | +typedef struct { | |
8300 | + unsigned long words[4]; | |
8301 | +} altivec_reg_t; | |
8302 | + | |
8303 | +#define NR_HOST_IRQS 64 | |
8304 | + | |
8305 | +typedef struct irq_bitfield { | |
8306 | + unsigned long irqs[(NR_HOST_IRQS - 1) / sizeof(unsigned long) + 1]; | |
8307 | +} irq_bitfield_t; | |
8308 | + | |
8309 | +typedef struct mac_regs { /* this struct is page aligned */ | |
8310 | + /* the sprs should be page aligned (occupies one page) */ | |
8311 | + unsigned long spr[NUM_SPRS]; /* special purpose registers */ | |
8312 | + | |
8313 | + unsigned long segr[16]; /* segment registers */ | |
8314 | + altivec_reg_t vec[32]; /* AltiVec vector registers */ | |
8315 | + fpu_register fpr[32]; /* FPU registers (64 bits) */ | |
8316 | + | |
8317 | + unsigned long vscr_pad[3], vscr; /* AltiVec status control register */ | |
8318 | + unsigned long pad_fpscr, fpscr; /* fp. status and control register */ | |
8319 | + unsigned long pad_ef, emulator_fpscr; /* emulator fp. status and control reg */ | |
8320 | + | |
8321 | + /* Keep this cache-block aligned (typcically 8 words) */ | |
8322 | + unsigned long cr; /* Condition register */ | |
8323 | + unsigned long link; /* Link register */ | |
8324 | + unsigned long flag_bits; /* Various flags (fbXXXXX) */ | |
8325 | + unsigned long inst_opcode; /* opcode of instruction */ | |
8326 | + unsigned long gpr[32]; /* gprs */ | |
8327 | + | |
8328 | + unsigned long ctr; /* Count register */ | |
8329 | + unsigned long xer; /* Integer exception register */ | |
8330 | + unsigned long nip; /* Instruction pointer */ | |
8331 | + unsigned long msr; /* Machine state register (virtual) */ | |
8332 | + | |
8333 | + /* interrupts and timers */ | |
8334 | + int interrupt; /* set if the kernel should return to the emulator */ | |
8335 | + int in_virtual_mode; /* set while MOL is in virtualization mode */ | |
8336 | + ulong dec_stamp; /* xDEC = dec_stamp - tbl */ | |
8337 | + ulong timer_stamp; /* TIMER = dec_stamp - tbl */ | |
8338 | + int obsolete_irq; /* unused */ | |
8339 | + | |
8340 | + /* RVEC parameters */ | |
8341 | +#ifdef __darwin__ | |
8342 | + ulong rvec_vector; /* Used in kernel C-mode */ | |
8343 | +#endif | |
8344 | + ulong rvec_param[3]; /* Used in kernel C-mode */ | |
8345 | + | |
8346 | + /* misc */ | |
8347 | + int fpu_state; /* FPU_STATE_xxx (see below) */ | |
8348 | + int processor; /* processor to emulate, 1=601, 4=604 */ | |
8349 | + int altivec_used; /* useful for altivec detection */ | |
8350 | + int no_altivec; /* Don't use altivec (e.g. no kernel support) */ | |
8351 | + | |
8352 | + int use_bat_hack; /* Newworld BAT optimization (HACK) */ | |
8353 | + | |
8354 | +#ifdef EMULATE_603 | |
8355 | + unsigned long gprsave_603[4]; /* GPR0-3 (for 603 DMISS/IMISS) */ | |
8356 | +#endif | |
8357 | + /* moldeb support */ | |
8358 | + unsigned long mdbg_ea_break; /* used together with BREAK_EA_PAGE */ | |
8359 | + | |
8360 | + /* DEBUG */ | |
8361 | + unsigned long debug[NUM_DEBUG_REGS]; | |
8362 | + unsigned long debug_scr1; /* dbg scratch register */ | |
8363 | + unsigned long debug_scr2; /* dbg scratch register */ | |
8364 | + unsigned long debug_trace; /* dbg trace register */ | |
8365 | + unsigned long dbg_trace_space[256]; | |
8366 | + unsigned long dbg_last_rvec; /* useful for tracing segfaults etc. */ | |
8367 | + unsigned long dbg_last_osi; | |
8368 | + | |
8369 | + unsigned long kernel_dbg_stop; /* stop emulation flag */ | |
8370 | + | |
8371 | + /* host irq mapping data */ | |
8372 | + irq_bitfield_t mapped_irqs; /* keeps track of used host irqs */ | |
8373 | + irq_bitfield_t active_irqs; /* irqs that are up are marked here */ | |
8374 | + int hostirq_update; /* whether userspace should update the pic */ | |
8375 | + /* should be mol_atomic_t but causes trouble... */ | |
8376 | + int hostirq_active_cnt; /* number of active host irq lines */ | |
8377 | + | |
8378 | +} mac_regs_t; | |
8379 | + | |
8380 | +#define NUM_MREGS_PAGES ((sizeof(mac_regs_t)+0xfff)/0x1000) | |
8381 | + | |
8382 | +#define BIT(n) (1U<<(31-(n))) /* bit 0 is MSB */ | |
8383 | + | |
8384 | +#ifndef __KERNEL__ | |
8385 | +extern mac_regs_t *mregs; | |
8386 | +#endif | |
8387 | +#endif /* __ASSEMBLY__ */ | |
8388 | + | |
8389 | +/* mregs->fpu_state (only valid when FBIT_FPUInUse is false) */ | |
8390 | +#define FPU_STATE_HALF_SAVED 0 /* fpscr & fr0-fr13 saved */ | |
8391 | +#define FPU_STATE_DIRTY 1 /* fpscr & fr13 saved */ | |
8392 | +#define FPU_STATE_SAVED 3 /* everything is saved to mregs */ | |
8393 | + | |
8394 | +/* flag_bits (loaded into cr4-7). TOUCH THESE *ONLY* FROM THE MAIN THREAD! */ | |
8395 | +#ifdef __KERNEL__ | |
8396 | +/* these must be in cr7 (set through a mtcrf) */ | |
8397 | +#define MMU_CR_FIELD 0x01 | |
8398 | +#define FBIT_InSplitmode 31 /* (S) */ | |
8399 | +#define FBIT_PrepareSplitmode 30 /* (S) */ | |
8400 | +#define FBIT_LoadSegreg 29 /* (S) */ | |
8401 | + | |
8402 | +/* must be in cr6; (set through a mtcrf) */ | |
8403 | +#define TRACE_CR_FIELD 0x02 | |
8404 | +#define FBIT_DbgTrace 27 /* (S) equals BREAK_SINGLE_STEP */ | |
8405 | +#define FBIT_Trace 26 /* (S) */ | |
8406 | + | |
8407 | +#define FBIT_MolDecLoaded 23 /* (S) */ | |
8408 | +#define FBIT_DecSeenZero 22 /* (S) */ | |
8409 | +#define FBIT_DecINT 21 /* (S) */ | |
8410 | +#define FBIT_FPUInUse 20 /* (S) Set when fpu is mac-owned (only valid in the kernel) */ | |
8411 | + | |
8412 | +#endif | |
8413 | + | |
8414 | +#define FBIT_MsrModified 19 /* (U) */ | |
8415 | +#define FBIT_RecalcDecInt 18 /* (U) */ | |
8416 | +#define FBIT_IRQPending 17 /* (U) IRQ is pending */ | |
8417 | +#ifdef EMULATE_603 | |
8418 | +#define FBIT_603_AltGPR 16 /* (U) Alternate GPR0-3 in use */ | |
8419 | +#endif | |
8420 | + | |
8421 | + | |
8422 | +#ifdef __KERNEL__ | |
8423 | +#define fb_DbgTrace BIT( FBIT_DbgTrace ) | |
8424 | +#define fb_Trace BIT( FBIT_Trace ) | |
8425 | +#define fb_PrepareSplitmode BIT( FBIT_PrepareSplitmode ) | |
8426 | +#define fb_InSplitmode BIT( FBIT_InSplitmode ) | |
8427 | +#define fb_LoadSegreg BIT( FBIT_LoadSegreg ) | |
8428 | +#endif | |
8429 | +#define fb_MsrModified BIT( FBIT_MsrModified ) | |
8430 | +#define fb_RecalcDecInt BIT( FBIT_RecalcDecInt ) | |
8431 | +#define fb_IRQPending BIT( FBIT_IRQPending ) | |
8432 | +#ifdef EMULATE_603 | |
8433 | +#define fb_603_AltGPR BIT( FBIT_603_AltGPR ) | |
8434 | +#endif | |
8435 | + | |
8436 | +#endif /* _MAC_REGISTERS_H */ | |
8437 | --- /dev/null | |
8438 | +++ b/drivers/macintosh/mol/include/map.h | |
8439 | @@ -0,0 +1,43 @@ | |
8440 | +/* | |
8441 | + * Creation Date: <2004/03/13 13:25:42 samuel> | |
8442 | + * Time-stamp: <2004/03/13 14:07:11 samuel> | |
8443 | + * | |
8444 | + * <map.h> | |
8445 | + * | |
8446 | + * | |
8447 | + * | |
8448 | + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) | |
8449 | + * | |
8450 | + * This program is free software; you can redistribute it and/or | |
8451 | + * modify it under the terms of the GNU General Public License | |
8452 | + * version 2 | |
8453 | + */ | |
8454 | + | |
8455 | +#ifndef _H_MAP | |
8456 | +#define _H_MAP | |
8457 | + | |
8458 | +/* map a userspace address into the kernel address space */ | |
8459 | +extern void *map_phys_range( ulong paddr, ulong size, char **ret_addr ); | |
8460 | +extern void unmap_phys_range( void *handle ); | |
8461 | + | |
8462 | +/* map a userspace address into the kernel address space */ | |
8463 | +extern void *map_virt_range( ulong va, ulong size, char **ret_addr ); | |
8464 | +extern void unmap_virt_range( void *handle ); | |
8465 | + | |
8466 | +/* map the virtualized PTE hash into the kernel address space */ | |
8467 | +extern ulong *map_emulated_hash( kernel_vars_t *kv, ulong mbase, ulong size ); | |
8468 | +extern void unmap_emulated_hash( kernel_vars_t *kv ); | |
8469 | + | |
8470 | +#ifdef __linux__ | |
8471 | +static inline ulong* map_hw_hash( ulong physbase, int size ) { | |
8472 | + return phys_to_virt( physbase ); | |
8473 | +} | |
8474 | +static inline void unmap_hw_hash( ulong *base ) {} | |
8475 | +#endif | |
8476 | + | |
8477 | +#ifdef __darwin__ | |
8478 | +static inline void *map_hw_hash( ulong physbase, int size ) { return NULL; } | |
8479 | +static inline void unmap_hw_hash( ulong *base ) {} | |
8480 | +#endif | |
8481 | + | |
8482 | +#endif /* _H_MAP */ | |
8483 | --- /dev/null | |
8484 | +++ b/drivers/macintosh/mol/include/misc.h | |
8485 | @@ -0,0 +1,105 @@ | |
8486 | +/* | |
8487 | + * Creation Date: <97/06/16 18:02:12 samuel> | |
8488 | + * Time-stamp: <2004/03/13 14:03:30 samuel> | |
8489 | + * | |
8490 | + * <misc.h> | |
8491 | + * | |
8492 | + * | |
8493 | + * | |
8494 | + * Copyright (C) 1997-2004 Samuel Rydh (samuel@ibrium.se) | |
8495 | + * | |
8496 | + * This program is free software; you can redistribute it and/or | |
8497 | + * modify it under the terms of the GNU General Public License | |
8498 | + * as published by the Free Software Foundation | |
8499 | + * | |
8500 | + */ | |
8501 | + | |
8502 | +#ifndef _H_MOD | |
8503 | +#define _H_MOD | |
8504 | + | |
8505 | +#ifdef __linux__ | |
8506 | + | |
8507 | +#include <linux/version.h> | |
8508 | +#include <asm/uaccess.h> | |
8509 | + | |
8510 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | |
8511 | +#define compat_verify_area(a,b,c) ( ! access_ok(a,b,c) ) | |
8512 | +#else | |
8513 | +#define compat_verify_area(a,b,c) verify_area(a,b,c) | |
8514 | +#endif | |
8515 | + | |
8516 | +#endif /* __linux__ */ | |
8517 | + | |
8518 | +extern int g_num_sessions; /* number of active sessions */ | |
8519 | + | |
8520 | +struct kernel_vars; | |
8521 | + | |
8522 | +/* init.c */ | |
8523 | +extern int common_init( void ); | |
8524 | +extern void common_cleanup( void ); | |
8525 | +extern int initialize_session( unsigned int sess_index ); | |
8526 | +extern void destroy_session( unsigned int sess_index ); | |
8527 | +extern uint get_session_magic( uint random_magic ); | |
8528 | + | |
8529 | +/* arch specific functions */ | |
8530 | +extern int arch_common_init( void ); | |
8531 | +extern void arch_common_cleanup( void ); | |
8532 | +extern struct kernel_vars *alloc_kvar_pages( void ); | |
8533 | +extern void free_kvar_pages( struct kernel_vars *kv ); | |
8534 | +extern void prevent_mod_unload( void ); | |
8535 | + | |
8536 | +/* misc.c */ | |
8537 | +struct dbg_op_params; | |
8538 | +struct perf_ctr; | |
8539 | +extern int do_debugger_op( kernel_vars_t *kv, struct dbg_op_params *pb ); | |
8540 | +extern int handle_ioctl( kernel_vars_t *kv, int what, int arg1, int arg2, int arg3 ); | |
8541 | + | |
8542 | +/* hostirq.c */ | |
8543 | +extern int grab_host_irq(kernel_vars_t *kv, int irq); | |
8544 | +extern int release_host_irq(kernel_vars_t *kv, int irq); | |
8545 | +extern void init_host_irqs(kernel_vars_t *kv); | |
8546 | +extern void cleanup_host_irqs(kernel_vars_t *kv); | |
8547 | + | |
8548 | +/* actions.c */ | |
8549 | +extern int perform_actions( void ); | |
8550 | +extern void cleanup_actions( void ); | |
8551 | + | |
8552 | +/* bit table manipulation */ | |
8553 | +static inline void | |
8554 | +set_bit_mol( int nr, char *addr ) | |
8555 | +{ | |
8556 | + ulong mask = 1 << (nr & 0x1f); | |
8557 | + ulong *p = ((ulong*)addr) + (nr >> 5); | |
8558 | + *p |= mask; | |
8559 | +} | |
8560 | + | |
8561 | +static inline void | |
8562 | +clear_bit_mol( int nr, char *addr ) | |
8563 | +{ | |
8564 | + ulong mask = 1 << (nr & 0x1f); | |
8565 | + ulong *p = ((ulong*)addr) + (nr >> 5); | |
8566 | + *p &= ~mask; | |
8567 | +} | |
8568 | + | |
8569 | +static inline int | |
8570 | +check_bit_mol( int nr, char *addr ) | |
8571 | +{ | |
8572 | + ulong mask = 1 << (nr & 0x1f); | |
8573 | + ulong *p = ((ulong*)addr) + (nr >> 5); | |
8574 | + return (*p & mask) != 0; | |
8575 | +} | |
8576 | + | |
8577 | +/* typesafe min/max (stolen from kernel.h) */ | |
8578 | +#define min_mol(x,y) ({ \ | |
8579 | + const typeof(x) _x = (x); \ | |
8580 | + const typeof(y) _y = (y); \ | |
8581 | + (void) (&_x == &_y); \ | |
8582 | + _x < _y ? _x : _y; }) | |
8583 | + | |
8584 | +#define max_mol(x,y) ({ \ | |
8585 | + const typeof(x) _x = (x); \ | |
8586 | + const typeof(y) _y = (y); \ | |
8587 | + (void) (&_x == &_y); \ | |
8588 | + _x > _y ? _x : _y; }) | |
8589 | + | |
8590 | +#endif | |
8591 | --- /dev/null | |
8592 | +++ b/drivers/macintosh/mol/include/mmu.h | |
8593 | @@ -0,0 +1,102 @@ | |
8594 | +/* | |
8595 | + * Creation Date: <1998-11-11 13:55:49 samuel> | |
8596 | + * Time-stamp: <2004/02/28 19:20:23 samuel> | |
8597 | + * | |
8598 | + * <mmu.h> | |
8599 | + * | |
8600 | + * MMU related things | |
8601 | + * | |
8602 | + * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se) | |
8603 | + * | |
8604 | + * This program is free software; you can redistribute it and/or | |
8605 | + * modify it under the terms of the GNU General Public License | |
8606 | + * as published by the Free Software Foundation | |
8607 | + * | |
8608 | + */ | |
8609 | + | |
8610 | +#ifndef _H_MMU | |
8611 | +#define _H_MMU | |
8612 | + | |
8613 | +#ifndef __ASSEMBLY__ | |
8614 | +#include "kernel_vars.h" | |
8615 | +#include "mac_registers.h" | |
8616 | +#include "mmu_mappings.h" | |
8617 | +#endif | |
8618 | + | |
8619 | +#ifdef CONFIG_MOL_HOSTED | |
8620 | +#define IO_PAGE_MAGIC_1 0x10BADA57 | |
8621 | +#define IO_PAGE_MAGIC_2 0x136AB779 | |
8622 | +#else | |
8623 | +#define IO_PAGE_MAGIC_1 0x10BACA57 | |
8624 | +#define IO_PAGE_MAGIC_2 0x135AB779 | |
8625 | +#endif | |
8626 | + | |
8627 | +#ifndef __ASSEMBLY__ | |
8628 | +typedef struct io_page { /* Must fit within a single 4K page */ | |
8629 | + ulong magic; /* identifier 1 */ | |
8630 | + ulong magic2; /* identifier 2 */ | |
8631 | + | |
8632 | + ulong me_phys; /* physical address of this block */ | |
8633 | + ulong mphys; /* mac-physical address of block */ | |
8634 | + struct io_page *next; /* next io_page */ | |
8635 | + | |
8636 | + void *usr_data[512]; /* usr data (grain=double word) */ | |
8637 | +} io_page_t; | |
8638 | + | |
8639 | +/* from mmu.c */ | |
8640 | +extern int init_mmu( kernel_vars_t *kv ); | |
8641 | +extern void cleanup_mmu( kernel_vars_t *kv ); | |
8642 | +extern void do_flush( ulong vsid, ulong va, ulong *dummy, int num ); | |
8643 | +extern void mmu_altered( kernel_vars_t *kv ); | |
8644 | +extern void clear_vsid_refs( kernel_vars_t *kv ); | |
8645 | + | |
8646 | +/* arch/mmu.c */ | |
8647 | +extern int arch_mmu_init( kernel_vars_t *kv ); | |
8648 | + | |
8649 | +/* from mmu_io.c */ | |
8650 | +struct pte_lvrange; | |
8651 | +extern int init_mmu_io( kernel_vars_t *kv ); | |
8652 | +extern void cleanup_mmu_io( kernel_vars_t *kv ); | |
8653 | +extern int add_io_trans( kernel_vars_t *kv, ulong mbase, int size, void *usr_data ); | |
8654 | +extern int remove_io_trans( kernel_vars_t *kv, ulong mbase, int size ); | |
8655 | +extern int mphys_to_pte( kernel_vars_t *kv, ulong mphys, ulong *pte1, int is_write, struct pte_lvrange **lvrange ); | |
8656 | +extern void mmu_add_map( kernel_vars_t *kv, struct mmu_mapping *m ); | |
8657 | +extern void mmu_remove_map( kernel_vars_t *kv, struct mmu_mapping *m ); | |
8658 | + | |
8659 | +/* from context.c */ | |
8660 | +extern int init_contexts( kernel_vars_t *kv ); | |
8661 | +extern void cleanup_contexts( kernel_vars_t *kv ); | |
8662 | +extern int alloc_context( kernel_vars_t *kv ); | |
8663 | +extern void handle_context_wrap( kernel_vars_t *kv, int nvsid_needed ); | |
8664 | + | |
8665 | +/* from mmu_fb.c */ | |
8666 | +extern int init_mmu_fb( kernel_vars_t *kv ); | |
8667 | +extern void cleanup_mmu_fb( kernel_vars_t *kv ); | |
8668 | +extern void video_pte_inserted( kernel_vars_t *kv, ulong lvptr, ulong *slot, | |
8669 | + ulong pte0, ulong pte1, ulong ea ); | |
8670 | +extern void setup_fb_acceleration( kernel_vars_t *kv, char *lvbase, int bytes_per_row, int height ); | |
8671 | +extern int get_dirty_fb_lines( kernel_vars_t *kv, short *retbuf, int num_bytes ); | |
8672 | + | |
8673 | +/* from mmu_tracker.c */ | |
8674 | +extern int init_mmu_tracker( kernel_vars_t *kv ); | |
8675 | +extern void cleanup_mmu_tracker( kernel_vars_t *kv ); | |
8676 | +extern int track_lvrange( kernel_vars_t *kv ); | |
8677 | +extern size_t get_track_buffer( kernel_vars_t *kv, char *retbuf ); | |
8678 | +extern void set_track_buffer( kernel_vars_t *kv, char *buf ); | |
8679 | +extern void lvpage_dirty( kernel_vars_t *kv, ulong lvpage ); | |
8680 | + | |
8681 | +/* These functions should be used by the debugger only */ | |
8682 | +struct dbg_page_info; | |
8683 | +extern int dbg_get_PTE( kernel_vars_t *kv, int context, ulong va, mPTE_t *ret ); | |
8684 | +extern int dbg_get_linux_page( ulong va, struct dbg_page_info *r ); | |
8685 | +extern int dbg_translate_ea( kernel_vars_t *kv, int context, ulong va, int *ret_mphys, int data_access ); | |
8686 | + | |
8687 | +/* arch functions */ | |
8688 | +extern ulong get_phys_page( kernel_vars_t *kv, ulong lvptr, int request_rw ); | |
8689 | + | |
8690 | +/* VSID stuff */ | |
8691 | +#define VSID_MASK 0xffffff | |
8692 | + | |
8693 | + | |
8694 | +#endif /* __ASSEMBLY__ */ | |
8695 | +#endif /* _H_MMU */ | |
8696 | --- /dev/null | |
8697 | +++ b/drivers/macintosh/mol/include/mmu_contexts.h | |
8698 | @@ -0,0 +1,55 @@ | |
8699 | +/* | |
8700 | + * Creation Date: <97/07/17 14:26:14 samuel> | |
8701 | + * Time-stamp: <2003/06/06 19:17:26 samuel> | |
8702 | + * | |
8703 | + * <mmu_contexts.h> | |
8704 | + * | |
8705 | + * | |
8706 | + * | |
8707 | + * Copyright (C) 1997, 2001, 2002, 2003 Samuel Rydh | |
8708 | + * | |
8709 | + * This program is free software; you can redistribute it and/or | |
8710 | + * modify it under the terms of the GNU General Public License | |
8711 | + * version 2 | |
8712 | + * | |
8713 | + */ | |
8714 | + | |
8715 | +#ifndef _H_MMU_CONTEXTS | |
8716 | +#define _H_MMU_CONTEXTS | |
8717 | + | |
8718 | +/********************************************************** | |
8719 | + * EVERYTHING IN THIS FILE IS UESED FOR DEBUGGING ONLY | |
8720 | + *********************************************************/ | |
8721 | + | |
8722 | +/* MMU context identifiers */ | |
8723 | +#define kContextUnmapped 1 | |
8724 | +#define kContextMapped_S 2 | |
8725 | +#define kContextMapped_U 3 | |
8726 | + | |
8727 | +#define kContextEmulator 20 /* for debugging purposes ONLY !!!! */ | |
8728 | +#define kContextKernel 21 /* for debugging purposes ONLY !!!! */ | |
8729 | + | |
8730 | + | |
8731 | +/* Flags returned by _get_physical_page(). The first flags should | |
8732 | + * equal the _PAGE_XXX of the old MM implementation (<2.4.6). | |
8733 | + */ | |
8734 | +#define M_PAGE_PRESENT 0x001 /* software: pte contains a translation */ | |
8735 | +#define M_PAGE_USER 0x002 /* usermode access allowed */ | |
8736 | +#define M_PAGE_RW 0x004 /* usermode access allowed */ | |
8737 | +#define M_PAGE_GUARDED 0x008 /* G: prohibit speculative access */ | |
8738 | +#define M_PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */ | |
8739 | +#define M_PAGE_NO_CACHE 0x020 /* I: cache inhibit */ | |
8740 | +#define M_PAGE_WRITETHRU 0x040 /* W: cache write-through */ | |
8741 | +#define M_PAGE_DIRTY 0x080 /* C: page changed */ | |
8742 | +#define M_PAGE_ACCESSED 0x100 /* R: page referenced */ | |
8743 | +/* new linux-MM implementation */ | |
8744 | +#define M_PAGE_HASHPTE 0x1000 /* hash_page has made an HPTE for this pte */ | |
8745 | +#define M_PAGE_EXEC 0x2000 /* software: i-cache coherency required */ | |
8746 | + | |
8747 | +#ifdef __KERNEL__ | |
8748 | +#define DBG_TRANSL_PAGE_FLAG( val, flagname ) \ | |
8749 | + (((val) & flagname )? M##flagname : 0) | |
8750 | +#endif | |
8751 | + | |
8752 | + | |
8753 | +#endif /* _H_MMU_CONTEXTS */ | |
8754 | --- /dev/null | |
8755 | +++ b/drivers/macintosh/mol/include/mmu_mappings.h | |
8756 | @@ -0,0 +1,48 @@ | |
8757 | +/* | |
8758 | + * Creation Date: <1998-10-31 03:11:06 samuel> | |
8759 | + * Time-stamp: <2004/03/13 16:44:58 samuel> | |
8760 | + * | |
8761 | + * <mmu_mappings.h> | |
8762 | + * | |
8763 | + * Mappings mac physical <-> linux virtual | |
8764 | + * | |
8765 | + * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se) | |
8766 | + * | |
8767 | + * This program is free software; you can redistribute it and/or | |
8768 | + * modify it under the terms of the GNU General Public License | |
8769 | + * as published by the Free Software Foundation | |
8770 | + * | |
8771 | + */ | |
8772 | + | |
8773 | +#ifndef _H_MMU_MAPPINGS | |
8774 | +#define _H_MMU_MAPPINGS | |
8775 | + | |
8776 | +typedef struct mmu_mapping { | |
8777 | + ulong mbase; /* mac physical base */ | |
8778 | + char *lvbase; /* linux virtual base */ | |
8779 | + size_t size; /* size (in bytes) */ | |
8780 | + int flags; /* MAPPING_xxx */ | |
8781 | + | |
8782 | + int id; /* set to zero, returned by the kerrnel module */ | |
8783 | +} mmu_mapping_t; | |
8784 | + | |
8785 | +/* mmu_mapping flags */ | |
8786 | + | |
8787 | +#define MAPPING_RO 1 /* read only memory (ROM etc) */ | |
8788 | +#define MAPPING_PHYSICAL 2 /* physical (ROM etc) */ | |
8789 | +#define MAPPING_SCRATCH 4 /* (block transl) scratch area */ | |
8790 | +#define MAPPING_FORCE_CACHE 8 /* force write-through caching */ | |
8791 | +#define MAPPING_FB_ACCEL 16 /* offscreen framebuffer, track changes */ | |
8792 | +#define MAPPING_FB 32 /* framebuffer (ea assumed to be constant) */ | |
8793 | +#define MAPPING_DBAT 64 /* allow use of a DBAT register */ | |
8794 | +#define MAPPING_MACOS_CONTROLS_CACHE 128 /* do not force WIM bits to 001 */ | |
8795 | +#define MAPPING_PUT_FIRST 256 /* take precedence over other translations */ | |
8796 | +#define MAPPING_MREGS 512 /* map mregs into emulated process */ | |
8797 | +#define MAPPING_FORCE_WRITABLE 4096 /* guess what... */ | |
8798 | + | |
8799 | +#ifdef __KERNEL__ | |
8800 | +#define MAPPING_IO 1024 /* I/O translation */ | |
8801 | +#define MAPPING_VALID 2048 /* valid bit */ | |
8802 | +#endif | |
8803 | + | |
8804 | +#endif /* _H_MMU_MAPPINGS */ | |
8805 | --- /dev/null | |
8806 | +++ b/drivers/macintosh/mol/include/mmutypes.h | |
8807 | @@ -0,0 +1,76 @@ | |
8808 | +/* | |
8809 | + * Creation Date: <2002/01/13 13:53:14 samuel> | |
8810 | + * Time-stamp: <2002/01/27 19:56:11 samuel> | |
8811 | + * | |
8812 | + * <mmutypes.h> | |
8813 | + * | |
8814 | + * MMU definitions | |
8815 | + * | |
8816 | + * Most of these declarations originate from the Linux Kernel | |
8817 | + * | |
8818 | + * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se) | |
8819 | + * | |
8820 | + * This program is free software; you can redistribute it and/or | |
8821 | + * modify it under the terms of the GNU General Public License | |
8822 | + * as published by the Free Software Foundation | |
8823 | + * | |
8824 | + */ | |
8825 | + | |
8826 | +#ifndef _H_MMUTYPES | |
8827 | +#define _H_MMUTYPES | |
8828 | + | |
8829 | +/* Hardware Page Table Entry */ | |
8830 | +typedef struct mPTE { | |
8831 | + unsigned long v:1; /* Entry is valid */ | |
8832 | + unsigned long vsid:24; /* Virtual segment identifier */ | |
8833 | + unsigned long h:1; /* Hash algorithm indicator */ | |
8834 | + unsigned long api:6; /* Abbreviated page index */ | |
8835 | + | |
8836 | + unsigned long rpn:20; /* Real (physical) page number */ | |
8837 | + unsigned long :3; /* Unused */ | |
8838 | + unsigned long r:1; /* Referenced */ | |
8839 | + unsigned long c:1; /* Changed */ | |
8840 | + unsigned long w:1; /* Write-thru cache mode */ | |
8841 | + unsigned long i:1; /* Cache inhibited */ | |
8842 | + unsigned long m:1; /* Memory coherence */ | |
8843 | + unsigned long g:1; /* Guarded */ | |
8844 | + unsigned long :1; /* Unused */ | |
8845 | + unsigned long pp:2; /* Page protection */ | |
8846 | +} mPTE_t; | |
8847 | + | |
8848 | + | |
8849 | +typedef struct _mBATU { /* Upper part of BAT (all except 601) */ | |
8850 | + unsigned long bepi:15; /* Effective page index (virtual address) */ | |
8851 | + unsigned long :4; /* Unused */ | |
8852 | + unsigned long bl:11; /* Block size mask */ | |
8853 | + unsigned long vs:1; /* Supervisor valid */ | |
8854 | + unsigned long vp:1; /* User valid */ | |
8855 | +} mBATU; | |
8856 | + | |
8857 | +typedef struct _mBATL { /* Lower part of BAT (all except 601) */ | |
8858 | + unsigned long brpn:15; /* Real page index (physical address) */ | |
8859 | + unsigned long :10; /* Unused */ | |
8860 | + unsigned long w:1; /* Write-thru cache */ | |
8861 | + unsigned long i:1; /* Cache inhibit */ | |
8862 | + unsigned long m:1; /* Memory coherence */ | |
8863 | + unsigned long g:1; /* Guarded (MBZ in IBAT) */ | |
8864 | + unsigned long :1; /* Unused */ | |
8865 | + unsigned long pp:2; /* Page access protections */ | |
8866 | +} mBATL; | |
8867 | + | |
8868 | +typedef struct _mBAT { | |
8869 | + mBATU batu; /* Upper register */ | |
8870 | + mBATL batl; /* Lower register */ | |
8871 | +} mBAT; | |
8872 | + | |
8873 | +typedef struct _mSEGREG { | |
8874 | + unsigned long t:1; /* Normal or I/O type */ | |
8875 | + unsigned long ks:1; /* Supervisor 'key' (normally 0) */ | |
8876 | + unsigned long kp:1; /* User 'key' (normally 1) */ | |
8877 | + unsigned long n:1; /* No-execute */ | |
8878 | + unsigned long :4; /* Unused */ | |
8879 | + unsigned long vsid:24; /* Virtual Segment Identifier */ | |
8880 | +} mSEGREG; | |
8881 | + | |
8882 | + | |
8883 | +#endif /* _H_MMUTYPES */ | |
8884 | --- /dev/null | |
8885 | +++ b/drivers/macintosh/mol/include/mol-ioctl.h | |
8886 | @@ -0,0 +1,121 @@ | |
8887 | +/* | |
8888 | + * Creation Date: <2003/08/26 10:53:07 samuel> | |
8889 | + * Time-stamp: <2004/02/08 20:17:58 samuel> | |
8890 | + * | |
8891 | + * <mol-ioctl.h> | |
8892 | + * | |
8893 | + * | |
8894 | + * | |
8895 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
8896 | + * | |
8897 | + * This program is free software; you can redistribute it and/or | |
8898 | + * modify it under the terms of the GNU General Public License | |
8899 | + * version 2 | |
8900 | + * | |
8901 | + */ | |
8902 | + | |
8903 | +#ifndef _H_MOL_IOCTL | |
8904 | +#define _H_MOL_IOCTL | |
8905 | + | |
8906 | +#ifndef __ASSEMBLY__ | |
8907 | +#include "mmutypes.h" | |
8908 | + | |
8909 | +typedef struct { | |
8910 | + int version; /* MOL version */ | |
8911 | + int smp_kernel; /* compiled with CONFIG_SMP */ | |
8912 | + int pvr; /* cpu version/revision (PVR) */ | |
8913 | + int rombase; | |
8914 | + int romsize; | |
8915 | + unsigned int tb_freq; | |
8916 | +} mol_kmod_info_t; | |
8917 | + | |
8918 | +typedef struct perf_ctr { | |
8919 | + unsigned int ctr; | |
8920 | + char name[40]; | |
8921 | +} perf_ctr_t; | |
8922 | + | |
8923 | +typedef struct dbg_page_info { | |
8924 | + int phys; | |
8925 | + int mflags; /* M_PAGE_XXX */ | |
8926 | +} dbg_page_info_t; | |
8927 | + | |
8928 | +typedef struct dbg_op_params { | |
8929 | + /* input */ | |
8930 | + int operation; /* DBG_OP_xxx */ | |
8931 | + int ea; | |
8932 | + int context; | |
8933 | + int param; | |
8934 | + | |
8935 | + /* output */ | |
8936 | + union { | |
8937 | + int phys; | |
8938 | + dbg_page_info_t page; | |
8939 | + mPTE_t pte; | |
8940 | + } ret; | |
8941 | +} dbg_op_params_t; | |
8942 | + | |
8943 | +typedef struct mol_ioctl_pb { | |
8944 | + int arg1, arg2, arg3; | |
8945 | +#ifdef __darwin__ | |
8946 | + int ret; | |
8947 | +#endif | |
8948 | +} mol_ioctl_pb_t; | |
8949 | + | |
8950 | +#endif /* __ASSEMBLY__ */ | |
8951 | + | |
8952 | +/* ioctls that do not use the mol_ioctl_pb arg */ | |
8953 | +#define MOL_IOCTL_SMP_SEND_IPI _IO('M', 1) /* void ( void ) */ | |
8954 | +#ifdef __darwin__ | |
8955 | +#define MOL_IOCTL_CALL_KERNEL _IO('M', 2) /* void ( void ) */ | |
8956 | +#endif | |
8957 | + | |
8958 | +/* debugger ioctls */ | |
8959 | +#define MOL_IOCTL_DEBUGGER_OP _IOWR('M', 10, mol_ioctl_pb_t) /* int ( dbg_op_params *p ) */ | |
8960 | +#define DBG_OP_EMULATE_TLBIE 1 /* void ( ulong pageindex ) */ | |
8961 | +#define DBG_OP_EMULATE_TLBIA 2 /* void ( void ) */ | |
8962 | +#define DBG_OP_GET_PTE 3 /* lvptr, context, int ( ulong vsid, ulong va, PTE *retpte ) */ | |
8963 | +#define DBG_OP_GET_PHYS_PAGE 4 /* int ( ulong lvptr, ulong *retptr ) */ | |
8964 | +#define DBG_OP_BREAKPOINT_FLAGS 5 /* void ( ulong flags ) */ | |
8965 | +#define DBG_OP_TRANSLATE_EA 6 /* ea, context, is_data -- mphys */ | |
8966 | +#define MOL_IOCTL_CLEAR_PERF_INFO _IOWR('M', 11, mol_ioctl_pb_t) /* void ( void ) */ | |
8967 | +#define MOL_IOCTL_GET_PERF_INFO _IOWR('M', 12, mol_ioctl_pb_t) /* int ( int index, perf_ctr_t *ctr ) */ | |
8968 | + | |
8969 | +/* config selectors */ | |
8970 | +#define MOL_IOCTL_CREATE_SESSION _IOWR('M', 30, mol_ioctl_pb_t) /* int ( int session_index ) */ | |
8971 | +#define MOL_IOCTL_GET_INFO _IOWR('M', 31, mol_ioctl_pb_t) /* int ( mol_kmod_info_t *retinfo, int size ) */ | |
8972 | +#define MOL_IOCTL_SET_RAM _IOWR('M', 33, mol_ioctl_pb_t) /* void ( ulong ram_start, ulong ram_end ) */ | |
8973 | +#define MOL_IOCTL_COPY_LAST_ROMPAGE _IOWR('M', 34, mol_ioctl_pb_t) /* void ( char *destpage ) */ | |
8974 | +#define MOL_IOCTL_SPR_CHANGED _IOWR('M', 35, mol_ioctl_pb_t) /* void ( void ) */ | |
8975 | +#define MOL_IOCTL_IDLE_RECLAIM_MEMORY _IOWR('M', 36, mol_ioctl_pb_t) /* void ( void ) */ | |
8976 | +#define MOL_IOCTL_MMU_MAP _IOWR('M', 37, mol_ioctl_pb_t) /* void ( struct mmu_mapping *m, int add_map ) */ | |
8977 | +#define MOL_IOCTL_ADD_IORANGE _IOWR('M', 39, mol_ioctl_pb_t) /* void ( ulong mbase, size_t size, io_ops_t *) */ | |
8978 | +#define MOL_IOCTL_REMOVE_IORANGE _IOWR('M', 40, mol_ioctl_pb_t) /* void ( ulong mbase, size_t size ) */ | |
8979 | +#define MOL_IOCTL_SETUP_FBACCEL _IOWR('M', 41, mol_ioctl_pb_t) /* void * ( char *lvbase, int bytes_per_row, int height ) */ | |
8980 | +#define MOL_IOCTL_GET_DIRTY_FBLINES _IOWR('M', 42, mol_ioctl_pb_t) /* int ( short *rettable, int table_size_in_bytes ) */ | |
8981 | +#define MOL_IOCTL_TRACK_DIRTY_RAM _IOWR('M', 43, mol_ioctl_pb_t) /* int ( char *lvbase, size_t size ) */ | |
8982 | +#define MOL_IOCTL_GET_DIRTY_RAM _IOWR('M', 44, mol_ioctl_pb_t) /* size_t ( char *retbuf ) */ | |
8983 | +#define MOL_IOCTL_SET_DIRTY_RAM _IOWR('M', 45, mol_ioctl_pb_t) /* void ( char *dirtybuf ) */ | |
8984 | +#define MOL_IOCTL_GET_MREGS_PHYS _IOWR('M', 46, mol_ioctl_pb_t) /* ulong ( void ) */ | |
8985 | +#define MOL_IOCTL_ALLOC_EMUACCEL_SLOT _IOWR('M', 47, mol_ioctl_pb_t) /* int ( int inst_flags, int param, int inst_addr ) */ | |
8986 | +#define MOL_IOCTL_MAPIN_EMUACCEL_PAGE _IOWR('M', 48, mol_ioctl_pb_t) /* int ( int mphys ) */ | |
8987 | +#define MOL_IOCTL_TUNE_SPR _IOWR('M', 49, mol_ioctl_pb_t) /* int ( int spr, int action ) */ | |
8988 | +#define MOL_IOCTL_GET_SESSION_MAGIC _IOWR('M', 50, mol_ioctl_pb_t) /* uint ( uint new_random_magic ) */ | |
8989 | + | |
8990 | +#define MOL_IOCTL_DBG_COPY_KVARS _IOWR('M', 51, mol_ioctl_pb_t) /* int ( int session, kernel_vars_t *dest ) */ | |
8991 | + | |
8992 | +#ifdef __darwin__ | |
8993 | +#define MOL_IOCTL_GET_MREGS_VIRT _IOWR('M', 52, mol_ioctl_pb_t) /* int ( mac_regs_t **ret ) */ | |
8994 | +#endif | |
8995 | + | |
8996 | +#define MOL_IOCTL_GRAB_IRQ _IOWR('M', 53, mol_ioctl_pb_t) /* int ( int irq ) */ | |
8997 | +#define MOL_IOCTL_RELEASE_IRQ _IOWR('M', 54, mol_ioctl_pb_t) /* int ( int irq ) */ | |
8998 | +#define MOL_IOCTL_GET_IRQS _IOWR('M', 55, mol_ioctl_pb_t) /* int ( irq_bitfield_t * ) */ | |
8999 | + | |
9000 | + | |
9001 | +/* MOL error codes */ | |
9002 | +#define EMOLGENERAL 100 | |
9003 | +#define EMOLINUSE 101 | |
9004 | +#define EMOLINVAL 102 | |
9005 | +#define EMOLSECURITY 103 | |
9006 | + | |
9007 | +#endif /* _H_MOL_IOCTL */ | |
9008 | --- /dev/null | |
9009 | +++ b/drivers/macintosh/mol/include/mol_config.h | |
9010 | @@ -0,0 +1,76 @@ | |
9011 | +/* | |
9012 | + * Creation Date: <1999/05/30 15:30:25 samuel> | |
9013 | + * Time-stamp: <2004/06/05 19:47:33 samuel> | |
9014 | + * | |
9015 | + * <mol_config.h> | |
9016 | + * | |
9017 | + * Header to be included first... | |
9018 | + * | |
9019 | + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
9020 | + * | |
9021 | + * This program is free software; you can redistribute it and/or | |
9022 | + * modify it under the terms of the GNU General Public License | |
9023 | + * as published by the Free Software Foundation | |
9024 | + * | |
9025 | + */ | |
9026 | + | |
9027 | +#ifndef _H_MOL_CONFIG | |
9028 | +#define _H_MOL_CONFIG | |
9029 | + | |
9030 | +/* Some debugging flags */ | |
9031 | +#define COLLECT_RVEC_STATISTICS | |
9032 | +//#define EMULATE_603 | |
9033 | +//#define ENABLE_ASSERT | |
9034 | + | |
9035 | +#define _GNU_SOURCE | |
9036 | +#define _REENTRANT | |
9037 | +#define _LARGEFILE64_SOURCE | |
9038 | + | |
9039 | +#if defined(__powerpc__) && !defined(__ppc__) | |
9040 | +#define __ppc__ | |
9041 | +#endif | |
9042 | +#if defined(__ppc__) && !defined(__powerpc__) | |
9043 | +#define __powerpc__ | |
9044 | +#endif | |
9045 | + | |
9046 | +#if !defined(__linux__) && !defined(__ASSEMBLY__) | |
9047 | +typedef unsigned long ulong; | |
9048 | +#endif | |
9049 | + | |
9050 | +#if !defined(__ASSEMBLY__) && !defined(__KERNEL__) | |
9051 | +#include <stdio.h> | |
9052 | +#include <stdlib.h> | |
9053 | +#include <string.h> | |
9054 | +#include <unistd.h> | |
9055 | +#include <sys/types.h> | |
9056 | +#include <sys/stat.h> | |
9057 | +#include <fcntl.h> | |
9058 | +#include <errno.h> | |
9059 | +#include <ctype.h> | |
9060 | + | |
9061 | +#include "config.h" | |
9062 | +#include "autoconf.h" | |
9063 | +#include "unconfig.h" | |
9064 | + | |
9065 | +#ifdef CONFIG_OLDWORLD | |
9066 | +#define OLDWORLD_SUPPORT | |
9067 | +#endif | |
9068 | + | |
9069 | +#include "platform.h" | |
9070 | + | |
9071 | +/* from emulaiton/main.c */ | |
9072 | +extern int in_security_mode; | |
9073 | + | |
9074 | +/* common MOL header fiels */ | |
9075 | + | |
9076 | +#include "debugger.h" /* for printm */ | |
9077 | +#include "extralib.h" | |
9078 | + | |
9079 | +#endif /* __ASSEMBLY__ && __KERNEL__ */ | |
9080 | + | |
9081 | +#ifdef __ASSEMBLY__ | |
9082 | +changequote([[[[[,]]]]]) | |
9083 | +[[[[[ /* shield includes from m4-expansion */ | |
9084 | +#endif | |
9085 | + | |
9086 | +#endif /* _H_MOL_CONFIG */ | |
9087 | --- /dev/null | |
9088 | +++ b/drivers/macintosh/mol/include/molasm.h | |
9089 | @@ -0,0 +1,138 @@ | |
9090 | +/* -*- asm -*- | |
9091 | + * | |
9092 | + * Creation Date: <2001/01/28 20:33:22 samuel> | |
9093 | + * Time-stamp: <2004/01/29 19:29:10 samuel> | |
9094 | + * | |
9095 | + * <molasm.h> | |
9096 | + * | |
9097 | + * Utility assembly macros | |
9098 | + * | |
9099 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
9100 | + * | |
9101 | + * This program is free software; you can redistribute it and/or | |
9102 | + * modify it under the terms of the GNU General Public License | |
9103 | + * as published by the Free Software Foundation | |
9104 | + * | |
9105 | + */ | |
9106 | + | |
9107 | +#ifndef _H_MOLASM | |
9108 | +#define _H_MOLASM | |
9109 | + | |
9110 | +#define GLOBAL_SYMBOL( sym_name ) \ | |
9111 | +GLOBL(sym_name) | |
9112 | + | |
9113 | + | |
9114 | +/************************************************************************/ | |
9115 | +/* SPRG usage */ | |
9116 | +/************************************************************************/ | |
9117 | + | |
9118 | +/* Darwin and Linux uses the sprg's differently. Linux uses sprg0/1 in | |
9119 | + * the exception vectors while Darwin uses sprg2/3. | |
9120 | + */ | |
9121 | +#ifdef __linux__ | |
9122 | +define([mfsprg_a0], [mfsprg0]) | |
9123 | +define([mfsprg_a1], [mfsprg1]) | |
9124 | +define([mfsprg_a2], [mfsprg2]) | |
9125 | +define([mfsprg_a3], [mfsprg3]) | |
9126 | +define([mtsprg_a0], [mtsprg0]) | |
9127 | +define([mtsprg_a1], [mtsprg1]) | |
9128 | +define([mtsprg_a2], [mtsprg2]) | |
9129 | +define([mtsprg_a3], [mtsprg3]) | |
9130 | +#else | |
9131 | +define([mfsprg_a0], [mfsprg2]) | |
9132 | +define([mfsprg_a1], [mfsprg3]) | |
9133 | +define([mfsprg_a2], [mfsprg0]) | |
9134 | +define([mfsprg_a3], [mfsprg1]) | |
9135 | +define([mtsprg_a0], [mtsprg2]) | |
9136 | +define([mtsprg_a1], [mtsprg3]) | |
9137 | +define([mtsprg_a2], [mtsprg0]) | |
9138 | +define([mtsprg_a3], [mtsprg1]) | |
9139 | +#endif | |
9140 | + | |
9141 | + | |
9142 | +/************************************************************************/ | |
9143 | +/* Utility */ | |
9144 | +/************************************************************************/ | |
9145 | + | |
9146 | +MACRO(LOAD_VARIABLE, [reg, offs], [ | |
9147 | + lis _reg,HA(k_mol_stack + _offs) | |
9148 | + lwz _reg,LO(k_mol_stack + _offs)(_reg) | |
9149 | +]) | |
9150 | + | |
9151 | +MACRO(SET_SESSION_TABLE, [reg], [ | |
9152 | + lis _reg,HA(EXTERN(Symbol_SESSION_TABLE)) | |
9153 | + addi _reg,_reg,LO(EXTERN(Symbol_SESSION_TABLE)) | |
9154 | +]) | |
9155 | + | |
9156 | + | |
9157 | +/************************************************************************/ | |
9158 | +/* GPR save / restore */ | |
9159 | +/************************************************************************/ | |
9160 | + | |
9161 | +MACRO(xGPR_SAVE, [reg], [ | |
9162 | + stw rPREFIX[]_reg,(xGPR0 + _reg*4)(r1) | |
9163 | +]) | |
9164 | + | |
9165 | +MACRO(xGPR_LOAD, [reg], [ | |
9166 | + lwz rPREFIX[]_reg,(xGPR0 + _reg*4)(r1) | |
9167 | +]) | |
9168 | + | |
9169 | + | |
9170 | +/************************************************************************/ | |
9171 | +/* FPU misc */ | |
9172 | +/************************************************************************/ | |
9173 | + | |
9174 | +MACRO(ENABLE_MSR_FP, [scr], [ | |
9175 | + mfmsr _scr | |
9176 | + ori _scr,_scr,MSR_FP | |
9177 | + mtmsr _scr | |
9178 | + isync | |
9179 | +]) | |
9180 | + | |
9181 | +/************************************************************************/ | |
9182 | +/* Segment registers */ | |
9183 | +/************************************************************************/ | |
9184 | + | |
9185 | +MACRO(LOAD_SEGMENT_REGS, [base, scr, scr2], [ | |
9186 | + mFORLOOP([i],0,7,[ | |
9187 | + lwz _scr,eval(i * 8)(_base) | |
9188 | + lwz _scr2,eval((i * 8)+4)(_base) | |
9189 | + mtsr srPREFIX[]eval(i*2),_scr | |
9190 | + mtsr srPREFIX[]eval(i*2+1),_scr2 | |
9191 | + ]) | |
9192 | +]) | |
9193 | + | |
9194 | +MACRO(SAVE_SEGMENT_REGS, [base, scr, scr2], [ | |
9195 | + mFORLOOP([i],0,7,[ | |
9196 | + mfsr _scr,srPREFIX[]eval(i*2) | |
9197 | + mfsr _scr2,srPREFIX[]eval(i*2+1) | |
9198 | + stw _scr,eval(i * 8)(_base) | |
9199 | + stw _scr2,eval((i * 8) + 4)(_base) | |
9200 | + ]) | |
9201 | +]) | |
9202 | + | |
9203 | +/************************************************************************/ | |
9204 | +/* BAT register */ | |
9205 | +/************************************************************************/ | |
9206 | + | |
9207 | +MACRO(SAVE_DBATS, [varoffs, scr1], [ | |
9208 | + mfpvr _scr1 | |
9209 | + srwi _scr1,_scr1,16 | |
9210 | + cmpwi r3,1 | |
9211 | + beq 9f | |
9212 | + mFORLOOP([nn],0,7,[ | |
9213 | + mfspr _scr1, S_DBAT0U + nn | |
9214 | + stw _scr1,(_varoffs + (4 * nn))(r1) | |
9215 | + ]) | |
9216 | +9: | |
9217 | +]) | |
9218 | + | |
9219 | +MACRO(SAVE_IBATS, [varoffs, scr1], [ | |
9220 | + mFORLOOP([nn],0,7,[ | |
9221 | + mfspr _scr1, S_IBAT0U + nn | |
9222 | + stw _scr1,(_varoffs + (4 * nn))(r1) | |
9223 | + ]) | |
9224 | +]) | |
9225 | + | |
9226 | + | |
9227 | +#endif /* _H_MOLASM */ | |
9228 | --- /dev/null | |
9229 | +++ b/drivers/macintosh/mol/include/molversion.h | |
9230 | @@ -0,0 +1,6 @@ | |
9231 | +#define MOL_BUILD_DATE "Okt 13 2007 11:49" | |
9232 | +#define MOL_VERSION_STR "0.9.73" | |
9233 | +#define MOL_RELEASE "0.9.73-SVN" | |
9234 | +#define MOL_MAJOR_VERSION 0 | |
9235 | +#define MOL_MINOR_VERSION 9 | |
9236 | +#define MOL_PATCHLEVEL 73 | |
9237 | --- /dev/null | |
9238 | +++ b/drivers/macintosh/mol/include/mtable.h | |
9239 | @@ -0,0 +1,71 @@ | |
9240 | +/* | |
9241 | + * Creation Date: <2002/05/26 15:52:50 samuel> | |
9242 | + * Time-stamp: <2004/02/21 16:18:11 samuel> | |
9243 | + * | |
9244 | + * <mtable.h> | |
9245 | + * | |
9246 | + * Keeps track of the PTEs | |
9247 | + * | |
9248 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
9249 | + * | |
9250 | + * This program is free software; you can redistribute it and/or | |
9251 | + * modify it under the terms of the GNU General Public License | |
9252 | + * as published by the Free Software Foundation | |
9253 | + * | |
9254 | + */ | |
9255 | + | |
9256 | +#ifndef _H_MTABLE | |
9257 | +#define _H_MTABLE | |
9258 | + | |
9259 | +#ifndef __ASSEMBLY__ | |
9260 | +typedef struct pte_lvrange pte_lvrange_t; | |
9261 | +typedef struct vsid_info vsid_info_t; | |
9262 | +typedef struct vsid_ent vsid_ent_t; | |
9263 | + | |
9264 | +extern int init_mtable( kernel_vars_t *kv ); | |
9265 | +extern void cleanup_mtable( kernel_vars_t *kv ); | |
9266 | + | |
9267 | +extern pte_lvrange_t *register_lvrange( kernel_vars_t *kv, char *lvbase, int size ); | |
9268 | +extern void free_lvrange( kernel_vars_t *kv, pte_lvrange_t *pte_range ); | |
9269 | + | |
9270 | +extern vsid_ent_t *vsid_get_user_sv( kernel_vars_t *kv, int mac_vsid, ulong *user_sr, ulong *sv_sr ); | |
9271 | + | |
9272 | +extern int mtable_memory_check( kernel_vars_t *kv ); | |
9273 | +extern void pte_inserted( kernel_vars_t *kv, ulong ea, char *lvptr, | |
9274 | + pte_lvrange_t *lvrange, ulong *pte, vsid_ent_t *r, | |
9275 | + int segreg ); | |
9276 | + | |
9277 | +extern void flush_vsid_ea( kernel_vars_t *kv, int vsid, ulong ea ); | |
9278 | +extern void flush_ea_range( kernel_vars_t *kv, ulong ea, int size ); | |
9279 | +extern void flush_lvptr( kernel_vars_t *kv, ulong lvptr ); | |
9280 | +extern void flush_lv_range( kernel_vars_t *kv, ulong lvbase, int size ); | |
9281 | + | |
9282 | +extern void clear_all_vsids( kernel_vars_t *kv ); | |
9283 | +extern void clear_pte_hash_table( kernel_vars_t *kv ); | |
9284 | + | |
9285 | +extern void mtable_reclaim( kernel_vars_t *kv ); | |
9286 | +extern void mtable_tune_alloc_limit( kernel_vars_t *kv, int ramsize_mb ); | |
9287 | + | |
9288 | +static inline void | |
9289 | +make_lvptr_reservation( kernel_vars_t *kv, char *lvptr ) { | |
9290 | + kv->mmu.lvptr_reservation = lvptr; | |
9291 | + kv->mmu.lvptr_reservation_lost = 0; | |
9292 | +} | |
9293 | + | |
9294 | + | |
9295 | +#endif /* __ASSEMBLY__ */ | |
9296 | + | |
9297 | +/* offsets to linux_vsid and linux_vsid_sv (used from assembly) */ | |
9298 | +#define VSID_MYSELF_VIRT 0 | |
9299 | +#define VSID_USER_OFFS 4 | |
9300 | +#define VSID_SV_OFFS 8 | |
9301 | +#define SIZEOF_VSID_ENT (64*4 + 12) | |
9302 | + | |
9303 | +#define VSID_OFFSETS_OK \ | |
9304 | + ((offsetof(vsid_ent_t, linux_vsid) == VSID_USER_OFFS ) || \ | |
9305 | + (offsetof(vsid_ent_t, linux_vsid_sv) == VSID_SV_OFFS ) || \ | |
9306 | + (sizeof(vsid_ent_t) == SIZEOF_VSID_ENT)) | |
9307 | + | |
9308 | +#endif /* _H_MTABLE */ | |
9309 | + | |
9310 | + | |
9311 | --- /dev/null | |
9312 | +++ b/drivers/macintosh/mol/include/osi.h | |
9313 | @@ -0,0 +1,170 @@ | |
9314 | +/* | |
9315 | + * Creation Date: <1999/03/18 03:19:43 samuel> | |
9316 | + * Time-stamp: <2003/12/26 16:58:19 samuel> | |
9317 | + * | |
9318 | + * <os_interface.h> | |
9319 | + * | |
9320 | + * This file includes definitions for drivers | |
9321 | + * running in the "emulated" OS. (Mainly the 'sc' | |
9322 | + * mechanism of communicating) | |
9323 | + * | |
9324 | + * Copyright (C) 1999, 2000, 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) | |
9325 | + * | |
9326 | + * This program is free software; you can redistribute it and/or | |
9327 | + * modify it under the terms of the GNU General Public License | |
9328 | + * as published by the Free Software Foundation | |
9329 | + * | |
9330 | + */ | |
9331 | + | |
9332 | +#ifndef _H_OSI | |
9333 | +#define _H_OSI | |
9334 | + | |
9335 | +/* Magic register values loaded into r3 and r4 before the 'sc' assembly instruction */ | |
9336 | +#define OSI_SC_MAGIC_R3 0x113724FA | |
9337 | +#define OSI_SC_MAGIC_R4 0x77810F9B | |
9338 | + | |
9339 | + | |
9340 | +/************************************************************************/ | |
9341 | +/* Selectors (passed in r5) */ | |
9342 | +/************************************************************************/ | |
9343 | + | |
9344 | +#define OSI_CALL_AVAILABLE 0 | |
9345 | +#define OSI_DEBUGGER 1 /* enter debugger */ | |
9346 | +/* obsolete OSI_LOG_STR 3 */ | |
9347 | +#define OSI_CMOUNT_DRV_VOL 4 /* conditionally mount driver volume */ | |
9348 | +/* obsolete OSI_SCSI_xxx 5-6 */ | |
9349 | +#define OSI_GET_GMT_TIME 7 | |
9350 | +#define OSI_MOUSE_CNTRL 8 | |
9351 | +#define OSI_GET_LOCALTIME 9 /* return time in secs from 01/01/04 */ | |
9352 | + | |
9353 | +#define OSI_ENET_OPEN 10 | |
9354 | +#define OSI_ENET_CLOSE 11 | |
9355 | +#define OSI_ENET_GET_ADDR 12 | |
9356 | +#define OSI_ENET_GET_STATUS 13 | |
9357 | +#define OSI_ENET_CONTROL 14 | |
9358 | +#define OSI_ENET_ADD_MULTI 16 | |
9359 | +#define OSI_ENET_DEL_MULTI 17 | |
9360 | +#define OSI_ENET_GET_PACKET 18 | |
9361 | +#define OSI_ENET_SEND_PACKET 19 | |
9362 | + | |
9363 | +#define OSI_OF_INTERFACE 20 | |
9364 | +#define OSI_OF_TRAP 21 | |
9365 | +#define OSI_OF_RTAS 22 | |
9366 | + | |
9367 | +#define OSI_SCSI_CNTRL 23 | |
9368 | +#define OSI_SCSI_SUBMIT 24 | |
9369 | +#define OSI_SCSI_ACK 25 | |
9370 | + | |
9371 | +#define OSI_GET_MOUSE 26 /* -- r3 status, r4-r8 mouse data */ | |
9372 | +#define OSI_ACK_MOUSE_IRQ 27 /* -- int */ | |
9373 | + | |
9374 | +#define OSI_SET_VMODE 28 /* modeID, depth -- error */ | |
9375 | +#define OSI_GET_VMODE_INFO 29 /* mode, depth -- r3 status, r4-r9 pb */ | |
9376 | +#define OSI_GET_MOUSE_DPI 30 /* -- mouse_dpi */ | |
9377 | + | |
9378 | +#define OSI_SET_VIDEO_POWER 31 | |
9379 | +#define OSI_GET_FB_INFO 32 /* void -- r3 status, r4-r8 video data */ | |
9380 | + | |
9381 | +#define OSI_SOUND_WRITE 33 | |
9382 | +/* #define OSI_SOUND_FORMAT 34 */ | |
9383 | +#define OSI_SOUND_SET_VOLUME 35 | |
9384 | +#define OSI_SOUND_CNTL 36 | |
9385 | +/* obsolete OSI_SOUND call 37 */ | |
9386 | + | |
9387 | +#define OSI_VIDEO_ACK_IRQ 38 | |
9388 | +#define OSI_VIDEO_CNTRL 39 | |
9389 | + | |
9390 | +#define OSI_SOUND_IRQ_ACK 40 | |
9391 | +#define OSI_SOUND_START_STOP 41 | |
9392 | + | |
9393 | +#define OSI_REGISTER_IRQ 42 /* reg_property[0] appl_int -- irq_cookie */ | |
9394 | +/* obsolete OSI_IRQ 43-46 */ | |
9395 | + | |
9396 | +#define OSI_LOG_PUTC 47 /* char -- */ | |
9397 | + | |
9398 | +#define OSI_KBD_CNTRL 50 | |
9399 | +#define OSI_GET_ADB_KEY 51 /* -- adb_keycode (keycode | keycode_id in r4) */ | |
9400 | + | |
9401 | +#define OSI_WRITE_NVRAM_BYTE 52 /* offs, byte -- */ | |
9402 | +#define OSI_READ_NVRAM_BYTE 53 /* offs -- byte */ | |
9403 | + | |
9404 | +#define OSI_EXIT 54 | |
9405 | + | |
9406 | +#define OSI_KEYCODE_TO_ADB 55 /* (keycode | keycode_id) -- adb_keycode */ | |
9407 | +#define OSI_MAP_ADB_KEY 56 /* keycode, adbcode -- */ | |
9408 | +#define OSI_SAVE_KEYMAPPING 57 /* -- */ | |
9409 | +#define OSI_USLEEP 58 /* usecs -- */ | |
9410 | +#define OSI_SET_COLOR 59 /* index value -- */ | |
9411 | + | |
9412 | +#define OSI_PIC_MASK_IRQ 60 /* irq -- */ | |
9413 | +#define OSI_PIC_UNMASK_IRQ 61 /* irq -- */ | |
9414 | +#define OSI_PIC_ACK_IRQ 62 /* irq mask_flag -- */ | |
9415 | +#define OSI_PIC_GET_ACTIVE_IRQ 63 | |
9416 | + | |
9417 | +#define OSI_GET_COLOR 64 /* index -- value */ | |
9418 | + | |
9419 | +/* 65-67 old ablk implementation */ | |
9420 | +#define OSI_IRQTEST 65 | |
9421 | + | |
9422 | +#define OSI_ENET2_OPEN 68 | |
9423 | +#define OSI_ENET2_CLOSE 69 | |
9424 | +#define OSI_ENET2_CNTRL 70 | |
9425 | +#define OSI_ENET2_RING_SETUP 71 | |
9426 | +#define OSI_ENET2_KICK 72 | |
9427 | +#define OSI_ENET2_GET_HWADDR 73 | |
9428 | +#define OSI_ENET2_IRQ_ACK 74 | |
9429 | + | |
9430 | +#define OSI_PROM_IFACE 76 | |
9431 | +#define kPromClose 0 | |
9432 | +#define kPromPeer 1 | |
9433 | +#define kPromChild 2 | |
9434 | +#define kPromParent 3 | |
9435 | +#define kPromPackageToPath 4 | |
9436 | +#define kPromGetPropLen 5 | |
9437 | +#define kPromGetProp 6 | |
9438 | +#define kPromNextProp 7 | |
9439 | +#define kPromSetProp 8 | |
9440 | +#define kPromChangePHandle 9 | |
9441 | + | |
9442 | +#define OSI_PROM_PATH_IFACE 77 | |
9443 | +#define kPromCreateNode 16 | |
9444 | +#define kPromFindDevice 17 | |
9445 | + | |
9446 | +#define OSI_BOOT_HELPER 78 | |
9447 | +#define kBootHAscii2Unicode 32 | |
9448 | +#define kBootHUnicode2Ascii 33 | |
9449 | +#define kBootHGetStrResInd 34 /* key, buf, len -- buf */ | |
9450 | +#define kBootHGetRAMSize 35 /* -- ramsize */ | |
9451 | + | |
9452 | +#define OSI_ABLK_RING_SETUP 79 | |
9453 | +#define OSI_ABLK_CNTRL 80 | |
9454 | +#define OSI_ABLK_DISK_INFO 81 | |
9455 | +#define OSI_ABLK_KICK 82 | |
9456 | +#define OSI_ABLK_IRQ_ACK 83 | |
9457 | +#define OSI_ABLK_SYNC_READ 84 | |
9458 | +#define OSI_ABLK_SYNC_WRITE 85 | |
9459 | +#define OSI_ABLK_BLESS_DISK 86 | |
9460 | + | |
9461 | +#define OSI_EMUACCEL 89 /* EMULATE_xxx, nip -- index */ | |
9462 | +#define OSI_MAPIN_MREGS 90 /* mphys */ | |
9463 | +#define OSI_NVRAM_SIZE 91 | |
9464 | + | |
9465 | +#define OSI_MTICKS_TO_USECS 92 | |
9466 | +#define OSI_USECS_TO_MTICKS 93 | |
9467 | + | |
9468 | +/* obsolete OSI_BLK 94-95 */ | |
9469 | + | |
9470 | +#define OSI_PSEUDO_FS 96 | |
9471 | +#define kPseudoFSOpen 1 | |
9472 | +#define kPseudoFSClose 2 | |
9473 | +#define kPseudoFSGetSize 3 | |
9474 | +#define kPseudoFSRead 4 | |
9475 | +#define kPseudoFSIndex2Name 5 | |
9476 | + | |
9477 | +#define OSI_TTY_PUTC 97 | |
9478 | +#define OSI_TTY_GETC 98 | |
9479 | +#define OSI_TTY_IRQ_ACK 99 | |
9480 | + | |
9481 | +#define NUM_OSI_SELECTORS 100 /* remember to increase this... */ | |
9482 | + | |
9483 | +#endif /* _H_OSI */ | |
9484 | --- /dev/null | |
9485 | +++ b/drivers/macintosh/mol/include/osi_calls.h | |
9486 | @@ -0,0 +1,475 @@ | |
9487 | +/* | |
9488 | + * Creation Date: <2002/06/16 01:40:57 samuel> | |
9489 | + * Time-stamp: <2004/02/23 01:04:31 samuel> | |
9490 | + * | |
9491 | + * <osi_calls.h> | |
9492 | + * | |
9493 | + * OSI call inlines | |
9494 | + * | |
9495 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
9496 | + * | |
9497 | + * This program is free software; you can redistribute it and/or | |
9498 | + * modify it under the terms of the GNU General Public License | |
9499 | + * as published by the Free Software Foundation | |
9500 | + * | |
9501 | + */ | |
9502 | + | |
9503 | +#ifndef _H_OSI_CALLS | |
9504 | +#define _H_OSI_CALLS | |
9505 | + | |
9506 | +#include "osi.h" | |
9507 | + | |
9508 | +/* Old gcc versions have a limit on the number of registers used. | |
9509 | + * Newer gcc versions (gcc 3.3) require that the clobber list does | |
9510 | + * not overlap declared registers. | |
9511 | + */ | |
9512 | +#if __GNUC__ == 2 || ( __GNUC__ == 3 && __GNUC_MINOR__ < 3 ) | |
9513 | +#define SHORT_REGLIST | |
9514 | +#endif | |
9515 | + | |
9516 | + | |
9517 | +/************************************************************************/ | |
9518 | +/* OSI call instantiation macros */ | |
9519 | +/************************************************************************/ | |
9520 | + | |
9521 | +#define dreg(n) __oc_##n __asm__ (#n) | |
9522 | +#define ir(n) "r" (__oc_##n) | |
9523 | +#define rr(n) "=r" (__oc_##n) | |
9524 | + | |
9525 | +#define _oc_head( input_regs... ) \ | |
9526 | +{ \ | |
9527 | + int _ret=0; \ | |
9528 | + { \ | |
9529 | + register unsigned long dreg(r3); \ | |
9530 | + register unsigned long dreg(r4); \ | |
9531 | + register unsigned long dreg(r5) \ | |
9532 | + ,##input_regs ; | |
9533 | + | |
9534 | +#define _oc_syscall( number, extra_ret_regs... ) \ | |
9535 | + __oc_r3 = OSI_SC_MAGIC_R3; \ | |
9536 | + __oc_r4 = OSI_SC_MAGIC_R4; \ | |
9537 | + __oc_r5 = number; \ | |
9538 | + __asm__ __volatile__ ( \ | |
9539 | + "sc " : rr(r3) ,## extra_ret_regs | |
9540 | + | |
9541 | +#define _oc_input( regs... ) \ | |
9542 | + : ir(r3), ir(r4), ir(r5) \ | |
9543 | + , ## regs \ | |
9544 | + : "memory" ); | |
9545 | + | |
9546 | +/* the tail memory clobber is necessary since we violate the strict | |
9547 | + * aliasing rules when we return structs through the registers. | |
9548 | + */ | |
9549 | +#define _oc_tail \ | |
9550 | + asm volatile ( "" : : : "memory" ); \ | |
9551 | + _ret = __oc_r3; \ | |
9552 | + } \ | |
9553 | + return _ret; \ | |
9554 | +} | |
9555 | + | |
9556 | + | |
9557 | +/************************************************************************/ | |
9558 | +/* Alternatives */ | |
9559 | +/************************************************************************/ | |
9560 | + | |
9561 | +#ifdef SHORT_REGLIST | |
9562 | +#ifdef __linux__ | |
9563 | +#define _oc_syscall_r10w6( number, inputregs... ) \ | |
9564 | + __oc_r3 = OSI_SC_MAGIC_R3; \ | |
9565 | + __oc_r4 = OSI_SC_MAGIC_R4; \ | |
9566 | + __oc_r5 = number; \ | |
9567 | + __asm__ __volatile__ ( \ | |
9568 | + "sc \n" \ | |
9569 | + "stw 4,0(10) \n" \ | |
9570 | + "stw 5,4(10) \n" \ | |
9571 | + "stw 6,8(10) \n" \ | |
9572 | + "stw 7,12(10) \n" \ | |
9573 | + "stw 8,16(10) \n" \ | |
9574 | + "stw 9,20(10) \n" \ | |
9575 | + : rr(r3) \ | |
9576 | + : ir(r3), ir(r4), ir(r5), ir(r10) \ | |
9577 | + ,## inputregs \ | |
9578 | + : "memory", \ | |
9579 | + "r4", "r5", "r6", "r7", "r8", "r9" ); | |
9580 | +#endif | |
9581 | +#ifdef __darwin__ | |
9582 | +#define _oc_syscall_r10w6( number, inputregs... ) \ | |
9583 | + __oc_r3 = OSI_SC_MAGIC_R3; \ | |
9584 | + __oc_r4 = OSI_SC_MAGIC_R4; \ | |
9585 | + __oc_r5 = number; \ | |
9586 | + __asm__ __volatile__ ( \ | |
9587 | + "sc \n" \ | |
9588 | + "stw r4,0(r10) \n" \ | |
9589 | + "stw r5,4(r10) \n" \ | |
9590 | + "stw r6,8(r10) \n" \ | |
9591 | + "stw r7,12(r10) \n" \ | |
9592 | + "stw r8,16(r10) \n" \ | |
9593 | + "stw r9,20(r10) \n" \ | |
9594 | + : rr(r3) \ | |
9595 | + : ir(r3), ir(r4), ir(r5), ir(r10) \ | |
9596 | + ,## inputregs \ | |
9597 | + : "memory", \ | |
9598 | + "r4", "r5", "r6", "r7", "r8", "r9" ); | |
9599 | +#endif | |
9600 | +#endif | |
9601 | + | |
9602 | + | |
9603 | +/************************************************************************/ | |
9604 | +/* Common helper functions */ | |
9605 | +/************************************************************************/ | |
9606 | + | |
9607 | +#define _osi_call0( type, name, number ) \ | |
9608 | +type name( void ) \ | |
9609 | + _oc_head() \ | |
9610 | + _oc_syscall( number ) \ | |
9611 | + _oc_input() \ | |
9612 | + _oc_tail | |
9613 | + | |
9614 | +#define _osi_call1( type, name, number, type1, arg1 ) \ | |
9615 | +type name( type1 arg1 ) \ | |
9616 | + _oc_head( dreg(r6) ) \ | |
9617 | + __oc_r6 = (ulong)arg1; \ | |
9618 | + _oc_syscall( number ) \ | |
9619 | + _oc_input( ir(r6) ) \ | |
9620 | + _oc_tail | |
9621 | + | |
9622 | +#define _osi_call2( type, name, number, t1, a1, t2, a2 ) \ | |
9623 | +type name( t1 a1, t2 a2 ) \ | |
9624 | + _oc_head( dreg(r6), dreg(r7) ) \ | |
9625 | + __oc_r6 = (ulong)a1; \ | |
9626 | + __oc_r7 = (ulong)a2; \ | |
9627 | + _oc_syscall( number ) \ | |
9628 | + _oc_input( ir(r6), ir(r7) ) \ | |
9629 | + _oc_tail | |
9630 | + | |
9631 | +#define _osi_call3( type, name, number, t1, a1, t2, a2, t3, a3 ) \ | |
9632 | +type name( t1 a1, t2 a2, t3 a3 ) \ | |
9633 | + _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \ | |
9634 | + __oc_r6 = (ulong)a1; \ | |
9635 | + __oc_r7 = (ulong)a2; \ | |
9636 | + __oc_r8 = (ulong)a3; \ | |
9637 | + _oc_syscall( number ) \ | |
9638 | + _oc_input( ir(r6), ir(r7), ir(r8) ) \ | |
9639 | + _oc_tail | |
9640 | + | |
9641 | +#define _osi_call4( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4 ) \ | |
9642 | +type name( t1 a1, t2 a2, t3 a3, t4 a4 ) \ | |
9643 | + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \ | |
9644 | + __oc_r6 = (ulong)a1; \ | |
9645 | + __oc_r7 = (ulong)a2; \ | |
9646 | + __oc_r8 = (ulong)a3; \ | |
9647 | + __oc_r9 = (ulong)a4; \ | |
9648 | + _oc_syscall( number ) \ | |
9649 | + _oc_input( ir(r6), ir(r7), ir(r8), ir(r9) ) \ | |
9650 | + _oc_tail | |
9651 | + | |
9652 | +#define _osi_call5( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5 ) \ | |
9653 | +type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5 ) \ | |
9654 | + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10) ) \ | |
9655 | + __oc_r6 = (ulong)a1; \ | |
9656 | + __oc_r7 = (ulong)a2; \ | |
9657 | + __oc_r8 = (ulong)a3; \ | |
9658 | + __oc_r9 = (ulong)a4; \ | |
9659 | + __oc_r10 = (ulong)a5; \ | |
9660 | + _oc_syscall( number ) \ | |
9661 | + _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10) ) \ | |
9662 | + _oc_tail | |
9663 | + | |
9664 | +#define _osi_call6( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6 ) \ | |
9665 | +type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6 ) \ | |
9666 | + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10), dreg(r11) )\ | |
9667 | + __oc_r6 = (ulong)a1; \ | |
9668 | + __oc_r7 = (ulong)a2; \ | |
9669 | + __oc_r8 = (ulong)a3; \ | |
9670 | + __oc_r9 = (ulong)a4; \ | |
9671 | + __oc_r10 = (ulong)a5; \ | |
9672 | + __oc_r11 = (ulong)a6; \ | |
9673 | + _oc_syscall( number ) \ | |
9674 | + _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10), ir(r11) ) \ | |
9675 | + _oc_tail | |
9676 | + | |
9677 | + | |
9678 | +/************************************************************************/ | |
9679 | +/* Special */ | |
9680 | +/************************************************************************/ | |
9681 | + | |
9682 | +/* r4 returned in retarg1 pointer */ | |
9683 | +#define _osi_call0_w1( type, name, number, type1, retarg1 ) \ | |
9684 | +type name( type1 retarg1 ) \ | |
9685 | + _oc_head() \ | |
9686 | + _oc_syscall( number, rr(r4) ) \ | |
9687 | + _oc_input() \ | |
9688 | + *retarg1 = __oc_r4; \ | |
9689 | + _oc_tail | |
9690 | + | |
9691 | +#define _osi_call0_w2( type, name, number, type1, retarg1 ) \ | |
9692 | +type name( type1 retarg1 ) \ | |
9693 | + _oc_head() \ | |
9694 | + _oc_syscall( number, rr(r4), rr(r5) ) \ | |
9695 | + _oc_input() \ | |
9696 | + ((ulong*)retarg1)[0] = __oc_r4; \ | |
9697 | + ((ulong*)retarg1)[1] = __oc_r5; \ | |
9698 | + _oc_tail | |
9699 | + | |
9700 | +/* r4-r8 returned in retarg1 pointer */ | |
9701 | +#define _osi_call0_w5( type, name, number, type1, retarg1 ) \ | |
9702 | +type name( type1 retarg1 ) \ | |
9703 | + _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \ | |
9704 | + _oc_syscall( number, \ | |
9705 | + rr(r4), rr(r5), rr(r6), rr(r7), rr(r8) ) \ | |
9706 | + _oc_input() \ | |
9707 | + ((ulong*)retarg1)[0] = __oc_r4; \ | |
9708 | + ((ulong*)retarg1)[1] = __oc_r5; \ | |
9709 | + ((ulong*)retarg1)[2] = __oc_r6; \ | |
9710 | + ((ulong*)retarg1)[3] = __oc_r7; \ | |
9711 | + ((ulong*)retarg1)[4] = __oc_r8; \ | |
9712 | + _oc_tail | |
9713 | + | |
9714 | +/* r4 returned in retarg pointer */ | |
9715 | +#define _osi_call1_w1( type, name, number, t1, a1, t2, retarg ) \ | |
9716 | +type name( t1 a1, t2 retarg ) \ | |
9717 | + _oc_head( dreg(r6) ) \ | |
9718 | + __oc_r6 = (ulong)a1; \ | |
9719 | + _oc_syscall( number, rr(r4) ) \ | |
9720 | + _oc_input( ir(r6) ) \ | |
9721 | + ((ulong*)retarg)[0] = __oc_r4; \ | |
9722 | + _oc_tail | |
9723 | + | |
9724 | +/* r4,r5 returned in retarg1, retarg2 */ | |
9725 | +#define _osi_call1_w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2 ) \ | |
9726 | +type name( t1 a1, t2 retarg1, t3 retarg2 ) \ | |
9727 | + _oc_head( dreg(r6) ) \ | |
9728 | + __oc_r6 = (ulong)a1; \ | |
9729 | + _oc_syscall( number, rr(r4), rr(r5) ) \ | |
9730 | + _oc_input( ir(r6) ) \ | |
9731 | + ((ulong*)retarg1)[0] = __oc_r4; \ | |
9732 | + ((ulong*)retarg2)[0] = __oc_r5; \ | |
9733 | + _oc_tail | |
9734 | + | |
9735 | +/* r4,r5 returned in retarg1, retarg2, retarg3 */ | |
9736 | +#define _osi_call1_w1w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2, t4, retarg3 ) \ | |
9737 | +type name( t1 a1, t2 retarg1, t3 retarg2, t4 retarg3 ) \ | |
9738 | + _oc_head( dreg(r6) ) \ | |
9739 | + __oc_r6 = (ulong)a1; \ | |
9740 | + _oc_syscall( number, rr(r4), rr(r5), rr(r6) ) \ | |
9741 | + _oc_input( ir(r6) ) \ | |
9742 | + ((ulong*)retarg1)[0] = __oc_r4; \ | |
9743 | + ((ulong*)retarg2)[0] = __oc_r5; \ | |
9744 | + ((ulong*)retarg3)[0] = __oc_r6; \ | |
9745 | + _oc_tail | |
9746 | + | |
9747 | +/* r4,r5 returned in retarg pointer */ | |
9748 | +#define _osi_call1_w2( type, name, number, t1, a1, t2, retarg ) \ | |
9749 | +type name( t1 a1, t2 retarg ) \ | |
9750 | + _oc_head( dreg(r6) ) \ | |
9751 | + __oc_r6 = (ulong)a1; \ | |
9752 | + _oc_syscall( number, rr(r4), rr(r5) ) \ | |
9753 | + _oc_input( ir(r6) ) \ | |
9754 | + ((ulong*)retarg)[0] = __oc_r4; \ | |
9755 | + ((ulong*)retarg)[1] = __oc_r5; \ | |
9756 | + _oc_tail | |
9757 | + | |
9758 | +/* r4-r7 returned in retarg pointer */ | |
9759 | +#define _osi_call1_w4( type, name, number, t1, a1, t2, retarg ) \ | |
9760 | +type name( t1 a1, t2 retarg ) \ | |
9761 | + _oc_head( dreg(r6), dreg(r7) ) \ | |
9762 | + __oc_r6 = (ulong)a1; \ | |
9763 | + _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \ | |
9764 | + _oc_input( ir(r6) ) \ | |
9765 | + ((ulong*)retarg)[0] = __oc_r4; \ | |
9766 | + ((ulong*)retarg)[1] = __oc_r5; \ | |
9767 | + ((ulong*)retarg)[2] = __oc_r6; \ | |
9768 | + ((ulong*)retarg)[3] = __oc_r7; \ | |
9769 | + _oc_tail | |
9770 | + | |
9771 | + | |
9772 | +/* r4-r5 returned in retarg pointer */ | |
9773 | +#define _osi_call2_w2( type, name, number, t1, a1, t2, a2, t3, retarg ) \ | |
9774 | +type name( t1 a1, t2 a2, t3 retarg ) \ | |
9775 | + _oc_head( dreg(r6), dreg(r7) ) \ | |
9776 | + __oc_r6 = (ulong)a1; \ | |
9777 | + __oc_r7 = (ulong)a2; \ | |
9778 | + _oc_syscall( number, rr(r4), rr(r5) ) \ | |
9779 | + _oc_input( ir(r6), ir(r7) ) \ | |
9780 | + ((ulong*)retarg)[0] = __oc_r4; \ | |
9781 | + ((ulong*)retarg)[1] = __oc_r5; \ | |
9782 | + _oc_tail | |
9783 | + | |
9784 | +/* r4-r7 returned in retarg pointer */ | |
9785 | +#define _osi_call2_w4( type, name, number, t1, a1, t2, a2, t3, retarg ) \ | |
9786 | +type name( t1 a1, t2 a2, t3 retarg ) \ | |
9787 | + _oc_head( dreg(r6), dreg(r7) ) \ | |
9788 | + __oc_r6 = (ulong)a1; \ | |
9789 | + __oc_r7 = (ulong)a2; \ | |
9790 | + _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \ | |
9791 | + _oc_input( ir(r6), ir(r7) ) \ | |
9792 | + ((ulong*)retarg)[0] = __oc_r4; \ | |
9793 | + ((ulong*)retarg)[1] = __oc_r5; \ | |
9794 | + ((ulong*)retarg)[2] = __oc_r6; \ | |
9795 | + ((ulong*)retarg)[3] = __oc_r7; \ | |
9796 | + _oc_tail | |
9797 | + | |
9798 | +#ifdef SHORT_REGLIST | |
9799 | +/* r4-r9 returned in retarg pointer */ | |
9800 | +#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \ | |
9801 | +type name( t1 a1, t2 a2, t3 retarg ) \ | |
9802 | + _oc_head( dreg(r6), dreg(r7), dreg(r10) ) \ | |
9803 | + __oc_r6 = (ulong)a1; \ | |
9804 | + __oc_r7 = (ulong)a2; \ | |
9805 | + __oc_r10 = (ulong)retarg; \ | |
9806 | + _oc_syscall_r10w6( number, ir(r6), ir(r7) ) \ | |
9807 | + _oc_tail | |
9808 | + | |
9809 | +#else /* SHORT_REGLIST */ | |
9810 | + | |
9811 | +/* r4-r9 returned in retarg pointer */ | |
9812 | +#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \ | |
9813 | +type name( t1 a1, t2 a2, t3 retarg ) \ | |
9814 | + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \ | |
9815 | + __oc_r6 = (ulong)a1; \ | |
9816 | + __oc_r7 = (ulong)a2; \ | |
9817 | + _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7), rr(r8), rr(r9) ) \ | |
9818 | + _oc_input( ir(r6), ir(r7) ) \ | |
9819 | + ((ulong*)retarg)[0] = __oc_r4; \ | |
9820 | + ((ulong*)retarg)[1] = __oc_r5; \ | |
9821 | + ((ulong*)retarg)[2] = __oc_r6; \ | |
9822 | + ((ulong*)retarg)[3] = __oc_r7; \ | |
9823 | + ((ulong*)retarg)[4] = __oc_r8; \ | |
9824 | + ((ulong*)retarg)[5] = __oc_r9; \ | |
9825 | + _oc_tail | |
9826 | + | |
9827 | +#endif /* SHORT_REGLIST */ | |
9828 | + | |
9829 | + | |
9830 | +/************************************************************************/ | |
9831 | +/* OSI call inlines */ | |
9832 | +/************************************************************************/ | |
9833 | + | |
9834 | +static inline _osi_call1( int, OSI_CallAvailable, OSI_CALL_AVAILABLE, int, osi_num ); | |
9835 | + | |
9836 | +static inline _osi_call1( int, OSI_PutC, OSI_LOG_PUTC, int, ch ); | |
9837 | + | |
9838 | +static inline _osi_call1( int, OSI_Debugger, OSI_DEBUGGER, int, num ); | |
9839 | +static inline _osi_call0( int, OSI_Exit, OSI_EXIT ); | |
9840 | + | |
9841 | +/* misc */ | |
9842 | +static inline _osi_call0( ulong, OSI_GetLocalTime, OSI_GET_LOCALTIME ); | |
9843 | +static inline _osi_call0( ulong, OSI_GetGMTTime, OSI_GET_GMT_TIME ); | |
9844 | +static inline _osi_call1( int, OSI_USleep, OSI_USLEEP, int, usecs ); | |
9845 | + | |
9846 | +/* NVRAM */ | |
9847 | +static inline _osi_call0( int, OSI_NVRamSize, OSI_NVRAM_SIZE ); | |
9848 | +static inline _osi_call1( int, OSI_ReadNVRamByte, OSI_READ_NVRAM_BYTE, int, offs ); | |
9849 | +static inline _osi_call2( int, OSI_WriteNVRamByte, OSI_WRITE_NVRAM_BYTE, int, offs, | |
9850 | + unsigned char, ch ); | |
9851 | + | |
9852 | +/* keyboard stuff */ | |
9853 | +static inline _osi_call0_w1( int, OSI_GetAdbKey2, OSI_GET_ADB_KEY, int *, raw_key ); | |
9854 | +static inline _osi_call1( int, OSI_KbdCntrl, OSI_KBD_CNTRL, int, cmd ); | |
9855 | + | |
9856 | +static inline int OSI_GetAdbKey( void ) | |
9857 | + { int dummy_raw_key; return OSI_GetAdbKey2( &dummy_raw_key ); } | |
9858 | +static inline _osi_call2( int, OSI_MapAdbKey, OSI_MAP_ADB_KEY, int, keycode, int, adbkey ) | |
9859 | +static inline _osi_call1( int, OSI_KeycodeToAdb, OSI_KEYCODE_TO_ADB, int, keycode ); | |
9860 | +static inline _osi_call0( int, OSI_SaveKeymapping, OSI_SAVE_KEYMAPPING ); | |
9861 | + | |
9862 | +/* mouse support */ | |
9863 | +struct osi_mouse; | |
9864 | +static inline _osi_call0_w5( int, OSI_GetMouse, OSI_GET_MOUSE, struct osi_mouse *, ret ); | |
9865 | +static inline _osi_call0( int, OSI_GetMouseDPI, OSI_GET_MOUSE_DPI ); | |
9866 | + | |
9867 | +/* video */ | |
9868 | +static inline _osi_call2( int, OSI_SetVMode_, OSI_SET_VMODE, int, mode, int, depth_mode ); | |
9869 | +struct osi_get_vmode_info; | |
9870 | +static inline _osi_call2_w6( int, OSI_GetVModeInfo_, OSI_GET_VMODE_INFO, int, mode, int, depth_mode, | |
9871 | + struct osi_get_vmode_info *, ret ); | |
9872 | +static inline _osi_call1( int, OSI_SetVPowerState, OSI_SET_VIDEO_POWER, int, power_state ); | |
9873 | +static inline _osi_call2( int, OSI_SetColor, OSI_SET_COLOR, int, index, int, rgb ); | |
9874 | +static inline _osi_call0_w1( int, OSI_VideoAckIRQ, OSI_VIDEO_ACK_IRQ, int *, events ); | |
9875 | + | |
9876 | +static inline void OSI_RefreshPalette( void ) { OSI_SetColor(-1,0); } | |
9877 | + | |
9878 | +/* PIC (mac-io replacement) */ | |
9879 | +static inline _osi_call1( int, OSI_PICMaskIRQ, OSI_PIC_MASK_IRQ, int, irq ); | |
9880 | +static inline _osi_call1( int, OSI_PICUnmaskIRQ, OSI_PIC_UNMASK_IRQ, int, irq ); | |
9881 | +static inline _osi_call2( int, OSI_PICAckIRQ, OSI_PIC_ACK_IRQ, int, irq, int, mask_it ); | |
9882 | +static inline _osi_call0( int, OSI_PICGetActiveIRQ, OSI_PIC_GET_ACTIVE_IRQ ); | |
9883 | + | |
9884 | +/* sound */ | |
9885 | +static inline _osi_call1( int, OSI_SoundCntl, OSI_SOUND_CNTL, int, cmd ); | |
9886 | +static inline _osi_call2( int, OSI_SoundCntl1, OSI_SOUND_CNTL, int, cmd, int, p1 ); | |
9887 | +static inline _osi_call3( int, OSI_SoundCntl2, OSI_SOUND_CNTL, int, cmd, int, p1, int, p2 ); | |
9888 | +static inline _osi_call0_w2( int, OSI_SoundIRQAck, OSI_SOUND_IRQ_ACK, ulong *, timestamp ); | |
9889 | +static inline _osi_call3( int, OSI_SoundWrite, OSI_SOUND_WRITE, int, physbuf, int, len, int, restart ); | |
9890 | +static inline _osi_call3( int, OSI_SoundSetVolume, OSI_SOUND_SET_VOLUME, int, hwvol, int, speakervol, int, mute ); | |
9891 | + | |
9892 | +/* async block driver */ | |
9893 | +struct ablk_disk_info; | |
9894 | +static inline _osi_call2_w4( int, OSI_ABlkDiskInfo, OSI_ABLK_DISK_INFO, int, channel, int, unit, | |
9895 | + struct ablk_disk_info *, retinfo ); | |
9896 | +static inline _osi_call1( int, OSI_ABlkKick, OSI_ABLK_KICK, int, channel ); | |
9897 | +static inline _osi_call1_w1w1w1( int, OSI_ABlkIRQAck, OSI_ABLK_IRQ_ACK, int, channel, int *, req_count, | |
9898 | + int *, active, int *, events ); | |
9899 | +static inline _osi_call3( int, OSI_ABlkRingSetup, OSI_ABLK_RING_SETUP, int, channel, int, mphys, int, n_el ); | |
9900 | +static inline _osi_call2( int, OSI_ABlkCntrl, OSI_ABLK_CNTRL, int, channel, int, cmd ); | |
9901 | +static inline _osi_call3( int, OSI_ABlkCntrl1, OSI_ABLK_CNTRL, int, channel, int, cmd, int, param ); | |
9902 | +static inline _osi_call5( int, OSI_ABlkSyncRead, OSI_ABLK_SYNC_READ, int, channel, int, unit, | |
9903 | + int, blk, ulong, mphys, int, size ); | |
9904 | +static inline _osi_call5( int, OSI_ABlkSyncWrite, OSI_ABLK_SYNC_WRITE, int, channel, int, unit, | |
9905 | + int, blk, ulong, mphys, int, size ); | |
9906 | +static inline _osi_call2( int, OSI_ABlkBlessDisk, OSI_ABLK_BLESS_DISK, int, channel, int, unit ); | |
9907 | + | |
9908 | +static inline _osi_call0( int, OSI_CMountDrvVol, OSI_CMOUNT_DRV_VOL ); | |
9909 | + | |
9910 | +/* enet2 */ | |
9911 | +static inline _osi_call0( int, OSI_Enet2Open, OSI_ENET2_OPEN ); | |
9912 | +static inline _osi_call0( int, OSI_Enet2Close, OSI_ENET2_CLOSE ); | |
9913 | +static inline _osi_call3( int, OSI_Enet2RingSetup, OSI_ENET2_RING_SETUP, int, which_ring, | |
9914 | + int, ring_mphys, int, n_el ); | |
9915 | +static inline _osi_call2( int, OSI_Enet2Cntrl1, OSI_ENET2_CNTRL, int, cmd, int, param ); | |
9916 | +static inline _osi_call1( int, OSI_Enet2Cntrl, OSI_ENET2_CNTRL, int, cmd ); | |
9917 | +static inline _osi_call0( int, OSI_Enet2Kick, OSI_ENET2_KICK ); | |
9918 | + | |
9919 | +static inline _osi_call0_w2( int, OSI_Enet2GetHWAddr__, OSI_ENET2_GET_HWADDR, ulong *, retbuf ); | |
9920 | +static inline int OSI_Enet2GetHWAddr( unsigned char *addr ) { | |
9921 | + int ret; | |
9922 | + ulong buf[2]; | |
9923 | + | |
9924 | + ret = OSI_Enet2GetHWAddr__( buf ); | |
9925 | + | |
9926 | + ((ulong*)addr)[0] = buf[0]; | |
9927 | + ((ushort*)addr)[2] = (buf[1] >> 16); | |
9928 | + return ret; | |
9929 | +} | |
9930 | +static inline _osi_call2( int, OSI_Enet2IRQAck, OSI_ENET2_IRQ_ACK, int, irq_enable, int, rx_head ); | |
9931 | + | |
9932 | +/* PROM (device-tree) */ | |
9933 | +static inline _osi_call2( int, OSI_PromIface, OSI_PROM_IFACE, int, what, int, ph ); | |
9934 | +static inline _osi_call3( int, OSI_PromIface1, OSI_PROM_IFACE, int, what, int, ph, int, p1 ); | |
9935 | +static inline _osi_call4( int, OSI_PromIface2, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2 ); | |
9936 | +static inline _osi_call5( int, OSI_PromIface3, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2, int, p3 ); | |
9937 | +static inline _osi_call2( int, OSI_PromPathIface, OSI_PROM_PATH_IFACE, int, what, const char *, p ); | |
9938 | + | |
9939 | +/* emulation acceleration */ | |
9940 | +static inline _osi_call1( int, OSI_MapinMregs, OSI_MAPIN_MREGS, ulong, mphys ); | |
9941 | +static inline _osi_call3( int, OSI_EmuAccel, OSI_EMUACCEL, int, emuaccel_flags, int, param, int, inst_addr ); | |
9942 | + | |
9943 | +/* timer frequency */ | |
9944 | +static inline _osi_call1( int, OSI_MticksToUsecs, OSI_MTICKS_TO_USECS, ulong, mticks ); | |
9945 | +static inline _osi_call1( int, OSI_UsecsToMticks, OSI_USECS_TO_MTICKS, ulong, usecs ); | |
9946 | + | |
9947 | +/* fb info */ | |
9948 | +struct osi_fb_info; | |
9949 | +static inline _osi_call0_w5( int, OSI_GetFBInfo, OSI_GET_FB_INFO, struct osi_fb_info *, retinfo ); | |
9950 | + | |
9951 | +/* SCSI */ | |
9952 | +static inline _osi_call0( int, OSI_SCSIAck, OSI_SCSI_ACK ); | |
9953 | +static inline _osi_call1( int, OSI_SCSISubmit, OSI_SCSI_SUBMIT, int, req_mphys ); | |
9954 | +static inline _osi_call2( int, OSI_SCSIControl, OSI_SCSI_CNTRL, int, sel, int, param ); | |
9955 | + | |
9956 | +/* TTY */ | |
9957 | +static inline _osi_call0( int, OSI_TTYGetc, OSI_TTY_GETC ); | |
9958 | +static inline _osi_call1( int, OSI_TTYPutc, OSI_TTY_PUTC, int, ch ); | |
9959 | +static inline _osi_call0( int, OSI_TTYIRQAck, OSI_TTY_IRQ_ACK ); | |
9960 | + | |
9961 | +#endif /* _H_OSI_CALLS */ | |
9962 | --- /dev/null | |
9963 | +++ b/drivers/macintosh/mol/include/performance.h | |
9964 | @@ -0,0 +1,71 @@ | |
9965 | +/* | |
9966 | + * Creation Date: <2001/04/01 00:44:40 samuel> | |
9967 | + * Time-stamp: <2003/01/27 02:42:03 samuel> | |
9968 | + * | |
9969 | + * <performance.h> | |
9970 | + * | |
9971 | + * performance counters | |
9972 | + * | |
9973 | + * Copyright (C) 2001, 2002 Samuel Rydh (samuel@ibrium.se) | |
9974 | + * | |
9975 | + * This program is free software; you can redistribute it and/or | |
9976 | + * modify it under the terms of the GNU General Public License | |
9977 | + * as published by the Free Software Foundation | |
9978 | + * | |
9979 | + */ | |
9980 | + | |
9981 | +#ifndef _H_PERFORMANCE | |
9982 | +#define _H_PERFORMANCE | |
9983 | + | |
9984 | +typedef struct { | |
9985 | + char *name; | |
9986 | + unsigned long *ctrptr; | |
9987 | +} perf_info_t; | |
9988 | + | |
9989 | +extern perf_info_t g_perf_info_table[]; | |
9990 | + | |
9991 | +#if defined(PERFORMANCE_INFO) && !defined(PERFORMANCE_INFO_LIGHT) | |
9992 | +#define BUMP(x) do { extern int gPerf__##x; gPerf__##x++; } while(0) | |
9993 | +#define BUMP_N(x,n) do { extern int gPerf__##x; gPerf__##x+=(n); } while(0) | |
9994 | +#else | |
9995 | +#define BUMP(x) do {} while(0) | |
9996 | +#define BUMP_N(x,n) do {} while(0) | |
9997 | +#endif | |
9998 | + | |
9999 | + | |
10000 | +/************************************************************************/ | |
10001 | +/* tick counters */ | |
10002 | +/************************************************************************/ | |
10003 | + | |
10004 | +#ifdef PERFORMANCE_INFO | |
10005 | + | |
10006 | +#define TICK_CNTR_PUSH( kv ) do { \ | |
10007 | + int ind = (kv)->num_acntrs; \ | |
10008 | + acc_counter_t *c = &(kv)->acntrs[ind]; \ | |
10009 | + if( ind < MAX_ACC_CNTR_DEPTH ) { \ | |
10010 | + c->subticks=0; \ | |
10011 | + (kv)->num_acntrs++; \ | |
10012 | + asm volatile( "mftb %0" : "=r" (c->stamp) : ); \ | |
10013 | + } \ | |
10014 | +} while(0) | |
10015 | + | |
10016 | +#define TICK_CNTR_POP( kv, name ) do { \ | |
10017 | + int ind = (kv)->num_acntrs; \ | |
10018 | + ulong now, ticks; \ | |
10019 | + asm volatile( "mftb %0" : "=r" (now) : ); \ | |
10020 | + if( --ind >= 0 ) { \ | |
10021 | + acc_counter_t *c = &(kv)->acntrs[ind]; \ | |
10022 | + (kv)->num_acntrs = ind; \ | |
10023 | + ticks = now - c->stamp - c->subticks; \ | |
10024 | + BUMP_N( name##_ticks, ticks ); \ | |
10025 | + if( ind ) \ | |
10026 | + (kv)->acntrs[ind-1].subticks += ticks; \ | |
10027 | + } \ | |
10028 | +} while(0) | |
10029 | + | |
10030 | +#else | |
10031 | +#define TICK_CNTR_PUSH( kv ) do {} while(0) | |
10032 | +#define TICK_CNTR_POP( kv, name ) do {} while(0) | |
10033 | +#endif | |
10034 | + | |
10035 | +#endif /* _H_PERFORMANCE */ | |
10036 | --- /dev/null | |
10037 | +++ b/drivers/macintosh/mol/include/platform.h | |
10038 | @@ -0,0 +1,73 @@ | |
10039 | +/* | |
10040 | + * Creation Date: <2001/12/29 19:46:46 samuel> | |
10041 | + * Time-stamp: <2004/02/07 16:51:57 samuel> | |
10042 | + * | |
10043 | + * <platform.h> | |
10044 | + * | |
10045 | + * Misc definitions needed on certain platforms | |
10046 | + * | |
10047 | + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
10048 | + * | |
10049 | + * This program is free software; you can redistribute it and/or | |
10050 | + * modify it under the terms of the GNU General Public License | |
10051 | + * as published by the Free Software Foundation | |
10052 | + * | |
10053 | + */ | |
10054 | + | |
10055 | +#ifndef _H_PLATFORM | |
10056 | +#define _H_PLATFORM | |
10057 | + | |
10058 | +#ifndef NULL | |
10059 | +#define NULL 0 | |
10060 | +#endif /* NULL */ | |
10061 | + | |
10062 | +typedef unsigned long long ullong; | |
10063 | +typedef long long llong; | |
10064 | + | |
10065 | +typedef signed char s8; | |
10066 | +typedef unsigned char u8; | |
10067 | +typedef signed short s16; | |
10068 | +typedef unsigned short u16; | |
10069 | +typedef signed int s32; | |
10070 | +typedef unsigned int u32; | |
10071 | +typedef signed long long s64; | |
10072 | +typedef unsigned long long u64; | |
10073 | + | |
10074 | +#define TO_ULLONG( hi, lo ) (((ullong)(hi)<< 32 ) | (lo) ) | |
10075 | +#define TO_LLONG( hi, lo ) (((llong)(hi)<< 32 ) | (lo) ) | |
10076 | + | |
10077 | +#ifndef TEMP_FAILURE_RETRY | |
10078 | +# define TEMP_FAILURE_RETRY(expression) \ | |
10079 | + (__extension__ \ | |
10080 | + ({ long int __result; \ | |
10081 | + do __result = (long int) (expression); \ | |
10082 | + while (__result == -1L && errno == EINTR); \ | |
10083 | + __result; })) | |
10084 | +#endif | |
10085 | + | |
10086 | +/* | |
10087 | + * Allow us to mark functions as 'deprecated' and have gcc emit a nice | |
10088 | + * warning for each use, in hopes of speeding the functions removal. | |
10089 | + * Usage is: | |
10090 | + * int __deprecated foo(void) | |
10091 | + */ | |
10092 | +#if __GNUC__ == 2 && __GNUC_MINOR__ < 96 | |
10093 | +#define __builtin_expect(x, expected_value) (x) | |
10094 | +#endif | |
10095 | + | |
10096 | +#define likely(x) __builtin_expect((x),1) | |
10097 | +#define unlikely(x) __builtin_expect((x),0) | |
10098 | + | |
10099 | +#ifndef HAVE_CLEARENV | |
10100 | +static inline int clearenv( void ) { extern char **environ; environ=NULL; return 0; } | |
10101 | +#endif | |
10102 | + | |
10103 | +#ifdef __darwin__ | |
10104 | +#define ARCH_STR "osx" | |
10105 | +#endif | |
10106 | + | |
10107 | +#ifdef __linux__ | |
10108 | +#define ARCH_STR "linux" | |
10109 | +#endif | |
10110 | + | |
10111 | +#endif /* _H_PLATFORM */ | |
10112 | --- /dev/null | |
10113 | +++ b/drivers/macintosh/mol/include/processor.h | |
10114 | @@ -0,0 +1,409 @@ | |
10115 | +/* | |
10116 | + * Creation Date: <2000/10/29 01:43:29 samuel> | |
10117 | + * Time-stamp: <2003/07/27 22:37:49 samuel> | |
10118 | + * | |
10119 | + * <processor.h> | |
10120 | + * | |
10121 | + * Extract from <asm/processor.h> | |
10122 | + * | |
10123 | + * | |
10124 | + * This program is free software; you can redistribute it and/or | |
10125 | + * modify it under the terms of the GNU General Public License | |
10126 | + * as published by the Free Software Foundation | |
10127 | + * | |
10128 | + */ | |
10129 | + | |
10130 | +#ifndef _H_PROCESSOR | |
10131 | +#define _H_PROCESSOR | |
10132 | + | |
10133 | + | |
10134 | +#define PTE0_VSID(s) (((s)>>7) & 0xffffff) | |
10135 | +#define PTE0_V BIT(0) | |
10136 | +#define PTE0_H BIT(25) | |
10137 | +#define PTE0_API 0x3f | |
10138 | + | |
10139 | +#define PTE1_R BIT(23) | |
10140 | +#define PTE1_C BIT(24) | |
10141 | +#define PTE1_W BIT(25) | |
10142 | +#define PTE1_I BIT(26) | |
10143 | +#define PTE1_M BIT(27) | |
10144 | +#define PTE1_G BIT(28) | |
10145 | +#ifdef CONFIG_AMIGAONE | |
10146 | +/* Memory coherence locks up A1 compatible systems. */ | |
10147 | +#define PTE1_WIMG (PTE1_W | PTE1_I | PTE1_G) | |
10148 | +#else | |
10149 | +#define PTE1_WIMG (PTE1_W | PTE1_I | PTE1_M | PTE1_G) | |
10150 | +#endif | |
10151 | +#define PTE1_PP 0x3 | |
10152 | +#define PTE1_RPN (~0xfffUL) | |
10153 | + | |
10154 | +#define VSID_Ks BIT(1) | |
10155 | +#define VSID_Kp BIT(2) | |
10156 | +#define VSID_N BIT(3) | |
10157 | + | |
10158 | + | |
10159 | + | |
10160 | +#ifndef MSR_VEC | |
10161 | + | |
10162 | +#define MSR_VEC (1<<25) /* 6: Enable AltiVec */ | |
10163 | +#define MSR_POW (1<<18) /* 13: Enable Power Management */ | |
10164 | +#define MSR_TGPR (1<<17) /* 14: TLB Update registers in use */ | |
10165 | +#define MSR_ILE (1<<16) /* 15: Interrupt Little Endian */ | |
10166 | +#define MSR_EE (1<<15) /* 16: External Interrupt Enable */ | |
10167 | +#define MSR_PR (1<<14) /* 17: Privilege Level */ | |
10168 | +#define MSR_FP (1<<13) /* 18: Floating Point enable */ | |
10169 | +#define MSR_ME (1<<12) /* 19: Machine Check Enable */ | |
10170 | +#define MSR_FE0 (1<<11) /* 20: Floating Exception mode 0 */ | |
10171 | +#define MSR_SE (1<<10) /* 21: Single Step */ | |
10172 | +#define MSR_BE (1<<9) /* 22: Branch Trace */ | |
10173 | +#define MSR_FE1 (1<<8) /* 23: Floating Exception mode 1 */ | |
10174 | +#define MSR_IP (1<<6) /* 25: Exception prefix 0x000/0xFFF */ | |
10175 | +#define MSR_IR (1<<5) /* 26: Instruction Relocate */ | |
10176 | +#define MSR_DR (1<<4) /* 27: Data Relocate */ | |
10177 | +#define MSR_PE (1<<2) /* 29: Performance Monitor Flag */ | |
10178 | +#define MSR_RI (1<<1) /* 30: Recoverable Exception */ | |
10179 | +#define MSR_LE (1<<0) /* 31: Little Endian */ | |
10180 | + | |
10181 | +#endif /* MSR_VEC */ | |
10182 | + | |
10183 | +#ifndef S_SPRG0 | |
10184 | + | |
10185 | +#define NUM_SPRS 1024 | |
10186 | +//#define S_XER 1 | |
10187 | +#define S_RTCU_R 4 /* 601 RTC Upper/Lower (Reading) */ | |
10188 | +#define S_RTCL_R 5 | |
10189 | +//#define S_LR 8 | |
10190 | +//#define S_CTR 9 | |
10191 | +#define S_DSISR 18 /* Source Instruction Service Register */ | |
10192 | +#define S_DAR 19 /* Data Address Register */ | |
10193 | +#define S_RTCU_W 20 /* 601 RTC Upper/Lower (Writing) */ | |
10194 | +#define S_RTCL_W 21 | |
10195 | +#define S_DEC 22 /* Decrementer Register */ | |
10196 | +#define S_SDR1 25 /* Table Search Description Register */ | |
10197 | +#define S_SRR0 26 /* Save and Restore Register 0 */ | |
10198 | +#define S_SRR1 27 /* Save and Restore Register 1 */ | |
10199 | +#define S_VRSAVE 256 /* (AltiVec) Vector Register Save Register */ | |
10200 | +#define S_TBRL 268 /* Time base Upper/Lower (Reading) */ | |
10201 | +#define S_TBRU 269 | |
10202 | +#define S_SPRG0 272 /* SPR General 0-3 */ | |
10203 | +#define S_SPRG1 273 | |
10204 | +#define S_SPRG2 274 | |
10205 | +#define S_SPRG3 275 | |
10206 | +#define S_SPRG4 276 /* SPR General 4-7 (7445/7455) */ | |
10207 | +#define S_SPRG5 277 | |
10208 | +#define S_SPRG6 278 | |
10209 | +#define S_SPRG7 279 | |
10210 | +#define S_EAR 282 /* External Access Register */ | |
10211 | +#define S_TBWL 284 /* Time base Upper/Lower (Writing) */ | |
10212 | +#define S_TBWU 285 | |
10213 | +#define S_PVR 287 /* Processor Version Register */ | |
10214 | +#define S_IBAT0U 528 | |
10215 | +#define S_IBAT0L 529 | |
10216 | +#define S_IBAT1U 530 | |
10217 | +#define S_IBAT1L 531 | |
10218 | +#define S_IBAT2U 532 | |
10219 | +#define S_IBAT2L 533 | |
10220 | +#define S_IBAT3U 534 | |
10221 | +#define S_IBAT3L 535 | |
10222 | +#define S_DBAT0U 536 | |
10223 | +#define S_DBAT0L 537 | |
10224 | +#define S_DBAT1U 538 | |
10225 | +#define S_DBAT1L 539 | |
10226 | +#define S_DBAT2U 540 | |
10227 | +#define S_DBAT2L 541 | |
10228 | +#define S_DBAT3U 542 | |
10229 | +#define S_DBAT3L 543 | |
10230 | +#define S_UMMCR2 928 | |
10231 | +#define S_UPMC5 929 /* User Performance Monitor Counter Register */ | |
10232 | +#define S_UPMC6 930 | |
10233 | +#define S_UBAMR 935 | |
10234 | +#define S_UMMCR0 936 /* User Monitor Mode Control Register */ | |
10235 | +#define S_UPMC1 937 | |
10236 | +#define S_UPMC2 938 | |
10237 | +#define S_USIAR 939 /* User Sampled Instruction Address Register */ | |
10238 | +#define S_UMMCR1 940 | |
10239 | +#define S_UPMC3 941 | |
10240 | +#define S_UPMC4 942 /* User Performance Monitor Counter Register 4 */ | |
10241 | +#define S_USDAR 943 /* User Sampled Data Address Register */ | |
10242 | +#define S_MMCR2 944 /* Monitor Mode Control Register */ | |
10243 | +#define S_PMC5 945 | |
10244 | +#define S_PMC6 946 | |
10245 | +#define S_BAMR 951 /* Breakpoint Address Mask Register (74xx) */ | |
10246 | +#define S_MMCR0 952 /* Monitor Mode Control Register 0 */ | |
10247 | +#define S_PMC1 953 /* Performance Counter Register */ | |
10248 | +#define S_PMC2 954 | |
10249 | +#define S_SIAR 955 /* Sampled Instruction Address Register */ | |
10250 | +#define S_MMCR1 956 | |
10251 | +#define S_PMC3 957 | |
10252 | +#define S_PMC4 958 | |
10253 | +#define S_SDAR 959 /* Sampled Data Address Register */ | |
10254 | +#define S_DMISS 976 /* 603 */ | |
10255 | +#define S_DCMP 977 /* 603 */ | |
10256 | +#define S_HASH1 978 /* 603 */ | |
10257 | +#define S_HASH2 979 /* 603 */ | |
10258 | +#define S_IMISS 980 /* 603 */ | |
10259 | +#define S_TLBMISS 980 /* 7445/7455 */ | |
10260 | +#define S_ICMP 981 /* 603 */ | |
10261 | +#define S_PTEHI 981 /* 7445/7455 */ | |
10262 | +#define S_RPA 982 /* 603 */ | |
10263 | +#define S_PTELO 982 /* 7445/7455 */ | |
10264 | +#define S_L3PM 983 /* L3 Private Memory Address Control Register */ | |
10265 | +#define S_L3ITCR0 984 /* ??? */ | |
10266 | +#define S_L3OHCR 1000 /* ??? */ | |
10267 | +#define S_L3ITCR1 1001 /* ??? */ | |
10268 | +#define S_L3ITCR2 1002 /* ??? */ | |
10269 | +#define S_L3ITCR3 1003 /* ??? */ | |
10270 | +#define S_HID0 1008 /* Hardware Implementation Registers */ | |
10271 | +#define S_HID1 1009 | |
10272 | +#define S_HID2 1010 | |
10273 | +#define S_IABR S_HID2 /* HID2 - Instruction Address Breakpoint Register */ | |
10274 | +#define S_ICTRL 1011 /* HID3 - Instruction Cache & Interrupt control reg */ | |
10275 | +#define S_HID4 1012 /* HID4 - Instruction Address Compare 1 (?) */ | |
10276 | +#define S_HID5 1013 | |
10277 | +#define S_DABR S_HID5 /* HID5 - Data Address Breakpoint */ | |
10278 | +#define S_MSSCR0 1014 /* HID6 - Memory Subsystem Control Register 0 */ | |
10279 | +#define S_MSSCR1 1015 /* HID7 - Memory Subsystem Control Register 1 */ | |
10280 | +#define S_LDSTCR 1016 /* HID8 - Load/Store Control Register */ | |
10281 | +#define S_L2CR 1017 /* HID9 - Level 2 Cache Control Regsiter */ | |
10282 | +#define S_L3CR 1018 /* HID10 - Level 3 Cache Control Regsiter (7450) */ | |
10283 | +#define S_HID11 1019 | |
10284 | +#define S_ICTC S_HID11 /* HID11 - Instruction Cache Throttling Control Reg */ | |
10285 | +#define S_ICCR S_HID11 /* Instruction Cache Cacheability Reigster */ | |
10286 | +#define S_THRM1 1020 /* HID12 - Thermal Management Register 1 */ | |
10287 | +#define S_THRM2 1021 /* HID13 - Thermal Management Register 2 */ | |
10288 | +#define S_THRM3 1022 /* HID14 - Thermal Management Register 3 */ | |
10289 | +#define S_HID15 1023 | |
10290 | +#define S_PIR S_HID15 /* HID15 - Processor Identification Register */ | |
10291 | + | |
10292 | +#endif /* S_SPRG0 */ | |
10293 | + | |
10294 | +/* the kernel might define these too... */ | |
10295 | +#if !defined(__KERNEL__) || defined(__ASSEMBLY__) | |
10296 | + | |
10297 | +/* Floating Point Status and Control Register (FPSCR) Fields */ | |
10298 | +#define FPSCR_FX 0x80000000 /* FPU exception summary */ | |
10299 | +#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */ | |
10300 | +#define FPSCR_VX 0x20000000 /* Invalid operation summary */ | |
10301 | +#define FPSCR_OX 0x10000000 /* Overflow exception summary */ | |
10302 | +#define FPSCR_UX 0x08000000 /* Underflow exception summary */ | |
10303 | +#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */ | |
10304 | +#define FPSCR_XX 0x02000000 /* Inexact exception summary */ | |
10305 | +#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */ | |
10306 | +#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */ | |
10307 | +#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */ | |
10308 | +#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */ | |
10309 | +#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */ | |
10310 | +#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */ | |
10311 | +#define FPSCR_FR 0x00040000 /* Fraction rounded */ | |
10312 | +#define FPSCR_FI 0x00020000 /* Fraction inexact */ | |
10313 | +#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */ | |
10314 | +#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */ | |
10315 | +#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */ | |
10316 | +#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */ | |
10317 | +#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */ | |
10318 | +#define FPSCR_VE 0x00000080 /* Invalid op exception enable */ | |
10319 | +#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */ | |
10320 | +#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */ | |
10321 | +#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */ | |
10322 | +#define FPSCR_XE 0x00000008 /* FP inexact exception enable */ | |
10323 | +#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */ | |
10324 | +#define FPSCR_RN 0x00000003 /* FPU rounding control */ | |
10325 | + | |
10326 | +/* SPR_HID0 */ | |
10327 | +#define HID0_EMCP (1<<31) /* Enable Machine Check pin */ | |
10328 | +#define HID0_EBA (1<<29) /* Enable Bus Address Parity */ | |
10329 | +#define HID0_EBD (1<<28) /* Enable Bus Data Parity */ | |
10330 | +#define HID0_SBCLK (1<<27) | |
10331 | +#define HID0_EICE (1<<26) | |
10332 | +#define HID0_ECLK (1<<25) | |
10333 | +#define HID0_PAR (1<<24) | |
10334 | +#define HID0_DOZE (1<<23) | |
10335 | +#define HID0_NAP (1<<22) | |
10336 | +#define HID0_SLEEP (1<<21) | |
10337 | +#define HID0_DPM (1<<20) | |
10338 | +#define HID0_NHR (1<<16) /* Not Hard Reset */ | |
10339 | +#define HID0_ICE (1<<15) /* Instruction Cache Enable */ | |
10340 | +#define HID0_DCE (1<<14) /* Data Cache Enable */ | |
10341 | +#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */ | |
10342 | +#define HID0_DLOCK (1<<12) /* Data Cache Lock */ | |
10343 | +#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */ | |
10344 | +#define HID0_DCFI (1<<10) /* Data Cache Flash Invalidate */ | |
10345 | +#define HID0_SPD (1<<9) /* Speculative disable */ | |
10346 | +#define HID0_SGE (1<<7) /* Store Gathering Enable */ | |
10347 | +#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */ | |
10348 | +#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */ | |
10349 | +#define HID0_ABE (1<<3) /* Address Broadcast Enable */ | |
10350 | +#define HID0_BHT (1<<2) /* Branch History Table Enable */ | |
10351 | +#define HID0_BTCD (1<<1) /* Branch target cache disable */ | |
10352 | + | |
10353 | +#define L2CR_L2E BIT(0) /* L2 enable */ | |
10354 | +#define L2CR_L2PE BIT(1) /* L2 data parity generation and checking */ | |
10355 | +#define L2CR_L2SIZ_512K BIT(2) | |
10356 | +#define L2CR_L2SIZ_256K BIT(3) | |
10357 | +#define L2CR_L2SIZ_1MB (BIT(2)|BIT(3)) | |
10358 | +#define L2CR_L2CLK_1 BIT(6) /* L2 clock ration */ | |
10359 | +#define L2CR_L2CLK_15 (BIT(6)*2) | |
10360 | +#define L2CR_L2CLK_2 (BIT(6)*4) | |
10361 | +#define L2CR_L2CLK_25 (BIT(6)*5) | |
10362 | +#define L2CR_L2CLK_3 (BIT(6)*6) | |
10363 | +#define L2CR_L2RAM_FT 0 /* flow-through (reg-buf) synchronous SRAM */ | |
10364 | +#define L2CR_L2RAM_PB BIT(7) /* Piplined (reg-reg) synchronous burst SRAM */ | |
10365 | +#define L2CR_L2RAM_PLW (BIT(7)|BIT(8)) /* Piplined (reg-reg) synchronous late-write */ | |
10366 | +#define L2CR_L2DO BIT(9) /* L2 data-only */ | |
10367 | +#define L2CR_L2I BIT(10) /* L2 global invalidate */ | |
10368 | +#define L2CR_L2CTL BIT(11) /* L2 RAM control (ZZ enable, low-power mode) */ | |
10369 | +#define L2CR_L2WT BIT(12) /* L2 write-through */ | |
10370 | +#define L2CR_L2TS BIT(13) /* L2 test support */ | |
10371 | +#define L2CR_L2OH_05 0 /* L2 output hold 0.5 nS */ | |
10372 | +#define L2CR_L2OH_10 BIT(15) /* L2 output hold 1.0 nS */ | |
10373 | +#define L2CR_L2SL BIT(16) /* L2 DLL slow (use if bus freq < 150 MHz) */ | |
10374 | +#define L2CR_L2DF BIT(17) /* L2 differential clock */ | |
10375 | +#define L2CR_L2BYP BIT(18) /* L2 DLL bypass */ | |
10376 | +#define L2CR_L2IP BIT(31) /* L2 global invalidate in progress */ | |
10377 | + | |
10378 | +/* SPR_THRM1 */ | |
10379 | +#define THRM1_TIN (1 << 31) | |
10380 | +#define THRM1_TIV (1 << 30) | |
10381 | +#define THRM1_THRES(x) ((x&0x7f)<<23) | |
10382 | +#define THRM3_SITV(x) ((x&0x3fff)<<1) | |
10383 | +#define THRM1_TID (1<<2) | |
10384 | +#define THRM1_TIE (1<<1) | |
10385 | +#define THRM1_V (1<<0) | |
10386 | + | |
10387 | +/* SPR_THRM3 */ | |
10388 | +#define THRM3_E (1<<0) | |
10389 | + | |
10390 | +/* Processor Version Numbers */ | |
10391 | + | |
10392 | +#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ | |
10393 | +#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */ | |
10394 | + | |
10395 | +#define PVR_403GA 0x00200000 | |
10396 | +#define PVR_403GB 0x00200100 | |
10397 | +#define PVR_403GC 0x00200200 | |
10398 | +#define PVR_403GCX 0x00201400 | |
10399 | +#define PVR_405GP 0x40110000 | |
10400 | +#define PVR_601 0x00010000 | |
10401 | +#define PVR_602 0x00050000 | |
10402 | +#define PVR_603 0x00030000 | |
10403 | +#define PVR_603e 0x00060000 | |
10404 | +#define PVR_603ev 0x00070000 | |
10405 | +#define PVR_603r 0x00071000 | |
10406 | +#define PVR_604 0x00040000 | |
10407 | +#define PVR_604e 0x00090000 | |
10408 | +#define PVR_604r 0x000A0000 | |
10409 | +#define PVR_620 0x00140000 | |
10410 | +#define PVR_740 0x00080000 | |
10411 | +#define PVR_750 PVR_740 | |
10412 | +#define PVR_740P 0x10080000 | |
10413 | +#define PVR_750P PVR_740P | |
10414 | +#define PVR_821 0x00500000 | |
10415 | +#define PVR_823 PVR_821 | |
10416 | +#define PVR_850 PVR_821 | |
10417 | +#define PVR_860 PVR_821 | |
10418 | +#define PVR_7400 0x000C0000 | |
10419 | +#define PVR_8240 0x00810100 | |
10420 | +#define PVR_8260 PVR_8240 | |
10421 | + | |
10422 | +/* Vector VSCR register */ | |
10423 | +#define VSCR_NJ 0x10000 | |
10424 | +#define VSCR_SAT 0x1 | |
10425 | + | |
10426 | +#endif /* __KERNEL__ */ | |
10427 | + | |
10428 | + | |
10429 | +#ifdef __ASSEMBLY__ | |
10430 | + | |
10431 | +#define CTR S_CTR /* Counter Register */ | |
10432 | +#define DAR S_DAR /* Data Address Register */ | |
10433 | +#define DABR S_DABR /* Data Address Breakpoint Register */ | |
10434 | +#define DBAT0L S_DBAT0L /* Data BAT 0 Lower Register */ | |
10435 | +#define DBAT0U S_DBAT0U /* Data BAT 0 Upper Register */ | |
10436 | +#define DBAT1L S_DBAT1L /* Data BAT 1 Lower Register */ | |
10437 | +#define DBAT1U S_DBAT1U /* Data BAT 1 Upper Register */ | |
10438 | +#define DBAT2L S_DBAT2L /* Data BAT 2 Lower Register */ | |
10439 | +#define DBAT2U S_DBAT2U /* Data BAT 2 Upper Register */ | |
10440 | +#define DBAT3L S_DBAT3L /* Data BAT 3 Lower Register */ | |
10441 | +#define DBAT3U S_DBAT3U /* Data BAT 3 Upper Register */ | |
10442 | +#define DCMP S_DCMP /* Data TLB Compare Register */ | |
10443 | +#define DEC S_DEC /* Decrement Register */ | |
10444 | +#define DMISS S_DMISS /* Data TLB Miss Register */ | |
10445 | +#define DSISR S_DSISR /* Data Storage Interrupt Status Register */ | |
10446 | +#define EAR S_EAR /* External Address Register */ | |
10447 | +#define HASH1 S_HASH1 /* Primary Hash Address Register */ | |
10448 | +#define HASH2 S_HASH2 /* Secondary Hash Address Register */ | |
10449 | +#define HID0 S_HID0 /* Hardware Implementation Register 0 */ | |
10450 | +#define HID1 S_HID1 /* Hardware Implementation Register 1 */ | |
10451 | +#define IABR S_IABR /* Instruction Address Breakpoint Register */ | |
10452 | +#define IBAT0L S_IBAT0L /* Instruction BAT 0 Lower Register */ | |
10453 | +#define IBAT0U S_IBAT0U /* Instruction BAT 0 Upper Register */ | |
10454 | +#define IBAT1L S_IBAT1L /* Instruction BAT 1 Lower Register */ | |
10455 | +#define IBAT1U S_IBAT1U /* Instruction BAT 1 Upper Register */ | |
10456 | +#define IBAT2L S_IBAT2L /* Instruction BAT 2 Lower Register */ | |
10457 | +#define IBAT2U S_IBAT2U /* Instruction BAT 2 Upper Register */ | |
10458 | +#define IBAT3L S_IBAT3L /* Instruction BAT 3 Lower Register */ | |
10459 | +#define IBAT3U S_IBAT3U /* Instruction BAT 3 Upper Register */ | |
10460 | +#define ICMP S_ICMP /* Instruction TLB Compare Register */ | |
10461 | +#define IMISS S_IMISS /* Instruction TLB Miss Register */ | |
10462 | +#define IMMR S_IMMR /* PPC 860/821 Internal Memory Map Register */ | |
10463 | +#define L2CR S_L2CR /* PPC 750 L2 control register */ | |
10464 | +#define PVR S_PVR /* Processor Version */ | |
10465 | +#define RPA S_RPA /* Required Physical Address Register */ | |
10466 | +#define SDR1 S_SDR1 /* MMU hash base register */ | |
10467 | +#define SPR0 S_SPRG0 /* Supervisor Private Registers */ | |
10468 | +#define SPR1 S_SPRG1 | |
10469 | +#define SPR2 S_SPRG2 | |
10470 | +#define SPR3 S_SPRG3 | |
10471 | +#define SPRG0 S_SPRG0 | |
10472 | +#define SPRG1 S_SPRG1 | |
10473 | +#define SPRG2 S_SPRG2 | |
10474 | +#define SPRG3 S_SPRG3 | |
10475 | +#define SRR0 S_SRR0 /* Save and Restore Register 0 */ | |
10476 | +#define SRR1 S_SRR1 /* Save and Restore Register 1 */ | |
10477 | +#define TBRL S_STBRL /* Time Base Read Lower Register */ | |
10478 | +#define TBRU S_TBRU /* Time Base Read Upper Register */ | |
10479 | +#define TBWL S_TBWL /* Time Base Write Lower Register */ | |
10480 | +#define TBWU S_TBWU /* Time Base Write Upper Register */ | |
10481 | +#define ICTC S_ICTC | |
10482 | +#define THRM1 S_THRM1 /* Thermal Management Register 1 */ | |
10483 | +#define THRM2 S_THRM2 /* Thermal Management Register 2 */ | |
10484 | +#define THRM3 S_THRM3 /* Thermal Management Register 3 */ | |
10485 | +#define SIAR S_SIAR | |
10486 | +#define SDAR S_SDAR | |
10487 | +#define XER 1 | |
10488 | + | |
10489 | +#define SR0 0 /* Segment registers */ | |
10490 | +#define SR1 1 | |
10491 | +#define SR2 2 | |
10492 | +#define SR3 3 | |
10493 | +#define SR4 4 | |
10494 | +#define SR5 5 | |
10495 | +#define SR6 6 | |
10496 | +#define SR7 7 | |
10497 | +#define SR8 8 | |
10498 | +#define SR9 9 | |
10499 | +#define SR10 10 | |
10500 | +#define SR11 11 | |
10501 | +#define SR12 12 | |
10502 | +#define SR13 13 | |
10503 | +#define SR14 14 | |
10504 | +#define SR15 15 | |
10505 | + | |
10506 | +#endif /* __ASSEMBLY__ */ | |
10507 | + | |
10508 | +/* opcode macros */ | |
10509 | + | |
10510 | +#define OPCODE_PRIM(n) ( ((ulong)(n)) >> 26 ) | |
10511 | +#define OPCODE_EXT(n) ( (((ulong)(n)) >> 1) & 0x3ff ) | |
10512 | +#define OPCODE(op,op_ext) ( ((op)<<10) + op_ext ) | |
10513 | + | |
10514 | +#define B1(n) ( (((ulong)(n)) >> 21) & 0x1f ) | |
10515 | +#define B2(n) ( (((ulong)(n)) >> 16) & 0x1f ) | |
10516 | +#define B3(n) ( (((ulong)(n)) >> 11) & 0x1f ) | |
10517 | + | |
10518 | +#define BD(n) ((ulong)((n) & 0x7fff) + (((n) & 0x8000) ? (ulong)0xffff8000 : 0)) | |
10519 | + | |
10520 | +#define SPRNUM_FLIP( v ) ( (((v)>>5) & 0x1f) | (((v)<<5) & 0x3e0) ) | |
10521 | + | |
10522 | +#endif /* _H_PROCESSOR */ | |
10523 | + | |
10524 | --- /dev/null | |
10525 | +++ b/drivers/macintosh/mol/include/prom.h | |
10526 | @@ -0,0 +1,46 @@ | |
10527 | +/* | |
10528 | + * Creation Date: <1999/02/22 23:22:17 samuel> | |
10529 | + * Time-stamp: <2003/06/02 16:17:36 samuel> | |
10530 | + * | |
10531 | + * <prom.h> | |
10532 | + * | |
10533 | + * OF device tree structs | |
10534 | + * | |
10535 | + * Copyright (C) 1999, 2000, 2002, 2003 Samuel Rydh (samuel@ibrium.se) | |
10536 | + * | |
10537 | + * This program is free software; you can redistribute it and/or | |
10538 | + * modify it under the terms of the GNU General Public License | |
10539 | + * as published by the Free Software Foundation | |
10540 | + * | |
10541 | + */ | |
10542 | + | |
10543 | +#ifndef _H_PROM | |
10544 | +#define _H_PROM | |
10545 | + | |
10546 | +typedef void *p_phandle_t; | |
10547 | + | |
10548 | +typedef struct { | |
10549 | + int nirq; | |
10550 | + int irq[5]; | |
10551 | + unsigned long controller[5]; | |
10552 | +} irq_info_t; | |
10553 | + | |
10554 | +typedef struct p_property { | |
10555 | + char *name; | |
10556 | + int length; | |
10557 | + unsigned char *value; | |
10558 | + struct p_property *next; | |
10559 | +} p_property_t; | |
10560 | + | |
10561 | +typedef struct mol_device_node { | |
10562 | + p_phandle_t node; | |
10563 | + struct p_property *properties; | |
10564 | + struct mol_device_node *parent; | |
10565 | + struct mol_device_node *child; | |
10566 | + struct mol_device_node *sibling; | |
10567 | + struct mol_device_node *next; /* next device of same type */ | |
10568 | + struct mol_device_node *allnext; /* next in list of all nodes */ | |
10569 | + char *unit_string; | |
10570 | +} mol_device_node_t; | |
10571 | + | |
10572 | +#endif /* _H_PROM */ | |
10573 | --- /dev/null | |
10574 | +++ b/drivers/macintosh/mol/include/rvec.h | |
10575 | @@ -0,0 +1,147 @@ | |
10576 | +/* | |
10577 | + * Creation Date: <2001/01/26 21:33:45 samuel> | |
10578 | + * Time-stamp: <2004/02/08 20:08:20 samuel> | |
10579 | + * | |
10580 | + * <return_vectors.h> | |
10581 | + * | |
10582 | + * Possible mac-return vectors (see mainloop.S) | |
10583 | + * | |
10584 | + * Copyright (C) 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
10585 | + * | |
10586 | + * This program is free software; you can redistribute it and/or | |
10587 | + * modify it under the terms of the GNU General Public License | |
10588 | + * as published by the Free Software Foundation | |
10589 | + * | |
10590 | + */ | |
10591 | + | |
10592 | +#ifndef _H_RVEC | |
10593 | +#define _H_RVEC | |
10594 | + | |
10595 | + | |
10596 | +/* ---------------------------------------------------------------------------- */ | |
10597 | + | |
10598 | +#define NRVECS_LOG2 6 | |
10599 | +#define NUM_RVECS 64 /* = 2 ^ NRVECS_LOG2 */ | |
10600 | +#define RVEC_MASK (NUM_RVECS-1) | |
10601 | + | |
10602 | +/* ---------------------------------------------------------------------------- */ | |
10603 | + | |
10604 | +#define RVEC_NOP 0 /* Must be zero */ | |
10605 | +#ifdef __darwin__ | |
10606 | +#define RVEC_CALL_KERNEL 1 /* call kernel */ | |
10607 | +#endif | |
10608 | +#define RVEC_ENABLE_FPU 3 /* Load up FPU */ | |
10609 | + | |
10610 | +#define RVEC_TRACE_TRAP 6 | |
10611 | +#define RVEC_ISI_TRAP 7 /* r4=nip, r5=srr1 */ | |
10612 | +#define RVEC_DSI_TRAP 8 /* r4=dar, r5=srr1 */ | |
10613 | +#define RVEC_ALIGNMENT_TRAP 9 /* r4=dar, r5=srr1 */ | |
10614 | +#ifdef EMULATE_603 | |
10615 | +#define RVEC_DMISS_LOAD_TRAP 10 | |
10616 | +#define RVEC_DMISS_STORE_TRAP 11 | |
10617 | +#define RVEC_IMISS_TRAP 12 | |
10618 | +#endif | |
10619 | + | |
10620 | +#define RVEC_SPR_READ 13 /* r4=spr#, r5=gprnum */ | |
10621 | +#define RVEC_SPR_WRITE 14 /* r4=spr#, r5=value */ | |
10622 | +#define RVEC_PRIV_INST 15 /* r4=opcode */ | |
10623 | +#define RVEC_ILLEGAL_INST 16 /* r4=opcode */ | |
10624 | + | |
10625 | +#define RVEC_UNUSUAL_PROGRAM_EXCEP 17 /* r4=opcode, r5=srr1 */ | |
10626 | + | |
10627 | +#define RVEC_ALTIVEC_UNAVAIL_TRAP 18 | |
10628 | +#define RVEC_ALTIVEC_ASSIST 19 /* r4=srr1 */ | |
10629 | +#define RVEC_ENABLE_ALTIVEC 20 | |
10630 | + | |
10631 | +#define RVEC_EXIT 21 | |
10632 | +/* 22 was RVEC_INTERRUPT */ | |
10633 | +#define RVEC_OSI_SYSCALL 23 | |
10634 | +#define RVEC_TIMER 24 | |
10635 | + | |
10636 | +#define RVEC_IO_READ 25 | |
10637 | +#define RVEC_IO_WRITE 26 | |
10638 | + | |
10639 | +#define RVEC_MSR_POW 27 /* (MSR_POW 0->1) => doze */ | |
10640 | + | |
10641 | +/* error/debug */ | |
10642 | +#define RVEC_UNUSUAL_DSISR_BITS 28 /* dar, dsisr (bit 0,5,9 or 11 was set) */ | |
10643 | +#define RVEC_MMU_IO_SEG_ACCESS 29 /* IO segment access (more or less unused) */ | |
10644 | +#define RVEC_INTERNAL_ERROR 30 | |
10645 | +#define RVEC_DEBUGGER 31 | |
10646 | +#define RVEC_BREAK 32 /* r4 = break_flag */ | |
10647 | +#define RVEC_BAD_NIP 33 /* r4 = phys_nip */ | |
10648 | +#define RVEC_OUT_OF_MEMORY 34 /* fatal out of memory... */ | |
10649 | + | |
10650 | +#define RVEC_CHECK_IRQS 35 /* check interrupts */ | |
10651 | + | |
10652 | + | |
10653 | +/************************************************************************/ | |
10654 | +/* MOL kernel/emulator switch magic */ | |
10655 | +/************************************************************************/ | |
10656 | + | |
10657 | +/* magic to be loaded into r4/r5 before the illegal instruction is issued */ | |
10658 | +#define MOL_ENTRY_R4_MAGIC 0x7ba5 | |
10659 | +#define MOL_INITIALIZE_FLAG 0x8000 | |
10660 | +#define MOL_KERNEL_ENTRY_MAGIC mfmsr r0 /* any privileged instruction will do */ | |
10661 | + | |
10662 | + | |
10663 | +/************************************************************************/ | |
10664 | +/* Kernel definitions */ | |
10665 | +/************************************************************************/ | |
10666 | + | |
10667 | +#if defined(__KERNEL__) && !defined( __ASSEMBLY__ ) | |
10668 | + | |
10669 | +#define RVEC_RETURN_1( mregsptr, rvec, arg1 ) \ | |
10670 | + ({ (mregsptr)->rvec_param[0] = (ulong)(arg1); \ | |
10671 | + return rvec; }) | |
10672 | + | |
10673 | +#define RVEC_RETURN_2( mregsptr, rvec, arg1, arg2 ) \ | |
10674 | + ({ (mregsptr)->rvec_param[0] = (ulong)(arg1); \ | |
10675 | + (mregsptr)->rvec_param[1] = (ulong)(arg2); \ | |
10676 | + return rvec; }) | |
10677 | + | |
10678 | +#define RVEC_RETURN_3( mregsptr, rvec, arg1, arg2, arg3 ) \ | |
10679 | + ({ (mregsptr)->rvec_param[0] = (ulong)(arg1); \ | |
10680 | + (mregsptr)->rvec_param[1] = (ulong)(arg2); \ | |
10681 | + (mregsptr)->rvec_param[2] = (ulong)(arg3); \ | |
10682 | + return rvec; }) | |
10683 | + | |
10684 | +#endif /* !__ASSEMBLY__ && __KERNEL__ */ | |
10685 | + | |
10686 | + | |
10687 | +/************************************************************************/ | |
10688 | +/* userspace definitions */ | |
10689 | +/************************************************************************/ | |
10690 | + | |
10691 | +#if !defined(__KERNEL__) || defined(__MPC107__) | |
10692 | + | |
10693 | +#if !defined(__ASSEMBLY__) | |
10694 | +#if !defined(__KERNEL__) | |
10695 | + | |
10696 | +typedef struct { | |
10697 | + int vnum; | |
10698 | + void *vector; | |
10699 | + const char *name; | |
10700 | +} rvec_entry_t; | |
10701 | + | |
10702 | +extern void rvec_init( void ); | |
10703 | +extern void rvec_cleanup( void ); | |
10704 | +extern void set_rvector( uint vnum, void *vector, const char *vector_name ); | |
10705 | +extern void set_rvecs( rvec_entry_t *table, int tablesize ); | |
10706 | +#endif | |
10707 | + | |
10708 | +/* this struct is private to rvec.c/mainloop.S (offsets are HARDCODED) */ | |
10709 | +typedef struct { | |
10710 | + int (*rvec)( int rvec /*, arguments */ ); | |
10711 | + int dbg_count; | |
10712 | + const char *name; | |
10713 | + int filler; | |
10714 | +} priv_rvec_entry_t; | |
10715 | +#endif /* __ASSEMBLY__ */ | |
10716 | + | |
10717 | +#define RVEC_ESIZE_LOG2 4 /* 2^n = sizeof(priv_rvec_entry_t) */ | |
10718 | +#define RVEC_ESIZE 16 /* sizeof(priv_rvec_entry_t) */ | |
10719 | + | |
10720 | +#endif /* __KERNEL__ || __MPC107__ */ | |
10721 | + | |
10722 | +#endif /* _H_RVEC */ | |
10723 | --- /dev/null | |
10724 | +++ b/drivers/macintosh/mol/include/skiplist.h | |
10725 | @@ -0,0 +1,87 @@ | |
10726 | +/* | |
10727 | + * Creation Date: <2003/03/03 22:59:04 samuel> | |
10728 | + * Time-stamp: <2004/02/21 12:17:38 samuel> | |
10729 | + * | |
10730 | + * <skiplist.h> | |
10731 | + * | |
10732 | + * Skiplist implementation | |
10733 | + * | |
10734 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
10735 | + * | |
10736 | + * This program is free software; you can redistribute it and/or | |
10737 | + * modify it under the terms of the GNU General Public License | |
10738 | + * as published by the Free Software Foundation | |
10739 | + * | |
10740 | + */ | |
10741 | + | |
10742 | +#ifndef _H_SKIPLIST | |
10743 | +#define _H_SKIPLIST | |
10744 | + | |
10745 | +#define SKIPLIST_MAX_HEIGHT 16 | |
10746 | + | |
10747 | +typedef struct skiplist_el skiplist_el_t; | |
10748 | + | |
10749 | +typedef struct { | |
10750 | +#ifdef __darwin__ | |
10751 | + ulong next_phys; /* for usage from assembly */ | |
10752 | +#endif | |
10753 | + skiplist_el_t *next; | |
10754 | +} skiplist_level_t; | |
10755 | + | |
10756 | +/* data (of datasize) is stored before the skiplist_el */ | |
10757 | +typedef struct skiplist_el { | |
10758 | + int key; | |
10759 | + skiplist_level_t level[1]; /* level 0 */ | |
10760 | + /* level 1..n are optionally stored here */ | |
10761 | +} *skiplist_iter_t; | |
10762 | + | |
10763 | +typedef struct { | |
10764 | + int nel; | |
10765 | + int slevel; /* start level */ | |
10766 | + int datasize; /* size of data (stored before each key) */ | |
10767 | + | |
10768 | + skiplist_level_t root[SKIPLIST_MAX_HEIGHT]; | |
10769 | + skiplist_el_t nil_el; | |
10770 | + | |
10771 | + skiplist_level_t freelist; /* key = level, linked list in next[0] */ | |
10772 | +} skiplist_t; | |
10773 | + | |
10774 | +static inline int | |
10775 | +skiplist_getnext( skiplist_t *sl, skiplist_iter_t *iterator, char **data ) | |
10776 | +{ | |
10777 | + skiplist_el_t *el = *iterator; | |
10778 | + *data = (char*)el - sl->datasize; | |
10779 | + *iterator = el->level[0].next; | |
10780 | + return el != &sl->nil_el; | |
10781 | +} | |
10782 | + | |
10783 | +static inline int | |
10784 | +skiplist_iter_getkey( skiplist_t *sl, char *data ) | |
10785 | +{ | |
10786 | + return ((skiplist_el_t*)(data + sl->datasize))->key; | |
10787 | +} | |
10788 | + | |
10789 | +static inline skiplist_iter_t | |
10790 | +skiplist_iterate( skiplist_t *sl ) | |
10791 | +{ | |
10792 | + return sl->root[0].next; | |
10793 | +} | |
10794 | + | |
10795 | +static inline int | |
10796 | +skiplist_needalloc( skiplist_t *sl ) | |
10797 | +{ | |
10798 | + return !sl->freelist.next; | |
10799 | +} | |
10800 | + | |
10801 | +typedef void (*skiplist_el_callback)( char *data, int ind, int n, void *usr1, void *usr2 ); | |
10802 | + | |
10803 | +extern void skiplist_init( skiplist_t *sl, int datasize ); | |
10804 | +extern int skiplist_prealloc( skiplist_t *sl, char *buf, unsigned int size, | |
10805 | + skiplist_el_callback callback, void *usr1, void *usr2 ); | |
10806 | + | |
10807 | +extern char *skiplist_insert( skiplist_t *sl, int key ); | |
10808 | +extern char *skiplist_delete( skiplist_t *sl, int key ); | |
10809 | +extern char *skiplist_lookup( skiplist_t *sl, int key ); | |
10810 | + | |
10811 | + | |
10812 | +#endif /* _H_SKIPLIST */ | |
10813 | --- /dev/null | |
10814 | +++ b/drivers/macintosh/mol/include/tlbie.h | |
10815 | @@ -0,0 +1,102 @@ | |
10816 | +/* | |
10817 | + * Creation Date: <2003/05/27 16:56:10 samuel> | |
10818 | + * Time-stamp: <2003/08/16 16:55:31 samuel> | |
10819 | + * | |
10820 | + * <tlbie.h> | |
10821 | + * | |
10822 | + * tlbie and PTE operations | |
10823 | + * | |
10824 | + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) | |
10825 | + * | |
10826 | + * This program is free software; you can redistribute it and/or | |
10827 | + * modify it under the terms of the GNU General Public License | |
10828 | + * version 2 | |
10829 | + * | |
10830 | + */ | |
10831 | + | |
10832 | +#ifndef _H_TLBIE | |
10833 | +#define _H_TLBIE | |
10834 | + | |
10835 | + | |
10836 | +#ifdef CONFIG_SMP | |
10837 | +extern void (*xx_tlbie_lowmem)( void /* special */ ); | |
10838 | +extern void (*xx_store_pte_lowmem)( void /* special */ ); | |
10839 | +extern int compat_hash_table_lock; | |
10840 | + | |
10841 | +static inline void | |
10842 | +__tlbie( int ea ) | |
10843 | +{ | |
10844 | + register ulong _ea __asm__ ("r3"); | |
10845 | + register ulong _lock __asm__ ("r7"); | |
10846 | + register ulong _func __asm__ ("r9"); | |
10847 | + | |
10848 | + _func = (ulong)xx_tlbie_lowmem; | |
10849 | + _lock = (ulong)&compat_hash_table_lock; | |
10850 | + _ea = ea; | |
10851 | + | |
10852 | + asm volatile ( | |
10853 | + "mtctr 9 \n" | |
10854 | + "li 8,0x1235 \n" /* lock value */ | |
10855 | + "mfmsr 10 \n" | |
10856 | + "rlwinm 0,10,0,17,15 \n" /* clear MSR_EE */ | |
10857 | + "mtmsr 0 \n" | |
10858 | + "bctrl \n" /* modifies r0 */ | |
10859 | + "mtmsr 10 \n" | |
10860 | + : | |
10861 | + : "r" (_ea), "r" (_lock), "r" (_func) | |
10862 | + : "ctr", "lr", "cc", "r8", "r0", "r10" | |
10863 | + ); | |
10864 | +} | |
10865 | + | |
10866 | +static inline void | |
10867 | +__store_PTE( int ea, unsigned long *slot, int pte0, int pte1 ) | |
10868 | +{ | |
10869 | + register ulong _ea __asm__ ("r3"); | |
10870 | + register ulong _pte_slot __asm__ ("r4"); | |
10871 | + register ulong _pte0 __asm__ ("r5"); | |
10872 | + register ulong _pte1 __asm__ ("r6"); | |
10873 | + register ulong _lock __asm__ ("r7"); | |
10874 | + register ulong _func __asm__ ("r9"); | |
10875 | + | |
10876 | + _func = (ulong)xx_store_pte_lowmem; | |
10877 | + _ea = ea; | |
10878 | + _pte_slot = (ulong)slot; | |
10879 | + _pte0 = pte0; | |
10880 | + _pte1 = pte1; | |
10881 | + _lock = (ulong)&compat_hash_table_lock; | |
10882 | + | |
10883 | + asm volatile ( | |
10884 | + "mtctr 9 \n" | |
10885 | + "li 8,0x1234 \n" /* lock value */ | |
10886 | + "mfmsr 10 \n" | |
10887 | + "rlwinm 0,10,0,17,15 \n" /* clear MSR_EE */ | |
10888 | + "mtmsr 0 \n" | |
10889 | + "bctrl \n" /* modifies r0 */ | |
10890 | + "mtmsr 10 \n" | |
10891 | + : | |
10892 | + : "r" (_ea), "r" (_pte_slot), "r" (_pte0), "r" (_pte1), "r" (_lock), "r" (_func) | |
10893 | + : "ctr", "lr", "cc", "r0", "r8", "r10" | |
10894 | + ); | |
10895 | +} | |
10896 | + | |
10897 | +#else /* CONFIG_SMP */ | |
10898 | +extern void (*xx_store_pte_lowmem)( unsigned long *slot, int pte0, int pte1 ); | |
10899 | + | |
10900 | +static inline void __tlbie( int ea ) { | |
10901 | + asm volatile ("tlbie %0" : : "r"(ea)); | |
10902 | +} | |
10903 | + | |
10904 | +static inline void | |
10905 | +__store_PTE( int ea, unsigned long *slot, int pte0, int pte1 ) | |
10906 | +{ | |
10907 | + ulong flags; | |
10908 | + local_irq_save(flags); | |
10909 | + (*xx_store_pte_lowmem)( slot, pte0, pte1 ); | |
10910 | + local_irq_restore(flags); | |
10911 | + __tlbie( ea ); | |
10912 | +} | |
10913 | + | |
10914 | +#endif /* CONFIG_SMP */ | |
10915 | + | |
10916 | + | |
10917 | +#endif /* _H_TLBIE */ | |
10918 | --- /dev/null | |
10919 | +++ b/drivers/macintosh/mol/include/uaccess.h | |
10920 | @@ -0,0 +1,36 @@ | |
10921 | +/* | |
10922 | + * Creation Date: <2004/02/01 20:02:11 samuel> | |
10923 | + * Time-stamp: <2004/02/01 20:02:11 samuel> | |
10924 | + * | |
10925 | + * <uaccess.h> | |
10926 | + * | |
10927 | + * | |
10928 | + * | |
10929 | + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) | |
10930 | + * | |
10931 | + * This program is free software; you can redistribute it and/or | |
10932 | + * modify it under the terms of the GNU General Public License | |
10933 | + * version 2 | |
10934 | + * | |
10935 | + */ | |
10936 | + | |
10937 | +#ifndef _H_UACCESS | |
10938 | +#define _H_UACCESS | |
10939 | + | |
10940 | + | |
10941 | +static inline unsigned int copy_to_user_mol( void *to, const void *from, ulong len ) { | |
10942 | + return copy_to_user( to, from, len ); | |
10943 | +} | |
10944 | +static inline unsigned int copy_from_user_mol( void *to, const void *from, ulong len ) { | |
10945 | + return copy_from_user( to, from, len ); | |
10946 | +} | |
10947 | + | |
10948 | +static inline unsigned int copy_int_to_user( int *to, int val ) { | |
10949 | + return copy_to_user_mol( to, &val, sizeof(int) ); | |
10950 | +} | |
10951 | +static inline unsigned int copy_int_from_user( int *retint, int *userptr ) { | |
10952 | + return copy_from_user_mol( retint, userptr, sizeof(int) ); | |
10953 | +} | |
10954 | + | |
10955 | + | |
10956 | +#endif /* _H_UACCESS */ | |
10957 | --- /dev/null | |
10958 | +++ b/drivers/macintosh/mol/include/vector.h | |
10959 | @@ -0,0 +1,189 @@ | |
10960 | +/* | |
10961 | + * Creation Date: <2003/05/26 00:00:28 samuel> | |
10962 | + * Time-stamp: <2004/03/07 14:44:50 samuel> | |
10963 | + * | |
10964 | + * <vector.h> | |
10965 | + * | |
10966 | + * Vector hooks | |
10967 | + * | |
10968 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
10969 | + * | |
10970 | + * This program is free software; you can redistribute it and/or | |
10971 | + * modify it under the terms of the GNU General Public License | |
10972 | + * version 2 | |
10973 | + * | |
10974 | + */ | |
10975 | + | |
10976 | +#ifndef _H_VECTOR | |
10977 | +#define _H_VECTOR | |
10978 | + | |
10979 | +#define MOL_SPRG2_MAGIC 0x1779 | |
10980 | + | |
10981 | +#ifdef __MPC107__ | |
10982 | +#include "mpcvector.h" | |
10983 | +#else | |
10984 | + | |
10985 | +#define PERFMON_VECTOR 0xf00 | |
10986 | + | |
10987 | + | |
10988 | +/************************************************************************/ | |
10989 | +/* Vector entry point definitions */ | |
10990 | +/************************************************************************/ | |
10991 | + | |
10992 | +/* | |
10993 | + * This code uses the dynamic linkage/action symbol functionality of | |
10994 | + * the MOL kernel loader to automatically install the hooks. Refer to | |
10995 | + * hook.c for the actual implementation. | |
10996 | + */ | |
10997 | + | |
10998 | +/* Description of ACTION_RELOC_HOOK: | |
10999 | + * | |
11000 | + * .long ACTION_RELOC_HOOK | |
11001 | + * .long vector | |
11002 | + * .long #bytes to copy to lowmem | |
11003 | + * .long offset to vret function | |
11004 | + * -- offsets are calculated from here -- | |
11005 | + */ | |
11006 | + | |
11007 | +mDEFINE(VECTOR_HOOK, [v], [ | |
11008 | + balign_32 | |
11009 | + ACTION_PB( ACTION_RELOC_HOOK ) | |
11010 | + .long _v | |
11011 | + .long vhook_end_[]_v - vhook_[]_v | |
11012 | + .long vret_[]_v - vhook_[]_v | |
11013 | +vhook_[]_v: | |
11014 | + mtsprg_a0 r3 | |
11015 | + addis r3,0,0 /* [1] hook address inserted */ | |
11016 | + mtsprg_a1 r1 | |
11017 | + ori r3,r3,0 /* [3] at module initialization */ | |
11018 | + mfctr r1 | |
11019 | + mtctr r3 | |
11020 | + bctr | |
11021 | + | |
11022 | +vret_[]_v: | |
11023 | + nop /* overwritten instruction is inserted here */ | |
11024 | + ba _v + 0x4 | |
11025 | +vhook_end_[]_v: | |
11026 | + | |
11027 | + .text | |
11028 | + /* entrypoint */ | |
11029 | +]) | |
11030 | + | |
11031 | +/* these macros are to be used from the not_mol vector hook */ | |
11032 | +#define CONTINUE_TRAP( v ) \ | |
11033 | + mfsprg_a0 r3 ; \ | |
11034 | + fix_sprg2 /**/ R1 /* sprg2 == sprg_a0 */ ; \ | |
11035 | + mfsprg_a1 r1 ; \ | |
11036 | + ACTION_1( ACTION_VRET, v ) /* ba vret_xxx */ | |
11037 | + | |
11038 | +#define ABORT_TRAP( dummy_v ) \ | |
11039 | + mfsprg_a0 r3 ; \ | |
11040 | + fix_sprg2 /**/ R1 /* sprg2 == sprg_a0 */ ; \ | |
11041 | + mfsprg_a1 r1 ; \ | |
11042 | + rfi | |
11043 | + | |
11044 | +/* SPRG0,1 = saved r3,r1, r1 = saved lr */ | |
11045 | +mDEFINE(VECTOR_, [v, dummy_str, secondary, not_mol_label], [ | |
11046 | + | |
11047 | +not_mol_[]_v: | |
11048 | + mtcr r3 | |
11049 | + CONTINUE_TRAP( _v ) | |
11050 | + | |
11051 | +secondary_int_[]_v: | |
11052 | + li r3,_v | |
11053 | + b _secondary | |
11054 | + | |
11055 | + VECTOR_HOOK( _v ) | |
11056 | + | |
11057 | + /* entrypoint */ | |
11058 | + mtctr r1 | |
11059 | + mfcr r3 | |
11060 | + mfsprg_a2 r1 | |
11061 | + cmpwi r1,MOL_SPRG2_MAGIC | |
11062 | + bne- _not_mol_label | |
11063 | +soft_603_entry_[]_v: | |
11064 | + mfsrr1 r1 | |
11065 | + andi. r1,r1,MSR_PR /* MSR_PR set? */ | |
11066 | + mfsprg_a3 r1 | |
11067 | + beq- secondary_int_[]_v /* if not, take a secondary trap? */ | |
11068 | +]) | |
11069 | + | |
11070 | +#define VECTOR(v, dummy_str, secondary) \ | |
11071 | + VECTOR_(v, dummy_str, secondary, not_mol_##v ) | |
11072 | + | |
11073 | +/* this macro takes an exception from mac mode (call save_middle_regs first) */ | |
11074 | +#define TAKE_EXCEPTION( v ) \ | |
11075 | + bl take_exception ; \ | |
11076 | + ACTION_1( ACTION_VRET, v ) | |
11077 | + | |
11078 | +/* no need to relocate the 0xf00 trap */ | |
11079 | +#define PERFMON_VECTOR_RELOCATION( newvec ) | |
11080 | + | |
11081 | + | |
11082 | +/************************************************************************/ | |
11083 | +/* 603 vector HOOKs (r0-r3, cr0 saved by hardware) */ | |
11084 | +/************************************************************************/ | |
11085 | + | |
11086 | +mDEFINE(VECTOR_603, [v, dummy_str], [ | |
11087 | + balign_32 | |
11088 | + ACTION_PB( ACTION_RELOC_HOOK ) | |
11089 | + .long _v | |
11090 | + .long vhook_end_[]_v - vhook_[]_v | |
11091 | + .long vret_[]_v - vhook_[]_v | |
11092 | +vhook_[]_v: | |
11093 | + mfsprg_a2 r1 | |
11094 | + addis r3,0,0 /* [1] hook address inserted */ | |
11095 | + cmpwi r1,MOL_SPRG2_MAGIC | |
11096 | + ori r3,r3,0 /* [3] at module initialization */ | |
11097 | + bne vret_[]_v | |
11098 | + mfctr r0 | |
11099 | + mtctr r3 | |
11100 | + bctr | |
11101 | + | |
11102 | +vret_[]_v: | |
11103 | + nop /* overwritten instruction is inserted here */ | |
11104 | + ba _v + 0x4 | |
11105 | +vhook_end_[]_v: | |
11106 | + | |
11107 | + .text | |
11108 | + /* entrypoint */ | |
11109 | +]) | |
11110 | + | |
11111 | + | |
11112 | +/* all register are assumed to be unmodified */ | |
11113 | +mDEFINE(SOFT_VECTOR_ENTRY_603, [v], [ | |
11114 | + mtsprg_a0 r3 | |
11115 | + mtsprg_a1 r1 | |
11116 | + mfcr r3 | |
11117 | + b soft_603_entry_[]_v | |
11118 | +]) | |
11119 | + | |
11120 | + | |
11121 | +/************************************************************************/ | |
11122 | +/* FUNCTION_HOOK */ | |
11123 | +/************************************************************************/ | |
11124 | + | |
11125 | +mDEFINE(FHOOK, [symind], [ | |
11126 | + ACTION_PB( ACTION_HOOK_FUNCTION ) | |
11127 | + .long _symind | |
11128 | + .long fhook_end_[]_symind - fhook_[]_symind | |
11129 | + .long fret_[]_symind - fhook_[]_symind | |
11130 | +fhook_[]_symind: | |
11131 | + mflr r10 | |
11132 | + addis r9,0,0 /* [1] address inserted */ | |
11133 | + ori r9,r9,0 /* [2] at runtime */ | |
11134 | + mtctr r9 | |
11135 | + bctrl | |
11136 | + mtlr r10 | |
11137 | +fret_[]_symind: | |
11138 | + nop /* overwritten instruction is inserted here */ | |
11139 | + nop /* return (through a relative branch) */ | |
11140 | +fhook_end_[]_symind: | |
11141 | + | |
11142 | + .text | |
11143 | + /* hook goes here */ | |
11144 | +]) | |
11145 | + | |
11146 | + | |
11147 | +#endif /* MOLMPC */ | |
11148 | +#endif /* _H_VECTOR */ | |
11149 | --- /dev/null | |
11150 | +++ b/drivers/macintosh/mol/include/version.h | |
11151 | @@ -0,0 +1,11 @@ | |
11152 | + | |
11153 | +#ifndef _H_VERSION | |
11154 | +#define _H_VERSION | |
11155 | + | |
11156 | +#include "molversion.h" | |
11157 | + | |
11158 | +#define MOL_VERSION ((MOL_MAJOR_VERSION << 16) \ | |
11159 | + + (MOL_MINOR_VERSION << 8) \ | |
11160 | + + MOL_PATCHLEVEL ) | |
11161 | + | |
11162 | +#endif /* _H_VERSION */ | |
11163 | --- /dev/null | |
11164 | +++ b/drivers/macintosh/mol/include/weaksym.h | |
11165 | @@ -0,0 +1,39 @@ | |
11166 | +/* | |
11167 | + * Creation Date: <2001/08/02 23:53:57 samuel> | |
11168 | + * Time-stamp: <2001/08/03 00:30:23 samuel> | |
11169 | + * | |
11170 | + * <weak.h> | |
11171 | + * | |
11172 | + * Support of weak symbols (extract, stolen from glibc) | |
11173 | + * | |
11174 | + * This program is free software; you can redistribute it and/or | |
11175 | + * modify it under the terms of the GNU General Public License | |
11176 | + * as published by the Free Software Foundation | |
11177 | + * | |
11178 | + */ | |
11179 | + | |
11180 | +#ifndef _H_WEAKSYM | |
11181 | +#define _H_WEAKSYM | |
11182 | + | |
11183 | + | |
11184 | +/* Define ALIASNAME as a strong alias for NAME. */ | |
11185 | +#define strong_alias(name, aliasname) _strong_alias(name, aliasname) | |
11186 | +#define _strong_alias(name, aliasname) \ | |
11187 | + extern __typeof (name) aliasname __attribute__ ((alias (#name))); | |
11188 | + | |
11189 | +/* This comes between the return type and function name in | |
11190 | + a function definition to make that definition weak. */ | |
11191 | +#define weak_function __attribute__ ((weak)) | |
11192 | +#define weak_const_function __attribute__ ((weak, __const__)) | |
11193 | + | |
11194 | +/* Define ALIASNAME as a weak alias for NAME. */ | |
11195 | +#define weak_alias(name, aliasname) _weak_alias (name, aliasname) | |
11196 | +#define _weak_alias(name, aliasname) \ | |
11197 | + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); | |
11198 | + | |
11199 | +/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */ | |
11200 | +#define weak_extern(symbol) _weak_extern (symbol) | |
11201 | +# define _weak_extern(symbol) asm (".weak " #symbol); | |
11202 | + | |
11203 | + | |
11204 | +#endif /* _H_WEAKSYM */ | |
11205 | --- /dev/null | |
11206 | +++ b/drivers/macintosh/mol/init.c | |
11207 | @@ -0,0 +1,191 @@ | |
11208 | +/* | |
11209 | + * Creation Date: <2002/01/13 20:45:37 samuel> | |
11210 | + * Time-stamp: <2004/02/14 14:01:09 samuel> | |
11211 | + * | |
11212 | + * <init.c> | |
11213 | + * | |
11214 | + * Kernel module initialization | |
11215 | + * | |
11216 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
11217 | + * | |
11218 | + * This program is free software; you can redistribute it and/or | |
11219 | + * modify it under the terms of the GNU General Public License | |
11220 | + * as published by the Free Software Foundation | |
11221 | + * | |
11222 | + */ | |
11223 | + | |
11224 | +#include "archinclude.h" | |
11225 | +#include "alloc.h" | |
11226 | +#include "kernel_vars.h" | |
11227 | +#include "misc.h" | |
11228 | +#include "mmu.h" | |
11229 | +#include "asmfuncs.h" | |
11230 | +#include "performance.h" | |
11231 | +#include "mol-ioctl.h" | |
11232 | +#include "version.h" | |
11233 | +#include "hash.h" | |
11234 | + | |
11235 | +/* globals */ | |
11236 | +session_table_t *g_sesstab; | |
11237 | +int g_num_sessions; | |
11238 | + | |
11239 | + | |
11240 | +/************************************************************************/ | |
11241 | +/* init/cleanup kernel module */ | |
11242 | +/************************************************************************/ | |
11243 | + | |
11244 | +int | |
11245 | +common_init( void ) | |
11246 | +{ | |
11247 | + if( init_hash() ) | |
11248 | + return 1; | |
11249 | + | |
11250 | + if( !(g_sesstab=kmalloc_cont_mol(sizeof(*g_sesstab))) ) { | |
11251 | + cleanup_hash(); | |
11252 | + return 1; | |
11253 | + } | |
11254 | + | |
11255 | + memset( g_sesstab, 0, sizeof(*g_sesstab) ); | |
11256 | + init_MUTEX_mol( &g_sesstab->lock ); | |
11257 | + | |
11258 | + if( arch_common_init() ) { | |
11259 | + free_MUTEX_mol( &g_sesstab->lock ); | |
11260 | + kfree_cont_mol( g_sesstab ); | |
11261 | + cleanup_hash(); | |
11262 | + return 1; | |
11263 | + } | |
11264 | + return 0; | |
11265 | +} | |
11266 | + | |
11267 | +void | |
11268 | +common_cleanup( void ) | |
11269 | +{ | |
11270 | + arch_common_cleanup(); | |
11271 | + | |
11272 | + free_MUTEX_mol( &g_sesstab->lock ); | |
11273 | + kfree_cont_mol( g_sesstab ); | |
11274 | + g_sesstab = NULL; | |
11275 | + | |
11276 | + cleanup_hash(); | |
11277 | +} | |
11278 | + | |
11279 | + | |
11280 | +/************************************************************************/ | |
11281 | +/* initialize / destroy session */ | |
11282 | +/************************************************************************/ | |
11283 | + | |
11284 | +static int | |
11285 | +initialize_session_( uint index ) | |
11286 | +{ | |
11287 | + kernel_vars_t *kv; | |
11288 | + ulong kv_phys; | |
11289 | + | |
11290 | + if( g_sesstab->magic == 1 ) | |
11291 | + return -EMOLSECURITY; | |
11292 | + | |
11293 | + /* printk("initialize_session\n" ); */ | |
11294 | + if( g_sesstab->kvars[index] ) | |
11295 | + return -EMOLINUSE; | |
11296 | + | |
11297 | + if( !g_num_sessions && perform_actions() ) | |
11298 | + return -EMOLGENERAL; | |
11299 | + | |
11300 | + if( !(kv=alloc_kvar_pages()) ) | |
11301 | + goto error; | |
11302 | + | |
11303 | + memset( kv, 0, NUM_KVARS_PAGES * 0x1000 ); | |
11304 | + kv->session_index = index; | |
11305 | + kv->kvars_virt = kv; | |
11306 | + kv_phys = tophys_mol(kv); | |
11307 | + kv->kvars_tophys_offs = kv_phys - (ulong)kv; | |
11308 | + | |
11309 | + if( init_mmu(kv) ) | |
11310 | + goto error; | |
11311 | + | |
11312 | + init_host_irqs(kv); | |
11313 | + initialize_spr_table( kv ); | |
11314 | + | |
11315 | + msr_altered( kv ); | |
11316 | + | |
11317 | + g_num_sessions++; | |
11318 | + | |
11319 | + g_sesstab->kvars_ph[index] = kv_phys; | |
11320 | + g_sesstab->kvars[index] = kv; | |
11321 | + | |
11322 | + return 0; | |
11323 | + error: | |
11324 | + if( !g_num_sessions ) | |
11325 | + cleanup_actions(); | |
11326 | + if( kv ) | |
11327 | + free_kvar_pages( kv ); | |
11328 | + return -EMOLGENERAL; | |
11329 | +} | |
11330 | + | |
11331 | +int | |
11332 | +initialize_session( uint index ) | |
11333 | +{ | |
11334 | + int ret; | |
11335 | + if( index >= MAX_NUM_SESSIONS ) | |
11336 | + return -EMOLINVAL; | |
11337 | + | |
11338 | + SESSION_LOCK; | |
11339 | + ret = initialize_session_( index ); | |
11340 | + SESSION_UNLOCK; | |
11341 | + | |
11342 | + return ret; | |
11343 | +} | |
11344 | + | |
11345 | +void | |
11346 | +destroy_session( uint index ) | |
11347 | +{ | |
11348 | + kernel_vars_t *kv; | |
11349 | + | |
11350 | + if( index >= MAX_NUM_SESSIONS ) | |
11351 | + return; | |
11352 | + | |
11353 | + if( g_sesstab->magic == 1 ) { | |
11354 | + printk("Security alert! Somebody other than MOL has tried to invoke\n" | |
11355 | + "the MOL switch magic. The MOL infrastructure has been disabled.\n" | |
11356 | + "Reboot in order to get MOL running again\n"); | |
11357 | + /* make it impossible to unload the module */ | |
11358 | + prevent_mod_unload(); | |
11359 | + } | |
11360 | + | |
11361 | + SESSION_LOCK; | |
11362 | + if( (kv=g_sesstab->kvars[index]) ) { | |
11363 | + | |
11364 | + g_sesstab->kvars[index] = NULL; | |
11365 | + g_sesstab->kvars_ph[index] = 0; | |
11366 | + | |
11367 | + /* decrease before freeing anything (simplifies deallocation of shared resources) */ | |
11368 | + g_num_sessions--; | |
11369 | + cleanup_host_irqs(kv); | |
11370 | + cleanup_mmu( kv ); | |
11371 | + | |
11372 | + if( kv->emuaccel_page ) | |
11373 | + free_page_mol( kv->emuaccel_page ); | |
11374 | + | |
11375 | + memset( kv, 0, NUM_KVARS_PAGES * 0x1000 ); | |
11376 | + free_kvar_pages( kv ); | |
11377 | + | |
11378 | + if( !g_num_sessions ) | |
11379 | + cleanup_actions(); | |
11380 | + } | |
11381 | + SESSION_UNLOCK; | |
11382 | +} | |
11383 | + | |
11384 | +uint | |
11385 | +get_session_magic( uint random_magic ) | |
11386 | +{ | |
11387 | + if( random_magic < 2 ) | |
11388 | + random_magic = 2; | |
11389 | + /* negative return values are interpreted as errors */ | |
11390 | + random_magic &= 0x7fffffff; | |
11391 | + | |
11392 | + SESSION_LOCK; | |
11393 | + if( !g_sesstab->magic ) | |
11394 | + g_sesstab->magic = random_magic; | |
11395 | + SESSION_UNLOCK; | |
11396 | + | |
11397 | + return g_sesstab->magic; | |
11398 | +} | |
11399 | --- /dev/null | |
11400 | +++ b/drivers/macintosh/mol/misc.c | |
11401 | @@ -0,0 +1,255 @@ | |
11402 | +/* | |
11403 | + * Creation Date: <2003/06/06 20:00:52 samuel> | |
11404 | + * Time-stamp: <2004/03/06 13:54:26 samuel> | |
11405 | + * | |
11406 | + * <misc.c> | |
11407 | + * | |
11408 | + * Miscellaneous | |
11409 | + * | |
11410 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
11411 | + * | |
11412 | + * This program is free software; you can redistribute it and/or | |
11413 | + * modify it under the terms of the GNU General Public License | |
11414 | + * version 2 | |
11415 | + * | |
11416 | + */ | |
11417 | + | |
11418 | +#include "archinclude.h" | |
11419 | +#include "mol-ioctl.h" | |
11420 | +#include "mmu.h" | |
11421 | +#include "mtable.h" | |
11422 | +#include "constants.h" | |
11423 | +#include "asmfuncs.h" | |
11424 | +#include "performance.h" | |
11425 | +#include "misc.h" | |
11426 | +#include "emu.h" | |
11427 | +#include "alloc.h" | |
11428 | +#include "uaccess.h" | |
11429 | + | |
11430 | + | |
11431 | +/************************************************************************/ | |
11432 | +/* Performance Info */ | |
11433 | +/************************************************************************/ | |
11434 | + | |
11435 | +#ifdef PERFORMANCE_INFO | |
11436 | + | |
11437 | +static void | |
11438 | +clear_performance_info( kernel_vars_t *kv ) | |
11439 | +{ | |
11440 | + perf_info_t *p = g_perf_info_table; | |
11441 | + int i; | |
11442 | + | |
11443 | + for( ; p->name ; p++ ) | |
11444 | + *p->ctrptr = 0; | |
11445 | + for( i=0; i<NUM_ASM_BUMP_CNTRS; i++ ) | |
11446 | + kv->asm_bump_cntr[i] = 0; | |
11447 | + kv->num_acntrs = 0; | |
11448 | +} | |
11449 | + | |
11450 | +static int | |
11451 | +get_performance_info( kernel_vars_t *kv, uint ind, perf_ctr_t *r ) | |
11452 | +{ | |
11453 | + perf_info_t *p; | |
11454 | + int len; | |
11455 | + char *name; | |
11456 | + | |
11457 | + for( p=g_perf_info_table; p->name && ind; p++, ind-- ) | |
11458 | + ; | |
11459 | + if( !p->name ) { | |
11460 | + extern int __start_bumptable[], __end_bumptable[]; | |
11461 | + if( ind >= __end_bumptable - __start_bumptable ) | |
11462 | + return 1; | |
11463 | + name = (char*)__start_bumptable + __start_bumptable[ind]; | |
11464 | + r->ctr = kv->asm_bump_cntr[ind]; | |
11465 | + } else { | |
11466 | + name = p->name; | |
11467 | + r->ctr = *p->ctrptr; | |
11468 | + } | |
11469 | + | |
11470 | + if( (len=strlen(name)+1) > sizeof(r->name) ) | |
11471 | + len = sizeof(r->name); | |
11472 | + memcpy( r->name, name, len ); | |
11473 | + return 0; | |
11474 | +} | |
11475 | + | |
11476 | +#else /* PERFORMANCE_INFO */ | |
11477 | + | |
11478 | +static void | |
11479 | +clear_performance_info( kernel_vars_t *kv ) | |
11480 | +{ | |
11481 | +} | |
11482 | + | |
11483 | +static int | |
11484 | +get_performance_info( kernel_vars_t *kv, uint ind, perf_ctr_t *r ) | |
11485 | +{ | |
11486 | + return 1; | |
11487 | +} | |
11488 | + | |
11489 | +#endif /* PERFORMANCE_INFO */ | |
11490 | + | |
11491 | + | |
11492 | + | |
11493 | +/************************************************************************/ | |
11494 | +/* misc */ | |
11495 | +/************************************************************************/ | |
11496 | + | |
11497 | +int | |
11498 | +do_debugger_op( kernel_vars_t *kv, dbg_op_params_t *pb ) | |
11499 | +{ | |
11500 | + int ret = 0; | |
11501 | + | |
11502 | + switch( pb->operation ) { | |
11503 | + case DBG_OP_EMULATE_TLBIE: | |
11504 | + flush_ea_range( kv, (pb->ea & ~0xf0000000), 0x1000 ); | |
11505 | + break; | |
11506 | + | |
11507 | + case DBG_OP_EMULATE_TLBIA: | |
11508 | + clear_all_vsids( kv ); | |
11509 | + break; | |
11510 | + | |
11511 | + case DBG_OP_GET_PTE: | |
11512 | + ret = dbg_get_PTE( kv, pb->context, pb->ea, &pb->ret.pte ); | |
11513 | + break; | |
11514 | + | |
11515 | + case DBG_OP_BREAKPOINT_FLAGS: | |
11516 | + kv->break_flags = pb->param; | |
11517 | + kv->mregs.flag_bits &= ~fb_DbgTrace; | |
11518 | + kv->mregs.flag_bits |= (pb->param & BREAK_SINGLE_STEP)? fb_DbgTrace : 0; | |
11519 | + msr_altered( kv ); | |
11520 | + break; | |
11521 | + | |
11522 | + case DBG_OP_TRANSLATE_EA: | |
11523 | + /* param == is_data_access */ | |
11524 | + ret = dbg_translate_ea( kv, pb->context, pb->ea, &pb->ret.phys, pb->param ); | |
11525 | + break; | |
11526 | + | |
11527 | + default: | |
11528 | + printk("Unimplemended debugger operation %d\n", pb->operation ); | |
11529 | + ret = -ENOSYS_MOL; | |
11530 | + break; | |
11531 | + } | |
11532 | + return ret; | |
11533 | +} | |
11534 | + | |
11535 | +static void | |
11536 | +tune_spr( kernel_vars_t *kv, uint spr, int action ) | |
11537 | +{ | |
11538 | + extern int r__spr_illegal[], r__spr_read_only[], r__spr_read_write[]; | |
11539 | + int hook, newhook=0; | |
11540 | + | |
11541 | + if( spr >= 1024 ) | |
11542 | + return; | |
11543 | + | |
11544 | + hook = kv->_bp.spr_hooks[spr]; | |
11545 | + | |
11546 | + /* LSB of hook specifies whether the SPR is privileged */ | |
11547 | + switch( action ) { | |
11548 | + case kTuneSPR_Illegal: | |
11549 | + newhook = (int)r__spr_illegal; | |
11550 | + hook &= ~1; | |
11551 | + break; | |
11552 | + | |
11553 | + case kTuneSPR_Privileged: | |
11554 | + hook |= 1; | |
11555 | + break; | |
11556 | + | |
11557 | + case kTuneSPR_Unprivileged: | |
11558 | + hook &= ~1; | |
11559 | + break; | |
11560 | + | |
11561 | + case kTuneSPR_ReadWrite: | |
11562 | + newhook = (int)r__spr_read_write; | |
11563 | + break; | |
11564 | + | |
11565 | + case kTuneSPR_ReadOnly: | |
11566 | + newhook = (int)r__spr_read_only; | |
11567 | + break; | |
11568 | + } | |
11569 | + if( newhook ) | |
11570 | + hook = (hook & 1) | tophys_mol( (char*)reloc_ptr(newhook) ); | |
11571 | + kv->_bp.spr_hooks[spr] = hook; | |
11572 | +} | |
11573 | + | |
11574 | +/* return value: <0: system error, >=0: ret value */ | |
11575 | +int | |
11576 | +handle_ioctl( kernel_vars_t *kv, int cmd, int arg1, int arg2, int arg3 ) | |
11577 | +{ | |
11578 | + struct mmu_mapping map; | |
11579 | + perf_ctr_t pctr; | |
11580 | + int ret = 0; | |
11581 | + | |
11582 | + switch( cmd ) { | |
11583 | + case MOL_IOCTL_GET_SESSION_MAGIC: | |
11584 | + ret = get_session_magic( arg1 ); | |
11585 | + break; | |
11586 | + | |
11587 | + case MOL_IOCTL_IDLE_RECLAIM_MEMORY: | |
11588 | + mtable_reclaim( kv ); | |
11589 | + break; | |
11590 | + | |
11591 | + case MOL_IOCTL_SPR_CHANGED: | |
11592 | + msr_altered(kv); | |
11593 | + mmu_altered(kv); | |
11594 | + break; | |
11595 | + | |
11596 | + case MOL_IOCTL_ADD_IORANGE: /* void ( ulong mbase, int size, void *usr_data )*/ | |
11597 | + add_io_trans( kv, arg1, arg2, (void*)arg3 ); | |
11598 | + break; | |
11599 | + case MOL_IOCTL_REMOVE_IORANGE: /* void ( ulong mbase, int size ) */ | |
11600 | + remove_io_trans( kv, arg1, arg2 ); | |
11601 | + break; | |
11602 | + | |
11603 | + case MOL_IOCTL_ALLOC_EMUACCEL_SLOT: /* EMULATE_xxx, param, ret_addr -- mphys */ | |
11604 | + ret = alloc_emuaccel_slot( kv, arg1, arg2, arg3 ); | |
11605 | + break; | |
11606 | + case MOL_IOCTL_MAPIN_EMUACCEL_PAGE: /* arg1 = mphys */ | |
11607 | + ret = mapin_emuaccel_page( kv, arg1 ); | |
11608 | + break; | |
11609 | + | |
11610 | + case MOL_IOCTL_SETUP_FBACCEL: /* lvbase, bytes_per_row, height */ | |
11611 | + setup_fb_acceleration( kv, (char*)arg1, arg2, arg3 ); | |
11612 | + break; | |
11613 | + case MOL_IOCTL_TUNE_SPR: /* spr#, action */ | |
11614 | + tune_spr( kv, arg1, arg2 ); | |
11615 | + break; | |
11616 | + | |
11617 | + case MOL_IOCTL_MMU_MAP: /* arg1=struct mmu_mapping *m, arg2=map/unmap */ | |
11618 | + if( copy_from_user_mol(&map, (struct mmu_mapping*)arg1, sizeof(map)) ) | |
11619 | + break; | |
11620 | + if( arg2 ) | |
11621 | + mmu_add_map( kv, &map ); | |
11622 | + else | |
11623 | + mmu_remove_map( kv, &map ); | |
11624 | + if( copy_to_user_mol((struct mmu_mapping*)arg1, &map, sizeof(map)) ) | |
11625 | + ret = -EFAULT_MOL; | |
11626 | + break; | |
11627 | + | |
11628 | + case MOL_IOCTL_GET_PERF_INFO: | |
11629 | + ret = get_performance_info( kv, arg1, &pctr ); | |
11630 | + if( copy_to_user_mol((perf_ctr_t*)arg2, &pctr, sizeof(pctr)) ) | |
11631 | + ret = -EFAULT_MOL; | |
11632 | + break; | |
11633 | + | |
11634 | +#if 0 | |
11635 | + case MOL_IOCTL_TRACK_DIRTY_RAM: | |
11636 | + ret = track_lvrange( kv ); | |
11637 | + break; | |
11638 | + case MOL_IOCTL_GET_DIRTY_RAM: | |
11639 | + ret = get_track_buffer( kv, (char*)arg1 ); | |
11640 | + break; | |
11641 | + case MOL_IOCTL_SET_DIRTY_RAM: | |
11642 | + set_track_buffer( kv, (char*)arg1 ); | |
11643 | + break; | |
11644 | +#endif | |
11645 | + /* ---------------- performance statistics ------------------ */ | |
11646 | + | |
11647 | + case MOL_IOCTL_CLEAR_PERF_INFO: | |
11648 | + clear_performance_info( kv ); | |
11649 | + break; | |
11650 | + | |
11651 | + default: | |
11652 | + printk("unsupported MOL ioctl %d\n", cmd ); | |
11653 | + ret = -ENOSYS_MOL; | |
11654 | + } | |
11655 | + return ret; | |
11656 | +} | |
11657 | --- /dev/null | |
11658 | +++ b/drivers/macintosh/mol/mmu.c | |
11659 | @@ -0,0 +1,251 @@ | |
11660 | +/* | |
11661 | + * Creation Date: <1998-11-11 11:56:45 samuel> | |
11662 | + * Time-stamp: <2004/03/13 14:25:26 samuel> | |
11663 | + * | |
11664 | + * <mmu.c> | |
11665 | + * | |
11666 | + * Handles page mappings and the mac MMU | |
11667 | + * | |
11668 | + * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se) | |
11669 | + * | |
11670 | + * This program is free software; you can redistribute it and/or | |
11671 | + * modify it under the terms of the GNU General Public License | |
11672 | + * as published by the Free Software Foundation | |
11673 | + * | |
11674 | + */ | |
11675 | + | |
11676 | +#include "archinclude.h" | |
11677 | +#include "alloc.h" | |
11678 | +#include "kernel_vars.h" | |
11679 | +#include "mmu.h" | |
11680 | +#include "mmu_contexts.h" | |
11681 | +#include "asmfuncs.h" | |
11682 | +#include "emu.h" | |
11683 | +#include "misc.h" | |
11684 | +#include "mtable.h" | |
11685 | +#include "performance.h" | |
11686 | +#include "context.h" | |
11687 | +#include "hash.h" | |
11688 | +#include "map.h" | |
11689 | + | |
11690 | +#define MREGS (kv->mregs) | |
11691 | +#define MMU (kv->mmu) | |
11692 | + | |
11693 | + | |
11694 | +/************************************************************************/ | |
11695 | +/* init / cleanup */ | |
11696 | +/************************************************************************/ | |
11697 | + | |
11698 | +int | |
11699 | +init_mmu( kernel_vars_t *kv ) | |
11700 | +{ | |
11701 | + int success; | |
11702 | + | |
11703 | + success = | |
11704 | + !arch_mmu_init( kv ) && | |
11705 | + !init_contexts( kv ) && | |
11706 | + !init_mtable( kv ) && | |
11707 | + !init_mmu_io( kv ) && | |
11708 | + !init_mmu_fb( kv ) && | |
11709 | + !init_mmu_tracker( kv ); | |
11710 | + | |
11711 | + if( !success ) { | |
11712 | + cleanup_mmu( kv ); | |
11713 | + return 1; | |
11714 | + } | |
11715 | + | |
11716 | + clear_vsid_refs( kv ); | |
11717 | + | |
11718 | + /* SDR1 is set from fStartEmulation */ | |
11719 | + return 0; | |
11720 | +} | |
11721 | + | |
11722 | +void | |
11723 | +cleanup_mmu( kernel_vars_t *kv ) | |
11724 | +{ | |
11725 | + /* We have to make sure the flush thread are not using the mtable | |
11726 | + * facilities. The kvars entry has been clear so we just have | |
11727 | + * to wait around until no threads are using it. | |
11728 | + */ | |
11729 | + while( atomic_read_mol(&g_sesstab->external_thread_cnt) ) | |
11730 | + ; | |
11731 | + | |
11732 | + cleanup_mmu_tracker( kv ); | |
11733 | + cleanup_mmu_fb( kv ); | |
11734 | + cleanup_mmu_io( kv ); | |
11735 | + cleanup_mtable( kv ); | |
11736 | + cleanup_contexts( kv ); | |
11737 | + | |
11738 | + if( MMU.pthash_inuse_bits ) | |
11739 | + kfree_cont_mol( MMU.pthash_inuse_bits ); | |
11740 | + if( MMU.hash_base ) | |
11741 | + unmap_emulated_hash( kv ); | |
11742 | + | |
11743 | + memset( &MMU, 0, sizeof(mmu_vars_t) ); | |
11744 | +} | |
11745 | + | |
11746 | + | |
11747 | +/************************************************************************/ | |
11748 | +/* misc */ | |
11749 | +/************************************************************************/ | |
11750 | + | |
11751 | +/* All vsid entries have been flushed; clear dangling pointers */ | |
11752 | +void | |
11753 | +clear_vsid_refs( kernel_vars_t *kv ) | |
11754 | +{ | |
11755 | + int i; | |
11756 | + for( i=0; i<16; i++ ) { | |
11757 | + MMU.vsid[i] = NULL; | |
11758 | + MMU.unmapped_vsid[i] = NULL; | |
11759 | + | |
11760 | + MMU.user_sr[i] = MMU.illegal_sr; | |
11761 | + MMU.sv_sr[i] = MMU.illegal_sr; | |
11762 | + MMU.unmapped_sr[i] = MMU.illegal_sr; | |
11763 | + MMU.split_sr[i] = MMU.illegal_sr; | |
11764 | + } | |
11765 | + invalidate_splitmode_sr( kv ); | |
11766 | +} | |
11767 | + | |
11768 | +/* | |
11769 | + * This function is called whenever the mac MMU-registers have | |
11770 | + * been manipulated externally. | |
11771 | + */ | |
11772 | +void | |
11773 | +mmu_altered( kernel_vars_t *kv ) | |
11774 | +{ | |
11775 | + int i; | |
11776 | + | |
11777 | + for( i=0; i<16; i++ ) { | |
11778 | + MMU.vsid[i] = NULL; | |
11779 | + MMU.user_sr[i] = MMU.illegal_sr; | |
11780 | + MMU.sv_sr[i] = MMU.illegal_sr; | |
11781 | + } | |
11782 | + invalidate_splitmode_sr( kv ); | |
11783 | + | |
11784 | + do_mtsdr1( kv, MREGS.spr[S_SDR1] ); | |
11785 | + | |
11786 | + for( i=0; i<16; i++ ) | |
11787 | + do_mtbat( kv, S_IBAT0U+i, MREGS.spr[ S_IBAT0U+i ], 1 ); | |
11788 | +} | |
11789 | + | |
11790 | +/* | |
11791 | + * A page we might be using is about to be destroyed (e.g. swapped out). | |
11792 | + * Any PTEs referencing this page must be flushed. The context parameter | |
11793 | + * is vsid >> 4. | |
11794 | + * | |
11795 | + * ENTRYPOINT! | |
11796 | + */ | |
11797 | +void | |
11798 | +do_flush( ulong context, ulong va, ulong *dummy, int n ) | |
11799 | +{ | |
11800 | + int i; | |
11801 | + kernel_vars_t *kv; | |
11802 | + BUMP( do_flush ); | |
11803 | + | |
11804 | + atomic_inc_mol( &g_sesstab->external_thread_cnt ); | |
11805 | + | |
11806 | + for( i=0; i<MAX_NUM_SESSIONS; i++ ) { | |
11807 | + if( !(kv=g_sesstab->kvars[i]) || context != kv->mmu.emulator_context ) | |
11808 | + continue; | |
11809 | + | |
11810 | + BUMP_N( block_destroyed_ctr, n ); | |
11811 | + for( ; n-- ; va += 0x1000 ) | |
11812 | + flush_lvptr( kv, va ); | |
11813 | + break; | |
11814 | + } | |
11815 | + | |
11816 | + atomic_dec_mol( &g_sesstab->external_thread_cnt ); | |
11817 | +} | |
11818 | + | |
11819 | + | |
11820 | +/************************************************************************/ | |
11821 | +/* Debugger functions */ | |
11822 | +/************************************************************************/ | |
11823 | + | |
11824 | +int | |
11825 | +dbg_get_PTE( kernel_vars_t *kv, int context, ulong va, mPTE_t *retptr ) | |
11826 | +{ | |
11827 | + ulong base, mask; | |
11828 | + ulong vsid, ptmp, stmp, *pteg, *steg; | |
11829 | + ulong cmp; | |
11830 | + ulong *uret = (ulong*)retptr; | |
11831 | + int i, num_match=0; | |
11832 | + | |
11833 | + switch( context ) { | |
11834 | + case kContextUnmapped: | |
11835 | + vsid = MMU.unmapped_sr[va>>28]; | |
11836 | + break; | |
11837 | + case kContextMapped_S: | |
11838 | + vsid = MMU.sv_sr[va>>28]; | |
11839 | + break; | |
11840 | + case kContextMapped_U: | |
11841 | + vsid = MMU.user_sr[va>>28]; | |
11842 | + break; | |
11843 | + case kContextEmulator: | |
11844 | + vsid = (MUNGE_CONTEXT(MMU.emulator_context) + ((va>>28) * MUNGE_ESID_ADD)) & 0xffffff; | |
11845 | + break; | |
11846 | + case kContextKernel: | |
11847 | + vsid = 0; | |
11848 | + break; | |
11849 | + default: | |
11850 | + printk("get_PTE: no such context: %d\n", context ); | |
11851 | + return 0; | |
11852 | + } | |
11853 | + | |
11854 | + /* mask vsid and va */ | |
11855 | + vsid &= 0xffffff; | |
11856 | + va &= 0x0ffff000; | |
11857 | + | |
11858 | + /* get hash base and hash mask */ | |
11859 | + base = (ulong)ptehash.base; | |
11860 | + mask = ptehash.pteg_mask >> 6; | |
11861 | + | |
11862 | + /* hash function */ | |
11863 | + ptmp = (vsid ^ (va>>12)) & mask; | |
11864 | + stmp = mask & ~ptmp; | |
11865 | + pteg = (ulong*)((ptmp << 6) + base); | |
11866 | + steg = (ulong*)((stmp << 6) + base); | |
11867 | + | |
11868 | + /* construct compare word */ | |
11869 | + cmp = 0x80000000 | (vsid <<7) | (va>>22); | |
11870 | + | |
11871 | + /* look in primary PTEG */ | |
11872 | + for( i=0; i<8; i++ ) { | |
11873 | + if( cmp == pteg[i*2] ) { | |
11874 | + if( !num_match++ && uret ) { | |
11875 | + uret[0] = pteg[i*2]; | |
11876 | + uret[1] = pteg[i*2+1]; | |
11877 | + } | |
11878 | + if( num_match == 2 ) { | |
11879 | + printk("Internal ERROR: duplicate PTEs!\n"); | |
11880 | + printk("p-hash: low_pte: %08lX high_pte: %08lX\n", | |
11881 | + uret ? uret[0]:0, retptr? uret[1]:0 ); | |
11882 | + } | |
11883 | + if( num_match >= 2 ) { | |
11884 | + printk("p-hash: low_pte: %08lX high_pte: %08lX\n", | |
11885 | + pteg[i*2], pteg[i*2+1] ); | |
11886 | + } | |
11887 | + } | |
11888 | + } | |
11889 | + | |
11890 | + /* look in secondary PTEG */ | |
11891 | + cmp |= 0x40; | |
11892 | + for( i=0; i<8; i++ ) { | |
11893 | + if( cmp == steg[i*2] ) { | |
11894 | + if( !num_match++ && uret ) { | |
11895 | + uret[0] = steg[i*2]; | |
11896 | + uret[1] = steg[i*2+1]; | |
11897 | + } | |
11898 | + if( num_match == 2 ) { | |
11899 | + printk("Internal ERROR: duplicate PTEs!\n"); | |
11900 | + printk("?-hash: low_pte: %08lX high_pte: %08lX\n", | |
11901 | + uret? uret[0]:0, uret? uret[1]:0 ); | |
11902 | + } | |
11903 | + if( num_match >= 2 ) { | |
11904 | + printk("s-hash: low_pte: %08lX high_pte: %08lX\n", | |
11905 | + steg[i*2], steg[i*2+1] ); | |
11906 | + } | |
11907 | + } | |
11908 | + } | |
11909 | + return num_match; | |
11910 | +} | |
11911 | --- /dev/null | |
11912 | +++ b/drivers/macintosh/mol/mmu_fb.c | |
11913 | @@ -0,0 +1,186 @@ | |
11914 | +/* | |
11915 | + * Creation Date: <1999-12-28 14:03:18 samuel> | |
11916 | + * Time-stamp: <2004/02/14 14:52:52 samuel> | |
11917 | + * | |
11918 | + * <mmu_fb.c> | |
11919 | + * | |
11920 | + * Offscreen framebuffer acceleration | |
11921 | + * | |
11922 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
11923 | + * | |
11924 | + * This program is free software; you can redistribute it and/or | |
11925 | + * modify it under the terms of the GNU General Public License | |
11926 | + * as published by the Free Software Foundation | |
11927 | + * | |
11928 | + */ | |
11929 | + | |
11930 | +#include "archinclude.h" | |
11931 | +#include "alloc.h" | |
11932 | +#include "uaccess.h" | |
11933 | +#include "mmu.h" | |
11934 | +#include "asmfuncs.h" | |
11935 | +#include "performance.h" | |
11936 | +#include "misc.h" | |
11937 | + | |
11938 | +typedef struct line_entry { | |
11939 | + short y1, y2; | |
11940 | + int dirty; | |
11941 | + ulong *slot; | |
11942 | + ulong pte0; | |
11943 | + ulong pte1; | |
11944 | + ulong ea; | |
11945 | +} line_entry_t; | |
11946 | + | |
11947 | +typedef struct fb_data { | |
11948 | + line_entry_t *line_table; | |
11949 | + int nrec; | |
11950 | + char *lv_base; /* linux virtual of first entry in table */ | |
11951 | +} fb_data_t; | |
11952 | + | |
11953 | +#define MMU (kv->mmu) | |
11954 | +#define DECLARE_FB fb_data_t *fb = MMU.fb_data | |
11955 | + | |
11956 | +#ifdef __darwin__ | |
11957 | +static inline void | |
11958 | +__put_user( short val, short *destptr ) | |
11959 | +{ | |
11960 | + copy_to_user_mol( destptr, &val, sizeof(short) ); | |
11961 | +} | |
11962 | +#endif | |
11963 | + | |
11964 | + | |
11965 | +int | |
11966 | +init_mmu_fb( kernel_vars_t *kv ) | |
11967 | +{ | |
11968 | + /* setup_fb_acceleration does the initialization */ | |
11969 | + return 0; | |
11970 | +} | |
11971 | + | |
11972 | +void | |
11973 | +cleanup_mmu_fb( kernel_vars_t *kv ) | |
11974 | +{ | |
11975 | + DECLARE_FB; | |
11976 | + if( !fb ) | |
11977 | + return; | |
11978 | + if( fb->line_table ) | |
11979 | + vfree_mol( fb->line_table ); | |
11980 | + | |
11981 | + kfree_mol( fb ); | |
11982 | + MMU.fb_data = NULL; | |
11983 | +} | |
11984 | + | |
11985 | +void | |
11986 | +video_pte_inserted( kernel_vars_t *kv, ulong lvptr, ulong *slot, ulong pte0, ulong pte1, ulong ea ) | |
11987 | +{ | |
11988 | + DECLARE_FB; | |
11989 | + int i; | |
11990 | + | |
11991 | + if( !fb ) | |
11992 | + return; | |
11993 | + | |
11994 | + i = (lvptr - (ulong)fb->lv_base) >> 12; | |
11995 | + if( i >= 0 && i < fb->nrec ) { | |
11996 | + line_entry_t *p = &fb->line_table[i]; | |
11997 | + | |
11998 | + /* allow at most one video PTE to be mapped at any time */ | |
11999 | + if( p->slot && (p->slot != slot || p->pte0 != pte0) ) { | |
12000 | + BUMP( video_pte_reinsert ); | |
12001 | + if( p->slot != slot ) | |
12002 | + p->slot[0] = 0; | |
12003 | + __tlbie(p->ea); | |
12004 | + p->dirty = 1; | |
12005 | + } | |
12006 | + | |
12007 | + p->slot = slot; | |
12008 | + p->pte0 = pte0; | |
12009 | + p->pte1 = pte1 & ~PTE1_C; | |
12010 | + p->ea = ea; | |
12011 | + } else { | |
12012 | + printk("Warning: video_page outside range, %lx %p\n", lvptr, fb->lv_base ); | |
12013 | + } | |
12014 | +} | |
12015 | + | |
12016 | +/* setup/remove framebuffer acceleration */ | |
12017 | +void | |
12018 | +setup_fb_acceleration( kernel_vars_t *kv, char *lvbase, int bytes_per_row, int height ) | |
12019 | +{ | |
12020 | + DECLARE_FB; | |
12021 | + int i, offs = (ulong)lvbase & 0xfff; | |
12022 | + line_entry_t *p; | |
12023 | + | |
12024 | + if( fb ) | |
12025 | + cleanup_mmu_fb( kv ); | |
12026 | + if( !lvbase ) | |
12027 | + return; | |
12028 | + if( !(fb=kmalloc_mol(sizeof(fb_data_t))) ) | |
12029 | + return; | |
12030 | + memset( fb, 0, sizeof(fb_data_t) ); | |
12031 | + MMU.fb_data = fb; | |
12032 | + | |
12033 | + fb->nrec = (bytes_per_row * height + offs + 0xfff) >> 12; | |
12034 | + if( !(p=(line_entry_t*)vmalloc_mol(sizeof(line_entry_t) * fb->nrec)) ) { | |
12035 | + cleanup_mmu_fb( kv ); | |
12036 | + return; | |
12037 | + } | |
12038 | + memset( p, 0, sizeof(line_entry_t) * fb->nrec ); | |
12039 | + fb->line_table = p; | |
12040 | + | |
12041 | + fb->lv_base = (char*)((ulong)lvbase & ~0xfff); | |
12042 | + for( i=0; i<fb->nrec; i++, p++ ){ | |
12043 | + p->y1 = (0x1000*i - offs) / bytes_per_row; | |
12044 | + p->y2 = (0x1000*(i+1)-1 -offs) / bytes_per_row; | |
12045 | + if( p->y1 < 0 ) | |
12046 | + p->y1 = 0; | |
12047 | + if( p->y2 >= height ) | |
12048 | + p->y2 = height-1; | |
12049 | + | |
12050 | + /* we should make sure the page is really unmapped here! */ | |
12051 | + p->slot = NULL; | |
12052 | + } | |
12053 | +} | |
12054 | + | |
12055 | +/* return format is {startline,endline} pairs */ | |
12056 | +int | |
12057 | +get_dirty_fb_lines( kernel_vars_t *kv, short *userbuf, int num_bytes ) | |
12058 | +{ | |
12059 | + DECLARE_FB; | |
12060 | + int i, n, s, start; | |
12061 | + line_entry_t *p; | |
12062 | + | |
12063 | + s = num_bytes/sizeof(short[2]) - 1; | |
12064 | + | |
12065 | + if( !fb || (uint)s <= 0 ) | |
12066 | + return -1; | |
12067 | + | |
12068 | + p = fb->line_table; | |
12069 | + for( start=-1, n=0, i=0; i<fb->nrec; i++, p++ ) { | |
12070 | + if( p->slot ) { | |
12071 | + if( p->slot[0] != p->pte0 ) { | |
12072 | + /* evicted FB PTE */ | |
12073 | + p->slot = NULL; | |
12074 | + p->dirty = 1; | |
12075 | + __tlbie( p->ea ); | |
12076 | + } else if( p->slot[1] & BIT(24) ) { /* C-BIT */ | |
12077 | + p->dirty = 1; | |
12078 | + __store_PTE( p->ea, p->slot, p->pte0, p->pte1 ); | |
12079 | + BUMP(fb_ptec_flush); | |
12080 | + } | |
12081 | + } | |
12082 | + if( p->dirty && start < 0 ) | |
12083 | + start = p->y1; | |
12084 | + else if( !p->dirty && start >= 0 ) { | |
12085 | + __put_user( start, userbuf++ ); | |
12086 | + __put_user( p->y2, userbuf++ ); | |
12087 | + start = -1; | |
12088 | + if( ++n >= s ) | |
12089 | + break; | |
12090 | + } | |
12091 | + p->dirty = 0; | |
12092 | + } | |
12093 | + if( start >= 0 ) { | |
12094 | + __put_user( start, userbuf++ ); | |
12095 | + __put_user( fb->line_table[fb->nrec-1].y2, userbuf++ ); | |
12096 | + n++; | |
12097 | + } | |
12098 | + return n; | |
12099 | +} | |
12100 | --- /dev/null | |
12101 | +++ b/drivers/macintosh/mol/mmu_io.c | |
12102 | @@ -0,0 +1,470 @@ | |
12103 | +/* | |
12104 | + * Creation Date: <1998-12-02 03:23:31 samuel> | |
12105 | + * Time-stamp: <2004/03/13 16:57:31 samuel> | |
12106 | + * | |
12107 | + * <mmu_io.c> | |
12108 | + * | |
12109 | + * Translate mac_phys to whatever has been mapped in at | |
12110 | + * a particular address (linux ram, framebuffer, ROM, etc.) | |
12111 | + * | |
12112 | + * Copyright (C) 1998-2004 Samuel Rydh (samuel@ibrium.se) | |
12113 | + * | |
12114 | + * This program is free software; you can redistribute it and/or | |
12115 | + * modify it under the terms of the GNU General Public License | |
12116 | + * as published by the Free Software Foundation | |
12117 | + * | |
12118 | + */ | |
12119 | + | |
12120 | +#include "archinclude.h" | |
12121 | +#include "alloc.h" | |
12122 | +#include "kernel_vars.h" | |
12123 | +#include "mmu.h" | |
12124 | +#include "misc.h" | |
12125 | +#include "mtable.h" | |
12126 | +#include "performance.h" | |
12127 | +#include "processor.h" | |
12128 | + | |
12129 | +#define MAX_BLOCK_TRANS 6 | |
12130 | + | |
12131 | +/* Block translations are used for ROM, RAM, VRAM and similar things. | |
12132 | + * | |
12133 | + * IO-translations are a different type of mappings. Whenever an IO-area | |
12134 | + * is accessed, a page fault occurs. If there is a page present (although | |
12135 | + * r/w prohibited), then the low-level exception handler examines if the | |
12136 | + * page has a magic signature in the first 8 bytes. If there is a match, | |
12137 | + * then the page is of the type io_page_t and contains the information | |
12138 | + * necessary to emulate the IO. If no page is present, then the corresponding | |
12139 | + * IO-page is looked up and hashed. | |
12140 | + */ | |
12141 | + | |
12142 | +typedef struct { | |
12143 | + ulong mbase; | |
12144 | + char *lvbase; | |
12145 | + pte_lvrange_t *lvrange; | |
12146 | + | |
12147 | + size_t size; | |
12148 | + int flags; | |
12149 | + | |
12150 | + int id; | |
12151 | +} block_trans_t; | |
12152 | + | |
12153 | +typedef struct io_data { | |
12154 | + block_trans_t btable[MAX_BLOCK_TRANS]; | |
12155 | + int num_btrans; | |
12156 | + int next_free_id; | |
12157 | + io_page_t *io_page_head; | |
12158 | +} io_data_t; | |
12159 | + | |
12160 | +static char *scratch_page; | |
12161 | + | |
12162 | +#define MMU (kv->mmu) | |
12163 | +#define DECLARE_IOD io_data_t *iod = kv->mmu.io_data | |
12164 | + | |
12165 | + | |
12166 | + | |
12167 | +int | |
12168 | +init_mmu_io( kernel_vars_t *kv ) | |
12169 | +{ | |
12170 | + if( !(MMU.io_data=kmalloc_mol(sizeof(io_data_t))) ) | |
12171 | + return 1; | |
12172 | + memset( MMU.io_data, 0, sizeof(io_data_t) ); | |
12173 | + return 0; | |
12174 | +} | |
12175 | + | |
12176 | +void | |
12177 | +cleanup_mmu_io( kernel_vars_t *kv ) | |
12178 | +{ | |
12179 | + DECLARE_IOD; | |
12180 | + io_page_t *next2, *p2; | |
12181 | + int i; | |
12182 | + | |
12183 | + if( !iod ) | |
12184 | + return; | |
12185 | + | |
12186 | + for( p2=iod->io_page_head; p2; p2=next2 ) { | |
12187 | + next2 = p2->next; | |
12188 | + free_page_mol( (ulong)p2 ); | |
12189 | + } | |
12190 | + iod->io_page_head = 0; | |
12191 | + | |
12192 | + /* release the scratch page (not always allocated) */ | |
12193 | + if( !g_num_sessions && scratch_page ) { | |
12194 | + free_page_mol( (int)scratch_page ); | |
12195 | + scratch_page = 0; | |
12196 | + } | |
12197 | + | |
12198 | + /* release any lvranges */ | |
12199 | + for( i=0; i<iod->num_btrans; i++ ) | |
12200 | + if( iod->btable[i].lvrange ) | |
12201 | + free_lvrange( kv, iod->btable[i].lvrange ); | |
12202 | + | |
12203 | + kfree_mol( iod ); | |
12204 | + MMU.io_data = NULL; | |
12205 | +} | |
12206 | + | |
12207 | + | |
12208 | +/* This is primarily intended for framebuffers */ | |
12209 | +static int | |
12210 | +bat_align( int flags, ulong ea, ulong lphys, ulong size, ulong bat[2] ) | |
12211 | +{ | |
12212 | + ulong s; | |
12213 | + ulong offs1, offs2; | |
12214 | + | |
12215 | + s=0x20000; /* 128K */ | |
12216 | + if( s> size ) | |
12217 | + return 1; | |
12218 | + /* Limit to 128MB in order not to cross segments (256MB is bat-max) */ | |
12219 | + if( size > 0x10000000 ) | |
12220 | + size = 0x10000000; | |
12221 | + for( ; s<size ; s = (s<<1) ) | |
12222 | + ; | |
12223 | + offs1 = ea & (s-1); | |
12224 | + offs2 = lphys & (s-1); | |
12225 | + if( offs1 != offs2 ) { | |
12226 | + printk("Can't use DBAT since offsets differ (%ld != %ld)\n", offs1, offs2 ); | |
12227 | + return 1; | |
12228 | + } | |
12229 | + /* BEPI | BL | VS | VP */ | |
12230 | + bat[0] = (ea & ~(s-1)) | (((s-1)>>17) << 2) | 3; | |
12231 | + bat[1] = (lphys & ~(s-1)) | 2; /* pp=10, R/W */ | |
12232 | + | |
12233 | +#ifndef CONFIG_AMIGAONE | |
12234 | + bat[1] |= BIT(27); /* [M] (memory coherence) */ | |
12235 | +#endif | |
12236 | + | |
12237 | + if( !(flags & MAPPING_FORCE_CACHE) ) { | |
12238 | + bat[1] |= BIT(26); /* [I] (inhibit cache) */ | |
12239 | + } else { | |
12240 | + bat[1] |= BIT(25); /* [W] (write through) */ | |
12241 | + } | |
12242 | + return 0; | |
12243 | +} | |
12244 | + | |
12245 | + | |
12246 | +/* | |
12247 | + * Handle block translations (translations of mac-physical | |
12248 | + * blocks to linux virtual physical addresses) | |
12249 | + */ | |
12250 | +static int | |
12251 | +add_block_trans( kernel_vars_t *kv, ulong mbase, char *lvbase, ulong size, int flags ) | |
12252 | +{ | |
12253 | + DECLARE_IOD; | |
12254 | + block_trans_t *bt; | |
12255 | + pte_lvrange_t *lvrange = NULL; | |
12256 | + int ind, i; | |
12257 | + | |
12258 | + /* warn if things are not aligned properly */ | |
12259 | + if( (size & 0xfff) || ((int)lvbase & 0xfff) || (mbase & 0xfff) ) | |
12260 | + printk("Bad block translation alignement\n"); | |
12261 | + | |
12262 | + /* we keep an unsorted list - RAM should be added first, then ROM, then VRAM etc */ | |
12263 | + if( iod->num_btrans >= MAX_BLOCK_TRANS ) { | |
12264 | + printk("Maximal number of block translations exceeded!\n"); | |
12265 | + return -1; | |
12266 | + } | |
12267 | + | |
12268 | + /* remove illegal combinations */ | |
12269 | + flags &= ~MAPPING_IO; | |
12270 | + if( (flags & MAPPING_DBAT) && !(flags & MAPPING_PHYSICAL) ) | |
12271 | + flags &= ~MAPPING_DBAT; | |
12272 | + | |
12273 | + /* scratch pages are always physical - lvbase isn't used */ | |
12274 | + if( (flags & MAPPING_SCRATCH) ) { | |
12275 | + lvbase = NULL; | |
12276 | + flags |= MAPPING_PHYSICAL; | |
12277 | + flags &= ~MAPPING_DBAT; | |
12278 | + } | |
12279 | + | |
12280 | + /* IMPORTANT: DBATs can _only_ be used when we KNOW that ea == mphys. */ | |
12281 | + if( (flags & MAPPING_DBAT) ) { | |
12282 | + ulong bat[2]; | |
12283 | + if( !bat_align(flags, mbase, (ulong)lvbase, size, bat) ) { | |
12284 | + /* printk("BATS: %08lX %08lX\n", bat[0], bat[1] ); */ | |
12285 | + MMU.transl_dbat0.word[0] = bat[0]; | |
12286 | + MMU.transl_dbat0.word[1] = bat[1]; | |
12287 | + } | |
12288 | + } | |
12289 | + | |
12290 | + if( !(flags & MAPPING_PHYSICAL) ) | |
12291 | + if( !(lvrange=register_lvrange(kv, lvbase, size)) ) | |
12292 | + return -1; | |
12293 | + | |
12294 | + /* Determine where to insert the translation in the table. | |
12295 | + * RAM should go right efter entries marked with MAPPING_PUT_FIRST. | |
12296 | + * The MAPPING_PUT_FIRST flag is used to do magic things like | |
12297 | + * embedding a copy of mregs in RAM. | |
12298 | + */ | |
12299 | + ind = (!mbase || (flags & MAPPING_PUT_FIRST)) ? 0 : iod->num_btrans; | |
12300 | + for( i=0; i<iod->num_btrans && ind <= i; i++ ) | |
12301 | + if( iod->btable[i].flags & MAPPING_PUT_FIRST ) | |
12302 | + ind++; | |
12303 | + bt = &iod->btable[ind]; | |
12304 | + if( ind < iod->num_btrans ) | |
12305 | + memmove( &iod->btable[ind+1], bt, sizeof(iod->btable[0]) * (iod->num_btrans - ind) ); | |
12306 | + iod->num_btrans++; | |
12307 | + memset( bt, 0, sizeof(block_trans_t) ); | |
12308 | + | |
12309 | + bt->mbase = mbase; | |
12310 | + bt->lvbase = lvbase; | |
12311 | + bt->lvrange = lvrange; | |
12312 | + bt->size = size; | |
12313 | + bt->flags = flags | MAPPING_VALID; | |
12314 | + bt->id = ++iod->next_free_id; | |
12315 | + | |
12316 | + /* flush everything if we a translation was overridden */ | |
12317 | + if( flags & MAPPING_PUT_FIRST ) | |
12318 | + clear_pte_hash_table( kv ); | |
12319 | + | |
12320 | + return bt->id; | |
12321 | +} | |
12322 | + | |
12323 | +static void | |
12324 | +remove_block_trans( kernel_vars_t *kv, int id ) | |
12325 | +{ | |
12326 | + DECLARE_IOD; | |
12327 | + block_trans_t *p; | |
12328 | + int i; | |
12329 | + | |
12330 | + /* Remove all mappings in the TLB table... | |
12331 | + * (too difficult to find the entries we need to flush) | |
12332 | + */ | |
12333 | + BUMP(remove_block_trans); | |
12334 | + clear_pte_hash_table( kv ); | |
12335 | + | |
12336 | + for( p=iod->btable, i=0; i<iod->num_btrans; i++, p++ ) { | |
12337 | + if( id == p->id ) { | |
12338 | + if( p->flags & MAPPING_DBAT ) { | |
12339 | + MMU.transl_dbat0.word[0] = 0; | |
12340 | + MMU.transl_dbat0.word[1] = 0; | |
12341 | + } | |
12342 | + if( p->lvrange ) | |
12343 | + free_lvrange( kv, p->lvrange ); | |
12344 | + | |
12345 | + memmove( p,p+1, (iod->num_btrans-1-i)*sizeof(block_trans_t) ); | |
12346 | + iod->num_btrans--; | |
12347 | + return; | |
12348 | + } | |
12349 | + } | |
12350 | + printk("Trying to remove nonexistent block mapping!\n"); | |
12351 | +} | |
12352 | + | |
12353 | +/* adds an I/O-translation. It is legal to add the same | |
12354 | + * range multiple times (for instance, to alter usr_data) | |
12355 | + */ | |
12356 | +int | |
12357 | +add_io_trans( kernel_vars_t *kv, ulong mbase, int size, void *usr_data ) | |
12358 | +{ | |
12359 | + DECLARE_IOD; | |
12360 | + io_page_t *ip, **pre_next; | |
12361 | + ulong mb; | |
12362 | + int i, num; | |
12363 | + | |
12364 | + /* align mbase and size to double word boundarys */ | |
12365 | + size += mbase & 7; | |
12366 | + mbase -= mbase & 7; | |
12367 | + size = (size+7) & ~7; | |
12368 | + | |
12369 | + while( size > 0 ) { | |
12370 | + mb = mbase & 0xfffff000; | |
12371 | + | |
12372 | + pre_next = &iod->io_page_head; | |
12373 | + for( ip=iod->io_page_head; ip && ip->mphys < mb; ip=ip->next ) | |
12374 | + pre_next = &ip->next; | |
12375 | + | |
12376 | + if( !ip || ip->mphys != mb ) { | |
12377 | + /* create new page */ | |
12378 | + if( !(ip=(io_page_t*)alloc_page_mol()) ) { | |
12379 | + printk("Failed allocating IO-page\n"); | |
12380 | + return 1; | |
12381 | + } | |
12382 | + ip->next = *pre_next; | |
12383 | + *pre_next = ip; | |
12384 | + | |
12385 | + /* setup block */ | |
12386 | + ip->magic = IO_PAGE_MAGIC_1; | |
12387 | + ip->magic2 = IO_PAGE_MAGIC_2; | |
12388 | + ip->me_phys = tophys_mol(ip); | |
12389 | + ip->mphys = mb; | |
12390 | + } | |
12391 | + /* fill in IO */ | |
12392 | + num = size>>3; | |
12393 | + i = (mbase & 0xfff) >> 3; | |
12394 | + if( i+num > 512 ) | |
12395 | + num = 512-i; | |
12396 | + mbase += num<<3; | |
12397 | + size -= num<<3; | |
12398 | + while( num-- ) | |
12399 | + ip->usr_data[i++] = usr_data; | |
12400 | + } | |
12401 | + return 0; | |
12402 | +} | |
12403 | + | |
12404 | +int | |
12405 | +remove_io_trans( kernel_vars_t *kv, ulong mbase, int size ) | |
12406 | +{ | |
12407 | + DECLARE_IOD; | |
12408 | + io_page_t *ip, **pre_next; | |
12409 | + ulong mb; | |
12410 | + int i, num; | |
12411 | + | |
12412 | + /* To remove an unused IO-page, we must make sure there are no | |
12413 | + * dangling references to it. Hence we must search the PTE hash | |
12414 | + * table and remove all references. We must also issue a | |
12415 | + * tlbia to make sure it is not in the on-chip DTLB/ITLB cashe. | |
12416 | + * | |
12417 | + * XXX: Instead of seraching the hash, we simply make sure the magic | |
12418 | + * constants are invalid. This is perfectly safe since the exception | |
12419 | + * handler doesn't write to the page in question - and the physical | |
12420 | + * page always exists even if it is allocated by somebody else. | |
12421 | + * It is better to make sure there are no references of it though. | |
12422 | + * | |
12423 | + * XXX: This needs to be fixed... commonly, we reallocate | |
12424 | + * the page ourselves for I/O so the magic constants might | |
12425 | + * be valid... | |
12426 | + */ | |
12427 | + | |
12428 | + /* align mbase and size to double word boundarys */ | |
12429 | + size += mbase & 7; | |
12430 | + mbase -= mbase & 7; | |
12431 | + size = (size+7) & ~7; | |
12432 | + | |
12433 | + while( size > 0 ) { | |
12434 | + mb = mbase & 0xfffff000; | |
12435 | + | |
12436 | + pre_next = &iod->io_page_head; | |
12437 | + for( ip=iod->io_page_head; ip && ip->mphys < mb; ip=ip->next ) | |
12438 | + pre_next = &ip->next; | |
12439 | + | |
12440 | + if( !ip || ip->mphys != mb ) { | |
12441 | + /* no page... */ | |
12442 | + size -= 0x1000 - (mbase & 0xfff); | |
12443 | + mbase += 0x1000 - (mbase & 0xfff); | |
12444 | + continue; | |
12445 | + } | |
12446 | + /* clear IO */ | |
12447 | + num = size>>3; | |
12448 | + i = (mbase & 0xfff) >> 3; | |
12449 | + if( i+num > 512 ) | |
12450 | + num = 512-i; | |
12451 | + mbase += num<<3; | |
12452 | + size -= num<<3; | |
12453 | + while( num-- ) | |
12454 | + ip->usr_data[i++] = 0; | |
12455 | + | |
12456 | + /* May we free the page? */ | |
12457 | + for( i=0; i<512 && !ip->usr_data[i]; i++ ) | |
12458 | + ; | |
12459 | + if( i==512 ) { | |
12460 | + /* Free page (XXX: Remove page fram hash, see above ) */ | |
12461 | + *pre_next = ip->next; | |
12462 | + ip->magic2 = ip->magic = 0; /* IMPORTANT */ | |
12463 | + free_page_mol( (ulong)ip ); | |
12464 | + } | |
12465 | + } | |
12466 | + return 0; | |
12467 | + | |
12468 | +} | |
12469 | + | |
12470 | + | |
12471 | +/* Translate a mac-physical address (32 bit, not page-index) | |
12472 | + * and fill in rpn (and _possibly_ other fields) of the pte. | |
12473 | + * The WIMG bits are not modified after this call. | |
12474 | + * The calling function is not supposed to alter the pte after | |
12475 | + * this function call. | |
12476 | + * | |
12477 | + * Retuns: | |
12478 | + * 0 no translation found | |
12479 | + * block_flags translation found | |
12480 | + */ | |
12481 | + | |
12482 | +int | |
12483 | +mphys_to_pte( kernel_vars_t *kv, ulong mphys, ulong *the_pte1, int is_write, pte_lvrange_t **lvrange ) | |
12484 | +{ | |
12485 | + DECLARE_IOD; | |
12486 | + int i, num_btrans; | |
12487 | + block_trans_t *p; | |
12488 | + io_page_t *p2; | |
12489 | + int pte1 = *the_pte1; | |
12490 | + | |
12491 | + num_btrans = iod->num_btrans; | |
12492 | + mphys &= ~0xfff; | |
12493 | + | |
12494 | + /* check for emuaccel page */ | |
12495 | + if( mphys == kv->emuaccel_mphys && kv->emuaccel_page_phys ) { | |
12496 | + /* printk("emuaccel - PTE-insert\n"); */ | |
12497 | + pte1 |= kv->emuaccel_page_phys; | |
12498 | + /* supervisor r/w, no user access */ | |
12499 | + pte1 &= ~(PTE1_W | PTE1_I | PTE1_PP); | |
12500 | + *lvrange = NULL; | |
12501 | + *the_pte1 = pte1; | |
12502 | + return MAPPING_VALID | MAPPING_PHYSICAL; | |
12503 | + } | |
12504 | + | |
12505 | + /* check for a block mapping. */ | |
12506 | + for( p=iod->btable, i=0; i<num_btrans; i++,p++ ) { | |
12507 | + if( mphys - p->mbase < (ulong)p->size ) { | |
12508 | + if( (p->flags & MAPPING_SCRATCH) ) { | |
12509 | + /* it is OK to return silently if we run out of memory */ | |
12510 | + if( !scratch_page && !(scratch_page=(char*)alloc_page_mol()) ) | |
12511 | + return 0; | |
12512 | + pte1 |= tophys_mol(scratch_page); | |
12513 | + } else | |
12514 | + pte1 |= (mphys - p->mbase + (ulong)p->lvbase) & PTE1_RPN; | |
12515 | + | |
12516 | + if( p->flags & MAPPING_FORCE_CACHE ) { | |
12517 | + /* use write through for now */ | |
12518 | + pte1 |= PTE1_W; | |
12519 | + pte1 &= ~PTE1_I; | |
12520 | + } else if( !(p->flags & MAPPING_MACOS_CONTROLS_CACHE) ) | |
12521 | + pte1 &= ~(PTE1_W | PTE1_I); | |
12522 | + | |
12523 | + /* well, just a try... */ | |
12524 | + if ( p->flags & MAPPING_FORCE_WRITABLE ) { | |
12525 | + /* printk("forcing mphys page %lx writable\n", mphys); */ | |
12526 | + pte1 = (pte1 & ~3) | 2; | |
12527 | + } | |
12528 | + | |
12529 | + *lvrange = p->lvrange; | |
12530 | + *the_pte1 = pte1; | |
12531 | + return p->flags; | |
12532 | + } | |
12533 | + } | |
12534 | + | |
12535 | + /* check for an I/O mapping. */ | |
12536 | + for( p2=iod->io_page_head; p2 && p2->mphys<=mphys; p2=p2->next ) { | |
12537 | + if( p2->mphys != mphys ) | |
12538 | + continue; | |
12539 | + pte1 |= p2->me_phys; | |
12540 | + /* supervisor R/W */ | |
12541 | + pte1 &= ~(PTE1_PP | PTE1_W | PTE1_I); | |
12542 | + *lvrange = NULL; | |
12543 | + *the_pte1 = pte1; | |
12544 | + return MAPPING_VALID | MAPPING_IO | MAPPING_PHYSICAL; | |
12545 | + } | |
12546 | + return 0; | |
12547 | +} | |
12548 | + | |
12549 | +void | |
12550 | +mmu_add_map( kernel_vars_t *kv, struct mmu_mapping *m ) | |
12551 | +{ | |
12552 | + if( m->flags & MAPPING_MREGS ) { | |
12553 | + char *start = (char*)tophys_mol(&kv->mregs); | |
12554 | + uint offs = (uint)m->lvbase; | |
12555 | + m->flags &= ~MAPPING_MREGS; | |
12556 | + m->flags |= MAPPING_PHYSICAL; | |
12557 | + m->lvbase = start + offs; | |
12558 | + m->id = -1; | |
12559 | + if( offs + (uint)m->size > NUM_MREGS_PAGES * 0x1000 ) { | |
12560 | + printk("Invalid mregs mapping\n"); | |
12561 | + return; | |
12562 | + } | |
12563 | + } | |
12564 | + m->id = add_block_trans( kv, m->mbase, m->lvbase, m->size, m->flags ); | |
12565 | +} | |
12566 | + | |
12567 | +void | |
12568 | +mmu_remove_map( kernel_vars_t *kv, struct mmu_mapping *m ) | |
12569 | +{ | |
12570 | + remove_block_trans( kv, m->id ); | |
12571 | + m->id = 0; | |
12572 | +} | |
12573 | --- /dev/null | |
12574 | +++ b/drivers/macintosh/mol/mmu_tracker.c | |
12575 | @@ -0,0 +1,128 @@ | |
12576 | +/* | |
12577 | + * Creation Date: <2000/09/07 20:36:54 samuel> | |
12578 | + * Time-stamp: <2004/02/14 14:45:33 samuel> | |
12579 | + * | |
12580 | + * <mmu_tracker.c> | |
12581 | + * | |
12582 | + * Keeps track of dirty RAM pages | |
12583 | + * | |
12584 | + * Copyright (C) 2000, 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
12585 | + * | |
12586 | + * This program is free software; you can redistribute it and/or | |
12587 | + * modify it under the terms of the GNU General Public License | |
12588 | + * as published by the Free Software Foundation | |
12589 | + * | |
12590 | + */ | |
12591 | + | |
12592 | +#include "archinclude.h" | |
12593 | +#include "alloc.h" | |
12594 | +#include "uaccess.h" | |
12595 | +#include "mmu.h" | |
12596 | + | |
12597 | + | |
12598 | +typedef struct tracker_data { | |
12599 | + char *table; | |
12600 | + size_t table_size; | |
12601 | + | |
12602 | + int npages; | |
12603 | + ulong lvbase; | |
12604 | +} tracker_data_t; | |
12605 | + | |
12606 | +#define MMU (kv->mmu) | |
12607 | +#define DECLARE_TS tracker_data_t *ts = MMU.tracker_data | |
12608 | + | |
12609 | + | |
12610 | + | |
12611 | +int | |
12612 | +init_mmu_tracker( kernel_vars_t *kv ) | |
12613 | +{ | |
12614 | + /* track_lvrange does the initialization */ | |
12615 | + return 0; | |
12616 | +} | |
12617 | + | |
12618 | +void | |
12619 | +cleanup_mmu_tracker( kernel_vars_t *kv ) | |
12620 | +{ | |
12621 | + DECLARE_TS; | |
12622 | + if( !ts ) | |
12623 | + return; | |
12624 | + | |
12625 | + if( ts->table ) | |
12626 | + vfree_mol( ts->table ); | |
12627 | + | |
12628 | + kfree_mol( ts ); | |
12629 | + MMU.tracker_data = NULL; | |
12630 | +} | |
12631 | + | |
12632 | +int | |
12633 | +track_lvrange( kernel_vars_t *kv ) | |
12634 | +{ | |
12635 | + ulong lvbase = MMU.userspace_ram_base; | |
12636 | + int size = MMU.ram_size; | |
12637 | + | |
12638 | + DECLARE_TS; | |
12639 | + if( ts ) | |
12640 | + cleanup_mmu_tracker( kv ); | |
12641 | + if( !size ) | |
12642 | + return 0; | |
12643 | + | |
12644 | + if( !(ts=kmalloc_mol(sizeof(tracker_data_t))) ) | |
12645 | + return 1; | |
12646 | + memset( ts, 0, sizeof(tracker_data_t) ); | |
12647 | + MMU.tracker_data = ts; | |
12648 | + | |
12649 | + ts->npages = size >> 12; | |
12650 | + ts->table_size = (ts->npages+7)/8; | |
12651 | + ts->lvbase = lvbase; | |
12652 | + if( !(ts->table=vmalloc_mol(ts->table_size)) ) { | |
12653 | + cleanup_mmu_tracker( kv ); | |
12654 | + return 1; | |
12655 | + } | |
12656 | + memset( ts->table, 0, ts->table_size ); | |
12657 | + return 0; | |
12658 | +} | |
12659 | + | |
12660 | +void | |
12661 | +lvpage_dirty( kernel_vars_t *kv, ulong lvbase ) | |
12662 | +{ | |
12663 | + DECLARE_TS; | |
12664 | + int pgindex; | |
12665 | + | |
12666 | + if( !ts ) | |
12667 | + return; | |
12668 | + | |
12669 | + pgindex = (lvbase - ts->lvbase) >> 12; | |
12670 | + | |
12671 | + if( pgindex >=0 && pgindex < ts->npages ) | |
12672 | + ts->table[pgindex >> 3] |= (1 << (pgindex & 7)); | |
12673 | +} | |
12674 | + | |
12675 | + | |
12676 | +size_t | |
12677 | +get_track_buffer( kernel_vars_t *kv, char *retbuf ) | |
12678 | +{ | |
12679 | + DECLARE_TS; | |
12680 | + | |
12681 | + if( !ts ) | |
12682 | + return 0; | |
12683 | + if( !retbuf ) | |
12684 | + return ts->table_size; | |
12685 | + | |
12686 | + if( copy_to_user_mol(retbuf, ts->table, ts->table_size) ) | |
12687 | + return 0; | |
12688 | + return ts->table_size; | |
12689 | +} | |
12690 | + | |
12691 | +void | |
12692 | +set_track_buffer( kernel_vars_t *kv, char *buf ) | |
12693 | +{ | |
12694 | + DECLARE_TS; | |
12695 | + | |
12696 | + if( !ts || !buf ) { | |
12697 | + printk("set_track_buffer: error\n"); | |
12698 | + return; | |
12699 | + } | |
12700 | + if( copy_from_user_mol(ts->table, buf, ts->table_size) ) { | |
12701 | + printk("set_track_buffer: Bad access\n"); | |
12702 | + } | |
12703 | +} | |
12704 | --- /dev/null | |
12705 | +++ b/drivers/macintosh/mol/mtable.c | |
12706 | @@ -0,0 +1,960 @@ | |
12707 | +/* | |
12708 | + * Creation Date: <2002/05/26 14:46:42 samuel> | |
12709 | + * Time-stamp: <2004/02/28 19:33:21 samuel> | |
12710 | + * | |
12711 | + * <mtable.c> | |
12712 | + * | |
12713 | + * Keeps track of all PTEs MOL uses. | |
12714 | + * | |
12715 | + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
12716 | + * | |
12717 | + * This program is free software; you can redistribute it and/or | |
12718 | + * modify it under the terms of the GNU General Public License | |
12719 | + * as published by the Free Software Foundation | |
12720 | + * | |
12721 | + */ | |
12722 | + | |
12723 | +#ifdef UL_DEBUG | |
12724 | +#include "mtable_dbg.c" | |
12725 | +#else | |
12726 | +#include "archinclude.h" | |
12727 | +#include "alloc.h" | |
12728 | +#include "kernel_vars.h" | |
12729 | +#include "asmfuncs.h" | |
12730 | +#include "mmu.h" | |
12731 | +#include "performance.h" | |
12732 | +#endif | |
12733 | +#include "mtable.h" | |
12734 | +#include "hash.h" | |
12735 | + | |
12736 | +/* #define DEBUG */ | |
12737 | + | |
12738 | +/* | |
12739 | + * Implementation notes: | |
12740 | + * | |
12741 | + * - It is assumed bit the ITLB/DTLB is addressed by ea bits 14-19. | |
12742 | + * This holds true for all CPUs at the moment (603, 604, 750, 7400, | |
12743 | + * 7410, 7450) except the 601 (which uses bits 13-19). | |
12744 | + */ | |
12745 | + | |
12746 | +typedef struct pterec pterec_t; | |
12747 | + | |
12748 | +struct pterec { | |
12749 | + pterec_t *ea_next; /* ea ring (MUST GO FIRST) */ | |
12750 | + pterec_t *lv_next; /* lv ring */ | |
12751 | + uint pent; /* defined below */ | |
12752 | +}; | |
12753 | + | |
12754 | +#define PENT_LV_HEAD BIT(0) /* Resident - do not put on free list */ | |
12755 | +#define PENT_UNUSED BIT(1) /* (lvhead) PTE index is not valid */ | |
12756 | +#define PENT_EA_BIT14 BIT(2) /* for the partial ea used by tlbie */ | |
12757 | +#define PENT_EA_LAST BIT(3) /* next entry is the pelist pointer */ | |
12758 | +#define PENT_TOPEA_MASK 0x0f800000 /* bit 4-8 of ea */ | |
12759 | +#define PENT_SV_BIT 0x00400000 /* PTE uses vsid_sv */ | |
12760 | +#define PENT_INDEX_MASK 0x003fffff /* PTE index (there can be at most 2^22 PTEs) */ | |
12761 | +#define PENT_CMP_MASK (PENT_TOPEA_MASK | PENT_SV_BIT) | |
12762 | + | |
12763 | +/* The index below corresponds to bit 15-19 of the ea. Bit 14 of the ea | |
12764 | + * is stored in the pent field. Thus bits 14-19 of the ea can hence always | |
12765 | + * be reconstructed (this struct is always properly aligned). Note that the | |
12766 | + * pelist forms a ring (this is the reason why ea_next must be | |
12767 | + * the first element in the pterec struct). | |
12768 | + */ | |
12769 | + | |
12770 | +typedef struct { | |
12771 | + pterec_t *pelist[32]; /* always NULL if ring is empty */ | |
12772 | +} pent_table_t; | |
12773 | + | |
12774 | +struct vsid_ent { /* record which describes a mac vsid */ | |
12775 | + vsid_ent_t *myself_virt; /* virtual address of this struct */ | |
12776 | + int linux_vsid; /* munged mac context | VSID(Kp) */ | |
12777 | + int linux_vsid_sv; /* munged privileged mac context | VSID(Kp) */ | |
12778 | + pent_table_t *lev2[64]; /* bit 9-14 of ea */ | |
12779 | +}; | |
12780 | + | |
12781 | +#define LEV2_MASK 0x0001ffff /* bit 15-31 */ | |
12782 | + | |
12783 | +#define LEV2_IND(ea) (((ea) >> (12+5)) & 0x3f) /* lev2 index is bit 9-14 */ | |
12784 | +#define PELIST_IND(ea) (((ea) >> 12) & 0x1f) /* pelist index is 15-19 */ | |
12785 | + | |
12786 | +#define PTE_TO_IND(pte) ((((int)pte - (int)ptehash.base) & ptehash.pte_mask) >> 3) | |
12787 | + | |
12788 | +#define ZERO_PTE(pent) *((ulong*)ptehash.base + ((pent & PENT_INDEX_MASK) << 1)) = 0 | |
12789 | + | |
12790 | + | |
12791 | +struct pte_lvrange { | |
12792 | + pterec_t *pents; | |
12793 | + ulong base; /* we want to do unsigned compares */ | |
12794 | + ulong size; | |
12795 | + pte_lvrange_t *next; /* linked list */ | |
12796 | +}; | |
12797 | + | |
12798 | +typedef struct alloc_ent { | |
12799 | + struct alloc_ent *next; | |
12800 | + char *ptr; | |
12801 | + int what; /* ALLOC_CONTENTS_XXX */ | |
12802 | +} alloc_ent_t; | |
12803 | + | |
12804 | +struct vsid_info { | |
12805 | + mol_spinlock_t lock; /* lvrange and pent ring lock */ | |
12806 | + | |
12807 | + pte_lvrange_t *lvrange_head; | |
12808 | + pterec_t *free_pents; /* free list (lv_next is used) */ | |
12809 | + pent_table_t *free_pent_tables; /* pelist[0] is used for the linked list */ | |
12810 | + | |
12811 | + alloc_ent_t *allocations; /* the allocations we have performed */ | |
12812 | + int alloc_size; /* total size of allocations */ | |
12813 | + int alloc_limit; /* imposed limit */ | |
12814 | +}; | |
12815 | + | |
12816 | +/* don't change the CHUNK_SIZE unless you know what you are doing... */ | |
12817 | +#define CHUNK_SIZE (0x1000 - sizeof(alloc_ent_t)) | |
12818 | + | |
12819 | +#define ALLOC_CONT_ANY 0 | |
12820 | +#define ALLOC_CONT_VSID 1 | |
12821 | +#define ALLOC_CONT_PENT 2 | |
12822 | +#define ALLOC_CONT_LEV2 3 | |
12823 | + | |
12824 | +#define MMU (kv->mmu) | |
12825 | + | |
12826 | +#define LOCK spin_lock_mol( &vi->lock ) | |
12827 | +#define UNLOCK spin_unlock_mol( &vi->lock ) | |
12828 | + | |
12829 | +/* | |
12830 | + * Remarks about locking: There is one asynchronous entrypoint | |
12831 | + * (flush_lvptr). This function touches the lvranges as well | |
12832 | + * as all pent rings. It will not free vsids or unlink | |
12833 | + * level2 tables (but pents are put on the free list). | |
12834 | + */ | |
12835 | + | |
12836 | + | |
12837 | +/************************************************************************/ | |
12838 | +/* Table Flushing */ | |
12839 | +/************************************************************************/ | |
12840 | + | |
12841 | +#define vsid_ent_lookup( kv, mvsid ) ((vsid_ent_t*)skiplist_lookup( &kv->mmu.vsid_sl, mvsid )) | |
12842 | + | |
12843 | +static void | |
12844 | +flush_vsid_ea_( vsid_info_t *vi, vsid_ent_t *r, ulong ea ) | |
12845 | +{ | |
12846 | + pent_table_t *t = r->lev2[LEV2_IND(ea)]; | |
12847 | + pterec_t **pp, **headp, *pr, *next, *lvp; | |
12848 | + uint topea, pent; | |
12849 | + int worked; | |
12850 | + | |
12851 | + if( !t || !(*(pp=&t->pelist[PELIST_IND(ea)])) ) | |
12852 | + return; | |
12853 | + | |
12854 | + topea = (ea & PENT_TOPEA_MASK); | |
12855 | + worked = 0; | |
12856 | + headp = pp; | |
12857 | + pr = *pp; | |
12858 | + do { | |
12859 | + pent = pr->pent; | |
12860 | + next = pr->ea_next; | |
12861 | + | |
12862 | + if( (pent & PENT_TOPEA_MASK) == topea ) { | |
12863 | + worked = 1; | |
12864 | + /* unlink ea */ | |
12865 | + *pp = pr->ea_next; | |
12866 | + | |
12867 | + /* unlink it from lv ring (unless it is the lv-head) */ | |
12868 | + if( pent & PENT_LV_HEAD ) { | |
12869 | + pr->pent = PENT_UNUSED | PENT_LV_HEAD; | |
12870 | + } else { | |
12871 | + /* it is not certain it belong to a lv ring at all... */ | |
12872 | + if( pr->lv_next ) { | |
12873 | + for( lvp=pr->lv_next ; lvp->lv_next != pr ; lvp=lvp->lv_next ) | |
12874 | + ; | |
12875 | + lvp->lv_next = pr->lv_next; | |
12876 | + } | |
12877 | + /* ...and put it on the free list */ | |
12878 | + //printk("pent released\n"); | |
12879 | + pr->lv_next = vi->free_pents; | |
12880 | + vi->free_pents = pr; | |
12881 | + } | |
12882 | + ZERO_PTE( pent ); | |
12883 | + | |
12884 | + if( pent & PENT_EA_LAST ) { | |
12885 | + if( pp == headp ) { | |
12886 | + /* ring empty, set pelist pointer to NULL */ | |
12887 | + *headp = NULL; | |
12888 | + } else { | |
12889 | + /* put marker on previous entry */ | |
12890 | + ((pterec_t*)pp)->pent |= PENT_EA_LAST; | |
12891 | + } | |
12892 | + } | |
12893 | + } else { | |
12894 | + pp = &pr->ea_next; | |
12895 | + } | |
12896 | + pr = next; | |
12897 | + } while( !(pent & PENT_EA_LAST) ); | |
12898 | + | |
12899 | + if( worked ) | |
12900 | + __tlbie( ea ); | |
12901 | +} | |
12902 | + | |
12903 | +void | |
12904 | +flush_vsid_ea( kernel_vars_t *kv, int mac_vsid, ulong ea ) | |
12905 | +{ | |
12906 | + vsid_info_t *vi = MMU.vsid_info; | |
12907 | + vsid_ent_t *r; | |
12908 | + | |
12909 | + LOCK; | |
12910 | + if( (r=vsid_ent_lookup(kv, mac_vsid)) ) | |
12911 | + flush_vsid_ea_( vi, r, ea ); | |
12912 | + UNLOCK; | |
12913 | +} | |
12914 | + | |
12915 | + | |
12916 | +static void | |
12917 | +pent_flush_unlink_ea( pterec_t *pr ) | |
12918 | +{ | |
12919 | + pterec_t **head, *prev; | |
12920 | + uint ea; | |
12921 | + | |
12922 | + //BUMP( pent_flush_unlink_ea ); | |
12923 | +#ifdef DEBUG | |
12924 | + if( pr->pent & PENT_UNUSED ) | |
12925 | + printk("pent_flush_unlink_ea: Internal error\n"); | |
12926 | +#endif | |
12927 | + /* find head and previous pent in ea ring */ | |
12928 | + for( prev=pr; !(prev->pent & PENT_EA_LAST); prev=prev->ea_next ) | |
12929 | + ; | |
12930 | + head = (pterec_t**)prev->ea_next; | |
12931 | + for( ; prev->ea_next != pr ; prev=prev->ea_next ) | |
12932 | + ; | |
12933 | + | |
12934 | + if( (pr->pent & PENT_EA_LAST) ) { | |
12935 | + /* just a single entry in the ea ring? */ | |
12936 | + if( prev == (pterec_t*)head ) { | |
12937 | + pr->ea_next = NULL; /* prev->ea_next is set to this below */ | |
12938 | + } else { | |
12939 | + prev->pent |= PENT_EA_LAST; | |
12940 | + } | |
12941 | + } | |
12942 | + prev->ea_next = pr->ea_next; | |
12943 | + | |
12944 | + /* OK... it is unlinked. Reconstruct EA and flush it */ | |
12945 | + ZERO_PTE( pr->pent ); | |
12946 | + ea = ((uint)head >> 2) & 0x1f; /* Bits 15-19 of ea */ | |
12947 | + if( pr->pent & PENT_EA_BIT14 ) | |
12948 | + ea |= 0x20; | |
12949 | + ea = ea << 12; | |
12950 | + __tlbie(ea); /* Bits 14-19 used */ | |
12951 | + | |
12952 | + // printk("lvflush: ea (bit 14-19) %08X (pent %08X)\n", ea, pr->pent ); | |
12953 | + | |
12954 | + /* caller's responsibility to free the pent */ | |
12955 | +} | |
12956 | + | |
12957 | +static void | |
12958 | +flush_lvptr_( vsid_info_t *vi, ulong lvptr ) | |
12959 | +{ | |
12960 | + pterec_t *head, *last, *first; | |
12961 | + pte_lvrange_t *lvr; | |
12962 | + | |
12963 | + //BUMP( pent_flush_lvptr ); | |
12964 | + | |
12965 | + for( lvr=vi->lvrange_head; lvr && lvptr - lvr->base >= lvr->size ; lvr=lvr->next ) | |
12966 | + ; | |
12967 | + if( !lvr ) | |
12968 | + return; | |
12969 | + // printk("flush_lvptr: %08lX\n", lvptr ); | |
12970 | + | |
12971 | + head = lvr->pents + ((lvptr - lvr->base) >> 12); | |
12972 | +#ifdef DEBUG | |
12973 | + if( !(head->pent & PENT_LV_HEAD) ) { | |
12974 | + printk("flush: Internal error\n"); | |
12975 | + return; | |
12976 | + } | |
12977 | +#endif | |
12978 | + /* first pent to be put on the free list */ | |
12979 | + first = head->lv_next; | |
12980 | + | |
12981 | + /* not just a single entry? */ | |
12982 | + if( first != head ) { | |
12983 | + last = head; | |
12984 | + do { | |
12985 | + last = last->lv_next; | |
12986 | + pent_flush_unlink_ea( last ); | |
12987 | + } while( last->lv_next != head ); | |
12988 | + | |
12989 | + last->lv_next = vi->free_pents; | |
12990 | + vi->free_pents = first; | |
12991 | + } | |
12992 | + if( !(head->pent & PENT_UNUSED) ) | |
12993 | + pent_flush_unlink_ea( head ); | |
12994 | + | |
12995 | + //head->ea_next = NULL; | |
12996 | + head->lv_next = head; | |
12997 | + head->pent = PENT_UNUSED | PENT_LV_HEAD; | |
12998 | +} | |
12999 | + | |
13000 | +/* asynchronous entrypoint (caused e.g. a swapout) */ | |
13001 | +void | |
13002 | +flush_lvptr( kernel_vars_t *kv, ulong lvptr ) | |
13003 | +{ | |
13004 | + vsid_info_t *vi = MMU.vsid_info; | |
13005 | + LOCK; | |
13006 | + if( (char*)lvptr == MMU.lvptr_reservation ) | |
13007 | + MMU.lvptr_reservation_lost = 1; | |
13008 | + flush_lvptr_( vi, lvptr ); | |
13009 | + UNLOCK; | |
13010 | +} | |
13011 | + | |
13012 | + | |
13013 | +void | |
13014 | +flush_lv_range( kernel_vars_t *kv, ulong lvbase, int size ) | |
13015 | +{ | |
13016 | + vsid_info_t *vi = MMU.vsid_info; | |
13017 | + LOCK; | |
13018 | + /* this is quite inefficient but the function is seldom used */ | |
13019 | + for( ; size > 0 ; lvbase += 0x1000, size -= 0x1000 ) | |
13020 | + flush_lvptr_( vi, lvbase ); | |
13021 | + UNLOCK; | |
13022 | +} | |
13023 | + | |
13024 | +void | |
13025 | +flush_ea_range( kernel_vars_t *kv, ulong org_ea, int size ) | |
13026 | +{ | |
13027 | + vsid_info_t *vi = MMU.vsid_info; | |
13028 | + skiplist_iter_t iter; | |
13029 | + pent_table_t *t; | |
13030 | + char *userdata; | |
13031 | + ulong ea, end; | |
13032 | + int i; | |
13033 | + | |
13034 | + //BUMP( flush_ea_range ); | |
13035 | + //printk("flush_ea_range\n"); | |
13036 | + | |
13037 | + LOCK; | |
13038 | +#ifdef DEBUG | |
13039 | + if( size > 0x10000000 || org_ea & 0xf0000000 ) { | |
13040 | + printk("flush_ea_range: Bad parameters %08lX %08X\n", org_ea, size); | |
13041 | + size=0x10000000; | |
13042 | + org_ea=0; | |
13043 | + } | |
13044 | +#endif | |
13045 | + end = org_ea + size; | |
13046 | + | |
13047 | + /* XXX: This is horribly inefficient */ | |
13048 | + iter = skiplist_iterate( &MMU.vsid_sl ); | |
13049 | + while( skiplist_getnext(&MMU.vsid_sl, &iter, &userdata) ) { | |
13050 | + vsid_ent_t *r = (vsid_ent_t*)userdata; | |
13051 | + ea = org_ea; | |
13052 | + while( ea < end ) { | |
13053 | + if( !(t=r->lev2[LEV2_IND(ea)]) ) { | |
13054 | + ea = (ea & ~LEV2_MASK) + LEV2_MASK + 1; | |
13055 | + continue; | |
13056 | + } | |
13057 | + for( i=PELIST_IND(ea); i<32 && ea < end; i++, ea += 0x1000 ) { | |
13058 | + if( t->pelist[i] ) | |
13059 | + flush_vsid_ea_( vi, r, ea ); | |
13060 | + } | |
13061 | + } | |
13062 | + } | |
13063 | + UNLOCK; | |
13064 | +} | |
13065 | + | |
13066 | +/* clear all pte entries belonging to this vsid */ | |
13067 | +static void | |
13068 | +flush_vsid( vsid_info_t *vi, vsid_ent_t *r ) | |
13069 | +{ | |
13070 | + pent_table_t *t; | |
13071 | + ulong ea=0; | |
13072 | + int i; | |
13073 | + | |
13074 | + //BUMP( flush_vsid ); | |
13075 | + | |
13076 | + /* not very efficient */ | |
13077 | + while( ea < 0x10000000 ) { | |
13078 | + if( !(t=r->lev2[LEV2_IND(ea)]) ) { | |
13079 | + ea = (ea & ~LEV2_MASK) + LEV2_MASK + 1; | |
13080 | + continue; | |
13081 | + } | |
13082 | + for( i=PELIST_IND(ea); i<32; i++, ea += 0x1000 ) { | |
13083 | + if( t->pelist[i] ) | |
13084 | + flush_vsid_ea_( vi, r, ea ); | |
13085 | + } | |
13086 | + } | |
13087 | + /* free level2 tables */ | |
13088 | + for( i=0; i<64; i++ ) { | |
13089 | + pent_table_t *t = r->lev2[i]; | |
13090 | + r->lev2[i] = NULL; | |
13091 | + | |
13092 | + /* XXX: The lev2 table _should_ be empty but we | |
13093 | + * might want to verify this... | |
13094 | + */ | |
13095 | + if( t ) { | |
13096 | + t->pelist[0] = (void*)vi->free_pent_tables; | |
13097 | + vi->free_pent_tables = t; | |
13098 | + } | |
13099 | + } | |
13100 | +} | |
13101 | + | |
13102 | + | |
13103 | +/************************************************************************/ | |
13104 | +/* Allocations */ | |
13105 | +/************************************************************************/ | |
13106 | + | |
13107 | +/* this function allocates 0x1000 - sizeof(alloc_ent_t) zeroed bytes */ | |
13108 | +static void * | |
13109 | +do_chunk_kmalloc( vsid_info_t *vi, int what ) | |
13110 | +{ | |
13111 | + alloc_ent_t *mp; | |
13112 | + char *ptr; | |
13113 | + | |
13114 | + if( vi->alloc_size > vi->alloc_limit ) | |
13115 | + return NULL; | |
13116 | + if( !(ptr=(char*)alloc_page_mol()) ) | |
13117 | + return NULL; | |
13118 | + mp = (alloc_ent_t*)((char*)ptr + 0x1000 - sizeof(alloc_ent_t)); | |
13119 | + | |
13120 | + mp->next = vi->allocations; | |
13121 | + mp->ptr = ptr; | |
13122 | + mp->what = what; | |
13123 | + vi->allocations = mp; | |
13124 | + | |
13125 | + vi->alloc_size += 0x1000; | |
13126 | + BUMP_N( alloced, 0x1000 ); | |
13127 | + return ptr; | |
13128 | +} | |
13129 | + | |
13130 | +static void | |
13131 | +do_kfree( vsid_info_t *vi, int what ) | |
13132 | +{ | |
13133 | + alloc_ent_t *p, **mp = &vi->allocations; | |
13134 | + | |
13135 | + while( *mp ) { | |
13136 | + p = *mp; | |
13137 | + if( p->what == what || what == ALLOC_CONT_ANY ) { | |
13138 | + *mp = p->next; | |
13139 | + free_page_mol( (ulong)p->ptr ); | |
13140 | + | |
13141 | + vi->alloc_size -= 0x1000; | |
13142 | + BUMP_N( released, 0x1000 ); | |
13143 | + } else { | |
13144 | + mp = &p->next; | |
13145 | + } | |
13146 | + } | |
13147 | +} | |
13148 | + | |
13149 | +/* Note: mtable_memory_check() must have been called previously */ | |
13150 | +static inline pent_table_t * | |
13151 | +get_free_lev2( vsid_info_t *vi ) | |
13152 | +{ | |
13153 | + pent_table_t *t = vi->free_pent_tables; | |
13154 | + | |
13155 | + vi->free_pent_tables = (pent_table_t*)vi->free_pent_tables->pelist[0]; | |
13156 | + t->pelist[0] = NULL; | |
13157 | + return t; | |
13158 | +} | |
13159 | + | |
13160 | +/* this function is responsible for setting PENT_LV_HEAD and lv_next */ | |
13161 | +static pterec_t * | |
13162 | +get_free_pent( vsid_info_t *vi, pte_lvrange_t *lvrange, char *lvptr ) | |
13163 | +{ | |
13164 | + pterec_t *pr, *pr2; | |
13165 | + int pent = 0; | |
13166 | + int ind; | |
13167 | + | |
13168 | + if( lvrange ) { | |
13169 | + ind = (((int)lvptr - lvrange->base) >> 12); | |
13170 | + pr2 = &lvrange->pents[ind]; | |
13171 | + | |
13172 | + if( (pr2->pent & PENT_UNUSED) ) { | |
13173 | + pr = pr2; | |
13174 | + pent = PENT_LV_HEAD; | |
13175 | + } else { | |
13176 | + /* alloc new entry */ | |
13177 | + pr = vi->free_pents; | |
13178 | + vi->free_pents = pr->lv_next; | |
13179 | + | |
13180 | + /* add to lv ring (after the head element) */ | |
13181 | + pr->lv_next = pr2->lv_next; | |
13182 | + pr2->lv_next = pr; | |
13183 | + } | |
13184 | + } else { | |
13185 | + /* alloc new entry */ | |
13186 | + pr = vi->free_pents; | |
13187 | + vi->free_pents = pr->lv_next; | |
13188 | + | |
13189 | + pr->lv_next = NULL; | |
13190 | + } | |
13191 | + | |
13192 | + /* allocate pterec_t and insert into the lv ring */ | |
13193 | + pr->pent = pent; | |
13194 | + return pr; | |
13195 | +} | |
13196 | + | |
13197 | +static int | |
13198 | +lev2_alloc( vsid_info_t *vi ) | |
13199 | +{ | |
13200 | + const int m = sizeof(pent_table_t) - 1; | |
13201 | + pent_table_t *t; | |
13202 | + int i, n = CHUNK_SIZE/sizeof(pent_table_t); | |
13203 | + | |
13204 | + //BUMP( lev2_alloc ); | |
13205 | + | |
13206 | + if( !(t=do_chunk_kmalloc(vi, ALLOC_CONT_LEV2)) ) | |
13207 | + return 1; | |
13208 | + | |
13209 | + /* the alignment must be correct (the ea calculation will fail otherwise) */ | |
13210 | + if( (int)t & m ) { | |
13211 | + t = (pent_table_t*)((int)t + m + 1 - ((int)t & m)); | |
13212 | + n--; | |
13213 | + } | |
13214 | + | |
13215 | + memset( t, 0, n*sizeof(pent_table_t) ); | |
13216 | + for( i=0; i<n-1; i++ ) | |
13217 | + t[i].pelist[0] = (void*)&t[i+1]; | |
13218 | + LOCK; | |
13219 | + t[i].pelist[0] = (void*)vi->free_pent_tables; | |
13220 | + vi->free_pent_tables = &t[0]; | |
13221 | + UNLOCK; | |
13222 | + return 0; | |
13223 | +} | |
13224 | + | |
13225 | +static int | |
13226 | +pent_alloc( vsid_info_t *vi ) | |
13227 | +{ | |
13228 | + const int n = CHUNK_SIZE/sizeof(pterec_t); | |
13229 | + pterec_t *pr; | |
13230 | + int i; | |
13231 | + | |
13232 | + //BUMP( pent_alloc ); | |
13233 | + | |
13234 | + if( !(pr=do_chunk_kmalloc(vi, ALLOC_CONT_PENT)) ) | |
13235 | + return 1; | |
13236 | + memset( pr, 0, CHUNK_SIZE ); | |
13237 | + | |
13238 | + for( i=0; i<n-1; i++ ) | |
13239 | + pr[i].lv_next = &pr[i+1]; | |
13240 | + LOCK; | |
13241 | + pr[i].lv_next = vi->free_pents; | |
13242 | + vi->free_pents = &pr[0]; | |
13243 | + UNLOCK; | |
13244 | + return 0; | |
13245 | +} | |
13246 | + | |
13247 | + | |
13248 | +/* This function is to be called at a safe time (it might allocate | |
13249 | + * memory). It ensures the next pte_inserted call will succeed. | |
13250 | + */ | |
13251 | +int | |
13252 | +mtable_memory_check( kernel_vars_t *kv ) | |
13253 | +{ | |
13254 | + vsid_info_t *vi = MMU.vsid_info; | |
13255 | + | |
13256 | + /* optimize the common case */ | |
13257 | + if( vi->free_pents && vi->free_pent_tables ) | |
13258 | + return 0; | |
13259 | + | |
13260 | + if( !vi->free_pent_tables ) | |
13261 | + lev2_alloc(vi); | |
13262 | + if( !vi->free_pents ) | |
13263 | + pent_alloc(vi); | |
13264 | + | |
13265 | + if( !vi->free_pents || !vi->free_pent_tables ) { | |
13266 | + clear_all_vsids( kv ); | |
13267 | + return 1; | |
13268 | + } | |
13269 | + return 0; | |
13270 | +} | |
13271 | + | |
13272 | + | |
13273 | +/************************************************************************/ | |
13274 | +/* pte_insert */ | |
13275 | +/************************************************************************/ | |
13276 | + | |
13277 | +static inline void | |
13278 | +relink_lv( vsid_info_t *vi, pterec_t *pr, pte_lvrange_t *lvrange, char *lvptr ) | |
13279 | +{ | |
13280 | + int ind = (((int)lvptr - lvrange->base) >> 12); | |
13281 | + pterec_t *pnew, *p, *lv_head = &lvrange->pents[ind]; | |
13282 | + | |
13283 | + if( !pr->lv_next ) { | |
13284 | + //printk("Not previously on lvlist\n"); | |
13285 | + pr->lv_next = lv_head->lv_next; | |
13286 | + lv_head->lv_next = pr; | |
13287 | + return; | |
13288 | + } | |
13289 | + | |
13290 | + if( pr->pent & PENT_LV_HEAD ) { | |
13291 | + if( pr == lv_head ) { | |
13292 | + //printk("lvptr is head (correct lv ring)\n"); | |
13293 | + return; | |
13294 | + } | |
13295 | + | |
13296 | + /* unlink from ea ring and add new pent */ | |
13297 | + for( p=pr->ea_next; p->ea_next != pr ; p=p->ea_next ) | |
13298 | + ; | |
13299 | + pnew = get_free_pent( vi, lvrange, lvptr ); | |
13300 | + pnew->ea_next = pr->ea_next; | |
13301 | + p->ea_next = pnew; | |
13302 | + | |
13303 | + pnew->pent |= (pr->pent & ~(PENT_UNUSED | PENT_LV_HEAD)); | |
13304 | + | |
13305 | + /* clear old lvhead */ | |
13306 | + // pr->ea_next = NULL; | |
13307 | + pr->pent = PENT_LV_HEAD | PENT_UNUSED; | |
13308 | + | |
13309 | + //printk("lvptr is head\n"); | |
13310 | + return; | |
13311 | + } else { | |
13312 | + for( p=pr->lv_next; !(p->pent & PENT_LV_HEAD) ; p=p->lv_next ) | |
13313 | + ; | |
13314 | + if( p == lv_head ) { | |
13315 | + //printk("lvptr is on the correct lv ring\n"); | |
13316 | + return; | |
13317 | + } | |
13318 | + | |
13319 | + /* lvptr has chagned, unlink */ | |
13320 | + for( ; p->lv_next != pr ; p=p->lv_next ) | |
13321 | + ; | |
13322 | + p->lv_next = pr->lv_next; | |
13323 | + | |
13324 | + /* add to lv ring */ | |
13325 | + pr->lv_next = lv_head->lv_next; | |
13326 | + lv_head->lv_next = pr; | |
13327 | + } | |
13328 | +} | |
13329 | + | |
13330 | +/* Note: If lvrange is NULL then lvptr should be ignored */ | |
13331 | +void | |
13332 | +pte_inserted( kernel_vars_t *kv, ulong ea, char *lvptr, pte_lvrange_t *lvrange, | |
13333 | + ulong *pte, vsid_ent_t *r, int segreg ) | |
13334 | +{ | |
13335 | + vsid_info_t *vi = MMU.vsid_info; | |
13336 | + int pl_ind = PELIST_IND(ea); | |
13337 | + uint pent, pent_cmp; | |
13338 | + pterec_t *pr, **pp; | |
13339 | + pent_table_t **tt; | |
13340 | + | |
13341 | + LOCK; | |
13342 | + if( lvrange && MMU.lvptr_reservation_lost ) { | |
13343 | + printk("mtable: lvptr reservation lost %08x\n", (int)lvptr ); | |
13344 | + pte[0] = 0; | |
13345 | + __tlbie(ea); | |
13346 | + goto out; | |
13347 | + } | |
13348 | + | |
13349 | + tt = &r->lev2[ LEV2_IND(ea) ]; | |
13350 | + | |
13351 | + pent_cmp = (ea & PENT_TOPEA_MASK); | |
13352 | + if( (r->linux_vsid_sv & VSID_MASK) == (segreg & VSID_MASK) ) | |
13353 | + pent_cmp |= PENT_SV_BIT; | |
13354 | + | |
13355 | + if( !*tt ) | |
13356 | + *tt = get_free_lev2(vi); | |
13357 | + | |
13358 | + pp = &(**tt).pelist[ pl_ind ]; | |
13359 | + if( (pr=*pp) ) { | |
13360 | + do { | |
13361 | + pent = pr->pent; | |
13362 | + if( (pent & PENT_CMP_MASK) == pent_cmp ) { | |
13363 | + pent &= ~PENT_INDEX_MASK; | |
13364 | + pent |= PTE_TO_IND(pte); | |
13365 | + pr->pent = pent; | |
13366 | + | |
13367 | + /* the lvptr might have changed */ | |
13368 | + if( lvrange ) | |
13369 | + relink_lv( vi, pr, lvrange, lvptr ); | |
13370 | + else { | |
13371 | + /* The pent might belong to a lvring unnecessarily. | |
13372 | + * It is not worth the extra overhead addressing this | |
13373 | + * (uncommon) case | |
13374 | + */ | |
13375 | + } | |
13376 | + //printk("PTE entry reused\n"); | |
13377 | + goto out; | |
13378 | + } | |
13379 | + pr=pr->ea_next; | |
13380 | + } while( !(pent & PENT_EA_LAST) ); | |
13381 | + | |
13382 | + /* get_free_pent inserts the entry into the lvring and sets a few pent bits */ | |
13383 | + pr = get_free_pent(vi, lvrange, lvptr); | |
13384 | + pr->pent |= PTE_TO_IND(pte) | pent_cmp | ((ea & BIT(14)) ? PENT_EA_BIT14 : 0); | |
13385 | + | |
13386 | + /* insert in (non-empty) ea ring */ | |
13387 | + pr->ea_next = *pp; | |
13388 | + *pp = pr; | |
13389 | + } else { | |
13390 | + /* ea ring was empty */ | |
13391 | + pr = *pp = get_free_pent(vi, lvrange, lvptr); | |
13392 | + pr->pent |= PENT_EA_LAST | PTE_TO_IND(pte) | pent_cmp | |
13393 | + | ((ea & BIT(14)) ? PENT_EA_BIT14 : 0); | |
13394 | + pr->ea_next = (pterec_t*)pp; | |
13395 | + } | |
13396 | + out: | |
13397 | + UNLOCK; | |
13398 | +} | |
13399 | + | |
13400 | + | |
13401 | +/************************************************************************/ | |
13402 | +/* VSID allocation */ | |
13403 | +/************************************************************************/ | |
13404 | + | |
13405 | +/* initialize vsid element callback (ind loops from 0 to n-1) */ | |
13406 | +static void | |
13407 | +_vsid_el_callback( char *data, int ind, int n, void *usr1_kv, void *dummy ) | |
13408 | +{ | |
13409 | + kernel_vars_t *kv = (kernel_vars_t*)usr1_kv; | |
13410 | + vsid_ent_t *r = (vsid_ent_t*)data; | |
13411 | + | |
13412 | + r->linux_vsid = alloc_context(kv) | VSID_Kp; | |
13413 | + r->linux_vsid_sv = alloc_context(kv) | VSID_Kp; | |
13414 | + r->myself_virt = r; | |
13415 | +} | |
13416 | + | |
13417 | +/* mac_vsid might be negative (used as vsid for unmapped access). | |
13418 | + * Thus, do not apply this VSID mask anywhere... | |
13419 | + */ | |
13420 | +static vsid_ent_t * | |
13421 | +alloc_vsid_ent( kernel_vars_t *kv, int mac_vsid ) | |
13422 | +{ | |
13423 | + char *buf; | |
13424 | + | |
13425 | + if( skiplist_needalloc(&MMU.vsid_sl) ) { | |
13426 | + /* this check might invoke clear_all_vsids() */ | |
13427 | + handle_context_wrap( kv, CHUNK_SIZE/sizeof(vsid_ent_t)*2 ); | |
13428 | + | |
13429 | + if( !(buf=do_chunk_kmalloc(MMU.vsid_info, ALLOC_CONT_VSID)) ) | |
13430 | + return NULL; | |
13431 | + memset( buf, 0, CHUNK_SIZE ); | |
13432 | + | |
13433 | + (void) skiplist_prealloc( &MMU.vsid_sl, buf, CHUNK_SIZE, _vsid_el_callback, kv, NULL ); | |
13434 | + } | |
13435 | + return (vsid_ent_t*)skiplist_insert( &MMU.vsid_sl, mac_vsid ); | |
13436 | +} | |
13437 | + | |
13438 | +/* flushes all vsids (including the fake no-MMU vsids) */ | |
13439 | +void | |
13440 | +clear_all_vsids( kernel_vars_t *kv ) | |
13441 | +{ | |
13442 | + vsid_info_t *vi = MMU.vsid_info; | |
13443 | + skiplist_iter_t iter; | |
13444 | + char *userdata; | |
13445 | + | |
13446 | + LOCK; | |
13447 | + iter = skiplist_iterate( &MMU.vsid_sl ); | |
13448 | + while( skiplist_getnext(&MMU.vsid_sl, &iter, &userdata) ) | |
13449 | + flush_vsid( vi, (vsid_ent_t*)userdata ); | |
13450 | + | |
13451 | + skiplist_init( &MMU.vsid_sl, sizeof(vsid_ent_t) ); | |
13452 | + | |
13453 | + /* flush any dangling pointers */ | |
13454 | + clear_vsid_refs( kv ); | |
13455 | + | |
13456 | + /* all vsids cleared -> all lev2 cleared -> no pents in use */ | |
13457 | + vi->free_pents = NULL; | |
13458 | + vi->free_pent_tables = NULL; | |
13459 | + UNLOCK; | |
13460 | + do_kfree( vi, ALLOC_CONT_ANY ); | |
13461 | + | |
13462 | + BUMP(clear_all_vsids); | |
13463 | +} | |
13464 | + | |
13465 | +/* This function flushes *ALL* PTEs inserted by MOL. It is primarily | |
13466 | + * used when it is too difficult to make a more specific invalidation. | |
13467 | + */ | |
13468 | +void | |
13469 | +clear_pte_hash_table( kernel_vars_t *kv ) | |
13470 | +{ | |
13471 | + /* this will free the vsids too... */ | |
13472 | + clear_all_vsids( kv ); | |
13473 | +} | |
13474 | + | |
13475 | +vsid_ent_t * | |
13476 | +vsid_get_user_sv( kernel_vars_t *kv, int mac_vsid, ulong *user_ret, ulong *sv_ret ) | |
13477 | +{ | |
13478 | + vsid_ent_t *r = vsid_ent_lookup( kv, mac_vsid ); | |
13479 | + | |
13480 | + if( !r && !(r=alloc_vsid_ent(kv, mac_vsid)) ) { | |
13481 | + clear_all_vsids( kv ); | |
13482 | + if( !(r=alloc_vsid_ent(kv, mac_vsid)) ) { | |
13483 | + printk("VSID allocation failure\n"); | |
13484 | + return NULL; | |
13485 | + } | |
13486 | + } | |
13487 | + *user_ret = r->linux_vsid; | |
13488 | + *sv_ret = r->linux_vsid_sv; | |
13489 | + return r; | |
13490 | +} | |
13491 | + | |
13492 | +/************************************************************************/ | |
13493 | +/* resource reclaiming */ | |
13494 | +/************************************************************************/ | |
13495 | + | |
13496 | +void | |
13497 | +mtable_reclaim( kernel_vars_t *kv ) | |
13498 | +{ | |
13499 | + vsid_info_t *vi = MMU.vsid_info; | |
13500 | + skiplist_iter_t iter; | |
13501 | + pent_table_t *t; | |
13502 | + char *userdata; | |
13503 | + int i,j; | |
13504 | + | |
13505 | + /* This thread runs on the main thread, thus the skiplist stuff does | |
13506 | + * not need locking. In fact, it is only the free_pent_tables | |
13507 | + * list that needs spinlock protection. | |
13508 | + */ | |
13509 | + LOCK; | |
13510 | + iter = skiplist_iterate( &MMU.vsid_sl ); | |
13511 | + while( skiplist_getnext(&MMU.vsid_sl, &iter, &userdata) ) { | |
13512 | + vsid_ent_t *r = (vsid_ent_t*)userdata; | |
13513 | + const int n1 = sizeof(r->lev2)/sizeof(r->lev2[0]); | |
13514 | + const int n2 = sizeof(t->pelist)/sizeof(t->pelist[0]); | |
13515 | + | |
13516 | + for( i=0; i<n1; i++ ) { | |
13517 | + if( !(t=r->lev2[i]) ) | |
13518 | + continue; | |
13519 | + for( j=0; j<n2 && !(t->pelist[j]) ; j++ ) | |
13520 | + ; | |
13521 | + if( j != n2 ) | |
13522 | + break; | |
13523 | + /* level2 empty... */ | |
13524 | + r->lev2[i]->pelist[0] = (void*)vi->free_pent_tables; | |
13525 | + vi->free_pent_tables = r->lev2[i]; | |
13526 | + r->lev2[i] = NULL; | |
13527 | + | |
13528 | + BUMP(lev2_reclaim); | |
13529 | + } | |
13530 | + if( i == n1 ) { | |
13531 | + int vsid = skiplist_iter_getkey( &MMU.vsid_sl, (char*)r ); | |
13532 | + | |
13533 | + /* the segment might be in use... */ | |
13534 | + for( i=0; i<16 && MMU.vsid[i] != r; i++ ) | |
13535 | + ; | |
13536 | + if( i != 16 || (uint)vsid > VSID_MASK ) | |
13537 | + continue; | |
13538 | + skiplist_delete( &MMU.vsid_sl, vsid ); | |
13539 | + BUMP(vsid_reclaim); | |
13540 | + } | |
13541 | + } | |
13542 | + UNLOCK; | |
13543 | +} | |
13544 | + | |
13545 | +/************************************************************************/ | |
13546 | +/* lvrange allocation */ | |
13547 | +/************************************************************************/ | |
13548 | + | |
13549 | +pte_lvrange_t * | |
13550 | +register_lvrange( kernel_vars_t *kv, char *lvbase, int size ) | |
13551 | +{ | |
13552 | + vsid_info_t *vi = MMU.vsid_info; | |
13553 | + pte_lvrange_t *lvr; | |
13554 | + int i, nel = (size >> 12); | |
13555 | + int s = sizeof(pterec_t) * nel; | |
13556 | + | |
13557 | + /* printk("register_lvrange\n"); */ | |
13558 | + | |
13559 | + if( !(lvr=kmalloc_mol(sizeof(pte_lvrange_t))) ) | |
13560 | + return NULL; | |
13561 | + memset( lvr, 0, sizeof(pte_lvrange_t) ); | |
13562 | + | |
13563 | + if( !(lvr->pents=vmalloc_mol(s)) ) { | |
13564 | + kfree_mol( lvr ); | |
13565 | + return NULL; | |
13566 | + } | |
13567 | + /* setup empty lvrings */ | |
13568 | + for( i=0; i<nel; i++ ) { | |
13569 | + lvr->pents[i].pent = PENT_LV_HEAD | PENT_UNUSED; | |
13570 | + lvr->pents[i].lv_next = &lvr->pents[i]; | |
13571 | + lvr->pents[i].ea_next = NULL; | |
13572 | + } | |
13573 | + lvr->base = (ulong)lvbase; | |
13574 | + lvr->size = size; | |
13575 | + | |
13576 | + LOCK; | |
13577 | + /* add to linked list */ | |
13578 | + lvr->next = vi->lvrange_head; | |
13579 | + vi->lvrange_head = lvr; | |
13580 | + UNLOCK; | |
13581 | + | |
13582 | + return lvr; | |
13583 | +} | |
13584 | + | |
13585 | +void | |
13586 | +free_lvrange( kernel_vars_t *kv, pte_lvrange_t *lvrange ) | |
13587 | +{ | |
13588 | + vsid_info_t *vi = MMU.vsid_info; | |
13589 | + pte_lvrange_t **lvr; | |
13590 | + | |
13591 | + lvr = &vi->lvrange_head; | |
13592 | + for( ; *lvr && *lvr != lvrange; lvr=&(**lvr).next ) | |
13593 | + ; | |
13594 | + if( !*lvr ) { | |
13595 | + printk("free_lvrange: Internal error\n"); | |
13596 | + return; | |
13597 | + } | |
13598 | + flush_lv_range( kv, (**lvr).base, (**lvr).size ); | |
13599 | + LOCK; | |
13600 | + *lvr = (**lvr).next; | |
13601 | + UNLOCK; | |
13602 | + | |
13603 | + vfree_mol( lvrange->pents ); | |
13604 | + kfree_mol( lvrange ); | |
13605 | +} | |
13606 | + | |
13607 | +/************************************************************************/ | |
13608 | +/* init / cleanup */ | |
13609 | +/************************************************************************/ | |
13610 | + | |
13611 | +void | |
13612 | +mtable_tune_alloc_limit( kernel_vars_t *kv, int ramsize_mb ) | |
13613 | +{ | |
13614 | + vsid_info_t *vi = MMU.vsid_info; | |
13615 | + vi->alloc_limit = (ramsize_mb + 160) * 4096; | |
13616 | + /* printk("alloc_limit: %d K\n", vi->alloc_limit/1024 ); */ | |
13617 | +} | |
13618 | + | |
13619 | +int | |
13620 | +init_mtable( kernel_vars_t *kv ) | |
13621 | +{ | |
13622 | + vsid_info_t *vi = kmalloc_mol( sizeof(vsid_info_t) ); | |
13623 | + | |
13624 | + MMU.vsid_info = vi; | |
13625 | + if( !vi ) | |
13626 | + return 1; | |
13627 | + memset( vi, 0, sizeof(vsid_info_t) ); | |
13628 | + spin_lock_init_mol( &vi->lock ); | |
13629 | + | |
13630 | + /* will be tuned when we know how much RAM we have */ | |
13631 | + vi->alloc_limit = 2 * 1024 * 1024; | |
13632 | + | |
13633 | + skiplist_init( &MMU.vsid_sl, sizeof(vsid_ent_t) ); | |
13634 | + | |
13635 | + if( !VSID_OFFSETS_OK ) { | |
13636 | + printk("VSID offsets are BAD (fix offset in source)!\n"); | |
13637 | + return 1; | |
13638 | + } | |
13639 | + return 0; | |
13640 | +} | |
13641 | + | |
13642 | +void | |
13643 | +cleanup_mtable( kernel_vars_t *kv ) | |
13644 | +{ | |
13645 | + vsid_info_t *vi = MMU.vsid_info; | |
13646 | + | |
13647 | + if( vi ) { | |
13648 | + while( vi->lvrange_head ) { | |
13649 | + printk("Bug: lvrange unreleased!\n"); | |
13650 | + free_lvrange( kv, vi->lvrange_head ); | |
13651 | + } | |
13652 | + do_kfree( vi, ALLOC_CONT_ANY ); | |
13653 | + kfree_mol( vi ); | |
13654 | + } | |
13655 | + memset( &MMU.vsid_sl, 0, sizeof(MMU.vsid_sl) ); | |
13656 | + MMU.vsid_info = NULL; | |
13657 | +} | |
13658 | + | |
13659 | + | |
13660 | +/************************************************************************/ | |
13661 | +/* userland debug */ | |
13662 | +/************************************************************************/ | |
13663 | + | |
13664 | +#ifdef UL_DEBUG | |
13665 | +#include "mtable_dbg.c" | |
13666 | +#endif | |
13667 | --- /dev/null | |
13668 | +++ b/drivers/macintosh/mol/ptaccess.c | |
13669 | @@ -0,0 +1,153 @@ | |
13670 | +/* | |
13671 | + * Creation Date: <2001/03/25 18:04:45 samuel> | |
13672 | + * Time-stamp: <2002/08/03 17:43:10 samuel> | |
13673 | + * | |
13674 | + * <ptaccess.c> | |
13675 | + * | |
13676 | + * Handle stores to the (emulated) page table | |
13677 | + * | |
13678 | + * Copyright (C) 2001, 2002 Samuel Rydh (samuel@ibrium.se) | |
13679 | + * | |
13680 | + * This program is free software; you can redistribute it and/or | |
13681 | + * modify it under the terms of the GNU General Public License | |
13682 | + * as published by the Free Software Foundation | |
13683 | + * | |
13684 | + */ | |
13685 | + | |
13686 | +#include "archinclude.h" | |
13687 | +#include "mmu.h" | |
13688 | +#include "rvec.h" | |
13689 | +#include "mtable.h" | |
13690 | +#include "misc.h" | |
13691 | +#include "performance.h" | |
13692 | + | |
13693 | +extern int do_intercept_tlbie( kernel_vars_t *kv, ulong pte0, ulong pte1, ulong pteoffs ); | |
13694 | +extern int do_intercept_tlbie_block( kernel_vars_t *kv, ulong pteoffs, ulong length ); | |
13695 | + | |
13696 | +#define MMU (kv->mmu) | |
13697 | +#define MREGS (kv->mregs) | |
13698 | + | |
13699 | +int | |
13700 | +do_intercept_tlbie( kernel_vars_t *kv, ulong pte0, ulong pte1, ulong pteoffs ) | |
13701 | +{ | |
13702 | + int vsid = (pte0 >> 7) & VSID_MASK; | |
13703 | + ulong v; | |
13704 | + | |
13705 | + BUMP( do_intercept_tlbie ); | |
13706 | + | |
13707 | + if( MMU.pthash_inuse_bits ) | |
13708 | + clear_bit_mol( pteoffs >> 3, MMU.pthash_inuse_bits ); | |
13709 | + | |
13710 | + v = (pteoffs >> 6); | |
13711 | + if( pte0 & BIT(25) ) /* secondary hash? */ | |
13712 | + v = ~v; | |
13713 | + v ^= (pte0 >> 7); | |
13714 | + v = ((pte0 << 10) & 0xfc00) | (v & 0x3ff); | |
13715 | + | |
13716 | + //printk("do_intercept_tlbie: vsid %08lX, ea %08lX\n", vsid, (v<<12) ); | |
13717 | + flush_vsid_ea( kv, vsid, (v<<12) ); | |
13718 | + | |
13719 | + return RVEC_NOP; | |
13720 | +} | |
13721 | + | |
13722 | +int | |
13723 | +do_intercept_tlbie_block( kernel_vars_t *kv, ulong pteoffs, ulong length ) | |
13724 | +{ | |
13725 | + unsigned int finish; | |
13726 | + | |
13727 | + //printk("do_intercept_tlbie_block: pteoffs %08lX length %08lX\n", pteoffs, length); | |
13728 | + | |
13729 | + if (pteoffs + length > MMU.hash_mask) { | |
13730 | + printk("do_intercept_tlbie_block: length exceeding hash!\n"); | |
13731 | + finish = MMU.hash_mask + 1; | |
13732 | + } else | |
13733 | + finish = pteoffs + length; | |
13734 | + | |
13735 | + if (MMU.pthash_inuse_bits == NULL) | |
13736 | + return RVEC_NOP; | |
13737 | + | |
13738 | + while (pteoffs < finish) { | |
13739 | + if (check_bit_mol(pteoffs >> 3, MMU.pthash_inuse_bits)) { | |
13740 | + ulong pte0, pte1; | |
13741 | + | |
13742 | + pte0 = *((unsigned int *) (MMU.hash_base + pteoffs)); | |
13743 | + pte1 = *((unsigned int *) (MMU.hash_base + pteoffs + 4)); | |
13744 | + do_intercept_tlbie(kv, pte0, pte1, pteoffs); | |
13745 | + } | |
13746 | + | |
13747 | + pteoffs += 8; | |
13748 | + } | |
13749 | + | |
13750 | + return RVEC_NOP; | |
13751 | +} | |
13752 | + | |
13753 | +#ifdef EMULATE_603 | |
13754 | + | |
13755 | +extern int do_tlbli( kernel_vars_t *kv, ulong ea ); | |
13756 | +extern int do_tlbld( kernel_vars_t *kv, ulong ea ); | |
13757 | + | |
13758 | +int | |
13759 | +do_tlbli( kernel_vars_t *kv, ulong ea ) | |
13760 | +{ | |
13761 | + int ind = (ea >> 12) & 0x1f; | |
13762 | + mPTE_t *p; | |
13763 | + | |
13764 | + //printk("do_tlbli %08lX : %08lX %08lX\n", ea, MREGS.spr[S_ICMP], MREGS.spr[S_RPA] ); | |
13765 | + if( MREGS.spr[S_SRR1] & BIT(14) ) | |
13766 | + ind += 32; | |
13767 | + | |
13768 | + p = &MMU.ptes_i_603[ind]; | |
13769 | + if( p->v ) | |
13770 | + flush_vsid_ea( kv, p->vsid, MMU.ptes_i_ea_603[ind] ); | |
13771 | + MMU.ptes_i_ea_603[ind] = ea & 0x0ffff000; | |
13772 | + *(ulong*)p = MREGS.spr[ S_ICMP ]; | |
13773 | + *((ulong*)p+1) = MREGS.spr[ S_RPA ]; | |
13774 | + | |
13775 | + return RVEC_NOP; | |
13776 | +} | |
13777 | + | |
13778 | +int | |
13779 | +do_tlbld( kernel_vars_t *kv, ulong ea ) | |
13780 | +{ | |
13781 | + int ind = (ea >> 12) & 0x1f; | |
13782 | + mPTE_t *p; | |
13783 | + | |
13784 | + //printk("do_tlbld %08lX\n", ea ); | |
13785 | + | |
13786 | + if( MREGS.spr[S_SRR1] & BIT(14) ) | |
13787 | + ind += 32; | |
13788 | + | |
13789 | + p = &MMU.ptes_d_603[ind]; | |
13790 | + if( p->v ) | |
13791 | + flush_vsid_ea( kv, p->vsid, MMU.ptes_d_ea_603[ind] ); | |
13792 | + MMU.ptes_d_ea_603[ind] = ea & 0x0ffff000; | |
13793 | + *(ulong*)p = MREGS.spr[ S_DCMP ]; | |
13794 | + *((ulong*)p+1) = MREGS.spr[ S_RPA ]; | |
13795 | + | |
13796 | + return RVEC_NOP; | |
13797 | +} | |
13798 | + | |
13799 | +int | |
13800 | +do_tlbie( kernel_vars_t *kv, ulong ea ) | |
13801 | +{ | |
13802 | + int ind = (ea >> 12) & 0x1f; | |
13803 | + mPTE_t *pi, *pd; | |
13804 | + ulong *iea, *dea; | |
13805 | + | |
13806 | + pi = &MMU.ptes_i_603[ind]; | |
13807 | + pd = &MMU.ptes_d_603[ind]; | |
13808 | + iea = &MMU.ptes_i_ea_603[ind]; | |
13809 | + dea = &MMU.ptes_d_ea_603[ind]; | |
13810 | + for( ; ind < 64; ind +=32, pd += 32, pi += 32, iea += 32, dea +=32 ) { | |
13811 | + if( pi->v ) | |
13812 | + flush_vsid_ea( kv, pi->vsid, *iea ); | |
13813 | + if( pd->v ) | |
13814 | + flush_vsid_ea( kv, pd->vsid, *dea ); | |
13815 | + *(ulong*)pi = 0; | |
13816 | + *(ulong*)pd = 0; | |
13817 | + } | |
13818 | + return RVEC_NOP; | |
13819 | +} | |
13820 | + | |
13821 | +#endif /* EMULATE_603 */ | |
13822 | + | |
13823 | --- /dev/null | |
13824 | +++ b/drivers/macintosh/mol/sheep.c | |
13825 | @@ -0,0 +1,701 @@ | |
13826 | +/* | |
13827 | + * sheep_net.c - Linux driver for SheepShaver/Basilisk II networking (access to raw Ethernet packets) | |
13828 | + * | |
13829 | + * SheepShaver (C) 1997-1999 Mar"c" Hellwig and Christian Bauer | |
13830 | + * Basilisk II (C) 1997-1999 Christian Bauer | |
13831 | + * | |
13832 | + * Ported to 2.4 and reworked, Samuel Rydh 1999-2003 | |
13833 | + */ | |
13834 | + | |
13835 | +#include <linux/kernel.h> | |
13836 | +#include <linux/module.h> | |
13837 | +#include <linux/version.h> | |
13838 | +#include <linux/miscdevice.h> | |
13839 | +#include <linux/netdevice.h> | |
13840 | +#include <linux/etherdevice.h> | |
13841 | +#include <linux/if_ether.h> | |
13842 | +#include <linux/if_arp.h> | |
13843 | +#include <linux/fs.h> | |
13844 | +#include <linux/poll.h> | |
13845 | +#include <linux/init.h> | |
13846 | +#include <net/sock.h> | |
13847 | +#include <asm/uaccess.h> | |
13848 | +#include <net/arp.h> | |
13849 | +#include <net/ip.h> | |
13850 | +#include <linux/in.h> | |
13851 | +#include <linux/wait.h> | |
13852 | + | |
13853 | +MODULE_AUTHOR("Marc Hellwig and Christian Bauer"); | |
13854 | +MODULE_DESCRIPTION("SheepShaver/Basilisk II networking"); | |
13855 | +MODULE_LICENSE("GPL"); | |
13856 | + | |
13857 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | |
13858 | +#define LINUX_26 | |
13859 | +#endif | |
13860 | + | |
13861 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) | |
13862 | +#define ETH_HDR(skb) eth_hdr((skb)) | |
13863 | +#else | |
13864 | +#define ETH_HDR(skb) (skb)->mac.ethernet | |
13865 | +#endif | |
13866 | + | |
13867 | +#define DEBUG 0 | |
13868 | + | |
13869 | +#define bug printk | |
13870 | +#if DEBUG | |
13871 | +#define D(x) (x); | |
13872 | +#else | |
13873 | +#define D(x) ; | |
13874 | +#endif | |
13875 | + | |
13876 | +#define SHEEP_NET_MINOR 198 // Driver minor number | |
13877 | +#define MAX_QUEUE 32 // Maximum number of packets in queue | |
13878 | +#define PROT_MAGIC 1520 // Our "magic" protocol type | |
13879 | + | |
13880 | +#define ETH_ADDR_MULTICAST 0x1 | |
13881 | +#define ETH_ADDR_LOCALLY_DEFINED 0x2 | |
13882 | + | |
13883 | +#define SIOC_MOL_GET_IPFILTER SIOCDEVPRIVATE | |
13884 | +#define SIOC_MOL_SET_IPFILTER (SIOCDEVPRIVATE + 1) | |
13885 | + | |
13886 | +struct SheepVars { | |
13887 | + /* IMPORTANT: the packet_type struct must go first. It no longer (2.6) contains | |
13888 | + * a data field so we typecast to get the SheepVars struct | |
13889 | + */ | |
13890 | + struct packet_type pt; // Receiver packet type | |
13891 | + struct net_device *ether; // The Ethernet device we're attached to | |
13892 | + struct sock *skt; // Socket for communication with Ethernet card | |
13893 | + struct sk_buff_head queue; // Receiver packet queue | |
13894 | + wait_queue_head_t wait; // Wait queue for blocking read operations | |
13895 | + unsigned long ipfilter; // only receive ip packets destined for this address | |
13896 | + char fake_addr[6]; | |
13897 | +}; | |
13898 | + | |
13899 | +/* | |
13900 | + * How various hosts address MOL | |
13901 | + * | |
13902 | + * External hosts: eth_addr, MOL_IP | |
13903 | + * Local host: fake_addr, MOL_IP | |
13904 | + * MOL: fake_addr, MOL_IP | |
13905 | + */ | |
13906 | + | |
13907 | +#ifdef LINUX_26 | |
13908 | + | |
13909 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) | |
13910 | +#define compat_sk_alloc(a,b,c) sk_alloc( (a), (b), &mol_proto, 1 ) | |
13911 | +#else | |
13912 | +#define compat_sk_alloc(a,b,c) sk_alloc( (a), (b), (c), NULL ) | |
13913 | +#endif | |
13914 | + | |
13915 | +#define skt_set_dead(skt) do {} while(0) | |
13916 | +#define wmem_alloc sk_wmem_alloc | |
13917 | +#else | |
13918 | +#define compat_sk_alloc sk_alloc | |
13919 | +#define skt_set_dead(skt) (skt)->dead = 1 | |
13920 | +#endif | |
13921 | + | |
13922 | +/************************************************************************/ | |
13923 | +/* ethernet address masquerading */ | |
13924 | +/************************************************************************/ | |
13925 | + | |
13926 | +static inline int | |
13927 | +addrcmp( const char *a1, const char *a2 ) | |
13928 | +{ | |
13929 | + if( *(u32*)a1 != *(u32*)a2 ) | |
13930 | + return 1; | |
13931 | + return *((u16*)a1+2) != *((u16*)a2+2); | |
13932 | +} | |
13933 | + | |
13934 | +/* Outgoing packet. Replace the fake enet addr with the real one. */ | |
13935 | +static inline void | |
13936 | +cpyaddr( char *d, const char *s ) | |
13937 | +{ | |
13938 | + *(u32*)d = *(u32*)s; | |
13939 | + *(u16*)&d[4] = *(u16*)&s[4]; | |
13940 | +} | |
13941 | + | |
13942 | +static void | |
13943 | +demasquerade( struct sk_buff *skb, struct SheepVars *v ) | |
13944 | +{ | |
13945 | + const char *local_addr = v->ether->dev_addr; | |
13946 | + const char *fake_addr = v->fake_addr; | |
13947 | +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) | |
13948 | + char *p = skb_mac_header(skb); | |
13949 | +#else | |
13950 | + char *p = skb->mac.raw; | |
13951 | +#endif | |
13952 | + int proto = *(short*)&p[12]; | |
13953 | + | |
13954 | + cpyaddr( &p[6], local_addr ); // Source address | |
13955 | + | |
13956 | + // Need to fix ARP packets | |
13957 | + if( proto == htons(ETH_P_ARP) ) | |
13958 | + if( !addrcmp(&p[14+8], fake_addr) ) // sender HW-addr | |
13959 | + cpyaddr( &p[14+8], local_addr ); | |
13960 | + | |
13961 | + // ...and AARPs (snap code: 0x00,0x00,0x00,0x80,0xF3) | |
13962 | + if( !p[17] && *(u32*)&p[18] == 0x000080F3 ){ | |
13963 | + // XXX: we should perhaps look for the 802 frame too | |
13964 | + if( !addrcmp(&p[30], fake_addr) ) | |
13965 | + cpyaddr( &p[30], local_addr ); // sender HW-addr | |
13966 | + } | |
13967 | +} | |
13968 | + | |
13969 | + | |
13970 | +/************************************************************************/ | |
13971 | +/* receive filter (also intercepts outgoing packets) */ | |
13972 | +/************************************************************************/ | |
13973 | + | |
13974 | +/* This function filters both outgoing and incoming traffic. | |
13975 | + * | |
13976 | + * - Outgoing PROT_MAGIC packets are outgoing mol packets | |
13977 | + * addressed to the world (not to the local host). | |
13978 | + * | |
13979 | + * - Outgoing packets addressed to the fake address | |
13980 | + * are incoming MOL packets (from the local host). | |
13981 | + * These packets will be seen on the wire, since we can't | |
13982 | + * block them... | |
13983 | + * | |
13984 | + * - Incoming packets which originate from the fake address | |
13985 | + * are MOL packets addressed to the local host. | |
13986 | + * | |
13987 | + * - Incomming external traffic to the MOL IP address are incoming | |
13988 | + * MOL packets. Linux will see these packets too. (Hmm... if | |
13989 | + * we change protocol to PROT_MAGIC then linux ought to ignore | |
13990 | + * them; currently linux responds to ICMP packets even though | |
13991 | + * the IP address is wrong.) | |
13992 | + */ | |
13993 | + | |
13994 | + | |
13995 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) | |
13996 | +static int | |
13997 | +sheep_net_receiver( struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev ) | |
13998 | +#else | |
13999 | +static int | |
14000 | +sheep_net_receiver( struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ) | |
14001 | +#endif | |
14002 | +{ | |
14003 | + int multicast = (ETH_HDR(skb)->h_dest[0] & ETH_ADDR_MULTICAST); | |
14004 | + const char *laddr = dev->dev_addr; | |
14005 | + struct sk_buff *skb2; | |
14006 | + struct SheepVars *v = (struct SheepVars*)pt; | |
14007 | + | |
14008 | + D(bug("sheep_net: packet received\n")); | |
14009 | + | |
14010 | + if( skb->pkt_type == PACKET_OUTGOING ) { | |
14011 | + // Is this an MOL packet to the world? | |
14012 | + if( skb->protocol == PROT_MAGIC ) | |
14013 | + goto drop; | |
14014 | + | |
14015 | + if( !multicast ) { | |
14016 | + // Drop, unless this is a localhost -> MOL transmission */ | |
14017 | + if( addrcmp((char*)Ð_HDR(skb)->h_dest, v->fake_addr) ) | |
14018 | + goto drop; | |
14019 | + | |
14020 | + /* XXX: If it were possible, we would prevent the packet from beeing sent out | |
14021 | + * on the wire (after having put it on our packet reception queue). | |
14022 | + * A transmission to a non-existent mac address will unfortunately | |
14023 | + * be subnet-visible (having a switched network doesn't help). As a | |
14024 | + * workaround, we change the destination address to the address of | |
14025 | + * the controller. This way, the packet ought to be discarded by | |
14026 | + * switches. | |
14027 | + */ | |
14028 | + cpyaddr( Ð_HDR(skb)->h_dest[0], laddr ); | |
14029 | + } | |
14030 | + } else { | |
14031 | + // is this a packet to the local host from MOL? | |
14032 | + if( !addrcmp((char*)Ð_HDR(skb)->h_source, v->fake_addr) ) | |
14033 | + goto drop; | |
14034 | + | |
14035 | + if( !multicast ) { | |
14036 | + // if the packet is not meant for this host, discard it | |
14037 | + if( addrcmp((char*)Ð_HDR(skb)->h_dest, laddr) ) | |
14038 | + goto drop; | |
14039 | + | |
14040 | + // filter IP-traffic | |
14041 | + if( (skb->protocol == htons(ETH_P_IP)) ) { | |
14042 | + // drop if not addreesed to MOL? | |
14043 | +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) | |
14044 | + if( !v->ipfilter || (ipip_hdr(skb)->daddr != v->ipfilter) ) | |
14045 | +#else | |
14046 | + if( !v->ipfilter || (skb->h.ipiph->daddr != v->ipfilter) ) | |
14047 | +#endif | |
14048 | + goto drop; | |
14049 | + // we don't want this packet interpreted by linux... | |
14050 | + skb->protocol = PROT_MAGIC; | |
14051 | + } | |
14052 | + } | |
14053 | + } | |
14054 | + // Discard packets if queue gets too full | |
14055 | + if( skb_queue_len(&v->queue) > MAX_QUEUE ) | |
14056 | + goto drop; | |
14057 | + | |
14058 | + /* masquerade. The skb is typically has a refcount != 1 so we play safe | |
14059 | + * and make a copy before modifying it. This also takes care of fragmented | |
14060 | + * skbuffs (we might receive those if we are attached to a device with support | |
14061 | + * for it) | |
14062 | + */ | |
14063 | + if( !(skb2=skb_copy(skb, GFP_ATOMIC)) ) | |
14064 | + goto drop; | |
14065 | + kfree_skb( skb ); | |
14066 | + skb = skb2; | |
14067 | + | |
14068 | + if( !multicast ) | |
14069 | + cpyaddr( Ð_HDR(skb)->h_dest[0], v->fake_addr ); | |
14070 | + | |
14071 | + // We also want the Ethernet header | |
14072 | +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) | |
14073 | + skb_push( skb, skb->data - skb_mac_header(skb) ); | |
14074 | +#else | |
14075 | + skb_push( skb, skb->data - skb->mac.raw ); | |
14076 | +#endif | |
14077 | + | |
14078 | + // Enqueue packet | |
14079 | + skb_queue_tail( &v->queue, skb ); | |
14080 | + | |
14081 | + // Unblock blocked read | |
14082 | + wake_up_interruptible( &v->wait ); | |
14083 | + return 0; | |
14084 | + | |
14085 | +drop: | |
14086 | + kfree_skb( skb ); | |
14087 | + return 0; | |
14088 | +} | |
14089 | + | |
14090 | + | |
14091 | +/************************************************************************/ | |
14092 | +/* misc device ops */ | |
14093 | +/************************************************************************/ | |
14094 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) | |
14095 | +static struct proto mol_proto = | |
14096 | +{ | |
14097 | + .name = "MOL", | |
14098 | + .owner = THIS_MODULE, | |
14099 | + .obj_size = sizeof(struct sock) | |
14100 | +}; | |
14101 | +#endif | |
14102 | + | |
14103 | + | |
14104 | +static int | |
14105 | +sheep_net_open( struct inode *inode, struct file *f ) | |
14106 | +{ | |
14107 | + static char fake_addr_[6] = { 0xFE, 0xFD, 0xDE, 0xAD, 0xBE, 0xEF }; | |
14108 | + struct SheepVars *v; | |
14109 | + D(bug("sheep_net: open\n")); | |
14110 | + | |
14111 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) | |
14112 | + if (proto_register(&mol_proto,0) < 0) | |
14113 | + { | |
14114 | + printk(KERN_INFO "Unable to register protocol type\n"); | |
14115 | + return -1; | |
14116 | + } | |
14117 | +#endif | |
14118 | + | |
14119 | + // Must be opened with read permissions | |
14120 | + if( (f->f_flags & O_ACCMODE) == O_WRONLY ) | |
14121 | + return -EPERM; | |
14122 | + | |
14123 | + // Allocate private variables | |
14124 | + f->private_data = kmalloc(sizeof(struct SheepVars), GFP_USER); | |
14125 | + if( f->private_data == NULL) | |
14126 | + return -ENOMEM; | |
14127 | + | |
14128 | + v = (struct SheepVars *) f->private_data; | |
14129 | + | |
14130 | + memset( v, 0, sizeof(*v) ); | |
14131 | + memcpy( v->fake_addr, fake_addr_, 6 ); | |
14132 | + | |
14133 | + skb_queue_head_init( &v->queue ); | |
14134 | + init_waitqueue_head( &v->wait ); | |
14135 | + return 0; | |
14136 | +} | |
14137 | + | |
14138 | + | |
14139 | +static int | |
14140 | +sheep_net_release( struct inode *inode, struct file *f ) | |
14141 | +{ | |
14142 | + struct SheepVars *v = (struct SheepVars *)f->private_data; | |
14143 | + struct sk_buff *skb; | |
14144 | + D(bug("sheep_net: close\n")); | |
14145 | + | |
14146 | + // Detach from Ethernet card | |
14147 | + if( v->ether ) { | |
14148 | + dev_remove_pack( &v->pt ); | |
14149 | + sk_free( v->skt ); | |
14150 | + v->skt = NULL; | |
14151 | + dev_put( v->ether ); | |
14152 | + v->ether = NULL; | |
14153 | + } | |
14154 | + | |
14155 | + // Empty packet queue | |
14156 | + while( (skb=skb_dequeue(&v->queue)) ) | |
14157 | + kfree_skb(skb); | |
14158 | + | |
14159 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) | |
14160 | + proto_unregister(&mol_proto); | |
14161 | +#endif | |
14162 | + | |
14163 | + // Free private variables | |
14164 | + kfree(v); | |
14165 | + return 0; | |
14166 | +} | |
14167 | + | |
14168 | +static inline int | |
14169 | +get_iovsize( const struct iovec *iv, int count ) | |
14170 | +{ | |
14171 | + int s; | |
14172 | + for( s=0; count-- ; iv++ ) | |
14173 | + s += iv->iov_len; | |
14174 | + return s; | |
14175 | +} | |
14176 | + | |
14177 | +static int | |
14178 | +memcpy_tov( const struct iovec *iv, const char *buf, int s ) | |
14179 | +{ | |
14180 | + while( s > 0 ) { | |
14181 | + int len = min_t( unsigned int, iv->iov_len, s ); | |
14182 | + | |
14183 | + if( copy_to_user(iv->iov_base, buf, len) ) | |
14184 | + return -EFAULT; | |
14185 | + s -= len; | |
14186 | + buf += len; | |
14187 | + iv++; | |
14188 | + } | |
14189 | + return 0; | |
14190 | +} | |
14191 | + | |
14192 | +static int | |
14193 | +memcpy_fromv( char *buf, const struct iovec *iv, int s ) | |
14194 | +{ | |
14195 | + while( s > 0 ) { | |
14196 | + int len = min_t( unsigned int, iv->iov_len, s ); | |
14197 | + | |
14198 | + if( copy_from_user(buf, iv->iov_base, len) ) | |
14199 | + return -EFAULT; | |
14200 | + s -= len; | |
14201 | + buf += len; | |
14202 | + iv++; | |
14203 | + } | |
14204 | + return 0; | |
14205 | +} | |
14206 | + | |
14207 | +static ssize_t | |
14208 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) | |
14209 | +sheep_net_aio_read(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t pos) | |
14210 | +{ | |
14211 | + struct file *f = iocb->ki_filp; | |
14212 | +#else /* Linux 2.6.18 or older */ | |
14213 | +sheep_net_readv( struct file *f, const struct iovec *iv, unsigned long count, loff_t *pos ) | |
14214 | +{ | |
14215 | +#endif | |
14216 | + struct SheepVars *v = (struct SheepVars *)f->private_data; | |
14217 | + struct sk_buff *skb; | |
14218 | + int size = get_iovsize( iv, count ); | |
14219 | + | |
14220 | + D(bug("sheep_net: read\n")); | |
14221 | + | |
14222 | + while( !(skb=skb_dequeue(&v->queue)) ) { | |
14223 | + // wait around... | |
14224 | + if( (f->f_flags & O_NONBLOCK)) | |
14225 | + return -EAGAIN; | |
14226 | + | |
14227 | + interruptible_sleep_on( &v->wait ); | |
14228 | + | |
14229 | + if( signal_pending(current) ) | |
14230 | + return -EINTR; | |
14231 | + } | |
14232 | + | |
14233 | + // Pass packet to caller | |
14234 | + if( size > skb->len ) | |
14235 | + size = skb->len; | |
14236 | + if( memcpy_tov(iv, skb->data, size) ) | |
14237 | + size = -EFAULT; | |
14238 | + | |
14239 | + kfree_skb( skb ); | |
14240 | + return size; | |
14241 | +} | |
14242 | + | |
14243 | +static ssize_t | |
14244 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) | |
14245 | +sheep_net_aio_write(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t off) | |
14246 | +{ | |
14247 | + struct file *f = iocb->ki_filp; | |
14248 | +#else /* Linux 2.6.18 or older */ | |
14249 | +sheep_net_writev( struct file *f, const struct iovec *iv, unsigned long count, loff_t *off ) | |
14250 | +{ | |
14251 | +#endif | |
14252 | + struct SheepVars *v = (struct SheepVars *)f->private_data; | |
14253 | + struct sk_buff *skb; | |
14254 | + int size = get_iovsize( iv, count ); | |
14255 | + char *p, *laddr; | |
14256 | + D(bug("sheep_net: write\n")); | |
14257 | + | |
14258 | + // Check packet size | |
14259 | + if( size < sizeof(struct ethhdr) ) | |
14260 | + return -EINVAL; | |
14261 | + if( size > 1514 ) { | |
14262 | + printk("sheep_net_write: packet > 1514!\n"); | |
14263 | + size = 1514; | |
14264 | + } | |
14265 | + | |
14266 | + // Interface active? | |
14267 | + if( !v->ether ) | |
14268 | + return size; | |
14269 | + laddr = v->ether->dev_addr; | |
14270 | + | |
14271 | + // Allocate buffer for packet | |
14272 | + if( !(skb=dev_alloc_skb(size)) ) | |
14273 | + return -ENOBUFS; | |
14274 | + | |
14275 | + // Stuff packet in buffer | |
14276 | + p = skb_put( skb, size ); | |
14277 | + if( memcpy_fromv(p, iv, size) ) { | |
14278 | + kfree_skb(skb); | |
14279 | + return -EFAULT; | |
14280 | + } | |
14281 | + | |
14282 | + // Transmit packet | |
14283 | + atomic_add( skb->truesize, &v->skt->wmem_alloc ); | |
14284 | + skb->sk = v->skt; | |
14285 | + skb->dev = v->ether; | |
14286 | + skb->priority = 0; | |
14287 | +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) | |
14288 | + skb_set_network_header(skb, v->ether->hard_header_len); | |
14289 | + skb_set_transport_header(skb, v->ether->hard_header_len); | |
14290 | + skb_reset_mac_header(skb); | |
14291 | +#else | |
14292 | + skb->nh.raw = skb->h.raw = skb->data + v->ether->hard_header_len; | |
14293 | + skb->mac.raw = skb->data; | |
14294 | +#endif | |
14295 | + | |
14296 | + // Base the IP-filter on the IP address of outgoing ARPs | |
14297 | + if( ETH_HDR(skb)->h_proto == htons(ETH_P_ARP) ) { | |
14298 | + char *s = &skb->data[14+14]; /* source IP-address */ | |
14299 | + int n[4]; | |
14300 | + if( *(long*)s != v->ipfilter ) { | |
14301 | + v->ipfilter = *(long*)s; | |
14302 | + n[0]=s[0], n[1]=s[1], n[2]=s[2], n[3]=s[3]; | |
14303 | + printk("IP-filter: %d.%d.%d.%d\n", n[0], n[1], n[2], n[3] ); | |
14304 | + } | |
14305 | + } | |
14306 | + | |
14307 | + // Is this package addressed solely to the local host? | |
14308 | + if( !addrcmp(skb->data, laddr) && !(skb->data[0] & ETH_ADDR_MULTICAST) ) { | |
14309 | + skb->protocol = eth_type_trans( skb, v->ether ); | |
14310 | + netif_rx_ni( skb ); | |
14311 | + return size; | |
14312 | + } | |
14313 | + if( skb->data[0] & ETH_ADDR_MULTICAST ) { | |
14314 | + // We can't clone the skb since we will manipulate the data below | |
14315 | + struct sk_buff *lskb = skb_copy( skb, GFP_ATOMIC ); | |
14316 | + if( lskb ) { | |
14317 | + lskb->protocol = eth_type_trans( lskb, v->ether ); | |
14318 | + netif_rx_ni( lskb ); | |
14319 | + } | |
14320 | + } | |
14321 | + // Outgoing packet (will be seen on the wire) | |
14322 | + demasquerade( skb, v ); | |
14323 | + | |
14324 | + skb->protocol = PROT_MAGIC; // Magic value (we can recognize the packet in sheep_net_receiver) | |
14325 | + dev_queue_xmit( skb ); | |
14326 | + return size; | |
14327 | +} | |
14328 | + | |
14329 | +/* We take care of this using do_sync_* instead in 2.6.19 and newer */ | |
14330 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) | |
14331 | +static ssize_t | |
14332 | +sheep_net_read( struct file *f, char *buf, size_t count, loff_t *off ) | |
14333 | +{ | |
14334 | + struct iovec iv; | |
14335 | + iv.iov_base = buf; | |
14336 | + iv.iov_len = count; | |
14337 | + return sheep_net_readv( f, &iv, 1, off ); | |
14338 | +} | |
14339 | + | |
14340 | +static ssize_t | |
14341 | +sheep_net_write( struct file *f, const char *buf, size_t count, loff_t *off ) | |
14342 | +{ | |
14343 | + struct iovec iv; | |
14344 | + iv.iov_len = count; | |
14345 | + iv.iov_base = (char *)buf; | |
14346 | + return sheep_net_writev( f, &iv, 1, off ); | |
14347 | +} | |
14348 | +#endif | |
14349 | + | |
14350 | +static unsigned int | |
14351 | +sheep_net_poll( struct file *f, struct poll_table_struct *wait ) | |
14352 | +{ | |
14353 | + struct SheepVars *v = (struct SheepVars *)f->private_data; | |
14354 | + D(bug("sheep_net: poll\n")); | |
14355 | + | |
14356 | + poll_wait( f, &v->wait, wait ); | |
14357 | + | |
14358 | + if( !skb_queue_empty(&v->queue) ) | |
14359 | + return POLLIN | POLLRDNORM; | |
14360 | + return 0; | |
14361 | +} | |
14362 | + | |
14363 | +static int | |
14364 | +sheep_net_ioctl( struct inode *inode, struct file *f, unsigned int code, unsigned long arg ) | |
14365 | +{ | |
14366 | + struct SheepVars *v = (struct SheepVars *)f->private_data; | |
14367 | + D(bug("sheep_net: ioctl %04x\n", code)); | |
14368 | + | |
14369 | + switch( code ) { | |
14370 | + // Attach to Ethernet card | |
14371 | + // arg: pointer to name of Ethernet device (char[20]) | |
14372 | + case SIOCSIFLINK: { | |
14373 | + char name[20]; | |
14374 | + int err; | |
14375 | + | |
14376 | + // Already attached? | |
14377 | + if( v->ether ) | |
14378 | + return -EBUSY; | |
14379 | + | |
14380 | + // Get Ethernet card name | |
14381 | + if( copy_from_user(name, (void *)arg, 20) ) | |
14382 | + return -EFAULT; | |
14383 | + name[19] = 0; | |
14384 | + | |
14385 | + // Find card | |
14386 | + if( !(v->ether=dev_get_by_name(name)) ) | |
14387 | + return -ENODEV; | |
14388 | + | |
14389 | + // Is it Ethernet? | |
14390 | + if( v->ether->type != ARPHRD_ETHER) { | |
14391 | + err = -EINVAL; | |
14392 | + goto error; | |
14393 | + } | |
14394 | + | |
14395 | + // Allocate socket | |
14396 | + if( !(v->skt=compat_sk_alloc(0, GFP_USER, 1)) ) { | |
14397 | + err = -ENOMEM; | |
14398 | + goto error; | |
14399 | + } | |
14400 | + skt_set_dead( v->skt ); | |
14401 | + | |
14402 | + // Attach packet handler | |
14403 | + v->pt.type = htons(ETH_P_ALL); | |
14404 | + v->pt.dev = v->ether; | |
14405 | + v->pt.func = sheep_net_receiver; | |
14406 | + //v->pt.data = v; | |
14407 | + dev_add_pack( &v->pt ); | |
14408 | + return 0; | |
14409 | +error: | |
14410 | + if( v->ether ) | |
14411 | + dev_put( v->ether ); | |
14412 | + v->ether = NULL; | |
14413 | + return err; | |
14414 | + } | |
14415 | + | |
14416 | + // Get hardware address of Ethernet card | |
14417 | + // arg: pointer to buffer (6 bytes) to store address | |
14418 | + case SIOCGIFADDR: | |
14419 | + if( copy_to_user((void *)arg, v->fake_addr, 6)) | |
14420 | + return -EFAULT; | |
14421 | + return 0; | |
14422 | + | |
14423 | + // Set the fake HW-address the client will see | |
14424 | + case SIOCSIFADDR: | |
14425 | + if( copy_from_user(v->fake_addr, (void*)arg, 6 )) | |
14426 | + return -EFAULT; | |
14427 | + return 0; | |
14428 | + | |
14429 | + // Add multicast address | |
14430 | + // arg: pointer to address (6 bytes) | |
14431 | + case SIOCADDMULTI: { | |
14432 | + char addr[6]; | |
14433 | + int ret; | |
14434 | + if( !v->ether ) | |
14435 | + return -ENODEV; | |
14436 | + if( copy_from_user(addr, (void *)arg, 6)) | |
14437 | + return -EFAULT; | |
14438 | + ret = dev_mc_add(v->ether, addr, 6, 0); | |
14439 | + return ret; | |
14440 | + } | |
14441 | + | |
14442 | + // Remove multicast address | |
14443 | + // arg: pointer to address (6 bytes) | |
14444 | + case SIOCDELMULTI: { | |
14445 | + char addr[6]; | |
14446 | + if( !v->ether ) | |
14447 | + return -ENODEV; | |
14448 | + if( copy_from_user(addr, (void *)arg, 6)) | |
14449 | + return -EFAULT; | |
14450 | + return dev_mc_delete(v->ether, addr, 6, 0); | |
14451 | + } | |
14452 | + | |
14453 | +#if 0 | |
14454 | + // Return size of first packet in queue | |
14455 | + case FIONREAD: { | |
14456 | + int count = 0; | |
14457 | + struct sk_buff *skb; | |
14458 | + long flags; | |
14459 | + spin_lock_irqsave(&v->queue.lock, flags ); | |
14460 | + | |
14461 | + skb = skb_peek(&v->queue); | |
14462 | + if( skb ) | |
14463 | + count = skb->len; | |
14464 | + | |
14465 | + spin_unlock_irqrestore(&v->queue.lock, flags ); | |
14466 | + return put_user(count, (int *)arg); | |
14467 | + } | |
14468 | +#endif | |
14469 | + case SIOC_MOL_GET_IPFILTER: | |
14470 | + return put_user(v->ipfilter, (int *)arg ); | |
14471 | + | |
14472 | + case SIOC_MOL_SET_IPFILTER: | |
14473 | + v->ipfilter = arg; | |
14474 | + return 0; | |
14475 | + } | |
14476 | + return -ENOIOCTLCMD; | |
14477 | +} | |
14478 | + | |
14479 | + | |
14480 | +/************************************************************************/ | |
14481 | +/* init / cleanup */ | |
14482 | +/************************************************************************/ | |
14483 | + | |
14484 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) | |
14485 | +static struct file_operations sheep_net_fops = { | |
14486 | + .owner = THIS_MODULE, | |
14487 | + .read = do_sync_read, | |
14488 | + .aio_read = sheep_net_aio_read, | |
14489 | + .write = do_sync_write, | |
14490 | + .aio_write = sheep_net_aio_write, | |
14491 | + .poll = sheep_net_poll, | |
14492 | + .ioctl = sheep_net_ioctl, | |
14493 | + .open = sheep_net_open, | |
14494 | + .release = sheep_net_release, | |
14495 | +}; | |
14496 | +#else | |
14497 | +static struct file_operations sheep_net_fops = { | |
14498 | + .owner = THIS_MODULE, | |
14499 | + .read = sheep_net_read, | |
14500 | + .write = sheep_net_write, | |
14501 | + .readv = sheep_net_readv, | |
14502 | + .writev = sheep_net_writev, | |
14503 | + .poll = sheep_net_poll, | |
14504 | + .ioctl = sheep_net_ioctl, | |
14505 | + .open = sheep_net_open, | |
14506 | + .release = sheep_net_release, | |
14507 | +}; | |
14508 | +#endif | |
14509 | + | |
14510 | +static struct miscdevice sheep_net_device = { | |
14511 | + .minor = SHEEP_NET_MINOR, | |
14512 | + .name = "sheep_net", | |
14513 | + .fops = &sheep_net_fops | |
14514 | +}; | |
14515 | + | |
14516 | +int | |
14517 | +init_module( void ) | |
14518 | +{ | |
14519 | + return misc_register( &sheep_net_device ); | |
14520 | +} | |
14521 | + | |
14522 | +void | |
14523 | +cleanup_module( void ) | |
14524 | +{ | |
14525 | + (void) misc_deregister( &sheep_net_device ); | |
14526 | +} | |
14527 | --- /dev/null | |
14528 | +++ b/drivers/macintosh/mol/skiplist.c | |
14529 | @@ -0,0 +1,222 @@ | |
14530 | +/* | |
14531 | + * Creation Date: <2003/03/03 23:19:47 samuel> | |
14532 | + * Time-stamp: <2004/02/21 16:24:56 samuel> | |
14533 | + * | |
14534 | + * <skiplist.c> | |
14535 | + * | |
14536 | + * Skiplist implementation | |
14537 | + * | |
14538 | + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) | |
14539 | + * | |
14540 | + * This program is free software; you can redistribute it and/or | |
14541 | + * modify it under the terms of the GNU General Public License | |
14542 | + * as published by the Free Software Foundation | |
14543 | + * | |
14544 | + */ | |
14545 | + | |
14546 | +#include "archinclude.h" | |
14547 | +#include "skiplist.h" | |
14548 | +#include "alloc.h" | |
14549 | + | |
14550 | +#define SKIPLIST_END INT_MAX /* this key is reserved */ | |
14551 | + | |
14552 | +/* | |
14553 | + * Skiplist Example: | |
14554 | + * | |
14555 | + * level 0 -> el1 -> el2 -> el3 --> el4 --> null_el | |
14556 | + * level 1 --> el2 -> el3 --> el4 --> null_el | |
14557 | + * level 2 --> el2 --> el4 --> null_el | |
14558 | + * level 3 --> el2 -----> null_el | |
14559 | + * level 4 ------------> null_el | |
14560 | + * ... | |
14561 | + * SKIPLIST_MAX_HEIGHT-1 ------------> null_el | |
14562 | + */ | |
14563 | + | |
14564 | +static unsigned int mol_rand_seed = 152; | |
14565 | + | |
14566 | +static inline int | |
14567 | +_cntlz( int val ) | |
14568 | +{ | |
14569 | + int ret; | |
14570 | + asm volatile("cntlzw %0,%1" : "=r" (ret) : "r"(val) ); | |
14571 | + return ret; | |
14572 | +} | |
14573 | + | |
14574 | +static unsigned long | |
14575 | +mol_random( void ) | |
14576 | +{ | |
14577 | + unsigned int t; | |
14578 | + asm( "mftb %0" : "=r"(t) : ); | |
14579 | + mol_rand_seed = mol_rand_seed*69069L+1; | |
14580 | + return mol_rand_seed^t; | |
14581 | +} | |
14582 | + | |
14583 | +static void | |
14584 | +mol_random_entropy( void ) | |
14585 | +{ | |
14586 | + unsigned int entropy; | |
14587 | + asm( "mftb %0" : "=r" (entropy) : ); | |
14588 | + mol_rand_seed ^= entropy; | |
14589 | +} | |
14590 | + | |
14591 | +static inline void | |
14592 | +set_level_next( skiplist_level_t *level, skiplist_el_t *el ) | |
14593 | +{ | |
14594 | + level->next = el; | |
14595 | +#ifdef __darwin__ | |
14596 | + level->next_phys = el ? tophys_mol(el) : 0; | |
14597 | +#endif | |
14598 | +} | |
14599 | + | |
14600 | + | |
14601 | +/************************************************************************/ | |
14602 | +/* skiplist operations */ | |
14603 | +/************************************************************************/ | |
14604 | + | |
14605 | +int | |
14606 | +skiplist_prealloc( skiplist_t *sl, char *buf, unsigned int size, | |
14607 | + skiplist_el_callback callback, void *usr1, void *usr2 ) | |
14608 | +{ | |
14609 | + skiplist_el_t *p, *head; | |
14610 | + unsigned int s; | |
14611 | + int n, count; | |
14612 | + | |
14613 | + head = NULL; | |
14614 | + for( count=0 ;; size -= s, buf += s, count++ ) { | |
14615 | + for( n=0; n<SKIPLIST_MAX_HEIGHT-1 && (mol_random() & 0x40) ; n++ ) | |
14616 | + ; | |
14617 | + s = sl->datasize + sizeof(skiplist_t) + n*sizeof(skiplist_level_t); | |
14618 | + if( s > size ) | |
14619 | + break; | |
14620 | + p = (skiplist_el_t*)(buf + sl->datasize); | |
14621 | + p->key = n; | |
14622 | + set_level_next( &p->level[0], head ); | |
14623 | + head = p; | |
14624 | + } | |
14625 | + | |
14626 | + /* note: the callback is allowed to manipulate the skiplist */ | |
14627 | + for( n=0, p=head; p; p=p->level[0].next, n++ ) { | |
14628 | + if( callback ) | |
14629 | + (*callback)( (char*)p - sl->datasize, n, count, usr1, usr2 ); | |
14630 | + if( !p->level[0].next ) { | |
14631 | + p->level[0] = sl->freelist; | |
14632 | + set_level_next( &sl->freelist, head ); | |
14633 | + break; | |
14634 | + } | |
14635 | + } | |
14636 | + return count; | |
14637 | +} | |
14638 | + | |
14639 | +char * | |
14640 | +skiplist_insert( skiplist_t *sl, int key ) | |
14641 | +{ | |
14642 | + skiplist_el_t *pleft = (skiplist_el_t*)((char*)&sl->root[0] - offsetof(skiplist_el_t, level)); | |
14643 | + skiplist_level_t el = sl->freelist; | |
14644 | + skiplist_el_t *p = el.next; | |
14645 | + int n, slev; | |
14646 | + | |
14647 | + if( !p ) | |
14648 | + return NULL; | |
14649 | + sl->freelist = p->level[0]; | |
14650 | + n = p->key; | |
14651 | + p->key = key; | |
14652 | + | |
14653 | + /* pick a good search level (the -3 is benchmarked) */ | |
14654 | + sl->nel++; | |
14655 | + slev = 31 - _cntlz(sl->nel) - 3; | |
14656 | + if( slev > SKIPLIST_MAX_HEIGHT-1 ) | |
14657 | + slev = SKIPLIST_MAX_HEIGHT-1; | |
14658 | + else if( slev < 0 ) | |
14659 | + slev = 0; | |
14660 | + sl->slevel = slev; | |
14661 | + | |
14662 | + /* insert element */ | |
14663 | + if( slev < n ) | |
14664 | + slev = n; | |
14665 | + for( ; slev >= 0; slev-- ) { | |
14666 | + for( ; pleft->level[slev].next->key < key ; pleft=pleft->level[slev].next ) | |
14667 | + ; | |
14668 | + if( slev <= n ) { | |
14669 | + p->level[slev] = pleft->level[slev]; | |
14670 | + pleft->level[slev] = el; | |
14671 | + } | |
14672 | + } | |
14673 | + | |
14674 | + return (char*)p - sl->datasize; | |
14675 | +} | |
14676 | + | |
14677 | +char * | |
14678 | +skiplist_delete( skiplist_t *sl, int key ) | |
14679 | +{ | |
14680 | + skiplist_el_t *p = (skiplist_el_t*)((char*)&sl->root[0] - offsetof(skiplist_el_t, level)); | |
14681 | + skiplist_level_t delptr; | |
14682 | + int n, level = -1; | |
14683 | + | |
14684 | + delptr.next = 0; | |
14685 | + | |
14686 | + for( n=SKIPLIST_MAX_HEIGHT-1; n>=0; n-- ) { | |
14687 | + for( ; p->level[n].next->key < key ; p=p->level[n].next ) | |
14688 | + ; | |
14689 | + if( p->level[n].next->key != key ) | |
14690 | + continue; | |
14691 | + | |
14692 | + if( level < 0 ) { | |
14693 | + delptr = p->level[n]; | |
14694 | + level = n; | |
14695 | + } | |
14696 | + p->level[n] = delptr.next->level[n]; | |
14697 | + } | |
14698 | + if( level < 0 ) | |
14699 | + return NULL; | |
14700 | + | |
14701 | + /* put on freelist */ | |
14702 | + p = delptr.next; | |
14703 | + p->key = level; | |
14704 | + p->level[0] = sl->freelist; | |
14705 | + sl->freelist = delptr; | |
14706 | + sl->nel--; | |
14707 | + | |
14708 | + return (char*)p - sl->datasize; | |
14709 | +} | |
14710 | + | |
14711 | +char * | |
14712 | +skiplist_lookup( skiplist_t *sl, int key ) | |
14713 | +{ | |
14714 | + skiplist_el_t *p = (skiplist_el_t*)((char*)&sl->root[0] - offsetof(skiplist_el_t, level)); | |
14715 | + int n = sl->slevel; | |
14716 | + | |
14717 | + for( ;; ) { | |
14718 | + if( p->level[n].next->key < key ) { | |
14719 | + p = p->level[n].next; | |
14720 | + continue; | |
14721 | + } | |
14722 | + if( p->level[n].next->key > key ) { | |
14723 | + if( --n < 0 ) | |
14724 | + break; | |
14725 | + continue; | |
14726 | + } | |
14727 | + return (char*)p->level[n].next - sl->datasize; | |
14728 | + } | |
14729 | + return NULL; | |
14730 | +} | |
14731 | + | |
14732 | +void | |
14733 | +skiplist_init( skiplist_t *sl, int datasize ) | |
14734 | +{ | |
14735 | + skiplist_level_t nilptr; | |
14736 | + int i; | |
14737 | + | |
14738 | + mol_random_entropy(); | |
14739 | + | |
14740 | + memset( sl, 0, sizeof(*sl) ); | |
14741 | + | |
14742 | + sl->nil_el.key = SKIPLIST_END; | |
14743 | + sl->datasize = datasize; | |
14744 | + | |
14745 | + /* remember: the nil element is of level 0 */ | |
14746 | + set_level_next( &nilptr, &sl->nil_el ); | |
14747 | + sl->nil_el.level[0] = nilptr; | |
14748 | + | |
14749 | + for( i=0; i < SKIPLIST_MAX_HEIGHT ; i++ ) | |
14750 | + sl->root[i] = nilptr; | |
14751 | +} |