Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
wr-switch-sw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
white-rabbit
wr-switch-sw
Commits
0b161dcf
Commit
0b161dcf
authored
Nov 28, 2014
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel: support bootcount reporting
Signed-off-by:
Alessandro Rubini
<
rubini@gnudd.com
>
parent
76939652
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
248 additions
and
0 deletions
+248
-0
wrs-developer-manual.in
doc/wrs-developer-manual.in
+80
-0
0014-sam9m10g45ek-for-wrs-provide-bootcount-using-scratch.patch
...am9m10g45ek-for-wrs-provide-bootcount-using-scratch.patch
+168
-0
No files found.
doc/wrs-developer-manual.in
View file @
0b161dcf
...
...
@@ -1648,6 +1648,86 @@ is using a shared memory connection for communication. The details
are documented in the @t{mini-rpc} manual. Only the hal process
sends commands to the @t{rt} subsystem.
@c ##########################################################################
@node Reboot/Reset Diagnostics
@chapter Reboot/Reset Diagnostics
For management and diagnostics, the @sc{wrs} keeps track of the number
of boots since power on. It does so relying on 4 32-bit @sc{cpu}
registers that are unpredictable at power-up and remain unchanged over
reboots. They are called ``backup registers'' in vendor documentation
(@t{GPBR}): they actually read 0 on power-up but the documentation
doesn`t say anything so we can'
t
count
on
it
.
Our
kernel
patches
use
the
16
bytes
in
the
following
way
;
all
values
are
little
-
endian
.
@
table
@
code
@
item
bytes
0..2
A
magic
number
:
if
not
found
,
then
this
is
a
power
-
on
boot
.
(
Note
:
we
may
use
the
"reset reason"
register
as
an
alternative
)
@
item
byte
3
Another
magic
number
:
it
is
`@
t
{
R
}
' (0x52) if the last reboot
has been requested by an operator. The value is reset to
`@t{U}'
(
for
``
unknown
''
)
right
after
boot
.
@
item
bytes
4..5
The
number
of
boots
since
power
on
.
This
is
at
least
1.
If
zero
,
the
code
is
not
working
.
@
item
bytes
6..7
The
number
of
soft
reboots
.
This
is
incremented
by
the
@
i
{
reboot
}
system
call
,
and
not
by
accidental
reboots
(
i
.
e
.
panic
or
other
yet
-
unforeseen
situation
).
A
healthy
sytem
should
feature
one
soft
-
reboot
less
than
total
boots
.
@
item
bytes
8..11
(
Not
implemented
yet
).
The
fault
address
of
the
last
panic
.
This
is
the
instruction
pointer
normally
printed
by
the
stack
backtrace
.
The
register
is
zeroed
at
first
boot
and
only
modified
within
@
i
{
panic
}.
@
item
bytes
12..15
(
Not
implemented
yet
).
The
"link register"
register
at
last
panic
,
like
above
.
This
is
usually
the
caller
of
the
function
that
failed
,
but
it
may
be
a
local
register
if
the
failing
function
saved
@
t
{
lr
}
to
the
stack
and
used
it
as
a
scratch
register
.
@
end
table
The
kernel
exports
the
current
status
in
@
t
{/
proc
/
wrs
-
bootcount
}
in
a
tagged
text
format
for
easy
parsing
.
This
is
an
example
,
after
power
-
on
,
one
@
t
{
reboot
}
command
and
one
hard
reset
(
by
pressing
the
button
on
the
@
sc
{
scb
}):
@
smallexample
#
cat
/
proc
/
wrs
-
bootcount
boot_count
:
3
reboot_count
:
1
last_is_reboot
:
0
fault_ip
:
0x00000000
fault_lr
:
0x00000000
@
end
smallexample
@
sp
1
We
will
likely
introduce
support
for
the
hardware
watchdog
,
but
it
is
not
supported
at
this
time
.
We
may
also
consider
to
use
one
of
the
kernel
's mechanisms for persistent
storage of information across reboots, to recover panic messages
after a reboot.
@c ##########################################################################
@node SDB and Hardware Information
@chapter SDB and Hardware Information
...
...
patches/kernel/v2.6.39/0014-sam9m10g45ek-for-wrs-provide-bootcount-using-scratch.patch
0 → 100644
View file @
0b161dcf
From dd4abd9483cdb6bc31cba97763028770cabbfed0 Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Fri, 28 Nov 2014 14:18:27 +0100
Subject: [PATCH 14/14] sam9m10g45ek (for wrs): provide bootcount using
scratch registers
Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
---
arch/arm/kernel/process.c | 13 ++++
arch/arm/mach-at91/Makefile | 1 +
arch/arm/mach-at91/wrs-bootcount.c | 109 ++++++++++++++++++++++++++++++++++++
3 files changed, 123 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-at91/wrs-bootcount.c
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 5e1e541..720d1e1 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -93,6 +93,19 @@ __setup("hlt", hlt_setup);
void arm_machine_restart(char mode, const char *cmd)
{
+ uint32_t gpbr_val;
+ char *gpbr_str = (void *)&gpbr_val;
+ unsigned short *gpbr_short = (void *)&gpbr_val;
+
+ /* WRS: Change the static registers. See wrs-bootcount.c for details */
+ gpbr_val = at91_sys_read(AT91_GPBR);
+ gpbr_str[3] = 'R'; /* reboot requested by user */
+ at91_sys_write(AT91_GPBR, gpbr_val);
+
+ gpbr_val = at91_sys_read(AT91_GPBR + 4);
+ gpbr_short[1]++; /* count the user-requeted reboots */
+ at91_sys_write(AT91_GPBR + 4, gpbr_val);
+
/* Disable interrupts first */
local_irq_disable();
local_fiq_disable();
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index a83835e..f1db0b2 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o
# AT91SAM9G45 board-specific support
obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
+obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += wrs-bootcount.o
# AT91CAP9 board-specific support
obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
diff --git a/arch/arm/mach-at91/wrs-bootcount.c b/arch/arm/mach-at91/wrs-bootcount.c
new file mode 100644
index 0000000..9088377
--- /dev/null
+++ b/arch/arm/mach-at91/wrs-bootcount.c
@@ -0,0 +1,109 @@
+/* Alessandro Rubini for CERN 2014 */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/map.h>
+
+#ifdef CONFIG_RTC_DRV_AT91SAM9
+#error "This is incompatible with CONFIG_RTC_DRV_AT91SAM9"
+#endif
+
+/* This structures is mapped over the general purpose registers */
+struct wrs_bc {
+ unsigned char magic[3];
+ unsigned char last_is_reboot;
+ unsigned short boot_count;
+ unsigned short reboot_count;
+ uint32_t fault_ip;
+ uint32_t fault_lr;
+};
+
+static struct wrs_bc __bc_soft, __bc_hard;
+
+/* bc_regs points there, bc_hw is a local tmp working copy, bc_sw is sw */
+static struct wrs_bc __iomem *bc_regs;
+static struct wrs_bc *bc_hw = &__bc_hard;
+static struct wrs_bc *bc_sw = &__bc_soft;
+
+/*
+ * For some reason, memcpy_fromio and toio is not working. The MSB
+ * is repeated 4 times in the resulting word. So do it by hand
+ */
+static void copy16_fromio(void *dest, void __iomem *src)
+{
+ uint32_t __iomem *s = src;
+ uint32_t *d = dest;
+ int i;
+ for (i = 0; i < 4; i++)
+ d[i] = __raw_readl(s + i);
+}
+
+static void copy16_toio(void __iomem *dest, void *src)
+{
+ uint32_t __iomem *d = dest;
+ uint32_t *s = src;
+ int i;
+ for (i = 0; i < 4; i++)
+ __raw_writel(s[i], d + i);
+}
+
+/* As soon as possible, copy stuff over */
+static int __init wrs_bc_early_init(void)
+{
+ bc_regs = (void __iomem *)AT91_VA_BASE_SYS + AT91_GPBR;
+ copy16_fromio(bc_hw, bc_regs);
+
+ if (strncmp(bc_hw->magic, "WRS", 3)) /* power on */
+ memset(bc_hw, 0, sizeof(*bc_hw));
+
+ strncpy(bc_hw->magic, "WRS", 3);
+ bc_hw->boot_count++;
+
+ /* save sw for printing, fix hw and copy back */
+ memcpy(bc_sw, bc_hw, sizeof(*bc_sw));
+ bc_hw->last_is_reboot = 'U';
+ bc_hw->fault_ip = bc_hw->fault_lr = 0;
+ copy16_toio(bc_regs, bc_hw);
+ return 0;
+}
+early_initcall(wrs_bc_early_init);
+
+/* Over time, export in proc */
+static int wrs_bc_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "boot_count: %i\n"
+ "reboot_count: %i\n"
+ "last_is_reboot: %i\n"
+ "fault_ip: 0x%08x\n"
+ "fault_lr: 0x%08x\n",
+ bc_sw->boot_count,
+ bc_sw->reboot_count,
+ bc_sw->last_is_reboot == 'R',
+ bc_sw->fault_ip,
+ bc_sw->fault_lr);
+ return 0;
+}
+
+static int wrs_bc_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wrs_bc_proc_show, NULL);
+}
+
+static const struct file_operations wrs_bc_proc_fops = {
+ .open = wrs_bc_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init proc_wrs_bc_init(void)
+{
+ /* two files use dash and two use underscore in /proc. Pick one */
+ proc_create("wrs-bootcount", 0, NULL, &wrs_bc_proc_fops);
+ return 0;
+}
+module_init(proc_wrs_bc_init);
--
1.7.7.2
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment