Patchwork [qom-next,05/59] apic: Replace cpu_env pointer by X86CPU link

login
register
mail settings
Submitter Andreas Färber
Date May 23, 2012, 3:07 a.m.
Message ID <1337742502-28565-6-git-send-email-afaerber@suse.de>
Download mbox | patch
Permalink /patch/160814/
State New
Headers show

Comments

Andreas Färber - May 23, 2012, 3:07 a.m.
Needed for converting cpu_is_bsp().

Signed-off-by: Andreas Färber <afaerber@suse.de>
Cc: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/apic.c          |   34 +++++++++++++++++++---------------
 hw/apic_common.c   |   14 +++++++++++---
 hw/apic_internal.h |    2 +-
 hw/kvm/apic.c      |    9 +++++----
 hw/pc.c            |    9 ++++++++-
 5 files changed, 44 insertions(+), 24 deletions(-)
Igor Mammedov - July 11, 2012, 10:47 a.m.
On 05/23/2012 05:07 AM, Andreas Färber wrote:
> Needed for converting cpu_is_bsp().
>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> ---
...
> @@ -899,7 +900,13 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
>       }
>
>       qdev_prop_set_uint8(dev, "id", apic_id);
> -    qdev_prop_set_ptr(dev, "cpu_env", env);
> +    object_property_set_link(OBJECT(dev), OBJECT(ENV_GET_CPU(env)), "cpu",
> +                             &error);

Setting back-link should be done before or inside of x86_cpu_realize(),
i.e. no CPU internals outside of CPU object.
But that depends on CPU becoming a child of something between object_new(TYPE_X86_CPU)
and x86_cpu_realize(), otherwise it would crash in object_property_set_link ().

Currently it could be done in target-i386/helper.c:cpu_x86_init()but not in
hw/pc.c:pc_new_cpu() because cpu_x86_init() returns realized CPU.

Perhaps we should wait with this and previous patch till APIC is moved inside of CPU.

As a way to avoid back-link issue we could make CPU a child of /machine in
cpu_x86_init() before callling x86_cpu_realize(). Yes, it won't be at board level but it won't
hurt *-user target and might be acceptable sacrifice for i386-softmmu in effort of QOMifing
x86cpu and converting from qdev_prop_set_ptr() to object_property_set_link().

Patch

diff --git a/hw/apic.c b/hw/apic.c
index 4eeaf88..1207c33 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -114,7 +114,7 @@  static void apic_sync_vapic(APICCommonState *s, int sync_type)
         length = offsetof(VAPICState, enabled) - offsetof(VAPICState, isr);
 
         if (sync_type & SYNC_TO_VAPIC) {
-            assert(qemu_cpu_is_self(s->cpu_env));
+            assert(qemu_cpu_is_self(&s->cpu->env));
 
             vapic_state.tpr = s->tpr;
             vapic_state.enabled = 1;
@@ -158,15 +158,15 @@  static void apic_local_deliver(APICCommonState *s, int vector)
 
     switch ((lvt >> 8) & 7) {
     case APIC_DM_SMI:
-        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SMI);
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SMI);
         break;
 
     case APIC_DM_NMI:
-        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_NMI);
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_NMI);
         break;
 
     case APIC_DM_EXTINT:
-        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
         break;
 
     case APIC_DM_FIXED:
@@ -194,7 +194,7 @@  void apic_deliver_pic_intr(DeviceState *d, int level)
             reset_bit(s->irr, lvt & 0xff);
             /* fall through */
         case APIC_DM_EXTINT:
-            cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
             break;
         }
     }
@@ -255,18 +255,22 @@  static void apic_bus_deliver(const uint32_t *deliver_bitmask,
 
         case APIC_DM_SMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
+                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_SMI)
+            );
             return;
 
         case APIC_DM_NMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
+                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_NMI)
+            );
             return;
 
         case APIC_DM_INIT:
             /* normal INIT IPI sent to processors */
             foreach_apic(apic_iter, deliver_bitmask,
-                         cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
+                         cpu_interrupt(&apic_iter->cpu->env,
+                                       CPU_INTERRUPT_INIT)
+            );
             return;
 
         case APIC_DM_EXTINT:
@@ -300,7 +304,7 @@  static void apic_set_base(APICCommonState *s, uint64_t val)
     /* if disabled, cannot be enabled again */
     if (!(val & MSR_IA32_APICBASE_ENABLE)) {
         s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
-        cpu_clear_apic_feature(s->cpu_env);
+        cpu_clear_apic_feature(&s->cpu->env);
         s->spurious_vec &= ~APIC_SV_ENABLE;
     }
 }
@@ -370,7 +374,7 @@  static void apic_update_irq(APICCommonState *s)
         return;
     }
     if (apic_irq_pending(s) > 0) {
-        cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+        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);
@@ -480,18 +484,18 @@  static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
 static void apic_startup(APICCommonState *s, int vector_num)
 {
     s->sipi_vector = vector_num;
-    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
+    cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
 }
 
 void apic_sipi(DeviceState *d)
 {
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
 
-    cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_SIPI);
+    cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
 
     if (!s->wait_for_sipi)
         return;
-    cpu_x86_load_seg_cache_sipi(s->cpu_env, s->sipi_vector);
+    cpu_x86_load_seg_cache_sipi(&s->cpu->env, s->sipi_vector);
     s->wait_for_sipi = 0;
 }
 
@@ -666,7 +670,7 @@  static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
     case 0x08:
         apic_sync_vapic(s, SYNC_FROM_VAPIC);
         if (apic_report_tpr_access) {
-            cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_READ);
+            cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_READ);
         }
         val = s->tpr;
         break;
@@ -768,7 +772,7 @@  static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
         break;
     case 0x08:
         if (apic_report_tpr_access) {
-            cpu_report_tpr_access(s->cpu_env, TPR_ACCESS_WRITE);
+            cpu_report_tpr_access(&s->cpu->env, TPR_ACCESS_WRITE);
         }
         s->tpr = val;
         apic_sync_vapic(s, SYNC_TO_VAPIC);
diff --git a/hw/apic_common.c b/hw/apic_common.c
index 60b8259..46a9ff7 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -103,7 +103,7 @@  void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
 {
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
 
-    vapic_report_tpr_access(s->vapic, s->cpu_env, ip, access);
+    vapic_report_tpr_access(s->vapic, &s->cpu->env, ip, access);
 }
 
 void apic_report_irq_delivered(int delivered)
@@ -207,7 +207,7 @@  static void apic_reset_common(DeviceState *d)
     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
     bool bsp;
 
-    bsp = cpu_is_bsp(s->cpu_env);
+    bsp = cpu_is_bsp(&s->cpu->env);
     s->apicbase = 0xfee00000 |
         (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
 
@@ -354,9 +354,16 @@  static const VMStateDescription vmstate_apic_common = {
     }
 };
 
+static void apic_common_initfn(Object *obj)
+{
+    APICCommonState *s = APIC_COMMON(obj);
+
+    object_property_add_link(obj, "cpu", TYPE_X86_CPU, (Object **)&s->cpu,
+                             NULL);
+}
+
 static Property apic_properties_common[] = {
     DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
-    DEFINE_PROP_PTR("cpu_env", APICCommonState, cpu_env),
     DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
                     true),
     DEFINE_PROP_END_OF_LIST(),
@@ -378,6 +385,7 @@  static TypeInfo apic_common_type = {
     .name = TYPE_APIC_COMMON,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(APICCommonState),
+    .instance_init = apic_common_initfn,
     .class_size = sizeof(APICCommonClass),
     .class_init = apic_common_class_init,
     .abstract = true,
diff --git a/hw/apic_internal.h b/hw/apic_internal.h
index 60a6a8b..645718c 100644
--- a/hw/apic_internal.h
+++ b/hw/apic_internal.h
@@ -96,7 +96,7 @@  typedef struct APICCommonClass
 struct APICCommonState {
     SysBusDevice busdev;
     MemoryRegion io_memory;
-    void *cpu_env;
+    X86CPU *cpu;
     uint32_t apicbase;
     uint8_t id;
     uint8_t arb_id;
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index ffe7a52..cf52bb2 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -103,7 +103,7 @@  static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable)
         .enabled = enable
     };
 
-    kvm_vcpu_ioctl(s->cpu_env, KVM_TPR_ACCESS_REPORTING, &ctl);
+    kvm_vcpu_ioctl(&s->cpu->env, KVM_TPR_ACCESS_REPORTING, &ctl);
 }
 
 static void kvm_apic_vapic_base_update(APICCommonState *s)
@@ -113,7 +113,7 @@  static void kvm_apic_vapic_base_update(APICCommonState *s)
     };
     int ret;
 
-    ret = kvm_vcpu_ioctl(s->cpu_env, KVM_SET_VAPIC_ADDR, &vapid_addr);
+    ret = kvm_vcpu_ioctl(&s->cpu->env, KVM_SET_VAPIC_ADDR, &vapid_addr);
     if (ret < 0) {
         fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n",
                 strerror(-ret));
@@ -124,7 +124,8 @@  static void kvm_apic_vapic_base_update(APICCommonState *s)
 static void do_inject_external_nmi(void *data)
 {
     APICCommonState *s = data;
-    CPUX86State *env = s->cpu_env;
+    X86CPU *cpu = s->cpu;
+    CPUX86State *env = &cpu->env;
     uint32_t lvt;
     int ret;
 
@@ -142,7 +143,7 @@  static void do_inject_external_nmi(void *data)
 
 static void kvm_apic_external_nmi(APICCommonState *s)
 {
-    run_on_cpu(s->cpu_env, do_inject_external_nmi, s);
+    run_on_cpu(&s->cpu->env, do_inject_external_nmi, s);
 }
 
 static void kvm_apic_init(APICCommonState *s)
diff --git a/hw/pc.c b/hw/pc.c
index e9d7e05..6bb3d2a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -888,6 +888,7 @@  DeviceState *cpu_get_current_apic(void)
 static DeviceState *apic_init(void *env, uint8_t apic_id)
 {
     DeviceState *dev;
+    Error *error = NULL;
     static int apic_mapped;
 
     if (kvm_irqchip_in_kernel()) {
@@ -899,7 +900,13 @@  static DeviceState *apic_init(void *env, uint8_t apic_id)
     }
 
     qdev_prop_set_uint8(dev, "id", apic_id);
-    qdev_prop_set_ptr(dev, "cpu_env", env);
+    object_property_set_link(OBJECT(dev), OBJECT(ENV_GET_CPU(env)), "cpu",
+                             &error);
+    if (error_is_set(&error)) {
+        qerror_report_err(error);
+        error_free(error);
+        exit(1);
+    }
     qdev_init_nofail(dev);
 
     /* XXX: mapping more APICs at the same memory location */