]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.suse/suse-ppc32-mol.patch
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / suse-ppc32-mol.patch
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*)&ETH_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( &ETH_HDR(skb)->h_dest[0], laddr );
14029 + }
14030 + } else {
14031 + // is this a packet to the local host from MOL?
14032 + if( !addrcmp((char*)&ETH_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*)&ETH_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( &ETH_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 +}