Revision 53a89e26

b/hw/cpu/icc_bus.c
80 80
    /*< public >*/
81 81

  
82 82
    ICCBus icc_bus;
83
    MemoryRegion apic_container;
83 84
} ICCBridgeState;
84 85

  
85 86
#define ICC_BRIGDE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
......
87 88
static void icc_bridge_init(Object *obj)
88 89
{
89 90
    ICCBridgeState *s = ICC_BRIGDE(obj);
91
    SysBusDevice *sb = SYS_BUS_DEVICE(obj);
90 92

  
91 93
    qbus_create_inplace(&s->icc_bus, TYPE_ICC_BUS, DEVICE(s), "icc");
94

  
95
    /* Do not change order of registering regions,
96
     * APIC must be first registered region, board maps it by 0 index
97
     */
98
    memory_region_init(&s->apic_container, "icc-apic-container",
99
                       APIC_SPACE_SIZE);
100
    sysbus_init_mmio(sb, &s->apic_container);
101
    s->icc_bus.apic_address_space = &s->apic_container;
92 102
}
93 103

  
94 104
static const TypeInfo icc_bridge_info = {
b/hw/i386/pc.c
53 53
#include "qemu/bitmap.h"
54 54
#include "qemu/config-file.h"
55 55
#include "hw/acpi/acpi.h"
56
#include "hw/cpu/icc_bus.h"
56 57

  
57 58
/* debug PC/ISA interrupts */
58 59
//#define DEBUG_IRQ
......
921 922
void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
922 923
{
923 924
    int i;
925
    X86CPU *cpu = NULL;
924 926
    Error *error = NULL;
925 927

  
926 928
    /* init CPUs */
......
933 935
    }
934 936

  
935 937
    for (i = 0; i < smp_cpus; i++) {
936
        pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
937
                   icc_bridge, &error);
938
        cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
939
                         icc_bridge, &error);
938 940
        if (error) {
939 941
            fprintf(stderr, "%s\n", error_get_pretty(error));
940 942
            error_free(error);
941 943
            exit(1);
942 944
        }
943 945
    }
946

  
947
    /* map APIC MMIO area if CPU has APIC */
948
    if (cpu && cpu->env.apic_state) {
949
        /* XXX: what if the base changes? */
950
        sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
951
                                APIC_DEFAULT_ADDRESS, 0x1000);
952
    }
944 953
}
945 954

  
946 955
void pc_acpi_init(const char *default_dsdt)
b/hw/intc/apic_common.c
21 21
#include "hw/i386/apic_internal.h"
22 22
#include "trace.h"
23 23
#include "sysemu/kvm.h"
24
#include "hw/qdev.h"
25
#include "hw/sysbus.h"
24 26

  
25 27
static int apic_irq_delivered;
26 28
bool apic_report_tpr_access;
......
282 284
    return 0;
283 285
}
284 286

  
285
static int apic_init_common(SysBusDevice *dev)
287
static int apic_init_common(ICCDevice *dev)
286 288
{
287 289
    APICCommonState *s = APIC_COMMON(dev);
288 290
    APICCommonClass *info;
289 291
    static DeviceState *vapic;
290 292
    static int apic_no;
293
    static bool mmio_registered;
291 294

  
292 295
    if (apic_no >= MAX_APICS) {
293 296
        return -1;
......
296 299

  
297 300
    info = APIC_COMMON_GET_CLASS(s);
298 301
    info->init(s);
299

  
300
    sysbus_init_mmio(dev, &s->io_memory);
302
    if (!mmio_registered) {
303
        ICCBus *b = ICC_BUS(qdev_get_parent_bus(DEVICE(dev)));
304
        memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory);
305
        mmio_registered = true;
306
    }
301 307

  
302 308
    /* Note: We need at least 1M to map the VAPIC option ROM */
303 309
    if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
......
375 381

  
376 382
static void apic_common_class_init(ObjectClass *klass, void *data)
377 383
{
378
    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
384
    ICCDeviceClass *idc = ICC_DEVICE_CLASS(klass);
379 385
    DeviceClass *dc = DEVICE_CLASS(klass);
380 386

  
381 387
    dc->vmsd = &vmstate_apic_common;
382 388
    dc->reset = apic_reset_common;
383 389
    dc->no_user = 1;
384 390
    dc->props = apic_properties_common;
385
    sc->init = apic_init_common;
391
    idc->init = apic_init_common;
386 392
}
387 393

  
388 394
static const TypeInfo apic_common_type = {
389 395
    .name = TYPE_APIC_COMMON,
390
    .parent = TYPE_SYS_BUS_DEVICE,
396
    .parent = TYPE_ICC_DEVICE,
391 397
    .instance_size = sizeof(APICCommonState),
392 398
    .class_size = sizeof(APICCommonClass),
393 399
    .class_init = apic_common_class_init,
b/include/hw/cpu/icc_bus.h
22 22
#ifndef ICC_BUS_H
23 23
#define ICC_BUS_H
24 24

  
25
#include "exec/memory.h"
25 26
#include "hw/qdev-core.h"
26 27

  
27 28
#define TYPE_ICC_BUS "icc-bus"
......
37 38
    /*< private >*/
38 39
    BusState parent_obj;
39 40
    /*< public >*/
41

  
42
    MemoryRegion *apic_address_space;
40 43
} ICCBus;
41 44

  
42 45
#define ICC_BUS(obj) OBJECT_CHECK(ICCBus, (obj), TYPE_ICC_BUS)
b/include/hw/i386/apic_internal.h
21 21
#define QEMU_APIC_INTERNAL_H
22 22

  
23 23
#include "exec/memory.h"
24
#include "hw/sysbus.h"
24
#include "hw/cpu/icc_bus.h"
25 25
#include "qemu/timer.h"
26 26

  
27 27
/* APIC Local Vector Table */
......
78 78

  
79 79
typedef struct APICCommonClass
80 80
{
81
    SysBusDeviceClass parent_class;
81
    ICCDeviceClass parent_class;
82 82

  
83 83
    void (*init)(APICCommonState *s);
84 84
    void (*set_base)(APICCommonState *s, uint64_t val);
......
92 92
} APICCommonClass;
93 93

  
94 94
struct APICCommonState {
95
    SysBusDevice busdev;
95
    ICCDevice busdev;
96 96

  
97 97
    MemoryRegion io_memory;
98 98
    X86CPU *cpu;
b/target-i386/cpu.c
41 41
#endif
42 42

  
43 43
#include "sysemu/sysemu.h"
44
#include "hw/qdev-properties.h"
44 45
#include "hw/cpu/icc_bus.h"
45 46
#ifndef CONFIG_USER_ONLY
46 47
#include "hw/xen/xen.h"
47
#include "hw/sysbus.h"
48 48
#include "hw/i386/apic_internal.h"
49 49
#endif
50 50

  
......
2131 2131
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
2132 2132
{
2133 2133
    CPUX86State *env = &cpu->env;
2134
    DeviceState *dev = DEVICE(cpu);
2134 2135
    APICCommonState *apic;
2135 2136
    const char *apic_type = "apic";
2136 2137

  
......
2140 2141
        apic_type = "xen-apic";
2141 2142
    }
2142 2143

  
2143
    env->apic_state = qdev_try_create(NULL, apic_type);
2144
    env->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
2144 2145
    if (env->apic_state == NULL) {
2145 2146
        error_setg(errp, "APIC device '%s' could not be created", apic_type);
2146 2147
        return;
......
2157 2158
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
2158 2159
{
2159 2160
    CPUX86State *env = &cpu->env;
2160
    static int apic_mapped;
2161 2161

  
2162 2162
    if (env->apic_state == NULL) {
2163 2163
        return;
......
2168 2168
                   object_get_typename(OBJECT(env->apic_state)));
2169 2169
        return;
2170 2170
    }
2171

  
2172
    /* XXX: mapping more APICs at the same memory location */
2173
    if (apic_mapped == 0) {
2174
        /* NOTE: the APIC is directly connected to the CPU - it is not
2175
           on the global memory bus. */
2176
        /* XXX: what if the base changes? */
2177
        sysbus_mmio_map_overlap(SYS_BUS_DEVICE(env->apic_state), 0,
2178
                                APIC_DEFAULT_ADDRESS, 0x1000);
2179
        apic_mapped = 1;
2180
    }
2181 2171
}
2182 2172
#else
2183 2173
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)

Also available in: Unified diff