linux-mips-fnet
[Top] [All Lists]

Re: Platform-independent hack in ptrace.c

To: Ralf Baechle <ralf@uni-koblenz.de>
Subject: Re: Platform-independent hack in ptrace.c
From: "Vladimir A. Roganov" <roganov@niisi.msk.ru>
Date: Fri, 28 May 1999 13:19:45 +0400
Cc: linux@engr.sgi.com, linux-mips@fnet.fr, linux-mips@vger.rutgers.edu
Organization: NIISI
References: <374D37E6.59A6A9F3@niisi.msk.ru> <19990527212654.A4058@uni-koblenz.de>
Sender: vladimir@niisi.msk.ru
Ralf Baechle wrote:
> 
> On Thu, May 27, 1999 at 04:17:42PM +0400, Vladimir A. Roganov wrote:
> 
> > Does anybody know which kind of protection is encoded in ptrace.c:69:
> > (function get_long)
> >
> >       /* This is a hack for non-kernel-mapped video buffers and similar */
> >       if (MAP_NR(page) >= MAP_NR(high_memory))
> >               return 0;
> >
> > By this reason gdb shows all user-mapped io as zeros.
> >
> > Same time, put_long enable to write to such memory !
> > So when You enter something like 'set *p = 0xff' gdb'ing program
> > which has p->video_memory, You will see appearing pixels, but 'p *p'
> > prints only zeros.
> >
> > Elimination of this check does not destroy something: gdb shows right
> > values.
> >
> > It looks clean that above problem is not very important, but just
> > imagine programmer debugging some application for Linux used to control
> > some device on MIPS embedded computer, which mmap'ed to device registers
> > and don't understand why they are all clean :-)
> 
> Basically I think you're right.  However a correct patch is slightly more
> complex and will acount for the fact that KSEG0 through which we route
> the access is only 512mb large.  Therefore we might have to install a
> temporary mapping and access memory through it, if outside of the 512mb.

YES!  

We are using such technique in our Baget/MIPS code.
We implemented try_read function which carefully read 1,2,4-long value from bus
which check for KSEGs, tunes TLB and catch SIGBUS.
Code is located in 'arch/mips/baget/bagetIRQ.S':


#define DBE_HANDLER       0x1C

NESTED(try_read, PT_SIZE, sp)
        mfc0    t3, CP0_STATUS          # save flags and
        CLI                             #  disable interrupts

        li      t0, KSEG2
        sltu    t1, t0, a0              # Is it KSEG2 address ?
        beqz    t1, mapped              # No - already mapped !

        move    t0, a0
        ori     t0, 0xfff
        xori    t0, 0xfff               # round address to page

        ori     t1, t0, 0xf00           # prepare EntryLo (N,V,D,G)

        mfc0    t2,   CP0_ENTRYHI       # save ASID value
        mtc0    zero, CP0_INDEX
        mtc0    t0,   CP0_ENTRYHI       # Load MMU values ...
        mtc0    t1,   CP0_ENTRYLO0
        nop                             # let it understand
        nop
        tlbwi                           # ... and write ones
        nop
        nop
        mtc0    t2,  CP0_ENTRYHI

mapped:
        la      t0, exception_handlers
        lw      t1, DBE_HANDLER(t0)     # save real handler
        la      t2, dbe_handler
        sw      t2, DBE_HANDLER(t0)     # set temporary local handler
        li      v0, -1                  # default (failure) value

        li      t2, 1
        beq     t2, a1, 1f
        li      t2, 2
        beq     t2, a1, 2f
        li      t2, 4
        beq     t2, a1, 4f
        b       out

1:      lbu     v0, (a0)                # byte
        b       out

2:      lhu     v0, (a0)                # short
        b       out

4:      lw      v0, (a0)                # word

out:
        sw      t1, DBE_HANDLER(t0)     # restore real handler
        mtc0    t3, CP0_STATUS          # restore CPU flags
        jr      ra

dbe_handler:
        li      v0, -1                  # mark our failure
        .set    push
        .set    noreorder
        b       out                     # "no problems !"
        rfe                             #   return from trap
        .set    pop
END(try_read)

We implemented it by very interesting reason: old Baget uses special
VIC register which exists on bus only (!!!) when interrupt is active.
But interrupt can be deactivated by external reason. In such case
IRQ handler catch SIGBUS, what crashes current process.

It was overwritten twice, and it looks debugged hardly :-)
May be it can help here.

> The other bug is that memory accesses via ptrace for virtual addresses
> which are uncached would be executed cached, trouble ahead.

YES, we obtained such effect.
To avoid it we just moved to physical address space (high bits are ignored),
but it is not good in general.

> Further complexity is added by handling write buffers for the R3000 and
> virtual coherency for R4000.
> 
>   Ralf

Yes, it should be tried to be fixed once for every arch.

Best wishes,
Vladimir.

<Prev in Thread] Current Thread [Next in Thread>