aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-12-14 16:54:46 +0200
committerAvi Kivity <avi@redhat.com>2009-12-14 16:54:46 +0200
commit4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d (patch)
tree7cc9bb0c932c159bf60275e762bfaed231b50077
parentRevert "Temporarily avoid loading pxe option roms" (diff)
parentmsix: function mask support (diff)
downloadqemu-kvm-4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d.tar.gz
qemu-kvm-4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d.tar.bz2
qemu-kvm-4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d.zip
Merge commit 'c99d32efe6970493c44fe410ee4a4aafc1a35428' into stable-0.12-merge
* commit 'c99d32efe6970493c44fe410ee4a4aafc1a35428': msix: function mask support msix: macro rename for function mask support cpuid: Fix multicore setup on Intel kvm: x86: Fix initial kvm_has_msr_star Update OpenBIOS images to r640 Update version to -rc1 Conflicts: hw/msix.c Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--VERSION2
-rw-r--r--hw/msix.c74
-rw-r--r--[-rwxr-xr-x]pc-bios/openbios-ppcbin295636 -> 312124 bytes
-rw-r--r--pc-bios/openbios-sparc32bin209472 -> 217700 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1065872 -> 1065880 bytes
-rw-r--r--target-i386/helper.c46
-rw-r--r--target-i386/kvm.c4
7 files changed, 85 insertions, 41 deletions
diff --git a/VERSION b/VERSION
index 93d635abd..568d15238 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.11.50
+0.11.91
diff --git a/hw/msix.c b/hw/msix.c
index 6d598ee24..d117bcfaa 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -22,6 +22,7 @@
#define PCI_MSIX_FLAGS 2 /* Table at lower 11 bits */
#define PCI_MSIX_FLAGS_QSIZE 0x7FF
#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
+#define PCI_MSIX_FLAGS_MASKALL (1 << 14)
#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
/* MSI-X capability structure */
@@ -29,9 +30,10 @@
#define MSIX_PBA_OFFSET 8
#define MSIX_CAP_LENGTH 12
-/* MSI enable bit is in byte 1 in FLAGS register */
-#define MSIX_ENABLE_OFFSET (PCI_MSIX_FLAGS + 1)
+/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */
+#define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1)
#define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8)
+#define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8)
/* MSI-X table format */
#define MSIX_MSG_ADDR 0
@@ -214,22 +216,11 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
bar_nr);
pdev->msix_cap = config_offset;
/* Make flags bit writeable. */
- pdev->wmask[config_offset + MSIX_ENABLE_OFFSET] |= MSIX_ENABLE_MASK;
+ pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
+ MSIX_MASKALL_MASK;
return 0;
}
-/* Handle MSI-X capability config write. */
-void msix_write_config(PCIDevice *dev, uint32_t addr,
- uint32_t val, int len)
-{
- unsigned enable_pos = dev->msix_cap + MSIX_ENABLE_OFFSET;
- if (addr + len <= enable_pos || addr > enable_pos)
- return;
-
- if (msix_enabled(dev))
- qemu_set_irq(dev->irq[0], 0);
-}
-
static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr)
{
PCIDevice *dev = opaque;
@@ -270,10 +261,50 @@ static void msix_clr_pending(PCIDevice *dev, int vector)
*msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
}
+static int msix_function_masked(PCIDevice *dev)
+{
+ return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK;
+}
+
static int msix_is_masked(PCIDevice *dev, int vector)
{
unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL;
- return dev->msix_table_page[offset] & MSIX_VECTOR_MASK;
+ return msix_function_masked(dev) ||
+ dev->msix_table_page[offset] & MSIX_VECTOR_MASK;
+}
+
+static void msix_handle_mask_update(PCIDevice *dev, int vector)
+{
+ if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) {
+ msix_clr_pending(dev, vector);
+ msix_notify(dev, vector);
+ }
+}
+
+/* Handle MSI-X capability config write. */
+void msix_write_config(PCIDevice *dev, uint32_t addr,
+ uint32_t val, int len)
+{
+ unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
+ int vector;
+
+ if (addr + len <= enable_pos || addr > enable_pos) {
+ return;
+ }
+
+ if (!msix_enabled(dev)) {
+ return;
+ }
+
+ qemu_set_irq(dev->irq[0], 0);
+
+ if (msix_function_masked(dev)) {
+ return;
+ }
+
+ for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
+ msix_handle_mask_update(dev, vector);
+ }
}
static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
@@ -287,10 +318,7 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
}
- if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) {
- msix_clr_pending(dev, vector);
- msix_notify(dev, vector);
- }
+ msix_handle_mask_update(dev, vector);
}
static void msix_mmio_write_unallowed(void *opaque, target_phys_addr_t addr,
@@ -462,7 +490,7 @@ int msix_present(PCIDevice *dev)
int msix_enabled(PCIDevice *dev)
{
return (dev->cap_present & QEMU_PCI_CAP_MSIX) &&
- (dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &
+ (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
MSIX_ENABLE_MASK);
}
@@ -505,8 +533,8 @@ void msix_reset(PCIDevice *dev)
if (!(dev->cap_present & QEMU_PCI_CAP_MSIX))
return;
msix_free_irq_entries(dev);
- dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &=
- ~dev->wmask[dev->msix_cap + MSIX_ENABLE_OFFSET];
+ dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
+ ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE);
msix_mask_all(dev, dev->msix_entries_nr);
}
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 3941c0bf5..badcb9c04 100755..100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 2454b4a2e..596e5eed9 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 271718123..017d68cbd 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
diff --git a/target-i386/helper.c b/target-i386/helper.c
index fd32b2ee9..09ba5e9cf 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1645,6 +1645,24 @@ static void host_cpuid(uint32_t function, uint32_t count,
#endif
}
+static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx)
+{
+ *ebx = env->cpuid_vendor1;
+ *edx = env->cpuid_vendor2;
+ *ecx = env->cpuid_vendor3;
+
+ /* sysenter isn't supported on compatibility mode on AMD, syscall
+ * isn't supported in compatibility mode on Intel.
+ * Normally we advertise the actual cpu vendor, but you can override
+ * this if you want to use KVM's sysenter/syscall emulation
+ * in compatibility mode and when doing cross vendor migration
+ */
+ if (kvm_enabled() && env->cpuid_vendor_override) {
+ host_cpuid(0, 0, NULL, ebx, ecx, edx);
+ }
+}
+
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
@@ -1661,16 +1679,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
switch(index) {
case 0:
*eax = env->cpuid_level;
- *ebx = env->cpuid_vendor1;
- *edx = env->cpuid_vendor2;
- *ecx = env->cpuid_vendor3;
-
- /* sysenter isn't supported on compatibility mode on AMD. and syscall
- * isn't supported in compatibility mode on Intel. so advertise the
- * actuall cpu, and say goodbye to migration between different vendors
- * is you use compatibility mode. */
- if (kvm_enabled() && !env->cpuid_vendor_override)
- host_cpuid(0, 0, NULL, ebx, ecx, edx);
+ get_cpuid_vendor(env, ebx, ecx, edx);
break;
case 1:
*eax = env->cpuid_version;
@@ -1766,11 +1775,18 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*ecx = env->cpuid_ext3_features;
*edx = env->cpuid_ext2_features;
- if (env->nr_cores * env->nr_threads > 1 &&
- env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
- env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
- env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
- *ecx |= 1 << 1; /* CmpLegacy bit */
+ /* The Linux kernel checks for the CMPLegacy bit and
+ * discards multiple thread information if it is set.
+ * So dont set it here for Intel to make Linux guests happy.
+ */
+ if (env->nr_cores * env->nr_threads > 1) {
+ uint32_t tebx, tecx, tedx;
+ get_cpuid_vendor(env, &tebx, &tecx, &tedx);
+ if (tebx != CPUID_VENDOR_INTEL_1 ||
+ tedx != CPUID_VENDOR_INTEL_2 ||
+ tecx != CPUID_VENDOR_INTEL_3) {
+ *ecx |= 1 << 1; /* CmpLegacy bit */
+ }
}
if (kvm_enabled()) {
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 568e2117b..6926cc959 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -245,9 +245,9 @@ static int kvm_has_msr_star(CPUState *env)
* save/restore */
msr_list.nmsrs = 0;
ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list);
- if (ret < 0)
+ if (ret < 0 && ret != -E2BIG) {
return 0;
-
+ }
/* Old kernel modules had a bug and could write beyond the provided
memory. Allocate at least a safe amount of 1K. */
kvm_msr_list = qemu_mallocz(MAX(1024, sizeof(msr_list) +