Skip to content

Commit

Permalink
Merge tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Apr 14, 2020
2 parents 6cc9306 + f3a99e7 commit 8632e9b
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 24 deletions.
6 changes: 5 additions & 1 deletion arch/x86/hyperv/hv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/mm.h>
#include <linux/hyperv.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/cpuhotplug.h>
#include <linux/syscore_ops.h>
#include <clocksource/hyperv_timer.h>
Expand Down Expand Up @@ -419,11 +420,14 @@ void hyperv_cleanup(void)
}
EXPORT_SYMBOL_GPL(hyperv_cleanup);

void hyperv_report_panic(struct pt_regs *regs, long err)
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
{
static bool panic_reported;
u64 guest_id;

if (in_die && !panic_on_oops)
return;

/*
* We prefer to report panic on 'die' chain as we have proper
* registers to report, but if we miss it (e.g. on BUG()) we need
Expand Down
14 changes: 12 additions & 2 deletions arch/x86/kernel/cpu/mshyperv.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ static void __init ms_hyperv_init_platform(void)
ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);

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

ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
ms_hyperv.max_lp_index = cpuid_ebx(HYPERV_CPUID_IMPLEMENT_LIMITS);
Expand Down Expand Up @@ -263,6 +263,16 @@ static void __init ms_hyperv_init_platform(void)
cpuid_eax(HYPERV_CPUID_NESTED_FEATURES);
}

/*
* Hyper-V expects to get crash register data or kmsg when
* crash enlightment is available and system crashes. Set
* crash_kexec_post_notifiers to be true to make sure that
* calling crash enlightment interface before running kdump
* kernel.
*/
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
crash_kexec_post_notifiers = true;

#ifdef CONFIG_X86_LOCAL_APIC
if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
Expand Down
3 changes: 3 additions & 0 deletions drivers/hv/channel_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,9 @@ void vmbus_initiate_unload(bool crash)
{
struct vmbus_channel_message_header hdr;

if (xchg(&vmbus_connection.conn_state, DISCONNECTED) == DISCONNECTED)
return;

/* Pre-Win2012R2 hosts don't support reconnect */
if (vmbus_proto_version < VERSION_WIN8_1)
return;
Expand Down
2 changes: 1 addition & 1 deletion drivers/hv/hv_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#include "hyperv_vmbus.h"

struct dentry *hv_debug_root;
static struct dentry *hv_debug_root;

static int hv_debugfs_delay_get(void *data, u64 *val)
{
Expand Down
2 changes: 1 addition & 1 deletion drivers/hv/hyperv_vmbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ struct vmbus_msginfo {
struct list_head msglist_entry;

/* The message itself */
unsigned char msg[0];
unsigned char msg[];
};


Expand Down
62 changes: 44 additions & 18 deletions drivers/hv/vmbus_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/kdebug.h>
#include <linux/efi.h>
#include <linux/random.h>
#include <linux/kernel.h>
#include <linux/syscore_ops.h>
#include <clocksource/hyperv_timer.h>
#include "hyperv_vmbus.h"
Expand All @@ -48,14 +49,35 @@ static int hyperv_cpuhp_online;

static void *hv_panic_page;

/*
* Boolean to control whether to report panic messages over Hyper-V.
*
* It can be set via /proc/sys/kernel/hyperv/record_panic_msg
*/
static int sysctl_record_panic_msg = 1;

static int hyperv_report_reg(void)
{
return !sysctl_record_panic_msg || !hv_panic_page;
}

static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
void *args)
{
struct pt_regs *regs;

regs = current_pt_regs();
vmbus_initiate_unload(true);

hyperv_report_panic(regs, val);
/*
* Hyper-V should be notified only once about a panic. If we will be
* doing hyperv_report_panic_msg() later with kmsg data, don't do
* the notification here.
*/
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
&& hyperv_report_reg()) {
regs = current_pt_regs();
hyperv_report_panic(regs, val, false);
}
return NOTIFY_DONE;
}

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

hyperv_report_panic(regs, val);
/*
* Hyper-V should be notified only once about a panic. If we will be
* doing hyperv_report_panic_msg() later with kmsg data, don't do
* the notification here.
*/
if (hyperv_report_reg())
hyperv_report_panic(regs, val, true);
return NOTIFY_DONE;
}

Expand Down Expand Up @@ -1252,13 +1280,6 @@ static void vmbus_isr(void)
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
}

/*
* Boolean to control whether to report panic messages over Hyper-V.
*
* It can be set via /proc/sys/kernel/hyperv/record_panic_msg
*/
static int sysctl_record_panic_msg = 1;

/*
* Callback from kmsg_dump. Grab as much as possible from the end of the kmsg
* buffer and call into Hyper-V to transfer the data.
Expand Down Expand Up @@ -1382,19 +1403,29 @@ static int vmbus_bus_init(void)
hv_panic_page = (void *)hv_alloc_hyperv_zeroed_page();
if (hv_panic_page) {
ret = kmsg_dump_register(&hv_kmsg_dumper);
if (ret)
if (ret) {
pr_err("Hyper-V: kmsg dump register "
"error 0x%x\n", ret);
hv_free_hyperv_page(
(unsigned long)hv_panic_page);
hv_panic_page = NULL;
}
} else
pr_err("Hyper-V: panic message page memory "
"allocation failed");
}

register_die_notifier(&hyperv_die_block);
atomic_notifier_chain_register(&panic_notifier_list,
&hyperv_panic_block);
}

/*
* Always register the panic notifier because we need to unload
* the VMbus channel connection to prevent any VMbus
* activity after the VM panics.
*/
atomic_notifier_chain_register(&panic_notifier_list,
&hyperv_panic_block);

vmbus_request_offers();

return 0;
Expand All @@ -1407,7 +1438,6 @@ static int vmbus_bus_init(void)
hv_remove_vmbus_irq();

bus_unregister(&hv_bus);
hv_free_hyperv_page((unsigned long)hv_panic_page);
unregister_sysctl_table(hv_ctl_table_hdr);
hv_ctl_table_hdr = NULL;
return ret;
Expand Down Expand Up @@ -2204,8 +2234,6 @@ static int vmbus_bus_suspend(struct device *dev)

vmbus_initiate_unload(false);

vmbus_connection.conn_state = DISCONNECTED;

/* Reset the event for the next resume. */
reinit_completion(&vmbus_connection.ready_for_resume_event);

Expand Down Expand Up @@ -2289,7 +2317,6 @@ static void hv_kexec_handler(void)
{
hv_stimer_global_cleanup();
vmbus_initiate_unload(false);
vmbus_connection.conn_state = DISCONNECTED;
/* Make sure conn_state is set as hv_synic_cleanup checks for it */
mb();
cpuhp_remove_state(hyperv_cpuhp_online);
Expand All @@ -2306,7 +2333,6 @@ static void hv_crash_handler(struct pt_regs *regs)
* doing the cleanup for current CPU only. This should be sufficient
* for kdump.
*/
vmbus_connection.conn_state = DISCONNECTED;
cpu = smp_processor_id();
hv_stimer_cleanup(cpu);
hv_synic_disable_regs(cpu);
Expand Down
2 changes: 1 addition & 1 deletion include/asm-generic/mshyperv.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
return nr_bank;
}

void hyperv_report_panic(struct pt_regs *regs, long err);
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
void hyperv_report_panic_msg(phys_addr_t pa, size_t size);
bool hv_is_hyperv_initialized(void);
bool hv_is_hibernation_supported(void);
Expand Down

0 comments on commit 8632e9b

Please sign in to comment.