Skip to content

Commit e94281e

Browse files
committed
修复 general_map 异常返回行为的问题, 内核堆增加扩容机制.
- 增加 memfd 与 memfd_create 系统调用 - initramfs 修复与 rootfs 新增 xorg
1 parent 4f17d16 commit e94281e

File tree

13 files changed

+257
-10
lines changed

13 files changed

+257
-10
lines changed

assets/cp_rootfs.sfs

17.3 MB
Binary file not shown.

assets/initramfs.img

512 Bytes
Binary file not shown.

libs/liballoc-x86_64.a

-296 Bytes
Binary file not shown.

src/arch/x86_64/include/nr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
#define SYSCALL_PIPE2 293
154154
#define SYSCALL_PRLIMIT64 302
155155
#define SYSCALL_GETRANDOM 318
156+
#define SYSCALL_MEMFD_CREATE 319
156157
#define SYSCALL_CP_F_RANGE 326
157158
#define SYSCALL_STATX 332
158159
#define SYSCALL_FSOPEN 430

src/arch/x86_64/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "fs/sysfs.h"
3030
#include "fs/tmpfs.h"
3131
#include "fs/vfs.h"
32+
#include "fs/memfd.h"
3233
#include "fsgsbase.h"
3334
#include "hpet.h"
3435
#include "intctl.h"
@@ -124,6 +125,7 @@ USED _Noreturn void kmain() {
124125
sockfs_regist();
125126
epollfs_regist();
126127
eventfdfs_regist();
128+
memfd_setup();
127129
sysfs_regist();
128130

129131
// 率先将调度器 IRQ 注册进去, 防止驱动程序IRQ分配占用

src/arch/x86_64/syscall.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ syscall_t syscall_handlers[MAX_SYSCALLS] = {
254254
[SYSCALL_EPOLL_PWAIT] = (syscall_t)syscall_epoll_pwait,
255255
[SYSCALL_ACCEPT4] = (syscall_t)syscall_accept4,
256256
[SYSCALL_EVENTFD2] = (syscall_t)syscall_eventfd2,
257+
[SYSCALL_FTRUNCATE] = (syscall_t)syscall_ftruncate,
258+
[SYSCALL_MEMFD_CREATE] = (syscall_t)syscall_memfd_create,
257259
};
258260

259261
USED void syscall_handler(struct syscall_regs *regs, uint64_t user_regs) { // syscall 指令处理

src/fs/memfd.c

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#include "fs/memfd.h"
2+
#include "errno.h"
3+
#include "mem/frame.h"
4+
#include "mem/page.h"
5+
#include "task/task.h"
6+
#include "term/klog.h"
7+
#include "syscall.h"
8+
9+
static int memfd_fsid = 0;
10+
11+
static size_t memfd_read(void *data, void *buf, size_t offset, size_t len) {
12+
const struct memfd_ctx *ctx = data;
13+
const size_t avail = ctx->len - offset;
14+
if (avail <= 0) {
15+
return 0;
16+
}
17+
const size_t copy_len = len < avail ? len : avail;
18+
memcpy(buf, ctx->data + offset, copy_len);
19+
return copy_len;
20+
}
21+
22+
static size_t memfd_write(void *data, const void *buf, size_t offset, size_t len) {
23+
struct memfd_ctx *ctx = data;
24+
spin_lock(ctx->lock);
25+
if (offset + len > ctx->len) {
26+
const size_t new_size = ctx->len * 2;
27+
const uint64_t phys_addr = alloc_frames(new_size / PAGE_SIZE);
28+
uint8_t *new_data = phys_to_virt(phys_addr);
29+
if (!new_data) {
30+
spin_unlock(ctx->lock);
31+
return -ENOMEM;
32+
}
33+
page_map_range(
34+
get_kernel_pagedir(), (uint64_t)new_data, phys_addr, ctx->len, KERNEL_PTE_FLAGS
35+
);
36+
memcpy(new_data, ctx->data, ctx->len);
37+
unmap_page_range(get_kernel_pagedir(), (uint64_t)ctx->data, ctx->len);
38+
ctx->data = new_data;
39+
ctx->len = new_size;
40+
}
41+
memcpy(ctx->data + offset, buf, len);
42+
ctx->node->size = ctx->len;
43+
spin_unlock(ctx->lock);
44+
return len;
45+
}
46+
47+
static void *
48+
memfd_map(void *file, void *addr, size_t offset, size_t size, size_t prot, size_t flags) {
49+
if ((flags & MAP_TYPE) == MAP_PRIVATE) {
50+
return general_map(memfd_read, file, (uint64_t)addr, size, prot, flags, offset);
51+
}
52+
const struct memfd_ctx *ctx = file;
53+
page_map_range(
54+
get_current_task()->process->directory,
55+
(uint64_t)addr,
56+
virt_to_phys((void *)ctx->data + offset),
57+
size,
58+
KERNEL_PTE_FLAGS
59+
);
60+
return addr;
61+
}
62+
63+
bool memfd_close(void *handle) {
64+
struct memfd_ctx *ctx = handle;
65+
if (!ctx) {
66+
return true;
67+
}
68+
69+
spin_lock(ctx->lock);
70+
71+
unmap_page_range(get_kernel_pagedir(), (uint64_t)ctx->data, ctx->len);
72+
73+
spin_unlock(ctx->lock);
74+
ctx->node->handle = NULL;
75+
free(ctx);
76+
return true;
77+
}
78+
79+
errno_t memfd_stat(void *file, vfs_node_t node) {
80+
struct memfd_ctx *ctx = file;
81+
if (!ctx) {
82+
return -EINVAL;
83+
}
84+
node->size = ctx->len;
85+
return EOK;
86+
}
87+
88+
errno_t memfd_free(void *handle) {
89+
if (!handle) {
90+
return EOK;
91+
}
92+
free(handle);
93+
return EOK;
94+
}
95+
96+
syscall_(memfd_create, const char *name, const unsigned int flags) {
97+
if (flags & MFD_HUGETLB) {
98+
return -EINVAL;
99+
}
100+
101+
if (flags & MFD_NOEXEC_SEAL || flags & MFD_EXEC) {
102+
return -EINVAL;
103+
}
104+
105+
struct memfd_ctx *ctx = malloc(sizeof(struct memfd_ctx));
106+
if (!ctx) {
107+
return SYSCALL_FAULT_(ENOMEM);
108+
}
109+
strncpy(ctx->name, name, 63);
110+
ctx->name[63] = '\0';
111+
ctx->len = PAGE_SIZE;
112+
113+
const uint64_t phys_addr = alloc_frames(1);
114+
ctx->data = phys_to_virt(phys_addr);
115+
page_map_range(
116+
get_kernel_pagedir(), (uint64_t)ctx->data, phys_addr, ctx->len, KERNEL_PTE_FLAGS
117+
);
118+
memset(ctx->data, 0, ctx->len);
119+
ctx->flags = flags;
120+
ctx->lock = SPIN_INIT;
121+
122+
const vfs_node_t node = vfs_node_alloc(NULL, NULL);
123+
node->type = file_none;
124+
node->fsid = memfd_fsid;
125+
node->handle = ctx;
126+
node->refcount++;
127+
node->size = 0;
128+
ctx->node = node;
129+
fd_t *fd = calloc(1, sizeof(fd_t));
130+
if (!fd) {
131+
free(ctx);
132+
return SYSCALL_FAULT_(ENOMEM);
133+
}
134+
fd->flags = flags;
135+
fd->node = node;
136+
return add_fd(get_current_task()->process->fdts, fd);
137+
}
138+
139+
static struct vfs_callback memfd_callbacks = {
140+
.mount = (vfs_mount_t)dummy,
141+
.unmount = (vfs_unmount_t)dummy,
142+
.mkdir = (vfs_mk_t)dummy,
143+
.close = memfd_close,
144+
.stat = memfd_stat,
145+
.open = (vfs_open_t)dummy,
146+
.read = memfd_read,
147+
.write = memfd_write,
148+
.readlink = (vfs_readlink_t)dummy,
149+
.mkfile = (vfs_mk_t)dummy,
150+
.link = (vfs_mk_t)dummy,
151+
.symlink = (vfs_mk_t)dummy,
152+
.ioctl = (vfs_ioctl_t)dummy,
153+
.dup = (vfs_dup_t)dummy,
154+
.delete = (vfs_del_t)dummy,
155+
.rename = (vfs_rename_t)dummy,
156+
.poll = (vfs_poll_t)dummy,
157+
.map = memfd_map,
158+
.free = memfd_free,
159+
.chmod = (vfs_chmod_t)dummy,
160+
.mknod = (vfs_mknod_t)dummy,
161+
};
162+
163+
void memfd_setup() {
164+
memfd_fsid = vfs_regist("memfdfs", &memfd_callbacks, 0x45564644, FS_VIRTUAL_FLAGS);
165+
if (memfd_fsid == -EINVAL) {
166+
kerror("eventfdfs regist error.");
167+
}
168+
}

src/fs/procfs/procfs.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ size_t procfs_self_readlink(vfs_node_t file, void *addr, size_t offset, size_t s
108108
return 0;
109109
if (offset >= strlen(file->linkto->name))
110110
return 0;
111-
logkf("procfs: readlink offset:%llu size:%llu", offset, size);
112111
char *ptr = file->linkto->name + offset;
113112
ssize_t len = strlen(ptr);
114113
len = MIN(len, (ssize_t)size);

src/fs/vfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ void vfs_deinit() {
614614
static _Atomic size_t inode_now = 0;
615615

616616
vfs_node_t vfs_node_alloc(vfs_node_t parent, const char *name) {
617-
vfs_node_t node = malloc(sizeof(struct vfs_node));
617+
const vfs_node_t node = malloc(sizeof(struct vfs_node));
618618
not_null_assert(node, "vfs alloc null");
619619
if (unlikely(node == NULL))
620620
return NULL;
@@ -1098,7 +1098,7 @@ void *general_map(
10981098

10991099
ssize_t ret = read_callback(file, (void *)addr, offset, len);
11001100
if (ret < 0)
1101-
return (void *)-ENOMEM;
1101+
return (void*)ret;
11021102

11031103
if ((uint64_t)ret < len) {
11041104
memset((void *)(addr + (uint64_t)ret), 0, len - (uint64_t)ret);

src/include/fs/memfd.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#define MFD_CLOEXEC 0x0001U
4+
#define MFD_ALLOW_SEALING 0x0002U
5+
#define MFD_HUGETLB 0x0004U
6+
#define MFD_NOEXEC_SEAL 0x0008U
7+
#define MFD_EXEC 0x0010U
8+
9+
#include "fs/vfs.h"
10+
#include "lock.h"
11+
12+
struct memfd_ctx {
13+
vfs_node_t node;
14+
char name[64];
15+
uint8_t *data;
16+
size_t len;
17+
int flags;
18+
spin_t lock;
19+
};
20+
21+
void memfd_setup();

0 commit comments

Comments
 (0)