1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
<?php
class HardwareInfo
{
// Never change these!
const RAM_MODULE = 'RAM';
const MAINBOARD = 'MAINBOARD';
const DMI_SYSTEM = 'DMI_SYSTEM';
const POWER_SUPPLY = 'POWER_SUPPLY';
const SYSTEM_SLOT = 'SYSTEM_SLOT';
const PCI_DEVICE = 'PCI_DEVICE';
const HDD = 'HDD';
const CPU = 'CPU';
/**
* Get a KCL modification string for the given machine, enabling GVT, PCI passthrough etc.
* You can provide a UUID and/or MAC, or nothing. If nothing is provided,
* the "uuid" and "mac" GET parameters will be used. If both are provided,
* the resulting machine that has the greatest "lastseen" value will be used.
* @param ?string $uuid UUID of machine
* @param ?string $mac MAC of machine
* @return string
*/
public static function getKclModifications($uuid = null, $mac = null): string
{
if ($uuid === null && $mac === null) {
$uuid = Request::get('uuid', '', 'string');
$mac = Request::get('mac', '', 'string');
$mac = str_replace(':', '-', $mac);
}
$res = Database::simpleQuery("SELECT machineuuid, lastseen FROM machine
WHERE machineuuid = :uuid OR macaddr = :mac", ['uuid' => $uuid, 'mac' => $mac]);
$best = null;
foreach ($res as $row) {
if ($best === null || $best['lastseen'] < $row['lastseen']) {
$best = $row;
}
}
if ($best === null)
return '';
$hw = new HardwareQuery(self::PCI_DEVICE, $best['machineuuid'], true);
// TODO: Get list of enabled pass through groups for this client's location
$hw->addWhere(true, '@PASSTHROUGH', 'IN', ['GPU', 'GVT']);
$hw->addGlobalColumn('vendor');
$hw->addGlobalColumn('device');
$hw->addLocalColumn('slot');
$res = $hw->query();
$passthrough = [];
$slots = [];
$gvt = false;
foreach ($res as $row) {
if ($row['@PASSTHROUGH'] === 'GVT') {
$gvt = true;
} else {
$passthrough[$row['vendor'] . ':' . $row['device']] = 1;
error_log('Passthouorgh: ' . $row['vendor'] . ':' . $row['device']);
$slots[preg_replace('/\.[0-9]+$/', '', $row['slot'])] = 1;
}
}
$kcl = '';
if ($gvt || !empty($passthrough)) {
$kcl = '-iommu -intel_iommu iommu=pt intel_iommu=on'; // TODO AMD
}
if (!empty($passthrough)) {
foreach (array_keys($slots) as $slot) {
error_log('Querying slot ' . $slot);
$hw = new HardwareQuery(self::PCI_DEVICE, $best['machineuuid'], true);
$hw->addWhere(false, 'slot', 'LIKE', $slot . '.%');
$hw->addGlobalColumn('vendor');
$hw->addGlobalColumn('device');
foreach ($hw->query() as $row) {
$passthrough[$row['vendor'] . ':' . $row['device']] = 1;
error_log('Extra PT: ' . $row['vendor'] . ':' . $row['device']);
}
}
$kcl .= ' vfio-pci.ids=' . implode(',', array_keys($passthrough));
}
if ($gvt) {
$kcl .= ' i915.enable_gvt=1';
}
return $kcl;
}
}
|