Skip to content

Commit 08273c9

Browse files
nathanlynchmpe
authored andcommitted
powerpc/rtas: arch-wide function token lookup conversions
With the tokens for all implemented RTAS functions now available via rtas_function_token(), which is optimal and safe for arbitrary contexts, there is no need to use rtas_token() or cache its result. Most conversions are trivial, but a few are worth describing in more detail: * Error injection token comparisons for lockdown purposes are consolidated into a simple predicate: token_is_restricted_errinjct(). * A couple of special cases in block_rtas_call() do not use rtas_token() but perform string comparisons against names in the function table. These are converted to compare against token values instead, which is logically equivalent but less expensive. * The lookup for the ibm,os-term token can be deferred until needed, instead of caching it at boot to avoid device tree traversal during panic. * Since rtas_function_token() accesses a read-only data structure without taking any locks, xmon's lookup of set-indicator can be performed as needed instead of cached at startup. Signed-off-by: Nathan Lynch <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 716bfc9 commit 08273c9

File tree

28 files changed

+123
-137
lines changed

28 files changed

+123
-137
lines changed

arch/powerpc/kernel/rtas-proc.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,9 @@ static ssize_t ppc_rtas_poweron_write(struct file *file,
287287

288288
rtc_time64_to_tm(nowtime, &tm);
289289

290-
error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL,
291-
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
292-
tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
290+
error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_FOR_POWER_ON), 7, 1, NULL,
291+
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
292+
tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
293293
if (error)
294294
printk(KERN_WARNING "error: setting poweron time returned: %s\n",
295295
ppc_rtas_process_error(error));
@@ -350,9 +350,9 @@ static ssize_t ppc_rtas_clock_write(struct file *file,
350350
return error;
351351

352352
rtc_time64_to_tm(nowtime, &tm);
353-
error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
354-
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
355-
tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
353+
error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_OF_DAY), 7, 1, NULL,
354+
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
355+
tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
356356
if (error)
357357
printk(KERN_WARNING "error: setting the clock returned: %s\n",
358358
ppc_rtas_process_error(error));
@@ -362,7 +362,7 @@ static ssize_t ppc_rtas_clock_write(struct file *file,
362362
static int ppc_rtas_clock_show(struct seq_file *m, void *v)
363363
{
364364
int ret[8];
365-
int error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
365+
int error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret);
366366

367367
if (error) {
368368
printk(KERN_WARNING "error: reading the clock returned: %s\n",
@@ -385,7 +385,7 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
385385
{
386386
int i,j;
387387
int state, error;
388-
int get_sensor_state = rtas_token("get-sensor-state");
388+
int get_sensor_state = rtas_function_token(RTAS_FN_GET_SENSOR_STATE);
389389

390390
seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n");
391391
seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n");
@@ -708,8 +708,8 @@ static ssize_t ppc_rtas_tone_freq_write(struct file *file,
708708
return error;
709709

710710
rtas_tone_frequency = freq; /* save it for later */
711-
error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
712-
TONE_FREQUENCY, 0, freq);
711+
error = rtas_call(rtas_function_token(RTAS_FN_SET_INDICATOR), 3, 1, NULL,
712+
TONE_FREQUENCY, 0, freq);
713713
if (error)
714714
printk(KERN_WARNING "error: setting tone frequency returned: %s\n",
715715
ppc_rtas_process_error(error));
@@ -736,8 +736,8 @@ static ssize_t ppc_rtas_tone_volume_write(struct file *file,
736736
volume = 100;
737737

738738
rtas_tone_volume = volume; /* save it for later */
739-
error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
740-
TONE_VOLUME, 0, volume);
739+
error = rtas_call(rtas_function_token(RTAS_FN_SET_INDICATOR), 3, 1, NULL,
740+
TONE_VOLUME, 0, volume);
741741
if (error)
742742
printk(KERN_WARNING "error: setting tone volume returned: %s\n",
743743
ppc_rtas_process_error(error));

arch/powerpc/kernel/rtas-rtc.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ time64_t __init rtas_get_boot_time(void)
2121

2222
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
2323
do {
24-
error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
24+
error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret);
2525

2626
wait_time = rtas_busy_delay_time(error);
2727
if (wait_time) {
@@ -53,7 +53,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
5353

5454
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
5555
do {
56-
error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
56+
error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret);
5757

5858
wait_time = rtas_busy_delay_time(error);
5959
if (wait_time) {
@@ -90,7 +90,7 @@ int rtas_set_rtc_time(struct rtc_time *tm)
9090

9191
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
9292
do {
93-
error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
93+
error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_OF_DAY), 7, 1, NULL,
9494
tm->tm_year + 1900, tm->tm_mon + 1,
9595
tm->tm_mday, tm->tm_hour, tm->tm_min,
9696
tm->tm_sec, 0);

arch/powerpc/kernel/rtas.c

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -782,8 +782,8 @@ void rtas_progress(char *s, unsigned short hex)
782782
"ibm,display-truncation-length", NULL);
783783
of_node_put(root);
784784
}
785-
display_character = rtas_token("display-character");
786-
set_indicator = rtas_token("set-indicator");
785+
display_character = rtas_function_token(RTAS_FN_DISPLAY_CHARACTER);
786+
set_indicator = rtas_function_token(RTAS_FN_SET_INDICATOR);
787787
}
788788

789789
if (display_character == RTAS_UNKNOWN_SERVICE) {
@@ -937,7 +937,6 @@ static void __init init_error_log_max(void)
937937

938938

939939
static char rtas_err_buf[RTAS_ERROR_LOG_MAX];
940-
static int rtas_last_error_token;
941940

942941
/** Return a copy of the detailed error text associated with the
943942
* most recent failed call to rtas. Because the error text
@@ -947,16 +946,17 @@ static int rtas_last_error_token;
947946
*/
948947
static char *__fetch_rtas_last_error(char *altbuf)
949948
{
949+
const s32 token = rtas_function_token(RTAS_FN_RTAS_LAST_ERROR);
950950
struct rtas_args err_args, save_args;
951951
u32 bufsz;
952952
char *buf = NULL;
953953

954-
if (rtas_last_error_token == -1)
954+
if (token == -1)
955955
return NULL;
956956

957957
bufsz = rtas_get_error_log_max();
958958

959-
err_args.token = cpu_to_be32(rtas_last_error_token);
959+
err_args.token = cpu_to_be32(token);
960960
err_args.nargs = cpu_to_be32(2);
961961
err_args.nret = cpu_to_be32(1);
962962
err_args.args[0] = cpu_to_be32(__pa(rtas_err_buf));
@@ -1025,8 +1025,11 @@ void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, int nret,
10251025
va_end(list);
10261026
}
10271027

1028-
static int ibm_open_errinjct_token;
1029-
static int ibm_errinjct_token;
1028+
static bool token_is_restricted_errinjct(s32 token)
1029+
{
1030+
return token == rtas_function_token(RTAS_FN_IBM_OPEN_ERRINJCT) ||
1031+
token == rtas_function_token(RTAS_FN_IBM_ERRINJCT);
1032+
}
10301033

10311034
/**
10321035
* rtas_call() - Invoke an RTAS firmware function.
@@ -1098,7 +1101,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
10981101
if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
10991102
return -1;
11001103

1101-
if (token == ibm_open_errinjct_token || token == ibm_errinjct_token) {
1104+
if (token_is_restricted_errinjct(token)) {
11021105
/*
11031106
* It would be nicer to not discard the error value
11041107
* from security_locked_down(), but callers expect an
@@ -1330,7 +1333,7 @@ static int rtas_error_rc(int rtas_rc)
13301333

13311334
int rtas_get_power_level(int powerdomain, int *level)
13321335
{
1333-
int token = rtas_token("get-power-level");
1336+
int token = rtas_function_token(RTAS_FN_GET_POWER_LEVEL);
13341337
int rc;
13351338

13361339
if (token == RTAS_UNKNOWN_SERVICE)
@@ -1347,7 +1350,7 @@ EXPORT_SYMBOL_GPL(rtas_get_power_level);
13471350

13481351
int rtas_set_power_level(int powerdomain, int level, int *setlevel)
13491352
{
1350-
int token = rtas_token("set-power-level");
1353+
int token = rtas_function_token(RTAS_FN_SET_POWER_LEVEL);
13511354
int rc;
13521355

13531356
if (token == RTAS_UNKNOWN_SERVICE)
@@ -1365,7 +1368,7 @@ EXPORT_SYMBOL_GPL(rtas_set_power_level);
13651368

13661369
int rtas_get_sensor(int sensor, int index, int *state)
13671370
{
1368-
int token = rtas_token("get-sensor-state");
1371+
int token = rtas_function_token(RTAS_FN_GET_SENSOR_STATE);
13691372
int rc;
13701373

13711374
if (token == RTAS_UNKNOWN_SERVICE)
@@ -1383,7 +1386,7 @@ EXPORT_SYMBOL_GPL(rtas_get_sensor);
13831386

13841387
int rtas_get_sensor_fast(int sensor, int index, int *state)
13851388
{
1386-
int token = rtas_token("get-sensor-state");
1389+
int token = rtas_function_token(RTAS_FN_GET_SENSOR_STATE);
13871390
int rc;
13881391

13891392
if (token == RTAS_UNKNOWN_SERVICE)
@@ -1425,7 +1428,7 @@ bool rtas_indicator_present(int token, int *maxindex)
14251428

14261429
int rtas_set_indicator(int indicator, int index, int new_value)
14271430
{
1428-
int token = rtas_token("set-indicator");
1431+
int token = rtas_function_token(RTAS_FN_SET_INDICATOR);
14291432
int rc;
14301433

14311434
if (token == RTAS_UNKNOWN_SERVICE)
@@ -1446,8 +1449,8 @@ EXPORT_SYMBOL_GPL(rtas_set_indicator);
14461449
*/
14471450
int rtas_set_indicator_fast(int indicator, int index, int new_value)
14481451
{
1452+
int token = rtas_function_token(RTAS_FN_SET_INDICATOR);
14491453
int rc;
1450-
int token = rtas_token("set-indicator");
14511454

14521455
if (token == RTAS_UNKNOWN_SERVICE)
14531456
return -ENOENT;
@@ -1489,10 +1492,11 @@ int rtas_set_indicator_fast(int indicator, int index, int new_value)
14891492
*/
14901493
int rtas_ibm_suspend_me(int *fw_status)
14911494
{
1495+
int token = rtas_function_token(RTAS_FN_IBM_SUSPEND_ME);
14921496
int fwrc;
14931497
int ret;
14941498

1495-
fwrc = rtas_call(rtas_token("ibm,suspend-me"), 0, 1, NULL);
1499+
fwrc = rtas_call(token, 0, 1, NULL);
14961500

14971501
switch (fwrc) {
14981502
case 0:
@@ -1525,7 +1529,7 @@ void __noreturn rtas_restart(char *cmd)
15251529
if (rtas_flash_term_hook)
15261530
rtas_flash_term_hook(SYS_RESTART);
15271531
pr_emerg("system-reboot returned %d\n",
1528-
rtas_call(rtas_token("system-reboot"), 0, 1, NULL));
1532+
rtas_call(rtas_function_token(RTAS_FN_SYSTEM_REBOOT), 0, 1, NULL));
15291533
for (;;);
15301534
}
15311535

@@ -1535,7 +1539,7 @@ void rtas_power_off(void)
15351539
rtas_flash_term_hook(SYS_POWER_OFF);
15361540
/* allow power on only with power button press */
15371541
pr_emerg("power-off returned %d\n",
1538-
rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
1542+
rtas_call(rtas_function_token(RTAS_FN_POWER_OFF), 2, 1, NULL, -1, -1));
15391543
for (;;);
15401544
}
15411545

@@ -1545,16 +1549,17 @@ void __noreturn rtas_halt(void)
15451549
rtas_flash_term_hook(SYS_HALT);
15461550
/* allow power on only with power button press */
15471551
pr_emerg("power-off returned %d\n",
1548-
rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1));
1552+
rtas_call(rtas_function_token(RTAS_FN_POWER_OFF), 2, 1, NULL, -1, -1));
15491553
for (;;);
15501554
}
15511555

15521556
/* Must be in the RMO region, so we place it here */
15531557
static char rtas_os_term_buf[2048];
1554-
static s32 ibm_os_term_token = RTAS_UNKNOWN_SERVICE;
1558+
static bool ibm_extended_os_term;
15551559

15561560
void rtas_os_term(char *str)
15571561
{
1562+
s32 token = rtas_function_token(RTAS_FN_IBM_OS_TERM);
15581563
int status;
15591564

15601565
/*
@@ -1563,7 +1568,8 @@ void rtas_os_term(char *str)
15631568
* this property may terminate the partition which we want to avoid
15641569
* since it interferes with panic_timeout.
15651570
*/
1566-
if (ibm_os_term_token == RTAS_UNKNOWN_SERVICE)
1571+
1572+
if (token == RTAS_UNKNOWN_SERVICE || !ibm_extended_os_term)
15671573
return;
15681574

15691575
snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);
@@ -1574,8 +1580,7 @@ void rtas_os_term(char *str)
15741580
* schedules.
15751581
*/
15761582
do {
1577-
status = rtas_call(ibm_os_term_token, 1, 1, NULL,
1578-
__pa(rtas_os_term_buf));
1583+
status = rtas_call(token, 1, 1, NULL, __pa(rtas_os_term_buf));
15791584
} while (rtas_busy_delay_time(status));
15801585

15811586
if (status != 0)
@@ -1595,10 +1600,9 @@ void rtas_os_term(char *str)
15951600
*/
15961601
void rtas_activate_firmware(void)
15971602
{
1598-
int token;
1603+
int token = rtas_function_token(RTAS_FN_IBM_ACTIVATE_FIRMWARE);
15991604
int fwrc;
16001605

1601-
token = rtas_token("ibm,activate-firmware");
16021606
if (token == RTAS_UNKNOWN_SERVICE) {
16031607
pr_notice("ibm,activate-firmware method unavailable\n");
16041608
return;
@@ -1684,6 +1688,8 @@ static bool block_rtas_call(int token, int nargs,
16841688
{
16851689
const struct rtas_function *func;
16861690
const struct rtas_filter *f;
1691+
const bool is_platform_dump = token == rtas_function_token(RTAS_FN_IBM_PLATFORM_DUMP);
1692+
const bool is_config_conn = token == rtas_function_token(RTAS_FN_IBM_CONFIGURE_CONNECTOR);
16871693
u32 base, size, end;
16881694

16891695
/*
@@ -1720,8 +1726,7 @@ static bool block_rtas_call(int token, int nargs,
17201726
* Special case for ibm,platform-dump - NULL buffer
17211727
* address is used to indicate end of dump processing
17221728
*/
1723-
if (!strcmp(func->name, "ibm,platform-dump") &&
1724-
base == 0)
1729+
if (is_platform_dump && base == 0)
17251730
return false;
17261731

17271732
if (!in_rmo_buf(base, end))
@@ -1742,8 +1747,7 @@ static bool block_rtas_call(int token, int nargs,
17421747
* Special case for ibm,configure-connector where the
17431748
* address can be 0
17441749
*/
1745-
if (!strcmp(func->name, "ibm,configure-connector") &&
1746-
base == 0)
1750+
if (is_config_conn && base == 0)
17471751
return false;
17481752

17491753
if (!in_rmo_buf(base, end))
@@ -1798,7 +1802,7 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
17981802
if (block_rtas_call(token, nargs, &args))
17991803
return -EINVAL;
18001804

1801-
if (token == ibm_open_errinjct_token || token == ibm_errinjct_token) {
1805+
if (token_is_restricted_errinjct(token)) {
18021806
int err;
18031807

18041808
err = security_locked_down(LOCKDOWN_RTAS_ERROR_INJECTION);
@@ -1807,7 +1811,7 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
18071811
}
18081812

18091813
/* Need to handle ibm,suspend_me call specially */
1810-
if (token == rtas_token("ibm,suspend-me")) {
1814+
if (token == rtas_function_token(RTAS_FN_IBM_SUSPEND_ME)) {
18111815

18121816
/*
18131817
* rtas_ibm_suspend_me assumes the streamid handle is in cpu
@@ -1942,11 +1946,10 @@ void __init rtas_initialize(void)
19421946
rtas_function_table_init();
19431947

19441948
/*
1945-
* Discover these now to avoid device tree lookups in the
1949+
* Discover this now to avoid a device tree lookup in the
19461950
* panic path.
19471951
*/
1948-
if (of_property_read_bool(rtas.dev, "ibm,extended-os-term"))
1949-
ibm_os_term_token = rtas_token("ibm,os-term");
1952+
ibm_extended_os_term = of_property_read_bool(rtas.dev, "ibm,extended-os-term");
19501953

19511954
/* If RTAS was found, allocate the RMO buffer for it and look for
19521955
* the stop-self token if any
@@ -1961,12 +1964,6 @@ void __init rtas_initialize(void)
19611964
panic("ERROR: RTAS: Failed to allocate %lx bytes below %pa\n",
19621965
PAGE_SIZE, &rtas_region);
19631966

1964-
#ifdef CONFIG_RTAS_ERROR_LOGGING
1965-
rtas_last_error_token = rtas_token("rtas-last-error");
1966-
#endif
1967-
ibm_open_errinjct_token = rtas_token("ibm,open-errinjct");
1968-
ibm_errinjct_token = rtas_token("ibm,errinjct");
1969-
19701967
rtas_work_area_reserve_arena(rtas_region);
19711968
}
19721969

@@ -2022,13 +2019,13 @@ void rtas_give_timebase(void)
20222019

20232020
raw_spin_lock_irqsave(&timebase_lock, flags);
20242021
hard_irq_disable();
2025-
rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
2022+
rtas_call(rtas_function_token(RTAS_FN_FREEZE_TIME_BASE), 0, 1, NULL);
20262023
timebase = get_tb();
20272024
raw_spin_unlock(&timebase_lock);
20282025

20292026
while (timebase)
20302027
barrier();
2031-
rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
2028+
rtas_call(rtas_function_token(RTAS_FN_THAW_TIME_BASE), 0, 1, NULL);
20322029
local_irq_restore(flags);
20332030
}
20342031

0 commit comments

Comments
 (0)