diff --git a/arch/sim/src/sim/posix/sim_hostmemory.c b/arch/sim/src/sim/posix/sim_hostmemory.c index 4677b70681..f65d820c64 100644 --- a/arch/sim/src/sim/posix/sim_hostmemory.c +++ b/arch/sim/src/sim/posix/sim_hostmemory.c @@ -92,32 +92,20 @@ void host_freeheap(void *mem) host_uninterruptible(munmap, mem, 0); } -void *host_allocshmem(const char *name, size_t size, int master) +void *host_allocshmem(const char *name, size_t size) { void *mem; int oflag; int ret; int fd; - oflag = O_RDWR; - if (master) - { - oflag |= O_CREAT | O_TRUNC; - } - + oflag = O_RDWR | O_CREAT; fd = host_uninterruptible(shm_open, name, oflag, S_IRUSR | S_IWUSR); if (fd < 0) { return NULL; } - if (!master) - { - /* Avoid the second slave instance open successfully */ - - host_unlinkshmem(name); - } - ret = host_uninterruptible(ftruncate, fd, size); if (ret < 0) { diff --git a/arch/sim/src/sim/sim_internal.h b/arch/sim/src/sim/sim_internal.h index a78260eb08..bad8bd8a8c 100644 --- a/arch/sim/src/sim/sim_internal.h +++ b/arch/sim/src/sim/sim_internal.h @@ -224,7 +224,7 @@ int host_waitpid(pid_t pid); void *host_allocheap(size_t size, bool exec); void host_freeheap(void *mem); -void *host_allocshmem(const char *name, size_t size, int master); +void *host_allocshmem(const char *name, size_t size); void host_freeshmem(void *mem); size_t host_mallocsize(void *mem); diff --git a/arch/sim/src/sim/sim_rptun.c b/arch/sim/src/sim/sim_rptun.c index 2a1e21a3dd..fd9cb1874f 100644 --- a/arch/sim/src/sim/sim_rptun.c +++ b/arch/sim/src/sim/sim_rptun.c @@ -40,6 +40,12 @@ #define SIM_RPTUN_SHIFT 16 #define SIM_RPTUN_WORK_DELAY 1 +/* Status byte for master/slave to report progress */ + +#define SIM_RPTUN_STATUS_BOOT 0x01 +#define SIM_RPTUN_STATUS_OK 0x02 +#define SIM_RPTUN_STATUS_NEED_RESET 0x04 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -51,6 +57,8 @@ struct sim_rptun_shmem_s volatile unsigned int seqm; volatile unsigned int cmds; volatile unsigned int cmdm; + volatile unsigned int boots; + volatile unsigned int bootm; struct rptun_rsc_s rsc; char buf[0x10000]; }; @@ -91,24 +99,14 @@ sim_rptun_get_resource(struct rptun_dev_s *dev) struct sim_rptun_dev_s *priv = container_of(dev, struct sim_rptun_dev_s, rptun); - if (priv->shmem) - { - return &priv->shmem->rsc; - } - - while (priv->shmem == NULL) - { - priv->shmem = host_allocshmem(priv->shmemname, - sizeof(*priv->shmem), - priv->master); - usleep(1000); - - /* Master isn't ready, sleep and try again */ - } + priv->shmem = host_allocshmem(priv->shmemname, + sizeof(*priv->shmem)); if (priv->master) { struct rptun_rsc_s *rsc = &priv->shmem->rsc; + memset(priv->shmem->buf, 0, sizeof(priv->shmem->buf)); + memset(rsc, 0, sizeof(struct rptun_rsc_s)); rsc->rsc_tbl_hdr.ver = 1; rsc->rsc_tbl_hdr.num = 1; @@ -121,9 +119,11 @@ sim_rptun_get_resource(struct rptun_dev_s *dev) | 1 << VIRTIO_RPMSG_F_BUFSZ; rsc->rpmsg_vdev.config_len = sizeof(struct fw_rsc_config); rsc->rpmsg_vdev.num_of_vrings = 2; + rsc->rpmsg_vring0.da = 0; rsc->rpmsg_vring0.align = 8; rsc->rpmsg_vring0.num = 8; rsc->rpmsg_vring0.notifyid = RSC_NOTIFY_ID_ANY; + rsc->rpmsg_vring1.da = 0; rsc->rpmsg_vring1.align = 8; rsc->rpmsg_vring1.num = 8; rsc->rpmsg_vring1.notifyid = RSC_NOTIFY_ID_ANY; @@ -131,16 +131,36 @@ sim_rptun_get_resource(struct rptun_dev_s *dev) rsc->config.h2r_buf_size = 0x800; priv->shmem->base = (uintptr_t)priv->shmem; + + /* The master notifies its slave when it starts again */ + + if (priv->shmem->boots & SIM_RPTUN_STATUS_OK) + { + priv->shmem->boots = SIM_RPTUN_STATUS_NEED_RESET; + } + + priv->shmem->bootm = SIM_RPTUN_STATUS_BOOT; } else { + /* The slave notifies its master when it starts again */ + + if (priv->shmem->boots & SIM_RPTUN_STATUS_OK) + { + priv->shmem->bootm = SIM_RPTUN_STATUS_NEED_RESET; + } + + priv->shmem->boots = SIM_RPTUN_STATUS_BOOT; + /* Wait untils master is ready */ - while (priv->shmem->base == 0) + while (!(priv->shmem->bootm & SIM_RPTUN_STATUS_OK)) { usleep(1000); } + priv->shmem->boots = SIM_RPTUN_STATUS_OK; + priv->addrenv[0].va = (uintptr_t)priv->shmem; priv->addrenv[0].pa = priv->shmem->base; priv->addrenv[0].size = sizeof(*priv->shmem); @@ -180,6 +200,14 @@ static int sim_rptun_start(struct rptun_dev_s *dev) priv->pid = pid; } + /* Wait until slave has started */ + + while (!(priv->shmem->boots & SIM_RPTUN_STATUS_BOOT)) + { + usleep(1000); + } + + priv->shmem->bootm = SIM_RPTUN_STATUS_OK; return 0; } @@ -188,13 +216,21 @@ static int sim_rptun_stop(struct rptun_dev_s *dev) struct sim_rptun_dev_s *priv = container_of(dev, struct sim_rptun_dev_s, rptun); - if ((priv->master & SIM_RPTUN_BOOT) && (priv->pid > 0)) + /* Don't send SIM_RPTUN_STOP when slave recovery */ + + if (priv->shmem->boots & SIM_RPTUN_STATUS_OK) { priv->shmem->cmdm = SIM_RPTUN_STOP << SIM_RPTUN_SHIFT; + } + + if ((priv->master & SIM_RPTUN_BOOT) && priv->pid > 0) + { host_waitpid(priv->pid); } - if (priv->shmem) + /* Master cleans shmem when both sides are about to exit */ + + if (priv->shmem && (priv->shmem->boots & SIM_RPTUN_STATUS_OK)) { host_freeshmem(priv->shmem); priv->shmem = NULL; @@ -267,6 +303,22 @@ static void sim_rptun_check_cmd(struct sim_rptun_dev_s *priv) } } +static void sim_rptun_check_reset(struct sim_rptun_dev_s *priv) +{ + if (priv->master && + (priv->shmem->bootm & SIM_RPTUN_STATUS_NEED_RESET)) + { + priv->shmem->bootm = 0; + rptun_boot(priv->cpuname); + } + else if (!priv->master && + (priv->shmem->boots & SIM_RPTUN_STATUS_NEED_RESET)) + { + priv->shmem->boots = 0; + rptun_boot(priv->cpuname); + } +} + static void sim_rptun_work(void *arg) { struct sim_rptun_dev_s *dev = arg; @@ -277,6 +329,10 @@ static void sim_rptun_work(void *arg) sim_rptun_check_cmd(dev); + /* Check if master/slave need to reset */ + + sim_rptun_check_reset(dev); + if (dev->master && dev->seq != dev->shmem->seqs) { dev->seq = dev->shmem->seqs; diff --git a/arch/sim/src/sim/sim_uart.c b/arch/sim/src/sim/sim_uart.c index f5e51f8c27..deced81576 100644 --- a/arch/sim/src/sim/sim_uart.c +++ b/arch/sim/src/sim/sim_uart.c @@ -675,7 +675,7 @@ static int sim_uartram_register(const char *devname, bool slave) struct uart_rambuf_s *shmem; strlcpy(name, strrchr(devname, '/') + 1, NAME_MAX); - shmem = host_allocshmem(name, sizeof(struct uart_rambuf_s) * 2, !slave); + shmem = host_allocshmem(name, sizeof(struct uart_rambuf_s) * 2); DEBUGASSERT(shmem); memset(shmem, 0, sizeof(struct uart_rambuf_s) * 2); diff --git a/arch/sim/src/sim/win/sim_hostmemory.c b/arch/sim/src/sim/win/sim_hostmemory.c index 98844efdab..e0359cb20f 100644 --- a/arch/sim/src/sim/win/sim_hostmemory.c +++ b/arch/sim/src/sim/win/sim_hostmemory.c @@ -56,7 +56,7 @@ void host_freeheap(void *mem) _aligned_free(mem); } -void *host_allocshmem(const char *name, size_t size, int master) +void *host_allocshmem(const char *name, size_t size) { HANDLE handle; void *mem;