From nobody Sat May 30 18:34:29 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1777787984; cv=none; d=zohomail.com; s=zohoarc; b=bO3K5AJxgzw3L09eHkg0Ci6ObqwdE1L1342rzzSIAyfHbgY0YIyFAUfbakctDiHFC8zXpDc4KHQnf+Kebxstku2f+AHSNdmiirbvd8bBAUQ7KF3rer89WpdnmzAyOvR4nbYXgttZ2dAj2oyvWtczlmu3gPdMS0xMBv1cW3hTyTw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777787984; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=UHLoSL7bJ7XP3E/wJcb8DLImZUQfEkLy4reFzKuMpYQ=; b=jya4i2zfDiFx2iCqLdgfDHnNxSA/v742IVbmbIYw+NwnKbrBbmjPDe4SVQNyJ996ZD/NbRZMuhrCDkeBua1Bw5Eja+gKIkNPIZNPLBeDisD7k3S1bypnNDuvG4/+kzMjrrUU1qYrcQNB+zuTYKFlKYJ4xcTSkkq2fUGWxNQTiqo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from=<54weasels@gmail.com> (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777787983938916.9683109137826; Sat, 2 May 2026 22:59:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wJPrC-0001Ci-GY; Sun, 03 May 2026 01:59:10 -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 <54weasels@gmail.com>) id 1wJM67-0004un-Df for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:20 -0400 Received: from mail-dy1-x132b.google.com ([2607:f8b0:4864:20::132b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <54weasels@gmail.com>) id 1wJM64-0000RT-Mw for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:19 -0400 Received: by mail-dy1-x132b.google.com with SMTP id 5a478bee46e88-2bdd40d3c61so3788988eec.1 for ; Sat, 02 May 2026 18:58:15 -0700 (PDT) Received: from newsled.lan ([76.133.142.170]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee38d79eb9sm14361735eec.8.2026.05.02.18.58.12 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 02 May 2026 18:58:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777773494; x=1778378294; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UHLoSL7bJ7XP3E/wJcb8DLImZUQfEkLy4reFzKuMpYQ=; b=lO03dlPb8hwGC28aTGyGYc45CYxyYR9Uoo8RrVzDGqmAXjnRSOGfv9yyVs9/u/BOzS CX3bIbzLMMnlq+QOT0ghHIqYRBOyWTUXjTVCLfefvnyZcRTTc2/tf8dPQB37597n6yqX fiUoJgayXSxlFVtip3AUk/aoACqKqPf1qnh8qaCNpHAUMLDwX8LafNQHHGvsjatEonA/ 7gG8KQrvXdY92wFy+1EqyzHqbboBTs1vrCFcpgiXNZtpgdNGKIknuLtFvo2hiX7qcS/z D0KU8+43EvCHQ0SDTf1dHu0tXHMDEC+9Njc5Gzk+AS6M++lFFmxGnsRplZkbcfgAWee1 T9vg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777773494; x=1778378294; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=UHLoSL7bJ7XP3E/wJcb8DLImZUQfEkLy4reFzKuMpYQ=; b=ClLwyAJoJGuxzkg+rTAzFTeAnlYCyXaUZGbuMBcrLlECjsVIaQHcB9QqjtoZRggRPV 7MCgd88SPSTjtN2Id60lZmuzVFdo3cWKXV1l6x754eGv7R5jd1fi0haFwrvDqkr/sdD8 p2C3mETl288y/DuOZoh1t3ZlfmR4ta2mTe0R7iqMc1EJW9xLN74BcH9kwwrkUPXCJDvI hP3eE5Njj2n/X4KqyhzIfTY2qAs/wBBuxL1e6RXaKL897ESnpKhcJSgVdeF7+UBnKxoH +XgaHrzNfKGhxXFlL9mrPnEJ0+1AuSC377oSz9PuEpn5uj5PuMpoYy6Lf64UVjFNIP4p 4TMw== X-Gm-Message-State: AOJu0YzWJzZ4pE+RnuDBWoqQnoXYK0ofWweJas75bIZJBHHX9EQVkKi5 vC67hpBmQMaPcMJvvRGOmnXwKt6YfaEvVkWYA03PyNF0ni00kjy2PCmkoZQQng== X-Gm-Gg: AeBDievYKsz+6nBBsfjPhhcNVbRHyh+skdg9cVCPPMu7mhuXFYGcLC9683RHcuEqyOI WNaIlRW1VONVAmPPjwrA9bwNTjxmn08ZCW7uCkQLVuPdwLLLgdNVZAqFVfNb41Vd7NMnilLD2UA 3HkbyfD+ey82LoTgFnbDYw/nLnh2yNHm8Osvq9OGMGrGGKcAeAB4cWRg6MvyxG452osUcl6Rf3z 0eNGp8veqTlM1D+q/YTNB4uy/CP6/+iJRjyAaNInXDP6RZmeHMXHZXxI4kGqu3hfjdqntJn1bhY QI0QzC2JHhlanfm3f3wRbkj0qPBV/FOXGNotvC/VE2Uv+cUHUnVnFWfIwk2QuUOneD91DzL26rv qR8R/yv89kr7cFa/kePMfUdbamPNSrFV4GiKDWtjdOnbheMkkz6kHjT3TNFAd9/OrMM2QRjV6DX VR23E3JJ/kjrF9nGI7eayab9AyN5kLgbVVHKpLU+r0OMQLmgpPMg== X-Received: by 2002:a05:693c:3001:b0:2da:2ec2:64e5 with SMTP id 5a478bee46e88-2efbac9a7famr1949610eec.18.1777773493348; Sat, 02 May 2026 18:58:13 -0700 (PDT) From: 54weasels <54weasels@gmail.com> To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, thuth@redhat.com, 54weasels <54weasels@gmail.com> Subject: [PATCH 1/7] target/m68k: Implement Physical Bus Error exception handling Date: Sat, 2 May 2026 18:57:50 -0700 Message-ID: <20260503015756.99176-2-54weasels@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260503015756.99176-1-54weasels@gmail.com> References: <20260503015756.99176-1-54weasels@gmail.com> 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=2607:f8b0:4864:20::132b; envelope-from=54weasels@gmail.com; helo=mail-dy1-x132b.google.com 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 03 May 2026 01:58:55 -0400 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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1777787985091158500 Content-Type: text/plain; charset="utf-8" The M68020 natively maps hardware Bus Error (BERR) timeouts into a Long Bus= Cycle Fault (Format 0xB). This commit adds the memory exception routing to= natively synthesize these EXCP_ACCESS cycle faults. It also implements the= double-fault / watchdog reset behavior required for Sun-3 hardware diagnos= tics, properly handles FSAVE/FRESTORE for 68881 FPU stubs, and properly con= structs the 84-byte internal bus fault frame. Signed-off-by: 54weasels <54weasels@gmail.com> --- target/m68k/cpu.c | 5 +- target/m68k/cpu.h | 18 +++- target/m68k/helper.c | 130 ++++++++++++++++++++++++++++- target/m68k/op_helper.c | 176 ++++++++++++++++++++++++++-------------- target/m68k/translate.c | 31 +++++-- 5 files changed, 283 insertions(+), 77 deletions(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index d849a4a90f..af375f0bce 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * QEMU Motorola 68k CPU * @@ -51,8 +52,8 @@ static TCGTBCPUState m68k_get_tb_cpu_state(CPUState *cs) flags =3D (env->macsr >> 4) & TB_FLAGS_MACSR; if (env->sr & SR_S) { flags |=3D TB_FLAGS_MSR_S; - flags |=3D (env->sfc << (TB_FLAGS_SFC_S_BIT - 2)) & TB_FLAGS_SFC_S; - flags |=3D (env->dfc << (TB_FLAGS_DFC_S_BIT - 2)) & TB_FLAGS_DFC_S; + flags |=3D (env->sfc << TB_FLAGS_SFC_S_BIT) & TB_FLAGS_SFC_S; + flags |=3D (env->dfc << TB_FLAGS_DFC_S_BIT) & TB_FLAGS_DFC_S; } if (M68K_SR_TRACE(env->sr) =3D=3D M68K_SR_TRACE_ANY_INS) { flags |=3D TB_FLAGS_TRACE; diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index 7911ab9de3..426ef6a6e1 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -149,10 +149,18 @@ typedef struct CPUArchState { =20 int pending_vector; int pending_level; + bool nmi_pending; =20 /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; =20 + /* Custom MMU intercept logic, if any (e.g. for Sun-3) */ + void *custom_mmu_opaque; + int (*custom_mmu_get_physical_address)(void *env, hwaddr *physical, + int *prot, vaddr address, + int access_type, + hwaddr *page_size); + /* Fields from here on are preserved across CPU reset. */ uint64_t features; } CPUM68KState; @@ -601,12 +609,14 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr= physaddr, vaddr addr, #define TB_FLAGS_MSR_S_BIT 13 #define TB_FLAGS_MSR_S (1 << TB_FLAGS_MSR_S_BIT) #define TB_FLAGS_SFC_S_BIT 14 -#define TB_FLAGS_SFC_S (1 << TB_FLAGS_SFC_S_BIT) -#define TB_FLAGS_DFC_S_BIT 15 -#define TB_FLAGS_DFC_S (1 << TB_FLAGS_DFC_S_BIT) -#define TB_FLAGS_TRACE 16 +#define TB_FLAGS_SFC_S (7 << TB_FLAGS_SFC_S_BIT) /* 3 Bits reserv= ed */ +#define TB_FLAGS_DFC_S_BIT 17 +#define TB_FLAGS_DFC_S (7 << TB_FLAGS_DFC_S_BIT) /* 3 Bits reserv= ed */ +#define TB_FLAGS_TRACE 20 #define TB_FLAGS_TRACE_BIT (1 << TB_FLAGS_TRACE) =20 +#define MMU_MOVES_FC_BASE 2 /* mmu_idx 2-9 correspond to FC 0-7 */ + void dump_mmu(CPUM68KState *env); =20 #endif diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 9bab184389..997c2616f4 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -28,6 +28,7 @@ #include "system/memory.h" #include "gdbstub/helpers.h" #include "fpu/softfloat.h" +#include "qemu/log.h" #include "qemu/qemu-print.h" =20 #define SIGNBIT (1u << 31) @@ -280,8 +281,10 @@ void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t= reg, uint32_t val) return; } break; - /* Unimplemented Registers */ + /* Dummy implementation for CAAR */ case M68K_CR_CAAR: + return; + /* Unimplemented Registers */ case M68K_CR_PCR: case M68K_CR_BUSCR: cpu_abort(env_cpu(env), @@ -384,8 +387,10 @@ uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, ui= nt32_t reg) return env->mmu.ttr[M68K_DTTR1]; } break; - /* Unimplemented Registers */ + /* Dummy implementation for CAAR */ case M68K_CR_CAAR: + return 0; + /* Unimplemented Registers */ case M68K_CR_PCR: case M68K_CR_BUSCR: cpu_abort(env_cpu(env), "Unimplemented control register read 0x%x\= n", @@ -915,6 +920,21 @@ hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vadd= r addr) int access_type; target_ulong page_size; =20 + access_type =3D ACCESS_DATA | ACCESS_DEBUG; + if (env->sr & SR_S) { + access_type |=3D ACCESS_SUPER; + } + + if (env->custom_mmu_get_physical_address) { + hwaddr custom_page_size; + if (env->custom_mmu_get_physical_address(env, &phys_addr, &prot, a= ddr, + access_type, + &custom_page_size) =3D=3D= 0) { + return phys_addr; + } + return -1; + } + if ((env->mmu.tcr & M68K_TCR_ENABLED) =3D=3D 0) { /* MMU disabled */ return addr; @@ -944,6 +964,12 @@ void m68k_set_irq_level(M68kCPU *cpu, int level, uint8= _t vector) CPUState *cs =3D CPU(cpu); CPUM68KState *env =3D &cpu->env; =20 + if (level =3D=3D 7 && env->pending_level !=3D 7) { + env->nmi_pending =3D true; + } else if (level !=3D 7) { + env->nmi_pending =3D false; + } + env->pending_level =3D level; env->pending_vector =3D vector; if (level) { @@ -964,6 +990,106 @@ bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, i= nt size, int ret; target_ulong page_size; =20 + if (qemu_access_type =3D=3D MMU_INST_FETCH) { + access_type =3D ACCESS_CODE; + } else { + access_type =3D ACCESS_DATA; + if (qemu_access_type =3D=3D MMU_DATA_STORE) { + access_type |=3D ACCESS_STORE; + } + } + + /* Decode explicit Function Codes from moves instructions */ + if (mmu_idx >=3D MMU_MOVES_FC_BASE) { + uint8_t fc =3D mmu_idx - MMU_MOVES_FC_BASE; + access_type |=3D (fc << 8); /* Pack explicit FC into access type */ + if (fc !=3D 1 && fc !=3D 2) { + access_type |=3D ACCESS_SUPER; + } + } else { + /* Standard memory accesses map logically to normal M68K FCs */ + if (mmu_idx =3D=3D MMU_KERNEL_IDX) { + access_type |=3D ACCESS_SUPER; + access_type |=3D ((qemu_access_type =3D=3D MMU_INST_FETCH ? 6 = : 5) << 8); + } else { + access_type |=3D ((qemu_access_type =3D=3D MMU_INST_FETCH ? 2 = : 1) << 8); + } + } + + if (env->custom_mmu_get_physical_address) { + hwaddr custom_page_size; + + /* Delegate translation to external board-specific MMU if register= ed */ + ret =3D env->custom_mmu_get_physical_address(env, &physical, &prot, + address, access_type, + &custom_page_size); + + if (likely(ret =3D=3D 0)) { + tlb_set_page(cs, address & TARGET_PAGE_MASK, + physical & TARGET_PAGE_MASK, prot, + mmu_idx, custom_page_size); + return true; + } + + if (probe) { + return false; + } + + /* page fault */ + cs->exception_index =3D EXCP_ACCESS; + env->mmu.ar =3D address; + + if (m68k_feature(env, M68K_FEATURE_M68040)) { + env->mmu.ssw =3D M68K_ATC_040; + switch (size) { + case 1: + env->mmu.ssw |=3D M68K_BA_SIZE_BYTE; + break; + case 2: + env->mmu.ssw |=3D M68K_BA_SIZE_WORD; + break; + case 4: + env->mmu.ssw |=3D M68K_BA_SIZE_LONG; + break; + } + env->mmu.ssw |=3D M68K_TM_040_DATA; + } else { + /* M68020/030 Special Status Word (SSW) */ + uint16_t ssw =3D 0x0100; /* DF - Data Fault */ + switch (size) { + case 1: + ssw |=3D 0x0010; + break; + case 2: + ssw |=3D 0x0020; + break; + case 3: + ssw |=3D 0x0030; + break; + case 4: + ssw |=3D 0x0000; + break; + } + if (qemu_access_type !=3D MMU_DATA_STORE) { + ssw |=3D 0x0040; /* RW - Read */ + } + /* Function Code */ + uint8_t fc; + if (mmu_idx >=3D MMU_MOVES_FC_BASE) { + fc =3D mmu_idx - MMU_MOVES_FC_BASE; + } else { + if (mmu_idx =3D=3D MMU_KERNEL_IDX) { + fc =3D (qemu_access_type =3D=3D MMU_INST_FETCH) ? 6 : = 5; + } else { + fc =3D (qemu_access_type =3D=3D MMU_INST_FETCH) ? 2 : = 1; + } + } + ssw |=3D (fc & 7); + env->mmu.ssw =3D ssw; + } + cpu_loop_exit_restore(cs, retaddr); + } + if ((env->mmu.tcr & M68K_TCR_ENABLED) =3D=3D 0) { /* MMU disabled */ tlb_set_page(cs, address & TARGET_PAGE_MASK, diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 8148a8852e..84d5270767 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * M68K helper routines * @@ -25,6 +26,7 @@ #include "qemu/plugin.h" =20 #if !defined(CONFIG_USER_ONLY) +#include "system/runstate.h" =20 static void cf_rte(CPUM68KState *env) { @@ -73,6 +75,12 @@ throwaway: case 7: sp +=3D 52; break; + case 0xa: /* Short Bus Cycle Fault (Format 0xA) */ + sp +=3D 32 - 8; /* 32 bytes total - 8 bytes header =3D 24 byte= s */ + break; + case 0xb: /* Long Bus Cycle Fault (Format 0xB) */ + sp +=3D 92 - 8; /* 92 bytes total - 8 bytes header =3D 84 byte= s */ + break; } } env->aregs[7] =3D sp; @@ -342,56 +350,80 @@ static void m68k_interrupt_all(CPUM68KState *env, int= is_hw) switch (cs->exception_index) { case EXCP_ACCESS: if (env->mmu.fault) { - cpu_abort(cs, "DOUBLE MMU FAULT\n"); + qemu_log_mask(LOG_GUEST_ERROR, + "M68K: Double MMU Fault. Halting CPU and request= ing reset.\n"); + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + cs->halted =3D 1; + cs->exception_index =3D EXCP_HLT; + cpu_loop_exit(cs); } env->mmu.fault =3D true; - /* push data 3 */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* push data 2 */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* push data 1 */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 1 / push data 0 */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 1 address */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 2 data */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 2 address */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 3 data */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 3 address */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, env->mmu.ar, MMU_KERNEL_IDX, 0); - /* fault address */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, env->mmu.ar, MMU_KERNEL_IDX, 0); - /* write back 1 status */ - sp -=3D 2; - cpu_stw_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 2 status */ - sp -=3D 2; - cpu_stw_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* write back 3 status */ - sp -=3D 2; - cpu_stw_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); - /* special status word */ - sp -=3D 2; - cpu_stw_be_mmuidx_ra(env, sp, env->mmu.ssw, MMU_KERNEL_IDX, 0); - /* effective address */ - sp -=3D 4; - cpu_stl_be_mmuidx_ra(env, sp, env->mmu.ar, MMU_KERNEL_IDX, 0); - - do_stack_frame(env, &sp, 7, oldsr, 0, env->pc); + + if (m68k_feature(env, M68K_FEATURE_M68040)) { + /* push data 3 */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* push data 2 */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* push data 1 */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 1 / push data 0 */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 1 address */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 2 data */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 2 address */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 3 data */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 3 address */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, env->mmu.ar, MMU_KERNEL_IDX, 0); + /* fault address */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, env->mmu.ar, MMU_KERNEL_IDX, 0); + /* write back 1 status */ + sp -=3D 2; + cpu_stw_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 2 status */ + sp -=3D 2; + cpu_stw_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* write back 3 status */ + sp -=3D 2; + cpu_stw_be_mmuidx_ra(env, sp, 0, MMU_KERNEL_IDX, 0); + /* special status word */ + sp -=3D 2; + cpu_stw_be_mmuidx_ra(env, sp, env->mmu.ssw, MMU_KERNEL_IDX, 0); + /* effective address */ + sp -=3D 4; + cpu_stl_be_mmuidx_ra(env, sp, env->mmu.ar, MMU_KERNEL_IDX, 0); + + do_stack_frame(env, &sp, 7, oldsr, 0, env->pc); + } else { + /* M68020 Long Bus Cycle Fault (Format 0xB) */ + /* + * 84 bytes of internal state are pushed before the generic + * 8-byte header + */ + sp -=3D 84; + for (int i =3D 0; i < 84; i +=3D 4) { + cpu_stl_be_mmuidx_ra(env, sp + i, 0, MMU_KERNEL_IDX, 0); + } + /* Offset 0x02 from internal frame: SSW */ + cpu_stw_be_mmuidx_ra(env, sp + 2, env->mmu.ssw, MMU_KERNEL_IDX= , 0); + /* Offset 0x08 from internal frame: Fault Address */ + cpu_stl_be_mmuidx_ra(env, sp + 8, env->mmu.ar, MMU_KERNEL_IDX,= 0); + + do_stack_frame(env, &sp, 0xb, oldsr, 0, env->pc); + } env->mmu.fault =3D false; if (qemu_loglevel_mask(CPU_LOG_INT)) { qemu_log(" " @@ -437,7 +469,9 @@ static void m68k_interrupt_all(CPUM68KState *env, int i= s_hw) =20 env->aregs[7] =3D sp; /* Jump to vector. */ + env->mmu.fault =3D true; env->pc =3D cpu_ldl_be_mmuidx_ra(env, env->vbr + vector, MMU_KERNEL_ID= X, 0); + env->mmu.fault =3D false; =20 do_plugin_vcpu_interrupt_cb(cs, last_pc); } @@ -509,26 +543,46 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr= physaddr, vaddr addr, if (access_type !=3D MMU_DATA_STORE) { env->mmu.ssw |=3D M68K_RW_040; } - - env->mmu.ar =3D addr; - - cs->exception_index =3D EXCP_ACCESS; - cpu_loop_exit(cs); + } else if (m68k_feature(env, M68K_FEATURE_M68020)) { + /* + * M68020 Long Bus Cycle Fault (Format 0xB). + * The Motorola 68020 hardware intrinsically generates a physical + * Bus Error exception whenever the system bus flags a transaction + * timeout or failure (e.g., attempting to read an unpopulated bus + * address). This natively injects the EXCP_ACCESS cycle to build + * the generic 84-byte exception stack frame. + */ + env->mmu.ssw =3D 0; + if (access_type =3D=3D MMU_INST_FETCH) { + env->mmu.ssw |=3D 0x1000; + } else if (access_type =3D=3D MMU_DATA_STORE) { + env->mmu.ssw |=3D 0x0040; + } else { + env->mmu.ssw |=3D 0x0080; + } + } else { + /* + * Older architectures (e.g. 68000) do not currently support + * hardware-injected transaction failures in QEMU. + */ + return; } + + env->mmu.ar =3D addr; + cs->exception_index =3D EXCP_ACCESS; + cpu_loop_exit(cs); } =20 bool m68k_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { CPUM68KState *env =3D cpu_env(cs); =20 - if (interrupt_request & CPU_INTERRUPT_HARD - && ((env->sr & SR_I) >> SR_I_SHIFT) < env->pending_level) { - /* - * Real hardware gets the interrupt vector via an IACK cycle - * at this point. Current emulated hardware doesn't rely on - * this, so we provide/save the vector when the interrupt is - * first signalled. - */ + if (env->nmi_pending) { + env->nmi_pending =3D false; + cs->exception_index =3D env->pending_vector; + do_interrupt_m68k_hardirq(env); + return true; + } else if (((env->sr & SR_I) >> SR_I_SHIFT) < env->pending_level) { cs->exception_index =3D env->pending_vector; do_interrupt_m68k_hardirq(env); return true; diff --git a/target/m68k/translate.c b/target/m68k/translate.c index abc1c79f3c..d6fcd6c4d9 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * m68k translation * @@ -163,10 +164,12 @@ static void do_writebacks(DisasContext *s) #define IS_USER(s) 1 #else #define IS_USER(s) (!(s->base.tb->flags & TB_FLAGS_MSR_S)) -#define SFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_SFC_S) ? \ - MMU_KERNEL_IDX : MMU_USER_IDX) -#define DFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_DFC_S) ? \ - MMU_KERNEL_IDX : MMU_USER_IDX) +#define SFC_INDEX(s) (MMU_MOVES_FC_BASE + \ + (((s)->base.tb->flags & TB_FLAGS_SFC_S) >> \ + TB_FLAGS_SFC_S_BIT)) +#define DFC_INDEX(s) (MMU_MOVES_FC_BASE + \ + (((s)->base.tb->flags & TB_FLAGS_DFC_S) >> \ + TB_FLAGS_DFC_S_BIT)) #endif =20 typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t in= sn); @@ -5364,11 +5367,19 @@ DISAS_INSN(frestore) gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); return; } - if (m68k_feature(s->env, M68K_FEATURE_M68040)) { + if (m68k_feature(s->env, M68K_FEATURE_M68040) || + m68k_feature(s->env, M68K_FEATURE_FPU)) { SRC_EA(env, addr, OS_LONG, 0, NULL); - /* FIXME: check the state frame */ + if (m68k_feature(s->env, M68K_FEATURE_M68040)) { + /* FIXME: check the state frame */ + } else { + /* + * 68881/68882 FRESTORE: read the state frame + * (NULL frame is 4 bytes) + */ + } } else { - disas_undef(env, s, insn); + disas_undef_fpu(env, s, insn); } } =20 @@ -5383,8 +5394,12 @@ DISAS_INSN(fsave) /* always write IDLE */ TCGv idle =3D tcg_constant_i32(0x41000000); DEST_EA(env, insn, OS_LONG, idle, NULL); + } else if (m68k_feature(s->env, M68K_FEATURE_FPU)) { + /* 68881/68882 FSAVE: always write NULL frame */ + TCGv null_frame =3D tcg_constant_i32(0x00000000); + DEST_EA(env, insn, OS_LONG, null_frame, NULL); } else { - disas_undef(env, s, insn); + disas_undef_fpu(env, s, insn); } } #endif --=20 2.50.1 (Apple Git-155) From nobody Sat May 30 18:34:29 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1777787983; cv=none; d=zohomail.com; s=zohoarc; b=af1Sncv6O4FMFbohXCufe0dOINhsHrjKSjU3sDOZrLHTkScWfRJp7ZMLY4kSjYTKo0dWkGvJ8bT7flEr8Z1AsCfDM5NOiNmPglv6pf+E5NkpQMYlQGiwo52/CULC/onu0gSubso/YMR9lswdqb9Ijfoq97tOjIJKen/q/1wS5bM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777787983; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=kOwNqYRk9+UvfOEov+BJRCxT8ZvnhEczC7nF4l7D9sI=; b=UXRycvcDUPFvYzR0MbA94RcmCC4aVWFIWGr9XXU8ksyys0SvEP3h/IbMUJsa+fuh/G+iS3D43qaMvg2Yj7tqBCqkvbgcoO+HWLgJp1EpVHfFeEx6g8U8bajuc0ZU6hshp4s2PvI5Kfk6z1TKradg53OEp7zhINIerLhEWEsbpkk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from=<54weasels@gmail.com> (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777787983870862.106165137295; Sat, 2 May 2026 22:59:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wJPqz-000162-T8; Sun, 03 May 2026 01:58:58 -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 <54weasels@gmail.com>) id 1wJM68-0004v6-H2 for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:20 -0400 Received: from mail-dy1-x132a.google.com ([2607:f8b0:4864:20::132a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <54weasels@gmail.com>) id 1wJM66-0000Ss-FD for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:20 -0400 Received: by mail-dy1-x132a.google.com with SMTP id 5a478bee46e88-2d868d014a5so3106392eec.1 for ; Sat, 02 May 2026 18:58:18 -0700 (PDT) Received: from newsled.lan ([76.133.142.170]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee38d79eb9sm14361735eec.8.2026.05.02.18.58.16 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 02 May 2026 18:58:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777773497; x=1778378297; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kOwNqYRk9+UvfOEov+BJRCxT8ZvnhEczC7nF4l7D9sI=; b=AW0f4Bw5AkN32VsdvEiq5B34X9VppDUiLjqamRLSYkIvsY0cKjDFngWj/007kxc0eO boIBC8aYIrW79Ywb2vzlJJRFYaUBvaTlRXT5ZOZituSifVNhEKTnMA2dCeWllcmov1la PmXWs7FSDuJbSnwia7cgmFRpgedrvOk/OKtkrwc+lQt+IVPZFiOF850V4VDyz5dK1/Tx z60JykAzgXgyl6ovWKvMsucET2rbRrFGrXCs5HkMevkkqOrzLGz/l4a2iSDmWEi6pLxi KI6J3WINEzWyp4+v9+ZuNIeupglDOz+unC9VPzKATh5v+uzFF1FM4cyEw0TPnBxE7Ldj tAvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777773497; x=1778378297; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=kOwNqYRk9+UvfOEov+BJRCxT8ZvnhEczC7nF4l7D9sI=; b=hFSF4mBLUe1PThE8EdmdMQmtdNVdJgaj558XCbozV8wKb8TEOJAQskGtfWBAptl54Q /oTVULvHVjP9ywfGw3swiyTUbPUAA0kuvZOVbcm0UyhiYku2j73Rf8CGRxvPjjfo9MjM OmrDas9MfItKFonR6ji5D0MT1xr7zu6hVE6T2rC0hKNi8+nlWXKwwhciGKqmEmAFRYaK Tfo7LXIAOkhatXcw/1kkEF0vtFa091iB59oN23NUGKdVBS8iAgVXyT7x4VpX4kXnkYwO WJPoKHhlMRSbNEavjxfRUir9/8HLJsy0QjdStVg6n//Fy1VdtUDmD2dmWQqZ054dEjWT 1FWw== X-Gm-Message-State: AOJu0YyujGyDXWH+dlPfZ6DSEX5cwc/nDo9KUXViRTEgOwx9jXRftvv+ X8paCJuQQ3RImXkHu5FUa9o8knkktLKUi0BM6BBe9Qdd2SJXqD639VfTeUnbTg== X-Gm-Gg: AeBDietIzhtUvufNVOUNKgEbxJ3cT+jGgt8CgpeiivcXAk2Rbnk3GL59boNSykZcFV6 G4psy8xUOIOQgRMkN5zSY8yh4t7Pr80DS8aSfxD09Bp2vmOMXmfA9SvfpWBQU2HGfN3P0zVyeYf 2JnHHZpLmYLsg3BZxvIanLZFaYm3nN72DIhyniIgfQxzLmaSrGrsScxOOATJqQ7sEp81kreETtB EItcNC7cGQW3xxsyJRP9diXPDFoGlu7ode8gNCSIW+mY65hYwekYmXyw9UguHmrJjvEAf0Dv8jd 56XxxKkvdZE74SUGb3FhKbt3FBpPJoE6rvmRAxD7WlK81Us6zaPiEoajSeZ2YF5i+rFR7QeooM1 y869MfUlwmbx9vIvM97H6VLM6+l9DgAC6Atx2r1Bk+xEEBHS7F8YxRL1YsMedoFxmO33hawSY2z ZatXnCkTaK/yqYXAQWMr9cOpuHanY3sZP5rBF+Pk6rvhLe106bPw== X-Received: by 2002:a05:7301:e8f:b0:2ee:d76a:3754 with SMTP id 5a478bee46e88-2efb5024ee0mr2155263eec.0.1777773496681; Sat, 02 May 2026 18:58:16 -0700 (PDT) From: 54weasels <54weasels@gmail.com> To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, thuth@redhat.com, 54weasels <54weasels@gmail.com> Subject: [PATCH 2/7] hw/net/lance: Add Sun-3 Native DMA byte-swapping support Date: Sat, 2 May 2026 18:57:51 -0700 Message-ID: <20260503015756.99176-3-54weasels@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260503015756.99176-1-54weasels@gmail.com> References: <20260503015756.99176-1-54weasels@gmail.com> 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=2607:f8b0:4864:20::132a; envelope-from=54weasels@gmail.com; helo=mail-dy1-x132a.google.com 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 03 May 2026 01:58:52 -0400 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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1777787986367154100 Content-Type: text/plain; charset="utf-8" The Sun-3 hardware physically byte-swaps the D0-D7 and D8-D15 DMA lanes bet= ween the Little-Endian LANCE controller and the Big-Endian Sun-3 memory. Th= is commit intercepts the LANCE DMA reads/writes by injecting a phys_mem ove= rride in pcnet.c specifically for the Sun-3 instance, dynamically neutraliz= ing the hardcoded internal initblk swap and properly mapping the payload pa= yloads. Signed-off-by: 54weasels <54weasels@gmail.com> --- hw/net/lance.c | 111 ++++++++++++++++++++++++++++++++++++++--- hw/net/meson.build | 3 +- include/hw/net/lance.h | 3 ++ 3 files changed, 109 insertions(+), 8 deletions(-) diff --git a/hw/net/lance.c b/hw/net/lance.c index 5d5bf9b961..93944fb35d 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * QEMU AMD PC-Net II (Am79C970A) emulation * @@ -22,7 +23,8 @@ * THE SOFTWARE. */ =20 -/* This software was written to be compatible with the specification: +/* + * This software was written to be compatible with the specification: * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 */ @@ -44,8 +46,73 @@ #include "hw/core/qdev-properties.h" #include "trace.h" #include "system/system.h" +#include "system/address-spaces.h" +#include "system/dma.h" + +/* + * LANCE Native DMA Read Hook + * + * Sun-3 Hardware intrinsically byte-swaps the D0-D7 and D8-D15 DMA lanes + * between the Little-Endian LANCE controller and the Big-Endian Sun-3 mem= ory. + * We MUST model this manually. pcnet.c passes CSR_BSWP(s) for payloads + * (correctly bypassing the swap if LANCE internally neutralizes it). + * However, pcnet.c hardcodes do_bswap=3D1 for the `initblk` structure + * (len 24/28). + * We dynamically intercept the `initblk` fetch by cross-referencing CSR_I= ADR to + * enforce the hardware swap reliably. Because this branch is only taken w= hen + * `dma_mr` is explicitly provided by the machine, this quirk is safely is= olated + * to the Sun-3 and does not impact SPARC (which uses `ledma`). + */ +static void lance_dma_read(void *dma_opaque, hwaddr addr, + uint8_t *buf, int len, int do_bswap) +{ + SysBusPCNetState *d =3D SYSBUS_PCNET(dma_opaque); + PCNetState *s =3D &d->state; + + dma_memory_read(&d->dma_as, addr, buf, len, MEMTXATTRS_UNSPECIFIED); + + uint32_t bcr_ssize32 =3D (s->bcr[20] & 0x0100); + hwaddr iadr =3D (s->csr[1] | ((uint32_t)s->csr[2] << 16)); + if (!bcr_ssize32) { + iadr |=3D ((0xff00 & (uint32_t)s->csr[2]) << 16); + } =20 + int internal_bswap =3D do_bswap; + if (addr =3D=3D iadr && (len =3D=3D 24 || len =3D=3D 28)) { + internal_bswap =3D 0; /* Force hardware swap natively for initblk = */ + } =20 + if (!internal_bswap) { + for (int i =3D 0; i < (len & ~1); i +=3D 2) { + uint8_t tmp =3D buf[i]; + buf[i] =3D buf[i + 1]; + buf[i + 1] =3D tmp; + } + } +} + +/* LANCE Native DMA Write Hook */ +static void lance_dma_write(void *dma_opaque, hwaddr addr, + uint8_t *buf, int len, int do_bswap) +{ + SysBusPCNetState *s =3D SYSBUS_PCNET(dma_opaque); + + if (!do_bswap) { + uint8_t *swapped_buf =3D g_malloc(len); + for (int i =3D 0; i < (len & ~1); i +=3D 2) { + swapped_buf[i] =3D buf[i + 1]; + swapped_buf[i + 1] =3D buf[i]; + } + if (len & 1) { + swapped_buf[len - 1] =3D buf[len - 1]; + } + dma_memory_write(&s->dma_as, addr, swapped_buf, len, + MEMTXATTRS_UNSPECIFIED); + g_free(swapped_buf); + } else { + dma_memory_write(&s->dma_as, addr, buf, len, MEMTXATTRS_UNSPECIFIE= D); + } +} static void parent_lance_reset(void *opaque, int irq, int level) { SysBusPCNetState *d =3D opaque; @@ -59,7 +126,15 @@ static void lance_mem_write(void *opaque, hwaddr addr, SysBusPCNetState *d =3D opaque; =20 trace_lance_mem_writew(addr, val & 0xffff); - pcnet_ioport_writew(&d->state, addr, val & 0xffff); + if (size =3D=3D 1) { + uint16_t orig =3D pcnet_ioport_readw(&d->state, addr & ~1); + if (addr & 1) { /* LSB in Big Endian */ + val =3D (orig & 0xff00) | (val & 0xff); + } else { /* MSB in Big Endian */ + val =3D (orig & 0x00ff) | ((val & 0xff) << 8); + } + } + pcnet_ioport_writew(&d->state, addr & ~1, val & 0xffff); } =20 static uint64_t lance_mem_read(void *opaque, hwaddr addr, @@ -68,18 +143,28 @@ static uint64_t lance_mem_read(void *opaque, hwaddr ad= dr, SysBusPCNetState *d =3D opaque; uint32_t val; =20 - val =3D pcnet_ioport_readw(&d->state, addr); - trace_lance_mem_readw(addr, val & 0xffff); + val =3D pcnet_ioport_readw(&d->state, addr & ~1); + if (size =3D=3D 1) { + if (addr & 1) { + val =3D val & 0xff; + } else { + val =3D (val >> 8) & 0xff; + } + } return val & 0xffff; } =20 static const MemoryRegionOps lance_mem_ops =3D { .read =3D lance_mem_read, .write =3D lance_mem_write, - .endianness =3D DEVICE_NATIVE_ENDIAN, + .endianness =3D DEVICE_BIG_ENDIAN, .valid =3D { - .min_access_size =3D 2, - .max_access_size =3D 2, + .min_access_size =3D 1, + .max_access_size =3D 4, + }, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, }, }; =20 @@ -115,8 +200,18 @@ static void lance_realize(DeviceState *dev, Error **er= rp) =20 sysbus_init_irq(sbd, &s->irq); =20 + if (d->dma_mr) { + address_space_init(&d->dma_as, d->dma_mr, "lance-dma"); + s->phys_mem_read =3D lance_dma_read; + s->phys_mem_write =3D lance_dma_write; + s->dma_opaque =3D DEVICE(d); + } else { +#if defined(TARGET_SPARC) s->phys_mem_read =3D ledma_memory_read; s->phys_mem_write =3D ledma_memory_write; +#endif + } + pcnet_common_init(dev, s, &net_lance_info); } =20 @@ -140,6 +235,8 @@ static void lance_instance_init(Object *obj) static const Property lance_properties[] =3D { DEFINE_PROP_LINK("dma", SysBusPCNetState, state.dma_opaque, TYPE_DEVICE, DeviceState *), + DEFINE_PROP_LINK("dma_mr", SysBusPCNetState, dma_mr, + TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf), }; =20 diff --git a/hw/net/meson.build b/hw/net/meson.build index 3102587469..e653a9bc73 100644 --- a/hw/net/meson.build +++ b/hw/net/meson.build @@ -31,7 +31,8 @@ system_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: fi= les('mv88w8618_eth.c')) =20 system_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_gem.c')) system_ss.add(when: 'CONFIG_STELLARIS_ENET', if_true: files('stellaris_ene= t.c')) -system_ss.add(when: 'CONFIG_LANCE', if_true: files('lance.c')) +# LANCE uses target-specific memory types (e.g., target_ulong) and must be= compiled per-target. +specific_ss.add(when: 'CONFIG_LANCE', if_true: files('lance.c')) system_ss.add(when: 'CONFIG_LASI_82596', if_true: files('lasi_i82596.c')) system_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c')) system_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c')) diff --git a/include/hw/net/lance.h b/include/hw/net/lance.h index be473e2eed..706160d7eb 100644 --- a/include/hw/net/lance.h +++ b/include/hw/net/lance.h @@ -31,6 +31,7 @@ =20 #include "net/net.h" #include "hw/net/pcnet.h" +#include "system/memory.h" #include "hw/core/sysbus.h" #include "qom/object.h" =20 @@ -43,6 +44,8 @@ struct SysBusPCNetState { SysBusDevice parent_obj; =20 PCNetState state; + MemoryRegion *dma_mr; + AddressSpace dma_as; }; =20 #endif --=20 2.50.1 (Apple Git-155) From nobody Sat May 30 18:34:29 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1777788003; cv=none; d=zohomail.com; s=zohoarc; b=CK2Ray0AOPZ8wfvgBn66m8HmH3PM3dL6Zv9Ln10BG0gqN6TWfmmt0Yk8/YpZrxPakRkXLWAn4bBH4sV2UlM6hW1gMMyurvPzk81/vPrCgQavOD1vD/yKzWlpXcAdprQ3dG6f7X7pktTcW8SQpmInKRPEZ5SuTMexB3DeC2BOrzY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777788003; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=I2TKKB6U+GwReeGYv3aDJklJVz+rIvoLzCBt6yji+TY=; b=Yx7glum4eN8Y4WlSSUg4N5BfxVBFPf5FpVAf566TjVrzhcrzSp6YS5/UQdVcTKW6AHIzFcE5mpYwuG8GqE6Kuu0BbyzLoMVhQ9xgAavMO+Fcw6vnOUeTTqdw7uDxLQtqoNtjfwawS7QEzjlTPr6q1hxTmJFTdY/GK9F7zLXUcSs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from=<54weasels@gmail.com> (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777788003493276.9359091410887; Sat, 2 May 2026 23:00:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wJPr8-0001Aj-A6; Sun, 03 May 2026 01:59:06 -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 <54weasels@gmail.com>) id 1wJM69-0004vX-Ug for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:21 -0400 Received: from mail-dy1-x132f.google.com ([2607:f8b0:4864:20::132f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <54weasels@gmail.com>) id 1wJM68-0000T9-73 for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:21 -0400 Received: by mail-dy1-x132f.google.com with SMTP id 5a478bee46e88-2ef38cf04f0so1238998eec.1 for ; Sat, 02 May 2026 18:58:19 -0700 (PDT) Received: from newsled.lan ([76.133.142.170]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee38d79eb9sm14361735eec.8.2026.05.02.18.58.17 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 02 May 2026 18:58:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777773498; x=1778378298; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=I2TKKB6U+GwReeGYv3aDJklJVz+rIvoLzCBt6yji+TY=; b=c+Xkx3SUPuXTGiPWc8Vy6wJ5wTTfizWEpl2Ui89X56k3dj0KF0ybSNUiKeigVQFDr0 ODUZwU1rFh60eHXM/JL677yhhvr9AvHDYFhUsxOjUDGVSOXqZJtskipXjfQWpjirTKEp w4Moof7G6IeIZAhbhYnN3RXCbpeJ0VTBRpGA1j/m5q/8JoTUSNM8Olu74KcSNHp9WA2p zRVnmA7YZ0gSCSqDymwYJZB2X/cWpxw6t0fM1QmxYxnHiyGVP8faStuT8AmkIakHsZy8 nzMuRtn46ChP83hRK0H/xkquIngAs7UbPRZSOWgMBbHMUV58ZPSUg05TLmhQzaAH6RZv 2Bbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777773498; x=1778378298; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=I2TKKB6U+GwReeGYv3aDJklJVz+rIvoLzCBt6yji+TY=; b=gBAbbioAJSpnB6Anb1YSmYl4CEeN/QSQGMH3YhsQ+GWuMlXGhoMiEzLCJ5lpeHZ/jO nlBnS8ADDC/qSYcfw9IDiiKo1DANYYpse0cPGSXN4kyGW/5zT2WJf6fR4NiHXtt/HRVb 5spMfX+3QgCI7BB+KsF+xV53Y2OCuW6MjFQXZd+zwiLOVAWJQNicPCB7NNkUsAFsKel/ FJsqUp1UE/UFLWc3hE66SYTjOpQOTZLBds8/Cf/Tns89NcXrzKcjWruyBxpdtpcww6wH 7T1YsAg+NmQ8zUOwptTJBZQyALzR1tz5k/rYm0F+o/4QMZVH9u3/ZvndtdZBDP9qkWxW sjZQ== X-Gm-Message-State: AOJu0Yy2HUPOVbP7KbbNW50UPGZ597zL6onjiGay6jOtkXhzIi5nnGWF mcPyDfXOoh+UhzXD24bxU0L1o3af3Y9umnvwxP3ZEOXp7acCkGq63sn4/CM9Xg== X-Gm-Gg: AeBDieu1dXANmLtFP3b7GiIXNaF55tT0g1UXw5nRwvng8C0BswHrAplNXbMXAlQUzh+ QdEHxkV9ue4nhun6P8MTpE2gxlKHe3bZou6Mbsr8R8DYEFaYd2LVzzvkfWegWePwuGOmXNoCoz+ Db3TnLyOTaI5aNvuM3Nx7GkfvPeri/rSkGH1dEQVovCr454oNpGQxwxQRJcAH5nxMzrBpL1kD+9 NdnkdxuWstC8WIhLDKG72XKFLcxYGdt89pv3VTjbsfLH6bGDSeOi56QmB7KH9VNKVmMhF2ZRaZ/ q+874VIf0U0RSMELw/6KUhKOsKqxWEX4w4n3Okij/Ju2nI9+1MzaPsD4restRwnW3qMVAFoLZEk ImW4Nd/kRREq+GZ75uXA1En1uXUwGmDiItdzlIkYN2sq+u/E1PLJ+1BSAIwSySnnW1Xwxjl7sAO LEoAWbv6zJUHjDXmzm03uC7ls1oONVEaTy/56C+tuc5V/3DT1eKg== X-Received: by 2002:a05:7300:fd0a:b0:2dd:6937:79b8 with SMTP id 5a478bee46e88-2efb7dcacd4mr2400101eec.5.1777773498418; Sat, 02 May 2026 18:58:18 -0700 (PDT) From: 54weasels <54weasels@gmail.com> To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, thuth@redhat.com, 54weasels <54weasels@gmail.com> Subject: [PATCH 3/7] hw/char/escc: Expose diagnostic RS232 I/O routing Date: Sat, 2 May 2026 18:57:52 -0700 Message-ID: <20260503015756.99176-4-54weasels@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260503015756.99176-1-54weasels@gmail.com> References: <20260503015756.99176-1-54weasels@gmail.com> 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=2607:f8b0:4864:20::132f; envelope-from=54weasels@gmail.com; helo=mail-dy1-x132f.google.com 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 03 May 2026 01:59:00 -0400 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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1777788004409154100 Content-Type: text/plain; charset="utf-8" This adds proper initialization and routing hooks for the ESCC serial contr= oller to support the specific diagnostic RS232 UART mappings expected by th= e Sun-3 Boot PROM. Signed-off-by: 54weasels <54weasels@gmail.com> --- hw/char/escc.c | 33 ++++++++++++++++++++++++--------- include/hw/char/escc.h | 3 +++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/hw/char/escc.c b/hw/char/escc.c index 3b46818ecc..d870806a35 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -313,7 +313,8 @@ static void escc_soft_reset_chn(ESCCChannelState *s) =20 s->rregs[R_STATUS] &=3D STATUS_DCD | STATUS_SYNC | STATUS_CTS | STATUS= _BRK; s->rregs[R_STATUS] |=3D STATUS_TXEMPTY | STATUS_TXUNDRN; - if (s->disabled) { + if (s->disabled || s->parent->force_hw_ready) { + /* Force assert to satisfy Sun-3 PROM Flow Control */ s->rregs[R_STATUS] |=3D STATUS_DCD | STATUS_SYNC | STATUS_CTS; } s->rregs[R_SPEC] &=3D SPEC_ALLSENT; @@ -653,7 +654,8 @@ static void escc_mem_write(void *opaque, hwaddr addr, s->txint =3D 0; escc_update_irq(s); s->tx =3D val; - if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { /* tx enabled */ + if (s->parent->force_hw_ready || (s->wregs[W_TXCTRL2] & TXCTRL2_TX= EN)) { + /* tx consistently forced enabled for Sun-3 boot PROM hooks */ if (s->wregs[W_MISC2] & MISC2_LCL_LOOP) { serial_receive_byte(s, s->tx); } else if (qemu_chr_fe_backend_connected(&s->chr)) { @@ -691,6 +693,12 @@ static uint64_t escc_mem_read(void *opaque, hwaddr add= r, case SERIAL_CTRL: trace_escc_mem_readb_ctrl(CHN_C(s), s->reg, s->rregs[s->reg]); ret =3D s->rregs[s->reg]; + if (s->reg =3D=3D R_STATUS) { + if (serial->force_hw_ready) { + ret |=3D STATUS_DCD | STATUS_SYNC | STATUS_CTS; + /* Force Flow Control PINs */ + } + } s->reg =3D 0; return ret; case SERIAL_DATA: @@ -715,6 +723,10 @@ static const MemoryRegionOps escc_mem_ops =3D { .write =3D escc_mem_write, .endianness =3D DEVICE_NATIVE_ENDIAN, .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, + .impl =3D { .min_access_size =3D 1, .max_access_size =3D 1, }, @@ -1067,16 +1079,17 @@ static void escc_realize(DeviceState *dev, Error **= errp) s->chn[0].disabled =3D s->disabled; s->chn[1].disabled =3D s->disabled; =20 + uint32_t escc_size =3D s->mmio_size ? s->mmio_size :\ + (ESCC_SIZE << s->it_shift); memory_region_init_io(&s->mmio, OBJECT(dev), &escc_mem_ops, s, "escc", - ESCC_SIZE << s->it_shift); + escc_size); =20 for (i =3D 0; i < 2; i++) { - if (qemu_chr_fe_backend_connected(&s->chn[i].chr)) { - s->chn[i].clock =3D s->frequency / 2; - qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive, - serial_receive1, serial_event, NULL, - &s->chn[i], NULL, true); - } + s->chn[i].parent =3D s; + s->chn[i].clock =3D s->frequency / 2; + qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive, + serial_receive1, serial_event, NULL, + &s->chn[i], NULL, true); } =20 if (s->chn[0].type =3D=3D escc_mouse) { @@ -1093,7 +1106,9 @@ static const Property escc_properties[] =3D { DEFINE_PROP_UINT32("frequency", ESCCState, frequency, 0), DEFINE_PROP_UINT32("it_shift", ESCCState, it_shift, 0), DEFINE_PROP_BOOL("bit_swap", ESCCState, bit_swap, false), + DEFINE_PROP_BOOL("force-hw-ready", ESCCState, force_hw_ready, false), DEFINE_PROP_UINT32("disabled", ESCCState, disabled, 0), + DEFINE_PROP_UINT32("mmio_size", ESCCState, mmio_size, 0), DEFINE_PROP_UINT32("chnBtype", ESCCState, chn[0].type, 0), DEFINE_PROP_UINT32("chnAtype", ESCCState, chn[1].type, 0), DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr), diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h index 9e60175b77..db4700d8e4 100644 --- a/include/hw/char/escc.h +++ b/include/hw/char/escc.h @@ -49,6 +49,7 @@ typedef struct ESCCChannelState { int sunmouse_dx; int sunmouse_dy; int sunmouse_buttons; + ESCCState *parent; } ESCCChannelState; =20 struct ESCCState { @@ -57,9 +58,11 @@ struct ESCCState { struct ESCCChannelState chn[2]; uint32_t it_shift; bool bit_swap; + bool force_hw_ready; MemoryRegion mmio; uint32_t disabled; uint32_t frequency; + uint32_t mmio_size; }; =20 #endif --=20 2.50.1 (Apple Git-155) From nobody Sat May 30 18:34:29 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1777787985; cv=none; d=zohomail.com; s=zohoarc; b=aHavufxXSuMzEI6VysOkyQ2qdRWsKDzR0LsA+cL67UqLXkO8UB3WOl495vaORtv8PjEUaqI0xilMJverjwPkr10BMMJgX27dNyICtUDn9rJbL2uMto67gIBnKSzUphgqdTPUPeeTh4W1Qdmq53ycxuWXYZtQRBxO9SHDYxveXU4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777787985; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=O85A+8mTtk4dus5AdYbZBy3FLqoryx7HTG4VFhPinZ8=; b=EN7okz0bULnI48xP+xNx33FZlEmN2+kE0TJktR58PHJKRAFADgHzfQsoXBqSNakFib2IG2ZMhe+83Wj/8LKRM9ZgHXQ7HW7K5vO+j2QIeLmlBIjvMOKu0J2j/n0GHqs4QCICNBSK/gzm1duQQp2HRrmqA8CnVdN+HIhteZvmzaE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from=<54weasels@gmail.com> (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777787985800906.4187019863148; Sat, 2 May 2026 22:59:45 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wJPrE-0001Dk-Sl; Sun, 03 May 2026 01:59:13 -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 <54weasels@gmail.com>) id 1wJM6B-0004vn-Vj for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:24 -0400 Received: from mail-dy1-x1334.google.com ([2607:f8b0:4864:20::1334]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <54weasels@gmail.com>) id 1wJM6A-0000U3-0b for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:23 -0400 Received: by mail-dy1-x1334.google.com with SMTP id 5a478bee46e88-2ecf9e398f4so6483088eec.1 for ; Sat, 02 May 2026 18:58:21 -0700 (PDT) Received: from newsled.lan ([76.133.142.170]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee38d79eb9sm14361735eec.8.2026.05.02.18.58.19 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 02 May 2026 18:58:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777773500; x=1778378300; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=O85A+8mTtk4dus5AdYbZBy3FLqoryx7HTG4VFhPinZ8=; b=MSREn1KA9YlfJJMXx8WERucqsq66ryQwJVXdIOL0PJ7SNPigg6y6/uAznqjP9VIhzl pnI/djsEcWPfiVfTR0/2J1nNoyB0WVHlRMuSC4n4YTJJiPAmXQ7HhPpuLoZ1f9cibUil Of37Qtw6EvqfHcUAS2suaa97A+JwxEAclf6g86svEr5p16bvsPSxZc5ht90ksZzjLsEb wAJ8z/FpEz3A2e3Svt/1NT0wUKKwxAPjZ1BJXXglDe9Pji5lmA9YuyssUX/OG15Uv2f6 MfVfaEwCXl1yJbgDCYIFgI3N+dLdbptEmFYQxw2dskpdSsHCegznC39mh8PWQKsFf6nB vUQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777773500; x=1778378300; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=O85A+8mTtk4dus5AdYbZBy3FLqoryx7HTG4VFhPinZ8=; b=CwUdfoN/LAa1Ta7hwEZ+Bdgo6a2K1POEYcBlPgG/Gc8kTESqcwzJgehgiW/UWGh4Ch AiD840hpis/5AgyvRUiE2xZeuAQ/YYVjpzcRqq+YqBxhILXJzKOPub/aBe0H+8bUDrYi 8JKsr/8G0Cp1Jji9O2OVq5cmDTbrFpiSrI85IHSWcFZ4Sl9VN6g90ojmFOb6CauQALkT IStrzGQdn3jZRPXumfQaR3/iYIHP139/6KwF3DKyb1dp9yzwuZGewJx+5nUelGkxvfre Xp2IBOyVlxzQxkK/FJ74S6M3muAWhe2mX5gXNT20zJZmnTo5IJ+vpQ7B7P4rNid/GXtV lEWw== X-Gm-Message-State: AOJu0YyyUMMwcQ5Qf/f+zHgVrp86J/lt6PZm6cgkjnI+2iCJR3ADkKap C+J+FqyoJ8QlpwPJQQ8Iz6GhApXZ5/+i09oNcpDjnPOMvytwG633jSTRghD6ew== X-Gm-Gg: AeBDievFrsN8PGs6gQFxpg5QWemHCwD5RwmwZvcA+W6SuOolezJk4vR/phx6y1YEQx2 OkAb+2Qu9bjbJWaom7RGrl7Sh7W5N2FdFvE05yl9u+EKG5IHqtoU3feMSY3bYh6UIANlNjRMkj+ ugKf1PREO45hl9vxy9X1Ou4vlLnV4JeB1oLqGbQIzeAT7XQbW6Aazrvn/Ey0Fv39TJkd7rX1slB iyzhF+aFkoOYGIxho4C8MEgNXSC4BAP9ED3NSmh2d79IKwVc0p1DhkozzgSCATwcDEacckv2l4A 1ZooXdDpQ12jN0m8oVNOcwnMmMOYDijtztG8mWiSbdF89IXC3oUqlAaQmAHm90wfZKSuiD5nb/8 AaaQW6H21vBixoeIcftb4wOHELI0UcSTTQTJ6MoBh3UgqNWBIDgSKJTA1g8A1hVNQ8UZ3GGUUyq OZW5x5cXaICEZAyBWkX6oLZUWpOMqntvDFxBkKxb/WueTSf9OF+Q== X-Received: by 2002:a05:7301:9f06:b0:2be:142f:d499 with SMTP id 5a478bee46e88-2efb99a10e1mr2273410eec.16.1777773499981; Sat, 02 May 2026 18:58:19 -0700 (PDT) From: 54weasels <54weasels@gmail.com> To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, thuth@redhat.com, 54weasels <54weasels@gmail.com> Subject: [PATCH 4/7] hw/timer: Introduce Intersil 7170 RTC implementation Date: Sat, 2 May 2026 18:57:53 -0700 Message-ID: <20260503015756.99176-5-54weasels@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260503015756.99176-1-54weasels@gmail.com> References: <20260503015756.99176-1-54weasels@gmail.com> 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=2607:f8b0:4864:20::1334; envelope-from=54weasels@gmail.com; helo=mail-dy1-x1334.google.com 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 03 May 2026 01:59:06 -0400 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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1777787986754158500 Content-Type: text/plain; charset="utf-8" This adds the Intersil 7170 Time-of-Day clock / CMOS RAM chip. It implement= s the register map, alarm interrupt logic, and persistent 32-byte battery-b= acked NVRAM used by the Sun-3 architecture for storing the MAC address, EEP= ROM checksums, and boot parameters. Signed-off-by: 54weasels <54weasels@gmail.com> --- hw/timer/Kconfig | 3 + hw/timer/intersil7170.c | 216 ++++++++++++++++++++++++++++++++ hw/timer/meson.build | 1 + include/hw/timer/intersil7170.h | 9 ++ 4 files changed, 229 insertions(+) create mode 100644 hw/timer/intersil7170.c create mode 100644 include/hw/timer/intersil7170.h diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index b3d823ce2c..a828273b6c 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -65,3 +65,6 @@ config STELLARIS_GPTM =20 config AVR_TIMER16 bool + +config INTERSIL7170 + bool diff --git a/hw/timer/intersil7170.c b/hw/timer/intersil7170.c new file mode 100644 index 0000000000..138151fdc1 --- /dev/null +++ b/hw/timer/intersil7170.c @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU Intersil 7170 Real Time Clock and Timer Emulation + * + * This device mimics the core functionality of the Intersil 7170 RTC, + * specifically targeting the 1/100th second periodic interrupt requested + * by the Sun-3 Boot PROM diagnostic routines. + */ + +#include "qemu/osdep.h" + +#include "hw/timer/intersil7170.h" +#include "hw/core/irq.h" +#include "hw/core/qdev.h" +#include "hw/core/sysbus.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qom/object.h" + +OBJECT_DECLARE_SIMPLE_TYPE(Intersil7170State, INTERSIL_7170) + +struct Intersil7170State { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + QEMUTimer *timer; + + /* Registers */ + uint8_t int_status; /* 0x10 */ + uint8_t int_mask; + uint8_t command; /* 0x11 */ +}; + +#define REG_INT 0x10 +#define REG_CMD 0x11 + +/* Interrupt Register bits */ +#define RTC_INT_PENDING 0x80 +#define RTC_INT_DAY 0x40 +#define RTC_INT_HOUR 0x20 +#define RTC_INT_MIN 0x10 +#define RTC_INT_SEC 0x08 +#define RTC_INT_TSEC 0x04 +#define RTC_INT_HSEC 0x02 +#define RTC_INT_ALARM 0x01 + +/* Command Register bits */ +#define RTC_CMD_INTENA 0x10 +#define RTC_CMD_RUN 0x08 + +static void intersil7170_update_irq(Intersil7170State *s) +{ + bool level =3D (s->int_status & s->int_mask) && (s->command & RTC_CMD_= INTENA); + + if (level) { + s->int_status |=3D RTC_INT_PENDING; + } else { + s->int_status &=3D ~RTC_INT_PENDING; + } + + qemu_set_irq(s->irq, level); +} + +static void intersil7170_timer_cb(void *opaque) +{ + Intersil7170State *s =3D opaque; + + if (!(s->command & RTC_CMD_RUN)) { + return; + } + + /* + * Timer fired. Set pending bit based on what is unmasked. + * The Sun-3 PROM primarily demands the Hundredth-Second + * (RTC_INT_HSEC) tick. + */ + if (s->int_mask & RTC_INT_HSEC) { + s->int_status |=3D RTC_INT_HSEC; + intersil7170_update_irq(s); + + /* Reschedule for 1/100th of a second (10,000,000 ns) */ + timer_mod(s->timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 10000000); + } +} + +static uint64_t intersil7170_read(void *opaque, hwaddr addr, unsigned size) +{ + Intersil7170State *s =3D opaque; + uint32_t val =3D 0; + + switch (addr) { + case REG_INT: + val =3D s->int_status; + /* + * Reading the interrupt register formally clears all + * pending interrupts. + */ + s->int_status =3D 0; + intersil7170_update_irq(s); + break; + case REG_CMD: + val =3D s->command; + break; + default: + val =3D 0; + break; + } + + return val; +} + +static void intersil7170_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Intersil7170State *s =3D opaque; + + switch (addr) { + case REG_INT: + /* + * Writing to the INT register sets the mask! + * Pending flag is read-only. + */ + s->int_mask =3D val & ~RTC_INT_PENDING; + intersil7170_update_irq(s); + + /* If timer requires starting, schedule immediately */ + if ((s->command & RTC_CMD_RUN) && (s->int_mask & RTC_INT_HSEC)) { + timer_mod(s->timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 10000000); + } + break; + case REG_CMD: + s->command =3D val; + intersil7170_update_irq(s); + + if ((s->command & RTC_CMD_RUN) && (s->int_mask & RTC_INT_HSEC)) { + timer_mod(s->timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 10000000); + } else if (!(s->command & RTC_CMD_RUN)) { + timer_del(s->timer); + } + break; + default: + break; + } +} + +static const MemoryRegionOps intersil7170_ops =3D { + .read =3D intersil7170_read, + .write =3D intersil7170_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + .unaligned =3D true, + }, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + .unaligned =3D true, + }, +}; + +static void intersil7170_realize(DeviceState *dev, Error **errp) +{ + Intersil7170State *s =3D INTERSIL_7170(OBJECT(dev)); + + s->timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, intersil7170_timer_cb, s= ); +} + +static void intersil7170_reset(DeviceState *dev) +{ + Intersil7170State *s =3D INTERSIL_7170(OBJECT(dev)); + + s->int_status =3D 0; + s->int_mask =3D 0; + s->command =3D 0; + timer_del(s->timer); +} + +static void intersil7170_init(Object *obj) +{ + Intersil7170State *s =3D INTERSIL_7170(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &intersil7170_ops, s, "intersil7= 170", + 8192); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); +} + +static void intersil7170_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D intersil7170_realize; + device_class_set_legacy_reset(dc, intersil7170_reset); +} + +static const TypeInfo intersil7170_info =3D { + .name =3D TYPE_INTERSIL_7170, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(Intersil7170State), + .instance_init =3D intersil7170_init, + .class_init =3D intersil7170_class_init, +}; + +static void intersil7170_register_types(void) +{ + type_register_static(&intersil7170_info); +} + +type_init(intersil7170_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 178321c029..72f33ec31f 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -15,6 +15,7 @@ system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exy= nos4210_pwm.c')) system_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_gptimer.c')) system_ss.add(when: 'CONFIG_HPET_C', if_true: files('hpet.c')) system_ss.add(when: 'CONFIG_I8254', if_true: files('i8254_common.c', 'i825= 4.c')) +system_ss.add(when: 'CONFIG_INTERSIL7170', if_true: files('intersil7170.c'= )) system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_epit.c')) system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpt.c')) system_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gictimer.c')) diff --git a/include/hw/timer/intersil7170.h b/include/hw/timer/intersil717= 0.h new file mode 100644 index 0000000000..cab42b4cc0 --- /dev/null +++ b/include/hw/timer/intersil7170.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef HW_TIMER_INTERSIL7170_H +#define HW_TIMER_INTERSIL7170_H + +#define TYPE_INTERSIL_7170 "intersil7170" + +typedef struct Intersil7170State Intersil7170State; + +#endif --=20 2.50.1 (Apple Git-155) From nobody Sat May 30 18:34:29 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1777787994; cv=none; d=zohomail.com; s=zohoarc; b=FGwoFwATjj5WGRlsjHyNohu59oOOmTCs6WN8iXsgkBAUN/ll+KTN7xWszGs+WxJuCtpX5jhuxDyHL08scr4kHzDHI6aE2kxXu3I9xpeyZNFpOlMzt4PgN5LBNZStbJdzqdPyAzXQo9VXhR52/1Yl8/tfM0dHcPobTtBTRQUXRMs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777787994; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=8bxTylT5zdHOxeOuQ+JQtXcO2yUlfuze6HxbUoeHOzw=; b=IDuBKe9q/NWx2G3oWFJXLyXdEMa0QS0eBUUPQuUFgaMZSv3W6CQ2WVuGDpQomB76v6DFgwMNaOte6lpG/PCgmZExEjJZe6r1YuuR3VKdgrWjahkI5o6xXI84lSAD1ARjMGkTzN5bcP2cXTgx4k+io4/6/0z2H4NGiTuaBw63XbY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from=<54weasels@gmail.com> (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777787994338888.7734264340713; Sat, 2 May 2026 22:59:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wJPrM-0001GV-VY; Sun, 03 May 2026 01:59:21 -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 <54weasels@gmail.com>) id 1wJM6H-0004x9-0Z for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:29 -0400 Received: from mail-dl1-x1234.google.com ([2607:f8b0:4864:20::1234]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <54weasels@gmail.com>) id 1wJM6C-0000Ye-BO for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:28 -0400 Received: by mail-dl1-x1234.google.com with SMTP id a92af1059eb24-12dbd0f7ecaso6827179c88.0 for ; Sat, 02 May 2026 18:58:23 -0700 (PDT) Received: from newsled.lan ([76.133.142.170]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee38d79eb9sm14361735eec.8.2026.05.02.18.58.20 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 02 May 2026 18:58:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777773503; x=1778378303; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8bxTylT5zdHOxeOuQ+JQtXcO2yUlfuze6HxbUoeHOzw=; b=R2NcN/kwpqEJHSe2KmvaTsPNTRYb5GH7JOt5zF+dr9HEWfbFwAl0ixNfO4clI+iiqC VYgRJD6k1Z0qkksTnO0cWZWKNt8QnVf8/4MInDYHLpxBqt5o6Di1Pcf6mNitAGof9t0N yi85kHqfEthbXyA6y0QxSAF34RxDlShXXflBdRCBaPNCJCQuT/URG01875s0V/SfCoCD A7aiTbVBRkws25SK6MenjRGz5XF0UwUf/eQ57S/YAOqaV4eeUqRVrLoRzc5glUeZrHid unRgFQuXQ+4gNRNgamxZLFPwqwiPUP2SACT/JaQPSh4gh4/Gc3JZEaEiDBJFigQ4CbRH qWAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777773503; x=1778378303; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=8bxTylT5zdHOxeOuQ+JQtXcO2yUlfuze6HxbUoeHOzw=; b=epkwBLyZFGxByfvLAisG9su9iNFS2+D0ayoAtRult7OcDKLoweQaT+rl2n/qsPp3gc +GyNRGC7Qx9I00azikdwlvn5a7lVH6juu0UmcJWktVKEpdU9l0ZM6IaSzXfI2lkp+5TV i4kSePFi/TsIUy2G8H6GldcCqUwrpAZU1/xky6re8AA0W2HXaM9C1BrkcZs9gRGbhJaA cCnh+IPkPAcn2oSPezinsTQlC5GlFbG8i+QRhmfQ9UqVfqxiCdkq4e/a9sa/0+ot07ch JhCmhltjWmS/Fv6Q1SSJcWWZPVt8ZIo8t0GqEogJvpq5ZrlTWwisHEgQTE9FO67Nap0j zIhA== X-Gm-Message-State: AOJu0Yw2mv7A4oGGME+PouRrDNCV/U1xWZNqseepqSxWIM65l1oUrUaq x09CbkoTGhwsDzo2wQ07Qv/2ROCLIGUaGC/RgNpWi8kqCMJo5yN+RDE9mr8Mww== X-Gm-Gg: AeBDiesqPvIPQnqaMX7IsWPFl4Sliw6Oq30VKKzxMdKhNhhl+4LdOs6QohbvvmsMtOS ZHsDFFNF3RXxKOO8mQV1Afw9dAQAAWZhH2MSC45ufmHA0UY4h14ZNlSrpt5+cFkKunz5GeXK42h NCsHFg/ba++9T/xDeROGKx9XBntYsA4cC3Ch5IHwmNtnAooVhFm92ZBd8sV3/s9EQAAtQ90LLZR wqvw840312GtLVEArh6oNOooFdBvdaFo0sCnt6Gnf9hoKcbQg/8hYQfw0cmyknh34UwHdfaC/0x sfdyWyNORlEPr5m/45tsnXktSSArMKriLosq0CM7yUwIrju2O9S+K9BHXZXd6oqjOQvACKix/6f Bpd0ecT7KbGebLNjj0jnHBc3bLUTZ3wQvHcE4RM2B7d/MK15npeGGcpkqhJVBiO7gACUh8TPils sm9h0HNcOoS1IRd2DSFTD5KjJa8dxMCV7sWPonwZPrQxHlOLf8WcTfgbr28RgW X-Received: by 2002:a05:7022:401:b0:12d:b3f8:60e7 with SMTP id a92af1059eb24-12dfd85ed7fmr2551232c88.34.1777773501751; Sat, 02 May 2026 18:58:21 -0700 (PDT) From: 54weasels <54weasels@gmail.com> To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, thuth@redhat.com, 54weasels <54weasels@gmail.com> Subject: [PATCH 5/7] hw/m68k: Overhaul Sun-3 MMU and Boot PROM mapping Date: Sat, 2 May 2026 18:57:54 -0700 Message-ID: <20260503015756.99176-6-54weasels@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260503015756.99176-1-54weasels@gmail.com> References: <20260503015756.99176-1-54weasels@gmail.com> 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=2607:f8b0:4864:20::1234; envelope-from=54weasels@gmail.com; helo=mail-dl1-x1234.google.com 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 03 May 2026 01:59:18 -0400 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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1777787996345154100 Content-Type: text/plain; charset="utf-8" This heavily refactors the Sun-3 machine initialization to support its prop= rietary Custom MMU implementation, which replaces the standard Motorola 688= 51 MMU. It maps the diagnostic EEPROM, sets the correct 28-bit address bus = masks, implements the OBIO aliasing rules for the Boot PROM, and connects t= he newly added LANCE, ESCC, and Intersil 7170 peripherals. Signed-off-by: 54weasels <54weasels@gmail.com> --- hw/m68k/Kconfig | 8 + hw/m68k/meson.build | 1 + hw/m68k/sun3.c | 499 ++++++++++++++++++++++++++ hw/m68k/sun3_eeprom_data.h | 259 ++++++++++++++ hw/m68k/sun3mmu.c | 705 +++++++++++++++++++++++++++++++++++++ include/hw/m68k/sun3mmu.h | 65 ++++ 6 files changed, 1537 insertions(+) create mode 100644 hw/m68k/sun3.c create mode 100644 hw/m68k/sun3_eeprom_data.h create mode 100644 hw/m68k/sun3mmu.c create mode 100644 include/hw/m68k/sun3mmu.h diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index aff769b30f..59b36c75ee 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -46,3 +46,11 @@ config M68K_VIRT select GOLDFISH_TTY select GOLDFISH_RTC select VIRTIO_MMIO + +config SUN3 + bool + default y + depends on M68K + select ESCC + select LANCE + select INTERSIL7170 diff --git a/hw/m68k/meson.build b/hw/m68k/meson.build index 84bc68fa4e..c8b07d81fb 100644 --- a/hw/m68k/meson.build +++ b/hw/m68k/meson.build @@ -3,6 +3,7 @@ m68k_ss.add(when: 'CONFIG_AN5206', if_true: files('an5206.c= ', 'mcf5206.c')) m68k_ss.add(when: 'CONFIG_MCF5208', if_true: files('mcf5208.c', 'mcf_intc.= c')) m68k_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-kbd.c', 'next-cu= be.c')) m68k_ss.add(when: 'CONFIG_Q800', if_true: files('q800.c', 'q800-glue.c')) +m68k_ss.add(when: 'CONFIG_SUN3', if_true: files('sun3.c', 'sun3mmu.c')) m68k_ss.add(when: 'CONFIG_M68K_VIRT', if_true: files('virt.c')) =20 hw_arch +=3D {'m68k': m68k_ss} diff --git a/hw/m68k/sun3.c b/hw/m68k/sun3.c new file mode 100644 index 0000000000..16ad8b063d --- /dev/null +++ b/hw/m68k/sun3.c @@ -0,0 +1,499 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU Sun-3 Board Emulation + * + * Copyright (c) 2026 + */ + +#include "qemu/osdep.h" + +#include "chardev/char.h" +#include "hw/char/escc.h" +#include "hw/core/boards.h" +#include "hw/core/irq.h" +#include "hw/core/loader.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/sysbus.h" +#include "hw/net/lance.h" +#include "hw/intc/m68k_irqc.h" +#include "hw/m68k/sun3mmu.h" +#include "hw/timer/intersil7170.h" +#include "qapi/error.h" +#include "system/qtest.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/units.h" +#include "sun3_eeprom_data.h" +#include "system/address-spaces.h" +#include "system/reset.h" +#include "system/system.h" +#include "target/m68k/cpu.h" +#include "qom/object.h" + +#define SUN3_PROM_BASE 0x0FEF0000 +#define SUN3_PROM_SIZE (64 * 1024) + +#define TYPE_SUN3_MACHINE MACHINE_TYPE_NAME("sun3") +OBJECT_DECLARE_SIMPLE_TYPE(Sun3MachineState, SUN3_MACHINE) + +struct Sun3MachineState { + MachineState parent_obj; + + /* Embedded Memory Regions */ + MemoryRegion rom; + MemoryRegion rom_alias; + MemoryRegion idprom; + MemoryRegion intreg_iomem; + MemoryRegion memerr_iomem; + MemoryRegion eeprom; + MemoryRegion nvram; + MemoryRegion timeout_net; + + /* Devices */ + DeviceState *irqc_dev; + DeviceState *sun3mmu; + + /* Boot State */ + uint32_t boot_sp; + uint32_t boot_pc; + + /* Interrupt Register State */ + uint8_t intreg; + bool clock_pending; + + /* Memory Error Register (Parity Spoof) State */ + uint8_t memerr_reg; + uint8_t spoof_parity_lane; + uint8_t parity_bit_counter; + bool test_parity_written; +}; + +static void sun3_update_clock_irq(Sun3MachineState *s) +{ + if (!s->irqc_dev) { + return; + } + + /* Lower everything first */ + qemu_irq_lower(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_5)); + qemu_irq_lower(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_7)); + + /* Assert the currently enabled level if the clock is pulsing */ + if (s->clock_pending && (s->intreg & 0x01)) { + if (s->intreg & 0x20) { + qemu_irq_raise(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_5= )); + } else if (s->intreg & 0x80) { + qemu_irq_raise(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_7= )); + } + } +} + +static void sun3_clock_irq_handler(void *opaque, int n, int level) +{ + Sun3MachineState *s =3D SUN3_MACHINE(opaque); + s->clock_pending =3D !!level; + sun3_update_clock_irq(s); +} + +static uint64_t sun3_intreg_read(void *opaque, hwaddr addr, unsigned size) +{ + Sun3MachineState *s =3D SUN3_MACHINE(opaque); + return s->intreg; +} + +static void sun3_intreg_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Sun3MachineState *s =3D SUN3_MACHINE(opaque); + s->intreg =3D val; + + qemu_log_mask( + LOG_GUEST_ERROR, + "[SUN3 INTREG] Write: 0x%02x (Enable=3D%d, L1=3D%d, L2=3D%d, L3=3D= %d)\n", + (uint8_t)val, !!(val & 0x01), !!(val & 0x02), !!(val & 0x04), + !!(val & 0x08)); + + if ((val & 0x01) =3D=3D 0) { + /* Master Interrupt Enable is CLEAR. Mask everything! */ + qemu_set_irq(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_1), 0); + qemu_set_irq(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_2), 0); + qemu_set_irq(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_3), 0); + sun3_update_clock_irq(s); + return; + } + + /* Master Enable is SET. Fire the Soft Interrupts! */ + qemu_set_irq(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_1), + !!(val & 0x02)); + qemu_set_irq(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_2), + !!(val & 0x04)); + qemu_set_irq(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_3), + !!(val & 0x08)); + + /* + * Retrigger clock IRQs because the Master Enable or Local Enables mig= ht + * have changed + */ + sun3_update_clock_irq(s); +} + +static const MemoryRegionOps sun3_intreg_ops =3D {.read =3D sun3_intreg_re= ad, + .write =3D sun3_intreg_wri= te, + .endianness =3D + DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + } }; + +static uint64_t sun3_memerr_read(void *opaque, hwaddr addr, unsigned size) +{ + Sun3MachineState *s =3D SUN3_MACHINE(opaque); + return s->memerr_reg; +} + +static void sun3_memerr_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Sun3MachineState *s =3D SUN3_MACHINE(opaque); + + if (addr =3D=3D 4) { + s->memerr_reg &=3D ~0x80; + if (s->irqc_dev) { + qemu_irq_lower(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_7= )); + } + return; + } + + s->memerr_reg =3D val & 0xFF; + if (val =3D=3D 0x20) { + s->test_parity_written =3D true; + } else if (val =3D=3D 0) { + s->test_parity_written =3D false; + } + + if (s->irqc_dev) { + if ((val & 0x10) && (val & 0x40) && s->test_parity_written) { + s->memerr_reg |=3D + 0x80 | s->spoof_parity_lane; /* active & spoofed bit lane = */ + s->parity_bit_counter++; + if (s->parity_bit_counter =3D=3D 8) { + s->parity_bit_counter =3D 0; + s->spoof_parity_lane >>=3D 1; + if (s->spoof_parity_lane =3D=3D 0) { + s->spoof_parity_lane =3D 8; + } + } + + qemu_irq_raise(qdev_get_gpio_in( + s->irqc_dev, M68K_IRQC_LEVEL_7)); /* M68K_IRQC_LEVEL_7 */ + } else { + s->memerr_reg &=3D ~0x80; + qemu_irq_lower(qdev_get_gpio_in(s->irqc_dev, M68K_IRQC_LEVEL_7= )); + } + } +} + +static const MemoryRegionOps sun3_memerr_ops =3D { + .read =3D sun3_memerr_read, + .write =3D sun3_memerr_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + .unaligned =3D true, + }, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + .unaligned =3D true, + }, +}; + +static MemTxResult sun3_timeout_read_with_attrs(void *opaque, hwaddr addr, + uint64_t *data, unsigned s= ize, + MemTxAttrs attrs) +{ + Sun3MMUState *mmu =3D SUN3_MMU(opaque); + mmu->buserr_reg |=3D 0x20; /* Timeout */ + return MEMTX_ERROR; +} + +static MemTxResult sun3_timeout_write_with_attrs(void *opaque, hwaddr addr, + uint64_t val, unsigned si= ze, + MemTxAttrs attrs) +{ + Sun3MMUState *mmu =3D SUN3_MMU(opaque); + mmu->buserr_reg |=3D 0x20; /* Timeout */ + return MEMTX_ERROR; +} + +static const MemoryRegionOps sun3_timeout_ops =3D { + .read_with_attrs =3D sun3_timeout_read_with_attrs, + .write_with_attrs =3D sun3_timeout_write_with_attrs, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static void sun3_cpu_reset(void *opaque) +{ + M68kCPU *cpu =3D opaque; + CPUState *cs =3D CPU(cpu); + CPUM68KState *env =3D cpu_env(cs); + Sun3MachineState *s =3D SUN3_MACHINE(current_machine); + + /* + * Execute generic QEMU system reset (wipes everything to 0). + * This includes setting env->pc =3D 0 and env->aregs[7] =3D 0. + */ + cpu_reset(cs); + + /* + * Forcefully inject the Boot PROM SP/PC vectors on EVERY reset. + * The Sun-3 hardware uses a temporary MMU override to map the PROM to + * 0x00000000 during the first few cycles of reset. Since QEMU does not + * emulate this specific micro-architectural quirk, we must manually + * restore the vectors here to prevent the CPU from executing uninitia= lized + * RAM at 0x00000000 and getting stuck in a zero-pitch orib loop. + */ + env->aregs[7] =3D s->boot_sp; + env->sp[0] =3D s->boot_sp; /* M68K_SSP (Master) */ + env->sp[1] =3D s->boot_sp; /* M68K_USP (User) */ + env->sp[2] =3D s->boot_sp; /* M68K_ISP (Interrupt) */ + env->pc =3D s->boot_pc; +} + +static void sun3_init(MachineState *machine) +{ + Sun3MachineState *s_mach =3D SUN3_MACHINE(machine); + M68kCPU *cpu; + CPUM68KState *env; + DeviceState *sun3mmu; + DeviceState *dev; + DeviceState *irqc_dev; + SysBusDevice *s; + + /* Initialize defaults */ + s_mach->memerr_reg =3D 0x40; + s_mach->spoof_parity_lane =3D 8; + s_mach->parity_bit_counter =3D 0; + s_mach->test_parity_written =3D false; + s_mach->intreg =3D 0; + s_mach->clock_pending =3D false; + + /* Initialize the CPU. The Sun 3/60 uses a 68020. */ + cpu =3D M68K_CPU(cpu_create(machine->cpu_type)); + env =3D &cpu->env; + qemu_register_reset(sun3_cpu_reset, cpu); + + /* Use automatically allocated main RAM */ + memory_region_add_subregion(get_system_memory(), 0x00000000, machine->= ram); + + /* Allocate and map ROM as writable RAM! */ + memory_region_init_ram(&s_mach->rom, NULL, "sun3.prom", + SUN3_PROM_SIZE, &error_fatal); + memory_region_set_readonly(&s_mach->rom, false); + memory_region_add_subregion(get_system_memory(), SUN3_PROM_BASE, + &s_mach->rom); + + memory_region_init_alias(&s_mach->rom_alias, NULL, "sun3.prom.alias", + &s_mach->rom, 0, + SUN3_PROM_SIZE); + memory_region_add_subregion(get_system_memory(), 0x0FF00000, + &s_mach->rom_alias); + + const char *bios_name =3D machine->firmware ?: "sun3.prom"; + if (bios_name) { + int load_size =3D load_image_targphys(bios_name, SUN3_PROM_BASE, + SUN3_PROM_SIZE, + qtest_enabled() ? NULL : &error_fatal); + if (load_size < 0) { + if (!qtest_enabled()) { + error_report("sun3: could not load prom '%s'", bios_name); + exit(1); + } + } + error_report("Sun3 Init: Loaded %d bytes from '%s' at 0x%08x", + load_size, + bios_name, SUN3_PROM_BASE); + + /* Initial PC is always at offset 4 in firmware binaries */ + uint8_t *ptr =3D rom_ptr(SUN3_PROM_BASE, 8); + if (ptr) { + s_mach->boot_sp =3D ldl_be_p(ptr); + s_mach->boot_pc =3D ldl_be_p(ptr + 4); + error_report("Sun3 Init: Saved Firmware Vectors " + "SP=3D0x%08x PC=3D0x%08x", + s_mach->boot_sp, s_mach->boot_pc); + } + } else { + error_report( + "Sun3 Init: No firmware specified! Use -bios or -machine firmw= are=3D"); + } + + /* Set up the custom Sun-3 MMU */ + sun3mmu =3D qdev_new(TYPE_SUN3_MMU); + s_mach->sun3mmu =3D sun3mmu; + s =3D SYS_BUS_DEVICE(sun3mmu); + sysbus_realize_and_unref(s, &error_fatal); + + /* Intercept CPU memory translations with our custom MMU hook */ + env->custom_mmu_opaque =3D sun3mmu; + env->custom_mmu_get_physical_address =3D sun3mmu_get_physical_address; + + sysbus_mmio_map(s, 0, 0x80000000); /* Context Register */ + sysbus_mmio_map(s, 1, 0x90000000); /* Segment Map */ + sysbus_mmio_map(s, 2, 0xA0000000); /* Page Map */ + sysbus_mmio_map(s, 3, 0xB0000000); /* Control / System Enable */ + sysbus_mmio_map(s, 4, 0xC0000000); /* Bus Error Register */ + + memory_region_init_ram(&s_mach->idprom, NULL, "sun3.idprom", 8192, + &error_fatal); + memory_region_add_subregion(get_system_memory(), 0x08000000, + &s_mach->idprom); + + uint8_t idprom_data[32] =3D { + 0x01, /* Format: 1 */ + 0x17, /* Machine Type: Sun-3/60 (0x1= 7) */ + 0x08, 0x00, 0x20, 0x00, 0x00, 0x01, /* MAC Address */ + 0x00, 0x00, 0x00, 0x00, /* Date */ + 0x00, 0x00, 0x01, /* Serial */ + 0x00 /* Checksum */ + }; + uint8_t chksum =3D 0; + for (int i =3D 0; i < 15; i++) { + chksum ^=3D idprom_data[i]; + } + idprom_data[15] =3D chksum; + + rom_add_blob_fixed("sun3.idprom_content", idprom_data, sizeof(idprom_d= ata), + 0x08000000); + + /* + * Set up the Interrupt Controller (IRQC) to route IRQs to + * CPU autovectors + */ + irqc_dev =3D qdev_new(TYPE_M68K_IRQC); + object_property_set_link(OBJECT(irqc_dev), "m68k-cpu", OBJECT(cpu), + &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(irqc_dev), &error_fatal); + s_mach->irqc_dev =3D irqc_dev; + + dev =3D qdev_new(TYPE_INTERSIL_7170); + s =3D SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, 0x0FE60000); + sysbus_connect_irq(s, 0, + qemu_allocate_irq(sun3_clock_irq_handler, s_mach, 0= )); + + dev =3D qdev_new(TYPE_ESCC); + qdev_prop_set_bit(dev, "force-hw-ready", true); + qdev_prop_set_uint32(dev, "disabled", 0); + qdev_prop_set_uint32(dev, "frequency", 4915200); /* 4.9152 MHz */ + qdev_prop_set_uint32(dev, "it_shift", 1); + qdev_prop_set_bit(dev, "bit_swap", false); /* Control/Data interleavin= g */ + qdev_prop_set_uint32(dev, "mmio_size", 8192); + qdev_prop_set_chr(dev, "chrB", serial_hd(0)); /* Keyboard/Mouse A */ + qdev_prop_set_chr(dev, "chrA", serial_hd(1)); /* Keyboard/Mouse B */ + qdev_prop_set_uint32(dev, "chnBtype", escc_serial); + qdev_prop_set_uint32(dev, "chnAtype", escc_serial); + s =3D SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, 0x0FE00000); + sysbus_connect_irq(s, 0, + qdev_get_gpio_in(irqc_dev, M68K_IRQC_LEVEL_6)); + /* IPL 6 */ + sysbus_connect_irq(s, 1, + qdev_get_gpio_in(irqc_dev, M68K_IRQC_LEVEL_6)); + /* IPL 6 */ + + dev =3D qdev_new(TYPE_ESCC); + qdev_prop_set_bit(dev, "force-hw-ready", true); + qdev_prop_set_uint32(dev, "disabled", 0); + qdev_prop_set_uint32(dev, "frequency", 4915200); /* 4.9152 MHz */ + qdev_prop_set_uint32(dev, "it_shift", 1); + qdev_prop_set_bit(dev, "bit_swap", false); /* Control/Data interleavin= g */ + qdev_prop_set_uint32(dev, "mmio_size", 8192); + qdev_prop_set_chr(dev, "chrB", serial_hd(2)); /* Serial B */ + qdev_prop_set_chr(dev, "chrA", serial_hd(3)); /* Serial A */ + qdev_prop_set_uint32(dev, "chnBtype", escc_serial); + qdev_prop_set_uint32(dev, "chnAtype", escc_serial); + s =3D SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, 0x0FE20000); + sysbus_connect_irq(s, 0, + qdev_get_gpio_in(irqc_dev, M68K_IRQC_LEVEL_6)); + /* IPL 6 */ + sysbus_connect_irq(s, 1, + qdev_get_gpio_in(irqc_dev, M68K_IRQC_LEVEL_6)); + /* IPL 6 */ + + memory_region_init_io(&s_mach->intreg_iomem, NULL, &sun3_intreg_ops, s= _mach, + "sun3.intreg", 8192); + memory_region_add_subregion(get_system_memory(), 0x0FEA0000, + &s_mach->intreg_iomem); + + memory_region_init_io(&s_mach->memerr_iomem, NULL, &sun3_memerr_ops, s= _mach, + "sun3.memerr", 32); + memory_region_add_subregion(get_system_memory(), 0x0FE80000, + &s_mach->memerr_iomem); + + dev =3D qdev_new("lance"); + qemu_configure_nic_device(dev, true, NULL); + object_property_set_link(OBJECT(dev), "dma_mr", + OBJECT(&SUN3_MMU(sun3mmu)->dvma_iommu), + &error_abort); + s =3D SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, 0x0FF20000); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(irqc_dev, M68K_IRQC_LEVEL_3)= ); + + memory_region_init_ram(&s_mach->eeprom, NULL, "sun3.eeprom", 2048, + &error_fatal); + memory_region_add_subregion(get_system_memory(), 0x0FE40000, + &s_mach->eeprom); + memcpy(memory_region_get_ram_ptr(&s_mach->eeprom), sun3_eeprom_blob, + sizeof(sun3_eeprom_blob)); + + memory_region_init_ram(&s_mach->nvram, NULL, "sun3.nvram", 8192, + &error_fatal); + memory_region_add_subregion(get_system_memory(), 0x0FE50000, + &s_mach->nvram); + + memory_region_init_io(&s_mach->timeout_net, NULL, &sun3_timeout_ops, + sun3mmu, + "sun3.timeout", 0x06000000); + memory_region_add_subregion_overlap(get_system_memory(), 0x0A000000, + &s_mach->timeout_net, -10); +} + +static void sun3_machine_class_init(ObjectClass *oc, const void *data) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "Sun-3 (3/60)"; + mc->init =3D sun3_init; + mc->default_cpu_type =3D M68K_CPU_TYPE_NAME("m68020"); + /* Minimum of 4MB for a 3/60, typical maximum ~24MB */ + mc->default_ram_size =3D 4 * MiB; + mc->default_ram_id =3D "sun3.ram"; + + mc->ignore_memory_transaction_failures =3D false; +} + +static const TypeInfo sun3_machine_type =3D { + .name =3D TYPE_SUN3_MACHINE, + .parent =3D TYPE_MACHINE, + .class_init =3D sun3_machine_class_init, + .instance_size =3D sizeof(Sun3MachineState), +}; + +static void sun3_machine_register_types(void) +{ + type_register_static(&sun3_machine_type); +} + +type_init(sun3_machine_register_types) diff --git a/hw/m68k/sun3_eeprom_data.h b/hw/m68k/sun3_eeprom_data.h new file mode 100644 index 0000000000..fbe3a84d6d --- /dev/null +++ b/hw/m68k/sun3_eeprom_data.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +static const uint8_t sun3_eeprom_blob[2048] =3D { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, + 0x00, 0x3c, 0x00, 0x00, 0xc4, 0xc4, 0xc4, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, + 0x12, 0x73, 0x64, 0x00, 0x08, 0x00, 0x03, 0x12, + 0x12, 0x00, 0x73, 0x64, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, + 0x74, 0x6f, 0x20, 0x53, 0x2f, 0x57, 0x20, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x4c, 0x4d, 0x53, 0x32, 0x20, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x0a, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x01, 0x01, + 0x02, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, +}; diff --git a/hw/m68k/sun3mmu.c b/hw/m68k/sun3mmu.c new file mode 100644 index 0000000000..a0192b5677 --- /dev/null +++ b/hw/m68k/sun3mmu.c @@ -0,0 +1,705 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU Sun-3 MMU Model + * + * Copyright (c) 2026 + */ +#include "qemu/osdep.h" + +#include "exec/cputlb.h" +#include "hw/core/boards.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/sysbus.h" +#include "hw/m68k/sun3mmu.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "system/runstate.h" +#include "target/m68k/cpu.h" +#include "system/address-spaces.h" + +#define SUN3_MMU_CONTEXT(addr) ((addr >> 28) & 0x7) + +static uint64_t sun3_mmu_context_read(void *opaque, hwaddr addr, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + return s->context_reg; +} + +static void sun3_mmu_context_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + s->context_reg =3D val & 0x7; + tlb_flush(CPU(first_cpu)); +} + +static const MemoryRegionOps sun3_mmu_context_ops =3D { + .read =3D sun3_mmu_context_read, + .write =3D sun3_mmu_context_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static uint64_t sun3_mmu_segment_read(void *opaque, hwaddr addr, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + uint32_t ctx =3D s->context_reg & (SUN3_MMU_CONTEXTS - 1); + /* + * The Segment Map index is determined by bits 17..27 of the virtual a= ddress + */ + uint16_t seg_index =3D (addr >> 17) & 0x7FF; + uint32_t index =3D (ctx << 11) | seg_index; + return s->segment_map[index]; +} + +static void sun3_mmu_segment_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + uint32_t ctx =3D s->context_reg & (SUN3_MMU_CONTEXTS - 1); + /* + * The Segment Map index is determined by bits 17..27 of the virtual a= ddress + */ + uint16_t seg_index =3D (addr >> 17) & 0x7FF; + s->segment_map[(ctx * SUN3_MMU_SEGMENTS_PER_CONTEXT) + seg_index] =3D + val & 0xFF; + tlb_flush(CPU(first_cpu)); +} + +static const MemoryRegionOps sun3_mmu_segment_ops =3D { + .read =3D sun3_mmu_segment_read, + .write =3D sun3_mmu_segment_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static uint64_t sun3_mmu_page_read(void *opaque, hwaddr addr, unsigned siz= e) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + uint32_t ctx =3D s->context_reg & (SUN3_MMU_CONTEXTS - 1); + + /* + * The Page Map address offset contains the virtual segment AND page + * index. + */ + uint16_t vtr_seg =3D (addr >> 17) & 0x7FF; + uint16_t vtr_page =3D (addr >> 13) & 0xF; + uint32_t pmeg =3D s->segment_map[(ctx << 11) | vtr_seg]; + uint32_t index =3D (pmeg << 4) | vtr_page; + return s->page_map[index]; +} + +static void sun3_mmu_page_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + uint32_t ctx =3D s->context_reg & (SUN3_MMU_CONTEXTS - 1); + + uint16_t vtr_seg =3D (addr >> 17) & 0x7FF; + uint16_t vtr_page =3D (addr >> 13) & 0xF; + uint32_t pmeg =3D s->segment_map[(ctx << 11) | vtr_seg]; + uint32_t index =3D (pmeg << 4) | vtr_page; + + if (size =3D=3D 4) { + s->page_map[index] =3D val; + } else if (size =3D=3D 2) { + uint32_t shift =3D (addr & 2) ? 0 : 16; + s->page_map[index] =3D (s->page_map[index] & ~(0xFFFF << shift)) | + ((val & 0xFFFF) << shift); + } else if (size =3D=3D 1) { + uint32_t shift =3D (3 - (addr & 3)) * 8; + s->page_map[index] =3D (s->page_map[index] & ~(0xFF << shift)) | + ((val & 0xFF) << shift); + } + + tlb_flush(CPU(first_cpu)); +} + +static const MemoryRegionOps sun3_mmu_page_ops =3D { + .read =3D sun3_mmu_page_read, + .write =3D sun3_mmu_page_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static uint64_t sun3_mmu_control_read(void *opaque, hwaddr addr, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + /* The region covers multiple 32-bit mapped registers now */ + if (addr =3D=3D 0x0) { + /* + * The hardware diagnostic switch on the Sun-3 CPU board is checked + * here. Setting bit 0 to 1 forces the extended memory test. + */ + return s->enable_reg | 0x01; + } + + /* Diagnostic LEDs */ + if (addr =3D=3D 0x30000000) { + return 0xFF; /* Typically inverted, 0xFF means all off */ + } + + qemu_log_mask(LOG_UNIMP, + "sun3_mmu_control_read at offset 0x%" HWADDR_PRIx + " (size=3D%u)\n", + addr, size); + return 0; +} + +static uint64_t sun3_mmu_buserr_read(void *opaque, hwaddr addr, unsigned s= ize) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + + uint8_t ret =3D s->buserr_reg; + s->buserr_reg =3D 0; /* Hardware clears on read */ + + return ret; +} + +static void sun3_mmu_buserr_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + s->buserr_reg =3D 0; +} + +static const MemoryRegionOps sun3_mmu_buserr_ops =3D { + .read =3D sun3_mmu_buserr_read, + .write =3D sun3_mmu_buserr_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static void sun3_mmu_control_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + Sun3MMUState *s =3D SUN3_MMU(opaque); + if (addr =3D=3D 0x0) { + /* System Enable Register at 0x40000000 */ + uint8_t enable_old =3D s->enable_reg; + s->enable_reg =3D (enable_old & 0x01) | (val & 0xFE); + + tlb_flush(CPU(first_cpu)); + return; + } + + if (addr =3D=3D 0x30000000) { + /* Otherwise Diagnostic LEDs (e.g. 0xFF to clear) */ + return; + } + + qemu_log_mask(LOG_UNIMP, + "sun3_mmu_control_write at offset 0x%" HWADDR_PRIx + "\n", addr); +} + +static const MemoryRegionOps sun3_mmu_control_ops =3D { + .read =3D sun3_mmu_control_read, + .write =3D sun3_mmu_control_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static void sun3_mmu_reset(DeviceState *dev) +{ + Sun3MMUState *s =3D SUN3_MMU(dev); + + s->context_reg =3D 0; + + /* + * On a Cold Boot, the Bus Error Register MUST be 0x00. + * Bit 0 is NOT a Watchdog flag that must be 1. In fact, if the regist= er + * reads + * non-zero, the PROM assumes it is returning from a Watchdog/Bus Error + * Panic and attempts to dump CPU state to memory (moveml) before the + * MMU is initialized, causing a Double Fault. + */ + s->buserr_reg =3D 0x00; + + /* + * CRITICAL: Do NOT wipe the Segment Map or Page Map! + The Sun-3 Boot PROM relies on the physical MMU SRAM persisting acro= ss + * Watchdog Resets so it can trace and push exception vectors back + * into mapped physical RAM! + */ +} + +static void sun3_mmu_init(Object *obj) +{ + Sun3MMUState *s =3D SUN3_MMU(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + /* Context Map */ + /* + * Note: Control space regions decode the top nibble of a 32-bit addre= ss. + The PROM uses the raw virtual address as the offset when accessing + these regions, so they must handle sparsely distributed addresses u= p to + 256MB. + */ + memory_region_init_io(&s->context_mem, obj, &sun3_mmu_context_ops, s, + "sun3-mmu-context", 0x10000000); + sysbus_init_mmio(sbd, &s->context_mem); + + /* Segment Map */ + memory_region_init_io(&s->segment_mem, obj, &sun3_mmu_segment_ops, s, + "sun3-mmu-segment", 0x10000000); + sysbus_init_mmio(sbd, &s->segment_mem); + + /* Page Map */ + memory_region_init_io(&s->page_mem, obj, &sun3_mmu_page_ops, s, + "sun3-mmu-page", 0x10000000); + sysbus_init_mmio(sbd, &s->page_mem); + + /* Other control bits (Enable Register, Diagnostic LEDs) */ + memory_region_init_io(&s->control_mem, obj, &sun3_mmu_control_ops, s, + "sun3-mmu-control", 0x40000000); + sysbus_init_mmio(sbd, &s->control_mem); + + /* + * Bus Error Register dedicated mapping + */ + memory_region_init_io(&s->buserr_mem, obj, &sun3_mmu_buserr_ops, s, + "sun3-mmu-buserr", 1); + sysbus_init_mmio(sbd, &s->buserr_mem); + + /* DVMA IOMMU interception region */ + memory_region_init_iommu(&s->dvma_iommu, sizeof(s->dvma_iommu), + TYPE_SUN3_DVMA_IOMMU_MEMORY_REGION, + obj, "sun3-dvma", 0x1000000); +} + +static void sun3_mmu_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + device_class_set_legacy_reset(dc, sun3_mmu_reset); + dc->vmsd =3D NULL; /* TODO: Add migration state later */ +} + +static IOMMUTLBEntry sun3_dvma_translate(IOMMUMemoryRegion *iommu, hwaddr = addr, + IOMMUAccessFlags flag, int iommu_= idx) +{ + Sun3MMUState *s =3D container_of(iommu, Sun3MMUState, dvma_iommu); + CPUState *cs =3D first_cpu; + CPUM68KState *env =3D cs ? cpu_env(cs) : NULL; + + IOMMUTLBEntry ret =3D { + .target_as =3D &address_space_memory, + .iova =3D addr, + .translated_addr =3D 0, + .addr_mask =3D ~(hwaddr)0, + .perm =3D IOMMU_NONE, + }; + + if (!env) { + return ret; + } + + hwaddr physical; + int prot; + hwaddr page_size; + /* + * Lance DVMA translates 24-bit requests implicitly onto the top 16MB = of + * the 28-bit virtual Bus (0x0Fxxxxxx) tied rigidly to Context 0. + */ + uint32_t vaddr =3D addr + 0x0F000000; + + int access_type =3D ACCESS_DATA | ACCESS_SUPER | (5 << 8); + if (flag =3D=3D IOMMU_WO || flag =3D=3D IOMMU_RW) { + access_type |=3D ACCESS_STORE; + } + + uint8_t old_ctx =3D s->context_reg; + s->context_reg =3D 0; /* Hardware forces Context 0 during DVMA */ + + if (sun3mmu_get_physical_address(env, &physical, &prot, vaddr, + access_type, &page_size) =3D=3D 0) { + ret.translated_addr =3D physical & ~(page_size - 1); + ret.addr_mask =3D page_size - 1; + if (prot & PAGE_WRITE) { + ret.perm =3D IOMMU_RW; + } else if (prot & PAGE_READ) { + ret.perm =3D IOMMU_RO; + } + } + s->context_reg =3D old_ctx; /* Restore pre-DVMA context */ + return ret; +} + +static void sun3_dvma_iommu_memory_region_class_init(ObjectClass *klass, + const void *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + imrc->translate =3D sun3_dvma_translate; +} + +static const TypeInfo sun3_dvma_iommu_memory_region_info =3D { + .name =3D TYPE_SUN3_DVMA_IOMMU_MEMORY_REGION, + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .class_init =3D sun3_dvma_iommu_memory_region_class_init, +}; + +static const TypeInfo sun3_mmu_info =3D { + .name =3D TYPE_SUN3_MMU, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(Sun3MMUState), + .instance_init =3D sun3_mmu_init, + .class_init =3D sun3_mmu_class_init, +}; + +static void sun3_mmu_register_types(void) +{ + type_register_static(&sun3_mmu_info); + type_register_static(&sun3_dvma_iommu_memory_region_info); +} + +type_init(sun3_mmu_register_types) + +static bool is_valid_sun3_phys(hwaddr p, ram_addr_t ram_size) +{ + if (p < ram_size) { + return true; + } + if (p >=3D 0x0FE50000 && p <=3D 0x0FE7FFFF) { + return true; /* NVRAM and OBIO RAM */ + } + if (p >=3D 0x08000000 && p <=3D 0x08001FFF) { + return true; /* IDPROM */ + } + if (p >=3D 0x0FEF0000 && p <=3D 0x0FEFFFFF) { + return true; /* PROM */ + } + if (p >=3D 0x0FF00000 && p <=3D 0x0FF0FFFF) { + return true; /* PROM Alias */ + } + + /* Specific OBIO devices for Sun-3/60 (Ferrari) */ + if (p >=3D 0x0FE00000 && p <=3D 0x0FE00007) { + return true; /* ZS1 (Kbd/Mouse) */ + } + if (p >=3D 0x0FE20000 && p <=3D 0x0FE20007) { + return true; /* ZS0 (Serial) */ + } + if (p >=3D 0x0FE40000 && p <=3D 0x0FE407FF) { + return true; /* EEPROM */ + } + if (p >=3D 0x0FF20000 && p <=3D 0x0FF201FF) { + return true; /* LANCE Am7990 */ + } + if (p >=3D 0x0FE60000 && p <=3D 0x0FE6003F) { + return true; /* Timer */ + } + if (p >=3D 0x0FE80000 && p <=3D 0x0FE8001F) { + return true; /* Memerr */ + } + if (p >=3D 0x0FEA0000 && p <=3D 0x0FEA0003) { + return true; /* Intreg */ + } + + return false; +} + +int sun3mmu_get_physical_address(void *env, hwaddr *physical, int *prot, + vaddr address, int access_type, + hwaddr *page_size) +{ + /* + * Translate the virtual address using the Sun-3 MMU maps. + */ + CPUM68KState *m68k_env =3D env; + Sun3MMUState *s =3D SUN3_MMU(m68k_env->custom_mmu_opaque); + + uint8_t context; + uint16_t pmeg =3D 0; + uint32_t pte; + uint32_t pte_index =3D 0; + uint32_t pte_offset =3D 0; + uint32_t phys_addr; + + /* + * access_type from m68k TCG: + ACCESS_CODE (0x10), ACCESS_DATA (0x20) + * ACCESS_SUPER (0x01) * + */ + bool is_write =3D access_type & ACCESS_STORE; + bool is_supervisor =3D access_type & ACCESS_SUPER; + + *page_size =3D TARGET_PAGE_SIZE; + + /* + * QEMU Pipeline Prefetch Workaround: + * The Sun-3 PROM executes `movesb %d0, 0x40000000` out of ROM (0x0FEF= xxxx) + * to enable the MMU (`enable_reg |=3D 0x80`). On real M68020 hardware= , the + * subsequent instruction(s) have already been prefetched while the MMU + * was off. QEMU attempts to fetch the next sequential instruction + * synchronously with the MMU fully active. Because the PROM has not m= apped + * 0x0FEF0000 in the Page Table (it only maps Virtual 0x00000000 to + * the ROM), + * QEMU triggers an immediate Translation Fault Exception Loop! We must + * manually bless instruction fetches originating mechanically from the + * physical ROM space to emulate the prefetch cache. * + */ + if ((access_type & ACCESS_CODE) && + (address >=3D 0x0FEF0000 && address <=3D 0x0FEFFFFF)) { + *physical =3D address; + *prot =3D PAGE_READ | PAGE_EXEC; + return 0; + } + + /* + * Boot Mode PROM Bypass: + If the Not-Boot bit (0x80) in the Enable Register is clear (System = is in + Boot State): ONLY Instruction Fetches bypass the MMU mapping mechan= ism! + Data accesses and Stack Pushes (such as the Exception Frame push to + 0x0FEEFFFE) proceed through the MMU mapped tables normally because = the + * PROM sets up its stack logically! * + */ + + + + qemu_log_mask(CPU_LOG_MMU, + "[SUN3MMU] get_physical_address(0x%08" VADDR_PRIx + ") enable_reg=3D0x%02x\n", + address, s->enable_reg); + + /* + * Sun-3 Hardware Architectural Demultiplexer: + * The M68020 emulator now seamlessly passes the Source/Destination Fu= nction + * Code inside the top 8 bits of the `access_type` bitmask, directly + * supplied + * via an isolation index in the QEMU TCG pipeline. This mirrors + * how the physical M68K processor provides 3 explicit FC pins in + * addition to + * the 32-bit physical address bus! + * + * If the extracted FC equals 3 (Control Space / Hardware Registers), = it + * NEVER enters the MMU Segment Map. It is universally 1:1 mapped to + * physical memory for raw HW device configuration (0x60000000, 0x1000= 0000)! + */ + uint8_t true_fc =3D (access_type >> 8) & 0x07; + if (true_fc =3D=3D 3) { + /* + * Direct Physical Bypass Mapping to discrete SysBus devices. + * The top nibble of the virtual address selects the Control Space + * target. All lower bits are aliases. + */ + uint32_t device_base =3D address & 0x70000000; + + if (device_base =3D=3D 0x00000000) { + /* + * IDPROM is logically at 0x0 and occupies 32 bytes in hardwar= e. We + * shift it to 0x08000000 linearly in QEMU and force a 5-bit w= rap + * so it safely avoids physical Main RAM/ROM collisions! * + */ + *physical =3D 0x08000000 | (address & 0x1F); + } else { + switch (device_base) { + case 0x10000000: /* Page Map */ + /* + * Hardware Page Map physically contains 256 PMEGs * + * 16 PTEs * 4 bytes =3D 16,384 bytes + */ + *physical =3D 0xA0000000 | (address & 0x0FFFFFFF); + break; + case 0x20000000: /* Segment Map */ + /* + * Hardware Segment Map structurally is 8 Contexts * + * 2048 segments * 1 byte =3D 16,384 bytes + */ + *physical =3D 0x90000000 | (address & 0x0FFFFFFF); + break; + case 0x30000000: /* Context Register */ + /* + * Context register physically uniquely masks natively + * strictly functionally inside hardware + */ + *physical =3D 0x80000000 | (address & 0x07); + break; + case 0x40000000: /* System Enable */ + *physical =3D 0xB0000000 | (address & 0x0FFFFFFF); + break; + case 0x60000000: /* Bus Error Register */ + *physical =3D 0xC0000000 | (address & 0x0FFFFFFF); + break; + case 0x70000000: + /* Diagnostic Register (Aliases into Enable mem region) */ + *physical =3D 0xB0000000ULL + 0x30000000ULL + + (address & 0x0FFFFFFF); + break; + default: + s->buserr_reg |=3D 0x20; /* Timeout */ + return 1; + } + } + + *prot =3D PAGE_READ | PAGE_WRITE; + *page_size =3D SUN3_PAGE_SIZE; + + qemu_log_mask( + CPU_LOG_MMU, + "[SUN3MMU] TRUE FC=3D3 CONTROL SPACE DECODE: vaddr=3D0x%08" VADD= R_PRIx + " mapped directly to physical 0x%08x\n", + address, (unsigned int)*physical); + + return 0; + } + + /* + * For all standard memory operations, the Sun-3 physically masks the + * Address Bus to 28 virtual bits before hitting the MMU Arrays. + */ + address &=3D 0x0FFFFFFF; + + if (!(s->enable_reg & 0x80)) { + /* Boot State: Not-Boot bit (0x80) is CLEAR */ + + /* + * Address < 0x01000000 && Supervisor Program: + * Bypass MMU and map to the physical PROM (0x0FEF0000). + */ + if (true_fc =3D=3D 6 && (address < 0x01000000 || + (address >=3D 0x0FEF0000 && address < 0x0FF00= 000))) { + *physical =3D 0x0FEF0000 | (address & 0x0001FFFF); + *prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; + *page_size =3D SUN3_PAGE_SIZE; + return 0; + } + } + + context =3D s->context_reg & (SUN3_MMU_CONTEXTS - 1); + + /* Segment map lookup: top 11 bits of 28-bit virtual address (bits 17-= 27) */ + uint32_t seg_index =3D (address >> 17) & (SUN3_MMU_SEGMENTS_PER_CONTEX= T - 1); + pmeg =3D s->segment_map[(context * SUN3_MMU_SEGMENTS_PER_CONTEXT) + + seg_index]; + + /* Page map lookup: bits 13-16 of virtual address */ + pte_index =3D (address >> SUN3_PAGE_SHIFT) & (SUN3_MMU_PTE_PER_PMEG - = 1); + pte_offset =3D (pmeg * SUN3_MMU_PTE_PER_PMEG) + pte_index; + pte =3D s->page_map[pte_offset]; + + /* Update PTE Accessed/Modified bits */ + if (pte & SUN3_PTE_VALID) { + uint32_t new_pte =3D pte | SUN3_PTE_REF; + if (is_write) { + new_pte |=3D SUN3_PTE_MOD; + } + if (new_pte !=3D pte) { + s->page_map[pte_offset] =3D new_pte; + } + } + + if (!(pte & SUN3_PTE_VALID)) { + s->buserr_reg |=3D 0x80; /* Invalid */ + return 1; /* Translation fault */ + } + + /* Protection check */ + uint8_t mmu_prot =3D (pte >> 29) & 3; + + if (!is_supervisor && (mmu_prot & 1)) { + s->buserr_reg |=3D 0x40; /* Protection */ + return 1; /* User access to supervisor page */ + } + + *prot =3D PAGE_READ | PAGE_EXEC; + if (mmu_prot & 2) { + if (is_write || (pte & SUN3_PTE_MOD)) { + *prot |=3D PAGE_WRITE; + } + } + + if (is_write && !(mmu_prot & 2)) { + s->buserr_reg |=3D 0x40; /* Protection */ + return 1; + } + + /* + * Extract physical address. The top 15 bits come from the PTE's + * PGFRAME. Bottom 13 bits (0x1FFF) come directly from the virtual + * address. + */ + phys_addr =3D ((pte & SUN3_PTE_PGFRAME) << SUN3_PAGE_SHIFT) | + (address & (SUN3_PAGE_SIZE - 1)); + + /* + * Address space Mapping reference: + * - OBMEM: 0x00000000 (Follows native Map) + * - OBIO: 0x0FE00000 (Relocated above typical 24MB RAM) + * - VME_D16: 0x40000000 (Relocated out of bounds) + * - VME_D32: 0x50000000 + */ + uint32_t pgbase =3D ((pte & SUN3_PTE_PGFRAME) << SUN3_PAGE_SHIFT); + uint32_t pgtype =3D (pte & SUN3_PTE_PGTYPE) >> 26; + + /* + * Sun-3 Hardware Quirk: + * The Boot PROM maps Virtual `0x00000000` to its ROM header using OBIO + * Page `0x80` (`0xC4000080`). Native hardware intercepts OBIO offset + * `0x100000` and transparently aliases it back to OBMEM PROM + * (`0x0FEF0000`) using the virtual address to index the ROM! * + */ + if (pgtype =3D=3D SUN3_PGTYPE_OBIO && + (pgbase >=3D 0x100000 && pgbase < 0x120000)) { + phys_addr =3D 0x0FEF0000 | (address & 0x1FFFF); + } else { + switch (pgtype) { + case SUN3_PGTYPE_OBMEM: + break; + case SUN3_PGTYPE_OBIO: + phys_addr +=3D 0x0FE00000; + break; + case SUN3_PGTYPE_VME_D16: + phys_addr +=3D 0x40000000; + break; + case SUN3_PGTYPE_VME_D32: + phys_addr +=3D 0x50000000; + break; + } + } + + /* NXM (Non-Existent Memory) Bounds Checking */ + if (!is_valid_sun3_phys(phys_addr, current_machine->ram_size)) { + s->buserr_reg |=3D 0x20; /* Timeout */ + return 1; + } + + /* + * The QEMU TLB works in 4KB frames, not Sun-3's 8KB native frames. + * We MUST explicitly append the intra-page offset within the 8KB page, + * otherwise accesses to the upper 4KB (e.g. 0x1000, 0x3000) will be + * truncated and overwrite the physical memory of the lower 4KB! + */ + *physical =3D phys_addr | (address & (SUN3_PAGE_SIZE - 1)); + + *page_size =3D TARGET_PAGE_SIZE; + + return 0; /* 0 =3D success, no fault */ +} diff --git a/include/hw/m68k/sun3mmu.h b/include/hw/m68k/sun3mmu.h new file mode 100644 index 0000000000..bdd79d963b --- /dev/null +++ b/include/hw/m68k/sun3mmu.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef HW_M68K_SUN3MMU_H +#define HW_M68K_SUN3MMU_H + +#include "exec/cpu-common.h" +#include "exec/hwaddr.h" +#include "exec/target_page.h" +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_SUN3_MMU "sun3-mmu" +OBJECT_DECLARE_SIMPLE_TYPE(Sun3MMUState, SUN3_MMU) + +#define TYPE_SUN3_DVMA_IOMMU_MEMORY_REGION "sun3-dvma-iommu-memory-region" + +#define SUN3_MMU_CONTEXTS 8 +#define SUN3_MMU_PMEGS 256 +#define SUN3_MMU_PTE_PER_PMEG 16 +#define SUN3_MMU_SEGMENTS_PER_CONTEXT 2048 + +#define SUN3_PAGE_SIZE 0x2000 /* 8 KB */ +#define SUN3_PAGE_MASK (~(SUN3_PAGE_SIZE - 1)) +#define SUN3_PAGE_SHIFT 13 + +/* PTE bits */ +#define SUN3_PTE_VALID (1U << 31) +#define SUN3_PTE_WRITE (1U << 30) +#define SUN3_PTE_SYSTEM (1U << 29) +#define SUN3_PTE_NC (1U << 28) +#define SUN3_PTE_PGTYPE (3U << 26) +#define SUN3_PTE_REF (1U << 25) +#define SUN3_PTE_MOD (1U << 24) +#define SUN3_PTE_PGFRAME 0x0007FFFF + +/* PTE PGTYPE values */ +#define SUN3_PGTYPE_OBMEM 0 +#define SUN3_PGTYPE_OBIO 1 +#define SUN3_PGTYPE_VME_D16 2 +#define SUN3_PGTYPE_VME_D32 3 + +struct Sun3MMUState { + SysBusDevice parent_obj; + + MemoryRegion context_mem; + MemoryRegion segment_mem; + MemoryRegion page_mem; + MemoryRegion control_mem; + MemoryRegion buserr_mem; + IOMMUMemoryRegion dvma_iommu; + + uint8_t sys_enable_reg; /* Reserved mapping for testing */ + + uint8_t context_reg; + uint8_t enable_reg; + uint8_t buserr_reg; + uint8_t int_reg; + uint8_t segment_map[SUN3_MMU_CONTEXTS * SUN3_MMU_SEGMENTS_PER_CONTEXT]; + uint32_t page_map[SUN3_MMU_PMEGS * SUN3_MMU_PTE_PER_PMEG]; +}; + +int sun3mmu_get_physical_address(void *env, hwaddr *physical, int *prot, + vaddr address, int access_type, + hwaddr *page_size); + +#endif --=20 2.50.1 (Apple Git-155) From nobody Sat May 30 18:34:29 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1777787983; cv=none; d=zohomail.com; s=zohoarc; b=OsDEANmROfIwOpOx8zP+RKSvHu0h0G/l9o6ct1gpGpWpWvkMo4L5q8ScNZHQl4TVr6ludMMXhYDL9TkNu02byAWK6tJm3p13Xx4o9jRiltb95J5Esu77omXJ9R+IzBiPI6Ul9Um/eLNrBZN/UxVvDswWHxdXHbWbYEnDpVw4VwU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777787983; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Gcpjqh/XTVHiUj0x51nDVg2xWlGOek5lFSsj05b9g04=; b=lCn1+OzgnEKWzZP0xV0ANyJ/YmuKfu0HovlycxfVLOuBcB9GC8Wt6LLYr9aZ3Y0D6q6sNxOA4zAbNzayOrduPv0bmaoQ8+7+bs4JGnliYscfTsCJaJOPjVkPeV7wrSuVIOFWZF8Ugynjd6qFPB0VWAfvILPYdfU6soxUz7gMtSk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from=<54weasels@gmail.com> (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777787983729303.46410016884715; Sat, 2 May 2026 22:59:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wJPrJ-0001Fx-QB; Sun, 03 May 2026 01:59:17 -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 <54weasels@gmail.com>) id 1wJM6F-0004wp-MN for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:27 -0400 Received: from mail-dy1-x1331.google.com ([2607:f8b0:4864:20::1331]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <54weasels@gmail.com>) id 1wJM6D-0000Yq-AS for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:26 -0400 Received: by mail-dy1-x1331.google.com with SMTP id 5a478bee46e88-2c156c4a9efso5331549eec.1 for ; Sat, 02 May 2026 18:58:24 -0700 (PDT) Received: from newsled.lan ([76.133.142.170]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee38d79eb9sm14361735eec.8.2026.05.02.18.58.22 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 02 May 2026 18:58:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777773503; x=1778378303; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Gcpjqh/XTVHiUj0x51nDVg2xWlGOek5lFSsj05b9g04=; b=hVpR3a24Fj+MkB5c9344FlmbpP1EGO8rOBf1K8RXLZKkjb8AMLSklzU7EwLu+Nc4AC /6mhF5OK1GqDVLQPsEZvZOE6C5yI73fcjh00o1KnA+bAtxlv8KKgynpXNHhXey+19suv l8AUtPq/lpntqLtcgu5LK761qjdt1Q5wDZbuH4LioRtL+qOHxGF2ajpByFUeT62jNCVn m7NsOrB0wlRkK8ez3VTraaSYx4ZKpTWlc0/2HKM6kJ8RHGbm4UUy5dhOjzCZ/B5636ZY hywUEBkvIpcZr9oCXcJYzk4Jqxbo7QNixTguofBOIIQ5Ww5ja3z6TwwQV+kplnDgonCq BmhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777773503; x=1778378303; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Gcpjqh/XTVHiUj0x51nDVg2xWlGOek5lFSsj05b9g04=; b=mp+ZHqS/PJVcI1lsVbC+5bG7TVfiokm96Erf2NzG0EDlXy2zrTmNJIsGlyo1rBn+fE oGIgXEDBplRgC98vsism6do3SS0nKz6VZZ9ieTBC2io57FneNZ5f16ZieBXsHkq3o9OI oWlW+I8WSu5LBR0Yp05+H4FVISwFkTLqFUH4Ml4lwOG/QrvZaSHWeRHIjSN1UM+X1GC1 AM3l43sSupuVhmt3BexJ8NOLzU7htdJJtQisjz17aRxUiJ1wy5aVxXRkyy5JDNlgTdi3 TLIzWY5uMw3eexyW2z79YDnpG5tDabGJu/CAVX4ww0HpQ92ieSDzgVcmnqCPTzy/PlqJ STMQ== X-Gm-Message-State: AOJu0YzpVleDubkoDprhh1GImd/GSC094m3qXcU4n74BiGfyqGbTHoWC SvzsbFZGBICOh4XU8AcFMRqeT9RwRhTmrNgvf82JUehmTGCT6i32FHMMBn2Ogw== X-Gm-Gg: AeBDietV4ja3vp14c3z3x8CHJsxsgv44zz6G7jFoWCh7LEEj9lUOTzv3WQVU6XAcGRJ 9aZ3NFsn8co/sIsl5GeIlmATUdE2TkSDoMTn+Dp+i5j9IcdlIFugyHVPmB/kzpCD4G8lL6kr2Bf zvkDBtEqncTa7P+olD9NJtgpNzWSQt/RZTJ59QGR2Q/a5K9AZ4DC5igM0/kbv6acxoJeKae7L8T ec7jgu0ETeT4e74M9S5RcdIZ5cbZ02Pq0oyWnxeZUwsbKAtsi8YPeiorpDrGyG4kTgQ83qsBvQu TomN9w3r9oJYqkXexdQUXEHd9YYKQ3Lu1x20IDDtbP7DNuWeUxkB43WlBuAUrGJN4uwBD/cbRcb X0mQ4f+z3e/4YuFPs1ZeFKi6rQ9RLE6zv4y865Aqr6yyS8qq2CMSJdq7kAUSG1fm773zwGUNlWU vilEirJr9NbftFm+Jj7zhBoTH/othN8rbUoSGbxJiOVoZXRkSNyg== X-Received: by 2002:a05:7301:9f06:b0:2d8:df01:d9f6 with SMTP id 5a478bee46e88-2efba17c714mr1929349eec.23.1777773503474; Sat, 02 May 2026 18:58:23 -0700 (PDT) From: 54weasels <54weasels@gmail.com> To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, thuth@redhat.com, 54weasels <54weasels@gmail.com> Subject: [PATCH 6/7] tests/qtest: Add Sun-3 hardware interaction tests Date: Sat, 2 May 2026 18:57:55 -0700 Message-ID: <20260503015756.99176-7-54weasels@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260503015756.99176-1-54weasels@gmail.com> References: <20260503015756.99176-1-54weasels@gmail.com> 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=2607:f8b0:4864:20::1331; envelope-from=54weasels@gmail.com; helo=mail-dy1-x1331.google.com 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 03 May 2026 01:59:14 -0400 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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1777787986188154100 Content-Type: text/plain; charset="utf-8" This adds basic architectural and register validation for the newly assembl= ed Sun-3 machine. Signed-off-by: 54weasels <54weasels@gmail.com> --- tests/qtest/meson.build | 1 + tests/qtest/sun3-test.c | 67 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/qtest/sun3-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index be4fa627b5..184d1a3f8c 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -154,6 +154,7 @@ qtests_loongarch64 =3D qtests_filter + \ 'cpu-plug-test'] =20 qtests_m68k =3D ['boot-serial-test'] + \ + ['sun3-test'] + \ qtests_filter =20 qtests_microblaze =3D ['boot-serial-test'] + \ diff --git a/tests/qtest/sun3-test.c b/tests/qtest/sun3-test.c new file mode 100644 index 0000000000..50f6c166d1 --- /dev/null +++ b/tests/qtest/sun3-test.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QTest device validation for the Sun-3 Machine + * + * Copyright (c) 2026 + */ + +#include "qemu/osdep.h" +#include "libqtest.h" + +/* OBIO Memory Map Addresses */ +#define SUN3_INTREG_BASE 0x0FEA0000 +#define SUN3_MEMERR_BASE 0x0FE80000 + +static void test_intreg(void) +{ + QTestState *s; + uint8_t val; + + s =3D qtest_init("-machine sun3 -nographic"); + + /* Default state should be 0 */ + val =3D qtest_readb(s, SUN3_INTREG_BASE); + g_assert_cmphex(val, =3D=3D, 0x00); + + /* Write and verify */ + qtest_writeb(s, SUN3_INTREG_BASE, 0x0f); + val =3D qtest_readb(s, SUN3_INTREG_BASE); + g_assert_cmphex(val, =3D=3D, 0x0f); + + qtest_quit(s); +} + +static void test_memerr(void) +{ + QTestState *s; + uint8_t val; + + s =3D qtest_init("-machine sun3 -nographic"); + + /* Default state should be 0x40 (default no-error) */ + val =3D qtest_readb(s, SUN3_MEMERR_BASE); + g_assert_cmphex(val, =3D=3D, 0x40); + + /* Test parity error spoof sequence */ + qtest_writeb(s, SUN3_MEMERR_BASE, 0x20); /* Set test_parity_written */ + qtest_writeb(s, SUN3_MEMERR_BASE, 0x50); /* Trigger spoof */ + val =3D qtest_readb(s, SUN3_MEMERR_BASE); + + /* + * Since we didn't clock enough parity lanes, high bit and lane 8 shou= ld + * be set (0x50 | 0x80 | 0x08 =3D 0xd8) + */ + g_assert_cmphex(val, =3D=3D, 0xd8); + + qtest_quit(s); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/m68k/sun3/intreg", test_intreg); + qtest_add_func("/m68k/sun3/memerr", test_memerr); + + return g_test_run(); +} --=20 2.50.1 (Apple Git-155) From nobody Sat May 30 18:34:29 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1777788013; cv=none; d=zohomail.com; s=zohoarc; b=nTTfZt6YnHkEMlwgOyg5j5IcSB6lPSS6xtmadjCZ9LZJIoLlo/BfhAPFnDIhS40KYqrRsTic+izwklgqbDxRsHe+waab+E/ZD7hOeedCFmlQ9kaB+ZZkTCYW2GDhISyOTmAVeXDAahTwEx07SocRKyUgRkM5iOxn402Lr7srZO4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777788013; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=1QR6NDChDJEAzSKlkW2JjzGfYbC4Be2Ip1t74TmvjhY=; b=L7Hy/NcIeLX1a/8ujm7nJawvQfWb+LxST9bQ1b1KHA9mqJD0eVAaBY0Gh4+6KhQzI0ODIolxoN9ytlL6fVxWdBUvBBq7QJKpHa2LdEVaITtliokzaAWmIecrHD5yUPU6tnEXAN0MXi5IexVcqGY84C3eHlMBpdWgu1aA5x4gdOY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from=<54weasels@gmail.com> (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177778801313335.79541728140168; Sat, 2 May 2026 23:00:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wJPrN-0001Gn-90; Sun, 03 May 2026 01:59:21 -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 <54weasels@gmail.com>) id 1wJM6H-0004xB-36 for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:29 -0400 Received: from mail-dy1-x132f.google.com ([2607:f8b0:4864:20::132f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <54weasels@gmail.com>) id 1wJM6F-0000Z3-F2 for qemu-devel@nongnu.org; Sat, 02 May 2026 21:58:28 -0400 Received: by mail-dy1-x132f.google.com with SMTP id 5a478bee46e88-2dee127b3c5so7234327eec.1 for ; Sat, 02 May 2026 18:58:26 -0700 (PDT) Received: from newsled.lan ([76.133.142.170]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2ee38d79eb9sm14361735eec.8.2026.05.02.18.58.24 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 02 May 2026 18:58:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777773505; x=1778378305; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1QR6NDChDJEAzSKlkW2JjzGfYbC4Be2Ip1t74TmvjhY=; b=Vz37szzR8bQ6naELtPV/XOkFeIUJo0n3mzZkwFIDoZjxsWgV17tZ3ES2aCzNcV2wbf SrmhIgD8xYy4KJFUR17SrgZ7KvOnyh4caOyNHTypstU5v3sUfdcwDKu4nrDr5I+0VPSR WC1egrFmYc+gygzdJH4D3neICq94cnmpTqN9Z9EAsE9ksBhmDnhwFCH254iz5y+Px7QC WI5WtYT1sza6Glh3Rx8kTaOdL/yoQvMlp3bT+TwFCvqVGGtS9r8kA521Wm6p2EC+8tdp sciTS/QJERzTQEPqrlw7/MDeclRXmE1oB+12QR3c9fC+c14eoTvkSt479DPodUvy6cGq GEig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777773505; x=1778378305; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=1QR6NDChDJEAzSKlkW2JjzGfYbC4Be2Ip1t74TmvjhY=; b=fuJHemPjd89ZDRLZGOJZikxFiQWaoIHJIXoE/2IUF+n7WRbGF+NkhpHknzoDaaCFzt jOGmVMubp2Qj4L/4H8beQ7SsbbeW66koipZuD6C5C6CGeSCbBjULe2ctzCHuH01VhTKg zAFNGNxFXjMOx6mNU0l1F2arhLMsE7jsKZpZdz9vSZlcFXHAwIAaCcVS5A/PyQylOTuF rJ8QupkkM9pADmLMJDb8d58K/t2M0VU7GHi27X5sHiA1/zNuWUAXOD7B6roLZsEE+RYz QObwKNQI9i7lu0Sbclubbc7ju72FGQQ7Q4BYlnfDHLR7PTvdxBw3EJSOJaFIuHcZ76uA Q70g== X-Gm-Message-State: AOJu0YzU6SOg1Qn7dJCYG2tVcgMSiMtMbrJrM/b0wdjBFgoSb4j690Xm rliT36O1zUevmoDiGJ5vxxFX+wgDOJwdNoMNoOzu8bpUYZCmVGBftAyXKTZHDw== X-Gm-Gg: AeBDiesfeMVJmqQHTac2+I2VLkEzn7PYADQEbQX+S1Xi3qTtJ5H8fIcCfh939XEWEw2 GjXpbSf/49Hg6uhv40hzbIdQEPSbTTOmRVdAq39qJ+XPOGsp0qfKkDbzJB8iIqqFJq8mUBqjvFn 8R2pwi0CUHBR8RLC0L6dU/ZOSIaSths/mgwJKBJPbYxdMoWeCcjpFqF9r49ipTC5R3/rr6+WjfG zCfA93LHdj9mrKWb+roqN3rtRD3dajGmlKOz0D8zEGPiF2/IRdeiQIQAN4crA7R1e2V8yl+jRQP yYAxI7G7vxGBbjLLbF6su5TS1rBSjYtsN0OFxhKHJwQnDNuEz1sJrwcoknWyrCG5wI0UXhqHhrb Y68lVq9ibIv/9bCMi9RmIBeH/Vk0F2Aj+5wpg2ZSlERUdINUJpwPXaZ2GZc1rXoACs59mf0Pjow rbpyjsTkgDJsOK8ZLTwkUBReRAeIX0grBA7cNP+k76+fBiYL15pw== X-Received: by 2002:a05:7300:a18a:b0:2c5:60d0:701e with SMTP id 5a478bee46e88-2efb79cc45amr2300616eec.3.1777773505012; Sat, 02 May 2026 18:58:25 -0700 (PDT) From: 54weasels <54weasels@gmail.com> To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, thuth@redhat.com, 54weasels <54weasels@gmail.com> Subject: [PATCH 7/7] tests/functional: Add Sun-3 firmware boot and diagnostic test Date: Sat, 2 May 2026 18:57:56 -0700 Message-ID: <20260503015756.99176-8-54weasels@gmail.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260503015756.99176-1-54weasels@gmail.com> References: <20260503015756.99176-1-54weasels@gmail.com> 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=2607:f8b0:4864:20::132f; envelope-from=54weasels@gmail.com; helo=mail-dy1-x132f.google.com 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 03 May 2026 01:59:20 -0400 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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1777788014873158500 Content-Type: text/plain; charset="utf-8" This adds an integration test that downloads the Sun-3/60 Boot PROM, initia= lizes the machine, and ensures the self-test successfully routes to TTY A. Signed-off-by: 54weasels <54weasels@gmail.com> --- tests/functional/m68k/meson.build | 1 + tests/functional/m68k/test_sun3.py | 34 +++++++++++++++++++++++++++++ tests/functional/qemu_test/asset.py | 11 +++++----- 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100755 tests/functional/m68k/test_sun3.py diff --git a/tests/functional/m68k/meson.build b/tests/functional/m68k/meso= n.build index 679faaf86d..601c28d863 100644 --- a/tests/functional/m68k/meson.build +++ b/tests/functional/m68k/meson.build @@ -9,5 +9,6 @@ tests_m68k_system_thorough =3D [ 'nextcube', 'replay', 'q800', + 'sun3', 'tuxrun', ] diff --git a/tests/functional/m68k/test_sun3.py b/tests/functional/m68k/tes= t_sun3.py new file mode 100755 index 0000000000..f441184616 --- /dev/null +++ b/tests/functional/m68k/test_sun3.py @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +#!/usr/bin/env python3 +# +# Functional test that boots a Sun-3 machine and checks its serial console. +# +# Copyright (c) 2026 +# + + +import os +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + +class Sun3Machine(QemuSystemTest): + timeout =3D 60 + + ASSET_PROM =3D Asset( + 'https://github.com/54weasels/sun3_60/raw/main/bootprom/boot_1810_= 01.BIN', + '471bf34cc9313814726c2e3506d85a13291603e37b45aaffa71bc1154a2d4851' + ) + + def test_m68k_sun3_boot(self): + self.set_machine('sun3') + prom_path =3D self.ASSET_PROM.fetch() + + # Sun-3 maps TTY A to serial_hd(3) + self.vm.set_console(console_index=3D3) + self.vm.add_args('-bios', prom_path) + self.vm.launch() + + wait_for_console_pattern(self, '>') + +if __name__ =3D=3D '__main__': + QemuSystemTest.main() diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_te= st/asset.py index 51a434b2b7..eac1e60536 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -223,11 +223,12 @@ def fetch(self): raise AssetError(self, "Download retries exceeded", transient= =3DTrue) =20 try: - # Set these just for informational purposes - os.setxattr(str(tmp_cache_file), "user.qemu-asset-url", - self.url.encode('utf8')) - os.setxattr(str(tmp_cache_file), "user.qemu-asset-hash", - self.hash.encode('utf8')) + if hasattr(os, 'setxattr'): + # Set these just for informational purposes + os.setxattr(str(tmp_cache_file), "user.qemu-asset-url", + self.url.encode('utf8')) + os.setxattr(str(tmp_cache_file), "user.qemu-asset-hash", + self.hash.encode('utf8')) except OSError as e: self.log.debug("Unable to set xattr on %s: %s", tmp_cache_file= , e) =20 --=20 2.50.1 (Apple Git-155)