summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorVaporeon2018-08-29 02:46:34 +1200
committerVaporeon2018-08-29 02:46:34 +1200
commit6deed290a0f3db7fd433395a6d1305cd5726c0db (patch)
tree6bf2c361a3e3cd478098d04100c0b7cce9d5174c
parentb5d8c4ec72a9b2fe1acc0de2da58332a00459485 (diff)
downloadaur-6deed290a0f3db7fd433395a6d1305cd5726c0db.tar.gz
update 3.0.0
-rw-r--r--.SRCINFO20
-rw-r--r--PKGBUILD18
-rw-r--r--amd-smt-fixes-v7.patch1148
-rw-r--r--pa-fixes.patch (renamed from audio-improvements.patch)350
-rw-r--r--ps2-fixes-v2.patch315
5 files changed, 53 insertions, 1798 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 8bafd325aefe..37b4ca2917c2 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,9 +1,9 @@
# Generated by mksrcinfo v8
-# Mon Aug 6 00:22:48 UTC 2018
+# Tue Aug 28 14:34:40 UTC 2018
pkgbase = qemu-patched
pkgdesc = A generic and open source machine emulator and virtualizer - Patched for extra functionality
- pkgver = 2.12.1
- pkgrel = 4
+ pkgver = 3.0.0
+ pkgrel = 1
url = http://wiki.qemu.org/
arch = x86_64
license = GPL2
@@ -33,24 +33,20 @@ pkgbase = qemu-patched
depends = spice
depends = libcacard
depends = usbredir
- source = http://wiki.qemu.org//download/qemu-2.12.1.tar.xz
- source = http://wiki.qemu.org//download/qemu-2.12.1.tar.xz.sig
+ source = http://wiki.qemu.org//download/qemu-3.0.0.tar.xz
+ source = http://wiki.qemu.org//download/qemu-3.0.0.tar.xz.sig
source = qemu-ga.service
source = 65-kvm.rules
source = allow_elf64.patch
source = cpu-pinning.patch
- source = audio-improvements.patch
- source = amd-smt-fixes-v7.patch
- source = ps2-fixes-v2.patch
- sha256sums = 33583800e0006cd00b78226b85be5a27c8e3b156bed2e60e83ecbeb7b9b8364f
+ source = pa-fixes.patch
+ sha256sums = 8d7af64fe8bd5ea5c3bdf17131a8b858491bcce1ee3839425a6d91fb821b5713
sha256sums = SKIP
sha256sums = c39bcde4a09165e64419fd2033b3532378bba84d509d39e2d51694d44c1f8d88
sha256sums = a66f0e791b16b03b91049aac61a25950d93e962e1b2ba64a38c6ad7f609b532c
sha256sums = 59751f1ed26ea61b2a37ebee4be6979e584a450b611282138a0893aa9173e2e4
sha256sums = 5c6baf8d171a75c342ffcc5c4259570b3d8d4f34166d7bc1f694ecf571662f2d
- sha256sums = 2368e94e0e0c7bbabe5117f2019ceb0e942726d2161d9984d231f775a71d9b19
- sha256sums = 4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b
- sha256sums = 6d83a0f70c5f57a0c0fbb657b47ecceeb79273487625f5b29639f105261c33f8
+ sha256sums = 0fd49e734ee141b90d7d41d534f5635c175734a454e61c1c7e31b9fec3e19508
pkgname = qemu-patched
optdepends = qemu-patched-arch-extra: extra architectures support
diff --git a/PKGBUILD b/PKGBUILD
index 2a94bf24c75f..e4dd5b2bde08 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -7,8 +7,8 @@ pkgname=(qemu-patched qemu-patched-headless qemu-patched-arch-extra qemu-patched
qemu-patched-block-{iscsi,rbd,gluster} qemu-patched-guest-agent)
_pkgname=qemu
pkgdesc="A generic and open source machine emulator and virtualizer - Patched for extra functionality"
-pkgver=2.12.1
-pkgrel=4
+pkgver=3.0.0
+pkgrel=1
arch=(x86_64)
license=(GPL2 LGPL2.1)
url="http://wiki.qemu.org/"
@@ -21,18 +21,14 @@ source=("$url/download/${_pkgname}-${pkgver}.tar.xz"{,.sig}
65-kvm.rules
allow_elf64.patch
cpu-pinning.patch
- audio-improvements.patch
- amd-smt-fixes-v7.patch
- ps2-fixes-v2.patch)
-sha256sums=('33583800e0006cd00b78226b85be5a27c8e3b156bed2e60e83ecbeb7b9b8364f'
+ pa-fixes.patch)
+sha256sums=('8d7af64fe8bd5ea5c3bdf17131a8b858491bcce1ee3839425a6d91fb821b5713'
'SKIP'
'c39bcde4a09165e64419fd2033b3532378bba84d509d39e2d51694d44c1f8d88'
'a66f0e791b16b03b91049aac61a25950d93e962e1b2ba64a38c6ad7f609b532c'
'59751f1ed26ea61b2a37ebee4be6979e584a450b611282138a0893aa9173e2e4'
'5c6baf8d171a75c342ffcc5c4259570b3d8d4f34166d7bc1f694ecf571662f2d'
- '2368e94e0e0c7bbabe5117f2019ceb0e942726d2161d9984d231f775a71d9b19'
- '4a06b86eaa9cde2ad5613a7cd7ac0a222b388a116f5dcf285252dddcb883108b'
- '6d83a0f70c5f57a0c0fbb657b47ecceeb79273487625f5b29639f105261c33f8')
+ '0fd49e734ee141b90d7d41d534f5635c175734a454e61c1c7e31b9fec3e19508')
validpgpkeys=('CEACC9E15534EBABB82D3FA03353C9CEF108B584')
case $CARCH in
@@ -49,9 +45,7 @@ prepare() {
patch -p1 < ../allow_elf64.patch
patch -p1 < ../cpu-pinning.patch
- patch -p0 < ../audio-improvements.patch
- patch -p1 < ../amd-smt-fixes-v7.patch
- patch -p1 < ../ps2-fixes-v2.patch
+ patch -p1 < ../pa-fixes.patch
}
build() {
diff --git a/amd-smt-fixes-v7.patch b/amd-smt-fixes-v7.patch
deleted file mode 100644
index 66fd9b2693be..000000000000
--- a/amd-smt-fixes-v7.patch
+++ /dev/null
@@ -1,1148 +0,0 @@
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index a20fe26..b6c1592 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -56,33 +56,240 @@
-
- #include "disas/capstone.h"
-
-+/* Helpers for building CPUID[2] descriptors: */
-+
-+struct CPUID2CacheDescriptorInfo {
-+ enum CacheType type;
-+ int level;
-+ int size;
-+ int line_size;
-+ int associativity;
-+};
-
--/* Cache topology CPUID constants: */
-+#define KiB 1024
-+#define MiB (1024 * 1024)
-
--/* CPUID Leaf 2 Descriptors */
-+/*
-+ * Known CPUID 2 cache descriptors.
-+ * From Intel SDM Volume 2A, CPUID instruction
-+ */
-+struct CPUID2CacheDescriptorInfo cpuid2_cache_descriptors[] = {
-+ [0x06] = { .level = 1, .type = ICACHE, .size = 8 * KiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x08] = { .level = 1, .type = ICACHE, .size = 16 * KiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x09] = { .level = 1, .type = ICACHE, .size = 32 * KiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0x0A] = { .level = 1, .type = DCACHE, .size = 8 * KiB,
-+ .associativity = 2, .line_size = 32, },
-+ [0x0C] = { .level = 1, .type = DCACHE, .size = 16 * KiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x0D] = { .level = 1, .type = DCACHE, .size = 16 * KiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0x0E] = { .level = 1, .type = DCACHE, .size = 24 * KiB,
-+ .associativity = 6, .line_size = 64, },
-+ [0x1D] = { .level = 2, .type = UNIFIED_CACHE, .size = 128 * KiB,
-+ .associativity = 2, .line_size = 64, },
-+ [0x21] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB,
-+ .associativity = 8, .line_size = 64, },
-+ /* lines per sector is not supported cpuid2_cache_descriptor(),
-+ * so descriptors 0x22, 0x23 are not included
-+ */
-+ [0x24] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB,
-+ .associativity = 16, .line_size = 64, },
-+ /* lines per sector is not supported cpuid2_cache_descriptor(),
-+ * so descriptors 0x25, 0x20 are not included
-+ */
-+ [0x2C] = { .level = 1, .type = DCACHE, .size = 32 * KiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0x30] = { .level = 1, .type = ICACHE, .size = 32 * KiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0x41] = { .level = 2, .type = UNIFIED_CACHE, .size = 128 * KiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x42] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x43] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x44] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x45] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB,
-+ .associativity = 4, .line_size = 32, },
-+ [0x46] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0x47] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0x48] = { .level = 2, .type = UNIFIED_CACHE, .size = 3 * MiB,
-+ .associativity = 12, .line_size = 64, },
-+ /* Descriptor 0x49 depends on CPU family/model, so it is not included */
-+ [0x4A] = { .level = 3, .type = UNIFIED_CACHE, .size = 6 * MiB,
-+ .associativity = 12, .line_size = 64, },
-+ [0x4B] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB,
-+ .associativity = 16, .line_size = 64, },
-+ [0x4C] = { .level = 3, .type = UNIFIED_CACHE, .size = 12 * MiB,
-+ .associativity = 12, .line_size = 64, },
-+ [0x4D] = { .level = 3, .type = UNIFIED_CACHE, .size = 16 * MiB,
-+ .associativity = 16, .line_size = 64, },
-+ [0x4E] = { .level = 2, .type = UNIFIED_CACHE, .size = 6 * MiB,
-+ .associativity = 24, .line_size = 64, },
-+ [0x60] = { .level = 1, .type = DCACHE, .size = 16 * KiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0x66] = { .level = 1, .type = DCACHE, .size = 8 * KiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0x67] = { .level = 1, .type = DCACHE, .size = 16 * KiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0x68] = { .level = 1, .type = DCACHE, .size = 32 * KiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0x78] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB,
-+ .associativity = 4, .line_size = 64, },
-+ /* lines per sector is not supported cpuid2_cache_descriptor(),
-+ * so descriptors 0x79, 0x7A, 0x7B, 0x7C are not included.
-+ */
-+ [0x7D] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0x7F] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB,
-+ .associativity = 2, .line_size = 64, },
-+ [0x80] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0x82] = { .level = 2, .type = UNIFIED_CACHE, .size = 256 * KiB,
-+ .associativity = 8, .line_size = 32, },
-+ [0x83] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB,
-+ .associativity = 8, .line_size = 32, },
-+ [0x84] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB,
-+ .associativity = 8, .line_size = 32, },
-+ [0x85] = { .level = 2, .type = UNIFIED_CACHE, .size = 2 * MiB,
-+ .associativity = 8, .line_size = 32, },
-+ [0x86] = { .level = 2, .type = UNIFIED_CACHE, .size = 512 * KiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0x87] = { .level = 2, .type = UNIFIED_CACHE, .size = 1 * MiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0xD0] = { .level = 3, .type = UNIFIED_CACHE, .size = 512 * KiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0xD1] = { .level = 3, .type = UNIFIED_CACHE, .size = 1 * MiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0xD2] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB,
-+ .associativity = 4, .line_size = 64, },
-+ [0xD6] = { .level = 3, .type = UNIFIED_CACHE, .size = 1 * MiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0xD7] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0xD8] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB,
-+ .associativity = 8, .line_size = 64, },
-+ [0xDC] = { .level = 3, .type = UNIFIED_CACHE, .size = 1.5 * MiB,
-+ .associativity = 12, .line_size = 64, },
-+ [0xDD] = { .level = 3, .type = UNIFIED_CACHE, .size = 3 * MiB,
-+ .associativity = 12, .line_size = 64, },
-+ [0xDE] = { .level = 3, .type = UNIFIED_CACHE, .size = 6 * MiB,
-+ .associativity = 12, .line_size = 64, },
-+ [0xE2] = { .level = 3, .type = UNIFIED_CACHE, .size = 2 * MiB,
-+ .associativity = 16, .line_size = 64, },
-+ [0xE3] = { .level = 3, .type = UNIFIED_CACHE, .size = 4 * MiB,
-+ .associativity = 16, .line_size = 64, },
-+ [0xE4] = { .level = 3, .type = UNIFIED_CACHE, .size = 8 * MiB,
-+ .associativity = 16, .line_size = 64, },
-+ [0xEA] = { .level = 3, .type = UNIFIED_CACHE, .size = 12 * MiB,
-+ .associativity = 24, .line_size = 64, },
-+ [0xEB] = { .level = 3, .type = UNIFIED_CACHE, .size = 18 * MiB,
-+ .associativity = 24, .line_size = 64, },
-+ [0xEC] = { .level = 3, .type = UNIFIED_CACHE, .size = 24 * MiB,
-+ .associativity = 24, .line_size = 64, },
-+};
-+
-+/*
-+ * "CPUID leaf 2 does not report cache descriptor information,
-+ * use CPUID leaf 4 to query cache parameters"
-+ */
-+#define CACHE_DESCRIPTOR_UNAVAILABLE 0xFF
-
--#define CPUID_2_L1D_32KB_8WAY_64B 0x2c
--#define CPUID_2_L1I_32KB_8WAY_64B 0x30
--#define CPUID_2_L2_2MB_8WAY_64B 0x7d
--#define CPUID_2_L3_16MB_16WAY_64B 0x4d
-+/*
-+ * Return a CPUID 2 cache descriptor for a given cache.
-+ * If no known descriptor is found, return CACHE_DESCRIPTOR_UNAVAILABLE
-+ */
-+static uint8_t cpuid2_cache_descriptor(CPUCacheInfo *cache)
-+{
-+ int i;
-+
-+ assert(cache->size > 0);
-+ assert(cache->level > 0);
-+ assert(cache->line_size > 0);
-+ assert(cache->associativity > 0);
-+ for (i = 0; i < ARRAY_SIZE(cpuid2_cache_descriptors); i++) {
-+ struct CPUID2CacheDescriptorInfo *d = &cpuid2_cache_descriptors[i];
-+ if (d->level == cache->level && d->type == cache->type &&
-+ d->size == cache->size && d->line_size == cache->line_size &&
-+ d->associativity == cache->associativity) {
-+ return i;
-+ }
-+ }
-
-+ return CACHE_DESCRIPTOR_UNAVAILABLE;
-+}
-
- /* CPUID Leaf 4 constants: */
-
- /* EAX: */
--#define CPUID_4_TYPE_DCACHE 1
--#define CPUID_4_TYPE_ICACHE 2
--#define CPUID_4_TYPE_UNIFIED 3
-+#define CACHE_TYPE_D 1
-+#define CACHE_TYPE_I 2
-+#define CACHE_TYPE_UNIFIED 3
-
--#define CPUID_4_LEVEL(l) ((l) << 5)
-+#define CACHE_LEVEL(l) (l << 5)
-
--#define CPUID_4_SELF_INIT_LEVEL (1 << 8)
--#define CPUID_4_FULLY_ASSOC (1 << 9)
-+#define CACHE_SELF_INIT_LEVEL (1 << 8)
-
- /* EDX: */
--#define CPUID_4_NO_INVD_SHARING (1 << 0)
--#define CPUID_4_INCLUSIVE (1 << 1)
--#define CPUID_4_COMPLEX_IDX (1 << 2)
-+#define CACHE_NO_INVD_SHARING (1 << 0)
-+#define CACHE_INCLUSIVE (1 << 1)
-+#define CACHE_COMPLEX_IDX (1 << 2)
-+
-+/* Encode CacheType for CPUID[4].EAX */
-+#define CACHE_TYPE(t) (((t) == DCACHE) ? CACHE_TYPE_D : \
-+ ((t) == ICACHE) ? CACHE_TYPE_I : \
-+ ((t) == UNIFIED_CACHE) ? CACHE_TYPE_UNIFIED : \
-+ 0 /* Invalid value */)
-+
-+
-+/* Encode cache info for CPUID[4] */
-+static void encode_cache_cpuid4(CPUCacheInfo *cache,
-+ int num_apic_ids, int num_cores,
-+ uint32_t *eax, uint32_t *ebx,
-+ uint32_t *ecx, uint32_t *edx)
-+{
-+ assert(cache->size == cache->line_size * cache->associativity *
-+ cache->partitions * cache->sets);
-+
-+ assert(num_apic_ids > 0);
-+ *eax = CACHE_TYPE(cache->type) |
-+ CACHE_LEVEL(cache->level) |
-+ (cache->self_init ? CACHE_SELF_INIT_LEVEL : 0) |
-+ ((num_cores - 1) << 26) |
-+ ((num_apic_ids - 1) << 14);
-+
-+ assert(cache->line_size > 0);
-+ assert(cache->partitions > 0);
-+ assert(cache->associativity > 0);
-+ /* We don't implement fully-associative caches */
-+ assert(cache->associativity < cache->sets);
-+ *ebx = (cache->line_size - 1) |
-+ ((cache->partitions - 1) << 12) |
-+ ((cache->associativity - 1) << 22);
-+
-+ assert(cache->sets > 0);
-+ *ecx = cache->sets - 1;
-+
-+ *edx = (cache->no_invd_sharing ? CACHE_NO_INVD_SHARING : 0) |
-+ (cache->inclusive ? CACHE_INCLUSIVE : 0) |
-+ (cache->complex_indexing ? CACHE_COMPLEX_IDX : 0);
-+}
-+
-+/* Encode cache info for CPUID[0x80000005].ECX or CPUID[0x80000005].EDX */
-+static uint32_t encode_cache_cpuid80000005(CPUCacheInfo *cache)
-+{
-+ assert(cache->size % 1024 == 0);
-+ assert(cache->lines_per_tag > 0);
-+ assert(cache->associativity > 0);
-+ assert(cache->line_size > 0);
-+ return ((cache->size / 1024) << 24) | (cache->associativity << 16) |
-+ (cache->lines_per_tag << 8) | (cache->line_size);
-+}
-
- #define ASSOC_FULL 0xFF
-
-@@ -100,57 +307,140 @@
- a == ASSOC_FULL ? 0xF : \
- 0 /* invalid value */)
-
-+/*
-+ * Encode cache info for CPUID[0x80000006].ECX and CPUID[0x80000006].EDX
-+ * @l3 can be NULL.
-+ */
-+static void encode_cache_cpuid80000006(CPUCacheInfo *l2,
-+ CPUCacheInfo *l3,
-+ uint32_t *ecx, uint32_t *edx)
-+{
-+ assert(l2->size % 1024 == 0);
-+ assert(l2->associativity > 0);
-+ assert(l2->lines_per_tag > 0);
-+ assert(l2->line_size > 0);
-+ *ecx = ((l2->size / 1024) << 16) |
-+ (AMD_ENC_ASSOC(l2->associativity) << 12) |
-+ (l2->lines_per_tag << 8) | (l2->line_size);
-+
-+ if (l3) {
-+ assert(l3->size % (512 * 1024) == 0);
-+ assert(l3->associativity > 0);
-+ assert(l3->lines_per_tag > 0);
-+ assert(l3->line_size > 0);
-+ *edx = ((l3->size / (512 * 1024)) << 18) |
-+ (AMD_ENC_ASSOC(l3->associativity) << 12) |
-+ (l3->lines_per_tag << 8) | (l3->line_size);
-+ } else {
-+ *edx = 0;
-+ }
-+}
-
- /* Definitions of the hardcoded cache entries we expose: */
-
- /* L1 data cache: */
--#define L1D_LINE_SIZE 64
--#define L1D_ASSOCIATIVITY 8
--#define L1D_SETS 64
--#define L1D_PARTITIONS 1
--/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
--#define L1D_DESCRIPTOR CPUID_2_L1D_32KB_8WAY_64B
-+static CPUCacheInfo l1d_cache = {
-+ .type = DCACHE,
-+ .level = 1,
-+ .size = 32 * KiB,
-+ .self_init = 1,
-+ .line_size = 64,
-+ .associativity = 8,
-+ .sets = 64,
-+ .partitions = 1,
-+ .no_invd_sharing = true,
-+};
-+
- /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
--#define L1D_LINES_PER_TAG 1
--#define L1D_SIZE_KB_AMD 64
--#define L1D_ASSOCIATIVITY_AMD 2
-+static CPUCacheInfo l1d_cache_amd = {
-+ .type = DCACHE,
-+ .level = 1,
-+ .size = 64 * KiB,
-+ .self_init = 1,
-+ .line_size = 64,
-+ .associativity = 2,
-+ .sets = 512,
-+ .partitions = 1,
-+ .lines_per_tag = 1,
-+ .no_invd_sharing = true,
-+};
-
- /* L1 instruction cache: */
--#define L1I_LINE_SIZE 64
--#define L1I_ASSOCIATIVITY 8
--#define L1I_SETS 64
--#define L1I_PARTITIONS 1
--/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
--#define L1I_DESCRIPTOR CPUID_2_L1I_32KB_8WAY_64B
-+static CPUCacheInfo l1i_cache = {
-+ .type = ICACHE,
-+ .level = 1,
-+ .size = 32 * KiB,
-+ .self_init = 1,
-+ .line_size = 64,
-+ .associativity = 8,
-+ .sets = 64,
-+ .partitions = 1,
-+ .no_invd_sharing = true,
-+};
-+
- /*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
--#define L1I_LINES_PER_TAG 1
--#define L1I_SIZE_KB_AMD 64
--#define L1I_ASSOCIATIVITY_AMD 2
-+static CPUCacheInfo l1i_cache_amd = {
-+ .type = ICACHE,
-+ .level = 1,
-+ .size = 64 * KiB,
-+ .self_init = 1,
-+ .line_size = 64,
-+ .associativity = 2,
-+ .sets = 512,
-+ .partitions = 1,
-+ .lines_per_tag = 1,
-+ .no_invd_sharing = true,
-+};
-
- /* Level 2 unified cache: */
--#define L2_LINE_SIZE 64
--#define L2_ASSOCIATIVITY 16
--#define L2_SETS 4096
--#define L2_PARTITIONS 1
--/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 4MiB */
-+static CPUCacheInfo l2_cache = {
-+ .type = UNIFIED_CACHE,
-+ .level = 2,
-+ .size = 4 * MiB,
-+ .self_init = 1,
-+ .line_size = 64,
-+ .associativity = 16,
-+ .sets = 4096,
-+ .partitions = 1,
-+ .no_invd_sharing = true,
-+};
-+
- /*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */
--#define L2_DESCRIPTOR CPUID_2_L2_2MB_8WAY_64B
-+static CPUCacheInfo l2_cache_cpuid2 = {
-+ .type = UNIFIED_CACHE,
-+ .level = 2,
-+ .size = 2 * MiB,
-+ .line_size = 64,
-+ .associativity = 8,
-+};
-+
-+
- /*FIXME: CPUID leaf 0x80000006 is inconsistent with leaves 2 & 4 */
--#define L2_LINES_PER_TAG 1
--#define L2_SIZE_KB_AMD 512
-+static CPUCacheInfo l2_cache_amd = {
-+ .type = UNIFIED_CACHE,
-+ .level = 2,
-+ .size = 512 * KiB,
-+ .line_size = 64,
-+ .lines_per_tag = 1,
-+ .associativity = 8,
-+ .sets = 1024,
-+ .partitions = 1,
-+};
-
- /* Level 3 unified cache: */
--#define L3_SIZE_KB 0 /* disabled */
--#define L3_ASSOCIATIVITY 0 /* disabled */
--#define L3_LINES_PER_TAG 0 /* disabled */
--#define L3_LINE_SIZE 0 /* disabled */
--#define L3_N_LINE_SIZE 64
--#define L3_N_ASSOCIATIVITY 16
--#define L3_N_SETS 16384
--#define L3_N_PARTITIONS 1
--#define L3_N_DESCRIPTOR CPUID_2_L3_16MB_16WAY_64B
--#define L3_N_LINES_PER_TAG 1
--#define L3_N_SIZE_KB_AMD 16384
-+static CPUCacheInfo l3_cache = {
-+ .type = UNIFIED_CACHE,
-+ .level = 3,
-+ .size = 16 * MiB,
-+ .line_size = 64,
-+ .associativity = 16,
-+ .sets = 16384,
-+ .partitions = 1,
-+ .lines_per_tag = 1,
-+ .self_init = true,
-+ .inclusive = true,
-+ .complex_indexing = true,
-+};
-
- /* TLB definitions: */
-
-@@ -3301,85 +3591,53 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- if (!cpu->enable_l3_cache) {
- *ecx = 0;
- } else {
-- *ecx = L3_N_DESCRIPTOR;
-+ *ecx = cpuid2_cache_descriptor(&l3_cache);
- }
-- *edx = (L1D_DESCRIPTOR << 16) | \
-- (L1I_DESCRIPTOR << 8) | \
-- (L2_DESCRIPTOR);
-+ *edx = (cpuid2_cache_descriptor(&l1d_cache) << 16) |
-+ (cpuid2_cache_descriptor(&l1i_cache) << 8) |
-+ (cpuid2_cache_descriptor(&l2_cache_cpuid2));
- break;
- case 4:
- /* cache info: needed for Core compatibility */
- if (cpu->cache_info_passthrough) {
- host_cpuid(index, count, eax, ebx, ecx, edx);
-+ /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
- *eax &= ~0xFC000000;
-+ if ((*eax & 31) && cs->nr_cores > 1) {
-+ *eax |= (cs->nr_cores - 1) << 26;
-+ }
- } else {
- *eax = 0;
- switch (count) {
- case 0: /* L1 dcache info */
-- *eax |= CPUID_4_TYPE_DCACHE | \
-- CPUID_4_LEVEL(1) | \
-- CPUID_4_SELF_INIT_LEVEL;
-- *ebx = (L1D_LINE_SIZE - 1) | \
-- ((L1D_PARTITIONS - 1) << 12) | \
-- ((L1D_ASSOCIATIVITY - 1) << 22);
-- *ecx = L1D_SETS - 1;
-- *edx = CPUID_4_NO_INVD_SHARING;
-+ encode_cache_cpuid4(&l1d_cache,
-+ 1, cs->nr_cores,
-+ eax, ebx, ecx, edx);
- break;
- case 1: /* L1 icache info */
-- *eax |= CPUID_4_TYPE_ICACHE | \
-- CPUID_4_LEVEL(1) | \
-- CPUID_4_SELF_INIT_LEVEL;
-- *ebx = (L1I_LINE_SIZE - 1) | \
-- ((L1I_PARTITIONS - 1) << 12) | \
-- ((L1I_ASSOCIATIVITY - 1) << 22);
-- *ecx = L1I_SETS - 1;
-- *edx = CPUID_4_NO_INVD_SHARING;
-+ encode_cache_cpuid4(&l1i_cache,
-+ 1, cs->nr_cores,
-+ eax, ebx, ecx, edx);
- break;
- case 2: /* L2 cache info */
-- *eax |= CPUID_4_TYPE_UNIFIED | \
-- CPUID_4_LEVEL(2) | \
-- CPUID_4_SELF_INIT_LEVEL;
-- if (cs->nr_threads > 1) {
-- *eax |= (cs->nr_threads - 1) << 14;
-- }
-- *ebx = (L2_LINE_SIZE - 1) | \
-- ((L2_PARTITIONS - 1) << 12) | \
-- ((L2_ASSOCIATIVITY - 1) << 22);
-- *ecx = L2_SETS - 1;
-- *edx = CPUID_4_NO_INVD_SHARING;
-+ encode_cache_cpuid4(&l2_cache,
-+ cs->nr_threads, cs->nr_cores,
-+ eax, ebx, ecx, edx);
- break;
- case 3: /* L3 cache info */
-- if (!cpu->enable_l3_cache) {
-- *eax = 0;
-- *ebx = 0;
-- *ecx = 0;
-- *edx = 0;
-+ pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);
-+ if (cpu->enable_l3_cache) {
-+ encode_cache_cpuid4(&l3_cache,
-+ (1 << pkg_offset), cs->nr_cores,
-+ eax, ebx, ecx, edx);
- break;
- }
-- *eax |= CPUID_4_TYPE_UNIFIED | \
-- CPUID_4_LEVEL(3) | \
-- CPUID_4_SELF_INIT_LEVEL;
-- pkg_offset = apicid_pkg_offset(cs->nr_cores, cs->nr_threads);
-- *eax |= ((1 << pkg_offset) - 1) << 14;
-- *ebx = (L3_N_LINE_SIZE - 1) | \
-- ((L3_N_PARTITIONS - 1) << 12) | \
-- ((L3_N_ASSOCIATIVITY - 1) << 22);
-- *ecx = L3_N_SETS - 1;
-- *edx = CPUID_4_INCLUSIVE | CPUID_4_COMPLEX_IDX;
-- break;
-+ /* fall through */
- default: /* end of info */
-- *eax = 0;
-- *ebx = 0;
-- *ecx = 0;
-- *edx = 0;
-+ *eax = *ebx = *ecx = *edx = 0;
- break;
- }
- }
--
-- /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
-- if ((*eax & 31) && cs->nr_cores > 1) {
-- *eax |= (cs->nr_cores - 1) << 26;
-- }
- break;
- case 5:
- /* mwait info: needed for Core compatibility */
-@@ -3583,10 +3841,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- (L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES);
- *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
- (L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES);
-- *ecx = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \
-- (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE);
-- *edx = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \
-- (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE);
-+ *ecx = encode_cache_cpuid80000005(&l1d_cache_amd);
-+ *edx = encode_cache_cpuid80000005(&l1i_cache_amd);
- break;
- case 0x80000006:
- /* cache info (L2 cache) */
-@@ -3602,18 +3858,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- (L2_DTLB_4K_ENTRIES << 16) | \
- (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
- (L2_ITLB_4K_ENTRIES);
-- *ecx = (L2_SIZE_KB_AMD << 16) | \
-- (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \
-- (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE);
-- if (!cpu->enable_l3_cache) {
-- *edx = ((L3_SIZE_KB / 512) << 18) | \
-- (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
-- (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
-- } else {
-- *edx = ((L3_N_SIZE_KB_AMD / 512) << 18) | \
-- (AMD_ENC_ASSOC(L3_N_ASSOCIATIVITY) << 12) | \
-- (L3_N_LINES_PER_TAG << 8) | (L3_N_LINE_SIZE);
-- }
-+ encode_cache_cpuid80000006(&l2_cache_amd,
-+ cpu->enable_l3_cache ? &l3_cache : NULL,
-+ ecx, edx);
- break;
- case 0x80000007:
- *eax = 0;
-diff --git a/target/i386/cpu.h b/target/i386/cpu.h
-index 1b219fa..fa03e2c 100644
---- a/target/i386/cpu.h
-+++ b/target/i386/cpu.h
-@@ -1044,6 +1044,59 @@ typedef enum TPRAccess {
- TPR_ACCESS_WRITE,
- } TPRAccess;
-
-+/* Cache information data structures: */
-+
-+enum CacheType {
-+ DCACHE,
-+ ICACHE,
-+ UNIFIED_CACHE
-+};
-+
-+typedef struct CPUCacheInfo {
-+ enum CacheType type;
-+ uint8_t level;
-+ /* Size in bytes */
-+ uint32_t size;
-+ /* Line size, in bytes */
-+ uint16_t line_size;
-+ /*
-+ * Associativity.
-+ * Note: representation of fully-associative caches is not implemented
-+ */
-+ uint8_t associativity;
-+ /* Physical line partitions. CPUID[0x8000001D].EBX, CPUID[4].EBX */
-+ uint8_t partitions;
-+ /* Number of sets. CPUID[0x8000001D].ECX, CPUID[4].ECX */
-+ uint32_t sets;
-+ /*
-+ * Lines per tag.
-+ * AMD-specific: CPUID[0x80000005], CPUID[0x80000006].
-+ * (Is this synonym to @partitions?)
-+ */
-+ uint8_t lines_per_tag;
-+
-+ /* Self-initializing cache */
-+ bool self_init;
-+ /*
-+ * WBINVD/INVD is not guaranteed to act upon lower level caches of
-+ * non-originating threads sharing this cache.
-+ * CPUID[4].EDX[bit 0], CPUID[0x8000001D].EDX[bit 0]
-+ */
-+ bool no_invd_sharing;
-+ /*
-+ * Cache is inclusive of lower cache levels.
-+ * CPUID[4].EDX[bit 1], CPUID[0x8000001D].EDX[bit 1].
-+ */
-+ bool inclusive;
-+ /*
-+ * A complex function is used to index the cache, potentially using all
-+ * address bits. CPUID[4].EDX[bit 2].
-+ */
-+ bool complex_indexing;
-+} CPUCacheInfo;
-+
-+
-+
- typedef struct CPUX86State {
- /* standard registers */
- target_ulong regs[CPU_NB_REGS];
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index b6c1592..a518a0f 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -1105,6 +1105,7 @@ struct X86CPUDefinition {
- int stepping;
- FeatureWordArray features;
- const char *model_id;
-+ CPUCaches cache_info;
- };
-
- static X86CPUDefinition builtin_x86_defs[] = {
-@@ -3242,6 +3243,9 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
- env->features[w] = def->features[w];
- }
-
-+ /* Load Cache information from the X86CPUDefinition */
-+ memcpy(&env->cache_info, &def->cache_info, sizeof(CPUCaches));
-+
- /* Special cases not set in the X86CPUDefinition structs: */
- /* TODO: in-kernel irqchip for hvf */
- if (kvm_enabled()) {
-diff --git a/target/i386/cpu.h b/target/i386/cpu.h
-index fa03e2c..1213bb7 100644
---- a/target/i386/cpu.h
-+++ b/target/i386/cpu.h
-@@ -1096,6 +1096,13 @@ typedef struct CPUCacheInfo {
- } CPUCacheInfo;
-
-
-+typedef struct CPUCaches {
-+ bool valid;
-+ CPUCacheInfo l1d_cache;
-+ CPUCacheInfo l1i_cache;
-+ CPUCacheInfo l2_cache;
-+ CPUCacheInfo l3_cache;
-+} CPUCaches;
-
- typedef struct CPUX86State {
- /* standard registers */
-@@ -1282,6 +1289,7 @@ typedef struct CPUX86State {
- /* Features that were explicitly enabled/disabled */
- FeatureWordArray user_features;
- uint32_t cpuid_model[12];
-+ CPUCaches cache_info;
-
- /* MTRRs */
- uint64_t mtrr_fixed[11];
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index a518a0f..5d88363 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -2302,6 +2302,54 @@ static X86CPUDefinition builtin_x86_defs[] = {
- CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
- .model_id = "AMD EPYC Processor",
-+ .cache_info.valid = 1,
-+ .cache_info.l1d_cache = {
-+ .type = DCACHE,
-+ .level = 1,
-+ .size = 32 * KiB,
-+ .line_size = 64,
-+ .associativity = 8,
-+ .partitions = 1,
-+ .sets = 64,
-+ .lines_per_tag = 1,
-+ .self_init = 1,
-+ .no_invd_sharing = true,
-+ },
-+ .cache_info.l1i_cache = {
-+ .type = ICACHE,
-+ .level = 1,
-+ .size = 64 * KiB,
-+ .line_size = 64,
-+ .associativity = 4,
-+ .partitions = 1,
-+ .sets = 256,
-+ .lines_per_tag = 1,
-+ .self_init = 1,
-+ .no_invd_sharing = true,
-+ },
-+ .cache_info.l2_cache = {
-+ .type = UNIFIED_CACHE,
-+ .level = 2,
-+ .size = 512 * KiB,
-+ .line_size = 64,
-+ .associativity = 8,
-+ .partitions = 1,
-+ .sets = 1024,
-+ .lines_per_tag = 1,
-+ },
-+ .cache_info.l3_cache = {
-+ .type = UNIFIED_CACHE,
-+ .level = 3,
-+ .size = 8 * MiB,
-+ .line_size = 64,
-+ .associativity = 16,
-+ .partitions = 1,
-+ .sets = 8192,
-+ .lines_per_tag = 1,
-+ .self_init = true,
-+ .inclusive = true,
-+ .complex_indexing = true,
-+ },
- },
- {
- .name = "EPYC-IBPB",
-@@ -2348,6 +2396,54 @@ static X86CPUDefinition builtin_x86_defs[] = {
- CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
- .model_id = "AMD EPYC Processor (with IBPB)",
-+ .cache_info.valid = 1,
-+ .cache_info.l1d_cache = {
-+ .type = DCACHE,
-+ .level = 1,
-+ .size = 32 * KiB,
-+ .line_size = 64,
-+ .associativity = 8,
-+ .partitions = 1,
-+ .sets = 64,
-+ .lines_per_tag = 1,
-+ .self_init = 1,
-+ .no_invd_sharing = true,
-+ },
-+ .cache_info.l1i_cache = {
-+ .type = ICACHE,
-+ .level = 1,
-+ .size = 64 * KiB,
-+ .line_size = 64,
-+ .associativity = 4,
-+ .partitions = 1,
-+ .sets = 256,
-+ .lines_per_tag = 1,
-+ .self_init = 1,
-+ .no_invd_sharing = true,
-+ },
-+ .cache_info.l2_cache = {
-+ .type = UNIFIED_CACHE,
-+ .level = 2,
-+ .size = 512 * KiB,
-+ .line_size = 64,
-+ .associativity = 8,
-+ .partitions = 1,
-+ .sets = 1024,
-+ .lines_per_tag = 1,
-+ },
-+ .cache_info.l3_cache = {
-+ .type = UNIFIED_CACHE,
-+ .level = 3,
-+ .size = 8 * MiB,
-+ .line_size = 64,
-+ .associativity = 16,
-+ .partitions = 1,
-+ .sets = 8192,
-+ .lines_per_tag = 1,
-+ .self_init = true,
-+ .inclusive = true,
-+ .complex_indexing = true,
-+ },
- },
- };
-
-diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
-index ffee841..d904a3c 100644
---- a/include/hw/i386/pc.h
-+++ b/include/hw/i386/pc.h
-@@ -327,6 +327,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
- .driver = "q35-pcihost",\
- .property = "x-pci-hole64-fix",\
- .value = "off",\
-+ },{\
-+ .driver = TYPE_X86_CPU,\
-+ .property = "legacy-cache",\
-+ .value = "on",\
- },
-
- #define PC_COMPAT_2_9 \
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index 5d88363..a27b658 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -5138,6 +5138,7 @@ static Property x86_cpu_properties[] = {
- false),
- DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
- DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true),
-+ DEFINE_PROP_BOOL("legacy-cache", X86CPU, legacy_cache, false),
-
- /*
- * From "Requirements for Implementing the Microsoft
-diff --git a/target/i386/cpu.h b/target/i386/cpu.h
-index 1213bb7..852586a 100644
---- a/target/i386/cpu.h
-+++ b/target/i386/cpu.h
-@@ -1395,6 +1395,11 @@ struct X86CPU {
- */
- bool enable_l3_cache;
-
-+ /* Compatibility bits for old machine types.
-+ * If true present the old cache topology information
-+ */
-+ bool legacy_cache;
-+
- /* Compatibility bits for old machine types: */
- bool enable_cpuid_0xb;
-
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index a27b658..56d2f0b 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -3941,8 +3941,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- (L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES);
- *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
- (L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES);
-- *ecx = encode_cache_cpuid80000005(&l1d_cache_amd);
-- *edx = encode_cache_cpuid80000005(&l1i_cache_amd);
-+ if (env->cache_info.valid && !cpu->legacy_cache) {
-+ *ecx = encode_cache_cpuid80000005(&env->cache_info.l1d_cache);
-+ *edx = encode_cache_cpuid80000005(&env->cache_info.l1i_cache);
-+ } else {
-+ *ecx = encode_cache_cpuid80000005(&l1d_cache_amd);
-+ *edx = encode_cache_cpuid80000005(&l1i_cache_amd);
-+ }
- break;
- case 0x80000006:
- /* cache info (L2 cache) */
-@@ -3958,9 +3963,16 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- (L2_DTLB_4K_ENTRIES << 16) | \
- (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
- (L2_ITLB_4K_ENTRIES);
-- encode_cache_cpuid80000006(&l2_cache_amd,
-- cpu->enable_l3_cache ? &l3_cache : NULL,
-- ecx, edx);
-+ if (env->cache_info.valid && !cpu->legacy_cache) {
-+ encode_cache_cpuid80000006(&env->cache_info.l2_cache,
-+ cpu->enable_l3_cache ?
-+ &env->cache_info.l3_cache : NULL,
-+ ecx, edx);
-+ } else {
-+ encode_cache_cpuid80000006(&l2_cache_amd,
-+ cpu->enable_l3_cache ? &l3_cache : NULL,
-+ ecx, edx);
-+ }
- break;
- case 0x80000007:
- *eax = 0;
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index 56d2f0b..1024b09 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -307,6 +307,14 @@ static uint32_t encode_cache_cpuid80000005(CPUCacheInfo *cache)
- a == ASSOC_FULL ? 0xF : \
- 0 /* invalid value */)
-
-+/* Definitions used on CPUID Leaf 0x8000001D */
-+/* Number of logical cores in a complex */
-+#define CORES_IN_CMPLX 4
-+/* Number of logical processors sharing cache */
-+#define NUM_SHARING_CACHE(threads) (threads ? \
-+ (((CORES_IN_CMPLX - 1) * 2) + 1) : \
-+ (CORES_IN_CMPLX - 1))
-+
- /*
- * Encode cache info for CPUID[0x80000006].ECX and CPUID[0x80000006].EDX
- * @l3 can be NULL.
-@@ -336,6 +344,41 @@ static void encode_cache_cpuid80000006(CPUCacheInfo *l2,
- }
- }
-
-+/* Encode cache info for CPUID[8000001D] */
-+static void encode_cache_cpuid8000001d(CPUCacheInfo *cache, int nr_threads,
-+ uint32_t *eax, uint32_t *ebx,
-+ uint32_t *ecx, uint32_t *edx)
-+{
-+ assert(cache->size == cache->line_size * cache->associativity *
-+ cache->partitions * cache->sets);
-+
-+ *eax = CACHE_TYPE(cache->type) | CACHE_LEVEL(cache->level) |
-+ (cache->self_init ? CACHE_SELF_INIT_LEVEL : 0);
-+
-+ /* L3 is shared among multiple cores */
-+ if (cache->level == 3) {
-+ *eax |= (NUM_SHARING_CACHE(nr_threads - 1) << 14);
-+ } else {
-+ *eax |= ((nr_threads - 1) << 14);
-+ }
-+
-+ assert(cache->line_size > 0);
-+ assert(cache->partitions > 0);
-+ assert(cache->associativity > 0);
-+ /* We don't implement fully-associative caches */
-+ assert(cache->associativity < cache->sets);
-+ *ebx = (cache->line_size - 1) |
-+ ((cache->partitions - 1) << 12) |
-+ ((cache->associativity - 1) << 22);
-+
-+ assert(cache->sets > 0);
-+ *ecx = cache->sets - 1;
-+
-+ *edx = (cache->no_invd_sharing ? CACHE_NO_INVD_SHARING : 0) |
-+ (cache->inclusive ? CACHE_INCLUSIVE : 0) |
-+ (cache->complex_indexing ? CACHE_COMPLEX_IDX : 0);
-+}
-+
- /* Definitions of the hardcoded cache entries we expose: */
-
- /* L1 data cache: */
-@@ -4013,6 +4056,55 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- *edx = 0;
- }
- break;
-+ case 0x8000001D:
-+ *eax = 0;
-+ switch (count) {
-+ case 0: /* L1 dcache info */
-+ if (env->cache_info.valid && !cpu->legacy_cache) {
-+ encode_cache_cpuid8000001d(&env->cache_info.l1d_cache,
-+ cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ } else {
-+ encode_cache_cpuid8000001d(&l1d_cache_amd, cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ }
-+ break;
-+ case 1: /* L1 icache info */
-+ if (env->cache_info.valid && !cpu->legacy_cache) {
-+ encode_cache_cpuid8000001d(&env->cache_info.l1i_cache,
-+ cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ } else {
-+ encode_cache_cpuid8000001d(&l1i_cache_amd,
-+ cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ }
-+ break;
-+ case 2: /* L2 cache info */
-+ if (env->cache_info.valid && !cpu->legacy_cache) {
-+ encode_cache_cpuid8000001d(&env->cache_info.l2_cache,
-+ cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ } else {
-+ encode_cache_cpuid8000001d(&l2_cache_amd, cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ }
-+ break;
-+ case 3: /* L3 cache info */
-+ if (env->cache_info.valid && !cpu->legacy_cache) {
-+ encode_cache_cpuid8000001d(&env->cache_info.l3_cache,
-+ cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ } else {
-+ encode_cache_cpuid8000001d(&l3_cache, cs->nr_threads,
-+ eax, ebx, ecx, edx);
-+ }
-+ break;
-+ default: /* end of info */
-+ *eax = *ebx = *ecx = *edx = 0;
-+ break;
-+ }
-+ break;
- case 0xC0000000:
- *eax = env->cpuid_xlevel2;
- *ebx = 0;
-diff --git a/target/i386/kvm.c b/target/i386/kvm.c
-index 6c49954..6e66f9c 100644
---- a/target/i386/kvm.c
-+++ b/target/i386/kvm.c
-@@ -967,9 +967,32 @@ int kvm_arch_init_vcpu(CPUState *cs)
- }
- c = &cpuid_data.entries[cpuid_i++];
-
-- c->function = i;
-- c->flags = 0;
-- cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
-+ switch (i) {
-+ case 0x8000001d:
-+ /* Query for all AMD cache information leaves */
-+ for (j = 0; ; j++) {
-+ c->function = i;
-+ c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
-+ c->index = j;
-+ cpu_x86_cpuid(env, i, j, &c->eax, &c->ebx, &c->ecx, &c->edx);
-+
-+ if (c->eax == 0) {
-+ break;
-+ }
-+ if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
-+ fprintf(stderr, "cpuid_data is full, no space for "
-+ "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
-+ abort();
-+ }
-+ c = &cpuid_data.entries[cpuid_i++];
-+ }
-+ break;
-+ default:
-+ c->function = i;
-+ c->flags = 0;
-+ cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
-+ break;
-+ }
- }
-
- /* Call Centaur's CPUID instructions they are supported. */
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index 1024b09..1b15023 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -315,6 +315,12 @@ static uint32_t encode_cache_cpuid80000005(CPUCacheInfo *cache)
- (((CORES_IN_CMPLX - 1) * 2) + 1) : \
- (CORES_IN_CMPLX - 1))
-
-+/* Definitions used on CPUID Leaf 0x8000001E */
-+#define EXTENDED_APIC_ID(threads, socket_id, core_id, thread_id) \
-+ ((threads) ? \
-+ ((socket_id << 6) | (core_id << 1) | thread_id) : \
-+ ((socket_id << 6) | core_id))
-+
- /*
- * Encode cache info for CPUID[0x80000006].ECX and CPUID[0x80000006].EDX
- * @l3 can be NULL.
-@@ -4105,6 +4111,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
- break;
- }
- break;
-+ case 0x8000001E:
-+ assert(cpu->core_id <= 255);
-+ *eax = EXTENDED_APIC_ID((cs->nr_threads - 1),
-+ cpu->socket_id, cpu->core_id, cpu->thread_id);
-+ *ebx = (cs->nr_threads - 1) << 8 | cpu->core_id;
-+ *ecx = cpu->socket_id;
-+ *edx = 0;
-+ break;
- case 0xC0000000:
- *eax = env->cpuid_xlevel2;
- *ebx = 0;
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index 1b15023..6ebbef2 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -2334,7 +2334,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
- .features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH |
- CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM |
-- CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
-+ CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM |
-+ CPUID_EXT3_TOPOEXT,
- .features[FEAT_7_0_EBX] =
- CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 |
- CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED |
-@@ -2426,7 +2427,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
- .features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH |
- CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM |
-- CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
-+ CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM |
-+ CPUID_EXT3_TOPOEXT,
- .features[FEAT_8000_0008_EBX] =
- CPUID_8000_0008_EBX_IBPB,
- .features[FEAT_7_0_EBX] =
-@@ -4580,6 +4582,11 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
- x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A);
- }
-
-+ /* TOPOEXT feature requires 0x8000001E */
-+ if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_TOPOEXT) {
-+ x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000001E);
-+ }
-+
- /* SEV requires CPUID[0x8000001F] */
- if (sev_enabled()) {
- x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000001F);
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index 6ebbef2..54d908f 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -4830,17 +4830,20 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
-
- qemu_init_vcpu(cs);
-
-- /* Only Intel CPUs support hyperthreading. Even though QEMU fixes this
-- * issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX
-- * based on inputs (sockets,cores,threads), it is still better to gives
-+ /* Most Intel and certain AMD CPUs support hyperthreading. Even though QEMU
-+ * fixes this issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX
-+ * based on inputs (sockets,cores,threads), it is still better to give
- * users a warning.
- *
- * NOTE: the following code has to follow qemu_init_vcpu(). Otherwise
- * cs->nr_threads hasn't be populated yet and the checking is incorrect.
- */
-- if (!IS_INTEL_CPU(env) && cs->nr_threads > 1 && !ht_warned) {
-- error_report("AMD CPU doesn't support hyperthreading. Please configure"
-- " -smp options properly.");
-+ if (IS_AMD_CPU(env) &&
-+ !(env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_TOPOEXT) &&
-+ cs->nr_threads > 1 && !ht_warned) {
-+ error_report("This family of AMD CPU doesn't support "
-+ "hyperthreading. Please configure -smp "
-+ "options properly.");
- ht_warned = true;
- }
-
diff --git a/audio-improvements.patch b/pa-fixes.patch
index d51a053a642b..65d046502c92 100644
--- a/audio-improvements.patch
+++ b/pa-fixes.patch
@@ -1,8 +1,20 @@
-diff --git audio/audio.c audio/audio.c
-index 6eccdb17ee..4eb190a18f 100644
---- audio/audio.c
-+++ audio/audio.c
-@@ -2097,3 +2097,8 @@ void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
+From fa5f68de47d120b4f6a5f973f21567ef389b42ac Mon Sep 17 00:00:00 2001
+From: Geoffrey McRae <geoff@hostfission.com>
+Date: Tue, 8 May 2018 02:59:17 +1000
+Subject: [PATCH] PA fixes
+
+---
+ audio/audio.c | 5 +
+ audio/audio_int.h | 2 +
+ audio/paaudio.c | 635 +++++++++++++++++--------------------------
+ hw/audio/hda-codec.c | 2 +
+ 4 files changed, 264 insertions(+), 380 deletions(-)
+
+diff --git a/audio/audio.c b/audio/audio.c
+index 1ace47f510..253e470d12 100644
+--- a/audio/audio.c
++++ b/audio/audio.c
+@@ -2118,3 +2118,8 @@ void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
}
}
}
@@ -11,10 +23,10 @@ index 6eccdb17ee..4eb190a18f 100644
+{
+ return conf.period.ticks;
+}
-diff --git audio/audio_int.h audio/audio_int.h
+diff --git a/audio/audio_int.h b/audio/audio_int.h
index 244b454012..19ba2d7aa4 100644
---- audio/audio_int.h
-+++ audio/audio_int.h
+--- a/audio/audio_int.h
++++ b/audio/audio_int.h
@@ -210,6 +210,8 @@ extern const struct mixeng_volume nominal_volume;
void audio_driver_register(audio_driver *drv);
audio_driver *audio_driver_lookup(const char *name);
@@ -24,10 +36,10 @@ index 244b454012..19ba2d7aa4 100644
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
-diff --git audio/paaudio.c audio/paaudio.c
-index 949769774d..cfa200fa96 100644
---- audio/paaudio.c
-+++ audio/paaudio.c
+diff --git a/audio/paaudio.c b/audio/paaudio.c
+index 949769774d..bd5a1781bf 100644
+--- a/audio/paaudio.c
++++ b/audio/paaudio.c
@@ -1,16 +1,22 @@
/* public domain */
#include "qemu/osdep.h"
@@ -87,21 +99,10 @@ index 949769774d..cfa200fa96 100644
} PAVoiceIn;
static void qpa_audio_fini(void *opaque);
-@@ -89,7 +85,7 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
- } \
- goto label; \
- } \
-- } while (0)
-+ } while (0);
-
- #define CHECK_DEAD_GOTO(c, stream, rerror, label) \
- do { \
-@@ -107,184 +103,61 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
- } \
- goto label; \
+@@ -109,182 +105,59 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
} \
-- } while (0)
--
+ } while (0)
+
-static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
-{
- paaudio *g = p->g;
@@ -150,8 +151,7 @@ index 949769774d..cfa200fa96 100644
-
- pa_threaded_mainloop_unlock (g->mainloop);
- return 0;
-+ } while (0);
-
+-
-unlock_and_fail:
- pa_threaded_mainloop_unlock (g->mainloop);
- return -1;
@@ -840,10 +840,10 @@ index 949769774d..cfa200fa96 100644
},
{
.name = "SERVER",
-diff --git hw/audio/hda-codec.c hw/audio/hda-codec.c
-index e8aa7842e6..e68830490f 100644
---- hw/audio/hda-codec.c
-+++ hw/audio/hda-codec.c
+diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
+index 617a1c1016..6627c5cbfd 100644
+--- a/hw/audio/hda-codec.c
++++ b/hw/audio/hda-codec.c
@@ -18,6 +18,7 @@
*/
@@ -852,286 +852,14 @@ index e8aa7842e6..e68830490f 100644
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "intel-hda.h"
-@@ -126,6 +127,11 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
- #define PARAM nomixemu
+@@ -128,6 +129,7 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
#include "hda-codec-common.h"
-+#define HDA_TIMER_TICKS (SCALE_MS)
+ #define HDA_TIMER_TICKS (SCALE_MS)
+#define MAX_CORR (SCALE_US * 100)
-+#define B_SIZE sizeof(st->buf)
-+#define B_MASK (sizeof(st->buf) - 1)
-+
- /* -------------------------------------------------------------------------- */
-
- static const char *fmt2name[] = {
-@@ -154,8 +160,13 @@ struct HDAAudioStream {
- SWVoiceIn *in;
- SWVoiceOut *out;
- } voice;
-- uint8_t buf[HDA_BUFFER_SIZE];
-- uint32_t bpos;
-+ uint8_t compat_buf[HDA_BUFFER_SIZE];
-+ uint32_t compat_bpos;
-+ uint8_t buf[8192]; /* size must be power of two */
-+ int64_t rpos;
-+ int64_t wpos;
-+ QEMUTimer *buft;
-+ int64_t buft_start;
- };
-
- #define TYPE_HDA_AUDIO "hda-audio"
-@@ -176,53 +187,146 @@ struct HDAAudioState {
- bool mixer;
- };
-
-+static inline int64_t hda_bytes_per_second(HDAAudioStream *st)
-+{
-+ return 2 * st->as.nchannels * st->as.freq;
-+}
-+
-+static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos)
-+{
-+ int64_t corr =
-+ NANOSECONDS_PER_SECOND * target_pos / hda_bytes_per_second(st);
-+ if (corr > MAX_CORR) {
-+ corr = MAX_CORR;
-+ } else if (corr < -MAX_CORR) {
-+ corr = -MAX_CORR;
-+ }
-+ atomic_fetch_add(&st->buft_start, corr);
-+}
-+
-+static void hda_audio_input_timer(void *opaque)
-+{
-+ HDAAudioStream *st = opaque;
-+
-+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-+
-+ int64_t buft_start = atomic_fetch_add(&st->buft_start, 0);
-+ int64_t wpos = atomic_fetch_add(&st->wpos, 0);
-+ int64_t rpos = atomic_fetch_add(&st->rpos, 0);
-+
-+ int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start)
-+ / NANOSECONDS_PER_SECOND;
-+ wanted_rpos &= -4; /* IMPORTANT! clip to frames */
-+
-+ if (wanted_rpos <= rpos) {
-+ /* we already transmitted the data */
-+ goto out_timer;
-+ }
-+
-+ int64_t to_transfer = audio_MIN(wpos - rpos, wanted_rpos - rpos);
-+ while (to_transfer) {
-+ uint32_t start = (rpos & B_MASK);
-+ uint32_t chunk = audio_MIN(B_SIZE - start, to_transfer);
-+ int rc = hda_codec_xfer(
-+ &st->state->hda, st->stream, false, st->buf + start, chunk);
-+ if (!rc) {
-+ break;
-+ }
-+ rpos += chunk;
-+ to_transfer -= chunk;
-+ atomic_fetch_add(&st->rpos, chunk);
-+ }
-+
-+out_timer:
-+
-+ if (st->running) {
-+ timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
-+ }
-+}
-+
- static void hda_audio_input_cb(void *opaque, int avail)
- {
- HDAAudioStream *st = opaque;
-- int recv = 0;
-- int len;
-- bool rc;
--
-- while (avail - recv >= sizeof(st->buf)) {
-- if (st->bpos != sizeof(st->buf)) {
-- len = AUD_read(st->voice.in, st->buf + st->bpos,
-- sizeof(st->buf) - st->bpos);
-- st->bpos += len;
-- recv += len;
-- if (st->bpos != sizeof(st->buf)) {
-- break;
-- }
-+
-+ int64_t wpos = atomic_fetch_add(&st->wpos, 0);
-+ int64_t rpos = atomic_fetch_add(&st->rpos, 0);
-+
-+ int64_t to_transfer = audio_MIN(B_SIZE - (wpos - rpos), avail);
-+
-+ hda_timer_sync_adjust(st, -((wpos - rpos) + to_transfer - (B_SIZE >> 1)));
-+
-+ while (to_transfer) {
-+ uint32_t start = (uint32_t) (wpos & B_MASK);
-+ uint32_t chunk = (uint32_t) audio_MIN(B_SIZE - start, to_transfer);
-+ uint32_t read = AUD_read(st->voice.in, st->buf + start, chunk);
-+ wpos += read;
-+ to_transfer -= read;
-+ atomic_fetch_add(&st->wpos, read);
-+ if (chunk != read) {
-+ break;
- }
-- rc = hda_codec_xfer(&st->state->hda, st->stream, false,
-- st->buf, sizeof(st->buf));
-+ }
-+}
-+
-+static void hda_audio_output_timer(void *opaque)
-+{
-+ HDAAudioStream *st = opaque;
-+
-+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-+
-+ int64_t buft_start = atomic_fetch_add(&st->buft_start, 0);
-+ int64_t wpos = atomic_fetch_add(&st->wpos, 0);
-+ int64_t rpos = atomic_fetch_add(&st->rpos, 0);
-+
-+ int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start)
-+ / NANOSECONDS_PER_SECOND;
-+ wanted_wpos &= -4; /* IMPORTANT! clip to frames */
-+
-+ if (wanted_wpos <= wpos) {
-+ /* we already received the data */
-+ goto out_timer;
-+ }
-+
-+ int64_t to_transfer = audio_MIN(B_SIZE - (wpos - rpos), wanted_wpos - wpos);
-+ while (to_transfer) {
-+ uint32_t start = (wpos & B_MASK);
-+ uint32_t chunk = audio_MIN(B_SIZE - start, to_transfer);
-+ int rc = hda_codec_xfer(
-+ &st->state->hda, st->stream, true, st->buf + start, chunk);
- if (!rc) {
- break;
- }
-- st->bpos = 0;
-+ wpos += chunk;
-+ to_transfer -= chunk;
-+ atomic_fetch_add(&st->wpos, chunk);
-+ }
-+
-+out_timer:
-+
-+ if (st->running) {
-+ timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
- }
- }
-
- static void hda_audio_output_cb(void *opaque, int avail)
- {
- HDAAudioStream *st = opaque;
-- int sent = 0;
-- int len;
-- bool rc;
--
-- while (avail - sent >= sizeof(st->buf)) {
-- if (st->bpos == sizeof(st->buf)) {
-- rc = hda_codec_xfer(&st->state->hda, st->stream, true,
-- st->buf, sizeof(st->buf));
-- if (!rc) {
-- break;
-- }
-- st->bpos = 0;
-- }
-- len = AUD_write(st->voice.out, st->buf + st->bpos,
-- sizeof(st->buf) - st->bpos);
-- st->bpos += len;
-- sent += len;
-- if (st->bpos != sizeof(st->buf)) {
-+
-+ int64_t wpos = atomic_fetch_add(&st->wpos, 0);
-+ int64_t rpos = atomic_fetch_add(&st->rpos, 0);
-+
-+ int64_t to_transfer = audio_MIN(wpos - rpos, avail);
-+
-+ hda_timer_sync_adjust(st, (wpos - rpos) - to_transfer - (B_SIZE >> 1));
-+
-+ while (to_transfer) {
-+ uint32_t start = (uint32_t) (rpos & B_MASK);
-+ uint32_t chunk = (uint32_t) audio_MIN(B_SIZE - start, to_transfer);
-+ uint32_t written = AUD_write(st->voice.out, st->buf + start, chunk);
-+ rpos += written;
-+ to_transfer -= written;
-+ atomic_fetch_add(&st->rpos, written);
-+ if (chunk != written) {
- break;
- }
- }
-@@ -239,6 +343,15 @@ static void hda_audio_set_running(HDAAudioStream *st, bool running)
- st->running = running;
- dprint(st->state, 1, "%s: %s (stream %d)\n", st->node->name,
- st->running ? "on" : "off", st->stream);
-+ if (running) {
-+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-+ st->rpos = 0;
-+ st->wpos = 0;
-+ st->buft_start = now;
-+ timer_mod_anticipate_ns(st->buft, now + HDA_TIMER_TICKS);
-+ } else {
-+ timer_del(st->buft);
-+ }
- if (st->output) {
- AUD_set_active_out(st->voice.out, st->running);
- } else {
-@@ -286,10 +399,12 @@ static void hda_audio_setup(HDAAudioStream *st)
- st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
- st->node->name, st,
- hda_audio_output_cb, &st->as);
-+ st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL, hda_audio_output_timer, st);
- } else {
- st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
- st->node->name, st,
- hda_audio_input_cb, &st->as);
-+ st->buft = timer_new_ns(QEMU_CLOCK_VIRTUAL, hda_audio_input_timer, st);
- }
- }
-
-@@ -505,7 +620,6 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
- /* unmute output by default */
- st->gain_left = QEMU_HDA_AMP_STEPS;
- st->gain_right = QEMU_HDA_AMP_STEPS;
-- st->bpos = sizeof(st->buf);
- st->output = true;
- } else {
- st->output = false;
-@@ -532,6 +646,7 @@ static void hda_audio_exit(HDACodecDevice *hda)
- if (st->node == NULL) {
- continue;
- }
-+ timer_del(st->buft);
- if (st->output) {
- AUD_close_out(&a->card, st->voice.out);
- } else {
-@@ -592,8 +707,8 @@ static const VMStateDescription vmstate_hda_audio_stream = {
- VMSTATE_UINT32(gain_right, HDAAudioStream),
- VMSTATE_BOOL(mute_left, HDAAudioStream),
- VMSTATE_BOOL(mute_right, HDAAudioStream),
-- VMSTATE_UINT32(bpos, HDAAudioStream),
-- VMSTATE_BUFFER(buf, HDAAudioStream),
-+ VMSTATE_UINT32(compat_bpos, HDAAudioStream),
-+ VMSTATE_BUFFER(compat_buf, HDAAudioStream),
- VMSTATE_END_OF_LIST()
- }
- };
-diff --git hw/audio/intel-hda.c hw/audio/intel-hda.c
-index 948268afd8..23a2cf6484 100644
---- hw/audio/intel-hda.c
-+++ hw/audio/intel-hda.c
-@@ -407,13 +407,6 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
- if (st->bpl == NULL) {
- return false;
- }
-- if (st->ctl & (1 << 26)) {
-- /*
-- * Wait with the next DMA xfer until the guest
-- * has acked the buffer completion interrupt
-- */
-- return false;
-- }
+ #define B_SIZE sizeof(st->buf)
+ #define B_MASK (sizeof(st->buf) - 1)
- left = len;
- s = st->bentries;
+--
+2.18.0
+
diff --git a/ps2-fixes-v2.patch b/ps2-fixes-v2.patch
deleted file mode 100644
index 3aa3f90ed5ae..000000000000
--- a/ps2-fixes-v2.patch
+++ /dev/null
@@ -1,315 +0,0 @@
-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