diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt.php index c24b546de..26564b565 100644 --- a/emhttp/plugins/dynamix.vm.manager/include/libvirt.php +++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt.php @@ -353,11 +353,17 @@ class Libvirt { } if (!empty($domain['cpumigrate'])) $cpumigrate = " migratable='".$domain['cpumigrate']."'"; } + $cpupmemlmt =''; + if ($domain['cpupmemlmt'] != "None") { + if ($domain['cpumode'] == 'host-passthrough') $cpupmemlmt = ""; + else $cpupmemlmt = ""; + } # #Skylake-Client-noTSX-IBRS $cpustr = " $cpucache + $cpupmemlmt $cpufeatures {$vcpus} @@ -2033,6 +2039,25 @@ class Libvirt { return $var; } + function domain_get_cpu_pmem_limit($domain) { + $cpu_mode = $this->get_xpath($domain, '//domain/cpu/@mode', false); + if (!$cpu_mode) return null; + + $cpu_mode = $cpu_mode[0]; + + if ($cpu_mode === 'host-passthrough') { + // In passthrough mode, limit is a bit count (e.g., limit="39") + $limit = $this->get_xpath($domain, '//domain/cpu/maxphysaddr/@limit', false); + return $limit ? intval($limit[0]) : "None"; + } elseif ($cpu_mode === 'custom') { + // In custom mode, bits defines the max physical address width + $bits = $this->get_xpath($domain, '//domain/cpu/maxphysaddr/@bits', false); + return $bits ? intval($bits[0]) : "None"; + } + + return "None"; // no limit found or not enforced + } + # # Skylake-Client-noTSX-IBRS diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php index 8350c5fbe..900e2db70 100644 --- a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php +++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php @@ -1002,7 +1002,7 @@ class Array2XML { if (empty($arrMatch['name'])) { // Device name is blank, attempt to lookup usb details - exec("lsusb -d ".$arrMatch['id']." -v 2>/dev/null | grep -Po '^\s+(iManufacturer|iProduct)\s+[1-9]+ \K[^\\n]+'", $arrAltName); + exec("lsusb -d ".$arrMatch['id']." -v 2>/dev/null | grep -Po '^\s+(iManufacturer|iProduct)\s+[1-9]+ \K[^\\n]+'", $arrAltName); #PHPS $arrMatch['name'] = trim(implode(' ', (array)$arrAltName)); if (empty($arrMatch['name'])) { @@ -1405,6 +1405,7 @@ class Array2XML { 'maxmem' => $lv->domain_get_memory($res), 'password' => '', //TODO? 'cpumode' => $lv->domain_get_cpu_type($res), + 'cpupmemlmt' => $lv->domain_get_cpu_pmem_limit($res), 'cpumigrate' => $lv->domain_get_cpu_migrate($res), 'vcpus' => $dom['nrVirtCpu'], 'vcpu' => $lv->domain_get_vcpu_pins($res), @@ -1506,7 +1507,7 @@ class Array2XML { // remove existing auto-generated settings unset($old['cputune']['vcpupin'],$old['devices']['video'],$old['devices']['disk'],$old['devices']['interface'],$old['devices']['filesystem'],$old['cpu']['@attributes'],$old['os']['boot'],$old['os']['loader'],$old['os']['nvram']); // Remove old CPU cache and features - unset($old['cpu']['cache'], $old['cpu']['feature']); + unset($old['cpu']['cache'], $old['cpu']['feature'], $old['cpu']['maxphysaddr']); unset($old['features']['hyperv'],$old['devices']['channel']); // set namespace $new['metadata']['vmtemplate']['@attributes']['xmlns'] = 'unraid'; @@ -1803,7 +1804,7 @@ class Array2XML { } $cmdstr = "rsync -ahPIXS --out-format=%f --info=flist0,misc0,stats0,name1,progress2 '$repsrc' '$reptgt'"; - $error = execCommand_nchan_clone($cmdstr,$target,$refcmd); + $error = execCommand_nchan_clone($cmdstr,$target,$refcmd); #PHPS if (!$error) { write("addLog\0".htmlspecialchars("Image copied failed.")); return( false); } } } @@ -1895,7 +1896,7 @@ class Array2XML { $file = $disk["file"]; if ($disk['device'] == "hdc" ) $primarypath = dirname(transpose_user_path($file)); $output = array(); - exec("qemu-img info --backing-chain -U '$file' | grep image:",$output); + exec("qemu-img info --backing-chain -U '$file' | grep image:",$output); #PHPS foreach($output as $key => $line) { $line=str_replace("image: ","",$line); $output[$key] = $line; diff --git a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php index 09360472f..1a327eaec 100644 --- a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php +++ b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php @@ -133,6 +133,7 @@ $arrConfigDefaults = [ ] ]; $hdrXML = "\n"; // XML encoding declaration +$debug = false; // Merge in any default values from the VM template if ($arrAllTemplates[$strSelectedTemplate] && $arrAllTemplates[$strSelectedTemplate]['overrides']) { @@ -256,6 +257,12 @@ if (isset($_POST['updatevm'])) { if ($error = create_vdisk($_POST) === false) { $arrExistingConfig = custom::createArray('domain',$strXML); $arrUpdatedConfig = custom::createArray('domain',$lv->config_to_xml($_POST)); + if ($debug) { + file_put_contents("/tmp/vmdebug_exist",$strXML); + file_put_contents("/tmp/vmdebug_new",$lv->config_to_xml($_POST)); + file_put_contents("/tmp/vmdebug_arrayN",json_encode($arrUpdatedConfig,JSON_PRETTY_PRINT)); + file_put_contents("/tmp/vmdebug_arrayE",json_encode($arrExistingConfig,JSON_PRETTY_PRINT)); + } array_update_recursive($arrExistingConfig, $arrUpdatedConfig); $arrConfig = array_replace_recursive($arrExistingConfig, $arrUpdatedConfig); $xml = custom::createXML('domain',$arrConfig)->saveXML(); @@ -1903,6 +1910,37 @@ foreach ($arrConfig['evdev'] as $i => $arrEvdev) {

+ + + + + + +
_(Physical Address Bit Limit)_ +
+
+
+

+ Physical Address Bit Limit
+ Sets limit on the physical address space. +
+ Some guest systems or GPUs passed through might not work properly if mapped to high physical addresses (especially GPUs with 32-bit BARs). Using maxphysaddr=36 or maxphysaddr=39 limits the physical memory below 64 GB or 512 GB, avoiding such issues. +
+
bits=32 Addressable Memory 4 GB Use Case: Force 32-bit PCI compatibility +
bits=36 Addressable Memory 64 GB Use Case: Compatibility with older devices / 32-bit BARs +
bits=39 Addressable Memory 512 GB Use Case: Safe for most modern guests +
bits=48 Addressable Memory 256 TB Use Case: Full addressing, default on modern CPUs +

+