* [PATCH] ASoC: sunxi: Add bindings for sun8i to SPDIF
From: codekipper at gmail.com @ 2017-01-12 17:33 UTC (permalink / raw)
To: linux-arm-kernel
From: Marcus Cooper <codekipper@gmail.com>
The H3 SoC uses the same SPDIF block as found in earlier SoCs, but the
transmit fifo is at a different address.
Signed-off-by: Marcus Cooper <codekipper@gmail.com>
---
Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt b/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt
index 0230c4d20506..fe0a65e6d629 100644
--- a/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt
+++ b/Documentation/devicetree/bindings/sound/sunxi,sun4i-spdif.txt
@@ -10,6 +10,7 @@ Required properties:
- compatible : should be one of the following:
- "allwinner,sun4i-a10-spdif": for the Allwinner A10 SoC
- "allwinner,sun6i-a31-spdif": for the Allwinner A31 SoC
+ - "allwinner,sun8i-h3-spdif": for the Allwinner H3 SoC
- reg : Offset and length of the register set for the device.
--
2.11.0
^ permalink raw reply related
* [PATCHv7 00/11] CONFIG_DEBUG_VIRTUAL for arm64
From: Will Deacon @ 2017-01-12 17:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484084150-1523-1-git-send-email-labbott@redhat.com>
On Tue, Jan 10, 2017 at 01:35:39PM -0800, Laura Abbott wrote:
> This is v7 of the patches to add CONFIG_DEBUG_VIRTUAL for arm64. This is
> a simple reordering of patches from v6 per request of Will Deacon for ease
> of merging support for arm which depends on this series.
>
> Laura Abbott (11):
> lib/Kconfig.debug: Add ARCH_HAS_DEBUG_VIRTUAL
> mm/cma: Cleanup highmem check
> mm: Introduce lm_alias
> kexec: Switch to __pa_symbol
> mm/kasan: Switch to using __pa_symbol and lm_alias
> mm/usercopy: Switch to using lm_alias
> drivers: firmware: psci: Use __pa_symbol for kernel symbol
> arm64: Move some macros under #ifndef __ASSEMBLY__
> arm64: Add cast for virt_to_pfn
> arm64: Use __pa_symbol for kernel symbols
> arm64: Add support for CONFIG_DEBUG_VIRTUAL
I've pushed this into linux-next and, assuming it survives the
autobuilders etc I'll co-ordinate with Russell to get the common parts
pulled into the ARM tree too (so he can take Florian's series). They're
currently split out on the arm64 for-next/debug-virtual branch.
Thanks!
Will
^ permalink raw reply
* [linux-sunxi][PATCH] ARM: dts: sun8i-h3: Add dts for the Beelink X2 STB
From: Code Kipper @ 2017-01-12 17:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170112172813.cbwqfpjlprkxdzcp@lukather>
On 12 January 2017 at 18:28, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Thu, Jan 12, 2017 at 06:11:35PM +0100, codekipper at gmail.com wrote:
>> From: Marcus Cooper <codekipper@gmail.com>
>>
>> The Beelink X2 is an STB based on the Allwinner H3 SoC with a uSD slot,
>> 2 USB ports( 1 * USB-2 Host, 1 USB OTG), a 10/100M ethernet port using the
>> SoC's integrated PHY, Wifi via a RTL8189ETV sdio wifi chip, HDMI, an IR
>> receiver, 1 LEDs and an optical S/PDIF connector.
>>
>> Signed-off-by: Marcus Cooper <codekipper@gmail.com>
>> ---
>> arch/arm/boot/dts/Makefile | 1 +
>> arch/arm/boot/dts/sun8i-h3-beelink-x2.dts | 187 ++++++++++++++++++++++++++++++
>> 2 files changed, 188 insertions(+)
>> create mode 100644 arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 78a94b747059..75960b1468a4 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -857,6 +857,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
>> sun8i-a83t-cubietruck-plus.dtb \
>> sun8i-h2-plus-orangepi-zero.dtb \
>> sun8i-h3-bananapi-m2-plus.dtb \
>> + sun8i-h3-beelink-x2.dtb \
>> sun8i-h3-nanopi-m1.dtb \
>> sun8i-h3-nanopi-neo.dtb \
>> sun8i-h3-orangepi-2.dtb \
>> diff --git a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
>> new file mode 100644
>> index 000000000000..bc5aed52cb1d
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
>> @@ -0,0 +1,187 @@
>> +/*
>> + * Copyright (C) 2017 Marcus Cooper <codekipper@gmail.com>
>> + *
>> + * This file is dual-licensed: you can use it either under the terms
>> + * of the GPL or the X11 license, at your option. Note that this dual
>> + * licensing only applies to this file, and not this project as a
>> + * whole.
>> + *
>> + * a) This file is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation; either version 2 of the
>> + * License, or (at your option) any later version.
>> + *
>> + * This file is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * Or, alternatively,
>> + *
>> + * b) Permission is hereby granted, free of charge, to any person
>> + * obtaining a copy of this software and associated documentation
>> + * files (the "Software"), to deal in the Software without
>> + * restriction, including without limitation the rights to use,
>> + * copy, modify, merge, publish, distribute, sublicense, and/or
>> + * sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following
>> + * conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> + * included in all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
>> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + * OTHER DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +/dts-v1/;
>> +#include "sun8i-h3.dtsi"
>> +#include "sunxi-common-regulators.dtsi"
>> +
>> +#include <dt-bindings/gpio/gpio.h>
>> +#include <dt-bindings/input/input.h>
>> +#include <dt-bindings/pinctrl/sun4i-a10.h>
>> +
>> +/ {
>> + model = "Beelink X2";
>> + compatible = "roofull,beelink-x2", "allwinner,sun8i-h3";
>> +
>> + aliases {
>> + serial0 = &uart0;
>> + /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
>> + ethernet1 = &rtl8189ftv;
>> + };
>> +
>> + chosen {
>> + stdout-path = "serial0:115200n8";
>> + };
>> +
>> + leds {
>> + compatible = "gpio-leds";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pwr_led_x2>;
>
> Please drop all the pinctrl nodes for the GPIOs. They're useless, and
> will be harmful when we'll switch to a stricter pinctrl driver.
>
ACK
>> +
>> + pwr_led {
>> + label = "beelink-x2:red:pwr";
>> + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
>> + default-state = "on";
>> + };
>> + };
>> +
>> + gpio_keys {
>> + compatible = "gpio-keys";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&sw_r_x2>;
>> +
>> + sw4 {
>> + label = "power";
>> + linux,code = <BTN_0>;
>
> Should that be BTN_0 then if the label is that one?
>
ACK
>> + gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
>> + };
>> + };
>> +
>> + wifi_pwrseq: wifi_pwrseq {
>> + compatible = "mmc-pwrseq-simple";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&wifi_en_x2>;
>> + reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
>> + };
>> +};
>> +
>> +&ehci1 {
>> + status = "okay";
>> +};
>> +
>> +&ir {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&ir_pins_a>;
>> + status = "okay";
>> +};
>> +
>> +&mmc0 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
>> + vmmc-supply = <®_vcc3v3>;
>> + bus-width = <4>;
>> + cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
>> + cd-inverted;
>> + status = "okay";
>> +};
>> +
>> +&mmc1 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&mmc1_pins_a>;
>> + vmmc-supply = <®_vcc3v3>;
>> + bus-width = <4>;
>> + non-removable;
>> + status = "okay";
>> +
>> + /*
>> + * Explicitly define the sdio device, so that we can add an ethernet
>> + * alias for it (which e.g. makes u-boot set a mac-address).
>> + */
>> + rtl8189ftv: sdio_wifi at 1 {
>> + reg = <1>;
>> + };
>> +};
>> +
>> +&mmc2 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&mmc2_8bit_pins>;
>> + vmmc-supply = <®_vcc3v3>;
>> + bus-width = <8>;
>> + non-removable;
>> + cap-mmc-hw-reset;
>> + status = "okay";
>> +};
>> +
>> +&mmc2_8bit_pins {
>> + /* Increase drive strength for DDR modes */
>> + drive-strength = <40>;
>
> Have you actually tested that it was needed?
>
I'll confess that I've rushed this one as I just wanted to verify my
spdif changes. I'll respin this,
BR,
CK
>> + /* eMMC is missing pull-ups */
>> + bias-pull-up;
>
> This is already enabled in the DTSI.
>
> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
^ permalink raw reply
* [PATCH 4/4] ARM: dts: sun8i: add OTG function to Lichee Pi Zero
From: Maxime Ripard @ 2017-01-12 17:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170112145014.GC16865@uda0271908>
Hi Bin,
On Thu, Jan 12, 2017 at 08:50:14AM -0600, Bin Liu wrote:
> On Wed, Jan 11, 2017 at 10:06:38PM +0100, Maxime Ripard wrote:
> > On Wed, Jan 11, 2017 at 02:08:11PM -0600, Bin Liu wrote:
> > > On Thu, Jan 12, 2017 at 03:55:33AM +0800, Icenowy Zheng wrote:
> > > >
> > > >
> > > > 11.01.2017, 04:24, "Bin Liu" <b-liu@ti.com>:
> > > > > On Tue, Jan 03, 2017 at 11:25:34PM +0800, Icenowy Zheng wrote:
> > > > >> ?Lichee Pi Zero features a USB OTG port.
> > > > >>
> > > > >> ?Add support for it.
> > > > >>
> > > > >> ?Note: in order to use the Host mode, the board must be powered via the
> > > > >> ?+5V and GND pins.
> > > > >>
> > > > >> ?Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> > > > >> ?---
> > > > >> ??arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 10 ++++++++++
> > > > >> ??1 file changed, 10 insertions(+)
> > > > >>
> > > > >> ?diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
> > > > >> ?index 0099affc6ce3..3d9168cbaeca 100644
> > > > >> ?--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
> > > > >> ?+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
> > > > >> ?@@ -71,3 +71,13 @@
> > > > >> ??????????pinctrl-names = "default";
> > > > >> ??????????status = "okay";
> > > > >> ??};
> > > > >> ?+
> > > > >> ?+&usb_otg {
> > > > >> ?+ dr_mode = "otg";
> > > > >
> > > > > Why not set this default mode in dtsi instead?
> > > > >
> > > > > Regards,
> > > > > -Bin.
> > > >
> > > > There's possibly boards which do not have OTG functions.
> > >
> > > That is board specific.
> >
> > Exactly, and this is why it should be done in the board DT.
>
> I am just suggesting based on the common practice. If a .dtsi exists for
> a family, the .dtsi describes the device and common properties for all
> possible boards, and each board .dts adds or overrides its specific
> implementation. Kernel has many devices/boards done in this way - define
> the default dr_mode in .dtsi.
>
> In this case, I suggest to set the common dr_mode in .dtsi, then each
> board .dts only overrides it if the implementation is different.
>
> >
> > The controller in the Allwinner SoCs do not handle directly the ID pin
> > and VBUS, but rather rely on a GPIO to do so.
> >
> > So boards with OTG will need setup anyway, at least to tell which
> > GPIOs are used. There's no point in enforcing a default if it doesn't
> > work by default.
>
> Then define a default which supposes to work for most boards.
>
> Why I suggest this, is because defining a default dr_mode which works
> for most cases in dtsi could prevent a little surprise in MUSB function.
> If someone designs a new board but forgets to define dr_mode in the new
> board DT, the MUSB driver will default to org mode, which might not be
> intended.
The point is that there is no sensible default. Some boards don't have
an ID pin and no VBUS (peripheral), some don't have an ID pin but VBUS
(host), and some have an ID pin but no controllable VBUS, some have an
ID pin and a controllable VBUS, but we have no idea which GPIOs are
used.
There's no way we can have something that works on most cases.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170112/f36ac00b/attachment-0001.sig>
^ permalink raw reply
* [PATCH] ASoC: sunxi: Add bindings for sun8i to SPDIF
From: Maxime Ripard @ 2017-01-12 17:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170112173343.9953-1-codekipper@gmail.com>
On Thu, Jan 12, 2017 at 06:33:43PM +0100, codekipper at gmail.com wrote:
> From: Marcus Cooper <codekipper@gmail.com>
>
> The H3 SoC uses the same SPDIF block as found in earlier SoCs, but the
> transmit fifo is at a different address.
>
> Signed-off-by: Marcus Cooper <codekipper@gmail.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170112/388153bd/attachment.sig>
^ permalink raw reply
* [PATCH v2] ARM64: dts: meson-gxbb-odroidc2: Disable SCPI DVFS
From: Martin Blumenstingl @ 2017-01-12 17:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483689872-30389-1-git-send-email-narmstrong@baylibre.com>
Hi Neil,
(adding Brian Kim, one of the Hardkernel developers to this conversation)
On Fri, Jan 6, 2017 at 9:04 AM, Neil Armstrong <narmstrong@baylibre.com> wrote:
> The current hardware is not able to run with all cores enabled at a
> cluster frequency superior at 1536MHz.
> But the currently shipped u-boot for the platform still reports an OPP
> table with possible DVFS frequency up to 2GHz, and will not change since
> the off-tree linux tree supports limiting the OPPs with a kernel parameter.
> A recent u-boot change reports the boot-time DVFS around 100MHz and
> the default performance cpufreq governor sets the maximum frequency.
> Previous version of u-boot reported to be already at the max OPP and
> left the OPP as is.
> Nevertheless, other governors like ondemand could setup the max frequency
> and make the system crash.
>
> This patch disables the DVFS clock and disables cpufreq.
I don't have any Odroid-C2 board, but having to live without cpufreq
sounds bad for the Odroid-C2 users.
What would we expect from a kernel perspective (maybe the Hardkernel
guys would adjust their u-boot instead of us adjusting to the behavior
of one specific device? one solution that I could think of involves
the "maxcpus" kernel parameter (see [0]), if this is not set u-boot
should report a max CPU frequency of 1536MHz (= max frequency for 4
active cores). Based on the "maxcpus" value additional frequencies can
be unlocked (this could be step-by-step if there are different
frequencies for one core/two cores/etc.). However, I'd like to hear
other opinions as well.
Regards,
Martin
[0] http://lxr.free-electrons.com/source/Documentation/kernel-parameters.txt?v=4.8#L2163
^ permalink raw reply
* [PATCH 2/5] clk: sunxi-ng: add support for V3s CCU
From: Maxime Ripard @ 2017-01-12 17:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170112203149.VhtuR9dM@smtp3j.mail.yandex.net>
On Fri, Jan 13, 2017 at 01:31:41AM +0800, Icenowy Zheng wrote:
>
> 2017?1?13? 01:19? Maxime Ripard <maxime.ripard@free-electrons.com>???
> >
> > On Thu, Jan 12, 2017 at 03:44:53AM +0800, Icenowy Zheng wrote:
> > >
> > >
> > > 12.01.2017, 03:40, "Icenowy Zheng" <icenowy@aosc.xyz>:
> > > > 11.01.2017, 02:10, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> > > >> ?On Tue, Jan 03, 2017 at 11:16:26PM +0800, Icenowy Zheng wrote:
> > > >>> ??V3s has a similar but cut-down CCU to H3.
> > > >>>
> > > >>> ??Add support for it.
> > > >>>
> > > >>> ??Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> > > >>
> > > >> ?It looks like there's nothing different but the clocks that you
> > > >> ?register with the H3, please just use the H3 driver.
> > > >
> > > > Nope.
> > > >
> > > > It has a different PLL (PLL_ISP) at different address, and some
> > > > different muxes.
> > >
> > > Forgot to mention the missing of PLL_DE and related misses.
> >
> > Those are not conflicting, it's just a slightly different set of
> > clocks.
>
> If saying so, we can have only one ccu driver, and make every ccu
> register different set ;-)
>
> V3s itself is a totally different SoC with H3.
>
> The relationship of V3s and H3 can be farther than the relationship
> of A33 and H3?
A33 and H3 are an entirely different story. The H3 and A33 have
conflicting clocks (ie same clocks with different parameters). This is
not your case.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170112/8631d007/attachment.sig>
^ permalink raw reply
* [kvm-unit-tests PATCH 1/6] libcflat: add PRI(dux)32 format types
From: Andrew Jones @ 2017-01-12 17:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87fuko2o4e.fsf@linaro.org>
On Thu, Jan 12, 2017 at 05:18:25PM +0000, Alex Benn?e wrote:
>
> Andrew Jones <drjones@redhat.com> writes:
>
> > On Thu, Jan 12, 2017 at 01:29:24PM +0100, Paolo Bonzini wrote:
> >>
> >>
> >> On 11/01/2017 17:28, Alex Benn?e wrote:
> >> > So we can have portable formatting of uint32_t types. However there is
> >> > a catch. Different compilers can use legally subtly different types
> >> > though so we need to probe the compiler defined intdef.h first.
> >>
> >> Interesting, what platform has long uint32_t? I thought the issue was
> >> whether 64-bit is long or "long long".
> >>
> >> Paolo
> >>
> >> > Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
> >> > ---
> >> > Makefile | 1 +
> >> > configure | 13 +++++++++++++
> >> > lib/libcflat.h | 9 +++++++++
> >> > 3 files changed, 23 insertions(+)
> >> >
> >> > diff --git a/Makefile b/Makefile
> >> > index a32333b..9822d9a 100644
> >> > --- a/Makefile
> >> > +++ b/Makefile
> >> > @@ -55,6 +55,7 @@ CFLAGS += $(fomit_frame_pointer)
> >> > CFLAGS += $(fno_stack_protector)
> >> > CFLAGS += $(fno_stack_protector_all)
> >> > CFLAGS += $(wno_frame_address)
> >> > +CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,)
> >> >
> >> > CXXFLAGS += $(CFLAGS)
> >> >
> >> > diff --git a/configure b/configure
> >> > index 995c8fa..127868c 100755
> >> > --- a/configure
> >> > +++ b/configure
> >> > @@ -109,6 +109,18 @@ if [ -f $testdir/run ]; then
> >> > ln -fs $testdir/run $testdir-run
> >> > fi
> >> >
> >> > +# check if uint32_t needs a long format modifier
> >> > +cat << EOF > lib_test.c
> >> > +#include <inttypes.h>
> >> > +EOF
> >> > +
> >> > +$cross_prefix$cc lib_test.c -E | grep "typedef" | grep "long" | grep "uint32_t" &> /dev/null
> >
> > This won't work with cross compilers that don't have inttypes.h in their
> > path (like mine). How about something like
>
> Hmm good point, in my case inttypes.h came from the libnewlib-dev package.
>
> >
> > cat << EOF > lib_test.c
> > __UINT32_TYPE__
> > EOF
> > u32_long="`aarch64-linux-gnu-gcc lib_test.c -E | awk '/unsigned/ && $2 == "long"'`"
>
> Hmm it is not clear from the docs if this is a GCCism. If it is do we
> care? Also the docs do say:
I think we're pretty bound to gcc already. I guess until somebody picks
up the effort to get clang, or whatever, compiling runnable
kvm-unit-tests, and commits to maintaining it, then I wouldn't worry too
much about it...
>
> "Some of these macros may not be defined on particular systems if GCC does not provide a stdint.h header on those systems. "
We already expect stdint.h, we include it from libcflat.h.
>
> > Although I feel there should be a compiler macro way to do this without
> > a need for configure/makefile trickery at all...
>
> I did ask our toolchain bods. They started going on about potential
> solutions using _Generic but I fear that might be worse in this case!
Yikes :-)
drew
>
> >
> > Thanks,
> > drew
> >
> >
> >> > +exit=$?
> >> > +if [ $exit -eq 0 ]; then
> >> > + u32_long=true
> >> > +fi
> >> > +rm -f lib_test.c
> >> > +
> >> > # check for dependent 32 bit libraries
> >> > if [ "$arch" != "arm" ]; then
> >> > cat << EOF > lib_test.c
> >> > @@ -155,4 +167,5 @@ TEST_DIR=$testdir
> >> > FIRMWARE=$firmware
> >> > ENDIAN=$endian
> >> > PRETTY_PRINT_STACKS=$pretty_print_stacks
> >> > +U32_LONG_FMT=$u32_long
> >> > EOF
> >> > diff --git a/lib/libcflat.h b/lib/libcflat.h
> >> > index 380395f..e80fc50 100644
> >> > --- a/lib/libcflat.h
> >> > +++ b/lib/libcflat.h
> >> > @@ -58,12 +58,21 @@ typedef _Bool bool;
> >> > #define true 1
> >> >
> >> > #if __SIZEOF_LONG__ == 8
> >> > +# define __PRI32_PREFIX
> >> > # define __PRI64_PREFIX "l"
> >> > # define __PRIPTR_PREFIX "l"
> >> > #else
> >> > +#if defined(__U32_LONG_FMT__)
> >> > +# define __PRI32_PREFIX "l"
> >> > +#else
> >> > +# define __PRI32_PREFIX
> >> > +#endif
> >> > # define __PRI64_PREFIX "ll"
> >> > # define __PRIPTR_PREFIX
> >> > #endif
> >> > +#define PRId32 __PRI32_PREFIX "d"
> >> > +#define PRIu32 __PRI32_PREFIX "u"
> >> > +#define PRIx32 __PRI32_PREFIX "x"
> >> > #define PRId64 __PRI64_PREFIX "d"
> >> > #define PRIu64 __PRI64_PREFIX "u"
> >> > #define PRIx64 __PRI64_PREFIX "x"
> >> >
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe kvm" in
> >> the body of a message to majordomo at vger.kernel.org
> >> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
> --
> Alex Benn?e
^ permalink raw reply
* [kvm-unit-tests PATCH 1/6] libcflat: add PRI(dux)32 format types
From: Paolo Bonzini @ 2017-01-12 17:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87fuko2o4e.fsf@linaro.org>
On 12/01/2017 18:18, Alex Benn?e wrote:
>> Although I feel there should be a compiler macro way to do this without
>> a need for configure/makefile trickery at all...
>
> I did ask our toolchain bods. They started going on about potential
> solutions using _Generic but I fear that might be worse in this case!
I don't think _Generic can do string concatenation, can it?
inttypes.h is not part of the set of freestanding headers, only stdint.h
is. Who is providing stdint.h in your case?
Paolo
^ permalink raw reply
* [PATCH v8 2/5] i2c: Add STM32F4 I2C driver
From: Uwe Kleine-König @ 2017-01-12 17:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOAejn289GLOSP-nPJnO_VpXLpyhTsF1bWQ7Ns9OfgPQCa8YTw@mail.gmail.com>
On Thu, Jan 12, 2017 at 02:47:42PM +0100, M'boumba Cedric Madianga wrote:
> 2017-01-12 13:03 GMT+01:00 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> > Hello Cedric,
> >
> > On Thu, Jan 12, 2017 at 12:23:12PM +0100, M'boumba Cedric Madianga wrote:
> >> 2017-01-11 16:39 GMT+01:00 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> >> > On Wed, Jan 11, 2017 at 02:58:44PM +0100, M'boumba Cedric Madianga wrote:
> >> >> 2017-01-11 9:22 GMT+01:00 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> >> >> > This is surprising. I didn't recheck the manual, but that looks very
> >> >> > uncomfortable.
> >> >>
> >> >> I agree but this exactly the hardware way of working described in the
> >> >> reference manual.
> >> >
> >> > IMHO that's a hw bug. This makes it for example impossible to implement
> >> > SMBus block transfers (I think).
> >>
> >> This is not correct.
> >> Setting STOP/START bit does not mean the the pulse will be sent right now.
> >> Here we have just to prepare the hardware for the 2 next pulse but the
> >> STOP/START/ACK pulse will be generated at the right time as required
> >> by I2C specification.
> >> So SMBus block transfer will be possible.
> >
> > A block transfer consists of a byte that specifies the count of bytes
> > yet to come. So the device sends for example:
> >
> > 0x01 0xab
> >
> > So when you read the 1 in the first byte it's already too late to set
> > STOP to get it after the 2nd byte.
> >
> > Not sure I got all the required details right, though.
>
> Ok I understand your use case but I always think that the harware manages it.
> If I take the above example, the I2C SMBus block read transaction will
> be as below:
> S Addr Wr [A] Comm [A]
> S Addr Rd [A] [Count] A [Data1] A [Data2] NA P
>
> The first message is a single byte-transmission so there is no problem.
>
> The second message is a N-byte reception with N = 3
>
> When the I2C controller has finished to send the device address (S
> Addr Rd), the ADDR flag is set and an interrupt is raised.
> In the routine that handles ADDR event, we set ACK bit in order to
> generate ACK pulse as soon as a data byte is received in the shift
> register and then we clear the ADDR flag.
> Please note that the SCL line is stretched low until ADDR flag is cleared.
> So, as far I understand, the device could not sent any data as long as
> the SCL line is stretched low. Right ?
>
> Then, as soon as the SCL line is high, the device could send the first
> data byte (Count).
> When this byte is received in the shift register, an ACK is
> automatically generated as defined during adress match phase and the
> data byte is pushed in DR (data register).
> Then, an interrupt is raised as RXNE (RX not empty) flag is set.
> In the routine that handles RXNE event, as N=3, we just clear all
> buffer interrupts in order to avoid another system preemption due to
> RXNE event but we does not read the data in DR.
In my example I want to receive a block of length 1, so only two bytes
are read, a 1 (the length) and the data byte (0xab in my example). I
think that as soon as you read the 1 it's already to late to schedule
the NA after the next byte?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [kvm-unit-tests PATCH 6/6] run_tests: allow passing of options to QEMU
From: Paolo Bonzini @ 2017-01-12 17:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170112173204.ufd2ggw7iz7xv772@hawk.localdomain>
On 12/01/2017 18:32, Andrew Jones wrote:
>>
>> +# Any options left for QEMU?
>> +shift $((OPTIND-1))
>> +if [ "$#" -gt 0 ]; then
>> + extra_opts="$@"
>> +fi
> We can unconditionally do the extra_opts="$@", extra_opts will just
> be null in the case there aren't more args, like it was before.
extra_opts is not an array, so this would mess up options that contain
spaces. (Alex's patch in general, not your tweak).
Paolo
>> +
>> RUNTIME_log_stderr () { cat >> test.log; }
>> RUNTIME_log_stdout () {
>> if [ "$PRETTY_PRINT_STACKS" = "yes" ]; then
>> @@ -59,4 +68,4 @@ RUNTIME_log_stdout () {
>> config=$TEST_DIR/unittests.cfg
>> rm -f test.log
>> printf "BUILD_HEAD=$(cat build-head)\n\n" > test.log
>> -for_each_unittest $config run
>> +for_each_unittest $config run "$extra_opts"
^ permalink raw reply
* [PATCH 1/2] memory: aemif: allow passing device lookup table as platform data
From: santosh.shilimkar at oracle.com @ 2017-01-12 17:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483526167-24209-2-git-send-email-bgolaszewski@baylibre.com>
On 1/4/17 2:36 AM, Bartosz Golaszewski wrote:
> TI aemif driver creates its own subnodes of the device tree in order
> to guarantee that all child devices are probed after the AEMIF timing
> parameters are configured.
>
> Some devices (e.g. da850) use struct of_dev_auxdata for clock lookup
> but nodes created from within the aemif driver can't access the lookup
> table.
>
> Create a platform data structure that holds a pointer to
> of_dev_auxdata so that we can use it with of_platform_populate().
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
Patch looks fine to me. Did I miss PATCH 2/2 ?
drivers/memory/* patches has been queue via Greg KH tree. Please
repost your series with acks and copy Greg. I will request Greg
to queue these changes via his tree.
Regards,
Santosh
^ permalink raw reply
* [kvm-unit-tests PATCH 1/6] libcflat: add PRI(dux)32 format types
From: Alex Bennée @ 2017-01-12 18:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <144fdce4-ddd4-0c93-296b-44aeec57c664@redhat.com>
Paolo Bonzini <pbonzini@redhat.com> writes:
> On 12/01/2017 18:18, Alex Benn?e wrote:
>>> Although I feel there should be a compiler macro way to do this without
>>> a need for configure/makefile trickery at all...
>>
>> I did ask our toolchain bods. They started going on about potential
>> solutions using _Generic but I fear that might be worse in this case!
>
> I don't think _Generic can do string concatenation, can it?
>
> inttypes.h is not part of the set of freestanding headers, only stdint.h
> is. Who is providing stdint.h in your case?
/usr/lib/gcc/arm-none-eabi/5.4.1/include/stdint.h
is part of the compiler package although it can just include the lib
stdint.h if it is there:
#ifndef _GCC_WRAP_STDINT_H
#if __STDC_HOSTED__
# if defined __cplusplus && __cplusplus >= 201103L
# undef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
# undef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
# endif
# include_next <stdint.h>
#else
# include "stdint-gcc.h"
#endif
#define _GCC_WRAP_STDINT_H
#endif
So using inttypes we would get:
>arm-none-eabi-gcc ./test.c -E | grep typedef | grep uint32
typedef long unsigned int __uint32_t;
typedef __uint32_t uint32_t ;
--
Alex Benn?e
^ permalink raw reply
* [RFC PATCH v4 0/5] ARM: Fix dma_alloc_coherent() and friends for NOMMU
From: Robin Murphy @ 2017-01-12 18:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <78458e5f-6b30-ab9b-1226-83fe3a844e3a@arm.com>
On 12/01/17 17:15, Vladimir Murzin wrote:
> On 12/01/17 17:04, Robin Murphy wrote:
>> On 12/01/17 16:52, Vladimir Murzin wrote:
>>> On 12/01/17 10:55, Benjamin Gaignard wrote:
>>>> 2017-01-12 11:35 GMT+01:00 Benjamin Gaignard <benjamin.gaignard@linaro.org>:
>>>>> 2017-01-11 15:34 GMT+01:00 Vladimir Murzin <vladimir.murzin@arm.com>:
>>>>>> On 11/01/17 13:17, Benjamin Gaignard wrote:
>>>>>>> 2017-01-10 15:18 GMT+01:00 Vladimir Murzin <vladimir.murzin@arm.com>:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> It seem that addition of cache support for M-class cpus uncovered
>>>>>>>> latent bug in DMA usage. NOMMU memory model has been treated as being
>>>>>>>> always consistent; however, for R/M classes of cpu memory can be
>>>>>>>> covered by MPU which in turn might configure RAM as Normal
>>>>>>>> i.e. bufferable and cacheable. It breaks dma_alloc_coherent() and
>>>>>>>> friends, since data can stuck in caches now or be buffered.
>>>>>>>>
>>>>>>>> This patch set is trying to address the issue by providing region of
>>>>>>>> memory suitable for consistent DMA operations. It is supposed that
>>>>>>>> such region is marked by MPU as non-cacheable. Robin suggested to
>>>>>>>> advertise such memory as reserved shared-dma-pool, rather then using
>>>>>>>> homebrew command line option, and extend dma-coherent to provide
>>>>>>>> default DMA area in the similar way as it is done for CMA (PATCH
>>>>>>>> 2/5). It allows us to offload all bookkeeping on generic coherent DMA
>>>>>>>> framework, and it is seems that it might be reused by other
>>>>>>>> architectures like c6x and blackfin.
>>>>>>>>
>>>>>>>> Dedicated DMA region is required for cases other than:
>>>>>>>> - MMU/MPU is off
>>>>>>>> - cpu is v7m w/o cache support
>>>>>>>> - device is coherent
>>>>>>>>
>>>>>>>> In case one of the above conditions is true dma operations are forced
>>>>>>>> to be coherent and wired with dma_noop_ops.
>>>>>>>>
>>>>>>>> To make life easier NOMMU dma operations are kept in separate
>>>>>>>> compilation unit.
>>>>>>>>
>>>>>>>> Since the issue was reported in the same time as Benjamin sent his
>>>>>>>> patch [1] to allow mmap for NOMMU, his case is also addressed in this
>>>>>>>> series (PATCH 1/5 and PATCH 3/5).
>>>>>>>>
>>>>>>>> Thanks!
>>>>>>>
>>>>>>> I have tested this v4 on my setup (stm32f4, no cache, no MPU) and unfortunately
>>>>>>> it doesn't work with my drm/kms driver.
>>>>>>
>>>>>> I guess the same is for fbmem, but would be better to have confirmation since
>>>>>> amba-clcd I use has not been ported to drm/kms (yet), so I can't test.
>>>>>>
>>>>>>> I haven't any errors but nothing is displayed unlike what I have when
>>>>>>> using current dma-mapping
>>>>>>> code.
>>>>>>> I guess the issue is coming from dma-noop where __get_free_pages() is
>>>>>>> used instead of alloc_pages()
>>>>>>> in dma-mapping.
>>>>>>
>>>>>> Unless I've missed something bellow is a call stack for both
>>>>>>
>>>>>> #1
>>>>>> __alloc_simple_buffer
>>>>>> __dma_alloc_buffer
>>>>>> alloc_pages
>>>>>> split_page
>>>>>> __dma_clear_buffer
>>>>>> memset
>>>>>> page_address
>>>>>>
>>>>>> #2
>>>>>> __get_free_pages
>>>>>> alloc_pages
>>>>>> page_address
>>>>>>
>>>>>> So the difference is that nommu case in dma-mapping.c memzeros memory, handles
>>>>>> DMA_ATTR_NO_KERNEL_MAPPING and does optimisation of memory usage.
>>>>>>
>>>>>> Is something from above critical for your driver?
>>>>>
>>>>> I have removed all the diff (split_page, __dma_clear_buffer, memset)
>>>>> from #1 and it is still working.
>>>>> DMA_ATTR_NO_KERNEL_MAPPING flag is not set when allocating the buffer.
>>>>>
>>>>> I have investigated more and found that dma-noop doesn't take care of
>>>>> "dma-ranges" property which is set in DT.
>>>>> I believed that is the root cause of my problem with your patches.
>>>>
>>>> After testing changing virt_to_phys to virt_to_dma in dma-noop.c fix the issue
>>>> modetest and fbdemo are now still functional.
>>>>
>>>
>>> Thanks for narrowing it down! I did not noticed that stm32f4 remap its memory,
>>> so dma-ranges property is in use.
>>>
>>> It looks like virt_to_dma is ARM specific, so I probably have to discard idea
>>> of reusing dma-noop-ops and switch logic into dma-mapping-nommu.c based on
>>> is_device_dma_coherent(dev) check.
>>
>> dma_pfn_offset is a member of struct device, so it should be OK for
>> dma_noop_ops to also make reference to it (and assume it's zero if not
>> explicitly set).
>>
>>> Meanwhile, I'm quite puzzled on how such memory remaping should work together
>>> with reserved memory. It seem it doesn't account dma-ranges while reserving
>>> memory (it is too early) nor while allocating/mapping/etc.
>>
>> The reserved memory is described in terms of CPU physical addresses, so
>> a device offset shouldn't matter from that perspective. It only comes
>> into play at the point you generate the dma_addr_t to hand off to the
>> device - only then do you need to transform the CPU physical address of
>> the allocated/mapped page into the device's view of that page (i.e.
>> subtract the offset).
>
> Thanks for explanation! So dma-coherent.c should be modified, right? I see
> that some architectures provide phys_to_dma/dma_to_phys helpers primary for
> swiotlb, is it safe to reuse them given that default implementation is
> provided? Nothing under Documentation explains how they supposed to be used,
> sorry if asking stupid question.
Those are essentially SWIOTLB-specific, so can't be universally relied
upon. I think something like this ought to suffice:
---8<---
diff --git a/lib/dma-noop.c b/lib/dma-noop.c
index 3d766e78fbe2..fbb1b37750d5 100644
--- a/lib/dma-noop.c
+++ b/lib/dma-noop.c
@@ -8,6 +8,11 @@
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
+static dma_addr_t dma_noop_dev_offset(struct device *dev)
+{
+ return (dma_addr_t)dev->dma_pfn_offset << PAGE_SHIFT;
+}
+
static void *dma_noop_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
unsigned long attrs)
@@ -16,7 +21,7 @@ static void *dma_noop_alloc(struct device *dev, size_t
size,
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret)
- *dma_handle = virt_to_phys(ret);
+ *dma_handle = virt_to_phys(ret) - dma_noop_dev_offset(dev);
return ret;
}
@@ -32,7 +37,7 @@ static dma_addr_t dma_noop_map_page(struct device
*dev, struct page *page,
enum dma_data_direction dir,
unsigned long attrs)
{
- return page_to_phys(page) + offset;
+ return page_to_phys(page) + offset - dma_noop_dev_offset(dev);
}
static int dma_noop_map_sg(struct device *dev, struct scatterlist *sgl,
int nents,
@@ -47,7 +52,8 @@ static int dma_noop_map_sg(struct device *dev, struct
scatterlist *sgl, int nent
BUG_ON(!sg_page(sg));
va = sg_virt(sg);
- sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va);
+ sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va) -
+ dma_noop_dev_offset(dev);
sg_dma_len(sg) = sg->length;
}
--->8---
intentionally whitespace-damaged by copy-pasting off my terminal to
emphasise how utterly untested it is ;)
Robin.
^ permalink raw reply related
* [PATCH V7 00/10] Add UEFI 2.6 and ACPI 6.1 updates for RAS on ARM64
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
When a memory error, CPU error, PCIe error, or other type of hardware error
that's covered by RAS occurs, firmware should populate the shared GHES memory
location with the proper GHES structures to notify the OS of the error.
For example, platforms that implement firmware first handling may implement
separate GHES sources for corrected errors and uncorrected errors. If the
error is an uncorrectable error, then the firmware will notify the OS
immediately since the error needs to be handled ASAP. The OS will then be able
to take the appropriate action needed such as offlining a page. If the error
is a corrected error, then the firmware will not interrupt the OS immediately.
Instead, the OS will see and report the error the next time it's GHES timer
expires. The kernel will first parse the GHES structures and report the errors
through the kernel logs and then notify the user space through RAS trace
events. This allows user space applications such as RAS Daemon to see the
errors and report them however the user desires. This patchset extends the
kernel functionality for RAS errors based on updates in the UEFI 2.6 and
ACPI 6.1 specifications.
An example flow from firmware to user space could be:
+---------------+
+-------->| |
| | GHES polling |--+
+-------------+ | source | | +---------------+ +------------+
| | +---------------+ | | Kernel GHES | | |
| Firmware | +-->| CPER AER and |-->| RAS trace |
| | +---------------+ | | EDAC drivers | | event |
+-------------+ | | | +---------------+ +------------+
| | GHES sci |--+
+-------->| source |
+---------------+
Add support for Generic Hardware Error Source (GHES) v2, which introduces the
capability for the OS to acknowledge the consumption of the error record
generated by the Reliability, Availability and Serviceability (RAS) controller.
This eliminates potential race conditions between the OS and the RAS controller.
Add support for the timestamp field added to the Generic Error Data Entry v3,
allowing the OS to log the time that the error is generated by the firmware,
rather than the time the error is consumed. This improves the correctness of
event sequences when analyzing error logs. The timestamp is added in
ACPI 6.1, reference Table 18-343 Generic Error Data Entry.
Add support for ARMv8 Common Platform Error Record (CPER) per UEFI 2.6
specification. ARMv8 specific processor error information is reported as part of
the CPER records. This provides more detail on for processor error logs. This
can help describe ARMv8 cache, tlb, and bus errors.
Synchronous External Abort (SEA) represents a specific processor error condition
in ARM systems. A handler is added to recognize SEA errors, and a notifier is
added to parse and report the errors before the process is killed. Refer to
section N.2.1.1 in the Common Platform Error Record appendix of the UEFI 2.6
specification.
Currently the kernel ignores CPER records that are unrecognized.
On the other hand, UEFI spec allows for non-standard (eg. vendor
proprietary) error section type in CPER (Common Platform Error Record),
as defined in section N2.3 of UEFI version 2.5. Therefore, user
is not able to see hardware error data of non-standard section.
If section Type field of Generic Error Data Entry is unrecognized,
prints out the raw data in dmesg buffer, and also adds a tracepoint
for reporting such hardware errors.
Currently even if an error status block's severity is fatal, the kernel
does not honor the severity level and panic. With the firmware first
model, the platform could inform the OS about a fatal hardware error
through the non-NMI GHES notification type. The OS should panic when a
hardware error record is received with this severity.
Add support to handle SEAs that occur while a KVM guest kernel is
running. Currently these are unsupported by the guest abort handling.
V7: Update a couple prints for ARM processor errors
Add Print notifying if overflow occurred for ARM processor errors
Check for ARM configuration to allow the compiler to ignore ARM code
on non-ARM systems
Use SEA acronym instead of spelling it out
Update fault_info prints to be more clear
Add NMI locking to SEA notification
Remove error info structure from ARM trace event since there can be
a variable amount of these structures
V6: Change HEST_TYPE_GENERIC_V2 to IS_HEST_TYPE_GENERIC_V2 for readability
Move APEI helper defines from cper.h to ghes.h
Add data_len decrement back into print loop
Change references to ARMv8 to just ARM
Rewrite ARM processor context info parsing
Check valid bit of ARM error info field before printing it
Add include of linux/uuid.h in ghes.c
V5: Fix GHES goto logic for error conditions
Change ghes_do_read_ack to ghes_ack_error
Make sure data version check is >= 3
Use CPER helper functions in print functions
Make handle_guest_sea() dummy function static for arm
Add arm to subject line for KVM patch
V4: Add bit offset left shift to read_ack_write value
Make HEST generic and generic_v2 structures a union in the ghes structure
Move gdata v3 helper functions into ghes.h to avoid duplication
Reorder the timestamp print and avoid memcpy
Add helper functions for gdata size checking
Rename the SEA functions
Add helper function for GHES panics
Set fru_id to NULL UUID at variable declaration
Limit ARM trace event parameters to the needed structures
Reorder the ARM trace event variables to save space
Add comment for why we don't pass SEAs to the guest when it aborts
Move ARM trace event call into GHES driver instead of CPER
V3: Fix unmapped address to the read_ack_register in ghes.c
Add helper function to get the proper payload based on generic data entry
version
Move timestamp print to avoid changing function calls in cper.c
Remove patch "arm64: exception: handle instruction abort at current EL"
since the el1_ia handler is already added in 4.8
Add EFI and ARM64 dependencies for HAVE_ACPI_APEI_SEA
Add a new trace event for ARM type errors
Add support to handle KVM guest SEAs
V2: Add PSCI state print for the ARMv8 error type.
Separate timestamp year into year and century using BCD format.
Rebase on top of ACPICA 20160318 release and remove header file changes
in include/acpi/actbl1.h.
Add panic OS with fatal error status block patch.
Add processing of unrecognized CPER error section patches with updates
from previous comments. Original patches: https://lkml.org/lkml/2015/9/8/646
V1: https://lkml.org/lkml/2016/2/5/544
Jonathan (Zhixiong) Zhang (1):
acpi: apei: panic OS with fatal error status block
Tyler Baicar (9):
acpi: apei: read ack upon ghes record consumption
ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1
efi: parse ARM processor error
arm64: exception: handle Synchronous External Abort
acpi: apei: handle SEA notification type for ARMv8
efi: print unrecognized CPER section
ras: acpi / apei: generate trace event for unrecognized CPER section
trace, ras: add ARM processor error trace event
arm/arm64: KVM: add guest SEA support
arch/arm/include/asm/kvm_arm.h | 1 +
arch/arm/include/asm/system_misc.h | 5 +
arch/arm/kvm/mmu.c | 18 ++-
arch/arm64/Kconfig | 2 +
arch/arm64/include/asm/kvm_arm.h | 1 +
arch/arm64/include/asm/system_misc.h | 15 +++
arch/arm64/mm/fault.c | 71 ++++++++++--
drivers/acpi/apei/Kconfig | 14 +++
drivers/acpi/apei/ghes.c | 188 ++++++++++++++++++++++++++++---
drivers/acpi/apei/hest.c | 7 +-
drivers/firmware/efi/cper.c | 209 ++++++++++++++++++++++++++++++++---
drivers/ras/ras.c | 2 +
include/acpi/ghes.h | 27 ++++-
include/linux/cper.h | 54 +++++++++
include/ras/ras_event.h | 79 +++++++++++++
15 files changed, 649 insertions(+), 44 deletions(-)
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH V7 01/10] acpi: apei: read ack upon ghes record consumption
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
A RAS (Reliability, Availability, Serviceability) controller
may be a separate processor running in parallel with OS
execution, and may generate error records for consumption by
the OS. If the RAS controller produces multiple error records,
then they may be overwritten before the OS has consumed them.
The Generic Hardware Error Source (GHES) v2 structure
introduces the capability for the OS to acknowledge the
consumption of the error record generated by the RAS
controller. A RAS controller supporting GHESv2 shall wait for
the acknowledgment before writing a new error record, thus
eliminating the race condition.
Add support for parsing of GHESv2 sub-tables as well.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Richard Ruigrok <rruigrok@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
drivers/acpi/apei/ghes.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---
drivers/acpi/apei/hest.c | 7 +++++--
include/acpi/ghes.h | 5 ++++-
3 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 60746ef..b23160d 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -45,6 +45,7 @@
#include <linux/aer.h>
#include <linux/nmi.h>
+#include <acpi/actbl1.h>
#include <acpi/ghes.h>
#include <acpi/apei.h>
#include <asm/tlbflush.h>
@@ -79,6 +80,10 @@
((struct acpi_hest_generic_status *) \
((struct ghes_estatus_node *)(estatus_node) + 1))
+#define IS_HEST_TYPE_GENERIC_V2(ghes) \
+ ((struct acpi_hest_header *)ghes->generic)->type == \
+ ACPI_HEST_TYPE_GENERIC_ERROR_V2
+
/*
* This driver isn't really modular, however for the time being,
* continuing to use module_param is the easiest way to remain
@@ -248,10 +253,18 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
ghes = kzalloc(sizeof(*ghes), GFP_KERNEL);
if (!ghes)
return ERR_PTR(-ENOMEM);
+
ghes->generic = generic;
+ if (IS_HEST_TYPE_GENERIC_V2(ghes)) {
+ rc = apei_map_generic_address(
+ &ghes->generic_v2->read_ack_register);
+ if (rc)
+ goto err_free;
+ }
+
rc = apei_map_generic_address(&generic->error_status_address);
if (rc)
- goto err_free;
+ goto err_unmap_read_ack_addr;
error_block_length = generic->error_block_length;
if (error_block_length > GHES_ESTATUS_MAX_SIZE) {
pr_warning(FW_WARN GHES_PFX
@@ -263,13 +276,17 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
ghes->estatus = kmalloc(error_block_length, GFP_KERNEL);
if (!ghes->estatus) {
rc = -ENOMEM;
- goto err_unmap;
+ goto err_unmap_status_addr;
}
return ghes;
-err_unmap:
+err_unmap_status_addr:
apei_unmap_generic_address(&generic->error_status_address);
+err_unmap_read_ack_addr:
+ if (IS_HEST_TYPE_GENERIC_V2(ghes))
+ apei_unmap_generic_address(
+ &ghes->generic_v2->read_ack_register);
err_free:
kfree(ghes);
return ERR_PTR(rc);
@@ -279,6 +296,9 @@ static void ghes_fini(struct ghes *ghes)
{
kfree(ghes->estatus);
apei_unmap_generic_address(&ghes->generic->error_status_address);
+ if (IS_HEST_TYPE_GENERIC_V2(ghes))
+ apei_unmap_generic_address(
+ &ghes->generic_v2->read_ack_register);
}
static inline int ghes_severity(int severity)
@@ -648,6 +668,23 @@ static void ghes_estatus_cache_add(
rcu_read_unlock();
}
+static int ghes_ack_error(struct acpi_hest_generic_v2 *generic_v2)
+{
+ int rc;
+ u64 val = 0;
+
+ rc = apei_read(&val, &generic_v2->read_ack_register);
+ if (rc)
+ return rc;
+ val &= generic_v2->read_ack_preserve <<
+ generic_v2->read_ack_register.bit_offset;
+ val |= generic_v2->read_ack_write <<
+ generic_v2->read_ack_register.bit_offset;
+ rc = apei_write(val, &generic_v2->read_ack_register);
+
+ return rc;
+}
+
static int ghes_proc(struct ghes *ghes)
{
int rc;
@@ -660,6 +697,12 @@ static int ghes_proc(struct ghes *ghes)
ghes_estatus_cache_add(ghes->generic, ghes->estatus);
}
ghes_do_proc(ghes, ghes->estatus);
+
+ if (IS_HEST_TYPE_GENERIC_V2(ghes)) {
+ rc = ghes_ack_error(ghes->generic_v2);
+ if (rc)
+ return rc;
+ }
out:
ghes_clear_estatus(ghes);
return 0;
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 792a0d9..ef725a9 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -52,6 +52,7 @@ static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
[ACPI_HEST_TYPE_AER_ENDPOINT] = sizeof(struct acpi_hest_aer),
[ACPI_HEST_TYPE_AER_BRIDGE] = sizeof(struct acpi_hest_aer_bridge),
[ACPI_HEST_TYPE_GENERIC_ERROR] = sizeof(struct acpi_hest_generic),
+ [ACPI_HEST_TYPE_GENERIC_ERROR_V2] = sizeof(struct acpi_hest_generic_v2),
};
static int hest_esrc_len(struct acpi_hest_header *hest_hdr)
@@ -146,7 +147,8 @@ static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void
{
int *count = data;
- if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR)
+ if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR ||
+ hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR_V2)
(*count)++;
return 0;
}
@@ -157,7 +159,8 @@ static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
struct ghes_arr *ghes_arr = data;
int rc, i;
- if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
+ if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR &&
+ hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR_V2)
return 0;
if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 720446c..68f088a 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -13,7 +13,10 @@
#define GHES_EXITING 0x0002
struct ghes {
- struct acpi_hest_generic *generic;
+ union {
+ struct acpi_hest_generic *generic;
+ struct acpi_hest_generic_v2 *generic_v2;
+ };
struct acpi_hest_generic_status *estatus;
u64 buffer_paddr;
unsigned long flags;
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 02/10] ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
Currently when a RAS error is reported it is not timestamped.
The ACPI 6.1 spec adds the timestamp field to the generic error
data entry v3 structure. The timestamp of when the firmware
generated the error is now being reported.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Richard Ruigrok <rruigrok@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
drivers/acpi/apei/ghes.c | 9 ++++---
drivers/firmware/efi/cper.c | 63 +++++++++++++++++++++++++++++++++++----------
include/acpi/ghes.h | 22 ++++++++++++++++
3 files changed, 77 insertions(+), 17 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index b23160d..2acbc60 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -420,7 +420,8 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int
int flags = -1;
int sec_sev = ghes_severity(gdata->error_severity);
struct cper_sec_mem_err *mem_err;
- mem_err = (struct cper_sec_mem_err *)(gdata + 1);
+
+ mem_err = acpi_hest_generic_data_payload(gdata);
if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
return;
@@ -457,7 +458,8 @@ static void ghes_do_proc(struct ghes *ghes,
if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err;
- mem_err = (struct cper_sec_mem_err *)(gdata+1);
+
+ mem_err = acpi_hest_generic_data_payload(gdata);
ghes_edac_report_mem_error(ghes, sev, mem_err);
arch_apei_report_mem_error(sev, mem_err);
@@ -467,7 +469,8 @@ static void ghes_do_proc(struct ghes *ghes,
else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
CPER_SEC_PCIE)) {
struct cper_sec_pcie *pcie_err;
- pcie_err = (struct cper_sec_pcie *)(gdata+1);
+
+ pcie_err = acpi_hest_generic_data_payload(gdata);
if (sev == GHES_SEV_RECOVERABLE &&
sec_sev == GHES_SEV_RECOVERABLE &&
pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index d425374..8fa4e23 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -32,6 +32,9 @@
#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/aer.h>
+#include <linux/printk.h>
+#include <linux/bcd.h>
+#include <acpi/ghes.h>
#define INDENT_SP " "
@@ -386,13 +389,37 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
pfx, pcie->bridge.secondary_status, pcie->bridge.control);
}
+static void cper_estatus_print_section_v300(const char *pfx,
+ const struct acpi_hest_generic_data_v300 *gdata)
+{
+ __u8 hour, min, sec, day, mon, year, century, *timestamp;
+
+ if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) {
+ timestamp = (__u8 *)&(gdata->time_stamp);
+ sec = bcd2bin(timestamp[0]);
+ min = bcd2bin(timestamp[1]);
+ hour = bcd2bin(timestamp[2]);
+ day = bcd2bin(timestamp[4]);
+ mon = bcd2bin(timestamp[5]);
+ year = bcd2bin(timestamp[6]);
+ century = bcd2bin(timestamp[7]);
+ printk("%stime: %7s %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx,
+ 0x01 & *(timestamp + 3) ? "precise" : "", century,
+ year, mon, day, hour, min, sec);
+ }
+}
+
static void cper_estatus_print_section(
- const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no)
+ const char *pfx, struct acpi_hest_generic_data *gdata, int sec_no)
{
uuid_le *sec_type = (uuid_le *)gdata->section_type;
__u16 severity;
char newpfx[64];
+ if (acpi_hest_generic_data_version(gdata) >= 3)
+ cper_estatus_print_section_v300(pfx,
+ (const struct acpi_hest_generic_data_v300 *)gdata);
+
severity = gdata->error_severity;
printk("%s""Error %d, type: %s\n", pfx, sec_no,
cper_severity_str(severity));
@@ -403,14 +430,18 @@ static void cper_estatus_print_section(
snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) {
- struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1);
+ struct cper_sec_proc_generic *proc_err;
+
+ proc_err = acpi_hest_generic_data_payload(gdata);
printk("%s""section_type: general processor error\n", newpfx);
if (gdata->error_data_length >= sizeof(*proc_err))
cper_print_proc_generic(newpfx, proc_err);
else
goto err_section_too_small;
} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
- struct cper_sec_mem_err *mem_err = (void *)(gdata + 1);
+ struct cper_sec_mem_err *mem_err;
+
+ mem_err = acpi_hest_generic_data_payload(gdata);
printk("%s""section_type: memory error\n", newpfx);
if (gdata->error_data_length >=
sizeof(struct cper_sec_mem_err_old))
@@ -419,7 +450,9 @@ static void cper_estatus_print_section(
else
goto err_section_too_small;
} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) {
- struct cper_sec_pcie *pcie = (void *)(gdata + 1);
+ struct cper_sec_pcie *pcie;
+
+ pcie = acpi_hest_generic_data_payload(gdata);
printk("%s""section_type: PCIe error\n", newpfx);
if (gdata->error_data_length >= sizeof(*pcie))
cper_print_pcie(newpfx, pcie, gdata);
@@ -438,7 +471,7 @@ void cper_estatus_print(const char *pfx,
const struct acpi_hest_generic_status *estatus)
{
struct acpi_hest_generic_data *gdata;
- unsigned int data_len, gedata_len;
+ unsigned int data_len;
int sec_no = 0;
char newpfx[64];
__u16 severity;
@@ -451,12 +484,13 @@ void cper_estatus_print(const char *pfx,
printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
data_len = estatus->data_length;
gdata = (struct acpi_hest_generic_data *)(estatus + 1);
+
snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
- while (data_len >= sizeof(*gdata)) {
- gedata_len = gdata->error_data_length;
+
+ while (data_len >= acpi_hest_generic_data_size(gdata)) {
cper_estatus_print_section(newpfx, gdata, sec_no);
- data_len -= gedata_len + sizeof(*gdata);
- gdata = (void *)(gdata + 1) + gedata_len;
+ data_len -= acpi_hest_generic_data_record_size(gdata);
+ gdata = acpi_hest_generic_data_next(gdata);
sec_no++;
}
}
@@ -486,12 +520,13 @@ int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
return rc;
data_len = estatus->data_length;
gdata = (struct acpi_hest_generic_data *)(estatus + 1);
- while (data_len >= sizeof(*gdata)) {
- gedata_len = gdata->error_data_length;
- if (gedata_len > data_len - sizeof(*gdata))
+
+ while (data_len >= acpi_hest_generic_data_size(gdata)) {
+ gedata_len = acpi_hest_generic_data_error_length(gdata);
+ if (gedata_len > data_len - acpi_hest_generic_data_size(gdata))
return -EINVAL;
- data_len -= gedata_len + sizeof(*gdata);
- gdata = (void *)(gdata + 1) + gedata_len;
+ data_len -= gedata_len + acpi_hest_generic_data_size(gdata);
+ gdata = acpi_hest_generic_data_next(gdata);
}
if (data_len)
return -EINVAL;
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 68f088a..6ae318b 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -12,6 +12,18 @@
#define GHES_TO_CLEAR 0x0001
#define GHES_EXITING 0x0002
+#define acpi_hest_generic_data_error_length(gdata) \
+ (((struct acpi_hest_generic_data *)(gdata))->error_data_length)
+#define acpi_hest_generic_data_size(gdata) \
+ ((acpi_hest_generic_data_version(gdata) >= 3) ? \
+ sizeof(struct acpi_hest_generic_data_v300) : \
+ sizeof(struct acpi_hest_generic_data))
+#define acpi_hest_generic_data_record_size(gdata) \
+ (acpi_hest_generic_data_size(gdata) + \
+ acpi_hest_generic_data_error_length(gdata))
+#define acpi_hest_generic_data_next(gdata) \
+ ((void *)(gdata) + acpi_hest_generic_data_record_size(gdata))
+
struct ghes {
union {
struct acpi_hest_generic *generic;
@@ -73,3 +85,13 @@ static inline void ghes_edac_unregister(struct ghes *ghes)
{
}
#endif
+
+#define acpi_hest_generic_data_version(gdata) \
+ (gdata->revision >> 8)
+
+static inline void *acpi_hest_generic_data_payload(struct acpi_hest_generic_data *gdata)
+{
+ return acpi_hest_generic_data_version(gdata) >= 3 ?
+ (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1) :
+ gdata + 1;
+}
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 03/10] efi: parse ARM processor error
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
Add support for ARM Common Platform Error Record (CPER).
UEFI 2.6 specification adds support for ARM specific
processor error information to be reported as part of the
CPER records. This provides more detail on for processor error logs.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
drivers/firmware/efi/cper.c | 133 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/cper.h | 54 ++++++++++++++++++
2 files changed, 187 insertions(+)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 8fa4e23..c2b0a12 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -110,12 +110,15 @@ void cper_print_bits(const char *pfx, unsigned int bits,
static const char * const proc_type_strs[] = {
"IA32/X64",
"IA64",
+ "ARM",
};
static const char * const proc_isa_strs[] = {
"IA32",
"IA64",
"X64",
+ "ARM A32/T32",
+ "ARM A64",
};
static const char * const proc_error_type_strs[] = {
@@ -139,6 +142,18 @@ static const char * const proc_flag_strs[] = {
"corrected",
};
+static const char * const arm_reg_ctx_strs[] = {
+ "AArch32 general purpose registers",
+ "AArch32 EL1 context registers",
+ "AArch32 EL2 context registers",
+ "AArch32 secure context registers",
+ "AArch64 general purpose registers",
+ "AArch64 EL1 context registers",
+ "AArch64 EL2 context registers",
+ "AArch64 EL3 context registers",
+ "Misc. system register structure",
+};
+
static void cper_print_proc_generic(const char *pfx,
const struct cper_sec_proc_generic *proc)
{
@@ -184,6 +199,114 @@ static void cper_print_proc_generic(const char *pfx,
printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
}
+static void cper_print_proc_arm(const char *pfx,
+ const struct cper_sec_proc_arm *proc)
+{
+ int i, len, max_ctx_type;
+ struct cper_arm_err_info *err_info;
+ struct cper_arm_ctx_info *ctx_info;
+ char newpfx[64];
+
+ printk("%s""section length: %d\n", pfx, proc->section_length);
+ printk("%s""MIDR: 0x%016llx\n", pfx, proc->midr);
+
+ len = proc->section_length - (sizeof(*proc) +
+ proc->err_info_num * (sizeof(*err_info)));
+ if (len < 0) {
+ printk("%s""section length is too small\n", pfx);
+ printk("%s""firmware-generated error record is incorrect\n", pfx);
+ printk("%s""ERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
+ return;
+ }
+
+ if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
+ printk("%s""MPIDR: 0x%016llx\n", pfx, proc->mpidr);
+ if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
+ printk("%s""error affinity level: %d\n", pfx,
+ proc->affinity_level);
+ if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
+ printk("%s""running state: 0x%x\n", pfx, proc->running_state);
+ printk("%s""PSCI state: %d\n", pfx, proc->psci_state);
+ }
+
+ snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+
+ err_info = (struct cper_arm_err_info *)(proc + 1);
+ for (i = 0; i < proc->err_info_num; i++) {
+ printk("%s""Error info structure %d:\n", pfx, i);
+ printk("%s""version:%d\n", newpfx, err_info->version);
+ printk("%s""length:%d\n", newpfx, err_info->length);
+ if (err_info->validation_bits &
+ CPER_ARM_INFO_VALID_MULTI_ERR) {
+ if (err_info->multiple_error == 0)
+ printk("%s""single error\n", newpfx);
+ else if (err_info->multiple_error == 1)
+ printk("%s""multiple errors\n", newpfx);
+ else
+ printk("%s""multiple errors count:%u\n",
+ newpfx, err_info->multiple_error);
+ }
+ if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
+ if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
+ printk("%s""first error captured\n", newpfx);
+ if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
+ printk("%s""last error captured\n", newpfx);
+ if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
+ printk("%s""propagated error captured\n",
+ newpfx);
+ if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
+ printk("%s""overflow occurred, error info is incomplete\n",
+ newpfx);
+ }
+ printk("%s""error_type: %d, %s\n", newpfx, err_info->type,
+ err_info->type < ARRAY_SIZE(proc_error_type_strs) ?
+ proc_error_type_strs[err_info->type] : "unknown");
+ if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
+ printk("%s""error_info: 0x%016llx\n", newpfx,
+ err_info->error_info);
+ if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
+ printk("%s""virtual fault address: 0x%016llx\n",
+ newpfx, err_info->virt_fault_addr);
+ if (err_info->validation_bits &
+ CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
+ printk("%s""physical fault address: 0x%016llx\n",
+ newpfx, err_info->physical_fault_addr);
+ err_info += 1;
+ }
+ ctx_info = (struct cper_arm_ctx_info *)err_info;
+ max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
+ for (i = 0; i < proc->context_info_num; i++) {
+ int size = sizeof(*ctx_info) + ctx_info->size;
+
+ printk("%s""Context info structure %d:\n", pfx, i);
+ if (len < size) {
+ printk("%s""section length is too small\n", newpfx);
+ printk("%s""firmware-generated error record is incorrect\n", pfx);
+ return;
+ }
+ if (ctx_info->type > max_ctx_type) {
+ printk("%s""Invalid context type: %d\n", newpfx,
+ ctx_info->type);
+ printk("%s""Max context type: %d\n", newpfx,
+ max_ctx_type);
+ return;
+ }
+ printk("%s""register context type %d: %s\n", newpfx,
+ ctx_info->type, arm_reg_ctx_strs[ctx_info->type]);
+ print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
+ (ctx_info + 1), ctx_info->size, 0);
+ len -= size;
+ ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
+ }
+
+ if (len > 0) {
+ printk("%s""Vendor specific error info has %u bytes:\n", pfx,
+ len);
+ print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
+ len, 0);
+ }
+}
+
static const char * const mem_err_type_strs[] = {
"unknown",
"no error",
@@ -458,6 +581,16 @@ static void cper_estatus_print_section(
cper_print_pcie(newpfx, pcie, gdata);
else
goto err_section_too_small;
+ } else if ((IS_ENABLED(CONFIG_ARM64) || IS_ENABLED(CONFIG_ARM)) &&
+ !uuid_le_cmp(*sec_type, CPER_SEC_PROC_ARM)) {
+ struct cper_sec_proc_arm *arm_err;
+
+ arm_err = acpi_hest_generic_data_payload(gdata);
+ printk("%ssection_type: ARM processor error\n", newpfx);
+ if (gdata->error_data_length >= sizeof(*arm_err))
+ cper_print_proc_arm(newpfx, arm_err);
+ else
+ goto err_section_too_small;
} else
printk("%s""section type: unknown, %pUl\n", newpfx, sec_type);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index dcacb1a..85450f3 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -180,6 +180,10 @@ enum {
#define CPER_SEC_PROC_IPF \
UUID_LE(0xE429FAF1, 0x3CB7, 0x11D4, 0x0B, 0xCA, 0x07, 0x00, \
0x80, 0xC7, 0x3C, 0x88, 0x81)
+/* Processor Specific: ARM */
+#define CPER_SEC_PROC_ARM \
+ UUID_LE(0xE19E3D16, 0xBC11, 0x11E4, 0x9C, 0xAA, 0xC2, 0x05, \
+ 0x1D, 0x5D, 0x46, 0xB0)
/* Platform Memory */
#define CPER_SEC_PLATFORM_MEM \
UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
@@ -255,6 +259,22 @@ enum {
#define CPER_PCIE_SLOT_SHIFT 3
+#define CPER_ARM_VALID_MPIDR 0x00000001
+#define CPER_ARM_VALID_AFFINITY_LEVEL 0x00000002
+#define CPER_ARM_VALID_RUNNING_STATE 0x00000004
+#define CPER_ARM_VALID_VENDOR_INFO 0x00000008
+
+#define CPER_ARM_INFO_VALID_MULTI_ERR 0x0001
+#define CPER_ARM_INFO_VALID_FLAGS 0x0002
+#define CPER_ARM_INFO_VALID_ERR_INFO 0x0004
+#define CPER_ARM_INFO_VALID_VIRT_ADDR 0x0008
+#define CPER_ARM_INFO_VALID_PHYSICAL_ADDR 0x0010
+
+#define CPER_ARM_INFO_FLAGS_FIRST 0x0001
+#define CPER_ARM_INFO_FLAGS_LAST 0x0002
+#define CPER_ARM_INFO_FLAGS_PROPAGATED 0x0004
+#define CPER_ARM_INFO_FLAGS_OVERFLOW 0x0008
+
/*
* All tables and structs must be byte-packed to match CPER
* specification, since the tables are provided by the system BIOS
@@ -340,6 +360,40 @@ struct cper_ia_proc_ctx {
__u64 mm_reg_addr;
};
+/* ARM Processor Error Section */
+struct cper_sec_proc_arm {
+ __u32 validation_bits;
+ __u16 err_info_num; /* Number of Processor Error Info */
+ __u16 context_info_num; /* Number of Processor Context Info Records*/
+ __u32 section_length;
+ __u8 affinity_level;
+ __u8 reserved[3]; /* must be zero */
+ __u64 mpidr;
+ __u64 midr;
+ __u32 running_state; /* Bit 0 set - Processor running. PSCI = 0 */
+ __u32 psci_state;
+};
+
+/* ARM Processor Error Information Structure */
+struct cper_arm_err_info {
+ __u8 version;
+ __u8 length;
+ __u16 validation_bits;
+ __u8 type;
+ __u16 multiple_error;
+ __u8 flags;
+ __u64 error_info;
+ __u64 virt_fault_addr;
+ __u64 physical_fault_addr;
+};
+
+/* ARM Processor Context Information Structure */
+struct cper_arm_ctx_info {
+ __u16 version;
+ __u16 type;
+ __u32 size;
+};
+
/* Old Memory Error Section UEFI 2.1, 2.2 */
struct cper_sec_mem_err_old {
__u64 validation_bits;
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
SEA exceptions are often caused by an uncorrected hardware
error, and are handled when data abort and instruction abort
exception classes have specific values for their Fault Status
Code.
When SEA occurs, before killing the process, go through
the handlers registered in the notification list.
Update fault_info[] with specific SEA faults so that the
new SEA handler is used.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
---
arch/arm64/include/asm/system_misc.h | 13 ++++++++
arch/arm64/mm/fault.c | 58 +++++++++++++++++++++++++++++-------
2 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index 57f110b..e7f3440 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -64,4 +64,17 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
#endif /* __ASSEMBLY__ */
+/*
+ * The functions below are used to register and unregister callbacks
+ * that are to be invoked when a Synchronous External Abort (SEA)
+ * occurs. An SEA is raised by certain fault status codes that have
+ * either data or instruction abort as the exception class, and
+ * callbacks may be registered to parse or handle such hardware errors.
+ *
+ * Registered callbacks are run in an interrupt/atomic context. They
+ * are not allowed to block or sleep.
+ */
+int register_sea_notifier(struct notifier_block *nb);
+void unregister_sea_notifier(struct notifier_block *nb);
+
#endif /* __ASM_SYSTEM_MISC_H */
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 05d2bd7..81039c7 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -39,6 +39,22 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
+/*
+ * GHES SEA handler code may register a notifier call here to
+ * handle HW error record passed from platform.
+ */
+static ATOMIC_NOTIFIER_HEAD(sea_handler_chain);
+
+int register_sea_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&sea_handler_chain, nb);
+}
+
+void unregister_sea_notifier(struct notifier_block *nb)
+{
+ atomic_notifier_chain_unregister(&sea_handler_chain, nb);
+}
+
static const char *fault_name(unsigned int esr);
#ifdef CONFIG_KPROBES
@@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
return 1;
}
+/*
+ * This abort handler deals with Synchronous External Abort.
+ * It calls notifiers, and then returns "fault".
+ */
+static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+{
+ struct siginfo info;
+
+ atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
+
+ pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
+ fault_name(esr), esr, addr);
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = 0;
+ info.si_addr = (void __user *)addr;
+ arm64_notify_die("", regs, &info, esr);
+
+ return 0;
+}
+
static const struct fault_info {
int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
int sig;
@@ -502,22 +540,22 @@ static const struct fault_info {
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
- { do_bad, SIGBUS, 0, "synchronous external abort" },
+ { do_sea, SIGBUS, 0, "synchronous external abort" },
{ do_bad, SIGBUS, 0, "unknown 17" },
{ do_bad, SIGBUS, 0, "unknown 18" },
{ do_bad, SIGBUS, 0, "unknown 19" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error" },
+ { do_sea, SIGBUS, 0, "level 0 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 1 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 2 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 3 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "synchronous parity or ECC err" },
{ do_bad, SIGBUS, 0, "unknown 25" },
{ do_bad, SIGBUS, 0, "unknown 26" },
{ do_bad, SIGBUS, 0, "unknown 27" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 0 synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 1 synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 2 synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 3 synchronous parity error (translation table walk)" },
{ do_bad, SIGBUS, 0, "unknown 32" },
{ do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
{ do_bad, SIGBUS, 0, "unknown 34" },
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
ARM APEI extension proposal added SEA (Synchrounous External
Abort) notification type for ARMv8.
Add a new GHES error source handling function for SEA. If an error
source's notification type is SEA, then this function can be registered
into the SEA exception handler. That way GHES will parse and report
SEA exceptions when they occur.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
---
arch/arm64/Kconfig | 2 ++
drivers/acpi/apei/Kconfig | 14 ++++++++
drivers/acpi/apei/ghes.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 100 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b380c87..0465601 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -53,6 +53,8 @@ config ARM64
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND
select HAVE_ACPI_APEI if (ACPI && EFI)
+ select HAVE_ACPI_APEI_SEA if (ACPI && EFI)
+ select HAVE_NMI if HAVE_ACPI_APEI_SEA
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_BITREVERSE
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index b0140c8..3786ff1 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -4,6 +4,20 @@ config HAVE_ACPI_APEI
config HAVE_ACPI_APEI_NMI
bool
+config HAVE_ACPI_APEI_SEA
+ bool "APEI Synchronous External Abort logging/recovering support"
+ depends on ARM64
+ help
+ This option should be enabled if the system supports
+ firmware first handling of SEA (Synchronous External Abort).
+ SEA happens with certain faults of data abort or instruction
+ abort synchronous exceptions on ARMv8 systems. If a system
+ supports firmware first handling of SEA, the platform analyzes
+ and handles hardware error notifications with SEA, and it may then
+ form a HW error record for the OS to parse and handle. This
+ option allows the OS to look for such HW error record, and
+ take appropriate action.
+
config ACPI_APEI
bool "ACPI Platform Error Interface (APEI)"
select MISC_FILESYSTEMS
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 2acbc60..87efe26 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -44,12 +44,17 @@
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/nmi.h>
+#include <linux/hardirq.h>
#include <acpi/actbl1.h>
#include <acpi/ghes.h>
#include <acpi/apei.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_HAVE_ACPI_APEI_SEA
+#include <asm/system_misc.h>
+#endif
+
#include "apei-internal.h"
#define GHES_PFX "GHES: "
@@ -767,6 +772,62 @@ static struct notifier_block ghes_notifier_sci = {
.notifier_call = ghes_notify_sci,
};
+#ifdef CONFIG_HAVE_ACPI_APEI_SEA
+static LIST_HEAD(ghes_sea);
+
+static int ghes_notify_sea(struct notifier_block *this,
+ unsigned long event, void *data)
+{
+ struct ghes *ghes;
+ int ret = NOTIFY_DONE;
+
+ nmi_enter();
+ list_for_each_entry_rcu(ghes, &ghes_sea, list) {
+ if (!ghes_proc(ghes))
+ ret = NOTIFY_OK;
+ }
+ nmi_exit();
+
+ return ret;
+}
+
+static struct notifier_block ghes_notifier_sea = {
+ .notifier_call = ghes_notify_sea,
+};
+
+static int ghes_sea_add(struct ghes *ghes)
+{
+ mutex_lock(&ghes_list_mutex);
+ if (list_empty(&ghes_sea))
+ register_sea_notifier(&ghes_notifier_sea);
+ list_add_rcu(&ghes->list, &ghes_sea);
+ mutex_unlock(&ghes_list_mutex);
+ return 0;
+}
+
+static void ghes_sea_remove(struct ghes *ghes)
+{
+ mutex_lock(&ghes_list_mutex);
+ list_del_rcu(&ghes->list);
+ if (list_empty(&ghes_sea))
+ unregister_sea_notifier(&ghes_notifier_sea);
+ mutex_unlock(&ghes_list_mutex);
+}
+#else /* CONFIG_HAVE_ACPI_APEI_SEA */
+static inline int ghes_sea_add(struct ghes *ghes)
+{
+ pr_err(GHES_PFX "ID: %d, trying to add SEA notification which is not supported\n",
+ ghes->generic->header.source_id);
+ return -ENOTSUPP;
+}
+
+static inline void ghes_sea_remove(struct ghes *ghes)
+{
+ pr_err(GHES_PFX "ID: %d, trying to remove SEA notification which is not supported\n",
+ ghes->generic->header.source_id);
+}
+#endif /* CONFIG_HAVE_ACPI_APEI_SEA */
+
#ifdef CONFIG_HAVE_ACPI_APEI_NMI
/*
* printk is not safe in NMI context. So in NMI handler, we allocate
@@ -1011,6 +1072,14 @@ static int ghes_probe(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_EXTERNAL:
case ACPI_HEST_NOTIFY_SCI:
break;
+ case ACPI_HEST_NOTIFY_SEA:
+ if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_SEA)) {
+ pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEA is not supported\n",
+ generic->header.source_id);
+ rc = -ENOTSUPP;
+ goto err;
+ }
+ break;
case ACPI_HEST_NOTIFY_NMI:
if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) {
pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n",
@@ -1022,6 +1091,13 @@ static int ghes_probe(struct platform_device *ghes_dev)
pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
generic->header.source_id);
goto err;
+ case ACPI_HEST_NOTIFY_GPIO:
+ case ACPI_HEST_NOTIFY_SEI:
+ case ACPI_HEST_NOTIFY_GSIV:
+ pr_warn(GHES_PFX "Generic hardware error source: %d notified via notification type %u is not supported\n",
+ generic->header.source_id, generic->header.source_id);
+ rc = -ENOTSUPP;
+ goto err;
default:
pr_warning(FW_WARN GHES_PFX "Unknown notification type: %u for generic hardware error source: %d\n",
generic->notify.type, generic->header.source_id);
@@ -1076,6 +1152,11 @@ static int ghes_probe(struct platform_device *ghes_dev)
list_add_rcu(&ghes->list, &ghes_sci);
mutex_unlock(&ghes_list_mutex);
break;
+ case ACPI_HEST_NOTIFY_SEA:
+ rc = ghes_sea_add(ghes);
+ if (rc)
+ goto err_edac_unreg;
+ break;
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_add(ghes);
break;
@@ -1118,6 +1199,9 @@ static int ghes_remove(struct platform_device *ghes_dev)
unregister_acpi_hed_notifier(&ghes_notifier_sci);
mutex_unlock(&ghes_list_mutex);
break;
+ case ACPI_HEST_NOTIFY_SEA:
+ ghes_sea_remove(ghes);
+ break;
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_remove(ghes);
break;
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 06/10] acpi: apei: panic OS with fatal error status block
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
From: "Jonathan (Zhixiong) Zhang" <zjzhang@codeaurora.org>
Even if an error status block's severity is fatal, the kernel does not
honor the severity level and panic.
With the firmware first model, the platform could inform the OS about a
fatal hardware error through the non-NMI GHES notification type. The OS
should panic when a hardware error record is received with this
severity.
Call panic() after CPER data in error status block is printed if
severity is fatal, before each error section is handled.
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 87efe26..4e9a20d 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -142,6 +142,8 @@ static unsigned long ghes_estatus_pool_size_request;
static struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
static atomic_t ghes_estatus_cache_alloced;
+static int ghes_panic_timeout __read_mostly = 30;
+
static int ghes_ioremap_init(void)
{
ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES,
@@ -693,6 +695,13 @@ static int ghes_ack_error(struct acpi_hest_generic_v2 *generic_v2)
return rc;
}
+static void __ghes_call_panic(void)
+{
+ if (panic_timeout == 0)
+ panic_timeout = ghes_panic_timeout;
+ panic("Fatal hardware error!");
+}
+
static int ghes_proc(struct ghes *ghes)
{
int rc;
@@ -704,6 +713,10 @@ static int ghes_proc(struct ghes *ghes)
if (ghes_print_estatus(NULL, ghes->generic, ghes->estatus))
ghes_estatus_cache_add(ghes->generic, ghes->estatus);
}
+ if (ghes_severity(ghes->estatus->error_severity) >= GHES_SEV_PANIC) {
+ __ghes_call_panic();
+ }
+
ghes_do_proc(ghes, ghes->estatus);
if (IS_HEST_TYPE_GENERIC_V2(ghes)) {
@@ -848,8 +861,6 @@ static atomic_t ghes_in_nmi = ATOMIC_INIT(0);
static LIST_HEAD(ghes_nmi);
-static int ghes_panic_timeout __read_mostly = 30;
-
static void ghes_proc_in_irq(struct irq_work *irq_work)
{
struct llist_node *llnode, *next;
@@ -942,9 +953,7 @@ static void __ghes_panic(struct ghes *ghes)
__ghes_print_estatus(KERN_EMERG, ghes->generic, ghes->estatus);
/* reboot to log the error! */
- if (panic_timeout == 0)
- panic_timeout = ghes_panic_timeout;
- panic("Fatal hardware error!");
+ __ghes_call_panic();
}
static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 07/10] efi: print unrecognized CPER section
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
UEFI spec allows for non-standard section in Common Platform Error
Record. This is defined in section N.2.3 of UEFI version 2.5.
Currently if the CPER section's type (UUID) does not match with
one of the section types that the kernel knows how to parse, the
section is skipped. Therefore, user is not able to see
such CPER data, for instance, error record of non-standard section.
For above mentioned case, this change prints out the raw data in
hex in dmesg buffer. Data length is taken from Error Data length
field of Generic Error Data Entry.
Following is a sample output from dmesg:
[ 115.771702] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
[ 115.779042] {1}[Hardware Error]: It has been corrected by h/w and requires no further action
[ 115.787456] {1}[Hardware Error]: event severity: corrected
[ 115.792927] {1}[Hardware Error]: Error 0, type: corrected
[ 115.798415] {1}[Hardware Error]: fru_id: 00000000-0000-0000-0000-000000000000
[ 115.805596] {1}[Hardware Error]: fru_text:
[ 115.816105] {1}[Hardware Error]: section type: d2e2621c-f936-468d-0d84-15a4ed015c8b
[ 115.823880] {1}[Hardware Error]: section length: 88
[ 115.828779] {1}[Hardware Error]: 00000000: 01000001 00000002 5f434345 525f4543
[ 115.836153] {1}[Hardware Error]: 00000010: 0000574d 00000000 00000000 00000000
[ 115.843531] {1}[Hardware Error]: 00000020: 00000000 00000000 00000000 00000000
[ 115.850908] {1}[Hardware Error]: 00000030: 00000000 00000000 00000000 00000000
[ 115.858288] {1}[Hardware Error]: 00000040: fe800000 00000000 00000004 5f434345
[ 115.865665] {1}[Hardware Error]: 00000050: 525f4543 0000574d
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
---
drivers/firmware/efi/cper.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index c2b0a12..48cb8ee 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -591,8 +591,16 @@ static void cper_estatus_print_section(
cper_print_proc_arm(newpfx, arm_err);
else
goto err_section_too_small;
- } else
- printk("%s""section type: unknown, %pUl\n", newpfx, sec_type);
+ } else {
+ const void *unknown_err;
+
+ unknown_err = acpi_hest_generic_data_payload(gdata);
+ printk("%ssection type: %pUl\n", newpfx, sec_type);
+ printk("%ssection length: %d\n", newpfx,
+ gdata->error_data_length);
+ print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
+ unknown_err, gdata->error_data_length, 0);
+ }
return;
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 08/10] ras: acpi / apei: generate trace event for unrecognized CPER section
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
UEFI spec allows for non-standard section in Common Platform Error
Record. This is defined in section N.2.3 of UEFI version 2.5.
Currently if the CPER section's type (UUID) does not match with
any section type that the kernel knows how to parse, trace event
is not generated for such section. And thus user is not able to know
happening of such hardware error, including error record of
non-standard section.
This commit generates a trace event which contains raw error data
for unrecognized CPER section.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 22 ++++++++++++++++++++--
drivers/ras/ras.c | 1 +
include/ras/ras_event.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 4e9a20d..a32c1b1 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -45,11 +45,13 @@
#include <linux/aer.h>
#include <linux/nmi.h>
#include <linux/hardirq.h>
+#include <linux/uuid.h>
#include <acpi/actbl1.h>
#include <acpi/ghes.h>
#include <acpi/apei.h>
#include <asm/tlbflush.h>
+#include <ras/ras_event.h>
#ifdef CONFIG_HAVE_ACPI_APEI_SEA
#include <asm/system_misc.h>
@@ -458,11 +460,21 @@ static void ghes_do_proc(struct ghes *ghes,
{
int sev, sec_sev;
struct acpi_hest_generic_data *gdata;
+ uuid_le sec_type;
+ uuid_le *fru_id = &NULL_UUID_LE;
+ char *fru_text = "";
sev = ghes_severity(estatus->error_severity);
apei_estatus_for_each_section(estatus, gdata) {
sec_sev = ghes_severity(gdata->error_severity);
- if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
+ sec_type = *(uuid_le *)gdata->section_type;
+
+ if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
+ fru_id = (uuid_le *)gdata->fru_id;
+ if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
+ fru_text = gdata->fru_text;
+
+ if (!uuid_le_cmp(sec_type,
CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err;
@@ -473,7 +485,7 @@ static void ghes_do_proc(struct ghes *ghes,
ghes_handle_memory_failure(gdata, sev);
}
#ifdef CONFIG_ACPI_APEI_PCIEAER
- else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
+ else if (!uuid_le_cmp(sec_type,
CPER_SEC_PCIE)) {
struct cper_sec_pcie *pcie_err;
@@ -506,6 +518,12 @@ static void ghes_do_proc(struct ghes *ghes,
}
#endif
+ else {
+ void *unknown_err = acpi_hest_generic_data_payload(gdata);
+ trace_unknown_sec_event(&sec_type,
+ fru_id, fru_text, sec_sev,
+ unknown_err, gdata->error_data_length);
+ }
}
}
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index b67dd36..fb2500b 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -27,3 +27,4 @@ subsys_initcall(ras_init);
EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
#endif
EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
+EXPORT_TRACEPOINT_SYMBOL_GPL(unknown_sec_event);
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 1791a12..5861b6f 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -162,6 +162,51 @@ TRACE_EVENT(mc_event,
);
/*
+ * Unknown Section Report
+ *
+ * This event is generated when hardware detected a hardware
+ * error event, which may be of non-standard section as defined
+ * in UEFI spec appendix "Common Platform Error Record", or may
+ * be of sections for which TRACE_EVENT is not defined.
+ *
+ */
+TRACE_EVENT(unknown_sec_event,
+
+ TP_PROTO(const uuid_le *sec_type,
+ const uuid_le *fru_id,
+ const char *fru_text,
+ const u8 sev,
+ const u8 *err,
+ const u32 len),
+
+ TP_ARGS(sec_type, fru_id, fru_text, sev, err, len),
+
+ TP_STRUCT__entry(
+ __array(char, sec_type, 16)
+ __array(char, fru_id, 16)
+ __string(fru_text, fru_text)
+ __field(u8, sev)
+ __field(u32, len)
+ __dynamic_array(u8, buf, len)
+ ),
+
+ TP_fast_assign(
+ memcpy(__entry->sec_type, sec_type, sizeof(uuid_le));
+ memcpy(__entry->fru_id, fru_id, sizeof(uuid_le));
+ __assign_str(fru_text, fru_text);
+ __entry->sev = sev;
+ __entry->len = len;
+ memcpy(__get_dynamic_array(buf), err, len);
+ ),
+
+ TP_printk("severity: %d; sec type:%pU; FRU: %pU %s; data len:%d; raw data:%s",
+ __entry->sev, __entry->sec_type,
+ __entry->fru_id, __get_str(fru_text),
+ __entry->len,
+ __print_hex(__get_dynamic_array(buf), __entry->len))
+);
+
+/*
* PCIe AER Trace event
*
* These events are generated when hardware detects a corrected or
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 09/10] trace, ras: add ARM processor error trace event
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
Currently there are trace events for the various RAS
errors with the exception of ARM processor type errors.
Add a new trace event for such errors so that the user
will know when they occur. These trace events are
consistent with the ARM processor error section type
defined in UEFI 2.6 spec section N.2.4.4.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
---
drivers/acpi/apei/ghes.c | 7 ++++++-
drivers/firmware/efi/cper.c | 1 +
drivers/ras/ras.c | 1 +
include/ras/ras_event.h | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index a32c1b1..324a032 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -518,7 +518,12 @@ static void ghes_do_proc(struct ghes *ghes,
}
#endif
- else {
+ else if (!uuid_le_cmp(sec_type, CPER_SEC_PROC_ARM)) {
+ struct cper_sec_proc_arm *arm_err;
+
+ arm_err = acpi_hest_generic_data_payload(gdata);
+ trace_arm_event(arm_err);
+ } else {
void *unknown_err = acpi_hest_generic_data_payload(gdata);
trace_unknown_sec_event(&sec_type,
fru_id, fru_text, sec_sev,
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 48cb8ee..0ec678e 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -35,6 +35,7 @@
#include <linux/printk.h>
#include <linux/bcd.h>
#include <acpi/ghes.h>
+#include <ras/ras_event.h>
#define INDENT_SP " "
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index fb2500b..8ba5a94 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -28,3 +28,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
#endif
EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
EXPORT_TRACEPOINT_SYMBOL_GPL(unknown_sec_event);
+EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event);
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 5861b6f..b36db48 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -162,6 +162,40 @@ TRACE_EVENT(mc_event,
);
/*
+ * ARM Processor Events Report
+ *
+ * This event is generated when hardware detects an ARM processor error
+ * has occurred. UEFI 2.6 spec section N.2.4.4.
+ */
+TRACE_EVENT(arm_event,
+
+ TP_PROTO(const struct cper_sec_proc_arm *proc),
+
+ TP_ARGS(proc),
+
+ TP_STRUCT__entry(
+ __field(u64, mpidr)
+ __field(u64, midr)
+ __field(u32, running_state)
+ __field(u32, psci_state)
+ __field(u8, affinity)
+ ),
+
+ TP_fast_assign(
+ __entry->affinity = proc->affinity_level;
+ __entry->mpidr = proc->mpidr;
+ __entry->midr = proc->midr;
+ __entry->running_state = proc->running_state;
+ __entry->psci_state = proc->psci_state;
+ ),
+
+ TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
+ "running state: %d; PSCI state: %d",
+ __entry->affinity, __entry->mpidr, __entry->midr,
+ __entry->running_state, __entry->psci_state)
+);
+
+/*
* Unknown Section Report
*
* This event is generated when hardware detected a hardware
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
* [PATCH V7 10/10] arm/arm64: KVM: add guest SEA support
From: Tyler Baicar @ 2017-01-12 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484244924-24786-1-git-send-email-tbaicar@codeaurora.org>
Currently external aborts are unsupported by the guest abort
handling. Add handling for SEAs so that the host kernel reports
SEAs which occur in the guest kernel.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
---
arch/arm/include/asm/kvm_arm.h | 1 +
arch/arm/include/asm/system_misc.h | 5 +++++
arch/arm/kvm/mmu.c | 18 ++++++++++++++++--
arch/arm64/include/asm/kvm_arm.h | 1 +
arch/arm64/include/asm/system_misc.h | 2 ++
arch/arm64/mm/fault.c | 13 +++++++++++++
6 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index e22089f..33a77509 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -187,6 +187,7 @@
#define FSC_FAULT (0x04)
#define FSC_ACCESS (0x08)
#define FSC_PERM (0x0c)
+#define FSC_EXTABT (0x10)
/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
#define HPFAR_MASK (~0xf)
diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
index a3d61ad..ea45d94 100644
--- a/arch/arm/include/asm/system_misc.h
+++ b/arch/arm/include/asm/system_misc.h
@@ -24,4 +24,9 @@ extern unsigned int user_debug;
#endif /* !__ASSEMBLY__ */
+static inline int handle_guest_sea(unsigned long addr, unsigned int esr)
+{
+ return -1;
+}
+
#endif /* __ASM_ARM_SYSTEM_MISC_H */
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index e9a5c0e..1152966 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -29,6 +29,7 @@
#include <asm/kvm_asm.h>
#include <asm/kvm_emulate.h>
#include <asm/virt.h>
+#include <asm/system_misc.h>
#include "trace.h"
@@ -1441,8 +1442,21 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
/* Check the stage-2 fault is trans. fault or write fault */
fault_status = kvm_vcpu_trap_get_fault_type(vcpu);
- if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
- fault_status != FSC_ACCESS) {
+
+ /* The host kernel will handle the synchronous external abort. There
+ * is no need to pass the error into the guest.
+ */
+ if (fault_status == FSC_EXTABT) {
+ if(handle_guest_sea((unsigned long)fault_ipa,
+ kvm_vcpu_get_hsr(vcpu))) {
+ kvm_err("Failed to handle guest SEA, FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
+ kvm_vcpu_trap_get_class(vcpu),
+ (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
+ (unsigned long)kvm_vcpu_get_hsr(vcpu));
+ return -EFAULT;
+ }
+ } else if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
+ fault_status != FSC_ACCESS) {
kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
kvm_vcpu_trap_get_class(vcpu),
(unsigned long)kvm_vcpu_trap_get_fault(vcpu),
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 4b5c977..be0efb6 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -201,6 +201,7 @@
#define FSC_FAULT ESR_ELx_FSC_FAULT
#define FSC_ACCESS ESR_ELx_FSC_ACCESS
#define FSC_PERM ESR_ELx_FSC_PERM
+#define FSC_EXTABT ESR_ELx_FSC_EXTABT
/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
#define HPFAR_MASK (~UL(0xf))
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index e7f3440..27816cb 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -77,4 +77,6 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
int register_sea_notifier(struct notifier_block *nb);
void unregister_sea_notifier(struct notifier_block *nb);
+int handle_guest_sea(unsigned long addr, unsigned int esr);
+
#endif /* __ASM_SYSTEM_MISC_H */
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 81039c7..fa8d4d7 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -597,6 +597,19 @@ static const char *fault_name(unsigned int esr)
}
/*
+ * Handle Synchronous External Aborts that occur in a guest kernel.
+ */
+int handle_guest_sea(unsigned long addr, unsigned int esr)
+{
+ atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
+
+ pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
+ fault_name(esr), esr, addr);
+
+ return 0;
+}
+
+/*
* Dispatch a data abort to the relevant handler.
*/
asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox