qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH 1/2] ppc: Add support for MPC7450 software TLB miss interrupt


From: Fabiano Rosas
Subject: [RFC PATCH 1/2] ppc: Add support for MPC7450 software TLB miss interrupts
Date: Fri, 19 Nov 2021 10:44:30 -0300

The MPC7450 Family has a software TLB search feature that defines
three interrupts at 0x1000, 0x1100 and 0x1200. These are not currently
implemented in openbios.

Due to an outstanding bug in QEMU[1], the feature is always enabled
when emulating the 7450, requiring any software that runs in those
cpus to implement the interrupt handlers.

Fortunately, the 7450 User Manual provides sample code[2] for the TLB
miss handlers so adding support for the feature in openbios is
somewhat easy.

This patch implements the software TLB search so that we can get the
MPC7450 working again on the emulator.

1- https://gitlab.com/qemu-project/qemu/-/issues/86
2- https://www.nxp.com/docs/en/reference-manual/MPC7450UM.pdf
(5.5.5.2.2 - Code for Example Exception Handlers)

Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com>
---
 arch/ppc/qemu/start.S | 236 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 233 insertions(+), 3 deletions(-)

diff --git a/arch/ppc/qemu/start.S b/arch/ppc/qemu/start.S
index c679230..a09a210 100644
--- a/arch/ppc/qemu/start.S
+++ b/arch/ppc/qemu/start.S
@@ -25,6 +25,10 @@
 #define ILLEGAL_VECTOR( v )    .org __vectors + v ; vector__##v: bl trap_error 
;
 #define VECTOR( v, dummystr )  .org __vectors + v ; vector__##v
 
+#define SPR_TLBMISS 980
+#define SPR_PTEHI   981
+#define SPR_PTELO   982
+
 #ifdef CONFIG_PPC_64BITSUPPORT
 
 /* We're trying to use the same code for the ppc32 and ppc64 handlers here.
@@ -164,6 +168,76 @@
        EXCEPTION_EPILOGUE_TEMPLATE
 .endm
 
+.macro ITLB_SEARCH
+       TLB_SEARCH
+.endm
+
+.macro DTLB_SEARCH
+       TLB_SEARCH 1
+.endm
+
+.macro TLB_SEARCH data
+       mfspr   r0,SPR_TLBMISS /* EA of access that missed */
+       rlwinm  r0,r0,20,16,31 /* mask out lower 16 bits of EA */
+       mfspr   r1,SPR_PTEHI   /* PTEHI[1:24] has the VSID */
+       rlwinm  r1,r1,25,8,31  /* mask out upper 23 bits of VSID */
+
+       xor     r1,r0,r1       /* primary hash */
+       mfsdr1  r3
+       rlwinm  r0,r3,10,13,31 /* align HTMEXT and HTABMASK fields */
+       ori     r0,r0,0x3ff    /* mask out HTMEXT and HTABMASK */
+       and     r1,r0,r1
+       rlwinm  r0,r3,26,13,21
+       or      r1,r0,r1
+
+/* 32-bit PTEG address generation into r2 */
+       andis.  r2,r3,0xfe00
+       rlwimi  r2,r1,6,7,25
+
+       xor     r1,r1,r1
+       addi    r1,r1,8
+       mfspr   r3,SPR_PTEHI
+       addi    r2,r2,-8
+
+1:
+       mtctr   r1
+2:
+       lwzu    r1,8(r2)      /* get next pte */
+       cmp     0,r1,r3
+       bdnzf   eq,2b
+       beq     1f           /* found */
+
+       andi.   r1,r3,0x0040   /* see if we have done second hash */
+.ifnb data
+       bne     do_dsi
+.else
+       bne     do_isi
+.endif
+       mfspr   r0,SPR_TLBMISS /* EA of access that missed */
+       rlwinm  r0,r0,20,16,3  /* mask out lower 16 bits of EA */
+       mfspr   r1,SPR_PTEHI   /* PTEHI[1:24] has the VSID */
+       rlwinm  r1,r1,25,8,31  /* mask out uppder 23 bits of VSID */
+
+       xor     r1,r0,r1       /* primary hash */
+       mfsdr1  r3
+       rlwinm  r0,r3,10,13,31  /* align HTMEXT and HTABMASK fields */
+       ori     r0,r0,0x3ff     /* mask out HTMEXT and HTABMASK */
+       and     r1,r0,r1
+       rlwinm  r0,r3,26,13,21
+       or      r1,r0,r1
+
+/* 32-bit PTEG address generation into r2 */
+       andis.  r2,r3,0xfe00
+       rlwimi  r2,r1,6,7,25
+
+       ori     r3,r3,0x0040
+       addi    r1,r0,8
+       addi    r2,r2,-8
+       b       1b
+
+1:
+.endm
+
 #undef ULONG_SIZE
 #undef stl
 #undef ll
@@ -329,9 +403,16 @@ ILLEGAL_VECTOR( 0xd00 )
 ILLEGAL_VECTOR( 0xe00 )
 ILLEGAL_VECTOR( 0xf00 )
 ILLEGAL_VECTOR( 0xf20 )
-ILLEGAL_VECTOR( 0x1000 )
-ILLEGAL_VECTOR( 0x1100 )
-ILLEGAL_VECTOR( 0x1200 )
+
+VECTOR( 0x1000, "IFTLB" ):
+       b       insn_tlb_miss
+
+VECTOR( 0x1100, "DLTLB" ):
+       b       data_load_tlb_miss
+
+VECTOR( 0x1200, "DSTLB" ):
+       b       data_store_tlb_miss
+
 ILLEGAL_VECTOR( 0x1300 )
 ILLEGAL_VECTOR( 0x1400 )
 ILLEGAL_VECTOR( 0x1500 )
@@ -373,6 +454,155 @@ real_isi:
 exception_return:
        EXCEPTION_EPILOGUE
 
+/*
+ * Instruction TLB miss
+ * Entry:
+ *       srr0    -> address of instruction that missed
+ *       srr1    -> 16:31 = saved MSR
+ *       TLBMISS -> ea that missed
+ *       PTEHI   -> upper 32-bits of pte value
+ *       PTELO   -> lower 32-bits of pte value
+ */
+insn_tlb_miss:
+       EXCEPTION_PREAMBLE
+       mtsprg3 r1             /* save ABI frame, we might call into C later */
+
+       ITLB_SEARCH
+
+/* pte found*/
+       lwz     r1,4(r2)          /* load tlb entry lower-word */
+       andi.   r3,r1,8           /* check G-bit */
+       bne     isi_prot          /* if guarded, take an ISI */
+
+       ori     r1,r1,0x100       /* set reference bit */
+       mtspr   SPR_PTELO,r1      /* put rpn into PTELO */
+       mfspr   r0,SPR_TLBMISS
+       tlbli   r0                /* load the itlb */
+       srwi    r1,r1,8           /* get byte 7 of pte */
+       stb     r1,6(r2)          /* update page table */
+
+       mfsprg3 r1           /* restore C ABI stack */
+       b exception_return
+
+/* Guarded memory protection violation: synthesize an ISI exception */
+isi_prot:
+       mfsrr1  r3
+       andi.   r2,r3,0xffff /* clean upper SRR1 */
+       addis   r2,r2,0x0800 /* protection violation flag */
+       b       1f
+
+do_isi:
+       mfsrr1  r3
+       andi.   r2,r3,0xffff
+       addis   r2,r2,0x4000 /* pte not found flag */
+       mtsrr1  r2
+       mtcrf   0x80,r3
+1:
+       mfsprg3 r1           /* restore C ABI stack */
+       LOAD_REG_FUNC(r3, isi_exception)
+       mtctr   r3
+       bctrl
+       b exception_return
+
+/*
+ * Data Load TLB miss
+ * Entry:
+ *       srr0    -> address of instruction that caused data tlb miss
+ *       srr1    -> 16:31 = saved MSR
+ *       TLBMISS -> ea that missed
+ *       PTEHI   -> upper 32-bits of pte value
+ *       PTELO   -> lower 32-bits of pte value
+ */
+data_load_tlb_miss:
+       EXCEPTION_PREAMBLE
+       mtsprg3 r1             /* save ABI frame, we might call into C later */
+
+       DTLB_SEARCH
+
+/* pte found */
+       lwz     r1,4(r2)       /* load tlb entry lower-word */
+       ori     r1,r1,0x100    /* set reference bit */
+       mtspr   SPR_PTELO,r1   /* put RPN into PTELO */
+       mfspr   r0,SPR_TLBMISS
+       tlbld   r0             /* load the dtlb */
+       srwi    r1,r1,8        /* get byte 7 of pte */
+       stb     r1,6(r2)       /* update page table */
+
+       mfsprg3 r1             /* restore C ABI stack */
+       b exception_return
+
+/*
+ * Data Store TLB miss
+ * Entry:
+ *       srr0    -> address of instruction that caused data tlb miss
+ *       srr1    -> 16:31 = saved MSR
+ *       TLBMISS -> ea that missed
+ *       PTEHI   -> upper 32-bits of pte value
+ *       PTELO   -> lower 32-bits of pte value
+ */
+data_store_tlb_miss:
+       EXCEPTION_PREAMBLE
+       mtsprg3 r1             /* save ABI frame, we might call into C later */
+
+       DTLB_SEARCH
+
+/* pte found */
+       lwz     r1,4(r2)               /* load tlb entry lower-word */
+       andi.   r3,r1,0x80             /* check the C-bit */
+       beq     data_store_prot_check  /* if (C==0) go check protection modes */
+3:
+       ori     r1,r1,0x180     /* set reference and change bit */
+       mtspr   SPR_PTELO,r1    /* put RPN into PTELO */
+       mfspr   r0,SPR_TLBMISS
+       xori    r0,r0,0x01      /* toggle LRU bit */
+       tlbld   r0              /* load the dtlb */
+       sth     r1,6(r2)        /* update page table */
+
+       mfsprg3 r1             /* restore C ABI stack */
+       b exception_return
+
+data_store_prot_check:
+       rlwinm. r3,r1,30,0,1  /* test PP */
+       bge-    1f            /* if (PP==00 or PP==01) go check KEY bit */
+       andi.   r3,r1,1       /* test PP[0] */
+       beq+    3b            /* return if PP[0]==0 */
+       b       dsi_prot
+1:
+       mfsrr1  r3
+       andis.  r3,r3,0x0008  /* test the KEY bit (SRR1-bit 12) */
+       ble     3b
+
+dsi_prot:
+       mfsrr1  r3
+       rlwinm  r1,r3,9,6,6  /* copy load/store bit over */
+       addis   r1,r1,0x0800 /* protection violation flag */
+       b       2f
+
+do_dsi:
+       mfsrr1  r3
+       rlwinm  r1,r3,9,6,6   /* copy load/store bit over */
+       addis   r1,r1,0x4000  /* pte not found */
+
+2:
+       andis.  r2,r3,0x0200  /* save the Altivec Avail. bit in r2 */
+       andi.   r3,r3,0xffff  /* clear upper SRR1 */
+       or      r2,r2,r3
+       mtsrr1  r2
+       mtdsisr r1
+       mfspr   r1,SPR_TLBMISS
+       rlwinm  r1,r1,0,0,30   /* Clear the LRU bit */
+       rlwinm. r2,r2,0,31,31  /* test LE bit */
+       beq     3f
+       xori    r1,r1,0x07
+3:
+       mtdar   r1
+       mtcrf   0x80,r3
+       mfsprg3 r1           /* restore C ABI stack */
+       LOAD_REG_FUNC(r3, dsi_exception)
+       mtctr   r3
+       bctrl
+       b exception_return
+
 GLOBL(__vectors_end):
 
 /************************************************************************/
-- 
2.29.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]