patch-2.4.22 linux-2.4.22/arch/ppc/mm/4xx_tlb.c
Next file: linux-2.4.22/arch/ppc/mm/4xx_tlb.h
Previous file: linux-2.4.22/arch/ppc/mm/4xx_mmu.c
Back to the patch index
Back to the overall index
- Lines: 359
- Date:
1969-12-31 16:00:00.000000000 -0800
- Orig file:
linux-2.4.21/arch/ppc/mm/4xx_tlb.c
- Orig date:
2003-06-13 07:51:31.000000000 -0700
diff -urN linux-2.4.21/arch/ppc/mm/4xx_tlb.c linux-2.4.22/arch/ppc/mm/4xx_tlb.c
@@ -1,358 +0,0 @@
-/*
- *
- * Copyright (c) 1998-1999 TiVo, Inc.
- * Original implementation.
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- * Minor rework.
- *
- * Module name: 4xx_tlb.c
- *
- * Description:
- * Routines for manipulating the TLB on PowerPC 400-class processors.
- *
- */
-
-#include <linux/mm.h>
-
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-
-
-/* Preprocessor Defines */
-
-#if !defined(TRUE) || TRUE != 1
-#define TRUE 1
-#endif
-
-#if !defined(FALSE) || FALSE != 0
-#define FALSE 0
-#endif
-
-
-/* Global Variables */
-
-static int pinned = 0;
-
-
-/* Function Prototypes */
-
-static int PPC4xx_tlb_miss(struct pt_regs *, unsigned long, int);
-
-extern void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
-
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-static inline void
-PPC4xx_tlb_write(unsigned long tag, unsigned long data, unsigned int index)
-{
- asm("tlbwe %0,%1,1" : : "r" (data), "r" (index));
- asm("tlbwe %0,%1,0" : : "r" (tag), "r" (index));
-}
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-void
-PPC4xx_flush_tlb_all(void)
-{
- int i;
- unsigned long flags, pid;
-
- save_flags(flags);
- cli();
-
- pid = mfspr(SPRN_PID);
- mtspr(SPRN_PID, 0);
-
- for (i = pinned; i < PPC4XX_TLB_SIZE; i++) {
- PPC4xx_tlb_write(0, 0, i);
- }
- asm("sync;isync");
-
- mtspr(SPRN_PID, pid);
- restore_flags(flags);
-}
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-void
-PPC4xx_dtlb_miss(struct pt_regs *regs)
-{
- unsigned long addr = mfspr(SPRN_DEAR);
- int write = mfspr(SPRN_ESR) & ESR_DST;
-
- if (PPC4xx_tlb_miss(regs, addr, write) < 0) {
- sti();
- do_page_fault(regs, addr, write);
- cli();
- }
-
-}
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-void
-PPC4xx_itlb_miss(struct pt_regs *regs)
-{
- unsigned long addr = regs->nip;
-
- if (PPC4xx_tlb_miss(regs, addr, 0) < 0) {
- sti();
- do_page_fault(regs, addr, 0);
- cli();
- }
-}
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-void
-PPC4xx_tlb_pin(unsigned long va, unsigned long pa, int pagesz, int cache)
-{
- unsigned long tag, data;
- unsigned long opid;
-
- if (pinned >= PPC4XX_TLB_SIZE)
- return;
-
- opid = mfspr(SPRN_PID);
- mtspr(SPRN_PID, 0);
-
- data = (pa & TLB_RPN_MASK) | TLB_WR;
-
- if (cache)
- data |= (TLB_EX);
- else
- data |= (TLB_G | TLB_I);
-
- tag = (va & TLB_EPN_MASK) | TLB_VALID | pagesz;
-
- PPC4xx_tlb_write(tag, data, pinned++);
-
- mtspr(SPRN_PID, opid);
- return;
-}
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-void
-PPC4xx_tlb_unpin(unsigned long va, unsigned long pa, int size)
-{
- /* XXX - To be implemented. */
-}
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-static inline void
-PPC4xx_tlb_update(unsigned long addr, pte_t *pte)
-{
- unsigned long data, tag, rand;
- int i, found = 1;
-
- /* Construct the hardware TLB entry from the Linux-style PTE */
-
- tag = tag = (addr & PAGE_MASK) | TLB_VALID | TLB_PAGESZ(PAGESZ_4K);
- data = data = (pte_val(*pte) & PAGE_MASK) | TLB_EX | TLB_WR;
-
-#if 0
- if (pte_val(*pte) & _PAGE_HWWRITE)
- data |= TLB_WR;
-#endif
-
- if (pte_val(*pte) & _PAGE_NO_CACHE)
- data |= TLB_I;
-
- if (pte_val(*pte) & _PAGE_GUARDED)
- data |= TLB_G;
-
- if (addr < KERNELBASE)
- data |= TLB_ZSEL(1);
-
- /* Attempt to match the new tag to an existing entry in the TLB. */
-
- asm("tlbsx. %0,0,%2;"
- "beq 1f;"
- "li %1,0;1:" : "=r" (i), "=r" (found) : "r" (tag));
-
- /*
- * If we found a match for the tag, reuse the entry index and update
- * the tag and data portions. Otherwise, we did not find a match. Use
- * the lower 5 bits of the lower time base register as a pseudo-random
- * index into the TLB and replace the entry at that index.
- */
-
- if (found) {
- PPC4xx_tlb_write(tag, data, i);
- } else {
- rand = mfspr(SPRN_TBLO) & (PPC4XX_TLB_SIZE - 1);
- rand += pinned;
- if (rand >= PPC4XX_TLB_SIZE)
- rand -= pinned;
-
- PPC4xx_tlb_write(tag, data, rand);
- asm("isync;sync");
- }
-}
-
-/*
- * ()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- *
- *
- * Output(s):
- *
- *
- * Returns:
- *
- *
- */
-static int
-PPC4xx_tlb_miss(struct pt_regs *regs, unsigned long addr, int write)
-{
- unsigned long spid, ospid;
- struct mm_struct *mm;
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
-
- if (!user_mode(regs) && (addr >= KERNELBASE)) {
- mm = &init_mm;
- spid = 0;
- } else {
- mm = current->mm;
- spid = mfspr(SPRN_PID);
- }
-
- pgd = pgd_offset(mm, addr);
- if (pgd_none(*pgd))
- goto bad;
-
- pmd = pmd_offset(pgd, addr);
- if (pmd_none(*pmd))
- goto bad;
-
- pte = pte_offset(pmd, addr);
- if (pte_none(*pte) || !pte_present(*pte))
- goto bad;
-
- if (write) {
- if (!pte_write(*pte))
- goto bad;
-
- set_pte(pte, pte_mkdirty(*pte));
- }
- set_pte(pte, pte_mkyoung(*pte));
-
- ospid = mfspr(SPRN_PID);
- mtspr(SPRN_PID, spid);
- PPC4xx_tlb_update(addr, pte);
- mtspr(SPRN_PID, ospid);
-
- return (0);
-bad:
- return (-1);
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)