arm_sdei.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2017 Arm Ltd.
  3. #define pr_fmt(fmt) "sdei: " fmt
  4. #include <acpi/ghes.h>
  5. #include <linux/acpi.h>
  6. #include <linux/arm_sdei.h>
  7. #include <linux/arm-smccc.h>
  8. #include <linux/atomic.h>
  9. #include <linux/bitops.h>
  10. #include <linux/compiler.h>
  11. #include <linux/cpuhotplug.h>
  12. #include <linux/cpu.h>
  13. #include <linux/cpu_pm.h>
  14. #include <linux/errno.h>
  15. #include <linux/hardirq.h>
  16. #include <linux/kernel.h>
  17. #include <linux/kprobes.h>
  18. #include <linux/kvm_host.h>
  19. #include <linux/list.h>
  20. #include <linux/mutex.h>
  21. #include <linux/notifier.h>
  22. #include <linux/of.h>
  23. #include <linux/of_platform.h>
  24. #include <linux/percpu.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/pm.h>
  27. #include <linux/ptrace.h>
  28. #include <linux/preempt.h>
  29. #include <linux/reboot.h>
  30. #include <linux/slab.h>
  31. #include <linux/smp.h>
  32. #include <linux/spinlock.h>
  33. /*
  34. * The call to use to reach the firmware.
  35. */
  36. static asmlinkage void (*sdei_firmware_call)(unsigned long function_id,
  37. unsigned long arg0, unsigned long arg1,
  38. unsigned long arg2, unsigned long arg3,
  39. unsigned long arg4, struct arm_smccc_res *res);
  40. /* entry point from firmware to arch asm code */
  41. static unsigned long sdei_entry_point;
  42. static int sdei_hp_state;
  43. struct sdei_event {
  44. /* These three are protected by the sdei_list_lock */
  45. struct list_head list;
  46. bool reregister;
  47. bool reenable;
  48. u32 event_num;
  49. u8 type;
  50. u8 priority;
  51. /* This pointer is handed to firmware as the event argument. */
  52. union {
  53. /* Shared events */
  54. struct sdei_registered_event *registered;
  55. /* CPU private events */
  56. struct sdei_registered_event __percpu *private_registered;
  57. };
  58. };
  59. /* Take the mutex for any API call or modification. Take the mutex first. */
  60. static DEFINE_MUTEX(sdei_events_lock);
  61. /* and then hold this when modifying the list */
  62. static DEFINE_SPINLOCK(sdei_list_lock);
  63. static LIST_HEAD(sdei_list);
  64. /* Private events are registered/enabled via IPI passing one of these */
  65. struct sdei_crosscall_args {
  66. struct sdei_event *event;
  67. atomic_t errors;
  68. int first_error;
  69. };
  70. #define CROSSCALL_INIT(arg, event) \
  71. do { \
  72. arg.event = event; \
  73. arg.first_error = 0; \
  74. atomic_set(&arg.errors, 0); \
  75. } while (0)
  76. static inline int sdei_do_local_call(smp_call_func_t fn,
  77. struct sdei_event *event)
  78. {
  79. struct sdei_crosscall_args arg;
  80. CROSSCALL_INIT(arg, event);
  81. fn(&arg);
  82. return arg.first_error;
  83. }
  84. static inline int sdei_do_cross_call(smp_call_func_t fn,
  85. struct sdei_event *event)
  86. {
  87. struct sdei_crosscall_args arg;
  88. CROSSCALL_INIT(arg, event);
  89. on_each_cpu(fn, &arg, true);
  90. return arg.first_error;
  91. }
  92. static inline void
  93. sdei_cross_call_return(struct sdei_crosscall_args *arg, int err)
  94. {
  95. if (err && (atomic_inc_return(&arg->errors) == 1))
  96. arg->first_error = err;
  97. }
  98. static int sdei_to_linux_errno(unsigned long sdei_err)
  99. {
  100. switch (sdei_err) {
  101. case SDEI_NOT_SUPPORTED:
  102. return -EOPNOTSUPP;
  103. case SDEI_INVALID_PARAMETERS:
  104. return -EINVAL;
  105. case SDEI_DENIED:
  106. return -EPERM;
  107. case SDEI_PENDING:
  108. return -EINPROGRESS;
  109. case SDEI_OUT_OF_RESOURCE:
  110. return -ENOMEM;
  111. }
  112. return 0;
  113. }
  114. static int invoke_sdei_fn(unsigned long function_id, unsigned long arg0,
  115. unsigned long arg1, unsigned long arg2,
  116. unsigned long arg3, unsigned long arg4,
  117. u64 *result)
  118. {
  119. int err;
  120. struct arm_smccc_res res;
  121. if (sdei_firmware_call) {
  122. sdei_firmware_call(function_id, arg0, arg1, arg2, arg3, arg4,
  123. &res);
  124. err = sdei_to_linux_errno(res.a0);
  125. } else {
  126. /*
  127. * !sdei_firmware_call means we failed to probe or called
  128. * sdei_mark_interface_broken(). -EIO is not an error returned
  129. * by sdei_to_linux_errno() and is used to suppress messages
  130. * from this driver.
  131. */
  132. err = -EIO;
  133. res.a0 = SDEI_NOT_SUPPORTED;
  134. }
  135. if (result)
  136. *result = res.a0;
  137. return err;
  138. }
  139. NOKPROBE_SYMBOL(invoke_sdei_fn);
  140. static struct sdei_event *sdei_event_find(u32 event_num)
  141. {
  142. struct sdei_event *e, *found = NULL;
  143. lockdep_assert_held(&sdei_events_lock);
  144. spin_lock(&sdei_list_lock);
  145. list_for_each_entry(e, &sdei_list, list) {
  146. if (e->event_num == event_num) {
  147. found = e;
  148. break;
  149. }
  150. }
  151. spin_unlock(&sdei_list_lock);
  152. return found;
  153. }
  154. int sdei_api_event_context(u32 query, u64 *result)
  155. {
  156. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_CONTEXT, query, 0, 0, 0, 0,
  157. result);
  158. }
  159. NOKPROBE_SYMBOL(sdei_api_event_context);
  160. static int sdei_api_event_get_info(u32 event, u32 info, u64 *result)
  161. {
  162. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_GET_INFO, event, info, 0,
  163. 0, 0, result);
  164. }
  165. static struct sdei_event *sdei_event_create(u32 event_num,
  166. sdei_event_callback *cb,
  167. void *cb_arg)
  168. {
  169. int err;
  170. u64 result;
  171. struct sdei_event *event;
  172. struct sdei_registered_event *reg;
  173. lockdep_assert_held(&sdei_events_lock);
  174. event = kzalloc(sizeof(*event), GFP_KERNEL);
  175. if (!event) {
  176. err = -ENOMEM;
  177. goto fail;
  178. }
  179. INIT_LIST_HEAD(&event->list);
  180. event->event_num = event_num;
  181. err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_PRIORITY,
  182. &result);
  183. if (err)
  184. goto fail;
  185. event->priority = result;
  186. err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_TYPE,
  187. &result);
  188. if (err)
  189. goto fail;
  190. event->type = result;
  191. if (event->type == SDEI_EVENT_TYPE_SHARED) {
  192. reg = kzalloc(sizeof(*reg), GFP_KERNEL);
  193. if (!reg) {
  194. err = -ENOMEM;
  195. goto fail;
  196. }
  197. reg->event_num = event->event_num;
  198. reg->priority = event->priority;
  199. reg->callback = cb;
  200. reg->callback_arg = cb_arg;
  201. event->registered = reg;
  202. } else {
  203. int cpu;
  204. struct sdei_registered_event __percpu *regs;
  205. regs = alloc_percpu(struct sdei_registered_event);
  206. if (!regs) {
  207. err = -ENOMEM;
  208. goto fail;
  209. }
  210. for_each_possible_cpu(cpu) {
  211. reg = per_cpu_ptr(regs, cpu);
  212. reg->event_num = event->event_num;
  213. reg->priority = event->priority;
  214. reg->callback = cb;
  215. reg->callback_arg = cb_arg;
  216. }
  217. event->private_registered = regs;
  218. }
  219. spin_lock(&sdei_list_lock);
  220. list_add(&event->list, &sdei_list);
  221. spin_unlock(&sdei_list_lock);
  222. return event;
  223. fail:
  224. kfree(event);
  225. return ERR_PTR(err);
  226. }
  227. static void sdei_event_destroy_llocked(struct sdei_event *event)
  228. {
  229. lockdep_assert_held(&sdei_events_lock);
  230. lockdep_assert_held(&sdei_list_lock);
  231. list_del(&event->list);
  232. if (event->type == SDEI_EVENT_TYPE_SHARED)
  233. kfree(event->registered);
  234. else
  235. free_percpu(event->private_registered);
  236. kfree(event);
  237. }
  238. static void sdei_event_destroy(struct sdei_event *event)
  239. {
  240. spin_lock(&sdei_list_lock);
  241. sdei_event_destroy_llocked(event);
  242. spin_unlock(&sdei_list_lock);
  243. }
  244. static int sdei_api_get_version(u64 *version)
  245. {
  246. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_VERSION, 0, 0, 0, 0, 0, version);
  247. }
  248. int sdei_mask_local_cpu(void)
  249. {
  250. int err;
  251. err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PE_MASK, 0, 0, 0, 0, 0, NULL);
  252. if (err && err != -EIO) {
  253. pr_warn_once("failed to mask CPU[%u]: %d\n",
  254. smp_processor_id(), err);
  255. return err;
  256. }
  257. return 0;
  258. }
  259. static void _ipi_mask_cpu(void *ignored)
  260. {
  261. WARN_ON_ONCE(preemptible());
  262. sdei_mask_local_cpu();
  263. }
  264. int sdei_unmask_local_cpu(void)
  265. {
  266. int err;
  267. err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PE_UNMASK, 0, 0, 0, 0, 0, NULL);
  268. if (err && err != -EIO) {
  269. pr_warn_once("failed to unmask CPU[%u]: %d\n",
  270. smp_processor_id(), err);
  271. return err;
  272. }
  273. return 0;
  274. }
  275. static void _ipi_unmask_cpu(void *ignored)
  276. {
  277. WARN_ON_ONCE(preemptible());
  278. sdei_unmask_local_cpu();
  279. }
  280. static void _ipi_private_reset(void *ignored)
  281. {
  282. int err;
  283. WARN_ON_ONCE(preemptible());
  284. err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PRIVATE_RESET, 0, 0, 0, 0, 0,
  285. NULL);
  286. if (err && err != -EIO)
  287. pr_warn_once("failed to reset CPU[%u]: %d\n",
  288. smp_processor_id(), err);
  289. }
  290. static int sdei_api_shared_reset(void)
  291. {
  292. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_SHARED_RESET, 0, 0, 0, 0, 0,
  293. NULL);
  294. }
  295. static void sdei_mark_interface_broken(void)
  296. {
  297. pr_err("disabling SDEI firmware interface\n");
  298. on_each_cpu(&_ipi_mask_cpu, NULL, true);
  299. sdei_firmware_call = NULL;
  300. }
  301. static int sdei_platform_reset(void)
  302. {
  303. int err;
  304. on_each_cpu(&_ipi_private_reset, NULL, true);
  305. err = sdei_api_shared_reset();
  306. if (err) {
  307. pr_err("Failed to reset platform: %d\n", err);
  308. sdei_mark_interface_broken();
  309. }
  310. return err;
  311. }
  312. static int sdei_api_event_enable(u32 event_num)
  313. {
  314. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_ENABLE, event_num, 0, 0, 0,
  315. 0, NULL);
  316. }
  317. /* Called directly by the hotplug callbacks */
  318. static void _local_event_enable(void *data)
  319. {
  320. int err;
  321. struct sdei_crosscall_args *arg = data;
  322. err = sdei_api_event_enable(arg->event->event_num);
  323. sdei_cross_call_return(arg, err);
  324. }
  325. int sdei_event_enable(u32 event_num)
  326. {
  327. int err = -EINVAL;
  328. struct sdei_event *event;
  329. mutex_lock(&sdei_events_lock);
  330. event = sdei_event_find(event_num);
  331. if (!event) {
  332. mutex_unlock(&sdei_events_lock);
  333. return -ENOENT;
  334. }
  335. cpus_read_lock();
  336. if (event->type == SDEI_EVENT_TYPE_SHARED)
  337. err = sdei_api_event_enable(event->event_num);
  338. else
  339. err = sdei_do_cross_call(_local_event_enable, event);
  340. if (!err) {
  341. spin_lock(&sdei_list_lock);
  342. event->reenable = true;
  343. spin_unlock(&sdei_list_lock);
  344. }
  345. cpus_read_unlock();
  346. mutex_unlock(&sdei_events_lock);
  347. return err;
  348. }
  349. static int sdei_api_event_disable(u32 event_num)
  350. {
  351. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_DISABLE, event_num, 0, 0,
  352. 0, 0, NULL);
  353. }
  354. static void _ipi_event_disable(void *data)
  355. {
  356. int err;
  357. struct sdei_crosscall_args *arg = data;
  358. err = sdei_api_event_disable(arg->event->event_num);
  359. sdei_cross_call_return(arg, err);
  360. }
  361. int sdei_event_disable(u32 event_num)
  362. {
  363. int err = -EINVAL;
  364. struct sdei_event *event;
  365. mutex_lock(&sdei_events_lock);
  366. event = sdei_event_find(event_num);
  367. if (!event) {
  368. mutex_unlock(&sdei_events_lock);
  369. return -ENOENT;
  370. }
  371. spin_lock(&sdei_list_lock);
  372. event->reenable = false;
  373. spin_unlock(&sdei_list_lock);
  374. if (event->type == SDEI_EVENT_TYPE_SHARED)
  375. err = sdei_api_event_disable(event->event_num);
  376. else
  377. err = sdei_do_cross_call(_ipi_event_disable, event);
  378. mutex_unlock(&sdei_events_lock);
  379. return err;
  380. }
  381. static int sdei_api_event_unregister(u32 event_num)
  382. {
  383. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_UNREGISTER, event_num, 0,
  384. 0, 0, 0, NULL);
  385. }
  386. /* Called directly by the hotplug callbacks */
  387. static void _local_event_unregister(void *data)
  388. {
  389. int err;
  390. struct sdei_crosscall_args *arg = data;
  391. err = sdei_api_event_unregister(arg->event->event_num);
  392. sdei_cross_call_return(arg, err);
  393. }
  394. int sdei_event_unregister(u32 event_num)
  395. {
  396. int err;
  397. struct sdei_event *event;
  398. WARN_ON(in_nmi());
  399. mutex_lock(&sdei_events_lock);
  400. event = sdei_event_find(event_num);
  401. if (!event) {
  402. pr_warn("Event %u not registered\n", event_num);
  403. err = -ENOENT;
  404. goto unlock;
  405. }
  406. spin_lock(&sdei_list_lock);
  407. event->reregister = false;
  408. event->reenable = false;
  409. spin_unlock(&sdei_list_lock);
  410. if (event->type == SDEI_EVENT_TYPE_SHARED)
  411. err = sdei_api_event_unregister(event->event_num);
  412. else
  413. err = sdei_do_cross_call(_local_event_unregister, event);
  414. if (err)
  415. goto unlock;
  416. sdei_event_destroy(event);
  417. unlock:
  418. mutex_unlock(&sdei_events_lock);
  419. return err;
  420. }
  421. /*
  422. * unregister events, but don't destroy them as they are re-registered by
  423. * sdei_reregister_shared().
  424. */
  425. static int sdei_unregister_shared(void)
  426. {
  427. int err = 0;
  428. struct sdei_event *event;
  429. mutex_lock(&sdei_events_lock);
  430. spin_lock(&sdei_list_lock);
  431. list_for_each_entry(event, &sdei_list, list) {
  432. if (event->type != SDEI_EVENT_TYPE_SHARED)
  433. continue;
  434. err = sdei_api_event_unregister(event->event_num);
  435. if (err)
  436. break;
  437. }
  438. spin_unlock(&sdei_list_lock);
  439. mutex_unlock(&sdei_events_lock);
  440. return err;
  441. }
  442. static int sdei_api_event_register(u32 event_num, unsigned long entry_point,
  443. void *arg, u64 flags, u64 affinity)
  444. {
  445. return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_REGISTER, event_num,
  446. (unsigned long)entry_point, (unsigned long)arg,
  447. flags, affinity, NULL);
  448. }
  449. /* Called directly by the hotplug callbacks */
  450. static void _local_event_register(void *data)
  451. {
  452. int err;
  453. struct sdei_registered_event *reg;
  454. struct sdei_crosscall_args *arg = data;
  455. reg = per_cpu_ptr(arg->event->private_registered, smp_processor_id());
  456. err = sdei_api_event_register(arg->event->event_num, sdei_entry_point,
  457. reg, 0, 0);
  458. sdei_cross_call_return(arg, err);
  459. }
  460. int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg)
  461. {
  462. int err;
  463. struct sdei_event *event;
  464. WARN_ON(in_nmi());
  465. mutex_lock(&sdei_events_lock);
  466. if (sdei_event_find(event_num)) {
  467. pr_warn("Event %u already registered\n", event_num);
  468. err = -EBUSY;
  469. goto unlock;
  470. }
  471. event = sdei_event_create(event_num, cb, arg);
  472. if (IS_ERR(event)) {
  473. err = PTR_ERR(event);
  474. pr_warn("Failed to create event %u: %d\n", event_num, err);
  475. goto unlock;
  476. }
  477. cpus_read_lock();
  478. if (event->type == SDEI_EVENT_TYPE_SHARED) {
  479. err = sdei_api_event_register(event->event_num,
  480. sdei_entry_point,
  481. event->registered,
  482. SDEI_EVENT_REGISTER_RM_ANY, 0);
  483. } else {
  484. err = sdei_do_cross_call(_local_event_register, event);
  485. if (err)
  486. sdei_do_cross_call(_local_event_unregister, event);
  487. }
  488. if (err) {
  489. sdei_event_destroy(event);
  490. pr_warn("Failed to register event %u: %d\n", event_num, err);
  491. goto cpu_unlock;
  492. }
  493. spin_lock(&sdei_list_lock);
  494. event->reregister = true;
  495. spin_unlock(&sdei_list_lock);
  496. cpu_unlock:
  497. cpus_read_unlock();
  498. unlock:
  499. mutex_unlock(&sdei_events_lock);
  500. return err;
  501. }
  502. static int sdei_reregister_shared(void)
  503. {
  504. int err = 0;
  505. struct sdei_event *event;
  506. mutex_lock(&sdei_events_lock);
  507. spin_lock(&sdei_list_lock);
  508. list_for_each_entry(event, &sdei_list, list) {
  509. if (event->type != SDEI_EVENT_TYPE_SHARED)
  510. continue;
  511. if (event->reregister) {
  512. err = sdei_api_event_register(event->event_num,
  513. sdei_entry_point, event->registered,
  514. SDEI_EVENT_REGISTER_RM_ANY, 0);
  515. if (err) {
  516. pr_err("Failed to re-register event %u\n",
  517. event->event_num);
  518. sdei_event_destroy_llocked(event);
  519. break;
  520. }
  521. }
  522. if (event->reenable) {
  523. err = sdei_api_event_enable(event->event_num);
  524. if (err) {
  525. pr_err("Failed to re-enable event %u\n",
  526. event->event_num);
  527. break;
  528. }
  529. }
  530. }
  531. spin_unlock(&sdei_list_lock);
  532. mutex_unlock(&sdei_events_lock);
  533. return err;
  534. }
  535. static int sdei_cpuhp_down(unsigned int cpu)
  536. {
  537. struct sdei_event *event;
  538. int err;
  539. /* un-register private events */
  540. spin_lock(&sdei_list_lock);
  541. list_for_each_entry(event, &sdei_list, list) {
  542. if (event->type == SDEI_EVENT_TYPE_SHARED)
  543. continue;
  544. err = sdei_do_local_call(_local_event_unregister, event);
  545. if (err) {
  546. pr_err("Failed to unregister event %u: %d\n",
  547. event->event_num, err);
  548. }
  549. }
  550. spin_unlock(&sdei_list_lock);
  551. return sdei_mask_local_cpu();
  552. }
  553. static int sdei_cpuhp_up(unsigned int cpu)
  554. {
  555. struct sdei_event *event;
  556. int err;
  557. /* re-register/enable private events */
  558. spin_lock(&sdei_list_lock);
  559. list_for_each_entry(event, &sdei_list, list) {
  560. if (event->type == SDEI_EVENT_TYPE_SHARED)
  561. continue;
  562. if (event->reregister) {
  563. err = sdei_do_local_call(_local_event_register, event);
  564. if (err) {
  565. pr_err("Failed to re-register event %u: %d\n",
  566. event->event_num, err);
  567. }
  568. }
  569. if (event->reenable) {
  570. err = sdei_do_local_call(_local_event_enable, event);
  571. if (err) {
  572. pr_err("Failed to re-enable event %u: %d\n",
  573. event->event_num, err);
  574. }
  575. }
  576. }
  577. spin_unlock(&sdei_list_lock);
  578. return sdei_unmask_local_cpu();
  579. }
  580. /* When entering idle, mask/unmask events for this cpu */
  581. static int sdei_pm_notifier(struct notifier_block *nb, unsigned long action,
  582. void *data)
  583. {
  584. int rv;
  585. WARN_ON_ONCE(preemptible());
  586. switch (action) {
  587. case CPU_PM_ENTER:
  588. rv = sdei_mask_local_cpu();
  589. break;
  590. case CPU_PM_EXIT:
  591. case CPU_PM_ENTER_FAILED:
  592. rv = sdei_unmask_local_cpu();
  593. break;
  594. default:
  595. return NOTIFY_DONE;
  596. }
  597. if (rv)
  598. return notifier_from_errno(rv);
  599. return NOTIFY_OK;
  600. }
  601. static struct notifier_block sdei_pm_nb = {
  602. .notifier_call = sdei_pm_notifier,
  603. };
  604. static int sdei_device_suspend(struct device *dev)
  605. {
  606. on_each_cpu(_ipi_mask_cpu, NULL, true);
  607. return 0;
  608. }
  609. static int sdei_device_resume(struct device *dev)
  610. {
  611. on_each_cpu(_ipi_unmask_cpu, NULL, true);
  612. return 0;
  613. }
  614. /*
  615. * We need all events to be reregistered when we resume from hibernate.
  616. *
  617. * The sequence is freeze->thaw. Reboot. freeze->restore. We unregister
  618. * events during freeze, then re-register and re-enable them during thaw
  619. * and restore.
  620. */
  621. static int sdei_device_freeze(struct device *dev)
  622. {
  623. int err;
  624. /* unregister private events */
  625. cpuhp_remove_state(sdei_entry_point);
  626. err = sdei_unregister_shared();
  627. if (err)
  628. return err;
  629. return 0;
  630. }
  631. static int sdei_device_thaw(struct device *dev)
  632. {
  633. int err;
  634. /* re-register shared events */
  635. err = sdei_reregister_shared();
  636. if (err) {
  637. pr_warn("Failed to re-register shared events...\n");
  638. sdei_mark_interface_broken();
  639. return err;
  640. }
  641. err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "SDEI",
  642. &sdei_cpuhp_up, &sdei_cpuhp_down);
  643. if (err < 0) {
  644. pr_warn("Failed to re-register CPU hotplug notifier...\n");
  645. return err;
  646. }
  647. sdei_hp_state = err;
  648. return 0;
  649. }
  650. static int sdei_device_restore(struct device *dev)
  651. {
  652. int err;
  653. err = sdei_platform_reset();
  654. if (err)
  655. return err;
  656. return sdei_device_thaw(dev);
  657. }
  658. static const struct dev_pm_ops sdei_pm_ops = {
  659. .suspend = sdei_device_suspend,
  660. .resume = sdei_device_resume,
  661. .freeze = sdei_device_freeze,
  662. .thaw = sdei_device_thaw,
  663. .restore = sdei_device_restore,
  664. };
  665. /*
  666. * Mask all CPUs and unregister all events on panic, reboot or kexec.
  667. */
  668. static int sdei_reboot_notifier(struct notifier_block *nb, unsigned long action,
  669. void *data)
  670. {
  671. /*
  672. * We are going to reset the interface, after this there is no point
  673. * doing work when we take CPUs offline.
  674. */
  675. cpuhp_remove_state(sdei_hp_state);
  676. sdei_platform_reset();
  677. return NOTIFY_OK;
  678. }
  679. static struct notifier_block sdei_reboot_nb = {
  680. .notifier_call = sdei_reboot_notifier,
  681. };
  682. static void sdei_smccc_smc(unsigned long function_id,
  683. unsigned long arg0, unsigned long arg1,
  684. unsigned long arg2, unsigned long arg3,
  685. unsigned long arg4, struct arm_smccc_res *res)
  686. {
  687. arm_smccc_smc(function_id, arg0, arg1, arg2, arg3, arg4, 0, 0, res);
  688. }
  689. NOKPROBE_SYMBOL(sdei_smccc_smc);
  690. static void sdei_smccc_hvc(unsigned long function_id,
  691. unsigned long arg0, unsigned long arg1,
  692. unsigned long arg2, unsigned long arg3,
  693. unsigned long arg4, struct arm_smccc_res *res)
  694. {
  695. arm_smccc_hvc(function_id, arg0, arg1, arg2, arg3, arg4, 0, 0, res);
  696. }
  697. NOKPROBE_SYMBOL(sdei_smccc_hvc);
  698. int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
  699. sdei_event_callback *critical_cb)
  700. {
  701. int err;
  702. u64 result;
  703. u32 event_num;
  704. sdei_event_callback *cb;
  705. if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
  706. return -EOPNOTSUPP;
  707. event_num = ghes->generic->notify.vector;
  708. if (event_num == 0) {
  709. /*
  710. * Event 0 is reserved by the specification for
  711. * SDEI_EVENT_SIGNAL.
  712. */
  713. return -EINVAL;
  714. }
  715. err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_PRIORITY,
  716. &result);
  717. if (err)
  718. return err;
  719. if (result == SDEI_EVENT_PRIORITY_CRITICAL)
  720. cb = critical_cb;
  721. else
  722. cb = normal_cb;
  723. err = sdei_event_register(event_num, cb, ghes);
  724. if (!err)
  725. err = sdei_event_enable(event_num);
  726. return err;
  727. }
  728. int sdei_unregister_ghes(struct ghes *ghes)
  729. {
  730. int i;
  731. int err;
  732. u32 event_num = ghes->generic->notify.vector;
  733. might_sleep();
  734. if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
  735. return -EOPNOTSUPP;
  736. /*
  737. * The event may be running on another CPU. Disable it
  738. * to stop new events, then try to unregister a few times.
  739. */
  740. err = sdei_event_disable(event_num);
  741. if (err)
  742. return err;
  743. for (i = 0; i < 3; i++) {
  744. err = sdei_event_unregister(event_num);
  745. if (err != -EINPROGRESS)
  746. break;
  747. schedule();
  748. }
  749. return err;
  750. }
  751. static int sdei_get_conduit(struct platform_device *pdev)
  752. {
  753. const char *method;
  754. struct device_node *np = pdev->dev.of_node;
  755. sdei_firmware_call = NULL;
  756. if (np) {
  757. if (of_property_read_string(np, "method", &method)) {
  758. pr_warn("missing \"method\" property\n");
  759. return SMCCC_CONDUIT_NONE;
  760. }
  761. if (!strcmp("hvc", method)) {
  762. sdei_firmware_call = &sdei_smccc_hvc;
  763. return SMCCC_CONDUIT_HVC;
  764. } else if (!strcmp("smc", method)) {
  765. sdei_firmware_call = &sdei_smccc_smc;
  766. return SMCCC_CONDUIT_SMC;
  767. }
  768. pr_warn("invalid \"method\" property: %s\n", method);
  769. } else if (!acpi_disabled) {
  770. if (acpi_psci_use_hvc()) {
  771. sdei_firmware_call = &sdei_smccc_hvc;
  772. return SMCCC_CONDUIT_HVC;
  773. } else {
  774. sdei_firmware_call = &sdei_smccc_smc;
  775. return SMCCC_CONDUIT_SMC;
  776. }
  777. }
  778. return SMCCC_CONDUIT_NONE;
  779. }
  780. static int sdei_probe(struct platform_device *pdev)
  781. {
  782. int err;
  783. u64 ver = 0;
  784. int conduit;
  785. conduit = sdei_get_conduit(pdev);
  786. if (!sdei_firmware_call)
  787. return 0;
  788. err = sdei_api_get_version(&ver);
  789. if (err) {
  790. pr_err("Failed to get SDEI version: %d\n", err);
  791. sdei_mark_interface_broken();
  792. return err;
  793. }
  794. pr_info("SDEIv%d.%d (0x%x) detected in firmware.\n",
  795. (int)SDEI_VERSION_MAJOR(ver), (int)SDEI_VERSION_MINOR(ver),
  796. (int)SDEI_VERSION_VENDOR(ver));
  797. if (SDEI_VERSION_MAJOR(ver) != 1) {
  798. pr_warn("Conflicting SDEI version detected.\n");
  799. sdei_mark_interface_broken();
  800. return -EINVAL;
  801. }
  802. err = sdei_platform_reset();
  803. if (err)
  804. return err;
  805. sdei_entry_point = sdei_arch_get_entry_point(conduit);
  806. if (!sdei_entry_point) {
  807. /* Not supported due to hardware or boot configuration */
  808. sdei_mark_interface_broken();
  809. return 0;
  810. }
  811. err = cpu_pm_register_notifier(&sdei_pm_nb);
  812. if (err) {
  813. pr_warn("Failed to register CPU PM notifier...\n");
  814. goto error;
  815. }
  816. err = register_reboot_notifier(&sdei_reboot_nb);
  817. if (err) {
  818. pr_warn("Failed to register reboot notifier...\n");
  819. goto remove_cpupm;
  820. }
  821. err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "SDEI",
  822. &sdei_cpuhp_up, &sdei_cpuhp_down);
  823. if (err < 0) {
  824. pr_warn("Failed to register CPU hotplug notifier...\n");
  825. goto remove_reboot;
  826. }
  827. sdei_hp_state = err;
  828. return 0;
  829. remove_reboot:
  830. unregister_reboot_notifier(&sdei_reboot_nb);
  831. remove_cpupm:
  832. cpu_pm_unregister_notifier(&sdei_pm_nb);
  833. error:
  834. sdei_mark_interface_broken();
  835. return err;
  836. }
  837. static const struct of_device_id sdei_of_match[] = {
  838. { .compatible = "arm,sdei-1.0" },
  839. {}
  840. };
  841. static struct platform_driver sdei_driver = {
  842. .driver = {
  843. .name = "sdei",
  844. .pm = &sdei_pm_ops,
  845. .of_match_table = sdei_of_match,
  846. },
  847. .probe = sdei_probe,
  848. };
  849. static bool __init sdei_present_acpi(void)
  850. {
  851. acpi_status status;
  852. struct acpi_table_header *sdei_table_header;
  853. if (acpi_disabled)
  854. return false;
  855. status = acpi_get_table(ACPI_SIG_SDEI, 0, &sdei_table_header);
  856. if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
  857. const char *msg = acpi_format_exception(status);
  858. pr_info("Failed to get ACPI:SDEI table, %s\n", msg);
  859. }
  860. if (ACPI_FAILURE(status))
  861. return false;
  862. acpi_put_table(sdei_table_header);
  863. return true;
  864. }
  865. void __init sdei_init(void)
  866. {
  867. struct platform_device *pdev;
  868. int ret;
  869. ret = platform_driver_register(&sdei_driver);
  870. if (ret || !sdei_present_acpi())
  871. return;
  872. pdev = platform_device_register_simple(sdei_driver.driver.name,
  873. 0, NULL, 0);
  874. if (IS_ERR(pdev)) {
  875. ret = PTR_ERR(pdev);
  876. platform_driver_unregister(&sdei_driver);
  877. pr_info("Failed to register ACPI:SDEI platform device %d\n",
  878. ret);
  879. }
  880. }
  881. int sdei_event_handler(struct pt_regs *regs,
  882. struct sdei_registered_event *arg)
  883. {
  884. int err;
  885. u32 event_num = arg->event_num;
  886. err = arg->callback(event_num, regs, arg->callback_arg);
  887. if (err)
  888. pr_err_ratelimited("event %u on CPU %u failed with error: %d\n",
  889. event_num, smp_processor_id(), err);
  890. return err;
  891. }
  892. NOKPROBE_SYMBOL(sdei_event_handler);
  893. void sdei_handler_abort(void)
  894. {
  895. /*
  896. * If the crash happened in an SDEI event handler then we need to
  897. * finish the handler with the firmware so that we can have working
  898. * interrupts in the crash kernel.
  899. */
  900. if (__this_cpu_read(sdei_active_critical_event)) {
  901. pr_warn("still in SDEI critical event context, attempting to finish handler.\n");
  902. __sdei_handler_abort();
  903. __this_cpu_write(sdei_active_critical_event, NULL);
  904. }
  905. if (__this_cpu_read(sdei_active_normal_event)) {
  906. pr_warn("still in SDEI normal event context, attempting to finish handler.\n");
  907. __sdei_handler_abort();
  908. __this_cpu_write(sdei_active_normal_event, NULL);
  909. }
  910. }