From patchwork Thu Jun 9 09:46:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Alrae X-Patchwork-Id: 632702 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rQLDj2SYlz9sDX for ; Thu, 9 Jun 2016 19:51:49 +1000 (AEST) Received: from localhost ([::1]:33447 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAwct-0003DI-5j for incoming@patchwork.ozlabs.org; Thu, 09 Jun 2016 05:51:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50688) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAwZ2-0000Vk-AS for qemu-devel@nongnu.org; Thu, 09 Jun 2016 05:47:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bAwYx-0001As-8W for qemu-devel@nongnu.org; Thu, 09 Jun 2016 05:47:47 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:64798) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAwYw-0001A8-V1 for qemu-devel@nongnu.org; Thu, 09 Jun 2016 05:47:43 -0400 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 5698644C72F; Thu, 9 Jun 2016 10:47:38 +0100 (IST) Received: from hhmipssw204.hh.imgtec.org (10.100.21.121) by hhmail02.hh.imgtec.org (10.100.10.20) with Microsoft SMTP Server (TLS) id 14.3.294.0; Thu, 9 Jun 2016 10:47:40 +0100 From: Leon Alrae To: Date: Thu, 9 Jun 2016 10:46:52 +0100 Message-ID: <1465465612-4543-4-git-send-email-leon.alrae@imgtec.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1465465612-4543-1-git-send-email-leon.alrae@imgtec.com> References: <1465465612-4543-1-git-send-email-leon.alrae@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [10.100.21.121] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Subject: [Qemu-devel] [PATCH 3/3] hw/mips_cmgcr: implement RESET_BASE register in CM GCR 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: , Cc: aurelien@aurel32.net Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Implement RESET_BASE register which is local to each VP and a write to it changes VP's reset exception base. Also, add OTHER register to allow a software running on one VP to access other VP's local registers. Guest can use this mechanism to specify custom address from which a VP will start execution. Signed-off-by: Leon Alrae --- hw/misc/mips_cmgcr.c | 54 +++++++++++++++++++++++++++++++++++++++++++- include/hw/misc/mips_cmgcr.h | 18 +++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c index e6cf17d..b3ba166 100644 --- a/hw/misc/mips_cmgcr.c +++ b/hw/misc/mips_cmgcr.c @@ -59,6 +59,8 @@ static inline void update_gic_base(MIPSGCRState *gcr, uint64_t val) static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) { MIPSGCRState *gcr = (MIPSGCRState *) opaque; + MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index]; + MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other]; switch (addr) { /* Global Control Block Register */ @@ -85,8 +87,14 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS: /* Set PVP to # of VPs - 1 */ return gcr->num_vps - 1; + case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS: + return current_vps->reset_base; + case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS: + return other_vps->reset_base; case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS: - return 0; + return current_vps->other; + case MIPS_COCB_OFS + GCR_CL_OTHER_OFS: + return other_vps->other; default: qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx "\n", size, addr); @@ -95,10 +103,18 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size) return 0; } +static inline target_ulong get_exception_base(MIPSGCRVPState *vps) +{ + /* TODO: BEV_BASE and SELECT_BEV */ + return (int32_t)(vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK); +} + /* Write GCR registers */ static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { MIPSGCRState *gcr = (MIPSGCRState *)opaque; + MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index]; + MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other]; switch (addr) { case GCR_GIC_BASE_OFS: @@ -107,6 +123,26 @@ static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) case GCR_CPC_BASE_OFS: update_cpc_base(gcr, data); break; + case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS: + current_vps->reset_base = data & GCR_CL_RESET_BASE_MSK; + cpu_set_exception_base(current_cpu->cpu_index, + get_exception_base(current_vps)); + break; + case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS: + other_vps->reset_base = data & GCR_CL_RESET_BASE_MSK; + cpu_set_exception_base(current_vps->other, + get_exception_base(other_vps)); + break; + case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS: + if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) { + current_vps->other = data & GCR_CL_OTHER_MSK; + } + break; + case MIPS_COCB_OFS + GCR_CL_OTHER_OFS: + if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) { + other_vps->other = data & GCR_CL_OTHER_MSK; + } + break; default: qemu_log_mask(LOG_UNIMP, "Write %d bytes at GCR offset 0x%" HWADDR_PRIx " 0x%" PRIx64 "\n", size, addr, data); @@ -148,9 +184,16 @@ static void mips_gcr_init(Object *obj) static void mips_gcr_reset(DeviceState *dev) { MIPSGCRState *s = MIPS_GCR(dev); + int i; update_gic_base(s, 0); update_cpc_base(s, 0); + + for (i = 0; i < s->num_vps; i++) { + s->vps[i].other = 0; + s->vps[i].reset_base = 0xBFC00000 & GCR_CL_RESET_BASE_MSK; + cpu_set_exception_base(i, get_exception_base(&s->vps[i])); + } } static const VMStateDescription vmstate_mips_gcr = { @@ -170,12 +213,21 @@ static Property mips_gcr_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void mips_gcr_realize(DeviceState *dev, Error **errp) +{ + MIPSGCRState *s = MIPS_GCR(dev); + + /* Create local set of registers for each VP */ + s->vps = g_new(MIPSGCRVPState, s->num_vps); +} + static void mips_gcr_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->props = mips_gcr_properties; dc->vmsd = &vmstate_mips_gcr; dc->reset = mips_gcr_reset; + dc->realize = mips_gcr_realize; } static const TypeInfo mips_gcr_info = { diff --git a/include/hw/misc/mips_cmgcr.h b/include/hw/misc/mips_cmgcr.h index 5b90e94..690e1d6 100644 --- a/include/hw/misc/mips_cmgcr.h +++ b/include/hw/misc/mips_cmgcr.h @@ -35,6 +35,7 @@ /* Core Local and Core Other Block Register Map */ #define GCR_CL_CONFIG_OFS 0x0010 #define GCR_CL_OTHER_OFS 0x0018 +#define GCR_CL_RESETBASE_OFS 0x0020 /* GCR_L2_CONFIG register fields */ #define GCR_L2_CONFIG_BYPASS_SHF 20 @@ -50,6 +51,20 @@ #define GCR_CPC_BASE_CPCBASE_MSK 0xFFFFFFFF8000ULL #define GCR_CPC_BASE_MSK (GCR_CPC_BASE_CPCEN_MSK | GCR_CPC_BASE_CPCBASE_MSK) +/* GCR_CL_OTHER_OFS register fields */ +#define GCR_CL_OTHER_VPOTHER_MSK 0x7 +#define GCR_CL_OTHER_MSK GCR_CL_OTHER_VPOTHER_MSK + +/* GCR_CL_RESETBASE_OFS register fields */ +#define GCR_CL_RESET_BASE_RESETBASE_MSK 0xFFFFF000U +#define GCR_CL_RESET_BASE_MSK GCR_CL_RESET_BASE_RESETBASE_MSK + +typedef struct MIPSGCRVPState MIPSGCRVPState; +struct MIPSGCRVPState { + uint32_t other; + uint64_t reset_base; +}; + typedef struct MIPSGCRState MIPSGCRState; struct MIPSGCRState { SysBusDevice parent_obj; @@ -63,6 +78,9 @@ struct MIPSGCRState { uint64_t cpc_base; uint64_t gic_base; + + /* VP Local/Other Registers */ + MIPSGCRVPState *vps; }; #endif /* _MIPS_GCR_H */