Re: Using emap for i386/amd64 early during boot
Jean-Yves Migeon jeanyves.mig...@free.fr wrote: Agree with David's point, but it should not be done at function level. Rather higher level interface abstraction. In uvmplock branch, I have already split some x86 pmap bits into pmap_tlb.c and xen_pmap.c modules. More interfaces can be abstracted in respect to e.g. Xen. ... Is pmap.c expected to be split in two files too (pmap.c and x86_pmap.c?) I noticed that in your pmap.c, some functions (already found in xen_pmap.c) are #ifndef XEN out, to avoid conflict I suppose. Not into pmap.c and x86_pmap.c - it is already x86. :) But yes, some helper routines which tend to differ between i386 and amd64 might be abstracted into separate {i386,amd64}_pmap.c modules. However, I am thinking of higher level abstractions first, for example - splitting page table management code into pmap_pt.c and making it a clearer interface. -- Mindaugas
Re: Using emap for i386/amd64 early during boot
Jean-Yves Migeon jeanyves.mig...@free.fr wrote: As I have yet to understand the inner workings of emap, I'd like to know if it is possible to wrap i386_cpu_switch_pmap() around uvm_emap functions, like this: [...] u_int gen = uvm_emap_gen_return(); i386_cpu_switch_pmap(pmap); uvm_emap_update(gen); [...] Sure. Both calls just get/update the generation numbers (see uvm_emap.c). However, there are some thoughts to revisit current UVM emap, so I would suggest you to not spend much time on this (i.e. you can just skip these calls around TLB flushes for now). -- Mindaugas
Re: Using emap for i386/amd64 early during boot
On Sun, Jun 20, 2010 at 07:45:32PM +0200, Jean-Yves Migeon wrote: For convenience, here's i386_cpu_switch_pmap: I know that a lot of legacy code uses the preprocessor the way that you have in i386_cpu_switch_pmap(), but I don't think that the preprocessor should be used in that way any longer. In my experience, code that uses the preprocessor heavily is harder to read and to change and to test. Why don't you let config(1) and ld(1) do the work that the preprocessor does? For example: file switch_pmap_pae_xen.c pae xen /* * Switches pmap for the current CPU. Hides the implementation * differences between the PAE and non-PAE cases. */ void i386_cpu_switch_pmap(struct pmap *pmap) { int i; int s = splvm(); /* just to be safe */ struct cpu_info *ci = curcpu(); paddr_t l3_pd = xpmap_ptom_masked(ci-ci_l3_pdirpa); /* don't update the kernel L3 slot */ for (i = 0 ; i PDP_SIZE - 1; i++) { xpq_queue_pte_update(l3_pd + i * sizeof(pd_entry_t), xpmap_ptom(pmap-pm_pdirpa[i]) | PG_V); } splx(s); u_int gen = uvm_emap_gen_return(); tlbflush(); uvm_emap_update(gen); } file switch_pmap_pae.c pae !xen /* * Switches pmap for the current CPU. Hides the implementation * differences between the PAE and non-PAE cases. */ void i386_cpu_switch_pmap(struct pmap *pmap) { int i; int s = splvm(); /* just to be safe */ struct cpu_info *ci = curcpu(); pd_entry_t *l3_pd = ci-ci_l3_pdir; for (i = 0 ; i PDP_SIZE; i++) { l3_pd[i] = pmap-pm_pdirpa[i] | PG_V; } splx(s); u_int gen = uvm_emap_gen_return(); tlbflush(); uvm_emap_update(gen); } file switch_pmap.c !pae /* * Switches pmap for the current CPU. Hides the implementation * differences between the PAE and non-PAE cases. */ void i386_cpu_switch_pmap(struct pmap *pmap) { u_int gen = uvm_emap_gen_return(); lcr3(pmap_pdirpa(pmap, 0)); uvm_emap_update(gen); } -- David Young OJC Technologies dyo...@ojctech.com Urbana, IL * (217) 278-3933
Re: Using emap for i386/amd64 early during boot
On 20.06.2010 22:19, David Young wrote: On Sun, Jun 20, 2010 at 07:45:32PM +0200, Jean-Yves Migeon wrote: For convenience, here's i386_cpu_switch_pmap: I know that a lot of legacy code uses the preprocessor the way that you have in i386_cpu_switch_pmap(), but I don't think that the preprocessor should be used in that way any longer. In my experience, code that uses the preprocessor heavily is harder to read and to change and to test. Why don't you let config(1) and ld(1) do the work that the preprocessor does? For example: [snip] I like that. Will do. Thanks! -- Jean-Yves Migeon jeanyves.mig...@free.fr
Re: Using emap for i386/amd64 early during boot
On 20.06.2010 20:00, Mindaugas Rasiukevicius wrote: Jean-Yves Migeonjeanyves.mig...@free.fr wrote: As I have yet to understand the inner workings of emap, I'd like to know if it is possible to wrap i386_cpu_switch_pmap() around uvm_emap functions, like this: [...] u_int gen = uvm_emap_gen_return(); i386_cpu_switch_pmap(pmap); uvm_emap_update(gen); [...] Sure. Both calls just get/update the generation numbers (see uvm_emap.c). However, there are some thoughts to revisit current UVM emap, so I would suggest you to not spend much time on this (i.e. you can just skip these calls around TLB flushes for now). Alright; then I'll go directly to benchmarking/regression testing, patch is in final state for me. Cheers, -- Jean-Yves Migeon jeanyves.mig...@free.fr
Re: Using emap for i386/amd64 early during boot
Jean-Yves Migeon jeanyves.mig...@free.fr wrote: I know that a lot of legacy code uses the preprocessor the way that you have in i386_cpu_switch_pmap(), but I don't think that the preprocessor should be used in that way any longer. In my experience, code that uses the preprocessor heavily is harder to read and to change and to test. Why don't you let config(1) and ld(1) do the work that the preprocessor does? For example: [snip] I like that. Will do. Thanks! Agree with David's point, but it should not be done at function level. Rather higher level interface abstraction. In uvmplock branch, I have already split some x86 pmap bits into pmap_tlb.c and xen_pmap.c modules. More interfaces can be abstracted in respect to e.g. Xen. -- Mindaugas
Re: Using emap for i386/amd64 early during boot
On 21.06.2010 00:39, Mindaugas Rasiukevicius wrote: Jean-Yves Migeonjeanyves.mig...@free.fr wrote: I know that a lot of legacy code uses the preprocessor the way that you have in i386_cpu_switch_pmap(), but I don't think that the preprocessor should be used in that way any longer. In my experience, code that uses the preprocessor heavily is harder to read and to change and to test. Why don't you let config(1) and ld(1) do the work that the preprocessor does? For example: [snip] I like that. Will do. Thanks! Agree with David's point, but it should not be done at function level. Rather higher level interface abstraction. In uvmplock branch, I have already split some x86 pmap bits into pmap_tlb.c and xen_pmap.c modules. More interfaces can be abstracted in respect to e.g. Xen. I just took a look: to avoid ugly #ifdef's, we have to handle 4 different scenarios for pmap switching: - i386 native, amd64 native, and i386 Xen (no-PAE) case, which all share the same piece of code (use of lcr3) - i386 PAE, not Xen: iterate through L3 entries, without Xen address physical = machine address translation - i386 PAE, Xen: same as above, but use P2M translations - amd64 Xen, where pmap code has some quirks to circumvent amd64 limitations regarding paravirtualization. I can split Xen and non-Xen case, but we will still have to distinguish i386 and amd64 case, as well as PAE/!PAE (within i386). Either we deal with it at function level and let config(1) handle that, or cpp(1). Choice is limited here :/ For your branch: * xen/x86/xen_pmap.c will contain the code for i386 (PAE !PAE), amd64, only for Xen * x86/x86/pmap.c will contain native i386 (PAE !PAE), and amd64. Is pmap.c expected to be split in two files too (pmap.c and x86_pmap.c?) I noticed that in your pmap.c, some functions (already found in xen_pmap.c) are #ifndef XEN out, to avoid conflict I suppose. -- Jean-Yves Migeon jeanyves.mig...@free.fr