Re: why open("dev/console",O_RDWR,0) get stuck
From: ben bodley <hidden>
Date: 2000-06-29 03:50:25
Wentao Xu wrote:
ben, Thanks for your help. That error does not appear now, after doing what you told me. BTW, can you tell me what toolkit you are using with the ppc401, the one from Monta Vista? I have been haunted by the bad PTE error for 2 weeks. I dont know if I shall make some modification of the MMU code before running the 405 code on the redwood 3. Can you give me a hint? Thanks
my kernel is based on grant ericksons latest patch + some montavisa mods
+ my mods..
here is my slightly hacked 4xx_tlb.c if you find it of any help... i am
having some problems with the romeo bus at pres. hence hacking out the
_PAGE_GUARDED..
/*
*
* Copyright (c) 1999 Grant Erickson [off-list ref]
* copyright (c) 2000 m2 technology ltd [off-list ref]
*
* 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_tlb_flush_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);
}
void
PPC4xx_tlb_flush_page(int pid, unsigned long va)
{
unsigned long flags, opid, tag, i;
unsigned int found = 1;
save_flags(flags);
cli();
opid = mfspr(SPRN_PID);
/* set our new context as the one we want to flush */
mtspr(SPRN_PID, pid);
/* guess at a valid 4k page */
tag = (va & PAGE_MASK) | TLB_VALID | TLB_PAGESZ(PAGESZ_4K);
/* Attempt to match the 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 (found) {
/* modify the tag portion to indicate an invalid tlb
entry */
asm("tlbre %0,%1,0" : "=r" (tag) : "r" (i));
tag &= ~TLB_VALID;
asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i));
/* and now resync the tlb table */
asm("isync;sync");
}
/* restore old pid (context) */
mtspr(SPRN_PID, opid);
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();
PPC4xx_tlb_miss(regs, addr, write);
}
#if 0
printk("attempted data access at %08lx from %08lx\n", addr,
regs->nip);
#endif
}
/*
* ()
*
* Description:
* This routine...
*
* Input(s):
*
*
* Output(s):
*
*
* Returns:
*
*
*/
void
PPC4xx_itlb_miss(struct pt_regs *regs)
{
unsigned long addr = regs->nip;
#if 0
printk("attempted instruction access at %08lx\n", addr);
#endif
if (PPC4xx_tlb_miss(regs, addr, 0) < 0) {
sti();
do_page_fault(regs, addr, 0);
cli();
PPC4xx_tlb_miss(regs, addr, 0);
}
}
/*
* ()
*
* 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++);
asm("isync; sync");
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);
if (pte_val(*pte) & _PAGE_RW)
data |= TLB_WR;
if (pte_val(*pte) & _PAGE_NO_CACHE)
data |= TLB_I | TLB_G;
else
data |= TLB_EX;
/* if (pte_val(*pte) & _PAGE_GUARDED)
data |= TLB_G; */
if (pte_val(*pte) & _PAGE_USER)
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);
}
cheers,
ben
--
/\\------------------------------------------------------------------
:::::::::::..ben.b..m2technologyltd.nz..64.9.4448307.130..:::::::::::
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/