Skip to content

Commit 8632e9b

Browse files
committed
Merge tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv fixes from Wei Liu: - a series from Tianyu Lan to fix crash reporting on Hyper-V - three miscellaneous cleanup patches * tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: x86/Hyper-V: Report crash data in die() when panic_on_oops is set x86/Hyper-V: Report crash register data when sysctl_record_panic_msg is not set x86/Hyper-V: Report crash register data or kmsg before running crash kernel x86/Hyper-V: Trigger crash enlightenment only once during system crash. x86/Hyper-V: Free hv_panic_page when fail to register kmsg dump x86/Hyper-V: Unload vmbus channel in hv panic callback x86: hyperv: report value of misc_features hv_debugfs: Make hv_debug_root static hv: hyperv_vmbus.h: Replace zero-length array with flexible-array member
2 parents 6cc9306 + f3a99e7 commit 8632e9b

File tree

7 files changed

+67
-24
lines changed

7 files changed

+67
-24
lines changed

arch/x86/hyperv/hv_init.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/mm.h>
2121
#include <linux/hyperv.h>
2222
#include <linux/slab.h>
23+
#include <linux/kernel.h>
2324
#include <linux/cpuhotplug.h>
2425
#include <linux/syscore_ops.h>
2526
#include <clocksource/hyperv_timer.h>
@@ -419,11 +420,14 @@ void hyperv_cleanup(void)
419420
}
420421
EXPORT_SYMBOL_GPL(hyperv_cleanup);
421422

422-
void hyperv_report_panic(struct pt_regs *regs, long err)
423+
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
423424
{
424425
static bool panic_reported;
425426
u64 guest_id;
426427

428+
if (in_die && !panic_on_oops)
429+
return;
430+
427431
/*
428432
* We prefer to report panic on 'die' chain as we have proper
429433
* registers to report, but if we miss it (e.g. on BUG()) we need

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,8 @@ static void __init ms_hyperv_init_platform(void)
227227
ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
228228
ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
229229

230-
pr_info("Hyper-V: features 0x%x, hints 0x%x\n",
231-
ms_hyperv.features, ms_hyperv.hints);
230+
pr_info("Hyper-V: features 0x%x, hints 0x%x, misc 0x%x\n",
231+
ms_hyperv.features, ms_hyperv.hints, ms_hyperv.misc_features);
232232

233233
ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
234234
ms_hyperv.max_lp_index = cpuid_ebx(HYPERV_CPUID_IMPLEMENT_LIMITS);
@@ -263,6 +263,16 @@ static void __init ms_hyperv_init_platform(void)
263263
cpuid_eax(HYPERV_CPUID_NESTED_FEATURES);
264264
}
265265

266+
/*
267+
* Hyper-V expects to get crash register data or kmsg when
268+
* crash enlightment is available and system crashes. Set
269+
* crash_kexec_post_notifiers to be true to make sure that
270+
* calling crash enlightment interface before running kdump
271+
* kernel.
272+
*/
273+
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
274+
crash_kexec_post_notifiers = true;
275+
266276
#ifdef CONFIG_X86_LOCAL_APIC
267277
if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
268278
ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {

drivers/hv/channel_mgmt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,9 @@ void vmbus_initiate_unload(bool crash)
839839
{
840840
struct vmbus_channel_message_header hdr;
841841

842+
if (xchg(&vmbus_connection.conn_state, DISCONNECTED) == DISCONNECTED)
843+
return;
844+
842845
/* Pre-Win2012R2 hosts don't support reconnect */
843846
if (vmbus_proto_version < VERSION_WIN8_1)
844847
return;

drivers/hv/hv_debugfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
#include "hyperv_vmbus.h"
1313

14-
struct dentry *hv_debug_root;
14+
static struct dentry *hv_debug_root;
1515

1616
static int hv_debugfs_delay_get(void *data, u64 *val)
1717
{

drivers/hv/hyperv_vmbus.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ struct vmbus_msginfo {
292292
struct list_head msglist_entry;
293293

294294
/* The message itself */
295-
unsigned char msg[0];
295+
unsigned char msg[];
296296
};
297297

298298

drivers/hv/vmbus_drv.c

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/kdebug.h>
3232
#include <linux/efi.h>
3333
#include <linux/random.h>
34+
#include <linux/kernel.h>
3435
#include <linux/syscore_ops.h>
3536
#include <clocksource/hyperv_timer.h>
3637
#include "hyperv_vmbus.h"
@@ -48,14 +49,35 @@ static int hyperv_cpuhp_online;
4849

4950
static void *hv_panic_page;
5051

52+
/*
53+
* Boolean to control whether to report panic messages over Hyper-V.
54+
*
55+
* It can be set via /proc/sys/kernel/hyperv/record_panic_msg
56+
*/
57+
static int sysctl_record_panic_msg = 1;
58+
59+
static int hyperv_report_reg(void)
60+
{
61+
return !sysctl_record_panic_msg || !hv_panic_page;
62+
}
63+
5164
static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
5265
void *args)
5366
{
5467
struct pt_regs *regs;
5568

56-
regs = current_pt_regs();
69+
vmbus_initiate_unload(true);
5770

58-
hyperv_report_panic(regs, val);
71+
/*
72+
* Hyper-V should be notified only once about a panic. If we will be
73+
* doing hyperv_report_panic_msg() later with kmsg data, don't do
74+
* the notification here.
75+
*/
76+
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
77+
&& hyperv_report_reg()) {
78+
regs = current_pt_regs();
79+
hyperv_report_panic(regs, val, false);
80+
}
5981
return NOTIFY_DONE;
6082
}
6183

@@ -65,7 +87,13 @@ static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
6587
struct die_args *die = (struct die_args *)args;
6688
struct pt_regs *regs = die->regs;
6789

68-
hyperv_report_panic(regs, val);
90+
/*
91+
* Hyper-V should be notified only once about a panic. If we will be
92+
* doing hyperv_report_panic_msg() later with kmsg data, don't do
93+
* the notification here.
94+
*/
95+
if (hyperv_report_reg())
96+
hyperv_report_panic(regs, val, true);
6997
return NOTIFY_DONE;
7098
}
7199

@@ -1252,13 +1280,6 @@ static void vmbus_isr(void)
12521280
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
12531281
}
12541282

1255-
/*
1256-
* Boolean to control whether to report panic messages over Hyper-V.
1257-
*
1258-
* It can be set via /proc/sys/kernel/hyperv/record_panic_msg
1259-
*/
1260-
static int sysctl_record_panic_msg = 1;
1261-
12621283
/*
12631284
* Callback from kmsg_dump. Grab as much as possible from the end of the kmsg
12641285
* buffer and call into Hyper-V to transfer the data.
@@ -1382,19 +1403,29 @@ static int vmbus_bus_init(void)
13821403
hv_panic_page = (void *)hv_alloc_hyperv_zeroed_page();
13831404
if (hv_panic_page) {
13841405
ret = kmsg_dump_register(&hv_kmsg_dumper);
1385-
if (ret)
1406+
if (ret) {
13861407
pr_err("Hyper-V: kmsg dump register "
13871408
"error 0x%x\n", ret);
1409+
hv_free_hyperv_page(
1410+
(unsigned long)hv_panic_page);
1411+
hv_panic_page = NULL;
1412+
}
13881413
} else
13891414
pr_err("Hyper-V: panic message page memory "
13901415
"allocation failed");
13911416
}
13921417

13931418
register_die_notifier(&hyperv_die_block);
1394-
atomic_notifier_chain_register(&panic_notifier_list,
1395-
&hyperv_panic_block);
13961419
}
13971420

1421+
/*
1422+
* Always register the panic notifier because we need to unload
1423+
* the VMbus channel connection to prevent any VMbus
1424+
* activity after the VM panics.
1425+
*/
1426+
atomic_notifier_chain_register(&panic_notifier_list,
1427+
&hyperv_panic_block);
1428+
13981429
vmbus_request_offers();
13991430

14001431
return 0;
@@ -1407,7 +1438,6 @@ static int vmbus_bus_init(void)
14071438
hv_remove_vmbus_irq();
14081439

14091440
bus_unregister(&hv_bus);
1410-
hv_free_hyperv_page((unsigned long)hv_panic_page);
14111441
unregister_sysctl_table(hv_ctl_table_hdr);
14121442
hv_ctl_table_hdr = NULL;
14131443
return ret;
@@ -2204,8 +2234,6 @@ static int vmbus_bus_suspend(struct device *dev)
22042234

22052235
vmbus_initiate_unload(false);
22062236

2207-
vmbus_connection.conn_state = DISCONNECTED;
2208-
22092237
/* Reset the event for the next resume. */
22102238
reinit_completion(&vmbus_connection.ready_for_resume_event);
22112239

@@ -2289,7 +2317,6 @@ static void hv_kexec_handler(void)
22892317
{
22902318
hv_stimer_global_cleanup();
22912319
vmbus_initiate_unload(false);
2292-
vmbus_connection.conn_state = DISCONNECTED;
22932320
/* Make sure conn_state is set as hv_synic_cleanup checks for it */
22942321
mb();
22952322
cpuhp_remove_state(hyperv_cpuhp_online);
@@ -2306,7 +2333,6 @@ static void hv_crash_handler(struct pt_regs *regs)
23062333
* doing the cleanup for current CPU only. This should be sufficient
23072334
* for kdump.
23082335
*/
2309-
vmbus_connection.conn_state = DISCONNECTED;
23102336
cpu = smp_processor_id();
23112337
hv_stimer_cleanup(cpu);
23122338
hv_synic_disable_regs(cpu);

include/asm-generic/mshyperv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
163163
return nr_bank;
164164
}
165165

166-
void hyperv_report_panic(struct pt_regs *regs, long err);
166+
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
167167
void hyperv_report_panic_msg(phys_addr_t pa, size_t size);
168168
bool hv_is_hyperv_initialized(void);
169169
bool hv_is_hibernation_supported(void);

0 commit comments

Comments
 (0)