Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] PCI: Add information about describing PCI in ACPI
From: Bjorn Helgaas @ 2016-11-17 17:59 UTC (permalink / raw)
  To: linux-arm-kernel

Add a writeup about how PCI host bridges should be described in ACPI
using PNP0A03/PNP0A08 devices, PNP0C02 devices, and the MCFG table.

Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 Documentation/PCI/00-INDEX      |    2 +
 Documentation/PCI/acpi-info.txt |  136 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+)
 create mode 100644 Documentation/PCI/acpi-info.txt

diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
index 147231f..0780280 100644
--- a/Documentation/PCI/00-INDEX
+++ b/Documentation/PCI/00-INDEX
@@ -1,5 +1,7 @@
 00-INDEX
 	- this file
+acpi-info.txt
+	- info on how PCI host bridges are represented in ACPI
 MSI-HOWTO.txt
 	- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
 PCIEBUS-HOWTO.txt
diff --git a/Documentation/PCI/acpi-info.txt b/Documentation/PCI/acpi-info.txt
new file mode 100644
index 0000000..ccbcfda
--- /dev/null
+++ b/Documentation/PCI/acpi-info.txt
@@ -0,0 +1,136 @@
+	    ACPI considerations for PCI host bridges
+
+The basic requirement is that the ACPI namespace should describe
+*everything* that consumes address space unless there's another
+standard way for the OS to find it [1, 2]. ?For example, windows that
+are forwarded to PCI by a PCI host bridge should be described via ACPI
+devices, since the OS can't locate the host bridge by itself. ?PCI
+devices *below* the host bridge do not need to be described via ACPI,
+because the resources they consume are inside the host bridge windows,
+and the OS can discover them via the standard PCI enumeration
+mechanism (using config accesses to read and size the BARs).
+
+This ACPI resource description is done via _CRS methods of devices in
+the ACPI namespace [2]. ? _CRS methods are like generalized PCI BARs:
+the OS can read _CRS and figure out what resource is being consumed
+even if it doesn't have a driver for the device [3]. ?That's important
+because it means an old OS can work correctly even on a system with
+new devices unknown to the OS. ?The new devices won't do anything, but
+the OS can at least make sure no resources conflict with them.
+
+Static tables like MCFG, HPET, ECDT, etc., are *not* mechanisms for
+reserving address space!  The static tables are for things the OS
+needs to know early in boot, before it can parse the ACPI namespace.
+If a new table is defined, an old OS needs to operate correctly even
+though it ignores the table.  _CRS allows that because it is generic
+and understood by the old OS; a static table does not.
+
+If the OS is expected to manage an ACPI device, that device will have
+a specific _HID/_CID that tells the OS what driver to bind to it, and
+the _CRS tells the OS and the driver where the device's registers are.
+
+PNP0C02 "motherboard" devices are basically a catch-all. ?There's no
+programming model for them other than "don't use these resources for
+anything else." ?So any address space that is (1) not claimed by some
+other ACPI device and (2) should not be assigned by the OS to
+something else, should be claimed by a PNP0C02 _CRS method.
+
+PCI host bridges are PNP0A03 or PNP0A08 devices. ?Their _CRS should
+describe all the address space they consume. ?In principle, this would
+be all the windows they forward down to the PCI bus, as well as the
+bridge registers themselves. ?The bridge registers include things like
+secondary/subordinate bus registers that determine the bus range below
+the bridge, window registers that describe the apertures, etc. ?These
+are all device-specific, non-architected things, so the only way a
+PNP0A03/PNP0A08 driver can manage them is via _PRS/_CRS/_SRS, which
+contain the device-specific details. ?These bridge registers also
+include ECAM space, since it is consumed by the bridge.
+
+ACPI defined a Producer/Consumer bit that was intended to distinguish
+the bridge apertures from the bridge registers [4, 5]. ?However,
+BIOSes didn't use that bit correctly, and the result is that OSes have
+to assume that everything in a PCI host bridge _CRS is a window. ?That
+leaves no way to describe the bridge registers in the PNP0A03/PNP0A08
+device itself.
+
+The workaround is to describe the bridge registers (including ECAM
+space) in PNP0C02 catch-all devices [6]. ?With the exception of ECAM,
+the bridge register space is device-specific anyway, so the generic
+PNP0A03/PNP0A08 driver (pci_root.c) has no need to know about it. ?For
+ECAM, pci_root.c learns about the space from either MCFG or the _CBA
+method.
+
+Note that the PCIe spec actually does require ECAM unless there's a
+standard firmware interface for config access, e.g., the ia64 SAL
+interface [7].  One reason is that we want a generic host bridge
+driver (pci_root.c), and a generic driver requires a generic way to
+access config space.
+
+
+[1] ACPI 6.0, sec 6.1:
+    For any device that is on a non-enumerable type of bus (for
+    example, an ISA bus), OSPM enumerates the devices' identifier(s)
+    and the ACPI system firmware must supply an _HID object ... for
+    each device to enable OSPM to do that.
+
+[2] ACPI 6.0, sec 3.7:
+    The OS enumerates motherboard devices simply by reading through
+    the ACPI Namespace looking for devices with hardware IDs.
+
+    Each device enumerated by ACPI includes ACPI-defined objects in
+    the ACPI Namespace that report the hardware resources the device
+    could occupy [_PRS], an object that reports the resources that are
+    currently used by the device [_CRS], and objects for configuring
+    those resources [_SRS].  The information is used by the Plug and
+    Play OS (OSPM) to configure the devices.
+
+[3] ACPI 6.0, sec 6.2:
+    OSPM uses device configuration objects to configure hardware
+    resources for devices enumerated via ACPI.  Device configuration
+    objects provide information about current and possible resource
+    requirements, the relationship between shared resources, and
+    methods for configuring hardware resources.
+
+    When OSPM enumerates a device, it calls _PRS to determine the
+    resource requirements of the device.  It may also call _CRS to
+    find the current resource settings for the device.  Using this
+    information, the Plug and Play system determines what resources
+    the device should consume and sets those resources by calling the
+    device?s _SRS control method.
+
+    In ACPI, devices can consume resources (for example, legacy
+    keyboards), provide resources (for example, a proprietary PCI
+    bridge), or do both.  Unless otherwise specified, resources for a
+    device are assumed to be taken from the nearest matching resource
+    above the device in the device hierarchy.
+
+[4] ACPI 6.0, sec 6.4.3.5.4:
+    Extended Address Space Descriptor
+    General Flags: Bit [0] Consumer/Producer:
+	1?This device consumes this resource
+	0?This device produces and consumes this resource
+
+[5] ACPI 6.0, sec 19.6.43:
+    ResourceUsage specifies whether the Memory range is consumed by
+    this device (ResourceConsumer) or passed on to child devices
+    (ResourceProducer).  If nothing is specified, then
+    ResourceConsumer is assumed.
+
+[6] PCI Firmware 3.0, sec 4.1.2:
+    If the operating system does not natively comprehend reserving the
+    MMCFG region, the MMCFG region must be reserved by firmware.  The
+    address range reported in the MCFG table or by _CBA method (see
+    Section 4.1.3) must be reserved by declaring a motherboard
+    resource.  For most systems, the motherboard resource would appear
+    at the root of the ACPI namespace (under \_SB) in a node with a
+    _HID of EISAID (PNP0C02), and the resources in this case should
+    not be claimed in the root PCI bus?s _CRS.  The resources can
+    optionally be returned in Int15 E820 or EFIGetMemoryMap as
+    reserved memory but must always be reported through ACPI as a
+    motherboard resource.
+
+[7] PCI Express 3.0, sec 7.2.2:
+    For systems that are PC-compatible, or that do not implement a
+    processor-architecture-specific firmware interface standard that
+    allows access to the Configuration Space, the ECAM is required as
+    defined in this section.

^ permalink raw reply related

* [PATCH 8/9] arm64: tegra: Enable PSCI on P3310
From: Thierry Reding @ 2016-11-17 17:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <786f354d-a1f2-f2c6-fde7-7b1af3df756c@arm.com>

On Thu, Nov 17, 2016 at 05:21:34PM +0000, Sudeep Holla wrote:
> 
> 
> On 17/11/16 17:11, Thierry Reding wrote:
> > From: Thierry Reding <treding@nvidia.com>
> > 
> > The P3310 processor module comes ships with a firmware that implements
> > PSCI 1.0. Enable and use it to bring up all CPUs.
> > 
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >  arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 36 ++++++++++++++++++++++++++
> >  1 file changed, 36 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
> > index 807af7b68761..2c158c6809a5 100644
> > --- a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
> > +++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
> > @@ -26,7 +26,43 @@
> >  		status = "okay";
> >  	};
> > 
> > +	cpus {
> > +		cpu at 0 {
> > +			enable-method = "psci";
> > +		};
> > +
> > +		cpu at 1 {
> > +			enable-method = "psci";
> > +		};
> > +
> > +		cpu at 2 {
> > +			enable-method = "psci";
> > +		};
> > +
> > +		cpu at 3 {
> > +			enable-method = "psci";
> > +		};
> > +
> > +		cpu at 4 {
> > +			enable-method = "psci";
> > +		};
> > +
> > +		cpu at 5 {
> > +			enable-method = "psci";
> > +		};
> > +	};
> > +
> >  	bpmp {
> >  		status = "okay";
> >  	};
> > +
> > +	psci {
> > +		compatible = "arm,psci-1.0";
> > +		status = "okay";
> > +		method = "smc";
> 
> [...]
> 
> > +
> > +		cpu_off = <0x84000002>;
> > +		cpu_on = <0xc4000003>;
> > +		cpu_suspend = <0xc4000001>;
> 
> These are applicable only for "arm,psci"(i.e. PSCI v0.1), so you need to
> drop them.

Oh, indeed. I obviously skipped the arm,psci and arm,psci-0.2 entries in
the binding documentation and then assumed the optional properties
applied regardless of PSCI version.

Removed these and everything still works as expected.

Thanks,
Thierry
-------------- 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/20161117/e20a846e/attachment.sig>

^ permalink raw reply

* Boot failures in -next due to 'ARM: dts: imx: Remove skeleton.dtsi'
From: Guenter Roeck @ 2016-11-17 17:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117163906.GB21742@leverpostej>

On 11/17/2016 08:39 AM, Mark Rutland wrote:
> On Thu, Nov 17, 2016 at 08:17:00AM -0800, Guenter Roeck wrote:
>> On 11/17/2016 07:05 AM, Mark Rutland wrote:
>>> On Thu, Nov 17, 2016 at 06:44:55AM -0800, Guenter Roeck wrote:
>>>> On 11/17/2016 02:55 AM, Mark Rutland wrote:
>>>>> Memory nodes require this property per ePAPR and the devicetree.org
>>>>> spec, so the bug is that we didn't add those when removing the
>>>>> skeleton.dtsi include.
>>>>
>>>> The downside from qemu perspective is that the real hardware seems
>>>> to add the property unconditionally, or the boot failure would have
>>>> been seen there as well.
>>>>
>>>> I submitted https://patchwork.ozlabs.org/patch/695951/; we'll see how it goes.
>>>
>>> Sure, the firmare/bootlaoder you're using may add this automatically.
>>>
>>> My worry is that adding this to a generic file in QEMU only serves to
>>> mask this class of bug for other boards (i.e. they'll work fine in QEMU,
>>> but not on real HW using whatever bootlaoder happens ot be there).
>>>
>> Good point.
>>
>> What would be the correct behavior for qemu ? Adding a chosen node if it does
>> not exist is one detail we already established. Also, I think a check if
>> /memory/device_type exists (and to bail out if it doesn't) would make sense.
>
> We'd also need to check for /memory@<n> nodes, as they can validly have
> unit-addresses (and many do).
>
> Generally, the "correct" way to find them is to iterate over all ndoes
> with device_type = "memory", so one could do that and give up if none
> are found, ignoring the naming entirely.
>
>> What about the memory node ? Does it have to exist, or should it be added
>> (including the device_type property) if not ?
>
> I'm not sure what QEMU does in this area. I suspect it may expect a node
> in some cases, or may generate one in others.
>
> There's no point generating one when we don't have the information to
> hand, certainly.
>
So far, for arm, qemu assumes that the /memory node exists, and it fills in
/memory/reg. This is done if a devicetree file is specified and numa is disabled.

Numa node handling is different; if NUMA is enabled, qemu removes an existing
/memory node and creates /memory@ nodes as configured. It does not expect
to see pre-existing /memory@ nodes.

Thanks,
Guenter

^ permalink raw reply

* [PATCH 8/9] arm64: tegra: Enable PSCI on P3310
From: Sudeep Holla @ 2016-11-17 17:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-8-thierry.reding@gmail.com>



On 17/11/16 17:11, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> The P3310 processor module comes ships with a firmware that implements
> PSCI 1.0. Enable and use it to bring up all CPUs.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 36 ++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
> index 807af7b68761..2c158c6809a5 100644
> --- a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
> +++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
> @@ -26,7 +26,43 @@
>  		status = "okay";
>  	};
>
> +	cpus {
> +		cpu at 0 {
> +			enable-method = "psci";
> +		};
> +
> +		cpu at 1 {
> +			enable-method = "psci";
> +		};
> +
> +		cpu at 2 {
> +			enable-method = "psci";
> +		};
> +
> +		cpu at 3 {
> +			enable-method = "psci";
> +		};
> +
> +		cpu at 4 {
> +			enable-method = "psci";
> +		};
> +
> +		cpu at 5 {
> +			enable-method = "psci";
> +		};
> +	};
> +
>  	bpmp {
>  		status = "okay";
>  	};
> +
> +	psci {
> +		compatible = "arm,psci-1.0";
> +		status = "okay";
> +		method = "smc";

[...]

> +
> +		cpu_off = <0x84000002>;
> +		cpu_on = <0xc4000003>;
> +		cpu_suspend = <0xc4000001>;

These are applicable only for "arm,psci"(i.e. PSCI v0.1), so you need to
drop them.

-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCH 9/9] arm64: tegra: Add NVIDIA P2771 board support
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Joseph Lo <josephl@nvidia.com>

The NVIDIA P2771 is composed of a P3310 processor module that connects
to the P2597 I/O board. It comes with a 1200x1920 MIPI DSI panel that is
connected via the P2597's display connector and has several connectors
such as HDMI, USB 3.0, PCIe and ethernet.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/Makefile                | 1 +
 arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts | 8 ++++++++
 2 files changed, 9 insertions(+)
 create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts

diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile
index 0f7cdf3e05c1..18941458cb4d 100644
--- a/arch/arm64/boot/dts/nvidia/Makefile
+++ b/arch/arm64/boot/dts/nvidia/Makefile
@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
+dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb
 
 always		:= $(dtb-y)
 clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
new file mode 100644
index 000000000000..0d3c0996d832
--- /dev/null
+++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+#include "tegra186-p3310.dtsi"
+
+/ {
+	model = "NVIDIA Tegra186 P2771-0000 Development Board";
+	compatible = "nvidia,p2771-0000", "nvidia,tegra186";
+};
-- 
2.10.2

^ permalink raw reply related

* [PATCH 8/9] arm64: tegra: Enable PSCI on P3310
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

The P3310 processor module comes ships with a firmware that implements
PSCI 1.0. Enable and use it to bring up all CPUs.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 36 ++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
index 807af7b68761..2c158c6809a5 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
@@ -26,7 +26,43 @@
 		status = "okay";
 	};
 
+	cpus {
+		cpu at 0 {
+			enable-method = "psci";
+		};
+
+		cpu at 1 {
+			enable-method = "psci";
+		};
+
+		cpu at 2 {
+			enable-method = "psci";
+		};
+
+		cpu at 3 {
+			enable-method = "psci";
+		};
+
+		cpu at 4 {
+			enable-method = "psci";
+		};
+
+		cpu at 5 {
+			enable-method = "psci";
+		};
+	};
+
 	bpmp {
 		status = "okay";
 	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		status = "okay";
+		method = "smc";
+
+		cpu_off = <0x84000002>;
+		cpu_on = <0xc4000003>;
+		cpu_suspend = <0xc4000001>;
+	};
 };
-- 
2.10.2

^ permalink raw reply related

* [PATCH 7/9] arm64: tegra: Add NVIDIA P3310 processor module support
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Joseph Lo <josephl@nvidia.com>

The NVIDIA P3310 is a processor module used in several reference designs
that features a Tegra186 SoC, 8 GiB of LPDDR4 RAM, 32 GiB eMMC and other
essentials such as ethernet, WiFi and a PMIC. It is typically connected
to an I/O board (such as the P2597) that provides the connecters needed
to hook it up to the outside world.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi | 32 ++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi

diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
new file mode 100644
index 000000000000..807af7b68761
--- /dev/null
+++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
@@ -0,0 +1,32 @@
+#include "tegra186.dtsi"
+
+/ {
+	model = "NVIDIA Tegra186 P3310 Processor Module";
+	compatible = "nvidia,p3310", "nvidia,tegra186";
+
+	aliases {
+		serial0 = &uarta;
+	};
+
+	chosen {
+		bootargs = "earlycon console=ttyS0,115200n8";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x2 0x00000000>;
+	};
+
+	serial at 3100000 {
+		status = "okay";
+	};
+
+	hsp at 3c00000 {
+		status = "okay";
+	};
+
+	bpmp {
+		status = "okay";
+	};
+};
-- 
2.10.2

^ permalink raw reply related

* [PATCH 6/9] arm64: tegra: Add GPIO controllers on Tegra186
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

Tegra186 has two GPIO controllers that are no longer compatible with the
controller found on earlier generations. One of these controllers exists
in an always-on partition of the SoC whereas the other can be clock- and
powergated.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 1aca69f24fb0..62fa85ae0271 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1,4 +1,5 @@
 #include <dt-bindings/clock/tegra186-clock.h>
+#include <dt-bindings/gpio/tegra186-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mailbox/tegra186-hsp.h>
 #include <dt-bindings/reset/tegra186-reset.h>
@@ -9,6 +10,23 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	gpio: gpio at 2200000 {
+		compatible = "nvidia,tegra186-gpio";
+		reg-names = "security", "gpio";
+		reg = <0x0 0x2200000 0x0 0x10000>,
+		      <0x0 0x2210000 0x0 0x10000>;
+		interrupts = <GIC_SPI  47 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  50 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  53 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  56 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  59 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
 	uarta: serial at 3100000 {
 		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x03100000 0x0 0x40>;
@@ -277,6 +295,18 @@
 		status = "disabled";
 	};
 
+	gpio_aon: gpio at c2f0000 {
+		compatible = "nvidia,tegra186-gpio-aon";
+		reg-names = "security", "gpio";
+		reg = <0x0 0xc2f0000 0x0 0x1000>,
+		      <0x0 0xc2f1000 0x0 0x1000>;
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
 	sysram at 30000000 {
 		compatible = "nvidia,tegra186-sysram", "mmio-sram";
 		reg = <0x0 0x30000000 0x0 0x50000>;
-- 
2.10.2

^ permalink raw reply related

* [PATCH 5/9] arm64: tegra: Add SDHCI controllers on Tegra186
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

Tegra186 has a total of four SDHCI controllers that each support SD 4.2
(up to UHS-I speed), SDIO 4.1 (up to UHS-I speed), eSD 2.1, eMMC 5.1 and
SDHOST 4.1 (up to UHS-I speed).

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 44 ++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b1a77d78d202..1aca69f24fb0 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -163,6 +163,50 @@
 		status = "disabled";
 	};
 
+	sdmmc1: sdhci at 3400000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03400000 0x0 0x10000>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_SDMMC1>;
+		clock-names = "sdhci";
+		resets = <&bpmp TEGRA186_RESET_SDMMC1>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
+	sdmmc2: sdhci at 3420000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03420000 0x0 0x10000>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_SDMMC2>;
+		clock-names = "sdhci";
+		resets = <&bpmp TEGRA186_RESET_SDMMC2>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
+	sdmmc3: sdhci at 3440000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03440000 0x0 0x10000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_SDMMC3>;
+		clock-names = "sdhci";
+		resets = <&bpmp TEGRA186_RESET_SDMMC3>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
+	sdmmc4: sdhci at 3460000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03460000 0x0 0x10000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_SDMMC4>;
+		clock-names = "sdhci";
+		resets = <&bpmp TEGRA186_RESET_SDMMC4>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
 	gic: interrupt-controller at 3881000 {
 		compatible = "arm,gic-400";
 		#interrupt-cells = <3>;
-- 
2.10.2

^ permalink raw reply related

* [PATCH 4/9] arm64: tegra: Add I2C controllers on Tegra186
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

Tegra186 has a total of nine I2C controllers that are compatible with
the I2C controllers introduced in Tegra114. Two of these controllers
share pads with two DPAUX controllers (for AUX transactions).

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 120 +++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 911f288966ba..b1a77d78d202 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -69,6 +69,100 @@
 		status = "disabled";
 	};
 
+	gen1_i2c: i2c at 3160000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x03160000 0x0 0x10000>;
+		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C1>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C1>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	cam_i2c: i2c at 3180000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x03180000 0x0 0x10000>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C3>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C3>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	/* shares pads with dpaux1 */
+	dp_aux_ch1_i2c: i2c at 3190000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x03190000 0x0 0x10000>;
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C4>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C4>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	/* controlled by BPMP, should not be enabled */
+	pwr_i2c: i2c at 31a0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031a0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C5>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C5>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	/* shares pads with dpaux0 */
+	dp_aux_ch0_i2c: i2c at 31b0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031b0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C6>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C6>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen7_i2c: i2c at 31c0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031c0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C7>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C7>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen9_i2c: i2c at 31e0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031e0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C9>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C9>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
 	gic: interrupt-controller at 3881000 {
 		compatible = "arm,gic-400";
 		#interrupt-cells = <3>;
@@ -89,6 +183,32 @@
 		status = "disabled";
 	};
 
+	gen2_i2c: i2c at c240000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x0c240000 0x0 0x10000>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C2>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C2>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen8_i2c: i2c at c250000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x0c250000 0x0 0x10000>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp TEGRA186_CLK_I2C8>;
+		clock-names = "div-clk";
+		resets = <&bpmp TEGRA186_RESET_I2C8>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
 	uartc: serial at c280000 {
 		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x0c280000 0x0 0x40>;
-- 
2.10.2

^ permalink raw reply related

* [PATCH 3/9] arm64: tegra: Add serial ports on Tegra186
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

The initial patch only added UARTA, but there's no reason we shouldn't
be adding all of them. While at it, also specify the missing clocks and
resets for UARTA.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 78 ++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index eadbfacd16c2..911f288966ba 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1,5 +1,7 @@
+#include <dt-bindings/clock/tegra186-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mailbox/tegra186-hsp.h>
+#include <dt-bindings/reset/tegra186-reset.h>
 
 / {
 	compatible = "nvidia,tegra186";
@@ -12,6 +14,58 @@
 		reg = <0x0 0x03100000 0x0 0x40>;
 		reg-shift = <2>;
 		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_UARTA>;
+		clock-names = "serial";
+		resets = <&bpmp TEGRA186_RESET_UARTA>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartb: serial at 3110000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03110000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_UARTB>;
+		clock-names = "serial";
+		resets = <&bpmp TEGRA186_RESET_UARTB>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartd: serial at 3130000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03130000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_UARTD>;
+		clock-names = "serial";
+		resets = <&bpmp TEGRA186_RESET_UARTD>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uarte: serial at 3140000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03140000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_UARTE>;
+		clock-names = "serial";
+		resets = <&bpmp TEGRA186_RESET_UARTE>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartf: serial at 3150000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03150000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_UARTF>;
+		clock-names = "serial";
+		resets = <&bpmp TEGRA186_RESET_UARTF>;
+		reset-names = "serial";
 		status = "disabled";
 	};
 
@@ -35,6 +89,30 @@
 		status = "disabled";
 	};
 
+	uartc: serial at c280000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x0c280000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_UARTC>;
+		clock-names = "serial";
+		resets = <&bpmp TEGRA186_RESET_UARTC>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartg: serial at c290000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x0c290000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp TEGRA186_CLK_UARTG>;
+		clock-names = "serial";
+		resets = <&bpmp TEGRA186_RESET_UARTG>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
 	sysram at 30000000 {
 		compatible = "nvidia,tegra186-sysram", "mmio-sram";
 		reg = <0x0 0x30000000 0x0 0x50000>;
-- 
2.10.2

^ permalink raw reply related

* [PATCH 2/9] arm64: tegra: Add CPU nodes for Tegra186
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117171131.20062-1-thierry.reding@gmail.com>

From: Thierry Reding <treding@nvidia.com>

Tegra186 has six CPUs: two CPUs are second generation Denver CPUs that
support ARMv8 and four CPUs are Cortex-A57 CPUs.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 41 ++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 6cb8ac918530..eadbfacd16c2 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -57,6 +57,47 @@
 		};
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			compatible = "nvidia,tegra186-denver", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x000>;
+		};
+
+		cpu at 1 {
+			compatible = "nvidia,tegra186-denver", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x001>;
+		};
+
+		cpu at 2 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x100>;
+		};
+
+		cpu at 3 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x101>;
+		};
+
+		cpu at 4 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x102>;
+		};
+
+		cpu at 5 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x103>;
+		};
+	};
+
 	bpmp: bpmp {
 		compatible = "nvidia,tegra186-bpmp";
 		mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB
-- 
2.10.2

^ permalink raw reply related

* [PATCH 1/9] arm64: tegra: Add Tegra186 support
From: Thierry Reding @ 2016-11-17 17:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Joseph Lo <josephl@nvidia.com>

This adds the initial support of Tegra186 SoC. It provides enough to
enable the serial console and boot from an initial ramdisk.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
[treding at nvidia.com: remove leading 0 from unit-addresses]
[treding at nvidia.com: remove unused nvidia,bpmp property]
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 89 ++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 arch/arm64/boot/dts/nvidia/tegra186.dtsi

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
new file mode 100644
index 000000000000..6cb8ac918530
--- /dev/null
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -0,0 +1,89 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/mailbox/tegra186-hsp.h>
+
+/ {
+	compatible = "nvidia,tegra186";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	uarta: serial at 3100000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03100000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller at 3881000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x0 0x03881000 0x0 0x1000>,
+		      <0x0 0x03882000 0x0 0x2000>;
+		interrupts = <GIC_PPI 9
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
+	};
+
+	hsp_top0: hsp at 3c00000 {
+		compatible = "nvidia,tegra186-hsp";
+		reg = <0x0 0x03c00000 0x0 0xa0000>;
+		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "doorbell";
+		#mbox-cells = <2>;
+		status = "disabled";
+	};
+
+	sysram at 30000000 {
+		compatible = "nvidia,tegra186-sysram", "mmio-sram";
+		reg = <0x0 0x30000000 0x0 0x50000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
+
+		cpu_bpmp_tx: shmem at 4e000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4e000 0x0 0x1000>;
+			label = "cpu-bpmp-tx";
+			pool;
+		};
+
+		cpu_bpmp_rx: shmem at 4f000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4f000 0x0 0x1000>;
+			label = "cpu-bpmp-rx";
+			pool;
+		};
+	};
+
+	bpmp: bpmp {
+		compatible = "nvidia,tegra186-bpmp";
+		mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB
+				    TEGRA_HSP_DB_MASTER_BPMP>;
+		shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+
+		bpmp_i2c: i2c {
+			compatible = "nvidia,tegra186-bpmp-i2c";
+			nvidia,bpmp-bus-id = <5>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+		interrupt-parent = <&gic>;
+	};
+};
-- 
2.10.2

^ permalink raw reply related

* [PATCH 01/16] ARM: scu: Provide support for parsing SCU device node to enable SCU
From: Arnd Bergmann @ 2016-11-17 17:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <fe90b6cc-81b1-772e-ab78-f2199957ec96@samsung.com>

On Thursday, November 17, 2016 9:50:27 AM CET pankaj.dubey wrote:
> 
> >>> of_scu_enable() which _only_ looks up the SCU address in DT and enables
> >>> it if it finds it, otherwise returning failure.
> >>>
> >>> a9_scu_enable() which tries to use the A9 provided SCU address and
> >>> enables it if it finds it, otherwise returning failure.
> >>>
> 
> OK, In that case I can see need for following four helpers as:
> 
> 1: of_scu_enable() which will __only__ lookup the SCU address in DT and
> enables it if it finds, otherwise return -ENOMEM failure.
> This helper APIs is required and sufficient for most of platforms such
> as exynos, berlin, realview, socfpga, STi, ux500, vexpress, rockchip and
> mvebu
> 
> 2: a9_scu_enable(), which will __only__ use A9 provided SCU address and
> enables it, if address mapped successfully, otherwise returning failure.
> This helper APIs is required and sufficient for two ARM platforms as of
> now tegra and hisi.
> 
> 3: of_scu_get_base() which will lookup the SCU address in DT and if node
> found maps address and returns ioremapped address to caller.
> This helper APIs is required for three ARM plaforms rockchip, mvebu and
> ux500, along with scu_enable() API to enable and find number_of_cores.
> 
> 4: s9_scu_iomap_base() which will internally use s9_scu_get_base() and
> do ioremap of scu address and returns ioremapped address to the caller
> along with ownership (caller has responsibility to unmap it).
> This helper APIs is required to simplify SCU enable and related code in
> two ARM plaforms BCM ans ZX.
>
> For remaining two ARM platforms (IMX and ZYNQ), none of these helpers
> are useful for the time-being, as they need SCU mapping very early of
> boot, where we can't use iomap APIs. So I will drop patches related to
> these platforms in v2 version.
> 
> Please let me know if any concern in this approach.

I think ideally we wouldn't even need to know the virtual address
outside of smp_scu.c. If we can move all users of the address
into that file directly, it could become a local variable and
we change scu_power_mode() and scu_get_core_count() instead to
not require the address argument.

The only user I could find outside of that file is

static int shmobile_smp_scu_psr_core_disabled(int cpu)
{
        unsigned long mask = SCU_PM_POWEROFF << (cpu * 8);

        if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask)
                return 1;

        return 0;
}

which can be done in the same file as well.

> >>> Then callers can decide which of these to call, and what error messages
> >>> to print on their failures.
> >>
> >> Splitting the function in two is probably simpler overall, but
> >> we may still have to look at all the callers: Any platform that
> >> currently tries to map it on any CPU and doesn't warn about the
> >> absence of the device node (or about scu_a9_has_base() == false)
> >> should really continue not to warn about that.
> > 
> > Did you miss the bit where none of of_scu_enable() or a9_scu_enable()
> > should produce any warnings or errors to be printed.  It's up to the
> > caller to report the failure, otherwise doing this doesn't make sense:
> > 
> >       if (of_scu_enable() < 0 && a9_scu_enable() < 0)
> >               pr_err("Failed to map and enable the SCU\n");
> > 
> > because if of_scu_enable() prints a warning/error, then it's patently
> > misleading.
> > 

That's why I said "otherwise we can leave the warning in the caller
after checking the return code of the new APIs." for the case where
we actually need it.

> I will move out error message out of these helpers and let caller
> (platform specific code) handle and print error if required.

Ok.

	Arnd

^ permalink raw reply

* [PATCH] clk: sunxi-ng: enable so-said LDOs for A33 SoC's pll-mipi clock
From: Icenowy Zheng @ 2016-11-17 16:49 UTC (permalink / raw)
  To: linux-arm-kernel

In the user manual of A33 SoC, the bit 22 and 23 of pll-mipi control
register is called "LDO{1,2}_EN", and according to the BSP source code
from Allwinner [1], the LDOs are enabled during the clock's enabling
process.

The clock failed to generate output if the two LDOs are not enabled.

Add the two bits to the clock's gate bits, so that the LDOs are enabled
when the PLL is enabled.

[1] https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/drivers/clk/sunxi/clk-sun8iw5.c#L429

Fixes: d05c748bd730 ("clk: sunxi-ng: Add A33 CCU support")

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Dear Chen-Yu:
As you said, the two bits are also present in the CCU of A23 and A31.
Could you please check whether the PLL works on the two SoCs?
I remembered you mentioned you failed to make TCON enabled on A23.
On A31, you may hack the parent of tcon-ch0 to force the tcon clock to
use pll-mipi as parent, in order to check whether the pll works.

However, I didn't found the code that enables the LDOs in the BSP A23/31
sources, so you must test them to ensure whether the code is needed for
these SoCs.

Regards,
Icenowy
 drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
index 96b40ca..9bd1f78 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
@@ -131,7 +131,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_mipi_clk, "pll-mipi",
 				    8, 4,		/* N */
 				    4, 2,		/* K */
 				    0, 4,		/* M */
-				    BIT(31),		/* gate */
+				    BIT(31) | BIT(23) | BIT(22), /* gate */
 				    BIT(28),		/* lock */
 				    CLK_SET_RATE_UNGATE);
 
-- 
2.10.1

^ permalink raw reply related

* Boot failures in -next due to 'ARM: dts: imx: Remove skeleton.dtsi'
From: Mark Rutland @ 2016-11-17 16:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2eaf84f9-ea00-d331-1875-56adafb62378@roeck-us.net>

On Thu, Nov 17, 2016 at 08:17:00AM -0800, Guenter Roeck wrote:
> On 11/17/2016 07:05 AM, Mark Rutland wrote:
> >On Thu, Nov 17, 2016 at 06:44:55AM -0800, Guenter Roeck wrote:
> >>On 11/17/2016 02:55 AM, Mark Rutland wrote:
> >>>Memory nodes require this property per ePAPR and the devicetree.org
> >>>spec, so the bug is that we didn't add those when removing the
> >>>skeleton.dtsi include.
> >>
> >>The downside from qemu perspective is that the real hardware seems
> >>to add the property unconditionally, or the boot failure would have
> >>been seen there as well.
> >>
> >>I submitted https://patchwork.ozlabs.org/patch/695951/; we'll see how it goes.
> >
> >Sure, the firmare/bootlaoder you're using may add this automatically.
> >
> >My worry is that adding this to a generic file in QEMU only serves to
> >mask this class of bug for other boards (i.e. they'll work fine in QEMU,
> >but not on real HW using whatever bootlaoder happens ot be there).
> >
> Good point.
> 
> What would be the correct behavior for qemu ? Adding a chosen node if it does
> not exist is one detail we already established. Also, I think a check if
> /memory/device_type exists (and to bail out if it doesn't) would make sense.

We'd also need to check for /memory@<n> nodes, as they can validly have
unit-addresses (and many do).

Generally, the "correct" way to find them is to iterate over all ndoes
with device_type = "memory", so one could do that and give up if none
are found, ignoring the naming entirely.

> What about the memory node ? Does it have to exist, or should it be added
> (including the device_type property) if not ?

I'm not sure what QEMU does in this area. I suspect it may expect a node
in some cases, or may generate one in others.

There's no point generating one when we don't have the information to
hand, certainly.

Thanks,
Mark.

^ permalink raw reply

* [PATCH 1/2] drm/i2c: tda998x: allow interrupt to be shared
From: Russell King - ARM Linux @ 2016-11-17 16:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117122457.GC21156@e106950-lin.cambridge.arm.com>

On Thu, Nov 17, 2016 at 12:24:57PM +0000, Brian Starkey wrote:
> I tested these two and the power-down one on mali-dp and hdlcd. The
> output, hotplugging and EDID continued to work; so you can have my
> tested-by and reviewed-by for all 3.

Thanks!

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply

* Boot failures in -next due to 'ARM: dts: imx: Remove skeleton.dtsi'
From: Guenter Roeck @ 2016-11-17 16:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161117150551.GA21742@leverpostej>

On 11/17/2016 07:05 AM, Mark Rutland wrote:
> On Thu, Nov 17, 2016 at 06:44:55AM -0800, Guenter Roeck wrote:
>> On 11/17/2016 02:55 AM, Mark Rutland wrote:
>>> On Wed, Nov 16, 2016 at 02:40:24PM -0800, Guenter Roeck wrote:
>>>> On Wed, Nov 16, 2016 at 08:27:09PM -0200, Fabio Estevam wrote:
>>>>> Hi Guenter,
>>>>>
>>>>> On Wed, Nov 16, 2016 at 8:10 PM, Guenter Roeck <linux@roeck-us.net> wrote:
>>>>>>
>>>>>> Anyway, I guess the problem is that the "official" dtb files no longer provide
>>>>>> the skeleton /chosen and /memory nodes (and maybe others), and qemu seems to
>>>>>> expect that they are provided. Is that correct ?
>>>>>
>>>>> imx6qdl-sabrelite.dtsi provides chosen and memory nodes.
>>>>
>>>> Yes, but not the 'device_type' property, which the kernel seems to expect.
>>>
>>> Memory nodes require this property per ePAPR and the devicetree.org
>>> spec, so the bug is that we didn't add those when removing the
>>> skeleton.dtsi include.
>>
>> The downside from qemu perspective is that the real hardware seems
>> to add the property unconditionally, or the boot failure would have
>> been seen there as well.
>>
>> I submitted https://patchwork.ozlabs.org/patch/695951/; we'll see how it goes.
>
> Sure, the firmare/bootlaoder you're using may add this automatically.
>
> My worry is that adding this to a generic file in QEMU only serves to
> mask this class of bug for other boards (i.e. they'll work fine in QEMU,
> but not on real HW using whatever bootlaoder happens ot be there).
>
Good point.

What would be the correct behavior for qemu ? Adding a chosen node if it does
not exist is one detail we already established. Also, I think a check if
/memory/device_type exists (and to bail out if it doesn't) would make sense.

What about the memory node ? Does it have to exist, or should it be added
(including the device_type property) if not ?

Thanks,
Guenter

^ permalink raw reply

* [PATCH v8 6/7] arm/arm64: vgic: Implement VGICv3 CPU interface access
From: Christoffer Dall @ 2016-11-17 16:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CALicx6t5D5n3dDQzeKZNUWdS-q5LNiSq-UrP4HdmbdUCj1tF1g@mail.gmail.com>

On Thu, Nov 17, 2016 at 09:25:59PM +0530, Vijay Kilari wrote:
> On Thu, Nov 17, 2016 at 12:22 AM, Christoffer Dall
> <christoffer.dall@linaro.org> wrote:
> > On Fri, Nov 04, 2016 at 04:43:32PM +0530, vijay.kilari at gmail.com wrote:
> >> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> >>
> >> VGICv3 CPU interface registers are accessed using
> >> KVM_DEV_ARM_VGIC_CPU_SYSREGS ioctl. These registers are accessed
> >> as 64-bit. The cpu MPIDR value is passed along with register id.
> >> is used to identify the cpu for registers access.
> >>
> >> The version of VGIC v3 specification is define here
> >> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/445611.html
> >>
> >> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> >> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> >> ---
> >>  arch/arm64/include/uapi/asm/kvm.h   |   3 +
> >>  arch/arm64/kvm/Makefile             |   1 +
> >>  include/kvm/arm_vgic.h              |   9 +
> >>  virt/kvm/arm/vgic/vgic-kvm-device.c |  27 +++
> >>  virt/kvm/arm/vgic/vgic-mmio-v3.c    |  19 +++
> >>  virt/kvm/arm/vgic/vgic-sys-reg-v3.c | 324 ++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic-v3.c         |   8 +
> >>  virt/kvm/arm/vgic/vgic.h            |   4 +
> >>  8 files changed, 395 insertions(+)
> >>
> >> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> >> index 56dc08d..91c7137 100644
> >> --- a/arch/arm64/include/uapi/asm/kvm.h
> >> +++ b/arch/arm64/include/uapi/asm/kvm.h
> >> @@ -206,9 +206,12 @@ struct kvm_arch_memory_slot {
> >>                       (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
> >>  #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT      0
> >>  #define   KVM_DEV_ARM_VGIC_OFFSET_MASK       (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
> >> +#define   KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
> >>  #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
> >>  #define KVM_DEV_ARM_VGIC_GRP_CTRL    4
> >>  #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> >> +#define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6
> >> +
> >>  #define   KVM_DEV_ARM_VGIC_CTRL_INIT 0
> >>
> >>  /* Device Control API on vcpu fd */
> >> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> >> index d50a82a..1a14e29 100644
> >> --- a/arch/arm64/kvm/Makefile
> >> +++ b/arch/arm64/kvm/Makefile
> >> @@ -32,5 +32,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
> >>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
> >>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
> >>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
> >> +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-sys-reg-v3.o
> >
> > Thi is making me wonder:  Are we properly handling GICv3 save/restore
> > for AArch32 now that we have GICv3 support for AArch32?  By properly I
> > mean that either it is clearly only supported on AArch64 systems or it's
> > supported on both AArch64 and AArch32, but it shouldn't break randomly
> > on AArch32.
> 
> It supports both AArch64 and AArch64 in handling of system registers
> save/restore.
> All system registers that we save/restore are 32-bit for both aarch64
> and aarch32.
> Though opcode op0 should be zero for aarch32, the remaining Op and CRn codes
> are same. However the codes sent by qemu is matched and register
> are handled properly irrespective of AArch32 or AArch64.
> 
> I don't have platform which support AArch32 guests to verify.

Actually this is not about the guest, it's about an ARMv8 AArch32 host
that has a GICv3.

I just tried to do a v7 compile with your patches, and it results in an
epic failure, so there's something for you to look at.

> >
> >>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
> >>  kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
> >> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> >> index 002f092..730a18a 100644
> >> --- a/include/kvm/arm_vgic.h
> >> +++ b/include/kvm/arm_vgic.h
> >> @@ -71,6 +71,9 @@ struct vgic_global {
> >>
> >>       /* GIC system register CPU interface */
> >>       struct static_key_false gicv3_cpuif;
> >> +
> >> +     /* Cache ICH_VTR_EL2 reg value */
> >> +     u32                     ich_vtr_el2;
> >>  };
> >>
> >>  extern struct vgic_global kvm_vgic_global_state;
> >> @@ -269,6 +272,12 @@ struct vgic_cpu {
> >>       u64 pendbaser;
> >>
> >>       bool lpis_enabled;
> >> +
> >> +     /* Cache guest priority bits */
> >> +     u32 num_pri_bits;
> >> +
> >> +     /* Cache guest interrupt ID bits */
> >> +     u32 num_id_bits;
> >>  };
> >>
> >>  extern struct static_key_false vgic_v2_cpuif_trap;
> >> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> index 6c7d30c..da532d1 100644
> >> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> @@ -504,6 +504,14 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
> >>               if (!is_write)
> >>                       *reg = tmp32;
> >>               break;
> >> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> >> +             u64 regid;
> >> +
> >> +             regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> >> +             ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
> >> +                                               regid, reg);
> >> +             break;
> >> +     }
> >>       default:
> >>               ret = -EINVAL;
> >>               break;
> >> @@ -537,6 +545,15 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
> >>               reg = tmp32;
> >>               return vgic_v3_attr_regs_access(dev, attr, &reg, true);
> >>       }
> >> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> >> +             u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> >> +             u64 reg;
> >> +
> >> +             if (get_user(reg, uaddr))
> >> +                     return -EFAULT;
> >> +
> >> +             return vgic_v3_attr_regs_access(dev, attr, &reg, true);
> >> +     }
> >>       }
> >>       return -ENXIO;
> >>  }
> >> @@ -563,6 +580,15 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
> >>               tmp32 = reg;
> >>               return put_user(tmp32, uaddr);
> >>       }
> >> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> >> +             u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> >> +             u64 reg;
> >> +
> >> +             ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
> >> +             if (ret)
> >> +                     return ret;
> >> +             return put_user(reg, uaddr);
> >> +     }
> >>       }
> >>
> >>       return -ENXIO;
> >> @@ -581,6 +607,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
> >>               break;
> >>       case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> >>       case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
> >> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS:
> >>               return vgic_v3_has_attr_regs(dev, attr);
> >>       case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> >>               return 0;
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> >> index b35fb83..519b919 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> >> @@ -23,6 +23,7 @@
> >>
> >>  #include "vgic.h"
> >>  #include "vgic-mmio.h"
> >> +#include "sys_regs.h"
> >>
> >>  /* extract @num bytes at @offset bytes offset in data */
> >>  unsigned long extract_bytes(u64 data, unsigned int offset,
> >> @@ -639,6 +640,24 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> >>               nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
> >>               break;
> >>       }
> >> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> >> +             u64 reg, id;
> >> +             unsigned long vgic_mpidr, mpidr_reg;
> >> +             struct kvm_vcpu *vcpu;
> >> +
> >> +             vgic_mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
> >> +                           KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;
> >> +
> >> +             /* Convert plain mpidr value to MPIDR reg format */
> >> +             mpidr_reg = VGIC_TO_MPIDR(vgic_mpidr);
> >> +
> >> +             vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr_reg);
> >> +             if (!vcpu)
> >> +                     return -EINVAL;
> >> +
> >> +             id = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> >> +             return vgic_v3_has_cpu_sysregs_attr(vcpu, 0, id, &reg);
> >> +     }
> >>       default:
> >>               return -ENXIO;
> >>       }
> >> diff --git a/virt/kvm/arm/vgic/vgic-sys-reg-v3.c b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
> >> new file mode 100644
> >> index 0000000..69d8597
> >> --- /dev/null
> >> +++ b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
> >
> > Shouldn't we have a GPL header here?
> >
> >> @@ -0,0 +1,324 @@
> >> +#include <linux/irqchip/arm-gic-v3.h>
> >> +#include <linux/kvm.h>
> >> +#include <linux/kvm_host.h>
> >> +#include <kvm/iodev.h>
> >> +#include <kvm/arm_vgic.h>
> >> +#include <asm/kvm_emulate.h>
> >> +#include <asm/kvm_arm.h>
> >> +#include <asm/kvm_mmu.h>
> >> +
> >> +#include "vgic.h"
> >> +#include "vgic-mmio.h"
> >> +#include "sys_regs.h"
> >> +
> >> +static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                         const struct sys_reg_desc *r)
> >> +{
> >> +     struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
> >> +     struct vgic_vmcr vmcr;
> >> +     u64 val;
> >> +     u32 num_pri_bits, num_id_bits;
> >> +
> >> +     vgic_get_vmcr(vcpu, &vmcr);
> >> +     if (p->is_write) {
> >> +             val = p->regval;
> >> +
> >> +             /*
> >> +              * Does not allow update of ICC_CTLR_EL1 if HW does not support
> >> +              * guest programmed ID and PRI bits
> >> +              */
> >
> > I would suggest rewording this comment:
> > Disallow restoring VM state not supported by this hardware.
> >
> >> +             num_pri_bits = ((val & ICC_CTLR_EL1_PRI_BITS_MASK) >>
> >> +                             ICC_CTLR_EL1_PRI_BITS_SHIFT) + 1;
> >> +             if (num_pri_bits > vgic_v3_cpu->num_pri_bits)
> >> +                     return false;
> >> +
> >> +             vgic_v3_cpu->num_pri_bits = num_pri_bits;
> >
> > hmmm, this looks weird to me, because vgic_v3_cpu->num_pri_bits I don't
> > understand which effect this is intended to have?
> >
> > Sure, it may limit what you do with other registers later, but since
> > there's no ordering requirement that the ctlr be restored first, I'm not
> > sure it makes sense.
> >
> > Also, since this field is RO in the ICH_VTR, we'll have a strange
> > situation during runtime after a GICv3 restore where the
> > vgic_v3_cpu->num_pri_its differs from the hardware's ICH_VTR_EL2 field,
> > which is never the case if you didn't do a save/restore.
> 
> Yes, but in any case, vgic_v3_cpu->num_pri_bits will be always less
> than HW supported
> value.
> 

So answer my question:  What is the intended effect of writing this
value?  Is it just so that if you migrate this platform back again, then
you're checking compatibility with what the guest would potentially do,
or should you maintain the num_pri_bits limitation during runtime
somehow?

> >
> > Finally, should we somehow ensure that this field is set to the same
> > value across VCPUs or is that not an architectural requirement?
> >
>    Yes it is nice to have it same across VCPUs. But should be ok as
> we are ensuring value is not greater than HW supported value.

Does the architecture allow having a different number of priority bits
supported across CPUs?  If not, you shouldn't allow a VM programming
things that way either.

> There is no single point of place where we can make such a check
> 
> >> +
> >> +             num_id_bits = (val & ICC_CTLR_EL1_ID_BITS_MASK) >>
> >> +                            ICC_CTLR_EL1_ID_BITS_SHIFT;
> >> +             if (num_id_bits > vgic_v3_cpu->num_id_bits)
> >> +                     return false;
> >> +
> >> +             vgic_v3_cpu->num_id_bits = num_id_bits;
> >
> > same questions
> >
> >> +
> >> +             vmcr.ctlr &= ~(ICH_VMCR_CBPR_MASK | ICH_VMCR_EOIM_MASK);
> >> +             vmcr.ctlr |= ((val & ICC_CTLR_EL1_CBPR_MASK) >>
> >> +                           ICC_CTLR_EL1_CBPR_SHIFT) << ICH_VMCR_CBPR_SHIFT;
> >> +             vmcr.ctlr |= ((val & ICC_CTLR_EL1_EOImode_MASK) >>
> >> +                           ICC_CTLR_EL1_EOImode_SHIFT) <<
> >> +                           ICH_VMCR_EOIM_SHIFT;
> >
> > I'm really confused here.  Is the vmcr.ctlr field in the ICC_CTLR_EL1
> > format or in the VMCR format?  I would assume the former, since
> > otherwise I don't get the point with this indirection, and for GICv2
> > vmcr.ctlr captures the GICC_CTLR value and git_set_vmcr transforms this
> > into VMCR values.
> >
> > Having a line that says "ctlr &= ~ICH_VMCR" should make some alarm bells
> > ring.
> 
> I will check and fix it.
> >
> >> +             vgic_set_vmcr(vcpu, &vmcr);
> >
> > Should we check compatibility between the source and destination for the
> > SEIS and A3V support here?
> 
> Can be checked. But I feel A3V check makes more sense than checking for
> SEIS.
> 

Please argue the *why* for whatever you end up doing with respect to
both bits in the commit message of your next patch revision.

> >
> >> +     } else {
> >> +             val = 0;
> >> +             val |= (vgic_v3_cpu->num_pri_bits - 1) <<
> >> +                     ICC_CTLR_EL1_PRI_BITS_SHIFT;
> >> +             val |= vgic_v3_cpu->num_id_bits <<
> >> +                     ICC_CTLR_EL1_ID_BITS_SHIFT;
> >> +             val |= ((kvm_vgic_global_state.ich_vtr_el2 &
> >> +                     ICH_VTR_SEIS_MASK) >> ICH_VTR_SEIS_SHIFT) <<
> >> +                     ICC_CTLR_EL1_SEIS_SHIFT;
> >> +             val |= ((kvm_vgic_global_state.ich_vtr_el2 &
> >> +                     ICH_VTR_A3V_MASK) >> ICH_VTR_A3V_SHIFT) <<
> >> +                     ICC_CTLR_EL1_A3V_SHIFT;
> >> +             val |= ((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >>
> >> +                     ICH_VMCR_CBPR_SHIFT) << ICC_CTLR_EL1_CBPR_SHIFT;
> >> +             val |= ((vmcr.ctlr & ICH_VMCR_EOIM_MASK) >>
> >> +                     ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
> >
> > again, these last two look weird to me.
> >
> >> +
> >> +             p->regval = val;
> >> +     }
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static bool access_gic_pmr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                        const struct sys_reg_desc *r)
> >> +{
> >> +     struct vgic_vmcr vmcr;
> >> +
> >> +     vgic_get_vmcr(vcpu, &vmcr);
> >> +     if (p->is_write) {
> >> +             vmcr.pmr = (p->regval & ICC_PMR_EL1_MASK) >> ICC_PMR_EL1_SHIFT;
> >> +             vgic_set_vmcr(vcpu, &vmcr);
> >> +     } else {
> >> +             p->regval = (vmcr.pmr << ICC_PMR_EL1_SHIFT) & ICC_PMR_EL1_MASK;
> >> +     }
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static bool access_gic_bpr0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                         const struct sys_reg_desc *r)
> >> +{
> >> +     struct vgic_vmcr vmcr;
> >> +
> >> +     vgic_get_vmcr(vcpu, &vmcr);
> >> +     if (p->is_write) {
> >> +             vmcr.bpr = (p->regval & ICC_BPR0_EL1_MASK) >>
> >> +                         ICC_BPR0_EL1_SHIFT;
> >> +             vgic_set_vmcr(vcpu, &vmcr);
> >> +     } else {
> >> +             p->regval = (vmcr.bpr << ICC_BPR0_EL1_SHIFT) &
> >> +                          ICC_BPR0_EL1_MASK;
> >> +     }
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                         const struct sys_reg_desc *r)
> >> +{
> >> +     struct vgic_vmcr vmcr;
> >> +
> >> +     if (!p->is_write)
> >> +             p->regval = 0;
> >> +
> >> +     vgic_get_vmcr(vcpu, &vmcr);
> >> +     if (!((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT)) {
> >> +             if (p->is_write) {
> >> +                     vmcr.abpr = (p->regval & ICC_BPR1_EL1_MASK) >>
> >> +                                  ICC_BPR1_EL1_SHIFT;
> >> +                     vgic_set_vmcr(vcpu, &vmcr);
> >> +             } else {
> >> +                     p->regval = (vmcr.abpr << ICC_BPR1_EL1_SHIFT) &
> >> +                                  ICC_BPR1_EL1_MASK;
> >> +             }
> >> +     } else {
> >> +             if (!p->is_write)
> >> +                     p->regval = min((vmcr.bpr + 1), 7U);
> >> +     }
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static bool access_gic_grpen0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                           const struct sys_reg_desc *r)
> >> +{
> >> +     struct vgic_vmcr vmcr;
> >> +
> >> +     vgic_get_vmcr(vcpu, &vmcr);
> >> +     if (p->is_write) {
> >> +             vmcr.grpen0 = (p->regval & ICC_IGRPEN0_EL1_MASK) >>
> >> +                                   ICC_IGRPEN0_EL1_SHIFT;
> >> +             vgic_set_vmcr(vcpu, &vmcr);
> >> +     } else {
> >> +             p->regval = (vmcr.grpen0 << ICC_IGRPEN0_EL1_SHIFT) &
> >> +                          ICC_IGRPEN0_EL1_MASK;
> >> +     }
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static bool access_gic_grpen1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                           const struct sys_reg_desc *r)
> >> +{
> >> +     struct vgic_vmcr vmcr;
> >> +
> >> +     vgic_get_vmcr(vcpu, &vmcr);
> >> +     if (p->is_write) {
> >> +             vmcr.grpen1 = (p->regval & ICC_IGRPEN1_EL1_MASK) >>
> >> +                                   ICC_IGRPEN1_EL1_SHIFT;
> >> +             vgic_set_vmcr(vcpu, &vmcr);
> >> +     } else {
> >> +             p->regval = (vmcr.grpen1 << ICC_IGRPEN1_EL1_SHIFT) &
> >> +                          ICC_IGRPEN1_EL1_MASK;
> >> +     }
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static void vgic_v3_access_apr_reg(struct kvm_vcpu *vcpu,
> >> +                                struct sys_reg_params *p, u8 apr, u8 idx)
> >> +{
> >> +     struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> >> +     uint32_t *ap_reg;
> >> +
> >> +     if (apr)
> >> +             ap_reg = &vgicv3->vgic_ap1r[idx];
> >> +     else
> >> +             ap_reg = &vgicv3->vgic_ap0r[idx];
> >> +
> >> +     if (p->is_write)
> >> +             *ap_reg = p->regval;
> >> +     else
> >> +             p->regval = *ap_reg;
> >> +}
> >> +
> >> +static void access_gic_aprn(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                         const struct sys_reg_desc *r, u8 apr)
> >> +{
> >> +     struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
> >> +     u8 idx = r->Op2 & 3;
> >> +
> >> +     switch (vgic_v3_cpu->num_pri_bits) {
> >> +     case 7:
> >> +             if (idx > 3)
> >> +                     goto err;
> >
> > idx cannot be higher than three given the mask above, right?
> >
> >> +             vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> >> +             break;
> >> +     case 6:
> >> +             if (idx > 1)
> >> +                     goto err;
> >> +             vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> >> +             break;
> >> +     default:
> >> +             if (idx > 0)
> >> +                     goto err;
> >> +             vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> >> +     }
> >
> > what's the rationale behind ignoring the case where userspace is using
> > unsupported priorities?  Is it that this will be checked during
> > save/restore of the ctlr?
> >
> > This sort of thing just looks like the case that's impossible to debug,
> > because userspace could be scratching its head trying to understand why
> > the value it wrote isn't recorded anywhere...
> >
> > If there's a good rationale for doing it this way, then could we have a
> > comment to that effect?
> 
> Accessing umplemented priority registers raised UNDEF exception.
> So userspace accesing should be ignored instead of recording unsupported
> values.
> 

That's not what I asked.

I asked why it's silently ignored as opposed to raising an error visible
to user space?

> >
> >> +
> >> +     return;
> >> +err:
> >> +     if (!p->is_write)
> >> +             p->regval = 0;
> >> +}
> >> +
> >> +static bool access_gic_ap0r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                         const struct sys_reg_desc *r)
> >> +{
> >> +     access_gic_aprn(vcpu, p, r, 0);
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static bool access_gic_ap1r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                         const struct sys_reg_desc *r)
> >> +{
> >> +     access_gic_aprn(vcpu, p, r, 1);
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static bool access_gic_sre(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> >> +                        const struct sys_reg_desc *r)
> >> +{
> >> +     struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> >> +
> >> +     /* Validate SRE bit */
> >> +     if (p->is_write) {
> >> +             if (!(p->regval & ICC_SRE_EL1_SRE))
> >> +                     return false;
> >> +     } else {
> >> +             p->regval = vgicv3->vgic_sre;
> >> +     }
> >> +
> >> +     return true;
> >> +}
> >> +
> >> +static const struct sys_reg_desc gic_v3_icc_reg_descs[] = {
> >> +     /* ICC_PMR_EL1 */
> >> +     { Op0(3), Op1(0), CRn(4), CRm(6), Op2(0), access_gic_pmr },
> >> +     /* ICC_BPR0_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(3), access_gic_bpr0 },
> >> +     /* ICC_AP0R0_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(4), access_gic_ap0r },
> >> +     /* ICC_AP0R1_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(5), access_gic_ap0r },
> >> +     /* ICC_AP0R2_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(6), access_gic_ap0r },
> >> +     /* ICC_AP0R3_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(7), access_gic_ap0r },
> >> +     /* ICC_AP1R0_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(0), access_gic_ap1r },
> >> +     /* ICC_AP1R1_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(1), access_gic_ap1r },
> >> +     /* ICC_AP1R2_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(2), access_gic_ap1r },
> >> +     /* ICC_AP1R3_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(3), access_gic_ap1r },
> >> +     /* ICC_BPR1_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(3), access_gic_bpr1 },
> >> +     /* ICC_CTLR_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(4), access_gic_ctlr },
> >> +     /* ICC_SRE_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(5), access_gic_sre },
> >> +     /* ICC_IGRPEN0_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(6), access_gic_grpen0 },
> >> +     /* ICC_GRPEN1_EL1 */
> >> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(7), access_gic_grpen1 },
> >> +};
> >> +
> >> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> >> +                             u64 *reg)
> >> +{
> >> +     struct sys_reg_params params;
> >> +     u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
> >> +
> >> +     params.regval = *reg;
> >> +     params.is_write = is_write;
> >> +     params.is_aarch32 = false;
> >> +     params.is_32bit = false;
> >> +
> >> +     if (find_reg_by_id(sysreg, &params, gic_v3_icc_reg_descs,
> >> +                           ARRAY_SIZE(gic_v3_icc_reg_descs)))
> >> +             return 0;
> >> +
> >> +     return -ENXIO;
> >> +}
> >> +
> >> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> >> +                             u64 *reg)
> >> +{
> >> +     struct sys_reg_params params;
> >> +     const struct sys_reg_desc *r;
> >> +     u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
> >> +
> >> +     if (is_write)
> >> +             params.regval = *reg;
> >> +     params.is_write = is_write;
> >> +     params.is_aarch32 = false;
> >> +     params.is_32bit = false;
> >> +
> >> +     r = find_reg_by_id(sysreg, &params, gic_v3_icc_reg_descs,
> >> +                        ARRAY_SIZE(gic_v3_icc_reg_descs));
> >> +     if (!r)
> >> +             return -ENXIO;
> >> +
> >> +     if (!r->access(vcpu, &params, r))
> >> +             return -EINVAL;
> >
> > According to the API, EINVAL meansinvalid mpidr.  Should we expand on
> > how it can be used or allocate a new error code?
> How abt EACCES error code?
> 

That would mean permission denied, which is a bit weird.

> >
> >> +
> >> +     if (!is_write)
> >> +             *reg = params.regval;
> >> +
> >> +     return 0;
> >> +}
> >> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> >> index 967c295..1139971 100644
> >> --- a/virt/kvm/arm/vgic/vgic-v3.c
> >> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> >> @@ -228,6 +228,13 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
> >>               vgic_v3->vgic_sre = 0;
> >>       }
> >>
> >> +     vcpu->arch.vgic_cpu.num_id_bits = (kvm_vgic_global_state.ich_vtr_el2 &
> >> +                                        ICH_VTR_ID_BITS_MASK) >>
> >> +                                        ICH_VTR_ID_BITS_SHIFT;
> >> +     vcpu->arch.vgic_cpu.num_pri_bits = ((kvm_vgic_global_state.ich_vtr_el2 &
> >> +                                         ICH_VTR_PRI_BITS_MASK) >>
> >> +                                         ICH_VTR_PRI_BITS_SHIFT) + 1;
> >> +
> >>       /* Get the show on the road... */
> >>       vgic_v3->vgic_hcr = ICH_HCR_EN;
> >>  }
> >> @@ -328,6 +335,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> >>        */
> >>       kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
> >>       kvm_vgic_global_state.can_emulate_gicv2 = false;
> >> +     kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
> >>
> >>       if (!info->vcpu.start) {
> >>               kvm_info("GICv3: no GICV resource entry\n");
> >> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> >> index c461f6b..0e632d0 100644
> >> --- a/virt/kvm/arm/vgic/vgic.h
> >> +++ b/virt/kvm/arm/vgic/vgic.h
> >> @@ -126,6 +126,10 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> >>                        int offset, u32 *val);
> >>  int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> >>                        int offset, u32 *val);
> >> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> >> +                      u64 id, u64 *val);
> >> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> >> +                             u64 *reg);
> >>  #else
> >>  static inline int vgic_register_its_iodevs(struct kvm *kvm)
> >>  {
> >> --

Thanks,
-Christoffer

^ permalink raw reply

* [PATCH 2/2] arm64: defconfig: enable MFD RK808 and RK808 regulator
From: Heiko Stuebner @ 2016-11-17 16:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473249028-27161-1-git-send-email-andy.yan@rock-chips.com>

Am Mittwoch, 7. September 2016, 19:50:28 CET schrieb Andy Yan:
> Many rockchip based arm64 boards use RK808 as PMIC, so
> enabe it here let the board bootup normally.
> 
> Signed-off-by: Andy Yan <andy.yan@rock-chips.com>

applied to a defconfig64 branch after adding rk808-rtc as module and rk808-clk 
output as builtin as well.


Thanks
Heiko

^ permalink raw reply

* [PATCH v8 5/7] arm/arm64: vgic: Introduce VENG0 and VENG1 fields to vmcr struct
From: Christoffer Dall @ 2016-11-17 16:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CALicx6vP8FyaGa3f=T6RdC+Qd0iYMWiQ5g+g0_KQG6kzoJtzFA@mail.gmail.com>

On Thu, Nov 17, 2016 at 06:12:39PM +0530, Vijay Kilari wrote:
> On Thu, Nov 17, 2016 at 12:22 AM, Christoffer Dall
> <christoffer.dall@linaro.org> wrote:
> > On Fri, Nov 04, 2016 at 04:43:31PM +0530, vijay.kilari at gmail.com wrote:
> >> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> >>
> >> ICC_VMCR_EL2 supports virtual access to ICC_IGRPEN1_EL1.Enable
> >> and ICC_IGRPEN0_EL1.Enable fields. Add grpen0 and grpen1 member
> >> variables to struct vmcr to support read and write of these fields.
> >>
> >> Also refactor vgic_set_vmcr and vgic_get_vmcr() code.
> >> Drop ICH_VMCR_CTLR_SHIFT and ICH_VMCR_CTLR_MASK macros and instead
> >> use ICH_VMCR_EOI* and ICH_VMCR_CBPR* macros
> >> .
> >> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> >> ---
> >>  include/linux/irqchip/arm-gic-v3.h |  2 --
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c   | 16 ----------------
> >>  virt/kvm/arm/vgic/vgic-mmio.c      | 16 ++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic-v3.c        | 10 ++++++++--
> >>  virt/kvm/arm/vgic/vgic.h           |  5 +++++
> >>  5 files changed, 29 insertions(+), 20 deletions(-)
> >>
> >> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> >> index d48d886..61646aa 100644
> >> --- a/include/linux/irqchip/arm-gic-v3.h
> >> +++ b/include/linux/irqchip/arm-gic-v3.h
> >> @@ -404,8 +404,6 @@
> >>  #define ICH_HCR_EN                   (1 << 0)
> >>  #define ICH_HCR_UIE                  (1 << 1)
> >>
> >> -#define ICH_VMCR_CTLR_SHIFT          0
> >> -#define ICH_VMCR_CTLR_MASK           (0x21f << ICH_VMCR_CTLR_SHIFT)
> >>  #define ICH_VMCR_CBPR_SHIFT          4
> >>  #define ICH_VMCR_CBPR_MASK           (1 << ICH_VMCR_CBPR_SHIFT)
> >>  #define ICH_VMCR_EOIM_SHIFT          9
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index 2cb04b7..ad353b5 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -212,22 +212,6 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
> >>       }
> >>  }
> >>
> >> -static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >> -{
> >> -     if (kvm_vgic_global_state.type == VGIC_V2)
> >> -             vgic_v2_set_vmcr(vcpu, vmcr);
> >> -     else
> >> -             vgic_v3_set_vmcr(vcpu, vmcr);
> >> -}
> >> -
> >> -static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >> -{
> >> -     if (kvm_vgic_global_state.type == VGIC_V2)
> >> -             vgic_v2_get_vmcr(vcpu, vmcr);
> >> -     else
> >> -             vgic_v3_get_vmcr(vcpu, vmcr);
> >> -}
> >> -
> >>  #define GICC_ARCH_VERSION_V2 0x2
> >>
> >>  /* These are for userland accesses only, there is no guest-facing emulation. */
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >> index 9939d1d..173d6f0 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >> @@ -416,6 +416,22 @@ int vgic_validate_mmio_region_addr(struct kvm_device *dev,
> >>       return -ENXIO;
> >>  }
> >>
> >> +void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >> +{
> >> +     if (kvm_vgic_global_state.type == VGIC_V2)
> >> +             vgic_v2_set_vmcr(vcpu, vmcr);
> >> +     else
> >> +             vgic_v3_set_vmcr(vcpu, vmcr);
> >> +}
> >> +
> >> +void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >> +{
> >> +     if (kvm_vgic_global_state.type == VGIC_V2)
> >> +             vgic_v2_get_vmcr(vcpu, vmcr);
> >> +     else
> >> +             vgic_v3_get_vmcr(vcpu, vmcr);
> >> +}
> >> +
> >>  /*
> >>   * kvm_mmio_read_buf() returns a value in a format where it can be converted
> >>   * to a byte array and be directly observed as the guest wanted it to appear
> >> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> >> index 9f0dae3..967c295 100644
> >> --- a/virt/kvm/arm/vgic/vgic-v3.c
> >> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> >> @@ -175,10 +175,13 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> >>  {
> >>       u32 vmcr;
> >>
> >> -     vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
> >> +     vmcr  = (vmcrp->ctlr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK;
> >> +     vmcr |= (vmcrp->ctlr << ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;
> >
> > This looks weird:  The EOImode field is bit[2] in the CTLR, and VEOIM is
> > bit[9] in the ICH_VMCR, but you're just shifting the ctlr field left by
> > 9 and then masking off everything by bit 9, so you'll end with never
> > being able to set VEOIM I think...
> >
> OK
> > Also, we do we now forget about VFIQEn and VAckCtl?  The latter I can
> > understand because it's deprecated, but why the first?  This particular
> > piece of information would be very nice to have in the commit message.
> 
> I understand that group 0 interrupts are not handled. So vFIQEn can be ignored.
> Spec says, if SRE=1 (non-secure) this bit is RES1 also it is alias to
> ICC_CTLR_EL1
> if SRE is 1. However there is no bit in ICC_CTLR_EL1 for FIQen. It is defined
> only in GICV_CTLR which is used when SRE=0.

So you should add a comment or the very least add to the commit message
that we ignore the FIQen bit, because our GIC emulation always implies
SRE=1 which means the vFIQEn bit is also RES1 (if I got this right).

-Christoffer

^ permalink raw reply

* [PATCH v8 6/7] arm/arm64: vgic: Implement VGICv3 CPU interface access
From: Vijay Kilari @ 2016-11-17 15:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161116185232.GF3811@cbox>

On Thu, Nov 17, 2016 at 12:22 AM, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> On Fri, Nov 04, 2016 at 04:43:32PM +0530, vijay.kilari at gmail.com wrote:
>> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>>
>> VGICv3 CPU interface registers are accessed using
>> KVM_DEV_ARM_VGIC_CPU_SYSREGS ioctl. These registers are accessed
>> as 64-bit. The cpu MPIDR value is passed along with register id.
>> is used to identify the cpu for registers access.
>>
>> The version of VGIC v3 specification is define here
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/445611.html
>>
>> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
>> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>> ---
>>  arch/arm64/include/uapi/asm/kvm.h   |   3 +
>>  arch/arm64/kvm/Makefile             |   1 +
>>  include/kvm/arm_vgic.h              |   9 +
>>  virt/kvm/arm/vgic/vgic-kvm-device.c |  27 +++
>>  virt/kvm/arm/vgic/vgic-mmio-v3.c    |  19 +++
>>  virt/kvm/arm/vgic/vgic-sys-reg-v3.c | 324 ++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic-v3.c         |   8 +
>>  virt/kvm/arm/vgic/vgic.h            |   4 +
>>  8 files changed, 395 insertions(+)
>>
>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
>> index 56dc08d..91c7137 100644
>> --- a/arch/arm64/include/uapi/asm/kvm.h
>> +++ b/arch/arm64/include/uapi/asm/kvm.h
>> @@ -206,9 +206,12 @@ struct kvm_arch_memory_slot {
>>                       (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
>>  #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT      0
>>  #define   KVM_DEV_ARM_VGIC_OFFSET_MASK       (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
>> +#define   KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
>>  #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
>>  #define KVM_DEV_ARM_VGIC_GRP_CTRL    4
>>  #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
>> +#define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6
>> +
>>  #define   KVM_DEV_ARM_VGIC_CTRL_INIT 0
>>
>>  /* Device Control API on vcpu fd */
>> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
>> index d50a82a..1a14e29 100644
>> --- a/arch/arm64/kvm/Makefile
>> +++ b/arch/arm64/kvm/Makefile
>> @@ -32,5 +32,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
>>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
>>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
>>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
>> +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-sys-reg-v3.o
>
> Thi is making me wonder:  Are we properly handling GICv3 save/restore
> for AArch32 now that we have GICv3 support for AArch32?  By properly I
> mean that either it is clearly only supported on AArch64 systems or it's
> supported on both AArch64 and AArch32, but it shouldn't break randomly
> on AArch32.

It supports both AArch64 and AArch64 in handling of system registers
save/restore.
All system registers that we save/restore are 32-bit for both aarch64
and aarch32.
Though opcode op0 should be zero for aarch32, the remaining Op and CRn codes
are same. However the codes sent by qemu is matched and register
are handled properly irrespective of AArch32 or AArch64.

I don't have platform which support AArch32 guests to verify.
>
>>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
>>  kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index 002f092..730a18a 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -71,6 +71,9 @@ struct vgic_global {
>>
>>       /* GIC system register CPU interface */
>>       struct static_key_false gicv3_cpuif;
>> +
>> +     /* Cache ICH_VTR_EL2 reg value */
>> +     u32                     ich_vtr_el2;
>>  };
>>
>>  extern struct vgic_global kvm_vgic_global_state;
>> @@ -269,6 +272,12 @@ struct vgic_cpu {
>>       u64 pendbaser;
>>
>>       bool lpis_enabled;
>> +
>> +     /* Cache guest priority bits */
>> +     u32 num_pri_bits;
>> +
>> +     /* Cache guest interrupt ID bits */
>> +     u32 num_id_bits;
>>  };
>>
>>  extern struct static_key_false vgic_v2_cpuif_trap;
>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> index 6c7d30c..da532d1 100644
>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> @@ -504,6 +504,14 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
>>               if (!is_write)
>>                       *reg = tmp32;
>>               break;
>> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
>> +             u64 regid;
>> +
>> +             regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
>> +             ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
>> +                                               regid, reg);
>> +             break;
>> +     }
>>       default:
>>               ret = -EINVAL;
>>               break;
>> @@ -537,6 +545,15 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
>>               reg = tmp32;
>>               return vgic_v3_attr_regs_access(dev, attr, &reg, true);
>>       }
>> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
>> +             u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>> +             u64 reg;
>> +
>> +             if (get_user(reg, uaddr))
>> +                     return -EFAULT;
>> +
>> +             return vgic_v3_attr_regs_access(dev, attr, &reg, true);
>> +     }
>>       }
>>       return -ENXIO;
>>  }
>> @@ -563,6 +580,15 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
>>               tmp32 = reg;
>>               return put_user(tmp32, uaddr);
>>       }
>> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
>> +             u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>> +             u64 reg;
>> +
>> +             ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
>> +             if (ret)
>> +                     return ret;
>> +             return put_user(reg, uaddr);
>> +     }
>>       }
>>
>>       return -ENXIO;
>> @@ -581,6 +607,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
>>               break;
>>       case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>       case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
>> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS:
>>               return vgic_v3_has_attr_regs(dev, attr);
>>       case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>>               return 0;
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> index b35fb83..519b919 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -23,6 +23,7 @@
>>
>>  #include "vgic.h"
>>  #include "vgic-mmio.h"
>> +#include "sys_regs.h"
>>
>>  /* extract @num bytes at @offset bytes offset in data */
>>  unsigned long extract_bytes(u64 data, unsigned int offset,
>> @@ -639,6 +640,24 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
>>               nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
>>               break;
>>       }
>> +     case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
>> +             u64 reg, id;
>> +             unsigned long vgic_mpidr, mpidr_reg;
>> +             struct kvm_vcpu *vcpu;
>> +
>> +             vgic_mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
>> +                           KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;
>> +
>> +             /* Convert plain mpidr value to MPIDR reg format */
>> +             mpidr_reg = VGIC_TO_MPIDR(vgic_mpidr);
>> +
>> +             vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr_reg);
>> +             if (!vcpu)
>> +                     return -EINVAL;
>> +
>> +             id = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
>> +             return vgic_v3_has_cpu_sysregs_attr(vcpu, 0, id, &reg);
>> +     }
>>       default:
>>               return -ENXIO;
>>       }
>> diff --git a/virt/kvm/arm/vgic/vgic-sys-reg-v3.c b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
>> new file mode 100644
>> index 0000000..69d8597
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
>
> Shouldn't we have a GPL header here?
>
>> @@ -0,0 +1,324 @@
>> +#include <linux/irqchip/arm-gic-v3.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +#include <kvm/iodev.h>
>> +#include <kvm/arm_vgic.h>
>> +#include <asm/kvm_emulate.h>
>> +#include <asm/kvm_arm.h>
>> +#include <asm/kvm_mmu.h>
>> +
>> +#include "vgic.h"
>> +#include "vgic-mmio.h"
>> +#include "sys_regs.h"
>> +
>> +static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                         const struct sys_reg_desc *r)
>> +{
>> +     struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
>> +     struct vgic_vmcr vmcr;
>> +     u64 val;
>> +     u32 num_pri_bits, num_id_bits;
>> +
>> +     vgic_get_vmcr(vcpu, &vmcr);
>> +     if (p->is_write) {
>> +             val = p->regval;
>> +
>> +             /*
>> +              * Does not allow update of ICC_CTLR_EL1 if HW does not support
>> +              * guest programmed ID and PRI bits
>> +              */
>
> I would suggest rewording this comment:
> Disallow restoring VM state not supported by this hardware.
>
>> +             num_pri_bits = ((val & ICC_CTLR_EL1_PRI_BITS_MASK) >>
>> +                             ICC_CTLR_EL1_PRI_BITS_SHIFT) + 1;
>> +             if (num_pri_bits > vgic_v3_cpu->num_pri_bits)
>> +                     return false;
>> +
>> +             vgic_v3_cpu->num_pri_bits = num_pri_bits;
>
> hmmm, this looks weird to me, because vgic_v3_cpu->num_pri_bits I don't
> understand which effect this is intended to have?
>
> Sure, it may limit what you do with other registers later, but since
> there's no ordering requirement that the ctlr be restored first, I'm not
> sure it makes sense.
>
> Also, since this field is RO in the ICH_VTR, we'll have a strange
> situation during runtime after a GICv3 restore where the
> vgic_v3_cpu->num_pri_its differs from the hardware's ICH_VTR_EL2 field,
> which is never the case if you didn't do a save/restore.

Yes, but in any case, vgic_v3_cpu->num_pri_bits will be always less
than HW supported
value.

>
> Finally, should we somehow ensure that this field is set to the same
> value across VCPUs or is that not an architectural requirement?
>
   Yes it is nice to have it same across VCPUs. But should be ok as
we are ensuring value is not greater than HW supported value.
There is no single point of place where we can make such a check

>> +
>> +             num_id_bits = (val & ICC_CTLR_EL1_ID_BITS_MASK) >>
>> +                            ICC_CTLR_EL1_ID_BITS_SHIFT;
>> +             if (num_id_bits > vgic_v3_cpu->num_id_bits)
>> +                     return false;
>> +
>> +             vgic_v3_cpu->num_id_bits = num_id_bits;
>
> same questions
>
>> +
>> +             vmcr.ctlr &= ~(ICH_VMCR_CBPR_MASK | ICH_VMCR_EOIM_MASK);
>> +             vmcr.ctlr |= ((val & ICC_CTLR_EL1_CBPR_MASK) >>
>> +                           ICC_CTLR_EL1_CBPR_SHIFT) << ICH_VMCR_CBPR_SHIFT;
>> +             vmcr.ctlr |= ((val & ICC_CTLR_EL1_EOImode_MASK) >>
>> +                           ICC_CTLR_EL1_EOImode_SHIFT) <<
>> +                           ICH_VMCR_EOIM_SHIFT;
>
> I'm really confused here.  Is the vmcr.ctlr field in the ICC_CTLR_EL1
> format or in the VMCR format?  I would assume the former, since
> otherwise I don't get the point with this indirection, and for GICv2
> vmcr.ctlr captures the GICC_CTLR value and git_set_vmcr transforms this
> into VMCR values.
>
> Having a line that says "ctlr &= ~ICH_VMCR" should make some alarm bells
> ring.

I will check and fix it.
>
>> +             vgic_set_vmcr(vcpu, &vmcr);
>
> Should we check compatibility between the source and destination for the
> SEIS and A3V support here?

Can be checked. But I feel A3V check makes more sense than checking for
SEIS.

>
>> +     } else {
>> +             val = 0;
>> +             val |= (vgic_v3_cpu->num_pri_bits - 1) <<
>> +                     ICC_CTLR_EL1_PRI_BITS_SHIFT;
>> +             val |= vgic_v3_cpu->num_id_bits <<
>> +                     ICC_CTLR_EL1_ID_BITS_SHIFT;
>> +             val |= ((kvm_vgic_global_state.ich_vtr_el2 &
>> +                     ICH_VTR_SEIS_MASK) >> ICH_VTR_SEIS_SHIFT) <<
>> +                     ICC_CTLR_EL1_SEIS_SHIFT;
>> +             val |= ((kvm_vgic_global_state.ich_vtr_el2 &
>> +                     ICH_VTR_A3V_MASK) >> ICH_VTR_A3V_SHIFT) <<
>> +                     ICC_CTLR_EL1_A3V_SHIFT;
>> +             val |= ((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >>
>> +                     ICH_VMCR_CBPR_SHIFT) << ICC_CTLR_EL1_CBPR_SHIFT;
>> +             val |= ((vmcr.ctlr & ICH_VMCR_EOIM_MASK) >>
>> +                     ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
>
> again, these last two look weird to me.
>
>> +
>> +             p->regval = val;
>> +     }
>> +
>> +     return true;
>> +}
>> +
>> +static bool access_gic_pmr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                        const struct sys_reg_desc *r)
>> +{
>> +     struct vgic_vmcr vmcr;
>> +
>> +     vgic_get_vmcr(vcpu, &vmcr);
>> +     if (p->is_write) {
>> +             vmcr.pmr = (p->regval & ICC_PMR_EL1_MASK) >> ICC_PMR_EL1_SHIFT;
>> +             vgic_set_vmcr(vcpu, &vmcr);
>> +     } else {
>> +             p->regval = (vmcr.pmr << ICC_PMR_EL1_SHIFT) & ICC_PMR_EL1_MASK;
>> +     }
>> +
>> +     return true;
>> +}
>> +
>> +static bool access_gic_bpr0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                         const struct sys_reg_desc *r)
>> +{
>> +     struct vgic_vmcr vmcr;
>> +
>> +     vgic_get_vmcr(vcpu, &vmcr);
>> +     if (p->is_write) {
>> +             vmcr.bpr = (p->regval & ICC_BPR0_EL1_MASK) >>
>> +                         ICC_BPR0_EL1_SHIFT;
>> +             vgic_set_vmcr(vcpu, &vmcr);
>> +     } else {
>> +             p->regval = (vmcr.bpr << ICC_BPR0_EL1_SHIFT) &
>> +                          ICC_BPR0_EL1_MASK;
>> +     }
>> +
>> +     return true;
>> +}
>> +
>> +static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                         const struct sys_reg_desc *r)
>> +{
>> +     struct vgic_vmcr vmcr;
>> +
>> +     if (!p->is_write)
>> +             p->regval = 0;
>> +
>> +     vgic_get_vmcr(vcpu, &vmcr);
>> +     if (!((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT)) {
>> +             if (p->is_write) {
>> +                     vmcr.abpr = (p->regval & ICC_BPR1_EL1_MASK) >>
>> +                                  ICC_BPR1_EL1_SHIFT;
>> +                     vgic_set_vmcr(vcpu, &vmcr);
>> +             } else {
>> +                     p->regval = (vmcr.abpr << ICC_BPR1_EL1_SHIFT) &
>> +                                  ICC_BPR1_EL1_MASK;
>> +             }
>> +     } else {
>> +             if (!p->is_write)
>> +                     p->regval = min((vmcr.bpr + 1), 7U);
>> +     }
>> +
>> +     return true;
>> +}
>> +
>> +static bool access_gic_grpen0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                           const struct sys_reg_desc *r)
>> +{
>> +     struct vgic_vmcr vmcr;
>> +
>> +     vgic_get_vmcr(vcpu, &vmcr);
>> +     if (p->is_write) {
>> +             vmcr.grpen0 = (p->regval & ICC_IGRPEN0_EL1_MASK) >>
>> +                                   ICC_IGRPEN0_EL1_SHIFT;
>> +             vgic_set_vmcr(vcpu, &vmcr);
>> +     } else {
>> +             p->regval = (vmcr.grpen0 << ICC_IGRPEN0_EL1_SHIFT) &
>> +                          ICC_IGRPEN0_EL1_MASK;
>> +     }
>> +
>> +     return true;
>> +}
>> +
>> +static bool access_gic_grpen1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                           const struct sys_reg_desc *r)
>> +{
>> +     struct vgic_vmcr vmcr;
>> +
>> +     vgic_get_vmcr(vcpu, &vmcr);
>> +     if (p->is_write) {
>> +             vmcr.grpen1 = (p->regval & ICC_IGRPEN1_EL1_MASK) >>
>> +                                   ICC_IGRPEN1_EL1_SHIFT;
>> +             vgic_set_vmcr(vcpu, &vmcr);
>> +     } else {
>> +             p->regval = (vmcr.grpen1 << ICC_IGRPEN1_EL1_SHIFT) &
>> +                          ICC_IGRPEN1_EL1_MASK;
>> +     }
>> +
>> +     return true;
>> +}
>> +
>> +static void vgic_v3_access_apr_reg(struct kvm_vcpu *vcpu,
>> +                                struct sys_reg_params *p, u8 apr, u8 idx)
>> +{
>> +     struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
>> +     uint32_t *ap_reg;
>> +
>> +     if (apr)
>> +             ap_reg = &vgicv3->vgic_ap1r[idx];
>> +     else
>> +             ap_reg = &vgicv3->vgic_ap0r[idx];
>> +
>> +     if (p->is_write)
>> +             *ap_reg = p->regval;
>> +     else
>> +             p->regval = *ap_reg;
>> +}
>> +
>> +static void access_gic_aprn(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                         const struct sys_reg_desc *r, u8 apr)
>> +{
>> +     struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu;
>> +     u8 idx = r->Op2 & 3;
>> +
>> +     switch (vgic_v3_cpu->num_pri_bits) {
>> +     case 7:
>> +             if (idx > 3)
>> +                     goto err;
>
> idx cannot be higher than three given the mask above, right?
>
>> +             vgic_v3_access_apr_reg(vcpu, p, apr, idx);
>> +             break;
>> +     case 6:
>> +             if (idx > 1)
>> +                     goto err;
>> +             vgic_v3_access_apr_reg(vcpu, p, apr, idx);
>> +             break;
>> +     default:
>> +             if (idx > 0)
>> +                     goto err;
>> +             vgic_v3_access_apr_reg(vcpu, p, apr, idx);
>> +     }
>
> what's the rationale behind ignoring the case where userspace is using
> unsupported priorities?  Is it that this will be checked during
> save/restore of the ctlr?
>
> This sort of thing just looks like the case that's impossible to debug,
> because userspace could be scratching its head trying to understand why
> the value it wrote isn't recorded anywhere...
>
> If there's a good rationale for doing it this way, then could we have a
> comment to that effect?

Accessing umplemented priority registers raised UNDEF exception.
So userspace accesing should be ignored instead of recording unsupported
values.

>
>> +
>> +     return;
>> +err:
>> +     if (!p->is_write)
>> +             p->regval = 0;
>> +}
>> +
>> +static bool access_gic_ap0r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                         const struct sys_reg_desc *r)
>> +{
>> +     access_gic_aprn(vcpu, p, r, 0);
>> +
>> +     return true;
>> +}
>> +
>> +static bool access_gic_ap1r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                         const struct sys_reg_desc *r)
>> +{
>> +     access_gic_aprn(vcpu, p, r, 1);
>> +
>> +     return true;
>> +}
>> +
>> +static bool access_gic_sre(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
>> +                        const struct sys_reg_desc *r)
>> +{
>> +     struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
>> +
>> +     /* Validate SRE bit */
>> +     if (p->is_write) {
>> +             if (!(p->regval & ICC_SRE_EL1_SRE))
>> +                     return false;
>> +     } else {
>> +             p->regval = vgicv3->vgic_sre;
>> +     }
>> +
>> +     return true;
>> +}
>> +
>> +static const struct sys_reg_desc gic_v3_icc_reg_descs[] = {
>> +     /* ICC_PMR_EL1 */
>> +     { Op0(3), Op1(0), CRn(4), CRm(6), Op2(0), access_gic_pmr },
>> +     /* ICC_BPR0_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(3), access_gic_bpr0 },
>> +     /* ICC_AP0R0_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(4), access_gic_ap0r },
>> +     /* ICC_AP0R1_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(5), access_gic_ap0r },
>> +     /* ICC_AP0R2_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(6), access_gic_ap0r },
>> +     /* ICC_AP0R3_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(8), Op2(7), access_gic_ap0r },
>> +     /* ICC_AP1R0_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(0), access_gic_ap1r },
>> +     /* ICC_AP1R1_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(1), access_gic_ap1r },
>> +     /* ICC_AP1R2_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(2), access_gic_ap1r },
>> +     /* ICC_AP1R3_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(9), Op2(3), access_gic_ap1r },
>> +     /* ICC_BPR1_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(3), access_gic_bpr1 },
>> +     /* ICC_CTLR_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(4), access_gic_ctlr },
>> +     /* ICC_SRE_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(5), access_gic_sre },
>> +     /* ICC_IGRPEN0_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(6), access_gic_grpen0 },
>> +     /* ICC_GRPEN1_EL1 */
>> +     { Op0(3), Op1(0), CRn(12), CRm(12), Op2(7), access_gic_grpen1 },
>> +};
>> +
>> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
>> +                             u64 *reg)
>> +{
>> +     struct sys_reg_params params;
>> +     u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
>> +
>> +     params.regval = *reg;
>> +     params.is_write = is_write;
>> +     params.is_aarch32 = false;
>> +     params.is_32bit = false;
>> +
>> +     if (find_reg_by_id(sysreg, &params, gic_v3_icc_reg_descs,
>> +                           ARRAY_SIZE(gic_v3_icc_reg_descs)))
>> +             return 0;
>> +
>> +     return -ENXIO;
>> +}
>> +
>> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
>> +                             u64 *reg)
>> +{
>> +     struct sys_reg_params params;
>> +     const struct sys_reg_desc *r;
>> +     u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
>> +
>> +     if (is_write)
>> +             params.regval = *reg;
>> +     params.is_write = is_write;
>> +     params.is_aarch32 = false;
>> +     params.is_32bit = false;
>> +
>> +     r = find_reg_by_id(sysreg, &params, gic_v3_icc_reg_descs,
>> +                        ARRAY_SIZE(gic_v3_icc_reg_descs));
>> +     if (!r)
>> +             return -ENXIO;
>> +
>> +     if (!r->access(vcpu, &params, r))
>> +             return -EINVAL;
>
> According to the API, EINVAL meansinvalid mpidr.  Should we expand on
> how it can be used or allocate a new error code?
How abt EACCES error code?

>
>> +
>> +     if (!is_write)
>> +             *reg = params.regval;
>> +
>> +     return 0;
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>> index 967c295..1139971 100644
>> --- a/virt/kvm/arm/vgic/vgic-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>> @@ -228,6 +228,13 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>>               vgic_v3->vgic_sre = 0;
>>       }
>>
>> +     vcpu->arch.vgic_cpu.num_id_bits = (kvm_vgic_global_state.ich_vtr_el2 &
>> +                                        ICH_VTR_ID_BITS_MASK) >>
>> +                                        ICH_VTR_ID_BITS_SHIFT;
>> +     vcpu->arch.vgic_cpu.num_pri_bits = ((kvm_vgic_global_state.ich_vtr_el2 &
>> +                                         ICH_VTR_PRI_BITS_MASK) >>
>> +                                         ICH_VTR_PRI_BITS_SHIFT) + 1;
>> +
>>       /* Get the show on the road... */
>>       vgic_v3->vgic_hcr = ICH_HCR_EN;
>>  }
>> @@ -328,6 +335,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>>        */
>>       kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
>>       kvm_vgic_global_state.can_emulate_gicv2 = false;
>> +     kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>>
>>       if (!info->vcpu.start) {
>>               kvm_info("GICv3: no GICV resource entry\n");
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index c461f6b..0e632d0 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -126,6 +126,10 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>>                        int offset, u32 *val);
>>  int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>>                        int offset, u32 *val);
>> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>> +                      u64 id, u64 *val);
>> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
>> +                             u64 *reg);
>>  #else
>>  static inline int vgic_register_its_iodevs(struct kvm *kvm)
>>  {
>> --
>
>
> Thanks,
> -Christoffer

^ permalink raw reply

* [PATCH 1/2] arm64: defconfig: enable I2C and DW MMC controller on rockchip platform
From: Heiko Stuebner @ 2016-11-17 15:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473248790-27101-1-git-send-email-andy.yan@rock-chips.com>

Am Mittwoch, 7. September 2016, 19:46:30 CET schrieb Andy Yan:
> I2C and MMC are very basic modules for a board to bootup, as I2C always
> used to configure PMIC and MMC devices often used to store filesytem.
> So enable them here to let the rockchip based arm64 boards can bootup.
> 
> Signed-off-by: Andy Yan <andy.yan@rock-chips.com>

applied to a defconfig64 branch, after moving I2C_RK3X between QUP and TEGRA
RCAR seems to be an exception to the otherwise alphabetically sorted list.


Heiko

^ permalink raw reply

* ILP32 for ARM64: testing with glibc testsuite
From: Catalin Marinas @ 2016-11-17 15:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CC4F99A7-1FD2-486A-BD66-ED06F1B8BF50@linaro.org>

On Wed, Nov 16, 2016 at 03:22:26PM +0400, Maxim Kuvyrkov wrote:
> Regarding ILP32 runtime, my opinion is that it is acceptable for ILP32
> to have extra failures compared to LP64, since these are not
> regressions, but, rather, failures of a new configuration.

I disagree with this. We definitely need to understand why they fail,
otherwise we run the risk of potential glibc or kernel implementation
bugs becoming ABI.

-- 
Catalin

^ permalink raw reply

* [PATCH -next] ARM: dts: omap5: replace gpio-key,wakeup with wakeup-source property
From: Tony Lindgren @ 2016-11-17 15:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <8d06724a-98af-05ab-f5a8-07c552722fca@arm.com>

* Sudeep Holla <sudeep.holla@arm.com> [161117 07:32]:
> 
> 
> On 17/11/16 15:27, Tony Lindgren wrote:
> > * Sudeep Holla <sudeep.holla@arm.com> [161114 07:44]:
> > > Though the keyboard driver for GPIO buttons(gpio-keys) will continue to
> > > check for/support the legacy "gpio-key,wakeup" boolean property to
> > > enable gpio buttons as wakeup source, "wakeup-source" is the new
> > > standard binding.
> > > 
> > > This patch replaces the legacy "gpio-key,wakeup" with the unified
> > > "wakeup-source" property in order to avoid any further copy-paste
> > > duplication.
> > > 
> > > Cc: "Beno?t Cousson" <bcousson@baylibre.com>
> > > Cc: Tony Lindgren <tony@atomide.com>
> > > Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> > > ---
> > >  arch/arm/boot/dts/omap5-uevm.dts | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > Hi,
> > > 
> > > Inspite of getting rid of most of the legacy property almost a year ago,
> > > addition of new platforms have brought this back and over time it's
> > > now found again in few places. Just get rid of them *again*
> > 
> > Thanks for the annual check up :)
> > 
> > Acked-by: Tony Lindgren <tony@atomide.com>
> > 
> > Please let me know if you want me to pick this up instead.
> 
> Yes that would be better. Also it's present only in your -next,
> looks like something newly added via commit 2d46c0c60725 ("ARM:
> dts: omap5 uevm: add USR1 button")

OK applied into omap-for-v4.10/dt:omap-for-v4.10/dt thanks.

Tony

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox