2021-05-23 22:24:02 +08:00

93 lines
2.7 KiB
C

/*
* Copyright (c) 2020 Institute of Parallel And Distributed Systems (IPADS),
* Shanghai Jiao Tong University (SJTU) OS-Lab-2020 (i.e., ChCore) is licensed
* under the Mulan PSL v1. You can use this software according to the terms and
* conditions of the Mulan PSL v1. You may obtain a copy of Mulan PSL v1 at:
* http://license.coscl.org.cn/MulanPSL
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v1 for more details.
*/
#include <common/errno.h>
#include <common/kprint.h>
#include <common/macro.h>
#include <common/util.h>
#include <ipc/ipc.h>
#include <exception/irq.h>
#include <common/kmalloc.h>
#include <common/mm.h>
#include <common/uaccess.h>
#include <process/thread.h>
#include <sched/context.h>
#include <sched/sched.h>
#define SHADOW_THREAD_PRIO MAX_PRIO - 1
/**
* The core function for registering the server
*/
static int register_server(struct thread *server, u64 callback, u64 max_client,
u64 vm_config_ptr)
{
int r;
struct server_ipc_config *server_ipc_config;
struct ipc_vm_config *vm_config;
BUG_ON(server == NULL);
// Create the server ipc_config
server_ipc_config = kmalloc(sizeof(struct server_ipc_config));
if (!server_ipc_config) {
r = -ENOMEM;
goto out_fail;
}
server->server_ipc_config = server_ipc_config;
// Init the server ipc_config
server_ipc_config->callback = callback;
if (max_client > IPC_MAX_CONN_PER_SERVER) {
r = -EINVAL;
goto out_free_server_ipc_config;
}
server_ipc_config->max_client = max_client;
server_ipc_config->conn_bmp =
kzalloc(BITS_TO_LONGS(max_client) * sizeof(long));
if (!server_ipc_config->conn_bmp) {
r = -ENOMEM;
goto out_free_server_ipc_config;
}
// Get and check the parameter vm_config
vm_config = &server_ipc_config->vm_config;
r = copy_from_user((char *)vm_config, (char *)vm_config_ptr,
sizeof(*vm_config));
if (r < 0)
goto out_free_conn_bmp;
if (!is_user_addr_range(vm_config->stack_base_addr,
vm_config->stack_size) ||
!is_user_addr_range(vm_config->buf_base_addr,
vm_config->buf_size) ||
!IS_ALIGNED(vm_config->stack_base_addr, PAGE_SIZE) ||
!IS_ALIGNED(vm_config->stack_size, PAGE_SIZE) ||
!IS_ALIGNED(vm_config->buf_base_addr, PAGE_SIZE) ||
!IS_ALIGNED(vm_config->buf_size, PAGE_SIZE)) {
r = -EINVAL;
goto out_free_conn_bmp;
}
return r;
out_free_conn_bmp:
kfree(server_ipc_config->conn_bmp);
out_free_server_ipc_config:
kfree(server_ipc_config);
out_fail:
return r;
}
u64 sys_register_server(u64 callback, u64 max_client, u64 vm_config_ptr)
{
return register_server(current_thread, callback, max_client,
vm_config_ptr);
}