From patchwork Thu Feb 3 19:32:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 81713 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4CE60B70DA for ; Fri, 4 Feb 2011 07:21:07 +1100 (EST) Received: from localhost ([127.0.0.1]:59130 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pl5D5-0008Lh-Vu for incoming@patchwork.ozlabs.org; Thu, 03 Feb 2011 14:51:20 -0500 Received: from [140.186.70.92] (port=45290 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pl58O-0006F2-Er for qemu-devel@nongnu.org; Thu, 03 Feb 2011 14:46:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Pl4vM-0008Es-Ih for qemu-devel@nongnu.org; Thu, 03 Feb 2011 14:33:02 -0500 Received: from david.siemens.de ([192.35.17.14]:34242) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Pl4vM-0008Em-28 for qemu-devel@nongnu.org; Thu, 03 Feb 2011 14:33:00 -0500 Received: from mail1.siemens.de (localhost [127.0.0.1]) by david.siemens.de (8.13.6/8.13.6) with ESMTP id p13JWvHa028794; Thu, 3 Feb 2011 20:32:57 +0100 Received: from mchn199C.mchp.siemens.de ([139.25.109.49]) by mail1.siemens.de (8.13.6/8.13.6) with ESMTP id p13JWuTG028480; Thu, 3 Feb 2011 20:32:57 +0100 Message-ID: <4D4B02E8.7060104@siemens.com> Date: Thu, 03 Feb 2011 20:32:56 +0100 From: Jan Kiszka User-Agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666 MIME-Version: 1.0 To: qemu-devel X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 192.35.17.14 Cc: Blue Swirl Subject: [Qemu-devel] [RFC][PATCH] apic: Fix relocation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org When the guest remaps an APIC by modifying MSR_IA32_APICBASE, we need to update its mmio mapping. This is a bit tricky as multiple APICs might be mapped to the same address. So walk through the full list to avoid unmapping a region that is still in use. Signed-off-by: Jan Kiszka --- RFC as I did not yet have a chance to test actual relocation. Standard OSes don't do this, otherwise we would have noticed this earlier. hw/apic.c | 38 +++++++++++++++++++++++++++++++++++++- hw/pc.c | 10 ---------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/hw/apic.c b/hw/apic.c index 05a115f..b64af59 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -294,6 +294,40 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, trigger_mode); } +static void apic_update_mapping(APICState *s) +{ + target_phys_addr_t new_addr; + bool overlap = false; + APICState *apic_iter; + int i; + + for (i = 0; i < MAX_APICS; i++) { + apic_iter = local_apics[i]; + if (!apic_iter || apic_iter == s) { + continue; + } + if ((apic_iter->apicbase & MSR_IA32_APICBASE_BASE) == + s->busdev.mmio[0].addr) { + overlap = true; + break; + } + } + if (overlap) { + /* + * As APICs are pre-CPU devices, they may have identical base + * addresses. We must avoid unregistering an old io-region that is + * still in use by another APIC. + */ + s->busdev.mmio[0].addr = (target_phys_addr_t)-1; + } + if (s->apicbase & MSR_IA32_APICBASE_ENABLE) { + new_addr = s->apicbase & MSR_IA32_APICBASE_BASE; + } else { + new_addr = (target_phys_addr_t)-1; + } + sysbus_mmio_map(&s->busdev, 0, new_addr); +} + void cpu_set_apic_base(DeviceState *d, uint64_t val) { APICState *s = DO_UPCAST(APICState, busdev.qdev, d); @@ -302,7 +336,7 @@ void cpu_set_apic_base(DeviceState *d, uint64_t val) if (!s) return; - s->apicbase = (val & 0xfffff000) | + s->apicbase = (val & MSR_IA32_APICBASE_BASE) | (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE)); /* if disabled, cannot be enabled again */ if (!(val & MSR_IA32_APICBASE_ENABLE)) { @@ -310,6 +344,7 @@ void cpu_set_apic_base(DeviceState *d, uint64_t val) cpu_clear_apic_feature(s->cpu_env); s->spurious_vec &= ~APIC_SV_ENABLE; } + apic_update_mapping(s); } uint64_t cpu_get_apic_base(DeviceState *d) @@ -948,6 +983,7 @@ static void apic_reset(DeviceState *d) bsp = cpu_is_bsp(s->cpu_env); s->apicbase = 0xfee00000 | (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; + apic_update_mapping(s); apic_init_reset(d); diff --git a/hw/pc.c b/hw/pc.c index 4dfdc0b..294aa66 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -859,7 +859,6 @@ static DeviceState *apic_init(void *env, uint8_t apic_id) { DeviceState *dev; SysBusDevice *d; - static int apic_mapped; dev = qdev_create(NULL, "apic"); qdev_prop_set_uint8(dev, "id", apic_id); @@ -867,15 +866,6 @@ static DeviceState *apic_init(void *env, uint8_t apic_id) qdev_init_nofail(dev); d = sysbus_from_qdev(dev); - /* XXX: mapping more APICs at the same memory location */ - if (apic_mapped == 0) { - /* NOTE: the APIC is directly connected to the CPU - it is not - on the global memory bus. */ - /* XXX: what if the base changes? */ - sysbus_mmio_map(d, 0, MSI_ADDR_BASE); - apic_mapped = 1; - } - msix_supported = 1; return dev;