1717#include <linux/export.h>
1818#include <linux/bitfield.h>
1919#include <linux/cpumask.h>
20+ #include <linux/sched/task_stack.h>
2021#include <linux/panic_notifier.h>
2122#include <linux/ptrace.h>
23+ #include <linux/kdebug.h>
24+ #include <linux/kmsg_dump.h>
2225#include <linux/slab.h>
2326#include <linux/dma-map-ops.h>
2427#include <asm/hyperv-tlfs.h>
@@ -54,6 +57,10 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
5457void * __percpu * hyperv_pcpu_output_arg ;
5558EXPORT_SYMBOL_GPL (hyperv_pcpu_output_arg );
5659
60+ static void hv_kmsg_dump_unregister (void );
61+
62+ static struct ctl_table_header * hv_ctl_table_hdr ;
63+
5764/*
5865 * Hyper-V specific initialization and shutdown code that is
5966 * common across all architectures. Called from architecture
@@ -62,6 +69,12 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg);
6269
6370void __init hv_common_free (void )
6471{
72+ unregister_sysctl_table (hv_ctl_table_hdr );
73+ hv_ctl_table_hdr = NULL ;
74+
75+ if (ms_hyperv .misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE )
76+ hv_kmsg_dump_unregister ();
77+
6578 kfree (hv_vp_index );
6679 hv_vp_index = NULL ;
6780
@@ -72,10 +85,203 @@ void __init hv_common_free(void)
7285 hyperv_pcpu_input_arg = NULL ;
7386}
7487
88+ /*
89+ * Functions for allocating and freeing memory with size and
90+ * alignment HV_HYP_PAGE_SIZE. These functions are needed because
91+ * the guest page size may not be the same as the Hyper-V page
92+ * size. We depend upon kmalloc() aligning power-of-two size
93+ * allocations to the allocation size boundary, so that the
94+ * allocated memory appears to Hyper-V as a page of the size
95+ * it expects.
96+ */
97+
98+ void * hv_alloc_hyperv_page (void )
99+ {
100+ BUILD_BUG_ON (PAGE_SIZE < HV_HYP_PAGE_SIZE );
101+
102+ if (PAGE_SIZE == HV_HYP_PAGE_SIZE )
103+ return (void * )__get_free_page (GFP_KERNEL );
104+ else
105+ return kmalloc (HV_HYP_PAGE_SIZE , GFP_KERNEL );
106+ }
107+ EXPORT_SYMBOL_GPL (hv_alloc_hyperv_page );
108+
109+ void * hv_alloc_hyperv_zeroed_page (void )
110+ {
111+ if (PAGE_SIZE == HV_HYP_PAGE_SIZE )
112+ return (void * )__get_free_page (GFP_KERNEL | __GFP_ZERO );
113+ else
114+ return kzalloc (HV_HYP_PAGE_SIZE , GFP_KERNEL );
115+ }
116+ EXPORT_SYMBOL_GPL (hv_alloc_hyperv_zeroed_page );
117+
118+ void hv_free_hyperv_page (unsigned long addr )
119+ {
120+ if (PAGE_SIZE == HV_HYP_PAGE_SIZE )
121+ free_page (addr );
122+ else
123+ kfree ((void * )addr );
124+ }
125+ EXPORT_SYMBOL_GPL (hv_free_hyperv_page );
126+
127+ static void * hv_panic_page ;
128+
129+ /*
130+ * Boolean to control whether to report panic messages over Hyper-V.
131+ *
132+ * It can be set via /proc/sys/kernel/hyperv_record_panic_msg
133+ */
134+ static int sysctl_record_panic_msg = 1 ;
135+
136+ /*
137+ * sysctl option to allow the user to control whether kmsg data should be
138+ * reported to Hyper-V on panic.
139+ */
140+ static struct ctl_table hv_ctl_table [] = {
141+ {
142+ .procname = "hyperv_record_panic_msg" ,
143+ .data = & sysctl_record_panic_msg ,
144+ .maxlen = sizeof (int ),
145+ .mode = 0644 ,
146+ .proc_handler = proc_dointvec_minmax ,
147+ .extra1 = SYSCTL_ZERO ,
148+ .extra2 = SYSCTL_ONE
149+ },
150+ {}
151+ };
152+
153+ static int hv_die_panic_notify_crash (struct notifier_block * self ,
154+ unsigned long val , void * args );
155+
156+ static struct notifier_block hyperv_die_report_block = {
157+ .notifier_call = hv_die_panic_notify_crash ,
158+ };
159+
160+ static struct notifier_block hyperv_panic_report_block = {
161+ .notifier_call = hv_die_panic_notify_crash ,
162+ };
163+
164+ /*
165+ * The following callback works both as die and panic notifier; its
166+ * goal is to provide panic information to the hypervisor unless the
167+ * kmsg dumper is used [see hv_kmsg_dump()], which provides more
168+ * information but isn't always available.
169+ *
170+ * Notice that both the panic/die report notifiers are registered only
171+ * if we have the capability HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE set.
172+ */
173+ static int hv_die_panic_notify_crash (struct notifier_block * self ,
174+ unsigned long val , void * args )
175+ {
176+ struct pt_regs * regs ;
177+ bool is_die ;
178+
179+ /* Don't notify Hyper-V unless we have a die oops event or panic. */
180+ if (self == & hyperv_panic_report_block ) {
181+ is_die = false;
182+ regs = current_pt_regs ();
183+ } else { /* die event */
184+ if (val != DIE_OOPS )
185+ return NOTIFY_DONE ;
186+
187+ is_die = true;
188+ regs = ((struct die_args * )args )-> regs ;
189+ }
190+
191+ /*
192+ * Hyper-V should be notified only once about a panic/die. If we will
193+ * be calling hv_kmsg_dump() later with kmsg data, don't do the
194+ * notification here.
195+ */
196+ if (!sysctl_record_panic_msg || !hv_panic_page )
197+ hyperv_report_panic (regs , val , is_die );
198+
199+ return NOTIFY_DONE ;
200+ }
201+
202+ /*
203+ * Callback from kmsg_dump. Grab as much as possible from the end of the kmsg
204+ * buffer and call into Hyper-V to transfer the data.
205+ */
206+ static void hv_kmsg_dump (struct kmsg_dumper * dumper ,
207+ enum kmsg_dump_reason reason )
208+ {
209+ struct kmsg_dump_iter iter ;
210+ size_t bytes_written ;
211+
212+ /* We are only interested in panics. */
213+ if (reason != KMSG_DUMP_PANIC || !sysctl_record_panic_msg )
214+ return ;
215+
216+ /*
217+ * Write dump contents to the page. No need to synchronize; panic should
218+ * be single-threaded.
219+ */
220+ kmsg_dump_rewind (& iter );
221+ kmsg_dump_get_buffer (& iter , false, hv_panic_page , HV_HYP_PAGE_SIZE ,
222+ & bytes_written );
223+ if (!bytes_written )
224+ return ;
225+ /*
226+ * P3 to contain the physical address of the panic page & P4 to
227+ * contain the size of the panic data in that page. Rest of the
228+ * registers are no-op when the NOTIFY_MSG flag is set.
229+ */
230+ hv_set_register (HV_REGISTER_CRASH_P0 , 0 );
231+ hv_set_register (HV_REGISTER_CRASH_P1 , 0 );
232+ hv_set_register (HV_REGISTER_CRASH_P2 , 0 );
233+ hv_set_register (HV_REGISTER_CRASH_P3 , virt_to_phys (hv_panic_page ));
234+ hv_set_register (HV_REGISTER_CRASH_P4 , bytes_written );
235+
236+ /*
237+ * Let Hyper-V know there is crash data available along with
238+ * the panic message.
239+ */
240+ hv_set_register (HV_REGISTER_CRASH_CTL ,
241+ (HV_CRASH_CTL_CRASH_NOTIFY |
242+ HV_CRASH_CTL_CRASH_NOTIFY_MSG ));
243+ }
244+
245+ static struct kmsg_dumper hv_kmsg_dumper = {
246+ .dump = hv_kmsg_dump ,
247+ };
248+
249+ static void hv_kmsg_dump_unregister (void )
250+ {
251+ kmsg_dump_unregister (& hv_kmsg_dumper );
252+ unregister_die_notifier (& hyperv_die_report_block );
253+ atomic_notifier_chain_unregister (& panic_notifier_list ,
254+ & hyperv_panic_report_block );
255+
256+ hv_free_hyperv_page ((unsigned long )hv_panic_page );
257+ hv_panic_page = NULL ;
258+ }
259+
260+ static void hv_kmsg_dump_register (void )
261+ {
262+ int ret ;
263+
264+ hv_panic_page = hv_alloc_hyperv_zeroed_page ();
265+ if (!hv_panic_page ) {
266+ pr_err ("Hyper-V: panic message page memory allocation failed\n" );
267+ return ;
268+ }
269+
270+ ret = kmsg_dump_register (& hv_kmsg_dumper );
271+ if (ret ) {
272+ pr_err ("Hyper-V: kmsg dump register error 0x%x\n" , ret );
273+ hv_free_hyperv_page ((unsigned long )hv_panic_page );
274+ hv_panic_page = NULL ;
275+ }
276+ }
277+
75278int __init hv_common_init (void )
76279{
77280 int i ;
78281
282+ if (hv_is_isolation_supported ())
283+ sysctl_record_panic_msg = 0 ;
284+
79285 /*
80286 * Hyper-V expects to get crash register data or kmsg when
81287 * crash enlightment is available and system crashes. Set
@@ -84,8 +290,33 @@ int __init hv_common_init(void)
84290 * kernel.
85291 */
86292 if (ms_hyperv .misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE ) {
293+ u64 hyperv_crash_ctl ;
294+
87295 crash_kexec_post_notifiers = true;
88296 pr_info ("Hyper-V: enabling crash_kexec_post_notifiers\n" );
297+
298+ /*
299+ * Panic message recording (sysctl_record_panic_msg)
300+ * is enabled by default in non-isolated guests and
301+ * disabled by default in isolated guests; the panic
302+ * message recording won't be available in isolated
303+ * guests should the following registration fail.
304+ */
305+ hv_ctl_table_hdr = register_sysctl ("kernel" , hv_ctl_table );
306+ if (!hv_ctl_table_hdr )
307+ pr_err ("Hyper-V: sysctl table register error" );
308+
309+ /*
310+ * Register for panic kmsg callback only if the right
311+ * capability is supported by the hypervisor.
312+ */
313+ hyperv_crash_ctl = hv_get_register (HV_REGISTER_CRASH_CTL );
314+ if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG )
315+ hv_kmsg_dump_register ();
316+
317+ register_die_notifier (& hyperv_die_report_block );
318+ atomic_notifier_chain_register (& panic_notifier_list ,
319+ & hyperv_panic_report_block );
89320 }
90321
91322 /*
0 commit comments