The Blackfin arch supports a simple sram allocator for userspace, as well
as a DMA memcpy function to access the sram.

Signed-off-by: Mike Frysinger <vap...@gentoo.org>
---
 linux-user/strace.list |  9 ++++++
 linux-user/syscall.c   | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/linux-user/strace.list b/linux-user/strace.list
index 08f115d..cf093cc 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -105,6 +105,9 @@
 #ifdef TARGET_NR_dipc
 { TARGET_NR_dipc, "dipc" , NULL, NULL, NULL },
 #endif
+#ifdef TARGET_NR_dma_memcpy
+{ TARGET_NR_dma_memcpy, "dma_memcpy" , NULL, NULL, NULL },
+#endif
 #ifdef TARGET_NR_dup
 { TARGET_NR_dup, "dup" , NULL, NULL, NULL },
 #endif
@@ -1299,6 +1302,12 @@
 #ifdef TARGET_NR_splice
 { TARGET_NR_splice, "splice" , NULL, NULL, NULL },
 #endif
+#ifdef TARGET_NR_sram_alloc
+{ TARGET_NR_sram_alloc, "sram_alloc" , NULL, NULL, NULL },
+#endif
+#ifdef TARGET_NR_sram_free
+{ TARGET_NR_sram_free, "sram_free" , NULL, NULL, NULL },
+#endif
 #ifdef TARGET_NR_ssetmask
 { TARGET_NR_ssetmask, "ssetmask" , NULL, NULL, NULL },
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a9dce35..a4431f0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4755,6 +4755,14 @@ static inline abi_long host_to_target_stat64(void 
*cpu_env,
 }
 #endif
 
+#ifdef TARGET_NR_sram_alloc
+struct sram_frag {
+    struct sram_frag *next;
+    abi_ulong addr, size;
+};
+static struct sram_frag *sfrags;
+#endif
+
 #if defined(CONFIG_USE_NPTL)
 /* ??? Using host futex calls even when target atomic operations
    are not really atomic probably breaks things.  However implementing
@@ -6413,6 +6421,72 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
arg1,
         ret = get_errno(munlockall());
         break;
 #endif
+#ifdef TARGET_NR_sram_alloc
+    case TARGET_NR_sram_alloc:
+        {
+            /* We don't want L1 insn to be read/write, but doing that
+             * keeps standard qemu funcs from being able to read/write
+             * that too.  So grant r/w access to all. */
+            int prot = PROT_READ | PROT_WRITE;
+            if ((arg2 & 1 /*L1_INST_SRAM*/) || (arg2 & 8 /*L2_SRAM*/)) {
+                prot |= PROT_EXEC;
+            }
+
+            ret = get_errno(target_mmap(0, arg1, prot, MAP_PRIVATE |
+                                        MAP_ANONYMOUS, -1, 0));
+
+            if (!is_error(ret)) {
+                struct sram_frag *sf = malloc(sizeof(*sf));
+                sf->addr = ret;
+                sf->size = arg1;
+                if (sfrags) {
+                    sf->next = sfrags;
+                    sfrags = sf;
+                } else {
+                    sf->next = NULL;
+                    sfrags = sf;
+                }
+            }
+        }
+        break;
+#endif
+#ifdef TARGET_NR_sram_free
+    case TARGET_NR_sram_free:
+        {
+            struct sram_frag *sf, *prev;
+
+            ret = -TARGET_EINVAL;
+
+            sf = prev = sfrags;
+            while (sf) {
+                if (sf->addr == arg1) {
+                    ret = get_errno(target_munmap(arg1, sf->size));
+                    if (!is_error(ret)) {
+                        if (sfrags == sf) {
+                            sfrags = sf->next;
+                        } else {
+                            prev->next = sf->next;
+                        }
+                        free(sf);
+                    }
+                    break;
+                }
+                prev = sf;
+                sf = sf->next;
+            }
+        }
+        break;
+#endif
+#ifdef TARGET_NR_dma_memcpy
+    case TARGET_NR_dma_memcpy:
+        p = alloca(arg3);
+        if (copy_from_user(p, arg2, arg3))
+            goto efault;
+        if (copy_to_user(arg1, p, arg3))
+            goto efault;
+        ret = arg1;
+        break;
+#endif
     case TARGET_NR_truncate:
         if (!(p = lock_user_string(arg1)))
             goto efault;
-- 
1.8.2.1


Reply via email to