This python script calls 'query-cpus' QMP command to retrieve
vCPUs thread IDs.
Thread IDs are then used by taskset to pin vCPUs to physical
CPUs passed in command line.

In case more vCPUs are present than the number of CPUs assigned
in command line, multiple vCPUs get pinned to physical CPUs.

Signed-off-by: Maxime Coquelin <maxime.coque...@redhat.com>
---

This script is not for production, where libvirt should be used.
However, I find it useful during development, so I propose to share
it as it might interest other people.

Note: it seems that tcp socket support is broken with QMP class.
The bug has already been reported and patch proposed[0].
So it has only been tested with UNIX socket.

[0]: 
<b9d0e4270773564788dc15a2db8e407119648956.1471108930.git.c...@resonantcircuitlabs.com>

 scripts/qmp/qmp-vcpu-pin | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100755 scripts/qmp/qmp-vcpu-pin

diff --git a/scripts/qmp/qmp-vcpu-pin b/scripts/qmp/qmp-vcpu-pin
new file mode 100755
index 0000000..7bf96f7
--- /dev/null
+++ b/scripts/qmp/qmp-vcpu-pin
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+# QEMU vCPU pinning tool
+#
+# Copyright (C) 2016 Red Hat Inc.
+#
+# Authors:
+#  Maxime Coquelin <maxime.coque...@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory
+import argparse
+import json
+import os
+
+from subprocess import call
+from qmp import QEMUMonitorProtocol
+
+parser = argparse.ArgumentParser(description='Pin QEMU vCPUs to physical CPUs')
+parser.add_argument('-s', '--server', type=str, required=True,
+                    help='QMP server path or address:port')
+parser.add_argument('cpu', type=int, nargs='+',
+                    help='Physical CPUs IDs')
+args = parser.parse_args()
+
+devnull = open(os.devnull, 'w')
+
+srv = QEMUMonitorProtocol(args.server)
+srv.connect()
+
+for vcpu in srv.command('query-cpus'):
+    vcpuid = vcpu['CPU']
+    tid = vcpu['thread_id']
+    cpuid = args.cpu[vcpuid % len(args.cpu)]
+    print 'Pin vCPU {} (tid {}) to physical CPU {}'.format(vcpuid, tid, cpuid)
+    try:
+        call(['taskset', '-pc', str(cpuid), str(tid)], stdout=devnull)
+    except OSError:
+        print 'Failed to pin vCPU{} to CPU{}'.format(vcpuid, cpuid)
+
-- 
2.7.4


Reply via email to