All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation
@ 2018-01-29 17:45 ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

ARM has recently published a SMC Calling Convention (SMCCC)
specification update[1] that provides an optimised calling convention
and optional, discoverable support for mitigating CVE-2017-5715. ARM
Trusted Firmware (ATF) has already gained such an implementation[2].

This series addresses a few things:

- It provides a KVM implementation of PSCI v1.0, which is a
  prerequisite for being able to discover SMCCC v1.1, together with a
  new userspace API to control the PSCI revision number that the guest
  sees.

- It allows KVM to advertise SMCCC v1.1, which is de-facto supported
  already (it never corrupts any of the guest registers).

- It implements KVM support for the ARCH_WORKAROUND_1 function that is
  used to mitigate CVE-2017-5715 in a guest (if such mitigation is
  available on the host).

- It implements SMCCC v1.1 and ARCH_WORKAROUND_1 discovery support in
  the kernel itself.

- It finally provides firmware callbacks for CVE-2017-5715 for both
  kernel and KVM.

This method is intended to fully replace the initial PSCI_GET_VERSION
approach. Although PSCI_GET_VERSION still works, it has an obvious
overhead and is called on some of the hottest paths. We expect
ARCH_WORKAROUND_1 to be much faster.

Patch 1 is already merged, and included here for reference. Patches on
top of arm64/for-next/core. Tested on Seattle and Juno, the latter
with ATF implementing SMCCC v1.1.

[1]: https://developer.arm.com/-/media/developer/pdf/ARM%20DEN%200070A%20Firmware%20interfaces%20for%20mitigating%20CVE-2017-5715_V1.0.pdf

Hopefully this link is a persistent one. It is otherwise linked to
from [3], which is persistent.

[2]: https://github.com/ARM-software/arm-trusted-firmware/pull/1240

[3]: https://developer.arm.com/support/security-update/frequently-asked-questions

* From v1:
  - Fixed 32bit build
  - Fix function number sign extension (Ard)
  - Inline SMCCC v1.1 primitives (cpp soup)
  - Prevent SMCCC spamming on feature probing
  - Random fixes and tidying up

Marc Zyngier (16):
  arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  arm/arm64: KVM: Consolidate the PSCI include files
  arm/arm64: KVM: Add PSCI_VERSION helper
  arm/arm64: KVM: Add smccc accessors to PSCI code
  arm/arm64: KVM: Implement PSCI 1.0 support
  arm/arm64: KVM: Add PSCI version selection API
  arm/arm64: KVM: Advertise SMCCC v1.1
  arm/arm64: KVM: Turn kvm_psci_version into a static inline
  arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
  arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
  firmware/psci: Expose PSCI conduit
  firmware/psci: Expose SMCCC version through psci_ops
  arm/arm64: smccc: Make function identifiers an unsigned quantity
  arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

 Documentation/virtual/kvm/api.txt      |   3 +-
 Documentation/virtual/kvm/arm/psci.txt |  30 +++++
 arch/arm/include/asm/kvm_host.h        |   3 +
 arch/arm/include/asm/kvm_psci.h        |  27 -----
 arch/arm/include/uapi/asm/kvm.h        |   6 +
 arch/arm/kvm/guest.c                   |  13 +++
 arch/arm/kvm/handle_exit.c             |   8 +-
 arch/arm64/include/asm/kvm_host.h      |   3 +
 arch/arm64/include/asm/kvm_psci.h      |  44 ++++++-
 arch/arm64/include/uapi/asm/kvm.h      |   6 +
 arch/arm64/kernel/bpi.S                |  20 ++++
 arch/arm64/kernel/cpu_errata.c         |  68 ++++++++++-
 arch/arm64/kvm/guest.c                 |  14 ++-
 arch/arm64/kvm/handle_exit.c           |   9 +-
 arch/arm64/kvm/hyp/hyp-entry.S         |  20 +++-
 arch/arm64/kvm/hyp/switch.c            |  20 ++--
 drivers/firmware/psci.c                |  49 +++++++-
 include/kvm/arm_psci.h                 |  63 ++++++++++
 include/linux/arm-smccc.h              | 181 ++++++++++++++++++++++++++++-
 include/linux/psci.h                   |  13 +++
 virt/kvm/arm/arm.c                     |   2 +-
 virt/kvm/arm/psci.c                    | 202 +++++++++++++++++++++++++++++----
 22 files changed, 721 insertions(+), 83 deletions(-)
 create mode 100644 Documentation/virtual/kvm/arm/psci.txt
 delete mode 100644 arch/arm/include/asm/kvm_psci.h
 create mode 100644 include/kvm/arm_psci.h

-- 
2.14.2

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation
@ 2018-01-29 17:45 ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

ARM has recently published a SMC Calling Convention (SMCCC)
specification update[1] that provides an optimised calling convention
and optional, discoverable support for mitigating CVE-2017-5715. ARM
Trusted Firmware (ATF) has already gained such an implementation[2].

This series addresses a few things:

- It provides a KVM implementation of PSCI v1.0, which is a
  prerequisite for being able to discover SMCCC v1.1, together with a
  new userspace API to control the PSCI revision number that the guest
  sees.

- It allows KVM to advertise SMCCC v1.1, which is de-facto supported
  already (it never corrupts any of the guest registers).

- It implements KVM support for the ARCH_WORKAROUND_1 function that is
  used to mitigate CVE-2017-5715 in a guest (if such mitigation is
  available on the host).

- It implements SMCCC v1.1 and ARCH_WORKAROUND_1 discovery support in
  the kernel itself.

- It finally provides firmware callbacks for CVE-2017-5715 for both
  kernel and KVM.

This method is intended to fully replace the initial PSCI_GET_VERSION
approach. Although PSCI_GET_VERSION still works, it has an obvious
overhead and is called on some of the hottest paths. We expect
ARCH_WORKAROUND_1 to be much faster.

Patch 1 is already merged, and included here for reference. Patches on
top of arm64/for-next/core. Tested on Seattle and Juno, the latter
with ATF implementing SMCCC v1.1.

[1]: https://developer.arm.com/-/media/developer/pdf/ARM%20DEN%200070A%20Firmware%20interfaces%20for%20mitigating%20CVE-2017-5715_V1.0.pdf

Hopefully this link is a persistent one. It is otherwise linked to
from [3], which is persistent.

[2]: https://github.com/ARM-software/arm-trusted-firmware/pull/1240

[3]: https://developer.arm.com/support/security-update/frequently-asked-questions

* From v1:
  - Fixed 32bit build
  - Fix function number sign extension (Ard)
  - Inline SMCCC v1.1 primitives (cpp soup)
  - Prevent SMCCC spamming on feature probing
  - Random fixes and tidying up

Marc Zyngier (16):
  arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  arm/arm64: KVM: Consolidate the PSCI include files
  arm/arm64: KVM: Add PSCI_VERSION helper
  arm/arm64: KVM: Add smccc accessors to PSCI code
  arm/arm64: KVM: Implement PSCI 1.0 support
  arm/arm64: KVM: Add PSCI version selection API
  arm/arm64: KVM: Advertise SMCCC v1.1
  arm/arm64: KVM: Turn kvm_psci_version into a static inline
  arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
  arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
  firmware/psci: Expose PSCI conduit
  firmware/psci: Expose SMCCC version through psci_ops
  arm/arm64: smccc: Make function identifiers an unsigned quantity
  arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

 Documentation/virtual/kvm/api.txt      |   3 +-
 Documentation/virtual/kvm/arm/psci.txt |  30 +++++
 arch/arm/include/asm/kvm_host.h        |   3 +
 arch/arm/include/asm/kvm_psci.h        |  27 -----
 arch/arm/include/uapi/asm/kvm.h        |   6 +
 arch/arm/kvm/guest.c                   |  13 +++
 arch/arm/kvm/handle_exit.c             |   8 +-
 arch/arm64/include/asm/kvm_host.h      |   3 +
 arch/arm64/include/asm/kvm_psci.h      |  44 ++++++-
 arch/arm64/include/uapi/asm/kvm.h      |   6 +
 arch/arm64/kernel/bpi.S                |  20 ++++
 arch/arm64/kernel/cpu_errata.c         |  68 ++++++++++-
 arch/arm64/kvm/guest.c                 |  14 ++-
 arch/arm64/kvm/handle_exit.c           |   9 +-
 arch/arm64/kvm/hyp/hyp-entry.S         |  20 +++-
 arch/arm64/kvm/hyp/switch.c            |  20 ++--
 drivers/firmware/psci.c                |  49 +++++++-
 include/kvm/arm_psci.h                 |  63 ++++++++++
 include/linux/arm-smccc.h              | 181 ++++++++++++++++++++++++++++-
 include/linux/psci.h                   |  13 +++
 virt/kvm/arm/arm.c                     |   2 +-
 virt/kvm/arm/psci.c                    | 202 +++++++++++++++++++++++++++++----
 22 files changed, 721 insertions(+), 83 deletions(-)
 create mode 100644 Documentation/virtual/kvm/arm/psci.txt
 delete mode 100644 arch/arm/include/asm/kvm_psci.h
 create mode 100644 include/kvm/arm_psci.h

-- 
2.14.2

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 01/16] arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

KVM doesn't follow the SMCCC when it comes to unimplemented calls,
and inject an UNDEF instead of returning an error. Since firmware
calls are now used for security mitigation, they are becoming more
common, and the undef is counter productive.

Instead, let's follow the SMCCC which states that -1 must be returned
to the caller when getting an unknown function number.

Cc: <stable@vger.kernel.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
 arch/arm64/kvm/handle_exit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index c09fc5a576c7..520b0dad3c62 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -53,7 +53,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 	ret = kvm_psci_call(vcpu);
 	if (ret < 0) {
-		kvm_inject_undefined(vcpu);
+		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
 	}
 
@@ -62,7 +62,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	kvm_inject_undefined(vcpu);
+	vcpu_set_reg(vcpu, 0, ~0UL);
 	return 1;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 01/16] arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

KVM doesn't follow the SMCCC when it comes to unimplemented calls,
and inject an UNDEF instead of returning an error. Since firmware
calls are now used for security mitigation, they are becoming more
common, and the undef is counter productive.

Instead, let's follow the SMCCC which states that -1 must be returned
to the caller when getting an unknown function number.

Cc: <stable@vger.kernel.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
 arch/arm64/kvm/handle_exit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index c09fc5a576c7..520b0dad3c62 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -53,7 +53,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 	ret = kvm_psci_call(vcpu);
 	if (ret < 0) {
-		kvm_inject_undefined(vcpu);
+		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
 	}
 
@@ -62,7 +62,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	kvm_inject_undefined(vcpu);
+	vcpu_set_reg(vcpu, 0, ~0UL);
 	return 1;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 02/16] arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

KVM doesn't follow the SMCCC when it comes to unimplemented calls,
and inject an UNDEF instead of returning an error. Since firmware
calls are now used for security mitigation, they are becoming more
common, and the undef is counter productive.

Instead, let's follow the SMCCC which states that -1 must be returned
to the caller when getting an unknown function number.

Cc: <stable@vger.kernel.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/handle_exit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index cf8bf6bf87c4..d15ac772d186 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,7 +38,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 	ret = kvm_psci_call(vcpu);
 	if (ret < 0) {
-		kvm_inject_undefined(vcpu);
+		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
 	}
 
@@ -47,7 +47,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	kvm_inject_undefined(vcpu);
+	vcpu_set_reg(vcpu, 0, ~0UL);
 	return 1;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 02/16] arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Jon Masters, Robin Murphy,
	Christoffer Dall

KVM doesn't follow the SMCCC when it comes to unimplemented calls,
and inject an UNDEF instead of returning an error. Since firmware
calls are now used for security mitigation, they are becoming more
common, and the undef is counter productive.

Instead, let's follow the SMCCC which states that -1 must be returned
to the caller when getting an unknown function number.

Cc: <stable@vger.kernel.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/handle_exit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index cf8bf6bf87c4..d15ac772d186 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,7 +38,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 	ret = kvm_psci_call(vcpu);
 	if (ret < 0) {
-		kvm_inject_undefined(vcpu);
+		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
 	}
 
@@ -47,7 +47,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	kvm_inject_undefined(vcpu);
+	vcpu_set_reg(vcpu, 0, ~0UL);
 	return 1;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 02/16] arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

KVM doesn't follow the SMCCC when it comes to unimplemented calls,
and inject an UNDEF instead of returning an error. Since firmware
calls are now used for security mitigation, they are becoming more
common, and the undef is counter productive.

Instead, let's follow the SMCCC which states that -1 must be returned
to the caller when getting an unknown function number.

Cc: <stable@vger.kernel.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/handle_exit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index cf8bf6bf87c4..d15ac772d186 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,7 +38,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 	ret = kvm_psci_call(vcpu);
 	if (ret < 0) {
-		kvm_inject_undefined(vcpu);
+		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
 	}
 
@@ -47,7 +47,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	kvm_inject_undefined(vcpu);
+	vcpu_set_reg(vcpu, 0, ~0UL);
 	return 1;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 03/16] arm/arm64: KVM: Consolidate the PSCI include files
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

As we're about to update the PSCI support, and because I'm lazy,
let's move the PSCI include file to include/kvm so that both
ARM architectures can find it.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/kvm_psci.h                    | 27 ----------------------
 arch/arm/kvm/handle_exit.c                         |  2 +-
 arch/arm64/kvm/handle_exit.c                       |  3 ++-
 .../asm/kvm_psci.h => include/kvm/arm_psci.h       |  6 ++---
 virt/kvm/arm/arm.c                                 |  2 +-
 virt/kvm/arm/psci.c                                |  3 ++-
 6 files changed, 9 insertions(+), 34 deletions(-)
 delete mode 100644 arch/arm/include/asm/kvm_psci.h
 rename arch/arm64/include/asm/kvm_psci.h => include/kvm/arm_psci.h (89%)

diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
deleted file mode 100644
index 6bda945d31fa..000000000000
--- a/arch/arm/include/asm/kvm_psci.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2012 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#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);
-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 d15ac772d186..e020cc82c4b1 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -21,7 +21,7 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_mmu.h>
-#include <asm/kvm_psci.h>
+#include <kvm/arm_psci.h>
 #include <trace/events/kvm.h>
 
 #include "trace.h"
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 520b0dad3c62..97e8d64a203d 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -22,13 +22,14 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 
+#include <kvm/arm_psci.h>
+
 #include <asm/esr.h>
 #include <asm/exception.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
-#include <asm/kvm_psci.h>
 #include <asm/debug-monitors.h>
 #include <asm/traps.h>
 
diff --git a/arch/arm64/include/asm/kvm_psci.h b/include/kvm/arm_psci.h
similarity index 89%
rename from arch/arm64/include/asm/kvm_psci.h
rename to include/kvm/arm_psci.h
index bc39e557c56c..2042bb909474 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -15,8 +15,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __ARM64_KVM_PSCI_H__
-#define __ARM64_KVM_PSCI_H__
+#ifndef __KVM_ARM_PSCI_H__
+#define __KVM_ARM_PSCI_H__
 
 #define KVM_ARM_PSCI_0_1	1
 #define KVM_ARM_PSCI_0_2	2
@@ -24,4 +24,4 @@
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
 
-#endif /* __ARM64_KVM_PSCI_H__ */
+#endif /* __KVM_ARM_PSCI_H__ */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 15bf026eb182..af3e98fc377e 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -31,6 +31,7 @@
 #include <linux/irqbypass.h>
 #include <trace/events/kvm.h>
 #include <kvm/arm_pmu.h>
+#include <kvm/arm_psci.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -46,7 +47,6 @@
 #include <asm/kvm_mmu.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
-#include <asm/kvm_psci.h>
 #include <asm/sections.h>
 
 #ifdef REQUIRES_VIRT
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index f1e363bab5e8..b322e46fd142 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -21,9 +21,10 @@
 
 #include <asm/cputype.h>
 #include <asm/kvm_emulate.h>
-#include <asm/kvm_psci.h>
 #include <asm/kvm_host.h>
 
+#include <kvm/arm_psci.h>
+
 #include <uapi/linux/psci.h>
 
 /*
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 03/16] arm/arm64: KVM: Consolidate the PSCI include files
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

As we're about to update the PSCI support, and because I'm lazy,
let's move the PSCI include file to include/kvm so that both
ARM architectures can find it.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/kvm_psci.h                    | 27 ----------------------
 arch/arm/kvm/handle_exit.c                         |  2 +-
 arch/arm64/kvm/handle_exit.c                       |  3 ++-
 .../asm/kvm_psci.h => include/kvm/arm_psci.h       |  6 ++---
 virt/kvm/arm/arm.c                                 |  2 +-
 virt/kvm/arm/psci.c                                |  3 ++-
 6 files changed, 9 insertions(+), 34 deletions(-)
 delete mode 100644 arch/arm/include/asm/kvm_psci.h
 rename arch/arm64/include/asm/kvm_psci.h => include/kvm/arm_psci.h (89%)

diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
deleted file mode 100644
index 6bda945d31fa..000000000000
--- a/arch/arm/include/asm/kvm_psci.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2012 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#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);
-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 d15ac772d186..e020cc82c4b1 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -21,7 +21,7 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_mmu.h>
-#include <asm/kvm_psci.h>
+#include <kvm/arm_psci.h>
 #include <trace/events/kvm.h>
 
 #include "trace.h"
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 520b0dad3c62..97e8d64a203d 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -22,13 +22,14 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 
+#include <kvm/arm_psci.h>
+
 #include <asm/esr.h>
 #include <asm/exception.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
-#include <asm/kvm_psci.h>
 #include <asm/debug-monitors.h>
 #include <asm/traps.h>
 
diff --git a/arch/arm64/include/asm/kvm_psci.h b/include/kvm/arm_psci.h
similarity index 89%
rename from arch/arm64/include/asm/kvm_psci.h
rename to include/kvm/arm_psci.h
index bc39e557c56c..2042bb909474 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -15,8 +15,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __ARM64_KVM_PSCI_H__
-#define __ARM64_KVM_PSCI_H__
+#ifndef __KVM_ARM_PSCI_H__
+#define __KVM_ARM_PSCI_H__
 
 #define KVM_ARM_PSCI_0_1	1
 #define KVM_ARM_PSCI_0_2	2
@@ -24,4 +24,4 @@
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
 
-#endif /* __ARM64_KVM_PSCI_H__ */
+#endif /* __KVM_ARM_PSCI_H__ */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 15bf026eb182..af3e98fc377e 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -31,6 +31,7 @@
 #include <linux/irqbypass.h>
 #include <trace/events/kvm.h>
 #include <kvm/arm_pmu.h>
+#include <kvm/arm_psci.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -46,7 +47,6 @@
 #include <asm/kvm_mmu.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
-#include <asm/kvm_psci.h>
 #include <asm/sections.h>
 
 #ifdef REQUIRES_VIRT
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index f1e363bab5e8..b322e46fd142 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -21,9 +21,10 @@
 
 #include <asm/cputype.h>
 #include <asm/kvm_emulate.h>
-#include <asm/kvm_psci.h>
 #include <asm/kvm_host.h>
 
+#include <kvm/arm_psci.h>
+
 #include <uapi/linux/psci.h>
 
 /*
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

As we're about to trigger a PSCI version explosion, it doesn't
hurt to introduce a PSCI_VERSION helper that is going to be
used everywhere.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_psci.h | 5 +++--
 virt/kvm/arm/psci.c    | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 2042bb909474..3a408c846c09 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -18,8 +18,9 @@
 #ifndef __KVM_ARM_PSCI_H__
 #define __KVM_ARM_PSCI_H__
 
-#define KVM_ARM_PSCI_0_1	1
-#define KVM_ARM_PSCI_0_2	2
+#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
+#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index b322e46fd142..c00bb324e14e 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -222,7 +222,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		 * Bits[31:16] = Major Version = 0
 		 * Bits[15:0] = Minor Version = 2
 		 */
-		val = 2;
+		val = KVM_ARM_PSCI_0_2;
 		break;
 	case PSCI_0_2_FN_CPU_SUSPEND:
 	case PSCI_0_2_FN64_CPU_SUSPEND:
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Jon Masters, Robin Murphy,
	Christoffer Dall

As we're about to trigger a PSCI version explosion, it doesn't
hurt to introduce a PSCI_VERSION helper that is going to be
used everywhere.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_psci.h | 5 +++--
 virt/kvm/arm/psci.c    | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 2042bb909474..3a408c846c09 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -18,8 +18,9 @@
 #ifndef __KVM_ARM_PSCI_H__
 #define __KVM_ARM_PSCI_H__
 
-#define KVM_ARM_PSCI_0_1	1
-#define KVM_ARM_PSCI_0_2	2
+#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
+#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index b322e46fd142..c00bb324e14e 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -222,7 +222,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		 * Bits[31:16] = Major Version = 0
 		 * Bits[15:0] = Minor Version = 2
 		 */
-		val = 2;
+		val = KVM_ARM_PSCI_0_2;
 		break;
 	case PSCI_0_2_FN_CPU_SUSPEND:
 	case PSCI_0_2_FN64_CPU_SUSPEND:
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

As we're about to trigger a PSCI version explosion, it doesn't
hurt to introduce a PSCI_VERSION helper that is going to be
used everywhere.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_psci.h | 5 +++--
 virt/kvm/arm/psci.c    | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 2042bb909474..3a408c846c09 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -18,8 +18,9 @@
 #ifndef __KVM_ARM_PSCI_H__
 #define __KVM_ARM_PSCI_H__
 
-#define KVM_ARM_PSCI_0_1	1
-#define KVM_ARM_PSCI_0_2	2
+#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
+#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index b322e46fd142..c00bb324e14e 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -222,7 +222,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		 * Bits[31:16] = Major Version = 0
 		 * Bits[15:0] = Minor Version = 2
 		 */
-		val = 2;
+		val = KVM_ARM_PSCI_0_2;
 		break;
 	case PSCI_0_2_FN_CPU_SUSPEND:
 	case PSCI_0_2_FN64_CPU_SUSPEND:
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 05/16] arm/arm64: KVM: Add smccc accessors to PSCI code
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Instead of open coding the accesses to the various registers,
let's add explicit SMCCC accessors.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/psci.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 42 insertions(+), 10 deletions(-)

diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index c00bb324e14e..053654082bd4 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -34,6 +34,38 @@
 
 #define AFFINITY_MASK(level)	~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1)
 
+static u32 smccc_get_function(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 0);
+}
+
+static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 1);
+}
+
+static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 2);
+}
+
+static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 3);
+}
+
+static void smccc_set_retval(struct kvm_vcpu *vcpu,
+			     unsigned long a0,
+			     unsigned long a1,
+			     unsigned long a2,
+			     unsigned long a3)
+{
+	vcpu_set_reg(vcpu, 0, a0);
+	vcpu_set_reg(vcpu, 1, a1);
+	vcpu_set_reg(vcpu, 2, a2);
+	vcpu_set_reg(vcpu, 3, a3);
+}
+
 static unsigned long psci_affinity_mask(unsigned long affinity_level)
 {
 	if (affinity_level <= 3)
@@ -79,7 +111,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	unsigned long context_id;
 	phys_addr_t target_pc;
 
-	cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
+	cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK;
 	if (vcpu_mode_is_32bit(source_vcpu))
 		cpu_id &= ~((u32) 0);
 
@@ -98,8 +130,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 			return PSCI_RET_INVALID_PARAMS;
 	}
 
-	target_pc = vcpu_get_reg(source_vcpu, 2);
-	context_id = vcpu_get_reg(source_vcpu, 3);
+	target_pc = smccc_get_arg2(source_vcpu);
+	context_id = smccc_get_arg3(source_vcpu);
 
 	kvm_reset_vcpu(vcpu);
 
@@ -118,7 +150,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	 * NOTE: We always update r0 (or x0) because for PSCI v0.1
 	 * the general puspose registers are undefined upon CPU_ON.
 	 */
-	vcpu_set_reg(vcpu, 0, context_id);
+	smccc_set_retval(vcpu, context_id, 0, 0, 0);
 	vcpu->arch.power_off = false;
 	smp_mb();		/* Make sure the above is visible */
 
@@ -138,8 +170,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
 	struct kvm *kvm = vcpu->kvm;
 	struct kvm_vcpu *tmp;
 
-	target_affinity = vcpu_get_reg(vcpu, 1);
-	lowest_affinity_level = vcpu_get_reg(vcpu, 2);
+	target_affinity = smccc_get_arg1(vcpu);
+	lowest_affinity_level = smccc_get_arg2(vcpu);
 
 	/* Determine target affinity mask */
 	target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
@@ -212,7 +244,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
-	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
+	u32 psci_fn = smccc_get_function(vcpu);
 	unsigned long val;
 	int ret = 1;
 
@@ -279,14 +311,14 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		break;
 	}
 
-	vcpu_set_reg(vcpu, 0, val);
+	smccc_set_retval(vcpu, val, 0, 0, 0);
 	return ret;
 }
 
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
-	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
+	u32 psci_fn = smccc_get_function(vcpu);
 	unsigned long val;
 
 	switch (psci_fn) {
@@ -304,7 +336,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 		break;
 	}
 
-	vcpu_set_reg(vcpu, 0, val);
+	smccc_set_retval(vcpu, val, 0, 0, 0);
 	return 1;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 05/16] arm/arm64: KVM: Add smccc accessors to PSCI code
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

Instead of open coding the accesses to the various registers,
let's add explicit SMCCC accessors.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/psci.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 42 insertions(+), 10 deletions(-)

diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index c00bb324e14e..053654082bd4 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -34,6 +34,38 @@
 
 #define AFFINITY_MASK(level)	~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1)
 
+static u32 smccc_get_function(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 0);
+}
+
+static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 1);
+}
+
+static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 2);
+}
+
+static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu)
+{
+	return vcpu_get_reg(vcpu, 3);
+}
+
+static void smccc_set_retval(struct kvm_vcpu *vcpu,
+			     unsigned long a0,
+			     unsigned long a1,
+			     unsigned long a2,
+			     unsigned long a3)
+{
+	vcpu_set_reg(vcpu, 0, a0);
+	vcpu_set_reg(vcpu, 1, a1);
+	vcpu_set_reg(vcpu, 2, a2);
+	vcpu_set_reg(vcpu, 3, a3);
+}
+
 static unsigned long psci_affinity_mask(unsigned long affinity_level)
 {
 	if (affinity_level <= 3)
@@ -79,7 +111,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	unsigned long context_id;
 	phys_addr_t target_pc;
 
-	cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
+	cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK;
 	if (vcpu_mode_is_32bit(source_vcpu))
 		cpu_id &= ~((u32) 0);
 
@@ -98,8 +130,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 			return PSCI_RET_INVALID_PARAMS;
 	}
 
-	target_pc = vcpu_get_reg(source_vcpu, 2);
-	context_id = vcpu_get_reg(source_vcpu, 3);
+	target_pc = smccc_get_arg2(source_vcpu);
+	context_id = smccc_get_arg3(source_vcpu);
 
 	kvm_reset_vcpu(vcpu);
 
@@ -118,7 +150,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	 * NOTE: We always update r0 (or x0) because for PSCI v0.1
 	 * the general puspose registers are undefined upon CPU_ON.
 	 */
-	vcpu_set_reg(vcpu, 0, context_id);
+	smccc_set_retval(vcpu, context_id, 0, 0, 0);
 	vcpu->arch.power_off = false;
 	smp_mb();		/* Make sure the above is visible */
 
@@ -138,8 +170,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
 	struct kvm *kvm = vcpu->kvm;
 	struct kvm_vcpu *tmp;
 
-	target_affinity = vcpu_get_reg(vcpu, 1);
-	lowest_affinity_level = vcpu_get_reg(vcpu, 2);
+	target_affinity = smccc_get_arg1(vcpu);
+	lowest_affinity_level = smccc_get_arg2(vcpu);
 
 	/* Determine target affinity mask */
 	target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
@@ -212,7 +244,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
-	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
+	u32 psci_fn = smccc_get_function(vcpu);
 	unsigned long val;
 	int ret = 1;
 
@@ -279,14 +311,14 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		break;
 	}
 
-	vcpu_set_reg(vcpu, 0, val);
+	smccc_set_retval(vcpu, val, 0, 0, 0);
 	return ret;
 }
 
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
-	unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
+	u32 psci_fn = smccc_get_function(vcpu);
 	unsigned long val;
 
 	switch (psci_fn) {
@@ -304,7 +336,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 		break;
 	}
 
-	vcpu_set_reg(vcpu, 0, val);
+	smccc_set_retval(vcpu, val, 0, 0, 0);
 	return 1;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 06/16] arm/arm64: KVM: Implement PSCI 1.0 support
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

PSCI 1.0 can be trivially implemented by having PSCI 0.2 and
the FEATURES call. Of, and returning 1.0 as the PSCI version.

We happily ignore everything else, as it is optional.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_psci.h |  1 +
 virt/kvm/arm/psci.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 3a408c846c09..e7f69c0dc249 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -21,6 +21,7 @@
 #define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
 #define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
 #define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0	PSCI_VERSION(1, 0)
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 053654082bd4..6299501f7664 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -315,6 +315,47 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 	return ret;
 }
 
+static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
+{
+	u32 psci_fn = smccc_get_function(vcpu);
+	u32 feature;
+	unsigned long val;
+	int ret = 1;
+
+	switch(psci_fn) {
+	case PSCI_0_2_FN_PSCI_VERSION:
+		val = KVM_ARM_PSCI_1_0;
+		break;
+	case PSCI_1_0_FN_PSCI_FEATURES:
+		feature = smccc_get_arg1(vcpu);
+		switch(feature) {
+		case PSCI_0_2_FN_PSCI_VERSION:
+		case PSCI_0_2_FN_CPU_SUSPEND:
+		case PSCI_0_2_FN64_CPU_SUSPEND:
+		case PSCI_0_2_FN_CPU_OFF:
+		case PSCI_0_2_FN_CPU_ON:
+		case PSCI_0_2_FN64_CPU_ON:
+		case PSCI_0_2_FN_AFFINITY_INFO:
+		case PSCI_0_2_FN64_AFFINITY_INFO:
+		case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+		case PSCI_0_2_FN_SYSTEM_OFF:
+		case PSCI_0_2_FN_SYSTEM_RESET:
+		case PSCI_1_0_FN_PSCI_FEATURES:
+			val = 0;
+			break;
+		default:
+			val = PSCI_RET_NOT_SUPPORTED;
+			break;
+		}
+		break;
+	default:
+		return kvm_psci_0_2_call(vcpu);
+	}
+
+	smccc_set_retval(vcpu, val, 0, 0, 0);
+	return ret;
+}
+
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
@@ -357,6 +398,8 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
 	switch (kvm_psci_version(vcpu)) {
+	case KVM_ARM_PSCI_1_0:
+		return kvm_psci_1_0_call(vcpu);
 	case KVM_ARM_PSCI_0_2:
 		return kvm_psci_0_2_call(vcpu);
 	case KVM_ARM_PSCI_0_1:
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 06/16] arm/arm64: KVM: Implement PSCI 1.0 support
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

PSCI 1.0 can be trivially implemented by having PSCI 0.2 and
the FEATURES call. Of, and returning 1.0 as the PSCI version.

We happily ignore everything else, as it is optional.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_psci.h |  1 +
 virt/kvm/arm/psci.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 3a408c846c09..e7f69c0dc249 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -21,6 +21,7 @@
 #define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
 #define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
 #define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0	PSCI_VERSION(1, 0)
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 053654082bd4..6299501f7664 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -315,6 +315,47 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 	return ret;
 }
 
+static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
+{
+	u32 psci_fn = smccc_get_function(vcpu);
+	u32 feature;
+	unsigned long val;
+	int ret = 1;
+
+	switch(psci_fn) {
+	case PSCI_0_2_FN_PSCI_VERSION:
+		val = KVM_ARM_PSCI_1_0;
+		break;
+	case PSCI_1_0_FN_PSCI_FEATURES:
+		feature = smccc_get_arg1(vcpu);
+		switch(feature) {
+		case PSCI_0_2_FN_PSCI_VERSION:
+		case PSCI_0_2_FN_CPU_SUSPEND:
+		case PSCI_0_2_FN64_CPU_SUSPEND:
+		case PSCI_0_2_FN_CPU_OFF:
+		case PSCI_0_2_FN_CPU_ON:
+		case PSCI_0_2_FN64_CPU_ON:
+		case PSCI_0_2_FN_AFFINITY_INFO:
+		case PSCI_0_2_FN64_AFFINITY_INFO:
+		case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+		case PSCI_0_2_FN_SYSTEM_OFF:
+		case PSCI_0_2_FN_SYSTEM_RESET:
+		case PSCI_1_0_FN_PSCI_FEATURES:
+			val = 0;
+			break;
+		default:
+			val = PSCI_RET_NOT_SUPPORTED;
+			break;
+		}
+		break;
+	default:
+		return kvm_psci_0_2_call(vcpu);
+	}
+
+	smccc_set_retval(vcpu, val, 0, 0, 0);
+	return ret;
+}
+
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
@@ -357,6 +398,8 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
 	switch (kvm_psci_version(vcpu)) {
+	case KVM_ARM_PSCI_1_0:
+		return kvm_psci_1_0_call(vcpu);
 	case KVM_ARM_PSCI_0_2:
 		return kvm_psci_0_2_call(vcpu);
 	case KVM_ARM_PSCI_0_1:
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Although we've implemented PSCI 1.0 and 1.1, nothing can select them
Since all the new PSCI versions are backward compatible, we decide to
default to the latest version of the PSCI implementation. This is no
different from doing a firmware upgrade on KVM.

But in order to give a chance to hypothetical badly implemented guests
that would have a fit by discovering something other than PSCI 0.2,
let's provide a new API that allows userspace to pick one particular
version of the API.

This is implemented as a new class of "firmware" registers, where
we expose the PSCI version. This allows the PSCI version to be
save/restored as part of a guest migration, and also set to
any supported version if the guest requires it.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/virtual/kvm/api.txt      |  3 +-
 Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
 arch/arm/include/asm/kvm_host.h        |  3 ++
 arch/arm/include/uapi/asm/kvm.h        |  6 +++
 arch/arm/kvm/guest.c                   | 13 +++++++
 arch/arm64/include/asm/kvm_host.h      |  3 ++
 arch/arm64/include/uapi/asm/kvm.h      |  6 +++
 arch/arm64/kvm/guest.c                 | 14 ++++++-
 include/kvm/arm_psci.h                 |  9 +++++
 virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
 10 files changed, 149 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/virtual/kvm/arm/psci.txt

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 57d3ee9e4bde..334905202141 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2493,7 +2493,8 @@ Possible features:
 	  and execute guest code when KVM_RUN is called.
 	- 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.
+	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
+          backward compatible with v0.2) for the CPU.
 	  Depends on KVM_CAP_ARM_PSCI_0_2.
 	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
 	  Depends on KVM_CAP_ARM_PMU_V3.
diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
new file mode 100644
index 000000000000..2e49a4e9f084
--- /dev/null
+++ b/Documentation/virtual/kvm/arm/psci.txt
@@ -0,0 +1,28 @@
+KVM implements the PSCI (Power State Coordination Interface)
+specification in order to provide services such as CPU on/off, reset
+and power-off to the guest.
+
+The PSCI specification is regularly updated to provide new features,
+and KVM implements these updates if they make sense from a virtualization
+point of view.
+
+This means that a guest booted on two different versions of KVM can
+observe two different "firmware" revisions. This could cause issues if
+a given guest is tied to a particular PSCI revision (unlikely), or if
+a migration causes a different PSCI version to be exposed out of the
+blue to an unsuspecting guest.
+
+In order to remedy this situation, KVM exposes a set of "firmware
+pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
+interface. These registers can be saved/restored by userspace, and set
+to a convenient value if required.
+
+The following register is defined:
+
+* KVM_REG_ARM_PSCI_VERSION:
+
+  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
+  - Returns the current PSCI version on GET_ONE_REG
+  - Allows any supported PSCI version compatible with v0.2 to be set
+    with SET_ONE_REG
+  - Affects the whole VM (even if the register view is per-vcpu)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index acbf9ec7b396..e9d57060d88c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -75,6 +75,9 @@ struct kvm_arch {
 	/* Interrupt controller */
 	struct vgic_dist	vgic;
 	int max_vcpus;
+
+	/* Mandated version of PSCI */
+	u32 psci_version;
 };
 
 #define KVM_NR_MEM_OBJS     40
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 6edd177bb1c7..47dfc99f5cd0 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_VFP_FPINST		0x1009
 #define KVM_REG_ARM_VFP_FPINST2		0x100A
 
+/* KVM-as-firmware specific pseudo-registers */
+#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_REG(r)		(KVM_REG_ARM | KVM_REG_SIZE_U64 | \
+					 KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_PSCI_VERSION	KVM_REG_ARM_FW_REG(0)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 1e0784ebbfd6..a18f33edc471 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <kvm/arm_psci.h>
 #include <asm/cputype.h>
 #include <linux/uaccess.h>
 #include <asm/kvm.h>
@@ -176,6 +177,7 @@ static unsigned long num_core_regs(void)
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
 	return num_core_regs() + kvm_arm_num_coproc_regs(vcpu)
+		+ kvm_arm_get_fw_num_regs(vcpu)
 		+ NUM_TIMER_REGS;
 }
 
@@ -196,6 +198,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 		uindices++;
 	}
 
+	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
+	if (ret)
+		return ret;
+	uindices += kvm_arm_get_fw_num_regs(vcpu);
+
 	ret = copy_timer_indices(vcpu, uindices);
 	if (ret)
 		return ret;
@@ -214,6 +221,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return get_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_get_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return get_timer_reg(vcpu, reg);
 
@@ -230,6 +240,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return set_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_set_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return set_timer_reg(vcpu, reg);
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 4485ae8e98de..10af386642c6 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -73,6 +73,9 @@ struct kvm_arch {
 
 	/* Interrupt controller */
 	struct vgic_dist	vgic;
+
+	/* Mandated version of PSCI */
+	u32 psci_version;
 };
 
 #define KVM_NR_MEM_OBJS     40
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 9abbf3044654..04b3256f8e6d 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -206,6 +206,12 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_TIMER_CNT		ARM64_SYS_REG(3, 3, 14, 3, 2)
 #define KVM_REG_ARM_TIMER_CVAL		ARM64_SYS_REG(3, 3, 14, 0, 2)
 
+/* KVM-as-firmware specific pseudo-registers */
+#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_REG(r)		(KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
+					 KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_PSCI_VERSION	KVM_REG_ARM_FW_REG(0)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 5c7f657dd207..811f04c5760e 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <kvm/arm_psci.h>
 #include <asm/cputype.h>
 #include <linux/uaccess.h>
 #include <asm/kvm.h>
@@ -205,7 +206,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
 	return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu)
-                + NUM_TIMER_REGS;
+		+ kvm_arm_get_fw_num_regs(vcpu)	+ NUM_TIMER_REGS;
 }
 
 /**
@@ -225,6 +226,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 		uindices++;
 	}
 
+	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
+	if (ret)
+		return ret;
+	uindices += kvm_arm_get_fw_num_regs(vcpu);
+
 	ret = copy_timer_indices(vcpu, uindices);
 	if (ret)
 		return ret;
@@ -243,6 +249,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return get_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_get_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return get_timer_reg(vcpu, reg);
 
@@ -259,6 +268,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return set_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_set_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return set_timer_reg(vcpu, reg);
 
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index e7f69c0dc249..f2fa7d752c4e 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -23,7 +23,16 @@
 #define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
 #define KVM_ARM_PSCI_1_0	PSCI_VERSION(1, 0)
 
+#define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
+
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
 
+struct kvm_one_reg;
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+
 #endif /* __KVM_ARM_PSCI_H__ */
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 6299501f7664..682f9be6264b 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -17,6 +17,7 @@
 
 #include <linux/preempt.h>
 #include <linux/kvm_host.h>
+#include <linux/uaccess.h>
 #include <linux/wait.h>
 
 #include <asm/cputype.h>
@@ -235,8 +236,19 @@ static void kvm_psci_system_reset(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;
+	/*
+	 * Our PSCI implementation stays the same across versions from
+	 * v0.2 onward, only adding the few mandatory functions (such
+	 * as FEATURES with 1.0) that are required by newer
+	 * revisions. It is thus safe to return the latest, unless
+	 * userspace has instructed us otherwise.
+	 */
+	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		if (vcpu->kvm->arch.psci_version)
+			return vcpu->kvm->arch.psci_version;
+
+		return KVM_ARM_PSCI_LATEST;
+	}
 
 	return KVM_ARM_PSCI_0_1;
 }
@@ -408,3 +420,55 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
 		return -EINVAL;
 	};
 }
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
+{
+	return 1;		/* PSCI version */
+}
+
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+	if (put_user(KVM_REG_ARM_PSCI_VERSION, uindices))
+		return -EFAULT;
+
+	return 0;
+}
+
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	if (reg->id == KVM_REG_ARM_PSCI_VERSION) {
+		void __user *uaddr = (void __user *)(long)reg->addr;
+		u64 val;
+
+		val = kvm_psci_version(vcpu, vcpu->kvm);
+		if (val == KVM_ARM_PSCI_0_1)
+			return -EINVAL;
+		if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
+			return -EFAULT;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	if (reg->id == KVM_REG_ARM_PSCI_VERSION &&
+	    test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		void __user *uaddr = (void __user *)(long)reg->addr;
+		u64 val;
+
+		if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
+			return -EFAULT;
+
+		switch (val) {
+		case KVM_ARM_PSCI_0_2:
+		case KVM_ARM_PSCI_1_0:
+			vcpu->kvm->arch.psci_version = val;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

Although we've implemented PSCI 1.0 and 1.1, nothing can select them
Since all the new PSCI versions are backward compatible, we decide to
default to the latest version of the PSCI implementation. This is no
different from doing a firmware upgrade on KVM.

But in order to give a chance to hypothetical badly implemented guests
that would have a fit by discovering something other than PSCI 0.2,
let's provide a new API that allows userspace to pick one particular
version of the API.

This is implemented as a new class of "firmware" registers, where
we expose the PSCI version. This allows the PSCI version to be
save/restored as part of a guest migration, and also set to
any supported version if the guest requires it.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/virtual/kvm/api.txt      |  3 +-
 Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
 arch/arm/include/asm/kvm_host.h        |  3 ++
 arch/arm/include/uapi/asm/kvm.h        |  6 +++
 arch/arm/kvm/guest.c                   | 13 +++++++
 arch/arm64/include/asm/kvm_host.h      |  3 ++
 arch/arm64/include/uapi/asm/kvm.h      |  6 +++
 arch/arm64/kvm/guest.c                 | 14 ++++++-
 include/kvm/arm_psci.h                 |  9 +++++
 virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
 10 files changed, 149 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/virtual/kvm/arm/psci.txt

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 57d3ee9e4bde..334905202141 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2493,7 +2493,8 @@ Possible features:
 	  and execute guest code when KVM_RUN is called.
 	- 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.
+	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
+          backward compatible with v0.2) for the CPU.
 	  Depends on KVM_CAP_ARM_PSCI_0_2.
 	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
 	  Depends on KVM_CAP_ARM_PMU_V3.
diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
new file mode 100644
index 000000000000..2e49a4e9f084
--- /dev/null
+++ b/Documentation/virtual/kvm/arm/psci.txt
@@ -0,0 +1,28 @@
+KVM implements the PSCI (Power State Coordination Interface)
+specification in order to provide services such as CPU on/off, reset
+and power-off to the guest.
+
+The PSCI specification is regularly updated to provide new features,
+and KVM implements these updates if they make sense from a virtualization
+point of view.
+
+This means that a guest booted on two different versions of KVM can
+observe two different "firmware" revisions. This could cause issues if
+a given guest is tied to a particular PSCI revision (unlikely), or if
+a migration causes a different PSCI version to be exposed out of the
+blue to an unsuspecting guest.
+
+In order to remedy this situation, KVM exposes a set of "firmware
+pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
+interface. These registers can be saved/restored by userspace, and set
+to a convenient value if required.
+
+The following register is defined:
+
+* KVM_REG_ARM_PSCI_VERSION:
+
+  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
+  - Returns the current PSCI version on GET_ONE_REG
+  - Allows any supported PSCI version compatible with v0.2 to be set
+    with SET_ONE_REG
+  - Affects the whole VM (even if the register view is per-vcpu)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index acbf9ec7b396..e9d57060d88c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -75,6 +75,9 @@ struct kvm_arch {
 	/* Interrupt controller */
 	struct vgic_dist	vgic;
 	int max_vcpus;
+
+	/* Mandated version of PSCI */
+	u32 psci_version;
 };
 
 #define KVM_NR_MEM_OBJS     40
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 6edd177bb1c7..47dfc99f5cd0 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_VFP_FPINST		0x1009
 #define KVM_REG_ARM_VFP_FPINST2		0x100A
 
+/* KVM-as-firmware specific pseudo-registers */
+#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_REG(r)		(KVM_REG_ARM | KVM_REG_SIZE_U64 | \
+					 KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_PSCI_VERSION	KVM_REG_ARM_FW_REG(0)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 1e0784ebbfd6..a18f33edc471 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <kvm/arm_psci.h>
 #include <asm/cputype.h>
 #include <linux/uaccess.h>
 #include <asm/kvm.h>
@@ -176,6 +177,7 @@ static unsigned long num_core_regs(void)
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
 	return num_core_regs() + kvm_arm_num_coproc_regs(vcpu)
+		+ kvm_arm_get_fw_num_regs(vcpu)
 		+ NUM_TIMER_REGS;
 }
 
@@ -196,6 +198,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 		uindices++;
 	}
 
+	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
+	if (ret)
+		return ret;
+	uindices += kvm_arm_get_fw_num_regs(vcpu);
+
 	ret = copy_timer_indices(vcpu, uindices);
 	if (ret)
 		return ret;
@@ -214,6 +221,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return get_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_get_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return get_timer_reg(vcpu, reg);
 
@@ -230,6 +240,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return set_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_set_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return set_timer_reg(vcpu, reg);
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 4485ae8e98de..10af386642c6 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -73,6 +73,9 @@ struct kvm_arch {
 
 	/* Interrupt controller */
 	struct vgic_dist	vgic;
+
+	/* Mandated version of PSCI */
+	u32 psci_version;
 };
 
 #define KVM_NR_MEM_OBJS     40
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 9abbf3044654..04b3256f8e6d 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -206,6 +206,12 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_TIMER_CNT		ARM64_SYS_REG(3, 3, 14, 3, 2)
 #define KVM_REG_ARM_TIMER_CVAL		ARM64_SYS_REG(3, 3, 14, 0, 2)
 
+/* KVM-as-firmware specific pseudo-registers */
+#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_REG(r)		(KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
+					 KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_PSCI_VERSION	KVM_REG_ARM_FW_REG(0)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 5c7f657dd207..811f04c5760e 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <kvm/arm_psci.h>
 #include <asm/cputype.h>
 #include <linux/uaccess.h>
 #include <asm/kvm.h>
@@ -205,7 +206,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
 	return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu)
-                + NUM_TIMER_REGS;
+		+ kvm_arm_get_fw_num_regs(vcpu)	+ NUM_TIMER_REGS;
 }
 
 /**
@@ -225,6 +226,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 		uindices++;
 	}
 
+	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
+	if (ret)
+		return ret;
+	uindices += kvm_arm_get_fw_num_regs(vcpu);
+
 	ret = copy_timer_indices(vcpu, uindices);
 	if (ret)
 		return ret;
@@ -243,6 +249,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return get_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_get_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return get_timer_reg(vcpu, reg);
 
@@ -259,6 +268,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
 		return set_core_reg(vcpu, reg);
 
+	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
+		return kvm_arm_set_fw_reg(vcpu, reg);
+
 	if (is_timer_reg(reg->id))
 		return set_timer_reg(vcpu, reg);
 
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index e7f69c0dc249..f2fa7d752c4e 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -23,7 +23,16 @@
 #define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
 #define KVM_ARM_PSCI_1_0	PSCI_VERSION(1, 0)
 
+#define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
+
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
 
+struct kvm_one_reg;
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+
 #endif /* __KVM_ARM_PSCI_H__ */
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 6299501f7664..682f9be6264b 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -17,6 +17,7 @@
 
 #include <linux/preempt.h>
 #include <linux/kvm_host.h>
+#include <linux/uaccess.h>
 #include <linux/wait.h>
 
 #include <asm/cputype.h>
@@ -235,8 +236,19 @@ static void kvm_psci_system_reset(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;
+	/*
+	 * Our PSCI implementation stays the same across versions from
+	 * v0.2 onward, only adding the few mandatory functions (such
+	 * as FEATURES with 1.0) that are required by newer
+	 * revisions. It is thus safe to return the latest, unless
+	 * userspace has instructed us otherwise.
+	 */
+	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		if (vcpu->kvm->arch.psci_version)
+			return vcpu->kvm->arch.psci_version;
+
+		return KVM_ARM_PSCI_LATEST;
+	}
 
 	return KVM_ARM_PSCI_0_1;
 }
@@ -408,3 +420,55 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
 		return -EINVAL;
 	};
 }
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
+{
+	return 1;		/* PSCI version */
+}
+
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+	if (put_user(KVM_REG_ARM_PSCI_VERSION, uindices))
+		return -EFAULT;
+
+	return 0;
+}
+
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	if (reg->id == KVM_REG_ARM_PSCI_VERSION) {
+		void __user *uaddr = (void __user *)(long)reg->addr;
+		u64 val;
+
+		val = kvm_psci_version(vcpu, vcpu->kvm);
+		if (val == KVM_ARM_PSCI_0_1)
+			return -EINVAL;
+		if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
+			return -EFAULT;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	if (reg->id == KVM_REG_ARM_PSCI_VERSION &&
+	    test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		void __user *uaddr = (void __user *)(long)reg->addr;
+		u64 val;
+
+		if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
+			return -EFAULT;
+
+		switch (val) {
+		case KVM_ARM_PSCI_0_2:
+		case KVM_ARM_PSCI_1_0:
+			vcpu->kvm->arch.psci_version = val;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

The new SMC Calling Convention (v1.1) allows for a reduced overhead
when calling into the firmware, and provides a new feature discovery
mechanism.

Make it visible to KVM guests.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/virtual/kvm/arm/psci.txt | 12 +++++++-----
 arch/arm/kvm/handle_exit.c             |  2 +-
 arch/arm64/kvm/handle_exit.c           |  2 +-
 include/kvm/arm_psci.h                 |  2 +-
 include/linux/arm-smccc.h              | 13 +++++++++++++
 virt/kvm/arm/psci.c                    | 24 +++++++++++++++++++++++-
 6 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
index 2e49a4e9f084..aafdab887b04 100644
--- a/Documentation/virtual/kvm/arm/psci.txt
+++ b/Documentation/virtual/kvm/arm/psci.txt
@@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out of the
 blue to an unsuspecting guest.
 
 In order to remedy this situation, KVM exposes a set of "firmware
-pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
+pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
 interface. These registers can be saved/restored by userspace, and set
 to a convenient value if required.
 
@@ -21,8 +21,10 @@ The following register is defined:
 
 * KVM_REG_ARM_PSCI_VERSION:
 
-  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
-  - Returns the current PSCI version on GET_ONE_REG
-  - Allows any supported PSCI version compatible with v0.2 to be set
-    with SET_ONE_REG
+  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
+    (and thus has already been initialized)
+  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
+    highest PSCI version implemented by KVM and compatible with v0.2)
+  - Allows any PSCI version implemented by KVM and compatible with
+    v0.2 to be set with SET_ONE_REG
   - Affects the whole VM (even if the register view is per-vcpu)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index e020cc82c4b1..a4520c7118d2 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		      kvm_vcpu_hvc_get_imm(vcpu));
 	vcpu->stat.hvc_exit_stat++;
 
-	ret = kvm_psci_call(vcpu);
+	ret = kvm_hvc_call_handler(vcpu);
 	if (ret < 0) {
 		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 97e8d64a203d..bb6e1518d819 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			    kvm_vcpu_hvc_get_imm(vcpu));
 	vcpu->stat.hvc_exit_stat++;
 
-	ret = kvm_psci_call(vcpu);
+	ret = kvm_hvc_call_handler(vcpu);
 	if (ret < 0) {
 		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index f2fa7d752c4e..4876bfac2195 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -26,7 +26,7 @@
 #define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
-int kvm_psci_call(struct kvm_vcpu *vcpu);
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
 
 struct kvm_one_reg;
 
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 4c5bca38c653..dc68aa5a7261 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -60,6 +60,19 @@
 #define ARM_SMCCC_QUIRK_NONE		0
 #define ARM_SMCCC_QUIRK_QCOM_A6		1 /* Save/restore register a6 */
 
+#define ARM_SMCCC_VERSION_1_0		0x10000
+#define ARM_SMCCC_VERSION_1_1		0x10001
+
+#define ARM_SMCCC_VERSION_FUNC_ID					\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
+			   ARM_SMCCC_SMC_32,				\
+			   0, 0)
+
+#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID					\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
+			   ARM_SMCCC_SMC_32,				\
+			   0, 1)
+
 #ifndef __ASSEMBLY__
 
 #include <linux/linkage.h>
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 682f9be6264b..3bb336ac7d7d 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/arm-smccc.h>
 #include <linux/preempt.h>
 #include <linux/kvm_host.h>
 #include <linux/uaccess.h>
@@ -353,6 +354,7 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
 		case PSCI_0_2_FN_SYSTEM_OFF:
 		case PSCI_0_2_FN_SYSTEM_RESET:
 		case PSCI_1_0_FN_PSCI_FEATURES:
+		case ARM_SMCCC_VERSION_FUNC_ID:
 			val = 0;
 			break;
 		default:
@@ -407,7 +409,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
  * Errors:
  * -EINVAL: Unrecognized PSCI function
  */
-int kvm_psci_call(struct kvm_vcpu *vcpu)
+static int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
 	switch (kvm_psci_version(vcpu)) {
 	case KVM_ARM_PSCI_1_0:
@@ -421,6 +423,26 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
 	};
 }
 
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
+{
+	u32 func_id = smccc_get_function(vcpu);
+	u32 val;
+
+	switch (func_id) {
+	case ARM_SMCCC_VERSION_FUNC_ID:
+		val = ARM_SMCCC_VERSION_1_1;
+		break;
+	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
+		val = -1;	/* Nothing supported yet */
+		break;
+	default:
+		return kvm_psci_call(vcpu);
+	}
+
+	smccc_set_retval(vcpu, val, 0, 0, 0);
+	return 1;
+}
+
 int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
 {
 	return 1;		/* PSCI version */
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

The new SMC Calling Convention (v1.1) allows for a reduced overhead
when calling into the firmware, and provides a new feature discovery
mechanism.

Make it visible to KVM guests.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/virtual/kvm/arm/psci.txt | 12 +++++++-----
 arch/arm/kvm/handle_exit.c             |  2 +-
 arch/arm64/kvm/handle_exit.c           |  2 +-
 include/kvm/arm_psci.h                 |  2 +-
 include/linux/arm-smccc.h              | 13 +++++++++++++
 virt/kvm/arm/psci.c                    | 24 +++++++++++++++++++++++-
 6 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
index 2e49a4e9f084..aafdab887b04 100644
--- a/Documentation/virtual/kvm/arm/psci.txt
+++ b/Documentation/virtual/kvm/arm/psci.txt
@@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out of the
 blue to an unsuspecting guest.
 
 In order to remedy this situation, KVM exposes a set of "firmware
-pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
+pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
 interface. These registers can be saved/restored by userspace, and set
 to a convenient value if required.
 
@@ -21,8 +21,10 @@ The following register is defined:
 
 * KVM_REG_ARM_PSCI_VERSION:
 
-  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
-  - Returns the current PSCI version on GET_ONE_REG
-  - Allows any supported PSCI version compatible with v0.2 to be set
-    with SET_ONE_REG
+  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
+    (and thus has already been initialized)
+  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
+    highest PSCI version implemented by KVM and compatible with v0.2)
+  - Allows any PSCI version implemented by KVM and compatible with
+    v0.2 to be set with SET_ONE_REG
   - Affects the whole VM (even if the register view is per-vcpu)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index e020cc82c4b1..a4520c7118d2 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		      kvm_vcpu_hvc_get_imm(vcpu));
 	vcpu->stat.hvc_exit_stat++;
 
-	ret = kvm_psci_call(vcpu);
+	ret = kvm_hvc_call_handler(vcpu);
 	if (ret < 0) {
 		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 97e8d64a203d..bb6e1518d819 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			    kvm_vcpu_hvc_get_imm(vcpu));
 	vcpu->stat.hvc_exit_stat++;
 
-	ret = kvm_psci_call(vcpu);
+	ret = kvm_hvc_call_handler(vcpu);
 	if (ret < 0) {
 		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index f2fa7d752c4e..4876bfac2195 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -26,7 +26,7 @@
 #define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
-int kvm_psci_call(struct kvm_vcpu *vcpu);
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
 
 struct kvm_one_reg;
 
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 4c5bca38c653..dc68aa5a7261 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -60,6 +60,19 @@
 #define ARM_SMCCC_QUIRK_NONE		0
 #define ARM_SMCCC_QUIRK_QCOM_A6		1 /* Save/restore register a6 */
 
+#define ARM_SMCCC_VERSION_1_0		0x10000
+#define ARM_SMCCC_VERSION_1_1		0x10001
+
+#define ARM_SMCCC_VERSION_FUNC_ID					\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
+			   ARM_SMCCC_SMC_32,				\
+			   0, 0)
+
+#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID					\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
+			   ARM_SMCCC_SMC_32,				\
+			   0, 1)
+
 #ifndef __ASSEMBLY__
 
 #include <linux/linkage.h>
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 682f9be6264b..3bb336ac7d7d 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/arm-smccc.h>
 #include <linux/preempt.h>
 #include <linux/kvm_host.h>
 #include <linux/uaccess.h>
@@ -353,6 +354,7 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
 		case PSCI_0_2_FN_SYSTEM_OFF:
 		case PSCI_0_2_FN_SYSTEM_RESET:
 		case PSCI_1_0_FN_PSCI_FEATURES:
+		case ARM_SMCCC_VERSION_FUNC_ID:
 			val = 0;
 			break;
 		default:
@@ -407,7 +409,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
  * Errors:
  * -EINVAL: Unrecognized PSCI function
  */
-int kvm_psci_call(struct kvm_vcpu *vcpu)
+static int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
 	switch (kvm_psci_version(vcpu)) {
 	case KVM_ARM_PSCI_1_0:
@@ -421,6 +423,26 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
 	};
 }
 
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
+{
+	u32 func_id = smccc_get_function(vcpu);
+	u32 val;
+
+	switch (func_id) {
+	case ARM_SMCCC_VERSION_FUNC_ID:
+		val = ARM_SMCCC_VERSION_1_1;
+		break;
+	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
+		val = -1;	/* Nothing supported yet */
+		break;
+	default:
+		return kvm_psci_call(vcpu);
+	}
+
+	smccc_set_retval(vcpu, val, 0, 0, 0);
+	return 1;
+}
+
 int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
 {
 	return 1;		/* PSCI version */
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 09/16] arm/arm64: KVM: Turn kvm_psci_version into a static inline
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

We're about to need kvm_psci_version in HYP too. So let's turn it
into a static inline, and pass the kvm structure as a second
parameter (so that HYP can do a kern_hyp_va on it).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/hyp/switch.c | 20 ++++++++++++--------
 include/kvm/arm_psci.h      | 27 ++++++++++++++++++++++++++-
 virt/kvm/arm/psci.c         | 23 ++---------------------
 3 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 036e1f3d77a6..408c04d789a5 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -19,6 +19,8 @@
 #include <linux/jump_label.h>
 #include <uapi/linux/psci.h>
 
+#include <kvm/arm_psci.h>
+
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
@@ -350,14 +352,16 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
 
 	if (exit_code == ARM_EXCEPTION_TRAP &&
 	    (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC64 ||
-	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32) &&
-	    vcpu_get_reg(vcpu, 0) == PSCI_0_2_FN_PSCI_VERSION) {
-		u64 val = PSCI_RET_NOT_SUPPORTED;
-		if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
-			val = 2;
-
-		vcpu_set_reg(vcpu, 0, val);
-		goto again;
+	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32)) {
+		u32 val = vcpu_get_reg(vcpu, 0);
+
+		if (val == PSCI_0_2_FN_PSCI_VERSION) {
+			val = kvm_psci_version(vcpu, kern_hyp_va(vcpu->kvm));
+			if (unlikely(val == KVM_ARM_PSCI_0_1))
+				val = PSCI_RET_NOT_SUPPORTED;
+			vcpu_set_reg(vcpu, 0, val);
+			goto again;
+		}
 	}
 
 	if (static_branch_unlikely(&vgic_v2_cpuif_trap) &&
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 4876bfac2195..32978b578002 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -18,6 +18,8 @@
 #ifndef __KVM_ARM_PSCI_H__
 #define __KVM_ARM_PSCI_H__
 
+#include <linux/kvm_host.h>
+
 #define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
 #define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
 #define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
@@ -25,7 +27,30 @@
 
 #define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
 
-int kvm_psci_version(struct kvm_vcpu *vcpu);
+/*
+ * We need the KVM pointer independently from the vcpu as we can call
+ * this from HYP, and need to apply kern_hyp_va on it...
+ */
+static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+	/*
+	 * Our PSCI implementation stays the same across versions from
+	 * v0.2 onward, only adding the few mandatory functions (such
+	 * as FEATURES with 1.0) that are required by newer
+	 * revisions. It is thus safe to return the latest, unless
+	 * userspace has instructed us otherwise.
+	 */
+	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		if (kvm->arch.psci_version)
+			return kvm->arch.psci_version;
+
+		return KVM_ARM_PSCI_LATEST;
+	}
+
+	return KVM_ARM_PSCI_0_1;
+}
+
+
 int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
 
 struct kvm_one_reg;
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 3bb336ac7d7d..a021b62ed762 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -126,7 +126,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	if (!vcpu)
 		return PSCI_RET_INVALID_PARAMS;
 	if (!vcpu->arch.power_off) {
-		if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
+		if (kvm_psci_version(source_vcpu, kvm) != KVM_ARM_PSCI_0_1)
 			return PSCI_RET_ALREADY_ON;
 		else
 			return PSCI_RET_INVALID_PARAMS;
@@ -235,25 +235,6 @@ 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)
-{
-	/*
-	 * Our PSCI implementation stays the same across versions from
-	 * v0.2 onward, only adding the few mandatory functions (such
-	 * as FEATURES with 1.0) that are required by newer
-	 * revisions. It is thus safe to return the latest, unless
-	 * userspace has instructed us otherwise.
-	 */
-	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
-		if (vcpu->kvm->arch.psci_version)
-			return vcpu->kvm->arch.psci_version;
-
-		return KVM_ARM_PSCI_LATEST;
-	}
-
-	return KVM_ARM_PSCI_0_1;
-}
-
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
@@ -411,7 +392,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
  */
 static int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
-	switch (kvm_psci_version(vcpu)) {
+	switch (kvm_psci_version(vcpu, vcpu->kvm)) {
 	case KVM_ARM_PSCI_1_0:
 		return kvm_psci_1_0_call(vcpu);
 	case KVM_ARM_PSCI_0_2:
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 09/16] arm/arm64: KVM: Turn kvm_psci_version into a static inline
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

We're about to need kvm_psci_version in HYP too. So let's turn it
into a static inline, and pass the kvm structure as a second
parameter (so that HYP can do a kern_hyp_va on it).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/hyp/switch.c | 20 ++++++++++++--------
 include/kvm/arm_psci.h      | 27 ++++++++++++++++++++++++++-
 virt/kvm/arm/psci.c         | 23 ++---------------------
 3 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 036e1f3d77a6..408c04d789a5 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -19,6 +19,8 @@
 #include <linux/jump_label.h>
 #include <uapi/linux/psci.h>
 
+#include <kvm/arm_psci.h>
+
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
@@ -350,14 +352,16 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
 
 	if (exit_code == ARM_EXCEPTION_TRAP &&
 	    (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC64 ||
-	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32) &&
-	    vcpu_get_reg(vcpu, 0) == PSCI_0_2_FN_PSCI_VERSION) {
-		u64 val = PSCI_RET_NOT_SUPPORTED;
-		if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
-			val = 2;
-
-		vcpu_set_reg(vcpu, 0, val);
-		goto again;
+	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32)) {
+		u32 val = vcpu_get_reg(vcpu, 0);
+
+		if (val == PSCI_0_2_FN_PSCI_VERSION) {
+			val = kvm_psci_version(vcpu, kern_hyp_va(vcpu->kvm));
+			if (unlikely(val == KVM_ARM_PSCI_0_1))
+				val = PSCI_RET_NOT_SUPPORTED;
+			vcpu_set_reg(vcpu, 0, val);
+			goto again;
+		}
 	}
 
 	if (static_branch_unlikely(&vgic_v2_cpuif_trap) &&
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 4876bfac2195..32978b578002 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -18,6 +18,8 @@
 #ifndef __KVM_ARM_PSCI_H__
 #define __KVM_ARM_PSCI_H__
 
+#include <linux/kvm_host.h>
+
 #define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
 #define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
 #define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
@@ -25,7 +27,30 @@
 
 #define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
 
-int kvm_psci_version(struct kvm_vcpu *vcpu);
+/*
+ * We need the KVM pointer independently from the vcpu as we can call
+ * this from HYP, and need to apply kern_hyp_va on it...
+ */
+static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+	/*
+	 * Our PSCI implementation stays the same across versions from
+	 * v0.2 onward, only adding the few mandatory functions (such
+	 * as FEATURES with 1.0) that are required by newer
+	 * revisions. It is thus safe to return the latest, unless
+	 * userspace has instructed us otherwise.
+	 */
+	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		if (kvm->arch.psci_version)
+			return kvm->arch.psci_version;
+
+		return KVM_ARM_PSCI_LATEST;
+	}
+
+	return KVM_ARM_PSCI_0_1;
+}
+
+
 int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
 
 struct kvm_one_reg;
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 3bb336ac7d7d..a021b62ed762 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -126,7 +126,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	if (!vcpu)
 		return PSCI_RET_INVALID_PARAMS;
 	if (!vcpu->arch.power_off) {
-		if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
+		if (kvm_psci_version(source_vcpu, kvm) != KVM_ARM_PSCI_0_1)
 			return PSCI_RET_ALREADY_ON;
 		else
 			return PSCI_RET_INVALID_PARAMS;
@@ -235,25 +235,6 @@ 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)
-{
-	/*
-	 * Our PSCI implementation stays the same across versions from
-	 * v0.2 onward, only adding the few mandatory functions (such
-	 * as FEATURES with 1.0) that are required by newer
-	 * revisions. It is thus safe to return the latest, unless
-	 * userspace has instructed us otherwise.
-	 */
-	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
-		if (vcpu->kvm->arch.psci_version)
-			return vcpu->kvm->arch.psci_version;
-
-		return KVM_ARM_PSCI_LATEST;
-	}
-
-	return KVM_ARM_PSCI_0_1;
-}
-
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
@@ -411,7 +392,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
  */
 static int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
-	switch (kvm_psci_version(vcpu)) {
+	switch (kvm_psci_version(vcpu, vcpu->kvm)) {
 	case KVM_ARM_PSCI_1_0:
 		return kvm_psci_1_0_call(vcpu);
 	case KVM_ARM_PSCI_0_2:
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 10/16] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

A new feature of SMCCC 1.1 is that it offers firmware-based CPU
workarounds. In particular, SMCCC_ARCH_WORKAROUND_1 provides
BP hardening for CVE-2017-5715.

If the host has some mitigation for this issue, report that
we deal with it using SMCCC_ARCH_WORKAROUND_1, as we apply the
host workaround on every guest exit.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h |  5 +++++
 virt/kvm/arm/psci.c       | 17 +++++++++++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dc68aa5a7261..e1ef944ef1da 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -73,6 +73,11 @@
 			   ARM_SMCCC_SMC_32,				\
 			   0, 1)
 
+#define ARM_SMCCC_ARCH_WORKAROUND_1					\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
+			   ARM_SMCCC_SMC_32,				\
+			   0, 0x8000)
+
 #ifndef __ASSEMBLY__
 
 #include <linux/linkage.h>
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index a021b62ed762..5677d16abc71 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -407,14 +407,27 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
 int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
 {
 	u32 func_id = smccc_get_function(vcpu);
-	u32 val;
+	u32 val, feature;
 
 	switch (func_id) {
 	case ARM_SMCCC_VERSION_FUNC_ID:
 		val = ARM_SMCCC_VERSION_1_1;
 		break;
 	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
-		val = -1;	/* Nothing supported yet */
+		feature = smccc_get_arg1(vcpu);
+		switch(feature) {
+#ifdef CONFIG_ARM64
+		case ARM_SMCCC_ARCH_WORKAROUND_1:
+			if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR))
+				val = 0;
+			else
+				val = -1;
+			break;
+#endif
+		default:
+			val = -1;
+			break;
+		}
 		break;
 	default:
 		return kvm_psci_call(vcpu);
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 10/16] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

A new feature of SMCCC 1.1 is that it offers firmware-based CPU
workarounds. In particular, SMCCC_ARCH_WORKAROUND_1 provides
BP hardening for CVE-2017-5715.

If the host has some mitigation for this issue, report that
we deal with it using SMCCC_ARCH_WORKAROUND_1, as we apply the
host workaround on every guest exit.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h |  5 +++++
 virt/kvm/arm/psci.c       | 17 +++++++++++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dc68aa5a7261..e1ef944ef1da 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -73,6 +73,11 @@
 			   ARM_SMCCC_SMC_32,				\
 			   0, 1)
 
+#define ARM_SMCCC_ARCH_WORKAROUND_1					\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
+			   ARM_SMCCC_SMC_32,				\
+			   0, 0x8000)
+
 #ifndef __ASSEMBLY__
 
 #include <linux/linkage.h>
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index a021b62ed762..5677d16abc71 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -407,14 +407,27 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
 int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
 {
 	u32 func_id = smccc_get_function(vcpu);
-	u32 val;
+	u32 val, feature;
 
 	switch (func_id) {
 	case ARM_SMCCC_VERSION_FUNC_ID:
 		val = ARM_SMCCC_VERSION_1_1;
 		break;
 	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
-		val = -1;	/* Nothing supported yet */
+		feature = smccc_get_arg1(vcpu);
+		switch(feature) {
+#ifdef CONFIG_ARM64
+		case ARM_SMCCC_ARCH_WORKAROUND_1:
+			if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR))
+				val = 0;
+			else
+				val = -1;
+			break;
+#endif
+		default:
+			val = -1;
+			break;
+		}
 		break;
 	default:
 		return kvm_psci_call(vcpu);
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 11/16] arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

We want SMCCC_ARCH_WORKAROUND_1 to be fast. As fast as possible.
So let's intercept it as early as we can by testing for the
function call number as soon as we've identified a HVC call
coming from the guest.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/hyp/hyp-entry.S | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index e4f37b9dd47c..f36464bd57c5 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/arm-smccc.h>
 #include <linux/linkage.h>
 
 #include <asm/alternative.h>
@@ -64,10 +65,11 @@ alternative_endif
 	lsr	x0, x1, #ESR_ELx_EC_SHIFT
 
 	cmp	x0, #ESR_ELx_EC_HVC64
+	ccmp	x0, #ESR_ELx_EC_HVC32, #4, ne
 	b.ne	el1_trap
 
-	mrs	x1, vttbr_el2		// If vttbr is valid, the 64bit guest
-	cbnz	x1, el1_trap		// called HVC
+	mrs	x1, vttbr_el2		// If vttbr is valid, the guest
+	cbnz	x1, el1_hvc_guest	// called HVC
 
 	/* Here, we're pretty sure the host called HVC. */
 	ldp	x0, x1, [sp], #16
@@ -100,6 +102,20 @@ alternative_endif
 
 	eret
 
+el1_hvc_guest:
+	/*
+	 * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1.
+	 * The workaround has already been applied on the host,
+	 * so let's quickly get back to the guest. We don't bother
+	 * restoring x1, as it can be clobbered anyway.
+	 */
+	ldr	x1, [sp]				// Guest's x0
+	eor	w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
+	cbnz	w1, el1_trap
+	mov	x0, x1
+	add	sp, sp, #16
+	eret
+
 el1_trap:
 	/*
 	 * x0: ESR_EC
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 11/16] arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Jon Masters, Robin Murphy,
	Christoffer Dall

We want SMCCC_ARCH_WORKAROUND_1 to be fast. As fast as possible.
So let's intercept it as early as we can by testing for the
function call number as soon as we've identified a HVC call
coming from the guest.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/hyp/hyp-entry.S | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index e4f37b9dd47c..f36464bd57c5 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/arm-smccc.h>
 #include <linux/linkage.h>
 
 #include <asm/alternative.h>
@@ -64,10 +65,11 @@ alternative_endif
 	lsr	x0, x1, #ESR_ELx_EC_SHIFT
 
 	cmp	x0, #ESR_ELx_EC_HVC64
+	ccmp	x0, #ESR_ELx_EC_HVC32, #4, ne
 	b.ne	el1_trap
 
-	mrs	x1, vttbr_el2		// If vttbr is valid, the 64bit guest
-	cbnz	x1, el1_trap		// called HVC
+	mrs	x1, vttbr_el2		// If vttbr is valid, the guest
+	cbnz	x1, el1_hvc_guest	// called HVC
 
 	/* Here, we're pretty sure the host called HVC. */
 	ldp	x0, x1, [sp], #16
@@ -100,6 +102,20 @@ alternative_endif
 
 	eret
 
+el1_hvc_guest:
+	/*
+	 * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1.
+	 * The workaround has already been applied on the host,
+	 * so let's quickly get back to the guest. We don't bother
+	 * restoring x1, as it can be clobbered anyway.
+	 */
+	ldr	x1, [sp]				// Guest's x0
+	eor	w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
+	cbnz	w1, el1_trap
+	mov	x0, x1
+	add	sp, sp, #16
+	eret
+
 el1_trap:
 	/*
 	 * x0: ESR_EC
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 11/16] arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

We want SMCCC_ARCH_WORKAROUND_1 to be fast. As fast as possible.
So let's intercept it as early as we can by testing for the
function call number as soon as we've identified a HVC call
coming from the guest.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/hyp/hyp-entry.S | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index e4f37b9dd47c..f36464bd57c5 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/arm-smccc.h>
 #include <linux/linkage.h>
 
 #include <asm/alternative.h>
@@ -64,10 +65,11 @@ alternative_endif
 	lsr	x0, x1, #ESR_ELx_EC_SHIFT
 
 	cmp	x0, #ESR_ELx_EC_HVC64
+	ccmp	x0, #ESR_ELx_EC_HVC32, #4, ne
 	b.ne	el1_trap
 
-	mrs	x1, vttbr_el2		// If vttbr is valid, the 64bit guest
-	cbnz	x1, el1_trap		// called HVC
+	mrs	x1, vttbr_el2		// If vttbr is valid, the guest
+	cbnz	x1, el1_hvc_guest	// called HVC
 
 	/* Here, we're pretty sure the host called HVC. */
 	ldp	x0, x1, [sp], #16
@@ -100,6 +102,20 @@ alternative_endif
 
 	eret
 
+el1_hvc_guest:
+	/*
+	 * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1.
+	 * The workaround has already been applied on the host,
+	 * so let's quickly get back to the guest. We don't bother
+	 * restoring x1, as it can be clobbered anyway.
+	 */
+	ldr	x1, [sp]				// Guest's x0
+	eor	w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
+	cbnz	w1, el1_trap
+	mov	x0, x1
+	add	sp, sp, #16
+	eret
+
 el1_trap:
 	/*
 	 * x0: ESR_EC
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 12/16] firmware/psci: Expose PSCI conduit
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

In order to call into the firmware to apply workarounds, it is
useful to find out whether we're using HVC or SMC. Let's expose
this through the psci_ops.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/firmware/psci.c | 28 +++++++++++++++++++++++-----
 include/linux/psci.h    |  7 +++++++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 8b25d31e8401..e9493da2b111 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
 	return cpu == resident_cpu;
 }
 
-struct psci_operations psci_ops;
+struct psci_operations psci_ops = {
+	.conduit = PSCI_CONDUIT_NONE,
+};
 
 typedef unsigned long (psci_fn)(unsigned long, unsigned long,
 				unsigned long, unsigned long);
@@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
 			      0, 0, 0);
 }
 
+static void set_conduit(enum psci_conduit conduit)
+{
+	switch (conduit) {
+	case PSCI_CONDUIT_HVC:
+		invoke_psci_fn = __invoke_psci_fn_hvc;
+		break;
+	case PSCI_CONDUIT_SMC:
+		invoke_psci_fn = __invoke_psci_fn_smc;
+		break;
+	default:
+		WARN(1, "Unexpected PSCI conduit %d\n", conduit);
+	}
+
+	psci_ops.conduit = conduit;
+}
+
 static int get_set_conduit_method(struct device_node *np)
 {
 	const char *method;
@@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
 	}
 
 	if (!strcmp("hvc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_hvc;
+		set_conduit(PSCI_CONDUIT_HVC);
 	} else if (!strcmp("smc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_smc;
+		set_conduit(PSCI_CONDUIT_SMC);
 	} else {
 		pr_warn("invalid \"method\" property: %s\n", method);
 		return -EINVAL;
@@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
 	pr_info("probing for conduit method from ACPI.\n");
 
 	if (acpi_psci_use_hvc())
-		invoke_psci_fn = __invoke_psci_fn_hvc;
+		set_conduit(PSCI_CONDUIT_HVC);
 	else
-		invoke_psci_fn = __invoke_psci_fn_smc;
+		set_conduit(PSCI_CONDUIT_SMC);
 
 	return psci_probe();
 }
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f724fd8c78e8..f2679e5faa4f 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
 int psci_cpu_init_idle(unsigned int cpu);
 int psci_cpu_suspend_enter(unsigned long index);
 
+enum psci_conduit {
+	PSCI_CONDUIT_NONE,
+	PSCI_CONDUIT_SMC,
+	PSCI_CONDUIT_HVC,
+};
+
 struct psci_operations {
 	u32 (*get_version)(void);
 	int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -34,6 +40,7 @@ struct psci_operations {
 	int (*affinity_info)(unsigned long target_affinity,
 			unsigned long lowest_affinity_level);
 	int (*migrate_info_type)(void);
+	enum psci_conduit conduit;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 12/16] firmware/psci: Expose PSCI conduit
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Lorenzo Pieralisi, Ard Biesheuvel, Catalin Marinas, Will Deacon,
	Jon Masters, Robin Murphy

In order to call into the firmware to apply workarounds, it is
useful to find out whether we're using HVC or SMC. Let's expose
this through the psci_ops.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/firmware/psci.c | 28 +++++++++++++++++++++++-----
 include/linux/psci.h    |  7 +++++++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 8b25d31e8401..e9493da2b111 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
 	return cpu == resident_cpu;
 }
 
-struct psci_operations psci_ops;
+struct psci_operations psci_ops = {
+	.conduit = PSCI_CONDUIT_NONE,
+};
 
 typedef unsigned long (psci_fn)(unsigned long, unsigned long,
 				unsigned long, unsigned long);
@@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
 			      0, 0, 0);
 }
 
+static void set_conduit(enum psci_conduit conduit)
+{
+	switch (conduit) {
+	case PSCI_CONDUIT_HVC:
+		invoke_psci_fn = __invoke_psci_fn_hvc;
+		break;
+	case PSCI_CONDUIT_SMC:
+		invoke_psci_fn = __invoke_psci_fn_smc;
+		break;
+	default:
+		WARN(1, "Unexpected PSCI conduit %d\n", conduit);
+	}
+
+	psci_ops.conduit = conduit;
+}
+
 static int get_set_conduit_method(struct device_node *np)
 {
 	const char *method;
@@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
 	}
 
 	if (!strcmp("hvc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_hvc;
+		set_conduit(PSCI_CONDUIT_HVC);
 	} else if (!strcmp("smc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_smc;
+		set_conduit(PSCI_CONDUIT_SMC);
 	} else {
 		pr_warn("invalid \"method\" property: %s\n", method);
 		return -EINVAL;
@@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
 	pr_info("probing for conduit method from ACPI.\n");
 
 	if (acpi_psci_use_hvc())
-		invoke_psci_fn = __invoke_psci_fn_hvc;
+		set_conduit(PSCI_CONDUIT_HVC);
 	else
-		invoke_psci_fn = __invoke_psci_fn_smc;
+		set_conduit(PSCI_CONDUIT_SMC);
 
 	return psci_probe();
 }
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f724fd8c78e8..f2679e5faa4f 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
 int psci_cpu_init_idle(unsigned int cpu);
 int psci_cpu_suspend_enter(unsigned long index);
 
+enum psci_conduit {
+	PSCI_CONDUIT_NONE,
+	PSCI_CONDUIT_SMC,
+	PSCI_CONDUIT_HVC,
+};
+
 struct psci_operations {
 	u32 (*get_version)(void);
 	int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -34,6 +40,7 @@ struct psci_operations {
 	int (*affinity_info)(unsigned long target_affinity,
 			unsigned long lowest_affinity_level);
 	int (*migrate_info_type)(void);
+	enum psci_conduit conduit;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 12/16] firmware/psci: Expose PSCI conduit
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

In order to call into the firmware to apply workarounds, it is
useful to find out whether we're using HVC or SMC. Let's expose
this through the psci_ops.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/firmware/psci.c | 28 +++++++++++++++++++++++-----
 include/linux/psci.h    |  7 +++++++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 8b25d31e8401..e9493da2b111 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
 	return cpu == resident_cpu;
 }
 
-struct psci_operations psci_ops;
+struct psci_operations psci_ops = {
+	.conduit = PSCI_CONDUIT_NONE,
+};
 
 typedef unsigned long (psci_fn)(unsigned long, unsigned long,
 				unsigned long, unsigned long);
@@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
 			      0, 0, 0);
 }
 
+static void set_conduit(enum psci_conduit conduit)
+{
+	switch (conduit) {
+	case PSCI_CONDUIT_HVC:
+		invoke_psci_fn = __invoke_psci_fn_hvc;
+		break;
+	case PSCI_CONDUIT_SMC:
+		invoke_psci_fn = __invoke_psci_fn_smc;
+		break;
+	default:
+		WARN(1, "Unexpected PSCI conduit %d\n", conduit);
+	}
+
+	psci_ops.conduit = conduit;
+}
+
 static int get_set_conduit_method(struct device_node *np)
 {
 	const char *method;
@@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
 	}
 
 	if (!strcmp("hvc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_hvc;
+		set_conduit(PSCI_CONDUIT_HVC);
 	} else if (!strcmp("smc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_smc;
+		set_conduit(PSCI_CONDUIT_SMC);
 	} else {
 		pr_warn("invalid \"method\" property: %s\n", method);
 		return -EINVAL;
@@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
 	pr_info("probing for conduit method from ACPI.\n");
 
 	if (acpi_psci_use_hvc())
-		invoke_psci_fn = __invoke_psci_fn_hvc;
+		set_conduit(PSCI_CONDUIT_HVC);
 	else
-		invoke_psci_fn = __invoke_psci_fn_smc;
+		set_conduit(PSCI_CONDUIT_SMC);
 
 	return psci_probe();
 }
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f724fd8c78e8..f2679e5faa4f 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
 int psci_cpu_init_idle(unsigned int cpu);
 int psci_cpu_suspend_enter(unsigned long index);
 
+enum psci_conduit {
+	PSCI_CONDUIT_NONE,
+	PSCI_CONDUIT_SMC,
+	PSCI_CONDUIT_HVC,
+};
+
 struct psci_operations {
 	u32 (*get_version)(void);
 	int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -34,6 +40,7 @@ struct psci_operations {
 	int (*affinity_info)(unsigned long target_affinity,
 			unsigned long lowest_affinity_level);
 	int (*migrate_info_type)(void);
+	enum psci_conduit conduit;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
let's do that at boot time, and expose the version of the calling
convention as part of the psci_ops structure.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/firmware/psci.c | 21 +++++++++++++++++++++
 include/linux/psci.h    |  6 ++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index e9493da2b111..dd035aaa1c33 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
 	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
 }
 
+static void __init psci_init_smccc(u32 ver)
+{
+	int feature = PSCI_RET_NOT_SUPPORTED;
+
+	if (PSCI_VERSION_MAJOR(ver) >= 1)
+		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
+
+	if (feature == PSCI_RET_NOT_SUPPORTED) {
+		psci_ops.variant = SMCCC_VARIANT_1_0;
+	} else {
+		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
+		if (ver != ARM_SMCCC_VERSION_1_1)
+			psci_ops.variant = SMCCC_VARIANT_1_0;
+		else
+			psci_ops.variant = SMCCC_VARIANT_1_1;
+	}
+
+	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
+}
+
 static void __init psci_0_2_set_functions(void)
 {
 	pr_info("Using standard PSCI v0.2 function IDs\n");
@@ -557,6 +577,7 @@ static int __init psci_probe(void)
 	psci_0_2_set_functions();
 
 	psci_init_migrate();
+	psci_init_smccc(ver);
 
 	if (PSCI_VERSION_MAJOR(ver) >= 1) {
 		psci_init_cpu_suspend();
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f2679e5faa4f..83fd16a37be3 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -31,6 +31,11 @@ enum psci_conduit {
 	PSCI_CONDUIT_HVC,
 };
 
+enum smccc_variant {
+	SMCCC_VARIANT_1_0,
+	SMCCC_VARIANT_1_1,
+};
+
 struct psci_operations {
 	u32 (*get_version)(void);
 	int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -41,6 +46,7 @@ struct psci_operations {
 			unsigned long lowest_affinity_level);
 	int (*migrate_info_type)(void);
 	enum psci_conduit conduit;
+	enum smccc_variant variant;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Jon Masters, Robin Murphy,
	Christoffer Dall

Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
let's do that at boot time, and expose the version of the calling
convention as part of the psci_ops structure.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/firmware/psci.c | 21 +++++++++++++++++++++
 include/linux/psci.h    |  6 ++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index e9493da2b111..dd035aaa1c33 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
 	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
 }
 
+static void __init psci_init_smccc(u32 ver)
+{
+	int feature = PSCI_RET_NOT_SUPPORTED;
+
+	if (PSCI_VERSION_MAJOR(ver) >= 1)
+		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
+
+	if (feature == PSCI_RET_NOT_SUPPORTED) {
+		psci_ops.variant = SMCCC_VARIANT_1_0;
+	} else {
+		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
+		if (ver != ARM_SMCCC_VERSION_1_1)
+			psci_ops.variant = SMCCC_VARIANT_1_0;
+		else
+			psci_ops.variant = SMCCC_VARIANT_1_1;
+	}
+
+	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
+}
+
 static void __init psci_0_2_set_functions(void)
 {
 	pr_info("Using standard PSCI v0.2 function IDs\n");
@@ -557,6 +577,7 @@ static int __init psci_probe(void)
 	psci_0_2_set_functions();
 
 	psci_init_migrate();
+	psci_init_smccc(ver);
 
 	if (PSCI_VERSION_MAJOR(ver) >= 1) {
 		psci_init_cpu_suspend();
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f2679e5faa4f..83fd16a37be3 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -31,6 +31,11 @@ enum psci_conduit {
 	PSCI_CONDUIT_HVC,
 };
 
+enum smccc_variant {
+	SMCCC_VARIANT_1_0,
+	SMCCC_VARIANT_1_1,
+};
+
 struct psci_operations {
 	u32 (*get_version)(void);
 	int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -41,6 +46,7 @@ struct psci_operations {
 			unsigned long lowest_affinity_level);
 	int (*migrate_info_type)(void);
 	enum psci_conduit conduit;
+	enum smccc_variant variant;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
let's do that at boot time, and expose the version of the calling
convention as part of the psci_ops structure.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/firmware/psci.c | 21 +++++++++++++++++++++
 include/linux/psci.h    |  6 ++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index e9493da2b111..dd035aaa1c33 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
 	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
 }
 
+static void __init psci_init_smccc(u32 ver)
+{
+	int feature = PSCI_RET_NOT_SUPPORTED;
+
+	if (PSCI_VERSION_MAJOR(ver) >= 1)
+		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
+
+	if (feature == PSCI_RET_NOT_SUPPORTED) {
+		psci_ops.variant = SMCCC_VARIANT_1_0;
+	} else {
+		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
+		if (ver != ARM_SMCCC_VERSION_1_1)
+			psci_ops.variant = SMCCC_VARIANT_1_0;
+		else
+			psci_ops.variant = SMCCC_VARIANT_1_1;
+	}
+
+	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
+}
+
 static void __init psci_0_2_set_functions(void)
 {
 	pr_info("Using standard PSCI v0.2 function IDs\n");
@@ -557,6 +577,7 @@ static int __init psci_probe(void)
 	psci_0_2_set_functions();
 
 	psci_init_migrate();
+	psci_init_smccc(ver);
 
 	if (PSCI_VERSION_MAJOR(ver) >= 1) {
 		psci_init_cpu_suspend();
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f2679e5faa4f..83fd16a37be3 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -31,6 +31,11 @@ enum psci_conduit {
 	PSCI_CONDUIT_HVC,
 };
 
+enum smccc_variant {
+	SMCCC_VARIANT_1_0,
+	SMCCC_VARIANT_1_1,
+};
+
 struct psci_operations {
 	u32 (*get_version)(void);
 	int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -41,6 +46,7 @@ struct psci_operations {
 			unsigned long lowest_affinity_level);
 	int (*migrate_info_type)(void);
 	enum psci_conduit conduit;
+	enum smccc_variant variant;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 14/16] arm/arm64: smccc: Make function identifiers an unsigned quantity
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Function identifiers are a 32bit, unsigned quantity. But we never
tell so to the compiler, resulting in the following:

 4ac:   b26187e0        mov     x0, #0xffffffff80000001

We thus rely on the firmware narrowing it for us, which is not
always a reasonable expectation.

Cc: stable@vger.kernel.org
Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1ef944ef1da..dd44d8458c04 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -14,14 +14,16 @@
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
 
+#include <uapi/linux/const.h>
+
 /*
  * This file provides common defines for ARM SMC Calling Convention as
  * specified in
  * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
  */
 
-#define ARM_SMCCC_STD_CALL		0
-#define ARM_SMCCC_FAST_CALL		1
+#define ARM_SMCCC_STD_CALL	        _AC(0,U)
+#define ARM_SMCCC_FAST_CALL	        _AC(1,U)
 #define ARM_SMCCC_TYPE_SHIFT		31
 
 #define ARM_SMCCC_SMC_32		0
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 14/16] arm/arm64: smccc: Make function identifiers an unsigned quantity
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Jon Masters, Robin Murphy,
	Christoffer Dall

Function identifiers are a 32bit, unsigned quantity. But we never
tell so to the compiler, resulting in the following:

 4ac:   b26187e0        mov     x0, #0xffffffff80000001

We thus rely on the firmware narrowing it for us, which is not
always a reasonable expectation.

Cc: stable@vger.kernel.org
Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1ef944ef1da..dd44d8458c04 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -14,14 +14,16 @@
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
 
+#include <uapi/linux/const.h>
+
 /*
  * This file provides common defines for ARM SMC Calling Convention as
  * specified in
  * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
  */
 
-#define ARM_SMCCC_STD_CALL		0
-#define ARM_SMCCC_FAST_CALL		1
+#define ARM_SMCCC_STD_CALL	        _AC(0,U)
+#define ARM_SMCCC_FAST_CALL	        _AC(1,U)
 #define ARM_SMCCC_TYPE_SHIFT		31
 
 #define ARM_SMCCC_SMC_32		0
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 14/16] arm/arm64: smccc: Make function identifiers an unsigned quantity
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

Function identifiers are a 32bit, unsigned quantity. But we never
tell so to the compiler, resulting in the following:

 4ac:   b26187e0        mov     x0, #0xffffffff80000001

We thus rely on the firmware narrowing it for us, which is not
always a reasonable expectation.

Cc: stable at vger.kernel.org
Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1ef944ef1da..dd44d8458c04 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -14,14 +14,16 @@
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
 
+#include <uapi/linux/const.h>
+
 /*
  * This file provides common defines for ARM SMC Calling Convention as
  * specified in
  * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
  */
 
-#define ARM_SMCCC_STD_CALL		0
-#define ARM_SMCCC_FAST_CALL		1
+#define ARM_SMCCC_STD_CALL	        _AC(0,U)
+#define ARM_SMCCC_FAST_CALL	        _AC(1,U)
 #define ARM_SMCCC_TYPE_SHIFT		31
 
 #define ARM_SMCCC_SMC_32		0
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

One of the major improvement of SMCCC v1.1 is that it only clobbers
the first 4 registers, both on 32 and 64bit. This means that it
becomes very easy to provide an inline version of the SMC call
primitive, and avoid performing a function call to stash the
registers that would otherwise be clobbered by SMCCC v1.0.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 157 insertions(+)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dd44d8458c04..bc5843728909 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 
 #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
 
+/* SMCCC v1.1 implementation madness follows */
+#ifdef CONFIG_ARM64
+
+#define SMCCC_SMC_INST	"smc	#0"
+#define SMCCC_HVC_INST	"hvc	#0"
+
+#define __arm_smccc_1_1_prologue(inst)					\
+	inst "\n"							\
+	"cbz	%[ptr], 1f\n"						\
+	"stp	%x[r0], %x[r1], %[ra0]\n"				\
+	"stp	%x[r2], %x[r3], %[ra2]\n"				\
+	"1:\n"								\
+	: [ra0] "=Ump" (*(&___res->a0)),				\
+	  [ra2] "=Ump" (*(&___res->a2)),
+
+#define __arm_smccc_1_1_epilogue	: "memory"
+		     
+#endif
+
+#ifdef CONFIG_ARM
+#include <asm/opcodes-sec.h>
+#include <asm/opcodes-virt.h>
+
+#define SMCCC_SMC_INST	__SMC(0)
+#define SMCCC_HVC_INST	__HVC(0)
+
+#define __arm_smccc_1_1_prologue(inst)					\
+	inst "\n"							\
+	"cmp	%[ptr], #0\n"						\
+	"stmne	%[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"			\
+	: "=m" (*___res),
+
+#define __arm_smccc_1_1_epilogue	: "memory", "cc"
+		     
+#endif
+
+#define __constraint_write_0						\
+	[r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_1						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_2						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
+#define __constraint_write_3						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
+#define __constraint_write_4	__constraint_write_3
+#define __constraint_write_5	__constraint_write_3
+#define __constraint_write_6	__constraint_write_3
+#define __constraint_write_7	__constraint_write_3
+
+#define __constraint_read_0	: [ptr] "r" (___res)
+#define __constraint_read_1	__constraint_read_0
+#define __constraint_read_2	__constraint_read_0
+#define __constraint_read_3	__constraint_read_0
+#define __constraint_read_4	__constraint_read_3, "r" (r4)
+#define __constraint_read_5	__constraint_read_4, "r" (r5)
+#define __constraint_read_6	__constraint_read_5, "r" (r6)
+#define __constraint_read_7	__constraint_read_6, "r" (r7)
+
+#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
+
+#define __count_args(...)						\
+	___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define __declare_arg_0(a0, res)					\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register unsigned long r1 asm("r1");				\
+	register unsigned long r2 asm("r2");				\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_1(a0, a1, res)					\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register unsigned long r2 asm("r2");				\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_2(a0, a1, a2, res)				\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register typeof(a2)    r2 asm("r2") = a2;			\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_3(a0, a1, a2, a3, res)				\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register typeof(a2)    r2 asm("r2") = a2;			\
+	register typeof(a3)    r3 asm("r3") = a3
+
+#define __declare_arg_4(a0, a1, a2, a3, a4, res)			\
+	__declare_arg_3(a0, a1, a2, a3, res);				\
+	register typeof(a4) r4 asm("r4") = a4
+
+#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)			\
+	__declare_arg_4(a0, a1, a2, a3, a4, res);			\
+	register typeof(a5) r5 asm("r5") = a5
+
+#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)		\
+	__declare_arg_5(a0, a1, a2, a3, a4, a5, res);			\
+	register typeof(a6) r6 asm("r6") = a6
+
+#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)		\
+	__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);		\
+	register typeof(a7) r7 asm("r7") = a7
+
+#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
+#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
+
+#define ___constraint_write(count)  __constraint_write_ ## count
+#define __constraint_write(count)   ___constraint_write(count)
+
+#define ___constraint_read(count)   __constraint_read_ ## count
+#define __constraint_read(count)    ___constraint_read(count)
+
+#define __arm_smccc_1_1(inst, ...)					\
+	do {								\
+		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
+		asm(__arm_smccc_1_1_prologue(inst)			\
+		    __constraint_write(__count_args(__VA_ARGS__))	\
+		    __constraint_read(__count_args(__VA_ARGS__))	\
+		    __arm_smccc_1_1_epilogue);				\
+	} while (0)
+
+/*
+ * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
+ *
+ * This is a variadic macro taking one to eight source arguments, and
+ * an optional return structure.
+ *
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ *
+ * This macro is used to make SMC calls following SMC Calling Convention v1.1.
+ * The content of the supplied param are copied to registers 0 to 7 prior
+ * to the SMC instruction. The return values are updated with the content
+ * from register 0 to 3 on return from the SMC instruction if not NULL.
+ */
+#define arm_smccc_1_1_smc(...)	__arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
+
+/*
+ * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
+ *
+ * This is a variadic macro taking one to eight source arguments, and
+ * an optional return structure.
+ *
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ *
+ * This macro is used to make HVC calls following SMC Calling Convention v1.1.
+ * The content of the supplied param are copied to registers 0 to 7 prior
+ * to the HVC instruction. The return values are updated with the content
+ * from register 0 to 3 on return from the HVC instruction if not NULL.
+ */
+#define arm_smccc_1_1_hvc(...)	__arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
+
 #endif /*__ASSEMBLY__*/
 #endif /*__LINUX_ARM_SMCCC_H*/
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Lorenzo Pieralisi, Ard Biesheuvel, Catalin Marinas, Will Deacon,
	Jon Masters, Robin Murphy

One of the major improvement of SMCCC v1.1 is that it only clobbers
the first 4 registers, both on 32 and 64bit. This means that it
becomes very easy to provide an inline version of the SMC call
primitive, and avoid performing a function call to stash the
registers that would otherwise be clobbered by SMCCC v1.0.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 157 insertions(+)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dd44d8458c04..bc5843728909 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 
 #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
 
+/* SMCCC v1.1 implementation madness follows */
+#ifdef CONFIG_ARM64
+
+#define SMCCC_SMC_INST	"smc	#0"
+#define SMCCC_HVC_INST	"hvc	#0"
+
+#define __arm_smccc_1_1_prologue(inst)					\
+	inst "\n"							\
+	"cbz	%[ptr], 1f\n"						\
+	"stp	%x[r0], %x[r1], %[ra0]\n"				\
+	"stp	%x[r2], %x[r3], %[ra2]\n"				\
+	"1:\n"								\
+	: [ra0] "=Ump" (*(&___res->a0)),				\
+	  [ra2] "=Ump" (*(&___res->a2)),
+
+#define __arm_smccc_1_1_epilogue	: "memory"
+		     
+#endif
+
+#ifdef CONFIG_ARM
+#include <asm/opcodes-sec.h>
+#include <asm/opcodes-virt.h>
+
+#define SMCCC_SMC_INST	__SMC(0)
+#define SMCCC_HVC_INST	__HVC(0)
+
+#define __arm_smccc_1_1_prologue(inst)					\
+	inst "\n"							\
+	"cmp	%[ptr], #0\n"						\
+	"stmne	%[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"			\
+	: "=m" (*___res),
+
+#define __arm_smccc_1_1_epilogue	: "memory", "cc"
+		     
+#endif
+
+#define __constraint_write_0						\
+	[r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_1						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_2						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
+#define __constraint_write_3						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
+#define __constraint_write_4	__constraint_write_3
+#define __constraint_write_5	__constraint_write_3
+#define __constraint_write_6	__constraint_write_3
+#define __constraint_write_7	__constraint_write_3
+
+#define __constraint_read_0	: [ptr] "r" (___res)
+#define __constraint_read_1	__constraint_read_0
+#define __constraint_read_2	__constraint_read_0
+#define __constraint_read_3	__constraint_read_0
+#define __constraint_read_4	__constraint_read_3, "r" (r4)
+#define __constraint_read_5	__constraint_read_4, "r" (r5)
+#define __constraint_read_6	__constraint_read_5, "r" (r6)
+#define __constraint_read_7	__constraint_read_6, "r" (r7)
+
+#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
+
+#define __count_args(...)						\
+	___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define __declare_arg_0(a0, res)					\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register unsigned long r1 asm("r1");				\
+	register unsigned long r2 asm("r2");				\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_1(a0, a1, res)					\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register unsigned long r2 asm("r2");				\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_2(a0, a1, a2, res)				\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register typeof(a2)    r2 asm("r2") = a2;			\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_3(a0, a1, a2, a3, res)				\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register typeof(a2)    r2 asm("r2") = a2;			\
+	register typeof(a3)    r3 asm("r3") = a3
+
+#define __declare_arg_4(a0, a1, a2, a3, a4, res)			\
+	__declare_arg_3(a0, a1, a2, a3, res);				\
+	register typeof(a4) r4 asm("r4") = a4
+
+#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)			\
+	__declare_arg_4(a0, a1, a2, a3, a4, res);			\
+	register typeof(a5) r5 asm("r5") = a5
+
+#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)		\
+	__declare_arg_5(a0, a1, a2, a3, a4, a5, res);			\
+	register typeof(a6) r6 asm("r6") = a6
+
+#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)		\
+	__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);		\
+	register typeof(a7) r7 asm("r7") = a7
+
+#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
+#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
+
+#define ___constraint_write(count)  __constraint_write_ ## count
+#define __constraint_write(count)   ___constraint_write(count)
+
+#define ___constraint_read(count)   __constraint_read_ ## count
+#define __constraint_read(count)    ___constraint_read(count)
+
+#define __arm_smccc_1_1(inst, ...)					\
+	do {								\
+		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
+		asm(__arm_smccc_1_1_prologue(inst)			\
+		    __constraint_write(__count_args(__VA_ARGS__))	\
+		    __constraint_read(__count_args(__VA_ARGS__))	\
+		    __arm_smccc_1_1_epilogue);				\
+	} while (0)
+
+/*
+ * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
+ *
+ * This is a variadic macro taking one to eight source arguments, and
+ * an optional return structure.
+ *
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ *
+ * This macro is used to make SMC calls following SMC Calling Convention v1.1.
+ * The content of the supplied param are copied to registers 0 to 7 prior
+ * to the SMC instruction. The return values are updated with the content
+ * from register 0 to 3 on return from the SMC instruction if not NULL.
+ */
+#define arm_smccc_1_1_smc(...)	__arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
+
+/*
+ * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
+ *
+ * This is a variadic macro taking one to eight source arguments, and
+ * an optional return structure.
+ *
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ *
+ * This macro is used to make HVC calls following SMC Calling Convention v1.1.
+ * The content of the supplied param are copied to registers 0 to 7 prior
+ * to the HVC instruction. The return values are updated with the content
+ * from register 0 to 3 on return from the HVC instruction if not NULL.
+ */
+#define arm_smccc_1_1_hvc(...)	__arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
+
 #endif /*__ASSEMBLY__*/
 #endif /*__LINUX_ARM_SMCCC_H*/
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

One of the major improvement of SMCCC v1.1 is that it only clobbers
the first 4 registers, both on 32 and 64bit. This means that it
becomes very easy to provide an inline version of the SMC call
primitive, and avoid performing a function call to stash the
registers that would otherwise be clobbered by SMCCC v1.0.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 157 insertions(+)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dd44d8458c04..bc5843728909 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 
 #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
 
+/* SMCCC v1.1 implementation madness follows */
+#ifdef CONFIG_ARM64
+
+#define SMCCC_SMC_INST	"smc	#0"
+#define SMCCC_HVC_INST	"hvc	#0"
+
+#define __arm_smccc_1_1_prologue(inst)					\
+	inst "\n"							\
+	"cbz	%[ptr], 1f\n"						\
+	"stp	%x[r0], %x[r1], %[ra0]\n"				\
+	"stp	%x[r2], %x[r3], %[ra2]\n"				\
+	"1:\n"								\
+	: [ra0] "=Ump" (*(&___res->a0)),				\
+	  [ra2] "=Ump" (*(&___res->a2)),
+
+#define __arm_smccc_1_1_epilogue	: "memory"
+		     
+#endif
+
+#ifdef CONFIG_ARM
+#include <asm/opcodes-sec.h>
+#include <asm/opcodes-virt.h>
+
+#define SMCCC_SMC_INST	__SMC(0)
+#define SMCCC_HVC_INST	__HVC(0)
+
+#define __arm_smccc_1_1_prologue(inst)					\
+	inst "\n"							\
+	"cmp	%[ptr], #0\n"						\
+	"stmne	%[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"			\
+	: "=m" (*___res),
+
+#define __arm_smccc_1_1_epilogue	: "memory", "cc"
+		     
+#endif
+
+#define __constraint_write_0						\
+	[r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_1						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_2						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
+#define __constraint_write_3						\
+	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
+#define __constraint_write_4	__constraint_write_3
+#define __constraint_write_5	__constraint_write_3
+#define __constraint_write_6	__constraint_write_3
+#define __constraint_write_7	__constraint_write_3
+
+#define __constraint_read_0	: [ptr] "r" (___res)
+#define __constraint_read_1	__constraint_read_0
+#define __constraint_read_2	__constraint_read_0
+#define __constraint_read_3	__constraint_read_0
+#define __constraint_read_4	__constraint_read_3, "r" (r4)
+#define __constraint_read_5	__constraint_read_4, "r" (r5)
+#define __constraint_read_6	__constraint_read_5, "r" (r6)
+#define __constraint_read_7	__constraint_read_6, "r" (r7)
+
+#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
+
+#define __count_args(...)						\
+	___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define __declare_arg_0(a0, res)					\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register unsigned long r1 asm("r1");				\
+	register unsigned long r2 asm("r2");				\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_1(a0, a1, res)					\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register unsigned long r2 asm("r2");				\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_2(a0, a1, a2, res)				\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register typeof(a2)    r2 asm("r2") = a2;			\
+	register unsigned long r3 asm("r3")
+
+#define __declare_arg_3(a0, a1, a2, a3, res)				\
+	struct arm_smccc_res   *___res = res;				\
+	register u32           r0 asm("r0") = a0;			\
+	register typeof(a1)    r1 asm("r1") = a1;			\
+	register typeof(a2)    r2 asm("r2") = a2;			\
+	register typeof(a3)    r3 asm("r3") = a3
+
+#define __declare_arg_4(a0, a1, a2, a3, a4, res)			\
+	__declare_arg_3(a0, a1, a2, a3, res);				\
+	register typeof(a4) r4 asm("r4") = a4
+
+#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)			\
+	__declare_arg_4(a0, a1, a2, a3, a4, res);			\
+	register typeof(a5) r5 asm("r5") = a5
+
+#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)		\
+	__declare_arg_5(a0, a1, a2, a3, a4, a5, res);			\
+	register typeof(a6) r6 asm("r6") = a6
+
+#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)		\
+	__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);		\
+	register typeof(a7) r7 asm("r7") = a7
+
+#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
+#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
+
+#define ___constraint_write(count)  __constraint_write_ ## count
+#define __constraint_write(count)   ___constraint_write(count)
+
+#define ___constraint_read(count)   __constraint_read_ ## count
+#define __constraint_read(count)    ___constraint_read(count)
+
+#define __arm_smccc_1_1(inst, ...)					\
+	do {								\
+		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
+		asm(__arm_smccc_1_1_prologue(inst)			\
+		    __constraint_write(__count_args(__VA_ARGS__))	\
+		    __constraint_read(__count_args(__VA_ARGS__))	\
+		    __arm_smccc_1_1_epilogue);				\
+	} while (0)
+
+/*
+ * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
+ *
+ * This is a variadic macro taking one to eight source arguments, and
+ * an optional return structure.
+ *
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ *
+ * This macro is used to make SMC calls following SMC Calling Convention v1.1.
+ * The content of the supplied param are copied to registers 0 to 7 prior
+ * to the SMC instruction. The return values are updated with the content
+ * from register 0 to 3 on return from the SMC instruction if not NULL.
+ */
+#define arm_smccc_1_1_smc(...)	__arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
+
+/*
+ * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
+ *
+ * This is a variadic macro taking one to eight source arguments, and
+ * an optional return structure.
+ *
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ *
+ * This macro is used to make HVC calls following SMC Calling Convention v1.1.
+ * The content of the supplied param are copied to registers 0 to 7 prior
+ * to the HVC instruction. The return values are updated with the content
+ * from register 0 to 3 on return from the HVC instruction if not NULL.
+ */
+#define arm_smccc_1_1_hvc(...)	__arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
+
 #endif /*__ASSEMBLY__*/
 #endif /*__LINUX_ARM_SMCCC_H*/
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-29 17:45 ` Marc Zyngier
  (?)
@ 2018-01-29 17:45   ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
It is lovely. Really.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_psci.h | 63 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/bpi.S           | 20 ++++++++++++
 arch/arm64/kernel/cpu_errata.c    | 68 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/kvm_psci.h

diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
new file mode 100644
index 000000000000..f553e3795a4e
--- /dev/null
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_KVM_PSCI_H__
+#define __ARM64_KVM_PSCI_H__
+
+#include <linux/kvm_host.h>
+
+#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
+#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0	PSCI_VERSION(1, 0)
+
+#define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
+
+/*
+ * We need the KVM pointer independently from the vcpu as we can call
+ * this from HYP, and need to apply kern_hyp_va on it...
+ */
+static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+	/*
+	 * Our PSCI implementation stays the same across versions from
+	 * v0.2 onward, only adding the few mandatory functions (such
+	 * as FEATURES with 1.0) that are required by newer
+	 * revisions. It is thus safe to return the latest, unless
+	 * userspace has instructed us otherwise.
+	 */
+	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		if (kvm->arch.psci_version)
+			return kvm->arch.psci_version;
+
+		return KVM_ARM_PSCI_LATEST;
+	}
+
+	return KVM_ARM_PSCI_0_1;
+}
+
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+
+struct kvm_one_reg;
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+
+#endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
index 76225c2611ea..fdeed629f2c6 100644
--- a/arch/arm64/kernel/bpi.S
+++ b/arch/arm64/kernel/bpi.S
@@ -17,6 +17,7 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/arm-smccc.h>
 
 .macro ventry target
 	.rept 31
@@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
 	.endr
 	ldp	x29, x30, [sp], #16
 ENTRY(__qcom_hyp_sanitize_link_stack_end)
+
+.macro smccc_workaround_1 inst
+	sub	sp, sp, #(8 * 4)
+	stp	x2, x3, [sp, #(8 * 0)]
+	stp	x0, x1, [sp, #(8 * 2)]
+	mov	w0, #ARM_SMCCC_ARCH_WORKAROUND_1
+	\inst	#0
+	ldp	x2, x3, [sp, #(8 * 0)]
+	ldp	x0, x1, [sp, #(8 * 2)]
+	add	sp, sp, #(8 * 4)
+.endm
+
+ENTRY(__smccc_workaround_1_smc_start)
+	smccc_workaround_1	smc
+ENTRY(__smccc_workaround_1_smc_end)
+
+ENTRY(__smccc_workaround_1_hvc_start)
+	smccc_workaround_1	hvc
+ENTRY(__smccc_workaround_1_hvc_end)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index ed6881882231..36cff870d5d7 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
 extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
 extern char __qcom_hyp_sanitize_link_stack_start[];
 extern char __qcom_hyp_sanitize_link_stack_end[];
+extern char __smccc_workaround_1_smc_start[];
+extern char __smccc_workaround_1_smc_end[];
+extern char __smccc_workaround_1_hvc_start[];
+extern char __smccc_workaround_1_hvc_end[];
 
 static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
 				const char *hyp_vecs_end)
@@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 #define __psci_hyp_bp_inval_end			NULL
 #define __qcom_hyp_sanitize_link_stack_start	NULL
 #define __qcom_hyp_sanitize_link_stack_end	NULL
+#define __smccc_workaround_1_smc_start		NULL
+#define __smccc_workaround_1_smc_end		NULL
+#define __smccc_workaround_1_hvc_start		NULL
+#define __smccc_workaround_1_hvc_end		NULL
 
 static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 				      const char *hyp_vecs_start,
@@ -142,17 +150,75 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
 	__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
 }
 
+#include <uapi/linux/psci.h>
+#include <linux/arm-smccc.h>
 #include <linux/psci.h>
 
+static void call_smc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+
+static void call_hvc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+
+static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
+{
+	bp_hardening_cb_t cb;
+	void *smccc_start, *smccc_end;
+	struct arm_smccc_res res;
+
+	if (!entry->matches(entry, SCOPE_LOCAL_CPU))
+		return false;
+
+	if (psci_ops.variant == SMCCC_VARIANT_1_0)
+		return false;
+
+	switch (psci_ops.conduit) {
+	case PSCI_CONDUIT_HVC:
+		arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+		if (res.a0)
+			return false;
+		cb = call_hvc_arch_workaround_1;
+		smccc_start = __smccc_workaround_1_hvc_start;
+		smccc_end = __smccc_workaround_1_hvc_end;
+		break;
+
+	case PSCI_CONDUIT_SMC:
+		arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+		if (res.a0)
+			return false;
+		cb = call_smc_arch_workaround_1;
+		smccc_start = __smccc_workaround_1_smc_start;
+		smccc_end = __smccc_workaround_1_smc_end;
+		break;
+
+	default:
+		return false;
+	}
+
+	install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
+
+	return true;
+}
+
 static int enable_psci_bp_hardening(void *data)
 {
 	const struct arm64_cpu_capabilities *entry = data;
 
-	if (psci_ops.get_version)
+	if (psci_ops.get_version) {
+		if (check_smccc_arch_workaround_1(entry))
+			return 0;
+
 		install_bp_hardening_cb(entry,
 				       (bp_hardening_cb_t)psci_ops.get_version,
 				       __psci_hyp_bp_inval_start,
 				       __psci_hyp_bp_inval_end);
+	}
 
 	return 0;
 }
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: Lorenzo Pieralisi, Ard Biesheuvel, Catalin Marinas, Will Deacon,
	Jon Masters, Robin Murphy

Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
It is lovely. Really.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_psci.h | 63 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/bpi.S           | 20 ++++++++++++
 arch/arm64/kernel/cpu_errata.c    | 68 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/kvm_psci.h

diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
new file mode 100644
index 000000000000..f553e3795a4e
--- /dev/null
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_KVM_PSCI_H__
+#define __ARM64_KVM_PSCI_H__
+
+#include <linux/kvm_host.h>
+
+#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
+#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0	PSCI_VERSION(1, 0)
+
+#define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
+
+/*
+ * We need the KVM pointer independently from the vcpu as we can call
+ * this from HYP, and need to apply kern_hyp_va on it...
+ */
+static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+	/*
+	 * Our PSCI implementation stays the same across versions from
+	 * v0.2 onward, only adding the few mandatory functions (such
+	 * as FEATURES with 1.0) that are required by newer
+	 * revisions. It is thus safe to return the latest, unless
+	 * userspace has instructed us otherwise.
+	 */
+	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		if (kvm->arch.psci_version)
+			return kvm->arch.psci_version;
+
+		return KVM_ARM_PSCI_LATEST;
+	}
+
+	return KVM_ARM_PSCI_0_1;
+}
+
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+
+struct kvm_one_reg;
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+
+#endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
index 76225c2611ea..fdeed629f2c6 100644
--- a/arch/arm64/kernel/bpi.S
+++ b/arch/arm64/kernel/bpi.S
@@ -17,6 +17,7 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/arm-smccc.h>
 
 .macro ventry target
 	.rept 31
@@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
 	.endr
 	ldp	x29, x30, [sp], #16
 ENTRY(__qcom_hyp_sanitize_link_stack_end)
+
+.macro smccc_workaround_1 inst
+	sub	sp, sp, #(8 * 4)
+	stp	x2, x3, [sp, #(8 * 0)]
+	stp	x0, x1, [sp, #(8 * 2)]
+	mov	w0, #ARM_SMCCC_ARCH_WORKAROUND_1
+	\inst	#0
+	ldp	x2, x3, [sp, #(8 * 0)]
+	ldp	x0, x1, [sp, #(8 * 2)]
+	add	sp, sp, #(8 * 4)
+.endm
+
+ENTRY(__smccc_workaround_1_smc_start)
+	smccc_workaround_1	smc
+ENTRY(__smccc_workaround_1_smc_end)
+
+ENTRY(__smccc_workaround_1_hvc_start)
+	smccc_workaround_1	hvc
+ENTRY(__smccc_workaround_1_hvc_end)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index ed6881882231..36cff870d5d7 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
 extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
 extern char __qcom_hyp_sanitize_link_stack_start[];
 extern char __qcom_hyp_sanitize_link_stack_end[];
+extern char __smccc_workaround_1_smc_start[];
+extern char __smccc_workaround_1_smc_end[];
+extern char __smccc_workaround_1_hvc_start[];
+extern char __smccc_workaround_1_hvc_end[];
 
 static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
 				const char *hyp_vecs_end)
@@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 #define __psci_hyp_bp_inval_end			NULL
 #define __qcom_hyp_sanitize_link_stack_start	NULL
 #define __qcom_hyp_sanitize_link_stack_end	NULL
+#define __smccc_workaround_1_smc_start		NULL
+#define __smccc_workaround_1_smc_end		NULL
+#define __smccc_workaround_1_hvc_start		NULL
+#define __smccc_workaround_1_hvc_end		NULL
 
 static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 				      const char *hyp_vecs_start,
@@ -142,17 +150,75 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
 	__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
 }
 
+#include <uapi/linux/psci.h>
+#include <linux/arm-smccc.h>
 #include <linux/psci.h>
 
+static void call_smc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+
+static void call_hvc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+
+static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
+{
+	bp_hardening_cb_t cb;
+	void *smccc_start, *smccc_end;
+	struct arm_smccc_res res;
+
+	if (!entry->matches(entry, SCOPE_LOCAL_CPU))
+		return false;
+
+	if (psci_ops.variant == SMCCC_VARIANT_1_0)
+		return false;
+
+	switch (psci_ops.conduit) {
+	case PSCI_CONDUIT_HVC:
+		arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+		if (res.a0)
+			return false;
+		cb = call_hvc_arch_workaround_1;
+		smccc_start = __smccc_workaround_1_hvc_start;
+		smccc_end = __smccc_workaround_1_hvc_end;
+		break;
+
+	case PSCI_CONDUIT_SMC:
+		arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+		if (res.a0)
+			return false;
+		cb = call_smc_arch_workaround_1;
+		smccc_start = __smccc_workaround_1_smc_start;
+		smccc_end = __smccc_workaround_1_smc_end;
+		break;
+
+	default:
+		return false;
+	}
+
+	install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
+
+	return true;
+}
+
 static int enable_psci_bp_hardening(void *data)
 {
 	const struct arm64_cpu_capabilities *entry = data;
 
-	if (psci_ops.get_version)
+	if (psci_ops.get_version) {
+		if (check_smccc_arch_workaround_1(entry))
+			return 0;
+
 		install_bp_hardening_cb(entry,
 				       (bp_hardening_cb_t)psci_ops.get_version,
 				       __psci_hyp_bp_inval_start,
 				       __psci_hyp_bp_inval_end);
+	}
 
 	return 0;
 }
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-29 17:45   ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-29 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
It is lovely. Really.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_psci.h | 63 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/bpi.S           | 20 ++++++++++++
 arch/arm64/kernel/cpu_errata.c    | 68 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/kvm_psci.h

diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
new file mode 100644
index 000000000000..f553e3795a4e
--- /dev/null
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_KVM_PSCI_H__
+#define __ARM64_KVM_PSCI_H__
+
+#include <linux/kvm_host.h>
+
+#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
+#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0	PSCI_VERSION(1, 0)
+
+#define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
+
+/*
+ * We need the KVM pointer independently from the vcpu as we can call
+ * this from HYP, and need to apply kern_hyp_va on it...
+ */
+static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+	/*
+	 * Our PSCI implementation stays the same across versions from
+	 * v0.2 onward, only adding the few mandatory functions (such
+	 * as FEATURES with 1.0) that are required by newer
+	 * revisions. It is thus safe to return the latest, unless
+	 * userspace has instructed us otherwise.
+	 */
+	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+		if (kvm->arch.psci_version)
+			return kvm->arch.psci_version;
+
+		return KVM_ARM_PSCI_LATEST;
+	}
+
+	return KVM_ARM_PSCI_0_1;
+}
+
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+
+struct kvm_one_reg;
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+
+#endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
index 76225c2611ea..fdeed629f2c6 100644
--- a/arch/arm64/kernel/bpi.S
+++ b/arch/arm64/kernel/bpi.S
@@ -17,6 +17,7 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/arm-smccc.h>
 
 .macro ventry target
 	.rept 31
@@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
 	.endr
 	ldp	x29, x30, [sp], #16
 ENTRY(__qcom_hyp_sanitize_link_stack_end)
+
+.macro smccc_workaround_1 inst
+	sub	sp, sp, #(8 * 4)
+	stp	x2, x3, [sp, #(8 * 0)]
+	stp	x0, x1, [sp, #(8 * 2)]
+	mov	w0, #ARM_SMCCC_ARCH_WORKAROUND_1
+	\inst	#0
+	ldp	x2, x3, [sp, #(8 * 0)]
+	ldp	x0, x1, [sp, #(8 * 2)]
+	add	sp, sp, #(8 * 4)
+.endm
+
+ENTRY(__smccc_workaround_1_smc_start)
+	smccc_workaround_1	smc
+ENTRY(__smccc_workaround_1_smc_end)
+
+ENTRY(__smccc_workaround_1_hvc_start)
+	smccc_workaround_1	hvc
+ENTRY(__smccc_workaround_1_hvc_end)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index ed6881882231..36cff870d5d7 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
 extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
 extern char __qcom_hyp_sanitize_link_stack_start[];
 extern char __qcom_hyp_sanitize_link_stack_end[];
+extern char __smccc_workaround_1_smc_start[];
+extern char __smccc_workaround_1_smc_end[];
+extern char __smccc_workaround_1_hvc_start[];
+extern char __smccc_workaround_1_hvc_end[];
 
 static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
 				const char *hyp_vecs_end)
@@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 #define __psci_hyp_bp_inval_end			NULL
 #define __qcom_hyp_sanitize_link_stack_start	NULL
 #define __qcom_hyp_sanitize_link_stack_end	NULL
+#define __smccc_workaround_1_smc_start		NULL
+#define __smccc_workaround_1_smc_end		NULL
+#define __smccc_workaround_1_hvc_start		NULL
+#define __smccc_workaround_1_hvc_end		NULL
 
 static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 				      const char *hyp_vecs_start,
@@ -142,17 +150,75 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
 	__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
 }
 
+#include <uapi/linux/psci.h>
+#include <linux/arm-smccc.h>
 #include <linux/psci.h>
 
+static void call_smc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+
+static void call_hvc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+
+static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
+{
+	bp_hardening_cb_t cb;
+	void *smccc_start, *smccc_end;
+	struct arm_smccc_res res;
+
+	if (!entry->matches(entry, SCOPE_LOCAL_CPU))
+		return false;
+
+	if (psci_ops.variant == SMCCC_VARIANT_1_0)
+		return false;
+
+	switch (psci_ops.conduit) {
+	case PSCI_CONDUIT_HVC:
+		arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+		if (res.a0)
+			return false;
+		cb = call_hvc_arch_workaround_1;
+		smccc_start = __smccc_workaround_1_hvc_start;
+		smccc_end = __smccc_workaround_1_hvc_end;
+		break;
+
+	case PSCI_CONDUIT_SMC:
+		arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+		if (res.a0)
+			return false;
+		cb = call_smc_arch_workaround_1;
+		smccc_start = __smccc_workaround_1_smc_start;
+		smccc_end = __smccc_workaround_1_smc_end;
+		break;
+
+	default:
+		return false;
+	}
+
+	install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
+
+	return true;
+}
+
 static int enable_psci_bp_hardening(void *data)
 {
 	const struct arm64_cpu_capabilities *entry = data;
 
-	if (psci_ops.get_version)
+	if (psci_ops.get_version) {
+		if (check_smccc_arch_workaround_1(entry))
+			return 0;
+
 		install_bp_hardening_cb(entry,
 				       (bp_hardening_cb_t)psci_ops.get_version,
 				       __psci_hyp_bp_inval_start,
 				       __psci_hyp_bp_inval_end);
+	}
 
 	return 0;
 }
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 12/16] firmware/psci: Expose PSCI conduit
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-29 17:55     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 116+ messages in thread
From: Lorenzo Pieralisi @ 2018-01-29 17:55 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Catalin Marinas,
	Will Deacon, Peter Maydell, Christoffer Dall, Mark Rutland,
	Robin Murphy, Ard Biesheuvel, Jon Masters

On Mon, Jan 29, 2018 at 05:45:55PM +0000, Marc Zyngier wrote:
> In order to call into the firmware to apply workarounds, it is
> useful to find out whether we're using HVC or SMC. Let's expose
> this through the psci_ops.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  drivers/firmware/psci.c | 28 +++++++++++++++++++++++-----
>  include/linux/psci.h    |  7 +++++++
>  2 files changed, 30 insertions(+), 5 deletions(-)

Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 8b25d31e8401..e9493da2b111 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
>  	return cpu == resident_cpu;
>  }
>  
> -struct psci_operations psci_ops;
> +struct psci_operations psci_ops = {
> +	.conduit = PSCI_CONDUIT_NONE,
> +};
>  
>  typedef unsigned long (psci_fn)(unsigned long, unsigned long,
>  				unsigned long, unsigned long);
> @@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
>  			      0, 0, 0);
>  }
>  
> +static void set_conduit(enum psci_conduit conduit)
> +{
> +	switch (conduit) {
> +	case PSCI_CONDUIT_HVC:
> +		invoke_psci_fn = __invoke_psci_fn_hvc;
> +		break;
> +	case PSCI_CONDUIT_SMC:
> +		invoke_psci_fn = __invoke_psci_fn_smc;
> +		break;
> +	default:
> +		WARN(1, "Unexpected PSCI conduit %d\n", conduit);
> +	}
> +
> +	psci_ops.conduit = conduit;
> +}
> +
>  static int get_set_conduit_method(struct device_node *np)
>  {
>  	const char *method;
> @@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
>  	}
>  
>  	if (!strcmp("hvc", method)) {
> -		invoke_psci_fn = __invoke_psci_fn_hvc;
> +		set_conduit(PSCI_CONDUIT_HVC);
>  	} else if (!strcmp("smc", method)) {
> -		invoke_psci_fn = __invoke_psci_fn_smc;
> +		set_conduit(PSCI_CONDUIT_SMC);
>  	} else {
>  		pr_warn("invalid \"method\" property: %s\n", method);
>  		return -EINVAL;
> @@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
>  	pr_info("probing for conduit method from ACPI.\n");
>  
>  	if (acpi_psci_use_hvc())
> -		invoke_psci_fn = __invoke_psci_fn_hvc;
> +		set_conduit(PSCI_CONDUIT_HVC);
>  	else
> -		invoke_psci_fn = __invoke_psci_fn_smc;
> +		set_conduit(PSCI_CONDUIT_SMC);
>  
>  	return psci_probe();
>  }
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f724fd8c78e8..f2679e5faa4f 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
>  int psci_cpu_init_idle(unsigned int cpu);
>  int psci_cpu_suspend_enter(unsigned long index);
>  
> +enum psci_conduit {
> +	PSCI_CONDUIT_NONE,
> +	PSCI_CONDUIT_SMC,
> +	PSCI_CONDUIT_HVC,
> +};
> +
>  struct psci_operations {
>  	u32 (*get_version)(void);
>  	int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -34,6 +40,7 @@ struct psci_operations {
>  	int (*affinity_info)(unsigned long target_affinity,
>  			unsigned long lowest_affinity_level);
>  	int (*migrate_info_type)(void);
> +	enum psci_conduit conduit;
>  };
>  
>  extern struct psci_operations psci_ops;
> -- 
> 2.14.2
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 12/16] firmware/psci: Expose PSCI conduit
@ 2018-01-29 17:55     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 116+ messages in thread
From: Lorenzo Pieralisi @ 2018-01-29 17:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 29, 2018 at 05:45:55PM +0000, Marc Zyngier wrote:
> In order to call into the firmware to apply workarounds, it is
> useful to find out whether we're using HVC or SMC. Let's expose
> this through the psci_ops.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  drivers/firmware/psci.c | 28 +++++++++++++++++++++++-----
>  include/linux/psci.h    |  7 +++++++
>  2 files changed, 30 insertions(+), 5 deletions(-)

Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 8b25d31e8401..e9493da2b111 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
>  	return cpu == resident_cpu;
>  }
>  
> -struct psci_operations psci_ops;
> +struct psci_operations psci_ops = {
> +	.conduit = PSCI_CONDUIT_NONE,
> +};
>  
>  typedef unsigned long (psci_fn)(unsigned long, unsigned long,
>  				unsigned long, unsigned long);
> @@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
>  			      0, 0, 0);
>  }
>  
> +static void set_conduit(enum psci_conduit conduit)
> +{
> +	switch (conduit) {
> +	case PSCI_CONDUIT_HVC:
> +		invoke_psci_fn = __invoke_psci_fn_hvc;
> +		break;
> +	case PSCI_CONDUIT_SMC:
> +		invoke_psci_fn = __invoke_psci_fn_smc;
> +		break;
> +	default:
> +		WARN(1, "Unexpected PSCI conduit %d\n", conduit);
> +	}
> +
> +	psci_ops.conduit = conduit;
> +}
> +
>  static int get_set_conduit_method(struct device_node *np)
>  {
>  	const char *method;
> @@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
>  	}
>  
>  	if (!strcmp("hvc", method)) {
> -		invoke_psci_fn = __invoke_psci_fn_hvc;
> +		set_conduit(PSCI_CONDUIT_HVC);
>  	} else if (!strcmp("smc", method)) {
> -		invoke_psci_fn = __invoke_psci_fn_smc;
> +		set_conduit(PSCI_CONDUIT_SMC);
>  	} else {
>  		pr_warn("invalid \"method\" property: %s\n", method);
>  		return -EINVAL;
> @@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
>  	pr_info("probing for conduit method from ACPI.\n");
>  
>  	if (acpi_psci_use_hvc())
> -		invoke_psci_fn = __invoke_psci_fn_hvc;
> +		set_conduit(PSCI_CONDUIT_HVC);
>  	else
> -		invoke_psci_fn = __invoke_psci_fn_smc;
> +		set_conduit(PSCI_CONDUIT_SMC);
>  
>  	return psci_probe();
>  }
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f724fd8c78e8..f2679e5faa4f 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
>  int psci_cpu_init_idle(unsigned int cpu);
>  int psci_cpu_suspend_enter(unsigned long index);
>  
> +enum psci_conduit {
> +	PSCI_CONDUIT_NONE,
> +	PSCI_CONDUIT_SMC,
> +	PSCI_CONDUIT_HVC,
> +};
> +
>  struct psci_operations {
>  	u32 (*get_version)(void);
>  	int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -34,6 +40,7 @@ struct psci_operations {
>  	int (*affinity_info)(unsigned long target_affinity,
>  			unsigned long lowest_affinity_level);
>  	int (*migrate_info_type)(void);
> +	enum psci_conduit conduit;
>  };
>  
>  extern struct psci_operations psci_ops;
> -- 
> 2.14.2
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-29 18:39     ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 116+ messages in thread
From: Lorenzo Pieralisi @ 2018-01-29 18:39 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Catalin Marinas,
	Will Deacon, Peter Maydell, Christoffer Dall, Mark Rutland,
	Robin Murphy, Ard Biesheuvel, Jon Masters

On Mon, Jan 29, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
> let's do that at boot time, and expose the version of the calling
> convention as part of the psci_ops structure.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  drivers/firmware/psci.c | 21 +++++++++++++++++++++
>  include/linux/psci.h    |  6 ++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index e9493da2b111..dd035aaa1c33 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>  	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>  }
>  
> +static void __init psci_init_smccc(u32 ver)
> +{
> +	int feature = PSCI_RET_NOT_SUPPORTED;
> +
> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
> +
> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
> +		psci_ops.variant = SMCCC_VARIANT_1_0;
> +	} else {
> +		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
> +		if (ver != ARM_SMCCC_VERSION_1_1)
> +			psci_ops.variant = SMCCC_VARIANT_1_0;
> +		else
> +			psci_ops.variant = SMCCC_VARIANT_1_1;
> +	}
> +
> +	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
> +}
> +
>  static void __init psci_0_2_set_functions(void)
>  {
>  	pr_info("Using standard PSCI v0.2 function IDs\n");
> @@ -557,6 +577,7 @@ static int __init psci_probe(void)
>  	psci_0_2_set_functions();
>  
>  	psci_init_migrate();
> +	psci_init_smccc(ver);

Given that SMCCC_VARIANT_1_0 is already the default value (unless you do
the same we did with the conduit) we can move psci_init_smccc() call
inside the if below (that is there to detect a callable psci_features())
and remove the check in psci_init_smccc(), up to you.

>  
>  	if (PSCI_VERSION_MAJOR(ver) >= 1) {
>  		psci_init_cpu_suspend();
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f2679e5faa4f..83fd16a37be3 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -31,6 +31,11 @@ enum psci_conduit {
>  	PSCI_CONDUIT_HVC,
>  };
>  
> +enum smccc_variant {
> +	SMCCC_VARIANT_1_0,
> +	SMCCC_VARIANT_1_1,
> +};
> +
>  struct psci_operations {
>  	u32 (*get_version)(void);
>  	int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -41,6 +46,7 @@ struct psci_operations {
>  			unsigned long lowest_affinity_level);
>  	int (*migrate_info_type)(void);
>  	enum psci_conduit conduit;
> +	enum smccc_variant variant;

Nit: I would add an smccc_ prefix to the variant field (or rename it
to smccc_version).

You can add my:

Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
@ 2018-01-29 18:39     ` Lorenzo Pieralisi
  0 siblings, 0 replies; 116+ messages in thread
From: Lorenzo Pieralisi @ 2018-01-29 18:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 29, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
> let's do that at boot time, and expose the version of the calling
> convention as part of the psci_ops structure.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  drivers/firmware/psci.c | 21 +++++++++++++++++++++
>  include/linux/psci.h    |  6 ++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index e9493da2b111..dd035aaa1c33 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>  	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>  }
>  
> +static void __init psci_init_smccc(u32 ver)
> +{
> +	int feature = PSCI_RET_NOT_SUPPORTED;
> +
> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
> +
> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
> +		psci_ops.variant = SMCCC_VARIANT_1_0;
> +	} else {
> +		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
> +		if (ver != ARM_SMCCC_VERSION_1_1)
> +			psci_ops.variant = SMCCC_VARIANT_1_0;
> +		else
> +			psci_ops.variant = SMCCC_VARIANT_1_1;
> +	}
> +
> +	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
> +}
> +
>  static void __init psci_0_2_set_functions(void)
>  {
>  	pr_info("Using standard PSCI v0.2 function IDs\n");
> @@ -557,6 +577,7 @@ static int __init psci_probe(void)
>  	psci_0_2_set_functions();
>  
>  	psci_init_migrate();
> +	psci_init_smccc(ver);

Given that SMCCC_VARIANT_1_0 is already the default value (unless you do
the same we did with the conduit) we can move psci_init_smccc() call
inside the if below (that is there to detect a callable psci_features())
and remove the check in psci_init_smccc(), up to you.

>  
>  	if (PSCI_VERSION_MAJOR(ver) >= 1) {
>  		psci_init_cpu_suspend();
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f2679e5faa4f..83fd16a37be3 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -31,6 +31,11 @@ enum psci_conduit {
>  	PSCI_CONDUIT_HVC,
>  };
>  
> +enum smccc_variant {
> +	SMCCC_VARIANT_1_0,
> +	SMCCC_VARIANT_1_1,
> +};
> +
>  struct psci_operations {
>  	u32 (*get_version)(void);
>  	int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -41,6 +46,7 @@ struct psci_operations {
>  			unsigned long lowest_affinity_level);
>  	int (*migrate_info_type)(void);
>  	enum psci_conduit conduit;
> +	enum smccc_variant variant;

Nit: I would add an smccc_ prefix to the variant field (or rename it
to smccc_version).

You can add my:

Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-29 19:07     ` Robin Murphy
  -1 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-29 19:07 UTC (permalink / raw)
  To: Marc Zyngier, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Ard Biesheuvel, Jon Masters

On 29/01/18 17:45, Marc Zyngier wrote:
> One of the major improvement of SMCCC v1.1 is that it only clobbers
> the first 4 registers, both on 32 and 64bit. This means that it
> becomes very easy to provide an inline version of the SMC call
> primitive, and avoid performing a function call to stash the
> registers that would otherwise be clobbered by SMCCC v1.0.

This is disgusting... I love it :D

> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 157 insertions(+)
> 
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index dd44d8458c04..bc5843728909 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>   
>   #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>   
> +/* SMCCC v1.1 implementation madness follows */
> +#ifdef CONFIG_ARM64
> +
> +#define SMCCC_SMC_INST	"smc	#0"
> +#define SMCCC_HVC_INST	"hvc	#0"
> +
> +#define __arm_smccc_1_1_prologue(inst)					\
> +	inst "\n"							\
> +	"cbz	%[ptr], 1f\n"						\
> +	"stp	%x[r0], %x[r1], %[ra0]\n"				\
> +	"stp	%x[r2], %x[r3], %[ra2]\n"				\
> +	"1:\n"								\
> +	: [ra0] "=Ump" (*(&___res->a0)),				\
> +	  [ra2] "=Ump" (*(&___res->a2)),

Rather than embedding a guaranteed spill to memory, I wonder if there's 
money in just always declaring r0-r3 as in-out operands, and propagating 
them by value afterwards, i.e.:

	asm(...);
	if (___res)
		*___res = (struct arm_smccc_res){ r0, r1, r2, r3 };

In theory, for sufficiently simple callers that might allow res to stay 
in registers for its entire lifetime and give nicer codegen. It *might* 
also simplify some of this macro machinery too, although at this point 
in the evening I can't really tell...

Robin.

> +
> +#define __arm_smccc_1_1_epilogue	: "memory"
> +		
> +#endif
> +
> +#ifdef CONFIG_ARM
> +#include <asm/opcodes-sec.h>
> +#include <asm/opcodes-virt.h>
> +
> +#define SMCCC_SMC_INST	__SMC(0)
> +#define SMCCC_HVC_INST	__HVC(0)
> +
> +#define __arm_smccc_1_1_prologue(inst)					\
> +	inst "\n"							\
> +	"cmp	%[ptr], #0\n"						\
> +	"stmne	%[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"			\
> +	: "=m" (*___res),
> +
> +#define __arm_smccc_1_1_epilogue	: "memory", "cc"
> +		
> +#endif
> +
> +#define __constraint_write_0						\
> +	[r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_1						\
> +	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_2						\
> +	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_3						\
> +	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
> +#define __constraint_write_4	__constraint_write_3
> +#define __constraint_write_5	__constraint_write_3
> +#define __constraint_write_6	__constraint_write_3
> +#define __constraint_write_7	__constraint_write_3
> +
> +#define __constraint_read_0	: [ptr] "r" (___res)
> +#define __constraint_read_1	__constraint_read_0
> +#define __constraint_read_2	__constraint_read_0
> +#define __constraint_read_3	__constraint_read_0
> +#define __constraint_read_4	__constraint_read_3, "r" (r4)
> +#define __constraint_read_5	__constraint_read_4, "r" (r5)
> +#define __constraint_read_6	__constraint_read_5, "r" (r6)
> +#define __constraint_read_7	__constraint_read_6, "r" (r7)
> +
> +#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
> +
> +#define __count_args(...)						\
> +	___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
> +
> +#define __declare_arg_0(a0, res)					\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register unsigned long r1 asm("r1");				\
> +	register unsigned long r2 asm("r2");				\
> +	register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_1(a0, a1, res)					\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register typeof(a1)    r1 asm("r1") = a1;			\
> +	register unsigned long r2 asm("r2");				\
> +	register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_2(a0, a1, a2, res)				\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register typeof(a1)    r1 asm("r1") = a1;			\
> +	register typeof(a2)    r2 asm("r2") = a2;			\
> +	register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_3(a0, a1, a2, a3, res)				\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register typeof(a1)    r1 asm("r1") = a1;			\
> +	register typeof(a2)    r2 asm("r2") = a2;			\
> +	register typeof(a3)    r3 asm("r3") = a3
> +
> +#define __declare_arg_4(a0, a1, a2, a3, a4, res)			\
> +	__declare_arg_3(a0, a1, a2, a3, res);				\
> +	register typeof(a4) r4 asm("r4") = a4
> +
> +#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)			\
> +	__declare_arg_4(a0, a1, a2, a3, a4, res);			\
> +	register typeof(a5) r5 asm("r5") = a5
> +
> +#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)		\
> +	__declare_arg_5(a0, a1, a2, a3, a4, a5, res);			\
> +	register typeof(a6) r6 asm("r6") = a6
> +
> +#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)		\
> +	__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);		\
> +	register typeof(a7) r7 asm("r7") = a7
> +
> +#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
> +#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
> +
> +#define ___constraint_write(count)  __constraint_write_ ## count
> +#define __constraint_write(count)   ___constraint_write(count)
> +
> +#define ___constraint_read(count)   __constraint_read_ ## count
> +#define __constraint_read(count)    ___constraint_read(count)
> +
> +#define __arm_smccc_1_1(inst, ...)					\
> +	do {								\
> +		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
> +		asm(__arm_smccc_1_1_prologue(inst)			\
> +		    __constraint_write(__count_args(__VA_ARGS__))	\
> +		    __constraint_read(__count_args(__VA_ARGS__))	\
> +		    __arm_smccc_1_1_epilogue);				\
> +	} while (0)
> +
> +/*
> + * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make SMC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the SMC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the SMC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_smc(...)	__arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
> +
> +/*
> + * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make HVC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the HVC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the HVC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_hvc(...)	__arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
> +
>   #endif /*__ASSEMBLY__*/
>   #endif /*__LINUX_ARM_SMCCC_H*/
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-29 19:07     ` Robin Murphy
  0 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-29 19:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 17:45, Marc Zyngier wrote:
> One of the major improvement of SMCCC v1.1 is that it only clobbers
> the first 4 registers, both on 32 and 64bit. This means that it
> becomes very easy to provide an inline version of the SMC call
> primitive, and avoid performing a function call to stash the
> registers that would otherwise be clobbered by SMCCC v1.0.

This is disgusting... I love it :D

> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 157 insertions(+)
> 
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index dd44d8458c04..bc5843728909 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>   
>   #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>   
> +/* SMCCC v1.1 implementation madness follows */
> +#ifdef CONFIG_ARM64
> +
> +#define SMCCC_SMC_INST	"smc	#0"
> +#define SMCCC_HVC_INST	"hvc	#0"
> +
> +#define __arm_smccc_1_1_prologue(inst)					\
> +	inst "\n"							\
> +	"cbz	%[ptr], 1f\n"						\
> +	"stp	%x[r0], %x[r1], %[ra0]\n"				\
> +	"stp	%x[r2], %x[r3], %[ra2]\n"				\
> +	"1:\n"								\
> +	: [ra0] "=Ump" (*(&___res->a0)),				\
> +	  [ra2] "=Ump" (*(&___res->a2)),

Rather than embedding a guaranteed spill to memory, I wonder if there's 
money in just always declaring r0-r3 as in-out operands, and propagating 
them by value afterwards, i.e.:

	asm(...);
	if (___res)
		*___res = (struct arm_smccc_res){ r0, r1, r2, r3 };

In theory, for sufficiently simple callers that might allow res to stay 
in registers for its entire lifetime and give nicer codegen. It *might* 
also simplify some of this macro machinery too, although at this point 
in the evening I can't really tell...

Robin.

> +
> +#define __arm_smccc_1_1_epilogue	: "memory"
> +		
> +#endif
> +
> +#ifdef CONFIG_ARM
> +#include <asm/opcodes-sec.h>
> +#include <asm/opcodes-virt.h>
> +
> +#define SMCCC_SMC_INST	__SMC(0)
> +#define SMCCC_HVC_INST	__HVC(0)
> +
> +#define __arm_smccc_1_1_prologue(inst)					\
> +	inst "\n"							\
> +	"cmp	%[ptr], #0\n"						\
> +	"stmne	%[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"			\
> +	: "=m" (*___res),
> +
> +#define __arm_smccc_1_1_epilogue	: "memory", "cc"
> +		
> +#endif
> +
> +#define __constraint_write_0						\
> +	[r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_1						\
> +	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_2						\
> +	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_3						\
> +	[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
> +#define __constraint_write_4	__constraint_write_3
> +#define __constraint_write_5	__constraint_write_3
> +#define __constraint_write_6	__constraint_write_3
> +#define __constraint_write_7	__constraint_write_3
> +
> +#define __constraint_read_0	: [ptr] "r" (___res)
> +#define __constraint_read_1	__constraint_read_0
> +#define __constraint_read_2	__constraint_read_0
> +#define __constraint_read_3	__constraint_read_0
> +#define __constraint_read_4	__constraint_read_3, "r" (r4)
> +#define __constraint_read_5	__constraint_read_4, "r" (r5)
> +#define __constraint_read_6	__constraint_read_5, "r" (r6)
> +#define __constraint_read_7	__constraint_read_6, "r" (r7)
> +
> +#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
> +
> +#define __count_args(...)						\
> +	___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
> +
> +#define __declare_arg_0(a0, res)					\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register unsigned long r1 asm("r1");				\
> +	register unsigned long r2 asm("r2");				\
> +	register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_1(a0, a1, res)					\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register typeof(a1)    r1 asm("r1") = a1;			\
> +	register unsigned long r2 asm("r2");				\
> +	register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_2(a0, a1, a2, res)				\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register typeof(a1)    r1 asm("r1") = a1;			\
> +	register typeof(a2)    r2 asm("r2") = a2;			\
> +	register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_3(a0, a1, a2, a3, res)				\
> +	struct arm_smccc_res   *___res = res;				\
> +	register u32           r0 asm("r0") = a0;			\
> +	register typeof(a1)    r1 asm("r1") = a1;			\
> +	register typeof(a2)    r2 asm("r2") = a2;			\
> +	register typeof(a3)    r3 asm("r3") = a3
> +
> +#define __declare_arg_4(a0, a1, a2, a3, a4, res)			\
> +	__declare_arg_3(a0, a1, a2, a3, res);				\
> +	register typeof(a4) r4 asm("r4") = a4
> +
> +#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)			\
> +	__declare_arg_4(a0, a1, a2, a3, a4, res);			\
> +	register typeof(a5) r5 asm("r5") = a5
> +
> +#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)		\
> +	__declare_arg_5(a0, a1, a2, a3, a4, a5, res);			\
> +	register typeof(a6) r6 asm("r6") = a6
> +
> +#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)		\
> +	__declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);		\
> +	register typeof(a7) r7 asm("r7") = a7
> +
> +#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
> +#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
> +
> +#define ___constraint_write(count)  __constraint_write_ ## count
> +#define __constraint_write(count)   ___constraint_write(count)
> +
> +#define ___constraint_read(count)   __constraint_read_ ## count
> +#define __constraint_read(count)    ___constraint_read(count)
> +
> +#define __arm_smccc_1_1(inst, ...)					\
> +	do {								\
> +		__declare_args(__count_args(__VA_ARGS__), __VA_ARGS__);	\
> +		asm(__arm_smccc_1_1_prologue(inst)			\
> +		    __constraint_write(__count_args(__VA_ARGS__))	\
> +		    __constraint_read(__count_args(__VA_ARGS__))	\
> +		    __arm_smccc_1_1_epilogue);				\
> +	} while (0)
> +
> +/*
> + * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make SMC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the SMC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the SMC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_smc(...)	__arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
> +
> +/*
> + * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make HVC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the HVC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the HVC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_hvc(...)	__arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
> +
>   #endif /*__ASSEMBLY__*/
>   #endif /*__LINUX_ARM_SMCCC_H*/
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-29 19:41     ` Ard Biesheuvel
  -1 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-29 19:41 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
> It is lovely. Really.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm64/include/asm/kvm_psci.h | 63 ++++++++++++++++++++++++++++++++++++
>  arch/arm64/kernel/bpi.S           | 20 ++++++++++++
>  arch/arm64/kernel/cpu_errata.c    | 68 ++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 150 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm64/include/asm/kvm_psci.h
>
> diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h

Did you mean to add this file? It is mostly identical to include/kvm/arm_psci.h

> new file mode 100644
> index 000000000000..f553e3795a4e
> --- /dev/null
> +++ b/arch/arm64/include/asm/kvm_psci.h
> @@ -0,0 +1,63 @@
> +/*
> + * Copyright (C) 2012,2013 - ARM Ltd
> + * Author: Marc Zyngier <marc.zyngier@arm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __ARM64_KVM_PSCI_H__
> +#define __ARM64_KVM_PSCI_H__
> +
> +#include <linux/kvm_host.h>
> +
> +#define PSCI_VERSION(x,y)      ((((x) & 0x7fff) << 16) | ((y) & 0xffff))
> +#define KVM_ARM_PSCI_0_1       PSCI_VERSION(0, 1)
> +#define KVM_ARM_PSCI_0_2       PSCI_VERSION(0, 2)
> +#define KVM_ARM_PSCI_1_0       PSCI_VERSION(1, 0)
> +
> +#define KVM_ARM_PSCI_LATEST    KVM_ARM_PSCI_1_0
> +
> +/*
> + * We need the KVM pointer independently from the vcpu as we can call
> + * this from HYP, and need to apply kern_hyp_va on it...
> + */
> +static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
> +{
> +       /*
> +        * Our PSCI implementation stays the same across versions from
> +        * v0.2 onward, only adding the few mandatory functions (such
> +        * as FEATURES with 1.0) that are required by newer
> +        * revisions. It is thus safe to return the latest, unless
> +        * userspace has instructed us otherwise.
> +        */
> +       if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
> +               if (kvm->arch.psci_version)
> +                       return kvm->arch.psci_version;
> +
> +               return KVM_ARM_PSCI_LATEST;
> +       }
> +
> +       return KVM_ARM_PSCI_0_1;
> +}
> +
> +
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
> +
> +struct kvm_one_reg;
> +
> +int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
> +int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
> +int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> +int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> +
> +#endif /* __ARM64_KVM_PSCI_H__ */
> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
> index 76225c2611ea..fdeed629f2c6 100644
> --- a/arch/arm64/kernel/bpi.S
> +++ b/arch/arm64/kernel/bpi.S
> @@ -17,6 +17,7 @@
>   */
>
>  #include <linux/linkage.h>
> +#include <linux/arm-smccc.h>
>
>  .macro ventry target
>         .rept 31
> @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
>         .endr
>         ldp     x29, x30, [sp], #16
>  ENTRY(__qcom_hyp_sanitize_link_stack_end)
> +
> +.macro smccc_workaround_1 inst
> +       sub     sp, sp, #(8 * 4)
> +       stp     x2, x3, [sp, #(8 * 0)]
> +       stp     x0, x1, [sp, #(8 * 2)]
> +       mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_1
> +       \inst   #0
> +       ldp     x2, x3, [sp, #(8 * 0)]
> +       ldp     x0, x1, [sp, #(8 * 2)]
> +       add     sp, sp, #(8 * 4)
> +.endm
> +
> +ENTRY(__smccc_workaround_1_smc_start)
> +       smccc_workaround_1      smc
> +ENTRY(__smccc_workaround_1_smc_end)
> +
> +ENTRY(__smccc_workaround_1_hvc_start)
> +       smccc_workaround_1      hvc
> +ENTRY(__smccc_workaround_1_hvc_end)
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index ed6881882231..36cff870d5d7 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
>  extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
>  extern char __qcom_hyp_sanitize_link_stack_start[];
>  extern char __qcom_hyp_sanitize_link_stack_end[];
> +extern char __smccc_workaround_1_smc_start[];
> +extern char __smccc_workaround_1_smc_end[];
> +extern char __smccc_workaround_1_hvc_start[];
> +extern char __smccc_workaround_1_hvc_end[];
>
>  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
>                                 const char *hyp_vecs_end)
> @@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
>  #define __psci_hyp_bp_inval_end                        NULL
>  #define __qcom_hyp_sanitize_link_stack_start   NULL
>  #define __qcom_hyp_sanitize_link_stack_end     NULL
> +#define __smccc_workaround_1_smc_start         NULL
> +#define __smccc_workaround_1_smc_end           NULL
> +#define __smccc_workaround_1_hvc_start         NULL
> +#define __smccc_workaround_1_hvc_end           NULL
>
>  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
>                                       const char *hyp_vecs_start,
> @@ -142,17 +150,75 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
>         __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
>  }
>
> +#include <uapi/linux/psci.h>
> +#include <linux/arm-smccc.h>
>  #include <linux/psci.h>
>
> +static void call_smc_arch_workaround_1(void)
> +{
> +       arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
> +}
> +
> +static void call_hvc_arch_workaround_1(void)
> +{
> +       arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
> +}
> +
> +static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
> +{
> +       bp_hardening_cb_t cb;
> +       void *smccc_start, *smccc_end;
> +       struct arm_smccc_res res;
> +
> +       if (!entry->matches(entry, SCOPE_LOCAL_CPU))
> +               return false;
> +
> +       if (psci_ops.variant == SMCCC_VARIANT_1_0)
> +               return false;
> +
> +       switch (psci_ops.conduit) {
> +       case PSCI_CONDUIT_HVC:
> +               arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> +                                 ARM_SMCCC_ARCH_WORKAROUND_1, &res);
> +               if (res.a0)
> +                       return false;
> +               cb = call_hvc_arch_workaround_1;
> +               smccc_start = __smccc_workaround_1_hvc_start;
> +               smccc_end = __smccc_workaround_1_hvc_end;
> +               break;
> +
> +       case PSCI_CONDUIT_SMC:
> +               arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> +                                 ARM_SMCCC_ARCH_WORKAROUND_1, &res);
> +               if (res.a0)
> +                       return false;
> +               cb = call_smc_arch_workaround_1;
> +               smccc_start = __smccc_workaround_1_smc_start;
> +               smccc_end = __smccc_workaround_1_smc_end;
> +               break;
> +
> +       default:
> +               return false;
> +       }
> +
> +       install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
> +
> +       return true;
> +}
> +
>  static int enable_psci_bp_hardening(void *data)
>  {
>         const struct arm64_cpu_capabilities *entry = data;
>
> -       if (psci_ops.get_version)
> +       if (psci_ops.get_version) {
> +               if (check_smccc_arch_workaround_1(entry))
> +                       return 0;
> +
>                 install_bp_hardening_cb(entry,
>                                        (bp_hardening_cb_t)psci_ops.get_version,
>                                        __psci_hyp_bp_inval_start,
>                                        __psci_hyp_bp_inval_end);
> +       }
>
>         return 0;
>  }
> --
> 2.14.2
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-29 19:41     ` Ard Biesheuvel
  0 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-29 19:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
> It is lovely. Really.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm64/include/asm/kvm_psci.h | 63 ++++++++++++++++++++++++++++++++++++
>  arch/arm64/kernel/bpi.S           | 20 ++++++++++++
>  arch/arm64/kernel/cpu_errata.c    | 68 ++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 150 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm64/include/asm/kvm_psci.h
>
> diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h

Did you mean to add this file? It is mostly identical to include/kvm/arm_psci.h

> new file mode 100644
> index 000000000000..f553e3795a4e
> --- /dev/null
> +++ b/arch/arm64/include/asm/kvm_psci.h
> @@ -0,0 +1,63 @@
> +/*
> + * Copyright (C) 2012,2013 - ARM Ltd
> + * Author: Marc Zyngier <marc.zyngier@arm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __ARM64_KVM_PSCI_H__
> +#define __ARM64_KVM_PSCI_H__
> +
> +#include <linux/kvm_host.h>
> +
> +#define PSCI_VERSION(x,y)      ((((x) & 0x7fff) << 16) | ((y) & 0xffff))
> +#define KVM_ARM_PSCI_0_1       PSCI_VERSION(0, 1)
> +#define KVM_ARM_PSCI_0_2       PSCI_VERSION(0, 2)
> +#define KVM_ARM_PSCI_1_0       PSCI_VERSION(1, 0)
> +
> +#define KVM_ARM_PSCI_LATEST    KVM_ARM_PSCI_1_0
> +
> +/*
> + * We need the KVM pointer independently from the vcpu as we can call
> + * this from HYP, and need to apply kern_hyp_va on it...
> + */
> +static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
> +{
> +       /*
> +        * Our PSCI implementation stays the same across versions from
> +        * v0.2 onward, only adding the few mandatory functions (such
> +        * as FEATURES with 1.0) that are required by newer
> +        * revisions. It is thus safe to return the latest, unless
> +        * userspace has instructed us otherwise.
> +        */
> +       if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
> +               if (kvm->arch.psci_version)
> +                       return kvm->arch.psci_version;
> +
> +               return KVM_ARM_PSCI_LATEST;
> +       }
> +
> +       return KVM_ARM_PSCI_0_1;
> +}
> +
> +
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
> +
> +struct kvm_one_reg;
> +
> +int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
> +int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
> +int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> +int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> +
> +#endif /* __ARM64_KVM_PSCI_H__ */
> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
> index 76225c2611ea..fdeed629f2c6 100644
> --- a/arch/arm64/kernel/bpi.S
> +++ b/arch/arm64/kernel/bpi.S
> @@ -17,6 +17,7 @@
>   */
>
>  #include <linux/linkage.h>
> +#include <linux/arm-smccc.h>
>
>  .macro ventry target
>         .rept 31
> @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
>         .endr
>         ldp     x29, x30, [sp], #16
>  ENTRY(__qcom_hyp_sanitize_link_stack_end)
> +
> +.macro smccc_workaround_1 inst
> +       sub     sp, sp, #(8 * 4)
> +       stp     x2, x3, [sp, #(8 * 0)]
> +       stp     x0, x1, [sp, #(8 * 2)]
> +       mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_1
> +       \inst   #0
> +       ldp     x2, x3, [sp, #(8 * 0)]
> +       ldp     x0, x1, [sp, #(8 * 2)]
> +       add     sp, sp, #(8 * 4)
> +.endm
> +
> +ENTRY(__smccc_workaround_1_smc_start)
> +       smccc_workaround_1      smc
> +ENTRY(__smccc_workaround_1_smc_end)
> +
> +ENTRY(__smccc_workaround_1_hvc_start)
> +       smccc_workaround_1      hvc
> +ENTRY(__smccc_workaround_1_hvc_end)
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index ed6881882231..36cff870d5d7 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
>  extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
>  extern char __qcom_hyp_sanitize_link_stack_start[];
>  extern char __qcom_hyp_sanitize_link_stack_end[];
> +extern char __smccc_workaround_1_smc_start[];
> +extern char __smccc_workaround_1_smc_end[];
> +extern char __smccc_workaround_1_hvc_start[];
> +extern char __smccc_workaround_1_hvc_end[];
>
>  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
>                                 const char *hyp_vecs_end)
> @@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
>  #define __psci_hyp_bp_inval_end                        NULL
>  #define __qcom_hyp_sanitize_link_stack_start   NULL
>  #define __qcom_hyp_sanitize_link_stack_end     NULL
> +#define __smccc_workaround_1_smc_start         NULL
> +#define __smccc_workaround_1_smc_end           NULL
> +#define __smccc_workaround_1_hvc_start         NULL
> +#define __smccc_workaround_1_hvc_end           NULL
>
>  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
>                                       const char *hyp_vecs_start,
> @@ -142,17 +150,75 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
>         __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
>  }
>
> +#include <uapi/linux/psci.h>
> +#include <linux/arm-smccc.h>
>  #include <linux/psci.h>
>
> +static void call_smc_arch_workaround_1(void)
> +{
> +       arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
> +}
> +
> +static void call_hvc_arch_workaround_1(void)
> +{
> +       arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
> +}
> +
> +static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
> +{
> +       bp_hardening_cb_t cb;
> +       void *smccc_start, *smccc_end;
> +       struct arm_smccc_res res;
> +
> +       if (!entry->matches(entry, SCOPE_LOCAL_CPU))
> +               return false;
> +
> +       if (psci_ops.variant == SMCCC_VARIANT_1_0)
> +               return false;
> +
> +       switch (psci_ops.conduit) {
> +       case PSCI_CONDUIT_HVC:
> +               arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> +                                 ARM_SMCCC_ARCH_WORKAROUND_1, &res);
> +               if (res.a0)
> +                       return false;
> +               cb = call_hvc_arch_workaround_1;
> +               smccc_start = __smccc_workaround_1_hvc_start;
> +               smccc_end = __smccc_workaround_1_hvc_end;
> +               break;
> +
> +       case PSCI_CONDUIT_SMC:
> +               arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> +                                 ARM_SMCCC_ARCH_WORKAROUND_1, &res);
> +               if (res.a0)
> +                       return false;
> +               cb = call_smc_arch_workaround_1;
> +               smccc_start = __smccc_workaround_1_smc_start;
> +               smccc_end = __smccc_workaround_1_smc_end;
> +               break;
> +
> +       default:
> +               return false;
> +       }
> +
> +       install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
> +
> +       return true;
> +}
> +
>  static int enable_psci_bp_hardening(void *data)
>  {
>         const struct arm64_cpu_capabilities *entry = data;
>
> -       if (psci_ops.get_version)
> +       if (psci_ops.get_version) {
> +               if (check_smccc_arch_workaround_1(entry))
> +                       return 0;
> +
>                 install_bp_hardening_cb(entry,
>                                        (bp_hardening_cb_t)psci_ops.get_version,
>                                        __psci_hyp_bp_inval_start,
>                                        __psci_hyp_bp_inval_end);
> +       }
>
>         return 0;
>  }
> --
> 2.14.2
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-29 21:45     ` Ard Biesheuvel
  -1 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-29 21:45 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
> One of the major improvement of SMCCC v1.1 is that it only clobbers
> the first 4 registers, both on 32 and 64bit. This means that it
> becomes very easy to provide an inline version of the SMC call
> primitive, and avoid performing a function call to stash the
> registers that would otherwise be clobbered by SMCCC v1.0.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 157 insertions(+)
>
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index dd44d8458c04..bc5843728909 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>
>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>
> +/* SMCCC v1.1 implementation madness follows */
> +#ifdef CONFIG_ARM64
> +
> +#define SMCCC_SMC_INST "smc    #0"
> +#define SMCCC_HVC_INST "hvc    #0"
> +
> +#define __arm_smccc_1_1_prologue(inst)                                 \
> +       inst "\n"                                                       \
> +       "cbz    %[ptr], 1f\n"                                           \
> +       "stp    %x[r0], %x[r1], %[ra0]\n"                               \
> +       "stp    %x[r2], %x[r3], %[ra2]\n"                               \
> +       "1:\n"                                                          \
> +       : [ra0] "=Ump" (*(&___res->a0)),                                \
> +         [ra2] "=Ump" (*(&___res->a2)),
> +
> +#define __arm_smccc_1_1_epilogue       : "memory"
> +
> +#endif
> +
> +#ifdef CONFIG_ARM
> +#include <asm/opcodes-sec.h>
> +#include <asm/opcodes-virt.h>
> +
> +#define SMCCC_SMC_INST __SMC(0)
> +#define SMCCC_HVC_INST __HVC(0)
> +
> +#define __arm_smccc_1_1_prologue(inst)                                 \
> +       inst "\n"                                                       \
> +       "cmp    %[ptr], #0\n"                                           \
> +       "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"                 \
> +       : "=m" (*___res),
> +
> +#define __arm_smccc_1_1_epilogue       : "memory", "cc"
> +
> +#endif
> +
> +#define __constraint_write_0                                           \
> +       [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_1                                           \
> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_2                                           \
> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_3                                           \
> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)

It seems you need +r for all arguments, otherwise the compiler will
notice that the value is never used, and may assign the register to
'res' instead, i.e.,

 3e4:   320107e0        mov     w0, #0x80000001                 // #-2147483647
 3e8:   320183e1        mov     w1, #0x80008000                 // #-2147450880
 3ec:   910123a2        add     x2, x29, #0x48
 3f0:   d4000002        hvc     #0x0
 3f4:   b4000062        cbz     x2, 400 <enable_psci_bp_hardening+0x88>
 3f8:   a90487a0        stp     x0, x1, [x29, #72]
 3fc:   a9058fa2        stp     x2, x3, [x29, #88]

(for the code generated in the next patch)

> +#define __constraint_write_4   __constraint_write_3
> +#define __constraint_write_5   __constraint_write_3
> +#define __constraint_write_6   __constraint_write_3
> +#define __constraint_write_7   __constraint_write_3
> +
> +#define __constraint_read_0    : [ptr] "r" (___res)
> +#define __constraint_read_1    __constraint_read_0
> +#define __constraint_read_2    __constraint_read_0
> +#define __constraint_read_3    __constraint_read_0
> +#define __constraint_read_4    __constraint_read_3, "r" (r4)
> +#define __constraint_read_5    __constraint_read_4, "r" (r5)
> +#define __constraint_read_6    __constraint_read_5, "r" (r6)
> +#define __constraint_read_7    __constraint_read_6, "r" (r7)
> +
> +#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
> +
> +#define __count_args(...)                                              \
> +       ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
> +
> +#define __declare_arg_0(a0, res)                                       \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register unsigned long r1 asm("r1");                            \
> +       register unsigned long r2 asm("r2");                            \
> +       register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_1(a0, a1, res)                                   \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register typeof(a1)    r1 asm("r1") = a1;                       \
> +       register unsigned long r2 asm("r2");                            \
> +       register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_2(a0, a1, a2, res)                               \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register typeof(a1)    r1 asm("r1") = a1;                       \
> +       register typeof(a2)    r2 asm("r2") = a2;                       \
> +       register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_3(a0, a1, a2, a3, res)                           \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register typeof(a1)    r1 asm("r1") = a1;                       \
> +       register typeof(a2)    r2 asm("r2") = a2;                       \
> +       register typeof(a3)    r3 asm("r3") = a3
> +
> +#define __declare_arg_4(a0, a1, a2, a3, a4, res)                       \
> +       __declare_arg_3(a0, a1, a2, a3, res);                           \
> +       register typeof(a4) r4 asm("r4") = a4
> +
> +#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)                   \
> +       __declare_arg_4(a0, a1, a2, a3, a4, res);                       \
> +       register typeof(a5) r5 asm("r5") = a5
> +
> +#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)               \
> +       __declare_arg_5(a0, a1, a2, a3, a4, a5, res);                   \
> +       register typeof(a6) r6 asm("r6") = a6
> +
> +#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)           \
> +       __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);               \
> +       register typeof(a7) r7 asm("r7") = a7
> +
> +#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
> +#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
> +
> +#define ___constraint_write(count)  __constraint_write_ ## count
> +#define __constraint_write(count)   ___constraint_write(count)
> +
> +#define ___constraint_read(count)   __constraint_read_ ## count
> +#define __constraint_read(count)    ___constraint_read(count)
> +
> +#define __arm_smccc_1_1(inst, ...)                                     \
> +       do {                                                            \
> +               __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
> +               asm(__arm_smccc_1_1_prologue(inst)                      \
> +                   __constraint_write(__count_args(__VA_ARGS__))       \
> +                   __constraint_read(__count_args(__VA_ARGS__))        \
> +                   __arm_smccc_1_1_epilogue);                          \
> +       } while (0)
> +
> +/*
> + * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make SMC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the SMC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the SMC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
> +
> +/*
> + * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make HVC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the HVC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the HVC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
> +
>  #endif /*__ASSEMBLY__*/
>  #endif /*__LINUX_ARM_SMCCC_H*/
> --
> 2.14.2
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-29 21:45     ` Ard Biesheuvel
  0 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-29 21:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
> One of the major improvement of SMCCC v1.1 is that it only clobbers
> the first 4 registers, both on 32 and 64bit. This means that it
> becomes very easy to provide an inline version of the SMC call
> primitive, and avoid performing a function call to stash the
> registers that would otherwise be clobbered by SMCCC v1.0.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 157 insertions(+)
>
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index dd44d8458c04..bc5843728909 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>
>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>
> +/* SMCCC v1.1 implementation madness follows */
> +#ifdef CONFIG_ARM64
> +
> +#define SMCCC_SMC_INST "smc    #0"
> +#define SMCCC_HVC_INST "hvc    #0"
> +
> +#define __arm_smccc_1_1_prologue(inst)                                 \
> +       inst "\n"                                                       \
> +       "cbz    %[ptr], 1f\n"                                           \
> +       "stp    %x[r0], %x[r1], %[ra0]\n"                               \
> +       "stp    %x[r2], %x[r3], %[ra2]\n"                               \
> +       "1:\n"                                                          \
> +       : [ra0] "=Ump" (*(&___res->a0)),                                \
> +         [ra2] "=Ump" (*(&___res->a2)),
> +
> +#define __arm_smccc_1_1_epilogue       : "memory"
> +
> +#endif
> +
> +#ifdef CONFIG_ARM
> +#include <asm/opcodes-sec.h>
> +#include <asm/opcodes-virt.h>
> +
> +#define SMCCC_SMC_INST __SMC(0)
> +#define SMCCC_HVC_INST __HVC(0)
> +
> +#define __arm_smccc_1_1_prologue(inst)                                 \
> +       inst "\n"                                                       \
> +       "cmp    %[ptr], #0\n"                                           \
> +       "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"                 \
> +       : "=m" (*___res),
> +
> +#define __arm_smccc_1_1_epilogue       : "memory", "cc"
> +
> +#endif
> +
> +#define __constraint_write_0                                           \
> +       [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_1                                           \
> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_2                                           \
> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_3                                           \
> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)

It seems you need +r for all arguments, otherwise the compiler will
notice that the value is never used, and may assign the register to
'res' instead, i.e.,

 3e4:   320107e0        mov     w0, #0x80000001                 // #-2147483647
 3e8:   320183e1        mov     w1, #0x80008000                 // #-2147450880
 3ec:   910123a2        add     x2, x29, #0x48
 3f0:   d4000002        hvc     #0x0
 3f4:   b4000062        cbz     x2, 400 <enable_psci_bp_hardening+0x88>
 3f8:   a90487a0        stp     x0, x1, [x29, #72]
 3fc:   a9058fa2        stp     x2, x3, [x29, #88]

(for the code generated in the next patch)

> +#define __constraint_write_4   __constraint_write_3
> +#define __constraint_write_5   __constraint_write_3
> +#define __constraint_write_6   __constraint_write_3
> +#define __constraint_write_7   __constraint_write_3
> +
> +#define __constraint_read_0    : [ptr] "r" (___res)
> +#define __constraint_read_1    __constraint_read_0
> +#define __constraint_read_2    __constraint_read_0
> +#define __constraint_read_3    __constraint_read_0
> +#define __constraint_read_4    __constraint_read_3, "r" (r4)
> +#define __constraint_read_5    __constraint_read_4, "r" (r5)
> +#define __constraint_read_6    __constraint_read_5, "r" (r6)
> +#define __constraint_read_7    __constraint_read_6, "r" (r7)
> +
> +#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
> +
> +#define __count_args(...)                                              \
> +       ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
> +
> +#define __declare_arg_0(a0, res)                                       \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register unsigned long r1 asm("r1");                            \
> +       register unsigned long r2 asm("r2");                            \
> +       register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_1(a0, a1, res)                                   \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register typeof(a1)    r1 asm("r1") = a1;                       \
> +       register unsigned long r2 asm("r2");                            \
> +       register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_2(a0, a1, a2, res)                               \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register typeof(a1)    r1 asm("r1") = a1;                       \
> +       register typeof(a2)    r2 asm("r2") = a2;                       \
> +       register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_3(a0, a1, a2, a3, res)                           \
> +       struct arm_smccc_res   *___res = res;                           \
> +       register u32           r0 asm("r0") = a0;                       \
> +       register typeof(a1)    r1 asm("r1") = a1;                       \
> +       register typeof(a2)    r2 asm("r2") = a2;                       \
> +       register typeof(a3)    r3 asm("r3") = a3
> +
> +#define __declare_arg_4(a0, a1, a2, a3, a4, res)                       \
> +       __declare_arg_3(a0, a1, a2, a3, res);                           \
> +       register typeof(a4) r4 asm("r4") = a4
> +
> +#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)                   \
> +       __declare_arg_4(a0, a1, a2, a3, a4, res);                       \
> +       register typeof(a5) r5 asm("r5") = a5
> +
> +#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)               \
> +       __declare_arg_5(a0, a1, a2, a3, a4, a5, res);                   \
> +       register typeof(a6) r6 asm("r6") = a6
> +
> +#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)           \
> +       __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);               \
> +       register typeof(a7) r7 asm("r7") = a7
> +
> +#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
> +#define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
> +
> +#define ___constraint_write(count)  __constraint_write_ ## count
> +#define __constraint_write(count)   ___constraint_write(count)
> +
> +#define ___constraint_read(count)   __constraint_read_ ## count
> +#define __constraint_read(count)    ___constraint_read(count)
> +
> +#define __arm_smccc_1_1(inst, ...)                                     \
> +       do {                                                            \
> +               __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
> +               asm(__arm_smccc_1_1_prologue(inst)                      \
> +                   __constraint_write(__count_args(__VA_ARGS__))       \
> +                   __constraint_read(__count_args(__VA_ARGS__))        \
> +                   __arm_smccc_1_1_epilogue);                          \
> +       } while (0)
> +
> +/*
> + * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make SMC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the SMC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the SMC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)
> +
> +/*
> + * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call
> + *
> + * This is a variadic macro taking one to eight source arguments, and
> + * an optional return structure.
> + *
> + * @a0-a7: arguments passed in registers 0 to 7
> + * @res: result values from registers 0 to 3
> + *
> + * This macro is used to make HVC calls following SMC Calling Convention v1.1.
> + * The content of the supplied param are copied to registers 0 to 7 prior
> + * to the HVC instruction. The return values are updated with the content
> + * from register 0 to 3 on return from the HVC instruction if not NULL.
> + */
> +#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__)
> +
>  #endif /*__ASSEMBLY__*/
>  #endif /*__LINUX_ARM_SMCCC_H*/
> --
> 2.14.2
>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-30  0:23     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 116+ messages in thread
From: Russell King - ARM Linux @ 2018-01-30  0:23 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Mark Rutland,
	Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Jon Masters, Robin Murphy,
	Christoffer Dall

On Mon, Jan 29, 2018 at 05:45:51PM +0000, Marc Zyngier wrote:
> The new SMC Calling Convention (v1.1) allows for a reduced overhead
> when calling into the firmware, and provides a new feature discovery
> mechanism.
> 
> Make it visible to KVM guests.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  Documentation/virtual/kvm/arm/psci.txt | 12 +++++++-----
>  arch/arm/kvm/handle_exit.c             |  2 +-
>  arch/arm64/kvm/handle_exit.c           |  2 +-
>  include/kvm/arm_psci.h                 |  2 +-
>  include/linux/arm-smccc.h              | 13 +++++++++++++
>  virt/kvm/arm/psci.c                    | 24 +++++++++++++++++++++++-
>  6 files changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> index 2e49a4e9f084..aafdab887b04 100644
> --- a/Documentation/virtual/kvm/arm/psci.txt
> +++ b/Documentation/virtual/kvm/arm/psci.txt
> @@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out of the
>  blue to an unsuspecting guest.
>  
>  In order to remedy this situation, KVM exposes a set of "firmware
> -pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> +pseudo-registers" that can be manipulated using the GET/SET_ONE_REG

This should surely be in patch 7?

>  interface. These registers can be saved/restored by userspace, and set
>  to a convenient value if required.
>  
> @@ -21,8 +21,10 @@ The following register is defined:
>  
>  * KVM_REG_ARM_PSCI_VERSION:
>  
> -  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> -  - Returns the current PSCI version on GET_ONE_REG
> -  - Allows any supported PSCI version compatible with v0.2 to be set
> -    with SET_ONE_REG
> +  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
> +    (and thus has already been initialized)
> +  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
> +    highest PSCI version implemented by KVM and compatible with v0.2)
> +  - Allows any PSCI version implemented by KVM and compatible with
> +    v0.2 to be set with SET_ONE_REG
>    - Affects the whole VM (even if the register view is per-vcpu)
> diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
> index e020cc82c4b1..a4520c7118d2 100644
> --- a/arch/arm/kvm/handle_exit.c
> +++ b/arch/arm/kvm/handle_exit.c
> @@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  		      kvm_vcpu_hvc_get_imm(vcpu));
>  	vcpu->stat.hvc_exit_stat++;
>  
> -	ret = kvm_psci_call(vcpu);
> +	ret = kvm_hvc_call_handler(vcpu);
>  	if (ret < 0) {
>  		vcpu_set_reg(vcpu, 0, ~0UL);
>  		return 1;
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 97e8d64a203d..bb6e1518d819 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  			    kvm_vcpu_hvc_get_imm(vcpu));
>  	vcpu->stat.hvc_exit_stat++;
>  
> -	ret = kvm_psci_call(vcpu);
> +	ret = kvm_hvc_call_handler(vcpu);
>  	if (ret < 0) {
>  		vcpu_set_reg(vcpu, 0, ~0UL);
>  		return 1;
> diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
> index f2fa7d752c4e..4876bfac2195 100644
> --- a/include/kvm/arm_psci.h
> +++ b/include/kvm/arm_psci.h
> @@ -26,7 +26,7 @@
>  #define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
>  
>  int kvm_psci_version(struct kvm_vcpu *vcpu);
> -int kvm_psci_call(struct kvm_vcpu *vcpu);
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
>  
>  struct kvm_one_reg;
>  
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 4c5bca38c653..dc68aa5a7261 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -60,6 +60,19 @@
>  #define ARM_SMCCC_QUIRK_NONE		0
>  #define ARM_SMCCC_QUIRK_QCOM_A6		1 /* Save/restore register a6 */
>  
> +#define ARM_SMCCC_VERSION_1_0		0x10000
> +#define ARM_SMCCC_VERSION_1_1		0x10001
> +
> +#define ARM_SMCCC_VERSION_FUNC_ID					\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
> +			   ARM_SMCCC_SMC_32,				\
> +			   0, 0)
> +
> +#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID					\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
> +			   ARM_SMCCC_SMC_32,				\
> +			   0, 1)
> +
>  #ifndef __ASSEMBLY__
>  
>  #include <linux/linkage.h>
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index 682f9be6264b..3bb336ac7d7d 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -15,6 +15,7 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include <linux/arm-smccc.h>
>  #include <linux/preempt.h>
>  #include <linux/kvm_host.h>
>  #include <linux/uaccess.h>
> @@ -353,6 +354,7 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
>  		case PSCI_0_2_FN_SYSTEM_OFF:
>  		case PSCI_0_2_FN_SYSTEM_RESET:
>  		case PSCI_1_0_FN_PSCI_FEATURES:
> +		case ARM_SMCCC_VERSION_FUNC_ID:
>  			val = 0;
>  			break;
>  		default:
> @@ -407,7 +409,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
>   * Errors:
>   * -EINVAL: Unrecognized PSCI function
>   */
> -int kvm_psci_call(struct kvm_vcpu *vcpu)
> +static int kvm_psci_call(struct kvm_vcpu *vcpu)
>  {
>  	switch (kvm_psci_version(vcpu)) {
>  	case KVM_ARM_PSCI_1_0:
> @@ -421,6 +423,26 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
>  	};
>  }
>  
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
> +{
> +	u32 func_id = smccc_get_function(vcpu);
> +	u32 val;
> +
> +	switch (func_id) {
> +	case ARM_SMCCC_VERSION_FUNC_ID:
> +		val = ARM_SMCCC_VERSION_1_1;
> +		break;
> +	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
> +		val = -1;	/* Nothing supported yet */
> +		break;
> +	default:
> +		return kvm_psci_call(vcpu);
> +	}
> +
> +	smccc_set_retval(vcpu, val, 0, 0, 0);
> +	return 1;
> +}
> +
>  int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
>  {
>  	return 1;		/* PSCI version */
> -- 
> 2.14.2
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1
@ 2018-01-30  0:23     ` Russell King - ARM Linux
  0 siblings, 0 replies; 116+ messages in thread
From: Russell King - ARM Linux @ 2018-01-30  0:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 29, 2018 at 05:45:51PM +0000, Marc Zyngier wrote:
> The new SMC Calling Convention (v1.1) allows for a reduced overhead
> when calling into the firmware, and provides a new feature discovery
> mechanism.
> 
> Make it visible to KVM guests.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  Documentation/virtual/kvm/arm/psci.txt | 12 +++++++-----
>  arch/arm/kvm/handle_exit.c             |  2 +-
>  arch/arm64/kvm/handle_exit.c           |  2 +-
>  include/kvm/arm_psci.h                 |  2 +-
>  include/linux/arm-smccc.h              | 13 +++++++++++++
>  virt/kvm/arm/psci.c                    | 24 +++++++++++++++++++++++-
>  6 files changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> index 2e49a4e9f084..aafdab887b04 100644
> --- a/Documentation/virtual/kvm/arm/psci.txt
> +++ b/Documentation/virtual/kvm/arm/psci.txt
> @@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out of the
>  blue to an unsuspecting guest.
>  
>  In order to remedy this situation, KVM exposes a set of "firmware
> -pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> +pseudo-registers" that can be manipulated using the GET/SET_ONE_REG

This should surely be in patch 7?

>  interface. These registers can be saved/restored by userspace, and set
>  to a convenient value if required.
>  
> @@ -21,8 +21,10 @@ The following register is defined:
>  
>  * KVM_REG_ARM_PSCI_VERSION:
>  
> -  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> -  - Returns the current PSCI version on GET_ONE_REG
> -  - Allows any supported PSCI version compatible with v0.2 to be set
> -    with SET_ONE_REG
> +  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
> +    (and thus has already been initialized)
> +  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
> +    highest PSCI version implemented by KVM and compatible with v0.2)
> +  - Allows any PSCI version implemented by KVM and compatible with
> +    v0.2 to be set with SET_ONE_REG
>    - Affects the whole VM (even if the register view is per-vcpu)
> diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
> index e020cc82c4b1..a4520c7118d2 100644
> --- a/arch/arm/kvm/handle_exit.c
> +++ b/arch/arm/kvm/handle_exit.c
> @@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  		      kvm_vcpu_hvc_get_imm(vcpu));
>  	vcpu->stat.hvc_exit_stat++;
>  
> -	ret = kvm_psci_call(vcpu);
> +	ret = kvm_hvc_call_handler(vcpu);
>  	if (ret < 0) {
>  		vcpu_set_reg(vcpu, 0, ~0UL);
>  		return 1;
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 97e8d64a203d..bb6e1518d819 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  			    kvm_vcpu_hvc_get_imm(vcpu));
>  	vcpu->stat.hvc_exit_stat++;
>  
> -	ret = kvm_psci_call(vcpu);
> +	ret = kvm_hvc_call_handler(vcpu);
>  	if (ret < 0) {
>  		vcpu_set_reg(vcpu, 0, ~0UL);
>  		return 1;
> diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
> index f2fa7d752c4e..4876bfac2195 100644
> --- a/include/kvm/arm_psci.h
> +++ b/include/kvm/arm_psci.h
> @@ -26,7 +26,7 @@
>  #define KVM_ARM_PSCI_LATEST	KVM_ARM_PSCI_1_0
>  
>  int kvm_psci_version(struct kvm_vcpu *vcpu);
> -int kvm_psci_call(struct kvm_vcpu *vcpu);
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
>  
>  struct kvm_one_reg;
>  
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 4c5bca38c653..dc68aa5a7261 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -60,6 +60,19 @@
>  #define ARM_SMCCC_QUIRK_NONE		0
>  #define ARM_SMCCC_QUIRK_QCOM_A6		1 /* Save/restore register a6 */
>  
> +#define ARM_SMCCC_VERSION_1_0		0x10000
> +#define ARM_SMCCC_VERSION_1_1		0x10001
> +
> +#define ARM_SMCCC_VERSION_FUNC_ID					\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
> +			   ARM_SMCCC_SMC_32,				\
> +			   0, 0)
> +
> +#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID					\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
> +			   ARM_SMCCC_SMC_32,				\
> +			   0, 1)
> +
>  #ifndef __ASSEMBLY__
>  
>  #include <linux/linkage.h>
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index 682f9be6264b..3bb336ac7d7d 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -15,6 +15,7 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include <linux/arm-smccc.h>
>  #include <linux/preempt.h>
>  #include <linux/kvm_host.h>
>  #include <linux/uaccess.h>
> @@ -353,6 +354,7 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
>  		case PSCI_0_2_FN_SYSTEM_OFF:
>  		case PSCI_0_2_FN_SYSTEM_RESET:
>  		case PSCI_1_0_FN_PSCI_FEATURES:
> +		case ARM_SMCCC_VERSION_FUNC_ID:
>  			val = 0;
>  			break;
>  		default:
> @@ -407,7 +409,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
>   * Errors:
>   * -EINVAL: Unrecognized PSCI function
>   */
> -int kvm_psci_call(struct kvm_vcpu *vcpu)
> +static int kvm_psci_call(struct kvm_vcpu *vcpu)
>  {
>  	switch (kvm_psci_version(vcpu)) {
>  	case KVM_ARM_PSCI_1_0:
> @@ -421,6 +423,26 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
>  	};
>  }
>  
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
> +{
> +	u32 func_id = smccc_get_function(vcpu);
> +	u32 val;
> +
> +	switch (func_id) {
> +	case ARM_SMCCC_VERSION_FUNC_ID:
> +		val = ARM_SMCCC_VERSION_1_1;
> +		break;
> +	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
> +		val = -1;	/* Nothing supported yet */
> +		break;
> +	default:
> +		return kvm_psci_call(vcpu);
> +	}
> +
> +	smccc_set_retval(vcpu, val, 0, 0, 0);
> +	return 1;
> +}
> +
>  int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
>  {
>  	return 1;		/* PSCI version */
> -- 
> 2.14.2
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  2018-01-29 19:07     ` Robin Murphy
@ 2018-01-30  8:54       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30  8:54 UTC (permalink / raw)
  To: Robin Murphy, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Ard Biesheuvel, Jon Masters

On 29/01/18 19:07, Robin Murphy wrote:
> On 29/01/18 17:45, Marc Zyngier wrote:
>> One of the major improvement of SMCCC v1.1 is that it only clobbers
>> the first 4 registers, both on 32 and 64bit. This means that it
>> becomes very easy to provide an inline version of the SMC call
>> primitive, and avoid performing a function call to stash the
>> registers that would otherwise be clobbered by SMCCC v1.0.
> 
> This is disgusting... I love it :D

I expected nothing less from you! ;-)

> 
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 157 insertions(+)
>>
>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>> index dd44d8458c04..bc5843728909 100644
>> --- a/include/linux/arm-smccc.h
>> +++ b/include/linux/arm-smccc.h
>> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>>   
>>   #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>>   
>> +/* SMCCC v1.1 implementation madness follows */
>> +#ifdef CONFIG_ARM64
>> +
>> +#define SMCCC_SMC_INST	"smc	#0"
>> +#define SMCCC_HVC_INST	"hvc	#0"
>> +
>> +#define __arm_smccc_1_1_prologue(inst)					\
>> +	inst "\n"							\
>> +	"cbz	%[ptr], 1f\n"						\
>> +	"stp	%x[r0], %x[r1], %[ra0]\n"				\
>> +	"stp	%x[r2], %x[r3], %[ra2]\n"				\
>> +	"1:\n"								\
>> +	: [ra0] "=Ump" (*(&___res->a0)),				\
>> +	  [ra2] "=Ump" (*(&___res->a2)),
> 
> Rather than embedding a guaranteed spill to memory, I wonder if there's 
> money in just always declaring r0-r3 as in-out operands, and propagating 
> them by value afterwards, i.e.:
> 
> 	asm(...);
> 	if (___res)
> 		*___res = (struct arm_smccc_res){ r0, r1, r2, r3 };
> 
> In theory, for sufficiently simple callers that might allow res to stay 
> in registers for its entire lifetime and give nicer codegen. It *might* 
> also simplify some of this macro machinery too, although at this point 
> in the evening I can't really tell...

I just implemented it, and this is indeed much better. In most cases,
the store gets optimized away, mostly because we either pass NULL (and
the condition is dropped) or the store doesn't need to take place as we
evaluate a condition and discard the structure, like in
check_smccc_arch_workaround_1.

In all cases, this allows for slightly reduced levels of cpp madness,
and better codegen. I also suspect it will solve Ard's register
allocation issue.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-30  8:54       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30  8:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 19:07, Robin Murphy wrote:
> On 29/01/18 17:45, Marc Zyngier wrote:
>> One of the major improvement of SMCCC v1.1 is that it only clobbers
>> the first 4 registers, both on 32 and 64bit. This means that it
>> becomes very easy to provide an inline version of the SMC call
>> primitive, and avoid performing a function call to stash the
>> registers that would otherwise be clobbered by SMCCC v1.0.
> 
> This is disgusting... I love it :D

I expected nothing less from you! ;-)

> 
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 157 insertions(+)
>>
>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>> index dd44d8458c04..bc5843728909 100644
>> --- a/include/linux/arm-smccc.h
>> +++ b/include/linux/arm-smccc.h
>> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>>   
>>   #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>>   
>> +/* SMCCC v1.1 implementation madness follows */
>> +#ifdef CONFIG_ARM64
>> +
>> +#define SMCCC_SMC_INST	"smc	#0"
>> +#define SMCCC_HVC_INST	"hvc	#0"
>> +
>> +#define __arm_smccc_1_1_prologue(inst)					\
>> +	inst "\n"							\
>> +	"cbz	%[ptr], 1f\n"						\
>> +	"stp	%x[r0], %x[r1], %[ra0]\n"				\
>> +	"stp	%x[r2], %x[r3], %[ra2]\n"				\
>> +	"1:\n"								\
>> +	: [ra0] "=Ump" (*(&___res->a0)),				\
>> +	  [ra2] "=Ump" (*(&___res->a2)),
> 
> Rather than embedding a guaranteed spill to memory, I wonder if there's 
> money in just always declaring r0-r3 as in-out operands, and propagating 
> them by value afterwards, i.e.:
> 
> 	asm(...);
> 	if (___res)
> 		*___res = (struct arm_smccc_res){ r0, r1, r2, r3 };
> 
> In theory, for sufficiently simple callers that might allow res to stay 
> in registers for its entire lifetime and give nicer codegen. It *might* 
> also simplify some of this macro machinery too, although at this point 
> in the evening I can't really tell...

I just implemented it, and this is indeed much better. In most cases,
the store gets optimized away, mostly because we either pass NULL (and
the condition is dropped) or the store doesn't need to take place as we
evaluate a condition and discard the structure, like in
check_smccc_arch_workaround_1.

In all cases, this allows for slightly reduced levels of cpp madness,
and better codegen. I also suspect it will solve Ard's register
allocation issue.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
  2018-01-29 18:39     ` Lorenzo Pieralisi
@ 2018-01-30 12:09       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:09 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Catalin Marinas,
	Will Deacon, Peter Maydell, Christoffer Dall, Mark Rutland,
	Robin Murphy, Ard Biesheuvel, Jon Masters

On 29/01/18 18:39, Lorenzo Pieralisi wrote:
> On Mon, Jan 29, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
>> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
>> let's do that at boot time, and expose the version of the calling
>> convention as part of the psci_ops structure.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  drivers/firmware/psci.c | 21 +++++++++++++++++++++
>>  include/linux/psci.h    |  6 ++++++
>>  2 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
>> index e9493da2b111..dd035aaa1c33 100644
>> --- a/drivers/firmware/psci.c
>> +++ b/drivers/firmware/psci.c
>> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>>  	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>>  }
>>  
>> +static void __init psci_init_smccc(u32 ver)
>> +{
>> +	int feature = PSCI_RET_NOT_SUPPORTED;
>> +
>> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
>> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
>> +
>> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
>> +		psci_ops.variant = SMCCC_VARIANT_1_0;
>> +	} else {
>> +		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
>> +		if (ver != ARM_SMCCC_VERSION_1_1)
>> +			psci_ops.variant = SMCCC_VARIANT_1_0;
>> +		else
>> +			psci_ops.variant = SMCCC_VARIANT_1_1;
>> +	}
>> +
>> +	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
>> +}
>> +
>>  static void __init psci_0_2_set_functions(void)
>>  {
>>  	pr_info("Using standard PSCI v0.2 function IDs\n");
>> @@ -557,6 +577,7 @@ static int __init psci_probe(void)
>>  	psci_0_2_set_functions();
>>  
>>  	psci_init_migrate();
>> +	psci_init_smccc(ver);
> 
> Given that SMCCC_VARIANT_1_0 is already the default value (unless you do
> the same we did with the conduit) we can move psci_init_smccc() call
> inside the if below (that is there to detect a callable psci_features())
> and remove the check in psci_init_smccc(), up to you.

Yes, this makes sense.

> 
>>  
>>  	if (PSCI_VERSION_MAJOR(ver) >= 1) {
>>  		psci_init_cpu_suspend();
>> diff --git a/include/linux/psci.h b/include/linux/psci.h
>> index f2679e5faa4f..83fd16a37be3 100644
>> --- a/include/linux/psci.h
>> +++ b/include/linux/psci.h
>> @@ -31,6 +31,11 @@ enum psci_conduit {
>>  	PSCI_CONDUIT_HVC,
>>  };
>>  
>> +enum smccc_variant {
>> +	SMCCC_VARIANT_1_0,
>> +	SMCCC_VARIANT_1_1,
>> +};
>> +
>>  struct psci_operations {
>>  	u32 (*get_version)(void);
>>  	int (*cpu_suspend)(u32 state, unsigned long entry_point);
>> @@ -41,6 +46,7 @@ struct psci_operations {
>>  			unsigned long lowest_affinity_level);
>>  	int (*migrate_info_type)(void);
>>  	enum psci_conduit conduit;
>> +	enum smccc_variant variant;
> 
> Nit: I would add an smccc_ prefix to the variant field (or rename it
> to smccc_version).

I've renamed both the field and the enum to smccc_version (as well as
the members of the enum). This is definitely more consistent with the
symbols exposed by arm-smccc.h.

> 
> You can add my:
> 
> Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
@ 2018-01-30 12:09       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 18:39, Lorenzo Pieralisi wrote:
> On Mon, Jan 29, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
>> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
>> let's do that at boot time, and expose the version of the calling
>> convention as part of the psci_ops structure.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  drivers/firmware/psci.c | 21 +++++++++++++++++++++
>>  include/linux/psci.h    |  6 ++++++
>>  2 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
>> index e9493da2b111..dd035aaa1c33 100644
>> --- a/drivers/firmware/psci.c
>> +++ b/drivers/firmware/psci.c
>> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>>  	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>>  }
>>  
>> +static void __init psci_init_smccc(u32 ver)
>> +{
>> +	int feature = PSCI_RET_NOT_SUPPORTED;
>> +
>> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
>> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
>> +
>> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
>> +		psci_ops.variant = SMCCC_VARIANT_1_0;
>> +	} else {
>> +		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
>> +		if (ver != ARM_SMCCC_VERSION_1_1)
>> +			psci_ops.variant = SMCCC_VARIANT_1_0;
>> +		else
>> +			psci_ops.variant = SMCCC_VARIANT_1_1;
>> +	}
>> +
>> +	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
>> +}
>> +
>>  static void __init psci_0_2_set_functions(void)
>>  {
>>  	pr_info("Using standard PSCI v0.2 function IDs\n");
>> @@ -557,6 +577,7 @@ static int __init psci_probe(void)
>>  	psci_0_2_set_functions();
>>  
>>  	psci_init_migrate();
>> +	psci_init_smccc(ver);
> 
> Given that SMCCC_VARIANT_1_0 is already the default value (unless you do
> the same we did with the conduit) we can move psci_init_smccc() call
> inside the if below (that is there to detect a callable psci_features())
> and remove the check in psci_init_smccc(), up to you.

Yes, this makes sense.

> 
>>  
>>  	if (PSCI_VERSION_MAJOR(ver) >= 1) {
>>  		psci_init_cpu_suspend();
>> diff --git a/include/linux/psci.h b/include/linux/psci.h
>> index f2679e5faa4f..83fd16a37be3 100644
>> --- a/include/linux/psci.h
>> +++ b/include/linux/psci.h
>> @@ -31,6 +31,11 @@ enum psci_conduit {
>>  	PSCI_CONDUIT_HVC,
>>  };
>>  
>> +enum smccc_variant {
>> +	SMCCC_VARIANT_1_0,
>> +	SMCCC_VARIANT_1_1,
>> +};
>> +
>>  struct psci_operations {
>>  	u32 (*get_version)(void);
>>  	int (*cpu_suspend)(u32 state, unsigned long entry_point);
>> @@ -41,6 +46,7 @@ struct psci_operations {
>>  			unsigned long lowest_affinity_level);
>>  	int (*migrate_info_type)(void);
>>  	enum psci_conduit conduit;
>> +	enum smccc_variant variant;
> 
> Nit: I would add an smccc_ prefix to the variant field (or rename it
> to smccc_version).

I've renamed both the field and the enum to smccc_version (as well as
the members of the enum). This is definitely more consistent with the
symbols exposed by arm-smccc.h.

> 
> You can add my:
> 
> Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-29 19:41     ` Ard Biesheuvel
@ 2018-01-30 12:10       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:10 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 29/01/18 19:41, Ard Biesheuvel wrote:
> On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
>> It is lovely. Really.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm64/include/asm/kvm_psci.h | 63 ++++++++++++++++++++++++++++++++++++
>>  arch/arm64/kernel/bpi.S           | 20 ++++++++++++
>>  arch/arm64/kernel/cpu_errata.c    | 68 ++++++++++++++++++++++++++++++++++++++-
>>  3 files changed, 150 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/arm64/include/asm/kvm_psci.h
>>
>> diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
> 
> Did you mean to add this file? It is mostly identical to include/kvm/arm_psci.h

No, that's yet another patch splitting mistake. I'll drop it.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-30 12:10       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 19:41, Ard Biesheuvel wrote:
> On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
>> It is lovely. Really.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm64/include/asm/kvm_psci.h | 63 ++++++++++++++++++++++++++++++++++++
>>  arch/arm64/kernel/bpi.S           | 20 ++++++++++++
>>  arch/arm64/kernel/cpu_errata.c    | 68 ++++++++++++++++++++++++++++++++++++++-
>>  3 files changed, 150 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/arm64/include/asm/kvm_psci.h
>>
>> diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
> 
> Did you mean to add this file? It is mostly identical to include/kvm/arm_psci.h

No, that's yet another patch splitting mistake. I'll drop it.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  2018-01-29 21:45     ` Ard Biesheuvel
@ 2018-01-30 12:27       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:27 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 29/01/18 21:45, Ard Biesheuvel wrote:
> On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> One of the major improvement of SMCCC v1.1 is that it only clobbers
>> the first 4 registers, both on 32 and 64bit. This means that it
>> becomes very easy to provide an inline version of the SMC call
>> primitive, and avoid performing a function call to stash the
>> registers that would otherwise be clobbered by SMCCC v1.0.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 157 insertions(+)
>>
>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>> index dd44d8458c04..bc5843728909 100644
>> --- a/include/linux/arm-smccc.h
>> +++ b/include/linux/arm-smccc.h
>> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>>
>>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>>
>> +/* SMCCC v1.1 implementation madness follows */
>> +#ifdef CONFIG_ARM64
>> +
>> +#define SMCCC_SMC_INST "smc    #0"
>> +#define SMCCC_HVC_INST "hvc    #0"
>> +
>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>> +       inst "\n"                                                       \
>> +       "cbz    %[ptr], 1f\n"                                           \
>> +       "stp    %x[r0], %x[r1], %[ra0]\n"                               \
>> +       "stp    %x[r2], %x[r3], %[ra2]\n"                               \
>> +       "1:\n"                                                          \
>> +       : [ra0] "=Ump" (*(&___res->a0)),                                \
>> +         [ra2] "=Ump" (*(&___res->a2)),
>> +
>> +#define __arm_smccc_1_1_epilogue       : "memory"
>> +
>> +#endif
>> +
>> +#ifdef CONFIG_ARM
>> +#include <asm/opcodes-sec.h>
>> +#include <asm/opcodes-virt.h>
>> +
>> +#define SMCCC_SMC_INST __SMC(0)
>> +#define SMCCC_HVC_INST __HVC(0)
>> +
>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>> +       inst "\n"                                                       \
>> +       "cmp    %[ptr], #0\n"                                           \
>> +       "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"                 \
>> +       : "=m" (*___res),
>> +
>> +#define __arm_smccc_1_1_epilogue       : "memory", "cc"
>> +
>> +#endif
>> +
>> +#define __constraint_write_0                                           \
>> +       [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>> +#define __constraint_write_1                                           \
>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>> +#define __constraint_write_2                                           \
>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
>> +#define __constraint_write_3                                           \
>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
> 
> It seems you need +r for all arguments, otherwise the compiler will
> notice that the value is never used, and may assign the register to
> 'res' instead, i.e.,
> 
>  3e4:   320107e0        mov     w0, #0x80000001                 // #-2147483647
>  3e8:   320183e1        mov     w1, #0x80008000                 // #-2147450880
>  3ec:   910123a2        add     x2, x29, #0x48
>  3f0:   d4000002        hvc     #0x0
>  3f4:   b4000062        cbz     x2, 400 <enable_psci_bp_hardening+0x88>
>  3f8:   a90487a0        stp     x0, x1, [x29, #72]
>  3fc:   a9058fa2        stp     x2, x3, [x29, #88]
> 
> (for the code generated in the next patch)

Well spotted.

I think this is because of the lack of early-clobber for the unassigned
registers. The compiler assumes the whole sequence is a single
instruction, with the output registers being affected at the end. If we
mark those with '=&r', we will prevent GCC from emitting this kind of
horror.

Note that with Robin's trick of moving the assignment back to C code,
this is a bit moot as this is really a single instruction (smc/hvc), and
there is no intermediate register evaluation.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-30 12:27       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 21:45, Ard Biesheuvel wrote:
> On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> One of the major improvement of SMCCC v1.1 is that it only clobbers
>> the first 4 registers, both on 32 and 64bit. This means that it
>> becomes very easy to provide an inline version of the SMC call
>> primitive, and avoid performing a function call to stash the
>> registers that would otherwise be clobbered by SMCCC v1.0.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 157 insertions(+)
>>
>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>> index dd44d8458c04..bc5843728909 100644
>> --- a/include/linux/arm-smccc.h
>> +++ b/include/linux/arm-smccc.h
>> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>>
>>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>>
>> +/* SMCCC v1.1 implementation madness follows */
>> +#ifdef CONFIG_ARM64
>> +
>> +#define SMCCC_SMC_INST "smc    #0"
>> +#define SMCCC_HVC_INST "hvc    #0"
>> +
>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>> +       inst "\n"                                                       \
>> +       "cbz    %[ptr], 1f\n"                                           \
>> +       "stp    %x[r0], %x[r1], %[ra0]\n"                               \
>> +       "stp    %x[r2], %x[r3], %[ra2]\n"                               \
>> +       "1:\n"                                                          \
>> +       : [ra0] "=Ump" (*(&___res->a0)),                                \
>> +         [ra2] "=Ump" (*(&___res->a2)),
>> +
>> +#define __arm_smccc_1_1_epilogue       : "memory"
>> +
>> +#endif
>> +
>> +#ifdef CONFIG_ARM
>> +#include <asm/opcodes-sec.h>
>> +#include <asm/opcodes-virt.h>
>> +
>> +#define SMCCC_SMC_INST __SMC(0)
>> +#define SMCCC_HVC_INST __HVC(0)
>> +
>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>> +       inst "\n"                                                       \
>> +       "cmp    %[ptr], #0\n"                                           \
>> +       "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"                 \
>> +       : "=m" (*___res),
>> +
>> +#define __arm_smccc_1_1_epilogue       : "memory", "cc"
>> +
>> +#endif
>> +
>> +#define __constraint_write_0                                           \
>> +       [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>> +#define __constraint_write_1                                           \
>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>> +#define __constraint_write_2                                           \
>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
>> +#define __constraint_write_3                                           \
>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
> 
> It seems you need +r for all arguments, otherwise the compiler will
> notice that the value is never used, and may assign the register to
> 'res' instead, i.e.,
> 
>  3e4:   320107e0        mov     w0, #0x80000001                 // #-2147483647
>  3e8:   320183e1        mov     w1, #0x80008000                 // #-2147450880
>  3ec:   910123a2        add     x2, x29, #0x48
>  3f0:   d4000002        hvc     #0x0
>  3f4:   b4000062        cbz     x2, 400 <enable_psci_bp_hardening+0x88>
>  3f8:   a90487a0        stp     x0, x1, [x29, #72]
>  3fc:   a9058fa2        stp     x2, x3, [x29, #88]
> 
> (for the code generated in the next patch)

Well spotted.

I think this is because of the lack of early-clobber for the unassigned
registers. The compiler assumes the whole sequence is a single
instruction, with the output registers being affected at the end. If we
mark those with '=&r', we will prevent GCC from emitting this kind of
horror.

Note that with Robin's trick of moving the assignment back to C code,
this is a bit moot as this is really a single instruction (smc/hvc), and
there is no intermediate register evaluation.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1
  2018-01-30  0:23     ` Russell King - ARM Linux
  (?)
@ 2018-01-30 12:28       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:28 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Mark Rutland,
	Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Jon Masters, Robin Murphy,
	Christoffer Dall

On 30/01/18 00:23, Russell King - ARM Linux wrote:
> On Mon, Jan 29, 2018 at 05:45:51PM +0000, Marc Zyngier wrote:
>> The new SMC Calling Convention (v1.1) allows for a reduced overhead
>> when calling into the firmware, and provides a new feature discovery
>> mechanism.
>>
>> Make it visible to KVM guests.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  Documentation/virtual/kvm/arm/psci.txt | 12 +++++++-----
>>  arch/arm/kvm/handle_exit.c             |  2 +-
>>  arch/arm64/kvm/handle_exit.c           |  2 +-
>>  include/kvm/arm_psci.h                 |  2 +-
>>  include/linux/arm-smccc.h              | 13 +++++++++++++
>>  virt/kvm/arm/psci.c                    | 24 +++++++++++++++++++++++-
>>  6 files changed, 46 insertions(+), 9 deletions(-)
>>
>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
>> index 2e49a4e9f084..aafdab887b04 100644
>> --- a/Documentation/virtual/kvm/arm/psci.txt
>> +++ b/Documentation/virtual/kvm/arm/psci.txt
>> @@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out of the
>>  blue to an unsuspecting guest.
>>  
>>  In order to remedy this situation, KVM exposes a set of "firmware
>> -pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
>> +pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
> 
> This should surely be in patch 7?

Indeed. Thanks for the heads up.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1
@ 2018-01-30 12:28       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:28 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, linux-kernel, Christoffer Dall,
	Jon Masters, Robin Murphy, kvmarm, linux-arm-kernel

On 30/01/18 00:23, Russell King - ARM Linux wrote:
> On Mon, Jan 29, 2018 at 05:45:51PM +0000, Marc Zyngier wrote:
>> The new SMC Calling Convention (v1.1) allows for a reduced overhead
>> when calling into the firmware, and provides a new feature discovery
>> mechanism.
>>
>> Make it visible to KVM guests.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  Documentation/virtual/kvm/arm/psci.txt | 12 +++++++-----
>>  arch/arm/kvm/handle_exit.c             |  2 +-
>>  arch/arm64/kvm/handle_exit.c           |  2 +-
>>  include/kvm/arm_psci.h                 |  2 +-
>>  include/linux/arm-smccc.h              | 13 +++++++++++++
>>  virt/kvm/arm/psci.c                    | 24 +++++++++++++++++++++++-
>>  6 files changed, 46 insertions(+), 9 deletions(-)
>>
>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
>> index 2e49a4e9f084..aafdab887b04 100644
>> --- a/Documentation/virtual/kvm/arm/psci.txt
>> +++ b/Documentation/virtual/kvm/arm/psci.txt
>> @@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out of the
>>  blue to an unsuspecting guest.
>>  
>>  In order to remedy this situation, KVM exposes a set of "firmware
>> -pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
>> +pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
> 
> This should surely be in patch 7?

Indeed. Thanks for the heads up.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1
@ 2018-01-30 12:28       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/18 00:23, Russell King - ARM Linux wrote:
> On Mon, Jan 29, 2018 at 05:45:51PM +0000, Marc Zyngier wrote:
>> The new SMC Calling Convention (v1.1) allows for a reduced overhead
>> when calling into the firmware, and provides a new feature discovery
>> mechanism.
>>
>> Make it visible to KVM guests.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  Documentation/virtual/kvm/arm/psci.txt | 12 +++++++-----
>>  arch/arm/kvm/handle_exit.c             |  2 +-
>>  arch/arm64/kvm/handle_exit.c           |  2 +-
>>  include/kvm/arm_psci.h                 |  2 +-
>>  include/linux/arm-smccc.h              | 13 +++++++++++++
>>  virt/kvm/arm/psci.c                    | 24 +++++++++++++++++++++++-
>>  6 files changed, 46 insertions(+), 9 deletions(-)
>>
>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
>> index 2e49a4e9f084..aafdab887b04 100644
>> --- a/Documentation/virtual/kvm/arm/psci.txt
>> +++ b/Documentation/virtual/kvm/arm/psci.txt
>> @@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out of the
>>  blue to an unsuspecting guest.
>>  
>>  In order to remedy this situation, KVM exposes a set of "firmware
>> -pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
>> +pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
> 
> This should surely be in patch 7?

Indeed. Thanks for the heads up.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  2018-01-30 12:27       ` Marc Zyngier
  (?)
@ 2018-01-30 12:29         ` Ard Biesheuvel
  -1 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-30 12:29 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 30 January 2018 at 12:27, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 29/01/18 21:45, Ard Biesheuvel wrote:
>> On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>> One of the major improvement of SMCCC v1.1 is that it only clobbers
>>> the first 4 registers, both on 32 and 64bit. This means that it
>>> becomes very easy to provide an inline version of the SMC call
>>> primitive, and avoid performing a function call to stash the
>>> registers that would otherwise be clobbered by SMCCC v1.0.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 157 insertions(+)
>>>
>>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>>> index dd44d8458c04..bc5843728909 100644
>>> --- a/include/linux/arm-smccc.h
>>> +++ b/include/linux/arm-smccc.h
>>> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>>>
>>>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>>>
>>> +/* SMCCC v1.1 implementation madness follows */
>>> +#ifdef CONFIG_ARM64
>>> +
>>> +#define SMCCC_SMC_INST "smc    #0"
>>> +#define SMCCC_HVC_INST "hvc    #0"
>>> +
>>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>>> +       inst "\n"                                                       \
>>> +       "cbz    %[ptr], 1f\n"                                           \
>>> +       "stp    %x[r0], %x[r1], %[ra0]\n"                               \
>>> +       "stp    %x[r2], %x[r3], %[ra2]\n"                               \
>>> +       "1:\n"                                                          \
>>> +       : [ra0] "=Ump" (*(&___res->a0)),                                \
>>> +         [ra2] "=Ump" (*(&___res->a2)),
>>> +
>>> +#define __arm_smccc_1_1_epilogue       : "memory"
>>> +
>>> +#endif
>>> +
>>> +#ifdef CONFIG_ARM
>>> +#include <asm/opcodes-sec.h>
>>> +#include <asm/opcodes-virt.h>
>>> +
>>> +#define SMCCC_SMC_INST __SMC(0)
>>> +#define SMCCC_HVC_INST __HVC(0)
>>> +
>>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>>> +       inst "\n"                                                       \
>>> +       "cmp    %[ptr], #0\n"                                           \
>>> +       "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"                 \
>>> +       : "=m" (*___res),
>>> +
>>> +#define __arm_smccc_1_1_epilogue       : "memory", "cc"
>>> +
>>> +#endif
>>> +
>>> +#define __constraint_write_0                                           \
>>> +       [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_1                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_2                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_3                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
>>
>> It seems you need +r for all arguments, otherwise the compiler will
>> notice that the value is never used, and may assign the register to
>> 'res' instead, i.e.,
>>
>>  3e4:   320107e0        mov     w0, #0x80000001                 // #-2147483647
>>  3e8:   320183e1        mov     w1, #0x80008000                 // #-2147450880
>>  3ec:   910123a2        add     x2, x29, #0x48
>>  3f0:   d4000002        hvc     #0x0
>>  3f4:   b4000062        cbz     x2, 400 <enable_psci_bp_hardening+0x88>
>>  3f8:   a90487a0        stp     x0, x1, [x29, #72]
>>  3fc:   a9058fa2        stp     x2, x3, [x29, #88]
>>
>> (for the code generated in the next patch)
>
> Well spotted.
>
> I think this is because of the lack of early-clobber for the unassigned
> registers. The compiler assumes the whole sequence is a single
> instruction, with the output registers being affected at the end. If we
> mark those with '=&r', we will prevent GCC from emitting this kind of
> horror.
>

Tried that, actually, but it still doesn't help. It simply notices
that r2 (in this case) is not referenced after the asm () [nor before]
and so it simply seems to forget all about it, and reassigns it to
something else.

> Note that with Robin's trick of moving the assignment back to C code,
> this is a bit moot as this is really a single instruction (smc/hvc), and
> there is no intermediate register evaluation.
>

Yeah, that does look much better.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-30 12:29         ` Ard Biesheuvel
  0 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-30 12:29 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Catalin Marinas,
	Will Deacon, Linux Kernel Mailing List, Christoffer Dall,
	Jon Masters, Robin Murphy, kvmarm, linux-arm-kernel

On 30 January 2018 at 12:27, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 29/01/18 21:45, Ard Biesheuvel wrote:
>> On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>> One of the major improvement of SMCCC v1.1 is that it only clobbers
>>> the first 4 registers, both on 32 and 64bit. This means that it
>>> becomes very easy to provide an inline version of the SMC call
>>> primitive, and avoid performing a function call to stash the
>>> registers that would otherwise be clobbered by SMCCC v1.0.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 157 insertions(+)
>>>
>>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>>> index dd44d8458c04..bc5843728909 100644
>>> --- a/include/linux/arm-smccc.h
>>> +++ b/include/linux/arm-smccc.h
>>> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>>>
>>>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>>>
>>> +/* SMCCC v1.1 implementation madness follows */
>>> +#ifdef CONFIG_ARM64
>>> +
>>> +#define SMCCC_SMC_INST "smc    #0"
>>> +#define SMCCC_HVC_INST "hvc    #0"
>>> +
>>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>>> +       inst "\n"                                                       \
>>> +       "cbz    %[ptr], 1f\n"                                           \
>>> +       "stp    %x[r0], %x[r1], %[ra0]\n"                               \
>>> +       "stp    %x[r2], %x[r3], %[ra2]\n"                               \
>>> +       "1:\n"                                                          \
>>> +       : [ra0] "=Ump" (*(&___res->a0)),                                \
>>> +         [ra2] "=Ump" (*(&___res->a2)),
>>> +
>>> +#define __arm_smccc_1_1_epilogue       : "memory"
>>> +
>>> +#endif
>>> +
>>> +#ifdef CONFIG_ARM
>>> +#include <asm/opcodes-sec.h>
>>> +#include <asm/opcodes-virt.h>
>>> +
>>> +#define SMCCC_SMC_INST __SMC(0)
>>> +#define SMCCC_HVC_INST __HVC(0)
>>> +
>>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>>> +       inst "\n"                                                       \
>>> +       "cmp    %[ptr], #0\n"                                           \
>>> +       "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"                 \
>>> +       : "=m" (*___res),
>>> +
>>> +#define __arm_smccc_1_1_epilogue       : "memory", "cc"
>>> +
>>> +#endif
>>> +
>>> +#define __constraint_write_0                                           \
>>> +       [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_1                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_2                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_3                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
>>
>> It seems you need +r for all arguments, otherwise the compiler will
>> notice that the value is never used, and may assign the register to
>> 'res' instead, i.e.,
>>
>>  3e4:   320107e0        mov     w0, #0x80000001                 // #-2147483647
>>  3e8:   320183e1        mov     w1, #0x80008000                 // #-2147450880
>>  3ec:   910123a2        add     x2, x29, #0x48
>>  3f0:   d4000002        hvc     #0x0
>>  3f4:   b4000062        cbz     x2, 400 <enable_psci_bp_hardening+0x88>
>>  3f8:   a90487a0        stp     x0, x1, [x29, #72]
>>  3fc:   a9058fa2        stp     x2, x3, [x29, #88]
>>
>> (for the code generated in the next patch)
>
> Well spotted.
>
> I think this is because of the lack of early-clobber for the unassigned
> registers. The compiler assumes the whole sequence is a single
> instruction, with the output registers being affected at the end. If we
> mark those with '=&r', we will prevent GCC from emitting this kind of
> horror.
>

Tried that, actually, but it still doesn't help. It simply notices
that r2 (in this case) is not referenced after the asm () [nor before]
and so it simply seems to forget all about it, and reassigns it to
something else.

> Note that with Robin's trick of moving the assignment back to C code,
> this is a bit moot as this is really a single instruction (smc/hvc), and
> there is no intermediate register evaluation.
>

Yeah, that does look much better.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
@ 2018-01-30 12:29         ` Ard Biesheuvel
  0 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-30 12:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 30 January 2018 at 12:27, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 29/01/18 21:45, Ard Biesheuvel wrote:
>> On 29 January 2018 at 17:45, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>> One of the major improvement of SMCCC v1.1 is that it only clobbers
>>> the first 4 registers, both on 32 and 64bit. This means that it
>>> becomes very easy to provide an inline version of the SMC call
>>> primitive, and avoid performing a function call to stash the
>>> registers that would otherwise be clobbered by SMCCC v1.0.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/arm-smccc.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 157 insertions(+)
>>>
>>> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
>>> index dd44d8458c04..bc5843728909 100644
>>> --- a/include/linux/arm-smccc.h
>>> +++ b/include/linux/arm-smccc.h
>>> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>>>
>>>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>>>
>>> +/* SMCCC v1.1 implementation madness follows */
>>> +#ifdef CONFIG_ARM64
>>> +
>>> +#define SMCCC_SMC_INST "smc    #0"
>>> +#define SMCCC_HVC_INST "hvc    #0"
>>> +
>>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>>> +       inst "\n"                                                       \
>>> +       "cbz    %[ptr], 1f\n"                                           \
>>> +       "stp    %x[r0], %x[r1], %[ra0]\n"                               \
>>> +       "stp    %x[r2], %x[r3], %[ra2]\n"                               \
>>> +       "1:\n"                                                          \
>>> +       : [ra0] "=Ump" (*(&___res->a0)),                                \
>>> +         [ra2] "=Ump" (*(&___res->a2)),
>>> +
>>> +#define __arm_smccc_1_1_epilogue       : "memory"
>>> +
>>> +#endif
>>> +
>>> +#ifdef CONFIG_ARM
>>> +#include <asm/opcodes-sec.h>
>>> +#include <asm/opcodes-virt.h>
>>> +
>>> +#define SMCCC_SMC_INST __SMC(0)
>>> +#define SMCCC_HVC_INST __HVC(0)
>>> +
>>> +#define __arm_smccc_1_1_prologue(inst)                                 \
>>> +       inst "\n"                                                       \
>>> +       "cmp    %[ptr], #0\n"                                           \
>>> +       "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"                 \
>>> +       : "=m" (*___res),
>>> +
>>> +#define __arm_smccc_1_1_epilogue       : "memory", "cc"
>>> +
>>> +#endif
>>> +
>>> +#define __constraint_write_0                                           \
>>> +       [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_1                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_2                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
>>> +#define __constraint_write_3                                           \
>>> +       [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
>>
>> It seems you need +r for all arguments, otherwise the compiler will
>> notice that the value is never used, and may assign the register to
>> 'res' instead, i.e.,
>>
>>  3e4:   320107e0        mov     w0, #0x80000001                 // #-2147483647
>>  3e8:   320183e1        mov     w1, #0x80008000                 // #-2147450880
>>  3ec:   910123a2        add     x2, x29, #0x48
>>  3f0:   d4000002        hvc     #0x0
>>  3f4:   b4000062        cbz     x2, 400 <enable_psci_bp_hardening+0x88>
>>  3f8:   a90487a0        stp     x0, x1, [x29, #72]
>>  3fc:   a9058fa2        stp     x2, x3, [x29, #88]
>>
>> (for the code generated in the next patch)
>
> Well spotted.
>
> I think this is because of the lack of early-clobber for the unassigned
> registers. The compiler assumes the whole sequence is a single
> instruction, with the output registers being affected at the end. If we
> mark those with '=&r', we will prevent GCC from emitting this kind of
> horror.
>

Tried that, actually, but it still doesn't help. It simply notices
that r2 (in this case) is not referenced after the asm () [nor before]
and so it simply seems to forget all about it, and reassigns it to
something else.

> Note that with Robin's trick of moving the assignment back to C code,
> this is a bit moot as this is really a single instruction (smc/hvc), and
> there is no intermediate register evaluation.
>

Yeah, that does look much better.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 10/16] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-30 12:38     ` Robin Murphy
  -1 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-30 12:38 UTC (permalink / raw)
  To: Marc Zyngier, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Ard Biesheuvel, Jon Masters

On 29/01/18 17:45, Marc Zyngier wrote:
> A new feature of SMCCC 1.1 is that it offers firmware-based CPU
> workarounds. In particular, SMCCC_ARCH_WORKAROUND_1 provides
> BP hardening for CVE-2017-5715.
> 
> If the host has some mitigation for this issue, report that
> we deal with it using SMCCC_ARCH_WORKAROUND_1, as we apply the
> host workaround on every guest exit.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/linux/arm-smccc.h |  5 +++++
>   virt/kvm/arm/psci.c       | 17 +++++++++++++++--
>   2 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index dc68aa5a7261..e1ef944ef1da 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -73,6 +73,11 @@
>   			   ARM_SMCCC_SMC_32,				\
>   			   0, 1)
>   
> +#define ARM_SMCCC_ARCH_WORKAROUND_1					\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
> +			   ARM_SMCCC_SMC_32,				\
> +			   0, 0x8000)
> +
>   #ifndef __ASSEMBLY__
>   
>   #include <linux/linkage.h>
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index a021b62ed762..5677d16abc71 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -407,14 +407,27 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
>   int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
>   {
>   	u32 func_id = smccc_get_function(vcpu);
> -	u32 val;
> +	u32 val, feature;
>   
>   	switch (func_id) {
>   	case ARM_SMCCC_VERSION_FUNC_ID:
>   		val = ARM_SMCCC_VERSION_1_1;
>   		break;
>   	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
> -		val = -1;	/* Nothing supported yet */

Conceptually, might it still make sense to initialise val to 
NOT_SUPPORTED here, then overwrite it if and when a feature actually is 
present? It would in this case save a few lines as well, but I know 
multiple assignment can be one of those religious issues, so I'm not too 
fussed either way.

Robin.

> +		feature = smccc_get_arg1(vcpu);
> +		switch(feature) {
> +#ifdef CONFIG_ARM64
> +		case ARM_SMCCC_ARCH_WORKAROUND_1:
> +			if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR))
> +				val = 0;
> +			else
> +				val = -1;
> +			break;
> +#endif
> +		default:
> +			val = -1;
> +			break;
> +		}
>   		break;
>   	default:
>   		return kvm_psci_call(vcpu);
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 10/16] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-30 12:38     ` Robin Murphy
  0 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-30 12:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 17:45, Marc Zyngier wrote:
> A new feature of SMCCC 1.1 is that it offers firmware-based CPU
> workarounds. In particular, SMCCC_ARCH_WORKAROUND_1 provides
> BP hardening for CVE-2017-5715.
> 
> If the host has some mitigation for this issue, report that
> we deal with it using SMCCC_ARCH_WORKAROUND_1, as we apply the
> host workaround on every guest exit.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/linux/arm-smccc.h |  5 +++++
>   virt/kvm/arm/psci.c       | 17 +++++++++++++++--
>   2 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index dc68aa5a7261..e1ef944ef1da 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -73,6 +73,11 @@
>   			   ARM_SMCCC_SMC_32,				\
>   			   0, 1)
>   
> +#define ARM_SMCCC_ARCH_WORKAROUND_1					\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
> +			   ARM_SMCCC_SMC_32,				\
> +			   0, 0x8000)
> +
>   #ifndef __ASSEMBLY__
>   
>   #include <linux/linkage.h>
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index a021b62ed762..5677d16abc71 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -407,14 +407,27 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
>   int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
>   {
>   	u32 func_id = smccc_get_function(vcpu);
> -	u32 val;
> +	u32 val, feature;
>   
>   	switch (func_id) {
>   	case ARM_SMCCC_VERSION_FUNC_ID:
>   		val = ARM_SMCCC_VERSION_1_1;
>   		break;
>   	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
> -		val = -1;	/* Nothing supported yet */

Conceptually, might it still make sense to initialise val to 
NOT_SUPPORTED here, then overwrite it if and when a feature actually is 
present? It would in this case save a few lines as well, but I know 
multiple assignment can be one of those religious issues, so I'm not too 
fussed either way.

Robin.

> +		feature = smccc_get_arg1(vcpu);
> +		switch(feature) {
> +#ifdef CONFIG_ARM64
> +		case ARM_SMCCC_ARCH_WORKAROUND_1:
> +			if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR))
> +				val = 0;
> +			else
> +				val = -1;
> +			break;
> +#endif
> +		default:
> +			val = -1;
> +			break;
> +		}
>   		break;
>   	default:
>   		return kvm_psci_call(vcpu);
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-30 12:55     ` Robin Murphy
  -1 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-30 12:55 UTC (permalink / raw)
  To: Marc Zyngier, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Ard Biesheuvel, Jon Masters

On 29/01/18 17:45, Marc Zyngier wrote:
> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
> let's do that at boot time, and expose the version of the calling
> convention as part of the psci_ops structure.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   drivers/firmware/psci.c | 21 +++++++++++++++++++++
>   include/linux/psci.h    |  6 ++++++
>   2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index e9493da2b111..dd035aaa1c33 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>   	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>   }
>   
> +static void __init psci_init_smccc(u32 ver)
> +{
> +	int feature = PSCI_RET_NOT_SUPPORTED;
> +
> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
> +
> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
> +		psci_ops.variant = SMCCC_VARIANT_1_0;

Presumably at some point in the future we might want to update PSCI 
itself to use 'fast' calls if available, at which point this 
initialisation is a bit backwards given that you've already made a call 
using *some* convention. Even I think relying on the enum value working 
out OK is a bit subtle, so perhaps it's best to default-initialise 
psci_ops.variant to 1.0 (either statically, or dynamically before the 
first call), then only update it to 1.1 if and when we discover that.

Robin.

> +	} else {
> +		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
> +		if (ver != ARM_SMCCC_VERSION_1_1)
> +			psci_ops.variant = SMCCC_VARIANT_1_0;
> +		else
> +			psci_ops.variant = SMCCC_VARIANT_1_1;
> +	}
> +
> +	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
> +}
> +
>   static void __init psci_0_2_set_functions(void)
>   {
>   	pr_info("Using standard PSCI v0.2 function IDs\n");
> @@ -557,6 +577,7 @@ static int __init psci_probe(void)
>   	psci_0_2_set_functions();
>   
>   	psci_init_migrate();
> +	psci_init_smccc(ver);
>   
>   	if (PSCI_VERSION_MAJOR(ver) >= 1) {
>   		psci_init_cpu_suspend();
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f2679e5faa4f..83fd16a37be3 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -31,6 +31,11 @@ enum psci_conduit {
>   	PSCI_CONDUIT_HVC,
>   };
>   
> +enum smccc_variant {
> +	SMCCC_VARIANT_1_0,
> +	SMCCC_VARIANT_1_1,
> +};
> +
>   struct psci_operations {
>   	u32 (*get_version)(void);
>   	int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -41,6 +46,7 @@ struct psci_operations {
>   			unsigned long lowest_affinity_level);
>   	int (*migrate_info_type)(void);
>   	enum psci_conduit conduit;
> +	enum smccc_variant variant;
>   };
>   
>   extern struct psci_operations psci_ops;
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
@ 2018-01-30 12:55     ` Robin Murphy
  0 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-30 12:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 17:45, Marc Zyngier wrote:
> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
> let's do that at boot time, and expose the version of the calling
> convention as part of the psci_ops structure.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   drivers/firmware/psci.c | 21 +++++++++++++++++++++
>   include/linux/psci.h    |  6 ++++++
>   2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index e9493da2b111..dd035aaa1c33 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>   	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>   }
>   
> +static void __init psci_init_smccc(u32 ver)
> +{
> +	int feature = PSCI_RET_NOT_SUPPORTED;
> +
> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
> +
> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
> +		psci_ops.variant = SMCCC_VARIANT_1_0;

Presumably at some point in the future we might want to update PSCI 
itself to use 'fast' calls if available, at which point this 
initialisation is a bit backwards given that you've already made a call 
using *some* convention. Even I think relying on the enum value working 
out OK is a bit subtle, so perhaps it's best to default-initialise 
psci_ops.variant to 1.0 (either statically, or dynamically before the 
first call), then only update it to 1.1 if and when we discover that.

Robin.

> +	} else {
> +		ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
> +		if (ver != ARM_SMCCC_VERSION_1_1)
> +			psci_ops.variant = SMCCC_VARIANT_1_0;
> +		else
> +			psci_ops.variant = SMCCC_VARIANT_1_1;
> +	}
> +
> +	pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
> +}
> +
>   static void __init psci_0_2_set_functions(void)
>   {
>   	pr_info("Using standard PSCI v0.2 function IDs\n");
> @@ -557,6 +577,7 @@ static int __init psci_probe(void)
>   	psci_0_2_set_functions();
>   
>   	psci_init_migrate();
> +	psci_init_smccc(ver);
>   
>   	if (PSCI_VERSION_MAJOR(ver) >= 1) {
>   		psci_init_cpu_suspend();
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f2679e5faa4f..83fd16a37be3 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -31,6 +31,11 @@ enum psci_conduit {
>   	PSCI_CONDUIT_HVC,
>   };
>   
> +enum smccc_variant {
> +	SMCCC_VARIANT_1_0,
> +	SMCCC_VARIANT_1_1,
> +};
> +
>   struct psci_operations {
>   	u32 (*get_version)(void);
>   	int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -41,6 +46,7 @@ struct psci_operations {
>   			unsigned long lowest_affinity_level);
>   	int (*migrate_info_type)(void);
>   	enum psci_conduit conduit;
> +	enum smccc_variant variant;
>   };
>   
>   extern struct psci_operations psci_ops;
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-30 13:15     ` Robin Murphy
  -1 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-30 13:15 UTC (permalink / raw)
  To: Marc Zyngier, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Ard Biesheuvel, Jon Masters

On 29/01/18 17:45, Marc Zyngier wrote:
> As we're about to trigger a PSCI version explosion, it doesn't
> hurt to introduce a PSCI_VERSION helper that is going to be
> used everywhere.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/kvm/arm_psci.h | 5 +++--
>   virt/kvm/arm/psci.c    | 2 +-
>   2 files changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
> index 2042bb909474..3a408c846c09 100644
> --- a/include/kvm/arm_psci.h
> +++ b/include/kvm/arm_psci.h
> @@ -18,8 +18,9 @@
>   #ifndef __KVM_ARM_PSCI_H__
>   #define __KVM_ARM_PSCI_H__
>   
> -#define KVM_ARM_PSCI_0_1	1
> -#define KVM_ARM_PSCI_0_2	2
> +#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))

I see virt/kvm/arm/psci.c already pulls in uapi/linux/psci.h, so maybe 
this guy could go in there alongside the other PSCI_VERSION_* gubbins?

Robin.

> +#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
> +#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
>   
>   int kvm_psci_version(struct kvm_vcpu *vcpu);
>   int kvm_psci_call(struct kvm_vcpu *vcpu);
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index b322e46fd142..c00bb324e14e 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -222,7 +222,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
>   		 * Bits[31:16] = Major Version = 0
>   		 * Bits[15:0] = Minor Version = 2
>   		 */
> -		val = 2;
> +		val = KVM_ARM_PSCI_0_2;
>   		break;
>   	case PSCI_0_2_FN_CPU_SUSPEND:
>   	case PSCI_0_2_FN64_CPU_SUSPEND:
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper
@ 2018-01-30 13:15     ` Robin Murphy
  0 siblings, 0 replies; 116+ messages in thread
From: Robin Murphy @ 2018-01-30 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/01/18 17:45, Marc Zyngier wrote:
> As we're about to trigger a PSCI version explosion, it doesn't
> hurt to introduce a PSCI_VERSION helper that is going to be
> used everywhere.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   include/kvm/arm_psci.h | 5 +++--
>   virt/kvm/arm/psci.c    | 2 +-
>   2 files changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
> index 2042bb909474..3a408c846c09 100644
> --- a/include/kvm/arm_psci.h
> +++ b/include/kvm/arm_psci.h
> @@ -18,8 +18,9 @@
>   #ifndef __KVM_ARM_PSCI_H__
>   #define __KVM_ARM_PSCI_H__
>   
> -#define KVM_ARM_PSCI_0_1	1
> -#define KVM_ARM_PSCI_0_2	2
> +#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))

I see virt/kvm/arm/psci.c already pulls in uapi/linux/psci.h, so maybe 
this guy could go in there alongside the other PSCI_VERSION_* gubbins?

Robin.

> +#define KVM_ARM_PSCI_0_1	PSCI_VERSION(0, 1)
> +#define KVM_ARM_PSCI_0_2	PSCI_VERSION(0, 2)
>   
>   int kvm_psci_version(struct kvm_vcpu *vcpu);
>   int kvm_psci_call(struct kvm_vcpu *vcpu);
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index b322e46fd142..c00bb324e14e 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -222,7 +222,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
>   		 * Bits[31:16] = Major Version = 0
>   		 * Bits[15:0] = Minor Version = 2
>   		 */
> -		val = 2;
> +		val = KVM_ARM_PSCI_0_2;
>   		break;
>   	case PSCI_0_2_FN_CPU_SUSPEND:
>   	case PSCI_0_2_FN64_CPU_SUSPEND:
> 

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
  2018-01-30 12:55     ` Robin Murphy
@ 2018-01-30 13:51       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 13:51 UTC (permalink / raw)
  To: Robin Murphy, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Ard Biesheuvel, Jon Masters

On 30/01/18 12:55, Robin Murphy wrote:
> On 29/01/18 17:45, Marc Zyngier wrote:
>> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
>> let's do that at boot time, and expose the version of the calling
>> convention as part of the psci_ops structure.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   drivers/firmware/psci.c | 21 +++++++++++++++++++++
>>   include/linux/psci.h    |  6 ++++++
>>   2 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
>> index e9493da2b111..dd035aaa1c33 100644
>> --- a/drivers/firmware/psci.c
>> +++ b/drivers/firmware/psci.c
>> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>>   	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>>   }
>>   
>> +static void __init psci_init_smccc(u32 ver)
>> +{
>> +	int feature = PSCI_RET_NOT_SUPPORTED;
>> +
>> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
>> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
>> +
>> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
>> +		psci_ops.variant = SMCCC_VARIANT_1_0;
> 
> Presumably at some point in the future we might want to update PSCI 
> itself to use 'fast' calls if available, at which point this 
> initialisation is a bit backwards given that you've already made a call 
> using *some* convention. Even I think relying on the enum value working 
> out OK is a bit subtle, so perhaps it's best to default-initialise 
> psci_ops.variant to 1.0 (either statically, or dynamically before the 
> first call), then only update it to 1.1 if and when we discover that.

Indeed. Lorenzo already suggested something along those lines, and I now
(statically) default to 1.0.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops
@ 2018-01-30 13:51       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 13:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/18 12:55, Robin Murphy wrote:
> On 29/01/18 17:45, Marc Zyngier wrote:
>> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
>> let's do that at boot time, and expose the version of the calling
>> convention as part of the psci_ops structure.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   drivers/firmware/psci.c | 21 +++++++++++++++++++++
>>   include/linux/psci.h    |  6 ++++++
>>   2 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
>> index e9493da2b111..dd035aaa1c33 100644
>> --- a/drivers/firmware/psci.c
>> +++ b/drivers/firmware/psci.c
>> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>>   	pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>>   }
>>   
>> +static void __init psci_init_smccc(u32 ver)
>> +{
>> +	int feature = PSCI_RET_NOT_SUPPORTED;
>> +
>> +	if (PSCI_VERSION_MAJOR(ver) >= 1)
>> +		feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
>> +
>> +	if (feature == PSCI_RET_NOT_SUPPORTED) {
>> +		psci_ops.variant = SMCCC_VARIANT_1_0;
> 
> Presumably at some point in the future we might want to update PSCI 
> itself to use 'fast' calls if available, at which point this 
> initialisation is a bit backwards given that you've already made a call 
> using *some* convention. Even I think relying on the enum value working 
> out OK is a bit subtle, so perhaps it's best to default-initialise 
> psci_ops.variant to 1.0 (either statically, or dynamically before the 
> first call), then only update it to 1.1 if and when we discover that.

Indeed. Lorenzo already suggested something along those lines, and I now
(statically) default to 1.0.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper
  2018-01-30 13:15     ` Robin Murphy
@ 2018-01-30 14:52       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 14:52 UTC (permalink / raw)
  To: Robin Murphy, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Ard Biesheuvel, Jon Masters

On 30/01/18 13:15, Robin Murphy wrote:
> On 29/01/18 17:45, Marc Zyngier wrote:
>> As we're about to trigger a PSCI version explosion, it doesn't
>> hurt to introduce a PSCI_VERSION helper that is going to be
>> used everywhere.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   include/kvm/arm_psci.h | 5 +++--
>>   virt/kvm/arm/psci.c    | 2 +-
>>   2 files changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
>> index 2042bb909474..3a408c846c09 100644
>> --- a/include/kvm/arm_psci.h
>> +++ b/include/kvm/arm_psci.h
>> @@ -18,8 +18,9 @@
>>   #ifndef __KVM_ARM_PSCI_H__
>>   #define __KVM_ARM_PSCI_H__
>>   
>> -#define KVM_ARM_PSCI_0_1	1
>> -#define KVM_ARM_PSCI_0_2	2
>> +#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
> 
> I see virt/kvm/arm/psci.c already pulls in uapi/linux/psci.h, so maybe 
> this guy could go in there alongside the other PSCI_VERSION_* gubbins?

Good point. Moved.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper
@ 2018-01-30 14:52       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-30 14:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/01/18 13:15, Robin Murphy wrote:
> On 29/01/18 17:45, Marc Zyngier wrote:
>> As we're about to trigger a PSCI version explosion, it doesn't
>> hurt to introduce a PSCI_VERSION helper that is going to be
>> used everywhere.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>   include/kvm/arm_psci.h | 5 +++--
>>   virt/kvm/arm/psci.c    | 2 +-
>>   2 files changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
>> index 2042bb909474..3a408c846c09 100644
>> --- a/include/kvm/arm_psci.h
>> +++ b/include/kvm/arm_psci.h
>> @@ -18,8 +18,9 @@
>>   #ifndef __KVM_ARM_PSCI_H__
>>   #define __KVM_ARM_PSCI_H__
>>   
>> -#define KVM_ARM_PSCI_0_1	1
>> -#define KVM_ARM_PSCI_0_2	2
>> +#define PSCI_VERSION(x,y)	((((x) & 0x7fff) << 16) | ((y) & 0xffff))
> 
> I see virt/kvm/arm/psci.c already pulls in uapi/linux/psci.h, so maybe 
> this guy could go in there alongside the other PSCI_VERSION_* gubbins?

Good point. Moved.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-29 17:45   ` Marc Zyngier
  (?)
@ 2018-01-31 13:56     ` Hanjun Guo
  -1 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-01-31 13:56 UTC (permalink / raw)
  To: Marc Zyngier, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Hi Marc,

On 2018/1/30 1:45, Marc Zyngier wrote:
>  static int enable_psci_bp_hardening(void *data)
>  {
>  	const struct arm64_cpu_capabilities *entry = data;
>  
> -	if (psci_ops.get_version)
> +	if (psci_ops.get_version) {
> +		if (check_smccc_arch_workaround_1(entry))
> +			return 0;

If I'm using the new version SMCCC, the firmware have the choice to decide
whether this machine needs the workaround, even if the CPU is vulnerable
for CVE-2017-5715, but..

> +
>  		install_bp_hardening_cb(entry,
>  				       (bp_hardening_cb_t)psci_ops.get_version,
>  				       __psci_hyp_bp_inval_start,
>  				       __psci_hyp_bp_inval_end);

..the code above seems will enable get_psci_version() for CPU and will
trap to trust firmware even the new version of firmware didn't say
we need the workaround, did I understand it correctly?

I'm ask this because some platform will not expose to users to
take advantage of CVE-2017-5715, and we can use different firmware
to report we need such workaround or not, then use a single kernel
image for both vulnerable platforms and no vulnerable ones.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-31 13:56     ` Hanjun Guo
  0 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-01-31 13:56 UTC (permalink / raw)
  To: Marc Zyngier, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Hi Marc,

On 2018/1/30 1:45, Marc Zyngier wrote:
>  static int enable_psci_bp_hardening(void *data)
>  {
>  	const struct arm64_cpu_capabilities *entry = data;
>  
> -	if (psci_ops.get_version)
> +	if (psci_ops.get_version) {
> +		if (check_smccc_arch_workaround_1(entry))
> +			return 0;

If I'm using the new version SMCCC, the firmware have the choice to decide
whether this machine needs the workaround, even if the CPU is vulnerable
for CVE-2017-5715, but..

> +
>  		install_bp_hardening_cb(entry,
>  				       (bp_hardening_cb_t)psci_ops.get_version,
>  				       __psci_hyp_bp_inval_start,
>  				       __psci_hyp_bp_inval_end);

..the code above seems will enable get_psci_version() for CPU and will
trap to trust firmware even the new version of firmware didn't say
we need the workaround, did I understand it correctly?

I'm ask this because some platform will not expose to users to
take advantage of CVE-2017-5715, and we can use different firmware
to report we need such workaround or not, then use a single kernel
image for both vulnerable platforms and no vulnerable ones.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-31 13:56     ` Hanjun Guo
  0 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-01-31 13:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 2018/1/30 1:45, Marc Zyngier wrote:
>  static int enable_psci_bp_hardening(void *data)
>  {
>  	const struct arm64_cpu_capabilities *entry = data;
>  
> -	if (psci_ops.get_version)
> +	if (psci_ops.get_version) {
> +		if (check_smccc_arch_workaround_1(entry))
> +			return 0;

If I'm using the new version SMCCC, the firmware have the choice to decide
whether this machine needs the workaround, even if the CPU is vulnerable
for CVE-2017-5715, but..

> +
>  		install_bp_hardening_cb(entry,
>  				       (bp_hardening_cb_t)psci_ops.get_version,
>  				       __psci_hyp_bp_inval_start,
>  				       __psci_hyp_bp_inval_end);

..the code above seems will enable get_psci_version() for CPU and will
trap to trust firmware even the new version of firmware didn't say
we need the workaround, did I understand it correctly?

I'm ask this because some platform will not expose to users to
take advantage of CVE-2017-5715, and we can use different firmware
to report we need such workaround or not, then use a single kernel
image for both vulnerable platforms and no vulnerable ones.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-31 13:56     ` Hanjun Guo
@ 2018-01-31 14:11       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 14:11 UTC (permalink / raw)
  To: Hanjun Guo, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

On 31/01/18 13:56, Hanjun Guo wrote:
> Hi Marc,
> 
> On 2018/1/30 1:45, Marc Zyngier wrote:
>>  static int enable_psci_bp_hardening(void *data)
>>  {
>>  	const struct arm64_cpu_capabilities *entry = data;
>>  
>> -	if (psci_ops.get_version)
>> +	if (psci_ops.get_version) {
>> +		if (check_smccc_arch_workaround_1(entry))
>> +			return 0;
> 
> If I'm using the new version SMCCC, the firmware have the choice to decide
> whether this machine needs the workaround, even if the CPU is vulnerable
> for CVE-2017-5715, but..
> 
>> +
>>  		install_bp_hardening_cb(entry,
>>  				       (bp_hardening_cb_t)psci_ops.get_version,
>>  				       __psci_hyp_bp_inval_start,
>>  				       __psci_hyp_bp_inval_end);
> 
> ..the code above seems will enable get_psci_version() for CPU and will
> trap to trust firmware even the new version of firmware didn't say
> we need the workaround, did I understand it correctly?

Well, you only get there if we've established that your CPU is affected
(it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
capability), and that entry points to enable_psci_bp_hardening. It is
not the firmware that decides whether we need hardening, but the kernel.
The firmware merely provides a facility to apply the hardening.

> I'm ask this because some platform will not expose to users to
> take advantage of CVE-2017-5715, and we can use different firmware
> to report we need such workaround or not, then use a single kernel
> image for both vulnerable platforms and no vulnerable ones.

You cannot have your cake and eat it. If you don't want to workaround
the issue, you can disable the hardening. But asking for the same kernel
to do both depending on what the firmware reports doesn't make much
sense to me.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-31 14:11       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 14:11 UTC (permalink / raw)
  To: linux-arm-kernel

On 31/01/18 13:56, Hanjun Guo wrote:
> Hi Marc,
> 
> On 2018/1/30 1:45, Marc Zyngier wrote:
>>  static int enable_psci_bp_hardening(void *data)
>>  {
>>  	const struct arm64_cpu_capabilities *entry = data;
>>  
>> -	if (psci_ops.get_version)
>> +	if (psci_ops.get_version) {
>> +		if (check_smccc_arch_workaround_1(entry))
>> +			return 0;
> 
> If I'm using the new version SMCCC, the firmware have the choice to decide
> whether this machine needs the workaround, even if the CPU is vulnerable
> for CVE-2017-5715, but..
> 
>> +
>>  		install_bp_hardening_cb(entry,
>>  				       (bp_hardening_cb_t)psci_ops.get_version,
>>  				       __psci_hyp_bp_inval_start,
>>  				       __psci_hyp_bp_inval_end);
> 
> ..the code above seems will enable get_psci_version() for CPU and will
> trap to trust firmware even the new version of firmware didn't say
> we need the workaround, did I understand it correctly?

Well, you only get there if we've established that your CPU is affected
(it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
capability), and that entry points to enable_psci_bp_hardening. It is
not the firmware that decides whether we need hardening, but the kernel.
The firmware merely provides a facility to apply the hardening.

> I'm ask this because some platform will not expose to users to
> take advantage of CVE-2017-5715, and we can use different firmware
> to report we need such workaround or not, then use a single kernel
> image for both vulnerable platforms and no vulnerable ones.

You cannot have your cake and eat it. If you don't want to workaround
the issue, you can disable the hardening. But asking for the same kernel
to do both depending on what the firmware reports doesn't make much
sense to me.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-31 14:11       ` Marc Zyngier
@ 2018-01-31 14:35         ` Ard Biesheuvel
  -1 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-31 14:35 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Hanjun Guo, Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 31/01/18 13:56, Hanjun Guo wrote:
>> Hi Marc,
>>
>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>  static int enable_psci_bp_hardening(void *data)
>>>  {
>>>      const struct arm64_cpu_capabilities *entry = data;
>>>
>>> -    if (psci_ops.get_version)
>>> +    if (psci_ops.get_version) {
>>> +            if (check_smccc_arch_workaround_1(entry))
>>> +                    return 0;
>>
>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>> whether this machine needs the workaround, even if the CPU is vulnerable
>> for CVE-2017-5715, but..
>>
>>> +
>>>              install_bp_hardening_cb(entry,
>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>                                     __psci_hyp_bp_inval_start,
>>>                                     __psci_hyp_bp_inval_end);
>>
>> ..the code above seems will enable get_psci_version() for CPU and will
>> trap to trust firmware even the new version of firmware didn't say
>> we need the workaround, did I understand it correctly?
>
> Well, you only get there if we've established that your CPU is affected
> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
> capability), and that entry points to enable_psci_bp_hardening. It is
> not the firmware that decides whether we need hardening, but the kernel.
> The firmware merely provides a facility to apply the hardening.
>
>> I'm ask this because some platform will not expose to users to
>> take advantage of CVE-2017-5715, and we can use different firmware
>> to report we need such workaround or not, then use a single kernel
>> image for both vulnerable platforms and no vulnerable ones.
>
> You cannot have your cake and eat it. If you don't want to workaround
> the issue, you can disable the hardening. But asking for the same kernel
> to do both depending on what the firmware reports doesn't make much
> sense to me.

The SMCCC v1.1. document does appear to imply that systems that
implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
should be assumed to be unaffected.

"""
If the discovery call returns NOT_SUPPORTED:
• SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
• none of the PEs in the system require firmware mitigation for CVE-2017-5715.
"""

How to deal with conflicting information in this regard (quirk table
vs firmware implementation) is a matter of policy, of course.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-31 14:35         ` Ard Biesheuvel
  0 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-31 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 31/01/18 13:56, Hanjun Guo wrote:
>> Hi Marc,
>>
>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>  static int enable_psci_bp_hardening(void *data)
>>>  {
>>>      const struct arm64_cpu_capabilities *entry = data;
>>>
>>> -    if (psci_ops.get_version)
>>> +    if (psci_ops.get_version) {
>>> +            if (check_smccc_arch_workaround_1(entry))
>>> +                    return 0;
>>
>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>> whether this machine needs the workaround, even if the CPU is vulnerable
>> for CVE-2017-5715, but..
>>
>>> +
>>>              install_bp_hardening_cb(entry,
>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>                                     __psci_hyp_bp_inval_start,
>>>                                     __psci_hyp_bp_inval_end);
>>
>> ..the code above seems will enable get_psci_version() for CPU and will
>> trap to trust firmware even the new version of firmware didn't say
>> we need the workaround, did I understand it correctly?
>
> Well, you only get there if we've established that your CPU is affected
> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
> capability), and that entry points to enable_psci_bp_hardening. It is
> not the firmware that decides whether we need hardening, but the kernel.
> The firmware merely provides a facility to apply the hardening.
>
>> I'm ask this because some platform will not expose to users to
>> take advantage of CVE-2017-5715, and we can use different firmware
>> to report we need such workaround or not, then use a single kernel
>> image for both vulnerable platforms and no vulnerable ones.
>
> You cannot have your cake and eat it. If you don't want to workaround
> the issue, you can disable the hardening. But asking for the same kernel
> to do both depending on what the firmware reports doesn't make much
> sense to me.

The SMCCC v1.1. document does appear to imply that systems that
implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
should be assumed to be unaffected.

"""
If the discovery call returns NOT_SUPPORTED:
? SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
? none of the PEs in the system require firmware mitigation for CVE-2017-5715.
"""

How to deal with conflicting information in this regard (quirk table
vs firmware implementation) is a matter of policy, of course.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-31 14:35         ` Ard Biesheuvel
@ 2018-01-31 14:38           ` Ard Biesheuvel
  -1 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-31 14:38 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Hanjun Guo, Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> On 31/01/18 13:56, Hanjun Guo wrote:
>>> Hi Marc,
>>>
>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>  static int enable_psci_bp_hardening(void *data)
>>>>  {
>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>
>>>> -    if (psci_ops.get_version)
>>>> +    if (psci_ops.get_version) {
>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>> +                    return 0;
>>>
>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>> for CVE-2017-5715, but..
>>>
>>>> +
>>>>              install_bp_hardening_cb(entry,
>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>                                     __psci_hyp_bp_inval_start,
>>>>                                     __psci_hyp_bp_inval_end);
>>>
>>> ..the code above seems will enable get_psci_version() for CPU and will
>>> trap to trust firmware even the new version of firmware didn't say
>>> we need the workaround, did I understand it correctly?
>>
>> Well, you only get there if we've established that your CPU is affected
>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>> capability), and that entry points to enable_psci_bp_hardening. It is
>> not the firmware that decides whether we need hardening, but the kernel.
>> The firmware merely provides a facility to apply the hardening.
>>
>>> I'm ask this because some platform will not expose to users to
>>> take advantage of CVE-2017-5715, and we can use different firmware
>>> to report we need such workaround or not, then use a single kernel
>>> image for both vulnerable platforms and no vulnerable ones.
>>
>> You cannot have your cake and eat it. If you don't want to workaround
>> the issue, you can disable the hardening. But asking for the same kernel
>> to do both depending on what the firmware reports doesn't make much
>> sense to me.
>
> The SMCCC v1.1. document does appear to imply that systems that
> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
> should be assumed to be unaffected.
>
> """
> If the discovery call returns NOT_SUPPORTED:
> • SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
> • none of the PEs in the system require firmware mitigation for CVE-2017-5715.
> """
>
> How to deal with conflicting information in this regard (quirk table
> vs firmware implementation) is a matter of policy, of course.

... and actually, perhaps it makes sense for the
SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
based errata matching?

I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
we should probably invoke it even if the MIDR is not known to belong
to an affected implementation.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-31 14:38           ` Ard Biesheuvel
  0 siblings, 0 replies; 116+ messages in thread
From: Ard Biesheuvel @ 2018-01-31 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> On 31/01/18 13:56, Hanjun Guo wrote:
>>> Hi Marc,
>>>
>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>  static int enable_psci_bp_hardening(void *data)
>>>>  {
>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>
>>>> -    if (psci_ops.get_version)
>>>> +    if (psci_ops.get_version) {
>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>> +                    return 0;
>>>
>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>> for CVE-2017-5715, but..
>>>
>>>> +
>>>>              install_bp_hardening_cb(entry,
>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>                                     __psci_hyp_bp_inval_start,
>>>>                                     __psci_hyp_bp_inval_end);
>>>
>>> ..the code above seems will enable get_psci_version() for CPU and will
>>> trap to trust firmware even the new version of firmware didn't say
>>> we need the workaround, did I understand it correctly?
>>
>> Well, you only get there if we've established that your CPU is affected
>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>> capability), and that entry points to enable_psci_bp_hardening. It is
>> not the firmware that decides whether we need hardening, but the kernel.
>> The firmware merely provides a facility to apply the hardening.
>>
>>> I'm ask this because some platform will not expose to users to
>>> take advantage of CVE-2017-5715, and we can use different firmware
>>> to report we need such workaround or not, then use a single kernel
>>> image for both vulnerable platforms and no vulnerable ones.
>>
>> You cannot have your cake and eat it. If you don't want to workaround
>> the issue, you can disable the hardening. But asking for the same kernel
>> to do both depending on what the firmware reports doesn't make much
>> sense to me.
>
> The SMCCC v1.1. document does appear to imply that systems that
> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
> should be assumed to be unaffected.
>
> """
> If the discovery call returns NOT_SUPPORTED:
> ? SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
> ? none of the PEs in the system require firmware mitigation for CVE-2017-5715.
> """
>
> How to deal with conflicting information in this regard (quirk table
> vs firmware implementation) is a matter of policy, of course.

... and actually, perhaps it makes sense for the
SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
based errata matching?

I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
we should probably invoke it even if the MIDR is not known to belong
to an affected implementation.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-31 14:38           ` Ard Biesheuvel
@ 2018-01-31 15:05             ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 15:05 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Hanjun Guo, Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 31/01/18 14:38, Ard Biesheuvel wrote:
> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>> Hi Marc,
>>>>
>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>  {
>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>
>>>>> -    if (psci_ops.get_version)
>>>>> +    if (psci_ops.get_version) {
>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>> +                    return 0;
>>>>
>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>> for CVE-2017-5715, but..
>>>>
>>>>> +
>>>>>              install_bp_hardening_cb(entry,
>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>                                     __psci_hyp_bp_inval_end);
>>>>
>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>> trap to trust firmware even the new version of firmware didn't say
>>>> we need the workaround, did I understand it correctly?
>>>
>>> Well, you only get there if we've established that your CPU is affected
>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>> capability), and that entry points to enable_psci_bp_hardening. It is
>>> not the firmware that decides whether we need hardening, but the kernel.
>>> The firmware merely provides a facility to apply the hardening.
>>>
>>>> I'm ask this because some platform will not expose to users to
>>>> take advantage of CVE-2017-5715, and we can use different firmware
>>>> to report we need such workaround or not, then use a single kernel
>>>> image for both vulnerable platforms and no vulnerable ones.
>>>
>>> You cannot have your cake and eat it. If you don't want to workaround
>>> the issue, you can disable the hardening. But asking for the same kernel
>>> to do both depending on what the firmware reports doesn't make much
>>> sense to me.
>>
>> The SMCCC v1.1. document does appear to imply that systems that
>> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
>> should be assumed to be unaffected.
>>
>> """
>> If the discovery call returns NOT_SUPPORTED:
>> • SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
>> • none of the PEs in the system require firmware mitigation for CVE-2017-5715.
>> """
>>
>> How to deal with conflicting information in this regard (quirk table
>> vs firmware implementation) is a matter of policy, of course.

Yup. And the current approach fits the spec, I believe. The
PSCI_GET_VERSION band-aid should normally be removed shortly after these
patches hit mainline.

> 
> ... and actually, perhaps it makes sense for the
> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
> based errata matching?
> 
> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
> we should probably invoke it even if the MIDR is not known to belong
> to an affected implementation.

This would have an impact on big-little systems, for which there is
often a bunch of unaffected CPUs.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-01-31 15:05             ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 15:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 31/01/18 14:38, Ard Biesheuvel wrote:
> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>> Hi Marc,
>>>>
>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>  {
>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>
>>>>> -    if (psci_ops.get_version)
>>>>> +    if (psci_ops.get_version) {
>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>> +                    return 0;
>>>>
>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>> for CVE-2017-5715, but..
>>>>
>>>>> +
>>>>>              install_bp_hardening_cb(entry,
>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>                                     __psci_hyp_bp_inval_end);
>>>>
>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>> trap to trust firmware even the new version of firmware didn't say
>>>> we need the workaround, did I understand it correctly?
>>>
>>> Well, you only get there if we've established that your CPU is affected
>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>> capability), and that entry points to enable_psci_bp_hardening. It is
>>> not the firmware that decides whether we need hardening, but the kernel.
>>> The firmware merely provides a facility to apply the hardening.
>>>
>>>> I'm ask this because some platform will not expose to users to
>>>> take advantage of CVE-2017-5715, and we can use different firmware
>>>> to report we need such workaround or not, then use a single kernel
>>>> image for both vulnerable platforms and no vulnerable ones.
>>>
>>> You cannot have your cake and eat it. If you don't want to workaround
>>> the issue, you can disable the hardening. But asking for the same kernel
>>> to do both depending on what the firmware reports doesn't make much
>>> sense to me.
>>
>> The SMCCC v1.1. document does appear to imply that systems that
>> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
>> should be assumed to be unaffected.
>>
>> """
>> If the discovery call returns NOT_SUPPORTED:
>> ? SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
>> ? none of the PEs in the system require firmware mitigation for CVE-2017-5715.
>> """
>>
>> How to deal with conflicting information in this regard (quirk table
>> vs firmware implementation) is a matter of policy, of course.

Yup. And the current approach fits the spec, I believe. The
PSCI_GET_VERSION band-aid should normally be removed shortly after these
patches hit mainline.

> 
> ... and actually, perhaps it makes sense for the
> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
> based errata matching?
> 
> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
> we should probably invoke it even if the MIDR is not known to belong
> to an affected implementation.

This would have an impact on big-little systems, for which there is
often a bunch of unaffected CPUs.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-31 17:38     ` Andrew Jones
  -1 siblings, 0 replies; 116+ messages in thread
From: Andrew Jones @ 2018-01-31 17:38 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Lorenzo Pieralisi,
	Ard Biesheuvel, Catalin Marinas, Will Deacon, Jon Masters,
	Robin Murphy

On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
> Since all the new PSCI versions are backward compatible, we decide to
> default to the latest version of the PSCI implementation. This is no
> different from doing a firmware upgrade on KVM.
> 
> But in order to give a chance to hypothetical badly implemented guests
> that would have a fit by discovering something other than PSCI 0.2,
> let's provide a new API that allows userspace to pick one particular
> version of the API.
> 
> This is implemented as a new class of "firmware" registers, where
> we expose the PSCI version. This allows the PSCI version to be
> save/restored as part of a guest migration, and also set to
> any supported version if the guest requires it.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  Documentation/virtual/kvm/api.txt      |  3 +-
>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
>  arch/arm/include/asm/kvm_host.h        |  3 ++
>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
>  arch/arm/kvm/guest.c                   | 13 +++++++
>  arch/arm64/include/asm/kvm_host.h      |  3 ++
>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
>  arch/arm64/kvm/guest.c                 | 14 ++++++-
>  include/kvm/arm_psci.h                 |  9 +++++
>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
>  10 files changed, 149 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 57d3ee9e4bde..334905202141 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2493,7 +2493,8 @@ Possible features:
>  	  and execute guest code when KVM_RUN is called.
>  	- 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.
> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
> +          backward compatible with v0.2) for the CPU.
>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
>  	  Depends on KVM_CAP_ARM_PMU_V3.
> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> new file mode 100644
> index 000000000000..2e49a4e9f084
> --- /dev/null
> +++ b/Documentation/virtual/kvm/arm/psci.txt
> @@ -0,0 +1,28 @@
> +KVM implements the PSCI (Power State Coordination Interface)
> +specification in order to provide services such as CPU on/off, reset
> +and power-off to the guest.
> +
> +The PSCI specification is regularly updated to provide new features,
> +and KVM implements these updates if they make sense from a virtualization
> +point of view.
> +
> +This means that a guest booted on two different versions of KVM can
> +observe two different "firmware" revisions. This could cause issues if
> +a given guest is tied to a particular PSCI revision (unlikely), or if
> +a migration causes a different PSCI version to be exposed out of the
> +blue to an unsuspecting guest.
> +
> +In order to remedy this situation, KVM exposes a set of "firmware
> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> +interface. These registers can be saved/restored by userspace, and set
> +to a convenient value if required.

Userspace can save/restore any state it deems necessary. Is there another
reason to invent a pseudo register? Considering the PSCI version is VM
state, then maybe a VM "device" attribute[*], like s390 use, would fit
better. Or, if keeping it VCPU state has some benefit, then we already
have VCPU device attribute support for ARM that we could extend with
another attribute. An advantage of using the device-attr API is that it
has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
How should userspace check if the pseudo register is supported? Maybe
by just failing with NOT_SUPPORTED to get/set it?

[*] Documentation/virtual/kvm/devices/vm.txt

> +
> +The following register is defined:
> +
> +* KVM_REG_ARM_PSCI_VERSION:
> +
> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> +  - Returns the current PSCI version on GET_ONE_REG
> +  - Allows any supported PSCI version compatible with v0.2 to be set
> +    with SET_ONE_REG
> +  - Affects the whole VM (even if the register view is per-vcpu)


> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index acbf9ec7b396..e9d57060d88c 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -75,6 +75,9 @@ struct kvm_arch {
>  	/* Interrupt controller */
>  	struct vgic_dist	vgic;
>  	int max_vcpus;
> +
> +	/* Mandated version of PSCI */
> +	u32 psci_version;
>  };
>  
>  #define KVM_NR_MEM_OBJS     40
> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> index 6edd177bb1c7..47dfc99f5cd0 100644
> --- a/arch/arm/include/uapi/asm/kvm.h
> +++ b/arch/arm/include/uapi/asm/kvm.h
> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
>  #define KVM_REG_ARM_VFP_FPINST		0x1009
>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
>  
> +/* KVM-as-firmware specific pseudo-registers */
> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)

Is this 0x14 documented somewhere? I'm just curious how the space for
pseudo registers is reserved. Is there a common place that we should
document that 0x14 is for the firmware (if it's not documented there
already)?

Thanks,
drew

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-31 17:38     ` Andrew Jones
  0 siblings, 0 replies; 116+ messages in thread
From: Andrew Jones @ 2018-01-31 17:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
> Since all the new PSCI versions are backward compatible, we decide to
> default to the latest version of the PSCI implementation. This is no
> different from doing a firmware upgrade on KVM.
> 
> But in order to give a chance to hypothetical badly implemented guests
> that would have a fit by discovering something other than PSCI 0.2,
> let's provide a new API that allows userspace to pick one particular
> version of the API.
> 
> This is implemented as a new class of "firmware" registers, where
> we expose the PSCI version. This allows the PSCI version to be
> save/restored as part of a guest migration, and also set to
> any supported version if the guest requires it.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  Documentation/virtual/kvm/api.txt      |  3 +-
>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
>  arch/arm/include/asm/kvm_host.h        |  3 ++
>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
>  arch/arm/kvm/guest.c                   | 13 +++++++
>  arch/arm64/include/asm/kvm_host.h      |  3 ++
>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
>  arch/arm64/kvm/guest.c                 | 14 ++++++-
>  include/kvm/arm_psci.h                 |  9 +++++
>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
>  10 files changed, 149 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 57d3ee9e4bde..334905202141 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2493,7 +2493,8 @@ Possible features:
>  	  and execute guest code when KVM_RUN is called.
>  	- 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.
> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
> +          backward compatible with v0.2) for the CPU.
>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
>  	  Depends on KVM_CAP_ARM_PMU_V3.
> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> new file mode 100644
> index 000000000000..2e49a4e9f084
> --- /dev/null
> +++ b/Documentation/virtual/kvm/arm/psci.txt
> @@ -0,0 +1,28 @@
> +KVM implements the PSCI (Power State Coordination Interface)
> +specification in order to provide services such as CPU on/off, reset
> +and power-off to the guest.
> +
> +The PSCI specification is regularly updated to provide new features,
> +and KVM implements these updates if they make sense from a virtualization
> +point of view.
> +
> +This means that a guest booted on two different versions of KVM can
> +observe two different "firmware" revisions. This could cause issues if
> +a given guest is tied to a particular PSCI revision (unlikely), or if
> +a migration causes a different PSCI version to be exposed out of the
> +blue to an unsuspecting guest.
> +
> +In order to remedy this situation, KVM exposes a set of "firmware
> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> +interface. These registers can be saved/restored by userspace, and set
> +to a convenient value if required.

Userspace can save/restore any state it deems necessary. Is there another
reason to invent a pseudo register? Considering the PSCI version is VM
state, then maybe a VM "device" attribute[*], like s390 use, would fit
better. Or, if keeping it VCPU state has some benefit, then we already
have VCPU device attribute support for ARM that we could extend with
another attribute. An advantage of using the device-attr API is that it
has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
How should userspace check if the pseudo register is supported? Maybe
by just failing with NOT_SUPPORTED to get/set it?

[*] Documentation/virtual/kvm/devices/vm.txt

> +
> +The following register is defined:
> +
> +* KVM_REG_ARM_PSCI_VERSION:
> +
> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> +  - Returns the current PSCI version on GET_ONE_REG
> +  - Allows any supported PSCI version compatible with v0.2 to be set
> +    with SET_ONE_REG
> +  - Affects the whole VM (even if the register view is per-vcpu)


> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index acbf9ec7b396..e9d57060d88c 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -75,6 +75,9 @@ struct kvm_arch {
>  	/* Interrupt controller */
>  	struct vgic_dist	vgic;
>  	int max_vcpus;
> +
> +	/* Mandated version of PSCI */
> +	u32 psci_version;
>  };
>  
>  #define KVM_NR_MEM_OBJS     40
> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> index 6edd177bb1c7..47dfc99f5cd0 100644
> --- a/arch/arm/include/uapi/asm/kvm.h
> +++ b/arch/arm/include/uapi/asm/kvm.h
> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
>  #define KVM_REG_ARM_VFP_FPINST		0x1009
>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
>  
> +/* KVM-as-firmware specific pseudo-registers */
> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)

Is this 0x14 documented somewhere? I'm just curious how the space for
pseudo registers is reserved. Is there a common place that we should
document that 0x14 is for the firmware (if it's not documented there
already)?

Thanks,
drew

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
  2018-01-31 17:38     ` Andrew Jones
@ 2018-01-31 17:45       ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 17:45 UTC (permalink / raw)
  To: Andrew Jones
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Lorenzo Pieralisi,
	Ard Biesheuvel, Catalin Marinas, Will Deacon, Jon Masters,
	Robin Murphy

On 31/01/18 17:38, Andrew Jones wrote:
> On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
>> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
>> Since all the new PSCI versions are backward compatible, we decide to
>> default to the latest version of the PSCI implementation. This is no
>> different from doing a firmware upgrade on KVM.
>>
>> But in order to give a chance to hypothetical badly implemented guests
>> that would have a fit by discovering something other than PSCI 0.2,
>> let's provide a new API that allows userspace to pick one particular
>> version of the API.
>>
>> This is implemented as a new class of "firmware" registers, where
>> we expose the PSCI version. This allows the PSCI version to be
>> save/restored as part of a guest migration, and also set to
>> any supported version if the guest requires it.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  Documentation/virtual/kvm/api.txt      |  3 +-
>>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
>>  arch/arm/include/asm/kvm_host.h        |  3 ++
>>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
>>  arch/arm/kvm/guest.c                   | 13 +++++++
>>  arch/arm64/include/asm/kvm_host.h      |  3 ++
>>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
>>  arch/arm64/kvm/guest.c                 | 14 ++++++-
>>  include/kvm/arm_psci.h                 |  9 +++++
>>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
>>  10 files changed, 149 insertions(+), 4 deletions(-)
>>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
>>
>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>> index 57d3ee9e4bde..334905202141 100644
>> --- a/Documentation/virtual/kvm/api.txt
>> +++ b/Documentation/virtual/kvm/api.txt
>> @@ -2493,7 +2493,8 @@ Possible features:
>>  	  and execute guest code when KVM_RUN is called.
>>  	- 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.
>> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
>> +          backward compatible with v0.2) for the CPU.
>>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
>>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
>>  	  Depends on KVM_CAP_ARM_PMU_V3.
>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
>> new file mode 100644
>> index 000000000000..2e49a4e9f084
>> --- /dev/null
>> +++ b/Documentation/virtual/kvm/arm/psci.txt
>> @@ -0,0 +1,28 @@
>> +KVM implements the PSCI (Power State Coordination Interface)
>> +specification in order to provide services such as CPU on/off, reset
>> +and power-off to the guest.
>> +
>> +The PSCI specification is regularly updated to provide new features,
>> +and KVM implements these updates if they make sense from a virtualization
>> +point of view.
>> +
>> +This means that a guest booted on two different versions of KVM can
>> +observe two different "firmware" revisions. This could cause issues if
>> +a given guest is tied to a particular PSCI revision (unlikely), or if
>> +a migration causes a different PSCI version to be exposed out of the
>> +blue to an unsuspecting guest.
>> +
>> +In order to remedy this situation, KVM exposes a set of "firmware
>> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
>> +interface. These registers can be saved/restored by userspace, and set
>> +to a convenient value if required.
> 
> Userspace can save/restore any state it deems necessary. 

Only if it has access to it. Until now, that wasn't an option.

> Is there another
> reason to invent a pseudo register? Considering the PSCI version is VM
> state, then maybe a VM "device" attribute[*], like s390 use, would fit
> better. 

Possibly. But that means current userspace won't engage the mitigation
by default, and that's pretty bad.

> Or, if keeping it VCPU state has some benefit, then we already
> have VCPU device attribute support for ARM that we could extend with
> another attribute. An advantage of using the device-attr API is that it
> has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
> How should userspace check if the pseudo register is supported? Maybe
> by just failing with NOT_SUPPORTED to get/set it?
> 
> [*] Documentation/virtual/kvm/devices/vm.txt

Frankly, I have no opinion on the way to implement it. My only
requirement is that it becomes enabled by default, without any userspace
change.

> 
>> +
>> +The following register is defined:
>> +
>> +* KVM_REG_ARM_PSCI_VERSION:
>> +
>> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
>> +  - Returns the current PSCI version on GET_ONE_REG
>> +  - Allows any supported PSCI version compatible with v0.2 to be set
>> +    with SET_ONE_REG
>> +  - Affects the whole VM (even if the register view is per-vcpu)
> 
> 
>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
>> index acbf9ec7b396..e9d57060d88c 100644
>> --- a/arch/arm/include/asm/kvm_host.h
>> +++ b/arch/arm/include/asm/kvm_host.h
>> @@ -75,6 +75,9 @@ struct kvm_arch {
>>  	/* Interrupt controller */
>>  	struct vgic_dist	vgic;
>>  	int max_vcpus;
>> +
>> +	/* Mandated version of PSCI */
>> +	u32 psci_version;
>>  };
>>  
>>  #define KVM_NR_MEM_OBJS     40
>> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
>> index 6edd177bb1c7..47dfc99f5cd0 100644
>> --- a/arch/arm/include/uapi/asm/kvm.h
>> +++ b/arch/arm/include/uapi/asm/kvm.h
>> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
>>  #define KVM_REG_ARM_VFP_FPINST		0x1009
>>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
>>  
>> +/* KVM-as-firmware specific pseudo-registers */
>> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> 
> Is this 0x14 documented somewhere? I'm just curious how the space for
> pseudo registers is reserved. Is there a common place that we should
> document that 0x14 is for the firmware (if it's not documented there
> already)?

No. First come, first served.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-31 17:45       ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 17:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 31/01/18 17:38, Andrew Jones wrote:
> On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
>> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
>> Since all the new PSCI versions are backward compatible, we decide to
>> default to the latest version of the PSCI implementation. This is no
>> different from doing a firmware upgrade on KVM.
>>
>> But in order to give a chance to hypothetical badly implemented guests
>> that would have a fit by discovering something other than PSCI 0.2,
>> let's provide a new API that allows userspace to pick one particular
>> version of the API.
>>
>> This is implemented as a new class of "firmware" registers, where
>> we expose the PSCI version. This allows the PSCI version to be
>> save/restored as part of a guest migration, and also set to
>> any supported version if the guest requires it.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  Documentation/virtual/kvm/api.txt      |  3 +-
>>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
>>  arch/arm/include/asm/kvm_host.h        |  3 ++
>>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
>>  arch/arm/kvm/guest.c                   | 13 +++++++
>>  arch/arm64/include/asm/kvm_host.h      |  3 ++
>>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
>>  arch/arm64/kvm/guest.c                 | 14 ++++++-
>>  include/kvm/arm_psci.h                 |  9 +++++
>>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
>>  10 files changed, 149 insertions(+), 4 deletions(-)
>>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
>>
>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>> index 57d3ee9e4bde..334905202141 100644
>> --- a/Documentation/virtual/kvm/api.txt
>> +++ b/Documentation/virtual/kvm/api.txt
>> @@ -2493,7 +2493,8 @@ Possible features:
>>  	  and execute guest code when KVM_RUN is called.
>>  	- 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.
>> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
>> +          backward compatible with v0.2) for the CPU.
>>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
>>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
>>  	  Depends on KVM_CAP_ARM_PMU_V3.
>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
>> new file mode 100644
>> index 000000000000..2e49a4e9f084
>> --- /dev/null
>> +++ b/Documentation/virtual/kvm/arm/psci.txt
>> @@ -0,0 +1,28 @@
>> +KVM implements the PSCI (Power State Coordination Interface)
>> +specification in order to provide services such as CPU on/off, reset
>> +and power-off to the guest.
>> +
>> +The PSCI specification is regularly updated to provide new features,
>> +and KVM implements these updates if they make sense from a virtualization
>> +point of view.
>> +
>> +This means that a guest booted on two different versions of KVM can
>> +observe two different "firmware" revisions. This could cause issues if
>> +a given guest is tied to a particular PSCI revision (unlikely), or if
>> +a migration causes a different PSCI version to be exposed out of the
>> +blue to an unsuspecting guest.
>> +
>> +In order to remedy this situation, KVM exposes a set of "firmware
>> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
>> +interface. These registers can be saved/restored by userspace, and set
>> +to a convenient value if required.
> 
> Userspace can save/restore any state it deems necessary. 

Only if it has access to it. Until now, that wasn't an option.

> Is there another
> reason to invent a pseudo register? Considering the PSCI version is VM
> state, then maybe a VM "device" attribute[*], like s390 use, would fit
> better. 

Possibly. But that means current userspace won't engage the mitigation
by default, and that's pretty bad.

> Or, if keeping it VCPU state has some benefit, then we already
> have VCPU device attribute support for ARM that we could extend with
> another attribute. An advantage of using the device-attr API is that it
> has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
> How should userspace check if the pseudo register is supported? Maybe
> by just failing with NOT_SUPPORTED to get/set it?
> 
> [*] Documentation/virtual/kvm/devices/vm.txt

Frankly, I have no opinion on the way to implement it. My only
requirement is that it becomes enabled by default, without any userspace
change.

> 
>> +
>> +The following register is defined:
>> +
>> +* KVM_REG_ARM_PSCI_VERSION:
>> +
>> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
>> +  - Returns the current PSCI version on GET_ONE_REG
>> +  - Allows any supported PSCI version compatible with v0.2 to be set
>> +    with SET_ONE_REG
>> +  - Affects the whole VM (even if the register view is per-vcpu)
> 
> 
>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
>> index acbf9ec7b396..e9d57060d88c 100644
>> --- a/arch/arm/include/asm/kvm_host.h
>> +++ b/arch/arm/include/asm/kvm_host.h
>> @@ -75,6 +75,9 @@ struct kvm_arch {
>>  	/* Interrupt controller */
>>  	struct vgic_dist	vgic;
>>  	int max_vcpus;
>> +
>> +	/* Mandated version of PSCI */
>> +	u32 psci_version;
>>  };
>>  
>>  #define KVM_NR_MEM_OBJS     40
>> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
>> index 6edd177bb1c7..47dfc99f5cd0 100644
>> --- a/arch/arm/include/uapi/asm/kvm.h
>> +++ b/arch/arm/include/uapi/asm/kvm.h
>> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
>>  #define KVM_REG_ARM_VFP_FPINST		0x1009
>>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
>>  
>> +/* KVM-as-firmware specific pseudo-registers */
>> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> 
> Is this 0x14 documented somewhere? I'm just curious how the space for
> pseudo registers is reserved. Is there a common place that we should
> document that 0x14 is for the firmware (if it's not documented there
> already)?

No. First come, first served.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
  2018-01-31 17:45       ` Marc Zyngier
  (?)
@ 2018-01-31 18:03         ` Andrew Jones
  -1 siblings, 0 replies; 116+ messages in thread
From: Andrew Jones @ 2018-01-31 18:03 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Lorenzo Pieralisi,
	Ard Biesheuvel, Catalin Marinas, Will Deacon, Jon Masters,
	Robin Murphy

On Wed, Jan 31, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
> On 31/01/18 17:38, Andrew Jones wrote:
> > On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
> >> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
> >> Since all the new PSCI versions are backward compatible, we decide to
> >> default to the latest version of the PSCI implementation. This is no
> >> different from doing a firmware upgrade on KVM.
> >>
> >> But in order to give a chance to hypothetical badly implemented guests
> >> that would have a fit by discovering something other than PSCI 0.2,
> >> let's provide a new API that allows userspace to pick one particular
> >> version of the API.
> >>
> >> This is implemented as a new class of "firmware" registers, where
> >> we expose the PSCI version. This allows the PSCI version to be
> >> save/restored as part of a guest migration, and also set to
> >> any supported version if the guest requires it.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >>  Documentation/virtual/kvm/api.txt      |  3 +-
> >>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
> >>  arch/arm/include/asm/kvm_host.h        |  3 ++
> >>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
> >>  arch/arm/kvm/guest.c                   | 13 +++++++
> >>  arch/arm64/include/asm/kvm_host.h      |  3 ++
> >>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
> >>  arch/arm64/kvm/guest.c                 | 14 ++++++-
> >>  include/kvm/arm_psci.h                 |  9 +++++
> >>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
> >>  10 files changed, 149 insertions(+), 4 deletions(-)
> >>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
> >>
> >> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> >> index 57d3ee9e4bde..334905202141 100644
> >> --- a/Documentation/virtual/kvm/api.txt
> >> +++ b/Documentation/virtual/kvm/api.txt
> >> @@ -2493,7 +2493,8 @@ Possible features:
> >>  	  and execute guest code when KVM_RUN is called.
> >>  	- 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.
> >> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
> >> +          backward compatible with v0.2) for the CPU.
> >>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
> >>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
> >>  	  Depends on KVM_CAP_ARM_PMU_V3.
> >> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> >> new file mode 100644
> >> index 000000000000..2e49a4e9f084
> >> --- /dev/null
> >> +++ b/Documentation/virtual/kvm/arm/psci.txt
> >> @@ -0,0 +1,28 @@
> >> +KVM implements the PSCI (Power State Coordination Interface)
> >> +specification in order to provide services such as CPU on/off, reset
> >> +and power-off to the guest.
> >> +
> >> +The PSCI specification is regularly updated to provide new features,
> >> +and KVM implements these updates if they make sense from a virtualization
> >> +point of view.
> >> +
> >> +This means that a guest booted on two different versions of KVM can
> >> +observe two different "firmware" revisions. This could cause issues if
> >> +a given guest is tied to a particular PSCI revision (unlikely), or if
> >> +a migration causes a different PSCI version to be exposed out of the
> >> +blue to an unsuspecting guest.
> >> +
> >> +In order to remedy this situation, KVM exposes a set of "firmware
> >> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> >> +interface. These registers can be saved/restored by userspace, and set
> >> +to a convenient value if required.
> > 
> > Userspace can save/restore any state it deems necessary. 
> 
> Only if it has access to it. Until now, that wasn't an option.
> 
> > Is there another
> > reason to invent a pseudo register? Considering the PSCI version is VM
> > state, then maybe a VM "device" attribute[*], like s390 use, would fit
> > better. 
> 
> Possibly. But that means current userspace won't engage the mitigation
> by default, and that's pretty bad.
> 
> > Or, if keeping it VCPU state has some benefit, then we already
> > have VCPU device attribute support for ARM that we could extend with
> > another attribute. An advantage of using the device-attr API is that it
> > has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
> > How should userspace check if the pseudo register is supported? Maybe
> > by just failing with NOT_SUPPORTED to get/set it?
> > 
> > [*] Documentation/virtual/kvm/devices/vm.txt
> 
> Frankly, I have no opinion on the way to implement it. My only
> requirement is that it becomes enabled by default, without any userspace
> change.

I think we can turn it on by default in KVM, no matter what API we choose,
and then enable userspace (with whatever API) to turn it off. Newer
machine types certainly wouldn't do that, and, as later PSCI is compatible
with older PSCI, we're probably safe (safer regarding the BTB) not using
the older PSCI with older machine types either - although that would be up
for debate and the whole point of adding the API.

> 
> > 
> >> +
> >> +The following register is defined:
> >> +
> >> +* KVM_REG_ARM_PSCI_VERSION:
> >> +
> >> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> >> +  - Returns the current PSCI version on GET_ONE_REG
> >> +  - Allows any supported PSCI version compatible with v0.2 to be set
> >> +    with SET_ONE_REG
> >> +  - Affects the whole VM (even if the register view is per-vcpu)
> > 
> > 
> >> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >> index acbf9ec7b396..e9d57060d88c 100644
> >> --- a/arch/arm/include/asm/kvm_host.h
> >> +++ b/arch/arm/include/asm/kvm_host.h
> >> @@ -75,6 +75,9 @@ struct kvm_arch {
> >>  	/* Interrupt controller */
> >>  	struct vgic_dist	vgic;
> >>  	int max_vcpus;
> >> +
> >> +	/* Mandated version of PSCI */
> >> +	u32 psci_version;
> >>  };
> >>  
> >>  #define KVM_NR_MEM_OBJS     40
> >> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> >> index 6edd177bb1c7..47dfc99f5cd0 100644
> >> --- a/arch/arm/include/uapi/asm/kvm.h
> >> +++ b/arch/arm/include/uapi/asm/kvm.h
> >> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
> >>  #define KVM_REG_ARM_VFP_FPINST		0x1009
> >>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
> >>  
> >> +/* KVM-as-firmware specific pseudo-registers */
> >> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> > 
> > Is this 0x14 documented somewhere? I'm just curious how the space for
> > pseudo registers is reserved. Is there a common place that we should
> > document that 0x14 is for the firmware (if it's not documented there
> > already)?
> 
> No. First come, first served.

Should we document it in Documentation/ somewhere?

Thanks,
drew

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-31 18:03         ` Andrew Jones
  0 siblings, 0 replies; 116+ messages in thread
From: Andrew Jones @ 2018-01-31 18:03 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Ard Biesheuvel, Catalin Marinas, Will Deacon,
	linux-kernel, Jon Masters, Robin Murphy, kvmarm,
	linux-arm-kernel

On Wed, Jan 31, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
> On 31/01/18 17:38, Andrew Jones wrote:
> > On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
> >> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
> >> Since all the new PSCI versions are backward compatible, we decide to
> >> default to the latest version of the PSCI implementation. This is no
> >> different from doing a firmware upgrade on KVM.
> >>
> >> But in order to give a chance to hypothetical badly implemented guests
> >> that would have a fit by discovering something other than PSCI 0.2,
> >> let's provide a new API that allows userspace to pick one particular
> >> version of the API.
> >>
> >> This is implemented as a new class of "firmware" registers, where
> >> we expose the PSCI version. This allows the PSCI version to be
> >> save/restored as part of a guest migration, and also set to
> >> any supported version if the guest requires it.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >>  Documentation/virtual/kvm/api.txt      |  3 +-
> >>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
> >>  arch/arm/include/asm/kvm_host.h        |  3 ++
> >>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
> >>  arch/arm/kvm/guest.c                   | 13 +++++++
> >>  arch/arm64/include/asm/kvm_host.h      |  3 ++
> >>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
> >>  arch/arm64/kvm/guest.c                 | 14 ++++++-
> >>  include/kvm/arm_psci.h                 |  9 +++++
> >>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
> >>  10 files changed, 149 insertions(+), 4 deletions(-)
> >>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
> >>
> >> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> >> index 57d3ee9e4bde..334905202141 100644
> >> --- a/Documentation/virtual/kvm/api.txt
> >> +++ b/Documentation/virtual/kvm/api.txt
> >> @@ -2493,7 +2493,8 @@ Possible features:
> >>  	  and execute guest code when KVM_RUN is called.
> >>  	- 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.
> >> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
> >> +          backward compatible with v0.2) for the CPU.
> >>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
> >>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
> >>  	  Depends on KVM_CAP_ARM_PMU_V3.
> >> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> >> new file mode 100644
> >> index 000000000000..2e49a4e9f084
> >> --- /dev/null
> >> +++ b/Documentation/virtual/kvm/arm/psci.txt
> >> @@ -0,0 +1,28 @@
> >> +KVM implements the PSCI (Power State Coordination Interface)
> >> +specification in order to provide services such as CPU on/off, reset
> >> +and power-off to the guest.
> >> +
> >> +The PSCI specification is regularly updated to provide new features,
> >> +and KVM implements these updates if they make sense from a virtualization
> >> +point of view.
> >> +
> >> +This means that a guest booted on two different versions of KVM can
> >> +observe two different "firmware" revisions. This could cause issues if
> >> +a given guest is tied to a particular PSCI revision (unlikely), or if
> >> +a migration causes a different PSCI version to be exposed out of the
> >> +blue to an unsuspecting guest.
> >> +
> >> +In order to remedy this situation, KVM exposes a set of "firmware
> >> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> >> +interface. These registers can be saved/restored by userspace, and set
> >> +to a convenient value if required.
> > 
> > Userspace can save/restore any state it deems necessary. 
> 
> Only if it has access to it. Until now, that wasn't an option.
> 
> > Is there another
> > reason to invent a pseudo register? Considering the PSCI version is VM
> > state, then maybe a VM "device" attribute[*], like s390 use, would fit
> > better. 
> 
> Possibly. But that means current userspace won't engage the mitigation
> by default, and that's pretty bad.
> 
> > Or, if keeping it VCPU state has some benefit, then we already
> > have VCPU device attribute support for ARM that we could extend with
> > another attribute. An advantage of using the device-attr API is that it
> > has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
> > How should userspace check if the pseudo register is supported? Maybe
> > by just failing with NOT_SUPPORTED to get/set it?
> > 
> > [*] Documentation/virtual/kvm/devices/vm.txt
> 
> Frankly, I have no opinion on the way to implement it. My only
> requirement is that it becomes enabled by default, without any userspace
> change.

I think we can turn it on by default in KVM, no matter what API we choose,
and then enable userspace (with whatever API) to turn it off. Newer
machine types certainly wouldn't do that, and, as later PSCI is compatible
with older PSCI, we're probably safe (safer regarding the BTB) not using
the older PSCI with older machine types either - although that would be up
for debate and the whole point of adding the API.

> 
> > 
> >> +
> >> +The following register is defined:
> >> +
> >> +* KVM_REG_ARM_PSCI_VERSION:
> >> +
> >> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> >> +  - Returns the current PSCI version on GET_ONE_REG
> >> +  - Allows any supported PSCI version compatible with v0.2 to be set
> >> +    with SET_ONE_REG
> >> +  - Affects the whole VM (even if the register view is per-vcpu)
> > 
> > 
> >> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >> index acbf9ec7b396..e9d57060d88c 100644
> >> --- a/arch/arm/include/asm/kvm_host.h
> >> +++ b/arch/arm/include/asm/kvm_host.h
> >> @@ -75,6 +75,9 @@ struct kvm_arch {
> >>  	/* Interrupt controller */
> >>  	struct vgic_dist	vgic;
> >>  	int max_vcpus;
> >> +
> >> +	/* Mandated version of PSCI */
> >> +	u32 psci_version;
> >>  };
> >>  
> >>  #define KVM_NR_MEM_OBJS     40
> >> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> >> index 6edd177bb1c7..47dfc99f5cd0 100644
> >> --- a/arch/arm/include/uapi/asm/kvm.h
> >> +++ b/arch/arm/include/uapi/asm/kvm.h
> >> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
> >>  #define KVM_REG_ARM_VFP_FPINST		0x1009
> >>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
> >>  
> >> +/* KVM-as-firmware specific pseudo-registers */
> >> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> > 
> > Is this 0x14 documented somewhere? I'm just curious how the space for
> > pseudo registers is reserved. Is there a common place that we should
> > document that 0x14 is for the firmware (if it's not documented there
> > already)?
> 
> No. First come, first served.

Should we document it in Documentation/ somewhere?

Thanks,
drew

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-31 18:03         ` Andrew Jones
  0 siblings, 0 replies; 116+ messages in thread
From: Andrew Jones @ 2018-01-31 18:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
> On 31/01/18 17:38, Andrew Jones wrote:
> > On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
> >> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
> >> Since all the new PSCI versions are backward compatible, we decide to
> >> default to the latest version of the PSCI implementation. This is no
> >> different from doing a firmware upgrade on KVM.
> >>
> >> But in order to give a chance to hypothetical badly implemented guests
> >> that would have a fit by discovering something other than PSCI 0.2,
> >> let's provide a new API that allows userspace to pick one particular
> >> version of the API.
> >>
> >> This is implemented as a new class of "firmware" registers, where
> >> we expose the PSCI version. This allows the PSCI version to be
> >> save/restored as part of a guest migration, and also set to
> >> any supported version if the guest requires it.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >>  Documentation/virtual/kvm/api.txt      |  3 +-
> >>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
> >>  arch/arm/include/asm/kvm_host.h        |  3 ++
> >>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
> >>  arch/arm/kvm/guest.c                   | 13 +++++++
> >>  arch/arm64/include/asm/kvm_host.h      |  3 ++
> >>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
> >>  arch/arm64/kvm/guest.c                 | 14 ++++++-
> >>  include/kvm/arm_psci.h                 |  9 +++++
> >>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
> >>  10 files changed, 149 insertions(+), 4 deletions(-)
> >>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
> >>
> >> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> >> index 57d3ee9e4bde..334905202141 100644
> >> --- a/Documentation/virtual/kvm/api.txt
> >> +++ b/Documentation/virtual/kvm/api.txt
> >> @@ -2493,7 +2493,8 @@ Possible features:
> >>  	  and execute guest code when KVM_RUN is called.
> >>  	- 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.
> >> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
> >> +          backward compatible with v0.2) for the CPU.
> >>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
> >>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
> >>  	  Depends on KVM_CAP_ARM_PMU_V3.
> >> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> >> new file mode 100644
> >> index 000000000000..2e49a4e9f084
> >> --- /dev/null
> >> +++ b/Documentation/virtual/kvm/arm/psci.txt
> >> @@ -0,0 +1,28 @@
> >> +KVM implements the PSCI (Power State Coordination Interface)
> >> +specification in order to provide services such as CPU on/off, reset
> >> +and power-off to the guest.
> >> +
> >> +The PSCI specification is regularly updated to provide new features,
> >> +and KVM implements these updates if they make sense from a virtualization
> >> +point of view.
> >> +
> >> +This means that a guest booted on two different versions of KVM can
> >> +observe two different "firmware" revisions. This could cause issues if
> >> +a given guest is tied to a particular PSCI revision (unlikely), or if
> >> +a migration causes a different PSCI version to be exposed out of the
> >> +blue to an unsuspecting guest.
> >> +
> >> +In order to remedy this situation, KVM exposes a set of "firmware
> >> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> >> +interface. These registers can be saved/restored by userspace, and set
> >> +to a convenient value if required.
> > 
> > Userspace can save/restore any state it deems necessary. 
> 
> Only if it has access to it. Until now, that wasn't an option.
> 
> > Is there another
> > reason to invent a pseudo register? Considering the PSCI version is VM
> > state, then maybe a VM "device" attribute[*], like s390 use, would fit
> > better. 
> 
> Possibly. But that means current userspace won't engage the mitigation
> by default, and that's pretty bad.
> 
> > Or, if keeping it VCPU state has some benefit, then we already
> > have VCPU device attribute support for ARM that we could extend with
> > another attribute. An advantage of using the device-attr API is that it
> > has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
> > How should userspace check if the pseudo register is supported? Maybe
> > by just failing with NOT_SUPPORTED to get/set it?
> > 
> > [*] Documentation/virtual/kvm/devices/vm.txt
> 
> Frankly, I have no opinion on the way to implement it. My only
> requirement is that it becomes enabled by default, without any userspace
> change.

I think we can turn it on by default in KVM, no matter what API we choose,
and then enable userspace (with whatever API) to turn it off. Newer
machine types certainly wouldn't do that, and, as later PSCI is compatible
with older PSCI, we're probably safe (safer regarding the BTB) not using
the older PSCI with older machine types either - although that would be up
for debate and the whole point of adding the API.

> 
> > 
> >> +
> >> +The following register is defined:
> >> +
> >> +* KVM_REG_ARM_PSCI_VERSION:
> >> +
> >> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> >> +  - Returns the current PSCI version on GET_ONE_REG
> >> +  - Allows any supported PSCI version compatible with v0.2 to be set
> >> +    with SET_ONE_REG
> >> +  - Affects the whole VM (even if the register view is per-vcpu)
> > 
> > 
> >> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >> index acbf9ec7b396..e9d57060d88c 100644
> >> --- a/arch/arm/include/asm/kvm_host.h
> >> +++ b/arch/arm/include/asm/kvm_host.h
> >> @@ -75,6 +75,9 @@ struct kvm_arch {
> >>  	/* Interrupt controller */
> >>  	struct vgic_dist	vgic;
> >>  	int max_vcpus;
> >> +
> >> +	/* Mandated version of PSCI */
> >> +	u32 psci_version;
> >>  };
> >>  
> >>  #define KVM_NR_MEM_OBJS     40
> >> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> >> index 6edd177bb1c7..47dfc99f5cd0 100644
> >> --- a/arch/arm/include/uapi/asm/kvm.h
> >> +++ b/arch/arm/include/uapi/asm/kvm.h
> >> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
> >>  #define KVM_REG_ARM_VFP_FPINST		0x1009
> >>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
> >>  
> >> +/* KVM-as-firmware specific pseudo-registers */
> >> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> > 
> > Is this 0x14 documented somewhere? I'm just curious how the space for
> > pseudo registers is reserved. Is there a common place that we should
> > document that 0x14 is for the firmware (if it's not documented there
> > already)?
> 
> No. First come, first served.

Should we document it in Documentation/ somewhere?

Thanks,
drew

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
  2018-01-29 17:45   ` Marc Zyngier
@ 2018-01-31 18:11     ` kbuild test robot
  -1 siblings, 0 replies; 116+ messages in thread
From: kbuild test robot @ 2018-01-31 18:11 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: kbuild-all, linux-kernel, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

[-- Attachment #1: Type: text/plain, Size: 2289 bytes --]

Hi Marc,

I love your patch! Yet something to improve:

[auto build test ERROR on arm64/for-next/core]
[cannot apply to kvmarm/next linus/master v4.15 next-20180126]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Marc-Zyngier/arm64-Add-SMCCC-v1-1-support-and-CVE-2017-5715-Spectre-variant-2-mitigation/20180131-234336
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

Note: the linux-review/Marc-Zyngier/arm64-Add-SMCCC-v1-1-support-and-CVE-2017-5715-Spectre-variant-2-mitigation/20180131-234336 HEAD 8c17f9fc363230480b44d05f728350e6fa448bd4 builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   arch/arm64/kvm/../../../virt/kvm/arm/psci.c: In function 'kvm_arm_get_fw_reg':
>> arch/arm64/kvm/../../../virt/kvm/arm/psci.c:443:9: error: too many arguments to function 'kvm_psci_version'
      val = kvm_psci_version(vcpu, vcpu->kvm);
            ^~~~~~~~~~~~~~~~
   arch/arm64/kvm/../../../virt/kvm/arm/psci.c:237:5: note: declared here
    int kvm_psci_version(struct kvm_vcpu *vcpu)
        ^~~~~~~~~~~~~~~~

vim +/kvm_psci_version +443 arch/arm64/kvm/../../../virt/kvm/arm/psci.c

   436	
   437	int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
   438	{
   439		if (reg->id == KVM_REG_ARM_PSCI_VERSION) {
   440			void __user *uaddr = (void __user *)(long)reg->addr;
   441			u64 val;
   442	
 > 443			val = kvm_psci_version(vcpu, vcpu->kvm);
   444			if (val == KVM_ARM_PSCI_0_1)
   445				return -EINVAL;
   446			if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
   447				return -EFAULT;
   448	
   449			return 0;
   450		}
   451	
   452		return -EINVAL;
   453	}
   454	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37478 bytes --]

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-31 18:11     ` kbuild test robot
  0 siblings, 0 replies; 116+ messages in thread
From: kbuild test robot @ 2018-01-31 18:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

I love your patch! Yet something to improve:

[auto build test ERROR on arm64/for-next/core]
[cannot apply to kvmarm/next linus/master v4.15 next-20180126]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Marc-Zyngier/arm64-Add-SMCCC-v1-1-support-and-CVE-2017-5715-Spectre-variant-2-mitigation/20180131-234336
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

Note: the linux-review/Marc-Zyngier/arm64-Add-SMCCC-v1-1-support-and-CVE-2017-5715-Spectre-variant-2-mitigation/20180131-234336 HEAD 8c17f9fc363230480b44d05f728350e6fa448bd4 builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   arch/arm64/kvm/../../../virt/kvm/arm/psci.c: In function 'kvm_arm_get_fw_reg':
>> arch/arm64/kvm/../../../virt/kvm/arm/psci.c:443:9: error: too many arguments to function 'kvm_psci_version'
      val = kvm_psci_version(vcpu, vcpu->kvm);
            ^~~~~~~~~~~~~~~~
   arch/arm64/kvm/../../../virt/kvm/arm/psci.c:237:5: note: declared here
    int kvm_psci_version(struct kvm_vcpu *vcpu)
        ^~~~~~~~~~~~~~~~

vim +/kvm_psci_version +443 arch/arm64/kvm/../../../virt/kvm/arm/psci.c

   436	
   437	int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
   438	{
   439		if (reg->id == KVM_REG_ARM_PSCI_VERSION) {
   440			void __user *uaddr = (void __user *)(long)reg->addr;
   441			u64 val;
   442	
 > 443			val = kvm_psci_version(vcpu, vcpu->kvm);
   444			if (val == KVM_ARM_PSCI_0_1)
   445				return -EINVAL;
   446			if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
   447				return -EFAULT;
   448	
   449			return 0;
   450		}
   451	
   452		return -EINVAL;
   453	}
   454	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 37478 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180201/15788a39/attachment-0001.gz>

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
  2018-01-31 18:03         ` Andrew Jones
@ 2018-01-31 18:36           ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 18:36 UTC (permalink / raw)
  To: Andrew Jones
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Lorenzo Pieralisi,
	Ard Biesheuvel, Catalin Marinas, Will Deacon, Jon Masters,
	Robin Murphy

On 31/01/18 18:03, Andrew Jones wrote:
> On Wed, Jan 31, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
>> On 31/01/18 17:38, Andrew Jones wrote:
>>> On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
>>>> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
>>>> Since all the new PSCI versions are backward compatible, we decide to
>>>> default to the latest version of the PSCI implementation. This is no
>>>> different from doing a firmware upgrade on KVM.
>>>>
>>>> But in order to give a chance to hypothetical badly implemented guests
>>>> that would have a fit by discovering something other than PSCI 0.2,
>>>> let's provide a new API that allows userspace to pick one particular
>>>> version of the API.
>>>>
>>>> This is implemented as a new class of "firmware" registers, where
>>>> we expose the PSCI version. This allows the PSCI version to be
>>>> save/restored as part of a guest migration, and also set to
>>>> any supported version if the guest requires it.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>> ---
>>>>  Documentation/virtual/kvm/api.txt      |  3 +-
>>>>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
>>>>  arch/arm/include/asm/kvm_host.h        |  3 ++
>>>>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
>>>>  arch/arm/kvm/guest.c                   | 13 +++++++
>>>>  arch/arm64/include/asm/kvm_host.h      |  3 ++
>>>>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
>>>>  arch/arm64/kvm/guest.c                 | 14 ++++++-
>>>>  include/kvm/arm_psci.h                 |  9 +++++
>>>>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
>>>>  10 files changed, 149 insertions(+), 4 deletions(-)
>>>>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
>>>>
>>>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>>>> index 57d3ee9e4bde..334905202141 100644
>>>> --- a/Documentation/virtual/kvm/api.txt
>>>> +++ b/Documentation/virtual/kvm/api.txt
>>>> @@ -2493,7 +2493,8 @@ Possible features:
>>>>  	  and execute guest code when KVM_RUN is called.
>>>>  	- 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.
>>>> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
>>>> +          backward compatible with v0.2) for the CPU.
>>>>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
>>>>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
>>>>  	  Depends on KVM_CAP_ARM_PMU_V3.
>>>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
>>>> new file mode 100644
>>>> index 000000000000..2e49a4e9f084
>>>> --- /dev/null
>>>> +++ b/Documentation/virtual/kvm/arm/psci.txt
>>>> @@ -0,0 +1,28 @@
>>>> +KVM implements the PSCI (Power State Coordination Interface)
>>>> +specification in order to provide services such as CPU on/off, reset
>>>> +and power-off to the guest.
>>>> +
>>>> +The PSCI specification is regularly updated to provide new features,
>>>> +and KVM implements these updates if they make sense from a virtualization
>>>> +point of view.
>>>> +
>>>> +This means that a guest booted on two different versions of KVM can
>>>> +observe two different "firmware" revisions. This could cause issues if
>>>> +a given guest is tied to a particular PSCI revision (unlikely), or if
>>>> +a migration causes a different PSCI version to be exposed out of the
>>>> +blue to an unsuspecting guest.
>>>> +
>>>> +In order to remedy this situation, KVM exposes a set of "firmware
>>>> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
>>>> +interface. These registers can be saved/restored by userspace, and set
>>>> +to a convenient value if required.
>>>
>>> Userspace can save/restore any state it deems necessary. 
>>
>> Only if it has access to it. Until now, that wasn't an option.
>>
>>> Is there another
>>> reason to invent a pseudo register? Considering the PSCI version is VM
>>> state, then maybe a VM "device" attribute[*], like s390 use, would fit
>>> better. 
>>
>> Possibly. But that means current userspace won't engage the mitigation
>> by default, and that's pretty bad.
>>
>>> Or, if keeping it VCPU state has some benefit, then we already
>>> have VCPU device attribute support for ARM that we could extend with
>>> another attribute. An advantage of using the device-attr API is that it
>>> has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
>>> How should userspace check if the pseudo register is supported? Maybe
>>> by just failing with NOT_SUPPORTED to get/set it?
>>>
>>> [*] Documentation/virtual/kvm/devices/vm.txt
>>
>> Frankly, I have no opinion on the way to implement it. My only
>> requirement is that it becomes enabled by default, without any userspace
>> change.
> 
> I think we can turn it on by default in KVM, no matter what API we choose,
> and then enable userspace (with whatever API) to turn it off. Newer
> machine types certainly wouldn't do that, and, as later PSCI is compatible
> with older PSCI, we're probably safe (safer regarding the BTB) not using
> the older PSCI with older machine types either - although that would be up
> for debate and the whole point of adding the API.

OK. At least we're aligned on this. As for your question about finding
out about the register, here's what I have in kvmtool:

+       reg.addr = (u64)&data;
+       reg.id = KVM_REG_ARM_PSCI_VERSION;
+       err = ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg);
+       if (err < 0)
+               pr_info("Unable to get PSCI version\n");
+       else
+               pr_info("PSCI version %llx\n", data);

If you get an error, the feature doesn't exist. One of the reasons for
using a register is that migration works with today's QEMU. And if you
try to restore a VM that's aware of the PSCI version (and possibly of
the BTB invalidation) on a host that doesn't support it, you get a fail
without any change of userspace.

To me, that's a pretty good argument in favour of this method. But if
you have strong feelings about it and would like me to implement
something else, please let me know ASAP. We'd like this series to land
in -rc1, so we only have a few days left...

>>
>>>
>>>> +
>>>> +The following register is defined:
>>>> +
>>>> +* KVM_REG_ARM_PSCI_VERSION:
>>>> +
>>>> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
>>>> +  - Returns the current PSCI version on GET_ONE_REG
>>>> +  - Allows any supported PSCI version compatible with v0.2 to be set
>>>> +    with SET_ONE_REG
>>>> +  - Affects the whole VM (even if the register view is per-vcpu)
>>>
>>>
>>>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
>>>> index acbf9ec7b396..e9d57060d88c 100644
>>>> --- a/arch/arm/include/asm/kvm_host.h
>>>> +++ b/arch/arm/include/asm/kvm_host.h
>>>> @@ -75,6 +75,9 @@ struct kvm_arch {
>>>>  	/* Interrupt controller */
>>>>  	struct vgic_dist	vgic;
>>>>  	int max_vcpus;
>>>> +
>>>> +	/* Mandated version of PSCI */
>>>> +	u32 psci_version;
>>>>  };
>>>>  
>>>>  #define KVM_NR_MEM_OBJS     40
>>>> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
>>>> index 6edd177bb1c7..47dfc99f5cd0 100644
>>>> --- a/arch/arm/include/uapi/asm/kvm.h
>>>> +++ b/arch/arm/include/uapi/asm/kvm.h
>>>> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
>>>>  #define KVM_REG_ARM_VFP_FPINST		0x1009
>>>>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
>>>>  
>>>> +/* KVM-as-firmware specific pseudo-registers */
>>>> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
>>>
>>> Is this 0x14 documented somewhere? I'm just curious how the space for
>>> pseudo registers is reserved. Is there a common place that we should
>>> document that 0x14 is for the firmware (if it's not documented there
>>> already)?
>>
>> No. First come, first served.
> 
> Should we document it in Documentation/ somewhere?
We can. I tend to see the uapi/asm/kvm.h file as the reference (and I
feel that a text file would simply be an English translation of that
file), but I'm not opposed to it either. I'm not sure I have the
bandwidth for that at the moment though.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-31 18:36           ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-01-31 18:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 31/01/18 18:03, Andrew Jones wrote:
> On Wed, Jan 31, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
>> On 31/01/18 17:38, Andrew Jones wrote:
>>> On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
>>>> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
>>>> Since all the new PSCI versions are backward compatible, we decide to
>>>> default to the latest version of the PSCI implementation. This is no
>>>> different from doing a firmware upgrade on KVM.
>>>>
>>>> But in order to give a chance to hypothetical badly implemented guests
>>>> that would have a fit by discovering something other than PSCI 0.2,
>>>> let's provide a new API that allows userspace to pick one particular
>>>> version of the API.
>>>>
>>>> This is implemented as a new class of "firmware" registers, where
>>>> we expose the PSCI version. This allows the PSCI version to be
>>>> save/restored as part of a guest migration, and also set to
>>>> any supported version if the guest requires it.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>> ---
>>>>  Documentation/virtual/kvm/api.txt      |  3 +-
>>>>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
>>>>  arch/arm/include/asm/kvm_host.h        |  3 ++
>>>>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
>>>>  arch/arm/kvm/guest.c                   | 13 +++++++
>>>>  arch/arm64/include/asm/kvm_host.h      |  3 ++
>>>>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
>>>>  arch/arm64/kvm/guest.c                 | 14 ++++++-
>>>>  include/kvm/arm_psci.h                 |  9 +++++
>>>>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
>>>>  10 files changed, 149 insertions(+), 4 deletions(-)
>>>>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
>>>>
>>>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>>>> index 57d3ee9e4bde..334905202141 100644
>>>> --- a/Documentation/virtual/kvm/api.txt
>>>> +++ b/Documentation/virtual/kvm/api.txt
>>>> @@ -2493,7 +2493,8 @@ Possible features:
>>>>  	  and execute guest code when KVM_RUN is called.
>>>>  	- 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.
>>>> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
>>>> +          backward compatible with v0.2) for the CPU.
>>>>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
>>>>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
>>>>  	  Depends on KVM_CAP_ARM_PMU_V3.
>>>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
>>>> new file mode 100644
>>>> index 000000000000..2e49a4e9f084
>>>> --- /dev/null
>>>> +++ b/Documentation/virtual/kvm/arm/psci.txt
>>>> @@ -0,0 +1,28 @@
>>>> +KVM implements the PSCI (Power State Coordination Interface)
>>>> +specification in order to provide services such as CPU on/off, reset
>>>> +and power-off to the guest.
>>>> +
>>>> +The PSCI specification is regularly updated to provide new features,
>>>> +and KVM implements these updates if they make sense from a virtualization
>>>> +point of view.
>>>> +
>>>> +This means that a guest booted on two different versions of KVM can
>>>> +observe two different "firmware" revisions. This could cause issues if
>>>> +a given guest is tied to a particular PSCI revision (unlikely), or if
>>>> +a migration causes a different PSCI version to be exposed out of the
>>>> +blue to an unsuspecting guest.
>>>> +
>>>> +In order to remedy this situation, KVM exposes a set of "firmware
>>>> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
>>>> +interface. These registers can be saved/restored by userspace, and set
>>>> +to a convenient value if required.
>>>
>>> Userspace can save/restore any state it deems necessary. 
>>
>> Only if it has access to it. Until now, that wasn't an option.
>>
>>> Is there another
>>> reason to invent a pseudo register? Considering the PSCI version is VM
>>> state, then maybe a VM "device" attribute[*], like s390 use, would fit
>>> better. 
>>
>> Possibly. But that means current userspace won't engage the mitigation
>> by default, and that's pretty bad.
>>
>>> Or, if keeping it VCPU state has some benefit, then we already
>>> have VCPU device attribute support for ARM that we could extend with
>>> another attribute. An advantage of using the device-attr API is that it
>>> has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
>>> How should userspace check if the pseudo register is supported? Maybe
>>> by just failing with NOT_SUPPORTED to get/set it?
>>>
>>> [*] Documentation/virtual/kvm/devices/vm.txt
>>
>> Frankly, I have no opinion on the way to implement it. My only
>> requirement is that it becomes enabled by default, without any userspace
>> change.
> 
> I think we can turn it on by default in KVM, no matter what API we choose,
> and then enable userspace (with whatever API) to turn it off. Newer
> machine types certainly wouldn't do that, and, as later PSCI is compatible
> with older PSCI, we're probably safe (safer regarding the BTB) not using
> the older PSCI with older machine types either - although that would be up
> for debate and the whole point of adding the API.

OK. At least we're aligned on this. As for your question about finding
out about the register, here's what I have in kvmtool:

+       reg.addr = (u64)&data;
+       reg.id = KVM_REG_ARM_PSCI_VERSION;
+       err = ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg);
+       if (err < 0)
+               pr_info("Unable to get PSCI version\n");
+       else
+               pr_info("PSCI version %llx\n", data);

If you get an error, the feature doesn't exist. One of the reasons for
using a register is that migration works with today's QEMU. And if you
try to restore a VM that's aware of the PSCI version (and possibly of
the BTB invalidation) on a host that doesn't support it, you get a fail
without any change of userspace.

To me, that's a pretty good argument in favour of this method. But if
you have strong feelings about it and would like me to implement
something else, please let me know ASAP. We'd like this series to land
in -rc1, so we only have a few days left...

>>
>>>
>>>> +
>>>> +The following register is defined:
>>>> +
>>>> +* KVM_REG_ARM_PSCI_VERSION:
>>>> +
>>>> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
>>>> +  - Returns the current PSCI version on GET_ONE_REG
>>>> +  - Allows any supported PSCI version compatible with v0.2 to be set
>>>> +    with SET_ONE_REG
>>>> +  - Affects the whole VM (even if the register view is per-vcpu)
>>>
>>>
>>>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
>>>> index acbf9ec7b396..e9d57060d88c 100644
>>>> --- a/arch/arm/include/asm/kvm_host.h
>>>> +++ b/arch/arm/include/asm/kvm_host.h
>>>> @@ -75,6 +75,9 @@ struct kvm_arch {
>>>>  	/* Interrupt controller */
>>>>  	struct vgic_dist	vgic;
>>>>  	int max_vcpus;
>>>> +
>>>> +	/* Mandated version of PSCI */
>>>> +	u32 psci_version;
>>>>  };
>>>>  
>>>>  #define KVM_NR_MEM_OBJS     40
>>>> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
>>>> index 6edd177bb1c7..47dfc99f5cd0 100644
>>>> --- a/arch/arm/include/uapi/asm/kvm.h
>>>> +++ b/arch/arm/include/uapi/asm/kvm.h
>>>> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
>>>>  #define KVM_REG_ARM_VFP_FPINST		0x1009
>>>>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
>>>>  
>>>> +/* KVM-as-firmware specific pseudo-registers */
>>>> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
>>>
>>> Is this 0x14 documented somewhere? I'm just curious how the space for
>>> pseudo registers is reserved. Is there a common place that we should
>>> document that 0x14 is for the firmware (if it's not documented there
>>> already)?
>>
>> No. First come, first served.
> 
> Should we document it in Documentation/ somewhere?
We can. I tend to see the uapi/asm/kvm.h file as the reference (and I
feel that a text file would simply be an English translation of that
file), but I'm not opposed to it either. I'm not sure I have the
bandwidth for that at the moment though.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
  2018-01-31 18:36           ` Marc Zyngier
@ 2018-01-31 19:15             ` Andrew Jones
  -1 siblings, 0 replies; 116+ messages in thread
From: Andrew Jones @ 2018-01-31 19:15 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Lorenzo Pieralisi,
	Ard Biesheuvel, Catalin Marinas, Will Deacon, Jon Masters,
	Robin Murphy

On Wed, Jan 31, 2018 at 06:36:38PM +0000, Marc Zyngier wrote:
> On 31/01/18 18:03, Andrew Jones wrote:
> > On Wed, Jan 31, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
> >> On 31/01/18 17:38, Andrew Jones wrote:
> >>> On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
> >>>> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
> >>>> Since all the new PSCI versions are backward compatible, we decide to
> >>>> default to the latest version of the PSCI implementation. This is no
> >>>> different from doing a firmware upgrade on KVM.
> >>>>
> >>>> But in order to give a chance to hypothetical badly implemented guests
> >>>> that would have a fit by discovering something other than PSCI 0.2,
> >>>> let's provide a new API that allows userspace to pick one particular
> >>>> version of the API.
> >>>>
> >>>> This is implemented as a new class of "firmware" registers, where
> >>>> we expose the PSCI version. This allows the PSCI version to be
> >>>> save/restored as part of a guest migration, and also set to
> >>>> any supported version if the guest requires it.
> >>>>
> >>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >>>> ---
> >>>>  Documentation/virtual/kvm/api.txt      |  3 +-
> >>>>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
> >>>>  arch/arm/include/asm/kvm_host.h        |  3 ++
> >>>>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
> >>>>  arch/arm/kvm/guest.c                   | 13 +++++++
> >>>>  arch/arm64/include/asm/kvm_host.h      |  3 ++
> >>>>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
> >>>>  arch/arm64/kvm/guest.c                 | 14 ++++++-
> >>>>  include/kvm/arm_psci.h                 |  9 +++++
> >>>>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
> >>>>  10 files changed, 149 insertions(+), 4 deletions(-)
> >>>>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
> >>>>
> >>>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> >>>> index 57d3ee9e4bde..334905202141 100644
> >>>> --- a/Documentation/virtual/kvm/api.txt
> >>>> +++ b/Documentation/virtual/kvm/api.txt
> >>>> @@ -2493,7 +2493,8 @@ Possible features:
> >>>>  	  and execute guest code when KVM_RUN is called.
> >>>>  	- 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.
> >>>> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
> >>>> +          backward compatible with v0.2) for the CPU.
> >>>>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
> >>>>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
> >>>>  	  Depends on KVM_CAP_ARM_PMU_V3.
> >>>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> >>>> new file mode 100644
> >>>> index 000000000000..2e49a4e9f084
> >>>> --- /dev/null
> >>>> +++ b/Documentation/virtual/kvm/arm/psci.txt
> >>>> @@ -0,0 +1,28 @@
> >>>> +KVM implements the PSCI (Power State Coordination Interface)
> >>>> +specification in order to provide services such as CPU on/off, reset
> >>>> +and power-off to the guest.
> >>>> +
> >>>> +The PSCI specification is regularly updated to provide new features,
> >>>> +and KVM implements these updates if they make sense from a virtualization
> >>>> +point of view.
> >>>> +
> >>>> +This means that a guest booted on two different versions of KVM can
> >>>> +observe two different "firmware" revisions. This could cause issues if
> >>>> +a given guest is tied to a particular PSCI revision (unlikely), or if
> >>>> +a migration causes a different PSCI version to be exposed out of the
> >>>> +blue to an unsuspecting guest.
> >>>> +
> >>>> +In order to remedy this situation, KVM exposes a set of "firmware
> >>>> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> >>>> +interface. These registers can be saved/restored by userspace, and set
> >>>> +to a convenient value if required.
> >>>
> >>> Userspace can save/restore any state it deems necessary. 
> >>
> >> Only if it has access to it. Until now, that wasn't an option.
> >>
> >>> Is there another
> >>> reason to invent a pseudo register? Considering the PSCI version is VM
> >>> state, then maybe a VM "device" attribute[*], like s390 use, would fit
> >>> better. 
> >>
> >> Possibly. But that means current userspace won't engage the mitigation
> >> by default, and that's pretty bad.
> >>
> >>> Or, if keeping it VCPU state has some benefit, then we already
> >>> have VCPU device attribute support for ARM that we could extend with
> >>> another attribute. An advantage of using the device-attr API is that it
> >>> has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
> >>> How should userspace check if the pseudo register is supported? Maybe
> >>> by just failing with NOT_SUPPORTED to get/set it?
> >>>
> >>> [*] Documentation/virtual/kvm/devices/vm.txt
> >>
> >> Frankly, I have no opinion on the way to implement it. My only
> >> requirement is that it becomes enabled by default, without any userspace
> >> change.
> > 
> > I think we can turn it on by default in KVM, no matter what API we choose,
> > and then enable userspace (with whatever API) to turn it off. Newer
> > machine types certainly wouldn't do that, and, as later PSCI is compatible
> > with older PSCI, we're probably safe (safer regarding the BTB) not using
> > the older PSCI with older machine types either - although that would be up
> > for debate and the whole point of adding the API.
> 
> OK. At least we're aligned on this. As for your question about finding
> out about the register, here's what I have in kvmtool:

Actually I was starting to have some second thoughts about that default,
but...

> 
> +       reg.addr = (u64)&data;
> +       reg.id = KVM_REG_ARM_PSCI_VERSION;
> +       err = ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg);
> +       if (err < 0)
> +               pr_info("Unable to get PSCI version\n");
> +       else
> +               pr_info("PSCI version %llx\n", data);
> 
> If you get an error, the feature doesn't exist. One of the reasons for
> using a register is that migration works with today's QEMU. And if you
> try to restore a VM that's aware of the PSCI version (and possibly of
> the BTB invalidation) on a host that doesn't support it, you get a fail
> without any change of userspace.
> 
> To me, that's a pretty good argument in favour of this method. But if

...I agree that does sound like a good argument.

> you have strong feelings about it and would like me to implement
> something else, please let me know ASAP. We'd like this series to land
> in -rc1, so we only have a few days left...

I'll do some experiments tomorrow and let you know if my second thoughts
are valid concerns right away.

> 
> >>
> >>>
> >>>> +
> >>>> +The following register is defined:
> >>>> +
> >>>> +* KVM_REG_ARM_PSCI_VERSION:
> >>>> +
> >>>> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> >>>> +  - Returns the current PSCI version on GET_ONE_REG
> >>>> +  - Allows any supported PSCI version compatible with v0.2 to be set
> >>>> +    with SET_ONE_REG
> >>>> +  - Affects the whole VM (even if the register view is per-vcpu)
> >>>
> >>>
> >>>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >>>> index acbf9ec7b396..e9d57060d88c 100644
> >>>> --- a/arch/arm/include/asm/kvm_host.h
> >>>> +++ b/arch/arm/include/asm/kvm_host.h
> >>>> @@ -75,6 +75,9 @@ struct kvm_arch {
> >>>>  	/* Interrupt controller */
> >>>>  	struct vgic_dist	vgic;
> >>>>  	int max_vcpus;
> >>>> +
> >>>> +	/* Mandated version of PSCI */
> >>>> +	u32 psci_version;
> >>>>  };
> >>>>  
> >>>>  #define KVM_NR_MEM_OBJS     40
> >>>> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> >>>> index 6edd177bb1c7..47dfc99f5cd0 100644
> >>>> --- a/arch/arm/include/uapi/asm/kvm.h
> >>>> +++ b/arch/arm/include/uapi/asm/kvm.h
> >>>> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
> >>>>  #define KVM_REG_ARM_VFP_FPINST		0x1009
> >>>>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
> >>>>  
> >>>> +/* KVM-as-firmware specific pseudo-registers */
> >>>> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> >>>
> >>> Is this 0x14 documented somewhere? I'm just curious how the space for
> >>> pseudo registers is reserved. Is there a common place that we should
> >>> document that 0x14 is for the firmware (if it's not documented there
> >>> already)?
> >>
> >> No. First come, first served.
> > 
> > Should we document it in Documentation/ somewhere?
> We can. I tend to see the uapi/asm/kvm.h file as the reference (and I
> feel that a text file would simply be an English translation of that
> file), but I'm not opposed to it either. I'm not sure I have the
> bandwidth for that at the moment though.

Yeah, docs can come later. But now that I look, I think we just need a
couple lines in Documentation/virtual/kvm/api.txt like

ARM 32-bit firmware registers have the following id bit patterns:
  0x4030 0000 0014 0 <regno:16>

ARM 64-bit firmware registers have the following id bit patterns:
  0x6030 0000 0014 0 <regno:16>

(I'm not sure those are correct. I'd expect both to start with 4 like
 the other entries in that file, but maybe not, or the other 64-bit
 entries in that file aren't correct?)

Thanks,
drew

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API
@ 2018-01-31 19:15             ` Andrew Jones
  0 siblings, 0 replies; 116+ messages in thread
From: Andrew Jones @ 2018-01-31 19:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 31, 2018 at 06:36:38PM +0000, Marc Zyngier wrote:
> On 31/01/18 18:03, Andrew Jones wrote:
> > On Wed, Jan 31, 2018 at 05:45:56PM +0000, Marc Zyngier wrote:
> >> On 31/01/18 17:38, Andrew Jones wrote:
> >>> On Mon, Jan 29, 2018 at 05:45:50PM +0000, Marc Zyngier wrote:
> >>>> Although we've implemented PSCI 1.0 and 1.1, nothing can select them
> >>>> Since all the new PSCI versions are backward compatible, we decide to
> >>>> default to the latest version of the PSCI implementation. This is no
> >>>> different from doing a firmware upgrade on KVM.
> >>>>
> >>>> But in order to give a chance to hypothetical badly implemented guests
> >>>> that would have a fit by discovering something other than PSCI 0.2,
> >>>> let's provide a new API that allows userspace to pick one particular
> >>>> version of the API.
> >>>>
> >>>> This is implemented as a new class of "firmware" registers, where
> >>>> we expose the PSCI version. This allows the PSCI version to be
> >>>> save/restored as part of a guest migration, and also set to
> >>>> any supported version if the guest requires it.
> >>>>
> >>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >>>> ---
> >>>>  Documentation/virtual/kvm/api.txt      |  3 +-
> >>>>  Documentation/virtual/kvm/arm/psci.txt | 28 ++++++++++++++
> >>>>  arch/arm/include/asm/kvm_host.h        |  3 ++
> >>>>  arch/arm/include/uapi/asm/kvm.h        |  6 +++
> >>>>  arch/arm/kvm/guest.c                   | 13 +++++++
> >>>>  arch/arm64/include/asm/kvm_host.h      |  3 ++
> >>>>  arch/arm64/include/uapi/asm/kvm.h      |  6 +++
> >>>>  arch/arm64/kvm/guest.c                 | 14 ++++++-
> >>>>  include/kvm/arm_psci.h                 |  9 +++++
> >>>>  virt/kvm/arm/psci.c                    | 68 +++++++++++++++++++++++++++++++++-
> >>>>  10 files changed, 149 insertions(+), 4 deletions(-)
> >>>>  create mode 100644 Documentation/virtual/kvm/arm/psci.txt
> >>>>
> >>>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> >>>> index 57d3ee9e4bde..334905202141 100644
> >>>> --- a/Documentation/virtual/kvm/api.txt
> >>>> +++ b/Documentation/virtual/kvm/api.txt
> >>>> @@ -2493,7 +2493,8 @@ Possible features:
> >>>>  	  and execute guest code when KVM_RUN is called.
> >>>>  	- 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.
> >>>> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
> >>>> +          backward compatible with v0.2) for the CPU.
> >>>>  	  Depends on KVM_CAP_ARM_PSCI_0_2.
> >>>>  	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
> >>>>  	  Depends on KVM_CAP_ARM_PMU_V3.
> >>>> diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
> >>>> new file mode 100644
> >>>> index 000000000000..2e49a4e9f084
> >>>> --- /dev/null
> >>>> +++ b/Documentation/virtual/kvm/arm/psci.txt
> >>>> @@ -0,0 +1,28 @@
> >>>> +KVM implements the PSCI (Power State Coordination Interface)
> >>>> +specification in order to provide services such as CPU on/off, reset
> >>>> +and power-off to the guest.
> >>>> +
> >>>> +The PSCI specification is regularly updated to provide new features,
> >>>> +and KVM implements these updates if they make sense from a virtualization
> >>>> +point of view.
> >>>> +
> >>>> +This means that a guest booted on two different versions of KVM can
> >>>> +observe two different "firmware" revisions. This could cause issues if
> >>>> +a given guest is tied to a particular PSCI revision (unlikely), or if
> >>>> +a migration causes a different PSCI version to be exposed out of the
> >>>> +blue to an unsuspecting guest.
> >>>> +
> >>>> +In order to remedy this situation, KVM exposes a set of "firmware
> >>>> +pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> >>>> +interface. These registers can be saved/restored by userspace, and set
> >>>> +to a convenient value if required.
> >>>
> >>> Userspace can save/restore any state it deems necessary. 
> >>
> >> Only if it has access to it. Until now, that wasn't an option.
> >>
> >>> Is there another
> >>> reason to invent a pseudo register? Considering the PSCI version is VM
> >>> state, then maybe a VM "device" attribute[*], like s390 use, would fit
> >>> better. 
> >>
> >> Possibly. But that means current userspace won't engage the mitigation
> >> by default, and that's pretty bad.
> >>
> >>> Or, if keeping it VCPU state has some benefit, then we already
> >>> have VCPU device attribute support for ARM that we could extend with
> >>> another attribute. An advantage of using the device-attr API is that it
> >>> has KVM_HAS_DEVICE_ATTR, allowing the new attribute support to be probed.
> >>> How should userspace check if the pseudo register is supported? Maybe
> >>> by just failing with NOT_SUPPORTED to get/set it?
> >>>
> >>> [*] Documentation/virtual/kvm/devices/vm.txt
> >>
> >> Frankly, I have no opinion on the way to implement it. My only
> >> requirement is that it becomes enabled by default, without any userspace
> >> change.
> > 
> > I think we can turn it on by default in KVM, no matter what API we choose,
> > and then enable userspace (with whatever API) to turn it off. Newer
> > machine types certainly wouldn't do that, and, as later PSCI is compatible
> > with older PSCI, we're probably safe (safer regarding the BTB) not using
> > the older PSCI with older machine types either - although that would be up
> > for debate and the whole point of adding the API.
> 
> OK. At least we're aligned on this. As for your question about finding
> out about the register, here's what I have in kvmtool:

Actually I was starting to have some second thoughts about that default,
but...

> 
> +       reg.addr = (u64)&data;
> +       reg.id = KVM_REG_ARM_PSCI_VERSION;
> +       err = ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg);
> +       if (err < 0)
> +               pr_info("Unable to get PSCI version\n");
> +       else
> +               pr_info("PSCI version %llx\n", data);
> 
> If you get an error, the feature doesn't exist. One of the reasons for
> using a register is that migration works with today's QEMU. And if you
> try to restore a VM that's aware of the PSCI version (and possibly of
> the BTB invalidation) on a host that doesn't support it, you get a fail
> without any change of userspace.
> 
> To me, that's a pretty good argument in favour of this method. But if

...I agree that does sound like a good argument.

> you have strong feelings about it and would like me to implement
> something else, please let me know ASAP. We'd like this series to land
> in -rc1, so we only have a few days left...

I'll do some experiments tomorrow and let you know if my second thoughts
are valid concerns right away.

> 
> >>
> >>>
> >>>> +
> >>>> +The following register is defined:
> >>>> +
> >>>> +* KVM_REG_ARM_PSCI_VERSION:
> >>>> +
> >>>> +  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> >>>> +  - Returns the current PSCI version on GET_ONE_REG
> >>>> +  - Allows any supported PSCI version compatible with v0.2 to be set
> >>>> +    with SET_ONE_REG
> >>>> +  - Affects the whole VM (even if the register view is per-vcpu)
> >>>
> >>>
> >>>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >>>> index acbf9ec7b396..e9d57060d88c 100644
> >>>> --- a/arch/arm/include/asm/kvm_host.h
> >>>> +++ b/arch/arm/include/asm/kvm_host.h
> >>>> @@ -75,6 +75,9 @@ struct kvm_arch {
> >>>>  	/* Interrupt controller */
> >>>>  	struct vgic_dist	vgic;
> >>>>  	int max_vcpus;
> >>>> +
> >>>> +	/* Mandated version of PSCI */
> >>>> +	u32 psci_version;
> >>>>  };
> >>>>  
> >>>>  #define KVM_NR_MEM_OBJS     40
> >>>> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> >>>> index 6edd177bb1c7..47dfc99f5cd0 100644
> >>>> --- a/arch/arm/include/uapi/asm/kvm.h
> >>>> +++ b/arch/arm/include/uapi/asm/kvm.h
> >>>> @@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
> >>>>  #define KVM_REG_ARM_VFP_FPINST		0x1009
> >>>>  #define KVM_REG_ARM_VFP_FPINST2		0x100A
> >>>>  
> >>>> +/* KVM-as-firmware specific pseudo-registers */
> >>>> +#define KVM_REG_ARM_FW			(0x0014 << KVM_REG_ARM_COPROC_SHIFT)
> >>>
> >>> Is this 0x14 documented somewhere? I'm just curious how the space for
> >>> pseudo registers is reserved. Is there a common place that we should
> >>> document that 0x14 is for the firmware (if it's not documented there
> >>> already)?
> >>
> >> No. First come, first served.
> > 
> > Should we document it in Documentation/ somewhere?
> We can. I tend to see the uapi/asm/kvm.h file as the reference (and I
> feel that a text file would simply be an English translation of that
> file), but I'm not opposed to it either. I'm not sure I have the
> bandwidth for that at the moment though.

Yeah, docs can come later. But now that I look, I think we just need a
couple lines in Documentation/virtual/kvm/api.txt like

ARM 32-bit firmware registers have the following id bit patterns:
  0x4030 0000 0014 0 <regno:16>

ARM 64-bit firmware registers have the following id bit patterns:
  0x6030 0000 0014 0 <regno:16>

(I'm not sure those are correct. I'd expect both to start with 4 like
 the other entries in that file, but maybe not, or the other 64-bit
 entries in that file aren't correct?)

Thanks,
drew

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-01-31 15:05             ` Marc Zyngier
@ 2018-02-01  2:40               ` Hanjun Guo
  -1 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-02-01  2:40 UTC (permalink / raw)
  To: Marc Zyngier, Ard Biesheuvel
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 2018/1/31 23:05, Marc Zyngier wrote:
> On 31/01/18 14:38, Ard Biesheuvel wrote:
>> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>>> Hi Marc,
>>>>>
>>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>>  {
>>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>>
>>>>>> -    if (psci_ops.get_version)
>>>>>> +    if (psci_ops.get_version) {
>>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>>> +                    return 0;
>>>>>
>>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>>> for CVE-2017-5715, but..
>>>>>
>>>>>> +
>>>>>>              install_bp_hardening_cb(entry,
>>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>>                                     __psci_hyp_bp_inval_end);
>>>>>
>>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>>> trap to trust firmware even the new version of firmware didn't say
>>>>> we need the workaround, did I understand it correctly?
>>>>
>>>> Well, you only get there if we've established that your CPU is affected
>>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>>> capability), and that entry points to enable_psci_bp_hardening. It is

I understand, but A53, A57, A72 and etc are always in the list :)

>>>> not the firmware that decides whether we need hardening, but the kernel.
>>>> The firmware merely provides a facility to apply the hardening.
>>>>
>>>>> I'm ask this because some platform will not expose to users to
>>>>> take advantage of CVE-2017-5715, and we can use different firmware
>>>>> to report we need such workaround or not, then use a single kernel
>>>>> image for both vulnerable platforms and no vulnerable ones.
>>>>
>>>> You cannot have your cake and eat it. If you don't want to workaround
>>>> the issue, you can disable the hardening. But asking for the same kernel
>>>> to do both depending on what the firmware reports doesn't make much
>>>> sense to me.
>>>
>>> The SMCCC v1.1. document does appear to imply that systems that
>>> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
>>> should be assumed to be unaffected.
>>>
>>> """
>>> If the discovery call returns NOT_SUPPORTED:
>>> • SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
>>> • none of the PEs in the system require firmware mitigation for CVE-2017-5715.
>>> """
>>>
>>> How to deal with conflicting information in this regard (quirk table
>>> vs firmware implementation) is a matter of policy, of course.
> 
> Yup. And the current approach fits the spec, I believe. The

Yes, approach in this patch set fits the spec, it just conflicts with
MIDR based approach.

> PSCI_GET_VERSION band-aid should normally be removed shortly after these
> patches hit mainline.

I'm a big fan of this :)

> 
>>
>> ... and actually, perhaps it makes sense for the
>> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
>> based errata matching?
>>
>> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
>> we should probably invoke it even if the MIDR is not known to belong
>> to an affected implementation.
> 
> This would have an impact on big-little systems, for which there is
> often a bunch of unaffected CPUs.

I think it's what we are doing now, SMCCC v1.1 didn't provide the ability
to report per-cpu SMCCC_ARCH_WORKAROUND_1, and it said:
 - The discovery call must return the same result on all PEs in the system.
 - In heterogeneous systems with some PEs that require mitigation and others
   that do not, the firmware must provide a safe implementation of this
   function on all PEs.

So from the spec that it's the firmware to take care of unaffected CPUs,
to the kernel it's the same.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-02-01  2:40               ` Hanjun Guo
  0 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-02-01  2:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 2018/1/31 23:05, Marc Zyngier wrote:
> On 31/01/18 14:38, Ard Biesheuvel wrote:
>> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>>> Hi Marc,
>>>>>
>>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>>  {
>>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>>
>>>>>> -    if (psci_ops.get_version)
>>>>>> +    if (psci_ops.get_version) {
>>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>>> +                    return 0;
>>>>>
>>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>>> for CVE-2017-5715, but..
>>>>>
>>>>>> +
>>>>>>              install_bp_hardening_cb(entry,
>>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>>                                     __psci_hyp_bp_inval_end);
>>>>>
>>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>>> trap to trust firmware even the new version of firmware didn't say
>>>>> we need the workaround, did I understand it correctly?
>>>>
>>>> Well, you only get there if we've established that your CPU is affected
>>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>>> capability), and that entry points to enable_psci_bp_hardening. It is

I understand, but A53, A57, A72 and etc are always in the list :)

>>>> not the firmware that decides whether we need hardening, but the kernel.
>>>> The firmware merely provides a facility to apply the hardening.
>>>>
>>>>> I'm ask this because some platform will not expose to users to
>>>>> take advantage of CVE-2017-5715, and we can use different firmware
>>>>> to report we need such workaround or not, then use a single kernel
>>>>> image for both vulnerable platforms and no vulnerable ones.
>>>>
>>>> You cannot have your cake and eat it. If you don't want to workaround
>>>> the issue, you can disable the hardening. But asking for the same kernel
>>>> to do both depending on what the firmware reports doesn't make much
>>>> sense to me.
>>>
>>> The SMCCC v1.1. document does appear to imply that systems that
>>> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
>>> should be assumed to be unaffected.
>>>
>>> """
>>> If the discovery call returns NOT_SUPPORTED:
>>> ? SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
>>> ? none of the PEs in the system require firmware mitigation for CVE-2017-5715.
>>> """
>>>
>>> How to deal with conflicting information in this regard (quirk table
>>> vs firmware implementation) is a matter of policy, of course.
> 
> Yup. And the current approach fits the spec, I believe. The

Yes, approach in this patch set fits the spec, it just conflicts with
MIDR based approach.

> PSCI_GET_VERSION band-aid should normally be removed shortly after these
> patches hit mainline.

I'm a big fan of this :)

> 
>>
>> ... and actually, perhaps it makes sense for the
>> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
>> based errata matching?
>>
>> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
>> we should probably invoke it even if the MIDR is not known to belong
>> to an affected implementation.
> 
> This would have an impact on big-little systems, for which there is
> often a bunch of unaffected CPUs.

I think it's what we are doing now, SMCCC v1.1 didn't provide the ability
to report per-cpu SMCCC_ARCH_WORKAROUND_1, and it said:
 - The discovery call must return the same result on all PEs in the system.
 - In heterogeneous systems with some PEs that require mitigation and others
   that do not, the firmware must provide a safe implementation of this
   function on all PEs.

So from the spec that it's the firmware to take care of unaffected CPUs,
to the kernel it's the same.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-02-01  2:40               ` Hanjun Guo
  (?)
@ 2018-02-01  6:52                 ` Hanjun Guo
  -1 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-02-01  6:52 UTC (permalink / raw)
  To: Marc Zyngier, Ard Biesheuvel
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 2018/2/1 10:40, Hanjun Guo wrote:
> On 2018/1/31 23:05, Marc Zyngier wrote:
>> On 31/01/18 14:38, Ard Biesheuvel wrote:
>>> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>>>> Hi Marc,
>>>>>>
>>>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>>>  {
>>>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>>>
>>>>>>> -    if (psci_ops.get_version)
>>>>>>> +    if (psci_ops.get_version) {
>>>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>>>> +                    return 0;
>>>>>>
>>>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>>>> for CVE-2017-5715, but..
>>>>>>
>>>>>>> +
>>>>>>>              install_bp_hardening_cb(entry,
>>>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>>>                                     __psci_hyp_bp_inval_end);
>>>>>>
>>>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>>>> trap to trust firmware even the new version of firmware didn't say
>>>>>> we need the workaround, did I understand it correctly?
>>>>>
>>>>> Well, you only get there if we've established that your CPU is affected
>>>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>>>> capability), and that entry points to enable_psci_bp_hardening. It is
> 
> I understand, but A53, A57, A72 and etc are always in the list :)

Sorry, A53 is not susceptible to branch predictor aliasing..

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-02-01  6:52                 ` Hanjun Guo
  0 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-02-01  6:52 UTC (permalink / raw)
  To: Marc Zyngier, Ard Biesheuvel
  Cc: Mark Rutland, Peter Maydell, Lorenzo Pieralisi, Catalin Marinas,
	Will Deacon, Linux Kernel Mailing List, Christoffer Dall,
	Jon Masters, Robin Murphy, kvmarm, linux-arm-kernel

On 2018/2/1 10:40, Hanjun Guo wrote:
> On 2018/1/31 23:05, Marc Zyngier wrote:
>> On 31/01/18 14:38, Ard Biesheuvel wrote:
>>> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>>>> Hi Marc,
>>>>>>
>>>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>>>  {
>>>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>>>
>>>>>>> -    if (psci_ops.get_version)
>>>>>>> +    if (psci_ops.get_version) {
>>>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>>>> +                    return 0;
>>>>>>
>>>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>>>> for CVE-2017-5715, but..
>>>>>>
>>>>>>> +
>>>>>>>              install_bp_hardening_cb(entry,
>>>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>>>                                     __psci_hyp_bp_inval_end);
>>>>>>
>>>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>>>> trap to trust firmware even the new version of firmware didn't say
>>>>>> we need the workaround, did I understand it correctly?
>>>>>
>>>>> Well, you only get there if we've established that your CPU is affected
>>>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>>>> capability), and that entry points to enable_psci_bp_hardening. It is
> 
> I understand, but A53, A57, A72 and etc are always in the list :)

Sorry, A53 is not susceptible to branch predictor aliasing..

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-02-01  6:52                 ` Hanjun Guo
  0 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-02-01  6:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 2018/2/1 10:40, Hanjun Guo wrote:
> On 2018/1/31 23:05, Marc Zyngier wrote:
>> On 31/01/18 14:38, Ard Biesheuvel wrote:
>>> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>>>> Hi Marc,
>>>>>>
>>>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>>>  {
>>>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>>>
>>>>>>> -    if (psci_ops.get_version)
>>>>>>> +    if (psci_ops.get_version) {
>>>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>>>> +                    return 0;
>>>>>>
>>>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>>>> for CVE-2017-5715, but..
>>>>>>
>>>>>>> +
>>>>>>>              install_bp_hardening_cb(entry,
>>>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>>>                                     __psci_hyp_bp_inval_end);
>>>>>>
>>>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>>>> trap to trust firmware even the new version of firmware didn't say
>>>>>> we need the workaround, did I understand it correctly?
>>>>>
>>>>> Well, you only get there if we've established that your CPU is affected
>>>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>>>> capability), and that entry points to enable_psci_bp_hardening. It is
> 
> I understand, but A53, A57, A72 and etc are always in the list :)

Sorry, A53 is not susceptible to branch predictor aliasing..

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-02-01  2:40               ` Hanjun Guo
@ 2018-02-01  8:53                 ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-02-01  8:53 UTC (permalink / raw)
  To: Hanjun Guo, Ard Biesheuvel
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 01/02/18 02:40, Hanjun Guo wrote:
> On 2018/1/31 23:05, Marc Zyngier wrote:
>> On 31/01/18 14:38, Ard Biesheuvel wrote:
>>> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>>>> Hi Marc,
>>>>>>
>>>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>>>  {
>>>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>>>
>>>>>>> -    if (psci_ops.get_version)
>>>>>>> +    if (psci_ops.get_version) {
>>>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>>>> +                    return 0;
>>>>>>
>>>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>>>> for CVE-2017-5715, but..
>>>>>>
>>>>>>> +
>>>>>>>              install_bp_hardening_cb(entry,
>>>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>>>                                     __psci_hyp_bp_inval_end);
>>>>>>
>>>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>>>> trap to trust firmware even the new version of firmware didn't say
>>>>>> we need the workaround, did I understand it correctly?
>>>>>
>>>>> Well, you only get there if we've established that your CPU is affected
>>>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>>>> capability), and that entry points to enable_psci_bp_hardening. It is
> 
> I understand, but A53, A57, A72 and etc are always in the list :)
> 
>>>>> not the firmware that decides whether we need hardening, but the kernel.
>>>>> The firmware merely provides a facility to apply the hardening.
>>>>>
>>>>>> I'm ask this because some platform will not expose to users to
>>>>>> take advantage of CVE-2017-5715, and we can use different firmware
>>>>>> to report we need such workaround or not, then use a single kernel
>>>>>> image for both vulnerable platforms and no vulnerable ones.
>>>>>
>>>>> You cannot have your cake and eat it. If you don't want to workaround
>>>>> the issue, you can disable the hardening. But asking for the same kernel
>>>>> to do both depending on what the firmware reports doesn't make much
>>>>> sense to me.
>>>>
>>>> The SMCCC v1.1. document does appear to imply that systems that
>>>> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
>>>> should be assumed to be unaffected.
>>>>
>>>> """
>>>> If the discovery call returns NOT_SUPPORTED:
>>>> • SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
>>>> • none of the PEs in the system require firmware mitigation for CVE-2017-5715.
>>>> """
>>>>
>>>> How to deal with conflicting information in this regard (quirk table
>>>> vs firmware implementation) is a matter of policy, of course.
>>
>> Yup. And the current approach fits the spec, I believe. The
> 
> Yes, approach in this patch set fits the spec, it just conflicts with
> MIDR based approach.

No it doesn't. We know that A72 is affected. However you look at it,
there is no way around that fact. So if you have an affected CPU *and*
you implement SMCCC 1.1 with WORKAROUND_1, you get the mitigation.

If your firmware doesn't implement it, blame your provider for supplying
you with an outdated firmware.

>> PSCI_GET_VERSION band-aid should normally be removed shortly after these
>> patches hit mainline.
> 
> I'm a big fan of this :)
> 
>>
>>>
>>> ... and actually, perhaps it makes sense for the
>>> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
>>> based errata matching?
>>>
>>> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
>>> we should probably invoke it even if the MIDR is not known to belong
>>> to an affected implementation.
>>
>> This would have an impact on big-little systems, for which there is
>> often a bunch of unaffected CPUs.
> 
> I think it's what we are doing now, SMCCC v1.1 didn't provide the ability
> to report per-cpu SMCCC_ARCH_WORKAROUND_1, and it said:
>  - The discovery call must return the same result on all PEs in the system.
>  - In heterogeneous systems with some PEs that require mitigation and others
>    that do not, the firmware must provide a safe implementation of this
>    function on all PEs.
> 
> So from the spec that it's the firmware to take care of unaffected CPUs,
> to the kernel it's the same.

The spec makes it safe. The MIDR list makes it fast.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-02-01  8:53                 ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-02-01  8:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/02/18 02:40, Hanjun Guo wrote:
> On 2018/1/31 23:05, Marc Zyngier wrote:
>> On 31/01/18 14:38, Ard Biesheuvel wrote:
>>> On 31 January 2018 at 14:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>>>> On 31 January 2018 at 14:11, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>>>> On 31/01/18 13:56, Hanjun Guo wrote:
>>>>>> Hi Marc,
>>>>>>
>>>>>> On 2018/1/30 1:45, Marc Zyngier wrote:
>>>>>>>  static int enable_psci_bp_hardening(void *data)
>>>>>>>  {
>>>>>>>      const struct arm64_cpu_capabilities *entry = data;
>>>>>>>
>>>>>>> -    if (psci_ops.get_version)
>>>>>>> +    if (psci_ops.get_version) {
>>>>>>> +            if (check_smccc_arch_workaround_1(entry))
>>>>>>> +                    return 0;
>>>>>>
>>>>>> If I'm using the new version SMCCC, the firmware have the choicARM_SMCCC_ARCH_WORKAROUND_1e to decide
>>>>>> whether this machine needs the workaround, even if the CPU is vulnerable
>>>>>> for CVE-2017-5715, but..
>>>>>>
>>>>>>> +
>>>>>>>              install_bp_hardening_cb(entry,
>>>>>>>                                     (bp_hardening_cb_t)psci_ops.get_version,
>>>>>>>                                     __psci_hyp_bp_inval_start,
>>>>>>>                                     __psci_hyp_bp_inval_end);
>>>>>>
>>>>>> ..the code above seems will enable get_psci_version() for CPU and will
>>>>>> trap to trust firmware even the new version of firmware didn't say
>>>>>> we need the workaround, did I understand it correctly?
>>>>>
>>>>> Well, you only get there if we've established that your CPU is affected
>>>>> (it has an entry matching its MIDR with the HARDEN_BRANCH_PREDICTOR
>>>>> capability), and that entry points to enable_psci_bp_hardening. It is
> 
> I understand, but A53, A57, A72 and etc are always in the list :)
> 
>>>>> not the firmware that decides whether we need hardening, but the kernel.
>>>>> The firmware merely provides a facility to apply the hardening.
>>>>>
>>>>>> I'm ask this because some platform will not expose to users to
>>>>>> take advantage of CVE-2017-5715, and we can use different firmware
>>>>>> to report we need such workaround or not, then use a single kernel
>>>>>> image for both vulnerable platforms and no vulnerable ones.
>>>>>
>>>>> You cannot have your cake and eat it. If you don't want to workaround
>>>>> the issue, you can disable the hardening. But asking for the same kernel
>>>>> to do both depending on what the firmware reports doesn't make much
>>>>> sense to me.
>>>>
>>>> The SMCCC v1.1. document does appear to imply that systems that
>>>> implement SMCCC v1.1 but don't implement ARM_SMCCC_ARCH_WORKAROUND_1
>>>> should be assumed to be unaffected.
>>>>
>>>> """
>>>> If the discovery call returns NOT_SUPPORTED:
>>>> ? SMCCC_ARCH_WORKAROUND_1 must not be invoked on any PE in the system, and
>>>> ? none of the PEs in the system require firmware mitigation for CVE-2017-5715.
>>>> """
>>>>
>>>> How to deal with conflicting information in this regard (quirk table
>>>> vs firmware implementation) is a matter of policy, of course.
>>
>> Yup. And the current approach fits the spec, I believe. The
> 
> Yes, approach in this patch set fits the spec, it just conflicts with
> MIDR based approach.

No it doesn't. We know that A72 is affected. However you look at it,
there is no way around that fact. So if you have an affected CPU *and*
you implement SMCCC 1.1 with WORKAROUND_1, you get the mitigation.

If your firmware doesn't implement it, blame your provider for supplying
you with an outdated firmware.

>> PSCI_GET_VERSION band-aid should normally be removed shortly after these
>> patches hit mainline.
> 
> I'm a big fan of this :)
> 
>>
>>>
>>> ... and actually, perhaps it makes sense for the
>>> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
>>> based errata matching?
>>>
>>> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
>>> we should probably invoke it even if the MIDR is not known to belong
>>> to an affected implementation.
>>
>> This would have an impact on big-little systems, for which there is
>> often a bunch of unaffected CPUs.
> 
> I think it's what we are doing now, SMCCC v1.1 didn't provide the ability
> to report per-cpu SMCCC_ARCH_WORKAROUND_1, and it said:
>  - The discovery call must return the same result on all PEs in the system.
>  - In heterogeneous systems with some PEs that require mitigation and others
>    that do not, the firmware must provide a safe implementation of this
>    function on all PEs.
> 
> So from the spec that it's the firmware to take care of unaffected CPUs,
> to the kernel it's the same.

The spec makes it safe. The MIDR list makes it fast.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
  2018-02-01  8:53                 ` Marc Zyngier
@ 2018-02-02  3:43                   ` Hanjun Guo
  -1 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-02-02  3:43 UTC (permalink / raw)
  To: Marc Zyngier, Ard Biesheuvel
  Cc: Linux Kernel Mailing List, linux-arm-kernel, kvmarm,
	Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Jon Masters

On 2018/2/1 16:53, Marc Zyngier wrote:
[...]
>>>> ... and actually, perhaps it makes sense for the
>>>> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
>>>> based errata matching?
>>>>
>>>> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
>>>> we should probably invoke it even if the MIDR is not known to belong
>>>> to an affected implementation.
>>>
>>> This would have an impact on big-little systems, for which there is
>>> often a bunch of unaffected CPUs.
>>
>> I think it's what we are doing now, SMCCC v1.1 didn't provide the ability
>> to report per-cpu SMCCC_ARCH_WORKAROUND_1, and it said:
>>  - The discovery call must return the same result on all PEs in the system.
>>  - In heterogeneous systems with some PEs that require mitigation and others
>>    that do not, the firmware must provide a safe implementation of this
>>    function on all PEs.
>>
>> So from the spec that it's the firmware to take care of unaffected CPUs,
>> to the kernel it's the same.
> 
> The spec makes it safe. The MIDR list makes it fast.

Got it, thank you for clarifying this.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
@ 2018-02-02  3:43                   ` Hanjun Guo
  0 siblings, 0 replies; 116+ messages in thread
From: Hanjun Guo @ 2018-02-02  3:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 2018/2/1 16:53, Marc Zyngier wrote:
[...]
>>>> ... and actually, perhaps it makes sense for the
>>>> SMCCC_ARCH_WORKAROUND_1 check to be completely independent of MIDR
>>>> based errata matching?
>>>>
>>>> I.e., if SMCCC v1.1 and SMCCC_ARCH_WORKAROUND_1 are both implemented,
>>>> we should probably invoke it even if the MIDR is not known to belong
>>>> to an affected implementation.
>>>
>>> This would have an impact on big-little systems, for which there is
>>> often a bunch of unaffected CPUs.
>>
>> I think it's what we are doing now, SMCCC v1.1 didn't provide the ability
>> to report per-cpu SMCCC_ARCH_WORKAROUND_1, and it said:
>>  - The discovery call must return the same result on all PEs in the system.
>>  - In heterogeneous systems with some PEs that require mitigation and others
>>    that do not, the firmware must provide a safe implementation of this
>>    function on all PEs.
>>
>> So from the spec that it's the firmware to take care of unaffected CPUs,
>> to the kernel it's the same.
> 
> The spec makes it safe. The MIDR list makes it fast.

Got it, thank you for clarifying this.

Thanks
Hanjun

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation
  2018-01-29 17:45 ` Marc Zyngier
@ 2018-06-09 13:22   ` Jon Masters
  -1 siblings, 0 replies; 116+ messages in thread
From: Jon Masters @ 2018-06-09 13:22 UTC (permalink / raw)
  To: Marc Zyngier, linux-kernel, linux-arm-kernel, kvmarm
  Cc: Catalin Marinas, Will Deacon, Peter Maydell, Christoffer Dall,
	Lorenzo Pieralisi, Mark Rutland, Robin Murphy, Ard Biesheuvel,
	Jon Masters

Hi Marc,

On 01/29/2018 12:45 PM, Marc Zyngier wrote:

> ARM has recently published a SMC Calling Convention (SMCCC)
> specification update[1] that provides an optimised calling convention
> and optional, discoverable support for mitigating CVE-2017-5715. ARM
> Trusted Firmware (ATF) has already gained such an implementation[2].

Some questions:

1). What's the plan to implement the boot time on/off control for
spectre_v2 mitigations?

2). What's the plan to handle live migration of VMs?

Jon.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation
@ 2018-06-09 13:22   ` Jon Masters
  0 siblings, 0 replies; 116+ messages in thread
From: Jon Masters @ 2018-06-09 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 01/29/2018 12:45 PM, Marc Zyngier wrote:

> ARM has recently published a SMC Calling Convention (SMCCC)
> specification update[1] that provides an optimised calling convention
> and optional, discoverable support for mitigating CVE-2017-5715. ARM
> Trusted Firmware (ATF) has already gained such an implementation[2].

Some questions:

1). What's the plan to implement the boot time on/off control for
spectre_v2 mitigations?

2). What's the plan to handle live migration of VMs?

Jon.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation
  2018-06-09 13:22   ` Jon Masters
  (?)
@ 2018-06-09 14:06     ` Marc Zyngier
  -1 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-06-09 14:06 UTC (permalink / raw)
  To: Jon Masters
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Catalin Marinas,
	Will Deacon, Peter Maydell, Lorenzo Pieralisi, Mark Rutland,
	Robin Murphy, Ard Biesheuvel, Jon Masters, christoffer.dall

Hi Jon,

On Sat, 09 Jun 2018 14:22:27 +0100,
Jon Masters wrote:
> 
> Hi Marc,
> 
> On 01/29/2018 12:45 PM, Marc Zyngier wrote:
> 
> > ARM has recently published a SMC Calling Convention (SMCCC)
> > specification update[1] that provides an optimised calling convention
> > and optional, discoverable support for mitigating CVE-2017-5715. ARM
> > Trusted Firmware (ATF) has already gained such an implementation[2].
> 
> Some questions:
> 
> 1). What's the plan to implement the boot time on/off control for
> spectre_v2 mitigations?

None so far. It can only be disabled at compile time.

> 2). What's the plan to handle live migration of VMs?

[I assume that by "migration of VMs, you actually mean migration of
the mitigation state]

As I mentioned in response to your comment on the variant-4 series,
this is a work in progress, and is mentioned in the cover letter of
that series. Hopefully I'll find time to work on it next week.

	M.

-- 
Jazz is not dead, it just smell funny.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation
@ 2018-06-09 14:06     ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-06-09 14:06 UTC (permalink / raw)
  To: Jon Masters
  Cc: linux-kernel, linux-arm-kernel, kvmarm, Catalin Marinas,
	Will Deacon, Peter Maydell, Lorenzo Pieralisi, Mark Rutland,
	Robin Murphy, Ard Biesheuvel, Jon Masters, christoffer.dall

Hi Jon,

On Sat, 09 Jun 2018 14:22:27 +0100,
Jon Masters wrote:
> 
> Hi Marc,
> 
> On 01/29/2018 12:45 PM, Marc Zyngier wrote:
> 
> > ARM has recently published a SMC Calling Convention (SMCCC)
> > specification update[1] that provides an optimised calling convention
> > and optional, discoverable support for mitigating CVE-2017-5715. ARM
> > Trusted Firmware (ATF) has already gained such an implementation[2].
> 
> Some questions:
> 
> 1). What's the plan to implement the boot time on/off control for
> spectre_v2 mitigations?

None so far. It can only be disabled at compile time.

> 2). What's the plan to handle live migration of VMs?

[I assume that by "migration of VMs, you actually mean migration of
the mitigation state]

As I mentioned in response to your comment on the variant-4 series,
this is a work in progress, and is mentioned in the cover letter of
that series. Hopefully I'll find time to work on it next week.

	M.

-- 
Jazz is not dead, it just smell funny.

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation
@ 2018-06-09 14:06     ` Marc Zyngier
  0 siblings, 0 replies; 116+ messages in thread
From: Marc Zyngier @ 2018-06-09 14:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jon,

On Sat, 09 Jun 2018 14:22:27 +0100,
Jon Masters wrote:
> 
> Hi Marc,
> 
> On 01/29/2018 12:45 PM, Marc Zyngier wrote:
> 
> > ARM has recently published a SMC Calling Convention (SMCCC)
> > specification update[1] that provides an optimised calling convention
> > and optional, discoverable support for mitigating CVE-2017-5715. ARM
> > Trusted Firmware (ATF) has already gained such an implementation[2].
> 
> Some questions:
> 
> 1). What's the plan to implement the boot time on/off control for
> spectre_v2 mitigations?

None so far. It can only be disabled at compile time.

> 2). What's the plan to handle live migration of VMs?

[I assume that by "migration of VMs, you actually mean migration of
the mitigation state]

As I mentioned in response to your comment on the variant-4 series,
this is a work in progress, and is mentioned in the cover letter of
that series. Hopefully I'll find time to work on it next week.

	M.

-- 
Jazz is not dead, it just smell funny.

^ permalink raw reply	[flat|nested] 116+ messages in thread

end of thread, other threads:[~2018-06-09 14:07 UTC | newest]

Thread overview: 116+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-29 17:45 [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation Marc Zyngier
2018-01-29 17:45 ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 01/16] arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 02/16] arm: " Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 03/16] arm/arm64: KVM: Consolidate the PSCI include files Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-30 13:15   ` Robin Murphy
2018-01-30 13:15     ` Robin Murphy
2018-01-30 14:52     ` Marc Zyngier
2018-01-30 14:52       ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 05/16] arm/arm64: KVM: Add smccc accessors to PSCI code Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 06/16] arm/arm64: KVM: Implement PSCI 1.0 support Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-31 17:38   ` Andrew Jones
2018-01-31 17:38     ` Andrew Jones
2018-01-31 17:45     ` Marc Zyngier
2018-01-31 17:45       ` Marc Zyngier
2018-01-31 18:03       ` Andrew Jones
2018-01-31 18:03         ` Andrew Jones
2018-01-31 18:03         ` Andrew Jones
2018-01-31 18:36         ` Marc Zyngier
2018-01-31 18:36           ` Marc Zyngier
2018-01-31 19:15           ` Andrew Jones
2018-01-31 19:15             ` Andrew Jones
2018-01-31 18:11   ` kbuild test robot
2018-01-31 18:11     ` kbuild test robot
2018-01-29 17:45 ` [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1 Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-30  0:23   ` Russell King - ARM Linux
2018-01-30  0:23     ` Russell King - ARM Linux
2018-01-30 12:28     ` Marc Zyngier
2018-01-30 12:28       ` Marc Zyngier
2018-01-30 12:28       ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 09/16] arm/arm64: KVM: Turn kvm_psci_version into a static inline Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 10/16] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-30 12:38   ` Robin Murphy
2018-01-30 12:38     ` Robin Murphy
2018-01-29 17:45 ` [PATCH v2 11/16] arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 12/16] firmware/psci: Expose PSCI conduit Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:55   ` Lorenzo Pieralisi
2018-01-29 17:55     ` Lorenzo Pieralisi
2018-01-29 17:45 ` [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 18:39   ` Lorenzo Pieralisi
2018-01-29 18:39     ` Lorenzo Pieralisi
2018-01-30 12:09     ` Marc Zyngier
2018-01-30 12:09       ` Marc Zyngier
2018-01-30 12:55   ` Robin Murphy
2018-01-30 12:55     ` Robin Murphy
2018-01-30 13:51     ` Marc Zyngier
2018-01-30 13:51       ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 14/16] arm/arm64: smccc: Make function identifiers an unsigned quantity Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45 ` [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 19:07   ` Robin Murphy
2018-01-29 19:07     ` Robin Murphy
2018-01-30  8:54     ` Marc Zyngier
2018-01-30  8:54       ` Marc Zyngier
2018-01-29 21:45   ` Ard Biesheuvel
2018-01-29 21:45     ` Ard Biesheuvel
2018-01-30 12:27     ` Marc Zyngier
2018-01-30 12:27       ` Marc Zyngier
2018-01-30 12:29       ` Ard Biesheuvel
2018-01-30 12:29         ` Ard Biesheuvel
2018-01-30 12:29         ` Ard Biesheuvel
2018-01-29 17:45 ` [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 17:45   ` Marc Zyngier
2018-01-29 19:41   ` Ard Biesheuvel
2018-01-29 19:41     ` Ard Biesheuvel
2018-01-30 12:10     ` Marc Zyngier
2018-01-30 12:10       ` Marc Zyngier
2018-01-31 13:56   ` Hanjun Guo
2018-01-31 13:56     ` Hanjun Guo
2018-01-31 13:56     ` Hanjun Guo
2018-01-31 14:11     ` Marc Zyngier
2018-01-31 14:11       ` Marc Zyngier
2018-01-31 14:35       ` Ard Biesheuvel
2018-01-31 14:35         ` Ard Biesheuvel
2018-01-31 14:38         ` Ard Biesheuvel
2018-01-31 14:38           ` Ard Biesheuvel
2018-01-31 15:05           ` Marc Zyngier
2018-01-31 15:05             ` Marc Zyngier
2018-02-01  2:40             ` Hanjun Guo
2018-02-01  2:40               ` Hanjun Guo
2018-02-01  6:52               ` Hanjun Guo
2018-02-01  6:52                 ` Hanjun Guo
2018-02-01  6:52                 ` Hanjun Guo
2018-02-01  8:53               ` Marc Zyngier
2018-02-01  8:53                 ` Marc Zyngier
2018-02-02  3:43                 ` Hanjun Guo
2018-02-02  3:43                   ` Hanjun Guo
2018-06-09 13:22 ` [PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation Jon Masters
2018-06-09 13:22   ` Jon Masters
2018-06-09 14:06   ` Marc Zyngier
2018-06-09 14:06     ` Marc Zyngier
2018-06-09 14:06     ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.