summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel/head_8xx.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/kernel/head_8xx.S')
-rw-r--r--arch/ppc/kernel/head_8xx.S176
1 files changed, 122 insertions, 54 deletions
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index 83f276585..59b8a49c6 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -136,7 +136,7 @@ __start:
mtspr DC_CST, r8
lis r8, IDC_ENABLE@h
mtspr IC_CST, r8
-#if 0
+#ifdef CONFIG_8xx_COPYBACK
mtspr DC_CST, r8
#else
/* For a debug option, I left this here to easily enable
@@ -356,15 +356,26 @@ SystemCall:
* only perform the attribute functions.
*/
InstructionTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, SRR0 /* Get effective address of fault */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3780
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_EPN, r20 /* Have to use MD_EPN for walk, MI_EPN can't */
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load the MI_TWC with the attributes
@@ -372,88 +383,131 @@ InstructionTLBMiss:
*/
tophys(r21,r21)
ori r21,r21,1 /* Set valid bit */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_TWC, r21 /* Set page attributes */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
+#if 0
+ ori r20, r20, _PAGE_ACCESSED
+ stw r20, 0(r21)
+#endif
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MI_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b InstructionAccess
. = 0x1200
DataStoreTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
- mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ mfspr r20, MD_TWC /* ....and get the pte address */
+ lwz r20, 0(r20) /* Get the pte */
+
+ /* Insert the Guarded flag into the TWC from the Linux PTE.
+ * It is bit 27 of both the Linux PTE and the TWC (at least
+ * I got that right :-). It will be better when we can put
+ * this into the Linux pgd/pmd and load it in the operation
+ * above.
+ */
+ rlwimi r21, r20, 0, 27, 27
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
+ mtspr MD_TWC, r21
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+#if 0
+ ori r20, r20, 0x00f0
+#else
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#endif
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
/* This is an instruction TLB error on the MPC8xx. This could be due
@@ -474,6 +528,12 @@ InstructionTLBError:
*/
. = 0x1400
DataTLBError:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
@@ -487,52 +547,59 @@ DataTLBError:
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, bail */
/* We have a pte table, so fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
- andi. r20, r21, _PAGE_RW /* Is it writeable? */
+ andi. r21, r20, _PAGE_RW /* Is it writeable? */
beq 2f /* Bail out if not */
- ori r21, r21, _PAGE_DIRTY /* Update changed bit */
- mfspr r20, MD_TWC /* Get pte address again */
- stw r21, 0(r20) /* and update pte in table */
+ /* Update 'changed', among others.
+ */
+ ori r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED
+ mfspr r21, MD_TWC /* Get pte address again */
+ stw r20, 0(r21) /* and update pte in table */
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2:
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
STD_EXCEPTION(0x1500, Trap_15, UnknownException)
@@ -542,6 +609,7 @@ DataTLBError:
STD_EXCEPTION(0x1900, Trap_19, UnknownException)
STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+
/* On the MPC8xx, these next four traps are used for development
* support of breakpoints and such. Someday I will get around to
* using them.