diff options
author | Ambroise Vincent <ambroise.vincent@arm.com> | 2019-07-12 13:47:03 +0100 |
---|---|---|
committer | Olivier Deprez <olivier.deprez@arm.com> | 2019-12-18 09:59:12 +0100 |
commit | 992f091b5de3b0837c95a338a4e739f6ca2f254f (patch) | |
tree | 59bd4557e49cc2dcd57aee496356c7e8cb55f040 /docs/components | |
parent | d310239d775c34d237b8c4b81baa6f6a12207824 (diff) | |
download | platform_external_arm-trusted-firmware-992f091b5de3b0837c95a338a4e739f6ca2f254f.tar.gz platform_external_arm-trusted-firmware-992f091b5de3b0837c95a338a4e739f6ca2f254f.tar.bz2 platform_external_arm-trusted-firmware-992f091b5de3b0837c95a338a4e739f6ca2f254f.zip |
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
Diffstat (limited to 'docs/components')
-rw-r--r-- | docs/components/arm-sip-service.rst | 341 | ||||
-rw-r--r-- | docs/components/debugfs-design.rst | 132 |
2 files changed, 473 insertions, 0 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 |