This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new daedc1f  openamp: Download libmetal and open-amp from github
daedc1f is described below

commit daedc1f5e2c270b217950819252090343236c5fa
Author: Xiang Xiao <xiaoxi...@xiaomi.com>
AuthorDate: Tue Apr 21 20:37:06 2020 +0800

    openamp: Download libmetal and open-amp from github
    
    and apply the patch which is pending merge to upstream
    
    Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
---
 openamp/.gitignore                                 |   3 +
 ...x-change-sched_kfree-to-metal_free_memory.patch |  29 +
 ...e-the-address-check-in-rpmsg_send-rpmsg_t.patch |  38 +
 ...-rpmsg_register_endpoint-into-rpmsg_init_.patch | 128 ++++
 ...dn-t-allocate-0-1023-address-in-rpmsg_cre.patch | 227 ++++++
 .../0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch  | 128 ++++
 ...n-fail-if-either-source-or-destination-ad.patch |  45 ++
 ...eproc_mmap-support-va-to-pa-da-conversion.patch | 785 +++++++++++++++++++++
 .../0007-rpmsg-bring-back-zero-copy-transfer.patch | 470 ++++++++++++
 ...acknowledge-the-received-creation-message.patch | 132 ++++
 ...proc_virtio_read_config-rproc_virtio_writ.patch | 119 ++++
 ...otiate-individual-buffer-size-dynamically.patch | 159 +++++
 openamp/Makefile                                   |   3 +-
 openamp/libmetal.defs                              |  29 +-
 openamp/open-amp.defs                              |  24 +-
 15 files changed, 2303 insertions(+), 16 deletions(-)

diff --git a/openamp/.gitignore b/openamp/.gitignore
index 95c5cfa..95e0042 100644
--- a/openamp/.gitignore
+++ b/openamp/.gitignore
@@ -1,4 +1,7 @@
 /.libmetal_headers
 /.openamp_headers
+/.depend
+/Make.dep
 /libmetal
 /open-amp
+/*.zip
diff --git a/openamp/0001-nuttx-change-sched_kfree-to-metal_free_memory.patch 
b/openamp/0001-nuttx-change-sched_kfree-to-metal_free_memory.patch
new file mode 100644
index 0000000..94a848d
--- /dev/null
+++ b/openamp/0001-nuttx-change-sched_kfree-to-metal_free_memory.patch
@@ -0,0 +1,29 @@
+From e84d8dd13d31de4942bbf4ec8093932961b9d1b9 Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Tue, 21 Apr 2020 22:02:38 +0800
+Subject: [PATCH] nuttx: change sched_kfree to metal_free_memory
+
+since the upstream remove sched_kfree and put the similar logic into kmm_free:
+https://github.com/apache/incubator-nuttx/commit/231ad202ee0a3abfd2e14fab1f218b588f61284b
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ lib/system/nuttx/irq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/system/nuttx/irq.c libmetal/lib/system/nuttx/irq.c
+index 476eab9..84200d3 100644
+--- a/lib/system/nuttx/irq.c
++++ libmetal/lib/system/nuttx/irq.c
+@@ -45,7 +45,7 @@ static int metal_cntr_irq_handler(int irq, void *context, 
void *data)
+ 
+       /* context == NULL mean unregister */
+       irqchain_detach(irq, metal_cntr_irq_handler, data);
+-      sched_kfree(data);
++      metal_free_memory(data);
+       return 0;
+ }
+ 
+-- 
+2.17.1
+
diff --git 
a/openamp/0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch 
b/openamp/0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch
new file mode 100644
index 0000000..023d244
--- /dev/null
+++ b/openamp/0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch
@@ -0,0 +1,38 @@
+From aca01202ec47984ea90d3904560b973976cab1e5 Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Fri, 24 Apr 2020 01:44:31 +0800
+Subject: [PATCH 01/10] rpmsg: remove the address check in
+ rpmsg_send/rpmsg_trysend
+
+since rpmsg_send_offchannel_raw already do the same validation
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ lib/include/openamp/rpmsg.h | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
+index f2a6454..8401c38 100644
+--- a/lib/include/openamp/rpmsg.h
++++ open-amp/lib/include/openamp/rpmsg.h
+@@ -146,8 +146,6 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, 
uint32_t src,
+ static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data,
+                            int len)
+ {
+-      if (ept->dest_addr == RPMSG_ADDR_ANY)
+-              return RPMSG_ERR_ADDR;
+       return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data,
+                                        len, true);
+ }
+@@ -216,8 +214,6 @@ static inline int rpmsg_send_offchannel(struct 
rpmsg_endpoint *ept,
+ static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data,
+                               int len)
+ {
+-      if (ept->dest_addr == RPMSG_ADDR_ANY)
+-              return RPMSG_ERR_ADDR;
+       return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data,
+                                        len, false);
+ }
+-- 
+2.17.1
+
diff --git 
a/openamp/0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch 
b/openamp/0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch
new file mode 100644
index 0000000..52a1f57
--- /dev/null
+++ b/openamp/0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch
@@ -0,0 +1,128 @@
+From c4c3577a3d7a1e957c84f86caa64b7e076b9db89 Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Fri, 24 Apr 2020 03:40:56 +0800
+Subject: [PATCH 02/10] rpmsg: merge rpmsg_register_endpoint into
+ rpmsg_init_ept
+
+so the service which use preserved address could call rpmsg_init_ept
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ lib/include/openamp/rpmsg.h | 19 +++++++------------
+ lib/rpmsg/rpmsg.c           | 17 +++++++++++++----
+ lib/rpmsg/rpmsg_internal.h  |  2 --
+ lib/rpmsg/rpmsg_virtio.c    |  3 +--
+ 4 files changed, 21 insertions(+), 20 deletions(-)
+
+diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
+index 8401c38..a08f9d3 100644
+--- a/lib/include/openamp/rpmsg.h
++++ open-amp/lib/include/openamp/rpmsg.h
+@@ -271,6 +271,7 @@ static inline int rpmsg_trysend_offchannel(struct 
rpmsg_endpoint *ept,
+  * remoteproc address, endpoint callback, and destroy endpoint callback.
+  *
+  * @ept: pointer to rpmsg endpoint
++ * @rdev: pointer to the rpmsg device
+  * @name: service name associated to the endpoint
+  * @src: local address of the endpoint
+  * @dest: target address of the endpoint
+@@ -278,18 +279,12 @@ static inline int rpmsg_trysend_offchannel(struct 
rpmsg_endpoint *ept,
+  * @ns_unbind_cb: end point service unbind callback, called when remote ept is
+  *                destroyed.
+  */
+-static inline void rpmsg_init_ept(struct rpmsg_endpoint *ept,
+-                                const char *name,
+-                                uint32_t src, uint32_t dest,
+-                                rpmsg_ept_cb cb,
+-                                rpmsg_ns_unbind_cb ns_unbind_cb)
+-{
+-      strncpy(ept->name, name ? name : "", sizeof(ept->name));
+-      ept->addr = src;
+-      ept->dest_addr = dest;
+-      ept->cb = cb;
+-      ept->ns_unbind_cb = ns_unbind_cb;
+-}
++void rpmsg_init_ept(struct rpmsg_endpoint *ept,
++                  struct rpmsg_device *rdev,
++                  const char *name,
++                  uint32_t src, uint32_t dest,
++                  rpmsg_ept_cb cb,
++                  rpmsg_ns_unbind_cb ns_unbind_cb);
+ 
+ /**
+  * rpmsg_create_ept - create rpmsg endpoint and register it to rpmsg device
+diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c
+index 5b9c735..eee1c28 100644
+--- a/lib/rpmsg/rpmsg.c
++++ open-amp/lib/rpmsg/rpmsg.c
+@@ -182,6 +182,7 @@ static void rpmsg_unregister_endpoint(struct 
rpmsg_endpoint *ept)
+               return;
+ 
+       rdev = ept->rdev;
++      ept->rdev = NULL;
+ 
+       if (ept->addr != RPMSG_ADDR_ANY)
+               rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE,
+@@ -189,9 +190,18 @@ static void rpmsg_unregister_endpoint(struct 
rpmsg_endpoint *ept)
+       metal_list_del(&ept->node);
+ }
+ 
+-void rpmsg_register_endpoint(struct rpmsg_device *rdev,
+-                           struct rpmsg_endpoint *ept)
++void rpmsg_init_ept(struct rpmsg_endpoint *ept,
++                  struct rpmsg_device *rdev,
++                  const char *name,
++                  uint32_t src, uint32_t dest,
++                  rpmsg_ept_cb cb,
++                  rpmsg_ns_unbind_cb ns_unbind_cb)
+ {
++      strncpy(ept->name, name ? name : "", sizeof(ept->name));
++      ept->addr = src;
++      ept->dest_addr = dest;
++      ept->cb = cb;
++      ept->ns_unbind_cb = ns_unbind_cb;
+       ept->rdev = rdev;
+       metal_list_add_tail(&rdev->endpoints, &ept->node);
+ }
+@@ -224,8 +234,7 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct 
rpmsg_device *rdev,
+               addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE);
+       }
+ 
+-      rpmsg_init_ept(ept, name, addr, dest, cb, unbind_cb);
+-      rpmsg_register_endpoint(rdev, ept);
++      rpmsg_init_ept(ept, rdev, name, addr, dest, cb, unbind_cb);
+ 
+       if (rdev->support_ns && ept->dest_addr == RPMSG_ADDR_ANY) {
+               /* Send NS announcement to remote processor */
+diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h
+index f63c958..9c46970 100644
+--- a/lib/rpmsg/rpmsg_internal.h
++++ open-amp/lib/rpmsg/rpmsg_internal.h
+@@ -92,8 +92,6 @@ int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, 
unsigned long flags);
+ struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rvdev,
+                                         const char *name, uint32_t addr,
+                                         uint32_t dest_addr);
+-void rpmsg_register_endpoint(struct rpmsg_device *rdev,
+-                           struct rpmsg_endpoint *ept);
+ 
+ static inline struct rpmsg_endpoint *
+ rpmsg_get_ept_from_addr(struct rpmsg_device *rdev, uint32_t addr)
+diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c
+index cf3ec21..ff1226b 100644
+--- a/lib/rpmsg/rpmsg_virtio.c
++++ open-amp/lib/rpmsg/rpmsg_virtio.c
+@@ -636,10 +636,9 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+        * service announcement feature.
+        */
+       if (rdev->support_ns) {
+-              rpmsg_init_ept(&rdev->ns_ept, "NS",
++              rpmsg_init_ept(&rdev->ns_ept, rdev, "NS",
+                              RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR,
+                              rpmsg_virtio_ns_callback, NULL);
+-              rpmsg_register_endpoint(rdev, &rdev->ns_ept);
+       }
+ 
+ #ifndef VIRTIO_SLAVE_ONLY
+-- 
+2.17.1
+
diff --git 
a/openamp/0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch 
b/openamp/0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch
new file mode 100644
index 0000000..b550c0d
--- /dev/null
+++ b/openamp/0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch
@@ -0,0 +1,227 @@
+From 373d773c188920088af1673867de5cfed12ea4de Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Fri, 24 Apr 2020 01:33:12 +0800
+Subject: [PATCH 03/10] rpmsg: shouldn't allocate 0-1023 address in
+ rpmsg_create_ept
+
+since this region is reserved for predefined services(e.g. NS use 0x35)
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ apps/examples/echo/rpmsg-echo.c               |  2 +-
+ apps/examples/echo/rpmsg-ping.c               |  2 +-
+ .../matrix_multiply/matrix_multiply.c         |  2 +-
+ .../matrix_multiply/matrix_multiplyd.c        |  2 +-
+ apps/examples/rpc_demo/rpc_demod.c            |  2 +-
+ .../rpmsg_sample_echo/rpmsg-sample-ping.c     |  2 +-
+ apps/tests/msg/rpmsg-flood-ping.c             |  2 +-
+ apps/tests/msg/rpmsg-ping.c                   |  2 +-
+ apps/tests/msg/rpmsg-update.c                 |  2 +-
+ lib/include/openamp/rpmsg.h                   | 27 ++++++++++---------
+ lib/rpmsg/rpmsg.c                             | 11 +++++---
+ 11 files changed, 30 insertions(+), 26 deletions(-)
+
+diff --git a/apps/examples/echo/rpmsg-echo.c 
open-amp/apps/examples/echo/rpmsg-echo.c
+index 0c75203..71a0bbf 100644
+--- a/apps/examples/echo/rpmsg-echo.c
++++ open-amp/apps/examples/echo/rpmsg-echo.c
+@@ -58,7 +58,7 @@ int app(struct rpmsg_device *rdev, void *priv)
+       LPRINTF("Try to create rpmsg endpoint.\r\n");
+ 
+       ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME,
+-                             0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
++                             1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
+                              rpmsg_service_unbind);
+       if (ret) {
+               LPERROR("Failed to create endpoint.\r\n");
+diff --git a/apps/examples/echo/rpmsg-ping.c 
open-amp/apps/examples/echo/rpmsg-ping.c
+index 3b716b0..ff639cd 100644
+--- a/apps/examples/echo/rpmsg-ping.c
++++ open-amp/apps/examples/echo/rpmsg-ping.c
+@@ -11,7 +11,7 @@ This application echoes back data that was sent to it by the 
master core. */
+ #include "platform_info.h"
+ #include "rpmsg-echo.h"
+ 
+-#define APP_EPT_ADDR    0
++#define APP_EPT_ADDR    1024
+ #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
+ #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
+ 
+diff --git a/apps/examples/matrix_multiply/matrix_multiply.c 
open-amp/apps/examples/matrix_multiply/matrix_multiply.c
+index b9da29b..3928088 100644
+--- a/apps/examples/matrix_multiply/matrix_multiply.c
++++ open-amp/apps/examples/matrix_multiply/matrix_multiply.c
+@@ -14,7 +14,7 @@ multiplies them and returns the result to the master core. */
+ 
+ #define       MAX_SIZE      6
+ #define NUM_MATRIX    2
+-#define APP_EPT_ADDR  0
++#define APP_EPT_ADDR  1024
+ 
+ #define raw_printf(format, ...) printf(format, ##__VA_ARGS__)
+ #define LPRINTF(format, ...) raw_printf("CLIENT> " format, ##__VA_ARGS__)
+diff --git a/apps/examples/matrix_multiply/matrix_multiplyd.c 
open-amp/apps/examples/matrix_multiply/matrix_multiplyd.c
+index 6b4a118..29c6380 100644
+--- a/apps/examples/matrix_multiply/matrix_multiplyd.c
++++ open-amp/apps/examples/matrix_multiply/matrix_multiplyd.c
+@@ -92,7 +92,7 @@ int app(struct rpmsg_device *rdev, void *priv)
+       int ret;
+ 
+       ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME,
+-                             0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
++                             1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
+                              rpmsg_service_unbind);
+       if (ret) {
+               LPERROR("Failed to create endpoint.\r\n");
+diff --git a/apps/examples/rpc_demo/rpc_demod.c 
open-amp/apps/examples/rpc_demo/rpc_demod.c
+index 44c92a2..a4659f3 100644
+--- a/apps/examples/rpc_demo/rpc_demod.c
++++ open-amp/apps/examples/rpc_demo/rpc_demod.c
+@@ -312,7 +312,7 @@ int app(struct rpmsg_device *rdev, void *priv)
+       LPRINTF("Try to create rpmsg endpoint.\r\n");
+ 
+       ret = rpmsg_create_ept(&app_ept, rdev, RPMSG_SERVICE_NAME,
+-                             0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
++                             1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
+                              rpmsg_service_unbind);
+       if (ret) {
+               LPERROR("Failed to create endpoint.\r\n");
+diff --git a/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c 
open-amp/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c
+index ee866b4..14456e3 100644
+--- a/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c
++++ open-amp/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c
+@@ -20,7 +20,7 @@
+ #define BYE_MSG               "goodbye!"
+ #define MSG_LIMIT     100
+ 
+-#define APP_EPT_ADDR    0
++#define APP_EPT_ADDR    1024
+ #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
+ #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
+ 
+diff --git a/apps/tests/msg/rpmsg-flood-ping.c 
open-amp/apps/tests/msg/rpmsg-flood-ping.c
+index 66489f8..28edc66 100644
+--- a/apps/tests/msg/rpmsg-flood-ping.c
++++ open-amp/apps/tests/msg/rpmsg-flood-ping.c
+@@ -12,7 +12,7 @@
+ #include "platform_info.h"
+ #include "rpmsg-ping.h"
+ 
+-#define APP_EPT_ADDR    0
++#define APP_EPT_ADDR    1024
+ #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
+ #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
+ 
+diff --git a/apps/tests/msg/rpmsg-ping.c open-amp/apps/tests/msg/rpmsg-ping.c
+index 0220a27..752b16c 100644
+--- a/apps/tests/msg/rpmsg-ping.c
++++ open-amp/apps/tests/msg/rpmsg-ping.c
+@@ -11,7 +11,7 @@ This application echoes back data that was sent to it by the 
master core. */
+ #include "platform_info.h"
+ #include "rpmsg-ping.h"
+ 
+-#define APP_EPT_ADDR    0
++#define APP_EPT_ADDR    1024
+ #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__)
+ #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
+ 
+diff --git a/apps/tests/msg/rpmsg-update.c 
open-amp/apps/tests/msg/rpmsg-update.c
+index 9b26cac..b8e08db 100644
+--- a/apps/tests/msg/rpmsg-update.c
++++ open-amp/apps/tests/msg/rpmsg-update.c
+@@ -73,7 +73,7 @@ int app(struct rpmsg_device *rdev, void *priv)
+       LPRINTF("Try to create rpmsg endpoint.\r\n");
+ 
+       ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME,
+-                             0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
++                             1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb,
+                              rpmsg_service_unbind);
+       if (ret) {
+               LPERROR("Failed to create endpoint.\r\n");
+diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
+index a08f9d3..3403240 100644
+--- a/lib/include/openamp/rpmsg.h
++++ open-amp/lib/include/openamp/rpmsg.h
+@@ -25,22 +25,23 @@ extern "C" {
+ #endif
+ 
+ /* Configurable parameters */
+-#define RPMSG_NAME_SIZE               (32)
+-#define RPMSG_ADDR_BMP_SIZE   (128)
++#define RPMSG_NAME_SIZE                       (32)
++#define RPMSG_ADDR_BMP_SIZE           (128)
+ 
+-#define RPMSG_NS_EPT_ADDR     (0x35)
+-#define RPMSG_ADDR_ANY                0xFFFFFFFF
++#define RPMSG_NS_EPT_ADDR             (0x35)
++#define RPMSG_RESERVED_ADDRESSES      (1024)
++#define RPMSG_ADDR_ANY                        0xFFFFFFFF
+ 
+ /* Error macros. */
+-#define RPMSG_SUCCESS         0
+-#define RPMSG_ERROR_BASE      -2000
+-#define RPMSG_ERR_NO_MEM      (RPMSG_ERROR_BASE - 1)
+-#define RPMSG_ERR_NO_BUFF     (RPMSG_ERROR_BASE - 2)
+-#define RPMSG_ERR_PARAM               (RPMSG_ERROR_BASE - 3)
+-#define RPMSG_ERR_DEV_STATE   (RPMSG_ERROR_BASE - 4)
+-#define RPMSG_ERR_BUFF_SIZE   (RPMSG_ERROR_BASE - 5)
+-#define RPMSG_ERR_INIT                (RPMSG_ERROR_BASE - 6)
+-#define RPMSG_ERR_ADDR                (RPMSG_ERROR_BASE - 7)
++#define RPMSG_SUCCESS                 0
++#define RPMSG_ERROR_BASE              -2000
++#define RPMSG_ERR_NO_MEM              (RPMSG_ERROR_BASE - 1)
++#define RPMSG_ERR_NO_BUFF             (RPMSG_ERROR_BASE - 2)
++#define RPMSG_ERR_PARAM                       (RPMSG_ERROR_BASE - 3)
++#define RPMSG_ERR_DEV_STATE           (RPMSG_ERROR_BASE - 4)
++#define RPMSG_ERR_BUFF_SIZE           (RPMSG_ERROR_BASE - 5)
++#define RPMSG_ERR_INIT                        (RPMSG_ERROR_BASE - 6)
++#define RPMSG_ERR_ADDR                        (RPMSG_ERROR_BASE - 7)
+ 
+ struct rpmsg_endpoint;
+ struct rpmsg_device;
+diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c
+index eee1c28..dcc39c1 100644
+--- a/lib/rpmsg/rpmsg.c
++++ open-amp/lib/rpmsg/rpmsg.c
+@@ -29,7 +29,7 @@ static uint32_t rpmsg_get_address(unsigned long *bitmap, int 
size)
+ 
+       nextbit = metal_bitmap_next_clear_bit(bitmap, 0, size);
+       if (nextbit < (uint32_t)size) {
+-              addr = nextbit;
++              addr = RPMSG_RESERVED_ADDRESSES + nextbit;
+               metal_bitmap_set_bit(bitmap, nextbit);
+       }
+ 
+@@ -48,7 +48,8 @@ static uint32_t rpmsg_get_address(unsigned long *bitmap, int 
size)
+ static void rpmsg_release_address(unsigned long *bitmap, int size,
+                                 int addr)
+ {
+-      if (addr < size)
++      addr -= RPMSG_RESERVED_ADDRESSES;
++      if (addr >= 0 && addr < size)
+               metal_bitmap_clear_bit(bitmap, addr);
+ }
+ 
+@@ -65,7 +66,8 @@ static void rpmsg_release_address(unsigned long *bitmap, int 
size,
+  */
+ static int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr)
+ {
+-      if (addr < size)
++      addr -= RPMSG_RESERVED_ADDRESSES;
++      if (addr >= 0 && addr < size)
+               return metal_bitmap_is_bit_set(bitmap, addr);
+       else
+               return RPMSG_ERR_PARAM;
+@@ -84,7 +86,8 @@ static int rpmsg_is_address_set(unsigned long *bitmap, int 
size, int addr)
+  */
+ static int rpmsg_set_address(unsigned long *bitmap, int size, int addr)
+ {
+-      if (addr < size) {
++      addr -= RPMSG_RESERVED_ADDRESSES;
++      if (addr >= 0 && addr < size) {
+               metal_bitmap_set_bit(bitmap, addr);
+               return RPMSG_SUCCESS;
+       } else {
+-- 
+2.17.1
+
diff --git a/openamp/0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch 
b/openamp/0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch
new file mode 100644
index 0000000..59d89df
--- /dev/null
+++ b/openamp/0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch
@@ -0,0 +1,128 @@
+From 2a82b3350bc5eb44d6ffd66da6e3bae6d15ec84c Mon Sep 17 00:00:00 2001
+From: ligd <liguid...@pinecone.net>
+Date: Wed, 20 Feb 2019 11:36:57 +0800
+Subject: [PATCH 04/10] rpmsg: wait ept ready in rpmsg_send
+
+since the destination address need time to return from peer
+
+Signed-off-by: ligd <liguid...@pinecone.net>
+---
+ lib/include/openamp/rpmsg.h | 48 ++++++++++++++++++++++++-------------
+ lib/rpmsg/rpmsg_virtio.c    |  7 ------
+ 2 files changed, 32 insertions(+), 23 deletions(-)
+
+diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
+index 3403240..7000453 100644
+--- a/lib/include/openamp/rpmsg.h
++++ open-amp/lib/include/openamp/rpmsg.h
+@@ -15,6 +15,7 @@
+ #include <metal/compiler.h>
+ #include <metal/mutex.h>
+ #include <metal/list.h>
++#include <metal/sleep.h>
+ #include <metal/utilities.h>
+ #include <string.h>
+ #include <stdbool.h>
+@@ -32,6 +33,12 @@ extern "C" {
+ #define RPMSG_RESERVED_ADDRESSES      (1024)
+ #define RPMSG_ADDR_ANY                        0xFFFFFFFF
+ 
++/* Total tick count for 15secs - 1usec tick. */
++#define RPMSG_TICK_COUNT              15000000
++
++/* Time to wait - In multiple of 1 msecs. */
++#define RPMSG_TICKS_PER_INTERVAL      1000
++
+ /* Error macros. */
+ #define RPMSG_SUCCESS                 0
+ #define RPMSG_ERROR_BASE              -2000
+@@ -129,6 +136,20 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, 
uint32_t src,
+                             uint32_t dst, const void *data, int size,
+                             int wait);
+ 
++/**
++ * is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send
++ *
++ * @ept: pointer to rpmsg endpoint
++ *
++ * Returns 1 if the rpmsg endpoint has both local addr and destination
++ * addr set, 0 otherwise
++ */
++static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept)
++{
++      return (ept->dest_addr != RPMSG_ADDR_ANY) &&
++              (ept->addr != RPMSG_ADDR_ANY);
++}
++
+ /**
+  * rpmsg_send() - send a message across to the remote processor
+  * @ept: the rpmsg endpoint
+@@ -147,8 +168,17 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, 
uint32_t src,
+ static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data,
+                            int len)
+ {
+-      return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data,
+-                                       len, true);
++      int tc = 0;
++
++      for (; tc < RPMSG_TICK_COUNT; tc += RPMSG_TICKS_PER_INTERVAL) {
++              if (is_rpmsg_ept_ready(ept))
++                      return rpmsg_send_offchannel_raw(ept, ept->addr,
++                                                       ept->dest_addr,
++                                                       data, len, true);
++              metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL);
++      }
++
++      return RPMSG_ERR_ADDR;
+ }
+ 
+ /**
+@@ -328,20 +358,6 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct 
rpmsg_device *rdev,
+  */
+ void rpmsg_destroy_ept(struct rpmsg_endpoint *ept);
+ 
+-/**
+- * is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send
+- *
+- * @ept: pointer to rpmsg endpoint
+- *
+- * Returns 1 if the rpmsg endpoint has both local addr and destination
+- * addr set, 0 otherwise
+- */
+-static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept)
+-{
+-      return (ept->dest_addr != RPMSG_ADDR_ANY) &&
+-              (ept->addr != RPMSG_ADDR_ANY);
+-}
+-
+ #if defined __cplusplus
+ }
+ #endif
+diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c
+index ff1226b..17f2998 100644
+--- a/lib/rpmsg/rpmsg_virtio.c
++++ open-amp/lib/rpmsg/rpmsg_virtio.c
+@@ -8,7 +8,6 @@
+  */
+ 
+ #include <metal/alloc.h>
+-#include <metal/sleep.h>
+ #include <metal/utilities.h>
+ #include <openamp/rpmsg_virtio.h>
+ #include <openamp/virtqueue.h>
+@@ -17,12 +16,6 @@
+ 
+ #define RPMSG_NUM_VRINGS                        2
+ 
+-/* Total tick count for 15secs - 1usec tick. */
+-#define RPMSG_TICK_COUNT                        15000000
+-
+-/* Time to wait - In multiple of 1 msecs. */
+-#define RPMSG_TICKS_PER_INTERVAL                1000
+-
+ #ifndef VIRTIO_SLAVE_ONLY
+ metal_weak void *
+ rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool,
+-- 
+2.17.1
+
diff --git 
a/openamp/0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch 
b/openamp/0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch
new file mode 100644
index 0000000..fd4ccaf
--- /dev/null
+++ b/openamp/0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch
@@ -0,0 +1,45 @@
+From 8169c7954d432c6abd8db8f1bde35890bba672ff Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Fri, 24 Apr 2020 02:22:15 +0800
+Subject: [PATCH 05/10] rpmsg: return fail if either source or destination
+ address is zero
+
+to help detect rpmsg_send is called before the endpoint
+initialization or after the endpoint uninitialization
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ lib/include/openamp/rpmsg.h | 3 +--
+ lib/rpmsg/rpmsg.c           | 2 +-
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
+index 7000453..1279ea2 100644
+--- a/lib/include/openamp/rpmsg.h
++++ open-amp/lib/include/openamp/rpmsg.h
+@@ -146,8 +146,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, 
uint32_t src,
+  */
+ static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept)
+ {
+-      return (ept->dest_addr != RPMSG_ADDR_ANY) &&
+-              (ept->addr != RPMSG_ADDR_ANY);
++      return ept && ept->rdev && ept->dest_addr && ept->dest_addr != 
RPMSG_ADDR_ANY;
+ }
+ 
+ /**
+diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c
+index dcc39c1..9da38a1 100644
+--- a/lib/rpmsg/rpmsg.c
++++ open-amp/lib/rpmsg/rpmsg.c
+@@ -115,7 +115,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, 
uint32_t src,
+ {
+       struct rpmsg_device *rdev;
+ 
+-      if (!ept || !ept->rdev || !data || dst == RPMSG_ADDR_ANY)
++      if (!ept || !ept->rdev || !data || !dst || dst == RPMSG_ADDR_ANY)
+               return RPMSG_ERR_PARAM;
+ 
+       rdev = ept->rdev;
+-- 
+2.17.1
+
diff --git a/openamp/0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch 
b/openamp/0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch
new file mode 100644
index 0000000..e6a4fa7
--- /dev/null
+++ b/openamp/0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch
@@ -0,0 +1,785 @@
+From bdadd236975ba4b4d9011d3b86d528d305476cb2 Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Fri, 15 Mar 2019 01:51:03 +0800
+Subject: [PATCH 06/10] remoteproc_mmap support va to pa/da conversion
+
+1.change va from output to input/output
+2.remoteproc_get_io_xxx fallback to mmap callback
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ .../load_fw/zynqmp_r5_lcm_rproc_example.c     |  69 +++++------
+ apps/machine/zynq7/platform_info.c            |  16 +--
+ apps/machine/zynq7/zynq_a9_rproc.c            |  40 +++----
+ apps/machine/zynqmp/platform_info.c           |   6 +-
+ apps/machine/zynqmp/zynqmp_linux_r5_proc.c    |  40 ++++---
+ apps/machine/zynqmp_r5/platform_info.c        |  16 +--
+ apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c  |  38 +++---
+ .../linux/machine/generic/platform_info.c     |  52 ++++----
+ lib/include/openamp/remoteproc.h              |  19 +--
+ lib/remoteproc/remoteproc.c                   | 112 ++++++++++--------
+ lib/remoteproc/rsc_table_parser.c             |   2 +-
+ 11 files changed, 212 insertions(+), 198 deletions(-)
+
+diff --git a/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c 
open-amp/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c
+index 26a09e5..e224631 100644
+--- a/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c
++++ open-amp/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c
+@@ -137,86 +137,79 @@ void r5_rproc_remove(struct remoteproc *rproc)
+       }
+ }
+ 
+-void *r5_rproc_mmap(struct remoteproc *rproc,
+-                  metal_phys_addr_t *pa, metal_phys_addr_t *da,
+-                  size_t size, unsigned int attribute,
+-                  struct metal_io_region **io)
++int r5_rproc_mmap(struct remoteproc *rproc,
++                metal_phys_addr_t *pa, metal_phys_addr_t *da,
++                void **va, size_t size, unsigned int attribute,
++                struct metal_io_region **io)
+ {
+       struct remoteproc_mem *mem;
++      struct metal_io_region *tmpio;
+       struct r5_rproc_priv *priv;
+-      metal_phys_addr_t lpa, lda;
+ 
+       priv = rproc->priv;
+ 
+-      if (!da || !pa)
+-              return NULL;
+       LPRINTF("%s: pa=0x%x, da=0x%x, size=0x%x, atrribute=0x%x\r\n",
+               __func__, *pa, *da, size, attribute);
+-      lda = *da;
+-      lpa = *pa;
+       if (!attribute)
+               attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW;
+-      if (lda <= 0x40000) {
++      if (*da <= 0x40000) {
+               metal_phys_addr_t lda_end;
+ 
+-              lda_end = lda + size;
++              lda_end = *da + size;
+               if (priv->cpu_id == NODE_RPU_0 || priv->cpu_id == NODE_RPU) {
+-                      lpa = 0xFFE00000 + lda;
+-                      if (lda < 0x10000)
++                      *pa = 0xFFE00000 + *da;
++                      if (*da < 0x10000)
+                               XPm_RequestNode(NODE_TCM_0_A,
+                                               PM_CAP_ACCESS, 0,
+                                               REQUEST_ACK_BLOCKING);
+-                      if (lda <= 0x20000 && lda_end >= 0x10000)
++                      if (*da <= 0x20000 && lda_end >= 0x10000)
+                               XPm_RequestNode(NODE_TCM_1_A,
+                                               PM_CAP_ACCESS, 0,
+                                               REQUEST_ACK_BLOCKING);
+-                      if (lda <= 0x30000 && lda_end >= 0x20000)
++                      if (*da <= 0x30000 && lda_end >= 0x20000)
+                               XPm_RequestNode(NODE_TCM_0_B,
+                                               PM_CAP_ACCESS, 0,
+                                               REQUEST_ACK_BLOCKING);
+-                      if (lda <= 0x40000 && lda_end >= 0x30000)
++                      if (*da <= 0x40000 && lda_end >= 0x30000)
+                               XPm_RequestNode(NODE_TCM_1_B,
+                                               PM_CAP_ACCESS, 0,
+                                               REQUEST_ACK_BLOCKING);
+               } else if (priv->cpu_id == NODE_RPU_1) {
+-                      lpa = 0xFFE90000 + lda;
+-                      if (lda < 0x10000)
++                      *pa = 0xFFE90000 + *da;
++                      if (*da < 0x10000)
+                               XPm_RequestNode(NODE_TCM_1_A,
+                                               PM_CAP_ACCESS, 0,
+                                               REQUEST_ACK_BLOCKING);
+-                      if (lda <= 0x30000 && lda_end >= 0x20000)
++                      if (*da <= 0x30000 && lda_end >= 0x20000)
+                               XPm_RequestNode(NODE_TCM_1_B,
+                                               PM_CAP_ACCESS, 0,
+                                               REQUEST_ACK_BLOCKING);
+               } else {
+                       LPERROR("mmap failed: invalid cpu node: %d\r\n",
+                               priv->cpu_id);
+-                      return NULL;
++                      return -RPROC_EINVAL;
+               }
+       }
+-      if (lpa == METAL_BAD_PHYS)
+-              lpa = lda;
+-      if (lpa == METAL_BAD_PHYS)
+-              return NULL;
++      if (*pa == METAL_BAD_PHYS)
++              *pa = *da;
++      if (*pa == METAL_BAD_PHYS)
++              return -RPROC_EINVAL;
+       mem = metal_allocate_memory(sizeof(*mem));
+       if (!mem)
+-              return NULL;
+-      mem->pa = lpa;
+-      mem->da = lda;
+-
+-      *io = metal_allocate_memory(sizeof(struct metal_io_region));
+-      if (!*io) {
++              return -RPROC_ENOMEM;
++      tmpio = metal_allocate_memory(sizeof(struct metal_io_region));
++      if (!tmpio) {
+               metal_free_memory(mem);
+-              return NULL;
++              return -RPROC_ENOMEM;
+       }
+-      metal_io_init(*io, (void *)mem->pa, &mem->pa, size,
++      remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio);
++      metal_io_init(tmpio, (void *)mem->pa, &mem->pa, size,
+                     sizeof(metal_phys_addr_t)<<3, attribute, NULL);
+-      mem->io = *io;
+-      metal_list_add_tail(&rproc->mems, &mem->node);
+-      *pa = lpa;
+-      *da = lda;
+-      mem->size = size;
+-      return metal_io_phys_to_virt(*io, mem->pa);
++      remoteproc_add_mem(rproc, mem);
++      *va = metal_io_phys_to_virt(tmpio, mem->pa);
++      if (io)
++              *io = tmpio;
++      return 0;
+ }
+ 
+ int r5_rproc_start(struct remoteproc *rproc)
+diff --git a/apps/machine/zynq7/platform_info.c 
open-amp/apps/machine/zynq7/platform_info.c
+index d753e0e..7885b31 100644
+--- a/apps/machine/zynq7/platform_info.c
++++ open-amp/apps/machine/zynq7/platform_info.c
+@@ -108,16 +108,16 @@ platform_create_proc(int proc_index, int rsc_index)
+        */
+       /* mmap resource table */
+       pa = (metal_phys_addr_t)rsc_table;
+-      (void *)remoteproc_mmap(&rproc_inst, &pa,
+-                              NULL, rsc_size,
+-                              NORM_NONCACHE | STRONG_ORDERED,
+-                              &rproc_inst.rsc_io);
++      remoteproc_mmap(&rproc_inst, &pa,
++                      NULL, NULL, rsc_size,
++                      NORM_NONCACHE | STRONG_ORDERED,
++                      &rproc_inst.rsc_io);
+       /* mmap shared memory */
+       pa = SHARED_MEM_PA;
+-      (void *)remoteproc_mmap(&rproc_inst, &pa,
+-                              NULL, SHARED_MEM_SIZE,
+-                              NORM_NONCACHE | STRONG_ORDERED,
+-                              NULL);
++      remoteproc_mmap(&rproc_inst, &pa,
++                      NULL, NULL, SHARED_MEM_SIZE,
++                      NORM_NONCACHE | STRONG_ORDERED,
++                      NULL);
+ 
+       /* parse resource table to remoteproc */
+       ret = remoteproc_set_rsc_table(&rproc_inst, rsc_table, rsc_size);
+diff --git a/apps/machine/zynq7/zynq_a9_rproc.c 
open-amp/apps/machine/zynq7/zynq_a9_rproc.c
+index f830749..ad7cd49 100644
+--- a/apps/machine/zynq7/zynq_a9_rproc.c
++++ open-amp/apps/machine/zynq7/zynq_a9_rproc.c
+@@ -94,45 +94,43 @@ static void zynq_a9_proc_remove(struct remoteproc *rproc)
+               metal_device_close(dev);
+ }
+ 
+-static void *
++static int
+ zynq_a9_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
+-                      metal_phys_addr_t *da, size_t size,
+-                      unsigned int attribute, struct metal_io_region **io)
++                metal_phys_addr_t *da, void **va, size_t size,
++                unsigned int attribute, struct metal_io_region **io)
+ {
+       struct remoteproc_mem *mem;
+-      metal_phys_addr_t lpa, lda;
+       struct metal_io_region *tmpio;
+ 
+-      lpa = *pa;
+-      lda = *da;
+-
+-      if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS)
+-              return NULL;
+-      if (lpa == METAL_BAD_PHYS)
+-              lpa = lda;
+-      if (lda == METAL_BAD_PHYS)
+-              lda = lpa;
++      /* va is the same as pa/da in this platform */
++      if (*pa != METAL_BAD_PHYS) {
++              *da = *pa;
++              *va = (void *)*pa;
++      } else if (*da != METAL_BAD_PHYS) {
++              *pa = *da;
++              *va = (void *)*da;
++      } else if (*va)
++              *pa = *da = (metal_phys_addr_t)*va;
++      else
++              return -RPROC_EINVAL;
+ 
+       if (!attribute)
+               attribute = NORM_NONCACHE | STRONG_ORDERED;
+       mem = metal_allocate_memory(sizeof(*mem));
+       if (!mem)
+-              return NULL;
++              return -RPROC_ENOMEM;
+       tmpio = metal_allocate_memory(sizeof(*tmpio));
+       if (!tmpio) {
+               metal_free_memory(mem);
+-              return NULL;
++              return -RPROC_ENOMEM;
+       }
+-      remoteproc_init_mem(mem, NULL, lpa, lda, size, tmpio);
+-      /* va is the same as pa in this platform */
+-      metal_io_init(tmpio, (void *)lpa, &mem->pa, size,
++      remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio);
++      metal_io_init(tmpio, *va, &mem->pa, size,
+                     sizeof(metal_phys_addr_t)<<3, attribute, NULL);
+       remoteproc_add_mem(rproc, mem);
+-      *pa = lpa;
+-      *da = lda;
+       if (io)
+               *io = tmpio;
+-      return metal_io_phys_to_virt(tmpio, mem->pa);
++      return 0;
+ }
+ 
+ static int zynq_a9_proc_notify(struct remoteproc *rproc, uint32_t id)
+diff --git a/apps/machine/zynqmp/platform_info.c 
open-amp/apps/machine/zynqmp/platform_info.c
+index 3081ec9..17abcc5 100644
+--- a/apps/machine/zynqmp/platform_info.c
++++ open-amp/apps/machine/zynqmp/platform_info.c
+@@ -84,7 +84,7 @@ static struct rpmsg_virtio_shm_pool shpool;
+ static struct remoteproc *
+ platform_create_proc(int proc_index, int rsc_index)
+ {
+-      void *rsc_table;
++      void *rsc_table = NULL;
+       int rsc_size;
+       int ret;
+       metal_phys_addr_t pa;
+@@ -102,8 +102,8 @@ platform_create_proc(int proc_index, int rsc_index)
+       /* Mmap resource table */
+       pa = RSC_MEM_PA;
+       printf("Calling mmap resource table.\r\n");
+-      rsc_table = remoteproc_mmap(&rproc_inst, &pa, NULL, rsc_size,
+-                                  0, NULL);
++      remoteproc_mmap(&rproc_inst, &pa, NULL, &rsc_table, rsc_size,
++                      0, NULL);
+       if (!rsc_table) {
+               fprintf(stderr, "ERROR: Failed to mmap resource table.\r\n");
+               return NULL;
+diff --git a/apps/machine/zynqmp/zynqmp_linux_r5_proc.c 
open-amp/apps/machine/zynqmp/zynqmp_linux_r5_proc.c
+index 2e4df9d..0950d0b 100644
+--- a/apps/machine/zynqmp/zynqmp_linux_r5_proc.c
++++ open-amp/apps/machine/zynqmp/zynqmp_linux_r5_proc.c
+@@ -143,38 +143,44 @@ static void zynqmp_linux_r5_proc_remove(struct 
remoteproc *rproc)
+         metal_device_close(prproc->shm_dev);
+ }
+ 
+-static void *
++static int
+ zynqmp_linux_r5_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
+-              metal_phys_addr_t *da, size_t size,
+-              unsigned int attribute, struct metal_io_region **io)
++                          metal_phys_addr_t *da, void **va, size_t size,
++                          unsigned int attribute, struct metal_io_region **io)
+ {
+     struct remoteproc_priv *prproc;
+-    metal_phys_addr_t lpa, lda;
+     struct metal_io_region *tmpio;
+ 
+     (void)attribute;
+     (void)size;
+     if (!rproc)
+-        return NULL;
++        return -RPROC_EINVAL;
+     prproc = rproc->priv;
+-    lpa = *pa;
+-    lda = *da;
+ 
+-    if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS)
+-        return NULL;
+-    if (lpa == METAL_BAD_PHYS)
+-        lpa = lda;
+-    if (lda == METAL_BAD_PHYS)
+-        lda = lpa;
+     tmpio = prproc->shm_io;
+     if (!tmpio)
+-        return NULL;
++        return -RPROC_EINVAL;
++
++    if (*pa != METAL_BAD_PHYS) {
++        *da = *pa;
++        *va = metal_io_phys_to_virt(tmpio, *pa);
++        if (!*va)
++            return -RPROC_EINVAL;
++    } else if (*da != METAL_BAD_PHYS) {
++        *pa = *da;
++        *va = metal_io_phys_to_virt(tmpio, *da);
++        if (!*va)
++            return -RPROC_EINVAL;
++    } else if (*va) {
++        *pa = *da = metal_io_virt_to_phys(tmpio, *va);
++        if (*pa == METAL_BAD_PHYS)
++            return -RPROC_EINVAL;
++    } else
++        return -RPROC_EINVAL;
+ 
+-    *pa = lpa;
+-    *da = lda;
+     if (io)
+         *io = tmpio;
+-    return metal_io_phys_to_virt(tmpio, lpa);
++    return 0;
+ }
+ 
+ static int zynqmp_linux_r5_proc_notify(struct remoteproc *rproc, uint32_t id)
+diff --git a/apps/machine/zynqmp_r5/platform_info.c 
open-amp/apps/machine/zynqmp_r5/platform_info.c
+index 96c03c9..a2f7d9d 100644
+--- a/apps/machine/zynqmp_r5/platform_info.c
++++ open-amp/apps/machine/zynqmp_r5/platform_info.c
+@@ -114,16 +114,16 @@ platform_create_proc(int proc_index, int rsc_index)
+        */
+       /* mmap resource table */
+       pa = (metal_phys_addr_t)rsc_table;
+-      (void *)remoteproc_mmap(&rproc_inst, &pa,
+-                              NULL, rsc_size,
+-                              NORM_NSHARED_NCACHE|PRIV_RW_USER_RW,
+-                              &rproc_inst.rsc_io);
++      remoteproc_mmap(&rproc_inst, &pa,
++                      NULL, NULL, rsc_size,
++                      NORM_NSHARED_NCACHE|PRIV_RW_USER_RW,
++                      &rproc_inst.rsc_io);
+       /* mmap shared memory */
+       pa = SHARED_MEM_PA;
+-      (void *)remoteproc_mmap(&rproc_inst, &pa,
+-                              NULL, SHARED_MEM_SIZE,
+-                              NORM_NSHARED_NCACHE|PRIV_RW_USER_RW,
+-                              NULL);
++      remoteproc_mmap(&rproc_inst, &pa,
++                      NULL, NULL, SHARED_MEM_SIZE,
++                      NORM_NSHARED_NCACHE|PRIV_RW_USER_RW,
++                      NULL);
+ 
+       /* parse resource table to remoteproc */
+       ret = remoteproc_set_rsc_table(&rproc_inst, rsc_table, rsc_size);
+diff --git a/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c 
open-amp/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c
+index ee25368..ef5299c 100644
+--- a/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c
++++ open-amp/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c
+@@ -109,45 +109,43 @@ static void zynqmp_r5_a53_proc_remove(struct remoteproc 
*rproc)
+       }
+ }
+ 
+-static void *
++static int
+ zynqmp_r5_a53_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
+-                      metal_phys_addr_t *da, size_t size,
++                      metal_phys_addr_t *da, void **va, size_t size,
+                       unsigned int attribute, struct metal_io_region **io)
+ {
+       struct remoteproc_mem *mem;
+-      metal_phys_addr_t lpa, lda;
+       struct metal_io_region *tmpio;
+ 
+-      lpa = *pa;
+-      lda = *da;
+-
+-      if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS)
+-              return NULL;
+-      if (lpa == METAL_BAD_PHYS)
+-              lpa = lda;
+-      if (lda == METAL_BAD_PHYS)
+-              lda = lpa;
++      /* va is the same as pa/da in this platform */
++      if (*pa != METAL_BAD_PHYS) {
++              *da = *pa;
++              *va = (void *)*pa;
++      } else if (*da != METAL_BAD_PHYS) {
++              *pa = *da;
++              *va = (void *)*da;
++      } else if (*va)
++              *pa = *da = (metal_phys_addr_t)*va;
++      else
++              return -RPROC_EINVAL;
+ 
+       if (!attribute)
+               attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW;
+       mem = metal_allocate_memory(sizeof(*mem));
+       if (!mem)
+-              return NULL;
++              return -RPROC_ENOMEM;
+       tmpio = metal_allocate_memory(sizeof(*tmpio));
+       if (!tmpio) {
+               metal_free_memory(mem);
+-              return NULL;
++              return -RPROC_ENOMEM;
+       }
+-      remoteproc_init_mem(mem, NULL, lpa, lda, size, tmpio);
+-      /* va is the same as pa in this platform */
+-      metal_io_init(tmpio, (void *)lpa, &mem->pa, size,
++      remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio);
++      metal_io_init(tmpio, *va, &mem->pa, size,
+                         sizeof(metal_phys_addr_t)<<3, attribute, NULL);
+       remoteproc_add_mem(rproc, mem);
+-      *pa = lpa;
+-      *da = lda;
+       if (io)
+               *io = tmpio;
+-      return metal_io_phys_to_virt(tmpio, mem->pa);
++      return 0;
+ }
+ 
+ static int zynqmp_r5_a53_proc_notify(struct remoteproc *rproc, uint32_t id)
+diff --git a/apps/system/linux/machine/generic/platform_info.c 
open-amp/apps/system/linux/machine/generic/platform_info.c
+index 5743c5c..66d15c1 100644
+--- a/apps/system/linux/machine/generic/platform_info.c
++++ open-amp/apps/system/linux/machine/generic/platform_info.c
+@@ -319,39 +319,43 @@ static void linux_proc_remove(struct remoteproc *rproc)
+       }
+ }
+ 
+-static void *
++static int
+ linux_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
+-              metal_phys_addr_t *da, size_t size,
++              metal_phys_addr_t *da, void **va, size_t size,
+               unsigned int attribute, struct metal_io_region **io)
+ {
+       struct remoteproc_mem *mem;
+       struct remoteproc_priv *prproc;
+-      metal_phys_addr_t lpa, lda;
+-      void *va;
+ 
+       (void)attribute;
+       (void)size;
+-      lpa = *pa;
+-      lda = *da;
+-
+-      if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS)
+-              return NULL;
+-      if (lpa == METAL_BAD_PHYS)
+-              lpa = lda;
+-      if (lda == METAL_BAD_PHYS)
+-              lda = lpa;
+ 
+       if (!rproc)
+-              return NULL;
++              return -RPROC_EINVAL;
+       prproc = rproc->priv;
+       mem = &prproc->shm;
+-      va = metal_io_phys_to_virt(mem->io, lpa);
+-      if (va) {
+-              if (io)
+-                      *io = mem->io;
+-              metal_list_add_tail(&rproc->mems, &mem->node);
+-      }
+-      return va;
++
++      if (*pa != METAL_BAD_PHYS) {
++              *da = *pa;
++              *va = metal_io_phys_to_virt(mem->io, *pa);
++              if (!*va)
++                      return -RPROC_EINVAL;
++      } else if (*da != METAL_BAD_PHYS) {
++              *pa = *da;
++              *va = metal_io_phys_to_virt(mem->io, *da);
++              if (!*va)
++                      return -RPROC_EINVAL;
++      } else if (*va) {
++              *pa = *da = metal_io_virt_to_phys(mem->io, *va);
++              if (*pa == METAL_BAD_PHYS)
++                      return -RPROC_EINVAL;
++      } else
++              return -RPROC_EINVAL;
++
++      remoteproc_add_mem(rproc, mem);
++      if (io)
++              *io = mem->io;
++      return 0;
+ }
+ 
+ static int linux_proc_notify(struct remoteproc *rproc, uint32_t id)
+@@ -420,7 +424,7 @@ static struct remoteproc *
+ platform_create_proc(int proc_index, int rsc_index)
+ {
+       struct remoteproc_priv *prproc;
+-      void *rsc_table, *rsc_table_shm;
++      void *rsc_table, *rsc_table_shm = NULL;
+       int rsc_size;
+       int ret;
+       metal_phys_addr_t pa;
+@@ -449,8 +453,8 @@ platform_create_proc(int proc_index, int rsc_index)
+ 
+       /* Mmap resource table */
+       pa = RSC_MEM_PA;
+-      rsc_table_shm = remoteproc_mmap(&rproc_inst, &pa, NULL, rsc_size,
+-                                      0, &rproc_inst.rsc_io);
++      remoteproc_mmap(&rproc_inst, &pa, NULL, &rsc_table_shm, rsc_size,
++                      0, &rproc_inst.rsc_io);
+ 
+       /* parse resource table to remoteproc */
+       ret = remoteproc_set_rsc_table(&rproc_inst, rsc_table_shm, rsc_size);
+diff --git a/lib/include/openamp/remoteproc.h 
open-amp/lib/include/openamp/remoteproc.h
+index a83aa12..b34cb1a 100644
+--- a/lib/include/openamp/remoteproc.h
++++ open-amp/lib/include/openamp/remoteproc.h
+@@ -400,10 +400,10 @@ struct remoteproc_ops {
+       struct remoteproc *(*init)(struct remoteproc *rproc,
+                                  struct remoteproc_ops *ops, void *arg);
+       void (*remove)(struct remoteproc *rproc);
+-      void *(*mmap)(struct remoteproc *rproc,
+-                    metal_phys_addr_t *pa, metal_phys_addr_t *da,
+-                    size_t size, unsigned int attribute,
+-                    struct metal_io_region **io);
++      int (*mmap)(struct remoteproc *rproc,
++                  metal_phys_addr_t *pa, metal_phys_addr_t *da,
++                  void **va, size_t size, unsigned int attribute,
++                  struct metal_io_region **io);
+       int (*handle_rsc)(struct remoteproc *rproc, void *rsc, size_t len);
+       int (*config)(struct remoteproc *rproc, void *data);
+       int (*start)(struct remoteproc *rproc);
+@@ -606,16 +606,17 @@ remoteproc_get_io_with_va(struct remoteproc *rproc,
+  * @rproc - pointer to the remote processor
+  * @pa - physical address pointer
+  * @da - device address pointer
++ * @va - virtual address pointer
+  * @size - size of the memory
+  * @attribute - memory attribute
+  * @io - pointer to the I/O region
+  *
+- * returns pointer to the memory
++ * returns 0 for success and negative value for errors
+  */
+-void *remoteproc_mmap(struct remoteproc *rproc,
+-                    metal_phys_addr_t *pa, metal_phys_addr_t *da,
+-                    size_t size, unsigned int attribute,
+-                    struct metal_io_region **io);
++int remoteproc_mmap(struct remoteproc *rproc,
++                  metal_phys_addr_t *pa, metal_phys_addr_t *da,
++                  void **va, size_t size, unsigned int attribute,
++                  struct metal_io_region **io);
+ 
+ /**
+  * remoteproc_set_rsc_table
+diff --git a/lib/remoteproc/remoteproc.c open-amp/lib/remoteproc/remoteproc.c
+index 057edc6..27fcdb4 100644
+--- a/lib/remoteproc/remoteproc.c
++++ open-amp/lib/remoteproc/remoteproc.c
+@@ -295,13 +295,14 @@ struct metal_io_region *
+ remoteproc_get_io_with_pa(struct remoteproc *rproc,
+                         metal_phys_addr_t pa)
+ {
+-      struct remoteproc_mem *mem;
++      struct metal_io_region *io;
++      int ret;
+ 
+-      mem = remoteproc_get_mem(rproc, NULL, pa, METAL_BAD_PHYS, NULL, 0);
+-      if (mem)
+-              return mem->io;
+-      else
++      ret = remoteproc_mmap(rproc, &pa, NULL, NULL, 0, 0, &io);
++      if (ret < 0)
+               return NULL;
++
++      return io;
+ }
+ 
+ struct metal_io_region *
+@@ -309,48 +310,44 @@ remoteproc_get_io_with_da(struct remoteproc *rproc,
+                         metal_phys_addr_t da,
+                         unsigned long *offset)
+ {
+-      struct remoteproc_mem *mem;
+-
+-      mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, da, NULL, 0);
+-      if (mem) {
+-              struct metal_io_region *io;
+-              metal_phys_addr_t pa;
++      struct metal_io_region *io;
++      metal_phys_addr_t pa = METAL_BAD_PHYS;
++      int ret;
+ 
+-              io = mem->io;
+-              pa = remoteproc_datopa(mem, da);
+-              *offset = metal_io_phys_to_offset(io, pa);
+-              return io;
+-      } else {
++      ret = remoteproc_mmap(rproc, &pa, &da, NULL, 0, 0, &io);
++      if (ret < 0)
+               return NULL;
+-      }
++
++      *offset = metal_io_phys_to_offset(io, pa);
++      return io;
+ }
+ 
+ struct metal_io_region *
+ remoteproc_get_io_with_va(struct remoteproc *rproc, void *va)
+ {
+-      struct remoteproc_mem *mem;
++      struct metal_io_region *io;
++      int ret;
+ 
+-      mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, METAL_BAD_PHYS,
+-                               va, 0);
+-      if (mem)
+-              return mem->io;
+-      else
++      ret = remoteproc_mmap(rproc, NULL, NULL, &va, 0, 0, &io);
++      if (ret < 0)
+               return NULL;
++
++      return io;
+ }
+ 
+-void *remoteproc_mmap(struct remoteproc *rproc,
+-                    metal_phys_addr_t *pa, metal_phys_addr_t *da,
+-                    size_t size, unsigned int attribute,
+-                    struct metal_io_region **io)
++int remoteproc_mmap(struct remoteproc *rproc,
++                  metal_phys_addr_t *pa, metal_phys_addr_t *da,
++                  void **va, size_t size, unsigned int attribute,
++                  struct metal_io_region **io)
+ {
+-      void *va = NULL;
++      void *lva = NULL;
+       metal_phys_addr_t lpa, lda;
+       struct remoteproc_mem *mem;
+ 
+       if (!rproc)
+-              return NULL;
+-      else if (!pa && !da)
+-              return NULL;
++              return -RPROC_EINVAL;
++      else if (!pa && !da && !va)
++              return -RPROC_EINVAL;
+       if (pa)
+               lpa = *pa;
+       else
+@@ -359,24 +356,40 @@ void *remoteproc_mmap(struct remoteproc *rproc,
+               lda =  *da;
+       else
+               lda = METAL_BAD_PHYS;
+-      mem = remoteproc_get_mem(rproc, NULL, lpa, lda, NULL, size);
++      if (va)
++              lva = *va;
++      mem = remoteproc_get_mem(rproc, NULL, lpa, lda, lva, size);
+       if (mem) {
+-              if (lpa != METAL_BAD_PHYS)
++              if (lpa != METAL_BAD_PHYS) {
+                       lda = remoteproc_patoda(mem, lpa);
+-              else if (lda != METAL_BAD_PHYS)
++                      lva = metal_io_phys_to_virt(mem->io, lpa);
++              } else if (lda != METAL_BAD_PHYS) {
+                       lpa = remoteproc_datopa(mem, lda);
++                      lva = metal_io_phys_to_virt(mem->io, lpa);
++              } else if (lva != NULL) {
++                      lpa = metal_io_virt_to_phys(mem->io, lva);
++                      lda = remoteproc_patoda(mem, lpa);
++              }
+               if (io)
+                       *io = mem->io;
+-              va = metal_io_phys_to_virt(mem->io, lpa);
+-      } else if (rproc->ops->mmap) {
+-              va = rproc->ops->mmap(rproc, &lpa, &lda, size, attribute, io);
++      } else {
++              int ret = -RPROC_EINVAL;
++
++              if (rproc->ops->mmap)
++                      ret = rproc->ops->mmap(rproc, &lpa, &lda, &lva, size, 
attribute, io);
++
++              if (ret < 0)
++                      return ret;
+       }
+ 
+       if (pa)
+               *pa  = lpa;
+       if (da)
+               *da = lda;
+-      return va;
++      if (va)
++              *va = lva;
++
++      return 0;
+ }
+ 
+ int remoteproc_load(struct remoteproc *rproc, const char *path,
+@@ -529,8 +542,8 @@ int remoteproc_load(struct remoteproc *rproc, const char 
*path,
+                       img_data = NULL;
+                       /* get the I/O region from remoteproc */
+                       pa = METAL_BAD_PHYS;
+-                      (void)remoteproc_mmap(rproc, &pa, &da, nmemsize, 0, 
&io);
+-                      if (pa == METAL_BAD_PHYS || io == NULL) {
++                      remoteproc_mmap(rproc, &pa, &da, NULL, nmemsize, 0, 
&io);
++                      if (pa == METAL_BAD_PHYS || !io) {
+                               metal_log(METAL_LOG_ERROR,
+                                         "load failed, no mapping for 
0x%llx.\r\n",
+                                         da);
+@@ -599,8 +612,9 @@ int remoteproc_load(struct remoteproc *rproc, const char 
*path,
+ 
+               metal_log(METAL_LOG_DEBUG,
+                         "%s, update resource table\r\n", __func__);
+-              rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da,
+-                                          rsc_size, 0, &io);
++              rsc_table = NULL;
++              remoteproc_mmap(rproc, NULL, &rsc_da,
++                              &rsc_table, rsc_size, 0, &io);
+               if (rsc_table) {
+                       size_t rsc_io_offset;
+ 
+@@ -759,8 +773,8 @@ int remoteproc_load_noblock(struct remoteproc *rproc,
+               if (da != RPROC_LOAD_ANYADDR) {
+                       /* get the I/O region from remoteproc */
+                       *pa = METAL_BAD_PHYS;
+-                      (void)remoteproc_mmap(rproc, pa, &da, *nmlen, 0, io);
+-                      if (*pa == METAL_BAD_PHYS || io == NULL) {
++                      remoteproc_mmap(rproc, pa, &da, NULL, *nmlen, 0, io);
++                      if (*pa == METAL_BAD_PHYS || !io) {
+                               metal_log(METAL_LOG_ERROR,
+                                         "load failed, no mapping for 
0x%llx.\r\n",
+                                         da);
+@@ -784,9 +798,9 @@ int remoteproc_load_noblock(struct remoteproc *rproc,
+                               ret = -RPROC_ENOMEM;
+                               goto error1;
+                       }
+-                      rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da,
+-                                                  rsc_size, 0, io);
+-                      if (*io == NULL) {
++                      remoteproc_mmap(rproc, NULL, &rsc_da,
++                                      &rsc_table, rsc_size, 0, io);
++                      if (!*io) {
+                               metal_log(METAL_LOG_ERROR,
+                                         "load failed: failed to mmap 
rsc\r\n");
+                               metal_free_memory(lrsc_table);
+@@ -923,7 +937,7 @@ remoteproc_create_virtio(struct remoteproc *rproc,
+               metal_phys_addr_t da;
+               unsigned int num_descs, align;
+               struct metal_io_region *io;
+-              void *va;
++              void *va = NULL;
+               size_t size;
+               int ret;
+ 
+@@ -933,7 +947,7 @@ remoteproc_create_virtio(struct remoteproc *rproc,
+               num_descs = vring_rsc->num;
+               align = vring_rsc->align;
+               size = vring_size(num_descs, align);
+-              va = remoteproc_mmap(rproc, NULL, &da, size, 0, &io);
++              remoteproc_mmap(rproc, NULL, &da, &va, size, 0, &io);
+               if (!va)
+                       goto err1;
+               ret = rproc_virtio_init_vring(vdev, i, notifyid,
+diff --git a/lib/remoteproc/rsc_table_parser.c 
open-amp/lib/remoteproc/rsc_table_parser.c
+index 184a463..816a0ee 100644
+--- a/lib/remoteproc/rsc_table_parser.c
++++ open-amp/lib/remoteproc/rsc_table_parser.c
+@@ -109,7 +109,7 @@ int handle_carve_out_rsc(struct remoteproc *rproc, void 
*rsc)
+       da = carve_rsc->da;
+       size = carve_rsc->len;
+       attribute = carve_rsc->flags;
+-      if (remoteproc_mmap(rproc, &pa, &da, size, attribute, NULL))
++      if (remoteproc_mmap(rproc, &pa, &da, NULL, size, attribute, NULL))
+               return 0;
+       else
+               return -RPROC_EINVAL;
+-- 
+2.17.1
+
diff --git a/openamp/0007-rpmsg-bring-back-zero-copy-transfer.patch 
b/openamp/0007-rpmsg-bring-back-zero-copy-transfer.patch
new file mode 100644
index 0000000..5a65e52
--- /dev/null
+++ b/openamp/0007-rpmsg-bring-back-zero-copy-transfer.patch
@@ -0,0 +1,470 @@
+From 4224f5f028aec8ebc13e1e203cbae3127b07605e Mon Sep 17 00:00:00 2001
+From: anchao <anc...@pinecone.net>
+Date: Mon, 10 Dec 2018 19:39:01 +0800
+Subject: [PATCH 07/10] rpmsg: bring back zero copy transfer
+
+Commit-id:
+b16ca55 Adding RPMsg Extension layer implementing zero-copy send and receive.
+
+Signed-off-by: anchao <anc...@pinecone.net>
+---
+ lib/include/openamp/rpmsg.h | 178 ++++++++++++++++++++++++++++++++++++
+ lib/rpmsg/rpmsg.c           |  58 ++++++++++++
+ lib/rpmsg/rpmsg_internal.h  |   3 +
+ lib/rpmsg/rpmsg_virtio.c    | 130 +++++++++++++++++++++++++-
+ 4 files changed, 367 insertions(+), 2 deletions(-)
+
+diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
+index 1279ea2..0b46ee1 100644
+--- a/lib/include/openamp/rpmsg.h
++++ open-amp/lib/include/openamp/rpmsg.h
+@@ -89,9 +89,20 @@ struct rpmsg_endpoint {
+ 
+ /**
+  * struct rpmsg_device_ops - RPMsg device operations
++ * @hold_rx_buffer: hold RPMsg RX buffer
++ * @release_rx_buffer: release RPMsg RX buffer
++ * @get_tx_payload_buffer: get RPMsg TX buffer
++ * @send_offchannel_nocopy: send RPMsg data without copy
+  * @send_offchannel_raw: send RPMsg data
+  */
+ struct rpmsg_device_ops {
++      void (*hold_rx_buffer)(struct rpmsg_device *rdev, void *rxbuf);
++      void (*release_rx_buffer)(struct rpmsg_device *rdev, void *rxbuf);
++      void *(*get_tx_payload_buffer)(struct rpmsg_device *rdev,
++                                     uint32_t *len, int wait);
++      int (*send_offchannel_nocopy)(struct rpmsg_device *rdev,
++                                    uint32_t src, uint32_t dst,
++                                     const void *data, int len);
+       int (*send_offchannel_raw)(struct rpmsg_device *rdev,
+                                  uint32_t src, uint32_t dst,
+                                  const void *data, int size, int wait);
+@@ -294,6 +305,173 @@ static inline int rpmsg_trysend_offchannel(struct 
rpmsg_endpoint *ept,
+       return rpmsg_send_offchannel_raw(ept, src, dst, data, len, false);
+ }
+ 
++/**
++ * @brief Holds the rx buffer for usage outside the receive callback.
++ *
++ * Calling this function prevents the RPMsg receive buffer from being released
++ * back to the pool of shmem buffers. This API can only be called at rx
++ * callback context (rpmsg_rx_cb_t). With this API, the application doesn't
++ * need to copy the message in rx callback. Instead, the rx buffer base 
address
++ * is saved in application context and further processed in application
++ * process. After the message is processed, the application can release the rx
++ * buffer for future reuse in vring by calling the rpmsg_release_rx_buffer()
++ * function.
++ *
++ * @param: ept The rpmsg endpoint
++ * @param: rxbuf RX buffer with message payload
++ *
++ * @see rpmsg_release_rx_buffer
++ */
++void rpmsg_hold_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf);
++
++/**
++ * @brief Releases the rx buffer for future reuse in vring.
++ *
++ * This API can be called at process context when the message in rx buffer is
++ * processed.
++ *
++ * @ept: the rpmsg endpoint
++ * @rxbuf: rx buffer with message payload
++ *
++ * @see rpmsg_hold_rx_buffer
++ */
++void rpmsg_release_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf);
++
++/**
++ * @brief Gets the tx buffer for message payload.
++ *
++ * This API can only be called at process context to get the tx buffer in 
vring.
++ * By this way, the application can directly put its message into the vring tx
++ * buffer without copy from an application buffer.
++ * It is the application responsibility to correctly fill the allocated tx
++ * buffer by data and passing correct parameters to the rpmsg_send_nocopy() or
++ * rpmsg_sendto_nocopy() function to perform data no-copy-send mechanism.
++ *
++ * @ept:  Pointer to rpmsg endpoint
++ * @len:  Pointer to store tx buffer size
++ * @wait: Boolean, wait or not for buffer to become available
++ *
++ * @return The tx buffer address on success and NULL on failure
++ *
++ * @see rpmsg_send_offchannel_nocopy
++ * @see rpmsg_sendto_nocopy
++ * @see rpmsg_send_nocopy
++ */
++void *rpmsg_get_tx_payload_buffer(struct rpmsg_endpoint *ept,
++                                uint32_t *len, int wait);
++
++/**
++ * rpmsg_send_offchannel_nocopy() - send a message in tx buffer reserved by
++ * rpmsg_get_tx_payload_buffer() across to the remote processor.
++ *
++ * This function sends buf of length len to the remote dst address,
++ * and uses src as the source address.
++ * The message will be sent to the remote processor which the ept
++ * endpoint belongs to.
++ * The application has to take the responsibility for:
++ *  1. tx buffer reserved (rpmsg_get_tx_payload_buffer() )
++ *  2. filling the data to be sent into the pre-allocated tx buffer
++ *  3. not exceeding the buffer size when filling the data
++ *  4. data cache coherency
++ *
++ * After the rpmsg_send_offchannel_nocopy() function is issued the tx buffer 
is
++ * no more owned by the sending task and must not be touched anymore unless 
the
++ * rpmsg_send_offchannel_nocopy() function fails and returns an error. In that
++ * case the application should try to re-issue the 
rpmsg_send_offchannel_nocopy()
++ * again.
++ *
++ * @ept:  The rpmsg endpoint
++ * @src:  The rpmsg endpoint local address
++ * @dst:  The rpmsg endpoint remote address
++ * @data: TX buffer with message filled
++ * @len:  Length of payload
++ *
++ * @return number of bytes it has sent or negative error value on failure.
++ *
++ * @see rpmsg_get_tx_payload_buffer
++ * @see rpmsg_sendto_nocopy
++ * @see rpmsg_send_nocopy
++ */
++int rpmsg_send_offchannel_nocopy(struct rpmsg_endpoint *ept, uint32_t src,
++                               uint32_t dst, const void *data, int len);
++
++/**
++ * @brief Sends a message in tx buffer allocated by 
rpmsg_get_tx_payload_buffer()
++ * across to the remote processor, specify dst.
++ *
++ * This function sends buf of length len to the remote dst address.
++ * The message will be sent to the remote processor which the ept
++ * endpoint belongs to, using ept's source address.
++ * The application has to take the responsibility for:
++ *  1. tx buffer allocation (rpmsg_get_tx_payload_buffer() )
++ *  2. filling the data to be sent into the pre-allocated tx buffer
++ *  3. not exceeding the buffer size when filling the data
++ *  4. data cache coherency
++ *
++ * After the rpmsg_sendto_nocopy() function is issued the tx buffer is no more
++ * owned by the sending task and must not be touched anymore unless the
++ * rpmsg_sendto_nocopy() function fails and returns an error. In that case the
++ * application should try to re-issue the rpmsg_sendto_nocopy() again.
++ *
++ * @ept:  The rpmsg endpoint
++ * @data: TX buffer with message filled
++ * @len:  Length of payload
++ * @dst:  Destination address
++ *
++ * @return number of bytes it has sent or negative error value on failure.
++ *
++ * @see rpmsg_get_tx_payload_buffer
++ * @see rpmsg_send_offchannel_nocopy
++ * @see rpmsg_send_nocopy
++ */
++static inline int rpmsg_sendto_nocopy(struct rpmsg_endpoint *ept,
++                                    const void *data, int len, uint32_t dst)
++{
++      return rpmsg_send_offchannel_nocopy(ept, ept->addr, dst, data, len);
++}
++
++/**
++ * rpmsg_send_nocopy() - send a message in tx buffer reserved by
++ * rpmsg_get_tx_payload_buffer() across to the remote processor.
++ *
++ * This function sends buf of length len on the ept endpoint.
++ * The message will be sent to the remote processor which the ept
++ * endpoint belongs to, using ept's source and destination addresses.
++ * The application has to take the responsibility for:
++ *  1. tx buffer reserved (rpmsg_get_tx_payload_buffer() )
++ *  2. filling the data to be sent into the pre-allocated tx buffer
++ *  3. not exceeding the buffer size when filling the data
++ *  4. data cache coherency
++ *
++ * After the rpmsg_send_nocopy() function is issued the tx buffer is no more
++ * owned by the sending task and must not be touched anymore unless the
++ * rpmsg_send_nocopy() function fails and returns an error. In that case the
++ * application should try to re-issue the rpmsg_send_nocopy() again.
++ *
++ * @ept:  The rpmsg endpoint
++ * @data: TX buffer with message filled
++ * @len:  Length of payload
++ *
++ * @return number of bytes it has sent or negative error value on failure.
++ *
++ * @see rpmsg_get_tx_payload_buffer
++ * @see rpmsg_send_offchannel_nocopy
++ * @see rpmsg_sendto_nocopy
++ */
++static inline int rpmsg_send_nocopy(struct rpmsg_endpoint *ept, const void 
*data, int len)
++{
++      int tc = 0;
++
++      for (; tc < RPMSG_TICK_COUNT; tc += RPMSG_TICKS_PER_INTERVAL) {
++              if (is_rpmsg_ept_ready(ept))
++                      return rpmsg_send_offchannel_nocopy(ept, ept->addr,
++                                                          ept->dest_addr, 
data, len);
++              metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL);
++      }
++
++      return RPMSG_ERR_ADDR;
++}
++
+ /**
+  * rpmsg_init_ept - initialize rpmsg endpoint
+  *
+diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c
+index 9da38a1..0a8de1b 100644
+--- a/lib/rpmsg/rpmsg.c
++++ open-amp/lib/rpmsg/rpmsg.c
+@@ -144,6 +144,64 @@ int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, 
unsigned long flags)
+               return RPMSG_SUCCESS;
+ }
+ 
++void rpmsg_hold_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf)
++{
++      struct rpmsg_device *rdev;
++
++      if (!ept || !ept->rdev || !rxbuf)
++              return;
++
++      rdev = ept->rdev;
++
++      if (rdev->ops.hold_rx_buffer)
++              rdev->ops.hold_rx_buffer(rdev, rxbuf);
++}
++
++void rpmsg_release_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf)
++{
++      struct rpmsg_device *rdev;
++
++      if (!ept || !ept->rdev || !rxbuf)
++              return;
++
++      rdev = ept->rdev;
++
++      if (rdev->ops.release_rx_buffer)
++              rdev->ops.release_rx_buffer(rdev, rxbuf);
++}
++
++void *rpmsg_get_tx_payload_buffer(struct rpmsg_endpoint *ept,
++                                uint32_t *len, int wait)
++{
++      struct rpmsg_device *rdev;
++
++      if (!ept || !ept->rdev || !len)
++              return NULL;
++
++      rdev = ept->rdev;
++
++      if (rdev->ops.get_tx_payload_buffer)
++              return rdev->ops.get_tx_payload_buffer(rdev, len, wait);
++
++      return NULL;
++}
++
++int rpmsg_send_offchannel_nocopy(struct rpmsg_endpoint *ept, uint32_t src,
++                               uint32_t dst, const void *data, int len)
++{
++      struct rpmsg_device *rdev;
++
++      if (!ept || !ept->rdev || !data || !dst || dst == RPMSG_ADDR_ANY)
++              return RPMSG_ERR_PARAM;
++
++      rdev = ept->rdev;
++
++      if (rdev->ops.send_offchannel_nocopy)
++              return rdev->ops.send_offchannel_nocopy(rdev, src, dst, data, 
len);
++
++      return RPMSG_ERR_PARAM;
++}
++
+ struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rdev,
+                                         const char *name, uint32_t addr,
+                                         uint32_t dest_addr)
+diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h
+index 9c46970..3db6b24 100644
+--- a/lib/rpmsg/rpmsg_internal.h
++++ open-amp/lib/rpmsg/rpmsg_internal.h
+@@ -35,6 +35,9 @@ extern "C" {
+       } while (0)
+ #endif
+ 
++#define RPMSG_BUF_HELD (1U << 31) /* Flag to suggest to hold the buffer */
++
++#define RPMSG_LOCATE_HDR(p) (struct rpmsg_hdr *)((char *)(p) - sizeof(struct 
rpmsg_hdr))
+ #define RPMSG_LOCATE_DATA(p) ((unsigned char *)(p) + sizeof(struct rpmsg_hdr))
+ /**
+  * enum rpmsg_ns_flags - dynamic name service announcement flags
+diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c
+index 17f2998..a525066 100644
+--- a/lib/rpmsg/rpmsg_virtio.c
++++ open-amp/lib/rpmsg/rpmsg_virtio.c
+@@ -140,6 +140,7 @@ static void *rpmsg_virtio_get_tx_buffer(struct 
rpmsg_virtio_device *rvdev,
+                       data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool,
+                                                       RPMSG_BUFFER_SIZE);
+                       *len = RPMSG_BUFFER_SIZE;
++                      *idx = 0;
+               }
+       }
+ #endif /*!VIRTIO_SLAVE_ONLY*/
+@@ -253,6 +254,118 @@ static int _rpmsg_virtio_get_buffer_size(struct 
rpmsg_virtio_device *rvdev)
+       return length;
+ }
+ 
++static void rpmsg_virtio_hold_rx_buffer(struct rpmsg_device *rdev, void 
*rxbuf)
++{
++      struct rpmsg_hdr *rp_hdr;
++
++      rp_hdr = RPMSG_LOCATE_HDR(rxbuf);
++
++      /* Set held status to keep buffer */
++      rp_hdr->reserved = RPMSG_BUF_HELD;
++}
++
++static void rpmsg_virtio_release_rx_buffer(struct rpmsg_device *rdev, void 
*rxbuf)
++{
++      struct rpmsg_virtio_device *rvdev;
++      struct rpmsg_hdr *rp_hdr;
++      uint16_t idx;
++      uint32_t len;
++
++      rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev);
++      rp_hdr = RPMSG_LOCATE_HDR(rxbuf);
++      /* The reserved field contains buffer index */
++      idx = rp_hdr->reserved;
++
++      metal_mutex_acquire(&rdev->lock);
++      /* Return buffer on virtqueue. */
++      len = virtqueue_get_buffer_length(rvdev->rvq, idx);
++      rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx);
++      metal_mutex_release(&rdev->lock);
++}
++
++static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev,
++                                              uint32_t *len, int wait)
++{
++      struct rpmsg_virtio_device *rvdev;
++      struct rpmsg_hdr *rp_hdr;
++      uint16_t idx;
++      int tick_count;
++
++      /* Get the associated remote device for channel. */
++      rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev);
++
++      if (wait)
++              tick_count = RPMSG_TICK_COUNT / RPMSG_TICKS_PER_INTERVAL;
++      else
++              tick_count = 0;
++
++      while (1) {
++              /* Lock the device to enable exclusive access to virtqueues */
++              metal_mutex_acquire(&rdev->lock);
++              rp_hdr = rpmsg_virtio_get_tx_buffer(rvdev, len, &idx);
++              metal_mutex_release(&rdev->lock);
++              if (rp_hdr || !tick_count)
++                      break;
++              metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL);
++              tick_count--;
++      }
++
++      if (!rp_hdr)
++              return NULL;
++
++      /* Store the index into the reserved field to be used when sending */
++      rp_hdr->reserved = idx;
++
++      /* Actual data buffer size is vring buffer size minus rpmsg header 
length */
++      *len -= sizeof(struct rpmsg_hdr);
++      return RPMSG_LOCATE_DATA(rp_hdr);
++}
++
++static int rpmsg_virtio_send_offchannel_nocopy(struct rpmsg_device *rdev,
++                                             uint32_t src, uint32_t dst,
++                                             const void *data, int len)
++{
++      struct rpmsg_virtio_device *rvdev;
++      struct rpmsg_hdr rp_hdr;
++      struct rpmsg_hdr *hdr;
++      uint16_t idx;
++      int status;
++      struct metal_io_region *io;
++
++      /* Get the associated remote device for channel. */
++      rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev);
++
++      hdr = RPMSG_LOCATE_HDR(data);
++      /* The reserved field contains buffer index */
++      idx = hdr->reserved;
++
++      /* Initialize RPMSG header. */
++      rp_hdr.dst = dst;
++      rp_hdr.src = src;
++      rp_hdr.len = len;
++      rp_hdr.reserved = 0;
++      rp_hdr.flags = 0;
++
++      /* Copy data to rpmsg buffer. */
++      io = rvdev->shbuf_io;
++      status = metal_io_block_write(io, metal_io_virt_to_offset(io, hdr),
++                                    &rp_hdr, sizeof(rp_hdr));
++      RPMSG_ASSERT(status == sizeof(rp_hdr), "failed to write header\r\n");
++
++      metal_mutex_acquire(&rdev->lock);
++
++      /* Enqueue buffer on virtqueue. */
++      len = virtqueue_get_buffer_length(rvdev->svq, idx);
++      status = rpmsg_virtio_enqueue_buffer(rvdev, hdr, len, idx);
++      RPMSG_ASSERT(status == VQUEUE_SUCCESS, "failed to enqueue buffer\r\n");
++      /* Let the other side know that there is a job to process. */
++      virtqueue_kick(rvdev->svq);
++
++      metal_mutex_release(&rdev->lock);
++
++      return len;
++}
++
+ /**
+  * This function sends rpmsg "message" to remote device.
+  *
+@@ -389,6 +502,8 @@ static void rpmsg_virtio_rx_callback(struct virtqueue *vq)
+       metal_mutex_release(&rdev->lock);
+ 
+       while (rp_hdr) {
++              rp_hdr->reserved = 0;
++
+               /* Get the channel node from the remote device channels list. */
+               metal_mutex_acquire(&rdev->lock);
+               ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst);
+@@ -411,8 +526,15 @@ static void rpmsg_virtio_rx_callback(struct virtqueue *vq)
+ 
+               metal_mutex_acquire(&rdev->lock);
+ 
+-              /* Return used buffers. */
+-              rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx);
++              /* Check whether callback wants to hold buffer */
++              if (rp_hdr->reserved & RPMSG_BUF_HELD) {
++                      /* 'rp_hdr->reserved' field is now used as storage for
++                       * 'idx' to release buffer later */
++                      rp_hdr->reserved = idx;
++              } else {
++                      /* Return used buffers. */
++                      rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx);
++              }
+ 
+               rp_hdr = rpmsg_virtio_get_rx_buffer(rvdev, &len, &idx);
+               if (rp_hdr == NULL) {
+@@ -522,6 +644,10 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+       rvdev->vdev = vdev;
+       rdev->ns_bind_cb = ns_bind_cb;
+       vdev->priv = rvdev;
++      rdev->ops.hold_rx_buffer = rpmsg_virtio_hold_rx_buffer;
++      rdev->ops.release_rx_buffer = rpmsg_virtio_release_rx_buffer;
++      rdev->ops.get_tx_payload_buffer = rpmsg_virtio_get_tx_payload_buffer;
++      rdev->ops.send_offchannel_nocopy = rpmsg_virtio_send_offchannel_nocopy;
+       rdev->ops.send_offchannel_raw = rpmsg_virtio_send_offchannel_raw;
+       role = rpmsg_virtio_get_role(rvdev);
+ 
+-- 
+2.17.1
+
diff --git a/openamp/0008-ns-acknowledge-the-received-creation-message.patch 
b/openamp/0008-ns-acknowledge-the-received-creation-message.patch
new file mode 100644
index 0000000..1f527b7
--- /dev/null
+++ b/openamp/0008-ns-acknowledge-the-received-creation-message.patch
@@ -0,0 +1,132 @@
+From c2d2e03d9a0ddf9e1782c33fd459973c9bc7275a Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Mon, 7 Jan 2019 02:15:42 +0800
+Subject: [PATCH 08/10] ns: acknowledge the received creation message
+
+the two phase handsake make the client could initiate the transfer
+immediately without the server side send any dummy message first.
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ lib/include/openamp/rpmsg.h        |  1 +
+ lib/include/openamp/rpmsg_virtio.h |  1 +
+ lib/rpmsg/rpmsg.c                  |  7 +++++--
+ lib/rpmsg/rpmsg_internal.h         |  4 ++--
+ lib/rpmsg/rpmsg_virtio.c           | 12 +++++++++---
+ 5 files changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
+index 0b46ee1..318acd1 100644
+--- a/lib/include/openamp/rpmsg.h
++++ open-amp/lib/include/openamp/rpmsg.h
+@@ -127,6 +127,7 @@ struct rpmsg_device {
+       rpmsg_ns_bind_cb ns_bind_cb;
+       struct rpmsg_device_ops ops;
+       bool support_ns;
++      bool support_ack;
+ };
+ 
+ /**
+diff --git a/lib/include/openamp/rpmsg_virtio.h 
open-amp/lib/include/openamp/rpmsg_virtio.h
+index 528b9bf..a2dd504 100644
+--- a/lib/include/openamp/rpmsg_virtio.h
++++ open-amp/lib/include/openamp/rpmsg_virtio.h
+@@ -28,6 +28,7 @@ extern "C" {
+ 
+ /* The feature bitmap for virtio rpmsg */
+ #define VIRTIO_RPMSG_F_NS     0 /* RP supports name service notifications */
++#define VIRTIO_RPMSG_F_ACK    1 /* RP supports name service acknowledge */
+ 
+ /**
+  * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers
+diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c
+index 0a8de1b..0cc80da 100644
+--- a/lib/rpmsg/rpmsg.c
++++ open-amp/lib/rpmsg/rpmsg.c
+@@ -297,10 +297,13 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct 
rpmsg_device *rdev,
+ 
+       rpmsg_init_ept(ept, rdev, name, addr, dest, cb, unbind_cb);
+ 
+-      if (rdev->support_ns && ept->dest_addr == RPMSG_ADDR_ANY) {
++      if (ept->name[0]) {
+               /* Send NS announcement to remote processor */
+               metal_mutex_release(&rdev->lock);
+-              status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE);
++              if (rdev->support_ns && ept->dest_addr == RPMSG_ADDR_ANY)
++                      status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE);
++              else if (rdev->support_ack && ept->dest_addr != RPMSG_ADDR_ANY)
++                      status = rpmsg_send_ns_message(ept, 
RPMSG_NS_CREATE_ACK);
+               metal_mutex_acquire(&rdev->lock);
+               if (status)
+                       rpmsg_unregister_endpoint(ept);
+diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h
+index 3db6b24..d513a56 100644
+--- a/lib/rpmsg/rpmsg_internal.h
++++ open-amp/lib/rpmsg/rpmsg_internal.h
+@@ -44,12 +44,12 @@ extern "C" {
+  *
+  * @RPMSG_NS_CREATE: a new remote service was just created
+  * @RPMSG_NS_DESTROY: a known remote service was just destroyed
+- * @RPMSG_NS_CREATE_WITH_ACK: a new remote service was just created waiting
+- *                            acknowledgment.
++ * @RPMSG_NS_CREATE_ACK: acknowledge the previous creation message
+  */
+ enum rpmsg_ns_flags {
+       RPMSG_NS_CREATE = 0,
+       RPMSG_NS_DESTROY = 1,
++      RPMSG_NS_CREATE_ACK = 2,
+ };
+ 
+ /**
+diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c
+index a525066..e57b1c2 100644
+--- a/lib/rpmsg/rpmsg_virtio.c
++++ open-amp/lib/rpmsg/rpmsg_virtio.c
+@@ -586,13 +586,13 @@ static int rpmsg_virtio_ns_callback(struct 
rpmsg_endpoint *ept, void *data,
+       metal_mutex_acquire(&rdev->lock);
+       _ept = rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest);
+ 
+-      if (ns_msg->flags & RPMSG_NS_DESTROY) {
++      if (ns_msg->flags == RPMSG_NS_DESTROY) {
+               if (_ept)
+                       _ept->dest_addr = RPMSG_ADDR_ANY;
+               metal_mutex_release(&rdev->lock);
+               if (_ept && _ept->ns_unbind_cb)
+                       _ept->ns_unbind_cb(ept);
+-      } else {
++      } else if (ns_msg->flags == RPMSG_NS_CREATE) {
+               if (!_ept) {
+                       /*
+                        * send callback to application, that can
+@@ -607,6 +607,11 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint 
*ept, void *data,
+                       _ept->dest_addr = dest;
+                       metal_mutex_release(&rdev->lock);
+               }
++      } else { /* RPMSG_NS_CREATE_ACK */
++              /* save the received destination address */
++              if (_ept)
++                      _ept->dest_addr = dest;
++              metal_mutex_release(&rdev->lock);
+       }
+ 
+       return RPMSG_SUCCESS;
+@@ -659,6 +664,7 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+ #endif /*!VIRTIO_MASTER_ONLY*/
+       vdev->features = rpmsg_virtio_get_features(rvdev);
+       rdev->support_ns = !!(vdev->features & (1 << VIRTIO_RPMSG_F_NS));
++      rdev->support_ack = !!(vdev->features & (1 << VIRTIO_RPMSG_F_ACK));
+ 
+ #ifndef VIRTIO_SLAVE_ONLY
+       if (role == RPMSG_MASTER) {
+@@ -754,7 +760,7 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+        * Create name service announcement endpoint if device supports name
+        * service announcement feature.
+        */
+-      if (rdev->support_ns) {
++      if (rdev->support_ns || rdev->support_ack) {
+               rpmsg_init_ept(&rdev->ns_ept, rdev, "NS",
+                              RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR,
+                              rpmsg_virtio_ns_callback, NULL);
+-- 
+2.17.1
+
diff --git 
a/openamp/0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch 
b/openamp/0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch
new file mode 100644
index 0000000..7faf2b3
--- /dev/null
+++ b/openamp/0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch
@@ -0,0 +1,119 @@
+From 1d94cd9ae8345543fa93c12cdc11ccbc2ca5b127 Mon Sep 17 00:00:00 2001
+From: Xiang Xiao <xiaoxi...@xiaomi.com>
+Date: Thu, 3 Jan 2019 14:20:48 +0800
+Subject: [PATCH 09/10] implement
+ rproc_virtio_read_config/rproc_virtio_write_config
+
+so the rpmsg could access the configuration space as needed
+
+Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
+---
+ lib/include/openamp/rpmsg_virtio.h | 14 +++++++++++
+ lib/include/openamp/virtio.h       |  1 +
+ lib/remoteproc/remoteproc_virtio.c | 40 ++++++++++++++++++++++++------
+ 3 files changed, 47 insertions(+), 8 deletions(-)
+
+diff --git a/lib/include/openamp/rpmsg_virtio.h 
open-amp/lib/include/openamp/rpmsg_virtio.h
+index a2dd504..e7c670e 100644
+--- a/lib/include/openamp/rpmsg_virtio.h
++++ open-amp/lib/include/openamp/rpmsg_virtio.h
+@@ -86,6 +86,20 @@ rpmsg_virtio_get_features(struct rpmsg_virtio_device *rvdev)
+       return rvdev->vdev->func->get_features(rvdev->vdev);
+ }
+ 
++static inline void
++rpmsg_virtio_read_config(struct rpmsg_virtio_device *rvdev,
++                       uint32_t offset, void *dst, int length)
++{
++      rvdev->vdev->func->read_config(rvdev->vdev, offset, dst, length);
++}
++
++static inline void
++rpmsg_virtio_write_config(struct rpmsg_virtio_device *rvdev,
++                       uint32_t offset, void *dst, int length)
++{
++      rvdev->vdev->func->write_config(rvdev->vdev, offset, dst, length);
++}
++
+ static inline int
+ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev,
+                              int flags, unsigned int nvqs,
+diff --git a/lib/include/openamp/virtio.h open-amp/lib/include/openamp/virtio.h
+index 7085554..a93e0d9 100644
+--- a/lib/include/openamp/virtio.h
++++ open-amp/lib/include/openamp/virtio.h
+@@ -100,6 +100,7 @@ struct virtio_device {
+       virtio_dev_reset_cb reset_cb; /**< user registered device callback */
+       const struct virtio_dispatch *func; /**< Virtio dispatch table */
+       void *priv; /**< TODO: remove pointer to virtio_device private data */
++      unsigned int config_len;  /**< config space length */
+       unsigned int vrings_num; /**< number of vrings */
+       struct virtio_vring_info *vrings_info;
+ };
+diff --git a/lib/remoteproc/remoteproc_virtio.c 
open-amp/lib/remoteproc/remoteproc_virtio.c
+index e495d81..6a3b28b 100644
+--- a/lib/remoteproc/remoteproc_virtio.c
++++ open-amp/lib/remoteproc/remoteproc_virtio.c
+@@ -126,20 +126,43 @@ static uint32_t rproc_virtio_negotiate_features(struct 
virtio_device *vdev,
+ static void rproc_virtio_read_config(struct virtio_device *vdev,
+                                    uint32_t offset, void *dst, int length)
+ {
+-      (void)vdev;
+-      (void)offset;
+-      (void)dst;
+-      (void)length;
++      struct remoteproc_virtio *rpvdev;
++      struct fw_rsc_vdev *vdev_rsc;
++      struct metal_io_region *io;
++      char *config;
++
++      if (offset + length > vdev->config_len || offset + length < length)
++              return;
++
++      rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev);
++      vdev_rsc = rpvdev->vdev_rsc;
++      config = (char *)(&vdev_rsc->vring[vdev->vrings_num]);
++      io = rpvdev->vdev_rsc_io;
++      metal_io_block_read(io,
++                          metal_io_virt_to_offset(io, config + offset),
++                          dst, length);
+ }
+ 
+ #ifndef VIRTIO_SLAVE_ONLY
+ static void rproc_virtio_write_config(struct virtio_device *vdev,
+                                     uint32_t offset, void *src, int length)
+ {
+-      (void)vdev;
+-      (void)offset;
+-      (void)src;
+-      (void)length;
++      struct remoteproc_virtio *rpvdev;
++      struct fw_rsc_vdev *vdev_rsc;
++      struct metal_io_region *io;
++      char *config;
++
++      if (offset + length > vdev->config_len || offset + length < length)
++              return;
++
++      rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev);
++      vdev_rsc = rpvdev->vdev_rsc;
++      config = (char *)(&vdev_rsc->vring[vdev->vrings_num]);
++      io = rpvdev->vdev_rsc_io;
++      metal_io_block_write(io,
++                          metal_io_virt_to_offset(io, config + offset),
++                          src, length);
++      rpvdev->notify(rpvdev->priv, vdev->notifyid);
+ }
+ 
+ static void rproc_virtio_reset_device(struct virtio_device *vdev)
+@@ -220,6 +243,7 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int 
notifyid,
+       vdev->notifyid = notifyid;
+       vdev->role = role;
+       vdev->reset_cb = rst_cb;
++      vdev->config_len = vdev_rsc->config_len;
+       vdev->vrings_num = num_vrings;
+       vdev->func = &remoteproc_virtio_dispatch_funcs;
+ 
+-- 
+2.17.1
+
diff --git a/openamp/0010-Negotiate-individual-buffer-size-dynamically.patch 
b/openamp/0010-Negotiate-individual-buffer-size-dynamically.patch
new file mode 100644
index 0000000..60d1ce8
--- /dev/null
+++ b/openamp/0010-Negotiate-individual-buffer-size-dynamically.patch
@@ -0,0 +1,159 @@
+From f5f905a5c7b63e0b90a6b67e45d70305e6dfaa2c Mon Sep 17 00:00:00 2001
+From: anchao <anc...@pinecone.net>
+Date: Mon, 10 Dec 2018 16:26:39 +0800
+Subject: [PATCH 10/10] Negotiate individual buffer size dynamically
+
+If slave support VIRTIO_RPMSG_F_BUFSZ(0x04) feature, master
+determine the buffer size from config space(first 8 bytes),
+otherwise the default size(512 bytes) will be used.
+
+Signed-off-by: anchao <anc...@pinecone.net>
+---
+ lib/include/openamp/remoteproc.h   | 17 +++++++++++++++++
+ lib/include/openamp/rpmsg_virtio.h |  4 ++++
+ lib/rpmsg/rpmsg_virtio.c           | 22 ++++++++++++++++------
+ 3 files changed, 37 insertions(+), 6 deletions(-)
+
+diff --git a/lib/include/openamp/remoteproc.h 
open-amp/lib/include/openamp/remoteproc.h
+index b34cb1a..ee9162a 100644
+--- a/lib/include/openamp/remoteproc.h
++++ open-amp/lib/include/openamp/remoteproc.h
+@@ -303,6 +303,23 @@ struct fw_rsc_vdev {
+       struct fw_rsc_vdev_vring vring[0];
+ } METAL_PACKED_END;
+ 
++/**
++ * struct fw_rsc_config - configuration space declaration
++ * @txbuf_size: the tx buffer size
++ * @rxbuf_size: the rx buffer size
++ * @reserved: reserved (must be zero)
++ *
++ * This structure immediately follow fw_rsc_vdev to provide the config info.
++ */
++METAL_PACKED_BEGIN
++struct fw_rsc_config {
++      /* The tx/rx individual buffer size(if VIRTIO_RPMSG_F_BUFSZ) */
++      uint32_t txbuf_size;
++      uint32_t rxbuf_size;
++      uint32_t reserved[14]; /* Reserve for the future use */
++      /* Put the customize config here */
++} METAL_PACKED_END;
++
+ /**
+  * struct fw_rsc_vendor - remote processor vendor specific resource
+  * @len: length of the resource
+diff --git a/lib/include/openamp/rpmsg_virtio.h 
open-amp/lib/include/openamp/rpmsg_virtio.h
+index e7c670e..e58c84e 100644
+--- a/lib/include/openamp/rpmsg_virtio.h
++++ open-amp/lib/include/openamp/rpmsg_virtio.h
+@@ -16,6 +16,7 @@
+ #include <metal/mutex.h>
+ #include <openamp/rpmsg.h>
+ #include <openamp/virtio.h>
++#include <openamp/remoteproc.h>
+ 
+ #if defined __cplusplus
+ extern "C" {
+@@ -29,6 +30,7 @@ extern "C" {
+ /* The feature bitmap for virtio rpmsg */
+ #define VIRTIO_RPMSG_F_NS     0 /* RP supports name service notifications */
+ #define VIRTIO_RPMSG_F_ACK    1 /* RP supports name service acknowledge */
++#define VIRTIO_RPMSG_F_BUFSZ  2 /* RP supports get buffer size from config 
space */
+ 
+ /**
+  * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers
+@@ -45,6 +47,7 @@ struct rpmsg_virtio_shm_pool {
+ /**
+  * struct rpmsg_virtio_device - representation of a rpmsg device based on 
virtio
+  * @rdev: rpmsg device, first property in the struct
++ * @config: rpmsg config information
+  * @vdev: pointer to the virtio device
+  * @rvq: pointer to receive virtqueue
+  * @svq: pointer to send virtqueue
+@@ -53,6 +56,7 @@ struct rpmsg_virtio_shm_pool {
+  */
+ struct rpmsg_virtio_device {
+       struct rpmsg_device rdev;
++      struct fw_rsc_config config;
+       struct virtio_device *vdev;
+       struct virtqueue *rvq;
+       struct virtqueue *svq;
+diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c
+index e57b1c2..792a3b1 100644
+--- a/lib/rpmsg/rpmsg_virtio.c
++++ open-amp/lib/rpmsg/rpmsg_virtio.c
+@@ -138,8 +138,8 @@ static void *rpmsg_virtio_get_tx_buffer(struct 
rpmsg_virtio_device *rvdev,
+               data = virtqueue_get_buffer(rvdev->svq, len, idx);
+               if (data == NULL) {
+                       data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool,
+-                                                      RPMSG_BUFFER_SIZE);
+-                      *len = RPMSG_BUFFER_SIZE;
++                                                      
rvdev->config.rxbuf_size);
++                      *len = rvdev->config.rxbuf_size;
+                       *idx = 0;
+               }
+       }
+@@ -232,7 +232,7 @@ static int _rpmsg_virtio_get_buffer_size(struct 
rpmsg_virtio_device *rvdev)
+                * If device role is Master then buffers are provided by us,
+                * so just provide the macro.
+                */
+-              length = RPMSG_BUFFER_SIZE - sizeof(struct rpmsg_hdr);
++              length = rvdev->config.rxbuf_size - sizeof(struct rpmsg_hdr);
+       }
+ #endif /*!VIRTIO_SLAVE_ONLY*/
+ 
+@@ -649,11 +649,14 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+       rvdev->vdev = vdev;
+       rdev->ns_bind_cb = ns_bind_cb;
+       vdev->priv = rvdev;
++      rvdev->config.txbuf_size = RPMSG_BUFFER_SIZE;
++      rvdev->config.rxbuf_size = RPMSG_BUFFER_SIZE;
+       rdev->ops.hold_rx_buffer = rpmsg_virtio_hold_rx_buffer;
+       rdev->ops.release_rx_buffer = rpmsg_virtio_release_rx_buffer;
+       rdev->ops.get_tx_payload_buffer = rpmsg_virtio_get_tx_payload_buffer;
+       rdev->ops.send_offchannel_nocopy = rpmsg_virtio_send_offchannel_nocopy;
+       rdev->ops.send_offchannel_raw = rpmsg_virtio_send_offchannel_raw;
++
+       role = rpmsg_virtio_get_role(rvdev);
+ 
+ #ifndef VIRTIO_MASTER_ONLY
+@@ -666,6 +669,13 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+       rdev->support_ns = !!(vdev->features & (1 << VIRTIO_RPMSG_F_NS));
+       rdev->support_ack = !!(vdev->features & (1 << VIRTIO_RPMSG_F_ACK));
+ 
++      if (vdev->features & (1 << VIRTIO_RPMSG_F_BUFSZ)) {
++              rpmsg_virtio_read_config(rvdev,
++                      0,
++                      &rvdev->config,
++                      sizeof(rvdev->config));
++      }
++
+ #ifndef VIRTIO_SLAVE_ONLY
+       if (role == RPMSG_MASTER) {
+               /*
+@@ -726,11 +736,11 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+               unsigned int idx;
+               void *buffer;
+ 
+-              vqbuf.len = RPMSG_BUFFER_SIZE;
++              vqbuf.len = rvdev->config.txbuf_size;
+               for (idx = 0; idx < rvdev->rvq->vq_nentries; idx++) {
+                       /* Initialize TX virtqueue buffers for remote device */
+                       buffer = rpmsg_virtio_shm_pool_get_buffer(shpool,
+-                                                      RPMSG_BUFFER_SIZE);
++                                              rvdev->config.txbuf_size);
+ 
+                       if (!buffer) {
+                               return RPMSG_ERR_NO_BUFF;
+@@ -741,7 +751,7 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
+                       metal_io_block_set(shm_io,
+                                          metal_io_virt_to_offset(shm_io,
+                                                                  buffer),
+-                                         0x00, RPMSG_BUFFER_SIZE);
++                                         0x00, rvdev->config.txbuf_size);
+                       status =
+                               virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1,
+                                                    buffer);
+-- 
+2.17.1
+
diff --git a/openamp/Makefile b/openamp/Makefile
index b9e82ce..9f2c254 100644
--- a/openamp/Makefile
+++ b/openamp/Makefile
@@ -41,6 +41,8 @@ CSRCS =
 VPATH := $(SRCDIR)
 DEPPATH = --dep-path .
 
+VERSION ?= 2020.01.0
+
 include libmetal.defs
 include open-amp.defs
 
@@ -73,7 +75,6 @@ dirlinks::
 depend: .depend
 
 clean:
-       $(foreach obj,$(OBJS),$(call DELFILE, $(obj)))
        $(call DELFILE, $(BIN))
        $(call CLEAN)
 
diff --git a/openamp/libmetal.defs b/openamp/libmetal.defs
index cf5b46f..d851011 100644
--- a/openamp/libmetal.defs
+++ b/openamp/libmetal.defs
@@ -37,15 +37,10 @@ ifeq ($(CONFIG_OPENAMP),y)
 
 ifeq ($(CONFIG_ARCH), sim)
 LIBMETAL_ARCH = x86_64
-else
-LIBMETAL_ARCH = $(subst -,,$(CONFIG_ARCH))
+else ifeq ($(CONFIG_ARCH), risc-v)
+LIBMETAL_ARCH = riscv
 endif
 
-LIBMETAL_HDRS += $(wildcard libmetal/lib/compiler/gcc/*.h)
-LIBMETAL_HDRS += $(wildcard libmetal/lib/processor/$(LIBMETAL_ARCH)/*.h)
-LIBMETAL_HDRS += $(wildcard libmetal/lib/system/nuttx/*.h)
-LIBMETAL_HDRS += $(wildcard libmetal/lib/*.h)
-
 CSRCS += libmetal/lib/system/nuttx/condition.c
 CSRCS += libmetal/lib/system/nuttx/device.c
 CSRCS += libmetal/lib/system/nuttx/init.c
@@ -77,11 +72,21 @@ LIBMETAL_HDRS_SEDEXP := \
         s/@PROJECT_MACHINE_UPPER@/$(CONFIG_ARCH_CHIP)/g; \
         s/cmakedefine/undef/g"
 
-.libmetal_headers: $(LIBMETAL_HDRS)
-       $(foreach headers,$(LIBMETAL_HDRS), \
-               $(eval hobj := $(patsubst 
libmetal$(DELIM)lib$(DELIM)%,$(TOPDIR)$(DELIM)include$(DELIM)metal$(DELIM)%,$(headers)))
 \
+libmetal.zip:
+       $(Q) wget https://github.com/OpenAMP/libmetal/archive/v$(VERSION).zip 
-O libmetal.zip
+       $(Q) unzip -o libmetal.zip
+       $(Q) mv libmetal-$(VERSION) libmetal
+       $(Q) patch -p0 < 
0001-nuttx-change-sched_kfree-to-metal_free_memory.patch
+
+.libmetal_headers: libmetal.zip
+       $(eval headers := $(wildcard libmetal/lib/compiler/gcc/*.h))
+       $(eval headers += $(wildcard 
libmetal/lib/processor/$(LIBMETAL_ARCH)/*.h))
+       $(eval headers += $(wildcard libmetal/lib/system/nuttx/*.h))
+       $(eval headers += $(wildcard libmetal/lib/*.h))
+       $(foreach header,$(headers), \
+               $(eval hobj := $(patsubst 
libmetal$(DELIM)lib$(DELIM)%,$(TOPDIR)$(DELIM)include$(DELIM)metal$(DELIM)%,$(header)))
 \
                $(shell if [ ! -d $(dir $(hobj)) ];then mkdir -p $(dir 
$(hobj)); fi) \
-               $(shell sed $(LIBMETAL_HDRS_SEDEXP) $(headers) > $(hobj)) \
+               $(shell sed $(LIBMETAL_HDRS_SEDEXP) $(header) > $(hobj)) \
        )
        touch $@
 
@@ -89,6 +94,8 @@ dirlinks:: .libmetal_headers
 
 distclean::
        $(call DELDIR, $(TOPDIR)$(DELIM)include$(DELIM)metal)
+       $(call DELDIR, libmetal)
+       $(call DELFILE, libmetal.zip)
        $(call DELFILE, .libmetal_headers)
 
 endif
diff --git a/openamp/open-amp.defs b/openamp/open-amp.defs
index 6391eec..dda86d9 100644
--- a/openamp/open-amp.defs
+++ b/openamp/open-amp.defs
@@ -35,8 +35,6 @@
 
 ifeq ($(CONFIG_OPENAMP),y)
 
-OPENAMP_HDRS += $(wildcard open-amp/lib/include/openamp/*.h)
-
 CSRCS += open-amp/lib/remoteproc/elf_loader.c
 CSRCS += open-amp/lib/remoteproc/remoteproc.c
 CSRCS += open-amp/lib/remoteproc/remoteproc_virtio.c
@@ -46,15 +44,33 @@ CSRCS += open-amp/lib/rpmsg/rpmsg_virtio.c
 CSRCS += open-amp/lib/virtio/virtio.c
 CSRCS += open-amp/lib/virtio/virtqueue.c
 
-.openamp_headers: $(OPENAMP_HDRS)
+open-amp.zip:
+       $(Q) wget https://github.com/OpenAMP/open-amp/archive/v$(VERSION).zip 
-O open-amp.zip
+       $(Q) unzip -o open-amp.zip
+       $(Q) mv open-amp-$(VERSION) open-amp
+       $(Q) patch -p0 < 
0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch
+       $(Q) patch -p0 < 
0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch
+       $(Q) patch -p0 < 
0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch
+       $(Q) patch -p0 < 0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch
+       $(Q) patch -p0 < 
0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch
+       $(Q) patch -p0 < 
0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch
+       $(Q) patch -p0 < 0007-rpmsg-bring-back-zero-copy-transfer.patch
+       $(Q) patch -p0 < 0008-ns-acknowledge-the-received-creation-message.patch
+       $(Q) patch -p0 < 
0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch
+       $(Q) patch -p0 < 0010-Negotiate-individual-buffer-size-dynamically.patch
+
+.openamp_headers: open-amp.zip
+       $(eval headers := $(wildcard open-amp/lib/include/openamp/*.h))
        $(shell mkdir -p $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM))
-       $(foreach header,$^,$(shell cp -rf $(header) 
$(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM)))
+       $(foreach header,$(headers),$(shell cp -rf $(header) 
$(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM)))
        touch $@
 
 dirlinks:: .openamp_headers
 
 distclean::
        $(call DELDIR, $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM))
+       $(call DELDIR, open-amp)
+       $(call DELFILE, open-amp.zip)
        $(call DELFILE, .openamp_headers)
 
 endif

Reply via email to