Re: [Milkymist port] virtual memory management

2014-02-20 Thread Yann Sionneau

Le 18/02/14 13:48, Joerg Sonnenberger a écrit :

On Tue, Feb 18, 2014 at 12:54:05PM +0100, Yann Sionneau wrote:

Is there somewhere a function like vaddr_t map_paddr(paddr_t, prot)?

uvm_km_alloc with UVM_KMF_VAONLY can be used to allocate the VA,
pmap_kenter_pa to map a given physical address. Don't forget to call
pmap_update(pmap_kernel()) afterwards. A simple example is
arch/x86/x86/mpbios.c, mpbios_map.

Joerg
Thank you Matt and Joerg for your very quick answer, for now I 
implemented as Joerg said, but I imagine that the clean way is to use 
bus_space(9), right?


Anyway, it works very well now :)

From now on I need to debug an infinite loop, it seems that since 
cold = 0 (after configure2() ran), any printf (which calls kprintf then 
putchar then logputchar) will end up in a dead lock:


logputchar() is calling mutex_spin_exit(), the latter is calling 
turnstile_exit() which in turn is calling mutex_spin_exit() as well, 
then it goes on and on.

I didn't figure out yet what's going on.

Cheers,

--
Yann Sionneau


Re: [Milkymist port] virtual memory management

2014-02-18 Thread Yann Sionneau

Le 10/02/14 23:00, Yann Sionneau a écrit :
Thanks for all your explanations, if everything I said here is correct 
(which would mean I understood correctly your answer) then I think I'm 
ready to implement all this :)


Hi,

I have made good progress on the NetBSD port, it is now booting up to 
enabling interrupts and cpu_initclocks() call, see the boot log [0].


But then I am wondering how I can map the memory mapped registers of the 
timer0 of Milkymist SoC in order to use it as the main ticking clock.


Basically, I need to map physical address 0xe000.1000 somewhere in 
kernel virtual memory.


Is there somewhere a function like vaddr_t map_paddr(paddr_t, prot)?

I could indeed walk the kernel page table and insert somewhere in a free 
PTE (a NULL one) a reference to the 0xe000.1000 physical address, but 
then how to be sure that the vm subsystem will not allocate this virtual 
address twice?


Is there an iomapping mechanism?

Thank you for your help :)

[0] -- http://pastebin.com/MYitt9L4

Best regards,

--
Yann Sionneau


Re: [Milkymist port] virtual memory management

2014-02-18 Thread Joerg Sonnenberger
On Tue, Feb 18, 2014 at 12:54:05PM +0100, Yann Sionneau wrote:
 Is there somewhere a function like vaddr_t map_paddr(paddr_t, prot)?

uvm_km_alloc with UVM_KMF_VAONLY can be used to allocate the VA,
pmap_kenter_pa to map a given physical address. Don't forget to call
pmap_update(pmap_kernel()) afterwards. A simple example is
arch/x86/x86/mpbios.c, mpbios_map.

Joerg


Re: [Milkymist port] virtual memory management

2014-02-18 Thread Matt Thomas

On Feb 18, 2014, at 3:54 AM, Yann Sionneau yann.sionn...@gmail.com wrote:

 Le 10/02/14 23:00, Yann Sionneau a écrit :
 Thanks for all your explanations, if everything I said here is correct 
 (which would mean I understood correctly your answer) then I think I'm ready 
 to implement all this :)
 
 Hi,
 
 I have made good progress on the NetBSD port, it is now booting up to 
 enabling interrupts and cpu_initclocks() call, see the boot log [0].
 
 But then I am wondering how I can map the memory mapped registers of the 
 timer0 of Milkymist SoC in order to use it as the main ticking clock.
 
 Basically, I need to map physical address 0xe000.1000 somewhere in kernel 
 virtual memory.
 
 Is there somewhere a function like vaddr_t map_paddr(paddr_t, prot)?
 
 I could indeed walk the kernel page table and insert somewhere in a free PTE 
 (a NULL one) a reference to the 0xe000.1000 physical address, but then how to 
 be sure that the vm subsystem will not allocate this virtual address twice?
 
 Is there an iomapping mechanism?
 
 Thank you for your help :)
 
 [0] -- http://pastebin.com/MYitt9L4

see bus_space(9), specifically bus_space_map.

internally, it allocates some KVA via uvm and uses pmap_kenter_pa to 
map the I/O address via the allocated KVA.



Re: [Milkymist port] virtual memory management

2014-02-10 Thread Eduardo Horvath
On Sun, 9 Feb 2014, Yann Sionneau wrote:

 Thank you for your answer Matt,
 
 Le 09/02/14 19:49, Matt Thomas a écrit :
  On Feb 9, 2014, at 10:07 AM, Yann Sionneau yann.sionn...@gmail.com wrote:


   Since the kernel runs with MMU on, using virtual addresses, it cannot
   dereference physical pointers then it cannot add/modify/remove PTEs,
   right?
  Wrong.  See above.
 You mean that the TLB contains entries which map a physical address to itself?
 like 0xabcd. is mapped to 0xabcd.? Or you mean all RAM is always
 mapped but to the (0xa000.000+physical_pframe) kind of virtual address you
 mention later in your reply?

What I did for BookE is reserve the low half of the kernel address space 
for VA=PA mappings.  The kernel resides in the high half of the address 
space.  I did this because the existing PPC port did strange things with 
BAT registers to access physical memory and copyin/copyout operations and 
I couldn't come up with a better way to do something compatible with the 
BookE MMU.  It did limit the machine to 2GB RAM, which wasn't a problem 
for the 405GP.

Also, the user address space is not shared with the kernel address space 
as on most machines.  Instead, user processes get access to their own 4GB 
address space, and the kernel has 2GB to play with when you deduct the 2GB 
VA==PA region.  (It's the same sort of thing I did for sparc64 way back 
when it was running 32-bit userland.  But it doesn't need VA==PA mappings 
and can access physical and userland addresses while the kernel address 
space is active.  Much nicer design.)

When a BookE machine takes an MMU miss fault, the fault handler examines 
the faulting address if the high bit is zero, it synthesizes a TLB entry 
where the physical address is the same as the virtual address.  If the 
high bit is set, it walks the page tables to find the TLB entry.

This did make the copyin/copyout operations a bit complicated since it 
requires flipping the MMU between two contexts while doing the copy 
operation.

   Also, is it possible to make sure that everything (in kernel space) is
   mapped so that virtual_addr = physical_addr - RAM_START_ADDR +
   virtual_offset
   In my case RAM_START_ADDR is 0x4000 and I am trying to use
   virtual_offset of 0xc000 (everything in my kernel ELF binary is mapped
   at virtual address starting at 0xc000)
   If I can ensure that this formula is always correct I can then use a very
   simple macro to translate statically a physical address to a virtual
   address.
  Not knowing how much ram you have, I can only speak in generalities.
 I have 128 MB of RAM.
  But in general you reserve a part of the address space for direct mapped
  memory and then place the kernel about that.
  
  For instance, you might have 512MB of RAM which you map at 0xa000.
  and then have the kernel's mapped va space start at 0xc000..
 So if I understand correctly, the first page of physical ram (0x4000.) is
 mapped at virtual address 0xa000. *and* at 0xc000. ?
 Isn't it a problem that a physical address is mapped twice in the same process
 (here the kernel)?
 My caches are VIPT, couldn't it generate cache aliases issues?

If the MMU is always on while the kernel is running, and covers all of the 
KVA, then you could relocate the kernel text and data segments wherever 
you want them to be.  If you want to put the kernel text and data segments 
in the direct-mapped range, you can easily do that.  If you want it 
elsewhere, that should work too.  

The cache aliasing issues in VIPT caches only occur if the cache way size 
is larger than the page size.  If you're designing your own hardware, 
don't do that.  Otherwise, remember to only access a page through a single 
mapping and you won't have aliasing issues.  And flush the page from the 
cache wenever establishing a new mapping.

Eduardo

Re: [Milkymist port] virtual memory management

2014-02-10 Thread Yann Sionneau

Le 10/02/14 18:10, Eduardo Horvath a écrit :

On Sun, 9 Feb 2014, Yann Sionneau wrote:


Thank you for your answer Matt,

Le 09/02/14 19:49, Matt Thomas a écrit :

On Feb 9, 2014, at 10:07 AM, Yann Sionneau yann.sionn...@gmail.com wrote:



Since the kernel runs with MMU on, using virtual addresses, it cannot
dereference physical pointers then it cannot add/modify/remove PTEs,
right?

Wrong.  See above.

You mean that the TLB contains entries which map a physical address to itself?
like 0xabcd. is mapped to 0xabcd.? Or you mean all RAM is always
mapped but to the (0xa000.000+physical_pframe) kind of virtual address you
mention later in your reply?

What I did for BookE is reserve the low half of the kernel address space
for VA=PA mappings.  The kernel resides in the high half of the address
space.  I did this because the existing PPC port did strange things with
BAT registers to access physical memory and copyin/copyout operations and
I couldn't come up with a better way to do something compatible with the
BookE MMU.  It did limit the machine to 2GB RAM, which wasn't a problem
for the 405GP.

Also, the user address space is not shared with the kernel address space
as on most machines.  Instead, user processes get access to their own 4GB
address space, and the kernel has 2GB to play with when you deduct the 2GB
VA==PA region.  (It's the same sort of thing I did for sparc64 way back
when it was running 32-bit userland.  But it doesn't need VA==PA mappings
and can access physical and userland addresses while the kernel address
space is active.  Much nicer design.)

When a BookE machine takes an MMU miss fault, the fault handler examines
the faulting address if the high bit is zero, it synthesizes a TLB entry
where the physical address is the same as the virtual address.  If the
high bit is set, it walks the page tables to find the TLB entry.

This did make the copyin/copyout operations a bit complicated since it
requires flipping the MMU between two contexts while doing the copy
operation.


Also, is it possible to make sure that everything (in kernel space) is
mapped so that virtual_addr = physical_addr - RAM_START_ADDR +
virtual_offset
In my case RAM_START_ADDR is 0x4000 and I am trying to use
virtual_offset of 0xc000 (everything in my kernel ELF binary is mapped
at virtual address starting at 0xc000)
If I can ensure that this formula is always correct I can then use a very
simple macro to translate statically a physical address to a virtual
address.

Not knowing how much ram you have, I can only speak in generalities.

I have 128 MB of RAM.

But in general you reserve a part of the address space for direct mapped
memory and then place the kernel about that.

For instance, you might have 512MB of RAM which you map at 0xa000.
and then have the kernel's mapped va space start at 0xc000..

So if I understand correctly, the first page of physical ram (0x4000.) is
mapped at virtual address 0xa000. *and* at 0xc000. ?
Isn't it a problem that a physical address is mapped twice in the same process
(here the kernel)?
My caches are VIPT, couldn't it generate cache aliases issues?

If the MMU is always on while the kernel is running, and covers all of the
KVA, then you could relocate the kernel text and data segments wherever
you want them to be.  If you want to put the kernel text and data segments
in the direct-mapped range, you can easily do that.  If you want it
elsewhere, that should work too.

So if I understand correctly I could implement the following scheme:

Let my linker put the kernel ELF virtual addresses to 0xc000.. Load 
the kernel at base of RAM (0x4000.)
Then reserve this memory region as a window over physical ram : 
0xc000.-0xc800. (ram size is 128 MB) by doing something like 
physseg[0].avail_start = 0xc800.; in pmap_bootstrap()


Then in my tlb miss handlers I could do:

if (fault happened in kernel mode) /* we don't want user space to access 
all ram through the kernel window */

{
if ( (miss_vaddr   0xc800)  (miss_vaddr = 0xc000) ) /* 
= this would be kind of like your test of the high bit of the faulty 
vaddr */

{
reload_tlb_with(atop(miss_vaddr), atop(miss_vaddr - 0xc000 
+ 0x4000) | some_flags); /* = create the mapping for accessing the 
window */

return_from_exception;
}
} else {
- access the page table to reload tlb
- page table contains only physical addresses
- but I can dereference those using the 0xc000.-0xc800. 
window knowing that a nested tlb miss can happen

}

Does this sound reasonable ?



The cache aliasing issues in VIPT caches only occur if the cache way size
is larger than the page size.  If you're designing your own hardware,
don't do that.  Otherwise, remember to only access a page through a single
mapping and you won't have aliasing issues.  And flush the page from the
cache wenever establishing a new mapping.
Well, lm32 caches are configurable but 

Re: [Milkymist port] virtual memory management

2014-02-10 Thread Matt Thomas

On Feb 10, 2014, at 9:10 AM, Eduardo Horvath e...@netbsd.org wrote:

 On Sun, 9 Feb 2014, Yann Sionneau wrote:
 
 Thank you for your answer Matt,
 
 Le 09/02/14 19:49, Matt Thomas a écrit :
 On Feb 9, 2014, at 10:07 AM, Yann Sionneau yann.sionn...@gmail.com wrote:
 
 
 Since the kernel runs with MMU on, using virtual addresses, it cannot
 dereference physical pointers then it cannot add/modify/remove PTEs,
 right?
 Wrong.  See above.
 You mean that the TLB contains entries which map a physical address to 
 itself?
 like 0xabcd. is mapped to 0xabcd.? Or you mean all RAM is always
 mapped but to the (0xa000.000+physical_pframe) kind of virtual address you
 mention later in your reply?
 
 What I did for BookE is reserve the low half of the kernel address space 
 for VA=PA mappings.  The kernel resides in the high half of the address 
 space.  I did this because the existing PPC port did strange things with 
 BAT registers to access physical memory and copyin/copyout operations and 
 I couldn't come up with a better way to do something compatible with the 
 BookE MMU.  It did limit the machine to 2GB RAM, which wasn't a problem 
 for the 405GP.

For the MPC85xx, I did something similar but I used fixed TLB1 entries
to map the physical ram 1:1 with VA=PA mappings.

 Also, the user address space is not shared with the kernel address space 
 as on most machines.  Instead, user processes get access to their own 4GB 
 address space, and the kernel has 2GB to play with when you deduct the 2GB 
 VA==PA region.  (It's the same sort of thing I did for sparc64 way back 
 when it was running 32-bit userland.  But it doesn't need VA==PA mappings 
 and can access physical and userland addresses while the kernel address 
 space is active.  Much nicer design.)

BookE could have avoided the VA==PA mappings but it simplifies a lot of things.

 When a BookE machine takes an MMU miss fault, the fault handler examines 
 the faulting address if the high bit is zero, it synthesizes a TLB entry 
 where the physical address is the same as the virtual address.  If the 
 high bit is set, it walks the page tables to find the TLB entry.

Not true for the MPC85xx BookE.  Then a trap happens, the PSL[PR] bit gets
reset along with the PSL[DS] and PSL[IS] bits.  This forces the MMU to only
match the match TLB entries with a MAS1[TS] == 0 (e.g. kernel TLB entries).

 This did make the copyin/copyout operations a bit complicated since it 
 requires flipping the MMU between two contexts while doing the copy 
 operation.

Well, for the MPC85xx, I only set the PSL[DS] bit so I can access the
user address space, load/store stuff to/from register, and then reset it back.
It's not as fast as I'd like but it works.

 Also, is it possible to make sure that everything (in kernel space) is
 mapped so that virtual_addr = physical_addr - RAM_START_ADDR +
 virtual_offset
 In my case RAM_START_ADDR is 0x4000 and I am trying to use
 virtual_offset of 0xc000 (everything in my kernel ELF binary is mapped
 at virtual address starting at 0xc000)
 If I can ensure that this formula is always correct I can then use a very
 simple macro to translate statically a physical address to a virtual
 address.
 Not knowing how much ram you have, I can only speak in generalities.
 I have 128 MB of RAM.
 But in general you reserve a part of the address space for direct mapped
 memory and then place the kernel about that.
 
 For instance, you might have 512MB of RAM which you map at 0xa000.
 and then have the kernel's mapped va space start at 0xc000..
 So if I understand correctly, the first page of physical ram (0x4000.) is
 mapped at virtual address 0xa000. *and* at 0xc000. ?
 Isn't it a problem that a physical address is mapped twice in the same 
 process
 (here the kernel)?
 My caches are VIPT, couldn't it generate cache aliases issues?
 
 If the MMU is always on while the kernel is running, and covers all of the 
 KVA, then you could relocate the kernel text and data segments wherever 
 you want them to be.  If you want to put the kernel text and data segments 
 in the direct-mapped range, you can easily do that.  If you want it 
 elsewhere, that should work too.  

In fast, I'd recommend doing that.  Leaving the mapped KVA space for those
things that need to dynamically mapped.

 The cache aliasing issues in VIPT caches only occur if the cache way size 
 is larger than the page size.  If you're designing your own hardware, 
 don't do that.  Otherwise, remember to only access a page through a single 
 mapping and you won't have aliasing issues.  And flush the page from the 
 cache wenever establishing a new mapping.

I agree.  You can play other games with VIPT but it becomes complex quickly.

Re: [Milkymist port] virtual memory management

2014-02-10 Thread Matt Thomas

On Feb 10, 2014, at 2:00 PM, Yann Sionneau yann.sionn...@gmail.com wrote:

 So if I understand correctly I could implement the following scheme:
 
 Let my linker put the kernel ELF virtual addresses to 0xc000.. Load the 
 kernel at base of RAM (0x4000.)
 Then reserve this memory region as a window over physical ram : 
 0xc000.-0xc800. (ram size is 128 MB) by doing something like 
 physseg[0].avail_start = 0xc800.; in pmap_bootstrap()
 
 Then in my tlb miss handlers I could do:
 
 if (fault happened in kernel mode) /* we don't want user space to access all 
 ram through the kernel window */
 {
if ( (miss_vaddr   0xc800)  (miss_vaddr = 0xc000) ) /* = this 
 would be kind of like your test of the high bit of the faulty vaddr */
{
reload_tlb_with(atop(miss_vaddr), atop(miss_vaddr - 0xc000 + 
 0x4000) | some_flags); /* = create the mapping for accessing the window 
 */

atop(miss_vaddr ^ 0x800) :)

return_from_exception;
}
 } else {
- access the page table to reload tlb
- page table contains only physical addresses
- but I can dereference those using the 0xc000.-0xc800. window 
 knowing that a nested tlb miss can happen
 }

I'd leave the page_table using virtual addresses but since they will all
be direct mapped, simply convert to them to physical before using them.

That way, when the kernel is running with the TLB enabled (which is most
of the time), it can traverse the page tables normally.

 Does this sound reasonable ?
 
 
 The cache aliasing issues in VIPT caches only occur if the cache way size
 is larger than the page size.  If you're designing your own hardware,
 don't do that.  Otherwise, remember to only access a page through a single
 mapping and you won't have aliasing issues.  And flush the page from the
 cache wenever establishing a new mapping.
 Well, lm32 caches are configurable but for the Milkymist SoC they are not 
 configured too big such that there is no alias problem.
 In order to handle all cases of lm32 cache sizes I guess I need to add a 
 macro that the machine headers will define if there are cache alias issues 
 possible.
 But then if I am using the 0xc000.-0xc800. window during my tlb miss 
 handler I guess I will have no choice but to invalidate the cache because any 
 fault while reading this window will then add a tlb entry to this window 
 which would possibly cause a physical page to be mapped twice and then could 
 cause alias issues (in the scenario where caches are too big).

Hopefully, if they make the caches larger they increase the number of ways.
I wouldn't add code to flush.  Just add a panic if you detect you can have
aliases and deal with it if it ever happens.



Re: [Milkymist port] virtual memory management

2014-02-10 Thread David Laight
On Mon, Feb 10, 2014 at 02:38:27PM -0800, Matt Thomas wrote:
 Hopefully, if they make the caches larger they increase the number of ways.
 I wouldn't add code to flush.  Just add a panic if you detect you can have
 aliases and deal with it if it ever happens.

IIRC A lot of sparc systems have VIPT caches where the cache size
(divided by the ways) is much larger than a page size (IIRC at least 64k).

If memory has to be mapped at different VA (eg in different processes)
then it is best to pick VA so that the data hits the correct part of the
cache.  Otherwise it has to be mapped uncached.

I guess another solution is to use logical pages that are the right size.

David

-- 
David Laight: da...@l8s.co.uk


Re: [Milkymist port] virtual memory management

2014-02-09 Thread Yann Sionneau

Hello Eduardo,

Le 30/05/13 22:45, Eduardo Horvath a écrit :

On Wed, 29 May 2013, Yann Sionneau wrote:


Hello NetBSD fellows,

As I mentioned in my previous e-mail, I may need from time to time a little
bit of help since this is my first full featured OS port.

I am wondering how I can manage virtual memory (especially how to avoid tlb
miss, or deal with them) in exception handlers.

There are essentially three ways to do this.  Which one you chose depends
on the hardware.

1) Turn off the MMU on exception

2) Keep parts of the address space untranslated

3) Lock important pages into the TLB


Turning off the MMU is pretty straight-forward.  ISTR the PowerPC Book E
processors do this.  Just look up the TLB entry in the table and return
from exception.  You just have to make sure that the kernel manages page
tables using physical addresses.
This seems like the easiest thing to do (because I won't have to think 
about recursive faults) but then if I put physical addresses in my 1st 
level page table, how does the kernel manage the page table entries?
Since the kernel runs with MMU on, using virtual addresses, it cannot 
dereference physical pointers then it cannot add/modify/remove PTEs, right?
I'm sure there is some kernel internal mechanism that I don't know about 
which could help me getting the virtual address from the physical one, 
do you know which mechanism it would be?


Also, is it possible to make sure that everything (in kernel space) is 
mapped so that virtual_addr = physical_addr - RAM_START_ADDR + 
virtual_offset
In my case RAM_START_ADDR is 0x4000 and I am trying to use 
virtual_offset of 0xc000 (everything in my kernel ELF binary is 
mapped at virtual address starting at 0xc000)
If I can ensure that this formula is always correct I can then use a 
very simple macro to translate statically a physical address to a 
virtual address.


Then I have another question, who is supposed to build the kernel's page 
table? pmap_bootstrap()?
If so, then how do I allocate pages for that purpose? using 
pmap_pte_pagealloc() and pmap_segtab_init() ?


FYI I am using those files for my pmap:

uvm/pmap/pmap.c
uvm/pmap/pmap_segtab.c
uvm/pmap/pmap_tlb.c

I am taking inspiration from the PPC Book-E (mpc85xx) code.

Thanks !

Regards,

--
Yann


Re: [Milkymist port] virtual memory management

2014-02-09 Thread Matt Thomas

On Feb 9, 2014, at 10:07 AM, Yann Sionneau yann.sionn...@gmail.com wrote:

 This seems like the easiest thing to do (because I won't have to think about 
 recursive faults) but then if I put physical addresses in my 1st level page 
 table, how does the kernel manage the page table entries?

BookE always has the MMU on and contains fixed TLB entries to make sure
all of physical ram is always mapped.

 Since the kernel runs with MMU on, using virtual addresses, it cannot 
 dereference physical pointers then it cannot add/modify/remove PTEs, right?

Wrong.  See above.  Note that on BookE, PTEs are purely a software 
construction and the H/W never reads them directly.

 I'm sure there is some kernel internal mechanism that I don't know about 
 which could help me getting the virtual address from the physical one, do you 
 know which mechanism it would be?

Look at __HAVE_MM_MD_DIRECT_MAPPED_PHYS and/or PMAP_{MAP,UNMAP}_POOLPAGE.


 Also, is it possible to make sure that everything (in kernel space) is mapped 
 so that virtual_addr = physical_addr - RAM_START_ADDR + virtual_offset
 In my case RAM_START_ADDR is 0x4000 and I am trying to use virtual_offset 
 of 0xc000 (everything in my kernel ELF binary is mapped at virtual 
 address starting at 0xc000)
 If I can ensure that this formula is always correct I can then use a very 
 simple macro to translate statically a physical address to a virtual 
 address.

Not knowing how much ram you have, I can only speak in generalities. 
But in general you reserve a part of the address space for direct mapped
memory and then place the kernel about that.

For instance, you might have 512MB of RAM which you map at 0xa000.
and then have the kernel's mapped va space start at 0xc000..

Then conversion to from PA to VA is just adding a constant while getting
the PA from a direct mapped VA is just subtraction.

 Then I have another question, who is supposed to build the kernel's page 
 table? pmap_bootstrap()?

Some part of MD code.  pmap_bootstrap() could be that.

 If so, then how do I allocate pages for that purpose? using 
 pmap_pte_pagealloc() and pmap_segtab_init() ?

usually you use pmap_steal_memory to do that.
But for mpc85xx I just allocate the kernel initial segmap in the .bss.
But the page tables were from allocated using uvm can do prebootstrap
allocations.

 
 FYI I am using those files for my pmap:
 
 uvm/pmap/pmap.c
 uvm/pmap/pmap_segtab.c
 uvm/pmap/pmap_tlb.c
 
 I am taking inspiration from the PPC Book-E (mpc85xx) code.



Re: [Milkymist port] virtual memory management

2014-02-09 Thread Yann Sionneau

Thank you for your answer Matt,

Le 09/02/14 19:49, Matt Thomas a écrit :

On Feb 9, 2014, at 10:07 AM, Yann Sionneau yann.sionn...@gmail.com wrote:


This seems like the easiest thing to do (because I won't have to think about 
recursive faults) but then if I put physical addresses in my 1st level page 
table, how does the kernel manage the page table entries?

BookE always has the MMU on and contains fixed TLB entries to make sure
all of physical ram is always mapped.
My TLB hardware is very simple and does not give me the option to fix 
a TLB entry so I won't be able to do that.
the lm32 MMU is turned off upon exception (tlb miss for instance) 
automatically, then I can enable it back if I want. In the end the MMU 
is enabled back upon return from exception.



Since the kernel runs with MMU on, using virtual addresses, it cannot 
dereference physical pointers then it cannot add/modify/remove PTEs, right?

Wrong.  See above.
You mean that the TLB contains entries which map a physical address to 
itself? like 0xabcd. is mapped to 0xabcd.? Or you mean all RAM 
is always mapped but to the (0xa000.000+physical_pframe) kind of virtual 
address you mention later in your reply?

Note that on BookE, PTEs are purely a software
construction and the H/W never reads them directly.
Here my HW is like BookE, I don't have hardware page tree walker, PTEs 
are only for the software to reload the TLB when there is an exception 
(tlb miss), TLB will never read memory to find PTE in my lm32 MMU 
implementation.



I'm sure there is some kernel internal mechanism that I don't know about which 
could help me getting the virtual address from the physical one, do you know 
which mechanism it would be?

Look at __HAVE_MM_MD_DIRECT_MAPPED_PHYS and/or PMAP_{MAP,UNMAP}_POOLPAGE.

For now I have something like that:

vaddr_t
pmap_md_map_poolpage(paddr_t pa, vsize_t size)
{
  const vaddr_t sva = (vaddr_t) pa - 0x4000 + 0xc000;
  return sva;
}

But I guess it only works to access the content of kernel ELF (text and 
data) but not to access dynamic runtime kernel allocations, right?




Also, is it possible to make sure that everything (in kernel space) is mapped 
so that virtual_addr = physical_addr - RAM_START_ADDR + virtual_offset
In my case RAM_START_ADDR is 0x4000 and I am trying to use virtual_offset 
of 0xc000 (everything in my kernel ELF binary is mapped at virtual address 
starting at 0xc000)
If I can ensure that this formula is always correct I can then use a very simple macro to 
translate statically a physical address to a virtual address.

Not knowing how much ram you have, I can only speak in generalities.

I have 128 MB of RAM.

But in general you reserve a part of the address space for direct mapped
memory and then place the kernel about that.

For instance, you might have 512MB of RAM which you map at 0xa000.
and then have the kernel's mapped va space start at 0xc000..
So if I understand correctly, the first page of physical ram 
(0x4000.) is mapped at virtual address 0xa000. *and* at 
0xc000. ?
Isn't it a problem that a physical address is mapped twice in the same 
process (here the kernel)?

My caches are VIPT, couldn't it generate cache aliases issues?


Then conversion to from PA to VA is just adding a constant while getting
the PA from a direct mapped VA is just subtraction.


Then I have another question, who is supposed to build the kernel's page table? 
pmap_bootstrap()?

Some part of MD code.  pmap_bootstrap() could be that.


If so, then how do I allocate pages for that purpose? using 
pmap_pte_pagealloc() and pmap_segtab_init() ?

usually you use pmap_steal_memory to do that.
But for mpc85xx I just allocate the kernel initial segmap in the .bss.
But the page tables were from allocated using uvm can do prebootstrap
allocations.

Are you referring to the following code?

  /*
   * Now actually allocate the kernel PTE array (must be done
   * after virtual_end is initialized).
   */
  const vaddr_t kv_segtabs = avail[0].start;
  KASSERT(kv_segtabs == endkernel);
  KASSERT(avail[0].size = NBPG * kv_nsegtabs);
  printf( kv_nsegtabs=%#PRIxVSIZE, kv_nsegtabs);
  printf( kv_segtabs=%#PRIxVADDR, kv_segtabs);
  avail[0].start += NBPG * kv_nsegtabs;
  avail[0].size -= NBPG * kv_nsegtabs;
  endkernel += NBPG * kv_nsegtabs;

  /*
   * Initialize the kernel's two-level page level.  This only wastes
   * an extra page for the segment table and allows the user/kernel
   * access to be common.
   */
  pt_entry_t **ptp = stp-seg_tab[VM_MIN_KERNEL_ADDRESS  SEGSHIFT];
  pt_entry_t *ptep = (void *)kv_segtabs;
  memset(ptep, 0, NBPG * kv_nsegtabs);
  for (size_t i = 0; i  kv_nsegtabs; i++, ptep += NPTEPG) {
*ptp++ = ptep;
  }



FYI I am using those files for my pmap:

uvm/pmap/pmap.c
uvm/pmap/pmap_segtab.c
uvm/pmap/pmap_tlb.c

I am taking inspiration from the PPC Book-E (mpc85xx) code.

Regards,

--
Yann


Re: [Milkymist port] virtual memory management

2013-05-30 Thread David Holland
On Wed, May 29, 2013 at 07:51:15PM +0200, Yann Sionneau wrote:
  I am wondering how I can manage virtual memory (especially how to
  avoid tlb miss, or deal with them) in exception handlers.
  
  At first my idea was to do most of the low level stuff in exception
  handlers with MMU turned off, I was told it was a very bad idea.
  LM32 MMU (for now at least) turns itself off upon any CPU
  exception, therefore I plan on turning it on right away in the
  exception handler.
  
  This leads to the following scenario I don't know how to deal with:
  [snip]

hold on, hold on. What's the high-level picture? Does the kernel
normally run with the MMU on or off? What's the intended scheme for
TLB refill? Are the page tables supposed to be mapped in virtual
memory (mips, vax) or placed in physical memory (x86)?

-- 
David A. Holland
dholl...@netbsd.org