* [PATCH] bus: vexpress-config: fix device reference leak
From: Johan Hovold @ 2016-11-04 13:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478259746.17152.126.camel@arm.com>
On Fri, Nov 04, 2016 at 11:42:26AM +0000, Pawel Moll wrote:
> On Tue, 2016-11-01 at 11:43 +0100, Johan Hovold wrote:
> > Make sure to drop the reference to the parent device taken by
> > class_find_device() after populating the bus.
> >
> > Fixes: 3b9334ac835b ("mfd: vexpress: Convert custom func API to
> > regmap")
> > Signed-off-by: Johan Hovold <johan@kernel.org>
>
> You're right. May I ask how did you figure it out? The get_device()
> happening in class_find_device() is a bit obscure, so have you simply
> followed places where it's being used or used some static (?) analysis
> tool? If the latter, I'd be very curios to hear what was it :-)
I stumbled over one of these leaks and grepped and searched for more.
I've submitted a few patches this week fixing some of the more obvious
ones, but there are more lurking behind various subsystem wrappers.
Thanks,
Johan
^ permalink raw reply
* [1/4] ARM: EXYNOS: Remove smp_init_cpus hook from platsmp.c
From: Alim Akhtar @ 2016-11-04 12:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478230764-13748-2-git-send-email-pankaj.dubey@samsung.com>
Hi Pankaj,
On 11/04/2016 09:09 AM, Pankaj Dubey wrote:
> We can safely remove exynos_smp_init_cpus() hook from mach-exynos/platsmp.c,
> as all SMP platforms in mach-exynos can rely on DT for CPU core description
> instead of determining number of cores from the SCU.
>
> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
> ---
Looks good.
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
> arch/arm/mach-exynos/platsmp.c | 31 -------------------------------
> 1 file changed, 31 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
> index 98ffe1e..a5d6841 100644
> --- a/arch/arm/mach-exynos/platsmp.c
> +++ b/arch/arm/mach-exynos/platsmp.c
> @@ -385,36 +385,6 @@ fail:
> return pen_release != -1 ? ret : 0;
> }
>
> -/*
> - * Initialise the CPU possible map early - this describes the CPUs
> - * which may be present or become present in the system.
> - */
> -
> -static void __init exynos_smp_init_cpus(void)
> -{
> - void __iomem *scu_base = scu_base_addr();
> - unsigned int i, ncores;
> -
> - if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
> - ncores = scu_base ? scu_get_core_count(scu_base) : 1;
> - else
> - /*
> - * CPU Nodes are passed thru DT and set_cpu_possible
> - * is set by "arm_dt_init_cpu_maps".
> - */
> - return;
> -
> - /* sanity check */
> - if (ncores > nr_cpu_ids) {
> - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
> - ncores, nr_cpu_ids);
> - ncores = nr_cpu_ids;
> - }
> -
> - for (i = 0; i < ncores; i++)
> - set_cpu_possible(i, true);
> -}
> -
> static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
> {
> int i;
> @@ -479,7 +449,6 @@ static void exynos_cpu_die(unsigned int cpu)
> #endif /* CONFIG_HOTPLUG_CPU */
>
> const struct smp_operations exynos_smp_ops __initconst = {
> - .smp_init_cpus = exynos_smp_init_cpus,
> .smp_prepare_cpus = exynos_smp_prepare_cpus,
> .smp_secondary_init = exynos_secondary_init,
> .smp_boot_secondary = exynos_boot_secondary,
>
^ permalink raw reply
* [PATCH 2/3] ARM: cache-uniphier: refactor jump label to follow coding style guideline
From: Masahiro Yamada @ 2016-11-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104122322.GB1041@n2100.armlinux.org.uk>
Hi Russell,
2016-11-04 21:23 GMT+09:00 Russell King - ARM Linux <linux@armlinux.org.uk>:
> On Fri, Nov 04, 2016 at 08:43:35PM +0900, Masahiro Yamada wrote:
>> Documentation/CodingStyle recommends to use label names which say
>> what the goto does or why the goto exists.
>>
>> Just in case, split it up into three labels because the CodingStyle
>> says "one err bugs" is a common type of bug (although, I do not
>> believe the current code includes such a bug).
>
> However, this has the effect of making the code unnecessarily more
> complicated, which is a bad thing. Avoiding unnecessary code
> complexity wins over style rules.
I thought this patch is stupid, but makes the code more straight-forward;
the failure path only calls really needed iounmap/kfree()
without exploiting that NULL input makes them no-op.
--
Best Regards
Masahiro Yamada
^ permalink raw reply
* [PATCH] convert orion5x ls-chl to device tree
From: Gregory CLEMENT @ 2016-11-04 12:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <14522899-679b-2f8b-73ca-493788299790@gmail.com>
Hi Ash,
On mar., oct. 25 2016, Ash Hughes <sehguh.hsa@gmail.com> wrote:
> Hi all,
>
> This patch converts my orion5x ls-chl Linkstation device to device
> tree.
I was about to apply your patch but it does not apply on mvebu/dt or
even on v4.9-rc1.
Could you rebase it?
Thanks,
Gregory
>
> Signed-off-by: Ashley Hughes <ashley.hughes@blueyonder.co.uk>
> ---
> arch/arm/boot/dts/Makefile | 1 +
> arch/arm/boot/dts/orion5x-lschl.dts | 171 ++++++++++++++++++
> arch/arm/mach-orion5x/Kconfig | 4 +-
> arch/arm/mach-orion5x/Makefile | 1 -
> arch/arm/mach-orion5x/ls-chl-setup.c | 331 -----------------------------------
> 5 files changed, 174 insertions(+), 334 deletions(-)
> create mode 100644 arch/arm/boot/dts/orion5x-lschl.dts
> delete mode 100644 arch/arm/mach-orion5x/ls-chl-setup.c
>
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index befcd26..4853049 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -597,6 +597,7 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
> orion5x-lacie-ethernet-disk-mini-v2.dtb \
> orion5x-linkstation-lsgl.dtb \
> orion5x-linkstation-lswtgl.dtb \
> + orion5x-lschl.dtb \
> orion5x-lswsgl.dtb \
> orion5x-maxtor-shared-storage-2.dtb \
> orion5x-netgear-wnr854t.dtb \
> diff --git a/arch/arm/boot/dts/orion5x-lschl.dts b/arch/arm/boot/dts/orion5x-lschl.dts
> new file mode 100644
> index 0000000..9474092
> --- /dev/null
> +++ b/arch/arm/boot/dts/orion5x-lschl.dts
> @@ -0,0 +1,171 @@
> +/*
> + * Device Tree file for Buffalo Linkstation LS-CHLv3
> + *
> + * Copyright (C) 2016 Ash Hughes <ashley.hughes@blueyonder.co.uk>
> + * Copyright (C) 2015, 2016
> + * Roger Shimizu <rogershimizu@gmail.com>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + * a) This file is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This file is distributed in the hope that it will be useful
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Or, alternatively
> + *
> + * b) Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use
> + * copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +/dts-v1/;
> +
> +#include "orion5x-linkstation.dtsi"
> +#include "mvebu-linkstation-gpio-simple.dtsi"
> +#include "mvebu-linkstation-fan.dtsi"
> +#include <dt-bindings/gpio/gpio.h>
> +
> +/ {
> + model = "Buffalo Linkstation Live v3 (LS-CHL)";
> + compatible = "buffalo,lschl", "marvell,orion5x-88f5182", "marvell,orion5x";
> +
> + memory { /* 128 MB */
> + device_type = "memory";
> + reg = <0x00000000 0x8000000>;
> + };
> +
> + gpio_keys {
> + func {
> + label = "Function Button";
> + linux,code = <KEY_OPTION>;
> + gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
> + };
> +
> + power-on-switch {
> + gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
> + };
> +
> + power-auto-switch {
> + gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
> + };
> + };
> +
> + gpio_leds {
> + pinctrl-0 = <&pmx_led_power &pmx_led_alarm &pmx_led_info &pmx_led_func>;
> + blue-power-led {
> + gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
> + };
> +
> + red-alarm-led {
> + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
> + };
> +
> + amber-info-led {
> + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
> + };
> +
> + func {
> + label = "lschl:func:blue:top";
> + gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
> + };
> + };
> +
> + gpio_fan {
> + gpios = <&gpio0 14 GPIO_ACTIVE_LOW
> + &gpio0 16 GPIO_ACTIVE_LOW>;
> +
> + alarm-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
> + };
> +};
> +
> +&pinctrl {
> + pmx_led_power: pmx-leds {
> + marvell,pins = "mpp0";
> + marvell,function = "gpio";
> + };
> +
> + pmx_power_hdd: pmx-power-hdd {
> + marvell,pins = "mpp1";
> + marvell,function = "gpio";
> + };
> +
> + pmx_led_alarm: pmx-leds {
> + marvell,pins = "mpp2";
> + marvell,function = "gpio";
> + };
> +
> + pmx_led_info: pmx-leds {
> + marvell,pins = "mpp3";
> + marvell,function = "gpio";
> + };
> +
> + pmx_fan_lock: pmx-fan-lock {
> + marvell,pins = "mpp6";
> + marvell,function = "gpio";
> + };
> +
> + pmx_power_switch: pmx-power-switch {
> + marvell,pins = "mpp8", "mpp10", "mpp15";
> + marvell,function = "gpio";
> + };
> +
> + pmx_power_usb: pmx-power-usb {
> + marvell,pins = "mpp9";
> + marvell,function = "gpio";
> + };
> +
> + pmx_fan_high: pmx-fan-high {
> + marvell,pins = "mpp14";
> + marvell,function = "gpio";
> + };
> +
> + pmx_fan_low: pmx-fan-low {
> + marvell,pins = "mpp16";
> + marvell,function = "gpio";
> + };
> +
> + pmx_led_func: pmx-leds {
> + marvell,pins = "mpp17";
> + marvell,function = "gpio";
> + };
> +
> + pmx_sw_init: pmx-sw-init {
> + marvell,pins = "mpp7";
> + marvell,function = "gpio";
> + };
> +};
> +
> +&hdd_power {
> + gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
> +};
> +
> +&usb_power {
> + gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
> +};
> +
> diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
> index 89bb0fc..793efa9 100644
> --- a/arch/arm/mach-orion5x/Kconfig
> +++ b/arch/arm/mach-orion5x/Kconfig
> @@ -85,8 +85,8 @@ config MACH_LINKSTATION_PRO
> v2 devices are supported.
>
> config MACH_LINKSTATION_LSCHL
> - bool "Buffalo Linkstation Live v3 (LS-CHL)"
> - select I2C_BOARDINFO if I2C
> + bool "Buffalo Linkstation Live v3 (LS-CHL) (Flattened Device Tree)"
> + select ARCH_ORION5X_DT
> help
> Say 'Y' here if you want your kernel to support the
> Buffalo Linkstation Live v3 (LS-CHL) platform.
> diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
> index 4b2502b..ae91872 100644
> --- a/arch/arm/mach-orion5x/Makefile
> +++ b/arch/arm/mach-orion5x/Makefile
> @@ -18,7 +18,6 @@ obj-$(CONFIG_MACH_WNR854T) += wnr854t-setup.o
> obj-$(CONFIG_MACH_RD88F5181L_GE) += rd88f5181l-ge-setup.o
> obj-$(CONFIG_MACH_RD88F5181L_FXO) += rd88f5181l-fxo-setup.o
> obj-$(CONFIG_MACH_RD88F6183AP_GE) += rd88f6183ap-ge-setup.o
> -obj-$(CONFIG_MACH_LINKSTATION_LSCHL) += ls-chl-setup.o
>
> obj-$(CONFIG_ARCH_ORION5X_DT) += board-dt.o
> obj-$(CONFIG_MACH_D2NET_DT) += board-d2net.o
> diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
> deleted file mode 100644
> index dfdaa8a..0000000
> --- a/arch/arm/mach-orion5x/ls-chl-setup.c
> +++ /dev/null
> @@ -1,331 +0,0 @@
> -/*
> - * arch/arm/mach-orion5x/ls-chl-setup.c
> - *
> - * Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk>
> - *
> - * This file is licensed under the terms of the GNU General Public
> - * License version 2. This program is licensed "as is" without any
> - * warranty of any kind, whether express or implied.
> - */
> -
> -#include <linux/kernel.h>
> -#include <linux/init.h>
> -#include <linux/platform_device.h>
> -#include <linux/mtd/physmap.h>
> -#include <linux/mv643xx_eth.h>
> -#include <linux/leds.h>
> -#include <linux/gpio_keys.h>
> -#include <linux/gpio-fan.h>
> -#include <linux/input.h>
> -#include <linux/i2c.h>
> -#include <linux/ata_platform.h>
> -#include <linux/gpio.h>
> -#include <asm/mach-types.h>
> -#include <asm/mach/arch.h>
> -#include "common.h"
> -#include "mpp.h"
> -#include "orion5x.h"
> -
> -/*****************************************************************************
> - * Linkstation LS-CHL Info
> - ****************************************************************************/
> -
> -/*
> - * 256K NOR flash Device bus boot chip select
> - */
> -
> -#define LSCHL_NOR_BOOT_BASE 0xf4000000
> -#define LSCHL_NOR_BOOT_SIZE SZ_256K
> -
> -/*****************************************************************************
> - * 256KB NOR Flash on BOOT Device
> - ****************************************************************************/
> -
> -static struct physmap_flash_data lschl_nor_flash_data = {
> - .width = 1,
> -};
> -
> -static struct resource lschl_nor_flash_resource = {
> - .flags = IORESOURCE_MEM,
> - .start = LSCHL_NOR_BOOT_BASE,
> - .end = LSCHL_NOR_BOOT_BASE + LSCHL_NOR_BOOT_SIZE - 1,
> -};
> -
> -static struct platform_device lschl_nor_flash = {
> - .name = "physmap-flash",
> - .id = 0,
> - .dev = {
> - .platform_data = &lschl_nor_flash_data,
> - },
> - .num_resources = 1,
> - .resource = &lschl_nor_flash_resource,
> -};
> -
> -/*****************************************************************************
> - * Ethernet
> - ****************************************************************************/
> -
> -static struct mv643xx_eth_platform_data lschl_eth_data = {
> - .phy_addr = MV643XX_ETH_PHY_ADDR(8),
> -};
> -
> -/*****************************************************************************
> - * RTC 5C372a on I2C bus
> - ****************************************************************************/
> -
> -static struct i2c_board_info __initdata lschl_i2c_rtc = {
> - I2C_BOARD_INFO("rs5c372a", 0x32),
> -};
> -
> -/*****************************************************************************
> - * LEDs attached to GPIO
> - ****************************************************************************/
> -
> -#define LSCHL_GPIO_LED_ALARM 2
> -#define LSCHL_GPIO_LED_INFO 3
> -#define LSCHL_GPIO_LED_FUNC 17
> -#define LSCHL_GPIO_LED_PWR 0
> -
> -static struct gpio_led lschl_led_pins[] = {
> - {
> - .name = "alarm:red",
> - .gpio = LSCHL_GPIO_LED_ALARM,
> - .active_low = 1,
> - }, {
> - .name = "info:amber",
> - .gpio = LSCHL_GPIO_LED_INFO,
> - .active_low = 1,
> - }, {
> - .name = "func:blue:top",
> - .gpio = LSCHL_GPIO_LED_FUNC,
> - .active_low = 1,
> - }, {
> - .name = "power:blue:bottom",
> - .gpio = LSCHL_GPIO_LED_PWR,
> - },
> -};
> -
> -static struct gpio_led_platform_data lschl_led_data = {
> - .leds = lschl_led_pins,
> - .num_leds = ARRAY_SIZE(lschl_led_pins),
> -};
> -
> -static struct platform_device lschl_leds = {
> - .name = "leds-gpio",
> - .id = -1,
> - .dev = {
> - .platform_data = &lschl_led_data,
> - },
> -};
> -
> -/*****************************************************************************
> - * SATA
> - ****************************************************************************/
> -static struct mv_sata_platform_data lschl_sata_data = {
> - .n_ports = 2,
> -};
> -
> -/*****************************************************************************
> - * LS-CHL specific power off method: reboot
> - ****************************************************************************/
> -/*
> - * On the LS-CHL, the shutdown process is following:
> - * - Userland monitors key events until the power switch goes to off position
> - * - The board reboots
> - * - U-boot starts and goes into an idle mode waiting for the user
> - * to move the switch to ON position
> - *
> - */
> -
> -static void lschl_power_off(void)
> -{
> - orion5x_restart(REBOOT_HARD, NULL);
> -}
> -
> -/*****************************************************************************
> - * General Setup
> - ****************************************************************************/
> -#define LSCHL_GPIO_USB_POWER 9
> -#define LSCHL_GPIO_AUTO_POWER 17
> -#define LSCHL_GPIO_POWER 18
> -
> -/****************************************************************************
> - * GPIO Attached Keys
> - ****************************************************************************/
> -#define LSCHL_GPIO_KEY_FUNC 15
> -#define LSCHL_GPIO_KEY_POWER 8
> -#define LSCHL_GPIO_KEY_AUTOPOWER 10
> -#define LSCHL_SW_POWER 0x00
> -#define LSCHL_SW_AUTOPOWER 0x01
> -#define LSCHL_SW_FUNC 0x02
> -
> -static struct gpio_keys_button lschl_buttons[] = {
> - {
> - .type = EV_SW,
> - .code = LSCHL_SW_POWER,
> - .gpio = LSCHL_GPIO_KEY_POWER,
> - .desc = "Power-on Switch",
> - .active_low = 1,
> - }, {
> - .type = EV_SW,
> - .code = LSCHL_SW_AUTOPOWER,
> - .gpio = LSCHL_GPIO_KEY_AUTOPOWER,
> - .desc = "Power-auto Switch",
> - .active_low = 1,
> - }, {
> - .type = EV_SW,
> - .code = LSCHL_SW_FUNC,
> - .gpio = LSCHL_GPIO_KEY_FUNC,
> - .desc = "Function Switch",
> - .active_low = 1,
> - },
> -};
> -
> -static struct gpio_keys_platform_data lschl_button_data = {
> - .buttons = lschl_buttons,
> - .nbuttons = ARRAY_SIZE(lschl_buttons),
> -};
> -
> -static struct platform_device lschl_button_device = {
> - .name = "gpio-keys",
> - .id = -1,
> - .num_resources = 0,
> - .dev = {
> - .platform_data = &lschl_button_data,
> - },
> -};
> -
> -#define LSCHL_GPIO_HDD_POWER 1
> -
> -/****************************************************************************
> - * GPIO Fan
> - ****************************************************************************/
> -
> -#define LSCHL_GPIO_FAN_LOW 16
> -#define LSCHL_GPIO_FAN_HIGH 14
> -#define LSCHL_GPIO_FAN_LOCK 6
> -
> -static struct gpio_fan_alarm lschl_alarm = {
> - .gpio = LSCHL_GPIO_FAN_LOCK,
> -};
> -
> -static struct gpio_fan_speed lschl_speeds[] = {
> - {
> - .rpm = 0,
> - .ctrl_val = 3,
> - }, {
> - .rpm = 1500,
> - .ctrl_val = 2,
> - }, {
> - .rpm = 3250,
> - .ctrl_val = 1,
> - }, {
> - .rpm = 5000,
> - .ctrl_val = 0,
> - },
> -};
> -
> -static int lschl_gpio_list[] = {
> - LSCHL_GPIO_FAN_HIGH, LSCHL_GPIO_FAN_LOW,
> -};
> -
> -static struct gpio_fan_platform_data lschl_fan_data = {
> - .num_ctrl = ARRAY_SIZE(lschl_gpio_list),
> - .ctrl = lschl_gpio_list,
> - .alarm = &lschl_alarm,
> - .num_speed = ARRAY_SIZE(lschl_speeds),
> - .speed = lschl_speeds,
> -};
> -
> -static struct platform_device lschl_fan_device = {
> - .name = "gpio-fan",
> - .id = -1,
> - .num_resources = 0,
> - .dev = {
> - .platform_data = &lschl_fan_data,
> - },
> -};
> -
> -/****************************************************************************
> - * GPIO Data
> - ****************************************************************************/
> -
> -static unsigned int lschl_mpp_modes[] __initdata = {
> - MPP0_GPIO, /* LED POWER */
> - MPP1_GPIO, /* HDD POWER */
> - MPP2_GPIO, /* LED ALARM */
> - MPP3_GPIO, /* LED INFO */
> - MPP4_UNUSED,
> - MPP5_UNUSED,
> - MPP6_GPIO, /* FAN LOCK */
> - MPP7_GPIO, /* SW INIT */
> - MPP8_GPIO, /* SW POWER */
> - MPP9_GPIO, /* USB POWER */
> - MPP10_GPIO, /* SW AUTO POWER */
> - MPP11_UNUSED,
> - MPP12_UNUSED,
> - MPP13_UNUSED,
> - MPP14_GPIO, /* FAN HIGH */
> - MPP15_GPIO, /* SW FUNC */
> - MPP16_GPIO, /* FAN LOW */
> - MPP17_GPIO, /* LED FUNC */
> - MPP18_UNUSED,
> - MPP19_UNUSED,
> - 0,
> -};
> -
> -static void __init lschl_init(void)
> -{
> - /*
> - * Setup basic Orion functions. Needs to be called early.
> - */
> - orion5x_init();
> -
> - orion5x_mpp_conf(lschl_mpp_modes);
> -
> - /*
> - * Configure peripherals.
> - */
> - orion5x_ehci0_init();
> - orion5x_ehci1_init();
> - orion5x_eth_init(&lschl_eth_data);
> - orion5x_i2c_init();
> - orion5x_sata_init(&lschl_sata_data);
> - orion5x_uart0_init();
> - orion5x_xor_init();
> -
> - mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
> - ORION_MBUS_DEVBUS_BOOT_ATTR,
> - LSCHL_NOR_BOOT_BASE,
> - LSCHL_NOR_BOOT_SIZE);
> - platform_device_register(&lschl_nor_flash);
> -
> - platform_device_register(&lschl_leds);
> -
> - platform_device_register(&lschl_button_device);
> -
> - platform_device_register(&lschl_fan_device);
> -
> - i2c_register_board_info(0, &lschl_i2c_rtc, 1);
> -
> - /* usb power on */
> - gpio_set_value(LSCHL_GPIO_USB_POWER, 1);
> -
> - /* register power-off method */
> - pm_power_off = lschl_power_off;
> -
> - pr_info("%s: finished\n", __func__);
> -}
> -
> -MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
> - /* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
> - .atag_offset = 0x100,
> - .nr_irqs = ORION5X_NR_IRQS,
> - .init_machine = lschl_init,
> - .map_io = orion5x_map_io,
> - .init_early = orion5x_init_early,
> - .init_irq = orion5x_init_irq,
> - .init_time = orion5x_timer_init,
> - .fixup = tag_fixup_mem32,
> - .restart = orion5x_restart,
> -MACHINE_END
> -- 2.7.4
>
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH] ARM: mvebu: Update comment for main PLL frequency
From: Gregory CLEMENT @ 2016-11-04 12:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025235242.31764-1-chris.packham@alliedtelesis.co.nz>
Hi Chris,
On mer., oct. 26 2016, Chris Packham <chris.packham@alliedtelesis.co.nz> wrote:
> The actual frequency was updated in commit ae142bd99765 ("ARM: mvebu:
> Fix the main PLL frequency on Armada 375, 38x and 39x SoCs") but the
> comment was not updated. Update it now.
>
> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Applied on mvebu/dt
Thanks,
Gregory
> ---
> arch/arm/boot/dts/armada-375.dtsi | 2 +-
> arch/arm/boot/dts/armada-38x.dtsi | 2 +-
> arch/arm/boot/dts/armada-39x.dtsi | 2 +-
> 3 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi
> index cc952cf8ec30..45fa92f9cf5c 100644
> --- a/arch/arm/boot/dts/armada-375.dtsi
> +++ b/arch/arm/boot/dts/armada-375.dtsi
> @@ -65,7 +65,7 @@
> };
>
> clocks {
> - /* 2 GHz fixed main PLL */
> + /* 1 GHz fixed main PLL */
> mainpll: mainpll {
> compatible = "fixed-clock";
> #clock-cells = <0>;
> diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
> index 2d7668848c5a..7450e9fea45d 100644
> --- a/arch/arm/boot/dts/armada-38x.dtsi
> +++ b/arch/arm/boot/dts/armada-38x.dtsi
> @@ -661,7 +661,7 @@
> };
>
> clocks {
> - /* 2 GHz fixed main PLL */
> + /* 1 GHz fixed main PLL */
> mainpll: mainpll {
> compatible = "fixed-clock";
> #clock-cells = <0>;
> diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/armada-39x.dtsi
> index 34cba87f9200..de171baffcf6 100644
> --- a/arch/arm/boot/dts/armada-39x.dtsi
> +++ b/arch/arm/boot/dts/armada-39x.dtsi
> @@ -573,7 +573,7 @@
> };
>
> clocks {
> - /* 2 GHz fixed main PLL */
> + /* 1 GHz fixed main PLL */
> mainpll: mainpll {
> compatible = "fixed-clock";
> #clock-cells = <0>;
> --
> 2.10.1
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH] ARM: dts: armada-370-rn102: add pinmuxing for i2c0
From: Gregory CLEMENT @ 2016-11-04 12:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020191942.30616-1-u.kleine-koenig@pengutronix.de>
Hi Uwe,
On jeu., oct. 20 2016, Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de> wrote:
> Up to now a working i2c bus depended on the bootloader to configure the
> pinmuxing. Make it explicit.
>
> As a side effect this change makes i2c work in barebox.
>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Applied on mvebu/dt
Thanks,
Gregory
> ---
> arch/arm/boot/dts/armada-370-netgear-rn102.dts | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
> index 3ca6330a1752..a9e3810aea65 100644
> --- a/arch/arm/boot/dts/armada-370-netgear-rn102.dts
> +++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
> @@ -121,6 +121,10 @@
>
> i2c at 11000 {
> clock-frequency = <100000>;
> +
> + pinctrl-0 = <&i2c0_pins>;
> + pinctrl-names = "default";
> +
> status = "okay";
>
> isl12057: isl12057 at 68 {
> --
> 2.9.3
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH] ARM: dts: armada-370-rn102: drop specification of compatible for i2c0
From: Gregory CLEMENT @ 2016-11-04 12:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020191527.27679-1-u.kleine-koenig@pengutronix.de>
Hi Uwe,
On jeu., oct. 20 2016, Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de> wrote:
> The compatible string is already provided by armada-370.dtsi.
>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Applied on mvebu/dt
Thanks,
Gregory
> ---
> Hello,
>
> this is the same as commit 43940ce3b089962f97de544d72b783bd146ef362 that
> currently is in next, just for rn102 instead of rn104.
>
> Best regards
> Uwe
>
> arch/arm/boot/dts/armada-370-netgear-rn102.dts | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
> index 39181b3fa90d..3ca6330a1752 100644
> --- a/arch/arm/boot/dts/armada-370-netgear-rn102.dts
> +++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
> @@ -120,7 +120,6 @@
> };
>
> i2c at 11000 {
> - compatible = "marvell,mv64xxx-i2c";
> clock-frequency = <100000>;
> status = "okay";
>
> --
> 2.9.3
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH 2/3] ARM: cache-uniphier: refactor jump label to follow coding style guideline
From: Russell King - ARM Linux @ 2016-11-04 12:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478259816-24965-3-git-send-email-yamada.masahiro@socionext.com>
On Fri, Nov 04, 2016 at 08:43:35PM +0900, Masahiro Yamada wrote:
> Documentation/CodingStyle recommends to use label names which say
> what the goto does or why the goto exists.
>
> Just in case, split it up into three labels because the CodingStyle
> says "one err bugs" is a common type of bug (although, I do not
> believe the current code includes such a bug).
However, this has the effect of making the code unnecessarily more
complicated, which is a bad thing. Avoiding unnecessary code
complexity wins over style rules.
--
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
* [PATCH] bus: vexpress-config: fix device reference leak
From: Russell King - ARM Linux @ 2016-11-04 12:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478259746.17152.126.camel@arm.com>
On Fri, Nov 04, 2016 at 11:42:26AM +0000, Pawel Moll wrote:
> On Tue, 2016-11-01 at 11:43 +0100, Johan Hovold wrote:
> > Make sure to drop the reference to the parent device taken by
> > class_find_device() after populating the bus.
> >
> > Fixes: 3b9334ac835b ("mfd: vexpress: Convert custom func API to
> > regmap")
> > Signed-off-by: Johan Hovold <johan@kernel.org>
>
> You're right. May I ask how did you figure it out? The get_device()
> happening in class_find_device() is a bit obscure,
It's not obscure at all - all the functions that find a device do so
under a lock to ensure that the device does not go away, and they
take a reference count on the device before returning the pointer for
exactly the same reason.
If they didn't do that, the find function could locate a struct device
while another thread is deleting the struct device, and it would then
return a stale pointer - and dereferencing that pointer would then be
a use-after-free bug.
So not obscure, but rather fundamentally necessary.
--
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
* [PATCH 3/3] ARM: cache-uniphier: clean up active way setup code
From: Masahiro Yamada @ 2016-11-04 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478259816-24965-1-git-send-email-yamada.masahiro@socionext.com>
Now, the active way setup function is called with a fixed value zero
for the second argument only when enabling the outer-cache.
The code can be simpler.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
arch/arm/mm/cache-uniphier.c | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mm/cache-uniphier.c b/arch/arm/mm/cache-uniphier.c
index c71ab7c..58ba2bd 100644
--- a/arch/arm/mm/cache-uniphier.c
+++ b/arch/arm/mm/cache-uniphier.c
@@ -71,8 +71,7 @@
* @ctrl_base: virtual base address of control registers
* @rev_base: virtual base address of revision registers
* @op_base: virtual base address of operation registers
- * @way_present_mask: each bit specifies if the way is present
- * @way_locked_mask: each bit specifies if the way is locked
+ * @way_mask: each bit specifies if the way is present
* @nsets: number of associativity sets
* @line_size: line size in bytes
* @range_op_max_size: max size that can be handled by a single range operation
@@ -83,8 +82,7 @@ struct uniphier_cache_data {
void __iomem *rev_base;
void __iomem *op_base;
void __iomem *way_ctrl_base;
- u32 way_present_mask;
- u32 way_locked_mask;
+ u32 way_mask;
u32 nsets;
u32 line_size;
u32 range_op_max_size;
@@ -234,17 +232,13 @@ static void __uniphier_cache_enable(struct uniphier_cache_data *data, bool on)
writel_relaxed(val, data->ctrl_base + UNIPHIER_SSCC);
}
-static void __init __uniphier_cache_set_locked_ways(
- struct uniphier_cache_data *data,
- u32 way_mask)
+static void __init __uniphier_cache_set_active_ways(
+ struct uniphier_cache_data *data)
{
unsigned int cpu;
- data->way_locked_mask = way_mask & data->way_present_mask;
-
for_each_possible_cpu(cpu)
- writel_relaxed(~data->way_locked_mask & data->way_present_mask,
- data->way_ctrl_base + 4 * cpu);
+ writel_relaxed(data->way_mask, data->way_ctrl_base + 4 * cpu);
}
static void uniphier_cache_maint_range(unsigned long start, unsigned long end,
@@ -307,7 +301,7 @@ static void __init uniphier_cache_enable(void)
list_for_each_entry(data, &uniphier_cache_list, list) {
__uniphier_cache_enable(data, true);
- __uniphier_cache_set_locked_ways(data, 0);
+ __uniphier_cache_set_active_ways(data);
}
}
@@ -381,7 +375,7 @@ static int __init __uniphier_cache_init(struct device_node *np,
data->line_size = line_size;
data->nsets = nsets;
- data->way_present_mask = ((u32)1 << cache_size / nsets / line_size) - 1;
+ data->way_mask = GENMASK(cache_size / nsets / line_size - 1, 0);
data->ctrl_base = of_iomap(np, 0);
if (!data->ctrl_base) {
--
1.9.1
^ permalink raw reply related
* [PATCH 2/3] ARM: cache-uniphier: refactor jump label to follow coding style guideline
From: Masahiro Yamada @ 2016-11-04 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478259816-24965-1-git-send-email-yamada.masahiro@socionext.com>
Documentation/CodingStyle recommends to use label names which say
what the goto does or why the goto exists.
Just in case, split it up into three labels because the CodingStyle
says "one err bugs" is a common type of bug (although, I do not
believe the current code includes such a bug).
During the refactoring, iounmap(data->op_base) turned out to have no
corresponding bail-out point, so remove it.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
arch/arm/mm/cache-uniphier.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mm/cache-uniphier.c b/arch/arm/mm/cache-uniphier.c
index 58f2ddb..c71ab7c 100644
--- a/arch/arm/mm/cache-uniphier.c
+++ b/arch/arm/mm/cache-uniphier.c
@@ -387,21 +387,21 @@ static int __init __uniphier_cache_init(struct device_node *np,
if (!data->ctrl_base) {
pr_err("L%d: failed to map control register\n", *cache_level);
ret = -ENOMEM;
- goto err;
+ goto free_mem;
}
data->rev_base = of_iomap(np, 1);
if (!data->rev_base) {
pr_err("L%d: failed to map revision register\n", *cache_level);
ret = -ENOMEM;
- goto err;
+ goto unmap_ctrl;
}
data->op_base = of_iomap(np, 2);
if (!data->op_base) {
pr_err("L%d: failed to map operation register\n", *cache_level);
ret = -ENOMEM;
- goto err;
+ goto unmap_rev;
}
data->way_ctrl_base = data->ctrl_base + 0xc00;
@@ -451,10 +451,12 @@ static int __init __uniphier_cache_init(struct device_node *np,
of_node_put(next_np);
return ret;
-err:
- iounmap(data->op_base);
+
+unmap_rev:
iounmap(data->rev_base);
+unmap_ctrl:
iounmap(data->ctrl_base);
+free_mem:
kfree(data);
return ret;
--
1.9.1
^ permalink raw reply related
* [PATCH 1/3] ARM: cache-uniphier: call kzalloc() after DT property parsing
From: Masahiro Yamada @ 2016-11-04 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478259816-24965-1-git-send-email-yamada.masahiro@socionext.com>
Allocate memory after DT property parsing that has more possibility
of failure. This will decrease the number of bail-out points for
kfree().
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
arch/arm/mm/cache-uniphier.c | 34 ++++++++++++++++------------------
1 file changed, 16 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mm/cache-uniphier.c b/arch/arm/mm/cache-uniphier.c
index dfe97b4..58f2ddb 100644
--- a/arch/arm/mm/cache-uniphier.c
+++ b/arch/arm/mm/cache-uniphier.c
@@ -328,7 +328,7 @@ static int __init __uniphier_cache_init(struct device_node *np,
unsigned int *cache_level)
{
struct uniphier_cache_data *data;
- u32 level, cache_size;
+ u32 level, line_size, nsets, cache_size;
struct device_node *next_np;
int ret = 0;
@@ -354,36 +354,34 @@ static int __init __uniphier_cache_init(struct device_node *np,
return -EINVAL;
}
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- if (of_property_read_u32(np, "cache-line-size", &data->line_size) ||
- !is_power_of_2(data->line_size)) {
+ if (of_property_read_u32(np, "cache-line-size", &line_size) |
+ !is_power_of_2(line_size)) {
pr_err("L%d: cache-line-size is unspecified or invalid\n",
*cache_level);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
- if (of_property_read_u32(np, "cache-sets", &data->nsets) ||
- !is_power_of_2(data->nsets)) {
+ if (of_property_read_u32(np, "cache-sets", &nsets) ||
+ !is_power_of_2(nsets)) {
pr_err("L%d: cache-sets is unspecified or invalid\n",
*cache_level);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
if (of_property_read_u32(np, "cache-size", &cache_size) ||
- cache_size == 0 || cache_size % (data->nsets * data->line_size)) {
+ cache_size == 0 || cache_size % (nsets * line_size)) {
pr_err("L%d: cache-size is unspecified or invalid\n",
*cache_level);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
- data->way_present_mask =
- ((u32)1 << cache_size / data->nsets / data->line_size) - 1;
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->line_size = line_size;
+ data->nsets = nsets;
+ data->way_present_mask = ((u32)1 << cache_size / nsets / line_size) - 1;
data->ctrl_base = of_iomap(np, 0);
if (!data->ctrl_base) {
--
1.9.1
^ permalink raw reply related
* [PATCH 0/3] ARM: cache-uniphier: slight cleanups and trivial coding style fix
From: Masahiro Yamada @ 2016-11-04 11:43 UTC (permalink / raw)
To: linux-arm-kernel
The cache-uniphier is a full-custom outer-cache for
Socionext UniPhier SoC family.
This series includes SoC-specific cleanups and
a trivial coding style fix suggested by Documentation/CodingStyle.
Masahiro Yamada (3):
ARM: cache-uniphier: call kzalloc() after DT property parsing
ARM: cache-uniphier: refactor jump label to follow coding style
guideline
ARM: cache-uniphier: clean up active way setup code
arch/arm/mm/cache-uniphier.c | 64 ++++++++++++++++++++------------------------
1 file changed, 29 insertions(+), 35 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v2] ARM: DTS: r8a7794: alt: Fix PFC names for DU
From: Sergei Shtylyov @ 2016-11-04 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478201686-25488-1-git-send-email-jacopo@jmondi.org>
Hello.
On 11/3/2016 10:34 PM, Jacopo Mondi wrote:
> Update the PFC pin groups and function names of DU interface for
> r8a7794 ALT board.
>
> The currently specified pin groups and function names prevented PFC and
> DU interfaces from being correctly configured:
>
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> rcar-du: probe of feb00000.display failed with error -22
>
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Acked-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
MBR, Sergei
^ permalink raw reply
* [PATCH] bus: vexpress-config: fix device reference leak
From: Pawel Moll @ 2016-11-04 11:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477997017-29103-1-git-send-email-johan@kernel.org>
On Tue, 2016-11-01 at 11:43 +0100, Johan Hovold wrote:
> Make sure to drop the reference to the parent device taken by
> class_find_device() after populating the bus.
>
> Fixes: 3b9334ac835b ("mfd: vexpress: Convert custom func API to
> regmap")
> Signed-off-by: Johan Hovold <johan@kernel.org>
You're right. May I ask how did you figure it out? The get_device()
happening in class_find_device() is a bit obscure, so have you simply
followed places where it's being used or used some static (?) analysis
tool? If the latter, I'd be very curios to hear what was it :-)
Acked-by: Pawel Moll <pawel.moll@arm.com>
Thanks!
Pawel
^ permalink raw reply
* [RFC v2 0/8] KVM PCIe/MSI passthrough on ARM/ARM64 - Alt II
From: Eric Auger @ 2016-11-04 11:23 UTC (permalink / raw)
To: linux-arm-kernel
Following Will & Robin's suggestions, this series attempts to propose
an alternative to [1] where the host would arbitrarily decide the
location of the IOVA MSI window and would be able to report to the
userspace the list of reserved IOVA regions that cannot be used
along with VFIO_IOMMU_MAP_DMA. This would allow the userspace to react
in case of conflict.
Userspace can retrieve all the reserved regions through the VFIO_IOMMU_GET_INFO
IOCTL by querying the new RESV_IOVA_RANGE chained capability. Each reserved
IOVA range is put in a separate capability.
At IOMMU level, the reserved regions are stored in an iommu_domain list
which is populated on each device attachment. An IOMMU add_reserved_regions
callback specializes the registration of the reserved regions.
On x86, the [FEE0_0000h - FEF0_000h] MSI window is registered (NOT tested).
On ARM, the PCI host bridge windows (ACS check to be added?) + the MSI IOVA
reserved regions are populated by the arm-smmu driver. Currently the MSI
IOVA region is arbitrarily located at 0x8000000 and 1MB sized. An IOVA domain
is created in add_reserved_regions callback. Then MSIs transparently are
mapped using this IOVA domain.
This series currently does not address some features addressed in [1]:
- MSI IOVA size requirement computation
- IRQ safety assessment
This RFC was just tested on ARM Overdrive with QEMU and is sent to help
potential discussions at LPC. Additionnal development + testing is needed.
2 tentative fixes may be submitted separately:
- vfio: fix vfio_info_cap_add/shift
- iommu/iova: fix __alloc_and_insert_iova_range
Best Regards
[1] [PATCH v14 00/16] KVM PCIe/MSI passthrough on ARM/ARM64
https://lkml.org/lkml/2016/10/12/347
Git: complete series available at
https://github.com/eauger/linux/tree/v4.9-rc3-reserved-rfc-v2
History:
RFC v1 -> v2:
- no functional change despite Alex' first feedback:
waiting for LPC discussion outcome
- fix intel_add_reserved_regions
- add mutex lock/unlock in vfio_iommu_type1
Eric Auger (7):
vfio: fix vfio_info_cap_add/shift
iommu/iova: fix __alloc_and_insert_iova_range
iommu: Add a list of iommu_reserved_region in iommu_domain
vfio/type1: Introduce RESV_IOVA_RANGE capability
iommu: Handle the list of reserved regions
iommu/vt-d: Implement add_reserved_regions callback
iommu/arm-smmu: implement add_reserved_regions callback
Robin Murphy (1):
iommu/dma: Allow MSI-only cookies
drivers/iommu/arm-smmu.c | 66 ++++++++++++++++++++++++++++++++++++++
drivers/iommu/dma-iommu.c | 39 +++++++++++++++++++++++
drivers/iommu/intel-iommu.c | 48 ++++++++++++++++++++--------
drivers/iommu/iommu.c | 25 +++++++++++++++
drivers/iommu/iova.c | 2 +-
drivers/vfio/vfio.c | 5 +--
drivers/vfio/vfio_iommu_type1.c | 70 ++++++++++++++++++++++++++++++++++++++++-
include/linux/dma-iommu.h | 9 ++++++
include/linux/iommu.h | 23 ++++++++++++++
include/uapi/linux/vfio.h | 16 +++++++++-
10 files changed, 285 insertions(+), 18 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 0/10] mmc: Add support to Marvell Xenon SD Host Controller
From: Gregory CLEMENT @ 2016-11-04 11:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.86006f271b60cf7c0b4c5a51762a9dacca4c4718.1477911954.git-series.gregory.clement@free-electrons.com>
Hi,
On lun., oct. 31 2016, Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> Hello,
>
> This the second version of the series adding support for the SDHCI
> Xenon controller. It can be currently found on the Armada 37xx and the
> Armada 7K/8K but will be also used in more Marvell SoC (and not only
> the mvebu ones actually).
>
> Some of the remarks had been taking into account since the first
> version, according to Ziji Hu, here are the following chcanges:
> "Changes in V2:
> rebase on v4.9-rc2.
> Re-write Xenon bindings. Ajust Xenon DT property naming.
> Add a new DT property to indicate eMMC card type, instead of using
> variable card_candidate.
> Clear quirks SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 in Xenon platform data
> Add support to HS400 retuning."
>
> I think the main open point which remains is about issuing commands
> from the ->set_ios() callback (in patch 7).
> Ulf, could you comment about it?
A few comments:
- I forgot to add the v2 prefix on the series I hope it won't be too
annoying, if needed I can re-post the series with the correct title.
- I also forgot to add my Reviewed-by flag on the 7 first patches, I
will add them back on the v3.
- For the ones who want to get the series using git here is the place
you can get it here:
repository: git at github.com:MISL-EBU-System-SW/mainline-public.git
branch: sdhci-xenon-v2
Thanks,
Gregory
>
> Thanks,
>
> Gregory
>
> Gregory CLEMENT (3):
> arm64: dts: marvell: add eMMC support for Armada 37xx
> arm64: dts: marvell: add sdhci support for Armada 7K/8K
> arm64: configs: enable SDHCI driver for Xenon
>
> Ziji Hu (7):
> mmc: sdhci: Export sdhci_set_ios() from sdhci.c
> mmc: sdhci: Export sdhci_start_signal_voltage_switch() in sdhci.c
> mmc: sdhci: Export sdhci_execute_tuning() in sdhci.c
> MAINTAINERS: add entry for Marvell Xenon MMC Host Controller drivers
> dt: bindings: Add bindings for Marvell Xenon SD Host Controller
> mmc: sdhci-xenon: Add Marvell Xenon SDHC core functionality
> mmc: sdhci-xenon: Add support to PHYs of Marvell Xenon SDHC
>
> Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt | 161 +-
> MAINTAINERS | 7 +-
> arch/arm64/boot/dts/marvell/armada-3720-db.dts | 8 +-
> arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 11 +-
> arch/arm64/boot/dts/marvell/armada-7040-db.dts | 8 +-
> arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 9 +-
> arch/arm64/configs/defconfig | 1 +-
> drivers/mmc/host/Kconfig | 9 +-
> drivers/mmc/host/Makefile | 3 +-
> drivers/mmc/host/sdhci-xenon-phy.c | 1181 +++++++-
> drivers/mmc/host/sdhci-xenon-phy.h | 157 +-
> drivers/mmc/host/sdhci-xenon.c | 598 ++++-
> drivers/mmc/host/sdhci-xenon.h | 159 +-
> drivers/mmc/host/sdhci.c | 11 +-
> drivers/mmc/host/sdhci.h | 4 +-
> 15 files changed, 2323 insertions(+), 4 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
> create mode 100644 drivers/mmc/host/sdhci-xenon-phy.c
> create mode 100644 drivers/mmc/host/sdhci-xenon-phy.h
> create mode 100644 drivers/mmc/host/sdhci-xenon.c
> create mode 100644 drivers/mmc/host/sdhci-xenon.h
>
> base-commit: 9fe68cad6e74967b88d0c6aeca7d9cd6b6e91942
> --
> git-series 0.8.10
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH 10/13] ARM: dts: exynos: replace to "max-frequecy" instead of "clock-freq-min-max"
From: Heiko Stuebner @ 2016-11-04 11:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ecf4fac2-0ab7-d4c4-69e3-d498ee5b601c@samsung.com>
Hi Jaehoon,
Am Freitag, 4. November 2016, 19:21:30 CET schrieb Jaehoon Chung:
> On 11/04/2016 03:41 AM, Krzysztof Kozlowski wrote:
> > On Thu, Nov 03, 2016 at 03:21:32PM +0900, Jaehoon Chung wrote:
> >> In drivers/mmc/core/host.c, there is "max-frequency" property.
> >> It should be same behavior. So Use the "max-frequency" instead of
> >> "clock-freq-min-max".
> >>
> >> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
> >> ---
> >>
> >> arch/arm/boot/dts/exynos3250-artik5-eval.dts | 2 +-
> >> arch/arm/boot/dts/exynos3250-artik5.dtsi | 2 +-
> >> arch/arm/boot/dts/exynos3250-monk.dts | 2 +-
> >> arch/arm/boot/dts/exynos3250-rinato.dts | 2 +-
> >> 4 files changed, 4 insertions(+), 4 deletions(-)
> >
> > This looks totally independent to rest of patches so it can be applied
> > separately without any functional impact (except lack of minimum
> > frequency). Is that correct?
>
> You're right. I will split the patches. And will resend.
> Thanks!
I think what Krzysztof was asking was just if he can simply pick up this patch
alone, as it does not require any of the previous changes.
Same is true for the Rockchip patches I guess, so we could just take them
individually into samsung/rockchip dts branches.
Heiko
^ permalink raw reply
* [PATCH 6/6] ARM: dts: rockchip: add rockchip RK1108 Evaluation board
From: Heiko Stuebner @ 2016-11-04 11:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ce6e9d62-75e5-60bc-2775-507aa326e3a2@rock-chips.com>
Am Freitag, 4. November 2016, 18:54:35 CET schrieb Andy Yan:
> Hi Heiko:
>
> On 2016?11?04? 18:03, Heiko Stuebner wrote:
> > Am Donnerstag, 3. November 2016, 20:43:59 CET schrieb Andy Yan:
> >> RK1108EVB is designed by Rockchip for CVR field.
> >> This patch add basic support for it, which can boot with
> >> initramfs into shell.
> >>
> >> Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
> >
> > looks good, the only thing I can also change myself is moving the board in
> > the rockchip.txt to the block of Rockchip boards (i.e. sorting by
> > manufacturer and board name).
> >
> >
> > Heiko
>
> You mean it's better to put it between "Rockchip RK3368 evb" and
> "Rockchip PX5 Evaluation board"? if so, I will change it in next version.
yep, that is the location I also would've moved it to :-) .
^ permalink raw reply
* [PATCH v8 7/7] arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl
From: vijay.kilari at gmail.com @ 2016-11-04 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478258013-6669-1-git-send-email-vijay.kilari@gmail.com>
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
Userspace requires to store and restore of line_level for
level triggered interrupts using ioctl KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO.
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
---
arch/arm64/include/uapi/asm/kvm.h | 6 +++++
virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
virt/kvm/arm/vgic/vgic-mmio-v3.c | 11 ++++++++
virt/kvm/arm/vgic/vgic-mmio.c | 33 ++++++++++++++++++++++++
virt/kvm/arm/vgic/vgic-mmio.h | 5 ++++
virt/kvm/arm/vgic/vgic.h | 3 +++
6 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 91c7137..4100f8c 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -211,6 +211,12 @@ struct kvm_arch_memory_slot {
#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_GRP_LEVEL_INFO 7
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
+ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
+#define VGIC_LEVEL_INFO_LINE_LEVEL 0
#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index da532d1..0f82a91 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -512,6 +512,25 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
regid, reg);
break;
}
+ case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+ unsigned int info, intid;
+
+ info = (attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
+ KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT;
+ if (info == VGIC_LEVEL_INFO_LINE_LEVEL) {
+ if (is_write)
+ tmp32 = *reg;
+ intid = attr->attr &
+ KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK;
+ ret = vgic_v3_line_level_info_uaccess(vcpu, is_write,
+ intid, &tmp32);
+ if (!is_write)
+ *reg = tmp32;
+ } else {
+ ret = -EINVAL;
+ }
+ break;
+ }
default:
ret = -EINVAL;
break;
@@ -554,6 +573,17 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
return vgic_v3_attr_regs_access(dev, attr, ®, true);
}
+ case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ u64 reg;
+ u32 tmp32;
+
+ if (get_user(tmp32, uaddr))
+ return -EFAULT;
+
+ reg = tmp32;
+ return vgic_v3_attr_regs_access(dev, attr, ®, true);
+ }
}
return -ENXIO;
}
@@ -589,8 +619,18 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
return ret;
return put_user(reg, uaddr);
}
- }
+ case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ u64 reg;
+ u32 tmp32;
+ ret = vgic_v3_attr_regs_access(dev, attr, ®, false);
+ if (ret)
+ return ret;
+ tmp32 = reg;
+ return put_user(tmp32, uaddr);
+ }
+ }
return -ENXIO;
}
@@ -611,11 +651,19 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
return vgic_v3_has_attr_regs(dev, attr);
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
return 0;
+ case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+ if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
+ KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) ==
+ VGIC_LEVEL_INFO_LINE_LEVEL)
+ return 0;
+ break;
+ }
case KVM_DEV_ARM_VGIC_GRP_CTRL:
switch (attr->attr) {
case KVM_DEV_ARM_VGIC_CTRL_INIT:
return 0;
}
+ break;
}
return -ENXIO;
}
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 519b919..38b481c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -807,3 +807,14 @@ int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
return vgic_uaccess(vcpu, &rd_dev, is_write,
offset, val);
}
+
+int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+ u32 intid, u32 *val)
+{
+ if (is_write)
+ vgic_write_irq_line_level_info(vcpu, intid, *val);
+ else
+ *val = vgic_read_irq_line_level_info(vcpu, intid);
+
+ return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 173d6f0..fb018eb 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -371,6 +371,39 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
}
}
+unsigned long vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid)
+{
+ int i;
+ unsigned long val = 0;
+
+ for (i = 0; i < 32; i++) {
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+ if (irq->line_level)
+ val |= (1U << i);
+
+ vgic_put_irq(vcpu->kvm, irq);
+ }
+
+ return val;
+}
+
+void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
+ const unsigned long val)
+{
+ int i;
+
+ for_each_set_bit(i, &val, 32) {
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+ spin_lock(&irq->irq_lock);
+ irq->line_level = true;
+ spin_unlock(&irq->irq_lock);
+
+ vgic_put_irq(vcpu->kvm, irq);
+ }
+}
+
static int match_region(const void *key, const void *elt)
{
const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index acbf99e..938702c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -181,6 +181,11 @@ int vgic_validate_mmio_region_addr(struct kvm_device *dev,
const struct vgic_register_region *regions,
int nr_regions, gpa_t addr);
+unsigned long vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid);
+
+void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
+ const unsigned long val);
+
unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 0e632d0..77d3d84 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -130,6 +130,9 @@ 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);
+int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+ u32 intid, u32 *val);
+
#else
static inline int vgic_register_its_iodevs(struct kvm *kvm)
{
--
1.9.1
^ permalink raw reply related
* [PATCH v8 6/7] arm/arm64: vgic: Implement VGICv3 CPU interface access
From: vijay.kilari at gmail.com @ 2016-11-04 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478258013-6669-1-git-send-email-vijay.kilari@gmail.com>
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
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, ®, 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, ®, 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, ®, 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, ®);
+ }
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
@@ -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
+ */
+ 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;
+
+ 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;
+
+ 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;
+ vgic_set_vmcr(vcpu, &vmcr);
+ } 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;
+
+ 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;
+ 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);
+ }
+
+ 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, ¶ms, 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, ¶ms, gic_v3_icc_reg_descs,
+ ARRAY_SIZE(gic_v3_icc_reg_descs));
+ if (!r)
+ return -ENXIO;
+
+ if (!r->access(vcpu, ¶ms, r))
+ return -EINVAL;
+
+ 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)
{
--
1.9.1
^ permalink raw reply related
* [PATCH v8 5/7] arm/arm64: vgic: Introduce VENG0 and VENG1 fields to vmcr struct
From: vijay.kilari at gmail.com @ 2016-11-04 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478258013-6669-1-git-send-email-vijay.kilari@gmail.com>
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;
vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
+ vmcr |= (vmcrp->grpen0 << ICH_VMCR_ENG0_SHIFT) & ICH_VMCR_ENG0_MASK;
+ vmcr |= (vmcrp->grpen1 << ICH_VMCR_ENG1_SHIFT) & ICH_VMCR_ENG1_MASK;
vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
}
@@ -187,10 +190,13 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
{
u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
- vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
+ vmcrp->ctlr = (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+ vmcrp->ctlr |= (vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT;
vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
vmcrp->bpr = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
vmcrp->pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+ vmcrp->grpen0 = (vmcr & ICH_VMCR_ENG0_MASK) >> ICH_VMCR_ENG0_SHIFT;
+ vmcrp->grpen1 = (vmcr & ICH_VMCR_ENG1_MASK) >> ICH_VMCR_ENG1_SHIFT;
}
#define INITIAL_PENDBASER_VALUE \
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index d901b0c..c461f6b 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -63,6 +63,9 @@ struct vgic_vmcr {
u32 abpr;
u32 bpr;
u32 pmr;
+ /* Below member variable are valid only for GICv3 */
+ u32 grpen0;
+ u32 grpen1;
};
struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
@@ -150,6 +153,8 @@ static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
#endif
int kvm_register_vgic_device(unsigned long type);
+void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
int vgic_lazy_init(struct kvm *kvm);
int vgic_init(struct kvm *kvm);
--
1.9.1
^ permalink raw reply related
* [PATCH v8 4/7] irqchip/gic-v3: Add missing system register definitions
From: vijay.kilari at gmail.com @ 2016-11-04 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478258013-6669-1-git-send-email-vijay.kilari@gmail.com>
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
Define register definitions for ICH_VMCR_EL2, ICC_CTLR_EL1 and
ICH_VTR_EL2, ICC_BPR0_EL1, ICC_BPR1_EL1 registers.
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
---
include/linux/irqchip/arm-gic-v3.h | 43 ++++++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index b7e3431..d48d886 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -352,8 +352,30 @@
/*
* CPU interface registers
*/
-#define ICC_CTLR_EL1_EOImode_drop_dir (0U << 1)
-#define ICC_CTLR_EL1_EOImode_drop (1U << 1)
+#define ICC_CTLR_EL1_EOImode_SHIFT (1)
+#define ICC_CTLR_EL1_EOImode_drop_dir (0U << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_EOImode_drop (1U << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_EOImode_MASK (1 << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_CBPR_SHIFT 0
+#define ICC_CTLR_EL1_CBPR_MASK (1 << ICC_CTLR_EL1_CBPR_SHIFT)
+#define ICC_CTLR_EL1_PRI_BITS_SHIFT 8
+#define ICC_CTLR_EL1_PRI_BITS_MASK (0x7 << ICC_CTLR_EL1_PRI_BITS_SHIFT)
+#define ICC_CTLR_EL1_ID_BITS_SHIFT 11
+#define ICC_CTLR_EL1_ID_BITS_MASK (0x7 << ICC_CTLR_EL1_ID_BITS_SHIFT)
+#define ICC_CTLR_EL1_SEIS_SHIFT 14
+#define ICC_CTLR_EL1_SEIS_MASK (0x1 << ICC_CTLR_EL1_SEIS_SHIFT)
+#define ICC_CTLR_EL1_A3V_SHIFT 15
+#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
+#define ICC_PMR_EL1_SHIFT 0
+#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
+#define ICC_BPR0_EL1_SHIFT 0
+#define ICC_BPR0_EL1_MASK (0x7 << ICC_BPR0_EL1_SHIFT)
+#define ICC_BPR1_EL1_SHIFT 0
+#define ICC_BPR1_EL1_MASK (0x7 << ICC_BPR1_EL1_SHIFT)
+#define ICC_IGRPEN0_EL1_SHIFT 0
+#define ICC_IGRPEN0_EL1_MASK (1 << ICC_IGRPEN0_EL1_SHIFT)
+#define ICC_IGRPEN1_EL1_SHIFT 0
+#define ICC_IGRPEN1_EL1_MASK (1 << ICC_IGRPEN1_EL1_SHIFT)
#define ICC_SRE_EL1_SRE (1U << 0)
/*
@@ -384,12 +406,29 @@
#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
+#define ICH_VMCR_EOIM_MASK (1 << ICH_VMCR_EOIM_SHIFT)
#define ICH_VMCR_BPR1_SHIFT 18
#define ICH_VMCR_BPR1_MASK (7 << ICH_VMCR_BPR1_SHIFT)
#define ICH_VMCR_BPR0_SHIFT 21
#define ICH_VMCR_BPR0_MASK (7 << ICH_VMCR_BPR0_SHIFT)
#define ICH_VMCR_PMR_SHIFT 24
#define ICH_VMCR_PMR_MASK (0xffUL << ICH_VMCR_PMR_SHIFT)
+#define ICH_VMCR_ENG0_SHIFT 0
+#define ICH_VMCR_ENG0_MASK (1 << ICH_VMCR_ENG0_SHIFT)
+#define ICH_VMCR_ENG1_SHIFT 1
+#define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT)
+
+#define ICH_VTR_PRI_BITS_SHIFT 29
+#define ICH_VTR_PRI_BITS_MASK (7 << ICH_VTR_PRI_BITS_SHIFT)
+#define ICH_VTR_ID_BITS_SHIFT 23
+#define ICH_VTR_ID_BITS_MASK (7 << ICH_VTR_ID_BITS_SHIFT)
+#define ICH_VTR_SEIS_SHIFT 22
+#define ICH_VTR_SEIS_MASK (1 << ICH_VTR_SEIS_SHIFT)
+#define ICH_VTR_A3V_SHIFT 21
+#define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT)
#define ICC_IAR1_EL1_SPURIOUS 0x3ff
--
1.9.1
^ permalink raw reply related
* [PATCH v8 3/7] arm/arm64: vgic: Introduce find_reg_by_id()
From: vijay.kilari at gmail.com @ 2016-11-04 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478258013-6669-1-git-send-email-vijay.kilari@gmail.com>
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
In order to implement vGICv3 CPU interface access, we will need to perform
table lookup of system registers. We would need both index_to_params() and
find_reg() exported for that purpose, but instead we export a single
function which combines them both.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
---
arch/arm64/kvm/sys_regs.c | 22 +++++++++++++++-------
arch/arm64/kvm/sys_regs.h | 4 ++++
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index f302fdb..1330d4c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1789,6 +1789,17 @@ static bool index_to_params(u64 id, struct sys_reg_params *params)
}
}
+const struct sys_reg_desc *find_reg_by_id(u64 id,
+ struct sys_reg_params *params,
+ const struct sys_reg_desc table[],
+ unsigned int num)
+{
+ if (!index_to_params(id, params))
+ return NULL;
+
+ return find_reg(params, table, num);
+}
+
/* Decode an index value, and find the sys_reg_desc entry. */
static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
u64 id)
@@ -1912,10 +1923,8 @@ static int get_invariant_sys_reg(u64 id, void __user *uaddr)
struct sys_reg_params params;
const struct sys_reg_desc *r;
- if (!index_to_params(id, ¶ms))
- return -ENOENT;
-
- r = find_reg(¶ms, invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs));
+ r = find_reg_by_id(id, ¶ms, invariant_sys_regs,
+ ARRAY_SIZE(invariant_sys_regs));
if (!r)
return -ENOENT;
@@ -1929,9 +1938,8 @@ static int set_invariant_sys_reg(u64 id, void __user *uaddr)
int err;
u64 val = 0; /* Make sure high bits are 0 for 32-bit regs */
- if (!index_to_params(id, ¶ms))
- return -ENOENT;
- r = find_reg(¶ms, invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs));
+ r = find_reg_by_id(id, ¶ms, invariant_sys_regs,
+ ARRAY_SIZE(invariant_sys_regs));
if (!r)
return -ENOENT;
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index dbbb01c..9c6ffd0 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -136,6 +136,10 @@ static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
return i1->Op2 - i2->Op2;
}
+const struct sys_reg_desc *find_reg_by_id(u64 id,
+ struct sys_reg_params *params,
+ const struct sys_reg_desc table[],
+ unsigned int num);
#define Op0(_x) .Op0 = _x
#define Op1(_x) .Op1 = _x
--
1.9.1
^ permalink raw reply related
* [PATCH v8 2/7] arm/arm64: vgic: Add distributor and redistributor access
From: vijay.kilari at gmail.com @ 2016-11-04 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478258013-6669-1-git-send-email-vijay.kilari@gmail.com>
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
VGICv3 Distributor and Redistributor registers are accessed using
KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_DIST_REGS
with KVM_SET_DEVICE_ATTR and KVM_GET_DEVICE_ATTR ioctls.
These registers are accessed as 32-bit and cpu mpidr
value passed along with register offset is used to identify the
cpu for redistributor 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: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
---
arch/arm64/include/uapi/asm/kvm.h | 4 +
virt/kvm/arm/vgic/vgic-kvm-device.c | 149 +++++++++++++++++++++++++++++++++---
virt/kvm/arm/vgic/vgic-mmio-v2.c | 16 +---
virt/kvm/arm/vgic/vgic-mmio-v3.c | 72 +++++++++++++++++
virt/kvm/arm/vgic/vgic-mmio.c | 22 ++++++
virt/kvm/arm/vgic/vgic-mmio.h | 4 +
virt/kvm/arm/vgic/vgic.h | 33 ++++++++
7 files changed, 276 insertions(+), 24 deletions(-)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 3051f86..56dc08d 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -201,10 +201,14 @@ struct kvm_arch_memory_slot {
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
+#define KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
+ (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_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_CTRL_INIT 0
/* Device Control API on vcpu fd */
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index ce1f4ed..6c7d30c 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -237,7 +237,7 @@ struct vgic_reg_attr {
gpa_t addr;
};
-static int parse_vgic_v2_attr(struct kvm_device *dev,
+static int vgic_v2_parse_attr(struct kvm_device *dev,
struct kvm_device_attr *attr,
struct vgic_reg_attr *reg_attr)
{
@@ -294,14 +294,14 @@ static bool lock_all_vcpus(struct kvm *kvm)
}
/**
- * vgic_attr_regs_access_v2 - allows user space to access VGIC v2 state
+ * vgic_v2_attr_regs_access - allows user space to access VGIC v2 state
*
* @dev: kvm device handle
* @attr: kvm device attribute
* @reg: address the value is read or written
* @is_write: true if userspace is writing a register
*/
-static int vgic_attr_regs_access_v2(struct kvm_device *dev,
+static int vgic_v2_attr_regs_access(struct kvm_device *dev,
struct kvm_device_attr *attr,
u32 *reg, bool is_write)
{
@@ -310,7 +310,7 @@ static int vgic_attr_regs_access_v2(struct kvm_device *dev,
struct kvm_vcpu *vcpu;
int ret;
- ret = parse_vgic_v2_attr(dev, attr, ®_attr);
+ ret = vgic_v2_parse_attr(dev, attr, ®_attr);
if (ret)
return ret;
@@ -319,9 +319,10 @@ static int vgic_attr_regs_access_v2(struct kvm_device *dev,
mutex_lock(&dev->kvm->lock);
- ret = vgic_init(dev->kvm);
- if (ret)
+ if (unlikely(!vgic_initialized(dev->kvm))) {
+ ret = -EBUSY;
goto out;
+ }
if (!lock_all_vcpus(dev->kvm)) {
ret = -EBUSY;
@@ -364,7 +365,7 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
if (get_user(reg, uaddr))
return -EFAULT;
- return vgic_attr_regs_access_v2(dev, attr, ®, true);
+ return vgic_v2_attr_regs_access(dev, attr, ®, true);
}
}
@@ -386,7 +387,7 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
u32 reg = 0;
- ret = vgic_attr_regs_access_v2(dev, attr, ®, false);
+ ret = vgic_v2_attr_regs_access(dev, attr, ®, false);
if (ret)
return ret;
return put_user(reg, uaddr);
@@ -430,16 +431,141 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
.has_attr = vgic_v2_has_attr,
};
+static int vgic_v3_parse_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ struct vgic_reg_attr *reg_attr)
+{
+ unsigned long vgic_mpidr, mpidr_reg;
+
+ vgic_mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
+ KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;
+
+ mpidr_reg = VGIC_TO_MPIDR(vgic_mpidr);
+ reg_attr->vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr_reg);
+ if (!reg_attr->vcpu)
+ return -EINVAL;
+
+ reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+ return 0;
+}
+
+/*
+ * vgic_v3_attr_regs_access - allows user space to access VGIC v3 state
+ *
+ * @dev: kvm device handle
+ * @attr: kvm device attribute
+ * @reg: address the value is read or written
+ * @is_write: true if userspace is writing a register
+ */
+static int vgic_v3_attr_regs_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ u64 *reg, bool is_write)
+{
+ struct vgic_reg_attr reg_attr;
+ gpa_t addr;
+ struct kvm_vcpu *vcpu;
+ int ret;
+ u32 tmp32;
+
+ ret = vgic_v3_parse_attr(dev, attr, ®_attr);
+ if (ret)
+ return ret;
+
+ vcpu = reg_attr.vcpu;
+ addr = reg_attr.addr;
+
+ mutex_lock(&dev->kvm->lock);
+
+ if (unlikely(!vgic_initialized(dev->kvm))) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (!lock_all_vcpus(dev->kvm)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ switch (attr->group) {
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ if (is_write)
+ tmp32 = *reg;
+
+ ret = vgic_v3_dist_uaccess(vcpu, is_write, addr, &tmp32);
+ if (!is_write)
+ *reg = tmp32;
+ break;
+ case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
+ if (is_write)
+ tmp32 = *reg;
+
+ ret = vgic_v3_redist_uaccess(vcpu, is_write, addr, &tmp32);
+ if (!is_write)
+ *reg = tmp32;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ unlock_all_vcpus(dev->kvm);
+out:
+ mutex_unlock(&dev->kvm->lock);
+ return ret;
+}
+
static int vgic_v3_set_attr(struct kvm_device *dev,
struct kvm_device_attr *attr)
{
- return vgic_set_common_attr(dev, attr);
+ int ret;
+
+ ret = vgic_set_common_attr(dev, attr);
+ if (ret != -ENXIO)
+ return ret;
+
+ switch (attr->group) {
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ u32 tmp32;
+ u64 reg;
+
+ if (get_user(tmp32, uaddr))
+ return -EFAULT;
+
+ reg = tmp32;
+ return vgic_v3_attr_regs_access(dev, attr, ®, true);
+ }
+ }
+ return -ENXIO;
}
static int vgic_v3_get_attr(struct kvm_device *dev,
struct kvm_device_attr *attr)
{
- return vgic_get_common_attr(dev, attr);
+ int ret;
+
+ ret = vgic_get_common_attr(dev, attr);
+ if (ret != -ENXIO)
+ return ret;
+
+ switch (attr->group) {
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ u64 reg;
+ u32 tmp32;
+
+ ret = vgic_v3_attr_regs_access(dev, attr, ®, false);
+ if (ret)
+ return ret;
+ tmp32 = reg;
+ return put_user(tmp32, uaddr);
+ }
+ }
+
+ return -ENXIO;
}
static int vgic_v3_has_attr(struct kvm_device *dev,
@@ -453,6 +579,9 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
return 0;
}
break;
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
+ return vgic_v3_has_attr_regs(dev, attr);
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
return 0;
case KVM_DEV_ARM_VGIC_GRP_CTRL:
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 0b32f40..2cb04b7 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -368,10 +368,9 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
{
- int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
const struct vgic_register_region *regions;
gpa_t addr;
- int nr_regions, i, len;
+ int nr_regions;
addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
@@ -392,18 +391,7 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
if (addr & 3)
return -ENXIO;
- for (i = 0; i < nr_regions; i++) {
- if (regions[i].bits_per_irq)
- len = (regions[i].bits_per_irq * nr_irqs) / 8;
- else
- len = regions[i].len;
-
- if (regions[i].reg_offset <= addr &&
- regions[i].reg_offset + len > addr)
- return 0;
- }
-
- return -ENXIO;
+ return vgic_validate_mmio_region_addr(dev, regions, nr_regions, addr);
}
int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index ce2708d..b35fb83 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -18,6 +18,8 @@
#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"
@@ -437,6 +439,9 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16,
VGIC_ACCESS_32bit),
+ REGISTER_DESC_WITH_LENGTH(GICD_STATUSR,
+ vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
+ VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
vgic_mmio_read_rao, vgic_mmio_write_wi, NULL, NULL, 1,
VGIC_ACCESS_32bit),
@@ -484,12 +489,18 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
vgic_mmio_read_v3r_ctlr, vgic_mmio_write_v3r_ctlr, 4,
VGIC_ACCESS_32bit),
+ REGISTER_DESC_WITH_LENGTH(GICR_STATUSR,
+ vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+ VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4,
VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8,
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+ REGISTER_DESC_WITH_LENGTH(GICR_WAKER,
+ vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+ VGIC_ACCESS_32bit),
REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
vgic_mmio_read_propbase, vgic_mmio_write_propbase, 8,
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
@@ -610,6 +621,34 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
return ret;
}
+int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+ const struct vgic_register_region *regions;
+ gpa_t addr;
+ int nr_regions;
+
+ addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+ switch (attr->group) {
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ regions = vgic_v3_dist_registers;
+ nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
+ break;
+ case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:{
+ regions = vgic_v3_rdbase_registers;
+ nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
+ break;
+ }
+ default:
+ return -ENXIO;
+ }
+
+ /* We only support aligned 32-bit accesses. */
+ if (addr & 3)
+ return -ENXIO;
+
+ return vgic_validate_mmio_region_addr(dev, regions, nr_regions, addr);
+}
/*
* Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
* generation register ICC_SGI1R_EL1) with a given VCPU.
@@ -716,3 +755,36 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
vgic_put_irq(vcpu->kvm, irq);
}
}
+
+int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+ int offset, u32 *val)
+{
+ struct vgic_io_device dev = {
+ .regions = vgic_v3_dist_registers,
+ .nr_regions = ARRAY_SIZE(vgic_v3_dist_registers),
+ };
+
+ return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
+int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+ int offset, u32 *val)
+{
+ struct vgic_io_device rd_dev = {
+ .regions = vgic_v3_rdbase_registers,
+ .nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers),
+ };
+
+ struct vgic_io_device sgi_dev = {
+ .regions = vgic_v3_sgibase_registers,
+ .nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers),
+ };
+
+ /* SGI_base is the next 64K frame after RD_base */
+ if (offset >= SZ_64K)
+ return vgic_uaccess(vcpu, &sgi_dev, is_write,
+ offset - SZ_64K, val);
+ else
+ return vgic_uaccess(vcpu, &rd_dev, is_write,
+ offset, val);
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 31f85df..9939d1d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -394,6 +394,28 @@ static int match_region(const void *key, const void *elt)
sizeof(region[0]), match_region);
}
+/* Check if address falls within the region */
+int vgic_validate_mmio_region_addr(struct kvm_device *dev,
+ const struct vgic_register_region *regions,
+ int nr_regions, gpa_t addr)
+{
+ int i, len;
+ int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+
+ for (i = 0; i < nr_regions; i++) {
+ if (regions[i].bits_per_irq)
+ len = (regions[i].bits_per_irq * nr_irqs) / 8;
+ else
+ len = regions[i].len;
+
+ if (regions[i].reg_offset <= addr &&
+ regions[i].reg_offset + len > addr)
+ return 0;
+ }
+
+ return -ENXIO;
+}
+
/*
* 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-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 97e6df7..acbf99e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -177,6 +177,10 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
bool is_write, int offset, u32 *val);
+int vgic_validate_mmio_region_addr(struct kvm_device *dev,
+ const struct vgic_register_region *regions,
+ int nr_regions, gpa_t addr);
+
unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 9d9e014..d901b0c 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -30,6 +30,34 @@
#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
+#define VGIC_AFFINITY_0_SHIFT 0
+#define VGIC_AFFINITY_0_MASK (0xffUL << VGIC_AFFINITY_0_SHIFT)
+#define VGIC_AFFINITY_1_SHIFT 8
+#define VGIC_AFFINITY_1_MASK (0xffUL << VGIC_AFFINITY_1_SHIFT)
+#define VGIC_AFFINITY_2_SHIFT 16
+#define VGIC_AFFINITY_2_MASK (0xffUL << VGIC_AFFINITY_2_SHIFT)
+#define VGIC_AFFINITY_3_SHIFT 24
+#define VGIC_AFFINITY_3_MASK (0xffUL << VGIC_AFFINITY_3_SHIFT)
+
+#define VGIC_AFFINITY_LEVEL(reg, level) \
+ ((((reg) & VGIC_AFFINITY_## level ##_MASK) \
+ >> VGIC_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
+
+/*
+ * The userspace encode the affinity differently from the MPIDR,
+ * Below macro converts vgic userspace format to MPIDR reg format.
+ */
+#define VGIC_TO_MPIDR(val) (VGIC_AFFINITY_LEVEL(val, 0) | \
+ VGIC_AFFINITY_LEVEL(val, 1) | \
+ VGIC_AFFINITY_LEVEL(val, 2) | \
+ VGIC_AFFINITY_LEVEL(val, 3))
+
+#define KVM_DEV_ARM_VGIC_SYSREG_MASK (KVM_REG_ARM64_SYSREG_OP0_MASK | \
+ KVM_REG_ARM64_SYSREG_OP1_MASK | \
+ KVM_REG_ARM64_SYSREG_CRN_MASK | \
+ KVM_REG_ARM64_SYSREG_CRM_MASK | \
+ KVM_REG_ARM64_SYSREG_OP2_MASK)
+
struct vgic_vmcr {
u32 ctlr;
u32 abpr;
@@ -90,6 +118,11 @@ static inline void vgic_get_irq_kref(struct vgic_irq *irq)
int kvm_vgic_register_its_device(void);
void vgic_enable_lpis(struct kvm_vcpu *vcpu);
int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
+int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
+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);
#else
static inline int vgic_register_its_iodevs(struct kvm *kvm)
{
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox