From patchwork Fri Sep 13 14:50:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 11144867 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 322E714E5 for ; Fri, 13 Sep 2019 14:53:01 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 035CF20830 for ; Fri, 13 Sep 2019 14:53:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="aWjhOprH" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 035CF20830 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8mvK-0005iP-H3; Fri, 13 Sep 2019 14:51:46 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i8mvJ-0005hu-FW for xen-devel@lists.xenproject.org; Fri, 13 Sep 2019 14:51:45 +0000 X-Inumbo-ID: ebaddf8a-d635-11e9-b299-bc764e2007e4 Received: from esa1.hc3370-68.iphmx.com (unknown [216.71.145.142]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id ebaddf8a-d635-11e9-b299-bc764e2007e4; Fri, 13 Sep 2019 14:51:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1568386269; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IOs1gvcTUToUpQsObk2JavC2UIX7VvOdxsW6CAsBJ5Y=; b=aWjhOprH/Z8iWBw1Xj9He1/SglSOktYPb2qAn5jYEj0hXYjoQAqzmg5q rR+y2G73PKeCvw0cbHZMonzHhjgwm7b+mgQPcv5AVd52ifZFu0AUaBthB qyL/w0xm6HaqkOtye0OlU1KhZGb8x00tt2PMKXvvPDBlV6AflXel6Z/IE o=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=anthony.perard@citrix.com; spf=Pass smtp.mailfrom=anthony.perard@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of anthony.perard@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="anthony.perard@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa1.hc3370-68.iphmx.com: domain of anthony.perard@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="anthony.perard@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: ddcTRW12wA0uCmjNrI/O8WX9I7vcQnpvyypnl+N45WWMhTtD3YHKTFyApqK06QfIrJ0jFIVjWV 0+FrEgmGJ8HS+arVzdX2Q7/QNtRLueOA8zLZBQAGIhgYkQkmUgRmlahB81EsMfTeJagTdupQ3t bEnvPZo8Dgugar8nvtXPW+oc5f4/lwmWdtB23E5AYccfR8/nmFUDE7NlL2jxlWtIGHYsby838H u6pFW87eAXTN9h8xFJWJK5KsyxbrZ5Eg74GC9ibSQ/1vxX2g5Tjua6w5GDTedj8RjYjn3dipOY Djc= X-SBRS: 2.7 X-MesageID: 5595150 X-Ironport-Server: esa1.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,501,1559534400"; d="scan'208";a="5595150" From: Anthony PERARD To: Date: Fri, 13 Sep 2019 15:50:58 +0100 Message-ID: <20190913145100.303433-10-anthony.perard@citrix.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190913145100.303433-1-anthony.perard@citrix.com> References: <20190913145100.303433-1-anthony.perard@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 09/11] OvmfPkg/XenBusDxe: Fix NotifyExitBoot to avoid Memory Allocation Services X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel , Jordan Justen , Julien Grall , Anthony Perard , xen-devel@lists.xenproject.org, Laszlo Ersek Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This patch fix the EVT_SIGNAL_EXIT_BOOT_SERVICES handler to avoid using the Memory Allocation Services. This comes with a new interface named RegisterExitCallback so that PV drivers can disconnect from the backend before XenBusDxe is teared down. Instead of using Disconnect() to tear down the XenBus driver and the children drivers, we are going to ask every driver using XENBUS_PROTOCOL to disconnect from the hardware via the callback set with RegisterExitCallback, then reset the xenstore shared ring and the grant table. Since there are no driver using RegisterExitCallback yet, no driver are going to be disconnected. Linux can deal with that. And that will be fixed by the next patch with a change for XenPvBlkDxe. Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2190 Signed-off-by: Anthony PERARD --- OvmfPkg/Include/Protocol/XenBus.h | 35 +++++++++++++++++++++++++++++++ OvmfPkg/XenBusDxe/XenBus.c | 18 ++++++++++++++++ OvmfPkg/XenBusDxe/XenBusDxe.c | 27 +++++++++++++++++++++--- OvmfPkg/XenBusDxe/XenBusDxe.h | 2 ++ OvmfPkg/XenBusDxe/XenStore.c | 22 ++++++++++++++++++- OvmfPkg/XenBusDxe/XenStore.h | 21 +++++++++++++++++++ 6 files changed, 121 insertions(+), 4 deletions(-) diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h index c22bdfb368..04986747c8 100644 --- a/OvmfPkg/Include/Protocol/XenBus.h +++ b/OvmfPkg/Include/Protocol/XenBus.h @@ -373,6 +373,38 @@ XENSTORE_STATUS IN VOID *Token ); +typedef +VOID +(EFIAPI *XENBUS_EXIT_CALLBACK)( + IN VOID *Context + ); + +/** + Register a function to be called during the ExitBootServices event. + + NotifyFunction will be called when XenBusDxe is notified of + EVT_SIGNAL_EXIT_BOOT_SERVICES. The function should follow the same + requirements as if it as registered an event on + EVT_SIGNAL_EXIT_BOOT_SERVICES, i.e. no use of the Memory Allocation + Services. + + To unregister the function, call RegisterExitCallback with + NotifyFunction=NULL. + + @note There can only be one callback per driver. + + @param This A pointer to the XENBUS_PROTOCOL. + @param NotifyFunction The function to be called. + @param NotifyContext A context. +**/ +typedef +VOID +(EFIAPI *XENBUS_SET_EXIT_CALLBACK) ( + IN XENBUS_PROTOCOL *This, + IN XENBUS_EXIT_CALLBACK NotifyFunction, + IN VOID *NotifyContext + ); + /// /// Protocol structure @@ -400,6 +432,9 @@ struct _XENBUS_PROTOCOL { XENBUS_REGISTER_WATCH_BACKEND RegisterWatchBackend; XENBUS_UNREGISTER_WATCH UnregisterWatch; XENBUS_WAIT_FOR_WATCH WaitForWatch; + + XENBUS_SET_EXIT_CALLBACK RegisterExitCallback; + // // Protocol data fields // diff --git a/OvmfPkg/XenBusDxe/XenBus.c b/OvmfPkg/XenBusDxe/XenBus.c index 78835ec7b3..54166505d2 100644 --- a/OvmfPkg/XenBusDxe/XenBus.c +++ b/OvmfPkg/XenBusDxe/XenBus.c @@ -343,6 +343,23 @@ XenBusSetState ( return Status; } +STATIC +VOID +EFIAPI +XenBusRegisterExitCallback ( + IN XENBUS_PROTOCOL *This, + IN XENBUS_EXIT_CALLBACK NotifyFunction, + IN VOID *NotifyContext + ) +{ + XENBUS_PRIVATE_DATA *Dev; + + Dev = XENBUS_PRIVATE_DATA_FROM_THIS (This); + + Dev->ExitCallback = NotifyFunction; + Dev->ExitCallbackContext = NotifyContext; +} + STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = { XENBUS_PRIVATE_DATA_SIGNATURE, // Signature { NULL, NULL }, // Link @@ -364,6 +381,7 @@ STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = { XenBusRegisterWatchBackend, // XenBusIo.RegisterWatchBackend XenBusUnregisterWatch, // XenBusIo.UnregisterWatch XenBusWaitForWatch, // XenBusIo.WaitForWatch + XenBusRegisterExitCallback, // XenBusIo.RegisterExitCallback NULL, // XenBusIo.Type 0, // XenBusIo.DeviceId diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c index 634c7b71eb..c71966a666 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.c +++ b/OvmfPkg/XenBusDxe/XenBusDxe.c @@ -258,10 +258,31 @@ NotifyExitBoot ( IN VOID *Context ) { - XENBUS_DEVICE *Dev = Context; + XENBUS_DEVICE *Dev; + LIST_ENTRY *Entry; + XENBUS_PRIVATE_DATA *Child; - gBS->DisconnectController(Dev->ControllerHandle, - Dev->This->DriverBindingHandle, NULL); + Dev = Context; + + // + // First, ask every driver using xenbus to disconnect without + // deallocating memory. + // + for (Entry = GetFirstNode (&Dev->ChildList); + !IsNodeAtEnd (&Dev->ChildList, Entry); + Entry = GetNextNode (&Dev->ChildList, Entry)) { + Child = XENBUS_PRIVATE_DATA_FROM_LINK (Entry); + if (Child->ExitCallback != NULL) { + Child->ExitCallback (Child->ExitCallbackContext); + } + } + + // + // Now, we can reset the devices used by XenBusDxe. + // + XenStoreResetWatches (); + XenStoreResetRing (Dev); + XenGrantTableDeinit (Dev); } /** diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h index b1dcc3549c..0e91c24338 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.h +++ b/OvmfPkg/XenBusDxe/XenBusDxe.h @@ -94,6 +94,8 @@ typedef struct { XENBUS_PROTOCOL XenBusIo; XENBUS_DEVICE *Dev; XENBUS_DEVICE_PATH *DevicePath; + XENBUS_EXIT_CALLBACK ExitCallback; + VOID *ExitCallbackContext; } XENBUS_PRIVATE_DATA; #define XENBUS_PRIVATE_DATA_FROM_THIS(a) \ diff --git a/OvmfPkg/XenBusDxe/XenStore.c b/OvmfPkg/XenBusDxe/XenStore.c index cb2d9e1215..4026c8a829 100644 --- a/OvmfPkg/XenBusDxe/XenStore.c +++ b/OvmfPkg/XenBusDxe/XenStore.c @@ -1054,8 +1054,18 @@ XenStoreDeinit ( } } + XenStoreResetRing (Dev); + gBS->CloseEvent (xs.EventChannelEvent); + xs.XenStore = NULL; +} + +VOID +XenStoreResetRing ( + IN XENBUS_DEVICE *Dev + ) +{ if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) { xs.XenStore->connection = XENSTORE_RECONNECT; XenEventChannelNotify (xs.Dev, xs.EventChannel); @@ -1072,7 +1082,17 @@ XenStoreDeinit ( xs.XenStore->req_cons = xs.XenStore->req_prod = 0; xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0; } - xs.XenStore = NULL; +} + +VOID +XenStoreResetWatches ( + VOID + ) +{ + XENSTORE_STATUS Status; + + Status = XenStoreSingle (XST_NIL, XS_RESET_WATCHES, "", NULL, NULL, NULL); + ASSERT (Status == XENSTORE_STATUS_SUCCESS); } // diff --git a/OvmfPkg/XenBusDxe/XenStore.h b/OvmfPkg/XenBusDxe/XenStore.h index ca8c080433..62cd5e97bf 100644 --- a/OvmfPkg/XenBusDxe/XenStore.h +++ b/OvmfPkg/XenBusDxe/XenStore.h @@ -271,6 +271,27 @@ XenStoreDeinit ( IN XENBUS_DEVICE *Dev ); +/** + Effectively reset all watches registered with xenstore. + + To be used by ExitBootServices +**/ +VOID +XenStoreResetWatches ( + VOID + ); + +/** + Reset the xenstore shared ring before handing it over to the next + operating system. + + To be used by ExitBootServices +**/ +VOID +XenStoreResetRing ( + IN XENBUS_DEVICE *Dev + ); + // // XENBUS protocol