All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
To: John Snow <jsnow@redhat.com>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	Shiju Jose <shiju.jose@huawei.com>,
	Cleber Rosa <crosa@redhat.com>,
	linux-kernel@vger.kernel.org, qemu-devel@nongnu.org
Subject: Re: [PATCH v5 7/7] scripts/ghes_inject: add a script to generate GHES error inject
Date: Fri, 9 Aug 2024 09:37:18 +0200	[thread overview]
Message-ID: <20240809093718.095d0a34@foz.lan> (raw)
In-Reply-To: <20240809082609.1864eabe@foz.lan>

Em Fri, 9 Aug 2024 08:26:09 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:

> Em Fri, 9 Aug 2024 00:41:37 +0200
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:
> 
> > > You should be able to use e.g.
> > > 
> > > legacy.py's QEMUMonitorProtocol class for synchronous connections, e.g.
> > > 
> > > from qemu.qmp.legacy import QEMUMonitorProtocol
> > > 
> > > qmp = QEMUMonitorProtocol((host, port))
> > > qmp.connect(negotiate=True)  
> > 
> > That sounds interesting! I give it a try.
> 
> I applied the enclosed patch at the end of my patch series, but
> somehow it is not working. For whatever reason, connect() is
> raising a StateError apparently due to Runstate.CONNECTING.
> 
> I tried both as declaring (see enclosed patch):
> 
> 	class qmp(QEMUMonitorProtocol)
> 
> and using:
> 
> -        super().__init__(self.host, self.port)
> +        self.qmp_monitor = QEMUMonitorProtocol(self.host, self.port)
> 
> On both cases, it keeps waiting forever for a connection.

Nevermind, placing host/post on a tuple made it work.

The enclosed patch converts the script to use QEMUMonitorProtocol.

I'll fold it with the script for the next spin of this series.

Regards,
Mauro

---

[PATCH] scripts/qmp_helper.py: use QEMUMonitorProtocol class

Instead of reinventing the wheel, let's use QEMUMonitorProtocol.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/scripts/arm_processor_error.py b/scripts/arm_processor_error.py
index 756935a2263c..f869f07860b8 100644
--- a/scripts/arm_processor_error.py
+++ b/scripts/arm_processor_error.py
@@ -169,14 +169,11 @@ def send_cper(self, args):
         if args.mpidr:
             cper["mpidr-el1"] = arg["mpidr"]
         elif cpus:
-            get_mpidr = {
-                "execute": "qom-get",
-                "arguments": {
-                    'path': cpus[0],
-                    'property': "x-mpidr"
-                }
+            cmd_arg = {
+                'path': cpus[0],
+                'property': "x-mpidr"
             }
-            ret = qmp_cmd.send_cmd(get_mpidr, may_open=True)
+            ret = qmp_cmd.send_cmd("qom-get", cmd_arg, may_open=True)
             if isinstance(ret, int):
                 cper["mpidr-el1"] = ret
             else:
@@ -291,8 +288,7 @@ def send_cper(self, args):
         context_info_num = 0
 
         if ctx:
-            ret = qmp_cmd.send_cmd('{ "execute": "query-target" }',
-                                   may_open=True)
+            ret = qmp_cmd.send_cmd("query-target", may_open=True)
 
             default_ctx = self.CONTEXT_MISC_REG
 
@@ -363,14 +359,11 @@ def send_cper(self, args):
 
         if "midr-el1" not in arg:
             if cpus:
-                get_mpidr = {
-                    "execute": "qom-get",
-                    "arguments": {
-                        'path': cpus[0],
-                        'property': "midr"
-                    }
+                cmd_arg = {
+                    'path': cpus[0],
+                    'property': "midr"
                 }
-                ret = qmp_cmd.send_cmd(get_mpidr, may_open=True)
+                ret = qmp_cmd.send_cmd("qom-get", cmd_arg, may_open=True)
                 if isinstance(ret, int):
                     arg["midr-el1"] = ret
 
diff --git a/scripts/qmp_helper.py b/scripts/qmp_helper.py
index 7214c15c6718..e2e0a881f6c1 100644
--- a/scripts/qmp_helper.py
+++ b/scripts/qmp_helper.py
@@ -9,6 +9,19 @@
 import socket
 import sys
 
+from os import path
+
+try:
+    qemu_dir = path.abspath(path.dirname(path.dirname(__file__)))
+    sys.path.append(path.join(qemu_dir, 'python'))
+
+    from qemu.qmp.legacy import QEMUMonitorProtocol
+
+except ModuleNotFoundError as exc:
+    print(f"Module '{exc.name}' not found.")
+    print("Try export PYTHONPATH=top-qemu-dir/python or run from top-qemu-dir")
+    sys.exit(1)
+
 from base64 import b64encode
 
 class qmp:
@@ -16,26 +29,23 @@ class qmp:
     Opens a connection and send/receive QMP commands.
     """
 
-    def send_cmd(self, command, may_open=False, return_error=True):
+    def send_cmd(self, command, args=None, may_open=False, return_error=True):
         """Send a command to QMP, optinally opening a connection"""
 
         if may_open:
             self._connect()
-        elif not self.socket:
-            return None
+        elif not self.connected:
+            return False
 
-        if isinstance(command, dict):
-            data = json.dumps(command).encode("utf-8")
-        else:
-            data = command.encode("utf-8")
+        msg = { 'execute': command }
+        if args:
+            msg['arguments'] = args
 
-        self.socket.sendall(data)
-        data = self.socket.recv(1024)
         try:
-            obj = json.loads(data.decode("utf-8"))
-        except json.JSONDecodeError as e:
-            print(f"Invalid QMP answer: {e}")
-            self._close()
+            obj = self.qmp_monitor.cmd_obj(msg)
+        except Exception as e:
+            print(f"Command: {command}")
+            print(f"Failed to inject error: {e}.")
             return None
 
         if "return" in obj:
@@ -49,6 +59,7 @@ def send_cmd(self, command, may_open=False, return_error=True):
         elif isinstance(obj.get("error"), dict):
             error = obj["error"]
             if return_error:
+                print(f"Command: {msg}")
                 print(f'{error["class"]}: {error["desc"]}')
         else:
             print(json.dumps(obj))
@@ -57,75 +68,37 @@ def send_cmd(self, command, may_open=False, return_error=True):
 
     def _close(self):
         """Shutdown and close the socket, if opened"""
-        if not self.socket:
+        if not self.connected:
             return
 
-        self.socket.shutdown(socket.SHUT_WR)
-        while 1:
-            data = self.socket.recv(1024)
-            if data == b"":
-                break
-            try:
-                obj = json.loads(data.decode("utf-8"))
-            except json.JSONDecodeError as e:
-                print(f"Invalid QMP answer: {e}")
-                self.socket.close()
-                self.socket = None
-                return
-
-            if isinstance(obj.get("return"), dict):
-                print(json.dumps(obj["return"]))
-            if isinstance(obj.get("error"), dict):
-                error = obj["error"]
-                print(f'{error["class"]}: {error["desc"]}')
-            else:
-                print(json.dumps(obj))
-
-        self.socket.close()
-        self.socket = None
+        self.qmp_monitor.close()
+        self.connected = False
 
     def _connect(self):
         """Connect to a QMP TCP/IP port, if not connected yet"""
 
-        if self.socket:
+        if self.connected:
             return True
 
-        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         try:
-            self.socket.connect((self.host, self.port))
-        except ConnectionRefusedError:
+            ret = self.qmp_monitor.connect(negotiate=True)
+        except ConnectionError:
             sys.exit(f"Can't connect to QMP host {self.host}:{self.port}")
-
-        data = self.socket.recv(1024)
-        try:
-            obj = json.loads(data.decode("utf-8"))
-        except json.JSONDecodeError as e:
-            print(f"Invalid QMP answer: {e}")
-            self._close()
             return False
 
-        if "QMP" not in obj:
-            print(f"Invalid QMP answer: {data.decode('utf-8')}")
-            self._close()
-            return False
-
-        result = self.send_cmd('{ "execute": "qmp_capabilities" }')
-        if not result:
-            self._close()
-            return False
+        self.connected = True
 
         return True
 
     def __init__(self, host, port, debug=False):
         """Initialize variables used by the QMP send logic"""
 
-        self.socket = None
+        self.connected = False
         self.host = host
         self.port = port
         self.debug = debug
 
-    def __del__(self):
-        self._close()
+        self.qmp_monitor = QEMUMonitorProtocol(address=(self.host, self.port))
 
     #
     # Socket QMP send command
@@ -142,9 +115,6 @@ def send_cper(self, guid, data):
             }
         }
 
-        command = '{ "execute": "ghes-cper", '
-        command += '"arguments": ' + json.dumps(cmd_arg) + " }"
-
         if self.debug:
             print(f"GUID: {guid}")
             print("CPER:")
@@ -168,7 +138,7 @@ def send_cper(self, guid, data):
 
         self._connect()
 
-        if self.send_cmd(command):
+        if self.send_cmd("ghes-cper", cmd_arg):
             print("Error injected.")
 
     def search_qom(self, path, prop, regex):
@@ -185,14 +155,11 @@ def search_qom(self, path, prop, regex):
         i = 0
         while 1:
             dev = f"{path}[{i}]"
-            cmd =  {
-                "execute": "qom-get",
-                "arguments": {
-                    'path': dev,
-                    'property': prop
-                }
+            args = {
+                'path': dev,
+                'property': prop
             }
-            ret = self.send_cmd(cmd, may_open=True, return_error=False)
+            ret = self.send_cmd("qom-get", args, may_open=True, return_error=False)
             if not ret:
                 break
 



      reply	other threads:[~2024-08-09  7:38 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-02 21:43 [PATCH v5 0/7] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
2024-08-02 21:43 ` [PATCH v5 1/7] arm/virt: place power button pin number on a define Mauro Carvalho Chehab
2024-08-06  8:57   ` Igor Mammedov
2024-08-02 21:43 ` [PATCH v5 2/7] acpi/generic_event_device: add an APEI error device Mauro Carvalho Chehab
2024-08-05 16:39   ` Jonathan Cameron via
2024-08-05 16:39     ` Jonathan Cameron
2024-08-06  5:50     ` Mauro Carvalho Chehab
2024-08-06  8:54   ` Igor Mammedov
2024-08-02 21:43 ` [PATCH v5 3/7] arm/virt: Wire up GPIO error source for ACPI / GHES Mauro Carvalho Chehab
2024-08-05 16:54   ` Jonathan Cameron
2024-08-05 16:54     ` Jonathan Cameron via
2024-08-06  5:56     ` Mauro Carvalho Chehab
2024-08-06  9:15   ` Igor Mammedov
2024-08-02 21:43 ` [PATCH v5 4/7] acpi/ghes: Support GPIO error source Mauro Carvalho Chehab
2024-08-05 16:56   ` Jonathan Cameron via
2024-08-05 16:56     ` Jonathan Cameron
2024-08-05 16:56     ` Jonathan Cameron via
2024-08-06  6:09     ` Mauro Carvalho Chehab
2024-08-06  9:18       ` Igor Mammedov
2024-08-06  9:32   ` Igor Mammedov
2024-08-07  7:15     ` Mauro Carvalho Chehab
2024-08-02 21:44 ` [PATCH v5 5/7] qapi/ghes-cper: add an interface to do generic CPER error injection Mauro Carvalho Chehab
2024-08-05 17:00   ` Jonathan Cameron
2024-08-05 17:00     ` Jonathan Cameron via
2024-08-06  9:15   ` Shiju Jose
2024-08-06  9:15     ` Shiju Jose via
2024-08-06 12:51   ` Igor Mammedov
2024-08-06 12:58     ` Mauro Carvalho Chehab
2024-08-08  8:50   ` Markus Armbruster
2024-08-08 14:11     ` Mauro Carvalho Chehab
2024-08-08 14:22       ` Igor Mammedov
2024-08-08 14:45         ` Markus Armbruster
2024-08-09  8:42           ` Mauro Carvalho Chehab
2024-08-02 21:44 ` [PATCH v5 6/7] acpi/ghes: add support for generic error injection via QAPI Mauro Carvalho Chehab
2024-08-05 17:03   ` Jonathan Cameron
2024-08-05 17:03     ` Jonathan Cameron via
2024-08-06 11:13   ` Shiju Jose
2024-08-06 11:13     ` Shiju Jose via
2024-08-06 14:31   ` Igor Mammedov
2024-08-07  7:47     ` Mauro Carvalho Chehab
2024-08-07  9:34       ` Jonathan Cameron
2024-08-07  9:34         ` Jonathan Cameron via
2024-08-07 13:23         ` Mauro Carvalho Chehab
2024-08-07 13:43           ` Igor Mammedov
2024-08-07 13:28         ` Igor Mammedov
2024-08-07 14:25     ` Jonathan Cameron
2024-08-07 14:25       ` Jonathan Cameron via
2024-08-08  8:11       ` Igor Mammedov
2024-08-08 18:19         ` Mauro Carvalho Chehab
2024-08-12  9:39           ` Igor Mammedov
2024-08-13 18:59             ` Mauro Carvalho Chehab
2024-08-08 12:11     ` Mauro Carvalho Chehab
2024-08-08 12:45       ` Igor Mammedov
2024-08-02 21:44 ` [PATCH v5 7/7] scripts/ghes_inject: add a script to generate GHES error inject Mauro Carvalho Chehab
2024-08-06 14:56   ` Igor Mammedov
2024-08-08 20:58   ` John Snow
2024-08-08 21:51     ` Mauro Carvalho Chehab
2024-08-08 21:21   ` John Snow
2024-08-08 22:41     ` Mauro Carvalho Chehab
2024-08-08 23:33       ` John Snow
2024-08-09  8:24         ` Mauro Carvalho Chehab
2024-08-09 19:26           ` John Snow
2024-08-09  6:26       ` Mauro Carvalho Chehab
2024-08-09  7:37         ` Mauro Carvalho Chehab [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240809093718.095d0a34@foz.lan \
    --to=mchehab+huawei@kernel.org \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=crosa@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=qemu-devel@nongnu.org \
    --cc=shiju.jose@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.