mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-22 04:52:56 +01:00
Compare commits
222 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93845e1de5 | ||
|
|
5518b5f5f2 | ||
|
|
08d08716c2 | ||
|
|
74030a2e38 | ||
|
|
468ebebbda | ||
|
|
ee804a84fa | ||
|
|
b80428abf6 | ||
|
|
c48e13e1c0 | ||
|
|
46a7b2ea66 | ||
|
|
16adc852a5 | ||
|
|
1e4672db4a | ||
|
|
783da4ee1d | ||
|
|
97a41394b4 | ||
|
|
3e6308e83b | ||
|
|
957fe694c5 | ||
|
|
92a10541aa | ||
|
|
357b84835a | ||
|
|
1208d14681 | ||
|
|
722fd85bc1 | ||
|
|
608df38402 | ||
|
|
6b94e761f8 | ||
|
|
66b7a01d58 | ||
|
|
57f47db823 | ||
|
|
38c5abbaad | ||
|
|
ee7f965061 | ||
|
|
db20e1d87b | ||
|
|
6b0022f032 | ||
|
|
b9b8114a4e | ||
|
|
e1c451f19a | ||
|
|
5424628ebd | ||
|
|
63e6dc05cd | ||
|
|
369ff2a001 | ||
|
|
bcefc874d6 | ||
|
|
b9e7fb1edf | ||
|
|
0106045bad | ||
|
|
ee05fb9259 | ||
|
|
47990f37d7 | ||
|
|
44648bb5c7 | ||
|
|
2a92f4bf55 | ||
|
|
b65a50ed25 | ||
|
|
111d74744d | ||
|
|
638db70b94 | ||
|
|
ff76e69542 | ||
|
|
5842b2065e | ||
|
|
2cde1d36c1 | ||
|
|
30e57d4581 | ||
|
|
807be83b1b | ||
|
|
15141f3ca7 | ||
|
|
ef9a7d2230 | ||
|
|
a99989af40 | ||
|
|
59aec6114b | ||
|
|
3ba61a2ddf | ||
|
|
bb3e9300f6 | ||
|
|
69e9929f71 | ||
|
|
61572263d7 | ||
|
|
0fae8fe9c3 | ||
|
|
a7b3072cc2 | ||
|
|
3361651e9e | ||
|
|
f19b269360 | ||
|
|
8da737acfd | ||
|
|
e0c0794f33 | ||
|
|
8d797105b3 | ||
|
|
16914bddc8 | ||
|
|
cb232891bf | ||
|
|
dccad4c526 | ||
|
|
77c4510787 | ||
|
|
0ac1d1774d | ||
|
|
ea726a1f48 | ||
|
|
f81867f208 | ||
|
|
27a73b89f0 | ||
|
|
bed870ead4 | ||
|
|
abed38e8ac | ||
|
|
3df03fbc41 | ||
|
|
f6dec901bb | ||
|
|
1e95af5bab | ||
|
|
ab88599682 | ||
|
|
fd401bdf53 | ||
|
|
7b73d1d823 | ||
|
|
1f395ae780 | ||
|
|
3bceefc9cf | ||
|
|
dc8690ae37 | ||
|
|
40a5af42eb | ||
|
|
52cc50174f | ||
|
|
b38c5006d8 | ||
|
|
b8cd56cb90 | ||
|
|
ba0545de07 | ||
|
|
4f69772ecc | ||
|
|
7274ca997d | ||
|
|
b49e588c1c | ||
|
|
2bc8a0f76a | ||
|
|
73b463cdbb | ||
|
|
861508ad68 | ||
|
|
549f77eafe | ||
|
|
4aafa882d8 | ||
|
|
d891016632 | ||
|
|
511acad507 | ||
|
|
e20bbe7002 | ||
|
|
93b82c14ac | ||
|
|
19b3824bfb | ||
|
|
7c1235ff34 | ||
|
|
1fc707d9dc | ||
|
|
3195311b53 | ||
|
|
2dfbfd7173 | ||
|
|
133c46a784 | ||
|
|
463b39fc73 | ||
|
|
ab9fe9cc6c | ||
|
|
1ba1980727 | ||
|
|
ccd50cc9f5 | ||
|
|
da0c467518 | ||
|
|
cd420b05ec | ||
|
|
f5f8011d02 | ||
|
|
9cd26c4d61 | ||
|
|
dd90cb3bfe | ||
|
|
ff4033c6b0 | ||
|
|
cba6f5f298 | ||
|
|
bf5df7d88d | ||
|
|
43cf789371 | ||
|
|
642ce6ca77 | ||
|
|
579f4d4991 | ||
|
|
7a64e0bb80 | ||
|
|
4ef2b0ed2e | ||
|
|
9508f397a2 | ||
|
|
d5d891a227 | ||
|
|
a96130f20b | ||
|
|
cdf57b60f9 | ||
|
|
df272c90ec | ||
|
|
e6061a794f | ||
|
|
5b12034531 | ||
|
|
05e09a6116 | ||
|
|
0709340788 | ||
|
|
f186587cab | ||
|
|
0c299c5e08 | ||
|
|
e9dec93f4b | ||
|
|
fbc35cb796 | ||
|
|
db5969e6cc | ||
|
|
7cf40a0971 | ||
|
|
ed37c2ecff | ||
|
|
329ab80d1d | ||
|
|
8971bb25ce | ||
|
|
357dbdd64b | ||
|
|
1d301e9c14 | ||
|
|
b8e52189d5 | ||
|
|
14ca140135 | ||
|
|
4a58154e07 | ||
|
|
d1dc5a9071 | ||
|
|
e22cd98a4f | ||
|
|
cb952d2087 | ||
|
|
58632ab8b5 | ||
|
|
82a7799638 | ||
|
|
98b9a24357 | ||
|
|
3e1fa54c61 | ||
|
|
036f3b5702 | ||
|
|
338cfe5a94 | ||
|
|
063a603948 | ||
|
|
44fe44e8b6 | ||
|
|
b07be42e9f | ||
|
|
14f1ac497e | ||
|
|
051e84c4b4 | ||
|
|
4ac7127f89 | ||
|
|
b6afee344f | ||
|
|
17401d6a63 | ||
|
|
a0d08d4bd1 | ||
|
|
f153bc9a74 | ||
|
|
0cacd41823 | ||
|
|
02f84f98c3 | ||
|
|
1f719dee26 | ||
|
|
146c694513 | ||
|
|
a1239c5e9d | ||
|
|
febb0cc13d | ||
|
|
07e10a04f9 | ||
|
|
d32b5a54b6 | ||
|
|
cda07b7da0 | ||
|
|
47878bd3e1 | ||
|
|
4cdfb9bc2f | ||
|
|
da5d182ad3 | ||
|
|
dc0ebba1ec | ||
|
|
84bfb4c04c | ||
|
|
da16ecc002 | ||
|
|
bc058e698a | ||
|
|
5085ad36c3 | ||
|
|
eb4c6c0456 | ||
|
|
c53bbfa83c | ||
|
|
9b0eb720b0 | ||
|
|
28117fee12 | ||
|
|
611a73be36 | ||
|
|
4a0b63431f | ||
|
|
cf6f3f46f8 | ||
|
|
9a3185f8ed | ||
|
|
76db3b9c06 | ||
|
|
2490e399dc | ||
|
|
f46a504bb6 | ||
|
|
110d71c2a8 | ||
|
|
723d9e7784 | ||
|
|
23c1d4c66d | ||
|
|
d0735b1734 | ||
|
|
688e86ab68 | ||
|
|
7f73e5e879 | ||
|
|
3c686fc9c6 | ||
|
|
8132a16137 | ||
|
|
6773d631b9 | ||
|
|
1a19ca5f7b | ||
|
|
3473955212 | ||
|
|
6e7f7bdad4 | ||
|
|
2e701f9afa | ||
|
|
6de763cb0b | ||
|
|
e6729316ff | ||
|
|
be496c6dc1 | ||
|
|
62b1c55399 | ||
|
|
b1910cdd54 | ||
|
|
705ac74498 | ||
|
|
5d559a0699 | ||
|
|
079484c5d0 | ||
|
|
0d6dc46bbb | ||
|
|
958bf4d903 | ||
|
|
ff10687a6c | ||
|
|
992a5ec1ae | ||
|
|
b039608e95 | ||
|
|
74342ca2fc | ||
|
|
b9263a7f4e | ||
|
|
c17069b35e | ||
|
|
b4c49a4bf0 | ||
|
|
37459d833b |
4
README
4
README
@@ -10,7 +10,7 @@ the project's official website:
|
||||
|
||||
:Official project website for the Genode OS Framework:
|
||||
|
||||
[http://genode.org/documentation/general-overview]
|
||||
[https://genode.org/documentation/general-overview]
|
||||
|
||||
The current implementation can be compiled for 8 different kernels: Linux,
|
||||
L4ka::Pistachio, L4/Fiasco, OKL4, NOVA, Fiasco.OC, seL4, and a custom
|
||||
@@ -70,5 +70,5 @@ mailing list. Please feel welcome to join in!
|
||||
|
||||
:Genode Mailing Lists:
|
||||
|
||||
[http://genode.org/community/mailing-lists]
|
||||
[https://genode.org/community/mailing-lists]
|
||||
|
||||
|
||||
@@ -1,789 +0,0 @@
|
||||
|
||||
====================================
|
||||
Design of the Genode OS Architecture
|
||||
====================================
|
||||
|
||||
|
||||
Norman Feske and Christian Helmuth
|
||||
|
||||
Abstract
|
||||
########
|
||||
|
||||
In the software world, high complexity of a problem solution comes along with a
|
||||
high risk for bugs and vulnerabilities.
|
||||
This correlation is particularly perturbing for todays commodity operating
|
||||
systems with their tremendous complexity.
|
||||
The numerous approaches to increase the user's confidence in the correct
|
||||
functioning of software comprise exhaustive tests, code auditing, static code
|
||||
analysis, and formal verification.
|
||||
Such quality-assurance measures are either rather shallow or they scale badly
|
||||
with increasing complexity.
|
||||
|
||||
The operating-system design presented in this document focuses on the root of the
|
||||
problem by providing means to minimize the underlying system complexity for
|
||||
each security-sensitive application individually.
|
||||
On the other hand, we want to enable multiple applications to execute on the
|
||||
system at the same time whereas each application may have different functional
|
||||
requirements from the operating system.
|
||||
Todays operating systems provide a functional superset of the requirements of
|
||||
all applications and thus, violate the principle of minimalism for each single
|
||||
application.
|
||||
We resolve the conflict between the principle of minimalism and the versatility
|
||||
of the operating system by decomposing the operating system into small
|
||||
components and by providing a way to execute those components isolated and
|
||||
independent from each other.
|
||||
Components can be device drivers, protocol stacks such as file systems and
|
||||
network stacks, native applications, and containers for executing legacy
|
||||
software.
|
||||
Each application depends only on the functionality of a bounded set of
|
||||
components that we call _application-specific_trusted_computing_base_(TCB)_.
|
||||
If the TCBs of two applications are executed completely _isolated_ and
|
||||
_independent_ from each other, we consider both TCBs as minimal.
|
||||
|
||||
In practice however, we want to share physical resources between multiple applications
|
||||
without sacrificing their independence.
|
||||
Therefore, the operating-system design has to enable the assignment of physical
|
||||
resources to each application and its TCB to maintain independence from other
|
||||
applications.
|
||||
Furthermore, rather than living in complete isolation, components require to
|
||||
communicate with each other to cooperate.
|
||||
The operating-system design must enable components to create other components
|
||||
and get them to know each other while maintaining isolation from uninvolved
|
||||
parts of the system.
|
||||
|
||||
First, we narrow our goals and pose our mayor challenges in Section [Goals and Challenges].
|
||||
Section [Interfaces and Mechanisms] introduces our fundamental concepts and
|
||||
protocols that apply to each component in the system.
|
||||
In Section [Core - the root of the process tree], we present the one component
|
||||
that is mandatory part of each TCB, enables the bootstrapping of the system,
|
||||
and provides abstractions for the lowest-level resources.
|
||||
We exercise the composition of the presented mechanisms by the means of process
|
||||
creation in Section [Process creation].
|
||||
;Section [Framework infrastructure]
|
||||
|
||||
|
||||
Goals and Challenges
|
||||
####################
|
||||
|
||||
The Genode architecture is designed to accommodate the following types
|
||||
of components in a secure manner concurrently on one machine:
|
||||
|
||||
:Device drivers:
|
||||
|
||||
Device drivers translate the facilities of raw physical devices to
|
||||
device-class-specific interfaces to be used by other components.
|
||||
They contain no security policies and provide their services
|
||||
to only one client component per device.
|
||||
|
||||
:Services that multiplex resources:
|
||||
|
||||
To make one physical resource (e.g., a device) usable by multiple
|
||||
components at the same time, the physical resource must be translated
|
||||
to multiple virtual resources. For example, a
|
||||
frame buffer provided by a device driver can only be used by one
|
||||
client at the same time. A window system multiplexes this physical
|
||||
resource to make it available to multiple clients. Other examples
|
||||
are an audio mixer or a virtual network hub.
|
||||
In contrast to a device driver, a _resource multiplexer_ deals with multiple
|
||||
clients and therefore, plays a crucial role for maintaining the independence
|
||||
and isolation of its clients from each other.
|
||||
|
||||
:Protocol stacks:
|
||||
|
||||
Protocol stacks translate low-level protocols to a higher and more applicable
|
||||
level.
|
||||
For example, a file system translates a block-device protocol to a file
|
||||
abstraction, a TCP/IP stack translates network packets to a socket
|
||||
abstraction, or a widget set maps high-level GUI elements to pixels.
|
||||
Compared to resource multiplexers, protocol stacks are typically an
|
||||
order of magnitude more complex.
|
||||
Protocol stacks may also act as resource multiplexers. In this case however,
|
||||
high complexity puts the independence and isolation of multiple
|
||||
clients at a high risk.
|
||||
Therefore, our design should enable the instantiation of protocol stacks per
|
||||
application.
|
||||
For example, instead of letting a security-sensitive application share one
|
||||
TCP/IP stack with multiple other (untrusted) applications, it could use a
|
||||
dedicated instance of a TCP/IP stack to increase its independence and
|
||||
isolation from the other applications.
|
||||
|
||||
:Containers for executing legacy software:
|
||||
|
||||
A _legacy container_ provides an environment for the execution of existing
|
||||
legacy software. This can be achieved by the means of a virtual machine
|
||||
(e.g., a Java VM, a virtual PC), a compatible programming API (e.g., POSIX,
|
||||
Qt), a language environment (e.g., LISP), or a script interpreter.
|
||||
In the majority of cases, we regard legacy software as an untrusted black box.
|
||||
One particular example for legacy software are untrusted legacy device drivers.
|
||||
In this case, the container has to protect the physical hardware from
|
||||
potentially malicious device accesses by the untrusted driver.
|
||||
Legacy software may be extremely complex and resource demanding, for example
|
||||
the Firefox web browser executed on top of the X window system and the Linux
|
||||
kernel inside a virtualized PC.
|
||||
In this case, the legacy container may locally implement sophisticated
|
||||
resource-management techniques such as virtual memory.
|
||||
|
||||
:Small custom security-sensitive applications:
|
||||
|
||||
Alongside legacy software, small custom applications implement crucial
|
||||
security-sensitive functionality.
|
||||
In contrast to legacy software, which we mostly regard as untrusted anyway,
|
||||
a low TCB complexity for custom applications is of extreme importance.
|
||||
Given the special liability of such an application, it is very carefully
|
||||
designed to have low complexity and require as little infrastructure as
|
||||
possible.
|
||||
A typical example is a cryptographic component that protects credentials
|
||||
of the user.
|
||||
Such an application does not require swapping (virtual memory), a POSIX API,
|
||||
or a complete C library.
|
||||
Instead, the main objectives of such an application are to avoid as much as
|
||||
possible code from being included in its TCB and to keep its requirements at
|
||||
a minimum.
|
||||
|
||||
Our design must be able to create and destroy subsystems that are composed of
|
||||
multiple such components.
|
||||
The _isolation_ requirement as stated in the introduction raises the
|
||||
question of how to organize the locality of name spaces and how to distribute
|
||||
access from components to other components within the system.
|
||||
The _independence_ requirement demands the assignment of physical resources
|
||||
to components such that different applications do not interfere.
|
||||
Instead of managing access control and physical resources from a central
|
||||
place, we desire a distributed way for applying policy for trading and revocating
|
||||
resources and for delegating rights.
|
||||
|
||||
|
||||
|
||||
Interfaces and Mechanisms
|
||||
#########################
|
||||
|
||||
The system is structured as a tree.
|
||||
The nodes of the tree are processes.
|
||||
A node, for which sub-nodes exist, is called the _parent_ of these sub-nodes
|
||||
(_children_).
|
||||
The parent creates children out of its own resources and defines
|
||||
their execution environment.
|
||||
Each process can announce services to its parent.
|
||||
The parent, in turn, can mediate such a service to its other children.
|
||||
When a child is created, its parent provides the initial contact to the
|
||||
outer world via the following interface:
|
||||
|
||||
! void exit(int exit_value);
|
||||
!
|
||||
! Session_capability session(String service_name,
|
||||
! String args);
|
||||
!
|
||||
! void close(Session_capability session_cap);
|
||||
!
|
||||
! int announce(String service_name,
|
||||
! Root_capability service_root_cap);
|
||||
!
|
||||
! int transfer_quota(Session_capability to_session_cap,
|
||||
! String amount);
|
||||
|
||||
|
||||
:'exit': is called by a child to request its own termination.
|
||||
|
||||
:'session': is called by a child to request a connection to the specified
|
||||
service as known by its parent whereas 'service_name' is the name
|
||||
of the desired service _interface_.
|
||||
The way of resolving or even denying a 'session' request depends on
|
||||
the policy of the parent.
|
||||
The 'args' parameter contains construction arguments for the session
|
||||
to be created.
|
||||
In particular, 'args' contains a specification of resources that the
|
||||
process is willing to donate to the server during the session lifetime.
|
||||
|
||||
:'close': is called by a child to inform its parent that the specified
|
||||
session is no longer needed.
|
||||
The parent should close the session and hand back donated
|
||||
resources to the child.
|
||||
|
||||
:'announce': is called by a child to register a locally implemented
|
||||
service at its parent. Hence, this child is a server.
|
||||
|
||||
:'transfer_quota': enables a child to extend its resource donation
|
||||
to the server that provides the specified session.
|
||||
|
||||
We provide a detailed description and motivation for the different functions
|
||||
in Sections [Servers] and [Quota].
|
||||
|
||||
Servers
|
||||
=======
|
||||
|
||||
Each process may implement services and announce them via the 'announce'
|
||||
function of the parent interface.
|
||||
When announcing a service, the server specifies a _root_ capability for
|
||||
the implemented service.
|
||||
The interface of the root capability enables the parent to create, configure,
|
||||
and close sessions of the service:
|
||||
|
||||
! Session_capability session(String args);
|
||||
!
|
||||
! int transfer_quota(Session_capability to_session_cap,
|
||||
! String amount);
|
||||
!
|
||||
! void close(Session_capability session_cap);
|
||||
|
||||
|
||||
[image announce 60%]
|
||||
Announcement of a service by a child (server).
|
||||
Colored circles at the edge of a component represent remotely accessible
|
||||
objects. Small circles inside a component represent a reference (capability)
|
||||
to a remote object. A cross-component reference to a remote object is
|
||||
illustrated by a dashed arrow. An opaque arrow symbolizes a RPC call/return.
|
||||
|
||||
Figure [announce] illustrates an announcement of a service.
|
||||
Initially, each child has a capability to its parent.
|
||||
After Child1 announces its service "Service", its parent knows the
|
||||
root capability of this service under the local name 'srv1_r' and stores
|
||||
the root capability with the announced service name in its _root_list_.
|
||||
The root capability is intended to be used and kept by the parent only.
|
||||
|
||||
[image request 60%]
|
||||
Service request by a client.
|
||||
|
||||
When a parent calls the 'session' function of the root interface of a server
|
||||
child, the server creates a new client session and returns the corresponding
|
||||
'client_session' capability.
|
||||
This session capability provides the actual service-specific interface.
|
||||
The parent can use it directly or it may pass it to other processes, in
|
||||
particular to another child that requested the session.
|
||||
In Figure [request], Child2 initiates the creation of a "Service" session
|
||||
by a 'session' call at its parent capability (1).
|
||||
The parent uses its root list to look up the root capability that matches the
|
||||
service name "Service" (2) and calls the 'session' function at the
|
||||
server (3).
|
||||
Child1 being the server creates a new session ('session1') and returns the
|
||||
session capability as result of the 'session' call (4).
|
||||
The parent now knows the new session under the local name 'srv1_s1' (5) and
|
||||
passes the session capability as return value of Child2's initial 'session'
|
||||
call (6).
|
||||
The parent maintains a _session_list_, which stores the interrelation between
|
||||
children and their created sessions.
|
||||
Now, Child2 has a direct communication channel to 'session1' provided by
|
||||
the server (Child1) (7).
|
||||
|
||||
The 'close' function of the root interface instructs the server to
|
||||
destroy the specified session and to release all session-specific resources.
|
||||
|
||||
; Mittels 'set_quota' kann der Parent einen Dienst anweisen, die Ressourcennutzung
|
||||
; für eine angegebene 'client_session' zu begrenzen. Eine nähere Beschreibung des
|
||||
; Ressourcen-Accountings erfolgt in Kapitel [Quota].
|
||||
|
||||
[image twolevels 80%]
|
||||
Announcement and request of a service in a subsystem.
|
||||
For simplicity, parent capabilities are not displayed.
|
||||
|
||||
Even though the prior examples involved only one parent,
|
||||
the announce-request mechanism can be used recursively for tree
|
||||
structures of any depth and thus allow for partitioning
|
||||
the system into subsystems that can cooperate with each other whereas
|
||||
parents are always in complete control over the communication
|
||||
and resource usage of their children (and their subsystems).
|
||||
|
||||
Figure [twolevels] depicts a nested subsystem on the left.
|
||||
Child1 announces its service named "Service" at its parent that, in turn,
|
||||
announces a service named "Service" at the Grandparent.
|
||||
The service names do not need to be identical.
|
||||
Their meaning spans to their immediate parent only and there
|
||||
may be a name remapping on each hierarchy level.
|
||||
Each parent can decide itself whether to further announce
|
||||
services of their children to the outer world or not.
|
||||
The parent can announce Child1's service to the grandparent
|
||||
by creating a new root capability to a local service that forwards
|
||||
session-creation and closing requests to Child1.
|
||||
Both Parent and Grandparent keep their local root lists.
|
||||
In a second step, Parent2 initiates the creation of a session to
|
||||
the service by issuing a 'session' request at the Grandparent (1).
|
||||
Grandparent uses its root list to look up the service-providing child (from
|
||||
Grandparent's local view) Parent1 (2).
|
||||
Parent1 in turn, implements the service not by itself but delegates
|
||||
the 'session' request to Child1 by calling the 'session' function
|
||||
of the actual "Service" root interface (3).
|
||||
The session capability, created by Child1 (4), can now be passed to Parent2
|
||||
as return value of nested 'session' calls (5, 6).
|
||||
Each involved node keeps the local knowledge about the created session
|
||||
such that later, the session can be closed in the same nested fashion.
|
||||
|
||||
Quota
|
||||
=====
|
||||
|
||||
Each process that provides services to other processes consumes resources on
|
||||
behalf of it clients.
|
||||
Such a server requires memory to maintain session-specific state, processing
|
||||
time to perform the actual service function, and eventually further system
|
||||
resources (e.g., bus bandwidth) dependent on client requests.
|
||||
To avoid denial-of-service problems, a server must not allocate such
|
||||
resources from its own budget but let the client pay.
|
||||
Therefore, a mechanism for donating resource quotas from the client to the
|
||||
server is required.
|
||||
Both client and server may be arbitrary nodes in the process tree.
|
||||
In the following, we examine the trading of resource quotas within
|
||||
the recursive system structure using memory as an example.
|
||||
|
||||
When creating a child, the parent assigns a part of its own memory quota
|
||||
to the new child.
|
||||
During the lifetime of the child, the parent can further transfer
|
||||
quota back and forth between the child's and its own account.
|
||||
Because the parent creates its children out of its own resources,
|
||||
it has a natural interest to correctly manage child quotas.
|
||||
When a child requests a session to a service, it can bind a part
|
||||
of its quota to the new session by specifying a resource donation
|
||||
as an argument.
|
||||
When receiving a session request, the parent has to distinct
|
||||
three different cases, dependent on where the corresponding server
|
||||
resides:
|
||||
|
||||
:Parent provides service:
|
||||
|
||||
If the parent provides the requested services by itself,
|
||||
it transfers the donated amount of memory quota from the
|
||||
requesting child's account to its own account to compensate
|
||||
the session-specific memory allocation on behalf of its own
|
||||
child.
|
||||
|
||||
:Server is another child:
|
||||
|
||||
If there exists a matching entry in the parent's root list,
|
||||
the requested service is provided by another child (or a
|
||||
node within the child subsystem). In this case, the parent
|
||||
transfers the donated memory quota from the requesting child
|
||||
to the service-providing child.
|
||||
|
||||
:Delegation to grandparent:
|
||||
|
||||
The parent may decide to delegate the session request to
|
||||
its own parent because the requested service is provided by
|
||||
a lower node of the process tree.
|
||||
Thus, the parent will request a session on behalf of its child.
|
||||
The grandparent neither knows nor cares about the actual
|
||||
origin of the request and will simply decrease the memory
|
||||
quota of the parent.
|
||||
For this reason, the parent transfers the donated memory
|
||||
quota from the requesting child to its own account before
|
||||
calling the grandparent.
|
||||
|
||||
This algorithm works recursively.
|
||||
Once, the server receives the session request, it checks if
|
||||
the donated memory quota suffices for storing the session-specific
|
||||
data and, on success, creates the session.
|
||||
If the initial quota donation turns out to be too scarce during
|
||||
the lifetime of a session, the client may make further donations
|
||||
via the 'transfer_quota' function of the parent interface that
|
||||
works analogously.
|
||||
|
||||
If a child requests to close a session, the parent must distinguish
|
||||
the three cases as above.
|
||||
Once, the server receives the session-close request from its parent,
|
||||
it is responsible to release all resources that were used for this session.
|
||||
After the server releases the session-specific resources, the
|
||||
server's quota can be decreased to the prior state.
|
||||
However, an ill-behaving server may fail to release those resources by malice
|
||||
or caused by a bug.
|
||||
|
||||
If the misbehaving service was provided by the parent himself,
|
||||
it has the full authority to not hand back session-quota to
|
||||
its child.
|
||||
If the misbehaving service was provided by the grandparent,
|
||||
the parent (and its whole subsystem) has to subordinate.
|
||||
If, however, the service was provided by another child and the
|
||||
child refuses to release resources, decreasing its quota after
|
||||
closing the session will fail.
|
||||
It is up to the policy of the parent to handle such a failure either by
|
||||
punishing it (e.g., killing the misbehaving server) or by granting more of its
|
||||
own quota.
|
||||
Generally, misbehavior is against the server's own interests and
|
||||
each server would obey the parent's 'close' request to avoid intervention.
|
||||
|
||||
|
||||
Successive policy management
|
||||
============================
|
||||
|
||||
For supporting a high variety of security policies for access control, we
|
||||
require a way to bind properties and restrictions to sessions. For example,
|
||||
a file service may want to restrict the access to files according to an
|
||||
access-control policy that is specific for each client session.
|
||||
On session creation, the 'session' call takes an 'args' argument that can be
|
||||
used for that purpose. It is a list of tag-value pairs describing the session
|
||||
properties. By convention, the list is ordered by attribute priority starting
|
||||
with the most important property.
|
||||
The server uses these 'args' as construction arguments for the new
|
||||
session and enforces the security policy as expressed by 'args' accordingly.
|
||||
Whereas the client defines its desired session-construction arguments, each
|
||||
node that is incorporated in the session creation can alter these arguments in
|
||||
any way and may add further properties.
|
||||
This effectively enables each parent to impose any desired restrictions to
|
||||
sessions created by its children.
|
||||
This concept works recursively and enables each node in the process hierarchy
|
||||
to control exactly the properties that it knows and cares about. As a side
|
||||
note, the specification of resource donations as described in the Section
|
||||
[Quota] is performed with the same mechanism. A resource donation is a property
|
||||
of a session.
|
||||
|
||||
[image incremental_restrictions]
|
||||
Successive application of policies at the creation time of a new session.
|
||||
|
||||
Figure [incremental_restrictions] shows an example scenario. A user
|
||||
application issues the creation of a new session to the 'GUI' server and
|
||||
specifies its wish for reading user input and using the string "Terminal" as
|
||||
window label (1).
|
||||
The parent of the user application is the user manager that introduces
|
||||
user identities into the system and wants to ensure that each displayed window
|
||||
gets tagged with the user and the executed program. Therefore, it overrides the
|
||||
'label' attribute with more accurate information (2). Note that the modified
|
||||
argument is now the head of the argument list.
|
||||
The parent of the user manager, in turn, implements further policies. In the
|
||||
example, Init's policy prohibits the user-manager subtree from reading
|
||||
input (for example to disable access to the system beyond official working hours)
|
||||
by redefining the 'input' attribute and leaving all other attributes unchanged (3).
|
||||
The actual GUI server observes the final result of the successively changed
|
||||
session-construction arguments (4) and it is responsible for enforcing the specified
|
||||
policy for the lifetime of the session.
|
||||
Once a session has been established, its properties are fixed and cannot be changed.
|
||||
|
||||
|
||||
Core - the root of the process tree
|
||||
###################################
|
||||
|
||||
Core is the first user-level program that takes control when starting up the
|
||||
system. It has access to the raw physical resources and converts them to
|
||||
abstractions that enable multiple programs to use these resources.
|
||||
In particular, core converts the physical address space to higher-level
|
||||
containers called _dataspaces_.
|
||||
A dataspace represents a contiguous physical address space region with an
|
||||
arbitrary size (at page-size granularity).
|
||||
Multiple processes can make the same dataspace accessible in their
|
||||
local address spaces.
|
||||
The system on top of core never deals with physical memory pages but
|
||||
uses this uniform abstraction to work with memory, memory-mapped I/O
|
||||
regions, and ROM areas.
|
||||
|
||||
*Note:* _Using only contiguous dataspaces may lead to fragmentation of the_
|
||||
_physical address space. This property is, however, only required by_
|
||||
_a few rare cases (e.g., DMA transfers). Therefore, later versions of the_
|
||||
_design will support non-contiguous dataspaces._
|
||||
|
||||
Furthermore, core provides all prerequisites to bootstrap the process tree.
|
||||
These prerequisites comprise services for creating processes and threads,
|
||||
for allocating memory, for accessing boot-time-present files, and for managing
|
||||
address-space layouts.
|
||||
Core is almost free from policy. There are no configuration options.
|
||||
The only policy of core is the startup of the init process to which core
|
||||
grants all available resources.
|
||||
|
||||
In the following, we explain the session interfaces of core's services in
|
||||
detail.
|
||||
|
||||
|
||||
RAM - allocator for physical memory
|
||||
===================================
|
||||
|
||||
A RAM session is a quota-bounded allocator of blocks from physical memory.
|
||||
There are no RAM-specific session-construction arguments.
|
||||
Immediately after the creation of a RAM session, its quota is zero.
|
||||
To make the RAM session functional, it must be loaded with quota from
|
||||
another already existing RAM session, which we call the _reference account_.
|
||||
The reference account of a RAM session can be defined initially via:
|
||||
!int ref_account(Ram_session_capability ram_session_cap);
|
||||
Once the reference account is defined, quota can be transferred back and
|
||||
forth between the reference account and the new RAM session with:
|
||||
!int transfer_quota(Ram_session_capability ram_session_cap,
|
||||
! size_t amount);
|
||||
Provided, the RAM session has enough quota, a dataspace of a given size
|
||||
can be allocated with:
|
||||
!Ram_dataspace_capability alloc(size_t size);
|
||||
The result value of 'alloc' is a capability to the RAM-dataspace
|
||||
object implemented in core. This capability can be communicated to other
|
||||
processes and can be used to make the dataspace's physical-memory region
|
||||
accessible from these processes.
|
||||
An allocated dataspace can be released with:
|
||||
!void free(Ram_dataspace_capability ds_cap);
|
||||
The 'alloc' and 'free' calls track the used-quota information of the RAM
|
||||
session accordingly.
|
||||
Current statistical information about the quota limit and the
|
||||
used quota can be retrieved by:
|
||||
!size_t quota();
|
||||
!size_t used();
|
||||
Closing a RAM session implicitly destroys all allocated dataspaces.
|
||||
|
||||
|
||||
ROM - boot-time-file access
|
||||
===========================
|
||||
|
||||
A ROM session represents a boot-time-present read-only file. This may be a
|
||||
module provided by the boot loader or a part of a static ROM image. On session
|
||||
construction, a file identifier must be specified as a session argument using the
|
||||
tag 'filename'. The available filenames are not fixed but depend on the actual
|
||||
deployment. On some platforms, core may provide logical files for special memory
|
||||
objects such as the GRUB multiboot info structure or a kernel info page. The
|
||||
ROM session enables the actual read access to the file by exporting the file as
|
||||
dataspace:
|
||||
!Rom_dataspace_capability dataspace();
|
||||
|
||||
|
||||
IO_MEM - memory mapped I/O access
|
||||
=================================
|
||||
|
||||
With IO_MEM, core provides a dataspace abstraction for non-memory parts of the
|
||||
physical address space such as memory-mapped I/O regions or BIOS areas. In
|
||||
contrast to a memory block that is used for storing information of which the
|
||||
physical location in memory is of no matter, a non-memory object has a special
|
||||
semantics attached to its location within the physical address space. Its
|
||||
location is either fixed (by standard) or can be determined at runtime, for
|
||||
example by scanning the PCI bus for PCI resources. If the physical location of
|
||||
such a non-memory object is known, an IO_MEM session can be created by
|
||||
specifying 'base' and 'size' as session-construction arguments.
|
||||
The IO_MEM session then provides the specified physical memory area as
|
||||
dataspace:
|
||||
!Io_mem_dataspace_capability dataspace();
|
||||
|
||||
|
||||
IO_PORT - access to I/O ports
|
||||
=============================
|
||||
|
||||
For platforms that rely on I/O ports for device access, core's IO_PORT service
|
||||
enables fine-grained assignment of port ranges to individual processes.
|
||||
Each IO_PORT session corresponds to the exclusive access right to a
|
||||
port range as specified with the 'io_port_base' and 'io_port_size'
|
||||
session-construction arguments. Core creates the new IO_PORT session
|
||||
only if the specified port range does not overlap with an already existing
|
||||
session. This ensures that each I/O port is driven by only one
|
||||
process at a time. The IO_PORT session interface resembles the
|
||||
physical I/O port access instructions. Reading from an I/O port
|
||||
can be performed via an 8bit, 16bit, or 32bit access:
|
||||
!unsigned char inb(unsigned short address);
|
||||
!unsigned short inw(unsigned short address);
|
||||
!unsigned inl(unsigned short address);
|
||||
Vice versa, there exist functions for writing to an I/O port via
|
||||
an 8bit, 16bit, or 32bit access:
|
||||
!void outb(unsigned short address, unsigned char value);
|
||||
!void outw(unsigned short address, unsigned short value);
|
||||
!void outl(unsigned short address, unsigned value);
|
||||
The address argument of I/O-port access functions are absolute
|
||||
port addresses that must be within the port range of the session.
|
||||
|
||||
|
||||
IRQ - handling device interrupts
|
||||
================================
|
||||
|
||||
The IRQ service of core provides processes with an interface to
|
||||
device interrupts. Each IRQ session corresponds to an attached
|
||||
interrupt. The physical interrupt number is specified via the
|
||||
'irq_number' session-construction argument. A physical interrupt
|
||||
number can be attached to only one session. The IRQ session
|
||||
interface provides a blocking function to wait for the next
|
||||
interrupt:
|
||||
!void wait_for_irq();
|
||||
While the 'wait_for_irq' function blocks, core unmasks the
|
||||
interrupt corresponding to the IRQ session.
|
||||
On function return, the corresponding interrupt line is masked
|
||||
and acknowledged.
|
||||
|
||||
;*Note:* _The interface of the IRQ service is going to be changed_
|
||||
;_with the planed addition of signals to the framework._
|
||||
|
||||
|
||||
RM - managing address space layouts
|
||||
===================================
|
||||
|
||||
RM is a _region manager_ service that allows for constructing address space
|
||||
layouts (_region map_) from dataspaces and that provides support for assigning
|
||||
region maps to processes by paging the process' threads.
|
||||
Each RM session corresponds to one region map. After creating a new RM session,
|
||||
dataspaces can be attached to the region map via:
|
||||
!void *attach(Dataspace_capability ds_cap,
|
||||
! size_t size=0, off_t offset=0,
|
||||
! bool use_local_addr = false,
|
||||
! addr_t local_addr = 0);
|
||||
The 'attach' function inserts the specified dataspace into the region map and
|
||||
returns the actually used start position within the region map.
|
||||
By using the default arguments, the region manager chooses an appropriate
|
||||
position that is large enough to hold the whole dataspace.
|
||||
Alternatively, the caller of 'attach' can attach any sub-range of the dataspace
|
||||
at a specified target position to the region map by enabling 'use_local_addr'
|
||||
and specifying an argument for 'local_addr'. Note that the interface allows for the
|
||||
same dataspace to be attached not only to multiple region maps but also multiple
|
||||
times to the same region map.
|
||||
As the counterpart to 'attach', 'detach' removes dataspaces from the region map:
|
||||
!void detach(void *local_addr);
|
||||
The region manager determines the dataspace at the specified 'local_addr' (not
|
||||
necessarily the start address) and removes the whole dataspace from the region
|
||||
map.
|
||||
To enable the use of a RM session by a process, we must associate it with
|
||||
each thread running in the process. The function
|
||||
!Thread_capability add_client(Thread_capability thread);
|
||||
returns a thread capability for a _pager_ that handles the page faults of the
|
||||
specified 'thread' according to the region map.
|
||||
With subsequent page faults caused by the thread, the address-space layout
|
||||
described by the region map becomes valid for the process that is executing the
|
||||
thread.
|
||||
|
||||
|
||||
CPU - allocator for processing time
|
||||
===================================
|
||||
|
||||
A CPU session is an allocator for processing time that allows for the creation,
|
||||
the control, and the destruction of threads of execution.
|
||||
There are no session arguments used.
|
||||
The functionality of starting and killing threads is provided by two functions:
|
||||
!Thread_capability create_thread(const char* name);
|
||||
!void kill_thread(Thread_capability thread_cap);
|
||||
The 'create_thread' function takes a symbolic thread name (that is only used
|
||||
for debugging purposes) and returns a capability to the new thread.
|
||||
Furthermore, the CPU session provides the following functions for operating
|
||||
on threads:
|
||||
!int set_pager(Thread_capability thread_cap,
|
||||
! Thread_capability pager_cap);
|
||||
|
||||
!int cancel_blocking(Thread_capability thread_cap);
|
||||
|
||||
!int start(Thread_capability thread_cap,
|
||||
! addr_t ip, addr_t sp);
|
||||
|
||||
!int state(Thread_capability thread,
|
||||
! Thread_state *out_state);
|
||||
The 'set_pager' function registers the thread's pager whereas 'pager_cap'
|
||||
(obtained by calling 'add_client' at a RM session) refers to the RM session to
|
||||
be used as the address-space layout.
|
||||
For starting the actual execution of the thread, its initial instruction
|
||||
pointer ('ip') and stack pointer ('sp') must be specified for the 'start'
|
||||
operation.
|
||||
In turn, the 'state' function provides the current thread state including
|
||||
the current instruction pointer and stack pointer.
|
||||
The 'cancel_blocking' function causes the specified thread to cancel a
|
||||
currently executed blocking operation such as waiting for an incoming message
|
||||
or acquiring a lock. This function is used by the framework for gracefully
|
||||
destructing threads.
|
||||
|
||||
*Note:* _Future versions of the CPU service will provide means to further control the_
|
||||
_thread during execution (e.g., pause, execution of only one instruction),_
|
||||
_acquiring more comprehensive thread state (current registers), and configuring_
|
||||
_scheduling parameters._
|
||||
|
||||
|
||||
PD - providing protection domains
|
||||
=================================
|
||||
|
||||
A PD session corresponds to a memory protection domain. Together
|
||||
with one or more threads and an address-space layout (RM session), it forms a
|
||||
process.
|
||||
There are no session arguments. After session creation, the PD contains no
|
||||
threads. Once a new thread has been created from a CPU session, it can be assigned
|
||||
to the PD by calling:
|
||||
! int bind_thread(Thread_capability thread);
|
||||
|
||||
|
||||
CAP - allocator for capabilities
|
||||
================================
|
||||
|
||||
A capability is a system-wide unique object identity that typically refers to a
|
||||
remote object implemented by a service. For each object to be made remotely
|
||||
accessible, the service creates a new capability associated with the local
|
||||
object. CAP is a service to allocate and free capabilities:
|
||||
! Capability alloc(Capability ep_cap);
|
||||
! void free(Capability cap);
|
||||
The 'alloc' function takes an entrypoint capability as argument, which is the
|
||||
communication receiver for invocations of the new capability's RPC interface.
|
||||
|
||||
|
||||
LOG - debug output facility
|
||||
===========================
|
||||
|
||||
The LOG service is used by the lowest-level system components such as the init
|
||||
process for printing debug output.
|
||||
Each LOG session takes a 'label' string as session argument,
|
||||
which is used to prefix the debug output of this session.
|
||||
This enables developers to distinguish multiple producers of debug output.
|
||||
The function
|
||||
! size_t write(const char *string);
|
||||
outputs the specified 'string' to the debug-output backend of core.
|
||||
|
||||
|
||||
Process creation
|
||||
################
|
||||
|
||||
The previous section presented the services implemented by core.
|
||||
In this section, we show how to combine these basic mechanisms to create and
|
||||
execute a process.
|
||||
Process creation serves as a prime example for our general approach to first
|
||||
provide very simple functional primitives and then solve complex problems using
|
||||
a composition of these primitives.
|
||||
We use slightly simplified pseudo code to illustrate this procedure.
|
||||
The 'env()' object refers to the environment of the creating process, which
|
||||
contains its RM session and RAM session.
|
||||
|
||||
:Obtaining the executable ELF binary:
|
||||
|
||||
If the binary is available as ROM object, we can access its data by creating
|
||||
a ROM session with the binary's name as argument and attaching its dataspace
|
||||
to our local address space:
|
||||
!Rom_session_capability file_cap;
|
||||
!file_cap = session("ROM", "filename=init");
|
||||
!Rom_dataspace_capability ds_cap;
|
||||
!ds_cap = Rom_session_client(file_cap).dataspace();
|
||||
!
|
||||
!void *elf_addr = env()->rm_session()->attach(ds_cap);
|
||||
|
||||
The variable 'elf_addr' now points to the start of the binary data.
|
||||
|
||||
:ELF binary decoding and creation of the new region map:
|
||||
|
||||
We create a new region map using the RM service:
|
||||
!Rm_session_capability rm_cap;
|
||||
!rm_cap = session("RM");
|
||||
!Rm_session_client rsc(rm_cap);
|
||||
Initially, this region map is empty.
|
||||
The ELF binary contains CODE, DATA, and BSS sections.
|
||||
For each section, we add a dataspace to the region map.
|
||||
For read-only CODE and DATA sections, we attach the corresponding ranges of
|
||||
the original ELF dataspace ('ds_cap'):
|
||||
!rsc.attach(ds_cap, size, offset, true, addr);
|
||||
The 'size' and 'offset' arguments specify the location of the section within
|
||||
the ELF image. The 'addr' argument defines the desired start position at the
|
||||
region map.
|
||||
For each BSS and DATA section, we allocate a read-and-writeable RAM dataspace
|
||||
!Ram_dataspace_capability rw_cap;
|
||||
!rw_cap = env()->ram_session()->alloc(section_size);
|
||||
and assign its initial content (zero for BSS sections, copy of ELF DATA sections).
|
||||
!void *sec_addr = env()->rm_session()->attach(rw_cap);
|
||||
! ... /* write to buffer at sec_addr */
|
||||
!env()->rm_session()->detach(sec_addr);
|
||||
After iterating through all ELF sections, the region map of the new process
|
||||
is completely initialized.
|
||||
|
||||
:Creating the first thread:
|
||||
|
||||
For creating the main thread of the new process, we create a
|
||||
new CPU session from which we allocate the thread:
|
||||
!CPU_session_capability cpu_cap = session("CPU");
|
||||
!Cpu_session_client csc(cpu_cap);
|
||||
!Thread_capability thread_cap = csc.create_thread();
|
||||
When the thread starts its execution and fetches its first instruction, it
|
||||
will immediately trigger a page fault. Therefore, we need to assign a
|
||||
page-fault handler (pager) to the thread. With resolving subsequent page faults, the
|
||||
pager will populate the address space in which the thread is executed with
|
||||
memory mappings according to a region map:
|
||||
!Thread_capability pager_cap = rsc.add_client(thread_cap);
|
||||
!csc.set_pager(thread_cap, pager_cap);
|
||||
|
||||
:Creating a protection domain:
|
||||
|
||||
The new process' protection domain corresponds to a PD session:
|
||||
!Pd_session_capability pd_cap = session("PD");
|
||||
!Pd_session_client pdsc(pd_cap);
|
||||
|
||||
:Assigning the first thread to the protection domain:
|
||||
|
||||
!pdsc.bind_thread(thread_cap);
|
||||
|
||||
:Starting the execution:
|
||||
|
||||
Now that we defined the relationship of the process' region map, its main
|
||||
thread, and its address space, we can start the process by specifying the
|
||||
initial instruction pointer and stack pointer as obtained from the ELF
|
||||
binary.
|
||||
!csc.start(thread_cap, ip, sp);
|
||||
|
||||
; supplying the parent capability to the new process
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ Identifiers
|
||||
* 'Multi_word_identifiers' use underline to separate words.
|
||||
* 'CONSTANTS' and template arguments are upper case.
|
||||
* Private and protected members of a class begin with an '_'-character.
|
||||
* Accessor functions are named after their corresponding attributes:
|
||||
* Accessor methods are named after their corresponding attributes:
|
||||
|
||||
! /**
|
||||
! * Request private member variable
|
||||
@@ -67,6 +67,10 @@ Identifiers
|
||||
! */
|
||||
! void value(int value) { _value = value; }
|
||||
|
||||
* Accessors that return a boolean value do not carry an 'is_' prefix. E.g.,
|
||||
a method for requesting the validity of an object should be named
|
||||
'valid()', not 'is_valid()'.
|
||||
|
||||
|
||||
Indentation
|
||||
===========
|
||||
@@ -136,13 +140,13 @@ Braces
|
||||
! {
|
||||
! public:
|
||||
!
|
||||
! void function(void)
|
||||
! void method(void)
|
||||
! {
|
||||
! ...
|
||||
! }
|
||||
! };
|
||||
|
||||
except for single-line functions.
|
||||
except for one-line functions.
|
||||
|
||||
* All other occurrences of open braces (for 'if', 'while', 'do', 'for',
|
||||
'namespace', 'enum' etc.) are at the end of a line:
|
||||
@@ -153,7 +157,8 @@ Braces
|
||||
! ..
|
||||
! }
|
||||
|
||||
* Surprisingly, one-line functions should be written on one line.
|
||||
* One-line functions should be written on a single line as long as the line
|
||||
length does not exceed approximately 80 characters.
|
||||
Typically, this applies for accessor functions.
|
||||
If slightly more space than one line is needed, indent as follows:
|
||||
|
||||
@@ -164,10 +169,10 @@ Braces
|
||||
Comments
|
||||
========
|
||||
|
||||
Function header
|
||||
~~~~~~~~~~~~~~~
|
||||
Function/method header
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Each public or protected (but no private) function in a header-file should be
|
||||
Each public or protected (but no private) method in a header-file should be
|
||||
prepended by a header as follows:
|
||||
|
||||
! /**
|
||||
|
||||
@@ -79,6 +79,14 @@ Platform devices
|
||||
this simple ACPI parser traverses the ACPI tables and reports device-resource
|
||||
information (e.g., interrupt lines of PCI devices).
|
||||
|
||||
:'libports/src/app/acpica':
|
||||
In addition to our ACPI base driver, the acpica component uses the
|
||||
ACPICA library to provide access to dynamic functions like battery
|
||||
states, events (e.g., notebook lid close and power buttons), as well
|
||||
as reset and power off. The componenten reports ACPI events and
|
||||
states as reports and itself responds to system state changes of
|
||||
certain configuration ROMs.
|
||||
|
||||
|
||||
UART devices
|
||||
============
|
||||
@@ -169,13 +177,13 @@ at the same time). Depending on the base platform, the implementation uses
|
||||
different time sources. Time sources are either hardware timers, a time source
|
||||
provided by the kernel, or a pseudo time source (busy):
|
||||
|
||||
:'nova': NOVA kernel semaphores as time source
|
||||
:'okl4_x86': PIT as time source
|
||||
:'foc': IPC timeout as time source
|
||||
:'fiasco': IPC timeout as time source
|
||||
:'pistachio': IPC timeout as time source
|
||||
:'linux': nanosleep as time source
|
||||
:'hw': hardware timers depending on platform, e.g., PIT on x86
|
||||
:'nova': NOVA kernel semaphores
|
||||
:'okl4_x86': Programmable Interval Timer (PIT) device
|
||||
:'foc': IPC timeout
|
||||
:'fiasco': IPC timeout
|
||||
:'pistachio': IPC timeout
|
||||
:'linux': nanosleep()
|
||||
:'hw': kernel timer
|
||||
|
||||
|
||||
Audio drivers
|
||||
@@ -461,9 +469,6 @@ Libraries:
|
||||
:'libports/lib/mk/libc':
|
||||
C runtime ported from FreeBSD.
|
||||
|
||||
:'libports/lib/mk/libc_log':
|
||||
Redirects the standard output of the libc to Genode's LOG session interface.
|
||||
|
||||
:'libports/lib/mk/libc_lwip_nic_dhcp':
|
||||
Translates the BSD socket API to a NIC session using the lwIP stack.
|
||||
|
||||
@@ -479,13 +484,6 @@ Libraries:
|
||||
:'libports/lib/mk/libc_fuse_ext2':
|
||||
Accesses files on a block device that contains an ext2 file system.
|
||||
|
||||
:'libports/lib/mk/libc_fs':
|
||||
Allows libc-using programs to access the Genode file-system infrastructure
|
||||
using the POSIX file API.
|
||||
|
||||
:'libports/lib/mk/libc_block':
|
||||
Accesses a block session as a virtual block device.
|
||||
|
||||
:'libports/lib/mk/libc_terminal':
|
||||
Connects the standard input and output from/to Genode's terminal session
|
||||
interface.
|
||||
|
||||
@@ -13,7 +13,7 @@ should be documented but isn't? Or the documentation contains errors with
|
||||
regard to content or spelling? Please let us know by raising the issue at the
|
||||
genode-main mailing list:
|
||||
|
||||
:[http://genode.org/community/mailing-lists - Genode mailing lists]:
|
||||
:[https://genode.org/community/mailing-lists - Genode mailing lists]:
|
||||
|
||||
If you are interested in getting your hands dirty with working on the Genode
|
||||
code base or authoring additional documentation, you are more than welcome.
|
||||
@@ -31,9 +31,9 @@ Alternatively, you may like to have a look at our road map and future
|
||||
challenges to see the big picture of our developments and to get inspiration
|
||||
for your own activities:
|
||||
|
||||
:[http://genode.org/about/road-map]: Road Map
|
||||
:[https://genode.org/about/road-map]: Road Map
|
||||
|
||||
:[http://genode.org/about/challenges]: Future Challenges
|
||||
:[https://genode.org/about/challenges]: Future Challenges
|
||||
|
||||
Once you settled on a specific topic to work on, it is a good idea to get
|
||||
acquainted with the work flow and tools used by the project. The following
|
||||
@@ -81,7 +81,7 @@ Genode's source code follows certain time-tested conventions regarding the
|
||||
coding style and code pattern, which are important to us. The coding style
|
||||
is described in the following document:
|
||||
|
||||
:[http://genode.org/documentation/developer-resources/coding_style]:
|
||||
:[https://genode.org/documentation/developer-resources/coding_style]:
|
||||
Coding Style Guidelines
|
||||
|
||||
We know from experience that for new developers, adhering the coding style can
|
||||
|
||||
@@ -64,12 +64,11 @@ different kernels such as L4/Fiasco, L4ka::Pistachio, OKL4, and NOVA. Those
|
||||
kernels largely differ in terms of feature sets, build systems, tools, and boot
|
||||
concepts. To relieve you from dealing with those peculiarities, Genode provides
|
||||
you with an unified way of using them. For each kernel platform, there exists
|
||||
a dedicated directory called 'base-<platform>'. Within this directory, you will
|
||||
find a 'Makefile', which automates the task of downloading the source codes of
|
||||
the kernel and interfacing the kernel with Genode. Just change to the
|
||||
respective 'base-<platform>' directory and issue:
|
||||
a dedicated description file that enables the 'prepare_port' tool to fetch and
|
||||
prepare the designated 3rd-party sources. Just issue the following command
|
||||
within the toplevel directory of the Genode source tree:
|
||||
|
||||
! make prepare
|
||||
! ./tool/ports/prepare_port <platform>
|
||||
|
||||
Note that each 'base-<platform>' directory comes with a 'README' file, which
|
||||
you should revisit first when exploring the base platform. Additionally, most
|
||||
@@ -77,10 +76,10 @@ you should revisit first when exploring the base platform. Additionally, most
|
||||
respective 'doc/' subdirectories.
|
||||
|
||||
For the VESA driver on x86, the x86emu library is required and can be
|
||||
downloaded and prepared by invoking the following command from within the
|
||||
'libports' directory:
|
||||
downloaded and prepared by again invoking the 3rd-party sources preparation
|
||||
tool:
|
||||
|
||||
! make prepare PKG=x86emu
|
||||
! ./tool/ports/prepare_port x86emu
|
||||
|
||||
Now that the base platform is prepared, the 'create_builddir' tool can be used
|
||||
to create a build directory for your platform of choice by giving the platform
|
||||
@@ -92,7 +91,7 @@ steps are required:
|
||||
|
||||
# Download the kernel:
|
||||
! cd <genode-dir>
|
||||
! make -C repos/base-okl4 prepare
|
||||
! ./tool/ports/prepare_port okl4
|
||||
# Create a build directory
|
||||
! ./tool/create_builddir okl4_x86 BUILD_DIR=build.okl4
|
||||
# Uncomment the following line in 'build.okl4/etc/build.conf'
|
||||
|
||||
55
doc/news.txt
55
doc/news.txt
@@ -4,6 +4,61 @@
|
||||
===========
|
||||
|
||||
|
||||
Genode OS Framework release 16.05 | 2016-05-27
|
||||
##############################################
|
||||
|
||||
| With version 16.05, the Genode API receives a fundamental revision.
|
||||
| The list of further improvements ranges from the introduction of Rust,
|
||||
| over improved GDB support, to a profound update of many device drivers
|
||||
| and ACPI features.
|
||||
|
||||
The current release marks the most profound API revision in the project's
|
||||
history. The new API is designed to reinforce the best practices
|
||||
for implementing Genode components. It is the result of countless
|
||||
experiments and the practical experiences made while developing over hundred
|
||||
genuine components during the past ten years.
|
||||
|
||||
The introduction of the new API prompted us to rework our documentation.
|
||||
In particular, Genode 16.05 is accompanied with a new edition of the
|
||||
"Genode Foundations" book that incorporates all architectural changes and
|
||||
interface modifications of the past year.
|
||||
|
||||
The second focus of the current release is the major update of device
|
||||
drivers. All the drivers that we ported from the Linux kernel correspond
|
||||
now to Linux version 4.4.3. Those drivers comprise the Intel wireless
|
||||
stack, the Intel graphics driver, the USB drivers, and the TCP/IP stack.
|
||||
The updated OpenBSD-based audio driver corresponds to OpenBSD 5.9.
|
||||
|
||||
Apart from the revision of the base framework and device drivers, Genode
|
||||
gains the ability to use the Rust programming language, makes many ACPI
|
||||
features accessible, and allows the use of the GNU debugger with the
|
||||
64-bit version of the NOVA hypervisor.
|
||||
|
||||
The complete story behind these and many more changes is covered by the
|
||||
[http:/documentation/release-notes/16.05 - release documentation of version 16.05...]
|
||||
|
||||
|
||||
How Genode came to RISC-V | 2016-03-22
|
||||
######################################
|
||||
|
||||
| Our new article provides a look behind the scenes of porting Genode to
|
||||
| the RISC-V hardware architecture.
|
||||
|
||||
The experience report
|
||||
[http:/documentation/articles/riscv - How Genode came to RISC-V] complements
|
||||
our recent
|
||||
[http:/documentation/release-notes/16.02#New_support_for_the_RISC-V_CPU_architecture - announcement]
|
||||
about Genode's added RISC-V support with in-depth technical information.
|
||||
It briefly introduces the parts of the instruction set architecture (ISA) that
|
||||
were most relevant for the porting work, presents various challenges we
|
||||
encountered, and explains how we overcame them.
|
||||
|
||||
The article is written with two target audiences in mind: People interested in
|
||||
practical experiences with RISC-V, and developers who aspire to port Genode
|
||||
to new CPU architectures.
|
||||
[http:/documentation/articles/riscv - Read the article...]
|
||||
|
||||
|
||||
Genode OS Framework release 16.02 | 2016-02-26
|
||||
##############################################
|
||||
|
||||
|
||||
@@ -1303,7 +1303,7 @@ You can build the demo by executing
|
||||
A tutorial on how to create a bootable SD card can be found in the
|
||||
corresponding run script _os/tz_vmm.run_. A tutorial on how to reproduce the
|
||||
pre-built Linux image, Rootfs and DTB - used by the run script - can be found
|
||||
at [https://github.com/m-stein/genode_binaries/blob/master/tz_vmm/usb_armory/README].
|
||||
at [http://genode.org/files/release-15.11/usb_armory_tz_vmm/README].
|
||||
|
||||
|
||||
NOVA
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
|
||||
With version 16.02, we add RISC-V to the Genode's supported CPU architectures,
|
||||
With version 16.02, we add RISC-V to Genode's supported CPU architectures,
|
||||
enable the secure pass-through of individual USB devices to virtual machines,
|
||||
and update the support for the Muen and seL4 kernels.
|
||||
|
||||
@@ -97,9 +97,9 @@ implement inheritance. This object model is used throughout QEMU. We took the
|
||||
easy way out and just used a C++ wrapper class that contains all QEMU objects
|
||||
that are used in the USB subsystem.
|
||||
|
||||
The next step was to develop an USB host device model. This model connects a
|
||||
The next step was to develop a USB host device model. This model connects a
|
||||
USB device attached to Genode's USB host-controller driver to the xHCI device
|
||||
model. Lucky for us, QEMU already contains an USB host device model that uses
|
||||
model. Lucky for us, QEMU already contains a USB host device model that uses
|
||||
libusb, which we could use as blueprint. We implemented a USB host device that
|
||||
leverages Genode's custom USB session interface. This host device reacts to a
|
||||
USB device report coming from another component such as the host-controller
|
||||
@@ -107,7 +107,7 @@ driver. It tries to claim all devices it finds in that report and then creates
|
||||
a QEMU USB device for each of them that is attached to the xHCI device model.
|
||||
|
||||
The xHCI device model needs infrastructure that normally is provided by QEMU
|
||||
itself such as a timer queue and PCI device handling. We introduced an QEMU
|
||||
itself such as a timer queue and PCI device handling. We introduced a QEMU
|
||||
USB controller interface _repos/libports/include/qemu/usb.h_ whose back-end
|
||||
library interface has to be implemented by a component, i.e. the VMM, that
|
||||
wants to use the library.
|
||||
@@ -262,7 +262,7 @@ Steps to test Genode on RISC-V
|
||||
|
||||
! # download Genode
|
||||
! cd ../../
|
||||
! git clone https://github.com/ssumpf/genode.git
|
||||
! git clone https://github.com/genodelabs/genode.git
|
||||
!
|
||||
! # build the Genode tool chain
|
||||
! cd genode
|
||||
@@ -475,7 +475,7 @@ Execution on bare hardware (base-hw)
|
||||
|
||||
Within the last months, the initialization code of our custom kernel got
|
||||
re-arranged to simplify the addition of new architectures, e.g., the RISC-V
|
||||
port (Section [New support for the RISC-V CPU architecture]) while also make
|
||||
port (Section [New support for the RISC-V CPU architecture]) while also making
|
||||
its implementation leaner. A positive side effect of this work was the
|
||||
generalization of multi-processor and L2-cache support for ARM's Cortex-A9
|
||||
CPUs. For instance, the Wandboard (Freescale i.MX6 SoC) is now driven with all
|
||||
|
||||
1315
doc/release_notes-16-05.txt
Normal file
1315
doc/release_notes-16-05.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,8 @@ Genode.
|
||||
Recommended development platform
|
||||
################################
|
||||
|
||||
We currently use [http://www.ubuntu.com/ - Ubuntu] 12.04 LTS on servers and
|
||||
client machines. Hence, Genode should always build without trouble on these
|
||||
We use recent [http://www.ubuntu.com/ - Ubuntu] LTS releases on our
|
||||
development hosts. Hence, Genode should always build without trouble on these
|
||||
platforms.
|
||||
|
||||
|
||||
@@ -23,9 +23,10 @@ Unified tool chain
|
||||
##################
|
||||
|
||||
Starting with Genode version 11.11, there is a unified tool chain for all base
|
||||
platforms and supported CPU architectures (x86_32, x86_64, and ARM). For Genode
|
||||
development, we highly recommend the use of the official Genode tool chain. It
|
||||
can be obtained in two ways: as pre-compiled binaries or manually compiled:
|
||||
platforms and supported CPU architectures (x86_32, x86_64, ARM, and RISC-V). For
|
||||
Genode development, we highly recommend the use of the official Genode tool
|
||||
chain. It can be obtained in two ways: as pre-compiled binaries or manually
|
||||
compiled:
|
||||
|
||||
:Pre-compiled:
|
||||
Our pre-compiled tool chain is runnable on Linux x86_32 and x86_64. The
|
||||
@@ -44,12 +45,12 @@ can be obtained in two ways: as pre-compiled binaries or manually compiled:
|
||||
instructions, just start the tool without arguments.
|
||||
|
||||
In both cases, the tool chain will be installed to '/usr/local/genode-gcc'. All
|
||||
tools are prefixed with 'genode-x86-' or 'genode-arm-' respectively such that
|
||||
it is safe to add the installation directory to our 'PATH' variable (optional).
|
||||
The Genode tool chain will be used by the Genode build system by default. If
|
||||
you desire to use a different tool chain, create a file called 'tools.conf' in
|
||||
the 'etc/' subdirectory of your build directory where you can define the
|
||||
tool-chain prefix to be used:
|
||||
tools are prefixed with 'genode-x86-', 'genode-arm-', or 'genode-riscv-'
|
||||
respectively such that it is safe to add the installation directory to our
|
||||
'PATH' variable (optional). The Genode tool chain will be used by the Genode
|
||||
build system by default. If you desire to use a different tool chain, create a
|
||||
file called 'tools.conf' in the 'etc/' subdirectory of your build directory
|
||||
where you can define the tool-chain prefix to be used:
|
||||
|
||||
! CROSS_DEV_PREFIX = /path/to/your/custom/tool_chain/your-x86-
|
||||
|
||||
@@ -58,20 +59,6 @@ see a valid reason not to use it, please contact us (e.g., via the mailing
|
||||
list).
|
||||
|
||||
|
||||
; XXX The Gentoo Portage overlay must be update to the new tool chain
|
||||
;
|
||||
;Gentoo Portage overlay
|
||||
;######################
|
||||
;
|
||||
;For Gentoo users, there exist a Portage overlay, which includes the Genode
|
||||
;toolchain.
|
||||
;
|
||||
;:[https://github.com/blitz/blitz-overlay]:
|
||||
; Portage overlay for using the Genode tool chain on Gentoo
|
||||
;
|
||||
;You'll find the toolchain under sys-devel/genode-toolchain.
|
||||
|
||||
|
||||
Background information - Why do we need a special tool chain?
|
||||
#############################################################
|
||||
|
||||
|
||||
16
repos/README
16
repos/README
@@ -10,7 +10,7 @@ build-system manual:
|
||||
|
||||
:Build-system manual:
|
||||
|
||||
[http://genode.org/documentation/developer-resources/build_system]
|
||||
[https://genode.org/documentation/developer-resources/build_system]
|
||||
|
||||
The build system uses a configurable selection of those reposities to obtain
|
||||
the source codes for the build process. The repositories are not independent
|
||||
@@ -31,33 +31,33 @@ but build upon of each other:
|
||||
|
||||
:'nova':
|
||||
NOVA hypervisor developed at University of Technology Dresden
|
||||
See [http://genode.org/documentation/platforms/nova]
|
||||
See [https://genode.org/documentation/platforms/nova]
|
||||
|
||||
:'foc':
|
||||
Fiasco.OC is a modernized version of the Fiasco microkernel with a
|
||||
completely revised kernel interface fostering capability-based
|
||||
security. It is not compatible with L4/Fiasco.
|
||||
See [http://genode.org/documentation/platforms/foc]
|
||||
See [https://genode.org/documentation/platforms/foc]
|
||||
|
||||
:'hw':
|
||||
The hw platform allows the execution of Genode on bare ARM and x86 hardware
|
||||
without the need for a separate kernel. The kernel functionality is
|
||||
included in core except in the special case of the Muen separation
|
||||
kernel.
|
||||
See [http://genode.org/documentation/platforms/hw] and
|
||||
[http://genode.org/documentation/platforms/muen]
|
||||
See [https://genode.org/documentation/platforms/hw] and
|
||||
[https://genode.org/documentation/platforms/muen]
|
||||
|
||||
:'okl4':
|
||||
OKL4 kernel (x86_32 and ARM) developed at Open-Kernel-Labs.
|
||||
See [http://genode.org/documentation/platforms/okl4]
|
||||
See [https://genode.org/documentation/platforms/okl4]
|
||||
|
||||
:'pistachio':
|
||||
L4ka::Pistachio kernel developed at University of Karlsruhe.
|
||||
See [http://genode.org/documentation/platforms/pistachio]
|
||||
See [https://genode.org/documentation/platforms/pistachio]
|
||||
|
||||
:'fiasco':
|
||||
L4/Fiasco kernel developed at University of Technology Dresden.
|
||||
See [http://genode.org/documentation/platforms/fiasco]
|
||||
See [https://genode.org/documentation/platforms/fiasco]
|
||||
|
||||
:'sel4':
|
||||
seL4 microkernel developed at NICTA/General Dynamics
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
include ../../tool/prepare.mk
|
||||
@@ -40,15 +40,14 @@ Information about Fiasco are provided at its official website:
|
||||
! http://os.inf.tu-dresden.de/fiasco/prev/
|
||||
|
||||
To download the kernel and integrate it with Genode, issue the following
|
||||
command from within the 'base-fiasco' directory:
|
||||
command from within the toplevel directory:
|
||||
|
||||
! make prepare
|
||||
! ./tool/ports/prepare_port fiasco
|
||||
|
||||
For the vesa driver on x86 the x86emu library is required and can be downloaded
|
||||
and prepared by invoking the following command from within the 'libports'
|
||||
directory:
|
||||
and prepared by invoking the following command:
|
||||
|
||||
! make prepare PKG=x86emu
|
||||
! ./tool/ports/prepare_port x86emu
|
||||
|
||||
This command will download a prepackaged version of the kernel tested
|
||||
with Genode. The build process of the kernel is integrated with Genode's
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* \brief Basic locking primitive
|
||||
* \author Norman Feske
|
||||
* \date 2006-07-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__CANCELABLE_LOCK_H_
|
||||
#define _INCLUDE__BASE__CANCELABLE_LOCK_H_
|
||||
|
||||
#include <base/lock_guard.h>
|
||||
#include <base/blocking.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Cancelable_lock
|
||||
{
|
||||
private:
|
||||
|
||||
int volatile _lock;
|
||||
|
||||
public:
|
||||
|
||||
enum State { LOCKED, UNLOCKED };
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
explicit Cancelable_lock(State initial = UNLOCKED);
|
||||
|
||||
/**
|
||||
* Try to aquire lock an block while lock is not free
|
||||
*
|
||||
* This function may throw a Genode::Blocking_canceled exception.
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/**
|
||||
* Release lock
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/**
|
||||
* Lock guard
|
||||
*/
|
||||
typedef Genode::Lock_guard<Cancelable_lock> Guard;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__CANCELABLE_LOCK_H_ */
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* \brief Fiasco-specific layout of IPC message buffer
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
#define _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* IPC message buffer layout
|
||||
*/
|
||||
class Msgbuf_base
|
||||
{
|
||||
protected:
|
||||
|
||||
Genode::size_t _size;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* Begin of message buffer layout
|
||||
*/
|
||||
|
||||
Fiasco::l4_fpage_t rcv_fpage;
|
||||
Fiasco::l4_msgdope_t size_dope;
|
||||
Fiasco::l4_msgdope_t send_dope;
|
||||
char buf[];
|
||||
|
||||
/**
|
||||
* Return size of message buffer
|
||||
*/
|
||||
inline size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
*/
|
||||
inline void *addr() { return &rcv_fpage; };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Instance of IPC message buffer with specified buffer size
|
||||
*/
|
||||
template <unsigned BUF_SIZE>
|
||||
class Msgbuf : public Msgbuf_base
|
||||
{
|
||||
public:
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
Msgbuf() { _size = BUF_SIZE; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
|
||||
@@ -14,6 +14,7 @@
|
||||
#ifndef _INCLUDE__BASE__NATIVE_TYPES_H_
|
||||
#define _INCLUDE__BASE__NATIVE_TYPES_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/native_capability.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
@@ -25,8 +26,6 @@ namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
|
||||
typedef Fiasco::l4_threadid_t Native_thread_id;
|
||||
|
||||
struct Cap_dst_policy
|
||||
{
|
||||
typedef Fiasco::l4_threadid_t Dst;
|
||||
@@ -39,57 +38,7 @@ namespace Genode {
|
||||
static void copy(void* dst, Native_capability_tpl<Cap_dst_policy>* src);
|
||||
};
|
||||
|
||||
struct Native_thread
|
||||
{
|
||||
Native_thread_id l4id;
|
||||
|
||||
/**
|
||||
* Only used in core
|
||||
*
|
||||
* For 'Thread' objects created within core, 'pt' points to
|
||||
* the physical thread object, which is going to be destroyed
|
||||
* on destruction of the 'Thread'.
|
||||
*/
|
||||
Platform_thread *pt;
|
||||
};
|
||||
|
||||
inline unsigned long convert_native_thread_id_to_badge(Native_thread_id tid)
|
||||
{
|
||||
/*
|
||||
* Fiasco has no server-defined badges for page-fault messages.
|
||||
* Therefore, we have to interpret the sender ID as badge.
|
||||
*/
|
||||
return tid.raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty UTCB type expected by the thread library
|
||||
*
|
||||
* On this kernel, UTCBs are not placed within the the context area. Each
|
||||
* thread can request its own UTCB pointer using the kernel interface.
|
||||
*/
|
||||
typedef struct { } Native_utcb;
|
||||
|
||||
typedef Native_capability_tpl<Cap_dst_policy> Native_capability;
|
||||
typedef Fiasco::l4_threadid_t Native_connection_state;
|
||||
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
struct Native_pd_args { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
|
||||
@@ -4,28 +4,13 @@
|
||||
# \date 2013-02-14
|
||||
#
|
||||
|
||||
LIBS += cxx startup
|
||||
include $(BASE_DIR)/lib/mk/base-common.inc
|
||||
|
||||
LIBS += startup
|
||||
|
||||
SRC_CC += cap_copy.cc
|
||||
SRC_CC += ipc/ipc.cc ipc/ipc_marshal_cap.cc
|
||||
SRC_CC += avl_tree/avl_tree.cc
|
||||
SRC_CC += allocator/slab.cc
|
||||
SRC_CC += allocator/allocator_avl.cc
|
||||
SRC_CC += heap/heap.cc heap/sliced_heap.cc
|
||||
SRC_CC += console/console.cc
|
||||
SRC_CC += child/child.cc
|
||||
SRC_CC += process/process.cc
|
||||
SRC_CC += elf/elf_binary.cc
|
||||
SRC_CC += lock/lock.cc
|
||||
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/base/lock
|
||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||
SRC_CC += signal_submit.cc
|
||||
SRC_CC += rpc_dispatch_loop.cc
|
||||
SRC_CC += thread.cc thread_bootstrap.cc thread_myself.cc
|
||||
|
||||
vpath cap_copy.cc $(BASE_DIR)/src/lib/startup
|
||||
vpath %.cc $(REP_DIR)/src/base
|
||||
vpath %.cc $(BASE_DIR)/src/base
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
#
|
||||
# \brief Portions of base library that are exclusive to non-core processes
|
||||
# \author Norman Feske
|
||||
# \date 2013-02-14
|
||||
#
|
||||
include $(BASE_DIR)/lib/mk/base.inc
|
||||
|
||||
LIBS += base-common
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc
|
||||
SRC_CC += thread/thread_start.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
|
||||
INC_DIR += $(BASE_DIR)/src/base/env
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/base
|
||||
vpath %.cc $(BASE_DIR)/src/base
|
||||
SRC_CC += thread_start.cc
|
||||
SRC_CC += cache.cc
|
||||
|
||||
@@ -19,7 +19,7 @@ ifeq ($(L4_BUILD_DIR),$(BUILD_BASE_DIR)/l4)
|
||||
all: $(L4_SRC_DIR)
|
||||
|
||||
$(L4_SRC_DIR):
|
||||
$(VERBOSE)$(ECHO) "--> Please, execute 'make prepare' in $(REP_DIR)"
|
||||
$(VERBOSE)$(ECHO) "--> Please, execute './tool/ports/prepare_port fiasco' in $(GENODE_DIR)"
|
||||
$(VERBOSE)$(ECHO) "--> before compiling Genode apps for Fiasco."
|
||||
$(VERBOSE)exit 1
|
||||
endif
|
||||
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* \brief IPC implementation for Fiasco
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/printf.h>
|
||||
#include <base/ipc.h>
|
||||
#include <base/blocking.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ipc.h>
|
||||
#include <l4/sys/syscalls.h>
|
||||
#include <l4/sys/kdebug.h>
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
void Ipc_ostream::_send()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
|
||||
|
||||
l4_msgdope_t result;
|
||||
l4_ipc_send(_dst.dst(), _snd_msg->addr(), _dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
|
||||
L4_IPC_NEVER, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result)) {
|
||||
PERR("Ipc error %lx", L4_IPC_ERROR(result));
|
||||
throw Genode::Ipc_error();
|
||||
}
|
||||
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg) :
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
void Ipc_istream::_wait()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
l4_msgdope_t result;
|
||||
|
||||
/*
|
||||
* Wait until we get a proper message and thereby
|
||||
* ignore receive message cuts on the server-side.
|
||||
* This error condition should be handled by the
|
||||
* client. The server does not bother.
|
||||
*/
|
||||
do {
|
||||
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
|
||||
|
||||
l4_ipc_wait(&_rcv_cs, _rcv_msg->addr(),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[0]),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
|
||||
L4_IPC_NEVER, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result))
|
||||
PERR("Ipc error %lx", L4_IPC_ERROR(result));
|
||||
|
||||
} while (L4_IPC_IS_ERROR(result));
|
||||
|
||||
/* reset buffer read offset */
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg):
|
||||
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
|
||||
Native_capability(Fiasco::l4_myself(), 0),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
_rcv_cs = L4_INVALID_ID;
|
||||
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
l4_msgdope_t ipc_result;
|
||||
long rec_badge;
|
||||
|
||||
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + 2*sizeof(umword_t) - 1)>>2, 0);
|
||||
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
|
||||
|
||||
l4_ipc_call(Ipc_ostream::_dst.dst(),
|
||||
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg->addr(),
|
||||
Ipc_ostream::_dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
|
||||
_rcv_msg->addr(),
|
||||
reinterpret_cast<l4_umword_t *>(&rec_badge),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
|
||||
L4_IPC_NEVER, &ipc_result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(ipc_result)) {
|
||||
|
||||
if (L4_IPC_ERROR(ipc_result) == L4_IPC_RECANCELED)
|
||||
throw Genode::Blocking_canceled();
|
||||
|
||||
PERR("Ipc error %lx", L4_IPC_ERROR(ipc_result));
|
||||
throw Genode::Ipc_error();
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset buffer read and write offsets. We shadow the first mword of the
|
||||
* send message buffer (filled via '_write_offset') with the local name of
|
||||
* the invoked remote object. We shadow the first mword of the receive
|
||||
* buffer (retrieved via '_read_offset') with the local name of the reply
|
||||
* capability ('rec_badge'), which is bogus in the L4/Fiasco case. In both
|
||||
* cases, we skip the shadowed message mword when reading/writing the
|
||||
* message payload.
|
||||
*/
|
||||
_write_offset = _read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short):
|
||||
Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
|
||||
{ }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_server **
|
||||
****************/
|
||||
|
||||
void Ipc_server::_prepare_next_reply_wait()
|
||||
{
|
||||
/* now we have a request to reply */
|
||||
_reply_needed = true;
|
||||
|
||||
/* leave space for return value at the beginning of the msgbuf */
|
||||
_write_offset = 2*sizeof(umword_t);
|
||||
|
||||
/* receive buffer offset */
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try { Ipc_istream::_wait(); } catch (Blocking_canceled) { }
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs, badge());
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
|
||||
|
||||
l4_msgdope_t result;
|
||||
l4_ipc_send(Ipc_ostream::_dst.dst(), _snd_msg->addr(),
|
||||
Ipc_ostream::_dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
|
||||
L4_IPC_SEND_TIMEOUT_0, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result))
|
||||
PERR("Ipc error %lx, ignored", L4_IPC_ERROR(result));
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
if (_reply_needed) {
|
||||
|
||||
l4_msgdope_t ipc_result;
|
||||
|
||||
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
|
||||
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
|
||||
|
||||
/*
|
||||
* Use short IPC for reply if possible.
|
||||
* This is the common case of returning
|
||||
* an integer as RPC result.
|
||||
*/
|
||||
l4_ipc_reply_and_wait(
|
||||
Ipc_ostream::_dst.dst(),
|
||||
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg->addr(),
|
||||
Ipc_ostream::_dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
|
||||
&_rcv_cs, _rcv_msg->addr(),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[0]),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
|
||||
L4_IPC_SEND_TIMEOUT_0, &ipc_result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(ipc_result)) {
|
||||
PERR("Ipc error %lx", L4_IPC_ERROR(ipc_result));
|
||||
|
||||
/*
|
||||
* The error conditions could be a message cut (which
|
||||
* we want to ignore on the server side) or a reply failure
|
||||
* (for example, if the caller went dead during the call.
|
||||
* In both cases, we do not reflect the error condition to
|
||||
* the user but want to wait for the next proper incoming
|
||||
* message. So let's just wait now.
|
||||
*/
|
||||
_wait();
|
||||
}
|
||||
|
||||
} else _wait();
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs, badge());
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg):
|
||||
Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false)
|
||||
{ }
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* \brief Platform-specific parts of cores CPU-service
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <cpu_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_cap)
|
||||
{
|
||||
PERR("%s: Not implemented", __PRETTY_FUNCTION__);
|
||||
return Ram_dataspace_capability();
|
||||
}
|
||||
|
||||
|
||||
Cpu_session::Quota Cpu_session_component::quota() { return Quota(); }
|
||||
@@ -19,9 +19,14 @@
|
||||
#include <base/ipc.h>
|
||||
#include <base/stdint.h>
|
||||
#include <base/native_types.h>
|
||||
#include <fiasco/thread_helper.h>
|
||||
#include <util/touch.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/fiasco_thread_helper.h>
|
||||
|
||||
/* core includes */
|
||||
#include <util.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/types.h>
|
||||
@@ -89,10 +94,10 @@ namespace Genode {
|
||||
{
|
||||
private:
|
||||
|
||||
Native_thread_id _last; /* origin of last fault message */
|
||||
addr_t _pf_addr; /* page-fault address */
|
||||
addr_t _pf_ip; /* instruction pointer of faulter */
|
||||
Mapping _reply_mapping; /* page-fault answer */
|
||||
Fiasco::l4_threadid_t _last; /* origin of last fault message */
|
||||
addr_t _pf_addr; /* page-fault address */
|
||||
addr_t _pf_ip; /* instruction pointer of faulter */
|
||||
Mapping _reply_mapping; /* page-fault answer */
|
||||
|
||||
public:
|
||||
|
||||
@@ -156,12 +161,12 @@ namespace Genode {
|
||||
unsigned long badge() const {
|
||||
return convert_native_thread_id_to_badge(_last); }
|
||||
|
||||
bool is_write_fault() const { return (_pf_addr & 2); }
|
||||
bool write_fault() const { return (_pf_addr & 2); }
|
||||
|
||||
/**
|
||||
* Return true if last fault was an exception
|
||||
*/
|
||||
bool is_exception() const
|
||||
bool exception() const
|
||||
{
|
||||
/*
|
||||
* Reflection of exceptions is not supported on this platform.
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Genode {
|
||||
*/
|
||||
inline bool map_local(addr_t from_addr, addr_t to_addr, size_t num_pages)
|
||||
{
|
||||
Native_thread_id core_pager = platform_specific()->core_pager()->native_thread_id();
|
||||
Fiasco::l4_threadid_t core_pager = platform_specific()->core_pager()->native_thread_id();
|
||||
|
||||
addr_t offset = 0;
|
||||
size_t page_size = get_page_size();
|
||||
@@ -84,4 +84,3 @@ namespace Genode {
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__MAP_LOCAL_H_ */
|
||||
|
||||
|
||||
@@ -164,12 +164,9 @@ namespace Genode {
|
||||
/**
|
||||
* Bind thread to protection domain
|
||||
*
|
||||
* \return 0 on success or
|
||||
* -1 if thread ID allocation failed.
|
||||
*
|
||||
* This function allocates the physical L4 thread ID.
|
||||
* \return true on success
|
||||
*/
|
||||
int bind_thread(Platform_thread *thread);
|
||||
bool bind_thread(Platform_thread *thread);
|
||||
|
||||
/**
|
||||
* Unbind thread from protection domain
|
||||
@@ -181,7 +178,7 @@ namespace Genode {
|
||||
/**
|
||||
* Assign parent interface to protection domain
|
||||
*/
|
||||
int assign_parent(Native_capability parent) { return 0; }
|
||||
void assign_parent(Native_capability parent) { }
|
||||
|
||||
int pd_id() const { return _pd_id; }
|
||||
|
||||
@@ -192,7 +189,7 @@ namespace Genode {
|
||||
|
||||
/*
|
||||
* On L4/Fiasco, we don't use directed unmap but rely on the
|
||||
* in-kernel mapping database. See 'rm_session_support.cc'.
|
||||
* in-kernel mapping database. See 'region_map_support.cc'.
|
||||
*/
|
||||
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||
};
|
||||
|
||||
@@ -35,14 +35,14 @@ namespace Genode {
|
||||
{
|
||||
private:
|
||||
|
||||
int _thread_id; /* plain thread number */
|
||||
Native_thread_id _l4_thread_id; /* L4 thread ID */
|
||||
char _name[32]; /* thread name that will be
|
||||
registered at the kernel
|
||||
debugger */
|
||||
Platform_pd *_platform_pd; /* protection domain thread
|
||||
is bound to */
|
||||
Pager_object *_pager;
|
||||
int _thread_id; /* plain thread number */
|
||||
Fiasco::l4_threadid_t _l4_thread_id; /* L4 thread ID */
|
||||
char _name[32]; /* thread name that will be
|
||||
registered at the kernel
|
||||
debugger */
|
||||
Platform_pd *_platform_pd; /* protection domain thread
|
||||
is bound to */
|
||||
Pager_object *_pager;
|
||||
|
||||
public:
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Genode {
|
||||
* Constructor
|
||||
*/
|
||||
Platform_thread(size_t, const char *name = 0, unsigned priority = 0,
|
||||
Affinity::Location = Affinity::Location(),
|
||||
addr_t utcb = 0, int thread_id = THREAD_INVALID);
|
||||
|
||||
/**
|
||||
@@ -77,6 +78,11 @@ namespace Genode {
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* Enable/disable single stepping
|
||||
*/
|
||||
void single_step(bool) { }
|
||||
|
||||
/**
|
||||
* Resume this thread
|
||||
*/
|
||||
@@ -94,7 +100,7 @@ namespace Genode {
|
||||
* \param l4_thread_id final L4 thread ID
|
||||
* \param pd platform pd, thread is bound to
|
||||
*/
|
||||
void bind(int thread_id, Native_thread_id l4_thread_id,
|
||||
void bind(int thread_id, Fiasco::l4_threadid_t l4_thread_id,
|
||||
Platform_pd *pd);
|
||||
|
||||
/**
|
||||
@@ -165,9 +171,9 @@ namespace Genode {
|
||||
** Fiasco-specific Accessors **
|
||||
*******************************/
|
||||
|
||||
int thread_id() const { return _thread_id; }
|
||||
Native_thread_id native_thread_id() const { return _l4_thread_id; }
|
||||
const char *name() const { return _name; }
|
||||
int thread_id() const { return _thread_id; }
|
||||
Fiasco::l4_threadid_t native_thread_id() const { return _l4_thread_id; }
|
||||
const char *name() const { return _name; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,12 @@
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
#include <base/printf.h>
|
||||
#include <rm_session/rm_session.h>
|
||||
#include <region_map/region_map.h>
|
||||
#include <util/touch.h>
|
||||
#include <fiasco/thread_helper.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/fiasco_thread_helper.h>
|
||||
#include <base/internal/page_size.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
@@ -92,19 +95,17 @@ namespace Genode {
|
||||
return l4_round_superpage(addr);
|
||||
}
|
||||
|
||||
constexpr size_t get_page_size() { return L4_PAGESIZE; }
|
||||
constexpr size_t get_page_size_log2() { return L4_LOG2_PAGESIZE; }
|
||||
constexpr size_t get_super_page_size() { return L4_SUPERPAGESIZE; }
|
||||
constexpr size_t get_super_page_size_log2() { return L4_LOG2_SUPERPAGESIZE; }
|
||||
|
||||
inline void print_page_fault(const char *msg, addr_t pf_addr, addr_t pf_ip,
|
||||
Rm_session::Fault_type pf_type,
|
||||
Region_map::State::Fault_type pf_type,
|
||||
unsigned long badge)
|
||||
{
|
||||
Native_thread_id tid;
|
||||
Fiasco::l4_threadid_t tid;
|
||||
tid.raw = badge;
|
||||
printf("%s (%s pf_addr=%p pf_ip=%p from %x.%02x)\n", msg,
|
||||
pf_type == Rm_session::WRITE_FAULT ? "WRITE" : "READ",
|
||||
pf_type == Region_map::State::WRITE_FAULT ? "WRITE" : "READ",
|
||||
(void *)pf_addr, (void *)pf_ip,
|
||||
(int)tid.id.task, (int)tid.id.lthread);
|
||||
}
|
||||
@@ -113,6 +114,15 @@ namespace Genode {
|
||||
return core_local_addr; }
|
||||
|
||||
inline size_t constrain_map_size_log2(size_t size_log2) { return size_log2; }
|
||||
|
||||
inline unsigned long convert_native_thread_id_to_badge(Fiasco::l4_threadid_t tid)
|
||||
{
|
||||
/*
|
||||
* Fiasco has no server-defined badges for page-fault messages.
|
||||
* Therefore, we have to interpret the sender ID as badge.
|
||||
*/
|
||||
return tid.raw;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__UTIL_H_ */
|
||||
|
||||
@@ -46,7 +46,7 @@ addr_t Io_mem_session_component::_map_local(addr_t base, size_t size)
|
||||
|
||||
/* find appropriate region for mapping */
|
||||
void *local_base = 0;
|
||||
if (platform()->region_alloc()->alloc_aligned(size, &local_base, alignment).is_error())
|
||||
if (platform()->region_alloc()->alloc_aligned(size, &local_base, alignment).error())
|
||||
return 0;
|
||||
|
||||
/* call sigma0 for I/O region */
|
||||
|
||||
@@ -81,7 +81,7 @@ void Irq_object::_wait_for_irq()
|
||||
|
||||
void Irq_object::start()
|
||||
{
|
||||
::Thread_base::start();
|
||||
::Thread::start();
|
||||
_sync_bootup.lock();
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ void Irq_object::entry()
|
||||
|
||||
Irq_object::Irq_object(unsigned irq)
|
||||
:
|
||||
Thread<4096>("irq"),
|
||||
Thread_deprecated<4096>("irq"),
|
||||
_sync_ack(Lock::LOCKED), _sync_bootup(Lock::LOCKED),
|
||||
_irq(irq)
|
||||
{ }
|
||||
@@ -132,7 +132,7 @@ Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
|
||||
if (msi)
|
||||
throw Root::Unavailable();
|
||||
|
||||
if (!irq_alloc || irq_alloc->alloc_addr(1, _irq_number).is_error()) {
|
||||
if (!irq_alloc || irq_alloc->alloc_addr(1, _irq_number).error()) {
|
||||
PERR("Unavailable IRQ 0x%x requested", _irq_number);
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
@@ -14,10 +14,13 @@
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
|
||||
/* Core includes */
|
||||
/* core includes */
|
||||
#include <ipc_pager.h>
|
||||
#include <pager.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/native_thread.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ipc.h>
|
||||
#include <l4/sys/syscalls.h>
|
||||
@@ -80,5 +83,5 @@ void Ipc_pager::acknowledge_wakeup()
|
||||
|
||||
Untyped_capability Pager_entrypoint::_pager_object_cap(unsigned long badge)
|
||||
{
|
||||
return Untyped_capability(_tid.l4id, badge);
|
||||
return Untyped_capability(native_thread().l4id, badge);
|
||||
}
|
||||
|
||||
50
repos/base-fiasco/src/core/pager_object.cc
Normal file
50
repos/base-fiasco/src/core/pager_object.cc
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* \brief Kernel-specific RM-faulter wake-up mechanism
|
||||
* \author Norman Feske
|
||||
* \date 2016-04-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ipc.h>
|
||||
#include <l4/sys/syscalls.h>
|
||||
#include <l4/sys/kdebug.h>
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Pager_object::wake_up()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
/* kernel-defined message header */
|
||||
struct {
|
||||
l4_fpage_t rcv_fpage; /* unused */
|
||||
l4_msgdope_t size_dope = L4_IPC_DOPE(0, 0);
|
||||
l4_msgdope_t send_dope = L4_IPC_DOPE(0, 0);
|
||||
} rcv_header;
|
||||
|
||||
l4_msgdope_t ipc_result;
|
||||
l4_umword_t dummy = 0;
|
||||
l4_ipc_call(cap().dst(), L4_IPC_SHORT_MSG,
|
||||
0, /* fault address */
|
||||
(l4_umword_t)this, /* instruction pointer */
|
||||
&rcv_header, &dummy, &dummy, L4_IPC_NEVER, &ipc_result);
|
||||
}
|
||||
|
||||
|
||||
void Pager_object::unresolved_page_fault_occurred()
|
||||
{
|
||||
state.unresolved_page_fault = true;
|
||||
}
|
||||
@@ -14,10 +14,13 @@
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/crt0.h>
|
||||
#include <base/sleep.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <fiasco/thread_helper.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/crt0.h>
|
||||
#include <base/internal/fiasco_thread_helper.h>
|
||||
#include <base/internal/stack_area.h>
|
||||
|
||||
/* core includes */
|
||||
#include <core_parent.h>
|
||||
@@ -130,7 +133,9 @@ static void _core_pager_loop()
|
||||
}
|
||||
|
||||
|
||||
Platform::Sigma0::Sigma0() : Pager_object(0, Affinity::Location())
|
||||
Platform::Sigma0::Sigma0()
|
||||
:
|
||||
Pager_object(Cpu_session_capability(), Thread_capability(), 0, Affinity::Location())
|
||||
{
|
||||
cap(reinterpret_cap_cast<Cpu_thread>(Native_capability(Fiasco::sigma0_threadid, 0)));
|
||||
}
|
||||
@@ -145,7 +150,8 @@ Platform::Sigma0 *Platform::sigma0()
|
||||
|
||||
Platform::Core_pager::Core_pager(Platform_pd *core_pd)
|
||||
:
|
||||
Platform_thread(0, "core.pager"), Pager_object(0, Affinity::Location())
|
||||
Platform_thread(0, "core.pager"),
|
||||
Pager_object(Cpu_session_capability(), Thread_capability(), 0, Affinity::Location())
|
||||
{
|
||||
Platform_thread::pager(sigma0());
|
||||
|
||||
@@ -304,8 +310,8 @@ void Platform::_setup_mem_alloc()
|
||||
}
|
||||
|
||||
region.start = addr; region.end = addr + size;
|
||||
if (!region.intersects(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size())) {
|
||||
if (!region.intersects(stack_area_virtual_base(),
|
||||
stack_area_virtual_size())) {
|
||||
add_region(region, _ram_alloc);
|
||||
add_region(region, _core_address_ranges());
|
||||
}
|
||||
@@ -409,9 +415,9 @@ void Platform::_setup_basics()
|
||||
_vm_start = _vm_start == 0 ? L4_PAGESIZE : _vm_start;
|
||||
_region_alloc.add_range(_vm_start, _vm_size);
|
||||
|
||||
/* preserve context area in core's virtual address space */
|
||||
_region_alloc.remove_range(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
/* preserve stack area in core's virtual address space */
|
||||
_region_alloc.remove_range(stack_area_virtual_base(),
|
||||
stack_area_virtual_size());
|
||||
|
||||
/* I/O memory could be the whole user address space */
|
||||
/* FIXME if the kernel helps to find out max address - use info here */
|
||||
|
||||
@@ -199,7 +199,7 @@ void Platform_pd::_free_thread(int thread_id)
|
||||
** Public object members **
|
||||
***************************/
|
||||
|
||||
int Platform_pd::bind_thread(Platform_thread *thread)
|
||||
bool Platform_pd::bind_thread(Platform_thread *thread)
|
||||
{
|
||||
/* thread_id is THREAD_INVALID by default - only core is the special case */
|
||||
int thread_id = thread->thread_id();
|
||||
@@ -207,8 +207,8 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
||||
|
||||
int t = _alloc_thread(thread_id, thread);
|
||||
if (t < 0) {
|
||||
PERR("Thread alloc failed");
|
||||
return -1;
|
||||
PERR("thread alloc failed");
|
||||
return false;
|
||||
}
|
||||
thread_id = t;
|
||||
|
||||
@@ -219,7 +219,7 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
||||
thread->bind(thread_id, l4_thread_id, this);
|
||||
|
||||
if (verbose) _debug_log_threads();
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ void Platform_thread::unbind()
|
||||
void Platform_thread::state(Thread_state s)
|
||||
{
|
||||
PDBG("Not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,8 @@ Weak_ptr<Address_space> Platform_thread::address_space()
|
||||
}
|
||||
|
||||
|
||||
Platform_thread::Platform_thread(size_t, const char *name, unsigned, addr_t,
|
||||
Platform_thread::Platform_thread(size_t, const char *name, unsigned,
|
||||
Affinity::Location, addr_t,
|
||||
int thread_id)
|
||||
: _thread_id(thread_id), _l4_thread_id(L4_INVALID_ID), _pager(0)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <fiasco/thread_helper.h>
|
||||
#include <base/internal/fiasco_thread_helper.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -2,12 +2,15 @@ TARGET = core
|
||||
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
SRC_CC += cap_session_component.cc \
|
||||
context_area.cc \
|
||||
SRC_CC += stack_area.cc \
|
||||
core_printf.cc \
|
||||
core_region_map.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_thread_component.cc \
|
||||
cpu_session_support.cc \
|
||||
dataspace_component.cc \
|
||||
default_log.cc \
|
||||
dump_alloc.cc \
|
||||
io_mem_session_component.cc \
|
||||
io_mem_session_support.cc \
|
||||
@@ -19,24 +22,26 @@ SRC_CC += cap_session_component.cc \
|
||||
pager_ep.cc \
|
||||
pager_object.cc \
|
||||
pd_session_component.cc \
|
||||
rpc_cap_factory.cc \
|
||||
pd_assign_pci.cc \
|
||||
pd_upgrade_ram_quota.cc \
|
||||
platform.cc \
|
||||
platform_pd.cc \
|
||||
platform_services.cc \
|
||||
platform_thread.cc \
|
||||
ram_session_component.cc \
|
||||
ram_session_support.cc \
|
||||
rm_session_component.cc \
|
||||
rm_session_support.cc \
|
||||
region_map_component.cc \
|
||||
region_map_support.cc \
|
||||
rom_session_component.cc \
|
||||
signal_session_component.cc \
|
||||
signal_source_component.cc \
|
||||
thread_start.cc \
|
||||
trace_session_component.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/core/include \
|
||||
$(GEN_CORE_DIR)/include \
|
||||
$(REP_DIR)/src/base/console \
|
||||
$(BASE_DIR)/src/base/thread
|
||||
$(REP_DIR)/src/include \
|
||||
$(BASE_DIR)/src/include
|
||||
|
||||
LIBS += base-common
|
||||
|
||||
@@ -48,17 +53,23 @@ vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rom_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cap_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rm_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rpc_cap_factory.cc $(GEN_CORE_DIR)
|
||||
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath core_region_map.cc $(GEN_CORE_DIR)
|
||||
vpath pd_assign_pci.cc $(GEN_CORE_DIR)
|
||||
vpath pd_upgrade_ram_quota.cc $(GEN_CORE_DIR)
|
||||
vpath region_map_component.cc $(GEN_CORE_DIR)
|
||||
vpath io_mem_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath signal_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath signal_source_component.cc $(GEN_CORE_DIR)
|
||||
vpath trace_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath dataspace_component.cc $(GEN_CORE_DIR)
|
||||
vpath default_log.cc $(GEN_CORE_DIR)
|
||||
vpath dump_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath context_area.cc $(GEN_CORE_DIR)
|
||||
vpath pager_object.cc $(GEN_CORE_DIR)
|
||||
vpath stack_area.cc $(GEN_CORE_DIR)
|
||||
vpath pager_ep.cc $(GEN_CORE_DIR)
|
||||
vpath core_printf.cc $(BASE_DIR)/src/base/console
|
||||
vpath core_printf.cc $(BASE_DIR)/src/lib/base
|
||||
vpath %.cc $(REP_DIR)/src/core
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include <base/thread.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <core_env.h>
|
||||
@@ -22,31 +25,31 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Thread_base::_thread_start()
|
||||
void Thread::_thread_start()
|
||||
{
|
||||
Thread_base::myself()->_thread_bootstrap();
|
||||
Thread_base::myself()->entry();
|
||||
Thread_base::myself()->_join_lock.unlock();
|
||||
Thread::myself()->_thread_bootstrap();
|
||||
Thread::myself()->entry();
|
||||
Thread::myself()->_join_lock.unlock();
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::start()
|
||||
void Thread::start()
|
||||
{
|
||||
/* create and start platform thread */
|
||||
_tid.pt = new(platform()->core_mem_alloc())
|
||||
Platform_thread(0, _context->name);
|
||||
native_thread().pt = new(platform()->core_mem_alloc())
|
||||
Platform_thread(0, _stack->name().string());
|
||||
|
||||
platform_specific()->core_pd()->bind_thread(_tid.pt);
|
||||
platform_specific()->core_pd()->bind_thread(native_thread().pt);
|
||||
|
||||
_tid.pt->pager(platform_specific()->core_pager());
|
||||
_tid.l4id = _tid.pt->native_thread_id();
|
||||
native_thread().pt->pager(platform_specific()->core_pager());
|
||||
native_thread().l4id = native_thread().pt->native_thread_id();
|
||||
|
||||
_tid.pt->start((void *)_thread_start, stack_top());
|
||||
native_thread().pt->start((void *)_thread_start, stack_top());
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::cancel_blocking()
|
||||
void Thread::cancel_blocking()
|
||||
{
|
||||
/*
|
||||
* Within core, we never need to unblock threads
|
||||
@@ -54,8 +57,8 @@ void Thread_base::cancel_blocking()
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_deinit_platform_thread()
|
||||
void Thread::_deinit_platform_thread()
|
||||
{
|
||||
/* destruct platform thread */
|
||||
destroy(platform()->core_mem_alloc(), _tid.pt);
|
||||
destroy(platform()->core_mem_alloc(), native_thread().pt);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__INTERNAL__CORE_CONSOLE_H_
|
||||
#define _INCLUDE__BASE__INTERNAL__CORE_CONSOLE_H_
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/kdebug.h>
|
||||
@@ -28,3 +31,5 @@ namespace Genode {
|
||||
void _out_char(char c) { Fiasco::outchar(c); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__INTERNAL__CORE_CONSOLE_H_ */
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* \brief L4/Fiasco-specific helper functions for the Lock implementation
|
||||
* \author Norman Feske
|
||||
@@ -19,6 +18,9 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_
|
||||
#define _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_
|
||||
|
||||
/* L4/Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ipc.h>
|
||||
@@ -32,3 +34,5 @@ static inline void thread_yield()
|
||||
{
|
||||
Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0));
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */
|
||||
41
repos/base-fiasco/src/include/base/internal/native_thread.h
Normal file
41
repos/base-fiasco/src/include/base/internal/native_thread.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* \brief Kernel-specific thread meta data
|
||||
* \author Norman Feske
|
||||
* \date 2016-03-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
|
||||
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/types.h>
|
||||
}
|
||||
|
||||
namespace Genode { struct Native_thread; }
|
||||
|
||||
struct Genode::Native_thread
|
||||
{
|
||||
Fiasco::l4_threadid_t l4id;
|
||||
|
||||
/**
|
||||
* Only used in core
|
||||
*
|
||||
* For 'Thread' objects created within core, 'pt' points to the physical
|
||||
* thread object, which is going to be destroyed on destruction of the
|
||||
* 'Thread'.
|
||||
*/
|
||||
Platform_thread *pt;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */
|
||||
23
repos/base-fiasco/src/include/base/internal/native_utcb.h
Normal file
23
repos/base-fiasco/src/include/base/internal/native_utcb.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* \brief UTCB definition
|
||||
* \author Norman Feske
|
||||
* \date 2016-03-08
|
||||
*
|
||||
* On this kernel, UTCBs are not placed within the the stack area. Each
|
||||
* thread can request its own UTCB pointer using the kernel interface.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_UTCB_H_
|
||||
#define _INCLUDE__BASE__INTERNAL__NATIVE_UTCB_H_
|
||||
|
||||
namespace Genode { struct Native_utcb { }; }
|
||||
|
||||
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_UTCB_H_ */
|
||||
|
||||
260
repos/base-fiasco/src/lib/base/ipc.cc
Normal file
260
repos/base-fiasco/src/lib/base/ipc.cc
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* \brief IPC implementation for Fiasco
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/ipc.h>
|
||||
#include <base/blocking.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/ipc_server.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ipc.h>
|
||||
#include <l4/sys/syscalls.h>
|
||||
#include <l4/sys/kdebug.h>
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
class Msg_header
|
||||
{
|
||||
private:
|
||||
|
||||
/* kernel-defined message header */
|
||||
Fiasco::l4_fpage_t rcv_fpage; /* unused */
|
||||
Fiasco::l4_msgdope_t size_dope;
|
||||
Fiasco::l4_msgdope_t send_dope;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* First two data words of message, used to transfer the local name of
|
||||
* the invoked object (when a client calls a server) or the exception
|
||||
* code (when the server replies), and the number of capability
|
||||
* arguments. The kernel does not fetch these data words from memory
|
||||
* but transfers them via the short-IPC registers.
|
||||
*/
|
||||
Fiasco::l4_umword_t protocol_word;
|
||||
Fiasco::l4_umword_t num_caps;
|
||||
|
||||
private:
|
||||
|
||||
enum { MAX_CAPS_PER_MSG = Msgbuf_base::MAX_CAPS_PER_MSG };
|
||||
|
||||
Fiasco::l4_threadid_t _cap_tid [MAX_CAPS_PER_MSG];
|
||||
unsigned long _cap_local_name [MAX_CAPS_PER_MSG];
|
||||
|
||||
size_t _num_msg_words(size_t num_data_words) const
|
||||
{
|
||||
size_t const caps_size = sizeof(_cap_tid) + sizeof(_cap_local_name);
|
||||
|
||||
/*
|
||||
* Account for the transfer of the protocol word, capability count,
|
||||
* and capability arguments in front of the payload.
|
||||
*/
|
||||
return 2 + caps_size/sizeof(Fiasco::l4_umword_t) + num_data_words;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void *msg_start() { return &rcv_fpage; }
|
||||
|
||||
/**
|
||||
* Load header fields according to send-message buffer
|
||||
*/
|
||||
void prepare_snd_msg(unsigned long protocol, Msgbuf_base const &snd_msg)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
protocol_word = protocol;
|
||||
num_caps = min((unsigned)MAX_CAPS_PER_MSG, snd_msg.used_caps());
|
||||
|
||||
size_t const snd_words = snd_msg.data_size()/sizeof(l4_umword_t);
|
||||
send_dope = L4_IPC_DOPE(_num_msg_words(snd_words), 0);
|
||||
|
||||
/* reset _cap_tid and _cap_local_name */
|
||||
for (unsigned i = 0; i < MAX_CAPS_PER_MSG; i++) {
|
||||
_cap_tid[i] = L4_INVALID_ID;
|
||||
_cap_local_name[i] = 0;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < num_caps; i++) {
|
||||
Native_capability const &cap = snd_msg.cap(i);
|
||||
_cap_tid[i] = cap.dst();
|
||||
_cap_local_name[i] = cap.local_name();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare header for receiving a message
|
||||
*/
|
||||
void prepare_rcv_msg(Msgbuf_base const &rcv_msg)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
size_t const rcv_max_words = rcv_msg.capacity()/sizeof(l4_umword_t);
|
||||
|
||||
size_dope = L4_IPC_DOPE(_num_msg_words(rcv_max_words), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy received capability arguments into receive message buffer
|
||||
*/
|
||||
void extract_caps(Msgbuf_base &rcv_msg) const
|
||||
{
|
||||
for (unsigned i = 0; i < min((unsigned)MAX_CAPS_PER_MSG, num_caps); i++)
|
||||
rcv_msg.insert(Native_capability(_cap_tid[i],
|
||||
_cap_local_name[i]));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/****************
|
||||
** IPC client **
|
||||
****************/
|
||||
|
||||
Rpc_exception_code Genode::ipc_call(Native_capability dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
|
||||
size_t)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
Msg_header &snd_header = snd_msg.header<Msg_header>();
|
||||
snd_header.prepare_snd_msg(dst.local_name(), snd_msg);
|
||||
|
||||
Msg_header &rcv_header = rcv_msg.header<Msg_header>();
|
||||
rcv_header.prepare_rcv_msg(rcv_msg);
|
||||
|
||||
l4_msgdope_t ipc_result;
|
||||
l4_ipc_call(dst.dst(),
|
||||
snd_header.msg_start(),
|
||||
snd_header.protocol_word,
|
||||
snd_header.num_caps,
|
||||
rcv_header.msg_start(),
|
||||
&rcv_header.protocol_word,
|
||||
&rcv_header.num_caps,
|
||||
L4_IPC_NEVER, &ipc_result);
|
||||
|
||||
rcv_header.extract_caps(rcv_msg);
|
||||
|
||||
if (L4_IPC_IS_ERROR(ipc_result)) {
|
||||
|
||||
if (L4_IPC_ERROR(ipc_result) == L4_IPC_RECANCELED)
|
||||
throw Genode::Blocking_canceled();
|
||||
|
||||
PERR("ipc_call error %lx", L4_IPC_ERROR(ipc_result));
|
||||
throw Genode::Ipc_error();
|
||||
}
|
||||
|
||||
return Rpc_exception_code(rcv_header.protocol_word);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
** IPC server **
|
||||
****************/
|
||||
|
||||
void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
|
||||
Msgbuf_base &snd_msg)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
Msg_header &snd_header = snd_msg.header<Msg_header>();
|
||||
snd_header.prepare_snd_msg(exc.value, snd_msg);
|
||||
|
||||
l4_msgdope_t result;
|
||||
l4_ipc_send(caller.dst(), snd_header.msg_start(),
|
||||
snd_header.protocol_word,
|
||||
snd_header.num_caps,
|
||||
L4_IPC_SEND_TIMEOUT_0, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result))
|
||||
PERR("ipc_send error %lx, ignored", L4_IPC_ERROR(result));
|
||||
}
|
||||
|
||||
|
||||
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
|
||||
Rpc_exception_code exc,
|
||||
Msgbuf_base &reply_msg,
|
||||
Msgbuf_base &request_msg)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
l4_msgdope_t ipc_result;
|
||||
|
||||
bool need_to_wait = true;
|
||||
|
||||
Msg_header &snd_header = reply_msg.header<Msg_header>();
|
||||
snd_header.prepare_snd_msg(exc.value, reply_msg);
|
||||
|
||||
request_msg.reset();
|
||||
Msg_header &rcv_header = request_msg.header<Msg_header>();
|
||||
rcv_header.prepare_rcv_msg(request_msg);
|
||||
|
||||
l4_threadid_t caller = L4_INVALID_ID;
|
||||
|
||||
if (last_caller.valid()) {
|
||||
|
||||
/*
|
||||
* Use short IPC for reply if possible. This is the common case of
|
||||
* returning an integer as RPC result.
|
||||
*/
|
||||
l4_ipc_reply_and_wait(last_caller.dst(), snd_header.msg_start(),
|
||||
snd_header.protocol_word,
|
||||
snd_header.num_caps,
|
||||
&caller, rcv_header.msg_start(),
|
||||
&rcv_header.protocol_word,
|
||||
&rcv_header.num_caps,
|
||||
L4_IPC_SEND_TIMEOUT_0, &ipc_result);
|
||||
|
||||
/*
|
||||
* The error condition could be a message cut (which we want to ignore
|
||||
* on the server side) or a reply failure (for example, if the caller
|
||||
* went dead during the call. In both cases, we do not reflect the
|
||||
* error condition to the user but want to wait for the next proper
|
||||
* incoming message.
|
||||
*/
|
||||
if (L4_IPC_IS_ERROR(ipc_result)) {
|
||||
PERR("ipc_reply_and_wait error %lx", L4_IPC_ERROR(ipc_result));
|
||||
} else {
|
||||
need_to_wait = false;
|
||||
}
|
||||
}
|
||||
|
||||
while (need_to_wait) {
|
||||
|
||||
l4_ipc_wait(&caller, rcv_header.msg_start(),
|
||||
&rcv_header.protocol_word,
|
||||
&rcv_header.num_caps,
|
||||
L4_IPC_NEVER, &ipc_result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(ipc_result)) {
|
||||
PERR("ipc_wait error %lx", L4_IPC_ERROR(ipc_result));
|
||||
} else {
|
||||
need_to_wait = false;
|
||||
}
|
||||
};
|
||||
|
||||
rcv_header.extract_caps(request_msg);
|
||||
|
||||
return Rpc_request(Native_capability(caller, 0), rcv_header.protocol_word);
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server() : Native_capability(Fiasco::l4_myself(), 0) { }
|
||||
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
||||
@@ -26,7 +26,7 @@ using namespace Genode;
|
||||
|
||||
|
||||
Cancelable_lock::Cancelable_lock(Cancelable_lock::State initial)
|
||||
: _lock(UNLOCKED)
|
||||
: _state(UNLOCKED), _owner(nullptr)
|
||||
{
|
||||
if (initial == LOCKED)
|
||||
lock();
|
||||
@@ -39,7 +39,7 @@ void Cancelable_lock::lock()
|
||||
* XXX: How to notice cancel-blocking signals issued when being outside the
|
||||
* 'l4_ipc_sleep' system call?
|
||||
*/
|
||||
while (!Genode::cmpxchg(&_lock, UNLOCKED, LOCKED))
|
||||
while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED))
|
||||
if (Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0)) != L4_IPC_RETIMEOUT)
|
||||
throw Genode::Blocking_canceled();
|
||||
}
|
||||
@@ -48,5 +48,5 @@ void Cancelable_lock::lock()
|
||||
void Cancelable_lock::unlock()
|
||||
{
|
||||
Genode::memory_barrier();
|
||||
_lock = UNLOCKED;
|
||||
_state = UNLOCKED;
|
||||
}
|
||||
@@ -6,26 +6,23 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2014 Genode Labs GmbH
|
||||
* Copyright (C) 2006-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__SLEEP_H_
|
||||
#define _INCLUDE__BASE__SLEEP_H_
|
||||
/* Genode includes */
|
||||
#include <base/sleep.h>
|
||||
#include <base/lock.h>
|
||||
|
||||
/* L4/Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ipc.h>
|
||||
}
|
||||
|
||||
namespace Genode {
|
||||
|
||||
__attribute__((noreturn)) inline void sleep_forever()
|
||||
{
|
||||
while (true) Fiasco::l4_ipc_sleep((Fiasco::l4_timeout_t){0});
|
||||
}
|
||||
void Genode::sleep_forever()
|
||||
{
|
||||
while (true) Fiasco::l4_ipc_sleep((Fiasco::l4_timeout_t){0});
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__SLEEP_H_ */
|
||||
@@ -27,14 +27,14 @@ void prepare_init_main_thread() { }
|
||||
void prepare_reinit_main_thread() { }
|
||||
|
||||
|
||||
/*****************
|
||||
** Thread_base **
|
||||
*****************/
|
||||
/************
|
||||
** Thread **
|
||||
************/
|
||||
|
||||
void Thread_base::_thread_bootstrap() { }
|
||||
void Thread::_thread_bootstrap() { }
|
||||
|
||||
|
||||
void Thread_base::_init_platform_thread(size_t, Type type)
|
||||
void Thread::_init_platform_thread(size_t, Type type)
|
||||
{
|
||||
if (type == NORMAL) { return; }
|
||||
_thread_cap = Genode::env()->parent()->main_thread_cap();
|
||||
@@ -1 +0,0 @@
|
||||
include ../../tool/prepare.mk
|
||||
@@ -46,19 +46,16 @@ The current version of Genode is available at the public subversion repository:
|
||||
After you've fetched the Genode source tree from the subversion repository, or
|
||||
downloaded the latest release tar archive, you need the Fiasco.OC source code,
|
||||
its kernel-bindings, additional bootstrap tools etc. To simplify that step,
|
||||
you can use a Makefile in the 'base-foc' directory of the Genode source tree,
|
||||
just do:
|
||||
you can use the 'prepare_port' tool:
|
||||
|
||||
! cd base-foc
|
||||
! make prepare
|
||||
! ./tool/ports/prepare_port foc
|
||||
|
||||
This will install all necessary third-party source code in the 'contrib' folder.
|
||||
|
||||
For the vesa driver on x86 the x86emu library is required and can be downloaded
|
||||
and prepared by invoking the following command from within the 'libports'
|
||||
directory:
|
||||
and prepared by invoking the following command:
|
||||
|
||||
! make prepare PKG=x86emu
|
||||
! ./tool/ports/prepare_port x86emu
|
||||
|
||||
Now, go to a directory where you want the Genode/Fiasco.OC build directory to
|
||||
remain. Use the helper script in the 'tool' directory of the Genode
|
||||
@@ -89,11 +86,10 @@ instead of building everything:
|
||||
Running L4Linux on top of Genode
|
||||
################################
|
||||
|
||||
To get the L4Linux running on top of Genode, you have to change to the
|
||||
'ports-foc' repository within your Genode source tree and do a 'make prepare':
|
||||
To get the L4Linux running on top of Genode, you have to change prepare its
|
||||
sources:
|
||||
|
||||
! cd ports-foc
|
||||
! make prepare
|
||||
! ./tool/ports/prepare_port l4linux
|
||||
|
||||
This will fetch the currently supported version from the L4Linux subversion
|
||||
repository, and apply a patch to it, that is needed to execute it on top of
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* \brief IPC message buffer layout for Fiasco.OC
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-11-30
|
||||
*
|
||||
* On Fiasco.OC, IPC is used to transmit plain data and capabilities.
|
||||
* Therefore the message buffer contains both categories of payload.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
#define _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/cap_map.h>
|
||||
|
||||
/* Fiasco.OC includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/types.h>
|
||||
#include <l4/sys/utcb.h>
|
||||
}
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Msgbuf_base
|
||||
{
|
||||
public:
|
||||
|
||||
enum { MAX_CAP_ARGS_LOG2 = 2, MAX_CAP_ARGS = 1 << MAX_CAP_ARGS_LOG2 };
|
||||
|
||||
protected:
|
||||
|
||||
size_t _size;
|
||||
|
||||
/**
|
||||
* Number of capability selectors to send.
|
||||
*/
|
||||
size_t _snd_cap_sel_cnt;
|
||||
|
||||
/**
|
||||
* Capability selectors to delegate.
|
||||
*/
|
||||
addr_t _snd_cap_sel[MAX_CAP_ARGS];
|
||||
|
||||
/**
|
||||
* Base of capability receive window.
|
||||
*/
|
||||
Cap_index* _rcv_idx_base;
|
||||
|
||||
/**
|
||||
* Read counter for unmarshalling portal capability selectors
|
||||
*/
|
||||
addr_t _rcv_cap_sel_cnt;
|
||||
|
||||
unsigned long _label;
|
||||
|
||||
char _msg_start[]; /* symbol marks start of message */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Msgbuf_base()
|
||||
: _rcv_idx_base(cap_idx_alloc()->alloc_range(MAX_CAP_ARGS)), _label(0)
|
||||
{
|
||||
rcv_reset();
|
||||
snd_reset();
|
||||
}
|
||||
|
||||
~Msgbuf_base() {
|
||||
cap_idx_alloc()->free(_rcv_idx_base, MAX_CAP_ARGS); }
|
||||
|
||||
/*
|
||||
* Begin of actual message buffer
|
||||
*/
|
||||
char buf[];
|
||||
|
||||
/**
|
||||
* Return size of message buffer
|
||||
*/
|
||||
inline size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; };
|
||||
|
||||
/**
|
||||
* Reset portal capability selector payload
|
||||
*/
|
||||
inline void snd_reset() { _snd_cap_sel_cnt = 0; }
|
||||
|
||||
/**
|
||||
* Append capability selector to message buffer
|
||||
*/
|
||||
inline bool snd_append_cap_sel(addr_t cap_sel)
|
||||
{
|
||||
if (_snd_cap_sel_cnt >= MAX_CAP_ARGS)
|
||||
return false;
|
||||
|
||||
_snd_cap_sel[_snd_cap_sel_cnt++] = cap_sel;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of marshalled capability selectors
|
||||
*/
|
||||
inline size_t snd_cap_sel_cnt() { return _snd_cap_sel_cnt; }
|
||||
|
||||
/**
|
||||
* Return capability selector to send.
|
||||
*
|
||||
* \param i index (0 ... 'snd_cap_sel_cnt()' - 1)
|
||||
* \return capability selector, or 0 if index is invalid
|
||||
*/
|
||||
addr_t snd_cap_sel(unsigned i) {
|
||||
return i < _snd_cap_sel_cnt ? _snd_cap_sel[i] : 0; }
|
||||
|
||||
/**
|
||||
* Return address of capability receive window.
|
||||
*/
|
||||
addr_t rcv_cap_sel_base() { return _rcv_idx_base->kcap(); }
|
||||
|
||||
/**
|
||||
* Reset capability receive window
|
||||
*/
|
||||
void rcv_reset() { _rcv_cap_sel_cnt = 0; }
|
||||
|
||||
/**
|
||||
* Return next received capability selector.
|
||||
*
|
||||
* \return capability selector, or 0 if index is invalid
|
||||
*/
|
||||
addr_t rcv_cap_sel() {
|
||||
return rcv_cap_sel_base() + _rcv_cap_sel_cnt++ * Fiasco::L4_CAP_SIZE; }
|
||||
|
||||
void label(unsigned long label) { _label = label; }
|
||||
unsigned long label() { return _label & (~0UL << 2); }
|
||||
};
|
||||
|
||||
|
||||
template <unsigned BUF_SIZE>
|
||||
class Msgbuf : public Msgbuf_base
|
||||
{
|
||||
public:
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
Msgbuf() { _size = BUF_SIZE; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
|
||||
@@ -1,7 +1,19 @@
|
||||
/*
|
||||
* \brief Platform-specific type definitions
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__NATIVE_TYPES_H_
|
||||
#define _INCLUDE__BASE__NATIVE_TYPES_H_
|
||||
|
||||
#include <base/native_config.h>
|
||||
#include <base/cap_map.h>
|
||||
|
||||
namespace Fiasco {
|
||||
@@ -63,15 +75,12 @@ namespace Fiasco {
|
||||
static bool valid(l4_cap_idx_t idx) {
|
||||
return !(idx & L4_INVALID_CAP_BIT) && idx != 0; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace Genode {
|
||||
|
||||
typedef Fiasco::l4_cap_idx_t Native_thread_id;
|
||||
typedef Fiasco::l4_cap_idx_t Native_thread;
|
||||
typedef Fiasco::l4_cap_idx_t Native_task;
|
||||
typedef Fiasco::l4_utcb_t* Native_utcb;
|
||||
|
||||
|
||||
/**
|
||||
@@ -158,11 +167,6 @@ namespace Genode {
|
||||
Dst dst() const { return _idx ? Dst(_idx->kcap()) : Dst(); }
|
||||
bool valid() const { return (_idx != 0) && _idx->valid(); }
|
||||
};
|
||||
|
||||
|
||||
typedef int Native_connection_state;
|
||||
|
||||
struct Native_pd_args { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace Genode {
|
||||
|
||||
struct Thread_state : Thread_state_base
|
||||
{
|
||||
Native_thread kcap; /* thread's gate cap in its pd */
|
||||
Fiasco::l4_cap_idx_t kcap; /* thread's gate cap in its pd */
|
||||
int id; /* id of gate capability */
|
||||
Native_utcb utcb; /* thread's utcb in its pd */
|
||||
addr_t utcb; /* thread's utcb in its pd */
|
||||
unsigned exceptions; /* counts exceptions raised by the thread */
|
||||
bool paused; /* indicates whether thread is stopped */
|
||||
bool in_exception; /* true if thread is in exception */
|
||||
|
||||
43
repos/base-foc/include/foc/native_thread.h
Normal file
43
repos/base-foc/include/foc/native_thread.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* \brief Kernel-specific thread meta data
|
||||
* \author Norman Feske
|
||||
* \date 2016-03-11
|
||||
*
|
||||
* On most platforms, the 'Genode::Native_thread' type is private to the base
|
||||
* framework. However, on Fiasco.OC, we make the type publicly available to
|
||||
* expose the low-level thread-specific capability selectors to L4Linux.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC__NATIVE_THREAD_H_
|
||||
#define _INCLUDE__FOC__NATIVE_THREAD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
#include <foc/receive_window.h>
|
||||
|
||||
/* Fiasco.OC includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/types.h>
|
||||
}
|
||||
|
||||
namespace Genode { struct Native_thread; }
|
||||
|
||||
struct Genode::Native_thread
|
||||
{
|
||||
Fiasco::l4_cap_idx_t kcap = 0;
|
||||
|
||||
/* receive window for capability selectors received at the server side */
|
||||
Receive_window rcv_window;
|
||||
|
||||
Native_thread() { }
|
||||
explicit Native_thread(Fiasco::l4_cap_idx_t kcap) : kcap(kcap) { }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FOC__NATIVE_THREAD_H_ */
|
||||
65
repos/base-foc/include/foc/receive_window.h
Normal file
65
repos/base-foc/include/foc/receive_window.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* \brief Receive window for capability selectors
|
||||
* \author Norman Feske
|
||||
* \date 2016-03-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC__RECEIVE_WINDOW_H_
|
||||
#define _INCLUDE__FOC__RECEIVE_WINDOW_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
#include <base/ipc_msgbuf.h>
|
||||
#include <base/cap_map.h>
|
||||
|
||||
namespace Genode { struct Receive_window; }
|
||||
|
||||
|
||||
class Genode::Receive_window
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Base of capability receive window.
|
||||
*/
|
||||
Cap_index* _rcv_idx_base = nullptr;
|
||||
|
||||
enum { MAX_CAPS_PER_MSG = Msgbuf_base::MAX_CAPS_PER_MSG };
|
||||
|
||||
public:
|
||||
|
||||
Receive_window() { }
|
||||
|
||||
~Receive_window()
|
||||
{
|
||||
if (_rcv_idx_base)
|
||||
cap_idx_alloc()->free(_rcv_idx_base, MAX_CAPS_PER_MSG);
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
_rcv_idx_base = cap_idx_alloc()->alloc_range(MAX_CAPS_PER_MSG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return address of capability receive window
|
||||
*/
|
||||
addr_t rcv_cap_sel_base() { return _rcv_idx_base->kcap(); }
|
||||
|
||||
/**
|
||||
* Return received selector with index i
|
||||
*
|
||||
* \return capability selector, or 0 if index is invalid
|
||||
*/
|
||||
addr_t rcv_cap_sel(unsigned i) {
|
||||
return rcv_cap_sel_base() + i*Fiasco::L4_CAP_SIZE; }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FOC__RECEIVE_WINDOW_H_ */
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* \brief Client-side cpu session Fiasco.OC extension
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_CPU_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__FOC_CPU_SESSION__CLIENT_H_
|
||||
|
||||
#include <cpu_session/client.h>
|
||||
#include <foc_cpu_session/foc_cpu_session.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Foc_cpu_session_client : Rpc_client<Foc_cpu_session>
|
||||
{
|
||||
explicit Foc_cpu_session_client(Cpu_session_capability session)
|
||||
: Rpc_client<Foc_cpu_session>(static_cap_cast<Foc_cpu_session>(session)) { }
|
||||
|
||||
Thread_capability create_thread(size_t weight, Name const &name, addr_t utcb = 0) {
|
||||
return call<Rpc_create_thread>(weight, name, utcb); }
|
||||
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) {
|
||||
return call<Rpc_utcb>(thread); }
|
||||
|
||||
void kill_thread(Thread_capability thread) {
|
||||
call<Rpc_kill_thread>(thread); }
|
||||
|
||||
int set_pager(Thread_capability thread, Pager_capability pager) {
|
||||
return call<Rpc_set_pager>(thread, pager); }
|
||||
|
||||
int start(Thread_capability thread, addr_t ip, addr_t sp) {
|
||||
return call<Rpc_start>(thread, ip, sp); }
|
||||
|
||||
void pause(Thread_capability thread) {
|
||||
call<Rpc_pause>(thread); }
|
||||
|
||||
void resume(Thread_capability thread) {
|
||||
call<Rpc_resume>(thread); }
|
||||
|
||||
void cancel_blocking(Thread_capability thread) {
|
||||
call<Rpc_cancel_blocking>(thread); }
|
||||
|
||||
int name(Thread_capability thread, char *name_dst, size_t name_len)
|
||||
{
|
||||
PWRN("name called, this function is deprecated");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Thread_state state(Thread_capability thread) {
|
||||
return call<Rpc_get_state>(thread); }
|
||||
|
||||
void state(Thread_capability thread, Thread_state const &state) {
|
||||
call<Rpc_set_state>(thread, state); }
|
||||
|
||||
void exception_handler(Thread_capability thread, Signal_context_capability handler) {
|
||||
call<Rpc_exception_handler>(thread, handler); }
|
||||
|
||||
void single_step(Thread_capability thread, bool enable) {
|
||||
call<Rpc_single_step>(thread, enable); }
|
||||
|
||||
Affinity::Space affinity_space() const {
|
||||
return call<Rpc_affinity_space>(); }
|
||||
|
||||
void affinity(Thread_capability thread, Affinity::Location location) {
|
||||
call<Rpc_affinity>(thread, location); }
|
||||
|
||||
Dataspace_capability trace_control() {
|
||||
return call<Rpc_trace_control>(); }
|
||||
|
||||
unsigned trace_control_index(Thread_capability thread) {
|
||||
return call<Rpc_trace_control_index>(thread); }
|
||||
|
||||
Dataspace_capability trace_buffer(Thread_capability thread) {
|
||||
return call<Rpc_trace_buffer>(thread); }
|
||||
|
||||
Dataspace_capability trace_policy(Thread_capability thread) {
|
||||
return call<Rpc_trace_policy>(thread); }
|
||||
|
||||
void enable_vcpu(Thread_capability cap, addr_t vcpu_state) {
|
||||
call<Rpc_enable_vcpu>(cap, vcpu_state); }
|
||||
|
||||
Native_capability native_cap(Thread_capability cap) {
|
||||
return call<Rpc_native_cap>(cap); }
|
||||
|
||||
Native_capability alloc_irq() {
|
||||
return call<Rpc_alloc_irq>(); }
|
||||
|
||||
int ref_account(Cpu_session_capability session) {
|
||||
return call<Rpc_ref_account>(session); }
|
||||
|
||||
int transfer_quota(Cpu_session_capability session, size_t amount) {
|
||||
return call<Rpc_transfer_quota>(session, amount); }
|
||||
|
||||
Quota quota() override { return call<Rpc_quota>(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__FOC_CPU_SESSION__CLIENT_H_ */
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* \brief Connection to Fiasco.OC specific cpu service
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_CPU_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__FOC_CPU_SESSION__CONNECTION_H_
|
||||
|
||||
#include <foc_cpu_session/client.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Foc_cpu_connection : Connection<Cpu_session>, Foc_cpu_session_client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param label initial session label
|
||||
* \param priority designated priority of all threads created
|
||||
* with this CPU session
|
||||
*/
|
||||
Foc_cpu_connection(const char *label = "",
|
||||
long priority = DEFAULT_PRIORITY)
|
||||
:
|
||||
Connection<Cpu_session>(
|
||||
session("priority=0x%lx, ram_quota=32K, label=\"%s\"",
|
||||
priority, label)),
|
||||
Foc_cpu_session_client(cap()) { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__FOC_CPU_SESSION__CONNECTION_H_ */
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* \brief Cpu session interface extension for Fiasco.OC
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_CPU_SESSION__FOC_CPU_SESSION_H_
|
||||
#define _INCLUDE__FOC_CPU_SESSION__FOC_CPU_SESSION_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
#include <cpu_session/cpu_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Foc_cpu_session : Cpu_session
|
||||
{
|
||||
virtual ~Foc_cpu_session() { }
|
||||
|
||||
virtual void enable_vcpu(Thread_capability cap, addr_t vcpu_state) = 0;
|
||||
|
||||
virtual Native_capability native_cap(Thread_capability cap) = 0;
|
||||
|
||||
virtual Native_capability alloc_irq() = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_enable_vcpu, void, enable_vcpu, Thread_capability, addr_t);
|
||||
GENODE_RPC(Rpc_native_cap, Native_capability, native_cap, Thread_capability);
|
||||
GENODE_RPC(Rpc_alloc_irq, Native_capability, alloc_irq);
|
||||
|
||||
GENODE_RPC_INTERFACE_INHERIT(Cpu_session,
|
||||
Rpc_enable_vcpu, Rpc_native_cap, Rpc_alloc_irq);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__FOC_CPU_SESSION__FOC_CPU_SESSION_H_ */
|
||||
39
repos/base-foc/include/foc_native_cpu/client.h
Normal file
39
repos/base-foc/include/foc_native_cpu/client.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* \brief Client-side Fiasco.OC specific CPU session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \author Norman Feske
|
||||
* \date 2011-04-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_NATIVE_CPU__CLIENT_H_
|
||||
#define _INCLUDE__FOC_NATIVE_CPU__CLIENT_H_
|
||||
|
||||
#include <foc_native_cpu/foc_native_cpu.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
namespace Genode { struct Foc_native_cpu_client; }
|
||||
|
||||
|
||||
struct Genode::Foc_native_cpu_client : Rpc_client<Foc_native_cpu>
|
||||
{
|
||||
explicit Foc_native_cpu_client(Capability<Native_cpu> cap)
|
||||
: Rpc_client<Foc_native_cpu>(static_cap_cast<Foc_native_cpu>(cap)) { }
|
||||
|
||||
void enable_vcpu(Thread_capability cap, addr_t vcpu_state) {
|
||||
call<Rpc_enable_vcpu>(cap, vcpu_state); }
|
||||
|
||||
Native_capability native_cap(Thread_capability cap) {
|
||||
return call<Rpc_native_cap>(cap); }
|
||||
|
||||
Native_capability alloc_irq() {
|
||||
return call<Rpc_alloc_irq>(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FOC_NATIVE_CPU__CLIENT_H_ */
|
||||
42
repos/base-foc/include/foc_native_cpu/foc_native_cpu.h
Normal file
42
repos/base-foc/include/foc_native_cpu/foc_native_cpu.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* \brief Fiasco.OC-specific part of the CPU session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \author Norman Feske
|
||||
* \date 2011-04-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_NATIVE_CPU__FOC_NATIVE_CPU_H_
|
||||
#define _INCLUDE__FOC_NATIVE_CPU__FOC_NATIVE_CPU_H_
|
||||
|
||||
#include <base/rpc.h>
|
||||
#include <cpu_session/cpu_session.h>
|
||||
|
||||
namespace Genode { struct Foc_native_cpu; }
|
||||
|
||||
|
||||
struct Genode::Foc_native_cpu : Cpu_session::Native_cpu
|
||||
{
|
||||
virtual void enable_vcpu(Thread_capability cap, addr_t vcpu_state) = 0;
|
||||
virtual Native_capability native_cap(Thread_capability cap) = 0;
|
||||
virtual Native_capability alloc_irq() = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_enable_vcpu, void, enable_vcpu, Thread_capability, addr_t);
|
||||
GENODE_RPC(Rpc_native_cap, Native_capability, native_cap, Thread_capability);
|
||||
GENODE_RPC(Rpc_alloc_irq, Native_capability, alloc_irq);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_enable_vcpu, Rpc_native_cap, Rpc_alloc_irq);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FOC_NATIVE_CPU__FOC_NATIVE_CPU_H_ */
|
||||
32
repos/base-foc/include/foc_native_pd/client.h
Normal file
32
repos/base-foc/include/foc_native_pd/client.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* \brief Client-side Fiasco.OC specific PD session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \author Norman Feske
|
||||
* \date 2011-04-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_NATIVE_PD__CLIENT_H_
|
||||
#define _INCLUDE__FOC_NATIVE_PD__CLIENT_H_
|
||||
|
||||
#include <foc_native_pd/foc_native_pd.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
namespace Genode { struct Foc_native_pd_client; }
|
||||
|
||||
|
||||
struct Genode::Foc_native_pd_client : Rpc_client<Foc_native_pd>
|
||||
{
|
||||
explicit Foc_native_pd_client(Capability<Native_pd> cap)
|
||||
: Rpc_client<Foc_native_pd>(static_cap_cast<Foc_native_pd>(cap)) { }
|
||||
|
||||
Native_capability task_cap() { return call<Rpc_task_cap>(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FOC_NATIVE_PD__CLIENT_H_ */
|
||||
33
repos/base-foc/include/foc_native_pd/foc_native_pd.h
Normal file
33
repos/base-foc/include/foc_native_pd/foc_native_pd.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* \brief Fiasco.OC-specific part of the PD session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \author Norman Feske
|
||||
* \date 2011-04-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_NATIVE_PD__FOC_NATIVE_PD_H_
|
||||
#define _INCLUDE__FOC_NATIVE_PD__FOC_NATIVE_PD_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <base/rpc.h>
|
||||
#include <pd_session/pd_session.h>
|
||||
|
||||
namespace Genode { struct Foc_native_pd; }
|
||||
|
||||
|
||||
struct Genode::Foc_native_pd : Pd_session::Native_pd
|
||||
{
|
||||
virtual Native_capability task_cap() = 0;
|
||||
|
||||
GENODE_RPC(Rpc_task_cap, Native_capability, task_cap);
|
||||
GENODE_RPC_INTERFACE(Rpc_task_cap);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FOC_NATIVE_PD__FOC_NATIVE_PD_H_ */
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* \brief Client-side Fiasco.OC specific PD session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_PD_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__FOC_PD_SESSION__CLIENT_H_
|
||||
|
||||
#include <foc_pd_session/foc_pd_session.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Foc_pd_session_client : Rpc_client<Foc_pd_session>
|
||||
{
|
||||
explicit Foc_pd_session_client(Capability<Foc_pd_session> session)
|
||||
: Rpc_client<Foc_pd_session>(session) { }
|
||||
|
||||
int bind_thread(Thread_capability thread) {
|
||||
return call<Rpc_bind_thread>(thread); }
|
||||
|
||||
int assign_parent(Parent_capability parent) {
|
||||
return call<Rpc_assign_parent>(parent); }
|
||||
|
||||
Native_capability task_cap() { return call<Rpc_task_cap>(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__FOC_PD_SESSION__CLIENT_H_ */
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* \brief Connection to Fiasco.OC specific PD service
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_PD_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__FOC_PD_SESSION__CONNECTION_H_
|
||||
|
||||
#include <foc_pd_session/client.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Foc_pd_connection : Connection<Foc_pd_session>, Foc_pd_session_client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param args additional session arguments
|
||||
*/
|
||||
Foc_pd_connection(const char *args = 0)
|
||||
:
|
||||
Connection<Foc_pd_session>(
|
||||
session("ram_quota=4K%s%s",
|
||||
args ? ", " : "",
|
||||
args ? args : "")),
|
||||
Foc_pd_session_client(cap())
|
||||
{ }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__FOC_PD_SESSION__CONNECTION_H_ */
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* \brief Fiasco.OC specific PD session extension
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__FOC_PD_SESSION__FOC_PD_SESSION_H_
|
||||
#define _INCLUDE__FOC_PD_SESSION__FOC_PD_SESSION_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <base/rpc.h>
|
||||
#include <pd_session/pd_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Foc_pd_session : Pd_session
|
||||
{
|
||||
virtual ~Foc_pd_session() { }
|
||||
|
||||
virtual Native_capability task_cap() = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_task_cap, Native_capability, task_cap);
|
||||
|
||||
GENODE_RPC_INTERFACE_INHERIT(Pd_session, Rpc_task_cap);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__FOC_PD_SESSION__FOC_PD_SESSION_H_ */
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* \brief Fiasco.OC-specific signal source RPC interface
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SIGNAL_SESSION__FOC_SOURCE_H_
|
||||
#define _INCLUDE__SIGNAL_SESSION__FOC_SOURCE_H_
|
||||
|
||||
#include <base/rpc.h>
|
||||
#include <signal_session/source.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Foc_signal_source : Signal_source
|
||||
{
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_request_semaphore, Native_capability, _request_semaphore);
|
||||
|
||||
GENODE_RPC_INTERFACE_INHERIT(Signal_source, Rpc_request_semaphore);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__SIGNAL_SESSION__FOC_SOURCE_H_ */
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* \brief Signal-source server interface
|
||||
* \author Norman Feske
|
||||
* \date 2010-02-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_
|
||||
#define _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
#include <signal_session/foc_source.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Signal_source_rpc_object : Rpc_object<Foc_signal_source, Signal_source_rpc_object>
|
||||
{
|
||||
protected:
|
||||
|
||||
Native_capability _blocking_semaphore;
|
||||
|
||||
public:
|
||||
|
||||
Signal_source_rpc_object(Native_capability cap)
|
||||
: _blocking_semaphore(cap) {}
|
||||
|
||||
Native_capability _request_semaphore() { return _blocking_semaphore; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_ */
|
||||
@@ -20,12 +20,15 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
|
||||
#define _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
|
||||
#ifndef _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
|
||||
#define _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
|
||||
|
||||
#include <base/rpc_client.h>
|
||||
#include <base/thread.h>
|
||||
#include <signal_session/foc_source.h>
|
||||
#include <signal_source/foc_signal_source.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/native_thread.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/irq.h>
|
||||
@@ -53,7 +56,7 @@ namespace Genode {
|
||||
_sem = call<Rpc_request_semaphore>();
|
||||
|
||||
l4_msgtag_t tag = l4_irq_attach(_sem.dst(), 0,
|
||||
Thread_base::myself()->tid());
|
||||
Thread::myself()->native_thread().kcap);
|
||||
if (l4_error(tag))
|
||||
PERR("l4_irq_attach failed with %ld!", l4_error(tag));
|
||||
}
|
||||
@@ -63,10 +66,17 @@ namespace Genode {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Signal_source_client(Signal_source_capability cap)
|
||||
Signal_source_client(Capability<Signal_source> cap)
|
||||
: Rpc_client<Foc_signal_source>(static_cap_cast<Foc_signal_source>(cap))
|
||||
{ _init_sem(); }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Signal_source_client()
|
||||
{
|
||||
Fiasco::l4_irq_detach(_sem.dst());
|
||||
}
|
||||
|
||||
/*****************************
|
||||
** Signal source interface **
|
||||
@@ -79,17 +89,25 @@ namespace Genode {
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
/* block on semaphore, will be unblocked if signal is available */
|
||||
l4_irq_receive(_sem.dst(), L4_IPC_NEVER);
|
||||
Signal signal;
|
||||
do {
|
||||
|
||||
/*
|
||||
* Now that the server has unblocked the semaphore, we are sure
|
||||
* that there is a signal pending. The following 'wait_for_signal'
|
||||
* request will be immediately answered.
|
||||
*/
|
||||
return call<Rpc_wait_for_signal>();
|
||||
/* block on semaphore until signal context was submitted */
|
||||
l4_irq_receive(_sem.dst(), L4_IPC_NEVER);
|
||||
|
||||
/*
|
||||
* The following request will return immediately and either
|
||||
* return a valid or a null signal. The latter may happen in
|
||||
* the case a submitted signal context was destroyed (by the
|
||||
* submitter) before we have a chance to raise our request.
|
||||
*/
|
||||
signal = call<Rpc_wait_for_signal>();
|
||||
|
||||
} while (!signal.imprint());
|
||||
|
||||
return signal;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_ */
|
||||
#endif /* _INCLUDE__SIGNAL_SOURCE__CLIENT_H_ */
|
||||
30
repos/base-foc/include/signal_source/foc_signal_source.h
Normal file
30
repos/base-foc/include/signal_source/foc_signal_source.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* \brief Fiasco.OC-specific signal source RPC interface
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-04-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SIGNAL_SOURCE__FOC_SIGNAL_SOURCE_H_
|
||||
#define _INCLUDE__SIGNAL_SOURCE__FOC_SIGNAL_SOURCE_H_
|
||||
|
||||
#include <signal_source/signal_source.h>
|
||||
#include <base/rpc_server.h>
|
||||
|
||||
namespace Genode { struct Foc_signal_source; }
|
||||
|
||||
|
||||
struct Genode::Foc_signal_source : Signal_source
|
||||
{
|
||||
GENODE_RPC(Rpc_request_semaphore, Native_capability, _request_semaphore);
|
||||
GENODE_RPC_INTERFACE_INHERIT(Signal_source, Rpc_request_semaphore);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SIGNAL_SOURCE__FOC_SIGNAL_SOURCE_H_ */
|
||||
38
repos/base-foc/include/signal_source/rpc_object.h
Normal file
38
repos/base-foc/include/signal_source/rpc_object.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* \brief Signal-source server interface
|
||||
* \author Norman Feske
|
||||
* \date 2010-02-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_
|
||||
#define _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_
|
||||
|
||||
#include <base/rpc_server.h>
|
||||
#include <signal_source/foc_signal_source.h>
|
||||
|
||||
namespace Genode { struct Signal_source_rpc_object; }
|
||||
|
||||
|
||||
struct Genode::Signal_source_rpc_object : Rpc_object<Foc_signal_source,
|
||||
Signal_source_rpc_object>
|
||||
{
|
||||
protected:
|
||||
|
||||
Native_capability _blocking_semaphore;
|
||||
|
||||
public:
|
||||
|
||||
Signal_source_rpc_object(Native_capability cap)
|
||||
: _blocking_semaphore(cap) {}
|
||||
|
||||
Native_capability _request_semaphore() { return _blocking_semaphore; }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_ */
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* \brief Platform-specific context area definitions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-01-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__NATIVE_CONFIG_H_
|
||||
#define _INCLUDE__BASE__NATIVE_CONFIG_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
return 0x20000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_CONFIG_H_ */
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* \brief Platform-specific context area definitions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-01-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__NATIVE_CONFIG_H_
|
||||
#define _INCLUDE__BASE__NATIVE_CONFIG_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_CONFIG_H_ */
|
||||
14
repos/base-foc/lib/mk/base-common.inc
Normal file
14
repos/base-foc/lib/mk/base-common.inc
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# \brief Portions of base library shared by core and non-core processes
|
||||
# \author Norman Feske
|
||||
# \date 2013-02-14
|
||||
#
|
||||
|
||||
include $(BASE_DIR)/lib/mk/base-common.inc
|
||||
|
||||
LIBS += syscall startup
|
||||
|
||||
SRC_CC += spin_lock.cc cap_map.cc
|
||||
SRC_CC += signal_submit.cc
|
||||
SRC_CC += rpc_dispatch_loop.cc
|
||||
SRC_CC += thread.cc thread_bootstrap.cc thread_myself.cc utcb.cc
|
||||
@@ -1,33 +0,0 @@
|
||||
#
|
||||
# \brief Portions of base library shared by core and non-core processes
|
||||
# \author Norman Feske
|
||||
# \date 2013-02-14
|
||||
#
|
||||
|
||||
LIBS += cxx syscall startup
|
||||
|
||||
SRC_CC += ipc/ipc.cc
|
||||
SRC_CC += avl_tree/avl_tree.cc
|
||||
SRC_CC += allocator/slab.cc
|
||||
SRC_CC += allocator/allocator_avl.cc
|
||||
SRC_CC += heap/heap.cc heap/sliced_heap.cc
|
||||
SRC_CC += console/console.cc
|
||||
SRC_CC += child/child.cc
|
||||
SRC_CC += process/process.cc
|
||||
SRC_CC += elf/elf_binary.cc
|
||||
SRC_CC += lock/lock.cc
|
||||
SRC_CC += env/spin_lock.cc env/cap_map.cc
|
||||
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/base/lock
|
||||
INC_DIR += $(BASE_DIR)/src/base/lock
|
||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/base
|
||||
vpath %.cc $(BASE_DIR)/src/base
|
||||
|
||||
# vi: set ft=make :
|
||||
4
repos/base-foc/lib/mk/base.inc
Normal file
4
repos/base-foc/lib/mk/base.inc
Normal file
@@ -0,0 +1,4 @@
|
||||
include $(BASE_DIR)/lib/mk/base.inc
|
||||
|
||||
SRC_CC += cap_map_remove.cc cap_alloc.cc
|
||||
SRC_CC += thread_start.cc
|
||||
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# \brief Portions of base library that are exclusive to non-core processes
|
||||
# \author Norman Feske
|
||||
# \date 2013-02-14
|
||||
#
|
||||
|
||||
LIBS += base-common
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc \
|
||||
env/cap_map_remove.cc env/cap_alloc.cc
|
||||
SRC_CC += thread/thread_start.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
|
||||
INC_DIR += $(BASE_DIR)/src/base/env
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/base
|
||||
vpath %.cc $(BASE_DIR)/src/base
|
||||
@@ -6,6 +6,12 @@
|
||||
# userland (L4re) that comes with Fiasco.OC.
|
||||
#
|
||||
|
||||
#
|
||||
# We do this also in the first build stage to ensure that the kernel
|
||||
# port, if missing, is added to the missing-ports list of this stage.
|
||||
#
|
||||
FOC_CONTRIB_DIR := $(call select_from_ports,foc)/src/kernel/foc
|
||||
|
||||
#
|
||||
# Execute the rules in this file only at the second build stage when we know
|
||||
# about the complete build settings, e.g., the 'CROSS_DEV_PREFIX'.
|
||||
@@ -26,8 +32,6 @@ $(BUILD_BASE_DIR)/include/%:
|
||||
$(VERBOSE)mkdir -p $(dir $@)
|
||||
$(VERBOSE)ln -sf $(L4_BUILD_DIR)/include/$* $@
|
||||
|
||||
FOC_CONTRIB_DIR := $(call select_from_ports,foc)/src/kernel/foc
|
||||
|
||||
#
|
||||
# Create L4 build directory
|
||||
#
|
||||
|
||||
4
repos/base-foc/lib/mk/spec/arm/base-common.mk
Normal file
4
repos/base-foc/lib/mk/spec/arm/base-common.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
# override default stack-area location
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
||||
include $(REP_DIR)/lib/mk/base-common.inc
|
||||
4
repos/base-foc/lib/mk/spec/arm/base.mk
Normal file
4
repos/base-foc/lib/mk/spec/arm/base.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
# override default stack-area location
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
||||
include $(REP_DIR)/lib/mk/base.inc
|
||||
1
repos/base-foc/lib/mk/spec/x86/base-common.mk
Normal file
1
repos/base-foc/lib/mk/spec/x86/base-common.mk
Normal file
@@ -0,0 +1 @@
|
||||
include $(REP_DIR)/lib/mk/base-common.inc
|
||||
1
repos/base-foc/lib/mk/spec/x86/base.mk
Normal file
1
repos/base-foc/lib/mk/spec/x86/base.mk
Normal file
@@ -0,0 +1 @@
|
||||
include $(REP_DIR)/lib/mk/base.inc
|
||||
@@ -1 +1 @@
|
||||
93b35252166845ea911ae0199c10bda630b82fae
|
||||
521140ea75494478740770721061509c6e7c6812
|
||||
|
||||
@@ -2,5 +2,5 @@ LICENSE := GPLv2
|
||||
VERSION := git
|
||||
DOWNLOADS := foc.git
|
||||
URL(foc) := http://github.com/ssumpf/foc.git
|
||||
REV(foc) := 818a435e9efa5b48fe396a1e88c09a3d1c3cc9b7
|
||||
REV(foc) := 4e0373fe5e2ee179dde0eeb796cdf6918936e293
|
||||
DIR(foc) := src/kernel/foc
|
||||
|
||||
@@ -9,9 +9,7 @@ install_config {
|
||||
<service name="RAM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="RM"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="SIGNAL"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
|
||||
@@ -1,369 +0,0 @@
|
||||
/*
|
||||
* \brief Implementation of the IPC API for Fiasco.OC
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2009-12-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/*
|
||||
* l4_msgtag_t (size == 1 mword) format:
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
* | label | 4 Bit flags | 6 Bit items | 6 Bit word count |
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/blocking.h>
|
||||
#include <base/ipc.h>
|
||||
#include <base/ipc_msgbuf.h>
|
||||
#include <base/thread.h>
|
||||
#include <util/assert.h>
|
||||
|
||||
/* base-foc/src/base/lock */
|
||||
#include <lock_helper.h> /* for 'thread_get_my_native_id()' */
|
||||
|
||||
/* Fiasco.OC includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/consts.h>
|
||||
#include <l4/sys/ipc.h>
|
||||
#include <l4/sys/types.h>
|
||||
#include <l4/sys/utcb.h>
|
||||
#include <l4/sys/kdebug.h>
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Fiasco;
|
||||
|
||||
|
||||
/*****************************
|
||||
** IPC marshalling support **
|
||||
*****************************/
|
||||
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
{
|
||||
if (cap.valid()) {
|
||||
if (!l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst()))) {
|
||||
_write_to_buf(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* transfer capability id */
|
||||
_write_to_buf(cap.local_name());
|
||||
|
||||
/* only transfer kernel-capability if it's a valid one */
|
||||
if (cap.valid())
|
||||
_snd_msg->snd_append_cap_sel(cap.dst());
|
||||
|
||||
ASSERT(!cap.valid() ||
|
||||
l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst())),
|
||||
"Send invalid cap");
|
||||
}
|
||||
|
||||
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
{
|
||||
long value = 0;
|
||||
|
||||
/* extract capability id from message buffer */
|
||||
_read_from_buf(value);
|
||||
|
||||
/* if id is zero an invalid capability was transfered */
|
||||
if (!value) {
|
||||
cap = Native_capability();
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to insert received capability in the map and return it */
|
||||
cap = Native_capability(cap_map()->insert_map(value, _rcv_msg->rcv_cap_sel()));
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** Utilities **
|
||||
***************/
|
||||
|
||||
enum Debug {
|
||||
DEBUG_MSG = 0,
|
||||
HALT_ON_ERROR = 0
|
||||
};
|
||||
|
||||
|
||||
static inline bool ipc_error(l4_msgtag_t tag, bool print)
|
||||
{
|
||||
int ipc_error = l4_ipc_error(tag, l4_utcb());
|
||||
if (ipc_error) {
|
||||
if (print) {
|
||||
outstring("Ipc error: ");
|
||||
outhex32(ipc_error);
|
||||
outstring(" occurred!\n");
|
||||
}
|
||||
if (HALT_ON_ERROR)
|
||||
enter_kdebug("Ipc error");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy message registers from UTCB to destination message buffer
|
||||
*/
|
||||
static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base *rcv_msg)
|
||||
{
|
||||
unsigned num_msg_words = l4_msgtag_words(tag);
|
||||
unsigned num_cap_sel = l4_msgtag_items(tag);
|
||||
if (num_msg_words == 0 && num_cap_sel == 0)
|
||||
return;
|
||||
|
||||
/* look up and validate destination message buffer to receive the payload */
|
||||
l4_mword_t *msg_buf = (l4_mword_t *)rcv_msg->buf;
|
||||
if (num_msg_words*sizeof(l4_mword_t) > rcv_msg->size()) {
|
||||
if (DEBUG_MSG)
|
||||
outstring("receive message buffer too small");
|
||||
num_msg_words = rcv_msg->size()/sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
/* read message payload into destination message buffer */
|
||||
l4_mword_t *src = (l4_mword_t *)l4_utcb_mr();
|
||||
l4_mword_t *dst = (l4_mword_t *)&msg_buf[0];
|
||||
for (unsigned i = 0; i < num_msg_words; i++)
|
||||
*dst++ = *src++;
|
||||
|
||||
rcv_msg->rcv_reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy message registers from message buffer to UTCB and create message tag.
|
||||
*/
|
||||
static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned offset,
|
||||
Native_capability dst)
|
||||
{
|
||||
l4_mword_t *msg_buf = (l4_mword_t *)snd_msg->buf;
|
||||
unsigned num_msg_words = offset/sizeof(l4_mword_t);
|
||||
unsigned num_cap_sel = snd_msg->snd_cap_sel_cnt();
|
||||
|
||||
if (num_msg_words + 2 * num_cap_sel > L4_UTCB_GENERIC_DATA_SIZE) {
|
||||
if (DEBUG_MSG)
|
||||
outstring("receive message buffer too small");
|
||||
throw Ipc_error();
|
||||
}
|
||||
|
||||
/* first copy target label to message buffer */
|
||||
msg_buf[0] = dst.local_name();
|
||||
|
||||
/* store message into UTCB message registers */
|
||||
for (unsigned i = 0; i < num_msg_words; i++)
|
||||
l4_utcb_mr()->mr[i] = msg_buf[i];
|
||||
|
||||
/* setup flexpages of capabilities to send */
|
||||
for (unsigned i = 0; i < num_cap_sel; i++) {
|
||||
unsigned idx = num_msg_words + 2*i;
|
||||
l4_utcb_mr()->mr[idx] = L4_ITEM_MAP/* | L4_ITEM_CONT*/;
|
||||
l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(snd_msg->snd_cap_sel(i),
|
||||
0, L4_FPAGE_RWX).raw;
|
||||
}
|
||||
|
||||
/* we have consumed capability selectors, reset message buffer */
|
||||
snd_msg->snd_reset();
|
||||
|
||||
return l4_msgtag(0, num_msg_words, num_cap_sel, 0);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
void Ipc_ostream::_send()
|
||||
{
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
|
||||
tag = l4_ipc_send(_dst.dst(), l4_utcb(), tag, L4_IPC_NEVER);
|
||||
if (ipc_error(tag, DEBUG_MSG))
|
||||
throw Ipc_error();
|
||||
|
||||
_write_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
/* Build with frame pointer to make GDB backtraces work. See issue #1061. */
|
||||
__attribute__((optimize("-fno-omit-frame-pointer")))
|
||||
__attribute__((noinline))
|
||||
void Ipc_istream::_wait()
|
||||
{
|
||||
l4_umword_t label = 0;
|
||||
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
}
|
||||
l4_utcb_br()->bdr = 0;
|
||||
|
||||
l4_msgtag_t tag;
|
||||
do {
|
||||
tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
|
||||
} while (ipc_error(tag, DEBUG_MSG));
|
||||
|
||||
/* copy received label into message buffer */
|
||||
_rcv_msg->label(label);
|
||||
|
||||
/* copy message from the UTCBs message registers to the receive buffer */
|
||||
copy_utcb_to_msgbuf(tag, _rcv_msg);
|
||||
|
||||
/* reset unmarshaller */
|
||||
_read_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
|
||||
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
_read_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
/* copy call message to the UTCBs message registers */
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
|
||||
|
||||
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
}
|
||||
|
||||
tag = l4_ipc_call(_dst.dst(), l4_utcb(), tag, L4_IPC_NEVER);
|
||||
if (l4_ipc_error(tag, l4_utcb()) == L4_IPC_RECANCELED)
|
||||
throw Genode::Blocking_canceled();
|
||||
if (ipc_error(tag, DEBUG_MSG))
|
||||
throw Genode::Ipc_error();
|
||||
|
||||
/* copy request message from the UTCBs message registers */
|
||||
copy_utcb_to_msgbuf(tag, _rcv_msg);
|
||||
|
||||
_write_offset = _read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_server **
|
||||
****************/
|
||||
|
||||
void Ipc_server::_prepare_next_reply_wait()
|
||||
{
|
||||
/* now we have a request to reply */
|
||||
_reply_needed = true;
|
||||
|
||||
/* leave space for return value at the beginning of the msgbuf */
|
||||
_write_offset = 2*sizeof(umword_t);
|
||||
|
||||
/* receive buffer offset */
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try { Ipc_istream::_wait(); } catch (Blocking_canceled) { }
|
||||
|
||||
/* we only have an unknown implicit reply capability */
|
||||
/* _dst = ???; */
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
{
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
|
||||
tag = l4_ipc_send(L4_SYSF_REPLY, l4_utcb(), tag, L4_IPC_SEND_TIMEOUT_0);
|
||||
ipc_error(tag, DEBUG_MSG);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
{
|
||||
if (_reply_needed) {
|
||||
l4_umword_t label;
|
||||
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
}
|
||||
|
||||
l4_utcb_br()->bdr &= ~L4_BDR_OFFSET_MASK;
|
||||
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
|
||||
tag = l4_ipc_reply_and_wait(l4_utcb(), tag, &label, L4_IPC_SEND_TIMEOUT_0);
|
||||
if (ipc_error(tag, false)) {
|
||||
/*
|
||||
* The error conditions could be a message cut (which
|
||||
* we want to ignore on the server side) or a reply failure
|
||||
* (for example, if the caller went dead during the call.
|
||||
* In both cases, we do not reflect the error condition to
|
||||
* the user but want to wait for the next proper incoming
|
||||
* message. So let's just wait now.
|
||||
*/
|
||||
_wait();
|
||||
} else {
|
||||
|
||||
/* copy received label into message buffer */
|
||||
_rcv_msg->label(label);
|
||||
|
||||
/* copy request message from the UTCBs message registers */
|
||||
copy_utcb_to_msgbuf(tag, _rcv_msg);
|
||||
}
|
||||
} else
|
||||
_wait();
|
||||
|
||||
/* reply capability is implicit in fiasco.oc and unknown to us */
|
||||
/* _dst = ???; */
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg)
|
||||
: Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg),
|
||||
_reply_needed(false)
|
||||
{ }
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* \brief Default version of platform-specific part of server framework
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2006-05-12
|
||||
*
|
||||
* This version is suitable for platforms similar to L4. Each platform
|
||||
* for which this implementation is not suited contains a platform-
|
||||
* specific version in its respective 'base-<platform>' repository.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/rpc_server.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/***********************
|
||||
** Server entrypoint **
|
||||
***********************/
|
||||
|
||||
Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
|
||||
{
|
||||
Untyped_capability new_obj_cap = _cap_session->alloc(_cap);
|
||||
|
||||
/* add server object to object pool */
|
||||
obj->cap(new_obj_cap);
|
||||
insert(obj);
|
||||
|
||||
/* return capability that uses the object id as badge */
|
||||
return new_obj_cap;
|
||||
}
|
||||
|
||||
|
||||
void Rpc_entrypoint::entry()
|
||||
{
|
||||
Ipc_server srv(&_snd_buf, &_rcv_buf);
|
||||
_ipc_server = &srv;
|
||||
_cap = srv;
|
||||
_cap_valid.unlock();
|
||||
|
||||
/*
|
||||
* Now, the capability of the server activation is initialized
|
||||
* an can be passed around. However, the processing of capability
|
||||
* invocations should not happen until activation-using server
|
||||
* is completely initialized. Thus, we wait until the activation
|
||||
* gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
|
||||
*/
|
||||
_delay_start.lock();
|
||||
|
||||
while (!_exit_handler.exit) {
|
||||
|
||||
int opcode = 0;
|
||||
|
||||
srv >> IPC_REPLY_WAIT >> opcode;
|
||||
|
||||
/* set default return value */
|
||||
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
|
||||
|
||||
/* check whether capability's label fits global id */
|
||||
if (((unsigned long)srv.badge()) != _rcv_buf.label()) {
|
||||
PWRN("somebody tries to fake us!");
|
||||
continue;
|
||||
}
|
||||
|
||||
apply(srv.badge(), [&] (Rpc_object_base *obj) {
|
||||
if (!obj) return;
|
||||
|
||||
try {
|
||||
srv.ret(obj->dispatch(opcode, srv, srv));
|
||||
} catch(Blocking_canceled&) { }
|
||||
});
|
||||
}
|
||||
|
||||
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
|
||||
srv << IPC_REPLY;
|
||||
|
||||
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
|
||||
_delay_exit.lock();
|
||||
}
|
||||
@@ -11,8 +11,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__CAP_IP_ALLOC_H_
|
||||
#define _CORE__INCLUDE__CAP_IP_ALLOC_H_
|
||||
#ifndef _CORE__INCLUDE__CAP_ID_ALLOC_H_
|
||||
#define _CORE__INCLUDE__CAP_ID_ALLOC_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_avl.h>
|
||||
@@ -48,4 +48,4 @@ namespace Genode {
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__CAP_IP_ALLOC_H_ */
|
||||
#endif /* _CORE__INCLUDE__CAP_ID_ALLOC_H_ */
|
||||
|
||||
@@ -17,33 +17,35 @@
|
||||
/* Genode includes */
|
||||
#include <base/cap_map.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <cap_session_component.h>
|
||||
/* base-internal includes */
|
||||
#include <base/internal/native_thread.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
class Pd_session_component;
|
||||
|
||||
class Core_cap_index : public Cap_index
|
||||
{
|
||||
private:
|
||||
|
||||
Cap_session_component *_session;
|
||||
Pd_session_component *_session;
|
||||
Platform_thread *_pt;
|
||||
Native_thread _gate;
|
||||
|
||||
public:
|
||||
|
||||
Core_cap_index(Cap_session_component *session = 0,
|
||||
Platform_thread *pt = 0,
|
||||
Native_thread gate = Native_thread() )
|
||||
Core_cap_index(Pd_session_component *session = 0,
|
||||
Platform_thread *pt = 0,
|
||||
Native_thread gate = Native_thread() )
|
||||
: _session(session), _pt(pt), _gate(gate) {}
|
||||
|
||||
Cap_session_component *session() { return _session; }
|
||||
Platform_thread *pt() { return _pt; }
|
||||
Native_thread gate() { return _gate; }
|
||||
Pd_session_component *session() { return _session; }
|
||||
Platform_thread *pt() { return _pt; }
|
||||
Native_thread gate() { return _gate; }
|
||||
|
||||
void session(Cap_session_component* c) { _session = c; }
|
||||
void pt(Platform_thread* t) { _pt = t; }
|
||||
void session(Pd_session_component *c) { _session = c; }
|
||||
void pt(Platform_thread *t) { _pt = t; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -40,13 +40,13 @@ namespace Genode {
|
||||
|
||||
public:
|
||||
|
||||
Native_capability local; /* reference to cap that is mapped */
|
||||
Native_thread_id remote; /* index in cap-space of the other pd */
|
||||
Native_capability local; /* reference to cap that is mapped */
|
||||
Fiasco::l4_cap_idx_t remote; /* index in cap-space of the other pd */
|
||||
|
||||
Cap_mapping(bool alloc=false,
|
||||
Native_thread_id r = Fiasco::L4_INVALID_CAP);
|
||||
Fiasco::l4_cap_idx_t r = Fiasco::L4_INVALID_CAP);
|
||||
Cap_mapping(Native_capability cap,
|
||||
Native_thread_id r = Fiasco::L4_INVALID_CAP);
|
||||
Fiasco::l4_cap_idx_t r = Fiasco::L4_INVALID_CAP);
|
||||
|
||||
/**
|
||||
* Map the cap in local to corresponding task.
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* \brief Capability session service
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-01-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/object_pool.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Cap_session_component : public Rpc_object<Cap_session>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Entry : Object_pool<Entry>::Entry
|
||||
{
|
||||
Entry(Native_capability cap) : Object_pool<Entry>::Entry(cap) {}
|
||||
};
|
||||
|
||||
Object_pool<Entry> _pool;
|
||||
Allocator *_md_alloc;
|
||||
|
||||
public:
|
||||
|
||||
Cap_session_component(Allocator *md_alloc, const char *args)
|
||||
: _md_alloc(md_alloc) {}
|
||||
|
||||
~Cap_session_component();
|
||||
|
||||
void upgrade_ram_quota(size_t ram_quota) { }
|
||||
|
||||
Native_capability alloc(Native_capability ep);
|
||||
|
||||
void free(Native_capability cap);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
|
||||
@@ -1,298 +0,0 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the CPU session/thread interfaces
|
||||
* \author Christian Helmuth
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2006-07-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <base/allocator_guard.h>
|
||||
#include <base/tslab.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <foc_cpu_session/foc_cpu_session.h>
|
||||
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
#include <platform_thread.h>
|
||||
#include <trace/control_area.h>
|
||||
#include <trace/source_registry.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* RPC interface of CPU thread
|
||||
*
|
||||
* We make 'Cpu_thread' a RPC object only to be able to lookup CPU threads
|
||||
* from thread capabilities supplied as arguments to CPU-session functions.
|
||||
* A CPU thread does not provide an actual RPC interface.
|
||||
*/
|
||||
struct Cpu_thread
|
||||
{
|
||||
GENODE_RPC_INTERFACE();
|
||||
};
|
||||
|
||||
|
||||
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
public List<Cpu_thread_component>::Element,
|
||||
public Trace::Source::Info_accessor
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Trace::Session_label Session_label;
|
||||
typedef Trace::Thread_name Thread_name;
|
||||
|
||||
private:
|
||||
|
||||
Session_label const _session_label;
|
||||
Thread_name const _name;
|
||||
Platform_thread _platform_thread;
|
||||
bool _bound; /* pd binding flag */
|
||||
Signal_context_capability _sigh; /* exception handler */
|
||||
unsigned const _trace_control_index;
|
||||
Trace::Source _trace_source;
|
||||
|
||||
public:
|
||||
|
||||
Cpu_thread_component(size_t const weight,
|
||||
size_t const quota,
|
||||
Session_label const &label,
|
||||
Thread_name const &name,
|
||||
unsigned priority, addr_t utcb,
|
||||
Signal_context_capability sigh,
|
||||
unsigned trace_control_index,
|
||||
Trace::Control &trace_control)
|
||||
:
|
||||
_session_label(label), _name(name),
|
||||
_platform_thread(name.string(), priority, utcb), _bound(false),
|
||||
_sigh(sigh), _trace_control_index(trace_control_index),
|
||||
_trace_source(*this, trace_control)
|
||||
{
|
||||
update_exception_sigh();
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
** Trace::Source::Info_accessor interface **
|
||||
********************************************/
|
||||
|
||||
Trace::Source::Info trace_source_info() const
|
||||
{
|
||||
return { _session_label, _name,
|
||||
_platform_thread.execution_time(),
|
||||
_platform_thread.affinity() };
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
** Accessor functions **
|
||||
************************/
|
||||
|
||||
Platform_thread *platform_thread() { return &_platform_thread; }
|
||||
bool bound() const { return _bound; }
|
||||
void bound(bool b) { _bound = b; }
|
||||
Trace::Source *trace_source() { return &_trace_source; }
|
||||
|
||||
size_t weight() const { return Cpu_session::DEFAULT_WEIGHT; }
|
||||
|
||||
void sigh(Signal_context_capability sigh)
|
||||
{
|
||||
_sigh = sigh;
|
||||
update_exception_sigh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate exception handler to platform thread
|
||||
*/
|
||||
void update_exception_sigh();
|
||||
|
||||
/**
|
||||
* Return index within the CPU-session's trace control area
|
||||
*/
|
||||
unsigned trace_control_index() const { return _trace_control_index; }
|
||||
};
|
||||
|
||||
|
||||
class Cpu_session_component : public Rpc_object<Foc_cpu_session>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Cpu_thread_component::Session_label Session_label;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Allocator used for managing the CPU threads associated with the
|
||||
* CPU session
|
||||
*/
|
||||
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
|
||||
|
||||
Session_label _label;
|
||||
Rpc_entrypoint *_session_ep;
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
Pager_entrypoint *_pager_ep;
|
||||
Allocator_guard _md_alloc; /* guarded meta-data allocator */
|
||||
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
|
||||
Lock _thread_alloc_lock; /* protect allocator access */
|
||||
List<Cpu_thread_component> _thread_list;
|
||||
Lock _thread_list_lock; /* protect thread list */
|
||||
unsigned _priority; /* priority of threads
|
||||
created with this
|
||||
session */
|
||||
Affinity::Location _location; /* CPU affinity of this
|
||||
session */
|
||||
Trace::Source_registry &_trace_sources;
|
||||
Trace::Control_area _trace_control_area;
|
||||
|
||||
size_t _weight;
|
||||
size_t _quota;
|
||||
Cpu_session_component * _ref;
|
||||
List<Cpu_session_component> _ref_members;
|
||||
Lock _ref_members_lock;
|
||||
|
||||
void _incr_weight(size_t);
|
||||
void _decr_weight(size_t);
|
||||
size_t _weight_to_quota(size_t) const;
|
||||
void _decr_quota(size_t);
|
||||
void _incr_quota(size_t);
|
||||
void _update_thread_quota(Cpu_thread_component *) const;
|
||||
void _update_each_thread_quota();
|
||||
void _transfer_quota(Cpu_session_component *, size_t);
|
||||
void _insert_ref_member(Cpu_session_component *) { }
|
||||
void _unsync_remove_ref_member(Cpu_session_component *) { }
|
||||
void _remove_ref_member(Cpu_session_component *) { }
|
||||
void _deinit_ref_account();
|
||||
void _deinit_threads();
|
||||
|
||||
/**
|
||||
* Exception handler that will be invoked unless overridden by a
|
||||
* call of 'Cpu_session::exception_handler'.
|
||||
*/
|
||||
Signal_context_capability _default_exception_handler;
|
||||
|
||||
/**
|
||||
* Raw thread-killing functionality
|
||||
*
|
||||
* This function is called from the 'kill_thread' function and
|
||||
* the destructor. Each these functions grab the list lock
|
||||
* by themselves and call this function to perform the actual
|
||||
* killing.
|
||||
*/
|
||||
void _unsynchronized_kill_thread(Thread_capability cap);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Cpu_session_component(Rpc_entrypoint *session_ep,
|
||||
Rpc_entrypoint *thread_ep,
|
||||
Pager_entrypoint *pager_ep,
|
||||
Allocator *md_alloc,
|
||||
Trace::Source_registry &trace_sources,
|
||||
const char *args, Affinity const &affinity,
|
||||
size_t quota);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_session_component();
|
||||
|
||||
/**
|
||||
* Register quota donation at allocator guard
|
||||
*/
|
||||
void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
|
||||
|
||||
|
||||
/***************************
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Thread_capability create_thread(size_t, Name const &, addr_t);
|
||||
Ram_dataspace_capability utcb(Thread_capability thread);
|
||||
void kill_thread(Thread_capability);
|
||||
Thread_capability first();
|
||||
Thread_capability next(Thread_capability);
|
||||
int set_pager(Thread_capability, Pager_capability);
|
||||
int start(Thread_capability, addr_t, addr_t);
|
||||
void pause(Thread_capability thread_cap);
|
||||
void resume(Thread_capability thread_cap);
|
||||
void single_step(Thread_capability thread_cap, bool enable);
|
||||
void cancel_blocking(Thread_capability);
|
||||
int name(Thread_capability, char *, size_t);
|
||||
Thread_state state(Thread_capability);
|
||||
void state(Thread_capability, Thread_state const &);
|
||||
void exception_handler(Thread_capability, Signal_context_capability);
|
||||
Affinity::Space affinity_space() const;
|
||||
void affinity(Thread_capability, Affinity::Location);
|
||||
Dataspace_capability trace_control();
|
||||
unsigned trace_control_index(Thread_capability);
|
||||
Dataspace_capability trace_buffer(Thread_capability);
|
||||
Dataspace_capability trace_policy(Thread_capability);
|
||||
int ref_account(Cpu_session_capability c);
|
||||
int transfer_quota(Cpu_session_capability, size_t);
|
||||
Quota quota() override;
|
||||
|
||||
|
||||
/***********************************
|
||||
** Fiasco.OC specific extensions **
|
||||
***********************************/
|
||||
|
||||
void enable_vcpu(Thread_capability, addr_t);
|
||||
Native_capability native_cap(Thread_capability);
|
||||
Native_capability alloc_irq();
|
||||
};
|
||||
|
||||
|
||||
class Cpu_session_irqs : public Avl_node<Cpu_session_irqs>
|
||||
{
|
||||
private:
|
||||
|
||||
enum { IRQ_MAX = 20 };
|
||||
|
||||
Cpu_session_component* _owner;
|
||||
Native_capability _irqs[IRQ_MAX];
|
||||
unsigned _cnt;
|
||||
|
||||
public:
|
||||
|
||||
Cpu_session_irqs(Cpu_session_component *owner)
|
||||
: _owner(owner), _cnt(0) {}
|
||||
|
||||
bool add(Native_capability irq)
|
||||
{
|
||||
if (_cnt >= (IRQ_MAX - 1))
|
||||
return false;
|
||||
_irqs[_cnt++] = irq;
|
||||
return true;
|
||||
}
|
||||
|
||||
/************************
|
||||
** Avl node interface **
|
||||
************************/
|
||||
|
||||
bool higher(Cpu_session_irqs *c) { return (c->_owner > _owner); }
|
||||
|
||||
Cpu_session_irqs *find_by_session(Cpu_session_component *o)
|
||||
{
|
||||
if (o == _owner) return this;
|
||||
|
||||
Cpu_session_irqs *c = Avl_node<Cpu_session_irqs>::child(o > _owner);
|
||||
return c ? c->find_by_session(o) : 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */
|
||||
66
repos/base-foc/src/core/include/cpu_session_irqs.h
Normal file
66
repos/base-foc/src/core/include/cpu_session_irqs.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* \brief Fiasco.OC-specific implementation of core's CPU service
|
||||
* \author Christian Helmuth
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2006-07-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__CPU_SESSION_IRQS_H_
|
||||
#define _CORE__INCLUDE__CPU_SESSION_IRQS_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_tree.h>
|
||||
|
||||
/* core includes */
|
||||
#include <cpu_session_component.h>
|
||||
|
||||
namespace Genode { class Cpu_session_irqs; }
|
||||
|
||||
|
||||
class Genode::Cpu_session_irqs : public Avl_node<Cpu_session_irqs>
|
||||
{
|
||||
private:
|
||||
|
||||
enum { IRQ_MAX = 20 };
|
||||
|
||||
Cpu_session_component* _owner;
|
||||
Native_capability _irqs[IRQ_MAX];
|
||||
unsigned _cnt;
|
||||
|
||||
public:
|
||||
|
||||
Cpu_session_irqs(Cpu_session_component *owner)
|
||||
: _owner(owner), _cnt(0) {}
|
||||
|
||||
bool add(Native_capability irq)
|
||||
{
|
||||
if (_cnt >= (IRQ_MAX - 1))
|
||||
return false;
|
||||
_irqs[_cnt++] = irq;
|
||||
return true;
|
||||
}
|
||||
|
||||
/************************
|
||||
** Avl node interface **
|
||||
************************/
|
||||
|
||||
bool higher(Cpu_session_irqs *c) { return (c->_owner > _owner); }
|
||||
|
||||
Cpu_session_irqs *find_by_session(Cpu_session_component *o)
|
||||
{
|
||||
if (o == _owner) return this;
|
||||
|
||||
Cpu_session_irqs *c = Avl_node<Cpu_session_irqs>::child(o > _owner);
|
||||
return c ? c->find_by_session(o) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */
|
||||
@@ -23,6 +23,9 @@
|
||||
#include <base/thread_state.h>
|
||||
#include <util/touch.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/native_thread.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/types.h>
|
||||
@@ -169,12 +172,12 @@ namespace Genode {
|
||||
*/
|
||||
unsigned long badge() { return _badge; }
|
||||
|
||||
bool is_write_fault() const { return (_pf_addr & 2); }
|
||||
bool write_fault() const { return (_pf_addr & 2); }
|
||||
|
||||
/**
|
||||
* Return true if last fault was an exception
|
||||
*/
|
||||
bool is_exception() const
|
||||
bool exception() const
|
||||
{
|
||||
return _type == Ipc_pager::EXCEPTION;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef _CORE__INCLUDE__IRQ_OBJECT_H_
|
||||
#define _CORE__INCLUDE__IRQ_OBJECT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
@@ -37,7 +38,7 @@ class Genode::Irq_object
|
||||
|
||||
Signal_context_capability _sig_cap;
|
||||
|
||||
Native_thread _capability() const { return _cap->kcap(); }
|
||||
Fiasco::l4_cap_idx_t _capability() const { return _cap->kcap(); }
|
||||
|
||||
public:
|
||||
|
||||
@@ -57,3 +58,5 @@ class Genode::Irq_object
|
||||
Irq_session::Polarity);
|
||||
void ack_irq();
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_OBJECT_H_ */
|
||||
|
||||
@@ -142,4 +142,3 @@ namespace Genode {
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__MAP_LOCAL_H_ */
|
||||
|
||||
|
||||
46
repos/base-foc/src/core/include/native_cpu_component.h
Normal file
46
repos/base-foc/src/core/include/native_cpu_component.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* \brief Kernel-specific part of the CPU-session interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-01-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/rpc_server.h>
|
||||
#include <foc_native_cpu/foc_native_cpu.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Cpu_session_component;
|
||||
class Native_cpu_component;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Native_cpu_component : public Rpc_object<Foc_native_cpu,
|
||||
Native_cpu_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Cpu_session_component &_cpu_session;
|
||||
Rpc_entrypoint &_thread_ep;
|
||||
|
||||
public:
|
||||
|
||||
Native_cpu_component(Cpu_session_component &, char const *);
|
||||
~Native_cpu_component();
|
||||
|
||||
void enable_vcpu(Thread_capability, addr_t) override;
|
||||
Native_capability native_cap(Thread_capability) override;
|
||||
Native_capability alloc_irq() override;
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_ */
|
||||
45
repos/base-foc/src/core/include/native_pd_component.h
Normal file
45
repos/base-foc/src/core/include/native_pd_component.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* \brief Kernel-specific part of the PD-session interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-01-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__NATIVE_PD_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__NATIVE_PD_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <foc_native_pd/foc_native_pd.h>
|
||||
|
||||
/* core-local includes */
|
||||
#include <rpc_cap_factory.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Pd_session_component;
|
||||
class Native_pd_component;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Native_pd_component : public Rpc_object<Foc_native_pd>
|
||||
{
|
||||
private:
|
||||
|
||||
Pd_session_component &_pd_session;
|
||||
|
||||
public:
|
||||
|
||||
Native_capability task_cap() override;
|
||||
|
||||
Native_pd_component(Pd_session_component &pd, char const *args);
|
||||
|
||||
~Native_pd_component();
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__NATIVE_PD_COMPONENT_H_ */
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the PD session interface
|
||||
* \author Christian Helmuth
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2006-07-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <foc_pd_session/foc_pd_session.h>
|
||||
#include <base/rpc_server.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform_pd.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Pd_session_component : public Rpc_object<Foc_pd_session>
|
||||
{
|
||||
private:
|
||||
|
||||
Platform_pd _pd;
|
||||
Parent_capability _parent;
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
|
||||
public:
|
||||
|
||||
Pd_session_component(Rpc_entrypoint *thread_ep,
|
||||
Allocator *md_alloc, const char *args)
|
||||
: _thread_ep(thread_ep) { }
|
||||
|
||||
/**
|
||||
* Register quota donation at allocator guard
|
||||
*/
|
||||
void upgrade_ram_quota(size_t ram_quota) { }
|
||||
|
||||
|
||||
/**************************
|
||||
** PD session interface **
|
||||
**************************/
|
||||
|
||||
int bind_thread(Thread_capability);
|
||||
int assign_parent(Parent_capability);
|
||||
|
||||
|
||||
/**********************************
|
||||
** Fiasco.OC specific functions **
|
||||
**********************************/
|
||||
|
||||
Native_capability task_cap();
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__PD_SESSION_COMPONENT_H_ */
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <cap_mapping.h>
|
||||
#include <address_space.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack_area.h>
|
||||
|
||||
/* Fiasco.OC includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/consts.h>
|
||||
@@ -48,8 +51,8 @@ namespace Genode {
|
||||
|
||||
addr_t utcb_area_start()
|
||||
{
|
||||
return (Native_config::context_area_virtual_base() +
|
||||
THREAD_MAX * Native_config::context_virtual_size());
|
||||
return stack_area_virtual_base() +
|
||||
THREAD_MAX*stack_virtual_size();
|
||||
}
|
||||
|
||||
Cap_mapping _task;
|
||||
@@ -69,7 +72,7 @@ namespace Genode {
|
||||
/**
|
||||
* Constructor for all tasks except core.
|
||||
*/
|
||||
Platform_pd();
|
||||
Platform_pd(Allocator *, char const *label);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
@@ -78,13 +81,8 @@ namespace Genode {
|
||||
|
||||
/**
|
||||
* Bind thread to protection domain
|
||||
*
|
||||
* \return 0 on success or
|
||||
* -1 if thread ID allocation failed.
|
||||
*
|
||||
* This function allocates the physical L4 thread ID.
|
||||
*/
|
||||
int bind_thread(Platform_thread *thread);
|
||||
bool bind_thread(Platform_thread *thread);
|
||||
|
||||
/**
|
||||
* Unbind thread from protection domain
|
||||
@@ -96,7 +94,7 @@ namespace Genode {
|
||||
/**
|
||||
* Assign parent interface to protection domain
|
||||
*/
|
||||
int assign_parent(Native_capability parent);
|
||||
void assign_parent(Native_capability parent);
|
||||
|
||||
|
||||
/*******************************
|
||||
@@ -112,7 +110,7 @@ namespace Genode {
|
||||
|
||||
/*
|
||||
* On Fiasco.OC, we don't use directed unmap but rely on the
|
||||
* in-kernel mapping database. See 'rm_session_support.cc'.
|
||||
* in-kernel mapping database. See 'region_map_support.cc'.
|
||||
*/
|
||||
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||
};
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
#include <platform_pd.h>
|
||||
#include <cap_session_component.h>
|
||||
#include <cap_mapping.h>
|
||||
#include <address_space.h>
|
||||
|
||||
@@ -43,7 +42,7 @@ namespace Genode {
|
||||
Cap_mapping _gate;
|
||||
Cap_mapping _pager;
|
||||
Cap_mapping _irq;
|
||||
Native_utcb _utcb;
|
||||
addr_t _utcb;
|
||||
char _name[32]; /* thread name that will be
|
||||
registered at the kernel
|
||||
debugger */
|
||||
@@ -65,7 +64,8 @@ namespace Genode {
|
||||
/**
|
||||
* Constructor for non-core threads
|
||||
*/
|
||||
Platform_thread(const char *name, unsigned priority, addr_t);
|
||||
Platform_thread(size_t, const char *name, unsigned priority,
|
||||
Affinity::Location, addr_t);
|
||||
|
||||
/**
|
||||
* Constructor for core main-thread
|
||||
@@ -99,6 +99,11 @@ namespace Genode {
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* Enable/disable single stepping
|
||||
*/
|
||||
void single_step(bool);
|
||||
|
||||
/**
|
||||
* Resume this thread
|
||||
*/
|
||||
@@ -186,7 +191,7 @@ namespace Genode {
|
||||
Cap_mapping& gate() { return _gate; }
|
||||
const char *name() const { return _name; }
|
||||
bool core_thread() const { return _core_thread; }
|
||||
Native_utcb utcb() const { return _utcb; }
|
||||
addr_t utcb() const { return _utcb; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user