Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (C) 2017 Arm Ltd.
0003 #define pr_fmt(fmt) "sdei: " fmt
0004 
0005 #include <acpi/ghes.h>
0006 #include <linux/acpi.h>
0007 #include <linux/arm_sdei.h>
0008 #include <linux/arm-smccc.h>
0009 #include <linux/atomic.h>
0010 #include <linux/bitops.h>
0011 #include <linux/compiler.h>
0012 #include <linux/cpuhotplug.h>
0013 #include <linux/cpu.h>
0014 #include <linux/cpu_pm.h>
0015 #include <linux/errno.h>
0016 #include <linux/hardirq.h>
0017 #include <linux/kernel.h>
0018 #include <linux/kprobes.h>
0019 #include <linux/kvm_host.h>
0020 #include <linux/list.h>
0021 #include <linux/mutex.h>
0022 #include <linux/notifier.h>
0023 #include <linux/of.h>
0024 #include <linux/of_platform.h>
0025 #include <linux/percpu.h>
0026 #include <linux/platform_device.h>
0027 #include <linux/pm.h>
0028 #include <linux/ptrace.h>
0029 #include <linux/preempt.h>
0030 #include <linux/reboot.h>
0031 #include <linux/slab.h>
0032 #include <linux/smp.h>
0033 #include <linux/spinlock.h>
0034 
0035 /*
0036  * The call to use to reach the firmware.
0037  */
0038 static asmlinkage void (*sdei_firmware_call)(unsigned long function_id,
0039               unsigned long arg0, unsigned long arg1,
0040               unsigned long arg2, unsigned long arg3,
0041               unsigned long arg4, struct arm_smccc_res *res);
0042 
0043 /* entry point from firmware to arch asm code */
0044 static unsigned long sdei_entry_point;
0045 
0046 struct sdei_event {
0047     /* These three are protected by the sdei_list_lock */
0048     struct list_head    list;
0049     bool            reregister;
0050     bool            reenable;
0051 
0052     u32         event_num;
0053     u8          type;
0054     u8          priority;
0055 
0056     /* This pointer is handed to firmware as the event argument. */
0057     union {
0058         /* Shared events */
0059         struct sdei_registered_event *registered;
0060 
0061         /* CPU private events */
0062         struct sdei_registered_event __percpu *private_registered;
0063     };
0064 };
0065 
0066 /* Take the mutex for any API call or modification. Take the mutex first. */
0067 static DEFINE_MUTEX(sdei_events_lock);
0068 
0069 /* and then hold this when modifying the list */
0070 static DEFINE_SPINLOCK(sdei_list_lock);
0071 static LIST_HEAD(sdei_list);
0072 
0073 /* Private events are registered/enabled via IPI passing one of these */
0074 struct sdei_crosscall_args {
0075     struct sdei_event *event;
0076     atomic_t errors;
0077     int first_error;
0078 };
0079 
0080 #define CROSSCALL_INIT(arg, event)      \
0081     do {                    \
0082         arg.event = event;      \
0083         arg.first_error = 0;        \
0084         atomic_set(&arg.errors, 0); \
0085     } while (0)
0086 
0087 static inline int sdei_do_local_call(smp_call_func_t fn,
0088                      struct sdei_event *event)
0089 {
0090     struct sdei_crosscall_args arg;
0091 
0092     CROSSCALL_INIT(arg, event);
0093     fn(&arg);
0094 
0095     return arg.first_error;
0096 }
0097 
0098 static inline int sdei_do_cross_call(smp_call_func_t fn,
0099                      struct sdei_event *event)
0100 {
0101     struct sdei_crosscall_args arg;
0102 
0103     CROSSCALL_INIT(arg, event);
0104     on_each_cpu(fn, &arg, true);
0105 
0106     return arg.first_error;
0107 }
0108 
0109 static inline void
0110 sdei_cross_call_return(struct sdei_crosscall_args *arg, int err)
0111 {
0112     if (err && (atomic_inc_return(&arg->errors) == 1))
0113         arg->first_error = err;
0114 }
0115 
0116 static int sdei_to_linux_errno(unsigned long sdei_err)
0117 {
0118     switch (sdei_err) {
0119     case SDEI_NOT_SUPPORTED:
0120         return -EOPNOTSUPP;
0121     case SDEI_INVALID_PARAMETERS:
0122         return -EINVAL;
0123     case SDEI_DENIED:
0124         return -EPERM;
0125     case SDEI_PENDING:
0126         return -EINPROGRESS;
0127     case SDEI_OUT_OF_RESOURCE:
0128         return -ENOMEM;
0129     }
0130 
0131     return 0;
0132 }
0133 
0134 static int invoke_sdei_fn(unsigned long function_id, unsigned long arg0,
0135               unsigned long arg1, unsigned long arg2,
0136               unsigned long arg3, unsigned long arg4,
0137               u64 *result)
0138 {
0139     int err;
0140     struct arm_smccc_res res;
0141 
0142     if (sdei_firmware_call) {
0143         sdei_firmware_call(function_id, arg0, arg1, arg2, arg3, arg4,
0144                    &res);
0145         err = sdei_to_linux_errno(res.a0);
0146     } else {
0147         /*
0148          * !sdei_firmware_call means we failed to probe or called
0149          * sdei_mark_interface_broken(). -EIO is not an error returned
0150          * by sdei_to_linux_errno() and is used to suppress messages
0151          * from this driver.
0152          */
0153         err = -EIO;
0154         res.a0 = SDEI_NOT_SUPPORTED;
0155     }
0156 
0157     if (result)
0158         *result = res.a0;
0159 
0160     return err;
0161 }
0162 NOKPROBE_SYMBOL(invoke_sdei_fn);
0163 
0164 static struct sdei_event *sdei_event_find(u32 event_num)
0165 {
0166     struct sdei_event *e, *found = NULL;
0167 
0168     lockdep_assert_held(&sdei_events_lock);
0169 
0170     spin_lock(&sdei_list_lock);
0171     list_for_each_entry(e, &sdei_list, list) {
0172         if (e->event_num == event_num) {
0173             found = e;
0174             break;
0175         }
0176     }
0177     spin_unlock(&sdei_list_lock);
0178 
0179     return found;
0180 }
0181 
0182 int sdei_api_event_context(u32 query, u64 *result)
0183 {
0184     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_CONTEXT, query, 0, 0, 0, 0,
0185                   result);
0186 }
0187 NOKPROBE_SYMBOL(sdei_api_event_context);
0188 
0189 static int sdei_api_event_get_info(u32 event, u32 info, u64 *result)
0190 {
0191     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_GET_INFO, event, info, 0,
0192                   0, 0, result);
0193 }
0194 
0195 static struct sdei_event *sdei_event_create(u32 event_num,
0196                         sdei_event_callback *cb,
0197                         void *cb_arg)
0198 {
0199     int err;
0200     u64 result;
0201     struct sdei_event *event;
0202     struct sdei_registered_event *reg;
0203 
0204     lockdep_assert_held(&sdei_events_lock);
0205 
0206     event = kzalloc(sizeof(*event), GFP_KERNEL);
0207     if (!event) {
0208         err = -ENOMEM;
0209         goto fail;
0210     }
0211 
0212     INIT_LIST_HEAD(&event->list);
0213     event->event_num = event_num;
0214 
0215     err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_PRIORITY,
0216                       &result);
0217     if (err)
0218         goto fail;
0219     event->priority = result;
0220 
0221     err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_TYPE,
0222                       &result);
0223     if (err)
0224         goto fail;
0225     event->type = result;
0226 
0227     if (event->type == SDEI_EVENT_TYPE_SHARED) {
0228         reg = kzalloc(sizeof(*reg), GFP_KERNEL);
0229         if (!reg) {
0230             err = -ENOMEM;
0231             goto fail;
0232         }
0233 
0234         reg->event_num = event->event_num;
0235         reg->priority = event->priority;
0236 
0237         reg->callback = cb;
0238         reg->callback_arg = cb_arg;
0239         event->registered = reg;
0240     } else {
0241         int cpu;
0242         struct sdei_registered_event __percpu *regs;
0243 
0244         regs = alloc_percpu(struct sdei_registered_event);
0245         if (!regs) {
0246             err = -ENOMEM;
0247             goto fail;
0248         }
0249 
0250         for_each_possible_cpu(cpu) {
0251             reg = per_cpu_ptr(regs, cpu);
0252 
0253             reg->event_num = event->event_num;
0254             reg->priority = event->priority;
0255             reg->callback = cb;
0256             reg->callback_arg = cb_arg;
0257         }
0258 
0259         event->private_registered = regs;
0260     }
0261 
0262     spin_lock(&sdei_list_lock);
0263     list_add(&event->list, &sdei_list);
0264     spin_unlock(&sdei_list_lock);
0265 
0266     return event;
0267 
0268 fail:
0269     kfree(event);
0270     return ERR_PTR(err);
0271 }
0272 
0273 static void sdei_event_destroy_llocked(struct sdei_event *event)
0274 {
0275     lockdep_assert_held(&sdei_events_lock);
0276     lockdep_assert_held(&sdei_list_lock);
0277 
0278     list_del(&event->list);
0279 
0280     if (event->type == SDEI_EVENT_TYPE_SHARED)
0281         kfree(event->registered);
0282     else
0283         free_percpu(event->private_registered);
0284 
0285     kfree(event);
0286 }
0287 
0288 static void sdei_event_destroy(struct sdei_event *event)
0289 {
0290     spin_lock(&sdei_list_lock);
0291     sdei_event_destroy_llocked(event);
0292     spin_unlock(&sdei_list_lock);
0293 }
0294 
0295 static int sdei_api_get_version(u64 *version)
0296 {
0297     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_VERSION, 0, 0, 0, 0, 0, version);
0298 }
0299 
0300 int sdei_mask_local_cpu(void)
0301 {
0302     int err;
0303 
0304     WARN_ON_ONCE(preemptible());
0305 
0306     err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PE_MASK, 0, 0, 0, 0, 0, NULL);
0307     if (err && err != -EIO) {
0308         pr_warn_once("failed to mask CPU[%u]: %d\n",
0309                   smp_processor_id(), err);
0310         return err;
0311     }
0312 
0313     return 0;
0314 }
0315 
0316 static void _ipi_mask_cpu(void *ignored)
0317 {
0318     sdei_mask_local_cpu();
0319 }
0320 
0321 int sdei_unmask_local_cpu(void)
0322 {
0323     int err;
0324 
0325     WARN_ON_ONCE(preemptible());
0326 
0327     err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PE_UNMASK, 0, 0, 0, 0, 0, NULL);
0328     if (err && err != -EIO) {
0329         pr_warn_once("failed to unmask CPU[%u]: %d\n",
0330                  smp_processor_id(), err);
0331         return err;
0332     }
0333 
0334     return 0;
0335 }
0336 
0337 static void _ipi_unmask_cpu(void *ignored)
0338 {
0339     sdei_unmask_local_cpu();
0340 }
0341 
0342 static void _ipi_private_reset(void *ignored)
0343 {
0344     int err;
0345 
0346     err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PRIVATE_RESET, 0, 0, 0, 0, 0,
0347                  NULL);
0348     if (err && err != -EIO)
0349         pr_warn_once("failed to reset CPU[%u]: %d\n",
0350                  smp_processor_id(), err);
0351 }
0352 
0353 static int sdei_api_shared_reset(void)
0354 {
0355     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_SHARED_RESET, 0, 0, 0, 0, 0,
0356                   NULL);
0357 }
0358 
0359 static void sdei_mark_interface_broken(void)
0360 {
0361     pr_err("disabling SDEI firmware interface\n");
0362     on_each_cpu(&_ipi_mask_cpu, NULL, true);
0363     sdei_firmware_call = NULL;
0364 }
0365 
0366 static int sdei_platform_reset(void)
0367 {
0368     int err;
0369 
0370     on_each_cpu(&_ipi_private_reset, NULL, true);
0371     err = sdei_api_shared_reset();
0372     if (err) {
0373         pr_err("Failed to reset platform: %d\n", err);
0374         sdei_mark_interface_broken();
0375     }
0376 
0377     return err;
0378 }
0379 
0380 static int sdei_api_event_enable(u32 event_num)
0381 {
0382     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_ENABLE, event_num, 0, 0, 0,
0383                   0, NULL);
0384 }
0385 
0386 /* Called directly by the hotplug callbacks */
0387 static void _local_event_enable(void *data)
0388 {
0389     int err;
0390     struct sdei_crosscall_args *arg = data;
0391 
0392     WARN_ON_ONCE(preemptible());
0393 
0394     err = sdei_api_event_enable(arg->event->event_num);
0395 
0396     sdei_cross_call_return(arg, err);
0397 }
0398 
0399 int sdei_event_enable(u32 event_num)
0400 {
0401     int err = -EINVAL;
0402     struct sdei_event *event;
0403 
0404     mutex_lock(&sdei_events_lock);
0405     event = sdei_event_find(event_num);
0406     if (!event) {
0407         mutex_unlock(&sdei_events_lock);
0408         return -ENOENT;
0409     }
0410 
0411 
0412     cpus_read_lock();
0413     if (event->type == SDEI_EVENT_TYPE_SHARED)
0414         err = sdei_api_event_enable(event->event_num);
0415     else
0416         err = sdei_do_cross_call(_local_event_enable, event);
0417 
0418     if (!err) {
0419         spin_lock(&sdei_list_lock);
0420         event->reenable = true;
0421         spin_unlock(&sdei_list_lock);
0422     }
0423     cpus_read_unlock();
0424     mutex_unlock(&sdei_events_lock);
0425 
0426     return err;
0427 }
0428 
0429 static int sdei_api_event_disable(u32 event_num)
0430 {
0431     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_DISABLE, event_num, 0, 0,
0432                   0, 0, NULL);
0433 }
0434 
0435 static void _ipi_event_disable(void *data)
0436 {
0437     int err;
0438     struct sdei_crosscall_args *arg = data;
0439 
0440     err = sdei_api_event_disable(arg->event->event_num);
0441 
0442     sdei_cross_call_return(arg, err);
0443 }
0444 
0445 int sdei_event_disable(u32 event_num)
0446 {
0447     int err = -EINVAL;
0448     struct sdei_event *event;
0449 
0450     mutex_lock(&sdei_events_lock);
0451     event = sdei_event_find(event_num);
0452     if (!event) {
0453         mutex_unlock(&sdei_events_lock);
0454         return -ENOENT;
0455     }
0456 
0457     spin_lock(&sdei_list_lock);
0458     event->reenable = false;
0459     spin_unlock(&sdei_list_lock);
0460 
0461     if (event->type == SDEI_EVENT_TYPE_SHARED)
0462         err = sdei_api_event_disable(event->event_num);
0463     else
0464         err = sdei_do_cross_call(_ipi_event_disable, event);
0465     mutex_unlock(&sdei_events_lock);
0466 
0467     return err;
0468 }
0469 
0470 static int sdei_api_event_unregister(u32 event_num)
0471 {
0472     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_UNREGISTER, event_num, 0,
0473                   0, 0, 0, NULL);
0474 }
0475 
0476 /* Called directly by the hotplug callbacks */
0477 static void _local_event_unregister(void *data)
0478 {
0479     int err;
0480     struct sdei_crosscall_args *arg = data;
0481 
0482     WARN_ON_ONCE(preemptible());
0483 
0484     err = sdei_api_event_unregister(arg->event->event_num);
0485 
0486     sdei_cross_call_return(arg, err);
0487 }
0488 
0489 int sdei_event_unregister(u32 event_num)
0490 {
0491     int err;
0492     struct sdei_event *event;
0493 
0494     WARN_ON(in_nmi());
0495 
0496     mutex_lock(&sdei_events_lock);
0497     event = sdei_event_find(event_num);
0498     if (!event) {
0499         pr_warn("Event %u not registered\n", event_num);
0500         err = -ENOENT;
0501         goto unlock;
0502     }
0503 
0504     spin_lock(&sdei_list_lock);
0505     event->reregister = false;
0506     event->reenable = false;
0507     spin_unlock(&sdei_list_lock);
0508 
0509     if (event->type == SDEI_EVENT_TYPE_SHARED)
0510         err = sdei_api_event_unregister(event->event_num);
0511     else
0512         err = sdei_do_cross_call(_local_event_unregister, event);
0513 
0514     if (err)
0515         goto unlock;
0516 
0517     sdei_event_destroy(event);
0518 unlock:
0519     mutex_unlock(&sdei_events_lock);
0520 
0521     return err;
0522 }
0523 
0524 /*
0525  * unregister events, but don't destroy them as they are re-registered by
0526  * sdei_reregister_shared().
0527  */
0528 static int sdei_unregister_shared(void)
0529 {
0530     int err = 0;
0531     struct sdei_event *event;
0532 
0533     mutex_lock(&sdei_events_lock);
0534     spin_lock(&sdei_list_lock);
0535     list_for_each_entry(event, &sdei_list, list) {
0536         if (event->type != SDEI_EVENT_TYPE_SHARED)
0537             continue;
0538 
0539         err = sdei_api_event_unregister(event->event_num);
0540         if (err)
0541             break;
0542     }
0543     spin_unlock(&sdei_list_lock);
0544     mutex_unlock(&sdei_events_lock);
0545 
0546     return err;
0547 }
0548 
0549 static int sdei_api_event_register(u32 event_num, unsigned long entry_point,
0550                    void *arg, u64 flags, u64 affinity)
0551 {
0552     return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_REGISTER, event_num,
0553                   (unsigned long)entry_point, (unsigned long)arg,
0554                   flags, affinity, NULL);
0555 }
0556 
0557 /* Called directly by the hotplug callbacks */
0558 static void _local_event_register(void *data)
0559 {
0560     int err;
0561     struct sdei_registered_event *reg;
0562     struct sdei_crosscall_args *arg = data;
0563 
0564     WARN_ON(preemptible());
0565 
0566     reg = per_cpu_ptr(arg->event->private_registered, smp_processor_id());
0567     err = sdei_api_event_register(arg->event->event_num, sdei_entry_point,
0568                       reg, 0, 0);
0569 
0570     sdei_cross_call_return(arg, err);
0571 }
0572 
0573 int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg)
0574 {
0575     int err;
0576     struct sdei_event *event;
0577 
0578     WARN_ON(in_nmi());
0579 
0580     mutex_lock(&sdei_events_lock);
0581     if (sdei_event_find(event_num)) {
0582         pr_warn("Event %u already registered\n", event_num);
0583         err = -EBUSY;
0584         goto unlock;
0585     }
0586 
0587     event = sdei_event_create(event_num, cb, arg);
0588     if (IS_ERR(event)) {
0589         err = PTR_ERR(event);
0590         pr_warn("Failed to create event %u: %d\n", event_num, err);
0591         goto unlock;
0592     }
0593 
0594     cpus_read_lock();
0595     if (event->type == SDEI_EVENT_TYPE_SHARED) {
0596         err = sdei_api_event_register(event->event_num,
0597                           sdei_entry_point,
0598                           event->registered,
0599                           SDEI_EVENT_REGISTER_RM_ANY, 0);
0600     } else {
0601         err = sdei_do_cross_call(_local_event_register, event);
0602         if (err)
0603             sdei_do_cross_call(_local_event_unregister, event);
0604     }
0605 
0606     if (err) {
0607         sdei_event_destroy(event);
0608         pr_warn("Failed to register event %u: %d\n", event_num, err);
0609         goto cpu_unlock;
0610     }
0611 
0612     spin_lock(&sdei_list_lock);
0613     event->reregister = true;
0614     spin_unlock(&sdei_list_lock);
0615 cpu_unlock:
0616     cpus_read_unlock();
0617 unlock:
0618     mutex_unlock(&sdei_events_lock);
0619     return err;
0620 }
0621 
0622 static int sdei_reregister_shared(void)
0623 {
0624     int err = 0;
0625     struct sdei_event *event;
0626 
0627     mutex_lock(&sdei_events_lock);
0628     spin_lock(&sdei_list_lock);
0629     list_for_each_entry(event, &sdei_list, list) {
0630         if (event->type != SDEI_EVENT_TYPE_SHARED)
0631             continue;
0632 
0633         if (event->reregister) {
0634             err = sdei_api_event_register(event->event_num,
0635                     sdei_entry_point, event->registered,
0636                     SDEI_EVENT_REGISTER_RM_ANY, 0);
0637             if (err) {
0638                 pr_err("Failed to re-register event %u\n",
0639                        event->event_num);
0640                 sdei_event_destroy_llocked(event);
0641                 break;
0642             }
0643         }
0644 
0645         if (event->reenable) {
0646             err = sdei_api_event_enable(event->event_num);
0647             if (err) {
0648                 pr_err("Failed to re-enable event %u\n",
0649                        event->event_num);
0650                 break;
0651             }
0652         }
0653     }
0654     spin_unlock(&sdei_list_lock);
0655     mutex_unlock(&sdei_events_lock);
0656 
0657     return err;
0658 }
0659 
0660 static int sdei_cpuhp_down(unsigned int cpu)
0661 {
0662     struct sdei_event *event;
0663     int err;
0664 
0665     /* un-register private events */
0666     spin_lock(&sdei_list_lock);
0667     list_for_each_entry(event, &sdei_list, list) {
0668         if (event->type == SDEI_EVENT_TYPE_SHARED)
0669             continue;
0670 
0671         err = sdei_do_local_call(_local_event_unregister, event);
0672         if (err) {
0673             pr_err("Failed to unregister event %u: %d\n",
0674                    event->event_num, err);
0675         }
0676     }
0677     spin_unlock(&sdei_list_lock);
0678 
0679     return sdei_mask_local_cpu();
0680 }
0681 
0682 static int sdei_cpuhp_up(unsigned int cpu)
0683 {
0684     struct sdei_event *event;
0685     int err;
0686 
0687     /* re-register/enable private events */
0688     spin_lock(&sdei_list_lock);
0689     list_for_each_entry(event, &sdei_list, list) {
0690         if (event->type == SDEI_EVENT_TYPE_SHARED)
0691             continue;
0692 
0693         if (event->reregister) {
0694             err = sdei_do_local_call(_local_event_register, event);
0695             if (err) {
0696                 pr_err("Failed to re-register event %u: %d\n",
0697                        event->event_num, err);
0698             }
0699         }
0700 
0701         if (event->reenable) {
0702             err = sdei_do_local_call(_local_event_enable, event);
0703             if (err) {
0704                 pr_err("Failed to re-enable event %u: %d\n",
0705                        event->event_num, err);
0706             }
0707         }
0708     }
0709     spin_unlock(&sdei_list_lock);
0710 
0711     return sdei_unmask_local_cpu();
0712 }
0713 
0714 /* When entering idle, mask/unmask events for this cpu */
0715 static int sdei_pm_notifier(struct notifier_block *nb, unsigned long action,
0716                 void *data)
0717 {
0718     int rv;
0719 
0720     switch (action) {
0721     case CPU_PM_ENTER:
0722         rv = sdei_mask_local_cpu();
0723         break;
0724     case CPU_PM_EXIT:
0725     case CPU_PM_ENTER_FAILED:
0726         rv = sdei_unmask_local_cpu();
0727         break;
0728     default:
0729         return NOTIFY_DONE;
0730     }
0731 
0732     if (rv)
0733         return notifier_from_errno(rv);
0734 
0735     return NOTIFY_OK;
0736 }
0737 
0738 static struct notifier_block sdei_pm_nb = {
0739     .notifier_call = sdei_pm_notifier,
0740 };
0741 
0742 static int sdei_device_suspend(struct device *dev)
0743 {
0744     on_each_cpu(_ipi_mask_cpu, NULL, true);
0745 
0746     return 0;
0747 }
0748 
0749 static int sdei_device_resume(struct device *dev)
0750 {
0751     on_each_cpu(_ipi_unmask_cpu, NULL, true);
0752 
0753     return 0;
0754 }
0755 
0756 /*
0757  * We need all events to be reregistered when we resume from hibernate.
0758  *
0759  * The sequence is freeze->thaw. Reboot. freeze->restore. We unregister
0760  * events during freeze, then re-register and re-enable them during thaw
0761  * and restore.
0762  */
0763 static int sdei_device_freeze(struct device *dev)
0764 {
0765     int err;
0766 
0767     /* unregister private events */
0768     cpuhp_remove_state(CPUHP_AP_ARM_SDEI_STARTING);
0769 
0770     err = sdei_unregister_shared();
0771     if (err)
0772         return err;
0773 
0774     return 0;
0775 }
0776 
0777 static int sdei_device_thaw(struct device *dev)
0778 {
0779     int err;
0780 
0781     /* re-register shared events */
0782     err = sdei_reregister_shared();
0783     if (err) {
0784         pr_warn("Failed to re-register shared events...\n");
0785         sdei_mark_interface_broken();
0786         return err;
0787     }
0788 
0789     err = cpuhp_setup_state(CPUHP_AP_ARM_SDEI_STARTING, "SDEI",
0790                 &sdei_cpuhp_up, &sdei_cpuhp_down);
0791     if (err)
0792         pr_warn("Failed to re-register CPU hotplug notifier...\n");
0793 
0794     return err;
0795 }
0796 
0797 static int sdei_device_restore(struct device *dev)
0798 {
0799     int err;
0800 
0801     err = sdei_platform_reset();
0802     if (err)
0803         return err;
0804 
0805     return sdei_device_thaw(dev);
0806 }
0807 
0808 static const struct dev_pm_ops sdei_pm_ops = {
0809     .suspend = sdei_device_suspend,
0810     .resume = sdei_device_resume,
0811     .freeze = sdei_device_freeze,
0812     .thaw = sdei_device_thaw,
0813     .restore = sdei_device_restore,
0814 };
0815 
0816 /*
0817  * Mask all CPUs and unregister all events on panic, reboot or kexec.
0818  */
0819 static int sdei_reboot_notifier(struct notifier_block *nb, unsigned long action,
0820                 void *data)
0821 {
0822     /*
0823      * We are going to reset the interface, after this there is no point
0824      * doing work when we take CPUs offline.
0825      */
0826     cpuhp_remove_state(CPUHP_AP_ARM_SDEI_STARTING);
0827 
0828     sdei_platform_reset();
0829 
0830     return NOTIFY_OK;
0831 }
0832 
0833 static struct notifier_block sdei_reboot_nb = {
0834     .notifier_call = sdei_reboot_notifier,
0835 };
0836 
0837 static void sdei_smccc_smc(unsigned long function_id,
0838                unsigned long arg0, unsigned long arg1,
0839                unsigned long arg2, unsigned long arg3,
0840                unsigned long arg4, struct arm_smccc_res *res)
0841 {
0842     arm_smccc_smc(function_id, arg0, arg1, arg2, arg3, arg4, 0, 0, res);
0843 }
0844 NOKPROBE_SYMBOL(sdei_smccc_smc);
0845 
0846 static void sdei_smccc_hvc(unsigned long function_id,
0847                unsigned long arg0, unsigned long arg1,
0848                unsigned long arg2, unsigned long arg3,
0849                unsigned long arg4, struct arm_smccc_res *res)
0850 {
0851     arm_smccc_hvc(function_id, arg0, arg1, arg2, arg3, arg4, 0, 0, res);
0852 }
0853 NOKPROBE_SYMBOL(sdei_smccc_hvc);
0854 
0855 int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
0856                sdei_event_callback *critical_cb)
0857 {
0858     int err;
0859     u64 result;
0860     u32 event_num;
0861     sdei_event_callback *cb;
0862 
0863     if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
0864         return -EOPNOTSUPP;
0865 
0866     event_num = ghes->generic->notify.vector;
0867     if (event_num == 0) {
0868         /*
0869          * Event 0 is reserved by the specification for
0870          * SDEI_EVENT_SIGNAL.
0871          */
0872         return -EINVAL;
0873     }
0874 
0875     err = sdei_api_event_get_info(event_num, SDEI_EVENT_INFO_EV_PRIORITY,
0876                       &result);
0877     if (err)
0878         return err;
0879 
0880     if (result == SDEI_EVENT_PRIORITY_CRITICAL)
0881         cb = critical_cb;
0882     else
0883         cb = normal_cb;
0884 
0885     err = sdei_event_register(event_num, cb, ghes);
0886     if (!err)
0887         err = sdei_event_enable(event_num);
0888 
0889     return err;
0890 }
0891 
0892 int sdei_unregister_ghes(struct ghes *ghes)
0893 {
0894     int i;
0895     int err;
0896     u32 event_num = ghes->generic->notify.vector;
0897 
0898     might_sleep();
0899 
0900     if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
0901         return -EOPNOTSUPP;
0902 
0903     /*
0904      * The event may be running on another CPU. Disable it
0905      * to stop new events, then try to unregister a few times.
0906      */
0907     err = sdei_event_disable(event_num);
0908     if (err)
0909         return err;
0910 
0911     for (i = 0; i < 3; i++) {
0912         err = sdei_event_unregister(event_num);
0913         if (err != -EINPROGRESS)
0914             break;
0915 
0916         schedule();
0917     }
0918 
0919     return err;
0920 }
0921 
0922 static int sdei_get_conduit(struct platform_device *pdev)
0923 {
0924     const char *method;
0925     struct device_node *np = pdev->dev.of_node;
0926 
0927     sdei_firmware_call = NULL;
0928     if (np) {
0929         if (of_property_read_string(np, "method", &method)) {
0930             pr_warn("missing \"method\" property\n");
0931             return SMCCC_CONDUIT_NONE;
0932         }
0933 
0934         if (!strcmp("hvc", method)) {
0935             sdei_firmware_call = &sdei_smccc_hvc;
0936             return SMCCC_CONDUIT_HVC;
0937         } else if (!strcmp("smc", method)) {
0938             sdei_firmware_call = &sdei_smccc_smc;
0939             return SMCCC_CONDUIT_SMC;
0940         }
0941 
0942         pr_warn("invalid \"method\" property: %s\n", method);
0943     } else if (!acpi_disabled) {
0944         if (acpi_psci_use_hvc()) {
0945             sdei_firmware_call = &sdei_smccc_hvc;
0946             return SMCCC_CONDUIT_HVC;
0947         } else {
0948             sdei_firmware_call = &sdei_smccc_smc;
0949             return SMCCC_CONDUIT_SMC;
0950         }
0951     }
0952 
0953     return SMCCC_CONDUIT_NONE;
0954 }
0955 
0956 static int sdei_probe(struct platform_device *pdev)
0957 {
0958     int err;
0959     u64 ver = 0;
0960     int conduit;
0961 
0962     conduit = sdei_get_conduit(pdev);
0963     if (!sdei_firmware_call)
0964         return 0;
0965 
0966     err = sdei_api_get_version(&ver);
0967     if (err) {
0968         pr_err("Failed to get SDEI version: %d\n", err);
0969         sdei_mark_interface_broken();
0970         return err;
0971     }
0972 
0973     pr_info("SDEIv%d.%d (0x%x) detected in firmware.\n",
0974         (int)SDEI_VERSION_MAJOR(ver), (int)SDEI_VERSION_MINOR(ver),
0975         (int)SDEI_VERSION_VENDOR(ver));
0976 
0977     if (SDEI_VERSION_MAJOR(ver) != 1) {
0978         pr_warn("Conflicting SDEI version detected.\n");
0979         sdei_mark_interface_broken();
0980         return -EINVAL;
0981     }
0982 
0983     err = sdei_platform_reset();
0984     if (err)
0985         return err;
0986 
0987     sdei_entry_point = sdei_arch_get_entry_point(conduit);
0988     if (!sdei_entry_point) {
0989         /* Not supported due to hardware or boot configuration */
0990         sdei_mark_interface_broken();
0991         return 0;
0992     }
0993 
0994     err = cpu_pm_register_notifier(&sdei_pm_nb);
0995     if (err) {
0996         pr_warn("Failed to register CPU PM notifier...\n");
0997         goto error;
0998     }
0999 
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 
1015 remove_reboot:
1016     unregister_reboot_notifier(&sdei_reboot_nb);
1017 
1018 remove_cpupm:
1019     cpu_pm_unregister_notifier(&sdei_pm_nb);
1020 
1021 error:
1022     sdei_mark_interface_broken();
1023     return err;
1024 }
1025 
1026 static const struct of_device_id sdei_of_match[] = {
1027     { .compatible = "arm,sdei-1.0" },
1028     {}
1029 };
1030 
1031 static 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 
1040 static 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 
1062 void __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 
1081 int 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 }
1094 NOKPROBE_SYMBOL(sdei_event_handler);