patch-pre2.0.8 linux/arch/ppc/mm/init.c
Next file: linux/arch/ppc/mm/mmu.h
Previous file: linux/arch/ppc/mm/fault.c
Back to the patch index
Back to the overall index
- Lines: 807
- Date:
Mon May 27 12:00:59 1996
- Orig file:
pre2.0.7/linux/arch/ppc/mm/init.c
- Orig date:
Fri Apr 12 15:51:48 1996
diff -u --recursive --new-file pre2.0.7/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
@@ -5,7 +5,6 @@
* Ported to PPC by Gary Thomas
*/
-
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -17,37 +16,18 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/swap.h>
-#include <asm/pgtable.h>
-
-
-/* made this a static array since alpha and intel aren't.
- thomas made it a dynamic array and had to add lots of stuff to other parts
- of linux to make sure the pages were contiguous and such. the static array
- seems much easier
- making it 8k for now. will change later.
- -- Cort
- */
-pgd_t swapper_pg_dir[1024];
-/*pgd_t *swapper_pg_dir;*/
+#define SHOW_FAULTS
+#undef SHOW_FAULTS
-pte *MMU_get_page(void);
+#define SHOW_INVALIDATES
+#undef SHOW_INVALIDATES
+#include <asm/pgtable.h>
-#if 0
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/mipsconfig.h>
-
-extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */
-#endif
+extern pgd_t swapper_pg_dir[1024*8];
-#ifdef CONFIG_DESKSTATION_TYNE
-extern void deskstation_tyne_dma_init(void);
-#endif
-#ifdef CONFIG_SOUND
-extern void sound_mem_init(void);
-#endif
extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
@@ -113,13 +93,9 @@
unsigned long __zero_page(void)
{
-#if 0
- panic("__zero_page");
-#else
extern char empty_zero_page[PAGE_SIZE];
bzero(empty_zero_page, PAGE_SIZE);
return (unsigned long) empty_zero_page;
-#endif
}
void show_mem(void)
@@ -133,7 +109,7 @@
i = high_memory >> PAGE_SHIFT;
while (i-- > 0) {
total++;
- if (mem_map[i].reserved)
+ if (PageReserved(mem_map+i))
reserved++;
else if (!mem_map[i].count)
free++;
@@ -161,7 +137,6 @@
*/
unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
{
-
#if 0
pgd_t * pg_dir;
pte_t * pg_table;
@@ -194,14 +169,13 @@
cacheflush();
#endif
invalidate();
-#endif
+#endif
return free_area_init(start_mem, end_mem);
}
void mem_init(unsigned long start_mem, unsigned long end_mem)
{
int codepages = 0;
- int reservedpages = 0;
int datapages = 0;
unsigned long tmp;
extern int etext;
@@ -213,30 +187,14 @@
start_mem = PAGE_ALIGN(start_mem);
#if 0
-printk("Mem init - Start: %x, End: %x\n", start_mem, high_memory);
-#endif
- while (start_mem < high_memory) {
- mem_map[MAP_NR(start_mem)].reserved = 0;
- start_mem += PAGE_SIZE;
- }
-#ifdef CONFIG_DESKSTATION_TYNE
- deskstation_tyne_dma_init();
-#endif
-#ifdef CONFIG_SOUND
- sound_mem_init();
+_printk("Mem init - Start: %x, End: %x\n", start_mem, high_memory);
#endif
for (tmp = KERNELBASE ; tmp < high_memory ; tmp += PAGE_SIZE)
{
- if (mem_map[MAP_NR(tmp)].reserved)
+ if (tmp < start_mem)
{
- /*
- * We don't have any reserved pages on the
- * MIPS systems supported until now
- */
- if (0)
- {
- reservedpages++;
- } else if (tmp < (unsigned long) &etext)
+ set_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
+ if (tmp < (unsigned long) &etext)
{
codepages++;
} else
@@ -245,15 +203,15 @@
}
continue;
}
+ clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
mem_map[MAP_NR(tmp)].count = 1;
free_page(tmp);
}
tmp = nr_free_pages << PAGE_SHIFT;
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
+ printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
tmp >> 10,
((int)high_memory - (int)KERNELBASE) >> 10,
codepages << (PAGE_SHIFT-10),
- reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10));
invalidate();
return;
@@ -261,26 +219,24 @@
void si_meminfo(struct sysinfo *val)
{
-#if 0
int i;
- i = high_memory >> PAGE_SHIFT;
+ i = ((int)high_memory & 0x00FFFFFF) >> PAGE_SHIFT;
val->totalram = 0;
val->sharedram = 0;
val->freeram = nr_free_pages << PAGE_SHIFT;
val->bufferram = buffermem;
while (i-- > 0) {
- if (mem_map[i] & MAP_PAGE_RESERVED)
+ if (PageReserved(mem_map+i))
continue;
val->totalram++;
- if (!mem_map[i])
+ if (!mem_map[i].count)
continue;
- val->sharedram += mem_map[i]-1;
+ val->sharedram += mem_map[i].count-1;
}
val->totalram <<= PAGE_SHIFT;
val->sharedram <<= PAGE_SHIFT;
return;
-#endif
}
/* Kernel MMU setup & lowest level hardware support */
@@ -326,8 +282,6 @@
};
BAT BAT2 =
{
-/* map kernel with bats 0 = yes */
-#if 1
{
0x00000000>>17, /* bepi */
BL_256M, /* bl */
@@ -342,22 +296,6 @@
0, /* g */
BPP_RW /* pp */
}
-#else
- {
- 0x90000000>>17, /* bepi */
- BL_256M, /* bl */
- 1, /* vs */
- 1, /* vp */
- },
- {
- 0x00000000>>17, /* brpn */
- 1, /* w */
- 0, /* i (cache enabled) */
- 0, /* m */
- 0, /* g */
- BPP_RW /* pp */
- }
-#endif
};
BAT BAT3 =
{
@@ -380,13 +318,13 @@
{ /* 0x9XXXXXXX -> 0x0XXXXXXX */
{
0x90000000>>17, /* bepi */
- BL_256M, /* bl */
+ BL_16M, /* bl */
1, /* vs */
1, /* vp */
},
{
0x00000000>>17, /* brpn */
- 1, /* w */
+ 0, /* w */
0, /* i (cache enabled) */
0, /* m */
0, /* g */
@@ -397,13 +335,17 @@
unsigned long _SDR1; /* Hardware SDR1 image */
PTE *Hash;
int Hash_size, Hash_mask;
+unsigned long *end_of_DRAM;
int cache_is_copyback = 1;
int kernel_pages_are_copyback = 1;
+/* Note: these need to be in 'data' so they live over the boot */
+unsigned char *BeBox_IO_page = 0;
+unsigned long isBeBox[2] = {0, 0};
-#define NUM_MAPPINGS 8
+#define NUM_MAPPINGS 128
struct
{
- int va, pa, task;
+ int va, pa, pg, task;
} last_mappings[NUM_MAPPINGS];
int next_mapping = 0;
@@ -460,13 +402,13 @@
extern char _start[], _end[];
-void MMU_init(void)
+MMU_init()
{
int i, p;
SEGREG *segs;
-/* _printk("MMU init - started\n");*/
+ _printk("MMU init - started\n");
find_end_of_memory();
-/* _printk(" Start at 0x%08X, End at 0x%08X, Hash at 0x%08X\n", _start, _end, Hash);*/
+ _printk(" Start at 0x%08X, End at 0x%08X, Hash at 0x%08X\n", _start, _end, Hash);
_SDR1 = ((unsigned long)Hash & 0x00FFFFFF) | Hash_mask;
p = (int)mmu_pages;
p = (p + (MMU_PAGE_SIZE-1)) & ~(MMU_PAGE_SIZE-1);
@@ -477,11 +419,12 @@
p += MMU_PAGE_SIZE;
}
/* Force initial page tables */
- /*swapper_pg_dir = (pgd_t *)MMU_get_page();*/
+#if 0
+ swapper_pg_dir = (pgd_t *)MMU_get_page();
+#endif
init_task.tss.pg_tables = (unsigned long *)swapper_pg_dir;
-
/* Segment registers */
- segs = (SEGREG *)init_task.tss.segs;
+ segs = init_task.tss.segs;
for (i = 0; i < 16; i++)
{
segs[i].ks = 0;
@@ -489,12 +432,21 @@
segs[i].vsid = i;
}
/* Map kernel TEXT+DATA+BSS */
-#if 0
- for (i = (int)_start; i <= (int)_end; i += MMU_PAGE_SIZE)
-#else
+ end_of_DRAM = (unsigned long *)Hash;
+ /* Hard map in any special local resources */
+ if (isBeBox[0])
+ {
+ /* Map in one page for the BeBox motherboard I/O */
+ end_of_DRAM = (unsigned long *)((unsigned long)end_of_DRAM - MMU_PAGE_SIZE);
+#if 0
+ BeBox_IO_page = (unsigned char *)0x7FFFF000;
+#endif
+ BeBox_IO_page = (unsigned char *)end_of_DRAM;
+ MMU_map_page(&init_task.tss, BeBox_IO_page, 0x7FFFF000, PAGE_KERNEL);
+ MMU_disable_cache_for_page(&init_task.tss, BeBox_IO_page);
+ }
/* Other parts of the kernel expect ALL RAM to be mapped */
- for (i = (int)_start; i <= (int)Hash; i += MMU_PAGE_SIZE)
-#endif
+ for (i = (int)_start; i < (int)end_of_DRAM; i += MMU_PAGE_SIZE)
{
MMU_map_page(&init_task.tss, i, i & 0x00FFFFFF, PAGE_KERNEL);
}
@@ -503,26 +455,32 @@
{
MMU_map_page(&init_task.tss, i, i & 0x00FFFFFF, PAGE_KERNEL);
}
-/* _printk("MMU init - done!\n");*/
+#if 0 /* I'm not sure this is necessary */
+ /* Clear all DRAM not explicitly used by kernel */
+ bzero(_end, (unsigned long)end_of_DRAM-(unsigned long)_end);
+#endif
+ _printk("MMU init - done!\n");
}
pte *
-MMU_get_page(void)
+MMU_get_page()
{
pte *pg;
if ((pg = (pte *)MMU_get_item(&_free_pages)))
{
bzero((char *)pg, MMU_PAGE_SIZE);
}
-/* _printk("MMU Allocate Page at %08X\n", pg);*/
+ _printk("MMU Allocate Page at %08X\n", pg);
return(pg);
}
MMU_map_page(struct thread_struct *tss, unsigned long va, unsigned long pa, int flags)
{
pte *pd, *pg;
+#if 0
if (va < (unsigned long)0x90000000)
- _printk("Thread: %x, Map VA: %08x -> PA: %08X, Flags: %x\n", tss, va, pa, flags);
+ printk("Thread: %x, Map VA: %08x -> PA: %08X, Flags: %x\n", tss, va, pa, flags);
+#endif
if ((pte **)tss->pg_tables == (pte **)NULL)
{ /* Allocate upper level page map */
(pte **)tss->pg_tables = (pte **)MMU_get_page();
@@ -533,6 +491,7 @@
}
/* Use upper 10 bits of VA to index the first level map */
pd = ((pte **)tss->pg_tables)[(va>>PD_SHIFT)&PD_MASK];
+ pd = (pte *)((int)pd & 0xFFFFF000);
if (pd == (pte *)NULL)
{ /* Need to allocate second-level table */
pd = (pte *)MMU_get_page();
@@ -559,15 +518,15 @@
PTE *_pte, *empty, *slot;
PTE *slot0, *slot1;
extern char _etext;
-
-
-/* printk("hashing tss = %x va = %x pg = %x\n", tss, va, pg);*/
/* TEMP */
+if (va < KERNELBASE)
+{
last_mappings[next_mapping].va = va;
last_mappings[next_mapping].pa = pg?*(int *)pg:0;
- last_mappings[next_mapping].task = current;
+ last_mappings[next_mapping].pg = pg;
+ last_mappings[next_mapping].task = current->pid;
if (++next_mapping == NUM_MAPPINGS) next_mapping = 0;
-
+}
/* TEMP */
page_index = ((int)va & 0x0FFFF000) >> 12;
segment = (unsigned int)va >> 28;
@@ -689,6 +648,7 @@
} else
{ /* Read only page */
perms = PP_RWRX;
+ perms = PP_RXRX;
}
} else
{ /* Kernel pages */
@@ -697,7 +657,7 @@
}
#ifdef SHOW_FAULTS
if (va < KERNELBASE)
-_printk("VA: %08X, PA: %08X, Flags: %x, Perms: %d\n", va, pg->page_num<<12, pg->flags, perms);
+printk("VA: %08X, PA: %08X, Flags: %x, Perms: %d, Vsid: %x\n", va, pg->page_num<<12, pg->flags, perms, vsid);
#endif
slot->pp = perms;
return (0);
@@ -708,56 +668,315 @@
if (slot->c) flags |= _PAGE_DIRTY;
slot->v = 0;
#ifdef SHOW_FAULTS
-_printk("Pull VA: %08X, Flags: %x\n", va, flags);
+printk("Pull VA: %08X, Flags: %x\n", va, flags);
#endif
return (flags);
}
}
/*
+ * Disable cache for a particular page
+ */
+MMU_disable_cache_for_page(struct thread_struct *tss, unsigned long va)
+{
+ int hash, page_index, segment, i, h, _h, api, vsid, perms;
+ PTE *_pte, *empty, *slot;
+ PTE *slot0, *slot1;
+ extern char _etext;
+ page_index = ((int)va & 0x0FFFF000) >> 12;
+ segment = (unsigned int)va >> 28;
+ api = page_index >> 10;
+ vsid = ((SEGREG *)tss->segs)[segment].vsid;
+ empty = slot = (PTE *)NULL;
+ for (_h = 0; _h < 2; _h++)
+ {
+ hash = page_index ^ vsid;
+ if (_h)
+ {
+ hash = ~hash; /* Secondary hash uses ones-complement */
+ }
+ hash &= 0x3FF | (Hash_mask << 10);
+ hash *= 8; /* Eight entries / hash bucket */
+ _pte = &Hash[hash];
+ /* Save slot addresses in case we have to purge */
+ if (_h)
+ {
+ slot1 = _pte;
+ } else
+ {
+ slot0 = _pte;
+ }
+ for (i = 0; i < 8; i++, _pte++)
+ {
+ if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api)
+ { /* Found it! */
+ h = _h;
+ slot = _pte;
+ goto found_it;
+ }
+ if ((empty == (PTE *)NULL) && !_pte->v)
+ {
+ h = _h;
+ empty = _pte;
+ }
+ }
+ }
+found_it:
+ _tlbie(va); /* Clear TLB */
+ slot->i = 1;
+ slot->m = 0;
+}
+
+/*
+ * Invalidate a hardware [hash] page table entry
+ * Note: this should never be called [currently] for kernel addresses.
+ */
+MMU_invalidate_page(struct mm_struct *mm, unsigned long va, pte *pg)
+{
+ int hash, page_index, segment, i, h, _h, api, vsid, perms;
+ PTE *_pte, *slot;
+ int flags = 0;
+ page_index = ((int)va & 0x0FFFF000) >> 12;
+ segment = (unsigned int)va >> 28;
+ api = page_index >> 10;
+ vsid = mm->context | segment;
+ slot = (PTE *)NULL;
+ for (_h = 0; _h < 2; _h++)
+ {
+ hash = page_index ^ vsid;
+ if (_h)
+ {
+ hash = ~hash; /* Secondary hash uses ones-complement */
+ }
+ hash &= 0x3FF | (Hash_mask << 10);
+ hash *= 8; /* Eight entries / hash bucket */
+ _pte = &Hash[hash];
+ for (i = 0; i < 8; i++, _pte++)
+ {
+ if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api)
+ { /* Found it! */
+ _tlbie(va); /* Clear TLB */
+ if (_pte->r) flags |= _PAGE_ACCESSED;
+ if (_pte->c) flags |= _PAGE_DIRTY;
+ _pte->v = 0;
+#ifdef SHOW_FAULTS
+printk("Pull VA: %08X, Flags: %x\n", va, flags);
+#endif
+ return (flags);
+ }
+ }
+ }
+ return (flags);
+}
+
+/*
* Invalidate the MMU [hardware] tables (for current task?)
*/
void
invalidate(void)
{
- int i, j, flags;
- unsigned long address;
- pgd_t *pgd;
- pte_t *_pte;
-#if 0
- _tlbia(); /* Flush TLB entries */
+ int i, j, flags;
+ unsigned long address;
+ pgd_t *pgd;
+ pte_t *_pte;
+ static long _invalidates;
+#ifdef SHOW_INVALIDATES
+printk("invalidate()\n");
+#endif
+ _invalidates++;
+#if 0 /* Unnecessary */
+ _tlbia(); /* Flush TLB entries */
+#endif
+ pgd = pgd_offset(current->mm, 0);
+ if (!pgd) return; /* No map? */
+ address = 0;
+ for (i = 0 ; (i < PTRS_PER_PGD) && (address < KERNELBASE); i++)
+ {
+ if (*(long *)pgd)
+ {
+ /* I know there are only two levels, but the macros don't */
+ _pte = pte_offset(pmd_offset(pgd,0),0);
+ if (_pte)
+ {
+ for (j = 0; j < PTRS_PER_PTE; j++)
+ {
+ if (pte_present(*_pte))
+ {
+ flags = MMU_hash_page(¤t->tss, address, 0);
+ ((pte *)_pte)->flags |= flags;
+ }
+ _pte++;
+ address += PAGE_SIZE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ pgd++;
+ }
+}
+
+/*
+ * Invalidate the MMU [hardware] tables (for current task?)
+ */
+void
+flush_cache_mm(struct mm_struct *mm)
+{
+ int i, j, flags;
+ unsigned long address;
+ pgd_t *pgd;
+ pte_t *_pte;
+ static long _invalidates;
+#ifdef SHOW_INVALIDATES
+printk("invalidate_mm(%x)\n", mm);
+#endif
+if (!mm) return;
+ _invalidates++;
+#if 0 /* Unnecessary */
+ _tlbia(); /* Flush TLB entries */
+#endif
+ pgd = pgd_offset(mm, 0);
+ if (!pgd) return; /* No map? */
+ address = 0;
+ for (i = 0 ; (i < PTRS_PER_PGD) && (address < KERNELBASE); i++)
+ {
+ if (*(long *)pgd)
+ {
+ /* I know there are only two levels, but the macros don't */
+ _pte = pte_offset(pmd_offset(pgd,0),0);
+ if (_pte)
+ {
+ for (j = 0; j < PTRS_PER_PTE; j++)
+ {
+ if (pte_present(*_pte))
+ {
+ flags = MMU_invalidate_page(mm, address, 0);
+ ((pte *)_pte)->flags |= flags;
+ }
+ _pte++;
+ address += PAGE_SIZE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ pgd++;
+ }
+}
+
+/*
+ * Invalidate the MMU [hardware] tables (for current task?)
+ */
+void
+flush_cache_page(struct vm_area_struct *vma, long va)
+{
+ int i, j, flags;
+ unsigned long address;
+ pgd_t *pgd;
+ pte_t *_pte;
+ static long _invalidates;
+ struct mm_struct *mm = vma->vm_mm;
+#ifdef SHOW_INVALIDATES
+printk("invalidate_page(%x[%x], %x)\n", vma, mm, va);
+#endif
+if (!mm) return; /* In case VMA lookup fails */
+ _invalidates++;
+#if 0 /* Unnecessary */
+ _tlbia(); /* Flush TLB entries */
+#endif
+/* Note: this could be MUCH better */
+ pgd = pgd_offset(mm, 0);
+ if (!pgd) return; /* No map? */
+ address = 0;
+ for (i = 0 ; (i < PTRS_PER_PGD) && (address < KERNELBASE); i++)
+ {
+ if (*(long *)pgd)
+ {
+ /* I know there are only two levels, but the macros don't */
+ _pte = pte_offset(pmd_offset(pgd,0),0);
+ if (_pte)
+ {
+ for (j = 0; j < PTRS_PER_PTE; j++)
+ {
+ if ((va == address) && pte_present(*_pte))
+ {
+ flags = MMU_invalidate_page(mm, address, 0);
+ ((pte *)_pte)->flags |= flags;
+ }
+ _pte++;
+ address += PAGE_SIZE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ pgd++;
+ }
+}
+
+/*
+ * Invalidate the MMU [hardware] tables (for current task?)
+ */
+void
+flush_cache_range(struct mm_struct *mm, unsigned long va_start, unsigned long va_end)
+{
+ int i, j, flags;
+ unsigned long address;
+ pgd_t *pgd;
+ pte_t *_pte;
+ static long _invalidates;
+#ifdef SHOW_INVALIDATES
+printk("invalidate_range(%x, %x, %x)\n", mm, va_start, va_end);
+#endif
+if (!mm) return;
+ _invalidates++;
+#if 0 /* Unnecessary */
+ _tlbia(); /* Flush TLB entries */
#endif
- pgd = pgd_offset(current->mm, 0);
- if (!pgd) return; /* No map? */
- address = 0;
- for (i = 0 ; (i < PTRS_PER_PGD) && (address < KERNELBASE); i++)
- {
- if (*(long *)pgd)
- {
- /* I know there are only two levels, but the macros don't */
- _pte = pte_offset(pmd_offset(pgd,0),0);
- if (_pte)
- {
- for (j = 0; j < PTRS_PER_PTE; j++)
- {
- if (pte_present(*_pte))
- {
- flags = MMU_hash_page(¤t->tss, address, 0);
- ((pte *)_pte)->flags |= flags;
- }
- _pte++;
- address += PAGE_SIZE;
- }
- } else
- {
- address += PAGE_SIZE*PTRS_PER_PTE;
- }
- } else
- {
- address += PAGE_SIZE*PTRS_PER_PTE;
- }
- pgd++;
- }
+/* Note: this could be MUCH better */
+ pgd = pgd_offset(mm, 0);
+ if (!pgd) return; /* No map? */
+ address = 0;
+ for (i = 0 ; (i < PTRS_PER_PGD) && (address < KERNELBASE); i++)
+ {
+ if (*(long *)pgd)
+ {
+ /* I know there are only two levels, but the macros don't */
+ _pte = pte_offset(pmd_offset(pgd,0),0);
+ if (_pte)
+ {
+ for (j = 0; j < PTRS_PER_PTE; j++)
+ {
+ if ((va_start <= address) && (va_end > address) && pte_present(*_pte))
+ {
+ flags = MMU_invalidate_page(mm, address, 0);
+ ((pte *)_pte)->flags |= flags;
+ }
+ _pte++;
+ address += PAGE_SIZE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ } else
+ {
+ address += PAGE_SIZE*PTRS_PER_PTE;
+ }
+ pgd++;
+ }
}
void
@@ -766,4 +985,57 @@
cache_is_copyback = ints[0];
}
+_verify_addr(long va)
+{
+ int hash, page_index, segment, i, h, _h, api, vsid, perms;
+ struct thread_struct *tss = ¤t->tss;
+ PTE *_pte, *empty, *slot;
+ PTE *slot0, *slot1;
+ page_index = ((int)va & 0x0FFFF000) >> 12;
+ segment = (unsigned int)va >> 28;
+ api = page_index >> 10;
+ vsid = ((SEGREG *)tss->segs)[segment].vsid;
+ empty = slot = (PTE *)NULL;
+ printk("Segment = %x/%x\n", *(long *)&tss->segs[segment], _get_SRx(segment));
+ for (_h = 0; _h < 2; _h++)
+ {
+ hash = page_index ^ vsid;
+ if (_h)
+ {
+ hash = ~hash; /* Secondary hash uses ones-complement */
+ }
+ hash &= 0x3FF | (Hash_mask << 10);
+ hash *= 8; /* Eight entries / hash bucket */
+ _pte = &Hash[hash];
+ dump_buf(_pte, 64);
+ for (i = 0; i < 8; i++, _pte++)
+ {
+ if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api)
+ { /* Found it! */
+ h = _h;
+ slot = _pte;
+ printk("Found at %x\n", slot);
+ goto found_it;
+ }
+ if ((empty == (PTE *)NULL) && !_pte->v)
+ {
+ h = _h;
+ empty = _pte;
+ }
+ }
+ }
+found_it:
+ cnpause();
+}
+
+flush_cache_all()
+{
+ printk("flush_cache_all()\n");
+ invalidate();
+}
+flush_tlb_all() {}
+flush_tlb_mm() {}
+flush_tlb_page() {}
+flush_tlb_range() {}
+flush_page_to_ram() {}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this