cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

arm_sdei.c (23704B)


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