]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/suse-ppc32-mol.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / suse-ppc32-mol.patch
CommitLineData
2cb7cef9
BS
1From: olh@suse.de
2Subject: vanilla sources from www.maconlinux.org
3Patch-mainline: never
4
5to avoid the km_ mess
6
7Never 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 ) {
82094b55 5146+ *pte = 0;
2cb7cef9
BS
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;
82094b55 5626+ int sv_mode, i, sbits;
2cb7cef9
BS
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+}