* [PATCH v3 03/10] KVM: arm64: Implement PV_FEATURES call
From: Steven Price @ 2019-08-21 15:36 UTC (permalink / raw)
To: Marc Zyngier, Will Deacon, linux-arm-kernel, kvmarm
Cc: Steven Price, Catalin Marinas, Paolo Bonzini,
Radim Krčmář, Russell King, James Morse,
Julien Thierry, Suzuki K Pouloze, Mark Rutland, kvm, linux-doc,
linux-kernel
In-Reply-To: <20190821153656.33429-1-steven.price@arm.com>
This provides a mechanism for querying which paravirtualized features
are available in this hypervisor.
Also add the header file which defines the ABI for the paravirtualized
clock features we're about to add.
Signed-off-by: Steven Price <steven.price@arm.com>
---
arch/arm/include/asm/kvm_host.h | 6 ++++++
arch/arm64/include/asm/kvm_host.h | 2 ++
arch/arm64/include/asm/pvclock-abi.h | 17 +++++++++++++++++
arch/arm64/kvm/Makefile | 1 +
include/linux/arm-smccc.h | 14 ++++++++++++++
virt/kvm/arm/hypercalls.c | 6 ++++++
virt/kvm/arm/pvtime.c | 21 +++++++++++++++++++++
7 files changed, 67 insertions(+)
create mode 100644 arch/arm64/include/asm/pvclock-abi.h
create mode 100644 virt/kvm/arm/pvtime.c
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 8a37c8e89777..369b5d2d54bf 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -7,6 +7,7 @@
#ifndef __ARM_KVM_HOST_H__
#define __ARM_KVM_HOST_H__
+#include <linux/arm-smccc.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/kvm_types.h>
@@ -323,6 +324,11 @@ static inline int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
int kvm_perf_init(void);
int kvm_perf_teardown(void);
+static inline int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
+{
+ return SMCCC_RET_NOT_SUPPORTED;
+}
+
void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index f656169db8c3..583b3639062a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -478,6 +478,8 @@ void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
int kvm_perf_init(void);
int kvm_perf_teardown(void);
+int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);
+
void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome);
struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
diff --git a/arch/arm64/include/asm/pvclock-abi.h b/arch/arm64/include/asm/pvclock-abi.h
new file mode 100644
index 000000000000..c4f1c0a0789c
--- /dev/null
+++ b/arch/arm64/include/asm/pvclock-abi.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2019 Arm Ltd. */
+
+#ifndef __ASM_PVCLOCK_ABI_H
+#define __ASM_PVCLOCK_ABI_H
+
+/* The below structure is defined in ARM DEN0057A */
+
+struct pvclock_vcpu_stolen_time {
+ __le32 revision;
+ __le32 attributes;
+ __le64 stolen_time;
+ /* Structure must be 64 byte aligned, pad to that size */
+ u8 padding[48];
+} __packed;
+
+#endif
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 73dce4d47d47..5ffbdc39e780 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -14,6 +14,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/e
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/pvtime.o
kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 080012a6f025..e7f129f26ebd 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -45,6 +45,7 @@
#define ARM_SMCCC_OWNER_SIP 2
#define ARM_SMCCC_OWNER_OEM 3
#define ARM_SMCCC_OWNER_STANDARD 4
+#define ARM_SMCCC_OWNER_STANDARD_HYP 5
#define ARM_SMCCC_OWNER_TRUSTED_APP 48
#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
#define ARM_SMCCC_OWNER_TRUSTED_OS 50
@@ -302,5 +303,18 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
#define SMCCC_RET_NOT_SUPPORTED -1
#define SMCCC_RET_NOT_REQUIRED -2
+/* Paravirtualised time calls (defined by ARM DEN0057A) */
+#define ARM_SMCCC_HV_PV_FEATURES \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_STANDARD_HYP, \
+ 0x20)
+
+#define ARM_SMCCC_HV_PV_TIME_ST \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_STANDARD_HYP, \
+ 0x22)
+
#endif /*__ASSEMBLY__*/
#endif /*__LINUX_ARM_SMCCC_H*/
diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c
index f875241bd030..63ae629c466a 100644
--- a/virt/kvm/arm/hypercalls.c
+++ b/virt/kvm/arm/hypercalls.c
@@ -48,8 +48,14 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
break;
}
break;
+ case ARM_SMCCC_HV_PV_FEATURES:
+ val = SMCCC_RET_SUCCESS;
+ break;
}
break;
+ case ARM_SMCCC_HV_PV_FEATURES:
+ val = kvm_hypercall_pv_features(vcpu);
+ break;
default:
return kvm_psci_call(vcpu);
}
diff --git a/virt/kvm/arm/pvtime.c b/virt/kvm/arm/pvtime.c
new file mode 100644
index 000000000000..6201d71cb1f8
--- /dev/null
+++ b/virt/kvm/arm/pvtime.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2019 Arm Ltd.
+
+#include <linux/arm-smccc.h>
+
+#include <kvm/arm_hypercalls.h>
+
+int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
+{
+ u32 feature = smccc_get_arg1(vcpu);
+ u32 val = SMCCC_RET_NOT_SUPPORTED;
+
+ switch (feature) {
+ case ARM_SMCCC_HV_PV_FEATURES:
+ val = SMCCC_RET_SUCCESS;
+ break;
+ }
+
+ return val;
+}
+
--
2.20.1
^ permalink raw reply related
* [PATCH v3 02/10] KVM: arm/arm64: Factor out hypercall handling from PSCI code
From: Steven Price @ 2019-08-21 15:36 UTC (permalink / raw)
To: Marc Zyngier, Will Deacon, linux-arm-kernel, kvmarm
Cc: Steven Price, Catalin Marinas, Paolo Bonzini,
Radim Krčmář, Russell King, James Morse,
Julien Thierry, Suzuki K Pouloze, Mark Rutland, kvm, linux-doc,
linux-kernel, Christoffer Dall
In-Reply-To: <20190821153656.33429-1-steven.price@arm.com>
From: Christoffer Dall <christoffer.dall@arm.com>
We currently intertwine the KVM PSCI implementation with the general
dispatch of hypercall handling, which makes perfect sense because PSCI
is the only category of hypercalls we support.
However, as we are about to support additional hypercalls, factor out
this functionality into a separate hypercall handler file.
Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
[steven.price@arm.com: rebased]
Signed-off-by: Steven Price <steven.price@arm.com>
---
arch/arm/kvm/Makefile | 2 +-
arch/arm/kvm/handle_exit.c | 2 +-
arch/arm64/kvm/Makefile | 1 +
arch/arm64/kvm/handle_exit.c | 4 +-
include/kvm/arm_hypercalls.h | 43 ++++++++++++++++++
include/kvm/arm_psci.h | 2 +-
virt/kvm/arm/hypercalls.c | 59 +++++++++++++++++++++++++
virt/kvm/arm/psci.c | 84 +-----------------------------------
8 files changed, 110 insertions(+), 87 deletions(-)
create mode 100644 include/kvm/arm_hypercalls.h
create mode 100644 virt/kvm/arm/hypercalls.c
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index 531e59f5be9c..ef4d01088efc 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -23,7 +23,7 @@ obj-y += kvm-arm.o init.o interrupts.o
obj-y += handle_exit.o guest.o emulate.o reset.o
obj-y += coproc.o coproc_a15.o coproc_a7.o vgic-v3-coproc.o
obj-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
-obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
+obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o $(KVM)/arm/hypercalls.o
obj-y += $(KVM)/arm/aarch32.o
obj-y += $(KVM)/arm/vgic/vgic.o
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 2a6a1394d26e..e58a89d2f13f 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -9,7 +9,7 @@
#include <asm/kvm_emulate.h>
#include <asm/kvm_coproc.h>
#include <asm/kvm_mmu.h>
-#include <kvm/arm_psci.h>
+#include <kvm/arm_hypercalls.h>
#include <trace/events/kvm.h>
#include "trace.h"
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 3ac1a64d2fb9..73dce4d47d47 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o
kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 706cca23f0d2..aacfc55de44c 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -11,8 +11,6 @@
#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>
@@ -22,6 +20,8 @@
#include <asm/debug-monitors.h>
#include <asm/traps.h>
+#include <kvm/arm_hypercalls.h>
+
#define CREATE_TRACE_POINTS
#include "trace.h"
diff --git a/include/kvm/arm_hypercalls.h b/include/kvm/arm_hypercalls.h
new file mode 100644
index 000000000000..0e2509d27910
--- /dev/null
+++ b/include/kvm/arm_hypercalls.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2019 Arm Ltd. */
+
+#ifndef __KVM_ARM_HYPERCALLS_H
+#define __KVM_ARM_HYPERCALLS_H
+
+#include <asm/kvm_emulate.h>
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+
+static inline u32 smccc_get_function(struct kvm_vcpu *vcpu)
+{
+ return vcpu_get_reg(vcpu, 0);
+}
+
+static inline unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+ return vcpu_get_reg(vcpu, 1);
+}
+
+static inline unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+ return vcpu_get_reg(vcpu, 2);
+}
+
+static inline unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu)
+{
+ return vcpu_get_reg(vcpu, 3);
+}
+
+static inline 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);
+}
+
+#endif
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 632e78bdef4d..5b58bd2fe088 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -40,7 +40,7 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
}
-int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+int kvm_psci_call(struct kvm_vcpu *vcpu);
struct kvm_one_reg;
diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c
new file mode 100644
index 000000000000..f875241bd030
--- /dev/null
+++ b/virt/kvm/arm/hypercalls.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2019 Arm Ltd.
+
+#include <linux/arm-smccc.h>
+#include <linux/kvm_host.h>
+
+#include <asm/kvm_emulate.h>
+
+#include <kvm/arm_hypercalls.h>
+#include <kvm/arm_psci.h>
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
+{
+ u32 func_id = smccc_get_function(vcpu);
+ u32 val = SMCCC_RET_NOT_SUPPORTED;
+ u32 feature;
+
+ switch (func_id) {
+ case ARM_SMCCC_VERSION_FUNC_ID:
+ val = ARM_SMCCC_VERSION_1_1;
+ break;
+ case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
+ feature = smccc_get_arg1(vcpu);
+ switch (feature) {
+ case ARM_SMCCC_ARCH_WORKAROUND_1:
+ switch (kvm_arm_harden_branch_predictor()) {
+ case KVM_BP_HARDEN_UNKNOWN:
+ break;
+ case KVM_BP_HARDEN_WA_NEEDED:
+ val = SMCCC_RET_SUCCESS;
+ break;
+ case KVM_BP_HARDEN_NOT_REQUIRED:
+ val = SMCCC_RET_NOT_REQUIRED;
+ break;
+ }
+ break;
+ case ARM_SMCCC_ARCH_WORKAROUND_2:
+ switch (kvm_arm_have_ssbd()) {
+ case KVM_SSBD_FORCE_DISABLE:
+ case KVM_SSBD_UNKNOWN:
+ break;
+ case KVM_SSBD_KERNEL:
+ val = SMCCC_RET_SUCCESS;
+ break;
+ case KVM_SSBD_FORCE_ENABLE:
+ case KVM_SSBD_MITIGATED:
+ val = SMCCC_RET_NOT_REQUIRED;
+ break;
+ }
+ break;
+ }
+ break;
+ default:
+ return kvm_psci_call(vcpu);
+ }
+
+ smccc_set_retval(vcpu, val, 0, 0, 0);
+ return 1;
+}
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 87927f7e1ee7..17e2bdd4b76f 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -15,6 +15,7 @@
#include <asm/kvm_host.h>
#include <kvm/arm_psci.h>
+#include <kvm/arm_hypercalls.h>
/*
* This is an implementation of the Power State Coordination Interface
@@ -23,38 +24,6 @@
#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)
@@ -373,7 +342,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
* Errors:
* -EINVAL: Unrecognized PSCI function
*/
-static int kvm_psci_call(struct kvm_vcpu *vcpu)
+int kvm_psci_call(struct kvm_vcpu *vcpu)
{
switch (kvm_psci_version(vcpu, vcpu->kvm)) {
case KVM_ARM_PSCI_1_0:
@@ -387,55 +356,6 @@ 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 = SMCCC_RET_NOT_SUPPORTED;
- u32 feature;
-
- switch (func_id) {
- case ARM_SMCCC_VERSION_FUNC_ID:
- val = ARM_SMCCC_VERSION_1_1;
- break;
- case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
- feature = smccc_get_arg1(vcpu);
- switch(feature) {
- case ARM_SMCCC_ARCH_WORKAROUND_1:
- switch (kvm_arm_harden_branch_predictor()) {
- case KVM_BP_HARDEN_UNKNOWN:
- break;
- case KVM_BP_HARDEN_WA_NEEDED:
- val = SMCCC_RET_SUCCESS;
- break;
- case KVM_BP_HARDEN_NOT_REQUIRED:
- val = SMCCC_RET_NOT_REQUIRED;
- break;
- }
- break;
- case ARM_SMCCC_ARCH_WORKAROUND_2:
- switch (kvm_arm_have_ssbd()) {
- case KVM_SSBD_FORCE_DISABLE:
- case KVM_SSBD_UNKNOWN:
- break;
- case KVM_SSBD_KERNEL:
- val = SMCCC_RET_SUCCESS;
- break;
- case KVM_SSBD_FORCE_ENABLE:
- case KVM_SSBD_MITIGATED:
- val = SMCCC_RET_NOT_REQUIRED;
- break;
- }
- break;
- }
- 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 3; /* PSCI version and two workaround registers */
--
2.20.1
^ permalink raw reply related
* [PATCH v3 05/10] KVM: arm64: Support stolen time reporting via shared structure
From: Steven Price @ 2019-08-21 15:36 UTC (permalink / raw)
To: Marc Zyngier, Will Deacon, linux-arm-kernel, kvmarm
Cc: Steven Price, Catalin Marinas, Paolo Bonzini,
Radim Krčmář, Russell King, James Morse,
Julien Thierry, Suzuki K Pouloze, Mark Rutland, kvm, linux-doc,
linux-kernel
In-Reply-To: <20190821153656.33429-1-steven.price@arm.com>
Implement the service call for configuring a shared structure between a
VCPU and the hypervisor in which the hypervisor can write the time
stolen from the VCPU's execution time by other tasks on the host.
The hypervisor allocates memory which is placed at an IPA chosen by user
space. The hypervisor then updates the shared structure using
kvm_put_guest() to ensure single copy atomicity of the 64-bit value
reporting the stolen time in nanoseconds.
Whenever stolen time is enabled by the guest, the stolen time counter is
reset.
The stolen time itself is retrieved from the sched_info structure
maintained by the Linux scheduler code. We enable SCHEDSTATS when
selecting KVM Kconfig to ensure this value is meaningful.
Signed-off-by: Steven Price <steven.price@arm.com>
---
arch/arm/include/asm/kvm_host.h | 20 +++++++++
arch/arm64/include/asm/kvm_host.h | 25 +++++++++++-
arch/arm64/kvm/Kconfig | 1 +
include/linux/kvm_types.h | 2 +
virt/kvm/arm/arm.c | 10 +++++
virt/kvm/arm/hypercalls.c | 3 ++
virt/kvm/arm/pvtime.c | 67 +++++++++++++++++++++++++++++++
7 files changed, 127 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 369b5d2d54bf..47d2ced99421 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -39,6 +39,7 @@
KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)
#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)
+#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3)
DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
@@ -329,6 +330,25 @@ static inline int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
return SMCCC_RET_NOT_SUPPORTED;
}
+static inline int kvm_hypercall_stolen_time(struct kvm_vcpu *vcpu)
+{
+ return SMCCC_RET_NOT_SUPPORTED;
+}
+
+static inline int kvm_update_stolen_time(struct kvm_vcpu *vcpu, bool init)
+{
+ return -ENOTSUPP;
+}
+
+static inline void kvm_pvtime_init_vm(struct kvm_arch *kvm_arch)
+{
+}
+
+static inline bool kvm_is_pvtime_enabled(struct kvm_arch *kvm_arch)
+{
+ return false;
+}
+
void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 583b3639062a..b6fa7beffd8a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -44,6 +44,7 @@
KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)
#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)
+#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3)
DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
@@ -83,6 +84,11 @@ struct kvm_arch {
/* Mandated version of PSCI */
u32 psci_version;
+
+ struct kvm_arch_pvtime {
+ gpa_t st_base;
+ u64 st_size;
+ } pvtime;
};
#define KVM_NR_MEM_OBJS 40
@@ -338,8 +344,13 @@ struct kvm_vcpu_arch {
/* True when deferrable sysregs are loaded on the physical CPU,
* see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
bool sysregs_loaded_on_cpu;
-};
+ /* Guest PV state */
+ struct {
+ u64 steal;
+ u64 last_steal;
+ } steal;
+};
/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
#define vcpu_sve_pffr(vcpu) ((void *)((char *)((vcpu)->arch.sve_state) + \
sve_ffr_offset((vcpu)->arch.sve_max_vl)))
@@ -479,6 +490,18 @@ int kvm_perf_init(void);
int kvm_perf_teardown(void);
int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);
+int kvm_hypercall_stolen_time(struct kvm_vcpu *vcpu);
+int kvm_update_stolen_time(struct kvm_vcpu *vcpu, bool init);
+
+static inline void kvm_pvtime_init_vm(struct kvm_arch *kvm_arch)
+{
+ kvm_arch->pvtime.st_base = GPA_INVALID;
+}
+
+static inline bool kvm_is_pvtime_enabled(struct kvm_arch *kvm_arch)
+{
+ return (kvm_arch->pvtime.st_base != GPA_INVALID);
+}
void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome);
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index a67121d419a2..d8b88e40d223 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -39,6 +39,7 @@ config KVM
select IRQ_BYPASS_MANAGER
select HAVE_KVM_IRQ_BYPASS
select HAVE_KVM_VCPU_RUN_PID_CHANGE
+ select SCHEDSTATS
---help---
Support hosting virtualized guest machines.
We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index bde5374ae021..1c88e69db3d9 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -35,6 +35,8 @@ typedef unsigned long gva_t;
typedef u64 gpa_t;
typedef u64 gfn_t;
+#define GPA_INVALID (~(gpa_t)0)
+
typedef unsigned long hva_t;
typedef u64 hpa_t;
typedef u64 hfn_t;
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 35a069815baf..5e8343e2dd62 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -40,6 +40,10 @@
#include <asm/kvm_coproc.h>
#include <asm/sections.h>
+#include <kvm/arm_hypercalls.h>
+#include <kvm/arm_pmu.h>
+#include <kvm/arm_psci.h>
+
#ifdef REQUIRES_VIRT
__asm__(".arch_extension virt");
#endif
@@ -135,6 +139,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm->arch.max_vcpus = vgic_present ?
kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS;
+ kvm_pvtime_init_vm(&kvm->arch);
return ret;
out_free_stage2_pgd:
kvm_free_stage2_pgd(kvm);
@@ -379,6 +384,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_vcpu_load_sysregs(vcpu);
kvm_arch_vcpu_load_fp(vcpu);
kvm_vcpu_pmu_restore_guest(vcpu);
+ if (kvm_is_pvtime_enabled(&vcpu->kvm->arch))
+ kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
if (single_task_running())
vcpu_clear_wfe_traps(vcpu);
@@ -644,6 +651,9 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
* that a VCPU sees new virtual interrupts.
*/
kvm_check_request(KVM_REQ_IRQ_PENDING, vcpu);
+
+ if (kvm_check_request(KVM_REQ_RECORD_STEAL, vcpu))
+ kvm_update_stolen_time(vcpu, false);
}
}
diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c
index 63ae629c466a..ac678eabf15f 100644
--- a/virt/kvm/arm/hypercalls.c
+++ b/virt/kvm/arm/hypercalls.c
@@ -56,6 +56,9 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
case ARM_SMCCC_HV_PV_FEATURES:
val = kvm_hypercall_pv_features(vcpu);
break;
+ case ARM_SMCCC_HV_PV_TIME_ST:
+ val = kvm_hypercall_stolen_time(vcpu);
+ break;
default:
return kvm_psci_call(vcpu);
}
diff --git a/virt/kvm/arm/pvtime.c b/virt/kvm/arm/pvtime.c
index 6201d71cb1f8..28603689f6e0 100644
--- a/virt/kvm/arm/pvtime.c
+++ b/virt/kvm/arm/pvtime.c
@@ -3,8 +3,51 @@
#include <linux/arm-smccc.h>
+#include <asm/pvclock-abi.h>
+
#include <kvm/arm_hypercalls.h>
+int kvm_update_stolen_time(struct kvm_vcpu *vcpu, bool init)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_arch_pvtime *pvtime = &kvm->arch.pvtime;
+ u64 steal;
+ u64 steal_le;
+ u64 offset;
+ int idx;
+ const int stride = sizeof(struct pvclock_vcpu_stolen_time);
+
+ if (pvtime->st_base == GPA_INVALID)
+ return -ENOTSUPP;
+
+ /* Let's do the local bookkeeping */
+ steal = vcpu->arch.steal.steal;
+ steal += current->sched_info.run_delay - vcpu->arch.steal.last_steal;
+ vcpu->arch.steal.last_steal = current->sched_info.run_delay;
+ vcpu->arch.steal.steal = steal;
+
+ offset = stride * kvm_vcpu_get_idx(vcpu);
+
+ if (unlikely(offset + stride > pvtime->st_size))
+ return -EINVAL;
+
+ steal_le = cpu_to_le64(steal);
+ idx = srcu_read_lock(&kvm->srcu);
+ if (init) {
+ struct pvclock_vcpu_stolen_time init_values = {
+ .revision = 0,
+ .attributes = 0
+ };
+ kvm_write_guest(kvm, pvtime->st_base + offset, &init_values,
+ sizeof(init_values));
+ }
+ offset += offsetof(struct pvclock_vcpu_stolen_time, stolen_time);
+ kvm_put_guest(kvm, pvtime->st_base + offset, steal_le, u64);
+ srcu_read_unlock(&kvm->srcu, idx);
+
+ return 0;
+}
+
int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
{
u32 feature = smccc_get_arg1(vcpu);
@@ -12,6 +55,7 @@ int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
switch (feature) {
case ARM_SMCCC_HV_PV_FEATURES:
+ case ARM_SMCCC_HV_PV_TIME_ST:
val = SMCCC_RET_SUCCESS;
break;
}
@@ -19,3 +63,26 @@ int kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
return val;
}
+int kvm_hypercall_stolen_time(struct kvm_vcpu *vcpu)
+{
+ u64 ret;
+ int err;
+
+ /*
+ * Start counting stolen time from the time the guest requests
+ * the feature enabled.
+ */
+ vcpu->arch.steal.steal = 0;
+ vcpu->arch.steal.last_steal = current->sched_info.run_delay;
+
+ err = kvm_update_stolen_time(vcpu, true);
+
+ if (err)
+ ret = SMCCC_RET_NOT_SUPPORTED;
+ else
+ ret = vcpu->kvm->arch.pvtime.st_base +
+ (sizeof(struct pvclock_vcpu_stolen_time) *
+ kvm_vcpu_get_idx(vcpu));
+
+ return ret;
+}
--
2.20.1
^ permalink raw reply related
* [PATCH v3 01/10] KVM: arm64: Document PV-time interface
From: Steven Price @ 2019-08-21 15:36 UTC (permalink / raw)
To: Marc Zyngier, Will Deacon, linux-arm-kernel, kvmarm
Cc: Steven Price, Catalin Marinas, Paolo Bonzini,
Radim Krčmář, Russell King, James Morse,
Julien Thierry, Suzuki K Pouloze, Mark Rutland, kvm, linux-doc,
linux-kernel
In-Reply-To: <20190821153656.33429-1-steven.price@arm.com>
Introduce a paravirtualization interface for KVM/arm64 based on the
"Arm Paravirtualized Time for Arm-Base Systems" specification DEN 0057A.
This only adds the details about "Stolen Time" as the details of "Live
Physical Time" have not been fully agreed.
User space can specify a reserved area of memory for the guest and
inform KVM to populate the memory with information on time that the host
kernel has stolen from the guest.
A hypercall interface is provided for the guest to interrogate the
hypervisor's support for this interface and the location of the shared
memory structures.
Signed-off-by: Steven Price <steven.price@arm.com>
---
Documentation/virt/kvm/arm/pvtime.txt | 100 ++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
create mode 100644 Documentation/virt/kvm/arm/pvtime.txt
diff --git a/Documentation/virt/kvm/arm/pvtime.txt b/Documentation/virt/kvm/arm/pvtime.txt
new file mode 100644
index 000000000000..1ceb118694e7
--- /dev/null
+++ b/Documentation/virt/kvm/arm/pvtime.txt
@@ -0,0 +1,100 @@
+Paravirtualized time support for arm64
+======================================
+
+Arm specification DEN0057/A defined a standard for paravirtualised time
+support for AArch64 guests:
+
+https://developer.arm.com/docs/den0057/a
+
+KVM/arm64 implements the stolen time part of this specification by providing
+some hypervisor service calls to support a paravirtualized guest obtaining a
+view of the amount of time stolen from its execution.
+
+Two new SMCCC compatible hypercalls are defined:
+
+PV_FEATURES 0xC5000020
+PV_TIME_ST 0xC5000022
+
+These are only available in the SMC64/HVC64 calling convention as
+paravirtualized time is not available to 32 bit Arm guests. The existence of
+the PV_FEATURES hypercall should be probed using the SMCCC 1.1 ARCH_FEATURES
+mechanism before calling it.
+
+PV_FEATURES
+ Function ID: (uint32) : 0xC5000020
+ PV_func_id: (uint32) : Either PV_TIME_LPT or PV_TIME_ST
+ Return value: (int32) : NOT_SUPPORTED (-1) or SUCCESS (0) if the relevant
+ PV-time feature is supported by the hypervisor.
+
+PV_TIME_ST
+ Function ID: (uint32) : 0xC5000022
+ Return value: (int64) : IPA of the stolen time data structure for this
+ (V)CPU. On failure:
+ NOT_SUPPORTED (-1)
+
+The IPA returned by PV_TIME_ST should be mapped by the guest as normal memory
+with inner and outer write back caching attributes, in the inner shareable
+domain. A total of 16 bytes from the IPA returned are guaranteed to be
+meaningfully filled by the hypervisor (see structure below).
+
+PV_TIME_ST returns the structure for the calling VCPU.
+
+Stolen Time
+-----------
+
+The structure pointed to by the PV_TIME_ST hypercall is as follows:
+
+ Field | Byte Length | Byte Offset | Description
+ ----------- | ----------- | ----------- | --------------------------
+ Revision | 4 | 0 | Must be 0 for version 0.1
+ Attributes | 4 | 4 | Must be 0
+ Stolen time | 8 | 8 | Stolen time in unsigned
+ | | | nanoseconds indicating how
+ | | | much time this VCPU thread
+ | | | was involuntarily not
+ | | | running on a physical CPU.
+
+The structure will be updated by the hypervisor prior to scheduling a VCPU. It
+will be present within a reserved region of the normal memory given to the
+guest. The guest should not attempt to write into this memory. There is a
+structure per VCPU of the guest.
+
+User space interface
+====================
+
+User space can request that KVM provide the paravirtualized time interface to
+a guest by creating a KVM_DEV_TYPE_ARM_PV_TIME device, for example:
+
+ struct kvm_create_device pvtime_device = {
+ .type = KVM_DEV_TYPE_ARM_PV_TIME,
+ .attr = 0,
+ .flags = 0,
+ };
+
+ pvtime_fd = ioctl(vm_fd, KVM_CREATE_DEVICE, &pvtime_device);
+
+Creation of the device should be done after creating the vCPUs of the virtual
+machine.
+
+The IPA of the structures must be given to KVM. This is the base address
+of an array of stolen time structures (one for each VCPU). The base address
+must be page aligned. The size must be at least 64 * number of VCPUs and be a
+multiple of PAGE_SIZE.
+
+The memory for these structures should be added to the guest in the usual
+manner (e.g. using KVM_SET_USER_MEMORY_REGION).
+
+For example:
+
+ struct kvm_dev_arm_st_region region = {
+ .gpa = <IPA of guest base address>,
+ .size = <size in bytes>
+ };
+
+ struct kvm_device_attr st_base = {
+ .group = KVM_DEV_ARM_PV_TIME_PADDR,
+ .attr = KVM_DEV_ARM_PV_TIME_ST,
+ .addr = (u64)®ion
+ };
+
+ ioctl(pvtime_fd, KVM_SET_DEVICE_ATTR, &st_base);
--
2.20.1
^ permalink raw reply related
* Re: [PATCH v7 3/7] of/platform: Add functional dependency link from DT bindings
From: Frank Rowand @ 2019-08-21 16:39 UTC (permalink / raw)
To: Saravana Kannan
Cc: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Rafael J. Wysocki,
Jonathan Corbet,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, LKML,
David Collins, Android Kernel Team, Linux Doc Mailing List
In-Reply-To: <CAGETcx-F7VoQsDihvJ1FY=Pw8Rhu69zh6pBzkV4nSabwYRvbZw@mail.gmail.com>
On 8/20/19 3:09 PM, Saravana Kannan wrote:
> On Mon, Aug 19, 2019 at 9:26 PM Frank Rowand <frowand.list@gmail.com> wrote:
>>
< snip - the stuff I snipped deserves reply, but I want to focus on just
one topic for this reply >
>> You have a real bug. I have told you how to fix the real bug. And you
>> have ignored my suggestion. (To be honest, I do not know for sure that
>> my suggestion is feasible, but on the surface it appears to be.)
>
> I'd actually say that your proposal is what's trying to paper over a
> generic problem by saying it's specific to one or a few set of
> resources. And it looks feasible to you because you haven't dove deep
> into this issue.
Not saying it is specific to one or a few sets of resources. The
proposal suggests handling every single consumer supplier relationship
for which the bootloader has enabled a supplier resource via an
explicit message communicating the enabled resources. And directly
handling those exact resources.
Think about the definition of "paper over" vs "directly address".
>
>> Again,
>> my suggestion is to have the boot loader pass information to the kernel
>> (via a chosen property) telling the kernel which devices the bootloader
>> has enabled power to. The power subsystem would use that information
>> early in boot to do a "get" on the power supplier (I am not using precise
>> power subsystem terminology, but it should be obvious what I mean).
>> The consumer device driver would also have to be aware of the information
>> passed via the chosen property because the power subsystem has done the
>> "get" on the consumer devices behalf (exactly how the consumer gets
>> that information is an implementation detail). This approach is
>> more direct, less subtle, less fragile.
>
> I'll have to disagree on your claim. You are adding unnecessary
> bootloader dependency when the kernel is completely capable of
> handling this on its own. You are requiring explicit "gets" by
> suppliers and then hoping all the consumers do the corresponding
> "puts" to balance it out. Somehow the consumers need to know which
> suppliers have parsed which bootloader input. And it's barely
> scratching the surface of the problem.
OK, let me flesh out a possible implementation just a little bit.
This is focused on devicetree, as is your patch series. For ACPI
a parallel implementation would exist.
The bootloader chosen property could be a list of tuples, each tuple
containing: consumer phandle, supplier phandle. Each tuple could
contain more data if the implementation demands, but I'm trying to
keep it simple to illustrate the concept.
In early-ish boot a core function processes the chosen property. For
each consumer / supplier pair, the supplier compatible could be used
to determine the supplier type. (This might not be enough info to
determine the supplier type - maybe the consumer property that points
to the supplier will also have to be specified in the chosen property
tuple, or maybe a supplier type could be added to the tuple.) Given
the consumer, supplier, and resource type the appropriate "get"
would be done.
Late in boot, and possible repeated after modules are loaded, a core
function would scan the chosen property tuples, and for each
consumer / supplier pair, if both the consumer and the supplier
drivers are bound, it would be ASSUMED that it is ok to do the
appropriate type of "put", and the "put" would be done.
>
> You are assuming this has to do with just power when it can be clocks,
> interconnects, etc. Why solve this repeated for each framework when
> you can have a generic solution?
No such assumption.
>
> Also, while I understand what you mean by "get" it's not going to be
> as simple as a reference count to keep the resource on. In reality
> you'll need more complex handling. For example, having to keep a
> voltage rail at or above X mV because one consumer might fail if the
> voltage is < X mV. Or making sure a clock never goes about the
> bootloader set frequency before all the consumer drivers are probed to
> avoid overclocking one of the consumers. Trying to have this
> explicitly coordinated across multiple drivers would be a nightmare.
> It gets even more complicated with interconnects.
>
> With my patch series, the consumers don't need to do anything. They
> just probe as usual. The suppliers don't need to track or coordinate
> with any consumers. For example, regulator suppliers just need to keep
> the voltage rail at (or above) the level that the boot loader left it
> on at and then apply the aggregated requests from their APIs once they
> get the sync_state() callback. And it actually works -- tested for
> regulators and clocks (and maybe even interconnects -- I forgot) in a
> device I have.
>
And same for the possible implementation I sketched above. The equivalent
of the sync_state() callback would be done by the end of boot (potentially
repeated after each module loads) core function making a similar call.
Hand waving here about what suppliers to call.
Of course this is not the only way to implement my concept, just an
example to suggest that it might be feasible and it might work.
< snip >
-Frank
^ permalink raw reply
* [PATCH v9 1/3] mm: untag user pointers in mmap/munmap/mremap/brk
From: Catalin Marinas @ 2019-08-21 16:47 UTC (permalink / raw)
To: linux-arm-kernel, linux-mm
Cc: Andrew Morton, Vincenzo Frascino, Will Deacon, Andrey Konovalov,
Szabolcs Nagy, Kevin Brodsky, Dave P Martin, Dave Hansen,
linux-doc, linux-arch
In-Reply-To: <20190821164730.47450-1-catalin.marinas@arm.com>
There isn't a good reason to differentiate between the user address
space layout modification syscalls and the other memory
permission/attributes ones (e.g. mprotect, madvise) w.r.t. the tagged
address ABI. Untag the user addresses on entry to these functions.
Acked-by: Will Deacon <will@kernel.org>
Acked-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
mm/mmap.c | 5 +++++
mm/mremap.c | 6 +-----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/mm/mmap.c b/mm/mmap.c
index 7e8c3e8ae75f..b766b633b7ae 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -201,6 +201,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
bool downgraded = false;
LIST_HEAD(uf);
+ brk = untagged_addr(brk);
+
if (down_write_killable(&mm->mmap_sem))
return -EINTR;
@@ -1573,6 +1575,8 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
struct file *file = NULL;
unsigned long retval;
+ addr = untagged_addr(addr);
+
if (!(flags & MAP_ANONYMOUS)) {
audit_mmap_fd(fd, flags);
file = fget(fd);
@@ -2874,6 +2878,7 @@ EXPORT_SYMBOL(vm_munmap);
SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
{
+ addr = untagged_addr(addr);
profile_munmap(addr);
return __vm_munmap(addr, len, true);
}
diff --git a/mm/mremap.c b/mm/mremap.c
index 64c9a3b8be0a..1fc8a29fbe3f 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -606,12 +606,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
LIST_HEAD(uf_unmap_early);
LIST_HEAD(uf_unmap);
- /*
- * Architectures may interpret the tag passed to mmap as a background
- * colour for the corresponding vma. For mremap we don't allow tagged
- * new_addr to preserve similar behaviour to mmap.
- */
addr = untagged_addr(addr);
+ new_addr = untagged_addr(new_addr);
if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
return ret;
^ permalink raw reply related
* [PATCH v9 2/3] arm64: Define Documentation/arm64/tagged-address-abi.rst
From: Catalin Marinas @ 2019-08-21 16:47 UTC (permalink / raw)
To: linux-arm-kernel, linux-mm
Cc: Andrew Morton, Vincenzo Frascino, Will Deacon, Andrey Konovalov,
Szabolcs Nagy, Kevin Brodsky, Dave P Martin, Dave Hansen,
linux-doc, linux-arch, Will Deacon
In-Reply-To: <20190821164730.47450-1-catalin.marinas@arm.com>
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace
(EL0) to perform memory accesses through 64-bit pointers with a non-zero
top byte. Introduce the document describing the relaxation of the
syscall ABI that allows userspace to pass certain tagged pointers to
kernel syscalls.
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
Documentation/arm64/tagged-address-abi.rst | 156 +++++++++++++++++++++
1 file changed, 156 insertions(+)
create mode 100644 Documentation/arm64/tagged-address-abi.rst
diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst
new file mode 100644
index 000000000000..d4a85d535bf9
--- /dev/null
+++ b/Documentation/arm64/tagged-address-abi.rst
@@ -0,0 +1,156 @@
+==========================
+AArch64 TAGGED ADDRESS ABI
+==========================
+
+Authors: Vincenzo Frascino <vincenzo.frascino@arm.com>
+ Catalin Marinas <catalin.marinas@arm.com>
+
+Date: 21 August 2019
+
+This document describes the usage and semantics of the Tagged Address
+ABI on AArch64 Linux.
+
+1. Introduction
+---------------
+
+On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing
+userspace (EL0) to perform memory accesses through 64-bit pointers with
+a non-zero top byte. This document describes the relaxation of the
+syscall ABI that allows userspace to pass certain tagged pointers to
+kernel syscalls.
+
+2. AArch64 Tagged Address ABI
+-----------------------------
+
+From the kernel syscall interface perspective and for the purposes of
+this document, a "valid tagged pointer" is a pointer with a potentially
+non-zero top-byte that references an address in the user process address
+space obtained in one of the following ways:
+
+- ``mmap()`` syscall where either:
+
+ - flags have the ``MAP_ANONYMOUS`` bit set or
+ - the file descriptor refers to a regular file (including those
+ returned by ``memfd_create()``) or ``/dev/zero``
+
+- ``brk()`` syscall (i.e. the heap area between the initial location of
+ the program break at process creation and its current location).
+
+- any memory mapped by the kernel in the address space of the process
+ during creation and with the same restrictions as for ``mmap()`` above
+ (e.g. data, bss, stack).
+
+The AArch64 Tagged Address ABI has two stages of relaxation depending
+how the user addresses are used by the kernel:
+
+1. User addresses not accessed by the kernel but used for address space
+ management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
+ of valid tagged pointers in this context is always allowed.
+
+2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
+ relaxation is disabled by default and the application thread needs to
+ explicitly enable it via ``prctl()`` as follows:
+
+ - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged
+ Address ABI for the calling thread.
+
+ The ``(unsigned int) arg2`` argument is a bit mask describing the
+ control mode used:
+
+ - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI.
+ Default status is disabled.
+
+ Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0.
+
+ - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged
+ Address ABI for the calling thread.
+
+ Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0.
+
+ The ABI properties described above are thread-scoped, inherited on
+ clone() and fork() and cleared on exec().
+
+ Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)``
+ returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally
+ disabled by ``sysctl abi.tagged_addr_disabled=1``. The default
+ ``sysctl abi.tagged_addr_disabled`` configuration is 0.
+
+When the AArch64 Tagged Address ABI is enabled for a thread, the
+following behaviours are guaranteed:
+
+- All syscalls except the cases mentioned in section 3 can accept any
+ valid tagged pointer.
+
+- The syscall behaviour is undefined for invalid tagged pointers: it may
+ result in an error code being returned, a (fatal) signal being raised,
+ or other modes of failure.
+
+- The syscall behaviour for a valid tagged pointer is the same as for
+ the corresponding untagged pointer.
+
+
+A definition of the meaning of tagged pointers on AArch64 can be found
+in Documentation/arm64/tagged-pointers.rst.
+
+3. AArch64 Tagged Address ABI Exceptions
+-----------------------------------------
+
+The following system call parameters must be untagged regardless of the
+ABI relaxation:
+
+- ``prctl()`` other than pointers to user data either passed directly or
+ indirectly as arguments to be accessed by the kernel.
+
+- ``ioctl()`` other than pointers to user data either passed directly or
+ indirectly as arguments to be accessed by the kernel.
+
+- ``shmat()`` and ``shmdt()``.
+
+Any attempt to use non-zero tagged pointers may result in an error code
+being returned, a (fatal) signal being raised, or other modes of
+failure.
+
+4. Example of correct usage
+---------------------------
+.. code-block:: c
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <sys/prctl.h>
+
+ #define PR_SET_TAGGED_ADDR_CTRL 55
+ #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+
+ #define TAG_SHIFT 56
+
+ int main(void)
+ {
+ int tbi_enabled = 0;
+ unsigned long tag = 0;
+ char *ptr;
+
+ /* check/enable the tagged address ABI */
+ if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0))
+ tbi_enabled = 1;
+
+ /* memory allocation */
+ ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (ptr == MAP_FAILED)
+ return 1;
+
+ /* set a non-zero tag if the ABI is available */
+ if (tbi_enabled)
+ tag = rand() & 0xff;
+ ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT));
+
+ /* memory access to a tagged address */
+ strcpy(ptr, "tagged pointer\n");
+
+ /* syscall with a tagged pointer */
+ write(1, ptr, strlen(ptr));
+
+ return 0;
+ }
^ permalink raw reply related
* [PATCH v9 3/3] arm64: Relax Documentation/arm64/tagged-pointers.rst
From: Catalin Marinas @ 2019-08-21 16:47 UTC (permalink / raw)
To: linux-arm-kernel, linux-mm
Cc: Andrew Morton, Vincenzo Frascino, Will Deacon, Andrey Konovalov,
Szabolcs Nagy, Kevin Brodsky, Dave P Martin, Dave Hansen,
linux-doc, linux-arch, Will Deacon
In-Reply-To: <20190821164730.47450-1-catalin.marinas@arm.com>
From: Vincenzo Frascino <vincenzo.frascino@arm.com>
On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace
(EL0) to perform memory accesses through 64-bit pointers with a non-zero
top byte. However, such pointers were not allowed at the user-kernel
syscall ABI boundary.
With the Tagged Address ABI patchset, it is now possible to pass tagged
pointers to the syscalls. Relax the requirements described in
tagged-pointers.rst to be compliant with the behaviours guaranteed by
the AArch64 Tagged Address ABI.
Cc: Will Deacon <will.deacon@arm.com>
Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Acked-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
Documentation/arm64/tagged-pointers.rst | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index 2acdec3ebbeb..04f2ba9b779e 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -20,7 +20,9 @@ Passing tagged addresses to the kernel
--------------------------------------
All interpretation of userspace memory addresses by the kernel assumes
-an address tag of 0x00.
+an address tag of 0x00, unless the application enables the AArch64
+Tagged Address ABI explicitly
+(Documentation/arm64/tagged-address-abi.rst).
This includes, but is not limited to, addresses found in:
@@ -33,13 +35,15 @@ This includes, but is not limited to, addresses found in:
- the frame pointer (x29) and frame records, e.g. when interpreting
them to generate a backtrace or call graph.
-Using non-zero address tags in any of these locations may result in an
-error code being returned, a (fatal) signal being raised, or other modes
-of failure.
+Using non-zero address tags in any of these locations when the
+userspace application did not enable the AArch64 Tagged Address ABI may
+result in an error code being returned, a (fatal) signal being raised,
+or other modes of failure.
-For these reasons, passing non-zero address tags to the kernel via
-system calls is forbidden, and using a non-zero address tag for sp is
-strongly discouraged.
+For these reasons, when the AArch64 Tagged Address ABI is disabled,
+passing non-zero address tags to the kernel via system calls is
+forbidden, and using a non-zero address tag for sp is strongly
+discouraged.
Programs maintaining a frame pointer and frame records that use non-zero
address tags may suffer impaired or inaccurate debug and profiling
@@ -59,6 +63,11 @@ be preserved.
The architecture prevents the use of a tagged PC, so the upper byte will
be set to a sign-extension of bit 55 on exception return.
+This behaviour is maintained when the AArch64 Tagged Address ABI is
+enabled. In addition, with the exceptions above, the kernel will
+preserve any non-zero tags passed by the user via syscalls and stored in
+kernel data structures (e.g. ``set_robust_list()``, ``sigaltstack()``).
+
Other considerations
--------------------
^ permalink raw reply related
* [PATCH v9 0/3] arm64 tagged address ABI
From: Catalin Marinas @ 2019-08-21 16:47 UTC (permalink / raw)
To: linux-arm-kernel, linux-mm
Cc: Andrew Morton, Vincenzo Frascino, Will Deacon, Andrey Konovalov,
Szabolcs Nagy, Kevin Brodsky, Dave P Martin, Dave Hansen,
linux-doc, linux-arch
Hi,
This series is an update to the arm64 tagged address ABI documentation
patches v8, posted here:
http://lkml.kernel.org/r/20190815154403.16473-1-catalin.marinas@arm.com
From v8, I dropped patches 2 and 3 as they've been queued by Will via
the arm64 tree. Reposting patch 1 (unmodified) as it should be merged
via the mm tree.
Changes in v9:
- Replaced the emphasized/bold font with a typewriter one for
function/constant names
- Simplified the mmap/brk bullet points when describing the tagged
pointer origin
- Reworded expected syscall behaviour with valid tagged pointers
- Reworded the prctl/ioctl restrictions to clarify the allowed tagged
pointers w.r.t. user data access by the kernel
Catalin Marinas (1):
mm: untag user pointers in mmap/munmap/mremap/brk
Vincenzo Frascino (2):
arm64: Define Documentation/arm64/tagged-address-abi.rst
arm64: Relax Documentation/arm64/tagged-pointers.rst
Documentation/arm64/tagged-address-abi.rst | 156 +++++++++++++++++++++
Documentation/arm64/tagged-pointers.rst | 23 ++-
mm/mmap.c | 5 +
mm/mremap.c | 6 +-
4 files changed, 178 insertions(+), 12 deletions(-)
create mode 100644 Documentation/arm64/tagged-address-abi.rst
^ permalink raw reply
* Re: [PATCH v3 2/2] drivers/perf: Add CCPI2 PMU support in ThunderX2 UNCORE driver.
From: Will Deacon @ 2019-08-21 16:53 UTC (permalink / raw)
To: Mark Rutland
Cc: Ganapatrao Kulkarni, Ganapatrao Kulkarni,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, corbet@lwn.net,
Jayachandran Chandrasekharan Nair, Robert Richter, Jan Glauber
In-Reply-To: <20190813110345.GD866@lakrids.cambridge.arm.com>
On Tue, Aug 13, 2019 at 12:03:45PM +0100, Mark Rutland wrote:
> On Tue, Aug 13, 2019 at 04:25:15PM +0530, Ganapatrao Kulkarni wrote:
> > On Mon, Aug 12, 2019 at 5:31 PM Mark Rutland <mark.rutland@arm.com> wrote:
> > >
> > > On Tue, Jul 23, 2019 at 09:16:28AM +0000, Ganapatrao Kulkarni wrote:
> > > > CCPI2 is a low-latency high-bandwidth serial interface for connecting
> > > > ThunderX2 processors. This patch adds support to capture CCPI2 perf events.
> > >
> > > It would be worth pointing out in the commit message how the CCPI2
> > > counters differ from the others. I realise you have that in the body of
> > > patch 1, but it's critical information when reviewing this patch...
> >
> > Ok, I will add in next version.
> > >
> > > >
> > > > Signed-off-by: Ganapatrao Kulkarni <gkulkarni@marvell.com>
> > > > ---
> > > > drivers/perf/thunderx2_pmu.c | 248 ++++++++++++++++++++++++++++++-----
> > > > 1 file changed, 214 insertions(+), 34 deletions(-)
> > > >
> > > > diff --git a/drivers/perf/thunderx2_pmu.c b/drivers/perf/thunderx2_pmu.c
> > > > index 43d76c85da56..a4e1273eafa3 100644
> > > > --- a/drivers/perf/thunderx2_pmu.c
> > > > +++ b/drivers/perf/thunderx2_pmu.c
> > > > @@ -17,22 +17,31 @@
> > > > */
> > > >
> > > > #define TX2_PMU_MAX_COUNTERS 4
> > >
> > > Shouldn't this be 8 now?
> >
> > It is kept unchanged to 4(as suggested by Will), which is same for
> > both L3 and DMC.
> > For CCPI2 this macro is not used.
>
> Hmmm....
>
> I disagree with that suggestion given that this also affects the
> active_counters bitmap size (and thus it is not correctly sized as of
> this patch), and it doesn't really save us much.
>
> I think it would be better to bump this to 8 and always update the
> events array, even though it will be unused for CCPI2. That's less
> surprising, needs fewer special-cases, and we can use the hrtimer
> function pointer alone to determine if we need to do any hrtimer work.
tbf, my complaint was actually about some macros applying to the whole
PMU whilst others refer only to DMC/L3C and this not being apparent from
the naming:
https://lkml.org/lkml/2019/6/27/250
so I'm fine having TX2_PMU_DMC_L3C_MAX_COUNTERS and
TX2_PMU_CCPI2_MAX_COUNTERS, but that sort of naming needs to be consistent
unless the macro/definition really applies to both. That fed the suggestion
that GET_EVENTID could be generic and switch on the event type internally
instead of at the caller.
Will
^ permalink raw reply
* Re: [PATCH v9 2/3] arm64: Define Documentation/arm64/tagged-address-abi.rst
From: Andrey Konovalov @ 2019-08-21 16:57 UTC (permalink / raw)
To: Catalin Marinas
Cc: Linux ARM, Linux Memory Management List, Andrew Morton,
Vincenzo Frascino, Will Deacon, Szabolcs Nagy, Kevin Brodsky,
Dave P Martin, Dave Hansen, open list:DOCUMENTATION, linux-arch,
Will Deacon
In-Reply-To: <20190821164730.47450-3-catalin.marinas@arm.com>
On Wed, Aug 21, 2019 at 6:47 PM Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> From: Vincenzo Frascino <vincenzo.frascino@arm.com>
>
> On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace
> (EL0) to perform memory accesses through 64-bit pointers with a non-zero
> top byte. Introduce the document describing the relaxation of the
> syscall ABI that allows userspace to pass certain tagged pointers to
> kernel syscalls.
>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Andrey Konovalov <andreyknvl@google.com>
> Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
> Cc: Kevin Brodsky <kevin.brodsky@arm.com>
> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
> Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Andrey Konovalov <andreyknvl@google.com>
> ---
> Documentation/arm64/tagged-address-abi.rst | 156 +++++++++++++++++++++
> 1 file changed, 156 insertions(+)
> create mode 100644 Documentation/arm64/tagged-address-abi.rst
>
> diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst
> new file mode 100644
> index 000000000000..d4a85d535bf9
> --- /dev/null
> +++ b/Documentation/arm64/tagged-address-abi.rst
> @@ -0,0 +1,156 @@
> +==========================
> +AArch64 TAGGED ADDRESS ABI
> +==========================
> +
> +Authors: Vincenzo Frascino <vincenzo.frascino@arm.com>
> + Catalin Marinas <catalin.marinas@arm.com>
> +
> +Date: 21 August 2019
> +
> +This document describes the usage and semantics of the Tagged Address
> +ABI on AArch64 Linux.
> +
> +1. Introduction
> +---------------
> +
> +On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing
> +userspace (EL0) to perform memory accesses through 64-bit pointers with
> +a non-zero top byte. This document describes the relaxation of the
> +syscall ABI that allows userspace to pass certain tagged pointers to
> +kernel syscalls.
> +
> +2. AArch64 Tagged Address ABI
> +-----------------------------
> +
> +From the kernel syscall interface perspective and for the purposes of
> +this document, a "valid tagged pointer" is a pointer with a potentially
> +non-zero top-byte that references an address in the user process address
> +space obtained in one of the following ways:
> +
> +- ``mmap()`` syscall where either:
> +
> + - flags have the ``MAP_ANONYMOUS`` bit set or
> + - the file descriptor refers to a regular file (including those
> + returned by ``memfd_create()``) or ``/dev/zero``
> +
> +- ``brk()`` syscall (i.e. the heap area between the initial location of
> + the program break at process creation and its current location).
> +
> +- any memory mapped by the kernel in the address space of the process
> + during creation and with the same restrictions as for ``mmap()`` above
> + (e.g. data, bss, stack).
> +
> +The AArch64 Tagged Address ABI has two stages of relaxation depending
> +how the user addresses are used by the kernel:
> +
> +1. User addresses not accessed by the kernel but used for address space
> + management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
> + of valid tagged pointers in this context is always allowed.
> +
> +2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
> + relaxation is disabled by default and the application thread needs to
> + explicitly enable it via ``prctl()`` as follows:
> +
> + - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged
> + Address ABI for the calling thread.
> +
> + The ``(unsigned int) arg2`` argument is a bit mask describing the
> + control mode used:
> +
> + - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI.
> + Default status is disabled.
> +
> + Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0.
> +
> + - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged
> + Address ABI for the calling thread.
> +
> + Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0.
> +
> + The ABI properties described above are thread-scoped, inherited on
> + clone() and fork() and cleared on exec().
> +
> + Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)``
> + returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally
> + disabled by ``sysctl abi.tagged_addr_disabled=1``. The default
> + ``sysctl abi.tagged_addr_disabled`` configuration is 0.
> +
> +When the AArch64 Tagged Address ABI is enabled for a thread, the
> +following behaviours are guaranteed:
> +
> +- All syscalls except the cases mentioned in section 3 can accept any
> + valid tagged pointer.
> +
> +- The syscall behaviour is undefined for invalid tagged pointers: it may
> + result in an error code being returned, a (fatal) signal being raised,
> + or other modes of failure.
> +
> +- The syscall behaviour for a valid tagged pointer is the same as for
> + the corresponding untagged pointer.
> +
> +
> +A definition of the meaning of tagged pointers on AArch64 can be found
> +in Documentation/arm64/tagged-pointers.rst.
> +
> +3. AArch64 Tagged Address ABI Exceptions
> +-----------------------------------------
> +
> +The following system call parameters must be untagged regardless of the
> +ABI relaxation:
> +
> +- ``prctl()`` other than pointers to user data either passed directly or
> + indirectly as arguments to be accessed by the kernel.
> +
> +- ``ioctl()`` other than pointers to user data either passed directly or
> + indirectly as arguments to be accessed by the kernel.
> +
> +- ``shmat()`` and ``shmdt()``.
> +
> +Any attempt to use non-zero tagged pointers may result in an error code
> +being returned, a (fatal) signal being raised, or other modes of
> +failure.
> +
> +4. Example of correct usage
> +---------------------------
> +.. code-block:: c
> +
> + #include <stdlib.h>
> + #include <string.h>
> + #include <unistd.h>
> + #include <sys/mman.h>
> + #include <sys/prctl.h>
> +
> + #define PR_SET_TAGGED_ADDR_CTRL 55
> + #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
> +
> + #define TAG_SHIFT 56
> +
> + int main(void)
> + {
> + int tbi_enabled = 0;
> + unsigned long tag = 0;
> + char *ptr;
> +
> + /* check/enable the tagged address ABI */
> + if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0))
> + tbi_enabled = 1;
> +
> + /* memory allocation */
> + ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> + if (ptr == MAP_FAILED)
> + return 1;
> +
> + /* set a non-zero tag if the ABI is available */
> + if (tbi_enabled)
> + tag = rand() & 0xff;
> + ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT));
> +
> + /* memory access to a tagged address */
> + strcpy(ptr, "tagged pointer\n");
> +
> + /* syscall with a tagged pointer */
> + write(1, ptr, strlen(ptr));
> +
> + return 0;
> + }
^ permalink raw reply
* Re: [PATCH v9 3/3] arm64: Relax Documentation/arm64/tagged-pointers.rst
From: Will Deacon @ 2019-08-21 17:33 UTC (permalink / raw)
To: Catalin Marinas
Cc: linux-arm-kernel, linux-mm, Andrew Morton, Vincenzo Frascino,
Andrey Konovalov, Szabolcs Nagy, Kevin Brodsky, Dave P Martin,
Dave Hansen, linux-doc, linux-arch, Will Deacon
In-Reply-To: <20190821164730.47450-4-catalin.marinas@arm.com>
On Wed, Aug 21, 2019 at 05:47:30PM +0100, Catalin Marinas wrote:
> From: Vincenzo Frascino <vincenzo.frascino@arm.com>
>
> On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace
> (EL0) to perform memory accesses through 64-bit pointers with a non-zero
> top byte. However, such pointers were not allowed at the user-kernel
> syscall ABI boundary.
>
> With the Tagged Address ABI patchset, it is now possible to pass tagged
> pointers to the syscalls. Relax the requirements described in
> tagged-pointers.rst to be compliant with the behaviours guaranteed by
> the AArch64 Tagged Address ABI.
>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
> Cc: Kevin Brodsky <kevin.brodsky@arm.com>
> Acked-by: Andrey Konovalov <andreyknvl@google.com>
> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
> Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> ---
> Documentation/arm64/tagged-pointers.rst | 23 ++++++++++++++++-------
> 1 file changed, 16 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> index 2acdec3ebbeb..04f2ba9b779e 100644
> --- a/Documentation/arm64/tagged-pointers.rst
> +++ b/Documentation/arm64/tagged-pointers.rst
> @@ -20,7 +20,9 @@ Passing tagged addresses to the kernel
> --------------------------------------
>
> All interpretation of userspace memory addresses by the kernel assumes
> -an address tag of 0x00.
> +an address tag of 0x00, unless the application enables the AArch64
> +Tagged Address ABI explicitly
> +(Documentation/arm64/tagged-address-abi.rst).
>
> This includes, but is not limited to, addresses found in:
>
> @@ -33,13 +35,15 @@ This includes, but is not limited to, addresses found in:
> - the frame pointer (x29) and frame records, e.g. when interpreting
> them to generate a backtrace or call graph.
>
> -Using non-zero address tags in any of these locations may result in an
> -error code being returned, a (fatal) signal being raised, or other modes
> -of failure.
> +Using non-zero address tags in any of these locations when the
> +userspace application did not enable the AArch64 Tagged Address ABI may
> +result in an error code being returned, a (fatal) signal being raised,
> +or other modes of failure.
>
> -For these reasons, passing non-zero address tags to the kernel via
> -system calls is forbidden, and using a non-zero address tag for sp is
> -strongly discouraged.
> +For these reasons, when the AArch64 Tagged Address ABI is disabled,
> +passing non-zero address tags to the kernel via system calls is
> +forbidden, and using a non-zero address tag for sp is strongly
> +discouraged.
>
> Programs maintaining a frame pointer and frame records that use non-zero
> address tags may suffer impaired or inaccurate debug and profiling
> @@ -59,6 +63,11 @@ be preserved.
> The architecture prevents the use of a tagged PC, so the upper byte will
> be set to a sign-extension of bit 55 on exception return.
>
> +This behaviour is maintained when the AArch64 Tagged Address ABI is
> +enabled. In addition, with the exceptions above, the kernel will
> +preserve any non-zero tags passed by the user via syscalls and stored in
> +kernel data structures (e.g. ``set_robust_list()``, ``sigaltstack()``).
Hmm. I can see the need to provide this guarantee for things like
set_robust_list(), but the problem is that the statement above is too broad
and isn't strictly true: for example, mmap() doesn't propagate the tag of
its address parameter into the VMA.
So I think we need to nail this down a bit more, but I'm having a really
hard time coming up with some wording :(
Will
^ permalink raw reply
* Re: [PATCH v9 2/3] arm64: Define Documentation/arm64/tagged-address-abi.rst
From: Will Deacon @ 2019-08-21 17:35 UTC (permalink / raw)
To: Catalin Marinas
Cc: linux-arm-kernel, linux-mm, Andrew Morton, Vincenzo Frascino,
Andrey Konovalov, Szabolcs Nagy, Kevin Brodsky, Dave P Martin,
Dave Hansen, linux-doc, linux-arch, Will Deacon
In-Reply-To: <20190821164730.47450-3-catalin.marinas@arm.com>
On Wed, Aug 21, 2019 at 05:47:29PM +0100, Catalin Marinas wrote:
> From: Vincenzo Frascino <vincenzo.frascino@arm.com>
>
> On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace
> (EL0) to perform memory accesses through 64-bit pointers with a non-zero
> top byte. Introduce the document describing the relaxation of the
> syscall ABI that allows userspace to pass certain tagged pointers to
> kernel syscalls.
>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Andrey Konovalov <andreyknvl@google.com>
> Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
> Cc: Kevin Brodsky <kevin.brodsky@arm.com>
> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
> Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> ---
> Documentation/arm64/tagged-address-abi.rst | 156 +++++++++++++++++++++
> 1 file changed, 156 insertions(+)
> create mode 100644 Documentation/arm64/tagged-address-abi.rst
Thanks, I'll pick this on up.
Will
^ permalink raw reply
* Re: [PATCH v9 3/3] arm64: Relax Documentation/arm64/tagged-pointers.rst
From: Dave Martin @ 2019-08-21 18:46 UTC (permalink / raw)
To: Will Deacon
Cc: Catalin Marinas, linux-arch, Dave Hansen, Szabolcs Nagy,
Andrey Konovalov, Kevin Brodsky, linux-doc, Will Deacon, linux-mm,
Andrew Morton, Vincenzo Frascino, linux-arm-kernel
In-Reply-To: <20190821173352.yqfgaozi7nfhcofg@willie-the-truck>
On Wed, Aug 21, 2019 at 06:33:53PM +0100, Will Deacon wrote:
> On Wed, Aug 21, 2019 at 05:47:30PM +0100, Catalin Marinas wrote:
> > From: Vincenzo Frascino <vincenzo.frascino@arm.com>
> >
> > On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace
> > (EL0) to perform memory accesses through 64-bit pointers with a non-zero
> > top byte. However, such pointers were not allowed at the user-kernel
> > syscall ABI boundary.
> >
> > With the Tagged Address ABI patchset, it is now possible to pass tagged
> > pointers to the syscalls. Relax the requirements described in
> > tagged-pointers.rst to be compliant with the behaviours guaranteed by
> > the AArch64 Tagged Address ABI.
> >
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
> > Cc: Kevin Brodsky <kevin.brodsky@arm.com>
> > Acked-by: Andrey Konovalov <andreyknvl@google.com>
> > Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
> > Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
> > Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> > ---
> > Documentation/arm64/tagged-pointers.rst | 23 ++++++++++++++++-------
> > 1 file changed, 16 insertions(+), 7 deletions(-)
> >
> > diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> > index 2acdec3ebbeb..04f2ba9b779e 100644
> > --- a/Documentation/arm64/tagged-pointers.rst
> > +++ b/Documentation/arm64/tagged-pointers.rst
> > @@ -20,7 +20,9 @@ Passing tagged addresses to the kernel
> > --------------------------------------
> >
> > All interpretation of userspace memory addresses by the kernel assumes
> > -an address tag of 0x00.
> > +an address tag of 0x00, unless the application enables the AArch64
> > +Tagged Address ABI explicitly
> > +(Documentation/arm64/tagged-address-abi.rst).
> >
> > This includes, but is not limited to, addresses found in:
> >
> > @@ -33,13 +35,15 @@ This includes, but is not limited to, addresses found in:
> > - the frame pointer (x29) and frame records, e.g. when interpreting
> > them to generate a backtrace or call graph.
> >
> > -Using non-zero address tags in any of these locations may result in an
> > -error code being returned, a (fatal) signal being raised, or other modes
> > -of failure.
> > +Using non-zero address tags in any of these locations when the
> > +userspace application did not enable the AArch64 Tagged Address ABI may
> > +result in an error code being returned, a (fatal) signal being raised,
> > +or other modes of failure.
> >
> > -For these reasons, passing non-zero address tags to the kernel via
> > -system calls is forbidden, and using a non-zero address tag for sp is
> > -strongly discouraged.
> > +For these reasons, when the AArch64 Tagged Address ABI is disabled,
> > +passing non-zero address tags to the kernel via system calls is
> > +forbidden, and using a non-zero address tag for sp is strongly
> > +discouraged.
> >
> > Programs maintaining a frame pointer and frame records that use non-zero
> > address tags may suffer impaired or inaccurate debug and profiling
> > @@ -59,6 +63,11 @@ be preserved.
> > The architecture prevents the use of a tagged PC, so the upper byte will
> > be set to a sign-extension of bit 55 on exception return.
> >
> > +This behaviour is maintained when the AArch64 Tagged Address ABI is
> > +enabled. In addition, with the exceptions above, the kernel will
> > +preserve any non-zero tags passed by the user via syscalls and stored in
> > +kernel data structures (e.g. ``set_robust_list()``, ``sigaltstack()``).
sigaltstack() is interesting, since we don't support tagged stacks.
Do we keep the ss_sp tag in the kernel, but squash it when delivering
a signal to the alternate stack?
(I can't remember whether this would be compatible with the
architectural tag checking semantics...)
> Hmm. I can see the need to provide this guarantee for things like
> set_robust_list(), but the problem is that the statement above is too broad
> and isn't strictly true: for example, mmap() doesn't propagate the tag of
> its address parameter into the VMA.
>
> So I think we need to nail this down a bit more, but I'm having a really
> hard time coming up with some wording :(
Time for some creative vagueness?
We can write a statement of our overall intent, along with examples of
a few cases where the tag should and should not be expected to emerge
intact.
There is no foolproof rule, unless we can rewrite history...
Cheers
---Dave
^ permalink raw reply
* Re: [PATCH v3] arm64: implement KPROBES_ON_FTRACE
From: Naveen N. Rao @ 2019-08-21 20:12 UTC (permalink / raw)
To: Catalin Marinas, Jonathan Corbet, Jisheng Zhang, Masami Hiramatsu,
Peter Zijlstra, Thomas Gleixner, Will Deacon
Cc: linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Ingo Molnar, Steven Rostedt
In-Reply-To: <20190821183501.33588dd8@xhacker.debian>
Jisheng Zhang wrote:
> KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it
> eliminates the need for a trap, as well as the need to emulate or
> single-step instructions.
>
> Tested on berlin arm64 platform.
>
> ~ # mount -t debugfs debugfs /sys/kernel/debug/
> ~ # cd /sys/kernel/debug/
> /sys/kernel/debug # echo 'p _do_fork' > tracing/kprobe_events
>
> before the patch:
>
> /sys/kernel/debug # cat kprobes/list
> ffffff801009fe28 k _do_fork+0x0 [DISABLED]
>
> after the patch:
>
> /sys/kernel/debug # cat kprobes/list
> ffffff801009ff54 k _do_fork+0x4 [DISABLED][FTRACE]
>
> Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
> ---
> KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it
> eliminates the need for a trap, as well as the need to emulate or
> single-step instructions.
>
> Applied after arm64 FTRACE_WITH_REGS:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2019-August/674404.html
>
> Changes since v2:
> - remove patch1, make it a single cleanup patch
> - remove "This patch" in the change log
> - implement arm64's kprobe_lookup_name() and arch_kprobe_on_func_entry instead
> patching the common kprobes code
>
> Changes since v1:
> - make the kprobes/x86: use instruction_pointer and instruction_pointer_set
> as patch1
> - add Masami's ACK to patch1
> - add some description about KPROBES_ON_FTRACE and why we need it on
> arm64
> - correct the log before the patch
> - remove the consolidation patch, make it as TODO
> - only adjust kprobe's addr when KPROBE_FLAG_FTRACE is set
> - if KPROBES_ON_FTRACE, ftrace_call_adjust() the kprobe's addr before
> calling ftrace_location()
> - update the kprobes-on-ftrace/arch-support.txt in doc
>
>
> .../debug/kprobes-on-ftrace/arch-support.txt | 2 +-
> arch/arm64/Kconfig | 1 +
> arch/arm64/kernel/probes/Makefile | 1 +
> arch/arm64/kernel/probes/ftrace.c | 60 +++++++++++++++++++
> arch/arm64/kernel/probes/kprobes.c | 23 +++++++
> 5 files changed, 86 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm64/kernel/probes/ftrace.c
>
> diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
> index 68f266944d5f..e8358a38981c 100644
> --- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
> +++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
> @@ -9,7 +9,7 @@
> | alpha: | TODO |
> | arc: | TODO |
> | arm: | TODO |
> - | arm64: | TODO |
> + | arm64: | ok |
> | c6x: | TODO |
> | csky: | TODO |
> | h8300: | TODO |
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 663392d1eae2..928700f15e23 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -167,6 +167,7 @@ config ARM64
> select HAVE_STACKPROTECTOR
> select HAVE_SYSCALL_TRACEPOINTS
> select HAVE_KPROBES
> + select HAVE_KPROBES_ON_FTRACE
> select HAVE_KRETPROBES
> select HAVE_GENERIC_VDSO
> select IOMMU_DMA if IOMMU_SUPPORT
> diff --git a/arch/arm64/kernel/probes/Makefile b/arch/arm64/kernel/probes/Makefile
> index 8e4be92e25b1..4020cfc66564 100644
> --- a/arch/arm64/kernel/probes/Makefile
> +++ b/arch/arm64/kernel/probes/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o \
> simulate-insn.o
> obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o \
> simulate-insn.o
> +obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
> diff --git a/arch/arm64/kernel/probes/ftrace.c b/arch/arm64/kernel/probes/ftrace.c
> new file mode 100644
> index 000000000000..1f0c09d02bb8
> --- /dev/null
> +++ b/arch/arm64/kernel/probes/ftrace.c
> @@ -0,0 +1,60 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Dynamic Ftrace based Kprobes Optimization
> + *
> + * Copyright (C) Hitachi Ltd., 2012
> + * Copyright (C) 2019 Jisheng Zhang <jszhang@kernel.org>
> + * Synaptics Incorporated
> + */
> +
> +#include <linux/kprobes.h>
> +
> +/* Ftrace callback handler for kprobes -- called under preepmt disabed */
> +void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
> + struct ftrace_ops *ops, struct pt_regs *regs)
> +{
> + struct kprobe *p;
> + struct kprobe_ctlblk *kcb;
> +
> + /* Preempt is disabled by ftrace */
> + p = get_kprobe((kprobe_opcode_t *)ip);
> + if (unlikely(!p) || kprobe_disabled(p))
> + return;
> +
> + kcb = get_kprobe_ctlblk();
> + if (kprobe_running()) {
> + kprobes_inc_nmissed_count(p);
> + } else {
> + unsigned long orig_ip = instruction_pointer(regs);
> + /* Kprobe handler expects regs->pc = pc + 4 as breakpoint hit */
> + instruction_pointer_set(regs, ip + sizeof(kprobe_opcode_t));
> +
> + __this_cpu_write(current_kprobe, p);
> + kcb->kprobe_status = KPROBE_HIT_ACTIVE;
> + if (!p->pre_handler || !p->pre_handler(p, regs)) {
> + /*
> + * Emulate singlestep (and also recover regs->pc)
> + * as if there is a nop
> + */
> + instruction_pointer_set(regs,
> + (unsigned long)p->addr + MCOUNT_INSN_SIZE);
> + if (unlikely(p->post_handler)) {
> + kcb->kprobe_status = KPROBE_HIT_SSDONE;
> + p->post_handler(p, regs, 0);
> + }
> + instruction_pointer_set(regs, orig_ip);
> + }
> + /*
> + * If pre_handler returns !0, it changes regs->pc. We have to
> + * skip emulating post_handler.
> + */
> + __this_cpu_write(current_kprobe, NULL);
> + }
> +}
> +NOKPROBE_SYMBOL(kprobe_ftrace_handler);
> +
> +int arch_prepare_kprobe_ftrace(struct kprobe *p)
> +{
> + p->ainsn.api.insn = NULL;
> + return 0;
> +}
> diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
> index c4452827419b..f2bf8c70da79 100644
> --- a/arch/arm64/kernel/probes/kprobes.c
> +++ b/arch/arm64/kernel/probes/kprobes.c
> @@ -551,6 +551,29 @@ void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
> return (void *)orig_ret_address;
> }
>
> +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
This should be CONFIG_KPROBES_ON_FTRACE since you only want to choose
the ftrace entry in that case.
> +kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
> +{
> + unsigned long addr = kallsyms_lookup_name(name);
> + unsigned long faddr;
> +
> + /*
> + * with -fpatchable-function-entry=2, the first 4 bytes is the
> + * LR saver, then the actual call insn. So ftrace location is
> + * always on the first 4 bytes offset.
> + */
> + faddr = ftrace_location_range(addr, addr + AARCH64_INSN_SIZE);
> + if (faddr)
> + return (kprobe_opcode_t *)faddr;
You should only return the ftrace location if offset is 0, since the
offset is added to the address returned from here (see _kprobe_addr()).
- Naveen
^ permalink raw reply
* Re: [PATCH v5 10/17] net: sgi: ioc3-eth: rework skb rx handling
From: Jakub Kicinski @ 2019-08-21 20:37 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Jonathan Corbet, Ralf Baechle, Paul Burton, James Hogan,
Dmitry Torokhov, Lee Jones, David S. Miller, Srinivas Kandagatla,
Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
Jiri Slaby, Evgeniy Polyakov, linux-doc, linux-kernel, linux-mips,
linux-input, netdev, linux-rtc, linux-serial,
Jesper Dangaard Brouer
In-Reply-To: <20190821162847.479c9967d4dc8026fe65fa0e@suse.de>
On Wed, 21 Aug 2019 16:28:47 +0200, Thomas Bogendoerfer wrote:
> > This looks like a DMA engine alignment requirement, more than an
> > optimization.
>
> that true, there are two constraints for the rx buffers, start must be aligned
> to 128 bytes and a buffer must not cross a 16kbyte boundary. I was already
> thinking of allocating pages and chop them up. Is there a Linux API available,
> which could help for implementing this ?
>
> I'll probably drop this patch or only change the skb_put stuff plus RX_BUF_SIZE
> define.
Sounds a little like frag allocator (napi_alloc_frag()/
netdev_alloc_frag()), but I'm not sure you'd have sufficient control
to skip over the 16k boundary.. Perhaps others have better suggestions.
^ permalink raw reply
* Re: [PATCH v2 4/6] dt-bindings: serial: Document Freescale LINFlex UART
From: Rob Herring @ 2019-08-21 21:18 UTC (permalink / raw)
To: Stefan-gabriel Mirea
Cc: corbet@lwn.net, mark.rutland@arm.com, gregkh@linuxfoundation.org,
catalin.marinas@arm.com, will@kernel.org, shawnguo@kernel.org,
Leo Li, jslaby@suse.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linux-serial@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Cosmin Stefan Stoica,
Larisa Ileana Grigore
In-Reply-To: <20190809112853.15846-5-stefan-gabriel.mirea@nxp.com>
On Fri, Aug 09, 2019 at 11:29:14AM +0000, Stefan-gabriel Mirea wrote:
> From: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>
>
> Add documentation for the serial communication interface module (LINFlex),
> found in two instances on S32V234.
>
> Signed-off-by: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>
> Signed-off-by: Larisa Grigore <Larisa.Grigore@nxp.com>
> Signed-off-by: Stefan-Gabriel Mirea <stefan-gabriel.mirea@nxp.com>
> ---
> .../bindings/serial/fsl,s32-linflexuart.txt | 24 +++++++++++++++++++
> 1 file changed, 24 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt
>
> diff --git a/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt b/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt
> new file mode 100644
> index 000000000000..957ffeaca9f1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt
> @@ -0,0 +1,24 @@
> +* Freescale Linflex UART
Be consistent with the name: LINFlexD?
> +
> +The LINFlexD controller implements several LIN protocol versions, as well as
> +support for full-duplex UART communication through 8-bit and 9-bit frames. The
> +Linflex UART driver enables operation only in UART mode.
What the driver supports or not is independent of the binding.
> +
> +See chapter 47 ("LINFlexD") in the reference manual[1].
> +
> +Required properties:
> +- compatible :
> + - "fsl,s32-linflexuart" for linflex configured in uart mode which
LINFlexD?
> + is compatible with the one integrated on S32V234 SoC
Compatibles should be SoC specific. Is 's32' specific enough to account
for any differences or future bugs found?
> +- reg : Address and length of the register set for the device
> +- interrupts : Should contain uart interrupt
> +
> +Example:
> +uart0:serial@40053000 {
space ^
> + compatible = "fsl,s32-linflexuart";
> + reg = <0x0 0x40053000 0x0 0x1000>;
> + interrupts = <0 59 4>;
> + status = "disabled";
Don't show status in examples.
> +};
> +
> +[1] https://www.nxp.com/webapp/Download?colCode=S32V234RM
> --
> 2.22.0
>
^ permalink raw reply
* [PATCH v4] arm64: implement KPROBES_ON_FTRACE
From: Jisheng Zhang @ 2019-08-22 3:45 UTC (permalink / raw)
To: Catalin Marinas, Jonathan Corbet, Masami Hiramatsu, Will Deacon,
Naveen N. Rao
Cc: Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Steven Rostedt,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Mark Rutland
KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it
eliminates the need for a trap, as well as the need to emulate or
single-step instructions.
Tested on berlin arm64 platform.
~ # mount -t debugfs debugfs /sys/kernel/debug/
~ # cd /sys/kernel/debug/
/sys/kernel/debug # echo 'p _do_fork' > tracing/kprobe_events
before the patch:
/sys/kernel/debug # cat kprobes/list
ffffff801009fe28 k _do_fork+0x0 [DISABLED]
after the patch:
/sys/kernel/debug # cat kprobes/list
ffffff801009ff54 k _do_fork+0x4 [DISABLED][FTRACE]
Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
---
KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it
eliminates the need for a trap, as well as the need to emulate or
single-step instructions.
Applied after arm64 FTRACE_WITH_REGS:
http://lists.infradead.org/pipermail/linux-arm-kernel/2019-August/674404.html
Changes since v3:
- move kprobe_lookup_name() and arch_kprobe_on_func_entry to ftrace.c since
we only want to choose the ftrace entry for KPROBES_ON_FTRACE.
- only choose ftrace entry if (addr && !offset)
Changes since v2:
- remove patch1, make it a single cleanup patch
- remove "This patch" in the change log
- implement arm64's kprobe_lookup_name() and arch_kprobe_on_func_entry instead
of patching the common kprobes code
Changes since v1:
- make the kprobes/x86: use instruction_pointer and instruction_pointer_set
as patch1
- add Masami's ACK to patch1
- add some description about KPROBES_ON_FTRACE and why we need it on
arm64
- correct the log before the patch
- remove the consolidation patch, make it as TODO
- only adjust kprobe's addr when KPROBE_FLAG_FTRACE is set
- if KPROBES_ON_FTRACE, ftrace_call_adjust() the kprobe's addr before
calling ftrace_location()
- update the kprobes-on-ftrace/arch-support.txt in doc
.../debug/kprobes-on-ftrace/arch-support.txt | 2 +-
arch/arm64/Kconfig | 1 +
arch/arm64/kernel/probes/Makefile | 1 +
arch/arm64/kernel/probes/ftrace.c | 84 +++++++++++++++++++
4 files changed, 87 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/kernel/probes/ftrace.c
diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
index 68f266944d5f..e8358a38981c 100644
--- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
+++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
@@ -9,7 +9,7 @@
| alpha: | TODO |
| arc: | TODO |
| arm: | TODO |
- | arm64: | TODO |
+ | arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 663392d1eae2..928700f15e23 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -167,6 +167,7 @@ config ARM64
select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
+ select HAVE_KPROBES_ON_FTRACE
select HAVE_KRETPROBES
select HAVE_GENERIC_VDSO
select IOMMU_DMA if IOMMU_SUPPORT
diff --git a/arch/arm64/kernel/probes/Makefile b/arch/arm64/kernel/probes/Makefile
index 8e4be92e25b1..4020cfc66564 100644
--- a/arch/arm64/kernel/probes/Makefile
+++ b/arch/arm64/kernel/probes/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o \
simulate-insn.o
obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o \
simulate-insn.o
+obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
diff --git a/arch/arm64/kernel/probes/ftrace.c b/arch/arm64/kernel/probes/ftrace.c
new file mode 100644
index 000000000000..5989c57660f3
--- /dev/null
+++ b/arch/arm64/kernel/probes/ftrace.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Dynamic Ftrace based Kprobes Optimization
+ *
+ * Copyright (C) Hitachi Ltd., 2012
+ * Copyright (C) 2019 Jisheng Zhang <jszhang@kernel.org>
+ * Synaptics Incorporated
+ */
+
+#include <linux/kprobes.h>
+
+/* Ftrace callback handler for kprobes -- called under preepmt disabed */
+void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
+ struct ftrace_ops *ops, struct pt_regs *regs)
+{
+ struct kprobe *p;
+ struct kprobe_ctlblk *kcb;
+
+ /* Preempt is disabled by ftrace */
+ p = get_kprobe((kprobe_opcode_t *)ip);
+ if (unlikely(!p) || kprobe_disabled(p))
+ return;
+
+ kcb = get_kprobe_ctlblk();
+ if (kprobe_running()) {
+ kprobes_inc_nmissed_count(p);
+ } else {
+ unsigned long orig_ip = instruction_pointer(regs);
+ /* Kprobe handler expects regs->pc = pc + 4 as breakpoint hit */
+ instruction_pointer_set(regs, ip + sizeof(kprobe_opcode_t));
+
+ __this_cpu_write(current_kprobe, p);
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+ if (!p->pre_handler || !p->pre_handler(p, regs)) {
+ /*
+ * Emulate singlestep (and also recover regs->pc)
+ * as if there is a nop
+ */
+ instruction_pointer_set(regs,
+ (unsigned long)p->addr + MCOUNT_INSN_SIZE);
+ if (unlikely(p->post_handler)) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ p->post_handler(p, regs, 0);
+ }
+ instruction_pointer_set(regs, orig_ip);
+ }
+ /*
+ * If pre_handler returns !0, it changes regs->pc. We have to
+ * skip emulating post_handler.
+ */
+ __this_cpu_write(current_kprobe, NULL);
+ }
+}
+NOKPROBE_SYMBOL(kprobe_ftrace_handler);
+
+kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
+{
+ unsigned long addr = kallsyms_lookup_name(name);
+
+ if (addr && !offset) {
+ unsigned long faddr;
+ /*
+ * with -fpatchable-function-entry=2, the first 4 bytes is the
+ * LR saver, then the actual call insn. So ftrace location is
+ * always on the first 4 bytes offset.
+ */
+ faddr = ftrace_location_range(addr,
+ addr + AARCH64_INSN_SIZE);
+ if (faddr)
+ return (kprobe_opcode_t *)faddr;
+ }
+ return (kprobe_opcode_t *)addr;
+}
+
+bool arch_kprobe_on_func_entry(unsigned long offset)
+{
+ return offset <= AARCH64_INSN_SIZE;
+}
+
+int arch_prepare_kprobe_ftrace(struct kprobe *p)
+{
+ p->ainsn.api.insn = NULL;
+ return 0;
+}
--
2.23.0.rc1
^ permalink raw reply related
* Re: [PATCH v3 2/2] drivers/perf: Add CCPI2 PMU support in ThunderX2 UNCORE driver.
From: Ganapatrao Kulkarni @ 2019-08-22 4:00 UTC (permalink / raw)
To: Will Deacon
Cc: Mark Rutland, Ganapatrao Kulkarni, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, corbet@lwn.net,
Jayachandran Chandrasekharan Nair, Robert Richter, Jan Glauber
In-Reply-To: <20190821165339.7gu4rxkvdjcr4mta@willie-the-truck>
On Wed, Aug 21, 2019 at 10:23 PM Will Deacon <will@kernel.org> wrote:
>
> On Tue, Aug 13, 2019 at 12:03:45PM +0100, Mark Rutland wrote:
> > On Tue, Aug 13, 2019 at 04:25:15PM +0530, Ganapatrao Kulkarni wrote:
> > > On Mon, Aug 12, 2019 at 5:31 PM Mark Rutland <mark.rutland@arm.com> wrote:
> > > >
> > > > On Tue, Jul 23, 2019 at 09:16:28AM +0000, Ganapatrao Kulkarni wrote:
> > > > > CCPI2 is a low-latency high-bandwidth serial interface for connecting
> > > > > ThunderX2 processors. This patch adds support to capture CCPI2 perf events.
> > > >
> > > > It would be worth pointing out in the commit message how the CCPI2
> > > > counters differ from the others. I realise you have that in the body of
> > > > patch 1, but it's critical information when reviewing this patch...
> > >
> > > Ok, I will add in next version.
> > > >
> > > > >
> > > > > Signed-off-by: Ganapatrao Kulkarni <gkulkarni@marvell.com>
> > > > > ---
> > > > > drivers/perf/thunderx2_pmu.c | 248 ++++++++++++++++++++++++++++++-----
> > > > > 1 file changed, 214 insertions(+), 34 deletions(-)
> > > > >
> > > > > diff --git a/drivers/perf/thunderx2_pmu.c b/drivers/perf/thunderx2_pmu.c
> > > > > index 43d76c85da56..a4e1273eafa3 100644
> > > > > --- a/drivers/perf/thunderx2_pmu.c
> > > > > +++ b/drivers/perf/thunderx2_pmu.c
> > > > > @@ -17,22 +17,31 @@
> > > > > */
> > > > >
> > > > > #define TX2_PMU_MAX_COUNTERS 4
> > > >
> > > > Shouldn't this be 8 now?
> > >
> > > It is kept unchanged to 4(as suggested by Will), which is same for
> > > both L3 and DMC.
> > > For CCPI2 this macro is not used.
> >
> > Hmmm....
> >
> > I disagree with that suggestion given that this also affects the
> > active_counters bitmap size (and thus it is not correctly sized as of
> > this patch), and it doesn't really save us much.
> >
> > I think it would be better to bump this to 8 and always update the
> > events array, even though it will be unused for CCPI2. That's less
> > surprising, needs fewer special-cases, and we can use the hrtimer
> > function pointer alone to determine if we need to do any hrtimer work.
>
> tbf, my complaint was actually about some macros applying to the whole
> PMU whilst others refer only to DMC/L3C and this not being apparent from
> the naming:
>
> https://lkml.org/lkml/2019/6/27/250
>
> so I'm fine having TX2_PMU_DMC_L3C_MAX_COUNTERS and
> TX2_PMU_CCPI2_MAX_COUNTERS, but that sort of naming needs to be consistent
> unless the macro/definition really applies to both. That fed the suggestion
> that GET_EVENTID could be generic and switch on the event type internally
> instead of at the caller.
Thanks Will for the clarification.
I will send new version with changes as suggested.
>
> Will
Thanks,
Ganapat
^ permalink raw reply
* Re: [PATCH v4] arm64: implement KPROBES_ON_FTRACE
From: Naveen N. Rao @ 2019-08-22 6:53 UTC (permalink / raw)
To: Catalin Marinas, Jonathan Corbet, Jisheng Zhang, Masami Hiramatsu,
Will Deacon
Cc: linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Mark Rutland, Ingo Molnar,
Peter Zijlstra, Steven Rostedt, Thomas Gleixner
In-Reply-To: <20190822113421.52920377@xhacker.debian>
Jisheng Zhang wrote:
> KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it
> eliminates the need for a trap, as well as the need to emulate or
> single-step instructions.
>
> Tested on berlin arm64 platform.
>
> ~ # mount -t debugfs debugfs /sys/kernel/debug/
> ~ # cd /sys/kernel/debug/
> /sys/kernel/debug # echo 'p _do_fork' > tracing/kprobe_events
>
> before the patch:
>
> /sys/kernel/debug # cat kprobes/list
> ffffff801009fe28 k _do_fork+0x0 [DISABLED]
>
> after the patch:
>
> /sys/kernel/debug # cat kprobes/list
> ffffff801009ff54 k _do_fork+0x4 [DISABLED][FTRACE]
>
> Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
This looks good to me. Except for a small confirmation below:
Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
> ---
> KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it
> eliminates the need for a trap, as well as the need to emulate or
> single-step instructions.
>
> Applied after arm64 FTRACE_WITH_REGS:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2019-August/674404.html
>
> Changes since v3:
> - move kprobe_lookup_name() and arch_kprobe_on_func_entry to ftrace.c since
> we only want to choose the ftrace entry for KPROBES_ON_FTRACE.
> - only choose ftrace entry if (addr && !offset)
>
> Changes since v2:
> - remove patch1, make it a single cleanup patch
> - remove "This patch" in the change log
> - implement arm64's kprobe_lookup_name() and arch_kprobe_on_func_entry instead
> of patching the common kprobes code
>
> Changes since v1:
> - make the kprobes/x86: use instruction_pointer and instruction_pointer_set
> as patch1
> - add Masami's ACK to patch1
> - add some description about KPROBES_ON_FTRACE and why we need it on
> arm64
> - correct the log before the patch
> - remove the consolidation patch, make it as TODO
> - only adjust kprobe's addr when KPROBE_FLAG_FTRACE is set
> - if KPROBES_ON_FTRACE, ftrace_call_adjust() the kprobe's addr before
> calling ftrace_location()
> - update the kprobes-on-ftrace/arch-support.txt in doc
>
>
> .../debug/kprobes-on-ftrace/arch-support.txt | 2 +-
> arch/arm64/Kconfig | 1 +
> arch/arm64/kernel/probes/Makefile | 1 +
> arch/arm64/kernel/probes/ftrace.c | 84 +++++++++++++++++++
> 4 files changed, 87 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm64/kernel/probes/ftrace.c
>
> diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
> index 68f266944d5f..e8358a38981c 100644
> --- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
> +++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
> @@ -9,7 +9,7 @@
> | alpha: | TODO |
> | arc: | TODO |
> | arm: | TODO |
> - | arm64: | TODO |
> + | arm64: | ok |
> | c6x: | TODO |
> | csky: | TODO |
> | h8300: | TODO |
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 663392d1eae2..928700f15e23 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -167,6 +167,7 @@ config ARM64
> select HAVE_STACKPROTECTOR
> select HAVE_SYSCALL_TRACEPOINTS
> select HAVE_KPROBES
> + select HAVE_KPROBES_ON_FTRACE
> select HAVE_KRETPROBES
> select HAVE_GENERIC_VDSO
> select IOMMU_DMA if IOMMU_SUPPORT
> diff --git a/arch/arm64/kernel/probes/Makefile b/arch/arm64/kernel/probes/Makefile
> index 8e4be92e25b1..4020cfc66564 100644
> --- a/arch/arm64/kernel/probes/Makefile
> +++ b/arch/arm64/kernel/probes/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o \
> simulate-insn.o
> obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o \
> simulate-insn.o
> +obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
> diff --git a/arch/arm64/kernel/probes/ftrace.c b/arch/arm64/kernel/probes/ftrace.c
> new file mode 100644
> index 000000000000..5989c57660f3
> --- /dev/null
> +++ b/arch/arm64/kernel/probes/ftrace.c
> @@ -0,0 +1,84 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Dynamic Ftrace based Kprobes Optimization
> + *
> + * Copyright (C) Hitachi Ltd., 2012
> + * Copyright (C) 2019 Jisheng Zhang <jszhang@kernel.org>
> + * Synaptics Incorporated
> + */
> +
> +#include <linux/kprobes.h>
> +
> +/* Ftrace callback handler for kprobes -- called under preepmt disabed */
> +void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
> + struct ftrace_ops *ops, struct pt_regs *regs)
> +{
> + struct kprobe *p;
> + struct kprobe_ctlblk *kcb;
> +
> + /* Preempt is disabled by ftrace */
> + p = get_kprobe((kprobe_opcode_t *)ip);
> + if (unlikely(!p) || kprobe_disabled(p))
> + return;
> +
> + kcb = get_kprobe_ctlblk();
> + if (kprobe_running()) {
> + kprobes_inc_nmissed_count(p);
> + } else {
> + unsigned long orig_ip = instruction_pointer(regs);
> + /* Kprobe handler expects regs->pc = pc + 4 as breakpoint hit */
> + instruction_pointer_set(regs, ip + sizeof(kprobe_opcode_t));
Just want to make sure that you've confirmed that this is what happens
with a regular trap/brk based kprobe on ARM64. The reason for setting
the instruction pointer here is to ensure that it is set to the same
value as would be set if there was a trap/brk instruction at the ftrace
location. This ensures that the kprobe pre handler sees the same value
regardless.
Further changes to the instruction pointer are to achieve the same
effect for kprobe post handlers.
- Naveen
^ permalink raw reply
* [PATCH 1/3] udmabuf: add documentation
From: Gerd Hoffmann @ 2019-08-22 9:36 UTC (permalink / raw)
To: dri-devel
Cc: laurent.pinchart, daniel, Gerd Hoffmann, Sumit Semwal,
Jonathan Corbet, open list:DMA BUFFER SHARING FRAMEWORK,
moderated list:DMA BUFFER SHARING FRAMEWORK,
open list:DOCUMENTATION, open list
In-Reply-To: <20190822093654.23752-1-kraxel@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
include/uapi/linux/udmabuf.h | 52 ++++++++++++++++++++++++++--
Documentation/driver-api/dma-buf.rst | 8 +++++
2 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/udmabuf.h b/include/uapi/linux/udmabuf.h
index 46b6532ed855..9fe440abf2f9 100644
--- a/include/uapi/linux/udmabuf.h
+++ b/include/uapi/linux/udmabuf.h
@@ -5,8 +5,39 @@
#include <linux/types.h>
#include <linux/ioctl.h>
+/**
+ * DOC: udmabuf
+ *
+ * udmabuf is a device driver which allows userspace to create
+ * dmabufs. The memory used for these dmabufs must be backed by
+ * memfd. The memfd must have F_SEAL_SHRINK and it must not have
+ * F_SEAL_WRITE.
+ *
+ * The driver has two ioctls, one to create a dmabuf from a single
+ * memory block and one to create a dmabuf from a list of memory
+ * blocks.
+ *
+ * UDMABUF_CREATE - _IOW('u', 0x42, udmabuf_create)
+ *
+ * UDMABUF_CREATE_LIST - _IOW('u', 0x43, udmabuf_create_list)
+ */
+
+#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
+#define UDMABUF_CREATE_LIST _IOW('u', 0x43, struct udmabuf_create_list)
+
#define UDMABUF_FLAGS_CLOEXEC 0x01
+/**
+ * struct udmabuf_create - create a dmabuf from a single memory block.
+ *
+ * @memfd: The file handle.
+ * @offset: Start of the buffer (from memfd start).
+ * Must be page aligned.
+ * @size: Size of the buffer. Must be rounded to page size.
+ *
+ * @flags:
+ * UDMABUF_FLAGS_CLOEXEC: set CLOEXEC flag for the dmabuf.
+ */
struct udmabuf_create {
__u32 memfd;
__u32 flags;
@@ -14,6 +45,15 @@ struct udmabuf_create {
__u64 size;
};
+/**
+ * struct udmabuf_create_item - one memory block list item.
+ *
+ * @memfd: The file handle.
+ * @__pad: Padding field (unused).
+ * @offset: Start of the buffer (from memfd start).
+ * Must be page aligned.
+ * @size: Size of the buffer. Must be rounded to page size.
+ */
struct udmabuf_create_item {
__u32 memfd;
__u32 __pad;
@@ -21,13 +61,19 @@ struct udmabuf_create_item {
__u64 size;
};
+/**
+ * struct udmabuf_create_list - create a dmabuf from a memory block list.
+ *
+ * @count: The number of list elements.
+ * @list: The memory block list
+ *
+ * @flags:
+ * UDMABUF_FLAGS_CLOEXEC: set CLOEXEC flag for the dmabuf.
+ */
struct udmabuf_create_list {
__u32 flags;
__u32 count;
struct udmabuf_create_item list[];
};
-#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)
-#define UDMABUF_CREATE_LIST _IOW('u', 0x43, struct udmabuf_create_list)
-
#endif /* _UAPI_LINUX_UDMABUF_H */
diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
index b541e97c7ab1..1f62c30a14b0 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -166,3 +166,11 @@ DMA Fence uABI/Sync File
.. kernel-doc:: include/linux/sync_file.h
:internal:
+Userspace DMA Buffer driver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: include/uapi/linux/udmabuf.h
+ :doc: udmabuf
+
+.. kernel-doc:: include/uapi/linux/udmabuf.h
+ :internal:
--
2.18.1
^ permalink raw reply related
* Re: [PATCH v9 2/3] arm64: Define Documentation/arm64/tagged-address-abi.rst
From: Kevin Brodsky @ 2019-08-22 9:38 UTC (permalink / raw)
To: Andrey Konovalov, Catalin Marinas
Cc: Linux ARM, Linux Memory Management List, Andrew Morton,
Vincenzo Frascino, Will Deacon, Szabolcs Nagy, Dave P Martin,
Dave Hansen, open list:DOCUMENTATION, linux-arch, Will Deacon
In-Reply-To: <CAAeHK+wHDx5bqNd+OQuJWoiA=LzsjCWkQ2UY_JVipr852Gv4JA@mail.gmail.com>
On 21/08/2019 17:57, Andrey Konovalov wrote:
> On Wed, Aug 21, 2019 at 6:47 PM Catalin Marinas <catalin.marinas@arm.com> wrote:
>> From: Vincenzo Frascino <vincenzo.frascino@arm.com>
>>
>> On AArch64 the TCR_EL1.TBI0 bit is set by default, allowing userspace
>> (EL0) to perform memory accesses through 64-bit pointers with a non-zero
>> top byte. Introduce the document describing the relaxation of the
>> syscall ABI that allows userspace to pass certain tagged pointers to
>> kernel syscalls.
>>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Andrey Konovalov <andreyknvl@google.com>
>> Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
>> Cc: Kevin Brodsky <kevin.brodsky@arm.com>
>> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
>> Co-developed-by: Catalin Marinas <catalin.marinas@arm.com>
>> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> Acked-by: Andrey Konovalov <andreyknvl@google.com>
Acked-by: Kevin Brodsky <kevin.brodsky@arm.com>
>> ---
>> Documentation/arm64/tagged-address-abi.rst | 156 +++++++++++++++++++++
>> 1 file changed, 156 insertions(+)
>> create mode 100644 Documentation/arm64/tagged-address-abi.rst
>>
>> diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst
>> new file mode 100644
>> index 000000000000..d4a85d535bf9
>> --- /dev/null
>> +++ b/Documentation/arm64/tagged-address-abi.rst
>> @@ -0,0 +1,156 @@
>> +==========================
>> +AArch64 TAGGED ADDRESS ABI
>> +==========================
>> +
>> +Authors: Vincenzo Frascino <vincenzo.frascino@arm.com>
>> + Catalin Marinas <catalin.marinas@arm.com>
>> +
>> +Date: 21 August 2019
>> +
>> +This document describes the usage and semantics of the Tagged Address
>> +ABI on AArch64 Linux.
>> +
>> +1. Introduction
>> +---------------
>> +
>> +On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing
>> +userspace (EL0) to perform memory accesses through 64-bit pointers with
>> +a non-zero top byte. This document describes the relaxation of the
>> +syscall ABI that allows userspace to pass certain tagged pointers to
>> +kernel syscalls.
>> +
>> +2. AArch64 Tagged Address ABI
>> +-----------------------------
>> +
>> +From the kernel syscall interface perspective and for the purposes of
>> +this document, a "valid tagged pointer" is a pointer with a potentially
>> +non-zero top-byte that references an address in the user process address
>> +space obtained in one of the following ways:
>> +
>> +- ``mmap()`` syscall where either:
>> +
>> + - flags have the ``MAP_ANONYMOUS`` bit set or
>> + - the file descriptor refers to a regular file (including those
>> + returned by ``memfd_create()``) or ``/dev/zero``
>> +
>> +- ``brk()`` syscall (i.e. the heap area between the initial location of
>> + the program break at process creation and its current location).
>> +
>> +- any memory mapped by the kernel in the address space of the process
>> + during creation and with the same restrictions as for ``mmap()`` above
>> + (e.g. data, bss, stack).
>> +
>> +The AArch64 Tagged Address ABI has two stages of relaxation depending
>> +how the user addresses are used by the kernel:
>> +
>> +1. User addresses not accessed by the kernel but used for address space
>> + management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
>> + of valid tagged pointers in this context is always allowed.
>> +
>> +2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
>> + relaxation is disabled by default and the application thread needs to
>> + explicitly enable it via ``prctl()`` as follows:
>> +
>> + - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged
>> + Address ABI for the calling thread.
>> +
>> + The ``(unsigned int) arg2`` argument is a bit mask describing the
>> + control mode used:
>> +
>> + - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI.
>> + Default status is disabled.
>> +
>> + Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0.
>> +
>> + - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged
>> + Address ABI for the calling thread.
>> +
>> + Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0.
>> +
>> + The ABI properties described above are thread-scoped, inherited on
>> + clone() and fork() and cleared on exec().
>> +
>> + Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)``
>> + returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally
>> + disabled by ``sysctl abi.tagged_addr_disabled=1``. The default
>> + ``sysctl abi.tagged_addr_disabled`` configuration is 0.
>> +
>> +When the AArch64 Tagged Address ABI is enabled for a thread, the
>> +following behaviours are guaranteed:
>> +
>> +- All syscalls except the cases mentioned in section 3 can accept any
>> + valid tagged pointer.
>> +
>> +- The syscall behaviour is undefined for invalid tagged pointers: it may
>> + result in an error code being returned, a (fatal) signal being raised,
>> + or other modes of failure.
>> +
>> +- The syscall behaviour for a valid tagged pointer is the same as for
>> + the corresponding untagged pointer.
>> +
>> +
>> +A definition of the meaning of tagged pointers on AArch64 can be found
>> +in Documentation/arm64/tagged-pointers.rst.
>> +
>> +3. AArch64 Tagged Address ABI Exceptions
>> +-----------------------------------------
>> +
>> +The following system call parameters must be untagged regardless of the
>> +ABI relaxation:
>> +
>> +- ``prctl()`` other than pointers to user data either passed directly or
>> + indirectly as arguments to be accessed by the kernel.
>> +
>> +- ``ioctl()`` other than pointers to user data either passed directly or
>> + indirectly as arguments to be accessed by the kernel.
>> +
>> +- ``shmat()`` and ``shmdt()``.
>> +
>> +Any attempt to use non-zero tagged pointers may result in an error code
>> +being returned, a (fatal) signal being raised, or other modes of
>> +failure.
>> +
>> +4. Example of correct usage
>> +---------------------------
>> +.. code-block:: c
>> +
>> + #include <stdlib.h>
>> + #include <string.h>
>> + #include <unistd.h>
>> + #include <sys/mman.h>
>> + #include <sys/prctl.h>
>> +
>> + #define PR_SET_TAGGED_ADDR_CTRL 55
>> + #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
>> +
>> + #define TAG_SHIFT 56
>> +
>> + int main(void)
>> + {
>> + int tbi_enabled = 0;
>> + unsigned long tag = 0;
>> + char *ptr;
>> +
>> + /* check/enable the tagged address ABI */
>> + if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0))
>> + tbi_enabled = 1;
>> +
>> + /* memory allocation */
>> + ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
>> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>> + if (ptr == MAP_FAILED)
>> + return 1;
>> +
>> + /* set a non-zero tag if the ABI is available */
>> + if (tbi_enabled)
>> + tag = rand() & 0xff;
>> + ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT));
>> +
>> + /* memory access to a tagged address */
>> + strcpy(ptr, "tagged pointer\n");
>> +
>> + /* syscall with a tagged pointer */
>> + write(1, ptr, strlen(ptr));
>> +
>> + return 0;
>> + }
^ permalink raw reply
* Re: [PATCH v4] arm64: implement KPROBES_ON_FTRACE
From: Jisheng Zhang @ 2019-08-22 9:47 UTC (permalink / raw)
To: Naveen N. Rao
Cc: Catalin Marinas, Jonathan Corbet, Masami Hiramatsu, Will Deacon,
linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Mark Rutland, Ingo Molnar,
Peter Zijlstra, Steven Rostedt, Thomas Gleixner
In-Reply-To: <1566456155.27ojwy97ss.naveen@linux.ibm.com>
Hi,
On Thu, 22 Aug 2019 12:23:58 +0530
"Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
>
>
> Jisheng Zhang wrote:
> > KPROBES_ON_FTRACE avoids much of the overhead with regular kprobes as it
> > eliminates the need for a trap, as well as the need to emulate or
> > single-step instructions.
> >
> > Tested on berlin arm64 platform.
> >
> > ~ # mount -t debugfs debugfs /sys/kernel/debug/
> > ~ # cd /sys/kernel/debug/
> > /sys/kernel/debug # echo 'p _do_fork' > tracing/kprobe_events
> >
> > before the patch:
> >
> > /sys/kernel/debug # cat kprobes/list
> > ffffff801009fe28 k _do_fork+0x0 [DISABLED]
> >
> > after the patch:
> >
> > /sys/kernel/debug # cat kprobes/list
> > ffffff801009ff54 k _do_fork+0x4 [DISABLED][FTRACE]
> >
> > Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
>
> This looks good to me. Except for a small confirmation below:
> Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
>
>
<...>
> > +/* Ftrace callback handler for kprobes -- called under preepmt disabed */
> > +void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
> > + struct ftrace_ops *ops, struct pt_regs *regs)
> > +{
> > + struct kprobe *p;
> > + struct kprobe_ctlblk *kcb;
> > +
> > + /* Preempt is disabled by ftrace */
> > + p = get_kprobe((kprobe_opcode_t *)ip);
> > + if (unlikely(!p) || kprobe_disabled(p))
> > + return;
> > +
> > + kcb = get_kprobe_ctlblk();
> > + if (kprobe_running()) {
> > + kprobes_inc_nmissed_count(p);
> > + } else {
> > + unsigned long orig_ip = instruction_pointer(regs);
> > + /* Kprobe handler expects regs->pc = pc + 4 as breakpoint hit */
> > + instruction_pointer_set(regs, ip + sizeof(kprobe_opcode_t));
>
> Just want to make sure that you've confirmed that this is what happens
> with a regular trap/brk based kprobe on ARM64. The reason for setting
> the instruction pointer here is to ensure that it is set to the same
> value as would be set if there was a trap/brk instruction at the ftrace
> location. This ensures that the kprobe pre handler sees the same value
> regardless.
Due to the arm64's DYNAMIC_FTRACE_WITH_REGS implementation, the code itself
is correct. But this doesn't look like "there was a trap instruction at
the ftrace location".
W/O KPROBE_ON_FTRACE:
foo:
00 insA
04 insB
08 insC
kprobe's pre_handler() will see pc points to 00.
W/ KPROBE_ON_FTRACE:
foo:
00 lr saver
04 nop // will be modified to ftrace call ins when KPROBE is armed
08 insA
0c insB
later, kprobe_ftrace_handler() will see pc points to 04, so pc + 4 will
point to 08 the same as the one w/o KPROBE_ON_FTRACE.
It seems I need to fix the comment.
>
> Further changes to the instruction pointer are to achieve the same
> effect for kprobe post handlers.
>
>
^ permalink raw reply
* Re: [PATCH v4] arm64: implement KPROBES_ON_FTRACE
From: Naveen N. Rao @ 2019-08-22 10:22 UTC (permalink / raw)
To: Jisheng Zhang
Cc: Catalin Marinas, Jonathan Corbet,
linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Mark Rutland, Masami Hiramatsu,
Ingo Molnar, Peter Zijlstra, Steven Rostedt, Thomas Gleixner,
Will Deacon
In-Reply-To: <20190822173558.63de3fc4@xhacker.debian>
Jisheng Zhang wrote:
> Hi,
>
> On Thu, 22 Aug 2019 12:23:58 +0530
> "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
>> Jisheng Zhang wrote:
...
>> > +/* Ftrace callback handler for kprobes -- called under preepmt
>> > disabed */
>> > +void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> > + struct ftrace_ops *ops, struct pt_regs *regs)
>> > +{
>> > + struct kprobe *p;
>> > + struct kprobe_ctlblk *kcb;
>> > +
>> > + /* Preempt is disabled by ftrace */
>> > + p = get_kprobe((kprobe_opcode_t *)ip);
>> > + if (unlikely(!p) || kprobe_disabled(p))
>> > + return;
>> > +
>> > + kcb = get_kprobe_ctlblk();
>> > + if (kprobe_running()) {
>> > + kprobes_inc_nmissed_count(p);
>> > + } else {
>> > + unsigned long orig_ip = instruction_pointer(regs);
>> > + /* Kprobe handler expects regs->pc = pc + 4 as breakpoint hit */
>> > + instruction_pointer_set(regs, ip + sizeof(kprobe_opcode_t));
>>
>> Just want to make sure that you've confirmed that this is what happens
>> with a regular trap/brk based kprobe on ARM64. The reason for setting
>> the instruction pointer here is to ensure that it is set to the same
>> value as would be set if there was a trap/brk instruction at the ftrace
>> location. This ensures that the kprobe pre handler sees the same value
>> regardless.
>
> Due to the arm64's DYNAMIC_FTRACE_WITH_REGS implementation, the code itself
> is correct. But this doesn't look like "there was a trap instruction at
> the ftrace location".
>
> W/O KPROBE_ON_FTRACE:
>
> foo:
> 00 insA
> 04 insB
> 08 insC
>
> kprobe's pre_handler() will see pc points to 00.
In this case, the probe will be placed at foo+0x00, so pre_handler()
seeing that address in pt_regs is correct behavior - as long as arm64
'brk' instruction causes an exception with the instruction pointer set
*to* the 'brk' instruction. This is similar to how powerpc 'trap' works.
However, x86 'int3' causes an exception *after* execution of the
instruction.
>
> W/ KPROBE_ON_FTRACE:
>
> foo:
> 00 lr saver
> 04 nop // will be modified to ftrace call ins when KPROBE is armed
> 08 insA
> 0c insB
In this case, if user asks for a probe to be placed at 'foo', we will
choose foo+0x04 and from that point on, the behavior should reflect that
a kprobe was placed at foo+0x04. In particular, the pre_handler() should
see foo+0x04 in pt_regs. The post_handler() would then see foo+0x08.
>
> later, kprobe_ftrace_handler() will see pc points to 04, so pc + 4 will
> point to 08 the same as the one w/o KPROBE_ON_FTRACE.
I didn't mean to compare regular trap/brk based kprobes with
KPROBES_ON_FTRACE. The only important aspect is that the handlers see
consistent pt_regs in both cases, depending on where the kprobe was
placed. Choosing a different address/offset to place a kprobe during its
registration is an orthogonal aspect.
>
> It seems I need to fix the comment.
Given your explanation above, I think you can simply drop the first
adjustment to the instruction pointer before the pre handler invocation.
The rest of the code looks fine.
- Naveen
^ permalink raw reply
* Re: [PATCH v3 04/10] KVM: Implement kvm_put_guest()
From: Jonathan Cameron @ 2019-08-22 10:29 UTC (permalink / raw)
To: Steven Price
Cc: Marc Zyngier, Will Deacon, linux-arm-kernel, kvmarm, Mark Rutland,
linux-kernel, kvm, Radim Krčmář, Catalin Marinas,
Suzuki K Pouloze, linux-doc, Russell King, James Morse,
Paolo Bonzini, Julien Thierry
In-Reply-To: <20190821153656.33429-5-steven.price@arm.com>
On Wed, 21 Aug 2019 16:36:50 +0100
Steven Price <steven.price@arm.com> wrote:
> kvm_put_guest() is analogous to put_user() - it writes a single value to
> the guest physical address. The implementation is built upon put_user()
> and so it has the same single copy atomic properties.
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> include/linux/kvm_host.h | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index fcb46b3374c6..e154a1897e20 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -746,6 +746,30 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
> unsigned long len);
> int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
> gpa_t gpa, unsigned long len);
> +
> +#define __kvm_put_guest(kvm, gfn, offset, value, type) \
> +({ \
> + unsigned long __addr = gfn_to_hva(kvm, gfn); \
> + type __user *__uaddr = (type __user *)(__addr + offset); \
> + int __ret = 0; \
Why initialize __ret?
> + \
> + if (kvm_is_error_hva(__addr)) \
> + __ret = -EFAULT; \
> + else \
> + __ret = put_user(value, __uaddr); \
> + if (!__ret) \
> + mark_page_dirty(kvm, gfn); \
> + __ret; \
> +})
> +
> +#define kvm_put_guest(kvm, gpa, value, type) \
> +({ \
> + gpa_t __gpa = gpa; \
> + struct kvm *__kvm = kvm; \
> + __kvm_put_guest(__kvm, __gpa >> PAGE_SHIFT, \
> + offset_in_page(__gpa), (value), type); \
> +})
> +
> int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
> int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
> struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox