From: David Herrmann <hidden> Date: 2012-06-16 22:04:51
Hi
As some might know I am working on making CONFIG_VT obsolete. But as a developer
it is often useful to have a kernel-log on the screen during boot to debug many
common kernel(-config) errors. However, without CONFIG_VT we cannot use the
VGA/framebbufer consoles either. Therefore, I am working on a small driver
called "fblog".
This driver simply writes the kernel log to all connected framebuffers. It works
similar to fbcon but removes all the complexity of the virtual terminals. There
is a sysfs attribute called "active" that allows to enable/disable fblog so
user-space can start an xserver or similar.
The main purpose is debugging kernel boot problems. Therefore, it is not
optimized for speed and I tried keeping it simple. I splitted the patches
into 10 small chunks to make review easier.
I would be glad if someone could review this and tell me whether this is
something we could include in mainline or not.
There are still some issues but apart from them it works fine on my
machine (x86):
- I register the fblog device during module_init and need to call
module_get(). However, this means it is impossible to call "rmmod fblog" as
fblog has a reference to itself. Using "rmmod -f fblog" works fine but is a
bit ugly. Is there a nice way to fix this? Otherwise I would need to call
device_get() in module_exit() if there is a pending user of the fblog-device
even though I unregistered it.
- I redraw all framebuffers while holding the console-lock. This may slow down
machines with more than 2 framebuffers (like 10 or 20). However, as this is
supposed to be a debug driver, I think I can ignore this? If someone wants
to improve the redraw logic to avoid redrawing the whole screen all the
time, I would be glad to include it in this patchset :)
- I am really no expert regarding the framebuffer subsystem. So I would
appreciate it if someone could comment whether I need to handle the events
in a different way or whether it is ok the way it is now.
I run this on my machine with CONFIG_VT=n and it works quite nice. If someone
wants to test it, this also works with CONFIG_VT=y and x11 running. Just load
the driver from your xserver and it will redraw the screen with the console.
Switching VTs back and forth will make the xserver redraw the whole screen
again. You need to remove "depends on !VT" of course.
Thanks and regards
David
David Herrmann (10):
fblog: new framebuffer kernel log dummy driver
fblog: implement buffer management
fblog: register framebuffer objects
fblog: implement fblog_redraw()
fblog: add framebuffer helpers
fblog: allow enabling/disabling fblog on runtime
fblog: forward kernel log messages to all framebuffers
fblog: react on framebuffer events
fblog: register all handlers on module-init
fblog: add "activate" module parameter
Documentation/ABI/testing/sysfs-fblog | 9 +
drivers/video/Kconfig | 5 +-
drivers/video/Makefile | 2 +-
drivers/video/console/Kconfig | 37 +-
drivers/video/console/Makefile | 1 +
drivers/video/console/fblog.c | 694 +++++++++++++++++++++++++++++++++
6 files changed, 735 insertions(+), 13 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-fblog
create mode 100644 drivers/video/console/fblog.c
--
1.7.10.4
From: David Herrmann <hidden> Date: 2012-06-16 22:04:55
Fblog displays all kernel log messages on all connected framebuffers. It
replaces fbcon when CONFIG_VT=n is selected. Its main purpose is to debug
boot problems by displaying the whole boot log on the screen. This patch
provides the first dummy module-init/deinit functions.
As is uses all the font and fb functions I placed it in
drivers/video/console. However, this means that we need to move the check
for CONFIG_VT in Makefile/Kconfig from drivers/video into
drivers/video/console as fblog does not depend on CONFIG_VT.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/Kconfig | 5 +---
drivers/video/Makefile | 2 +-
drivers/video/console/Kconfig | 37 +++++++++++++++++++++------
drivers/video/console/Makefile | 1 +
drivers/video/console/fblog.c | 55 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 87 insertions(+), 13 deletions(-)
create mode 100644 drivers/video/console/fblog.c
@@ -20,6 +20,7 @@ font-objs += $(font-objs-y)# Each configuration option enables a list of files.+obj-$(CONFIG_FBLOG)+=fblog.ofont.oobj-$(CONFIG_DUMMY_CONSOLE)+=dummycon.oobj-$(CONFIG_SGI_NEWPORT_CONSOLE)+=newport_con.ofont.oobj-$(CONFIG_STI_CONSOLE)+=sticon.osticore.ofont.o
From: David Herrmann <hidden> Date: 2012-06-16 22:04:57
We register each available framebuffer in the system with the fblog driver
so we always know all active devices. We directly open the fb-driver,
initialize the buffer and load a font so we are ready for drawing
operations. If a device cannot be opened, we mark it as dead and ignore it
in all other functions.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 108 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
From: David Herrmann <hidden> Date: 2012-06-16 22:05:00
This provides an fb-notifier object that can be registered with the
framebuffer subsystem. We are then notified about events on all
framebuffers.
Most of the events are only of interest for fbcon so we can safely ignore
them. However, we need to handle REGISTERED/UNBIND to add new framebbufers
and we need to react on mode-changes (probably triggered by user-space).
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 113 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
@@ -449,6 +449,119 @@ static void fblog_deactivate(void)fblog_unregister_all();}+staticintfblog_event(structnotifier_block*self,unsignedlongaction,+void*data)+{+structfb_event*event=data;+structfb_info*info=event->info;+structfblog_fb*fb=fblog_info2fb(info);+int*blank;++if(action=FB_EVENT_FB_REGISTERED){+/* This is called when a low-level system driver registers a new+*framebuffer.Theregistrationlockisheldbuttheconsole+*lockmightnotbeheldwhenthisiscalled(really?).*/+fblog_register(info);+return0;+}++if(!fb)+return0;++switch(action){+caseFB_EVENT_FB_UNREGISTERED:+/* This is called when a low-level system driver unregisters a+*framebuffer.Theregistrationlockisheldbuttheconsole+*lockmightnotbeheld(really?).*/+/* ignore; see UNBIND */+break;+caseFB_EVENT_FB_UNBIND:+/* Called directly before unregistering an FB. The FB is still+*validhereandtheregistrationlockisheldbuttheconsole+*lockmightnotbeheld(really?).*/+fblog_unregister(fb);+break;+caseFB_EVENT_SUSPEND:+/* This is called when the low-level display driver suspends the+*videosystem.Weshouldnotaccessthevideosystemwhileit+*issuspended.Thisiscalledwiththeconsolelockheld.*/+set_bit(FBLOG_SUSPENDED,&fb->flags);+break;+caseFB_EVENT_RESUME:+/* This is called when the low-level display driver resumes+*operating.Itiscalledwiththeconsolelockheld.*/+clear_bit(FBLOG_SUSPENDED,&fb->flags);+break;+caseFB_EVENT_MODE_DELETE:+/* This is sent when a video mode is removed. The current video+*modeisneverremoved!Theconsolelockisheldwhilethisis+*called.*/+/* fallthrough */+caseFB_EVENT_NEW_MODELIST:+/* This is sent when the modelist got changed. The console-lock+*isheldandweshouldresetthemode.*/+/* fallthrough */+caseFB_EVENT_MODE_CHANGE_ALL:+/* This is the same as below but notifies us that the user used+*theFB_ACTIVATE_ALLflagwhensettingthevideomode.*/+/* fallthrough */+caseFB_EVENT_MODE_CHANGE:+/* This is called when the _user_ changes the video mode via+*ioctls.Itisnotsent,whenthekernelchangesthemode+*internally.Thiscallbackiscalledinsidefb_set_var()so+*theconsolelockisheld.*/+fblog_refresh(fb);+break;+caseFB_EVENT_BLANK:+/* This gets called _after_ the framebuffer was successfully+*blanked.Theconsole-lockisalwaysheldwhilefb_blankis+*calledandduringthiscallback.*/+blank=(int*)event->data;+if(*blank=FB_BLANK_UNBLANK)+clear_bit(FBLOG_BLANKED,&fb->flags);+else+set_bit(FBLOG_BLANKED,&fb->flags);+break;+caseFB_EVENT_GET_REQ:+/* When fb_set_var() is called, this callback is called to get+*ourdisplayrequirements.Theyarethencomparedwiththe+*displaypropertiesandonlyiftheyfulfilltherequirements,+*thenewmodeisactivated.Theconsole-lockshouldbeheld+*whilecallingfb_set_var()sowecanassumeitislocked+*here.*/+/* ignore */+break;+caseFB_EVENT_CONBLANK:+/* This is sent by fbcon when doing a fake blank. That+*is,blankingthescreenwhenthefbdriverfailedtoperform+*anfb_blank().Itsimplywritesemptylinestothescreen.+*Wearenotinterestedinthissignal.Weshouldalsonever+*runtogetherwithfbconsothisshouldneverbecatched.*/+/* ignore */+break;+caseFB_EVENT_GET_CONSOLE_MAP:+/* fallthrough */+caseFB_EVENT_SET_CONSOLE_MAP:+/* Is there any reason why we should support this? We+*ignoreitasweconsiderourselfnottobetheclassiclinux+*console.Hence,thisrequestisnottargetedatus.*/+/* ignore */+break;+caseFB_EVENT_REMAP_ALL_CONSOLE:+/* What are we supposed to do here? Do we have to remap+*theprimarydevicetotheframebuffergivenby\info?Like+*abovewecurrentlyignoreitforthesamereasons.*/+/* ignore */+break;+}++return0;+}++staticstructnotifier_blockfblog_notifier={+.notifier_call=fblog_event,+};+staticvoidfblog_con_write(structconsole*con,constchar*buf,unsignedintlen){
From: David Herrmann <hidden> Date: 2012-06-16 22:05:15
This new parameter controls whether fblog is automatically activated when
it is loaded. This defaults to "true".
We can now compile with CONFIG_VT=n and CONFIG_FBLOG=y and control fblog
with fblog.activate=0/1 on the kernel command line to enable/disable
debugging.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 10 ++++++++++
1 file changed, 10 insertions(+)
From: David Herrmann <hidden> Date: 2012-06-16 22:05:46
We now create a new "fblog" device when initializing the fblog module. We
register the "active" sysfs-file with it so user-space can now access
fblog. We also register the framebuffer-notifier and console-handler so
fblog is ready to go.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 59 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
From: David Herrmann <hidden> Date: 2012-06-16 22:06:09
This provides a console-driver that forwards all log messages to all
framebuffers and redraws them.
To avoid redrawing multiple times in short intervals, we could use a
work-queue here by simply pushing the task onto the system work-queue.
However, fblog is not performance critical and only used for debugging so
we avoid the complexity for now. This may change in the future, though.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
From: David Herrmann <hidden> Date: 2012-06-16 22:06:30
A sysfs file called "active" can be used to enable and disable fblog on
runtime. For example, the init-process can run "echo '0' >.../active"
after booting the system. This will allow other applications like X11 to
use the graphics subsystem. During shutdown, we can write '1' to get
system messages again.
When disabling fblog, we remove all framebuffers and will prevent new
hotplugged framebuffers from being added. When enabling fblog again, we
rescan the system for all framebuffers and resume operating.
The sysfs file is not registered, yet, as we do not have a "struct device"
yet. This will follow shortly, though.
Signed-off-by: David Herrmann <redacted>
---
Documentation/ABI/testing/sysfs-fblog | 9 ++++++
drivers/video/console/fblog.c | 49 +++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-fblog
@@ -0,0 +1,9 @@+What: /sys/class/graphics/fblog/active+Date: June 2012+KernelVersion: 3.6+Contact: David Herrmann <dh.herrmann@googlemail.com>+Description: Enable/Disable fblog. When setting this to 0, fblog will stop+ writing to framebuffers and other applications can use the+ graphics subsystem. When setting this to 1, fblog will rescan+ the system for all framebuffers and resume drawing the kernel+ log onto all framebuffers.
From: David Herrmann <hidden> Date: 2012-06-16 22:06:31
These helpers scan the system for all available framebuffers and register
or unregister them. This is needed during startup and stopping fblog so we
are aware of all connected displays.
The third helper handles mode changes by rescanning the mode and adjusting
the buffer size.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
From: Bruno Prémont <bonbons@linux-vserver.org> Date: 2012-06-16 22:42:27
On Sun, 17 June 2012 David Herrmann [off-list ref] wrote:
quoted hunk
These helpers scan the system for all available framebuffers and register
or unregister them. This is needed during startup and stopping fblog so we
are aware of all connected displays.
The third helper handles mode changes by rescanning the mode and adjusting
the buffer size.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
You should take registration_lock mutex for accessing registered_fb[],
even better would be to make use of get_fb_info() and put_fb_info()
+}
+
+static void fblog_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < FB_MAX; ++i)
+ fblog_unregister(fblog_info2fb(registered_fb[i]));
Same here.
Though for unregistering I'm wondering why you still scan through
registered_fb[], you should just scan your fblog_fbs[] array!
But here again, make sure to have proper locking to not get races with
registration of new framebuffers or removal of existing ones via
notifications.
All these new functions are still unused, for easier following of your
patch series it would be nice to have them connected when they are
introduced as otherwise on has to search all following patches for
finding possible users.
From: David Herrmann <hidden> Date: 2012-06-18 18:50:16
Hi Bruno
On Sun, Jun 17, 2012 at 12:33 AM, Bruno Prémont
[off-list ref] wrote:
On Sun, 17 June 2012 David Herrmann [off-list ref] wrote:
quoted
These helpers scan the system for all available framebuffers and register
or unregister them. This is needed during startup and stopping fblog so we
are aware of all connected displays.
The third helper handles mode changes by rescanning the mode and adjusting
the buffer size.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
kfree(fb);
}
+static void fblog_register_all(void)
+{
+ int i;
+
+ for (i = 0; i < FB_MAX; ++i)
+ fblog_register(registered_fb[i]);
You should take registration_lock mutex for accessing registered_fb[],
even better would be to make use of get_fb_info() and put_fb_info()
Indeed, I will change it to use get_fb_info()/put_fb_info().
Btw., is it safe to call console_lock() during
FB_EVENT_FB_(UN)REGISTERED? I definitely need the console lock when
calling fblog_register() but I am not sure whether all fb-drivers lock
the console during "(un)register_framebuffer()". Otherwise, I would
have to avoid redrawing the console inside of fblog_register().
quoted
+}
+
+static void fblog_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < FB_MAX; ++i)
+ fblog_unregister(fblog_info2fb(registered_fb[i]));
Same here.
Though for unregistering I'm wondering why you still scan through
registered_fb[], you should just scan your fblog_fbs[] array!
Oops, you're right. I will change it.
But here again, make sure to have proper locking to not get races with
registration of new framebuffers or removal of existing ones via
notifications.
All these new functions are still unused, for easier following of your
patch series it would be nice to have them connected when they are
introduced as otherwise on has to search all following patches for
finding possible users.
I have to admit the split was crap. I am sorry. I will recreate the
patchset with a proper split. Thanks!
From: David Herrmann <hidden> Date: 2012-06-16 22:07:10
This mostly copies the functionality from drivers/video/console/bitblit.c
so we can draw the console content on all available framebuffers.
All speed optimizations have been removed for simplicity. The original
code depends heavily on CONFIG_VT so we cannot share the codebase here.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 126 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
On Sun, 17 Jun 2012 00:04:20 +0200
David Herrmann [off-list ref] wrote:
This mostly copies the functionality from drivers/video/console/bitblit.c
so we can draw the console content on all available framebuffers.
All speed optimizations have been removed for simplicity. The original
code depends heavily on CONFIG_VT so we cannot share the codebase here.
No. That means we've got two sets of code to maintain not one. Fix the
dependancy.
Pull the relevant subset of struct vc_data into another struct
Make struct vc_data be
struct vc_data {
struct vc_whatever
rest
}
Alan
From: David Herrmann <hidden> Date: 2012-06-18 18:36:52
Hi Alan
On Sun, Jun 17, 2012 at 12:35 AM, Alan Cox [off-list ref] wrote:
On Sun, 17 Jun 2012 00:04:20 +0200
David Herrmann [off-list ref] wrote:
quoted
This mostly copies the functionality from drivers/video/console/bitblit.c
so we can draw the console content on all available framebuffers.
All speed optimizations have been removed for simplicity. The original
code depends heavily on CONFIG_VT so we cannot share the codebase here.
No. That means we've got two sets of code to maintain not one. Fix the
dependancy.
Pull the relevant subset of struct vc_data into another struct
Make struct vc_data be
struct vc_data {
struct vc_whatever
rest
}
It's a bit more complex as we cannot call scr_read() either. Hence, I
need to assemble the array of printed characters before calling the
redraw functions. But that should be feasible, too. I just need to
figure out how to avoid heavy allocations during redraw to avoid
slowdowns.
If there are no objections I will send these patches as a separate
patchset as we can apply it without fblog.
From: David Herrmann <hidden> Date: 2012-06-16 22:07:37
Each available framebuffer can have a different font and buffer size
inside of fblog. Therefore, we need to remember all the log messages that
are currently printed on screen. We save them as an array of lines which
can be rotated and traversed very fast.
This also implements a very trivial way of resizing the buffer but still
keeping the content. As there is no need to improve this for speed, we can
keep it this way.
Signed-off-by: David Herrmann <redacted>
---
drivers/video/console/fblog.c | 126 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
From: David Herrmann <hidden> Date: 2012-06-18 19:06:20
Hi
On Sun, Jun 17, 2012 at 12:04 AM, David Herrmann
[off-list ref] wrote:
Hi
As some might know I am working on making CONFIG_VT obsolete. But as a developer
it is often useful to have a kernel-log on the screen during boot to debug many
common kernel(-config) errors. However, without CONFIG_VT we cannot use the
VGA/framebbufer consoles either. Therefore, I am working on a small driver
called "fblog".
This driver simply writes the kernel log to all connected framebuffers. It works
similar to fbcon but removes all the complexity of the virtual terminals. There
is a sysfs attribute called "active" that allows to enable/disable fblog so
user-space can start an xserver or similar.
The main purpose is debugging kernel boot problems. Therefore, it is not
optimized for speed and I tried keeping it simple. I splitted the patches
into 10 small chunks to make review easier.
I would be glad if someone could review this and tell me whether this is
something we could include in mainline or not.
There are still some issues but apart from them it works fine on my
machine (x86):
- I register the fblog device during module_init and need to call
module_get(). However, this means it is impossible to call "rmmod fblog" as
fblog has a reference to itself. Using "rmmod -f fblog" works fine but is a
bit ugly. Is there a nice way to fix this? Otherwise I would need to call
device_get() in module_exit() if there is a pending user of the fblog-device
even though I unregistered it.
- I redraw all framebuffers while holding the console-lock. This may slow down
machines with more than 2 framebuffers (like 10 or 20). However, as this is
supposed to be a debug driver, I think I can ignore this? If someone wants
to improve the redraw logic to avoid redrawing the whole screen all the
time, I would be glad to include it in this patchset :)
- I am really no expert regarding the framebuffer subsystem. So I would
appreciate it if someone could comment whether I need to handle the events
in a different way or whether it is ok the way it is now.
One additional issue:
With udlfb.c we have hotplug capable framebuffers. However, fbcon and
fblog currently never close a framebuffer if not explicitely requested
by user-space. Therefore, if a framebuffer device is removed, the
FB_EVENT_FB_UNREGISTER event will never be sent because fbcon/fblog
still have a reference to the framebuffer(-driver). Therefore, the
number of available fbs will grow until there are no more free
indices.
See dlfb_usb_disconnect() in udlfb.c for an example. It does not
invoke unregister_framebuffer() unless the last user closed the FB.
udlfb disables the console on its framebuffer devices to avoid this,
but this doesn't seem to be a good solution.
How about sending an FB_EVENT_FB_DISCONNECT event during unlink_framebuffer()?
This still doesn't force user-space to close /dev/fbX but it at least
will make it possible to fblog/fbcon to close the framebuffer. fbmem.c
can then still be modified to mark the open file as dead so user-space
will also close the device hopefully.
Regards
David