--- /dev/null
+RELEASE=2.0
+
+# also update debian/changelog
+KVMVER=0.15.0
+KVMPKGREL=1
+
+KVMPACKAGE=pve-qemu-kvm
+KVMDIR=qemu-kvm
+
+ARCH=amd64
+
+KVM_DEB=${KVMPACKAGE}_${KVMVER}-${KVMPKGREL}_${ARCH}.deb
+
+all: ${KVM_DEB} ${KVMDIR}-src.tar.gz
+
+${KVMDIR}.org/README:
+ rm -rf ${KVMDIR}.org
+ git clone git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git ${KVMDIR}.org
+ cd ${KVMDIR}.org; git checkout -b local qemu-kvm-${KVMVER}
+ touch $@
+
+${KVMDIR}-src.tar.gz: ${KVMDIR}.org/README
+ tar czf $@ ${KVMDIR}.org
+
+${KVM_DEB} kvm: ${KVMDIR}.org/README
+ rm -rf ${KVMDIR}
+ cp -a ${KVMDIR}.org ${KVMDIR}
+ cp -a debian ${KVMDIR}/debian
+ cd ${KVMDIR}; dpkg-buildpackage -rfakeroot -us -uc
+ lintian ${KVM_DEB} || true
+
+.PHONY: upload
+upload: ${KVM_DEB} ${KVMDIR}-src.tar.gz
+ umount /pve/${RELEASE}; mount /pve/${RELEASE} -o rw
+ mkdir -p /pve/${RELEASE}/extra
+ mkdir -p /pve/${RELEASE}/install
+ rm -rf /pve/${RELEASE}/extra/Packages*
+ rm -rf /pve/${RELEASE}/extra/${KVMPACKAGE}_*.deb
+ rm -rf /pve/${RELEASE}/install/${KVMDIR}-src.tar.gz
+ cp ${KVM_DEB} /pve/${RELEASE}/extra
+ cp ${KVMDIR}-src.tar.gz /pve/${RELEASE}/install
+ cd /pve/${RELEASE}/extra; dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz
+ umount /pve/${RELEASE}; mount /pve/${RELEASE} -o ro
+
+.PHONY: distclean
+distclean: clean
+ rm -rf ${KVMDIR}.org ${KVMDIR}-src.tar.gz
+
+
+.PHONY: clean
+clean:
+ rm -rf *~ ${KVMDIR} ${KVMPACKAGE}_*
+
+.PHONY: dinstall
+dinstall: ${KVM_DEB}
+ dpkg -i ${KVM_DEB}
--- /dev/null
+pve-qemu-kvm (0.15.0-1) unstable; urgency=low
+
+ * update to upstream 0.15.0
+
+ * depend on libaio1 (--enable-linux-aio)
+
+ * depend on libuuid1 (--enable-uuid)
+
+ * use pxe roms from upstream qemu-kvm
+
+ * do not use --disable-blobs (let qemu-kvm install files, and we remove
+ what we do not need)
+
+ -- Proxmox Support Team <support@proxmox.com> Thu, 11 Aug 2011 10:00:44 +0200
+
+pve-qemu-kvm (0.14.1-1) unstable; urgency=low
+
+ * update to upstream 0.14.1
+
+ * remove enable-ksm.diff patch (newer libc already have those
+ definitions)
+
+ * also install vgabios-qxl.bin vgabios-stdvga.bin vgabios-vmware.bin
+
+ -- Proxmox Support Team <support@proxmox.com> Tue, 21 Jun 2011 06:30:29 +0200
+
+pve-qemu-kvm (0.14.0-1) unstable; urgency=low
+
+ * update to 0.14.0
+
+ * removed kvmtrace (removed from upstream?)
+
+ * add vnc keyboard fixes for fr-ca (reported by Pierre-Yves)
+
+ -- Proxmox Support Team <support@proxmox.com> Fri, 25 Feb 2011 08:17:56 +0100
+
+pve-qemu-kvm (0.13.0-3) unstable; urgency=low
+
+ * fix vnc keyboard altgr/shift emulation
+
+ -- Proxmox Support Team <support@proxmox.com> Tue, 07 Dec 2010 12:45:16 +0100
+
+pve-qemu-kvm (0.13.0-2) unstable; urgency=low
+
+ * do not install unnecessary blobs (manually install blobs, use
+ --disable-blobs)
+
+ * update migration and vnc keymap patches for 0.13.0
+
+ -- Proxmox Support Team <support@proxmox.com> Mon, 25 Oct 2010 13:46:03 +0200
+
+pve-qemu-kvm (0.13.0-1) unstable; urgency=low
+
+ * update to qemu-kvm-0.13.0
+
+ -- Proxmox Support Team <support@proxmox.com> Thu, 21 Oct 2010 13:38:14 +0200
+
+pve-qemu-kvm (0.12.5-2) unstable; urgency=low
+
+ * enable up to 32 NICs (as suggested in the forum)
+
+ -- Proxmox Support Team <support@proxmox.com> Wed, 06 Oct 2010 08:23:07 +0200
+
+pve-qemu-kvm (0.12.5-1) unstable; urgency=low
+
+ * update to qemu-kvm-0.12.5
+
+ -- Proxmox Support Team <support@proxmox.com> Thu, 05 Aug 2010 11:01:56 +0200
+
+pve-qemu-kvm (0.12.4-1) unstable; urgency=low
+
+ * update to qemu-kvm-0.12.4
+
+ -- Proxmox Support Team <support@proxmox.com> Tue, 11 May 2010 08:14:29 +0200
+
+pve-qemu-kvm (0.12.3-1) unstable; urgency=low
+
+ * update to qemu-kvm-0.12.3
+
+ * include gPXE 1.0 network boot
+
+ * remove multicore.diff patch
+
+ * do not install ppc and sparc bios files
+
+ -- Proxmox Support Team <support@proxmox.com> Wed, 14 Apr 2010 13:30:23 +0200
+
+pve-qemu-kvm (0.11.1-2) unstable; urgency=low
+
+ * Use/Include PXE boot ROMs from the Etherboot package
+
+ -- Proxmox Support Team <support@proxmox.com> Tue, 26 Jan 2010 13:28:19 +0100
+
+pve-qemu-kvm (0.11.1-1) unstable; urgency=low
+
+ * update to qemu-kvm-0.11.1
+
+ * cleanup debian rules file
+
+ * install kvmtrace kvmtrace_format and kvm_stat
+
+ * configure with --disable-xen --with-kvm-trace
+
+ * depend on python for scripts
+
+ -- Proxmox Support Team <support@proxmox.com> Mon, 14 Dec 2009 14:44:56 +0100
+
+pve-qemu-kvm (0.11.0-2) stable; urgency=low
+
+ * fix live migration (live-migration-fxes.diff)
+
+ -- Proxmox Support Team <support@proxmox.com> Wed, 30 Sep 2009 11:07:23 +0200
+
+pve-qemu-kvm (0.11.0-1) stable; urgency=low
+
+ * update to stable branch
+
+ * rename packare to pve-qemu-kvm
+
+ -- Proxmox Support Team <support@proxmox.com> Mon, 28 Sep 2009 10:35:05 +0200
+
+pve-kvm (86-4) unstable; urgency=low
+
+ * include multicore patch from amd
+
+ -- Proxmox Support Team <support@proxmox.com> Mon, 14 Sep 2009 10:40:00 +0200
+
+pve-kvm (86-3) unstable; urgency=low
+
+ * fix "i8042.c: No controller found" problem
+
+ -- Proxmox Support Team <support@proxmox.com> Mon, 15 Jun 2009 13:35:57 +0200
+
+pve-kvm (86-2) unstable; urgency=low
+
+ * add CPUID fix: http://git.kernel.org/?p=virt/kvm/qemu-kvm.git;a=commitdiff_plain;h=8fa3b3ce6e
+
+ -- Proxmox Support Team <support@proxmox.com> Tue, 09 Jun 2009 09:50:28 +0200
+
+pve-kvm (86-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Proxmox Support Team <support@proxmox.com> Fri, 22 May 2009 09:16:27 +0200
+
+pve-kvm (85-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Proxmox Support Team <support@proxmox.com> Tue, 28 Apr 2009 07:41:21 +0200
+
+pve-kvm (83-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Proxmox Support Team <support@proxmox.com> Wed, 7 Jan 2009 12:57:02 +0100
+
+pve-kvm (75-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Proxmox Support Team <support@proxmox.com> Thu, 11 Sep 2008 10:03:51 +0200
+
+pve-kvm (74-1) unstable; urgency=low
+
+ * New upstream release
+
+ * added fairsched options
+
+ -- Proxmox Support Team <support@proxmox.com> Thu, 28 Aug 2008 12:40:32 +0200
+
--- /dev/null
+Source: pve-qemu-kvm
+Section: admin
+Priority: extra
+Maintainer: Proxmox Support Team <support@proxmox.com>
+Build-Depends: debhelper (>= 5), autotools-dev, libpci-dev, quilt, texinfo, texi2html, libgnutls-dev, libsdl1.2-dev, check, libaio-dev, uuid-dev
+Standards-Version: 3.7.2
+
+Package: pve-qemu-kvm
+Architecture: any
+Depends: iproute, bridge-utils, python, libsdl1.2debian, libaio1, libuuid1, ${shlibs:Depends}, ${misc:Depends}
+Conflicts: qemu, qemu-kvm, kvm, pve-kvm, pve-qemu-kvm-2.6.18
+Replaces: pve-kvm, pve-qemu-kvm-2.6.18
+Description: Full virtualization on x86 hardware
+ Using KVM, one can run multiple virtual PCs, each running unmodified Linux or
+ Windows images. Each virtual machine has private virtualized hardware: a
+ network card, disk, graphics adapter, etc.
--- /dev/null
+This package was debianized by the proxmox support team <support@proxmox.com>
+
+
+It was downloaded from
+
+git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git
+
+Upstream Author: Fabrice Bellard <fabrice.bellard@free.fr>
+
+Upstream Maintainers: Avi Kivity <avi@redhat.com>
+ Anthony Liguori <aliguori@us.ibm.com>
+
+Copyright: Copyright (C) 2006 Qumranet, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Fabrice Bellard
+
+License:
+
+ QEMU as a whole is released under the GNU General Public License version 2.
+ On Debian systems, the complete text of the GNU General Public License
+ version 2 can be found in the file /usr/share/common-licenses/GPL-2.
+
+ Parts of QEMU have specific licenses which are compatible with the
+ GNU General Public License. Hence each source file contains its own
+ licensing information.
+
+ In particular, the QEMU virtual CPU core library (libqemu.a) is
+ released under the GNU Lesser General Public License version 2 or later.
+ On Debian systems, the complete text of the GNU Lesser General Public
+ License can be found in the file /usr/share/common-licenses/LGPL.
+
+ Some hardware device emulation sources and other QEMU functionality are
+ released under the BSD license, including:
+ * aes, bsd-user, sd, slirp, sys-queue
+
+ On Debian systems, the complete text of the BSD license be found in the
+ file /usr/share/common-licenses/BSD.
+
+ Some hardware device emulation sources and other QEMU functionality are
+ released under the MIT/X11 (BSD-like) license, including:
+ * sdl, host-utils, vnc, keymaps, ioport, usb, hw/*, net, acl, block,
+ kqemu, monitor, curses, readline, vl, savevm, osdep, audio, tcg,
+ qemu-malloc, qemu-img
+
+ The following points clarify the QEMU license:
+ 1) QEMU as a whole is released under the GNU General Public License
+ 2) Parts of QEMU have specific licenses which are compatible with the
+ GNU General Public License. Hence each source file contains its own
+ licensing information.
+ In particular, the QEMU virtual CPU core library (libqemu.a) is
+ released under the GNU Lesser General Public License. Many hardware
+ device emulation sources are released under the BSD license.
+ 3) The Tiny Code Generator (TCG) is released under the BSD license
+ (see license headers in files).
+ 4) QEMU is a trademark of Fabrice Bellard.
+ -- Fabrice Bellard.
+
+ BIOS sources in QEMU:
+ bios.bin: Copyright (C) 2002 MandrakeSoft S.A. and others. This file
+ is licensed under the GNU LGPL, version 2, or (at your option) any later
+ version.
+ Homepage: http://sourceforge.net/projects/bochs
+
+ vgabios.bin and vgabios-cirrus.bin: (C) 2003 the LGPL VGABios
+ developers Team. These files are licensed under the GNU LGPL, version 2,
+ or (at your option) any later version.
+ Homepage: http://savannah.nongnu.org/projects/vgabios
--- /dev/null
+#!/bin/sh
+
+exit 0
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+switch=$(/sbin/ip route list | awk '/^default / { print $NF }')
+/sbin/ifconfig $1 0.0.0.0 promisc up
+/usr/sbin/brctl addif ${switch} $1
--- /dev/null
+Index: kvm-86/configure
+===================================================================
+--- kvm-86.orig/configure 2009-05-22 09:47:55.000000000 +0200
++++ kvm-86/configure 2009-05-22 09:48:26.000000000 +0200
+@@ -1393,8 +1393,8 @@
+ prefix="/usr/local"
+ fi
+ mansuffix="/share/man"
+- datasuffix="/share/qemu"
+- docsuffix="/share/doc/qemu"
++ datasuffix="/share/kvm"
++ docsuffix="/share/doc/pve-qemu-kvm"
+ binsuffix="/bin"
+ fi
+
+Index: kvm-86/net.h
+===================================================================
+--- kvm-86.orig/net.h 2009-05-22 09:47:48.000000000 +0200
++++ kvm-86/net.h 2009-05-22 09:48:26.000000000 +0200
+@@ -124,8 +124,8 @@
+ void net_host_device_add(Monitor *mon, const char *device, const char *opts);
+ void net_host_device_remove(Monitor *mon, int vlan_id, const char *device);
+
+-#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+-#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
++#define DEFAULT_NETWORK_SCRIPT "/etc/kvm/kvm-ifup"
++#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/kvm/kvm-ifdown"
+ #ifdef __sun__
+ #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+ #else
--- /dev/null
+see http://git.kernel.org/?p=virt/kvm/qemu-kvm.git;a=commitdiff;h=8fa3b3ce6e#patch1
+
+KVM_GET_SUPPORTED_CPUID has been known to fail to return -E2BIG
+when it runs out of entries. Detect this by always trying again
+with a bigger table if the ioctl() fills the table.
+
+--- a/kvm/libkvm/libkvm-x86.c
++++ b/kvm/libkvm/libkvm-x86.c
+@@ -575,6 +575,8 @@ static struct kvm_cpuid2 *try_get_cpuid(kvm_context_t kvm, int max)
+ r = ioctl(kvm->fd, KVM_GET_SUPPORTED_CPUID, cpuid);
+ if (r == -1)
+ r = -errno;
++ else if (r == 0 && cpuid->nent >= max)
++ r = -E2BIG;
+ if (r < 0) {
+ if (r == -E2BIG) {
+ free(cpuid);
+
--- /dev/null
+From: Izik Eidus <ieidus@redhat.com>
+Date: Thu, 8 Oct 2009 14:39:39 +0000 (+0200)
+Subject: ksm support
+X-Git-Url: http://git.kernel.org/?p=virt%2Fkvm%2Fqemu-kvm.git;a=commitdiff_plain;h=ccb167e9d7d460a7cd09fdabd848efd3606dd27e
+
+ksm support
+
+patch is slighly modified by <support@proxmox.com> for old libc
+
+Call MADV_MERGEABLE on guest memory allocations. MADV_MERGABLE will be
+available starting in Linux 2.6.32. This system call registers a region of
+virtual address space with Linux as a candidate for transparent memory
+sharing.
+
+Patchworks-ID: 35447
+Signed-off-by: Izik Eidus <ieidus@redhat.com>
+Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
+---
+
+Index: qemu-kvm/exec.c
+===================================================================
+--- qemu-kvm.orig/exec.c 2009-12-21 10:37:57.000000000 +0100
++++ qemu-kvm/exec.c 2009-12-21 11:22:34.000000000 +0100
+@@ -48,6 +48,9 @@
+ #include <qemu.h>
+ #endif
+
++/* our libc does not define it */
++#define MADV_MERGEABLE 12
++
+ //#define DEBUG_TB_INVALIDATE
+ //#define DEBUG_FLUSH
+ //#define DEBUG_TLB
--- /dev/null
+Index: qemu-kvm/qemu-options.hx
+===================================================================
+--- qemu-kvm.orig/qemu-options.hx 2009-12-21 10:37:57.000000000 +0100
++++ qemu-kvm/qemu-options.hx 2009-12-21 10:41:25.000000000 +0100
+@@ -66,6 +66,12 @@
+ are split equally.
+ ETEXI
+
++DEF("id", HAS_ARG, QEMU_OPTION_id,
++ "-id n set the faisched ID\n")
++
++DEF("cpuunits", HAS_ARG, QEMU_OPTION_cpuunits,
++ "-cpuuinits n set fairsched cpu units\n")
++
+ DEF("fda", HAS_ARG, QEMU_OPTION_fda,
+ "-fda/-fdb file use 'file' as floppy disk 0/1 image\n")
+ DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "")
+Index: qemu-kvm/vl.c
+===================================================================
+--- qemu-kvm.orig/vl.c 2009-12-21 10:37:58.000000000 +0100
++++ qemu-kvm/vl.c 2009-12-21 10:42:50.000000000 +0100
+@@ -159,6 +159,7 @@
+ #include "qemu-objects.h"
+ #include "qemu-kvm.h"
+ #include "hw/device-assignment.h"
++#include "vzsyscalls.h"
+
+ #include "disas.h"
+
+@@ -224,6 +225,7 @@
+ int max_cpus = 0;
+ int smp_cores = 1;
+ int smp_threads = 1;
++int fairsched_id = 0;
+ const char *vnc_display;
+ int acpi_enabled = 1;
+ #ifdef TARGET_I386
+@@ -363,7 +365,7 @@
+ prctl(PR_SET_NAME, name);
+ #endif
+ }
+-
++
+ /***************/
+ /* ballooning */
+
+@@ -4897,6 +4899,7 @@
+ const char *gdbstub_dev = NULL;
+ uint32_t boot_devices_bitmap = 0;
+ int i;
++ int cpuunits = 0;
+ int snapshot, linux_boot, net_boot;
+ const char *initrd_filename;
+ const char *kernel_filename, *kernel_cmdline;
+@@ -5550,6 +5553,20 @@
+ exit(1);
+ }
+ break;
++ case QEMU_OPTION_id:
++ fairsched_id = atoi(optarg);
++ if (fairsched_id < 100 || fairsched_id >= 1000000) {
++ fprintf(stderr, "Invalid ID\n");
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_cpuunits:
++ cpuunits = atoi(optarg);
++ if (cpuunits < 8 || cpuunits > 500000) {
++ fprintf(stderr, "Invalid value for cpuunits\n");
++ exit(1);
++ }
++ break;
+ case QEMU_OPTION_vnc:
+ display_type = DT_VNC;
+ vnc_display = optarg;
+@@ -5947,6 +5964,39 @@
+ if (ram_size == 0)
+ ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+
++ if (cpuunits && !fairsched_id) {
++ fprintf(stderr, "cpuunits specified without -id");
++ exit (1);
++ }
++
++ if (fairsched_id) {
++ int ret;
++ int weight = cpuunits ? 500000/cpuunits : 500;
++ pid_t cpid = getpid();
++
++ ret = syscall(__NR_fairsched_rmnod, fairsched_id);
++ if (ret == -EBUSY) {
++ fprintf (stderr, "unable to create fairsched node - still in use\n");
++ exit(1);
++ }
++
++ ret = syscall(__NR_fairsched_mknod, 0, weight, fairsched_id);
++ if (ret != fairsched_id) {
++ fprintf (stderr, "unable to create fairsched node\n");
++ exit(1);
++ }
++
++ ret = syscall(__NR_fairsched_mvpr, cpid, fairsched_id);
++ if (ret != 0) {
++ fprintf (stderr, "unable to move procces to fairsched group");
++ exit (1);
++ }
++
++ /* note: we can never remove ourself from the group, so the empty group
++ will exist after we finish
++ */
++ }
++
+ /* init the dynamic translator */
+ cpu_exec_init_all(tb_size * 1024 * 1024);
+
+Index: qemu-kvm/vzsyscalls.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ qemu-kvm/vzsyscalls.h 2009-12-21 10:41:25.000000000 +0100
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2000-2008, Parallels, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VZSYSCALLS_H_
++#define _VZSYSCALLS_H_
++
++#include <sys/syscall.h>
++
++#ifdef __x86_64__
++#define __NR_fairsched_vcpus 499
++#define __NR_setluid 501
++#define __NR_setublimit 502
++#define __NR_fairsched_mknod 504
++#define __NR_fairsched_rmnod 505
++#define __NR_fairsched_chwt 506
++#define __NR_fairsched_mvpr 507
++#define __NR_fairsched_rate 508
++#define __NR_ioprio_set 251
++#elif defined(__i386__)
++#define __NR_fairsched_mknod 500
++#define __NR_fairsched_rmnod 501
++#define __NR_fairsched_chwt 502
++#define __NR_fairsched_mvpr 503
++#define __NR_fairsched_rate 504
++#define __NR_fairsched_vcpus 505
++#define __NR_setluid 511
++#define __NR_setublimit 512
++#define __NR_ioprio_set 289
++#else
++#error "no syscall for this arch"
++#endif
++
++#endif
--- /dev/null
+Index: kvm-86/curses.c
+===================================================================
+--- kvm-86.orig/curses.c 2009-05-22 10:09:19.000000000 +0200
++++ kvm-86/curses.c 2009-05-22 10:10:38.000000000 +0200
+@@ -238,7 +238,11 @@
+ keysym = chr;
+
+ keycode &= ~KEY_MASK;
+- keycode |= keysym2scancode(kbd_layout, keysym);
++
++ keydata_t *kd = find_keysym(kbd_layout, keysym);
++ if (kd) {
++ keycode |= kd->keycode;
++ }
+ }
+
+ if (is_graphic_console()) {
+Index: kvm-86/keymaps.c
+===================================================================
+--- kvm-86.orig/keymaps.c 2009-05-22 10:09:24.000000000 +0200
++++ kvm-86/keymaps.c 2009-05-22 10:10:38.000000000 +0200
+@@ -67,6 +67,7 @@
+ char file_name[1024];
+ char line[1024];
+ int len;
++ int upper;
+
+ snprintf(file_name, sizeof(file_name),
+ "%s/keymaps/%s", bios_dir, language);
+@@ -97,25 +98,66 @@
+ if (*end_of_keysym) {
+ int keysym;
+ *end_of_keysym = 0;
++ uint8_t keymod;
++ int deadsym;
++
++ keymod = 0;
++ deadsym = 0;
++ upper = 0;
++redo:
++ if (upper==1){
++ char *c;
++ for(c=line;*c;c++)
++ *c=toupper(*c);
++ keymod |= KEYMOD_SHIFT;
++ upper++;
++ }
++
+ keysym = get_keysym(table, line);
+ if (keysym == 0) {
+ // fprintf(stderr, "Warning: unknown keysym %s\n", line);
+ } else {
+ const char *rest = end_of_keysym + 1;
+ char *rest2;
++ char *modifier;
+ int keycode = strtol(rest, &rest2, 0);
+
+- if (rest && strstr(rest, "numlock")) {
+- add_to_key_range(&k->keypad_range, keycode);
+- add_to_key_range(&k->numlock_range, keysym);
+- //fprintf(stderr, "keypad keysym %04x keycode %d\n", keysym, keycode);
++ modifier = strtok (rest2, " ");
++ while (modifier != NULL) {
++ if (!strcmp(modifier, "shift")) {
++ keymod |= KEYMOD_SHIFT;
++ } else
++ if (!strcmp(modifier, "addupper")) {
++ upper++;
++ } else
++ if (!strcmp(modifier, "ctrl")) {
++ keymod |= KEYMOD_CTRL;
++ } else
++ if (!strcmp(modifier, "alt")) {
++ keymod |= KEYMOD_ALT;
++ } else
++ if (!strcmp(modifier, "altgr")) {
++ keymod |= KEYMOD_ALTGR;
++ } else
++ if (!strncmp(modifier, "dead_",5)) {
++ keymod |= KEYMOD_DEAD;
++ deadsym = get_keysym(table, modifier);
++ } else
++ if (!strcmp(modifier, "numlock")) {
++ add_to_key_range(&k->keypad_range, keycode);
++ add_to_key_range(&k->numlock_range, keysym);
++ //fprintf(stderr, "keypad keysym %04x keycode %d\n", keysym, keycode);
++ }
++ modifier = strtok (NULL," ");
+ }
+
+ /* if(keycode&0x80)
+ keycode=(keycode<<8)^0x80e0; */
+ if (keysym < MAX_NORMAL_KEYCODE) {
+ //fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode);
+- k->keysym2keycode[keysym] = keycode;
++ k->keysym2keycode[keysym].keycode = keycode;
++ k->keysym2keycode[keysym].keymod = keymod;
++ k->keysym2keycode[keysym].deadsym = deadsym;
+ } else {
+ if (k->extra_count >= MAX_EXTRA_COUNT) {
+ fprintf(stderr,
+@@ -128,11 +170,18 @@
+ #endif
+ k->keysym2keycode_extra[k->extra_count].
+ keysym = keysym;
+- k->keysym2keycode_extra[k->extra_count].
+- keycode = keycode;
++ k->keysym2keycode_extra[k->extra_count].kdata.
++ keycode = keycode;
++ k->keysym2keycode_extra[k->extra_count].kdata.
++ keymod = keymod;
++ k->keysym2keycode_extra[k->extra_count].kdata.
++ deadsym = deadsym;
++
+ k->extra_count++;
+ }
+ }
++ if (upper==1)
++ goto redo;
+ }
+ }
+ }
+@@ -148,14 +197,11 @@
+ }
+
+
+-int keysym2scancode(void *kbd_layout, int keysym)
++keydata_t *find_keysym(void *kbd_layout, int keysym)
+ {
+ kbd_layout_t *k = kbd_layout;
+ if (keysym < MAX_NORMAL_KEYCODE) {
+- if (k->keysym2keycode[keysym] == 0)
+- fprintf(stderr, "Warning: no scancode found for keysym %d\n",
+- keysym);
+- return k->keysym2keycode[keysym];
++ return &k->keysym2keycode[keysym];
+ } else {
+ int i;
+ #ifdef XK_ISO_Left_Tab
+@@ -163,10 +209,10 @@
+ keysym = XK_Tab;
+ #endif
+ for (i = 0; i < k->extra_count; i++)
+- if (k->keysym2keycode_extra[i].keysym == keysym)
+- return k->keysym2keycode_extra[i].keycode;
++ if (k->keysym2keycode_extra[i].keysym == keysym)
++ return &k->keysym2keycode_extra[i].kdata;
+ }
+- return 0;
++ return NULL;
+ }
+
+ int keycode_is_keypad(void *kbd_layout, int keycode)
+Index: kvm-86/keymaps.h
+===================================================================
+--- kvm-86.orig/keymaps.h 2009-05-22 10:09:32.000000000 +0200
++++ kvm-86/keymaps.h 2009-05-22 10:10:38.000000000 +0200
+@@ -38,13 +38,26 @@
+ struct key_range *next;
+ };
+
++#define KEYMOD_SHIFT 0x01
++#define KEYMOD_CTRL 0x02
++#define KEYMOD_ALT 0x04
++#define KEYMOD_DEAD 0x08
++#define KEYMOD_ALTGR 0x10
++
+ #define MAX_NORMAL_KEYCODE 512
+ #define MAX_EXTRA_COUNT 256
++
++typedef struct {
++ uint16_t keycode;
++ uint8_t keymod;
++ int deadsym;
++} keydata_t;
++
+ typedef struct {
+- uint16_t keysym2keycode[MAX_NORMAL_KEYCODE];
++ keydata_t keysym2keycode[MAX_NORMAL_KEYCODE];
+ struct {
+ int keysym;
+- uint16_t keycode;
++ keydata_t kdata;
+ } keysym2keycode_extra[MAX_EXTRA_COUNT];
+ int extra_count;
+ struct key_range *keypad_range;
+@@ -53,7 +66,7 @@
+
+
+ void *init_keyboard_layout(const name2keysym_t *table, const char *language);
+-int keysym2scancode(void *kbd_layout, int keysym);
++keydata_t *find_keysym(void *kbd_layout, int keysym);
+ int keycode_is_keypad(void *kbd_layout, int keycode);
+ int keysym_is_numlock(void *kbd_layout, int keysym);
+
+Index: kvm-86/sdl.c
+===================================================================
+--- kvm-86.orig/sdl.c 2009-05-22 10:09:43.000000000 +0200
++++ kvm-86/sdl.c 2009-05-22 10:10:38.000000000 +0200
+@@ -214,7 +214,11 @@
+ if (keysym == 92 && ev->keysym.scancode == 133) {
+ keysym = 0xa5;
+ }
+- return keysym2scancode(kbd_layout, keysym);
++ keydata_t *kd = find_keysym(kbd_layout, keysym);
++ if (kd==NULL)
++ return 0;
++ else
++ return kd->keycode;
+ }
+
+ /* specific keyboard conversions from scan codes */
+Index: kvm-86/vnc.c
+===================================================================
+--- kvm-86.orig/vnc.c 2009-05-22 10:09:54.000000000 +0200
++++ kvm-86/vnc.c 2009-05-22 10:10:38.000000000 +0200
+@@ -1257,27 +1257,85 @@
+ check_pointer_type_change(vs, kbd_mouse_is_absolute());
+ }
+
++static void do_keycode(int keycode, int down)
++{
++ // fprintf (stderr, "KEY: %04x %d\n", keycode, down);
++ if (keycode & 0x80)
++ kbd_put_keycode(0xe0);
++ if (down)
++ kbd_put_keycode(keycode & 0x7f);
++ else
++ kbd_put_keycode(keycode | 0x80);
++}
++
++static void do_modifier(VncState *vs, int keycode, int down, int level)
++{
++ do_keycode(keycode, down);
++ vs->modifiers_state[level][keycode] = down;
++ if (level==0) {
++ vs->modifiers_state[1][keycode] = down;
++ }
++}
++
+ static void reset_keys(VncState *vs)
+ {
+ int i;
+ for(i = 0; i < 256; i++) {
+- if (vs->modifiers_state[i]) {
+- if (i & 0x80)
+- kbd_put_keycode(0xe0);
+- kbd_put_keycode(i | 0x80);
+- vs->modifiers_state[i] = 0;
++ if (vs->modifiers_state[0][i]) {
++ do_modifier (vs, i, 0, 0);
++ }
++ }
++}
++
++static void set_modifiers(VncState *vs, uint8_t reqstate, int down, int full)
++{
++ modifier_t *m;
++ for(m=test_modifier; m->bit; m++) {
++ int requested = reqstate & m->bit;
++ /* Release unwanted modifiers */
++ if (!down || full) {
++ if (vs->modifiers_state[1][m->keycode] && !requested)
++ do_modifier(vs, m->keycode, 0, 1);
++ }
++ /* Press desired modifiers */
++ if (down || full) {
++ int already_set = vs->modifiers_state[1][m->keycode];
++ if (!already_set && requested)
++ do_modifier(vs, m->keycode, 1, 1);
+ }
+ }
+ }
+
++static void restore_modifiers(VncState *vs)
++{
++ /* Restore modifiers from reference */
++ modifier_t *m;
++ for(m=test_modifier; m->bit; m++) {
++ if (vs->modifiers_state[0][m->keycode] !=
++ vs->modifiers_state[1][m->keycode])
++ do_modifier(vs, m->keycode, vs->modifiers_state[0][m->keycode], 0);
++ }
++}
+ static void press_key(VncState *vs, int keysym)
+ {
+- kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) & 0x7f);
+- kbd_put_keycode(keysym2scancode(vs->vd->kbd_layout, keysym) | 0x80);
++ keydata_t *kd = find_keysym(vs->vd->kbd_layout, keysym & 0xFFFF);
++ if (kd==NULL)
++ return;
++
++ kbd_put_keycode(kd->keycode & 0x7f);
++ kbd_put_keycode(kd->keycode | 0x80);
+ }
+
+-static void do_key_event(VncState *vs, int down, int keycode, int sym)
++static void do_key_event(VncState *vs, int down, keydata_t *kd, int sym)
+ {
++ if (kd==NULL)
++ return;
++
++ int keycode = kd->keycode;
++ //fprintf (stderr, "SYM: %04x SCANCODE: %04x MOD %04x\n",
++ // sym, keycode, kd->keymod);
++
++
+ /* QEMU console switch */
+ switch(keycode) {
+ case 0x2a: /* Left Shift */
+@@ -1286,23 +1344,24 @@
+ case 0x9d: /* Right CTRL */
+ case 0x38: /* Left ALT */
+ case 0xb8: /* Right ALT */
+- if (down)
+- vs->modifiers_state[keycode] = 1;
+- else
+- vs->modifiers_state[keycode] = 0;
+- break;
++ do_modifier(vs, keycode, down, 0);
++ return;
+ case 0x02 ... 0x0a: /* '1' to '9' keys */
+- if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
++ if (down && vs->modifiers_state[0][0x1d] && vs->modifiers_state[0][0x38]) {
+ /* Reset the modifiers sent to the current console */
+ reset_keys(vs);
+ console_select(keycode - 0x02);
+ return;
+ }
+ break;
+- case 0x3a: /* CapsLock */
+- case 0x45: /* NumLock */
+- if (!down)
+- vs->modifiers_state[keycode] ^= 1;
++ case 0x3a: /* CapsLock */
++ case 0x45: /* NumLock */
++ if (!down) {
++ if (vs->modifiers_state[0][0x45])
++ do_modifier(vs, keycode, 0, 0);
++ else
++ do_modifier(vs, keycode, 1, 0);
++ }
+ break;
+ }
+
+@@ -1312,25 +1371,42 @@
+ toggles numlock away from the VNC window.
+ */
+ if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
+- if (!vs->modifiers_state[0x45]) {
+- vs->modifiers_state[0x45] = 1;
++ if (!vs->modifiers_state[0][0x45]) {
++ do_modifier(vs, 0x45, 1, 0);
+ press_key(vs, 0xff7f);
+ }
+ } else {
+- if (vs->modifiers_state[0x45]) {
+- vs->modifiers_state[0x45] = 0;
+- press_key(vs, 0xff7f);
++ if (vs->modifiers_state[0][0x45]) {
++ do_modifier(vs, 0x45, 0, 0);
++ press_key(vs, 0xff7f);
+ }
+ }
+ }
+
+ if (is_graphic_console()) {
+- if (keycode & 0x80)
+- kbd_put_keycode(0xe0);
+- if (down)
+- kbd_put_keycode(keycode & 0x7f);
+- else
+- kbd_put_keycode(keycode | 0x80);
++ if (down) {
++ /* Send deadkey */
++ if (kd->keymod & KEYMOD_DEAD) {
++ keydata_t *deaddata;
++ deaddata = find_keysym(vs->vd->kbd_layout, kd->deadsym);
++ if (deaddata != NULL) {
++ set_modifiers(vs, deaddata->keymod, 0, 1);
++ do_keycode(deaddata->keycode, 1);
++ do_keycode(deaddata->keycode, 0);
++ restore_modifiers(vs);
++ }
++ }
++ set_modifiers(vs, kd->keymod, 1, 0);
++ } else
++ restore_modifiers(vs);
++
++ do_keycode (keycode, down);
++
++ /* vnc never sends ALTGR, so we create an artificial up event */
++ if (down && (kd->keymod & KEYMOD_ALTGR)) {
++ set_modifiers(vs, kd->keymod, 0, 0);
++ }
++
+ } else {
+ /* QEMU console emulation */
+ if (down) {
+@@ -1388,13 +1464,9 @@
+
+ static void key_event(VncState *vs, int down, uint32_t sym)
+ {
+- int keycode;
+-
+- if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
+- sym = sym - 'A' + 'a';
++ keydata_t *kd = find_keysym(vs->vd->kbd_layout, sym & 0xFFFF);
+
+- keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF);
+- do_key_event(vs, down, keycode, sym);
++ do_key_event(vs, down, kd, sym & 0xFFFF);
+ }
+
+ static void ext_key_event(VncState *vs, int down,
+@@ -1403,8 +1475,15 @@
+ /* if the user specifies a keyboard layout, always use it */
+ if (keyboard_layout)
+ key_event(vs, down, sym);
+- else
+- do_key_event(vs, down, keycode, sym);
++ else {
++ keydata_t kd;
++
++ kd.keycode = keycode;
++ kd.keymod = 0;
++ kd.deadsym = 0;
++
++ do_key_event(vs, down, &kd, sym & 0xFFFF);
++ }
+ }
+
+ static void framebuffer_update_request(VncState *vs, int incremental,
+Index: kvm-86/vnc.h
+===================================================================
+--- kvm-86.orig/vnc.h 2009-05-22 10:10:08.000000000 +0200
++++ kvm-86/vnc.h 2009-05-22 10:10:38.000000000 +0200
+@@ -49,6 +49,21 @@
+ *
+ *****************************************************************************/
+
++typedef struct {
++ int keycode;
++ int bit;
++} modifier_t;
++
++static modifier_t test_modifier[]={
++ {0x2a, KEYMOD_SHIFT},
++ {0x36, KEYMOD_SHIFT},
++ {0x1d, KEYMOD_CTRL},
++ {0x9d, KEYMOD_CTRL},
++ {0x38, KEYMOD_ALT},
++ {0xb8, KEYMOD_ALTGR},
++ {0,0},
++};
++
+ typedef struct Buffer
+ {
+ size_t capacity;
+@@ -156,7 +171,7 @@
+ VncReadEvent *read_handler;
+ size_t read_handler_expect;
+ /* input */
+- uint8_t modifiers_state[256];
++ uint8_t modifiers_state[2][256];
+
+ Buffer zlib;
+ Buffer zlib_tmp;
--- /dev/null
+Index: qemu-kvm/vl.c
+===================================================================
+--- qemu-kvm.orig/vl.c 2009-09-30 10:35:45.000000000 +0200
++++ qemu-kvm/vl.c 2009-09-30 10:47:05.000000000 +0200
+@@ -3175,9 +3175,10 @@
+ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
+ {
+ ram_addr_t addr;
+- uint64_t bytes_transferred_last;
+ double bwidth = 0;
+ uint64_t expected_time = 0;
++ static int64_t starttime = 0;
++ double timediff;
+
+ if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
+ qemu_file_set_error(f);
+@@ -3195,10 +3196,9 @@
+ cpu_physical_memory_set_dirty_tracking(1);
+
+ qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
+- }
+
+- bytes_transferred_last = bytes_transferred;
+- bwidth = get_clock();
++ starttime = get_clock();
++ }
+
+ while (!qemu_file_rate_limit(f)) {
+ int ret;
+@@ -3209,8 +3209,8 @@
+ break;
+ }
+
+- bwidth = get_clock() - bwidth;
+- bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
++ timediff = get_clock() - starttime;
++ bwidth = bytes_transferred / timediff;
+
+ /* if we haven't transferred anything this round, force expected_time to a
+ * a very high value, but without crashing */
+@@ -3230,6 +3230,10 @@
+
+ qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
+
++ if ((stage == 2) && (bytes_transferred > 2*ram_bytes_total())) {
++ return 1;
++ }
++
+ expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
+
+ return (stage == 2) && (expected_time <= migrate_max_downtime());
--- /dev/null
+Index: kvm-86/cpu-defs.h
+===================================================================
+--- kvm-86.orig/cpu-defs.h 2009-09-24 14:19:14.000000000 +0200
++++ kvm-86/cpu-defs.h 2009-09-24 14:47:00.000000000 +0200
+@@ -194,6 +194,8 @@
+ int cpu_index; /* CPU index (informative) */ \
+ uint32_t host_tid; /* host thread ID */ \
+ int numa_node; /* NUMA node this cpu is belonging to */ \
++ int nr_cores; /* number of cores within this CPU package */ \
++ int nr_threads;/* number of threads within this CPU */ \
+ int running; /* Nonzero if cpu is currently running(usermode). */ \
+ int thread_id; \
+ /* user data */ \
+Index: kvm-86/target-i386/helper.c
+===================================================================
+--- kvm-86.orig/target-i386/helper.c 2009-09-24 14:19:14.000000000 +0200
++++ kvm-86/target-i386/helper.c 2009-09-24 14:50:18.000000000 +0200
+@@ -121,7 +121,7 @@
+ #ifdef TARGET_X86_64
+ {
+ .name = "qemu64",
+- .level = 2,
++ .level = 4,
+ .vendor1 = CPUID_VENDOR_AMD_1,
+ .vendor2 = CPUID_VENDOR_AMD_2,
+ .vendor3 = CPUID_VENDOR_AMD_3,
+@@ -192,7 +192,7 @@
+ #endif
+ {
+ .name = "qemu32",
+- .level = 2,
++ .level = 4,
+ .family = 6,
+ .model = 3,
+ .stepping = 3,
+@@ -1638,6 +1638,12 @@
+ *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+ *ecx = env->cpuid_ext_features;
+ *edx = env->cpuid_features;
++
++ if (env->nr_cores * env->nr_threads > 1) {
++ *ebx |= (env->nr_cores * env->nr_threads) << 16;
++ *edx |= 1 << 28; /* HTT bit */
++ }
++
+ break;
+ case 2:
+ /* cache info: needed for Pentium Pro compatibility */
+@@ -1648,21 +1654,29 @@
+ break;
+ case 4:
+ /* cache info: needed for Core compatibility */
++ if (env->nr_cores > 1) {
++ *eax = (env->nr_cores - 1) << 26;
++ } else {
++ *eax = 0;
++ }
+ switch (count) {
+ case 0: /* L1 dcache info */
+- *eax = 0x0000121;
++ *eax |= 0x0000121;
+ *ebx = 0x1c0003f;
+ *ecx = 0x000003f;
+ *edx = 0x0000001;
+ break;
+ case 1: /* L1 icache info */
+- *eax = 0x0000122;
++ *eax |= 0x0000122;
+ *ebx = 0x1c0003f;
+ *ecx = 0x000003f;
+ *edx = 0x0000001;
+ break;
+ case 2: /* L2 cache info */
+- *eax = 0x0000143;
++ *eax |= 0x0000143;
++ if (env->nr_threads > 1) {
++ *eax |= (env->nr_threads - 1) << 14;
++ }
+ *ebx = 0x3c0003f;
+ *ecx = 0x0000fff;
+ *edx = 0x0000001;
+@@ -1715,6 +1729,16 @@
+ *ecx = env->cpuid_ext3_features;
+ *edx = env->cpuid_ext2_features;
+
++ if (env->nr_cores * env->nr_threads > 1) {
++ uint32_t teax, tebx, tecx, tedx;
++ cpu_x86_cpuid(env, 0, 0, &teax, &tebx, &tecx, &tedx);
++ if ( tebx == CPUID_VENDOR_AMD_1 &&
++ tedx == CPUID_VENDOR_AMD_2 &&
++ tecx == CPUID_VENDOR_AMD_3) {
++ *ecx |= 1 << 1; /* CmpLegacy bit */
++ }
++ }
++
+ if (kvm_enabled()) {
+ uint32_t h_eax, h_edx;
+
+@@ -1790,6 +1814,9 @@
+ *ebx = 0;
+ *ecx = 0;
+ *edx = 0;
++ if (env->nr_cores * env->nr_threads > 1) {
++ *ecx |= (env->nr_cores * env->nr_threads) - 1;
++ }
+ break;
+ case 0x8000000A:
+ *eax = 0x00000001; /* SVM Revision */
+Index: kvm-86/vl.c
+===================================================================
+--- kvm-86.orig/vl.c 2009-09-24 14:30:14.000000000 +0200
++++ kvm-86/vl.c 2009-09-24 14:47:00.000000000 +0200
+@@ -230,6 +230,8 @@
+ const char *assigned_devices[MAX_DEV_ASSIGN_CMDLINE];
+ int assigned_devices_index;
+ int smp_cpus = 1;
++int smp_cores = 1;
++int smp_threads = 1;
+ int fairsched_id = 0;
+ const char *vnc_display;
+ int acpi_enabled = 1;
+@@ -2499,6 +2501,52 @@
+ return;
+ }
+
++static void smp_parse(const char *optarg)
++{
++ int smp, sockets = 0, threads = 0, cores = 0;
++ char *endptr;
++ char option[128];
++
++ smp = strtoul(optarg, &endptr, 10);
++ if (endptr != optarg) {
++ if (*endptr == ',') {
++ endptr++;
++ }
++ }
++ if (get_param_value(option, 128, "sockets", endptr) != 0)
++ sockets = strtoull(option, NULL, 10);
++ if (get_param_value(option, 128, "cores", endptr) != 0)
++ cores = strtoull(option, NULL, 10);
++ if (get_param_value(option, 128, "threads", endptr) != 0)
++ threads = strtoull(option, NULL, 10);
++
++ /* compute missing values, prefer sockets over cores over threads */
++ if (smp == 0 || sockets == 0) {
++ sockets = sockets > 0 ? sockets : 1;
++ cores = cores > 0 ? cores : 1;
++ threads = threads > 0 ? threads : 1;
++ if (smp == 0) {
++ smp = cores * threads * sockets;
++ } else {
++ sockets = smp / (cores * threads);
++ }
++ } else {
++ if (cores == 0) {
++ threads = threads > 0 ? threads : 1;
++ cores = smp / (sockets * threads);
++ } else {
++ if (sockets == 0) {
++ sockets = smp / (cores * threads);
++ } else {
++ threads = smp / (cores * sockets);
++ }
++ }
++ }
++ smp_cpus = smp;
++ smp_cores = cores > 0 ? cores : 1;
++ smp_threads = threads > 0 ? threads : 1;
++}
++
+ /***********************************************************/
+ /* USB devices */
+
+@@ -3727,6 +3775,8 @@
+
+ if (kvm_enabled())
+ kvm_init_vcpu(env);
++ env->nr_cores = smp_cores;
++ env->nr_threads = smp_threads;
+ return;
+ }
+
+@@ -4060,6 +4110,8 @@
+ kvm_start_vcpu(env);
+ else
+ tcg_init_vcpu(env);
++ env->nr_cores = smp_cores;
++ env->nr_threads = smp_threads;
+ }
+
+ void qemu_notify_event(void)
+@@ -5560,7 +5612,7 @@
+ usb_devices_index++;
+ break;
+ case QEMU_OPTION_smp:
+- smp_cpus = atoi(optarg);
++ smp_parse(optarg);
+ if (smp_cpus < 1) {
+ fprintf(stderr, "Invalid number of CPUs\n");
+ exit(1);
--- /dev/null
+
+bug description: boot a guest, open VNC console, and when it's still in BIOS / bootloader sequence, type as many keys as you can, move your mouse as much as you can. If needed, just reboot the guest.
+
+Linux guest will boot with "i8042.c: No controller found" and no keyboard.
+
+Further discussion seem to lead to a conclusion that there is some obscure bug in Qemu BIOS which makes this problem visible.
+
+Index: kvm-86/hw/ps2.c
+===================================================================
+--- kvm-86.orig/hw/ps2.c 2009-06-15 13:31:24.000000000 +0200
++++ kvm-86/hw/ps2.c 2009-06-15 13:31:50.000000000 +0200
+@@ -70,7 +70,7 @@
+ #define MOUSE_STATUS_ENABLED 0x20
+ #define MOUSE_STATUS_SCALE21 0x10
+
+-#define PS2_QUEUE_SIZE 256
++#define PS2_QUEUE_SIZE 15
+
+ typedef struct {
+ uint8_t data[PS2_QUEUE_SIZE];
--- /dev/null
+adjust-path.diff
+fairsched.diff
+vncticket.diff
+#keymap.diff
+#multicore.diff
+live-migration-fixes.diff
+enable-ksm.diff
--- /dev/null
+Index: qemu-kvm/console.h
+===================================================================
+--- qemu-kvm.orig/console.h 2009-12-21 10:37:57.000000000 +0100
++++ qemu-kvm/console.h 2009-12-21 10:45:29.000000000 +0100
+@@ -322,7 +322,7 @@
+ void vnc_display_init(DisplayState *ds);
+ void vnc_display_close(DisplayState *ds);
+ int vnc_display_open(DisplayState *ds, const char *display);
+-int vnc_display_password(DisplayState *ds, const char *password);
++int vnc_display_password(DisplayState *ds, const char *password, int limit);
+ void do_info_vnc_print(Monitor *mon, const QObject *data);
+ void do_info_vnc(Monitor *mon, QObject **ret_data);
+ char *vnc_display_local_addr(DisplayState *ds);
+Index: qemu-kvm/monitor.c
+===================================================================
+--- qemu-kvm.orig/monitor.c 2009-12-21 10:37:58.000000000 +0100
++++ qemu-kvm/monitor.c 2009-12-21 11:03:40.000000000 +0100
+@@ -949,9 +949,9 @@
+ monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
+ }
+
+-static void change_vnc_password(const char *password)
++static void change_vnc_password(const char *password, int limit)
+ {
+- if (vnc_display_password(NULL, password) < 0)
++ if (vnc_display_password(NULL, password, limit) < 0)
+ qemu_error_new(QERR_SET_PASSWD_FAILED);
+
+ }
+@@ -959,19 +959,30 @@
+ static void change_vnc_password_cb(Monitor *mon, const char *password,
+ void *opaque)
+ {
+- change_vnc_password(password);
++ change_vnc_password(password, 0);
++ monitor_read_command(mon, 1);
++}
++
++static void change_vnc_ticket_cb(Monitor *mon, const char *password,
++ void *opaque)
++{
++ change_vnc_password(password, 1);
+ monitor_read_command(mon, 1);
+ }
+
+ static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
+ {
+ if (strcmp(target, "passwd") == 0 ||
+- strcmp(target, "password") == 0) {
++ strcmp(target, "password") == 0 ||
++ strcmp(target, "ticket") == 0) {
+ if (arg) {
+ char password[9];
+ strncpy(password, arg, sizeof(password));
+ password[sizeof(password) - 1] = '\0';
+- change_vnc_password(password);
++ if (strcmp(target, "ticket") == 0)
++ change_vnc_ticket_cb(mon, password, NULL);
++ else
++ change_vnc_password_cb(mon, password, NULL);
+ } else {
+ monitor_read_password(mon, change_vnc_password_cb, NULL);
+ }
+Index: qemu-kvm/vnc.c
+===================================================================
+--- qemu-kvm.orig/vnc.c 2009-12-21 10:37:57.000000000 +0100
++++ qemu-kvm/vnc.c 2009-12-21 10:44:13.000000000 +0100
+@@ -1763,7 +1763,7 @@
+ static void set_pixel_conversion(VncState *vs)
+ {
+ if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
+- (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
++ (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
+ !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
+ vs->write_pixels = vnc_write_pixels_copy;
+ switch (vs->ds->surface->pf.bits_per_pixel) {
+@@ -1871,7 +1871,7 @@
+ vnc_write_u8(vs, 0); /* msg id */
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1); /* number of rects */
+- vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
++ vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
+ ds_get_height(vs->ds), VNC_ENCODING_WMVi);
+ pixel_format_message(vs);
+ vnc_flush(vs);
+@@ -2068,7 +2068,10 @@
+ int i, j, pwlen;
+ unsigned char key[8];
+
+- if (!vs->vd->password || !vs->vd->password[0]) {
++ if (vs->vd->retries >= 0)
++ vs->vd->retries++;
++
++ if (!vs->vd->password || !vs->vd->password[0] || vs->vd->retries > 3) {
+ VNC_DEBUG("No password configured on server");
+ vnc_write_u32(vs, 1); /* Reject auth */
+ if (vs->minor >= 8) {
+@@ -2438,7 +2441,7 @@
+ #endif
+ }
+
+-int vnc_display_password(DisplayState *ds, const char *password)
++int vnc_display_password(DisplayState *ds, const char *password, int limit)
+ {
+ VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+
+@@ -2453,6 +2456,7 @@
+ if (password && password[0]) {
+ if (!(vs->password = qemu_strdup(password)))
+ return -1;
++ vs->retries = limit ? 0 : -1;
+ if (vs->auth == VNC_AUTH_NONE) {
+ vs->auth = VNC_AUTH_VNC;
+ }
+Index: qemu-kvm/vnc.h
+===================================================================
+--- qemu-kvm.orig/vnc.h 2009-12-21 10:37:57.000000000 +0100
++++ qemu-kvm/vnc.h 2009-12-21 10:44:13.000000000 +0100
+@@ -104,6 +104,7 @@
+
+ char *display;
+ char *password;
++ int retries;
+ int auth;
+ #ifdef CONFIG_VNC_TLS
+ int subauth; /* Used by VeNCrypt */
--- /dev/null
+Index: new/net.h
+===================================================================
+--- new.orig/net.h 2011-08-11 10:04:51.000000000 +0200
++++ new/net.h 2011-08-11 10:09:49.000000000 +0200
+@@ -172,8 +172,8 @@
+ int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+
+-#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+-#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
++#define DEFAULT_NETWORK_SCRIPT "/etc/kvm/kvm-ifup"
++#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/kvm/kvm-ifdown"
+ #ifdef __sun__
+ #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+ #else
+Index: new/configure
+===================================================================
+--- new.orig/configure 2011-08-11 10:04:51.000000000 +0200
++++ new/configure 2011-08-11 10:09:49.000000000 +0200
+@@ -157,7 +157,7 @@
+ bindir="\${prefix}/bin"
+ libdir="\${prefix}/lib"
+ sysconfdir="\${prefix}/etc"
+-confsuffix="/qemu"
++confsuffix="/kvm"
+ slirp="yes"
+ fmod_lib=""
+ fmod_inc=""
+Index: new/net/tap.h
+===================================================================
+--- new.orig/net/tap.h 2011-08-11 10:04:51.000000000 +0200
++++ new/net/tap.h 2011-08-11 10:09:49.000000000 +0200
+@@ -29,8 +29,6 @@
+ #include "qemu-common.h"
+ #include "qemu-option.h"
+
+-#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+-#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
+
+ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+
--- /dev/null
+see http://git.kernel.org/?p=virt/kvm/qemu-kvm.git;a=commitdiff;h=8fa3b3ce6e#patch1
+
+KVM_GET_SUPPORTED_CPUID has been known to fail to return -E2BIG
+when it runs out of entries. Detect this by always trying again
+with a bigger table if the ioctl() fills the table.
+
+--- a/kvm/libkvm/libkvm-x86.c
++++ b/kvm/libkvm/libkvm-x86.c
+@@ -575,6 +575,8 @@ static struct kvm_cpuid2 *try_get_cpuid(kvm_context_t kvm, int max)
+ r = ioctl(kvm->fd, KVM_GET_SUPPORTED_CPUID, cpuid);
+ if (r == -1)
+ r = -errno;
++ else if (r == 0 && cpuid->nent >= max)
++ r = -E2BIG;
+ if (r < 0) {
+ if (r == -E2BIG) {
+ free(cpuid);
+
--- /dev/null
+Index: new/qemu-options.hx
+===================================================================
+--- new.orig/qemu-options.hx 2011-08-11 10:04:51.000000000 +0200
++++ new/qemu-options.hx 2011-08-11 10:09:56.000000000 +0200
+@@ -89,6 +89,12 @@
+ are split equally.
+ ETEXI
+
++DEF("id", HAS_ARG, QEMU_OPTION_id,
++ "-id n set the faisched ID\n", QEMU_ARCH_ALL)
++
++DEF("cpuunits", HAS_ARG, QEMU_OPTION_cpuunits,
++ "-cpuuinits n set fairsched cpu units\n", QEMU_ARCH_ALL)
++
+ DEF("fda", HAS_ARG, QEMU_OPTION_fda,
+ "-fda/-fdb file use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL)
+ DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
+Index: new/vl.c
+===================================================================
+--- new.orig/vl.c 2011-08-11 10:04:51.000000000 +0200
++++ new/vl.c 2011-08-11 10:09:56.000000000 +0200
+@@ -150,6 +150,8 @@
+ #include "fsdev/qemu-fsdev.h"
+ #endif
+
++#include "vzsyscalls.h"
++
+ #include "disas.h"
+
+ #include "qemu_socket.h"
+@@ -203,6 +205,7 @@
+ int rtc_td_hack = 0;
+ int usb_enabled = 0;
+ int singlestep = 0;
++int fairsched_id = 0;
+ int smp_cpus = 1;
+ int max_cpus = 0;
+ int smp_cores = 1;
+@@ -2074,6 +2077,7 @@
+ {
+ const char *gdbstub_dev = NULL;
+ int i;
++ int cpuunits = 0;
+ int snapshot, linux_boot;
+ const char *icount_option = NULL;
+ const char *initrd_filename;
+@@ -2768,6 +2772,20 @@
+ exit(1);
+ }
+ break;
++ case QEMU_OPTION_id:
++ fairsched_id = atoi(optarg);
++ if (fairsched_id < 100 || fairsched_id >= 1000000) {
++ fprintf(stderr, "Invalid ID\n");
++ exit(1);
++ }
++ break;
++ case QEMU_OPTION_cpuunits:
++ cpuunits = atoi(optarg);
++ if (cpuunits < 8 || cpuunits > 500000) {
++ fprintf(stderr, "Invalid value for cpuunits\n");
++ exit(1);
++ }
++ break;
+ case QEMU_OPTION_vnc:
+ #ifdef CONFIG_VNC
+ display_remote++;
+@@ -3141,6 +3159,39 @@
+ if (ram_size == 0)
+ ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+
++ if (cpuunits && !fairsched_id) {
++ fprintf(stderr, "cpuunits specified without -id");
++ exit (1);
++ }
++
++ if (fairsched_id && cpuunits) {
++ int ret;
++ int weight = cpuunits ? 500000/cpuunits : 500;
++ pid_t cpid = getpid();
++
++ ret = syscall(__NR_fairsched_rmnod, fairsched_id);
++ if (ret == -EBUSY) {
++ fprintf (stderr, "unable to create fairsched node - still in use\n");
++ exit(1);
++ }
++
++ ret = syscall(__NR_fairsched_mknod, 0, weight, fairsched_id);
++ if (ret != fairsched_id) {
++ fprintf (stderr, "unable to create fairsched node\n");
++ exit(1);
++ }
++
++ ret = syscall(__NR_fairsched_mvpr, cpid, fairsched_id);
++ if (ret != 0) {
++ fprintf (stderr, "unable to move procces to fairsched group");
++ exit (1);
++ }
++
++ /* note: we can never remove ourself from the group, so the empty group
++ will exist after we finish
++ */
++ }
++
+ /* init the dynamic translator */
+ cpu_exec_init_all(tb_size * 1024 * 1024);
+
+Index: new/vzsyscalls.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ new/vzsyscalls.h 2011-08-11 10:09:56.000000000 +0200
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2000-2008, Parallels, Inc. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _VZSYSCALLS_H_
++#define _VZSYSCALLS_H_
++
++#include <sys/syscall.h>
++
++#ifdef __x86_64__
++#define __NR_fairsched_vcpus 499
++#define __NR_setluid 501
++#define __NR_setublimit 502
++#define __NR_fairsched_mknod 504
++#define __NR_fairsched_rmnod 505
++#define __NR_fairsched_chwt 506
++#define __NR_fairsched_mvpr 507
++#define __NR_fairsched_rate 508
++#define __NR_ioprio_set 251
++#elif defined(__i386__)
++#define __NR_fairsched_mknod 500
++#define __NR_fairsched_rmnod 501
++#define __NR_fairsched_chwt 502
++#define __NR_fairsched_mvpr 503
++#define __NR_fairsched_rate 504
++#define __NR_fairsched_vcpus 505
++#define __NR_setluid 511
++#define __NR_setublimit 512
++#define __NR_ioprio_set 289
++#else
++#error "no syscall for this arch"
++#endif
++
++#endif
--- /dev/null
+Index: new/pc-bios/keymaps/fr-ca
+===================================================================
+--- new.orig/pc-bios/keymaps/fr-ca 2011-08-11 10:04:51.000000000 +0200
++++ new/pc-bios/keymaps/fr-ca 2011-08-11 10:09:38.000000000 +0200
+@@ -14,22 +14,31 @@
+ twosuperior 0x9 altgr
+ threesuperior 0xa altgr
+ onequarter 0xb altgr
++minus 0x0c
+ onehalf 0xc altgr
++equal 0xd
+ threequarters 0xd altgr
+ section 0x18 altgr
+ paragraph 0x19 altgr
+ bracketleft 0x1a altgr
+ bracketright 0x1b altgr
++semicolon 0x27
++colon 0x27 shift
+ asciitilde 0x27 altgr
+ braceleft 0x28 altgr
++numbersign 0x29
+ braceright 0x2b altgr
+ less 0x2b
+ greater 0x2b shift
+ guillemotleft 0x56
+ guillemotright 0x56 shift
+ degree 0x56 altgr
++comma 0x33
+ mu 0x32 altgr
++apostrophe 0x33 shift
++period 0x34 shift
+ eacute 0x35
++Eacute 0x35 shift
+ dead_acute 0x35 altgr
+ dead_grave 0x28
+ dead_circumflex 0x1a
--- /dev/null
+Index: new/ui/vnc.c
+===================================================================
+--- new.orig/ui/vnc.c 2011-08-11 10:04:51.000000000 +0200
++++ new/ui/vnc.c 2011-08-11 10:10:00.000000000 +0200
+@@ -1444,6 +1444,10 @@
+
+ static void do_key_event(VncState *vs, int down, int keycode, int sym)
+ {
++ int mods = keycode & 0xf00;
++
++ keycode &= SCANCODE_KEYMASK;
++
+ /* QEMU console switch */
+ switch(keycode) {
+ case 0x2a: /* Left Shift */
+@@ -1514,12 +1518,42 @@
+ }
+
+ if (is_graphic_console()) {
++
++ /* our java vnc client never sends ALTGR, so we create
++ an artificial up/down event */
++
++ int emul_altgr = (mods & SCANCODE_ALTGR) &&
++ !vs->modifiers_state[0xb8];
++
++ if (emul_altgr) {
++ reset_keys(vs);
++ kbd_put_keycode(SCANCODE_EMUL0);
++ kbd_put_keycode(0xb8 & SCANCODE_KEYCODEMASK);
++ }
++
++ int emul_shift = (mods & SCANCODE_SHIFT) &&
++ !vs->modifiers_state[0x2a];
++
++ if (emul_shift) {
++ kbd_put_keycode(0x2a & SCANCODE_KEYCODEMASK);
++ }
++
+ if (keycode & SCANCODE_GREY)
+ kbd_put_keycode(SCANCODE_EMUL0);
+ if (down)
+ kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
+ else
+ kbd_put_keycode(keycode | SCANCODE_UP);
++
++ if (emul_shift) {
++ kbd_put_keycode(0x2a | SCANCODE_UP);
++ }
++
++ if (emul_altgr) {
++ kbd_put_keycode(SCANCODE_EMUL0);
++ kbd_put_keycode(0xb8 | SCANCODE_UP);
++ }
++
+ } else {
+ /* QEMU console emulation */
+ if (down) {
+@@ -1627,7 +1661,8 @@
+ lsym = lsym - 'A' + 'a';
+ }
+
+- keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF) & SCANCODE_KEYMASK;
++ keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF);
++
+ do_key_event(vs, down, keycode, sym);
+ }
+
--- /dev/null
+Index: new/arch_init.c
+===================================================================
+--- new.orig/arch_init.c 2011-08-11 10:04:51.000000000 +0200
++++ new/arch_init.c 2011-08-11 10:10:04.000000000 +0200
+@@ -251,9 +251,10 @@
+ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
+ {
+ ram_addr_t addr;
+- uint64_t bytes_transferred_last;
+ double bwidth = 0;
+ uint64_t expected_time = 0;
++ static int64_t starttime = 0;
++ double timediff;
+
+ if (stage < 0) {
+ cpu_physical_memory_set_dirty_tracking(0);
+@@ -293,10 +294,10 @@
+ qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
+ qemu_put_be64(f, block->length);
+ }
++
++ starttime = qemu_get_clock_ns(rt_clock);
+ }
+
+- bytes_transferred_last = bytes_transferred;
+- bwidth = qemu_get_clock_ns(rt_clock);
+
+ while (!qemu_file_rate_limit(f)) {
+ int bytes_sent;
+@@ -308,8 +309,8 @@
+ }
+ }
+
+- bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
+- bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
++ timediff = qemu_get_clock_ns(rt_clock) - starttime;
++ bwidth = bytes_transferred / timediff;
+
+ /* if we haven't transferred anything this round, force expected_time to a
+ * a very high value, but without crashing */
+@@ -330,6 +331,10 @@
+
+ qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
+
++ if ((stage == 2) && (bytes_transferred > 2*ram_bytes_total())) {
++ return 1;
++ }
++
+ expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
+
+ return (stage == 2) && (expected_time <= migrate_max_downtime());
--- /dev/null
+Index: kvm-86/cpu-defs.h
+===================================================================
+--- kvm-86.orig/cpu-defs.h 2009-09-24 14:19:14.000000000 +0200
++++ kvm-86/cpu-defs.h 2009-09-24 14:47:00.000000000 +0200
+@@ -194,6 +194,8 @@
+ int cpu_index; /* CPU index (informative) */ \
+ uint32_t host_tid; /* host thread ID */ \
+ int numa_node; /* NUMA node this cpu is belonging to */ \
++ int nr_cores; /* number of cores within this CPU package */ \
++ int nr_threads;/* number of threads within this CPU */ \
+ int running; /* Nonzero if cpu is currently running(usermode). */ \
+ int thread_id; \
+ /* user data */ \
+Index: kvm-86/target-i386/helper.c
+===================================================================
+--- kvm-86.orig/target-i386/helper.c 2009-09-24 14:19:14.000000000 +0200
++++ kvm-86/target-i386/helper.c 2009-09-24 14:50:18.000000000 +0200
+@@ -121,7 +121,7 @@
+ #ifdef TARGET_X86_64
+ {
+ .name = "qemu64",
+- .level = 2,
++ .level = 4,
+ .vendor1 = CPUID_VENDOR_AMD_1,
+ .vendor2 = CPUID_VENDOR_AMD_2,
+ .vendor3 = CPUID_VENDOR_AMD_3,
+@@ -192,7 +192,7 @@
+ #endif
+ {
+ .name = "qemu32",
+- .level = 2,
++ .level = 4,
+ .family = 6,
+ .model = 3,
+ .stepping = 3,
+@@ -1638,6 +1638,12 @@
+ *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+ *ecx = env->cpuid_ext_features;
+ *edx = env->cpuid_features;
++
++ if (env->nr_cores * env->nr_threads > 1) {
++ *ebx |= (env->nr_cores * env->nr_threads) << 16;
++ *edx |= 1 << 28; /* HTT bit */
++ }
++
+ break;
+ case 2:
+ /* cache info: needed for Pentium Pro compatibility */
+@@ -1648,21 +1654,29 @@
+ break;
+ case 4:
+ /* cache info: needed for Core compatibility */
++ if (env->nr_cores > 1) {
++ *eax = (env->nr_cores - 1) << 26;
++ } else {
++ *eax = 0;
++ }
+ switch (count) {
+ case 0: /* L1 dcache info */
+- *eax = 0x0000121;
++ *eax |= 0x0000121;
+ *ebx = 0x1c0003f;
+ *ecx = 0x000003f;
+ *edx = 0x0000001;
+ break;
+ case 1: /* L1 icache info */
+- *eax = 0x0000122;
++ *eax |= 0x0000122;
+ *ebx = 0x1c0003f;
+ *ecx = 0x000003f;
+ *edx = 0x0000001;
+ break;
+ case 2: /* L2 cache info */
+- *eax = 0x0000143;
++ *eax |= 0x0000143;
++ if (env->nr_threads > 1) {
++ *eax |= (env->nr_threads - 1) << 14;
++ }
+ *ebx = 0x3c0003f;
+ *ecx = 0x0000fff;
+ *edx = 0x0000001;
+@@ -1715,6 +1729,16 @@
+ *ecx = env->cpuid_ext3_features;
+ *edx = env->cpuid_ext2_features;
+
++ if (env->nr_cores * env->nr_threads > 1) {
++ uint32_t teax, tebx, tecx, tedx;
++ cpu_x86_cpuid(env, 0, 0, &teax, &tebx, &tecx, &tedx);
++ if ( tebx == CPUID_VENDOR_AMD_1 &&
++ tedx == CPUID_VENDOR_AMD_2 &&
++ tecx == CPUID_VENDOR_AMD_3) {
++ *ecx |= 1 << 1; /* CmpLegacy bit */
++ }
++ }
++
+ if (kvm_enabled()) {
+ uint32_t h_eax, h_edx;
+
+@@ -1790,6 +1814,9 @@
+ *ebx = 0;
+ *ecx = 0;
+ *edx = 0;
++ if (env->nr_cores * env->nr_threads > 1) {
++ *ecx |= (env->nr_cores * env->nr_threads) - 1;
++ }
+ break;
+ case 0x8000000A:
+ *eax = 0x00000001; /* SVM Revision */
+Index: kvm-86/vl.c
+===================================================================
+--- kvm-86.orig/vl.c 2009-09-24 14:30:14.000000000 +0200
++++ kvm-86/vl.c 2009-09-24 14:47:00.000000000 +0200
+@@ -230,6 +230,8 @@
+ const char *assigned_devices[MAX_DEV_ASSIGN_CMDLINE];
+ int assigned_devices_index;
+ int smp_cpus = 1;
++int smp_cores = 1;
++int smp_threads = 1;
+ int fairsched_id = 0;
+ const char *vnc_display;
+ int acpi_enabled = 1;
+@@ -2499,6 +2501,52 @@
+ return;
+ }
+
++static void smp_parse(const char *optarg)
++{
++ int smp, sockets = 0, threads = 0, cores = 0;
++ char *endptr;
++ char option[128];
++
++ smp = strtoul(optarg, &endptr, 10);
++ if (endptr != optarg) {
++ if (*endptr == ',') {
++ endptr++;
++ }
++ }
++ if (get_param_value(option, 128, "sockets", endptr) != 0)
++ sockets = strtoull(option, NULL, 10);
++ if (get_param_value(option, 128, "cores", endptr) != 0)
++ cores = strtoull(option, NULL, 10);
++ if (get_param_value(option, 128, "threads", endptr) != 0)
++ threads = strtoull(option, NULL, 10);
++
++ /* compute missing values, prefer sockets over cores over threads */
++ if (smp == 0 || sockets == 0) {
++ sockets = sockets > 0 ? sockets : 1;
++ cores = cores > 0 ? cores : 1;
++ threads = threads > 0 ? threads : 1;
++ if (smp == 0) {
++ smp = cores * threads * sockets;
++ } else {
++ sockets = smp / (cores * threads);
++ }
++ } else {
++ if (cores == 0) {
++ threads = threads > 0 ? threads : 1;
++ cores = smp / (sockets * threads);
++ } else {
++ if (sockets == 0) {
++ sockets = smp / (cores * threads);
++ } else {
++ threads = smp / (cores * sockets);
++ }
++ }
++ }
++ smp_cpus = smp;
++ smp_cores = cores > 0 ? cores : 1;
++ smp_threads = threads > 0 ? threads : 1;
++}
++
+ /***********************************************************/
+ /* USB devices */
+
+@@ -3727,6 +3775,8 @@
+
+ if (kvm_enabled())
+ kvm_init_vcpu(env);
++ env->nr_cores = smp_cores;
++ env->nr_threads = smp_threads;
+ return;
+ }
+
+@@ -4060,6 +4110,8 @@
+ kvm_start_vcpu(env);
+ else
+ tcg_init_vcpu(env);
++ env->nr_cores = smp_cores;
++ env->nr_threads = smp_threads;
+ }
+
+ void qemu_notify_event(void)
+@@ -5560,7 +5612,7 @@
+ usb_devices_index++;
+ break;
+ case QEMU_OPTION_smp:
+- smp_cpus = atoi(optarg);
++ smp_parse(optarg);
+ if (smp_cpus < 1) {
+ fprintf(stderr, "Invalid number of CPUs\n");
+ exit(1);
--- /dev/null
+
+bug description: boot a guest, open VNC console, and when it's still in BIOS / bootloader sequence, type as many keys as you can, move your mouse as much as you can. If needed, just reboot the guest.
+
+Linux guest will boot with "i8042.c: No controller found" and no keyboard.
+
+Further discussion seem to lead to a conclusion that there is some obscure bug in Qemu BIOS which makes this problem visible.
+
+Index: kvm-86/hw/ps2.c
+===================================================================
+--- kvm-86.orig/hw/ps2.c 2009-06-15 13:31:24.000000000 +0200
++++ kvm-86/hw/ps2.c 2009-06-15 13:31:50.000000000 +0200
+@@ -70,7 +70,7 @@
+ #define MOUSE_STATUS_ENABLED 0x20
+ #define MOUSE_STATUS_SCALE21 0x10
+
+-#define PS2_QUEUE_SIZE 256
++#define PS2_QUEUE_SIZE 15
+
+ typedef struct {
+ uint8_t data[PS2_QUEUE_SIZE];
--- /dev/null
+Index: new/ui/vnc.c
+===================================================================
+--- new.orig/ui/vnc.c 2011-08-11 10:10:00.000000000 +0200
++++ new/ui/vnc.c 2011-08-11 10:10:30.000000000 +0200
+@@ -31,6 +31,8 @@
+ #include "qemu-timer.h"
+ #include "acl.h"
+ #include "qemu-objects.h"
++#include <signal.h>
++#include <sys/wait.h>
+
+ #define VNC_REFRESH_INTERVAL_BASE 30
+ #define VNC_REFRESH_INTERVAL_INC 50
+@@ -41,6 +43,125 @@
+ #include "vnc_keysym.h"
+ #include "d3des.h"
+
++static int pve_vmid = 0;
++
++void pve_auth_setup(int vmid) {
++ pve_vmid = vmid;
++}
++
++static char *
++urlencode(char *buf, const char *value)
++{
++ static const char *hexchar = "0123456789abcdef";
++ char *p = buf;
++ int i;
++ int l = strlen(value);
++ for (i = 0; i < l; i++) {
++ char c = value[i];
++ if (('a' <= c && c <= 'z') ||
++ ('A' <= c && c <= 'Z') ||
++ ('0' <= c && c <= '9')) {
++ *p++ = c;
++ } else if (c == 32) {
++ *p++ = '+';
++ } else {
++ *p++ = '%';
++ *p++ = hexchar[c >> 4];
++ *p++ = hexchar[c & 15];
++ }
++ }
++ *p = 0;
++
++ return p;
++}
++
++int
++pve_auth_verify(const char *clientip, const char *username, const char *passwd)
++{
++ struct sockaddr_in server;
++
++ int sfd = socket(AF_INET, SOCK_STREAM, 0);
++ if (sfd == -1) {
++ perror("pve_auth_verify: socket failed");
++ return -1;
++ }
++
++ struct hostent *he;
++ if ((he = gethostbyname("localhost")) == NULL) {
++ fprintf(stderr, "pve_auth_verify: error resolving hostname\n");
++ goto err;
++ }
++
++ memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
++ server.sin_family = AF_INET;
++ server.sin_port = htons(85);
++
++ if (connect(sfd, (struct sockaddr *)&server, sizeof(server))) {
++ perror("pve_auth_verify: error connecting to server");
++ goto err;
++ }
++
++ char buf[8192];
++ char form[8192];
++
++ char *p = form;
++ p = urlencode(p, "username");
++ *p++ = '=';
++ p = urlencode(p, username);
++
++ *p++ = '&';
++ p = urlencode(p, "password");
++ *p++ = '=';
++ p = urlencode(p, passwd);
++
++ *p++ = '&';
++ p = urlencode(p, "path");
++ *p++ = '=';
++ char authpath[256];
++ sprintf(authpath, "/vms/%d", pve_vmid);
++ p = urlencode(p, authpath);
++
++ *p++ = '&';
++ p = urlencode(p, "privs");
++ *p++ = '=';
++ p = urlencode(p, "VM.Console");
++
++ sprintf(buf, "POST /api2/json/access/ticket HTTP/1.1\n"
++ "Host: localhost:85\n"
++ "Connection: close\n"
++ "PVEClientIP: %s\n"
++ "Content-Type: application/x-www-form-urlencoded\n"
++ "Content-Length: %zd\n\n%s\n", clientip, strlen(form), form);
++ ssize_t len = strlen(buf);
++ ssize_t sb = send(sfd, buf, len, 0);
++ if (sb < 0) {
++ perror("pve_auth_verify: send failed");
++ goto err;
++ }
++ if (sb != len) {
++ fprintf(stderr, "pve_auth_verify: partial send error\n");
++ goto err;
++ }
++
++ len = recv(sfd, buf, sizeof(buf) - 1, 0);
++ if (len < 0) {
++ perror("pve_auth_verify: recv failed");
++ goto err;
++ }
++
++ buf[len] = 0;
++
++ //printf("DATA:%s\n", buf);
++
++ shutdown(sfd, SHUT_RDWR);
++
++ return strncmp(buf, "HTTP/1.1 200 OK", 15);
++
++err:
++ shutdown(sfd, SHUT_RDWR);
++ return -1;
++}
++
+ static VncDisplay *vnc_display; /* needed for info vnc */
+ static DisplayChangeListener *dcl;
+
+@@ -1810,7 +1931,7 @@
+ static void set_pixel_conversion(VncState *vs)
+ {
+ if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
+- (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
++ (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
+ !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
+ vs->write_pixels = vnc_write_pixels_copy;
+ vnc_hextile_set_pixel_conversion(vs, 0);
+@@ -1896,7 +2017,7 @@
+ vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1); /* number of rects */
+- vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
++ vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
+ ds_get_height(vs->ds), VNC_ENCODING_WMVi);
+ pixel_format_message(vs);
+ vnc_unlock_output(vs);
+@@ -2729,7 +2850,7 @@
+ char *vnc_display_local_addr(DisplayState *ds)
+ {
+ VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+-
++
+ return vnc_socket_local_addr("%s:%s", vs->lsock);
+ }
+
+@@ -2778,6 +2899,7 @@
+ tls = 1; /* Require TLS */
+ } else if (strncmp(options, "x509", 4) == 0) {
+ char *start, *end;
++ tls = 1; /* Require TLS */
+ x509 = 1; /* Require x509 certificates */
+ if (strncmp(options, "x509verify", 10) == 0)
+ vs->tls.x509verify = 1; /* ...and verify client certs */
+@@ -2800,10 +2922,12 @@
+ }
+ qemu_free(path);
+ } else {
+- fprintf(stderr, "No certificate path provided\n");
+- qemu_free(vs->display);
+- vs->display = NULL;
+- return -1;
++ if (pve_tls_set_x509_creds_dir(vs) < 0) {
++ fprintf(stderr, "No certificate path provided\n");
++ qemu_free(vs->display);
++ vs->display = NULL;
++ return -1;
++ }
+ }
+ #endif
+ #if defined(CONFIG_VNC_TLS) || defined(CONFIG_VNC_SASL)
+@@ -2856,10 +2980,10 @@
+ vs->auth = VNC_AUTH_VENCRYPT;
+ if (x509) {
+ VNC_DEBUG("Initializing VNC server with x509 password auth\n");
+- vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
++ vs->subauth = VNC_AUTH_VENCRYPT_X509PLAIN;
+ } else {
+ VNC_DEBUG("Initializing VNC server with TLS password auth\n");
+- vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
++ vs->subauth = VNC_AUTH_VENCRYPT_TLSPLAIN;
+ }
+ } else {
+ #endif /* CONFIG_VNC_TLS */
+Index: new/ui/vnc-auth-vencrypt.c
+===================================================================
+--- new.orig/ui/vnc-auth-vencrypt.c 2011-08-11 10:04:51.000000000 +0200
++++ new/ui/vnc-auth-vencrypt.c 2011-08-11 10:10:30.000000000 +0200
+@@ -25,7 +25,107 @@
+ */
+
+ #include "vnc.h"
++#include "qemu_socket.h"
+
++static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
++{
++ const char *err = NULL;
++ char username[256];
++ char passwd[512];
++
++ char clientip[256];
++ clientip[0] = 0;
++ struct sockaddr_in client;
++ socklen_t addrlen = sizeof(client);
++ if (getpeername(vs->csock, &client, &addrlen) == 0) {
++ inet_ntop(client.sin_family, &client.sin_addr,
++ clientip, sizeof(clientip));
++ }
++
++ if ((len != (vs->username_len + vs->password_len)) ||
++ (vs->username_len >= (sizeof(username)-1)) ||
++ (vs->password_len >= (sizeof(passwd)-1)) ) {
++ err = "Got unexpected data length";
++ goto err;
++ }
++
++ strncpy(username, (char *)data, vs->username_len);
++ username[vs->username_len] = 0;
++ strncpy(passwd, (char *)data + vs->username_len, vs->password_len);
++ passwd[vs->password_len] = 0;
++
++ VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
++
++ if (pve_auth_verify(clientip, username, passwd) == 0) {
++ vnc_write_u32(vs, 0); /* Accept auth completion */
++ start_client_init(vs);
++ return 0;
++ }
++
++ err = "Authentication failed";
++err:
++ if (err) {
++ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
++ vnc_write_u32(vs, 1); /* Reject auth */
++ if (vs->minor >= 8) {
++ int elen = strlen(err);
++ vnc_write_u32(vs, elen);
++ vnc_write(vs, err, elen);
++ }
++ }
++ vnc_flush(vs);
++ vnc_client_error(vs);
++
++ return 0;
++
++}
++
++static int protocol_client_auth_plain_start(VncState *vs, uint8_t *data, size_t len)
++{
++ uint32_t ulen = read_u32(data, 0);
++ uint32_t pwlen = read_u32(data, 4);
++ const char *err = NULL;
++
++ VNC_DEBUG("AUTH PLAIN START %u %u\n", ulen, pwlen);
++
++ if (!ulen) {
++ err = "No User name.";
++ goto err;
++ }
++ if (ulen >= 255) {
++ err = "User name too long.";
++ goto err;
++ }
++ if (!pwlen) {
++ err = "Password too short";
++ goto err;
++ }
++ if (pwlen >= 511) {
++ err = "Password too long.";
++ goto err;
++ }
++
++ vs->username_len = ulen;
++ vs->password_len = pwlen;
++
++ vnc_read_when(vs, protocol_client_auth_plain, ulen + pwlen);
++
++ return 0;
++err:
++ if (err) {
++ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
++ vnc_write_u32(vs, 1); /* Reject auth */
++ if (vs->minor >= 8) {
++ int elen = strlen(err);
++ vnc_write_u32(vs, elen);
++ vnc_write(vs, err, elen);
++ }
++ }
++ vnc_flush(vs);
++ vnc_client_error(vs);
++
++ return 0;
++}
+
+ static void start_auth_vencrypt_subauth(VncState *vs)
+ {
+@@ -37,6 +137,12 @@
+ start_client_init(vs);
+ break;
+
++ case VNC_AUTH_VENCRYPT_TLSPLAIN:
++ case VNC_AUTH_VENCRYPT_X509PLAIN:
++ VNC_DEBUG("Start TLS auth PLAIN\n");
++ vnc_read_when(vs, protocol_client_auth_plain_start, 8);
++ break;
++
+ case VNC_AUTH_VENCRYPT_TLSVNC:
+ case VNC_AUTH_VENCRYPT_X509VNC:
+ VNC_DEBUG("Start TLS auth VNC\n");
+Index: new/ui/vnc.h
+===================================================================
+--- new.orig/ui/vnc.h 2011-08-11 10:04:51.000000000 +0200
++++ new/ui/vnc.h 2011-08-11 10:12:42.000000000 +0200
+@@ -260,6 +260,8 @@
+ char challenge[VNC_AUTH_CHALLENGE_SIZE];
+ #ifdef CONFIG_VNC_TLS
+ int subauth; /* Used by VeNCrypt */
++ int username_len;
++ int password_len;
+ VncStateTLS tls;
+ #endif
+ #ifdef CONFIG_VNC_SASL
+Index: new/ui/vnc-tls.c
+===================================================================
+--- new.orig/ui/vnc-tls.c 2011-08-11 10:04:51.000000000 +0200
++++ new/ui/vnc-tls.c 2011-08-11 10:10:30.000000000 +0200
+@@ -291,6 +291,14 @@
+ static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
+ static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
+
++ /* optimize for speed */
++ static const int ciphers[] = {
++ GNUTLS_CIPHER_ARCFOUR_128,
++ GNUTLS_CIPHER_AES_128_CBC,
++ GNUTLS_CIPHER_3DES_CBC,
++ 0
++ };
++
+ VNC_DEBUG("Do TLS setup\n");
+ if (vnc_tls_initialize() < 0) {
+ VNC_DEBUG("Failed to init TLS\n");
+@@ -310,6 +318,13 @@
+ return -1;
+ }
+
++ if ((gnutls_cipher_set_priority(vs->tls.session, ciphers)) < 0) {
++ gnutls_deinit(vs->tls.session);
++ vs->tls.session = NULL;
++ vnc_client_error(vs);
++ return -1;
++ }
++
+ if (gnutls_kx_set_priority(vs->tls.session, needX509Creds ? kx_x509 : kx_anon) < 0) {
+ gnutls_deinit(vs->tls.session);
+ vs->tls.session = NULL;
+@@ -419,6 +434,24 @@
+ return 0;
+ }
+
++int pve_tls_set_x509_creds_dir(VncDisplay *vd)
++{
++ if (vnc_set_x509_credential(vd, "/etc/pve", "pve-root-ca.pem", &vd->tls.x509cacert, 0) < 0)
++ goto cleanup;
++ if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.pem", &vd->tls.x509cert, 0) < 0)
++ goto cleanup;
++ if (vnc_set_x509_credential(vd, "/etc/pve/local", "pve-ssl.key", &vd->tls.x509key, 0) < 0)
++ goto cleanup;
++
++ return 0;
++
++ cleanup:
++ qemu_free(vd->tls.x509cacert);
++ qemu_free(vd->tls.x509cert);
++ qemu_free(vd->tls.x509key);
++ vd->tls.x509cacert = vd->tls.x509cacrl = vd->tls.x509cert = vd->tls.x509key = NULL;
++ return -1;
++}
+
+ int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
+ const char *certdir)
+Index: new/ui/vnc-tls.h
+===================================================================
+--- new.orig/ui/vnc-tls.h 2011-08-11 10:04:51.000000000 +0200
++++ new/ui/vnc-tls.h 2011-08-11 10:10:30.000000000 +0200
+@@ -68,6 +68,8 @@
+
+ int vnc_tls_validate_certificate(VncState *vs);
+
++int pve_tls_set_x509_creds_dir(VncDisplay *vd);
++
+ int vnc_tls_set_x509_creds_dir(VncDisplay *vd,
+ const char *path);
+
+Index: new/vl.c
+===================================================================
+--- new.orig/vl.c 2011-08-11 10:09:56.000000000 +0200
++++ new/vl.c 2011-08-11 10:10:30.000000000 +0200
+@@ -2774,6 +2774,7 @@
+ break;
+ case QEMU_OPTION_id:
+ fairsched_id = atoi(optarg);
++ pve_auth_setup(fairsched_id);
+ if (fairsched_id < 100 || fairsched_id >= 1000000) {
+ fprintf(stderr, "Invalid ID\n");
+ exit(1);
--- /dev/null
+fr-ca-keymap-corrections.diff
+adjust-path.diff
+fairsched.diff
+keymap.diff
+live-migration-fixes.diff
+set-max-nics.patch
+use-local-linux-kvm-h.diff
+pve-auth.patch
+
--- /dev/null
+Index: new/net.h
+===================================================================
+--- new.orig/net.h 2011-08-11 10:09:49.000000000 +0200
++++ new/net.h 2011-08-11 10:10:08.000000000 +0200
+@@ -126,7 +126,7 @@
+
+ /* NIC info */
+
+-#define MAX_NICS 8
++#define MAX_NICS 32
+
+ struct NICInfo {
+ MACAddr macaddr;
--- /dev/null
+
+Alway use our own version.
+
+Index: new/kvm/libkvm/libkvm.h
+===================================================================
+--- new.orig/kvm/libkvm/libkvm.h 2011-08-11 10:04:51.000000000 +0200
++++ new/kvm/libkvm/libkvm.h 2011-08-11 10:10:13.000000000 +0200
+@@ -15,7 +15,7 @@
+ #define __user /* temporary, until installed via make headers_install */
+ #endif
+
+-#include <linux/kvm.h>
++#include "linux/kvm.h"
+
+ #include <signal.h>
+
--- /dev/null
+Index: qemu-kvm/console.h
+===================================================================
+--- qemu-kvm.orig/console.h 2010-10-21 13:40:20.000000000 +0200
++++ qemu-kvm/console.h 2010-10-21 14:06:21.000000000 +0200
+@@ -368,7 +368,7 @@
+ void vnc_display_init(DisplayState *ds);
+ void vnc_display_close(DisplayState *ds);
+ int vnc_display_open(DisplayState *ds, const char *display);
+-int vnc_display_password(DisplayState *ds, const char *password);
++int vnc_display_password(DisplayState *ds, const char *password, int limit);
+ void do_info_vnc_print(Monitor *mon, const QObject *data);
+ void do_info_vnc(Monitor *mon, QObject **ret_data);
+ char *vnc_display_local_addr(DisplayState *ds);
+Index: qemu-kvm/ui/vnc.c
+===================================================================
+--- qemu-kvm.orig/ui/vnc.c 2010-10-21 13:40:21.000000000 +0200
++++ qemu-kvm/ui/vnc.c 2010-10-21 14:06:21.000000000 +0200
+@@ -1790,7 +1790,7 @@
+ static void set_pixel_conversion(VncState *vs)
+ {
+ if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
+- (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
++ (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG) &&
+ !memcmp(&(vs->clientds.pf), &(vs->ds->surface->pf), sizeof(PixelFormat))) {
+ vs->write_pixels = vnc_write_pixels_copy;
+ vnc_hextile_set_pixel_conversion(vs, 0);
+@@ -1876,7 +1876,7 @@
+ vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1); /* number of rects */
+- vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
++ vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds),
+ ds_get_height(vs->ds), VNC_ENCODING_WMVi);
+ pixel_format_message(vs);
+ vnc_unlock_output(vs);
+@@ -2079,7 +2079,10 @@
+ int i, j, pwlen;
+ unsigned char key[8];
+
+- if (!vs->vd->password || !vs->vd->password[0]) {
++ if (vs->vd->retries >= 0)
++ vs->vd->retries++;
++
++ if (!vs->vd->password || !vs->vd->password[0] || vs->vd->retries > 3) {
+ VNC_DEBUG("No password configured on server");
+ vnc_write_u32(vs, 1); /* Reject auth */
+ if (vs->minor >= 8) {
+@@ -2478,7 +2481,7 @@
+ #endif
+ }
+
+-int vnc_display_password(DisplayState *ds, const char *password)
++int vnc_display_password(DisplayState *ds, const char *password, int limit)
+ {
+ VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+
+@@ -2493,6 +2496,7 @@
+ if (password && password[0]) {
+ if (!(vs->password = qemu_strdup(password)))
+ return -1;
++ vs->retries = limit ? 0 : -1;
+ if (vs->auth == VNC_AUTH_NONE) {
+ vs->auth = VNC_AUTH_VNC;
+ }
+Index: qemu-kvm/ui/vnc.h
+===================================================================
+--- qemu-kvm.orig/ui/vnc.h 2010-10-21 13:40:20.000000000 +0200
++++ qemu-kvm/ui/vnc.h 2010-10-21 14:06:21.000000000 +0200
+@@ -120,6 +120,7 @@
+
+ char *display;
+ char *password;
++ int retries;
+ int auth;
+ bool lossy;
+ #ifdef CONFIG_VNC_TLS
+Index: qemu-kvm/monitor.c
+===================================================================
+--- qemu-kvm.orig/monitor.c 2010-10-21 13:40:21.000000000 +0200
++++ qemu-kvm/monitor.c 2010-10-21 14:14:38.000000000 +0200
+@@ -978,7 +978,7 @@
+
+ static int change_vnc_password(const char *password)
+ {
+- if (vnc_display_password(NULL, password) < 0) {
++ if (vnc_display_password(NULL, password, 0) < 0) {
+ qerror_report(QERR_SET_PASSWD_FAILED);
+ return -1;
+ }
+@@ -986,6 +986,17 @@
+ return 0;
+ }
+
++static int change_vnc_ticket(const char *password)
++{
++ if (vnc_display_password(NULL, password, 1) < 0) {
++ qerror_report(QERR_SET_PASSWD_FAILED);
++ return -1;
++ }
++
++ return 0;
++}
++
++
+ static void change_vnc_password_cb(Monitor *mon, const char *password,
+ void *opaque)
+ {
+@@ -996,12 +1007,16 @@
+ static int do_change_vnc(Monitor *mon, const char *target, const char *arg)
+ {
+ if (strcmp(target, "passwd") == 0 ||
+- strcmp(target, "password") == 0) {
++ strcmp(target, "password") == 0 ||
++ strcmp(target, "ticket") == 0) {
+ if (arg) {
+ char password[9];
+ strncpy(password, arg, sizeof(password));
+ password[sizeof(password) - 1] = '\0';
+- return change_vnc_password(password);
++ if (strcmp(target, "ticket") == 0)
++ return change_vnc_ticket(password);
++ else
++ return change_vnc_password(password);
+ } else {
+ return monitor_read_password(mon, change_vnc_password_cb, NULL);
+ }
+@@ -3324,11 +3339,11 @@
+ static int is_valid_option(const char *c, const char *typestr)
+ {
+ char option[3];
+-
++
+ option[0] = '-';
+ option[1] = *c;
+ option[2] = '\0';
+-
++
+ typestr = strstr(typestr, option);
+ return (typestr != NULL);
+ }
+@@ -3640,7 +3655,7 @@
+ p++;
+ if(c != *p) {
+ if(!is_valid_option(p, typestr)) {
+-
++
+ monitor_printf(mon, "%s: unsupported option -%c\n",
+ cmdname, *p);
+ goto fail;
--- /dev/null
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+PACKAGE=pve-qemu-kvm
+destdir := $(CURDIR)/debian/$(PACKAGE)
+
+ifneq "$(wildcard /usr/share/quilt/quilt.make)" ""
+include /usr/share/quilt/quilt.make
+endif
+
+CFLAGS = -Wall
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+
+config.status: configure
+ dh_testdir
+ # Add here commands to configure the package.
+ ./configure --prefix=/usr --datadir=/usr/share/kvm --docdir=/usr/share/doc/pve-qemu-kvm --sysconfdir=/etc --disable-xen --enable-vnc-tls --enable-sdl --enable-uuid --enable-linux-aio
+
+build: patch build-stamp
+
+build-stamp: config.status
+ dh_testdir
+
+ # Add here commands to compile the package.
+ $(MAKE) V=1
+
+ #docbook-to-man debian/kvm.sgml > kvm.1
+
+ touch $@
+
+clean: unpatch
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+
+ # Add here commands to clean up after the build process.
+ -$(MAKE) distclean
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+ cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+ cp -f /usr/share/misc/config.guess config.guess
+endif
+
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/pve-kvm.
+ $(MAKE) DESTDIR=$(destdir) install
+
+ mv $(destdir)/usr/bin/qemu-system-x86_64 $(destdir)/usr/bin/kvm
+ mv $(destdir)/usr/share/man/man1/qemu.1 $(destdir)/usr/share/man/man1/kvm.1
+
+ # Install the userspace utilities
+ install -m 0755 kvm/kvm_stat $(destdir)/usr/bin/
+
+ install -D -m 0755 $(CURDIR)/debian/kvm-ifup $(destdir)/etc/kvm/kvm-ifup
+ install -D -m 0755 $(CURDIR)/debian/kvm-ifdown $(destdir)/etc/kvm/kvm-ifdown
+ # we do not need openbios files (sparc/ppc)
+ rm -rf $(destdir)/usr/share/kvm/openbios-*
+ # remove ppc files
+ rm $(destdir)/usr/share/kvm/*.dtb
+ rm $(destdir)/usr/share/kvm/ppc_rom.bin
+ rm $(destdir)/usr/share/kvm/s390-zipl.rom
+ rm $(destdir)/usr/share/kvm/slof.bin
+ rm $(destdir)/usr/share/kvm/spapr-rtas.bin
+
+ # remove guest agent (that is only required for a guest)
+ rm $(destdir)/usr/bin/qemu-ga
+
+ # Remove things we don't package at all, would be a "kvm-dev" package
+ rm -Rf $(destdir)/usr/include/linux/
+ rm -Rf $(destdir)/usr/include
+ rm -Rf $(destdir)/usr/lib*
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installdocs
+ dh_installexamples
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_python
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+ dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install