diff mbox series

Improvements for the PS3

Message ID 20180714164906.GQ23412@localhost.localdomain (mailing list archive)
State Not Applicable
Headers show
Series Improvements for the PS3 | expand

Commit Message

Fredrik Noring July 14, 2018, 4:49 p.m. UTC
Hi,

I just checked out the latest "ps3-queue" branch

https://git.kernel.org/pub/scm/linux/kernel/git/geoff/ps3-linux.git/log/?h=ps3-queue

to upgrade my OtherOS boot kernel. I essentially started out with

$ make ARCH=powerpc ps3_defconfig
$ make ARCH=powerpc dtbImage.ps3

to obtain an image to install. The first problem was its size, which is
around 20 MB by default and therefore uninstallable. It seems the main
sections causing size problems in the ELF are (sizes in leftmost column):

	0x400000 OBJECT LOCAL  DEFAULT 37 stack_trace
	0x29feb0 OBJECT LOCAL  DEFAULT 37 lock_classes
	0x200000 OBJECT GLOBAL DEFAULT 37 lock_chains
	0x200000 OBJECT LOCAL  DEFAULT 37 list_entries
	 0xa0000 OBJECT LOCAL  DEFAULT 37 chain_hlocks
	 0x40000 OBJECT LOCAL  DEFAULT 37 chainhash_table
	 0x20000 OBJECT LOCAL  DEFAULT 37 __log_buf

I modified arch/powerpc/boot/wrapper to make the size error more apparent:


et voilà, the screen came alive and the kernel panic was revealed! It seems
the kernel panics so fast that the PS3 frame buffer is unprepared. This is,
of course, very unfortunate because trying to debug the boot process without
a screen or any other means of obtaining console text is quite difficult.

[ In this case the panic was caused by a missing CONFIG_DEVTMPFS=y, where
"Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100",
is helpful to actually see in text. ]

I suppose the problem is that it relies on interrupts for ps3fb_sync_image
to regularly copy the image, hence without them the screen isn't updated to
show kernel panics, etc. Perhaps one way to fix that is to implement the
struct fb_tile_ops API, so that the console is synchronously updated? Would
that be acceptable?

Fredrik

Comments

Geoff Levand July 18, 2018, 10:40 p.m. UTC | #1
Hi Fredrik,

On 07/14/2018 09:49 AM, Fredrik Noring wrote:
> so I added a sleep with
> 
> +	msleep(10000);
> +
>  	return 0;
> 
> et voilà, the screen came alive and the kernel panic was revealed! It seems
> the kernel panics so fast that the PS3 frame buffer is unprepared. This is,
> of course, very unfortunate because trying to debug the boot process without
> a screen or any other means of obtaining console text is quite difficult.

We could add a fixed delay there, but I'd like to avoid waiting that
long on every boot.  Why don't you add a kernel module_param named
something like ps3fb_delay that takes a value in milliseconds and a
default of zero.  See:

  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/video/fbdev/ps3fb.c?h=v4.17#n260

> I suppose the problem is that it relies on interrupts for ps3fb_sync_image
> to regularly copy the image, hence without them the screen isn't updated to
> show kernel panics, etc. Perhaps one way to fix that is to implement the
> struct fb_tile_ops API, so that the console is synchronously updated? Would
> that be acceptable?

I'm not sure if that would work or not.   Maybe Geert is more familiar with it.

-Geoff
Geert Uytterhoeven July 19, 2018, 7:45 a.m. UTC | #2
Hi Geoff, Frederik,

On Thu, Jul 19, 2018 at 12:40 AM Geoff Levand <geoff@infradead.org> wrote:
> On 07/14/2018 09:49 AM, Fredrik Noring wrote:
> > so I added a sleep with
> >
> > +     msleep(10000);

I can't see where you added the sleep, but 10s seems excessive.
If the real reason is the need to wait for an interrupt for ps3fb_sync_image(),
then waiting for 40 ms should be sufficient? Or am I missing something?

> > +
> >       return 0;
> >
> > et voilà, the screen came alive and the kernel panic was revealed! It seems
> > the kernel panics so fast that the PS3 frame buffer is unprepared. This is,
> > of course, very unfortunate because trying to debug the boot process without
> > a screen or any other means of obtaining console text is quite difficult.
>
> We could add a fixed delay there, but I'd like to avoid waiting that
> long on every boot.  Why don't you add a kernel module_param named
> something like ps3fb_delay that takes a value in milliseconds and a
> default of zero.  See:
>
>   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/video/fbdev/ps3fb.c?h=v4.17#n260
>
> > I suppose the problem is that it relies on interrupts for ps3fb_sync_image
> > to regularly copy the image, hence without them the screen isn't updated to
> > show kernel panics, etc. Perhaps one way to fix that is to implement the
> > struct fb_tile_ops API, so that the console is synchronously updated? Would
> > that be acceptable?
>
> I'm not sure if that would work or not.   Maybe Geert is more familiar with it.

That sounds like a complex solution, slowing down the console a lot.

What about letting ps3fb register a panic notifier to sync the screen, like
hyperv_fb does?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Geoff Levand July 19, 2018, 3:15 p.m. UTC | #3
Hi Geert, Fredrik,

On 07/19/2018 12:45 AM, Geert Uytterhoeven wrote:
>> On 07/14/2018 09:49 AM, Fredrik Noring wrote:
>>>
>>> et voilà, the screen came alive and the kernel panic was revealed! It seems
>>> the kernel panics so fast that the PS3 frame buffer is unprepared. This is,
>>> of course, very unfortunate because trying to debug the boot process without
>>> a screen or any other means of obtaining console text is quite difficult.
>>
> What about letting ps3fb register a panic notifier to sync the screen, like
> hyperv_fb does?

Seems like the thing to do.  Fredrik, do you want to try it?  Otherwise, I'll
work on it when I have some time.

-Geoff
Fredrik Noring July 19, 2018, 8:14 p.m. UTC | #4
Hi Geert, Geoff,

> > > so I added a sleep with
> > >
> > > +     msleep(10000);
> 
> I can't see where you added the sleep, but 10s seems excessive.
> If the real reason is the need to wait for an interrupt for ps3fb_sync_image(),
> then waiting for 40 ms should be sufficient? Or am I missing something?

It's at the end of ps3fb_probe, as shown in the original post:

https://lists.ozlabs.org/pipermail/linuxppc-dev/2018-July/175771.html

I thought 100 ms or so would work, but evidently it didn't. In fact, 1 s
for even 5 s didn't seem to work either. In any case, I would like to
develop a solution that does not need to sleep at all, so that will be my
first approach for a proper implementation.

> > > I suppose the problem is that it relies on interrupts for ps3fb_sync_image
> > > to regularly copy the image, hence without them the screen isn't updated to
> > > show kernel panics, etc. Perhaps one way to fix that is to implement the
> > > struct fb_tile_ops API, so that the console is synchronously updated? Would
> > > that be acceptable?
> >
> > I'm not sure if that would work or not.   Maybe Geert is more familiar with it.
> 
> That sounds like a complex solution, slowing down the console a lot.

Why would that be slow? I have implemented a similar technique for the
PlayStation 2 frame buffer, and (without any measurements at hand now) it
appears to be about as fast as is possible, and reasonably easy too. :)

It works like this:

The PS2 frame buffer can operate in two distinct modes: virtual mode or
console mode. Virtual mode is very similar to the PS3 in that the whole
visible kernel memory frame buffer is copied to the Graphics Synthesizer
(GS) via DMA regularly at vertical blank intervals.

Console mode is different. No kernel memory is allocated for the frame
buffer at all (which is a significant improvement in itself given that the
PS2 is limited to 32 MiB of main memory) and mmap is disabled. Some struct
fb_ops such as fb_fillrect and fb_copyarea are directly accelerated by GS
hardware. The GS has two CRT merge circuits made for picture-in-picture that
are used to accelerate YWRAP in hardware, which is particularly effective
for console text scrolling.

Additionally, the tiled API is implemented, and it turned out to be a rather
good fit. The GS has 4 MiB of local frame buffer video memory (not directly
accessible by the kernel). The maximum practical resolution 1920x1080p at 16
bits per pixel is 4147200 bytes, which leaves 47104 bytes for a tiled font
which at 8x8 pixels and a minimum 4 bits indexed texture palette is at most
1464 characters. The indexed palette makes it easy to switch colors. struct
fb_tile_ops such as fb_tileblit are accelerated by GS texture sprites which
are fast (GS local copy) for the kernel via simple DMA (GIF) GS commands.

Console text is always synchronous and therefore works properly in interrupt
contexts and with kernel panics, etc. which is essential for debuggability.
A buffered version could be faster, possibly, but I think that might as well
be implemented by a user space console driver using a /dev/gs interface that
can do zero-copy GS commands. The PS2 frame buffer implementation is nearly
complete:

https://github.com/frno7/linux/blob/ps2-v4.17-n3/drivers/video/fbdev/ps2fb.c

Some adjustments and feature reductions seem to be needed for a PS3 version
of anything similar. The simplest implementation is probably to just mirror
characters as they are printed synchronously. I don't know the overhead of
the hypervisor calls for copying graphics though, but the typical areas are
quite small. Perhaps one could avoid allocating the kernel frame buffer as
well when it's not needed. I have to investigate these things to be sure.

> What about letting ps3fb register a panic notifier to sync the screen, like
> hyperv_fb does?

That would not work with kernel freezes unfortunately. Debugging those with
nondeterministicly invisible kernel prints would be painful, I believe.

Fredrik
Geert Uytterhoeven July 20, 2018, 7:36 a.m. UTC | #5
Hi Fredrik,

On Thu, Jul 19, 2018 at 10:14 PM Fredrik Noring <noring@nocrew.org> wrote:
> > > > so I added a sleep with
> > > >
> > > > +     msleep(10000);
> >
> > I can't see where you added the sleep, but 10s seems excessive.
> > If the real reason is the need to wait for an interrupt for ps3fb_sync_image(),
> > then waiting for 40 ms should be sufficient? Or am I missing something?
>
> It's at the end of ps3fb_probe, as shown in the original post:
>
> https://lists.ozlabs.org/pipermail/linuxppc-dev/2018-July/175771.html

Thanks, I had found that one in the mean time...

> I thought 100 ms or so would work, but evidently it didn't. In fact, 1 s
> for even 5 s didn't seem to work either. In any case, I would like to
> develop a solution that does not need to sleep at all, so that will be my
> first approach for a proper implementation.

Hmm...

> > > I suppose the problem is that it relies on interrupts for ps3fb_sync_image
> > > > to regularly copy the image, hence without them the screen isn't updated to
> > > > show kernel panics, etc. Perhaps one way to fix that is to implement the
> > > > struct fb_tile_ops API, so that the console is synchronously updated? Would
> > > > that be acceptable?
> > >
> > > I'm not sure if that would work or not.   Maybe Geert is more familiar with it.
> >
> > That sounds like a complex solution, slowing down the console a lot.
>
> Why would that be slow? I have implemented a similar technique for the
> PlayStation 2 frame buffer, and (without any measurements at hand now) it
> appears to be about as fast as is possible, and reasonably easy too. :)

[...]

OK, I retract my statement ;-)

> > What about letting ps3fb register a panic notifier to sync the screen, like
> > hyperv_fb does?
>
> That would not work with kernel freezes unfortunately. Debugging those with
> nondeterministicly invisible kernel prints would be painful, I believe.

Unfortunately AFAIK the PS3 doesn't have any other "synchronous" output we
can use for debugging (like flashing the power LED).

Gr{oetje,eeting}s,

                        Geert
Fredrik Noring July 20, 2018, 8:46 a.m. UTC | #6
Hi Geert,

> > That would not work with kernel freezes unfortunately. Debugging those with
> > nondeterministicly invisible kernel prints would be painful, I believe.
> 
> Unfortunately AFAIK the PS3 doesn't have any other "synchronous" output we
> can use for debugging (like flashing the power LED).

Well, one can use lv1_panic to bisect the PowerPC boot process. It either
freezes, in which case the call to lv1_panic isn't reached, or it reboots.
This method yields 1 bit of information for every reflash and reboot, with
a procedure taking about 5 minutes per turn, so 12 bits/hour sustained. ;)

The prime advantage is that lv1_panic works everywhere, including the
earliest boot stages.

I've since learned about the PS3GELIC_UDBG option to broadcast UDP via the
Ethernet port, but I don't know how well it works or its limitations.

One useful option for debugging is to setup a very early graphical console,
more or less from head.S, before any kernel functions are invoked. I have a
simple proof of concept implemented for the PS2 here:

https://github.com/frno7/linux/blob/ps2-v4.17-n3/arch/mips/boot/compressed/dbg.c

This could be done for the PS3 as well. The OtherOS demo

http://mc.pp.se/ps3/oodemo.xhtml

by Marcus Comstedt in 2007 contains the essentials with MMU and hypervisor
initialisation for graphics. I discovered that a small patch is required to
make his demo work with modern GCC:

--- a/source/script.lds
+++ b/source/script.lds
@@ -50,6 +50,7 @@ SECTIONS
  .opd : {
       *(.opd)
       }
+ . = ALIGN(256);
  .got : {
       __toc_start = .;
       *(.got)

Fredrik
diff mbox series

Patch

--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -550,5 +550,10 @@  ps3)
     bld="otheros.bld"
     [ $size -le 16777216 ] || bld="otheros-too-big.bld"
     gzip -n --force -9 --stdout "$ofile.bin" > "$odir/$bld"
+    if [ $size -gt 16777216 ]
+    then
+	    echo "ERROR: Image size $size bytes is too large for 16 MiB limit" >&2
+	    exit 1
+    fi
     ;;
 esac

I then proceeded with disabling STACKTRACE_SUPPORT and LOCKDEP_SUPPORT,
which reduced the size to about 8 MB, well below the 16 MiB limit. Perhaps
disabling these entirely is a bit heavy-handed? Is there a smarter way?

Trying to start the kernel results in a completely black screen. Nothing
happens. To have a chance of seeing anything I had configured:

CONFIG_FB_PS3=y
CONFIG_FB_PS3_DEFAULT_SIZE_M=9
CONFIG_CMDLINE="video=ps3fb:mode:10"

I decided to proceed by using lv1_panic to bisect the PowerPC boot process.
It either froze, in which case the call to lv1_panic was not reached, or it
rebooted. Interestingly, it turned out that ps3fb_probe was actually called,
so I added a sleep with

--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -1178,6 +1179,8 @@  static int ps3fb_probe(struct ps3_system_bus_device *dev)
 
 	ps3fb.task = task;
 
+	msleep(10000);
+
 	return 0;
 
 err_unregister_framebuffer: