summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmbroise Vincent <ambroise.vincent@arm.com>2019-07-12 13:47:03 +0100
committerOlivier Deprez <olivier.deprez@arm.com>2019-12-18 09:59:12 +0100
commit992f091b5de3b0837c95a338a4e739f6ca2f254f (patch)
tree59bd4557e49cc2dcd57aee496356c7e8cb55f040
parentd310239d775c34d237b8c4b81baa6f6a12207824 (diff)
debugfs: add SMC channel
Provide an SMC interface to the 9p filesystem. This permits accessing firmware drivers through a common interface, using standardized read/write/control operations. Signed-off-by: Ambroise Vincent <ambroise.vincent@arm.com> Signed-off-by: Olivier Deprez <olivier.deprez@arm.com> Change-Id: I9314662314bb060f6bc02714476574da158b2a7d
-rw-r--r--docs/components/arm-sip-service.rst341
-rw-r--r--docs/components/debugfs-design.rst132
-rw-r--r--docs/getting_started/build-options.rst4
-rw-r--r--include/lib/debugfs.h23
-rw-r--r--include/plat/arm/common/arm_sip_svc.h8
-rw-r--r--lib/debugfs/debugfs.mk2
-rw-r--r--lib/debugfs/debugfs_smc.c209
-rw-r--r--plat/arm/board/fvp/fvp_common.c4
-rw-r--r--plat/arm/board/fvp/include/platform_def.h6
-rw-r--r--plat/arm/board/fvp/platform.mk4
-rw-r--r--plat/arm/common/arm_bl31_setup.c7
-rw-r--r--plat/arm/common/arm_sip_svc.c24
12 files changed, 759 insertions, 5 deletions
diff --git a/docs/components/arm-sip-service.rst b/docs/components/arm-sip-service.rst
index 2d58586b9..01bc04d71 100644
--- a/docs/components/arm-sip-service.rst
+++ b/docs/components/arm-sip-service.rst
@@ -17,6 +17,7 @@ The Arm SiP implementation offers the following services:
- Performance Measurement Framework (PMF)
- Execution State Switching service
+- DebugFS interface
Source definitions for Arm SiP service are located in the ``arm_sip_svc.h`` header
file.
@@ -87,6 +88,346 @@ Instead, execution starts at the supplied entry point, with the CPU registers 0
and 1 populated with the supplied *Cookie hi* and *Cookie lo* values,
respectively.
+DebugFS interface
+-----------------
+
+The optional DebugFS interface is accessed through an SMC SiP service. Refer
+to the component documentation for details.
+
+String parameters are passed through a shared buffer using a specific union:
+
+.. code:: c
+
+ union debugfs_parms {
+ struct {
+ char fname[MAX_PATH_LEN];
+ } open;
+
+ struct mount {
+ char srv[MAX_PATH_LEN];
+ char where[MAX_PATH_LEN];
+ char spec[MAX_PATH_LEN];
+ } mount;
+
+ struct {
+ char path[MAX_PATH_LEN];
+ dir_t dir;
+ } stat;
+
+ struct {
+ char oldpath[MAX_PATH_LEN];
+ char newpath[MAX_PATH_LEN];
+ } bind;
+ };
+
+Format of the dir_t structure as such:
+
+.. code:: c
+
+ typedef struct {
+ char name[NAMELEN];
+ long length;
+ unsigned char mode;
+ unsigned char index;
+ unsigned char dev;
+ qid_t qid;
+ } dir_t;
+
+
+* Identifiers
+
+======================== =============================================
+SMC_OK 0
+SMC_UNK -1
+DEBUGFS_E_INVALID_PARAMS -2
+======================== =============================================
+
+======================== =============================================
+MOUNT 0
+CREATE 1
+OPEN 2
+CLOSE 3
+READ 4
+WRITE 5
+SEEK 6
+BIND 7
+STAT 8
+INIT 10
+VERSION 11
+======================== =============================================
+
+MOUNT
+~~~~~
+
+Description
+^^^^^^^^^^^
+This operation mounts a blob of data pointed to by path stored in `src`, at
+filesystem location pointed to by path stored in `where`, using driver pointed
+to by path in `spec`.
+
+Parameters
+^^^^^^^^^^
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``MOUNT``
+======== ============================================================
+
+Return values
+^^^^^^^^^^^^^
+
+=============== ==========================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if mount operation failed
+=============== ==========================================================
+
+OPEN
+~~~~
+
+Description
+^^^^^^^^^^^
+This operation opens the file path pointed to by `fname`.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``OPEN``
+uint32_t mode
+======== ============================================================
+
+mode can be one of:
+
+.. code:: c
+
+ enum mode {
+ O_READ = 1 << 0,
+ O_WRITE = 1 << 1,
+ O_RDWR = 1 << 2,
+ O_BIND = 1 << 3,
+ O_DIR = 1 << 4,
+ O_STAT = 1 << 5
+ };
+
+Return values
+^^^^^^^^^^^^^
+
+=============== ==========================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if open operation failed
+
+uint32_t w1: file descriptor id on success.
+=============== ==========================================================
+
+CLOSE
+~~~~~
+
+Description
+^^^^^^^^^^^
+
+This operation closes a file described by a file descriptor obtained by a
+previous call to OPEN.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``CLOSE``
+uint32_t File descriptor id returned by OPEN
+======== ============================================================
+
+Return values
+^^^^^^^^^^^^^
+=============== ==========================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if close operation failed
+=============== ==========================================================
+
+READ
+~~~~
+
+Description
+^^^^^^^^^^^
+
+This operation reads a number of bytes from a file descriptor obtained by
+a previous call to OPEN.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``READ``
+uint32_t File descriptor id returned by OPEN
+uint32_t Number of bytes to read
+======== ============================================================
+
+Return values
+^^^^^^^^^^^^^
+
+On success, the read data is retrieved from the shared buffer after the
+operation.
+
+=============== ==========================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if read operation failed
+
+uint32_t w1: number of bytes read on success.
+=============== ==========================================================
+
+SEEK
+~~~~
+
+Description
+^^^^^^^^^^^
+
+Move file pointer for file described by given `file descriptor` of given
+`offset` related to `whence`.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``SEEK``
+uint32_t File descriptor id returned by OPEN
+sint32_t offset in the file relative to whence
+uint32_t whence
+======== ============================================================
+
+whence can be one of:
+
+========= ============================================================
+KSEEK_SET 0
+KSEEK_CUR 1
+KSEEK_END 2
+========= ============================================================
+
+Return values
+^^^^^^^^^^^^^
+
+=============== ==========================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if seek operation failed
+=============== ==========================================================
+
+BIND
+~~~~
+
+Description
+^^^^^^^^^^^
+
+Create a link from `oldpath` to `newpath`.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``BIND``
+======== ============================================================
+
+Return values
+^^^^^^^^^^^^^
+
+=============== ==========================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if bind operation failed
+=============== ==========================================================
+
+STAT
+~~~~
+
+Description
+^^^^^^^^^^^
+
+Perform a stat operation on provided file `name` and returns the directory
+entry statistics into `dir`.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``STAT``
+======== ============================================================
+
+Return values
+^^^^^^^^^^^^^
+
+=============== ==========================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if stat operation failed
+=============== ==========================================================
+
+INIT
+~~~~
+
+Description
+^^^^^^^^^^^
+Initial call to setup the shared exchange buffer. Notice if successful once,
+subsequent calls fail after a first initialization. The caller maps the same
+page frame in its virtual space and uses this buffer to exchange string
+parameters with filesystem primitives.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``INIT``
+uint64_t Physical address of the shared buffer.
+======== ============================================================
+
+Return values
+^^^^^^^^^^^^^
+
+=============== ======================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == DEBUGFS_E_INVALID_PARAMS if already initialized,
+ or internal error occurred.
+=============== ======================================================
+
+VERSION
+~~~~~~~
+
+Description
+^^^^^^^^^^^
+Returns the debugfs interface version if implemented in TF-A.
+
+Parameters
+^^^^^^^^^^
+
+======== ============================================================
+uint32_t FunctionID (0x82000030 / 0xC2000030)
+uint32_t ``VERSION``
+======== ============================================================
+
+Return values
+^^^^^^^^^^^^^
+
+=============== ======================================================
+int32_t w0 == SMC_OK on success
+
+ w0 == SMC_UNK if interface is not implemented
+
+uint32_t w1: On success, debugfs interface version, 32 bits
+ value with major version number in upper 16 bits and
+ minor version in lower 16 bits.
+=============== ======================================================
+
+* CREATE(1) and WRITE (5) command identifiers are unimplemented and
+ return `SMC_UNK`.
+
--------------
*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/components/debugfs-design.rst b/docs/components/debugfs-design.rst
new file mode 100644
index 000000000..06916f3d9
--- /dev/null
+++ b/docs/components/debugfs-design.rst
@@ -0,0 +1,132 @@
+========
+Debug FS
+========
+
+.. contents::
+
+Overview
+--------
+
+The *DebugFS* feature is primarily aimed at exposing firmware debug data to
+higher SW layers such as a non-secure component. Such component can be the
+TFTF test payload or a Linux kernel module.
+
+Virtual filesystem
+------------------
+
+The core functionality lies in a virtual file system based on a 9p file server
+interface (`Notes on the Plan 9 Kernel Source`_). The implementation permits
+exposing virtual files, firmware drivers, and file blobs.
+
+Namespace
+~~~~~~~~~
+
+Two namespaces are exposed:
+
+ - # is used as root for drivers (e.g. #t0 is the first uart)
+ - / is used as root for virtual "files" (e.g. /fip, or /dev/uart)
+
+9p interface
+~~~~~~~~~~~~
+
+The associated primitives are:
+
+- Unix-like:
+
+ - open(): create a file descriptor that acts as a handle to the file passed as
+ an argument.
+ - close(): close the file descriptor created by open().
+ - read(): read from a file to a buffer.
+ - write(): write from a buffer to a file.
+ - seek(): set the file position indicator of a file descriptor either to a
+ relative or an absolute offset.
+ - stat(): get information about a file (type, mode, size, ...).
+
+.. code:: c
+
+ int open(const char *name, int flags);
+ int close(int fd);
+ int read(int fd, void *buf, int n);
+ int write(int fd, void *buf, int n);
+ int seek(int fd, long off, int whence);
+ int stat(char *path, dir_t *dir);
+
+- Specific primitives :
+
+ - mount(): create a link between a driver and spec.
+ - create(): create a file in a specific location.
+ - bind(): expose the content of a directory to another directory.
+
+.. code:: c
+
+ int mount(char *srv, char *mnt, char *spec);
+ int create(const char *name, int flags);
+ int bind(char *path, char *where);
+
+This interface is embedded into the BL31 run-time payload when selected by build
+options. The interface multiplexes drivers or emulated "files":
+
+- Debug data can be partitioned into different virtual files e.g. expose PMF
+ measurements through a file, and internal firmware state counters through
+ another file.
+- This permits direct access to a firmware driver, mainly for test purposes
+ (e.g. a hardware device that may not be accessible to non-privileged/
+ non-secure layers, or for which no support exists in the NS side).
+
+SMC interface
+-------------
+
+The communication with the 9p layer in BL31 is made through an SMC conduit
+(`SMC Calling Convention PDD`_), using a specific SiP Function Id. An NS shared
+buffer is used to pass path string parameters, or e.g. to exchange data on a
+read operation. Refer to `ARM SiP Services`_ for a description of the SMC
+interface.
+
+Security considerations
+-----------------------
+
+- Due to the nature of the exposed data, the feature is considered experimental
+ and importantly **shall only be used in debug builds**.
+- Several primitive imply string manipulations and usage of string formats.
+- Special care is taken with the shared buffer to avoid TOCTOU attacks.
+
+Limitations
+-----------
+
+- In order to setup the shared buffer, the component consuming the interface
+ needs to allocate a physical page frame and transmit its address.
+- In order to map the shared buffer, BL31 requires enabling the dynamic xlat
+ table option.
+- Data exchange is limited by the shared buffer length. A large read operation
+ might be split into multiple read operations of smaller chunks.
+- On concurrent access, a spinlock is implemented in the BL31 service to protect
+ the internal work buffer, and re-entrancy into the filesystem layers.
+- Notice, a physical device driver if exposed by the firmware may conflict with
+ the higher level OS if the latter implements its own driver for the same
+ physical device.
+
+Applications
+------------
+
+The SMC interface is accessible from an NS environment, that is:
+
+- a test payload, bootloader or hypervisor running at NS-EL2
+- a Linux kernel driver running at NS-EL1
+- a Linux userspace application through the kernel driver
+
+References
+----------
+
+.. [#] `SMC Calling Convention PDD`_
+.. [#] `Notes on the Plan 9 Kernel Source`_
+.. [#] `Linux 9p remote filesystem protocol`_
+.. [#] `ARM SiP Services`_
+
+--------------
+
+*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
+
+.. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/
+.. _Notes on the Plan 9 Kernel Source: http://lsub.org/who/nemo/9.pdf
+.. _Linux 9p remote filesystem protocol: https://www.kernel.org/doc/Documentation/filesystems/9p.txt
+.. _ARM SiP Services: arm-sip-service.rst
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 051586bc3..469fd34b7 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -544,6 +544,10 @@ Common build options
(Coherent memory region is included) or 0 (Coherent memory region is
excluded). Default is 1.
+- ``USE_DEBUGFS``: When set to 1 this option activates an EXPERIMENTAL feature
+ exposing a virtual filesystem interface through BL31 as a SiP SMC function.
+ Default is 0.
+
- ``USE_ROMLIB``: This flag determines whether library at ROM will be used.
This feature creates a library of functions to be placed in ROM and thus
reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default
diff --git a/include/lib/debugfs.h b/include/lib/debugfs.h
index b7e33303c..8ed237ae2 100644
--- a/include/lib/debugfs.h
+++ b/include/lib/debugfs.h
@@ -56,5 +56,28 @@ int stat(const char *path, dir_t *dir);
/* DebugFS initialization */
void debugfs_init(void);
+int debugfs_smc_setup(void);
+
+/* Debugfs version returned through SMC interface */
+#define DEBUGFS_VERSION (0x000000001U)
+
+/* Function ID for accessing the debugfs interface */
+#define DEBUGFS_FID_VALUE (0x30U)
+
+#define is_debugfs_fid(_fid) \
+ (((_fid) & FUNCID_NUM_MASK) == DEBUGFS_FID_VALUE)
+
+/* Error code for debugfs SMC interface failures */
+#define DEBUGFS_E_INVALID_PARAMS (-2)
+#define DEBUGFS_E_DENIED (-3)
+
+uintptr_t debugfs_smc_handler(unsigned int smc_fid,
+ u_register_t cmd,
+ u_register_t arg2,
+ u_register_t arg3,
+ u_register_t arg4,
+ void *cookie,
+ void *handle,
+ uintptr_t flags);
#endif /* DEBUGFS_H */
diff --git a/include/plat/arm/common/arm_sip_svc.h b/include/plat/arm/common/arm_sip_svc.h
index 16573ce6a..85fdb289f 100644
--- a/include/plat/arm/common/arm_sip_svc.h
+++ b/include/plat/arm/common/arm_sip_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,9 +16,15 @@
/* U(0x8200ff02) is reserved */
#define ARM_SIP_SVC_VERSION U(0x8200ff03)
+/* PMF_SMC_GET_TIMESTAMP_32 0x82000010 */
+/* PMF_SMC_GET_TIMESTAMP_64 0xC2000010 */
+
/* Function ID for requesting state switch of lower EL */
#define ARM_SIP_SVC_EXE_STATE_SWITCH U(0x82000020)
+/* DEBUGFS_SMC_32 0x82000030U */
+/* DEBUGFS_SMC_64 0xC2000030U */
+
/* ARM SiP Service Calls version numbers */
#define ARM_SIP_SVC_VERSION_MAJOR U(0x0)
#define ARM_SIP_SVC_VERSION_MINOR U(0x2)
diff --git a/lib/debugfs/debugfs.mk b/lib/debugfs/debugfs.mk
index 2c0260006..138fc72a1 100644
--- a/lib/debugfs/debugfs.mk
+++ b/lib/debugfs/debugfs.mk
@@ -9,3 +9,5 @@ DEBUGFS_SRCS := $(addprefix lib/debugfs/, \
devc.c \
devroot.c \
devfip.c)
+
+DEBUGFS_SRCS += lib/debugfs/debugfs_smc.c
diff --git a/lib/debugfs/debugfs_smc.c b/lib/debugfs/debugfs_smc.c
new file mode 100644
index 000000000..400c166d7
--- /dev/null
+++ b/lib/debugfs/debugfs_smc.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <lib/debugfs.h>
+#include <lib/smccc.h>
+#include <lib/spinlock.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <smccc_helpers.h>
+
+#define MAX_PATH_LEN 256
+
+#define MOUNT 0
+#define CREATE 1
+#define OPEN 2
+#define CLOSE 3
+#define READ 4
+#define WRITE 5
+#define SEEK 6
+#define BIND 7
+#define STAT 8
+#define INIT 10
+#define VERSION 11
+
+/* This is the virtual address to which we map the NS shared buffer */
+#define DEBUGFS_SHARED_BUF_VIRT ((void *)0x81000000U)
+
+static union debugfs_parms {
+ struct {
+ char fname[MAX_PATH_LEN];
+ } open;
+
+ struct {
+ char srv[MAX_PATH_LEN];
+ char where[MAX_PATH_LEN];
+ char spec[MAX_PATH_LEN];
+ } mount;
+
+ struct {
+ char path[MAX_PATH_LEN];
+ dir_t dir;
+ } stat;
+
+ struct {
+ char oldpath[MAX_PATH_LEN];
+ char newpath[MAX_PATH_LEN];
+ } bind;
+} parms;
+
+/* debugfs_access_lock protects shared buffer and internal */
+/* FS functions from concurrent acccesses. */
+static spinlock_t debugfs_access_lock;
+
+static bool debugfs_initialized;
+
+uintptr_t debugfs_smc_handler(unsigned int smc_fid,
+ u_register_t cmd,
+ u_register_t arg2,
+ u_register_t arg3,
+ u_register_t arg4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ int64_t smc_ret = DEBUGFS_E_INVALID_PARAMS, smc_resp = 0;
+ int ret;
+
+ /* Allow calls from non-secure only */
+ if (is_caller_secure(flags)) {
+ SMC_RET1(handle, DEBUGFS_E_DENIED);
+ }
+
+ /* Expect a SiP service fast call */
+ if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
+ (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ /* Truncate parameters if 32b SMC convention call */
+ if (GET_SMC_CC(smc_fid) == SMC_32) {
+ arg2 &= 0xffffffff;
+ arg3 &= 0xffffffff;
+ arg4 &= 0xffffffff;
+ }
+
+ spin_lock(&debugfs_access_lock);
+
+ if (debugfs_initialized == true) {
+ /* Copy NS shared buffer to internal secure location */
+ memcpy(&parms, (void *)DEBUGFS_SHARED_BUF_VIRT,
+ sizeof(union debugfs_parms));
+ }
+
+ switch (cmd) {
+ case INIT:
+ if (debugfs_initialized == false) {
+ /* TODO: check PA validity e.g. whether */
+ /* it is an NS region. */
+ ret = mmap_add_dynamic_region(arg2,
+ (uintptr_t)DEBUGFS_SHARED_BUF_VIRT,
+ PAGE_SIZE_4KB,
+ MT_MEMORY | MT_RW | MT_NS);
+ if (ret == 0) {
+ debugfs_initialized = true;
+ smc_ret = SMC_OK;
+ smc_resp = 0;
+ }
+ }
+ break;
+
+ case VERSION:
+ smc_ret = SMC_OK;
+ smc_resp = DEBUGFS_VERSION;
+ break;
+
+ case MOUNT:
+ ret = mount(parms.mount.srv,
+ parms.mount.where,
+ parms.mount.spec);
+ if (ret == 0) {
+ smc_ret = SMC_OK;
+ smc_resp = 0;
+ }
+ break;
+
+ case OPEN:
+ ret = open(parms.open.fname, arg2);
+ if (ret >= 0) {
+ smc_ret = SMC_OK;
+ smc_resp = ret;
+ }
+ break;
+
+ case CLOSE:
+ ret = close(arg2);
+ if (ret == 0) {
+ smc_ret = SMC_OK;
+ smc_resp = 0;
+ }
+ break;
+
+ case READ:
+ ret = read(arg2, DEBUGFS_SHARED_BUF_VIRT, arg3);
+ if (ret >= 0) {
+ smc_ret = SMC_OK;
+ smc_resp = ret;
+ }
+ break;
+
+ case SEEK:
+ ret = seek(arg2, arg3, arg4);
+ if (ret == 0) {
+ smc_ret = SMC_OK;
+ smc_resp = 0;
+ }
+ break;
+
+ case BIND:
+ ret = bind(parms.bind.oldpath, parms.bind.newpath);
+ if (ret == 0) {
+ smc_ret = SMC_OK;
+ smc_resp = 0;
+ }
+ break;
+
+ case STAT:
+ ret = stat(parms.stat.path, &parms.stat.dir);
+ if (ret == 0) {
+ memcpy((void *)DEBUGFS_SHARED_BUF_VIRT, &parms,
+ sizeof(union debugfs_parms));
+ smc_ret = SMC_OK;
+ smc_resp = 0;
+ }
+ break;
+
+ /* Not implemented */
+ case CREATE:
+ /* Intentional fall-through */
+
+ /* Not implemented */
+ case WRITE:
+ /* Intentional fall-through */
+
+ default:
+ smc_ret = SMC_UNK;
+ smc_resp = 0;
+ }
+
+ spin_unlock(&debugfs_access_lock);
+
+ SMC_RET2(handle, smc_ret, smc_resp);
+
+ /* Not reached */
+ return smc_ret;
+}
+
+int debugfs_smc_setup(void)
+{
+ debugfs_initialized = false;
+ debugfs_access_lock.lock = 0;
+
+ return 0;
+}
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index a94879624..5c0df7a7d 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -122,6 +122,10 @@ const mmap_region_t plat_arm_mmap[] = {
#ifdef IMAGE_BL31
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
+#if USE_DEBUGFS
+ /* Required by devfip, can be removed if devfip is not used */
+ V2M_MAP_FLASH0_RW,
+#endif /* USE_DEBUGFS */
ARM_MAP_EL3_TZC_DRAM,
V2M_MAP_IOFPGA,
MAP_DEVICE0,
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 98dd0a97f..2b441747a 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -68,7 +68,11 @@
# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
# else
# define PLAT_ARM_MMAP_ENTRIES 8
-# define MAX_XLAT_TABLES 5
+# if USE_DEBUGFS
+# define MAX_XLAT_TABLES 6
+# else
+# define MAX_XLAT_TABLES 5
+# endif
# endif
#elif defined(IMAGE_BL32)
# define PLAT_ARM_MMAP_ENTRIES 8
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 3a9972bb4..8cf2612a7 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -291,6 +291,10 @@ else # if AArch64
endif
endif
+ifeq (${USE_DEBUGFS},1)
+ BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
+endif
+
# Add support for platform supplied linker script for BL31 build
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index ab90f46a8..939885f98 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,7 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/console.h>
+#include <lib/debugfs.h>
#include <lib/extensions/ras.h>
#include <lib/mmio.h>
#include <lib/utils.h>
@@ -231,6 +232,10 @@ void arm_bl31_platform_setup(void)
#if RAS_EXTENSION
ras_init();
#endif
+
+#if USE_DEBUGFS
+ debugfs_init();
+#endif /* USE_DEBUGFS */
}
/*******************************************************************************
diff --git a/plat/arm/common/arm_sip_svc.c b/plat/arm/common/arm_sip_svc.c
index 3d308a335..c8f480f18 100644
--- a/plat/arm/common/arm_sip_svc.c
+++ b/plat/arm/common/arm_sip_svc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,7 @@
#include <common/debug.h>
#include <common/runtime_svc.h>
+#include <lib/debugfs.h>
#include <lib/pmf/pmf.h>
#include <plat/arm/common/arm_sip_svc.h>
#include <plat/arm/common/plat_arm.h>
@@ -20,8 +21,18 @@ DEFINE_SVC_UUID2(arm_sip_svc_uid,
static int arm_sip_setup(void)
{
- if (pmf_setup() != 0)
+ if (pmf_setup() != 0) {
return 1;
+ }
+
+#if USE_DEBUGFS
+
+ if (debugfs_smc_setup() != 0) {
+ return 1;
+ }
+
+#endif /* USE_DEBUGFS */
+
return 0;
}
@@ -48,6 +59,15 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid,
handle, flags);
}
+#if USE_DEBUGFS
+
+ if (is_debugfs_fid(smc_fid)) {
+ return debugfs_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+
+#endif /* USE_DEBUGFS */
+
switch (smc_fid) {
case ARM_SIP_SVC_EXE_STATE_SWITCH: {
u_register_t pc;