~fboudra/qemu-linaro/new-upstream-release-1.2.0-2012.09-0ubuntu1

« back to all changes in this revision

Viewing changes to hw/kvm/arm_gic.c

  • Committer: Fathi Boudra
  • Author(s): Fathi Boudra
  • Date: 2012-08-21 06:47:11 UTC
  • mfrom: (0.1.16)
  • Revision ID: fathi.boudra@linaro.org-20120821064711-7yxmubp2v8a44xce
Tags: 1.1.50-2012.08-0ubuntu1
* New upstream release.
  - support emulated systems with more than 2G of memory. (LP: #1030588)
* Drop powerpc-missing-include.patch - merged upstream.
* Update debian/control: 
  - drop perl build dependency.
  - add libfdt-dev build dependency.
* Update debian/qemu-keymaps.install file.
* Update debian/rules:
  - update QEMU_CPU for ARM architecture: armv4l -> armv7l.
  - update conf_audio_drv: default to PulseAudio since PA is the default on
    Ubuntu.
  - enable KVM on ARM architecture.
  - enable flat device tree support (--enable-fdt). (LP: #1030594)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ARM Generic Interrupt Controller using KVM in-kernel support
 
3
 *
 
4
 * Copyright (c) 2012 Linaro Limited
 
5
 * Written by Peter Maydell
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation, either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along
 
18
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#include "hw/sysbus.h"
 
22
#include "kvm.h"
 
23
#include "hw/arm_gic_internal.h"
 
24
 
 
25
#define TYPE_KVM_ARM_GIC "kvm-arm_gic"
 
26
#define KVM_ARM_GIC(obj) \
 
27
     OBJECT_CHECK(gic_state, (obj), TYPE_KVM_ARM_GIC)
 
28
#define KVM_ARM_GIC_CLASS(klass) \
 
29
     OBJECT_CLASS_CHECK(KVMARMGICClass, (klass), TYPE_KVM_ARM_GIC)
 
30
#define KVM_ARM_GIC_GET_CLASS(obj) \
 
31
     OBJECT_GET_CLASS(KVMARMGICClass, (obj), TYPE_KVM_ARM_GIC)
 
32
 
 
33
typedef struct KVMARMGICClass {
 
34
    ARMGICCommonClass parent_class;
 
35
    int (*parent_init)(SysBusDevice *dev);
 
36
    void (*parent_reset)(DeviceState *dev);
 
37
} KVMARMGICClass;
 
38
 
 
39
static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
 
40
{
 
41
    /* Meaning of the 'irq' parameter:
 
42
     *  [0..N-1] : external interrupts
 
43
     *  [N..N+31] : PPI (internal) interrupts for CPU 0
 
44
     *  [N+32..N+63] : PPI (internal interrupts for CPU 1
 
45
     *  ...
 
46
     */
 
47
    gic_state *s = (gic_state *)opaque;
 
48
 
 
49
 
 
50
    if (irq < (s->num_irq - GIC_INTERNAL)) {
 
51
        /* External interrupt number 'irq' */
 
52
        kvm_set_irq(kvm_state, irq + GIC_INTERNAL, !!level);
 
53
    } else {
 
54
        struct kvm_irq_level irq_level;
 
55
        int cpu;
 
56
        irq -= (s->num_irq - GIC_INTERNAL);
 
57
        cpu = irq / GIC_INTERNAL;
 
58
        irq %= GIC_INTERNAL;
 
59
        /* Internal interrupt 'irq' for CPU 'cpu' */
 
60
        irq_level.irq = irq;
 
61
        irq_level.level = !!level;
 
62
        kvm_vcpu_ioctl(qemu_get_cpu(cpu), KVM_IRQ_LINE, &irq_level);
 
63
    }
 
64
}
 
65
 
 
66
static void kvm_arm_gic_put(gic_state *s)
 
67
{
 
68
    /* TODO: there isn't currently a kernel interface to set the GIC state */
 
69
}
 
70
 
 
71
static void kvm_arm_gic_get(gic_state *s)
 
72
{
 
73
    /* TODO: there isn't currently a kernel interface to get the GIC state */
 
74
}
 
75
 
 
76
static void kvm_arm_gic_reset(DeviceState *dev)
 
77
{
 
78
    gic_state *s = ARM_GIC_COMMON(dev);
 
79
    KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
 
80
    kgc->parent_reset(dev);
 
81
    kvm_arm_gic_put(s);
 
82
}
 
83
 
 
84
static int kvm_arm_gic_init(SysBusDevice *dev)
 
85
{
 
86
    /* Device instance init function for the GIC sysbus device */
 
87
    int i;
 
88
    gic_state *s = FROM_SYSBUS(gic_state, dev);
 
89
    KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
 
90
 
 
91
    kgc->parent_init(dev);
 
92
 
 
93
    i = s->num_irq - GIC_INTERNAL;
 
94
    /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
 
95
     * GPIO array layout is thus:
 
96
     *  [0..N-1] SPIs
 
97
     *  [N..N+31] PPIs for CPU 0
 
98
     *  [N+32..N+63] PPIs for CPU 1
 
99
     *   ...
 
100
     */
 
101
    i += (GIC_INTERNAL * s->num_cpu);
 
102
    qdev_init_gpio_in(&s->busdev.qdev, kvm_arm_gic_set_irq, i);
 
103
    /* We never use our outbound IRQ lines but provide them so that
 
104
     * we maintain the same interface as the non-KVM GIC.
 
105
     */
 
106
    for (i = 0; i < s->num_cpu; i++) {
 
107
        sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
 
108
    }
 
109
    /* Distributor */
 
110
    memory_region_init_reservation(&s->iomem, "kvm-gic_dist", 0x1000);
 
111
    sysbus_init_mmio(dev, &s->iomem);
 
112
    /* CPU interface for current core. Unlike arm_gic, we don't
 
113
     * provide the "interface for core #N" memory regions, because
 
114
     * cores with a VGIC don't have those.
 
115
     */
 
116
    memory_region_init_reservation(&s->cpuiomem[0], "kvm-gic_cpu", 0x1000);
 
117
    sysbus_init_mmio(dev, &s->cpuiomem[0]);
 
118
    /* TODO: we should tell the kernel at some point the address
 
119
     * of the private peripheral base. However we don't currently have
 
120
     * any convenient infrastructure to do that, and in any case the
 
121
     * kernel doesn't yet implement an ioctl to let us tell it.
 
122
     */
 
123
    return 0;
 
124
}
 
125
 
 
126
static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
 
127
{
 
128
    DeviceClass *dc = DEVICE_CLASS(klass);
 
129
    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
 
130
    ARMGICCommonClass *agcc = ARM_GIC_COMMON_CLASS(klass);
 
131
    KVMARMGICClass *kgc = KVM_ARM_GIC_CLASS(klass);
 
132
    agcc->pre_save = kvm_arm_gic_get;
 
133
    agcc->post_load = kvm_arm_gic_put;
 
134
    kgc->parent_init = sbc->init;
 
135
    kgc->parent_reset = dc->reset;
 
136
    sbc->init = kvm_arm_gic_init;
 
137
    dc->reset = kvm_arm_gic_reset;
 
138
    dc->no_user = 1;
 
139
}
 
140
 
 
141
static TypeInfo arm_gic_info = {
 
142
    .name = TYPE_KVM_ARM_GIC,
 
143
    .parent = TYPE_ARM_GIC_COMMON,
 
144
    .instance_size = sizeof(gic_state),
 
145
    .class_init = kvm_arm_gic_class_init,
 
146
};
 
147
 
 
148
static void arm_gic_register_types(void)
 
149
{
 
150
    type_register_static(&arm_gic_info);
 
151
}
 
152
 
 
153
type_init(arm_gic_register_types)