summaryrefslogtreecommitdiffstats
path: root/modules-available/statistics/inc/hardwareinfo.inc.php
blob: 5f1a4372397b0f5aa661fc355dd7103a7f3997a8 (plain) (blame)
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->addColumn(true, 'vendor');
		$hw->addColumn(true, 'device');
		$hw->addColumn(false, '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->addColumn(true, 'vendor');
				$hw->addColumn(true, '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;
	}

}