[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