All of lore.kernel.org
 help / color / mirror / Atom feed
* TLB mapping questions
@ 2003-04-19  5:32 Erik J. Green
  2003-04-19 14:48 ` Ralf Baechle
  0 siblings, 1 reply; 5+ messages in thread
From: Erik J. Green @ 2003-04-19  5:32 UTC (permalink / raw)
  To: linux-mips

Hello again, I have more newbie questions for you all.


I *think* I understand how the TLB translates addresses for ckseg2 in mips64. 
Can someone tell me if my understanding is correct?  

Given: Physical memory starts at 0x0000000020004000;

Therefore, an offset 0x2000 from the start of physical memory should be at 

0x0000000020006000, or 0xa000000020006000 as a 64 bit xkphys address.

So if I construct a TLB entry such that cp0_entryhi is 0xffffffffc0002000, and
cp0_entrylo0 has a PFN address of 0x0000000020006, giving it the correct ASID
(0) and valid bitflags(VG), I should be able to access the physical memory
offset above using the ckseg2 virtual address 0xffffffffc0002000?  

Again, if I understand this, the physical address to be referenced will be
constructed from the low order 12 bits of the ckseg2 address (in this case 000)
and the pfn address stored in the TLB entry giving 0x0000000020006000, which is
the physical RAM address.  This is provided that I've constructed the TLB entry
correctly so that it's matched for the address reference given.

Of course, the reason I discuss all this is that the above doesn't work. =)  



Erik 


-- 
Erik J. Green
erik@greendragon.org

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: TLB mapping questions
  2003-04-19  5:32 TLB mapping questions Erik J. Green
@ 2003-04-19 14:48 ` Ralf Baechle
  2003-04-20  2:30   ` Erik J. Green
  0 siblings, 1 reply; 5+ messages in thread
From: Ralf Baechle @ 2003-04-19 14:48 UTC (permalink / raw)
  To: Erik J. Green; +Cc: linux-mips

On Sat, Apr 19, 2003 at 05:32:50AM +0000, Erik J. Green wrote:

> I *think* I understand how the TLB translates addresses for ckseg2 in mips64. 
> Can someone tell me if my understanding is correct?  
> 
> Given: Physical memory starts at 0x0000000020004000;
> 
> Therefore, an offset 0x2000 from the start of physical memory should be at 
> 
> 0x0000000020006000, or 0xa000000020006000 as a 64 bit xkphys address.
> 
> So if I construct a TLB entry such that cp0_entryhi is 0xffffffffc0002000, and
> cp0_entrylo0 has a PFN address of 0x0000000020006, giving it the correct ASID
> (0) and valid bitflags(VG), I should be able to access the physical memory
> offset above using the ckseg2 virtual address 0xffffffffc0002000?  

You also want to set the dirty flag or otherwise the page is not writable.

Which page size have you been using?

The physical address must be a multiple of the page size of the page and
the virtual address must be a multiple of the double of the page size of
entry - remember that each TLB entry maps a pair of adjacent pages!

The entrylo value is computed by shifting the physical address right by
6 bits then inserting the right flag bits into the low 6 bits.  In your
case you want to set the valid, dirty and global bits.  You also need to
set the 3 coherency bits.  We want cachable coherent, the same mode as
used in the 0xa8... portion of XKPHYS.  So we set them to 5.  So:

 c0_entrylo0 = (phyaddr >> 6) | cacheable_coherent | dirty | valid | global

 c0_entrylo0 = 0x800180 | 0x28 | 0x4 | 0x2 | 0x1

 c0_entrylo0 = 0x8001af

An extra word about the global bit - there exists only one global bit in
the TLB entry though both c0_entrylo0 and c0_entrylo1 have a global bit.
The way this works is that the global bit of the TLB entry is written
as tlb[entry].g = (c0_entrylo0.g & c0_entrylo1.g) when writing an entry
and when read is copied into both entrylo global bits.  In other words
writing a TLB entry with only one of the G bits in the entrylo register
pair set will result in a TLB entry with the G bit cleared.

For your example this means:

  c0_entryhi   = 0xc0000000:00002000
  c0_entrylo0  = 0x00000000:008001af
  c0_entrylo1  = 0x00000000:00000001
  c0_pagemask  = 0x00000000				# 4kB pages
  c0_framemask = 0x00000000
  c0_index     = 0x00000000
  c0_wired     = 0x00000001
  tlbwi

would generated the mapping and make sure the entry won't be overwritten
by random TLB writes.

> Of course, the reason I discuss all this is that the above doesn't work. =)  

Every Linux port has started in a state as advanced as where you are so
keep up :-)

  Ralf

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: TLB mapping questions
  2003-04-19 14:48 ` Ralf Baechle
@ 2003-04-20  2:30   ` Erik J. Green
  2003-04-20  3:38     ` TLB mapping questions (followup q) Erik J. Green
  0 siblings, 1 reply; 5+ messages in thread
From: Erik J. Green @ 2003-04-20  2:30 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Quoting Ralf Baechle <ralf@linux-mips.org>:TLB_SE
> > So if I construct a TLB entry such that cp0_entryhi is 0xffffffffc0002000,
> and
> > cp0_entrylo0 has a PFN address of 0x0000000020006, giving it the correct
> ASID
> > (0) and valid bitflags(VG), I should be able to access the physical memory
> > offset above using the ckseg2 virtual address 0xffffffffc0002000?
> 
> You also want to set the dirty flag or otherwise the page is not writable.

That's ok for the first page, it's code only.  The second page mapped by the
entry is data, so I'll set the D bit on that.

> 
> Which page size have you been using?

16 megabyte

> 
> The physical address must be a multiple of the page size of the page and
> the virtual address must be a multiple of the double of the page size of
> entry - remember that each TLB entry maps a pair of adjacent pages!

This was my main problem - after I rounded my physical load address up to the
next 16M boundary: 0xa800000021000000 and adjusted the LOADADDRESS in my
makefile to point to the beginning of ckseg2 (the address of which is a multiple
of 32M) I am now able to jump into the ckseg2 code successfully.

> The entrylo value is computed by shifting the physical address right by
> 6 bits then inserting the right flag bits into the low 6 bits.  In your
> case you want to set the valid, dirty and global bits.  You also need to
> set the 3 coherency bits.  We want cachable coherent, the same mode as
> used in the 0xa8... portion of XKPHYS.  So we set them to 5.  So:
> 
>  c0_entrylo0 = (phyaddr >> 6) | cacheable_coherent | dirty | valid | global
> 
>  c0_entrylo0 = 0x800180 | 0x28 | 0x4 | 0x2 | 0x1
> 
>  c0_entrylo0 = 0x8001af

These are the very bits I'm using.  I'm actually using a modded version of the
MAPPED_KERNEL_SETUP_TLB macro in head.S.

> An extra word about the global bit - there exists only one global bit in

I made a note of this paragraph, will do some reading on it.

> would generated the mapping and make sure the entry won't be overwritten
> by random TLB writes.

Yes, CP0_WIRED is getting set to 1 to protect this entry.

> 
> > Of course, the reason I discuss all this is that the above doesn't work. =)
> 
> Every Linux port has started in a state as advanced as where you are so
> keep up :-)

I will do so =)  My next problem is getting the stack working.

Erik



> 
>   Ralf


-- 
Erik J. Green
erik@greendragon.org

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: TLB mapping questions (followup q)
  2003-04-20  2:30   ` Erik J. Green
@ 2003-04-20  3:38     ` Erik J. Green
  2003-04-20  4:20       ` Erik J. Green
  0 siblings, 1 reply; 5+ messages in thread
From: Erik J. Green @ 2003-04-20  3:38 UTC (permalink / raw)
  To: linux-mips@linux-mips.org

Quoting "Erik J. Green" <erik@greendragon.org>:
> 
> That's ok for the first page, it's code only.  The second page mapped by the
> entry is data, so I'll set the D bit on that.

A followup question:  my stack is working now that I've set the D flag in the
TLB entry, allowing writes to that page.  From what I can tell, the
MAPPED_KERNEL_SETUP_TLB macro in head.S actually creates two nearly identical
halves for the new TLB entry it creates, except the half in ENTRYLO1 has the D
bit set.  My problem with the stack code was that the address the stack pointer
was being saved to (ok, really more of an addressing problem than a stack
problem) was within that first (16MB) page of memory, which couldn't be written
until I set the D bit.  

How can this work in the existing head.S for a mapped kernel?  Wouldn't other
machines have the same problem, where the location for kernelsp is within the
non-writeable segment? 

Erik



PS: Code from the current (few days old CVS) head.S:

       .macro MAPPED_KERNEL_SETUP_TLB
#ifdef CONFIG_MAPPED_KERNEL
        /*
         * This needs to read the nasid - assume 0 for now.
         * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0,
         * 0+DVG in tlblo_1.
         */
        dli     t0, 0xffffffffc0000000
        dmtc0   t0, CP0_ENTRYHI
        li      t0, 0x1c000             # Offset of text into node memory
        dsll    t1, NASID_SHFT          # Shift text nasid into place
        dsll    t2, NASID_SHFT          # Same for data nasid
        or      t1, t1, t0              # Physical load address of kernel text
        or      t2, t2, t0              # Physical load address of kernel data
        dsrl    t1, 12                  # 4K pfn
        dsrl    t2, 12                  # 4K pfn
        dsll    t1, 6                   # Get pfn into place
        dsll    t2, 6                   # Get pfn into place
        li      t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6)
        or      t0, t0, t1
        mtc0    t0, CP0_ENTRYLO0        # physaddr, VG, cach exlwr
        li      t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW)
>> 6)
        or      t0, t0, t2
        mtc0    t0, CP0_ENTRYLO1        # physaddr, DVG, cach exlwr
        li      t0, 0x1ffe000           # MAPPED_KERN_TLBMASK, TLBPGMASK_16M
        mtc0    t0, CP0_PAGEMASK
        li      t0, 0                   # KMAP_INX
        mtc0    t0, CP0_INDEX
        li      t0, 1
        mtc0    t0, CP0_WIRED
        tlbwi
#else
        mtc0    zero, CP0_WIRED
#endif
        .endm



-- 
Erik J. Green
erik@greendragon.org

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: TLB mapping questions (followup q)
  2003-04-20  3:38     ` TLB mapping questions (followup q) Erik J. Green
@ 2003-04-20  4:20       ` Erik J. Green
  0 siblings, 0 replies; 5+ messages in thread
From: Erik J. Green @ 2003-04-20  4:20 UTC (permalink / raw)
  To: linux-mips

Quoting "Erik J. Green" <erik@greendragon.org>:

> How can this work in the existing head.S for a mapped kernel?  Wouldn't other
> machines have the same problem, where the location for kernelsp is within the
> non-writeable segment?
> 


And a followup to my followup: =)

Later in the boot, in tlb-andes.c, the andes_tlb_init function re-sets CP0_wired
to 0 (and pagemask to 4k), then the local_flush_tlb_all function overwrites the
TLB entry for the kernel, causing an immediate halt to things.

Am I correct in thinking the 16M page size initally set up in head.S (with
CONFIG_MAPPED_KERNEL=1) was so the mapped kernel could get to the point of
setting up the TLB "for real" later on?  If so, how is the switch to 4k pages
supposed to work?  I can see the existing code working if local_tlb_flush_all is
running out of unmapped memory, but in my case I would think the "starter" TLB
entry would need to be preserved until a replacement is created.

Thanks again,
Erik



-- 
Erik J. Green
erik@greendragon.org

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-04-20  4:20 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-04-19  5:32 TLB mapping questions Erik J. Green
2003-04-19 14:48 ` Ralf Baechle
2003-04-20  2:30   ` Erik J. Green
2003-04-20  3:38     ` TLB mapping questions (followup q) Erik J. Green
2003-04-20  4:20       ` Erik J. Green

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.