From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487623090555612.8110018183335; Mon, 20 Feb 2017 12:38:10 -0800 (PST) Received: from localhost ([::1]:40959 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfuim-0005Q4-VS for importer@patchew.org; Mon, 20 Feb 2017 15:38:09 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35961) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucH-00086S-AD for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucG-0004dl-91 for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:25 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:42521) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucG-0004a6-33 for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:24 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 9C7CB4EA56025 for ; Mon, 20 Feb 2017 20:31:11 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:15 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:30:55 +0000 Message-ID: <1487622662-62984-2-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 1/8] hw/mips_cmgcr: allow GCR base to be moved X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paul Burton Support moving the GCR base address & updating the CPU's CP0 CMGCRBase register appropriately. This is required if a platform needs to move its GCRs away from other memory, as the MIPS Boston development board does to avoid its flash memory. Signed-off-by: Paul Burton Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim --- hw/misc/mips_cmgcr.c | 17 +++++++++++++++++ include/hw/misc/mips_cmgcr.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c index b3ba166..a1edb53 100644 --- a/hw/misc/mips_cmgcr.c +++ b/hw/misc/mips_cmgcr.c @@ -29,6 +29,20 @@ static inline bool is_gic_connected(MIPSGCRState *s) return s->gic_mr !=3D NULL; } =20 +static inline void update_gcr_base(MIPSGCRState *gcr, uint64_t val) +{ + CPUState *cpu; + MIPSCPU *mips_cpu; + + gcr->gcr_base =3D val & GCR_BASE_GCRBASE_MSK; + memory_region_set_address(&gcr->iomem, gcr->gcr_base); + + CPU_FOREACH(cpu) { + mips_cpu =3D MIPS_CPU(cpu); + mips_cpu->env.CP0_CMGCRBase =3D gcr->gcr_base >> 4; + } +} + static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val) { if (is_cpc_connected(gcr)) { @@ -117,6 +131,9 @@ static void gcr_write(void *opaque, hwaddr addr, uint64= _t data, unsigned size) MIPSGCRVPState *other_vps =3D &gcr->vps[current_vps->other]; =20 switch (addr) { + case GCR_BASE_OFS: + update_gcr_base(gcr, data); + break; case GCR_GIC_BASE_OFS: update_gic_base(gcr, data); break; diff --git a/include/hw/misc/mips_cmgcr.h b/include/hw/misc/mips_cmgcr.h index a209d91..c9dfcb4 100644 --- a/include/hw/misc/mips_cmgcr.h +++ b/include/hw/misc/mips_cmgcr.h @@ -41,6 +41,9 @@ #define GCR_L2_CONFIG_BYPASS_SHF 20 #define GCR_L2_CONFIG_BYPASS_MSK ((0x1ULL) << GCR_L2_CONFIG_BYPASS_SHF) =20 +/* GCR_BASE register fields */ +#define GCR_BASE_GCRBASE_MSK 0xffffffff8000ULL + /* GCR_GIC_BASE register fields */ #define GCR_GIC_BASE_GICEN_MSK 1 #define GCR_GIC_BASE_GICBASE_MSK 0xFFFFFFFE0000ULL --=20 2.7.4 From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487622817970543.7488537944955; Mon, 20 Feb 2017 12:33:37 -0800 (PST) Received: from localhost ([::1]:40933 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfueN-0000km-M6 for importer@patchew.org; Mon, 20 Feb 2017 15:33:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35890) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucE-00084f-Ab for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucB-0004bF-RG for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:22 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:41431) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucB-0004aL-M9 for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:19 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 325C5FC8ED46C for ; Mon, 20 Feb 2017 20:31:12 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:15 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:30:56 +0000 Message-ID: <1487622662-62984-3-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 2/8] hw/mips_gictimer: provide API for retrieving frequency X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Paul Burton Provide a new function mips_gictimer_get_freq() which returns the frequency at which a GIC timer will count. This will be useful for boards which perform setup based upon this frequency. Signed-off-by: Paul Burton Reviewed-by: Leon Alrae Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Yongbok Kim --- hw/timer/mips_gictimer.c | 5 +++++ include/hw/timer/mips_gictimer.h | 1 + 2 files changed, 6 insertions(+) diff --git a/hw/timer/mips_gictimer.c b/hw/timer/mips_gictimer.c index 3698889..f5c5806 100644 --- a/hw/timer/mips_gictimer.c +++ b/hw/timer/mips_gictimer.c @@ -14,6 +14,11 @@ =20 #define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ =20 +uint32_t mips_gictimer_get_freq(MIPSGICTimerState *gic) +{ + return NANOSECONDS_PER_SECOND / TIMER_PERIOD; +} + static void gic_vptimer_update(MIPSGICTimerState *gictimer, uint32_t vp_index, uint64_t now) { diff --git a/include/hw/timer/mips_gictimer.h b/include/hw/timer/mips_gicti= mer.h index c8bc5d2..c7ca6c8 100644 --- a/include/hw/timer/mips_gictimer.h +++ b/include/hw/timer/mips_gictimer.h @@ -31,6 +31,7 @@ struct MIPSGICTimerState { MIPSGICTimerCB *cb; }; =20 +uint32_t mips_gictimer_get_freq(MIPSGICTimerState *gic); uint32_t mips_gictimer_get_sh_count(MIPSGICTimerState *gic); void mips_gictimer_store_sh_count(MIPSGICTimerState *gic, uint64_t count); uint32_t mips_gictimer_get_vp_compare(MIPSGICTimerState *gictimer, --=20 2.7.4 From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487623288432550.7142750296586; Mon, 20 Feb 2017 12:41:28 -0800 (PST) Received: from localhost ([::1]:40979 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfulw-0007t5-Oj for importer@patchew.org; Mon, 20 Feb 2017 15:41:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35935) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucG-00085Q-5V for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucE-0004dG-S0 for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:24 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:59028) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucE-0004aU-Jc for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:22 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id C2CC2BDAC3BAB for ; Mon, 20 Feb 2017 20:31:12 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:16 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:30:57 +0000 Message-ID: <1487622662-62984-4-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 3/8] hw/mips_gic: Update pin state on mask changes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paul Burton If the GIC interrupt mask is changed by a write to the smask (set mask) or rmask (reset mask) registers, we need to re-evaluate the state of the pins/IRQs fed to the CPU. Without doing so we risk leaving a pin high despite the interrupt that led to that state being masked, or losing interrupts if an already pending interrupt is unmasked. Signed-off-by: Paul Burton Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim --- hw/intc/mips_gic.c | 56 ++++++++++++++++++++++++++++++--------------------= ---- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/hw/intc/mips_gic.c b/hw/intc/mips_gic.c index 6e25773..15e6e40 100644 --- a/hw/intc/mips_gic.c +++ b/hw/intc/mips_gic.c @@ -20,31 +20,29 @@ #include "kvm_mips.h" #include "hw/intc/mips_gic.h" =20 -static void mips_gic_set_vp_irq(MIPSGICState *gic, int vp, int pin, int le= vel) +static void mips_gic_set_vp_irq(MIPSGICState *gic, int vp, int pin) { - int ored_level =3D level; + int ored_level =3D 0; int i; =20 /* ORing pending registers sharing same pin */ - if (!ored_level) { - for (i =3D 0; i < gic->num_irq; i++) { - if ((gic->irq_state[i].map_pin & GIC_MAP_MSK) =3D=3D pin && - gic->irq_state[i].map_vp =3D=3D vp && - gic->irq_state[i].enabled) { - ored_level |=3D gic->irq_state[i].pending; - } - if (ored_level) { - /* no need to iterate all interrupts */ - break; - } + for (i =3D 0; i < gic->num_irq; i++) { + if ((gic->irq_state[i].map_pin & GIC_MAP_MSK) =3D=3D pin && + gic->irq_state[i].map_vp =3D=3D vp && + gic->irq_state[i].enabled) { + ored_level |=3D gic->irq_state[i].pending; } - if (((gic->vps[vp].compare_map & GIC_MAP_MSK) =3D=3D pin) && - (gic->vps[vp].mask & GIC_VP_MASK_CMP_MSK)) { - /* ORing with local pending register (count/compare) */ - ored_level |=3D (gic->vps[vp].pend & GIC_VP_MASK_CMP_MSK) >> - GIC_VP_MASK_CMP_SHF; + if (ored_level) { + /* no need to iterate all interrupts */ + break; } } + if (((gic->vps[vp].compare_map & GIC_MAP_MSK) =3D=3D pin) && + (gic->vps[vp].mask & GIC_VP_MASK_CMP_MSK)) { + /* ORing with local pending register (count/compare) */ + ored_level |=3D (gic->vps[vp].pend & GIC_VP_MASK_CMP_MSK) >> + GIC_VP_MASK_CMP_SHF; + } if (kvm_enabled()) { kvm_mips_set_ipi_interrupt(mips_env_get_cpu(gic->vps[vp].env), pin + GIC_CPU_PIN_OFFSET, @@ -55,21 +53,27 @@ static void mips_gic_set_vp_irq(MIPSGICState *gic, int = vp, int pin, int level) } } =20 -static void gic_set_irq(void *opaque, int n_IRQ, int level) +static void gic_update_pin_for_irq(MIPSGICState *gic, int n_IRQ) { - MIPSGICState *gic =3D (MIPSGICState *) opaque; int vp =3D gic->irq_state[n_IRQ].map_vp; int pin =3D gic->irq_state[n_IRQ].map_pin & GIC_MAP_MSK; =20 + if (vp < 0 || vp >=3D gic->num_vps) { + return; + } + mips_gic_set_vp_irq(gic, vp, pin); +} + +static void gic_set_irq(void *opaque, int n_IRQ, int level) +{ + MIPSGICState *gic =3D (MIPSGICState *) opaque; + gic->irq_state[n_IRQ].pending =3D (uint8_t) level; if (!gic->irq_state[n_IRQ].enabled) { /* GIC interrupt source disabled */ return; } - if (vp < 0 || vp >=3D gic->num_vps) { - return; - } - mips_gic_set_vp_irq(gic, vp, pin, level); + gic_update_pin_for_irq(gic, n_IRQ); } =20 #define OFFSET_CHECK(c) \ @@ -209,7 +213,7 @@ static void gic_timer_store_vp_compare(MIPSGICState *gi= c, uint32_t vp_index, gic->vps[vp_index].pend &=3D ~(1 << GIC_LOCAL_INT_COMPARE); if (gic->vps[vp_index].compare_map & GIC_MAP_TO_PIN_MSK) { uint32_t pin =3D (gic->vps[vp_index].compare_map & GIC_MAP_MSK); - mips_gic_set_vp_irq(gic, vp_index, pin, 0); + mips_gic_set_vp_irq(gic, vp_index, pin); } mips_gictimer_store_vp_compare(gic->gic_timer, vp_index, compare); } @@ -286,6 +290,7 @@ static void gic_write(void *opaque, hwaddr addr, uint64= _t data, unsigned size) OFFSET_CHECK((base + size * 8) <=3D gic->num_irq); for (i =3D 0; i < size * 8; i++) { gic->irq_state[base + i].enabled &=3D !((data >> i) & 1); + gic_update_pin_for_irq(gic, base + i); } break; case GIC_SH_WEDGE_OFS: @@ -305,6 +310,7 @@ static void gic_write(void *opaque, hwaddr addr, uint64= _t data, unsigned size) OFFSET_CHECK((base + size * 8) <=3D gic->num_irq); for (i =3D 0; i < size * 8; i++) { gic->irq_state[base + i].enabled |=3D (data >> i) & 1; + gic_update_pin_for_irq(gic, base + i); } break; case GIC_SH_MAP0_PIN_OFS ... GIC_SH_MAP255_PIN_OFS: --=20 2.7.4 From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487622821014738.5794518758722; Mon, 20 Feb 2017 12:33:41 -0800 (PST) Received: from localhost ([::1]:40935 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfueR-0000pP-Pc for importer@patchew.org; Mon, 20 Feb 2017 15:33:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35887) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucE-00084c-9Y for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucD-0004c5-9l for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:22 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:7129) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucD-0004aW-3M for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:21 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 5DC3FFB70D93B for ; Mon, 20 Feb 2017 20:31:13 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:17 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:30:58 +0000 Message-ID: <1487622662-62984-5-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 4/8] target-mips: Provide function to test if a CPU supports an ISA X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Paul Burton Provide a new cpu_supports_isa function which allows callers to determine whether a CPU supports one of the ISA_ flags, by testing whether the associated struct mips_def_t sets the ISA flags in its insn_flags field. An example use of this is to allow boards which generate bootloader code to determine the properties of the CPU that will be used, for example whether the CPU is 64 bit or which architecture revision it implements. Signed-off-by: Paul Burton Reviewed-by: Leon Alrae Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Yongbok Kim --- target/mips/cpu.h | 1 + target/mips/translate.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index e1c78f5..4a4747a 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -815,6 +815,7 @@ int cpu_mips_signal_handler(int host_signum, void *pinf= o, void *puc); =20 #define cpu_init(cpu_model) CPU(cpu_mips_init(cpu_model)) bool cpu_supports_cps_smp(const char *cpu_model); +bool cpu_supports_isa(const char *cpu_model, unsigned int isa); void cpu_set_exception_base(int vp_index, target_ulong address); =20 /* TODO QOM'ify CPU reset and remove */ diff --git a/target/mips/translate.c b/target/mips/translate.c index 7f8ecf4..8b4a072 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -20233,6 +20233,16 @@ bool cpu_supports_cps_smp(const char *cpu_model) return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) !=3D 0; } =20 +bool cpu_supports_isa(const char *cpu_model, unsigned int isa) +{ + const mips_def_t *def =3D cpu_mips_find_by_name(cpu_model); + if (!def) { + return false; + } + + return (def->insn_flags & isa) !=3D 0; +} + void cpu_set_exception_base(int vp_index, target_ulong address) { MIPSCPU *vp =3D MIPS_CPU(qemu_get_cpu(vp_index)); --=20 2.7.4 From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487622819429405.1896002941919; Mon, 20 Feb 2017 12:33:39 -0800 (PST) Received: from localhost ([::1]:40934 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfueQ-0000nn-0i for importer@patchew.org; Mon, 20 Feb 2017 15:33:38 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35888) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucE-00084d-9n for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucB-0004b6-KZ for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:22 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:2709) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucB-0004at-FQ for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:19 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id F141AAFF79688 for ; Mon, 20 Feb 2017 20:31:13 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:17 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:30:59 +0000 Message-ID: <1487622662-62984-6-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 5/8] dtc: Update requirement to v1.4.2 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paul Burton In order to obtain fdt_first_subnode & fdt_next_subnode symbols from libfdt for use by a later patch, bump the requirement for dtc to v1.4.2 & the submodule to that same version. Signed-off-by: Paul Burton Reviewed-by: Yongbok Kim Signed-off-by: Yongbok Kim --- configure | 6 +++--- dtc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 1c9655e..4b68861 100755 --- a/configure +++ b/configure @@ -3396,11 +3396,11 @@ fi if test "$fdt" !=3D "no" ; then fdt_libs=3D"-lfdt" # explicitly check for libfdt_env.h as it is missing in some stable inst= alls - # and test for required functions to make sure we are on a version >=3D = 1.4.0 + # and test for required functions to make sure we are on a version >=3D = 1.4.2 cat > $TMPC << EOF #include #include -int main(void) { fdt_get_property_by_offset(0, 0, 0); return 0; } +int main(void) { fdt_first_subnode(0, 0); return 0; } EOF if compile_prog "" "$fdt_libs" ; then # system DTC is good - use it @@ -3418,7 +3418,7 @@ EOF fdt_libs=3D"-L\$(BUILD_DIR)/dtc/libfdt $fdt_libs" elif test "$fdt" =3D "yes" ; then # have neither and want - prompt for system/submodule install - error_exit "DTC (libfdt) version >=3D 1.4.0 not present. Your options:= " \ + error_exit "DTC (libfdt) version >=3D 1.4.2 not present. Your options:= " \ " (1) Preferred: Install the DTC (libfdt) devel package" \ " (2) Fetch the DTC submodule, using:" \ " git submodule update --init dtc" diff --git a/dtc b/dtc index 65cc4d2..ec02b34 160000 --- a/dtc +++ b/dtc @@ -1 +1 @@ -Subproject commit 65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf +Subproject commit ec02b34c05be04f249ffaaca4b666f5246877dea --=20 2.7.4 From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487622839985139.50149610141045; Mon, 20 Feb 2017 12:33:59 -0800 (PST) Received: from localhost ([::1]:40936 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfuek-00011P-LM for importer@patchew.org; Mon, 20 Feb 2017 15:33:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35928) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucF-000851-GM for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucD-0004bw-0D for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:23 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:2709) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucC-0004at-Nw for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:20 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 814DDC396C528 for ; Mon, 20 Feb 2017 20:31:14 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:18 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:31:00 +0000 Message-ID: <1487622662-62984-7-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 6/8] loader: Support Flattened Image Trees (FIT images) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paul Burton Introduce support for loading Flattened Image Trees, as used by modern U-Boot. FIT images are essentially flattened device tree files which contain binary images such as kernels, FDTs or ramdisks along with one or more configuration nodes describing boot configurations. The MIPS Boston board typically boots kernels in the form of FIT images, and will make use of this code. Signed-off-by: Paul Burton [yongbok.kim@imgtec.com: fixed potential memory leaks] Signed-off-by: Yongbok Kim --- hw/core/Makefile.objs | 1 + hw/core/loader-fit.c | 325 ++++++++++++++++++++++++++++++++++++++++++++= ++++ hw/core/loader.c | 7 +- include/hw/loader-fit.h | 41 ++++++ include/hw/loader.h | 6 + 5 files changed, 374 insertions(+), 6 deletions(-) create mode 100644 hw/core/loader-fit.c create mode 100644 include/hw/loader-fit.h diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 7f8c9dc..ff59512 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -13,6 +13,7 @@ common-obj-$(CONFIG_PTIMER) +=3D ptimer.o common-obj-$(CONFIG_SOFTMMU) +=3D sysbus.o common-obj-$(CONFIG_SOFTMMU) +=3D machine.o common-obj-$(CONFIG_SOFTMMU) +=3D loader.o +common-obj-$(CONFIG_SOFTMMU) +=3D loader-fit.o common-obj-$(CONFIG_SOFTMMU) +=3D qdev-properties-system.o common-obj-$(CONFIG_SOFTMMU) +=3D register.o common-obj-$(CONFIG_SOFTMMU) +=3D or-irq.o diff --git a/hw/core/loader-fit.c b/hw/core/loader-fit.c new file mode 100644 index 0000000..4ddd35e --- /dev/null +++ b/hw/core/loader-fit.c @@ -0,0 +1,325 @@ +/* + * Flattened Image Tree loader. + * + * Copyright (c) 2016 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "hw/loader.h" +#include "hw/loader-fit.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "sysemu/device_tree.h" +#include "sysemu/sysemu.h" + +#include +#include + +#define FIT_LOADER_MAX_PATH (128) + +static const void *fit_load_image_alloc(const void *itb, const char *name, + int *poff, size_t *psz) +{ + const void *data; + const char *comp; + void *uncomp_data; + char path[FIT_LOADER_MAX_PATH]; + int off, sz; + ssize_t uncomp_len; + + snprintf(path, sizeof(path), "/images/%s", name); + + off =3D fdt_path_offset(itb, path); + if (off < 0) { + return NULL; + } + if (poff) { + *poff =3D off; + } + + data =3D fdt_getprop(itb, off, "data", &sz); + if (!data) { + return NULL; + } + + comp =3D fdt_getprop(itb, off, "compression", NULL); + if (!comp || !strcmp(comp, "none")) { + if (psz) { + *psz =3D sz; + } + uncomp_data =3D g_malloc(sz); + memmove(uncomp_data, data, sz); + return uncomp_data; + } + + if (!strcmp(comp, "gzip")) { + uncomp_len =3D UBOOT_MAX_GUNZIP_BYTES; + uncomp_data =3D g_malloc(uncomp_len); + + uncomp_len =3D gunzip(uncomp_data, uncomp_len, (void *) data, sz); + if (uncomp_len < 0) { + error_printf("unable to decompress %s image\n", name); + g_free(uncomp_data); + return NULL; + } + + data =3D g_realloc(uncomp_data, uncomp_len); + if (psz) { + *psz =3D uncomp_len; + } + return data; + } + + error_printf("unknown compression '%s'\n", comp); + return NULL; +} + +static int fit_image_addr(const void *itb, int img, const char *name, + hwaddr *addr) +{ + const void *prop; + int len; + + prop =3D fdt_getprop(itb, img, name, &len); + if (!prop) { + return -ENOENT; + } + + switch (len) { + case 4: + *addr =3D fdt32_to_cpu(*(fdt32_t *)prop); + return 0; + case 8: + *addr =3D fdt64_to_cpu(*(fdt64_t *)prop); + return 0; + default: + error_printf("invalid %s address length %d\n", name, len); + return -EINVAL; + } +} + +static int fit_load_kernel(const struct fit_loader *ldr, const void *itb, + int cfg, void *opaque, hwaddr *pend) +{ + const char *name; + const void *data; + const void *load_data; + hwaddr load_addr, entry_addr; + int img_off, err; + size_t sz; + int ret; + + name =3D fdt_getprop(itb, cfg, "kernel", NULL); + if (!name) { + error_printf("no kernel specified by FIT configuration\n"); + return -EINVAL; + } + + data =3D fit_load_image_alloc(itb, name, &img_off, &sz); + if (!data) { + error_printf("unable to load kernel image from FIT\n"); + return -EINVAL; + } + + err =3D fit_image_addr(itb, img_off, "load", &load_addr); + if (err) { + error_printf("unable to read kernel load address from FIT\n"); + ret =3D err; + goto out; + } + + err =3D fit_image_addr(itb, img_off, "entry", &entry_addr); + if (err) { + error_printf("unable to read kernel entry address from FIT\n"); + ret =3D err; + goto out; + } + + if (ldr->kernel_filter) { + load_data =3D ldr->kernel_filter(opaque, data, &load_addr, &entry_= addr); + } + + if (pend) { + *pend =3D load_addr + sz; + } + + load_addr =3D ldr->addr_to_phys(opaque, load_addr); + rom_add_blob_fixed(name, load_data, sz, load_addr); + + ret =3D 0; +out: + g_free((void *) data); + if (data !=3D load_data) { + g_free((void *) load_data); + } + return ret; +} + +static int fit_load_fdt(const struct fit_loader *ldr, const void *itb, + int cfg, void *opaque, const void *match_data, + hwaddr kernel_end) +{ + const char *name; + const void *data; + const void *load_data; + hwaddr load_addr; + int img_off, err; + size_t sz; + int ret; + + name =3D fdt_getprop(itb, cfg, "fdt", NULL); + if (!name) { + return 0; + } + + data =3D fit_load_image_alloc(itb, name, &img_off, &sz); + if (!data) { + error_printf("unable to load FDT image from FIT\n"); + return -EINVAL; + } + + err =3D fit_image_addr(itb, img_off, "load", &load_addr); + if (err =3D=3D -ENOENT) { + load_addr =3D ROUND_UP(kernel_end, 64 * K_BYTE) + (10 * M_BYTE); + } else if (err) { + ret =3D err; + goto out; + } + + if (ldr->fdt_filter) { + load_data =3D ldr->fdt_filter(opaque, data, match_data, &load_addr= ); + } + + load_addr =3D ldr->addr_to_phys(opaque, load_addr); + sz =3D fdt_totalsize(load_data); + rom_add_blob_fixed(name, load_data, sz, load_addr); + + ret =3D 0; +out: + g_free((void *) data); + if (data !=3D load_data) { + g_free((void *) load_data); + } + return ret; +} + +static bool fit_cfg_compatible(const void *itb, int cfg, const char *compa= t) +{ + const void *fdt; + const char *fdt_name; + bool ret; + + fdt_name =3D fdt_getprop(itb, cfg, "fdt", NULL); + if (!fdt_name) { + return false; + } + + fdt =3D fit_load_image_alloc(itb, fdt_name, NULL, NULL); + if (!fdt) { + return false; + } + + if (fdt_check_header(fdt)) { + ret =3D false; + goto out; + } + + if (fdt_node_check_compatible(fdt, 0, compat)) { + ret =3D false; + goto out; + } + + ret =3D true; +out: + g_free((void *) fdt); + return ret; +} + +int load_fit(const struct fit_loader *ldr, const char *filename, void *opa= que) +{ + const struct fit_loader_match *match; + const void *itb, *match_data =3D NULL; + const char *def_cfg_name; + char path[FIT_LOADER_MAX_PATH]; + int itb_size, configs, cfg_off, off, err; + hwaddr kernel_end; + int ret; + + itb =3D load_device_tree(filename, &itb_size); + if (!itb) { + return -EINVAL; + } + + configs =3D fdt_path_offset(itb, "/configurations"); + if (configs < 0) { + ret =3D configs; + goto out; + } + + cfg_off =3D -FDT_ERR_NOTFOUND; + + if (ldr->matches) { + for (match =3D ldr->matches; match->compatible; match++) { + off =3D fdt_first_subnode(itb, configs); + while (off >=3D 0) { + if (fit_cfg_compatible(itb, off, match->compatible)) { + cfg_off =3D off; + match_data =3D match->data; + break; + } + + off =3D fdt_next_subnode(itb, off); + } + + if (cfg_off >=3D 0) { + break; + } + } + } + + if (cfg_off < 0) { + def_cfg_name =3D fdt_getprop(itb, configs, "default", NULL); + if (def_cfg_name) { + snprintf(path, sizeof(path), "/configurations/%s", def_cfg_nam= e); + cfg_off =3D fdt_path_offset(itb, path); + } + } + + if (cfg_off < 0) { + /* couldn't find a configuration to use */ + ret =3D cfg_off; + goto out; + } + + err =3D fit_load_kernel(ldr, itb, cfg_off, opaque, &kernel_end); + if (err) { + ret =3D err; + goto out; + } + + err =3D fit_load_fdt(ldr, itb, cfg_off, opaque, match_data, kernel_end= ); + if (err) { + ret =3D err; + goto out; + } + + ret =3D 0; +out: + g_free((void *) itb); + return ret; +} diff --git a/hw/core/loader.c b/hw/core/loader.c index ee5abd6..8b980e9 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -527,12 +527,7 @@ static void zfree(void *x, void *addr) =20 #define DEFLATED 8 =20 -/* This is the usual maximum in uboot, so if a uImage overflows this, it w= ould - * overflow on real hardware too. */ -#define UBOOT_MAX_GUNZIP_BYTES (64 << 20) - -static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, - size_t srclen) +ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen) { z_stream s; ssize_t dstbytes; diff --git a/include/hw/loader-fit.h b/include/hw/loader-fit.h new file mode 100644 index 0000000..9e2a068 --- /dev/null +++ b/include/hw/loader-fit.h @@ -0,0 +1,41 @@ +/* + * Flattened Image Tree loader. + * + * Copyright (c) 2016 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_LOADER_FIT_H +#define HW_LOADER_FIT_H + +#include + +struct fit_loader_match { + const char *compatible; + const void *data; +}; + +struct fit_loader { + const struct fit_loader_match *matches; + hwaddr (*addr_to_phys)(void *opaque, uint64_t addr); + const void *(*fdt_filter)(void *opaque, const void *fdt, + const void *match_data, hwaddr *load_addr); + const void *(*kernel_filter)(void *opaque, const void *kernel, + hwaddr *load_addr, hwaddr *entry_addr); +}; + +int load_fit(const struct fit_loader *ldr, const char *filename, void *opa= que); + +#endif /* HW_LOADER_FIT_H */ diff --git a/include/hw/loader.h b/include/hw/loader.h index 0dbd8d6..40c4153 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -164,6 +164,8 @@ int load_uimage(const char *filename, hwaddr *ep, */ int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz); =20 +ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen); + ssize_t read_targphys(const char *name, int fd, hwaddr dst_addr, size_t nbytes); void pstrcpy_targphys(const char *name, @@ -214,4 +216,8 @@ void hmp_info_roms(Monitor *mon, const QDict *qdict); int rom_add_vga(const char *file); int rom_add_option(const char *file, int32_t bootindex); =20 +/* This is the usual maximum in uboot, so if a uImage overflows this, it w= ould + * overflow on real hardware too. */ +#define UBOOT_MAX_GUNZIP_BYTES (64 << 20) + #endif --=20 2.7.4 From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487623453757125.38361083778261; Mon, 20 Feb 2017 12:44:13 -0800 (PST) Received: from localhost ([::1]:40988 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfuoe-0001rd-AQ for importer@patchew.org; Mon, 20 Feb 2017 15:44:12 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35943) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucG-00085n-K7 for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucE-0004cV-0h for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:24 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:2709) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucD-0004at-Lt for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:21 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 3C6A7C3ED441B for ; Mon, 20 Feb 2017 20:31:15 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:18 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:31:01 +0000 Message-ID: <1487622662-62984-8-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 7/8] hw: xilinx-pcie: Add support for Xilinx AXI PCIe Controller X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paul Burton Add support for emulating the Xilinx AXI Root Port Bridge for PCI Express as described by Xilinx' PG055 document. This is a PCIe controller that can be used with certain series of Xilinx FPGAs, and is used on the MIPS Boston board which will make use of this code. Signed-off-by: Paul Burton [yongbok.kim@imgtec.com: removed returning on !level, updated IRQ connection with GPIO logic, moved xilinx_pcie_init() to boston.c replaced stw_le_p() with pci_set_word() and other cosmetic changes] Signed-off-by: Yongbok Kim --- hw/pci-host/Makefile.objs | 1 + hw/pci-host/xilinx-pcie.c | 328 ++++++++++++++++++++++++++++++++++= ++++ include/hw/pci-host/xilinx-pcie.h | 68 ++++++++ 3 files changed, 397 insertions(+) create mode 100644 hw/pci-host/xilinx-pcie.c create mode 100644 include/hw/pci-host/xilinx-pcie.h diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs index 45f1f0e..9c7909c 100644 --- a/hw/pci-host/Makefile.objs +++ b/hw/pci-host/Makefile.objs @@ -16,3 +16,4 @@ common-obj-$(CONFIG_FULONG) +=3D bonito.o common-obj-$(CONFIG_PCI_PIIX) +=3D piix.o common-obj-$(CONFIG_PCI_Q35) +=3D q35.o common-obj-$(CONFIG_PCI_GENERIC) +=3D gpex.o +common-obj-$(CONFIG_PCI_XILINX) +=3D xilinx-pcie.o diff --git a/hw/pci-host/xilinx-pcie.c b/hw/pci-host/xilinx-pcie.c new file mode 100644 index 0000000..8b71e2d --- /dev/null +++ b/hw/pci-host/xilinx-pcie.c @@ -0,0 +1,328 @@ +/* + * Xilinx PCIe host controller emulation. + * + * Copyright (c) 2016 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci-host/xilinx-pcie.h" + +enum root_cfg_reg { + /* Interrupt Decode Register */ + ROOTCFG_INTDEC =3D 0x138, + + /* Interrupt Mask Register */ + ROOTCFG_INTMASK =3D 0x13c, + /* INTx Interrupt Received */ +#define ROOTCFG_INTMASK_INTX (1 << 16) + /* MSI Interrupt Received */ +#define ROOTCFG_INTMASK_MSI (1 << 17) + + /* PHY Status/Control Register */ + ROOTCFG_PSCR =3D 0x144, + /* Link Up */ +#define ROOTCFG_PSCR_LINK_UP (1 << 11) + + /* Root Port Status/Control Register */ + ROOTCFG_RPSCR =3D 0x148, + /* Bridge Enable */ +#define ROOTCFG_RPSCR_BRIDGEEN (1 << 0) + /* Interrupt FIFO Not Empty */ +#define ROOTCFG_RPSCR_INTNEMPTY (1 << 18) + /* Interrupt FIFO Overflow */ +#define ROOTCFG_RPSCR_INTOVF (1 << 19) + + /* Root Port Interrupt FIFO Read Register 1 */ + ROOTCFG_RPIFR1 =3D 0x158, +#define ROOTCFG_RPIFR1_INT_LANE_SHIFT 27 +#define ROOTCFG_RPIFR1_INT_ASSERT_SHIFT 29 +#define ROOTCFG_RPIFR1_INT_VALID_SHIFT 31 + /* Root Port Interrupt FIFO Read Register 2 */ + ROOTCFG_RPIFR2 =3D 0x15c, +}; + +static void xilinx_pcie_update_intr(XilinxPCIEHost *s, + uint32_t set, uint32_t clear) +{ + int level; + + s->intr |=3D set; + s->intr &=3D ~clear; + + if (s->intr_fifo_r !=3D s->intr_fifo_w) { + s->intr |=3D ROOTCFG_INTMASK_INTX; + } + + level =3D !!(s->intr & s->intr_mask); + qemu_set_irq(s->irq, level); +} + +static void xilinx_pcie_queue_intr(XilinxPCIEHost *s, + uint32_t fifo_reg1, uint32_t fifo_reg2) +{ + XilinxPCIEInt *intr; + unsigned int new_w; + + new_w =3D (s->intr_fifo_w + 1) % ARRAY_SIZE(s->intr_fifo); + if (new_w =3D=3D s->intr_fifo_r) { + s->rpscr |=3D ROOTCFG_RPSCR_INTOVF; + return; + } + + intr =3D &s->intr_fifo[s->intr_fifo_w]; + s->intr_fifo_w =3D new_w; + + intr->fifo_reg1 =3D fifo_reg1; + intr->fifo_reg2 =3D fifo_reg2; + + xilinx_pcie_update_intr(s, ROOTCFG_INTMASK_INTX, 0); +} + +static void xilinx_pcie_set_irq(void *opaque, int irq_num, int level) +{ + XilinxPCIEHost *s =3D XILINX_PCIE_HOST(opaque); + + xilinx_pcie_queue_intr(s, + (irq_num << ROOTCFG_RPIFR1_INT_LANE_SHIFT) | + (level << ROOTCFG_RPIFR1_INT_ASSERT_SHIFT) | + (1 << ROOTCFG_RPIFR1_INT_VALID_SHIFT), + 0); +} + +static void xilinx_pcie_host_realize(DeviceState *dev, Error **errp) +{ + PCIHostState *pci =3D PCI_HOST_BRIDGE(dev); + XilinxPCIEHost *s =3D XILINX_PCIE_HOST(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + PCIExpressHost *pex =3D PCIE_HOST_BRIDGE(dev); + + snprintf(s->name, sizeof(s->name), "pcie%u", s->bus_nr); + + /* PCI configuration space */ + pcie_host_mmcfg_init(pex, s->cfg_size); + + /* MMIO region */ + memory_region_init(&s->mmio, OBJECT(s), "mmio", UINT64_MAX); + memory_region_set_enabled(&s->mmio, false); + + /* dummy I/O region */ + memory_region_init_ram(&s->io, OBJECT(s), "io", 16, NULL); + memory_region_set_enabled(&s->io, false); + + /* interrupt out */ + qdev_init_gpio_out_named(dev, &s->irq, "interrupt_out", 1); + + sysbus_init_mmio(sbd, &pex->mmio); + sysbus_init_mmio(sbd, &s->mmio); + + pci->bus =3D pci_register_bus(dev, s->name, xilinx_pcie_set_irq, + pci_swizzle_map_irq_fn, s, &s->mmio, + &s->io, 0, 4, TYPE_PCIE_BUS); + + qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus)); + qdev_init_nofail(DEVICE(&s->root)); +} + +static const char *xilinx_pcie_host_root_bus_path(PCIHostState *host_bridg= e, + PCIBus *rootbus) +{ + return "0000:00"; +} + +static void xilinx_pcie_host_init(Object *obj) +{ + XilinxPCIEHost *s =3D XILINX_PCIE_HOST(obj); + XilinxPCIERoot *root =3D &s->root; + + object_initialize(root, sizeof(*root), TYPE_XILINX_PCIE_ROOT); + object_property_add_child(obj, "root", OBJECT(root), NULL); + qdev_prop_set_uint32(DEVICE(root), "addr", PCI_DEVFN(0, 0)); + qdev_prop_set_bit(DEVICE(root), "multifunction", false); +} + +static Property xilinx_pcie_host_props[] =3D { + DEFINE_PROP_UINT32("bus_nr", XilinxPCIEHost, bus_nr, 0), + DEFINE_PROP_SIZE("cfg_base", XilinxPCIEHost, cfg_base, 0), + DEFINE_PROP_SIZE("cfg_size", XilinxPCIEHost, cfg_size, 32 << 20), + DEFINE_PROP_SIZE("mmio_base", XilinxPCIEHost, mmio_base, 0), + DEFINE_PROP_SIZE("mmio_size", XilinxPCIEHost, mmio_size, 1 << 20), + DEFINE_PROP_BOOL("link_up", XilinxPCIEHost, link_up, true), + DEFINE_PROP_END_OF_LIST(), +}; + +static void xilinx_pcie_host_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIHostBridgeClass *hc =3D PCI_HOST_BRIDGE_CLASS(klass); + + hc->root_bus_path =3D xilinx_pcie_host_root_bus_path; + dc->realize =3D xilinx_pcie_host_realize; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->fw_name =3D "pci"; + dc->props =3D xilinx_pcie_host_props; +} + +static const TypeInfo xilinx_pcie_host_info =3D { + .name =3D TYPE_XILINX_PCIE_HOST, + .parent =3D TYPE_PCIE_HOST_BRIDGE, + .instance_size =3D sizeof(XilinxPCIEHost), + .instance_init =3D xilinx_pcie_host_init, + .class_init =3D xilinx_pcie_host_class_init, +}; + +static uint32_t xilinx_pcie_root_config_read(PCIDevice *d, + uint32_t address, int len) +{ + XilinxPCIEHost *s =3D XILINX_PCIE_HOST(OBJECT(d)->parent); + uint32_t val; + + switch (address) { + case ROOTCFG_INTDEC: + val =3D s->intr; + break; + case ROOTCFG_INTMASK: + val =3D s->intr_mask; + break; + case ROOTCFG_PSCR: + val =3D s->link_up ? ROOTCFG_PSCR_LINK_UP : 0; + break; + case ROOTCFG_RPSCR: + if (s->intr_fifo_r !=3D s->intr_fifo_w) { + s->rpscr &=3D ~ROOTCFG_RPSCR_INTNEMPTY; + } else { + s->rpscr |=3D ROOTCFG_RPSCR_INTNEMPTY; + } + val =3D s->rpscr; + break; + case ROOTCFG_RPIFR1: + if (s->intr_fifo_w =3D=3D s->intr_fifo_r) { + /* FIFO empty */ + val =3D 0; + } else { + val =3D s->intr_fifo[s->intr_fifo_r].fifo_reg1; + } + break; + case ROOTCFG_RPIFR2: + if (s->intr_fifo_w =3D=3D s->intr_fifo_r) { + /* FIFO empty */ + val =3D 0; + } else { + val =3D s->intr_fifo[s->intr_fifo_r].fifo_reg2; + } + break; + default: + val =3D pci_default_read_config(d, address, len); + break; + } + return val; +} + +static void xilinx_pcie_root_config_write(PCIDevice *d, uint32_t address, + uint32_t val, int len) +{ + XilinxPCIEHost *s =3D XILINX_PCIE_HOST(OBJECT(d)->parent); + switch (address) { + case ROOTCFG_INTDEC: + xilinx_pcie_update_intr(s, 0, val); + break; + case ROOTCFG_INTMASK: + s->intr_mask =3D val; + xilinx_pcie_update_intr(s, 0, 0); + break; + case ROOTCFG_RPSCR: + s->rpscr &=3D ~ROOTCFG_RPSCR_BRIDGEEN; + s->rpscr |=3D val & ROOTCFG_RPSCR_BRIDGEEN; + memory_region_set_enabled(&s->mmio, val & ROOTCFG_RPSCR_BRIDGEEN); + + if (val & ROOTCFG_INTMASK_INTX) { + s->rpscr &=3D ~ROOTCFG_INTMASK_INTX; + } + break; + case ROOTCFG_RPIFR1: + case ROOTCFG_RPIFR2: + if (s->intr_fifo_w =3D=3D s->intr_fifo_r) { + /* FIFO empty */ + return; + } else { + s->intr_fifo_r =3D (s->intr_fifo_r + 1) % ARRAY_SIZE(s->intr_f= ifo); + } + break; + default: + pci_default_write_config(d, address, val, len); + break; + } +} + +static int xilinx_pcie_root_init(PCIDevice *dev) +{ + BusState *bus =3D qdev_get_parent_bus(DEVICE(dev)); + XilinxPCIEHost *s =3D XILINX_PCIE_HOST(bus->parent); + + pci_set_word(dev->config + PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_set_word(dev->config + PCI_MEMORY_BASE, s->mmio_base >> 16); + pci_set_word(dev->config + PCI_MEMORY_LIMIT, + ((s->mmio_base + s->mmio_size - 1) >> 16) & 0xfff0); + + pci_bridge_initfn(dev, TYPE_PCI_BUS); + + if (pcie_endpoint_cap_v1_init(dev, 0x80) < 0) { + hw_error("Failed to initialize PCIe capability"); + } + + return 0; +} + +static void xilinx_pcie_root_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k =3D PCI_DEVICE_CLASS(klass); + DeviceClass *dc =3D DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->desc =3D "Xilinx AXI-PCIe Host Bridge"; + k->vendor_id =3D PCI_VENDOR_ID_XILINX; + k->device_id =3D 0x7021; + k->revision =3D 0; + k->class_id =3D PCI_CLASS_BRIDGE_HOST; + k->is_express =3D true; + k->is_bridge =3D true; + k->init =3D xilinx_pcie_root_init; + k->exit =3D pci_bridge_exitfn; + dc->reset =3D pci_bridge_reset; + k->config_read =3D xilinx_pcie_root_config_read; + k->config_write =3D xilinx_pcie_root_config_write; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->cannot_instantiate_with_device_add_yet =3D true; +} + +static const TypeInfo xilinx_pcie_root_info =3D { + .name =3D TYPE_XILINX_PCIE_ROOT, + .parent =3D TYPE_PCI_BRIDGE, + .instance_size =3D sizeof(XilinxPCIERoot), + .class_init =3D xilinx_pcie_root_class_init, +}; + +static void xilinx_pcie_register(void) +{ + type_register_static(&xilinx_pcie_root_info); + type_register_static(&xilinx_pcie_host_info); +} + +type_init(xilinx_pcie_register) diff --git a/include/hw/pci-host/xilinx-pcie.h b/include/hw/pci-host/xilinx= -pcie.h new file mode 100644 index 0000000..bec66b2 --- /dev/null +++ b/include/hw/pci-host/xilinx-pcie.h @@ -0,0 +1,68 @@ +/* + * Xilinx PCIe host controller emulation. + * + * Copyright (c) 2016 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_XILINX_PCIE_H +#define HW_XILINX_PCIE_H + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" +#include "hw/pci/pcie_host.h" + +#define TYPE_XILINX_PCIE_HOST "xilinx-pcie-host" +#define XILINX_PCIE_HOST(obj) \ + OBJECT_CHECK(XilinxPCIEHost, (obj), TYPE_XILINX_PCIE_HOST) + +#define TYPE_XILINX_PCIE_ROOT "xilinx-pcie-root" +#define XILINX_PCIE_ROOT(obj) \ + OBJECT_CHECK(XilinxPCIERoot, (obj), TYPE_XILINX_PCIE_ROOT) + +typedef struct XilinxPCIERoot { + PCIBridge parent_obj; +} XilinxPCIERoot; + +typedef struct XilinxPCIEInt { + uint32_t fifo_reg1; + uint32_t fifo_reg2; +} XilinxPCIEInt; + +typedef struct XilinxPCIEHost { + PCIExpressHost parent_obj; + + char name[16]; + + uint32_t bus_nr; + uint64_t cfg_base, cfg_size; + uint64_t mmio_base, mmio_size; + bool link_up; + qemu_irq irq; + + MemoryRegion mmio, io; + + XilinxPCIERoot root; + + uint32_t intr; + uint32_t intr_mask; + XilinxPCIEInt intr_fifo[16]; + unsigned int intr_fifo_r, intr_fifo_w; + uint32_t rpscr; +} XilinxPCIEHost; + +#endif /* HW_XILINX_PCIE_H */ --=20 2.7.4 From nobody Fri Apr 26 12:28:44 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487623111051661.1435229579569; Mon, 20 Feb 2017 12:38:31 -0800 (PST) Received: from localhost ([::1]:40960 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfuj7-0005el-KB for importer@patchew.org; Mon, 20 Feb 2017 15:38:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35955) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucH-00086J-1z for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cfucE-0004cl-AQ for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:25 -0500 Received: from mailapp01.imgtec.com ([195.59.15.196]:33819) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cfucD-0004cK-UP for qemu-devel@nongnu.org; Mon, 20 Feb 2017 15:31:22 -0500 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id A8F05A54314DA for ; Mon, 20 Feb 2017 20:31:15 +0000 (GMT) Received: from localhost.localdomain (192.168.161.53) by hhmail02.hh.imgtec.org (10.100.10.21) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 20 Feb 2017 20:31:19 +0000 From: Yongbok Kim To: Date: Mon, 20 Feb 2017 20:31:02 +0000 Message-ID: <1487622662-62984-9-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> References: <1487622662-62984-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.161.53] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PULL 8/8] hw/mips: MIPS Boston board support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Paul Burton Introduce support for emulating the MIPS Boston development board. The Boston board is built around an FPGA & 3 PCIe controllers, one of which is connected to an Intel EG20T Platform Controller Hub. It is used during the development & debug of new CPUs and the software intended to run on them, and is essentially the successor to the older MIPS Malta board. This patch does not implement the EG20T, instead connecting an already supported ICH-9 AHCI controller. Whilst this isn't accurate it's enough for typical stock Boston software (eg. Linux kernels) to work with hard disks given that both the ICH-9 & EG20T implement the AHCI specification. Boston boards typically boot kernels in the FIT image format, and this patch will treat kernels provided to QEMU as such. When loading a kernel directly, the board code will generate minimal firmware much as the Malta board code does. This firmware will set up the CM, CPC & GIC register base addresses then set argument registers & jump to the kernel entry point. Alternatively, bootloader code may be loaded using the bios argument in which case no firmware will be generated & execution will proceed from the start of the boot code at the default MIPS boot exception vector (offset 0x1fc00000 into (c)kseg1). Currently real Boston boards are always used with FPGA bitfiles that include a Global Interrupt Controller (GIC), so the interrupt configuration is only defined for such cases. Therefore the board will only allow use of CPUs which implement the CPS components, including the GIC, and will otherwise exit with a message. Signed-off-by: Paul Burton Reviewed-by: Yongbok Kim [yongbok.kim@imgtec.com: isolated boston machine support for mips64el. updated for recent Chardev changes. ignore missing bios/kernel for qtest.] Signed-off-by: Yongbok Kim --- configure | 2 +- default-configs/mips64el-softmmu.mak | 2 + hw/mips/Makefile.objs | 1 + hw/mips/boston.c | 576 +++++++++++++++++++++++++++++++= ++++ 4 files changed, 580 insertions(+), 1 deletion(-) create mode 100644 hw/mips/boston.c diff --git a/configure b/configure index 4b68861..8e8f18d 100755 --- a/configure +++ b/configure @@ -3378,7 +3378,7 @@ fi fdt_required=3Dno for target in $target_list; do case $target in - aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu) + aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu|mips64e= l-softmmu) fdt_required=3Dyes ;; esac diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64e= l-softmmu.mak index 485e218..cc5f3b3 100644 --- a/default-configs/mips64el-softmmu.mak +++ b/default-configs/mips64el-softmmu.mak @@ -10,3 +10,5 @@ CONFIG_JAZZ=3Dy CONFIG_G364FB=3Dy CONFIG_JAZZ_LED=3Dy CONFIG_VT82C686=3Dy +CONFIG_MIPS_BOSTON=3Dy +CONFIG_PCI_XILINX=3Dy diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs index 9352a1c..48cd2ef 100644 --- a/hw/mips/Makefile.objs +++ b/hw/mips/Makefile.objs @@ -4,3 +4,4 @@ obj-$(CONFIG_JAZZ) +=3D mips_jazz.o obj-$(CONFIG_FULONG) +=3D mips_fulong2e.o obj-y +=3D gt64xxx_pci.o obj-$(CONFIG_MIPS_CPS) +=3D cps.o +obj-$(CONFIG_MIPS_BOSTON) +=3D boston.o diff --git a/hw/mips/boston.c b/hw/mips/boston.c new file mode 100644 index 0000000..560c8b4 --- /dev/null +++ b/hw/mips/boston.c @@ -0,0 +1,576 @@ +/* + * MIPS Boston development board emulation. + * + * Copyright (c) 2016 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" + +#include "exec/address-spaces.h" +#include "hw/boards.h" +#include "hw/char/serial.h" +#include "hw/hw.h" +#include "hw/ide/pci.h" +#include "hw/ide/ahci.h" +#include "hw/loader.h" +#include "hw/loader-fit.h" +#include "hw/mips/cps.h" +#include "hw/mips/cpudevs.h" +#include "hw/pci-host/xilinx-pcie.h" +#include "qapi/error.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "sysemu/char.h" +#include "sysemu/device_tree.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" + +#include + +#define TYPE_MIPS_BOSTON "mips-boston" +#define BOSTON(obj) OBJECT_CHECK(BostonState, (obj), TYPE_MIPS_BOSTON) + +typedef struct { + SysBusDevice parent_obj; + + MachineState *mach; + MIPSCPSState *cps; + SerialState *uart; + + CharBackend lcd_display; + char lcd_content[8]; + bool lcd_inited; + + hwaddr kernel_entry; + hwaddr fdt_base; +} BostonState; + +enum boston_plat_reg { + PLAT_FPGA_BUILD =3D 0x00, + PLAT_CORE_CL =3D 0x04, + PLAT_WRAPPER_CL =3D 0x08, + PLAT_SYSCLK_STATUS =3D 0x0c, + PLAT_SOFTRST_CTL =3D 0x10, +#define PLAT_SOFTRST_CTL_SYSRESET (1 << 4) + PLAT_DDR3_STATUS =3D 0x14, +#define PLAT_DDR3_STATUS_LOCKED (1 << 0) +#define PLAT_DDR3_STATUS_CALIBRATED (1 << 2) + PLAT_PCIE_STATUS =3D 0x18, +#define PLAT_PCIE_STATUS_PCIE0_LOCKED (1 << 0) +#define PLAT_PCIE_STATUS_PCIE1_LOCKED (1 << 8) +#define PLAT_PCIE_STATUS_PCIE2_LOCKED (1 << 16) + PLAT_FLASH_CTL =3D 0x1c, + PLAT_SPARE0 =3D 0x20, + PLAT_SPARE1 =3D 0x24, + PLAT_SPARE2 =3D 0x28, + PLAT_SPARE3 =3D 0x2c, + PLAT_MMCM_DIV =3D 0x30, +#define PLAT_MMCM_DIV_CLK0DIV_SHIFT 0 +#define PLAT_MMCM_DIV_INPUT_SHIFT 8 +#define PLAT_MMCM_DIV_MUL_SHIFT 16 +#define PLAT_MMCM_DIV_CLK1DIV_SHIFT 24 + PLAT_BUILD_CFG =3D 0x34, +#define PLAT_BUILD_CFG_IOCU_EN (1 << 0) +#define PLAT_BUILD_CFG_PCIE0_EN (1 << 1) +#define PLAT_BUILD_CFG_PCIE1_EN (1 << 2) +#define PLAT_BUILD_CFG_PCIE2_EN (1 << 3) + PLAT_DDR_CFG =3D 0x38, +#define PLAT_DDR_CFG_SIZE (0xf << 0) +#define PLAT_DDR_CFG_MHZ (0xfff << 4) + PLAT_NOC_PCIE0_ADDR =3D 0x3c, + PLAT_NOC_PCIE1_ADDR =3D 0x40, + PLAT_NOC_PCIE2_ADDR =3D 0x44, + PLAT_SYS_CTL =3D 0x48, +}; + +static void boston_lcd_event(void *opaque, int event) +{ + BostonState *s =3D opaque; + if (event =3D=3D CHR_EVENT_OPENED && !s->lcd_inited) { + qemu_chr_fe_printf(&s->lcd_display, " "); + s->lcd_inited =3D true; + } +} + +static uint64_t boston_lcd_read(void *opaque, hwaddr addr, + unsigned size) +{ + BostonState *s =3D opaque; + uint64_t val =3D 0; + + switch (size) { + case 8: + val |=3D (uint64_t)s->lcd_content[(addr + 7) & 0x7] << 56; + val |=3D (uint64_t)s->lcd_content[(addr + 6) & 0x7] << 48; + val |=3D (uint64_t)s->lcd_content[(addr + 5) & 0x7] << 40; + val |=3D (uint64_t)s->lcd_content[(addr + 4) & 0x7] << 32; + /* fall through */ + case 4: + val |=3D (uint64_t)s->lcd_content[(addr + 3) & 0x7] << 24; + val |=3D (uint64_t)s->lcd_content[(addr + 2) & 0x7] << 16; + /* fall through */ + case 2: + val |=3D (uint64_t)s->lcd_content[(addr + 1) & 0x7] << 8; + /* fall through */ + case 1: + val |=3D (uint64_t)s->lcd_content[(addr + 0) & 0x7]; + break; + } + + return val; +} + +static void boston_lcd_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + BostonState *s =3D opaque; + + switch (size) { + case 8: + s->lcd_content[(addr + 7) & 0x7] =3D val >> 56; + s->lcd_content[(addr + 6) & 0x7] =3D val >> 48; + s->lcd_content[(addr + 5) & 0x7] =3D val >> 40; + s->lcd_content[(addr + 4) & 0x7] =3D val >> 32; + /* fall through */ + case 4: + s->lcd_content[(addr + 3) & 0x7] =3D val >> 24; + s->lcd_content[(addr + 2) & 0x7] =3D val >> 16; + /* fall through */ + case 2: + s->lcd_content[(addr + 1) & 0x7] =3D val >> 8; + /* fall through */ + case 1: + s->lcd_content[(addr + 0) & 0x7] =3D val; + break; + } + + qemu_chr_fe_printf(&s->lcd_display, + "\r%-8.8s", s->lcd_content); +} + +static const MemoryRegionOps boston_lcd_ops =3D { + .read =3D boston_lcd_read, + .write =3D boston_lcd_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static uint64_t boston_platreg_read(void *opaque, hwaddr addr, + unsigned size) +{ + BostonState *s =3D opaque; + uint32_t gic_freq, val; + + if (size !=3D 4) { + qemu_log_mask(LOG_UNIMP, "%uB platform register read", size); + return 0; + } + + switch (addr & 0xffff) { + case PLAT_FPGA_BUILD: + case PLAT_CORE_CL: + case PLAT_WRAPPER_CL: + return 0; + case PLAT_DDR3_STATUS: + return PLAT_DDR3_STATUS_LOCKED | PLAT_DDR3_STATUS_CALIBRATED; + case PLAT_MMCM_DIV: + gic_freq =3D mips_gictimer_get_freq(s->cps->gic.gic_timer) / 10000= 00; + val =3D gic_freq << PLAT_MMCM_DIV_INPUT_SHIFT; + val |=3D 1 << PLAT_MMCM_DIV_MUL_SHIFT; + val |=3D 1 << PLAT_MMCM_DIV_CLK0DIV_SHIFT; + val |=3D 1 << PLAT_MMCM_DIV_CLK1DIV_SHIFT; + return val; + case PLAT_BUILD_CFG: + val =3D PLAT_BUILD_CFG_PCIE0_EN; + val |=3D PLAT_BUILD_CFG_PCIE1_EN; + val |=3D PLAT_BUILD_CFG_PCIE2_EN; + return val; + case PLAT_DDR_CFG: + val =3D s->mach->ram_size / G_BYTE; + assert(!(val & ~PLAT_DDR_CFG_SIZE)); + val |=3D PLAT_DDR_CFG_MHZ; + return val; + default: + qemu_log_mask(LOG_UNIMP, "Read platform register 0x%" HWADDR_PRIx, + addr & 0xffff); + return 0; + } +} + +static void boston_platreg_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + if (size !=3D 4) { + qemu_log_mask(LOG_UNIMP, "%uB platform register write", size); + return; + } + + switch (addr & 0xffff) { + case PLAT_FPGA_BUILD: + case PLAT_CORE_CL: + case PLAT_WRAPPER_CL: + case PLAT_DDR3_STATUS: + case PLAT_PCIE_STATUS: + case PLAT_MMCM_DIV: + case PLAT_BUILD_CFG: + case PLAT_DDR_CFG: + /* read only */ + break; + case PLAT_SOFTRST_CTL: + if (val & PLAT_SOFTRST_CTL_SYSRESET) { + qemu_system_reset_request(); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "Write platform register 0x%" HWADDR_PRIx + " =3D 0x%" PRIx64, addr & 0xffff, val); + break; + } +} + +static const MemoryRegionOps boston_platreg_ops =3D { + .read =3D boston_platreg_read, + .write =3D boston_platreg_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static void boston_flash_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ +} + +static const MemoryRegionOps boston_flash_ops =3D { + .write =3D boston_flash_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static const TypeInfo boston_device =3D { + .name =3D TYPE_MIPS_BOSTON, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BostonState), +}; + +static void boston_register_types(void) +{ + type_register_static(&boston_device); +} +type_init(boston_register_types) + +static void gen_firmware(uint32_t *p, hwaddr kernel_entry, hwaddr fdt_addr, + bool is_64b) +{ + const uint32_t cm_base =3D 0x16100000; + const uint32_t gic_base =3D 0x16120000; + const uint32_t cpc_base =3D 0x16200000; + + /* Move CM GCRs */ + if (is_64b) { + stl_p(p++, 0x40287803); /* dmfc0 $8, CMGCRBase */ + stl_p(p++, 0x00084138); /* dsll $8, $8, 4 */ + } else { + stl_p(p++, 0x40087803); /* mfc0 $8, CMGCRBase */ + stl_p(p++, 0x00084100); /* sll $8, $8, 4 */ + } + stl_p(p++, 0x3c09a000); /* lui $9, 0xa000 */ + stl_p(p++, 0x01094025); /* or $8, $9 */ + stl_p(p++, 0x3c0a0000 | (cm_base >> 16)); /* lui $10, cm_base >> 16= */ + if (is_64b) { + stl_p(p++, 0xfd0a0008); /* sd $10, 0x8($8) */ + } else { + stl_p(p++, 0xad0a0008); /* sw $10, 0x8($8) */ + } + stl_p(p++, 0x012a4025); /* or $8, $10 */ + + /* Move & enable GIC GCRs */ + stl_p(p++, 0x3c090000 | (gic_base >> 16)); /* lui $9, gic_base >> 16= */ + stl_p(p++, 0x35290001); /* ori $9, 0x1 */ + if (is_64b) { + stl_p(p++, 0xfd090080); /* sd $9, 0x80($8) */ + } else { + stl_p(p++, 0xad090080); /* sw $9, 0x80($8) */ + } + + /* Move & enable CPC GCRs */ + stl_p(p++, 0x3c090000 | (cpc_base >> 16)); /* lui $9, cpc_base >> 16= */ + stl_p(p++, 0x35290001); /* ori $9, 0x1 */ + if (is_64b) { + stl_p(p++, 0xfd090088); /* sd $9, 0x88($8) */ + } else { + stl_p(p++, 0xad090088); /* sw $9, 0x88($8) */ + } + + /* + * Setup argument registers to follow the UHI boot protocol: + * + * a0/$4 =3D -2 + * a1/$5 =3D virtual address of FDT + * a2/$6 =3D 0 + * a3/$7 =3D 0 + */ + stl_p(p++, 0x2404fffe); /* li $4, -2 */ + /* lui $5, hi(fdt_addr) */ + stl_p(p++, 0x3c050000 | ((fdt_addr >> 16) & 0xffff)); + if (fdt_addr & 0xffff) { /* ori $5, lo(fdt_addr) */ + stl_p(p++, 0x34a50000 | (fdt_addr & 0xffff)); + } + stl_p(p++, 0x34060000); /* li $6, 0 */ + stl_p(p++, 0x34070000); /* li $7, 0 */ + + /* Load kernel entry address & jump to it */ + /* lui $25, hi(kernel_ent= ry) */ + stl_p(p++, 0x3c190000 | ((kernel_entry >> 16) & 0xffff)); + /* ori $25, lo(kernel_ent= ry) */ + stl_p(p++, 0x37390000 | (kernel_entry & 0xffff)); + stl_p(p++, 0x03200009); /* jr $25 */ +} + +static const void *boston_fdt_filter(void *opaque, const void *fdt_orig, + const void *match_data, hwaddr *load_= addr) +{ + BostonState *s =3D BOSTON(opaque); + MachineState *machine =3D s->mach; + const char *cmdline; + int err; + void *fdt; + size_t fdt_sz, ram_low_sz, ram_high_sz; + + fdt_sz =3D fdt_totalsize(fdt_orig) * 2; + fdt =3D g_malloc0(fdt_sz); + + err =3D fdt_open_into(fdt_orig, fdt, fdt_sz); + if (err) { + fprintf(stderr, "unable to open FDT\n"); + return NULL; + } + + cmdline =3D (machine->kernel_cmdline && machine->kernel_cmdline[0]) + ? machine->kernel_cmdline : " "; + err =3D qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); + if (err < 0) { + fprintf(stderr, "couldn't set /chosen/bootargs\n"); + return NULL; + } + + ram_low_sz =3D MIN(256 * M_BYTE, machine->ram_size); + ram_high_sz =3D machine->ram_size - ram_low_sz; + qemu_fdt_setprop_sized_cells(fdt, "/memory@0", "reg", + 1, 0x00000000, 1, ram_low_sz, + 1, 0x90000000, 1, ram_high_sz); + + fdt =3D g_realloc(fdt, fdt_totalsize(fdt)); + qemu_fdt_dumpdtb(fdt, fdt_sz); + + s->fdt_base =3D *load_addr; + + return fdt; +} + +static const void *boston_kernel_filter(void *opaque, const void *kernel, + hwaddr *load_addr, hwaddr *entry_a= ddr) +{ + BostonState *s =3D BOSTON(opaque); + + s->kernel_entry =3D *entry_addr; + + return kernel; +} + +static const struct fit_loader_match boston_matches[] =3D { + { "img,boston" }, + { NULL }, +}; + +static const struct fit_loader boston_fit_loader =3D { + .matches =3D boston_matches, + .addr_to_phys =3D cpu_mips_kseg0_to_phys, + .fdt_filter =3D boston_fdt_filter, + .kernel_filter =3D boston_kernel_filter, +}; + +static inline XilinxPCIEHost * +xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr, + hwaddr cfg_base, uint64_t cfg_size, + hwaddr mmio_base, uint64_t mmio_size, + qemu_irq irq, bool link_up) +{ + DeviceState *dev; + MemoryRegion *cfg, *mmio; + + dev =3D qdev_create(NULL, TYPE_XILINX_PCIE_HOST); + + qdev_prop_set_uint32(dev, "bus_nr", bus_nr); + qdev_prop_set_uint64(dev, "cfg_base", cfg_base); + qdev_prop_set_uint64(dev, "cfg_size", cfg_size); + qdev_prop_set_uint64(dev, "mmio_base", mmio_base); + qdev_prop_set_uint64(dev, "mmio_size", mmio_size); + qdev_prop_set_bit(dev, "link_up", link_up); + + qdev_init_nofail(dev); + + cfg =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion_overlap(sys_mem, cfg_base, cfg, 0); + + mmio =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_add_subregion_overlap(sys_mem, 0, mmio, 0); + + qdev_connect_gpio_out_named(dev, "interrupt_out", 0, irq); + + return XILINX_PCIE_HOST(dev); +} + +static void boston_mach_init(MachineState *machine) +{ + DeviceState *dev; + BostonState *s; + Error *err =3D NULL; + const char *cpu_model; + MemoryRegion *flash, *ddr, *ddr_low_alias, *lcd, *platreg; + MemoryRegion *sys_mem =3D get_system_memory(); + XilinxPCIEHost *pcie2; + PCIDevice *ahci; + DriveInfo *hd[6]; + Chardev *chr; + int fw_size, fit_err; + bool is_64b; + + if ((machine->ram_size % G_BYTE) || + (machine->ram_size > (2 * G_BYTE))) { + error_report("Memory size must be 1GB or 2GB"); + exit(1); + } + + cpu_model =3D machine->cpu_model ?: "I6400"; + + dev =3D qdev_create(NULL, TYPE_MIPS_BOSTON); + qdev_init_nofail(dev); + + s =3D BOSTON(dev); + s->mach =3D machine; + s->cps =3D g_new0(MIPSCPSState, 1); + + if (!cpu_supports_cps_smp(cpu_model)) { + error_report("Boston requires CPUs which support CPS"); + exit(1); + } + + is_64b =3D cpu_supports_isa(cpu_model, ISA_MIPS64); + + object_initialize(s->cps, sizeof(MIPSCPSState), TYPE_MIPS_CPS); + qdev_set_parent_bus(DEVICE(s->cps), sysbus_get_default()); + + object_property_set_str(OBJECT(s->cps), cpu_model, "cpu-model", &err); + object_property_set_int(OBJECT(s->cps), smp_cpus, "num-vp", &err); + object_property_set_bool(OBJECT(s->cps), true, "realized", &err); + + if (err !=3D NULL) { + error_report("%s", error_get_pretty(err)); + exit(1); + } + + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1); + + flash =3D g_new(MemoryRegion, 1); + memory_region_init_rom_device(flash, NULL, &boston_flash_ops, s, + "boston.flash", 128 * M_BYTE, &err); + memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0); + + ddr =3D g_new(MemoryRegion, 1); + memory_region_allocate_system_memory(ddr, NULL, "boston.ddr", + machine->ram_size); + memory_region_add_subregion_overlap(sys_mem, 0x80000000, ddr, 0); + + ddr_low_alias =3D g_new(MemoryRegion, 1); + memory_region_init_alias(ddr_low_alias, NULL, "boston_low.ddr", + ddr, 0, MIN(machine->ram_size, (256 * M_BYTE)= )); + memory_region_add_subregion_overlap(sys_mem, 0, ddr_low_alias, 0); + + xilinx_pcie_init(sys_mem, 0, + 0x10000000, 32 * M_BYTE, + 0x40000000, 1 * G_BYTE, + get_cps_irq(s->cps, 2), false); + + xilinx_pcie_init(sys_mem, 1, + 0x12000000, 32 * M_BYTE, + 0x20000000, 512 * M_BYTE, + get_cps_irq(s->cps, 1), false); + + pcie2 =3D xilinx_pcie_init(sys_mem, 2, + 0x14000000, 32 * M_BYTE, + 0x16000000, 1 * M_BYTE, + get_cps_irq(s->cps, 0), true); + + platreg =3D g_new(MemoryRegion, 1); + memory_region_init_io(platreg, NULL, &boston_platreg_ops, s, + "boston-platregs", 0x1000); + memory_region_add_subregion_overlap(sys_mem, 0x17ffd000, platreg, 0); + + if (!serial_hds[0]) { + serial_hds[0] =3D qemu_chr_new("serial0", "null"); + } + + s->uart =3D serial_mm_init(sys_mem, 0x17ffe000, 2, + get_cps_irq(s->cps, 3), 10000000, + serial_hds[0], DEVICE_NATIVE_ENDIAN); + + lcd =3D g_new(MemoryRegion, 1); + memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8= ); + memory_region_add_subregion_overlap(sys_mem, 0x17fff000, lcd, 0); + + chr =3D qemu_chr_new("lcd", "vc:320x240"); + qemu_chr_fe_init(&s->lcd_display, chr, NULL); + qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL, + boston_lcd_event, s, NULL, true); + + ahci =3D pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->se= c_bus, + PCI_DEVFN(0, 0), + true, TYPE_ICH9_AHCI); + g_assert(ARRAY_SIZE(hd) =3D=3D ICH_AHCI(ahci)->ahci.ports); + ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports); + ahci_ide_create_devs(ahci, hd); + + if (machine->firmware) { + fw_size =3D load_image_targphys(machine->firmware, + 0x1fc00000, 4 * M_BYTE); + if (fw_size =3D=3D -1) { + error_printf("unable to load firmware image '%s'\n", + machine->firmware); + exit(1); + } + } else if (machine->kernel_filename) { + fit_err =3D load_fit(&boston_fit_loader, machine->kernel_filename,= s); + if (fit_err) { + error_printf("unable to load FIT image\n"); + exit(1); + } + + gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000, + s->kernel_entry, s->fdt_base, is_64b); + } else if (!qtest_enabled()) { + error_printf("Please provide either a -kernel or -bios argument\n"= ); + exit(1); + } +} + +static void boston_mach_class_init(MachineClass *mc) +{ + mc->desc =3D "MIPS Boston"; + mc->init =3D boston_mach_init; + mc->default_ram_size =3D 2 * G_BYTE; + mc->max_cpus =3D 16; +} + +DEFINE_MACHINE("boston", boston_mach_class_init) --=20 2.7.4