Skip to content

Commit e536784

Browse files
author
Mamatha Inamdar
committed
powerpc/pseries: Add ibm,set-dynamic-indicator RTAS call support
JIRA: https://issues.redhat.com/browse/RHEL-101838 commit f60a379 Author: Haren Myneni <haren@linux.ibm.com> Date: Wed Apr 16 15:57:39 2025 -0700 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 Signed-off-by: Mamatha Inamdar <minamdar@redhat.com>
1 parent c5eac8d commit e536784

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

arch/powerpc/include/asm/rtas.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ extern unsigned long rtas_rmo_buf;
338338

339339
extern struct mutex rtas_ibm_get_vpd_lock;
340340
extern struct mutex rtas_ibm_get_indices_lock;
341+
extern struct mutex rtas_ibm_set_dynamic_indicator_lock;
341342

342343
#define GLOBAL_INTERRUPT_QUEUE 9005
343344

arch/powerpc/kernel/rtas.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ EXPORT_SYMBOL(rtas_flash_term_hook);
7878

7979
DEFINE_MUTEX(rtas_ibm_get_vpd_lock);
8080
DEFINE_MUTEX(rtas_ibm_get_indices_lock);
81+
DEFINE_MUTEX(rtas_ibm_set_dynamic_indicator_lock);
8182

8283
/* RTAS use home made raw locking instead of spin_lock_irqsave
8384
* because those can be called from within really nasty contexts
@@ -1122,6 +1123,9 @@ static struct mutex *find_rtas_mutex(int token)
11221123
if (token == rtas_token("ibm,get-indices"))
11231124
return &rtas_ibm_get_indices_lock;
11241125

1126+
if (token == rtas_token("ibm,set-dynamic-indicator"))
1127+
return &rtas_ibm_set_dynamic_indicator_lock;
1128+
11251129
return NULL;
11261130
}
11271131

arch/powerpc/platforms/pseries/papr-indices.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
#include <uapi/asm/papr-indices.h>
2121
#include "papr-rtas-common.h"
2222

23+
/*
24+
* Function-specific return values for ibm,set-dynamic-indicator and
25+
* ibm,get-dynamic-sensor-state RTAS calls.
26+
* PAPR+ v2.13 7.3.18 and 7.3.19.
27+
*/
28+
#define RTAS_IBM_DYNAMIC_INDICE_NO_INDICATOR -3
29+
2330
/**
2431
* struct rtas_get_indices_params - Parameters (in and out) for
2532
* ibm,get-indices.
@@ -260,6 +267,110 @@ static long papr_indices_create_handle(struct papr_indices_io_block __user *ubuf
260267
return fd;
261268
}
262269

270+
/*
271+
* Create work area with the input parameters. This function is used
272+
* for both ibm,set-dynamic-indicator and ibm,get-dynamic-sensor-state
273+
* RTAS Calls.
274+
*/
275+
static struct rtas_work_area *
276+
papr_dynamic_indice_buf_from_user(struct papr_indices_io_block __user *ubuf,
277+
struct papr_indices_io_block *kbuf)
278+
{
279+
struct rtas_work_area *work_area;
280+
u32 length;
281+
__be32 len_be;
282+
283+
if (copy_from_user(kbuf, ubuf, sizeof(*kbuf)))
284+
return ERR_PTR(-EFAULT);
285+
286+
287+
if (!string_is_terminated(kbuf->dynamic_param.location_code_str,
288+
ARRAY_SIZE(kbuf->dynamic_param.location_code_str)))
289+
return ERR_PTR(-EINVAL);
290+
291+
/*
292+
* The input data in the work area should be as follows:
293+
* - 32-bit integer length of the location code string,
294+
* including NULL.
295+
* - Location code string, NULL terminated, identifying the
296+
* token (sensor or indicator).
297+
* PAPR 2.13 - R1–7.3.18–5 ibm,set-dynamic-indicator
298+
* - R1–7.3.19–5 ibm,get-dynamic-sensor-state
299+
*/
300+
/*
301+
* Length that user space passed should also include NULL
302+
* terminator.
303+
*/
304+
length = strlen(kbuf->dynamic_param.location_code_str) + 1;
305+
if (length > LOC_CODE_SIZE)
306+
return ERR_PTR(-EINVAL);
307+
308+
len_be = cpu_to_be32(length);
309+
310+
work_area = rtas_work_area_alloc(LOC_CODE_SIZE + sizeof(u32));
311+
memcpy(rtas_work_area_raw_buf(work_area), &len_be, sizeof(u32));
312+
memcpy((rtas_work_area_raw_buf(work_area) + sizeof(u32)),
313+
&kbuf->dynamic_param.location_code_str, length);
314+
315+
return work_area;
316+
}
317+
318+
/**
319+
* papr_dynamic_indicator_ioc_set - ibm,set-dynamic-indicator RTAS Call
320+
* PAPR 2.13 7.3.18
321+
*
322+
* @ubuf: Input parameters to RTAS call such as indicator token and
323+
* new state.
324+
*
325+
* Returns success or -errno.
326+
*/
327+
static long papr_dynamic_indicator_ioc_set(struct papr_indices_io_block __user *ubuf)
328+
{
329+
struct papr_indices_io_block kbuf;
330+
struct rtas_work_area *work_area;
331+
s32 fwrc, token, ret;
332+
333+
token = rtas_token("ibm,set-dynamic-indicator");
334+
if (token == RTAS_UNKNOWN_SERVICE)
335+
return -ENOENT;
336+
337+
mutex_lock(&rtas_ibm_set_dynamic_indicator_lock);
338+
work_area = papr_dynamic_indice_buf_from_user(ubuf, &kbuf);
339+
if (IS_ERR(work_area)) {
340+
ret = PTR_ERR(work_area);
341+
goto out;
342+
}
343+
344+
do {
345+
fwrc = rtas_call(token, 3, 1, NULL,
346+
kbuf.dynamic_param.token,
347+
kbuf.dynamic_param.state,
348+
rtas_work_area_phys(work_area));
349+
} while (rtas_busy_delay(fwrc));
350+
351+
rtas_work_area_free(work_area);
352+
353+
switch (fwrc) {
354+
case 0: /* Success */
355+
ret = 0;
356+
break;
357+
case RTAS_IBM_DYNAMIC_INDICE_NO_INDICATOR: /* No such indicator */
358+
ret = -EOPNOTSUPP;
359+
break;
360+
default:
361+
pr_err("unexpected ibm,set-dynamic-indicator result %d\n",
362+
fwrc);
363+
fallthrough;
364+
case RTAS_HARDWARE_ERROR: /* Hardware/platform error */
365+
ret = -EIO;
366+
break;
367+
}
368+
369+
out:
370+
mutex_unlock(&rtas_ibm_set_dynamic_indicator_lock);
371+
return ret;
372+
}
373+
263374
/*
264375
* Top-level ioctl handler for /dev/papr-indices.
265376
*/
@@ -273,6 +384,12 @@ static long papr_indices_dev_ioctl(struct file *filp, unsigned int ioctl,
273384
case PAPR_INDICES_IOC_GET:
274385
ret = papr_indices_create_handle(argp);
275386
break;
387+
case PAPR_DYNAMIC_INDICATOR_IOC_SET:
388+
if (filp->f_mode & FMODE_WRITE)
389+
ret = papr_dynamic_indicator_ioc_set(argp);
390+
else
391+
ret = -EBADF;
392+
break;
276393
default:
277394
ret = -ENOIOCTLCMD;
278395
break;
@@ -296,6 +413,9 @@ static __init int papr_indices_init(void)
296413
if (!rtas_service_present("ibm,get-indices"))
297414
return -ENODEV;
298415

416+
if (!rtas_service_present("ibm,set-dynamic-indicator"))
417+
return -ENODEV;
418+
299419
return misc_register(&papr_indices_dev);
300420
}
301421
machine_device_initcall(pseries, papr_indices_init);

0 commit comments

Comments
 (0)