mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-05-22 15:13:47 +00:00
powerpc/8xx: Update TLB asm so it behaves as linux mm expects.
Update the TLB asm to make proper use of _PAGE_DIRY and _PAGE_ACCESSED. Get rid of _PAGE_HWWRITE too. Pros: - I/D TLB Miss never needs to write to the linux pte. - _PAGE_ACCESSED is only set on TLB Error fixing accounting - _PAGE_DIRTY is mapped to 0x100, the changed bit, and is set directly when a page has been made dirty. - Proper RO/RW mapping of user space. - Free up 2 SW TLB bits in the linux pte(add back _PAGE_WRITETHRU ?) - kernel RO/user NA support. Cons: - A few more instructions in the TLB Miss routines. Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
5efab4a02c
commit
fe11dc3f96
2 changed files with 57 additions and 55 deletions
|
@ -33,21 +33,20 @@
|
||||||
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
|
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
|
||||||
#define _PAGE_SHARED 0x0004 /* No ASID (context) compare */
|
#define _PAGE_SHARED 0x0004 /* No ASID (context) compare */
|
||||||
#define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */
|
#define _PAGE_SPECIAL 0x0008 /* SW entry, forced to 0 by the TLB miss */
|
||||||
|
#define _PAGE_DIRTY 0x0100 /* C: page changed */
|
||||||
|
|
||||||
/* These five software bits must be masked out when the entry is loaded
|
/* These 3 software bits must be masked out when the entry is loaded
|
||||||
* into the TLB.
|
* into the TLB, 2 SW bits left.
|
||||||
*/
|
*/
|
||||||
#define _PAGE_GUARDED 0x0010 /* software: guarded access */
|
#define _PAGE_GUARDED 0x0010 /* software: guarded access */
|
||||||
#define _PAGE_DIRTY 0x0020 /* software: page changed */
|
#define _PAGE_ACCESSED 0x0020 /* software: page referenced */
|
||||||
#define _PAGE_RW 0x0040 /* software: user write access allowed */
|
|
||||||
#define _PAGE_ACCESSED 0x0080 /* software: page referenced */
|
|
||||||
|
|
||||||
/* Setting any bits in the nibble with the follow two controls will
|
/* Setting any bits in the nibble with the follow two controls will
|
||||||
* require a TLB exception handler change. It is assumed unused bits
|
* require a TLB exception handler change. It is assumed unused bits
|
||||||
* are always zero.
|
* are always zero.
|
||||||
*/
|
*/
|
||||||
#define _PAGE_HWWRITE 0x0100 /* h/w write enable: never set in Linux PTE */
|
#define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */
|
||||||
#define _PAGE_USER 0x0800 /* One of the PP bits, the other is USER&~RW */
|
#define _PAGE_USER 0x0800 /* msb PP bits */
|
||||||
|
|
||||||
#define _PMD_PRESENT 0x0001
|
#define _PMD_PRESENT 0x0001
|
||||||
#define _PMD_BAD 0x0ff0
|
#define _PMD_BAD 0x0ff0
|
||||||
|
|
|
@ -333,26 +333,20 @@ InstructionTLBMiss:
|
||||||
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
|
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
|
||||||
lwz r10, 0(r11) /* Get the pte */
|
lwz r10, 0(r11) /* Get the pte */
|
||||||
|
|
||||||
#ifdef CONFIG_SWAP
|
andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT
|
||||||
/* do not set the _PAGE_ACCESSED bit of a non-present page */
|
cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT
|
||||||
andi. r11, r10, _PAGE_PRESENT
|
bne- cr0, 2f
|
||||||
beq 4f
|
|
||||||
ori r10, r10, _PAGE_ACCESSED
|
/* Clear PP lsb, 0x400 */
|
||||||
mfspr r11, SPRN_MD_TWC /* get the pte address again */
|
rlwinm r10, r10, 0, 22, 20
|
||||||
stw r10, 0(r11)
|
|
||||||
4:
|
|
||||||
#else
|
|
||||||
ori r10, r10, _PAGE_ACCESSED
|
|
||||||
stw r10, 0(r11)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||||
* Software indicator bits 21, 22 and 28 must be clear.
|
* Software indicator bits 22 and 28 must be clear.
|
||||||
* Software indicator bits 24, 25, 26, and 27 must be
|
* Software indicator bits 24, 25, 26, and 27 must be
|
||||||
* set. All other Linux PTE bits control the behavior
|
* set. All other Linux PTE bits control the behavior
|
||||||
* of the MMU.
|
* of the MMU.
|
||||||
*/
|
*/
|
||||||
2: li r11, 0x00f0
|
li r11, 0x00f0
|
||||||
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
|
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
|
||||||
DO_8xx_CPU6(0x2d80, r3)
|
DO_8xx_CPU6(0x2d80, r3)
|
||||||
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
|
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
|
||||||
|
@ -365,6 +359,22 @@ InstructionTLBMiss:
|
||||||
lwz r3, 8(r0)
|
lwz r3, 8(r0)
|
||||||
#endif
|
#endif
|
||||||
rfi
|
rfi
|
||||||
|
2:
|
||||||
|
mfspr r11, SPRN_SRR1
|
||||||
|
/* clear all error bits as TLB Miss
|
||||||
|
* sets a few unconditionally
|
||||||
|
*/
|
||||||
|
rlwinm r11, r11, 0, 0xffff
|
||||||
|
mtspr SPRN_SRR1, r11
|
||||||
|
|
||||||
|
mfspr r10, SPRN_M_TW /* Restore registers */
|
||||||
|
lwz r11, 0(r0)
|
||||||
|
mtcr r11
|
||||||
|
lwz r11, 4(r0)
|
||||||
|
#ifdef CONFIG_8xx_CPU6
|
||||||
|
lwz r3, 8(r0)
|
||||||
|
#endif
|
||||||
|
b InstructionAccess
|
||||||
|
|
||||||
. = 0x1200
|
. = 0x1200
|
||||||
DataStoreTLBMiss:
|
DataStoreTLBMiss:
|
||||||
|
@ -409,21 +419,27 @@ DataStoreTLBMiss:
|
||||||
DO_8xx_CPU6(0x3b80, r3)
|
DO_8xx_CPU6(0x3b80, r3)
|
||||||
mtspr SPRN_MD_TWC, r11
|
mtspr SPRN_MD_TWC, r11
|
||||||
|
|
||||||
#ifdef CONFIG_SWAP
|
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
|
||||||
/* do not set the _PAGE_ACCESSED bit of a non-present page */
|
* We also need to know if the insn is a load/store, so:
|
||||||
andi. r11, r10, _PAGE_PRESENT
|
* Clear _PAGE_PRESENT and load that which will
|
||||||
beq 4f
|
* trap into DTLB Error with store bit set accordinly.
|
||||||
ori r10, r10, _PAGE_ACCESSED
|
*/
|
||||||
4:
|
/* PRESENT=0x1, ACCESSED=0x20
|
||||||
/* and update pte in table */
|
* r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
|
||||||
#else
|
* r10 = (r10 & ~PRESENT) | r11;
|
||||||
ori r10, r10, _PAGE_ACCESSED
|
*/
|
||||||
#endif
|
rlwinm r11, r10, 32-5, 31, 31
|
||||||
mfspr r11, SPRN_MD_TWC /* get the pte address again */
|
and r11, r11, r10
|
||||||
stw r10, 0(r11)
|
rlwimi r10, r11, 0, 31, 31
|
||||||
|
|
||||||
|
/* Honour kernel RO, User NA */
|
||||||
|
andi. r11, r10, _PAGE_USER | _PAGE_RW
|
||||||
|
bne- cr0, 5f
|
||||||
|
ori r10,r10, 0x200 /* Extended encoding, bit 22 */
|
||||||
|
5: xori r10, r10, _PAGE_RW /* invert RW bit */
|
||||||
|
|
||||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||||
* Software indicator bits 21, 22 and 28 must be clear.
|
* Software indicator bits 22 and 28 must be clear.
|
||||||
* Software indicator bits 24, 25, 26, and 27 must be
|
* Software indicator bits 24, 25, 26, and 27 must be
|
||||||
* set. All other Linux PTE bits control the behavior
|
* set. All other Linux PTE bits control the behavior
|
||||||
* of the MMU.
|
* of the MMU.
|
||||||
|
@ -469,11 +485,12 @@ DataTLBError:
|
||||||
stw r10, 0(r0)
|
stw r10, 0(r0)
|
||||||
stw r11, 4(r0)
|
stw r11, 4(r0)
|
||||||
|
|
||||||
/* First, make sure this was a store operation.
|
mfspr r11, SPRN_DSISR
|
||||||
|
andis. r11, r11, 0x4800 /* !translation or protection */
|
||||||
|
bne 2f /* branch if either is set */
|
||||||
|
/* Only Change bit left now, do it here as it is faster
|
||||||
|
* than trapping to the C fault handler.
|
||||||
*/
|
*/
|
||||||
mfspr r10, SPRN_DSISR
|
|
||||||
andis. r11, r10, 0x0200 /* If set, indicates store op */
|
|
||||||
beq 2f
|
|
||||||
|
|
||||||
/* The EA of a data TLB miss is automatically stored in the MD_EPN
|
/* The EA of a data TLB miss is automatically stored in the MD_EPN
|
||||||
* register. The EA of a data TLB error is automatically stored in
|
* register. The EA of a data TLB error is automatically stored in
|
||||||
|
@ -522,26 +539,12 @@ DataTLBError:
|
||||||
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
|
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
|
||||||
lwz r10, 0(r11) /* Get the pte */
|
lwz r10, 0(r11) /* Get the pte */
|
||||||
|
|
||||||
andi. r11, r10, _PAGE_RW /* Is it writeable? */
|
ori r10, r10, _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HWWRITE
|
||||||
beq 2f /* Bail out if not */
|
|
||||||
|
|
||||||
/* Update 'changed', among others.
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_SWAP
|
|
||||||
ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE
|
|
||||||
/* do not set the _PAGE_ACCESSED bit of a non-present page */
|
|
||||||
andi. r11, r10, _PAGE_PRESENT
|
|
||||||
beq 4f
|
|
||||||
ori r10, r10, _PAGE_ACCESSED
|
|
||||||
4:
|
|
||||||
#else
|
|
||||||
ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
|
|
||||||
#endif
|
|
||||||
mfspr r11, SPRN_MD_TWC /* Get pte address again */
|
|
||||||
stw r10, 0(r11) /* and update pte in table */
|
stw r10, 0(r11) /* and update pte in table */
|
||||||
|
xori r10, r10, _PAGE_RW /* RW bit is inverted */
|
||||||
|
|
||||||
/* The Linux PTE won't go exactly into the MMU TLB.
|
/* The Linux PTE won't go exactly into the MMU TLB.
|
||||||
* Software indicator bits 21, 22 and 28 must be clear.
|
* Software indicator bits 22 and 28 must be clear.
|
||||||
* Software indicator bits 24, 25, 26, and 27 must be
|
* Software indicator bits 24, 25, 26, and 27 must be
|
||||||
* set. All other Linux PTE bits control the behavior
|
* set. All other Linux PTE bits control the behavior
|
||||||
* of the MMU.
|
* of the MMU.
|
||||||
|
|
Loading…
Add table
Reference in a new issue