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
+