1
0
Fork 0

firmware: add Intel Stratix10 service layer driver

Some features of the Intel Stratix10 SoC require a level of privilege
higher than the kernel is granted. Such secure features include
FPGA programming. In terms of the ARMv8 architecture, the kernel runs
at Exception Level 1 (EL1), access to the features requires
Exception Level 3 (EL3).

The Intel Stratix10 SoC service layer provides an in kernel API for
drivers to request access to the secure features. The requests are queued
and processed one by one. ARM’s SMCCC is used to pass the execution
of the requests on to a secure monitor (EL3).

The header file stratix10-sve-client.h defines the interface between
service providers (FPGA manager is one of them) and service layer.

The header file stratix10-smc.h defines the secure monitor call (SMC)
message protocols used for service layer driver in normal world
(EL1) to communicate with secure monitor SW in secure monitor exception
level 3 (EL3).

Signed-off-by: Richard Gong <richard.gong@intel.com>
Signed-off-by: Alan Tull <atull@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
hifive-unleashed-5.1
Richard Gong 2018-11-13 12:14:01 -06:00 committed by Greg Kroah-Hartman
parent adb9e3543d
commit 7ca5ce8965
5 changed files with 1492 additions and 0 deletions

View File

@ -216,6 +216,18 @@ config FW_CFG_SYSFS_CMDLINE
WARNING: Using incorrect parameters (base address in particular)
may crash your system.
config INTEL_STRATIX10_SERVICE
tristate "Intel Stratix10 Service Layer"
depends on HAVE_ARM_SMCCC
default n
help
Intel Stratix10 service layer runs at privileged exception level,
interfaces with the service providers (FPGA manager is one of them)
and manages secure monitor call to communicate with secure monitor
software at secure monitor exception level.
Say Y here if you want Stratix10 service layer support.
config QCOM_SCM
bool
depends on ARM || ARM64

View File

@ -12,6 +12,7 @@ obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
obj-$(CONFIG_EDD) += edd.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DMIID) += dmi-id.o
obj-$(CONFIG_INTEL_STRATIX10_SERVICE) += stratix10-svc.o
obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,265 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017-2018, Intel Corporation
*/
#ifndef __STRATIX10_SMC_H
#define __STRATIX10_SMC_H
#include <linux/arm-smccc.h>
#include <linux/bitops.h>
/**
* This file defines the Secure Monitor Call (SMC) message protocol used for
* service layer driver in normal world (EL1) to communicate with secure
* monitor software in Secure Monitor Exception Level 3 (EL3).
*
* This file is shared with secure firmware (FW) which is out of kernel tree.
*
* An ARM SMC instruction takes a function identifier and up to 6 64-bit
* register values as arguments, and can return up to 4 64-bit register
* value. The operation of the secure monitor is determined by the parameter
* values passed in through registers.
*
* EL1 and EL3 communicates pointer as physical address rather than the
* virtual address.
*
* Functions specified by ARM SMC Calling convention:
*
* FAST call executes atomic operations, returns when the requested operation
* has completed.
* STD call starts a operation which can be preempted by a non-secure
* interrupt. The call can return before the requested operation has
* completed.
*
* a0..a7 is used as register names in the descriptions below, on arm32
* that translates to r0..r7 and on arm64 to w0..w7.
*/
/**
* @func_num: function ID
*/
#define INTEL_SIP_SMC_STD_CALL_VAL(func_num) \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_64, \
ARM_SMCCC_OWNER_SIP, (func_num))
#define INTEL_SIP_SMC_FAST_CALL_VAL(func_num) \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
ARM_SMCCC_OWNER_SIP, (func_num))
/**
* Return values in INTEL_SIP_SMC_* call
*
* INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION:
* Secure monitor software doesn't recognize the request.
*
* INTEL_SIP_SMC_STATUS_OK:
* FPGA configuration completed successfully,
* In case of FPGA configuration write operation, it means secure monitor
* software can accept the next chunk of FPGA configuration data.
*
* INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY:
* In case of FPGA configuration write operation, it means secure monitor
* software is still processing previous data & can't accept the next chunk
* of data. Service driver needs to issue
* INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE call to query the
* completed block(s).
*
* INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR:
* There is error during the FPGA configuration process.
*/
#define INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
#define INTEL_SIP_SMC_STATUS_OK 0x0
#define INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY 0x1
#define INTEL_SIP_SMC_FPGA_CONFIG_STATUS_REJECTED 0x2
#define INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR 0x4
#define INTEL_SIP_SMC_REG_ERROR 0x5
/**
* Request INTEL_SIP_SMC_FPGA_CONFIG_START
*
* Sync call used by service driver at EL1 to request the FPGA in EL3 to
* be prepare to receive a new configuration.
*
* Call register usage:
* a0: INTEL_SIP_SMC_FPGA_CONFIG_START.
* a1: flag for full or partial configuration. 0 for full and 1 for partial
* configuration.
* a2-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK, or INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
* a1-3: not used.
*/
#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START 1
#define INTEL_SIP_SMC_FPGA_CONFIG_START \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START)
/**
* Request INTEL_SIP_SMC_FPGA_CONFIG_WRITE
*
* Async call used by service driver at EL1 to provide FPGA configuration data
* to secure world.
*
* Call register usage:
* a0: INTEL_SIP_SMC_FPGA_CONFIG_WRITE.
* a1: 64bit physical address of the configuration data memory block
* a2: Size of configuration data block.
* a3-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY or
* INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
* a1: 64bit physical address of 1st completed memory block if any completed
* block, otherwise zero value.
* a2: 64bit physical address of 2nd completed memory block if any completed
* block, otherwise zero value.
* a3: 64bit physical address of 3rd completed memory block if any completed
* block, otherwise zero value.
*/
#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE 2
#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE \
INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE)
/**
* Request INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE
*
* Sync call used by service driver at EL1 to track the completed write
* transactions. This request is called after INTEL_SIP_SMC_FPGA_CONFIG_WRITE
* call returns INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY.
*
* Call register usage:
* a0: INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE.
* a1-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY or
* INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
* a1: 64bit physical address of 1st completed memory block.
* a2: 64bit physical address of 2nd completed memory block if
* any completed block, otherwise zero value.
* a3: 64bit physical address of 3rd completed memory block if
* any completed block, otherwise zero value.
*/
#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE 3
#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
/**
* Request INTEL_SIP_SMC_FPGA_CONFIG_ISDONE
*
* Sync call used by service driver at EL1 to inform secure world that all
* data are sent, to check whether or not the secure world had completed
* the FPGA configuration process.
*
* Call register usage:
* a0: INTEL_SIP_SMC_FPGA_CONFIG_ISDONE.
* a1-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY or
* INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
* a1-3: not used.
*/
#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE 4
#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE)
/**
* Request INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM
*
* Sync call used by service driver at EL1 to query the physical address of
* memory block reserved by secure monitor software.
*
* Call register usage:
* a0:INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM.
* a1-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
* a1: start of physical address of reserved memory block.
* a2: size of reserved memory block.
* a3: not used.
*/
#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM 5
#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM)
/**
* Request INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK
*
* For SMC loop-back mode only, used for internal integration, debugging
* or troubleshooting.
*
* Call register usage:
* a0: INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK.
* a1-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
* a1-3: not used.
*/
#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK 6
#define INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK)
/*
* Request INTEL_SIP_SMC_REG_READ
*
* Read a protected register at EL3
*
* Call register usage:
* a0: INTEL_SIP_SMC_REG_READ.
* a1: register address.
* a2-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
* a1: value in the register
* a2-3: not used.
*/
#define INTEL_SIP_SMC_FUNCID_REG_READ 7
#define INTEL_SIP_SMC_REG_READ \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_READ)
/*
* Request INTEL_SIP_SMC_REG_WRITE
*
* Write a protected register at EL3
*
* Call register usage:
* a0: INTEL_SIP_SMC_REG_WRITE.
* a1: register address
* a2: value to program into register.
* a3-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
* a1-3: not used.
*/
#define INTEL_SIP_SMC_FUNCID_REG_WRITE 8
#define INTEL_SIP_SMC_REG_WRITE \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_WRITE)
/*
* Request INTEL_SIP_SMC_FUNCID_REG_UPDATE
*
* Update one or more bits in a protected register at EL3 using a
* read-modify-write operation.
*
* Call register usage:
* a0: INTEL_SIP_SMC_REG_UPDATE.
* a1: register address
* a2: write Mask.
* a3: value to write.
* a4-7: not used.
*
* Return status:
* a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
* a1-3: Not used.
*/
#define INTEL_SIP_SMC_FUNCID_REG_UPDATE 9
#define INTEL_SIP_SMC_REG_UPDATE \
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_UPDATE)
#endif

View File

@ -0,0 +1,201 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2017-2018, Intel Corporation
*/
#ifndef __STRATIX10_SVC_CLIENT_H
#define __STRATIX10_SVC_CLIENT_H
/**
* Service layer driver supports client names
*
* fpga: for FPGA configuration
*/
#define SVC_CLIENT_FPGA "fpga"
/**
* Status of the sent command, in bit number
*
* SVC_COMMAND_STATUS_RECONFIG_REQUEST_OK:
* Secure firmware accepts the request of FPGA reconfiguration.
*
* SVC_STATUS_RECONFIG_BUFFER_SUBMITTED:
* Service client successfully submits FPGA configuration
* data buffer to secure firmware.
*
* SVC_COMMAND_STATUS_RECONFIG_BUFFER_DONE:
* Secure firmware completes data process, ready to accept the
* next WRITE transaction.
*
* SVC_COMMAND_STATUS_RECONFIG_COMPLETED:
* Secure firmware completes FPGA configuration successfully, FPGA should
* be in user mode.
*
* SVC_COMMAND_STATUS_RECONFIG_BUSY:
* FPGA configuration is still in process.
*
* SVC_COMMAND_STATUS_RECONFIG_ERROR:
* Error encountered during FPGA configuration.
*/
#define SVC_STATUS_RECONFIG_REQUEST_OK 0
#define SVC_STATUS_RECONFIG_BUFFER_SUBMITTED 1
#define SVC_STATUS_RECONFIG_BUFFER_DONE 2
#define SVC_STATUS_RECONFIG_COMPLETED 3
#define SVC_STATUS_RECONFIG_BUSY 4
#define SVC_STATUS_RECONFIG_ERROR 5
/**
* Flag bit for COMMAND_RECONFIG
*
* COMMAND_RECONFIG_FLAG_PARTIAL:
* Set to FPGA configuration type (full or partial), the default
* is full reconfig.
*/
#define COMMAND_RECONFIG_FLAG_PARTIAL 0
/**
* Timeout settings for service clients:
* timeout value used in Stratix10 FPGA manager driver.
*/
#define SVC_RECONFIG_REQUEST_TIMEOUT_MS 100
#define SVC_RECONFIG_BUFFER_TIMEOUT_MS 240
struct stratix10_svc_chan;
/**
* enum stratix10_svc_command_code - supported service commands
*
* @COMMAND_NOOP: do 'dummy' request for integration/debug/trouble-shooting
*
* @COMMAND_RECONFIG: ask for FPGA configuration preparation, return status
* is SVC_STATUS_RECONFIG_REQUEST_OK
*
* @COMMAND_RECONFIG_DATA_SUBMIT: submit buffer(s) of bit-stream data for the
* FPGA configuration, return status is SVC_STATUS_RECONFIG_BUFFER_SUBMITTED,
* or SVC_STATUS_RECONFIG_ERROR
*
* @COMMAND_RECONFIG_DATA_CLAIM: check the status of the configuration, return
* status is SVC_STATUS_RECONFIG_COMPLETED, or SVC_STATUS_RECONFIG_BUSY, or
* SVC_STATUS_RECONFIG_ERROR
*
* @COMMAND_RECONFIG_STATUS: check the status of the configuration, return
* status is SVC_STATUS_RECONFIG_COMPLETED, or SVC_STATUS_RECONFIG_BUSY, or
* SVC_STATUS_RECONFIG_ERROR
*/
enum stratix10_svc_command_code {
COMMAND_NOOP = 0,
COMMAND_RECONFIG,
COMMAND_RECONFIG_DATA_SUBMIT,
COMMAND_RECONFIG_DATA_CLAIM,
COMMAND_RECONFIG_STATUS
};
/**
* struct stratix10_svc_client_msg - message sent by client to service
* @payload: starting address of data need be processed
* @payload_length: data size in bytes
* @command: service command
* @arg: args to be passed via registers and not physically mapped buffers
*/
struct stratix10_svc_client_msg {
void *payload;
size_t payload_length;
enum stratix10_svc_command_code command;
u64 arg[3];
};
/**
* struct stratix10_svc_command_config_type - config type
* @flags: flag bit for the type of FPGA configuration
*/
struct stratix10_svc_command_config_type {
u32 flags;
};
/**
* struct stratix10_svc_cb_data - callback data structure from service layer
* @status: the status of sent command
* @kaddr1: address of 1st completed data block
* @kaddr2: address of 2nd completed data block
* @kaddr3: address of 3rd completed data block
*/
struct stratix10_svc_cb_data {
u32 status;
void *kaddr1;
void *kaddr2;
void *kaddr3;
};
/**
* struct stratix10_svc_client - service client structure
* @dev: the client device
* @receive_cb: callback to provide service client the received data
* @priv: client private data
*/
struct stratix10_svc_client {
struct device *dev;
void (*receive_cb)(struct stratix10_svc_client *client,
struct stratix10_svc_cb_data *cb_data);
void *priv;
};
/**
* stratix10_svc_request_channel_byname() - request service channel
* @client: identity of the client requesting the channel
* @name: supporting client name defined above
*
* Return: a pointer to channel assigned to the client on success,
* or ERR_PTR() on error.
*/
struct stratix10_svc_chan
*stratix10_svc_request_channel_byname(struct stratix10_svc_client *client,
const char *name);
/**
* stratix10_svc_free_channel() - free service channel.
* @chan: service channel to be freed
*/
void stratix10_svc_free_channel(struct stratix10_svc_chan *chan);
/**
* stratix10_svc_allocate_memory() - allocate the momory
* @chan: service channel assigned to the client
* @size: number of bytes client requests
*
* Service layer allocates the requested number of bytes from the memory
* pool for the client.
*
* Return: the starting address of allocated memory on success, or
* ERR_PTR() on error.
*/
void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
size_t size);
/**
* stratix10_svc_free_memory() - free allocated memory
* @chan: service channel assigned to the client
* @kaddr: starting address of memory to be free back to pool
*/
void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr);
/**
* stratix10_svc_send() - send a message to the remote
* @chan: service channel assigned to the client
* @msg: message data to be sent, in the format of
* struct stratix10_svc_client_msg
*
* Return: 0 for success, -ENOMEM or -ENOBUFS on error.
*/
int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg);
/**
* intel_svc_done() - complete service request
* @chan: service channel assigned to the client
*
* This function is used by service client to inform service layer that
* client's service requests are completed, or there is an error in the
* request process.
*/
void stratix10_svc_done(struct stratix10_svc_chan *chan);
#endif