qemu_extdevice.c 6.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * qemu_extdevice.c: QEMU external devices support
 *
 * Copyright (C) 2014, 2018 IBM Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <config.h>

#include "qemu_extdevice.h"
24
#include "qemu_vhost_user_gpu.h"
25 26
#include "qemu_domain.h"
#include "qemu_tpm.h"
27
#include "qemu_slirp.h"
28 29 30 31 32

#include "viralloc.h"
#include "virlog.h"
#include "virstring.h"
#include "virtime.h"
33 34
#include "virtpm.h"
#include "virpidfile.h"
35 36 37

#define VIR_FROM_THIS VIR_FROM_QEMU

38
VIR_LOG_INIT("qemu.qemu_extdevice");
39 40

int
41 42
qemuExtDeviceLogCommand(virQEMUDriverPtr driver,
                        virDomainObjPtr vm,
43 44 45
                        virCommandPtr cmd,
                        const char *info)
{
46 47
    g_autofree char *timestamp = virTimeStringNow();
    g_autofree char *cmds = virCommandToString(cmd, false);
48

49 50
    if (!timestamp || !cmds)
        return -1;
51

52 53 54
    return qemuDomainLogAppendMessage(driver, vm,
                                      _("%s: Starting external device: %s\n%s\n"),
                                      timestamp, info, cmds);
55 56 57
}


58

59 60 61 62 63 64 65 66 67 68
/*
 * qemuExtDevicesInitPaths:
 *
 * @driver: QEMU driver
 * @def: domain definition
 *
 * Initialize paths of external devices so that it is known where state is
 * stored and we can remove directories and files in case of domain XML
 * changes.
 */
69
static int
70 71 72 73 74 75 76 77 78 79 80 81
qemuExtDevicesInitPaths(virQEMUDriverPtr driver,
                        virDomainDefPtr def)
{
    int ret = 0;

    if (def->tpm)
        ret = qemuExtTPMInitPaths(driver, def);

    return ret;
}


82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
/*
 * qemuExtDevicesPrepareDomain:
 *
 * @driver: QEMU driver
 * @vm: domain
 *
 * Code that modifies live XML of a domain which is about to start.
 */
int
qemuExtDevicesPrepareDomain(virQEMUDriverPtr driver,
                            virDomainObjPtr vm)
{
    int ret = 0;
    size_t i;

    for (i = 0; i < vm->def->nvideos; i++) {
        virDomainVideoDefPtr video = vm->def->videos[i];

        if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER) {
            if ((ret = qemuExtVhostUserGPUPrepareDomain(driver, video)) < 0)
                break;
        }
    }

    return ret;
}


110 111 112 113 114 115 116 117 118 119
/*
 * qemuExtDevicesPrepareHost:
 *
 * @driver: QEMU driver
 * @def: domain definition
 *
 * Prepare host storage paths for external devices.
 */
int
qemuExtDevicesPrepareHost(virQEMUDriverPtr driver,
120
                          virDomainObjPtr vm)
121
{
122 123
    virDomainDefPtr def = vm->def;
    size_t i;
124

125 126 127
    if (def->tpm &&
        qemuExtTPMPrepareHost(driver, def) < 0)
        return -1;
128

129 130 131 132 133 134 135 136 137
    for (i = 0; i < def->nnets; i++) {
        virDomainNetDefPtr net = def->nets[i];
        qemuSlirpPtr slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp;

        if (slirp && qemuSlirpOpen(slirp, driver, def) < 0)
            return -1;
    }

    return 0;
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
}


void
qemuExtDevicesCleanupHost(virQEMUDriverPtr driver,
                          virDomainDefPtr def)
{
    if (qemuExtDevicesInitPaths(driver, def) < 0)
        return;

    if (def->tpm)
        qemuExtTPMCleanupHost(def);
}


int
qemuExtDevicesStart(virQEMUDriverPtr driver,
155
                    virDomainObjPtr vm,
156
                    virLogManagerPtr logManager G_GNUC_UNUSED,
157
                    bool incomingMigration)
158
{
159 160
    virDomainDefPtr def = vm->def;
    size_t i;
161

162
    if (qemuExtDevicesInitPaths(driver, def) < 0)
163 164
        return -1;

165 166
    for (i = 0; i < def->nvideos; i++) {
        virDomainVideoDefPtr video = def->videos[i];
167 168

        if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER) {
169 170
            if (qemuExtVhostUserGPUStart(driver, vm, video) < 0)
                return -1;
171 172 173
        }
    }

174 175
    if (def->tpm && qemuExtTPMStart(driver, vm, incomingMigration) < 0)
        return -1;
176

177 178 179 180 181 182 183 184 185
    for (i = 0; i < def->nnets; i++) {
        virDomainNetDefPtr net = def->nets[i];
        qemuSlirpPtr slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp;

        if (slirp &&
            qemuSlirpStart(slirp, vm, driver, net, false, incomingMigration) < 0)
            return -1;
    }

186
    return 0;
187 188 189 190 191
}


void
qemuExtDevicesStop(virQEMUDriverPtr driver,
192
                   virDomainObjPtr vm)
193
{
194 195 196
    virDomainDefPtr def = vm->def;
    size_t i;

197
    if (qemuExtDevicesInitPaths(driver, def) < 0)
198 199
        return;

200 201 202 203 204 205 206 207
    for (i = 0; i < def->nvideos; i++) {
        virDomainVideoDefPtr video = def->videos[i];

        if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER)
            qemuExtVhostUserGPUStop(driver, vm, video);
    }

    if (def->tpm)
208
        qemuExtTPMStop(driver, vm);
209 210 211 212 213 214 215 216

    for (i = 0; i < def->nnets; i++) {
        virDomainNetDefPtr net = def->nets[i];
        qemuSlirpPtr slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp;

        if (slirp)
            qemuSlirpStop(slirp, vm, driver, net, false);
    }
217
}
218 219 220 221 222


bool
qemuExtDevicesHasDevice(virDomainDefPtr def)
{
223 224 225 226 227 228 229
    size_t i;

    for (i = 0; i < def->nvideos; i++) {
        if (def->videos[i]->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER)
            return true;
    }

230 231 232 233 234 235 236 237 238 239 240 241
    if (def->tpm && def->tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR)
        return true;

    return false;
}


int
qemuExtDevicesSetupCgroup(virQEMUDriverPtr driver,
                          virDomainDefPtr def,
                          virCgroupPtr cgroup)
{
242
    size_t i;
243

244 245
    for (i = 0; i < def->nvideos; i++) {
        virDomainVideoDefPtr video = def->videos[i];
246

247 248 249 250 251 252 253 254 255 256
        if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER &&
            qemuExtVhostUserGPUSetupCgroup(driver, def, video, cgroup) < 0)
            return -1;
    }

    if (def->tpm &&
        qemuExtTPMSetupCgroup(driver, def, cgroup) < 0)
        return -1;

    return 0;
257
}