Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
hi York, On 06/10/2014 02:15 AM, Mark Rutland wrote: Hi, Apologies for the delay in replying. On Fri, Jun 06, 2014 at 11:14:23PM +0100, York Sun wrote: On 06/06/2014 01:17 PM, York Sun wrote: On 06/06/2014 10:32 AM, Mark Rutland wrote: How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Mark, I appreciate the reminder. I tried on our emulator. With inner share set for TCR SH0 bits, u-boot works with the flushing, but doesn't work without flushing. It went to exception. Can you share more information about the inner share? I need to follow up with our designer to confirm. A second thought, do I need to set the first MMU table so DDR is inner shareable? I assume you mean configuring MAIR_ELx such that the mapping covering DDR is cacheable for the inner shareable domain? If so, yes. Mark, I tried both inner share and outer. It doesn't work without flushing the cache. I will keep this part of code until I learn otherwise. York The shareability attribute is different with cacheablilty attribute, it means whether the memory region would be accessed by other processors. If a memory region is configured as non sharable the access will not be snooped but still can be cached. It is the situation that current u-boot-armv8 used due to only master processor is active. If secondary processors also access the same memory region it should be configured as inner-sharable or outer-sharable otherwise the cache coherence between processors will not be maintained. The above is what I know. Wish this could help. David ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/18/2014 07:09 AM, feng...@phytium.com.cn wrote: hi York, On 06/10/2014 02:15 AM, Mark Rutland wrote: Hi, Apologies for the delay in replying. On Fri, Jun 06, 2014 at 11:14:23PM +0100, York Sun wrote: On 06/06/2014 01:17 PM, York Sun wrote: On 06/06/2014 10:32 AM, Mark Rutland wrote: How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Mark, I appreciate the reminder. I tried on our emulator. With inner share set for TCR SH0 bits, u-boot works with the flushing, but doesn't work without flushing. It went to exception. Can you share more information about the inner share? I need to follow up with our designer to confirm. A second thought, do I need to set the first MMU table so DDR is inner shareable? I assume you mean configuring MAIR_ELx such that the mapping covering DDR is cacheable for the inner shareable domain? If so, yes. Mark, I tried both inner share and outer. It doesn't work without flushing the cache. I will keep this part of code until I learn otherwise. York The shareability attribute is different with cacheablilty attribute, it means whether the memory region would be accessed by other processors. If a memory region is configured as non sharable the access will not be snooped but still can be cached. It is the situation that current u-boot-armv8 used due to only master processor is active. If secondary processors also access the same memory region it should be configured as inner-sharable or outer-sharable otherwise the cache coherence between processors will not be maintained. The above is what I know. Wish this could help. David, Thanks for chime in. It is not clear to me if I can put a new MMU table in d-cache and have MMU fetch from the d-cache. I tried several ways but it doesn't work. York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/10/2014 02:15 AM, Mark Rutland wrote: Hi, Apologies for the delay in replying. On Fri, Jun 06, 2014 at 11:14:23PM +0100, York Sun wrote: On 06/06/2014 01:17 PM, York Sun wrote: On 06/06/2014 10:32 AM, Mark Rutland wrote: How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Mark, I appreciate the reminder. I tried on our emulator. With inner share set for TCR SH0 bits, u-boot works with the flushing, but doesn't work without flushing. It went to exception. Can you share more information about the inner share? I need to follow up with our designer to confirm. A second thought, do I need to set the first MMU table so DDR is inner shareable? I assume you mean configuring MAIR_ELx such that the mapping covering DDR is cacheable for the inner shareable domain? If so, yes. Mark, I tried both inner share and outer. It doesn't work without flushing the cache. I will keep this part of code until I learn otherwise. York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
Hi, Apologies for the delay in replying. On Fri, Jun 06, 2014 at 11:14:23PM +0100, York Sun wrote: On 06/06/2014 01:17 PM, York Sun wrote: On 06/06/2014 10:32 AM, Mark Rutland wrote: How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Mark, I appreciate the reminder. I tried on our emulator. With inner share set for TCR SH0 bits, u-boot works with the flushing, but doesn't work without flushing. It went to exception. Can you share more information about the inner share? I need to follow up with our designer to confirm. A second thought, do I need to set the first MMU table so DDR is inner shareable? I assume you mean configuring MAIR_ELx such that the mapping covering DDR is cacheable for the inner shareable domain? If so, yes. Cheers, Mark. ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/10/2014 02:15 AM, Mark Rutland wrote: Hi, Apologies for the delay in replying. On Fri, Jun 06, 2014 at 11:14:23PM +0100, York Sun wrote: On 06/06/2014 01:17 PM, York Sun wrote: On 06/06/2014 10:32 AM, Mark Rutland wrote: How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Mark, I appreciate the reminder. I tried on our emulator. With inner share set for TCR SH0 bits, u-boot works with the flushing, but doesn't work without flushing. It went to exception. Can you share more information about the inner share? I need to follow up with our designer to confirm. A second thought, do I need to set the first MMU table so DDR is inner shareable? I assume you mean configuring MAIR_ELx such that the mapping covering DDR is cacheable for the inner shareable domain? If so, yes. Mark, I will continue to experiment this idea. In the meantime, please comment on my v6 patch set. York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
[...] What you need to do to replace the active set of tables (assuming that the new mapping has the instruction stream mapped in an identical way) is: - Write the tables. - DSB to make them visible to the MMU. - Write to the appropriate TTBR_*. - ISB to complete the write to the TTBR_*. - TLBI to invalidate the old mappings the the TLBs. - DSB to complete the TLBI. - If you've changed the instruction stream or system state that will affect the instruction stream, ISB to flush the CPU pipeline. Here is the flow I have (as of v5 patch) Write the tables (I removed dsb here in v5, need to add back) Write TTBR (I missed isb here, need to add) Flush dcache (otherwise the table will not be in DDR. Yes, I verified) This looks odd -- why do we need the tables to be in DDR? Why would we flush them here, when the address is partially visible to the MMU? This sounds odd but it actually makes sense. Let's say we have new tables created by u-boot. The new tables are in the address of DDR with D-cache enabled. If we don't flush the cache, the moment TLBs are invalidated, MMU will fetch the tables from TTBR which points to DDR. Without a valid TLB, MMU cannot get the table from D-cache, it has to fetch from the DDR directly. I have verified this by checking waveforms of the SoC and exercised code in both ways. How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. Cheers, Mark. ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On Thu, Jun 5, 2014 at 1:34 PM, York Sun york...@freescale.com wrote: On 06/05/2014 10:41 AM, Mark Rutland wrote: On Thu, Jun 05, 2014 at 04:07:17PM +0100, York Sun wrote: On 06/05/2014 03:09 AM, Mark Rutland wrote: [...] No objection here on the idea. But again this is not the case. My first MMU table is in SRAM, which is small and will be used for other purpose. The 2nd MMU table is in DDR. I could copy the table and do the maintenance as you said. For now, I want to stick with the static table and only create the API when I have to. Sure, if your tables are in SRAM then trying to do a load of dynamic allocation isn't going to work. Why do you need to turn on the MMU early using SRAM in the first place? Can't you delay that until after DDR setup? My fear is that while that sounds OK with a single user to do a quick havk and poke the tables directly, we'll end up with everyone doing that, and no-one will try to unify things. It is very diffifcult to unify such variation after the fact. That's a good reason. Let me start to code the API. It will take a while to cover the complexity of the multilevel tables and sizes. It will be a separated patch for later review. I don't want that to delay this patch set. I am hoping to get this set in for 2014.07 release. If I was maintainer I would say no because few people come back later to clean-up their mess. If you want to get platform support in now, perhaps you should just add the base platform first and add mmu setup later. Surely you don't need the MMU to just boot to u-boot shell. Rob ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/06/2014 05:33 AM, Mark Rutland wrote: [...] What you need to do to replace the active set of tables (assuming that the new mapping has the instruction stream mapped in an identical way) is: - Write the tables. - DSB to make them visible to the MMU. - Write to the appropriate TTBR_*. - ISB to complete the write to the TTBR_*. - TLBI to invalidate the old mappings the the TLBs. - DSB to complete the TLBI. - If you've changed the instruction stream or system state that will affect the instruction stream, ISB to flush the CPU pipeline. Here is the flow I have (as of v5 patch) Write the tables (I removed dsb here in v5, need to add back) Write TTBR (I missed isb here, need to add) Flush dcache (otherwise the table will not be in DDR. Yes, I verified) This looks odd -- why do we need the tables to be in DDR? Why would we flush them here, when the address is partially visible to the MMU? This sounds odd but it actually makes sense. Let's say we have new tables created by u-boot. The new tables are in the address of DDR with D-cache enabled. If we don't flush the cache, the moment TLBs are invalidated, MMU will fetch the tables from TTBR which points to DDR. Without a valid TLB, MMU cannot get the table from D-cache, it has to fetch from the DDR directly. I have verified this by checking waveforms of the SoC and exercised code in both ways. How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/06/2014 06:34 AM, Rob Herring wrote: On Thu, Jun 5, 2014 at 1:34 PM, York Sun york...@freescale.com wrote: On 06/05/2014 10:41 AM, Mark Rutland wrote: On Thu, Jun 05, 2014 at 04:07:17PM +0100, York Sun wrote: On 06/05/2014 03:09 AM, Mark Rutland wrote: [...] No objection here on the idea. But again this is not the case. My first MMU table is in SRAM, which is small and will be used for other purpose. The 2nd MMU table is in DDR. I could copy the table and do the maintenance as you said. For now, I want to stick with the static table and only create the API when I have to. Sure, if your tables are in SRAM then trying to do a load of dynamic allocation isn't going to work. Why do you need to turn on the MMU early using SRAM in the first place? Can't you delay that until after DDR setup? Logically yes. But it runs too slow without cache on emulator. My fear is that while that sounds OK with a single user to do a quick havk and poke the tables directly, we'll end up with everyone doing that, and no-one will try to unify things. It is very diffifcult to unify such variation after the fact. That's a good reason. Let me start to code the API. It will take a while to cover the complexity of the multilevel tables and sizes. It will be a separated patch for later review. I don't want that to delay this patch set. I am hoping to get this set in for 2014.07 release. If I was maintainer I would say no because few people come back later to clean-up their mess. If you want to get platform support in now, perhaps you should just add the base platform first and add mmu setup later. Surely you don't need the MMU to just boot to u-boot shell. My plan is to get the first platform in, then I will maintain Freescale stuff. So you can be sure I will continue to improve it. One reason to get these code in early is to enable our partners and early adopters to use u-boot. After all, this is the second ARMv8 platform. The first one vexpress_aemv8a doesn't even support cache. York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On Fri, Jun 06, 2014 at 07:52:44AM -0700, York Sun wrote: On 06/06/2014 06:34 AM, Rob Herring wrote: On Thu, Jun 5, 2014 at 1:34 PM, York Sun york...@freescale.com wrote: On 06/05/2014 10:41 AM, Mark Rutland wrote: On Thu, Jun 05, 2014 at 04:07:17PM +0100, York Sun wrote: On 06/05/2014 03:09 AM, Mark Rutland wrote: [...] No objection here on the idea. But again this is not the case. My first MMU table is in SRAM, which is small and will be used for other purpose. The 2nd MMU table is in DDR. I could copy the table and do the maintenance as you said. For now, I want to stick with the static table and only create the API when I have to. Sure, if your tables are in SRAM then trying to do a load of dynamic allocation isn't going to work. Why do you need to turn on the MMU early using SRAM in the first place? Can't you delay that until after DDR setup? Logically yes. But it runs too slow without cache on emulator. My fear is that while that sounds OK with a single user to do a quick havk and poke the tables directly, we'll end up with everyone doing that, and no-one will try to unify things. It is very diffifcult to unify such variation after the fact. That's a good reason. Let me start to code the API. It will take a while to cover the complexity of the multilevel tables and sizes. It will be a separated patch for later review. I don't want that to delay this patch set. I am hoping to get this set in for 2014.07 release. If I was maintainer I would say no because few people come back later to clean-up their mess. If you want to get platform support in now, perhaps you should just add the base platform first and add mmu setup later. Surely you don't need the MMU to just boot to u-boot shell. My plan is to get the first platform in, then I will maintain Freescale stuff. So you can be sure I will continue to improve it. One reason to get these code in early is to enable our partners and early adopters to use u-boot. After all, this is the second ARMv8 platform. The first one vexpress_aemv8a doesn't even support cache. For the record, I'm OK with this plan given York's track record in the U-Boot community. -- Tom signature.asc Description: Digital signature ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On Fri, Jun 06, 2014 at 03:54:49PM +0100, York Sun wrote: On 06/06/2014 05:33 AM, Mark Rutland wrote: [...] What you need to do to replace the active set of tables (assuming that the new mapping has the instruction stream mapped in an identical way) is: - Write the tables. - DSB to make them visible to the MMU. - Write to the appropriate TTBR_*. - ISB to complete the write to the TTBR_*. - TLBI to invalidate the old mappings the the TLBs. - DSB to complete the TLBI. - If you've changed the instruction stream or system state that will affect the instruction stream, ISB to flush the CPU pipeline. Here is the flow I have (as of v5 patch) Write the tables (I removed dsb here in v5, need to add back) Write TTBR (I missed isb here, need to add) Flush dcache (otherwise the table will not be in DDR. Yes, I verified) This looks odd -- why do we need the tables to be in DDR? Why would we flush them here, when the address is partially visible to the MMU? This sounds odd but it actually makes sense. Let's say we have new tables created by u-boot. The new tables are in the address of DDR with D-cache enabled. If we don't flush the cache, the moment TLBs are invalidated, MMU will fetch the tables from TTBR which points to DDR. Without a valid TLB, MMU cannot get the table from D-cache, it has to fetch from the DDR directly. I have verified this by checking waveforms of the SoC and exercised code in both ways. How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Cheers, Mark. ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/06/2014 10:32 AM, Mark Rutland wrote: On Fri, Jun 06, 2014 at 03:54:49PM +0100, York Sun wrote: On 06/06/2014 05:33 AM, Mark Rutland wrote: [...] What you need to do to replace the active set of tables (assuming that the new mapping has the instruction stream mapped in an identical way) is: - Write the tables. - DSB to make them visible to the MMU. - Write to the appropriate TTBR_*. - ISB to complete the write to the TTBR_*. - TLBI to invalidate the old mappings the the TLBs. - DSB to complete the TLBI. - If you've changed the instruction stream or system state that will affect the instruction stream, ISB to flush the CPU pipeline. Here is the flow I have (as of v5 patch) Write the tables (I removed dsb here in v5, need to add back) Write TTBR (I missed isb here, need to add) Flush dcache (otherwise the table will not be in DDR. Yes, I verified) This looks odd -- why do we need the tables to be in DDR? Why would we flush them here, when the address is partially visible to the MMU? This sounds odd but it actually makes sense. Let's say we have new tables created by u-boot. The new tables are in the address of DDR with D-cache enabled. If we don't flush the cache, the moment TLBs are invalidated, MMU will fetch the tables from TTBR which points to DDR. Without a valid TLB, MMU cannot get the table from D-cache, it has to fetch from the DDR directly. I have verified this by checking waveforms of the SoC and exercised code in both ways. How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. You may be right. I need to test it. It will take me a little while. In the meantime, would you comment on v6 patches please? If flushing is the only question left, I can address it after testing. York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/06/2014 10:32 AM, Mark Rutland wrote: How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Mark, I appreciate the reminder. I tried on our emulator. With inner share set for TCR SH0 bits, u-boot works with the flushing, but doesn't work without flushing. It went to exception. Can you share more information about the inner share? I need to follow up with our designer to confirm. York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/06/2014 01:17 PM, York Sun wrote: On 06/06/2014 10:32 AM, Mark Rutland wrote: How is TCR_EL2.SH0 (or TCR_EL1.SH*) configured? You'll only need to flush the cache if they're configured non shareable. It is configured as non shareable. Is there any reason not to configure them as inner shareable? That way the MMU will look in the D-cache, and you won't have to spend time flushing them. Mark, I appreciate the reminder. I tried on our emulator. With inner share set for TCR SH0 bits, u-boot works with the flushing, but doesn't work without flushing. It went to exception. Can you share more information about the inner share? I need to follow up with our designer to confirm. A second thought, do I need to set the first MMU table so DDR is inner shareable? York ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On Wed, Jun 04, 2014 at 05:27:30PM +0100, York Sun wrote: On 06/02/2014 11:01 AM, Mark Rutland wrote: On Mon, Jun 02, 2014 at 05:06:13PM +0100, York Sun wrote: On 06/02/2014 04:34 AM, Mark Rutland wrote: On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? The general ARMv8 MMU table is not detail enough to control memory attribute like cache for all addresses. We have devices mapping to addresses with different requirement for cache control. And there are no APIs for creating device mappings rather than exporting the raw pagetable accessors and hard-coding them differently in every board file? That's a good question. At this point, only two platforms are using ARMv8 code. I am expecting FSL ARMv8 implementation will stay similar, i.e. covered by the file I added. If that's not the case, or more ARMv8 SoCs need special MMU table, we then should introduce such API. Having a full function MMU API may be an overkill for U-boot. We don't need dynamic MMU anyway. Maybe. It just seems to me that it would be possible to pre-allocate an empty table that we could place device (nGnRnE?) mappings in. Then all you'd need to call from board code is a function to map a range, rather than having to duplicate logic for creating the tables you want. Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { -u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; -value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; +value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); -page_table[section] = value; +page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; +u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ -for (i = 0; i (PGTABLE_SIZE 3); i++) -set_pgtable_section(i, MT_DEVICE_NGNRNE); +for (i = 0; i (PGTABLE_SIZE 3); i++) { +set_pgtable_section(page_table, i, i SECTION_SHIFT, +MT_DEVICE_NGNRNE); +} /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { -set_pgtable_section(j, MT_NORMAL); +set_pgtable_section(page_table, j, j SECTION_SHIFT, +MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { -asm volatile(msr ttbr0_el1, %0 - : : r (gd-arch.tlb_addr) : memory); -asm volatile(msr tcr_el1, %0 - : : r (TCR_FLAGS | TCR_EL1_IPS_BITS) - : memory); -asm volatile(msr mair_el1, %0 - : : r (MEMORY_ATTRIBUTES) : memory); +set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL1_IPS_BITS, + MEMORY_ATTRIBUTES); } else if (el == 2) { -asm volatile(msr ttbr0_el2, %0 - : : r (gd-arch.tlb_addr) : memory); -asm volatile(msr tcr_el2, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); -
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/05/2014 03:09 AM, Mark Rutland wrote: On Wed, Jun 04, 2014 at 05:27:30PM +0100, York Sun wrote: On 06/02/2014 11:01 AM, Mark Rutland wrote: On Mon, Jun 02, 2014 at 05:06:13PM +0100, York Sun wrote: On 06/02/2014 04:34 AM, Mark Rutland wrote: On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? The general ARMv8 MMU table is not detail enough to control memory attribute like cache for all addresses. We have devices mapping to addresses with different requirement for cache control. And there are no APIs for creating device mappings rather than exporting the raw pagetable accessors and hard-coding them differently in every board file? That's a good question. At this point, only two platforms are using ARMv8 code. I am expecting FSL ARMv8 implementation will stay similar, i.e. covered by the file I added. If that's not the case, or more ARMv8 SoCs need special MMU table, we then should introduce such API. Having a full function MMU API may be an overkill for U-boot. We don't need dynamic MMU anyway. Maybe. It just seems to me that it would be possible to pre-allocate an empty table that we could place device (nGnRnE?) mappings in. Then all you'd need to call from board code is a function to map a range, rather than having to duplicate logic for creating the tables you want. It sounds good, but not the case. For the three level tables I am using (level0, level1, level2), I don't have level2 table for every address, that will be too many. Instead, I have a lot of blocks for level1. When I need some fine control within a level1 block range, I have to create a new level2 table. It is doable, but I will hold on that if I can use static table. Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { -u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; -value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; +value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); -page_table[section] = value; +page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; +u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ -for (i = 0; i (PGTABLE_SIZE 3); i++) -set_pgtable_section(i, MT_DEVICE_NGNRNE); +for (i = 0; i (PGTABLE_SIZE 3); i++) { +set_pgtable_section(page_table, i, i SECTION_SHIFT, +MT_DEVICE_NGNRNE); +} /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { -set_pgtable_section(j, MT_NORMAL); +set_pgtable_section(page_table, j, j SECTION_SHIFT, +MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { -asm volatile(msr ttbr0_el1, %0 - : : r (gd-arch.tlb_addr) : memory); -asm volatile(msr tcr_el1, %0 - : : r (TCR_FLAGS | TCR_EL1_IPS_BITS) - : memory); -asm volatile(msr mair_el1, %0 - : : r (MEMORY_ATTRIBUTES) : memory); +set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL1_IPS_BITS, +
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On Thu, Jun 05, 2014 at 04:07:17PM +0100, York Sun wrote: On 06/05/2014 03:09 AM, Mark Rutland wrote: On Wed, Jun 04, 2014 at 05:27:30PM +0100, York Sun wrote: On 06/02/2014 11:01 AM, Mark Rutland wrote: On Mon, Jun 02, 2014 at 05:06:13PM +0100, York Sun wrote: On 06/02/2014 04:34 AM, Mark Rutland wrote: On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? The general ARMv8 MMU table is not detail enough to control memory attribute like cache for all addresses. We have devices mapping to addresses with different requirement for cache control. And there are no APIs for creating device mappings rather than exporting the raw pagetable accessors and hard-coding them differently in every board file? That's a good question. At this point, only two platforms are using ARMv8 code. I am expecting FSL ARMv8 implementation will stay similar, i.e. covered by the file I added. If that's not the case, or more ARMv8 SoCs need special MMU table, we then should introduce such API. Having a full function MMU API may be an overkill for U-boot. We don't need dynamic MMU anyway. Maybe. It just seems to me that it would be possible to pre-allocate an empty table that we could place device (nGnRnE?) mappings in. Then all you'd need to call from board code is a function to map a range, rather than having to duplicate logic for creating the tables you want. It sounds good, but not the case. For the three level tables I am using (level0, level1, level2), I don't have level2 table for every address, that will be too many. Instead, I have a lot of blocks for level1. When I need some fine control within a level1 block range, I have to create a new level2 table. It is doable, but I will hold on that if I can use static table. While my suggestion might not be the best, I'm not sure I follow, unless you always want to idmap devices? If you don't idmap devices, then you can place all of the disparate physical mappings within a single table unless you have very large peripherals to map? Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { -u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; -value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; +value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); -page_table[section] = value; +page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; +u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ -for (i = 0; i (PGTABLE_SIZE 3); i++) -set_pgtable_section(i, MT_DEVICE_NGNRNE); +for (i = 0; i (PGTABLE_SIZE 3); i++) { +set_pgtable_section(page_table, i, i SECTION_SHIFT, +MT_DEVICE_NGNRNE); +} /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { -set_pgtable_section(j, MT_NORMAL); +set_pgtable_section(page_table, j, j SECTION_SHIFT, +MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { -asm volatile(msr ttbr0_el1, %0 - : : r (gd-arch.tlb_addr) : memory); -
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/05/2014 10:41 AM, Mark Rutland wrote: On Thu, Jun 05, 2014 at 04:07:17PM +0100, York Sun wrote: On 06/05/2014 03:09 AM, Mark Rutland wrote: On Wed, Jun 04, 2014 at 05:27:30PM +0100, York Sun wrote: On 06/02/2014 11:01 AM, Mark Rutland wrote: On Mon, Jun 02, 2014 at 05:06:13PM +0100, York Sun wrote: On 06/02/2014 04:34 AM, Mark Rutland wrote: On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? The general ARMv8 MMU table is not detail enough to control memory attribute like cache for all addresses. We have devices mapping to addresses with different requirement for cache control. And there are no APIs for creating device mappings rather than exporting the raw pagetable accessors and hard-coding them differently in every board file? That's a good question. At this point, only two platforms are using ARMv8 code. I am expecting FSL ARMv8 implementation will stay similar, i.e. covered by the file I added. If that's not the case, or more ARMv8 SoCs need special MMU table, we then should introduce such API. Having a full function MMU API may be an overkill for U-boot. We don't need dynamic MMU anyway. Maybe. It just seems to me that it would be possible to pre-allocate an empty table that we could place device (nGnRnE?) mappings in. Then all you'd need to call from board code is a function to map a range, rather than having to duplicate logic for creating the tables you want. It sounds good, but not the case. For the three level tables I am using (level0, level1, level2), I don't have level2 table for every address, that will be too many. Instead, I have a lot of blocks for level1. When I need some fine control within a level1 block range, I have to create a new level2 table. It is doable, but I will hold on that if I can use static table. While my suggestion might not be the best, I'm not sure I follow, unless you always want to idmap devices? If you don't idmap devices, then you can place all of the disparate physical mappings within a single table unless you have very large peripherals to map? If you mean identical map as idmap, yes I am creating identical map for devices. I got your point. For this particular SoC, if I can get it work with these simple static tables, I will stay with them. But if I need to maintain the tables for various SoCs, I will convert to dynamic API. Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { -u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; -value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; +value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); -page_table[section] = value; +page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; +u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ -for (i = 0; i (PGTABLE_SIZE 3); i++) -set_pgtable_section(i, MT_DEVICE_NGNRNE); +for (i = 0; i (PGTABLE_SIZE 3); i++) { +set_pgtable_section(page_table, i, i SECTION_SHIFT, +MT_DEVICE_NGNRNE); +} /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { -set_pgtable_section(j, MT_NORMAL); +set_pgtable_section(page_table, j, j SECTION_SHIFT, +MT_NORMAL);
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/02/2014 11:01 AM, Mark Rutland wrote: On Mon, Jun 02, 2014 at 05:06:13PM +0100, York Sun wrote: On 06/02/2014 04:34 AM, Mark Rutland wrote: On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? The general ARMv8 MMU table is not detail enough to control memory attribute like cache for all addresses. We have devices mapping to addresses with different requirement for cache control. And there are no APIs for creating device mappings rather than exporting the raw pagetable accessors and hard-coding them differently in every board file? That's a good question. At this point, only two platforms are using ARMv8 code. I am expecting FSL ARMv8 implementation will stay similar, i.e. covered by the file I added. If that's not the case, or more ARMv8 SoCs need special MMU table, we then should introduce such API. Having a full function MMU API may be an overkill for U-boot. We don't need dynamic MMU anyway. Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { - u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; - value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; + value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); - page_table[section] = value; + page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; + u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ - for (i = 0; i (PGTABLE_SIZE 3); i++) - set_pgtable_section(i, MT_DEVICE_NGNRNE); + for (i = 0; i (PGTABLE_SIZE 3); i++) { + set_pgtable_section(page_table, i, i SECTION_SHIFT, + MT_DEVICE_NGNRNE); + } /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { - set_pgtable_section(j, MT_NORMAL); + set_pgtable_section(page_table, j, j SECTION_SHIFT, + MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { - asm volatile(msr ttbr0_el1, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el1, %0 - : : r (TCR_FLAGS | TCR_EL1_IPS_BITS) - : memory); - asm volatile(msr mair_el1, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, +TCR_FLAGS | TCR_EL1_IPS_BITS, +MEMORY_ATTRIBUTES); } else if (el == 2) { - asm volatile(msr ttbr0_el2, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el2, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); - asm volatile(msr mair_el2, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, +TCR_FLAGS | TCR_EL2_IPS_BITS, +MEMORY_ATTRIBUTES); } else { - asm volatile(msr ttbr0_el3, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el3, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); - asm volatile(msr mair_el3, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, +TCR_FLAGS | TCR_EL3_IPS_BITS, +
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { - u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; - value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; + value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); - page_table[section] = value; + page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; + u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ - for (i = 0; i (PGTABLE_SIZE 3); i++) - set_pgtable_section(i, MT_DEVICE_NGNRNE); + for (i = 0; i (PGTABLE_SIZE 3); i++) { + set_pgtable_section(page_table, i, i SECTION_SHIFT, + MT_DEVICE_NGNRNE); + } /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { - set_pgtable_section(j, MT_NORMAL); + set_pgtable_section(page_table, j, j SECTION_SHIFT, + MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { - asm volatile(msr ttbr0_el1, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el1, %0 - : : r (TCR_FLAGS | TCR_EL1_IPS_BITS) - : memory); - asm volatile(msr mair_el1, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL1_IPS_BITS, + MEMORY_ATTRIBUTES); } else if (el == 2) { - asm volatile(msr ttbr0_el2, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el2, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); - asm volatile(msr mair_el2, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL2_IPS_BITS, + MEMORY_ATTRIBUTES); } else { - asm volatile(msr ttbr0_el3, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el3, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); - asm volatile(msr mair_el3, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL3_IPS_BITS, + MEMORY_ATTRIBUTES); } /* enable the mmu */ diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index 1193e76..7de4ff9 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -108,4 +108,27 @@ TCR_IRGN_WBWA | \ TCR_T0SZ(VA_BITS)) +#ifndef __ASSEMBLY__ +void set_pgtable_section(u64 *page_table, u64 index, + u64 section, u64 memory_type); +static inline void set_ttbr_tcr_mair(int el, u64 table, u64 tcr, u64 attr) +{ + asm volatile(dsb sy;isb); Huh? This wasn't anywhere before. Is the
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On 06/02/2014 04:34 AM, Mark Rutland wrote: On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? The general ARMv8 MMU table is not detail enough to control memory attribute like cache for all addresses. We have devices mapping to addresses with different requirement for cache control. Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { -u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; -value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; +value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); -page_table[section] = value; +page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; +u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ -for (i = 0; i (PGTABLE_SIZE 3); i++) -set_pgtable_section(i, MT_DEVICE_NGNRNE); +for (i = 0; i (PGTABLE_SIZE 3); i++) { +set_pgtable_section(page_table, i, i SECTION_SHIFT, +MT_DEVICE_NGNRNE); +} /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { -set_pgtable_section(j, MT_NORMAL); +set_pgtable_section(page_table, j, j SECTION_SHIFT, +MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { -asm volatile(msr ttbr0_el1, %0 - : : r (gd-arch.tlb_addr) : memory); -asm volatile(msr tcr_el1, %0 - : : r (TCR_FLAGS | TCR_EL1_IPS_BITS) - : memory); -asm volatile(msr mair_el1, %0 - : : r (MEMORY_ATTRIBUTES) : memory); +set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL1_IPS_BITS, + MEMORY_ATTRIBUTES); } else if (el == 2) { -asm volatile(msr ttbr0_el2, %0 - : : r (gd-arch.tlb_addr) : memory); -asm volatile(msr tcr_el2, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); -asm volatile(msr mair_el2, %0 - : : r (MEMORY_ATTRIBUTES) : memory); +set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL2_IPS_BITS, + MEMORY_ATTRIBUTES); } else { -asm volatile(msr ttbr0_el3, %0 - : : r (gd-arch.tlb_addr) : memory); -asm volatile(msr tcr_el3, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); -asm volatile(msr mair_el3, %0 - : : r (MEMORY_ATTRIBUTES) : memory); +set_ttbr_tcr_mair(el, gd-arch.tlb_addr, + TCR_FLAGS | TCR_EL3_IPS_BITS, + MEMORY_ATTRIBUTES); } /* enable the mmu */ diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index 1193e76..7de4ff9 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -108,4 +108,27 @@ TCR_IRGN_WBWA | \ TCR_T0SZ(VA_BITS)) +#ifndef __ASSEMBLY__ +void set_pgtable_section(u64 *page_table, u64 index, + u64 section, u64
Re: [U-Boot] [Patch v4 2/5] ARMv8: Adjust MMU setup
On Mon, Jun 02, 2014 at 05:06:13PM +0100, York Sun wrote: On 06/02/2014 04:34 AM, Mark Rutland wrote: On Thu, May 29, 2014 at 09:49:05PM +0100, York Sun wrote: Make MMU functions reusable. Platform code can setup its own MMU tables. What exactly does platform code need to setup its own tables for? The general ARMv8 MMU table is not detail enough to control memory attribute like cache for all addresses. We have devices mapping to addresses with different requirement for cache control. And there are no APIs for creating device mappings rather than exporting the raw pagetable accessors and hard-coding them differently in every board file? Also fix a typo of TCR_EL3_IPS_BITS in cache_v8.c. Signed-off-by: York Sun york...@freescale.com CC: David Feng feng...@phytium.com.cn --- Change log: v4: new patch, splitted from v3 2/4 Revise set_pgtable_section() to be reused by platform MMU code Add inline function set_ttbr_tcr_mair() to be used by this and platform mmu code arch/arm/cpu/armv8/cache_v8.c| 49 -- arch/arm/include/asm/armv8/mmu.h | 23 ++ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index a96ecda..67dbd46 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -12,15 +12,14 @@ DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_SYS_DCACHE_OFF - -static void set_pgtable_section(u64 section, u64 memory_type) +void set_pgtable_section(u64 *page_table, u64 index, u64 section, + u64 memory_type) { - u64 *page_table = (u64 *)gd-arch.tlb_addr; u64 value; - value = (section SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; + value = section | PMD_TYPE_SECT | PMD_SECT_AF; value |= PMD_ATTRINDX(memory_type); - page_table[section] = value; + page_table[index] = value; } /* to activate the MMU we need to set up virtual memory */ @@ -28,10 +27,13 @@ static void mmu_setup(void) { int i, j, el; bd_t *bd = gd-bd; + u64 *page_table = (u64 *)gd-arch.tlb_addr; /* Setup an identity-mapping for all spaces */ - for (i = 0; i (PGTABLE_SIZE 3); i++) - set_pgtable_section(i, MT_DEVICE_NGNRNE); + for (i = 0; i (PGTABLE_SIZE 3); i++) { + set_pgtable_section(page_table, i, i SECTION_SHIFT, + MT_DEVICE_NGNRNE); + } /* Setup an identity-mapping for all RAM space */ for (i = 0; i CONFIG_NR_DRAM_BANKS; i++) { @@ -39,36 +41,25 @@ static void mmu_setup(void) ulong end = bd-bi_dram[i].start + bd-bi_dram[i].size; for (j = start SECTION_SHIFT; j end SECTION_SHIFT; j++) { - set_pgtable_section(j, MT_NORMAL); + set_pgtable_section(page_table, j, j SECTION_SHIFT, + MT_NORMAL); } } /* load TTBR0 */ el = current_el(); if (el == 1) { - asm volatile(msr ttbr0_el1, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el1, %0 - : : r (TCR_FLAGS | TCR_EL1_IPS_BITS) - : memory); - asm volatile(msr mair_el1, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, +TCR_FLAGS | TCR_EL1_IPS_BITS, +MEMORY_ATTRIBUTES); } else if (el == 2) { - asm volatile(msr ttbr0_el2, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el2, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); - asm volatile(msr mair_el2, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, +TCR_FLAGS | TCR_EL2_IPS_BITS, +MEMORY_ATTRIBUTES); } else { - asm volatile(msr ttbr0_el3, %0 - : : r (gd-arch.tlb_addr) : memory); - asm volatile(msr tcr_el3, %0 - : : r (TCR_FLAGS | TCR_EL2_IPS_BITS) - : memory); - asm volatile(msr mair_el3, %0 - : : r (MEMORY_ATTRIBUTES) : memory); + set_ttbr_tcr_mair(el, gd-arch.tlb_addr, +TCR_FLAGS | TCR_EL3_IPS_BITS, +MEMORY_ATTRIBUTES); } /* enable the mmu */ diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index 1193e76..7de4ff9 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -108,4 +108,27 @@