Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Mar 2015 21:18:27 -0700
From:      Mark Millard <markmi@dsl-only.net>
To:        FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>, Nathan Whitehorn <nwhitehorn@freebsd.org>
Subject:   Re: 10.1-STABLE kern.vty=vt crashes PowerMac G5 extremely early in boot for 2560x1440 display...
Message-ID:  <EEF037EC-CFF2-4D4D-BB1B-0A0750E09C1F@dsl-only.net>
In-Reply-To: <8B7B5167-0C94-4BA3-9515-B4CB8A817BDB@dsl-only.net>
References:  <8B7B5167-0C94-4BA3-9515-B4CB8A817BDB@dsl-only.net>

next in thread | previous in thread | raw e-mail | index | archive | help
Nathan W. write:

> Could you please try -CURRENT? vt itself at least works fine there, =
but=20
> I'm not sure anyone has tested it with such a large display on any =
platform.
> -Nathan

I'll try. But it may take a bit to get a 11.0-CURRENT boot context =
established: I've got the G5's doing other things at the moment.

Looking at the -r279514 11.0-CURRENT code (see below) there seems a =
VBF_STATIC flag for indicating a statically sized initial buffer. But =
the code does not seem to use the static sized limits involved: instead =
the code always seems to use the final sizes even before vtbuf_grow =
toggles the flag's status.

In other words: I expect that this goes goes out of bounds and trashes =
memory it does not own while the static buffer is in use early on.


#ifdef SC_HISTORY_SIZE
#define VBF_DEFAULT_HISTORY_SIZE        SC_HISTORY_SIZE
#else
#define VBF_DEFAULT_HISTORY_SIZE        500
#endif
...
#ifndef VT_FB_DEFAULT_WIDTH
#define VT_FB_DEFAULT_WIDTH     2048
#endif
#ifndef VT_FB_DEFAULT_HEIGHT
#define VT_FB_DEFAULT_HEIGHT    1200
#endif
...

#define _VTDEFH MAX(100, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT))
#define _VTDEFW MAX(200, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH))
...
static term_char_t vt_constextbuf[(_VTDEFW) * =
(VBF_DEFAULT_HISTORY_SIZE)];
static term_char_t *vt_constextbufrows[VBF_DEFAULT_HISTORY_SIZE];
static struct vt_window vt_conswindow =3D {
        .vw_number =3D VT_CONSWINDOW,
        .vw_flags =3D VWF_CONSOLE,
        .vw_buf =3D {
                .vb_buffer =3D &vt_constextbuf[0],
                .vb_rows =3D &vt_constextbufrows[0],
                .vb_history_size =3D VBF_DEFAULT_HISTORY_SIZE,
                .vb_curroffset =3D 0,
                .vb_roffset =3D 0,
                .vb_flags =3D VBF_STATIC,
                .vb_mark_start =3D {.tp_row =3D 0, .tp_col =3D 0,},
                .vb_mark_end =3D {.tp_row =3D 0, .tp_col =3D 0,},
                .vb_scr_size =3D {
                        .tp_row =3D _VTDEFH,
                        .tp_col =3D _VTDEFW,
                },
        },
        .vw_device =3D &vt_consdev,
        .vw_terminal =3D &vt_consterm,
        .vw_kbdmode =3D K_XLATE,
        .vw_grabbed =3D 0,
};

...

void
vtbuf_init_early(struct vt_buf *vb)
{
        term_rect_t rect;

        vb->vb_flags |=3D VBF_CURSOR;
        vb->vb_roffset =3D 0;
        vb->vb_curroffset =3D 0;
        vb->vb_mark_start.tp_row =3D 0;
        vb->vb_mark_start.tp_col =3D 0;
        vb->vb_mark_end.tp_row =3D 0;
        vb->vb_mark_end.tp_col =3D 0;

        vtbuf_init_rows(vb);
        rect.tr_begin.tp_row =3D rect.tr_begin.tp_col =3D 0;
        rect.tr_end.tp_col =3D vb->vb_scr_size.tp_col;
        rect.tr_end.tp_row =3D vb->vb_history_size;
        vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR));
        vtbuf_make_undirty(vb);
        if ((vb->vb_flags & VBF_MTX_INIT) =3D=3D 0) {
                mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN);
                vb->vb_flags |=3D VBF_MTX_INIT;
        }
}
...
static void
vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c)
{
        unsigned int pr, pc;
        term_char_t *row;

        for (pr =3D r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) {
                row =3D vb->vb_rows[(vb->vb_curroffset + pr) %
                    VTBUF_MAX_HEIGHT(vb)];
                for (pc =3D r->tr_begin.tp_col; pc < r->tr_end.tp_col; =
pc++) {
                        row[pc] =3D c;
                }
        }
}
...
static void
vtbuf_init_rows(struct vt_buf *vb)
{
        int r;
       =20
        vb->vb_history_size =3D MAX(vb->vb_history_size, =
vb->vb_scr_size.tp_row);
           =20
        for (r =3D 0; r < vb->vb_history_size; r++)
                vb->vb_rows[r] =3D &vb->vb_buffer[r * =
vb->vb_scr_size.tp_col];
}
...
void
vtbuf_init(struct vt_buf *vb, const term_pos_t *p)
{
        int sz;

        vb->vb_scr_size =3D *p;
        vb->vb_history_size =3D VBF_DEFAULT_HISTORY_SIZE;

        if ((vb->vb_flags & VBF_STATIC) =3D=3D 0) {
                sz =3D vb->vb_history_size * p->tp_col * =
sizeof(term_char_t);
                vb->vb_buffer =3D malloc(sz, M_VTBUF, M_WAITOK | =
M_ZERO);

                sz =3D vb->vb_history_size * sizeof(term_char_t *);
                vb->vb_rows =3D malloc(sz, M_VTBUF, M_WAITOK | M_ZERO);
        }

        vtbuf_init_early(vb);
}
...
void
vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, unsigned int =
history_size)
{
...
        vb->vb_history_size =3D history_size;
        vb->vb_buffer =3D new;
        vb->vb_rows =3D rows;
        vb->vb_flags &=3D ~VBF_STATIC;
        vb->vb_scr_size =3D *p;
        vtbuf_init_rows(vb);
...



=3D=3D=3D
Mark Millard
markmi@dsl-only.net

On 2015-Mar-8, at 03:22 AM, Mark Millard <markmi@dsl-only.net> wrote:

Basic context:

$ freebsd-version -ku; uname -a
10.1-STABLE
10.1-STABLE
FreeBSD FBSDG5S0 10.1-STABLE FreeBSD 10.1-STABLE #0 r279507M: Fri Mar  6 =
23:08:59 PST 2015     root@FBSDG5S0:/usr/obj/usr/src/sys/GENERIC64vtsc  =
powerpc


The crash details (X11 is not part of the context, just console use):

I tried using a 2560x1440 display with a PowerMac G5 but forgot to =
switch from kern.vty=3Dvt to kern.vty=3Dsc in /boot/loader.conf first.

But the result was new since the last time I'd done such a thing (long =
ago)...

It crashed so early that it returned to Apple's OpenFirmware.

That allowed me to use .registers in OpenFirmware to find where it had =
crashed at.

It turned out that the Interrupt Vector was 0x700 and SRR0 was 0x380. =
(Openfirmare does not put an exception handler at 0x380 (leaving zeros) =
so a 0x380 exception handler's attempted use leads to a double fault =
when OpenFirmware's handlers are all that are in place, the 2nd of the =
pair going to the 0x700 exception handler.)

Luckily LR is preserved in this sequence and it ended up pointing to:

vtbuf_init_early+0x78 (0x40787c was the address for the build)

and that was the instruction after a bl to .vtbuf_fill.

This was fully repeatable.


As conformation of the size dependency: Switching to a smaller display =
booted fine (again fully repeatable).


I'll note that kern.vty=3Dsc handles the 2560x1440 display fine for that =
same PowerMac G5. sc uses most but not all of the width and it uses all =
of the height.


Other context details:

$ cd /usr/src
$ svnlite info
Path: .
Working Copy Root Path: /usr/src
URL: https://svn0.us-west.freebsd.org/base/stable/10
Relative URL: ^/stable/10
Repository Root: https://svn0.us-west.freebsd.org/base
Repository UUID: ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
Revision: 279507
Node Kind: directory
Schedule: normal
Last Changed Author: ngie
Last Changed Rev: 279507
Last Changed Date: 2015-03-01 14:12:24 -0800 (Sun, 01 Mar 2015)

$ svnlite st --no-ignore
?       .snap
?       restoresymtable
M       sys/ddb/db_main.c
M       sys/ddb/db_script.c
I       sys/powerpc/conf/GENERIC64vtsc
I       sys/powerpc/conf/GENERICvtsc
M       sys/powerpc/ofw/ofw_machdep.c
M       sys/powerpc/ofw/ofwcall64.S
M       sys/powerpc/powerpc/dump_machdep.c

sys/powerpc/ofw/ofw_machdep.c has a PowerMac G5 specific change to avoid =
intermittent boot problems.

sys/ddb/... and sys/powerpc/ofw/ofwcall64.S are just to help me get =
evidence if I do end up with another early-boot failure. DDB and GDB are =
listed in sys/powerpc/conf/GENERIC64vtsc for the same reason.

sys/powerpc/powerpc/dump_machdep.c is from me forcing the DMA transfer =
size for dumps to be small enough not to be rejected as too large of a =
DMA request size.

sys/powerpc/conf/GENERIC64vtsc turns off ps3 in order to turn on both vt =
and sc. It includes the standard GENERIC64.

# more /etc/make.conf
#CPP=3Dclang-cpp
#CC=3Dclang
#CXX=3Dclang++
WRKDIRPREFIX=3D/usr/obj/portswork
WITH_DEBUG=3D
MALLOC_PRODUCTION=3D

# more /etc/src.conf
#CPP=3Dclang-cpp
#CC=3Dclang
#CXX=3Dclang++
#CFLAGS+=3D-DELF_VERBOSE
#WITH_DEBUG_FILES=3D
#WITHOUT_CLANG

=3D=3D=3D
Mark Millard
markmi at dsl-only.net





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?EEF037EC-CFF2-4D4D-BB1B-0A0750E09C1F>