| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|
| 1 | 2 | #ifndef _POWERPC_RTAS_H |
|---|
| 2 | 3 | #define _POWERPC_RTAS_H |
|---|
| 3 | 4 | #ifdef __KERNEL__ |
|---|
| 4 | 5 | |
|---|
| 5 | 6 | #include <linux/spinlock.h> |
|---|
| 6 | 7 | #include <asm/page.h> |
|---|
| 8 | +#include <asm/rtas-types.h> |
|---|
| 7 | 9 | #include <linux/time.h> |
|---|
| 10 | +#include <linux/cpumask.h> |
|---|
| 8 | 11 | |
|---|
| 9 | 12 | /* |
|---|
| 10 | 13 | * Definitions for talking to the RTAS on CHRP machines. |
|---|
| 11 | 14 | * |
|---|
| 12 | 15 | * Copyright (C) 2001 Peter Bergner |
|---|
| 13 | 16 | * Copyright (C) 2001 PPC 64 Team, IBM Corp |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is free software; you can redistribute it and/or |
|---|
| 16 | | - * modify it under the terms of the GNU General Public License |
|---|
| 17 | | - * as published by the Free Software Foundation; either version |
|---|
| 18 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 19 | 17 | */ |
|---|
| 20 | 18 | |
|---|
| 21 | 19 | #define RTAS_UNKNOWN_SERVICE (-1) |
|---|
| .. | .. |
|---|
| 44 | 42 | * may be safely used for one-shot calls to RTAS. |
|---|
| 45 | 43 | * |
|---|
| 46 | 44 | */ |
|---|
| 47 | | - |
|---|
| 48 | | -typedef __be32 rtas_arg_t; |
|---|
| 49 | | - |
|---|
| 50 | | -struct rtas_args { |
|---|
| 51 | | - __be32 token; |
|---|
| 52 | | - __be32 nargs; |
|---|
| 53 | | - __be32 nret; |
|---|
| 54 | | - rtas_arg_t args[16]; |
|---|
| 55 | | - rtas_arg_t *rets; /* Pointer to return values in args[]. */ |
|---|
| 56 | | -}; |
|---|
| 57 | | - |
|---|
| 58 | | -struct rtas_t { |
|---|
| 59 | | - unsigned long entry; /* physical address pointer */ |
|---|
| 60 | | - unsigned long base; /* physical address pointer */ |
|---|
| 61 | | - unsigned long size; |
|---|
| 62 | | - arch_spinlock_t lock; |
|---|
| 63 | | - struct rtas_args args; |
|---|
| 64 | | - struct device_node *dev; /* virtual address pointer */ |
|---|
| 65 | | -}; |
|---|
| 66 | | - |
|---|
| 67 | | -struct rtas_suspend_me_data { |
|---|
| 68 | | - atomic_t working; /* number of cpus accessing this struct */ |
|---|
| 69 | | - atomic_t done; |
|---|
| 70 | | - int token; /* ibm,suspend-me */ |
|---|
| 71 | | - atomic_t error; |
|---|
| 72 | | - struct completion *complete; /* wait on this until working == 0 */ |
|---|
| 73 | | -}; |
|---|
| 74 | 45 | |
|---|
| 75 | 46 | /* RTAS event classes */ |
|---|
| 76 | 47 | #define RTAS_INTERNAL_ERROR 0x80000000 /* set bit 0 */ |
|---|
| .. | .. |
|---|
| 125 | 96 | #define RTAS_TYPE_INFO 0xE2 |
|---|
| 126 | 97 | #define RTAS_TYPE_DEALLOC 0xE3 |
|---|
| 127 | 98 | #define RTAS_TYPE_DUMP 0xE4 |
|---|
| 99 | +#define RTAS_TYPE_HOTPLUG 0xE5 |
|---|
| 128 | 100 | /* I don't add PowerMGM events right now, this is a different topic */ |
|---|
| 129 | 101 | #define RTAS_TYPE_PMGM_POWER_SW_ON 0x60 |
|---|
| 130 | 102 | #define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61 |
|---|
| .. | .. |
|---|
| 150 | 122 | /* RTAS check-exception vector offset */ |
|---|
| 151 | 123 | #define RTAS_VECTOR_EXTERNAL_INTERRUPT 0x500 |
|---|
| 152 | 124 | |
|---|
| 153 | | -struct rtas_error_log { |
|---|
| 154 | | - /* Byte 0 */ |
|---|
| 155 | | - uint8_t byte0; /* Architectural version */ |
|---|
| 156 | | - |
|---|
| 157 | | - /* Byte 1 */ |
|---|
| 158 | | - uint8_t byte1; |
|---|
| 159 | | - /* XXXXXXXX |
|---|
| 160 | | - * XXX 3: Severity level of error |
|---|
| 161 | | - * XX 2: Degree of recovery |
|---|
| 162 | | - * X 1: Extended log present? |
|---|
| 163 | | - * XX 2: Reserved |
|---|
| 164 | | - */ |
|---|
| 165 | | - |
|---|
| 166 | | - /* Byte 2 */ |
|---|
| 167 | | - uint8_t byte2; |
|---|
| 168 | | - /* XXXXXXXX |
|---|
| 169 | | - * XXXX 4: Initiator of event |
|---|
| 170 | | - * XXXX 4: Target of failed operation |
|---|
| 171 | | - */ |
|---|
| 172 | | - uint8_t byte3; /* General event or error*/ |
|---|
| 173 | | - __be32 extended_log_length; /* length in bytes */ |
|---|
| 174 | | - unsigned char buffer[1]; /* Start of extended log */ |
|---|
| 175 | | - /* Variable length. */ |
|---|
| 176 | | -}; |
|---|
| 177 | | - |
|---|
| 178 | 125 | static inline uint8_t rtas_error_severity(const struct rtas_error_log *elog) |
|---|
| 179 | 126 | { |
|---|
| 180 | 127 | return (elog->byte1 & 0xE0) >> 5; |
|---|
| .. | .. |
|---|
| 185 | 132 | return (elog->byte1 & 0x18) >> 3; |
|---|
| 186 | 133 | } |
|---|
| 187 | 134 | |
|---|
| 135 | +static inline |
|---|
| 136 | +void rtas_set_disposition_recovered(struct rtas_error_log *elog) |
|---|
| 137 | +{ |
|---|
| 138 | + elog->byte1 &= ~0x18; |
|---|
| 139 | + elog->byte1 |= (RTAS_DISP_FULLY_RECOVERED << 3); |
|---|
| 140 | +} |
|---|
| 141 | + |
|---|
| 188 | 142 | static inline uint8_t rtas_error_extended(const struct rtas_error_log *elog) |
|---|
| 189 | 143 | { |
|---|
| 190 | 144 | return (elog->byte1 & 0x04) >> 2; |
|---|
| 145 | +} |
|---|
| 146 | + |
|---|
| 147 | +static inline uint8_t rtas_error_initiator(const struct rtas_error_log *elog) |
|---|
| 148 | +{ |
|---|
| 149 | + return (elog->byte2 & 0xf0) >> 4; |
|---|
| 191 | 150 | } |
|---|
| 192 | 151 | |
|---|
| 193 | 152 | #define rtas_error_type(x) ((x)->byte3) |
|---|
| .. | .. |
|---|
| 201 | 160 | #define RTAS_V6EXT_LOG_FORMAT_EVENT_LOG 14 |
|---|
| 202 | 161 | |
|---|
| 203 | 162 | #define RTAS_V6EXT_COMPANY_ID_IBM (('I' << 24) | ('B' << 16) | ('M' << 8)) |
|---|
| 204 | | - |
|---|
| 205 | | -/* RTAS general extended event log, Version 6. The extended log starts |
|---|
| 206 | | - * from "buffer" field of struct rtas_error_log defined above. |
|---|
| 207 | | - */ |
|---|
| 208 | | -struct rtas_ext_event_log_v6 { |
|---|
| 209 | | - /* Byte 0 */ |
|---|
| 210 | | - uint8_t byte0; |
|---|
| 211 | | - /* XXXXXXXX |
|---|
| 212 | | - * X 1: Log valid |
|---|
| 213 | | - * X 1: Unrecoverable error |
|---|
| 214 | | - * X 1: Recoverable (correctable or successfully retried) |
|---|
| 215 | | - * X 1: Bypassed unrecoverable error (degraded operation) |
|---|
| 216 | | - * X 1: Predictive error |
|---|
| 217 | | - * X 1: "New" log (always 1 for data returned from RTAS) |
|---|
| 218 | | - * X 1: Big Endian |
|---|
| 219 | | - * X 1: Reserved |
|---|
| 220 | | - */ |
|---|
| 221 | | - |
|---|
| 222 | | - /* Byte 1 */ |
|---|
| 223 | | - uint8_t byte1; /* reserved */ |
|---|
| 224 | | - |
|---|
| 225 | | - /* Byte 2 */ |
|---|
| 226 | | - uint8_t byte2; |
|---|
| 227 | | - /* XXXXXXXX |
|---|
| 228 | | - * X 1: Set to 1 (indicating log is in PowerPC format) |
|---|
| 229 | | - * XXX 3: Reserved |
|---|
| 230 | | - * XXXX 4: Log format used for bytes 12-2047 |
|---|
| 231 | | - */ |
|---|
| 232 | | - |
|---|
| 233 | | - /* Byte 3 */ |
|---|
| 234 | | - uint8_t byte3; /* reserved */ |
|---|
| 235 | | - /* Byte 4-11 */ |
|---|
| 236 | | - uint8_t reserved[8]; /* reserved */ |
|---|
| 237 | | - /* Byte 12-15 */ |
|---|
| 238 | | - __be32 company_id; /* Company ID of the company */ |
|---|
| 239 | | - /* that defines the format for */ |
|---|
| 240 | | - /* the vendor specific log type */ |
|---|
| 241 | | - /* Byte 16-end of log */ |
|---|
| 242 | | - uint8_t vendor_log[1]; /* Start of vendor specific log */ |
|---|
| 243 | | - /* Variable length. */ |
|---|
| 244 | | -}; |
|---|
| 245 | 163 | |
|---|
| 246 | 164 | static |
|---|
| 247 | 165 | inline uint8_t rtas_ext_event_log_format(struct rtas_ext_event_log_v6 *ext_log) |
|---|
| .. | .. |
|---|
| 275 | 193 | #define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H') |
|---|
| 276 | 194 | #define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D') |
|---|
| 277 | 195 | #define PSERIES_ELOG_SECT_ID_HOTPLUG (('H' << 8) | 'P') |
|---|
| 278 | | - |
|---|
| 279 | | -/* Vendor specific Platform Event Log Format, Version 6, section header */ |
|---|
| 280 | | -struct pseries_errorlog { |
|---|
| 281 | | - __be16 id; /* 0x00 2-byte ASCII section ID */ |
|---|
| 282 | | - __be16 length; /* 0x02 Section length in bytes */ |
|---|
| 283 | | - uint8_t version; /* 0x04 Section version */ |
|---|
| 284 | | - uint8_t subtype; /* 0x05 Section subtype */ |
|---|
| 285 | | - __be16 creator_component; /* 0x06 Creator component ID */ |
|---|
| 286 | | - uint8_t data[]; /* 0x08 Start of section data */ |
|---|
| 287 | | -}; |
|---|
| 196 | +#define PSERIES_ELOG_SECT_ID_MCE (('M' << 8) | 'C') |
|---|
| 288 | 197 | |
|---|
| 289 | 198 | static |
|---|
| 290 | 199 | inline uint16_t pseries_errorlog_id(struct pseries_errorlog *sect) |
|---|
| .. | .. |
|---|
| 298 | 207 | return be16_to_cpu(sect->length); |
|---|
| 299 | 208 | } |
|---|
| 300 | 209 | |
|---|
| 301 | | -/* RTAS pseries hotplug errorlog section */ |
|---|
| 302 | | -struct pseries_hp_errorlog { |
|---|
| 303 | | - u8 resource; |
|---|
| 304 | | - u8 action; |
|---|
| 305 | | - u8 id_type; |
|---|
| 306 | | - u8 reserved; |
|---|
| 307 | | - union { |
|---|
| 308 | | - __be32 drc_index; |
|---|
| 309 | | - __be32 drc_count; |
|---|
| 310 | | - struct { __be32 count, index; } ic; |
|---|
| 311 | | - char drc_name[1]; |
|---|
| 312 | | - } _drc_u; |
|---|
| 313 | | -}; |
|---|
| 314 | | - |
|---|
| 315 | 210 | #define PSERIES_HP_ELOG_RESOURCE_CPU 1 |
|---|
| 316 | 211 | #define PSERIES_HP_ELOG_RESOURCE_MEM 2 |
|---|
| 317 | 212 | #define PSERIES_HP_ELOG_RESOURCE_SLOT 3 |
|---|
| 318 | 213 | #define PSERIES_HP_ELOG_RESOURCE_PHB 4 |
|---|
| 214 | +#define PSERIES_HP_ELOG_RESOURCE_PMEM 6 |
|---|
| 319 | 215 | |
|---|
| 320 | 216 | #define PSERIES_HP_ELOG_ACTION_ADD 1 |
|---|
| 321 | 217 | #define PSERIES_HP_ELOG_ACTION_REMOVE 2 |
|---|
| 322 | | -#define PSERIES_HP_ELOG_ACTION_READD 3 |
|---|
| 323 | 218 | |
|---|
| 324 | 219 | #define PSERIES_HP_ELOG_ID_DRC_NAME 1 |
|---|
| 325 | 220 | #define PSERIES_HP_ELOG_ID_DRC_INDEX 2 |
|---|
| .. | .. |
|---|
| 340 | 235 | extern int rtas_token(const char *service); |
|---|
| 341 | 236 | extern int rtas_service_present(const char *service); |
|---|
| 342 | 237 | extern int rtas_call(int token, int, int, int *, ...); |
|---|
| 238 | +int rtas_call_reentrant(int token, int nargs, int nret, int *outputs, ...); |
|---|
| 343 | 239 | void rtas_call_unlocked(struct rtas_args *args, int token, int nargs, |
|---|
| 344 | 240 | int nret, ...); |
|---|
| 345 | 241 | extern void __noreturn rtas_restart(char *cmd); |
|---|
| .. | .. |
|---|
| 356 | 252 | extern void rtas_progress(char *s, unsigned short hex); |
|---|
| 357 | 253 | extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); |
|---|
| 358 | 254 | extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); |
|---|
| 359 | | -extern int rtas_online_cpus_mask(cpumask_var_t cpus); |
|---|
| 360 | | -extern int rtas_offline_cpus_mask(cpumask_var_t cpus); |
|---|
| 361 | 255 | extern int rtas_ibm_suspend_me(u64 handle); |
|---|
| 362 | 256 | |
|---|
| 363 | 257 | struct rtc_time; |
|---|
| .. | .. |
|---|
| 471 | 365 | |
|---|
| 472 | 366 | extern int call_rtas(const char *, int, int, unsigned long *, ...); |
|---|
| 473 | 367 | |
|---|
| 368 | +#ifdef CONFIG_HV_PERF_CTRS |
|---|
| 369 | +void read_24x7_sys_info(void); |
|---|
| 370 | +#else |
|---|
| 371 | +static inline void read_24x7_sys_info(void) { } |
|---|
| 372 | +#endif |
|---|
| 373 | + |
|---|
| 474 | 374 | #endif /* __KERNEL__ */ |
|---|
| 475 | 375 | #endif /* _POWERPC_RTAS_H */ |
|---|