summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorVaporeon2018-05-11 01:03:57 +1200
committerVaporeon2018-05-11 01:03:57 +1200
commit16d1021ff9917fc3a52057dbfbf6ee7759479659 (patch)
tree8e6cef1ae8bae6e7865e5d63112d5333c7e19abc
parentd32abf9ef79b16fda6c3bc467b56914c3873565e (diff)
downloadaur-16d1021ff9917fc3a52057dbfbf6ee7759479659.tar.gz
PS/2 input patch
-rw-r--r--.SRCINFO6
-rw-r--r--PKGBUILD9
-rw-r--r--ps2-fixes-v2.patch315
3 files changed, 325 insertions, 5 deletions
diff --git a/.SRCINFO b/.SRCINFO
index cef4236631d7..f12a5828b50c 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,9 +1,9 @@
# Generated by mksrcinfo v8
-# Wed May 9 08:01:07 UTC 2018
+# Thu May 10 12:57:45 UTC 2018
pkgbase = qemu-patched
pkgdesc = A generic and open source machine emulator and virtualizer - Patched for extra functionality
pkgver = 2.12.0
- pkgrel = 2
+ pkgrel = 3
url = http://wiki.qemu.org/
arch = x86_64
license = GPL2
@@ -41,6 +41,7 @@ pkgbase = qemu-patched
source = cpu-pinning.patch
source = audio-improvements.patch
source = amd-smt-fixes-v7.patch
+ source = ps2-fixes-v2.patch
sha256sums = e69301f361ff65bf5dabd8a19196aeaa5613c1b5ae1678f0823bdf50e7d5c6fc
sha256sums = SKIP
sha256sums = c39bcde4a09165e64419fd2033b3532378bba84d509d39e2d51694d44c1f8d88
@@ -49,6 +50,7 @@ pkgbase = qemu-patched
sha256sums = 5c6baf8d171a75c342ffcc5c4259570b3d8d4f34166d7bc1f694ecf571662f2d
sha256sums = f54184f2eedf6e3eb1bf66f8f853df5e18cf62cad072fa4937744524d11a3f2b
sha256sums = 4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b
+ sha256sums = 6d83a0f70c5f57a0c0fbb657b47ecceeb79273487625f5b29639f105261c33f8
pkgname = qemu-patched
optdepends = qemu-patched-arch-extra: extra architectures support
diff --git a/PKGBUILD b/PKGBUILD
index cf48ab1e26f1..10bb705bbb83 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -8,7 +8,7 @@ pkgname=(qemu-patched qemu-patched-headless qemu-patched-arch-extra qemu-patched
_pkgname=qemu
pkgdesc="A generic and open source machine emulator and virtualizer - Patched for extra functionality"
pkgver=2.12.0
-pkgrel=2
+pkgrel=3
arch=(x86_64)
license=(GPL2 LGPL2.1)
url="http://wiki.qemu.org/"
@@ -22,7 +22,8 @@ source=("$url/download/${_pkgname}-${pkgver}.tar.xz"{,.sig}
allow_elf64.patch
cpu-pinning.patch
audio-improvements.patch
- amd-smt-fixes-v7.patch)
+ amd-smt-fixes-v7.patch
+ ps2-fixes-v2.patch)
sha256sums=('e69301f361ff65bf5dabd8a19196aeaa5613c1b5ae1678f0823bdf50e7d5c6fc'
'SKIP'
'c39bcde4a09165e64419fd2033b3532378bba84d509d39e2d51694d44c1f8d88'
@@ -30,7 +31,8 @@ sha256sums=('e69301f361ff65bf5dabd8a19196aeaa5613c1b5ae1678f0823bdf50e7d5c6fc'
'59751f1ed26ea61b2a37ebee4be6979e584a450b611282138a0893aa9173e2e4'
'5c6baf8d171a75c342ffcc5c4259570b3d8d4f34166d7bc1f694ecf571662f2d'
'f54184f2eedf6e3eb1bf66f8f853df5e18cf62cad072fa4937744524d11a3f2b'
- '4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b')
+ '4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b'
+ '6d83a0f70c5f57a0c0fbb657b47ecceeb79273487625f5b29639f105261c33f8')
validpgpkeys=('CEACC9E15534EBABB82D3FA03353C9CEF108B584')
case $CARCH in
@@ -49,6 +51,7 @@ prepare() {
patch -p1 < ../cpu-pinning.patch
patch -p1 < ../audio-improvements.patch
patch -p1 < ../amd-smt-fixes-v7.patch
+ patch -p1 < ../ps2-fixes-v2.patch
}
build() {
diff --git a/ps2-fixes-v2.patch b/ps2-fixes-v2.patch
new file mode 100644
index 000000000000..3aa3f90ed5ae
--- /dev/null
+++ b/ps2-fixes-v2.patch
@@ -0,0 +1,315 @@
+This allows guest's to correctly reinitialize and identify the mouse
+should the guest decide to re-scan or reset during mouse input events.
+
+When the guest sends the "Identify" command, due to the PC's hardware
+architecutre it is impossible to reliably determine the response from
+the command amongst other streaming data, such as mouse or keyboard
+events. Standard practice is for the guest to disable the device and
+then issue the identify command, so this must be obeyed.
+
+Signed-off-by: Geoffrey McRae <address@hidden>
+---
+ hw/input/ps2.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/hw/input/ps2.c b/hw/input/ps2.c
+index 06f5d2ac4a..f84a8f5179 100644
+--- a/hw/input/ps2.c
++++ b/hw/input/ps2.c
+@@ -232,6 +232,9 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
+ uint16_t keycode = 0;
+ int mod;
+
++ if (!s->scan_enabled)
++ return;
++
+ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+ assert(evt->type == INPUT_EVENT_KIND_KEY);
+ qcode = qemu_input_key_value_to_qcode(key->key);
+@@ -673,6 +676,9 @@ static void ps2_mouse_sync(DeviceState *dev)
+ {
+ PS2MouseState *s = (PS2MouseState *)dev;
+
++ if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
++ return;
++
+ if (s->mouse_buttons) {
+ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+ }
+@@ -776,6 +782,7 @@ void ps2_write_mouse(void *opaque, int val)
+ s->mouse_resolution = 2;
+ s->mouse_status = 0;
+ s->mouse_type = 0;
++ ps2_reset_queue(&s->common);
+ ps2_queue(&s->common, AUX_ACK);
+ ps2_queue(&s->common, 0xaa);
+ ps2_queue(&s->common, s->mouse_type);
+--
+2.14.2
+
+This fixes an issue by adding bounds checking to multi-byte packets
+where the PS/2 mouse data stream may become corrupted due to data being
+discarded when the PS/2 ringbuffer is full.
+
+Interrupts for Multi-byte responses are postponed until the final byte
+has been queued.
+
+These changes fix a bug where windows guests drop the mouse device
+entirely requring the guest to be restarted.
+
+Signed-off-by: Geoffrey McRae <address@hidden>
+---
+ hw/input/ps2.c | 120 +++++++++++++++++++++++++++++++++++++------------
+ include/hw/input/ps2.h | 5 +++
+ 2 files changed, 96 insertions(+), 29 deletions(-)
+
+diff --git a/hw/input/ps2.c b/hw/input/ps2.c
+index f84a8f5179..0580ca0700 100644
+--- a/hw/input/ps2.c
++++ b/hw/input/ps2.c
+@@ -188,16 +188,60 @@ static void ps2_reset_queue(PS2State *s)
+ q->count = 0;
+ }
+
+-void ps2_queue(PS2State *s, int b)
++void ps2_queue_noirq(PS2State *s, int b)
+ {
+ PS2Queue *q = &s->queue;
+
+- if (q->count >= PS2_QUEUE_SIZE - 1)
++ if (q->count == PS2_QUEUE_SIZE)
+ return;
++
+ q->data[q->wptr] = b;
+ if (++q->wptr == PS2_QUEUE_SIZE)
+ q->wptr = 0;
+ q->count++;
++}
++
++void ps2_raise_irq(PS2State *s)
++{
++ s->update_irq(s->update_arg, 1);
++}
++
++void ps2_queue(PS2State *s, int b)
++{
++ ps2_queue_noirq(s, b);
++ s->update_irq(s->update_arg, 1);
++}
++
++void ps2_queue_2(PS2State *s, int b1, int b2)
++{
++ if (PS2_QUEUE_SIZE - s->queue.count < 2)
++ return;
++
++ ps2_queue_noirq(s, b1);
++ ps2_queue_noirq(s, b2);
++ s->update_irq(s->update_arg, 1);
++}
++
++void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
++{
++ if (PS2_QUEUE_SIZE - s->queue.count < 3)
++ return;
++
++ ps2_queue_noirq(s, b1);
++ ps2_queue_noirq(s, b2);
++ ps2_queue_noirq(s, b3);
++ s->update_irq(s->update_arg, 1);
++}
++
++void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
++{
++ if (PS2_QUEUE_SIZE - s->queue.count < 4)
++ return;
++
++ ps2_queue_noirq(s, b1);
++ ps2_queue_noirq(s, b2);
++ ps2_queue_noirq(s, b3);
++ ps2_queue_noirq(s, b4);
+ s->update_irq(s->update_arg, 1);
+ }
+
+@@ -499,13 +543,17 @@ void ps2_write_keyboard(void *opaque, int val)
+ ps2_queue(&s->common, KBD_REPLY_RESEND);
+ break;
+ case KBD_CMD_GET_ID:
+- ps2_queue(&s->common, KBD_REPLY_ACK);
+ /* We emulate a MF2 AT keyboard here */
+- ps2_queue(&s->common, KBD_REPLY_ID);
+ if (s->translate)
+- ps2_queue(&s->common, 0x41);
++ ps2_queue_3(&s->common,
++ KBD_REPLY_ACK,
++ KBD_REPLY_ID,
++ 0x41);
+ else
+- ps2_queue(&s->common, 0x83);
++ ps2_queue_3(&s->common,
++ KBD_REPLY_ACK,
++ KBD_REPLY_ID,
++ 0x83);
+ break;
+ case KBD_CMD_ECHO:
+ ps2_queue(&s->common, KBD_CMD_ECHO);
+@@ -532,8 +580,9 @@ void ps2_write_keyboard(void *opaque, int val)
+ break;
+ case KBD_CMD_RESET:
+ ps2_reset_keyboard(s);
+- ps2_queue(&s->common, KBD_REPLY_ACK);
+- ps2_queue(&s->common, KBD_REPLY_POR);
++ ps2_queue_2(&s->common,
++ KBD_REPLY_ACK,
++ KBD_REPLY_POR);
+ break;
+ default:
+ ps2_queue(&s->common, KBD_REPLY_RESEND);
+@@ -542,8 +591,11 @@ void ps2_write_keyboard(void *opaque, int val)
+ break;
+ case KBD_CMD_SCANCODE:
+ if (val == 0) {
+- ps2_queue(&s->common, KBD_REPLY_ACK);
+- ps2_put_keycode(s, s->scancode_set);
++ if (s->common.queue.count <= PS2_QUEUE_SIZE - 2)
++ {
++ ps2_queue(&s->common, KBD_REPLY_ACK);
++ ps2_put_keycode(s, s->scancode_set);
++ }
+ } else if (val >= 1 && val <= 3) {
+ s->scancode_set = val;
+ ps2_queue(&s->common, KBD_REPLY_ACK);
+@@ -575,11 +627,15 @@ void ps2_keyboard_set_translation(void *opaque, int mode)
+ s->translate = mode;
+ }
+
+-static void ps2_mouse_send_packet(PS2MouseState *s)
++static int ps2_mouse_send_packet(PS2MouseState *s)
+ {
+ unsigned int b;
+ int dx1, dy1, dz1;
+
++ const int needed = 3 + (s->mouse_type - 2);
++ if (PS2_QUEUE_SIZE - s->common.queue.count < needed)
++ return 0;
++
+ dx1 = s->mouse_dx;
+ dy1 = s->mouse_dy;
+ dz1 = s->mouse_dz;
+@@ -593,9 +649,9 @@ static void ps2_mouse_send_packet(PS2MouseState *s)
+ else if (dy1 < -127)
+ dy1 = -127;
+ b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
+- ps2_queue(&s->common, b);
+- ps2_queue(&s->common, dx1 & 0xff);
+- ps2_queue(&s->common, dy1 & 0xff);
++ ps2_queue_noirq(&s->common, b);
++ ps2_queue_noirq(&s->common, dx1 & 0xff);
++ ps2_queue_noirq(&s->common, dy1 & 0xff);
+ /* extra byte for IMPS/2 or IMEX */
+ switch(s->mouse_type) {
+ default:
+@@ -605,7 +661,7 @@ static void ps2_mouse_send_packet(PS2MouseState *s)
+ dz1 = 127;
+ else if (dz1 < -127)
+ dz1 = -127;
+- ps2_queue(&s->common, dz1 & 0xff);
++ ps2_queue_noirq(&s->common, dz1 & 0xff);
+ break;
+ case 4:
+ if (dz1 > 7)
+@@ -613,15 +669,19 @@ static void ps2_mouse_send_packet(PS2MouseState *s)
+ else if (dz1 < -7)
+ dz1 = -7;
+ b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
+- ps2_queue(&s->common, b);
++ ps2_queue_noirq(&s->common, b);
+ break;
+ }
+
++ ps2_raise_irq(&s->common);
++
+ trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
+ /* update deltas */
+ s->mouse_dx -= dx1;
+ s->mouse_dy -= dy1;
+ s->mouse_dz -= dz1;
++
++ return 1;
+ }
+
+ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
+@@ -683,10 +743,9 @@ static void ps2_mouse_sync(DeviceState *dev)
+ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+ }
+ if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
+- while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
+- /* if not remote, send event. Multiple events are sent if
+- too big deltas */
+- ps2_mouse_send_packet(s);
++ /* if not remote, send event. Multiple events are sent if
++ too big deltas */
++ while(ps2_mouse_send_packet(s)) {
+ if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
+ break;
+ }
+@@ -745,8 +804,9 @@ void ps2_write_mouse(void *opaque, int val)
+ ps2_queue(&s->common, AUX_ACK);
+ break;
+ case AUX_GET_TYPE:
+- ps2_queue(&s->common, AUX_ACK);
+- ps2_queue(&s->common, s->mouse_type);
++ ps2_queue_2(&s->common,
++ AUX_ACK,
++ s->mouse_type);
+ break;
+ case AUX_SET_RES:
+ case AUX_SET_SAMPLE:
+@@ -754,10 +814,11 @@ void ps2_write_mouse(void *opaque, int val)
+ ps2_queue(&s->common, AUX_ACK);
+ break;
+ case AUX_GET_SCALE:
+- ps2_queue(&s->common, AUX_ACK);
+- ps2_queue(&s->common, s->mouse_status);
+- ps2_queue(&s->common, s->mouse_resolution);
+- ps2_queue(&s->common, s->mouse_sample_rate);
++ ps2_queue_4(&s->common,
++ AUX_ACK,
++ s->mouse_status,
++ s->mouse_resolution,
++ s->mouse_sample_rate);
+ break;
+ case AUX_POLL:
+ ps2_queue(&s->common, AUX_ACK);
+@@ -783,9 +844,10 @@ void ps2_write_mouse(void *opaque, int val)
+ s->mouse_status = 0;
+ s->mouse_type = 0;
+ ps2_reset_queue(&s->common);
+- ps2_queue(&s->common, AUX_ACK);
+- ps2_queue(&s->common, 0xaa);
+- ps2_queue(&s->common, s->mouse_type);
++ ps2_queue_3(&s->common,
++ AUX_ACK,
++ 0xaa,
++ s->mouse_type);
+ break;
+ default:
+ break;
+diff --git a/include/hw/input/ps2.h b/include/hw/input/ps2.h
+index 94709b8502..213aa16aa3 100644
+--- a/include/hw/input/ps2.h
++++ b/include/hw/input/ps2.h
+@@ -37,7 +37,12 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);
+ void ps2_write_mouse(void *, int val);
+ void ps2_write_keyboard(void *, int val);
+ uint32_t ps2_read_data(PS2State *s);
++void ps2_queue_noirq(PS2State *s, int b);
++void ps2_raise_irq(PS2State *s);
+ void ps2_queue(PS2State *s, int b);
++void ps2_queue_2(PS2State *s, int b1, int b2);
++void ps2_queue_3(PS2State *s, int b1, int b2, int b3);
++void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4);
+ void ps2_keyboard_set_translation(void *opaque, int mode);
+ void ps2_mouse_fake_event(void *opaque);
+
+--
+2.14.2