update components & lwp. (#7888)
This commit is contained in:
parent
7e7b303dd4
commit
4d20416b2f
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <rtthread.h>
|
||||
#include <dfs_fs.h>
|
||||
#include <dfs_file.h>
|
||||
|
||||
#include <drivers/mmcsd_core.h>
|
||||
#include <drivers/gpt.h>
|
||||
|
@ -25,6 +26,8 @@
|
|||
static rt_list_t blk_devices = RT_LIST_OBJECT_INIT(blk_devices);
|
||||
|
||||
#define BLK_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define RT_DEVICE_CTRL_BLK_SSIZEGET 0x1268 /**< get number of bytes per sector */
|
||||
#define RT_DEVICE_CTRL_ALL_BLK_SSIZEGET 0x80081272 /**< get number of bytes per sector * sector counts*/
|
||||
|
||||
struct mmcsd_blk_device
|
||||
{
|
||||
|
@ -267,6 +270,7 @@ static rt_err_t rt_mmcsd_close(rt_device_t dev)
|
|||
static rt_err_t rt_mmcsd_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case RT_DEVICE_CTRL_BLK_GETGEOME:
|
||||
|
@ -274,6 +278,16 @@ static rt_err_t rt_mmcsd_control(rt_device_t dev, int cmd, void *args)
|
|||
break;
|
||||
case RT_DEVICE_CTRL_BLK_PARTITION:
|
||||
rt_memcpy(args, &blk_dev->part, sizeof(struct dfs_partition));
|
||||
break;
|
||||
case RT_DEVICE_CTRL_BLK_SSIZEGET:
|
||||
rt_memcpy(args, &blk_dev->geometry.bytes_per_sector, sizeof(rt_uint32_t));
|
||||
break;
|
||||
case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET:
|
||||
{
|
||||
rt_uint64_t count_mul_per = blk_dev->geometry.bytes_per_sector * blk_dev->geometry.sector_count;
|
||||
rt_memcpy(args, &count_mul_per, sizeof(rt_uint64_t));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -414,6 +428,207 @@ const static struct rt_device_ops mmcsd_blk_ops =
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_DFS_V2
|
||||
|
||||
static ssize_t rt_mmcsd_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
int result = 0;
|
||||
rt_device_t dev = (rt_device_t)file->vnode->data;
|
||||
struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data;
|
||||
int bytes_per_sector = blk_dev->geometry.bytes_per_sector;
|
||||
int blk_pos = *pos / bytes_per_sector;
|
||||
int first_offs = *pos % bytes_per_sector;
|
||||
char *rbuf;
|
||||
int rsize = 0;
|
||||
|
||||
rbuf = rt_malloc(bytes_per_sector);
|
||||
if (!rbuf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** #1: read first unalign block size.
|
||||
*/
|
||||
result = rt_mmcsd_read(dev, blk_pos, rbuf, 1);
|
||||
if (result != 1)
|
||||
{
|
||||
rt_free(rbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count > bytes_per_sector - first_offs)
|
||||
{
|
||||
rsize = bytes_per_sector - first_offs;
|
||||
}
|
||||
else
|
||||
{
|
||||
rsize = count;
|
||||
}
|
||||
rt_memcpy(buf, rbuf + first_offs, rsize);
|
||||
blk_pos++;
|
||||
|
||||
/*
|
||||
** #2: read continuous block size.
|
||||
*/
|
||||
while (rsize < count)
|
||||
{
|
||||
result = rt_mmcsd_read(dev, blk_pos++, rbuf, 1);
|
||||
if (result != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (count - rsize >= bytes_per_sector)
|
||||
{
|
||||
rt_memcpy(buf + rsize, rbuf, bytes_per_sector);
|
||||
rsize += bytes_per_sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_memcpy(buf + rsize, rbuf, count - rsize);
|
||||
rsize = count;
|
||||
}
|
||||
}
|
||||
|
||||
rt_free(rbuf);
|
||||
*pos += rsize;
|
||||
|
||||
return rsize;
|
||||
}
|
||||
|
||||
static int rt_mmcsd_fops_ioctl(struct dfs_file *file, int cmd, void *arg)
|
||||
{
|
||||
rt_device_t dev = (rt_device_t)file->vnode->data;
|
||||
|
||||
return rt_mmcsd_control(dev,cmd,arg);
|
||||
}
|
||||
|
||||
static int rt_mmcsd_fops_open(struct dfs_file *file)
|
||||
{
|
||||
rt_device_t dev = (rt_device_t)file->vnode->data;
|
||||
rt_mmcsd_control(dev, RT_DEVICE_CTRL_ALL_BLK_SSIZEGET, &file->vnode->size);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static int rt_mmcsd_fops_close(struct dfs_file *file)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static ssize_t rt_mmcsd_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
int result = 0;
|
||||
rt_device_t dev = (rt_device_t)file->vnode->data;
|
||||
struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data;
|
||||
int bytes_per_sector = blk_dev->geometry.bytes_per_sector;
|
||||
int blk_pos = *pos / bytes_per_sector;
|
||||
int first_offs = *pos % bytes_per_sector;
|
||||
char *rbuf = 0;
|
||||
int wsize = 0;
|
||||
|
||||
/*
|
||||
** #1: write first unalign block size.
|
||||
*/
|
||||
if (first_offs != 0)
|
||||
{
|
||||
if (count > bytes_per_sector - first_offs)
|
||||
{
|
||||
wsize = bytes_per_sector - first_offs;
|
||||
}
|
||||
else
|
||||
{
|
||||
wsize = count;
|
||||
}
|
||||
|
||||
rbuf = rt_malloc(bytes_per_sector);
|
||||
if (!rbuf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = rt_mmcsd_read(dev, blk_pos, rbuf, 1);
|
||||
if (result != 1)
|
||||
{
|
||||
rt_free(rbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_memcpy(rbuf + first_offs, buf, wsize);
|
||||
result = rt_mmcsd_write(dev, blk_pos, rbuf, 1);
|
||||
if (result != 1)
|
||||
{
|
||||
rt_free(rbuf);
|
||||
return 0;
|
||||
}
|
||||
rt_free(rbuf);
|
||||
blk_pos += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** #2: write continuous block size.
|
||||
*/
|
||||
if ((count - wsize) / bytes_per_sector != 0)
|
||||
{
|
||||
result = rt_mmcsd_write(dev, blk_pos, buf + wsize, (count - wsize) / bytes_per_sector);
|
||||
wsize += result * bytes_per_sector;
|
||||
blk_pos += result;
|
||||
if (result != (count - wsize) / bytes_per_sector)
|
||||
{
|
||||
*pos += wsize;
|
||||
return wsize;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** # 3: write last unalign block size.
|
||||
*/
|
||||
if ((count - wsize) != 0)
|
||||
{
|
||||
rbuf = rt_malloc(bytes_per_sector);
|
||||
if (rbuf != RT_NULL)
|
||||
{
|
||||
result = rt_mmcsd_read(dev, blk_pos, rbuf, 1);
|
||||
if (result == 1)
|
||||
{
|
||||
rt_memcpy(rbuf, buf + wsize, count - wsize);
|
||||
result = rt_mmcsd_write(dev, blk_pos, rbuf, 1);
|
||||
if (result == 1)
|
||||
{
|
||||
wsize += count - wsize;
|
||||
}
|
||||
}
|
||||
|
||||
rt_free(rbuf);
|
||||
}
|
||||
}
|
||||
|
||||
*pos += wsize;
|
||||
return wsize;
|
||||
}
|
||||
|
||||
static int rt_mmcsd_fops_poll(struct dfs_file *file, struct rt_pollreq *req)
|
||||
{
|
||||
int mask = 0;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
const static struct dfs_file_ops mmcsd_blk_fops =
|
||||
{
|
||||
rt_mmcsd_fops_open,
|
||||
rt_mmcsd_fops_close,
|
||||
rt_mmcsd_fops_ioctl,
|
||||
rt_mmcsd_fops_read,
|
||||
rt_mmcsd_fops_write,
|
||||
RT_NULL,
|
||||
generic_dfs_lseek,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
rt_mmcsd_fops_poll
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_int32_t gpt_device_probe(struct rt_mmcsd_card *card)
|
||||
{
|
||||
rt_int32_t err = RT_EOK;
|
||||
|
@ -460,6 +675,11 @@ rt_int32_t gpt_device_probe(struct rt_mmcsd_card *card)
|
|||
|
||||
rt_device_register(&(blk_dev->dev), card->host->name,
|
||||
RT_DEVICE_FLAG_RDWR);
|
||||
#ifdef RT_USING_POSIX_DEVIO
|
||||
#ifdef RT_USING_DFS_V2
|
||||
blk_dev->dev.fops = &mmcsd_blk_fops;
|
||||
#endif
|
||||
#endif
|
||||
rt_list_insert_after(&blk_devices, &blk_dev->list);
|
||||
|
||||
for (i = 0; i < RT_GPT_PARTITION_MAX; i++)
|
||||
|
@ -505,6 +725,11 @@ rt_int32_t gpt_device_probe(struct rt_mmcsd_card *card)
|
|||
|
||||
rt_device_register(&(blk_dev->dev), dname,
|
||||
RT_DEVICE_FLAG_RDWR);
|
||||
#ifdef RT_USING_POSIX_DEVIO
|
||||
#ifdef RT_USING_DFS_V2
|
||||
blk_dev->dev.fops = &mmcsd_blk_fops;
|
||||
#endif
|
||||
#endif
|
||||
rt_list_insert_after(&blk_devices, &blk_dev->list);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -159,18 +159,25 @@ long list_thread(void)
|
|||
rt_list_t *obj_list[LIST_FIND_OBJ_NR];
|
||||
rt_list_t *next = (rt_list_t *)RT_NULL;
|
||||
const char *item_title = "thread";
|
||||
const size_t tcb_strlen = sizeof(void *) * 2 + 2;
|
||||
int maxlen;
|
||||
|
||||
list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
|
||||
|
||||
maxlen = RT_NAME_MAX;
|
||||
|
||||
rt_kprintf("%-*.*s ", tcb_strlen, tcb_strlen, "rt_thread_t");
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_kprintf("%-*.*s cpu bind pri status sp stack size max used left tick error\n", maxlen, maxlen, item_title);
|
||||
object_split(tcb_strlen);
|
||||
rt_kprintf(" ");
|
||||
object_split(maxlen);
|
||||
rt_kprintf(" --- ---- --- ------- ---------- ---------- ------ ---------- ---\n");
|
||||
#else
|
||||
rt_kprintf("%-*.*s pri status sp stack size max used left tick error\n", maxlen, maxlen, item_title);
|
||||
object_split(tcb_strlen);
|
||||
rt_kprintf(" ");
|
||||
object_split(maxlen);
|
||||
rt_kprintf(" --- ------- ---------- ---------- ------ ---------- ---\n");
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
@ -202,6 +209,7 @@ long list_thread(void)
|
|||
rt_uint8_t stat;
|
||||
rt_uint8_t *ptr;
|
||||
|
||||
rt_kprintf("%p ", thread);
|
||||
#ifdef RT_USING_SMP
|
||||
if (thread->oncpu != RT_CPU_DETACHED)
|
||||
rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->oncpu, thread->bind_cpu, thread->current_priority);
|
||||
|
|
|
@ -618,6 +618,7 @@ MSH_CMD_EXPORT_ALIAS(cmd_mount, mount, mount <device> <mountpoint> <fstype>);
|
|||
/* unmount the filesystem from the specified mountpoint */
|
||||
static int cmd_umount(int argc, char **argv)
|
||||
{
|
||||
#ifndef RT_USING_DFS_V2
|
||||
char *path = argv[1];
|
||||
|
||||
if (argc != 2)
|
||||
|
@ -637,6 +638,34 @@ static int cmd_umount(int argc, char **argv)
|
|||
rt_kprintf("succeed!\n");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int flags = 0;
|
||||
char *path = argv[1];
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
rt_kprintf("Usage: unmount [-f] <mountpoint>.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
flags = strcmp(argv[1], "-f") == 0 ? MNT_FORCE : 0;
|
||||
path = argv[2];
|
||||
}
|
||||
|
||||
rt_kprintf("unmount %s ... ", path);
|
||||
if (dfs_umount(path, flags) < 0)
|
||||
{
|
||||
rt_kprintf("failed!\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("succeed!\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(cmd_umount, umount, Unmount the mountpoint);
|
||||
|
||||
|
|
|
@ -30,39 +30,20 @@ int libc_system_init(void)
|
|||
dev_console = rt_console_get_device();
|
||||
if (dev_console)
|
||||
{
|
||||
int fd, ret;
|
||||
char name[STDIO_DEVICE_NAME_MAX];
|
||||
|
||||
rt_snprintf(name, sizeof(name) - 1, "/dev/%s", dev_console->parent.name);
|
||||
name[STDIO_DEVICE_NAME_MAX - 1] = '\0';
|
||||
|
||||
fd = open(name, O_RDWR);
|
||||
if (fd >= 0)
|
||||
{
|
||||
/* set fd (0, 1, 2) */
|
||||
ret = sys_dup2(fd, 0);
|
||||
if (ret != fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
sys_dup2(ret, 1);
|
||||
sys_dup2(ret, 2);
|
||||
|
||||
ret = libc_stdio_set_console(dev_console->parent.name, O_RDWR);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
int fd = libc_stdio_set_console(dev_console->parent.name, O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
/* set fd (0, 1, 2) */
|
||||
sys_dup2(fd, 0);
|
||||
sys_dup2(fd, 1);
|
||||
sys_dup2(fd, 2);
|
||||
}
|
||||
#endif /* RT_USING_POSIX_STDIO */
|
||||
return 0;
|
||||
}
|
||||
INIT_APP_EXPORT(libc_system_init);
|
||||
INIT_ENV_EXPORT(libc_system_init);
|
||||
|
||||
#if defined(RT_USING_POSIX_STDIO) && defined(RT_USING_NEWLIBC)
|
||||
|
||||
|
|
|
@ -1403,3 +1403,17 @@ void lwp_user_setting_restore(rt_thread_t thread)
|
|||
}
|
||||
}
|
||||
#endif /* ARCH_MM_MMU */
|
||||
|
||||
void lwp_uthread_ctx_save(void *ctx)
|
||||
{
|
||||
rt_thread_t thread;
|
||||
thread = rt_thread_self();
|
||||
thread->user_ctx.ctx = ctx;
|
||||
}
|
||||
|
||||
void lwp_uthread_ctx_restore(void)
|
||||
{
|
||||
rt_thread_t thread;
|
||||
thread = rt_thread_self();
|
||||
thread->user_ctx.ctx = RT_NULL;
|
||||
}
|
||||
|
|
|
@ -164,6 +164,10 @@ void lwp_aspace_switch(struct rt_thread *thread);
|
|||
#endif
|
||||
void lwp_user_setting_save(rt_thread_t thread);
|
||||
void lwp_user_setting_restore(rt_thread_t thread);
|
||||
|
||||
void lwp_uthread_ctx_save(void *ctx);
|
||||
void lwp_uthread_ctx_restore(void);
|
||||
|
||||
int lwp_setaffinity(pid_t pid, int cpu);
|
||||
|
||||
/* ctime lwp API */
|
||||
|
|
|
@ -980,6 +980,7 @@ int lwp_channel_open(int fdt_type, const char *name, int flags)
|
|||
{
|
||||
/* initialize vnode */
|
||||
dfs_vnode_init(d->vnode, FT_USER, &channel_fops);
|
||||
d->flags = O_RDWR; /* set flags as read and write */
|
||||
|
||||
/* set socket to the data of dfs_file */
|
||||
d->vnode->data = (void *)ch;
|
||||
|
|
|
@ -106,6 +106,11 @@ static void lwp_pid_put(pid_t pid)
|
|||
rt_base_t level;
|
||||
struct lwp_avl_struct *p;
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
p = lwp_avl_find(pid, lwp_pid_root);
|
||||
if (p)
|
||||
|
|
|
@ -94,4 +94,43 @@
|
|||
#define INTF_IPV6_V6ONLY 26
|
||||
#define IMPL_IPV6_V6ONLY 27
|
||||
|
||||
struct musl_sockaddr
|
||||
{
|
||||
uint16_t sa_family;
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
struct musl_ifmap {
|
||||
unsigned long int mem_start;
|
||||
unsigned long int mem_end;
|
||||
unsigned short int base_addr;
|
||||
unsigned char irq;
|
||||
unsigned char dma;
|
||||
unsigned char port;
|
||||
};
|
||||
|
||||
struct musl_ifreq
|
||||
{
|
||||
union
|
||||
{
|
||||
#define IFNAMSIZ 16
|
||||
char ifrn_name[IFNAMSIZ];
|
||||
} ifr_ifrn;
|
||||
union
|
||||
{
|
||||
struct musl_sockaddr ifru_addr;
|
||||
struct musl_sockaddr ifru_dstaddr;
|
||||
struct musl_sockaddr ifru_broadaddr;
|
||||
struct musl_sockaddr ifru_netmask;
|
||||
struct musl_sockaddr ifru_hwaddr;
|
||||
short int ifru_flags;
|
||||
int ifru_ivalue;
|
||||
int ifru_mtu;
|
||||
struct musl_ifmap ifru_map;
|
||||
char ifru_slave[IFNAMSIZ];
|
||||
char ifru_newname[IFNAMSIZ];
|
||||
char *ifru_data;
|
||||
} ifr_ifru;
|
||||
};
|
||||
|
||||
#endif /* __LWP_SYS_SOCKET_H__ */
|
||||
|
|
|
@ -103,12 +103,6 @@
|
|||
#error "No definition RT_USING_POSIX_CLOCK"
|
||||
#endif /* RT_USING_POSIX_CLOCK */
|
||||
|
||||
struct musl_sockaddr
|
||||
{
|
||||
uint16_t sa_family;
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
void lwp_cleanup(struct rt_thread *tid);
|
||||
|
||||
#ifdef ARCH_MM_MMU
|
||||
|
@ -551,7 +545,7 @@ sysret_t sys_open(const char *name, int flag, ...)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* syscall: "open" ret: "int" args: "const char *" "mode_t" "mode" */
|
||||
/* syscall: "openat" ret: "int" args: "const char *" "mode_t" "mode" */
|
||||
sysret_t sys_openat(int dirfd, const char *name, int flag, mode_t mode)
|
||||
{
|
||||
#ifdef ARCH_MM_MMU
|
||||
|
@ -4684,6 +4678,12 @@ sysret_t sys_sched_setparam(pid_t pid, void *param)
|
|||
return ret;
|
||||
}
|
||||
|
||||
sysret_t sys_sched_yield(void)
|
||||
{
|
||||
rt_thread_yield();
|
||||
return 0;
|
||||
}
|
||||
|
||||
sysret_t sys_sched_getparam(pid_t pid, void *param)
|
||||
{
|
||||
struct sched_param *sched_param = (struct sched_param *)param;
|
||||
|
@ -5378,7 +5378,154 @@ sysret_t sys_epoll_pwait(int fd,
|
|||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
}
|
||||
|
||||
static const struct rt_syscall_def func_table[] =
|
||||
sysret_t sys_chmod(const char *fileName, mode_t mode)
|
||||
{
|
||||
char *copy_fileName;
|
||||
size_t len_fileName, copy_len_fileName;
|
||||
int err_fileName;
|
||||
#ifdef RT_USING_DFS_V2
|
||||
struct dfs_attr attr;
|
||||
attr.st_mode = mode;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
len_fileName = lwp_user_strlen(fileName, &err_fileName);
|
||||
if (err_fileName)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
copy_fileName = (char*)rt_malloc(len_fileName + 1);
|
||||
if (!copy_fileName)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
copy_len_fileName = lwp_get_from_user(copy_fileName, (void *)fileName, len_fileName);
|
||||
copy_fileName[copy_len_fileName] = '\0';
|
||||
#ifdef RT_USING_DFS_V2
|
||||
ret = dfs_file_setattr(copy_fileName, &attr);
|
||||
#else
|
||||
SET_ERRNO(EFAULT);
|
||||
#endif
|
||||
rt_free(copy_fileName);
|
||||
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
}
|
||||
|
||||
sysret_t sys_reboot(int magic)
|
||||
{
|
||||
rt_hw_cpu_reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t sys_pread64(int fd, void *buf, int size, off_t offset)
|
||||
#ifdef RT_USING_DFS_V2
|
||||
{
|
||||
ssize_t pread(int fd, void *buf, size_t len, off_t offset);
|
||||
#ifdef ARCH_MM_MMU
|
||||
ssize_t ret = -1;
|
||||
void *kmem = RT_NULL;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!lwp_user_accessable((void *)buf, size))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
kmem = kmem_get(size);
|
||||
if (!kmem)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = pread(fd, kmem, size, offset);
|
||||
if (ret > 0)
|
||||
{
|
||||
lwp_put_to_user(buf, kmem, ret);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = GET_ERRNO();
|
||||
}
|
||||
|
||||
kmem_put(kmem);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
if (!lwp_user_accessable((void *)buf, size))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ssize_t ret = pread(fd, kmem, size, offset);
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
{
|
||||
ssize_t ret = -ENOSYS;
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t sys_pwrite64(int fd, void *buf, int size, off_t offset)
|
||||
#ifdef RT_USING_DFS_V2
|
||||
{
|
||||
ssize_t pwrite(int fd, const void *buf, size_t len, off_t offset);
|
||||
#ifdef ARCH_MM_MMU
|
||||
ssize_t ret = -1;
|
||||
void *kmem = RT_NULL;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!lwp_user_accessable((void *)buf, size))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
kmem = kmem_get(size);
|
||||
if (!kmem)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lwp_get_from_user(kmem, (void *)buf, size);
|
||||
|
||||
ret = pwrite(fd, kmem, size, offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = GET_ERRNO();
|
||||
}
|
||||
|
||||
kmem_put(kmem);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
if (!lwp_user_accessable((void *)buf, size))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ssize_t ret = pwrite(fd, kmem, size, offset);
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
{
|
||||
ssize_t ret = -ENOSYS;
|
||||
return (ret < 0 ? GET_ERRNO() : ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
const static struct rt_syscall_def func_table[] =
|
||||
{
|
||||
SYSCALL_SIGN(sys_exit), /* 01 */
|
||||
SYSCALL_SIGN(sys_read),
|
||||
|
@ -5600,11 +5747,11 @@ static const struct rt_syscall_def func_table[] =
|
|||
SYSCALL_SIGN(sys_symlink),
|
||||
SYSCALL_SIGN(sys_getaffinity), /* 180 */
|
||||
SYSCALL_SIGN(sys_sysinfo),
|
||||
SYSCALL_SIGN(sys_notimpl),
|
||||
SYSCALL_SIGN(sys_notimpl),
|
||||
SYSCALL_SIGN(sys_notimpl),
|
||||
SYSCALL_SIGN(sys_notimpl), /* 185 */
|
||||
SYSCALL_SIGN(sys_notimpl),
|
||||
SYSCALL_SIGN(sys_chmod),
|
||||
SYSCALL_SIGN(sys_reboot),
|
||||
SYSCALL_SIGN(sys_sched_yield),
|
||||
SYSCALL_SIGN(sys_pread64), /* 185 */
|
||||
SYSCALL_SIGN(sys_pwrite64),
|
||||
SYSCALL_SIGN(sys_sigpending),
|
||||
SYSCALL_SIGN(sys_sigtimedwait),
|
||||
SYSCALL_SIGN(sys_notimpl),
|
||||
|
@ -5632,7 +5779,10 @@ const void *lwp_get_sys_api(rt_uint32_t number)
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_I("Unimplement syscall %d", number);
|
||||
if (__sys_log_enable)
|
||||
{
|
||||
LOG_I("Unimplement syscall %d", number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5656,7 +5806,10 @@ const char *lwp_get_syscall_name(rt_uint32_t number)
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_I("Unimplement syscall %d", number);
|
||||
if (__sys_log_enable)
|
||||
{
|
||||
LOG_I("Unimplement syscall %d", number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1763,7 +1763,8 @@ netif_find(const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
num = (u8_t)atoi(&name[2]);
|
||||
/* Out netif's name is e0, e1... */
|
||||
num = (u8_t)atoi(&name[1]);
|
||||
|
||||
NETIF_FOREACH(netif) {
|
||||
if (num == netif->num &&
|
||||
|
|
|
@ -52,8 +52,9 @@ int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||
rt_set_errno(-ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
rt_memset(d->vnode, 0, sizeof(struct dfs_vnode));
|
||||
|
||||
dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops());
|
||||
d->flags = O_RDWR; /* set flags as read and write */
|
||||
|
||||
/* set socket to the data of dfs_file */
|
||||
d->vnode->data = (void *)(size_t)new_socket;
|
||||
|
@ -258,6 +259,7 @@ int socket(int domain, int type, int protocol)
|
|||
if (socket >= 0)
|
||||
{
|
||||
dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops());
|
||||
d->flags = O_RDWR; /* set flags as read and write */
|
||||
|
||||
/* set socket to the data of dfs_file */
|
||||
d->vnode->data = (void *)(size_t)socket;
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#include <ipc/workqueue.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
#include <lwp_sys_socket.h>
|
||||
#endif
|
||||
|
||||
/* check system workqueue stack size */
|
||||
#if defined(SAL_INTERNET_CHECK) && RT_SYSTEM_WORKQUEUE_STACKSIZE < 1536
|
||||
#error "The system workqueue stack size must more than 1536 bytes"
|
||||
|
@ -51,6 +55,16 @@ struct sal_netdev_res_table
|
|||
struct netdev *netdev;
|
||||
};
|
||||
|
||||
struct ifconf
|
||||
{
|
||||
int ifc_len; /* Size of buffer. */
|
||||
union
|
||||
{
|
||||
char* ifcu_buf;
|
||||
struct sal_ifreq *ifcu_req;
|
||||
} ifc_ifcu;
|
||||
};
|
||||
|
||||
#ifdef SAL_USING_TLS
|
||||
/* The global TLS protocol options */
|
||||
static struct sal_proto_tls *proto_tls;
|
||||
|
@ -1028,8 +1042,17 @@ int sal_closesocket(int socket)
|
|||
return error;
|
||||
}
|
||||
|
||||
#define ARPHRD_ETHER 1 /* Ethernet 10/100Mbps. */
|
||||
#define ARPHRD_LOOPBACK 772 /* Loopback device. */
|
||||
#define IFF_UP 0x1
|
||||
#define IFF_RUNNING 0x40
|
||||
#define IFF_NOARP 0x80
|
||||
|
||||
int sal_ioctlsocket(int socket, long cmd, void *arg)
|
||||
{
|
||||
rt_slist_t *node = RT_NULL;
|
||||
struct netdev *netdev = RT_NULL;
|
||||
struct netdev *cur_netdev_list = netdev_list;
|
||||
struct sal_socket *sock;
|
||||
struct sal_proto_family *pf;
|
||||
struct sockaddr_in *addr_in = RT_NULL;
|
||||
|
@ -1048,48 +1071,276 @@ int sal_ioctlsocket(int socket, long cmd, void *arg)
|
|||
switch (cmd)
|
||||
{
|
||||
case SIOCGIFADDR:
|
||||
addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_addr);
|
||||
#if NETDEV_IPV4 && NETDEV_IPV6
|
||||
addr_in->sin_addr.s_addr = sock->netdev->ip_addr.u_addr.ip4.addr;
|
||||
#elif NETDEV_IPV4
|
||||
addr_in->sin_addr.s_addr = sock->netdev->ip_addr.addr;
|
||||
#elif NETDEV_IPV6
|
||||
#error "not only support IPV6"
|
||||
#endif /* NETDEV_IPV4 && NETDEV_IPV6*/
|
||||
return 0;
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name))
|
||||
{
|
||||
addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_addr);
|
||||
#if NETDEV_IPV4 && NETDEV_IPV6
|
||||
addr_in->sin_addr.s_addr = sock->netdev->ip_addr.u_addr.ip4.addr;
|
||||
#elif NETDEV_IPV4
|
||||
addr_in->sin_addr.s_addr = sock->netdev->ip_addr.addr;
|
||||
#elif NETDEV_IPV6
|
||||
#error "not only support IPV6"
|
||||
#endif /* NETDEV_IPV4 && NETDEV_IPV6*/
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_netdev_list == RT_NULL)
|
||||
{
|
||||
LOG_E("ifconfig: network interface device list error.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name))
|
||||
{
|
||||
addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_addr);
|
||||
addr_in->sin_addr.s_addr = netdev->ip_addr.addr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
case SIOCSIFADDR:
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_addr);
|
||||
sal_sockaddr_to_ipaddr(addr,&input_ipaddr);
|
||||
netdev_set_ipaddr(sock->netdev,&input_ipaddr);
|
||||
return 0;
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name))
|
||||
{
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_addr);
|
||||
sal_sockaddr_to_ipaddr(addr, &input_ipaddr);
|
||||
netdev_set_ipaddr(sock->netdev, &input_ipaddr);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_netdev_list == RT_NULL)
|
||||
{
|
||||
LOG_E("ifconfig: network interface device list error.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name))
|
||||
{
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_addr);
|
||||
sal_sockaddr_to_ipaddr(addr, &input_ipaddr);
|
||||
netdev_set_ipaddr(netdev, &input_ipaddr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
case SIOCGIFNETMASK:
|
||||
addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_netmask);
|
||||
#if NETDEV_IPV4 && NETDEV_IPV6
|
||||
addr_in->sin_addr.s_addr = sock->netdev->netmask.u_addr.ip4.addr;
|
||||
#elif NETDEV_IPV4
|
||||
addr_in->sin_addr.s_addr = sock->netdev->netmask.addr;
|
||||
#elif NETDEV_IPV6
|
||||
#error "not only support IPV6"
|
||||
#endif /* NETDEV_IPV4 && NETDEV_IPV6*/
|
||||
return 0;
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name))
|
||||
{
|
||||
addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_netmask);
|
||||
#if NETDEV_IPV4 && NETDEV_IPV6
|
||||
addr_in->sin_addr.s_addr = sock->netdev->netmask.u_addr.ip4.addr;
|
||||
#elif NETDEV_IPV4
|
||||
addr_in->sin_addr.s_addr = sock->netdev->netmask.addr;
|
||||
#elif NETDEV_IPV6
|
||||
#error "not only support IPV6"
|
||||
#endif /* NETDEV_IPV4 && NETDEV_IPV6*/
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_netdev_list == RT_NULL)
|
||||
{
|
||||
LOG_E("ifconfig: network interface device list error.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name))
|
||||
{
|
||||
addr_in = (struct sockaddr_in *)&(ifr->ifr_ifru.ifru_netmask);
|
||||
#if NETDEV_IPV4 && NETDEV_IPV6
|
||||
addr_in->sin_addr.s_addr = netdev->netmask.u_addr.ip4.addr;
|
||||
#elif NETDEV_IPV4
|
||||
addr_in->sin_addr.s_addr = netdev->netmask.addr;
|
||||
#elif NETDEV_IPV6
|
||||
#error "not only support IPV6"
|
||||
#endif /* NETDEV_IPV4 && NETDEV_IPV6*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
case SIOCSIFNETMASK:
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_netmask);
|
||||
sal_sockaddr_to_ipaddr(addr,&input_ipaddr);
|
||||
netdev_set_netmask(sock->netdev,&input_ipaddr);
|
||||
return 0;
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name))
|
||||
{
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_netmask);
|
||||
sal_sockaddr_to_ipaddr(addr, &input_ipaddr);
|
||||
netdev_set_netmask(sock->netdev, &input_ipaddr);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_netdev_list == RT_NULL)
|
||||
{
|
||||
LOG_E("ifconfig: network interface device list error.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name))
|
||||
{
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_netmask);
|
||||
sal_sockaddr_to_ipaddr(addr, &input_ipaddr);
|
||||
netdev_set_netmask(netdev, &input_ipaddr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
case SIOCGIFHWADDR:
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_hwaddr);
|
||||
rt_memcpy(addr->sa_data,sock->netdev->hwaddr,sock->netdev->hwaddr_len);
|
||||
return 0;
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name,sock->netdev->name))
|
||||
{
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_hwaddr);
|
||||
#ifdef RT_USING_LWP
|
||||
if (!strcmp("lo", sock->netdev->name))
|
||||
{
|
||||
struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg;
|
||||
musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_LOOPBACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg;
|
||||
musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER;
|
||||
}
|
||||
#endif
|
||||
rt_memcpy(addr->sa_data, sock->netdev->hwaddr, sock->netdev->hwaddr_len);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_netdev_list == RT_NULL)
|
||||
{
|
||||
LOG_E("ifconfig: network interface device list error.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name))
|
||||
{
|
||||
addr = (struct sockaddr *)&(ifr->ifr_ifru.ifru_hwaddr);
|
||||
#ifdef RT_USING_LWP
|
||||
if (!strcmp("lo", netdev->name))
|
||||
{
|
||||
struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg;
|
||||
musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_LOOPBACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct musl_ifreq * musl_ifreq_tmp = (struct musl_ifreq *)arg;
|
||||
musl_ifreq_tmp->ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER;
|
||||
}
|
||||
#endif
|
||||
rt_memcpy(addr->sa_data, netdev->hwaddr, netdev->hwaddr_len);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
case SIOCGIFMTU:
|
||||
ifr->ifr_ifru.ifru_mtu = sock->netdev->mtu;
|
||||
return 0;
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name))
|
||||
{
|
||||
ifr->ifr_ifru.ifru_mtu = sock->netdev->mtu;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_netdev_list == RT_NULL)
|
||||
{
|
||||
LOG_E("ifconfig: network interface device list error.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name))
|
||||
{
|
||||
ifr->ifr_ifru.ifru_mtu = netdev->mtu;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
case SIOCGIFFLAGS:
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, sock->netdev->name))
|
||||
{
|
||||
uint16_t flags_tmp = 0;
|
||||
if (sock->netdev->flags & NETDEV_FLAG_UP)
|
||||
flags_tmp = flags_tmp | IFF_UP;
|
||||
if (!(sock->netdev->flags & NETDEV_FLAG_ETHARP))
|
||||
flags_tmp = flags_tmp | IFF_NOARP;
|
||||
flags_tmp = flags_tmp | IFF_RUNNING;
|
||||
ifr->ifr_ifru.ifru_flags = flags_tmp;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_netdev_list == RT_NULL)
|
||||
{
|
||||
LOG_E("ifconfig: network interface device list error.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
if (!strcmp(ifr->ifr_ifrn.ifrn_name, netdev->name))
|
||||
{
|
||||
uint16_t flags_tmp = 0;
|
||||
if (sock->netdev->flags & NETDEV_FLAG_UP)
|
||||
flags_tmp = flags_tmp | IFF_UP;
|
||||
if (!(sock->netdev->flags & NETDEV_FLAG_ETHARP))
|
||||
flags_tmp = flags_tmp | IFF_NOARP;
|
||||
ifr->ifr_ifru.ifru_flags = flags_tmp;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
case SIOCSIFFLAGS:
|
||||
sock->netdev->flags = ifr->ifr_ifru.ifru_flags;
|
||||
return 0;
|
||||
case SIOCGIFCONF:
|
||||
{
|
||||
struct ifconf *ifconf_tmp;
|
||||
ifconf_tmp = (struct ifconf *)arg;
|
||||
int count_size = 0;
|
||||
|
||||
for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
|
||||
{
|
||||
struct sal_ifreq sal_ifreq_temp;
|
||||
count_size++;
|
||||
netdev = rt_list_entry(node, struct netdev, list);
|
||||
rt_strcpy(sal_ifreq_temp.ifr_ifrn.ifrn_name, netdev->name);
|
||||
rt_memcpy(ifconf_tmp->ifc_ifcu.ifcu_buf, &sal_ifreq_temp, sizeof(struct sal_ifreq));
|
||||
ifconf_tmp->ifc_ifcu.ifcu_buf += sizeof(struct sal_ifreq);
|
||||
}
|
||||
ifconf_tmp->ifc_len = sizeof(struct sal_ifreq) * count_size;
|
||||
ifconf_tmp->ifc_ifcu.ifcu_buf = ifconf_tmp->ifc_ifcu.ifcu_buf - sizeof(struct sal_ifreq) * count_size;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -807,6 +807,8 @@ struct rt_user_context
|
|||
void *sp;
|
||||
void *pc;
|
||||
void *flag;
|
||||
|
||||
void *ctx;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -6,10 +6,15 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-06-02 Jesven the first version
|
||||
* 2023-06-24 WangXiaoyao Support backtrace for non-active thread
|
||||
*/
|
||||
|
||||
#include "mm_aspace.h"
|
||||
#include "mmu.h"
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <backtrace.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BT_NESTING_MAX 100
|
||||
|
||||
|
@ -19,7 +24,7 @@ static int unwind_frame(struct bt_frame *frame)
|
|||
|
||||
if ((fp & 0x7)
|
||||
#ifdef RT_USING_LWP
|
||||
|| fp < KERNEL_VADDR_START
|
||||
|| (rt_kmem_v2p((void *)fp) == ARCH_MAP_FAILED)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
@ -27,16 +32,18 @@ static int unwind_frame(struct bt_frame *frame)
|
|||
}
|
||||
frame->fp = *(unsigned long *)fp;
|
||||
frame->pc = *(unsigned long *)(fp + 8);
|
||||
|
||||
if ((rt_kmem_v2p((void *)frame->pc) == ARCH_MAP_FAILED))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void walk_unwind(unsigned long pc, unsigned long fp)
|
||||
{
|
||||
struct bt_frame frame;
|
||||
struct bt_frame frame = {fp, 1};
|
||||
unsigned long lr = pc;
|
||||
int nesting = 0;
|
||||
|
||||
frame.fp = fp;
|
||||
while (nesting < BT_NESTING_MAX)
|
||||
{
|
||||
rt_kprintf(" %p", (void *)lr);
|
||||
|
@ -51,18 +58,128 @@ static void walk_unwind(unsigned long pc, unsigned long fp)
|
|||
|
||||
void backtrace(unsigned long pc, unsigned long lr, unsigned long fp)
|
||||
{
|
||||
rt_kprintf("please use: addr2line -e rtthread.elf -a -f %p", (void *)pc);
|
||||
walk_unwind(lr, fp);
|
||||
rt_kprintf("please use: addr2line -e rtthread.elf -a -f");
|
||||
if (pc)
|
||||
rt_kprintf(" %p", (void *)pc);
|
||||
|
||||
if (lr && fp)
|
||||
walk_unwind(lr, fp);
|
||||
rt_kprintf("\n");
|
||||
}
|
||||
|
||||
int rt_backtrace(void)
|
||||
{
|
||||
unsigned long pc = (unsigned long)backtrace;
|
||||
unsigned long ra = (unsigned long)__builtin_return_address(0U);
|
||||
unsigned long fr = (unsigned long)__builtin_frame_address(0U);
|
||||
|
||||
backtrace(pc, ra, fr);
|
||||
backtrace(0, ra, fr);
|
||||
return 0;
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(rt_backtrace, bt_test, backtrace test);
|
||||
|
||||
#define ARCH_CONTEXT_FETCH(pctx, id) (*(((unsigned long *)pctx) + (id)))
|
||||
|
||||
int rt_backtrace_thread(rt_thread_t thread)
|
||||
{
|
||||
unsigned long lr;
|
||||
unsigned long fp;
|
||||
|
||||
if (thread == rt_thread_self())
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
lr = ARCH_CONTEXT_FETCH(thread->sp, 3);
|
||||
fp = ARCH_CONTEXT_FETCH(thread->sp, 7);
|
||||
backtrace(0, lr, fp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
|
||||
int rt_backtrace_user_thread(rt_thread_t thread)
|
||||
{
|
||||
unsigned long pc;
|
||||
unsigned long lr;
|
||||
unsigned long fp;
|
||||
unsigned long ctx = (unsigned long)thread->user_ctx.ctx;
|
||||
|
||||
if (ctx > (unsigned long)thread->stack_addr
|
||||
&& ctx < (unsigned long)thread->stack_addr + thread->stack_size)
|
||||
{
|
||||
pc = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 0);
|
||||
lr = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 3);
|
||||
fp = ARCH_CONTEXT_FETCH(thread->user_ctx.ctx, 7);
|
||||
backtrace(pc, lr, fp);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
static long custom_hex_to_long(const char* hex)
|
||||
{
|
||||
long result = 0;
|
||||
int i = 0;
|
||||
|
||||
// Skip the "0x" prefix
|
||||
if (hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X'))
|
||||
{
|
||||
i = 2;
|
||||
}
|
||||
|
||||
// Convert each hex digit to its decimal value
|
||||
for (; hex[i] != '\0'; i++)
|
||||
{
|
||||
char digit = hex[i];
|
||||
if (digit >= '0' && digit <= '9')
|
||||
{
|
||||
result = result * 16 + (digit - '0');
|
||||
}
|
||||
else if (digit >= 'a' && digit <= 'f')
|
||||
{
|
||||
result = result * 16 + (digit - 'a' + 10);
|
||||
}
|
||||
else if (digit >= 'A' && digit <= 'F')
|
||||
{
|
||||
result = result * 16 + (digit - 'A' + 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid hex digit
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cmd_backtrace(int argc, char** argv)
|
||||
{
|
||||
long pid;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
rt_kprintf("please use: backtrace pid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(argv[1], "0x", 2) == 0)
|
||||
{
|
||||
pid = custom_hex_to_long(argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
pid = atol(argv[1]);
|
||||
}
|
||||
if (pid)
|
||||
{
|
||||
rt_kprintf("backtrace %s(0x%lx), from %s\n", ((rt_thread_t)pid)->parent.name, pid, argv[1]);
|
||||
rt_backtrace_thread((rt_thread_t)pid);
|
||||
}
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(cmd_backtrace, backtrace, print backtrace of a thread);
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-06-02 Jesven the first version
|
||||
* 2023-06-24 WangXiaoyao Support backtrace for non-active thread
|
||||
*/
|
||||
|
||||
#ifndef __BACKTRACE_H__
|
||||
#define __BACKTRACE_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
struct bt_frame
|
||||
{
|
||||
unsigned long fp;
|
||||
|
@ -20,4 +23,7 @@ struct bt_frame
|
|||
void backtrace(unsigned long pc, unsigned long lr, unsigned long fp);
|
||||
int rt_backtrace(void);
|
||||
|
||||
int rt_backtrace_user_thread(rt_thread_t thread);
|
||||
int rt_backtrace_thread(rt_thread_t thread);
|
||||
|
||||
#endif /*__BACKTRACE_H__*/
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-18 Jesven the first version
|
||||
* 2023-06-24 WangXiaoyao Support backtrace for user thread
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
|
@ -375,13 +376,31 @@ rt_hw_context_switch_interrupt:
|
|||
vector_fiq:
|
||||
B .
|
||||
|
||||
.macro SAVE_USER_CTX
|
||||
MRS X1, SPSR_EL1
|
||||
AND X1, X1, 0xf
|
||||
CMP X1, XZR
|
||||
|
||||
BNE 1f
|
||||
BL lwp_uthread_ctx_save
|
||||
LDP X0, X1, [SP]
|
||||
1:
|
||||
.endm
|
||||
|
||||
.globl vector_irq
|
||||
vector_irq:
|
||||
SAVE_CONTEXT
|
||||
STP X0, X1, [SP, #-0x10]! /* X0 is thread sp */
|
||||
|
||||
BL rt_interrupt_enter
|
||||
LDP X0, X1, [SP]
|
||||
#ifdef RT_USING_LWP
|
||||
SAVE_USER_CTX
|
||||
#endif
|
||||
BL rt_hw_trap_irq
|
||||
#ifdef RT_USING_LWP
|
||||
BL lwp_uthread_ctx_restore
|
||||
#endif
|
||||
BL rt_interrupt_leave
|
||||
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
@ -515,7 +534,15 @@ vector_irq_exit:
|
|||
START_POINT(vector_exception)
|
||||
SAVE_CONTEXT
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
#ifdef RT_USING_LWP
|
||||
SAVE_USER_CTX
|
||||
#endif
|
||||
|
||||
BL rt_hw_trap_exception
|
||||
#ifdef RT_USING_LWP
|
||||
BL lwp_uthread_ctx_restore
|
||||
#endif
|
||||
|
||||
LDP X0, X1, [SP], #0x10
|
||||
MOV SP, X0
|
||||
RESTORE_CONTEXT_WITHOUT_MMU_SWITCH
|
||||
|
@ -523,6 +550,9 @@ START_POINT_END(vector_exception)
|
|||
|
||||
START_POINT(vector_serror)
|
||||
SAVE_CONTEXT
|
||||
#ifdef RT_USING_LWP
|
||||
SAVE_USER_CTX
|
||||
#endif
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
BL rt_hw_trap_serror
|
||||
b .
|
||||
|
|
|
@ -296,6 +296,19 @@ void rt_hw_trap_exception(struct rt_hw_exp_stack *regs)
|
|||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
{
|
||||
rt_thread_t th;
|
||||
|
||||
th = rt_thread_self();
|
||||
if (th && th->lwp)
|
||||
{
|
||||
rt_backtrace_user_thread(th);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
backtrace((unsigned long)regs->pc, (unsigned long)regs->x30, (unsigned long)regs->x29);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
|
|
@ -75,6 +75,13 @@ rt_weak const char *rt_hw_cpu_arch(void)
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
rt_weak void rt_hw_cpu_reset(void)
|
||||
{
|
||||
LOG_D("rt_hw_cpu_reset() doesn't support for this board."
|
||||
"Please consider implementing rt_hw_cpu_reset() in another file.");
|
||||
return ;
|
||||
}
|
||||
|
||||
static const char* rt_errno_strs[] =
|
||||
{
|
||||
"OK",
|
||||
|
|
Loading…
Reference in New Issue