feat(microkernel): implement pure microkernel architecture with vfs_server, net_server, and procmgr
- Added vfs_server in Ring 3 (Endpoint 5) managing unified VFS tree (/, /bin, /etc, /proc, /dev, /tmp) - Added net_server in Ring 3 (Endpoint 6) owning RTL8139 hardware NIC, DHCP, DNS, and TCP/IPv4 stack - Refactored procmgr in Ring 3 (Endpoint 4) to handle userspace process spawning via PROC_OP_SPAWN - Added primitive microkernel syscalls in Ring 0: SYS_TASK_CREATE (29), SYS_TASK_MAP_PAGE (30), SYS_TASK_START (31) - Updated shell (sh) and desktop GUI (gui_server) to delegate process management and I/O to Ring 3 daemons - Expanded boot pipeline to orchestrate 7 concurrent Ring 3 servers across dedicated SMP CPU cores
This commit is contained in:
@@ -654,20 +654,17 @@ static void execute_console_command(const char *raw_cmd) {
|
||||
exec_target++;
|
||||
}
|
||||
|
||||
int64_t tid = sys_module_exec(exec_target);
|
||||
if (tid < 0 && !strstr(exec_target, ".")) {
|
||||
char opc_name[70];
|
||||
snprintf(opc_name, sizeof(opc_name), "%s.opc", exec_target);
|
||||
tid = sys_module_exec(opc_name);
|
||||
if (tid < 0) {
|
||||
char elf_name[70];
|
||||
snprintf(elf_name, sizeof(elf_name), "%s.elf", exec_target);
|
||||
tid = sys_module_exec(elf_name);
|
||||
}
|
||||
uint64_t p0 = 0, p1 = 0;
|
||||
memcpy(&p0, exec_target, strlen(exec_target) < 8 ? strlen(exec_target) : 8);
|
||||
if (strlen(exec_target) > 8) {
|
||||
memcpy(&p1, exec_target + 8, strlen(exec_target) - 8 < 8 ? strlen(exec_target) - 8 : 8);
|
||||
}
|
||||
uint64_t out0 = 0, out1 = 0;
|
||||
sysret_t ret = sys_ipc_call_raw(PROCMGR_ENDPOINT, PROC_OP_SPAWN, p0, p1, 0, 0, &out0, &out1);
|
||||
int64_t tid = (ret == 0) ? (int64_t)out0 : -1;
|
||||
|
||||
if (tid >= 0) {
|
||||
snprintf(buf, sizeof(buf), "[osh] Process spawned with TID %ld on Ring 3\n", (long)tid);
|
||||
snprintf(buf, sizeof(buf), "[procmgr] Process spawned with TID %ld on Ring 3\n", (long)tid);
|
||||
lv_textarea_add_text(g_txt_term_output, buf);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "osh: %s: command not found\n", raw_cmd);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* opencoreC - Network Stack Server (Ring 3 User Space)
|
||||
* Centralized network daemon managing RTL8139 hardware NIC, ARP, DHCP, DNS, TCP/IP.
|
||||
* Listens on NET_ENDPOINT (6) and handles synchronous IPC requests from sh and gui_server.
|
||||
*/
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "abi/syscalls.h"
|
||||
#include "abi/ipc.h"
|
||||
#include "abi/net.h"
|
||||
|
||||
extern "C" void _start(void) {
|
||||
puts("[NET-SERVER] Initializing Hardware RTL8139 NIC & TCP/IP Stack in Ring 3...");
|
||||
net_init();
|
||||
|
||||
// Acquire DHCP lease on startup
|
||||
int dhcp_res = net_dhcp_discover();
|
||||
char ip_str[32], gw_str[32];
|
||||
format_ip(g_net_cfg.ip, ip_str);
|
||||
format_ip(g_net_cfg.gateway, gw_str);
|
||||
if (dhcp_res == 0) {
|
||||
printf("[NET-SERVER] DHCP OK: IP %s, Gateway %s\n", ip_str, gw_str);
|
||||
} else {
|
||||
printf("[NET-SERVER] DHCP fallback: IP %s, Gateway %s\n", ip_str, gw_str);
|
||||
}
|
||||
|
||||
uint64_t last_client = 0;
|
||||
uint64_t reply_val0 = 0;
|
||||
uint64_t reply_val1 = 0;
|
||||
|
||||
while (1) {
|
||||
uint64_t sender_tid = 0;
|
||||
uint64_t opcode = 0;
|
||||
uint64_t arg0 = 0;
|
||||
uint64_t arg1 = 0;
|
||||
|
||||
sysret_t ret = sys_ipc_reply_recv_raw(
|
||||
NET_ENDPOINT,
|
||||
last_client,
|
||||
reply_val0,
|
||||
reply_val1,
|
||||
&sender_tid,
|
||||
&opcode,
|
||||
&arg0,
|
||||
&arg1
|
||||
);
|
||||
|
||||
if (ret == 0 && sender_tid != 0) {
|
||||
last_client = sender_tid;
|
||||
|
||||
if (opcode == NET_OP_GET_CONFIG) {
|
||||
// reply_val0 = ip (low 32 bits) | (gateway << 32)
|
||||
// reply_val1 = netmask (low 32 bits) | (dns_server << 32)
|
||||
reply_val0 = ((uint64_t)g_net_cfg.gateway << 32) | (uint64_t)g_net_cfg.ip;
|
||||
reply_val1 = ((uint64_t)g_net_cfg.dns_server << 32) | (uint64_t)g_net_cfg.netmask;
|
||||
} else if (opcode == NET_OP_PING) {
|
||||
uint32_t target_ip = (uint32_t)arg0;
|
||||
uint16_t seq = (uint16_t)(arg1 ? arg1 : 1);
|
||||
int ping_res = net_send_icmp_ping(target_ip, seq);
|
||||
reply_val0 = (ping_res == 0) ? 0 : (uint64_t)-1;
|
||||
reply_val1 = 0;
|
||||
} else if (opcode == NET_OP_DNS) {
|
||||
// Domain string passed in arg0 (8 bytes) + arg1 (8 bytes)
|
||||
char domain[20] = {0};
|
||||
memcpy(domain, &arg0, 8);
|
||||
memcpy(domain + 8, &arg1, 8);
|
||||
uint32_t resolved_ip = 0;
|
||||
int res = net_dns_resolve(domain, &resolved_ip);
|
||||
reply_val0 = (res == 0) ? (uint64_t)resolved_ip : 0;
|
||||
reply_val1 = (uint64_t)res;
|
||||
} else if (opcode == NET_OP_DHCP) {
|
||||
int res = net_dhcp_discover();
|
||||
reply_val0 = (res == 0) ? (uint64_t)g_net_cfg.ip : 0;
|
||||
reply_val1 = (uint64_t)g_net_cfg.gateway;
|
||||
} else {
|
||||
reply_val0 = (uint64_t)-1;
|
||||
reply_val1 = 0;
|
||||
}
|
||||
} else {
|
||||
last_client = 0;
|
||||
sys_yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,25 @@ extern "C" void _start() {
|
||||
__asm__ volatile("syscall" : "+r"(rax) : "r"(rdi), "r"(rsi) : "rcx", "r11", "memory");
|
||||
reply_val0 = (rax > 0) ? rax : 0;
|
||||
reply_val1 = 0;
|
||||
} else if (opcode == PROC_OP_SPAWN) {
|
||||
// Program name passed in arg0 (8 bytes) + arg1 (8 bytes)
|
||||
char prog[20] = {0};
|
||||
memcpy(prog, &arg0, 8);
|
||||
memcpy(prog + 8, &arg1, 8);
|
||||
|
||||
int64_t tid = sys_module_exec(prog);
|
||||
if (tid < 0 && !strstr(prog, ".")) {
|
||||
char opc_name[28];
|
||||
snprintf(opc_name, sizeof(opc_name), "%s.opc", prog);
|
||||
tid = sys_module_exec(opc_name);
|
||||
if (tid < 0) {
|
||||
char elf_name[28];
|
||||
snprintf(elf_name, sizeof(elf_name), "%s.elf", prog);
|
||||
tid = sys_module_exec(elf_name);
|
||||
}
|
||||
}
|
||||
reply_val0 = (uint64_t)tid;
|
||||
reply_val1 = 0;
|
||||
} else {
|
||||
reply_val0 = 0;
|
||||
reply_val1 = 0;
|
||||
|
||||
+18
-14
@@ -339,10 +339,17 @@ static void cmd_run_module(const char *mod_name) {
|
||||
while (*mod_name == '.' || *mod_name == '/') {
|
||||
mod_name++;
|
||||
}
|
||||
printf("[osh] Launching native program '%s' via kernel loader...\n", mod_name);
|
||||
int64_t tid = sys_module_exec(mod_name);
|
||||
printf("[osh] Requesting Process Manager (procmgr) to spawn '%s'...\n", mod_name);
|
||||
uint64_t p0 = 0, p1 = 0;
|
||||
memcpy(&p0, mod_name, strlen(mod_name) < 8 ? strlen(mod_name) : 8);
|
||||
if (strlen(mod_name) > 8) {
|
||||
memcpy(&p1, mod_name + 8, strlen(mod_name) - 8 < 8 ? strlen(mod_name) - 8 : 8);
|
||||
}
|
||||
uint64_t out0 = 0, out1 = 0;
|
||||
sysret_t ret = sys_ipc_call_raw(PROCMGR_ENDPOINT, PROC_OP_SPAWN, p0, p1, 0, 0, &out0, &out1);
|
||||
int64_t tid = (ret == 0) ? (int64_t)out0 : -1;
|
||||
if (tid >= 0) {
|
||||
printf("[osh] Process successfully spawned with TID %ld on Ring 3!\n", (long)tid);
|
||||
printf("[procmgr] Process successfully spawned with TID %ld on Ring 3!\n", (long)tid);
|
||||
for (int i = 0; i < 6; i++) sys_yield();
|
||||
} else {
|
||||
printf("osh: failed to execute '%s' (module not found or invalid format)\n", mod_name);
|
||||
@@ -965,20 +972,17 @@ static void handle_command(char *cmd) {
|
||||
exec_target++;
|
||||
}
|
||||
|
||||
int64_t tid = sys_module_exec(exec_target);
|
||||
if (tid < 0 && !strstr(exec_target, ".")) {
|
||||
char opc_name[70];
|
||||
snprintf(opc_name, sizeof(opc_name), "%s.opc", exec_target);
|
||||
tid = sys_module_exec(opc_name);
|
||||
if (tid < 0) {
|
||||
char elf_name[70];
|
||||
snprintf(elf_name, sizeof(elf_name), "%s.elf", exec_target);
|
||||
tid = sys_module_exec(elf_name);
|
||||
}
|
||||
uint64_t p0 = 0, p1 = 0;
|
||||
memcpy(&p0, exec_target, strlen(exec_target) < 8 ? strlen(exec_target) : 8);
|
||||
if (strlen(exec_target) > 8) {
|
||||
memcpy(&p1, exec_target + 8, strlen(exec_target) - 8 < 8 ? strlen(exec_target) - 8 : 8);
|
||||
}
|
||||
uint64_t out0 = 0, out1 = 0;
|
||||
sysret_t ret = sys_ipc_call_raw(PROCMGR_ENDPOINT, PROC_OP_SPAWN, p0, p1, 0, 0, &out0, &out1);
|
||||
int64_t tid = (ret == 0) ? (int64_t)out0 : -1;
|
||||
|
||||
if (tid >= 0) {
|
||||
printf("[osh] Process spawned with TID %ld on Ring 3\n", (long)tid);
|
||||
printf("[procmgr] Process spawned with TID %ld on Ring 3\n", (long)tid);
|
||||
for (int i = 0; i < 6; i++) sys_yield();
|
||||
} else {
|
||||
printf("osh: command not found: %s\n", cmd);
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* opencoreC - Virtual File System Server (Ring 3 User Space)
|
||||
* Centralized file system daemon managing in-memory and virtual file hierarchy.
|
||||
* Listens on VFS_ENDPOINT (5) and handles synchronous IPC requests.
|
||||
*/
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "abi/syscalls.h"
|
||||
#include "abi/ipc.h"
|
||||
#include "abi/vfs.h"
|
||||
|
||||
#define MAX_VFS_NODES 64
|
||||
|
||||
struct VfsNode {
|
||||
char name[48];
|
||||
bool is_dir;
|
||||
uint32_t size;
|
||||
char content[1024];
|
||||
};
|
||||
|
||||
static VfsNode g_nodes[MAX_VFS_NODES];
|
||||
static size_t g_node_count = 0;
|
||||
|
||||
static void vfs_add_dir(const char *name) {
|
||||
if (g_node_count >= MAX_VFS_NODES) return;
|
||||
strncpy(g_nodes[g_node_count].name, name, sizeof(g_nodes[0].name) - 1);
|
||||
g_nodes[g_node_count].is_dir = true;
|
||||
g_nodes[g_node_count].size = 4096;
|
||||
g_nodes[g_node_count].content[0] = '\0';
|
||||
g_node_count++;
|
||||
}
|
||||
|
||||
static void vfs_add_file(const char *name, const char *content) {
|
||||
if (g_node_count >= MAX_VFS_NODES) return;
|
||||
strncpy(g_nodes[g_node_count].name, name, sizeof(g_nodes[0].name) - 1);
|
||||
g_nodes[g_node_count].is_dir = false;
|
||||
uint32_t len = (uint32_t)strlen(content);
|
||||
if (len >= sizeof(g_nodes[0].content)) len = sizeof(g_nodes[0].content) - 1;
|
||||
memcpy(g_nodes[g_node_count].content, content, len);
|
||||
g_nodes[g_node_count].content[len] = '\0';
|
||||
g_nodes[g_node_count].size = len;
|
||||
g_node_count++;
|
||||
}
|
||||
|
||||
static void vfs_init() {
|
||||
g_node_count = 0;
|
||||
|
||||
vfs_add_dir("/");
|
||||
vfs_add_dir("/bin");
|
||||
vfs_add_dir("/etc");
|
||||
vfs_add_dir("/proc");
|
||||
vfs_add_dir("/dev");
|
||||
vfs_add_dir("/tmp");
|
||||
|
||||
vfs_add_file("/etc/os-release",
|
||||
"NAME=\"opencoreC\"\n"
|
||||
"VERSION=\"0.1.0-release\"\n"
|
||||
"ID=opencorec\n"
|
||||
"PRETTY_NAME=\"opencoreC Microkernel x86_64\"\n");
|
||||
|
||||
vfs_add_file("/etc/motd",
|
||||
"=======================================================\n"
|
||||
" Welcome to opencoreC Pure Microkernel (x86_64)!\n"
|
||||
" Servers: init, uart, vfs, net, procmgr, sh, gui\n"
|
||||
"=======================================================\n");
|
||||
|
||||
vfs_add_file("/etc/hosts", "127.0.0.1 localhost\n");
|
||||
vfs_add_file("/proc/version", "opencoreC version 0.1.0-microkernel (Rust Ring 0 + C++ Ring 3)\n");
|
||||
vfs_add_file("/proc/cpuinfo", "model name: x86_64 SMP Microkernel Processor\ncores: 4\n");
|
||||
vfs_add_file("/dev/null", "");
|
||||
vfs_add_file("/dev/uart0", "");
|
||||
vfs_add_file("/dev/net0", "");
|
||||
|
||||
// Dynamically discover in-memory boot modules from Limine
|
||||
char mbuf[512] = {0};
|
||||
int len = sys_module_list(mbuf, sizeof(mbuf) - 1);
|
||||
if (len > 0) {
|
||||
char *p = mbuf;
|
||||
while (*p) {
|
||||
char mod_name[48] = {0};
|
||||
int mi = 0;
|
||||
while (*p && *p != ' ' && mi < 40) {
|
||||
mod_name[mi++] = *p++;
|
||||
}
|
||||
while (*p == ' ') p++;
|
||||
|
||||
if (mi > 0) {
|
||||
char full_path[56];
|
||||
snprintf(full_path, sizeof(full_path), "/bin/%s", mod_name);
|
||||
vfs_add_file(full_path, "[Executable Binary Module]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void _start(void) {
|
||||
vfs_init();
|
||||
puts("[VFS-SERVER] Virtual File System Daemon Started (Endpoint 5, Ring 3).");
|
||||
|
||||
uint64_t last_client = 0;
|
||||
uint64_t reply_val0 = 0;
|
||||
uint64_t reply_val1 = 0;
|
||||
|
||||
while (1) {
|
||||
uint64_t sender_tid = 0;
|
||||
uint64_t opcode = 0;
|
||||
uint64_t arg0 = 0;
|
||||
uint64_t arg1 = 0;
|
||||
|
||||
sysret_t ret = sys_ipc_reply_recv_raw(
|
||||
VFS_ENDPOINT,
|
||||
last_client,
|
||||
reply_val0,
|
||||
reply_val1,
|
||||
&sender_tid,
|
||||
&opcode,
|
||||
&arg0,
|
||||
&arg1
|
||||
);
|
||||
|
||||
if (ret == 0 && sender_tid != 0) {
|
||||
last_client = sender_tid;
|
||||
|
||||
if (opcode == VFS_OP_STAT) {
|
||||
// Path passed packed in arg0 (first 8 bytes) + arg1 (next 8 bytes)
|
||||
char path[32] = {0};
|
||||
memcpy(path, &arg0, 8);
|
||||
memcpy(path + 8, &arg1, 8);
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < g_node_count; i++) {
|
||||
if (strcmp(g_nodes[i].name, path) == 0) {
|
||||
reply_val0 = 0; // Success
|
||||
reply_val1 = g_nodes[i].size | (g_nodes[i].is_dir ? 0x80000000ULL : 0ULL);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
reply_val0 = (uint64_t)-1; // Not found
|
||||
reply_val1 = 0;
|
||||
}
|
||||
} else if (opcode == VFS_OP_LIST) {
|
||||
// arg0 = index
|
||||
size_t idx = (size_t)arg0;
|
||||
if (idx < g_node_count) {
|
||||
reply_val0 = 0; // Success
|
||||
reply_val1 = (uint64_t)g_nodes[idx].size | (g_nodes[idx].is_dir ? 0x80000000ULL : 0ULL);
|
||||
} else {
|
||||
reply_val0 = (uint64_t)-1; // End of list
|
||||
reply_val1 = 0;
|
||||
}
|
||||
} else if (opcode == VFS_OP_READ_FILE) {
|
||||
// arg0: packed name (first 8 bytes), arg1: offset
|
||||
char path[16] = {0};
|
||||
memcpy(path, &arg0, 8);
|
||||
size_t offset = (size_t)arg1;
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < g_node_count; i++) {
|
||||
if (strcmp(g_nodes[i].name, path) == 0) {
|
||||
found = true;
|
||||
if (offset < g_nodes[i].size) {
|
||||
uint64_t chunk = 0;
|
||||
size_t avail = g_nodes[i].size - offset;
|
||||
if (avail > 8) avail = 8;
|
||||
memcpy(&chunk, g_nodes[i].content + offset, avail);
|
||||
reply_val0 = avail;
|
||||
reply_val1 = chunk;
|
||||
} else {
|
||||
reply_val0 = 0; // EOF
|
||||
reply_val1 = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
reply_val0 = (uint64_t)-1;
|
||||
reply_val1 = 0;
|
||||
}
|
||||
} else if (opcode == VFS_OP_WRITE_FILE) {
|
||||
// arg0: packed name (first 8 bytes), arg1: 8 bytes data
|
||||
char path[16] = {0};
|
||||
memcpy(path, &arg0, 8);
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < g_node_count; i++) {
|
||||
if (strcmp(g_nodes[i].name, path) == 0) {
|
||||
found = true;
|
||||
memcpy(g_nodes[i].content, &arg1, 8);
|
||||
g_nodes[i].size = 8;
|
||||
reply_val0 = 0;
|
||||
reply_val1 = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found && g_node_count < MAX_VFS_NODES) {
|
||||
vfs_add_file(path, "");
|
||||
memcpy(g_nodes[g_node_count - 1].content, &arg1, 8);
|
||||
g_nodes[g_node_count - 1].size = 8;
|
||||
reply_val0 = 0;
|
||||
reply_val1 = 8;
|
||||
}
|
||||
} else {
|
||||
reply_val0 = (uint64_t)-1;
|
||||
reply_val1 = 0;
|
||||
}
|
||||
} else {
|
||||
last_client = 0;
|
||||
sys_yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user