[pve-devel] applied: [PATCH qemu-server 1/1 v2] fix #1952: make vga memory configurable

Thomas Lamprecht t.lamprecht at proxmox.com
Fri Nov 9 14:21:22 CET 2018


On 11/9/18 1:31 PM, Dominik Csapak wrote:
> we change 'vga' to a property string and add a 'memory' property
> with this, the user can better control the memory given to the virtual
> gpu, this is especially useful for spice/qxl since high resolutions need
> more memory
> 
> Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>

applied, with minor comment fixup (see below), thanks!

> ---
>  PVE/QemuServer.pm     | 134 ++++++++++++++++++++++++++++++++++++++++----------
>  PVE/QemuServer/PCI.pm |   3 +-
>  2 files changed, 109 insertions(+), 28 deletions(-)
> 
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index 82c9b96..c3932d0 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -223,6 +223,24 @@ my $agent_fmt = {
>      },
>  };
>  
> +my $vga_fmt = {
> +    type => {
> +	description => "Select the VGA type.",
> +	type => 'string',
> +	default => 'std',
> +	optional => 1,
> +	default_key => 1,
> +	enum => [qw(cirrus qxl qxl2 qxl3 qxl4 serial0 serial1 serial2 serial3 std virtio vmware)],
> +    },
> +    memory => {
> +	description => "Sets the VGA memory (in MiB). Has no effect with serial display.",
> +	type => 'integer',
> +	optional => 1,
> +	minimum => 4,
> +	maximum => 512,
> +    },
> +};
> +
>  my $confdesc = {
>      onboot => {
>  	optional => 1,
> @@ -431,17 +449,16 @@ EODESC
>      },
>      vga => {
>  	optional => 1,
> -	type => 'string',
> -	description => "Select the VGA type.",
> -        verbose_description => "Select the VGA type. If you want to use high resolution" .
> -	    " modes (>= 1280x1024x16) then you should use the options " .
> -	    "'std' or 'vmware'. Default is 'std' for win8/win7/w2k8, and " .
> -	    "'cirrus' for other OS types. The 'qxl' option enables the SPICE " .
> -	    "display sever. For win* OS you can select how many independent " .
> -	    "displays you want, Linux guests can add displays them self. " .
> -	    "You can also run without any graphic card, using a serial device" .
> -	    " as terminal.",
> -	enum => [qw(cirrus qxl qxl2 qxl3 qxl4 serial0 serial1 serial2 serial3 std virtio vmware)],
> +	type => 'string', format => $vga_fmt,
> +	description => "Configure the VGA hardware.",
> +	verbose_description => "Configure the VGA Hardware. If you want to use ".
> +	    "high resolution modes (>= 1280x1024x16) you may need to increase " .
> +	    "the vga memory option. Since QEMU 2.9 the default VGA display type " .
> +	    "is 'std' for all OS types besides some Windows versions (XP and " .
> +	    "older) which use 'cirrus'. The 'qxl' option enables the SPICE " .
> +	    "display server. For win* OS you can select how many independent " .
> +	    "displays you want, Linux guests can add displays them self.\n".
> +	    "You can also run without any graphic card, using a serial device as terminal.",
>      },
>      watchdog => {
>  	optional => 1,
> @@ -1961,6 +1978,54 @@ sub print_cpu_device {
>      return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
>  }
>  
> +my $vga_map = {
> +    'cirrus' => 'cirrus-vga',
> +    'std' => 'VGA',
> +    'vmware' => 'vmware-svga',
> +    'virtio' => 'virtio-vga',
> +};
> +
> +sub print_vga_device {
> +    my ($conf, $vga, $id, $qxlnum, $bridges) = @_;
> +
> +    my $type = $vga_map->{$vga->{type}};
> +    my $vgamem_mb = $vga->{memory};
> +    if ($qxlnum) {
> +	$type = $id ? 'qxl' : 'qxl-vga';
> +    }
> +    die "no devicetype for $vga->{type}\n" if !$type;
> +
> +    my $memory = "";
> +    if ($vgamem_mb) {
> +	if ($vga->{type} eq 'virtio') {
> +	    my $bytes = PVE::Tools::convert_size($vgamem_mb, "mb" => "b");
> +	    $memory = ",max_hostmem=$bytes";
> +	} elsif ($qxlnum) {
> +	    # from https://www.spice-space.org/multiple-monitors.html
> +	    $memory = ",vgamem_mb=$vga->{memory}";
> +	    my $ram = $vgamem_mb * 4;
> +	    my $vram = $vgamem_mb * 2;
> +	    $memory .= ",ram_size_mb=$ram,vram_size_mb=$vram";
> +	} else {
> +	    $memory = ",vgamem_mb=$vga->{memory}";
> +	}
> +    } elsif ($qxlnum && $id) {
> +	$memory = ",ram_size=67108864,vram_size=33554432";
> +    }
> +
> +    my $q35 = machine_type_is_q35($conf);
> +    my $vgaid = "vga" . ($id // '');
> +    my $pciaddr;
> +    if ($q35 && $vgaid eq 'vga') {
> +	# on is on the pcie.0 bus on q35

made above comment a bit saner ^^

> +	$pciaddr = print_pcie_addr($vgaid, $bridges);
> +    } else {
> +	$pciaddr = print_pci_addr($vgaid, $bridges);
> +    }
> +
> +    return "$type,id=${vgaid}${memory}${pciaddr}";
> +}
> +
>  sub drive_is_cloudinit {
>      my ($drive) = @_;
>      return $drive->{file} =~ m@[:/]vm-\d+-cloudinit(?:\.$QEMU_FORMAT_RE)?$@;
> @@ -2286,6 +2351,15 @@ sub parse_guest_agent {
>      return $res;
>  }
>  
> +sub parse_vga {
> +    my ($value) = @_;
> +
> +    return {} if !$value;
> +    my $res = eval { PVE::JSONSchema::parse_property_string($vga_fmt, $value) };
> +    warn $@ if $@;
> +    return $res;
> +}
> +
>  PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
>  sub verify_usb_device {
>      my ($value, $noerr) = @_;
> @@ -3167,7 +3241,9 @@ sub conf_has_serial {
>  sub vga_conf_has_spice {
>      my ($vga) = @_;
>  
> -    return 0 if !$vga || $vga !~ m/^qxl([234])?$/;
> +    my $vgaconf = parse_vga($vga);
> +    my $vgatype = $vgaconf->{type};
> +    return 0 if !$vgatype || $vgatype !~ m/^qxl([234])?$/;
>  
>      return $1 || 1;
>  }
> @@ -3277,16 +3353,16 @@ sub config_to_command {
>      # add usb controllers
>      my @usbcontrollers = PVE::QemuServer::USB::get_usb_controllers($conf, $bridges, $q35, $usbdesc->{format}, $MAX_USB_DEVICES);
>      push @$devices, @usbcontrollers if @usbcontrollers;
> -    my $vga = $conf->{vga};
> +    my $vga = parse_vga($conf->{vga});
>  
> -    my $qxlnum = vga_conf_has_spice($vga);
> -    $vga = 'qxl' if $qxlnum;
> +    my $qxlnum = vga_conf_has_spice($conf->{vga});
> +    $vga->{type} = 'qxl' if $qxlnum;
>  
> -    if (!$vga) {
> +    if (!$vga->{type}) {
>  	if (qemu_machine_feature_enabled($machine_type, $kvmver, 2, 9)) {
> -	    $vga = (!$winversion || $winversion >= 6) ? 'std' : 'cirrus';
> +	    $vga->{type} = (!$winversion || $winversion >= 6) ? 'std' : 'cirrus';
>  	} else {
> -	    $vga = ($winversion >= 6) ? 'std' : 'cirrus';
> +	    $vga->{type} = ($winversion >= 6) ? 'std' : 'cirrus';
>  	}
>      }
>  
> @@ -3297,7 +3373,7 @@ sub config_to_command {
>      } else {
>  	$tablet = $defaults->{tablet};
>  	$tablet = 0 if $qxlnum; # disable for spice because it is not needed
> -	$tablet = 0 if $vga =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
> +	$tablet = 0 if $vga->{type} =~ m/^serial\d+$/; # disable if we use serial terminal (no vga card)
>      }
>  
>      push @$devices, '-device', print_tabletdevice_full($conf) if $tablet;
> @@ -3325,7 +3401,7 @@ sub config_to_command {
>  	if ($d->{'x-vga'}) {
>  	    $xvga = ',x-vga=on';
>  	    $kvm_off = 1;
> -	    $vga = 'none';
> +	    $vga->{type} = 'none';
>  	    $gpu_passthrough = 1;
>  
>  	    if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
> @@ -3428,12 +3504,12 @@ sub config_to_command {
>  
>      push @$cmd, '-no-reboot' if  defined($conf->{reboot}) && $conf->{reboot} == 0;
>  
> -    push @$cmd, '-vga', $vga if $vga && $vga !~ m/^serial\d+$/; # for kvm 77 and later
> -
> -    if ($vga && $vga !~ m/^serial\d+$/ && $vga ne 'none'){
> +    if ($vga->{type} && $vga->{type} !~ m/^serial\d+$/ && $vga ne 'none'){
> +	push @$devices, '-device', print_vga_device($conf, $vga, undef, $qxlnum, $bridges);
>  	my $socket = vnc_socket($vmid);
>  	push @$cmd,  '-vnc', "unix:$socket,x509,password";
>      } else {
> +	push @$cmd, '-vga', 'none' if $vga->{type} eq 'none';
>  	push @$cmd, '-nographic';
>      }
>  
> @@ -3540,13 +3616,17 @@ sub config_to_command {
>  	if ($qxlnum > 1) {
>  	    if ($winversion){
>  		for(my $i = 1; $i < $qxlnum; $i++){
> -		    my $pciaddr = print_pci_addr("vga$i", $bridges);
> -		    push @$devices, '-device', "qxl,id=vga$i,ram_size=67108864,vram_size=33554432$pciaddr";
> +		    push @$devices, '-device', print_vga_device($conf, $vga, $i, $qxlnum, $bridges);
>  		}
>  	    } else {
>  		# assume other OS works like Linux
> -		push @$cmd, '-global', 'qxl-vga.ram_size=134217728';
> -		push @$cmd, '-global', 'qxl-vga.vram_size=67108864';
> +		my ($ram, $vram) = ("134217728", "67108864");
> +		if ($vga->{memory}) {
> +		    $ram = PVE::Tools::convert_size($qxlnum*4*$vga->{memory}, 'mb' => 'b');
> +		    $vram = PVE::Tools::convert_size($qxlnum*2*$vga->{memory}, 'mb' => 'b');
> +		}
> +		push @$cmd, '-global', "qxl-vga.ram_size=$ram";
> +		push @$cmd, '-global', "qxl-vga.vram_size=$vram";
>  	    }
>  	}
>  
> diff --git a/PVE/QemuServer/PCI.pm b/PVE/QemuServer/PCI.pm
> index 0d9cf24..5ddda4f 100644
> --- a/PVE/QemuServer/PCI.pm
> +++ b/PVE/QemuServer/PCI.pm
> @@ -9,7 +9,7 @@ print_pcie_addr
>  
>  my $devices = {
>      piix3 => { bus => 0, addr => 1 },
> -    #addr2 : first videocard
> +    vga => { bus => 0, addr => 2 },
>      balloon0 => { bus => 0, addr => 3 },
>      watchdog => { bus => 0, addr => 4 },
>      scsihw0 => { bus => 0, addr => 5 },
> @@ -130,6 +130,7 @@ sub print_pcie_addr {
>  
>      my $res = '';
>      my $devices = {
> +	vga => { bus => 'pcie.0', addr => 1 },
>  	hostpci0 => { bus => "ich9-pcie-port-1", addr => 0 },
>  	hostpci1 => { bus => "ich9-pcie-port-2", addr => 0 },
>  	hostpci2 => { bus => "ich9-pcie-port-3", addr => 0 },
> 





More information about the pve-devel mailing list