1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (C) 2017 Arm Ltd. |
3 | #ifndef __LINUX_ARM_SDEI_H |
4 | #define __LINUX_ARM_SDEI_H |
5 | |
6 | #include <uapi/linux/arm_sdei.h> |
7 | |
8 | #include <acpi/ghes.h> |
9 | |
10 | #ifdef CONFIG_ARM_SDE_INTERFACE |
11 | #include <asm/sdei.h> |
12 | #endif |
13 | |
14 | /* Arch code should override this to set the entry point from firmware... */ |
15 | #ifndef sdei_arch_get_entry_point |
16 | #define sdei_arch_get_entry_point(conduit) (0) |
17 | #endif |
18 | |
19 | /* |
20 | * When an event occurs sdei_event_handler() will call a user-provided callback |
21 | * like this in NMI context on the CPU that received the event. |
22 | */ |
23 | typedef int (sdei_event_callback)(u32 event, struct pt_regs *regs, void *arg); |
24 | |
25 | /* |
26 | * Register your callback to claim an event. The event must be described |
27 | * by firmware. |
28 | */ |
29 | int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg); |
30 | |
31 | /* |
32 | * Calls to sdei_event_unregister() may return EINPROGRESS. Keep calling |
33 | * it until it succeeds. |
34 | */ |
35 | int sdei_event_unregister(u32 event_num); |
36 | |
37 | int sdei_event_enable(u32 event_num); |
38 | int sdei_event_disable(u32 event_num); |
39 | |
40 | /* GHES register/unregister helpers */ |
41 | int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, |
42 | sdei_event_callback *critical_cb); |
43 | int sdei_unregister_ghes(struct ghes *ghes); |
44 | |
45 | #ifdef CONFIG_ARM_SDE_INTERFACE |
46 | /* For use by arch code when CPU hotplug notifiers are not appropriate. */ |
47 | int sdei_mask_local_cpu(void); |
48 | int sdei_unmask_local_cpu(void); |
49 | void __init sdei_init(void); |
50 | void sdei_handler_abort(void); |
51 | #else |
52 | static inline int sdei_mask_local_cpu(void) { return 0; } |
53 | static inline int sdei_unmask_local_cpu(void) { return 0; } |
54 | static inline void sdei_init(void) { } |
55 | static inline void sdei_handler_abort(void) { } |
56 | #endif /* CONFIG_ARM_SDE_INTERFACE */ |
57 | |
58 | |
59 | /* |
60 | * This struct represents an event that has been registered. The driver |
61 | * maintains a list of all events, and which ones are registered. (Private |
62 | * events have one entry in the list, but are registered on each CPU). |
63 | * A pointer to this struct is passed to firmware, and back to the event |
64 | * handler. The event handler can then use this to invoke the registered |
65 | * callback, without having to walk the list. |
66 | * |
67 | * For CPU private events, this structure is per-cpu. |
68 | */ |
69 | struct sdei_registered_event { |
70 | /* For use by arch code: */ |
71 | struct pt_regs interrupted_regs; |
72 | |
73 | sdei_event_callback *callback; |
74 | void *callback_arg; |
75 | u32 event_num; |
76 | u8 priority; |
77 | }; |
78 | |
79 | /* The arch code entry point should then call this when an event arrives. */ |
80 | int notrace sdei_event_handler(struct pt_regs *regs, |
81 | struct sdei_registered_event *arg); |
82 | |
83 | /* arch code may use this to retrieve the extra registers. */ |
84 | int sdei_api_event_context(u32 query, u64 *result); |
85 | |
86 | #endif /* __LINUX_ARM_SDEI_H */ |
87 | |