This is an automated email from Gerrit.

Antonio Borneo (borneo.anto...@gmail.com) just uploaded a new patch set to 
Gerrit, which you can find at http://openocd.zylin.com/4626

-- gerrit

commit 9b06c5c78a144f510770f06e113cfb7eab86e761
Author: Antonio Borneo <borneo.anto...@gmail.com>
Date:   Tue Jul 31 18:26:49 2018 +0200

    target/cortex_a: fix R/W across non-contiguous virtual pages
    
    When read_buffer/write_buffer uses AHB access, a virt2phys translation
    is required to get the physical address for the AHB access.
    But each translation is valid only within the limits of the page.
    If the read_buffer/write_buffer crosses the page boundary, we cannot
    assume that contiguous virtual pages are mapped on contiguous
    physical pages, thus a new virt2phys translation is required at each
    cross of page boundary.
    
    Split the AHB access in pages and loop among them.
    
    For simplicity, assume the page size is fixed to 4kB, that is the
    minimum size allowed by armv7a. Actually, in this specific case
    cortex_a_virt2phys() walks through the translation tables and can
    provide the real page size. Add a comment to explain it for further
    code improvement.
    
    Change-Id: I1030fa35b3032bf23f2259c4ff820521e03fe154
    Signed-off-by: Antonio Borneo <borneo.anto...@gmail.com>

diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index 409da15..eb32e49 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -2760,24 +2760,42 @@ static int cortex_a_read_memory_ahb(struct target 
*target, target_addr_t address
                        return retval;
        }
 
-       if (mmu_enabled) {
+       if (!count || !buffer)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (!mmu_enabled)
+               return mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, 
address);
+
+       /*
+        * TODO: here we are pessimistic and we use the smaller page of 4kB, but
+        * cortex_a_virt2phys() does a full table walk, so can return the actual
+        * size of page (4kB or 64kB) or section (1MB or 16Mb).
+        */
+       while (count) {
+               target_addr_t page_size = 0x1000;
+               uint32_t current_count;
+
                virt = address;
                retval = cortex_a_virt2phys(target, virt, &phys);
                if (retval != ERROR_OK)
                        return retval;
 
-               LOG_DEBUG("Reading at virtual address. "
-                         "Translating v:" TARGET_ADDR_FMT " to r:" 
TARGET_ADDR_FMT,
-                         virt, phys);
-               address = phys;
-       }
-
-       if (!count || !buffer)
-               return ERROR_COMMAND_SYNTAX_ERROR;
+               current_count = (page_size - (address & (page_size - 1))) / 
size;
+               if (current_count > count)
+                       current_count = count;
 
-       retval = mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, 
address);
+               LOG_DEBUG("Reading at virtual address 0x%" PRIx32 " bytes. "
+                         "Translating v:" TARGET_ADDR_FMT " to r:" 
TARGET_ADDR_FMT,
+                         size * current_count, virt, phys);
 
-       return retval;
+               retval = mem_ap_read_buf(armv7a->memory_ap, buffer, size, 
current_count, phys);
+               if (retval != ERROR_OK)
+                       return retval;
+               count -= current_count;
+               address += size * current_count;
+               buffer += size * current_count;
+       }
+       return ERROR_OK;
 }
 
 static int cortex_a_write_phys_memory(struct target *target,
@@ -2854,25 +2872,42 @@ static int cortex_a_write_memory_ahb(struct target 
*target, target_addr_t addres
                        return retval;
        }
 
-       if (mmu_enabled) {
+       if (!count || !buffer)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (!mmu_enabled)
+               return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, 
address);
+
+       /*
+        * TODO: here we are pessimistic and we use the smaller page of 4kB, but
+        * cortex_a_virt2phys() does a full table walk, so can return the actual
+        * size of page (4kB or 64kB) or section (1MB or 16Mb).
+        */
+       while (count) {
+               target_addr_t page_size = 0x1000;
+               uint32_t current_count;
+
                virt = address;
                retval = cortex_a_virt2phys(target, virt, &phys);
                if (retval != ERROR_OK)
                        return retval;
 
-               LOG_DEBUG("Writing to virtual address. "
-                         "Translating v:" TARGET_ADDR_FMT " to r:" 
TARGET_ADDR_FMT,
-                         virt,
-                         phys);
-               address = phys;
-       }
-
-       if (!count || !buffer)
-               return ERROR_COMMAND_SYNTAX_ERROR;
+               current_count = (page_size - (address & (page_size - 1))) / 
size;
+               if (current_count > count)
+                       current_count = count;
 
-       retval = mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, 
address);
+               LOG_DEBUG("Writing to virtual address 0x%" PRIx32 " bytes. "
+                         "Translating v:" TARGET_ADDR_FMT " to r:" 
TARGET_ADDR_FMT,
+                         size * current_count, virt, phys);
 
-       return retval;
+               retval = mem_ap_write_buf(armv7a->memory_ap, buffer, size, 
current_count, phys);
+               if (retval != ERROR_OK)
+                       return retval;
+               count -= current_count;
+               address += size * current_count;
+               buffer += size * current_count;
+       }
+       return ERROR_OK;
 }
 
 static int cortex_a_read_buffer(struct target *target, target_addr_t address,

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to