mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 20:33:54 -06:00
Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
* qemu-kvm/uq/master: kvm: Activate in-kernel irqchip support kvm: x86: Add user space part for in-kernel IOAPIC kvm: x86: Add user space part for in-kernel i8259 kvm: x86: Add user space part for in-kernel APIC kvm: x86: Establish IRQ0 override control kvm: Introduce core services for in-kernel irqchip support memory: Introduce memory_region_init_reservation ioapic: Factor out base class for KVM reuse ioapic: Drop post-load irr initialization i8259: Factor out base class for KVM reuse i8259: Completely privatize PicState apic: Open-code timer save/restore apic: Factor out base class for KVM reuse apic: Introduce apic_report_irq_delivered apic: Inject external NMI events via LINT1 apic: Stop timer on reset kvm: Move kvmclock into hw/kvm folder msi: Generalize msix_supported to msi_supported hyper-v: initialize Hyper-V CPUID leaves. hyper-v: introduce Hyper-V support infrastructure. Conflicts: Makefile.target Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
5b4448d27d
40 changed files with 1903 additions and 594 deletions
154
kvm-all.c
154
kvm-all.c
|
@ -78,6 +78,13 @@ struct KVMState
|
|||
int pit_in_kernel;
|
||||
int xsave, xcrs;
|
||||
int many_ioeventfds;
|
||||
int irqchip_inject_ioctl;
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
struct kvm_irq_routing *irq_routes;
|
||||
int nr_allocated_irq_routes;
|
||||
uint32_t *used_gsi_bitmap;
|
||||
unsigned int max_gsi;
|
||||
#endif
|
||||
};
|
||||
|
||||
KVMState *kvm_state;
|
||||
|
@ -729,6 +736,138 @@ static void kvm_handle_interrupt(CPUState *env, int mask)
|
|||
}
|
||||
}
|
||||
|
||||
int kvm_irqchip_set_irq(KVMState *s, int irq, int level)
|
||||
{
|
||||
struct kvm_irq_level event;
|
||||
int ret;
|
||||
|
||||
assert(s->irqchip_in_kernel);
|
||||
|
||||
event.level = level;
|
||||
event.irq = irq;
|
||||
ret = kvm_vm_ioctl(s, s->irqchip_inject_ioctl, &event);
|
||||
if (ret < 0) {
|
||||
perror("kvm_set_irqchip_line");
|
||||
abort();
|
||||
}
|
||||
|
||||
return (s->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status;
|
||||
}
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
static void set_gsi(KVMState *s, unsigned int gsi)
|
||||
{
|
||||
assert(gsi < s->max_gsi);
|
||||
|
||||
s->used_gsi_bitmap[gsi / 32] |= 1U << (gsi % 32);
|
||||
}
|
||||
|
||||
static void kvm_init_irq_routing(KVMState *s)
|
||||
{
|
||||
int gsi_count;
|
||||
|
||||
gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING);
|
||||
if (gsi_count > 0) {
|
||||
unsigned int gsi_bits, i;
|
||||
|
||||
/* Round up so we can search ints using ffs */
|
||||
gsi_bits = (gsi_count + 31) / 32;
|
||||
s->used_gsi_bitmap = g_malloc0(gsi_bits / 8);
|
||||
s->max_gsi = gsi_bits;
|
||||
|
||||
/* Mark any over-allocated bits as already in use */
|
||||
for (i = gsi_count; i < gsi_bits; i++) {
|
||||
set_gsi(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
s->irq_routes = g_malloc0(sizeof(*s->irq_routes));
|
||||
s->nr_allocated_irq_routes = 0;
|
||||
|
||||
kvm_arch_init_irq_routing(s);
|
||||
}
|
||||
|
||||
static void kvm_add_routing_entry(KVMState *s,
|
||||
struct kvm_irq_routing_entry *entry)
|
||||
{
|
||||
struct kvm_irq_routing_entry *new;
|
||||
int n, size;
|
||||
|
||||
if (s->irq_routes->nr == s->nr_allocated_irq_routes) {
|
||||
n = s->nr_allocated_irq_routes * 2;
|
||||
if (n < 64) {
|
||||
n = 64;
|
||||
}
|
||||
size = sizeof(struct kvm_irq_routing);
|
||||
size += n * sizeof(*new);
|
||||
s->irq_routes = g_realloc(s->irq_routes, size);
|
||||
s->nr_allocated_irq_routes = n;
|
||||
}
|
||||
n = s->irq_routes->nr++;
|
||||
new = &s->irq_routes->entries[n];
|
||||
memset(new, 0, sizeof(*new));
|
||||
new->gsi = entry->gsi;
|
||||
new->type = entry->type;
|
||||
new->flags = entry->flags;
|
||||
new->u = entry->u;
|
||||
|
||||
set_gsi(s, entry->gsi);
|
||||
}
|
||||
|
||||
void kvm_irqchip_add_route(KVMState *s, int irq, int irqchip, int pin)
|
||||
{
|
||||
struct kvm_irq_routing_entry e;
|
||||
|
||||
e.gsi = irq;
|
||||
e.type = KVM_IRQ_ROUTING_IRQCHIP;
|
||||
e.flags = 0;
|
||||
e.u.irqchip.irqchip = irqchip;
|
||||
e.u.irqchip.pin = pin;
|
||||
kvm_add_routing_entry(s, &e);
|
||||
}
|
||||
|
||||
int kvm_irqchip_commit_routes(KVMState *s)
|
||||
{
|
||||
s->irq_routes->flags = 0;
|
||||
return kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, s->irq_routes);
|
||||
}
|
||||
|
||||
#else /* !KVM_CAP_IRQ_ROUTING */
|
||||
|
||||
static void kvm_init_irq_routing(KVMState *s)
|
||||
{
|
||||
}
|
||||
#endif /* !KVM_CAP_IRQ_ROUTING */
|
||||
|
||||
static int kvm_irqchip_create(KVMState *s)
|
||||
{
|
||||
QemuOptsList *list = qemu_find_opts("machine");
|
||||
int ret;
|
||||
|
||||
if (QTAILQ_EMPTY(&list->head) ||
|
||||
!qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
|
||||
"kernel_irqchip", false) ||
|
||||
!kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Create kernel irqchip failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->irqchip_inject_ioctl = KVM_IRQ_LINE;
|
||||
if (kvm_check_extension(s, KVM_CAP_IRQ_INJECT_STATUS)) {
|
||||
s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS;
|
||||
}
|
||||
s->irqchip_in_kernel = 1;
|
||||
|
||||
kvm_init_irq_routing(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_init(void)
|
||||
{
|
||||
static const char upgrade_note[] =
|
||||
|
@ -824,6 +963,11 @@ int kvm_init(void)
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = kvm_irqchip_create(s);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
kvm_state = s;
|
||||
memory_listener_register(&kvm_memory_listener);
|
||||
|
||||
|
@ -1159,6 +1303,16 @@ int kvm_has_many_ioeventfds(void)
|
|||
return kvm_state->many_ioeventfds;
|
||||
}
|
||||
|
||||
int kvm_has_gsi_routing(void)
|
||||
{
|
||||
return kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
|
||||
}
|
||||
|
||||
int kvm_allows_irq0_override(void)
|
||||
{
|
||||
return !kvm_enabled() || !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
|
||||
}
|
||||
|
||||
void kvm_setup_guest_memory(void *start, size_t size)
|
||||
{
|
||||
if (!kvm_has_sync_mmu()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue