Hello, A gentle ping. This patch fixes TTE page-size MMU decoding so 32M/256M pages are no longer truncated across sparc/niagara (sun4v). It improves support for the Solaris 10/11 kernels. https://lore.kernel.org/qemu-devel/[email protected]/T/#u
Regards, Dmitry > On 18 Sep 2026, at 12:57, dpim <[email protected]> wrote: > > Currently, the TTE's page-size field, Size, is 2 bits wide: > > #define TTE_PGSIZE(tte) (((tte) >> 61) & 3ULL) > > That is the TTE of every UltraSPARC before UltraSPARC IV+. > The JPS1 implementation supplements for UltraSPARC III and IV+ > describe the TTE word in tables F-1 and F-1-4 respectively, and differ > in one bit: > Before IV+ bit 48 is reserved and reads as 0, Size is 2 bits at 62:61; > On IV+ bit 48 is Size<2>, which "is the most significant bit of the > page size and is concatenated with bits <62:61>" > On T1 the same split exists, szl at 62:61 and szh at 48 (T1 Supplement, > sec. 13.1.2). > > QEMU models parts on both sides of that change (UltraSPARC III/IIIi/IV, > IV+, T1, T2) with the III layout: Size<2> was never implemented. > Bit 48 gets lost in more than one place: > > On sun4u the raw TTE word is stored as the guest wrote it, bit 48 > included, but TTE_PGSIZE() only reads bits 62:61: the bit survives in > the TLB, it is just never decoded. > > On sun4v, sun4v_tte_to_sun4u() converts the incoming three-bit code > (cpu.h defines TTE_PGSIZE_UA2005() for it, unused until now) but masked > it to two: > > sun4u_tte |= (sun4v_tte & 3ULL) << 61; /* TTE_PGSIZE */ > > so the third bit was dropped before it was stored. > > demap_tlb() duplicates the same 2-bit math instead of calling > TTE_PGSIZE(), so it misses bit 48 too, for a TTE from either origin. > > Either way 256M decodes as 64K and 32M as 8K; the guest faults on the > first access past the truncated entry. > > This patch implements Size<2> at bit 48, where the hardware keeps it. > > TTE_PGSIZE() now reads bit 48 as the high bit; on parts that keep bit > 48 reserved it reads as zero, so they decode as before. > sun4v_tte_to_sun4u() stores the full three-bit code, and demap_tlb() > now calls TTE_PGSIZE() instead of its own copy. dump_mmu() gains 32M > and 256M labels. > > Link: > https://lore.kernel.org/qemu-devel/[email protected]/ > AI-used-for: code, analysis > Signed-off-by: Dmitry Pimenov <[email protected]> > --- > v2: described behaviour across sun4u/sun4v instead of the sun4v > conversion; no functional change. QEMU_BUILD_BUG_ON and comments in > cpu.h/ldst_helper.c are dropped. > > This email's text -- beyond the code and analysis the trailer above > covers -- also had AI involvement: current policy (AGENTS.md) > declines AI-derived content outright, and even the not-yet-merged > llm-usage.rst RFC would require it to be human-written regardless of > any trailer. Sending as-is rather than silently -- happy to hear if > that's not acceptable here. > > Happy to run more tests or provide more evidence if this isn't enough. > > Guest is OpenSolaris snv_134 (osol-dev-134-ai-sparc.iso). Firmware is > the S10image/ set from OpenSPARCT1_Arch.1.5.tar.bz2, which > docs/system/target-sparc64.rst names for this machine, except the > MD/hv-config pair (1up-md.bin, 1up-hv.bin), from the repo below. The > archive's own config only boots disk.s10hw2, capped at 4M pages. > > Observed on upstream 5f664cd37a, with and without this patch -- same > guest, firmware and RAM, plain `boot` at the `ok` prompt (occasionally > hits an unrelated, pre-existing trap in OBP's loader phase before the > kernel runs): > > pristine: hangs after "Loading: /platform/sun4v/kernel/sparcv9/unix"; > "info tlb" shows no 32M or 256M entry. > patched: boots to "Enter user name for system maintenance"; > "info tlb" shows 256M entries, e.g. > [17] VA: 600108b8000, PA: 140000000, 256M, priv, RW, ... > Full info tlb dumps: > > https://github.com/unix0cc/qemu-experimental-patches/blob/967a037/verification/0002-tte-size2/logs/pristine-plain-boot-tlb.txt > > https://github.com/unix0cc/qemu-experimental-patches/blob/967a037/verification/0002-tte-size2/logs/patched-plain-boot-tlb.txt > > The reproduction as a script, verify.sh (fetches firmware, MD and > ISO, checks their hashes, boots): > > https://github.com/unix0cc/qemu-experimental-patches/blob/967a037/verification/0002-tte-size2/verify.sh > > On sun4u the pre-extension page sizes are verified by > make check-qtest-sparc64 and make check-functional-sparc64 (sun4u, > tuxrun, migration), which pass on the patched build with logs: > > https://github.com/unix0cc/qemu-experimental-patches/blob/967a037/verification/0002-tte-size2/check-qtest-sparc64.log > > https://github.com/unix0cc/qemu-experimental-patches/blob/967a037/verification/0002-tte-size2/check-functional-sparc64.log > To check whether > Size<2> is exercised at all, I added a temporary log in > replace_tlb_entry() and ran both suites again: zero hits, as expected > -- IIi predates IV+ and doesn't implement Size<2>, so the guest > running under it never sets bit 48. Result: > > https://github.com/unix0cc/qemu-experimental-patches/blob/967a037/verification/0002-tte-size2/sun4u-bit48-probe/RESULT > Probe and logs: > > https://github.com/unix0cc/qemu-experimental-patches/tree/967a037/verification/0002-tte-size2/sun4u-bit48-probe/ > 32M/256M on sun4u stays untested by this suite; that would need a guest > running under Sun-UltraSparc-IV-plus. > > Overview of everything above (scripts, logs, README): > > https://github.com/unix0cc/qemu-experimental-patches/blob/967a037/verification/0002-tte-size2/README > > target/sparc/cpu.h | 4 +++- > target/sparc/ldst_helper.c | 9 +++++++-- > target/sparc/mmu_helper.c | 12 ++++++++++++ > 3 files changed, 22 insertions(+), 3 deletions(-) > > diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h > index 31a16c2af0..1ab420d831 100644 > --- a/target/sparc/cpu.h > +++ b/target/sparc/cpu.h > @@ -307,7 +307,9 @@ enum { > #define TTE_SET_USED(tte) ((tte) |= TTE_USED_BIT) > #define TTE_SET_UNUSED(tte) ((tte) &= ~TTE_USED_BIT) > > -#define TTE_PGSIZE(tte) (((tte) >> 61) & 3ULL) > +#define TTE_PGSIZE_HI_BIT (1ULL << 48) > +#define TTE_PGSIZE(tte) ((((tte) >> 61) & 3ULL) | \ > + (((tte) & TTE_PGSIZE_HI_BIT) >> 46)) > #define TTE_PGSIZE_UA2005(tte) ((tte) & 7ULL) > #define TTE_PA(tte) ((tte) & 0x1ffffffe000ULL) > > diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c > index 4ec8799d1f..142c1c24de 100644 > --- a/target/sparc/ldst_helper.c > +++ b/target/sparc/ldst_helper.c > @@ -186,7 +186,7 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong > demap_addr, > /* demap page > will remove any entry matching VA */ > mask = 0xffffffffffffe000ULL; > - mask <<= 3 * ((tlb[i].tte >> 61) & 3); > + mask <<= 3 * TTE_PGSIZE(tlb[i].tte); > > if (!compare_masked(demap_addr, tlb[i].tag, mask)) { > continue; > @@ -217,7 +217,12 @@ static uint64_t sun4v_tte_to_sun4u(CPUSPARCState *env, > uint64_t tag, > return sun4v_tte; > } > sun4u_tte = TTE_PA(sun4v_tte) | (sun4v_tte & TTE_VALID_BIT); > - sun4u_tte |= (sun4v_tte & 3ULL) << 61; /* TTE_PGSIZE */ > + { > + uint64_t pgsz = TTE_PGSIZE_UA2005(sun4v_tte); > + sun4u_tte |= (pgsz & 3ULL) << 61; /* TTE_PGSIZE bits 61-62 */ > + sun4u_tte |= (pgsz & 4ULL) ? > + TTE_PGSIZE_HI_BIT : 0; /* TTE_PGSIZE bit 48 */ > + } > sun4u_tte |= CONVERT_BIT(sun4v_tte, TTE_NFO_BIT_UA2005, TTE_NFO_BIT); > sun4u_tte |= CONVERT_BIT(sun4v_tte, TTE_USED_BIT_UA2005, TTE_USED_BIT); > sun4u_tte |= CONVERT_BIT(sun4v_tte, TTE_W_OK_BIT_UA2005, TTE_W_OK_BIT); > diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c > index 07ba25dfce..8544de097d 100644 > --- a/target/sparc/mmu_helper.c > +++ b/target/sparc/mmu_helper.c > @@ -830,6 +830,12 @@ void dump_mmu(CPUSPARCState *env) > case 0x3: > mask = " 4M"; > break; > + case 0x4: > + mask = " 32M"; > + break; > + case 0x5: > + mask = "256M"; > + break; > } > if (TTE_IS_VALID(env->dtlb[i].tte)) { > qemu_printf("[%02u] VA: %" PRIx64 ", PA: %llx" > @@ -869,6 +875,12 @@ void dump_mmu(CPUSPARCState *env) > case 0x3: > mask = " 4M"; > break; > + case 0x4: > + mask = " 32M"; > + break; > + case 0x5: > + mask = "256M"; > + break; > } > if (TTE_IS_VALID(env->itlb[i].tte)) { > qemu_printf("[%02u] VA: %" PRIx64 ", PA: %llx" > -- > 2.43.0 >
