[kernel] Add capabilities to handles
This change finally adds capabilities to handles. Included changes: - j6_handle_t is now again 64 bits, with the highest 8 bits being a type code, and the next highest 24 bits being the capability mask, so that programs can check type/caps without calling the kernel. - The definitions grammar now includes a `capabilities [ ]` section on objects, to list what capabilities are relevant. - j6/caps.h is auto-generated from object capability lists - init_libj6 again sets __handle_self and __handle_sys, this is a bit of a hack. - A new syscall, j6_handle_list, will return the list of existing handles owned by the calling process. - syscall_verify.cpp.cog now actually checks that the needed capabilities exist on handles before allowing the call.
This commit is contained in:
@@ -2,7 +2,7 @@ start: import_statement* (object|interface)+
|
|||||||
|
|
||||||
import_statement: "import" PATH
|
import_statement: "import" PATH
|
||||||
|
|
||||||
object: description? "object" name options? super? "{" uid cname? method* "}"
|
object: description? "object" name options? super? "{" uid cname? capabilities? method* "}"
|
||||||
|
|
||||||
interface: description? "interface" name options? "{" uid interface_param* "}"
|
interface: description? "interface" name options? "{" uid interface_param* "}"
|
||||||
|
|
||||||
@@ -14,6 +14,8 @@ uid: "uid" UID
|
|||||||
|
|
||||||
cname: "cname" IDENTIFIER
|
cname: "cname" IDENTIFIER
|
||||||
|
|
||||||
|
capabilities: "capabilities" "[" IDENTIFIER+ "]"
|
||||||
|
|
||||||
super: ":" name
|
super: ":" name
|
||||||
|
|
||||||
function: description? "function" name options? ("{" param* "}")?
|
function: description? "function" name options? ("{" param* "}")?
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
object channel : kobject {
|
object channel : kobject {
|
||||||
uid 3ea38b96aa0e54c8
|
uid 3ea38b96aa0e54c8
|
||||||
|
|
||||||
method create [constructor]
|
capabilities [
|
||||||
method close [destructor]
|
send
|
||||||
|
receive
|
||||||
|
close
|
||||||
|
]
|
||||||
|
|
||||||
method send {
|
method create [constructor]
|
||||||
|
method close [destructor cap:close]
|
||||||
|
|
||||||
|
method send [cap:send] {
|
||||||
param data buffer [inout]
|
param data buffer [inout]
|
||||||
}
|
}
|
||||||
|
|
||||||
method receive {
|
method receive [cap:receive] {
|
||||||
param data buffer [out]
|
param data buffer [out]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,18 +4,23 @@
|
|||||||
object endpoint : kobject {
|
object endpoint : kobject {
|
||||||
uid c5882f24a4c03b7e
|
uid c5882f24a4c03b7e
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
send
|
||||||
|
receive
|
||||||
|
]
|
||||||
|
|
||||||
method create [constructor]
|
method create [constructor]
|
||||||
|
|
||||||
# Send a message on a channel. Blocks until the message
|
# Send a message on a channel. Blocks until the message
|
||||||
# is received.
|
# is received.
|
||||||
method send {
|
method send [cap:send] {
|
||||||
param tag uint64
|
param tag uint64
|
||||||
param data buffer
|
param data buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
# Receieve a message on a channel. Blocks until a message
|
# Receieve a message on a channel. Blocks until a message
|
||||||
# is available.
|
# is available.
|
||||||
method receive {
|
method receive [cap:receive] {
|
||||||
param tag uint64 [out]
|
param tag uint64 [out]
|
||||||
param data buffer [out optional]
|
param data buffer [out optional]
|
||||||
param timeout uint64 # Receive timeout in nanoseconds
|
param timeout uint64 # Receive timeout in nanoseconds
|
||||||
@@ -24,7 +29,7 @@ object endpoint : kobject {
|
|||||||
# Send a message on a channel and then await a new message.
|
# Send a message on a channel and then await a new message.
|
||||||
# Equivalent to calling send and then recieve, as a single
|
# Equivalent to calling send and then recieve, as a single
|
||||||
# operation.
|
# operation.
|
||||||
method sendrecv {
|
method sendrecv [cap:send cap:receive] {
|
||||||
param tag uint64 [inout]
|
param tag uint64 [inout]
|
||||||
param data buffer [inout]
|
param data buffer [inout]
|
||||||
param timeout uint64 # Receive timeout in nanoseconds
|
param timeout uint64 # Receive timeout in nanoseconds
|
||||||
|
|||||||
@@ -6,11 +6,16 @@ import "objects/kobject.def"
|
|||||||
object process : kobject {
|
object process : kobject {
|
||||||
uid 0c69ee0b7502ba31
|
uid 0c69ee0b7502ba31
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
kill
|
||||||
|
create_thread
|
||||||
|
]
|
||||||
|
|
||||||
# Create a new empty process
|
# Create a new empty process
|
||||||
method create [constructor]
|
method create [constructor]
|
||||||
|
|
||||||
# Stop all threads and exit the given process
|
# Stop all threads and exit the given process
|
||||||
method kill [destructor]
|
method kill [destructor cap:kill]
|
||||||
|
|
||||||
# Stop all threads and exit the current process
|
# Stop all threads and exit the current process
|
||||||
method exit [static] {
|
method exit [static] {
|
||||||
|
|||||||
@@ -6,21 +6,28 @@ import "objects/vma.def"
|
|||||||
object system : kobject {
|
object system : kobject {
|
||||||
uid fa72506a2cf71a30
|
uid fa72506a2cf71a30
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
get_log
|
||||||
|
bind_irq
|
||||||
|
map_phys
|
||||||
|
change_iopl
|
||||||
|
]
|
||||||
|
|
||||||
# Get a log line from the kernel log
|
# Get a log line from the kernel log
|
||||||
method get_log {
|
method get_log [cap:get_log] {
|
||||||
param buffer buffer [out optional] # Buffer for the log message data structure
|
param buffer buffer [out optional] # Buffer for the log message data structure
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ask the kernel to send this process messages whenever
|
# Ask the kernel to send this process messages whenever
|
||||||
# the given IRQ fires
|
# the given IRQ fires
|
||||||
method bind_irq {
|
method bind_irq [cap:bind_irq] {
|
||||||
param dest object endpoint # Endpoint that will receive messages
|
param dest object endpoint # Endpoint that will receive messages
|
||||||
param irq uint # IRQ number to bind
|
param irq uint # IRQ number to bind
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a VMA and map an area of physical memory into it,
|
# Create a VMA and map an area of physical memory into it,
|
||||||
# also mapping that VMA into the current process
|
# also mapping that VMA into the current process
|
||||||
method map_phys {
|
method map_phys [cap:map_phys] {
|
||||||
param area object vma [out] # Receives a handle to the VMA created
|
param area object vma [out] # Receives a handle to the VMA created
|
||||||
param phys address # The physical address of the area
|
param phys address # The physical address of the area
|
||||||
param size size # Size of the area, in pages
|
param size size # Size of the area, in pages
|
||||||
@@ -29,7 +36,7 @@ object system : kobject {
|
|||||||
|
|
||||||
# Request the kernel change the IOPL for this process. The only values
|
# Request the kernel change the IOPL for this process. The only values
|
||||||
# that make sense are 0 and 3.
|
# that make sense are 0 and 3.
|
||||||
method request_iopl {
|
method request_iopl [cap:change_iopl] {
|
||||||
param iopl uint # The IOPL to set for this process
|
param iopl uint # The IOPL to set for this process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
object thread : kobject {
|
object thread : kobject {
|
||||||
uid 11f23e593d5761bd
|
uid 11f23e593d5761bd
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
kill
|
||||||
|
]
|
||||||
|
|
||||||
method create [constructor] {
|
method create [constructor] {
|
||||||
param process object process
|
param process object process [cap:create_thread]
|
||||||
param stack_top address
|
param stack_top address
|
||||||
param entrypoint address
|
param entrypoint address
|
||||||
}
|
}
|
||||||
|
|
||||||
method kill [destructor]
|
method kill [destructor cap:kill]
|
||||||
|
|
||||||
method exit [static] {
|
method exit [static] {
|
||||||
param status int32
|
param status int32
|
||||||
|
|||||||
@@ -4,27 +4,33 @@ object vma : kobject {
|
|||||||
uid d6a12b63b3ed3937
|
uid d6a12b63b3ed3937
|
||||||
cname vm_area
|
cname vm_area
|
||||||
|
|
||||||
|
capabilities [
|
||||||
|
map
|
||||||
|
unmap
|
||||||
|
resize
|
||||||
|
]
|
||||||
|
|
||||||
method create [constructor] {
|
method create [constructor] {
|
||||||
param size size
|
param size size
|
||||||
param flags uint32
|
param flags uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
method create_map [constructor] {
|
method create_map [constructor cap:map] {
|
||||||
param size size
|
param size size
|
||||||
param address address
|
param address address
|
||||||
param flags uint32
|
param flags uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
method map {
|
method map [cap:map] {
|
||||||
param process object process
|
param process object process
|
||||||
param address address
|
param address address
|
||||||
}
|
}
|
||||||
|
|
||||||
method unmap {
|
method unmap [cap:unmap] {
|
||||||
param process object process
|
param process object process
|
||||||
}
|
}
|
||||||
|
|
||||||
method resize {
|
method resize [cap:resize] {
|
||||||
param size size [inout]
|
param size size [inout]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import "objects/system.def"
|
|
||||||
import "objects/kobject.def"
|
import "objects/kobject.def"
|
||||||
import "objects/process.def"
|
|
||||||
import "objects/thread.def"
|
|
||||||
import "objects/channel.def"
|
import "objects/channel.def"
|
||||||
import "objects/endpoint.def"
|
import "objects/endpoint.def"
|
||||||
|
import "objects/event.def"
|
||||||
|
import "objects/process.def"
|
||||||
|
import "objects/system.def"
|
||||||
|
import "objects/thread.def"
|
||||||
import "objects/vma.def"
|
import "objects/vma.def"
|
||||||
|
|
||||||
interface syscalls [syscall] {
|
interface syscalls [syscall] {
|
||||||
@@ -11,6 +13,7 @@ interface syscalls [syscall] {
|
|||||||
|
|
||||||
expose object system
|
expose object system
|
||||||
expose object kobject
|
expose object kobject
|
||||||
|
expose object event
|
||||||
expose object process
|
expose object process
|
||||||
expose object thread
|
expose object thread
|
||||||
expose object channel
|
expose object channel
|
||||||
@@ -24,4 +27,11 @@ interface syscalls [syscall] {
|
|||||||
function log {
|
function log {
|
||||||
param message string
|
param message string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Get a list of handles owned by this process. If the
|
||||||
|
# supplied list is not big enough, will set the size
|
||||||
|
# needed in `size` and return j6_err_insufficient
|
||||||
|
function handle_list {
|
||||||
|
param handles object kobject [list inout optional] # A list of handles to be filled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,14 @@ class Context:
|
|||||||
from .types import ObjectRef
|
from .types import ObjectRef
|
||||||
ObjectRef.connect(objects)
|
ObjectRef.connect(objects)
|
||||||
|
|
||||||
|
for obj in objects.values():
|
||||||
|
for method in obj.methods:
|
||||||
|
caps = method.options.get("cap", list())
|
||||||
|
for cap in caps:
|
||||||
|
if not cap in obj.caps:
|
||||||
|
from .errors import UnknownCapError
|
||||||
|
raise UnknownCapError(f"Unknown capability {cap} on {obj.name}::{method.name}")
|
||||||
|
|
||||||
self.objects.update(objects)
|
self.objects.update(objects)
|
||||||
self.interfaces.update(interfaces)
|
self.interfaces.update(interfaces)
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
class InvalidType(Exception): pass
|
class InvalidType(Exception): pass
|
||||||
class UnknownTypeError(Exception): pass
|
class UnknownTypeError(Exception): pass
|
||||||
|
class UnknownCapError(Exception): pass
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
def generate_template(template, outfile, **kwargs):
|
|
||||||
from hashlib import md5
|
|
||||||
from os import makedirs
|
|
||||||
from os.path import dirname, exists
|
|
||||||
|
|
||||||
content = template.render(**kwargs)
|
|
||||||
h = md5(content.encode('utf-8')).hexdigest()
|
|
||||||
|
|
||||||
if exists(outfile):
|
|
||||||
existing = open(outfile, 'r').read().encode('utf-8')
|
|
||||||
if md5(existing).hexdigest() == h:
|
|
||||||
return False
|
|
||||||
|
|
||||||
makedirs(dirname(outfile), exist_ok=True)
|
|
||||||
open(outfile, 'w').write(content)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def generate(ctx, outdir, template_type):
|
|
||||||
from os.path import basename, join, split, splitext
|
|
||||||
from jinja2 import Environment, PackageLoader
|
|
||||||
|
|
||||||
for name, interface in ctx.interfaces.items():
|
|
||||||
base = "_".join(sorted(interface.options))
|
|
||||||
|
|
||||||
path = join("templates", base, template_type)
|
|
||||||
env = Environment(
|
|
||||||
loader = PackageLoader('definitions', package_path=path),
|
|
||||||
trim_blocks = True, lstrip_blocks = True)
|
|
||||||
|
|
||||||
env.filters
|
|
||||||
|
|
||||||
for template_name in env.list_templates():
|
|
||||||
template = env.get_template(template_name)
|
|
||||||
|
|
||||||
basepath, filename = split(template_name)
|
|
||||||
filename, ext = splitext(filename)
|
|
||||||
|
|
||||||
if filename == "_object_":
|
|
||||||
for obj in ctx.objects.values():
|
|
||||||
outfile = join(outdir, basepath, obj.name + ext)
|
|
||||||
wrote = generate_template(
|
|
||||||
template, outfile,
|
|
||||||
filename=obj.name + ext,
|
|
||||||
basepath=basepath,
|
|
||||||
object=obj,
|
|
||||||
interface=interface,
|
|
||||||
objects=ctx.objects)
|
|
||||||
|
|
||||||
if wrote and ctx.verbose:
|
|
||||||
print(f"Writing {outfile}")
|
|
||||||
|
|
||||||
else:
|
|
||||||
outfile = join(outdir, template_name)
|
|
||||||
wrote = generate_template(
|
|
||||||
template, outfile,
|
|
||||||
filename=basename(template_name),
|
|
||||||
interface=interface,
|
|
||||||
objects=ctx.objects)
|
|
||||||
|
|
||||||
if wrote and ctx.verbose:
|
|
||||||
print(f"Writing {outfile}")
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,12 +1,13 @@
|
|||||||
from .parser import Transformer, v_args
|
from .parser import Transformer, v_args
|
||||||
|
|
||||||
def get_opts(args):
|
def get_opts(args):
|
||||||
from .types import CName, Description, Options, Type, UID
|
from .types import Caps, CName, Description, Options, Type, UID
|
||||||
|
|
||||||
kinds = {
|
kinds = {
|
||||||
Description: "desc",
|
Description: "desc",
|
||||||
Options: "opts",
|
Options: "opts",
|
||||||
CName: "cname",
|
CName: "cname",
|
||||||
|
Caps: "caps",
|
||||||
UID: "uid",
|
UID: "uid",
|
||||||
Type: "typename",
|
Type: "typename",
|
||||||
}
|
}
|
||||||
@@ -112,6 +113,10 @@ class DefTransformer(Transformer):
|
|||||||
from .types import Options
|
from .types import Options
|
||||||
return Options([str(s) for s in args])
|
return Options([str(s) for s in args])
|
||||||
|
|
||||||
|
def capabilities(self, args):
|
||||||
|
from .types import Caps
|
||||||
|
return Caps([str(s) for s in args])
|
||||||
|
|
||||||
def description(self, s):
|
def description(self, s):
|
||||||
from .types import Description
|
from .types import Description
|
||||||
return Description("\n".join(s))
|
return Description("\n".join(s))
|
||||||
@@ -140,6 +145,9 @@ class DefTransformer(Transformer):
|
|||||||
def COMMENT(self, s):
|
def COMMENT(self, s):
|
||||||
return s[2:].strip()
|
return s[2:].strip()
|
||||||
|
|
||||||
|
def OPTION(self, s):
|
||||||
|
return str(s)
|
||||||
|
|
||||||
def IDENTIFIER(self, s):
|
def IDENTIFIER(self, s):
|
||||||
return str(s)
|
return str(s)
|
||||||
|
|
||||||
|
|||||||
@@ -5,16 +5,13 @@ def _indent(x):
|
|||||||
class CName(str): pass
|
class CName(str): pass
|
||||||
class Description(str): pass
|
class Description(str): pass
|
||||||
class Import(str): pass
|
class Import(str): pass
|
||||||
|
class Caps(list): pass
|
||||||
|
|
||||||
class Options(dict):
|
class Options(dict):
|
||||||
def __init__(self, opts = tuple()):
|
def __init__(self, opts = tuple()):
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
parts = opt.split(":", 1)
|
parts = opt.split(":", 1)
|
||||||
self[parts[0]] = "".join(parts[1:])
|
self[parts[0]] = self.get(parts[0], []) + ["".join(parts[1:])]
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if not self: return ""
|
|
||||||
return "[{}]".format(" ".join(self.keys()))
|
|
||||||
|
|
||||||
class UID(int):
|
class UID(int):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ class Param:
|
|||||||
self.options = opts
|
self.options = opts
|
||||||
self.desc = desc
|
self.desc = desc
|
||||||
|
|
||||||
|
self.caps = set()
|
||||||
|
for key, values in opts.items():
|
||||||
|
if key == "cap":
|
||||||
|
self.caps.update(values)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "param {} {} {} {}".format(
|
return "param {} {} {} {}".format(
|
||||||
self.name, repr(self.type), self.options, self.desc or "")
|
self.name, repr(self.type), self.options, self.desc or "")
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from . import _indent
|
from . import _indent
|
||||||
from . import Options
|
from . import Caps, Options
|
||||||
|
|
||||||
class Object:
|
class Object:
|
||||||
def __init__(self, name, uid, typename=None, opts=Options(), desc="", children=tuple(), cname=None):
|
def __init__(self, name, uid, typename=None, opts=Options(), caps=Caps(), desc="", children=tuple(), cname=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.uid = uid
|
self.uid = uid
|
||||||
self.options = opts
|
self.options = opts
|
||||||
@@ -11,6 +11,8 @@ class Object:
|
|||||||
self.methods = children
|
self.methods = children
|
||||||
self.cname = cname or name
|
self.cname = cname or name
|
||||||
|
|
||||||
|
self.caps = set(caps)
|
||||||
|
|
||||||
from . import ObjectRef
|
from . import ObjectRef
|
||||||
self.__ref = ObjectRef(name)
|
self.__ref = ObjectRef(name)
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ kernel = module("kernel",
|
|||||||
"syscalls.inc.cog",
|
"syscalls.inc.cog",
|
||||||
"syscalls/channel.cpp",
|
"syscalls/channel.cpp",
|
||||||
"syscalls/endpoint.cpp",
|
"syscalls/endpoint.cpp",
|
||||||
|
"syscalls/handle.cpp",
|
||||||
"syscalls/object.cpp",
|
"syscalls/object.cpp",
|
||||||
"syscalls/process.cpp",
|
"syscalls/process.cpp",
|
||||||
"syscalls/system.cpp",
|
"syscalls/system.cpp",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
/// \file channel.h
|
/// \file channel.h
|
||||||
/// Definition of channel objects and related functions
|
/// Definition of channel objects and related functions
|
||||||
|
|
||||||
|
#include <j6/caps.h>
|
||||||
#include <j6/signals.h>
|
#include <j6/signals.h>
|
||||||
#include <util/bip_buffer.h>
|
#include <util/bip_buffer.h>
|
||||||
#include <util/counted.h>
|
#include <util/counted.h>
|
||||||
@@ -17,7 +18,7 @@ class channel :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Capabilities on a newly constructed channel handle
|
/// Capabilities on a newly constructed channel handle
|
||||||
constexpr static j6_cap_t creation_caps = 0;
|
constexpr static j6_cap_t creation_caps = j6_cap_channel_all;
|
||||||
|
|
||||||
channel();
|
channel();
|
||||||
virtual ~channel();
|
virtual ~channel();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
/// \file endpoint.h
|
/// \file endpoint.h
|
||||||
/// Definition of endpoint kobject types
|
/// Definition of endpoint kobject types
|
||||||
|
|
||||||
|
#include <j6/caps.h>
|
||||||
#include <j6/signals.h>
|
#include <j6/signals.h>
|
||||||
#include <util/spinlock.h>
|
#include <util/spinlock.h>
|
||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
@@ -16,7 +17,7 @@ class endpoint :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Capabilities on a newly constructed endpoint handle
|
/// Capabilities on a newly constructed endpoint handle
|
||||||
constexpr static j6_cap_t creation_caps = 0;
|
constexpr static j6_cap_t creation_caps = j6_cap_endpoint_all;
|
||||||
|
|
||||||
endpoint();
|
endpoint();
|
||||||
virtual ~endpoint();
|
virtual ~endpoint();
|
||||||
|
|||||||
@@ -9,34 +9,40 @@ namespace obj {
|
|||||||
|
|
||||||
struct handle
|
struct handle
|
||||||
{
|
{
|
||||||
inline handle(j6_handle_t in_id, kobject *in_object, j6_cap_t in_caps) :
|
// A j6_handle_t is an id in the low 32 bits, caps in bits 32-55, and type in 56-63
|
||||||
id {in_id}, object {in_object}, caps {in_caps} {
|
static inline j6_handle_t make_id(j6_handle_t id, j6_cap_t caps, kobject *obj) {
|
||||||
|
return (id & 0xffffffffull) |
|
||||||
|
static_cast<j6_handle_t>(caps) << 32 |
|
||||||
|
static_cast<j6_handle_t>(obj ? obj->get_type() : kobject::type::none) << 56;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline handle(j6_handle_t in_id, kobject *in_obj, j6_cap_t caps) :
|
||||||
|
id {make_id(in_id, caps, in_obj)}, object {in_obj} {
|
||||||
if (object) object->handle_retain();
|
if (object) object->handle_retain();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline handle(const handle &other) :
|
inline handle(const handle &other) :
|
||||||
id {other.id}, object {other.object}, caps {other.caps} {
|
id {other.id}, object {other.object} {
|
||||||
if (object) object->handle_retain();
|
if (object) object->handle_retain();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline handle(handle &&other) :
|
inline handle(handle &&other) :
|
||||||
id {other.id}, object {other.object}, caps {other.caps} {
|
id {other.id}, object {other.object} {
|
||||||
other.id = 0;
|
other.id = 0;
|
||||||
other.caps = 0;
|
|
||||||
other.object = nullptr;
|
other.object = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline handle & operator=(const handle &other) {
|
inline handle & operator=(const handle &other) {
|
||||||
if (object) object->handle_release();
|
if (object) object->handle_release();
|
||||||
id = other.id; caps = other.caps; object = other.object;
|
id = other.id; object = other.object;
|
||||||
if (object) object->handle_retain();
|
if (object) object->handle_retain();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline handle & operator=(handle &&other) {
|
inline handle & operator=(handle &&other) {
|
||||||
if (object) object->handle_release();
|
if (object) object->handle_release();
|
||||||
id = other.id; caps = other.caps; object = other.object;
|
id = other.id; object = other.object;
|
||||||
other.id = other.caps = 0; other.object = nullptr;
|
other.id = 0; other.object = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,12 +50,14 @@ struct handle
|
|||||||
if (object) object->handle_release();
|
if (object) object->handle_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline j6_cap_t caps() const { return id >> 32; }
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline kobject::type type() const {
|
inline kobject::type type() const {
|
||||||
return object->get_type();
|
return static_cast<kobject::type>(id >> 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int compare(const handle &o) {
|
inline int compare(const handle &o) {
|
||||||
@@ -75,7 +83,6 @@ struct handle
|
|||||||
inline const kobject * as<kobject>() const { return object; }
|
inline const kobject * as<kobject>() const { return object; }
|
||||||
|
|
||||||
j6_handle_t id;
|
j6_handle_t id;
|
||||||
j6_cap_t caps;
|
|
||||||
kobject *object;
|
kobject *object;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class kobject
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Types of kernel objects.
|
/// Types of kernel objects.
|
||||||
enum class type : uint16_t
|
enum class type : uint8_t
|
||||||
{
|
{
|
||||||
#define OBJECT_TYPE( name, val ) name = val,
|
#define OBJECT_TYPE( name, val ) name = val,
|
||||||
#include <j6/tables/object_types.inc>
|
#include <j6/tables/object_types.inc>
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ process::process() :
|
|||||||
m_next_handle {1},
|
m_next_handle {1},
|
||||||
m_state {state::running}
|
m_state {state::running}
|
||||||
{
|
{
|
||||||
j6_handle_t self = add_handle(this, process::self_caps);
|
m_self_handle = add_handle(this, process::self_caps);
|
||||||
kassert(self == self_handle(), "Process self-handle is not 1");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The "kernel process"-only constructor
|
// The "kernel process"-only constructor
|
||||||
@@ -129,9 +128,10 @@ process::add_handle(kobject *obj, j6_cap_t caps)
|
|||||||
if (!obj)
|
if (!obj)
|
||||||
return j6_handle_invalid;
|
return j6_handle_invalid;
|
||||||
|
|
||||||
j6_handle_t id = m_next_handle++;
|
handle h {m_next_handle++, obj, caps};
|
||||||
m_handles.insert(id, {id, obj, caps});
|
j6_handle_t id = h.id;
|
||||||
|
|
||||||
|
m_handles.insert(id, h);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,4 +147,16 @@ process::lookup_handle(j6_handle_t id)
|
|||||||
return m_handles.find(id);
|
return m_handles.find(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
process::list_handles(j6_handle_t *handles, size_t len)
|
||||||
|
{
|
||||||
|
for (const auto &i : m_handles) {
|
||||||
|
if (len-- == 0)
|
||||||
|
break;
|
||||||
|
*handles++ = i.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_handles.count();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace obj
|
} // namespace obj
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
/// \file process.h
|
/// \file process.h
|
||||||
/// Definition of process kobject types
|
/// Definition of process kobject types
|
||||||
|
|
||||||
|
#include <j6/caps.h>
|
||||||
#include <util/map.h>
|
#include <util/map.h>
|
||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
|
|
||||||
@@ -17,10 +18,10 @@ class process :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Capabilities on a newly constructed process handle
|
/// Capabilities on a newly constructed process handle
|
||||||
constexpr static j6_cap_t creation_caps = 0;
|
constexpr static j6_cap_t creation_caps = j6_cap_process_all;
|
||||||
|
|
||||||
/// Capabilities on a process to itself
|
/// Capabilities on a process to itself
|
||||||
constexpr static j6_cap_t self_caps = 0;
|
constexpr static j6_cap_t self_caps = j6_cap_process_all;
|
||||||
|
|
||||||
/// Top of memory area where thread stacks are allocated
|
/// Top of memory area where thread stacks are allocated
|
||||||
constexpr static uintptr_t stacks_top = 0x0000800000000000;
|
constexpr static uintptr_t stacks_top = 0x0000800000000000;
|
||||||
@@ -74,13 +75,19 @@ public:
|
|||||||
/// \returns Pointer to the handle struct, or null if not found
|
/// \returns Pointer to the handle struct, or null if not found
|
||||||
handle * lookup_handle(j6_handle_t handle);
|
handle * lookup_handle(j6_handle_t handle);
|
||||||
|
|
||||||
|
/// Get the list of handle ids this process owns
|
||||||
|
/// \arg handles Pointer to an array of handles to copy into
|
||||||
|
/// \arg len Size of the array
|
||||||
|
/// \returns Total number of handles (may be more than number copied)
|
||||||
|
size_t list_handles(j6_handle_t *handles, size_t len);
|
||||||
|
|
||||||
/// Inform the process of an exited thread
|
/// Inform the process of an exited thread
|
||||||
/// \args th The thread which has exited
|
/// \args th The thread which has exited
|
||||||
/// \returns True if this thread ending has ended the process
|
/// \returns True if this thread ending has ended the process
|
||||||
bool thread_exited(thread *th);
|
bool thread_exited(thread *th);
|
||||||
|
|
||||||
/// Get the handle for this process to refer to itself
|
/// Get the handle for this process to refer to itself
|
||||||
inline j6_handle_t self_handle() const { return 1; }
|
inline j6_handle_t self_handle() const { return m_self_handle; }
|
||||||
|
|
||||||
/// Get the process object that owns kernel threads and the
|
/// Get the process object that owns kernel threads and the
|
||||||
/// kernel address space
|
/// kernel address space
|
||||||
@@ -95,6 +102,7 @@ private:
|
|||||||
// This constructor is called by create_kernel_process
|
// This constructor is called by create_kernel_process
|
||||||
process(page_table *kpml4);
|
process(page_table *kpml4);
|
||||||
|
|
||||||
|
j6_handle_t m_self_handle;
|
||||||
int32_t m_return_code;
|
int32_t m_return_code;
|
||||||
|
|
||||||
vm_space m_space;
|
vm_space m_space;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
/// \file system.h
|
/// \file system.h
|
||||||
/// Definition of kobject type representing the system
|
/// Definition of kobject type representing the system
|
||||||
|
|
||||||
|
#include <j6/caps.h>
|
||||||
#include "objects/kobject.h"
|
#include "objects/kobject.h"
|
||||||
|
|
||||||
namespace obj {
|
namespace obj {
|
||||||
@@ -11,7 +12,7 @@ class system :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Capabilities on system given to init
|
/// Capabilities on system given to init
|
||||||
constexpr static j6_cap_t init_caps = 0;
|
constexpr static j6_cap_t init_caps = j6_cap_system_all;
|
||||||
|
|
||||||
static constexpr kobject::type type = kobject::type::system;
|
static constexpr kobject::type type = kobject::type::system;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
/// \file thread.h
|
/// \file thread.h
|
||||||
/// Definition of thread kobject types
|
/// Definition of thread kobject types
|
||||||
|
|
||||||
|
#include <j6/caps.h>
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/enum_bitfields.h>
|
||||||
#include <util/linked_list.h>
|
#include <util/linked_list.h>
|
||||||
#include <util/spinlock.h>
|
#include <util/spinlock.h>
|
||||||
@@ -60,10 +61,10 @@ class thread :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Capabilities on a newly constructed thread handle
|
/// Capabilities on a newly constructed thread handle
|
||||||
constexpr static j6_cap_t creation_caps = 0;
|
constexpr static j6_cap_t creation_caps = j6_cap_thread_all;
|
||||||
|
|
||||||
/// Capabilities the parent process gets on new thread handles
|
/// Capabilities the parent process gets on new thread handles
|
||||||
constexpr static j6_cap_t parent_caps = 0;
|
constexpr static j6_cap_t parent_caps = j6_cap_thread_all;
|
||||||
|
|
||||||
enum class state : uint8_t {
|
enum class state : uint8_t {
|
||||||
ready = 0x01,
|
ready = 0x01,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <j6/caps.h>
|
||||||
#include <j6/signals.h>
|
#include <j6/signals.h>
|
||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/enum_bitfields.h>
|
||||||
@@ -34,7 +35,7 @@ class vm_area :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Capabilities on a newly constructed vma handle
|
/// Capabilities on a newly constructed vma handle
|
||||||
constexpr static j6_cap_t creation_caps = 0;
|
constexpr static j6_cap_t creation_caps = j6_cap_vma_all;
|
||||||
|
|
||||||
static constexpr kobject::type type = kobject::type::vma;
|
static constexpr kobject::type type = kobject::type::vma;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <arch/memory.h>
|
#include <arch/memory.h>
|
||||||
|
#include <j6/caps.h>
|
||||||
#include <j6/errors.h>
|
#include <j6/errors.h>
|
||||||
#include <j6/types.h>
|
#include <j6/types.h>
|
||||||
#include <util/counted.h>
|
#include <util/counted.h>
|
||||||
@@ -36,6 +37,10 @@ using util::buffer;
|
|||||||
/*[[[cog code generation
|
/*[[[cog code generation
|
||||||
cbool = {True: "true", False: "false"}
|
cbool = {True: "true", False: "false"}
|
||||||
|
|
||||||
|
def get_caps(opts, type):
|
||||||
|
caps = opts.get("cap", list())
|
||||||
|
return [f"j6_cap_{type.name}_{c}" for c in caps]
|
||||||
|
|
||||||
for id, scope, method in syscalls.methods:
|
for id, scope, method in syscalls.methods:
|
||||||
if scope:
|
if scope:
|
||||||
name = f"{scope.name}_{method.name}"
|
name = f"{scope.name}_{method.name}"
|
||||||
@@ -58,7 +63,11 @@ for id, scope, method in syscalls.methods:
|
|||||||
argdefs.append("j6_handle_t self")
|
argdefs.append("j6_handle_t self")
|
||||||
cxxargdefs.append(f"obj::{scope.cname} *self")
|
cxxargdefs.append(f"obj::{scope.cname} *self")
|
||||||
args.append("self_obj")
|
args.append("self_obj")
|
||||||
handles.append((f"obj::{scope.cname} *", "self", "self_obj"))
|
handles.append((
|
||||||
|
f"obj::{scope.cname} *",
|
||||||
|
"self",
|
||||||
|
"self_obj",
|
||||||
|
get_caps(method.options, scope)))
|
||||||
|
|
||||||
for param in method.params:
|
for param in method.params:
|
||||||
needs_obj = param.type.needs_object(param.options)
|
needs_obj = param.type.needs_object(param.options)
|
||||||
@@ -73,7 +82,7 @@ for id, scope, method in syscalls.methods:
|
|||||||
|
|
||||||
if needs_obj:
|
if needs_obj:
|
||||||
oarg = f"{arg}_obj"
|
oarg = f"{arg}_obj"
|
||||||
handles.append((type, arg, oarg))
|
handles.append((type, arg, oarg, get_caps(param.options, param.type.object)))
|
||||||
args.append(oarg)
|
args.append(oarg)
|
||||||
else:
|
else:
|
||||||
args.append(arg)
|
args.append(arg)
|
||||||
@@ -94,12 +103,18 @@ for id, scope, method in syscalls.methods:
|
|||||||
cog.outl( " return j6_err_invalid_arg;")
|
cog.outl( " return j6_err_invalid_arg;")
|
||||||
cog.outl()
|
cog.outl()
|
||||||
|
|
||||||
for type, inarg, outarg in handles:
|
for type, inarg, outarg, caps in handles:
|
||||||
if type.endswith('*'):
|
if type.endswith('*'):
|
||||||
type = type[:-1].strip()
|
type = type[:-1].strip()
|
||||||
|
|
||||||
cog.outl(f" obj::handle *{inarg}_handle = get_handle<typename {type}>({inarg});")
|
cog.outl(f" obj::handle *{inarg}_handle = get_handle<typename {type}>({inarg});")
|
||||||
cog.outl(f" if (!{inarg}_handle) return j6_err_invalid_arg;")
|
cog.outl(f" if (!{inarg}_handle) return j6_err_invalid_arg;")
|
||||||
|
|
||||||
|
if caps:
|
||||||
|
allcaps = " | ".join(caps)
|
||||||
|
cog.outl(f" j6_cap_t {inarg}_caps_req = {allcaps};")
|
||||||
|
cog.outl(f" if (!{inarg}_handle->has_cap({inarg}_caps_req)) return j6_err_denied;")
|
||||||
|
|
||||||
cog.outl(f" {type} *{outarg} = {inarg}_handle->as<typename {type}>();")
|
cog.outl(f" {type} *{outarg} = {inarg}_handle->as<typename {type}>();")
|
||||||
cog.outl(f" if (!{outarg}) return j6_err_invalid_arg;")
|
cog.outl(f" if (!{outarg}) return j6_err_invalid_arg;")
|
||||||
cog.outl()
|
cog.outl()
|
||||||
|
|||||||
27
src/kernel/syscalls/handle.cpp
Normal file
27
src/kernel/syscalls/handle.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include <j6/errors.h>
|
||||||
|
#include <j6/types.h>
|
||||||
|
|
||||||
|
#include "objects/process.h"
|
||||||
|
|
||||||
|
using namespace obj;
|
||||||
|
|
||||||
|
namespace syscalls {
|
||||||
|
|
||||||
|
j6_status_t
|
||||||
|
handle_list(j6_handle_t *handles, size_t *handles_len)
|
||||||
|
{
|
||||||
|
if (!handles_len || (*handles_len && !handles))
|
||||||
|
return j6_err_invalid_arg;
|
||||||
|
|
||||||
|
process &p = process::current();
|
||||||
|
size_t requested = *handles_len;
|
||||||
|
|
||||||
|
*handles_len = p.list_handles(handles, requested);
|
||||||
|
|
||||||
|
if (*handles_len < requested)
|
||||||
|
return j6_err_insufficient;
|
||||||
|
|
||||||
|
return j6_status_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace syscalls
|
||||||
25
src/libraries/j6/include/j6/caps.h.cog
Normal file
25
src/libraries/j6/include/j6/caps.h.cog
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
// vim: ft=cpp
|
||||||
|
|
||||||
|
/// \file caps.h
|
||||||
|
/// Capability bitfield constants
|
||||||
|
|
||||||
|
/*[[[cog code generation
|
||||||
|
from definitions.context import Context
|
||||||
|
|
||||||
|
ctx = Context(definitions_path)
|
||||||
|
ctx.parse("syscalls.def")
|
||||||
|
syscalls = ctx.interfaces["syscalls"]
|
||||||
|
|
||||||
|
for obj in syscalls.exposes:
|
||||||
|
i = 0
|
||||||
|
for cap in obj.object.caps:
|
||||||
|
name = f"j6_cap_{obj.object.name}_{cap}"
|
||||||
|
cog.outl(f"#define {name:<30} (1 << {i})")
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
name = f"j6_cap_{obj.object.name}_all"
|
||||||
|
cog.outl(f"#define {name:<30} ((1<<{i})-1)")
|
||||||
|
cog.outl()
|
||||||
|
]]]*/
|
||||||
|
/// [[[end]]]
|
||||||
@@ -18,4 +18,5 @@
|
|||||||
#define j6_err_not_ready j6_err(0x0004)
|
#define j6_err_not_ready j6_err(0x0004)
|
||||||
#define j6_err_insufficient j6_err(0x0005)
|
#define j6_err_insufficient j6_err(0x0005)
|
||||||
#define j6_err_timed_out j6_err(0x0006)
|
#define j6_err_timed_out j6_err(0x0006)
|
||||||
|
#define j6_err_denied j6_err(0x0007)
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,16 @@ typedef uint64_t j6_tag_t;
|
|||||||
#define j6_tag_from_irq(x) ((x) | j6_tag_irq_base)
|
#define j6_tag_from_irq(x) ((x) | j6_tag_irq_base)
|
||||||
#define j6_tag_to_irq(x) ((x) & ~j6_tag_irq_base)
|
#define j6_tag_to_irq(x) ((x) & ~j6_tag_irq_base)
|
||||||
|
|
||||||
/// Handles are references and capabilities to other objects.
|
/// Handles are references and capabilities to other objects. A handle is
|
||||||
typedef uint32_t j6_handle_t;
|
/// an id in the lower 32 bits, a bitfield of capabilities in bits 32-55
|
||||||
|
/// and a type id in bits 56-63.
|
||||||
|
typedef uint64_t j6_handle_t;
|
||||||
|
|
||||||
|
/// Bitfield for storage of capabilities on their own
|
||||||
|
typedef uint32_t j6_cap_t;
|
||||||
|
|
||||||
#define j6_handle_invalid ((j6_handle_t)-1)
|
#define j6_handle_invalid ((j6_handle_t)-1)
|
||||||
|
|
||||||
/// Bitfield for storage of capabilities
|
|
||||||
typedef uint32_t j6_cap_t;
|
|
||||||
|
|
||||||
enum j6_object_type {
|
enum j6_object_type {
|
||||||
#define OBJECT_TYPE( name, val ) j6_object_type_ ## name = val,
|
#define OBJECT_TYPE( name, val ) j6_object_type_ ## name = val,
|
||||||
#include <j6/tables/object_types.inc>
|
#include <j6/tables/object_types.inc>
|
||||||
|
|||||||
@@ -3,45 +3,47 @@
|
|||||||
#ifndef __j6kernel
|
#ifndef __j6kernel
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <j6/errors.h>
|
||||||
#include <j6/init.h>
|
#include <j6/init.h>
|
||||||
|
#include <j6/syscalls.h>
|
||||||
#include <j6/types.h>
|
#include <j6/types.h>
|
||||||
|
|
||||||
static size_t __initc = 0;
|
|
||||||
static struct j6_init_value *__initv = 0;
|
|
||||||
|
|
||||||
j6_handle_t __handle_sys = j6_handle_invalid;
|
j6_handle_t __handle_sys = j6_handle_invalid;
|
||||||
j6_handle_t __handle_self = j6_handle_invalid;
|
j6_handle_t __handle_self = j6_handle_invalid;
|
||||||
|
|
||||||
extern "C" void
|
namespace {
|
||||||
_get_init(size_t *initc, struct j6_init_value **initv)
|
constexpr size_t __static_arr_size = 4;
|
||||||
{
|
j6_handle_t __handle_array[__static_arr_size];
|
||||||
if (!initc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
*initc = __initc;
|
static j6_status_t
|
||||||
if (initv)
|
__load_handles()
|
||||||
*initv = __initv;
|
{
|
||||||
}
|
size_t count = __static_arr_size;
|
||||||
|
j6_handle_t *handles = __handle_array;
|
||||||
|
j6_status_t s = j6_handle_list(handles, &count);
|
||||||
|
|
||||||
|
if (s != j6_err_insufficient && s != j6_status_ok)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
if (count > __static_arr_size)
|
||||||
|
count = __static_arr_size;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
uint8_t type = (handles[i] >> 56);
|
||||||
|
if (type == j6_object_type_system && __handle_sys == j6_handle_invalid)
|
||||||
|
__handle_sys = handles[i];
|
||||||
|
else if (type == j6_object_type_process && __handle_self == j6_handle_invalid)
|
||||||
|
__handle_self = handles[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
_init_libj6(uint64_t *rsp)
|
_init_libj6(uint64_t *rsp)
|
||||||
{
|
{
|
||||||
uint64_t argc = *rsp++;
|
__load_handles();
|
||||||
rsp += argc;
|
|
||||||
|
|
||||||
__initc = *rsp++;
|
|
||||||
__initv = (struct j6_init_value *)rsp;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < __initc; ++i) {
|
|
||||||
if (__initv[i].type == j6_init_handle_other &&
|
|
||||||
__initv[i].handle.type == j6_object_type_system) {
|
|
||||||
__handle_sys = __initv[i].handle.handle;
|
|
||||||
}
|
|
||||||
else if (__initv[i].type == j6_init_handle_self &&
|
|
||||||
__initv[i].handle.type == j6_object_type_process) {
|
|
||||||
__handle_self = __initv[i].handle.handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __j6kernel
|
#endif // __j6kernel
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ j6 = module("j6",
|
|||||||
includes = [ "include" ],
|
includes = [ "include" ],
|
||||||
sources = [
|
sources = [
|
||||||
"init.cpp",
|
"init.cpp",
|
||||||
|
"include/j6/caps.h.cog",
|
||||||
"include/j6/syscalls.h.cog",
|
"include/j6/syscalls.h.cog",
|
||||||
"include/j6/sysconf.h.cog",
|
"include/j6/sysconf.h.cog",
|
||||||
"syscalls.s.cog",
|
"syscalls.s.cog",
|
||||||
@@ -18,6 +19,7 @@ sysconf = join(source_root, "definitions/sysconf.yaml")
|
|||||||
definitions = glob('definitions/**/*.def', recursive=True)
|
definitions = glob('definitions/**/*.def', recursive=True)
|
||||||
|
|
||||||
j6.add_depends([
|
j6.add_depends([
|
||||||
|
"include/j6/caps.h.cog",
|
||||||
"include/j6/syscalls.h.cog",
|
"include/j6/syscalls.h.cog",
|
||||||
"syscalls.s.cog",
|
"syscalls.s.cog",
|
||||||
], definitions)
|
], definitions)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <j6/syscalls.h>
|
#include <j6/syscalls.h>
|
||||||
//void *sbrk(intptr_t) __attribute__ ((weak));
|
//void *sbrk(intptr_t) __attribute__ ((weak));
|
||||||
|
|
||||||
static j6_handle_t __core_handle = 0;
|
static j6_handle_t __core_handle = j6_handle_invalid;
|
||||||
static intptr_t __core_size = 0;
|
static intptr_t __core_size = 0;
|
||||||
|
|
||||||
static const uintptr_t __core_base = 0x1c0000000;
|
static const uintptr_t __core_base = 0x1c0000000;
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ extern "C" {
|
|||||||
int main(int, const char **);
|
int main(int, const char **);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr j6_handle_t handle_self = 1;
|
extern j6_handle_t __handle_self;
|
||||||
constexpr j6_handle_t handle_sys = 2;
|
extern j6_handle_t __handle_sys;
|
||||||
|
|
||||||
struct entry
|
struct entry
|
||||||
{
|
{
|
||||||
@@ -76,13 +76,13 @@ log_pump_proc()
|
|||||||
void *message_buffer = nullptr;
|
void *message_buffer = nullptr;
|
||||||
char stringbuf[300];
|
char stringbuf[300];
|
||||||
|
|
||||||
j6_status_t result = j6_system_request_iopl(handle_sys, 3);
|
j6_status_t result = j6_system_request_iopl(__handle_sys, 3);
|
||||||
if (result != j6_status_ok)
|
if (result != j6_status_ok)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
size_t size = buffer_size;
|
size_t size = buffer_size;
|
||||||
j6_status_t s = j6_system_get_log(handle_sys, message_buffer, &size);
|
j6_status_t s = j6_system_get_log(__handle_sys, message_buffer, &size);
|
||||||
|
|
||||||
if (s == j6_err_insufficient) {
|
if (s == j6_err_insufficient) {
|
||||||
free(message_buffer);
|
free(message_buffer);
|
||||||
@@ -96,7 +96,7 @@ log_pump_proc()
|
|||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
j6_signal_t sigs = 0;
|
j6_signal_t sigs = 0;
|
||||||
j6_kobject_wait(handle_sys, j6_signal_system_has_log, &sigs);
|
j6_kobject_wait(__handle_sys, j6_signal_system_has_log, &sigs);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ main(int argc, const char **argv)
|
|||||||
j6_handle_t endp = j6_handle_invalid;
|
j6_handle_t endp = j6_handle_invalid;
|
||||||
j6_status_t result = j6_status_ok;
|
j6_status_t result = j6_status_ok;
|
||||||
|
|
||||||
result = j6_system_request_iopl(handle_sys, 3);
|
result = j6_system_request_iopl(__handle_sys, 3);
|
||||||
if (result != j6_status_ok)
|
if (result != j6_status_ok)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -129,11 +129,11 @@ main(int argc, const char **argv)
|
|||||||
if (result != j6_status_ok)
|
if (result != j6_status_ok)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = j6_system_bind_irq(handle_sys, endp, 3);
|
result = j6_system_bind_irq(__handle_sys, endp, 3);
|
||||||
if (result != j6_status_ok)
|
if (result != j6_status_ok)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = j6_system_bind_irq(handle_sys, endp, 4);
|
result = j6_system_bind_irq(__handle_sys, endp, 4);
|
||||||
if (result != j6_status_ok)
|
if (result != j6_status_ok)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ main(int argc, const char **argv)
|
|||||||
sp[0] = sp[1] = 0;
|
sp[0] = sp[1] = 0;
|
||||||
|
|
||||||
j6_handle_t child = j6_handle_invalid;
|
j6_handle_t child = j6_handle_invalid;
|
||||||
result = j6_thread_create(&child, handle_self, stack_top - 0x10, reinterpret_cast<uintptr_t>(&log_pump_proc));
|
result = j6_thread_create(&child, __handle_self, stack_top - 0x10, reinterpret_cast<uintptr_t>(&log_pump_proc));
|
||||||
if (result != j6_status_ok)
|
if (result != j6_status_ok)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ main(int argc, const char **argv)
|
|||||||
|
|
||||||
size_t initc = 0;
|
size_t initc = 0;
|
||||||
j6_init_value *initv = nullptr;
|
j6_init_value *initv = nullptr;
|
||||||
_get_init(&initc, &initv);
|
|
||||||
|
|
||||||
j6_init_framebuffer *fb = nullptr;
|
j6_init_framebuffer *fb = nullptr;
|
||||||
for (unsigned i = 0; i < initc; ++i) {
|
for (unsigned i = 0; i < initc; ++i) {
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
using bootproto::module_flags;
|
using bootproto::module_flags;
|
||||||
using bootproto::module_program;
|
using bootproto::module_program;
|
||||||
|
|
||||||
extern j6_handle_t handle_self;
|
extern j6_handle_t __handle_self;
|
||||||
extern j6_handle_t handle_system;
|
extern j6_handle_t __handle_sys;
|
||||||
|
|
||||||
constexpr uintptr_t load_addr_base = 0xf8000000;
|
constexpr uintptr_t load_addr_base = 0xf8000000;
|
||||||
constexpr size_t stack_size = 0x10000;
|
constexpr size_t stack_size = 0x10000;
|
||||||
@@ -28,13 +28,13 @@ load_program(const module_program &prog, char *err_msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
j6_handle_t elf_vma = j6_handle_invalid;
|
j6_handle_t elf_vma = j6_handle_invalid;
|
||||||
j6_status_t res = j6_system_map_phys(handle_system, &elf_vma, prog.base_address, prog.size, 0);
|
j6_status_t res = j6_system_map_phys(__handle_sys, &elf_vma, prog.base_address, prog.size, 0);
|
||||||
if (res != j6_status_ok) {
|
if (res != j6_status_ok) {
|
||||||
sprintf(err_msg, " ** error loading program '%s': creating physical vma: %lx", prog.filename, res);
|
sprintf(err_msg, " ** error loading program '%s': creating physical vma: %lx", prog.filename, res);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = j6_vma_map(elf_vma, handle_self, prog.base_address);
|
res = j6_vma_map(elf_vma, __handle_self, prog.base_address);
|
||||||
if (res != j6_status_ok) {
|
if (res != j6_status_ok) {
|
||||||
sprintf(err_msg, " ** error loading program '%s': mapping vma: %lx", prog.filename, res);
|
sprintf(err_msg, " ** error loading program '%s': mapping vma: %lx", prog.filename, res);
|
||||||
return false;
|
return false;
|
||||||
@@ -55,7 +55,7 @@ load_program(const module_program &prog, char *err_msg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = j6_process_give_handle(proc, handle_system, nullptr);
|
res = j6_process_give_handle(proc, __handle_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;
|
||||||
@@ -90,7 +90,7 @@ load_program(const module_program &prog, char *err_msg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = j6_vma_unmap(sub_vma, handle_self);
|
res = j6_vma_unmap(sub_vma, __handle_self);
|
||||||
if (res != j6_status_ok) {
|
if (res != j6_status_ok) {
|
||||||
sprintf(err_msg, " ** error loading program '%s': unmapping sub vma: %lx", prog.filename, res);
|
sprintf(err_msg, " ** error loading program '%s': unmapping sub vma: %lx", prog.filename, res);
|
||||||
return false;
|
return false;
|
||||||
@@ -115,7 +115,7 @@ load_program(const module_program &prog, char *err_msg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = j6_vma_unmap(stack_vma, handle_self);
|
res = j6_vma_unmap(stack_vma, __handle_self);
|
||||||
if (res != j6_status_ok) {
|
if (res != j6_status_ok) {
|
||||||
sprintf(err_msg, " ** error loading program '%s': unmapping stack vma: %lx", prog.filename, res);
|
sprintf(err_msg, " ** error loading program '%s': unmapping stack vma: %lx", prog.filename, res);
|
||||||
return false;
|
return false;
|
||||||
@@ -128,7 +128,7 @@ load_program(const module_program &prog, char *err_msg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = j6_vma_unmap(elf_vma, handle_self);
|
res = j6_vma_unmap(elf_vma, __handle_self);
|
||||||
if (res != j6_status_ok) {
|
if (res != j6_status_ok) {
|
||||||
sprintf(err_msg, " ** error loading program '%s': unmapping elf vma: %lx", prog.filename, res);
|
sprintf(err_msg, " ** error loading program '%s': unmapping elf vma: %lx", prog.filename, res);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <j6/errors.h>
|
||||||
#include <j6/syscalls.h>
|
#include <j6/syscalls.h>
|
||||||
|
#include <j6/types.h>
|
||||||
#include <bootproto/init.h>
|
#include <bootproto/init.h>
|
||||||
|
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
@@ -16,15 +19,15 @@ extern "C" {
|
|||||||
|
|
||||||
uintptr_t _arg_modules_phys; // This gets filled in in _start
|
uintptr_t _arg_modules_phys; // This gets filled in in _start
|
||||||
|
|
||||||
j6_handle_t handle_self = 1; // Self program handle is always 1
|
extern j6_handle_t __handle_self;
|
||||||
j6_handle_t handle_system = 2; // boot protocol is that init gets the system as handle 2
|
extern j6_handle_t __handle_sys;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char **argv)
|
main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
j6_log("srv.init starting");
|
j6_log("srv.init starting");
|
||||||
|
|
||||||
modules mods = modules::load_modules(_arg_modules_phys, handle_system, handle_self);
|
modules mods = modules::load_modules(_arg_modules_phys, __handle_sys, __handle_self);
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user