mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
powerpc/pseries: Add ibm,set-dynamic-indicator RTAS call support
The RTAS call ibm,set-dynamic-indicator is used to set the new
indicator state identified by a location code. The current
implementation uses rtas_set_dynamic_indicator() API provided by
librtas library which allocates RMO buffer and issue this RTAS
call in the user space. But /dev/mem access by the user space
is prohibited under system lockdown.
This patch provides an interface with new ioctl
PAPR_DYNAMIC_INDICATOR_IOC_SET to the papr-indices character
driver and expose this interface to the user space that is
compatible with lockdown.
Refer PAPR 7.3.18 ibm,set-dynamic-indicator for more
information on this RTAS call.
- User input parameters to the RTAS call: location code
string, indicator token and new state
Expose these interfaces to user space with a /dev/papr-indices
character device using the following programming model:
int fd = open("/dev/papr-indices", O_RDWR);
int ret = ioctl(fd, PAPR_DYNAMIC_INDICATOR_IOC_SET,
struct papr_indices_io_block)
- The user space passes input parameters in papr_indices_io_block
struct
Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Tested-by: Sathvika Vasireddy <sv@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20250416225743.596462-5-haren@linux.ibm.com
This commit is contained in:
parent
6e9aec5446
commit
f60a3796f8
|
|
@ -516,6 +516,7 @@ extern unsigned long rtas_rmo_buf;
|
|||
|
||||
extern struct mutex rtas_ibm_get_vpd_lock;
|
||||
extern struct mutex rtas_ibm_get_indices_lock;
|
||||
extern struct mutex rtas_ibm_set_dynamic_indicator_lock;
|
||||
|
||||
#define GLOBAL_INTERRUPT_QUEUE 9005
|
||||
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ static DEFINE_MUTEX(rtas_ibm_activate_firmware_lock);
|
|||
static DEFINE_MUTEX(rtas_ibm_get_dynamic_sensor_state_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_lpar_perftools_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_physical_attestation_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_set_dynamic_indicator_lock);
|
||||
DEFINE_MUTEX(rtas_ibm_get_vpd_lock);
|
||||
DEFINE_MUTEX(rtas_ibm_get_indices_lock);
|
||||
DEFINE_MUTEX(rtas_ibm_set_dynamic_indicator_lock);
|
||||
|
||||
static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
[RTAS_FNIDX__CHECK_EXCEPTION] = {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@
|
|||
#include <uapi/asm/papr-indices.h>
|
||||
#include "papr-rtas-common.h"
|
||||
|
||||
/*
|
||||
* Function-specific return values for ibm,set-dynamic-indicator and
|
||||
* ibm,get-dynamic-sensor-state RTAS calls.
|
||||
* PAPR+ v2.13 7.3.18 and 7.3.19.
|
||||
*/
|
||||
#define RTAS_IBM_DYNAMIC_INDICE_NO_INDICATOR -3
|
||||
|
||||
/**
|
||||
* struct rtas_get_indices_params - Parameters (in and out) for
|
||||
* ibm,get-indices.
|
||||
|
|
@ -260,6 +267,110 @@ static long papr_indices_create_handle(struct papr_indices_io_block __user *ubuf
|
|||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create work area with the input parameters. This function is used
|
||||
* for both ibm,set-dynamic-indicator and ibm,get-dynamic-sensor-state
|
||||
* RTAS Calls.
|
||||
*/
|
||||
static struct rtas_work_area *
|
||||
papr_dynamic_indice_buf_from_user(struct papr_indices_io_block __user *ubuf,
|
||||
struct papr_indices_io_block *kbuf)
|
||||
{
|
||||
struct rtas_work_area *work_area;
|
||||
u32 length;
|
||||
__be32 len_be;
|
||||
|
||||
if (copy_from_user(kbuf, ubuf, sizeof(*kbuf)))
|
||||
return ERR_PTR(-EFAULT);
|
||||
|
||||
|
||||
if (!string_is_terminated(kbuf->dynamic_param.location_code_str,
|
||||
ARRAY_SIZE(kbuf->dynamic_param.location_code_str)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/*
|
||||
* The input data in the work area should be as follows:
|
||||
* - 32-bit integer length of the location code string,
|
||||
* including NULL.
|
||||
* - Location code string, NULL terminated, identifying the
|
||||
* token (sensor or indicator).
|
||||
* PAPR 2.13 - R1–7.3.18–5 ibm,set-dynamic-indicator
|
||||
* - R1–7.3.19–5 ibm,get-dynamic-sensor-state
|
||||
*/
|
||||
/*
|
||||
* Length that user space passed should also include NULL
|
||||
* terminator.
|
||||
*/
|
||||
length = strlen(kbuf->dynamic_param.location_code_str) + 1;
|
||||
if (length > LOC_CODE_SIZE)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
len_be = cpu_to_be32(length);
|
||||
|
||||
work_area = rtas_work_area_alloc(LOC_CODE_SIZE + sizeof(u32));
|
||||
memcpy(rtas_work_area_raw_buf(work_area), &len_be, sizeof(u32));
|
||||
memcpy((rtas_work_area_raw_buf(work_area) + sizeof(u32)),
|
||||
&kbuf->dynamic_param.location_code_str, length);
|
||||
|
||||
return work_area;
|
||||
}
|
||||
|
||||
/**
|
||||
* papr_dynamic_indicator_ioc_set - ibm,set-dynamic-indicator RTAS Call
|
||||
* PAPR 2.13 7.3.18
|
||||
*
|
||||
* @ubuf: Input parameters to RTAS call such as indicator token and
|
||||
* new state.
|
||||
*
|
||||
* Returns success or -errno.
|
||||
*/
|
||||
static long papr_dynamic_indicator_ioc_set(struct papr_indices_io_block __user *ubuf)
|
||||
{
|
||||
struct papr_indices_io_block kbuf;
|
||||
struct rtas_work_area *work_area;
|
||||
s32 fwrc, token, ret;
|
||||
|
||||
token = rtas_function_token(RTAS_FN_IBM_SET_DYNAMIC_INDICATOR);
|
||||
if (token == RTAS_UNKNOWN_SERVICE)
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&rtas_ibm_set_dynamic_indicator_lock);
|
||||
work_area = papr_dynamic_indice_buf_from_user(ubuf, &kbuf);
|
||||
if (IS_ERR(work_area)) {
|
||||
ret = PTR_ERR(work_area);
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
fwrc = rtas_call(token, 3, 1, NULL,
|
||||
kbuf.dynamic_param.token,
|
||||
kbuf.dynamic_param.state,
|
||||
rtas_work_area_phys(work_area));
|
||||
} while (rtas_busy_delay(fwrc));
|
||||
|
||||
rtas_work_area_free(work_area);
|
||||
|
||||
switch (fwrc) {
|
||||
case RTAS_SUCCESS:
|
||||
ret = 0;
|
||||
break;
|
||||
case RTAS_IBM_DYNAMIC_INDICE_NO_INDICATOR: /* No such indicator */
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
default:
|
||||
pr_err("unexpected ibm,set-dynamic-indicator result %d\n",
|
||||
fwrc);
|
||||
fallthrough;
|
||||
case RTAS_HARDWARE_ERROR: /* Hardware/platform error */
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&rtas_ibm_set_dynamic_indicator_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Top-level ioctl handler for /dev/papr-indices.
|
||||
*/
|
||||
|
|
@ -273,6 +384,12 @@ static long papr_indices_dev_ioctl(struct file *filp, unsigned int ioctl,
|
|||
case PAPR_INDICES_IOC_GET:
|
||||
ret = papr_indices_create_handle(argp);
|
||||
break;
|
||||
case PAPR_DYNAMIC_INDICATOR_IOC_SET:
|
||||
if (filp->f_mode & FMODE_WRITE)
|
||||
ret = papr_dynamic_indicator_ioc_set(argp);
|
||||
else
|
||||
ret = -EBADF;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
|
|
@ -296,6 +413,9 @@ static __init int papr_indices_init(void)
|
|||
if (!rtas_function_implemented(RTAS_FN_IBM_GET_INDICES))
|
||||
return -ENODEV;
|
||||
|
||||
if (!rtas_function_implemented(RTAS_FN_IBM_SET_DYNAMIC_INDICATOR))
|
||||
return -ENODEV;
|
||||
|
||||
return misc_register(&papr_indices_dev);
|
||||
}
|
||||
machine_device_initcall(pseries, papr_indices_init);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user