From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437149653290.4822043713001; Thu, 3 Sep 2026 05:05:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CB-0002mV-FO; Thu, 03 Sep 2026 08:05:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C6-0002hv-RN for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:26 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C4-0005JF-BN for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:26 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 6bcce265 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:19 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 52b41ed0; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=zwjwzjd Xtt9PiOAneA1y9YeCGxpgTkFWazULqy8x1p32jH0s+1NhvOiGKiWqe8oY7fDtU89mE1FMM /o+jFujv7aTjtYLrRkkwdcuqFNLtPIyrVegHGvhzPZUsxS2yFhTdyZB6jPdK+RtNb3n8Ii 8/FGA0ocKv2kxM06JEJDRP2t59q5Eo4+1BITRqnShgiVbZUC70zVE1hGQrJvO+wEkHktWV eyWsTQwKPgyGClIjmn0zFc45P1DhUw1Kjz2dgRCVcpP77uhp5SV1vFW7W8QLGIhNd8FT4t v5uTfClUvFoK9YcIYJ/sy1vX9y/YeaRCnU47NOoS9qfE8Nns1tJ0whg== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=a b02a7Q52ZRcUUJ2Y8RxNP89U/nnaeELs7WTNEa33PE=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=WL6c9uCnoIWJuwODxm2otigupn01rfUpk0uybzERgew4ur9/7lSaG0UD/X9/6BuPKRFK zIpEX88FCuhbDbMNzlVOppUiQcAsPtaLEfb1TkHUgwps8CaZbquxRKwi1+uBLSVYJkMvoS ZyDOnSCn2FVtXZ2bU0F4rMjLmS/tssVT3vnwlKWXTqhszZxs+ZYkLUIjpKJYkzGZJpo9m+ g4ARlWlZVJjj410XB0Gv98sU7YDuHdN3oJsHo3T2Kyj4dHnBzMcajZoj30pBkjJRykgFht XXsj5JtoTvWT3ui/dbaLx0KuFGq/es4EszFuaZFx/7KSD4AYBMXLFufiIpg4qaAQ== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=BGd2VqgQ; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=T2zTYOET; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=ab02a7Q5 2ZRcUUJ2Y8RxNP89U/nnaeELs7WTNEa33PE=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=BGd2VqgQTMqUsX25BDdfFlcOYmtwGqDKztD sJ4LyRXJ4ix1+Mj4NjEdHaTmnv/nBTw0RdELDppcVnEGGWC1cu/n5K7i2lm6B4U/Ur+RBI TaSZFLnsAGM0RcRmicj6IvJvg4dcZsH7a3lIXBxY3thA87waI3qcfXTEP8PUi75pyDpMED ttUdDzuT2UwikGPFmxBK8E8ktMk6XfkHOjHIPO0CRTZuDQCR6ag8tah4Vqgw93szF/oVmL 0wg7Ciuon5ZeGrRuuHXMfZNL69phne9dhmXmVrxiL4jCg20cCxvYSVNT+kpPOrfNpdpjVi qMViKPcuCot3ilKC9QgoemzpreQ== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=ab02a7Q52ZRcUUJ2Y8RxNP89U/nnaeELs7WTNEa33PE=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=T2zTYOETMqmCThC+mi BgUpJaOBK690dJv2Ddvy7cbRlEmwweAqjNo8bLIrfThW+N2J9ubGofyFJXGZO4xYBODg== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 01/25] target/mips: make CP0 interrupt state atomic Date: Thu, 3 Sep 2026 14:01:49 +0200 Message-ID: <20260903120510.34876-2-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437152510158500 Content-Type: text/plain; charset="utf-8" MTTCG lets interrupt inputs and timer callbacks update CP0_Cause, CP0_Status, and CP0_Count while a vCPU checks interrupt state. Use qatomic accessors for CP0 fields that participate in interrupt and timer decisions, and kick remote CPUs explicitly after raising a hard interrupt; MIPS interrupt line updates no longer depend on taking the BQL. --- hw/mips/mips_int.c | 17 +++++++------ target/mips/internal.h | 13 ++++++---- target/mips/system/cp0.c | 27 +++++++++++++-------- target/mips/system/cp0_timer.c | 32 ++++++++++++++----------- target/mips/tcg/system/special_helper.c | 17 +++++++------ target/mips/tcg/system/tlb_helper.c | 21 +++++++++------- 6 files changed, 75 insertions(+), 52 deletions(-) diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index 26e7dd6d5f..537394c8fd 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -21,30 +21,33 @@ */ =20 #include "qemu/osdep.h" -#include "qemu/main-loop.h" #include "hw/core/irq.h" #include "target/mips/cpu.h" +#include "target/mips/internal.h" =20 static void cpu_mips_irq_request(void *opaque, int irq, int level) { MIPSCPU *cpu =3D opaque; CPUMIPSState *env =3D &cpu->env; CPUState *cs =3D CPU(cpu); + int32_t irq_bit; =20 if (irq < 0 || irq > 7) { return; } =20 - BQL_LOCK_GUARD(); - + irq_bit =3D 1 << (irq + CP0Ca_IP); if (level) { - env->CP0_Cause |=3D 1 << (irq + CP0Ca_IP); + qatomic_or(&env->CP0_Cause, irq_bit); } else { - env->CP0_Cause &=3D ~(1 << (irq + CP0Ca_IP)); + qatomic_and(&env->CP0_Cause, ~irq_bit); } =20 - if (env->CP0_Cause & CP0Ca_IP_mask) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); + if (qatomic_read(&env->CP0_Cause) & CP0Ca_IP_mask) { + cpu_set_interrupt(cs, CPU_INTERRUPT_HARD); + if (!qemu_cpu_is_self(cs)) { + qemu_cpu_kick(cs); + } } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); } diff --git a/target/mips/internal.h b/target/mips/internal.h index c5c286872e..cd06d84140 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -8,6 +8,7 @@ #ifndef MIPS_INTERNAL_H #define MIPS_INTERNAL_H =20 +#include "qemu/atomic.h" #include "exec/memattrs.h" #ifdef CONFIG_TCG #include "tcg/tcg-internal.h" @@ -167,9 +168,11 @@ extern const VMStateDescription vmstate_mips_cpu; =20 static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env) { - return (env->CP0_Status & (1 << CP0St_IE)) && - !(env->CP0_Status & (1 << CP0St_EXL)) && - !(env->CP0_Status & (1 << CP0St_ERL)) && + int32_t status =3D qatomic_read(&env->CP0_Status); + + return (status & (1 << CP0St_IE)) && + !(status & (1 << CP0St_EXL)) && + !(status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM) && /* * Note that the TCStatus IXMT field is initialized to zero, @@ -186,8 +189,8 @@ static inline bool cpu_mips_hw_interrupts_pending(CPUMI= PSState *env) int32_t status; bool r; =20 - pending =3D env->CP0_Cause & CP0Ca_IP_mask; - status =3D env->CP0_Status & CP0Ca_IP_mask; + pending =3D qatomic_read(&env->CP0_Cause) & CP0Ca_IP_mask; + status =3D qatomic_read(&env->CP0_Status) & CP0Ca_IP_mask; =20 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { /* diff --git a/target/mips/system/cp0.c b/target/mips/system/cp0.c index ff7d3db00c..6f222ad586 100644 --- a/target/mips/system/cp0.c +++ b/target/mips/system/cp0.c @@ -22,6 +22,7 @@ #include "cpu.h" #include "internal.h" #include "exec/cputlb.h" +#include "qemu/atomic.h" =20 /* Called for updates to CP0_Status. */ void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) @@ -61,7 +62,8 @@ void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu,= int tc) void cpu_mips_store_status(CPUMIPSState *env, target_ulong val) { uint32_t mask =3D env->CP0_Status_rw_bitmask; - target_ulong old =3D env->CP0_Status; + target_ulong old; + target_ulong status; =20 if (env->insn_flags & ISA_MIPS_R6) { bool has_supervisor =3D extract32(mask, CP0St_KSU, 2) =3D=3D 0x3; @@ -77,9 +79,11 @@ void cpu_mips_store_status(CPUMIPSState *env, target_ulo= ng val) mask &=3D ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val); } =20 - env->CP0_Status =3D (old & ~mask) | (val & mask); + old =3D qatomic_read(&env->CP0_Status); + status =3D (old & ~mask) | (val & mask); + qatomic_set(&env->CP0_Status, status); #if defined(TARGET_MIPS64) - if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) { + if ((status ^ old) & (old & (7 << CP0St_UX))) { /* Access to at least one of the 64-bit segments has been disabled= */ tlb_flush(env_cpu(env)); } @@ -93,8 +97,9 @@ void cpu_mips_store_status(CPUMIPSState *env, target_ulon= g val) =20 void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val) { - uint32_t mask =3D 0x00C00300; - uint32_t old =3D env->CP0_Cause; + int32_t mask =3D 0x00C00300; + int32_t old; + int32_t cause; int i; =20 if (env->insn_flags & ISA_MIPS_R2) { @@ -104,10 +109,12 @@ void cpu_mips_store_cause(CPUMIPSState *env, target_u= long val) mask &=3D ~((1 << CP0Ca_WP) & val); } =20 - env->CP0_Cause =3D (env->CP0_Cause & ~mask) | (val & mask); + old =3D qatomic_fetch_and(&env->CP0_Cause, ~mask); + qatomic_or(&env->CP0_Cause, (int32_t)(val & mask)); + cause =3D qatomic_read(&env->CP0_Cause); =20 - if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) { - if (env->CP0_Cause & (1 << CP0Ca_DC)) { + if ((old ^ cause) & (1 << CP0Ca_DC)) { + if (cause & (1 << CP0Ca_DC)) { cpu_mips_stop_count(env); } else { cpu_mips_start_count(env); @@ -116,8 +123,8 @@ void cpu_mips_store_cause(CPUMIPSState *env, target_ulo= ng val) =20 /* Set/reset software interrupts */ for (i =3D 0 ; i < 2 ; i++) { - if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) { - cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i= ))); + if ((old ^ cause) & (1 << (CP0Ca_IP + i))) { + cpu_mips_soft_irq(env, i, cause & (1 << (CP0Ca_IP + i))); } } } diff --git a/target/mips/system/cp0_timer.c b/target/mips/system/cp0_timer.c index 6aed5d3af2..622fee357d 100644 --- a/target/mips/system/cp0_timer.c +++ b/target/mips/system/cp0_timer.c @@ -23,6 +23,7 @@ #include "qemu/osdep.h" #include "hw/core/irq.h" #include "qemu/timer.h" +#include "qemu/atomic.h" #include "internal.h" =20 /* MIPS R4K timer */ @@ -31,7 +32,7 @@ static uint32_t cpu_mips_get_count_val(CPUMIPSState *env) MIPSCPU *cpu =3D env_archcpu(env); int64_t now_ns; now_ns =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - return env->CP0_Count + + return qatomic_read(&env->CP0_Count) + (uint32_t)clock_ns_to_ticks(cpu->count_clock, now_ns); } =20 @@ -56,15 +57,15 @@ static void cpu_mips_timer_expire(CPUMIPSState *env) { cpu_mips_timer_update(env); if (env->insn_flags & ISA_MIPS_R2) { - env->CP0_Cause |=3D 1 << CP0Ca_TI; + qatomic_or(&env->CP0_Cause, 1 << CP0Ca_TI); } qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); } =20 uint32_t cpu_mips_get_count(CPUMIPSState *env) { - if (env->CP0_Cause & (1 << CP0Ca_DC)) { - return env->CP0_Count; + if (qatomic_read(&env->CP0_Cause) & (1 << CP0Ca_DC)) { + return qatomic_read(&env->CP0_Count); } else { uint64_t now_ns; =20 @@ -86,12 +87,13 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t c= ount) * So env->timer may be NULL, so treat timer as disabled in that case. */ MIPSCPU *cpu =3D env_archcpu(env); - if (env->CP0_Cause & (1 << CP0Ca_DC) || !env->timer) { - env->CP0_Count =3D count; + if ((qatomic_read(&env->CP0_Cause) & (1 << CP0Ca_DC)) || !env->timer) { + qatomic_set(&env->CP0_Count, count); } else { /* Store new count register */ - env->CP0_Count =3D count - (uint32_t)clock_ns_to_ticks(cpu->count_= clock, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); + qatomic_set(&env->CP0_Count, + count - (uint32_t)clock_ns_to_ticks(cpu->count_clock, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL))); /* Update timer timer */ cpu_mips_timer_update(env); } @@ -100,26 +102,28 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t= count) void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value) { env->CP0_Compare =3D value; - if (!(env->CP0_Cause & (1 << CP0Ca_DC))) { + if (!(qatomic_read(&env->CP0_Cause) & (1 << CP0Ca_DC))) { cpu_mips_timer_update(env); } if (env->insn_flags & ISA_MIPS_R2) { - env->CP0_Cause &=3D ~(1 << CP0Ca_TI); + qatomic_and(&env->CP0_Cause, ~(1 << CP0Ca_TI)); } qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); } =20 void cpu_mips_start_count(CPUMIPSState *env) { - cpu_mips_store_count(env, env->CP0_Count); + cpu_mips_store_count(env, qatomic_read(&env->CP0_Count)); } =20 void cpu_mips_stop_count(CPUMIPSState *env) { /* Store the current value */ MIPSCPU *cpu =3D env_archcpu(env); - env->CP0_Count +=3D (uint32_t)clock_ns_to_ticks(cpu->count_clock, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); + + qatomic_add(&env->CP0_Count, + (uint32_t)clock_ns_to_ticks(cpu->count_clock, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL))); } =20 static void mips_timer_cb(void *opaque) @@ -128,7 +132,7 @@ static void mips_timer_cb(void *opaque) =20 env =3D opaque; =20 - if (env->CP0_Cause & (1 << CP0Ca_DC)) { + if (qatomic_read(&env->CP0_Cause) & (1 << CP0Ca_DC)) { return; } =20 diff --git a/target/mips/tcg/system/special_helper.c b/target/mips/tcg/syst= em/special_helper.c index b54cbe88a3..04ae0bc6c3 100644 --- a/target/mips/tcg/system/special_helper.c +++ b/target/mips/tcg/system/special_helper.c @@ -24,21 +24,22 @@ #include "exec/helper-proto.h" #include "exec/translation-block.h" #include "internal.h" +#include "qemu/atomic.h" =20 /* Specials */ target_ulong helper_di(CPUMIPSState *env) { - target_ulong t0 =3D env->CP0_Status; + target_ulong t0 =3D qatomic_read(&env->CP0_Status); =20 - env->CP0_Status =3D t0 & ~(1 << CP0St_IE); + qatomic_set(&env->CP0_Status, t0 & ~(1 << CP0St_IE)); return t0; } =20 target_ulong helper_ei(CPUMIPSState *env) { - target_ulong t0 =3D env->CP0_Status; + target_ulong t0 =3D qatomic_read(&env->CP0_Status); =20 - env->CP0_Status =3D t0 | (1 << CP0St_IE); + qatomic_set(&env->CP0_Status, t0 | (1 << CP0St_IE)); return t0; } =20 @@ -103,13 +104,15 @@ bool mips_io_recompile_replay_branch(CPUState *cs, co= nst TranslationBlock *tb) =20 static inline void exception_return(CPUMIPSState *env) { + target_ulong status =3D qatomic_read(&env->CP0_Status); + debug_pre_eret(env); - if (env->CP0_Status & (1 << CP0St_ERL)) { + if (status & (1 << CP0St_ERL)) { mips_env_set_pc(env, env->CP0_ErrorEPC); - env->CP0_Status &=3D ~(1 << CP0St_ERL); + qatomic_set(&env->CP0_Status, status & ~(1 << CP0St_ERL)); } else { mips_env_set_pc(env, env->CP0_EPC); - env->CP0_Status &=3D ~(1 << CP0St_EXL); + qatomic_set(&env->CP0_Status, status & ~(1 << CP0St_EXL)); } compute_hflags(env); debug_post_eret(env); diff --git a/target/mips/tcg/system/tlb_helper.c b/target/mips/tcg/system/t= lb_helper.c index 4398c6f80b..9772df5d6c 100644 --- a/target/mips/tcg/system/tlb_helper.c +++ b/target/mips/tcg/system/tlb_helper.c @@ -1106,7 +1106,7 @@ void mips_cpu_do_interrupt(CPUState *cs) env->hflags &=3D ~(MIPS_HFLAG_KSU); /* EJTAG probe trap enable is not implemented... */ if (!(env->CP0_Status & (1 << CP0St_EXL))) { - env->CP0_Cause &=3D ~(1U << CP0Ca_BD); + qatomic_and(&env->CP0_Cause, (int32_t)~(1U << CP0Ca_BD)); } env->active_tc.PC =3D env->exception_base + 0x480; set_hflags_for_handler(env); @@ -1134,7 +1134,7 @@ void mips_cpu_do_interrupt(CPUState *cs) env->hflags |=3D MIPS_HFLAG_CP0; env->hflags &=3D ~(MIPS_HFLAG_KSU); if (!(env->CP0_Status & (1 << CP0St_EXL))) { - env->CP0_Cause &=3D ~(1U << CP0Ca_BD); + qatomic_and(&env->CP0_Cause, (int32_t)~(1U << CP0Ca_BD)); } env->active_tc.PC =3D env->exception_base; set_hflags_for_handler(env); @@ -1148,7 +1148,9 @@ void mips_cpu_do_interrupt(CPUState *cs) offset =3D 0x200; } else { uint32_t vector =3D 0; - uint32_t pending =3D (env->CP0_Cause & CP0Ca_IP_mask) >> C= P0Ca_IP; + uint32_t pending =3D + (qatomic_read(&env->CP0_Cause) & CP0Ca_IP_mask) >> + CP0Ca_IP; =20 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { /* @@ -1246,8 +1248,9 @@ void mips_cpu_do_interrupt(CPUState *cs) case EXCP_CpU: cause =3D 11; update_badinstr =3D 1; - env->CP0_Cause =3D (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) | - (env->error_code << CP0Ca_CE); + qatomic_and(&env->CP0_Cause, (int32_t)~(0x3U << CP0Ca_CE)); + qatomic_or(&env->CP0_Cause, + (int32_t)(env->error_code << CP0Ca_CE)); goto set_EPC; case EXCP_OVERFLOW: cause =3D 12; @@ -1305,9 +1308,9 @@ void mips_cpu_do_interrupt(CPUState *cs) set_badinstr_registers(env); } if (env->hflags & MIPS_HFLAG_BMASK) { - env->CP0_Cause |=3D (1U << CP0Ca_BD); + qatomic_or(&env->CP0_Cause, (int32_t)(1U << CP0Ca_BD)); } else { - env->CP0_Cause &=3D ~(1U << CP0Ca_BD); + qatomic_and(&env->CP0_Cause, (int32_t)~(1U << CP0Ca_BD)); } env->CP0_Status |=3D (1 << CP0St_EXL); if (env->insn_flags & ISA_MIPS3) { @@ -1333,8 +1336,8 @@ void mips_cpu_do_interrupt(CPUState *cs) =20 env->active_tc.PC +=3D offset; set_hflags_for_handler(env); - env->CP0_Cause =3D (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | - (cause << CP0Ca_EC); + qatomic_and(&env->CP0_Cause, (int32_t)~(0x1f << CP0Ca_EC)); + qatomic_or(&env->CP0_Cause, cause << CP0Ca_EC); break; default: abort(); --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437150073551.8177033709205; Thu, 3 Sep 2026 05:05:50 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26C7-0002iN-Dy; Thu, 03 Sep 2026 08:05:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C4-0002hJ-Sp for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:25 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C2-0005Ja-Nb for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:24 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 4e406c7c (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:19 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 73407dda; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=NwJClQ6 rxqCQywUO4C92xb0lZf3f9zNQlczCl4ds27/sqjCy5wXdGJ23KvwE9a4BbbxrA4t3nWI7Z u3ZszT30zXx8qAZh5ffFfhdQaxAqz5XAVV4aoMrZJIZoEjubFw3pVnbMIMAk9SUXja9zIT Gh6Ly0/FGqQhvVnhIC6zySlorjArT6fVnFm/OOEfVV+VXP/n1lN7ODOsk5fO5jGW7cnesi VnBFOfOD0b8JUkeknHwvpYVCGK2c2wCG4l5YKf/EKND/aNt0vo4M+4HMRrecGzi6UQSNqY sxxsT1nF0hMGJhfZetfcXIZNGyYmcMjhcWrDKGRWTxzMhtGs/ci9HkA== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=4 pig9i2fHRxRANsh7tiMj+tEIYraNPzc4moL169W8vk=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=MWCod3c5AgbAxnGr9xXqGOWNT8G4b4JSIpK5UPo+z8z0a6F4VEp18FqRSzuvkH1L5GPa 0WhzgmWyGSS6s+FGjiMWXw6gOX0xTdJfbr84bHgoz7PWpDZOUAQXYkgQabNesiBUq3odKC ftHwQbAAzcpJlIB3ISEDX6LNZT/31muUygbmCzKYAQAdLyUIh7jxQT6muIn1wHDL21MPo6 UFBqhCTq7JSVQwLtKGLyth+yFvjECoh5tcPn5gKYKJJQBhPsFxn/FRTeOEcuXBaFlhTOvf eMfMAWykjk1SKZWJKME/j93szEh+/85ZZ+pkn/bzcIXXPcuw1S2N+tYIqIbhh0fg== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=Za9hJZYR; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=6NLDU0O3; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=4pig9i2f HRxRANsh7tiMj+tEIYraNPzc4moL169W8vk=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=Za9hJZYRNmFx9ogjfgwQmx5qKea36ZZ1yj2 qHdXM1D20DEgvpk7iD6w/0o7VGLsQUZxVZ9u8IuqswmIZr3nukCUfqWuxSzi3K312R+QLO cEUD0OFSJc1psVfBGnEub//niFWsY6S2go357cwUW4CIHFNxNKbPnP+6OfJsq5MENS9lZD sStwGByg0DHurc7Ikufox1BUqNCwQ/i4ku9/Hn0wImemcB5eZkx9JshmLkpnlCwAqD6QtX bz25ISoSbb79TrStcKVvI2jZ38mwpLEG3xXD5OMzDiKaExZwap64fkIrJSoh4WOD3ewC3P 97JQegNrPfnloT23dhtx9oZeczA== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=4pig9i2fHRxRANsh7tiMj+tEIYraNPzc4moL169W8vk=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=6NLDU0O3XtohzWzDAa 6KBRbh1U8ey4yz7vyf1pG/czDyigiLv2GF6vbQqeXI3XrNTs+IMdho+tt7Wh+XEoy9Dw== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 02/25] target/mips: fix MIPS64 segment access checks Date: Thu, 3 Sep 2026 14:01:50 +0200 Message-ID: <20260903120510.34876-3-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437152438158500 Content-Type: text/plain; charset="utf-8" The xuseg and xsseg checks only tested UX and SX respectively; kernel and supervisor accesses must instead use the mode bit that applies to the current execution mode. Allow supervisor and kernel mode to use xuseg when SX or KX is set, and allow kernel mode to use xsseg when KX is set. --- target/mips/system/physaddr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target/mips/system/physaddr.c b/target/mips/system/physaddr.c index 746dbf8aa4..626d7ccc4c 100644 --- a/target/mips/system/physaddr.c +++ b/target/mips/system/physaddr.c @@ -143,7 +143,9 @@ int get_physical_address(CPUMIPSState *env, hwaddr *phy= sical, #if defined(TARGET_MIPS64) } else if (address < 0x4000000000000000ULL) { /* xuseg */ - if (UX && address <=3D (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { + if (((user_mode && UX) || (supervisor_mode && SX) || + (kernel_mode && KX)) && + address <=3D (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { ret =3D env->tlb->map_address(env, physical, prot, real_address, access_type); } else { @@ -151,8 +153,8 @@ int get_physical_address(CPUMIPSState *env, hwaddr *phy= sical, } } else if (address < 0x8000000000000000ULL) { /* xsseg */ - if ((supervisor_mode || kernel_mode) && - SX && address <=3D (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { + if (((supervisor_mode && SX) || (kernel_mode && KX)) && + address <=3D (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { ret =3D env->tlb->map_address(env, physical, prot, real_address, access_type); } else { --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17884372498470.7660528186009969; Thu, 3 Sep 2026 05:07:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CC-0002oE-Gz; Thu, 03 Sep 2026 08:05:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C9-0002jf-Sq for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:30 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C7-0005JF-8o for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:29 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 03ea62da (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:21 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 4630338c; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=bzX8ugD Il06QJ3jJHD74t6ibT6l0ECqHIaSfvSapBz9U/tjwRBQtbbWFTbtLLeYpd39RB7E0Ak2As pF2h4V4ipQ45Lzoe0oEg5cir+XGAnFOsRdYpQnspXlpwj6YfI8HCxVMoctxWcSIzJbWIFk UirsY64C7P3NKxj1vAkfM7VAjbMcQkhoyImu5BYreeu/cB1+mZxeAaKqEBpuHPwcfQxf+n gyeJ0p8Kjgz0B9v4BLSmMa6l3xjz/WDrcFxzKF+lsyfs60UJpRbQd1XyTZrK8qMAm2HEsy uZqWZQV/6I6atVlHgbgg8loE7cZpRyN63LxPRuvFj5N/Rrdn+GCplyQ== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=n sknwmCpJ8wp9wFHy/xw1JvJkqzwM23UicaxYjyzWvk=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=Fy4NkCO3KJH0UURvyF4c2amEoLevH8VF80IVb6Y+yFSH9Cgl8WW367edOtpAtjyschcv yagiAI55KVVuKbeB7IPTybvGLGE0YxSzv0HT7FseCqkpjdlg4+mnIINcsAJ+H5+bZsY/C9 NS851WDh8GPRQ5pGhYvZxYXpyzZS/qXlkwPBvMs/q7GEw0Z7vMGIvgeNGEUHcByCm1m0tY PXPJzA5hJ2FnF5pW5+SqLeKctOQ5tGybXs6KDj4AVrzJU/3cXc+Osr8+51LIvJgRJnWllU A4o6kob86w7vspqZf0J5qmmvUBEO0ccU7WTuiDSaBxmr/89kCZays4SboFNbDI3w== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=sUKkD7xQ; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=+Ui+Hb/V; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=nsknwmCp J8wp9wFHy/xw1JvJkqzwM23UicaxYjyzWvk=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=sUKkD7xQOnIWqQDCOixPuHWjFJlQ9aSJc5t dlV1NzI1A+MOh7o2Pe6Tac6QwGZ7DLbvBOTsZi+CEnZn4q1bBRk4RDw1NI9cRUF/kq8wAC iqehh/3sPUzNZvvyJUB7i97INA46zaG57BuHkk9G6gOQNvlP64shRLTNRyltschCiPCJdi h1ADtEYwUrmsjYkdnG2q1inSco1g68xz/tcqlKrrHYyoTYQbfDsZ3v7HbjuJFsXsjRpr26 ylDj6sAC5usnwxrH0KFFUjNaFm/91P3uBbEDZcER9rfOWp9IqKiGvia7Ft3+W5SvEOgeU2 ZQJUC4Z1CvmbD8tJBLjOnHAc34w== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=nsknwmCpJ8wp9wFHy/xw1JvJkqzwM23UicaxYjyzWvk=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=+Ui+Hb/VRgvUvhjS+8 ZO60nt2TMNHufp0M+LBUOrTIS5lqRigMMOX5hpQAhNRXTrRAyC2uox7URLgU3005MoCg== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 03/25] target/mips: drop hidden TLB shadowing for tlbwr Date: Thu, 3 Sep 2026 14:01:51 +0200 Message-ID: <20260903120510.34876-4-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437251986158500 Content-Type: text/plain; charset="utf-8" tlbwr replaces a random architectural TLB entry. Once that happens, the evicted entry must stop translating guest virtual addresses. The current helper keeps the evicted entry in QEMU-only extra TLB state. That makes the old mapping survive until some later operation discards the extra entries. A guest can observe this directly by writing through a TLB mapping, replacing that entry with tlbwr, and writing through the old virtual address again. Invalidate the replaced entry instead of shadowing it. This keeps the translated TLB state aligned with the architectural TLB contents. --- target/mips/tcg/system/tlb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/tcg/system/tlb_helper.c b/target/mips/tcg/system/t= lb_helper.c index 9772df5d6c..4c0a25e622 100644 --- a/target/mips/tcg/system/tlb_helper.c +++ b/target/mips/tcg/system/tlb_helper.c @@ -165,7 +165,7 @@ static void r4k_helper_tlbwr(CPUMIPSState *env) { int r =3D cpu_mips_get_random(env); =20 - r4k_invalidate_tlb(env, r, 1); + r4k_invalidate_tlb(env, r, 0); r4k_fill_tlb(env, r); } =20 --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437252629776.9020318685696; Thu, 3 Sep 2026 05:07:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CC-0002nU-7V; Thu, 03 Sep 2026 08:05:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C8-0002j2-N9 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:29 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C5-0005Ja-9q for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:27 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id f5bed4a0 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:22 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 60d11da0; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=MoqJvAV 6apcp7mJ4/Ex4jMLyD3wJ3zpWpXKdQkK++VKvm691dB0QmDCYx7ezDG2qExKa/xfnEgF6Z IuKRCjoaRiJskFkfke34CF/T24hK/zQzADOb6deqxar27KOJRbafqy5ZX3qyhExzh27NRJ ZlST5W/GWPWnfO3eeBtAkimmbnViYMeP6RzB9Qq/gENKLO0nd3cZurdBw/g4RZ7z5QKTwW N5PAj1gzpb2BeEwGj+Vy59LUQDhSpz+E88aDyUb4DePcnoQAj/mtmvEZp2cvoQLelwV6lm oAiGiC611CYNmWKKpZjm6MSDqqUy1S4AKO9r14r0Jmx5i//fBgYa6fw== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=P uBIMXY9wWzAEtKOuCnJRGci1wgIVwMY0d6UGeXjRrU=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=LG+cfBzl4Or+4uVmvVHh3INacV2eQ5sCqkFoH6JIksYTEQqjJV7pDFbaDfEdx6V4+pU+ jr0xZ+IakPcjemspOBIYLwyUPasGrVFC1szbGGQNBEgzeZShvErPqoiNZX8PHEN+ZU9Fc0 KCFRQjIhQbmBBPUWrbQ+WDXhdfeC+qJFx6Z9yUe3MfpSEdpCrHV1ywRHzcQK1eAvQQ01LY zGX62Q9Ack3n50QjUMuPnNzUJNbTKaByLUrpYoss/N+X5r0wLQgA9r/Kuk9NbSNTgk8fk/ zqopytGiXoo3dcnzDnMmPzU1wUSIcPF1gDfZZgk3Q6EPOX8LL1tohGd6NKDC5v+A== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=zXLFDpWL; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=NkCL3aE7; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=PuBIMXY9 wWzAEtKOuCnJRGci1wgIVwMY0d6UGeXjRrU=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=zXLFDpWLAiKHx1sjhO7qd1UDa6QtWmKz3BL VcZUhY5Ow1F8xsgh+PsXpqlZMOhpBznGMj4fJ+F+KhtQRj6jUl8VJrdLeyzR9/5kieyq+2 ve0DvUBxn0GBVhjTXaTfp7kczuGKdl4AvX0Sho3rrLm1qFJ4Hhg7SBUJBF6kBN55IKSrm/ +MOlwUmg7yoXpCi0Ypgeedigyq9DSTLGMH2zzePOwwXujxV0b6Zz841hRGTHjFN9Pjggqx wDyiB7rTeMjuucdke0zXPBlMRNewn0ewENNI6LixzbSZ6G1rOj/Kf9L5Qu3B68JtkX+Dba wAobv9Pq5gLeatK2ThOw5SVLSxQ== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=PuBIMXY9wWzAEtKOuCnJRGci1wgIVwMY0d6UGeXjRrU=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=NkCL3aE7EdvYJXHZ41 RStjIdKv2hKD0BmVW075FnryRUibUIC93v/N8j6gTIKAMaG/BPftzq607jlxtoMv4kDw== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 04/25] target/mips: add Octeon CP0 register state Date: Thu, 3 Sep 2026 14:01:52 +0200 Message-ID: <20260903120510.34876-5-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437253970158500 Content-Type: text/plain; charset="utf-8" Octeon firmware and kernels use implementation specific CP0 registers for the cycle counter and local memory control. Add CvmCount, CvmCtl, and CvmMemCtl accessors for Octeon CPUs; migrate the new CP0 state, and translate the enabled CVMSEG virtual window to per vCPU backing memory. --- target/mips/cpu.h | 5 +++ target/mips/system/machine.c | 13 +++++++ target/mips/system/physaddr.c | 22 +++++++++++ target/mips/tcg/op_helper.c | 2 +- target/mips/tcg/system/cp0_helper.c | 10 +++++ target/mips/tcg/system_helper.h.inc | 1 + target/mips/tcg/translate.c | 60 +++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 1 deletion(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 319147a948..c6da52e17f 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -341,6 +341,8 @@ typedef struct mips_def_t mips_def_t; #define CP0_REG09__COUNT 0 #define CP0_REG09__SAARI 6 #define CP0_REG09__SAAR 7 +#define CP0_REG09__CVMCOUNT 6 +#define CP0_REG09__CVMCTL 7 /* CP0 Register 10 */ #define CP0_REG10__ENTRYHI 0 #define CP0_REG10__GUESTCTL1 4 @@ -349,6 +351,7 @@ typedef struct mips_def_t mips_def_t; /* CP0 Register 11 */ #define CP0_REG11__COMPARE 0 #define CP0_REG11__GUESTCTL0EXT 4 +#define CP0_REG11__CVMMEMCTL 7 /* CP0 Register 12 */ #define CP0_REG12__STATUS 0 #define CP0_REG12__INTCTL 1 @@ -787,6 +790,7 @@ typedef struct CPUArchState { * CP0 Register 9 */ int32_t CP0_Count; + target_ulong CP0_CvmCtl; #define CP0SAARI_TARGET 0 /* 5..0 */ #define CP0SAAR_BASE 12 /* 43..12 */ #define CP0SAAR_SIZE 1 /* 5..1 */ @@ -801,6 +805,7 @@ typedef struct CPUArchState { * CP0 Register 11 */ int32_t CP0_Compare; + target_ulong CP0_CvmMemCtl; /* * CP0 Register 12 */ diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c index bd1e4002cf..3661da0566 100644 --- a/target/mips/system/machine.c +++ b/target/mips/system/machine.c @@ -372,6 +372,18 @@ static const VMStateDescription mips_vmstate_octeon_cr= ypto =3D { } }; =20 +static const VMStateDescription mips_vmstate_octeon_cp0 =3D { + .name =3D "cpu/octeon_cp0", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D mips_octeon_needed, + .fields =3D (const VMStateField[]) { + VMSTATE_UINTTL(env.CP0_CvmCtl, MIPSCPU), + VMSTATE_UINTTL(env.CP0_CvmMemCtl, MIPSCPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_mips_cpu =3D { .name =3D "cpu", .version_id =3D 21, @@ -490,6 +502,7 @@ const VMStateDescription vmstate_mips_cpu =3D { &mips_vmstate_timer, &mips_vmstate_octeon_multiplier, &mips_vmstate_octeon_crypto, + &mips_vmstate_octeon_cp0, NULL } }; diff --git a/target/mips/system/physaddr.c b/target/mips/system/physaddr.c index 626d7ccc4c..a0538d8b6b 100644 --- a/target/mips/system/physaddr.c +++ b/target/mips/system/physaddr.c @@ -21,6 +21,14 @@ #include "exec/page-protection.h" #include "../internal.h" =20 +/* + * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; + * the guest sees the virtual CVMSEG window, not this physical address. + */ +#define OCTEON_CVMSEG_BASE 0x10000000000ULL +#define OCTEON_CVMSEG_SIZE 0x4000ULL +#define OCTEON_CVMSEG_MASK 0x3fffULL + static int is_seg_am_mapped(unsigned int am, bool eu, int mmu_idx) { /* @@ -128,6 +136,20 @@ int get_physical_address(CPUMIPSState *env, hwaddr *ph= ysical, int ret =3D TLBRET_MATCH; target_ulong address =3D real_address; =20 +#if defined(TARGET_MIPS64) + if ((env->insn_flags & INSN_OCTEON) && (env->CP0_CvmMemCtl & 0x100) && + address >=3D 0xffffffffffff8000ULL && + address <=3D 0xffffffffffffbfffULL) { + MIPSCPU *cpu =3D env_archcpu(env); + + *physical =3D OCTEON_CVMSEG_BASE + + CPU(cpu)->cpu_index * OCTEON_CVMSEG_SIZE + + (address & OCTEON_CVMSEG_MASK); + *prot =3D PAGE_READ | PAGE_WRITE; + return TLBRET_MATCH; + } +#endif + if (address <=3D USEG_LIMIT) { /* useg */ uint16_t segctl; diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c index df1b5c3734..2bfe661ef2 100644 --- a/target/mips/tcg/op_helper.c +++ b/target/mips/tcg/op_helper.c @@ -268,7 +268,7 @@ target_ulong helper_rdhwr_cvmcount(CPUMIPSState *env) #ifdef CONFIG_USER_ONLY return cpu_get_host_ticks(); #else - return (uint32_t)cpu_mips_get_count(env); + return helper_mfc0_cvmcount(env); #endif } =20 diff --git a/target/mips/tcg/system/cp0_helper.c b/target/mips/tcg/system/c= p0_helper.c index ba6b487b75..1c23d2a525 100644 --- a/target/mips/tcg/system/cp0_helper.c +++ b/target/mips/tcg/system/cp0_helper.c @@ -23,6 +23,8 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "qemu/main-loop.h" +#include "qemu/timer.h" +#include "hw/core/clock.h" #include "cpu.h" #include "internal.h" #include "qemu/host-utils.h" @@ -374,6 +376,14 @@ target_ulong helper_mfc0_count(CPUMIPSState *env) return (int32_t)cpu_mips_get_count(env); } =20 +target_ulong helper_mfc0_cvmcount(CPUMIPSState *env) +{ + MIPSCPU *cpu =3D env_archcpu(env); + + return clock_ns_to_ticks(cpu->clock, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); +} + target_ulong helper_mftc0_entryhi(CPUMIPSState *env) { int other_tc =3D env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); diff --git a/target/mips/tcg/system_helper.h.inc b/target/mips/tcg/system_h= elper.h.inc index eaac5e2c6f..c8b6d8b92c 100644 --- a/target/mips/tcg/system_helper.h.inc +++ b/target/mips/tcg/system_helper.h.inc @@ -31,6 +31,7 @@ DEF_HELPER_1(mftc0_tcschedule, tl, env) DEF_HELPER_1(mfc0_tcschefback, tl, env) DEF_HELPER_1(mftc0_tcschefback, tl, env) DEF_HELPER_1(mfc0_count, tl, env) +DEF_HELPER_1(mfc0_cvmcount, tl, env) DEF_HELPER_1(mftc0_entryhi, tl, env) DEF_HELPER_1(mftc0_status, tl, env) DEF_HELPER_1(mftc0_cause, tl, env) diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index e3467d1525..123ba6aecd 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -5460,6 +5460,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, in= t reg, int sel) ctx->base.is_jmp =3D DISAS_EXIT; register_name =3D "Count"; break; + case CP0_REG09__CVMCOUNT: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + translator_io_start(&ctx->base); + gen_helper_mfc0_cvmcount(arg, tcg_env); + tcg_gen_ext32s_tl(arg, arg); + register_name =3D "CvmCount"; + break; + case CP0_REG09__CVMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CvmCtl)= ); + tcg_gen_ext32s_tl(arg, arg); + register_name =3D "CvmCtl"; + break; default: goto cp0_unimplemented; } @@ -5481,6 +5494,13 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, in= t reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare)); register_name =3D "Compare"; break; + case CP0_REG11__CVMMEMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_ld_tl(arg, tcg_env, + offsetof(CPUMIPSState, CP0_CvmMemCtl)); + tcg_gen_ext32s_tl(arg, arg); + register_name =3D "CvmMemCtl"; + break; /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; @@ -6176,6 +6196,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, in= t reg, int sel) gen_helper_mtc0_count(tcg_env, arg); register_name =3D "Count"; break; + case CP0_REG09__CVMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CvmCtl)= ); + register_name =3D "CvmCtl"; + break; default: goto cp0_unimplemented; } @@ -6196,6 +6221,13 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, in= t reg, int sel) gen_helper_mtc0_compare(tcg_env, arg); register_name =3D "Compare"; break; + case CP0_REG11__CVMMEMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_st_tl(arg, tcg_env, + offsetof(CPUMIPSState, CP0_CvmMemCtl)); + ctx->base.is_jmp =3D DISAS_STOP; + register_name =3D "CvmMemCtl"; + break; /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; @@ -6940,6 +6972,17 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, i= nt reg, int sel) ctx->base.is_jmp =3D DISAS_EXIT; register_name =3D "Count"; break; + case CP0_REG09__CVMCOUNT: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + translator_io_start(&ctx->base); + gen_helper_mfc0_cvmcount(arg, tcg_env); + register_name =3D "CvmCount"; + break; + case CP0_REG09__CVMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CvmCtl)= ); + register_name =3D "CvmCtl"; + break; default: goto cp0_unimplemented; } @@ -6960,6 +7003,12 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, i= nt reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare)); register_name =3D "Compare"; break; + case CP0_REG11__CVMMEMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_ld_tl(arg, tcg_env, + offsetof(CPUMIPSState, CP0_CvmMemCtl)); + register_name =3D "CvmMemCtl"; + break; /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; @@ -7642,6 +7691,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, i= nt reg, int sel) gen_helper_mtc0_count(tcg_env, arg); register_name =3D "Count"; break; + case CP0_REG09__CVMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CvmCtl)= ); + register_name =3D "CvmCtl"; + break; default: goto cp0_unimplemented; } @@ -7664,6 +7718,12 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, i= nt reg, int sel) gen_helper_mtc0_compare(tcg_env, arg); register_name =3D "Compare"; break; + case CP0_REG11__CVMMEMCTL: + CP0_CHECK(ctx->insn_flags & INSN_OCTEON); + tcg_gen_st_tl(arg, tcg_env, + offsetof(CPUMIPSState, CP0_CvmMemCtl)); + register_name =3D "CvmMemCtl"; + break; /* 6,7 are implementation dependent */ default: goto cp0_unimplemented; --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437194164432.0343860396298; Thu, 3 Sep 2026 05:06:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CE-0002sx-IS; Thu, 03 Sep 2026 08:05:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CC-0002o7-Ct for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:32 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CA-0005JF-GO for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:32 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id b5224898 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:22 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 9ff2370d; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=V+7jQIX wI7VJXJveXplngZDJUd0BOQfA77SDNeejnpIRLHjgx6GvYDuJXqhSXpzWXWUSSuu1qxbcg 1V0/S3LpG/gYNXcTN0qtO9/e5C0EgQe9b07LnRv4cf1ns4QgTl+JynPIAhnxDu5jAm9BmN W7HTLEKn0DA6kMW/O4U/nGzh+DsnLLPuKj1UZhbPmsRrVJShLe59TPbwwxTf8knHIJIoQO GP0mrg2w0cwOSSI0O1Nh7PPtl1n4rNfNA5Infe32fuWsVCI4xDHvImDarP6iigG+dxSa63 s3rwgQfn9uByOn4zEn/2NdigcABqULdnD0S4AGZTdP9HSzp0HrjS49A== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=o /KWYEDAjV7XEuyr3cWlPL9WXNJRoioeURGef9XcXS4=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=ul2leS2/s8+YIGMSTL5NzSbhArU5Sca4NGhcoDl3f/Sga3PqXfQ2MfyfJoqoGhVrRp3H GUKC36/xoP5Koi8hHu1NaLvERBHpbat/62zQOhON7P/AUzkaIrXT4MwDZ40j7YghtH1o0o /7jVAeb7uyKgGRqnawFQJ5A7xSs0q4giZry1d/+E8XiJIqY2Rmy+oA0w/Yj+pplzfNWrZ6 L+0RvPD2HjhO7v6SVOq7+RAhF7TzwPBndF/Kh4buwlWeF8XLNPSebtoJOPbWi0D7Z0nyYg YPpLNlEd6IrQ1oQDp8fcfSysXOJRfrI1TXkpyCZxiemk0bkSccMCtQy6ryuyny2A== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=Vcbh2Zw3; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=wvK2sbCN; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=o/KWYEDA jV7XEuyr3cWlPL9WXNJRoioeURGef9XcXS4=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=Vcbh2Zw3CsMTn9P4KhVxdDxUpEUvndQT1f/ HDPmG0oI7Rn0V5zqKx+4zpqCWCileZzlMd29/sxodt6EmcYyFhgEQAzPki2IiRbtHwmM8O VAHYrJgCmFtAHeckUfRIVGztViN35aJx8TlKz9wENkSAfRsHM/0qc9/dryyofH0ZBiFn23 SdSQ/QXCo3NgkDLoFMkP73MseDAz8DO78lTuRevbCmF6a8/HjDFvBKRJPqKCQgxcr7Kw+a UJzAgQY8c93IJTqLs0Yc1Lb3kiBJJn1nEw2ypiP3ZFoTSdgBcdbDA5yRp59MdraQWytcRW gTRbhzFYAvrcK3LCxyI0NtlvQRg== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=o/KWYEDAjV7XEuyr3cWlPL9WXNJRoioeURGef9XcXS4=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=wvK2sbCNhrnfd+F5wD IXKwGorjpD6G6dZbfOc3As1xn3SJ7ciX3WaJpzKcvJXHEI4ZOCVYrVMh8cGETRPQZHBQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 05/25] target/mips: add Octeon CN73xx CPU model Date: Thu, 3 Sep 2026 14:01:53 +0200 Message-ID: <20260903120510.34876-6-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437195801158500 Content-Type: text/plain; charset="utf-8" Add a CN73xx CPU definition for the Octeon III machine. The PRId, FPU FIR, and L2 cache geometry come from EdgeRouter Infinity ER-8-XG data; the remaining CP0 fields come from a Juniper SRX300 CN70xx/CN71xx dump. --- target/mips/cpu-defs.c.inc | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc index cc1916232f..ee638568db 100644 --- a/target/mips/cpu-defs.c.inc +++ b/target/mips/cpu-defs.c.inc @@ -1023,6 +1023,48 @@ const mips_def_t mips_defs[] =3D .insn_flags =3D CPU_MIPS64R2 | INSN_OCTEON, .mmu_type =3D MMU_TYPE_R4000, }, + { + /* + * Minimal Octeon CN73xx model for EBB7304 firmware. PRId, FPU FIR, + * and L2 cache geometry match a Ubiquiti EdgeRouter Infinity + * ER-8-XG; the remaining CP0 values are a placeholder Octeon III + * model derived from a Juniper SRX300 CN70xx/CN71xx dump. + */ + .name =3D "OcteonCN73XX", + .CP0_PRid =3D 0x000D9702, + .CP0_Config0 =3D MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_= AT) | + (MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI), + .CP0_Config1 =3D MIPS_CONFIG1 | (1 << CP0C1_FP) | + (0x3F << CP0C1_MMU) | + (0 << CP0C1_IS) | (6 << CP0C1_IL) | (7 << CP0C1_IA)= | + (0 << CP0C1_DS) | (0 << CP0C1_DL) | (7 << CP0C1_DA)= | + (1 << CP0C1_C2) | (1 << CP0C1_PC) | + (1 << CP0C1_WR) | (1 << CP0C1_EP), + .CP0_Config2 =3D MIPS_CONFIG2 | (5 << CP0C2_SS) | (6 << CP0C2_SL) | + (15 << CP0C2_SA), + .CP0_Config3 =3D MIPS_CONFIG3 | (1U << CP0C3_M) | + (1 << CP0C3_BP) | (1 << CP0C3_BI) | + (1 << CP0C3_VZ) | (1 << CP0C3_ULRI) | + (1 << CP0C3_RXI) | (1 << CP0C3_LPA), + .CP0_Config4 =3D MIPS_CONFIG4 | (1U << CP0C4_M) | + (0x3c << CP0C4_KScrExist), + .CP0_Config7 =3D 1 << CP0C7_WII, + .CP0_LLAddr_rw_bitmask =3D 0, + .CP0_LLAddr_shift =3D 4, + .CP0_PageGrain =3D (1 << CP0PG_ELPA), + .SYNCI_Step =3D 32, + .CCRes =3D 1, + .CP0_Status_rw_bitmask =3D 0x36F8FFFF, + .CP1_fcr0 =3D (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | + (1 << FCR0_D) | (1 << FCR0_S) | + (0x97 << FCR0_PRID) | (0x0 << FCR0_REV), + .CP1_fcr31 =3D 0, + .CP1_fcr31_rw_bitmask =3D 0xFF83FFFF, + .SEGBITS =3D 42, + .PABITS =3D 49, + .insn_flags =3D CPU_MIPS64R2 | INSN_OCTEON, + .mmu_type =3D MMU_TYPE_R4000, + }, =20 #endif }; --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 178843723301874.12517002731136; Thu, 3 Sep 2026 05:07:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CE-0002sN-0J; Thu, 03 Sep 2026 08:05:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CB-0002mI-6u for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:31 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26C9-0005Ja-C0 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:30 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id ff5ed5d4 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:23 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id fa0c73ed; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=QWICf3s pWUu8XLh4/BsjIGRXRHFXGPokzVb1SyI4T3OLRdPibD4hK1PBPjVo03okES3f4MPhSjxnE uC/D1JUiqhK045QSVu2PEXNECd5roThAD0KDaYjcMT3MtM1ka4wdc3aE0WTDWpAZhU/avJ m4cdyLE6wtEUYWFXGz+PJMY/VPwQUCLc+GBKthiQEtiK4CoyITqqQEyDITp9fxzkQlX2Gj KvdqHEx0E3ztZFc4pAjKcuHRPWqZDhNCoavR0+O/neEObuNyQfruX5gsnATryYOdeQ3kPo me7XEMZM37RErPyTxFF0C4E4efJZVlIwGtl3qfPDkw5f4OZHNssjp5g== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=r qLyOejlQcL4jEeF3YZ9AxaUoEhdFLilYAK4VajrGMA=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=bky4EToxAQk21Wc1QbhCwplnn4Jvcvvy4Q9z+Wd7SxhDIb+nLalmFPGsJW9PXVQhQg+u IibqOY9IPCXd5AYGgjJVicrpSt4ze8DyaBrU0CX6oqLx0Y2Fdf+MJjw6obpbMhBIRViEq+ grh1tUybS30EWdDQNFK5VkPOqe/N//NS/xV3HaK9TPjLbHZY9+COS9K21wYQ2s20Iog7kN 3n8GL14QP/2+mq8a8c33xk6VdVuXdN3Av/Yhu9eOmiFT3JTrwdy2G+fdM8SE2dOIFhIGCE Nokm6AZOHWLO4mcUIg1VqdqWSfal/MTHqu8suPJ0gRokd0HJ/j4cmD0OwyvY0iGQ== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=h45MgYhx; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=LOk/zEUw; arc=none; iprev=fail; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=rqLyOejl QcL4jEeF3YZ9AxaUoEhdFLilYAK4VajrGMA=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=h45MgYhxxwvQd9VmLdsiw26tw5pf2VCWhDL aqS6/jL2/rzk3sPGraTD1ba8nef1Hj8RDtrZ/iQ6fmLUVUPpY68kptJTwF2W2BRPAeJ+w9 GfLHxatHRBAhHoseOLeEajCe1IBQRoOSJqQ1SLl+3bd9sdOlX9j0he6jIGmaOKqXoNgn4V RVvEh8huHker4ibnYYUNrYyFzwMmzqo+IA8qpNMpCWUlkGGqjDwyhq5pf+9p/ORdRuuQ0L RK9esP75C5SCND9QbiII8ch6WywYTCcyAh5oecQv+bk8ybuw9gy4GGpbO/VTP+/nhu5qhe CIqpY3SIHs2V9I3+WVPnzBaP96A== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=rqLyOejlQcL4jEeF3YZ9AxaUoEhdFLilYAK4VajrGMA=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=LOk/zEUwZjAUrHXmAs r+fLD1nh+SUbcHT2QndAhMG2w+Tgy2zPUfpkobPH0m6oVdJkHixp2zhlmo3/iNdyKXAQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 06/25] target/mips: accept Octeon PageMask encodings Date: Thu, 3 Sep 2026 14:01:54 +0200 Message-ID: <20260903120510.34876-7-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437234096158500 Content-Type: text/plain; charset="utf-8" Octeon firmware programs contiguous PageMask values that do not follow the generic R4K even maskbits rule. Keep the generic validation rule for other MIPS CPUs, while allowing Octeon CPUs to use the contiguous masks accepted by hardware. --- target/mips/tcg/system/cp0_helper.c | 15 ++++++++++----- target/mips/tcg/system/tlb_helper.c | 2 +- target/mips/tcg/tcg-internal.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/target/mips/tcg/system/cp0_helper.c b/target/mips/tcg/system/c= p0_helper.c index 1c23d2a525..40a41805fa 100644 --- a/target/mips/tcg/system/cp0_helper.c +++ b/target/mips/tcg/system/cp0_helper.c @@ -882,14 +882,19 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, targe= t_ulong arg1) } } =20 -uint32_t compute_pagemask(uint32_t val) +uint32_t compute_pagemask(CPUMIPSState *env, uint32_t val) { /* Don't care MASKX as we don't support 1KB page */ - uint32_t mask =3D extract32(val, CP0PM_MASK, 16); + uint32_t mask =3D val >> CP0PM_MASK; int maskbits =3D cto32(mask); =20 - /* Ensure no more set bit after first zero, and maskbits even. */ - if ((mask >> maskbits) =3D=3D 0 && maskbits % 2 =3D=3D 0) { + /* + * Generic R4K PageMask values use two mask bits per size step. + * Octeon accepts contiguous byte masks such as 0x003fffff for + * two 2 MiB pages. + */ + if ((mask & (mask + 1)) =3D=3D 0 && + ((env->insn_flags & INSN_OCTEON) || maskbits % 2 =3D=3D 0)) { return mask << CP0PM_MASK; } else { /* When invalid, set to default target page size. */ @@ -899,7 +904,7 @@ uint32_t compute_pagemask(uint32_t val) =20 void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1) { - env->CP0_PageMask =3D compute_pagemask(arg1); + env->CP0_PageMask =3D compute_pagemask(env, arg1); } =20 void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1) diff --git a/target/mips/tcg/system/tlb_helper.c b/target/mips/tcg/system/t= lb_helper.c index 4c0a25e622..ae805bff28 100644 --- a/target/mips/tcg/system/tlb_helper.c +++ b/target/mips/tcg/system/tlb_helper.c @@ -877,7 +877,7 @@ refill: } } pw_pagemask =3D m >> TARGET_PAGE_BITS; - pw_pagemask =3D compute_pagemask(pw_pagemask << CP0PM_MASK); + pw_pagemask =3D compute_pagemask(env, pw_pagemask << CP0PM_MASK); pw_entryhi =3D (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF); { target_ulong tmp_entryhi =3D env->CP0_EntryHi; diff --git a/target/mips/tcg/tcg-internal.h b/target/mips/tcg/tcg-internal.h index 950e6afc3f..66ae39551e 100644 --- a/target/mips/tcg/tcg-internal.h +++ b/target/mips/tcg/tcg-internal.h @@ -47,7 +47,7 @@ bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req); =20 void mmu_init(CPUMIPSState *env, const mips_def_t *def); =20 -uint32_t compute_pagemask(uint32_t val); +uint32_t compute_pagemask(CPUMIPSState *env, uint32_t val); =20 void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra); uint32_t cpu_mips_get_random(CPUMIPSState *env); --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 178843723849577.22297848259666; Thu, 3 Sep 2026 05:07:18 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CG-0002tP-4p; Thu, 03 Sep 2026 08:05:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CD-0002s0-I5 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:33 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CB-0005Ja-PO for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:33 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 6e9a89a8 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:24 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id bb67079e; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=JtsWlNo VAvbxXw57qvxt3fOowbbqlH3nlI5t4GBn6FF9WmrivCaZ3eDO3uy7eiRuD9EM5iJzWCqQa E73CapZAABSbQZpqoY60QvUSybGZmz91mdjyQNWxOxxP9zmlFj/DDfyRDfuDxCQrOXoHc6 F4vLCrp0NqoMTv7ZZ+oQ14FuMB/pAXHgv8FFT+DGRyRnAV8EhI6Ifqgj1Y00PEwizobK+A 6M9Gt+0gtMUOhV10JZZj2f/+TE9Ue+jLS5X54+zbASHYV+b7CZjUZNLrSgJ5V2FAResUo5 IEFs5/zU/QXTt7A/F84j/prChDSeQL1X2/7B2VdhOXGh6e7tuH0Dx7Q== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=e Rs7Nx22YOQkSo3nfdsN3O8p4gxxy+RQUr+QOagrgLk=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=Yrk4w5VX31BZKFuIWgs38plpfTVfZDi98G1/g8NsYa0oE0fWuPlHwzmTYuCIDlB0zGU7 cC9qgS/1IgMe8JwvlH6DNpmq61UFC9IIL2wZzOwe51eQUQ/eS+qlM5iZQKWDNvnqsefezh 4/o5lwkeHw0LmJyPim1URBOxZGsAFZt1esaFJ0c+XRn9C1x0TLHAxLdae/nWKNELgaon6T nIjRF2V4iheW7i/b4RL5TuN+k0dxsN7jUoiKgbh9W1EVO/gN3ODCHQtfThZlfkBaZL7mso bub+Va4+/0cE1SaaaRqjkBXZ/cmrCncv9X1G92a+lLPB6FPbPmCW9zOY6Ayuc2Rw== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=fPGQ2uJ2; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=4OkcnKlM; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=eRs7Nx22 YOQkSo3nfdsN3O8p4gxxy+RQUr+QOagrgLk=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=fPGQ2uJ2nUT/4eq6BE3u96FwDU5rj0aajX2 4LMwPh1zHK6KTttPgynGHxrPMFaFjq5LyT2H+gMik681QcYsvyN2d+kX0DfEyTXNQpDiuA 2zzEy4aiDJ0kneIZv4jblyRNRCXR65/1Q1Rbj75Q+a608zCRrAJk2ndmruR0l+JWpMNdLS BD+0t1UHYrLIeYoM1EG80KCMtiEtqjX978ozfon3AhewbdnE/L6yxhs4pF6YKr4Nu+eNqD ZIZiPtLPDEXoxoGvUBZx2/quRH5IGxt+S9hlbMZbsHLkLkKxKXaABzDHzr7irBbBUXEGOI Gj8MncV87zyKPtln93XTy9v5uEQ== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=eRs7Nx22YOQkSo3nfdsN3O8p4gxxy+RQUr+QOagrgLk=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=4OkcnKlMPl8TmTOgoK a5CymBWWB94h3eFTOM8NLEw6OI3OcIOKfSgUSq7kJgUjEyPRwvbVgMi0poURfRD4GPAQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 07/25] target/mips: allow Octeon unaligned accesses Date: Thu, 3 Sep 2026 14:01:55 +0200 Message-ID: <20260903120510.34876-8-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437239974158501 Content-Type: text/plain; charset="utf-8" Octeon firmware performs unaligned memory accesses during early DDR setup. Use QEMU's unaligned memory operation mode for Octeon translations, matching the existing treatment for MIPS R6 and Loongson3A. --- target/mips/tcg/translate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 123ba6aecd..d83f76e514 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -15193,6 +15193,7 @@ static void mips_tr_init_disas_context(DisasContext= Base *dcbase, CPUState *cs) #endif ctx->default_tcg_memop_mask =3D (!(ctx->insn_flags & ISA_NANOMIPS32) && (ctx->insn_flags & (ISA_MIPS_R6 | + INSN_OCTEON | INSN_LOONGSON3A))) ? MO_UNALN : MO_ALIGN; if (tb_flags & TB_FLAG_MIPS_FIXADE) { ctx->default_tcg_memop_mask =3D MO_UNALN; --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437210900530.6592226727652; Thu, 3 Sep 2026 05:06:50 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CG-0002tM-3E; Thu, 03 Sep 2026 08:05:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CE-0002sa-6U for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:34 -0400 Received: from mx1.catap.net ([2a01:4f8:271:125e::2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CC-0005L8-2k for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:33 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 0836436d (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:26 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id c3179195; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=zX2UcBH M9BQwVjanXFFNdJQN47+mJluOC2HuhJkic9gEiYihQ0xI+iWoovGPltVEsM52u4V2Rjflh dIXhXpEFpFjIufgcIaquIbnEX1tDJLiqJ5hyPsf0ONDjg/XfyN6pqsdm04ll4//KPBK9D4 juQssL3RfB9gz7nZx0Oung1qJpfm2OhsRLt17GcX9k0/beYuc0auUj21eT1lHuWmmFZgKj 77/NVaQPUIm8f933ZES1uTl3gM5dy4VNjBDp/RefgwRJ8MRG29FnofmXl+o4bg0bt5dbL5 4O9bPfmp855x6GOlfygRo/Q/FEBOq2JRZbkd3MKmqDJJCIjPluklTeQ== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=X tIA9Ar5ZgIs23Ony7XidFljjxuzUWLCKn7hmGG08Pg=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=PJbq47SKkT+ekFBzf1R4MTSrVNTuQ2ooahVf0ZaFc1IrQpi1yOVqn/mY1E4s9WUA40gG D8ILP5sFQemDbAyLQF7VdPDWF6D7o4nQfbUKmiAzZ0pm4rGZVCKnWLJXYeLRfrIpUYlGsL fCSveP+5YMItJxeoEY7n02vdueQAzh/4S4NWVu2RqOyh+a4+ucLyKtIYG2VgIo05uRDHoE BTCWrLQWcuZzhxkcm0WeyNlhdnS02xLtD5RGOZF/0gLi8iHnVbjh/eBHsUspBnUsxIWwSO LmeQosZnOWgF8HMeu317WvyEqXLITe3IY4Av/wCTe6cTG5bEgWwhj8hDV3KGKNKw== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=HzA+gLcS; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=B0B1TYeO; arc=none; iprev=fail; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=XtIA9Ar5 ZgIs23Ony7XidFljjxuzUWLCKn7hmGG08Pg=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=HzA+gLcSEb2eVdcOec2fD6CYCu7dg7ESGBm eJEv4Y6WI7fMDL71jKL7PkmhJTjWdEemIZU6KtaUiVk7ravsHrbPaL4aVUJQHooHQBjXGb L0KpuJdzbetNQMH/c1qEyL+UyqZpxB8N2xTBavmp2M+oOzQ7Sqclaz5hD/coLpb9LOcFuv /lhyGVpWfgAOGdGgPmQf8pFp34iKXJBGO1fMSWQFTg6XDyfwacIhfWxlifgbQyeb4QHbKW nJKHXyioz7KtVHx6W4Dur+cu0NVEMSMUnRdvFgpSGgUPO56A8AzAVPsDzv85aFgnuzeZg2 9X8NnPIJdNCkcUpM6eIkDJkwO6w== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=XtIA9Ar5ZgIs23Ony7XidFljjxuzUWLCKn7hmGG08Pg=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=B0B1TYeOv+Op5ojDSP x2iZWDiQ1vLDskJ3RFpTfT2ZYevSzAPQsZRicpDwiyabLpaBEHLCVaUgmPA0967l8WCg== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 08/25] hw/mips: add empty Octeon III machine Date: Thu, 3 Sep 2026 14:01:56 +0200 Message-ID: <20260903120510.34876-9-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a01:4f8:271:125e::2; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437213950158500 Content-Type: text/plain; charset="utf-8" Register an empty octeon3 machine for the Cavium/Marvell Octeon III EBB7304 evaluation board. Define its CPU, RAM and clock defaults; later commits add the board devices. Early Octeon investigation used Amir Mehmood's original Octeon host.patch as a behavioral reference; that work informed the basic machine approach and several hardware model ideas. No code from that patch remains in this implementation. --- hw/mips/Kconfig | 5 +++ hw/mips/meson.build | 1 + hw/mips/octeon.c | 89 +++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 16 +++++++ 4 files changed, 111 insertions(+) create mode 100644 hw/mips/octeon.c create mode 100644 hw/mips/octeon_internal.h diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index b59cb2f111..2e71e6dee6 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -67,6 +67,11 @@ config LOONGSON3V select FW_CFG_MIPS select UNIMP =20 +config MIPS_OCTEON + bool + default y + depends on MIPS64 && TARGET_BIG_ENDIAN + config MIPS_CPS bool select MIPS_ITU if TCG diff --git a/hw/mips/meson.build b/hw/mips/meson.build index 390f0fd7f9..f11dcdf794 100644 --- a/hw/mips/meson.build +++ b/hw/mips/meson.build @@ -10,6 +10,7 @@ if 'CONFIG_TCG' in config_all_accel mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: files('boston.c')) +mips_ss.add(when: 'CONFIG_MIPS_OCTEON', if_true: files('octeon.c')) endif =20 hw_arch +=3D {'mips': mips_ss} diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c new file mode 100644 index 0000000000..2ecc464579 --- /dev/null +++ b/hw/mips/octeon.c @@ -0,0 +1,89 @@ +/* + * QEMU Cavium Octeon board model. + * + * Copyright (c) 2026 Kirill A. Korinsky + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "hw/core/boards.h" +#include "hw/core/qdev-properties.h" +#include "hw/mips/octeon_internal.h" +#include "target/mips/cpu.h" + +#define TYPE_OCTEON_MACHINE MACHINE_TYPE_NAME("octeon3") +OBJECT_DECLARE_SIMPLE_TYPE(OcteonMachineState, OCTEON_MACHINE) + +#define OCTEON_DEFAULT_CPU_HZ 1800000000 +#define OCTEON_DEFAULT_REF_HZ 50000000 +#define OCTEON_DEFAULT_IO_HZ 1000000000 +#define OCTEON_DEFAULT_DDR_HZ 800000000 +#define OCTEON_DEFAULT_RAM_SIZE (1 * GiB) + +struct OcteonMachineState { + MachineState parent_obj; + uint64_t cpu_hz; + uint64_t ref_hz; + uint64_t io_hz; + uint64_t ddr_hz; +}; + +static void mips_octeon_init(MachineState *machine) +{ +} + +static void octeon_machine_instance_init(Object *obj) +{ + OcteonMachineState *oms =3D OCTEON_MACHINE(obj); + + oms->cpu_hz =3D OCTEON_DEFAULT_CPU_HZ; + oms->ref_hz =3D OCTEON_DEFAULT_REF_HZ; + oms->io_hz =3D OCTEON_DEFAULT_IO_HZ; + oms->ddr_hz =3D OCTEON_DEFAULT_DDR_HZ; + + object_property_add_uint64_ptr(obj, "cpu-clock-hz", &oms->cpu_hz, + OBJ_PROP_FLAG_READWRITE); + object_property_set_description(obj, "cpu-clock-hz", + "CPU clock frequency in Hz"); + + object_property_add_uint64_ptr(obj, "ref-clock-hz", &oms->ref_hz, + OBJ_PROP_FLAG_READWRITE); + object_property_set_description(obj, "ref-clock-hz", + "Reference clock frequency in Hz"); + + object_property_add_uint64_ptr(obj, "io-clock-hz", &oms->io_hz, + OBJ_PROP_FLAG_READWRITE); + object_property_set_description(obj, "io-clock-hz", + "IO clock frequency in Hz"); + + object_property_add_uint64_ptr(obj, "ddr-clock-hz", &oms->ddr_hz, + OBJ_PROP_FLAG_READWRITE); + object_property_set_description(obj, "ddr-clock-hz", + "DDR clock frequency in Hz"); +} + +static void octeon_machine_class_init(ObjectClass *oc, const void *data) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "Cavium Octeon III / EBB7304 EVK"; + mc->init =3D mips_octeon_init; + mc->default_cpu_type =3D MIPS_CPU_TYPE_NAME("OcteonCN73XX"); + mc->default_ram_size =3D OCTEON_DEFAULT_RAM_SIZE; + mc->default_ram_id =3D "octeon.ram"; + mc->max_cpus =3D OCTEON_MAX_CPUS; +} + +static const TypeInfo octeon_machine_types[] =3D { + { + .name =3D TYPE_OCTEON_MACHINE, + .parent =3D TYPE_MACHINE, + .instance_size =3D sizeof(OcteonMachineState), + .instance_init =3D octeon_machine_instance_init, + .class_init =3D octeon_machine_class_init, + } +}; + +DEFINE_TYPES(octeon_machine_types) diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h new file mode 100644 index 0000000000..7cab7790bd --- /dev/null +++ b/hw/mips/octeon_internal.h @@ -0,0 +1,16 @@ +/* + * QEMU Cavium Octeon board model internal declarations. + * + * Copyright (c) 2026 Kirill A. Korinsky + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MIPS_OCTEON_INTERNAL_H +#define HW_MIPS_OCTEON_INTERNAL_H + +#include "qemu/typedefs.h" + +#define OCTEON_MAX_CPUS 16 + +#endif --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437149428700.5974302481222; Thu, 3 Sep 2026 05:05:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CG-0002tx-P3; Thu, 03 Sep 2026 08:05:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CF-0002t9-Js for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:35 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CD-0005LJ-3e for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:35 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 992f30ee (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:26 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 2527561b; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=BvUdU9z nOeRDQlVJYSpCTRqRhjTHrwOWwu22Igxm0+WmNyrE6wOrDb89rGe+oogEY+vFQYnvkmh6Q /M6mBk08yVOH1v5hZbr40kPBA1mwUP5sVEeeR5KM0kVG/ZHswO3wDdd+vltdyuyesUZg6S PCpKBIWaGy7LLkvLiRkHDoWlwEIpzmgQwoVuK41jGrl3/hJ1H1j5zsZNCikZpMleYAVLLc qscWP/zSZlOIYnlG3+JhhZsHHcsUp1oj0siP150FLdV5HMQ3NyZTl9jDar1m0Dfky/uSaP 99x58MTWqFATCxCdtIyI6cj2NhGQ7pR6IQQFfHIw4zZ1hJhqx7U9+bw== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=G MaKr/KogLZ4MDb9MBe81a4oJC21q9KkOxQeOIuC28I=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=MpLBdi8/wJcMqMc/K57WJ4Bu5jqlddHatGePjOmOZgdfvYOP5OXQAaebjaTnyfebHwZC /iKbAabeRRVx07SLLktJZpWASTpXpoTP+wsgGIDOeQ48wHdpljVsQ+whcDwS51OCCEvqgr S0jrZiNBasVdNUdcaWcn5QpaDmdvEJoAauS8eTXekoHFzZ3KS1mn8t/sBqxqVsoRkxc8Ex 79xjPWe6O1ORTgY/3f9wDwugwB8WLn2P3BYevu8ap3i05G5htgeZ9C7zPaO3EhjAgKRTSe zSvwjv9gLg3m2uhpG8gG8t5h9weGSFjq6T9pAfDo5KWvLZuvvlI7zfoIhDzKO2Hw== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=S93VMW/Q; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=BsO21RXW; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=GMaKr/Ko gLZ4MDb9MBe81a4oJC21q9KkOxQeOIuC28I=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=S93VMW/Q78myjKErXnfgbhdZS5Ou3YK7ToZ GAS0pm4+JVl5fgRKxn8OFS7qKf1aREMbBt87S58M8yt4BjQAcy+qGRpDk/CukPrx7iJXtf 1uvPRQ/Oc7V/XWXiayR16QD446FZ46fUU4dvVqCo0c9gah/EnjRdaLY0CJisYnyVXI85Oa +l/kJOYFMvv4KovtvfmQV11T9U44LddsSp0xgAHpEjL5GRI0mQG54M2VxWBgP8gYe7CR/t m3eIpzqXaYhRXcajeXy+rtb3mVk0Rcw/Wo2BYtF/RycUkw3mOS5/s8ImFzMiPRHnGisYpm +ylioaIifkRTu1Ru9NvTHsBTzRw== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=GMaKr/KogLZ4MDb9MBe81a4oJC21q9KkOxQeOIuC28I=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=BsO21RXWM49xcalRHF ORpuzoB7PEpUumMGgbBeIlO0mPEy3w8P4p2Fl8Ooa/ugWsWav+OaLg5uSptMBNdM8nBA== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 09/25] hw/mips: add Octeon CPUs and boot memory Date: Thu, 3 Sep 2026 14:01:57 +0200 Message-ID: <20260903120510.34876-10-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437152512158500 Content-Type: text/plain; charset="utf-8" Create the Octeon CPUs and clock, map the split DRAM layout and per-core CVMSEG storage, and provide the EBB7304 boot flash windows. Load firmware into the flash reset alias and restore the boot PC during machine reset. --- hw/mips/Kconfig | 1 + hw/mips/octeon.c | 308 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 28 ++++ 3 files changed, 337 insertions(+) diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 2e71e6dee6..cb6057fe38 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -71,6 +71,7 @@ config MIPS_OCTEON bool default y depends on MIPS64 && TARGET_BIG_ENDIAN + select PFLASH_CFI02 =20 config MIPS_CPS bool diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 2ecc464579..0e02d3693d 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -8,30 +8,337 @@ =20 #include "qemu/osdep.h" #include "qemu/units.h" +#include "qemu/datadir.h" +#include "qapi/error.h" +#include "hw/core/clock.h" #include "hw/core/boards.h" +#include "hw/core/qdev-clock.h" #include "hw/core/qdev-properties.h" +#include "hw/core/qdev-properties-system.h" +#include "hw/core/sysbus.h" +#include "hw/block/flash.h" +#include "hw/mips/mips.h" +#include "system/blockdev.h" +#include "system/address-spaces.h" +#include "system/memory.h" +#include "system/reset.h" +#include "qemu/error-report.h" #include "hw/mips/octeon_internal.h" #include "target/mips/cpu.h" =20 #define TYPE_OCTEON_MACHINE MACHINE_TYPE_NAME("octeon3") OBJECT_DECLARE_SIMPLE_TYPE(OcteonMachineState, OCTEON_MACHINE) =20 +/* + * Clock defaults follow a Ubiquiti E1000 EBB7304 U-Boot banner. + * DDR follows the upstream EBB7304 U-Boot board default. + */ #define OCTEON_DEFAULT_CPU_HZ 1800000000 #define OCTEON_DEFAULT_REF_HZ 50000000 #define OCTEON_DEFAULT_IO_HZ 1000000000 #define OCTEON_DEFAULT_DDR_HZ 800000000 + +/* + * The physical layout follows U-Boot's generic Octeon III + * OCTEON_MAX_PHY_MEM_SIZE value. Keep 1 GiB as the tested default. + */ #define OCTEON_DEFAULT_RAM_SIZE (1 * GiB) +#define OCTEON_MAX_PHY_MEM_SIZE (512 * GiB) + +/* + * The EBB7304 FDT exposes DRAM below and above the + * 0x10000000..0x1fffffff boot-bus/EJTAG hole. + */ +#define OCTEON_DR0_BASE 0x000000000ULL +#define OCTEON_DR0_SIZE (256 * MiB) +#define OCTEON_DR1_BASE 0x020000000ULL +#define OCTEON_DR1_SIZE (OCTEON_MAX_PHY_MEM_SIZE - OCTEON_DR0_= SIZE) + +/* + * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; + * the guest sees the virtual CVMSEG window, not this physical address. + */ +#define OCTEON_CVMSEG_BASE 0x10000000000ULL +#define OCTEON_CVMSEG_SIZE 0x4000 +#define OCTEON_CVMSEG_TOTAL_SIZE (OCTEON_MAX_CPUS * OCTEON_CVMSEG_SIZE) + +#define OCTEON_FLASH_BASE 0x1f400000ULL +#define OCTEON_FLASH_RESET_BASE 0x1fc00000ULL +#define OCTEON_FLASH_RESET_SIZE (4 * MiB) +#define OCTEON_FLASH_MAIN_SECTORS 127 +#define OCTEON_FLASH_MAIN_SECTOR_SIZE (64 * KiB) +#define OCTEON_FLASH_ENV_SECTORS 8 +#define OCTEON_FLASH_ENV_SECTOR_SIZE 0x2000 +#define OCTEON_FLASH_SIZE \ + (OCTEON_FLASH_MAIN_SECTORS * OCTEON_FLASH_MAIN_SECTOR_SIZE + \ + OCTEON_FLASH_ENV_SECTORS * OCTEON_FLASH_ENV_SECTOR_SIZE) +#define OCTEON_FLASH_ENV_OFFSET \ + (OCTEON_FLASH_SIZE - OCTEON_FLASH_ENV_SECTOR_SIZE) +#define OCTEON_FLASH_WIDTH 2 =20 struct OcteonMachineState { MachineState parent_obj; + OcteonState *board; uint64_t cpu_hz; uint64_t ref_hz; uint64_t io_hz; uint64_t ddr_hz; }; =20 +static void octeon_validate_clocks(OcteonMachineState *oms) +{ + if (!oms->cpu_hz || !oms->ref_hz || !oms->io_hz || !oms->ddr_hz) { + error_report("octeon3 clock frequencies must be non-zero"); + exit(1); + } + + if (oms->cpu_hz % oms->ref_hz || oms->io_hz % oms->ref_hz) { + error_report("octeon3 CPU and IO clocks must be multiples of " + "ref-clock-hz"); + exit(1); + } +} + +static void octeon_cpu_after_reset(OcteonCPUState *cs) +{ + CPUMIPSState *env =3D &cs->cpu->env; + + env->CP0_CvmMemCtl =3D 0x100; + env->CP0_CvmCtl =3D 0; + + if (cs->boot_cpu && cs->board->firmware_entry) { + env->active_tc.PC =3D cs->board->firmware_entry; + } +} + +static void octeon_create_cpus(OcteonState *s) +{ + unsigned int i; + + s->cpuclk =3D clock_new(OBJECT(s->machine), "cpu-refclk"); + clock_set_hz(s->cpuclk, s->cpu_hz); + s->cpu_count =3D s->machine->smp.cpus; + for (i =3D 0; i < s->cpu_count; i++) { + DeviceState *dev =3D qdev_new(s->machine->cpu_type); + + s->cpu[i].board =3D s; + s->cpu[i].boot_cpu =3D i =3D=3D 0; + object_property_set_bool(OBJECT(dev), "big-endian", TARGET_BIG_END= IAN, + &error_abort); + object_property_set_bool(OBJECT(dev), "start-powered-off", i !=3D = 0, + &error_abort); + qdev_connect_clock_in(dev, "clk-in", s->cpuclk); + qdev_realize(dev, NULL, &error_abort); + s->cpu[i].cpu =3D MIPS_CPU(dev); + + cpu_mips_irq_init_cpu(s->cpu[i].cpu); + cpu_mips_clock_init(s->cpu[i].cpu); + qemu_register_resettable(OBJECT(dev)); + } +} + +static uint64_t octeon_map_ram_alias(OcteonState *s, MemoryRegion *alias, + const char *name, hwaddr base, + uint64_t offset, uint64_t size) +{ + MemoryRegion *sysmem =3D get_system_memory(); + + if (!size) { + return offset; + } + + memory_region_init_alias(alias, NULL, name, s->machine->ram, offset, s= ize); + memory_region_add_subregion(sysmem, base, alias); + return offset + size; +} + +static void octeon_map_ram(OcteonState *s) +{ + MemoryRegion *sysmem =3D get_system_memory(); + uint64_t offset =3D 0; + uint64_t remaining =3D s->machine->ram_size; + uint64_t size; + + size =3D MIN(remaining, (uint64_t)OCTEON_DR0_SIZE); + offset =3D octeon_map_ram_alias(s, &s->dr0, "octeon.dr0", + OCTEON_DR0_BASE, offset, size); + remaining -=3D size; + + size =3D MIN(remaining, (uint64_t)OCTEON_DR1_SIZE); + octeon_map_ram_alias(s, &s->dr1, "octeon.dr1", + OCTEON_DR1_BASE, offset, size); + + memory_region_init_ram(&s->cvmseg, NULL, "octeon.cvmseg", + OCTEON_CVMSEG_TOTAL_SIZE, &error_fatal); + memory_region_add_subregion(sysmem, OCTEON_CVMSEG_BASE, &s->cvmseg); +} + +static void octeon_load_firmware(OcteonState *s) +{ + g_autofree char *filename =3D NULL; + g_autofree gchar *contents =3D NULL; + g_autoptr(GError) err =3D NULL; + gsize len; + uint8_t *flash; + + if (!s->machine->firmware) { + return; + } + if (!s->flash) { + error_report("Octeon boot flash is not initialized"); + exit(1); + } + + filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, s->machine->firmware); + if (!filename) { + error_report("Could not find Octeon firmware '%s'", + s->machine->firmware); + exit(1); + } + + if (!g_file_get_contents(filename, &contents, &len, &err)) { + error_report("Could not load Octeon firmware '%s': %s", + filename, err->message); + exit(1); + } + + if (len =3D=3D 0 || len > OCTEON_FLASH_ENV_OFFSET) { + error_report("Octeon firmware '%s' has invalid size %" G_GSIZE_FOR= MAT, + filename, len); + exit(1); + } + + flash =3D memory_region_get_ram_ptr(s->flash); + memcpy(flash, contents, len); + s->firmware_entry =3D cpu_mips_phys_to_kseg1(NULL, OCTEON_FLASH_RESET_= BASE); +} + +static MemTxResult octeon_boot_flash_read(void *opaque, hwaddr addr, + uint64_t *data, unsigned size, + MemTxAttrs attrs) +{ + OcteonState *s =3D opaque; + uint8_t buf[8]; + MemTxResult result =3D MEMTX_OK; + unsigned int i; + + for (i =3D 0; i < size; i++) { + uint64_t value; + + result |=3D memory_region_dispatch_read(s->flash, addr + i, &value, + MO_8, attrs); + buf[i] =3D value; + } + *data =3D ldn_be_p(buf, size); + return result; +} + +static MemTxResult octeon_boot_flash_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size, + MemTxAttrs attrs) +{ + OcteonState *s =3D opaque; + unsigned access_size =3D MIN(size, 4); + + if (size > access_size) { + access_size =3D OCTEON_FLASH_WIDTH; + } + return memory_region_dispatch_write(s->flash, addr, value, + size_memop(access_size) | MO_BE, + attrs); +} + +static const MemoryRegionOps octeon_boot_flash_ops =3D { + .read_with_attrs =3D octeon_boot_flash_read, + .write_with_attrs =3D octeon_boot_flash_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + }, +}; + +static void octeon_init_flash(OcteonState *s) +{ + DriveInfo *dinfo =3D drive_get(IF_PFLASH, 0, 0); + DeviceState *dev; + uint8_t *flash; + + dev =3D qdev_new(TYPE_PFLASH_CFI02); + if (dinfo) { + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); + } + qdev_prop_set_uint32(dev, "num-blocks0", OCTEON_FLASH_MAIN_SECTORS); + qdev_prop_set_uint32(dev, "sector-length0", + OCTEON_FLASH_MAIN_SECTOR_SIZE); + qdev_prop_set_uint32(dev, "num-blocks1", OCTEON_FLASH_ENV_SECTORS); + qdev_prop_set_uint32(dev, "sector-length1", + OCTEON_FLASH_ENV_SECTOR_SIZE); + qdev_prop_set_uint8(dev, "width", OCTEON_FLASH_WIDTH); + qdev_prop_set_uint8(dev, "mappings", 1); + qdev_prop_set_uint8(dev, "big-endian", TARGET_BIG_ENDIAN); + qdev_prop_set_uint16(dev, "id0", 0x01); + qdev_prop_set_uint16(dev, "id1", 0x7e); + qdev_prop_set_uint16(dev, "id2", 0x00); + qdev_prop_set_uint16(dev, "id3", 0x00); + qdev_prop_set_uint16(dev, "unlock-addr0", 0x555); + qdev_prop_set_uint16(dev, "unlock-addr1", 0x2aa); + qdev_prop_set_string(dev, "name", "octeon.bootbus-flash"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + s->flash =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + if (!dinfo) { + flash =3D memory_region_get_ram_ptr(s->flash); + memset(flash, 0xff, OCTEON_FLASH_SIZE); + } + memory_region_init_io(&s->boot_flash, NULL, &octeon_boot_flash_ops, s, + "octeon.bootbus-flash-window", OCTEON_FLASH_SIZE= ); + memory_region_add_subregion(get_system_memory(), OCTEON_FLASH_BASE, + &s->boot_flash); + + memory_region_init_alias(&s->boot_flash_alias, NULL, + "octeon.bootbus-flash-reset-alias", + &s->boot_flash, 0, OCTEON_FLASH_RESET_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_FLASH_RESET_BA= SE, + &s->boot_flash_alias); +} + static void mips_octeon_init(MachineState *machine) { + OcteonMachineState *oms =3D OCTEON_MACHINE(machine); + OcteonState *s =3D g_new0(OcteonState, 1); + + octeon_validate_clocks(oms); + + oms->board =3D s; + s->machine =3D machine; + s->cpu_hz =3D oms->cpu_hz; + s->ref_hz =3D oms->ref_hz; + s->io_hz =3D oms->io_hz; + s->ddr_hz =3D oms->ddr_hz; + + if (machine->kernel_filename) { + error_report("-kernel is not implemented for octeon3; " + "boot via -bios and U-Boot"); + exit(1); + } + + octeon_map_ram(s); + octeon_init_flash(s); + octeon_load_firmware(s); + octeon_create_cpus(s); + +} + +static void octeon_machine_reset(MachineState *machine, ResetType type) +{ + OcteonState *s =3D OCTEON_MACHINE(machine)->board; + unsigned int i; + + qemu_devices_reset(type); + for (i =3D 0; i < s->cpu_count; i++) { + octeon_cpu_after_reset(&s->cpu[i]); + } } =20 static void octeon_machine_instance_init(Object *obj) @@ -70,6 +377,7 @@ static void octeon_machine_class_init(ObjectClass *oc, c= onst void *data) =20 mc->desc =3D "Cavium Octeon III / EBB7304 EVK"; mc->init =3D mips_octeon_init; + mc->reset =3D octeon_machine_reset; mc->default_cpu_type =3D MIPS_CPU_TYPE_NAME("OcteonCN73XX"); mc->default_ram_size =3D OCTEON_DEFAULT_RAM_SIZE; mc->default_ram_id =3D "octeon.ram"; diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 7cab7790bd..2e568c29ea 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -10,7 +10,35 @@ #define HW_MIPS_OCTEON_INTERNAL_H =20 #include "qemu/typedefs.h" +#include "system/memory.h" +#include "target/mips/cpu.h" =20 #define OCTEON_MAX_CPUS 16 +typedef struct OcteonState OcteonState; + +typedef struct OcteonCPUState { + OcteonState *board; + MIPSCPU *cpu; + bool boot_cpu; +} OcteonCPUState; + +struct OcteonState { + MachineState *machine; + Clock *cpuclk; + uint64_t cpu_hz; + uint64_t ref_hz; + uint64_t io_hz; + uint64_t ddr_hz; + OcteonCPUState cpu[OCTEON_MAX_CPUS]; + unsigned int cpu_count; + uint64_t firmware_entry; + + MemoryRegion dr0; + MemoryRegion dr1; + MemoryRegion *flash; + MemoryRegion boot_flash; + MemoryRegion boot_flash_alias; + MemoryRegion cvmseg; +}; =20 #endif --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437272700814.4919996237469; Thu, 3 Sep 2026 05:07:52 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CI-0002ud-FK; Thu, 03 Sep 2026 08:05:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CF-0002t0-5g for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:35 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CD-0005JF-7H for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:34 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 83d4bc85 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:26 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id bc3d2505; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=dP7nqBt A0cGC0E+yz0SCwQ460M0lkKu8MSO10A+alOEuHHm6yq2X8YtTEDPxSBb28TJKkVPPpKIIp dsLuDUXm3CS5lNu1NpV91+dXfXDXpgZ582lfA7HiyaV9wKW35/Ftubw4Ea2HHFuXgIc5Sj tYBmciYNrmeOG/9PB1MYMzrbbCweOuvTqpweB+8JF4C2fk01FWbuOW+m7UqOibljIw3hwN c4SgJe2A2NGmj0Ik1gx1McmhXCVJW4c2XCuiteOIbofqqXDJvLBSsppka0mg4G9Fpckm17 huOCbvU8uTRkKb45KBXIGQqLOnyIEba1QAsypZRTolOs6fBxv9S2k3Q== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=R hL2WKJct0UW7HSikSYL87UX23u1K8iS0O8O6sR/NpI=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=GFQFFaluxP6KCut1eI1xjR4jo1zllDKRMjhqoblaOW6eOuvQRowohmI3ZOZBtnQOqpRk xODEaDUQ/Zito3/AWGOV0FK4BZw05VD8U7QYb7gr07R4urdUqAsodOsgk+RWhzq487VFjo ao2xjThvPM4ctkJppC6grq4DdJwSKksngjTMIRv+J5lKs0dfOh0kl4JcITQStVup8FX4yN ZX/sZ2+WsuyN7nzMHGF+OF31xbbJuwnWIKHXc5+g/6ngJGud3tZPBVAsErcGyefw7CTO1B UZJUjrjx82bHYSJ1dvoETmOIrdu/MR70kOC7R8SVDOqA7OjGjV7PzkuWLSLcnhCg== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=J2uYES55; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=RM4X252P; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=RhL2WKJc t0UW7HSikSYL87UX23u1K8iS0O8O6sR/NpI=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=J2uYES55TacZXJL0kXt1i7btpEezr22XEW2 KbtGRF2+GnAQ4Q4qmRTO9DEpTn62xKFR9wmBJGjlOeSJBy9d3z/IOkBS5nRqayAtpwAr9K Lc+ppCQ7GP7ywRnTgCAc7kWdPqL+lJzE3kPjWgLeL3FyR4pwqziV169FBhZ0QM6s1zpqFx aNK2VxWDvg/JMOTPc/bDKxwiixFtOu00rb0fLPA82irT+in8gVasQ0el9GXZuawN5J72hU p+ladyY/p2o3pUANqSQI+E++ZqoC+crIXkno3BjmYFEWA4+ioDU+0mLHQijR9Saf5sPbM8 uPRYhg2yWNnJicBOFdMGuCVyW4w== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=RhL2WKJct0UW7HSikSYL87UX23u1K8iS0O8O6sR/NpI=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=RM4X252P7ceicLiFNo 13Ms7prTkzV5v2FeHWfhY5OWk2nuZdVnTZ5d1/RaDQYVKd6YVv+RYldTXIgUq/jPrqCQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 10/25] hw/mips: add Octeon reset controller Date: Thu, 3 Sep 2026 14:01:58 +0200 Message-ID: <20260903120510.34876-11-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437274180158500 Content-Type: text/plain; charset="utf-8" Add the common resettable peripheral base and model the Octeon RST state used to hold secondary cores in reset. Create and realize the controller as part of the machine without exposing its CSR interface yet. --- hw/mips/octeon.c | 105 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 2 + 2 files changed, 107 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 0e02d3693d..4fc5a71a90 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -29,6 +29,13 @@ #define TYPE_OCTEON_MACHINE MACHINE_TYPE_NAME("octeon3") OBJECT_DECLARE_SIMPLE_TYPE(OcteonMachineState, OCTEON_MACHINE) =20 +#define TYPE_OCTEON_PERIPHERAL "octeon-peripheral" +OBJECT_DECLARE_TYPE(OcteonPeripheralState, OcteonPeripheralClass, + OCTEON_PERIPHERAL) + +#define TYPE_OCTEON_RST "octeon-rst" +OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST) + /* * Clock defaults follow a Ubiquiti E1000 EBB7304 U-Boot banner. * DDR follows the upstream EBB7304 U-Boot board default. @@ -85,6 +92,22 @@ struct OcteonMachineState { uint64_t ddr_hz; }; =20 +struct OcteonPeripheralState { + SysBusDevice parent_obj; + OcteonState *board; + unsigned int index; +}; + +struct OcteonPeripheralClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + +struct OcteonRstState { + OcteonPeripheralState parent_obj; + uint64_t rst_pp_power; +}; + static void octeon_validate_clocks(OcteonMachineState *oms) { if (!oms->cpu_hz || !oms->ref_hz || !oms->io_hz || !oms->ddr_hz) { @@ -99,6 +122,16 @@ static void octeon_validate_clocks(OcteonMachineState *= oms) } } =20 +static uint64_t octeon_present_cpu_mask(OcteonState *s) +{ + return (1ULL << s->cpu_count) - 1; +} + +static uint64_t octeon_secondary_cpu_mask(OcteonState *s) +{ + return octeon_present_cpu_mask(s) & ~1ULL; +} + static void octeon_cpu_after_reset(OcteonCPUState *cs) { CPUMIPSState *env =3D &cs->cpu->env; @@ -303,6 +336,62 @@ static void octeon_init_flash(OcteonState *s) &s->boot_flash_alias); } =20 +static void octeon_rst_reset_hold(Object *obj, ResetType type) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); + OcteonRstState *rst =3D OCTEON_RST(obj); + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + rst->rst_pp_power =3D octeon_secondary_cpu_mask(rst->parent_obj.board); +} + +static void octeon_peripheral_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->user_creatable =3D false; +} + +static void octeon_rst_class_init(ObjectClass *klass, const void *data) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + resettable_class_set_parent_phases(rc, NULL, octeon_rst_reset_hold, + NULL, &opc->parent_phases); +} + +static OcteonPeripheralState *octeon_new_peripheral(OcteonState *s, + const char *type, + unsigned int index) +{ + DeviceState *qdev =3D qdev_new(type); + OcteonPeripheralState *dev =3D OCTEON_PERIPHERAL(qdev); + + dev->board =3D s; + dev->index =3D index; + return dev; +} + +static void octeon_create_peripherals(OcteonState *s) +{ + s->rst =3D OCTEON_RST(octeon_new_peripheral(s, TYPE_OCTEON_RST, 0)); +} + +static void octeon_realize_peripheral(OcteonPeripheralState *dev) +{ + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); +} + +static void octeon_realize_peripherals(OcteonState *s) +{ + octeon_realize_peripheral(&s->rst->parent_obj); +} + static void mips_octeon_init(MachineState *machine) { OcteonMachineState *oms =3D OCTEON_MACHINE(machine); @@ -316,6 +405,7 @@ static void mips_octeon_init(MachineState *machine) s->ref_hz =3D oms->ref_hz; s->io_hz =3D oms->io_hz; s->ddr_hz =3D oms->ddr_hz; + octeon_create_peripherals(s); =20 if (machine->kernel_filename) { error_report("-kernel is not implemented for octeon3; " @@ -328,6 +418,7 @@ static void mips_octeon_init(MachineState *machine) octeon_load_firmware(s); octeon_create_cpus(s); =20 + octeon_realize_peripherals(s); } =20 static void octeon_machine_reset(MachineState *machine, ResetType type) @@ -385,6 +476,20 @@ static void octeon_machine_class_init(ObjectClass *oc,= const void *data) } =20 static const TypeInfo octeon_machine_types[] =3D { + { + .name =3D TYPE_OCTEON_PERIPHERAL, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(OcteonPeripheralState), + .class_size =3D sizeof(OcteonPeripheralClass), + .class_init =3D octeon_peripheral_class_init, + .abstract =3D true, + }, + { + .name =3D TYPE_OCTEON_RST, + .parent =3D TYPE_OCTEON_PERIPHERAL, + .instance_size =3D sizeof(OcteonRstState), + .class_init =3D octeon_rst_class_init, + }, { .name =3D TYPE_OCTEON_MACHINE, .parent =3D TYPE_MACHINE, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 2e568c29ea..9c1baee292 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -15,6 +15,7 @@ =20 #define OCTEON_MAX_CPUS 16 typedef struct OcteonState OcteonState; +typedef struct OcteonRstState OcteonRstState; =20 typedef struct OcteonCPUState { OcteonState *board; @@ -39,6 +40,7 @@ struct OcteonState { MemoryRegion boot_flash; MemoryRegion boot_flash_alias; MemoryRegion cvmseg; + OcteonRstState *rst; }; =20 #endif --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437252712140.47340502323664; Thu, 3 Sep 2026 05:07:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CV-00037b-M3; Thu, 03 Sep 2026 08:05:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CG-0002tw-LN for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:36 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CE-0005Ja-2T for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:36 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 5519d0a9 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:27 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 43e10229; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=oNbwPQf DuGXPWUIffOncdaBk33gVnS8VCiJXbyAWPW+2o4eBQ9q1pt7YWgf+TVMPVWC7MkWE7HX0g O2+WSHIGo2HW5dUzOl/bOcKvCeM8TqTeyEQcpmNBPQyjrtdZOzgCe3FOp4Fzz7A2e233sD tLn1LB5+ZxawjSX/l+zuIQcFy615lFGUUObr8VzyYuUu95TllIUBl+ZCvSnkskTP35TjpX EY6kSEULbr58Syo58uWTcJUX27HPDQWzYNOhFrYxWgA0CwerEm9k9nphs+llKlWyHpCrYA uTYbE4c7Kt7+zy7Da4Vg5dcSkCKCM3AX0v75PqdiJZOvRFikt4e2AwA== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=H XFWpvE5gXR7SxSPG0Dfu9JhZ5XS5tm8GzpRdrzMyf0=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=apJcf6jd/pbhrMGTFOlrAd2Z/QwDNPZTfVHOQFyaqYIb6z4/L843tpwylW4K/JU6qj/N ZudeavNtj1Qd4ZUM8CvnZZxchW/izeicpbI1TIKPJryly2JmI8gxXzU636q1nUvvn0nXu6 WlzjXzINf+lsz/WobGKPm4vfhDRy6dyQ7b276mui7fKzCIQbuTn6J10IYSMwMYmpNhl4KC l2RV8NnZ0DQHrP/wtUNaWhgkwzbkwCdd2VRwA/ap+1eXPAo/XIiezSHM8SYbiviUo8LDeN 8NvQH/0xECixA4Xi10rN1+ZGpjk1PZSuDMZ9SHhJStVZB9c0Bs/XVAcnRwJbL1Hg== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=AvelHhqp; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=JJcQIkQA; arc=none; iprev=fail; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=HXFWpvE5 gXR7SxSPG0Dfu9JhZ5XS5tm8GzpRdrzMyf0=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=AvelHhqpYQ1Z1CA90ktmnS2ihHw3OGkBf6u t4VseKPy/hE2tiPcU8F6uE2FiUg+LPvC5nTNKSd35RgREttqMaMfZK+LOwiy2fnlMJJiTT bPcr8gjXYG3XVsExziTP95tzSlzsFGzeq5RVRJ3C+h1MVBtsaKlSPJqwhVtd3Io+ptWmh9 WtQwB7fFNtPfwW6ZCARmIyKB1a2poXdlxkhY6M1ba2d/9a5B2w03An6SyHajbuOMn3nKBf RaIEPlus80rP0pKlrsmL46obxr1W7JKyzEZZWPul88RUkqcspBBp5SJ1zNtHCejyV2uYCL d/8G/dQGa1LE9YcuEYSUsuoQh7w== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=HXFWpvE5gXR7SxSPG0Dfu9JhZ5XS5tm8GzpRdrzMyf0=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=JJcQIkQAgu3U/okT/f D+APf2mDr+zsLQBB5if1EiymLUalACtNF5z0e9/3wheFiGKrhEBcG5pnl4pw+W/WzYAA== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 11/25] hw/mips: add Octeon CIU3 CPU control Date: Thu, 3 Sep 2026 14:01:59 +0200 Message-ID: <20260903120510.34876-12-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437254050158500 Content-Type: text/plain; charset="utf-8" Model the CIU3 CPU reset, NMI and fuse registers. Park secondary cores after reset and release them through the CIU3 reset register or NMI path, while leaving interrupt source routing for a separate change. --- hw/mips/octeon.c | 247 +++++++++++++++++++++++++++++++++++++- hw/mips/octeon_internal.h | 6 + 2 files changed, 252 insertions(+), 1 deletion(-) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 4fc5a71a90..eeca7ca67e 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -20,9 +20,12 @@ #include "hw/mips/mips.h" #include "system/blockdev.h" #include "system/address-spaces.h" +#include "system/cpus.h" #include "system/memory.h" #include "system/reset.h" +#include "exec/cpu-interrupt.h" #include "qemu/error-report.h" +#include "qemu/atomic.h" #include "hw/mips/octeon_internal.h" #include "target/mips/cpu.h" =20 @@ -35,6 +38,10 @@ OBJECT_DECLARE_TYPE(OcteonPeripheralState, OcteonPeriphe= ralClass, =20 #define TYPE_OCTEON_RST "octeon-rst" OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST) +#define TYPE_OCTEON_INTC "octeon-intc" +OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) + +#define OCTEON_CSR_64BIT_SIZE 8 =20 /* * Clock defaults follow a Ubiquiti E1000 EBB7304 U-Boot banner. @@ -61,6 +68,13 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST) #define OCTEON_DR1_BASE 0x020000000ULL #define OCTEON_DR1_SIZE (OCTEON_MAX_PHY_MEM_SIZE - OCTEON_DR0_= SIZE) =20 +#define OCTEON_CIU3_BASE 0x1010000000000ULL +#define OCTEON_CIU3_SIZE 0xb0000000ULL +#define OCTEON_CIU3_PP_RST 0x100 +#define OCTEON_CIU3_PP_RST_PENDING 0x110 +#define OCTEON_CIU3_NMI 0x160 +#define OCTEON_CIU3_FUSE 0x1a0 + /* * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; * the guest sees the virtual CVMSEG window, not this physical address. @@ -108,6 +122,59 @@ struct OcteonRstState { uint64_t rst_pp_power; }; =20 +struct OcteonIntcState { + OcteonPeripheralState parent_obj; + MemoryRegion ciu3; + uint64_t ciu3_pp_rst; +}; + +uint64_t octeon_read64(uint64_t value, hwaddr addr, unsigned size) +{ + if (size =3D=3D 4) { + if (addr & 4) { + return value & 0xffffffffU; + } + return value >> 32; + } + + return value; +} + +uint64_t octeon_write64(uint64_t old, hwaddr addr, + uint64_t value, unsigned size) +{ + if (size =3D=3D 4) { + if (addr & 4) { + return (old & 0xffffffff00000000ULL) | (value & 0xffffffffU); + } + return (old & 0xffffffffULL) | ((value & 0xffffffffU) << 32); + } + + return value; +} + +static uint64_t octeon_atomic_write64(uint64_t *ptr, hwaddr addr, + uint64_t value, unsigned size, + uint64_t and_mask, uint64_t or_mask, + uint64_t *oldp) +{ + uint64_t old; + uint64_t new; + uint64_t cmp =3D qatomic_read(ptr); + + do { + old =3D cmp; + new =3D (octeon_write64(old, addr, value, size) & and_mask) | or_m= ask; + cmp =3D qatomic_cmpxchg(ptr, old, new); + } while (old !=3D cmp); + + if (oldp) { + *oldp =3D old; + } + + return new; +} + static void octeon_validate_clocks(OcteonMachineState *oms) { if (!oms->cpu_hz || !oms->ref_hz || !oms->io_hz || !oms->ddr_hz) { @@ -132,6 +199,140 @@ static uint64_t octeon_secondary_cpu_mask(OcteonState= *s) return octeon_present_cpu_mask(s) & ~1ULL; } =20 +static void octeon_cpu_park_now(MIPSCPU *cpu) +{ + CPUMIPSState *env =3D &cpu->env; + CPUState *cs =3D CPU(cpu); + + env->active_tc.CP0_TCHalt =3D 1; + env->tcs[0].CP0_TCHalt =3D 1; + cs->halted =3D 1; + cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); +} + +static void octeon_cpu_park_work(CPUState *cs, run_on_cpu_data data) +{ + octeon_cpu_park_now(MIPS_CPU(cs)); +} + +static void octeon_cpu_start_work(CPUState *cs, run_on_cpu_data data) +{ + MIPSCPU *cpu =3D MIPS_CPU(cs); + CPUMIPSState *env =3D &cpu->env; + + cpu->mvp->CP0_MVPControl |=3D (1 << CP0MVPCo_EVP); + env->CP0_VPEConf0 |=3D (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); + env->active_tc.CP0_TCHalt =3D 0; + env->tcs[0].CP0_TCHalt =3D 0; + env->active_tc.CP0_TCStatus =3D (1 << CP0TCSt_A); + env->tcs[0].CP0_TCStatus =3D (1 << CP0TCSt_A); + env->active_tc.PC =3D cpu_mips_phys_to_kseg1(NULL, OCTEON_FLASH_RESET_= BASE); + cs->halted =3D 0; + cpu_interrupt(cs, CPU_INTERRUPT_WAKE | CPU_INTERRUPT_EXITTB); +} + +static void octeon_start_cpu(OcteonState *s, unsigned int cpu_index) +{ + MIPSCPU *cpu; + + if (cpu_index >=3D s->cpu_count || !s->cpu[cpu_index].cpu) { + return; + } + + cpu =3D s->cpu[cpu_index].cpu; + async_run_on_cpu(CPU(cpu), octeon_cpu_start_work, RUN_ON_CPU_NULL); +} + +static void octeon_ciu3_start_cpu(OcteonState *s, unsigned int cpu_index) +{ + if (qatomic_read(&s->intc->ciu3_pp_rst) & (1ULL << cpu_index)) { + return; + } + + octeon_start_cpu(s, cpu_index); +} + +static void octeon_ciu3_nmi(OcteonState *s, uint64_t mask) +{ + unsigned int cpu; + + for (cpu =3D 1; cpu < s->cpu_count; cpu++) { + if (mask & (1ULL << cpu)) { + octeon_ciu3_start_cpu(s, cpu); + } + } +} + +static uint64_t octeon_ciu3_read(void *opaque, hwaddr addr, unsigned size) +{ + OcteonState *s =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t value; + + if (reg =3D=3D OCTEON_CIU3_PP_RST) { + return octeon_read64(qatomic_read(&s->intc->ciu3_pp_rst), addr, si= ze); + } + + if (reg =3D=3D OCTEON_CIU3_PP_RST_PENDING) { + return 0; + } + + if (reg =3D=3D OCTEON_CIU3_NMI) { + return 0; + } + + if (reg =3D=3D OCTEON_CIU3_FUSE) { + value =3D octeon_present_cpu_mask(s); + return octeon_read64(value, addr, size); + } + + return 0; +} + +static void octeon_ciu3_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t old; + unsigned int cpu; + + if (reg =3D=3D OCTEON_CIU3_PP_RST) { + value =3D octeon_atomic_write64(&s->intc->ciu3_pp_rst, addr, value= , size, + octeon_present_cpu_mask(s), 0, &old); + + for (cpu =3D 1; cpu < s->cpu_count; cpu++) { + uint64_t mask =3D 1ULL << cpu; + + if (!((old ^ value) & mask)) { + continue; + } + if (value & mask) { + async_run_on_cpu(CPU(s->cpu[cpu].cpu), octeon_cpu_park_wor= k, + RUN_ON_CPU_NULL); + } else { + octeon_ciu3_start_cpu(s, cpu); + } + } + return; + } + + if (reg =3D=3D OCTEON_CIU3_NMI) { + octeon_ciu3_nmi(s, octeon_write64(0, addr, value, size)); + return; + } +} + +static const MemoryRegionOps octeon_ciu3_ops =3D { + .read =3D octeon_ciu3_read, + .write =3D octeon_ciu3_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + static void octeon_cpu_after_reset(OcteonCPUState *cs) { CPUMIPSState *env =3D &cs->cpu->env; @@ -139,7 +340,13 @@ static void octeon_cpu_after_reset(OcteonCPUState *cs) env->CP0_CvmMemCtl =3D 0x100; env->CP0_CvmCtl =3D 0; =20 - if (cs->boot_cpu && cs->board->firmware_entry) { + if (!cs->boot_cpu) { + /* Secondary cores are released by the Octeon reset controller. */ + octeon_cpu_park_now(cs->cpu); + return; + } + + if (cs->board->firmware_entry) { env->active_tc.PC =3D cs->board->firmware_entry; } } @@ -151,6 +358,8 @@ static void octeon_create_cpus(OcteonState *s) s->cpuclk =3D clock_new(OBJECT(s->machine), "cpu-refclk"); clock_set_hz(s->cpuclk, s->cpu_hz); s->cpu_count =3D s->machine->smp.cpus; + qatomic_set(&s->intc->ciu3_pp_rst, octeon_secondary_cpu_mask(s)); + for (i =3D 0; i < s->cpu_count; i++) { DeviceState *dev =3D qdev_new(s->machine->cpu_type); =20 @@ -348,6 +557,19 @@ static void octeon_rst_reset_hold(Object *obj, ResetTy= pe type) rst->rst_pp_power =3D octeon_secondary_cpu_mask(rst->parent_obj.board); } =20 +static void octeon_intc_reset_hold(Object *obj, ResetType type) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); + OcteonIntcState *intc =3D OCTEON_INTC(obj); + OcteonState *s =3D intc->parent_obj.board; + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + qatomic_set(&intc->ciu3_pp_rst, octeon_secondary_cpu_mask(s)); +} + static void octeon_peripheral_class_init(ObjectClass *klass, const void *data) { @@ -365,6 +587,15 @@ static void octeon_rst_class_init(ObjectClass *klass, = const void *data) NULL, &opc->parent_phases); } =20 +static void octeon_intc_class_init(ObjectClass *klass, const void *data) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + resettable_class_set_parent_phases(rc, NULL, octeon_intc_reset_hold, + NULL, &opc->parent_phases); +} + static OcteonPeripheralState *octeon_new_peripheral(OcteonState *s, const char *type, unsigned int index) @@ -380,6 +611,7 @@ static OcteonPeripheralState *octeon_new_peripheral(Oct= eonState *s, static void octeon_create_peripherals(OcteonState *s) { s->rst =3D OCTEON_RST(octeon_new_peripheral(s, TYPE_OCTEON_RST, 0)); + s->intc =3D OCTEON_INTC(octeon_new_peripheral(s, TYPE_OCTEON_INTC, 0)); } =20 static void octeon_realize_peripheral(OcteonPeripheralState *dev) @@ -389,6 +621,7 @@ static void octeon_realize_peripheral(OcteonPeripheralS= tate *dev) =20 static void octeon_realize_peripherals(OcteonState *s) { + octeon_realize_peripheral(&s->intc->parent_obj); octeon_realize_peripheral(&s->rst->parent_obj); } =20 @@ -418,6 +651,12 @@ static void mips_octeon_init(MachineState *machine) octeon_load_firmware(s); octeon_create_cpus(s); =20 + memory_region_init_io(&s->intc->ciu3, OBJECT(s->intc), + &octeon_ciu3_ops, s, + "octeon.ciu3", OCTEON_CIU3_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_CIU3_BASE, + &s->intc->ciu3); + octeon_realize_peripherals(s); } =20 @@ -490,6 +729,12 @@ static const TypeInfo octeon_machine_types[] =3D { .instance_size =3D sizeof(OcteonRstState), .class_init =3D octeon_rst_class_init, }, + { + .name =3D TYPE_OCTEON_INTC, + .parent =3D TYPE_OCTEON_PERIPHERAL, + .instance_size =3D sizeof(OcteonIntcState), + .class_init =3D octeon_intc_class_init, + }, { .name =3D TYPE_OCTEON_MACHINE, .parent =3D TYPE_MACHINE, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 9c1baee292..884eed8994 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -16,6 +16,7 @@ #define OCTEON_MAX_CPUS 16 typedef struct OcteonState OcteonState; typedef struct OcteonRstState OcteonRstState; +typedef struct OcteonIntcState OcteonIntcState; =20 typedef struct OcteonCPUState { OcteonState *board; @@ -41,6 +42,11 @@ struct OcteonState { MemoryRegion boot_flash_alias; MemoryRegion cvmseg; OcteonRstState *rst; + OcteonIntcState *intc; }; =20 +uint64_t octeon_read64(uint64_t value, hwaddr addr, unsigned size); +uint64_t octeon_write64(uint64_t old, hwaddr addr, + uint64_t value, unsigned size); + #endif --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437212098636.0204236681568; Thu, 3 Sep 2026 05:06:52 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CK-0002vr-V6; Thu, 03 Sep 2026 08:05:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CI-0002ub-70 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:38 -0400 Received: from mx2.catap.net ([2a01:4f9:3b:5410::2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CE-0005LP-Jr for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:37 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id a7a91895 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:28 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 489d08e9; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=r7e2Smi 7PlY9Es9/gygBC0jfIhbwl4X6rbxe0vdylqUGgx+fJ4zrlNtw5pS1eaFFxbY+y1isezEqM q2jux64CapeRgJENufXs92R75beNPhTlDQ0t556qBiiUXOIEEqGxUhwuQU032IgJgM8O+n yUwvOOygaxPPN2gZoOq+ry2DkP2l9fHuor9ZvOjFw9OMjkqFVHY6Tfsbe3bElk1Omts9mE O7dVwrDMf1mrAgs4BJwrynkBwE8b8B82ue6JKhFpolm0r6VRNk/DV4ks3Tbmvxf51ikmqK I6G0wAT+1P2iGjtws3EGn/hflK87w7+CNLGrg7vg2L0kDlBWYx36FFw== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=y vYh0+KIlwKp0JutEJwrXit2UfWJdAGCqRb8dBZKmRY=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=GjomIlU9SB6Ba4nfINEKoIwI1Y312Ua5JTuA1PvRZGm8kkkVQ2f8QhO+AGh5x0cH6EiE bReRSLcwZxgypC74PUvnmlYRK6dtfRuYSSKQuBcODP4Vse9RQdS/Y3VC/gac5JDfdjrOU0 LdeYTbl60gChsskQoOY3b5MjMvG2MgwgVA6lOBdJyNItmHqqDmc4yIPz1jJPiRZo3uhPgh xkNJPOLlu/cy2yjKpuG+fJyic/v/xiK87JzFlQswWHAGFwcFPLLIkRNoKyq0tCsY36DLKZ NbSW05tfjz3f+fMqvUllQOJ9W+q8tQl08tWIqIkMzWPUzM64OjrULJ5LZp5ykpfQ== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=ztwIcF2L; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=80lgttAY; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=yvYh0+KI lwKp0JutEJwrXit2UfWJdAGCqRb8dBZKmRY=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=ztwIcF2LtF7vluzs9cPT8ombLquqpxlglPc YZfKFgXpHPHx8doDURi8CCCZDnmewnLnoMBr1w/9xsszOOwtX8wm+7MTRvgffN3xulX5UZ wvRQPjebKBRKZriqxO9J2X9xMmVdGXgK0dj7oeUxbR2StTFM5ubRJwNKEUm5mgrNHi7eEy DbcDzcbUSNsP4eODEbGGktewiDAp1fAXqgv1Pscl3rQqbLeYZRSZQhUlSlosPkSCFkhHFD eyEQGDONwjgWSCJ+EGc3FhPvRyhiTSjz6gj1CySNTuWDFSr4aDABz2oIlsA5W5xDh1/vcy wJMUOqq2Ar3qONAtrJnmtE1TD9w== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=yvYh0+KIlwKp0JutEJwrXit2UfWJdAGCqRb8dBZKmRY=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=80lgttAYusYamcbMe+ 9BWviLf+MK6Gy6rrMhJf1EZG3VtwQkOw1LkAozFRLKFQFwcmWrEhh8sI/FCyo3ZZjNDQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 12/25] hw/mips: add Octeon CIU3 interrupt routing Date: Thu, 3 Sep 2026 14:02:00 +0200 Message-ID: <20260903120510.34876-13-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a01:4f9:3b:5410::2; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437213691158500 Content-Type: text/plain; charset="utf-8" Model CIU3 interrupt sources, ISC and IDT registers, destination selection and CP0 interrupt delivery. Route UART and mailbox sources through CIU3 while keeping the legacy CIU register block separate. --- hw/mips/octeon.c | 483 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 15 ++ 2 files changed, 498 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index eeca7ca67e..567be0905a 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -11,6 +11,7 @@ #include "qemu/datadir.h" #include "qapi/error.h" #include "hw/core/clock.h" +#include "hw/core/irq.h" #include "hw/core/boards.h" #include "hw/core/qdev-clock.h" #include "hw/core/qdev-properties.h" @@ -74,6 +75,28 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) #define OCTEON_CIU3_PP_RST_PENDING 0x110 #define OCTEON_CIU3_NMI 0x160 #define OCTEON_CIU3_FUSE 0x1a0 +#define OCTEON_CIU3_IDT_CTL(idt) ((idt) * 8 + 0x110000U) +#define OCTEON_CIU3_IDT_PP(idt) ((idt) * 32 + 0x120000U) +#define OCTEON_CIU3_IDT_IO(idt) ((idt) * 8 + 0x130000U) +#define OCTEON_CIU3_DEST_PP_INT(cpu) ((cpu) * 8 + 0x200000U) +#define OCTEON_CIU3_DEST_PP_INT_INTSN_SHIFT 32 +#define OCTEON_CIU3_DEST_PP_INT_INTR 0x0000000000000001ULL +#define OCTEON_CIU3_IDT_CTL_IP_NUM 0x7 +#define OCTEON_CIU3_CP0_IRQ_BASE 2 +#define OCTEON_CIU3_ISC_CTL_BASE 0x80000000U +#define OCTEON_CIU3_ISC_W1C_BASE 0x90000000U +#define OCTEON_CIU3_ISC_W1S_BASE 0xa0000000U +#define OCTEON_CIU3_ISC_CTL_IDT 0x0000000000ff0000ULL +#define OCTEON_CIU3_ISC_CTL_IDT_SHIFT 16 +#define OCTEON_CIU3_ISC_CTL_IMP 0x0000000000008000ULL +#define OCTEON_CIU3_ISC_CTL_EN 0x0000000000000002ULL +#define OCTEON_CIU3_ISC_CTL_RAW 0x0000000000000001ULL +#define OCTEON_CIU3_SRC_LEVEL 0x00000001U +#define OCTEON_CIU3_SRC_RAW 0x00000002U +#define OCTEON_CIU3_NINTSN (1U << 20) +#define OCTEON_CIU3_ISC_SIZE (OCTEON_CIU3_NINTSN * 8) +#define OCTEON_CIU3_MBOX_INTSN(cpu) ((cpu) + 0x4000U) +#define OCTEON_CIU3_UART0_INTSN 0x8000 =20 /* * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; @@ -126,6 +149,13 @@ struct OcteonIntcState { OcteonPeripheralState parent_obj; MemoryRegion ciu3; uint64_t ciu3_pp_rst; + uint32_t ciu3_src_state[OCTEON_CIU3_SRC_COUNT]; + uint64_t ciu3_src_ctl[OCTEON_CIU3_SRC_COUNT]; + uint64_t ciu3_idt_ctl[OCTEON_CIU3_IDT_COUNT]; + uint64_t ciu3_idt_pp[OCTEON_CIU3_IDT_COUNT]; + uint64_t ciu3_idt_io[OCTEON_CIU3_IDT_COUNT]; + uint16_t ciu3_src_cursor[OCTEON_MAX_CPUS][OCTEON_CIU3_CP0_IRQ_COUNT]; + uint8_t ciu3_irq_line[OCTEON_MAX_CPUS][OCTEON_CIU3_CP0_IRQ_COUNT]; }; =20 uint64_t octeon_read64(uint64_t value, hwaddr addr, unsigned size) @@ -189,6 +219,286 @@ static void octeon_validate_clocks(OcteonMachineState= *oms) } } =20 +static bool octeon_ciu3_source_from_intsn(uint32_t intsn, + unsigned int *source) +{ + if (intsn =3D=3D OCTEON_CIU3_UART0_INTSN) { + *source =3D OCTEON_CIU3_SRC_UART0; + return true; + } + if (intsn >=3D OCTEON_CIU3_MBOX_INTSN(0) && + intsn < OCTEON_CIU3_MBOX_INTSN(OCTEON_MAX_CPUS)) { + *source =3D OCTEON_CIU3_SRC_MBOX0 + + intsn - OCTEON_CIU3_MBOX_INTSN(0); + return true; + } + + return false; +} + +static uint32_t octeon_ciu3_source_intsn(unsigned int source) +{ + switch (source) { + case OCTEON_CIU3_SRC_UART0: + return OCTEON_CIU3_UART0_INTSN; + } + + if (source >=3D OCTEON_CIU3_SRC_MBOX0 && + source < OCTEON_CIU3_SRC_COUNT) { + return OCTEON_CIU3_MBOX_INTSN(source - OCTEON_CIU3_SRC_MBOX0); + } + + g_assert_not_reached(); +} + +static bool octeon_ciu3_source_is_level(unsigned int source) +{ + switch (source) { + case OCTEON_CIU3_SRC_UART0: + return true; + } + + return false; +} + +static bool octeon_ciu3_set_level(OcteonState *s, unsigned int source, + int level) +{ + uint32_t old; + uint32_t new; + uint32_t cmp =3D qatomic_read(&s->intc->ciu3_src_state[source]); + + do { + old =3D cmp; + if (level) { + new =3D old | OCTEON_CIU3_SRC_LEVEL | OCTEON_CIU3_SRC_RAW; + } else { + new =3D old & ~(OCTEON_CIU3_SRC_LEVEL | OCTEON_CIU3_SRC_RAW); + } + if (new =3D=3D old) { + return false; + } + cmp =3D qatomic_cmpxchg(&s->intc->ciu3_src_state[source], old, new= ); + } while (old !=3D cmp); + + return true; +} + +static void octeon_ciu3_clear_raw(OcteonState *s, unsigned int source) +{ + uint32_t old; + uint32_t new; + uint32_t cmp =3D qatomic_read(&s->intc->ciu3_src_state[source]); + + do { + old =3D cmp; + if (octeon_ciu3_source_is_level(source) && + (old & OCTEON_CIU3_SRC_LEVEL)) { + new =3D old | OCTEON_CIU3_SRC_RAW; + } else { + new =3D old & ~OCTEON_CIU3_SRC_RAW; + } + if (new =3D=3D old) { + return; + } + cmp =3D qatomic_cmpxchg(&s->intc->ciu3_src_state[source], old, new= ); + } while (old !=3D cmp); +} + +static bool octeon_ciu3_isc_decode(hwaddr reg, uint32_t base, + uint32_t *intsn) +{ + if (reg < base || reg >=3D base + OCTEON_CIU3_ISC_SIZE) { + return false; + } + + *intsn =3D (reg - base) >> 3; + return true; +} + +static uint64_t octeon_ciu3_isc_read(OcteonState *s, uint32_t intsn) +{ + unsigned int src; + uint64_t value; + + if (!octeon_ciu3_source_from_intsn(intsn, &src)) { + return 0; + } + + value =3D qatomic_read(&s->intc->ciu3_src_ctl[src]) | OCTEON_CIU3_ISC_= CTL_IMP; + if (qatomic_read(&s->intc->ciu3_src_state[src]) & OCTEON_CIU3_SRC_RAW)= { + value |=3D OCTEON_CIU3_ISC_CTL_RAW; + } + return value; +} + +static bool octeon_ciu3_source_pending(OcteonState *s, unsigned int cpu_in= dex, + unsigned int irq, unsigned int src) +{ + uint64_t ctl =3D qatomic_read(&s->intc->ciu3_src_ctl[src]); + unsigned int idt; + unsigned int output; + + if (!(qatomic_read(&s->intc->ciu3_src_state[src]) & OCTEON_CIU3_SRC_RA= W) || + !(ctl & OCTEON_CIU3_ISC_CTL_EN)) { + return false; + } + + idt =3D (ctl & OCTEON_CIU3_ISC_CTL_IDT) >> + OCTEON_CIU3_ISC_CTL_IDT_SHIFT; + if (idt >=3D OCTEON_CIU3_IDT_COUNT) { + return false; + } + + output =3D qatomic_read(&s->intc->ciu3_idt_ctl[idt]) & + OCTEON_CIU3_IDT_CTL_IP_NUM; + if (output >=3D OCTEON_CIU3_CP0_IRQ_COUNT || + irq !=3D OCTEON_CIU3_CP0_IRQ_BASE + output) { + return false; + } + + return qatomic_read(&s->intc->ciu3_idt_pp[idt]) & (1ULL << cpu_index); +} + +static bool octeon_ciu3_pending_intsn(OcteonState *s, unsigned int cpu_ind= ex, + unsigned int irq, uint32_t *intsn) +{ + unsigned int src; + + for (src =3D 0; src < OCTEON_CIU3_SRC_COUNT; src++) { + if (octeon_ciu3_source_pending(s, cpu_index, irq, src)) { + *intsn =3D octeon_ciu3_source_intsn(src); + return true; + } + } + + return false; +} + +static bool octeon_ciu3_pending_intsn_from(OcteonState *s, + unsigned int cpu_index, + unsigned int irq, + unsigned int first_src, + uint32_t *intsn, + unsigned int *source) +{ + unsigned int i; + unsigned int src; + + for (i =3D 0; i < OCTEON_CIU3_SRC_COUNT; i++) { + src =3D (first_src + i) % OCTEON_CIU3_SRC_COUNT; + if (octeon_ciu3_source_pending(s, cpu_index, irq, src)) { + *intsn =3D octeon_ciu3_source_intsn(src); + *source =3D src; + return true; + } + } + + return false; +} + +static bool octeon_ciu3_pending_dest_intsn(OcteonState *s, + unsigned int cpu_index, + uint32_t *intsn) +{ + unsigned int irq; + unsigned int irq_index; + unsigned int src; + + for (irq =3D OCTEON_CIU3_CP0_IRQ_BASE; + irq < OCTEON_CIU3_CP0_IRQ_BASE + OCTEON_CIU3_CP0_IRQ_COUNT; + irq++) { + irq_index =3D irq - OCTEON_CIU3_CP0_IRQ_BASE; + if (octeon_ciu3_pending_intsn_from(s, cpu_index, irq, + qatomic_read(&s->intc->ciu3_src_cursor[cpu_index][irq_inde= x]), + intsn, &src)) { + qatomic_set(&s->intc->ciu3_src_cursor[cpu_index][irq_index], + (src + 1) % OCTEON_CIU3_SRC_COUNT); + return true; + } + } + + return false; +} + +static void octeon_ciu3_set_cpu_irq(OcteonState *s, unsigned int cpu_index, + unsigned int irq, bool level) +{ + CPUMIPSState *env =3D &s->cpu[cpu_index].cpu->env; + unsigned int irq_index =3D irq - OCTEON_CIU3_CP0_IRQ_BASE; + uint8_t new_level =3D level; + uint8_t old_level; + + old_level =3D qatomic_xchg(&s->intc->ciu3_irq_line[cpu_index][irq_inde= x], + new_level); + if (old_level =3D=3D new_level) { + return; + } + + qemu_set_irq(env->irq[irq], level); +} + +static void octeon_intc_update_cpu(OcteonState *s, unsigned int cpu_index) +{ + uint32_t intsn; + unsigned int irq; + bool level; + + if (cpu_index >=3D s->cpu_count || !s->cpu[cpu_index].cpu) { + return; + } + + if (qatomic_read(&s->intc->ciu3_pp_rst) & (1ULL << cpu_index)) { + for (irq =3D OCTEON_CIU3_CP0_IRQ_BASE; + irq < OCTEON_CIU3_CP0_IRQ_BASE + OCTEON_CIU3_CP0_IRQ_COUNT; + irq++) { + octeon_ciu3_set_cpu_irq(s, cpu_index, irq, false); + } + return; + } + + for (irq =3D OCTEON_CIU3_CP0_IRQ_BASE; + irq < OCTEON_CIU3_CP0_IRQ_BASE + OCTEON_CIU3_CP0_IRQ_COUNT; + irq++) { + level =3D false; + if (octeon_ciu3_pending_intsn(s, cpu_index, irq, &intsn)) { + level =3D true; + } + + octeon_ciu3_set_cpu_irq(s, cpu_index, irq, level); + } +} + +static void octeon_intc_request_cpu_update(OcteonState *s, + unsigned int cpu_index) +{ + if (cpu_index >=3D s->cpu_count || !s->cpu[cpu_index].cpu) { + return; + } + + octeon_intc_update_cpu(s, cpu_index); +} + +static void octeon_intc_update_cpu_mask(OcteonState *s, uint64_t cpu_mask) +{ + unsigned int cpu; + + for (cpu =3D 0; cpu < s->cpu_count; cpu++) { + if (cpu_mask & (1ULL << cpu)) { + octeon_intc_request_cpu_update(s, cpu); + } + } +} + +static void octeon_intc_update_all_cpus(OcteonState *s) +{ + unsigned int cpu; + + for (cpu =3D 0; cpu < s->cpu_count; cpu++) { + octeon_intc_request_cpu_update(s, cpu); + } +} + static uint64_t octeon_present_cpu_mask(OcteonState *s) { return (1ULL << s->cpu_count) - 1; @@ -199,6 +509,24 @@ static uint64_t octeon_secondary_cpu_mask(OcteonState = *s) return octeon_present_cpu_mask(s) & ~1ULL; } =20 +static uint64_t octeon_ciu3_ctl_cpu_mask(OcteonState *s, uint64_t ctl) +{ + unsigned int idt =3D (ctl & OCTEON_CIU3_ISC_CTL_IDT) >> + OCTEON_CIU3_ISC_CTL_IDT_SHIFT; + + if (idt >=3D OCTEON_CIU3_IDT_COUNT) { + return 0; + } + + return qatomic_read(&s->intc->ciu3_idt_pp[idt]); +} + +static uint64_t octeon_ciu3_source_cpu_mask(OcteonState *s, unsigned int s= rc) +{ + return octeon_ciu3_ctl_cpu_mask( + s, qatomic_read(&s->intc->ciu3_src_ctl[src])); +} + static void octeon_cpu_park_now(MIPSCPU *cpu) { CPUMIPSState *env =3D &cpu->env; @@ -268,6 +596,9 @@ static uint64_t octeon_ciu3_read(void *opaque, hwaddr a= ddr, unsigned size) OcteonState *s =3D opaque; hwaddr reg =3D addr & ~7ULL; uint64_t value; + uint32_t intsn; + unsigned int cpu; + unsigned int idt; =20 if (reg =3D=3D OCTEON_CIU3_PP_RST) { return octeon_read64(qatomic_read(&s->intc->ciu3_pp_rst), addr, si= ze); @@ -286,6 +617,51 @@ static uint64_t octeon_ciu3_read(void *opaque, hwaddr = addr, unsigned size) return octeon_read64(value, addr, size); } =20 + if (reg >=3D OCTEON_CIU3_IDT_CTL(0) && + reg < OCTEON_CIU3_IDT_CTL(OCTEON_CIU3_IDT_COUNT)) { + idt =3D (reg - OCTEON_CIU3_IDT_CTL(0)) >> 3; + return octeon_read64(qatomic_read(&s->intc->ciu3_idt_ctl[idt]), + addr, size); + } + + if (reg >=3D OCTEON_CIU3_IDT_PP(0) && + reg < OCTEON_CIU3_IDT_PP(OCTEON_CIU3_IDT_COUNT)) { + idt =3D (reg - OCTEON_CIU3_IDT_PP(0)) >> 5; + return octeon_read64(qatomic_read(&s->intc->ciu3_idt_pp[idt]), + addr, size); + } + + if (reg >=3D OCTEON_CIU3_IDT_IO(0) && + reg < OCTEON_CIU3_IDT_IO(OCTEON_CIU3_IDT_COUNT)) { + idt =3D (reg - OCTEON_CIU3_IDT_IO(0)) >> 3; + return octeon_read64(qatomic_read(&s->intc->ciu3_idt_io[idt]), + addr, size); + } + + if (reg >=3D OCTEON_CIU3_DEST_PP_INT(0) && + reg < OCTEON_CIU3_DEST_PP_INT(OCTEON_MAX_CPUS)) { + cpu =3D (reg - OCTEON_CIU3_DEST_PP_INT(0)) >> 3; + value =3D 0; + if (cpu < s->cpu_count) { + if (!(qatomic_read(&s->intc->ciu3_pp_rst) & (1ULL << cpu)) && + octeon_ciu3_pending_dest_intsn(s, cpu, &intsn)) { + value =3D OCTEON_CIU3_DEST_PP_INT_INTR | + ((uint64_t)intsn << + OCTEON_CIU3_DEST_PP_INT_INTSN_SHIFT); + } + } + return octeon_read64(value, addr, size); + } + + if (octeon_ciu3_isc_decode(reg, OCTEON_CIU3_ISC_CTL_BASE, &intsn)) { + return octeon_read64(octeon_ciu3_isc_read(s, intsn), addr, size); + } + + if (octeon_ciu3_isc_decode(reg, OCTEON_CIU3_ISC_W1C_BASE, &intsn) || + octeon_ciu3_isc_decode(reg, OCTEON_CIU3_ISC_W1S_BASE, &intsn)) { + return octeon_read64(octeon_ciu3_isc_read(s, intsn), addr, size); + } + return 0; } =20 @@ -295,7 +671,10 @@ static void octeon_ciu3_write(void *opaque, hwaddr add= r, OcteonState *s =3D opaque; hwaddr reg =3D addr & ~7ULL; uint64_t old; + uint32_t intsn; unsigned int cpu; + unsigned int idt; + unsigned int src; =20 if (reg =3D=3D OCTEON_CIU3_PP_RST) { value =3D octeon_atomic_write64(&s->intc->ciu3_pp_rst, addr, value= , size, @@ -314,13 +693,89 @@ static void octeon_ciu3_write(void *opaque, hwaddr ad= dr, octeon_ciu3_start_cpu(s, cpu); } } + octeon_intc_update_all_cpus(s); return; } =20 if (reg =3D=3D OCTEON_CIU3_NMI) { octeon_ciu3_nmi(s, octeon_write64(0, addr, value, size)); + octeon_intc_update_all_cpus(s); + return; + } + + if (reg >=3D OCTEON_CIU3_IDT_CTL(0) && + reg < OCTEON_CIU3_IDT_CTL(OCTEON_CIU3_IDT_COUNT)) { + idt =3D (reg - OCTEON_CIU3_IDT_CTL(0)) >> 3; + octeon_atomic_write64(&s->intc->ciu3_idt_ctl[idt], addr, value, si= ze, + UINT64_MAX, 0, NULL); + octeon_intc_update_cpu_mask( + s, qatomic_read(&s->intc->ciu3_idt_pp[idt])); + return; + } + + if (reg >=3D OCTEON_CIU3_IDT_PP(0) && + reg < OCTEON_CIU3_IDT_PP(OCTEON_CIU3_IDT_COUNT)) { + idt =3D (reg - OCTEON_CIU3_IDT_PP(0)) >> 5; + value =3D octeon_atomic_write64(&s->intc->ciu3_idt_pp[idt], addr, = value, + size, UINT64_MAX, 0, &old); + octeon_intc_update_cpu_mask(s, old | value); + return; + } + + if (reg >=3D OCTEON_CIU3_IDT_IO(0) && + reg < OCTEON_CIU3_IDT_IO(OCTEON_CIU3_IDT_COUNT)) { + idt =3D (reg - OCTEON_CIU3_IDT_IO(0)) >> 3; + octeon_atomic_write64(&s->intc->ciu3_idt_io[idt], addr, value, siz= e, + UINT64_MAX, 0, NULL); + octeon_intc_update_cpu_mask( + s, qatomic_read(&s->intc->ciu3_idt_pp[idt])); + return; + } + + if (octeon_ciu3_isc_decode(reg, OCTEON_CIU3_ISC_CTL_BASE, &intsn)) { + if (octeon_ciu3_source_from_intsn(intsn, &src)) { + value =3D octeon_atomic_write64(&s->intc->ciu3_src_ctl[src], a= ddr, + value, size, + ~OCTEON_CIU3_ISC_CTL_RAW, + 0, &old); + octeon_intc_update_cpu_mask(s, + octeon_ciu3_ctl_cpu_mask(s, old) | + octeon_ciu3_ctl_cpu_mask(s, value)= ); + } + return; + } + + if (octeon_ciu3_isc_decode(reg, OCTEON_CIU3_ISC_W1C_BASE, &intsn)) { + if (octeon_ciu3_source_from_intsn(intsn, &src)) { + old =3D qatomic_read(&s->intc->ciu3_src_ctl[src]); + if (value & OCTEON_CIU3_ISC_CTL_EN) { + qatomic_and(&s->intc->ciu3_src_ctl[src], + ~OCTEON_CIU3_ISC_CTL_EN); + } + if (value & OCTEON_CIU3_ISC_CTL_RAW) { + octeon_ciu3_clear_raw(s, src); + } + octeon_intc_update_cpu_mask(s, + octeon_ciu3_ctl_cpu_mask(s, old) | + octeon_ciu3_source_cpu_mask(s, src= )); + } return; } + + if (octeon_ciu3_isc_decode(reg, OCTEON_CIU3_ISC_W1S_BASE, &intsn)) { + if (octeon_ciu3_source_from_intsn(intsn, &src)) { + old =3D qatomic_read(&s->intc->ciu3_src_ctl[src]); + if (value & OCTEON_CIU3_ISC_CTL_EN) { + qatomic_or(&s->intc->ciu3_src_ctl[src], OCTEON_CIU3_ISC_CT= L_EN); + } + if (value & OCTEON_CIU3_ISC_CTL_RAW) { + qatomic_or(&s->intc->ciu3_src_state[src], OCTEON_CIU3_SRC_= RAW); + } + octeon_intc_update_cpu_mask(s, + octeon_ciu3_ctl_cpu_mask(s, old) | + octeon_ciu3_source_cpu_mask(s, src= )); + } + } } =20 static const MemoryRegionOps octeon_ciu3_ops =3D { @@ -333,6 +788,26 @@ static const MemoryRegionOps octeon_ciu3_ops =3D { }, }; =20 +void octeon_irq_set(void *opaque, int irq, int level) +{ + OcteonState *s =3D opaque; + unsigned int src; + + switch (irq) { + case OCTEON_IRQ_UART: + src =3D OCTEON_CIU3_SRC_UART0; + if (!octeon_ciu3_set_level(s, src, level)) { + return; + } + break; + default: + return; + } + + octeon_intc_update_cpu_mask(s, octeon_ciu3_source_cpu_mask(s, src)); +} + + static void octeon_cpu_after_reset(OcteonCPUState *cs) { CPUMIPSState *env =3D &cs->cpu->env; @@ -568,6 +1043,14 @@ static void octeon_intc_reset_hold(Object *obj, Reset= Type type) } =20 qatomic_set(&intc->ciu3_pp_rst, octeon_secondary_cpu_mask(s)); + memset(intc->ciu3_src_state, 0, sizeof(intc->ciu3_src_state)); + memset(intc->ciu3_src_ctl, 0, sizeof(intc->ciu3_src_ctl)); + memset(intc->ciu3_idt_ctl, 0, sizeof(intc->ciu3_idt_ctl)); + memset(intc->ciu3_idt_pp, 0, sizeof(intc->ciu3_idt_pp)); + memset(intc->ciu3_idt_io, 0, sizeof(intc->ciu3_idt_io)); + memset(intc->ciu3_src_cursor, 0, sizeof(intc->ciu3_src_cursor)); + memset(intc->ciu3_irq_line, 0, sizeof(intc->ciu3_irq_line)); + octeon_intc_update_all_cpus(s); } =20 static void octeon_peripheral_class_init(ObjectClass *klass, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 884eed8994..fef88419b5 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -14,6 +14,20 @@ #include "target/mips/cpu.h" =20 #define OCTEON_MAX_CPUS 16 +#define OCTEON_CIU3_CP0_IRQ_COUNT 4 +#define OCTEON_CIU3_IDT_COUNT (OCTEON_MAX_CPUS * 4) + +typedef enum OcteonIRQ { + OCTEON_IRQ_UART, + OCTEON_IRQ_COUNT, +} OcteonIRQ; + +typedef enum OcteonCiu3Source { + OCTEON_CIU3_SRC_UART0, + OCTEON_CIU3_SRC_MBOX0, + OCTEON_CIU3_SRC_COUNT =3D OCTEON_CIU3_SRC_MBOX0 + OCTEON_MAX_CPUS, +} OcteonCiu3Source; + typedef struct OcteonState OcteonState; typedef struct OcteonRstState OcteonRstState; typedef struct OcteonIntcState OcteonIntcState; @@ -48,5 +62,6 @@ struct OcteonState { uint64_t octeon_read64(uint64_t value, hwaddr addr, unsigned size); uint64_t octeon_write64(uint64_t old, hwaddr addr, uint64_t value, unsigned size); +void octeon_irq_set(void *opaque, int irq, int level); =20 #endif --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437233063202.48618759561657; Thu, 3 Sep 2026 05:07:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CQ-0002yT-9F; Thu, 03 Sep 2026 08:05:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CI-0002un-Fn for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:38 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CF-0005Lq-Kk for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:38 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 5ffeb52b (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:28 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id ae1abdc7; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=RNiUH6t mpREqn96NBmI8qZ+6+oa+F6IMCRChbRFQm+abe5iuuNqnKnnKWesED62vfozd/CIANAC0F 6kzKJXCJ1gVRL4ho9xAJ4ksKMBDQ2n8mKsD1OquP6+LAnhYBGmSLqrt926WBZm8Vhj/vQ9 e+92KVyFGDZqKN3ULGAv7KzZSet04Qa/nx9HtvKQDcVXLS2AMPx5kYa82LJAqQVmiUUSPu yweWJOSAs+h+d7O3Q7V3dzhpMZll7+KiDQbfiZI9HeJFoN91TL/rZEBLJ4l1Da30Lf6fKh +2uclcUdROPvEc6ntcyE+JsjrCeK4BuYx/ih1KYYlftrqBkwM882mzw== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=P eArIBzmNEPnbKwsS369KM2ngNlLMePHvmJE7Yix/sw=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=F7wqZQbsIfdqs/5fh1aO6IEFKpLc3xvwRAkR3jc2NR6ribP5CAvAqbM4OAVOBe2BOMkj b38XXKSLPML634m6Po8BTu3pvFhtt+uxKfGf9VCxByWYv084qiQihO8bobhH1B+GZ+j2xn 52wRFVMorvgRLXL1T3w69e3n2CROtL9e27n1dFXvS3p+acz8WI1tE4rQcdQn4Q2nIhzsdu 21hB2TbhF1/D8URjbKaSt3FkN4yXNSLfKma31AHxFM7SKcWucJAy2TgIjkb5GTapXLQ4zr 6awdyI0Fbs74IGm2Be0hgLw5OB32vWmUGkajK29WcsfBdh8HnqkLYE24wEMK7+PQ== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=fzacoJYH; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=srSYEUvZ; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=PeArIBzm NEPnbKwsS369KM2ngNlLMePHvmJE7Yix/sw=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=fzacoJYHI+aDRDDMoOhJS9csTvni3L+mdbR YWg2F6bwmgeaJKal0ihodj5l8lnb6kwG4sxlUnKanqE0rNy5ks7QMvO+EQgp6pmi7kQc6S 9HXm1lzVcCevJ5YrJCS01RgNBG+QYJeObul5KLoLvEyFJCINBqNPz6DkaKAA5bGYT/mUQL Sl/JddwDsA008HmkBUShqxaDsVglAmFARk32tuqP5jD6yAJTdeAATGSuv9dHWCHsztL6xD Ig8lY4Kd2mHKjIJJ6lfPnYYbJN3s9wl1Yviw1TF7dvwa6dlGHrqXUISlC5dOZDi1KOW/B2 56gy3fayIciL8CDyUD2JxFLVLCA== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=PeArIBzmNEPnbKwsS369KM2ngNlLMePHvmJE7Yix/sw=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=srSYEUvZ7aZqZUdFHr L41EJy+DgV2pTutQn443bkk75X6CLhYny6iiMbsQ9eAZk7V+EpAV5EO+DpndI9iPueCQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 13/25] hw/mips: add Octeon legacy CIU Date: Thu, 3 Sep 2026 14:02:01 +0200 Message-ID: <20260903120510.34876-14-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437234060158500 Content-Type: text/plain; charset="utf-8" Model the legacy CIU mailbox, IPI, GPIO and UART summary registers. Mirror mailbox state into CIU3 interrupt sources so firmware using either controller observes consistent interrupt delivery. --- hw/mips/octeon.c | 248 +++++++++++++++++++++++++++++++++++++- hw/mips/octeon_internal.h | 1 + 2 files changed, 248 insertions(+), 1 deletion(-) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 567be0905a..638d96559f 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -69,6 +69,29 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) #define OCTEON_DR1_BASE 0x020000000ULL #define OCTEON_DR1_SIZE (OCTEON_MAX_PHY_MEM_SIZE - OCTEON_DR0_= SIZE) =20 +#define OCTEON_CIU_BASE 0x1070000000000ULL +#define OCTEON_CIU_LEGACY_PAGE_SIZE (4 * KiB) +#define OCTEON_CIU_SIZE (1 * MiB + OCTEON_CIU_LEGACY_PAGE_SIZE) +#define OCTEON_CIU_FUSE 0x728 +#define OCTEON_CIU_SUM_IPI 0x0000000100000000ULL +#define OCTEON_CIU_SUM_UART 0x0000000800000000ULL +#define OCTEON_CIU_ENABLE0 0x88006f1800000000ULL +#define OCTEON_CIU_IPI_SUM_BASE 0x008 +#define OCTEON_CIU_IPI_SUM_STRIDE 0x10 +#define OCTEON_CIU_IPI_EN_BASE 0x210 +#define OCTEON_CIU_IPI_EN_STRIDE 0x20 +#define OCTEON_CIU_MBOX_SET_BASE 0x600 +#define OCTEON_CIU_MBOX_CLR_BASE 0x680 +#define OCTEON_CIU_MBOX_SET_STRIDE 8 +#define OCTEON_CIU_GPIO_RX_DAT 0x880 +#define OCTEON_CIU_GPIO_TX_SET 0x888 +#define OCTEON_CIU_GPIO_TX_CLR 0x890 +#define OCTEON_CIU_GPIO_BIT_CFG_STRIDE OCTEON_CSR_64BIT_SIZE +#define OCTEON_CIU_GPIO_BIT_CFGX(x) \ + (0x900 + (x) * OCTEON_CIU_GPIO_BIT_CFG_STRIDE) +#define OCTEON_CIU_GPIO_INPUTS ((1ULL << OCTEON_CIU_GPIO_COUNT) - 1) +#define OCTEON_CIU_GPIO_BIT_CFG_TX_OE (1ULL << 0) + #define OCTEON_CIU3_BASE 0x1010000000000ULL #define OCTEON_CIU3_SIZE 0xb0000000ULL #define OCTEON_CIU3_PP_RST 0x100 @@ -97,7 +120,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) #define OCTEON_CIU3_ISC_SIZE (OCTEON_CIU3_NINTSN * 8) #define OCTEON_CIU3_MBOX_INTSN(cpu) ((cpu) + 0x4000U) #define OCTEON_CIU3_UART0_INTSN 0x8000 - /* * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; * the guest sees the virtual CVMSEG window, not this physical address. @@ -147,7 +169,14 @@ struct OcteonRstState { =20 struct OcteonIntcState { OcteonPeripheralState parent_obj; + MemoryRegion ciu; MemoryRegion ciu3; + uint32_t ciu_mbox[OCTEON_MAX_CPUS]; + uint64_t ciu_ipi_en[OCTEON_MAX_CPUS]; + uint64_t ciu_gpio_rx; + uint64_t ciu_gpio_tx; + uint64_t ciu_gpio_bit_cfg[OCTEON_CIU_GPIO_COUNT]; + bool uart_pending; uint64_t ciu3_pp_rst; uint32_t ciu3_src_state[OCTEON_CIU3_SRC_COUNT]; uint64_t ciu3_src_ctl[OCTEON_CIU3_SRC_COUNT]; @@ -305,6 +334,12 @@ static void octeon_ciu3_clear_raw(OcteonState *s, unsi= gned int source) } while (old !=3D cmp); } =20 +static bool octeon_ciu3_set_mbox(OcteonState *s, unsigned int cpu) +{ + return octeon_ciu3_set_level(s, OCTEON_CIU3_SRC_MBOX0 + cpu, + qatomic_read(&s->intc->ciu_mbox[cpu]) != =3D 0); +} + static bool octeon_ciu3_isc_decode(hwaddr reg, uint32_t base, uint32_t *intsn) { @@ -461,6 +496,12 @@ static void octeon_intc_update_cpu(OcteonState *s, uns= igned int cpu_index) irq < OCTEON_CIU3_CP0_IRQ_BASE + OCTEON_CIU3_CP0_IRQ_COUNT; irq++) { level =3D false; + if (irq =3D=3D 3) { + level =3D qatomic_read(&s->intc->ciu_mbox[cpu_index]) && + (qatomic_read(&s->intc->ciu_ipi_en[cpu_index]) & + OCTEON_CIU_SUM_IPI); + } + if (octeon_ciu3_pending_intsn(s, cpu_index, irq, &intsn)) { level =3D true; } @@ -527,6 +568,189 @@ static uint64_t octeon_ciu3_source_cpu_mask(OcteonSta= te *s, unsigned int src) s, qatomic_read(&s->intc->ciu3_src_ctl[src])); } =20 +static uint64_t octeon_ciu_gpio_rx_value(OcteonState *s) +{ + uint64_t value =3D 0; + unsigned int i; + + for (i =3D 0; i < OCTEON_CIU_GPIO_COUNT; i++) { + uint64_t mask =3D 1ULL << i; + + if (qatomic_read(&s->intc->ciu_gpio_bit_cfg[i]) & + OCTEON_CIU_GPIO_BIT_CFG_TX_OE) { + if (qatomic_read(&s->intc->ciu_gpio_tx) & mask) { + value |=3D mask; + } + } else if (qatomic_read(&s->intc->ciu_gpio_rx) & mask) { + value |=3D mask; + } + } + + return value; +} + +static uint64_t octeon_ciu_read(void *opaque, hwaddr addr, unsigned size) +{ + OcteonState *s =3D opaque; + uint64_t value =3D 0; + hwaddr reg =3D addr & ~7ULL; + unsigned int cpu; + + if (reg =3D=3D 0) { + if (qatomic_read(&s->intc->uart_pending)) { + value |=3D OCTEON_CIU_SUM_UART; + } + octeon_intc_request_cpu_update(s, 0); + return octeon_read64(value, addr, size); + } + + if (reg =3D=3D OCTEON_CIU_IPI_EN_BASE) { + return octeon_read64(OCTEON_CIU_ENABLE0, addr, size); + } + + if (reg =3D=3D OCTEON_CIU_FUSE) { + value =3D octeon_present_cpu_mask(s); + return octeon_read64(value, addr, size); + } + + if (reg =3D=3D OCTEON_CIU_GPIO_RX_DAT) { + return octeon_read64(octeon_ciu_gpio_rx_value(s), addr, size); + } + + if (reg =3D=3D OCTEON_CIU_GPIO_TX_SET || + reg =3D=3D OCTEON_CIU_GPIO_TX_CLR) { + return octeon_read64(qatomic_read(&s->intc->ciu_gpio_tx), addr, si= ze); + } + + if (reg >=3D OCTEON_CIU_GPIO_BIT_CFGX(0) && + reg < OCTEON_CIU_GPIO_BIT_CFGX(OCTEON_CIU_GPIO_COUNT)) { + unsigned int index =3D (reg - OCTEON_CIU_GPIO_BIT_CFGX(0)) / + OCTEON_CIU_GPIO_BIT_CFG_STRIDE; + + return octeon_read64(qatomic_read(&s->intc->ciu_gpio_bit_cfg[index= ]), + addr, size); + } + + if (reg >=3D OCTEON_CIU_IPI_SUM_BASE && + reg < OCTEON_CIU_IPI_SUM_BASE + + OCTEON_MAX_CPUS * OCTEON_CIU_IPI_SUM_STRIDE && + ((reg - OCTEON_CIU_IPI_SUM_BASE) & + (OCTEON_CIU_IPI_SUM_STRIDE - 1)) =3D=3D 0) { + cpu =3D (reg - OCTEON_CIU_IPI_SUM_BASE) / OCTEON_CIU_IPI_SUM_STRID= E; + if (cpu < s->cpu_count && qatomic_read(&s->intc->ciu_mbox[cpu])) { + return octeon_read64(OCTEON_CIU_SUM_IPI, addr, size); + } + } + + if (reg >=3D OCTEON_CIU_IPI_EN_BASE && + reg < OCTEON_CIU_IPI_EN_BASE + + OCTEON_MAX_CPUS * OCTEON_CIU_IPI_EN_STRIDE && + ((reg - OCTEON_CIU_IPI_EN_BASE) & + (OCTEON_CIU_IPI_EN_STRIDE - 1)) =3D=3D 0) { + cpu =3D (reg - OCTEON_CIU_IPI_EN_BASE) / OCTEON_CIU_IPI_EN_STRIDE; + if (cpu < s->cpu_count) { + return octeon_read64(qatomic_read(&s->intc->ciu_ipi_en[cpu]), + addr, size); + } + } + + if (reg >=3D OCTEON_CIU_MBOX_CLR_BASE && + reg < OCTEON_CIU_MBOX_CLR_BASE + + OCTEON_MAX_CPUS * OCTEON_CIU_MBOX_SET_STRIDE && + ((reg - OCTEON_CIU_MBOX_CLR_BASE) & + (OCTEON_CIU_MBOX_SET_STRIDE - 1)) =3D=3D 0) { + cpu =3D (reg - OCTEON_CIU_MBOX_CLR_BASE) / OCTEON_CIU_MBOX_SET_STR= IDE; + if (cpu < s->cpu_count) { + return octeon_read64(qatomic_read(&s->intc->ciu_mbox[cpu]), + addr, size); + } + } + + return 0; +} + +static void octeon_ciu_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t old; + unsigned int cpu; + + if (reg >=3D OCTEON_CIU_IPI_EN_BASE && + reg < OCTEON_CIU_IPI_EN_BASE + + OCTEON_MAX_CPUS * OCTEON_CIU_IPI_EN_STRIDE && + ((reg - OCTEON_CIU_IPI_EN_BASE) & + (OCTEON_CIU_IPI_EN_STRIDE - 1)) =3D=3D 0) { + cpu =3D (reg - OCTEON_CIU_IPI_EN_BASE) / OCTEON_CIU_IPI_EN_STRIDE; + if (cpu < s->cpu_count) { + value =3D octeon_atomic_write64(&s->intc->ciu_ipi_en[cpu], add= r, + value, size, UINT64_MAX, 0, &old= ); + if (old !=3D value) { + octeon_intc_request_cpu_update(s, cpu); + } + } + return; + } + + if (reg >=3D OCTEON_CIU_MBOX_SET_BASE && + reg < OCTEON_CIU_MBOX_SET_BASE + + OCTEON_MAX_CPUS * OCTEON_CIU_MBOX_SET_STRIDE && + ((reg - OCTEON_CIU_MBOX_SET_BASE) & + (OCTEON_CIU_MBOX_SET_STRIDE - 1)) =3D=3D 0) { + cpu =3D (reg - OCTEON_CIU_MBOX_SET_BASE) / OCTEON_CIU_MBOX_SET_STR= IDE; + if (cpu < s->cpu_count) { + old =3D qatomic_fetch_or(&s->intc->ciu_mbox[cpu], value & UINT= 32_MAX); + if ((old | (value & UINT32_MAX)) !=3D old && + octeon_ciu3_set_mbox(s, cpu)) { + octeon_intc_request_cpu_update(s, cpu); + } + } + return; + } + + if (reg >=3D OCTEON_CIU_MBOX_CLR_BASE && + reg < OCTEON_CIU_MBOX_CLR_BASE + + OCTEON_MAX_CPUS * OCTEON_CIU_MBOX_SET_STRIDE && + ((reg - OCTEON_CIU_MBOX_CLR_BASE) & + (OCTEON_CIU_MBOX_SET_STRIDE - 1)) =3D=3D 0) { + cpu =3D (reg - OCTEON_CIU_MBOX_CLR_BASE) / OCTEON_CIU_MBOX_SET_STR= IDE; + if (cpu < s->cpu_count) { + old =3D qatomic_fetch_and(&s->intc->ciu_mbox[cpu], + ~(value & UINT32_MAX)); + if ((old & (value & UINT32_MAX)) && + octeon_ciu3_set_mbox(s, cpu)) { + octeon_intc_request_cpu_update(s, cpu); + } + } + return; + } + + if (reg =3D=3D OCTEON_CIU_GPIO_TX_SET) { + value =3D octeon_write64(0, addr, value, size) & + OCTEON_CIU_GPIO_INPUTS; + qatomic_or(&s->intc->ciu_gpio_tx, value); + return; + } + + if (reg =3D=3D OCTEON_CIU_GPIO_TX_CLR) { + value =3D octeon_write64(0, addr, value, size) & + OCTEON_CIU_GPIO_INPUTS; + qatomic_and(&s->intc->ciu_gpio_tx, ~value); + return; + } + + if (reg >=3D OCTEON_CIU_GPIO_BIT_CFGX(0) && + reg < OCTEON_CIU_GPIO_BIT_CFGX(OCTEON_CIU_GPIO_COUNT)) { + unsigned int index =3D (reg - OCTEON_CIU_GPIO_BIT_CFGX(0)) / + OCTEON_CIU_GPIO_BIT_CFG_STRIDE; + + octeon_atomic_write64(&s->intc->ciu_gpio_bit_cfg[index], addr, val= ue, + size, UINT64_MAX, 0, NULL); + return; + } +} + static void octeon_cpu_park_now(MIPSCPU *cpu) { CPUMIPSState *env =3D &cpu->env; @@ -591,6 +815,16 @@ static void octeon_ciu3_nmi(OcteonState *s, uint64_t m= ask) } } =20 +static const MemoryRegionOps octeon_ciu_ops =3D { + .read =3D octeon_ciu_read, + .write =3D octeon_ciu_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + static uint64_t octeon_ciu3_read(void *opaque, hwaddr addr, unsigned size) { OcteonState *s =3D opaque; @@ -799,6 +1033,7 @@ void octeon_irq_set(void *opaque, int irq, int level) if (!octeon_ciu3_set_level(s, src, level)) { return; } + qatomic_set(&s->intc->uart_pending, level); break; default: return; @@ -1042,6 +1277,12 @@ static void octeon_intc_reset_hold(Object *obj, Rese= tType type) opc->parent_phases.hold(obj, type); } =20 + memset(intc->ciu_mbox, 0, sizeof(intc->ciu_mbox)); + memset(intc->ciu_ipi_en, 0, sizeof(intc->ciu_ipi_en)); + qatomic_set(&intc->ciu_gpio_rx, OCTEON_CIU_GPIO_INPUTS); + qatomic_set(&intc->ciu_gpio_tx, 0); + memset(intc->ciu_gpio_bit_cfg, 0, sizeof(intc->ciu_gpio_bit_cfg)); + qatomic_set(&intc->uart_pending, false); qatomic_set(&intc->ciu3_pp_rst, octeon_secondary_cpu_mask(s)); memset(intc->ciu3_src_state, 0, sizeof(intc->ciu3_src_state)); memset(intc->ciu3_src_ctl, 0, sizeof(intc->ciu3_src_ctl)); @@ -1134,6 +1375,11 @@ static void mips_octeon_init(MachineState *machine) octeon_load_firmware(s); octeon_create_cpus(s); =20 + memory_region_init_io(&s->intc->ciu, OBJECT(s->intc), &octeon_ciu_ops,= s, + "octeon.ciu", OCTEON_CIU_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_CIU_BASE, + &s->intc->ciu); + memory_region_init_io(&s->intc->ciu3, OBJECT(s->intc), &octeon_ciu3_ops, s, "octeon.ciu3", OCTEON_CIU3_SIZE); diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index fef88419b5..cd810f3dd5 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -14,6 +14,7 @@ #include "target/mips/cpu.h" =20 #define OCTEON_MAX_CPUS 16 +#define OCTEON_CIU_GPIO_COUNT 32 #define OCTEON_CIU3_CP0_IRQ_COUNT 4 #define OCTEON_CIU3_IDT_COUNT (OCTEON_MAX_CPUS * 4) =20 --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437272928404.3844331101444; Thu, 3 Sep 2026 05:07:52 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CI-0002uv-Lf; Thu, 03 Sep 2026 08:05:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CH-0002u5-1o for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:37 -0400 Received: from mx1.catap.net ([2a01:4f8:271:125e::2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CE-0005L8-Jl for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:36 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 6ec0d3b4 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:28 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id ee385e07; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=oP+Hws9 s98Pbwlg+6Wf7Ki/ET4uJLtAFdtwG1ZCuE7o7e9v5pgQ2umexLcN4vgX6JVhXuorqhR9Wh r2nquBdsKjv0lQ0sywIkW/vmiQCDE5dWQ78I8NyWRttX93YGJvrV0UHMQVlNcEwLlUAQTj 5x21i1+IR6L5hu0wdGJcCc79cwywYHVCqlUA0ZV03P7R50JjIqRxeIaIW3yEp/4D/abbM5 SN88EwNAd1tN6LF8w8m5hmfsrBWIeWSzXfamaap7psyNhyazXoDUerBtD2Kglt2voq+Rkd qcAViz3zNjsIkLDxGnVHsDbdVzN0YqfGihsd/J1SeZHdl/SILS9IoVQ== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=Q oF6Ukat3D3zNqldaJ2X6rAo1er7s3SapxN867lmMIQ=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=s8+bKLJ7tL8pfTnAgu7ulom0uWS9I2LMgNORdVSFVcYyqnErKjw6vQ+jm1+Pk5IlH0sM AkPGOXg7RY8F3DPuhV71aqG83eluKoUYHrHjiHjuXdkRmwaqOD7Irh/CBV9fMlnu41NDpR LvixkeDk/hQM/+qLMxT0lM47q6uLoZMqACSogeiqf4dTokXnCFFhm0nBEcM89B1w5KIsFd 4250cjOyJnK45g3QmM8XzLZ+j3u/NJoRMbyyINAQqiZuOi0gFSolctT3QAvQB3eMxJkMum V/hvaG3xeMoNuaT4wsgbIBwQmZc1ZbQ56qfOZbt4V7akzaHvwBARnJEvTjBX1jSg== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=eytrx525; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=mmj3eWtX; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=QoF6Ukat 3D3zNqldaJ2X6rAo1er7s3SapxN867lmMIQ=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=eytrx525e7v0hkTtO3YXxThEAwBO4SdEaWX K59eeoTVDlQHt8UWyp6XI2h5P7tobyRmerLPRj10pTk0FOEcsrZ2F1UjFUdyr/8K6vNeqc WVDNrz3eCpqAsXTGuANOqNU4QzdySI0v+ycNwXO/NMgajke9ZKMaliLT3OhDyQD8qNnZAF b8GlCgWBU5OQA7q8K9nTnYRwVU+BGwUiDBA1rXJAzN7RriS0NdSwsI4gKNo7a4zMMoE7Zy E+OWZx/rjX5JgMkYiHJ4jNJV+NW9IHTS8TuDFqBWiZX1V45w4S60MNxARwZamFkt2G38QL qDPk9qCqrgNWbBJM063vk7eBFuA== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=QoF6Ukat3D3zNqldaJ2X6rAo1er7s3SapxN867lmMIQ=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=mmj3eWtX2r7U9lCchu +KvVCDB9U9bGQ2mQ+WuhcpUsRkg6yKyo5ilavif2AHKLL1ho0xxx1wU0KkTz7tHGfKDg== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 14/25] hw/mips: add Octeon CSR window Date: Thu, 3 Sep 2026 14:02:02 +0200 Message-ID: <20260903120510.34876-15-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a01:4f8:271:125e::2; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437274338158500 Content-Type: text/plain; charset="utf-8" Add the shared CSR window and backing register storage. Keep mutable state in a resettable CSR bank device so later controllers can route their registers through it. --- hw/mips/octeon.c | 146 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 7 ++ 2 files changed, 153 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 638d96559f..0caf088adf 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -41,6 +41,8 @@ OBJECT_DECLARE_TYPE(OcteonPeripheralState, OcteonPeripher= alClass, OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST) #define TYPE_OCTEON_INTC "octeon-intc" OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) +#define TYPE_OCTEON_CSR_BANK "octeon-csr-bank" +OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR_BANK) =20 #define OCTEON_CSR_64BIT_SIZE 8 =20 @@ -120,6 +122,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) #define OCTEON_CIU3_ISC_SIZE (OCTEON_CIU3_NINTSN * 8) #define OCTEON_CIU3_MBOX_INTSN(cpu) ((cpu) + 0x4000U) #define OCTEON_CIU3_UART0_INTSN 0x8000 +#define OCTEON_CSR_BASE 0x1180000000000ULL +#define OCTEON_CSR_SIZE 0x100000000ULL /* * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; * the guest sees the virtual CVMSEG window, not this physical address. @@ -187,6 +191,24 @@ struct OcteonIntcState { uint8_t ciu3_irq_line[OCTEON_MAX_CPUS][OCTEON_CIU3_CP0_IRQ_COUNT]; }; =20 +struct OcteonCsrBankState { + OcteonPeripheralState parent_obj; + MemoryRegion csr; + GHashTable *values; +}; + +guint octeon_uint64_hash(gconstpointer v) +{ + uint64_t value =3D *(const uint64_t *)v; + + return value ^ (value >> 32); +} + +gboolean octeon_uint64_equal(gconstpointer a, gconstpointer b) +{ + return *(const uint64_t *)a =3D=3D *(const uint64_t *)b; +} + uint64_t octeon_read64(uint64_t value, hwaddr addr, unsigned size) { if (size =3D=3D 4) { @@ -248,6 +270,38 @@ static void octeon_validate_clocks(OcteonMachineState = *oms) } } =20 +bool octeon_reg_lookup(GHashTable *regs, uint64_t reg, uint64_t *value) +{ + uint64_t *stored =3D g_hash_table_lookup(regs, ®); + + if (!stored) { + return false; + } + + *value =3D *stored; + return true; +} + +void octeon_reg_store(GHashTable *regs, uint64_t reg, uint64_t value) +{ + uint64_t *key =3D g_new(uint64_t, 1); + uint64_t *stored =3D g_new(uint64_t, 1); + + *key =3D reg; + *stored =3D value; + g_hash_table_replace(regs, key, stored); +} + +bool octeon_csr_lookup(OcteonState *s, uint64_t reg, uint64_t *value) +{ + return octeon_reg_lookup(s->csr_bank->values, reg, value); +} + +static void octeon_csr_store(OcteonState *s, uint64_t reg, uint64_t value) +{ + octeon_reg_store(s->csr_bank->values, reg, value); +} + static bool octeon_ciu3_source_from_intsn(uint32_t intsn, unsigned int *source) { @@ -1022,6 +1076,42 @@ static const MemoryRegionOps octeon_ciu3_ops =3D { }, }; =20 +static uint64_t octeon_csr_read(void *opaque, hwaddr addr, unsigned size) +{ + OcteonState *s =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t value; + + if (!octeon_csr_lookup(s, reg, &value)) { + value =3D 0; + } + return octeon_read64(value, addr, size); +} + +static void octeon_csr_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t old; + + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); +} + +static const MemoryRegionOps octeon_csr_ops =3D { + .read =3D octeon_csr_read, + .write =3D octeon_csr_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + void octeon_irq_set(void *opaque, int irq, int level) { OcteonState *s =3D opaque; @@ -1294,6 +1384,18 @@ static void octeon_intc_reset_hold(Object *obj, Rese= tType type) octeon_intc_update_all_cpus(s); } =20 +static void octeon_csr_bank_reset_hold(Object *obj, ResetType type) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); + OcteonCsrBankState *bank =3D OCTEON_CSR_BANK(obj); + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + g_hash_table_remove_all(bank->values); +} + static void octeon_peripheral_class_init(ObjectClass *klass, const void *data) { @@ -1302,6 +1404,23 @@ static void octeon_peripheral_class_init(ObjectClass= *klass, dc->user_creatable =3D false; } =20 +static GHashTable *octeon_reg_table_new(void) +{ + return g_hash_table_new_full(octeon_uint64_hash, + octeon_uint64_equal, + g_free, g_free); +} + +static void octeon_csr_bank_init(Object *obj) +{ + OCTEON_CSR_BANK(obj)->values =3D octeon_reg_table_new(); +} + +static void octeon_csr_bank_finalize(Object *obj) +{ + g_hash_table_destroy(OCTEON_CSR_BANK(obj)->values); +} + static void octeon_rst_class_init(ObjectClass *klass, const void *data) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); @@ -1320,6 +1439,16 @@ static void octeon_intc_class_init(ObjectClass *klas= s, const void *data) NULL, &opc->parent_phases); } =20 +static void octeon_csr_bank_class_init(ObjectClass *klass, const void *dat= a) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + resettable_class_set_parent_phases(rc, NULL, + octeon_csr_bank_reset_hold, NULL, + &opc->parent_phases); +} + static OcteonPeripheralState *octeon_new_peripheral(OcteonState *s, const char *type, unsigned int index) @@ -1336,6 +1465,8 @@ static void octeon_create_peripherals(OcteonState *s) { s->rst =3D OCTEON_RST(octeon_new_peripheral(s, TYPE_OCTEON_RST, 0)); s->intc =3D OCTEON_INTC(octeon_new_peripheral(s, TYPE_OCTEON_INTC, 0)); + s->csr_bank =3D OCTEON_CSR_BANK(octeon_new_peripheral( + s, TYPE_OCTEON_CSR_BANK, 0)); } =20 static void octeon_realize_peripheral(OcteonPeripheralState *dev) @@ -1347,6 +1478,7 @@ static void octeon_realize_peripherals(OcteonState *s) { octeon_realize_peripheral(&s->intc->parent_obj); octeon_realize_peripheral(&s->rst->parent_obj); + octeon_realize_peripheral(&s->csr_bank->parent_obj); } =20 static void mips_octeon_init(MachineState *machine) @@ -1386,6 +1518,12 @@ static void mips_octeon_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), OCTEON_CIU3_BASE, &s->intc->ciu3); =20 + memory_region_init_io(&s->csr_bank->csr, OBJECT(s->csr_bank), + &octeon_csr_ops, s, + "octeon.csr", OCTEON_CSR_SIZE); + memory_region_add_subregion_overlap(get_system_memory(), OCTEON_CSR_BA= SE, + &s->csr_bank->csr, -1); + octeon_realize_peripherals(s); } =20 @@ -1464,6 +1602,14 @@ static const TypeInfo octeon_machine_types[] =3D { .instance_size =3D sizeof(OcteonIntcState), .class_init =3D octeon_intc_class_init, }, + { + .name =3D TYPE_OCTEON_CSR_BANK, + .parent =3D TYPE_OCTEON_PERIPHERAL, + .instance_size =3D sizeof(OcteonCsrBankState), + .instance_init =3D octeon_csr_bank_init, + .instance_finalize =3D octeon_csr_bank_finalize, + .class_init =3D octeon_csr_bank_class_init, + }, { .name =3D TYPE_OCTEON_MACHINE, .parent =3D TYPE_MACHINE, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index cd810f3dd5..6327103f52 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -32,6 +32,7 @@ typedef enum OcteonCiu3Source { typedef struct OcteonState OcteonState; typedef struct OcteonRstState OcteonRstState; typedef struct OcteonIntcState OcteonIntcState; +typedef struct OcteonCsrBankState OcteonCsrBankState; =20 typedef struct OcteonCPUState { OcteonState *board; @@ -58,11 +59,17 @@ struct OcteonState { MemoryRegion cvmseg; OcteonRstState *rst; OcteonIntcState *intc; + OcteonCsrBankState *csr_bank; }; =20 +guint octeon_uint64_hash(gconstpointer v); +gboolean octeon_uint64_equal(gconstpointer a, gconstpointer b); uint64_t octeon_read64(uint64_t value, hwaddr addr, unsigned size); uint64_t octeon_write64(uint64_t old, hwaddr addr, uint64_t value, unsigned size); +bool octeon_reg_lookup(GHashTable *regs, uint64_t reg, uint64_t *value); +void octeon_reg_store(GHashTable *regs, uint64_t reg, uint64_t value); +bool octeon_csr_lookup(OcteonState *s, uint64_t reg, uint64_t *value); void octeon_irq_set(void *opaque, int irq, int level); =20 #endif --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437204473901.7863921107305; Thu, 3 Sep 2026 05:06:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CK-0002vp-A0; Thu, 03 Sep 2026 08:05:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CI-0002ua-7J for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:38 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CF-0005JF-MV for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:37 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 8478a0f5 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:28 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id ac7e1cfb; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=UraalP3 BuET368LJ+o/Ghs+5KCmoIzl6E8S2UEhpBdbdO8rddwZs2WLKqwlHHIqldtTY0CkFg9Y0Y VsTLKOkK/jtnEZUt4jmOEvJ9PFAGdeaK7S18EGjEwD/RYfiBXcjV2vyIyYhxdWFuB1rH5L QhwF8PuDWep8DiE8tSnlaKb+fri+MtO1uVaSUN78DHl2S35ZcqAu2kzXCUUc2rcZlguhLR 7F0ZqWtXmbsqCH4WthzS7l2QFnDaSl6OahiIk2DHxOqrIuYD/6KmqqNZjWjp+8hODywIGE N+Xno3EoDYEtdvFSGJqZxG2QDv7V22TapSxcJfKPI+2Xh1fq93r6UBA== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=+ g6cefjhdRUctd5g+HiBEWs0l+/VE1gDPtxIHqa5foI=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=My1KLrF5btLnTAfxPSVGHqQHWICAHWSPaGQCjmk97eTalNmO2NiciHuYTNRBw+mRFoTg WnyiMTny/qU740GfAIdcgTd83hcelFxoGZjhpSFxPd95ADuklh4oo304gFb0zOWSIY4fa4 UpIlx2UUCxoz+usX2KonwlC4wzknbgm/421HAX3hhP1r2xvD7YSoy+E8+OtCIY6fmnRqIX tJyM7etviztYqsgkYsiIkvm8utJLoblcxyf11NaLtFCF7HLwfVYWSbdtIetH+OZ1wojto6 cd9w3NdesMcu4XPYDXoNVwJgfGMMOtC/mohnZTOw06qq7746pMRdYkg38Pc4Z66Q== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=HgYyOulL; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=4Ht1w6U8; arc=none; iprev=fail; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=+g6cefjh dRUctd5g+HiBEWs0l+/VE1gDPtxIHqa5foI=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=HgYyOulLVdMwqrC5CAPbxss0+OFFsoFD8ay b74c8yZ7mO7oUKLomVAKWRMJfTO94X+kzu4aFaUx67TSoIMZ4zdo9OSPLWg1wDavkdm/+T Dejvkv93emVaFVyFh+ISq04tGade9PATICRAkWHyKH/SMHB6NEht5kr38dC211lxl2hKgY MGf3J/UB8ADmMMBZcYJ6ENh8T5GFW6lzVcSMRvaURfYt+GDsKTrGZhJqwqrPm2Gb7Yl4Lv /iBEnN06UP/B7sj1OUpP75LvdYROVBIoKMUvi1fBs9o0vN5PCRRrTwIthtG0D+IX5cjJP2 yhwhpdM1glZZYg4lnoV3dz2t79A== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=+g6cefjhdRUctd5g+HiBEWs0l+/VE1gDPtxIHqa5foI=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=4Ht1w6U8hJ9PxgxGjG AInkjH2z+8EoFa1t7YSufsHVeSlw1dItyaVwAccnnni2jjkuXdXzFExhKoe5EX0ju+AQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 15/25] hw/mips: expose Octeon reset CSRs Date: Thu, 3 Sep 2026 14:02:03 +0200 Message-ID: <20260903120510.34876-16-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437205670158500 Content-Type: text/plain; charset="utf-8" Expose reset clock, soft reset and processor power registers through the shared CSR window. Keep mutable register state and reset handling in the reset controller. --- hw/mips/octeon.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 0caf088adf..007fc4b537 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -24,6 +24,8 @@ #include "system/cpus.h" #include "system/memory.h" #include "system/reset.h" +#include "system/runstate.h" +#include "system/system.h" #include "exec/cpu-interrupt.h" #include "qemu/error-report.h" #include "qemu/atomic.h" @@ -124,6 +126,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_= CSR_BANK) #define OCTEON_CIU3_UART0_INTSN 0x8000 #define OCTEON_CSR_BASE 0x1180000000000ULL #define OCTEON_CSR_SIZE 0x100000000ULL +#define OCTEON_RST_BOOT 0x6001600 +#define OCTEON_RST_SOFT_RST 0x6001680 +/* U-Boot uses the reset controller to park and release secondary cores. */ +#define OCTEON_RST_PP_POWER 0x6001700 +#define OCTEON_RST_BOOT_C_MUL_SHIFT 30 +#define OCTEON_RST_BOOT_PNR_MUL_SHIFT 24 /* * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; * the guest sees the virtual CVMSEG window, not this physical address. @@ -168,6 +176,7 @@ struct OcteonPeripheralClass { =20 struct OcteonRstState { OcteonPeripheralState parent_obj; + GHashTable *regs; uint64_t rst_pp_power; }; =20 @@ -294,11 +303,18 @@ void octeon_reg_store(GHashTable *regs, uint64_t reg,= uint64_t value) =20 bool octeon_csr_lookup(OcteonState *s, uint64_t reg, uint64_t *value) { + if (reg =3D=3D OCTEON_RST_SOFT_RST) { + return octeon_reg_lookup(s->rst->regs, reg, value); + } return octeon_reg_lookup(s->csr_bank->values, reg, value); } =20 static void octeon_csr_store(OcteonState *s, uint64_t reg, uint64_t value) { + if (reg =3D=3D OCTEON_RST_SOFT_RST) { + octeon_reg_store(s->rst->regs, reg, value); + return; + } octeon_reg_store(s->csr_bank->values, reg, value); } =20 @@ -869,6 +885,33 @@ static void octeon_ciu3_nmi(OcteonState *s, uint64_t m= ask) } } =20 +static void octeon_rst_pp_power_write(OcteonState *s, hwaddr addr, + uint64_t value, unsigned size) +{ + uint64_t old =3D s->rst->rst_pp_power; + uint64_t changed; + unsigned int cpu; + + value =3D octeon_write64(old, addr, value, size) & + octeon_present_cpu_mask(s); + s->rst->rst_pp_power =3D value; + changed =3D old ^ value; + + for (cpu =3D 1; cpu < s->cpu_count; cpu++) { + uint64_t mask =3D 1ULL << cpu; + + if (!(changed & mask)) { + continue; + } + if (value & mask) { + async_run_on_cpu(CPU(s->cpu[cpu].cpu), octeon_cpu_park_work, + RUN_ON_CPU_NULL); + } else { + octeon_start_cpu(s, cpu); + } + } +} + static const MemoryRegionOps octeon_ciu_ops =3D { .read =3D octeon_ciu_read, .write =3D octeon_ciu_write, @@ -1082,6 +1125,19 @@ static uint64_t octeon_csr_read(void *opaque, hwaddr= addr, unsigned size) hwaddr reg =3D addr & ~7ULL; uint64_t value; =20 + switch (reg) { + case OCTEON_RST_BOOT: + value =3D ((uint64_t)(s->cpu_hz / s->ref_hz) << + OCTEON_RST_BOOT_C_MUL_SHIFT) | + ((uint64_t)(s->io_hz / s->ref_hz) << + OCTEON_RST_BOOT_PNR_MUL_SHIFT); + return octeon_read64(value, addr, size); + case OCTEON_RST_PP_POWER: + return octeon_read64(s->rst->rst_pp_power, addr, size); + default: + break; + } + if (!octeon_csr_lookup(s, reg, &value)) { value =3D 0; } @@ -1095,6 +1151,16 @@ static void octeon_csr_write(void *opaque, hwaddr ad= dr, hwaddr reg =3D addr & ~7ULL; uint64_t old; =20 + if (reg =3D=3D OCTEON_RST_SOFT_RST && value) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; + } + + if (reg =3D=3D OCTEON_RST_PP_POWER) { + octeon_rst_pp_power_write(s, addr, value, size); + return; + } + if (!octeon_csr_lookup(s, reg, &old)) { old =3D 0; } @@ -1354,6 +1420,7 @@ static void octeon_rst_reset_hold(Object *obj, ResetT= ype type) opc->parent_phases.hold(obj, type); } =20 + g_hash_table_remove_all(rst->regs); rst->rst_pp_power =3D octeon_secondary_cpu_mask(rst->parent_obj.board); } =20 @@ -1411,6 +1478,16 @@ static GHashTable *octeon_reg_table_new(void) g_free, g_free); } =20 +static void octeon_rst_init(Object *obj) +{ + OCTEON_RST(obj)->regs =3D octeon_reg_table_new(); +} + +static void octeon_rst_finalize(Object *obj) +{ + g_hash_table_destroy(OCTEON_RST(obj)->regs); +} + static void octeon_csr_bank_init(Object *obj) { OCTEON_CSR_BANK(obj)->values =3D octeon_reg_table_new(); @@ -1594,6 +1671,8 @@ static const TypeInfo octeon_machine_types[] =3D { .name =3D TYPE_OCTEON_RST, .parent =3D TYPE_OCTEON_PERIPHERAL, .instance_size =3D sizeof(OcteonRstState), + .instance_init =3D octeon_rst_init, + .instance_finalize =3D octeon_rst_finalize, .class_init =3D octeon_rst_class_init, }, { --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437267768123.22447007583855; Thu, 3 Sep 2026 05:07:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CW-00038E-8u; Thu, 03 Sep 2026 08:05:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CJ-0002vW-63 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:39 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CG-0005LJ-41 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:38 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 00894cc6 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:29 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id f5d3415c; Thu, 3 Sep 2026 14:05:15 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=Qn6dR6F s96vKS4+mgrnO8CjtvcDILrBf0v6VqUbo3XtsTxohPcnVjnImIRA31E2TIaS5pMNg2mdV4 jB44lgCkXxrfHfPAr5Sv6y4hnYtsoV8AHEtJ5c1t8IdybLROk9RgCSfPTi+M8FZw1q8+gn 2ttmKGQUYeh9Zs8s7tNFxSVuiObLRgf1ZZ/UokTGvdl5LVvpUN4vhD5ddLRSY9YsCdru8m /89mZzohInrGzWIFaPiv9x2evcE9hEGirs7OToU8h75zTblRroaP5eWm+HYUL32Cgz1gCg xRGIKP+fEnHRxU1VJTN4tyHi+OvSP2V0xi5ar2t7vRNszlqHks4TIaA== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=R eWD25dQSvYB7Ud+ELeirimQjLKYDoMueaIiBUqGH9M=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=HO6suBSICQsnq174iFEwQqDRg5f+uPjnpn0XUgBLdSQLPTRBjdWlsfhGtMGXWZFQARFa crn3Sfb1/Wa434aqQ37nJqZQJRHFuyHGNyg4PzSN+UIhhCYVj/qK3Xlr1KqPE89NS365Jc oClyM4LtyuyTVHORnswhXuCQi3TZT3ZPG51R0LHdYIhZ2RQxH6D1pEfILiv0KajQGNHzhX JqDN7nUPCYotTWWEFz+UbMjb0JZSHXqunID4IgqmVSd5ykfTCvy+PqkKlcE1k3z617v6Bt clPW5TspA0lhCSI5LwkRg9G0xvWOz58THv0xCqsRJJ7CIO3oPgF5voiHBYnRFfbQ== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=AAUpISRZ; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=+ETVEYPx; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=ReWD25dQ SvYB7Ud+ELeirimQjLKYDoMueaIiBUqGH9M=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=AAUpISRZaTurfpYcuymKDFSvbpX1Lv+zF4k pYL1RKu3aT4uzlc79T/RFWNR6s0SxwdGgE61ODa+yp3vXhtXT6GMh9tAVYeGA1T9NNhha3 WDdDW58ZYz7HSVWBWHNzEGTVIb2la5kMQOvGk0Vmlv5IKfmVE3j8/2nGvbDKJYTe1ex+BS 7LSS5T4ZaGiwvOpTZjfcKI1eFTRVZmjOnjo7V7xEB8mpBhgxmoKa+TXKATh4/Cvngi5zqi BXMSPESRtOlvXT34clxNgxOSzHey2X05Sg4R2sLV9oEvI8e7T6/habO88Cy2qMGvtjaHMn Vei+Phq1lsmzWpWkTXZMq5pXF/w== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=ReWD25dQSvYB7Ud+ELeirimQjLKYDoMueaIiBUqGH9M=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=+ETVEYPx71gJ12rRNN K4rtE9ima4OhPLiCm2t9NsAOG2M/M2qHd1yq/VB08HA5IFunM5V8f0Vu8dP4ElHDvjBQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 16/25] hw/mips: add Octeon MIO boot support Date: Thu, 3 Sep 2026 14:02:04 +0200 Message-ID: <20260903120510.34876-17-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437268223158500 Content-Type: text/plain; charset="utf-8" Add MIO boot bus configuration, boot location storage and fuse responses. Keep mutable state and memory mappings in a resettable MIO device. --- hw/mips/octeon.c | 248 +++++++++++++++++++++++++++++++++++++- hw/mips/octeon_internal.h | 4 + 2 files changed, 250 insertions(+), 2 deletions(-) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 007fc4b537..59754cb741 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -39,6 +39,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonMachineState, OCTEON_MAC= HINE) OBJECT_DECLARE_TYPE(OcteonPeripheralState, OcteonPeripheralClass, OCTEON_PERIPHERAL) =20 +#define TYPE_OCTEON_MIO "octeon-mio" +OBJECT_DECLARE_SIMPLE_TYPE(OcteonMioState, OCTEON_MIO) #define TYPE_OCTEON_RST "octeon-rst" OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST) #define TYPE_OCTEON_INTC "octeon-intc" @@ -126,12 +128,33 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON= _CSR_BANK) #define OCTEON_CIU3_UART0_INTSN 0x8000 #define OCTEON_CSR_BASE 0x1180000000000ULL #define OCTEON_CSR_SIZE 0x100000000ULL +#define OCTEON_MIO_BOOT_REG_CFGX(x) \ + (0x0000000 + (x) * OCTEON_CSR_64BIT_SIZE) +#define OCTEON_MIO_BOOT_REG_CFG_INDEX(reg) \ + ((reg) / OCTEON_CSR_64BIT_SIZE) +#define OCTEON_MIO_BOOT_REG_CFG_BASE 0x000000000000ffffULL +#define OCTEON_MIO_BOOT_LOC_CFGX(x) \ + (0x0000080 + ((x) & 1) * OCTEON_CSR_64BIT_SIZE) +#define OCTEON_MIO_BOOT_LOC_CFG_INDEX(reg) \ + (((reg) - OCTEON_MIO_BOOT_LOC_CFGX(0)) / OCTEON_CSR_64BIT_SIZE) +#define OCTEON_MIO_BOOT_LOC_ADR 0x0000090 +#define OCTEON_MIO_BOOT_LOC_DAT 0x0000098 +#define OCTEON_MIO_BOOT_LOC_CFG_BASE 0x000000000ffffff8ULL +#define OCTEON_MIO_BOOT_LOC_CFG_BASE_SHIFT 3 +#define OCTEON_MIO_BOOT_LOC_CFG_EN 0x0000000080000000ULL +#define OCTEON_MIO_BOOT_LOC_ADR_MASK 0xf8 +/* Fuses are left unprogrammed; firmware only needs reads to complete. */ +#define OCTEON_MIO_FUS_DAT2 0x0001410 +#define OCTEON_MIO_FUS_RCMD 0x0001500 +#define OCTEON_MIO_FUS_RCMD_PEND 0x0000000000001000ULL +#define OCTEON_MIO_FUS_RCMD_DAT 0x0000000000ff0000ULL #define OCTEON_RST_BOOT 0x6001600 #define OCTEON_RST_SOFT_RST 0x6001680 /* U-Boot uses the reset controller to park and release secondary cores. */ #define OCTEON_RST_PP_POWER 0x6001700 #define OCTEON_RST_BOOT_C_MUL_SHIFT 30 #define OCTEON_RST_BOOT_PNR_MUL_SHIFT 24 + /* * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; * the guest sees the virtual CVMSEG window, not this physical address. @@ -153,6 +176,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_C= SR_BANK) #define OCTEON_FLASH_ENV_OFFSET \ (OCTEON_FLASH_SIZE - OCTEON_FLASH_ENV_SECTOR_SIZE) #define OCTEON_FLASH_WIDTH 2 +#define OCTEON_MIO_BOOT_REG_CFG_RESET_BASE (OCTEON_FLASH_RESET_BASE >> 16) +#define OCTEON_BOOTBUS_LED_CS 4 +#define OCTEON_BOOTBUS_LED_SIZE (64 * KiB) =20 struct OcteonMachineState { MachineState parent_obj; @@ -174,6 +200,21 @@ struct OcteonPeripheralClass { ResettablePhases parent_phases; }; =20 +struct OcteonMioState { + OcteonPeripheralState parent_obj; + MemoryRegion bootbus_led; + MemoryRegion mio_boot_loc; + uint64_t mio_boot_reg_cfg[OCTEON_MIO_BOOT_REG_CFG_COUNT]; + uint64_t mio_boot_loc_cfg[2]; + uint64_t mio_boot_loc_adr; + uint64_t mio_fus_rcmd; + hwaddr mio_boot_loc_base; + uint8_t mio_boot_loc_data[OCTEON_MIO_BOOT_LOC_SIZE]; + bool mio_boot_loc_mapped; + hwaddr bootbus_led_base; + bool bootbus_led_mapped; +}; + struct OcteonRstState { OcteonPeripheralState parent_obj; GHashTable *regs; @@ -318,6 +359,89 @@ static void octeon_csr_store(OcteonState *s, uint64_t = reg, uint64_t value) octeon_reg_store(s->csr_bank->values, reg, value); } =20 +static hwaddr octeon_mio_boot_loc_base(uint64_t cfg) +{ + uint64_t base =3D (cfg & OCTEON_MIO_BOOT_LOC_CFG_BASE) >> + OCTEON_MIO_BOOT_LOC_CFG_BASE_SHIFT; + + return base << 7; +} + +static void octeon_mio_boot_loc_update(OcteonState *s) +{ + MemoryRegion *sysmem =3D get_system_memory(); + bool enabled =3D s->mio->mio_boot_loc_cfg[0] & OCTEON_MIO_BOOT_LOC_CFG= _EN; + hwaddr base =3D octeon_mio_boot_loc_base(s->mio->mio_boot_loc_cfg[0]); + + if (s->mio->mio_boot_loc_mapped) { + if (enabled && base =3D=3D s->mio->mio_boot_loc_base) { + return; + } + memory_region_del_subregion(sysmem, &s->mio->mio_boot_loc); + s->mio->mio_boot_loc_mapped =3D false; + } + + if (enabled) { + memory_region_add_subregion_overlap(sysmem, base, + &s->mio->mio_boot_loc, 1); + s->mio->mio_boot_loc_base =3D base; + s->mio->mio_boot_loc_mapped =3D true; + } +} + +static hwaddr octeon_mio_boot_reg_cfg_base(uint64_t cfg) +{ + return (cfg & OCTEON_MIO_BOOT_REG_CFG_BASE) << 16; +} + +static void octeon_bootbus_led_update(OcteonState *s) +{ + MemoryRegion *sysmem =3D get_system_memory(); + hwaddr base =3D octeon_mio_boot_reg_cfg_base( + s->mio->mio_boot_reg_cfg[OCTEON_BOOTBUS_LED_CS]); + + if (s->mio->bootbus_led_mapped) { + if (base =3D=3D s->mio->bootbus_led_base) { + return; + } + memory_region_del_subregion(sysmem, &s->mio->bootbus_led); + s->mio->bootbus_led_mapped =3D false; + } + + if (base) { + memory_region_add_subregion(sysmem, base, &s->mio->bootbus_led); + s->mio->bootbus_led_base =3D base; + s->mio->bootbus_led_mapped =3D true; + } +} + +static uint64_t octeon_mio_boot_loc_dat_read(OcteonState *s) +{ + unsigned int offset =3D s->mio->mio_boot_loc_adr & + OCTEON_MIO_BOOT_LOC_ADR_MASK; + uint64_t value =3D ldq_be_p(s->mio->mio_boot_loc_data + offset); + + s->mio->mio_boot_loc_adr =3D + (s->mio->mio_boot_loc_adr + OCTEON_CSR_64BIT_SIZE) & + OCTEON_MIO_BOOT_LOC_ADR_MASK; + return value; +} + +static void octeon_mio_boot_loc_dat_write(OcteonState *s, hwaddr addr, + uint64_t value, unsigned size) +{ + unsigned int offset =3D s->mio->mio_boot_loc_adr & + OCTEON_MIO_BOOT_LOC_ADR_MASK; + uint64_t old =3D ldq_be_p(s->mio->mio_boot_loc_data + offset); + + value =3D octeon_write64(old, addr, value, size); + stq_be_p(s->mio->mio_boot_loc_data + offset, value); + memory_region_set_dirty(&s->mio->mio_boot_loc, offset, sizeof(value)); + s->mio->mio_boot_loc_adr =3D + (s->mio->mio_boot_loc_adr + OCTEON_CSR_64BIT_SIZE) & + OCTEON_MIO_BOOT_LOC_ADR_MASK; +} + static bool octeon_ciu3_source_from_intsn(uint32_t intsn, unsigned int *source) { @@ -1125,7 +1249,28 @@ static uint64_t octeon_csr_read(void *opaque, hwaddr= addr, unsigned size) hwaddr reg =3D addr & ~7ULL; uint64_t value; =20 + if (reg >=3D OCTEON_MIO_BOOT_REG_CFGX(0) && + reg < OCTEON_MIO_BOOT_REG_CFGX(OCTEON_MIO_BOOT_REG_CFG_COUNT)) { + unsigned int index =3D OCTEON_MIO_BOOT_REG_CFG_INDEX(reg); + + return octeon_read64(s->mio->mio_boot_reg_cfg[index], addr, size); + } + switch (reg) { + case OCTEON_MIO_BOOT_LOC_CFGX(0): + case OCTEON_MIO_BOOT_LOC_CFGX(1): { + unsigned int index =3D OCTEON_MIO_BOOT_LOC_CFG_INDEX(reg); + + return octeon_read64(s->mio->mio_boot_loc_cfg[index], addr, size); + } + case OCTEON_MIO_BOOT_LOC_ADR: + return octeon_read64(s->mio->mio_boot_loc_adr, addr, size); + case OCTEON_MIO_BOOT_LOC_DAT: + return octeon_read64(octeon_mio_boot_loc_dat_read(s), addr, size); + case OCTEON_MIO_FUS_DAT2: + return 0; + case OCTEON_MIO_FUS_RCMD: + return octeon_read64(s->mio->mio_fus_rcmd, addr, size); case OCTEON_RST_BOOT: value =3D ((uint64_t)(s->cpu_hz / s->ref_hz) << OCTEON_RST_BOOT_C_MUL_SHIFT) | @@ -1156,11 +1301,56 @@ static void octeon_csr_write(void *opaque, hwaddr a= ddr, return; } =20 + if (reg =3D=3D OCTEON_MIO_BOOT_LOC_CFGX(0) || + reg =3D=3D OCTEON_MIO_BOOT_LOC_CFGX(1)) { + unsigned int index =3D OCTEON_MIO_BOOT_LOC_CFG_INDEX(reg); + + old =3D s->mio->mio_boot_loc_cfg[index]; + s->mio->mio_boot_loc_cfg[index] =3D + octeon_write64(old, addr, value, size); + if (index =3D=3D 0) { + octeon_mio_boot_loc_update(s); + } + return; + } + + if (reg =3D=3D OCTEON_MIO_BOOT_LOC_ADR) { + old =3D s->mio->mio_boot_loc_adr; + value =3D octeon_write64(old, addr, value, size); + s->mio->mio_boot_loc_adr =3D value & OCTEON_MIO_BOOT_LOC_ADR_MASK; + return; + } + + if (reg =3D=3D OCTEON_MIO_BOOT_LOC_DAT) { + octeon_mio_boot_loc_dat_write(s, addr, value, size); + return; + } + + if (reg =3D=3D OCTEON_MIO_FUS_RCMD) { + value =3D octeon_write64(s->mio->mio_fus_rcmd, addr, value, size); + s->mio->mio_fus_rcmd =3D value & ~(OCTEON_MIO_FUS_RCMD_PEND | + OCTEON_MIO_FUS_RCMD_DAT); + return; + } + if (reg =3D=3D OCTEON_RST_PP_POWER) { octeon_rst_pp_power_write(s, addr, value, size); return; } =20 + if (reg >=3D OCTEON_MIO_BOOT_REG_CFGX(0) && + reg < OCTEON_MIO_BOOT_REG_CFGX(OCTEON_MIO_BOOT_REG_CFG_COUNT)) { + unsigned int index =3D OCTEON_MIO_BOOT_REG_CFG_INDEX(reg); + + old =3D s->mio->mio_boot_reg_cfg[index]; + s->mio->mio_boot_reg_cfg[index] =3D + octeon_write64(old, addr, value, size); + if (index =3D=3D OCTEON_BOOTBUS_LED_CS) { + octeon_bootbus_led_update(s); + } + return; + } + if (!octeon_csr_lookup(s, reg, &old)) { old =3D 0; } @@ -1411,6 +1601,42 @@ static void octeon_init_flash(OcteonState *s) &s->boot_flash_alias); } =20 +static void octeon_init_mio_boot_loc(OcteonState *s) +{ + memory_region_init_ram(&s->mio->bootbus_led, OBJECT(s->mio), + "octeon.bootbus-led", + OCTEON_BOOTBUS_LED_SIZE, &error_fatal); + memory_region_init_ram_ptr(&s->mio->mio_boot_loc, OBJECT(s->mio), + "octeon.mio-boot-loc", + OCTEON_MIO_BOOT_LOC_SIZE, + s->mio->mio_boot_loc_data); +} + + +static void octeon_mio_reset_hold(Object *obj, ResetType type) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); + OcteonMioState *mio =3D OCTEON_MIO(obj); + OcteonState *s =3D mio->parent_obj.board; + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + if (mio->bootbus_led_mapped) { + memory_region_del_subregion(get_system_memory(), &mio->bootbus_led= ); + mio->bootbus_led_mapped =3D false; + } + memset(mio->mio_boot_reg_cfg, 0, sizeof(mio->mio_boot_reg_cfg)); + mio->mio_boot_reg_cfg[0] =3D OCTEON_MIO_BOOT_REG_CFG_RESET_BASE; + mio->mio_boot_loc_cfg[0] =3D 0; + mio->mio_boot_loc_cfg[1] =3D 0; + mio->mio_boot_loc_adr =3D 0; + mio->mio_fus_rcmd =3D 0; + memset(mio->mio_boot_loc_data, 0, sizeof(mio->mio_boot_loc_data)); + octeon_mio_boot_loc_update(s); +} + static void octeon_rst_reset_hold(Object *obj, ResetType type) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); @@ -1498,6 +1724,15 @@ static void octeon_csr_bank_finalize(Object *obj) g_hash_table_destroy(OCTEON_CSR_BANK(obj)->values); } =20 +static void octeon_mio_class_init(ObjectClass *klass, const void *data) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + resettable_class_set_parent_phases(rc, NULL, octeon_mio_reset_hold, + NULL, &opc->parent_phases); +} + static void octeon_rst_class_init(ObjectClass *klass, const void *data) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); @@ -1540,10 +1775,11 @@ static OcteonPeripheralState *octeon_new_peripheral= (OcteonState *s, =20 static void octeon_create_peripherals(OcteonState *s) { + s->mio =3D OCTEON_MIO(octeon_new_peripheral(s, TYPE_OCTEON_MIO, 0)); s->rst =3D OCTEON_RST(octeon_new_peripheral(s, TYPE_OCTEON_RST, 0)); s->intc =3D OCTEON_INTC(octeon_new_peripheral(s, TYPE_OCTEON_INTC, 0)); s->csr_bank =3D OCTEON_CSR_BANK(octeon_new_peripheral( - s, TYPE_OCTEON_CSR_BANK, 0)); + s, TYPE_OCTEON_CSR_BANK, 0)); } =20 static void octeon_realize_peripheral(OcteonPeripheralState *dev) @@ -1553,9 +1789,10 @@ static void octeon_realize_peripheral(OcteonPeripher= alState *dev) =20 static void octeon_realize_peripherals(OcteonState *s) { + octeon_realize_peripheral(&s->csr_bank->parent_obj); octeon_realize_peripheral(&s->intc->parent_obj); octeon_realize_peripheral(&s->rst->parent_obj); - octeon_realize_peripheral(&s->csr_bank->parent_obj); + octeon_realize_peripheral(&s->mio->parent_obj); } =20 static void mips_octeon_init(MachineState *machine) @@ -1581,6 +1818,7 @@ static void mips_octeon_init(MachineState *machine) =20 octeon_map_ram(s); octeon_init_flash(s); + octeon_init_mio_boot_loc(s); octeon_load_firmware(s); octeon_create_cpus(s); =20 @@ -1667,6 +1905,12 @@ static const TypeInfo octeon_machine_types[] =3D { .class_init =3D octeon_peripheral_class_init, .abstract =3D true, }, + { + .name =3D TYPE_OCTEON_MIO, + .parent =3D TYPE_OCTEON_PERIPHERAL, + .instance_size =3D sizeof(OcteonMioState), + .class_init =3D octeon_mio_class_init, + }, { .name =3D TYPE_OCTEON_RST, .parent =3D TYPE_OCTEON_PERIPHERAL, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 6327103f52..7b45daba10 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -17,6 +17,8 @@ #define OCTEON_CIU_GPIO_COUNT 32 #define OCTEON_CIU3_CP0_IRQ_COUNT 4 #define OCTEON_CIU3_IDT_COUNT (OCTEON_MAX_CPUS * 4) +#define OCTEON_MIO_BOOT_REG_CFG_COUNT 8 +#define OCTEON_MIO_BOOT_LOC_SIZE 0x100 =20 typedef enum OcteonIRQ { OCTEON_IRQ_UART, @@ -30,6 +32,7 @@ typedef enum OcteonCiu3Source { } OcteonCiu3Source; =20 typedef struct OcteonState OcteonState; +typedef struct OcteonMioState OcteonMioState; typedef struct OcteonRstState OcteonRstState; typedef struct OcteonIntcState OcteonIntcState; typedef struct OcteonCsrBankState OcteonCsrBankState; @@ -57,6 +60,7 @@ struct OcteonState { MemoryRegion boot_flash; MemoryRegion boot_flash_alias; MemoryRegion cvmseg; + OcteonMioState *mio; OcteonRstState *rst; OcteonIntcState *intc; OcteonCsrBankState *csr_bank; --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437185320132.74291382258423; Thu, 3 Sep 2026 05:06:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CR-0002ym-Oq; Thu, 03 Sep 2026 08:05:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CJ-0002vf-OA for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:39 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CH-0005Ja-4U for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:39 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 42da90b6 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:29 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 2be6b98e; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=g45znVZ oF+bNIMorAaT1+bSzk2NnW+RMJTreTWx/onZlQeT86jgn36NkOWECC8ac+JVpYRJkfx2w0 MNa9bRUodcXW/lEtfsnQRM6q0ACDyp4VFb1IEbwujmzg75MjHH7CsVikQBSSzXzz/akaZP xuPo9kq5HM8V+ECS0pQ59S+maGrMjomey8Awx6bgm4WOPNks/nidAryY+i3l2Sfsa2phbq whFwnqmkguZ7FPEDELTCNuh2UiRNsxX93ZLTPeZutnBVwfrOWeIq4tXrQlm6IW51Qu3gcm nV0dgVZtbsSMhh6auv5AyJ/TC21yeHJnlTFxLTGC0fNDdwvqNB90Tpw== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=m QOfBRwYsif5OU9zSZGkXqSIX79WV63PqbKnoDUPw/c=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=IXmShnwZZMhpc4KEo5zs8p4cWcIkap6HAERbzbwBICO52itpm70kzfnJu1JgHzLkIHD9 0kZcSeSmc5NXnzurmA1poTTiZdDwKzt6dyi4VEFkvZcxr5wW6GA/aDHFHLVJvKQMSYg3fo nMKA8bytrOQKpALJq2veWo7wcYjbLdHuzJG9r2jQJVIUx4At2R30ai5vnG0yeKkElQkjDp Mtyu/vjPCHzwHnK9W7Pk4amptiJ6xRPF9aiw7Wc/AGh0eVWIDhTMEiXXMIcO1J8znmdhzL IA3h1AqiLRIWwDDBiGSMAJINgv5aw+XOKfPYHZF/T24SyXjLgR7YH9Ny3VpbDJnQ== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=F2WvADiL; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=2xH/aLA+; arc=none; iprev=fail; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=mQOfBRwY sif5OU9zSZGkXqSIX79WV63PqbKnoDUPw/c=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=F2WvADiLMcHzWS5QrapDzxuWeRnp7oFPfw5 gITLbAiFJRElcusw5VY5IuIQNXBbuzEnwdtEepw7FoqSWZwefxECSFwbkgEuxxrSQv5oJf eRK9gzSuWtPnCjGmR4B7NF05ZoBd6aaylJs4htmpdxyMmsL1HyDx2EQTeq2gkey6xpJOtP LevAjky/KanIFCgvuAD4gaYW9ZweNtPVtGCJc9Rs7uJ3qkeNiI+qtHQtZ7MK8RYaQzqAFG VuOjyhQx2CMFujAUuV9aqIbQnJ3wC/FYoL/Wd0yvJy1Ivp49zLbWLCWIABoSXAzjEXTBxs FJ3BjyOrygkfhwIscTygiO9Vftw== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=mQOfBRwYsif5OU9zSZGkXqSIX79WV63PqbKnoDUPw/c=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=2xH/aLA+whjHPwLODw IKbS5J+SZX4RC5PWgL8xwETJMQQkZxtlugJ6opVDzceBy8EPfUaGZfnAHvdmSGx8TZDQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 17/25] hw/mips: wire the Octeon UART Date: Thu, 3 Sep 2026 14:02:05 +0200 Message-ID: <20260903120510.34876-18-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437187894158500 Content-Type: text/plain; charset="utf-8" Wire the Octeon UART and its alias to the existing serial-mm device. Provide the special transmit register window and connect the UART interrupt to CIU and CIU3. --- hw/mips/Kconfig | 1 + hw/mips/octeon.c | 69 +++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 5 +++ 3 files changed, 75 insertions(+) diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index cb6057fe38..5fe5f885e3 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -72,6 +72,7 @@ config MIPS_OCTEON default y depends on MIPS64 && TARGET_BIG_ENDIAN select PFLASH_CFI02 + select SERIAL_MM =20 config MIPS_CPS bool diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 59754cb741..133b3636a0 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -10,6 +10,7 @@ #include "qemu/units.h" #include "qemu/datadir.h" #include "qapi/error.h" +#include "hw/char/serial-mm.h" #include "hw/core/clock.h" #include "hw/core/irq.h" #include "hw/core/boards.h" @@ -48,7 +49,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) #define TYPE_OCTEON_CSR_BANK "octeon-csr-bank" OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR_BANK) =20 +#define OCTEON_CSR_32BIT_SIZE 4 #define OCTEON_CSR_64BIT_SIZE 8 +#define OCTEON_CSR_HI32_OFFSET 0 =20 /* * Clock defaults follow a Ubiquiti E1000 EBB7304 U-Boot banner. @@ -155,6 +158,12 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_= CSR_BANK) #define OCTEON_RST_BOOT_C_MUL_SHIFT 30 #define OCTEON_RST_BOOT_PNR_MUL_SHIFT 24 =20 +#define OCTEON_UART0_BASE 0x1180000000800ULL +#define OCTEON_UART0_ALIAS_BASE 0x1180000000c00ULL +#define OCTEON_UART_TX_REG 0x40 +#define OCTEON_UART_TX_HI32_OFFSET OCTEON_CSR_HI32_OFFSET +#define OCTEON_UART_TX_SIZE OCTEON_CSR_64BIT_SIZE + /* * QEMU-only backing for per-core CVMSEG. Keep it outside guest DRAM; * the guest sees the virtual CVMSEG window, not this physical address. @@ -1613,6 +1622,65 @@ static void octeon_init_mio_boot_loc(OcteonState *s) } =20 =20 +static uint64_t octeon_uart_tx_read(void *opaque, hwaddr addr, unsigned si= ze) +{ + return 0; +} + +static void octeon_uart_tx_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s =3D opaque; + + if (size =3D=3D OCTEON_CSR_32BIT_SIZE && + addr =3D=3D OCTEON_UART_TX_HI32_OFFSET) { + return; + } + + serial_io_ops.write(&s->uart->serial, 0, value & 0xff, 1); +} + +static const MemoryRegionOps octeon_uart_tx_ops =3D { + .read =3D octeon_uart_tx_read, + .write =3D octeon_uart_tx_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + }, +}; + +static void octeon_init_uart(OcteonState *s) +{ + SerialMM *uart; + qemu_irq uart_irq; + MemoryRegion *uart_mmio; + int baudbase =3D s->io_hz / 16; + + uart_irq =3D qemu_allocate_irq(octeon_irq_set, s, OCTEON_IRQ_UART); + uart =3D serial_mm_init(get_system_memory(), OCTEON_UART0_BASE, 3, uar= t_irq, + baudbase, serial_hd(0), DEVICE_BIG_ENDIAN); + s->uart =3D uart; + + uart_mmio =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0); + memory_region_init_alias(&s->uart_alias, NULL, "octeon.uart0-alias", + uart_mmio, 0, memory_region_size(uart_mmio)); + memory_region_add_subregion(get_system_memory(), OCTEON_UART0_ALIAS_BA= SE, + &s->uart_alias); + + memory_region_init_io(&s->uart_tx, NULL, &octeon_uart_tx_ops, s, + "octeon.uart0-tx", OCTEON_UART_TX_SIZE); + memory_region_add_subregion(get_system_memory(), + OCTEON_UART0_BASE + OCTEON_UART_TX_REG, + &s->uart_tx); + memory_region_init_io(&s->uart_alias_tx, NULL, &octeon_uart_tx_ops, s, + "octeon.uart0-alias-tx", OCTEON_UART_TX_SIZE); + memory_region_add_subregion(get_system_memory(), + OCTEON_UART0_ALIAS_BASE + OCTEON_UART_TX_R= EG, + &s->uart_alias_tx); +} + + static void octeon_mio_reset_hold(Object *obj, ResetType type) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); @@ -1833,6 +1901,7 @@ static void mips_octeon_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), OCTEON_CIU3_BASE, &s->intc->ciu3); =20 + octeon_init_uart(s); memory_region_init_io(&s->csr_bank->csr, OBJECT(s->csr_bank), &octeon_csr_ops, s, "octeon.csr", OCTEON_CSR_SIZE); diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 7b45daba10..fbe4875d66 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -10,6 +10,7 @@ #define HW_MIPS_OCTEON_INTERNAL_H =20 #include "qemu/typedefs.h" +#include "hw/char/serial-mm.h" #include "system/memory.h" #include "target/mips/cpu.h" =20 @@ -64,6 +65,10 @@ struct OcteonState { OcteonRstState *rst; OcteonIntcState *intc; OcteonCsrBankState *csr_bank; + SerialMM *uart; + MemoryRegion uart_alias; + MemoryRegion uart_tx; + MemoryRegion uart_alias_tx; }; =20 guint octeon_uint64_hash(gconstpointer v); --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437265598615.3890199542425; Thu, 3 Sep 2026 05:07:45 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CV-000364-AQ; Thu, 03 Sep 2026 08:05:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CM-0002wd-VA for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:45 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CI-0005Lq-Sj for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:41 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 7f6e74fc (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:32 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 51e98357; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=mr9FkuC cTqUKUtZgDvK1UFKmxcAMEay1P8xM13ee7+yFyQ2zXZNKkPlW0lQtxWrHXGwwoVJepEWCG 27dw0VSE4XMTvY3yCwqalkhLc8m6OwCBBUZurpbRp+cddY5qJ3LYKH6ZXHBhJXTYhwYLYJ vxbez5Fn4Xws4ptMJkAFNxXRsmAQhRSQWhpEeU7RaR2cVTyt5m5qWvLdc+07z84v8xjCDH DYkxS/Sp7avN6AsDiJ0gwnsMqMl2vbu/wr59r3JSt0icPF/L66pMQ+Vd4xWh2uKknoGNSM 5eBTNW4VNnIOpfbR5hgUhHydoyHszCs+q8W4sN0o4kkMUJd6HNxFZjA== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=0 xODLbI5x/QP+GPjQekHmdCJN3mUNo1kekofafHAsV0=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=OKAyku5ddJW+rpfX5ebEIVw7Fly9Apz/UQxO5bP7cISD63nNw58M4/HNxbJ6CoCEzBJy eh0XAx2vejIZUriUiSn07lFYag8aIjJ4iSgSTaBGuif7qPWNcsZxrZ+fxCQdFMmpmwBvnd N9fQZ9fHc0UtdgIgM1Sj/kWad6G1A7uSfALJoYYlbk0ynhxa2tDBWI62M8F/WmEk9Lq/XK S7vWEMOAVIA8lpdRGIsagPtnt+YU6E9weD/x9HjM9Am0gXUrt5BQGttPkDtLFphmfARoYe HWQlHYrneAmH+UyeLqQmD46WqjjNOIiCbYNja1BuehIG96xkIbXGhdk2Ma7bkdeQ== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=EwTTvfNp; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=pnPMx0eI; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=0xODLbI5 x/QP+GPjQekHmdCJN3mUNo1kekofafHAsV0=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=EwTTvfNpJ7y5gRYUdj9L+jTY27JnlssJC1x Et+V3FavspdMfgtpuoCUbcU4CltBFyvHOvO2cQc2SNoTloqnWT4Hz7P4RyAYaIodD33EvT /B9VH/F+0zQoqhqt/D5ZqeAuarK6UvU2II+D4W3Mx22Bsz1OBrbg3TZGKqy53s66Bic0lb NfPk2q3gkyqfPgrh0xLeKewUFQDKRPC1uX4DUj0so9+8yNfkVmXHAGGlz9iQxQAkFxt3pG qvEGfwJ1UZI9vgQDYf59eFxPDjdALdYLvLA8yot/iwO8ecLigBy5TFExGOW3EXUxbpQnS/ RFbKrX1M9kT3X8auv+7SESBI2bA== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=0xODLbI5x/QP+GPjQekHmdCJN3mUNo1kekofafHAsV0=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=pnPMx0eIoWamyh60bZ lMKhb7EXt4SNjISD6TKAI6/pQ/iN2EnXuCaKAl3HFyF6CZAwq64idmR+pYCs/G2sy3DA== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 18/25] hw/i2c: add Octeon TWSI controller Date: Thu, 3 Sep 2026 14:02:06 +0200 Message-ID: <20260903120510.34876-19-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437266179158501 Content-Type: text/plain; charset="utf-8" Add the two Octeon TWSI controllers and a synthesized DDR4 SPD EEPROM. Derive the SPD geometry and timing from the configured RAM size and DDR clock, then wire both controller windows into the machine. --- hw/i2c/meson.build | 5 + hw/i2c/octeon_twsi.c | 553 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon.c | 8 +- hw/mips/octeon_internal.h | 11 + 4 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 hw/i2c/octeon_twsi.c diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build index 88aea35662..1c744768e4 100644 --- a/hw/i2c/meson.build +++ b/hw/i2c/meson.build @@ -20,3 +20,8 @@ i2c_ss.add(when: 'CONFIG_PCA954X', if_true: files('i2c_mu= x_pca954x.c')) i2c_ss.add(when: 'CONFIG_PMBUS', if_true: files('pmbus_device.c')) i2c_ss.add(when: 'CONFIG_BCM2835_I2C', if_true: files('bcm2835_i2c.c')) system_ss.add_all(when: 'CONFIG_I2C', if_true: i2c_ss) + +if 'CONFIG_TCG' in config_all_accel + mips_ss.add(when: 'CONFIG_MIPS_OCTEON', + if_true: files('octeon_twsi.c')) +endif diff --git a/hw/i2c/octeon_twsi.c b/hw/i2c/octeon_twsi.c new file mode 100644 index 0000000000..3bc8bf7bcd --- /dev/null +++ b/hw/i2c/octeon_twsi.c @@ -0,0 +1,553 @@ +/* + * QEMU Cavium Octeon TWSI controller model. + * + * Copyright (c) 2026 Kirill A. Korinsky + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/host-utils.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/core/boards.h" +#include "hw/core/resettable.h" +#include "hw/core/sysbus.h" +#include "hw/mips/octeon_internal.h" +#include "qemu/module.h" + +#define OCTEON_TWSI_SIZE 0x200 +#define OCTEON_TWSI0_BASE 0x1180000001000ULL +#define OCTEON_TWSI1_BASE 0x1180000001200ULL +#define OCTEON_TWSI_SW_TWSI 0x00 +#define OCTEON_TWSI_INT 0x10 +#define OCTEON_TWSI_SW_DATA_MASK 0xffffffffULL +#define OCTEON_TWSI_SW_EOP_IA_SHIFT 32 +#define OCTEON_TWSI_SW_R (1ULL << 56) +#define OCTEON_TWSI_SW_OP_SHIFT 57 +#define OCTEON_TWSI_SW_V (1ULL << 63) +#define OCTEON_TWSI_OP_EOP_IA 6 +#define OCTEON_TWSI_EOP_DATA 1 +#define OCTEON_TWSI_EOP_CTL 2 +#define OCTEON_TWSI_EOP_STAT 3 +#define OCTEON_TWSI_CTL_AAK 0x04 +#define OCTEON_TWSI_CTL_IFLG 0x08 +#define OCTEON_TWSI_CTL_STP 0x10 +#define OCTEON_TWSI_CTL_STA 0x20 +#define OCTEON_TWSI_STAT_START 0x08 +#define OCTEON_TWSI_STAT_TXADDR_ACK 0x18 +#define OCTEON_TWSI_STAT_TXADDR_NAK 0x20 +#define OCTEON_TWSI_STAT_TXDATA_ACK 0x28 +#define OCTEON_TWSI_STAT_TXDATA_NAK 0x30 +#define OCTEON_TWSI_STAT_RXADDR_ACK 0x40 +#define OCTEON_TWSI_STAT_RXADDR_NAK 0x48 +#define OCTEON_TWSI_STAT_RXDATA_ACK 0x50 +#define OCTEON_TWSI_STAT_RXDATA_NAK 0x58 +#define OCTEON_SPD_BUS 1 +#define OCTEON_SPD_ADDR 0x50 +#define OCTEON_SPD_MIN_ROW_BITS 12 +#define OCTEON_SPD_MAX_ROW_BITS 18 +#define OCTEON_SPD_MIN_COL_BITS 9 +#define OCTEON_SPD_MAX_COL_BITS 10 +#define OCTEON_SPD_BANK_BITS 4 +#define OCTEON_SPD_MIN_RAM_SIZE \ + (1ULL << (OCTEON_SPD_MIN_ROW_BITS + OCTEON_SPD_MIN_COL_BITS + \ + OCTEON_SPD_BANK_BITS + 3)) +#define OCTEON_SPD_MAX_RAM_SIZE \ + (1ULL << (OCTEON_SPD_MAX_ROW_BITS + OCTEON_SPD_MAX_COL_BITS + \ + OCTEON_SPD_BANK_BITS + 3)) +#define OCTEON_SPD_DDR4_TCKMIN 18 +#define OCTEON_SPD_DDR4_FINE_TCKMIN 125 +#define OCTEON_SPD_DDR4_MTB_PS 125 +#define OCTEON_SPD_DDR4_FTB_PS 1 + +#define TYPE_OCTEON_TWSI "octeon-twsi" +OBJECT_DECLARE_TYPE(OcteonTWSIState, OcteonTWSIClass, OCTEON_TWSI) + +#define TYPE_OCTEON_SPD_EEPROM "octeon-spd-eeprom" +OBJECT_DECLARE_TYPE(OcteonSpdEepromState, OcteonSpdEepromClass, + OCTEON_SPD_EEPROM) + +struct OcteonTWSIState { + SysBusDevice parent_obj; + OcteonState *board; + MemoryRegion mmio; + unsigned int bus; + uint64_t sw_twsi; + uint64_t int_reg; + uint8_t ctl; + uint8_t stat; + uint8_t data; + uint8_t slave_addr; + uint8_t write_buf[2]; + unsigned int write_len; + bool have_slave; + bool read_transfer; + bool addr_phase; +}; + +struct OcteonTWSIClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + +struct OcteonSpdEepromState { + SysBusDevice parent_obj; + unsigned int bus; + uint8_t addr; + uint16_t offset; + uint8_t data[OCTEON_SPD_EEPROM_SIZE]; +}; + +struct OcteonSpdEepromClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + +static const uint8_t octeon_spd_eeprom_template[OCTEON_SPD_EEPROM_SIZE] = =3D { + [0] =3D 0x23, [1] =3D 0x11, [2] =3D 0x0c, [3] =3D 0x02, + [4] =3D 0x82, [5] =3D 0x19, [11] =3D 0x03, [12] =3D 0x01, + [13] =3D 0x03, [18] =3D 0x0a, [19] =3D 0x20, [20] =3D 0x78, + [24] =3D 0x6e, [25] =3D 0x6e, [26] =3D 0x6e, [27] =3D 0x11, + [29] =3D 0x6e, [31] =3D 0x05, [32] =3D 0x70, [33] =3D 0x03, + [34] =3D 0xd0, [35] =3D 0x02, [37] =3D 0xa8, [38] =3D 0x20, + [39] =3D 0x27, [40] =3D 0x28, [126] =3D 0x16, [127] =3D 0x2f, +}; + +static uint16_t octeon_spd_crc16(const uint8_t *ptr, int count) +{ + int crc =3D 0; + int i; + + while (--count >=3D 0) { + crc ^=3D *ptr++ << 8; + for (i =3D 0; i < 8; i++) { + if (crc & 0x8000) { + crc =3D (crc << 1) ^ 0x1021; + } else { + crc <<=3D 1; + } + } + } + + return crc & 0xffff; +} + +static bool octeon_spd_geometry(uint64_t ram_size, int *row_bits, + int *col_bits, int *density_code) +{ + uint64_t ram_mb; + int pbank_lsb; + int row_col_bits; + int col; + int row; + int density; + + if (ram_size < OCTEON_SPD_MIN_RAM_SIZE || + ram_size > OCTEON_SPD_MAX_RAM_SIZE || + !is_power_of_2(ram_size)) { + return false; + } + + ram_mb =3D ram_size / MiB; + pbank_lsb =3D ctz64(ram_size); + row_col_bits =3D pbank_lsb - 3 - OCTEON_SPD_BANK_BITS; + + col =3D MIN(OCTEON_SPD_MAX_COL_BITS, + row_col_bits - OCTEON_SPD_MIN_ROW_BITS); + col =3D MAX(OCTEON_SPD_MIN_COL_BITS, col); + row =3D row_col_bits - col; + density =3D ctz64(ram_mb) - 8; + + if (row < OCTEON_SPD_MIN_ROW_BITS || + row > OCTEON_SPD_MAX_ROW_BITS || + density < 0 || density > 7) { + return false; + } + + if (row_bits) { + *row_bits =3D row; + } + if (col_bits) { + *col_bits =3D col; + } + if (density_code) { + *density_code =3D density; + } + return true; +} + +void octeon_validate_ram_size(uint64_t ram_size) +{ + if (!octeon_spd_geometry(ram_size, NULL, NULL, NULL)) { + error_report("octeon3 RAM size must be a power of two from " + "%" PRIu64 " MB to %" PRIu64 " GB", + (uint64_t)OCTEON_SPD_MIN_RAM_SIZE / MiB, + (uint64_t)OCTEON_SPD_MAX_RAM_SIZE / GiB); + exit(1); + } +} + +static void octeon_spd_set_tckmin(OcteonState *s, uint8_t *spd) +{ + uint64_t tck_ps =3D (1000000000000ULL + s->ddr_hz - 1) / s->ddr_hz; + uint64_t mtb =3D tck_ps / OCTEON_SPD_DDR4_MTB_PS; + uint64_t fine =3D tck_ps % OCTEON_SPD_DDR4_MTB_PS; + + if (mtb =3D=3D 0 || mtb > UINT8_MAX || fine > INT8_MAX) { + error_report("octeon3 DDR clock cannot be represented in DDR4 SPD"= ); + exit(1); + } + + spd[OCTEON_SPD_DDR4_TCKMIN] =3D mtb; + spd[OCTEON_SPD_DDR4_FINE_TCKMIN] =3D fine / OCTEON_SPD_DDR4_FTB_PS; +} + +void octeon_init_spd(OcteonState *s) +{ + DeviceState *dev =3D qdev_new(TYPE_OCTEON_SPD_EEPROM); + OcteonSpdEepromState *eeprom =3D OCTEON_SPD_EEPROM(dev); + uint64_t ram_size =3D s->machine->ram_size; + int col_bits; + int row_bits; + int density_code; + uint16_t crc; + + s->spd[0] =3D eeprom; + eeprom->bus =3D OCTEON_SPD_BUS; + eeprom->addr =3D OCTEON_SPD_ADDR; + memcpy(eeprom->data, octeon_spd_eeprom_template, + sizeof(eeprom->data)); + + g_assert(octeon_spd_geometry(ram_size, &row_bits, &col_bits, + &density_code)); + + eeprom->data[4] =3D 0x80 | density_code; + eeprom->data[5] =3D ((row_bits - OCTEON_SPD_MIN_ROW_BITS) << 3) | + (col_bits - OCTEON_SPD_MIN_COL_BITS); + octeon_spd_set_tckmin(s, eeprom->data); + + crc =3D octeon_spd_crc16(eeprom->data, + (eeprom->data[0] & 0x80) ? 117 : 126); + eeprom->data[126] =3D crc & 0xff; + eeprom->data[127] =3D crc >> 8; + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); +} + +static OcteonSpdEepromState *octeon_twsi_find_spd(OcteonTWSIState *t) +{ + OcteonState *s =3D t->board; + unsigned int i; + + for (i =3D 0; i < OCTEON_SPD_EEPROM_COUNT; i++) { + if (s->spd[i]->bus =3D=3D t->bus && + s->spd[i]->addr =3D=3D t->slave_addr) { + return s->spd[i]; + } + } + + return NULL; +} + +static uint8_t octeon_spd_eeprom_read(OcteonSpdEepromState *eeprom) +{ + uint8_t value =3D 0xff; + + if (eeprom->offset < sizeof(eeprom->data)) { + value =3D eeprom->data[eeprom->offset]; + } + eeprom->offset++; + return value; +} + +static void octeon_twsi_write_ctl(OcteonTWSIState *t, uint8_t value) +{ + OcteonSpdEepromState *eeprom; + + t->ctl =3D value | OCTEON_TWSI_CTL_IFLG; + + if (value & OCTEON_TWSI_CTL_STA) { + t->have_slave =3D false; + t->addr_phase =3D false; + t->write_len =3D 0; + t->stat =3D OCTEON_TWSI_STAT_START; + } else if (value & OCTEON_TWSI_CTL_STP) { + t->have_slave =3D false; + t->addr_phase =3D false; + t->stat =3D OCTEON_TWSI_STAT_IDLE; + } else if (t->addr_phase) { + eeprom =3D octeon_twsi_find_spd(t); + t->addr_phase =3D false; + if (eeprom) { + t->stat =3D t->read_transfer ? OCTEON_TWSI_STAT_RXADDR_ACK : + OCTEON_TWSI_STAT_TXADDR_ACK; + } else { + t->stat =3D t->read_transfer ? OCTEON_TWSI_STAT_RXADDR_NAK : + OCTEON_TWSI_STAT_TXADDR_NAK; + } + } else if (t->read_transfer) { + t->stat =3D (value & OCTEON_TWSI_CTL_AAK) ? + OCTEON_TWSI_STAT_RXDATA_ACK : OCTEON_TWSI_STAT_RXDATA_NA= K; + } else { + t->stat =3D octeon_twsi_find_spd(t) ? OCTEON_TWSI_STAT_TXDATA_ACK : + OCTEON_TWSI_STAT_TXDATA_NAK; + } +} + +static void octeon_twsi_write_data(OcteonTWSIState *t, uint8_t value) +{ + OcteonSpdEepromState *eeprom; + + t->data =3D value; + + if (!t->have_slave) { + t->slave_addr =3D value >> 1; + t->read_transfer =3D value & 1; + t->have_slave =3D true; + t->addr_phase =3D true; + t->write_len =3D 0; + return; + } + + if (!t->read_transfer && t->write_len < ARRAY_SIZE(t->write_buf)) { + t->write_buf[t->write_len++] =3D value; + eeprom =3D octeon_twsi_find_spd(t); + if (eeprom) { + if (t->write_len =3D=3D 1) { + eeprom->offset =3D value; + } else if (t->write_len =3D=3D ARRAY_SIZE(t->write_buf)) { + eeprom->offset =3D (t->write_buf[0] << 8) | t->write_buf[1= ]; + } + } + } +} + +static uint8_t octeon_twsi_read_reg(OcteonTWSIState *t, unsigned int reg) +{ + switch (reg) { + case OCTEON_TWSI_EOP_DATA: + if (t->read_transfer) { + OcteonSpdEepromState *eeprom =3D octeon_twsi_find_spd(t); + + t->data =3D eeprom ? octeon_spd_eeprom_read(eeprom) : 0xff; + } + return t->data; + case OCTEON_TWSI_EOP_CTL: + return t->ctl; + case OCTEON_TWSI_EOP_STAT: + return t->stat; + default: + return 0; + } +} + +static void octeon_twsi_write_reg(OcteonTWSIState *t, unsigned int reg, + uint8_t value) +{ + switch (reg) { + case OCTEON_TWSI_EOP_DATA: + octeon_twsi_write_data(t, value); + break; + case OCTEON_TWSI_EOP_CTL: + octeon_twsi_write_ctl(t, value); + break; + default: + break; + } +} + +static uint64_t octeon_twsi_exec(OcteonTWSIState *t, uint64_t value) +{ + unsigned int op =3D (value >> OCTEON_TWSI_SW_OP_SHIFT) & 0xf; + unsigned int reg =3D (value >> OCTEON_TWSI_SW_EOP_IA_SHIFT) & 0x7; + + if (!(value & OCTEON_TWSI_SW_V)) { + return value; + } + + if (op =3D=3D OCTEON_TWSI_OP_EOP_IA) { + if (value & OCTEON_TWSI_SW_R) { + value &=3D ~OCTEON_TWSI_SW_DATA_MASK; + value |=3D octeon_twsi_read_reg(t, reg); + } else { + octeon_twsi_write_reg(t, reg, value & 0xff); + } + } + + return value & ~OCTEON_TWSI_SW_V; +} + +static uint64_t octeon_twsi_read(void *opaque, hwaddr addr, unsigned size) +{ + OcteonTWSIState *t =3D opaque; + hwaddr reg =3D addr & ~7ULL; + + switch (reg) { + case OCTEON_TWSI_SW_TWSI: + return octeon_read64(t->sw_twsi, addr, size); + case OCTEON_TWSI_INT: + return octeon_read64(t->int_reg, addr, size); + default: + return 0; + } +} + +static void octeon_twsi_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonTWSIState *t =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t old =3D 0; + + switch (reg) { + case OCTEON_TWSI_SW_TWSI: + old =3D t->sw_twsi; + value =3D octeon_write64(old, addr, value, size); + if (size =3D=3D 4 && !(addr & 4)) { + t->sw_twsi =3D value; + } else { + t->sw_twsi =3D octeon_twsi_exec(t, value); + } + break; + case OCTEON_TWSI_INT: + old =3D t->int_reg; + t->int_reg =3D octeon_write64(old, addr, value, size); + break; + default: + break; + } +} + +static const MemoryRegionOps octeon_twsi_ops =3D { + .read =3D octeon_twsi_read, + .write =3D octeon_twsi_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static void octeon_twsi_reset_hold(Object *obj, ResetType type) +{ + OcteonTWSIState *t =3D OCTEON_TWSI(obj); + OcteonTWSIClass *otc =3D OCTEON_TWSI_GET_CLASS(obj); + + if (otc->parent_phases.hold) { + otc->parent_phases.hold(obj, type); + } + + t->sw_twsi =3D 0; + t->int_reg =3D 0; + t->ctl =3D 0; + t->stat =3D OCTEON_TWSI_STAT_IDLE; + t->data =3D 0; + t->slave_addr =3D 0; + t->write_len =3D 0; + t->have_slave =3D false; + t->read_transfer =3D false; + t->addr_phase =3D false; + memset(t->write_buf, 0, sizeof(t->write_buf)); +} + +static void octeon_spd_eeprom_reset_hold(Object *obj, ResetType type) +{ + OcteonSpdEepromState *eeprom =3D OCTEON_SPD_EEPROM(obj); + OcteonSpdEepromClass *osec =3D OCTEON_SPD_EEPROM_GET_CLASS(obj); + + if (osec->parent_phases.hold) { + osec->parent_phases.hold(obj, type); + } + + eeprom->offset =3D 0; +} + +static void octeon_twsi_realize(DeviceState *dev, Error **errp) +{ + static const char *const name[OCTEON_TWSI_COUNT] =3D { + "octeon.twsi0", + "octeon.twsi1", + }; + OcteonTWSIState *t =3D OCTEON_TWSI(dev); + + memory_region_init_io(&t->mmio, OBJECT(dev), &octeon_twsi_ops, t, + name[t->bus], OCTEON_TWSI_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio); +} + +static void octeon_twsi_init(Object *obj) +{ + OcteonTWSIState *t =3D OCTEON_TWSI(obj); + + t->stat =3D OCTEON_TWSI_STAT_IDLE; +} + +static void octeon_twsi_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + OcteonTWSIClass *otc =3D OCTEON_TWSI_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + dc->realize =3D octeon_twsi_realize; + dc->user_creatable =3D false; + resettable_class_set_parent_phases(rc, NULL, octeon_twsi_reset_hold, N= ULL, + &otc->parent_phases); +} + +static void octeon_spd_eeprom_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + OcteonSpdEepromClass *osec =3D OCTEON_SPD_EEPROM_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + dc->user_creatable =3D false; + resettable_class_set_parent_phases(rc, NULL, + octeon_spd_eeprom_reset_hold, NULL, + &osec->parent_phases); +} + +static const TypeInfo octeon_twsi_type_info =3D { + .name =3D TYPE_OCTEON_TWSI, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(OcteonTWSIState), + .instance_init =3D octeon_twsi_init, + .class_size =3D sizeof(OcteonTWSIClass), + .class_init =3D octeon_twsi_class_init, +}; + +static const TypeInfo octeon_spd_eeprom_type_info =3D { + .name =3D TYPE_OCTEON_SPD_EEPROM, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(OcteonSpdEepromState), + .class_size =3D sizeof(OcteonSpdEepromClass), + .class_init =3D octeon_spd_eeprom_class_init, +}; + +static void octeon_twsi_register_types(void) +{ + type_register_static(&octeon_twsi_type_info); + type_register_static(&octeon_spd_eeprom_type_info); +} + +type_init(octeon_twsi_register_types) + +void octeon_init_twsi(OcteonState *s) +{ + static const uint64_t base[OCTEON_TWSI_COUNT] =3D { + OCTEON_TWSI0_BASE, + OCTEON_TWSI1_BASE, + }; + unsigned int i; + + for (i =3D 0; i < OCTEON_TWSI_COUNT; i++) { + DeviceState *dev =3D qdev_new(TYPE_OCTEON_TWSI); + OcteonTWSIState *t =3D OCTEON_TWSI(dev); + + t->board =3D s; + t->bus =3D i; + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base[i]); + } +} diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 133b3636a0..9388bc005b 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -64,7 +64,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR= _BANK) =20 /* * The physical layout follows U-Boot's generic Octeon III - * OCTEON_MAX_PHY_MEM_SIZE value. Keep 1 GiB as the tested default. + * OCTEON_MAX_PHY_MEM_SIZE value. The synthesized DDR4 SPD below accepts + * power-of-two RAM sizes from 256 MiB through 32 GiB. Keep 1 GiB as the + * tested default. */ #define OCTEON_DEFAULT_RAM_SIZE (1 * GiB) #define OCTEON_MAX_PHY_MEM_SIZE (512 * GiB) @@ -1884,6 +1886,8 @@ static void mips_octeon_init(MachineState *machine) exit(1); } =20 + octeon_validate_ram_size(machine->ram_size); + octeon_init_spd(s); octeon_map_ram(s); octeon_init_flash(s); octeon_init_mio_boot_loc(s); @@ -1902,6 +1906,8 @@ static void mips_octeon_init(MachineState *machine) &s->intc->ciu3); =20 octeon_init_uart(s); + octeon_init_twsi(s); + memory_region_init_io(&s->csr_bank->csr, OBJECT(s->csr_bank), &octeon_csr_ops, s, "octeon.csr", OCTEON_CSR_SIZE); diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index fbe4875d66..e9826f1713 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -20,6 +20,10 @@ #define OCTEON_CIU3_IDT_COUNT (OCTEON_MAX_CPUS * 4) #define OCTEON_MIO_BOOT_REG_CFG_COUNT 8 #define OCTEON_MIO_BOOT_LOC_SIZE 0x100 +#define OCTEON_TWSI_COUNT 2 +#define OCTEON_TWSI_STAT_IDLE 0xf8 +#define OCTEON_SPD_EEPROM_SIZE 139 +#define OCTEON_SPD_EEPROM_COUNT 1 =20 typedef enum OcteonIRQ { OCTEON_IRQ_UART, @@ -44,6 +48,8 @@ typedef struct OcteonCPUState { bool boot_cpu; } OcteonCPUState; =20 +typedef struct OcteonSpdEepromState OcteonSpdEepromState; + struct OcteonState { MachineState *machine; Clock *cpuclk; @@ -65,6 +71,7 @@ struct OcteonState { OcteonRstState *rst; OcteonIntcState *intc; OcteonCsrBankState *csr_bank; + OcteonSpdEepromState *spd[OCTEON_SPD_EEPROM_COUNT]; SerialMM *uart; MemoryRegion uart_alias; MemoryRegion uart_tx; @@ -81,4 +88,8 @@ void octeon_reg_store(GHashTable *regs, uint64_t reg, uin= t64_t value); bool octeon_csr_lookup(OcteonState *s, uint64_t reg, uint64_t *value); void octeon_irq_set(void *opaque, int irq, int level); =20 +void octeon_validate_ram_size(uint64_t ram_size); +void octeon_init_spd(OcteonState *s); +void octeon_init_twsi(OcteonState *s); + #endif --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 178843719422521.113069860332416; Thu, 3 Sep 2026 05:06:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CU-00034u-Jj; Thu, 03 Sep 2026 08:05:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CM-0002wc-Uj for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:45 -0400 Received: from mx2.catap.net ([2a01:4f9:3b:5410::2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CI-0005LP-Ok for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:41 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 73e9e837 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:31 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id e06bdad1; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=MXz2QZ/ UHlrzpjXv1qBbZEeWKc1BSu/YQDstjgOoSSECYwT2PsWOhhoBUeRlQki75yxzDd815lqVk PlgzEqTT2N0B6iceixz3sB1x/1YVnZnCbci0ngJkGzymd+AFkHZ5+PN2SEOxahD7B9y+eT KIYjek1Gai1Gorjrn+xRs11x5bwq3LkOzi8L9W8IAYzztuYQpeeB+icmhc2rEsyXLyNay5 enj9E3xU2+AX0+mNTnm7zeXPzG1yvr30iiQ7/QHa6wHTJbgaId1uik3vOyHTaybCUYgxMy i71NTgZ85HpecBJsJbDDDpif0QiEs5oYxqFvHuuj5acGNHisD8O1QhA== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=/ DoFh+CoKKuTky1Jb08lVrKwzSpfoKt0bKgqOQ3JWY0=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=oE+zyYCVPoCjXPSgW0prsrT03hcHFRZa2vW6hOLwqNkGpaX2rJDRAP3uMFtO1KGM0yTn buBOUm7oh+rqazh4Uw7KDnxjhMHDJ00YWD0w9Gg5fa3AOMRwUetDVS1IyCS9zzznVOJOTp Yb3Ap45b0ugvPSZdB6k4XchvxoZ7Gfu0pIeutNY+ksF7loCcif3A9OWfpq69s+6YA1+DGy MTsTMS4mK8l+TEJ1qwO4RkAa0frX/g9d+LxIu25EEPf6W307tbCrFf49iiVYspDWVfK5mk rQZSZEiJ1tlTsdVfzKfGmzeS7mazpLQfZYO/TgNz0Pg0silrlDW4AcjgkGH4j7eg== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=fM/EZ9vU; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=GIYiRI1U; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=/DoFh+Co KKuTky1Jb08lVrKwzSpfoKt0bKgqOQ3JWY0=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=fM/EZ9vUID67NsjlI3QgUPodnhDBNqa1SvK IZ1M+ICGatZHCsT8eUqhS1PFjwWD4iGR7Z864cqOt3y71C+cT2VgVYjsw0rpCLMT7vwlSq puSkcXdhj5gAA/clK0hOHm64JuJ64bGV+qWZEEMPkREOJ1QfhLkrEwYuIZXzDiT2pfXh47 chvsHfOJJ2ZV4PV3bUD/i9KG9NNv01XjRG3rgV5Bj5TRGcf/xKdkdanlxAoHual+zF+QUd kzf/oRoYcHDoWU1t2496SjNoL7ZoC5fIQ/0ovsHJ3AaW5jPJzYcfJpS+lSjBdmGjVCip6Y t9PmUc2wqF71htbETgHMVTjyKEg== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=/DoFh+CoKKuTky1Jb08lVrKwzSpfoKt0bKgqOQ3JWY0=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=GIYiRI1UReLXawy7Gx 0KP6poFNlr8WhZz7WunutK+mPr0kd8+GB94mj4DQEGjtfMQ24JWEDBflAElNFVKVslBQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 19/25] hw/mips: add Octeon EMM controller Date: Thu, 3 Sep 2026 14:02:07 +0200 Message-ID: <20260903120510.34876-20-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a01:4f9:3b:5410::2; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437196077158500 Content-Type: text/plain; charset="utf-8" Model the Octeon EMM command, DMA, switch and buffer registers needed by firmware MMC initialization. Give the controller its own reset state and route its registers through the shared CSR window. --- hw/mips/octeon.c | 491 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 3 + 2 files changed, 494 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 9388bc005b..f3f8a74cbe 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -9,6 +9,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu/datadir.h" +#include "qemu/host-utils.h" #include "qapi/error.h" #include "hw/char/serial-mm.h" #include "hw/core/clock.h" @@ -42,6 +43,8 @@ OBJECT_DECLARE_TYPE(OcteonPeripheralState, OcteonPeripher= alClass, =20 #define TYPE_OCTEON_MIO "octeon-mio" OBJECT_DECLARE_SIMPLE_TYPE(OcteonMioState, OCTEON_MIO) +#define TYPE_OCTEON_EMM "octeon-emm" +OBJECT_DECLARE_SIMPLE_TYPE(OcteonEmmState, OCTEON_EMM) #define TYPE_OCTEON_RST "octeon-rst" OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST) #define TYPE_OCTEON_INTC "octeon-intc" @@ -52,6 +55,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR= _BANK) #define OCTEON_CSR_32BIT_SIZE 4 #define OCTEON_CSR_64BIT_SIZE 8 #define OCTEON_CSR_HI32_OFFSET 0 +#define OCTEON_CSR_LO32_OFFSET 4 =20 /* * Clock defaults follow a Ubiquiti E1000 EBB7304 U-Boot banner. @@ -153,6 +157,88 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_= CSR_BANK) #define OCTEON_MIO_FUS_RCMD 0x0001500 #define OCTEON_MIO_FUS_RCMD_PEND 0x0000000000001000ULL #define OCTEON_MIO_FUS_RCMD_DAT 0x0000000000ff0000ULL +#define OCTEON_MIO_EMM_DMA_FIFO_CFG 0x0000160 +#define OCTEON_MIO_EMM_DMA_FIFO_ADR 0x0000170 +#define OCTEON_MIO_EMM_DMA_FIFO_CMD 0x0000178 +#define OCTEON_MIO_EMM_DMA_CFG 0x0000180 +#define OCTEON_MIO_EMM_DMA_ADR 0x0000188 +#define OCTEON_MIO_EMM_DMA_INT 0x0000190 +#define OCTEON_MIO_EMM_CFG 0x0002000 +#define OCTEON_MIO_EMM_MODEX(x) \ + (0x0002008 + (x) * OCTEON_CSR_64BIT_SIZE) +#define OCTEON_MIO_EMM_MODE_COUNT 4 +#define OCTEON_MIO_EMM_INT_EN_OLD 0x0002040 +#define OCTEON_MIO_EMM_SWITCH 0x0002048 +#define OCTEON_MIO_EMM_DMA 0x0002050 +#define OCTEON_MIO_EMM_CMD 0x0002058 +#define OCTEON_MIO_EMM_RSP_STS 0x0002060 +#define OCTEON_MIO_EMM_RSP_LO 0x0002068 +#define OCTEON_MIO_EMM_RSP_HI 0x0002070 +#define OCTEON_MIO_EMM_INT 0x0002078 +#define OCTEON_MIO_EMM_WDOG 0x0002088 +#define OCTEON_MIO_EMM_SAMPLE 0x0002090 +#define OCTEON_MIO_EMM_STS_MASK 0x0002098 +#define OCTEON_MIO_EMM_RCA 0x00020a0 +#define OCTEON_MIO_EMM_BUF_IDX 0x00020e0 +#define OCTEON_MIO_EMM_BUF_DAT 0x00020e8 +#define OCTEON_MIO_EMM_DEBUG 0x00020f8 +#define OCTEON_MIO_EMM_NODE_OFFSET 0x0002000 +#define OCTEON_MIO_EMM_CMD_VAL (1ULL << 59) +#define OCTEON_MIO_EMM_DMA_VAL (1ULL << 59) +#define OCTEON_MIO_EMM_DMA_BLOCK_CNT_SHIFT 32 +#define OCTEON_MIO_EMM_DMA_BLOCK_CNT_MASK \ + (0xffffULL << OCTEON_MIO_EMM_DMA_BLOCK_CNT_SHIFT) +#define OCTEON_MIO_EMM_SWITCH_EXE (1ULL << 59) +#define OCTEON_MIO_EMM_CMD_IDX_SHIFT 32 +#define OCTEON_MIO_EMM_CMD_IDX_BITS 6 +#define OCTEON_MIO_EMM_CMD_IDX_MASK \ + ((1U << OCTEON_MIO_EMM_CMD_IDX_BITS) - 1) +#define OCTEON_MIO_EMM_CMD_BUS_ID_SHIFT 60 +#define OCTEON_MIO_EMM_BUS_ID_MASK (OCTEON_MIO_EMM_MODE_COUNT - 1) +#define OCTEON_MIO_EMM_RSP_STS_CMD_DONE (1ULL << 0) +#define OCTEON_MIO_EMM_RSP_STS_CMD_IDX_SHIFT 1 +#define OCTEON_MIO_EMM_RSP_STS_RSP_TIMEOUT (1ULL << 13) +#define OCTEON_MIO_EMM_RSP_STS_DMA_VAL (1ULL << 57) +#define OCTEON_MIO_EMM_RSP_STS_DMA_PEND (1ULL << 56) +#define OCTEON_MIO_EMM_RSP_STS_BUS_ID_SHIFT 60 +#define OCTEON_MIO_EMM_DMA_INT_DONE (1ULL << 0) +#define OCTEON_MIO_EMM_INT_CMD_DONE (1ULL << 1) +#define OCTEON_MIO_EMM_INT_CMD_ERR (1ULL << 3) +#define OCTEON_MIO_EMM_INT_DMA_DONE (1ULL << 2) +#define OCTEON_MIO_EMM_INT_DMA_ERR (1ULL << 4) +#define OCTEON_MIO_EMM_INT_SWITCH_DONE (1ULL << 5) +#define OCTEON_MIO_EMM_INT_SWITCH_ERR (1ULL << 6) +#define OCTEON_MIO_EMM_SWITCH_MODE_MASK ((1ULL << 49) - 1) +#define OCTEON_MIO_EMM_CFG_BUS_EN_MASK \ + ((1ULL << OCTEON_MIO_EMM_MODE_COUNT) - 1) +#define OCTEON_MIO_EMM_LOW_SPEED_HZ 400000 +#define OCTEON_MIO_EMM_MODE_CLK_LO_MASK 0x000000000000ffffULL +#define OCTEON_MIO_EMM_MODE_CLK_HI_MASK 0x00000000ffff0000ULL +#define OCTEON_MIO_EMM_MODE_CLK_HI_SHIFT 16 +#define OCTEON_MIO_EMM_BUF_IDX_INC (1ULL << 16) +#define OCTEON_MIO_EMM_BUF_WORD_SIZE OCTEON_CSR_64BIT_SIZE +#define OCTEON_MIO_EMM_BUF_ENTRY_COUNT \ + (OCTEON_MIO_EMM_BUF_SIZE / OCTEON_MIO_EMM_BUF_WORD_SIZE) +#define OCTEON_MIO_EMM_BUF_IDX_OFF_MASK \ + (OCTEON_MIO_EMM_BUF_ENTRY_COUNT - 1) +#define OCTEON_MMC_CMD_GO_IDLE_STATE 0 +#define OCTEON_MMC_CMD_BUSTEST_R 14 +#define OCTEON_MMC_CMD_BUSTEST_W 19 +/* SD/MMC CMD19 request patterns and CMD14 response patterns. */ +#define OCTEON_MMC_BUSTEST_8_REQ0 0x55 +#define OCTEON_MMC_BUSTEST_8_REQ1 0xaa +#define OCTEON_MMC_BUSTEST_8_RESP0 0xaa +#define OCTEON_MMC_BUSTEST_8_RESP1 0x55 +#define OCTEON_MMC_BUSTEST_4_REQ0 0x5a +#define OCTEON_MMC_BUSTEST_4_REQ4 0x99 +#define OCTEON_MMC_BUSTEST_4_REQ5 0x50 +#define OCTEON_MMC_BUSTEST_4_REQ6 0x0f +#define OCTEON_MMC_BUSTEST_4_RESP0 0xa5 +#define OCTEON_MMC_BUSTEST_1_REQ0 0x80 +#define OCTEON_MMC_BUSTEST_1_REQ1 0x70 +#define OCTEON_MMC_BUSTEST_1_REQ2 0x78 +#define OCTEON_MMC_BUSTEST_1_REQ3 0x01 +#define OCTEON_MMC_BUSTEST_1_RESP0 0x40 #define OCTEON_RST_BOOT 0x6001600 #define OCTEON_RST_SOFT_RST 0x6001680 /* U-Boot uses the reset controller to park and release secondary cores. */ @@ -226,6 +312,19 @@ struct OcteonMioState { bool bootbus_led_mapped; }; =20 +struct OcteonEmmState { + OcteonPeripheralState parent_obj; + GHashTable *regs; + uint64_t mio_emm_rsp_sts; + uint64_t mio_emm_rsp_lo; + uint64_t mio_emm_rsp_hi; + uint64_t mio_emm_int; + uint64_t mio_emm_dma_int; + uint16_t mio_emm_buf_idx; + bool mio_emm_buf_inc; + uint8_t mio_emm_buf[OCTEON_MIO_EMM_BUF_SIZE]; +}; + struct OcteonRstState { OcteonPeripheralState parent_obj; GHashTable *regs; @@ -353,8 +452,15 @@ void octeon_reg_store(GHashTable *regs, uint64_t reg, = uint64_t value) g_hash_table_replace(regs, key, stored); } =20 +static bool octeon_mio_emm_decode(hwaddr reg, hwaddr *ereg); + bool octeon_csr_lookup(OcteonState *s, uint64_t reg, uint64_t *value) { + hwaddr ereg; + + if (octeon_mio_emm_decode(reg, &ereg)) { + return octeon_reg_lookup(s->emm->regs, ereg, value); + } if (reg =3D=3D OCTEON_RST_SOFT_RST) { return octeon_reg_lookup(s->rst->regs, reg, value); } @@ -363,6 +469,12 @@ bool octeon_csr_lookup(OcteonState *s, uint64_t reg, u= int64_t *value) =20 static void octeon_csr_store(OcteonState *s, uint64_t reg, uint64_t value) { + hwaddr ereg; + + if (octeon_mio_emm_decode(reg, &ereg)) { + octeon_reg_store(s->emm->regs, ereg, value); + return; + } if (reg =3D=3D OCTEON_RST_SOFT_RST) { octeon_reg_store(s->rst->regs, reg, value); return; @@ -453,6 +565,325 @@ static void octeon_mio_boot_loc_dat_write(OcteonState= *s, hwaddr addr, OCTEON_MIO_BOOT_LOC_ADR_MASK; } =20 +static bool octeon_mio_emm_valid_reg(hwaddr reg) +{ + if (reg >=3D OCTEON_MIO_EMM_MODEX(0) && + reg < OCTEON_MIO_EMM_MODEX(OCTEON_MIO_EMM_MODE_COUNT) && + (reg & (OCTEON_CSR_64BIT_SIZE - 1)) =3D=3D 0) { + return true; + } + + switch (reg) { + case OCTEON_MIO_EMM_DMA_INT: + case OCTEON_MIO_EMM_CFG: + case OCTEON_MIO_EMM_SWITCH: + case OCTEON_MIO_EMM_DMA: + case OCTEON_MIO_EMM_CMD: + case OCTEON_MIO_EMM_RSP_STS: + case OCTEON_MIO_EMM_INT: + case OCTEON_MIO_EMM_DMA_FIFO_CFG: + case OCTEON_MIO_EMM_DMA_FIFO_ADR: + case OCTEON_MIO_EMM_DMA_FIFO_CMD: + case OCTEON_MIO_EMM_DMA_CFG: + case OCTEON_MIO_EMM_DMA_ADR: + case OCTEON_MIO_EMM_INT_EN_OLD: + case OCTEON_MIO_EMM_RSP_LO: + case OCTEON_MIO_EMM_RSP_HI: + case OCTEON_MIO_EMM_WDOG: + case OCTEON_MIO_EMM_SAMPLE: + case OCTEON_MIO_EMM_STS_MASK: + case OCTEON_MIO_EMM_RCA: + case OCTEON_MIO_EMM_BUF_IDX: + case OCTEON_MIO_EMM_BUF_DAT: + case OCTEON_MIO_EMM_DEBUG: + return true; + default: + return false; + } +} + +static bool octeon_mio_emm_decode(hwaddr reg, hwaddr *ereg) +{ + if (octeon_mio_emm_valid_reg(reg)) { + *ereg =3D reg; + return true; + } + + reg -=3D OCTEON_MIO_EMM_NODE_OFFSET; + if (octeon_mio_emm_valid_reg(reg)) { + *ereg =3D reg; + return true; + } + + return false; +} + +static bool octeon_mio_emm_execute_write(hwaddr addr, unsigned size) +{ + return size =3D=3D OCTEON_CSR_64BIT_SIZE || + (size =3D=3D OCTEON_CSR_32BIT_SIZE && + (addr & OCTEON_CSR_LO32_OFFSET)); +} + +static void octeon_mio_emm_set_low_speed_mode(OcteonState *s, + unsigned int bus_id) +{ + uint64_t period =3D DIV_ROUND_UP(s->io_hz, OCTEON_MIO_EMM_LOW_SPEED_HZ= ); + uint64_t value; + + period =3D MIN(period, UINT16_MAX); + if (!octeon_csr_lookup(s, OCTEON_MIO_EMM_MODEX(bus_id), &value)) { + value =3D 0; + } + + value &=3D ~(OCTEON_MIO_EMM_MODE_CLK_LO_MASK | + OCTEON_MIO_EMM_MODE_CLK_HI_MASK); + value |=3D period | (period << OCTEON_MIO_EMM_MODE_CLK_HI_SHIFT); + octeon_csr_store(s, OCTEON_MIO_EMM_MODEX(bus_id), value); +} + +static void octeon_mio_emm_set_bustest(OcteonState *s) +{ + const uint8_t *buf =3D s->emm->mio_emm_buf; + bool bus8 =3D buf[0] =3D=3D OCTEON_MMC_BUSTEST_8_REQ0 && + buf[1] =3D=3D OCTEON_MMC_BUSTEST_8_REQ1; + bool bus4 =3D buf[0] =3D=3D OCTEON_MMC_BUSTEST_4_REQ0 && + buf[4] =3D=3D OCTEON_MMC_BUSTEST_4_REQ4 && + buf[5] =3D=3D OCTEON_MMC_BUSTEST_4_REQ5 && + buf[6] =3D=3D OCTEON_MMC_BUSTEST_4_REQ6; + bool bus1 =3D buf[0] =3D=3D OCTEON_MMC_BUSTEST_1_REQ0 && + buf[1] =3D=3D OCTEON_MMC_BUSTEST_1_REQ1 && + buf[2] =3D=3D OCTEON_MMC_BUSTEST_1_REQ2 && + buf[3] =3D=3D OCTEON_MMC_BUSTEST_1_REQ3; + + memset(s->emm->mio_emm_buf, 0, sizeof(s->emm->mio_emm_buf)); + if (bus8) { + s->emm->mio_emm_buf[0] =3D OCTEON_MMC_BUSTEST_8_RESP0; + s->emm->mio_emm_buf[1] =3D OCTEON_MMC_BUSTEST_8_RESP1; + } else if (bus4) { + s->emm->mio_emm_buf[0] =3D OCTEON_MMC_BUSTEST_4_RESP0; + } else if (bus1) { + s->emm->mio_emm_buf[0] =3D OCTEON_MMC_BUSTEST_1_RESP0; + } +} + +static void octeon_mio_emm_complete_dma(OcteonState *s, uint64_t dma) +{ + dma &=3D ~(OCTEON_MIO_EMM_DMA_VAL | OCTEON_MIO_EMM_DMA_BLOCK_CNT_MASK); + octeon_csr_store(s, OCTEON_MIO_EMM_DMA, dma); + s->emm->mio_emm_rsp_sts &=3D ~(OCTEON_MIO_EMM_RSP_STS_DMA_VAL | + OCTEON_MIO_EMM_RSP_STS_DMA_PEND); + s->emm->mio_emm_dma_int |=3D OCTEON_MIO_EMM_DMA_INT_DONE; + s->emm->mio_emm_int |=3D OCTEON_MIO_EMM_INT_DMA_DONE; +} + +static void octeon_mio_emm_command(OcteonState *s, uint64_t cmd) +{ + unsigned int cmd_idx =3D (cmd >> OCTEON_MIO_EMM_CMD_IDX_SHIFT) & + OCTEON_MIO_EMM_CMD_IDX_MASK; + unsigned int bus_id =3D (cmd >> OCTEON_MIO_EMM_CMD_BUS_ID_SHIFT) & + OCTEON_MIO_EMM_BUS_ID_MASK; + + s->emm->mio_emm_rsp_lo =3D 0; + s->emm->mio_emm_rsp_hi =3D 0; + s->emm->mio_emm_rsp_sts =3D + OCTEON_MIO_EMM_RSP_STS_CMD_DONE | + ((uint64_t)cmd_idx << OCTEON_MIO_EMM_RSP_STS_CMD_IDX_SHIFT) | + ((uint64_t)bus_id << OCTEON_MIO_EMM_RSP_STS_BUS_ID_SHIFT); + + switch (cmd_idx) { + case OCTEON_MMC_CMD_GO_IDLE_STATE: + case OCTEON_MMC_CMD_BUSTEST_W: + break; + case OCTEON_MMC_CMD_BUSTEST_R: + octeon_mio_emm_set_bustest(s); + break; + default: + s->emm->mio_emm_rsp_sts |=3D OCTEON_MIO_EMM_RSP_STS_RSP_TIMEOUT; + break; + } + + s->emm->mio_emm_int |=3D OCTEON_MIO_EMM_INT_CMD_DONE; + if (s->emm->mio_emm_rsp_sts & OCTEON_MIO_EMM_RSP_STS_RSP_TIMEOUT) { + s->emm->mio_emm_int |=3D OCTEON_MIO_EMM_INT_CMD_ERR; + } +} + +static uint64_t octeon_mio_emm_read(OcteonState *s, hwaddr reg, + hwaddr addr, unsigned size) +{ + uint64_t value; + + switch (reg) { + case OCTEON_MIO_EMM_RSP_STS: + value =3D s->emm->mio_emm_rsp_sts; + break; + case OCTEON_MIO_EMM_RSP_LO: + value =3D s->emm->mio_emm_rsp_lo; + break; + case OCTEON_MIO_EMM_RSP_HI: + value =3D s->emm->mio_emm_rsp_hi; + break; + case OCTEON_MIO_EMM_BUF_DAT: + value =3D ldq_be_p(s->emm->mio_emm_buf + s->emm->mio_emm_buf_idx); + if (s->emm->mio_emm_buf_inc) { + s->emm->mio_emm_buf_idx =3D + (s->emm->mio_emm_buf_idx + OCTEON_MIO_EMM_BUF_WORD_SIZE) % + OCTEON_MIO_EMM_BUF_SIZE; + } + break; + case OCTEON_MIO_EMM_INT: + value =3D s->emm->mio_emm_int; + break; + case OCTEON_MIO_EMM_DMA_INT: + value =3D s->emm->mio_emm_dma_int; + break; + case OCTEON_MIO_EMM_CMD: + case OCTEON_MIO_EMM_SWITCH: + case OCTEON_MIO_EMM_DMA: + if (!octeon_csr_lookup(s, reg, &value)) { + value =3D 0; + } + break; + case OCTEON_MIO_EMM_MODEX(0): + case OCTEON_MIO_EMM_MODEX(1): + case OCTEON_MIO_EMM_MODEX(2): + case OCTEON_MIO_EMM_MODEX(3): + if (!octeon_csr_lookup(s, reg, &value)) { + value =3D 0; + } + break; + default: + if (!octeon_csr_lookup(s, reg, &value)) { + value =3D 0; + } + break; + } + + return octeon_read64(value, addr, size); +} + +static void octeon_mio_emm_write(OcteonState *s, hwaddr reg, + hwaddr addr, uint64_t value, unsigned siz= e) +{ + uint64_t old; + uint64_t clear; + + switch (reg) { + case OCTEON_MIO_EMM_CMD: + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); + if (!(value & OCTEON_MIO_EMM_CMD_VAL)) { + return; + } + if (!octeon_mio_emm_execute_write(addr, size)) { + return; + } + + octeon_csr_store(s, reg, value & ~OCTEON_MIO_EMM_CMD_VAL); + octeon_mio_emm_command(s, value); + return; + case OCTEON_MIO_EMM_SWITCH: + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); + if (!(value & OCTEON_MIO_EMM_SWITCH_EXE)) { + return; + } + if (!octeon_mio_emm_execute_write(addr, size)) { + return; + } + octeon_csr_store(s, reg, value & ~OCTEON_MIO_EMM_SWITCH_EXE); + octeon_csr_store(s, OCTEON_MIO_EMM_MODEX( + (value >> OCTEON_MIO_EMM_CMD_BUS_ID_SHIFT) & + OCTEON_MIO_EMM_BUS_ID_MASK), + value & OCTEON_MIO_EMM_SWITCH_MODE_MASK); + s->emm->mio_emm_int |=3D OCTEON_MIO_EMM_INT_SWITCH_DONE; + return; + case OCTEON_MIO_EMM_DMA: + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); + if (!(value & OCTEON_MIO_EMM_DMA_VAL)) { + return; + } + if (!octeon_mio_emm_execute_write(addr, size)) { + return; + } + octeon_mio_emm_complete_dma(s, value); + return; + case OCTEON_MIO_EMM_INT: + clear =3D octeon_write64(0, addr, value, size); + s->emm->mio_emm_int &=3D ~clear; + return; + case OCTEON_MIO_EMM_DMA_INT: + clear =3D octeon_write64(0, addr, value, size); + s->emm->mio_emm_dma_int &=3D ~clear; + return; + case OCTEON_MIO_EMM_MODEX(0): + case OCTEON_MIO_EMM_MODEX(1): + case OCTEON_MIO_EMM_MODEX(2): + case OCTEON_MIO_EMM_MODEX(3): + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); + return; + case OCTEON_MIO_EMM_CFG: + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); + if (octeon_mio_emm_execute_write(addr, size)) { + uint64_t enabled =3D (value & ~old) & OCTEON_MIO_EMM_CFG_BUS_E= N_MASK; + unsigned int i; + + for (i =3D 0; i < OCTEON_MIO_EMM_MODE_COUNT; i++) { + if (enabled & (1U << i)) { + octeon_mio_emm_set_low_speed_mode(s, i); + } + } + } + return; + case OCTEON_MIO_EMM_BUF_IDX: + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); + s->emm->mio_emm_buf_idx =3D (value & OCTEON_MIO_EMM_BUF_IDX_OFF_MA= SK) * + OCTEON_MIO_EMM_BUF_WORD_SIZE; + s->emm->mio_emm_buf_inc =3D value & OCTEON_MIO_EMM_BUF_IDX_INC; + return; + case OCTEON_MIO_EMM_BUF_DAT: + old =3D ldq_be_p(s->emm->mio_emm_buf + s->emm->mio_emm_buf_idx); + value =3D octeon_write64(old, addr, value, size); + stq_be_p(s->emm->mio_emm_buf + s->emm->mio_emm_buf_idx, value); + if (s->emm->mio_emm_buf_inc) { + s->emm->mio_emm_buf_idx =3D + (s->emm->mio_emm_buf_idx + OCTEON_MIO_EMM_BUF_WORD_SIZE) % + OCTEON_MIO_EMM_BUF_SIZE; + } + return; + default: + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + value =3D octeon_write64(old, addr, value, size); + octeon_csr_store(s, reg, value); + return; + } +} + static bool octeon_ciu3_source_from_intsn(uint32_t intsn, unsigned int *source) { @@ -1258,6 +1689,7 @@ static uint64_t octeon_csr_read(void *opaque, hwaddr = addr, unsigned size) { OcteonState *s =3D opaque; hwaddr reg =3D addr & ~7ULL; + hwaddr ereg; uint64_t value; =20 if (reg >=3D OCTEON_MIO_BOOT_REG_CFGX(0) && @@ -1294,6 +1726,10 @@ static uint64_t octeon_csr_read(void *opaque, hwaddr= addr, unsigned size) break; } =20 + if (octeon_mio_emm_decode(reg, &ereg)) { + return octeon_mio_emm_read(s, ereg, addr, size); + } + if (!octeon_csr_lookup(s, reg, &value)) { value =3D 0; } @@ -1305,8 +1741,14 @@ static void octeon_csr_write(void *opaque, hwaddr ad= dr, { OcteonState *s =3D opaque; hwaddr reg =3D addr & ~7ULL; + hwaddr ereg; uint64_t old; =20 + if (octeon_mio_emm_decode(reg, &ereg)) { + octeon_mio_emm_write(s, ereg, addr, value, size); + return; + } + if (reg =3D=3D OCTEON_RST_SOFT_RST && value) { qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); return; @@ -1707,6 +2149,26 @@ static void octeon_mio_reset_hold(Object *obj, Reset= Type type) octeon_mio_boot_loc_update(s); } =20 +static void octeon_emm_reset_hold(Object *obj, ResetType type) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); + OcteonEmmState *emm =3D OCTEON_EMM(obj); + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + g_hash_table_remove_all(emm->regs); + emm->mio_emm_rsp_sts =3D 0; + emm->mio_emm_rsp_lo =3D 0; + emm->mio_emm_rsp_hi =3D 0; + emm->mio_emm_int =3D 0; + emm->mio_emm_dma_int =3D 0; + emm->mio_emm_buf_idx =3D 0; + emm->mio_emm_buf_inc =3D false; + memset(emm->mio_emm_buf, 0, sizeof(emm->mio_emm_buf)); +} + static void octeon_rst_reset_hold(Object *obj, ResetType type) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); @@ -1774,6 +2236,16 @@ static GHashTable *octeon_reg_table_new(void) g_free, g_free); } =20 +static void octeon_emm_init(Object *obj) +{ + OCTEON_EMM(obj)->regs =3D octeon_reg_table_new(); +} + +static void octeon_emm_finalize(Object *obj) +{ + g_hash_table_destroy(OCTEON_EMM(obj)->regs); +} + static void octeon_rst_init(Object *obj) { OCTEON_RST(obj)->regs =3D octeon_reg_table_new(); @@ -1803,6 +2275,15 @@ static void octeon_mio_class_init(ObjectClass *klass= , const void *data) NULL, &opc->parent_phases); } =20 +static void octeon_emm_class_init(ObjectClass *klass, const void *data) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + resettable_class_set_parent_phases(rc, NULL, octeon_emm_reset_hold, + NULL, &opc->parent_phases); +} + static void octeon_rst_class_init(ObjectClass *klass, const void *data) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); @@ -1846,6 +2327,7 @@ static OcteonPeripheralState *octeon_new_peripheral(O= cteonState *s, static void octeon_create_peripherals(OcteonState *s) { s->mio =3D OCTEON_MIO(octeon_new_peripheral(s, TYPE_OCTEON_MIO, 0)); + s->emm =3D OCTEON_EMM(octeon_new_peripheral(s, TYPE_OCTEON_EMM, 0)); s->rst =3D OCTEON_RST(octeon_new_peripheral(s, TYPE_OCTEON_RST, 0)); s->intc =3D OCTEON_INTC(octeon_new_peripheral(s, TYPE_OCTEON_INTC, 0)); s->csr_bank =3D OCTEON_CSR_BANK(octeon_new_peripheral( @@ -1862,6 +2344,7 @@ static void octeon_realize_peripherals(OcteonState *s) octeon_realize_peripheral(&s->csr_bank->parent_obj); octeon_realize_peripheral(&s->intc->parent_obj); octeon_realize_peripheral(&s->rst->parent_obj); + octeon_realize_peripheral(&s->emm->parent_obj); octeon_realize_peripheral(&s->mio->parent_obj); } =20 @@ -1986,6 +2469,14 @@ static const TypeInfo octeon_machine_types[] =3D { .instance_size =3D sizeof(OcteonMioState), .class_init =3D octeon_mio_class_init, }, + { + .name =3D TYPE_OCTEON_EMM, + .parent =3D TYPE_OCTEON_PERIPHERAL, + .instance_size =3D sizeof(OcteonEmmState), + .instance_init =3D octeon_emm_init, + .instance_finalize =3D octeon_emm_finalize, + .class_init =3D octeon_emm_class_init, + }, { .name =3D TYPE_OCTEON_RST, .parent =3D TYPE_OCTEON_PERIPHERAL, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index e9826f1713..a262107b54 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -20,6 +20,7 @@ #define OCTEON_CIU3_IDT_COUNT (OCTEON_MAX_CPUS * 4) #define OCTEON_MIO_BOOT_REG_CFG_COUNT 8 #define OCTEON_MIO_BOOT_LOC_SIZE 0x100 +#define OCTEON_MIO_EMM_BUF_SIZE 512 #define OCTEON_TWSI_COUNT 2 #define OCTEON_TWSI_STAT_IDLE 0xf8 #define OCTEON_SPD_EEPROM_SIZE 139 @@ -38,6 +39,7 @@ typedef enum OcteonCiu3Source { =20 typedef struct OcteonState OcteonState; typedef struct OcteonMioState OcteonMioState; +typedef struct OcteonEmmState OcteonEmmState; typedef struct OcteonRstState OcteonRstState; typedef struct OcteonIntcState OcteonIntcState; typedef struct OcteonCsrBankState OcteonCsrBankState; @@ -68,6 +70,7 @@ struct OcteonState { MemoryRegion boot_flash_alias; MemoryRegion cvmseg; OcteonMioState *mio; + OcteonEmmState *emm; OcteonRstState *rst; OcteonIntcState *intc; OcteonCsrBankState *csr_bank; --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437268355343.94539416438704; Thu, 3 Sep 2026 05:07:48 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CT-0002yn-Vs; Thu, 03 Sep 2026 08:05:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CK-0002vq-3Y for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:40 -0400 Received: from mx1.catap.net ([2a01:4f8:271:125e::2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CH-0005L8-FF for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:39 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 7b0242ca (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:32 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 11eabe04; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=tah2DDi riI0VWEaxNQncZ8lM6tGZKdHW8178lrZlXZQSlsoEB88jHc0T7Mi7DmJkvpofOScQErO3v Wut00JDA5L/rbBzCjOamEnFlUU4OVVQs5QkTUWYWzL1qdKe68spxTRHBrRwZSiZCSdv3Oi 7KuxPomoA/u0khNtDbJrz4IQs2gEoseAhGFDsH+Jn7t61XgcE9z0tNCDmEfQLMhMN99Bkb m0weqvkPlX3m+CMadlg2NFCHswUMqgaG+/9L1U9ngqlhapDOwZQda9XNvIJNBGku9mhpfj bcU5RTw+/Ky7gBfmgAhr093BCjAywUUggPFeYeo03lMYmvdGhVsgyWg== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=u yuaKGn+0qiJCEUXSsniBwhezh4HI3vtL0oyS+orCjU=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=Bgw/dLdTrepgUzWx7B6B+dtuqIatmYtOllkyIVvgXXJHr0LSCCgfaXDYrXagIQ6TKBWe NJ6qtKF3s8Pp1QwF0ElnxHO02gZn5+zgnb51J9vnsRXStQRn539b4hg8G/v6AjZ8/LmaSK czsmBX/guFyVsUixxJ+FjhU2l4t8NTGAydwFEyddStrh1a3ba0gyLEsQH2gsKsfxNJCfFT dpFQCGcJQv8N9dBa1tR7Zyl2TOvagSgpgdtLKH6aEYGi+cQV01cTRwK/Jb6kaviSpL19eO 7+gX2DALY8EjoVA6kQP2rjikMhQ+n66eLeond3vqMQr8ok939P3gTTdeeV9wnbtg== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=mSdO4VGp; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=v5PCIT0d; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=uyuaKGn+ 0qiJCEUXSsniBwhezh4HI3vtL0oyS+orCjU=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=mSdO4VGpJdUHJHqzNuHHYoKIeQYTGzUVZEi kPXrkEJnwDA2ICn4TdCSUDsU4+8acXY3z2z7t/YVpYHYok/HASdjLjLyTI8RKgdRjdjTRB P9QTJxPPoT6oxR/a0IK+qnhtRCUuuyjuWBpENM8D5qvsbs8J20yWDi9Q94oACySX8m67jL uh2hD7f+PBBEOse4Tfqt1Bk3+yGzdXMQFNHGWAThdLBSTAsnL0krN9NDebvMZ47ivKVxUV J6+VR5VSa/1EyrqghtHe4yeeFXwlMNOAHI40ZU+kYyZdQeTCzwdm0qYxCQRABa3oVSVOaJ 42n+FxEuSlgE1Ggfs5RDcsIhZZQ== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=uyuaKGn+0qiJCEUXSsniBwhezh4HI3vtL0oyS+orCjU=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=v5PCIT0dDjm80dvqk7 F/gX7vgzig28qVgLSqcTHpcJL1PcDSxguTIbPvMpUejY6LB27IwLXa/PLYE9pGTLNJBw== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 20/25] hw/mips: add Octeon LMC controllers Date: Thu, 3 Sep 2026 14:02:08 +0200 Message-ID: <20260903120510.34876-21-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a01:4f8:271:125e::2; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437270243158500 Content-Type: text/plain; charset="utf-8" Add four Octeon LMC register banks with the DDR training completion, leveling, MPR and clock responses used by firmware. Each LMC owns and resets its mutable register state. --- hw/mips/octeon.c | 184 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 3 + 2 files changed, 187 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index f3f8a74cbe..0553f8ea05 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -10,6 +10,7 @@ #include "qemu/units.h" #include "qemu/datadir.h" #include "qemu/host-utils.h" +#include "qemu/timer.h" #include "qapi/error.h" #include "hw/char/serial-mm.h" #include "hw/core/clock.h" @@ -49,6 +50,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonEmmState, OCTEON_EMM) OBJECT_DECLARE_SIMPLE_TYPE(OcteonRstState, OCTEON_RST) #define TYPE_OCTEON_INTC "octeon-intc" OBJECT_DECLARE_SIMPLE_TYPE(OcteonIntcState, OCTEON_INTC) +#define TYPE_OCTEON_LMC "octeon-lmc" +OBJECT_DECLARE_SIMPLE_TYPE(OcteonLmcState, OCTEON_LMC) #define TYPE_OCTEON_CSR_BANK "octeon-csr-bank" OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR_BANK) =20 @@ -243,6 +246,24 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_= CSR_BANK) #define OCTEON_RST_SOFT_RST 0x6001680 /* U-Boot uses the reset controller to park and release secondary cores. */ #define OCTEON_RST_PP_POWER 0x6001700 +#define OCTEON_LMC_BASE 0x88000000 +#define OCTEON_LMC_SEQ_CTL 0x48 +#define OCTEON_LMC_SEQ_COMPLETE (1ULL << 5) +#define OCTEON_LMC_MPR_DATA0 0x70 +#define OCTEON_LMC_MPR_DATA1 0x78 +#define OCTEON_LMC_DCLK_CNT 0x1e0 +#define OCTEON_LMC_PHY_CTL 0x210 +#define OCTEON_LMC_PHY_DSK_COMPLETE (1ULL << 49) +#define OCTEON_LMC_RLEVEL_RANK 0x280 +#define OCTEON_LMC_RLEVEL_STATUS (3ULL << 54) +#define OCTEON_LMC_RLEVEL_DBG 0x2a8 +#define OCTEON_LMC_RLEVEL_MASK 0x3f0 +#define OCTEON_LMC_WLEVEL_RANK 0x2c0 +#define OCTEON_LMC_RANK_COUNT 4 +#define OCTEON_LMC_WLEVEL_STATUS (3ULL << 45) +#define OCTEON_LMC_WLEVEL_DBG 0x308 +#define OCTEON_LMC_WLEVEL_MASK (0x0fULL << 4) +#define OCTEON_LMC_STRIDE 0x1000000 #define OCTEON_RST_BOOT_C_MUL_SHIFT 30 #define OCTEON_RST_BOOT_PNR_MUL_SHIFT 24 =20 @@ -351,6 +372,11 @@ struct OcteonIntcState { uint8_t ciu3_irq_line[OCTEON_MAX_CPUS][OCTEON_CIU3_CP0_IRQ_COUNT]; }; =20 +struct OcteonLmcState { + OcteonPeripheralState parent_obj; + GHashTable *regs; +}; + struct OcteonCsrBankState { OcteonPeripheralState parent_obj; MemoryRegion csr; @@ -416,6 +442,13 @@ static uint64_t octeon_atomic_write64(uint64_t *ptr, h= waddr addr, return new; } =20 +static uint64_t octeon_clock_count(uint64_t hz) +{ + uint64_t now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + return muldiv64(now, hz, NANOSECONDS_PER_SECOND); +} + static void octeon_validate_clocks(OcteonMachineState *oms) { if (!oms->cpu_hz || !oms->ref_hz || !oms->io_hz || !oms->ddr_hz) { @@ -884,6 +917,94 @@ static void octeon_mio_emm_write(OcteonState *s, hwadd= r reg, } } =20 +static bool octeon_lmc_decode(hwaddr reg, OcteonLmcState **lmc, hwaddr *lr= eg, + OcteonState *s) +{ + hwaddr offset; + unsigned int index; + + if (reg < OCTEON_LMC_BASE) { + return false; + } + + offset =3D reg - OCTEON_LMC_BASE; + index =3D offset / OCTEON_LMC_STRIDE; + if (index >=3D OCTEON_LMC_COUNT) { + return false; + } + + *lmc =3D s->lmc[index]; + *lreg =3D offset % OCTEON_LMC_STRIDE; + return true; +} + +static uint64_t octeon_lmc_get(OcteonLmcState *lmc, hwaddr reg) +{ + uint64_t value; + + if (!octeon_reg_lookup(lmc->regs, reg, &value)) { + return 0; + } + return value; +} + +static bool octeon_lmc_rank_reg(hwaddr reg, hwaddr base) +{ + return reg >=3D base && + reg < base + OCTEON_LMC_RANK_COUNT * 8 && + ((reg - base) & 7) =3D=3D 0; +} + +static uint64_t octeon_lmc_read(OcteonState *s, OcteonLmcState *lmc, + hwaddr reg, hwaddr addr, unsigned size) +{ + uint64_t value; + + switch (reg) { + case OCTEON_LMC_SEQ_CTL: + value =3D octeon_lmc_get(lmc, reg) | OCTEON_LMC_SEQ_COMPLETE; + break; + case OCTEON_LMC_MPR_DATA0: + value =3D ~0ULL; + break; + case OCTEON_LMC_MPR_DATA1: + value =3D 0xff; + break; + case OCTEON_LMC_DCLK_CNT: + value =3D octeon_clock_count(s->ddr_hz); + break; + case OCTEON_LMC_PHY_CTL: + value =3D octeon_lmc_get(lmc, reg) | OCTEON_LMC_PHY_DSK_COMPLETE; + break; + case OCTEON_LMC_RLEVEL_DBG: + value =3D OCTEON_LMC_RLEVEL_MASK; + break; + case OCTEON_LMC_WLEVEL_DBG: + value =3D OCTEON_LMC_WLEVEL_MASK; + break; + default: + if (octeon_lmc_rank_reg(reg, OCTEON_LMC_RLEVEL_RANK)) { + value =3D octeon_lmc_get(lmc, reg) | OCTEON_LMC_RLEVEL_STATUS; + } else if (octeon_lmc_rank_reg(reg, OCTEON_LMC_WLEVEL_RANK)) { + value =3D octeon_lmc_get(lmc, reg) | OCTEON_LMC_WLEVEL_STATUS; + } else { + value =3D octeon_lmc_get(lmc, reg); + } + break; + } + + return octeon_read64(value, addr, size); +} + +static void octeon_lmc_write(OcteonLmcState *lmc, hwaddr reg, + hwaddr addr, uint64_t value, unsigned size) +{ + uint64_t old =3D octeon_lmc_get(lmc, reg); + + value =3D octeon_write64(old, addr, value, size); + octeon_reg_store(lmc->regs, reg, value); +} + static bool octeon_ciu3_source_from_intsn(uint32_t intsn, unsigned int *source) { @@ -1688,7 +1809,9 @@ static const MemoryRegionOps octeon_ciu3_ops =3D { static uint64_t octeon_csr_read(void *opaque, hwaddr addr, unsigned size) { OcteonState *s =3D opaque; + OcteonLmcState *lmc; hwaddr reg =3D addr & ~7ULL; + hwaddr lreg; hwaddr ereg; uint64_t value; =20 @@ -1726,6 +1849,10 @@ static uint64_t octeon_csr_read(void *opaque, hwaddr= addr, unsigned size) break; } =20 + if (octeon_lmc_decode(reg, &lmc, &lreg, s)) { + return octeon_lmc_read(s, lmc, lreg, addr, size); + } + if (octeon_mio_emm_decode(reg, &ereg)) { return octeon_mio_emm_read(s, ereg, addr, size); } @@ -1740,10 +1867,17 @@ static void octeon_csr_write(void *opaque, hwaddr a= ddr, uint64_t value, unsigned size) { OcteonState *s =3D opaque; + OcteonLmcState *lmc; hwaddr reg =3D addr & ~7ULL; + hwaddr lreg; hwaddr ereg; uint64_t old; =20 + if (octeon_lmc_decode(reg, &lmc, &lreg, s)) { + octeon_lmc_write(lmc, lreg, addr, value, size); + return; + } + if (octeon_mio_emm_decode(reg, &ereg)) { octeon_mio_emm_write(s, ereg, addr, value, size); return; @@ -2209,6 +2343,18 @@ static void octeon_intc_reset_hold(Object *obj, Rese= tType type) octeon_intc_update_all_cpus(s); } =20 +static void octeon_lmc_reset_hold(Object *obj, ResetType type) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); + OcteonLmcState *lmc =3D OCTEON_LMC(obj); + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + g_hash_table_remove_all(lmc->regs); +} + static void octeon_csr_bank_reset_hold(Object *obj, ResetType type) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_GET_CLASS(obj); @@ -2256,6 +2402,16 @@ static void octeon_rst_finalize(Object *obj) g_hash_table_destroy(OCTEON_RST(obj)->regs); } =20 +static void octeon_lmc_init(Object *obj) +{ + OCTEON_LMC(obj)->regs =3D octeon_reg_table_new(); +} + +static void octeon_lmc_finalize(Object *obj) +{ + g_hash_table_destroy(OCTEON_LMC(obj)->regs); +} + static void octeon_csr_bank_init(Object *obj) { OCTEON_CSR_BANK(obj)->values =3D octeon_reg_table_new(); @@ -2302,6 +2458,15 @@ static void octeon_intc_class_init(ObjectClass *klas= s, const void *data) NULL, &opc->parent_phases); } =20 +static void octeon_lmc_class_init(ObjectClass *klass, const void *data) +{ + OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + resettable_class_set_parent_phases(rc, NULL, octeon_lmc_reset_hold, + NULL, &opc->parent_phases); +} + static void octeon_csr_bank_class_init(ObjectClass *klass, const void *dat= a) { OcteonPeripheralClass *opc =3D OCTEON_PERIPHERAL_CLASS(klass); @@ -2326,10 +2491,16 @@ static OcteonPeripheralState *octeon_new_peripheral= (OcteonState *s, =20 static void octeon_create_peripherals(OcteonState *s) { + unsigned int i; + s->mio =3D OCTEON_MIO(octeon_new_peripheral(s, TYPE_OCTEON_MIO, 0)); s->emm =3D OCTEON_EMM(octeon_new_peripheral(s, TYPE_OCTEON_EMM, 0)); s->rst =3D OCTEON_RST(octeon_new_peripheral(s, TYPE_OCTEON_RST, 0)); s->intc =3D OCTEON_INTC(octeon_new_peripheral(s, TYPE_OCTEON_INTC, 0)); + for (i =3D 0; i < OCTEON_LMC_COUNT; i++) { + s->lmc[i] =3D OCTEON_LMC(octeon_new_peripheral(s, TYPE_OCTEON_LMC, + i)); + } s->csr_bank =3D OCTEON_CSR_BANK(octeon_new_peripheral( s, TYPE_OCTEON_CSR_BANK, 0)); } @@ -2341,7 +2512,12 @@ static void octeon_realize_peripheral(OcteonPeripher= alState *dev) =20 static void octeon_realize_peripherals(OcteonState *s) { + int i; + octeon_realize_peripheral(&s->csr_bank->parent_obj); + for (i =3D OCTEON_LMC_COUNT - 1; i >=3D 0; i--) { + octeon_realize_peripheral(&s->lmc[i]->parent_obj); + } octeon_realize_peripheral(&s->intc->parent_obj); octeon_realize_peripheral(&s->rst->parent_obj); octeon_realize_peripheral(&s->emm->parent_obj); @@ -2491,6 +2667,14 @@ static const TypeInfo octeon_machine_types[] =3D { .instance_size =3D sizeof(OcteonIntcState), .class_init =3D octeon_intc_class_init, }, + { + .name =3D TYPE_OCTEON_LMC, + .parent =3D TYPE_OCTEON_PERIPHERAL, + .instance_size =3D sizeof(OcteonLmcState), + .instance_init =3D octeon_lmc_init, + .instance_finalize =3D octeon_lmc_finalize, + .class_init =3D octeon_lmc_class_init, + }, { .name =3D TYPE_OCTEON_CSR_BANK, .parent =3D TYPE_OCTEON_PERIPHERAL, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index a262107b54..96443a9d64 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -21,6 +21,7 @@ #define OCTEON_MIO_BOOT_REG_CFG_COUNT 8 #define OCTEON_MIO_BOOT_LOC_SIZE 0x100 #define OCTEON_MIO_EMM_BUF_SIZE 512 +#define OCTEON_LMC_COUNT 4 #define OCTEON_TWSI_COUNT 2 #define OCTEON_TWSI_STAT_IDLE 0xf8 #define OCTEON_SPD_EEPROM_SIZE 139 @@ -42,6 +43,7 @@ typedef struct OcteonMioState OcteonMioState; typedef struct OcteonEmmState OcteonEmmState; typedef struct OcteonRstState OcteonRstState; typedef struct OcteonIntcState OcteonIntcState; +typedef struct OcteonLmcState OcteonLmcState; typedef struct OcteonCsrBankState OcteonCsrBankState; =20 typedef struct OcteonCPUState { @@ -73,6 +75,7 @@ struct OcteonState { OcteonEmmState *emm; OcteonRstState *rst; OcteonIntcState *intc; + OcteonLmcState *lmc[OCTEON_LMC_COUNT]; OcteonCsrBankState *csr_bank; OcteonSpdEepromState *spd[OCTEON_SPD_EEPROM_COUNT]; SerialMM *uart; --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437159233547.7989203265867; Thu, 3 Sep 2026 05:05:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CY-0003AM-FF; Thu, 03 Sep 2026 08:05:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CK-0002wD-U8 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:41 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CI-0005JF-LD for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:40 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 1b2a744a (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:32 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id be389880; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=NM48FED chACfZ+4icZ+6eMxqqC23HSluTAbiH79u6ELGPpf49Er+SelVinbKtprLkvu80suc+CtRK K4Lq8tzBZJpsHw66mO7XJzlOX3jk/q8qt6viMkpRRJ1O2FUNr9zEnaAyyzt6/3bZ7WY+Yx WDmkRzQbxonZNgc4BIKCQmbjGESzOSGvWMh+W2wOuoyfdwL+odVB384biXMvtF/wQHBMcE +LEEWRMFQQk4YxjR8CQqBPGUevL8GBFBg0JWqUuwLA9IMqxpwPSvFaMhFad92jWCYlgC2T lMKTV76eAXwB4YQQzYeggGgWXaCxzbWcx05rx5Z7KrxjMZiDM6tpc7A== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=u G4Wpq5dy0v9JEJ6kGmy5Xn/8RRoBpPloiNIYVwqEyw=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=S30M2Vi499GnkzwBn7hlUjiwV8MZXMacybA1Cwzya/9LTP2F5184xWMCIVK+XYUo06ly 4+km1Wg+A4vYRDJdmUmOhRSgblXKELORPbKm0UdYJU+YJt+Xvp75royPwb8eI8bR+lkVbV gqs53Uu7T6XDkmQVN9yX2FyHkX8Zv9drgZFHe9HXqmd3Rdo3BvTWOeBBDGycGO1EEF0V7/ UE5HN4LLlayTWPyQFLCGF0cJhEibxlQ65mtRvTy9k5MGUt/SasByC34Zs3YC1HGH0CwL7F 7FBJFkcPKKC+XZ9HuG71DMbmNL+wtZRa705Y/3ojSxIbiO+A7SM1GH8tqrgMGPCA== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=njTU7JZe; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=8DWOE7RB; arc=none; iprev=fail; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=uG4Wpq5d y0v9JEJ6kGmy5Xn/8RRoBpPloiNIYVwqEyw=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=njTU7JZeop92ZSl9gtSzaZ4orAIVRr/AoW9 yI2A0Oiri5hdSwi8AGzRxUXnOs6Ft1keQ+xBZvRBzDCcV558v+EhDtj1yqS0WQKminmUkg oFm6aQnNQDp6AgCKEsXga9BNBTv8y5hWW8tu9Z1HZs5pOL2WaM/POMJpX4WZbWyALw2oPF YdxaWm4Yxii4Ogp7qhEJ/j7Ytb9MNaDvIEm6GFU8tbg3tuMM8HUNqZ42GBb2Q1VYlc0JsE 5v/r+ThGvBGYe2DdyhBuwnlfDovUAimWoR/1AgKSF0PKv/AaYnFoczVT4qe2ZGjWojHV/M YM5RvPplt9XAHMg1V19I81+KOVg== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=uG4Wpq5dy0v9JEJ6kGmy5Xn/8RRoBpPloiNIYVwqEyw=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=8DWOE7RB44s6Tyf+6l 6FHGLZArhBKp5mjI31eDfC7T9O4/Dy3LRlZ7FmGDu9v+CeFlD2M167EBiCtpkAvrHKCQ== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 21/25] hw/mips: add Octeon boot support registers Date: Thu, 3 Sep 2026 14:02:09 +0200 Message-ID: <20260903120510.34876-22-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437162115158500 Content-Type: text/plain; charset="utf-8" Add the small DPI, FPA, IPD, PKO, RNG and POW register windows needed while firmware initializes the platform. Reuse the CSR bank for stored values and compute clock and random values on demand. --- hw/mips/octeon.c | 218 ++++++++++++++++++++++++++++++++++++++ hw/mips/octeon_internal.h | 6 ++ 2 files changed, 224 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 0553f8ea05..7e78511b8f 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -30,6 +30,7 @@ #include "system/runstate.h" #include "system/system.h" #include "exec/cpu-interrupt.h" +#include "qemu/guest-random.h" #include "qemu/error-report.h" #include "qemu/atomic.h" #include "hw/mips/octeon_internal.h" @@ -140,6 +141,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_C= SR_BANK) #define OCTEON_CIU3_UART0_INTSN 0x8000 #define OCTEON_CSR_BASE 0x1180000000000ULL #define OCTEON_CSR_SIZE 0x100000000ULL +#define OCTEON_DPI_BASE 0x1df0000000000ULL +#define OCTEON_DPI_SIZE 0x10000 #define OCTEON_MIO_BOOT_REG_CFGX(x) \ (0x0000000 + (x) * OCTEON_CSR_64BIT_SIZE) #define OCTEON_MIO_BOOT_REG_CFG_INDEX(reg) \ @@ -267,6 +270,23 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_= CSR_BANK) #define OCTEON_RST_BOOT_C_MUL_SHIFT 30 #define OCTEON_RST_BOOT_PNR_MUL_SHIFT 24 =20 +#define OCTEON_FPA_BASE 0x1280000000000ULL +#define OCTEON_FPA_SIZE 0x1000 +#define OCTEON_FPA_CLK_COUNT 0xf0 + +#define OCTEON_IPD_BASE 0x14f0000000000ULL +#define OCTEON_IPD_SIZE 0x1000 +#define OCTEON_IPD_CLK_COUNT 0x338 + +#define OCTEON_PKO_BASE 0x1540000000000ULL +#define OCTEON_PKO_SIZE 0x1000000 + +#define OCTEON_RNG_BASE 0x1400000000000ULL +#define OCTEON_RNG_SIZE 0x8 + +#define OCTEON_POW_BASE 0x1670000000000ULL +#define OCTEON_POW_SIZE 0x2000 + #define OCTEON_UART0_BASE 0x1180000000800ULL #define OCTEON_UART0_ALIAS_BASE 0x1180000000c00ULL #define OCTEON_UART_TX_REG 0x40 @@ -1955,6 +1975,174 @@ static const MemoryRegionOps octeon_csr_ops =3D { }, }; =20 +static uint64_t octeon_stateful_io_read(OcteonState *s, uint64_t base, + hwaddr addr, unsigned size) +{ + uint64_t value; + uint64_t reg =3D base + (addr & ~7ULL); + + if (!octeon_csr_lookup(s, reg, &value)) { + value =3D 0; + } + + return octeon_read64(value, addr, size); +} + +static void octeon_stateful_io_write(OcteonState *s, uint64_t base, + hwaddr addr, uint64_t value, + unsigned size) +{ + uint64_t reg =3D base + (addr & ~7ULL); + uint64_t old; + + if (!octeon_csr_lookup(s, reg, &old)) { + old =3D 0; + } + + octeon_csr_store(s, reg, octeon_write64(old, addr, value, size)); +} + +static uint64_t octeon_dpi_read(void *opaque, hwaddr addr, unsigned size) +{ + return octeon_stateful_io_read(opaque, OCTEON_DPI_BASE, addr, size); +} + +static void octeon_dpi_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + octeon_stateful_io_write(opaque, OCTEON_DPI_BASE, addr, value, size); +} + +static const MemoryRegionOps octeon_dpi_ops =3D { + .read =3D octeon_dpi_read, + .write =3D octeon_dpi_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static uint64_t octeon_fpa_read(void *opaque, hwaddr addr, unsigned size) +{ + OcteonState *s =3D opaque; + hwaddr reg =3D addr & ~7ULL; + + if (reg =3D=3D OCTEON_FPA_CLK_COUNT) { + return octeon_read64(octeon_clock_count(s->io_hz), addr, size); + } + + return 0; +} + +static void octeon_fpa_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ +} + +static const MemoryRegionOps octeon_fpa_ops =3D { + .read =3D octeon_fpa_read, + .write =3D octeon_fpa_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static uint64_t octeon_ipd_read(void *opaque, hwaddr addr, unsigned size) +{ + OcteonState *s =3D opaque; + hwaddr reg =3D addr & ~7ULL; + + if (reg =3D=3D OCTEON_IPD_CLK_COUNT) { + return octeon_read64(octeon_clock_count(s->io_hz), addr, size); + } + + return 0; +} + +static void octeon_ipd_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ +} + +static const MemoryRegionOps octeon_ipd_ops =3D { + .read =3D octeon_ipd_read, + .write =3D octeon_ipd_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static uint64_t octeon_pko_read(void *opaque, hwaddr addr, unsigned size) +{ + return octeon_stateful_io_read(opaque, OCTEON_PKO_BASE, addr, size); +} + +static void octeon_pko_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + octeon_stateful_io_write(opaque, OCTEON_PKO_BASE, addr, value, size); +} + +static const MemoryRegionOps octeon_pko_ops =3D { + .read =3D octeon_pko_read, + .write =3D octeon_pko_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static uint64_t octeon_rng_read(void *opaque, hwaddr addr, unsigned size) +{ + uint64_t value; + + qemu_guest_getrandom_nofail(&value, sizeof(value)); + return octeon_read64(value, addr, size); +} + +static void octeon_rng_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ +} + +static const MemoryRegionOps octeon_rng_ops =3D { + .read =3D octeon_rng_read, + .write =3D octeon_rng_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static uint64_t octeon_pow_read(void *opaque, hwaddr addr, unsigned size) +{ + return octeon_stateful_io_read(opaque, OCTEON_POW_BASE, addr, size); +} + +static void octeon_pow_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + octeon_stateful_io_write(opaque, OCTEON_POW_BASE, addr, value, size); +} + +static const MemoryRegionOps octeon_pow_ops =3D { + .read =3D octeon_pow_read, + .write =3D octeon_pow_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + + void octeon_irq_set(void *opaque, int irq, int level) { OcteonState *s =3D opaque; @@ -2573,6 +2761,36 @@ static void mips_octeon_init(MachineState *machine) memory_region_add_subregion_overlap(get_system_memory(), OCTEON_CSR_BA= SE, &s->csr_bank->csr, -1); =20 + memory_region_init_io(&s->dpi, NULL, &octeon_dpi_ops, s, + "octeon.dpi", OCTEON_DPI_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_DPI_BASE, + &s->dpi); + + memory_region_init_io(&s->fpa, NULL, &octeon_fpa_ops, s, + "octeon.fpa", OCTEON_FPA_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_FPA_BASE, + &s->fpa); + + memory_region_init_io(&s->ipd, NULL, &octeon_ipd_ops, s, + "octeon.ipd", OCTEON_IPD_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_IPD_BASE, + &s->ipd); + + memory_region_init_io(&s->pko, NULL, &octeon_pko_ops, s, + "octeon.pko", OCTEON_PKO_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_PKO_BASE, + &s->pko); + + memory_region_init_io(&s->rng, NULL, &octeon_rng_ops, s, + "octeon.rng", OCTEON_RNG_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_RNG_BASE, + &s->rng); + + memory_region_init_io(&s->pow, NULL, &octeon_pow_ops, s, + "octeon.pow", OCTEON_POW_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_POW_BASE, + &s->pow); + octeon_realize_peripherals(s); } =20 diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 96443a9d64..f2daa35cdb 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -71,6 +71,12 @@ struct OcteonState { MemoryRegion boot_flash; MemoryRegion boot_flash_alias; MemoryRegion cvmseg; + MemoryRegion dpi; + MemoryRegion fpa; + MemoryRegion ipd; + MemoryRegion pko; + MemoryRegion rng; + MemoryRegion pow; OcteonMioState *mio; OcteonEmmState *emm; OcteonRstState *rst; --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 178843717356047.77221099465282; Thu, 3 Sep 2026 05:06:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CY-0003AJ-Eu; Thu, 03 Sep 2026 08:05:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CM-0002we-VM for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:45 -0400 Received: from mx1.catap.net ([162.55.82.72]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CJ-0005LJ-JT for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:41 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id c65ce093 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:33 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 298e3df3; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=uDdB2kD TBwRQmlEa3lLQlQZbnaZ4Bw70zweWkcHKCFHVTT5WEP7xnB/YUGRfNMAbUvT0SqSFbGTWw StAFRsyuyqKrrdCGAsFbM9SLmhxnOFFoAVvU5VnVeU/4uCvjprsKI+5fCQBLUxrB4a/dOx oGxZGSOf53BW2UrfTEnLhlNXb1UeTKfBc3vSw8zuyHLZPSPzTM7eGXikokAwsKnk2bROgi yBizJCUJCjIcgAPEWsVSHskERVOgfCR4y36d//x68GREybylBWipwdvkCsNChHq0LKhg1Q FMmvD3ADrcCde5sQY3ogcz76Q+OdgGL39sxNEIxay0ti/hHO3MV6Zig== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=l hLU3w6jM+wQ8szhcfeAWP1jX6A99vY6o3UnGD+JBHY=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=UcGNeZ8n3sCe5X91niU267vpEXOJy9vYEdZwGzxs+srycwK5SfzNaNp0aP3z7PD8ZWeF n3DSkv+voqdjH3KmU2myz2mb/RfeJpSiUoRb05tl0kpOI7eiPsuGj0rZDPZ2LEh7+Q9W1o 6SiiPBb6xyPxH+oKcGd9C1Nr06vwSGhLVRl2LxbgAFkg0Ja9SDGuPhMa8LPYgVAlNdNI/z qB/7lD2u9Gl6tp0ew5WrmmfIC6Ym+UW5eufSsRUQRNrR/W0M6sQYWLufymSHyfdhOJDqGH DpPyeSDb+RBT54FLjKr7wUtrVmMKWdUcj29DF+G0EXx3jAzt6PIQmBocUAj1O22A== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=onLoAPHJ; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=UXj3ND09; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=lhLU3w6j M+wQ8szhcfeAWP1jX6A99vY6o3UnGD+JBHY=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=onLoAPHJW4AS2b74ZYwWNxpYFM5nJDtQYA5 CF8ngFLr2gU2JJIoGeDe1HhAMICF8QVsOb2wxTfX7Sksr7BFmQO9IkLL/7xcybupKx8TrN 26Bb4FpuD+gZyX3q/GSGj5jWAF15z6r1BGBK5QNJuHK3VCCVIHC2LkSyHRuO7zhu1WCKhj sePyuS5shYnm6hQ6WiCrigncgYMZ0VtVk6T5rDFuN0Zl/d/mS4R7sfQJOKINCbTlP/CszU EE05Apzn7Ly7wmi02bLtWpI6jVEhvK5sSlZimmqnJ8ER/gNrlS3clw7vOBdFKg7dhcQTmV yKq3kV7C9zlns9ysPdtCBXYJNjw== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=lhLU3w6jM+wQ8szhcfeAWP1jX6A99vY6o3UnGD+JBHY=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=UXj3ND09jLhhVEM+XL 91A3vkMirglMSAepR8Hju1TR9ihY+xUqwDksa7s29Ekls6vLQqGxMDu6FQALyEGyY0BA== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 22/25] hw/usb: add Octeon USB controller Date: Thu, 3 Sep 2026 14:02:10 +0200 Message-ID: <20260903120510.34876-23-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=162.55.82.72; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437175973158501 Content-Type: text/plain; charset="utf-8" Add the Octeon UCTL wrapper around the DWC3 controller, including the big endian register window, byte swapping, DMA mapping and interrupt routing. Instantiate both EBB7304 USB controllers. --- hw/mips/Kconfig | 1 + hw/mips/octeon.c | 31 ++++ hw/mips/octeon_internal.h | 6 + hw/usb/meson.build | 5 + hw/usb/octeon_usb.c | 319 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 362 insertions(+) create mode 100644 hw/usb/octeon_usb.c diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 5fe5f885e3..2566df6da6 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -73,6 +73,7 @@ config MIPS_OCTEON depends on MIPS64 && TARGET_BIG_ENDIAN select PFLASH_CFI02 select SERIAL_MM + select USB_DWC3 =20 config MIPS_CPS bool diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 7e78511b8f..94717b6c89 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -287,6 +287,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_C= SR_BANK) #define OCTEON_POW_BASE 0x1670000000000ULL #define OCTEON_POW_SIZE 0x2000 =20 +#define OCTEON_CIU3_USB0_INTSN 0x68080 +#define OCTEON_CIU3_USB1_INTSN 0x69080 + #define OCTEON_UART0_BASE 0x1180000000800ULL #define OCTEON_UART0_ALIAS_BASE 0x1180000000c00ULL #define OCTEON_UART_TX_REG 0x40 @@ -1032,6 +1035,15 @@ static bool octeon_ciu3_source_from_intsn(uint32_t i= ntsn, *source =3D OCTEON_CIU3_SRC_UART0; return true; } + if (intsn =3D=3D OCTEON_CIU3_USB0_INTSN) { + *source =3D OCTEON_CIU3_SRC_USB0; + return true; + } + if (intsn =3D=3D OCTEON_CIU3_USB1_INTSN) { + *source =3D OCTEON_CIU3_SRC_USB1; + return true; + } + if (intsn >=3D OCTEON_CIU3_MBOX_INTSN(0) && intsn < OCTEON_CIU3_MBOX_INTSN(OCTEON_MAX_CPUS)) { *source =3D OCTEON_CIU3_SRC_MBOX0 + @@ -1047,6 +1059,10 @@ static uint32_t octeon_ciu3_source_intsn(unsigned in= t source) switch (source) { case OCTEON_CIU3_SRC_UART0: return OCTEON_CIU3_UART0_INTSN; + case OCTEON_CIU3_SRC_USB0: + return OCTEON_CIU3_USB0_INTSN; + case OCTEON_CIU3_SRC_USB1: + return OCTEON_CIU3_USB1_INTSN; } =20 if (source >=3D OCTEON_CIU3_SRC_MBOX0 && @@ -1061,6 +1077,8 @@ static bool octeon_ciu3_source_is_level(unsigned int = source) { switch (source) { case OCTEON_CIU3_SRC_UART0: + case OCTEON_CIU3_SRC_USB0: + case OCTEON_CIU3_SRC_USB1: return true; } =20 @@ -2156,6 +2174,18 @@ void octeon_irq_set(void *opaque, int irq, int level) } qatomic_set(&s->intc->uart_pending, level); break; + case OCTEON_IRQ_USB0: + src =3D OCTEON_CIU3_SRC_USB0; + if (!octeon_ciu3_set_level(s, src, level)) { + return; + } + break; + case OCTEON_IRQ_USB1: + src =3D OCTEON_CIU3_SRC_USB1; + if (!octeon_ciu3_set_level(s, src, level)) { + return; + } + break; default: return; } @@ -2791,6 +2821,7 @@ static void mips_octeon_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), OCTEON_POW_BASE, &s->pow); =20 + octeon_init_usb(s); octeon_realize_peripherals(s); } =20 diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index f2daa35cdb..6c93c957de 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -22,6 +22,7 @@ #define OCTEON_MIO_BOOT_LOC_SIZE 0x100 #define OCTEON_MIO_EMM_BUF_SIZE 512 #define OCTEON_LMC_COUNT 4 +#define OCTEON_USB_COUNT 2 #define OCTEON_TWSI_COUNT 2 #define OCTEON_TWSI_STAT_IDLE 0xf8 #define OCTEON_SPD_EEPROM_SIZE 139 @@ -29,11 +30,15 @@ =20 typedef enum OcteonIRQ { OCTEON_IRQ_UART, + OCTEON_IRQ_USB0, + OCTEON_IRQ_USB1, OCTEON_IRQ_COUNT, } OcteonIRQ; =20 typedef enum OcteonCiu3Source { OCTEON_CIU3_SRC_UART0, + OCTEON_CIU3_SRC_USB0, + OCTEON_CIU3_SRC_USB1, OCTEON_CIU3_SRC_MBOX0, OCTEON_CIU3_SRC_COUNT =3D OCTEON_CIU3_SRC_MBOX0 + OCTEON_MAX_CPUS, } OcteonCiu3Source; @@ -103,5 +108,6 @@ void octeon_irq_set(void *opaque, int irq, int level); void octeon_validate_ram_size(uint64_t ram_size); void octeon_init_spd(OcteonState *s); void octeon_init_twsi(OcteonState *s); +void octeon_init_usb(OcteonState *s); =20 #endif diff --git a/hw/usb/meson.build b/hw/usb/meson.build index ba55c28ef6..051140fa57 100644 --- a/hw/usb/meson.build +++ b/hw/usb/meson.build @@ -28,6 +28,11 @@ system_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('h= cd-dwc2.c')) system_ss.add(when: 'CONFIG_USB_DWC3', if_true: files('hcd-dwc3.c')) system_ss.add(when: 'CONFIG_USB_CHIPIDEA', if_true: files('chipidea.c')) =20 +if 'CONFIG_TCG' in config_all_accel + mips_ss.add(when: 'CONFIG_MIPS_OCTEON', + if_true: files('octeon_usb.c')) +endif + system_ss.add(when: 'CONFIG_IMX_USBPHY', if_true: files('imx-usb-phy.c')) system_ss.add(when: 'CONFIG_VT82C686', if_true: files('vt82c686-uhci-pci.c= ')) system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-usb2= -ctrl-regs.c')) diff --git a/hw/usb/octeon_usb.c b/hw/usb/octeon_usb.c new file mode 100644 index 0000000000..48e9ec234f --- /dev/null +++ b/hw/usb/octeon_usb.c @@ -0,0 +1,319 @@ +/* + * QEMU Cavium Octeon USB controller model. + * + * Copyright (c) 2026 Kirill A. Korinsky + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/bswap.h" +#include "qapi/error.h" +#include "hw/core/irq.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/resettable.h" +#include "hw/core/sysbus.h" +#include "hw/mips/octeon_internal.h" +#include "hw/usb/hcd-dwc3.h" +#include "system/address-spaces.h" +#include "system/memory.h" + +#define OCTEON_UCTL_SIZE 0x100 +#define OCTEON_USB0_UCTL_BASE 0x1180068000000ULL +#define OCTEON_USB1_UCTL_BASE 0x1180069000000ULL +#define OCTEON_USB0_DWC3_BASE 0x1680000000000ULL +#define OCTEON_USB1_DWC3_BASE 0x1690000000000ULL +#define OCTEON_UCTL_SHIM_CFG 0xe8 +#define OCTEON_UCTL_SHIM_CFG_CSR_BYTE_SWAP 0x3 +#define OCTEON_UCTL_SHIM_CFG_CSR_NATIVE 0x3 + +#define TYPE_OCTEON_USB "octeon-usb" +OBJECT_DECLARE_TYPE(OcteonUsbState, OcteonUsbClass, OCTEON_USB) + +struct OcteonUsbState { + SysBusDevice parent_obj; + USBDWC3 dwc3; + unsigned int index; + MemoryRegion uctl; + MemoryRegion dwc3_window; + AddressSpace dwc3_as; + GHashTable *regs; + bool dwc3_as_initialized; +}; + +struct OcteonUsbClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + +static uint64_t octeon_uctl_read(void *opaque, hwaddr addr, unsigned size) +{ + OcteonUsbState *usb =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t value; + + if (!octeon_reg_lookup(usb->regs, reg, &value)) { + value =3D 0; + } + + return octeon_read64(value, addr, size); +} + +static void octeon_uctl_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonUsbState *usb =3D opaque; + hwaddr reg =3D addr & ~7ULL; + uint64_t old; + + if (!octeon_reg_lookup(usb->regs, reg, &old)) { + old =3D 0; + } + + octeon_reg_store(usb->regs, reg, octeon_write64(old, addr, value, size= )); +} + +static const MemoryRegionOps octeon_uctl_ops =3D { + .read =3D octeon_uctl_read, + .write =3D octeon_uctl_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static bool octeon_usb_csr_needs_swap(OcteonUsbState *usb) +{ +#if TARGET_BIG_ENDIAN + uint64_t value; + + if (!octeon_reg_lookup(usb->regs, OCTEON_UCTL_SHIM_CFG, &value)) { + return true; + } + + return (value & OCTEON_UCTL_SHIM_CFG_CSR_BYTE_SWAP) !=3D + OCTEON_UCTL_SHIM_CFG_CSR_NATIVE; +#else + return false; +#endif +} + +static uint64_t octeon_usb_swap(uint64_t value, unsigned size) +{ + switch (size) { + case 2: + return bswap16(value); + case 4: + return bswap32(value); + case 8: + return bswap64(value); + default: + return value; + } +} + +static uint64_t octeon_dwc3_window_read(void *opaque, hwaddr addr, + unsigned size) +{ + OcteonUsbState *usb =3D opaque; + uint64_t value; + + switch (size) { + case 1: + value =3D address_space_ldub(&usb->dwc3_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 2: + value =3D address_space_lduw_le(&usb->dwc3_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 4: + value =3D address_space_ldl_le(&usb->dwc3_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 8: + value =3D address_space_ldq_le(&usb->dwc3_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + default: + g_assert_not_reached(); + } + + if (octeon_usb_csr_needs_swap(usb)) { + value =3D octeon_usb_swap(value, size); + } + + return value; +} + +static void octeon_dwc3_window_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonUsbState *usb =3D opaque; + + if (octeon_usb_csr_needs_swap(usb)) { + value =3D octeon_usb_swap(value, size); + } + + switch (size) { + case 1: + address_space_stb(&usb->dwc3_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 2: + address_space_stw_le(&usb->dwc3_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 4: + address_space_stl_le(&usb->dwc3_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 8: + address_space_stq_le(&usb->dwc3_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + default: + g_assert_not_reached(); + } +} + +static const MemoryRegionOps octeon_dwc3_window_ops =3D { + .read =3D octeon_dwc3_window_read, + .write =3D octeon_dwc3_window_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + }, +}; + +static void octeon_usb_reset_hold(Object *obj, ResetType type) +{ + OcteonUsbClass *ouc =3D OCTEON_USB_GET_CLASS(obj); + OcteonUsbState *usb =3D OCTEON_USB(obj); + + if (ouc->parent_phases.hold) { + ouc->parent_phases.hold(obj, type); + } + + g_hash_table_remove_all(usb->regs); +} + +static void octeon_usb_realize(DeviceState *dev, Error **errp) +{ + OcteonUsbState *usb =3D OCTEON_USB(dev); + static const char * const uctl_name[OCTEON_USB_COUNT] =3D { + "octeon.usb0-uctl", + "octeon.usb1-uctl", + }; + static const char * const dwc3_window_name[OCTEON_USB_COUNT] =3D { + "octeon.usb0-dwc3-window", + "octeon.usb1-dwc3-window", + }; + static const char * const dwc3_as_name[OCTEON_USB_COUNT] =3D { + "octeon.usb0-dwc3-as", + "octeon.usb1-dwc3-as", + }; + USBDWC3 *dwc3 =3D &usb->dwc3; + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + MemoryRegion *dwc3_mr; + + object_property_set_link(OBJECT(&dwc3->sysbus_xhci), "dma", + OBJECT(get_system_memory()), &error_abort); + qdev_prop_set_uint32(DEVICE(&dwc3->sysbus_xhci), "intrs", 1); + if (!sysbus_realize(SYS_BUS_DEVICE(dwc3), errp)) { + return; + } + + dwc3_mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dwc3), 0); + address_space_init(&usb->dwc3_as, dwc3_mr, + dwc3_as_name[usb->index]); + usb->dwc3_as_initialized =3D true; + memory_region_init_io(&usb->uctl, OBJECT(dev), &octeon_uctl_ops, usb, + uctl_name[usb->index], OCTEON_UCTL_SIZE); + sysbus_init_mmio(sbd, &usb->uctl); + memory_region_init_io(&usb->dwc3_window, OBJECT(dev), + &octeon_dwc3_window_ops, usb, + dwc3_window_name[usb->index], DWC3_SIZE); + sysbus_init_mmio(sbd, &usb->dwc3_window); + sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&dwc3->sysbus_xhci)); +} + +static void octeon_usb_init(Object *obj) +{ + OcteonUsbState *usb =3D OCTEON_USB(obj); + + usb->regs =3D g_hash_table_new_full(octeon_uint64_hash, + octeon_uint64_equal, + g_free, g_free); + object_initialize_child(obj, "dwc3", &usb->dwc3, TYPE_USB_DWC3); +} + +static void octeon_usb_finalize(Object *obj) +{ + OcteonUsbState *usb =3D OCTEON_USB(obj); + + if (usb->dwc3_as_initialized) { + address_space_destroy(&usb->dwc3_as); + } + g_hash_table_destroy(usb->regs); +} + +static void octeon_usb_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + OcteonUsbClass *ouc =3D OCTEON_USB_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + dc->realize =3D octeon_usb_realize; + dc->user_creatable =3D false; + resettable_class_set_parent_phases(rc, NULL, octeon_usb_reset_hold, NU= LL, + &ouc->parent_phases); +} + +static const TypeInfo octeon_usb_type_info =3D { + .name =3D TYPE_OCTEON_USB, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(OcteonUsbState), + .instance_init =3D octeon_usb_init, + .instance_finalize =3D octeon_usb_finalize, + .class_size =3D sizeof(OcteonUsbClass), + .class_init =3D octeon_usb_class_init, +}; + +static void octeon_usb_register_types(void) +{ + type_register_static(&octeon_usb_type_info); +} + +type_init(octeon_usb_register_types) + +void octeon_init_usb(OcteonState *s) +{ + static const uint64_t uctl_base[OCTEON_USB_COUNT] =3D { + OCTEON_USB0_UCTL_BASE, + OCTEON_USB1_UCTL_BASE, + }; + static const uint64_t dwc3_base[OCTEON_USB_COUNT] =3D { + OCTEON_USB0_DWC3_BASE, + OCTEON_USB1_DWC3_BASE, + }; + static const OcteonIRQ irq[OCTEON_USB_COUNT] =3D { + OCTEON_IRQ_USB0, + OCTEON_IRQ_USB1, + }; + unsigned int i; + + for (i =3D 0; i < OCTEON_USB_COUNT; i++) { + DeviceState *dev =3D qdev_new(TYPE_OCTEON_USB); + OcteonUsbState *usb =3D OCTEON_USB(dev); + + usb->index =3D i; + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, uctl_base[i]); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, dwc3_base[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, + qemu_allocate_irq(octeon_irq_set, s, irq[i])); + } +} --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437263682881.1612123841996; Thu, 3 Sep 2026 05:07:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CV-00037t-Sf; Thu, 03 Sep 2026 08:05:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CP-0002xu-U4 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:45 -0400 Received: from mx2.catap.net ([65.21.79.163]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CK-0005Ja-4C for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:43 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 114d187b (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:33 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 164ebe22; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=Bjt9VRn zIlt4tu9CqYdv0rGLhdjRa6fsIPFWBMsFSWN52hBJelPdOWBUoVh7bkgC8gSHGAUsKqWn1 Jmfv0dog74zSM9Hk7EIvfHbMyOM0O4scfcmtRaELuGZusl+oa8xwkclezWXLMeglYyMYMm mzcPcm/4nNRbM0AKxTHvoUGJ9CO0JP7nRq0N4GReqyLqjxxCdc7xtp9hvKTmZfASqZTNab bMOWPht/TUomOE/MLzJmEyQ0yuPQMNq5GiKq5/iOFqpcI7OyKUXPDazix0jw0fv962RmpF EDNSawClwbSNg1tG2COZuU5+e6n/E3MN6iLgmNWfLoERPu0x5fQbadA== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=h ER9bORUlFmyfRtvkhLfd0zjk5YWg3b77uyWOSu9Sbk=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=fmblZ1hcOCG1e4o8YpGObXQbxqUbrUQ3j6ZqX6TnQwBYp8qbu4Umffxt2uBY1TIrp4Da FgJcxbh0GiWfH3tixfVqKP+IcQO37YaSN29qyGuGR4lspGiCfuiW7HaBOq5rWCJ62yhvzc /tPHIQWhHgSf+yioMshJnklQjk4Mq8wSze20O7Ax4jq9POjpjaaP4sXveFk6qQ4eaPvIWw 51AfjUl3WPc4P6JYQyMd4RoQb/g5z7kpVsKPxGigIPZcENyAL8Jg24hZtdHlryKoHVDCdB PFNqeAMsiuFEhT/MEa1A7fNL7fIx6m4gp6O3MeaeKjV0NcTIVx+J6lIes48P8iGg== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=qabOOGsx; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=L1OJS7To; arc=none; iprev=fail; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=hER9bORU lFmyfRtvkhLfd0zjk5YWg3b77uyWOSu9Sbk=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=qabOOGsx7EabylemmVl3KMULPju+jeJzTeP LwuBjDwmgj3riX16+j22q7H8nYYe//zH8ItQLeP3PdStLCU0f5yYuZyoBef8ZMp0vdAXZ4 6mCghAjsAEUpS5VPheoLNxW2rZs3k/KsTnvNjQ6zfg6hlUBsBcvtXNa5YNPO1S9cdxjjfg p2fboH9wfc7mOAbnkV9mrxgvMG8R6kK5Qx0nB2QKrr5TFrzAROSgbIfkJU3bYI5tsCINus veDWfL9zdC5CUOU+Myeh2HgnNdPO7ZuISvnTfba8WcW9BeNf/HYXfhPeV0R0qaiD1Ffcpi 0+rMTUwUWifx9C82GJ0qv6jRqcA== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=hER9bORUlFmyfRtvkhLfd0zjk5YWg3b77uyWOSu9Sbk=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=L1OJS7ToAd6QojPBeY wLfk1iGmawmbz9rMlpxdCkZnwySP4A5dRMYkPbGhYSwrVJcgG7SMZUUEACVbrwnisCBg== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 23/25] hw/pci-bridge: add Octeon PCI host bridge Date: Thu, 3 Sep 2026 14:02:11 +0200 Message-ID: <20260903120510.34876-24-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=65.21.79.163; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437264432158500 Content-Type: text/plain; charset="utf-8" Add the root bus, configuration apertures, I/O window, PEM register access and interrupt routing. Leave guest PCI memory transactions to a separate patch. --- hw/mips/Kconfig | 3 + hw/mips/octeon.c | 69 ++++++- hw/mips/octeon_internal.h | 13 ++ hw/pci-bridge/meson.build | 5 + hw/pci-bridge/octeon_pci.c | 356 +++++++++++++++++++++++++++++++++++++ 5 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 hw/pci-bridge/octeon_pci.c diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 2566df6da6..54ce3cafbd 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -71,6 +71,9 @@ config MIPS_OCTEON bool default y depends on MIPS64 && TARGET_BIG_ENDIAN + imply E1000_PCI + imply PCI_DEVICES + select PCI select PFLASH_CFI02 select SERIAL_MM select USB_DWC3 diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 94717b6c89..19d1451464 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -94,6 +94,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR= _BANK) #define OCTEON_CIU_FUSE 0x728 #define OCTEON_CIU_SUM_IPI 0x0000000100000000ULL #define OCTEON_CIU_SUM_UART 0x0000000800000000ULL +#define OCTEON_CIU_SUM_PCI 0x0000001000000000ULL #define OCTEON_CIU_ENABLE0 0x88006f1800000000ULL #define OCTEON_CIU_IPI_SUM_BASE 0x008 #define OCTEON_CIU_IPI_SUM_STRIDE 0x10 @@ -137,6 +138,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_C= SR_BANK) #define OCTEON_CIU3_SRC_RAW 0x00000002U #define OCTEON_CIU3_NINTSN (1U << 20) #define OCTEON_CIU3_ISC_SIZE (OCTEON_CIU3_NINTSN * 8) +#define OCTEON_CIU3_PEM_INTSN_INTA(port) (((0xc0 + (port)) << 12) + 60) #define OCTEON_CIU3_MBOX_INTSN(cpu) ((cpu) + 0x4000U) #define OCTEON_CIU3_UART0_INTSN 0x8000 #define OCTEON_CSR_BASE 0x1180000000000ULL @@ -304,6 +306,18 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_= CSR_BANK) #define OCTEON_CVMSEG_SIZE 0x4000 #define OCTEON_CVMSEG_TOTAL_SIZE (OCTEON_MAX_CPUS * OCTEON_CVMSEG_SIZE) =20 +#define OCTEON_GSERX_CFG0 0x90000080 +#define OCTEON_GSERX_QLM_STAT0 0x900000a0 +#define OCTEON_RST_CTLX0 0x6001640 +#define OCTEON_RST_SOFT_PRSTX0 0x60016c0 +#define OCTEON_PEMX_CFG_RD0 0xc0000030 +#define OCTEON_PEMX_CFG_WR0 0xc0000028 +#define OCTEON_PEMX_BIST_STATUS0 0xc0000440 +#define OCTEON_PEMX_ON0 0xc0000420 +#define OCTEON_PEMX_STRAP0 0xc0000408 + +#define OCTEON_RST_CTL_HOST_MODE (1ULL << 6) +#define OCTEON_RST_CTL_RST_DONE (1ULL << 8) #define OCTEON_FLASH_BASE 0x1f400000ULL #define OCTEON_FLASH_RESET_BASE 0x1fc00000ULL #define OCTEON_FLASH_RESET_SIZE (4 * MiB) @@ -385,6 +399,7 @@ struct OcteonIntcState { uint64_t ciu_gpio_tx; uint64_t ciu_gpio_bit_cfg[OCTEON_CIU_GPIO_COUNT]; bool uart_pending; + bool pci_pending; uint64_t ciu3_pp_rst; uint32_t ciu3_src_state[OCTEON_CIU3_SRC_COUNT]; uint64_t ciu3_src_ctl[OCTEON_CIU3_SRC_COUNT]; @@ -517,7 +532,8 @@ bool octeon_csr_lookup(OcteonState *s, uint64_t reg, ui= nt64_t *value) if (octeon_mio_emm_decode(reg, &ereg)) { return octeon_reg_lookup(s->emm->regs, ereg, value); } - if (reg =3D=3D OCTEON_RST_SOFT_RST) { + if (reg =3D=3D OCTEON_RST_CTLX0 || reg =3D=3D OCTEON_RST_SOFT_PRSTX0 || + reg =3D=3D OCTEON_RST_SOFT_RST) { return octeon_reg_lookup(s->rst->regs, reg, value); } return octeon_reg_lookup(s->csr_bank->values, reg, value); @@ -531,7 +547,8 @@ static void octeon_csr_store(OcteonState *s, uint64_t r= eg, uint64_t value) octeon_reg_store(s->emm->regs, ereg, value); return; } - if (reg =3D=3D OCTEON_RST_SOFT_RST) { + if (reg =3D=3D OCTEON_RST_CTLX0 || reg =3D=3D OCTEON_RST_SOFT_PRSTX0 || + reg =3D=3D OCTEON_RST_SOFT_RST) { octeon_reg_store(s->rst->regs, reg, value); return; } @@ -1031,6 +1048,10 @@ static void octeon_lmc_write(OcteonLmcState *lmc, hw= addr reg, static bool octeon_ciu3_source_from_intsn(uint32_t intsn, unsigned int *source) { + if (intsn =3D=3D OCTEON_CIU3_PEM_INTSN_INTA(0)) { + *source =3D OCTEON_CIU3_SRC_PCI_INTA; + return true; + } if (intsn =3D=3D OCTEON_CIU3_UART0_INTSN) { *source =3D OCTEON_CIU3_SRC_UART0; return true; @@ -1057,6 +1078,8 @@ static bool octeon_ciu3_source_from_intsn(uint32_t in= tsn, static uint32_t octeon_ciu3_source_intsn(unsigned int source) { switch (source) { + case OCTEON_CIU3_SRC_PCI_INTA: + return OCTEON_CIU3_PEM_INTSN_INTA(0); case OCTEON_CIU3_SRC_UART0: return OCTEON_CIU3_UART0_INTSN; case OCTEON_CIU3_SRC_USB0: @@ -1076,6 +1099,7 @@ static uint32_t octeon_ciu3_source_intsn(unsigned int= source) static bool octeon_ciu3_source_is_level(unsigned int source) { switch (source) { + case OCTEON_CIU3_SRC_PCI_INTA: case OCTEON_CIU3_SRC_UART0: case OCTEON_CIU3_SRC_USB0: case OCTEON_CIU3_SRC_USB1: @@ -1395,6 +1419,9 @@ static uint64_t octeon_ciu_read(void *opaque, hwaddr = addr, unsigned size) if (qatomic_read(&s->intc->uart_pending)) { value |=3D OCTEON_CIU_SUM_UART; } + if (qatomic_read(&s->intc->pci_pending)) { + value |=3D OCTEON_CIU_SUM_PCI; + } octeon_intc_request_cpu_update(s, 0); return octeon_read64(value, addr, size); } @@ -1883,6 +1910,29 @@ static uint64_t octeon_csr_read(void *opaque, hwaddr= addr, unsigned size) return octeon_read64(value, addr, size); case OCTEON_RST_PP_POWER: return octeon_read64(s->rst->rst_pp_power, addr, size); + case OCTEON_GSERX_CFG0: + return octeon_read64(1, addr, size); + case OCTEON_GSERX_QLM_STAT0: + return octeon_read64(3, addr, size); + case OCTEON_RST_CTLX0: + if (!octeon_csr_lookup(s, reg, &value)) { + value =3D OCTEON_RST_CTL_HOST_MODE | OCTEON_RST_CTL_RST_DONE; + } + return octeon_read64(value, addr, size); + case OCTEON_RST_SOFT_PRSTX0: + if (!octeon_csr_lookup(s, reg, &value)) { + value =3D 1; + } + return octeon_read64(value, addr, size); + case OCTEON_PEMX_CFG_RD0: + case OCTEON_PEMX_CFG_WR0: + return octeon_pci_pem_read(s, reg, addr, size); + case OCTEON_PEMX_BIST_STATUS0: + return 0; + case OCTEON_PEMX_ON0: + return octeon_read64(3, addr, size); + case OCTEON_PEMX_STRAP0: + return octeon_read64(3, addr, size); default: break; } @@ -1963,6 +2013,11 @@ static void octeon_csr_write(void *opaque, hwaddr ad= dr, return; } =20 + if (reg =3D=3D OCTEON_PEMX_CFG_RD0 || reg =3D=3D OCTEON_PEMX_CFG_WR0) { + octeon_pci_pem_write(s, reg, addr, value, size); + return; + } + if (reg >=3D OCTEON_MIO_BOOT_REG_CFGX(0) && reg < OCTEON_MIO_BOOT_REG_CFGX(OCTEON_MIO_BOOT_REG_CFG_COUNT)) { unsigned int index =3D OCTEON_MIO_BOOT_REG_CFG_INDEX(reg); @@ -2174,6 +2229,13 @@ void octeon_irq_set(void *opaque, int irq, int level) } qatomic_set(&s->intc->uart_pending, level); break; + case OCTEON_IRQ_PCI: + src =3D OCTEON_CIU3_SRC_PCI_INTA; + if (!octeon_ciu3_set_level(s, src, level)) { + return; + } + qatomic_set(&s->intc->pci_pending, level); + break; case OCTEON_IRQ_USB0: src =3D OCTEON_CIU3_SRC_USB0; if (!octeon_ciu3_set_level(s, src, level)) { @@ -2550,6 +2612,7 @@ static void octeon_intc_reset_hold(Object *obj, Reset= Type type) qatomic_set(&intc->ciu_gpio_tx, 0); memset(intc->ciu_gpio_bit_cfg, 0, sizeof(intc->ciu_gpio_bit_cfg)); qatomic_set(&intc->uart_pending, false); + qatomic_set(&intc->pci_pending, false); qatomic_set(&intc->ciu3_pp_rst, octeon_secondary_cpu_mask(s)); memset(intc->ciu3_src_state, 0, sizeof(intc->ciu3_src_state)); memset(intc->ciu3_src_ctl, 0, sizeof(intc->ciu3_src_ctl)); @@ -2822,6 +2885,7 @@ static void mips_octeon_init(MachineState *machine) &s->pow); =20 octeon_init_usb(s); + octeon_init_pci(s); octeon_realize_peripherals(s); } =20 @@ -2877,6 +2941,7 @@ static void octeon_machine_class_init(ObjectClass *oc= , const void *data) mc->default_ram_size =3D OCTEON_DEFAULT_RAM_SIZE; mc->default_ram_id =3D "octeon.ram"; mc->max_cpus =3D OCTEON_MAX_CPUS; + mc->pci_allow_0_address =3D true; } =20 static const TypeInfo octeon_machine_types[] =3D { diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 6c93c957de..c2a88dac46 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -30,12 +30,14 @@ =20 typedef enum OcteonIRQ { OCTEON_IRQ_UART, + OCTEON_IRQ_PCI, OCTEON_IRQ_USB0, OCTEON_IRQ_USB1, OCTEON_IRQ_COUNT, } OcteonIRQ; =20 typedef enum OcteonCiu3Source { + OCTEON_CIU3_SRC_PCI_INTA, OCTEON_CIU3_SRC_UART0, OCTEON_CIU3_SRC_USB0, OCTEON_CIU3_SRC_USB1, @@ -93,6 +95,12 @@ struct OcteonState { MemoryRegion uart_alias; MemoryRegion uart_tx; MemoryRegion uart_alias_tx; + MemoryRegion pcie_cfg; + MemoryRegion pcie_sli_cfg; + MemoryRegion pcie0_io; + + DeviceState *pci_host; + PCIBus *pci_bus; }; =20 guint octeon_uint64_hash(gconstpointer v); @@ -109,5 +117,10 @@ void octeon_validate_ram_size(uint64_t ram_size); void octeon_init_spd(OcteonState *s); void octeon_init_twsi(OcteonState *s); void octeon_init_usb(OcteonState *s); +void octeon_init_pci(OcteonState *s); +uint64_t octeon_pci_pem_read(OcteonState *s, hwaddr reg, + hwaddr addr, unsigned size); +void octeon_pci_pem_write(OcteonState *s, hwaddr reg, hwaddr addr, + uint64_t value, unsigned size); =20 #endif diff --git a/hw/pci-bridge/meson.build b/hw/pci-bridge/meson.build index 2e0eb0d233..caababc555 100644 --- a/hw/pci-bridge/meson.build +++ b/hw/pci-bridge/meson.build @@ -9,6 +9,11 @@ pci_ss.add(when: 'CONFIG_PXB', if_true: files('pci_expande= r_bridge.c'), pci_ss.add(when: 'CONFIG_XIO3130', if_true: files('xio3130_upstream.c', 'x= io3130_downstream.c')) pci_ss.add(when: 'CONFIG_CXL', if_true: files('cxl_root_port.c', 'cxl_upst= ream.c', 'cxl_downstream.c')) =20 +if 'CONFIG_TCG' in config_all_accel + mips_ss.add(when: 'CONFIG_MIPS_OCTEON', + if_true: files('octeon_pci.c')) +endif + # Sun4u pci_ss.add(when: 'CONFIG_SIMBA', if_true: files('simba.c')) =20 diff --git a/hw/pci-bridge/octeon_pci.c b/hw/pci-bridge/octeon_pci.c new file mode 100644 index 0000000000..e2f856e164 --- /dev/null +++ b/hw/pci-bridge/octeon_pci.c @@ -0,0 +1,356 @@ +/* + * QEMU Cavium Octeon PCI host bridge model. + * + * Copyright (c) 2026 Kirill A. Korinsky + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/core/resettable.h" +#include "hw/core/sysbus.h" +#include "hw/mips/octeon_internal.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "qemu/module.h" +#include "system/memory.h" + +#define TYPE_OCTEON_PCI_HOST "octeon-pci-host" +OBJECT_DECLARE_TYPE(OcteonPCIHostState, OcteonPCIHostClass, + OCTEON_PCI_HOST) + +#define OCTEON_PCIE_CFG_BASE 0x1190400000000ULL +#define OCTEON_PCIE_CFG_SIZE 0x20000000ULL +#define OCTEON_PCIE_SLI_CFG_BASE 0x1190c00000000ULL +#define OCTEON_PCIE_SLI_CFG_PORTS 4 +#define OCTEON_PCIE_SLI_CFG_PORT_SIZE (1ULL << 32) +#define OCTEON_PCIE_SLI_CFG_SIZE \ + (OCTEON_PCIE_SLI_CFG_PORTS * OCTEON_PCIE_SLI_CFG_PORT_SIZE) +#define OCTEON_PCIE0_IO_BASE 0x11a0400000000ULL +#define OCTEON_PCIE0_IO_SIZE (1ULL << 32) +#define OCTEON_PCIE0_MEM_SIZE (1ULL << 32) +#define OCTEON_PCIE0_ENDPOINT_DEVFN PCI_DEVFN(0x0b, 0) +#define OCTEON_PEMX_CFG_WR0 0xc0000028 +#define OCTEON_PEMX_CFG_RD0 0xc0000030 +#define OCTEON_PCIE_CFG006 0x018 +#define OCTEON_PCIE_CFG031 0x07c +#define OCTEON_PCIE_CFG032 0x080 +#define OCTEON_PCIE_CFG068 0x110 + +struct OcteonPCIHostState { + PCIHostState parent_obj; + MemoryRegion mem; + MemoryRegion io; + uint32_t pem_cfg_rd_addr; + uint64_t pem_cfg_wr; + GHashTable *root_cfg; +}; + +struct OcteonPCIHostClass { + PCIHostBridgeClass parent_class; + ResettablePhases parent_phases; +}; + +static void octeon_pci_host_reset_hold(Object *obj, ResetType type) +{ + OcteonPCIHostState *host =3D OCTEON_PCI_HOST(obj); + OcteonPCIHostClass *opc =3D OCTEON_PCI_HOST_GET_CLASS(obj); + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + host->pem_cfg_rd_addr =3D 0; + host->pem_cfg_wr =3D 0; + g_hash_table_remove_all(host->root_cfg); +} + +static OcteonPCIHostState *octeon_pci_host(OcteonState *s) +{ + return OCTEON_PCI_HOST(s->pci_host); +} + +static uint32_t octeon_pcie_root_cfg_default(uint32_t reg) +{ + switch (reg) { + case OCTEON_PCIE_CFG006: + return 0x00010101; + case OCTEON_PCIE_CFG031: + return 0x00000011; + case OCTEON_PCIE_CFG032: + return 0x20110000; + default: + return 0; + } +} + +static uint32_t octeon_pcie_root_cfg_read(OcteonPCIHostState *host, + uint32_t reg) +{ + uint64_t value; + + reg &=3D ~3U; + switch (reg) { + case OCTEON_PCIE_CFG006: + case OCTEON_PCIE_CFG031: + case OCTEON_PCIE_CFG032: + return octeon_pcie_root_cfg_default(reg); + default: + break; + } + + if (octeon_reg_lookup(host->root_cfg, reg, &value)) { + return value; + } + + return octeon_pcie_root_cfg_default(reg); +} + +static void octeon_pcie_root_cfg_write(OcteonPCIHostState *host, + uint32_t reg, uint32_t value) +{ + reg &=3D ~3U; + if (reg =3D=3D OCTEON_PCIE_CFG068) { + value =3D 0; + } + + octeon_reg_store(host->root_cfg, reg, value); +} + +uint64_t octeon_pci_pem_read(OcteonState *s, hwaddr reg, + hwaddr addr, unsigned size) +{ + OcteonPCIHostState *host =3D octeon_pci_host(s); + uint64_t value; + + switch (reg) { + case OCTEON_PEMX_CFG_RD0: + value =3D ((uint64_t)octeon_pcie_root_cfg_read( + host, host->pem_cfg_rd_addr) << 32) | + host->pem_cfg_rd_addr; + break; + case OCTEON_PEMX_CFG_WR0: + value =3D host->pem_cfg_wr; + break; + default: + g_assert_not_reached(); + } + + return octeon_read64(value, addr, size); +} + +void octeon_pci_pem_write(OcteonState *s, hwaddr reg, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonPCIHostState *host =3D octeon_pci_host(s); + + switch (reg) { + case OCTEON_PEMX_CFG_RD0: + value =3D octeon_write64(0, addr, value, size); + host->pem_cfg_rd_addr =3D value; + break; + case OCTEON_PEMX_CFG_WR0: + value =3D octeon_write64(host->pem_cfg_wr, addr, value, size); + octeon_pcie_root_cfg_write(host, value, value >> 32); + host->pem_cfg_wr =3D value; + break; + default: + g_assert_not_reached(); + } +} + +static uint64_t octeon_pci_absent(unsigned size) +{ + return size =3D=3D 1 ? 0xff : size =3D=3D 2 ? 0xffff : 0xffffffffU; +} + +static bool octeon_pcie_config_addr(hwaddr addr, uint32_t *pci_addr, + bool sli_cfg) +{ + unsigned int bus =3D (addr >> 20) & 0xff; + unsigned int dev =3D (addr >> 15) & 0x1f; + unsigned int fn =3D (addr >> 12) & 0x7; + unsigned int reg =3D addr & 0xfff; + + if (sli_cfg) { + if (addr >=3D OCTEON_PCIE_SLI_CFG_PORT_SIZE || + bus !=3D 0 || dev !=3D 0 || fn !=3D 0 || + reg >=3D PCI_CONFIG_SPACE_SIZE) { + return false; + } + } else if (bus !=3D 1 || dev !=3D 0 || fn !=3D 0 || + reg >=3D PCI_CONFIG_SPACE_SIZE) { + return false; + } + + *pci_addr =3D 0x80000000U | (OCTEON_PCIE0_ENDPOINT_DEVFN << 8) | reg; + return true; +} + +static uint64_t octeon_pcie_cfg_read(void *opaque, hwaddr addr, + unsigned size) +{ + OcteonState *s =3D opaque; + uint32_t pci_addr; + + if (!octeon_pcie_config_addr(addr, &pci_addr, false)) { + return octeon_pci_absent(size); + } + + return pci_data_read(s->pci_bus, pci_addr, size); +} + +static void octeon_pcie_cfg_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s =3D opaque; + uint32_t pci_addr; + + if (octeon_pcie_config_addr(addr, &pci_addr, false)) { + pci_data_write(s->pci_bus, pci_addr, value, size); + } +} + +static const MemoryRegionOps octeon_pcie_cfg_ops =3D { + .read =3D octeon_pcie_cfg_read, + .write =3D octeon_pcie_cfg_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static uint64_t octeon_pcie_sli_cfg_read(void *opaque, hwaddr addr, + unsigned size) +{ + OcteonState *s =3D opaque; + uint32_t pci_addr; + + if (!octeon_pcie_config_addr(addr, &pci_addr, true)) { + return octeon_pci_absent(size); + } + + return pci_data_read(s->pci_bus, pci_addr, size); +} + +static void octeon_pcie_sli_cfg_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s =3D opaque; + uint32_t pci_addr; + + if (octeon_pcie_config_addr(addr, &pci_addr, true)) { + pci_data_write(s->pci_bus, pci_addr, value, size); + } +} + +static const MemoryRegionOps octeon_pcie_sli_cfg_ops =3D { + .read =3D octeon_pcie_sli_cfg_read, + .write =3D octeon_pcie_sli_cfg_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static int octeon_pci_map_irq(PCIDevice *pci_dev, int irq_num) +{ + return 0; +} + +static void octeon_pci_set_irq(void *opaque, int irq_num, int level) +{ + octeon_irq_set(opaque, OCTEON_IRQ_PCI, level); +} + +static void octeon_pci_host_init(Object *obj) +{ + OcteonPCIHostState *host =3D OCTEON_PCI_HOST(obj); + + host->root_cfg =3D g_hash_table_new_full(octeon_uint64_hash, + octeon_uint64_equal, + g_free, g_free); +} + +static void octeon_pci_host_finalize(Object *obj) +{ + OcteonPCIHostState *host =3D OCTEON_PCI_HOST(obj); + + g_hash_table_destroy(host->root_cfg); +} + +static void octeon_pci_host_class_init(ObjectClass *klass, const void *dat= a) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + OcteonPCIHostClass *opc =3D OCTEON_PCI_HOST_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + dc->fw_name =3D "pci"; + dc->user_creatable =3D false; + resettable_class_set_parent_phases(rc, NULL, + octeon_pci_host_reset_hold, NULL, + &opc->parent_phases); +} + +static const TypeInfo octeon_pci_host_info =3D { + .name =3D TYPE_OCTEON_PCI_HOST, + .parent =3D TYPE_PCI_HOST_BRIDGE, + .instance_size =3D sizeof(OcteonPCIHostState), + .instance_init =3D octeon_pci_host_init, + .instance_finalize =3D octeon_pci_host_finalize, + .class_size =3D sizeof(OcteonPCIHostClass), + .class_init =3D octeon_pci_host_class_init, +}; + +static void octeon_pci_host_register_types(void) +{ + type_register_static(&octeon_pci_host_info); +} + +type_init(octeon_pci_host_register_types) + +void octeon_init_pci(OcteonState *s) +{ + DeviceState *dev; + OcteonPCIHostState *host; + PCIHostState *phb; + + dev =3D qdev_new(TYPE_OCTEON_PCI_HOST); + host =3D OCTEON_PCI_HOST(dev); + s->pci_host =3D dev; + phb =3D PCI_HOST_BRIDGE(dev); + + memory_region_init(&host->mem, OBJECT(dev), "octeon.pci-mem", + OCTEON_PCIE0_MEM_SIZE); + memory_region_init(&host->io, OBJECT(dev), "octeon.pci-io", + OCTEON_PCIE0_IO_SIZE); + + phb->bus =3D pci_root_bus_new(dev, "pci", &host->mem, &host->io, + OCTEON_PCIE0_ENDPOINT_DEVFN, TYPE_PCI_BUS); + s->pci_bus =3D phb->bus; + pci_bus_irqs(s->pci_bus, octeon_pci_set_irq, s, 1); + pci_bus_map_irqs(s->pci_bus, octeon_pci_map_irq); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + memory_region_init_io(&s->pcie_cfg, NULL, &octeon_pcie_cfg_ops, s, + "octeon.pcie-config", OCTEON_PCIE_CFG_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_PCIE_CFG_BASE, + &s->pcie_cfg); + + memory_region_init_io(&s->pcie_sli_cfg, NULL, &octeon_pcie_sli_cfg_ops, + s, "octeon.pcie-sli-config", + OCTEON_PCIE_SLI_CFG_SIZE); + memory_region_add_subregion(get_system_memory(), + OCTEON_PCIE_SLI_CFG_BASE, + &s->pcie_sli_cfg); + + memory_region_init_alias(&s->pcie0_io, NULL, "octeon.pcie0-io", + &host->io, 0, + OCTEON_PCIE0_IO_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_PCIE0_IO_BASE, + &s->pcie0_io); + +} --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437269552987.7786196663128; Thu, 3 Sep 2026 05:07:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CX-00039f-Dl; Thu, 03 Sep 2026 08:05:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CS-0002yu-03 for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:49 -0400 Received: from mx2.catap.net ([2a01:4f9:3b:5410::2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CP-0005LP-Ki for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:47 -0400 Received: by mx2.catap.net (OpenSMTPD) with ESMTPSA id 13c34ed9 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:35 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id c0f7e4e2; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=HSXENeI JsLofcj6myfLouGpyRAj20qnRyyUMOj9ivGOUfqC00yE2O1I6HJNzzgUMdVnoKKm3Nfe37 sz+uzpKJZ1+JrX6YvmWvmhgYeZnTxHm+fBEYop4aPODuCAvUz+XzLt+pOIZewu/2ONiqjS kGO5VDVuD5EF/S2IBO2QLlXI/CemLaSydIUeUeexnHI7/Lwyoj+jbGWvjDh2mEK8etdWoV XPTwZQPimFUDm/vZ3B9KG2QGrTaOtUzRCJtR5Qs+UcyaGrNbhqCpoE1yhyZmF5UkHwUufT 0dlKA9Wsbohf+2+0O4QgUy/8b+Y0VhYsIsDimdsLiu2EVxhFovAypEQ== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=n uFO7LRIQOm580PX9X/euSBat09d/+pN13p352WestQ=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=fGULJ+aZcDCGCMt2plrs2HPOhAbPa+q2kHRtNpZi7mHFbd88kRseZlnxf6G3DVPuUrgE XJVnwgNplM6VBR8PbjV8eVhKyfzmD7aQAtrf5+5RrH2PVOJlSCKnG8jdDX0RN9dEERx8oi mlqYO/4tlSkr9+iz2WeeQtsWloEYwZh/ztJ321v06Clq9z4K0QLhY3Wi7Wf0V+oJJodr9G VXGuF2l54h0aLB7qpbvNMn3XbIab6dnptKPF19jEYHbxCI2D1QLm+jouAZHFoJRdfc7pjQ iD7wwhxYkuuza0sBEj5TE0LWazINsi6BcSVrthV5O6XKx950z9M05T6tqf3lJLYA== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=SHHRWdkh; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=mBummw1g; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=nuFO7LRI QOm580PX9X/euSBat09d/+pN13p352WestQ=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=SHHRWdkhlfhaLl0gCZuq2Hpbri9wf8uoVr/ BEPW7kIjRnTG1mkMl30H7w57ELzeFM+YpEkOoDul1rFHs4qctNmg8MWUncYS0tStiT1og7 NFUJv5qsXEdaZFzpo3u2xma944h6XVWumO0wdc2FlOZ6eORbpTUxu45NxREli9caW0mrmv /0L4ytKFCxl62+TSO0vT3NAaqmOp+S0VHkDvhpT84W9W7JsFgLUSCM1hWAd1Vw17iamVSH 7EqYweVAuEqj3vFkaPPBHc9FPqcjbjl3CLzmiauSEjoSpcS6CXe6zzSlhUMB4dZv3jQ4oF kz9P0YLqYqrfMr5lU8LWXVCSMww== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=nuFO7LRIQOm580PX9X/euSBat09d/+pN13p352WestQ=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=mBummw1glvtUIQdB5q I24FIXbM4wBlHD2rnGXJdaZXV62tL5rfMVNobinVDaqEjQEB4rpySTPv53rorhO1WVAA== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 24/25] hw/pci-bridge: add Octeon PCI memory window Date: Thu, 3 Sep 2026 14:02:12 +0200 Message-ID: <20260903120510.34876-25-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a01:4f9:3b:5410::2; envelope-from=kirill@korins.ky; helo=mx2.catap.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437272248158500 Content-Type: text/plain; charset="utf-8" Map the PCI memory aperture and PEXP register bank. Apply SUBID controlled byte swapping to transactions between the big endian CPU and little endian PCI memory space. --- hw/mips/octeon.c | 26 ++++++ hw/mips/octeon_internal.h | 8 ++ hw/pci-bridge/octeon_pci.c | 174 +++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 19d1451464..596fd678ff 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -2075,6 +2075,27 @@ static void octeon_stateful_io_write(OcteonState *s,= uint64_t base, octeon_csr_store(s, reg, octeon_write64(old, addr, value, size)); } =20 +static uint64_t octeon_pexp_read(void *opaque, hwaddr addr, unsigned size) +{ + return octeon_pci_pexp_read(opaque, addr, size); +} + +static void octeon_pexp_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + octeon_pci_pexp_write(opaque, addr, value, size); +} + +static const MemoryRegionOps octeon_pexp_ops =3D { + .read =3D octeon_pexp_read, + .write =3D octeon_pexp_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + static uint64_t octeon_dpi_read(void *opaque, hwaddr addr, unsigned size) { return octeon_stateful_io_read(opaque, OCTEON_DPI_BASE, addr, size); @@ -2854,6 +2875,11 @@ static void mips_octeon_init(MachineState *machine) memory_region_add_subregion_overlap(get_system_memory(), OCTEON_CSR_BA= SE, &s->csr_bank->csr, -1); =20 + memory_region_init_io(&s->pexp, NULL, &octeon_pexp_ops, s, + "octeon.pexp", OCTEON_PEXP_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_PEXP_BASE, + &s->pexp); + memory_region_init_io(&s->dpi, NULL, &octeon_dpi_ops, s, "octeon.dpi", OCTEON_DPI_SIZE); memory_region_add_subregion(get_system_memory(), OCTEON_DPI_BASE, diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index c2a88dac46..f4ecbbac4f 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -18,6 +18,8 @@ #define OCTEON_CIU_GPIO_COUNT 32 #define OCTEON_CIU3_CP0_IRQ_COUNT 4 #define OCTEON_CIU3_IDT_COUNT (OCTEON_MAX_CPUS * 4) +#define OCTEON_PEXP_BASE 0x11f0000000000ULL +#define OCTEON_PEXP_SIZE 0x40000 #define OCTEON_MIO_BOOT_REG_CFG_COUNT 8 #define OCTEON_MIO_BOOT_LOC_SIZE 0x100 #define OCTEON_MIO_EMM_BUF_SIZE 512 @@ -78,6 +80,7 @@ struct OcteonState { MemoryRegion boot_flash; MemoryRegion boot_flash_alias; MemoryRegion cvmseg; + MemoryRegion pexp; MemoryRegion dpi; MemoryRegion fpa; MemoryRegion ipd; @@ -98,6 +101,8 @@ struct OcteonState { MemoryRegion pcie_cfg; MemoryRegion pcie_sli_cfg; MemoryRegion pcie0_io; + MemoryRegion pcie0_mem; + AddressSpace pcie0_mem_as; =20 DeviceState *pci_host; PCIBus *pci_bus; @@ -122,5 +127,8 @@ uint64_t octeon_pci_pem_read(OcteonState *s, hwaddr reg, hwaddr addr, unsigned size); void octeon_pci_pem_write(OcteonState *s, hwaddr reg, hwaddr addr, uint64_t value, unsigned size); +uint64_t octeon_pci_pexp_read(OcteonState *s, hwaddr addr, unsigned size); +void octeon_pci_pexp_write(OcteonState *s, hwaddr addr, + uint64_t value, unsigned size); =20 #endif diff --git a/hw/pci-bridge/octeon_pci.c b/hw/pci-bridge/octeon_pci.c index e2f856e164..02c42c4d09 100644 --- a/hw/pci-bridge/octeon_pci.c +++ b/hw/pci-bridge/octeon_pci.c @@ -7,6 +7,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/bswap.h" #include "qapi/error.h" #include "hw/core/resettable.h" #include "hw/core/sysbus.h" @@ -14,6 +15,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" #include "qemu/module.h" +#include "system/address-spaces.h" #include "system/memory.h" =20 #define TYPE_OCTEON_PCI_HOST "octeon-pci-host" @@ -29,7 +31,15 @@ OBJECT_DECLARE_TYPE(OcteonPCIHostState, OcteonPCIHostCla= ss, (OCTEON_PCIE_SLI_CFG_PORTS * OCTEON_PCIE_SLI_CFG_PORT_SIZE) #define OCTEON_PCIE0_IO_BASE 0x11a0400000000ULL #define OCTEON_PCIE0_IO_SIZE (1ULL << 32) +#define OCTEON_PCIE0_MEM_BASE 0x11b0000000000ULL #define OCTEON_PCIE0_MEM_SIZE (1ULL << 32) +#define OCTEON_SLI_MEM_ACCESS_SUBID_BASE 0x000000e0 +#define OCTEON_SLI_MEM_ACCESS_SUBID_STRIDE 16 +#define OCTEON_SLI_MEM_ACCESS_SUBID_ESR_M 0x0000003000000000ULL +#define OCTEON_SLI_MEM_ACCESS_SUBID_ESR_S 36 +#define OCTEON_SLI_MEM_ACCESS_SUBID_ESW_M 0x0000000c00000000ULL +#define OCTEON_SLI_MEM_ACCESS_SUBID_ESW_S 34 +#define OCTEON_SLI_MEM_ACCESS_SWAP 3 #define OCTEON_PCIE0_ENDPOINT_DEVFN PCI_DEVFN(0x0b, 0) #define OCTEON_PEMX_CFG_WR0 0xc0000028 #define OCTEON_PEMX_CFG_RD0 0xc0000030 @@ -45,6 +55,7 @@ struct OcteonPCIHostState { uint32_t pem_cfg_rd_addr; uint64_t pem_cfg_wr; GHashTable *root_cfg; + GHashTable *pexp_regs; }; =20 struct OcteonPCIHostClass { @@ -64,6 +75,7 @@ static void octeon_pci_host_reset_hold(Object *obj, Reset= Type type) host->pem_cfg_rd_addr =3D 0; host->pem_cfg_wr =3D 0; g_hash_table_remove_all(host->root_cfg); + g_hash_table_remove_all(host->pexp_regs); } =20 static OcteonPCIHostState *octeon_pci_host(OcteonState *s) @@ -160,6 +172,34 @@ void octeon_pci_pem_write(OcteonState *s, hwaddr reg, = hwaddr addr, } } =20 +uint64_t octeon_pci_pexp_read(OcteonState *s, hwaddr addr, unsigned size) +{ + OcteonPCIHostState *host =3D octeon_pci_host(s); + uint64_t reg =3D OCTEON_PEXP_BASE + (addr & ~7ULL); + uint64_t value; + + if (!octeon_reg_lookup(host->pexp_regs, reg, &value)) { + value =3D 0; + } + + return octeon_read64(value, addr, size); +} + +void octeon_pci_pexp_write(OcteonState *s, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonPCIHostState *host =3D octeon_pci_host(s); + uint64_t reg =3D OCTEON_PEXP_BASE + (addr & ~7ULL); + uint64_t old; + + if (!octeon_reg_lookup(host->pexp_regs, reg, &old)) { + old =3D 0; + } + + octeon_reg_store(host->pexp_regs, reg, + octeon_write64(old, addr, value, size)); +} + static uint64_t octeon_pci_absent(unsigned size) { return size =3D=3D 1 ? 0xff : size =3D=3D 2 ? 0xffff : 0xffffffffU; @@ -256,6 +296,130 @@ static const MemoryRegionOps octeon_pcie_sli_cfg_ops = =3D { }, }; =20 +static uint64_t octeon_pcie_bswap(uint64_t value, unsigned size) +{ + switch (size) { + case 1: + return value; + case 2: + return bswap16(value); + case 4: + return bswap32(value); + case 8: + return bswap64(value); + default: + g_assert_not_reached(); + } +} + +static uint64_t octeon_pcie_mem_subid_reg(hwaddr addr) +{ + unsigned int subid =3D (addr >> 28) & 3; + + return OCTEON_PEXP_BASE + OCTEON_SLI_MEM_ACCESS_SUBID_BASE + + subid * OCTEON_SLI_MEM_ACCESS_SUBID_STRIDE; +} + +static bool octeon_pcie_mem_swap_enabled(OcteonPCIHostState *host, + hwaddr addr, bool write) +{ + uint64_t value; + uint64_t mask =3D write ? OCTEON_SLI_MEM_ACCESS_SUBID_ESW_M : + OCTEON_SLI_MEM_ACCESS_SUBID_ESR_M; + unsigned int shift =3D write ? OCTEON_SLI_MEM_ACCESS_SUBID_ESW_S : + OCTEON_SLI_MEM_ACCESS_SUBID_ESR_S; + + if (!octeon_reg_lookup(host->pexp_regs, + octeon_pcie_mem_subid_reg(addr), &value)) { + return false; + } + + return ((value & mask) >> shift) =3D=3D OCTEON_SLI_MEM_ACCESS_SWAP; +} + +static uint64_t octeon_pcie0_mem_read(void *opaque, hwaddr addr, + unsigned size) +{ + OcteonState *s =3D opaque; + OcteonPCIHostState *host =3D octeon_pci_host(s); + uint64_t value; + + switch (size) { + case 1: + value =3D address_space_ldub(&s->pcie0_mem_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 2: + value =3D address_space_lduw_le(&s->pcie0_mem_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 4: + value =3D address_space_ldl_le(&s->pcie0_mem_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 8: + value =3D address_space_ldq_le(&s->pcie0_mem_as, addr, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + default: + g_assert_not_reached(); + } + + if (TARGET_BIG_ENDIAN && + !octeon_pcie_mem_swap_enabled(host, addr, false)) { + value =3D octeon_pcie_bswap(value, size); + } + + return value; +} + +static void octeon_pcie0_mem_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s =3D opaque; + OcteonPCIHostState *host =3D octeon_pci_host(s); + + if (TARGET_BIG_ENDIAN && + !octeon_pcie_mem_swap_enabled(host, addr, true)) { + value =3D octeon_pcie_bswap(value, size); + } + + switch (size) { + case 1: + address_space_stb(&s->pcie0_mem_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 2: + address_space_stw_le(&s->pcie0_mem_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 4: + address_space_stl_le(&s->pcie0_mem_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + case 8: + address_space_stq_le(&s->pcie0_mem_as, addr, value, + MEMTXATTRS_UNSPECIFIED, NULL); + break; + default: + g_assert_not_reached(); + } +} + +static const MemoryRegionOps octeon_pcie0_mem_ops =3D { + .read =3D octeon_pcie0_mem_read, + .write =3D octeon_pcie0_mem_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + }, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + }, +}; + static int octeon_pci_map_irq(PCIDevice *pci_dev, int irq_num) { return 0; @@ -273,6 +437,9 @@ static void octeon_pci_host_init(Object *obj) host->root_cfg =3D g_hash_table_new_full(octeon_uint64_hash, octeon_uint64_equal, g_free, g_free); + host->pexp_regs =3D g_hash_table_new_full(octeon_uint64_hash, + octeon_uint64_equal, + g_free, g_free); } =20 static void octeon_pci_host_finalize(Object *obj) @@ -280,6 +447,7 @@ static void octeon_pci_host_finalize(Object *obj) OcteonPCIHostState *host =3D OCTEON_PCI_HOST(obj); =20 g_hash_table_destroy(host->root_cfg); + g_hash_table_destroy(host->pexp_regs); } =20 static void octeon_pci_host_class_init(ObjectClass *klass, const void *dat= a) @@ -353,4 +521,10 @@ void octeon_init_pci(OcteonState *s) memory_region_add_subregion(get_system_memory(), OCTEON_PCIE0_IO_BASE, &s->pcie0_io); =20 + address_space_init(&s->pcie0_mem_as, &host->mem, + "octeon.pcie0-mem-as"); + memory_region_init_io(&s->pcie0_mem, NULL, &octeon_pcie0_mem_ops, s, + "octeon.pcie0-mem", OCTEON_PCIE0_MEM_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_PCIE0_MEM_BASE, + &s->pcie0_mem); } --=20 2.55.0 From nobody Mon Sep 7 05:40:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=fail (Bad Signature); dmarc=fail(p=none dis=none) header.from=korins.ky Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788437228884493.6517862212834; Thu, 3 Sep 2026 05:07:08 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x26CW-000399-Vh; Thu, 03 Sep 2026 08:05:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CP-0002xx-Uf for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:46 -0400 Received: from mx1.catap.net ([2a01:4f8:271:125e::2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x26CK-0005L8-OM for qemu-devel@nongnu.org; Thu, 03 Sep 2026 08:05:43 -0400 Received: by mx1.catap.net (OpenSMTPD) with ESMTPSA id 4f02acfc (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 3 Sep 2026 14:05:34 +0200 (CEST) Received: from localhost (matebook.home.arpa [local]) by matebook.home.arpa (OpenSMTPD) with ESMTPA id 8ea342a1; Thu, 3 Sep 2026 14:05:16 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=20240125rsa; cv=none; d=mx.catap.net; b=aQr3Fiw s2MAd5UUb2gC2xzjaH3Z0toUe2q1ug+VfWaLqy8iCFQq4BW2kosrK+ufXKngjS/OPT4Tqv spU+VdeiXEBI3lZcSlPNg6PIk4F8C4HtLOwH8GMqOV3BPg3CJKOsw387EXVrgVoJJRDxxE tzvsByghCP4gj13UehZkuVniH6oYI6sbTVjC1tgSX2ti+Td4UhWLdtXFVZbF4jlpg2HM+J dIAZBK5nPsRk5t8dqqsUDGz7DwdEg6b1ZMFrMwh0znthflryJpGYts35oo/CzOtZZKSCp4 GpHqtABBHYekThi5X25bQqOlu3mKWgKI+n1IAylA+d5kijFtPDIdL9Q== ARC-Message-Signature: i=1; a=rsa-sha256; s=20240125rsa; c=simple/simple; bh=S WGfmNWEzuFLnOvW36cuYNj75rNosivGBrRlNukj2kU=; h=references:in-reply-to: date:subject:cc:to:from:dkim-signature:dkim-signature; d=mx.catap.net; b=GaFJ0uJEryEvFyKn27mWNtzCv+dxzpmVnyQG1QXPSGkTpzAxheJP7k5JTCxAfVt/G7Vm MhOqBuJ54WHgblK3RyyoTd81lvQpy9Mka1PdO1ySIInUnjpy7ByjvZz4g5KyX1KmFzQSnb nefI6uCkzk7OV3P2E8pImSEcwxYEDcW8MM+bdet2NmT/efQTg8+PRQ4c3qpYrTo6Jm2L6n MCOxnqzjFI9P726nykQettlaKsta6iiUUbrr/gS4Cl3gt9Xg5Rln+wm9644MR5kXy/oBbc wujr71fkqwpNeDcbC6HVr05eeF55I1OEcV+lzLie9ode4H79+6OZ/dlsOhgBcdow== ARC-Authentication-Results: i=1; mx.catap.net; dkim=pass header.s=20240125rsa header.d=korins.ky header.a=rsa-sha256 header.b=VqbmbT7D; dkim=pass header.s=20240125ed25519 header.d=korins.ky header.a=ed25519-sha256 header.b=ys35gz7g; arc=none; iprev=pass; spf=none smtp.helo=postmaster@matebook.home.arpa; spf=softfail smtp.mailfrom=kirill@korins.ky DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=20240125rsa; bh=SWGfmNWE zuFLnOvW36cuYNj75rNosivGBrRlNukj2kU=; h=references:in-reply-to:date: subject:cc:to:from; d=korins.ky; b=VqbmbT7DB2E+6g8sKnSqjCR3rcPCjRGd2rq vrSjo8YBMyFqFq0jQbsPc2nFuKVdDLdyBjEGQSbn9FbeikpUSM59r8ZnQdU8q+k+8UXunq zHwY9e9Lb906/2/gbRTNxAtYzEpl4p62rKqGiI5CekNKXJbWZlA3xn+ygF0x/p0dHVhcBk KT9oRFF/T2/0byEIqp+CjcQTaD9Pguu4WP6VPlu1YztsMihiX3L5aOpGfD8Ju46UZmrJRo jcNLeWYgcn4/G7QtEpVIKS/OMgqQvZjtUON5UwxMGAnwbw+RwSfejjZ8pg2oIGYKwK3w4q zOhKYNO8Itdkbjq823HCGXAzJzg== DKIM-Signature: v=1; a=ed25519-sha256; c=simple/simple; s=20240125ed25519; bh=SWGfmNWEzuFLnOvW36cuYNj75rNosivGBrRlNukj2kU=; h=references: in-reply-to:date:subject:cc:to:from; d=korins.ky; b=ys35gz7g+k2vqZO+7a KO4hitxb2TsrCEnqtloa92vxcye+JjJA/29RgZHqmm3DwGM+UZkOy2o9TqocOIKe48Ag== From: "Kirill A. Korinsky" To: Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Michael S. Tsirkin" , Aurelien Jarno , Jiaxun Yang , Aleksandar Rikalo , qemu-devel@nongnu.org Cc: "Kirill A. Korinsky" Subject: [PATCH v2 25/25] tests/functional: test Octeon III boot Date: Thu, 3 Sep 2026 14:02:13 +0200 Message-ID: <20260903120510.34876-26-kirill@korins.ky> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903120510.34876-1-kirill@korins.ky> References: <20260903120510.34876-1-kirill@korins.ky> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2a01:4f8:271:125e::2; envelope-from=kirill@korins.ky; helo=mx1.catap.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: fail (found 2 invalid signatures) X-ZM-MESSAGEID: 1788437230434158500 Content-Type: text/plain; charset="utf-8" Boot the OpenBSD/octeon ramdisk through U-Boot using an e1000 device and QEMU user mode TFTP. Verify PCI enumeration, DHCP, image transfer and entry into the OpenBSD installer. --- tests/functional/mips64/meson.build | 2 + tests/functional/mips64/test_octeon3.py | 54 +++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/functional/mips64/test_octeon3.py diff --git a/tests/functional/mips64/meson.build b/tests/functional/mips64/= meson.build index 3ff2118987..98b7c491a1 100644 --- a/tests/functional/mips64/meson.build +++ b/tests/functional/mips64/meson.build @@ -2,9 +2,11 @@ =20 test_mips64_timeouts =3D { 'malta' : 240, + 'octeon3' : 300, } =20 tests_mips64_system_thorough =3D [ 'malta', + 'octeon3', 'tuxrun', ] diff --git a/tests/functional/mips64/test_octeon3.py b/tests/functional/mip= s64/test_octeon3.py new file mode 100644 index 0000000000..9c2bc67ac4 --- /dev/null +++ b/tests/functional/mips64/test_octeon3.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# +# Functional test for the Cavium Octeon III / EBB7304 machine. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import shutil + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern as ec_and_wait + + +class Octeon3Machine(QemuSystemTest): + + ASSET_UBOOT =3D Asset( + 'https://kirill.korins.ky/pub/qemu-mips64-openbsd/u-boot.bin', + '7e519b2e52ba44b27bfafd16738c8f485e9eda5438b4899cf6a70520a6d34396') + + ASSET_BSD_RD =3D Asset( + 'https://kirill.korins.ky/pub/qemu-mips64-openbsd/bsd.rd', + '907f26f0ff67390dd21dc85e2c854fc0e65db295b15d47ae92e1927f98ac5872') + + def test_openbsd_ramdisk_tftp(self): + self.require_netdev('user') + self.require_device('e1000') + self.set_machine('octeon3') + + tftp_dir =3D self.scratch_file('tftp') + os.mkdir(tftp_dir) + shutil.copy(self.ASSET_BSD_RD.fetch(), + os.path.join(tftp_dir, 'bsd.rd')) + + self.vm.set_console() + self.vm.add_args('-bios', self.ASSET_UBOOT.fetch(), + '-m', '1G', + '-smp', '4', + '-no-reboot', + '-netdev', + f'user,id=3Dnet0,tftp=3D{tftp_dir},bootfile=3Dbsd= .rd', + '-device', 'e1000,netdev=3Dnet0') + self.vm.launch() + + wait_for_console_pattern(self, '=3D> ') + ec_and_wait(self, 'pci enum', '=3D> ') + ec_and_wait(self, 'dhcp', 'Bytes transferred') + wait_for_console_pattern(self, '=3D> ') + ec_and_wait(self, 'bootoctlinux ${loadaddr} numcores=3D4', + 'Welcome to the OpenBSD/octeon 7.9 installation progra= m.') + + +if __name__ =3D=3D '__main__': + QemuSystemTest.main() --=20 2.55.0