diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index ce958843..58132420 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -525,8 +525,6 @@ my $MAX_HOSTPCI_DEVICES = 4; my $MAX_SERIAL_PORTS = 4; my $MAX_PARALLEL_PORTS = 3; my $MAX_NUMA = 8; -my $MAX_MEM = 4194304; -my $STATICMEM = 1024; my $numa_fmt = { cpus => { @@ -3072,105 +3070,8 @@ sub config_to_command { push @$cmd, '-cpu', $cpu; - my $memory = $conf->{memory} || $defaults->{memory}; - my $static_memory = 0; - my $dimm_memory = 0; - - if ($hotplug_features->{memory}) { - die "NUMA need to be enabled for memory hotplug\n" if !$conf->{numa}; - die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM; - $static_memory = $STATICMEM; - die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory); - $dimm_memory = $memory - $static_memory; - push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M"; - - } else { - - $static_memory = $memory; - push @$cmd, '-m', $static_memory; - } - - if ($conf->{numa}) { - - my $numa_totalmemory = undef; - for (my $i = 0; $i < $MAX_NUMA; $i++) { - next if !$conf->{"numa$i"}; - my $numa = parse_numa($conf->{"numa$i"}); - next if !$numa; - # memory - die "missing NUMA node$i memory value\n" if !$numa->{memory}; - my $numa_memory = $numa->{memory}; - $numa_totalmemory += $numa_memory; - my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M"; - - # cpus - my $cpulists = $numa->{cpus}; - die "missing NUMA node$i cpus\n" if !defined($cpulists); - my $cpus = join(',', map { - my ($start, $end) = @$_; - defined($end) ? "$start-$end" : $start - } @$cpulists); - - # hostnodes - my $hostnodelists = $numa->{hostnodes}; - if (defined($hostnodelists)) { - my $hostnodes; - foreach my $hostnoderange (@$hostnodelists) { - my ($start, $end) = @$hostnoderange; - $hostnodes .= ',' if $hostnodes; - $hostnodes .= $start; - $hostnodes .= "-$end" if defined($end); - $end //= $start; - for (my $i = $start; $i <= $end; ++$i ) { - die "host NUMA node$i don't exist\n" if ! -d "/sys/devices/system/node/node$i/"; - } - } - - # policy - my $policy = $numa->{policy}; - die "you need to define a policy for hostnode $hostnodes\n" if !$policy; - $numa_object .= ",host-nodes=$hostnodes,policy=$policy"; - } - - push @$cmd, '-object', $numa_object; - push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i"; - } - - die "total memory for NUMA nodes must be equal to vm static memory\n" - if $numa_totalmemory && $numa_totalmemory != $static_memory; - - #if no custom tology, we split memory and cores across numa nodes - if(!$numa_totalmemory) { - - my $numa_memory = ($static_memory / $sockets) . "M"; - - for (my $i = 0; $i < $sockets; $i++) { - - my $cpustart = ($cores * $i); - my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1; - my $cpus = $cpustart; - $cpus .= "-$cpuend" if $cpuend; - - push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i"; - push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i"; - } - } - } - - if ($hotplug_features->{memory}) { - PVE::QemuServer::Memory::foreach_dimm($conf, $vmid, $memory, $sockets, sub { - my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_; - push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M"; - push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode"; - - #if dimm_memory is not aligned to dimm map - if($current_size > $memory) { - $conf->{memory} = $current_size; - PVE::QemuConfig->write_config($vmid, $conf); - } - }); - } - + PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd); + push @$cmd, '-S' if $conf->{freeze}; # set keyboard layout diff --git a/PVE/QemuServer/Memory.pm b/PVE/QemuServer/Memory.pm index 48224f2b..3c9659c6 100644 --- a/PVE/QemuServer/Memory.pm +++ b/PVE/QemuServer/Memory.pm @@ -4,6 +4,7 @@ use strict; use warnings; use PVE::QemuServer; +my $MAX_NUMA = 8; my $MAX_MEM = 4194304; my $STATICMEM = 1024; @@ -135,5 +136,109 @@ sub qemu_dimm_list { return $dimms; } +sub config { + my ($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd) = @_; + + my $memory = $conf->{memory} || $defaults->{memory}; + my $static_memory = 0; + my $dimm_memory = 0; + + if ($hotplug_features->{memory}) { + die "NUMA need to be enabled for memory hotplug\n" if !$conf->{numa}; + die "Total memory is bigger than ${MAX_MEM}MB\n" if $memory > $MAX_MEM; + $static_memory = $STATICMEM; + die "minimum memory must be ${static_memory}MB\n" if($memory < $static_memory); + $dimm_memory = $memory - $static_memory; + push @$cmd, '-m', "size=${static_memory},slots=255,maxmem=${MAX_MEM}M"; + + } else { + + $static_memory = $memory; + push @$cmd, '-m', $static_memory; + } + + if ($conf->{numa}) { + + my $numa_totalmemory = undef; + for (my $i = 0; $i < $MAX_NUMA; $i++) { + next if !$conf->{"numa$i"}; + my $numa = PVE::QemuServer::parse_numa($conf->{"numa$i"}); + next if !$numa; + # memory + die "missing NUMA node$i memory value\n" if !$numa->{memory}; + my $numa_memory = $numa->{memory}; + $numa_totalmemory += $numa_memory; + my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M"; + + # cpus + my $cpulists = $numa->{cpus}; + die "missing NUMA node$i cpus\n" if !defined($cpulists); + my $cpus = join(',', map { + my ($start, $end) = @$_; + defined($end) ? "$start-$end" : $start + } @$cpulists); + + # hostnodes + my $hostnodelists = $numa->{hostnodes}; + if (defined($hostnodelists)) { + my $hostnodes; + foreach my $hostnoderange (@$hostnodelists) { + my ($start, $end) = @$hostnoderange; + $hostnodes .= ',' if $hostnodes; + $hostnodes .= $start; + $hostnodes .= "-$end" if defined($end); + $end //= $start; + for (my $i = $start; $i <= $end; ++$i ) { + die "host NUMA node$i don't exist\n" if ! -d "/sys/devices/system/node/node$i/"; + } + } + + # policy + my $policy = $numa->{policy}; + die "you need to define a policy for hostnode $hostnodes\n" if !$policy; + $numa_object .= ",host-nodes=$hostnodes,policy=$policy"; + } + + push @$cmd, '-object', $numa_object; + push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i"; + } + + die "total memory for NUMA nodes must be equal to vm static memory\n" + if $numa_totalmemory && $numa_totalmemory != $static_memory; + + #if no custom tology, we split memory and cores across numa nodes + if(!$numa_totalmemory) { + + my $numa_memory = ($static_memory / $sockets) . "M"; + + for (my $i = 0; $i < $sockets; $i++) { + + my $cpustart = ($cores * $i); + my $cpuend = ($cpustart + $cores - 1) if $cores && $cores > 1; + my $cpus = $cpustart; + $cpus .= "-$cpuend" if $cpuend; + + push @$cmd, '-object', "memory-backend-ram,size=$numa_memory,id=ram-node$i"; + push @$cmd, '-numa', "node,nodeid=$i,cpus=$cpus,memdev=ram-node$i"; + } + } + } + + if ($hotplug_features->{memory}) { + foreach_dimm($conf, $vmid, $memory, $sockets, sub { + my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) = @_; + push @$cmd, "-object" , "memory-backend-ram,id=mem-$name,size=${dimm_size}M"; + push @$cmd, "-device", "pc-dimm,id=$name,memdev=mem-$name,node=$numanode"; + + #if dimm_memory is not aligned to dimm map + if($current_size > $memory) { + $conf->{memory} = $current_size; + PVE::QemuConfig->write_config($vmid, $conf); + } + }); + } +} + + 1;