Received: by 2002:ab3:6bd8:0:b0:1d9:5b01:1edb with SMTP id v24csp6137ltk; Fri, 19 Aug 2022 15:38:04 -0700 (PDT) X-Google-Smtp-Source: AA6agR4+V4x3PkhaswFAbGwsvVBdH4aXIW7fb5Udkhebp+GlO0mUKXCo7u/FtZE/w5r1SRGf/5l/ X-Received: by 2002:a05:6402:5cd:b0:446:5965:f4af with SMTP id n13-20020a05640205cd00b004465965f4afmr2207202edx.12.1660948683743; Fri, 19 Aug 2022 15:38:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1660948683; cv=none; d=google.com; s=arc-20160816; b=jZ8eR5yRKnWXEEuu/CuLmmN8gWzsJnzwbRakCFkrUSBY50EYxYQstZwl0Xz+3vfmiZ IGGZCc/go0ArGqrIAeZzt1uIVR/cchbTbyhjzcEEMLDHrh5rNYVNnh/7FxwMlFy31cux 4HxNb0uPoFVKOruvyp3rPOqiw1AOGq9vkMnZR/8Sh2Fp1/ZqFfAlyIjm4tmKNu7v241P iweHMJTKZLO14jtyY8/GCv4IPPP9AJhF6T1NSs1Xj2QhF0QqHNqJWfQcS3q8L35k7Yf4 HDIT50YmURG3tcOKcve9TeUStj3I8VsfiSzuMZ7nfqwxm2uy0ldvdVAWg/reniZQzeVG iDTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=JM9Drna9qCkuXYcgitMbKoCXFed7NeXSxXsah2tjvgg=; b=b5rmY88Nr7x0O6A5vdHKe3TQERkZN+0pkteWTUzHUVD8vzxhbX+TnI28F3rUaW9O8e Dw2G67uIWMi+EKQu29Qa7kEUgF+n2MPuHM67PcgE5tO5+Q+2PYZ93LFdLJXq1oAUI0qx X1QmbOlcfYs/qWmcDvHOAieEV3v5Rk3kUJODdwPmPFtmTn/K8AENTjvTisZV0WcYbI8J EGCPse5G3kePhtwEpigA0ilK1biq8etc80kyd517nCmXSa7z5+xj3JjCQRQmAht8zSZu JwMR/dKZmcqp9IL7BrIQtSkIdauyv/+JGH8vE3CTUku9WldNeRxcRlI+zJObCaVly8hM 5N0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@igalia.com header.s=20170329 header.b=p6K24F8r; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id tj2-20020a170907c24200b00738399b2bc9si3329097ejc.166.2022.08.19.15.37.37; Fri, 19 Aug 2022 15:38:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=fail header.i=@igalia.com header.s=20170329 header.b=p6K24F8r; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242191AbiHSW0q (ORCPT + 99 others); Fri, 19 Aug 2022 18:26:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53844 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241975AbiHSW0n (ORCPT ); Fri, 19 Aug 2022 18:26:43 -0400 Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0056F10A74E; Fri, 19 Aug 2022 15:26:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=JM9Drna9qCkuXYcgitMbKoCXFed7NeXSxXsah2tjvgg=; b=p6K24F8rtU3d2Ldfz0e5oJ9YuZ +KS6jNUq85CuFdFWjmJeia7WQ3YSDoUhro8F0PDVzyBBqiRkw6w91u7Zss9p2XNWqe0CRCv3WXtNO D/13l+mEenSy7LUNO882WVlwkbVHvEs9j9aU0jFdJYIUXJeoKHmpMZmuASj4VbQ+yV4eAhfdzt3XA rQX+NTVhKPJEz3Uu1BbUVYPCLApghZIKc0252OOOT/VdJhFXJXobcNY1VuDF5AHGkEY6+9gZFx7vM +LzLXSMwkxnG//aM2mgzIowrUrI3X7MRE3ah9WkBAGGMBStW7TJdj3Rl1E6THySNikKx/1E8Wi4dn J2J1lH+A==; Received: from [179.232.144.59] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1oPARm-00CbEo-54; Sat, 20 Aug 2022 00:26:36 +0200 From: "Guilherme G. Piccoli" To: akpm@linux-foundation.org, bhe@redhat.com, pmladek@suse.com, kexec@lists.infradead.org Cc: linux-kernel@vger.kernel.org, linux-hyperv@vger.kernel.org, netdev@vger.kernel.org, x86@kernel.org, kernel-dev@igalia.com, kernel@gpiccoli.net, halves@canonical.com, fabiomirmar@gmail.com, alejandro.j.jimenez@oracle.com, andriy.shevchenko@linux.intel.com, arnd@arndb.de, bp@alien8.de, corbet@lwn.net, d.hatayama@jp.fujitsu.com, dave.hansen@linux.intel.com, dyoung@redhat.com, feng.tang@intel.com, gregkh@linuxfoundation.org, mikelley@microsoft.com, hidehiro.kawai.ez@hitachi.com, jgross@suse.com, john.ogness@linutronix.de, keescook@chromium.org, luto@kernel.org, mhiramat@kernel.org, mingo@redhat.com, paulmck@kernel.org, peterz@infradead.org, rostedt@goodmis.org, senozhatsky@chromium.org, stern@rowland.harvard.edu, tglx@linutronix.de, vgoyal@redhat.com, vkuznets@redhat.com, will@kernel.org, xuqiang36@huawei.com, "Guilherme G. Piccoli" , Andrea Parri , Dexuan Cui , Haiyang Zhang , "K. Y. Srinivasan" , Stephen Hemminger , Tianyu Lan , Wei Liu Subject: [PATCH V3 10/11] drivers/hv/vmbus, video/hyperv_fb: Untangle and refactor Hyper-V panic notifiers Date: Fri, 19 Aug 2022 19:17:30 -0300 Message-Id: <20220819221731.480795-11-gpiccoli@igalia.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220819221731.480795-1-gpiccoli@igalia.com> References: <20220819221731.480795-1-gpiccoli@igalia.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently Hyper-V guests are among the most relevant users of the panic infrastructure, like panic notifiers, kmsg dumpers, etc. The reasons rely both in cleaning-up procedures (closing hypervisor <-> guest connection, disabling some paravirtualized timer) as well as to data collection (sending panic information to the hypervisor) and framebuffer management. The thing is: some notifiers are related to others, ordering matters, some functionalities are duplicated and there are lots of conditionals behind sending panic information to the hypervisor. As part of an effort to clean-up the panic notifiers mechanism and better document things, we hereby address some of the issues/complexities of Hyper-V panic handling through the following changes: (a) We have die and panic notifiers on vmbus_drv.c and both have goals of sending panic information to the hypervisor, though the panic notifier is also responsible for a cleaning-up procedure. This commit clears the code by splitting the panic notifier in two, one for closing the vmbus connection whereas the other is only for sending panic info to hypervisor. With that, it was possible to merge the die and panic notifiers in a single/well-documented function, and clear some conditional complexities on sending such information to the hypervisor. (b) There is a Hyper-V framebuffer panic notifier, which relies in doing a vmbus operation that demands a valid connection. So, we must order this notifier with the panic notifier from vmbus_drv.c, to guarantee that the framebuffer code executes before the vmbus connection is unloaded. Also, this commit removes a useless header. Although there is code rework and re-ordering, we expect that this change has no functional regressions but instead optimize the path and increase panic reliability on Hyper-V. This was tested on Hyper-V with success. Cc: Andrea Parri (Microsoft) Cc: Dexuan Cui Cc: Haiyang Zhang Cc: "K. Y. Srinivasan" Cc: Petr Mladek Cc: Stephen Hemminger Cc: Tianyu Lan Cc: Wei Liu Reviewed-by: Michael Kelley Tested-by: Fabio A M Martins Signed-off-by: Guilherme G. Piccoli --- V3: - Added Michael's review tag - thanks! V2: - Unfortunately we cannot rely in the crash shutdown (custom) handler to perform the vmbus unload - arm64 architecture doesn't have this "feature" [0]. So, in V2 we kept the notifier behavior and always unload the vmbus connection, no matter what - thanks Michael for pointing that; - Removed the Fixes tags as per Michael suggestion; - As per Petr suggestion, we abandoned the idea of distinguish among notifiers using an id - so, in V2 we rely in the old and good address comparison for that. Thanks Petr for the enriching discussion! [0] https://lore.kernel.org/lkml/427a8277-49f0-4317-d6c3-4a15d7070e55@igalia.com/ drivers/hv/vmbus_drv.c | 109 +++++++++++++++++++------------- drivers/video/fbdev/hyperv_fb.c | 8 +++ 2 files changed, 74 insertions(+), 43 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 23c680d1a0f5..0a77e2bb0b70 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -69,53 +68,74 @@ 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, +/* + * The panic notifier below is responsible solely for unloading the + * vmbus connection, which is necessary in a panic event. + * + * Notice an intrincate relation of this notifier with Hyper-V + * framebuffer panic notifier exists - we need vmbus connection alive + * there in order to succeed, so we need to order both with each other + * [see hvfb_on_panic()] - this is done using notifiers' priorities. + */ +static int hv_panic_vmbus_unload(struct notifier_block *nb, unsigned long val, void *args) +{ + vmbus_initiate_unload(true); + return NOTIFY_DONE; +} +static struct notifier_block hyperv_panic_vmbus_unload_block = { + .notifier_call = hv_panic_vmbus_unload, + .priority = INT_MIN + 1, /* almost the latest one to execute */ +}; + +static int hv_die_panic_notify_crash(struct notifier_block *self, + unsigned long val, void *args); + +static struct notifier_block hyperv_die_report_block = { + .notifier_call = hv_die_panic_notify_crash, +}; +static struct notifier_block hyperv_panic_report_block = { + .notifier_call = hv_die_panic_notify_crash, +}; + +/* + * The following callback works both as die and panic notifier; its + * goal is to provide panic information to the hypervisor unless the + * kmsg dumper is used [see hv_kmsg_dump()], which provides more + * information but isn't always available. + * + * Notice that both the panic/die report notifiers are registered only + * if we have the capability HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE set. + */ +static int hv_die_panic_notify_crash(struct notifier_block *self, + unsigned long val, void *args) { struct pt_regs *regs; + bool is_die; - vmbus_initiate_unload(true); - - /* - * Hyper-V should be notified only once about a panic. If we will be - * doing hv_kmsg_dump() with kmsg data later, don't do the notification - * here. - */ - if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE - && hyperv_report_reg()) { + /* Don't notify Hyper-V unless we have a die oops event or panic. */ + if (self == &hyperv_panic_report_block) { + is_die = false; regs = current_pt_regs(); - hyperv_report_panic(regs, val, false); + } else { /* die event */ + if (val != DIE_OOPS) + return NOTIFY_DONE; + + is_die = true; + regs = ((struct die_args *)args)->regs; } - return NOTIFY_DONE; -} - -static int hyperv_die_event(struct notifier_block *nb, unsigned long val, - void *args) -{ - struct die_args *die = args; - struct pt_regs *regs = die->regs; - - /* Don't notify Hyper-V if the die event is other than oops */ - if (val != DIE_OOPS) - return NOTIFY_DONE; /* - * Hyper-V should be notified only once about a panic. If we will be - * doing hv_kmsg_dump() with kmsg data later, don't do the notification - * here. + * Hyper-V should be notified only once about a panic/die. If we will + * be calling hv_kmsg_dump() later with kmsg data, don't do the + * notification here. */ if (hyperv_report_reg()) - hyperv_report_panic(regs, val, true); + hyperv_report_panic(regs, val, is_die); + return NOTIFY_DONE; } -static struct notifier_block hyperv_die_block = { - .notifier_call = hyperv_die_event, -}; -static struct notifier_block hyperv_panic_block = { - .notifier_call = hyperv_panic_event, -}; - static const char *fb_mmio_name = "fb_range"; static struct resource *fb_mmio; static struct resource *hyperv_mmio; @@ -1538,16 +1558,17 @@ static int vmbus_bus_init(void) if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG) hv_kmsg_dump_register(); - register_die_notifier(&hyperv_die_block); + register_die_notifier(&hyperv_die_report_block); + atomic_notifier_chain_register(&panic_notifier_list, + &hyperv_panic_report_block); } /* - * Always register the panic notifier because we need to unload - * the VMbus channel connection to prevent any VMbus - * activity after the VM panics. + * Always register the vmbus unload panic notifier because we + * need to shut the VMbus channel connection on panic. */ atomic_notifier_chain_register(&panic_notifier_list, - &hyperv_panic_block); + &hyperv_panic_vmbus_unload_block); vmbus_request_offers(); @@ -2776,15 +2797,17 @@ static void __exit vmbus_exit(void) if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { kmsg_dump_unregister(&hv_kmsg_dumper); - unregister_die_notifier(&hyperv_die_block); + unregister_die_notifier(&hyperv_die_report_block); + atomic_notifier_chain_unregister(&panic_notifier_list, + &hyperv_panic_report_block); } /* - * The panic notifier is always registered, hence we should + * The vmbus panic notifier is always registered, hence we should * also unconditionally unregister it here as well. */ atomic_notifier_chain_unregister(&panic_notifier_list, - &hyperv_panic_block); + &hyperv_panic_vmbus_unload_block); free_page((unsigned long)hv_panic_page); unregister_sysctl_table(hv_ctl_table_hdr); diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index e1b65a01fb96..9234d31d4305 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -1216,7 +1216,15 @@ static int hvfb_probe(struct hv_device *hdev, par->fb_ready = true; par->synchronous_fb = false; + + /* + * We need to be sure this panic notifier runs _before_ the + * vmbus disconnect, so order it by priority. It must execute + * before the function hv_panic_vmbus_unload() [drivers/hv/vmbus_drv.c], + * which is almost at the end of list, with priority = INT_MIN + 1. + */ par->hvfb_panic_nb.notifier_call = hvfb_on_panic; + par->hvfb_panic_nb.priority = INT_MIN + 10, atomic_notifier_chain_register(&panic_notifier_list, &par->hvfb_panic_nb); -- 2.37.2