Commit 09f06a6c authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'qemu-kvm/uq/master' into staging

* qemu-kvm/uq/master:
  virtio: move common irqfd handling out of virtio-pci
  virtio: move common ioeventfd handling out of virtio-pci
  event_notifier: add event_notifier_set_handler
  memory: pass EventNotifier, not eventfd
  ivshmem: wrap ivshmem_del_eventfd loops with transaction
  ivshmem: use EventNotifier and memory API
  event_notifier: add event_notifier_init_fd
  event_notifier: remove event_notifier_test
  event_notifier: add event_notifier_set
  apic: Defer interrupt updates to VCPU thread
  apic: Reevaluate pending interrupts on LVT_LINT0 changes
  apic: Resolve potential endless loop around apic_update_irq
  kvm: expose tsc deadline timer feature to guest
  kvm_pv_eoi: add flag support
  kvm: Don't abort on kvm_irqchip_add_msi_route()
parents 513e6bde 15b2bd18
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -288,6 +288,12 @@ int cpu_exec(CPUArchState *env)
                    }
#endif
#if defined(TARGET_I386)
#if !defined(CONFIG_USER_ONLY)
                    if (interrupt_request & CPU_INTERRUPT_POLL) {
                        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
                        apic_poll_irq(env->apic_state);
                    }
#endif
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
                            cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
                                                          0);
+18 −12
Original line number Diff line number Diff line
@@ -10,11 +10,19 @@
 * See the COPYING file in the top-level directory.
 */

#include "qemu-common.h"
#include "event_notifier.h"
#include "qemu-char.h"

#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
#endif

void event_notifier_init_fd(EventNotifier *e, int fd)
{
    e->fd = fd;
}

int event_notifier_init(EventNotifier *e, int active)
{
#ifdef CONFIG_EVENTFD
@@ -38,24 +46,22 @@ int event_notifier_get_fd(EventNotifier *e)
    return e->fd;
}

int event_notifier_test_and_clear(EventNotifier *e)
int event_notifier_set_handler(EventNotifier *e,
                               EventNotifierHandler *handler)
{
    uint64_t value;
    int r = read(e->fd, &value, sizeof(value));
    return qemu_set_fd_handler(e->fd, (IOHandler *)handler, NULL, e);
}

int event_notifier_set(EventNotifier *e)
{
    uint64_t value = 1;
    int r = write(e->fd, &value, sizeof(value));
    return r == sizeof(value);
}

int event_notifier_test(EventNotifier *e)
int event_notifier_test_and_clear(EventNotifier *e)
{
    uint64_t value;
    int r = read(e->fd, &value, sizeof(value));
    if (r == sizeof(value)) {
        /* restore previous value. */
        int s = write(e->fd, &value, sizeof(value));
        /* never blocks because we use EFD_SEMAPHORE.
         * If we didn't we'd get EAGAIN on overflow
         * and we'd have to write code to ignore it. */
        assert(s == sizeof(value));
    }
    return r == sizeof(value);
}
+6 −2
Original line number Diff line number Diff line
@@ -19,10 +19,14 @@ struct EventNotifier {
    int fd;
};

typedef void EventNotifierHandler(EventNotifier *);

void event_notifier_init_fd(EventNotifier *, int fd);
int event_notifier_init(EventNotifier *, int active);
void event_notifier_cleanup(EventNotifier *);
int event_notifier_get_fd(EventNotifier *);
int event_notifier_set(EventNotifier *);
int event_notifier_test_and_clear(EventNotifier *);
int event_notifier_test(EventNotifier *);
int event_notifier_set_handler(EventNotifier *, EventNotifierHandler *);

#endif
+4 −4
Original line number Diff line number Diff line
@@ -3210,13 +3210,13 @@ static void core_log_global_stop(MemoryListener *listener)

static void core_eventfd_add(MemoryListener *listener,
                             MemoryRegionSection *section,
                             bool match_data, uint64_t data, int fd)
                             bool match_data, uint64_t data, EventNotifier *e)
{
}

static void core_eventfd_del(MemoryListener *listener,
                             MemoryRegionSection *section,
                             bool match_data, uint64_t data, int fd)
                             bool match_data, uint64_t data, EventNotifier *e)
{
}

@@ -3276,13 +3276,13 @@ static void io_log_global_stop(MemoryListener *listener)

static void io_eventfd_add(MemoryListener *listener,
                           MemoryRegionSection *section,
                           bool match_data, uint64_t data, int fd)
                           bool match_data, uint64_t data, EventNotifier *e)
{
}

static void io_eventfd_del(MemoryListener *listener,
                           MemoryRegionSection *section,
                           bool match_data, uint64_t data, int fd)
                           bool match_data, uint64_t data, EventNotifier *e)
{
}

+22 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>
 */
#include "qemu-thread.h"
#include "apic_internal.h"
#include "apic.h"
#include "ioapic.h"
@@ -361,11 +362,10 @@ static void apic_update_irq(APICCommonState *s)
    if (!(s->spurious_vec & APIC_SV_ENABLE)) {
        return;
    }
    if (apic_irq_pending(s) > 0) {
    if (!qemu_cpu_is_self(s->cpu_env)) {
        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_POLL);
    } else if (apic_irq_pending(s) > 0) {
        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
    } else if (apic_accept_pic_intr(&s->busdev.qdev) &&
               pic_get_output(isa_pic)) {
        apic_deliver_pic_intr(&s->busdev.qdev, 1);
    }
}

@@ -535,6 +535,15 @@ static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
}

static bool apic_check_pic(APICCommonState *s)
{
    if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) {
        return false;
    }
    apic_deliver_pic_intr(&s->busdev.qdev, 1);
    return true;
}

int apic_get_interrupt(DeviceState *d)
{
    APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
@@ -560,7 +569,12 @@ int apic_get_interrupt(DeviceState *d)
    reset_bit(s->irr, intno);
    set_bit(s->isr, intno);
    apic_sync_vapic(s, SYNC_TO_VAPIC);

    /* re-inject if there is still a pending PIC interrupt */
    apic_check_pic(s);

    apic_update_irq(s);

    return intno;
}

@@ -800,8 +814,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
        {
            int n = index - 0x32;
            s->lvt[n] = val;
            if (n == APIC_LVT_TIMER)
            if (n == APIC_LVT_TIMER) {
                apic_timer_update(s, qemu_get_clock_ns(vm_clock));
            } else if (n == APIC_LVT_LINT0 && apic_check_pic(s)) {
                apic_update_irq(s);
            }
        }
        break;
    case 0x38:
Loading