mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[kernel] Add handle_clone syscall
Added the handle_clone syscall which allows for cloning a handle with a subset of the original handle's capabilities. Related changes: - srv.init now calls handle_clone on its system handle, and load_program was changed to allow this second system handle to be passed to loaded programs instead. However, as drv.uart is still a driver AND a log reader, this new handle is not actually passed yet. - The definition parser was using a set for the cap list, which meant the order (and thus values) of caps was not static. - Some code in objects/handle.h was made more explicit about what bits meant what.
This commit is contained in:
@@ -34,4 +34,12 @@ interface syscalls [syscall] {
|
|||||||
function handle_list {
|
function handle_list {
|
||||||
param handles object kobject [list inout optional] # A list of handles to be filled
|
param handles object kobject [list inout optional] # A list of handles to be filled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Create a clone of an existing handle, possibly with
|
||||||
|
# some capabilities masked out.
|
||||||
|
function handle_clone {
|
||||||
|
param handle object kobject [handle] # The handle to clone
|
||||||
|
param clone object kobject [out] # The new handle
|
||||||
|
param mask uint32 # The capability bitmask
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ class Object:
|
|||||||
self.super = typename
|
self.super = typename
|
||||||
self.methods = children
|
self.methods = children
|
||||||
self.cname = cname or name
|
self.cname = cname or name
|
||||||
|
self.caps = caps
|
||||||
self.caps = set(caps)
|
|
||||||
|
|
||||||
from . import ObjectRef
|
from . import ObjectRef
|
||||||
self.__ref = ObjectRef(name)
|
self.__ref = ObjectRef(name)
|
||||||
|
|||||||
@@ -9,11 +9,18 @@ namespace obj {
|
|||||||
|
|
||||||
struct handle
|
struct handle
|
||||||
{
|
{
|
||||||
|
constexpr static uint64_t id_mask = 0x00000000ffffffff;
|
||||||
|
constexpr static uint64_t cap_mask = 0x00ffffff00000000;
|
||||||
|
constexpr static uint64_t type_mask = 0xff00000000000000;
|
||||||
|
|
||||||
|
constexpr static unsigned cap_shift = 32;
|
||||||
|
constexpr static unsigned type_shift = 56;
|
||||||
|
|
||||||
// A j6_handle_t is an id in the low 32 bits, caps in bits 32-55, and type in 56-63
|
// A j6_handle_t is an id in the low 32 bits, caps in bits 32-55, and type in 56-63
|
||||||
static inline j6_handle_t make_id(j6_handle_t id, j6_cap_t caps, kobject *obj) {
|
static inline j6_handle_t make_id(j6_handle_t id, j6_cap_t caps, kobject *obj) {
|
||||||
return (id & 0xffffffffull) |
|
return (id & 0xffffffffull) |
|
||||||
static_cast<j6_handle_t>(caps) << 32 |
|
((static_cast<j6_handle_t>(caps) << cap_shift) & cap_mask) |
|
||||||
static_cast<j6_handle_t>(obj ? obj->get_type() : kobject::type::none) << 56;
|
static_cast<j6_handle_t>(obj ? obj->get_type() : kobject::type::none) << type_shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline handle(j6_handle_t in_id, kobject *in_obj, j6_cap_t caps) :
|
inline handle(j6_handle_t in_id, kobject *in_obj, j6_cap_t caps) :
|
||||||
@@ -50,7 +57,7 @@ struct handle
|
|||||||
if (object) object->handle_release();
|
if (object) object->handle_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline j6_cap_t caps() const { return id >> 32; }
|
inline j6_cap_t caps() const { return (id & cap_mask) >> cap_shift; }
|
||||||
|
|
||||||
inline bool has_cap(j6_cap_t test) const {
|
inline bool has_cap(j6_cap_t test) const {
|
||||||
return (caps() & test) == test;
|
return (caps() & test) == test;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <j6/types.h>
|
#include <j6/types.h>
|
||||||
|
|
||||||
#include "objects/process.h"
|
#include "objects/process.h"
|
||||||
|
#include "syscalls/helpers.h"
|
||||||
|
|
||||||
using namespace obj;
|
using namespace obj;
|
||||||
|
|
||||||
@@ -24,4 +25,19 @@ handle_list(j6_handle_t *handles, size_t *handles_len)
|
|||||||
return j6_status_ok;
|
return j6_status_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
j6_status_t
|
||||||
|
handle_clone(j6_handle_t orig, j6_handle_t *clone, uint32_t mask)
|
||||||
|
{
|
||||||
|
handle *orig_handle = get_handle<kobject>(orig);
|
||||||
|
if (!orig_handle)
|
||||||
|
return j6_err_invalid_arg;
|
||||||
|
|
||||||
|
process &p = process::current();
|
||||||
|
*clone = p.add_handle(
|
||||||
|
orig_handle->object,
|
||||||
|
orig_handle->caps() & mask);
|
||||||
|
|
||||||
|
return j6_status_ok;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace syscalls
|
} // namespace syscalls
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ constexpr size_t stack_size = 0x10000;
|
|||||||
constexpr uintptr_t stack_top = 0x80000000000;
|
constexpr uintptr_t stack_top = 0x80000000000;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
load_program(const module_program &prog, char *err_msg)
|
load_program(const module_program &prog, j6_handle_t sys, char *err_msg)
|
||||||
{
|
{
|
||||||
if (prog.mod_flags && module_flags::no_load) {
|
if (prog.mod_flags && module_flags::no_load) {
|
||||||
sprintf(err_msg, " skipping pre-loaded program module '%s' at %lx", prog.filename, prog.base_address);
|
sprintf(err_msg, " skipping pre-loaded program module '%s' at %lx", prog.filename, prog.base_address);
|
||||||
@@ -55,7 +55,7 @@ load_program(const module_program &prog, char *err_msg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = j6_process_give_handle(proc, __handle_sys, nullptr);
|
res = j6_process_give_handle(proc, sys, nullptr);
|
||||||
if (res != j6_status_ok) {
|
if (res != j6_status_ok) {
|
||||||
sprintf(err_msg, " ** error loading program '%s': giving system handle: %lx", prog.filename, res);
|
sprintf(err_msg, " ** error loading program '%s': giving system handle: %lx", prog.filename, res);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
/// \file loader.h
|
/// \file loader.h
|
||||||
/// Routines for loading and starting other programs
|
/// Routines for loading and starting other programs
|
||||||
|
|
||||||
|
#include <j6/types.h>
|
||||||
|
|
||||||
namespace bootproto {
|
namespace bootproto {
|
||||||
struct module_program;
|
struct module_program;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load_program(const bootproto::module_program &prog, char *err_msg);
|
bool load_program(const bootproto::module_program &prog, j6_handle_t sys, char *err_msg);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <j6/caps.h>
|
||||||
#include <j6/errors.h>
|
#include <j6/errors.h>
|
||||||
#include <j6/syscalls.h>
|
#include <j6/syscalls.h>
|
||||||
#include <j6/types.h>
|
#include <j6/types.h>
|
||||||
@@ -29,6 +30,12 @@ main(int argc, const char **argv)
|
|||||||
|
|
||||||
modules mods = modules::load_modules(_arg_modules_phys, __handle_sys, __handle_self);
|
modules mods = modules::load_modules(_arg_modules_phys, __handle_sys, __handle_self);
|
||||||
|
|
||||||
|
j6_handle_t drv_sys_handle = j6_handle_invalid;
|
||||||
|
j6_status_t s = j6_handle_clone(__handle_sys, &drv_sys_handle,
|
||||||
|
j6_cap_system_bind_irq | j6_cap_system_map_phys | j6_cap_system_change_iopl);
|
||||||
|
if (s != j6_status_ok)
|
||||||
|
return s;
|
||||||
|
|
||||||
for (auto &mod : mods.of_type(module_type::program)) {
|
for (auto &mod : mods.of_type(module_type::program)) {
|
||||||
auto &prog = static_cast<const module_program&>(mod);
|
auto &prog = static_cast<const module_program&>(mod);
|
||||||
|
|
||||||
@@ -36,7 +43,7 @@ main(int argc, const char **argv)
|
|||||||
sprintf(message, " loading program module '%s' at %lx", prog.filename, prog.base_address);
|
sprintf(message, " loading program module '%s' at %lx", prog.filename, prog.base_address);
|
||||||
j6_log(message);
|
j6_log(message);
|
||||||
|
|
||||||
if (!load_program(prog, message)) {
|
if (!load_program(prog, __handle_sys, message)) {
|
||||||
j6_log(message);
|
j6_log(message);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user