* [PATCH v3 09/11] ARM: KVM: introduce per-vcpu HYP Configuration Register
From: Catalin Marinas @ 2014-02-06 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391630151-7875-10-git-send-email-marc.zyngier@arm.com>
On Wed, Feb 05, 2014 at 07:55:49PM +0000, Marc Zyngier wrote:
> So far, KVM/ARM used a fixed HCR configuration per guest, except for
> the VI/VF/VA bits to control the interrupt in absence of VGIC.
>
> With the upcoming need to dynamically reconfigure trapping, it becomes
> necessary to allow the HCR to be changed on a per-vcpu basis.
>
> The fix here is to mimic what KVM/arm64 already does: a per vcpu HCR
> field, initialized at setup time.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply
* [PATCH v3 10/11] ARM: KVM: add world-switch for AMAIR{0,1}
From: Catalin Marinas @ 2014-02-06 11:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391630151-7875-11-git-send-email-marc.zyngier@arm.com>
On Wed, Feb 05, 2014 at 07:55:50PM +0000, Marc Zyngier wrote:
> HCR.TVM traps (among other things) accesses to AMAIR0 and AMAIR1.
> In order to minimise the amount of surprise a guest could generate by
> trying to access these registers with caches off, add them to the
> list of registers we switch/handle.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply
* [PATCH v3 11/11] ARM: KVM: trap VM system registers until MMU and caches are ON
From: Catalin Marinas @ 2014-02-06 11:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391630151-7875-12-git-send-email-marc.zyngier@arm.com>
On Wed, Feb 05, 2014 at 07:55:51PM +0000, Marc Zyngier wrote:
> In order to be able to detect the point where the guest enables
> its MMU and caches, trap all the VM related system registers.
>
> Once we see the guest enabling both the MMU and the caches, we
> can go back to a saner mode of operation, which is to leave these
> registers in complete control of the guest.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply
* [PATCH v2] ARM: dts: imx6qdl-sabreauto: Add PFUZE100 support
From: Fabio Estevam @ 2014-02-06 11:05 UTC (permalink / raw)
To: linux-arm-kernel
From: Fabio Estevam <fabio.estevam@freescale.com>
mx6 sabreauto boards have Freescale PFUZE100 regulator, so add support for it.
ARM: dts: imx6qdl-sabreauto: Add PFUZE100 support
mx6 sabreauto boards have Freescale PFUZE100 regulator, so add support for it.
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Changes since v1:
- Keep it sorted
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 113 +++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 10a00e4..466a544 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -63,6 +63,112 @@
status = "okay";
};
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ pmic: pfuze100 at 08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
@@ -133,6 +239,13 @@
>;
};
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
pinctrl_pwm3: pwm1grp {
fsl,pins = <
MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
--
1.8.1.2
^ permalink raw reply related
* [PATCH 1/3] wdt: sunxi: Introduce a new compatible for the A10 and A31
From: Hans de Goede @ 2014-02-06 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391349325-11132-1-git-send-email-maxime.ripard@free-electrons.com>
Hi,
On 02/02/2014 02:55 PM, Maxime Ripard wrote:
> For historical reasons, the Allwinner A10 compatibles are not following the
> patterns used for this other Allwinner SoCs.
>
> Introduce a new compatible following the usual pattern, and deprecate the olders.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt | 7 ++++---
> drivers/watchdog/sunxi_wdt.c | 1 +
> 2 files changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
> index e39cb26..6e8c937 100644
> --- a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
> +++ b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
> @@ -2,13 +2,14 @@ Allwinner SoCs Watchdog timer
>
> Required properties:
>
> -- compatible : should be "allwinner,<soc-family>-wdt", the currently supported
> - SoC families being sun4i and sun6i
> +- compatible : should be either "allwinner,sun4i-a10-wdt" or
> + "allwinner,sun6i-a31-wdt" (deprecated:
> + "allwinner,sun4i-wdt", "allwinner,sun6i-wdt")
> - reg : Specifies base physical address and size of the registers.
>
> Example:
>
> wdt: watchdog at 01c20c90 {
> - compatible = "allwinner,sun4i-wdt";
> + compatible = "allwinner,sun4i-a10-wdt";
> reg = <0x01c20c90 0x10>;
> };
You talk about deprecating the old compat strings in the commit message, but
here you outright replace them, which will break things with old dtb files ?
Other 2 patches in the series look good and are:
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
> diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c
> index 76332d8..7c8923d 100644
> --- a/drivers/watchdog/sunxi_wdt.c
> +++ b/drivers/watchdog/sunxi_wdt.c
> @@ -206,6 +206,7 @@ static void sunxi_wdt_shutdown(struct platform_device *pdev)
>
> static const struct of_device_id sunxi_wdt_dt_ids[] = {
> { .compatible = "allwinner,sun4i-wdt" },
> + { .compatible = "allwinner,sun4i-a10-wdt" },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
>
Regards,
Hans
^ permalink raw reply
* [PATCH] ARM: enable IRQs in user undefined instruction vector
From: Catalin Marinas @ 2014-02-06 11:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391545146-8320-1-git-send-email-kevin@bracey.fi>
On Tue, Feb 04, 2014 at 10:19:06PM +0200, Kevin Bracey wrote:
> If an abort occurs while loading an instruction from user space in
> __und_usr, the resulting do_page_fault() can output "sleeping function
> called from invalid context" warnings, due to IRQs being disabled in
> __und_usr, and hence in do_page_fault().
>
> Avoid the problem by enabling IRQs in __und_usr before attempting to
> load the instruction, and modify code and comments in the undefined
> instruction handlers to note that IRQs are enabled on entry iff the
> instruction was executed in user mode.
>
> See http://comments.gmane.org/gmane.linux.ports.arm.omap/59256 for
> an earlier report of the observed might_sleep() warning.
There was a follow-up on this:
http://thread.gmane.org/gmane.linux.ports.arm.kernel/263765
> arch/arm/kernel/entry-armv.S | 11 ++++++++---
> arch/arm/mach-ep93xx/crunch-bits.S | 7 ++++++-
> arch/arm/vfp/entry.S | 2 +-
> 3 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index b3fb8c9..bed1567 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -399,6 +399,7 @@ ENDPROC(__irq_usr)
> .align 5
> __und_usr:
> usr_entry
> + enable_irq
The problem is that you can be preempted here and parts of the kernel
may not cope with this.
The reason I haven't pushed my patches to mainline is that I was worried
about such preemption cases. We enter iwmmxt_task_enable for example
with interrupts and preemption enabled, we disable preemption there but
is it too late? I don't have a way to test these and even for VFP I'm
not sure testing would guarantee it in all scenarios.
So it needs more thinking. Please have a look at my patches, if we get
to the conclusion there is no issue, I'll push them upstream.
--
Catalin
^ permalink raw reply
* [PATCH 08/51] arm, hw-breakpoint: Fix CPU hotplug callback registration
From: Srivatsa S. Bhat @ 2014-02-06 11:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140206105718.GG26035@mudshark.cambridge.arm.com>
Hi Will,
On 02/06/2014 04:27 PM, Will Deacon wrote:
> Hi Srivatsa,
>
> On Wed, Feb 05, 2014 at 10:06:04PM +0000, Srivatsa S. Bhat wrote:
>> Subsystems that want to register CPU hotplug callbacks, as well as perform
>> initialization for the CPUs that are already online, often do it as shown
>> below:
>>
>> get_online_cpus();
>>
>> for_each_online_cpu(cpu)
>> init_cpu(cpu);
>>
>> register_cpu_notifier(&foobar_cpu_notifier);
>>
>> put_online_cpus();
>>
>> This is wrong, since it is prone to ABBA deadlocks involving the
>> cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
>> with CPU hotplug operations).
>
> Hmm, the code in question (for this patch) runs from an arch_initcall. How
> can you generate CPU hotplug operations at that stage?
>
You are right - in today's design of the init sequence, CPU hotplug
operations can't be triggered at that time during boot.
However, there have been proposals to boot CPUs in parallel along with the
rest of the kernel initialization [1] (and that would need full synchronization
with CPU hotplug even at the initcall stage). Of course this needs a lot of
auditing and modifications to the CPU hotplug notifiers of various subsystems
to make them robust enough to handle the parallel boot; so its not going to
happen very soon. But I felt that it would be a good idea to ensure that we
get the locking/synchronization right, even if the registrations happen very
early during boot today.. you know, just to be on the safer side and also to
make the job easier for whoever that is, who tries to implement parallel
CPU booting again in the future ;-)
[1]. http://thread.gmane.org/gmane.linux.kernel/1246209
>> Instead, the correct and race-free way of performing the callback
>> registration is:
>>
>> cpu_maps_update_begin();
>>
>> for_each_online_cpu(cpu)
>> init_cpu(cpu);
>>
>> /* Note the use of the double underscored version of the API */
>> __register_cpu_notifier(&foobar_cpu_notifier);
>>
>> cpu_maps_update_done();
>>
>>
>> Fix the hw-breakpoint code in arm by using this latter form of callback
>> registration.
>
> I guess you introduce __register_cpu_notifier somewhere earlier in the
> series,
Yes, patch 1 adds that API..
> so it's best if you take this all via your tree.
>
Hmm.. I'm not a maintainer myself, so I'm hoping that either Oleg or Rusty
or any of the other CPU hotplug maintainers (Thomas/Peter/Ingo) would be
willing to take these patches through their tree.
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* [PATCH] ARM: OMAP4: hwmod: Fix SOFTRESET logic for OMAP4
From: Roger Quadros @ 2014-02-06 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391612769-27890-1-git-send-email-illia.smyrnov@globallogic.com>
Hi Illia,
On 02/05/2014 05:06 PM, Illia Smyrnov wrote:
> Commit 313a76e (ARM: OMAP2+: hwmod: Fix SOFTRESET logic) introduced
> softreset bit cleaning right after set one. It is caused L3 error for
> OMAP4 ISS because ISS register write occurs when ISS reset process is in
> progress. Avoid this situation by cleaning softreset bit later, when reset
> process is successfully finished.
>
> Signed-off-by: Illia Smyrnov <illia.smyrnov@globallogic.com>
Thanks for the patch. Could you please send --cc this to stable as well. Thanks.
cheers,
-roger
> ---
> arch/arm/mach-omap2/omap_hwmod.c | 20 +++++++++++---------
> 1 file changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
> index 42d8188..1f33f5d 100644
> --- a/arch/arm/mach-omap2/omap_hwmod.c
> +++ b/arch/arm/mach-omap2/omap_hwmod.c
> @@ -1947,29 +1947,31 @@ static int _ocp_softreset(struct omap_hwmod *oh)
> goto dis_opt_clks;
>
> _write_sysconfig(v, oh);
> - ret = _clear_softreset(oh, &v);
> - if (ret)
> - goto dis_opt_clks;
> -
> - _write_sysconfig(v, oh);
>
> if (oh->class->sysc->srst_udelay)
> udelay(oh->class->sysc->srst_udelay);
>
> c = _wait_softreset_complete(oh);
> - if (c == MAX_MODULE_SOFTRESET_WAIT)
> + if (c == MAX_MODULE_SOFTRESET_WAIT) {
> pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
> oh->name, MAX_MODULE_SOFTRESET_WAIT);
> - else
> + ret = -ETIMEDOUT;
> + goto dis_opt_clks;
> + } else {
> pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
> + }
> +
> + ret = _clear_softreset(oh, &v);
> + if (ret)
> + goto dis_opt_clks;
> +
> + _write_sysconfig(v, oh);
>
> /*
> * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
> * _wait_target_ready() or _reset()
> */
>
> - ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
> -
> dis_opt_clks:
> if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
> _disable_optional_clocks(oh);
>
^ permalink raw reply
* [PATCH 2/3] PCI: ARM: add support for virtual PCI host controller
From: Arnd Bergmann @ 2014-02-06 11:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140206110016.GI26035@mudshark.cambridge.arm.com>
On Thursday 06 February 2014 11:00:16 Will Deacon wrote:
> On Thu, Feb 06, 2014 at 10:54:42AM +0000, Liviu Dudau wrote:
> > On Thu, Feb 06, 2014 at 08:54:03AM +0000, Anup Patel wrote:
> > > On Tue, Feb 4, 2014 at 10:23 PM, Will Deacon <will.deacon@arm.com> wrote:
> >
> > This is another reason why I prefer the reg property for specifying the configuration
> > space address range. I don't see a straight way of making the distinction you
> > need using the ranges property.
>
> Well if we need to distinguish cam vs ecam, then adding ioport to the mix
> should be (conceptually) easy and I don't think it would involve the "reg"
> property.
>
> However, I'm not planning to add ioport support myself.
Maybe it's better to have separate compatible strings for these cases,
can call it "pci-ecam-generic" or "pci-cam-generic" to have an easy
distinction. Or we just use the "reg-names" property so the device
can have a "cam" register or an "ecam" register or both.
I don't think we can make the driver generic enough for
x86 as Anup suggests though, since x86 has its own set of quirks to
deal with the various PCI config space access methods.
Arnd
^ permalink raw reply
* [PATCH 1/6] arm64: barriers: allow dsb macro to take option parameter
From: Will Deacon @ 2014-02-06 11:30 UTC (permalink / raw)
To: linux-arm-kernel
The dsb instruction takes an option specifying both the target access
types and shareability domain.
This patch allows such an option to be passed to the dsb macro,
resulting in potentially more efficient code. Currently the option is
ignored until all callers are updated (unlike ARM, the option is
mandated by the assembler).
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
Catalin -- I'd like to get this simple change in for 3.14, since it's a
blocker for actually implementing the barrier options (we
need to move all of the callers over before making the switch).
arch/arm64/include/asm/barrier.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index 78e20ba8806b..409ca370cfe2 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -25,7 +25,7 @@
#define wfi() asm volatile("wfi" : : : "memory")
#define isb() asm volatile("isb" : : : "memory")
-#define dsb() asm volatile("dsb sy" : : : "memory")
+#define dsb(opt) asm volatile("dsb sy" : : : "memory")
#define mb() dsb()
#define rmb() asm volatile("dsb ld" : : : "memory")
--
1.8.2.2
^ permalink raw reply related
* [PATCH 2/6] arm64: barriers: make use of barrier options with explicit barriers
From: Will Deacon @ 2014-02-06 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686253-13436-1-git-send-email-will.deacon@arm.com>
When calling our low-level barrier macros directly, we can often suffice
with more relaxed behaviour than the default "all accesses, full system"
option.
This patch updates the users of dsb() to specify the option whith they
actually require. The sev() macro is also updated so that a sevl can
be emitted if necessary.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/barrier.h | 4 ++--
arch/arm64/include/asm/cacheflush.h | 2 +-
arch/arm64/include/asm/pgtable.h | 4 ++--
arch/arm64/include/asm/tlbflush.h | 14 +++++++-------
arch/arm64/kernel/process.c | 2 +-
arch/arm64/kvm/sys_regs.c | 4 ++--
6 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index 409ca370cfe2..09f4cb4b665e 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -20,14 +20,14 @@
#ifndef __ASSEMBLY__
-#define sev() asm volatile("sev" : : : "memory")
+#define sev(l) asm volatile("sev" #l : : : "memory")
#define wfe() asm volatile("wfe" : : : "memory")
#define wfi() asm volatile("wfi" : : : "memory")
#define isb() asm volatile("isb" : : : "memory")
#define dsb(opt) asm volatile("dsb sy" : : : "memory")
-#define mb() dsb()
+#define mb() dsb(sy)
#define rmb() asm volatile("dsb ld" : : : "memory")
#define wmb() asm volatile("dsb st" : : : "memory")
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index fea9ee327206..b9495549cb08 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -142,7 +142,7 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end)
* set_pte_at() called from vmap_pte_range() does not
* have a DSB after cleaning the cache line.
*/
- dsb();
+ dsb(ishst);
}
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index b524dcd17243..54aa68f61008 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -310,7 +310,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
{
*pmdp = pmd;
- dsb();
+ dsb(ishst);
}
static inline void pmd_clear(pmd_t *pmdp)
@@ -340,7 +340,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
static inline void set_pud(pud_t *pudp, pud_t pud)
{
*pudp = pud;
- dsb();
+ dsb(ishst);
}
static inline void pud_clear(pud_t *pudp)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 8b482035cfc2..3083a08f9622 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -72,9 +72,9 @@ extern struct cpu_tlb_fns cpu_tlb;
*/
static inline void flush_tlb_all(void)
{
- dsb();
+ dsb(ishst);
asm("tlbi vmalle1is");
- dsb();
+ dsb(ish);
isb();
}
@@ -82,9 +82,9 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
{
unsigned long asid = (unsigned long)ASID(mm) << 48;
- dsb();
+ dsb(ishst);
asm("tlbi aside1is, %0" : : "r" (asid));
- dsb();
+ dsb(ish);
}
static inline void flush_tlb_page(struct vm_area_struct *vma,
@@ -93,9 +93,9 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long addr = uaddr >> 12 |
((unsigned long)ASID(vma->vm_mm) << 48);
- dsb();
+ dsb(ishst);
asm("tlbi vae1is, %0" : : "r" (addr));
- dsb();
+ dsb(ish);
}
/*
@@ -114,7 +114,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
* set_pte() does not have a DSB, so make sure that the page table
* write is visible.
*/
- dsb();
+ dsb(ishst);
}
#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 1c0a9be2ffa8..8e78cb238376 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -294,7 +294,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
* Complete any pending TLB or cache maintenance on this CPU in case
* the thread migrates to a different CPU.
*/
- dsb();
+ dsb(ish);
/* the actual thread switch */
last = cpu_switch_to(prev, next);
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 02e9d09e1d80..bbaaabe8e899 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -70,13 +70,13 @@ static u32 get_ccsidr(u32 csselr)
static void do_dc_cisw(u32 val)
{
asm volatile("dc cisw, %x0" : : "r" (val));
- dsb();
+ dsb(ishst);
}
static void do_dc_csw(u32 val)
{
asm volatile("dc csw, %x0" : : "r" (val));
- dsb();
+ dsb(ishst);
}
/* See note@ARM ARM B1.14.4 */
--
1.8.2.2
^ permalink raw reply related
* [PATCH 3/6] irqchip: gic: use writel instead of dsb + writel_relaxed
From: Will Deacon @ 2014-02-06 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686253-13436-1-git-send-email-will.deacon@arm.com>
When sending an SGI to another CPU, we require a DSB to ensure that
any pending stores to normal memory are made visible to the recipient
before the interrupt arrives.
Rather than use a dsb() (which will soon cause an assembly error on
arm64) followed by a writel_relaxed, we can use a writel instead, which
will emit a dsb st prior to the str.
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/irqchip/irq-gic.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 341c6016812d..03fe5ef3f2fe 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -662,11 +662,10 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/*
* Ensure that stores to Normal memory are visible to the
* other CPUs before issuing the IPI.
+ *
+ * This always happens on GIC0.
*/
- dsb();
-
- /* this always happens on GIC0 */
- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+ writel(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
}
--
1.8.2.2
^ permalink raw reply related
* [PATCH 4/6] iommu/arm-smmu: provide option to dsb macro when publishing tables
From: Will Deacon @ 2014-02-06 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686253-13436-1-git-send-email-will.deacon@arm.com>
On coherent systems, publishing new page tables to the SMMU walker is
achieved with a dsb instruction. In fact, this can be a dsb(ishst) which
also provides the mandatory barrier option for arm64.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/iommu/arm-smmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 8911850c9444..8f6fee54f3b1 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1417,7 +1417,7 @@ out_unlock:
/* Ensure new page tables are visible to the hardware walker */
if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
- dsb();
+ dsb(ishst);
return ret;
}
--
1.8.2.2
^ permalink raw reply related
* [PATCH 5/6] arm64: barriers: wire up new barrier options
From: Will Deacon @ 2014-02-06 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686253-13436-1-git-send-email-will.deacon@arm.com>
Now that all callers of the barrier macros are updated to pass the
mandatory options, update the macros so the option is actually used.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/barrier.h | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index 09f4cb4b665e..b5219b651850 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -25,11 +25,12 @@
#define wfi() asm volatile("wfi" : : : "memory")
#define isb() asm volatile("isb" : : : "memory")
-#define dsb(opt) asm volatile("dsb sy" : : : "memory")
+#define dmb(opt) asm volatile("dmb " #opt : : : "memory")
+#define dsb(opt) asm volatile("dsb " #opt : : : "memory")
#define mb() dsb(sy)
-#define rmb() asm volatile("dsb ld" : : : "memory")
-#define wmb() asm volatile("dsb st" : : : "memory")
+#define rmb() dsb(ld)
+#define wmb() dsb(st)
#ifndef CONFIG_SMP
#define smp_mb() barrier()
@@ -53,9 +54,9 @@ do { \
#else
-#define smp_mb() asm volatile("dmb ish" : : : "memory")
-#define smp_rmb() asm volatile("dmb ishld" : : : "memory")
-#define smp_wmb() asm volatile("dmb ishst" : : : "memory")
+#define smp_mb() dmb(ish)
+#define smp_rmb() dmb(ishld)
+#define smp_wmb() dmb(ishst)
#define smp_store_release(p, v) \
do { \
--
1.8.2.2
^ permalink raw reply related
* [PATCH 6/6] arm64: barriers: use barrier() instead of smp_mb() when !SMP
From: Will Deacon @ 2014-02-06 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686253-13436-1-git-send-email-will.deacon@arm.com>
The recently introduced acquire/release accessors refer to smp_mb()
in the !CONFIG_SMP case. This is confusing when reading the code, so use
barrier() directly when we know we're UP.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/barrier.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index b5219b651850..ef483c75ae34 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -40,7 +40,7 @@
#define smp_store_release(p, v) \
do { \
compiletime_assert_atomic_type(*p); \
- smp_mb(); \
+ barrier(); \
ACCESS_ONCE(*p) = (v); \
} while (0)
@@ -48,7 +48,7 @@ do { \
({ \
typeof(*p) ___p1 = ACCESS_ONCE(*p); \
compiletime_assert_atomic_type(*p); \
- smp_mb(); \
+ barrier(); \
___p1; \
})
--
1.8.2.2
^ permalink raw reply related
* [PATCH v4 00/10] In-kernel PSCI v0.2 emulation for KVM ARM/ARM64
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
Currently, KVM ARM/ARM64 only provides in-kernel emulation of Power State
and Coordination Interface (PSCI) v0.1.
This patchset aims at providing newer PSCI v0.2 for KVM ARM/ARM64 VCPUs
such that it does not break current KVM ARM/ARM64 ABI. Also, the patchset
provides emulation of only few PSCI v0.2 functions such as PSCI_VERSION,
CPU_ON, and CPU_OFF. Emulation of other PSCI v0.2 functions will be added
later.
The user space tools (i.e. QEMU or KVMTOOL) will have to explicitly enable
KVM_ARM_VCPU_PSCI_0_2 feature using KVM_ARM_VCPU_INIT ioctl for providing
PSCI v0.2 to VCPUs.
Changlog:
V4:
- Implement all mandatory functions required by PSCI v0.2
V3:
- Make KVM_ARM_VCPU_PSCI_0_2 feature experiementatl for now so that
it fails for user space till all mandatory PSCI v0.2 functions are
emulated by KVM ARM/ARM64
- Have separate patch for making KVM_ARM_VCPU_PSCI_0_2 feature available
to user space. This patch can be defferred for now
V2:
- Don't rename PSCI return values KVM_PSCI_RET_NI and KVM_PSCI_RET_INVAL
- Added kvm_psci_version() to get PSCI version available to VCPU
- Fixed grammer in Documentation/virtual/kvm/api.txt
V1:
- Initial RFC PATCH
Anup Patel (10):
KVM: Add capability to advertise PSCI v0.2 support
ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
KVM: Documentation: Add info regarding KVM_ARM_VCPU_PSCI_0_2 feature
ARM/ARM64: KVM: Make kvm_psci_call() return convention more flexible
KVM: Add KVM_EXIT_SYSTEM_EVENT to user space API header
ARM/ARM64: KVM: Emulate PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET
ARM/ARM64: KVM: Emulate PSCI v0.2 AFFINITY_INFO
ARM/ARM64: KVM: Emulate PSCI v0.2 MIGRATE_INFO_TYPE and related
functions
ARM/ARM64: KVM: Fix CPU_ON emulation for PSCI v0.2
ARM/ARM64: KVM: Emulate PSCI v0.2 CPU_SUSPEND
Documentation/virtual/kvm/api.txt | 17 +++
arch/arm/include/asm/kvm_host.h | 7 +-
arch/arm/include/asm/kvm_psci.h | 7 +-
arch/arm/include/uapi/asm/kvm.h | 35 ++++-
arch/arm/kvm/arm.c | 1 +
arch/arm/kvm/handle_exit.c | 10 +-
arch/arm/kvm/psci.c | 270 ++++++++++++++++++++++++++++++++++---
arch/arm/kvm/reset.c | 4 +
arch/arm64/include/asm/kvm_host.h | 7 +-
arch/arm64/include/asm/kvm_psci.h | 7 +-
arch/arm64/include/uapi/asm/kvm.h | 35 ++++-
arch/arm64/kvm/handle_exit.c | 10 +-
arch/arm64/kvm/reset.c | 4 +
include/uapi/linux/kvm.h | 9 ++
14 files changed, 395 insertions(+), 28 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH v4 01/10] KVM: Add capability to advertise PSCI v0.2 support
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
User space (i.e. QEMU or KVMTOOL) should be able to check whether KVM
ARM/ARM64 supports in-kernel PSCI v0.2 emulation. For this purpose, we
define KVM_CAP_ARM_PSCI_0_2 in KVM user space interface header.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
include/uapi/linux/kvm.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 932d7f2..fb3c3f3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -675,6 +675,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_SPAPR_MULTITCE 94
#define KVM_CAP_EXT_EMUL_CPUID 95
#define KVM_CAP_HYPERV_TIME 96
+#define KVM_CAP_ARM_PSCI_0_2 97
#ifdef KVM_CAP_IRQ_ROUTING
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 02/10] ARM/ARM64: KVM: Add base for PSCI v0.2 emulation
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to
VCPUs. This patch extends current in-kernel PSCI emulation to provide
PSCI v0.2 interface to VCPUs.
By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for
keeping the ABI backward-compatible.
To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or
KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU
init using KVM_ARM_VCPU_INIT ioctl.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
arch/arm/include/asm/kvm_host.h | 2 +-
arch/arm/include/asm/kvm_psci.h | 4 ++
arch/arm/include/uapi/asm/kvm.h | 35 ++++++++++++++-
arch/arm/kvm/arm.c | 1 +
arch/arm/kvm/psci.c | 85 +++++++++++++++++++++++++++++++------
arch/arm64/include/asm/kvm_host.h | 2 +-
arch/arm64/include/asm/kvm_psci.h | 4 ++
arch/arm64/include/uapi/asm/kvm.h | 35 ++++++++++++++-
8 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 09af149..193ceaf 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -36,7 +36,7 @@
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
#define KVM_HAVE_ONE_REG
-#define KVM_VCPU_MAX_FEATURES 1
+#define KVM_VCPU_MAX_FEATURES 2
#include <kvm/arm_vgic.h>
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
index 9a83d98..4c0e3e1 100644
--- a/arch/arm/include/asm/kvm_psci.h
+++ b/arch/arm/include/asm/kvm_psci.h
@@ -18,6 +18,10 @@
#ifndef __ARM_KVM_PSCI_H__
#define __ARM_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1
+#define KVM_ARM_PSCI_0_2 2
+
+int kvm_psci_version(struct kvm_vcpu *vcpu);
bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index ef0c878..9c922d9 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -83,6 +83,7 @@ struct kvm_regs {
#define KVM_VGIC_V2_CPU_SIZE 0x2000
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
+#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init {
__u32 target;
@@ -192,7 +193,7 @@ struct kvm_arch_memory_slot {
/* Highest supported SPI, from VGIC_NR_IRQS */
#define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */
+/* PSCI v0.1 interface */
#define KVM_PSCI_FN_BASE 0x95c1ba5e
#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -201,9 +202,41 @@ struct kvm_arch_memory_slot {
#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */
+#define KVM_PSCI_0_2_FN_BASE 0x84000000
+#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n))
+#define KVM_PSCI_0_2_FN64_BASE 0xC4000000
+#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0)
+#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1)
+#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2)
+#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3)
+#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4)
+#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
+ KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
+ KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8)
+#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1)
+#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3)
+#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4)
+#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5)
+#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
+ KVM_PSCI_0_2_FN64(7)
+
+/* PSCI return values */
#define KVM_PSCI_RET_SUCCESS 0
#define KVM_PSCI_RET_NI ((unsigned long)-1)
#define KVM_PSCI_RET_INVAL ((unsigned long)-2)
#define KVM_PSCI_RET_DENIED ((unsigned long)-3)
+#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4)
+#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5)
+#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6)
+#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7)
+#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif /* __ARM_KVM_H__ */
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 1d8248e..c8a71df 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -197,6 +197,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
case KVM_CAP_ONE_REG:
case KVM_CAP_ARM_PSCI:
+ case KVM_CAP_ARM_PSCI_0_2:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 448f60e..e4ec4af 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -85,17 +85,57 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
return KVM_PSCI_RET_SUCCESS;
}
-/**
- * kvm_psci_call - handle PSCI call if r0 value is in range
- * @vcpu: Pointer to the VCPU struct
- *
- * Handle PSCI calls from guests through traps from HVC instructions.
- * The calling convention is similar to SMC calls to the secure world where
- * the function number is placed in r0 and this function returns true if the
- * function number specified in r0 is withing the PSCI range, and false
- * otherwise.
- */
-bool kvm_psci_call(struct kvm_vcpu *vcpu)
+int kvm_psci_version(struct kvm_vcpu *vcpu)
+{
+ if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
+ return KVM_ARM_PSCI_0_2;
+
+ return KVM_ARM_PSCI_0_1;
+}
+
+static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
+{
+ unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
+ unsigned long val;
+
+ switch (psci_fn) {
+ case KVM_PSCI_0_2_FN_PSCI_VERSION:
+ /*
+ * Bits[31:16] = Major Version = 0
+ * Bits[15:0] = Minor Version = 2
+ */
+ val = 2;
+ break;
+ case KVM_PSCI_0_2_FN_CPU_OFF:
+ kvm_psci_vcpu_off(vcpu);
+ val = KVM_PSCI_RET_SUCCESS;
+ break;
+ case KVM_PSCI_0_2_FN_CPU_ON:
+ case KVM_PSCI_0_2_FN64_CPU_ON:
+ val = kvm_psci_vcpu_on(vcpu);
+ break;
+ case KVM_PSCI_0_2_FN_CPU_SUSPEND:
+ case KVM_PSCI_0_2_FN_AFFINITY_INFO:
+ case KVM_PSCI_0_2_FN_MIGRATE:
+ case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+ case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
+ case KVM_PSCI_0_2_FN_SYSTEM_OFF:
+ case KVM_PSCI_0_2_FN_SYSTEM_RESET:
+ case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
+ case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
+ case KVM_PSCI_0_2_FN64_MIGRATE:
+ case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
+ val = KVM_PSCI_RET_NI;
+ break;
+ default:
+ return false;
+ }
+
+ *vcpu_reg(vcpu, 0) = val;
+ return true;
+}
+
+static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
{
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
@@ -112,7 +152,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
case KVM_PSCI_FN_MIGRATE:
val = KVM_PSCI_RET_NI;
break;
-
default:
return false;
}
@@ -120,3 +159,25 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
*vcpu_reg(vcpu, 0) = val;
return true;
}
+
+/**
+ * kvm_psci_call - handle PSCI call if r0 value is in range
+ * @vcpu: Pointer to the VCPU struct
+ *
+ * Handle PSCI calls from guests through traps from HVC instructions.
+ * The calling convention is similar to SMC calls to the secure world where
+ * the function number is placed in r0 and this function returns true if the
+ * function number specified in r0 is withing the PSCI range, and false
+ * otherwise.
+ */
+bool kvm_psci_call(struct kvm_vcpu *vcpu)
+{
+ switch (kvm_psci_version(vcpu)) {
+ case KVM_ARM_PSCI_0_2:
+ return kvm_psci_0_2_call(vcpu);
+ case KVM_ARM_PSCI_0_1:
+ return kvm_psci_0_1_call(vcpu);
+ default:
+ return false;
+ };
+}
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 0a1d697..92242ce 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -39,7 +39,7 @@
#include <kvm/arm_vgic.h>
#include <kvm/arm_arch_timer.h>
-#define KVM_VCPU_MAX_FEATURES 2
+#define KVM_VCPU_MAX_FEATURES 3
struct kvm_vcpu;
int kvm_target_cpu(void);
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
index e301a48..e25c658 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -18,6 +18,10 @@
#ifndef __ARM64_KVM_PSCI_H__
#define __ARM64_KVM_PSCI_H__
+#define KVM_ARM_PSCI_0_1 1
+#define KVM_ARM_PSCI_0_2 2
+
+int kvm_psci_version(struct kvm_vcpu *vcpu);
bool kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index eaf54a3..cadc318 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -77,6 +77,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
#define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
+#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
struct kvm_vcpu_init {
__u32 target;
@@ -177,7 +178,7 @@ struct kvm_arch_memory_slot {
/* Highest supported SPI, from VGIC_NR_IRQS */
#define KVM_ARM_IRQ_GIC_MAX 127
-/* PSCI interface */
+/* PSCI v0.1 interface */
#define KVM_PSCI_FN_BASE 0x95c1ba5e
#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
@@ -186,10 +187,42 @@ struct kvm_arch_memory_slot {
#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
+/* PSCI v0.2 interface */
+#define KVM_PSCI_0_2_FN_BASE 0x84000000
+#define KVM_PSCI_0_2_FN(n) (KVM_PSCI_0_2_FN_BASE + (n))
+#define KVM_PSCI_0_2_FN64_BASE 0xC4000000
+#define KVM_PSCI_0_2_FN64(n) (KVM_PSCI_0_2_FN64_BASE + (n))
+
+#define KVM_PSCI_0_2_FN_PSCI_VERSION KVM_PSCI_0_2_FN(0)
+#define KVM_PSCI_0_2_FN_CPU_SUSPEND KVM_PSCI_0_2_FN(1)
+#define KVM_PSCI_0_2_FN_CPU_OFF KVM_PSCI_0_2_FN(2)
+#define KVM_PSCI_0_2_FN_CPU_ON KVM_PSCI_0_2_FN(3)
+#define KVM_PSCI_0_2_FN_AFFINITY_INFO KVM_PSCI_0_2_FN(4)
+#define KVM_PSCI_0_2_FN_MIGRATE KVM_PSCI_0_2_FN(5)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
+ KVM_PSCI_0_2_FN(6)
+#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
+ KVM_PSCI_0_2_FN(7)
+#define KVM_PSCI_0_2_FN_SYSTEM_OFF KVM_PSCI_0_2_FN(8)
+#define KVM_PSCI_0_2_FN_SYSTEM_RESET KVM_PSCI_0_2_FN(9)
+
+#define KVM_PSCI_0_2_FN64_CPU_SUSPEND KVM_PSCI_0_2_FN64(1)
+#define KVM_PSCI_0_2_FN64_CPU_ON KVM_PSCI_0_2_FN64(3)
+#define KVM_PSCI_0_2_FN64_AFFINITY_INFO KVM_PSCI_0_2_FN64(4)
+#define KVM_PSCI_0_2_FN64_MIGRATE KVM_PSCI_0_2_FN64(5)
+#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
+ KVM_PSCI_0_2_FN64(7)
+
+/* PSCI return values */
#define KVM_PSCI_RET_SUCCESS 0
#define KVM_PSCI_RET_NI ((unsigned long)-1)
#define KVM_PSCI_RET_INVAL ((unsigned long)-2)
#define KVM_PSCI_RET_DENIED ((unsigned long)-3)
+#define KVM_PSCI_RET_ALREADY_ON ((unsigned long)-4)
+#define KVM_PSCI_RET_ON_PENDING ((unsigned long)-5)
+#define KVM_PSCI_RET_INTERNAL_FAILURE ((unsigned long)-6)
+#define KVM_PSCI_RET_NOT_PRESENT ((unsigned long)-7)
+#define KVM_PSCI_RET_DISABLED ((unsigned long)-8)
#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 03/10] KVM: Documentation: Add info regarding KVM_ARM_VCPU_PSCI_0_2 feature
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
We have in-kernel emulation of PSCI v0.2 in KVM ARM/ARM64. To provide
PSCI v0.2 interface to VCPUs, we have to enable KVM_ARM_VCPU_PSCI_0_2
feature when doing KVM_ARM_VCPU_INIT ioctl.
The patch updates documentation of KVM_ARM_VCPU_INIT ioctl to provide
info regarding KVM_ARM_VCPU_PSCI_0_2 feature.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
Documentation/virtual/kvm/api.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 6cd63a9..73cb211 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2347,6 +2347,8 @@ Possible features:
Depends on KVM_CAP_ARM_PSCI.
- KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
+ - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU.
+ Depends on KVM_CAP_ARM_PSCI_0_2.
4.83 KVM_ARM_PREFERRED_TARGET
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 04/10] ARM/ARM64: KVM: Make kvm_psci_call() return convention more flexible
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
Currently, the kvm_psci_call() returns 'true' or 'false' based on whether
the PSCI function call was handled successfully or not. This does not help
us emulate system-level PSCI functions where the actual emulation work will
be done by user space (QEMU or KVMTOOL). Examples of such system-level PSCI
functions are: PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET.
This patch updates kvm_psci_call() to return three types of values:
1) > 0 (success)
2) = 0 (success but exit to user space)
3) < 0 (errors)
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
arch/arm/include/asm/kvm_psci.h | 2 +-
arch/arm/kvm/handle_exit.c | 10 +++++++---
arch/arm/kvm/psci.c | 28 ++++++++++++++++------------
arch/arm64/include/asm/kvm_psci.h | 2 +-
arch/arm64/kvm/handle_exit.c | 10 +++++++---
5 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
index 4c0e3e1..6bda945 100644
--- a/arch/arm/include/asm/kvm_psci.h
+++ b/arch/arm/include/asm/kvm_psci.h
@@ -22,6 +22,6 @@
#define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu);
-bool kvm_psci_call(struct kvm_vcpu *vcpu);
+int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM_KVM_PSCI_H__ */
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 0de91fc..1270095 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,14 +38,18 @@ static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
+ int ret;
+
trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
kvm_vcpu_hvc_get_imm(vcpu));
- if (kvm_psci_call(vcpu))
+ ret = kvm_psci_call(vcpu);
+ if (ret == -EINVAL) {
+ kvm_inject_undefined(vcpu);
return 1;
+ }
- kvm_inject_undefined(vcpu);
- return 1;
+ return ret;
}
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index e4ec4af..252acd0 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -93,7 +93,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
return KVM_ARM_PSCI_0_1;
}
-static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
+static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
{
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
@@ -128,14 +128,14 @@ static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
val = KVM_PSCI_RET_NI;
break;
default:
- return false;
+ return -EINVAL;
}
*vcpu_reg(vcpu, 0) = val;
- return true;
+ return 1;
}
-static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
+static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
{
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
@@ -153,11 +153,11 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
val = KVM_PSCI_RET_NI;
break;
default:
- return false;
+ return -EINVAL;
}
*vcpu_reg(vcpu, 0) = val;
- return true;
+ return 1;
}
/**
@@ -165,12 +165,16 @@ static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
* @vcpu: Pointer to the VCPU struct
*
* Handle PSCI calls from guests through traps from HVC instructions.
- * The calling convention is similar to SMC calls to the secure world where
- * the function number is placed in r0 and this function returns true if the
- * function number specified in r0 is withing the PSCI range, and false
- * otherwise.
+ * The calling convention is similar to SMC calls to the secure world
+ * where the function number is placed in r0.
+ *
+ * This function returns: > 0 (success), 0 (success but exit to user
+ * space), and < 0 (errors)
+ *
+ * Errors:
+ * -EINVAL: Unrecognized PSCI function
*/
-bool kvm_psci_call(struct kvm_vcpu *vcpu)
+int kvm_psci_call(struct kvm_vcpu *vcpu)
{
switch (kvm_psci_version(vcpu)) {
case KVM_ARM_PSCI_0_2:
@@ -178,6 +182,6 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
case KVM_ARM_PSCI_0_1:
return kvm_psci_0_1_call(vcpu);
default:
- return false;
+ return -EINVAL;
};
}
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
index e25c658..bc39e55 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -22,6 +22,6 @@
#define KVM_ARM_PSCI_0_2 2
int kvm_psci_version(struct kvm_vcpu *vcpu);
-bool kvm_psci_call(struct kvm_vcpu *vcpu);
+int kvm_psci_call(struct kvm_vcpu *vcpu);
#endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 7bc41ea..743a74d 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -30,11 +30,15 @@ typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
- if (kvm_psci_call(vcpu))
+ int ret;
+
+ ret = kvm_psci_call(vcpu);
+ if (ret == -EINVAL) {
+ kvm_inject_undefined(vcpu);
return 1;
+ }
- kvm_inject_undefined(vcpu);
- return 1;
+ return ret;
}
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 05/10] KVM: Add KVM_EXIT_SYSTEM_EVENT to user space API header
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
Currently, we don't have an exit reason to notify user space about
a system-level event (for e.g. system reset or shutdown) triggered
by the VCPU. This patch adds exit reason KVM_EXIT_SYSTEM_EVENT for
this purpose. We can also inform user space about the 'type' and
architecture specific 'flags' of a system-level event using the
kvm_run structure.
This newly added KVM_EXIT_SYSTEM_EVENT will be used by KVM ARM/ARM64
in-kernel PSCI v0.2 support to reset/shutdown VMs.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
Documentation/virtual/kvm/api.txt | 15 +++++++++++++++
include/uapi/linux/kvm.h | 8 ++++++++
2 files changed, 23 insertions(+)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 73cb211..0f70625 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2707,6 +2707,21 @@ It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an
external interrupt has just been delivered into the guest. User space
should put the acknowledged interrupt vector into the 'epr' field.
+ /* KVM_EXIT_SYSTEM_EVENT */
+ struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN 1
+#define KVM_SYSTEM_EVENT_RESET 2
+ __u32 type;
+ __u64 flags;
+ } system_event;
+
+If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered
+a system-level event using some architecture specific mechanism (hypercall
+or some special instruction). In case of ARM/ARM64, this is triggered using
+HVC instruction based PSCI call from the vcpu. The 'type' field describes
+the system-level event type. The 'flags' field describes architecture
+specific flags for the system-level event.
+
/* Fix the size of the union. */
char padding[256];
};
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index fb3c3f3..0723853 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -171,6 +171,7 @@ struct kvm_pit_config {
#define KVM_EXIT_WATCHDOG 21
#define KVM_EXIT_S390_TSCH 22
#define KVM_EXIT_EPR 23
+#define KVM_EXIT_SYSTEM_EVENT 24
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -301,6 +302,13 @@ struct kvm_run {
struct {
__u32 epr;
} epr;
+ /* KVM_EXIT_SYSTEM_EVENT */
+ struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN 1
+#define KVM_SYSTEM_EVENT_RESET 2
+ __u32 type;
+ __u64 flags;
+ } system_event;
/* Fix the size of the union. */
char padding[256];
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 06/10] ARM/ARM64: KVM: Emulate PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
The PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET functions are system-level
functions hence cannot be fully emulated by in-kernel PSCI emulation code.
To tackle this, we forward PSCI v0.2 SYSTEM_OFF and SYSTEM_RESET function
calls from vcpu to user space (i.e. QEMU or KVMTOOL) via kvm_run structure
using KVM_EXIT_SYSTEM_EVENT exit reasons.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
arch/arm/kvm/psci.c | 32 +++++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 252acd0..1f1720a 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -85,6 +85,23 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
return KVM_PSCI_RET_SUCCESS;
}
+static inline void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type)
+{
+ memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
+ vcpu->run->system_event.type = type;
+ vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+}
+
+static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
+{
+ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN);
+}
+
+static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
+{
+ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET);
+}
+
int kvm_psci_version(struct kvm_vcpu *vcpu)
{
if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
@@ -95,6 +112,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
{
+ int ret = 1;
unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
@@ -114,13 +132,21 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
+ case KVM_PSCI_0_2_FN_SYSTEM_OFF:
+ kvm_psci_system_off(vcpu);
+ val = KVM_PSCI_RET_SUCCESS;
+ ret = 0;
+ break;
+ case KVM_PSCI_0_2_FN_SYSTEM_RESET:
+ kvm_psci_system_reset(vcpu);
+ val = KVM_PSCI_RET_SUCCESS;
+ ret = 0;
+ break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
- case KVM_PSCI_0_2_FN_SYSTEM_OFF:
- case KVM_PSCI_0_2_FN_SYSTEM_RESET:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
@@ -132,7 +158,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
}
*vcpu_reg(vcpu, 0) = val;
- return 1;
+ return ret;
}
static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 07/10] ARM/ARM64: KVM: Emulate PSCI v0.2 AFFINITY_INFO
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
This patch adds emulation of PSCI v0.2 AFFINITY_INFO function call
for KVM ARM/ARM64. This is a VCPU-level function call which will be
used to determine current state of given affinity level.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
arch/arm/kvm/psci.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 1f1720a..9890710 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -85,6 +85,55 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
return KVM_PSCI_RET_SUCCESS;
}
+static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
+{
+ int i;
+ unsigned long mpidr;
+ unsigned long target_affinity;
+ unsigned long target_affinity_mask;
+ unsigned long lowest_affinity_level;
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_vcpu *tmp;
+
+ target_affinity = *vcpu_reg(vcpu, 1);
+ lowest_affinity_level = *vcpu_reg(vcpu, 2);
+
+ /* Determine target affinity mask */
+ target_affinity_mask = MPIDR_HWID_BITMASK;
+ switch (lowest_affinity_level) {
+ case 0: /* All affinity levels are valid */
+ target_affinity_mask &= ~0x0UL;
+ break;
+ case 1: /* Aff0 ignored */
+ target_affinity_mask &= ~0xFFUL;
+ break;
+ case 2: /* Aff0 and Aff1 ignored */
+ target_affinity_mask &= ~0xFFFFUL;
+ break;
+ case 3: /* Aff0, Aff1, and Aff2 ignored */
+ target_affinity_mask &= ~0xFFFFFFUL;
+ break;
+ default:
+ return KVM_PSCI_RET_INVAL;
+ };
+
+ /* Ignore other bits of target affinity */
+ target_affinity &= target_affinity_mask;
+
+ /* If one or more VCPU matching target affinity are running
+ * then return 0 (ON) else return 1 (OFF)
+ */
+ kvm_for_each_vcpu(i, tmp, kvm) {
+ mpidr = kvm_vcpu_get_mpidr(tmp);
+ if (((mpidr & target_affinity_mask) == target_affinity) &&
+ !tmp->arch.pause) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
static inline void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type)
{
memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
@@ -132,6 +181,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
case KVM_PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu);
break;
+ case KVM_PSCI_0_2_FN_AFFINITY_INFO:
+ case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
+ val = kvm_psci_vcpu_affinity_info(vcpu);
+ break;
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
kvm_psci_system_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
@@ -143,12 +196,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
ret = 0;
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN_MIGRATE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_MIGRATE:
case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 08/10] ARM/ARM64: KVM: Emulate PSCI v0.2 MIGRATE_INFO_TYPE and related functions
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
This patch adds emulation of PSCI v0.2 MIGRATE, MIGRATE_INFO_TYPE, and
MIGRATE_INFO_UP_CPU function calls for KVM ARM/ARM64.
KVM ARM/ARM64 being a hypervisor (and not a Trusted OS), we cannot provide
this functions hence we emulate these functions in following way:
1. MIGRATE - Returns "Not Supported"
2. MIGRATE_INFO_TYPE - Return 2 i.e. Trusted OS is either not present
or does not require migration
3. MIGRATE_INFO_UP_CPU - Returns "Not Supported"
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
arch/arm/kvm/psci.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 9890710..75447a3 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -120,7 +120,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
/* Ignore other bits of target affinity */
target_affinity &= target_affinity_mask;
- /* If one or more VCPU matching target affinity are running
+ /*
+ * If one or more VCPU matching target affinity are running
* then return 0 (ON) else return 1 (OFF)
*/
kvm_for_each_vcpu(i, tmp, kvm) {
@@ -185,6 +186,21 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
val = kvm_psci_vcpu_affinity_info(vcpu);
break;
+ case KVM_PSCI_0_2_FN_MIGRATE:
+ case KVM_PSCI_0_2_FN64_MIGRATE:
+ val = KVM_PSCI_RET_NI;
+ break;
+ case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+ /*
+ * Trusted OS is either not present or
+ * does not require migration
+ */
+ val = 2;
+ break;
+ case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
+ case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
+ val = KVM_PSCI_RET_NI;
+ break;
case KVM_PSCI_0_2_FN_SYSTEM_OFF:
kvm_psci_system_off(vcpu);
val = KVM_PSCI_RET_SUCCESS;
@@ -196,12 +212,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
ret = 0;
break;
case KVM_PSCI_0_2_FN_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN_MIGRATE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
- case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
- case KVM_PSCI_0_2_FN64_MIGRATE:
- case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
val = KVM_PSCI_RET_NI;
break;
default:
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 09/10] ARM/ARM64: KVM: Fix CPU_ON emulation for PSCI v0.2
From: Anup Patel @ 2014-02-06 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391686302-19451-1-git-send-email-anup.patel@linaro.org>
As-per PSCI v0.2, the source CPU provides physical address of
"entry point" and "context id" for starting a target CPU.
Current emulation of CPU_ON function does not consider physical
address of "context id" hence this patch updates kvm_psci_vcpu_on()
such that it works for both PSCI v0.1 and PSCI v0.2.
Signed-off-by: Anup Patel <anup.patel@linaro.org>
Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
---
arch/arm/kvm/psci.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 75447a3..675866e 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -32,12 +32,14 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
vcpu->arch.pause = true;
}
-static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
+static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu,
+ int psci_version)
{
struct kvm *kvm = source_vcpu->kvm;
struct kvm_vcpu *vcpu = NULL, *tmp;
wait_queue_head_t *wq;
unsigned long cpu_id;
+ unsigned long context_id;
unsigned long mpidr;
phys_addr_t target_pc;
int i;
@@ -62,6 +64,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
return KVM_PSCI_RET_INVAL;
target_pc = *vcpu_reg(source_vcpu, 2);
+ context_id = *vcpu_reg(source_vcpu, 3);
kvm_reset_vcpu(vcpu);
@@ -76,6 +79,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
kvm_vcpu_set_be(vcpu);
*vcpu_pc(vcpu) = target_pc;
+ if (psci_version != KVM_ARM_PSCI_0_1)
+ *vcpu_reg(vcpu, 0) = context_id;
vcpu->arch.pause = false;
smp_mb(); /* Make sure the above is visible */
@@ -180,7 +185,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
break;
case KVM_PSCI_0_2_FN_CPU_ON:
case KVM_PSCI_0_2_FN64_CPU_ON:
- val = kvm_psci_vcpu_on(vcpu);
+ val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_2);
break;
case KVM_PSCI_0_2_FN_AFFINITY_INFO:
case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
@@ -234,7 +239,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
val = KVM_PSCI_RET_SUCCESS;
break;
case KVM_PSCI_FN_CPU_ON:
- val = kvm_psci_vcpu_on(vcpu);
+ val = kvm_psci_vcpu_on(vcpu, KVM_ARM_PSCI_0_1);
break;
case KVM_PSCI_FN_CPU_SUSPEND:
case KVM_PSCI_FN_MIGRATE:
--
1.7.9.5
^ 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