]> git.sur5r.net Git - openocd/commitdiff
quark_x10xx: fix IO r/w operations with paging enabled
authorIvan De Cesaris <ivan.de.cesaris@intel.com>
Fri, 18 Apr 2014 09:19:40 +0000 (11:19 +0200)
committerPaul Fertser <fercerpav@gmail.com>
Sun, 27 Apr 2014 09:16:30 +0000 (09:16 +0000)
Paging checking and disabling wasn't present for IO r/w,
so the commands were successful only when paging wasn't
enabled (e.g. EFI boot phase).

Change-Id: I41366c0fadff3ea1eb8a153291f20a46cd9ddec1
Signed-off-by: Ivan De Cesaris <ivan.de.cesaris@intel.com>
Reviewed-on: http://openocd.zylin.com/2118
Tested-by: jenkins
Reviewed-by: Peter Stuge <peter@stuge.se>
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
src/target/x86_32_common.c

index 34da39b9fb23f1cbc3efbf707e184dfc4ca17681..0f75c97fff1dfc26974aef57423345995760cb74 100644 (file)
@@ -670,6 +670,7 @@ int x86_32_common_read_io(struct target *t, uint32_t addr,
        /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
        bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D;
        int retval = ERROR_FAIL;
+       bool pg_disabled = false;
        LOG_DEBUG("addr=%08" PRIx32 ", size=%d, buf=%p", addr, size, buf);
        check_not_halted(t);
        if (!buf || !addr) {
@@ -681,6 +682,13 @@ int x86_32_common_read_io(struct target *t, uint32_t addr,
                LOG_ERROR("%s error EDX write", __func__);
                return retval;
        }
+       /* to access physical memory, switch off the CR0.PG bit */
+       if (x86_32->is_paging_enabled(t)) {
+               retval = x86_32->disable_paging(t);
+               if (retval != ERROR_OK)
+                       return retval;
+               pg_disabled = true;
+       }
        switch (size) {
                case BYTE:
                        if (use32)
@@ -704,6 +712,13 @@ int x86_32_common_read_io(struct target *t, uint32_t addr,
                        LOG_ERROR("%s invalid read io size", __func__);
                        return ERROR_FAIL;
        }
+       /* restore CR0.PG bit if needed */
+       if (pg_disabled) {
+               retval = x86_32->enable_paging(t);
+               if (retval != ERROR_OK)
+                       return retval;
+               pg_disabled = false;
+       }
        uint32_t regval = 0;
        retval = x86_32->read_hw_reg(t, EAX, &regval, 0);
        if (retval != ERROR_OK) {
@@ -729,6 +744,7 @@ int x86_32_common_write_io(struct target *t, uint32_t addr,
        LOG_DEBUG("addr=%08" PRIx32 ", size=%d, buf=%p", addr, size, buf);
        check_not_halted(t);
        int retval = ERROR_FAIL;
+       bool pg_disabled = false;
        if (!buf || !addr) {
                LOG_ERROR("%s invalid params buf=%p, addr=%08" PRIx32, __func__, buf, addr);
                return retval;
@@ -747,6 +763,13 @@ int x86_32_common_write_io(struct target *t, uint32_t addr,
                LOG_ERROR("%s error on EAX write", __func__);
                return retval;
        }
+       /* to access physical memory, switch off the CR0.PG bit */
+       if (x86_32->is_paging_enabled(t)) {
+               retval = x86_32->disable_paging(t);
+               if (retval != ERROR_OK)
+                       return retval;
+               pg_disabled = true;
+       }
        switch (size) {
                case BYTE:
                        if (use32)
@@ -770,6 +793,13 @@ int x86_32_common_write_io(struct target *t, uint32_t addr,
                        LOG_ERROR("%s invalid write io size", __func__);
                        return ERROR_FAIL;
        }
+       /* restore CR0.PG bit if needed */
+       if (pg_disabled) {
+               retval = x86_32->enable_paging(t);
+               if (retval != ERROR_OK)
+                       return retval;
+               pg_disabled = false;
+       }
        retval = x86_32->transaction_status(t);
        if (retval != ERROR_OK) {
                LOG_ERROR("%s error on io write", __func__);