diff options
author | Avi Kivity <avi@redhat.com> | 2009-12-14 16:54:46 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-14 16:54:46 +0200 |
commit | 4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d (patch) | |
tree | 7cc9bb0c932c159bf60275e762bfaed231b50077 | |
parent | Revert "Temporarily avoid loading pxe option roms" (diff) | |
parent | msix: function mask support (diff) | |
download | qemu-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-- | VERSION | 2 | ||||
-rw-r--r-- | hw/msix.c | 74 | ||||
-rw-r--r--[-rwxr-xr-x] | pc-bios/openbios-ppc | bin | 295636 -> 312124 bytes | |||
-rw-r--r-- | pc-bios/openbios-sparc32 | bin | 209472 -> 217700 bytes | |||
-rw-r--r-- | pc-bios/openbios-sparc64 | bin | 1065872 -> 1065880 bytes | |||
-rw-r--r-- | target-i386/helper.c | 46 | ||||
-rw-r--r-- | target-i386/kvm.c | 4 |
7 files changed, 85 insertions, 41 deletions
@@ -1 +1 @@ -0.11.50 +0.11.91 @@ -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 Binary files differindex 3941c0bf5..badcb9c04 100755..100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex 2454b4a2e..596e5eed9 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex 271718123..017d68cbd 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 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) + |