From nobody Sat May 11 03:31:48 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=bytedance.com ARC-Seal: i=1; a=rsa-sha256; t=1602671910; cv=none; d=zohomail.com; s=zohoarc; b=XbAFqxWZ1FBHvRYbCAkgBbVsDX05OIn3q33RYcYkwTKiiBIlKvNwG/cWLndcff5nO6SE6d99tnXkm5/wYWqXcNl4ogwiBBLv1aevQL0nBIdUiEs2MtloSNwri1zk6B1RHrP5VbRoEiDFkS2COW147OGKWy4PTkYPQnv6mGdQOJY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1602671910; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=waQsC64HtRGR/xLdI6HWWCV9zu5cZt4a++VwajLR4QM=; b=VJdmEq8OGUGnZDzPfNjnljiBeqt1J+N32BTETFXgfhOjVDF3cmBpRM6EgxTi9kFig6aNMLTLCw1yxTyVm8rWdiLnw+sEzKthOWq8o59NwQ5MhIiLiEalidw5P8cG6Rn1jiXW1ea337XelS/VgKDQhwYN9mLeQXk2aTJK5sj45/0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 160267191058178.2832990265191; Wed, 14 Oct 2020 03:38:30 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-375-I7EFQYPMO3Kc9Scwqt86Ng-1; Wed, 14 Oct 2020 06:38:26 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2106F803657; Wed, 14 Oct 2020 10:38:21 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id B87FD19D7C; Wed, 14 Oct 2020 10:38:20 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id CF4AD58133; Wed, 14 Oct 2020 10:38:18 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 09EAcGqE006223 for ; Wed, 14 Oct 2020 06:38:16 -0400 Received: by smtp.corp.redhat.com (Postfix) id 1A772117541F; Wed, 14 Oct 2020 10:38:16 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast05.extmail.prod.ext.rdu2.redhat.com [10.11.55.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 164C9117541D for ; Wed, 14 Oct 2020 10:38:16 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DAE1080D623 for ; Wed, 14 Oct 2020 10:38:15 +0000 (UTC) Received: from mail-pg1-f196.google.com (mail-pg1-f196.google.com [209.85.215.196]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-228-yLjxPcu5NfiEvfjivR9eaw-1; Wed, 14 Oct 2020 06:38:12 -0400 Received: by mail-pg1-f196.google.com with SMTP id y14so1674370pgf.12 for ; Wed, 14 Oct 2020 03:38:12 -0700 (PDT) Received: from libai.bytedance.net ([61.120.150.71]) by smtp.gmail.com with ESMTPSA id v21sm3138659pgl.39.2020.10.14.03.38.07 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Oct 2020 03:38:10 -0700 (PDT) X-MC-Unique: I7EFQYPMO3Kc9Scwqt86Ng-1 X-MC-Unique: yLjxPcu5NfiEvfjivR9eaw-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=waQsC64HtRGR/xLdI6HWWCV9zu5cZt4a++VwajLR4QM=; b=doPhLJpgA3i6q4zDcs3t9e3GNWARthgwu/sQGy2LhDVzwU2YaTJogja8Pp53khMmcN snY/XGaw9kghtWVaILqn0rbChuYGj3qHun3u8oNnGGxXtjdcb9xsrEqJ9P21MNVxL+2h LxO+e4TnZzpnYW2glfO5ov/+NykCHN1aYAOMqmRoxETzCwmajSsF6+ofwR37Z7M8Fqlj 0AODNLRTeJZ/a4RU9ib3hMD3Vd1ALkNMab6/mRWc+qvBvzT9g/FXQEZ3YJlnX8d6mrUy PuID/8/W7ip2EFY21L3FXZy5hWsBCDiUwKMLY04FJFKuYZs3wRva/0UqgIiFBBWQ9cQC +aSA== X-Gm-Message-State: AOAM532MhDIYb4HM23h1SAiogC9GgSLKwg/iq21C4Zh9EIVWj1/l5l/Z JiKfn8m7z0qWzS0QbO+HV/LbKA== X-Google-Smtp-Source: ABdhPJwGo1r6HWMf2H7eT6IliA4+NG0Irv+nqVg7/et1RqPiS1FzQ0AKyVKyba/0+NaQ7KUcTriikQ== X-Received: by 2002:a63:f502:: with SMTP id w2mr3269889pgh.186.1602671891316; Wed, 14 Oct 2020 03:38:11 -0700 (PDT) From: zhenwei pi To: berrange@redhat.com, pkrempa@redhat.com, mprivozn@redhat.com Subject: [PATCH v3 1/2] libvirt: support memory failure event Date: Wed, 14 Oct 2020 18:37:50 +0800 Message-Id: <20201014103751.1046577-2-pizhenwei@bytedance.com> In-Reply-To: <20201014103751.1046577-1-pizhenwei@bytedance.com> References: <20201014103751.1046577-1-pizhenwei@bytedance.com> X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-loop: libvir-list@redhat.com Cc: libvir-list@redhat.com, danielhb413@gmail.com, pizhenwei@bytedance.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 2 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Introduce memory failure event. Libvirt should monitor domain's event, then posts it to uplayer. According to the hardware memory corrupted message, a cloud scheduler could migrate domain to another health physical server. Several changes in this patch: public API: include/* src/conf/* src/remote/* src/remote_protocol-structs client: examples/c/misc/event-test.c tools/virsh-domain.c With this patch, each driver could implement its own method to run this new event. Signed-off-by: zhenwei pi --- include/libvirt/libvirt-domain.h | 82 +++++++++++++++++++++++++++++++++= ++++ src/conf/domain_event.c | 80 +++++++++++++++++++++++++++++++++= +++ src/conf/domain_event.h | 12 ++++++ src/libvirt_private.syms | 2 + src/remote/remote_daemon_dispatch.c | 32 +++++++++++++++ src/remote/remote_driver.c | 32 +++++++++++++++ src/remote/remote_protocol.x | 16 +++++++- src/remote_protocol-structs | 8 ++++ examples/c/misc/event-test.c | 16 ++++++++ tools/virsh-domain.c | 40 ++++++++++++++++++ 10 files changed, 319 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-dom= ain.h index 77f9116675..5138843a56 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3196,6 +3196,64 @@ typedef enum { } virDomainEventCrashedDetailType; =20 /** + * virDomainMemoryFailureRecipientType: + * + * Recipient of a memory failure event. + */ +typedef enum { + /* memory failure at hypersivor memory address space */ + VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_HYPERVISOR =3D 0, + + /* memory failure at guest memory address space */ + VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_GUEST =3D 1, + +# ifdef VIR_ENUM_SENTINELS + VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_LAST +# endif +} virDomainMemoryFailureRecipientType; + + +/** + * virDomainMemoryFailureActionType: + * + * Action of a memory failure event. + */ +typedef enum { + /* the memory failure could be ignored. This will only be the case for + * action-optional failures. */ + VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_IGNORE =3D 0, + + /* memory failure occurred in guest memory, the guest enabled MCE hand= ling + * mechanism, and hypervisor could inject the MCE into the guest + * successfully. */ + VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_INJECT =3D 1, + + /* the failure is unrecoverable. This occurs for action-required fail= ures + * if the recipient is the hypervisor; hypervisor will exit. */ + VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_FATAL =3D 2, + + /* the failure is unrecoverable but confined to the guest. This occurs= if + * the recipient is a guest which is not ready to handle memory failur= es. */ + VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_RESET =3D 3, + +# ifdef VIR_ENUM_SENTINELS + VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_LAST +# endif +} virDomainMemoryFailureActionType; + + +typedef enum { + /* whether a memory failure event is action-required or action-optional + * (e.g. a failure during memory scrub). */ + VIR_DOMAIN_MEMORY_FAILURE_ACTION_REQUIRED =3D (1 << 0), + + /* whether the failure occurred while the previous failure was still in + * progress. */ + VIR_DOMAIN_MEMORY_FAILURE_RECURSIVE =3D (1 << 1), +} virDomainMemoryFailureFlags; + + +/** * virConnectDomainEventCallback: * @conn: virConnect connection * @dom: The domain on which the event occurred @@ -4565,6 +4623,29 @@ typedef void (*virConnectDomainEventBlockThresholdCa= llback)(virConnectPtr conn, void *opaque); =20 /** + * virConnectDomainEventMemoryFailureCallback: + * @conn: connection object + * @dom: domain on which the event occurred + * @recipient: the recipient of hardware memory failure + * @action: the action of hardware memory failure + * @flags: the flags of hardware memory failure + * @opaque: application specified data + * + * The callback occurs when the hypervisor handles the hardware memory + * corrupted event. + * + * The callback signature to use when registering for an event of type + * VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE with virConnectDomainEventRegisterAn= y() + */ +typedef void (*virConnectDomainEventMemoryFailureCallback)(virConnectPtr c= onn, + virDomainPtr do= m, + virDomainMemory= FailureRecipientType recipient, + virDomainMemory= FailureActionType action, + unsigned int fl= ags, + void *opaque); + + +/** * VIR_DOMAIN_EVENT_CALLBACK: * * Used to cast the event specific callback into the generic one @@ -4606,6 +4687,7 @@ typedef enum { VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED =3D 22, /* virConnectDomainE= ventDeviceRemovalFailedCallback */ VIR_DOMAIN_EVENT_ID_METADATA_CHANGE =3D 23, /* virConnectDomainEventMe= tadataChangeCallback */ VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD =3D 24, /* virConnectDomainEventBl= ockThresholdCallback */ + VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE =3D 25, /* virConnectDomainEventMe= moryFailureCallback */ =20 # ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_ID_LAST diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index a8bd9f1595..4a6051a6ab 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -57,6 +57,7 @@ static virClassPtr virDomainEventJobCompletedClass; static virClassPtr virDomainEventDeviceRemovalFailedClass; static virClassPtr virDomainEventMetadataChangeClass; static virClassPtr virDomainEventBlockThresholdClass; +static virClassPtr virDomainEventMemoryFailureClass; =20 static void virDomainEventDispose(void *obj); static void virDomainEventLifecycleDispose(void *obj); @@ -79,6 +80,7 @@ static void virDomainEventJobCompletedDispose(void *obj); static void virDomainEventDeviceRemovalFailedDispose(void *obj); static void virDomainEventMetadataChangeDispose(void *obj); static void virDomainEventBlockThresholdDispose(void *obj); +static void virDomainEventMemoryFailureDispose(void *obj); =20 static void virDomainEventDispatchDefaultFunc(virConnectPtr conn, @@ -287,6 +289,15 @@ struct _virDomainEventBlockThreshold { typedef struct _virDomainEventBlockThreshold virDomainEventBlockThreshold; typedef virDomainEventBlockThreshold *virDomainEventBlockThresholdPtr; =20 +struct _virDomainEventMemoryFailure { + virDomainEvent parent; + + virDomainMemoryFailureRecipientType recipient; + virDomainMemoryFailureActionType action; + unsigned int flags; +}; +typedef struct _virDomainEventMemoryFailure virDomainEventMemoryFailure; +typedef virDomainEventMemoryFailure *virDomainEventMemoryFailurePtr; =20 static int virDomainEventsOnceInit(void) @@ -333,6 +344,8 @@ virDomainEventsOnceInit(void) return -1; if (!VIR_CLASS_NEW(virDomainEventBlockThreshold, virDomainEventClass)) return -1; + if (!VIR_CLASS_NEW(virDomainEventMemoryFailure, virDomainEventClass)) + return -1; return 0; } =20 @@ -542,6 +555,14 @@ virDomainEventBlockThresholdDispose(void *obj) } =20 =20 +static void +virDomainEventMemoryFailureDispose(void *obj) +{ + virDomainEventMemoryFailurePtr event =3D obj; + VIR_DEBUG("obj=3D%p", event); +} + + static void * virDomainEventNew(virClassPtr klass, int eventID, @@ -1619,6 +1640,52 @@ virDomainEventBlockThresholdNewFromDom(virDomainPtr = dom, } =20 =20 +static virObjectEventPtr +virDomainEventMemoryFailureNew(int id, + const char *name, + unsigned char *uuid, + virDomainMemoryFailureRecipientType recipie= nt, + virDomainMemoryFailureActionType action, + unsigned int flags) +{ + virDomainEventMemoryFailurePtr ev; + + if (virDomainEventsInitialize() < 0) + return NULL; + + if (!(ev =3D virDomainEventNew(virDomainEventMemoryFailureClass, + VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE, + id, name, uuid))) + return NULL; + + ev->recipient =3D recipient; + ev->action =3D action; + ev->flags =3D flags; + + return (virObjectEventPtr)ev; +} + +virObjectEventPtr +virDomainEventMemoryFailureNewFromObj(virDomainObjPtr obj, + virDomainMemoryFailureRecipientType = recipient, + virDomainMemoryFailureActionType act= ion, + unsigned int flags) +{ + return virDomainEventMemoryFailureNew(obj->def->id, obj->def->name, + obj->def->uuid, recipient, actio= n, + flags); +} + +virObjectEventPtr +virDomainEventMemoryFailureNewFromDom(virDomainPtr dom, + virDomainMemoryFailureRecipientType = recipient, + virDomainMemoryFailureActionType act= ion, + unsigned int flags) +{ + return virDomainEventMemoryFailureNew(dom->id, dom->name, dom->uuid, + recipient, action, flags); +} + static void virDomainEventDispatchDefaultFunc(virConnectPtr conn, virObjectEventPtr event, @@ -1902,6 +1969,19 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn, cbopaque); goto cleanup; } + case VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE: + { + virDomainEventMemoryFailurePtr memoryFailureEvent; + + memoryFailureEvent =3D (virDomainEventMemoryFailurePtr)event; + ((virConnectDomainEventMemoryFailureCallback)cb)(conn, dom, + memoryFailure= Event->recipient, + memoryFailure= Event->action, + memoryFailure= Event->flags, + cbopaque); + goto cleanup; + } + case VIR_DOMAIN_EVENT_ID_LAST: break; } diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index d1cfb81d62..1d001e164e 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -255,6 +255,18 @@ virDomainEventBlockThresholdNewFromDom(virDomainPtr do= m, unsigned long long threshold, unsigned long long excess); =20 +virObjectEventPtr +virDomainEventMemoryFailureNewFromObj(virDomainObjPtr obj, + virDomainMemoryFailureRecipientType = recipient, + virDomainMemoryFailureActionType act= ion, + unsigned int flags); + +virObjectEventPtr +virDomainEventMemoryFailureNewFromDom(virDomainPtr dom, + virDomainMemoryFailureRecipientType = recipient, + virDomainMemoryFailureActionType act= ion, + unsigned int flags); + int virDomainEventStateRegister(virConnectPtr conn, virObjectEventStatePtr state, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 52e9c6313f..ca43d1c199 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -705,6 +705,8 @@ virDomainEventLifecycleNew; virDomainEventLifecycleNewFromDef; virDomainEventLifecycleNewFromDom; virDomainEventLifecycleNewFromObj; +virDomainEventMemoryFailureNewFromDom; +virDomainEventMemoryFailureNewFromObj; virDomainEventMetadataChangeNewFromDom; virDomainEventMetadataChangeNewFromObj; virDomainEventMigrationIterationNewFromDom; diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon= _dispatch.c index 32ebcd8f36..078467f8da 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -1302,6 +1302,37 @@ remoteRelayDomainEventBlockThreshold(virConnectPtr c= onn, } =20 =20 +static int +remoteRelayDomainEventMemoryFailure(virConnectPtr conn, + virDomainPtr dom, + virDomainMemoryFailureRecipientType re= cipient, + virDomainMemoryFailureActionType actio= n, + unsigned int flags, + void *opaque) +{ + daemonClientEventCallbackPtr callback =3D opaque; + remote_domain_event_memory_failure_msg data; + + if (callback->callbackID < 0 || + !remoteRelayDomainEventCheckACL(callback->client, conn, dom)) + return -1; + + /* build return data */ + memset(&data, 0, sizeof(data)); + data.callbackID =3D callback->callbackID; + data.recipient =3D recipient; + data.action =3D action; + data.flags =3D flags; + make_nonnull_domain(&data.dom, dom); + + remoteDispatchObjectEventSend(callback->client, remoteProgram, + REMOTE_PROC_DOMAIN_EVENT_MEMORY_FAILURE, + (xdrproc_t)xdr_remote_domain_event_memor= y_failure_msg, &data); + + return 0; +} + + static virConnectDomainEventGenericCallback domainEventCallbacks[] =3D { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), @@ -1328,6 +1359,7 @@ static virConnectDomainEventGenericCallback domainEve= ntCallbacks[] =3D { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold), + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryFailure), }; =20 G_STATIC_ASSERT(G_N_ELEMENTS(domainEventCallbacks) =3D=3D VIR_DOMAIN_EVENT= _ID_LAST); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d318224605..9cd2fd36ae 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -405,6 +405,11 @@ remoteDomainBuildEventBlockThreshold(virNetClientProgr= amPtr prog, void *evdata, void *opaque); =20 static void +remoteDomainBuildEventMemoryFailure(virNetClientProgramPtr prog, + virNetClientPtr client, + void *evdata, void *opaque); + +static void remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog G_GNU= C_UNUSED, virNetClientPtr client G_GNUC_UNU= SED, void *evdata, void *opaque); @@ -615,6 +620,10 @@ static virNetClientProgramEvent remoteEvents[] =3D { remoteDomainBuildEventBlockThreshold, sizeof(remote_domain_event_block_threshold_msg), (xdrproc_t)xdr_remote_domain_event_block_threshold_msg }, + { REMOTE_PROC_DOMAIN_EVENT_MEMORY_FAILURE, + remoteDomainBuildEventMemoryFailure, + sizeof(remote_domain_event_memory_failure_msg), + (xdrproc_t)xdr_remote_domain_event_memory_failure_msg }, }; =20 static void @@ -5440,6 +5449,29 @@ remoteDomainBuildEventBlockThreshold(virNetClientPro= gramPtr prog G_GNUC_UNUSED, } =20 =20 +static void +remoteDomainBuildEventMemoryFailure(virNetClientProgramPtr prog G_GNUC_UNU= SED, + virNetClientPtr client G_GNUC_UNUSED, + void *evdata, void *opaque) +{ + virConnectPtr conn =3D opaque; + remote_domain_event_memory_failure_msg *msg =3D evdata; + struct private_data *priv =3D conn->privateData; + virDomainPtr dom; + virObjectEventPtr event =3D NULL; + + if (!(dom =3D get_nonnull_domain(conn, msg->dom))) + return; + + event =3D virDomainEventMemoryFailureNewFromDom(dom, msg->recipient, + msg->action, msg->flags); + + virObjectUnref(dom); + + virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackI= D); +} + + static int remoteStreamSend(virStreamPtr st, const char *data, diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f4d6147676..5e5e781e76 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3469,6 +3469,14 @@ struct remote_domain_event_callback_metadata_change_= msg { remote_string nsuri; }; =20 +struct remote_domain_event_memory_failure_msg { + int callbackID; + remote_nonnull_domain dom; + int recipient; + int action; + unsigned int flags; +}; + struct remote_connect_secret_event_register_any_args { int eventID; remote_secret secret; @@ -6668,5 +6676,11 @@ enum remote_procedure { * @priority: high * @acl: domain:read */ - REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC =3D 422 + REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC =3D 422, + + /** + * @generate: both + * @acl: none + */ + REMOTE_PROC_DOMAIN_EVENT_MEMORY_FAILURE =3D 423 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index bae0f0b545..c2ae411885 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2862,6 +2862,13 @@ struct remote_domain_event_callback_metadata_change_= msg { int type; remote_string nsuri; }; +struct remote_domain_event_memory_failure_msg { + int callbackID; + remote_nonnull_domain dom; + int recipient; + int action; + u_int flags; +}; struct remote_connect_secret_event_register_any_args { int eventID; remote_secret secret; @@ -3558,4 +3565,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_AGENT_SET_RESPONSE_TIMEOUT =3D 420, REMOTE_PROC_DOMAIN_BACKUP_BEGIN =3D 421, REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC =3D 422, + REMOTE_PROC_DOMAIN_EVENT_MEMORY_FAILURE =3D 423, }; diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c index 52caa8ffa8..1651efe019 100644 --- a/examples/c/misc/event-test.c +++ b/examples/c/misc/event-test.c @@ -964,6 +964,21 @@ myDomainEventBlockThresholdCallback(virConnectPtr conn= G_GNUC_UNUSED, =20 =20 static int +myDomainEventMemoryFailureCallback(virConnectPtr conn G_GNUC_UNUSED, + virDomainPtr dom, + virDomainMemoryFailureRecipientType rec= ipient, + virDomainMemoryFailureActionType action, + unsigned int flags, + void *opaque G_GNUC_UNUSED) +{ + printf("%s EVENT: Domain %s(%d) memory failure: recipient '%d', " + "aciont '%d', flags '%d'", __func__, virDomainGetName(dom), + virDomainGetID(dom), recipient, action, flags); + return 0; +} + + +static int myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED, virDomainPtr dom, int iteration, @@ -1093,6 +1108,7 @@ struct domainEventData domainEvents[] =3D { DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventD= eviceRemovalFailedCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadat= aChangeCallback), DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockTh= resholdCallback), + DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE, myDomainEventMemoryFa= ilureCallback), }; =20 struct storagePoolEventData { diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 8f11393197..2bfb33e528 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -13590,6 +13590,44 @@ virshEventBlockThresholdPrint(virConnectPtr conn G= _GNUC_UNUSED, } =20 =20 +VIR_ENUM_DECL(virshEventMemoryFailureRecipientType); +VIR_ENUM_IMPL(virshEventMemoryFailureRecipientType, + VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_LAST, + N_("hypervisor"), + N_("guest")); + +VIR_ENUM_DECL(virshEventMemoryFailureActionType); +VIR_ENUM_IMPL(virshEventMemoryFailureActionType, + VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_LAST, + N_("ignore"), + N_("inject"), + N_("fatal"), + N_("reset")); + +static void +virshEventMemoryFailurePrint(virConnectPtr conn G_GNUC_UNUSED, + virDomainPtr dom, + virDomainMemoryFailureRecipientType recipient, + virDomainMemoryFailureActionType action, + unsigned int flags, + void *opaque) +{ + g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; + + virBufferAsprintf(&buf, _("event 'memory-failure' for domain %s:\n" + "recipient: %s\naction: %s\n"), + virDomainGetName(dom), + UNKNOWNSTR(virshEventMemoryFailureRecipientTypeTypeT= oString(recipient)), + UNKNOWNSTR(virshEventMemoryFailureActionTypeTypeToSt= ring(action))); + virBufferAsprintf(&buf, _("flags:\n" + "\taction required: %d\n\trecursive: %d\n"), + !!(flags & VIR_DOMAIN_MEMORY_FAILURE_ACTION_REQUIRED= ), + !!(flags & VIR_DOMAIN_MEMORY_FAILURE_RECURSIVE)); + + virshEventPrint(opaque, &buf); +} + + virshDomainEventCallback virshDomainEventCallbacks[] =3D { { "lifecycle", VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), }, @@ -13639,6 +13677,8 @@ virshDomainEventCallback virshDomainEventCallbacks[= ] =3D { VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), }, { "block-threshold", VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), }, + { "memory-failure", + VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryFailurePrint), }, }; G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST =3D=3D G_N_ELEMENTS(virshDomainEv= entCallbacks)); =20 --=20 2.11.0 From nobody Sat May 11 03:31:48 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=bytedance.com ARC-Seal: i=1; a=rsa-sha256; t=1602671918; cv=none; d=zohomail.com; s=zohoarc; b=LijM4YKbUoItKM0wKwAual1qgZQu+YrgtYKi/2cSuOjsncVUCtEoTSv9K7a1YjHuAYrr8XxBwdiVw33xqBuSHA1g9OZSfhh3gU9w9jYf1Jzef3GLL5ZoCNKz0hstlCC5si8860xr7b+xQvOWvr5L131JW+MYbnA0J6uhm0V7I3k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1602671918; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=zVTjMQ9FfyPHS7Mwd1LrC34dQoITgwm1vFy7A+7GGWk=; b=XJmvI8vv7HAzZbrv0GzAzDWKORriq0G/syS1E2sPvHzwJls67B+26G7hLFlMUA7+Yw5K3OJmXyZWtEBbTOekTXeurD5RQ4iHq/UPf4O9QdBGNo/9FARrjf9xJhhbU6uL8gI/3Wq18ng6sVdj+aMQqX/ejdKAIx8YLhKexRwH474= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1602671918603411.1881426181519; Wed, 14 Oct 2020 03:38:38 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-188-ocGC6qOqMjm1pszYt79XAQ-1; Wed, 14 Oct 2020 06:38:35 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E6A73107466C; Wed, 14 Oct 2020 10:38:29 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BB44710002A4; Wed, 14 Oct 2020 10:38:29 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 81B9E5813D; Wed, 14 Oct 2020 10:38:29 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 09EAcNVd006254 for ; Wed, 14 Oct 2020 06:38:23 -0400 Received: by smtp.corp.redhat.com (Postfix) id 417392157F49; Wed, 14 Oct 2020 10:38:23 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast04.extmail.prod.ext.rdu2.redhat.com [10.11.55.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 36F3B2157F24 for ; Wed, 14 Oct 2020 10:38:19 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 56F48102F1E0 for ; Wed, 14 Oct 2020 10:38:19 +0000 (UTC) Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-429-H2T0FLjfPNeO9OObV6_wKw-1; Wed, 14 Oct 2020 06:38:16 -0400 Received: by mail-pl1-f182.google.com with SMTP id o8so1542522pll.4 for ; Wed, 14 Oct 2020 03:38:16 -0700 (PDT) Received: from libai.bytedance.net ([61.120.150.71]) by smtp.gmail.com with ESMTPSA id v21sm3138659pgl.39.2020.10.14.03.38.11 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Oct 2020 03:38:15 -0700 (PDT) X-MC-Unique: ocGC6qOqMjm1pszYt79XAQ-1 X-MC-Unique: H2T0FLjfPNeO9OObV6_wKw-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zVTjMQ9FfyPHS7Mwd1LrC34dQoITgwm1vFy7A+7GGWk=; b=iRWWGjQQd9+yBMTbcyPCVSQsH1ZOu4tMvL/YPMWg+kOW52oXlKLJWpf9pd5AwXjqg+ EL2iDzFJmn10VhgkOtXEEtaMJWdzrpuOm2ue/P+5Dc0SHp2LwMIAuWjwFD/qmg9c0NPB wte2f4CnkGvMZ8JUsbJLj2mjleECFncWSGP3PZkQf0KP4iVG4Pjffnu1OdhaDVPM3YEa apfsEiEnTqhUNGkBkonV75arKPrR+NiDzppvoQc3gvsk4OKSnRYXIF6aqJky/ShPI3Ca wffj7XQ41zpQTH62sb6p4Tk4Pj0rTh+CZ4O8irHEToYCqix5pw/gadrmxvL4KTAQeUVU +nvA== X-Gm-Message-State: AOAM530h8pSyKjGebf+V8DOlwzA0YsgiD+TDcysaCTZdc6vA45tKrwg0 D9tfGLBO8bK6tmfudxSsjPT0fQ== X-Google-Smtp-Source: ABdhPJyAtsAiGWJL3maQIvEJWqPOrYYMwFJAtJQS326a5OojDkAuGxfr30SQxnaBVi/53cFwDShJSQ== X-Received: by 2002:a17:90a:e00f:: with SMTP id u15mr2996083pjy.87.1602671895733; Wed, 14 Oct 2020 03:38:15 -0700 (PDT) From: zhenwei pi To: berrange@redhat.com, pkrempa@redhat.com, mprivozn@redhat.com Subject: [PATCH v3 2/2] qemu: implement memory failure event Date: Wed, 14 Oct 2020 18:37:51 +0800 Message-Id: <20201014103751.1046577-3-pizhenwei@bytedance.com> In-Reply-To: <20201014103751.1046577-1-pizhenwei@bytedance.com> References: <20201014103751.1046577-1-pizhenwei@bytedance.com> X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-loop: libvir-list@redhat.com Cc: libvir-list@redhat.com, danielhb413@gmail.com, pizhenwei@bytedance.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 2 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Since QEMU 5.2 (commit-77b285f7f6), QEMU supports 'memory failure' event, posts event to monitor if hitting a hardware memory error. Fully support this feature for QEMU. Test with commit 'libvirt: support memory failure event', build a little complex environment(nested KVM): 1, install newly built libvirt in L1, and start a L2 vm. run command in L1: ~# virsh event l2 --event memory-failure 2, run command in L0 to inject MCE to L1: ~# virsh qemu-monitor-command l1 --hmp mce 0 9 0xbd000000000000c0 0xd 0x62= 000000 0x8c Test result in l1(recipient hypervisor case): event 'memory-failure' for domain l2: recipient: hypervisor action: ignore flags: action required: 0 recursive: 0 Test result in l1(recipient guest case): event 'memory-failure' for domain l2: recipient: guest action: inject flags: action required: 0 recursive: 0 Signed-off-by: zhenwei pi --- src/qemu/qemu_monitor.c | 21 +++++++++++++++- src/qemu/qemu_monitor.h | 39 +++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.c | 49 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_process.c | 59 ++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 167 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 8c991fefbb..189b789bb8 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -159,7 +159,6 @@ static int qemuMonitorOnceInit(void) =20 VIR_ONCE_GLOBAL_INIT(qemuMonitor); =20 - VIR_ENUM_IMPL(qemuMonitorMigrationStatus, QEMU_MONITOR_MIGRATION_STATUS_LAST, "inactive", "setup", @@ -197,6 +196,14 @@ VIR_ENUM_IMPL(qemuMonitorDumpStatus, "none", "active", "completed", "failed", ); =20 +VIR_ENUM_IMPL(qemuMonitorMemoryFailureRecipient, + QEMU_MONITOR_MEMORY_FAILURE_RECIPIENT_LAST, + "hypervisor", "guest"); + +VIR_ENUM_IMPL(qemuMonitorMemoryFailureAction, + QEMU_MONITOR_MEMORY_FAILURE_ACTION_LAST, + "ignore", "inject", + "fatal", "reset"); =20 #if DEBUG_RAW_IO static char * @@ -1428,6 +1435,18 @@ qemuMonitorEmitSpiceMigrated(qemuMonitorPtr mon) =20 =20 int +qemuMonitorEmitMemoryFailure(qemuMonitorPtr mon, + qemuMonitorEventMemoryFailurePtr mfp) +{ + int ret =3D -1; + + QEMU_MONITOR_CALLBACK(mon, ret, domainMemoryFailure, mon->vm, mfp); + + return ret; +} + + +int qemuMonitorEmitMigrationStatus(qemuMonitorPtr mon, int status) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a744c8975b..17ba006a2f 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -340,6 +340,40 @@ typedef int (*qemuMonitorDomainGuestCrashloadedCallbac= k)(qemuMonitorPtr mon, virDomainObjPtr v= m, void *opaque); =20 +typedef enum { + QEMU_MONITOR_MEMORY_FAILURE_RECIPIENT_HYPERVISOR, + QEMU_MONITOR_MEMORY_FAILURE_RECIPIENT_GUEST, + + QEMU_MONITOR_MEMORY_FAILURE_RECIPIENT_LAST +} qemuMonitorMemoryFailureRecipient; + +VIR_ENUM_DECL(qemuMonitorMemoryFailureRecipient); + +typedef enum { + QEMU_MONITOR_MEMORY_FAILURE_ACTION_IGNORE, + QEMU_MONITOR_MEMORY_FAILURE_ACTION_INJECT, + QEMU_MONITOR_MEMORY_FAILURE_ACTION_FATAL, + QEMU_MONITOR_MEMORY_FAILURE_ACTION_RESET, + + QEMU_MONITOR_MEMORY_FAILURE_ACTION_LAST +} qemuMonitorMemoryFailureAction; + +VIR_ENUM_DECL(qemuMonitorMemoryFailureAction); + +typedef struct _qemuMonitorEventMemoryFailure qemuMonitorEventMemoryFailur= e; +typedef qemuMonitorEventMemoryFailure *qemuMonitorEventMemoryFailurePtr; +struct _qemuMonitorEventMemoryFailure { + qemuMonitorMemoryFailureRecipient recipient; + qemuMonitorMemoryFailureAction action; + bool action_required; + bool recursive; +}; + +typedef int (*qemuMonitorDomainMemoryFailureCallback)(qemuMonitorPtr mon, + virDomainObjPtr vm, + qemuMonitorEventMemo= ryFailurePtr mfp, + void *opaque); + typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks; typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr; struct _qemuMonitorCallbacks { @@ -376,6 +410,7 @@ struct _qemuMonitorCallbacks { qemuMonitorDomainPRManagerStatusChangedCallback domainPRManagerStatusC= hanged; qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChang= ed; qemuMonitorDomainGuestCrashloadedCallback domainGuestCrashloaded; + qemuMonitorDomainMemoryFailureCallback domainMemoryFailure; }; =20 qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm, @@ -475,6 +510,10 @@ int qemuMonitorEmitSerialChange(qemuMonitorPtr mon, const char *devAlias, bool connected); int qemuMonitorEmitSpiceMigrated(qemuMonitorPtr mon); + +int qemuMonitorEmitMemoryFailure(qemuMonitorPtr mon, + qemuMonitorEventMemoryFailurePtr mfp); + int qemuMonitorEmitMigrationStatus(qemuMonitorPtr mon, int status); int qemuMonitorEmitMigrationPass(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 26ac499fc5..aa256727d6 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -112,6 +112,7 @@ static void qemuMonitorJSONHandleBlockThreshold(qemuMon= itorPtr mon, virJSONValue static void qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon, virJSON= ValuePtr data); static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitorPtr mon= , virJSONValuePtr data); static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitorPtr mon, = virJSONValuePtr data); +static void qemuMonitorJSONHandleMemoryFailure(qemuMonitorPtr mon, virJSON= ValuePtr data); =20 typedef struct { const char *type; @@ -132,6 +133,7 @@ static qemuEventHandler eventHandlers[] =3D { { "GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded, }, { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, }, { "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, }, + { "MEMORY_FAILURE", qemuMonitorJSONHandleMemoryFailure, }, { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, }, { "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, }, { "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, }, @@ -1336,6 +1338,53 @@ qemuMonitorJSONHandleSpiceMigrated(qemuMonitorPtr mo= n, =20 =20 static void +qemuMonitorJSONHandleMemoryFailure(qemuMonitorPtr mon, + virJSONValuePtr data) +{ + virJSONValuePtr flagsjson =3D virJSONValueObjectGetObject(data, "flags= "); + const char *str; + int recipient; + int action; + bool ar =3D false; + bool recursive =3D false; + qemuMonitorEventMemoryFailure mf =3D {0}; + + if (!(str =3D virJSONValueObjectGetString(data, "recipient"))) { + VIR_WARN("missing recipient in memory failure event"); + return; + } + + recipient =3D qemuMonitorMemoryFailureRecipientTypeFromString(str); + if (recipient =3D=3D -1) { + VIR_WARN("unknown recipient '%s' in memory_failure event", str); + return; + } + + if (!(str =3D virJSONValueObjectGetString(data, "action"))) { + VIR_WARN("missing action in memory failure event"); + return; + } + + action =3D qemuMonitorMemoryFailureActionTypeFromString(str); + if (action =3D=3D -1) { + VIR_WARN("unknown action '%s' in memory_failure event", str); + return; + } + + if (flagsjson) { + virJSONValueObjectGetBoolean(flagsjson, "action-required", &ar); + virJSONValueObjectGetBoolean(flagsjson, "recursive", &recursive); + } + + mf.recipient =3D recipient; + mf.action =3D action; + mf.action_required =3D ar; + mf.recursive =3D recursive; + qemuMonitorEmitMemoryFailure(mon, &mf); +} + + +static void qemuMonitorJSONHandleMigrationStatus(qemuMonitorPtr mon, virJSONValuePtr data) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 5bc76a75e3..77a9573933 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1878,6 +1878,64 @@ qemuProcessHandleGuestCrashloaded(qemuMonitorPtr mon= G_GNUC_UNUSED, } =20 =20 +static int +qemuProcessHandleMemoryFailure(qemuMonitorPtr mon G_GNUC_UNUSED, + virDomainObjPtr vm, + qemuMonitorEventMemoryFailurePtr mfp, + void *opaque) +{ + virQEMUDriverPtr driver =3D opaque; + virObjectEventPtr event =3D NULL; + virDomainMemoryFailureRecipientType recipient; + virDomainMemoryFailureActionType action; + unsigned int flags =3D 0; + + switch (mfp->recipient) { + case QEMU_MONITOR_MEMORY_FAILURE_RECIPIENT_HYPERVISOR: + recipient =3D VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_HYPERVISOR; + break; + case QEMU_MONITOR_MEMORY_FAILURE_RECIPIENT_GUEST: + recipient =3D VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_GUEST; + break; + case QEMU_MONITOR_MEMORY_FAILURE_RECIPIENT_LAST: + default: + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("requested unknown memory failure recipient")); + return -1; + } + + switch (mfp->action) { + case QEMU_MONITOR_MEMORY_FAILURE_ACTION_IGNORE: + action =3D VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_IGNORE; + break; + case QEMU_MONITOR_MEMORY_FAILURE_ACTION_INJECT: + action =3D VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_INJECT; + break; + case QEMU_MONITOR_MEMORY_FAILURE_ACTION_FATAL: + action =3D VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_FATAL; + break; + case QEMU_MONITOR_MEMORY_FAILURE_ACTION_RESET: + action =3D VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_RESET; + break; + case QEMU_MONITOR_MEMORY_FAILURE_ACTION_LAST: + default: + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("requested unknown memory failure action")); + return -1; + } + + if (mfp->action_required) + flags |=3D VIR_DOMAIN_MEMORY_FAILURE_ACTION_REQUIRED; + if (mfp->recursive) + flags |=3D VIR_DOMAIN_MEMORY_FAILURE_RECURSIVE; + + event =3D virDomainEventMemoryFailureNewFromObj(vm, recipient, action,= flags); + virObjectEventStateQueue(driver->domainEventState, event); + + return 0; +} + + static qemuMonitorCallbacks monitorCallbacks =3D { .eofNotify =3D qemuProcessHandleMonitorEOF, .errorNotify =3D qemuProcessHandleMonitorError, @@ -1910,6 +1968,7 @@ static qemuMonitorCallbacks monitorCallbacks =3D { .domainPRManagerStatusChanged =3D qemuProcessHandlePRManagerStatusChan= ged, .domainRdmaGidStatusChanged =3D qemuProcessHandleRdmaGidStatusChanged, .domainGuestCrashloaded =3D qemuProcessHandleGuestCrashloaded, + .domainMemoryFailure =3D qemuProcessHandleMemoryFailure, }; =20 static void --=20 2.11.0