1
0
mirror of https://git.yoctoproject.org/meta-arm synced 2026-06-06 14:50:03 +00:00

arm-bsp/tc1: use latest kernel and u-boot

Drop usage of the Android kernel and legacy u-boot in favor of the
latest of both

Signed-off-by: Jon Mason <jon.mason@arm.com>
This commit is contained in:
Jon Mason
2023-04-14 13:37:01 -04:00
parent 87831bf559
commit 6033dcb106
80 changed files with 3 additions and 24784 deletions
+1 -2
View File
@@ -6,13 +6,12 @@ MACHINEOVERRIDES =. "tc:"
# Das U-boot
UBOOT_MACHINE ?= "total_compute_defconfig"
PREFERRED_VERSION_u-boot ?= "2022.04"
UBOOT_RD_LOADADDRESS = "0x88000000"
UBOOT_RD_ENTRYPOINT = "0x88000000"
UBOOT_LOADADDRESS = "0x80080000"
UBOOT_ENTRYPOINT = "0x80080000"
PREFERRED_PROVIDER_virtual/kernel ?= "linux-arm64-ack"
PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
# OP-TEE
PREFERRED_VERSION_optee-os ?= "3.18%"
@@ -1,33 +0,0 @@
From f7c24393604e45012447b16aaa95eb5e7224ba07 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Tue, 12 Apr 2022 12:43:49 +0100
Subject: [PATCH] arm: total_compute: update secure dram size
Update secure DRAM size as it is increased by 64MB for additional
secure partitions.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Id8ce99c7a5330d3c28d473009c4db04141e6fa4d
Upstream-Status: Pending [Not submitted to upstream yet]
---
include/configs/total_compute.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/configs/total_compute.h b/include/configs/total_compute.h
index 0324b1e1b217..62bdb4f6a3ae 100644
--- a/include/configs/total_compute.h
+++ b/include/configs/total_compute.h
@@ -23,8 +23,8 @@
/* Physical Memory Map */
#define PHYS_SDRAM_1 0x80000000
-/* Top 48MB reserved for secure world use */
-#define DRAM_SEC_SIZE 0x03000000
+/* Top 112MB reserved for secure world use */
+#define DRAM_SEC_SIZE 0x07000000
#define PHYS_SDRAM_1_SIZE 0x80000000 - DRAM_SEC_SIZE
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
--
2.30.2
@@ -1,30 +0,0 @@
From 8dd3e03bd83939746b6a849dce37435ea7581032 Mon Sep 17 00:00:00 2001
From: Davidson K <davidson.kumaresan@arm.com>
Date: Thu, 14 Jul 2022 19:35:41 +0530
Subject: [PATCH 3/7] arm: total_compute: enable psci
psci is used for system reset
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: Iff4f769dc5e64b6000e892d77a011102b090acfd
Upstream-Status: Submitted [https://patchwork.ozlabs.org/project/uboot/patch/20220809102652.23776-1-davidson.kumaresan@arm.com/]
---
arch/arm/dts/total_compute.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/total_compute.dts b/arch/arm/dts/total_compute.dts
index 4399269a44..96edacda0b 100644
--- a/arch/arm/dts/total_compute.dts
+++ b/arch/arm/dts/total_compute.dts
@@ -45,4 +45,8 @@
clock-frequency = <24000000>;
clock-output-names = "bp:clock24mhz";
};
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2";
+ method = "smc";
+ };
};
--
2.34.1
@@ -1,37 +0,0 @@
From 6eee50e5376356b1faeb30507b411120a8b5c7d1 Mon Sep 17 00:00:00 2001
From: Davidson K <davidson.kumaresan@arm.com>
Date: Mon, 6 Jun 2022 15:13:15 +0530
Subject: [PATCH 4/7] arm_ffa: rxtx_map should use 64 bit calls
rxtx_map deals with the 64 bit addresses and hence the 64 bit calls
should be used
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: Iec1251266e61139767588d683d60bada1ed10abe
Upstream-Status: Pending [Not submitted to upstream yet]
---
include/arm_ffa.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index 313f46f747..9627107079 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -58,12 +58,13 @@
ARM_SMCCC_OWNER_STANDARD, (func_num))
#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
#define FFA_VERSION FFA_SMC_32(0x63)
#define FFA_ID_GET FFA_SMC_32(0x69)
#define FFA_FEATURES FFA_SMC_32(0x64)
#define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68)
-#define FFA_RXTX_MAP FFA_SMC_32(0x66)
+#define FFA_RXTX_MAP FFA_SMC_64(0x66)
#define FFA_RXTX_UNMAP FFA_SMC_32(0x67)
#define FFA_RX_RELEASE FFA_SMC_32(0x65)
#define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_32(0x6F)
--
2.34.1
@@ -1,993 +0,0 @@
From 6d26058401bce6012173b5341cdf4de72772a1c2 Mon Sep 17 00:00:00 2001
From: Davidson K <davidson.kumaresan@arm.com>
Date: Mon, 6 Jun 2022 13:19:07 +0530
Subject: [PATCH 5/7] efi_firmware: add new fmp driver that supports arm fwu
specification
This fmp driver communicates to the firmware update secure partition
executing in the secure world which is an implementation of the arm
psa specification for the firmware update. The communication to the
firmware update secure partition is based on stmm and arm ff-a framework.
It implements only the get_image_info and set_image api.
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: I94c2cad210c32a60a8a0594cacf530b68ab6a09d
Upstream-Status: Pending [Not submitted to upstream yet]
---
include/efi_firmware_arm_psa.h | 218 +++++++++++
include/efi_loader.h | 1 +
lib/efi_loader/Kconfig | 9 +
lib/efi_loader/Makefile | 1 +
lib/efi_loader/efi_capsule.c | 8 +
lib/efi_loader/efi_firmware.c | 134 +++++++
lib/efi_loader/efi_firmware_arm_psa.c | 520 ++++++++++++++++++++++++++
7 files changed, 891 insertions(+)
create mode 100644 include/efi_firmware_arm_psa.h
create mode 100644 lib/efi_loader/efi_firmware_arm_psa.c
diff --git a/include/efi_firmware_arm_psa.h b/include/efi_firmware_arm_psa.h
new file mode 100644
index 0000000000..82f932066c
--- /dev/null
+++ b/include/efi_firmware_arm_psa.h
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 Arm Limited
+ */
+
+#ifndef _EFI_FIRMWARE_ARM_PSA_H
+#define _EFI_FIRMWARE_ARM_PSA_H
+
+#include <efi_loader.h>
+#include <mm_communication.h>
+#include <stdint.h>
+
+#define PSA_FWU_DIRECTORY_UUID \
+ EFI_GUID(0xdeee58d9, 0x5147, 0x4ad3, \
+ 0xa2, 0x90, 0x77, 0x66, 0x6e, 0x23, 0x41, 0xa5)
+
+#define PSA_FWU_SP_UUID \
+ EFI_GUID(0x6823a838, 0x1b06, 0x470e, \
+ 0x97, 0x74, 0x0c, 0xce, 0x8b, 0xfb, 0x53, 0xfd)
+
+#define FFA_FWU_SP_UUID \
+ {0x68, 0x23, 0xa8, 0x38, 0x1b, 0x06, 0x47, \
+ 0x0e, 0x97, 0x74, 0x0c, 0xce, 0x8b, 0xfb, 0x53, 0xfd}
+
+#define FWU_DISCOVER 0
+#define FWU_BEGIN_STAGING 1
+#define FWU_END_STAGING 2
+#define FWU_CANCEL_STAGING 3
+#define FWU_OPEN 4
+#define FWU_WRITE_STREAM 5
+#define FWU_READ_STREAM 6
+#define FWU_COMMIT 7
+#define FWU_ACCEPT_IMAGE 9
+#define FWU_SELECT_PREVIOUS 10
+
+#define FWU_SUCCESS 0
+#define FWU_UNKNOWN ((int32_t)-1)
+#define FWU_BUSY ((int32_t)-2)
+#define FWU_OUT_OF_BOUNDS ((int32_t)-3)
+#define FWU_AUTH_FAIL ((int32_t)-4)
+#define FWU_NO_PERMISSION ((int32_t)-5)
+#define FWU_DENIED ((int32_t)-6)
+#define FWU_RESUME ((int32_t)-7)
+
+#define MAX_IMAGES 5
+
+typedef int32_t fwu_status_t;
+
+struct fwu_image_info_entry {
+ efi_guid_t image_guid;
+ uint32_t client_permissions;
+ uint32_t img_max_size;
+ uint32_t lowest_acceptable_version;
+ uint32_t img_version;
+ uint32_t accepted;
+ uint32_t reserved;
+}__packed;
+
+struct fwu_image_directory {
+ uint32_t directory_version;
+ uint32_t num_images;
+ uint32_t active_index;
+ uint32_t boot_index;
+ struct fwu_image_info_entry entries[MAX_IMAGES];
+}__packed;
+
+int __efi_runtime arm_psa_get_image_info(
+ efi_uintn_t *image_info_size,
+ struct efi_firmware_image_descriptor *image_info,
+ u32 *descriptor_version,
+ u8 *descriptor_count,
+ efi_uintn_t *descriptor_size,
+ u32 *package_version,
+ u16 **package_version_name
+);
+
+int __efi_runtime arm_psa_update(
+ const void *image,
+ u8 image_index,
+ efi_uintn_t image_size
+);
+
+struct mm_fwu_discover_arg {
+ uint32_t func_id;
+}__packed;
+
+struct mm_fwu_discover_ret {
+ uint32_t status;
+ uint8_t version_major;
+ uint8_t version_minor;
+ uint16_t num_func;
+ uint8_t function_presence[];
+}__packed;
+
+struct mm_fwu_begin_staging_arg {
+ uint32_t func_id;
+}__packed;
+
+struct mm_fwu_begin_staging_ret {
+ uint32_t status;
+}__packed;
+
+struct mm_fwu_end_staging_arg {
+ uint32_t func_id;
+}__packed;
+
+struct mm_fwu_end_staging_ret {
+ uint32_t status;
+}__packed;
+
+struct mm_fwu_cancel_staging_arg {
+ uint32_t func_id;
+}__packed;
+
+struct mm_fwu_cancel_staging_ret {
+ uint32_t status;
+}__packed;
+
+struct mm_fwu_open_arg {
+ uint32_t func_id;
+ efi_guid_t image_guid;
+}__packed;
+
+struct mm_fwu_open_ret {
+ uint32_t status;
+ uint32_t handle;
+}__packed;
+
+struct mm_fwu_write_stream_arg {
+ uint32_t func_id;
+ uint32_t handle;
+ uint32_t data_len;
+ uint8_t payload[];
+}__packed;
+
+struct mm_fwu_write_stream_ret {
+ uint32_t status;
+};
+
+struct mm_fwu_read_stream_arg {
+ uint32_t func_id;
+ uint32_t handle;
+}__packed;
+
+struct mm_fwu_read_stream_ret {
+ uint32_t status;
+ uint32_t read_bytes;
+ uint32_t total_bytes;
+ uint8_t payload[];
+}__packed;
+
+struct mm_fwu_commit_arg {
+ uint32_t func_id;
+ uint32_t handle;
+ uint32_t acceptance_req;
+ uint32_t max_atomic_len;
+}__packed;
+
+struct mm_fwu_commit_ret {
+ uint32_t status;
+ uint32_t progress;
+ uint32_t total_work;
+}__packed;
+
+struct mm_fwu_accept_arg {
+ uint32_t func_id;
+ uint32_t reserved;
+ efi_guid_t image_type_uuid;
+}__packed;
+
+struct mm_fwu_accept_ret {
+ uint32_t status;
+};
+
+struct mm_fwu_select_previous_arg {
+ uint32_t func_id;
+}__packed;
+
+struct mm_fwu_select_previous_ret {
+ uint32_t status;
+}__packed;
+
+inline static void *get_fwu_hdr(struct efi_mm_communicate_header *mm_hdr)
+{
+ const efi_guid_t fwu_sp_guid = PSA_FWU_SP_UUID;
+ guidcpy(&mm_hdr->header_guid, &fwu_sp_guid);
+ return mm_hdr->data;
+}
+
+#define GET_HDR(name) \
+static inline struct mm_fwu_##name * \
+get_fwu_##name (struct efi_mm_communicate_header *mm_hdr) \
+{ \
+ return (struct mm_fwu_##name *)get_fwu_hdr(mm_hdr); \
+} \
+
+GET_HDR(discover_arg)
+GET_HDR(discover_ret)
+GET_HDR(begin_staging_arg)
+GET_HDR(begin_staging_ret)
+GET_HDR(end_staging_arg)
+GET_HDR(end_staging_ret)
+GET_HDR(cancel_staging_arg)
+GET_HDR(cancel_staging_ret)
+GET_HDR(open_arg)
+GET_HDR(open_ret)
+GET_HDR(write_stream_arg)
+GET_HDR(write_stream_ret)
+GET_HDR(read_stream_arg)
+GET_HDR(read_stream_ret)
+GET_HDR(commit_arg)
+GET_HDR(commit_ret)
+GET_HDR(accept_arg)
+GET_HDR(accept_ret)
+GET_HDR(select_previous_arg)
+GET_HDR(select_previous_ret)
+
+#endif /* _EFI_FIRMWARE_ARM_PSA_H */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index af36639ec6..7327c87497 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -961,6 +961,7 @@ u16 *efi_create_indexed_name(u16 *buffer, size_t buffer_size, const char *name,
extern const struct efi_firmware_management_protocol efi_fmp_fit;
extern const struct efi_firmware_management_protocol efi_fmp_raw;
+extern const struct efi_firmware_management_protocol efi_fmp_arm_psa;
/* Capsule update */
efi_status_t EFIAPI efi_update_capsule(
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e5e35fe51f..f99d436f16 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -168,6 +168,15 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT
Select this option if you want to enable capsule-based
firmware update using Firmware Management Protocol.
+config EFI_CAPSULE_FIRMWARE_ARM_PSA
+ bool "FMP driver for ARM PSA FWU specification"
+ depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
+ select EFI_CAPSULE_FIRMWARE
+ help
+ Select this option if you want to enable firmware management protocol
+ driver that supports the ARM PSA firmware update specification as
+ mentioned in https://developer.arm.com/documentation/den0118/a/
+
config EFI_CAPSULE_FIRMWARE_FIT
bool "FMP driver for FIT images"
depends on FIT
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 034d26cf01..f986ac6417 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -38,6 +38,7 @@ obj-y += efi_boottime.o
obj-y += efi_helper.o
obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
+obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA) += efi_firmware_arm_psa.o
obj-y += efi_console.o
obj-y += efi_device_path.o
obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index f00440163d..3154fc51d3 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -1041,6 +1041,14 @@ efi_status_t __weak efi_load_capsule_drivers(void)
&efi_fmp_raw, NULL));
}
+ if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA)) {
+ handle = NULL;
+ ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
+ &handle,
+ &efi_guid_firmware_management_protocol,
+ &efi_fmp_arm_psa, NULL));
+ }
+
return ret;
}
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index a5ff32f121..3356559af8 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <charset.h>
#include <dfu.h>
+#include <efi_firmware_arm_psa.h>
#include <efi_loader.h>
#include <image.h>
#include <signatures.h>
@@ -478,3 +479,136 @@ const struct efi_firmware_management_protocol efi_fmp_raw = {
.set_package_info = efi_firmware_set_package_info_unsupported,
};
#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */
+
+#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA
+/*
+ * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
+ * method that supports the arm psa firmware update specification.
+ */
+
+/**
+ * efi_firmware_arm_psa_get_image_info - return information about the
+ * current firmware image
+ * @this: Protocol instance
+ * @image_info_size: Size of @image_info
+ * @image_info: Image information
+ * @descriptor_version: Pointer to version number
+ * @descriptor_count: Pointer to number of descriptors
+ * @descriptor_size: Pointer to descriptor size
+ * package_version: Package version
+ * package_version_name: Package version's name
+ *
+ * Return information bout the current firmware image in @image_info.
+ * @image_info will consist of a number of descriptors.
+ *
+ * Return status code
+ */
+
+static
+efi_status_t EFIAPI efi_firmware_arm_psa_get_image_info(
+ struct efi_firmware_management_protocol *this,
+ efi_uintn_t *image_info_size,
+ struct efi_firmware_image_descriptor *image_info,
+ u32 *descriptor_version,
+ u8 *descriptor_count,
+ efi_uintn_t *descriptor_size,
+ u32 *package_version,
+ u16 **package_version_name)
+{
+ int ret;
+
+ EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
+ image_info_size, image_info,
+ descriptor_version, descriptor_count, descriptor_size,
+ package_version, package_version_name);
+
+ if (!image_info_size)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ if (*image_info_size &&
+ (!image_info || !descriptor_version || !descriptor_count ||
+ !descriptor_size || !package_version || !package_version_name))
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ ret = arm_psa_get_image_info(image_info_size, image_info,
+ descriptor_version, descriptor_count,
+ descriptor_size,
+ package_version, package_version_name);
+
+ if (ret) {
+ if (ret == -ENOMEM)
+ return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+ else
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+ }
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+/**
+ * efi_firmware_arm_psa_set_image - update the firmware image
+ * @this: Protocol instance
+ * @image_index: Image index number
+ * @image: New image
+ * @image_size: Size of new image
+ * @vendor_code: Vendor-specific update policy
+ * @progress: Function to report the progress of update
+ * @abort_reason: Pointer to string of abort reason
+ *
+ * Update the firmware to new image, following the arm psa firmware
+ * update specification.
+ * @vendor_code, @progress and @abort_reason are not supported.
+ *
+ * Return: status code
+ */
+static
+efi_status_t EFIAPI efi_firmware_arm_psa_set_image(
+ struct efi_firmware_management_protocol *this,
+ u8 image_index,
+ const void *image,
+ efi_uintn_t image_size,
+ const void *vendor_code,
+ efi_status_t (*progress)(efi_uintn_t completion),
+ u16 **abort_reason)
+{
+ u32 fmp_hdr_signature;
+ const struct fmp_payload_header *header;
+
+ EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image,
+ image_size, vendor_code, progress, abort_reason);
+
+ if (!image)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+ /* TODO: capsule authentication */
+
+ fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
+ header = (void *)image;
+
+ if (!memcmp(&header->signature, &fmp_hdr_signature,
+ sizeof(fmp_hdr_signature))) {
+ /*
+ * When building the capsule with the scripts in
+ * edk2, a FMP header is inserted above the capsule
+ * payload. Compensate for this header to get the
+ * actual payload that is to be updated.
+ */
+ image = (unsigned char *)image + header->header_size;
+ image_size -= header->header_size;
+ }
+
+ if (arm_psa_update(image, image_index, image_size))
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
+const struct efi_firmware_management_protocol efi_fmp_arm_psa = {
+ .get_image_info = efi_firmware_arm_psa_get_image_info,
+ .get_image = efi_firmware_get_image_unsupported,
+ .set_image = efi_firmware_arm_psa_set_image,
+ .check_image = efi_firmware_check_image_unsupported,
+ .get_package_info = efi_firmware_get_package_info_unsupported,
+ .set_package_info = efi_firmware_set_package_info_unsupported,
+};
+#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA */
diff --git a/lib/efi_loader/efi_firmware_arm_psa.c b/lib/efi_loader/efi_firmware_arm_psa.c
new file mode 100644
index 0000000000..ab575f0124
--- /dev/null
+++ b/lib/efi_loader/efi_firmware_arm_psa.c
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 Arm Limited
+ */
+
+#include <arm_ffa_helper.h>
+#include <configs/total_compute.h>
+#include <efi_firmware_arm_psa.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <mm_communication.h>
+
+/* MM return codes */
+#define MM_SUCCESS 0
+
+#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 0xC4000061
+#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
+
+__efi_runtime_data static u16 mm_sp_id;
+__efi_runtime_data static int fwu_initialized = 0;
+__efi_runtime_data struct fwu_image_directory cached_image_directory;
+__efi_runtime_data struct efi_mm_communicate_header *mm_hdr;
+__efi_runtime_data void *mm_comm_buf;
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_discover_mm_sp_id(void)
+{
+ struct ffa_interface_data func_data = {0};
+ u32 count = 0;
+ int ret;
+ struct ffa_partition_info *parts_info;
+ static union ffa_partition_uuid fwu_sp_uuid = {.bytes = FFA_FWU_SP_UUID};
+
+ /*
+ * get from the driver the count of the SPs matching the UUID
+ */
+ func_data.data0_size = sizeof(fwu_sp_uuid);
+ func_data.data0 = &fwu_sp_uuid;
+ func_data.data1_size = sizeof(count);
+ func_data.data1 = &count;
+
+ ret = ffa_helper_get_partitions_info(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+ return ret;
+ }
+
+ if (!count) {
+ log_info("EFI: No MM partition found\n");
+ return ret;
+ }
+
+ /*
+ * pre-allocate a buffer to be filled by the driver
+ * with ffa_partition_info structs
+ */
+ parts_info = calloc(count, sizeof(struct ffa_partition_info));
+ if (!parts_info)
+ return -EINVAL;
+
+ log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+ func_data.data1_size = count * sizeof(struct ffa_partition_info);
+ func_data.data1 = parts_info;
+
+ /*
+ * ask the driver to fill the
+ * buffer with the SPs info
+ */
+ ret = ffa_helper_get_partitions_info(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+ free(parts_info);
+ return ret;
+ }
+
+ /*
+ * MM SPs found , use the first one
+ */
+
+ mm_sp_id = parts_info[0].id;
+
+ log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+ free(parts_info);
+
+ return 0;
+}
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_notify_mm_sp(void)
+{
+ struct ffa_interface_data func_data = {0};
+ struct ffa_send_direct_data msg = {0};
+ int ret;
+ u32 sp_event_complete;
+ int sp_event_ret;
+
+ func_data.data0_size = sizeof(mm_sp_id);
+ func_data.data0 = &mm_sp_id;
+
+ msg.a3 = FFA_SHARED_MM_BUFFER_ADDR;
+ msg.a4 = FFA_SHARED_MM_BUFFER_SIZE;
+ func_data.data1_size = sizeof(msg);
+ func_data.data1 = &msg;
+
+ ret = ffa_helper_msg_send_direct_req(&func_data);
+ if (ret != FFA_ERR_STAT_SUCCESS) {
+ log_err("EFI: Failure to notify the MM SP , FF-A error (%d)\n", ret);
+ return ret;
+ }
+
+ sp_event_complete = msg.a3;
+ sp_event_ret = (int)msg.a4;
+
+ if (sp_event_complete == ARM_SVC_ID_SP_EVENT_COMPLETE && sp_event_ret == MM_SUCCESS)
+ return 0;
+
+ log_err("EFI: Failure to notify the MM SP (0x%x , %d)\n",
+ sp_event_complete,
+ sp_event_ret);
+
+ return -EACCES;
+}
+
+static fwu_status_t __efi_runtime fwu_discover(void)
+{
+ int ret;
+ struct mm_fwu_discover_arg *discover_arg = get_fwu_discover_arg(mm_hdr);
+ struct mm_fwu_discover_ret *discover_ret = get_fwu_discover_ret(mm_hdr);
+
+ discover_arg->func_id = FWU_DISCOVER;
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_discover_arg);
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ if (discover_ret->version_major != 1) {
+ log_err("FWU: Unsupported Update Agent version\n");
+ return -EINVAL;
+ }
+ /* TODO: check other parameters as well */
+
+ return discover_ret->status;
+}
+
+static fwu_status_t __efi_runtime fwu_begin_staging(void)
+{
+ int ret;
+ struct mm_fwu_begin_staging_arg *begin_staging_arg = get_fwu_begin_staging_arg(mm_hdr);
+ struct mm_fwu_begin_staging_ret *begin_staging_ret = get_fwu_begin_staging_ret(mm_hdr);
+
+ begin_staging_arg->func_id = FWU_BEGIN_STAGING;
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_begin_staging_arg);
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ return begin_staging_ret->status;
+}
+
+static fwu_status_t __efi_runtime fwu_end_staging(void)
+{
+ int ret;
+ struct mm_fwu_end_staging_arg *end_staging_arg = get_fwu_end_staging_arg(mm_hdr);
+ struct mm_fwu_end_staging_ret *end_staging_ret = get_fwu_end_staging_ret(mm_hdr);
+
+ end_staging_arg->func_id = FWU_END_STAGING;
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_end_staging_arg);
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ return end_staging_ret->status;
+}
+
+static fwu_status_t __efi_runtime fwu_cancel_staging(void)
+{
+ int ret;
+ struct mm_fwu_cancel_staging_arg *cancel_staging_arg = get_fwu_cancel_staging_arg(mm_hdr);
+ struct mm_fwu_cancel_staging_ret *cancel_staging_ret = get_fwu_cancel_staging_ret(mm_hdr);
+
+ cancel_staging_arg->func_id = FWU_CANCEL_STAGING;
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_cancel_staging_arg);
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ return cancel_staging_ret->status;
+}
+
+static fwu_status_t __efi_runtime fwu_open(const efi_guid_t *img_uuid, uint32_t *handle)
+{
+ int ret;
+ struct mm_fwu_open_arg *open_hdr = get_fwu_open_arg(mm_hdr);
+ struct mm_fwu_open_ret *open_ret = get_fwu_open_ret(mm_hdr);
+
+ open_hdr->func_id = FWU_OPEN;
+ guidcpy(&open_hdr->image_guid, img_uuid);
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_open_arg);
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ *handle = open_ret->handle;
+
+ return open_ret->status;
+}
+
+static fwu_status_t __efi_runtime fwu_read_stream(uint32_t handle, uint8_t *buffer, uint32_t buffer_size)
+{
+ int ret;
+ struct mm_fwu_read_stream_arg *read_stream_hdr = get_fwu_read_stream_arg(mm_hdr);
+ struct mm_fwu_read_stream_ret *read_stream_ret = get_fwu_read_stream_ret(mm_hdr);
+ uint32_t payload_size = FFA_SHARED_MM_BUFFER_SIZE - sizeof(struct mm_fwu_read_stream_ret)
+ - sizeof(struct efi_mm_communicate_header);
+ uint32_t read_offset = 0, read_size, total_size;
+
+ do {
+ read_stream_hdr->func_id = FWU_READ_STREAM;
+ read_stream_hdr->handle = handle;
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_read_stream_arg);
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ if (read_stream_ret->status)
+ return read_stream_ret->status;
+
+ read_size = read_stream_ret->read_bytes;
+ total_size = read_stream_ret->total_bytes;
+
+ log_info("FWU: read bytes / total bytes : %d/%d\n", read_size, total_size);
+
+ if ((read_size <= payload_size) && (read_offset + read_size <= buffer_size))
+ memcpy(buffer + read_offset, read_stream_ret->payload, read_size);
+ else
+ return -EINVAL;
+
+ read_offset += read_size;
+
+ if (read_offset > total_size)
+ return -EINVAL;
+ } while (total_size != read_offset);
+
+ return read_stream_ret->status;
+}
+
+static fwu_status_t __efi_runtime fwu_write_stream(uint32_t handle, const uint8_t *buffer, uint32_t remaining_size)
+{
+ int ret;
+ struct mm_fwu_write_stream_arg *write_stream_arg = get_fwu_write_stream_arg(mm_hdr);
+ struct mm_fwu_write_stream_ret *write_stream_ret = get_fwu_write_stream_ret(mm_hdr);
+ uint32_t write_size;
+ uint32_t payload_size = FFA_SHARED_MM_BUFFER_SIZE - sizeof(struct mm_fwu_write_stream_arg)
+ - sizeof(struct efi_mm_communicate_header);
+
+ while (remaining_size) {
+ write_size = (remaining_size < payload_size) ? remaining_size : payload_size;
+ write_stream_arg->func_id = FWU_WRITE_STREAM;
+ write_stream_arg->handle = handle;
+ write_stream_arg->data_len = write_size;
+ memcpy(write_stream_arg->payload, buffer, write_size);
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_write_stream_arg) + write_size;
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ if(write_stream_ret->status)
+ return write_stream_ret->status;
+
+ remaining_size -= write_size;
+ buffer += write_size;
+
+ log_info("FWU: write size = %d, remaining size = %d\n",
+ write_size, remaining_size);
+ }
+
+ return write_stream_ret->status;
+}
+
+static fwu_status_t __efi_runtime fwu_commit(uint32_t handle, bool client_accept)
+{
+ int ret;
+ struct mm_fwu_commit_arg *commit_arg = get_fwu_commit_arg(mm_hdr);
+ struct mm_fwu_commit_ret *commit_ret = get_fwu_commit_ret(mm_hdr);
+
+ do {
+ commit_arg->func_id = FWU_COMMIT;
+ commit_arg->handle = handle;
+ commit_arg->acceptance_req = client_accept;
+ commit_arg->max_atomic_len = 0;
+
+ mm_hdr->message_len = sizeof(struct mm_fwu_commit_arg);
+
+ ret = ffa_notify_mm_sp();
+ if (ret)
+ return ret;
+
+ log_info("FWU: commit progress %d/%d (work/total_work)\n",
+ commit_ret->progress, commit_ret->total_work);
+
+ } while(commit_ret->status==FWU_RESUME);
+
+ return commit_ret->status;
+}
+
+int __efi_runtime arm_psa_update(
+ const void *image,
+ u8 image_index,
+ efi_uintn_t image_size
+)
+{
+ int ret = 0;
+ uint32_t handle;
+
+ if(image_index >= cached_image_directory.num_images)
+ return -EINVAL;
+
+ ret = fwu_begin_staging();
+ if (ret) {
+ log_err("FWU: begin staging failed, ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = fwu_open(&cached_image_directory.entries[image_index].image_guid, &handle);
+ if (ret) {
+ log_err("FWU: firmware image open failed, ret = %d\n", ret);
+ goto cancel_staging;
+ }
+
+ ret = fwu_write_stream(handle, (uint8_t *)image, image_size);
+ if (ret) {
+ log_err("FWU: write stream failed, ret = %d\n", ret);
+ goto cancel_staging;
+ }
+
+ /* TODO: implement client driven image acceptance */
+ ret = fwu_commit(handle, 0);
+ if (ret) {
+ log_err("FWU: commit failed, ret = %d\n", ret);
+ goto cancel_staging;
+ }
+
+ ret = fwu_end_staging();
+ if (ret) {
+ log_err("FWU: end staging failed, ret = %d\n", ret);
+ goto cancel_staging;
+ }
+
+ log_info("successfully updated the image at index %d\n", image_index);
+ return ret;
+
+cancel_staging:
+ if (fwu_cancel_staging())
+ log_err("FWU: cancel staging failed, ret = %d\n", ret);
+
+ return ret;
+}
+
+static int __efi_runtime read_image_directory(void)
+{
+ int ret;
+ uint32_t handle;
+
+ const efi_guid_t fwu_directory_uuid = PSA_FWU_DIRECTORY_UUID;
+
+ ret = fwu_open(&fwu_directory_uuid, &handle);
+ if (ret) {
+ log_err("FWU: open image directory failed, ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = fwu_read_stream(handle, (uint8_t *)&cached_image_directory, sizeof(cached_image_directory));
+ if (ret) {
+ log_err("FWU: read stream failed, ret = %d\n", ret);
+ return ret;
+ }
+
+ if(cached_image_directory.num_images > MAX_IMAGES) {
+ log_err("FWU: image limit exceeded.\n");
+ log_err("FWU: number of images present: %d, max number of images supported: %d\n",
+ cached_image_directory.num_images, MAX_IMAGES);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int update_agent_init(void)
+{
+ int ret;
+
+ ret = ffa_discover_mm_sp_id();
+ if (ret) {
+ log_err("FWU: discover update agent failed, ret = %d\n", ret);
+ return ret;
+ }
+
+ mm_comm_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+ mm_hdr = (struct efi_mm_communicate_header *)mm_comm_buf;
+
+ ret = fwu_discover();
+ if (ret) {
+ log_err("FWU: discover failed, ret = %d\n", ret);
+ goto out;
+ }
+
+ ret = read_image_directory();
+ if (ret) {
+ log_err("FWU: reading image directory failed, ret = %d\n", ret);
+ goto out;
+ }
+
+ fwu_initialized = 1;
+ return ret;
+out:
+ unmap_sysmem(mm_comm_buf);
+ return ret;
+}
+
+int __efi_runtime arm_psa_get_image_info(
+ efi_uintn_t *image_info_size,
+ struct efi_firmware_image_descriptor *image_info,
+ u32 *descriptor_version,
+ u8 *descriptor_count,
+ efi_uintn_t *descriptor_size,
+ u32 *package_version,
+ u16 **package_version_name)
+{
+ int ret = 0;
+ int required_image_info_size;
+
+ if (!fwu_initialized) {
+ ret = update_agent_init();
+ if (ret) {
+ log_err("update agent init failed, ret = %d\n", ret);
+ return ret;
+ }
+ }
+
+ required_image_info_size = cached_image_directory.num_images *
+ sizeof(struct efi_firmware_image_descriptor);
+
+ if (*image_info_size < required_image_info_size) {
+ *image_info_size = required_image_info_size;
+ return -ENOMEM;
+ }
+
+ *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+ *descriptor_count = cached_image_directory.num_images;
+ *descriptor_size = required_image_info_size;
+ *package_version = 0xffffffff; /* not supported */
+ *package_version_name = NULL; /* not supported */
+
+ for (int i = 0; i < cached_image_directory.num_images; i++) {
+ image_info[i].image_index = i+1;
+ guidcpy(&image_info[i].image_type_id, &cached_image_directory.entries[i].image_guid);
+ image_info[i].image_id = i;
+ image_info[i].image_id_name = NULL; /* not supported */
+ image_info[i].version = cached_image_directory.entries[i].img_version;
+ image_info[i].version_name = NULL; /* not supported */
+ image_info[i].size = cached_image_directory.entries[i].img_max_size;
+
+ image_info[i].attributes_supported =
+ IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
+ image_info[i].attributes_setting =
+ IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+
+ /* Check if the capsule authentication is enabled */
+ if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
+ image_info[i].attributes_setting |=
+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
+
+ image_info[i].lowest_supported_image_version =
+ cached_image_directory.entries[i].lowest_acceptable_version;
+ image_info[i].last_attempt_version = 0;
+ image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
+ image_info[i].hardware_instance = 1;
+ image_info[i].dependencies = NULL; /* not supported */
+ }
+
+ return ret;
+}
--
2.34.1
@@ -1,70 +0,0 @@
From 2ab887402b9e22842d07e5f2fe1ac54518555af5 Mon Sep 17 00:00:00 2001
From: Davidson K <davidson.kumaresan@arm.com>
Date: Mon, 6 Jun 2022 13:24:42 +0530
Subject: [PATCH 6/7] arm: total_compute: enable capsule update
It includes:
* Enabling runtime capsule update
* Enabling efidebug command line tool
* Enabling the FMP driver that supports ARM PSA firmware update specification
* Predefining the carved out memory to be used for MM communication
* Enabling FF-A transport driver and adding an entry in dts
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: I6d6c70c6fc386d6c40def800a7417c1ce4b8acf5
Upstream-Status: Pending [Not submitted to upstream yet]
---
arch/arm/dts/total_compute.dts | 7 +++++++
configs/total_compute_defconfig | 5 +++++
include/configs/total_compute.h | 4 ++++
3 files changed, 16 insertions(+)
diff --git a/arch/arm/dts/total_compute.dts b/arch/arm/dts/total_compute.dts
index 96edacda0b..9b2cbfb452 100644
--- a/arch/arm/dts/total_compute.dts
+++ b/arch/arm/dts/total_compute.dts
@@ -45,8 +45,15 @@
clock-frequency = <24000000>;
clock-output-names = "bp:clock24mhz";
};
+
psci {
compatible = "arm,psci-1.0", "arm,psci-0.2";
method = "smc";
};
+
+ arm_ffa {
+ compatible = "arm,ffa";
+ method = "smc";
+ status = "okay";
+ };
};
diff --git a/configs/total_compute_defconfig b/configs/total_compute_defconfig
index 6a375543cd..531ce41cd3 100644
--- a/configs/total_compute_defconfig
+++ b/configs/total_compute_defconfig
@@ -52,3 +52,8 @@ CONFIG_SYS_FLASH_PROTECTION=y
CONFIG_SYS_FLASH_CFI=y
CONFIG_LIBAVB=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_CMD_EFIDEBUG=y
+CONFIG_EFI_CAPSULE_FIRMWARE_ARM_PSA=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
diff --git a/include/configs/total_compute.h b/include/configs/total_compute.h
index 62bdb4f6a3..4b00f47ec6 100644
--- a/include/configs/total_compute.h
+++ b/include/configs/total_compute.h
@@ -59,4 +59,8 @@
#define CONFIG_SYS_FLASH_EMPTY_INFO /* flinfo indicates empty blocks */
#define FLASH_MAX_SECTOR_SIZE 0x00040000
+/* Shared buffer used for communication between u-boot and the FWU SP */
+#define FFA_SHARED_MM_BUFFER_SIZE 4 * 1024 * 1024 /* 4 MB */
+#define FFA_SHARED_MM_BUFFER_ADDR (0xFCA00000)
+
#endif /* __TOTAL_COMPUTE_H */
--
2.34.1
@@ -1,51 +0,0 @@
From 47be0456ea1760837d2de857e57842e595e9ea5e Mon Sep 17 00:00:00 2001
From: Davidson K <davidson.kumaresan@arm.com>
Date: Mon, 27 Jun 2022 14:11:27 +0530
Subject: [PATCH 7/7] arm_ffa: unmap rxtx buffer before exiting u-boot
The linux kernel ffa driver will be used after the kernel boots. It
will try to map its own rxtx buffer. But there can be only one rxtx
buffer mapped from the non secure world. Since the rxtx buffer of
the u-boot is no longer used and we have to map the rxtx buffer of
the linux kernel, the rxtx buffer of the u-boot should be unmapped.
This will not be needed after the efi runtime services are enabled
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: I9deb6283d81f791185aa0a32d205b394d6d91f76
Upstream-Status: Pending [Not submitted to upstream yet]
---
drivers/arm-ffa/core.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
index 98e2d2fa17..0c619439cb 100644
--- a/drivers/arm-ffa/core.c
+++ b/drivers/arm-ffa/core.c
@@ -1470,6 +1470,16 @@ static const struct udevice_id ffa_match_id[] = {
{},
};
+/**
+ * Unmap the rxtx buffer before exiting u-boot
+ * This avoids conflicts with the linux kernel ffa driver
+ */
+
+static int ffa_remove(struct udevice *dev)
+{
+ return ffa_unmap_rxtx_buffers();
+}
+
/**
* Declaring the arm_ffa driver under UCLASS_FFA
*/
@@ -1481,4 +1491,6 @@ U_BOOT_DRIVER(arm_ffa) = {
.of_to_plat = ffa_of_to_plat,
.probe = ffa_probe,
.plat_auto = sizeof(struct ffa_pdata),
+ .remove = ffa_remove,
+ .flags = DM_FLAG_OS_PREPARE,
};
--
2.34.1
@@ -1,3 +1,3 @@
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyAMA0 debug user_debug=31 earlycon=pl011,0x7ff80000 loglevel=9 androidboot.hardware=total_compute androidboot.boot_devices=1c050000.mmci androidboot.selinux=permissive allow_mismatched_32bit_el0"
CONFIG_BOOTARGS="console=ttyAMA0 debug earlycon=pl011,0x7ff80000"
CONFIG_BOOTDELAY=0
@@ -97,11 +97,4 @@ SRC_URI:append:juno = " file://0001-configs-vexpress-modify-to-boot-compressed-i
#
SRC_URI:append:tc = " \
file://bootargs.cfg \
file://0001-arm-total_compute-update-secure-dram-size.patch \
file://0002-arm_ffa-introducing-Arm-FF-A-low-level-driver.patch \
file://0003-arm-total_compute-enable-psci.patch \
file://0004-arm_ffa-rxtx_map-should-use-64-bit-calls.patch \
file://0005-efi_firmware-add-new-fmp-driver-that-supports-arm-fw.patch \
file://0006-arm-total_compute-enable-capsule-update.patch \
file://0007-arm_ffa-unmap-rxtx-buffer-before-exiting-u-boot.patch \
"
@@ -1,26 +0,0 @@
HOMEPAGE = "http://www.denx.de/wiki/U-Boot/WebHome"
DESCRIPTION = "U-Boot, a boot loader for Embedded boards based on PowerPC, \
ARM, MIPS and several other processors, which can be installed in a boot \
ROM and used to initialize and test the hardware or to download and run \
application code."
SECTION = "bootloaders"
DEPENDS += "flex-native bison-native"
LICENSE = "GPL-2.0-or-later"
LIC_FILES_CHKSUM = "file://Licenses/README;md5=5a7450c57ffe5ae63fd732446b988025"
PE = "1"
# We use the revision in order to avoid having to fetch it from the
# repo during parse
SRCREV = "e4b6ebd3de982ae7185dbf689a030e73fd06e0d2"
SRC_URI = "git://git.denx.de/u-boot.git;branch=master \
"
S = "${WORKDIR}/git"
B = "${WORKDIR}/build"
do_configure[cleandirs] = "${B}"
require recipes-bsp/u-boot/u-boot.inc
DEPENDS += "bc-native dtc-native gnutls-native"
@@ -1 +0,0 @@
kconf non-hardware tc/autofdo.cfg
@@ -1,13 +0,0 @@
kconf hardware tc/base.cfg
kconf non-hardware tc/dhcp.cfg
kconf non-hardware tc/devtmpfs.cfg
kconf non-hardware tc/gralloc.cfg
kconf non-hardware tc/mali.cfg
kconf non-hardware tc/ffa.cfg
kconf non-hardware tc/optee.cfg
kconf non-hardware tc/virtio.cfg
kconf non-hardware tc/autofdo.cfg
kconf non-hardware tc/ci700.cfg
kconf non-hardware tc/trusty.cfg
kconf non-hardware tc/disable_mpam.cfg
kconf non-hardware tc/disable_btf.cfg
@@ -1,3 +0,0 @@
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_SOURCE_ETM4X=y
CONFIG_CORESIGHT_TRBE=y
@@ -1,12 +0,0 @@
CONFIG_ARCH_VEXPRESS=y
CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=y
CONFIG_ARM_SMMU_V3=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_COMMON_CLK_SCMI=y
CONFIG_DRM_HDLCD=y
CONFIG_DRM_KOMEDA=y
CONFIG_DRM_VIRT_ENCODER=y
CONFIG_MMC_ARMMMCI=y
CONFIG_SERIO_AMBAKMI=y
CONFIG_SMC91X=y
@@ -1 +0,0 @@
CONFIG_ARM_CMN=y
@@ -1,3 +0,0 @@
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_VT=y
@@ -1,2 +0,0 @@
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
@@ -1 +0,0 @@
CONFIG_DEBUG_INFO_BTF=n
@@ -1 +0,0 @@
CONFIG_ARM64_MPAM=n
@@ -1 +0,0 @@
CONFIG_ARM_FFA_TRANSPORT=y
@@ -1,2 +0,0 @@
CONFIG_DMABUF_HEAPS_SYSTEM=y
CONFIG_DMABUF_HEAPS_CMA=y
@@ -1 +0,0 @@
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
@@ -1,2 +0,0 @@
CONFIG_TEE=y
CONFIG_OPTEE=y
@@ -1 +0,0 @@
CONFIG_TRUSTY=y
@@ -1,2 +0,0 @@
CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_MMIO=y
@@ -17,7 +17,6 @@ SRC_URI:append:fvp-base = " ${SRC_URI_KMETA}"
SRC_URI:append:fvp-baser-aemv8r64 = " ${SRC_URI_KMETA}"
SRC_URI:append:juno = " ${SRC_URI_KMETA}"
SRC_URI:append:n1sdp = " ${SRC_URI_KMETA}"
SRC_URI:append:tc = " ${SRC_URI_KMETA}"
SRCREV:arm-platforms-kmeta = "6147e82375aa9df8f2a162d42ea6406c79c854c5"
#
@@ -128,54 +127,5 @@ KCONFIG_MODE:sgi575 = "--alldefconfig"
# Total Compute (TC0/TC1) KMACHINE
#
COMPATIBLE_MACHINE:tc = "(tc0|tc1)"
KBUILD_DEFCONFIG:tc = "defconfig"
KCONFIG_MODE:tc = "--alldefconfig"
FILESEXTRAPATHS:prepend:tc := "${ARMBSPFILESPATHS}:${THISDIR}/linux-arm64-ack-5.15/tc:"
SRC_URI:append:tc = " \
file://gki_defconfig \
file://0001-drm-Add-component-aware-simple-encoder.patch \
file://0001-drm-komeda-Fix-handling-of-atomic-commits-in-the-ato.patch \
file://0002-drm-arm-komeda-add-RENDER-capability-to-the-device-n.patch \
file://0003-firmware-arm_ffa-Fix-uuid-argument-passed-to-ffa_par.patch \
file://0004-firmware-arm_ffa-Add-ffa_dev_get_drvdata.patch \
file://0005-firmware-arm_ffa-extern-ffa_bus_type.patch \
file://0006-firmware-arm_ffa-Fix-FFA_MEM_SHARE-and-FFA_MEM_FRAG_.patch \
file://0007-Revert-optee-use-driver-internal-tee_context-for-som.patch \
file://0008-tee-add-sec_world_id-to-struct-tee_shm.patch \
file://0009-optee-simplify-optee_release.patch \
file://0010-optee-refactor-driver-with-internal-callbacks.patch \
file://0011-optee-isolate-smc-abi.patch \
file://0012-optee-add-FF-A-support.patch \
file://0013-optee-smc_abi.c-add-missing-include-linux-mm.h.patch \
file://0014-optee-Fix-spelling-mistake-reclain-reclaim.patch \
file://0015-optee-fix-kfree-NULL-pointer.patch \
file://0016-perf-arm-cmn-Account-for-NUMA-affinity.patch \
file://0017-perf-arm-cmn-Drop-compile-test-restriction.patch \
file://0018-perf-arm-cmn-Refactor-node-ID-handling.patch \
file://0019-perf-arm-cmn-Streamline-node-iteration.patch \
file://0020-perf-arm-cmn-Refactor-DTM-handling.patch \
file://0021-perf-arm-cmn-Optimise-DTM-counter-reads.patch \
file://0022-perf-arm-cmn-Optimise-DTC-counter-accesses.patch \
file://0023-perf-arm-cmn-Move-group-validation-data-off-stack.patch \
file://0024-perf-arm-cmn-Demarcate-CMN-600-specifics.patch \
file://0025-perf-arm-cmn-Support-new-IP-features.patch \
file://0026-perf-arm-cmn-Add-CI-700-Support.patch \
file://0027-ANDROID-trusty-Backport-of-trusty-driver.patch \
file://0028-ANDROID-trusty-Remove-FFA-specific-initilization.patch \
file://0029-ANDROID-trusty-Rename-transfer-memory-function-to-le.patch \
file://0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch \
file://0031-ANDROID-trusty-Modify-device-compatible-string.patch \
file://0032-ANDROID-trusty-Add-transport-descriptor.patch \
file://0033-ANDROID-trusty-Add-trusty-ffa-driver.patch \
file://0034-ANDROID-trusty-ffa-Add-support-for-FFA-memory-operat.patch \
file://0035-ANDROID-trusty-ffa-Enable-FFA-transport-for-both-mem.patch \
file://0036-ANDROID-trusty-Make-trusty-transports-configurable.patch \
file://0037-ANDROID-trusty-log-include-panic_notifier.h.patch \
file://0038-ANDROID-trusty-ipc-fix-VIRTIO_ID_TRUSTY_IPC-ID.patch \
file://0039-gki_config-add-tc-disable_mpam.patch \
file://0040-ANDROID-KVM-arm64-disable-FFA-driver-at-EL2.patch \
file://init_disassemble_info-signature-changes-causes-compile-failures.patch \
file://0041-etherdevice-Adjust-ether_addr-prototypes-to-silence-.patch \
file://0042-mm-page_alloc-fix-building-error-on-Werror-array-com.patch \
"
KERNEL_FEATURES:append:tc = " bsp/arm-platforms/tc.scc"
KERNEL_FEATURES:append:tc1 = " bsp/arm-platforms/tc-autofdo.scc"
@@ -1,367 +0,0 @@
From 5c07d2e7bf1634743249178bf2ca2a06779e6e7a Mon Sep 17 00:00:00 2001
From: Tushar Khandelwal <tushar.khandelwal@arm.com>
Date: Tue, 16 Jun 2020 12:39:06 +0000
Subject: [PATCH 01/40] drm: Add component-aware simple encoder
This is a simple DRM encoder that gets its connector timings information
from a OF subnode in the device tree and exposes that as a "discovered"
panel. It can be used together with component-based DRM drivers in an
emulated environment where no real encoder or connector hardware exists
and the display output is configured outside the kernel.
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Upstream-Status: Backport [https://git.linaro.org/landing-teams/working/arm/kernel-release.git/commit/?h=latest-armlt&id=15283f7be4b1e586702551e85b4caf06531ac2fc]
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ic68cbba7da7d36ee23359ff53bf30eb44cb78661
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/gpu/drm/Kconfig | 11 +
drivers/gpu/drm/Makefile | 2 +
drivers/gpu/drm/drm_virtual_encoder.c | 299 ++++++++++++++++++++++++++
3 files changed, 312 insertions(+)
create mode 100644 drivers/gpu/drm/drm_virtual_encoder.c
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index cea777ae7fb9..2468ec7155ef 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -291,6 +291,17 @@ config DRM_VKMS
If M is selected the module will be called vkms.
+config DRM_VIRT_ENCODER
+ tristate "Virtual OF-based encoder"
+ depends on DRM && OF
+ select VIDEOMODE_HELPERS
+ help
+ Choose this option to get a virtual encoder and its associated
+ connector that will use the device tree to read the display
+ timings information. If M is selected the module will be called
+ drm_vencoder.
+
+
source "drivers/gpu/drm/exynos/Kconfig"
source "drivers/gpu/drm/rockchip/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index ad1112154898..361999b7d063 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -59,6 +59,8 @@ drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
+drm_vencoder-y := drm_virtual_encoder.o
+obj-$(CONFIG_DRM_VIRT_ENCODER) += drm_vencoder.o
obj-$(CONFIG_DRM) += drm.o
obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
diff --git a/drivers/gpu/drm/drm_virtual_encoder.c b/drivers/gpu/drm/drm_virtual_encoder.c
new file mode 100644
index 000000000000..39a902ecfe32
--- /dev/null
+++ b/drivers/gpu/drm/drm_virtual_encoder.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2016 ARM Limited
+ * Author: Liviu Dudau <Liviu.Dudau@arm.com>
+ *
+ * Dummy encoder and connector that use the OF to "discover" the attached
+ * display timings. Can be used in situations where the encoder and connector's
+ * functionality are emulated and no setup steps are needed, or to describe
+ * attached panels for which no driver exists but can be used without
+ * additional hardware setup.
+ *
+ * The encoder also uses the component framework so that it can be a quick
+ * replacement for existing drivers when testing in an emulated environment.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_print.h>
+#include <linux/platform_device.h>
+#include <drm/drm_of.h>
+#include <linux/component.h>
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+struct drm_virt_priv {
+ struct drm_connector connector;
+ struct drm_encoder encoder;
+ struct display_timings *timings;
+};
+
+#define connector_to_drm_virt_priv(x) \
+ container_of(x, struct drm_virt_priv, connector)
+
+#define encoder_to_drm_virt_priv(x) \
+ container_of(x, struct drm_virt_priv, encoder)
+
+static void drm_virtcon_destroy(struct drm_connector *connector)
+{
+ struct drm_virt_priv *conn = connector_to_drm_virt_priv(connector);
+
+ drm_connector_cleanup(connector);
+ display_timings_release(conn->timings);
+}
+
+static enum drm_connector_status
+drm_virtcon_detect(struct drm_connector *connector, bool force)
+{
+ return connector_status_connected;
+}
+
+static const struct drm_connector_funcs drm_virtcon_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .detect = drm_virtcon_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_virtcon_destroy,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int drm_virtcon_get_modes(struct drm_connector *connector)
+{
+ struct drm_virt_priv *conn = connector_to_drm_virt_priv(connector);
+ struct display_timings *timings = conn->timings;
+ int i;
+
+ for (i = 0; i < timings->num_timings; i++) {
+ struct drm_display_mode *mode = drm_mode_create(connector->dev);
+ struct videomode vm;
+
+ if (videomode_from_timings(timings, &vm, i))
+ break;
+
+ drm_display_mode_from_videomode(&vm, mode);
+ mode->type = DRM_MODE_TYPE_DRIVER;
+ if (timings->native_mode == i)
+ mode->type = DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+ }
+
+ return i;
+}
+
+static int drm_virtcon_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ return MODE_OK;
+}
+
+struct drm_encoder *drm_virtcon_best_encoder(struct drm_connector *connector)
+{
+ struct drm_virt_priv *priv = connector_to_drm_virt_priv(connector);
+
+ return &priv->encoder;
+}
+
+struct drm_encoder *
+drm_virtcon_atomic_best_encoder(struct drm_connector *connector,
+ struct drm_atomic_state *state)
+{
+ struct drm_virt_priv *priv = connector_to_drm_virt_priv(connector);
+
+ return &priv->encoder;
+}
+
+static const struct drm_connector_helper_funcs drm_virtcon_helper_funcs = {
+ .get_modes = drm_virtcon_get_modes,
+ .mode_valid = drm_virtcon_mode_valid,
+ .best_encoder = drm_virtcon_best_encoder,
+ .atomic_best_encoder = drm_virtcon_atomic_best_encoder,
+};
+
+static void drm_vencoder_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs drm_vencoder_funcs = {
+ .destroy = drm_vencoder_destroy,
+};
+
+static void drm_vencoder_dpms(struct drm_encoder *encoder, int mode)
+{
+ /* nothing needed */
+}
+
+static bool drm_vencoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ /* nothing needed */
+ return true;
+}
+
+static void drm_vencoder_prepare(struct drm_encoder *encoder)
+{
+ drm_vencoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void drm_vencoder_commit(struct drm_encoder *encoder)
+{
+ drm_vencoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static void drm_vencoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ /* nothing needed */
+}
+
+static const struct drm_encoder_helper_funcs drm_vencoder_helper_funcs = {
+ .dpms = drm_vencoder_dpms,
+ .mode_fixup = drm_vencoder_mode_fixup,
+ .prepare = drm_vencoder_prepare,
+ .commit = drm_vencoder_commit,
+ .mode_set = drm_vencoder_mode_set,
+};
+
+static int drm_vencoder_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_encoder *encoder;
+ struct drm_virt_priv *con;
+ struct drm_connector *connector;
+ struct drm_device *drm = data;
+ u32 crtcs = 0;
+ int ret;
+
+ con = devm_kzalloc(dev, sizeof(*con), GFP_KERNEL);
+ if (!con)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, con);
+ connector = &con->connector;
+ encoder = &con->encoder;
+
+ if (dev->of_node) {
+ struct drm_bridge *bridge;
+ crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+ bridge = of_drm_find_bridge(dev->of_node);
+ if (bridge) {
+ ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+ if (ret) {
+ DRM_ERROR("Failed to initialize bridge\n");
+ return ret;
+ }
+ }
+ con->timings = of_get_display_timings(dev->of_node);
+ if (!con->timings) {
+ dev_err(dev, "failed to get display panel timings\n");
+ return ENXIO;
+ }
+ }
+
+ /* If no CRTCs were found, fall back to the old encoder's behaviour */
+ if (crtcs == 0) {
+ dev_warn(dev, "Falling back to first CRTC\n");
+ crtcs = 1 << 0;
+ }
+
+ encoder->possible_crtcs = crtcs ? crtcs : 1;
+ encoder->possible_clones = 0;
+
+ ret = drm_encoder_init(drm, encoder, &drm_vencoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ if (ret)
+ goto encoder_init_err;
+
+ drm_encoder_helper_add(encoder, &drm_vencoder_helper_funcs);
+
+ /* bogus values, pretend we're a 24" screen for DPI calculations */
+ connector->display_info.width_mm = 519;
+ connector->display_info.height_mm = 324;
+ connector->interlace_allowed = false;
+ connector->doublescan_allowed = false;
+ connector->polled = 0;
+
+ ret = drm_connector_init(drm, connector, &drm_virtcon_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL);
+ if (ret)
+ goto connector_init_err;
+
+ drm_connector_helper_add(connector, &drm_virtcon_helper_funcs);
+
+ drm_connector_register(connector);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret)
+ goto attach_err;
+
+ return ret;
+
+attach_err:
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+connector_init_err:
+ drm_encoder_cleanup(encoder);
+encoder_init_err:
+ display_timings_release(con->timings);
+
+ return ret;
+};
+
+static void drm_vencoder_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_virt_priv *con = dev_get_drvdata(dev);
+
+ drm_connector_unregister(&con->connector);
+ drm_connector_cleanup(&con->connector);
+ drm_encoder_cleanup(&con->encoder);
+ display_timings_release(con->timings);
+}
+
+static const struct component_ops drm_vencoder_ops = {
+ .bind = drm_vencoder_bind,
+ .unbind = drm_vencoder_unbind,
+};
+
+static int drm_vencoder_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &drm_vencoder_ops);
+}
+
+static int drm_vencoder_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &drm_vencoder_ops);
+ return 0;
+}
+
+static const struct of_device_id drm_vencoder_of_match[] = {
+ { .compatible = "drm,virtual-encoder", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, drm_vencoder_of_match);
+
+static struct platform_driver drm_vencoder_driver = {
+ .probe = drm_vencoder_probe,
+ .remove = drm_vencoder_remove,
+ .driver = {
+ .name = "drm_vencoder",
+ .of_match_table = drm_vencoder_of_match,
+ },
+};
+
+module_platform_driver(drm_vencoder_driver);
+
+MODULE_AUTHOR("Liviu Dudau");
+MODULE_DESCRIPTION("Virtual DRM Encoder");
+MODULE_LICENSE("GPL v2");
--
2.34.1
@@ -1,115 +0,0 @@
From 3bfadb22e58bdf7691f80f403dd85794f2b86ad6 Mon Sep 17 00:00:00 2001
From: Liviu Dudau <liviu.dudau@arm.com>
Date: Fri, 8 Jul 2022 16:39:21 +0100
Subject: [PATCH] drm/komeda: Fix handling of atomic commits in the
atomic_commit_tail hook
Komeda driver relies on the generic DRM atomic helper functions to handle
commits. It only implements an atomic_commit_tail hook for the
mode_config_helper_funcs and even that one is pretty close to the generic
implementation with the exception of additional dma_fence signalling.
What the generic helper framework doesn't do is waiting for the actual
hardware to signal that the commit parameters have been written into the
appropriate registers. As we signal CRTC events only on the irq handlers,
we need to flush the configuration and wait for the hardware to respond.
Add the Komeda specific implementation for atomic_commit_hw_done() that
flushes and waits for flip done before calling drm_atomic_helper_commit_hw_done().
The fix was prompted by a patch from Carsten Haitzler where he was trying to
solve the same issue but in a different way that I think can lead to wrong
event signaling to userspace.
Upstream-Status: Backport [https://patchwork.freedesktop.org/patch/msgid/20220722122139.288486-1-liviu.dudau@arm.com]
Reported-by: Carsten Haitzler <carsten.haitzler@arm.com>
Tested-by: Carsten Haitzler <carsten.haitzler@arm.com>
Reviewed-by: Carsten Haitzler <carsten.haitzler@arm.com>
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220722122139.288486-1-liviu.dudau@arm.com
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
Change-Id: I0bd92150120eb929692c1d38c4d1077d38401cdd
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
.../gpu/drm/arm/display/komeda/komeda_crtc.c | 4 ++--
.../gpu/drm/arm/display/komeda/komeda_kms.c | 21 ++++++++++++++++++-
.../gpu/drm/arm/display/komeda/komeda_kms.h | 2 ++
3 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 59172acb9738..292f533d8cf0 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -235,7 +235,7 @@ void komeda_crtc_handle_event(struct komeda_crtc *kcrtc,
crtc->state->event = NULL;
drm_crtc_send_vblank_event(crtc, event);
} else {
- DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n",
+ DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n",
drm_crtc_index(&kcrtc->base));
}
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
@@ -286,7 +286,7 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc,
komeda_crtc_do_flush(crtc, old);
}
-static void
+void
komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
struct completion *input_flip_done)
{
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 8b2be8a9a27d..c434fb43d82c 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -69,6 +69,25 @@ static const struct drm_driver komeda_kms_driver = {
.minor = 1,
};
+static void komeda_kms_atomic_commit_hw_done(struct drm_atomic_state *state)
+{
+ struct drm_device *dev = state->dev;
+ struct komeda_kms_dev *kms = to_kdev(dev);
+ int i;
+
+ for (i = 0; i < kms->n_crtcs; i++) {
+ struct komeda_crtc *kcrtc = &kms->crtcs[i];
+
+ if (kcrtc->base.state->active) {
+ struct completion *flip_done = NULL;
+ if (kcrtc->base.state->event)
+ flip_done = kcrtc->base.state->event->base.completion;
+ komeda_crtc_flush_and_wait_for_flip_done(kcrtc, flip_done);
+ }
+ }
+ drm_atomic_helper_commit_hw_done(state);
+}
+
static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
{
struct drm_device *dev = old_state->dev;
@@ -81,7 +100,7 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
drm_atomic_helper_commit_modeset_enables(dev, old_state);
- drm_atomic_helper_commit_hw_done(old_state);
+ komeda_kms_atomic_commit_hw_done(old_state);
drm_atomic_helper_wait_for_flip_done(dev, old_state);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
index 456f3c435719..bf6e8fba5061 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
@@ -182,6 +182,8 @@ void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms);
void komeda_crtc_handle_event(struct komeda_crtc *kcrtc,
struct komeda_events *evts);
+void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
+ struct completion *input_flip_done);
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
void komeda_kms_detach(struct komeda_kms_dev *kms);
--
2.25.1
@@ -1,33 +0,0 @@
From 97bdf703e47606d15cd04f1aa5490bcaed842ae3 Mon Sep 17 00:00:00 2001
From: Tushar Khandelwal <tushar.khandelwal@arm.com>
Date: Wed, 17 Jun 2020 10:49:26 +0000
Subject: [PATCH 02/40] drm: arm: komeda: add RENDER capability to the device
node
this is required to make this driver work with android framework
Signed-off-by: Tushar Khandelwal <tushar.khandelwal@arm.com>
Upstream-Status: Inappropriate [Product specific configuration]
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/gpu/drm/arm/display/komeda/komeda_kms.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 93b7f09b96ca..8b2be8a9a27d 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -58,7 +58,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
}
static const struct drm_driver komeda_kms_driver = {
- .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_RENDER,
.lastclose = drm_fb_helper_lastclose,
DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_cma_dumb_create),
.fops = &komeda_cma_fops,
--
2.34.1
@@ -1,30 +0,0 @@
From 6b9cf2d89db4fc10b930b8d8f8fce3a0d00fecf8 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Thu, 13 Jan 2022 20:14:25 +0000
Subject: [PATCH 03/40] firmware: arm_ffa: Fix uuid argument passed to
ffa_partition_probe
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ib2749ec3e02da5bb6d835f7dbf2d608c41fad1f2
Upstream-Status: Backport [f3c45c045e25ed52461829d2ce07954f72b6ad15]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index fc6d3b9bd472..d3d53fbd3d29 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -501,7 +501,7 @@ static int ffa_partition_info_get(const char *uuid_str,
return -ENODEV;
}
- count = ffa_partition_probe(&uuid_null, &pbuf);
+ count = ffa_partition_probe(&uuid, &pbuf);
if (count <= 0)
return -ENOENT;
--
2.34.1
@@ -1,34 +0,0 @@
From 9fe23341c66deefb1f953d7ca642f928d8a50c6e Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Thu, 13 Jan 2022 22:22:28 +0000
Subject: [PATCH 04/40] firmware: arm_ffa: Add ffa_dev_get_drvdata
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Icd09d686cab9922563b1deda5276307ea5d94923
Upstream-Status: Backport [498af8d1678ae2351218337b47bbf3cb0fc16821]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
include/linux/arm_ffa.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index f0cb5b72b87b..06dc83d38779 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -129,7 +129,12 @@ struct ffa_driver {
static inline void ffa_dev_set_drvdata(struct ffa_device *fdev, void *data)
{
- fdev->dev.driver_data = data;
+ dev_set_drvdata(&fdev->dev, data);
+}
+
+static inline void *ffa_dev_get_drvdata(struct ffa_device *fdev)
+{
+ return dev_get_drvdata(&fdev->dev);
}
#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
--
2.34.1
@@ -1,31 +0,0 @@
From 53e29fa837f36f3a699f7ada50dd08e43028a9c7 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Thu, 13 Jan 2022 22:23:52 +0000
Subject: [PATCH 05/40] firmware: arm_ffa: extern ffa_bus_type
extern ffa_bus_type so that SP driver can use it in bus_find_device call.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ib7a6a563aa35627a545f82c796816a5f72c80d70
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
include/linux/arm_ffa.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 06dc83d38779..d5c0a0c37fbe 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -179,6 +179,8 @@ const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
#define ffa_unregister(driver) \
ffa_driver_unregister(driver)
+extern struct bus_type ffa_bus_type;
+
/**
* module_ffa_driver() - Helper macro for registering a psa_ffa driver
* @__ffa_driver: ffa_driver structure
--
2.34.1
@@ -1,55 +0,0 @@
From 47cd54d908380de17d84a852625ef3a1ff92f496 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Fri, 14 Jan 2022 12:23:04 +0000
Subject: [PATCH 06/40] firmware: arm_ffa: Fix FFA_MEM_SHARE and
FFA_MEM_FRAG_TX
FFA memory share on success might return FFA_MEM_FRAG_RX. In that case
set handle from w1/w2 from FFA return value.
FFA_MEM_FRAG_TX call will return FFA_SUCCESS for the last fragment, so
check for this return code.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I7ef44742d53a9e75d8587d1213be98a1352f16d4
Upstream-Status: Backport [987756f67dee237ec35f3b249ab1ae25260c5340]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index d3d53fbd3d29..de6641912768 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -317,11 +317,15 @@ static int ffa_mem_first_frag(u32 func_id, phys_addr_t buf, u32 buf_sz,
if (ret.a0 == FFA_ERROR)
return ffa_to_linux_errno((int)ret.a2);
- if (ret.a0 != FFA_SUCCESS)
+ if (ret.a0 != FFA_SUCCESS && ret.a0 != FFA_MEM_FRAG_RX)
return -EOPNOTSUPP;
- if (handle)
- *handle = PACK_HANDLE(ret.a2, ret.a3);
+ if (handle) {
+ if (ret.a0 == FFA_MEM_FRAG_RX)
+ *handle = PACK_HANDLE(ret.a1, ret.a2);
+ else
+ *handle = PACK_HANDLE(ret.a2, ret.a3);
+ }
return frag_len;
}
@@ -345,7 +349,7 @@ static int ffa_mem_next_frag(u64 handle, u32 frag_len)
if (ret.a0 == FFA_ERROR)
return ffa_to_linux_errno((int)ret.a2);
- if (ret.a0 != FFA_MEM_FRAG_RX)
+ if (ret.a0 != FFA_SUCCESS && ret.a0 != FFA_MEM_FRAG_RX)
return -EOPNOTSUPP;
return ret.a3;
--
2.34.1
@@ -1,111 +0,0 @@
From 96e0bd88e2fb4fcb1625240ef36bccf0383633f6 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Tue, 17 May 2022 16:53:56 +0100
Subject: [PATCH 07/40] Revert "optee: use driver internal tee_context for some
rpc"
This reverts commit 2922aff4339712ef004451715e94bdbd55fe38ed.
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/tee/optee/core.c | 8 --------
drivers/tee/optee/optee_private.h | 2 --
drivers/tee/optee/rpc.c | 8 +++-----
3 files changed, 3 insertions(+), 15 deletions(-)
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 50c0d839fe75..5363ebebfc35 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -588,7 +588,6 @@ static int optee_remove(struct platform_device *pdev)
/* Unregister OP-TEE specific client devices on TEE bus */
optee_unregister_devices();
- teedev_close_context(optee->ctx);
/*
* Ask OP-TEE to free all cached shared memory objects to decrease
* reference counters and also avoid wild pointers in secure world
@@ -634,7 +633,6 @@ static int optee_probe(struct platform_device *pdev)
struct optee *optee = NULL;
void *memremaped_shm = NULL;
struct tee_device *teedev;
- struct tee_context *ctx;
u32 sec_caps;
int rc;
@@ -721,12 +719,6 @@ static int optee_probe(struct platform_device *pdev)
optee_supp_init(&optee->supp);
optee->memremaped_shm = memremaped_shm;
optee->pool = pool;
- ctx = teedev_open(optee->teedev);
- if (IS_ERR(ctx)) {
- rc = PTR_ERR(ctx);
- goto err;
- }
- optee->ctx = ctx;
/*
* Ensure that there are no pre-existing shm objects before enabling
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index ea09533e30cd..f6bb4a763ba9 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -70,7 +70,6 @@ struct optee_supp {
* struct optee - main service struct
* @supp_teedev: supplicant device
* @teedev: client device
- * @ctx: driver internal TEE context
* @invoke_fn: function to issue smc or hvc
* @call_queue: queue of threads waiting to call @invoke_fn
* @wait_queue: queue of threads from secure world waiting for a
@@ -88,7 +87,6 @@ struct optee {
struct tee_device *supp_teedev;
struct tee_device *teedev;
optee_invoke_fn *invoke_fn;
- struct tee_context *ctx;
struct optee_call_queue call_queue;
struct optee_wait_queue wait_queue;
struct optee_supp supp;
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
index 456833d82007..efbaff7ad7e5 100644
--- a/drivers/tee/optee/rpc.c
+++ b/drivers/tee/optee/rpc.c
@@ -285,7 +285,6 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
}
static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
- struct optee *optee,
struct optee_msg_arg *arg,
struct optee_call_ctx *call_ctx)
{
@@ -315,8 +314,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
shm = cmd_alloc_suppl(ctx, sz);
break;
case OPTEE_RPC_SHM_TYPE_KERNEL:
- shm = tee_shm_alloc(optee->ctx, sz,
- TEE_SHM_MAPPED | TEE_SHM_PRIV);
+ shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
break;
default:
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -473,7 +471,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
break;
case OPTEE_RPC_CMD_SHM_ALLOC:
free_pages_list(call_ctx);
- handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx);
+ handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
break;
case OPTEE_RPC_CMD_SHM_FREE:
handle_rpc_func_cmd_shm_free(ctx, arg);
@@ -504,7 +502,7 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
case OPTEE_SMC_RPC_FUNC_ALLOC:
- shm = tee_shm_alloc(optee->ctx, param->a1,
+ shm = tee_shm_alloc(ctx, param->a1,
TEE_SHM_MAPPED | TEE_SHM_PRIV);
if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
reg_pair_from_64(&param->a1, &param->a2, pa);
--
2.34.1
@@ -1,45 +0,0 @@
From 04f76b1e265b37ab8a3acf4bbf64d1efd69a6c73 Mon Sep 17 00:00:00 2001
From: Jens Wiklander <jens.wiklander@linaro.org>
Date: Thu, 25 Mar 2021 15:08:44 +0100
Subject: [PATCH 08/40] tee: add sec_world_id to struct tee_shm
Adds sec_world_id to struct tee_shm which describes a shared memory
object. sec_world_id can be used by a driver to store an id assigned by
secure world.
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Upstream-Status: Backport [9028b2463c1ea96f51c3ba53e2479346019ff6ad]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
include/linux/tee_drv.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 38b701b7af4c..5e1533ee3785 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -197,7 +197,11 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
* @num_pages: number of locked pages
* @refcount: reference counter
* @flags: defined by TEE_SHM_* in tee_drv.h
- * @id: unique id of a shared memory object on this device
+ * @id: unique id of a shared memory object on this device, shared
+ * with user space
+ * @sec_world_id:
+ * secure world assigned id of this shared memory object, not
+ * used by all drivers
*
* This pool is only supposed to be accessed directly from the TEE
* subsystem and from drivers that implements their own shm pool manager.
@@ -213,6 +217,7 @@ struct tee_shm {
refcount_t refcount;
u32 flags;
int id;
+ u64 sec_world_id;
};
/**
--
2.34.1
@@ -1,181 +0,0 @@
From 5a2565d002084a4c6b80329a4a23cb6c98c4f344 Mon Sep 17 00:00:00 2001
From: Jens Wiklander <jens.wiklander@linaro.org>
Date: Thu, 25 Mar 2021 15:08:46 +0100
Subject: [PATCH 09/40] optee: simplify optee_release()
Simplifies optee_release() with a new helper function,
optee_close_session_helper() which has been factored out from
optee_close_session().
A separate optee_release_supp() is added for the supplicant device.
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Upstream-Status: Backport [c0ab6db39a908d86ed44e8a5632548e2ec1b4dca]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/tee/optee/call.c | 31 ++++++++++-------
drivers/tee/optee/core.c | 56 +++++++++++--------------------
drivers/tee/optee/optee_private.h | 1 +
3 files changed, 39 insertions(+), 49 deletions(-)
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index 945f03da0223..103976df2062 100644
--- a/drivers/tee/optee/call.c
+++ b/drivers/tee/optee/call.c
@@ -288,12 +288,28 @@ int optee_open_session(struct tee_context *ctx,
return rc;
}
-int optee_close_session(struct tee_context *ctx, u32 session)
+int optee_close_session_helper(struct tee_context *ctx, u32 session)
{
- struct optee_context_data *ctxdata = ctx->data;
struct tee_shm *shm;
struct optee_msg_arg *msg_arg;
phys_addr_t msg_parg;
+
+ shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+ msg_arg->session = session;
+ optee_do_call_with_arg(ctx, msg_parg);
+
+ tee_shm_free(shm);
+
+ return 0;
+}
+
+int optee_close_session(struct tee_context *ctx, u32 session)
+{
+ struct optee_context_data *ctxdata = ctx->data;
struct optee_session *sess;
/* Check that the session is valid and remove it from the list */
@@ -306,16 +322,7 @@ int optee_close_session(struct tee_context *ctx, u32 session)
return -EINVAL;
kfree(sess);
- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
- if (IS_ERR(shm))
- return PTR_ERR(shm);
-
- msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
- msg_arg->session = session;
- optee_do_call_with_arg(ctx, msg_parg);
-
- tee_shm_free(shm);
- return 0;
+ return optee_close_session_helper(ctx, session);
}
int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 5363ebebfc35..79f67a79e7b7 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -264,60 +264,42 @@ static int optee_open(struct tee_context *ctx)
return 0;
}
-static void optee_release(struct tee_context *ctx)
+static void optee_release_helper(struct tee_context *ctx,
+ int (*close_session)(struct tee_context *ctx,
+ u32 session))
{
struct optee_context_data *ctxdata = ctx->data;
- struct tee_device *teedev = ctx->teedev;
- struct optee *optee = tee_get_drvdata(teedev);
- struct tee_shm *shm;
- struct optee_msg_arg *arg = NULL;
- phys_addr_t parg;
struct optee_session *sess;
struct optee_session *sess_tmp;
if (!ctxdata)
return;
- shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg),
- TEE_SHM_MAPPED | TEE_SHM_PRIV);
- if (!IS_ERR(shm)) {
- arg = tee_shm_get_va(shm, 0);
- /*
- * If va2pa fails for some reason, we can't call into
- * secure world, only free the memory. Secure OS will leak
- * sessions and finally refuse more sessions, but we will
- * at least let normal world reclaim its memory.
- */
- if (!IS_ERR(arg))
- if (tee_shm_va2pa(shm, arg, &parg))
- arg = NULL; /* prevent usage of parg below */
- }
-
list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
list_node) {
list_del(&sess->list_node);
- if (!IS_ERR_OR_NULL(arg)) {
- memset(arg, 0, sizeof(*arg));
- arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
- arg->session = sess->session_id;
- optee_do_call_with_arg(ctx, parg);
- }
+ close_session(ctx, sess->session_id);
kfree(sess);
}
kfree(ctxdata);
+ ctx->data = NULL;
+}
- if (!IS_ERR(shm))
- tee_shm_free(shm);
+static void optee_release(struct tee_context *ctx)
+{
+ optee_release_helper(ctx, optee_close_session_helper);
+}
- ctx->data = NULL;
+static void optee_release_supp(struct tee_context *ctx)
+{
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
- if (teedev == optee->supp_teedev) {
- if (optee->scan_bus_wq) {
- destroy_workqueue(optee->scan_bus_wq);
- optee->scan_bus_wq = NULL;
- }
- optee_supp_release(&optee->supp);
+ optee_release_helper(ctx, optee_close_session_helper);
+ if (optee->scan_bus_wq) {
+ destroy_workqueue(optee->scan_bus_wq);
+ optee->scan_bus_wq = NULL;
}
+ optee_supp_release(&optee->supp);
}
static const struct tee_driver_ops optee_ops = {
@@ -341,7 +323,7 @@ static const struct tee_desc optee_desc = {
static const struct tee_driver_ops optee_supp_ops = {
.get_version = optee_get_version,
.open = optee_open,
- .release = optee_release,
+ .release = optee_release_supp,
.supp_recv = optee_supp_recv,
.supp_send = optee_supp_send,
.shm_register = optee_shm_register_supp,
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index f6bb4a763ba9..a55793f9f6eb 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -152,6 +152,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
int optee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param);
+int optee_close_session_helper(struct tee_context *ctx, u32 session);
int optee_close_session(struct tee_context *ctx, u32 session);
int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
struct tee_param *param);
--
2.34.1
@@ -1,722 +0,0 @@
From cbb24d5b6b4e6704da79bb3df76179a88a6ee14f Mon Sep 17 00:00:00 2001
From: Jens Wiklander <jens.wiklander@linaro.org>
Date: Thu, 25 Mar 2021 15:08:50 +0100
Subject: [PATCH 10/40] optee: refactor driver with internal callbacks
The OP-TEE driver is refactored with three internal callbacks replacing
direct calls to optee_from_msg_param(), optee_to_msg_param() and
optee_do_call_with_arg().
These functions a central to communicating with OP-TEE in secure world
by using the SMC Calling Convention directly.
This refactoring makes room for using other primitives to communicate
with OP-TEE in secure world while being able to reuse as much as
possible from the present driver.
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Upstream-Status: Backport [4602c5842f649da2fbd2cea3560af750cfbd59e3]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/tee/optee/call.c | 86 +++++++++--------
drivers/tee/optee/core.c | 148 ++++++++++++++++++++----------
drivers/tee/optee/optee_private.h | 35 +++++--
drivers/tee/optee/rpc.c | 19 ++--
4 files changed, 182 insertions(+), 106 deletions(-)
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
index 103976df2062..ddedde45f1ee 100644
--- a/drivers/tee/optee/call.c
+++ b/drivers/tee/optee/call.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
*/
#include <linux/arm-smccc.h>
#include <linux/device.h>
@@ -118,20 +118,25 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata,
/**
* optee_do_call_with_arg() - Do an SMC to OP-TEE in secure world
* @ctx: calling context
- * @parg: physical address of message to pass to secure world
+ * @arg: shared memory holding the message to pass to secure world
*
* Does and SMC to OP-TEE in secure world and handles eventual resulting
* Remote Procedure Calls (RPC) from OP-TEE.
*
* Returns return code from secure world, 0 is OK
*/
-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
{
struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_call_waiter w;
struct optee_rpc_param param = { };
struct optee_call_ctx call_ctx = { };
- u32 ret;
+ phys_addr_t parg;
+ int rc;
+
+ rc = tee_shm_get_pa(arg, 0, &parg);
+ if (rc)
+ return rc;
param.a0 = OPTEE_SMC_CALL_WITH_ARG;
reg_pair_from_64(&param.a1, &param.a2, parg);
@@ -160,7 +165,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
param.a3 = res.a3;
optee_handle_rpc(ctx, &param, &call_ctx);
} else {
- ret = res.a0;
+ rc = res.a0;
break;
}
}
@@ -172,14 +177,12 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
*/
optee_cq_wait_final(&optee->call_queue, &w);
- return ret;
+ return rc;
}
static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
- struct optee_msg_arg **msg_arg,
- phys_addr_t *msg_parg)
+ struct optee_msg_arg **msg_arg)
{
- int rc;
struct tee_shm *shm;
struct optee_msg_arg *ma;
@@ -190,22 +193,13 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
ma = tee_shm_get_va(shm, 0);
if (IS_ERR(ma)) {
- rc = PTR_ERR(ma);
- goto out;
+ tee_shm_free(shm);
+ return (void *)ma;
}
- rc = tee_shm_get_pa(shm, 0, msg_parg);
- if (rc)
- goto out;
-
memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
ma->num_params = num_params;
*msg_arg = ma;
-out:
- if (rc) {
- tee_shm_free(shm);
- return ERR_PTR(rc);
- }
return shm;
}
@@ -214,16 +208,16 @@ int optee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param)
{
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_context_data *ctxdata = ctx->data;
int rc;
struct tee_shm *shm;
struct optee_msg_arg *msg_arg;
- phys_addr_t msg_parg;
struct optee_session *sess = NULL;
uuid_t client_uuid;
/* +2 for the meta parameters added below */
- shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
+ shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg);
if (IS_ERR(shm))
return PTR_ERR(shm);
@@ -247,7 +241,8 @@ int optee_open_session(struct tee_context *ctx,
goto out;
export_uuid(msg_arg->params[1].u.octets, &client_uuid);
- rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
+ rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
+ arg->num_params, param);
if (rc)
goto out;
@@ -257,7 +252,7 @@ int optee_open_session(struct tee_context *ctx,
goto out;
}
- if (optee_do_call_with_arg(ctx, msg_parg)) {
+ if (optee->ops->do_call_with_arg(ctx, shm)) {
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
}
@@ -272,7 +267,8 @@ int optee_open_session(struct tee_context *ctx,
kfree(sess);
}
- if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
+ if (optee->ops->from_msg_param(optee, param, arg->num_params,
+ msg_arg->params + 2)) {
arg->ret = TEEC_ERROR_COMMUNICATION;
arg->ret_origin = TEEC_ORIGIN_COMMS;
/* Close session again to avoid leakage */
@@ -291,16 +287,16 @@ int optee_open_session(struct tee_context *ctx,
int optee_close_session_helper(struct tee_context *ctx, u32 session)
{
struct tee_shm *shm;
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_msg_arg *msg_arg;
- phys_addr_t msg_parg;
- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+ shm = get_msg_arg(ctx, 0, &msg_arg);
if (IS_ERR(shm))
return PTR_ERR(shm);
msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
msg_arg->session = session;
- optee_do_call_with_arg(ctx, msg_parg);
+ optee->ops->do_call_with_arg(ctx, shm);
tee_shm_free(shm);
@@ -328,10 +324,10 @@ int optee_close_session(struct tee_context *ctx, u32 session)
int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
struct tee_param *param)
{
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_context_data *ctxdata = ctx->data;
struct tee_shm *shm;
struct optee_msg_arg *msg_arg;
- phys_addr_t msg_parg;
struct optee_session *sess;
int rc;
@@ -342,7 +338,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
if (!sess)
return -EINVAL;
- shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
+ shm = get_msg_arg(ctx, arg->num_params, &msg_arg);
if (IS_ERR(shm))
return PTR_ERR(shm);
msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
@@ -350,16 +346,18 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
msg_arg->session = arg->session;
msg_arg->cancel_id = arg->cancel_id;
- rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
+ rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
+ param);
if (rc)
goto out;
- if (optee_do_call_with_arg(ctx, msg_parg)) {
+ if (optee->ops->do_call_with_arg(ctx, shm)) {
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
}
- if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
+ if (optee->ops->from_msg_param(optee, param, arg->num_params,
+ msg_arg->params)) {
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
}
@@ -373,10 +371,10 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
{
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_context_data *ctxdata = ctx->data;
struct tee_shm *shm;
struct optee_msg_arg *msg_arg;
- phys_addr_t msg_parg;
struct optee_session *sess;
/* Check that the session is valid */
@@ -386,14 +384,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
if (!sess)
return -EINVAL;
- shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+ shm = get_msg_arg(ctx, 0, &msg_arg);
if (IS_ERR(shm))
return PTR_ERR(shm);
msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
msg_arg->session = session;
msg_arg->cancel_id = cancel_id;
- optee_do_call_with_arg(ctx, msg_parg);
+ optee->ops->do_call_with_arg(ctx, shm);
tee_shm_free(shm);
return 0;
@@ -622,10 +620,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
struct page **pages, size_t num_pages,
unsigned long start)
{
- struct tee_shm *shm_arg = NULL;
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_msg_arg *msg_arg;
+ struct tee_shm *shm_arg;
u64 *pages_list;
- phys_addr_t msg_parg;
int rc;
if (!num_pages)
@@ -639,7 +637,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
if (!pages_list)
return -ENOMEM;
- shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
+ shm_arg = get_msg_arg(ctx, 1, &msg_arg);
if (IS_ERR(shm_arg)) {
rc = PTR_ERR(shm_arg);
goto out;
@@ -660,7 +658,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
(tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
- if (optee_do_call_with_arg(ctx, msg_parg) ||
+ if (optee->ops->do_call_with_arg(ctx, shm_arg) ||
msg_arg->ret != TEEC_SUCCESS)
rc = -EINVAL;
@@ -672,12 +670,12 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
{
- struct tee_shm *shm_arg;
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
struct optee_msg_arg *msg_arg;
- phys_addr_t msg_parg;
+ struct tee_shm *shm_arg;
int rc = 0;
- shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
+ shm_arg = get_msg_arg(ctx, 1, &msg_arg);
if (IS_ERR(shm_arg))
return PTR_ERR(shm_arg);
@@ -686,7 +684,7 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
- if (optee_do_call_with_arg(ctx, msg_parg) ||
+ if (optee->ops->do_call_with_arg(ctx, shm_arg) ||
msg_arg->ret != TEEC_SUCCESS)
rc = -EINVAL;
tee_shm_free(shm_arg);
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 79f67a79e7b7..26492d3115f5 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -27,21 +27,87 @@
#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
+static void from_msg_param_value(struct tee_param *p, u32 attr,
+ const struct optee_msg_param *mp)
+{
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
+ attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+ p->u.value.a = mp->u.value.a;
+ p->u.value.b = mp->u.value.b;
+ p->u.value.c = mp->u.value.c;
+}
+
+static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
+ const struct optee_msg_param *mp)
+{
+ struct tee_shm *shm;
+ phys_addr_t pa;
+ int rc;
+
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+ attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
+ p->u.memref.size = mp->u.tmem.size;
+ shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
+ if (!shm) {
+ p->u.memref.shm_offs = 0;
+ p->u.memref.shm = NULL;
+ return 0;
+ }
+
+ rc = tee_shm_get_pa(shm, 0, &pa);
+ if (rc)
+ return rc;
+
+ p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
+ p->u.memref.shm = shm;
+
+ /* Check that the memref is covered by the shm object */
+ if (p->u.memref.size) {
+ size_t o = p->u.memref.shm_offs +
+ p->u.memref.size - 1;
+
+ rc = tee_shm_get_pa(shm, o, NULL);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
+ const struct optee_msg_param *mp)
+{
+ struct tee_shm *shm;
+
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+ attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ p->u.memref.size = mp->u.rmem.size;
+ shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref;
+
+ if (shm) {
+ p->u.memref.shm_offs = mp->u.rmem.offs;
+ p->u.memref.shm = shm;
+ } else {
+ p->u.memref.shm_offs = 0;
+ p->u.memref.shm = NULL;
+ }
+}
+
/**
* optee_from_msg_param() - convert from OPTEE_MSG parameters to
* struct tee_param
+ * @optee: main service struct
* @params: subsystem internal parameter representation
* @num_params: number of elements in the parameter arrays
* @msg_params: OPTEE_MSG parameters
* Returns 0 on success or <0 on failure
*/
-int optee_from_msg_param(struct tee_param *params, size_t num_params,
- const struct optee_msg_param *msg_params)
+static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
+ size_t num_params,
+ const struct optee_msg_param *msg_params)
{
int rc;
size_t n;
- struct tee_shm *shm;
- phys_addr_t pa;
for (n = 0; n < num_params; n++) {
struct tee_param *p = params + n;
@@ -56,48 +122,19 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
- attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
- p->u.value.a = mp->u.value.a;
- p->u.value.b = mp->u.value.b;
- p->u.value.c = mp->u.value.c;
+ from_msg_param_value(p, attr, mp);
break;
case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
- attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
- p->u.memref.size = mp->u.tmem.size;
- shm = (struct tee_shm *)(unsigned long)
- mp->u.tmem.shm_ref;
- if (!shm) {
- p->u.memref.shm_offs = 0;
- p->u.memref.shm = NULL;
- break;
- }
- rc = tee_shm_get_pa(shm, 0, &pa);
+ rc = from_msg_param_tmp_mem(p, attr, mp);
if (rc)
return rc;
- p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
- p->u.memref.shm = shm;
break;
case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
- p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
- attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
- p->u.memref.size = mp->u.rmem.size;
- shm = (struct tee_shm *)(unsigned long)
- mp->u.rmem.shm_ref;
-
- if (!shm) {
- p->u.memref.shm_offs = 0;
- p->u.memref.shm = NULL;
- break;
- }
- p->u.memref.shm_offs = mp->u.rmem.offs;
- p->u.memref.shm = shm;
-
+ from_msg_param_reg_mem(p, attr, mp);
break;
default:
@@ -107,6 +144,16 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
return 0;
}
+static void to_msg_param_value(struct optee_msg_param *mp,
+ const struct tee_param *p)
+{
+ mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+ mp->u.value.a = p->u.value.a;
+ mp->u.value.b = p->u.value.b;
+ mp->u.value.c = p->u.value.c;
+}
+
static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
const struct tee_param *p)
{
@@ -149,13 +196,15 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
/**
* optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
+ * @optee: main service struct
* @msg_params: OPTEE_MSG parameters
* @num_params: number of elements in the parameter arrays
* @params: subsystem itnernal parameter representation
* Returns 0 on success or <0 on failure
*/
-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
- const struct tee_param *params)
+static int optee_to_msg_param(struct optee *optee,
+ struct optee_msg_param *msg_params,
+ size_t num_params, const struct tee_param *params)
{
int rc;
size_t n;
@@ -172,11 +221,7 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
- mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
- TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
- mp->u.value.a = p->u.value.a;
- mp->u.value.b = p->u.value.b;
- mp->u.value.c = p->u.value.c;
+ to_msg_param_value(mp, p);
break;
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
@@ -302,7 +347,7 @@ static void optee_release_supp(struct tee_context *ctx)
optee_supp_release(&optee->supp);
}
-static const struct tee_driver_ops optee_ops = {
+static const struct tee_driver_ops optee_clnt_ops = {
.get_version = optee_get_version,
.open = optee_open,
.release = optee_release,
@@ -314,9 +359,9 @@ static const struct tee_driver_ops optee_ops = {
.shm_unregister = optee_shm_unregister,
};
-static const struct tee_desc optee_desc = {
+static const struct tee_desc optee_clnt_desc = {
.name = DRIVER_NAME "-clnt",
- .ops = &optee_ops,
+ .ops = &optee_clnt_ops,
.owner = THIS_MODULE,
};
@@ -337,6 +382,12 @@ static const struct tee_desc optee_supp_desc = {
.flags = TEE_DESC_PRIVILEGED,
};
+static const struct optee_ops optee_ops = {
+ .do_call_with_arg = optee_do_call_with_arg,
+ .to_msg_param = optee_to_msg_param,
+ .from_msg_param = optee_from_msg_param,
+};
+
static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
{
struct arm_smccc_res res;
@@ -670,10 +721,11 @@ static int optee_probe(struct platform_device *pdev)
goto err;
}
+ optee->ops = &optee_ops;
optee->invoke_fn = invoke_fn;
optee->sec_caps = sec_caps;
- teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
+ teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee);
if (IS_ERR(teedev)) {
rc = PTR_ERR(teedev);
goto err;
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index a55793f9f6eb..beca97017996 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
*/
#ifndef OPTEE_PRIVATE_H
@@ -66,9 +66,34 @@ struct optee_supp {
struct completion reqs_c;
};
+struct optee;
+
+/**
+ * struct optee_ops - OP-TEE driver internal operations
+ * @do_call_with_arg: enters OP-TEE in secure world
+ * @to_msg_param: converts from struct tee_param to OPTEE_MSG parameters
+ * @from_msg_param: converts from OPTEE_MSG parameters to struct tee_param
+ *
+ * These OPs are only supposed to be used internally in the OP-TEE driver
+ * as a way of abstracting the different methogs of entering OP-TEE in
+ * secure world.
+ */
+struct optee_ops {
+ int (*do_call_with_arg)(struct tee_context *ctx,
+ struct tee_shm *shm_arg);
+ int (*to_msg_param)(struct optee *optee,
+ struct optee_msg_param *msg_params,
+ size_t num_params, const struct tee_param *params);
+ int (*from_msg_param)(struct optee *optee, struct tee_param *params,
+ size_t num_params,
+ const struct optee_msg_param *msg_params);
+};
+
/**
* struct optee - main service struct
* @supp_teedev: supplicant device
+ * @ops: internal callbacks for different ways to reach secure
+ * world
* @teedev: client device
* @invoke_fn: function to issue smc or hvc
* @call_queue: queue of threads waiting to call @invoke_fn
@@ -86,6 +111,7 @@ struct optee_supp {
struct optee {
struct tee_device *supp_teedev;
struct tee_device *teedev;
+ const struct optee_ops *ops;
optee_invoke_fn *invoke_fn;
struct optee_call_queue call_queue;
struct optee_wait_queue wait_queue;
@@ -148,7 +174,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
struct tee_param *param);
-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
+int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
int optee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param);
@@ -172,11 +198,6 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
unsigned long start);
int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
-int optee_from_msg_param(struct tee_param *params, size_t num_params,
- const struct optee_msg_param *msg_params);
-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
- const struct tee_param *params);
-
u64 *optee_allocate_pages_list(size_t num_entries);
void optee_free_pages_list(void *array, size_t num_entries);
void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
index efbaff7ad7e5..309258d47790 100644
--- a/drivers/tee/optee/rpc.c
+++ b/drivers/tee/optee/rpc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015-2016, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -55,6 +55,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
struct optee_msg_arg *arg)
{
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
struct tee_param *params;
struct i2c_adapter *adapter;
struct i2c_msg msg = { };
@@ -79,7 +80,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
return;
}
- if (optee_from_msg_param(params, arg->num_params, arg->params))
+ if (optee->ops->from_msg_param(optee, params, arg->num_params,
+ arg->params))
goto bad;
for (i = 0; i < arg->num_params; i++) {
@@ -122,7 +124,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
arg->ret = TEEC_ERROR_COMMUNICATION;
} else {
params[3].u.value.a = msg.len;
- if (optee_to_msg_param(arg->params, arg->num_params, params))
+ if (optee->ops->to_msg_param(optee, arg->params,
+ arg->num_params, params))
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
else
arg->ret = TEEC_SUCCESS;
@@ -234,7 +237,7 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
}
-static void handle_rpc_supp_cmd(struct tee_context *ctx,
+static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
struct optee_msg_arg *arg)
{
struct tee_param *params;
@@ -248,14 +251,16 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx,
return;
}
- if (optee_from_msg_param(params, arg->num_params, arg->params)) {
+ if (optee->ops->from_msg_param(optee, params, arg->num_params,
+ arg->params)) {
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
goto out;
}
arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
- if (optee_to_msg_param(arg->params, arg->num_params, params))
+ if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
+ params))
arg->ret = TEEC_ERROR_BAD_PARAMETERS;
out:
kfree(params);
@@ -480,7 +485,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
handle_rpc_func_cmd_i2c_transfer(ctx, arg);
break;
default:
- handle_rpc_supp_cmd(ctx, arg);
+ handle_rpc_supp_cmd(ctx, optee, arg);
}
}
--
2.34.1
@@ -1,63 +0,0 @@
From 61c33344f747deac2860571ef965c20f9170efea Mon Sep 17 00:00:00 2001
From: Jens Wiklander <jens.wiklander@linaro.org>
Date: Thu, 21 Oct 2021 14:55:39 +0200
Subject: [PATCH 13/40] optee: smc_abi.c: add missing #include <linux/mm.h>
Adds missing #include <linux/mm.h> drivers/tee/optee/smc_abi.c to fix
compile errors like:
drivers/tee/optee/smc_abi.c:405:15: error: implicit
declaration of function 'page_to_section'
[-Werror,-Wimplicit-function-declaration]
optee_page = page_to_phys(*pages) +
^
arch/arm/include/asm/memory.h:148:43: note: expanded from
macro 'page_to_phys'
^
include/asm-generic/memory_model.h:52:21: note: expanded
from macro 'page_to_pfn'
^
include/asm-generic/memory_model.h:35:14: note: expanded
from macro '__page_to_pfn'
int __sec = page_to_section(__pg); \
^
drivers/tee/optee/smc_abi.c:405:15: note: did you mean
'__nr_to_section'?
arch/arm/include/asm/memory.h:148:43: note: expanded from
macro 'page_to_phys'
^
include/asm-generic/memory_model.h:52:21: note: expanded
from macro 'page_to_pfn'
^
include/asm-generic/memory_model.h:35:14: note: expanded
from macro '__page_to_pfn'
int __sec = page_to_section(__pg); \
^
include/linux/mmzone.h:1365:35: note: '__nr_to_section'
declared here
static inline struct mem_section *__nr_to_section(unsigned long nr)
Fixes: c51a564a5b48 ("optee: isolate smc abi")
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Link: https://lore.kernel.org/r/20211021125539.3858495-1-jens.wiklander@linaro.org'
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Upstream-Status: Backport [https://lore.kernel.org/r/20211021125539.3858495-1-jens.wiklander@linaro.org]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/tee/optee/smc_abi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index 9a787fb4f5e5..6196d7c3888f 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/sched.h>
+#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
--
2.34.1
@@ -1,43 +0,0 @@
From bf890db9200464083c44987cd41c034b1019fc5a Mon Sep 17 00:00:00 2001
From: Colin Ian King <colin.i.king@googlemail.com>
Date: Sat, 23 Oct 2021 12:52:09 +0100
Subject: [PATCH 14/40] optee: Fix spelling mistake "reclain" -> "reclaim"
There are spelling mistakes in pr_err error messages. Fix them.
Fixes: 4615e5a34b95 ("optee: add FF-A support")
Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
[jw: added a fixes]
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Upstream-Status: Backport [1b73a9e4986a4e9065bacf1e5ab2dfda17b54161]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/tee/optee/ffa_abi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 6defd1ec982a..45424824e0f9 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -333,7 +333,7 @@ static int optee_ffa_shm_unregister(struct tee_context *ctx,
rc = ffa_ops->memory_reclaim(global_handle, 0);
if (rc)
- pr_err("mem_reclain: 0x%llx %d", global_handle, rc);
+ pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
return rc;
}
@@ -355,7 +355,7 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
optee_shm_rem_ffa_handle(optee, global_handle);
rc = ffa_ops->memory_reclaim(global_handle, 0);
if (rc)
- pr_err("mem_reclain: 0x%llx %d", global_handle, rc);
+ pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
shm->sec_world_id = 0;
--
2.34.1
@@ -1,44 +0,0 @@
From 9f3b899a2e8bf79f572f408bfd86836578f46106 Mon Sep 17 00:00:00 2001
From: Lv Ruyi <lv.ruyi@zte.com.cn>
Date: Thu, 4 Nov 2021 11:30:47 +0000
Subject: [PATCH 15/40] optee: fix kfree NULL pointer
This patch fixes the following Coccinelle error:
drivers/tee/optee/ffa_abi.c: 877: ERROR optee is NULL but dereferenced.
If memory allocation fails, optee is null pointer. the code will goto err
and release optee.
Fixes: 4615e5a34b95 ("optee: add FF-A support")
Reported-by: Zeal Robot <zealci@zte.com.cn>
Signed-off-by: Lv Ruyi <lv.ruyi@zte.com.cn>
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
[jw: removed the redundant braces]
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Upstream-Status: Backport [c23ca66a4dadb6f050dc57358bc8d57a747c35bf]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/tee/optee/ffa_abi.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 45424824e0f9..d8c8683863aa 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -810,10 +810,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
return -EINVAL;
optee = kzalloc(sizeof(*optee), GFP_KERNEL);
- if (!optee) {
- rc = -ENOMEM;
- goto err;
- }
+ if (!optee)
+ return -ENOMEM;
+
optee->pool = optee_ffa_config_dyn_shm();
if (IS_ERR(optee->pool)) {
rc = PTR_ERR(optee->pool);
--
2.34.1
@@ -1,107 +0,0 @@
From a52e1e964aa4f2592ebffb30df048cc85fa5a02c Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:51 +0000
Subject: [PATCH 16/40] perf/arm-cmn: Account for NUMA affinity
On a system with multiple CMN meshes, ideally we'd want to access each
PMU from within its own mesh, rather than with a long CML round-trip,
wherever feasible. Since such a system is likely to be presented as
multiple NUMA nodes, let's also hope a proximity domain is specified
for each CMN programming interface, and use that to guide our choice
of IRQ affinity to favour a node-local CPU where possible.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/32438b0d016e0649d882d47d30ac2000484287b9.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 51 +++++++++++++++++++++++++++++++-----------
1 file changed, 38 insertions(+), 13 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 400eb7f579dc..02b898dbba91 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -1147,23 +1147,47 @@ static int arm_cmn_commit_txn(struct pmu *pmu)
return 0;
}
-static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+static void arm_cmn_migrate(struct arm_cmn *cmn, unsigned int cpu)
+{
+ unsigned int i;
+
+ perf_pmu_migrate_context(&cmn->pmu, cmn->cpu, cpu);
+ for (i = 0; i < cmn->num_dtcs; i++)
+ irq_set_affinity(cmn->dtc[i].irq, cpumask_of(cpu));
+ cmn->cpu = cpu;
+}
+
+static int arm_cmn_pmu_online_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
{
struct arm_cmn *cmn;
- unsigned int i, target;
+ int node;
- cmn = hlist_entry_safe(node, struct arm_cmn, cpuhp_node);
- if (cpu != cmn->cpu)
- return 0;
+ cmn = hlist_entry_safe(cpuhp_node, struct arm_cmn, cpuhp_node);
+ node = dev_to_node(cmn->dev);
+ if (node != NUMA_NO_NODE && cpu_to_node(cmn->cpu) != node && cpu_to_node(cpu) == node)
+ arm_cmn_migrate(cmn, cpu);
+ return 0;
+}
+
+static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *cpuhp_node)
+{
+ struct arm_cmn *cmn;
+ unsigned int target;
+ int node;
+ cpumask_t mask;
- target = cpumask_any_but(cpu_online_mask, cpu);
- if (target >= nr_cpu_ids)
+ cmn = hlist_entry_safe(cpuhp_node, struct arm_cmn, cpuhp_node);
+ if (cpu != cmn->cpu)
return 0;
- perf_pmu_migrate_context(&cmn->pmu, cpu, target);
- for (i = 0; i < cmn->num_dtcs; i++)
- irq_set_affinity(cmn->dtc[i].irq, cpumask_of(target));
- cmn->cpu = target;
+ node = dev_to_node(cmn->dev);
+ if (cpumask_and(&mask, cpumask_of_node(node), cpu_online_mask) &&
+ cpumask_andnot(&mask, &mask, cpumask_of(cpu)))
+ target = cpumask_any(&mask);
+ else
+ target = cpumask_any_but(cpu_online_mask, cpu);
+ if (target < nr_cpu_ids)
+ arm_cmn_migrate(cmn, target);
return 0;
}
@@ -1532,7 +1556,7 @@ static int arm_cmn_probe(struct platform_device *pdev)
if (err)
return err;
- cmn->cpu = raw_smp_processor_id();
+ cmn->cpu = cpumask_local_spread(0, dev_to_node(cmn->dev));
cmn->pmu = (struct pmu) {
.module = THIS_MODULE,
.attr_groups = arm_cmn_attr_groups,
@@ -1608,7 +1632,8 @@ static int __init arm_cmn_init(void)
int ret;
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
- "perf/arm/cmn:online", NULL,
+ "perf/arm/cmn:online",
+ arm_cmn_pmu_online_cpu,
arm_cmn_pmu_offline_cpu);
if (ret < 0)
return ret;
--
2.34.1
@@ -1,89 +0,0 @@
From 16cf1b5483d4cbad8ee52fcc9945abcea6492bd1 Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:52 +0000
Subject: [PATCH 17/40] perf/arm-cmn: Drop compile-test restriction
Although CMN is currently (and overwhelmingly likely to remain) deployed
in arm64-only (modulo userspace) systems, the 64-bit "dependency" for
compile-testing was just laziness due to heavy reliance on readq/writeq
accessors. Since we only need one extra include for robustness in that
regard, let's pull that in, widen the compile-test coverage, and fix up
the smattering of type laziness that that brings to light.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/baee9ee0d0bdad8aaeb70f5a4b98d8fd4b1f5786.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/Kconfig | 2 +-
drivers/perf/arm-cmn.c | 25 +++++++++++++------------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 77522e5efe11..e453915ebc84 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -43,7 +43,7 @@ config ARM_CCN
config ARM_CMN
tristate "Arm CMN-600 PMU support"
- depends on ARM64 || (COMPILE_TEST && 64BIT)
+ depends on ARM64 || COMPILE_TEST
help
Support for PMU events monitoring on the Arm CMN-600 Coherent Mesh
Network interconnect.
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 02b898dbba91..1d52fcfe3a0d 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -7,6 +7,7 @@
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -122,11 +123,11 @@
/* Event attributes */
-#define CMN_CONFIG_TYPE GENMASK(15, 0)
-#define CMN_CONFIG_EVENTID GENMASK(23, 16)
-#define CMN_CONFIG_OCCUPID GENMASK(27, 24)
-#define CMN_CONFIG_BYNODEID BIT(31)
-#define CMN_CONFIG_NODEID GENMASK(47, 32)
+#define CMN_CONFIG_TYPE GENMASK_ULL(15, 0)
+#define CMN_CONFIG_EVENTID GENMASK_ULL(23, 16)
+#define CMN_CONFIG_OCCUPID GENMASK_ULL(27, 24)
+#define CMN_CONFIG_BYNODEID BIT_ULL(31)
+#define CMN_CONFIG_NODEID GENMASK_ULL(47, 32)
#define CMN_EVENT_TYPE(event) FIELD_GET(CMN_CONFIG_TYPE, (event)->attr.config)
#define CMN_EVENT_EVENTID(event) FIELD_GET(CMN_CONFIG_EVENTID, (event)->attr.config)
@@ -134,13 +135,13 @@
#define CMN_EVENT_BYNODEID(event) FIELD_GET(CMN_CONFIG_BYNODEID, (event)->attr.config)
#define CMN_EVENT_NODEID(event) FIELD_GET(CMN_CONFIG_NODEID, (event)->attr.config)
-#define CMN_CONFIG_WP_COMBINE GENMASK(27, 24)
-#define CMN_CONFIG_WP_DEV_SEL BIT(48)
-#define CMN_CONFIG_WP_CHN_SEL GENMASK(50, 49)
-#define CMN_CONFIG_WP_GRP BIT(52)
-#define CMN_CONFIG_WP_EXCLUSIVE BIT(53)
-#define CMN_CONFIG1_WP_VAL GENMASK(63, 0)
-#define CMN_CONFIG2_WP_MASK GENMASK(63, 0)
+#define CMN_CONFIG_WP_COMBINE GENMASK_ULL(27, 24)
+#define CMN_CONFIG_WP_DEV_SEL BIT_ULL(48)
+#define CMN_CONFIG_WP_CHN_SEL GENMASK_ULL(50, 49)
+#define CMN_CONFIG_WP_GRP BIT_ULL(52)
+#define CMN_CONFIG_WP_EXCLUSIVE BIT_ULL(53)
+#define CMN_CONFIG1_WP_VAL GENMASK_ULL(63, 0)
+#define CMN_CONFIG2_WP_MASK GENMASK_ULL(63, 0)
#define CMN_EVENT_WP_COMBINE(event) FIELD_GET(CMN_CONFIG_WP_COMBINE, (event)->attr.config)
#define CMN_EVENT_WP_DEV_SEL(event) FIELD_GET(CMN_CONFIG_WP_DEV_SEL, (event)->attr.config)
--
2.34.1
@@ -1,155 +0,0 @@
From 762ba0fb54d97c08c35fbe2745c19fd4a74ded0d Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:53 +0000
Subject: [PATCH 18/40] perf/arm-cmn: Refactor node ID handling
Add a bit more abstraction for the places where we decompose node IDs.
This will help keep things nice and manageable when we come to add yet
more variables which affect the node ID format. Also use the opportunity
to move the rest of the low-level node management helpers back up to the
logical place they were meant to be - how they ended up buried right in
the middle of the event-related definitions is somewhat of a mystery...
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/a2242a8c3c96056c13a04ae87bf2047e5e64d2d9.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 94 +++++++++++++++++++++++++-----------------
1 file changed, 56 insertions(+), 38 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 1d52fcfe3a0d..adf50d613734 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -255,6 +255,58 @@ struct arm_cmn {
static int arm_cmn_hp_state;
+struct arm_cmn_nodeid {
+ u8 x;
+ u8 y;
+ u8 port;
+ u8 dev;
+};
+
+static int arm_cmn_xyidbits(const struct arm_cmn *cmn)
+{
+ int dim = max(cmn->mesh_x, cmn->mesh_y);
+
+ return dim > 4 ? 3 : 2;
+}
+
+static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn *cmn, u16 id)
+{
+ struct arm_cmn_nodeid nid;
+ int bits = arm_cmn_xyidbits(cmn);
+
+ nid.x = CMN_NODEID_X(id, bits);
+ nid.y = CMN_NODEID_Y(id, bits);
+ nid.port = CMN_NODEID_PID(id);
+ nid.dev = CMN_NODEID_DEVID(id);
+
+ return nid;
+}
+
+static void arm_cmn_init_node_to_xp(const struct arm_cmn *cmn,
+ struct arm_cmn_node *dn)
+{
+ struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
+ int xp_idx = cmn->mesh_x * nid.y + nid.x;
+
+ dn->to_xp = (cmn->xps + xp_idx) - dn;
+}
+
+static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
+{
+ return dn->type == CMN_TYPE_XP ? dn : dn + dn->to_xp;
+}
+
+static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
+ enum cmn_node_type type)
+{
+ int i;
+
+ for (i = 0; i < cmn->num_dns; i++)
+ if (cmn->dns[i].type == type)
+ return &cmn->dns[i];
+ return NULL;
+}
+
struct arm_cmn_hw_event {
struct arm_cmn_node *dn;
u64 dtm_idx[2];
@@ -295,38 +347,6 @@ struct arm_cmn_format_attr {
int config;
};
-static int arm_cmn_xyidbits(const struct arm_cmn *cmn)
-{
- return cmn->mesh_x > 4 || cmn->mesh_y > 4 ? 3 : 2;
-}
-
-static void arm_cmn_init_node_to_xp(const struct arm_cmn *cmn,
- struct arm_cmn_node *dn)
-{
- int bits = arm_cmn_xyidbits(cmn);
- int x = CMN_NODEID_X(dn->id, bits);
- int y = CMN_NODEID_Y(dn->id, bits);
- int xp_idx = cmn->mesh_x * y + x;
-
- dn->to_xp = (cmn->xps + xp_idx) - dn;
-}
-
-static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
-{
- return dn->type == CMN_TYPE_XP ? dn : dn + dn->to_xp;
-}
-
-static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
- enum cmn_node_type type)
-{
- int i;
-
- for (i = 0; i < cmn->num_dns; i++)
- if (cmn->dns[i].type == type)
- return &cmn->dns[i];
- return NULL;
-}
-
#define CMN_EVENT_ATTR(_name, _type, _eventid, _occupid) \
(&((struct arm_cmn_event_attr[]) {{ \
.attr = __ATTR(_name, 0444, arm_cmn_event_show, NULL), \
@@ -966,11 +986,10 @@ static int arm_cmn_event_init(struct perf_event *event)
}
if (!hw->num_dns) {
- int bits = arm_cmn_xyidbits(cmn);
+ struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, nodeid);
dev_dbg(cmn->dev, "invalid node 0x%x (%d,%d,%d,%d) type 0x%x\n",
- nodeid, CMN_NODEID_X(nodeid, bits), CMN_NODEID_Y(nodeid, bits),
- CMN_NODEID_PID(nodeid), CMN_NODEID_DEVID(nodeid), type);
+ nodeid, nid.x, nid.y, nid.port, nid.dev, type);
return -EINVAL;
}
/*
@@ -1068,11 +1087,10 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
dn->wp_event[wp_idx] = dtc_idx;
writel_relaxed(cfg, dn->pmu_base + CMN_DTM_WPn_CONFIG(wp_idx));
} else {
- unsigned int port = CMN_NODEID_PID(dn->id);
- unsigned int dev = CMN_NODEID_DEVID(dn->id);
+ struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
input_sel = CMN__PMEVCNT0_INPUT_SEL_DEV + dtm_idx +
- (port << 4) + (dev << 2);
+ (nid.port << 4) + (nid.dev << 2);
if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event))) {
int occupid = CMN_EVENT_OCCUPID(event);
--
2.34.1
@@ -1,118 +0,0 @@
From ca15b67dc746c13a8231d11a3e2925f128982a7d Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:54 +0000
Subject: [PATCH 19/40] perf/arm-cmn: Streamline node iteration
Refactor the places where we scan through the set of nodes to switch
from explicit array indexing to pointer-based iteration. This leads to
slightly simpler object code, but also makes the source less dense and
more pleasant for further development. It also unearths an almost-bug
in arm_cmn_event_init() where we've been depending on the "array index"
of NULL relative to cmn->dns being a sufficiently large number, yuck.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/ee0c9eda9a643f46001ac43aadf3f0b1fd5660dd.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index adf50d613734..da7bf779fec2 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -299,11 +299,11 @@ static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
enum cmn_node_type type)
{
- int i;
+ struct arm_cmn_node *dn;
- for (i = 0; i < cmn->num_dns; i++)
- if (cmn->dns[i].type == type)
- return &cmn->dns[i];
+ for (dn = cmn->dns; dn->type; dn++)
+ if (dn->type == type)
+ return dn;
return NULL;
}
@@ -941,8 +941,8 @@ static int arm_cmn_event_init(struct perf_event *event)
{
struct arm_cmn *cmn = to_cmn(event->pmu);
struct arm_cmn_hw_event *hw = to_cmn_hw(event);
+ struct arm_cmn_node *dn;
enum cmn_node_type type;
- unsigned int i;
bool bynodeid;
u16 nodeid, eventid;
@@ -974,10 +974,12 @@ static int arm_cmn_event_init(struct perf_event *event)
nodeid = CMN_EVENT_NODEID(event);
hw->dn = arm_cmn_node(cmn, type);
- for (i = hw->dn - cmn->dns; i < cmn->num_dns && cmn->dns[i].type == type; i++) {
+ if (!hw->dn)
+ return -EINVAL;
+ for (dn = hw->dn; dn->type == type; dn++) {
if (!bynodeid) {
hw->num_dns++;
- } else if (cmn->dns[i].id != nodeid) {
+ } else if (dn->id != nodeid) {
hw->dn++;
} else {
hw->num_dns = 1;
@@ -1332,7 +1334,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
cmn->xps = arm_cmn_node(cmn, CMN_TYPE_XP);
- for (dn = cmn->dns; dn < cmn->dns + cmn->num_dns; dn++) {
+ for (dn = cmn->dns; dn->type; dn++) {
if (dn->type != CMN_TYPE_XP)
arm_cmn_init_node_to_xp(cmn, dn);
else if (cmn->num_dtcs == 1)
@@ -1382,6 +1384,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
u32 xp_offset[CMN_MAX_XPS];
u64 reg;
int i, j;
+ size_t sz;
cfg_region = cmn->base + rgn_offset;
reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
@@ -1408,14 +1411,13 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
cmn->num_dns += FIELD_GET(CMN_CI_CHILD_COUNT, reg);
}
- /* Cheeky +1 to help terminate pointer-based iteration */
- cmn->dns = devm_kcalloc(cmn->dev, cmn->num_dns + 1,
- sizeof(*cmn->dns), GFP_KERNEL);
- if (!cmn->dns)
+ /* Cheeky +1 to help terminate pointer-based iteration later */
+ dn = devm_kcalloc(cmn->dev, cmn->num_dns + 1, sizeof(*dn), GFP_KERNEL);
+ if (!dn)
return -ENOMEM;
/* Pass 2: now we can actually populate the nodes */
- dn = cmn->dns;
+ cmn->dns = dn;
for (i = 0; i < cmn->num_xps; i++) {
void __iomem *xp_region = cmn->base + xp_offset[i];
struct arm_cmn_node *xp = dn++;
@@ -1484,6 +1486,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
/* Correct for any nodes we skipped */
cmn->num_dns = dn - cmn->dns;
+ sz = (void *)(dn + 1) - (void *)cmn->dns;
+ dn = devm_krealloc(cmn->dev, cmn->dns, sz, GFP_KERNEL);
+ if (dn)
+ cmn->dns = dn;
+
/*
* If mesh_x wasn't set during discovery then we never saw
* an XP at (0,1), thus we must have an Nx1 configuration.
--
2.34.1
@@ -1,406 +0,0 @@
From a4c8c0c804b1a92373faceda9350512f2139562a Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:55 +0000
Subject: [PATCH 20/40] perf/arm-cmn: Refactor DTM handling
Untangle DTMs from XPs into a dedicated abstraction. This helps make
things a little more obvious and robust, but primarily paves the way
for further development where new IPs can grow extra DTMs per XP.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/9cca18b1b98f482df7f1aaf3d3213e7f39500423.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 169 +++++++++++++++++++++--------------------
1 file changed, 87 insertions(+), 82 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index da7bf779fec2..8b98ca9666d0 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -35,14 +35,9 @@
#define CMN_CHILD_NODE_ADDR GENMASK(27, 0)
#define CMN_CHILD_NODE_EXTERNAL BIT(31)
-#define CMN_ADDR_NODE_PTR GENMASK(27, 14)
-
-#define CMN_NODE_PTR_DEVID(ptr) (((ptr) >> 2) & 3)
-#define CMN_NODE_PTR_PID(ptr) ((ptr) & 1)
-#define CMN_NODE_PTR_X(ptr, bits) ((ptr) >> (6 + (bits)))
-#define CMN_NODE_PTR_Y(ptr, bits) (((ptr) >> 6) & ((1U << (bits)) - 1))
-
-#define CMN_MAX_XPS (8 * 8)
+#define CMN_MAX_DIMENSION 8
+#define CMN_MAX_XPS (CMN_MAX_DIMENSION * CMN_MAX_DIMENSION)
+#define CMN_MAX_DTMS CMN_MAX_XPS
/* The CFG node has one other useful purpose */
#define CMN_CFGM_PERIPH_ID_2 0x0010
@@ -190,32 +185,32 @@ struct arm_cmn_node {
u16 id, logid;
enum cmn_node_type type;
+ int dtm;
union {
- /* Device node */
+ /* DN/HN-F/CXHA */
struct {
- int to_xp;
- /* DN/HN-F/CXHA */
- unsigned int occupid_val;
- unsigned int occupid_count;
+ u8 occupid_val;
+ u8 occupid_count;
};
/* XP */
- struct {
- int dtc;
- u32 pmu_config_low;
- union {
- u8 input_sel[4];
- __le32 pmu_config_high;
- };
- s8 wp_event[4];
- };
+ int dtc;
};
-
union {
u8 event[4];
__le32 event_sel;
};
};
+struct arm_cmn_dtm {
+ void __iomem *base;
+ u32 pmu_config_low;
+ union {
+ u8 input_sel[4];
+ __le32 pmu_config_high;
+ };
+ s8 wp_event[4];
+};
+
struct arm_cmn_dtc {
void __iomem *base;
int irq;
@@ -241,6 +236,7 @@ struct arm_cmn {
struct arm_cmn_node *xps;
struct arm_cmn_node *dns;
+ struct arm_cmn_dtm *dtms;
struct arm_cmn_dtc *dtc;
unsigned int num_dtcs;
@@ -282,20 +278,14 @@ static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn *cmn, u16 id)
return nid;
}
-static void arm_cmn_init_node_to_xp(const struct arm_cmn *cmn,
- struct arm_cmn_node *dn)
+static struct arm_cmn_node *arm_cmn_node_to_xp(const struct arm_cmn *cmn,
+ const struct arm_cmn_node *dn)
{
struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
int xp_idx = cmn->mesh_x * nid.y + nid.x;
- dn->to_xp = (cmn->xps + xp_idx) - dn;
-}
-
-static struct arm_cmn_node *arm_cmn_node_to_xp(struct arm_cmn_node *dn)
-{
- return dn->type == CMN_TYPE_XP ? dn : dn + dn->to_xp;
+ return cmn->xps + xp_idx;
}
-
static struct arm_cmn_node *arm_cmn_node(const struct arm_cmn *cmn,
enum cmn_node_type type)
{
@@ -706,9 +696,9 @@ static u64 arm_cmn_read_dtm(struct arm_cmn *cmn, struct arm_cmn_hw_event *hw,
offset = snapshot ? CMN_DTM_PMEVCNTSR : CMN_DTM_PMEVCNT;
for_each_hw_dn(hw, dn, i) {
- struct arm_cmn_node *xp = arm_cmn_node_to_xp(dn);
+ struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
- u64 reg = readq_relaxed(xp->pmu_base + offset);
+ u64 reg = readq_relaxed(dtm->base + offset);
u16 dtm_count = reg >> (dtm_idx * 16);
count += dtm_count;
@@ -835,9 +825,9 @@ static void arm_cmn_event_stop(struct perf_event *event, int flags)
}
struct arm_cmn_val {
- u8 dtm_count[CMN_MAX_XPS];
- u8 occupid[CMN_MAX_XPS];
- u8 wp[CMN_MAX_XPS][4];
+ u8 dtm_count[CMN_MAX_DTMS];
+ u8 occupid[CMN_MAX_DTMS];
+ u8 wp[CMN_MAX_DTMS][4];
int dtc_count;
bool cycles;
};
@@ -866,16 +856,16 @@ static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *ev
occupid = 0;
for_each_hw_dn(hw, dn, i) {
- int wp_idx, xp = arm_cmn_node_to_xp(dn)->logid;
+ int wp_idx, dtm = dn->dtm;
- val->dtm_count[xp]++;
- val->occupid[xp] = occupid;
+ val->dtm_count[dtm]++;
+ val->occupid[dtm] = occupid;
if (type != CMN_TYPE_WP)
continue;
wp_idx = arm_cmn_wp_idx(event);
- val->wp[xp][wp_idx] = CMN_EVENT_WP_COMBINE(event) + 1;
+ val->wp[dtm][wp_idx] = CMN_EVENT_WP_COMBINE(event) + 1;
}
}
@@ -914,22 +904,22 @@ static int arm_cmn_validate_group(struct perf_event *event)
occupid = 0;
for_each_hw_dn(hw, dn, i) {
- int wp_idx, wp_cmb, xp = arm_cmn_node_to_xp(dn)->logid;
+ int wp_idx, wp_cmb, dtm = dn->dtm;
- if (val.dtm_count[xp] == CMN_DTM_NUM_COUNTERS)
+ if (val.dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
return -EINVAL;
- if (occupid && val.occupid[xp] && occupid != val.occupid[xp])
+ if (occupid && val.occupid[dtm] && occupid != val.occupid[dtm])
return -EINVAL;
if (type != CMN_TYPE_WP)
continue;
wp_idx = arm_cmn_wp_idx(event);
- if (val.wp[xp][wp_idx])
+ if (val.wp[dtm][wp_idx])
return -EINVAL;
- wp_cmb = val.wp[xp][wp_idx ^ 1];
+ wp_cmb = val.wp[dtm][wp_idx ^ 1];
if (wp_cmb && wp_cmb != CMN_EVENT_WP_COMBINE(event) + 1)
return -EINVAL;
}
@@ -1010,17 +1000,17 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
enum cmn_node_type type = CMN_EVENT_TYPE(event);
while (i--) {
- struct arm_cmn_node *xp = arm_cmn_node_to_xp(hw->dn + i);
+ struct arm_cmn_dtm *dtm = &cmn->dtms[hw->dn[i].dtm];
unsigned int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
if (type == CMN_TYPE_WP)
- hw->dn[i].wp_event[arm_cmn_wp_idx(event)] = -1;
+ dtm->wp_event[arm_cmn_wp_idx(event)] = -1;
if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
hw->dn[i].occupid_count--;
- xp->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
- writel_relaxed(xp->pmu_config_low, xp->pmu_base + CMN_DTM_PMU_CONFIG);
+ dtm->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
+ writel_relaxed(dtm->pmu_config_low, dtm->base + CMN_DTM_PMU_CONFIG);
}
memset(hw->dtm_idx, 0, sizeof(hw->dtm_idx));
@@ -1062,12 +1052,12 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
/* ...then the local counters to feed it. */
for_each_hw_dn(hw, dn, i) {
- struct arm_cmn_node *xp = arm_cmn_node_to_xp(dn);
+ struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
unsigned int dtm_idx, shift;
u64 reg;
dtm_idx = 0;
- while (xp->pmu_config_low & CMN__PMEVCNT_PAIRED(dtm_idx))
+ while (dtm->pmu_config_low & CMN__PMEVCNT_PAIRED(dtm_idx))
if (++dtm_idx == CMN_DTM_NUM_COUNTERS)
goto free_dtms;
@@ -1077,17 +1067,17 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
int tmp, wp_idx = arm_cmn_wp_idx(event);
u32 cfg = arm_cmn_wp_config(event);
- if (dn->wp_event[wp_idx] >= 0)
+ if (dtm->wp_event[wp_idx] >= 0)
goto free_dtms;
- tmp = dn->wp_event[wp_idx ^ 1];
+ tmp = dtm->wp_event[wp_idx ^ 1];
if (tmp >= 0 && CMN_EVENT_WP_COMBINE(event) !=
CMN_EVENT_WP_COMBINE(dtc->counters[tmp]))
goto free_dtms;
input_sel = CMN__PMEVCNT0_INPUT_SEL_WP + wp_idx;
- dn->wp_event[wp_idx] = dtc_idx;
- writel_relaxed(cfg, dn->pmu_base + CMN_DTM_WPn_CONFIG(wp_idx));
+ dtm->wp_event[wp_idx] = dtc_idx;
+ writel_relaxed(cfg, dtm->base + CMN_DTM_WPn_CONFIG(wp_idx));
} else {
struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
@@ -1095,7 +1085,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
(nid.port << 4) + (nid.dev << 2);
if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event))) {
- int occupid = CMN_EVENT_OCCUPID(event);
+ u8 occupid = CMN_EVENT_OCCUPID(event);
if (dn->occupid_count == 0) {
dn->occupid_val = occupid;
@@ -1110,13 +1100,13 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
arm_cmn_set_index(hw->dtm_idx, i, dtm_idx);
- xp->input_sel[dtm_idx] = input_sel;
+ dtm->input_sel[dtm_idx] = input_sel;
shift = CMN__PMEVCNTn_GLOBAL_NUM_SHIFT(dtm_idx);
- xp->pmu_config_low &= ~(CMN__PMEVCNT0_GLOBAL_NUM << shift);
- xp->pmu_config_low |= FIELD_PREP(CMN__PMEVCNT0_GLOBAL_NUM, dtc_idx) << shift;
- xp->pmu_config_low |= CMN__PMEVCNT_PAIRED(dtm_idx);
- reg = (u64)le32_to_cpu(xp->pmu_config_high) << 32 | xp->pmu_config_low;
- writeq_relaxed(reg, xp->pmu_base + CMN_DTM_PMU_CONFIG);
+ dtm->pmu_config_low &= ~(CMN__PMEVCNT0_GLOBAL_NUM << shift);
+ dtm->pmu_config_low |= FIELD_PREP(CMN__PMEVCNT0_GLOBAL_NUM, dtc_idx) << shift;
+ dtm->pmu_config_low |= CMN__PMEVCNT_PAIRED(dtm_idx);
+ reg = (u64)le32_to_cpu(dtm->pmu_config_high) << 32 | dtm->pmu_config_low;
+ writeq_relaxed(reg, dtm->base + CMN_DTM_PMU_CONFIG);
}
/* Go go go! */
@@ -1276,23 +1266,22 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
return 0;
}
-static void arm_cmn_init_dtm(struct arm_cmn_node *xp)
+static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp)
{
int i;
+ dtm->base = xp->pmu_base;
+ dtm->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN;
for (i = 0; i < 4; i++) {
- xp->wp_event[i] = -1;
- writeq_relaxed(0, xp->pmu_base + CMN_DTM_WPn_MASK(i));
- writeq_relaxed(~0ULL, xp->pmu_base + CMN_DTM_WPn_VAL(i));
+ dtm->wp_event[i] = -1;
+ writeq_relaxed(0, dtm->base + CMN_DTM_WPn_MASK(i));
+ writeq_relaxed(~0ULL, dtm->base + CMN_DTM_WPn_VAL(i));
}
- xp->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN;
- xp->dtc = -1;
}
static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int idx)
{
struct arm_cmn_dtc *dtc = cmn->dtc + idx;
- struct arm_cmn_node *xp;
dtc->base = dn->pmu_base - CMN_PMU_OFFSET;
dtc->irq = platform_get_irq(to_platform_device(cmn->dev), idx);
@@ -1303,10 +1292,6 @@ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int id
writel_relaxed(0x1ff, dtc->base + CMN_DT_PMOVSR_CLR);
writel_relaxed(CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR);
- /* We do at least know that a DTC's XP must be in that DTC's domain */
- xp = arm_cmn_node_to_xp(dn);
- xp->dtc = idx;
-
return 0;
}
@@ -1323,7 +1308,7 @@ static int arm_cmn_node_cmp(const void *a, const void *b)
static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
{
- struct arm_cmn_node *dn;
+ struct arm_cmn_node *dn, *xp;
int dtc_idx = 0;
cmn->dtc = devm_kcalloc(cmn->dev, cmn->num_dtcs, sizeof(cmn->dtc[0]), GFP_KERNEL);
@@ -1335,13 +1320,24 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
cmn->xps = arm_cmn_node(cmn, CMN_TYPE_XP);
for (dn = cmn->dns; dn->type; dn++) {
- if (dn->type != CMN_TYPE_XP)
- arm_cmn_init_node_to_xp(cmn, dn);
- else if (cmn->num_dtcs == 1)
- dn->dtc = 0;
+ if (dn->type == CMN_TYPE_XP) {
+ if (dn->dtc < 0 && cmn->num_dtcs == 1)
+ dn->dtc = 0;
+ continue;
+ }
- if (dn->type == CMN_TYPE_DTC)
- arm_cmn_init_dtc(cmn, dn, dtc_idx++);
+ xp = arm_cmn_node_to_xp(cmn, dn);
+ dn->dtm = xp->dtm;
+
+ if (dn->type == CMN_TYPE_DTC) {
+ int err;
+ /* We do at least know that a DTC's XP must be in that DTC's domain */
+ if (xp->dtc < 0)
+ xp->dtc = dtc_idx;
+ err = arm_cmn_init_dtc(cmn, dn, dtc_idx++);
+ if (err)
+ return err;
+ }
/* To the PMU, RN-Ds don't add anything over RN-Is, so smoosh them together */
if (dn->type == CMN_TYPE_RND)
@@ -1380,6 +1376,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
{
void __iomem *cfg_region;
struct arm_cmn_node cfg, *dn;
+ struct arm_cmn_dtm *dtm;
u16 child_count, child_poff;
u32 xp_offset[CMN_MAX_XPS];
u64 reg;
@@ -1416,14 +1413,18 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (!dn)
return -ENOMEM;
+ dtm = devm_kcalloc(cmn->dev, cmn->num_xps, sizeof(*dtm), GFP_KERNEL);
+ if (!dtm)
+ return -ENOMEM;
+
/* Pass 2: now we can actually populate the nodes */
cmn->dns = dn;
+ cmn->dtms = dtm;
for (i = 0; i < cmn->num_xps; i++) {
void __iomem *xp_region = cmn->base + xp_offset[i];
struct arm_cmn_node *xp = dn++;
arm_cmn_init_node_info(cmn, xp_offset[i], xp);
- arm_cmn_init_dtm(xp);
/*
* Thanks to the order in which XP logical IDs seem to be
* assigned, we can handily infer the mesh X dimension by
@@ -1433,6 +1434,10 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (xp->id == (1 << 3))
cmn->mesh_x = xp->logid;
+ xp->dtc = -1;
+ xp->dtm = dtm - cmn->dtms;
+ arm_cmn_init_dtm(dtm++, xp);
+
reg = readq_relaxed(xp_region + CMN_CHILD_INFO);
child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
child_poff = FIELD_GET(CMN_CI_CHILD_PTR_OFFSET, reg);
--
2.34.1
@@ -1,56 +0,0 @@
From 2919ec562ca976a0ae5f70b264379b3d45abdaf5 Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:56 +0000
Subject: [PATCH 21/40] perf/arm-cmn: Optimise DTM counter reads
When multiple nodes of the same type are connected to the same XP
(particularly in CAL configurations), it seems that they are likely
to be consecutive in logical ID. Therefore, we're likely to gain a
small benefit from an easy tweak to optimise out consecutive reads
of the same set of DTM counters for an aggregated event.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/7777d77c2df17693cd3dabb6e268906e15238d82.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 8b98ca9666d0..005a0d83bcac 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -690,18 +690,19 @@ static void arm_cmn_pmu_disable(struct pmu *pmu)
static u64 arm_cmn_read_dtm(struct arm_cmn *cmn, struct arm_cmn_hw_event *hw,
bool snapshot)
{
+ struct arm_cmn_dtm *dtm = NULL;
struct arm_cmn_node *dn;
- unsigned int i, offset;
- u64 count = 0;
+ unsigned int i, offset, dtm_idx;
+ u64 reg, count = 0;
offset = snapshot ? CMN_DTM_PMEVCNTSR : CMN_DTM_PMEVCNT;
for_each_hw_dn(hw, dn, i) {
- struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
- int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
- u64 reg = readq_relaxed(dtm->base + offset);
- u16 dtm_count = reg >> (dtm_idx * 16);
-
- count += dtm_count;
+ if (dtm != &cmn->dtms[dn->dtm]) {
+ dtm = &cmn->dtms[dn->dtm];
+ reg = readq_relaxed(dtm->base + offset);
+ }
+ dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
+ count += (u16)(reg >> (dtm_idx * 16));
}
return count;
}
--
2.34.1
@@ -1,111 +0,0 @@
From 1cf0522e9b4cdad7609c6ce31e848c3d8f2932d5 Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:57 +0000
Subject: [PATCH 22/40] perf/arm-cmn: Optimise DTC counter accesses
In cases where we do know which DTC domain a node belongs to, we can
skip initialising or reading the global count in DTCs where we know
it won't change. The machinery to achieve that is mostly in place
already, so finish hooking it up by converting the vestigial domain
tracking to propagate suitable bitmaps all the way through to events.
Note that this does not allow allocating such an unused counter to a
different event on that DTC, because that is a flippin' nightmare.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/51d930fd945ef51c81f5889ccca055c302b0a1d0.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 29 ++++++++++++-----------------
1 file changed, 12 insertions(+), 17 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 005a0d83bcac..acff8683af2c 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -193,7 +193,7 @@ struct arm_cmn_node {
u8 occupid_count;
};
/* XP */
- int dtc;
+ u8 dtc;
};
union {
u8 event[4];
@@ -968,14 +968,14 @@ static int arm_cmn_event_init(struct perf_event *event)
if (!hw->dn)
return -EINVAL;
for (dn = hw->dn; dn->type == type; dn++) {
- if (!bynodeid) {
- hw->num_dns++;
- } else if (dn->id != nodeid) {
+ if (bynodeid && dn->id != nodeid) {
hw->dn++;
- } else {
- hw->num_dns = 1;
- break;
+ continue;
}
+ hw->dtcs_used |= arm_cmn_node_to_xp(cmn, dn)->dtc;
+ hw->num_dns++;
+ if (bynodeid)
+ break;
}
if (!hw->num_dns) {
@@ -985,11 +985,6 @@ static int arm_cmn_event_init(struct perf_event *event)
nodeid, nid.x, nid.y, nid.port, nid.dev, type);
return -EINVAL;
}
- /*
- * By assuming events count in all DTC domains, we cunningly avoid
- * needing to know anything about how XPs are assigned to domains.
- */
- hw->dtcs_used = (1U << cmn->num_dtcs) - 1;
return arm_cmn_validate_group(event);
}
@@ -1311,6 +1306,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
{
struct arm_cmn_node *dn, *xp;
int dtc_idx = 0;
+ u8 dtcs_present = (1 << cmn->num_dtcs) - 1;
cmn->dtc = devm_kcalloc(cmn->dev, cmn->num_dtcs, sizeof(cmn->dtc[0]), GFP_KERNEL);
if (!cmn->dtc)
@@ -1322,8 +1318,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
for (dn = cmn->dns; dn->type; dn++) {
if (dn->type == CMN_TYPE_XP) {
- if (dn->dtc < 0 && cmn->num_dtcs == 1)
- dn->dtc = 0;
+ dn->dtc &= dtcs_present;
continue;
}
@@ -1333,8 +1328,8 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
if (dn->type == CMN_TYPE_DTC) {
int err;
/* We do at least know that a DTC's XP must be in that DTC's domain */
- if (xp->dtc < 0)
- xp->dtc = dtc_idx;
+ if (xp->dtc == 0xf)
+ xp->dtc = 1 << dtc_idx;
err = arm_cmn_init_dtc(cmn, dn, dtc_idx++);
if (err)
return err;
@@ -1435,7 +1430,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (xp->id == (1 << 3))
cmn->mesh_x = xp->logid;
- xp->dtc = -1;
+ xp->dtc = 0xf;
xp->dtm = dtm - cmn->dtms;
arm_cmn_init_dtm(dtm++, xp);
--
2.34.1
@@ -1,108 +0,0 @@
From 118a6499d8c5d940210c6543309addc97b48122c Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:58 +0000
Subject: [PATCH 23/40] perf/arm-cmn: Move group validation data off-stack
With the value of CMN_MAX_DTMS increasing significantly, our validation
data structure is set to get quite big. Technically we could pack it at
least twice as densely, since we only need around 19 bits of information
per DTM, but that makes the code even more mind-bogglingly impenetrable,
and even half of "quite big" may still be uncomfortably large for a
stack frame (~1KB). Just move it to an off-stack allocation instead.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 43 ++++++++++++++++++++++++------------------
1 file changed, 25 insertions(+), 18 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index acff8683af2c..d2dd02f040b8 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -876,8 +876,8 @@ static int arm_cmn_validate_group(struct perf_event *event)
struct arm_cmn_node *dn;
struct perf_event *sibling, *leader = event->group_leader;
enum cmn_node_type type;
- struct arm_cmn_val val;
- int i;
+ struct arm_cmn_val *val;
+ int i, ret = -EINVAL;
u8 occupid;
if (leader == event)
@@ -886,18 +886,22 @@ static int arm_cmn_validate_group(struct perf_event *event)
if (event->pmu != leader->pmu && !is_software_event(leader))
return -EINVAL;
- memset(&val, 0, sizeof(val));
+ val = kzalloc(sizeof(*val), GFP_KERNEL);
+ if (!val)
+ return -ENOMEM;
- arm_cmn_val_add_event(&val, leader);
+ arm_cmn_val_add_event(val, leader);
for_each_sibling_event(sibling, leader)
- arm_cmn_val_add_event(&val, sibling);
+ arm_cmn_val_add_event(val, sibling);
type = CMN_EVENT_TYPE(event);
- if (type == CMN_TYPE_DTC)
- return val.cycles ? -EINVAL : 0;
+ if (type == CMN_TYPE_DTC) {
+ ret = val->cycles ? -EINVAL : 0;
+ goto done;
+ }
- if (val.dtc_count == CMN_DT_NUM_COUNTERS)
- return -EINVAL;
+ if (val->dtc_count == CMN_DT_NUM_COUNTERS)
+ goto done;
if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
occupid = CMN_EVENT_OCCUPID(event) + 1;
@@ -907,25 +911,28 @@ static int arm_cmn_validate_group(struct perf_event *event)
for_each_hw_dn(hw, dn, i) {
int wp_idx, wp_cmb, dtm = dn->dtm;
- if (val.dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
- return -EINVAL;
+ if (val->dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
+ goto done;
- if (occupid && val.occupid[dtm] && occupid != val.occupid[dtm])
- return -EINVAL;
+ if (occupid && val->occupid[dtm] && occupid != val->occupid[dtm])
+ goto done;
if (type != CMN_TYPE_WP)
continue;
wp_idx = arm_cmn_wp_idx(event);
- if (val.wp[dtm][wp_idx])
- return -EINVAL;
+ if (val->wp[dtm][wp_idx])
+ goto done;
- wp_cmb = val.wp[dtm][wp_idx ^ 1];
+ wp_cmb = val->wp[dtm][wp_idx ^ 1];
if (wp_cmb && wp_cmb != CMN_EVENT_WP_COMBINE(event) + 1)
- return -EINVAL;
+ goto done;
}
- return 0;
+ ret = 0;
+done:
+ kfree(val);
+ return ret;
}
static int arm_cmn_event_init(struct perf_event *event)
--
2.34.1
@@ -1,466 +0,0 @@
From 86d66852aa85254b823578537f8e125915375d0b Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:44:59 +0000
Subject: [PATCH 24/40] perf/arm-cmn: Demarcate CMN-600 specifics
In preparation for supporting newer CMN products, let's introduce a
means to differentiate the features and events which are specific to a
particular IP from those which remain common to the whole family. The
newer designs have also smoothed off some of the rough edges in terms
of discoverability, so separate out the parts of the flow which have
effectively now become CMN-600 quirks.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/9f6368cdca4c821d801138939508a5bba54ccabb.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 313 +++++++++++++++++++++--------------------
1 file changed, 162 insertions(+), 151 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index d2dd02f040b8..ce94f923a607 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -151,7 +151,12 @@
#define CMN_WP_DOWN 2
-/* r0px probably don't exist in silicon, thankfully */
+enum cmn_model {
+ CMN_ANY = -1,
+ CMN600 = 1,
+};
+
+/* CMN-600 r0px shouldn't exist in silicon, thankfully */
enum cmn_revision {
CMN600_R1P0,
CMN600_R1P1,
@@ -159,6 +164,7 @@ enum cmn_revision {
CMN600_R1P3,
CMN600_R2P0,
CMN600_R3P0,
+ CMN600_R3P1,
};
enum cmn_node_type {
@@ -229,6 +235,7 @@ struct arm_cmn {
void __iomem *base;
enum cmn_revision rev;
+ enum cmn_model model;
u8 mesh_x;
u8 mesh_y;
u16 num_xps;
@@ -326,6 +333,7 @@ static unsigned int arm_cmn_get_index(u64 x[], unsigned int pos)
struct arm_cmn_event_attr {
struct device_attribute attr;
+ enum cmn_model model;
enum cmn_node_type type;
u8 eventid;
u8 occupid;
@@ -337,9 +345,10 @@ struct arm_cmn_format_attr {
int config;
};
-#define CMN_EVENT_ATTR(_name, _type, _eventid, _occupid) \
+#define CMN_EVENT_ATTR(_model, _name, _type, _eventid, _occupid) \
(&((struct arm_cmn_event_attr[]) {{ \
.attr = __ATTR(_name, 0444, arm_cmn_event_show, NULL), \
+ .model = _model, \
.type = _type, \
.eventid = _eventid, \
.occupid = _occupid, \
@@ -386,12 +395,15 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
eattr = container_of(attr, typeof(*eattr), attr.attr);
type = eattr->type;
+ if (!(eattr->model & cmn->model))
+ return 0;
+
/* Watchpoints aren't nodes */
if (type == CMN_TYPE_WP)
type = CMN_TYPE_XP;
/* Revision-specific differences */
- if (cmn->rev < CMN600_R1P2) {
+ if (cmn->model == CMN600 && cmn->rev < CMN600_R1P2) {
if (type == CMN_TYPE_HNF && eattr->eventid == 0x1b)
return 0;
}
@@ -402,25 +414,27 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
return attr->mode;
}
-#define _CMN_EVENT_DVM(_name, _event, _occup) \
- CMN_EVENT_ATTR(dn_##_name, CMN_TYPE_DVM, _event, _occup)
+#define _CMN_EVENT_DVM(_model, _name, _event, _occup) \
+ CMN_EVENT_ATTR(_model, dn_##_name, CMN_TYPE_DVM, _event, _occup)
#define CMN_EVENT_DTC(_name) \
- CMN_EVENT_ATTR(dtc_##_name, CMN_TYPE_DTC, 0, 0)
-#define _CMN_EVENT_HNF(_name, _event, _occup) \
- CMN_EVENT_ATTR(hnf_##_name, CMN_TYPE_HNF, _event, _occup)
+ CMN_EVENT_ATTR(CMN_ANY, dtc_##_name, CMN_TYPE_DTC, 0, 0)
+#define _CMN_EVENT_HNF(_model, _name, _event, _occup) \
+ CMN_EVENT_ATTR(_model, hnf_##_name, CMN_TYPE_HNF, _event, _occup)
#define CMN_EVENT_HNI(_name, _event) \
- CMN_EVENT_ATTR(hni_##_name, CMN_TYPE_HNI, _event, 0)
+ CMN_EVENT_ATTR(CMN_ANY, hni_##_name, CMN_TYPE_HNI, _event, 0)
#define __CMN_EVENT_XP(_name, _event) \
- CMN_EVENT_ATTR(mxp_##_name, CMN_TYPE_XP, _event, 0)
-#define CMN_EVENT_SBSX(_name, _event) \
- CMN_EVENT_ATTR(sbsx_##_name, CMN_TYPE_SBSX, _event, 0)
-#define CMN_EVENT_RNID(_name, _event) \
- CMN_EVENT_ATTR(rnid_##_name, CMN_TYPE_RNI, _event, 0)
-
-#define CMN_EVENT_DVM(_name, _event) \
- _CMN_EVENT_DVM(_name, _event, 0)
-#define CMN_EVENT_HNF(_name, _event) \
- _CMN_EVENT_HNF(_name, _event, 0)
+ CMN_EVENT_ATTR(CMN_ANY, mxp_##_name, CMN_TYPE_XP, _event, 0)
+#define CMN_EVENT_SBSX(_model, _name, _event) \
+ CMN_EVENT_ATTR(_model, sbsx_##_name, CMN_TYPE_SBSX, _event, 0)
+#define CMN_EVENT_RNID(_model, _name, _event) \
+ CMN_EVENT_ATTR(_model, rnid_##_name, CMN_TYPE_RNI, _event, 0)
+#define CMN_EVENT_MTSX(_name, _event) \
+ CMN_EVENT_ATTR(CMN_ANY, mtsx_##_name, CMN_TYPE_MTSX, _event, 0)
+
+#define CMN_EVENT_DVM(_model, _name, _event) \
+ _CMN_EVENT_DVM(_model, _name, _event, 0)
+#define CMN_EVENT_HNF(_model, _name, _event) \
+ _CMN_EVENT_HNF(_model, _name, _event, 0)
#define _CMN_EVENT_XP(_name, _event) \
__CMN_EVENT_XP(e_##_name, (_event) | (0 << 2)), \
__CMN_EVENT_XP(w_##_name, (_event) | (1 << 2)), \
@@ -445,115 +459,115 @@ static struct attribute *arm_cmn_event_attrs[] = {
* slot, but our lazy short-cut of using the DTM counter index for
* the PMU index as well happens to avoid that by construction.
*/
- CMN_EVENT_DVM(rxreq_dvmop, 0x01),
- CMN_EVENT_DVM(rxreq_dvmsync, 0x02),
- CMN_EVENT_DVM(rxreq_dvmop_vmid_filtered, 0x03),
- CMN_EVENT_DVM(rxreq_retried, 0x04),
- _CMN_EVENT_DVM(rxreq_trk_occupancy_all, 0x05, 0),
- _CMN_EVENT_DVM(rxreq_trk_occupancy_dvmop, 0x05, 1),
- _CMN_EVENT_DVM(rxreq_trk_occupancy_dvmsync, 0x05, 2),
-
- CMN_EVENT_HNF(cache_miss, 0x01),
- CMN_EVENT_HNF(slc_sf_cache_access, 0x02),
- CMN_EVENT_HNF(cache_fill, 0x03),
- CMN_EVENT_HNF(pocq_retry, 0x04),
- CMN_EVENT_HNF(pocq_reqs_recvd, 0x05),
- CMN_EVENT_HNF(sf_hit, 0x06),
- CMN_EVENT_HNF(sf_evictions, 0x07),
- CMN_EVENT_HNF(dir_snoops_sent, 0x08),
- CMN_EVENT_HNF(brd_snoops_sent, 0x09),
- CMN_EVENT_HNF(slc_eviction, 0x0a),
- CMN_EVENT_HNF(slc_fill_invalid_way, 0x0b),
- CMN_EVENT_HNF(mc_retries, 0x0c),
- CMN_EVENT_HNF(mc_reqs, 0x0d),
- CMN_EVENT_HNF(qos_hh_retry, 0x0e),
- _CMN_EVENT_HNF(qos_pocq_occupancy_all, 0x0f, 0),
- _CMN_EVENT_HNF(qos_pocq_occupancy_read, 0x0f, 1),
- _CMN_EVENT_HNF(qos_pocq_occupancy_write, 0x0f, 2),
- _CMN_EVENT_HNF(qos_pocq_occupancy_atomic, 0x0f, 3),
- _CMN_EVENT_HNF(qos_pocq_occupancy_stash, 0x0f, 4),
- CMN_EVENT_HNF(pocq_addrhaz, 0x10),
- CMN_EVENT_HNF(pocq_atomic_addrhaz, 0x11),
- CMN_EVENT_HNF(ld_st_swp_adq_full, 0x12),
- CMN_EVENT_HNF(cmp_adq_full, 0x13),
- CMN_EVENT_HNF(txdat_stall, 0x14),
- CMN_EVENT_HNF(txrsp_stall, 0x15),
- CMN_EVENT_HNF(seq_full, 0x16),
- CMN_EVENT_HNF(seq_hit, 0x17),
- CMN_EVENT_HNF(snp_sent, 0x18),
- CMN_EVENT_HNF(sfbi_dir_snp_sent, 0x19),
- CMN_EVENT_HNF(sfbi_brd_snp_sent, 0x1a),
- CMN_EVENT_HNF(snp_sent_untrk, 0x1b),
- CMN_EVENT_HNF(intv_dirty, 0x1c),
- CMN_EVENT_HNF(stash_snp_sent, 0x1d),
- CMN_EVENT_HNF(stash_data_pull, 0x1e),
- CMN_EVENT_HNF(snp_fwded, 0x1f),
-
- CMN_EVENT_HNI(rrt_rd_occ_cnt_ovfl, 0x20),
- CMN_EVENT_HNI(rrt_wr_occ_cnt_ovfl, 0x21),
- CMN_EVENT_HNI(rdt_rd_occ_cnt_ovfl, 0x22),
- CMN_EVENT_HNI(rdt_wr_occ_cnt_ovfl, 0x23),
- CMN_EVENT_HNI(wdb_occ_cnt_ovfl, 0x24),
- CMN_EVENT_HNI(rrt_rd_alloc, 0x25),
- CMN_EVENT_HNI(rrt_wr_alloc, 0x26),
- CMN_EVENT_HNI(rdt_rd_alloc, 0x27),
- CMN_EVENT_HNI(rdt_wr_alloc, 0x28),
- CMN_EVENT_HNI(wdb_alloc, 0x29),
- CMN_EVENT_HNI(txrsp_retryack, 0x2a),
- CMN_EVENT_HNI(arvalid_no_arready, 0x2b),
- CMN_EVENT_HNI(arready_no_arvalid, 0x2c),
- CMN_EVENT_HNI(awvalid_no_awready, 0x2d),
- CMN_EVENT_HNI(awready_no_awvalid, 0x2e),
- CMN_EVENT_HNI(wvalid_no_wready, 0x2f),
- CMN_EVENT_HNI(txdat_stall, 0x30),
- CMN_EVENT_HNI(nonpcie_serialization, 0x31),
- CMN_EVENT_HNI(pcie_serialization, 0x32),
-
- CMN_EVENT_XP(txflit_valid, 0x01),
- CMN_EVENT_XP(txflit_stall, 0x02),
- CMN_EVENT_XP(partial_dat_flit, 0x03),
+ CMN_EVENT_DVM(CMN600, rxreq_dvmop, 0x01),
+ CMN_EVENT_DVM(CMN600, rxreq_dvmsync, 0x02),
+ CMN_EVENT_DVM(CMN600, rxreq_dvmop_vmid_filtered, 0x03),
+ CMN_EVENT_DVM(CMN600, rxreq_retried, 0x04),
+ _CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_all, 0x05, 0),
+ _CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmop, 0x05, 1),
+ _CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmsync, 0x05, 2),
+
+ CMN_EVENT_HNF(CMN_ANY, cache_miss, 0x01),
+ CMN_EVENT_HNF(CMN_ANY, slc_sf_cache_access, 0x02),
+ CMN_EVENT_HNF(CMN_ANY, cache_fill, 0x03),
+ CMN_EVENT_HNF(CMN_ANY, pocq_retry, 0x04),
+ CMN_EVENT_HNF(CMN_ANY, pocq_reqs_recvd, 0x05),
+ CMN_EVENT_HNF(CMN_ANY, sf_hit, 0x06),
+ CMN_EVENT_HNF(CMN_ANY, sf_evictions, 0x07),
+ CMN_EVENT_HNF(CMN_ANY, dir_snoops_sent, 0x08),
+ CMN_EVENT_HNF(CMN_ANY, brd_snoops_sent, 0x09),
+ CMN_EVENT_HNF(CMN_ANY, slc_eviction, 0x0a),
+ CMN_EVENT_HNF(CMN_ANY, slc_fill_invalid_way, 0x0b),
+ CMN_EVENT_HNF(CMN_ANY, mc_retries, 0x0c),
+ CMN_EVENT_HNF(CMN_ANY, mc_reqs, 0x0d),
+ CMN_EVENT_HNF(CMN_ANY, qos_hh_retry, 0x0e),
+ _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_all, 0x0f, 0),
+ _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_read, 0x0f, 1),
+ _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_write, 0x0f, 2),
+ _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_atomic, 0x0f, 3),
+ _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_stash, 0x0f, 4),
+ CMN_EVENT_HNF(CMN_ANY, pocq_addrhaz, 0x10),
+ CMN_EVENT_HNF(CMN_ANY, pocq_atomic_addrhaz, 0x11),
+ CMN_EVENT_HNF(CMN_ANY, ld_st_swp_adq_full, 0x12),
+ CMN_EVENT_HNF(CMN_ANY, cmp_adq_full, 0x13),
+ CMN_EVENT_HNF(CMN_ANY, txdat_stall, 0x14),
+ CMN_EVENT_HNF(CMN_ANY, txrsp_stall, 0x15),
+ CMN_EVENT_HNF(CMN_ANY, seq_full, 0x16),
+ CMN_EVENT_HNF(CMN_ANY, seq_hit, 0x17),
+ CMN_EVENT_HNF(CMN_ANY, snp_sent, 0x18),
+ CMN_EVENT_HNF(CMN_ANY, sfbi_dir_snp_sent, 0x19),
+ CMN_EVENT_HNF(CMN_ANY, sfbi_brd_snp_sent, 0x1a),
+ CMN_EVENT_HNF(CMN_ANY, snp_sent_untrk, 0x1b),
+ CMN_EVENT_HNF(CMN_ANY, intv_dirty, 0x1c),
+ CMN_EVENT_HNF(CMN_ANY, stash_snp_sent, 0x1d),
+ CMN_EVENT_HNF(CMN_ANY, stash_data_pull, 0x1e),
+ CMN_EVENT_HNF(CMN_ANY, snp_fwded, 0x1f),
+
+ CMN_EVENT_HNI(rrt_rd_occ_cnt_ovfl, 0x20),
+ CMN_EVENT_HNI(rrt_wr_occ_cnt_ovfl, 0x21),
+ CMN_EVENT_HNI(rdt_rd_occ_cnt_ovfl, 0x22),
+ CMN_EVENT_HNI(rdt_wr_occ_cnt_ovfl, 0x23),
+ CMN_EVENT_HNI(wdb_occ_cnt_ovfl, 0x24),
+ CMN_EVENT_HNI(rrt_rd_alloc, 0x25),
+ CMN_EVENT_HNI(rrt_wr_alloc, 0x26),
+ CMN_EVENT_HNI(rdt_rd_alloc, 0x27),
+ CMN_EVENT_HNI(rdt_wr_alloc, 0x28),
+ CMN_EVENT_HNI(wdb_alloc, 0x29),
+ CMN_EVENT_HNI(txrsp_retryack, 0x2a),
+ CMN_EVENT_HNI(arvalid_no_arready, 0x2b),
+ CMN_EVENT_HNI(arready_no_arvalid, 0x2c),
+ CMN_EVENT_HNI(awvalid_no_awready, 0x2d),
+ CMN_EVENT_HNI(awready_no_awvalid, 0x2e),
+ CMN_EVENT_HNI(wvalid_no_wready, 0x2f),
+ CMN_EVENT_HNI(txdat_stall, 0x30),
+ CMN_EVENT_HNI(nonpcie_serialization, 0x31),
+ CMN_EVENT_HNI(pcie_serialization, 0x32),
+
+ CMN_EVENT_XP(txflit_valid, 0x01),
+ CMN_EVENT_XP(txflit_stall, 0x02),
+ CMN_EVENT_XP(partial_dat_flit, 0x03),
/* We treat watchpoints as a special made-up class of XP events */
- CMN_EVENT_ATTR(watchpoint_up, CMN_TYPE_WP, 0, 0),
- CMN_EVENT_ATTR(watchpoint_down, CMN_TYPE_WP, 2, 0),
-
- CMN_EVENT_SBSX(rd_req, 0x01),
- CMN_EVENT_SBSX(wr_req, 0x02),
- CMN_EVENT_SBSX(cmo_req, 0x03),
- CMN_EVENT_SBSX(txrsp_retryack, 0x04),
- CMN_EVENT_SBSX(txdat_flitv, 0x05),
- CMN_EVENT_SBSX(txrsp_flitv, 0x06),
- CMN_EVENT_SBSX(rd_req_trkr_occ_cnt_ovfl, 0x11),
- CMN_EVENT_SBSX(wr_req_trkr_occ_cnt_ovfl, 0x12),
- CMN_EVENT_SBSX(cmo_req_trkr_occ_cnt_ovfl, 0x13),
- CMN_EVENT_SBSX(wdb_occ_cnt_ovfl, 0x14),
- CMN_EVENT_SBSX(rd_axi_trkr_occ_cnt_ovfl, 0x15),
- CMN_EVENT_SBSX(cmo_axi_trkr_occ_cnt_ovfl, 0x16),
- CMN_EVENT_SBSX(arvalid_no_arready, 0x21),
- CMN_EVENT_SBSX(awvalid_no_awready, 0x22),
- CMN_EVENT_SBSX(wvalid_no_wready, 0x23),
- CMN_EVENT_SBSX(txdat_stall, 0x24),
- CMN_EVENT_SBSX(txrsp_stall, 0x25),
-
- CMN_EVENT_RNID(s0_rdata_beats, 0x01),
- CMN_EVENT_RNID(s1_rdata_beats, 0x02),
- CMN_EVENT_RNID(s2_rdata_beats, 0x03),
- CMN_EVENT_RNID(rxdat_flits, 0x04),
- CMN_EVENT_RNID(txdat_flits, 0x05),
- CMN_EVENT_RNID(txreq_flits_total, 0x06),
- CMN_EVENT_RNID(txreq_flits_retried, 0x07),
- CMN_EVENT_RNID(rrt_occ_ovfl, 0x08),
- CMN_EVENT_RNID(wrt_occ_ovfl, 0x09),
- CMN_EVENT_RNID(txreq_flits_replayed, 0x0a),
- CMN_EVENT_RNID(wrcancel_sent, 0x0b),
- CMN_EVENT_RNID(s0_wdata_beats, 0x0c),
- CMN_EVENT_RNID(s1_wdata_beats, 0x0d),
- CMN_EVENT_RNID(s2_wdata_beats, 0x0e),
- CMN_EVENT_RNID(rrt_alloc, 0x0f),
- CMN_EVENT_RNID(wrt_alloc, 0x10),
- CMN_EVENT_RNID(rdb_unord, 0x11),
- CMN_EVENT_RNID(rdb_replay, 0x12),
- CMN_EVENT_RNID(rdb_hybrid, 0x13),
- CMN_EVENT_RNID(rdb_ord, 0x14),
+ CMN_EVENT_ATTR(CMN_ANY, watchpoint_up, CMN_TYPE_WP, CMN_WP_UP, 0),
+ CMN_EVENT_ATTR(CMN_ANY, watchpoint_down, CMN_TYPE_WP, CMN_WP_DOWN, 0),
+
+ CMN_EVENT_SBSX(CMN_ANY, rd_req, 0x01),
+ CMN_EVENT_SBSX(CMN_ANY, wr_req, 0x02),
+ CMN_EVENT_SBSX(CMN_ANY, cmo_req, 0x03),
+ CMN_EVENT_SBSX(CMN_ANY, txrsp_retryack, 0x04),
+ CMN_EVENT_SBSX(CMN_ANY, txdat_flitv, 0x05),
+ CMN_EVENT_SBSX(CMN_ANY, txrsp_flitv, 0x06),
+ CMN_EVENT_SBSX(CMN_ANY, rd_req_trkr_occ_cnt_ovfl, 0x11),
+ CMN_EVENT_SBSX(CMN_ANY, wr_req_trkr_occ_cnt_ovfl, 0x12),
+ CMN_EVENT_SBSX(CMN_ANY, cmo_req_trkr_occ_cnt_ovfl, 0x13),
+ CMN_EVENT_SBSX(CMN_ANY, wdb_occ_cnt_ovfl, 0x14),
+ CMN_EVENT_SBSX(CMN_ANY, rd_axi_trkr_occ_cnt_ovfl, 0x15),
+ CMN_EVENT_SBSX(CMN_ANY, cmo_axi_trkr_occ_cnt_ovfl, 0x16),
+ CMN_EVENT_SBSX(CMN_ANY, arvalid_no_arready, 0x21),
+ CMN_EVENT_SBSX(CMN_ANY, awvalid_no_awready, 0x22),
+ CMN_EVENT_SBSX(CMN_ANY, wvalid_no_wready, 0x23),
+ CMN_EVENT_SBSX(CMN_ANY, txdat_stall, 0x24),
+ CMN_EVENT_SBSX(CMN_ANY, txrsp_stall, 0x25),
+
+ CMN_EVENT_RNID(CMN_ANY, s0_rdata_beats, 0x01),
+ CMN_EVENT_RNID(CMN_ANY, s1_rdata_beats, 0x02),
+ CMN_EVENT_RNID(CMN_ANY, s2_rdata_beats, 0x03),
+ CMN_EVENT_RNID(CMN_ANY, rxdat_flits, 0x04),
+ CMN_EVENT_RNID(CMN_ANY, txdat_flits, 0x05),
+ CMN_EVENT_RNID(CMN_ANY, txreq_flits_total, 0x06),
+ CMN_EVENT_RNID(CMN_ANY, txreq_flits_retried, 0x07),
+ CMN_EVENT_RNID(CMN_ANY, rrt_occ_ovfl, 0x08),
+ CMN_EVENT_RNID(CMN_ANY, wrt_occ_ovfl, 0x09),
+ CMN_EVENT_RNID(CMN_ANY, txreq_flits_replayed, 0x0a),
+ CMN_EVENT_RNID(CMN_ANY, wrcancel_sent, 0x0b),
+ CMN_EVENT_RNID(CMN_ANY, s0_wdata_beats, 0x0c),
+ CMN_EVENT_RNID(CMN_ANY, s1_wdata_beats, 0x0d),
+ CMN_EVENT_RNID(CMN_ANY, s2_wdata_beats, 0x0e),
+ CMN_EVENT_RNID(CMN_ANY, rrt_alloc, 0x0f),
+ CMN_EVENT_RNID(CMN_ANY, wrt_alloc, 0x10),
+ CMN_EVENT_RNID(CMN600, rdb_unord, 0x11),
+ CMN_EVENT_RNID(CMN600, rdb_replay, 0x12),
+ CMN_EVENT_RNID(CMN600, rdb_hybrid, 0x13),
+ CMN_EVENT_RNID(CMN600, rdb_ord, 0x14),
NULL
};
@@ -1386,15 +1400,14 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
int i, j;
size_t sz;
- cfg_region = cmn->base + rgn_offset;
- reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
- cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
- dev_dbg(cmn->dev, "periph_id_2 revision: %d\n", cmn->rev);
-
arm_cmn_init_node_info(cmn, rgn_offset, &cfg);
if (cfg.type != CMN_TYPE_CFG)
return -ENODEV;
+ cfg_region = cmn->base + rgn_offset;
+ reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
+ cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
+
reg = readq_relaxed(cfg_region + CMN_CHILD_INFO);
child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
child_poff = FIELD_GET(CMN_CI_CHILD_PTR_OFFSET, reg);
@@ -1507,13 +1520,14 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
cmn->mesh_x = cmn->num_xps;
cmn->mesh_y = cmn->num_xps / cmn->mesh_x;
+ dev_dbg(cmn->dev, "model %d, periph_id_2 revision %d\n", cmn->model, cmn->rev);
dev_dbg(cmn->dev, "mesh %dx%d, ID width %d\n",
cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn));
return 0;
}
-static int arm_cmn_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn)
+static int arm_cmn600_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn)
{
struct resource *cfg, *root;
@@ -1540,21 +1554,11 @@ static int arm_cmn_acpi_probe(struct platform_device *pdev, struct arm_cmn *cmn)
return root->start - cfg->start;
}
-static int arm_cmn_of_probe(struct platform_device *pdev, struct arm_cmn *cmn)
+static int arm_cmn600_of_probe(struct device_node *np)
{
- struct device_node *np = pdev->dev.of_node;
u32 rootnode;
- int ret;
- cmn->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(cmn->base))
- return PTR_ERR(cmn->base);
-
- ret = of_property_read_u32(np, "arm,root-node", &rootnode);
- if (ret)
- return ret;
-
- return rootnode;
+ return of_property_read_u32(np, "arm,root-node", &rootnode) ?: rootnode;
}
static int arm_cmn_probe(struct platform_device *pdev)
@@ -1569,12 +1573,19 @@ static int arm_cmn_probe(struct platform_device *pdev)
return -ENOMEM;
cmn->dev = &pdev->dev;
+ cmn->model = (unsigned long)device_get_match_data(cmn->dev);
platform_set_drvdata(pdev, cmn);
- if (has_acpi_companion(cmn->dev))
- rootnode = arm_cmn_acpi_probe(pdev, cmn);
- else
- rootnode = arm_cmn_of_probe(pdev, cmn);
+ if (cmn->model == CMN600 && has_acpi_companion(cmn->dev)) {
+ rootnode = arm_cmn600_acpi_probe(pdev, cmn);
+ } else {
+ rootnode = 0;
+ cmn->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(cmn->base))
+ return PTR_ERR(cmn->base);
+ if (cmn->model == CMN600)
+ rootnode = arm_cmn600_of_probe(pdev->dev.of_node);
+ }
if (rootnode < 0)
return rootnode;
@@ -1637,7 +1648,7 @@ static int arm_cmn_remove(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id arm_cmn_of_match[] = {
- { .compatible = "arm,cmn-600", },
+ { .compatible = "arm,cmn-600", .data = (void *)CMN600 },
{}
};
MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
@@ -1645,7 +1656,7 @@ MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id arm_cmn_acpi_match[] = {
- { "ARMHC600", },
+ { "ARMHC600", CMN600 },
{}
};
MODULE_DEVICE_TABLE(acpi, arm_cmn_acpi_match);
--
2.34.1
@@ -1,548 +0,0 @@
From 821c1c36ba8883a8709bbbcdf4ebc716e69da991 Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:45:00 +0000
Subject: [PATCH 25/40] perf/arm-cmn: Support new IP features
The second generation of CMN IPs add new node types and significantly
expand the configuration space with options for extra device ports on
edge XPs, either plumbed into the regular DTM or with extra dedicated
DTMs to monitor them, plus larger (and smaller) mesh sizes. Add basic
support for pulling this new information out of the hardware, piping
it around as necessary, and handling (most of) the new choices.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/e58b495bcc7deec3882be4bac910ed0bf6979674.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/e58b495bcc7deec3882be4bac910ed0bf6979674.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
---
drivers/perf/arm-cmn.c | 218 ++++++++++++++++++++++++++++++++---------
1 file changed, 171 insertions(+), 47 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index ce94f923a607..0a3f33a83c01 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -24,7 +24,10 @@
#define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32)
#define CMN_NODEID_DEVID(reg) ((reg) & 3)
+#define CMN_NODEID_EXT_DEVID(reg) ((reg) & 1)
#define CMN_NODEID_PID(reg) (((reg) >> 2) & 1)
+#define CMN_NODEID_EXT_PID(reg) (((reg) >> 1) & 3)
+#define CMN_NODEID_1x1_PID(reg) (((reg) >> 2) & 7)
#define CMN_NODEID_X(reg, bits) ((reg) >> (3 + (bits)))
#define CMN_NODEID_Y(reg, bits) (((reg) >> 3) & ((1U << (bits)) - 1))
@@ -37,13 +40,26 @@
#define CMN_MAX_DIMENSION 8
#define CMN_MAX_XPS (CMN_MAX_DIMENSION * CMN_MAX_DIMENSION)
-#define CMN_MAX_DTMS CMN_MAX_XPS
+#define CMN_MAX_DTMS (CMN_MAX_XPS + (CMN_MAX_DIMENSION - 1) * 4)
-/* The CFG node has one other useful purpose */
+/* The CFG node has various info besides the discovery tree */
#define CMN_CFGM_PERIPH_ID_2 0x0010
#define CMN_CFGM_PID2_REVISION GENMASK(7, 4)
-/* PMU registers occupy the 3rd 4KB page of each node's 16KB space */
+#define CMN_CFGM_INFO_GLOBAL 0x900
+#define CMN_INFO_MULTIPLE_DTM_EN BIT_ULL(63)
+#define CMN_INFO_RSP_VC_NUM GENMASK_ULL(53, 52)
+#define CMN_INFO_DAT_VC_NUM GENMASK_ULL(51, 50)
+
+/* XPs also have some local topology info which has uses too */
+#define CMN_MXP__CONNECT_INFO_P0 0x0008
+#define CMN_MXP__CONNECT_INFO_P1 0x0010
+#define CMN_MXP__CONNECT_INFO_P2 0x0028
+#define CMN_MXP__CONNECT_INFO_P3 0x0030
+#define CMN_MXP__CONNECT_INFO_P4 0x0038
+#define CMN_MXP__CONNECT_INFO_P5 0x0040
+
+/* PMU registers occupy the 3rd 4KB page of each node's region */
#define CMN_PMU_OFFSET 0x2000
/* For most nodes, this is all there is */
@@ -53,6 +69,7 @@
/* DTMs live in the PMU space of XP registers */
#define CMN_DTM_WPn(n) (0x1A0 + (n) * 0x18)
#define CMN_DTM_WPn_CONFIG(n) (CMN_DTM_WPn(n) + 0x00)
+#define CMN_DTM_WPn_CONFIG_WP_DEV_SEL2 GENMASK_ULL(18,17)
#define CMN_DTM_WPn_CONFIG_WP_COMBINE BIT(6)
#define CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE BIT(5)
#define CMN_DTM_WPn_CONFIG_WP_GRP BIT(4)
@@ -77,7 +94,11 @@
#define CMN_DTM_PMEVCNTSR 0x240
+#define CMN_DTM_UNIT_INFO 0x0910
+
#define CMN_DTM_NUM_COUNTERS 4
+/* Want more local counters? Why not replicate the whole DTM! Ugh... */
+#define CMN_DTM_OFFSET(n) ((n) * 0x200)
/* The DTC node is where the magic happens */
#define CMN_DT_DTC_CTL 0x0a00
@@ -131,10 +152,10 @@
#define CMN_EVENT_NODEID(event) FIELD_GET(CMN_CONFIG_NODEID, (event)->attr.config)
#define CMN_CONFIG_WP_COMBINE GENMASK_ULL(27, 24)
-#define CMN_CONFIG_WP_DEV_SEL BIT_ULL(48)
-#define CMN_CONFIG_WP_CHN_SEL GENMASK_ULL(50, 49)
-#define CMN_CONFIG_WP_GRP BIT_ULL(52)
-#define CMN_CONFIG_WP_EXCLUSIVE BIT_ULL(53)
+#define CMN_CONFIG_WP_DEV_SEL GENMASK_ULL(50, 48)
+#define CMN_CONFIG_WP_CHN_SEL GENMASK_ULL(55, 51)
+#define CMN_CONFIG_WP_GRP BIT_ULL(56)
+#define CMN_CONFIG_WP_EXCLUSIVE BIT_ULL(57)
#define CMN_CONFIG1_WP_VAL GENMASK_ULL(63, 0)
#define CMN_CONFIG2_WP_MASK GENMASK_ULL(63, 0)
@@ -176,9 +197,12 @@ enum cmn_node_type {
CMN_TYPE_HNF,
CMN_TYPE_XP,
CMN_TYPE_SBSX,
- CMN_TYPE_RNI = 0xa,
+ CMN_TYPE_MPAM_S,
+ CMN_TYPE_MPAM_NS,
+ CMN_TYPE_RNI,
CMN_TYPE_RND = 0xd,
CMN_TYPE_RNSAM = 0xf,
+ CMN_TYPE_MTSX,
CMN_TYPE_CXRA = 0x100,
CMN_TYPE_CXHA = 0x101,
CMN_TYPE_CXLA = 0x102,
@@ -233,6 +257,7 @@ struct arm_cmn_dtc {
struct arm_cmn {
struct device *dev;
void __iomem *base;
+ unsigned int state;
enum cmn_revision rev;
enum cmn_model model;
@@ -240,6 +265,13 @@ struct arm_cmn {
u8 mesh_y;
u16 num_xps;
u16 num_dns;
+ bool multi_dtm;
+ u8 ports_used;
+ struct {
+ unsigned int rsp_vc_num : 2;
+ unsigned int dat_vc_num : 2;
+ };
+
struct arm_cmn_node *xps;
struct arm_cmn_node *dns;
@@ -250,7 +282,6 @@ struct arm_cmn {
int cpu;
struct hlist_node cpuhp_node;
- unsigned int state;
struct pmu pmu;
};
@@ -275,13 +306,25 @@ static int arm_cmn_xyidbits(const struct arm_cmn *cmn)
static struct arm_cmn_nodeid arm_cmn_nid(const struct arm_cmn *cmn, u16 id)
{
struct arm_cmn_nodeid nid;
- int bits = arm_cmn_xyidbits(cmn);
- nid.x = CMN_NODEID_X(id, bits);
- nid.y = CMN_NODEID_Y(id, bits);
- nid.port = CMN_NODEID_PID(id);
- nid.dev = CMN_NODEID_DEVID(id);
+ if (cmn->num_xps == 1) {
+ nid.x = 0;
+ nid.y = 0;
+ nid.port = CMN_NODEID_1x1_PID(id);
+ nid.dev = CMN_NODEID_DEVID(id);
+ } else {
+ int bits = arm_cmn_xyidbits(cmn);
+ nid.x = CMN_NODEID_X(id, bits);
+ nid.y = CMN_NODEID_Y(id, bits);
+ if (cmn->ports_used & 0xc) {
+ nid.port = CMN_NODEID_EXT_PID(id);
+ nid.dev = CMN_NODEID_EXT_DEVID(id);
+ } else {
+ nid.port = CMN_NODEID_PID(id);
+ nid.dev = CMN_NODEID_DEVID(id);
+ }
+ }
return nid;
}
@@ -310,6 +353,7 @@ struct arm_cmn_hw_event {
unsigned int dtc_idx;
u8 dtcs_used;
u8 num_dns;
+ u8 dtm_offset;
};
#define for_each_hw_dn(hw, dn, i) \
@@ -354,7 +398,8 @@ struct arm_cmn_format_attr {
.occupid = _occupid, \
}})[0].attr.attr)
-static bool arm_cmn_is_occup_event(enum cmn_node_type type, unsigned int id)
+static bool arm_cmn_is_occup_event(enum cmn_model model,
+ enum cmn_node_type type, unsigned int id)
{
return (type == CMN_TYPE_DVM && id == 0x05) ||
(type == CMN_TYPE_HNF && id == 0x0f);
@@ -375,7 +420,7 @@ static ssize_t arm_cmn_event_show(struct device *dev,
"type=0x%x,eventid=0x%x,wp_dev_sel=?,wp_chn_sel=?,wp_grp=?,wp_val=?,wp_mask=?\n",
eattr->type, eattr->eventid);
- if (arm_cmn_is_occup_event(eattr->type, eattr->eventid))
+ if (arm_cmn_is_occup_event(eattr->model, eattr->type, eattr->eventid))
return sysfs_emit(buf, "type=0x%x,eventid=0x%x,occupid=0x%x\n",
eattr->type, eattr->eventid, eattr->occupid);
@@ -390,25 +435,36 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj);
struct arm_cmn *cmn = to_cmn(dev_get_drvdata(dev));
struct arm_cmn_event_attr *eattr;
- enum cmn_node_type type;
eattr = container_of(attr, typeof(*eattr), attr.attr);
- type = eattr->type;
if (!(eattr->model & cmn->model))
return 0;
- /* Watchpoints aren't nodes */
- if (type == CMN_TYPE_WP)
- type = CMN_TYPE_XP;
+ /* Watchpoints aren't nodes, so avoid confusion */
+ if (eattr->type == CMN_TYPE_WP)
+ return attr->mode;
+
+ /* Hide XP events for unused interfaces/channels */
+ if (eattr->type == CMN_TYPE_XP) {
+ unsigned int intf = (eattr->eventid >> 2) & 7;
+ unsigned int chan = eattr->eventid >> 5;
+
+ if ((intf & 4) && !(cmn->ports_used & BIT(intf & 3)))
+ return 0;
+
+ if ((chan == 5 && cmn->rsp_vc_num < 2) ||
+ (chan == 6 && cmn->dat_vc_num < 2))
+ return 0;
+ }
/* Revision-specific differences */
if (cmn->model == CMN600 && cmn->rev < CMN600_R1P2) {
- if (type == CMN_TYPE_HNF && eattr->eventid == 0x1b)
+ if (eattr->type == CMN_TYPE_HNF && eattr->eventid == 0x1b)
return 0;
}
- if (!arm_cmn_node(cmn, type))
+ if (!arm_cmn_node(cmn, eattr->type))
return 0;
return attr->mode;
@@ -669,7 +725,8 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_GRP, grp) |
- FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE, exc);
+ FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE, exc) |
+ FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >> 1);
if (combine && !grp)
config |= CMN_DTM_WPn_CONFIG_WP_COMBINE;
@@ -712,7 +769,7 @@ static u64 arm_cmn_read_dtm(struct arm_cmn *cmn, struct arm_cmn_hw_event *hw,
offset = snapshot ? CMN_DTM_PMEVCNTSR : CMN_DTM_PMEVCNT;
for_each_hw_dn(hw, dn, i) {
if (dtm != &cmn->dtms[dn->dtm]) {
- dtm = &cmn->dtms[dn->dtm];
+ dtm = &cmn->dtms[dn->dtm] + hw->dtm_offset;
reg = readq_relaxed(dtm->base + offset);
}
dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
@@ -800,8 +857,10 @@ static void arm_cmn_event_start(struct perf_event *event, int flags)
u64 mask = CMN_EVENT_WP_MASK(event);
for_each_hw_dn(hw, dn, i) {
- writeq_relaxed(val, dn->pmu_base + CMN_DTM_WPn_VAL(wp_idx));
- writeq_relaxed(mask, dn->pmu_base + CMN_DTM_WPn_MASK(wp_idx));
+ void __iomem *base = dn->pmu_base + CMN_DTM_OFFSET(hw->dtm_offset);
+
+ writeq_relaxed(val, base + CMN_DTM_WPn_VAL(wp_idx));
+ writeq_relaxed(mask, base + CMN_DTM_WPn_MASK(wp_idx));
}
} else for_each_hw_dn(hw, dn, i) {
int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
@@ -826,8 +885,10 @@ static void arm_cmn_event_stop(struct perf_event *event, int flags)
int wp_idx = arm_cmn_wp_idx(event);
for_each_hw_dn(hw, dn, i) {
- writeq_relaxed(0, dn->pmu_base + CMN_DTM_WPn_MASK(wp_idx));
- writeq_relaxed(~0ULL, dn->pmu_base + CMN_DTM_WPn_VAL(wp_idx));
+ void __iomem *base = dn->pmu_base + CMN_DTM_OFFSET(hw->dtm_offset);
+
+ writeq_relaxed(0, base + CMN_DTM_WPn_MASK(wp_idx));
+ writeq_relaxed(~0ULL, base + CMN_DTM_WPn_VAL(wp_idx));
}
} else for_each_hw_dn(hw, dn, i) {
int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
@@ -847,7 +908,8 @@ struct arm_cmn_val {
bool cycles;
};
-static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *event)
+static void arm_cmn_val_add_event(struct arm_cmn *cmn, struct arm_cmn_val *val,
+ struct perf_event *event)
{
struct arm_cmn_hw_event *hw = to_cmn_hw(event);
struct arm_cmn_node *dn;
@@ -865,7 +927,7 @@ static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *ev
}
val->dtc_count++;
- if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
+ if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event)))
occupid = CMN_EVENT_OCCUPID(event) + 1;
else
occupid = 0;
@@ -884,7 +946,7 @@ static void arm_cmn_val_add_event(struct arm_cmn_val *val, struct perf_event *ev
}
}
-static int arm_cmn_validate_group(struct perf_event *event)
+static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
{
struct arm_cmn_hw_event *hw = to_cmn_hw(event);
struct arm_cmn_node *dn;
@@ -904,9 +966,9 @@ static int arm_cmn_validate_group(struct perf_event *event)
if (!val)
return -ENOMEM;
- arm_cmn_val_add_event(val, leader);
+ arm_cmn_val_add_event(cmn, val, leader);
for_each_sibling_event(sibling, leader)
- arm_cmn_val_add_event(val, sibling);
+ arm_cmn_val_add_event(cmn, val, sibling);
type = CMN_EVENT_TYPE(event);
if (type == CMN_TYPE_DTC) {
@@ -917,7 +979,7 @@ static int arm_cmn_validate_group(struct perf_event *event)
if (val->dtc_count == CMN_DT_NUM_COUNTERS)
goto done;
- if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
+ if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event)))
occupid = CMN_EVENT_OCCUPID(event) + 1;
else
occupid = 0;
@@ -980,6 +1042,9 @@ static int arm_cmn_event_init(struct perf_event *event)
eventid = CMN_EVENT_EVENTID(event);
if (eventid != CMN_WP_UP && eventid != CMN_WP_DOWN)
return -EINVAL;
+ /* ...but the DTM may depend on which port we're watching */
+ if (cmn->multi_dtm)
+ hw->dtm_offset = CMN_EVENT_WP_DEV_SEL(event) / 2;
}
bynodeid = CMN_EVENT_BYNODEID(event);
@@ -1007,7 +1072,7 @@ static int arm_cmn_event_init(struct perf_event *event)
return -EINVAL;
}
- return arm_cmn_validate_group(event);
+ return arm_cmn_validate_group(cmn, event);
}
static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
@@ -1017,13 +1082,13 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
enum cmn_node_type type = CMN_EVENT_TYPE(event);
while (i--) {
- struct arm_cmn_dtm *dtm = &cmn->dtms[hw->dn[i].dtm];
+ struct arm_cmn_dtm *dtm = &cmn->dtms[hw->dn[i].dtm] + hw->dtm_offset;
unsigned int dtm_idx = arm_cmn_get_index(hw->dtm_idx, i);
if (type == CMN_TYPE_WP)
dtm->wp_event[arm_cmn_wp_idx(event)] = -1;
- if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event)))
+ if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event)))
hw->dn[i].occupid_count--;
dtm->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
@@ -1069,7 +1134,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
/* ...then the local counters to feed it. */
for_each_hw_dn(hw, dn, i) {
- struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm];
+ struct arm_cmn_dtm *dtm = &cmn->dtms[dn->dtm] + hw->dtm_offset;
unsigned int dtm_idx, shift;
u64 reg;
@@ -1098,10 +1163,13 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
} else {
struct arm_cmn_nodeid nid = arm_cmn_nid(cmn, dn->id);
+ if (cmn->multi_dtm)
+ nid.port %= 2;
+
input_sel = CMN__PMEVCNT0_INPUT_SEL_DEV + dtm_idx +
(nid.port << 4) + (nid.dev << 2);
- if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event))) {
+ if (arm_cmn_is_occup_event(cmn->model, type, CMN_EVENT_EVENTID(event))) {
u8 occupid = CMN_EVENT_OCCUPID(event);
if (dn->occupid_count == 0) {
@@ -1283,11 +1351,11 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
return 0;
}
-static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp)
+static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp, int idx)
{
int i;
- dtm->base = xp->pmu_base;
+ dtm->base = xp->pmu_base + CMN_DTM_OFFSET(idx);
dtm->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN;
for (i = 0; i < 4; i++) {
dtm->wp_event[i] = -1;
@@ -1345,6 +1413,8 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
xp = arm_cmn_node_to_xp(cmn, dn);
dn->dtm = xp->dtm;
+ if (cmn->multi_dtm)
+ dn->dtm += arm_cmn_nid(cmn, dn->id).port / 2;
if (dn->type == CMN_TYPE_DTC) {
int err;
@@ -1408,6 +1478,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_2);
cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
+ reg = readq_relaxed(cfg_region + CMN_CFGM_INFO_GLOBAL);
+ cmn->multi_dtm = reg & CMN_INFO_MULTIPLE_DTM_EN;
+ cmn->rsp_vc_num = FIELD_GET(CMN_INFO_RSP_VC_NUM, reg);
+ cmn->dat_vc_num = FIELD_GET(CMN_INFO_DAT_VC_NUM, reg);
+
reg = readq_relaxed(cfg_region + CMN_CHILD_INFO);
child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
child_poff = FIELD_GET(CMN_CI_CHILD_PTR_OFFSET, reg);
@@ -1429,7 +1504,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (!dn)
return -ENOMEM;
- dtm = devm_kcalloc(cmn->dev, cmn->num_xps, sizeof(*dtm), GFP_KERNEL);
+ /* Initial safe upper bound on DTMs for any possible mesh layout */
+ i = cmn->num_xps;
+ if (cmn->multi_dtm)
+ i += cmn->num_xps + 1;
+ dtm = devm_kcalloc(cmn->dev, i, sizeof(*dtm), GFP_KERNEL);
if (!dtm)
return -ENOMEM;
@@ -1439,6 +1518,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
for (i = 0; i < cmn->num_xps; i++) {
void __iomem *xp_region = cmn->base + xp_offset[i];
struct arm_cmn_node *xp = dn++;
+ unsigned int xp_ports = 0;
arm_cmn_init_node_info(cmn, xp_offset[i], xp);
/*
@@ -1450,9 +1530,39 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (xp->id == (1 << 3))
cmn->mesh_x = xp->logid;
- xp->dtc = 0xf;
+ if (cmn->model == CMN600)
+ xp->dtc = 0xf;
+ else
+ xp->dtc = 1 << readl_relaxed(xp_region + CMN_DTM_UNIT_INFO);
+
xp->dtm = dtm - cmn->dtms;
- arm_cmn_init_dtm(dtm++, xp);
+ arm_cmn_init_dtm(dtm++, xp, 0);
+ /*
+ * Keeping track of connected ports will let us filter out
+ * unnecessary XP events easily. We can also reliably infer the
+ * "extra device ports" configuration for the node ID format
+ * from this, since in that case we will see at least one XP
+ * with port 2 connected, for the HN-D.
+ */
+ if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P0))
+ xp_ports |= BIT(0);
+ if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P1))
+ xp_ports |= BIT(1);
+ if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P2))
+ xp_ports |= BIT(2);
+ if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P3))
+ xp_ports |= BIT(3);
+ if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P4))
+ xp_ports |= BIT(4);
+ if (readq_relaxed(xp_region + CMN_MXP__CONNECT_INFO_P5))
+ xp_ports |= BIT(5);
+
+ if (cmn->multi_dtm && (xp_ports & 0xc))
+ arm_cmn_init_dtm(dtm++, xp, 1);
+ if (cmn->multi_dtm && (xp_ports & 0x30))
+ arm_cmn_init_dtm(dtm++, xp, 2);
+
+ cmn->ports_used |= xp_ports;
reg = readq_relaxed(xp_region + CMN_CHILD_INFO);
child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
@@ -1488,11 +1598,14 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
case CMN_TYPE_SBSX:
case CMN_TYPE_RNI:
case CMN_TYPE_RND:
+ case CMN_TYPE_MTSX:
case CMN_TYPE_CXRA:
case CMN_TYPE_CXHA:
dn++;
break;
/* Nothing to see here */
+ case CMN_TYPE_MPAM_S:
+ case CMN_TYPE_MPAM_NS:
case CMN_TYPE_RNSAM:
case CMN_TYPE_CXLA:
break;
@@ -1512,6 +1625,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
if (dn)
cmn->dns = dn;
+ sz = (void *)dtm - (void *)cmn->dtms;
+ dtm = devm_krealloc(cmn->dev, cmn->dtms, sz, GFP_KERNEL);
+ if (dtm)
+ cmn->dtms = dtm;
+
/*
* If mesh_x wasn't set during discovery then we never saw
* an XP at (0,1), thus we must have an Nx1 configuration.
@@ -1520,9 +1638,15 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
cmn->mesh_x = cmn->num_xps;
cmn->mesh_y = cmn->num_xps / cmn->mesh_x;
+ /* 1x1 config plays havoc with XP event encodings */
+ if (cmn->num_xps == 1)
+ dev_warn(cmn->dev, "1x1 config not fully supported, translate XP events manually\n");
+
dev_dbg(cmn->dev, "model %d, periph_id_2 revision %d\n", cmn->model, cmn->rev);
- dev_dbg(cmn->dev, "mesh %dx%d, ID width %d\n",
- cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn));
+ reg = cmn->ports_used;
+ dev_dbg(cmn->dev, "mesh %dx%d, ID width %d, ports %6pbl%s\n",
+ cmn->mesh_x, cmn->mesh_y, arm_cmn_xyidbits(cmn), &reg,
+ cmn->multi_dtm ? ", multi-DTM" : "");
return 0;
}
--
2.34.1
@@ -1,150 +0,0 @@
From 806c281f4307dd321fe8a38ce557e8c983c3ce84 Mon Sep 17 00:00:00 2001
From: Robin Murphy <robin.murphy@arm.com>
Date: Fri, 3 Dec 2021 11:45:02 +0000
Subject: [PATCH 26/40] perf/arm-cmn: Add CI-700 Support
Add the identifiers and events for the CI-700 coherent interconnect.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Link: https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530442.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Upstream-Status: Backport [https://lore.kernel.org/r/28f566ab23a83733c6c9ef9414c010b760b4549c.1638530442.git.robin.murphy@arm.com]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com>
---
drivers/perf/arm-cmn.c | 57 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 53 insertions(+), 4 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 0a3f33a83c01..28ab87a6cde4 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -175,6 +175,7 @@
enum cmn_model {
CMN_ANY = -1,
CMN600 = 1,
+ CI700 = 2,
};
/* CMN-600 r0px shouldn't exist in silicon, thankfully */
@@ -186,6 +187,9 @@ enum cmn_revision {
CMN600_R2P0,
CMN600_R3P0,
CMN600_R3P1,
+ CI700_R0P0 = 0,
+ CI700_R1P0,
+ CI700_R2P0,
};
enum cmn_node_type {
@@ -401,8 +405,10 @@ struct arm_cmn_format_attr {
static bool arm_cmn_is_occup_event(enum cmn_model model,
enum cmn_node_type type, unsigned int id)
{
- return (type == CMN_TYPE_DVM && id == 0x05) ||
- (type == CMN_TYPE_HNF && id == 0x0f);
+ if (type == CMN_TYPE_DVM)
+ return (model == CMN600 && id == 0x05) ||
+ (model == CI700 && id == 0x0c);
+ return type == CMN_TYPE_HNF && id == 0x0f;
}
static ssize_t arm_cmn_event_show(struct device *dev,
@@ -497,14 +503,19 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
__CMN_EVENT_XP(n_##_name, (_event) | (2 << 2)), \
__CMN_EVENT_XP(s_##_name, (_event) | (3 << 2)), \
__CMN_EVENT_XP(p0_##_name, (_event) | (4 << 2)), \
- __CMN_EVENT_XP(p1_##_name, (_event) | (5 << 2))
+ __CMN_EVENT_XP(p1_##_name, (_event) | (5 << 2)), \
+ __CMN_EVENT_XP(p2_##_name, (_event) | (6 << 2)), \
+ __CMN_EVENT_XP(p3_##_name, (_event) | (7 << 2))
/* Good thing there are only 3 fundamental XP events... */
#define CMN_EVENT_XP(_name, _event) \
_CMN_EVENT_XP(req_##_name, (_event) | (0 << 5)), \
_CMN_EVENT_XP(rsp_##_name, (_event) | (1 << 5)), \
_CMN_EVENT_XP(snp_##_name, (_event) | (2 << 5)), \
- _CMN_EVENT_XP(dat_##_name, (_event) | (3 << 5))
+ _CMN_EVENT_XP(dat_##_name, (_event) | (3 << 5)), \
+ _CMN_EVENT_XP(pub_##_name, (_event) | (4 << 5)), \
+ _CMN_EVENT_XP(rsp2_##_name, (_event) | (5 << 5)), \
+ _CMN_EVENT_XP(dat2_##_name, (_event) | (6 << 5))
static struct attribute *arm_cmn_event_attrs[] = {
@@ -522,6 +533,20 @@ static struct attribute *arm_cmn_event_attrs[] = {
_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_all, 0x05, 0),
_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmop, 0x05, 1),
_CMN_EVENT_DVM(CMN600, rxreq_trk_occupancy_dvmsync, 0x05, 2),
+ CMN_EVENT_DVM(CI700, dvmop_tlbi, 0x01),
+ CMN_EVENT_DVM(CI700, dvmop_bpi, 0x02),
+ CMN_EVENT_DVM(CI700, dvmop_pici, 0x03),
+ CMN_EVENT_DVM(CI700, dvmop_vici, 0x04),
+ CMN_EVENT_DVM(CI700, dvmsync, 0x05),
+ CMN_EVENT_DVM(CI700, vmid_filtered, 0x06),
+ CMN_EVENT_DVM(CI700, rndop_filtered, 0x07),
+ CMN_EVENT_DVM(CI700, retry, 0x08),
+ CMN_EVENT_DVM(CI700, txsnp_flitv, 0x09),
+ CMN_EVENT_DVM(CI700, txsnp_stall, 0x0a),
+ CMN_EVENT_DVM(CI700, trkfull, 0x0b),
+ _CMN_EVENT_DVM(CI700, trk_occupancy_all, 0x0c, 0),
+ _CMN_EVENT_DVM(CI700, trk_occupancy_dvmop, 0x0c, 1),
+ _CMN_EVENT_DVM(CI700, trk_occupancy_dvmsync, 0x0c, 2),
CMN_EVENT_HNF(CMN_ANY, cache_miss, 0x01),
CMN_EVENT_HNF(CMN_ANY, slc_sf_cache_access, 0x02),
@@ -558,6 +583,9 @@ static struct attribute *arm_cmn_event_attrs[] = {
CMN_EVENT_HNF(CMN_ANY, stash_snp_sent, 0x1d),
CMN_EVENT_HNF(CMN_ANY, stash_data_pull, 0x1e),
CMN_EVENT_HNF(CMN_ANY, snp_fwded, 0x1f),
+ CMN_EVENT_HNF(CI700, atomic_fwd, 0x20),
+ CMN_EVENT_HNF(CI700, mpam_hardlim, 0x21),
+ CMN_EVENT_HNF(CI700, mpam_softlim, 0x22),
CMN_EVENT_HNI(rrt_rd_occ_cnt_ovfl, 0x20),
CMN_EVENT_HNI(rrt_wr_occ_cnt_ovfl, 0x21),
@@ -598,6 +626,7 @@ static struct attribute *arm_cmn_event_attrs[] = {
CMN_EVENT_SBSX(CMN_ANY, wdb_occ_cnt_ovfl, 0x14),
CMN_EVENT_SBSX(CMN_ANY, rd_axi_trkr_occ_cnt_ovfl, 0x15),
CMN_EVENT_SBSX(CMN_ANY, cmo_axi_trkr_occ_cnt_ovfl, 0x16),
+ CMN_EVENT_SBSX(CI700, rdb_occ_cnt_ovfl, 0x17),
CMN_EVENT_SBSX(CMN_ANY, arvalid_no_arready, 0x21),
CMN_EVENT_SBSX(CMN_ANY, awvalid_no_awready, 0x22),
CMN_EVENT_SBSX(CMN_ANY, wvalid_no_wready, 0x23),
@@ -624,6 +653,25 @@ static struct attribute *arm_cmn_event_attrs[] = {
CMN_EVENT_RNID(CMN600, rdb_replay, 0x12),
CMN_EVENT_RNID(CMN600, rdb_hybrid, 0x13),
CMN_EVENT_RNID(CMN600, rdb_ord, 0x14),
+ CMN_EVENT_RNID(CI700, padb_occ_ovfl, 0x11),
+ CMN_EVENT_RNID(CI700, rpdb_occ_ovfl, 0x12),
+ CMN_EVENT_RNID(CI700, rrt_occup_ovfl_slice1, 0x13),
+ CMN_EVENT_RNID(CI700, rrt_occup_ovfl_slice2, 0x14),
+ CMN_EVENT_RNID(CI700, rrt_occup_ovfl_slice3, 0x15),
+ CMN_EVENT_RNID(CI700, wrt_throttled, 0x16),
+
+ CMN_EVENT_MTSX(tc_lookup, 0x01),
+ CMN_EVENT_MTSX(tc_fill, 0x02),
+ CMN_EVENT_MTSX(tc_miss, 0x03),
+ CMN_EVENT_MTSX(tdb_forward, 0x04),
+ CMN_EVENT_MTSX(tcq_hazard, 0x05),
+ CMN_EVENT_MTSX(tcq_rd_alloc, 0x06),
+ CMN_EVENT_MTSX(tcq_wr_alloc, 0x07),
+ CMN_EVENT_MTSX(tcq_cmo_alloc, 0x08),
+ CMN_EVENT_MTSX(axi_rd_req, 0x09),
+ CMN_EVENT_MTSX(axi_wr_req, 0x0a),
+ CMN_EVENT_MTSX(tcq_occ_cnt_ovfl, 0x0b),
+ CMN_EVENT_MTSX(tdb_occ_cnt_ovfl, 0x0c),
NULL
};
@@ -1773,6 +1821,7 @@ static int arm_cmn_remove(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id arm_cmn_of_match[] = {
{ .compatible = "arm,cmn-600", .data = (void *)CMN600 },
+ { .compatible = "arm,ci-700", .data = (void *)CI700 },
{}
};
MODULE_DEVICE_TABLE(of, arm_cmn_of_match);
--
2.34.1
@@ -1,192 +0,0 @@
From 162daf58abe2d00b9279fce143595b6ff546f803 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Tue, 18 Jan 2022 18:27:09 +0000
Subject: [PATCH 29/40] ANDROID: trusty: Rename transfer memory function to
lend memory
Renaming trusty_transfer_memory to trusty_lend_memory allows Trusty
to export memory operation like share, lend, reclaim and use common
code for memory share and lend operations.
Define TRUSTY_DEFAULT_MEM_OBJ_TAG as 0 and use that in existing calls.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ie165a609cc4398bb916967595d0b748d54d75faf
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/trusty-ipc.c | 14 ++++++++----
drivers/trusty/trusty-test.c | 3 ++-
drivers/trusty/trusty-virtio.c | 3 ++-
drivers/trusty/trusty.c | 41 ++++++++++++++++++++++------------
include/linux/trusty/trusty.h | 11 ++++-----
5 files changed, 47 insertions(+), 25 deletions(-)
diff --git a/drivers/trusty/trusty-ipc.c b/drivers/trusty/trusty-ipc.c
index 82d6ddeb41f4..0a27af2063a7 100644
--- a/drivers/trusty/trusty-ipc.c
+++ b/drivers/trusty/trusty-ipc.c
@@ -1233,10 +1233,16 @@ static int dn_share_fd(struct tipc_dn_chan *dn, int fd,
goto cleanup_handle;
}
- ret = trusty_transfer_memory(tipc_shared_handle_dev(shared_handle),
- &mem_id, shared_handle->sgt->sgl,
- shared_handle->sgt->orig_nents, prot, tag,
- lend);
+ if (lend)
+ ret = trusty_lend_memory(tipc_shared_handle_dev(shared_handle),
+ &mem_id, shared_handle->sgt->sgl,
+ shared_handle->sgt->orig_nents, prot,
+ tag);
+ else
+ ret = trusty_share_memory(tipc_shared_handle_dev(shared_handle),
+ &mem_id, shared_handle->sgt->sgl,
+ shared_handle->sgt->orig_nents, prot,
+ tag);
if (ret < 0) {
dev_dbg(dev, "Transferring memory failed: %d\n", ret);
diff --git a/drivers/trusty/trusty-test.c b/drivers/trusty/trusty-test.c
index 844868981fa5..c25fc0f2fcf0 100644
--- a/drivers/trusty/trusty-test.c
+++ b/drivers/trusty/trusty-test.c
@@ -138,7 +138,8 @@ static int trusty_test_share_objs(struct trusty_test_state *s,
t1 = ktime_get();
tmpret = trusty_share_memory(s->trusty_dev, &obj->mem_id,
obj->sgt.sgl, obj->sgt.nents,
- PAGE_KERNEL);
+ PAGE_KERNEL,
+ TRUSTY_DEFAULT_MEM_OBJ_TAG);
t2 = ktime_get();
if (tmpret) {
ret = tmpret;
diff --git a/drivers/trusty/trusty-virtio.c b/drivers/trusty/trusty-virtio.c
index fea59cd2e218..365e7c04bcf4 100644
--- a/drivers/trusty/trusty-virtio.c
+++ b/drivers/trusty/trusty-virtio.c
@@ -626,7 +626,8 @@ static int trusty_virtio_add_devices(struct trusty_ctx *tctx)
sg_init_one(&tctx->shared_sg, descr_va, descr_buf_sz);
ret = trusty_share_memory(tctx->dev->parent, &descr_id,
- &tctx->shared_sg, 1, PAGE_KERNEL);
+ &tctx->shared_sg, 1, PAGE_KERNEL,
+ TRUSTY_DEFAULT_MEM_OBJ_TAG);
if (ret) {
dev_err(tctx->dev, "trusty_share_memory failed: %d\n", ret);
goto err_share_memory;
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index 2dec75398f69..6bd30bc1bbc9 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -222,18 +222,9 @@ s32 trusty_std_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2)
}
EXPORT_SYMBOL(trusty_std_call32);
-int trusty_share_memory(struct device *dev, u64 *id,
- struct scatterlist *sglist, unsigned int nents,
- pgprot_t pgprot)
-{
- return trusty_transfer_memory(dev, id, sglist, nents, pgprot, 0,
- false);
-}
-EXPORT_SYMBOL(trusty_share_memory);
-
-int trusty_transfer_memory(struct device *dev, u64 *id,
- struct scatterlist *sglist, unsigned int nents,
- pgprot_t pgprot, u64 tag, bool lend)
+static int __trusty_share_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist, unsigned int nents,
+ pgprot_t pgprot, u64 tag, bool mem_share)
{
struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
int ret;
@@ -253,6 +244,12 @@ int trusty_transfer_memory(struct device *dev, u64 *id,
return -EOPNOTSUPP;
}
+ if (mem_share == false && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
+ dev_err(s->dev, "%s: old trusty version does not support lending memory objects\n",
+ __func__);
+ return -EOPNOTSUPP;
+ }
+
count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
if (count != nents) {
dev_err(s->dev, "failed to dma map sg_table\n");
@@ -271,7 +268,22 @@ int trusty_transfer_memory(struct device *dev, u64 *id,
*id = pg_inf.compat_attr;
return 0;
}
-EXPORT_SYMBOL(trusty_transfer_memory);
+
+int trusty_share_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist, unsigned int nents,
+ pgprot_t pgprot, u64 tag)
+{
+ return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, true);
+}
+EXPORT_SYMBOL(trusty_share_memory);
+
+int trusty_lend_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist, unsigned int nents,
+ pgprot_t pgprot, u64 tag)
+{
+ return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, false);
+}
+EXPORT_SYMBOL(trusty_lend_memory);
/*
* trusty_share_memory_compat - trusty_share_memory wrapper for old apis
@@ -287,7 +299,8 @@ int trusty_share_memory_compat(struct device *dev, u64 *id,
int ret;
struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
- ret = trusty_share_memory(dev, id, sglist, nents, pgprot);
+ ret = trusty_share_memory(dev, id, sglist, nents, pgprot,
+ TRUSTY_DEFAULT_MEM_OBJ_TAG);
if (!ret && s->api_version < TRUSTY_API_VERSION_PHYS_MEM_OBJ)
*id &= 0x0000FFFFFFFFF000ull;
diff --git a/include/linux/trusty/trusty.h b/include/linux/trusty/trusty.h
index 272d96c1c696..27f635f2d12d 100644
--- a/include/linux/trusty/trusty.h
+++ b/include/linux/trusty/trusty.h
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/pagemap.h>
+#define TRUSTY_DEFAULT_MEM_OBJ_TAG (0)
#if IS_ENABLED(CONFIG_TRUSTY)
s32 trusty_std_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2);
@@ -62,13 +63,13 @@ struct scatterlist;
typedef u64 trusty_shared_mem_id_t;
int trusty_share_memory(struct device *dev, trusty_shared_mem_id_t *id,
struct scatterlist *sglist, unsigned int nents,
- pgprot_t pgprot);
+ pgprot_t pgprot, u64 tag);
int trusty_share_memory_compat(struct device *dev, trusty_shared_mem_id_t *id,
struct scatterlist *sglist, unsigned int nents,
pgprot_t pgprot);
-int trusty_transfer_memory(struct device *dev, u64 *id,
- struct scatterlist *sglist, unsigned int nents,
- pgprot_t pgprot, u64 tag, bool lend);
+int trusty_lend_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist, unsigned int nents,
+ pgprot_t pgprot, u64 tag);
int trusty_reclaim_memory(struct device *dev, trusty_shared_mem_id_t id,
struct scatterlist *sglist, unsigned int nents);
@@ -78,7 +79,7 @@ u64 trusty_dma_buf_get_ffa_tag(struct dma_buf *dma_buf);
#else
static inline u64 trusty_dma_buf_get_ffa_tag(struct dma_buf *dma_buf)
{
- return 0;
+ return TRUSTY_DEFAULT_MEM_OBJ_TAG;
}
#endif
--
2.34.1
@@ -1,496 +0,0 @@
From 41cab33091954ec655e7fe567c345f5a44fea122 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Fri, 14 Jan 2022 14:02:39 +0000
Subject: [PATCH 30/40] ANDROID: trusty: Separate out SMC based transport
This commit refactors SMC based transport operation like
smc_fastcalls, smc memory operations in a separate file.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Iebee505b7172f6247186e3bf1e0b50740b2e4dfa
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/Makefile | 1 +
drivers/trusty/trusty-private.h | 61 ++++++++++++++
drivers/trusty/trusty-smc.c | 136 ++++++++++++++++++++++++++++++
drivers/trusty/trusty.c | 144 +++++++++-----------------------
4 files changed, 237 insertions(+), 105 deletions(-)
create mode 100644 drivers/trusty/trusty-private.h
create mode 100644 drivers/trusty/trusty-smc.c
diff --git a/drivers/trusty/Makefile b/drivers/trusty/Makefile
index 2cf1cfccf97b..fbb53ee93003 100644
--- a/drivers/trusty/Makefile
+++ b/drivers/trusty/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_TRUSTY) += trusty-core.o
trusty-core-objs += trusty.o trusty-mem.o
+trusty-core-objs += trusty-smc.o
trusty-core-$(CONFIG_ARM) += trusty-smc-arm.o
trusty-core-$(CONFIG_ARM64) += trusty-smc-arm64.o
obj-$(CONFIG_TRUSTY_IRQ) += trusty-irq.o
diff --git a/drivers/trusty/trusty-private.h b/drivers/trusty/trusty-private.h
new file mode 100644
index 000000000000..4d73c6ae35d4
--- /dev/null
+++ b/drivers/trusty/trusty-private.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#ifndef _TRUSTY_PRIVATE_H
+#define _TRUSTY_PRIVATE_H
+
+#include <linux/types.h>
+
+struct trusty_work {
+ struct trusty_state *ts;
+ struct work_struct work;
+};
+
+struct trusty_msg_ops {
+ u32 (*send_direct_msg)(struct device *dev, unsigned long fid,
+ unsigned long a0, unsigned long a1,
+ unsigned long a2);
+};
+
+struct trusty_mem_ops {
+ int (*trusty_share_memory)(struct device *dev, u64 *id,
+ struct scatterlist *sglist,
+ unsigned int nents, pgprot_t pgprot, u64 tag);
+ int (*trusty_lend_memory)(struct device *dev, u64 *id,
+ struct scatterlist *sglist,
+ unsigned int nents, pgprot_t pgprot, u64 tag);
+ int (*trusty_reclaim_memory)(struct device *dev, u64 id,
+ struct scatterlist *sglist,
+ unsigned int nents);
+};
+
+struct trusty_state {
+ struct mutex smc_lock;
+ struct atomic_notifier_head notifier;
+ struct completion cpu_idle_completion;
+ char *version_str;
+ u32 api_version;
+ bool trusty_panicked;
+ struct device *dev;
+ struct workqueue_struct *nop_wq;
+ struct trusty_work __percpu *nop_works;
+ struct list_head nop_queue;
+ spinlock_t nop_lock; /* protects nop_queue */
+ struct device_dma_parameters dma_parms;
+ const struct trusty_msg_ops *msg_ops;
+ const struct trusty_mem_ops *mem_ops;
+};
+
+int trusty_init_api_version(struct trusty_state *s, struct device *dev,
+ u32 (*send_direct_msg)(struct device *dev,
+ unsigned long fid,
+ unsigned long a0,
+ unsigned long a1,
+ unsigned long a2));
+
+int trusty_smc_transport_setup(struct device *dev);
+void trusty_smc_transport_cleanup(struct device *dev);
+
+#endif /* _TRUSTY_PRIVATE_H */
diff --git a/drivers/trusty/trusty-smc.c b/drivers/trusty/trusty-smc.c
new file mode 100644
index 000000000000..8fa841e0e253
--- /dev/null
+++ b/drivers/trusty/trusty-smc.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 Google, Inc.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/trusty/smcall.h>
+#include <linux/trusty/trusty.h>
+
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+
+#include "trusty-smc.h"
+#include "trusty-private.h"
+
+static u32 trusty_smc_send_direct_msg(struct device *dev, unsigned long fid,
+ unsigned long a0, unsigned long a1,
+ unsigned long a2)
+{
+ return trusty_smc8(fid, a0, a1, a2, 0, 0, 0, 0).r0;
+}
+
+static int trusty_smc_share_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist,
+ unsigned int nents, pgprot_t pgprot, u64 tag)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+ int ret;
+ struct ns_mem_page_info pg_inf;
+ struct scatterlist *sg;
+ size_t count;
+
+ if (WARN_ON(nents < 1))
+ return -EINVAL;
+
+ if (nents != 1) {
+ dev_err(s->dev, "%s: old trusty version does not support "
+ "non-contiguous memory objects\n", __func__);
+ return -EOPNOTSUPP;
+ }
+
+ count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
+ if (count != nents) {
+ dev_err(s->dev, "failed to dma map sg_table\n");
+ return -EINVAL;
+ }
+
+ sg = sglist;
+ ret = trusty_encode_page_info(&pg_inf, phys_to_page(sg_dma_address(sg)),
+ pgprot);
+ if (ret) {
+ dev_err(s->dev, "%s: trusty_encode_page_info failed\n",
+ __func__);
+ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
+ return ret;
+ }
+
+ *id = pg_inf.compat_attr;
+ return 0;
+}
+
+static int trusty_smc_lend_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist,
+ unsigned int nents, pgprot_t pgprot, u64 tag)
+{
+ return -EOPNOTSUPP;
+}
+
+static int trusty_smc_reclaim_memory(struct device *dev, u64 id,
+ struct scatterlist *sglist,
+ unsigned int nents)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+
+ if (WARN_ON(nents < 1))
+ return -EINVAL;
+
+ if (WARN_ON(s->api_version >= TRUSTY_API_VERSION_MEM_OBJ))
+ return -EINVAL;
+
+ if (nents != 1) {
+ dev_err(s->dev, "%s: not supported\n", __func__);
+ return -EOPNOTSUPP;
+ }
+
+ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
+
+ dev_dbg(s->dev, "%s: done\n", __func__);
+ return 0;
+}
+
+static const struct trusty_msg_ops trusty_smc_msg_ops = {
+ .send_direct_msg = &trusty_smc_send_direct_msg,
+};
+
+static const struct trusty_mem_ops trusty_smc_mem_ops = {
+ .trusty_share_memory = &trusty_smc_share_memory,
+ .trusty_lend_memory = &trusty_smc_lend_memory,
+ .trusty_reclaim_memory = &trusty_smc_reclaim_memory,
+};
+
+int trusty_smc_transport_setup(struct device *dev)
+{
+ int rc;
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+
+ rc = trusty_init_api_version(s, dev, &trusty_smc_send_direct_msg);
+ if (rc != 0) {
+ return rc;
+ }
+
+ /*
+ * Initialize Trusty msg calls with Trusty SMC ABI
+ */
+ s->msg_ops = &trusty_smc_msg_ops;
+
+ /*
+ * Initialize Trusty memory operations with Trusty SMC ABI only when
+ * Trusty API version is below TRUSTY_API_VERSION_MEM_OBJ.
+ */
+ if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ)
+ s->mem_ops = &trusty_smc_mem_ops;
+
+ return 0;
+}
+
+void trusty_smc_transport_cleanup(struct device *dev)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+
+ if (s->msg_ops == &trusty_smc_msg_ops)
+ s->msg_ops = NULL;
+
+ if (s->mem_ops == &trusty_smc_mem_ops)
+ s->mem_ops = NULL;
+}
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index 6bd30bc1bbc9..0486827a45ca 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -18,37 +18,10 @@
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
-#include "trusty-smc.h"
+#include "trusty-private.h"
-struct trusty_state;
static struct platform_driver trusty_driver;
-struct trusty_work {
- struct trusty_state *ts;
- struct work_struct work;
-};
-
-struct trusty_state {
- struct mutex smc_lock;
- struct atomic_notifier_head notifier;
- struct completion cpu_idle_completion;
- char *version_str;
- u32 api_version;
- bool trusty_panicked;
- struct device *dev;
- struct workqueue_struct *nop_wq;
- struct trusty_work __percpu *nop_works;
- struct list_head nop_queue;
- spinlock_t nop_lock; /* protects nop_queue */
- struct device_dma_parameters dma_parms;
-};
-
-static inline unsigned long smc(unsigned long r0, unsigned long r1,
- unsigned long r2, unsigned long r3)
-{
- return trusty_smc8(r0, r1, r2, r3, 0, 0, 0, 0).r0;
-}
-
s32 trusty_fast_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2)
{
struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
@@ -60,7 +33,7 @@ s32 trusty_fast_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2)
if (WARN_ON(SMC_IS_SMC64(smcnr)))
return SM_ERR_INVALID_PARAMETERS;
- return smc(smcnr, a0, a1, a2);
+ return s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2);
}
EXPORT_SYMBOL(trusty_fast_call32);
@@ -76,7 +49,7 @@ s64 trusty_fast_call64(struct device *dev, u64 smcnr, u64 a0, u64 a1, u64 a2)
if (WARN_ON(!SMC_IS_SMC64(smcnr)))
return SM_ERR_INVALID_PARAMETERS;
- return smc(smcnr, a0, a1, a2);
+ return s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2);
}
EXPORT_SYMBOL(trusty_fast_call64);
#endif
@@ -88,13 +61,16 @@ static unsigned long trusty_std_call_inner(struct device *dev,
{
unsigned long ret;
int retry = 5;
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
dev_dbg(dev, "%s(0x%lx 0x%lx 0x%lx 0x%lx)\n",
__func__, smcnr, a0, a1, a2);
while (true) {
- ret = smc(smcnr, a0, a1, a2);
+ ret = s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2);
while ((s32)ret == SM_ERR_FIQ_INTERRUPTED)
- ret = smc(SMC_SC_RESTART_FIQ, 0, 0, 0);
+ ret = s->msg_ops->send_direct_msg(dev,
+ SMC_SC_RESTART_FIQ,
+ 0, 0, 0);
if ((int)ret != SM_ERR_BUSY || !retry)
break;
@@ -222,58 +198,17 @@ s32 trusty_std_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2)
}
EXPORT_SYMBOL(trusty_std_call32);
-static int __trusty_share_memory(struct device *dev, u64 *id,
- struct scatterlist *sglist, unsigned int nents,
- pgprot_t pgprot, u64 tag, bool mem_share)
+int trusty_share_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist, unsigned int nents,
+ pgprot_t pgprot, u64 tag)
{
struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
- int ret;
- struct ns_mem_page_info pg_inf;
- struct scatterlist *sg;
- size_t count;
if (WARN_ON(dev->driver != &trusty_driver.driver))
return -EINVAL;
- if (WARN_ON(nents < 1))
- return -EINVAL;
-
- if (nents != 1 && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
- dev_err(s->dev, "%s: old trusty version does not support non-contiguous memory objects\n",
- __func__);
- return -EOPNOTSUPP;
- }
-
- if (mem_share == false && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
- dev_err(s->dev, "%s: old trusty version does not support lending memory objects\n",
- __func__);
- return -EOPNOTSUPP;
- }
-
- count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
- if (count != nents) {
- dev_err(s->dev, "failed to dma map sg_table\n");
- return -EINVAL;
- }
-
- sg = sglist;
- ret = trusty_encode_page_info(&pg_inf, phys_to_page(sg_dma_address(sg)),
- pgprot);
- if (ret) {
- dev_err(s->dev, "%s: trusty_encode_page_info failed\n",
- __func__);
- return ret;
- }
-
- *id = pg_inf.compat_attr;
- return 0;
-}
-
-int trusty_share_memory(struct device *dev, u64 *id,
- struct scatterlist *sglist, unsigned int nents,
- pgprot_t pgprot, u64 tag)
-{
- return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, true);
+ return s->mem_ops->trusty_share_memory(dev, id, sglist, nents, pgprot,
+ tag);
}
EXPORT_SYMBOL(trusty_share_memory);
@@ -281,7 +216,13 @@ int trusty_lend_memory(struct device *dev, u64 *id,
struct scatterlist *sglist, unsigned int nents,
pgprot_t pgprot, u64 tag)
{
- return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, false);
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+
+ if (WARN_ON(dev->driver != &trusty_driver.driver))
+ return -EINVAL;
+
+ return s->mem_ops->trusty_lend_memory(dev, id, sglist, nents, pgprot,
+ tag);
}
EXPORT_SYMBOL(trusty_lend_memory);
@@ -316,22 +257,7 @@ int trusty_reclaim_memory(struct device *dev, u64 id,
if (WARN_ON(dev->driver != &trusty_driver.driver))
return -EINVAL;
- if (WARN_ON(nents < 1))
- return -EINVAL;
-
- if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
- if (nents != 1) {
- dev_err(s->dev, "%s: not supported\n", __func__);
- return -EOPNOTSUPP;
- }
-
- dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
-
- dev_dbg(s->dev, "%s: done\n", __func__);
- return 0;
- }
-
- return 0;
+ return s->mem_ops->trusty_reclaim_memory(dev, id, sglist, nents);
}
EXPORT_SYMBOL(trusty_reclaim_memory);
@@ -382,7 +308,7 @@ const char *trusty_version_str_get(struct device *dev)
}
EXPORT_SYMBOL(trusty_version_str_get);
-static void trusty_init_version(struct trusty_state *s, struct device *dev)
+static void trusty_init_version_str(struct trusty_state *s, struct device *dev)
{
int ret;
int i;
@@ -430,12 +356,17 @@ bool trusty_get_panic_status(struct device *dev)
}
EXPORT_SYMBOL(trusty_get_panic_status);
-static int trusty_init_api_version(struct trusty_state *s, struct device *dev)
+int trusty_init_api_version(struct trusty_state *s, struct device *dev,
+ u32 (*send_direct_msg)(struct device *dev,
+ unsigned long fid,
+ unsigned long a0,
+ unsigned long a1,
+ unsigned long a2))
{
u32 api_version;
- api_version = trusty_fast_call32(dev, SMC_FC_API_VERSION,
- TRUSTY_API_VERSION_CURRENT, 0, 0);
+ api_version = send_direct_msg(dev, SMC_FC_API_VERSION,
+ TRUSTY_API_VERSION_CURRENT, 0, 0);
if (api_version == SM_ERR_UNDEFINED_SMC)
api_version = 0;
@@ -598,11 +529,12 @@ static int trusty_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s);
- trusty_init_version(s, &pdev->dev);
+ /* Initialize SMC transport */
+ ret = trusty_smc_transport_setup(s->dev);
+ if (ret != 0 || s->msg_ops == NULL || s->mem_ops == NULL)
+ goto err_transport_setup;
- ret = trusty_init_api_version(s, &pdev->dev);
- if (ret < 0)
- goto err_api_version;
+ trusty_init_version_str(s, &pdev->dev);
s->nop_wq = alloc_workqueue("trusty-nop-wq", WQ_CPU_INTENSIVE, 0);
if (!s->nop_wq) {
@@ -648,9 +580,10 @@ static int trusty_probe(struct platform_device *pdev)
err_alloc_works:
destroy_workqueue(s->nop_wq);
err_create_nop_wq:
-err_api_version:
- s->dev->dma_parms = NULL;
kfree(s->version_str);
+ trusty_smc_transport_cleanup(s->dev);
+err_transport_setup:
+ s->dev->dma_parms = NULL;
device_for_each_child(&pdev->dev, NULL, trusty_remove_child);
mutex_destroy(&s->smc_lock);
kfree(s);
@@ -673,6 +606,7 @@ static int trusty_remove(struct platform_device *pdev)
free_percpu(s->nop_works);
destroy_workqueue(s->nop_wq);
+ trusty_smc_transport_cleanup(s->dev);
mutex_destroy(&s->smc_lock);
s->dev->dma_parms = NULL;
kfree(s->version_str);
--
2.34.1
@@ -1,57 +0,0 @@
From d022d0c3c6cadacf8a3a5fd2bb42c465834eef26 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Fri, 14 Jan 2022 14:22:42 +0000
Subject: [PATCH 31/40] ANDROID: trusty: Modify device compatible string
Drop smc keyword from device tree node as Trusty can use SMC or FFA
based transport.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Id99b52f32a2122434a22f1991c0b4cd52b0676ed
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
Documentation/devicetree/bindings/trusty/trusty-irq.txt | 2 +-
Documentation/devicetree/bindings/trusty/trusty-smc.txt | 2 +-
drivers/trusty/trusty.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/trusty/trusty-irq.txt b/Documentation/devicetree/bindings/trusty/trusty-irq.txt
index cbb545ad452b..ae02030be4e7 100644
--- a/Documentation/devicetree/bindings/trusty/trusty-irq.txt
+++ b/Documentation/devicetree/bindings/trusty/trusty-irq.txt
@@ -48,7 +48,7 @@ Example:
};
...
trusty {
- compatible = "android,trusty-smc-v1";
+ compatible = "android,trusty-v1";
ranges;
#address-cells = <2>;
#size-cells = <2>;
diff --git a/Documentation/devicetree/bindings/trusty/trusty-smc.txt b/Documentation/devicetree/bindings/trusty/trusty-smc.txt
index 1b39ad317c67..8d02a31ba814 100644
--- a/Documentation/devicetree/bindings/trusty/trusty-smc.txt
+++ b/Documentation/devicetree/bindings/trusty/trusty-smc.txt
@@ -3,4 +3,4 @@ Trusty smc interface
Trusty is running in secure mode on the same (arm) cpu(s) as the current os.
Required properties:
-- compatible: "android,trusty-smc-v1"
+- compatible: "android,trusty-v1"
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index 0486827a45ca..757dd7b2c527 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -615,7 +615,7 @@ static int trusty_remove(struct platform_device *pdev)
}
static const struct of_device_id trusty_of_match[] = {
- { .compatible = "android,trusty-smc-v1", },
+ { .compatible = "android,trusty-v1", },
{},
};
--
2.34.1
@@ -1,210 +0,0 @@
From e7fe12a5a7e3eac7a7d549ef9a7d88e9baba1832 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Fri, 14 Jan 2022 17:52:33 +0000
Subject: [PATCH 32/40] ANDROID: trusty: Add transport descriptor
Use transport descriptor to hold transport specific operations. This
helps to add new transport to Trusty core.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ibbde50de0302f6d259a7d572f0910067ce712b37
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/trusty-private.h | 20 +++++++++-
drivers/trusty/trusty-smc.c | 6 +++
drivers/trusty/trusty.c | 71 ++++++++++++++++++++++++++++++---
3 files changed, 90 insertions(+), 7 deletions(-)
diff --git a/drivers/trusty/trusty-private.h b/drivers/trusty/trusty-private.h
index 4d73c6ae35d4..74b88bb8f83b 100644
--- a/drivers/trusty/trusty-private.h
+++ b/drivers/trusty/trusty-private.h
@@ -14,12 +14,14 @@ struct trusty_work {
};
struct trusty_msg_ops {
+ const struct trusty_transport_desc *desc;
u32 (*send_direct_msg)(struct device *dev, unsigned long fid,
unsigned long a0, unsigned long a1,
unsigned long a2);
};
struct trusty_mem_ops {
+ const struct trusty_transport_desc *desc;
int (*trusty_share_memory)(struct device *dev, u64 *id,
struct scatterlist *sglist,
unsigned int nents, pgprot_t pgprot, u64 tag);
@@ -46,6 +48,19 @@ struct trusty_state {
struct device_dma_parameters dma_parms;
const struct trusty_msg_ops *msg_ops;
const struct trusty_mem_ops *mem_ops;
+ struct trusty_ffa_state *ffa;
+};
+
+struct trusty_ffa_state {
+ struct device *dev; /* ffa device */
+ const struct ffa_dev_ops *ops;
+ struct mutex share_memory_msg_lock; /* protects share_memory_msg */
+};
+
+struct trusty_transport_desc {
+ const char *name;
+ int (*setup)(struct device *dev);
+ void (*cleanup)(struct device *dev);
};
int trusty_init_api_version(struct trusty_state *s, struct device *dev,
@@ -55,7 +70,8 @@ int trusty_init_api_version(struct trusty_state *s, struct device *dev,
unsigned long a1,
unsigned long a2));
-int trusty_smc_transport_setup(struct device *dev);
-void trusty_smc_transport_cleanup(struct device *dev);
+typedef const struct trusty_transport_desc *trusty_transports_t;
+
+extern const struct trusty_transport_desc trusty_smc_transport;
#endif /* _TRUSTY_PRIVATE_H */
diff --git a/drivers/trusty/trusty-smc.c b/drivers/trusty/trusty-smc.c
index 8fa841e0e253..62d1d7060744 100644
--- a/drivers/trusty/trusty-smc.c
+++ b/drivers/trusty/trusty-smc.c
@@ -134,3 +134,9 @@ void trusty_smc_transport_cleanup(struct device *dev)
if (s->mem_ops == &trusty_smc_mem_ops)
s->mem_ops = NULL;
}
+
+const struct trusty_transport_desc trusty_smc_transport = {
+ .name = "smc",
+ .setup = trusty_smc_transport_setup,
+ .cleanup = trusty_smc_transport_cleanup,
+};
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index 757dd7b2c527..ec0fccfaa24c 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -493,6 +493,46 @@ void trusty_dequeue_nop(struct device *dev, struct trusty_nop *nop)
}
EXPORT_SYMBOL(trusty_dequeue_nop);
+static int
+trusty_transports_setup(const trusty_transports_t *transports,
+ struct device *dev)
+{
+ const struct trusty_transport_desc *transport;
+ int ret;
+ int transports_ret = -ENODEV;
+
+ if (!transports)
+ return -EINVAL;
+
+ for (; (transport = *transports); transports++) {
+ if (!transport->setup)
+ return -EINVAL;
+
+ ret = transport->setup(dev);
+ transports_ret &= ret;
+ }
+
+ /* One transport needs to complete setup without error. */
+ if (transports_ret < 0)
+ return -ENODEV;
+
+ return 0;
+}
+
+static void
+trusty_transports_cleanup(const trusty_transports_t *transports,
+ struct device *dev)
+{
+ const struct trusty_transport_desc *transport;
+
+ for (; (transport = *transports); transports++) {
+ if (!transport->cleanup)
+ continue;
+
+ transport->cleanup(dev);
+ }
+}
+
static int trusty_probe(struct platform_device *pdev)
{
int ret;
@@ -500,6 +540,7 @@ static int trusty_probe(struct platform_device *pdev)
work_func_t work_func;
struct trusty_state *s;
struct device_node *node = pdev->dev.of_node;
+ const trusty_transports_t *descs;
if (!node) {
dev_err(&pdev->dev, "of_node required\n");
@@ -529,8 +570,12 @@ static int trusty_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, s);
- /* Initialize SMC transport */
- ret = trusty_smc_transport_setup(s->dev);
+ /*
+ * Initialize Trusty transport. Trusty msg and mem ops has to be
+ * initialized as part of transport setup.
+ */
+ descs = of_device_get_match_data(&pdev->dev);
+ ret = trusty_transports_setup(descs, s->dev);
if (ret != 0 || s->msg_ops == NULL || s->mem_ops == NULL)
goto err_transport_setup;
@@ -581,7 +626,7 @@ static int trusty_probe(struct platform_device *pdev)
destroy_workqueue(s->nop_wq);
err_create_nop_wq:
kfree(s->version_str);
- trusty_smc_transport_cleanup(s->dev);
+ trusty_transports_cleanup(descs, s->dev);
err_transport_setup:
s->dev->dma_parms = NULL;
device_for_each_child(&pdev->dev, NULL, trusty_remove_child);
@@ -595,6 +640,7 @@ static int trusty_remove(struct platform_device *pdev)
{
unsigned int cpu;
struct trusty_state *s = platform_get_drvdata(pdev);
+ const trusty_transports_t *descs;
device_for_each_child(&pdev->dev, NULL, trusty_remove_child);
@@ -606,7 +652,10 @@ static int trusty_remove(struct platform_device *pdev)
free_percpu(s->nop_works);
destroy_workqueue(s->nop_wq);
- trusty_smc_transport_cleanup(s->dev);
+ /* call transport cleanup */
+ descs = of_device_get_match_data(&pdev->dev);
+ trusty_transports_cleanup(descs, s->dev);
+
mutex_destroy(&s->smc_lock);
s->dev->dma_parms = NULL;
kfree(s->version_str);
@@ -614,8 +663,20 @@ static int trusty_remove(struct platform_device *pdev)
return 0;
}
+/*
+ * Trusty probe will try all compiled in transports and will use the transport
+ * supported by the Trusty kernel.
+ *
+ * For Trusty API version < TRUSTY_API_VERSION_MEM_OBJ:
+ * trusty_smc_transport used for messaging.
+ */
+static const trusty_transports_t trusty_transports[] = {
+ &trusty_smc_transport,
+ NULL,
+};
+
static const struct of_device_id trusty_of_match[] = {
- { .compatible = "android,trusty-v1", },
+ { .compatible = "android,trusty-v1", .data = trusty_transports },
{},
};
--
2.34.1
@@ -1,313 +0,0 @@
From 34236d8df51d00d1167481760fda5abb56850765 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Fri, 14 Jan 2022 18:47:08 +0000
Subject: [PATCH 33/40] ANDROID: trusty: Add trusty-ffa driver
Initial changes related to FFA transport support
- Adds FFA transport descriptor
- Defines Trusty UUID
- Initializes FFA transport does probe, sets ffa_ops
- Defers Trusty probe if ARM FF-A driver is not initialized or
Trusty SP not found.
- Link FF-A device as the supplier for Trusty platform device.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I78f72b85c20e4bad4c24cf0826e96f27dcf2ee1d
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/Makefile | 1 +
drivers/trusty/trusty-ffa.c | 196 ++++++++++++++++++++++++++++++++
drivers/trusty/trusty-ffa.h | 28 +++++
drivers/trusty/trusty-private.h | 1 +
drivers/trusty/trusty.c | 6 +
5 files changed, 232 insertions(+)
create mode 100644 drivers/trusty/trusty-ffa.c
create mode 100644 drivers/trusty/trusty-ffa.h
diff --git a/drivers/trusty/Makefile b/drivers/trusty/Makefile
index fbb53ee93003..797d61bf68ef 100644
--- a/drivers/trusty/Makefile
+++ b/drivers/trusty/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_TRUSTY) += trusty-core.o
trusty-core-objs += trusty.o trusty-mem.o
trusty-core-objs += trusty-smc.o
+trusty-core-objs += trusty-ffa.o
trusty-core-$(CONFIG_ARM) += trusty-smc-arm.o
trusty-core-$(CONFIG_ARM64) += trusty-smc-arm64.o
obj-$(CONFIG_TRUSTY_IRQ) += trusty-irq.o
diff --git a/drivers/trusty/trusty-ffa.c b/drivers/trusty/trusty-ffa.c
new file mode 100644
index 000000000000..c8c16a1fc700
--- /dev/null
+++ b/drivers/trusty/trusty-ffa.c
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/trusty/smcall.h>
+#include <linux/arm_ffa.h>
+#include <linux/trusty/trusty.h>
+
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+
+#include "trusty-ffa.h"
+#include "trusty-private.h"
+
+static const struct trusty_mem_ops trusty_ffa_mem_ops = {
+ .desc = &trusty_ffa_transport,
+};
+
+static const struct ffa_device_id trusty_ffa_device_id[] = {
+ /*
+ * Trusty UID: RFC-4122 compliant UUID version 4
+ * 40ee25f0-a2bc-304c-8c4ca173c57d8af1
+ */
+ { UUID_INIT(0x40ee25f0, 0xa2bc, 0x304c,
+ 0x8c, 0x4c, 0xa1, 0x73, 0xc5, 0x7d, 0x8a, 0xf1) },
+ {}
+};
+
+static int trusty_ffa_dev_match(struct device *dev, const void *uuid)
+{
+ struct ffa_device *ffa_dev;
+
+ ffa_dev = to_ffa_dev(dev);
+ if (uuid_equal(&ffa_dev->uuid, uuid))
+ return 1;
+
+ return 0;
+}
+
+static struct ffa_device *trusty_ffa_dev_find(void)
+{
+ const void *data;
+ struct device *dev;
+
+ /* currently only one trusty instance is probed */
+ data = &trusty_ffa_device_id[0].uuid;
+
+ dev = bus_find_device(&ffa_bus_type, NULL, data, trusty_ffa_dev_match);
+ if (dev) {
+ /* drop reference count */
+ put_device(dev);
+ return to_ffa_dev(dev);
+ }
+
+ return NULL;
+}
+
+static int trusty_ffa_link_supplier(struct device *c_dev, struct device *s_dev)
+{
+ if (!c_dev || !s_dev)
+ return -EINVAL;
+
+ if (!device_link_add(c_dev, s_dev, DL_FLAG_AUTOREMOVE_CONSUMER)) {
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * called from trusty probe
+ */
+static int trusty_ffa_transport_setup(struct device *dev)
+{
+ int rc;
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+ struct trusty_ffa_state *ffa_state;
+ struct ffa_device *ffa_dev;
+
+ /* ffa transport not required for lower api versions */
+ if (s->api_version != 0 && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
+ return -EINVAL;
+ }
+
+ ffa_dev = trusty_ffa_dev_find();
+ if (!ffa_dev) {
+ dev_dbg(dev, "FFA: Trusty device not found defer probe\n");
+ return -EPROBE_DEFER;
+ }
+
+ ffa_state = ffa_dev_get_drvdata(ffa_dev);
+ if (!ffa_state)
+ return -EINVAL;
+
+ rc = trusty_ffa_link_supplier(dev, &ffa_dev->dev);
+ if (rc != 0)
+ return rc;
+
+ /* FFA used only for memory sharing operations */
+ if (s->api_version == TRUSTY_API_VERSION_MEM_OBJ) {
+ s->ffa = ffa_state;
+ s->mem_ops = &trusty_ffa_mem_ops;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static void trusty_ffa_transport_cleanup(struct device *dev)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+
+ /* ffa transport not setup for lower api versions */
+ if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
+ return;
+ }
+
+ s->ffa = NULL;
+ s->mem_ops = NULL;
+}
+
+static int trusty_ffa_probe(struct ffa_device *ffa_dev)
+{
+ const struct ffa_dev_ops *ffa_ops;
+ struct trusty_ffa_state *s;
+ u32 ffa_drv_version;
+
+ ffa_ops = ffa_dev_ops_get(ffa_dev);
+ if (!ffa_ops) {
+ dev_dbg(&ffa_dev->dev, "ffa_dev_ops_get: failed\n");
+ return -ENOENT;
+ }
+
+ /* check ffa driver version compatibility */
+ ffa_drv_version = ffa_ops->api_version_get();
+ if (TO_TRUSTY_FFA_MAJOR(ffa_drv_version) != TRUSTY_FFA_VERSION_MAJOR ||
+ TO_TRUSTY_FFA_MINOR(ffa_drv_version) < TRUSTY_FFA_VERSION_MINOR)
+ return -EINVAL;
+
+ s = kzalloc(sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->dev = &ffa_dev->dev;
+ s->ops = ffa_ops;
+ mutex_init(&s->share_memory_msg_lock);
+ ffa_dev_set_drvdata(ffa_dev, s);
+
+ ffa_ops->mode_32bit_set(ffa_dev);
+
+ return 0;
+}
+
+static void trusty_ffa_remove(struct ffa_device *ffa_dev)
+{
+ struct trusty_ffa_state *s;
+
+ s = ffa_dev_get_drvdata(ffa_dev);
+
+ mutex_destroy(&s->share_memory_msg_lock);
+ memset(s, 0, sizeof(struct trusty_ffa_state));
+ kfree(s);
+}
+
+static struct ffa_driver trusty_ffa_driver = {
+ .name = "trusty-ffa",
+ .probe = trusty_ffa_probe,
+ .remove = trusty_ffa_remove,
+ .id_table = trusty_ffa_device_id,
+};
+
+static int __init trusty_ffa_transport_init(void)
+{
+ if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)) {
+ return ffa_register(&trusty_ffa_driver);
+ } else
+ return -ENODEV;
+}
+
+static void __exit trusty_ffa_transport_exit(void)
+{
+ if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
+ ffa_unregister(&trusty_ffa_driver);
+}
+
+const struct trusty_transport_desc trusty_ffa_transport = {
+ .name = "ffa",
+ .setup = trusty_ffa_transport_setup,
+ .cleanup = trusty_ffa_transport_cleanup,
+};
+
+module_init(trusty_ffa_transport_init);
+module_exit(trusty_ffa_transport_exit);
diff --git a/drivers/trusty/trusty-ffa.h b/drivers/trusty/trusty-ffa.h
new file mode 100644
index 000000000000..267ca2c5db29
--- /dev/null
+++ b/drivers/trusty/trusty-ffa.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 ARM Ltd.
+ */
+
+#ifndef __LINUX_TRUSTY_FFA_H
+#define __LINUX_TRUSTY_FFA_H
+
+#include <linux/types.h>
+#include <linux/uuid.h>
+#include <linux/arm_ffa.h>
+
+#define TRUSTY_FFA_VERSION_MAJOR (1U)
+#define TRUSTY_FFA_VERSION_MINOR (0U)
+#define TRUSTY_FFA_VERSION_MAJOR_SHIFT (16U)
+#define TRUSTY_FFA_VERSION_MAJOR_MASK (0x7fffU)
+#define TRUSTY_FFA_VERSION_MINOR_SHIFT (0U)
+#define TRUSTY_FFA_VERSION_MINOR_MASK (0U)
+
+#define TO_TRUSTY_FFA_MAJOR(v) \
+ ((u16)((v >> TRUSTY_FFA_VERSION_MAJOR_SHIFT) & \
+ TRUSTY_FFA_VERSION_MAJOR_MASK))
+
+#define TO_TRUSTY_FFA_MINOR(v) \
+ ((u16)((v >> TRUSTY_FFA_VERSION_MINOR_SHIFT) & \
+ TRUSTY_FFA_VERSION_MINOR_MASK))
+
+#endif /* __LINUX_TRUSTY_FFA_H */
diff --git a/drivers/trusty/trusty-private.h b/drivers/trusty/trusty-private.h
index 74b88bb8f83b..2496f397e5d2 100644
--- a/drivers/trusty/trusty-private.h
+++ b/drivers/trusty/trusty-private.h
@@ -73,5 +73,6 @@ int trusty_init_api_version(struct trusty_state *s, struct device *dev,
typedef const struct trusty_transport_desc *trusty_transports_t;
extern const struct trusty_transport_desc trusty_smc_transport;
+extern const struct trusty_transport_desc trusty_ffa_transport;
#endif /* _TRUSTY_PRIVATE_H */
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index ec0fccfaa24c..4686b0d34f61 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -509,6 +509,11 @@ trusty_transports_setup(const trusty_transports_t *transports,
return -EINVAL;
ret = transport->setup(dev);
+ if (ret == -EPROBE_DEFER) {
+ dev_notice(dev, "transport %s: defer probe\n",
+ transport->name);
+ return ret;
+ }
transports_ret &= ret;
}
@@ -672,6 +677,7 @@ static int trusty_remove(struct platform_device *pdev)
*/
static const trusty_transports_t trusty_transports[] = {
&trusty_smc_transport,
+ &trusty_ffa_transport,
NULL,
};
--
2.34.1
@@ -1,152 +0,0 @@
From 996e6bae70ec2ce04061daab23f20e9c353c4227 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Tue, 18 Jan 2022 15:11:46 +0000
Subject: [PATCH 34/40] ANDROID: trusty-ffa: Add support for FFA memory
operations
Initializes Trusty mem_ops with FFA memory operations for share,
lend, reclaim.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Id3a1eb5ae8e4721cb983c624773d39bafe25a77d
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/trusty-ffa.c | 102 ++++++++++++++++++++++++++++++++++++
drivers/trusty/trusty.c | 5 ++
2 files changed, 107 insertions(+)
diff --git a/drivers/trusty/trusty-ffa.c b/drivers/trusty/trusty-ffa.c
index c8c16a1fc700..0655b3887b52 100644
--- a/drivers/trusty/trusty-ffa.c
+++ b/drivers/trusty/trusty-ffa.c
@@ -15,8 +15,110 @@
#include "trusty-ffa.h"
#include "trusty-private.h"
+static int __trusty_ffa_share_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist,
+ unsigned int nents, pgprot_t pgprot,
+ u64 tag, bool share)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+ int ret;
+ struct scatterlist *sg;
+ size_t count;
+ struct ffa_device *ffa_dev = to_ffa_dev(s->ffa->dev);
+ const struct ffa_dev_ops *ffa_ops = s->ffa->ops;
+ struct ffa_mem_region_attributes ffa_mem_attr;
+ struct ffa_mem_ops_args ffa_mem_args;
+
+ if (WARN_ON(nents < 1))
+ return -EINVAL;
+
+ count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
+ if (count != nents) {
+ dev_err(s->dev, "failed to dma map sg_table\n");
+ return -EINVAL;
+ }
+
+ sg = sglist;
+
+ mutex_lock(&s->ffa->share_memory_msg_lock);
+
+ ffa_mem_attr.receiver = ffa_dev->vm_id;
+ ffa_mem_attr.attrs = FFA_MEM_RW;
+
+ ffa_mem_args.use_txbuf = 1;
+ ffa_mem_args.tag = tag;
+ ffa_mem_args.attrs = &ffa_mem_attr;
+ ffa_mem_args.nattrs = 1;
+ ffa_mem_args.sg = sg;
+ ffa_mem_args.flags = 0;
+
+ if (share) {
+ ret = ffa_ops->memory_share(ffa_dev, &ffa_mem_args);
+ } else {
+ ret = ffa_ops->memory_lend(ffa_dev, &ffa_mem_args);
+ }
+
+ mutex_unlock(&s->ffa->share_memory_msg_lock);
+
+ if (!ret) {
+ *id = ffa_mem_args.g_handle;
+ dev_dbg(s->dev, "%s: done\n", __func__);
+ return 0;
+ }
+
+ dev_err(s->dev, "%s: failed %d", __func__, ret);
+
+ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
+ return ret;
+}
+
+static int trusty_ffa_share_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist,
+ unsigned int nents, pgprot_t pgprot, u64 tag)
+{
+ return __trusty_ffa_share_memory(dev, id, sglist, nents, pgprot, tag,
+ true);
+}
+
+static int trusty_ffa_lend_memory(struct device *dev, u64 *id,
+ struct scatterlist *sglist,
+ unsigned int nents, pgprot_t pgprot, u64 tag)
+{
+ return __trusty_ffa_share_memory(dev, id, sglist, nents, pgprot, tag,
+ false);
+}
+
+static int trusty_ffa_reclaim_memory(struct device *dev, u64 id,
+ struct scatterlist *sglist,
+ unsigned int nents)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+ int ret = 0;
+ const struct ffa_dev_ops *ffa_ops = s->ffa->ops;
+
+ if (WARN_ON(nents < 1))
+ return -EINVAL;
+
+ mutex_lock(&s->ffa->share_memory_msg_lock);
+
+ ret = ffa_ops->memory_reclaim(id, 0);
+
+ mutex_unlock(&s->ffa->share_memory_msg_lock);
+
+ if (ret != 0)
+ return ret;
+
+ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
+
+ dev_dbg(s->dev, "%s: done\n", __func__);
+ return 0;
+}
+
static const struct trusty_mem_ops trusty_ffa_mem_ops = {
.desc = &trusty_ffa_transport,
+ .trusty_share_memory = &trusty_ffa_share_memory,
+ .trusty_lend_memory = &trusty_ffa_lend_memory,
+ .trusty_reclaim_memory = &trusty_ffa_reclaim_memory,
};
static const struct ffa_device_id trusty_ffa_device_id[] = {
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index 4686b0d34f61..f91c255c9897 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -674,6 +674,11 @@ static int trusty_remove(struct platform_device *pdev)
*
* For Trusty API version < TRUSTY_API_VERSION_MEM_OBJ:
* trusty_smc_transport used for messaging.
+ *
+ * For Trusty API version == TRUSTY_API_VERSION_MEM_OBJ:
+ * trusty_smc_transport used for messaging.
+ * trusty_ffa_transport used for memory sharing.
+ *
*/
static const trusty_transports_t trusty_transports[] = {
&trusty_smc_transport,
--
2.34.1
@@ -1,143 +0,0 @@
From 8612a35bb376a3d104fe81f07c7109a252dcd9bf Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Thu, 3 Feb 2022 11:19:38 +0000
Subject: [PATCH 35/40] ANDROID: trusty-ffa: Enable FFA transport for both
memory and message ops
Adds new API version TRUSTY_API_VERSION_FFA and sets this as current
API version.
If Trusty on the secure side supports receipt of FFA direct request,
then trusty core uses FFA calls for messages and memory operations.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I4a8b060f906a96935a7df10713026fb543e2b9a7
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/trusty-ffa.c | 58 +++++++++++++++++++++++++++++++++++
drivers/trusty/trusty.c | 3 ++
include/linux/trusty/smcall.h | 3 +-
3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/drivers/trusty/trusty-ffa.c b/drivers/trusty/trusty-ffa.c
index 0655b3887b52..543f5a0d31cb 100644
--- a/drivers/trusty/trusty-ffa.c
+++ b/drivers/trusty/trusty-ffa.c
@@ -15,6 +15,36 @@
#include "trusty-ffa.h"
#include "trusty-private.h"
+/* partition property: Supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_REQ_RECV BIT(0)
+
+/* string representation of trusty UUID used for partition info get call */
+static const char *trusty_uuid = "40ee25f0-a2bc-304c-8c4c-a173c57d8af1";
+
+static u32 trusty_ffa_send_direct_msg(struct device *dev, unsigned long fid,
+ unsigned long a0, unsigned long a1,
+ unsigned long a2)
+{
+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
+ struct ffa_send_direct_data ffa_msg;
+ struct ffa_device *ffa_dev;
+ int ret;
+
+ ffa_dev = to_ffa_dev(s->ffa->dev);
+
+ ffa_msg.data0 = fid;
+ ffa_msg.data1 = a0;
+ ffa_msg.data2 = a1;
+ ffa_msg.data3 = a2;
+ ffa_msg.data4 = 0;
+
+ ret = s->ffa->ops->sync_send_receive(ffa_dev, &ffa_msg);
+ if (!ret)
+ return ffa_msg.data0;
+
+ return ret;
+}
+
static int __trusty_ffa_share_memory(struct device *dev, u64 *id,
struct scatterlist *sglist,
unsigned int nents, pgprot_t pgprot,
@@ -114,6 +144,11 @@ static int trusty_ffa_reclaim_memory(struct device *dev, u64 id,
return 0;
}
+static const struct trusty_msg_ops trusty_ffa_msg_ops = {
+ .desc = &trusty_ffa_transport,
+ .send_direct_msg = &trusty_ffa_send_direct_msg,
+};
+
static const struct trusty_mem_ops trusty_ffa_mem_ops = {
.desc = &trusty_ffa_transport,
.trusty_share_memory = &trusty_ffa_share_memory,
@@ -181,6 +216,7 @@ static int trusty_ffa_transport_setup(struct device *dev)
struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
struct trusty_ffa_state *ffa_state;
struct ffa_device *ffa_dev;
+ struct ffa_partition_info pinfo = { 0 };
/* ffa transport not required for lower api versions */
if (s->api_version != 0 && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
@@ -208,6 +244,28 @@ static int trusty_ffa_transport_setup(struct device *dev)
return 0;
}
+ /* check if Trusty partition can support receipt of direct requests. */
+ rc = ffa_state->ops->partition_info_get(trusty_uuid, &pinfo);
+ if (rc || !(pinfo.properties & FFA_PARTITION_DIRECT_REQ_RECV)) {
+ dev_err(ffa_state->dev, "trusty_ffa_pinfo: ret: 0x%x, prop: 0x%x\n",
+ rc, pinfo.properties);
+ return -EINVAL;
+ }
+
+ /* query and check Trusty API version */
+ s->ffa = ffa_state;
+ rc = trusty_init_api_version(s, dev, trusty_ffa_send_direct_msg);
+ if (rc) {
+ s->ffa = NULL;
+ return -EINVAL;
+ }
+
+ if (s->api_version == TRUSTY_API_VERSION_FFA) {
+ s->msg_ops = &trusty_ffa_msg_ops;
+ s->mem_ops = &trusty_ffa_mem_ops;
+ return 0;
+ }
+
return -EINVAL;
}
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index f91c255c9897..66273873f169 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -679,6 +679,9 @@ static int trusty_remove(struct platform_device *pdev)
* trusty_smc_transport used for messaging.
* trusty_ffa_transport used for memory sharing.
*
+ * For Trusty API version > TRUSTY_API_VERSION_MEM_OBJ:
+ * trusty_ffa_transport used for messaging and memory sharing operations.
+ *
*/
static const trusty_transports_t trusty_transports[] = {
&trusty_smc_transport,
diff --git a/include/linux/trusty/smcall.h b/include/linux/trusty/smcall.h
index aea3f6068593..17b3d1c2c4f6 100644
--- a/include/linux/trusty/smcall.h
+++ b/include/linux/trusty/smcall.h
@@ -109,7 +109,8 @@
#define TRUSTY_API_VERSION_SMP_NOP (3)
#define TRUSTY_API_VERSION_PHYS_MEM_OBJ (4)
#define TRUSTY_API_VERSION_MEM_OBJ (5)
-#define TRUSTY_API_VERSION_CURRENT (5)
+#define TRUSTY_API_VERSION_FFA (6)
+#define TRUSTY_API_VERSION_CURRENT (6)
#define SMC_FC_API_VERSION SMC_FASTCALL_NR(SMC_ENTITY_SECURE_MONITOR, 11)
/* TRUSTED_OS entity calls */
--
2.34.1
@@ -1,147 +0,0 @@
From f6ffd3bf7b561d603b350dc0274121886193fef0 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Wed, 16 Mar 2022 11:14:09 +0000
Subject: [PATCH 36/40] ANDROID: trusty: Make trusty transports configurable
With TRUSTY_SMC_TRANSPORT set to 'y', SMC based message passing and
memory sharing support will be compiled in to trusty core.
With TRUSTY_FFA_TRANSPORT set to 'y', FFA based message passing and
memory sharing support will be compiled in to trusty core. This
depends on ARM FF-A driver (ARM_FFA_TRANSPORT).
Enabling any of the transport sets config TRUSTY_HAVE_TRANSPORT to 'y'.
Not enabling any of the transport causes the build to break.
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ib5bbf0d39202e6897700264d14371ae33101c1d1
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/Kconfig | 30 ++++++++++++++++++++++++++++++
drivers/trusty/Makefile | 26 +++++++++++++++-----------
drivers/trusty/trusty-private.h | 4 ++++
drivers/trusty/trusty.c | 7 +++++++
4 files changed, 56 insertions(+), 11 deletions(-)
diff --git a/drivers/trusty/Kconfig b/drivers/trusty/Kconfig
index fcde7f097acf..260022e4595b 100644
--- a/drivers/trusty/Kconfig
+++ b/drivers/trusty/Kconfig
@@ -21,6 +21,36 @@ config TRUSTY
if TRUSTY
+config TRUSTY_HAVE_TRANSPORT
+ bool
+ help
+ If any of the Trusty transport is enabled then it sets this config
+ option. This variable is used to break the build when none of the
+ Trusty transports are enabled.
+
+config TRUSTY_SMC_TRANSPORT
+ bool "Trusty transport based on SMC"
+ select TRUSTY_HAVE_TRANSPORT
+ default n
+ help
+ Enable SMC based transport for Trusty. This transport is required for
+ Trusty API version <= TRUSTY_API_VERSION_MEM_OBJ.
+
+ If you want to use legacy SMC based transport for sending Trusty
+ messages to secure world, answer Y.
+
+config TRUSTY_FFA_TRANSPORT
+ bool "Trusty transport based on FFA"
+ select TRUSTY_HAVE_TRANSPORT
+ depends on ARM_FFA_TRANSPORT
+ default y
+ help
+ Enable ARM FF-A based transport for Trusty. This transport is required
+ for Trusty API version >= TRUSTY_API_VERSION_MEM_OBJ.
+
+ If you want to use ARM FF-A based transport for sending Trusty messages
+ to secure world, answer Y.
+
config TRUSTY_IRQ
tristate "Trusty IRQ support"
default y
diff --git a/drivers/trusty/Makefile b/drivers/trusty/Makefile
index 797d61bf68ef..104a4d0ed35c 100644
--- a/drivers/trusty/Makefile
+++ b/drivers/trusty/Makefile
@@ -3,14 +3,18 @@
# Makefile for trusty components
#
-obj-$(CONFIG_TRUSTY) += trusty-core.o
-trusty-core-objs += trusty.o trusty-mem.o
-trusty-core-objs += trusty-smc.o
-trusty-core-objs += trusty-ffa.o
-trusty-core-$(CONFIG_ARM) += trusty-smc-arm.o
-trusty-core-$(CONFIG_ARM64) += trusty-smc-arm64.o
-obj-$(CONFIG_TRUSTY_IRQ) += trusty-irq.o
-obj-$(CONFIG_TRUSTY_LOG) += trusty-log.o
-obj-$(CONFIG_TRUSTY_TEST) += trusty-test.o
-obj-$(CONFIG_TRUSTY_VIRTIO) += trusty-virtio.o
-obj-$(CONFIG_TRUSTY_VIRTIO_IPC) += trusty-ipc.o
+obj-$(CONFIG_TRUSTY) += trusty-core.o
+trusty-core-objs += trusty.o
+trusty-arm-smc-$(CONFIG_ARM) += trusty-smc-arm.o
+trusty-arm-smc64-$(CONFIG_ARM64) += trusty-smc-arm64.o
+trusty-transport-$(CONFIG_TRUSTY_SMC_TRANSPORT) += trusty-smc.o
+trusty-transport-$(CONFIG_TRUSTY_SMC_TRANSPORT) += trusty-mem.o
+trusty-transport-$(CONFIG_TRUSTY_SMC_TRANSPORT) += $(trusty-arm-smc-y)
+trusty-transport-$(CONFIG_TRUSTY_SMC_TRANSPORT) += $(trusty-arm-smc64-y)
+trusty-transport-$(CONFIG_TRUSTY_FFA_TRANSPORT) += trusty-ffa.o
+trusty-core-objs += $(trusty-transport-y)
+obj-$(CONFIG_TRUSTY_IRQ) += trusty-irq.o
+obj-$(CONFIG_TRUSTY_LOG) += trusty-log.o
+obj-$(CONFIG_TRUSTY_TEST) += trusty-test.o
+obj-$(CONFIG_TRUSTY_VIRTIO) += trusty-virtio.o
+obj-$(CONFIG_TRUSTY_VIRTIO_IPC) += trusty-ipc.o
diff --git a/drivers/trusty/trusty-private.h b/drivers/trusty/trusty-private.h
index 2496f397e5d2..386ca9ae5af3 100644
--- a/drivers/trusty/trusty-private.h
+++ b/drivers/trusty/trusty-private.h
@@ -72,7 +72,11 @@ int trusty_init_api_version(struct trusty_state *s, struct device *dev,
typedef const struct trusty_transport_desc *trusty_transports_t;
+#ifdef CONFIG_TRUSTY_SMC_TRANSPORT
extern const struct trusty_transport_desc trusty_smc_transport;
+#endif
+#ifdef CONFIG_TRUSTY_FFA_TRANSPORT
extern const struct trusty_transport_desc trusty_ffa_transport;
+#endif
#endif /* _TRUSTY_PRIVATE_H */
diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
index 66273873f169..06698f3c67f9 100644
--- a/drivers/trusty/trusty.c
+++ b/drivers/trusty/trusty.c
@@ -684,8 +684,12 @@ static int trusty_remove(struct platform_device *pdev)
*
*/
static const trusty_transports_t trusty_transports[] = {
+#ifdef CONFIG_TRUSTY_SMC_TRANSPORT
&trusty_smc_transport,
+#endif
+#ifdef CONFIG_TRUSTY_FFA_TRANSPORT
&trusty_ffa_transport,
+#endif
NULL,
};
@@ -708,6 +712,9 @@ static struct platform_driver trusty_driver = {
static int __init trusty_driver_init(void)
{
+ BUILD_BUG_ON_MSG(!IS_ENABLED(CONFIG_TRUSTY_HAVE_TRANSPORT),
+ "Trusty transport not configured");
+
return platform_driver_register(&trusty_driver);
}
--
2.34.1
@@ -1,27 +0,0 @@
From 71a99394b657019d234b43d9abacf9f86a3c4e4f Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Thu, 19 May 2022 09:56:04 +0100
Subject: [PATCH 37/40] ANDROID: trusty-log: include panic_notifier.h
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
drivers/trusty/trusty-log.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/trusty/trusty-log.c b/drivers/trusty/trusty-log.c
index 7b279fe63766..1bd68278d0be 100644
--- a/drivers/trusty/trusty-log.c
+++ b/drivers/trusty/trusty-log.c
@@ -6,6 +6,7 @@
#include <linux/trusty/smcall.h>
#include <linux/trusty/trusty.h>
#include <linux/notifier.h>
+#include <linux/panic_notifier.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/mm.h>
--
2.34.1
@@ -1,30 +0,0 @@
From dfa152d399d7e6a285ab31bcc2172f61d5db907d Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Thu, 19 May 2022 09:59:06 +0100
Subject: [PATCH 38/40] ANDROID: trusty-ipc: fix VIRTIO_ID_TRUSTY_IPC ID
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
include/uapi/linux/virtio_ids.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index 909905cd7618..06ccbf2db5fa 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.h
@@ -42,6 +42,10 @@
#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
#define VIRTIO_ID_CAIF 12 /* Virtio caif */
#define VIRTIO_ID_MEMORY_BALLOON 13 /* virtio memory balloon */
+/*
+ * todo: VIRTIO_ID_TRUSTY_IPC conflicts with VIRTIO_ID_MEMORY_BALLOON
+ * replace with unused ID and update trusty kernel header tipc_virtio_dev.h
+ */
#define VIRTIO_ID_TRUSTY_IPC 13 /* virtio trusty ipc */
#define VIRTIO_ID_GPU 16 /* virtio GPU */
#define VIRTIO_ID_CLOCK 17 /* virtio clock/timer */
--
2.34.1
@@ -1,27 +0,0 @@
From 6de0622bb6880b5a8e8422f6e6e847cc43231a89 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Wed, 18 May 2022 18:47:55 +0100
Subject: [PATCH 39/40] gki_config: add tc/disable_mpam
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
arch/arm64/configs/gki_defconfig | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig
index 31d836eef904..0536759d1baa 100644
--- a/arch/arm64/configs/gki_defconfig
+++ b/arch/arm64/configs/gki_defconfig
@@ -60,7 +60,6 @@ CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
-CONFIG_ARM64_MPAM=y
CONFIG_RANDOMIZE_BASE=y
# CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set
CONFIG_CMDLINE="stack_depot_disable=on kasan.stacktrace=off kvm-arm.mode=protected cgroup_disable=pressure"
--
2.34.1
@@ -1,52 +0,0 @@
From 2cdf0de8f42c4825f52618b9bbd2ec2084749de0 Mon Sep 17 00:00:00 2001
From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Date: Thu, 19 May 2022 16:44:13 +0100
Subject: [PATCH 40/40] ANDROID: KVM: arm64: disable FFA driver at EL2
Do not handle FFA calls
Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Upstream-Status: Pending [Not submitted to upstream yet]
Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
---
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 3 +++
arch/arm64/kvm/hyp/nvhe/setup.c | 4 +++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 49345929af0d..463cf27712c3 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -1134,8 +1134,11 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
bool handled;
handled = kvm_host_psci_handler(host_ctxt);
+ /* do not handle ffa calls as EL2 FFA driver is not yet complete */
+#if 0
if (!handled)
handled = kvm_host_ffa_handler(host_ctxt);
+#endif
if (!handled)
default_host_smc_handler(host_ctxt);
diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index 1a6f3eba5035..ce84030426d0 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -317,10 +317,12 @@ void __noreturn __pkvm_init_finalise(void)
if (ret)
goto out;
+ /* skip ffa init at EL2, use EL1 driver instead */
+#if 0
ret = hyp_ffa_init(ffa_proxy_pages);
if (ret)
goto out;
-
+#endif
hyp_shadow_table_init(shadow_table_base);
out:
/*
--
2.34.1
@@ -1,66 +0,0 @@
From 37948a54f3e49fc2fef157f89d5bb52cefcfe68e Mon Sep 17 00:00:00 2001
From: Kees Cook <keescook@chromium.org>
Date: Sat, 12 Feb 2022 09:14:49 -0800
Subject: [PATCH] etherdevice: Adjust ether_addr* prototypes to silence
-Wstringop-overead
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
With GCC 12, -Wstringop-overread was warning about an implicit cast from
char[6] to char[8]. However, the extra 2 bytes are always thrown away,
alignment doesn't matter, and the risk of hitting the edge of unallocated
memory has been accepted, so this prototype can just be converted to a
regular char *. Silences:
net/core/dev.c: In function bpf_prog_run_generic_xdp: net/core/dev.c:4618:21: warning: ether_addr_equal_64bits reading 8 bytes from a region of size 6 [-Wstringop-overread]
4618 | orig_host = ether_addr_equal_64bits(eth->h_dest, > skb->dev->dev_addr);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
net/core/dev.c:4618:21: note: referencing argument 1 of type const u8[8] {aka const unsigned char[8]}
net/core/dev.c:4618:21: note: referencing argument 2 of type const u8[8] {aka const unsigned char[8]}
In file included from net/core/dev.c:91: include/linux/etherdevice.h:375:20: note: in a call to function ether_addr_equal_64bits
375 | static inline bool ether_addr_equal_64bits(const u8 addr1[6+2],
| ^~~~~~~~~~~~~~~~~~~~~~~
Reported-by: Marc Kleine-Budde <mkl@pengutronix.de>
Tested-by: Marc Kleine-Budde <mkl@pengutronix.de>
Link: https://lore.kernel.org/netdev/20220212090811.uuzk6d76agw2vv73@pengutronix.de
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2618a0dae09ef37728dab89ff60418cbe25ae6bd]
Change-Id: I41ed4ace65094964eacddf0c56f9fc779f7d4e0c
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
---
include/linux/etherdevice.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index c58d50451485..7f28fa702bb7 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -127,7 +127,7 @@ static inline bool is_multicast_ether_addr(const u8 *addr)
#endif
}
-static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2])
+static inline bool is_multicast_ether_addr_64bits(const u8 *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
#ifdef __BIG_ENDIAN
@@ -364,8 +364,7 @@ static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
* Please note that alignment of addr1 & addr2 are only guaranteed to be 16 bits.
*/
-static inline bool ether_addr_equal_64bits(const u8 addr1[6+2],
- const u8 addr2[6+2])
+static inline bool ether_addr_equal_64bits(const u8 *addr1, const u8 *addr2)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2);
--
2.34.1
@@ -1,45 +0,0 @@
From 74979dd6327bbaa96ecb8525f8ea6025715d5ba7 Mon Sep 17 00:00:00 2001
From: Xiongwei Song <sxwjean@gmail.com>
Date: Fri, 14 Jan 2022 14:07:24 -0800
Subject: [PATCH] mm: page_alloc: fix building error on -Werror=array-compare
Arthur Marsh reported we would hit the error below when building kernel
with gcc-12:
CC mm/page_alloc.o
mm/page_alloc.c: In function `mem_init_print_info':
mm/page_alloc.c:8173:27: error: comparison between two arrays [-Werror=array-compare]
8173 | if (start <= pos && pos < end && size > adj) \
|
In C++20, the comparision between arrays should be warned.
Link: https://lkml.kernel.org/r/20211125130928.32465-1-sxwjean@me.com
Signed-off-by: Xiongwei Song <sxwjean@gmail.com>
Reported-by: Arthur Marsh <arthur.marsh@internode.on.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ca831f29f8f25c97182e726429b38c0802200c8f]
Signed-off-by: Davidson K <davidson.kumaresan@arm.com>
Change-Id: I11931013f1fd42f0f2a75375cdfb129cb3a9d5aa
---
mm/page_alloc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 185fbddecc83..3affeeb194d4 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -8282,7 +8282,7 @@ void __init mem_init_print_info(void)
*/
#define adj_init_size(start, end, size, pos, adj) \
do { \
- if (start <= pos && pos < end && size > adj) \
+ if (&start[0] <= &pos[0] && &pos[0] < &end[0] && size > adj) \
size -= adj; \
} while (0)
--
2.34.1
@@ -1,693 +0,0 @@
CONFIG_UAPI_HEADER_TEST=y
CONFIG_AUDIT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_TASKSTATS=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_PSI=y
CONFIG_RCU_EXPERT=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_IKHEADERS=y
CONFIG_UCLAMP_TASK=y
CONFIG_UCLAMP_BUCKETS_COUNT=20
CONFIG_CGROUPS=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_SCHED=y
CONFIG_UCLAMP_TASK_GROUP=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
# CONFIG_PID_NS is not set
CONFIG_RT_SOFTINT_OPTIMIZATION=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
CONFIG_BOOT_CONFIG=y
# CONFIG_SYSFS_SYSCALL is not set
# CONFIG_FHANDLE is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_USERFAULTFD=y
# CONFIG_RSEQ is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB_MERGE_DEFAULT is not set
CONFIG_SLAB_FREELIST_RANDOM=y
CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_SHUFFLE_PAGE_ALLOCATOR=y
CONFIG_PROFILING=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_QCOM=y
CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=32
CONFIG_PARAVIRT_TIME_ACCOUNTING=y
CONFIG_ARM64_SW_TTBR0_PAN=y
CONFIG_COMPAT=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_MPAM=y
CONFIG_RANDOMIZE_BASE=y
# CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set
CONFIG_CMDLINE="stack_depot_disable=on kasan.stacktrace=off kvm-arm.mode=protected cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
# CONFIG_DMI is not set
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_ENERGY_MODEL=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_GOV_TEO=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_TIMES=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_SCMI_CPUFREQ=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_KVM_S2MPU=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64_CE=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_SHADOW_CALL_STACK=y
CONFIG_LTO_CLANG_FULL=y
CONFIG_CFI_CLANG=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SCMVERSION=y
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_PROTECT=y
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
CONFIG_IOSCHED_BFQ=y
CONFIG_BFQ_GROUP_IOSCHED=y
CONFIG_GKI_HACKS_TO_FIX=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
CONFIG_CLEANCACHE=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_CMA_AREAS=16
# CONFIG_ZONE_DMA is not set
CONFIG_ANON_VMA_NAME=y
CONFIG_LRU_GEN=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_MIGRATE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_XDP_SOCKETS=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_NET_IPIP=y
CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IPGRE=y
CONFIG_NET_IPVTI=y
CONFIG_INET_ESP=y
CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_VTI=y
CONFIG_IPV6_GRE=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_DSCP=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
CONFIG_NETFILTER_XT_TARGET_TEE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_DSCP=y
CONFIG_NETFILTER_XT_MATCH_ESP=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_RPFILTER=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_TIPC=y
CONFIG_L2TP=y
CONFIG_BRIDGE=y
CONFIG_VLAN_8021Q=y
CONFIG_6LOWPAN=y
CONFIG_IEEE802154=y
CONFIG_IEEE802154_6LOWPAN=y
CONFIG_MAC802154=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
CONFIG_NET_SCH_MULTIQ=y
CONFIG_NET_SCH_SFQ=y
CONFIG_NET_SCH_TBF=y
CONFIG_NET_SCH_NETEM=y
CONFIG_NET_SCH_CODEL=y
CONFIG_NET_SCH_FQ_CODEL=y
CONFIG_NET_SCH_FQ=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_BASIC=y
CONFIG_NET_CLS_TCINDEX=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_FLOW=y
CONFIG_NET_CLS_BPF=y
CONFIG_NET_CLS_MATCHALL=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_CMP=y
CONFIG_NET_EMATCH_NBYTE=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_EMATCH_META=y
CONFIG_NET_EMATCH_TEXT=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_GACT=y
CONFIG_NET_ACT_MIRRED=y
CONFIG_NET_ACT_SKBEDIT=y
CONFIG_NET_ACT_BPF=y
CONFIG_VSOCKETS=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CAN=y
CONFIG_BT=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCIBTSDIO=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_BT_HCIUART_QCA=y
CONFIG_CFG80211=y
CONFIG_NL80211_TESTMODE=y
# CONFIG_CFG80211_DEFAULT_PS is not set
# CONFIG_CFG80211_CRDA_SUPPORT is not set
CONFIG_MAC80211=y
CONFIG_RFKILL=y
CONFIG_NFC=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIEAER=y
CONFIG_PCI_IOV=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCIE_DW_PLAT_EP=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCI_ENDPOINT=y
CONFIG_FW_LOADER_USER_HELPER=y
# CONFIG_FW_CACHE is not set
# CONFIG_SUN50I_DE2_BUS is not set
# CONFIG_SUNXI_RSB is not set
CONFIG_ARM_SCMI_PROTOCOL=y
# CONFIG_ARM_SCMI_POWER_DOMAIN is not set
CONFIG_ARM_SCPI_PROTOCOL=y
# CONFIG_ARM_SCPI_POWER_DOMAIN is not set
# CONFIG_EFI_ARMSTUB_DTB_LOADER is not set
CONFIG_GNSS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_SRAM=y
CONFIG_UID_SYS_STATS=y
CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PCI=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_DWC_TC_PLATFORM=y
CONFIG_SCSI_UFS_HISI=y
CONFIG_SCSI_UFS_BSG=y
CONFIG_SCSI_UFS_CRYPTO=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_DEFAULT_KEY=y
CONFIG_DM_SNAPSHOT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_WIREGUARD=y
CONFIG_IFB=y
CONFIG_MACSEC=y
CONFIG_TUN=y
CONFIG_VETH=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_USB_RTL8150=y
CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_CDC_EEM=y
# CONFIG_USB_NET_NET1080 is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set
CONFIG_USB_NET_AQC111=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
# CONFIG_WLAN_VENDOR_ATMEL is not set
# CONFIG_WLAN_VENDOR_BROADCOM is not set
# CONFIG_WLAN_VENDOR_CISCO is not set
# CONFIG_WLAN_VENDOR_INTEL is not set
# CONFIG_WLAN_VENDOR_INTERSIL is not set
# CONFIG_WLAN_VENDOR_MARVELL is not set
# CONFIG_WLAN_VENDOR_MEDIATEK is not set
# CONFIG_WLAN_VENDOR_RALINK is not set
# CONFIG_WLAN_VENDOR_REALTEK is not set
# CONFIG_WLAN_VENDOR_RSI is not set
# CONFIG_WLAN_VENDOR_ST is not set
# CONFIG_WLAN_VENDOR_TI is not set
# CONFIG_WLAN_VENDOR_ZYDAS is not set
# CONFIG_WLAN_VENDOR_QUANTENNA is not set
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
# CONFIG_MOUSE_PS2 is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_EXAR is not set
CONFIG_SERIAL_8250_RUNTIME_UARTS=0
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_SERIAL_QCOM_GENI=y
# CONFIG_SERIAL_QCOM_GENI_CONSOLE_DEFAULT_ENABLED is not set
CONFIG_SERIAL_QCOM_GENI_CONSOLE=y
CONFIG_SERIAL_SPRD=y
CONFIG_SERIAL_SPRD_CONSOLE=y
CONFIG_HVC_DCC=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_HW_RANDOM=y
# CONFIG_DEVMEM is not set
# CONFIG_DEVPORT is not set
CONFIG_RANDOM_TRUST_CPU=y
# CONFIG_I2C_COMPAT is not set
# CONFIG_I2C_HELPER_AUTO is not set
CONFIG_I3C=y
CONFIG_SPI=y
CONFIG_SPI_MEM=y
CONFIG_SPMI=y
# CONFIG_SPMI_MSM_PMIC_ARB is not set
# CONFIG_PINCTRL_SUN8I_H3_R is not set
# CONFIG_PINCTRL_SUN50I_A64 is not set
# CONFIG_PINCTRL_SUN50I_A64_R is not set
# CONFIG_PINCTRL_SUN50I_H5 is not set
# CONFIG_PINCTRL_SUN50I_H6 is not set
# CONFIG_PINCTRL_SUN50I_H6_R is not set
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_POWER_RESET_HISI=y
CONFIG_POWER_RESET_SYSCON=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_NETLINK=y
CONFIG_THERMAL_STATISTICS=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=100
CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_THERMAL_GOV_USER_SPACE=y
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
CONFIG_MFD_ACT8945A=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_RC_CORE=y
# CONFIG_RC_MAP is not set
CONFIG_LIRC=y
CONFIG_BPF_LIRC_MODE2=y
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
CONFIG_MEDIA_CEC_RC=y
# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
# CONFIG_MEDIA_RADIO_SUPPORT is not set
# CONFIG_MEDIA_SDR_SUPPORT is not set
# CONFIG_MEDIA_TEST_SUPPORT is not set
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=y
CONFIG_USB_GSPCA=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VGA_ARB is not set
CONFIG_DRM=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_HRTIMER=y
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_DRIVERS is not set
CONFIG_SND_USB_AUDIO=y
CONFIG_SND_SOC=y
CONFIG_HID_BATTERY_STRENGTH=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_APPLE=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_ELECOM=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NINTENDO=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PLANTRONICS=y
CONFIG_HID_PLAYSTATION=y
CONFIG_PLAYSTATION_FF=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SONY=y
CONFIG_SONY_FF=y
CONFIG_HID_STEAM=y
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
CONFIG_USB_HIDDEV=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
CONFIG_USB_DWC3=y
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
CONFIG_USB_CONFIGFS_F_UAC2=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_TYPEC=y
CONFIG_TYPEC_TCPM=y
CONFIG_TYPEC_TCPCI=y
CONFIG_TYPEC_UCSI=y
CONFIG_MMC=y
# CONFIG_PWRSEQ_EMMC is not set
# CONFIG_PWRSEQ_SIMPLE is not set
CONFIG_MMC_CRYPTO=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_LEDS_CLASS_FLASH=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_EDAC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PL030=y
CONFIG_RTC_DRV_PL031=y
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_SYSFS_STATS=y
CONFIG_DMABUF_HEAPS_DEFERRED_FREE=y
CONFIG_DMABUF_HEAPS_PAGE_POOL=y
CONFIG_UIO=y
CONFIG_VHOST_VSOCK=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_DEBUG_KINFO=y
CONFIG_COMMON_CLK_SCPI=y
# CONFIG_CLK_SUNXI is not set
# CONFIG_SUNXI_CCU is not set
CONFIG_HWSPINLOCK=y
# CONFIG_SUN50I_ERRATUM_UNKNOWN1 is not set
CONFIG_MAILBOX=y
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_RPMSG_CHAR=y
CONFIG_QCOM_GENI_SE=y
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
CONFIG_DEVFREQ_GOV_POWERSAVE=y
CONFIG_DEVFREQ_GOV_USERSPACE=y
CONFIG_DEVFREQ_GOV_PASSIVE=y
CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
CONFIG_IIO_TRIGGER=y
CONFIG_PWM=y
CONFIG_GENERIC_PHY=y
CONFIG_POWERCAP=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_ANDROID_DEBUG_SYMBOLS=y
CONFIG_ANDROID_VENDOR_HOOKS=y
CONFIG_LIBNVDIMM=y
# CONFIG_ND_BLK is not set
CONFIG_INTERCONNECT=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_FS_COMPRESSION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
CONFIG_FS_VERITY=y
CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y
# CONFIG_DNOTIFY is not set
CONFIG_QUOTA=y
CONFIG_QFMT_V2=y
CONFIG_FUSE_FS=y
CONFIG_VIRTIO_FS=y
CONFIG_OVERLAY_FS=y
CONFIG_INCREMENTAL_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_EXFAT_FS=y
CONFIG_TMPFS=y
# CONFIG_EFIVAR_FS is not set
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
CONFIG_EROFS_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_737=y
CONFIG_NLS_CODEPAGE_775=y
CONFIG_NLS_CODEPAGE_850=y
CONFIG_NLS_CODEPAGE_852=y
CONFIG_NLS_CODEPAGE_855=y
CONFIG_NLS_CODEPAGE_857=y
CONFIG_NLS_CODEPAGE_860=y
CONFIG_NLS_CODEPAGE_861=y
CONFIG_NLS_CODEPAGE_862=y
CONFIG_NLS_CODEPAGE_863=y
CONFIG_NLS_CODEPAGE_864=y
CONFIG_NLS_CODEPAGE_865=y
CONFIG_NLS_CODEPAGE_866=y
CONFIG_NLS_CODEPAGE_869=y
CONFIG_NLS_CODEPAGE_936=y
CONFIG_NLS_CODEPAGE_950=y
CONFIG_NLS_CODEPAGE_932=y
CONFIG_NLS_CODEPAGE_949=y
CONFIG_NLS_CODEPAGE_874=y
CONFIG_NLS_ISO8859_8=y
CONFIG_NLS_CODEPAGE_1250=y
CONFIG_NLS_CODEPAGE_1251=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_2=y
CONFIG_NLS_ISO8859_3=y
CONFIG_NLS_ISO8859_4=y
CONFIG_NLS_ISO8859_5=y
CONFIG_NLS_ISO8859_6=y
CONFIG_NLS_ISO8859_7=y
CONFIG_NLS_ISO8859_9=y
CONFIG_NLS_ISO8859_13=y
CONFIG_NLS_ISO8859_14=y
CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_KOI8_R=y
CONFIG_NLS_KOI8_U=y
CONFIG_NLS_MAC_ROMAN=y
CONFIG_NLS_MAC_CELTIC=y
CONFIG_NLS_MAC_CENTEURO=y
CONFIG_NLS_MAC_CROATIAN=y
CONFIG_NLS_MAC_CYRILLIC=y
CONFIG_NLS_MAC_GAELIC=y
CONFIG_NLS_MAC_GREEK=y
CONFIG_NLS_MAC_ICELAND=y
CONFIG_NLS_MAC_INUIT=y
CONFIG_NLS_MAC_ROMANIAN=y
CONFIG_NLS_MAC_TURKISH=y
CONFIG_NLS_UTF8=y
CONFIG_UNICODE=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
CONFIG_HARDENED_USERCOPY=y
# CONFIG_HARDENED_USERCOPY_FALLBACK is not set
CONFIG_STATIC_USERMODEHELPER=y
CONFIG_STATIC_USERMODEHELPER_PATH=""
CONFIG_SECURITY_SELINUX=y
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
CONFIG_CRYPTO_CHACHA20POLY1305=y
CONFIG_CRYPTO_ADIANTUM=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_BLAKE2B=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_LZ4=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_XZ_DEC=y
CONFIG_DMA_CMA=y
CONFIG_STACK_HASH_ORDER=12
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CALLER=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_MODULE_ALLOW_BTF_MISMATCH=y
CONFIG_HEADERS_INSTALL=y
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_UBSAN=y
CONFIG_UBSAN_TRAP=y
CONFIG_UBSAN_LOCAL_BOUNDS=y
# CONFIG_UBSAN_SHIFT is not set
# CONFIG_UBSAN_BOOL is not set
# CONFIG_UBSAN_ENUM is not set
CONFIG_PAGE_OWNER=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_KASAN=y
CONFIG_KASAN_HW_TAGS=y
CONFIG_KFENCE=y
CONFIG_KFENCE_SAMPLE_INTERVAL=500
CONFIG_KFENCE_NUM_OBJECTS=63
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=-1
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_WQ_WATCHDOG=y
CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_BUG_ON_DATA_CORRUPTION=y
CONFIG_TRACE_MMIO_ACCESS=y
CONFIG_HIST_TRIGGERS=y
CONFIG_PID_IN_CONTEXTIDR=y
# CONFIG_RUNTIME_TESTING_MENU is not set
@@ -1,99 +0,0 @@
From 1b2013986271de39360cf79e62ed9b7d2cc59f9b Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 22 Jun 2022 11:19:18 -0700
Subject: [PATCH] init_disassemble_info() signature changes causes compile
failures
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Hi,
binutils changed the signature of init_disassemble_info(), which now causes
perf and bpftool to fail to compile (e.g. on debian unstable).
Relevant binutils commit: https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=60a3da00bd5407f07d64dff82a4dae98230dfaac
util/annotate.c: In function symbol__disassemble_bpf:
util/annotate.c:1765:9: error: too few arguments to function init_disassemble_info
1765 | init_disassemble_info(&info, s,
| ^~~~~~~~~~~~~~~~~~~~~
In file included from util/annotate.c:1718:
/usr/include/dis-asm.h:472:13: note: declared here
472 | extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream,
| ^~~~~~~~~~~~~~~~~~~~~
with equivalent failures in
tools/bpf/bpf_jit_disasm.c
tools/bpf/bpftool/jit_disasm.c
The fix is easy enough, add a wrapper around fprintf() that conforms to the
new signature.
However I assume the necessary feature test and wrapper should only be added
once? I don't know the kernel stuff well enough to choose the right structure
here.
Attached is my local fix for perf. Obviously would need work to be a real
solution.
Greetings,
Andres Freund
---
binutils 2.39 changed the signature of init_disassemble_info(),
which now causes perf and bpftool to fail to compile.
Relevant binutils commit: [1]
There is a proper fix in development upstream[2].
This is a work-around for older kernels.
[1] https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=60a3da00bd5407f07d64dff82a4dae98230dfaac
[2] https://patchwork.kernel.org/project/netdevbpf/cover/20220801013834.156015-1-andres@anarazel.de/
Upstream-Status: Pending
Signed-off-by: Anton Antonov <Anton.Antonov@arm.com>
tools/perf/util/annotate.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 6c8575e182ed..466a3a68f5cd 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1677,6 +1677,18 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
#include <bfd.h>
#include <dis-asm.h>
+static int fprintf_styled(void *, enum disassembler_style, const char* fmt, ...)
+{
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+ r = vprintf(fmt, args);
+ va_end(args);
+
+ return r;
+}
+
static int symbol__disassemble_bpf(struct symbol *sym,
struct annotate_args *args)
{
@@ -1719,7 +1731,8 @@ static int symbol__disassemble_bpf(struct symbol *sym,
goto out;
}
init_disassemble_info(&info, s,
- (fprintf_ftype) fprintf);
+ (fprintf_ftype) fprintf,
+ fprintf_styled);
info.arch = bfd_get_arch(bfdf);
info.mach = bfd_get_mach(bfdf);
--
2.30.2
@@ -1,8 +0,0 @@
# Clang-specific configuration of kernel build
# We need to add this dependency as the kernel configuration depends on the compiler
do_kernel_configme[depends] += "androidclang-native:do_populate_sysroot"
DEPENDS:append = " androidclang-native"
KERNEL_CC = "${CCACHE}clang ${HOST_CC_KERNEL_ARCH}"
@@ -1,3 +0,0 @@
LINUX_ARM64_ACK_TOOLCHAIN_REQUIRE = "${@oe.utils.ifelse(d.getVar('LINUX_ACK_TOOLCHAIN_CLANG'), 'linux-arm64-ack-clang.inc', '')}"
require ${LINUX_ARM64_ACK_TOOLCHAIN_REQUIRE}
@@ -1,5 +0,0 @@
# Machine specific configurations
FILESEXTRAPATHS:prepend := "${THISDIR}/${BP}:"
require linux-arm-platforms.inc
@@ -1,21 +0,0 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (c) 2021 Arm Limited
#
DESCRIPTION = "Linux Android Common Kernel"
SECTION = "kernel"
LICENSE = "GPL-2.0-only"
LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
require recipes-kernel/linux/linux-yocto.inc
COMPATIBLE_MACHINE ?= "invalid"
ARCH = "arm64"
S = "${WORKDIR}/git"
LINUX_VERSION ?= "${PV}"
KERNEL_VERSION_SANITY_SKIP = "1"
KBRANCH = ""
@@ -1,46 +0,0 @@
Upstream-Status: Backport
Signed-off-by: Ross Burton <ross.burton@arm.com>
From af8dffeef974b488fd0f12723080a72b1b5f5822 Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <bruce.ashfield@gmail.com>
Date: Sun, 10 Jul 2022 22:56:53 -0400
Subject: [PATCH 1/2] lib/build_OID_registry: fix reproducibility issues
The script build_OID_registry captures the full path of itself
in the generated data. This causes reproduciblity issues as the
path is captured and packaged.
We use the basename of the script instead, and that allows us
to be reprodicible, with slightly less information captured in
the output data (but the generating script can still easily
be found).
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
---
lib/build_OID_registry | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/build_OID_registry b/lib/build_OID_registry
index d7fc32ea8ac2..f6de0a7f7457 100755
--- a/lib/build_OID_registry
+++ b/lib/build_OID_registry
@@ -8,6 +8,7 @@
#
use strict;
+use File::Basename;
my @names = ();
my @oids = ();
@@ -35,7 +36,7 @@ close IN_FILE || die;
#
open C_FILE, ">$ARGV[1]" or die;
print C_FILE "/*\n";
-print C_FILE " * Automatically generated by ", $0, ". Do not edit\n";
+print C_FILE " * Automatically generated by ", basename $0, ". Do not edit\n";
print C_FILE " */\n";
#
--
2.34.1
@@ -1,34 +0,0 @@
Take a patch from linux-yocto to fix buildpaths in perf's python module.
Upstream-Status: Pending
Signed-off-by: Ross Burton <ross.burton@arm.com>
From b8cd0e429bf75b673c438a8277d4bc74327df992 Mon Sep 17 00:00:00 2001
From: Tom Zanussi <tom.zanussi@intel.com>
Date: Tue, 3 Jul 2012 13:07:23 -0500
Subject: [PATCH] perf: change --root to --prefix for python install
Otherwise we get the sysroot path appended to the build path, not what
we want.
Signed-off-by: Tom Zanussi <tom.zanussi@intel.com>
---
tools/perf/Makefile.perf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 8f738e11356d..ee945d8e3996 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -1022,7 +1022,7 @@ install-bin: install-tools install-tests install-traceevent-plugins
install: install-bin try-install-man
install-python_ext:
- $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
+ $(PYTHON_WORD) util/setup.py --quiet install --prefix='$(DESTDIR_SQ)/usr'
# 'make install-doc' should call 'make -C Documentation install'
$(INSTALL_DOC_TARGETS):
--
2.34.1
@@ -1,56 +0,0 @@
Upstream-Status: Backport
Signed-off-by: Ross Burton <ross.burton@arm.com>
From 94b28f266f72c244051a2ec30ff4526a44b2ce85 Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <bruce.ashfield@gmail.com>
Date: Sun, 10 Jul 2022 21:37:07 -0400
Subject: [PATCH 2/2] vt/conmakehash: improve reproducibility
The file generated by conmakehash capture the application
path used to generate the file. While that can be informative,
it varies based on where the kernel was built, as the full
path is captured.
We tweak the application to use a second input as the "capture
name", and then modify the Makefile to pass the basename of
the source, making it reproducible.
This could be improved by using some sort of path mapping,
or the application manipualing argv[1] itself, but for now
this solves the reprodicibility issue.
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
---
drivers/tty/vt/Makefile | 2 +-
drivers/tty/vt/conmakehash.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/vt/Makefile b/drivers/tty/vt/Makefile
index fe30ce512819..cb51c21b58f9 100644
--- a/drivers/tty/vt/Makefile
+++ b/drivers/tty/vt/Makefile
@@ -15,7 +15,7 @@ clean-files := consolemap_deftbl.c defkeymap.c
hostprogs += conmakehash
quiet_cmd_conmk = CONMK $@
- cmd_conmk = $(obj)/conmakehash $< > $@
+ cmd_conmk = $(obj)/conmakehash $< $(shell basename $<) > $@
$(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE) $(obj)/conmakehash
$(call cmd,conmk)
diff --git a/drivers/tty/vt/conmakehash.c b/drivers/tty/vt/conmakehash.c
index cddd789fe46e..d62510b280e9 100644
--- a/drivers/tty/vt/conmakehash.c
+++ b/drivers/tty/vt/conmakehash.c
@@ -253,7 +253,7 @@ int main(int argc, char *argv[])
#include <linux/types.h>\n\
\n\
u8 dfont_unicount[%d] = \n\
-{\n\t", argv[1], fontlen);
+{\n\t", argv[2], fontlen);
for ( i = 0 ; i < fontlen ; i++ )
{
--
2.34.1
@@ -1,15 +0,0 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (c) 2022 Arm Limited
#
require linux-arm64-ack.inc
SRC_URI = " \
git://android.googlesource.com/kernel/common.git;protocol=https;branch=android13-5.15-lts \
file://0001-lib-build_OID_registry-fix-reproducibility-issues.patch \
file://0002-vt-conmakehash-improve-reproducibility.patch \
file://0001-perf-change-root-to-prefix-for-python-install.patch \
"
# tag: ASB-2022-05-05_13-5.15-93-ge8b3f31d7a60
SRCREV = "e8b3f31d7a60648343ecbd45ab58dbcfc425b22c"