xref: /openbmc/qemu/python/qemu/utils/accel.py (revision 11fb99e6)
1"""
2QEMU accel module:
3
4This module provides utilities for discover and check the availability of
5accelerators.
6"""
7# Copyright (C) 2015-2016 Red Hat Inc.
8# Copyright (C) 2012 IBM Corp.
9#
10# Authors:
11#  Fam Zheng <famz@redhat.com>
12#
13# This work is licensed under the terms of the GNU GPL, version 2.  See
14# the COPYING file in the top-level directory.
15#
16
17import logging
18import os
19import subprocess
20from typing import List, Optional
21
22
23LOG = logging.getLogger(__name__)
24
25# Mapping host architecture to any additional architectures it can
26# support which often includes its 32 bit cousin.
27ADDITIONAL_ARCHES = {
28    "x86_64": "i386",
29    "aarch64": "armhf",
30    "ppc64le": "ppc64",
31}
32
33
34def list_accel(qemu_bin: str) -> List[str]:
35    """
36    List accelerators enabled in the QEMU binary.
37
38    @param qemu_bin (str): path to the QEMU binary.
39    @raise Exception: if failed to run `qemu -accel help`
40    @return a list of accelerator names.
41    """
42    if not qemu_bin:
43        return []
44    try:
45        out = subprocess.check_output([qemu_bin, '-accel', 'help'],
46                                      universal_newlines=True)
47    except:
48        LOG.debug("Failed to get the list of accelerators in %s", qemu_bin)
49        raise
50    # Skip the first line which is the header.
51    return [acc.strip() for acc in out.splitlines()[1:]]
52
53
54def kvm_available(target_arch: Optional[str] = None,
55                  qemu_bin: Optional[str] = None) -> bool:
56    """
57    Check if KVM is available using the following heuristic:
58      - Kernel module is present in the host;
59      - Target and host arches don't mismatch;
60      - KVM is enabled in the QEMU binary.
61
62    @param target_arch (str): target architecture
63    @param qemu_bin (str): path to the QEMU binary
64    @return True if kvm is available, otherwise False.
65    """
66    if not os.access("/dev/kvm", os.R_OK | os.W_OK):
67        return False
68    if target_arch:
69        host_arch = os.uname()[4]
70        if target_arch != host_arch:
71            if target_arch != ADDITIONAL_ARCHES.get(host_arch):
72                return False
73    if qemu_bin and "kvm" not in list_accel(qemu_bin):
74        return False
75    return True
76
77
78def tcg_available(qemu_bin: str) -> bool:
79    """
80    Check if TCG is available.
81
82    @param qemu_bin (str): path to the QEMU binary
83    """
84    return 'tcg' in list_accel(qemu_bin)
85