Revision eb035b48

b/target-arm/kvm.c
19 19
#include "qemu/timer.h"
20 20
#include "sysemu/sysemu.h"
21 21
#include "sysemu/kvm.h"
22
#include "kvm_arm.h"
22 23
#include "cpu.h"
23 24
#include "hw/arm-misc.h"
24 25

  
......
67 68
    return ret;
68 69
}
69 70

  
71
/* We track all the KVM devices which need their memory addresses
72
 * passing to the kernel in a list of these structures.
73
 * When board init is complete we run through the list and
74
 * tell the kernel the base addresses of the memory regions.
75
 * We use a MemoryListener to track mapping and unmapping of
76
 * the regions during board creation, so the board models don't
77
 * need to do anything special for the KVM case.
78
 */
79
typedef struct KVMDevice {
80
    struct kvm_arm_device_addr kda;
81
    MemoryRegion *mr;
82
    QSLIST_ENTRY(KVMDevice) entries;
83
} KVMDevice;
84

  
85
static QSLIST_HEAD(kvm_devices_head, KVMDevice) kvm_devices_head;
86

  
87
static void kvm_arm_devlistener_add(MemoryListener *listener,
88
                                    MemoryRegionSection *section)
89
{
90
    KVMDevice *kd;
91

  
92
    QSLIST_FOREACH(kd, &kvm_devices_head, entries) {
93
        if (section->mr == kd->mr) {
94
            kd->kda.addr = section->offset_within_address_space;
95
        }
96
    }
97
}
98

  
99
static void kvm_arm_devlistener_del(MemoryListener *listener,
100
                                    MemoryRegionSection *section)
101
{
102
    KVMDevice *kd;
103

  
104
    QSLIST_FOREACH(kd, &kvm_devices_head, entries) {
105
        if (section->mr == kd->mr) {
106
            kd->kda.addr = -1;
107
        }
108
    }
109
}
110

  
111
static MemoryListener devlistener = {
112
    .region_add = kvm_arm_devlistener_add,
113
    .region_del = kvm_arm_devlistener_del,
114
};
115

  
116
static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
117
{
118
    KVMDevice *kd, *tkd;
119

  
120
    memory_listener_unregister(&devlistener);
121
    QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) {
122
        if (kd->kda.addr != -1) {
123
            if (kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR,
124
                             &kd->kda) < 0) {
125
                fprintf(stderr, "KVM_ARM_SET_DEVICE_ADDRESS failed: %s\n",
126
                        strerror(errno));
127
                abort();
128
            }
129
        }
130
        g_free(kd);
131
    }
132
}
133

  
134
static Notifier notify = {
135
    .notify = kvm_arm_machine_init_done,
136
};
137

  
138
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid)
139
{
140
    KVMDevice *kd;
141

  
142
    if (!kvm_irqchip_in_kernel()) {
143
        return;
144
    }
145

  
146
    if (QSLIST_EMPTY(&kvm_devices_head)) {
147
        memory_listener_register(&devlistener, NULL);
148
        qemu_add_machine_init_done_notifier(&notify);
149
    }
150
    kd = g_new0(KVMDevice, 1);
151
    kd->mr = mr;
152
    kd->kda.id = devid;
153
    kd->kda.addr = -1;
154
    QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
155
}
156

  
70 157
typedef struct Reg {
71 158
    uint64_t id;
72 159
    int offset;
b/target-arm/kvm_arm.h
1
/*
2
 * QEMU KVM support -- ARM specific functions.
3
 *
4
 * Copyright (c) 2012 Linaro Limited
5
 *
6
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7
 * See the COPYING file in the top-level directory.
8
 *
9
 */
10

  
11
#ifndef QEMU_KVM_ARM_H
12
#define QEMU_KVM_ARM_H
13

  
14
#include "sysemu/kvm.h"
15
#include "exec/memory.h"
16

  
17
/**
18
 * kvm_arm_register_device:
19
 * @mr: memory region for this device
20
 * @devid: the KVM device ID
21
 *
22
 * Remember the memory region @mr, and when it is mapped by the
23
 * machine model, tell the kernel that base address using the
24
 * KVM_SET_DEVICE_ADDRESS ioctl. @devid should be the ID of
25
 * the device as defined by KVM_SET_DEVICE_ADDRESS.
26
 * The machine model may map and unmap the device multiple times;
27
 * the kernel will only be told the final address at the point
28
 * where machine init is complete.
29
 */
30
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid);
31

  
32
#endif

Also available in: Unified diff