diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000000..366b9d892f
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,46 @@
+{
+ "configurations": [
+ {
+ "name": "EalánOS",
+ "includePath": [
+ "${workspaceFolder}/depot/genodelabs/api/libc/**",
+ "${workspaceFolder}/depot/genodelabs/api/stdcxx/**",
+ "${workspaceFolder}/repos/base/**",
+ "${workspaceFolder}/repos/base-nova/**",
+ "${workspaceFolder}/repos/**"
+ ],
+ "defines": [
+ "__GENODE__",
+ "__FreeBSD__=12",
+ "_GLIBCXX_HAVE_MBSTATE_T",
+ "_GLIBCXX_ATOMIC_BUILTINS_4",
+ "_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC"
+ ],
+ "compilerPath": "/usr/local/genode/tool/21.05/bin/genode-x86-g++",
+ "cStandard": "gnu17",
+ "cppStandard": "gnu++17",
+ "intelliSenseMode": "${default}",
+ "compilerArgs": [
+ "-nostdinc",
+ "-m64",
+ "-mcmodel=large",
+ "-MMD",
+ "-MP",
+ "-MT"
+ ],
+ "configurationProvider": "ms-vscode.cmake-tools"
+ },
+ {
+ "name": "Genode",
+ "includePath": [
+ "${workspaceFolder}/**"
+ ],
+ "defines": [],
+ "compilerPath": "/usr/bin/clang",
+ "cStandard": "c17",
+ "cppStandard": "c++14",
+ "intelliSenseMode": "linux-clang-x64"
+ }
+ ],
+ "version": 4
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000..dc2cb39413
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,12 @@
+{
+ "files.associations": {
+ "stop_token": "cpp",
+ "*.tcc": "cpp",
+ "initializer_list": "cpp",
+ "streambuf": "cpp",
+ "tuple": "cpp",
+ "memory": "cpp"
+ },
+ "vscode-as-git-mergetool.settingsAssistantOnStartup": false,
+ "makefile.makeDirectory": "build/x86_64"
+}
\ No newline at end of file
diff --git a/VERSION b/VERSION
index a01c758c18..54de1e741d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-22.05
+22.08
diff --git a/doc/news.txt b/doc/news.txt
index c1f29a5e9b..46f5b2cd18 100644
--- a/doc/news.txt
+++ b/doc/news.txt
@@ -4,6 +4,67 @@
===========
+Sculpt OS release 22.10 | 2022-10-13
+####################################
+
+| Sculpt OS 22.10 is a maintenance release of our Genode-based
+| general-purpose OS. It imposes a new rigid regime to the management of
+| low-level devices, improves USB hotplug support, and comes with numerous
+| performance optimizations.
+
+The just released version 22.10 of the Sculpt operating system bears the fruit
+of our year-long effort to apply the rigidity of Genode's architecture to the
+management of PCI configuration and device interrupts. This sweeping change
+left no single device driver unturned. If we did our job right, you should not
+notice any visible difference from the previous Sculpt version.
+
+However, you should definitely _feel_ a difference when using the new version.
+We put several performance optimizations in place - from accelerated system
+startup, over increased network thoughput, to improved user-interface
+responsiveness. Moreover, we put much emphasis on stressing Sculpt's USB
+hotplug support, which includes the dynamic assignment and revocation of
+USB devices to and from virtual machines.
+
+With respect to available software, Sculpt users can enjoy an updated
+Chromium engine - via the Falkon or Morph web browsers - and an updated
+audio driver based on OpenBSD 7.1.
+
+Sculpt OS 22.10 is available as ready-to-use system image at the
+[https://genode.org/download/sculpt - Sculpt download page] along with
+updated [https://genode.org/documentation/articles/sculpt-22-10 - documentation].
+
+
+Genode OS Framework release 22.08 | 2022-08-31
+##############################################
+
+| The overarching theme of Genode 22.08 is the emerging phone variant of
+| Sculpt OS, touching topics as diverse as USB ECM, Mali-400 GPU, SD-card
+| access, telephony, mobile-data connectivity, the Morph web browser, and a
+| custom user interface. Among the further highlights are new tracing tools,
+| improved network performance USB smart-card support, and VirtIO drivers for
+| RISC-V.
+
+The vision of a Genode-based smart phone is certainly our most ambitious
+undertaking since we created Sculpt OS for the PC. Over the past two years, we
+relentlessly pursued this vision while targeting the PinePhone hardware.
+The scope of work reaches from custom firmware for the system-control
+processor, over kernel development, a staggering variety of device drivers, to
+the user-interface and application level. With Genode 22.08, those efforts
+culminate in a first complete system - a phone variant of Sculpt OS. The
+[https://genode.org/documentation/release-notes/22.08 - release documentation]
+tells the story behind this line of work in great detail.
+
+Beside phone-related topics, the new release features new tooling for
+gathering and analyzing system traces that allow for holistic performance
+studies covering the interplay between components. One particular success
+story of the new trace recorder is a profoundly improved network performance.
+Further highlights are the support for USB smart cards via PKCS#11, VirtIO
+drivers for RISC-V, and the update of Qt5 to version 5.15.2.
+
+For the complete picture, please enjoy the official
+[https:/documentation/release-notes/22.08 - release documentation of version 22.08...]
+
+
Genode OS Framework release 22.05 | 2022-05-31
##############################################
diff --git a/doc/release_notes/22-08.txt b/doc/release_notes/22-08.txt
new file mode 100644
index 0000000000..6b501b28f2
--- /dev/null
+++ b/doc/release_notes/22-08.txt
@@ -0,0 +1,866 @@
+
+
+ ===============================================
+ Release notes for the Genode OS Framework 22.08
+ ===============================================
+
+ Genode Labs
+
+
+
+The overarching topic of version 22.08 is the emerging phone version of the
+Genode-based Sculpt OS, targeting the PinePhone. The immense breadth and depth
+of this line of work presented in Section [Genode coming to the phone]
+touches topics as diverse as telephony, mobile-data connectivity, a custom
+user interface, a mobile web browser, the GPU, SD-card access, USB, and audio
+control.
+
+With the growing sophistication of Genode-based systems, performance
+optimizations come more and more into focus. Aided by the new tools introduced
+in Section [Enhanced tooling for system tracing], we were able to profoundly
+improve the network performance of Genode's user-level network routing
+component. Speaking of optimizations, the current release reduces the CPU
+overhead of our Linux device-driver environment
+(Section [Linux-device-driver environment (DDE Linux)]) and
+improves the responsiveness of GUIs based on Genode's menu-view component
+(Section [Menu-view performance]).
+
+Further topics of the new version reach from our forthcoming platform-driver
+consolidation across PC and ARM-based devices, over the use of USB smart
+cards, to new VirtIO drivers on RISC-V.
+
+
+Genode coming to the phone
+##########################
+
+Our [https://genode.org/about/road-map - road map] for this year states the
+goal of reaching a useful base line of functionality of Genode on the
+PinePhone. This entails the principle ability to use the device as a phone -
+receiving and issuing voice calls - and a mobile internet browser. Once
+reached, this base line of functionality will allow us to routinely use Genode
+on the device ("eating our own dog food"), experience pain points, guide
+optimization efforts towards user-visible areas that matter, and faithfully
+evaluate non-functional aspects like battery lifetime with real-world work
+loads under realistic conditions.
+
+For the Genode-based phone, we pursue the combination of a minimally-complex
+trustworthy base system with a generally untrusted Web browser as application
+runtime. The feature set of the base system corresponds to the bare-bones
+[https://genode.org/download/sculpt - Sculpt OS] extended with appliance-like
+feature-phone functionality. Thanks to Sculpt's rigid component-based
+structure and the overall low complexity, it promises high reliability and
+security. The application runtime is hosted on top of the base system without
+tainting the assurance of the base system. In contrast to the appliance-like
+and rather static feature set of the base system, the application runtime
+anticipates a great variety of modern-day application scenarios, universally
+expected commodity user-interface paradigms, and fast-paced software updates.
+E.g., we aspire the use of WebRTC-based video conferencing via Jitsi as one
+reference scenario.
+
+Since we succeeded in bringing the Chromium web engine - the base technology
+of most modern web browsers - to life as a
+[https://genodians.org/nfeske/2022-01-27-browser-odyssey - native Genode component],
+users of Sculpt OS are able to use a fully featured web browser without
+relying on virtualization. With the use case of the browser on a mobile phone
+in sight, we already ensured that the browser would work on 64-bit ARM
+hardware. However, whereas we could showcase the technical feasibility of
+Chromium on Genode, the practical usability eventually depends on a suitable
+mobile user experience, which was largely disregarded by the desktop-oriented
+Falkon browser that we enabled on Genode.
+
+
+Assessment
+----------
+
+Fortunately, we discovered the Morph web browser while experimenting with
+[https://xnux.eu/p-boot-demo/ - various Linux distributions] on the PinePhone.
+Among the various alternatives to Android, the Ubuntu Touch UI - alongside
+Sailfish OS - stood out for its refined user experience, subjectively.
+The unobtrusive Morph browser as used by default on Ubuntu Touch left a
+particularly good impression on us. To our delight, we found that this
+browser relies on Qt5 and the Chromium web engine as its foundation, both of
+which we already had enabled on Genode. Out of this observation grew the idea
+of reusing the Morph browser as application runtime on our Genode-based phone.
+But we had to consider several risks.
+
+First, would the heaviness of Chromium overwhelm the rather resource-constrained
+PinePhone hardware when executed on Genode? In contrast to Linux, Genode's
+POSIX environment is less sophisticated and - most importantly - does not
+provide the over-provisioning of memory resources. The latter could be a show
+stopper.
+
+Second, the build mechanics of the browser deviate from the beaten track we
+covered so far, specifically the use of QMake. The Morph browser
+unconditionally depends on CMake as build tool. Even though we gathered
+[https://genodians.org/nfeske/2019-11-25-goa - early experiences], with using
+CMake for building Genode executables, we did not attempt using CMake for
+complex Qt5 applications targeting Genode so far.
+
+Finally, we discovered a so-called Ubuntu-Touch-UI toolkit as an
+additional dependency over Qt5. It presumably extends Qt5's QML with
+custom user-interface widgets for mobile user interfaces. In contrast
+to the multi-platform Qt5 framework, Ubuntu Touch generally targets
+Linux only, which raised a number of concerns with respect to hidden
+assumptions on the underlying platform. For example, the expectation
+of a certain service manager, the direct use of the Linux kernel interface,
+or accidentally complex library dependencies.
+
+
+Methodology
+===========
+
+As practiced during our work with bringing the Chromium-based Falkon web
+browser to Genode, we took several intermediate steps to mitigate technical
+risks as far as possible.
+
+Pruning dependencies
+--------------------
+
+The first step was building the Morph browser from source for its regular
+designated target platform, namely Linux. This step allowed us to validate the
+functionality of the browser built from source as opposed to merely testing a
+binary package. During this process, we learned about the mandatory dependence
+on CMake as build tool. We also identified the following library dependencies
+as sources of uncertainty.
+
+*Ubuntu-UI toolkit* is a collection of QML widgets for smartphone apps.
+It is built via QMake and comes with its own set of dependencies.
+We were specifically concerned by QtSystemInfo, QtOrganizer, D-Bus, and
+gettext. Genode has no meaningful equivalent to any of these dependencies.
+The *Ubuntu Themes* dependency comprises graphical assets, used on Ubuntu
+Touch. *Ubuntu-UI extras* extends Qt's feature set by functionality like the
+'TabsBar' QML-Widget introduces additional transitive dependencies
+such as the [https://www.cups.org/ - CUPS printing system] or
+the [https://exiv2.org/ - Exiv2] image metadata library.
+
+Further dependencies worth noting are QNetworkInterface, QtConcurrent, QtDBus,
+QtSystemInfo, unity-action-api, and D-Bus. Those libraries do not exist in
+Genode and may even raise conceptual problems. For example, the D-Bus
+inter-component mechanism on Linux is not in line with Genode's
+capability-based inter-component communication.
+
+With the first manually built executable of Morph created on Linux, we could
+repeatedly remove dependencies piece by piece and validate the functioning of
+the browser after each step. We ultimately reached a point where most of the
+library dependencies could be cut off while the core functionality of the
+browser - the ability to view web pages - stayed intact. The resulting
+minimized version of the Morph browser thereby served as starting point for
+the subsequent porting work to Genode.
+
+Re-targeting to Genode
+----------------------
+
+To stay as close as possible to the original browser, we decided to reuse the
+browser's build system by tweaking the CMake build tool such that the project
+could be cross compiled for Genode, similar to the approach we successfully
+employed for QMake in the past. At first, we targeted Genode/Linux on x86,
+which is still close to the browser's natural environment. Once the first
+version of the browser came to life, we immediately cross-validated the result
+on the 64-bit ARM architecture as this is our primary target. Subsequently, we
+moved away from Linux by moving the browser over to NOVA (on Sculpt) on PC
+hardware as well as our custom base-hw microkernel in order to target the
+actual PinePhone.
+
+[image touch_ui]
+ Ubuntu-Touch UI gallery demo running on Genode
+
+The methodology mirrored in large parts the approach we took for the original
+porting of the Chromium web engine, but it was a much smoother experience
+given that all road blocks we encountered during our Chromium work are solved
+problems by now. Image [touch_ui] shows the browser's underlying
+user-interface tool kit in action, running directly on Genode. Image [morph]
+shows the Morph browser hosted in Genode's window system.
+
+[image morph]
+ Morph browser running on Genode
+
+
+Unexpected caveats
+==================
+
+However, the smooth ride of re-targeting the browser to Genode ended once
+we discovered the extremely poor interactive performance of the browser
+running on Genode. This is in contrast to our prior experience with the
+Chromium-based Falkon browser which achieved comparable performance to Linux.
+
+The performance degradation originated from the Ubuntu-UI toolkit, which
+has a hard dependency on OpenGL despite being built atop the Qt5 framework.
+In several instances, the Ubuntu-UI toolkit accesses the OpenGL context
+directly, which is handled by a software fallback implementation in the
+Mesa library. We found the removal of those offending accesses infeasible
+because this change would cause several widgets appearing incomplete.
+To attain the visual completeness of the user interface, we also had to
+enhance the Genode-specific back end of Qt (QPA). However, even though
+we achieved correctly looking results, the performance of Mesa3D without
+GPU acceleration made the user interface practically unusable, even on
+powerful PC hardware, not speaking of the resource-constrained PinePhone.
+We came to the conclusion that the Morph browser's hard dependency
+on hardware-accelerated graphics cannot be worked around. This realization,
+in turn, spawned the line of work reported in
+Section [Hardware-accelerated graphics].
+
+As another - but arguably much less dramatic - caveat, we found the touch user
+interface behaving strangely in some situations when running on Genode. The
+reason turned out to be a disparity of Genode's notion of touch-release events
+from the expectations of Qt. Whereas Genode's input-event interface does not
+report a positional value of a touch-release event, Qt expects a positional
+value that corresponds to the original touch event. Fortunately, once this
+disparity had been identified, we could easily emulate the expected behavior
+locally in Genode's QPA plugin.
+
+
+Hardware-accelerated graphics
+=============================
+
+As mentioned above, we were taken by surprise by the hard dependency of the
+Morph browser on GPU-accelerated graphics. Even though we have explored the
+principle use of a GPU on an ARM-based platform before, our prior line of work
+was targeting the Vivante GPU of the NXP i.MX8 SoC, which is different from
+the Mali-400 GPU as present in the PinePhone's A64 SoC. Originally, we did not
+plan to deal with the PinePhone's GPU at the current stage. But the
+requirement of the Morph browser abruptly changed our priorities.
+
+As a rapid experiment, we took the challenge to port the Lima driver for the
+Mali-400 GPU from Linux to Genode and combine it with the matching user-level
+driver code of the Mesa library. Even though this experiment was pursued on
+short notice and risky, it was at least a tangible straw. To our delight,
+however, the first functional rapid prototype came to life after merely two
+weeks of work, which is almost an order of magnitude faster than our past
+efforts. The reason of this success is many-fold. First, our recently
+established methodology and tooling for porting Linux device drivers - as
+described in our comprehensive
+[https://genode.org/documentation/genode-platforms-22-05.pdf - Porting Guide] -
+streamlines the formerly labor-intensive grunt work. Second, we greatly
+benefited from our practical experience with GPUs accumulated over the past
+few years. And third, even though the Mali-400 is different from the Vivante
+GPU, the integration into the Linux GPU stack follows very similar patterns,
+unlike Intel GPUs. So we found our existing knowledge largely applicable.
+
+[image glmark2]
+ GLMark2 reference application using the GPU
+
+Following the initial rapid prototype, we successively refined this work to
+the point where the GPU driver became usable for the Morph browser on the
+PinePhone. Thanks to the added driver, the interactive performance got boosted
+to an acceptable level.
+
+
+Mobile data connectivity
+========================
+
+It goes without saying that a web browser requires network connectivity,
+which is a topic we had left unaddressed on the PinePhone until now.
+However, given our
+[https://genode.org/documentation/release-notes/22.05#Telephony - recent line]
+of modem-related work in the context of telephony, we foresaw a low-complexity
+solution to attain mobile data connectivity.
+
+Today's LTE modems offer
+[https://genodians.org/ssumpf/2020-12-04-mbim - QMI or MBIM] protocol support
+in order to configure and handle mobile data connections. Both protocols are
+in binary format and require a separate USB device (called Wireless Mobile
+Communication Device). For Genode, this would mean to add support for this
+device to USB while additionally the QMI or MBIM library would have to be
+ported and adjusted to Genode. For the
+[https://www.quectel.com/product/lte-eg25-g - Quectel EG25 modem]
+in the PinePhone, we found a much simpler solution to handle mobile data
+connections. The modem can be configured to emulate a USB Ethernet device
+([https://en.wikipedia.org/wiki/Ethernet_over_USB - ECM device]).
+In this operational mode, the modem will automatically connect to the carrier
+and register itself as USB Ethernet device at the PinePhone's USB host
+controller. Genode can thereby access the device through the USB networking
+and CDC Ethernet drivers. The modem also offers a DHCP server and will hand
+out a local IP address upon a DHCP request to Genode. Internally the modem
+will use [https://en.wikipedia.org/wiki/Network_address_translation - NAT] in
+order to translate IP requests from Genode to the address received from the
+carrier.
+
+As a prerequisite to conduct this solution, we had to enable a USB
+host-controller driver for the PinePhone. Of course, we took advantage of our
+modern DDE Linux porting approach for this work, which allowed to attain a
+functional USB driver in merely two weeks. This driver must be combined with
+our existing USB Ethernet driver (usb_net) that we swiftly extended to support
+ECM based devices.
+
+With this driver infrastructure in place, the USB network device of the modem
+appears as uplink to Genode's NIC router. The NIC router, in turn,
+successfully obtains a local IP address that is network-translated by the
+modem. At the carrier side, IP network connectivity can be established by
+issuing AT-protocol commands over UART. So the first prototype of the
+low-level network connectivity worked as anticipated. With this practical way
+of keeping the complexity of binary configuration protocols out of the loop,
+we can maintain the low-complexity implementation of telephony and SIM
+configuration via the UART control channel while regarding IP connectivity -
+and the unavoidable complexity of USB - as an entirely complementary feature.
+
+
+Phone flavor of Sculpt OS
+=========================
+
+Seeing the various puzzle pieces of the Morph browser scenario - GPU
+acceleration, data connectivity, the browser itself - coming together, it was
+time for the integration of those pieces into an overall system. The natural
+basis of such a Genode-based system is
+[https://genode.org/download/sculpt - Sculpt OS],
+which complements Genode with universally expected operating-system features
+such as interactive system configuration as well as the installation and
+deployment of software packages.
+
+Sculpt OS was originally designed for PC-based use cases. Its administrative
+user interface is largely mouse and keyboard driven, and network connectivity
+is usually attained by a wired or wireless LAN connection. Although we
+presented a first version of
+[https://fosdem.org/2022/schedule/event/nfeske/ - Sculpt OS on the PinePhone]
+earlier this year, the call for a touch-oriented user interface is more than
+obvious. Hence, we went forward with creating a phone-specific variant
+of Sculpt. Similar to the original Sculpt OS, the system consists of two
+largely isolated domains, the administrative domain called Leitzentrale and
+the domain of user-installed components called desktop. The user can switch
+between both domains at any time using a secure attention key or gesture.
+On the phone, the Leitzentrale domain plays the role of a feature-phone
+appliance that provides the most fundamental device functionality such
+as the interaction with the SIM card, power control, telephony, network
+configuration, storage management, and software installation. We approached
+the concept of the user interface from a clean slate striving for simplicity.
+
+[image sim_pin]
+ Emerging mobile-phone flavor of Sculpt OS
+
+As the first use case, we addressed telephony, displaying incoming calls,
+presenting the options for accepting/rejecting calls, and initiating calls
+using a dial pad. By modelling these scenarios, we could validate the
+user-interface concept of the evolving phone version of Sculpt's Leitzentrale.
+
+
+User interaction with the SIM card
+==================================
+
+The administrative user interface mentioned above must be matched by the
+underlying middleware that talks to the modem. Remember that our
+[https://genode.org/documentation/release-notes/22.05#Telephony - original]
+telephony scenario relied on the manual use of the modem's AT commands.
+We ultimately have to control the modem's control channel by software using an
+AT protocol stack. To bridge this gap with the lowest complexity possible, we
+created a simple AT protocol implementation that is specifically designed for
+Genode's state-driven component model.
+The modem driver - hosting the AT protocol driver - accepts a configuration
+that expresses the desired state (as opposed to desired actions). For example,
+a configuration may look as simple as follows.
+
+!
+!
+!
+
+The AT protocol implementation takes this configuration and the current modem
+state as the basis for determining a sequence of modem commands needed to
+attain the desired state. For example, if the modem is not powered, the driver
+steps through the powering sequence. Or in case the SIM PIN is required, the
+driver supplies the corresponding command to supply the configured PIN.
+
+To allow interactive usage, the driver supports dynamic reconfiguration.
+E.g., to cancel the outbound call of the example above, the configuration
+would be updated with the '' node removed. Given this approach, an
+interactive user interface comes down to generating such simple
+configurations.
+
+Vice versa, the driver exports the modem's state as a state report, which is
+updated whenever the modem state changes. E.g., an incoming call is reflected
+to the consumer of this state report with all information relevant for an
+interactive user interface. For example, the state report entails the power
+state, PIN state, and call states (incoming, outbound, alerting, rejected).
+This design nicely hides the peculiarities of the AT protocol from Genode's
+component interfaces.
+
+At the current stage, with less than 1000 lines of code, the AT protocol
+implementation suffices for basic telephony needs, supporting the interaction
+with the SIM card, managing call states, initiating calls, and driving the
+modem power up and down. It also takes care of establishing the modem
+configuration needed for USB ECM networking.
+
+
+Current state
+=============
+
+The current version of the phone variant of Sculpt OS is able to control the
+power state of the modem, interact with the SIM card (PIN entry), initiate
+phone calls via a dial pad, pick up inbound calls, establish mobile-data
+network connectivity, and deploy a preconfigured application scenario.
+The interactive switching between the base system and the application runtime
+can be triggered at any time by touching the left border of the touch screen.
+
+[image sculpt_pinephone]
+ The runtime graph of the base system (left) reveals the relationships of the
+ Morph browser with other components (right).
+
+This flavor of Sculpt OS evolves in the
+[https://github.com/nfeske/genode-allwinner - genode-allwinner] repository,
+specifically within the _sculpt/_ and _src/app/phone_manager/_ directories.
+The latter asserts the role of Sculpt's _gems/src/app/sculpt_manager_.
+We invite seasoned developers - especially those who are following the
+[https://genodians.org/nfeske/index - Pine-fun article series] - to experiment
+with the new phone variant. It can be built via the following command:
+
+! built/arm_v8a$ make run/sculpt KERNEL=hw BOARD=pinephone SCULPT=phone
+
+For a broader audience, we plan to provide a ready-to-use SD-card image for
+the PinePhone in tandem with the next release of Sculpt OS.
+
+
+Enhanced tooling for system tracing
+###################################
+
+Since release 13.08, Genode features a
+[https://genode.org/documentation/release-notes/13.08#Light-weight_event_tracing - light-weight event-tracing facility]
+that comes in form of core's TRACE service. Up to now, it has merely been used
+for capturing textual trace messages. The two prominent monitor components are
+the
+[https://genode.org/documentation/release-notes/18.02#New_trace-logging_component - trace_logger]
+and the
+[https://genode.org/documentation/release-notes/19.08#Tracing - VFS plugin]
+
+The trace recorder is a new monitor component that is designed for binary trace
+formats. Currently, it supports the Common Trace Format (CTF) and pcapng.
+CTF is a compact and scalable format for storing event traces. It is supported
+by [https://www.eclipse.org/tracecompass/ - TraceCompass], an Eclipse-based
+tool for trace analysis and visualization. Pcapng is a packet-capture format
+used by Wireshark.
+
+In order to support capturing network packets, we added a 'trace_eth_packet()'
+method to Genode's trace-policy API and equipped the NIC router with a
+'trace_packets' option to control packet capturing on domain level. For manual
+instrumentation of components, we also added a 'checkpoint()' method to the
+trace-policy API.
+
+For more details, please refer to the following Genodians article.
+
+:Identifying network-throughput bottlenecks with trace recording:
+
+ [https://genodians.org/jschlatow/2022-08-29-trace-recorder]
+
+
+Base framework and OS-level infrastructure
+##########################################
+
+Networking optimizations
+========================
+
+With the new trace recorder at hand, we took an effort in optimizing Genode's
+network throughput. First, we implemented a benchmark component called
+"nic_perf" that sends and/or receives an infinite stream of UDP packets in
+order to stimulate the involved networking components in separation. As a
+consequence of its central role, we particularly focused on the NIC router as
+a starting point.
+
+As a base line, we took two 'nic_perf' components: one as a sender and the other
+as a receiver. By taking any copying or packet inspection out of the loop, we
+could verify that the packet-stream interface holds up to our expectations with
+respect to attainable throughput. However, as soon as we put a NIC router in
+between, the throughput dropped to approx. 10% of our base line. On older
+ThinkPads, this meant sub-gigabit throughput and on a Cortex-A9 @ 666MHz we
+barely jumped over the 100Mbit mark.
+
+Since we were not able to explain the substantial decrease in packet throughput,
+we investigated with the help of the trace recorder and 'GENODE_LOG_TSC'.
+As it turned out, the NIC router spent most of its time with exception handling
+during routing-rule lookup, which is done for every packet. Since there are
+multiple types of rules, a lookup takes place for every rule type. If no rule
+was found for particular type, an exception was thrown and caught, which
+turned out to be incredibly expensive. We therefore eliminated exceptions from
+common-case code paths, more precisely from rule lookup, from ARP-cache
+lookup, and from packet allocation. The result impressed us with a tripled
+throughput.
+
+Another bottleneck that we identified were frequent 'trigger_once' and
+'elapsed_ms' RPCs. Given that the NIC router only maintains very
+coarse-grained timeouts, such frequent RPCs to the timer seemed finical.
+Sparing the details, we were able to significantly reduce the number of
+these RPCs by relaxing the precision of the NIC router's time keeping.
+
+Along the way, we identified a few more, minor, tweaks:
+
+* We increased the default value of 'max_packets_per_signal' from 32 to 150.
+ This value determines the maximum number of packets that are consumed from an
+ interface at once.
+* We eliminated eager packet-stream signalling from the NIC router to improve
+ batch processing of packets. With this change, packet-stream signals are only
+ emitted once the NIC router processed all available or
+ 'max_packets_per_signal' packets.
+* We implemented incremental checksum update for UDP/TCP according to RFC1071.
+* We discovered and fixed a few corner cases in the packet-stream interface
+ with respect to the signalling.
+* We fixed allocation errors in the 'ipxe_nic_drv' that popped up during high
+ TX load.
+
+In the end, we attained a ~5x speed up (exact values depending on the hardware)
+for the NIC router.
+
+
+Event-filter improvements for touch devices
+===========================================
+
+The phone variant of Sculpt OS calls for a way to trigger certain low-level
+buttons or keys using the touch screen. In particular, the switch between the
+administrative user interface and the runtime system must be possible at any
+time. On the [https://genode.org/download/sculpt - PC version], this switch
+is triggered by pressing F12, which is remapped to KEY_DASHBOARD. Even though
+a physical button could be used on the phone in principle, there are three
+arguments in favor of a virtual key. First, there are only three physical
+buttons available (volume +/- and power) on the PinePhone. Remapping one of
+those buttons to KEY_DASHBOARD deprives the button of its original purpose.
+Second, the force needed for pressing a physical button may impede the
+ergonomics of the device depending on how often the switch is needed. And
+third, the physical buttons require a driver. When enabling a new device, this
+barrier can be nicely sidestepped by a virtual key.
+
+Given this rationale, we extended Genode's event-filter component with a new
+'' filter type. Once added to the filter chain, it triggers an
+artificial key tap (a press event followed by a release event) whenever the
+user touches a preconfigured area on the touch screen. The filter node can
+host any number of '' sub nodes. Each sub node must define a rectangular
+area - using the attributes 'xpos', 'ypos', 'width', and 'height' - and the
+name of the tapped key as 'key' attribute.
+
+!
+!
+! ...
+!
+
+The example above repurposes the 25 left-most pixels of the touch screen as
+dashboard key. When touched, a pair of press and release events is fired at
+once.
+
+
+Menu-view performance
+=====================
+
+The administrative user interface of Sculpt OS is based on Genode's custom
+menu-view component, which renders and updates graphical dialogs based on
+high-level XML descriptions. Up to now, the component operated on Genode's
+GUI-session interface with alpha-channel support. However, the alpha channel
+noticeably impedes the software-rendering performance on lower-end devices
+like the PinePhone. In the latter case, we'd prefer to trade the nice-looking
+alpha blending for a better UI responsiveness.
+
+We have now enhanced the menu-view component with two new optional
+configuration attributes 'opaque' and 'background'. Setting 'opaque' to "yes"
+suppresses the use of the alpha channel at the GUI session. This improves the
+drawing performance by 20% on the PinePhone. The 'background' attribute can be
+specified to define the reset color of the GUI buffer. It alleviates the need
+to create a frame widget for the top level, significantly reducing the costs
+for drawing the background pixels.
+
+Finally, we found that the use of GCC's optimization level -O3 instead of the
+default level -O2 increases the drawing performance on the PinePhone by 30%.
+Combined, those optimizations result in an acceptable user experience of
+Sculpt's administrative user interface on the PinePhone.
+
+
+Device drivers
+##############
+
+USB networking via Ethernet control model (ECM)
+===============================================
+
+To implement mobile data connectivity on the PinePhone
+(Section [Mobile data connectivity]), we added USB host-controller support
+(EHCI) for the Allwinner A64 SoC to Genode by porting the corresponding
+host-controller driver from Linux using our DDE approach. Since our existing
+USB-over-Ethernet
+[https://github.com/genodelabs/genode/tree/master/repos/dde_linux/src/drivers/usb_net - driver]
+on Genode lacked support for the Ethernet Control Model, which is provided by
+the modem, we added support for ECM as well.
+
+
+GPU and Mesa driver for Mali-400
+================================
+
+As mentioned in Section [Genode coming to the phone], we enabled the principle
+ability to use the Mali-400 GPU of the PinePhone under Genode. This support
+entails two parts. The first part is the low-level driver code called Lima
+that normally resides in the Linux kernel. This component provides a GPU
+session interface. We transplanted the driver code to a dedicated Genode
+component, which is hosted at the
+[https://github.com/genodelabs/genode-allwinner - genode-allwinner] repository.
+The second part is the user-level Mesa3D driver stack - hosted at the libports
+repository - that is linked local to the application and uses the GPU session
+to access the GPU.
+
+The combination of both parts was successfully tested on the PinePhone and
+the Pine-A64-LTS V1.2 board. Given that the primary motivation for this
+line of work was our ambition to run the Morph web browser, we disregarded the
+multiplexing of the GPU for now. The GPU driver currently supports only one
+client at a time.
+
+
+SD-card driver for the PinePhone
+================================
+
+In anticipation of running Sculpt OS on the PinePhone, we ported the Linux
+SD/MMC-card driver to Genode. The driver - hosted at the
+[https://github.com/genodelabs/genode-allwinner - genode-allwinner] repository -
+was successfully tested with the PinePhone and Pine-A64LTS V1.2 board. For the
+moment, only SD cards (no eMMC) are supported.
+The provided _a64_sd_card_drv.run_ script illustrates the integration and use
+of the driver.
+
+
+Linux-device-driver environment (DDE Linux)
+===========================================
+
+Tickless idle operation
+-----------------------
+
+The DDE-Linux emulation library and thereby all ported drivers now support
+the NO_HZ_IDLE Linux kernel configuration option, which disables periodic
+timer ticks when ported drivers are idle. With this option, energy and up to
+3% CPU time per driver can be preserved, which becomes significant especially
+if multiple ported drivers are in use in sophisticated scenarios like Sculpt
+OS.
+
+Consistent use of SMP configuration
+-----------------------------------
+
+All kernel threads in the Linux device driver ports are currently mapped to one
+and the same native Genode thread, using cooperative scheduling within the
+emulation environment. Intuitively, it does not make much sense to address
+multi-processing support provided by the original Linux kernel code.
+Nonetheless, the drivers that we ported are normally used in the context of
+SMP-aware Linux kernel configurations only. To not leave the well tested and
+beaten track, we decided to switch on SMP support in all kernel configurations
+we use as porting base.
+
+This especially applies to the Linux drivers within the _repos/pc_
+sub-directory, and the WireGuard port. Other driver ports already used SMP
+support in their configuration.
+
+As a side effect, we removed the insufficient emulation of so called "softirqs"
+formerly used by the non-SMP driver ports, and replaced them with the original
+implementation.
+
+
+Forthcoming platform-driver modernization
+=========================================
+
+During the past year, we switched from board-specific platform driver APIs
+step-by-step to one generic interface. But PC-related drivers still depend on
+the legacy x86-specific platform driver and API, especially to the PCI-related
+part of it.
+
+To finalize the unification and modernization of the platform driver and its
+API, there were still some pieces missing, which we added with the current
+release.
+
+While trying to switch PC-related Linux device driver ports to the new API, we
+recognized that some drivers depend on additional information of the PCI
+configuration space that were not exported so far. Namely, the fields for
+sub-vendor, sub-product, and revision IDs were needed. Moreover, some ported
+drivers use hard-coded indices of PCI base-address registers (BAR) to refer to
+I/O resources of the device.
+
+Therefore, we extended the pci_decode tool to export this additional
+information, and to annotate I/O port ranges and memory attributes with the
+corresponding BAR index. The generic platform driver parses this additional
+information from a given devices ROM, and exports it to the corresponding
+clients accordingly. The correlation between I/O resources and BAR indices is
+only unveiled to clients where the platform driver's policy states that
+physical information has to be provided, like in this example:
+
+!
+!
+!
+!
+! ...
+!
+
+UHCI-specific platform extensions
+---------------------------------
+
+Some device-specific registers are only present within the PCI configuration
+space. For instance UHCI controllers in the PC architecture provide a special
+legacy support register only accessible via the PCI configuration space. This
+register is used to hand over the USB hardware from the BIOS to the operating
+system.
+
+We did not want to pollute the platform API with a lot of device specific
+tweaks nor provide unlimited access to the PCI configuration space to a
+driver. Therefore, we implement the hand-over of the UHCI PCI device in the
+platform driver if available. Moreover, we handle the Intel-specific resume
+register whenever a session to the corresponding UHCI controller is opened.
+
+Intel GPU information from Host Bridge
+--------------------------------------
+
+Some information needed by Intel GPU and framebuffer drivers is derived from
+the Intel Graphics and Controller HUB (GMCH) respectively its control
+register. It is used to calculate the GPU's Global Translation Table (GTT),
+and the stolen memory sizes. Again we do not want to give access to the whole
+configuration space of this sensitive device to either the GPU or the
+framebuffer driver. Instead, the platform driver now detects Intel PCI graphic
+cards, and exports the information found within the GMCH control register to
+the corresponding client as part of the platform session's devices ROM.
+
+Transition of PC drivers
+------------------------
+
+Although there is everything in place now to switch the remaining PC-drivers
+to the generic platform driver and its API, we decided to do this step after
+the current release. This way, we have time to stress-test the drivers during
+our daily use of Genode, the remaining transitional work is planned for the
+upcoming Sculpt OS release instead.
+
+
+Libraries and applications
+##########################
+
+Qt5 and Morph browser
+=====================
+
+As mentioned in Section [Genode coming to the phone], we had to improve
+Genode's Qt support to get the Morph browser to work. This work includes
+added support for building Qt projects with CMake, the addition of missing Qt
+modules like QtGraphicalEffects, and improving the OpenGL support of the QPA
+plugin. The latter was needed for the Ubuntu UI Toolkit to display its widgets
+correctly. Note that this change implies that QtQuick applications now use
+OpenGL by default instead of the QtQuick software rendering fallback back end.
+This can improve the experience when an accelerated GPU driver is available
+but can also slow down a QtQuick application if only the Mesa software driver
+('softpipe') is available on the target platform. In that case, it is possible
+to enforce the use of the software QtQuick renderer by setting the following
+environment variable in the configuration of the application:
+
+!
+
+When we tried to use the free public Jitsi server at [https://meet.jit.si] with
+our ported web browsers, we noticed that our QtWebEngine Chromium version was
+too old and caused issues like a non-working join button and failed WebRTC
+connections. For this reason, we updated our Qt port to the latest version with
+QtWebEngine support on FreeBSD, which at this time is version 5.15.2.
+
+To use this new version, it is necessary to update the Qt5 host tools with the
+'tool/tool_chain_qt5' script.
+
+We also updated the Falkon web browser to the latest version 3.2.0.
+
+Up-to-date Sculpt packages of both the Falkon and Morph browsers for x86_64 are
+available in the 'cproc' depot.
+
+
+USB smart cards via PKCS#11
+===========================
+
+With this release, Genode gains support for accessing USB smart-card devices
+via PKCS#11. This is achieved through a port of the OpenSC PKCS#11 tool that is
+now available as package for the Sculpt OS. A quick look into the features and
+integration of the tool is possible using the new _pkcs11_tool_ run script
+hosted in the [https://github.com/genodelabs/genode-world - genode-world]
+repository. For a more detailed guide to the tool, you may read the
+corresponding Genodians article.
+
+:USB smart cards via PKCS#11:
+
+ [https://genodians.org/m-stein/2022-08-18-pkcs11-tool-1]
+
+
+Sculpt OS improvements
+======================
+
+In addition to the major developments described in
+Section [Genode coming to the phone], Sculpt OS has received several minor
+refinements.
+
+When integrating a
+[https://genode.org/documentation/release-notes/22.02#Framework_for_special-purpose_Sculpt-based_operating_systems - Sculpt-based appliance]
+with a predefined deploy configuration, the _sculpt.run_ script automatically
+adds the required software packages as tar archive to the boot image. However,
+for complex scenarios, it is sometimes desirable to keep the boot image small
+and fetch the packages at runtime over the network. To support such use cases,
+we added the new run-script argument 'DEPOT' with the possible values 'tar'
+(default) and 'omit'. If the latter is specified, the deployed software
+packages are excluded from the boot image and the run script merely prints the
+versions of the required packages. This information can conveniently be used
+as input for publishing the packages.
+
+We added two new packages 'part_block' and 'ext2_fs' that simplify the access
+of multiple block devices and partitions in manually curated deploy
+configurations. The part_block package can be used in Sculpt's
+_/config/deploy_ as follows.
+
+!
+!
+!
+!
+!
+!
+!
+!
+!
+!
+
+It can be combined with the 'ext2_fs' package to access the files stored on a
+particular partition.
+
+!
+!
+!
+!
+!
+!
+!
+!
+!
+!
+
+
+Platforms
+#########
+
+Qemu virtual platform
+=====================
+
+Because more and more architectures on Genode now support VirtIO drivers on
+Qemu (ARMv7, ARMv8, and RISC-V), the generic board name "virt_qemu" did not
+suffice for keeping a clean distinction between the separate architecture
+requirements. Therefore, we decided to make the board name architecture
+specific. The following board names are now supported on base-hw:
+"virt_qemu_arm_v7a", "virt_qemu_arm_v8a", and "virt_qemu_riscv".
+The "virt_qemu" board name was removed.
+
+
+RISC-V
+======
+
+As suggested above Genode's RISC-V support got extended by VirtIO drivers.
+This includes a block driver, a networking driver, keyboard and mouse handling
+as well as basic framebuffer support. This way, it has become possible to test
+interactive and networking scenarios on Genode's RISC-V version using Qemu.
+
+This work was contributed by Piotr Tworek. Thanks a lot!
+
+
+Allwinner A64
+=============
+
+In the
+[https://genode.org/documentation/release-notes/22.05#Custom_system-control_processor__SCP__firmware - previous release],
+we introduced our custom firmware for the PinePhone's system-control processor
+(SCP). We have now generalized the firmware to cover also the Pine-A64-LTS
+board. By establishing our custom SCP firmware as a base line for all A64-based
+boards, we can make our A64 platform driver depend on the SCP for accessing the
+PMIC (power management chip) instead of driving the RSB and PMIC by itself.
+
+
+Build system and tools
+######################
+
+In this release, we improve support for booting Genode/Sculpt on UEFI
+platforms in several aspects. First, the Bender tool gains a more robust
+UEFI-boot detection mechanism while retrieving serial-device parameters. Also,
+the GRUB boot loader was updated to version 2.06 and now keeps lower RAM
+untouched from internal memory allocations, which prevents nasty surprises on
+booting some UEFI devices. And last, our [https://ipxe.org/ - iPXE-based] boot
+option received support for UEFI images when using the following run-tool
+configuration.
+
+! RUN_OPT += --include image/uefi
+! RUN_OPT += --include load/ipxe
+
diff --git a/repos/base-fiasco/recipes/src/base-fiasco/content.mk b/repos/base-fiasco/recipes/src/base-fiasco/content.mk
index 1c494bd998..cc4c522144 100644
--- a/repos/base-fiasco/recipes/src/base-fiasco/content.mk
+++ b/repos/base-fiasco/recipes/src/base-fiasco/content.mk
@@ -21,6 +21,5 @@ content:
for spec in x86_32; do \
mv lib/mk/spec/$$spec/ld-fiasco.mk lib/mk/spec/$$spec/ld.mk; \
done;
- sed -i "s/ld-fiasco/ld/" src/lib/ld/fiasco/target.mk
sed -i "s/fiasco_timer_drv/timer/" src/timer/fiasco/target.mk
diff --git a/repos/base-fiasco/recipes/src/base-fiasco/hash b/repos/base-fiasco/recipes/src/base-fiasco/hash
index e295e18337..f9dac8e5fc 100644
--- a/repos/base-fiasco/recipes/src/base-fiasco/hash
+++ b/repos/base-fiasco/recipes/src/base-fiasco/hash
@@ -1 +1 @@
-2022-05-24 1790ce242c001ed77aab9695f69923a44d1dc1d1
+2022-10-11 1f0607de6493bad0e47b24e66d84474652e8b6be
diff --git a/repos/base-fiasco/src/lib/ld/fiasco/target.mk b/repos/base-fiasco/src/lib/ld/fiasco/target.mk
deleted file mode 100644
index 060986f382..0000000000
--- a/repos/base-fiasco/src/lib/ld/fiasco/target.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = ld-fiasco
-LIBS = ld-fiasco
diff --git a/repos/base-foc/recipes/src/base-foc-imx6q_sabrelite/hash b/repos/base-foc/recipes/src/base-foc-imx6q_sabrelite/hash
index 4746445245..265fd08d89 100644
--- a/repos/base-foc/recipes/src/base-foc-imx6q_sabrelite/hash
+++ b/repos/base-foc/recipes/src/base-foc-imx6q_sabrelite/hash
@@ -1 +1 @@
-2022-05-24 f7900083623a2009d35234c47d2475dea8f6cf53
+2022-10-11 d258920f8664460c78eeea25fafb89eaa5e7adf5
diff --git a/repos/base-foc/recipes/src/base-foc-imx7d_sabre/hash b/repos/base-foc/recipes/src/base-foc-imx7d_sabre/hash
index f276f3e23e..b26ae8d41e 100644
--- a/repos/base-foc/recipes/src/base-foc-imx7d_sabre/hash
+++ b/repos/base-foc/recipes/src/base-foc-imx7d_sabre/hash
@@ -1 +1 @@
-2022-05-24 f7d228f6419c2fc9b1b0faf4ba8d88862ba61e81
+2022-10-11 1c94d29566bccccced246eeaf90702348e2b1a7f
diff --git a/repos/base-foc/recipes/src/base-foc-pbxa9/hash b/repos/base-foc/recipes/src/base-foc-pbxa9/hash
index 9db655430c..51ecc915eb 100644
--- a/repos/base-foc/recipes/src/base-foc-pbxa9/hash
+++ b/repos/base-foc/recipes/src/base-foc-pbxa9/hash
@@ -1 +1 @@
-2022-05-24 391b798b7c1d1b44ff65d855980eb41a8f4a87c1
+2022-10-11 2668fd23d5cbd45b8f632073fc7c155f96ecb848
diff --git a/repos/base-foc/recipes/src/base-foc-pc/hash b/repos/base-foc/recipes/src/base-foc-pc/hash
index 0ae034bc12..56c9910ab6 100644
--- a/repos/base-foc/recipes/src/base-foc-pc/hash
+++ b/repos/base-foc/recipes/src/base-foc-pc/hash
@@ -1 +1 @@
-2022-05-24 79eab679e71dd70803b0e1647a23e2ba86c76f50
+2022-10-11 8da054ff9e4c37895816fd30857b3c42d9e75eb0
diff --git a/repos/base-foc/recipes/src/base-foc-rpi3/hash b/repos/base-foc/recipes/src/base-foc-rpi3/hash
index 4b5f6173ab..e63b5c8e6a 100644
--- a/repos/base-foc/recipes/src/base-foc-rpi3/hash
+++ b/repos/base-foc/recipes/src/base-foc-rpi3/hash
@@ -1 +1 @@
-2022-05-24 7a16aeb081d1392c36d83f526936f17cc9560442
+2022-10-11 f41df6b57d2c4b090a84427e02950df84fb385ad
diff --git a/repos/base-foc/recipes/src/base-foc_content.inc b/repos/base-foc/recipes/src/base-foc_content.inc
index b4b26e44df..7d97f7d1e8 100644
--- a/repos/base-foc/recipes/src/base-foc_content.inc
+++ b/repos/base-foc/recipes/src/base-foc_content.inc
@@ -39,5 +39,4 @@ content:
for spec in x86_32 x86_64 arm arm_64; do \
mv lib/mk/spec/$$spec/ld-foc.mk lib/mk/spec/$$spec/ld.mk; \
done;
- sed -i "s/ld-foc/ld/" src/lib/ld/foc/target.mk
sed -i "s/foc_timer_drv/timer/" src/timer/foc/target.mk
diff --git a/repos/base-foc/src/lib/ld/foc/target.mk b/repos/base-foc/src/lib/ld/foc/target.mk
deleted file mode 100644
index ef4453cc43..0000000000
--- a/repos/base-foc/src/lib/ld/foc/target.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = ld-foc
-LIBS = ld-foc
diff --git a/repos/base-hw/board/virt_qemu/arch b/repos/base-hw/board/virt_qemu_arm_v7a/arch
similarity index 50%
rename from repos/base-hw/board/virt_qemu/arch
rename to repos/base-hw/board/virt_qemu_arm_v7a/arch
index cd8d498319..16c61114d8 100644
--- a/repos/base-hw/board/virt_qemu/arch
+++ b/repos/base-hw/board/virt_qemu_arm_v7a/arch
@@ -1,2 +1 @@
arm_v7a
-arm_v8a
diff --git a/repos/base-hw/board/virt_qemu/image_link_address b/repos/base-hw/board/virt_qemu_arm_v7a/image_link_address
similarity index 100%
rename from repos/base-hw/board/virt_qemu/image_link_address
rename to repos/base-hw/board/virt_qemu_arm_v7a/image_link_address
diff --git a/repos/base-hw/board/virt_qemu_arm_v8a/arch b/repos/base-hw/board/virt_qemu_arm_v8a/arch
new file mode 100644
index 0000000000..ae398b9a2e
--- /dev/null
+++ b/repos/base-hw/board/virt_qemu_arm_v8a/arch
@@ -0,0 +1 @@
+arm_v8a
diff --git a/repos/base-hw/board/virt_qemu_arm_v8a/image_link_address b/repos/base-hw/board/virt_qemu_arm_v8a/image_link_address
new file mode 100644
index 0000000000..f8742e5363
--- /dev/null
+++ b/repos/base-hw/board/virt_qemu_arm_v8a/image_link_address
@@ -0,0 +1 @@
+0x40000000
diff --git a/repos/base-hw/lib/mk/bootstrap-hw.inc b/repos/base-hw/lib/mk/bootstrap-hw.inc
index bdd5310976..f875b26bb3 100644
--- a/repos/base-hw/lib/mk/bootstrap-hw.inc
+++ b/repos/base-hw/lib/mk/bootstrap-hw.inc
@@ -12,6 +12,7 @@ SRC_CC += lib/base/avl_tree.cc
SRC_CC += lib/base/console.cc
SRC_CC += lib/base/elf_binary.cc
SRC_CC += lib/base/heap.cc
+SRC_CC += lib/base/regional_heap.cc
SRC_CC += lib/base/registry.cc
SRC_CC += lib/base/log.cc
SRC_CC += lib/base/output.cc
diff --git a/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu_arm_v7a.mk
similarity index 76%
rename from repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk
rename to repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu_arm_v7a.mk
index d4351334e5..b26a3dc66e 100644
--- a/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk
+++ b/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu_arm_v7a.mk
@@ -1,6 +1,6 @@
-REP_INC_DIR += src/bootstrap/board/virt_qemu
+REP_INC_DIR += src/bootstrap/board/virt_qemu_arm_v7a
-SRC_CC += bootstrap/board/virt_qemu/platform.cc
+SRC_CC += bootstrap/board/virt_qemu_arm_v7a/platform.cc
SRC_CC += bootstrap/spec/arm/arm_v7_cpu.cc
SRC_CC += bootstrap/spec/arm/cortex_a15_cpu.cc
SRC_CC += bootstrap/spec/arm/gicv2.cc
diff --git a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu_arm_v7a.mk
similarity index 93%
rename from repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu.mk
rename to repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu_arm_v7a.mk
index 477b70eb93..e6830f1877 100644
--- a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu.mk
+++ b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu_arm_v7a.mk
@@ -1,4 +1,4 @@
-REP_INC_DIR += src/core/board/virt_qemu
+REP_INC_DIR += src/core/board/virt_qemu_arm_v7a
REP_INC_DIR += src/core/spec/arm/virtualization
# add C++ sources
diff --git a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu_arm_v8a.mk
similarity index 77%
rename from repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk
rename to repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu_arm_v8a.mk
index c6d06d592f..65ac7ac5cb 100644
--- a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk
+++ b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu_arm_v8a.mk
@@ -1,8 +1,8 @@
-REP_INC_DIR += src/bootstrap/board/virt_qemu_64
+REP_INC_DIR += src/bootstrap/board/virt_qemu_arm_v8a
SRC_CC += bootstrap/spec/arm/gicv3.cc
SRC_CC += bootstrap/spec/arm_64/cortex_a53_mmu.cc
-SRC_CC += bootstrap/board/virt_qemu_64/platform.cc
+SRC_CC += bootstrap/board/virt_qemu_arm_v8a/platform.cc
SRC_CC += lib/base/arm_64/kernel/interface.cc
SRC_CC += spec/64bit/memory_map.cc
SRC_S += bootstrap/spec/arm_64/crt0.s
diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu_arm_v8a.mk
similarity index 92%
rename from repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu.mk
rename to repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu_arm_v8a.mk
index 27e337f0fe..41825db29d 100644
--- a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu.mk
+++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu_arm_v8a.mk
@@ -1,4 +1,4 @@
-REP_INC_DIR += src/core/board/virt_qemu_64
+REP_INC_DIR += src/core/board/virt_qemu_arm_v8a
REP_INC_DIR += src/core/spec/arm/virtualization
# add C++ sources
diff --git a/repos/base-hw/lib/mk/timeout-hw.mk b/repos/base-hw/lib/mk/timeout-hw.mk
index aad9ffa127..eabca0ad00 100644
--- a/repos/base-hw/lib/mk/timeout-hw.mk
+++ b/repos/base-hw/lib/mk/timeout-hw.mk
@@ -4,6 +4,6 @@ SRC_CC += timer_connection_time.cc
SRC_CC += hw/timer_connection_timestamp.cc
SRC_CC += duration.cc
-INC_DIR += $(BASE_DIR)/src/include
+REP_INC_DIR += src/include
-vpath % $(BASE_DIR)/src/lib/timeout
+vpath % $(call select_from_repositories,src/lib/timeout)
diff --git a/repos/base-hw/recipes/src/base-hw-imx53_qsb/hash b/repos/base-hw/recipes/src/base-hw-imx53_qsb/hash
index b22493af83..8dbc470141 100644
--- a/repos/base-hw/recipes/src/base-hw-imx53_qsb/hash
+++ b/repos/base-hw/recipes/src/base-hw-imx53_qsb/hash
@@ -1 +1 @@
-2022-05-24 ab1cb582165e76bda4abf27870f44ad7d1ae5b6d
+2022-10-11 50db06fe21eca6c46c9b4bf7fcbc81538ac74f32
diff --git a/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/content.mk b/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/content.mk
index cf571d6154..829317888c 100644
--- a/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/content.mk
+++ b/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/content.mk
@@ -1,4 +1,6 @@
CONTENT += src/core/board/imx53_qsb \
- src/bootstrap/board/imx53_qsb
+ src/bootstrap/board/imx53_qsb \
+ lib/mk/spec/arm_v7/core-hw-imx53_qsb.inc \
+ lib/mk/spec/arm_v7/bootstrap-hw-imx53_qsb.inc
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc
diff --git a/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/hash b/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/hash
index 31bad89aab..6d37391b56 100644
--- a/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/hash
+++ b/repos/base-hw/recipes/src/base-hw-imx53_qsb_tz/hash
@@ -1 +1 @@
-2022-05-24 0fff6ce83b962b3fd54cf6eda0a157cb0cb0c9d5
+2022-10-11 1377d3a2b7afaa265cc5ae6bbd515679be527c40
diff --git a/repos/base-hw/recipes/src/base-hw-imx6q_sabrelite/hash b/repos/base-hw/recipes/src/base-hw-imx6q_sabrelite/hash
index 5259a2354f..00b6238861 100644
--- a/repos/base-hw/recipes/src/base-hw-imx6q_sabrelite/hash
+++ b/repos/base-hw/recipes/src/base-hw-imx6q_sabrelite/hash
@@ -1 +1 @@
-2022-05-24 8c17512664a648eaed876c815ea678770eda3280
+2022-10-11 c32cf899ce00bd69aff5bbd4f7b6b611d2bfa47d
diff --git a/repos/base-hw/recipes/src/base-hw-imx7d_sabre/hash b/repos/base-hw/recipes/src/base-hw-imx7d_sabre/hash
index 31826aea8e..0df81b7f31 100644
--- a/repos/base-hw/recipes/src/base-hw-imx7d_sabre/hash
+++ b/repos/base-hw/recipes/src/base-hw-imx7d_sabre/hash
@@ -1 +1 @@
-2022-05-24 edc396d9bc9a2ebf73590e70c1363020226909be
+2022-10-11 39ff297bc573b8e8bf4f2e6e233bf0b1b21f13af
diff --git a/repos/base-hw/recipes/src/base-hw-nit6_solox/hash b/repos/base-hw/recipes/src/base-hw-nit6_solox/hash
index a2e240820d..59a5a7a695 100644
--- a/repos/base-hw/recipes/src/base-hw-nit6_solox/hash
+++ b/repos/base-hw/recipes/src/base-hw-nit6_solox/hash
@@ -1 +1 @@
-2022-05-24 da90478c4c0b8993041bc59488eedb124e680e78
+2022-10-11 f5456c3ed55b53ccaefee603fdb8d9b1e3ca84ab
diff --git a/repos/base-hw/recipes/src/base-hw-pbxa9/hash b/repos/base-hw/recipes/src/base-hw-pbxa9/hash
index 8842770459..9f9b562e4e 100644
--- a/repos/base-hw/recipes/src/base-hw-pbxa9/hash
+++ b/repos/base-hw/recipes/src/base-hw-pbxa9/hash
@@ -1 +1 @@
-2022-05-24 1b34e317209c48bfc88af6118db32be261ce3e0c
+2022-10-11 de2f50d9164952dbbf6ce76d29abad5d96da8512
diff --git a/repos/base-hw/recipes/src/base-hw-pc/hash b/repos/base-hw/recipes/src/base-hw-pc/hash
index 93f152f935..7518974942 100644
--- a/repos/base-hw/recipes/src/base-hw-pc/hash
+++ b/repos/base-hw/recipes/src/base-hw-pc/hash
@@ -1 +1 @@
-2022-05-24 46e9f88209bbc95228d3882cc0831770315402e4
+2022-10-11 5d72eb4e34f582c06c086345b225cee91ce539cc
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu/content.mk b/repos/base-hw/recipes/src/base-hw-virt_qemu/content.mk
deleted file mode 100644
index 2d331b60be..0000000000
--- a/repos/base-hw/recipes/src/base-hw-virt_qemu/content.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-CONTENT += src/core/board/virt_qemu_64 \
- src/bootstrap/board/virt_qemu_64
-
-include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu/hash b/repos/base-hw/recipes/src/base-hw-virt_qemu/hash
deleted file mode 100644
index 7bb55aaf3c..0000000000
--- a/repos/base-hw/recipes/src/base-hw-virt_qemu/hash
+++ /dev/null
@@ -1 +0,0 @@
-2022-05-24 bb6c39c093a24d2ec4ff1d00e397529c51e95fa7
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/content.mk b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/content.mk
new file mode 100644
index 0000000000..38ce9bebad
--- /dev/null
+++ b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/content.mk
@@ -0,0 +1,4 @@
+CONTENT += src/core/board/virt_qemu_arm_v7a \
+ src/bootstrap/board/virt_qemu_arm_v7a
+
+include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/hash b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/hash
new file mode 100644
index 0000000000..0eecd093ea
--- /dev/null
+++ b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/hash
@@ -0,0 +1 @@
+2022-10-11 70e53c98ef4b3215440efb2ea09e07ff7cd97c4f
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu/used_apis b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/used_apis
similarity index 100%
rename from repos/base-hw/recipes/src/base-hw-virt_qemu/used_apis
rename to repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v7a/used_apis
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/content.mk b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/content.mk
new file mode 100644
index 0000000000..7b0ace030f
--- /dev/null
+++ b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/content.mk
@@ -0,0 +1,4 @@
+CONTENT += src/core/board/virt_qemu_arm_v8a \
+ src/bootstrap/board/virt_qemu_arm_v8a
+
+include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/hash b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/hash
new file mode 100644
index 0000000000..ec4320f9e9
--- /dev/null
+++ b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/hash
@@ -0,0 +1 @@
+2022-10-11 c146d70c9bde3f928110c868a54b8c800beffd79
diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/used_apis b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/used_apis
new file mode 100644
index 0000000000..ed9b772565
--- /dev/null
+++ b/repos/base-hw/recipes/src/base-hw-virt_qemu_arm_v8a/used_apis
@@ -0,0 +1,2 @@
+base-hw
+base
diff --git a/repos/base-hw/recipes/src/base-hw_content.inc b/repos/base-hw/recipes/src/base-hw_content.inc
index f26b8981e6..ee1b9ae2f8 100644
--- a/repos/base-hw/recipes/src/base-hw_content.inc
+++ b/repos/base-hw/recipes/src/base-hw_content.inc
@@ -115,6 +115,12 @@ SRC_LIB_BASE += $(notdir $(wildcard $(BASE_HW_DIR)/src/lib/base/*.cc)) \
$(notdir $(wildcard $(BASE_DIR)/src/lib/base/*.cc)) \
${call selected_content,SRC_LIB_BASE_SPECS}
+SRC_LIB_TIMEOUT += duration.cc \
+ hw/timer_connection_timestamp.cc \
+ timeout.cc \
+ timer_connection.cc \
+ timer_connection_time.cc
+
SRC_LIB_STARTUP += init_main_thread.cc _main.cc \
$(addprefix spec/,${call selected_content,SRC_LIB_STARTUP_SPECS})
@@ -125,15 +131,24 @@ SRC_CORE += $(notdir $(wildcard $(BASE_HW_DIR)/src/core/*.cc)) \
$(addprefix board/,$(BOARD)) \
version.inc target.inc include hw kernel
-LIB_MK := base-hw-common.mk base-hw.mk bootstrap-hw.inc core-hw.inc \
- timeout-hw.mk cxx.mk base.inc base-common.inc startup.inc \
- $(addprefix spec/,${call selected_content,LIB_MK_SPECS})
+# names of the lib/mk/ files to consider for inclusion in the src archive
+LIB_MK_FILES := base-common.inc base-hw-common.mk \
+ base.inc base-hw.mk \
+ bootstrap-hw.inc bootstrap-hw-$(BOARD).inc bootstrap-hw-$(BOARD).mk \
+ core-hw.inc core-hw-$(BOARD).inc core-hw-$(BOARD).mk \
+ startup.inc startup-hw.mk \
+ timeout-hw.mk cxx.mk ld-hw.mk syscall-hw.mk
+
+LIB_MK_DIRS := lib/mk $(addprefix lib/mk/spec/,${call selected_content,LIB_MK_SPECS})
+
+CONTENT += $(foreach D,$(LIB_MK_DIRS),$(addprefix $D/,$(LIB_MK_FILES)))
CONTENT += $(addprefix src/timer/,$(SRC_TIMER)) \
$(addprefix src/include/hw/,$(SRC_INCLUDE_HW)) \
$(addprefix src/bootstrap/,$(SRC_BOOTSTRAP)) \
$(addprefix lib/mk/,$(LIB_MK)) \
$(addprefix src/lib/base/,$(SRC_LIB_BASE)) \
+ $(addprefix src/lib/timeout/,$(SRC_LIB_TIMEOUT)) \
$(addprefix src/lib/startup/,$(SRC_LIB_STARTUP)) \
$(addprefix src/core/,$(SRC_CORE)) \
src/lib/hw src/lib/ld src/lib/cxx \
@@ -180,7 +195,6 @@ generalize_target_names: $(CONTENT)
# apply kernel-agnostic convention of naming the timer and ld.lib.so
for subdir in ${call selected_content,LD_MK_DIRS}; do \
mv $$subdir/ld-hw.mk $$subdir/ld.mk; done
- sed -i "s/ld-hw/ld/" src/lib/ld/hw/target.mk
sed -i "s/hw_timer_drv/timer/" src/timer/hw/target.mk
# supplement BOARD definition that normally comes form the build dir
sed -i "s/\?= unknown/:= $(BOARD)/" src/core/hw/target.mk
@@ -189,5 +203,4 @@ generalize_target_names: $(CONTENT)
sed -i "1aREQUIRES := $(ARCH)" src/core/hw/target.mk
sed -i "1aREQUIRES := $(ARCH)" src/bootstrap/hw/target.mk
sed -i "/REQUIRES/s/hw/hw $(ARCH)/" src/timer/hw/target.mk
- sed -i "1aREQUIRES := $(ARCH)" src/lib/ld/hw/target.mk
diff --git a/repos/base-hw/src/bootstrap/board/virt_qemu/board.h b/repos/base-hw/src/bootstrap/board/virt_qemu_arm_v7a/board.h
similarity index 100%
rename from repos/base-hw/src/bootstrap/board/virt_qemu/board.h
rename to repos/base-hw/src/bootstrap/board/virt_qemu_arm_v7a/board.h
diff --git a/repos/base-hw/src/bootstrap/board/virt_qemu/platform.cc b/repos/base-hw/src/bootstrap/board/virt_qemu_arm_v7a/platform.cc
similarity index 100%
rename from repos/base-hw/src/bootstrap/board/virt_qemu/platform.cc
rename to repos/base-hw/src/bootstrap/board/virt_qemu_arm_v7a/platform.cc
diff --git a/repos/base-hw/src/bootstrap/board/virt_qemu_64/board.h b/repos/base-hw/src/bootstrap/board/virt_qemu_arm_v8a/board.h
similarity index 100%
rename from repos/base-hw/src/bootstrap/board/virt_qemu_64/board.h
rename to repos/base-hw/src/bootstrap/board/virt_qemu_arm_v8a/board.h
diff --git a/repos/base-hw/src/bootstrap/board/virt_qemu_64/platform.cc b/repos/base-hw/src/bootstrap/board/virt_qemu_arm_v8a/platform.cc
similarity index 100%
rename from repos/base-hw/src/bootstrap/board/virt_qemu_64/platform.cc
rename to repos/base-hw/src/bootstrap/board/virt_qemu_arm_v8a/platform.cc
diff --git a/repos/base-hw/src/core/board/virt_qemu/board.h b/repos/base-hw/src/core/board/virt_qemu_arm_v7a/board.h
similarity index 100%
rename from repos/base-hw/src/core/board/virt_qemu/board.h
rename to repos/base-hw/src/core/board/virt_qemu_arm_v7a/board.h
diff --git a/repos/base-hw/src/core/board/virt_qemu_64/board.h b/repos/base-hw/src/core/board/virt_qemu_arm_v8a/board.h
similarity index 100%
rename from repos/base-hw/src/core/board/virt_qemu_64/board.h
rename to repos/base-hw/src/core/board/virt_qemu_arm_v8a/board.h
diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc
index 7840d39acb..cd7e57b5b9 100644
--- a/repos/base-hw/src/core/kernel/cpu.cc
+++ b/repos/base-hw/src/core/kernel/cpu.cc
@@ -109,7 +109,8 @@ Cpu::Idle_thread::Idle_thread(Board::Address_space_id_allocator &addr_space_id_a
Cpu &cpu,
Pd &core_pd)
:
- Thread { addr_space_id_alloc, user_irq_pool, cpu_pool, core_pd, "idle" }
+ Thread { addr_space_id_alloc, user_irq_pool, cpu_pool, core_pd,
+ Cpu_priority::min(), 0, "idle", Thread::IDLE }
{
regs->ip = (addr_t)&idle_thread_main;
@@ -120,14 +121,9 @@ Cpu::Idle_thread::Idle_thread(Board::Address_space_id_allocator &addr_space_id_a
void Cpu::schedule(Job * const job)
{
- if (_id == executing_id())
- _scheduler.ready(job->share());
- else {
- _scheduler.ready_check(job->share());
-
- if (_scheduler.need_to_schedule())
- trigger_ip_interrupt();
- }
+ _scheduler.ready(job->share());
+ if (_id != executing_id() && _scheduler.need_to_schedule())
+ trigger_ip_interrupt();
}
diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.cc b/repos/base-hw/src/core/kernel/cpu_scheduler.cc
index a9ac614e5d..b56d771656 100644
--- a/repos/base-hw/src/core/kernel/cpu_scheduler.cc
+++ b/repos/base-hw/src/core/kernel/cpu_scheduler.cc
@@ -191,45 +191,17 @@ void Cpu_scheduler::update(time_t time)
}
-void Cpu_scheduler::ready_check(Share &s1)
-{
- assert(_head);
-
- ready(s1);
-
- if (_need_to_schedule)
- return;
-
- Share * s2 = _head;
- if (!s1._claim) {
- _need_to_schedule = s2 == &_idle;
- } else if (!_head_claims) {
- _need_to_schedule = true;
- } else if (s1._prio != s2->_prio) {
- _need_to_schedule = s1._prio > s2->_prio;
- } else {
- for (
- ; s2 && s2 != &s1;
- s2 =
- Double_list::next(&s2->_claim_item) != nullptr ?
- &Double_list::next(&s2->_claim_item)->payload() :
- nullptr) ;
-
- _need_to_schedule = !s2;
- }
-}
-
-
void Cpu_scheduler::ready(Share &s)
{
assert(!s._ready && &s != &_idle);
- _need_to_schedule = true;
-
s._ready = 1;
s._fill = _fill;
_fills.insert_tail(&s._fill_item);
+ if (_head == &_idle)
+ _need_to_schedule = true;
+
if (!s._quota)
return;
@@ -239,6 +211,28 @@ void Cpu_scheduler::ready(Share &s)
_rcl[s._prio].insert_head(&s._claim_item);
else
_rcl[s._prio].insert_tail(&s._claim_item);
+
+ /*
+ * Check whether we need to re-schedule
+ */
+ if (_need_to_schedule)
+ return;
+
+ /* current head has no quota left */
+ if (!_head_claims) {
+ _need_to_schedule = true;
+ return;
+ }
+
+ /* if current head has different priority */
+ if (s._prio != _head->_prio) {
+ _need_to_schedule = s._prio > _head->_prio;
+ return;
+ }
+
+ /* if current head has same priority, the ready share gets active */
+ if (s._claim)
+ _need_to_schedule = true;
}
@@ -246,7 +240,8 @@ void Cpu_scheduler::unready(Share &s)
{
assert(s._ready && &s != &_idle);
- _need_to_schedule = true;
+ if (&s == _head)
+ _need_to_schedule = true;
s._ready = 0;
_fills.remove(&s._fill_item);
@@ -270,21 +265,15 @@ void Cpu_scheduler::remove(Share &s)
{
assert(&s != &_idle);
- _need_to_schedule = true;
+ if (s._ready) unready(s);
if (&s == _head)
_head = nullptr;
- if (s._ready)
- _fills.remove(&s._fill_item);
-
if (!s._quota)
return;
- if (s._ready)
- _rcl[s._prio].remove(&s._claim_item);
- else
- _ucl[s._prio].remove(&s._claim_item);
+ _ucl[s._prio].remove(&s._claim_item);
}
@@ -292,8 +281,6 @@ void Cpu_scheduler::insert(Share &s)
{
assert(!s._ready);
- _need_to_schedule = true;
-
if (!s._quota)
return;
diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.h b/repos/base-hw/src/core/kernel/cpu_scheduler.h
index ad8624a257..70e921f44c 100644
--- a/repos/base-hw/src/core/kernel/cpu_scheduler.h
+++ b/repos/base-hw/src/core/kernel/cpu_scheduler.h
@@ -180,15 +180,10 @@ class Kernel::Cpu_scheduler
void timeout() { _need_to_schedule = true; }
/**
- * Update head according to the consumed time
+ * Update head according to the current (absolute) time
*/
void update(time_t time);
- /**
- * Set 's1' ready and return wether this outdates current head
- */
- void ready_check(Share &s1);
-
/**
* Set share 's' ready
*/
diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc
index 0d2e9227e7..a5f3b37593 100644
--- a/repos/base-hw/src/core/kernel/thread.cc
+++ b/repos/base-hw/src/core/kernel/thread.cc
@@ -329,6 +329,23 @@ void Thread::_call_start_thread()
/* join protection domain */
thread._pd = (Pd *) user_arg_3();
thread._ipc_init(*(Native_utcb *)user_arg_4(), *this);
+
+ /*
+ * Sanity check core threads!
+ *
+ * Currently, the model assumes that there is only one core
+ * entrypoint, which serves requests, and which can destroy
+ * threads and pds. If this changes, we have to inform all
+ * cpus about pd destructions to remove their page-tables
+ * from the hardware in case that a core-thread running with
+ * that same pd is currently active. Therefore, warn if the
+ * semantic changes, and additional core threads are started
+ * across cpu cores.
+ */
+ if (thread._pd == &_core_pd && cpu.id() != _cpu_pool.primary_cpu().id())
+ Genode::raw("Error: do not start core threads"
+ " on CPU cores different than boot cpu");
+
thread._become_active();
}
@@ -369,7 +386,7 @@ void Thread::_call_restart_thread()
Thread &thread = *thread_ptr;
- if (!_core && (&pd() != &thread.pd())) {
+ if (_type == USER && (&pd() != &thread.pd())) {
raw(*this, ": failed to lookup thread ", (unsigned)user_arg_1(),
" to restart it");
_die();
@@ -447,6 +464,18 @@ void Thread::_call_delete_thread()
}
+void Thread::_call_delete_pd()
+{
+ Genode::Kernel_object & pd =
+ *(Genode::Kernel_object*)user_arg_1();
+
+ if (_cpu->active(pd->mmu_regs))
+ _cpu->switch_to(_core_pd.mmu_regs);
+
+ _call_delete();
+}
+
+
void Thread::_call_await_request_msg()
{
if (_ipc_node.can_await_request()) {
@@ -793,7 +822,7 @@ void Thread::_call()
case call_id_pause_vm(): _call_pause_vm(); return;
default:
/* check wether this is a core thread */
- if (!_core) {
+ if (_type != CORE) {
Genode::raw(*this, ": not entitled to do kernel call");
_die();
return;
@@ -805,7 +834,7 @@ void Thread::_call()
_call_new(_addr_space_id_alloc, _user_irq_pool, _cpu_pool,
_core_pd, (unsigned) user_arg_2(),
(unsigned) _core_to_kernel_quota(user_arg_3()),
- (char const *) user_arg_4());
+ (char const *) user_arg_4(), USER);
return;
case call_id_new_core_thread():
_call_new(_addr_space_id_alloc, _user_irq_pool, _cpu_pool,
@@ -822,7 +851,7 @@ void Thread::_call()
*(Genode::Platform_pd *) user_arg_3(),
_addr_space_id_alloc);
return;
- case call_id_delete_pd(): _call_delete(); return;
+ case call_id_delete_pd(): _call_delete_pd(); return;
case call_id_new_signal_receiver(): _call_new(); return;
case call_id_new_signal_context():
_call_new(*(Signal_receiver*) user_arg_2(), user_arg_3());
@@ -857,7 +886,7 @@ void Thread::_mmu_exception()
return;
}
- if (_core)
+ if (_type != USER)
Genode::raw(*this, " raised a fault, which should never happen ",
_fault);
@@ -874,7 +903,7 @@ Thread::Thread(Board::Address_space_id_allocator &addr_space_id_alloc,
unsigned const priority,
unsigned const quota,
char const *const label,
- bool core)
+ Type type)
:
Kernel::Object { *this },
Cpu_job { priority, quota },
@@ -885,8 +914,8 @@ Thread::Thread(Board::Address_space_id_allocator &addr_space_id_alloc,
_ipc_node { *this },
_state { AWAITS_START },
_label { label },
- _core { core },
- regs { core }
+ _type { type },
+ regs { type != USER }
{ }
diff --git a/repos/base-hw/src/core/kernel/thread.h b/repos/base-hw/src/core/kernel/thread.h
index f7516a6ba9..93e45c3303 100644
--- a/repos/base-hw/src/core/kernel/thread.h
+++ b/repos/base-hw/src/core/kernel/thread.h
@@ -57,6 +57,10 @@ struct Kernel::Thread_fault
*/
class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
{
+ public:
+
+ enum Type { USER, CORE, IDLE };
+
private:
/*
@@ -149,7 +153,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
capid_t _timeout_sigid { 0 };
bool _paused { false };
bool _cancel_next_await_signal { false };
- bool const _core { false };
+ Type const _type;
Genode::Constructible _tlb_invalidation {};
Genode::Constructible _destroy {};
@@ -230,6 +234,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
void _call_restart_thread();
void _call_yield_thread();
void _call_delete_thread();
+ void _call_delete_pd();
void _call_await_request_msg();
void _call_send_request_msg();
void _call_send_reply_msg();
@@ -301,7 +306,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
unsigned const priority,
unsigned const quota,
char const *const label,
- bool core = false);
+ Type const type);
/**
* Constructor for core/kernel thread
@@ -315,7 +320,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
char const *const label)
:
Thread(addr_space_id_alloc, user_irq_pool, cpu_pool, core_pd,
- Cpu_priority::min(), 0, label, true)
+ Cpu_priority::min(), 0, label, CORE)
{ }
~Thread();
@@ -432,6 +437,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
char const * label() const { return _label; }
Thread_fault fault() const { return _fault; }
Genode::Native_utcb *utcb() { return _utcb; }
+ Type type() const { return _type; }
Pd &pd() const
{
diff --git a/repos/base-hw/src/core/kernel/vm.h b/repos/base-hw/src/core/kernel/vm.h
index bc7301e577..06a069a743 100644
--- a/repos/base-hw/src/core/kernel/vm.h
+++ b/repos/base-hw/src/core/kernel/vm.h
@@ -77,6 +77,8 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job
Kernel::Signal_context & context,
Identity & id);
+ ~Vm();
+
/**
* Inject an interrupt to this VM
*
diff --git a/repos/base-hw/src/core/spec/arm/cortex_a9_private_timer.cc b/repos/base-hw/src/core/spec/arm/cortex_a9_private_timer.cc
index 5ad0ced3f4..d2bf7dc4b4 100644
--- a/repos/base-hw/src/core/spec/arm/cortex_a9_private_timer.cc
+++ b/repos/base-hw/src/core/spec/arm/cortex_a9_private_timer.cc
@@ -22,13 +22,17 @@
using namespace Genode;
using namespace Kernel;
-using Device = Board::Timer;
+
+using Device = Board::Timer;
+using counter_t = Board::Timer::Counter::access_t;
enum {
TICS_PER_MS =
Board::CORTEX_A9_PRIVATE_TIMER_CLK /
- Board::CORTEX_A9_PRIVATE_TIMER_DIV / 1000
+ Board::CORTEX_A9_PRIVATE_TIMER_DIV / 1000,
+
+ MAX_COUNTER_VAL = ~(counter_t)0
};
@@ -79,12 +83,33 @@ time_t Timer::us_to_ticks(time_t const us) const {
time_t Timer::_duration() const
{
- Device::Counter::access_t last = _last_timeout_duration;
- Device::Counter::access_t cnt = _device.read();
- Device::Counter::access_t ret = (_device.read())
- ? _max_value() - cnt + last : last - cnt;
- return ret;
+ counter_t const start_counter_val { (counter_t)_last_timeout_duration };
+ counter_t const curr_counter_val { _device.read() };
+
+ /*
+ * Calculate result depending on whether the counter already wrapped or
+ * not. See the comment in the implementation of '_max_value' for an
+ * explanation why this comparison is done instead of checking the IRQ
+ * status and why it is sufficient.
+ */
+ if (curr_counter_val > start_counter_val)
+ return start_counter_val + (MAX_COUNTER_VAL - curr_counter_val);
+
+ return start_counter_val - curr_counter_val;
}
-time_t Timer::_max_value() const { return 0xfffffffe; }
+time_t Timer::_max_value() const
+{
+ /*
+ * We propagate a max timeout value far lower than the one required
+ * by the hardware. This is because on some platforms (Qemu 4.2.1 PBXA9),
+ * the IRQ status register is not reliable. Sometimes, it indicates an IRQ
+ * too early, i.e., shortly before the counter wraps. Therefore we have to
+ * accomplish wrap detection via counter comparison only. Therefore, we
+ * have to make sure that we always read out the counter before it hits
+ * the max timout value again. And, therefore, the max timeout value has
+ * to be far away from the first value the counter has after wrapping.
+ */
+ return MAX_COUNTER_VAL >> 1;
+}
diff --git a/repos/base-hw/src/core/spec/arm/cpu.cc b/repos/base-hw/src/core/spec/arm/cpu.cc
index f0a7fa4ea8..7c8c722e31 100644
--- a/repos/base-hw/src/core/spec/arm/cpu.cc
+++ b/repos/base-hw/src/core/spec/arm/cpu.cc
@@ -87,24 +87,25 @@ void Arm_cpu::mmu_fault_status(Fsr::access_t fsr, Thread_fault & fault)
}
-void Arm_cpu::switch_to(Arm_cpu::Context&, Arm_cpu::Mmu_context & o)
+bool Arm_cpu::active(Arm_cpu::Mmu_context & ctx)
{
- if (o.cidr == 0) return;
+ return (Cidr::read() == ctx.cidr);
+}
- Cidr::access_t cidr = Cidr::read();
- if (cidr != o.cidr) {
- /**
- * First switch to global mappings only to prevent
- * that wrong branch predicts result due to ASID
- * and Page-Table not being in sync (see ARM RM B 3.10.4)
- */
- Cidr::write(0);
- Cpu::synchronization_barrier();
- Ttbr0::write(o.ttbr0);
- Cpu::synchronization_barrier();
- Cidr::write(o.cidr);
- Cpu::synchronization_barrier();
- }
+
+void Arm_cpu::switch_to(Arm_cpu::Mmu_context & ctx)
+{
+ /**
+ * First switch to global mappings only to prevent
+ * that wrong branch predicts result due to ASID
+ * and Page-Table not being in sync (see ARM RM B 3.10.4)
+ */
+ Cidr::write(0);
+ Cpu::synchronization_barrier();
+ Ttbr0::write(ctx.ttbr0);
+ Cpu::synchronization_barrier();
+ Cidr::write(ctx.cidr);
+ Cpu::synchronization_barrier();
}
diff --git a/repos/base-hw/src/core/spec/arm/cpu_support.h b/repos/base-hw/src/core/spec/arm/cpu_support.h
index bba89ce42a..33d63848be 100644
--- a/repos/base-hw/src/core/spec/arm/cpu_support.h
+++ b/repos/base-hw/src/core/spec/arm/cpu_support.h
@@ -104,7 +104,8 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
else Tlbiall::write(0);
}
- void switch_to(Context&, Mmu_context & o);
+ bool active(Mmu_context &);
+ void switch_to(Mmu_context &);
static void mmu_fault(Context & c, Kernel::Thread_fault & fault);
static void mmu_fault_status(Fsr::access_t fsr,
diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread.cc b/repos/base-hw/src/core/spec/arm/kernel/thread.cc
index efc67e510a..838a730c79 100644
--- a/repos/base-hw/src/core/spec/arm/kernel/thread.cc
+++ b/repos/base-hw/src/core/spec/arm/kernel/thread.cc
@@ -67,7 +67,8 @@ void Kernel::Thread::Tlb_invalidation::execute() { };
void Thread::proceed(Cpu & cpu)
{
- cpu.switch_to(*regs, pd().mmu_regs);
+ if (!cpu.active(pd().mmu_regs) && type() != CORE)
+ cpu.switch_to(pd().mmu_regs);
regs->cpu_exception = cpu.stack_start();
kernel_to_user_context_switch((static_cast(&*regs)),
diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
index 968786b6d2..e6cc8f2d00 100644
--- a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
+++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
@@ -38,6 +38,9 @@ Vm::Vm(Irq::Pool & user_irq_pool,
}
+Vm::~Vm() {}
+
+
void Vm::exception(Cpu & cpu)
{
switch(_state.cpu_exception) {
diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s b/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s
index 837483f817..e2808a1670 100644
--- a/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s
+++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s
@@ -15,7 +15,7 @@
push { r0 }
mrc p15, 4, r0, c1, c1, 0 /* read HCR register */
tst r0, #1 /* check VM bit */
- beq _host_to_vm
+ beq _from_host
mov r0, #\exception_type
b _vm_to_host
.endm /* _vm_exit */
@@ -47,10 +47,27 @@ _vt_dab_entry: _vm_exit 5
_vt_irq_entry: _vm_exit 6
_vt_trp_entry: _vm_exit 8
-_host_to_vm:
+_from_host:
+ pop { r0 }
+ cmp r0, #0
+ beq _to_vm
+ cmp r0, #1
+ beq _invalidate_tlb
+ eret
+
+
+_invalidate_tlb:
+ push { r3, r4 }
+ mrrc p15, 6, r3, r4, c2 /* save VTTBR */
+ mcrr p15, 6, r1, r2, c2 /* write VTTBR */
+ mcr p15, 0, r0, c8, c3, 0 /* TLBIALLIS */
+ mcrr p15, 6, r3, r4, c2 /* restore VTTBR */
+ eret
+
+_to_vm:
push { r1 }
- ldr r0, [sp, #1*4]
- add r0, r0, #13*4
+ push { r2 }
+ add r0, r1, #13*4
ldmia r0!, { r1-r5 }
msr sp_usr, r1
mov lr, r2
@@ -115,6 +132,7 @@ _host_to_vm:
ldmia r0, {r0-r12} /* load vm's r0-r12 */
eret
+
_vm_to_host:
push { r0 } /* push cpu excep. */
ldr r0, [sp, #3*4] /* load vm state ptr */
@@ -218,6 +236,7 @@ _vm_to_host:
/* host kernel must jump to this point to switch to a vm */
-.global hypervisor_enter_vm
-hypervisor_enter_vm:
+.global hypervisor_call
+hypervisor_call:
hvc #0
+ bx lr
diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/hypervisor.h b/repos/base-hw/src/core/spec/arm_v7/virtualization/hypervisor.h
new file mode 100644
index 0000000000..d9935902d6
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/hypervisor.h
@@ -0,0 +1,55 @@
+/*
+ * \brief Interface between kernel and hypervisor
+ * \author Stefan Kalkowski
+ * \date 2022-06-13
+ */
+
+/*
+ * Copyright (C) 2022 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _SPEC__ARM_V7__VIRTUALIZATION_HYPERVISOR_H_
+#define _SPEC__ARM_V7__VIRTUALIZATION_HYPERVISOR_H_
+
+#include
+#include
+
+namespace Hypervisor {
+
+ struct Host_context;
+
+ enum Call_number {
+ WORLD_SWITCH = 0,
+ TLB_INVALIDATE = 1,
+ };
+
+ using Call_arg = Genode::umword_t;
+ using Call_ret = Genode::umword_t;
+
+ extern "C"
+ Call_ret hypervisor_call(Call_arg call_id,
+ Call_arg arg0,
+ Call_arg arg1);
+
+
+ inline void invalidate_tlb(Genode::uint64_t vttbr)
+ {
+ hypervisor_call(TLB_INVALIDATE,
+ (vttbr & 0xffffffff),
+ ((vttbr >> 32U) & 0xffffffff));
+ }
+
+
+ inline void switch_world(Genode::Vm_state & vm_state,
+ Host_context & host_state)
+ {
+ hypervisor_call(WORLD_SWITCH,
+ (Call_arg)&vm_state,
+ (Call_arg)&host_state);
+ }
+}
+
+#endif /* _SPEC__ARM_V7__VIRTUALIZATION_HYPERVISOR_H_ */
diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc
index d73b76a22e..416110121e 100644
--- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc
+++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
namespace Kernel {
@@ -41,7 +42,7 @@ namespace Kernel {
using namespace Kernel;
-struct Host_context
+struct Hypervisor::Host_context
{
Cpu::Ttbr_64bit::access_t vttbr;
Cpu::Hcr::access_t hcr;
@@ -61,15 +62,13 @@ struct Host_context
} vt_host_context;
-extern "C" void hypervisor_enter_vm(Genode::Vm_state&, Host_context&);
-
-
-static Host_context & host_context(Cpu & cpu)
+static Hypervisor::Host_context & host_context(Cpu & cpu)
{
- static Genode::Constructible host_context[NR_OF_CPUS];
+ static Genode::Constructible
+ host_context[NR_OF_CPUS];
if (!host_context[cpu.id()].constructed()) {
host_context[cpu.id()].construct();
- Host_context & c = *host_context[cpu.id()];
+ Hypervisor::Host_context & c = *host_context[cpu.id()];
c.sp = cpu.stack_start();
c.ttbr0 = Cpu::Ttbr0_64bit::read();
c.ttbr1 = Cpu::Ttbr1_64bit::read();
@@ -152,6 +151,15 @@ Kernel::Vm::Vm(Irq::Pool & user_irq_pool,
}
+Kernel::Vm::~Vm()
+{
+ Cpu::Ttbr_64bit::access_t vttbr =
+ Cpu::Ttbr_64bit::Ba::masked((Cpu::Ttbr_64bit::access_t)_id.table);
+ Cpu::Ttbr_64bit::Asid::set(vttbr, _id.id);
+ Hypervisor::invalidate_tlb(vttbr);
+}
+
+
void Kernel::Vm::exception(Cpu & cpu)
{
switch(_state.cpu_exception) {
@@ -190,7 +198,7 @@ void Kernel::Vm::proceed(Cpu & cpu)
_state.esr_el2 = Cpu::Hstr::init();
_state.hpfar_el2 = Cpu::Hcr::init();
- hypervisor_enter_vm(_state, host_context(cpu));
+ Hypervisor::switch_world(_state, host_context(cpu));
}
diff --git a/repos/base-hw/src/core/spec/arm_v8/cpu.cc b/repos/base-hw/src/core/spec/arm_v8/cpu.cc
index a06e142f1b..617b7fd70b 100644
--- a/repos/base-hw/src/core/spec/arm_v8/cpu.cc
+++ b/repos/base-hw/src/core/spec/arm_v8/cpu.cc
@@ -26,12 +26,15 @@ Genode::Cpu::Context::Context(bool privileged)
}
-void Genode::Cpu::switch_to(Context&, Mmu_context & mmu_context)
+bool Genode::Cpu::active(Mmu_context & mmu_context)
{
- if (mmu_context.id() == 0) return;
+ return (mmu_context.id() == Ttbr::Asid::get(Ttbr0_el1::read()));
+}
- if (mmu_context.id() != Ttbr::Asid::get(Ttbr0_el1::read()))
- Ttbr0_el1::write(mmu_context.ttbr);
+
+void Genode::Cpu::switch_to(Mmu_context & mmu_context)
+{
+ Ttbr0_el1::write(mmu_context.ttbr);
}
diff --git a/repos/base-hw/src/core/spec/arm_v8/cpu.h b/repos/base-hw/src/core/spec/arm_v8/cpu.h
index a9ca159ea3..b9ff4dbde6 100644
--- a/repos/base-hw/src/core/spec/arm_v8/cpu.h
+++ b/repos/base-hw/src/core/spec/arm_v8/cpu.h
@@ -99,7 +99,8 @@ struct Genode::Cpu : Hw::Arm_64_cpu
return Ttbr::Asid::get(ttbr) & 0xffff; }
};
- void switch_to(Context&, Mmu_context &);
+ bool active(Mmu_context &);
+ void switch_to(Mmu_context &);
static void mmu_fault(Context &, Kernel::Thread_fault &);
diff --git a/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc b/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc
index e3bb8df148..17e431043c 100644
--- a/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc
+++ b/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc
@@ -55,6 +55,16 @@ void Thread::exception(Cpu & cpu)
" ISS=", Cpu::Esr::Iss::get(esr),
" ip=", (void*)regs->ip);
};
+
+ /*
+ * If the machine exception is caused by a non-privileged
+ * component, mark it dead, and continue execution.
+ */
+ if (regs->exception_type == Cpu::SYNC_LEVEL_EL0) {
+ Genode::raw("Will freeze thread ", *this);
+ _become_inactive(DEAD);
+ return;
+ }
break;
}
default:
@@ -75,10 +85,14 @@ void Thread::exception(Cpu & cpu)
void Kernel::Thread::Tlb_invalidation::execute() { };
-bool Kernel::Pd::invalidate_tlb(Cpu &, addr_t addr, size_t size)
+bool Kernel::Pd::invalidate_tlb(Cpu & cpu, addr_t addr, size_t size)
{
using namespace Genode;
+ /* only apply to the active cpu */
+ if (cpu.id() != Cpu::executing_id())
+ return false;
+
/**
* The kernel part of the address space is mapped as global
* therefore we have to invalidate it differently
@@ -108,7 +122,9 @@ bool Kernel::Pd::invalidate_tlb(Cpu &, addr_t addr, size_t size)
void Thread::proceed(Cpu & cpu)
{
- cpu.switch_to(*regs, pd().mmu_regs);
+ if (!cpu.active(pd().mmu_regs) && type() != CORE)
+ cpu.switch_to(pd().mmu_regs);
+
kernel_to_user_context_switch((static_cast(&*regs)),
(void*)cpu.stack_start());
}
diff --git a/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s b/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s
index 8011bfeead..a159d81c34 100644
--- a/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s
+++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s
@@ -22,24 +22,34 @@
.global hypervisor_exception_vector
hypervisor_exception_vector:
.rept 16
- add sp, sp, #-16 /* push x0, x1 to stack */
- stp x0, x1, [sp]
- mrs x1, hcr_el2 /* read HCR register */
- tst x1, #1 /* check VM bit */
- beq _host_to_vm /* if VM bit is not set, switch to VM */
- ldr x0, [sp, #32] /* otherwise, load vm_state pointer */
- adr x1, . /* hold exception vector offset in x1 */
- and x1, x1, #0xf80
- b _vm_to_host
+ add sp, sp, #-16 /* push x29, x30 to stack */
+ stp x29, x30, [sp]
+ mrs x30, hcr_el2 /* read HCR register */
+ tst x30, #1 /* check VM bit */
+ beq _from_host /* if VM bit is not set, its a host call */
+ ldr x29, [sp, #32] /* otherwise, load vm_state pointer */
+ adr x30, . /* hold exception vector offset in x30 */
+ and x30, x30, #0xf80
+ b _from_vm
.balign 128
.endr
-_host_to_vm:
+_from_host:
+ ldp x29, x30, [sp], #2*8 /* pop x29, x30 from stack */
+ cmp x0, #0
+ beq _to_vm
+ cmp x0, #1
+ beq _invalidate_tlb
+ eret
- add sp, sp, #-16 /* push arg2 (vm pic state) to stack */
- str x2, [sp]
+_to_vm:
+ add sp, sp, #-16 /* push arg1/2 (vm/host state to stack */
+ stp x1, x2, [sp]
+ add sp, sp, #-16 /* push arg3 (vm pic state) to stack */
+ str x3, [sp]
- msr vttbr_el2, x3 /* stage2 table pointer was arg3 */
+ msr vttbr_el2, x4 /* stage2 table pointer was arg4 */
+ mov x0, x1
add x0, x0, #31*8 /* skip x0...x30, loaded later */
@@ -179,27 +189,38 @@ _host_to_vm:
eret
-_vm_to_host:
+
+_invalidate_tlb:
+ msr vttbr_el2, x1
+ tlbi vmalle1is
+ msr vttbr_el2, xzr
+ eret
+
+
+_from_vm:
/*********************
** Save vm context **
*********************/
/** general-purpose register **/
- add x0, x0, #2*8 /* skip x0 and x1 for now */
- stp x2, x3, [x0], #2*8
- stp x4, x5, [x0], #2*8
- stp x6, x7, [x0], #2*8
- stp x8, x9, [x0], #2*8
- stp x10, x11, [x0], #2*8
- stp x12, x13, [x0], #2*8
- stp x14, x15, [x0], #2*8
- stp x16, x17, [x0], #2*8
- stp x18, x19, [x0], #2*8
- stp x20, x21, [x0], #2*8
- stp x22, x23, [x0], #2*8
- stp x24, x25, [x0], #2*8
- stp x26, x27, [x0], #2*8
+ stp x0, x1, [x29], #2*8
+ stp x2, x3, [x29], #2*8
+ stp x4, x5, [x29], #2*8
+ stp x6, x7, [x29], #2*8
+ stp x8, x9, [x29], #2*8
+ stp x10, x11, [x29], #2*8
+ stp x12, x13, [x29], #2*8
+ stp x14, x15, [x29], #2*8
+ stp x16, x17, [x29], #2*8
+ stp x18, x19, [x29], #2*8
+ stp x20, x21, [x29], #2*8
+ stp x22, x23, [x29], #2*8
+ stp x24, x25, [x29], #2*8
+ stp x26, x27, [x29], #2*8
+ mov x0, x29
+ mov x1, x30
+ ldp x29, x30, [sp], #2*8 /* pop x29, x30 from stack */
stp x28, x29, [x0], #2*8
str x30, [x0], #1*8
@@ -284,11 +305,8 @@ _vm_to_host:
mov x0, #0b111
msr cnthctl_el2, x0
-
- ldp x0, x1, [sp], #2*8 /* pop x0, x1 from stack */
- ldr x29, [sp], #2*8 /* pop vm pic state from stack */
- ldp x2, x30, [sp], #2*8 /* pop vm, and host state from stack */
- stp x0, x1, [x2] /* save x0, x1 to vm state */
+ ldr x29, [sp], #2*8 /* pop vm pic state from stack */
+ ldp x2, x30, [sp], #2*8 /* pop vm, and host state from stack */
/**********************
@@ -364,6 +382,7 @@ _vm_to_host:
eret
/* host kernel must jump to this point to switch to a vm */
-.global hypervisor_enter_vm
-hypervisor_enter_vm:
+.global hypervisor_call
+hypervisor_call:
hvc #0
+ ret
diff --git a/repos/base-hw/src/core/spec/arm_v8/virtualization/hypervisor.h b/repos/base-hw/src/core/spec/arm_v8/virtualization/hypervisor.h
new file mode 100644
index 0000000000..b58193fb22
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/hypervisor.h
@@ -0,0 +1,52 @@
+/*
+ * \brief Interface between kernel and hypervisor
+ * \author Stefan Kalkowski
+ * \date 2022-06-13
+ */
+
+/*
+ * Copyright (C) 2022 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _SPEC__ARM_V8__VIRTUALIZATION_HYPERVISOR_H_
+#define _SPEC__ARM_V8__VIRTUALIZATION_HYPERVISOR_H_
+
+#include
+
+namespace Hypervisor {
+
+ enum Call_number {
+ WORLD_SWITCH = 0,
+ TLB_INVALIDATE = 1,
+ };
+
+ using Call_arg = Genode::umword_t;
+ using Call_ret = Genode::umword_t;
+
+ extern "C"
+ Call_ret hypervisor_call(Call_arg call_id,
+ Call_arg arg0,
+ Call_arg arg1,
+ Call_arg arg2,
+ Call_arg arg3);
+
+
+ inline void invalidate_tlb(Call_arg ttbr)
+ {
+ hypervisor_call(TLB_INVALIDATE, ttbr, 0, 0, 0);
+ }
+
+
+ inline void switch_world(Call_arg guest_state,
+ Call_arg host_state,
+ Call_arg pic_state,
+ Call_arg ttbr)
+ {
+ hypervisor_call(WORLD_SWITCH, guest_state, host_state, pic_state, ttbr);
+ }
+}
+
+#endif /* _SPEC__ARM_V8__VIRTUALIZATION_HYPERVISOR_H_ */
diff --git a/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc
index 6db8317560..30b6962865 100644
--- a/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc
+++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc
@@ -23,14 +23,12 @@
#include
#include
+#include
+
using Genode::addr_t;
using Kernel::Cpu;
using Kernel::Vm;
-extern void * kernel_stack;
-extern "C" void hypervisor_enter_vm(addr_t vm, addr_t host,
- addr_t pic, addr_t guest_table);
-
static Genode::Vm_state & host_context(Cpu & cpu)
{
@@ -154,6 +152,15 @@ Vm::Vm(Irq::Pool & user_irq_pool,
}
+Vm::~Vm()
+{
+ Cpu::Vttbr_el2::access_t vttbr_el2 =
+ Cpu::Vttbr_el2::Ba::masked((Cpu::Vttbr_el2::access_t)_id.table);
+ Cpu::Vttbr_el2::Asid::set(vttbr_el2, _id.id);
+ Hypervisor::invalidate_tlb(vttbr_el2);
+}
+
+
void Vm::exception(Cpu & cpu)
{
switch (_state.exception_type) {
@@ -197,7 +204,7 @@ void Vm::proceed(Cpu & cpu)
addr_t pic = Hw::Mm::el2_addr(&_vcpu_context.pic);
addr_t host = Hw::Mm::el2_addr(&host_context(cpu));
- hypervisor_enter_vm(guest, host, pic, vttbr_el2);
+ Hypervisor::switch_world(guest, host, pic, vttbr_el2);
}
diff --git a/repos/base-hw/src/core/spec/cortex_a15/cpu.h b/repos/base-hw/src/core/spec/cortex_a15/cpu.h
index 3a1ad078cf..ca1a447ec2 100644
--- a/repos/base-hw/src/core/spec/cortex_a15/cpu.h
+++ b/repos/base-hw/src/core/spec/cortex_a15/cpu.h
@@ -115,11 +115,14 @@ class Genode::Cpu : public Arm_v7_cpu
*/
static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); }
-
- void switch_to(Context &, Mmu_context & mmu_context)
+ bool active(Mmu_context & mmu_context)
{
- if (mmu_context.id() && (Ttbr0_64bit::read() != mmu_context.ttbr0))
- Ttbr0_64bit::write(mmu_context.ttbr0);
+ return (Ttbr0_64bit::read() == mmu_context.ttbr0);
+ }
+
+ void switch_to(Mmu_context & mmu_context)
+ {
+ Ttbr0_64bit::write(mmu_context.ttbr0);
}
};
diff --git a/repos/base-hw/src/core/spec/riscv/cpu.cc b/repos/base-hw/src/core/spec/riscv/cpu.cc
index e182afe444..e2e77f2aa5 100644
--- a/repos/base-hw/src/core/spec/riscv/cpu.cc
+++ b/repos/base-hw/src/core/spec/riscv/cpu.cc
@@ -53,22 +53,16 @@ Mmu_context::~Mmu_context()
}
+bool Genode::Cpu::active(Mmu_context & context)
+{
+ return Satp::read() == context.satp;
+}
+
+
void Genode::Cpu::switch_to(Mmu_context & context)
{
- /*
- * The sstatus register defines to which privilege level
- * the machin returns when doing an exception return
- */
- bool user = Satp::Asid::get(context.satp);
- Sstatus::access_t v = Sstatus::read();
- Sstatus::Spp::set(v, user ? 0 : 1);
- Sstatus::write(v);
-
- /* change the translation table when necessary */
- if (user) {
- Satp::write(context.satp);
- sfence();
- }
+ Satp::write(context.satp);
+ sfence();
}
diff --git a/repos/base-hw/src/core/spec/riscv/cpu.h b/repos/base-hw/src/core/spec/riscv/cpu.h
index 86820b3504..d719abcb1c 100644
--- a/repos/base-hw/src/core/spec/riscv/cpu.h
+++ b/repos/base-hw/src/core/spec/riscv/cpu.h
@@ -97,6 +97,7 @@ class Genode::Cpu : public Hw::Riscv_cpu
static void invalidate_tlb_by_pid(unsigned const /* pid */) { sfence(); }
+ bool active(Mmu_context & context);
void switch_to(Mmu_context & context);
static void mmu_fault(Context & c, Kernel::Thread_fault & f);
diff --git a/repos/base-hw/src/core/spec/riscv/kernel/thread.cc b/repos/base-hw/src/core/spec/riscv/kernel/thread.cc
index 15f568af26..10814fde15 100644
--- a/repos/base-hw/src/core/spec/riscv/kernel/thread.cc
+++ b/repos/base-hw/src/core/spec/riscv/kernel/thread.cc
@@ -100,7 +100,16 @@ void Kernel::Thread::_call_cache_invalidate_data_region() { }
void Kernel::Thread::proceed(Cpu & cpu)
{
- cpu.switch_to(_pd->mmu_regs);
+ /*
+ * The sstatus register defines to which privilege level
+ * the machine returns when doing an exception return
+ */
+ Cpu::Sstatus::access_t v = Cpu::Sstatus::read();
+ Cpu::Sstatus::Spp::set(v, (type() == USER) ? 0 : 1);
+ Cpu::Sstatus::write(v);
+
+ if (!cpu.active(pd().mmu_regs) && type() != CORE)
+ cpu.switch_to(_pd->mmu_regs);
asm volatile("csrw sscratch, %1 \n"
"mv x31, %0 \n"
diff --git a/repos/base-hw/src/core/spec/x86_64/cpu.cc b/repos/base-hw/src/core/spec/x86_64/cpu.cc
index 5ef6bc2cff..689e4f9e3d 100644
--- a/repos/base-hw/src/core/spec/x86_64/cpu.cc
+++ b/repos/base-hw/src/core/spec/x86_64/cpu.cc
@@ -111,11 +111,20 @@ extern void const * const kernel_stack;
extern Genode::size_t const kernel_stack_size;
-void Genode::Cpu::switch_to(Context & context, Mmu_context &mmu_context)
+bool Genode::Cpu::active(Mmu_context &mmu_context)
{
- if ((context.cs != 0x8) && (mmu_context.cr3 != Cr3::read()))
- Cr3::write(mmu_context.cr3);
+ return (mmu_context.cr3 == Cr3::read());
+}
+
+void Genode::Cpu::switch_to(Mmu_context &mmu_context)
+{
+ Cr3::write(mmu_context.cr3);
+}
+
+
+void Genode::Cpu::switch_to(Context & context)
+{
tss.ist[0] = (addr_t)&context + sizeof(Genode::Cpu_state);
addr_t const stack_base = reinterpret_cast(&kernel_stack);
diff --git a/repos/base-hw/src/core/spec/x86_64/cpu.h b/repos/base-hw/src/core/spec/x86_64/cpu.h
index 35073dcc93..781fa38373 100644
--- a/repos/base-hw/src/core/spec/x86_64/cpu.h
+++ b/repos/base-hw/src/core/spec/x86_64/cpu.h
@@ -126,7 +126,10 @@ class Genode::Cpu : public Hw::X86_64_cpu
*
* \param context next CPU context
*/
- void switch_to(Context & context, Mmu_context &mmu_context);
+ void switch_to(Context & context);
+
+ bool active(Mmu_context &mmu_context);
+ void switch_to(Mmu_context &mmu_context);
static void mmu_fault(Context & regs, Kernel::Thread_fault & fault);
diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc b/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc
index 9df97877b1..df3332a4de 100644
--- a/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc
+++ b/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc
@@ -43,7 +43,10 @@ void Kernel::Thread::_call_cache_invalidate_data_region() { }
void Kernel::Thread::proceed(Cpu & cpu)
{
- cpu.switch_to(*regs, pd().mmu_regs);
+ if (!cpu.active(pd().mmu_regs) && type() != CORE)
+ cpu.switch_to(pd().mmu_regs);
+
+ cpu.switch_to(*regs);
asm volatile("fxrstor (%1) \n"
"mov %0, %%rsp \n"
diff --git a/repos/base-hw/src/lib/ld/hw/target.mk b/repos/base-hw/src/lib/ld/hw/target.mk
deleted file mode 100644
index da9b4cb18f..0000000000
--- a/repos/base-hw/src/lib/ld/hw/target.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = ld-hw
-LIBS = ld-hw
diff --git a/repos/base-hw/src/test/cpu_scheduler/test.cc b/repos/base-hw/src/test/cpu_scheduler/test.cc
index 470a8ba44f..f26e2924ce 100644
--- a/repos/base-hw/src/test/cpu_scheduler/test.cc
+++ b/repos/base-hw/src/test/cpu_scheduler/test.cc
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2014-2017 Genode Labs GmbH
+ * Copyright (C) 2014-2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@@ -18,125 +18,110 @@
/* core includes */
#include
-/*
- * Utilities
- */
+using namespace Genode;
+using namespace Kernel;
-using Genode::size_t;
-using Genode::addr_t;
-using Genode::construct_at;
-using Kernel::Cpu_share;
-using Kernel::Cpu_scheduler;
-
-
-struct Data
+struct Main
{
- Cpu_share idle;
- Cpu_scheduler scheduler;
- char shares[9][sizeof(Cpu_share)];
+ enum { MAX_SHARES = 10 };
- Data() : idle(0, 0), scheduler(idle, 1000, 100) { }
+ Constructible shares[MAX_SHARES] {};
+ Cpu_scheduler scheduler;
+ time_t current_time { 0 };
+
+ Cpu_share & _idle()
+ {
+ if (!shares[0].constructed()) shares[0].construct(0, 0);
+ return *shares[0];
+ }
+
+ Main() : scheduler(_idle(), 1000, 100) { }
+
+ void done()
+ {
+ Genode::log("done");
+ while (1) ;
+ }
+
+ unsigned share_id(Cpu_share & share)
+ {
+ for (unsigned i = 0; i < MAX_SHARES; i++)
+ if (shares[i].constructed() && (&*shares[i] == &share))
+ return i;
+ return ~0U;
+ }
+
+ Cpu_share & share(unsigned const id)
+ {
+ return *shares[id];
+ }
+
+ void create(unsigned const id)
+ {
+ switch (id) {
+ case 1: shares[id].construct(2, 230); break;
+ case 2: shares[id].construct(0, 170); break;
+ case 3: shares[id].construct(3, 110); break;
+ case 4: shares[id].construct(1, 90); break;
+ case 5: shares[id].construct(3, 120); break;
+ case 6: shares[id].construct(3, 0); break;
+ case 7: shares[id].construct(2, 180); break;
+ case 8: shares[id].construct(2, 100); break;
+ case 9: shares[id].construct(2, 0); break;
+ default: return;
+ }
+ scheduler.insert(*shares[id]);
+ }
+
+ void destroy(unsigned const id)
+ {
+ if (!id || id >= MAX_SHARES)
+ return;
+
+ scheduler.remove(share(id));
+ shares[id].destruct();
+ }
+
+ unsigned time()
+ {
+ return scheduler.quota() - scheduler.residual();
+ }
+
+ void update_check(unsigned const l, unsigned const c, unsigned const t,
+ unsigned const s, unsigned const q)
+ {
+ current_time += c;
+ scheduler.update(current_time);
+ unsigned const st = time();
+ if (t != st) {
+ log("wrong time ", st, " in line ", l);
+ done();
+ }
+ Cpu_share & hs = scheduler.head();
+ unsigned const hq = scheduler.head_quota();
+ if (&hs != &share(s)) {
+ log("wrong share ", share_id(hs), " in line ", l);
+ done();
+ }
+ if (hq != q) {
+ log("wrong quota ", hq, " in line ", l);
+ done();
+ }
+ }
+
+ void ready_check(unsigned const l, unsigned const s, bool const x)
+ {
+ scheduler.ready(share(s));
+ if (scheduler.need_to_schedule() != x) {
+ log("wrong check result ", scheduler.need_to_schedule(), " in line ", l);
+ done();
+ }
+ }
+
+ void test();
};
-Data * data()
-{
- static Data d;
- return &d;
-}
-
-
-void done()
-{
- Genode::log("done");
- while (1) ;
-}
-
-
-unsigned share_id(void * const pointer)
-{
- addr_t const address = (addr_t)pointer;
- addr_t const base = (addr_t)data()->shares;
- if (address < base || address >= base + sizeof(data()->shares)) {
- return 0; }
- return (unsigned)((address - base) / sizeof(Cpu_share) + 1);
-}
-
-
-Cpu_share * share(unsigned const id)
-{
- if (!id) { return &data()->idle; }
- return reinterpret_cast(&data()->shares[id - 1]);
-}
-
-
-void create(unsigned const id)
-{
- Cpu_share * const s = share(id);
- void * const p = (void *)s;
- switch (id) {
- case 1: construct_at(p, 2, 230); break;
- case 2: construct_at(p, 0, 170); break;
- case 3: construct_at(p, 3, 110); break;
- case 4: construct_at(p, 1, 90); break;
- case 5: construct_at(p, 3, 120); break;
- case 6: construct_at(p, 3, 0); break;
- case 7: construct_at(p, 2, 180); break;
- case 8: construct_at(p, 2, 100); break;
- case 9: construct_at(p, 2, 0); break;
- default: return;
- }
- data()->scheduler.insert(*s);
-}
-
-
-void destroy(unsigned const id)
-{
- Cpu_share * const s = share(id);
- data()->scheduler.remove(*s);
- s->~Cpu_share();
-}
-
-
-unsigned time()
-{
- return data()->scheduler.quota() -
- data()->scheduler.residual();
-}
-
-
-void update_check(unsigned const l, unsigned const c, unsigned const t,
- unsigned const s, unsigned const q)
-{
- data()->scheduler.update(c);
- unsigned const st = time();
- if (t != st) {
- Genode::log("wrong time ", st, " in line ", l);
- done();
- }
- Cpu_share &hs = data()->scheduler.head();
- unsigned const hq = data()->scheduler.head_quota();
- if (&hs != share(s)) {
- unsigned const hi = share_id(&hs);
- Genode::log("wrong share ", hi, " in line ", l);
- done();
- }
- if (hq != q) {
- Genode::log("wrong quota ", hq, " in line ", l);
- done();
- }
-}
-
-
-void ready_check(unsigned const l, unsigned const s, bool const x)
-{
- data()->scheduler.ready_check(*share(s));
- if (data()->scheduler.need_to_schedule() != x) {
- Genode::log("wrong check result ", data()->scheduler.need_to_schedule(), " in line ", l);
- done();
- }
-}
-
/*
* Shortcuts for all basic operations that the test consists of
@@ -144,10 +129,10 @@ void ready_check(unsigned const l, unsigned const s, bool const x)
#define C(s) create(s);
#define D(s) destroy(s);
-#define A(s) data()->scheduler.ready(*share(s));
-#define I(s) data()->scheduler.unready(*share(s));
-#define Y data()->scheduler.yield();
-#define Q(s, q) data()->scheduler.quota(*share(s), q);
+#define A(s) scheduler.ready(share(s));
+#define I(s) scheduler.unready(share(s));
+#define Y scheduler.yield();
+#define Q(s, q) scheduler.quota(share(s), q);
#define U(c, t, s, q) update_check(__LINE__, c, t, s, q);
#define O(s) ready_check(__LINE__, s, true);
#define N(s) ready_check(__LINE__, s, false);
@@ -157,6 +142,13 @@ void ready_check(unsigned const l, unsigned const s, bool const x)
* Main routine
*/
void Component::construct(Genode::Env &)
+{
+ static Main main;
+ main.test();
+}
+
+
+void Main::test()
{
/*
* Step-by-step testing
diff --git a/repos/base-linux/recipes/api/base-linux/content.mk b/repos/base-linux/recipes/api/base-linux/content.mk
index c77cf9d735..7839296c17 100644
--- a/repos/base-linux/recipes/api/base-linux/content.mk
+++ b/repos/base-linux/recipes/api/base-linux/content.mk
@@ -1,8 +1,7 @@
FROM_BASE_LINUX := etc src/lib/syscall src/lib/lx_hybrid lib/import include
-FROM_BASE_LINUX_AND_BASE := lib/mk src/lib/base src/include
-FROM_BASE := src/lib/timeout
+FROM_BASE_LINUX_AND_BASE := src/lib/base src/include
-content: $(FROM_BASE_LINUX) $(FROM_BASE_LINUX_AND_BASE) $(FROM_BASE) LICENSE
+content: $(FROM_BASE_LINUX) $(FROM_BASE_LINUX_AND_BASE) LICENSE
$(FROM_BASE_LINUX):
mkdir -p $@
@@ -13,9 +12,30 @@ $(FROM_BASE_LINUX_AND_BASE):
cp -r $(GENODE_DIR)/repos/base/$@/* $@
cp -r $(REP_DIR)/$@/* $@
-$(FROM_BASE):
+BASE_LIB_MK_CONTENT := \
+ $(addprefix lib/mk/,base-common.inc timeout.mk)
+
+content: $(BASE_LIB_MK_CONTENT)
+
+$(BASE_LIB_MK_CONTENT):
+ mkdir -p $(dir $@)
+ cp $(GENODE_DIR)/repos/base/$@ $@
+
+content: src/lib/timeout
+
+src/lib/timeout:
mkdir -p $@
cp -r $(GENODE_DIR)/repos/base/$@/* $@
+BASE_LINUX_LIB_MK_CONTENT := \
+ $(addprefix lib/mk/,lx_hybrid.mk base-linux.inc base-linux-common.mk) \
+ $(foreach S,arm arm_64 x86_32 x86_64,lib/mk/spec/$S/syscall-linux.mk)
+
+content: $(BASE_LINUX_LIB_MK_CONTENT)
+
+$(BASE_LINUX_LIB_MK_CONTENT):
+ mkdir -p $(dir $@)
+ cp $(REP_DIR)/$@ $@
+
LICENSE:
cp $(GENODE_DIR)/LICENSE $@
diff --git a/repos/base-linux/recipes/api/base-linux/hash b/repos/base-linux/recipes/api/base-linux/hash
index 8c49e019b3..dbb7c16ebe 100644
--- a/repos/base-linux/recipes/api/base-linux/hash
+++ b/repos/base-linux/recipes/api/base-linux/hash
@@ -1 +1 @@
-2022-04-12 dcb2c9200b333adb17f9a8737620cbd84f641408
+2022-10-11 4544924c73b2ee1d8d2717672320f14732807267
diff --git a/repos/base-linux/recipes/src/base-linux/content.mk b/repos/base-linux/recipes/src/base-linux/content.mk
index ad1db4cc75..ac78f59846 100644
--- a/repos/base-linux/recipes/src/base-linux/content.mk
+++ b/repos/base-linux/recipes/src/base-linux/content.mk
@@ -10,7 +10,6 @@ content:
mv lib/mk/spec/$$spec/ld-linux.mk lib/mk/spec/$$spec/ld.mk; done;
sed -i "/TARGET/s/core-linux/core/" src/core/linux/target.mk
sed -i "s/BOARD.*unknown/BOARD := linux/" lib/mk/core-linux.inc
- sed -i "s/ld-linux/ld/" src/lib/ld/linux/target.mk
sed -i "s/linux_timer_drv/timer/" src/timer/linux/target.mk
- rm -rf src/lib/initramfs
+ rm -rf src/initramfs
diff --git a/repos/base-linux/recipes/src/base-linux/hash b/repos/base-linux/recipes/src/base-linux/hash
index 8ae6c7808f..7f3752b7d0 100644
--- a/repos/base-linux/recipes/src/base-linux/hash
+++ b/repos/base-linux/recipes/src/base-linux/hash
@@ -1 +1 @@
-2022-05-24 4aea382035415c79bf5d551642ebfa64d42e4d21
+2022-10-11 d7e12d81f12f081bb7c00233c18f3c8ac2f00d67
diff --git a/repos/base-linux/src/lib/initramfs/init.c b/repos/base-linux/src/initramfs/init.c
similarity index 100%
rename from repos/base-linux/src/lib/initramfs/init.c
rename to repos/base-linux/src/initramfs/init.c
diff --git a/repos/base-linux/src/lib/initramfs/target.mk b/repos/base-linux/src/initramfs/target.mk
similarity index 72%
rename from repos/base-linux/src/lib/initramfs/target.mk
rename to repos/base-linux/src/initramfs/target.mk
index c684f26c29..b7146371f4 100644
--- a/repos/base-linux/src/lib/initramfs/target.mk
+++ b/repos/base-linux/src/initramfs/target.mk
@@ -5,14 +5,14 @@ REQUIRES = x86_64
INITRAMFS = initramfs
INITRAMFS_SRC_C = init.c
-EXT_OBJECTS += $(BUILD_BASE_DIR)/lib/initramfs/$(INITRAMFS)
+EXT_OBJECTS += $(BUILD_BASE_DIR)/initramfs/$(INITRAMFS)
$(TARGET): $(INITRAMFS)
$(INITRAMFS): $(INITRAMFS_SRC_C)
$(MSG_BUILD)$(INITRAMFS)
$(VERBOSE)gcc $^ -O0 $(CC_MARCH) -Wall -W -Wextra -Werror -std=gnu99 -o $@ -Wl,-O3 -Wl,--as-needed -static
- $(VERBOSE)ln -sf $(BUILD_BASE_DIR)/lib/initramfs/$(INITRAMFS) $(BUILD_BASE_DIR)/bin/
+ $(VERBOSE)ln -sf $(BUILD_BASE_DIR)/initramfs/$(INITRAMFS) $(BUILD_BASE_DIR)/bin/
clean_initramfs:
$(VERBOSE)rm -rf $(INITRAMFS)
diff --git a/repos/base-linux/src/lib/base/region_map_mmap.cc b/repos/base-linux/src/lib/base/region_map_mmap.cc
index 01946e4204..46b34ae66b 100644
--- a/repos/base-linux/src/lib/base/region_map_mmap.cc
+++ b/repos/base-linux/src/lib/base/region_map_mmap.cc
@@ -172,6 +172,24 @@ void Region_map_mmap::_add_to_rmap(Region const ®ion)
}
+/*
+ * Tracing must be inhibited in attach/detach as RPC trace points may trigger
+ * attachment of trace dataspaces, which would result in nested mutex
+ * acquisition.
+ */
+
+namespace Genode { extern bool inhibit_tracing; }
+
+struct Inhibit_tracing_guard
+{
+ bool old_value = inhibit_tracing;
+
+ Inhibit_tracing_guard() { inhibit_tracing = true; }
+
+ ~Inhibit_tracing_guard() { inhibit_tracing = old_value; }
+};
+
+
Region_map::Local_addr Region_map_mmap::attach(Dataspace_capability ds,
size_t size, off_t offset,
bool use_local_addr,
@@ -180,6 +198,8 @@ Region_map::Local_addr Region_map_mmap::attach(Dataspace_capability ds,
{
Mutex::Guard mutex_guard(mutex());
+ Inhibit_tracing_guard it_guard { };
+
/* only support attach_at for sub RM sessions */
if (_sub_rm && !use_local_addr) {
error("Region_map_mmap::attach: attaching w/o local addr not supported");
@@ -325,6 +345,8 @@ void Region_map_mmap::detach(Region_map::Local_addr local_addr)
{
Mutex::Guard mutex_guard(mutex());
+ Inhibit_tracing_guard it_guard { };
+
/*
* Cases
*
diff --git a/repos/base-linux/src/lib/ld/linux/target.mk b/repos/base-linux/src/lib/ld/linux/target.mk
deleted file mode 100644
index dbbcd910ba..0000000000
--- a/repos/base-linux/src/lib/ld/linux/target.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-TARGET = ld-linux.lib
-LIBS = ld-linux
-
-BUILD_ARTIFACTS := ld-linux.lib.so
diff --git a/repos/base-nova/include/nova/syscall-generic.h b/repos/base-nova/include/nova/syscall-generic.h
index 1692e5aa84..eed3d3f90d 100644
--- a/repos/base-nova/include/nova/syscall-generic.h
+++ b/repos/base-nova/include/nova/syscall-generic.h
@@ -108,6 +108,7 @@ namespace Nova {
uint64_t const size;
Type const type;
uint32_t const aux;
+ uint32_t const domain;
};
uint32_t const signature; /* magic value 0x41564f4e */
@@ -143,6 +144,7 @@ namespace Nova {
uint8_t platform:3;
uint8_t reserved:1;
uint32_t patch;
+ uint8_t numa_id;
} __attribute__((packed));
unsigned cpu_max() const {
@@ -175,7 +177,7 @@ namespace Nova {
/**
* Map kernel cpu ids to virtual cpu ids.
*/
- bool remap_cpu_ids(uint8_t *map_cpus, unsigned const boot_cpu) const {
+ bool remap_cpu_ids(uint8_t *map_cpus, uint8_t *cpu_numa_map, unsigned const boot_cpu) const {
unsigned const num_cpus = cpus();
unsigned cpu_i = 0;
@@ -193,17 +195,18 @@ namespace Nova {
for (uint8_t core = 0; core < 255; core++) {
for (uint8_t thread = 0; thread < 255; thread++) {
for (unsigned i = 0; i < cpu_max(); i++) {
- if (i == boot_cpu || !is_cpu_enabled(i))
+ if (i == boot_cpu || !is_cpu_enabled(i))
continue;
Cpu_desc const * const c = cpu_desc_of_cpu(i);
- if (!c)
+ if (!c)
continue;
if (!(c->package == package && c->core == core &&
c->thread == thread))
continue;
+ cpu_numa_map[i] = c->numa_id;
map_cpus[cpu_i++] = (uint8_t)i;
if (cpu_i >= num_cpus)
return true;
@@ -257,6 +260,30 @@ namespace Nova {
*/
enum Pd_op { TRANSFER_QUOTA = 0U, PD_DEBUG = 2U };
+ class Gsi_flags
+ {
+ private:
+
+ uint8_t _value { 0 };
+
+ public:
+
+ enum Mode { HIGH, LOW, EDGE };
+
+ Gsi_flags() { }
+
+ Gsi_flags(Mode m)
+ {
+ switch (m) {
+ case HIGH: _value = 0b110; break; /* level-high */
+ case LOW: _value = 0b111; break; /* level-low */
+ case EDGE: _value = 0b100; break; /* edge-triggered */
+ }
+ }
+
+ uint8_t value() const { return _value; }
+ };
+
class Descriptor
{
@@ -516,7 +543,7 @@ namespace Nova {
public:
- enum { DEFAULT_QUANTUM = 10000, DEFAULT_PRIORITY = 64 };
+ enum { DEFAULT_QUANTUM = 1500, DEFAULT_PRIORITY = 64 };
Qpd(mword_t quantum = DEFAULT_QUANTUM,
mword_t priority = DEFAULT_PRIORITY)
diff --git a/repos/base-nova/include/spec/32bit/nova/syscalls.h b/repos/base-nova/include/spec/32bit/nova/syscalls.h
index e52c61d334..6fb41d4fee 100644
--- a/repos/base-nova/include/spec/32bit/nova/syscalls.h
+++ b/repos/base-nova/include/spec/32bit/nova/syscalls.h
@@ -457,12 +457,12 @@ namespace Nova {
ALWAYS_INLINE
inline uint8_t assign_gsi(mword_t sm, mword_t dev, mword_t cpu,
mword_t &msi_addr, mword_t &msi_data,
- mword_t si = ~0UL)
+ mword_t si = ~0UL, Gsi_flags flags = Gsi_flags())
{
msi_addr = dev;
msi_data = cpu;
- return syscall_5(NOVA_ASSIGN_GSI, 0, sm, msi_addr, msi_data, si);
+ return syscall_5(NOVA_ASSIGN_GSI, flags.value(), sm, msi_addr, msi_data, si);
}
diff --git a/repos/base-nova/include/spec/64bit/nova/syscalls.h b/repos/base-nova/include/spec/64bit/nova/syscalls.h
index 3ab7e887ed..9e8fa765fc 100644
--- a/repos/base-nova/include/spec/64bit/nova/syscalls.h
+++ b/repos/base-nova/include/spec/64bit/nova/syscalls.h
@@ -402,11 +402,11 @@ namespace Nova {
ALWAYS_INLINE
inline uint8_t assign_gsi(mword_t sm, mword_t dev, mword_t cpu,
mword_t &msi_addr, mword_t &msi_data,
- mword_t si = ~0UL)
+ mword_t si = ~0UL, Gsi_flags flags = Gsi_flags())
{
msi_addr = dev;
msi_data = cpu;
- return syscall_5(NOVA_ASSIGN_GSI, 0, sm, msi_addr, msi_data, si);
+ return syscall_5(NOVA_ASSIGN_GSI, flags.value(), sm, msi_addr, msi_data, si);
}
}
#endif /* _INCLUDE__SPEC__64BIT__NOVA__SYSCALLS_H_ */
diff --git a/repos/base-nova/lib/mk/core-nova.inc b/repos/base-nova/lib/mk/core-nova.inc
index 9df0b67e8f..781bf501f2 100644
--- a/repos/base-nova/lib/mk/core-nova.inc
+++ b/repos/base-nova/lib/mk/core-nova.inc
@@ -43,7 +43,8 @@ SRC_CC += stack_area.cc \
signal_receiver.cc \
vm_session_component.cc \
vm_session_common.cc \
- heartbeat.cc
+ heartbeat.cc \
+ topo_session_component.cc
INC_DIR = $(REP_DIR)/src/core/include \
$(REP_DIR)/src/include \
@@ -77,4 +78,5 @@ vpath platform_rom_modules.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)
vpath heartbeat.cc $(GEN_CORE_DIR)
vpath vm_session_common.cc $(GEN_CORE_DIR)
+vpath topo_session_component.cc $(GEN_CORE_DIR)
vpath %.cc $(REP_DIR)/src/core
diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash
index bf8d5f7d78..96a5286e98 100644
--- a/repos/base-nova/ports/nova.hash
+++ b/repos/base-nova/ports/nova.hash
@@ -1 +1 @@
-33a2fa953ec52b0f63b921f4d33d68891c0aada0
+d850a1b6412ce630abedf7b9aa623b5caa994235
diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port
index 90f33a67b9..c46b0978e5 100644
--- a/repos/base-nova/ports/nova.port
+++ b/repos/base-nova/ports/nova.port
@@ -2,9 +2,9 @@ LICENSE := GPLv2
VERSION := git
DOWNLOADS := nova.git
-# r10 branch
-URL(nova) := https://github.com/alex-ab/NOVA.git
-REV(nova) := 00dc49bc18e7f72a9c85487e8f94fd859511d89d
+# feature/numa branch
+URL(nova) := https://github.com/mmueller41/NOVA.git
+REV(nova) := 6479677bd61db47bcdcb4bd796566f83b9f655ef
DIR(nova) := src/kernel/nova
PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch))
diff --git a/repos/base-nova/recipes/api/base-nova/content.mk b/repos/base-nova/recipes/api/base-nova/content.mk
index c49d05cd49..dbb72ce372 100644
--- a/repos/base-nova/recipes/api/base-nova/content.mk
+++ b/repos/base-nova/recipes/api/base-nova/content.mk
@@ -1,5 +1,8 @@
FROM_BASE_NOVA := etc include
-FROM_BASE := lib/mk/timeout.mk src/lib/timeout
+
+# base-nova.lib.a depends on timeout.lib.a, which includes base/internal/gloabls.h
+FROM_BASE := lib/mk/timeout.mk src/lib/timeout \
+ src/include/base/internal/globals.h
content: $(FROM_BASE_NOVA) $(FROM_BASE) LICENSE
diff --git a/repos/base-nova/recipes/api/base-nova/hash b/repos/base-nova/recipes/api/base-nova/hash
index ee7a3a50cc..bbdab0a29c 100644
--- a/repos/base-nova/recipes/api/base-nova/hash
+++ b/repos/base-nova/recipes/api/base-nova/hash
@@ -1 +1 @@
-2022-05-24 91bc8d51bbe703d56f5671019d14e4636f21bf1f
+2022-10-11 4458ea63a69ae070e19a3cb09a403137755d2cb0
diff --git a/repos/base-nova/recipes/src/base-nova/content.mk b/repos/base-nova/recipes/src/base-nova/content.mk
index cf557b5dbe..41278a28a1 100644
--- a/repos/base-nova/recipes/src/base-nova/content.mk
+++ b/repos/base-nova/recipes/src/base-nova/content.mk
@@ -15,8 +15,7 @@ src/kernel/nova: src/kernel
content:
for spec in x86_32 x86_64; do \
- mv lib/mk/spec/$$spec/ld-nova.mk lib/mk/spec/$$spec/ld.mk; \
+ mv lib/mk/spec/$$spec/ld-nova.mk lib/mk/spec/$$spec/ld.mk; \
done;
- sed -i "s/ld-nova/ld/" src/lib/ld/nova/target.mk
sed -i "s/nova_timer_drv/timer/" src/timer/nova/target.mk
diff --git a/repos/base-nova/recipes/src/base-nova/hash b/repos/base-nova/recipes/src/base-nova/hash
index 3fce06004a..c2b670f646 100644
--- a/repos/base-nova/recipes/src/base-nova/hash
+++ b/repos/base-nova/recipes/src/base-nova/hash
@@ -1 +1 @@
-2022-05-24 8b59a28ade1392bae4aa772bbead1584a2dde1de
+2022-10-11 574204b7d442811236bba60e4fe3f79e34fe9985
diff --git a/repos/base-nova/src/core/core_log_out.cc b/repos/base-nova/src/core/core_log_out.cc
index 0571e83c16..84c7c5264c 100644
--- a/repos/base-nova/src/core/core_log_out.cc
+++ b/repos/base-nova/src/core/core_log_out.cc
@@ -22,7 +22,7 @@ void Genode::Core_log::out(char const c)
{
enum { CLOCK = 0, BAUDRATE = 115200 };
- static X86_uart uart(Bios_data_area::singleton()->serial_port(),
+ static X86_uart uart(0x3f8/*Bios_data_area::singleton()->serial_port()*/,
CLOCK, BAUDRATE);
if (c == '\n')
uart.put_char('\r');
diff --git a/repos/base-nova/src/core/include/irq_object.h b/repos/base-nova/src/core/include/irq_object.h
index e3a681bd2d..869eeed784 100644
--- a/repos/base-nova/src/core/include/irq_object.h
+++ b/repos/base-nova/src/core/include/irq_object.h
@@ -13,7 +13,9 @@
#ifndef _CORE__INCLUDE__IRQ_OBJECT_H_
#define _CORE__INCLUDE__IRQ_OBJECT_H_
-namespace Genode { class Irq_object; }
+#include /* Gsi_flags */
+
+namespace Genode { class Irq_object; class Irq_args; }
class Genode::Irq_object
{
@@ -26,22 +28,24 @@ class Genode::Irq_object
addr_t _msi_data;
addr_t _device_phys = 0; /* PCI config extended address */
+ Nova::Gsi_flags _gsi_flags { };
+
enum { KERNEL_CAP_COUNT_LOG2 = 0 };
- Genode::addr_t irq_sel() const { return _kernel_caps; }
+ addr_t irq_sel() const { return _kernel_caps; }
public:
Irq_object();
~Irq_object();
- Genode::addr_t msi_address() const { return _msi_addr; }
- Genode::addr_t msi_value() const { return _msi_data; }
+ addr_t msi_address() const { return _msi_addr; }
+ addr_t msi_value() const { return _msi_data; }
void sigh(Signal_context_capability cap);
void ack_irq();
- void start(unsigned irq, Genode::addr_t);
+ void start(unsigned irq, addr_t, Irq_args const &);
};
#endif /* _CORE__INCLUDE__IRQ_OBJECT_H_ */
diff --git a/repos/base-nova/src/core/include/platform.h b/repos/base-nova/src/core/include/platform.h
index d992f32b40..c648c84db9 100644
--- a/repos/base-nova/src/core/include/platform.h
+++ b/repos/base-nova/src/core/include/platform.h
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
namespace Genode {
@@ -50,6 +51,8 @@ namespace Genode {
/* map of virtual cpu ids in Genode to kernel cpu ids */
uint8_t map_cpu_ids[MAX_SUPPORTED_CPUS];
+ uint8_t cpu_numa_map[MAX_SUPPORTED_CPUS];
+ Genode::Range_allocator::Range numa_mem_ranges[MAX_SUPPORTED_CPUS]; // TODO: Add new macro for max of numa regions
addr_t _map_pages(addr_t phys_page, addr_t pages,
bool guard_page = false);
@@ -119,6 +122,27 @@ namespace Genode {
unsigned pager_index(Affinity::Location location) const;
unsigned kernel_cpu_id(Affinity::Location location) const;
+ /**
+ * @brief ID of NUMA region the CPU belongs to
+ *
+ * @param kernel_cpu_id id of CPU
+ * @return unsigned ID of corresponding NUMA region
+ */
+ unsigned domain_of_cpu(unsigned kernel_cpu_id) const {
+ return cpu_numa_map[kernel_cpu_id];
+ }
+
+ /**
+ * @brief Return memory range of a given NUMA region
+ *
+ * @param numa_id ID of NUMA region
+ * @return Genode::Range_allocator::Range physical address range for this NUMA region
+ */
+
+ Genode::Range_allocator::Range &mem_range(unsigned numa_id) {
+ return numa_mem_ranges[numa_id];
+ }
+
Affinity::Location sanitize(Affinity::Location location) {
return Affinity::Location(location.xpos() % _cpus.width(),
location.ypos() % _cpus.height(),
diff --git a/repos/base-nova/src/core/irq_session_component.cc b/repos/base-nova/src/core/irq_session_component.cc
index 472d885ce1..2d98d3f5bc 100644
--- a/repos/base-nova/src/core/irq_session_component.cc
+++ b/repos/base-nova/src/core/irq_session_component.cc
@@ -18,6 +18,7 @@
/* core includes */
#include
+#include
#include
/* NOVA includes */
@@ -27,13 +28,12 @@
using namespace Genode;
-static bool irq_ctrl(Genode::addr_t irq_sel,
- Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
- Genode::addr_t sig_sel, Genode::addr_t virt_addr = 0)
+static bool irq_ctrl(addr_t irq_sel, addr_t &msi_addr, addr_t &msi_data,
+ addr_t sig_sel, Nova::Gsi_flags flags, addr_t virt_addr)
{
/* assign IRQ to CPU && request msi data to be used by driver */
uint8_t res = Nova::assign_gsi(irq_sel, virt_addr, boot_cpu(),
- msi_addr, msi_data, sig_sel);
+ msi_addr, msi_data, sig_sel, flags);
if (res != Nova::NOVA_OK)
error("setting up MSI failed - error ", res);
@@ -46,30 +46,28 @@ static bool irq_ctrl(Genode::addr_t irq_sel,
}
-static bool associate(Genode::addr_t irq_sel,
- Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
- Genode::Signal_context_capability sig_cap,
- Genode::addr_t virt_addr = 0)
-{
- return irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(),
- virt_addr);
-}
-
-
-static void deassociate(Genode::addr_t irq_sel)
+static bool associate_gsi(addr_t irq_sel, Signal_context_capability sig_cap,
+ Nova::Gsi_flags gsi_flags)
{
addr_t dummy1 = 0, dummy2 = 0;
- if (!irq_ctrl(irq_sel, dummy1, dummy2, irq_sel))
+ return irq_ctrl(irq_sel, dummy1, dummy2, sig_cap.local_name(), gsi_flags, 0);
+}
+
+
+static void deassociate(addr_t irq_sel)
+{
+ addr_t dummy1 = 0, dummy2 = 0;
+
+ if (!irq_ctrl(irq_sel, dummy1, dummy2, irq_sel, Nova::Gsi_flags(), 0))
warning("Irq could not be de-associated");
}
-static bool msi(Genode::addr_t irq_sel, Genode::addr_t phys_mem,
- Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
- Genode::Signal_context_capability sig_cap)
+static bool associate_msi(addr_t irq_sel, addr_t phys_mem, addr_t &msi_addr,
+ addr_t &msi_data, Signal_context_capability sig_cap)
{
- return platform().region_alloc().alloc_aligned(4096, 12).convert(
+ return platform().region_alloc().alloc_aligned(4096, 12).convert(
[&] (void *virt_ptr) {
@@ -89,7 +87,7 @@ static bool msi(Genode::addr_t irq_sel, Genode::addr_t phys_mem,
}
/* try to assign MSI to device */
- bool res = associate(irq_sel, msi_addr, msi_data, sig_cap, virt_addr);
+ bool res = irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(), Nova::Gsi_flags(), virt_addr);
unmap_local(Nova::Mem_crd(virt_addr >> 12, 0, Rights(true, true, true)));
platform().region_alloc().free(virt_ptr, 4096);
@@ -118,11 +116,12 @@ void Irq_object::sigh(Signal_context_capability cap)
return;
}
+ /* associate GSI or MSI to device belonging to device_phys */
bool ok = false;
if (_device_phys)
- ok = msi(irq_sel(), _device_phys, _msi_addr, _msi_data, cap);
+ ok = associate_msi(irq_sel(), _device_phys, _msi_addr, _msi_data, cap);
else
- ok = associate(irq_sel(), _msi_addr, _msi_data, cap);
+ ok = associate_gsi(irq_sel(), cap, _gsi_flags);
if (!ok) {
deassociate(irq_sel());
@@ -141,7 +140,7 @@ void Irq_object::ack_irq()
}
-void Irq_object::start(unsigned irq, Genode::addr_t const device_phys)
+void Irq_object::start(unsigned irq, addr_t const device_phys, Irq_args const &irq_args)
{
/* map IRQ SM cap from kernel to core at irq_sel selector */
using Nova::Obj_crd;
@@ -158,12 +157,29 @@ void Irq_object::start(unsigned irq, Genode::addr_t const device_phys)
throw Service_denied();
}
+ /* initialize GSI IRQ flags */
+ auto gsi_flags = [] (Irq_args const &args) {
+ if (args.trigger() == Irq_session::TRIGGER_UNCHANGED
+ || args.polarity() == Irq_session::POLARITY_UNCHANGED)
+ return Nova::Gsi_flags();
+
+ if (args.trigger() == Irq_session::TRIGGER_EDGE)
+ return Nova::Gsi_flags(Nova::Gsi_flags::EDGE);
+
+ if (args.polarity() == Irq_session::POLARITY_HIGH)
+ return Nova::Gsi_flags(Nova::Gsi_flags::HIGH);
+ else
+ return Nova::Gsi_flags(Nova::Gsi_flags::LOW);
+ };
+
+ _gsi_flags = gsi_flags(irq_args);
+
/* associate GSI or MSI to device belonging to device_phys */
bool ok = false;
if (device_phys)
- ok = msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
+ ok = associate_msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
else
- ok = associate(irq_sel(), _msi_addr, _msi_data, _sigh_cap);
+ ok = associate_gsi(irq_sel(), _sigh_cap, _gsi_flags);
if (!ok)
throw Service_denied();
@@ -212,7 +228,9 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
:
_irq_number(~0U), _irq_alloc(irq_alloc), _irq_object()
{
- long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
+ Irq_args const irq_args(args);
+
+ long irq_number = irq_args.irq_number();
long device_phys = Arg_string::find_arg(args, "device_config_phys").long_value(0);
if (device_phys) {
@@ -232,7 +250,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
_irq_number = (unsigned)irq_number;
- _irq_object.start(_irq_number, device_phys);
+ _irq_object.start(_irq_number, device_phys, irq_args);
}
@@ -241,7 +259,7 @@ Irq_session_component::~Irq_session_component()
if (_irq_number == ~0U)
return;
- Genode::addr_t free_irq = _irq_number;
+ addr_t free_irq = _irq_number;
_irq_alloc.free((void *)free_irq);
}
@@ -252,13 +270,13 @@ void Irq_session_component::ack_irq()
}
-void Irq_session_component::sigh(Genode::Signal_context_capability cap)
+void Irq_session_component::sigh(Signal_context_capability cap)
{
_irq_object.sigh(cap);
}
-Genode::Irq_session::Info Irq_session_component::info()
+Irq_session::Info Irq_session_component::info()
{
if (!_irq_object.msi_address() || !_irq_object.msi_value())
return { .type = Info::Type::INVALID, .address = 0, .value = 0 };
diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc
index bb887537f9..e9e625d296 100644
--- a/repos/base-nova/src/core/platform.cc
+++ b/repos/base-nova/src/core/platform.cc
@@ -312,8 +312,6 @@ Platform::Platform()
if (hip.api_version != 8)
nova_die();
- /* determine number of available CPUs */
- _cpus = setup_affinity_space(hip);
/* register UTCB of main thread */
__main_thread_utcb = (Utcb *)(__initial_sp - get_page_size());
@@ -338,6 +336,8 @@ Platform::Platform()
/*
* Now that we can access the I/O ports for comport 0, printf works...
*/
+ /* determine number of available CPUs */
+ _cpus = setup_affinity_space(hip);
/*
* Mark successful boot of hypervisor for automatic tests. This must be
@@ -370,7 +370,7 @@ Platform::Platform()
" vs ", sizeof(map_cpu_ids) / sizeof(map_cpu_ids[0]));
nova_die();
}
- if (!hip.remap_cpu_ids(map_cpu_ids, (unsigned)boot_cpu())) {
+ if (!hip.remap_cpu_ids(map_cpu_ids, cpu_numa_map, (unsigned)boot_cpu())) {
error("re-ording cpu_id failed");
nova_die();
}
@@ -405,6 +405,8 @@ Platform::Platform()
size_t const num_mem_desc = (hip.hip_length - hip.mem_desc_offset)
/ hip.mem_desc_size;
+ log("HIP is ", hip.hip_length, " bytes long.");
+
addr_t mem_desc_base = ((addr_t)&hip + hip.mem_desc_offset);
/* define core's virtual address space */
@@ -477,6 +479,8 @@ Platform::Platform()
bool efi_boot = false;
size_t kernel_memory = 0;
+ log("Found ", num_mem_desc, " memory entries in HIP");
+ memset(numa_mem_ranges, 0, sizeof(Genode::Range_allocator::Range) * MAX_SUPPORTED_CPUS);
/*
* All "available" ram must be added to our physical allocator before all
* non "available" regions that overlaps with ram get removed.
@@ -497,7 +501,7 @@ Platform::Platform()
uint64_t const base = mem_desc->addr;
uint64_t const size = mem_desc->size;
log("detected physical memory: ", Hex(base, Hex::PREFIX, Hex::PAD),
- " - size: ", Hex(size, Hex::PREFIX, Hex::PAD));
+ " - size: ", Hex(size, Hex::PREFIX, Hex::PAD), " - node: ", mem_desc->domain, " type: ", static_cast(mem_desc->type));
}
if (!mem_desc->size) continue;
@@ -519,6 +523,11 @@ Platform::Platform()
_io_mem_alloc.remove_range((addr_t)base, (size_t)size);
ram_alloc().add_range((addr_t)base, (size_t)size);
+ log("Add mem range ", reinterpret_cast(base), "-", reinterpret_cast(base + size), " for node ", mem_desc->domain);
+ if (numa_mem_ranges[mem_desc->domain].start == 0)
+ numa_mem_ranges[mem_desc->domain] = {base, base + size};
+ else if (base > numa_mem_ranges[mem_desc->domain].end)
+ numa_mem_ranges[mem_desc->domain].end = base + size;
}
addr_t hyp_log = 0;
@@ -647,17 +656,19 @@ Platform::Platform()
_init_rom_modules();
- auto export_pages_as_rom_module = [&] (auto rom_name, size_t pages, auto content_fn)
+ auto export_pages_as_rom_module = [&](auto rom_name, size_t pages, auto content_fn)
{
size_t const bytes = pages << get_page_size_log2();
ram_alloc().alloc_aligned(bytes, get_page_size_log2()).with_result(
- [&] (void *phys_ptr) {
-
+ [&](void *phys_ptr)
+ {
+ log("Allocated mem for ROM module succefully.");
addr_t const phys_addr = reinterpret_cast(phys_ptr);
char * const core_local_ptr = (char *)_map_pages(phys_addr, pages);
- if (!core_local_ptr) {
+ if (!core_local_ptr)
+ {
warning("failed to export ", rom_name, " as ROM module");
ram_alloc().free(phys_ptr, bytes);
return;
@@ -667,32 +678,39 @@ Platform::Platform()
content_fn(core_local_ptr, bytes);
_rom_fs.insert(new (core_mem_alloc())
- Rom_module(phys_addr, bytes, rom_name));
+ Rom_module(phys_addr, bytes, rom_name));
+ log("ROM succesfully inserted.");
/* leave the ROM backing store mapped within core */
},
- [&] (Range_allocator::Alloc_error) {
- warning("failed to allocate physical memory for exporting ",
- rom_name, " as ROM module"); });
+ [&](Range_allocator::Alloc_error)
+ { warning("failed to allocate physical memory for exporting ",
+ rom_name, " as ROM module"); });
};
- export_pages_as_rom_module("platform_info", 1,
- [&] (char * const ptr, size_t const size) {
- Xml_generator xml(ptr, size, "platform_info", [&] ()
- {
+ export_pages_as_rom_module("platform_info", 1 + (MAX_SUPPORTED_CPUS / 32),
+ [&](char *const ptr, size_t const size)
+ {
+ log("Exporting platform info as ROM module");
+ Xml_generator xml(ptr, size, "platform_info", [&]()
+ {
+ log("Report kernel");
xml.node("kernel", [&] () {
xml.attribute("name", "nova");
xml.attribute("acpi", true);
xml.attribute("msi" , true);
});
- if (efi_sys_tab_phy) {
+ if (efi_sys_tab_phy)
+ {
+ log("Report EFI system table");
xml.node("efi-system-table", [&] () {
xml.attribute("address", String<32>(Hex(efi_sys_tab_phy)));
});
}
xml.node("acpi", [&] () {
+ log("Report ACPI");
xml.attribute("revision", 2); /* XXX */
if (rsdt)
@@ -701,11 +719,15 @@ Platform::Platform()
if (xsdt)
xml.attribute("xsdt", String<32>(Hex(xsdt)));
});
+
+ log("Report Affinity-space");
xml.node("affinity-space", [&] () {
xml.attribute("width", _cpus.width());
xml.attribute("height", _cpus.height());
});
- xml.node("boot", [&] () {
+ log("Report boot framebuffer");
+ xml.node("boot", [&]()
+ {
if (!boot_fb)
return;
@@ -719,20 +741,26 @@ Platform::Platform()
xml.attribute("bpp", Resolution::Bpp::get(boot_fb->size));
xml.attribute("type", Resolution::Type::get(boot_fb->size));
xml.attribute("pitch", boot_fb->aux);
- });
- });
+ }); });
+ log("Report Hardware");
xml.node("hardware", [&] () {
+ log("Report HW features");
xml.node("features", [&] () {
xml.attribute("svm", hip.has_feature_svm());
xml.attribute("vmx", hip.has_feature_vmx());
});
+ log("Report TSC");
xml.node("tsc", [&] () {
xml.attribute("invariant", cpuid_invariant_tsc());
xml.attribute("freq_khz" , hip.tsc_freq);
});
- xml.node("cpus", [&] () {
- hip.for_each_enabled_cpu([&](Hip::Cpu_desc const &cpu, unsigned i) {
- xml.node("cpu", [&] () {
+ log("Report CPUs");
+ xml.node("cpus", [&]()
+ {
+ hip.for_each_enabled_cpu([&](Hip::Cpu_desc const &cpu, unsigned i)
+ {
+ xml.node("cpu", [&]()
+ {
xml.attribute("id", i);
xml.attribute("package", cpu.package);
xml.attribute("core", cpu.core);
@@ -741,19 +769,16 @@ Platform::Platform()
xml.attribute("model", String<5>(Hex(cpu.model)));
xml.attribute("stepping", String<5>(Hex(cpu.stepping)));
xml.attribute("platform", String<5>(Hex(cpu.platform)));
- xml.attribute("patch", String<12>(Hex(cpu.patch)));
- });
- });
- });
- });
- });
- }
- );
+ xml.attribute("patch", String<12>(Hex(cpu.patch))); }); }); });
+ }); });
+ log("Exported platform info, succesfully.");
+ });
export_pages_as_rom_module("core_log", 4,
- [&] (char * const ptr, size_t const size) {
- init_core_log( Core_log_range { (addr_t)ptr, size } );
- });
+ [&](char *const ptr, size_t const size)
+ {
+ init_core_log(Core_log_range{(addr_t)ptr, size});
+ });
/* export hypervisor log memory */
if (hyp_log && hyp_log_size)
@@ -782,7 +807,7 @@ Platform::Platform()
cpu->core, ":", cpu->thread);
log(" remap (", location.xpos(), "x", location.ypos(),") -> ",
- kernel_cpu_id, " - ", text, ") ",
+ kernel_cpu_id, " - ", text, " node: ", cpu->numa_id, ") ",
boot_cpu() == kernel_cpu_id ? "boot cpu" : "");
});
}
diff --git a/repos/base-nova/src/core/ram_dataspace_support.cc b/repos/base-nova/src/core/ram_dataspace_support.cc
index a850892905..066e4ca203 100644
--- a/repos/base-nova/src/core/ram_dataspace_support.cc
+++ b/repos/base-nova/src/core/ram_dataspace_support.cc
@@ -58,15 +58,16 @@ void Ram_dataspace_factory::_clear_ds(Dataspace_component &ds)
{
size_t const page_rounded_size = align_addr(ds.size(), get_page_size_log2());
- size_t memset_count = page_rounded_size / 4;
- addr_t memset_ptr = ds.core_local_addr();
+ //size_t memset_count = page_rounded_size / 4;
+ //addr_t memset_ptr = ds.core_local_addr();
+ /*
if ((memset_count * 4 == page_rounded_size) && !(memset_ptr & 0x3))
asm volatile ("rep stosl" : "+D" (memset_ptr), "+c" (memset_count)
: "a" (0) : "memory");
else
memset(reinterpret_cast(memset_ptr), 0, page_rounded_size);
-
+ */
/* we don't keep any core-local mapping */
unmap_local(*reinterpret_cast(Thread::myself()->utcb()),
ds.core_local_addr(),
diff --git a/repos/base-nova/src/lib/ld/nova/target.mk b/repos/base-nova/src/lib/ld/nova/target.mk
deleted file mode 100644
index f9615eec76..0000000000
--- a/repos/base-nova/src/lib/ld/nova/target.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = ld-nova
-LIBS = ld-nova
diff --git a/repos/base-okl4/recipes/src/base-okl4/content.mk b/repos/base-okl4/recipes/src/base-okl4/content.mk
index 39d7d59d8a..4caca8c8cd 100644
--- a/repos/base-okl4/recipes/src/base-okl4/content.mk
+++ b/repos/base-okl4/recipes/src/base-okl4/content.mk
@@ -19,8 +19,7 @@ src/kernel/okl4: src/kernel
content:
for spec in x86_32; do \
- mv lib/mk/spec/$$spec/ld-okl4.mk lib/mk/spec/$$spec/ld.mk; \
+ mv lib/mk/spec/$$spec/ld-okl4.mk lib/mk/spec/$$spec/ld.mk; \
done;
- sed -i "s/ld-okl4/ld/" src/lib/ld/okl4/target.mk
sed -i "s/pit_timer_drv/timer/" src/timer/pit/target.inc
diff --git a/repos/base-okl4/recipes/src/base-okl4/hash b/repos/base-okl4/recipes/src/base-okl4/hash
index 606a20a29b..acee3cdeb5 100644
--- a/repos/base-okl4/recipes/src/base-okl4/hash
+++ b/repos/base-okl4/recipes/src/base-okl4/hash
@@ -1 +1 @@
-2022-05-24 3b2acba4ebd649394e26217802598cf650a4b226
+2022-10-11 b81b8b94731cda35017a740b0110ff4e8e233e07
diff --git a/repos/base-okl4/src/lib/ld/okl4/target.mk b/repos/base-okl4/src/lib/ld/okl4/target.mk
deleted file mode 100644
index 1d041e3cd2..0000000000
--- a/repos/base-okl4/src/lib/ld/okl4/target.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = ld-okl4
-LIBS = ld-okl4
diff --git a/repos/base-pistachio/recipes/src/base-pistachio/content.mk b/repos/base-pistachio/recipes/src/base-pistachio/content.mk
index b8c9dbb474..c33056fc45 100644
--- a/repos/base-pistachio/recipes/src/base-pistachio/content.mk
+++ b/repos/base-pistachio/recipes/src/base-pistachio/content.mk
@@ -21,6 +21,5 @@ content:
for spec in x86_32; do \
mv lib/mk/spec/$$spec/ld-pistachio.mk lib/mk/spec/$$spec/ld.mk; \
done;
- sed -i "s/ld-pistachio/ld/" src/lib/ld/pistachio/target.mk
sed -i "s/pit_timer_drv/timer/" src/timer/pit/target.inc
diff --git a/repos/base-pistachio/recipes/src/base-pistachio/hash b/repos/base-pistachio/recipes/src/base-pistachio/hash
index 73e511a7ee..6177cd0ad9 100644
--- a/repos/base-pistachio/recipes/src/base-pistachio/hash
+++ b/repos/base-pistachio/recipes/src/base-pistachio/hash
@@ -1 +1 @@
-2022-05-24 ca2c90ebcbaa61ade7373d6ea48a608912cd2629
+2022-10-11 b522663f9c8c779f255e2a5eb37f98b4301c5446
diff --git a/repos/base-pistachio/src/lib/ld/pistachio/target.mk b/repos/base-pistachio/src/lib/ld/pistachio/target.mk
deleted file mode 100644
index af224bfef8..0000000000
--- a/repos/base-pistachio/src/lib/ld/pistachio/target.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = ld-pistachio
-LIBS = ld-pistachio
diff --git a/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/content.mk b/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/content.mk
index 82d866de9c..3e4a0c2acb 100644
--- a/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/content.mk
+++ b/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/content.mk
@@ -35,7 +35,6 @@ etc/board.conf:
content:
mv lib/mk/spec/arm/ld-sel4.mk lib/mk/spec/arm/ld.mk;
- sed -i "s/ld-sel4/ld/" src/lib/ld/sel4/target.mk
sed -i "s/imx6_timer_drv/timer/" src/timer/epit/imx6/target.inc
find lib/mk/spec -name kernel-sel4-*.mk -o -name syscall-sel4-*.mk |\
grep -v "sel4-imx6q_sabrelite.mk" | xargs rm -rf
diff --git a/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/hash b/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/hash
index e47ab7ffe0..9b27295d9e 100644
--- a/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/hash
+++ b/repos/base-sel4/recipes/src/base-sel4-imx6q_sabrelite/hash
@@ -1 +1 @@
-2022-05-24 5d9558d34f4bd3f3e34d9b175fe3eb37be3561be
+2022-10-11 6966c1e6595fec6e545ae729b9a5893e745a9fc9
diff --git a/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/content.mk b/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/content.mk
index bb357a3ed8..d339aec070 100644
--- a/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/content.mk
+++ b/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/content.mk
@@ -35,7 +35,6 @@ etc/board.conf:
content:
mv lib/mk/spec/arm/ld-sel4.mk lib/mk/spec/arm/ld.mk;
- sed -i "s/ld-sel4/ld/" src/lib/ld/sel4/target.mk
sed -i "s/imx7_timer_drv/timer/" src/timer/gpt/imx7/target.inc
find lib/mk/spec -name kernel-sel4-*.mk -o -name syscall-sel4-*.mk |\
grep -v "sel4-imx7d_sabre.mk" | xargs rm -rf
diff --git a/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/hash b/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/hash
index 5ef0c29af4..bfb3e928ec 100644
--- a/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/hash
+++ b/repos/base-sel4/recipes/src/base-sel4-imx7d_sabre/hash
@@ -1 +1 @@
-2022-05-24 70a360e5c7b6aed126fb99fc3666cfce030cf53e
+2022-10-11 e11873b5f947ab3013208e8b4ad7621113b00580
diff --git a/repos/base-sel4/recipes/src/base-sel4-x86/content.mk b/repos/base-sel4/recipes/src/base-sel4-x86/content.mk
index 7d706f6fd2..cca289d09e 100644
--- a/repos/base-sel4/recipes/src/base-sel4-x86/content.mk
+++ b/repos/base-sel4/recipes/src/base-sel4-x86/content.mk
@@ -26,7 +26,6 @@ content:
for spec in x86_32 x86_64 arm; do \
mv lib/mk/spec/$$spec/ld-sel4.mk lib/mk/spec/$$spec/ld.mk; \
done;
- sed -i "s/ld-sel4/ld/" src/lib/ld/sel4/target.mk
sed -i "s/pit_timer_drv/timer/" src/timer/pit/target.inc
find lib/mk/spec -name kernel-sel4-*.mk -o -name syscall-sel4-*.mk |\
grep -v "sel4-pc.mk" | xargs rm -rf
diff --git a/repos/base-sel4/recipes/src/base-sel4-x86/hash b/repos/base-sel4/recipes/src/base-sel4-x86/hash
index 00c88112bc..44aa295142 100644
--- a/repos/base-sel4/recipes/src/base-sel4-x86/hash
+++ b/repos/base-sel4/recipes/src/base-sel4-x86/hash
@@ -1 +1 @@
-2022-05-24 fa03ec1bf7ea9b643319d67dbd52e146e0d98189
+2022-10-11 b816b62207fc76123ce72f844fa3914163949f56
diff --git a/repos/base-sel4/src/lib/ld/sel4/target.mk b/repos/base-sel4/src/lib/ld/sel4/target.mk
deleted file mode 100644
index 4e78c9b5b4..0000000000
--- a/repos/base-sel4/src/lib/ld/sel4/target.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = ld-sel4
-LIBS = ld-sel4
diff --git a/repos/base/board/pc/devices b/repos/base/board/pc/devices
new file mode 100644
index 0000000000..b5ca5a1261
--- /dev/null
+++ b/repos/base/board/pc/devices
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/repos/base/board/virt_qemu/qemu_args b/repos/base/board/virt_qemu_arm_v7a/qemu_args
similarity index 61%
rename from repos/base/board/virt_qemu/qemu_args
rename to repos/base/board/virt_qemu_arm_v7a/qemu_args
index 2d21c33626..183d6293ad 100644
--- a/repos/base/board/virt_qemu/qemu_args
+++ b/repos/base/board/virt_qemu_arm_v7a/qemu_args
@@ -1,9 +1,8 @@
-m 2048
+-M virt,virtualization=true -cpu cortex-a15 -smp 2
-global virtio-mmio.force-legacy=false
-device virtio-net-device,bus=virtio-mmio-bus.0,netdev=net0
-device virtio-mouse-device
-device virtio-keyboard-device
-device virtio-gpu-device
-netdev user,id=net0
-arm_v8a: -M virt,virtualization=true,gic-version=3 -cpu cortex-a53 -smp 4
-arm_v7a: -M virt,virtualization=true -cpu cortex-a15 -smp 2
diff --git a/repos/base/board/virt_qemu_arm_v8a/qemu_args b/repos/base/board/virt_qemu_arm_v8a/qemu_args
new file mode 100644
index 0000000000..a9c9e5f1f4
--- /dev/null
+++ b/repos/base/board/virt_qemu_arm_v8a/qemu_args
@@ -0,0 +1,8 @@
+-m 2048
+-M virt,virtualization=true,gic-version=3 -cpu cortex-a53 -smp 4
+-global virtio-mmio.force-legacy=false
+-device virtio-net-device,bus=virtio-mmio-bus.0,netdev=net0
+-device virtio-mouse-device
+-device virtio-keyboard-device
+-device virtio-gpu-device
+-netdev user,id=net0
diff --git a/repos/base/include/base/affinity.h b/repos/base/include/base/affinity.h
index 81d56f2f40..a41bcc4a24 100644
--- a/repos/base/include/base/affinity.h
+++ b/repos/base/include/base/affinity.h
@@ -189,10 +189,10 @@ class Genode::Affinity
Affinity::Space space { };
Affinity::Location location { };
- node.with_sub_node("affinity", [&] (Xml_node const &node) {
- node.with_sub_node("space", [&] (Xml_node const &node) {
+ node.with_optional_sub_node("affinity", [&] (Xml_node const &node) {
+ node.with_optional_sub_node("space", [&] (Xml_node const &node) {
space = Space::from_xml(node); });
- node.with_sub_node("location", [&] (Xml_node const &node) {
+ node.with_optional_sub_node("location", [&] (Xml_node const &node) {
location = Location::from_xml(space, node); });
});
diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h
index d38a3d75bd..403be1d9e9 100644
--- a/repos/base/include/base/child.h
+++ b/repos/base/include/base/child.h
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
namespace Genode {
@@ -609,6 +610,7 @@ class Genode::Child : protected Rpc_object,
Env_connection _cpu { *this, Env::cpu(), _policy.name() };
Env_connection _log { *this, Env::log(), _policy.name() };
Env_connection _binary { *this, Env::binary(), _policy.binary_name() };
+ Env_connection _topo { *this, Env::topo(), _policy.name() };
Constructible > _linker { };
@@ -761,6 +763,7 @@ class Genode::Child : protected Rpc_object,
Ram_allocator &ram() { return _pd.session(); }
Ram_allocator const &ram() const { return _pd.session(); }
Cpu_session &cpu() { return _cpu.session(); }
+ Topo_session &topo() { return _topo.session(); }
Pd_session &pd() { return _pd.session(); }
Pd_session const &pd() const { return _pd.session(); }
diff --git a/repos/base/include/base/env.h b/repos/base/include/base/env.h
index 57842dad8b..3425abbe67 100644
--- a/repos/base/include/base/env.h
+++ b/repos/base/include/base/env.h
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
namespace Genode { struct Env; }
@@ -48,6 +49,12 @@ struct Genode::Env : Interface
*/
Ram_allocator &ram() { return pd(); }
+ /**
+ * @brief Topology model
+ *
+ */
+ virtual Topo_session &topo() = 0;
+
/**
* Entrypoint for handling RPC requests and signals
*/
@@ -63,6 +70,12 @@ struct Genode::Env : Interface
*/
virtual Pd_session_capability pd_session_cap() = 0;
+ /**
+ * @brief Return the Topo-session capability
+ *
+ */
+ virtual Topo_session_capability topo_session_cap() = 0;
+
/**
* ID space of sessions obtained from the parent
*/
diff --git a/repos/base/include/base/ram_allocator.h b/repos/base/include/base/ram_allocator.h
index 46225e4592..e857959f89 100644
--- a/repos/base/include/base/ram_allocator.h
+++ b/repos/base/include/base/ram_allocator.h
@@ -40,6 +40,8 @@ struct Genode::Ram_allocator : Interface
struct Denied : Exception { };
+ typedef unsigned Numa_id;
+
/**
* Allocate RAM dataspace
*
@@ -50,6 +52,7 @@ struct Genode::Ram_allocator : Interface
* \return capability to RAM dataspace, or error code of type 'Alloc_error'
*/
virtual Alloc_result try_alloc(size_t size, Cache cache = CACHED) = 0;
+ virtual Alloc_result try_alloc(size_t size, Numa_id numa_id, Cache cache = CACHED) = 0;
/**
* Allocate RAM dataspace
@@ -154,6 +157,10 @@ class Genode::Constrained_ram_allocator : public Ram_allocator
);
}
+ Alloc_result try_alloc(size_t size, Numa_id, Cache cache = CACHED) override {
+ return this->Constrained_ram_allocator::try_alloc(size, cache); /* overriden in platform specific code */
+ }
+
void free(Ram_dataspace_capability ds) override
{
size_t const size = _ram_alloc.dataspace_size(ds);
diff --git a/repos/base/include/base/regional_heap.h b/repos/base/include/base/regional_heap.h
new file mode 100644
index 0000000000..f9332383f1
--- /dev/null
+++ b/repos/base/include/base/regional_heap.h
@@ -0,0 +1,230 @@
+/*
+ * \brief Heap partition
+ * \author Norman Feske
+ * \date 2006-05-15
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ * Copyright (C) 2006-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _INCLUDE__BASE__REGIONAL_HEAP_H_
+#define _INCLUDE__BASE__REGIONAL_HEAP_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Genode {
+
+ class Regional_heap;
+ class Sliced_regional_heap;
+}
+
+
+/**
+ * Heap that uses dataspaces as backing store and has a physical memory range limited to a single NUMA region
+ *
+ * The heap class provides an allocator that uses a list of dataspaces of a RAM
+ * allocator as backing store. One dataspace may be used for holding multiple
+ * blocks.
+ */
+class Genode::Regional_heap : public Allocator
+{
+ private:
+
+ class Dataspace : public List::Element
+ {
+ private:
+
+ /*
+ * Noncopyable
+ */
+ Dataspace(Dataspace const &);
+ Dataspace &operator = (Dataspace const &);
+
+ public:
+
+ Ram_dataspace_capability cap;
+ void *local_addr;
+ size_t size;
+
+ Dataspace(Ram_dataspace_capability c, void *local_addr, size_t size)
+ : cap(c), local_addr(local_addr), size(size) { }
+ };
+
+ /*
+ * This structure exists only to make sure that the dataspaces are
+ * destroyed after the AVL allocator.
+ */
+ class Dataspace_pool : public List
+ {
+ private:
+
+ /*
+ * Noncopyable
+ */
+ Dataspace_pool(Dataspace_pool const &);
+ Dataspace_pool &operator = (Dataspace_pool const &);
+
+ public:
+
+ Ram_allocator *ram_alloc; /* backing store */
+ Region_map *region_map;
+
+ Dataspace_pool(Ram_allocator *ram, Region_map *rm)
+ : ram_alloc(ram), region_map(rm) { }
+
+ ~Dataspace_pool();
+
+ void remove_and_free(Dataspace &);
+
+ void reassign_resources(Ram_allocator *ram, Region_map *rm) {
+ ram_alloc = ram, region_map = rm; }
+ };
+
+ Mutex mutable _mutex { };
+ Reconstructible _alloc; /* local allocator */
+ Dataspace_pool _ds_pool; /* list of dataspaces */
+ size_t _quota_limit { 0 };
+ size_t _quota_used { 0 };
+ size_t _chunk_size { 0 };
+ Ram_allocator::Numa_id _numa_id; /* ID of NUMA region to serve allocations from */
+
+ using Alloc_ds_result = Attempt;
+
+ /**
+ * Allocate a new dataspace of the specified size
+ *
+ * \param size number of bytes to allocate
+ * \param enforce_separate_metadata if true, the new dataspace
+ * will not contain any meta data
+ */
+ Alloc_ds_result _allocate_dataspace(size_t size, bool enforce_separate_metadata);
+
+ /**
+ * Try to allocate block at our local allocator
+ */
+ Alloc_result _try_local_alloc(size_t size);
+
+ /**
+ * Unsynchronized implementation of 'try_alloc'
+ */
+ Alloc_result _unsynchronized_alloc(size_t size);
+
+ public:
+
+ enum { UNLIMITED = ~0 };
+
+ Regional_heap(Ram_allocator *ram_allocator,
+ Region_map *region_map,
+ Topology::Numa_region ®ion,
+ size_t quota_limit = UNLIMITED,
+ void *static_addr = 0,
+ size_t static_size = 0);
+
+ Regional_heap(Ram_allocator &ram, Region_map &rm, Topology::Numa_region ®ion) : Regional_heap(&ram, &rm, region) { }
+
+ ~Regional_heap();
+
+ /**
+ * Reconfigure quota limit
+ *
+ * \return negative error code if new quota limit is higher than
+ * currently used quota.
+ */
+ int quota_limit(size_t new_quota_limit);
+
+ /**
+ * Re-assign RAM allocator and region map
+ */
+ void reassign_resources(Ram_allocator *ram, Region_map *rm) {
+ _ds_pool.reassign_resources(ram, rm); }
+
+ /**
+ * Call 'fn' with the start and size of each backing-store region
+ */
+ template
+ void for_each_region(FN const &fn) const
+ {
+ Mutex::Guard guard(_mutex);
+ for (Dataspace const *ds = _ds_pool.first(); ds; ds = ds->next())
+ fn(ds->local_addr, ds->size);
+ }
+
+
+ /*************************
+ ** Allocator interface **
+ *************************/
+
+ Alloc_result try_alloc(size_t) override;
+ void free(void *, size_t) override;
+ size_t consumed() const override { return _quota_used; }
+ size_t overhead(size_t size) const override { return _alloc->overhead(size); }
+ bool need_size_for_free() const override { return false; }
+};
+
+
+/**
+ * Heap that allocates each block at a separate dataspace
+ */
+class Genode::Sliced_regional_heap : public Allocator
+{
+ private:
+
+ /**
+ * Meta-data header placed in front of each allocated block
+ */
+ struct Block : List::Element
+ {
+ Ram_dataspace_capability const ds;
+ size_t const size;
+
+ Block(Ram_dataspace_capability ds, size_t size) : ds(ds), size(size)
+ { }
+ };
+
+ Ram_allocator &_ram_alloc; /* RAM allocator for backing store */
+ Region_map &_region_map; /* region map of the address space */
+ size_t _consumed = 0; /* number of allocated bytes */
+ List _blocks { }; /* list of allocated blocks */
+ Mutex _mutex { }; /* serialize allocations */
+
+ public:
+
+ /**
+ * Return size of header prepended to each allocated block in bytes
+ */
+ static constexpr size_t meta_data_size() { return sizeof(Block); }
+
+ /**
+ * Constructor
+ */
+ Sliced_regional_heap(Ram_allocator &ram_alloc, Region_map ®ion_map);
+
+ /**
+ * Destructor
+ */
+ ~Sliced_regional_heap();
+
+
+ /*************************
+ ** Allocator interface **
+ *************************/
+
+ Alloc_result try_alloc(size_t) override;
+ void free(void *, size_t) override;
+ size_t consumed() const override { return _consumed; }
+ size_t overhead(size_t size) const override;
+ bool need_size_for_free() const override { return false; }
+};
+
+#endif /* _INCLUDE__BASE__HEAP_H_ */
diff --git a/repos/base/include/base/rpc_server.h b/repos/base/include/base/rpc_server.h
index 6749849d22..66998550eb 100644
--- a/repos/base/include/base/rpc_server.h
+++ b/repos/base/include/base/rpc_server.h
@@ -481,6 +481,17 @@ class Genode::Rpc_entrypoint : Thread, public Object_pool
* This method is solely needed on Linux.
*/
bool is_myself() const;
+
+ /**
+ * Check whether given stack info matches stack of the entrypoint.
+ *
+ * \noapi
+ *
+ */
+ bool myself(addr_t const ptr) const
+ {
+ return addr_t(stack_base()) <= ptr && ptr <= addr_t(stack_top());
+ }
};
diff --git a/repos/base/include/base/thread.h b/repos/base/include/base/thread.h
index 08f7531afb..8604d2c2e4 100644
--- a/repos/base/include/base/thread.h
+++ b/repos/base/include/base/thread.h
@@ -49,6 +49,7 @@ class Genode::Thread
typedef Affinity::Location Location;
typedef Cpu_session::Name Name;
typedef Cpu_session::Weight Weight;
+ typedef unsigned Numa_id;
struct Stack_info { addr_t base; addr_t top;
addr_t libc_tls_pointer_offset; };
@@ -428,6 +429,8 @@ class Genode::Thread
* Thread affinity
*/
Affinity::Location affinity() const { return _affinity; }
+
+ void pin(Affinity::Location &loc);
};
#endif /* _INCLUDE__BASE__THREAD_H_ */
diff --git a/repos/base/include/base/trace/buffer.h b/repos/base/include/base/trace/buffer.h
index 59222f5e89..4ad84bb640 100644
--- a/repos/base/include/base/trace/buffer.h
+++ b/repos/base/include/base/trace/buffer.h
@@ -257,6 +257,9 @@ class Genode::Trace::Simple_buffer
size_t length() const { return _entry->len; }
char const *data() const { return _entry->data; }
+ template
+ T const &object() const { return *reinterpret_cast(data()); }
+
/* return whether entry is valid, i.e. length field is present */
bool last() const { return _entry == 0; }
diff --git a/repos/base/include/base/trace/events.h b/repos/base/include/base/trace/events.h
index 0b6f61e48a..b5d6026174 100644
--- a/repos/base/include/base/trace/events.h
+++ b/repos/base/include/base/trace/events.h
@@ -25,6 +25,8 @@ namespace Genode { namespace Trace {
struct Rpc_reply;
struct Signal_submit;
struct Signal_received;
+ struct Checkpoint;
+ struct Ethernet_packet;
} }
@@ -121,4 +123,62 @@ struct Genode::Trace::Signal_received
};
+struct Genode::Trace::Checkpoint
+{
+ enum Type : unsigned char {
+ UNDEF = 0x0,
+ START = 0x1,
+ END = 0x2,
+ OBJ_NEW = 0x10,
+ OBJ_DEL = 0x11,
+ OBJ_STATE = 0x12,
+ EXCEPTION = 0xfe,
+ FAILURE = 0xff
+ };
+
+ char const *name;
+ unsigned long const data;
+ Type const type;
+ void *addr;
+
+ Checkpoint(char const *name, unsigned long data, void *addr, Type type=Type::UNDEF)
+ : name(name), data(data), type(type), addr(addr)
+ {
+ Thread::trace(this);
+ }
+
+ size_t generate(Policy_module &policy, char *dst) const {
+ return policy.checkpoint(dst, name, data, addr, type); }
+};
+
+
+struct Genode::Trace::Ethernet_packet
+{
+ enum Direction : char {
+ RECV = 0x0,
+ SENT = 0x1
+ };
+
+ char const *name;
+ Direction direction;
+ char *data;
+ size_t length;
+
+ Ethernet_packet(char const *name, Direction direction, char *data, size_t len)
+ : name(name), direction(direction), data(data), length(len)
+ {
+ Thread::trace(this);
+ }
+
+ Ethernet_packet(char const *name, Direction direction, void *data, size_t len)
+ : name(name), direction(direction), data((char*)data), length(len)
+ {
+ Thread::trace(this);
+ }
+
+ size_t generate(Policy_module &policy, char *dst) const {
+ return policy.trace_eth_packet(dst, name, direction == Direction::SENT, data, length); }
+};
+
+
#endif /* _INCLUDE__BASE__TRACE__EVENTS_H_ */
diff --git a/repos/base/include/base/trace/policy.h b/repos/base/include/base/trace/policy.h
index 969c7ff062..05b8b2dd5a 100644
--- a/repos/base/include/base/trace/policy.h
+++ b/repos/base/include/base/trace/policy.h
@@ -31,14 +31,16 @@ namespace Genode {
*/
struct Genode::Trace::Policy_module
{
- size_t (*max_event_size) ();
- size_t (*log_output) (char *, char const *, size_t);
- size_t (*rpc_call) (char *, char const *, Msgbuf_base const &);
- size_t (*rpc_returned) (char *, char const *, Msgbuf_base const &);
- size_t (*rpc_dispatch) (char *, char const *);
- size_t (*rpc_reply) (char *, char const *);
- size_t (*signal_submit) (char *, unsigned const);
- size_t (*signal_received) (char *, Signal_context const &, unsigned const);
+ size_t (*max_event_size) ();
+ size_t (*trace_eth_packet) (char *, char const *, bool, char *, size_t);
+ size_t (*checkpoint) (char *, char const *, unsigned long, void *, unsigned char);
+ size_t (*log_output) (char *, char const *, size_t);
+ size_t (*rpc_call) (char *, char const *, Msgbuf_base const &);
+ size_t (*rpc_returned) (char *, char const *, Msgbuf_base const &);
+ size_t (*rpc_dispatch) (char *, char const *);
+ size_t (*rpc_reply) (char *, char const *);
+ size_t (*signal_submit) (char *, unsigned const);
+ size_t (*signal_received) (char *, Signal_context const &, unsigned const);
};
#endif /* _INCLUDE__BASE__TRACE__POLICY_H_ */
diff --git a/repos/base/include/cpu_session/client.h b/repos/base/include/cpu_session/client.h
index e677d64ef5..60e65f801b 100644
--- a/repos/base/include/cpu_session/client.h
+++ b/repos/base/include/cpu_session/client.h
@@ -33,6 +33,9 @@ struct Genode::Cpu_session_client : Rpc_client
void kill_thread(Thread_capability thread) override {
call(thread); }
+ void migrate_thread(Thread_capability thread, Affinity::Location loc) override {
+ call(thread, loc); }
+
void exception_sigh(Signal_context_capability sigh) override {
call(sigh); }
diff --git a/repos/base/include/cpu_session/cpu_session.h b/repos/base/include/cpu_session/cpu_session.h
index 67389f49e1..6297d5eadf 100644
--- a/repos/base/include/cpu_session/cpu_session.h
+++ b/repos/base/include/cpu_session/cpu_session.h
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
namespace Genode {
@@ -109,6 +110,14 @@ struct Genode::Cpu_session : Session
*/
virtual void kill_thread(Thread_capability thread) = 0;
+ /**
+ * Migrate a thread to a new location
+ *
+ * \param thread capability of the thread to migrate
+ * \param loc component-local location to migrate the thread to
+ */
+ virtual void migrate_thread(Thread_capability thread, Genode::Affinity::Location loc) = 0;
+
/**
* Register default signal handler for exceptions
*
@@ -237,6 +246,7 @@ struct Genode::Cpu_session : Session
Capability, Name const &, Affinity::Location,
Weight, addr_t);
GENODE_RPC(Rpc_kill_thread, void, kill_thread, Thread_capability);
+ GENODE_RPC(Rpc_migrate_thread, void, migrate_thread, Thread_capability, Affinity::Location);
GENODE_RPC(Rpc_exception_sigh, void, exception_sigh, Signal_context_capability);
GENODE_RPC(Rpc_affinity_space, Affinity::Space, affinity_space);
GENODE_RPC(Rpc_trace_control, Dataspace_capability, trace_control);
@@ -247,7 +257,7 @@ struct Genode::Cpu_session : Session
GENODE_RPC_INTERFACE(Rpc_create_thread, Rpc_kill_thread, Rpc_exception_sigh,
Rpc_affinity_space, Rpc_trace_control, Rpc_ref_account,
- Rpc_transfer_quota, Rpc_quota, Rpc_native_cpu);
+ Rpc_transfer_quota, Rpc_quota, Rpc_native_cpu, Rpc_migrate_thread);
};
diff --git a/repos/base/include/deprecated/env.h b/repos/base/include/deprecated/env.h
index 4164e40c2c..5a76a0a8cb 100644
--- a/repos/base/include/deprecated/env.h
+++ b/repos/base/include/deprecated/env.h
@@ -22,6 +22,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -87,6 +89,9 @@ struct Genode::Env_deprecated : Interface
*/
virtual Pd_session *pd_session() = 0;
virtual Pd_session_capability pd_session_cap() = 0;
+
+ virtual Topo_session *topo_session() = 0;
+ virtual Topo_session_capability topo_session_cap() = 0;
};
#endif /* _INCLUDE__DEPRECATED__ENV_H_ */
diff --git a/repos/base/include/irq_session/connection.h b/repos/base/include/irq_session/connection.h
index 38cb643640..f4b8f85ced 100644
--- a/repos/base/include/irq_session/connection.h
+++ b/repos/base/include/irq_session/connection.h
@@ -42,6 +42,26 @@ struct Genode::Irq_connection : Connection, Irq_session_client
irq, trigger, polarity, device_config_phys)),
Irq_session_client(cap())
{ }
+
+ /**
+ * Constructor for label-based configuration (used by pin driver)
+ *
+ * \param label session label
+ */
+ Irq_connection(Env &env,
+ char const *label)
+ :
+ Connection(env, session(env.parent(),
+ "ram_quota=%u, cap_quota=%u, "
+ "irq_number=%u, irq_trigger=%u, "
+ "irq_polarity=%u, device_config_phys=0x%lx, "
+ "label=\"%s\"",
+ RAM_QUOTA, CAP_QUOTA, 0,
+ Irq_session::TRIGGER_UNCHANGED,
+ Irq_session::POLARITY_UNCHANGED,
+ 0, label)),
+ Irq_session_client(cap())
+ { }
};
#endif /* _INCLUDE__IRQ_SESSION__CONNECTION_H_ */
diff --git a/repos/base/include/parent/parent.h b/repos/base/include/parent/parent.h
index 7379342e5b..2bc99ce6c6 100644
--- a/repos/base/include/parent/parent.h
+++ b/repos/base/include/parent/parent.h
@@ -71,7 +71,8 @@ class Genode::Parent
static Client::Id log() { return { 3 }; }
static Client::Id binary() { return { 4 }; }
static Client::Id linker() { return { 5 }; }
- static Client::Id last() { return { 5 }; }
+ static Client::Id topo() { return { 6 }; }
+ static Client::Id last() { return { 6 }; }
/**
* True if session ID refers to an environment session
diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h
index e578f192cd..9ee05e3700 100644
--- a/repos/base/include/pd_session/client.h
+++ b/repos/base/include/pd_session/client.h
@@ -77,6 +77,11 @@ struct Genode::Pd_session_client : Rpc_client
{
return call(size, cache);
}
+
+ Alloc_result try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cache = CACHED) override
+ {
+ return call(size, numa_id, cache);
+ }
void free(Ram_dataspace_capability ds) override { call(ds); }
diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h
index 9f6c7871c4..c6baa209e5 100644
--- a/repos/base/include/pd_session/pd_session.h
+++ b/repos/base/include/pd_session/pd_session.h
@@ -284,6 +284,11 @@ struct Genode::Pd_session : Session, Ram_allocator
*/
Ram_quota avail_ram() const { return { ram_quota().value - used_ram().value }; }
+ /**
+ * \brief Create new dataspace factory for given NUMA node
+ * \param
+ */
+
/*****************************************
** Access to kernel-specific interface **
@@ -381,6 +386,7 @@ struct Genode::Pd_session : Session, Ram_allocator
GENODE_RPC(Rpc_used_caps, Cap_quota, used_caps);
GENODE_RPC(Rpc_try_alloc, Alloc_result, try_alloc, size_t, Cache);
+ GENODE_RPC(Rpc_try_alloc_numa, Alloc_result, try_alloc, size_t, Ram_allocator::Numa_id, Cache);
GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability);
GENODE_RPC_THROW(Rpc_transfer_ram_quota, void, transfer_quota,
GENODE_TYPE_LIST(Out_of_ram, Invalid_session, Undefined_ref_account),
@@ -402,7 +408,7 @@ struct Genode::Pd_session : Session, Ram_allocator
Rpc_alloc_rpc_cap, Rpc_free_rpc_cap, Rpc_address_space,
Rpc_stack_area, Rpc_linker_area, Rpc_ref_account,
Rpc_transfer_cap_quota, Rpc_cap_quota, Rpc_used_caps,
- Rpc_try_alloc, Rpc_free,
+ Rpc_try_alloc, Rpc_try_alloc_numa, Rpc_free,
Rpc_transfer_ram_quota, Rpc_ram_quota, Rpc_used_ram,
Rpc_native_pd, Rpc_managing_system,
Rpc_dma_addr, Rpc_attach_dma);
diff --git a/repos/base/include/timer/timeout.h b/repos/base/include/timer/timeout.h
index c9fab0c45a..a76178931d 100644
--- a/repos/base/include/timer/timeout.h
+++ b/repos/base/include/timer/timeout.h
@@ -123,6 +123,8 @@ class Genode::Timeout : private Noncopyable,
void discard();
bool scheduled();
+
+ Microseconds deadline() const { return _deadline; }
};
diff --git a/repos/base/include/timer_session/connection.h b/repos/base/include/timer_session/connection.h
index cf126ca64b..4f24dea770 100644
--- a/repos/base/include/timer_session/connection.h
+++ b/repos/base/include/timer_session/connection.h
@@ -117,6 +117,8 @@ class Timer::One_shot_timeout : private Genode::Noncopyable,
void discard() { _timeout.discard(); }
bool scheduled() { return _timeout.scheduled(); }
+
+ Microseconds deadline() const { return _timeout.deadline(); }
};
diff --git a/repos/base/include/topo_session/capability.h b/repos/base/include/topo_session/capability.h
new file mode 100644
index 0000000000..17f7a1a01b
--- /dev/null
+++ b/repos/base/include/topo_session/capability.h
@@ -0,0 +1,22 @@
+/*
+ * \brief Topo-session capability type
+ * \author Michael Müller
+ * \date 2022-10-06
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalanOS, witch is based on Genode OS framework
+ * distributed under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Genode
+{
+ typedef Capability Topo_session_capability;
+} // namespace Genode
\ No newline at end of file
diff --git a/repos/base/include/topo_session/client.h b/repos/base/include/topo_session/client.h
new file mode 100644
index 0000000000..35d00fcbb8
--- /dev/null
+++ b/repos/base/include/topo_session/client.h
@@ -0,0 +1,44 @@
+/*
+ * \brief Client-side topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace Genode {
+ struct Topo_session_client;
+ struct Node;
+}
+
+struct Genode::Topo_session_client : Rpc_client
+{
+ explicit Topo_session_client(Topo_session_capability session)
+ : Rpc_client(session) { }
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override {
+ return call(loc);
+ }
+
+ Topology::Numa_region node_at_id(unsigned node_id) override {
+ return call(node_id);
+ }
+
+ unsigned node_count() override {
+ return call();
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/connection.h b/repos/base/include/topo_session/connection.h
new file mode 100644
index 0000000000..f20601f391
--- /dev/null
+++ b/repos/base/include/topo_session/connection.h
@@ -0,0 +1,50 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace Genode {
+ struct Topo_connection;
+}
+
+struct Genode::Topo_connection : Connection, Topo_session_client
+{
+ enum
+ {
+ RAM_QUOTA = 262144
+ };
+
+ Topo_connection(Env &env, const char *label = "", Affinity const &affinity = Affinity())
+ :
+ Connection(env,
+ session(env.parent(), affinity, "ram_quota=%u, cap_quota=%u, label=\"%s\"", RAM_QUOTA, CAP_QUOTA, label)),
+ Topo_session_client(cap()) {}
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override {
+ return Topo_session_client::node_affinity_of(loc);
+ }
+
+ Topology::Numa_region node_at_id(unsigned node_id) override {
+ return Topo_session_client::node_at_id(node_id);
+ }
+
+ unsigned node_count() override {
+ return Topo_session_client::node_count();
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/node.h b/repos/base/include/topo_session/node.h
new file mode 100644
index 0000000000..ffc7d631e2
--- /dev/null
+++ b/repos/base/include/topo_session/node.h
@@ -0,0 +1,58 @@
+/*
+ * \brief Representation of a NUMA node
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+
+namespace Topology {
+ struct Numa_region;
+}
+
+struct Topology::Numa_region : Genode::List::Element
+{
+ /* ID presented to component */
+ unsigned _id;
+
+ unsigned _core_count;
+ Genode::List neighbours;
+
+ /* Physical NUMA node ID */
+ unsigned _native_id;
+
+ Numa_region() : _id(0), _core_count(0), neighbours(), _native_id(0) { }
+ Numa_region(unsigned id, unsigned native_id) : _id(id), _core_count(0), neighbours(), _native_id(native_id) {}
+ Numa_region(Numa_region ©) : _id(copy.id()), _core_count(copy.core_count()), neighbours(), _native_id(copy.native_id()) {
+ }
+
+ unsigned native_id() { return _native_id; }
+ unsigned id() { return _id; }
+ unsigned core_count() { return _core_count; }
+ void core_count(unsigned count) { _core_count = count; }
+ void increment_core_count() { _core_count++; }
+ Numa_region &operator=(const Numa_region ©) {
+ if (this == ©)
+ return *this;
+
+ this->_id = copy._id;
+ this->_core_count = copy._core_count;
+ this->_native_id = copy._native_id;
+
+ /* At the moment, we do not copy the list of neighbours, as it is not used by any our applications. */
+ /* TODO: Copy list onf neighbours, as soons as any application is going to use that information. */
+
+ return *this;
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/topo_session.h b/repos/base/include/topo_session/topo_session.h
new file mode 100644
index 0000000000..d6f90b9d06
--- /dev/null
+++ b/repos/base/include/topo_session/topo_session.h
@@ -0,0 +1,58 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Genode {
+
+ struct Topo_session;
+ struct Topo_session_client;
+}
+
+namespace Topology
+{
+ struct Numa_region;
+} // namespace EalanOS
+
+struct Genode::Topo_session : Session
+{
+ /**
+ * \nooapi
+ *
+ */
+ static const char *service_name() { return "TOPO"; }
+
+ enum
+ {
+ CAP_QUOTA = 2
+ };
+
+ typedef Topo_session_client Client;
+
+ virtual ~Topo_session() { }
+
+ virtual Topology::Numa_region node_affinity_of(Affinity::Location const &) = 0;
+ virtual Topology::Numa_region node_at_id(unsigned node_id) = 0;
+ virtual unsigned node_count() = 0;
+
+ GENODE_RPC(Rpc_node_affinity, Topology::Numa_region, node_affinity_of, Affinity::Location const &);
+ GENODE_RPC(Rpc_node_id, Topology::Numa_region, node_at_id, unsigned);
+ GENODE_RPC(Rpc_node_count, unsigned, node_count);
+
+ GENODE_RPC_INTERFACE(Rpc_node_affinity, Rpc_node_id, Rpc_node_count);
+};
\ No newline at end of file
diff --git a/repos/base/include/trace/probe.h b/repos/base/include/trace/probe.h
new file mode 100644
index 0000000000..6a09ea7084
--- /dev/null
+++ b/repos/base/include/trace/probe.h
@@ -0,0 +1,85 @@
+/*
+ * \brief Trace probes
+ * \author Johannes Schlatow
+ * \date 2021-12-01
+ *
+ * Convenience macros for creating user-defined trace checkpoints.
+ */
+
+/*
+ * Copyright (C) 2021 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _INCLUDE__TRACE__PROBE_H_
+#define _INCLUDE__TRACE__PROBE_H_
+
+#include
+
+namespace Genode { namespace Trace {
+
+ class Duration
+ {
+ private:
+
+ char const *_name;
+ unsigned long const _data;
+
+ Duration(Duration const &) = delete;
+
+ Duration & operator = (Duration const &) = delete;
+
+ public:
+
+ Duration(char const * name, unsigned long data)
+ : _name(name), _data(data)
+ { Checkpoint(_name, _data, nullptr, Checkpoint::Type::START); }
+
+ ~Duration()
+ { Checkpoint(_name, _data, nullptr, Checkpoint::Type::END); }
+ };
+
+} }
+
+
+/**
+ * Trace a single checkpoint named after the current function.
+ *
+ * The argument 'data' specifies the payload as an unsigned value.
+ */
+#define GENODE_TRACE_CHECKPOINT(data) \
+ Genode::Trace::Checkpoint(__PRETTY_FUNCTION__, (unsigned long)data, nullptr);
+
+
+/**
+ * Variant of 'GENODE_TRACE_CHECKPOINT' that accepts the name of the checkpoint as argument.
+ *
+ * The argument 'data' specifies the payload as an unsigned value.
+ * The argument 'name' specifies the name of the checkpoint.
+ */
+#define GENODE_TRACE_CHECKPOINT_NAMED(data, name) \
+ Genode::Trace::Checkpoint(name, (unsigned long)data, nullptr);
+
+
+/**
+ * Trace a pair of checkpoints when entering and leaving the current scope.
+ *
+ * The argument 'data' specifies the payload as an unsigned value.
+ */
+#define GENODE_TRACE_DURATION(data) \
+ Genode::Trace::Duration duration(__PRETTY_FUNCTION__, (unsigned long)data);
+
+
+/**
+ * Variant of 'GENODE_TRACE_DURATION' that accepts the name of the checkpoints as argument.
+ *
+ * The argument 'data' specifies the payload as an unsigned value.
+ * The argument 'name' specifies the names of the checkpoints
+ */
+#define GENODE_TRACE_DURATION_NAMED(data, name) \
+ Genode::Trace::Duration duration(name, (unsigned long)data);
+
+
+#endif /* _INCLUDE__TRACE__PROBE_H_ */
diff --git a/repos/base/include/trace_session/client.h b/repos/base/include/trace_session/client.h
index 42276e607e..406bfbd93e 100644
--- a/repos/base/include/trace_session/client.h
+++ b/repos/base/include/trace_session/client.h
@@ -116,10 +116,6 @@ struct Genode::Trace::Session_client : Genode::Rpc_client(s, p, buffer_size); }
- void rule(Session_label const &label, Thread_name const &thread,
- Policy_id policy, size_t buffer_size) override {
- call(label, thread, policy, buffer_size); }
-
void pause(Subject_id subject) override {
call(subject); }
diff --git a/repos/base/include/trace_session/trace_session.h b/repos/base/include/trace_session/trace_session.h
index 1657aad55b..3bd61ba442 100644
--- a/repos/base/include/trace_session/trace_session.h
+++ b/repos/base/include/trace_session/trace_session.h
@@ -64,12 +64,6 @@ struct Genode::Trace::Session : Genode::Session
*/
virtual void trace(Subject_id, Policy_id, size_t buffer_size) = 0;
- /**
- * Install a matching rule for automatically tracing new threads
- */
- virtual void rule(Session_label const &, Thread_name const &,
- Policy_id, size_t buffer_size) = 0;
-
/**
* Pause generation of tracing data
*
@@ -124,10 +118,6 @@ struct Genode::Trace::Session : Genode::Session
Nonexistent_policy,
Traced_by_other_session),
Subject_id, Policy_id, size_t);
- GENODE_RPC_THROW(Rpc_rule, void, rule,
- GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
- Session_label const &, Thread_name const &,
- Policy_id, size_t);
GENODE_RPC_THROW(Rpc_pause, void, pause,
GENODE_TYPE_LIST(Nonexistent_subject), Subject_id);
GENODE_RPC_THROW(Rpc_resume, void, resume,
@@ -144,7 +134,7 @@ struct Genode::Trace::Session : Genode::Session
GENODE_TYPE_LIST(Nonexistent_subject), Subject_id);
GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_alloc_policy, Rpc_policy,
- Rpc_unload_policy, Rpc_trace, Rpc_rule, Rpc_pause,
+ Rpc_unload_policy, Rpc_trace, Rpc_pause,
Rpc_resume, Rpc_subjects, Rpc_buffer,
Rpc_free, Rpc_subject_infos);
};
diff --git a/repos/base/include/util/dictionary.h b/repos/base/include/util/dictionary.h
new file mode 100644
index 0000000000..c393b0776c
--- /dev/null
+++ b/repos/base/include/util/dictionary.h
@@ -0,0 +1,148 @@
+/*
+ * \brief Utility for accessing objects by name
+ * \author Norman Feske
+ * \date 2022-09-14
+ */
+
+/*
+ * Copyright (C) 2022 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _INCLUDE__UTIL__DICTIONARY_H_
+#define _INCLUDE__UTIL__DICTIONARY_H_
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Genode { template class Dictionary; }
+
+
+template
+class Genode::Dictionary : Noncopyable
+{
+ private:
+
+ Avl_tree _tree { };
+
+ public:
+
+ class Element : private Avl_node
+ {
+ public:
+
+ NAME const name;
+
+ private:
+
+ using This = Dictionary::Element;
+
+ Dictionary &_dictionary;
+
+ bool higher(T const *other) const { return name > other->This::name; }
+
+ friend class Avl_tree;
+ friend class Avl_node;
+ friend class Dictionary;
+
+ static T *_matching_sub_tree(T &curr, NAME const &name)
+ {
+ typename Avl_node::Side side = (curr.This::name > name);
+ return curr.Avl_node::child(side);
+ }
+
+ public:
+
+ Element(Dictionary &dictionary, NAME const &name)
+ :
+ name(name), _dictionary(dictionary)
+ {
+ if (_dictionary.exists(name))
+ warning("dictionary entry '", name, "' is not unique");
+
+ _dictionary._tree.insert(this);
+ }
+
+ ~Element()
+ {
+ _dictionary._tree.remove(this);
+ }
+ };
+
+ /**
+ * Call 'match_fn' with named constant dictionary element
+ *
+ * The 'match_fn' functor is called with a const reference to the
+ * matching dictionary element. If no maching element exists,
+ * 'no_match_fn' is called without argument.
+ */
+ template
+ auto with_element(NAME const &name, FN1 const &match_fn, FN2 const &no_match_fn)
+ -> typename Trait::Functor::Return_type
+ {
+ T *curr_ptr = _tree.first();
+ for (;;) {
+ if (!curr_ptr)
+ break;
+
+ if (curr_ptr->Element::name == name) {
+ return match_fn(*curr_ptr);
+ }
+
+ curr_ptr = Element::_matching_sub_tree(*curr_ptr, name);
+ }
+ return no_match_fn();
+ }
+
+ /**
+ * Call 'match_fn' with named mutable dictionary element
+ *
+ * The 'match_fn' functor is called with a non-const reference to the
+ * matching dictionary element. If no maching element exists,
+ * 'no_match_fn' is called without argument.
+ */
+ template
+ auto with_element(NAME const &name, FN1 const &match_fn, FN2 const &no_match_fn) const
+ -> typename Trait::Functor::Return_type
+ {
+ auto const_match_fn = [&] (T const &e) { return match_fn(e); };
+ auto non_const_this = const_cast(this);
+ return non_const_this->with_element(name, const_match_fn, no_match_fn);
+ }
+
+ /**
+ * Call 'fn' with a non-const reference to any dictionary element
+ *
+ * \return true if 'fn' was called, or
+ * false if the dictionary is empty
+ *
+ * This method is intended for the orderly destruction of a dictionary.
+ * It allows for the consecutive destruction of all elements.
+ */
+ template
+ bool with_any_element(FUNC const &fn)
+ {
+ T *curr_ptr = _tree.first();
+ if (!curr_ptr)
+ return false;
+
+ fn(*curr_ptr);
+ return true;
+ }
+
+ template
+ void for_each(FN const &fn) const { _tree.for_each(fn); }
+
+ bool exists(NAME const &name) const
+ {
+ return with_element(name, [] (T const &) { return true; },
+ [] { return false; });
+ }
+};
+
+#endif /* _INCLUDE__UTIL__DICTIONARY_H_ */
diff --git a/repos/base/include/util/string.h b/repos/base/include/util/string.h
index 683070132e..5eb4eb2162 100644
--- a/repos/base/include/util/string.h
+++ b/repos/base/include/util/string.h
@@ -459,20 +459,21 @@ namespace Genode {
/**
- * Read signed long value from string
+ * Read signed value from string
*
* \return number of consumed characters
*/
- inline size_t ascii_to(const char *s, long &result)
+ template
+ inline size_t ascii_to_signed(const char *s, T &result)
{
- int i = 0;
+ size_t i = 0;
/* read sign */
int sign = (*s == '-') ? -1 : 1;
if (*s == '-' || *s == '+') { s++; i++; }
- unsigned long value = 0;
+ T value = 0;
size_t const j = ascii_to_unsigned(s, value, 0);
@@ -484,6 +485,28 @@ namespace Genode {
}
+ /**
+ * Read signed long value from string
+ *
+ * \return number of consumed characters
+ */
+ inline size_t ascii_to(const char *s, long &result)
+ {
+ return ascii_to_signed(s, result);
+ }
+
+
+ /**
+ * Read signed integer value from string
+ *
+ * \return number of consumed characters
+ */
+ inline size_t ascii_to(const char *s, int &result)
+ {
+ return ascii_to_signed(s, result);
+ }
+
+
/**
* Read 'Number_of_bytes' value from string and handle the size suffixes
*
@@ -785,6 +808,12 @@ class Genode::String
return strcmp(string(), other.string()) != 0;
}
+ template
+ bool operator > (String const &other) const
+ {
+ return strcmp(string(), other.string()) > 0;
+ }
+
void print(Output &out) const { Genode::print(out, string()); }
};
diff --git a/repos/base/include/util/token.h b/repos/base/include/util/token.h
index e67d6e633d..2d60d00b94 100644
--- a/repos/base/include/util/token.h
+++ b/repos/base/include/util/token.h
@@ -110,7 +110,7 @@ class Genode::Token
/**
* Access single characters of token
*/
- char operator [] (int idx)
+ char operator [] (int idx) const
{
return ((idx >= 0) && ((unsigned)idx < _len)) ? _start[idx] : 0;
}
diff --git a/repos/base/include/util/xml_node.h b/repos/base/include/util/xml_node.h
index fede99d2b9..7dd4eefd0c 100644
--- a/repos/base/include/util/xml_node.h
+++ b/repos/base/include/util/xml_node.h
@@ -55,17 +55,16 @@ class Genode::Xml_attribute
struct Tokens
{
Token name;
- Token value;
+ Token equals { name .next().eat_whitespace() };
+ Token value { equals.next().eat_whitespace() };
- Tokens(Token t)
- : name(t.eat_whitespace()), value(name.next().next()) { };
+ Tokens(Token t) : name(t.eat_whitespace()) { };
bool valid() const
{
- bool const tag_present = (name.type() == Token::IDENT);
- bool const value_present = (name.next()[0] == '=' &&
- value.type() == Token::STRING);
- return tag_present && value_present;
+ return (name.type() == Token::IDENT)
+ && (equals[0] == '=')
+ && (value.type() == Token::STRING);
}
} _tokens;
@@ -103,7 +102,7 @@ class Genode::Xml_attribute
/**
* Return token following the attribute declaration
*/
- Token _next_token() const { return _tokens.name.next().next().next(); }
+ Token _next_token() const { return _tokens.value.next(); }
public:
@@ -355,7 +354,7 @@ class Genode::Xml_node
}
/**
- * Return true if tag as at least one attribute
+ * Return true if tag has at least one attribute
*/
bool has_attribute() const { return Xml_attribute::_valid(_name.next()); }
@@ -846,12 +845,27 @@ class Genode::Xml_node
* If no matching sub node exists, the functor is not called.
*/
template
- void with_sub_node(char const *type, FN const &fn) const
+ void with_optional_sub_node(char const *type, FN const &fn) const
{
if (has_sub_node(type))
fn(sub_node(type));
}
+ /**
+ * Apply functor 'fn' to first sub node of specified type
+ *
+ * The functor is called with the sub node as argument.
+ * If no matching sub node exists, the functor 'fn_nexists' is called.
+ */
+ template
+ void with_sub_node(char const *type, FN const &fn, FN_NEXISTS const &fn_nexists) const
+ {
+ if (has_sub_node(type))
+ fn(sub_node(type));
+ else
+ fn_nexists();
+ }
+
/**
* Execute functor 'fn' for each sub node of specified type
*/
diff --git a/repos/base/lib/mk/base-common.inc b/repos/base/lib/mk/base-common.inc
index 276f638946..074824120c 100644
--- a/repos/base/lib/mk/base-common.inc
+++ b/repos/base/lib/mk/base-common.inc
@@ -8,6 +8,7 @@ SRC_CC += avl_tree.cc
SRC_CC += slab.cc
SRC_CC += allocator_avl.cc
SRC_CC += heap.cc sliced_heap.cc
+SRC_CC += regional_heap.cc
SRC_CC += registry.cc
SRC_CC += console.cc
SRC_CC += output.cc
diff --git a/repos/base/lib/mk/ld.mk b/repos/base/lib/mk/ld.mk
index 4ba705717b..23fed31558 100644
--- a/repos/base/lib/mk/ld.mk
+++ b/repos/base/lib/mk/ld.mk
@@ -15,3 +15,6 @@ SHARED_LIB := yes
LD_OPT += -T$(BASE_DIR)/src/lib/ldso/linker.ld
LIBS += $(addprefix ld-,$(KERNEL))
+
+# as the stub libarary is not used at runtime, disregard it as build artifact
+BUILD_ARTIFACTS :=
diff --git a/repos/base/lib/mk/timeout-arm.mk b/repos/base/lib/mk/timeout-arm.mk
index e4af0c127f..064e501abd 100644
--- a/repos/base/lib/mk/timeout-arm.mk
+++ b/repos/base/lib/mk/timeout-arm.mk
@@ -3,6 +3,6 @@ SRC_CC += timer_connection.cc
SRC_CC += arm/timer_connection_time.cc
SRC_CC += duration.cc
-INC_DIR += $(BASE_DIR)/src/include
+REP_INC_DIR += src/include
-vpath % $(BASE_DIR)/src/lib/timeout
+vpath % $(call select_from_repositories,src/lib/timeout)
diff --git a/repos/base/lib/mk/timeout.mk b/repos/base/lib/mk/timeout.mk
index 5862c2343c..871948edda 100644
--- a/repos/base/lib/mk/timeout.mk
+++ b/repos/base/lib/mk/timeout.mk
@@ -4,6 +4,6 @@ SRC_CC += timer_connection_time.cc
SRC_CC += timer_connection_timestamp.cc
SRC_CC += duration.cc
-INC_DIR += $(BASE_DIR)/src/include
+REP_INC_DIR += src/include
vpath % $(call select_from_repositories,src/lib/timeout)
diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld
index 5a04b7470d..d4f08f65dd 100644
--- a/repos/base/lib/symbols/ld
+++ b/repos/base/lib/symbols/ld
@@ -38,6 +38,13 @@
# under the terms of the GNU Affero General Public License version 3.
#
+__atomic_store T
+__atomic_load T
+_Unwind_GetLanguageSpecificData T
+_Unwind_GetRegionStart T
+_Unwind_GetIP T
+_Unwind_SetGR T
+_Unwind_SetIP T
_Z11genode_exiti T
_Z16main_thread_utcbv T
_Z22__ldso_raise_exceptionv T
@@ -150,6 +157,26 @@ _ZN6Genode17Region_map_client6detachENS_10Region_map10Local_addrE T
_ZN6Genode17Region_map_client9dataspaceEv T
_ZN6Genode17Region_map_clientC1ENS_10CapabilityINS_10Region_mapEEE T
_ZN6Genode17Region_map_clientC2ENS_10CapabilityINS_10Region_mapEEE T
+_ZN6Genode13Regional_heap11quota_limitEm T
+_ZN6Genode13Regional_heap14Dataspace_pool15remove_and_freeERNS0_9DataspaceE T
+_ZN6Genode13Regional_heap14Dataspace_poolD1Ev T
+_ZN6Genode13Regional_heap14Dataspace_poolD2Ev T
+_ZN6Genode13Regional_heap16_try_local_allocEm T
+_ZN6Genode13Regional_heap19_allocate_dataspaceEmb T
+_ZN6Genode13Regional_heap21_unsynchronized_allocEm T
+_ZN6Genode13Regional_heap4freeEPvm T
+_ZN6Genode13Regional_heap9try_allocEm T
+_ZN6Genode13Regional_heapC1EPNS_13Ram_allocatorEPNS_10Region_mapERN8Topology11Numa_regionEmPvm T
+_ZN6Genode13Regional_heapC2EPNS_13Ram_allocatorEPNS_10Region_mapERN8Topology11Numa_regionEmPvm T
+_ZN6Genode13Regional_heapD0Ev T
+_ZN6Genode13Regional_heapD1Ev T
+_ZN6Genode13Regional_heapD2Ev T
+_ZNK6Genode13Regional_heap18need_size_for_freeEv T
+_ZNK6Genode13Regional_heap8consumedEv T
+_ZNK6Genode13Regional_heap8overheadEm T
+_ZTIN6Genode13Regional_heapE T
+_ZTSN6Genode13Regional_heapE T
+_ZTVN6Genode13Regional_heapE T
_ZN6Genode17Rm_session_client6createEm T
_ZN6Genode17Rm_session_client7destroyENS_10CapabilityINS_10Region_mapEEE T
_ZN6Genode17Rm_session_clientC1ENS_10CapabilityINS_10Rm_sessionEEE T
@@ -279,6 +306,7 @@ _ZN6Genode6Thread23stack_area_virtual_baseEv T
_ZN6Genode6Thread23stack_area_virtual_sizeEv T
_ZN6Genode6Thread4joinEv T
_ZN6Genode6Thread4nameEPcm T
+_ZN6Genode6Thread3pinERNS_8Affinity8LocationE T
_ZN6Genode6Thread4utcbEv T
_ZN6Genode6Thread5startEv T
_ZN6Genode6Thread6myselfEv T
@@ -616,8 +644,12 @@ _ZTVSt8bad_cast D 40
_ZTVSt9bad_alloc D 40
_ZTVSt9exception D 40
_ZTVSt9type_info D 64
+_ZdaPvSt11align_val_t W
_ZdlPv W
_ZdlPvm W
+_ZdlPvSt11align_val_t W
+_ZdlPvmSt11align_val_t W
+_ZnwmSt11align_val_t W
__aeabi_atexit W
__aeabi_unwind_cpp_pr0 T
__aeabi_unwind_cpp_pr1 T
diff --git a/repos/base/mk/dep_lib.mk b/repos/base/mk/dep_lib.mk
index c788b8ff64..fca6396daa 100644
--- a/repos/base/mk/dep_lib.mk
+++ b/repos/base/mk/dep_lib.mk
@@ -82,14 +82,19 @@ include $(BASE_DIR)/mk/base-libs.mk
include $(LIB_MK)
ifdef SHARED_LIB
-LIBS += ldso_so_support
+BUILD_ARTIFACTS ?= $(LIB).lib.so
+endif
# record creation of shared library build artifact
append_artifact_to_progress_log:
- @echo -e "\n# Build artifact $(LIB).lib.so\n" >> $(LIB_PROGRESS_LOG)
+ @( $(foreach A,$(BUILD_ARTIFACTS),\
+ echo -e "\n# Build artifact $A\n";) true \
+ ) >> $(LIB_PROGRESS_LOG)
append_lib_to_progress_log: append_artifact_to_progress_log
-endif
+ifdef SHARED_LIB
+LIBS += ldso_so_support
+endif
#
# Hide archive dependencies of shared libraries from users of the shared
@@ -119,8 +124,9 @@ warn_unsatisfied_requirements: generate_lib_rule_for_defect_library
@$(ECHO) "Skip library $(LIB) because it requires $(DARK_COL)$(UNSATISFIED_REQUIREMENTS)$(DEFAULT_COL)"
generate_lib_rule_for_defect_library:
- @echo "INVALID_DEPS += $(LIB)" >> $(LIB_DEP_FILE)
- @echo "" >> $(LIB_DEP_FILE)
+ @(echo "INVALID_DEPS += $(LIB)"; \
+ echo "$(LIB).lib:"; \
+ echo "") >> $(LIB_DEP_FILE)
LIBS_TO_VISIT = $(filter-out $(LIBS_READY),$(LIBS))
diff --git a/repos/base/mk/prg.mk b/repos/base/mk/prg.mk
index 6636d7f99d..3285274a33 100644
--- a/repos/base/mk/prg.mk
+++ b/repos/base/mk/prg.mk
@@ -183,7 +183,7 @@ $(LINK_ITEMS) $(TARGET): $(HOST_TOOLS)
#
# Trigger build of additional program specific targets
#
-$(TARGET): $(CUSTOM_TARGET_DEPS)
+all: $(CUSTOM_TARGET_DEPS)
LD_CMD += -Wl,--whole-archive -Wl,--start-group
LD_CMD += $(LINK_ITEMS_BRIEF)
diff --git a/repos/base/ports/grub2.hash b/repos/base/ports/grub2.hash
index 7bab68e1ba..9bb012cc65 100644
--- a/repos/base/ports/grub2.hash
+++ b/repos/base/ports/grub2.hash
@@ -1 +1 @@
-856f9946a1482cbebc519818e3e4736bcd11e5e4
+f15e84afbb47b892ed26a5ae56f5bb038777a3c0
diff --git a/repos/base/ports/grub2.port b/repos/base/ports/grub2.port
index e194a3483a..8daa867699 100644
--- a/repos/base/ports/grub2.port
+++ b/repos/base/ports/grub2.port
@@ -3,7 +3,7 @@ VERSION := git
DOWNLOADS := g2fg.git
URL(g2fg) := https://github.com/alex-ab/g2fg.git
-REV(g2fg) := a0c3164b6b23afb25119f2be8c3b7490c1dcb9e2
+REV(g2fg) := 7da0601946bd2bb75f4e9c3b56cb18e44b2997a1
DIR(g2fg) := boot
default: $(DOWNLOADS)
diff --git a/repos/base/recipes/api/base/hash b/repos/base/recipes/api/base/hash
index 4d1cf22bc1..65319582e1 100644
--- a/repos/base/recipes/api/base/hash
+++ b/repos/base/recipes/api/base/hash
@@ -1 +1 @@
-2022-05-24 d4b5b53bc270cebd87bf01a93c6da241077aad42
+2022-10-11 1574044ae0ee33a9ad3bdadb3c487c47d4f45bff
diff --git a/repos/base/recipes/api/timer_session/hash b/repos/base/recipes/api/timer_session/hash
index 29f62381b1..6c61c2e233 100644
--- a/repos/base/recipes/api/timer_session/hash
+++ b/repos/base/recipes/api/timer_session/hash
@@ -1 +1 @@
-2021-04-19 8628f8283cc104fdfd196d88fb029becaa39b258
+2022-08-16 1f83bc046ed3bb0c4fe6915e608d566dd5483e61
diff --git a/repos/base/recipes/pkg/test-ds_ownership/hash b/repos/base/recipes/pkg/test-ds_ownership/hash
index ea2d8baf94..587dda17cb 100644
--- a/repos/base/recipes/pkg/test-ds_ownership/hash
+++ b/repos/base/recipes/pkg/test-ds_ownership/hash
@@ -1 +1 @@
-2022-05-24 5e486a0f27fdda0a70b9275d62257d98e26589c8
+2022-10-11 b08e70f6de91f200618103ec75f53898c6ef60e8
diff --git a/repos/base/recipes/pkg/test-entrypoint/hash b/repos/base/recipes/pkg/test-entrypoint/hash
index 53f437789c..f392de77ae 100644
--- a/repos/base/recipes/pkg/test-entrypoint/hash
+++ b/repos/base/recipes/pkg/test-entrypoint/hash
@@ -1 +1 @@
-2022-05-24 e35abe047c7ec7fe02c0939de16bfc80ed421d38
+2022-10-11 ad5b85ab1377744e2f747ca2eb5010a3aee87f70
diff --git a/repos/base/recipes/pkg/test-log/hash b/repos/base/recipes/pkg/test-log/hash
index b451eee8c5..e4d25877e6 100644
--- a/repos/base/recipes/pkg/test-log/hash
+++ b/repos/base/recipes/pkg/test-log/hash
@@ -1 +1 @@
-2022-05-24 79d43c7e33381048618dbd7ba6ca34a3eda23f6c
+2022-10-11 3e1b9be9b239017a54b6b595cdec5891623ba59f
diff --git a/repos/base/recipes/pkg/test-mmio/hash b/repos/base/recipes/pkg/test-mmio/hash
index 19ea6f0fc4..63bb8c9fff 100644
--- a/repos/base/recipes/pkg/test-mmio/hash
+++ b/repos/base/recipes/pkg/test-mmio/hash
@@ -1 +1 @@
-2022-05-24 4b2af7d33e8264d080be962d0a4d9a6404ec4bc0
+2022-10-11 ee3cb10ce306e2afab97018d2bda4e33ce3f863c
diff --git a/repos/base/recipes/pkg/test-new_delete/hash b/repos/base/recipes/pkg/test-new_delete/hash
index f062e54171..8fdf563d97 100644
--- a/repos/base/recipes/pkg/test-new_delete/hash
+++ b/repos/base/recipes/pkg/test-new_delete/hash
@@ -1 +1 @@
-2022-05-24 ed1f37d2213211897d5360c9a8f32404d670722a
+2022-10-11 dac71b5071da69f218826b2bdc5462b7cf0c28a3
diff --git a/repos/base/recipes/pkg/test-reconstructible/hash b/repos/base/recipes/pkg/test-reconstructible/hash
index d7f9a74766..99f66adb70 100644
--- a/repos/base/recipes/pkg/test-reconstructible/hash
+++ b/repos/base/recipes/pkg/test-reconstructible/hash
@@ -1 +1 @@
-2022-05-24 f09098d18ca36bc8829a673be78dd80460c3d65e
+2022-10-11 5f899fc663f34b1c1aeeba243e54edc092aa40fa
diff --git a/repos/base/recipes/pkg/test-registry/hash b/repos/base/recipes/pkg/test-registry/hash
index 53ada5cd94..ce25cb14f6 100644
--- a/repos/base/recipes/pkg/test-registry/hash
+++ b/repos/base/recipes/pkg/test-registry/hash
@@ -1 +1 @@
-2022-05-24 3f91b26dbd239c52bb9af22e8f7713743ee851f4
+2022-10-11 50b25d7a4bbde78fc1722a4e822370eb49cb6b95
diff --git a/repos/base/recipes/pkg/test-rm_fault/hash b/repos/base/recipes/pkg/test-rm_fault/hash
index 49196a6937..2660982cdc 100644
--- a/repos/base/recipes/pkg/test-rm_fault/hash
+++ b/repos/base/recipes/pkg/test-rm_fault/hash
@@ -1 +1 @@
-2022-05-24 edbf57617935a054a681e097a611006496ed4c88
+2022-10-11 8882e9bea4fdc16ff4910913a79223d62aeb0cdc
diff --git a/repos/base/recipes/pkg/test-rm_fault_no_nox/hash b/repos/base/recipes/pkg/test-rm_fault_no_nox/hash
index 877b7bcb89..f0fed0ff13 100644
--- a/repos/base/recipes/pkg/test-rm_fault_no_nox/hash
+++ b/repos/base/recipes/pkg/test-rm_fault_no_nox/hash
@@ -1 +1 @@
-2022-05-24 ce2c9008ed6ea0db13999e9c6ab77a098d4f94a0
+2022-10-11 a2514b901565ebf0aa88a955c4431fe733964758
diff --git a/repos/base/recipes/pkg/test-rm_nested/hash b/repos/base/recipes/pkg/test-rm_nested/hash
index 67b68c9a7d..617c2179b0 100644
--- a/repos/base/recipes/pkg/test-rm_nested/hash
+++ b/repos/base/recipes/pkg/test-rm_nested/hash
@@ -1 +1 @@
-2022-05-24 afd4f2249a2d56bb6b29b6c0d24923ef2ec215c9
+2022-10-11 3a4ebd01ee612ba2e12ae8df14d6299fb4431375
diff --git a/repos/base/recipes/pkg/test-rm_stress/hash b/repos/base/recipes/pkg/test-rm_stress/hash
index 3d9787edac..a7c6d8a6d0 100644
--- a/repos/base/recipes/pkg/test-rm_stress/hash
+++ b/repos/base/recipes/pkg/test-rm_stress/hash
@@ -1 +1 @@
-2022-05-24 436a166f1c4371619d7a64bf879dd0ce2dc75429
+2022-10-11 5ac901826381a7d6de528cd3d3520b0767385f6c
diff --git a/repos/base/recipes/pkg/test-sanitizer/hash b/repos/base/recipes/pkg/test-sanitizer/hash
index 3662cf1783..655a1c5294 100644
--- a/repos/base/recipes/pkg/test-sanitizer/hash
+++ b/repos/base/recipes/pkg/test-sanitizer/hash
@@ -1 +1 @@
-2022-05-24 3877f6f98ff7c3921bdb7b2b83f40a161e9cd5bb
+2022-10-11 36717c21923ac35c938ad73930f1d1576ecaf385
diff --git a/repos/base/recipes/pkg/test-stack_smash/hash b/repos/base/recipes/pkg/test-stack_smash/hash
index bc4fb94d4a..3c46805904 100644
--- a/repos/base/recipes/pkg/test-stack_smash/hash
+++ b/repos/base/recipes/pkg/test-stack_smash/hash
@@ -1 +1 @@
-2022-05-24 00a8e3979871b2a0ab67088c3d2b57454ed653f9
+2022-10-11 b8e011ab9a1ae92c4293ab07f9a6b7df71c6aabc
diff --git a/repos/base/recipes/pkg/test-synced_interface/hash b/repos/base/recipes/pkg/test-synced_interface/hash
index aaff8bb4c0..053c382dc6 100644
--- a/repos/base/recipes/pkg/test-synced_interface/hash
+++ b/repos/base/recipes/pkg/test-synced_interface/hash
@@ -1 +1 @@
-2022-05-24 ab7b5f631d4abf8b01ed6b08c4da83b4164564a8
+2022-10-11 0a151f72dc20e2e6b8cca80b761128dee92bb7c5
diff --git a/repos/base/recipes/pkg/test-timer/hash b/repos/base/recipes/pkg/test-timer/hash
index 15136b90af..56f8cf4688 100644
--- a/repos/base/recipes/pkg/test-timer/hash
+++ b/repos/base/recipes/pkg/test-timer/hash
@@ -1 +1 @@
-2022-05-24 91ed52185381c38cf7e425fb0c351b46c4548b4f
+2022-10-11 8070010a6f4553f3be84c5fbe0729f50e5d3fde0
diff --git a/repos/base/recipes/pkg/test-tls/hash b/repos/base/recipes/pkg/test-tls/hash
index f185bc03db..eb94a8999b 100644
--- a/repos/base/recipes/pkg/test-tls/hash
+++ b/repos/base/recipes/pkg/test-tls/hash
@@ -1 +1 @@
-2022-05-24 7ff4d04d0b470eb6974b633bb0dca1212158f625
+2022-10-11 5068ceee7e2285a398ac7b6936f6d16c8daa29ea
diff --git a/repos/base/recipes/pkg/test-token/hash b/repos/base/recipes/pkg/test-token/hash
index 4e94f5e5d6..513c91136b 100644
--- a/repos/base/recipes/pkg/test-token/hash
+++ b/repos/base/recipes/pkg/test-token/hash
@@ -1 +1 @@
-2022-05-24 b96b88fee3e0946fea12a44cea94963b2b16d173
+2022-10-11 c4e1fb742ffc41fdb81aeb2ca2638ca81459578d
diff --git a/repos/base/recipes/pkg/test-xml_generator/hash b/repos/base/recipes/pkg/test-xml_generator/hash
index 0340fa2e62..01508ca781 100644
--- a/repos/base/recipes/pkg/test-xml_generator/hash
+++ b/repos/base/recipes/pkg/test-xml_generator/hash
@@ -1 +1 @@
-2022-05-24 c2d9a2849fe51277372d301c9a46d034c4674ab9
+2022-10-11 f44af3d8cc1af7801408f855c1c8c168c8d84aa7
diff --git a/repos/base/recipes/pkg/test-xml_node/hash b/repos/base/recipes/pkg/test-xml_node/hash
index 09ab49e610..fc516acfbc 100644
--- a/repos/base/recipes/pkg/test-xml_node/hash
+++ b/repos/base/recipes/pkg/test-xml_node/hash
@@ -1 +1 @@
-2022-05-24 88eb29b90a1e663e1f58de04a6a178f3a035f3f5
+2022-10-11 682420bf32f10e223946d7713bf70255ede1d451
diff --git a/repos/base/recipes/pkg/test-xml_node/runtime b/repos/base/recipes/pkg/test-xml_node/runtime
index 080a24193b..e526210460 100644
--- a/repos/base/recipes/pkg/test-xml_node/runtime
+++ b/repos/base/recipes/pkg/test-xml_node/runtime
@@ -99,6 +99,9 @@
[init -> test-xml_node] -- Test backslash as attribute value --
[init -> test-xml_node] attribute value: '\'
[init -> test-xml_node]
+ [init -> test-xml_node] -- Test whitespace around assignment character --
+ [init -> test-xml_node] attribute value: '123'
+ [init -> test-xml_node]
[init -> test-xml_node] -- Test exporting decoded content from XML node --
[init -> test-xml_node] step 1
[init -> test-xml_node] step 2
diff --git a/repos/base/recipes/src/test-ds_ownership/hash b/repos/base/recipes/src/test-ds_ownership/hash
index 4dcb62cd3d..cd73f3f0ac 100644
--- a/repos/base/recipes/src/test-ds_ownership/hash
+++ b/repos/base/recipes/src/test-ds_ownership/hash
@@ -1 +1 @@
-2022-05-24 715bfaa6ea0bff54c0e2477c1bbccf56c0bfc935
+2022-10-11 359a8ba82f0a85f6f83c2e140120e0ec2fc2ff4b
diff --git a/repos/base/recipes/src/test-entrypoint/hash b/repos/base/recipes/src/test-entrypoint/hash
index 066abed7fa..9ea1110839 100644
--- a/repos/base/recipes/src/test-entrypoint/hash
+++ b/repos/base/recipes/src/test-entrypoint/hash
@@ -1 +1 @@
-2022-05-24 05d5db1ec0b7fff36e8526fe701873731fd08660
+2022-10-11 5a9a370fb5f6483aa652fd13e805f8970580d8d7
diff --git a/repos/base/recipes/src/test-log/hash b/repos/base/recipes/src/test-log/hash
index c2a6422cbb..bf465ce443 100644
--- a/repos/base/recipes/src/test-log/hash
+++ b/repos/base/recipes/src/test-log/hash
@@ -1 +1 @@
-2022-05-24 7d26fbbb584ab24b8156eda78a8eca5bc9e1122f
+2022-10-11 095026fa1d5dc144f0d2bd21f3b0aad4c1ddacbd
diff --git a/repos/base/recipes/src/test-mmio/hash b/repos/base/recipes/src/test-mmio/hash
index f51cd1f6dc..6247eefd30 100644
--- a/repos/base/recipes/src/test-mmio/hash
+++ b/repos/base/recipes/src/test-mmio/hash
@@ -1 +1 @@
-2022-05-24 6542fc1df645f45c9fc71b5c18b458a9e630470d
+2022-10-11 2fc5a59b9a18db38188c8f0b5cd140f8af25debf
diff --git a/repos/base/recipes/src/test-new_delete/hash b/repos/base/recipes/src/test-new_delete/hash
index 2235c35484..196fd52868 100644
--- a/repos/base/recipes/src/test-new_delete/hash
+++ b/repos/base/recipes/src/test-new_delete/hash
@@ -1 +1 @@
-2022-05-24 67caefb3bbf5926dbd2ca46bbe933882de542db3
+2022-10-11 4b8f0df83f00b36d32640a767a861327034e51ed
diff --git a/repos/base/recipes/src/test-reconstructible/hash b/repos/base/recipes/src/test-reconstructible/hash
index a21bfcb092..62b89f129b 100644
--- a/repos/base/recipes/src/test-reconstructible/hash
+++ b/repos/base/recipes/src/test-reconstructible/hash
@@ -1 +1 @@
-2022-05-24 915f8bebfcdbfe4ef499ea94985303bacebeb8e8
+2022-10-11 03229606efad94460265721c6f828fdf4f1c1e36
diff --git a/repos/base/recipes/src/test-registry/hash b/repos/base/recipes/src/test-registry/hash
index 400b893782..dd85d8a1ff 100644
--- a/repos/base/recipes/src/test-registry/hash
+++ b/repos/base/recipes/src/test-registry/hash
@@ -1 +1 @@
-2022-05-24 e1e3559b2f3010d96d19e81cbaa6abbeb07c6251
+2022-10-11 3a9a202788b631072f5bc4a6220083ea3f0804ee
diff --git a/repos/base/recipes/src/test-rm_fault/hash b/repos/base/recipes/src/test-rm_fault/hash
index 27bdb498e9..8bb4d51590 100644
--- a/repos/base/recipes/src/test-rm_fault/hash
+++ b/repos/base/recipes/src/test-rm_fault/hash
@@ -1 +1 @@
-2022-05-24 93812b90ee88b44d4fc3b26af77ad0344359e51a
+2022-10-11 31d8bd8cf827651dc7996e6d3ca7b005ddc0bdcd
diff --git a/repos/base/recipes/src/test-rm_nested/hash b/repos/base/recipes/src/test-rm_nested/hash
index 07f64a4053..86599133e2 100644
--- a/repos/base/recipes/src/test-rm_nested/hash
+++ b/repos/base/recipes/src/test-rm_nested/hash
@@ -1 +1 @@
-2022-05-24 465cc6225756312ca657c39d5a398fd276088118
+2022-10-11 c81db79ecd943606a3113aad3e804c715fc33a1c
diff --git a/repos/base/recipes/src/test-rm_stress/hash b/repos/base/recipes/src/test-rm_stress/hash
index 92fcbd61b0..68e858396b 100644
--- a/repos/base/recipes/src/test-rm_stress/hash
+++ b/repos/base/recipes/src/test-rm_stress/hash
@@ -1 +1 @@
-2022-05-24 dd009dd4ea58101e1c15e5bd38cad4241f726fa4
+2022-10-11 ef88b5f407d0b49926354c8144d2322b778dfcad
diff --git a/repos/base/recipes/src/test-sanitizer/hash b/repos/base/recipes/src/test-sanitizer/hash
index 0cb0636545..2423895026 100644
--- a/repos/base/recipes/src/test-sanitizer/hash
+++ b/repos/base/recipes/src/test-sanitizer/hash
@@ -1 +1 @@
-2022-05-24 34b25aabaef3112a38eb0a24a13cf6e42da6ba65
+2022-10-11 27a1948a58c15301b3e1978f409ce9b076d704bc
diff --git a/repos/base/recipes/src/test-segfault/hash b/repos/base/recipes/src/test-segfault/hash
index 35e8c15921..f409498935 100644
--- a/repos/base/recipes/src/test-segfault/hash
+++ b/repos/base/recipes/src/test-segfault/hash
@@ -1 +1 @@
-2022-05-24 632e59190a6bcfe40a5a88ecff9f05e2924a43b1
+2022-10-11 29971db890cb657bb8d41bf07636ba21752ca8b3
diff --git a/repos/base/recipes/src/test-stack_smash/hash b/repos/base/recipes/src/test-stack_smash/hash
index 8d2194a103..8202e3d036 100644
--- a/repos/base/recipes/src/test-stack_smash/hash
+++ b/repos/base/recipes/src/test-stack_smash/hash
@@ -1 +1 @@
-2022-05-24 4e254230305117e2ce5dd2c13caa650ea65251e7
+2022-10-11 483ee9045181e9912f60834b45436d0226763bb8
diff --git a/repos/base/recipes/src/test-synced_interface/hash b/repos/base/recipes/src/test-synced_interface/hash
index 7ef1668a45..87e2688cb7 100644
--- a/repos/base/recipes/src/test-synced_interface/hash
+++ b/repos/base/recipes/src/test-synced_interface/hash
@@ -1 +1 @@
-2022-05-24 f9126bd0df2b402150c7ef76138d5ecb8cee05d4
+2022-10-11 bdabeb64387faee3c5307377d72bcb99f4086f00
diff --git a/repos/base/recipes/src/test-timer/hash b/repos/base/recipes/src/test-timer/hash
index f49d5f06e7..80fa15879a 100644
--- a/repos/base/recipes/src/test-timer/hash
+++ b/repos/base/recipes/src/test-timer/hash
@@ -1 +1 @@
-2022-05-24 402acbf040b8f905dcc0979700f6077d36dc707d
+2022-10-11 18675e4c9e59c67edede9b4c0eb0eb8bd8ff56d2
diff --git a/repos/base/recipes/src/test-tls/hash b/repos/base/recipes/src/test-tls/hash
index 824a9dd8ab..26715c617c 100644
--- a/repos/base/recipes/src/test-tls/hash
+++ b/repos/base/recipes/src/test-tls/hash
@@ -1 +1 @@
-2022-05-24 4ddec10779302c6d0c47ccbeba806fe1278e182b
+2022-10-11 e0674b3ea25b560f92bfe65b9ccbed95c3119665
diff --git a/repos/base/recipes/src/test-token/hash b/repos/base/recipes/src/test-token/hash
index da0f7e3805..efd237b5be 100644
--- a/repos/base/recipes/src/test-token/hash
+++ b/repos/base/recipes/src/test-token/hash
@@ -1 +1 @@
-2022-05-24 f04c4162857259fd48d864e9076ae401c9093dbb
+2022-10-11 6b24a7f9187ca2e87c5acffd6cd61c63bca52477
diff --git a/repos/base/recipes/src/test-xml_generator/hash b/repos/base/recipes/src/test-xml_generator/hash
index 7ac579a8e7..0858b2605a 100644
--- a/repos/base/recipes/src/test-xml_generator/hash
+++ b/repos/base/recipes/src/test-xml_generator/hash
@@ -1 +1 @@
-2022-05-24 e91f2b05a682df2206b8f487b7cb01cc8150350e
+2022-10-11 be8b5157c899db1007904028d0f77dc50acc1a7f
diff --git a/repos/base/recipes/src/test-xml_node/hash b/repos/base/recipes/src/test-xml_node/hash
index d9feccf844..4dd2a34d95 100644
--- a/repos/base/recipes/src/test-xml_node/hash
+++ b/repos/base/recipes/src/test-xml_node/hash
@@ -1 +1 @@
-2022-05-24 39a7ce53177b2bad4928846f40b8ef542d8f6840
+2022-10-11 53ba6ffafbcb4b78411e4117bbc3e7e3d721f20e
diff --git a/repos/base/run/platform_drv.inc b/repos/base/run/platform_drv.inc
index c442dff71d..3da9f74d87 100644
--- a/repos/base/run/platform_drv.inc
+++ b/repos/base/run/platform_drv.inc
@@ -188,6 +188,7 @@ proc platform_drv_config {} {
+
}
diff --git a/repos/base/src/core/cpu_session_component.cc b/repos/base/src/core/cpu_session_component.cc
index 959e1ab113..760cacbb87 100644
--- a/repos/base/src/core/cpu_session_component.cc
+++ b/repos/base/src/core/cpu_session_component.cc
@@ -16,6 +16,7 @@
/* Genode includes */
#include
#include
+#include
/* core includes */
#include
@@ -23,6 +24,7 @@
#include
#include
+
using namespace Genode;
@@ -144,6 +146,10 @@ void Cpu_session_component::kill_thread(Thread_capability thread_cap)
}
}
+void Cpu_session_component::migrate_thread(Thread_capability thread_cap, Affinity::Location loc)
+{
+ _thread_ep.apply(thread_cap, [&] (Cpu_thread_component *t) { t->affinity(_thread_affinity(loc)); });
+}
void Cpu_session_component::exception_sigh(Signal_context_capability sigh)
{
diff --git a/repos/base/src/core/include/core_env.h b/repos/base/src/core/include/core_env.h
index 9f7278ed9d..8b52ec1661 100644
--- a/repos/base/src/core/include/core_env.h
+++ b/repos/base/src/core/include/core_env.h
@@ -18,6 +18,7 @@
/* Genode includes */
#include
#include
+#include
/* base-internal includes */
#include
@@ -98,6 +99,8 @@ class Genode::Core_env : public Env_deprecated, Noncopyable
Pd_session *pd_session() override { return &_pd_session; }
Cpu_session *cpu_session() override { ASSERT_NEVER_CALLED; }
Cpu_session_capability cpu_session_cap() override { ASSERT_NEVER_CALLED; }
+ Topo_session *topo_session() override { ASSERT_NEVER_CALLED; }
+ Topo_session_capability topo_session_cap() override { ASSERT_NEVER_CALLED; }
Pd_session_capability pd_session_cap() override { return _pd_session.cap(); }
};
diff --git a/repos/base/src/core/include/cpu_session_component.h b/repos/base/src/core/include/cpu_session_component.h
index 328a498911..1b904ab3bf 100644
--- a/repos/base/src/core/include/cpu_session_component.h
+++ b/repos/base/src/core/include/cpu_session_component.h
@@ -169,6 +169,7 @@ class Genode::Cpu_session_component : public Session_object,
Thread_capability create_thread(Capability, Name const &,
Affinity::Location, Weight, addr_t) override;
void kill_thread(Thread_capability) override;
+ void migrate_thread(Thread_capability, Affinity::Location) override;
void exception_sigh(Signal_context_capability) override;
Affinity::Space affinity_space() const override;
Dataspace_capability trace_control() override;
diff --git a/repos/base/src/core/include/pd_session_component.h b/repos/base/src/core/include/pd_session_component.h
index 1b84ba015a..182ec8a1f5 100644
--- a/repos/base/src/core/include/pd_session_component.h
+++ b/repos/base/src/core/include/pd_session_component.h
@@ -318,6 +318,8 @@ class Genode::Pd_session_component : public Session_object
Alloc_result try_alloc(size_t, Cache) override;
+ Alloc_result try_alloc(size_t, Ram_allocator::Numa_id, Cache) override;
+
void free(Ram_dataspace_capability) override;
size_t dataspace_size(Ram_dataspace_capability) const override;
diff --git a/repos/base/src/core/include/ram_dataspace_factory.h b/repos/base/src/core/include/ram_dataspace_factory.h
index 747372b01b..01defb4302 100644
--- a/repos/base/src/core/include/ram_dataspace_factory.h
+++ b/repos/base/src/core/include/ram_dataspace_factory.h
@@ -45,7 +45,7 @@ class Genode::Ram_dataspace_factory : public Ram_allocator,
Rpc_entrypoint &_ep;
Range_allocator &_phys_alloc;
- Phys_range const _phys_range;
+ Phys_range _phys_range;
/*
@@ -109,6 +109,7 @@ class Genode::Ram_dataspace_factory : public Ram_allocator,
*****************************/
Alloc_result try_alloc(size_t, Cache) override;
+ Alloc_result try_alloc(size_t, Ram_allocator::Numa_id, Cache) override;
void free(Ram_dataspace_capability) override;
size_t dataspace_size(Ram_dataspace_capability ds) const override;
};
diff --git a/repos/base/src/core/include/synced_ram_allocator.h b/repos/base/src/core/include/synced_ram_allocator.h
index a7cd605fc6..139f812f27 100644
--- a/repos/base/src/core/include/synced_ram_allocator.h
+++ b/repos/base/src/core/include/synced_ram_allocator.h
@@ -38,6 +38,12 @@ class Genode::Synced_ram_allocator : public Ram_allocator
Mutex::Guard mutex_guard(_mutex);
return _alloc.try_alloc(size, cache);
}
+
+ Alloc_result try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cache) override
+ {
+ Mutex::Guard mutex_guard(_mutex);
+ return _alloc.try_alloc(size, numa_id, cache);
+ }
void free(Ram_dataspace_capability ds) override
{
diff --git a/repos/base/src/core/include/topo_root.h b/repos/base/src/core/include/topo_root.h
new file mode 100644
index 0000000000..9c7c5978b7
--- /dev/null
+++ b/repos/base/src/core/include/topo_root.h
@@ -0,0 +1,67 @@
+/*
+ * \brief Topology service root component
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+
+#include
+
+namespace Genode {
+
+ class Topo_root : public Root_component
+ {
+ private:
+ Ram_allocator &_ram_alloc;
+ Region_map &_local_rm;
+
+ protected:
+
+ Topo_session_component *_create_session(char const *args, Affinity const &affinity) override {
+ size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
+
+ if (ram_quota < Trace::Control_area::SIZE)
+ throw Insufficient_ram_quota();
+
+ if (!affinity.valid())
+ throw Service_denied();
+
+ return new (md_alloc())
+ Topo_session_component(*this->ep(),
+ session_resources_from_args(args),
+ session_label_from_args(args),
+ session_diag_from_args(args),
+ _ram_alloc, _local_rm,
+ const_cast(affinity));
+ }
+
+ void _upgrade_session(Topo_session_component *topo, const char *args) override
+ {
+ topo->upgrade(ram_quota_from_args(args));
+ topo->upgrade(cap_quota_from_args(args));
+ }
+
+ public:
+
+ Topo_root(Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Rpc_entrypoint &session_ep,
+ Allocator &md_alloc)
+ :
+ Root_component(&session_ep, &md_alloc),
+ _ram_alloc(ram_alloc), _local_rm(local_rm)
+ { }
+ };
+}
\ No newline at end of file
diff --git a/repos/base/src/core/include/topo_session_component.h b/repos/base/src/core/include/topo_session_component.h
new file mode 100644
index 0000000000..10ffb0e7b0
--- /dev/null
+++ b/repos/base/src/core/include/topo_session_component.h
@@ -0,0 +1,68 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+namespace Genode {
+ class Topo_session_component;
+}
+
+class Genode::Topo_session_component : public Session_object
+{
+ private:
+ Genode::Affinity &_affinity;
+ Sliced_heap _md_alloc;
+
+ Topology::Numa_region _node_affinities[64][64];
+ unsigned _node_count;
+ Topology::Numa_region _nodes[64];
+
+ public:
+ Topo_session_component(Rpc_entrypoint &session_ep,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag,
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Affinity &affinity
+ );
+
+
+ /**
+ * @brief Topology session interface
+ */
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override
+ {
+ return _node_affinities[loc.xpos()][loc.ypos()];
+ }
+
+ Topology::Numa_region node_at_id(unsigned numa_id) override
+ {
+ return _nodes[numa_id];
+ }
+
+ unsigned node_count() override
+ {
+ return _node_count;
+ }
+};
diff --git a/repos/base/src/core/include/trace/session_component.h b/repos/base/src/core/include/trace/session_component.h
index d115784ff6..dbdafbb847 100644
--- a/repos/base/src/core/include/trace/session_component.h
+++ b/repos/base/src/core/include/trace/session_component.h
@@ -78,7 +78,6 @@ class Genode::Trace::Session_component
Dataspace_capability policy(Policy_id) override;
void unload_policy(Policy_id) override;
void trace(Subject_id, Policy_id, size_t) override;
- void rule(Session_label const &, Thread_name const &, Policy_id, size_t) override;
void pause(Subject_id) override;
void resume(Subject_id) override;
Dataspace_capability buffer(Subject_id) override;
diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc
index 5455baac83..45c6fd56df 100644
--- a/repos/base/src/core/main.cc
+++ b/repos/base/src/core/main.cc
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
using namespace Genode;
@@ -267,6 +268,7 @@ int main()
platform().irq_alloc(), sliced_heap);
static Trace::Root trace_root (core_ram_alloc, local_rm, ep, sliced_heap,
Trace::sources(), trace_policies);
+ static Topo_root topo_root(core_ram_alloc, local_rm, ep, sliced_heap);
static Core_service rom_service (services, rom_root);
static Core_service rm_service (services, rm_root);
@@ -276,6 +278,7 @@ int main()
static Core_service io_mem_service (services, io_mem_root);
static Core_service irq_service (services, irq_root);
static Core_service trace_service (services, trace_root);
+ static Core_service topo_service(services, topo_root);
/* make platform-specific services known to service pool */
platform_add_local_services(ep, sliced_heap, services, Trace::sources());
diff --git a/repos/base/src/core/pd_session_component.cc b/repos/base/src/core/pd_session_component.cc
index acc607aed4..87eff1d5de 100644
--- a/repos/base/src/core/pd_session_component.cc
+++ b/repos/base/src/core/pd_session_component.cc
@@ -73,6 +73,58 @@ Pd_session_component::try_alloc(size_t ds_size, Cache cache)
);
}
+Ram_allocator::Alloc_result
+Pd_session_component::try_alloc(size_t ds_size, Ram_allocator::Numa_id numa_id, Cache cache)
+{
+ /* zero-sized dataspaces are not allowed */
+ if (!ds_size)
+ return Alloc_error::DENIED;
+
+ /* dataspace allocation granularity is page size */
+ ds_size = align_addr(ds_size, 12);
+
+ using Result = Ram_allocator::Alloc_result;
+ using Reservation = Genode::Reservation;
+
+ /* track quota use */
+ return _ram_quota_guard().with_reservation(Ram_quota{ds_size},
+
+ [&] (Reservation &ram_reservation) -> Result {
+
+ /*
+ * In the worst case, we need to allocate a new slab block for
+ * the meta data of the dataspace to be created. Therefore, we
+ * temporarily withdraw the slab block size here to trigger an
+ * exception if the account does not have enough room for the meta
+ * data.
+ */
+ Ram_quota const overhead { Ram_dataspace_factory::SLAB_BLOCK_SIZE };
+
+ if (!_ram_quota_guard().have_avail(overhead)) {
+ ram_reservation.cancel();
+ return Ram_allocator::Alloc_error::OUT_OF_RAM;
+ }
+
+ /*
+ * Each dataspace is an RPC object and thereby consumes a
+ * capability.
+ */
+ return _cap_quota_guard().with_reservation(Cap_quota{1},
+
+ [&] (Genode::Reservation &) -> Result {
+ return _ram_ds_factory.try_alloc(ds_size, numa_id, cache);
+ },
+ [&] () -> Result {
+ ram_reservation.cancel();
+ return Ram_allocator::Alloc_error::OUT_OF_CAPS;
+ }
+ );
+ },
+ [&] () -> Result {
+ return Ram_allocator::Alloc_error::OUT_OF_RAM;
+ }
+ );
+}
void Pd_session_component::free(Ram_dataspace_capability ds_cap)
{
diff --git a/repos/base/src/core/ram_dataspace_factory.cc b/repos/base/src/core/ram_dataspace_factory.cc
index 04911289a0..05079bc4eb 100644
--- a/repos/base/src/core/ram_dataspace_factory.cc
+++ b/repos/base/src/core/ram_dataspace_factory.cc
@@ -16,6 +16,8 @@
/* core includes */
#include
+#include
+#include
using namespace Genode;
@@ -144,6 +146,14 @@ Ram_dataspace_factory::try_alloc(size_t ds_size, Cache cache)
return static_cap_cast(ds_cap);
}
+Ram_allocator::Alloc_result Ram_dataspace_factory::try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cached=CACHED)
+{
+ Ram_dataspace_factory::Phys_range old = {_phys_range.start, _phys_range.end};
+ _phys_range = {platform_specific().mem_range(numa_id).start, platform_specific().mem_range(numa_id).end};
+ Ram_allocator::Alloc_result result = Ram_dataspace_factory::try_alloc(size, cached);
+ _phys_range = {old.start, old.end};
+ return result;
+}
void Ram_dataspace_factory::free(Ram_dataspace_capability ds_cap)
{
diff --git a/repos/base/src/core/stack_area.cc b/repos/base/src/core/stack_area.cc
index c981eb54e5..e39e01676d 100644
--- a/repos/base/src/core/stack_area.cc
+++ b/repos/base/src/core/stack_area.cc
@@ -132,6 +132,10 @@ struct Stack_area_ram_allocator : Ram_allocator
Alloc_result try_alloc(size_t, Cache) override {
return reinterpret_cap_cast(Native_capability()); }
+ Alloc_result try_alloc(size_t, Ram_allocator::Numa_id, Cache) override {
+ return reinterpret_cap_cast(Native_capability()); }
+
+
void free(Ram_dataspace_capability) override { }
size_t dataspace_size(Ram_dataspace_capability) const override { return 0; }
diff --git a/repos/base/src/core/topo_session_component.cc b/repos/base/src/core/topo_session_component.cc
new file mode 100644
index 0000000000..f4caaf3fd4
--- /dev/null
+++ b/repos/base/src/core/topo_session_component.cc
@@ -0,0 +1,74 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+#include
+#include
+#include
+#include
+
+using namespace Genode;
+
+Topo_session_component::Topo_session_component(Rpc_entrypoint &session_ep,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag,
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Affinity &affinity)
+ : Session_object(session_ep, resources, label, diag),
+ _affinity(affinity),
+ _md_alloc(ram_alloc, local_rm),
+ _node_count(0)
+{
+ Affinity::Location location = affinity.location();
+ const unsigned height = location.height();
+ unsigned width = location.width();
+ unsigned curr_node_id = 0;
+ Topology::Numa_region *node_created = new (_md_alloc) Topology::Numa_region[64]();
+
+ Genode::log("[", label, "] Creating new topology model of size ", width, "x", height);
+
+ for (unsigned x = 0; x < width; x++)
+ {
+ for (unsigned y = 0; y < height; y++)
+ {
+ /* Map component's affinity matrix to its position in the affinity space.
+ * In order to get the correct physical CPU id for a coordinate in the affinity matrix of a component,
+ * we need the global coordination for it relative to the whole affinity space.
+ * But, every component's maintains a local view on its affinity matrix starting by (0,0), since
+ * affinity locations can have arbitrary coordinates in the affinity space, we need to transpose the
+ * component's affinity matrix to the global view of the affinity space. */
+ Affinity::Location loc = location.transpose(x, y);
+ unsigned cpu_id = platform_specific().kernel_cpu_id(loc);
+ unsigned native_id = platform_specific().domain_of_cpu(cpu_id);
+
+ log("[", label, "] CPU (", x, "x", y, ") is native CPU ", cpu_id, " on node ", native_id);
+
+ if (node_created[native_id].core_count() == 0)
+ {
+ _nodes[curr_node_id] = _node_affinities[x][y] = Topology::Numa_region(curr_node_id, native_id);
+ _node_affinities[x][y].increment_core_count();
+ node_created[native_id] = _node_affinities[x][y];
+ log("[", label, "] Found new native NUMA region ", native_id, " for CPU (", x, "x", y, ")");
+ _node_count++;
+ curr_node_id++;
+ }
+ else
+ {
+ (_node_affinities[x][y] = node_created[native_id]).increment_core_count();
+ _nodes[curr_node_id].increment_core_count();
+ }
+ }
+ }
+}
diff --git a/repos/base/src/core/trace_session_component.cc b/repos/base/src/core/trace_session_component.cc
index 58308242ef..235da3555e 100644
--- a/repos/base/src/core/trace_session_component.cc
+++ b/repos/base/src/core/trace_session_component.cc
@@ -127,13 +127,6 @@ void Session_component::trace(Subject_id subject_id, Policy_id policy_id,
}
-void Session_component::rule(Session_label const &, Thread_name const &,
- Policy_id, size_t)
-{
- /* not implemented yet */
-}
-
-
void Session_component::pause(Subject_id subject_id)
{
_subjects.lookup_by_id(subject_id).pause();
diff --git a/repos/base/src/include/base/internal/expanding_topo_session_client.h b/repos/base/src/include/base/internal/expanding_topo_session_client.h
new file mode 100644
index 0000000000..654577e6a2
--- /dev/null
+++ b/repos/base/src/include/base/internal/expanding_topo_session_client.h
@@ -0,0 +1,51 @@
+/*
+ * \brief Topology session client that upgrades its session quota on demand
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+
+namespace Genode {
+ struct Expanding_topo_session_client;
+}
+
+struct Genode::Expanding_topo_session_client : Upgradeable_client
+{
+ Expanding_topo_session_client(Parent &parent, Genode::Topo_session_capability cap, Parent::Client::Id id)
+ :
+ Upgradeable_client
+ (parent, static_cap_cast(cap), id)
+ { }
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override
+ {
+ return retry(
+ [&]()
+ {
+ return retry(
+ [&]()
+ {
+ return Topo_session_client::node_affinity_of(loc);
+ },
+ [&]()
+ { upgrade_caps(2); });
+ },
+ [&]()
+ { upgrade_ram(8 * 1024); });
+ }
+};
\ No newline at end of file
diff --git a/repos/base/src/include/base/internal/platform_env.h b/repos/base/src/include/base/internal/platform_env.h
index a4919ff640..5d8d3ad06c 100644
--- a/repos/base/src/include/base/internal/platform_env.h
+++ b/repos/base/src/include/base/internal/platform_env.h
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
namespace Genode {
@@ -60,13 +61,15 @@ class Genode::Platform_env : public Platform_env_base
Expanding_pd_session_client pd;
Expanding_cpu_session_client cpu;
Expanding_region_map_client rm;
+ Expanding_topo_session_client topo;
Resources(Parent &parent)
:
pd (parent, request (parent, Parent::Env::pd())),
cpu(parent, request(parent, Parent::Env::cpu()),
Parent::Env::cpu()),
- rm(parent, pd.rpc_cap(), pd.address_space(), Parent::Env::pd())
+ rm(parent, pd.rpc_cap(), pd.address_space(), Parent::Env::pd()),
+ topo(parent, request(parent, Parent::Env::topo()), Parent::Env::topo())
{ }
};
@@ -107,6 +110,8 @@ class Genode::Platform_env : public Platform_env_base
Pd_session *pd_session() override { return &_resources.pd; }
Pd_session_capability pd_session_cap() override { return _resources.pd.rpc_cap(); }
Region_map *rm_session() override { return &_resources.rm; }
+ Topo_session *topo_session() override { return &_resources.topo; }
+ Topo_session_capability topo_session_cap() override { return _resources.topo.rpc_cap(); }
};
#endif /* _INCLUDE__BASE__INTERNAL__PLATFORM_ENV_H_ */
diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc
index 42e557a09e..45d96ee399 100644
--- a/repos/base/src/lib/base/child.cc
+++ b/repos/base/src/lib/base/child.cc
@@ -759,7 +759,7 @@ void Child::_try_construct_env_dependent_members()
{
/* check if the environment sessions are complete */
if (!_pd.cap().valid() || !_cpu.cap().valid() || !_log.cap().valid()
- || !_binary.cap().valid())
+ || !_binary.cap().valid() || !_topo.cap().valid())
return;
/*
@@ -824,6 +824,7 @@ void Child::initiate_env_sessions()
_cpu .initiate();
_log .initiate();
_binary.initiate();
+ _topo.initiate();
/*
* Issue environment-session request for obtaining the linker binary. We
@@ -909,6 +910,7 @@ void Child::close_all_sessions()
* Issue close requests to the providers of the environment sessions,
* which may be async services.
*/
+ _topo.close();
_log.close();
_binary.close();
if (_linker.constructed())
@@ -923,6 +925,7 @@ void Child::close_all_sessions()
_discard_env_session(Env::log());
_discard_env_session(Env::binary());
_discard_env_session(Env::linker());
+ _discard_env_session(Env::topo());
/*
* Remove dynamically created sessions from the child's ID space.
diff --git a/repos/base/src/lib/base/component.cc b/repos/base/src/lib/base/component.cc
index 82b8642ca7..622690e9a4 100644
--- a/repos/base/src/lib/base/component.cc
+++ b/repos/base/src/lib/base/component.cc
@@ -22,6 +22,7 @@
/* base-internal includes */
#include
+#include
/*
* XXX remove this pointer once 'Env_deprecated' is removed
@@ -78,6 +79,7 @@ namespace {
Genode::Region_map &rm() override { return *Genode::env_deprecated()->rm_session(); }
Genode::Pd_session &pd() override { return *Genode::env_deprecated()->pd_session(); }
Genode::Entrypoint &ep() override { return _ep; }
+ Genode::Topo_session &topo() override { return *Genode::env_deprecated()->topo_session(); }
Genode::Cpu_session_capability cpu_session_cap() override
{
@@ -94,6 +96,11 @@ namespace {
return Genode::env_session_id_space();
}
+ Genode::Topo_session_capability topo_session_cap() override
+ {
+ return Genode::env_deprecated()->topo_session_cap();
+ }
+
void _block_for_session()
{
/*
diff --git a/repos/base/src/lib/base/env_session_id_space.cc b/repos/base/src/lib/base/env_session_id_space.cc
index dca120f1bc..ea893ab02a 100644
--- a/repos/base/src/lib/base/env_session_id_space.cc
+++ b/repos/base/src/lib/base/env_session_id_space.cc
@@ -34,7 +34,8 @@ Id_space &Genode::env_session_id_space()
cpu { dummy, id_space, Parent::Env::cpu() },
log { dummy, id_space, Parent::Env::log() },
binary { dummy, id_space, Parent::Env::binary() },
- linker { dummy, id_space, Parent::Env::linker() };
+ linker { dummy, id_space, Parent::Env::linker() },
+ topo { dummy, id_space, Parent::Env::topo() };
return id_space;
}
diff --git a/repos/base/src/lib/base/mutex.cc b/repos/base/src/lib/base/mutex.cc
index f7bcfd8357..520617dec1 100644
--- a/repos/base/src/lib/base/mutex.cc
+++ b/repos/base/src/lib/base/mutex.cc
@@ -29,7 +29,7 @@ void Genode::Mutex::release()
{
Lock::Applicant myself(Thread::myself());
if (!_lock.lock_owner(myself)) {
- Genode::error("denied non mutex owner the release, mutex=",
+ Genode::error("release denied, caller not owner, mutex=",
this, ", return ip=", __builtin_return_address(0));
return;
}
diff --git a/repos/base/src/lib/base/regional_heap.cc b/repos/base/src/lib/base/regional_heap.cc
new file mode 100644
index 0000000000..2ca2a36d08
--- /dev/null
+++ b/repos/base/src/lib/base/regional_heap.cc
@@ -0,0 +1,348 @@
+/*
+ * \brief Implementation of Genode heap partition
+ * \author Norman Feske
+ * \date 2006-05-17
+ */
+
+/*
+ * Copyright (C) 2006-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#include
+#include
+#include
+#include
+
+using namespace Genode;
+
+
+namespace {
+
+ enum {
+ MIN_CHUNK_SIZE = 4*1024, /* in machine words */
+ MAX_CHUNK_SIZE = 256*1024,
+ /*
+ * Allocation sizes >= this value are considered as big
+ * allocations, which get their own dataspace. In contrast
+ * to smaller allocations, this memory is released to
+ * the RAM session when 'free()' is called.
+ */
+ BIG_ALLOCATION_THRESHOLD = 64*1024 /* in bytes */
+ };
+}
+
+
+void Regional_heap::Dataspace_pool::remove_and_free(Dataspace &ds)
+{
+ /*
+ * read dataspace capability and modify _ds_list before detaching
+ * possible backing store for Dataspace - we rely on LIFO list
+ * manipulation here!
+ */
+
+ Ram_dataspace_capability ds_cap = ds.cap;
+ void *ds_local_addr = ds.local_addr;
+
+ remove(&ds);
+
+ /*
+ * Call 'Dataspace' destructor to properly release the RAM dataspace
+ * capabilities. Note that we don't free the 'Dataspace' object at the
+ * local allocator because this is already done by the 'Regional_heap'
+ * destructor prior executing the 'Dataspace_pool' destructor.
+ */
+ ds.~Dataspace();
+
+ region_map->detach(ds_local_addr);
+ ram_alloc->free(ds_cap);
+}
+
+
+Regional_heap::Dataspace_pool::~Dataspace_pool()
+{
+ /* free all ram_dataspaces */
+ for (Dataspace *ds; (ds = first()); )
+ remove_and_free(*ds);
+}
+
+
+int Regional_heap::quota_limit(size_t new_quota_limit)
+{
+ if (new_quota_limit < _quota_used) return -1;
+ _quota_limit = new_quota_limit;
+ return 0;
+}
+
+
+Regional_heap::Alloc_ds_result
+Regional_heap::_allocate_dataspace(size_t size, bool enforce_separate_metadata)
+{
+ using Result = Alloc_ds_result;
+
+ return _ds_pool.ram_alloc->try_alloc(size, _numa_id).convert(
+
+ [&] (Ram_dataspace_capability ds_cap) -> Result {
+
+ struct Alloc_guard
+ {
+ Ram_allocator &ram;
+ Ram_dataspace_capability ds;
+ bool keep = false;
+
+ Alloc_guard(Ram_allocator &ram, Ram_dataspace_capability ds)
+ : ram(ram), ds(ds) { }
+
+ ~Alloc_guard() { if (!keep) ram.free(ds); }
+
+ } alloc_guard(*_ds_pool.ram_alloc, ds_cap);
+
+ struct Attach_guard
+ {
+ Region_map &rm;
+ struct { void *ptr = nullptr; };
+ bool keep = false;
+
+ Attach_guard(Region_map &rm) : rm(rm) { }
+
+ ~Attach_guard() { if (!keep && ptr) rm.detach(ptr); }
+
+ } attach_guard(*_ds_pool.region_map);
+
+ try {
+ attach_guard.ptr = _ds_pool.region_map->attach(ds_cap);
+ }
+ catch (Out_of_ram) { return Alloc_error::OUT_OF_RAM; }
+ catch (Out_of_caps) { return Alloc_error::OUT_OF_CAPS; }
+ catch (Region_map::Invalid_dataspace) { return Alloc_error::DENIED; }
+ catch (Region_map::Region_conflict) { return Alloc_error::DENIED; }
+
+ Alloc_result metadata = Alloc_error::DENIED;
+
+ /* allocate the 'Dataspace' structure */
+ if (enforce_separate_metadata) {
+ metadata = _unsynchronized_alloc(sizeof(Regional_heap::Dataspace));
+
+ } else {
+
+ /* add new local address range to our local allocator */
+ _alloc->add_range((addr_t)attach_guard.ptr, size).with_result(
+ [&] (Range_allocator::Range_ok) {
+ metadata = _alloc->alloc_aligned(sizeof(Regional_heap::Dataspace), log2(64U)); },
+ [&] (Alloc_error error) {
+ metadata = error; });
+ }
+
+ return metadata.convert(
+ [&] (void *md_ptr) -> Result {
+ Dataspace &ds = *construct_at(md_ptr, ds_cap,
+ attach_guard.ptr, size);
+ _ds_pool.insert(&ds);
+ alloc_guard.keep = attach_guard.keep = true;
+ return &ds;
+ },
+ [&] (Alloc_error error) {
+ return error; });
+ },
+ [&] (Alloc_error error) {
+ return error; });
+}
+
+
+Allocator::Alloc_result Regional_heap::_try_local_alloc(size_t size)
+{
+ return _alloc->alloc_aligned(size, log2(64U)).convert(
+
+ [&] (void *ptr) {
+ _quota_used += size;
+ return ptr; },
+
+ [&] (Alloc_error error) {
+ return error; });
+}
+
+
+Allocator::Alloc_result Regional_heap::_unsynchronized_alloc(size_t size)
+{
+ if (size >= BIG_ALLOCATION_THRESHOLD) {
+
+ /*
+ * big allocation
+ *
+ * In this case, we allocate one dataspace without any meta data in it
+ * and return its local address without going through the allocator.
+ */
+
+ /* align to 4K page */
+ size_t const dataspace_size = align_addr(size, 12);
+
+ return _allocate_dataspace(dataspace_size, true).convert(
+
+ [&] (Dataspace *ds_ptr) {
+ _quota_used += ds_ptr->size;
+ return ds_ptr->local_addr; },
+
+ [&] (Alloc_error error) {
+ return error; });
+ }
+
+ /* try allocation at our local allocator */
+ {
+ Alloc_result result = _try_local_alloc(size);
+ if (result.ok())
+ return result;
+ }
+
+ size_t dataspace_size = size
+ + Allocator_avl::slab_block_size()
+ + sizeof(Regional_heap::Dataspace);
+ /* align to 4K page */
+ dataspace_size = align_addr(dataspace_size, 12);
+
+ /*
+ * '_chunk_size' is a multiple of 4K, so 'dataspace_size' becomes
+ * 4K-aligned, too.
+ */
+ size_t const request_size = _chunk_size * sizeof(umword_t);
+
+ Alloc_ds_result result = Alloc_error::DENIED;
+
+ if (dataspace_size < request_size) {
+
+ result = _allocate_dataspace(request_size, false);
+ if (result.ok()) {
+
+ /*
+ * Exponentially increase chunk size with each allocated chunk until
+ * we hit 'MAX_CHUNK_SIZE'.
+ */
+ _chunk_size = min(2*_chunk_size, (size_t)MAX_CHUNK_SIZE);
+ }
+ } else {
+ result = _allocate_dataspace(dataspace_size, false);
+ }
+
+ if (result.failed())
+ return result.convert(
+ [&] (Dataspace *) { return Alloc_error::DENIED; },
+ [&] (Alloc_error error) { return error; });
+
+ /* allocate originally requested block */
+ return _try_local_alloc(size);
+}
+
+
+Allocator::Alloc_result Regional_heap::try_alloc(size_t size)
+{
+
+ if (size == 0)
+ error("attempt to allocate zero-size block from heap");
+
+ /* serialize access of heap functions */
+ Mutex::Guard guard(_mutex);
+
+ /* check requested allocation against quota limit */
+ if (size + _quota_used > _quota_limit)
+ return Alloc_error::DENIED;
+
+ return _unsynchronized_alloc(size);
+}
+
+
+void Regional_heap::free(void *addr, size_t)
+{
+ /* serialize access of heap functions */
+ Mutex::Guard guard(_mutex);
+
+ using Size_at_error = Allocator_avl::Size_at_error;
+
+ Allocator_avl::Size_at_result size_at_result = _alloc->size_at(addr);
+
+ if (size_at_result.ok()) {
+ /* forward request to our local allocator */
+ size_at_result.with_result(
+ [&] (size_t size) {
+ /* forward request to our local allocator */
+ _alloc->free(addr, size);
+ _quota_used -= size;
+ },
+ [&] (Size_at_error) { });
+
+ return;
+ }
+
+ if (size_at_result == Size_at_error::MISMATCHING_ADDR) {
+ /* address was found in local allocator but is not a block start address */
+ error("heap could not free memory block: given address ", addr,
+ " is not a block start adress");
+ return;
+ }
+
+ /*
+ * Block could not be found in local allocator. So it is either a big
+ * allocation or invalid address.
+ */
+
+ Regional_heap::Dataspace *ds = nullptr;
+ for (ds = _ds_pool.first(); ds; ds = ds->next())
+ if (((addr_t)addr >= (addr_t)ds->local_addr) &&
+ ((addr_t)addr <= (addr_t)ds->local_addr + ds->size - 1))
+ break;
+
+ if (!ds) {
+ //warning("heap could not free memory block: invalid address");
+ throw Region_map::Invalid_dataspace();
+ return;
+ }
+
+ _quota_used -= ds->size;
+
+ _ds_pool.remove_and_free(*ds);
+ _alloc->free(ds);
+}
+
+
+Regional_heap::Regional_heap(Ram_allocator *ram_alloc,
+ Region_map *region_map,
+ Topology::Numa_region ®ion,
+ size_t quota_limit,
+ void *static_addr,
+ size_t static_size)
+:
+ _alloc(nullptr),
+ _ds_pool(ram_alloc, region_map),
+ _quota_limit(quota_limit), _quota_used(0),
+ _chunk_size(MIN_CHUNK_SIZE),
+ _numa_id(region.native_id())
+{
+ if (static_addr)
+ _alloc->add_range((addr_t)static_addr, static_size);
+}
+
+
+Regional_heap::~Regional_heap()
+{
+ /*
+ * Revert allocations of heap-internal 'Dataspace' objects. Otherwise, the
+ * subsequent destruction of the 'Allocator_avl' would detect those blocks
+ * as dangling allocations.
+ *
+ * Since no new allocations can occur at the destruction time of the
+ * 'Regional_heap', it is safe to release the 'Dataspace' objects at the allocator
+ * yet still access them afterwards during the destruction of the
+ * 'Allocator_avl'.
+ */
+ for (Regional_heap::Dataspace *ds = _ds_pool.first(); ds; ds = ds->next())
+ _alloc->free(ds, sizeof(Dataspace));
+
+ /*
+ * Destruct 'Allocator_avl' before destructing the dataspace pool. This
+ * order is important because some dataspaces of the dataspace pool are
+ * used as backing store for the allocator's meta data. If we destroyed
+ * the object pool before the allocator, the subsequent attempt to destruct
+ * the allocator would access no-longer-present backing store.
+ */
+ _alloc.destruct();
+}
diff --git a/repos/base/src/lib/base/thread.cc b/repos/base/src/lib/base/thread.cc
index b7ee561a44..9d38ea1314 100644
--- a/repos/base/src/lib/base/thread.cc
+++ b/repos/base/src/lib/base/thread.cc
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
/* base-internal includes */
#include
@@ -197,6 +198,11 @@ size_t Thread::stack_area_virtual_size()
return Genode::stack_area_virtual_size();
}
+void Thread::pin(Affinity::Location &loc)
+{
+ _cpu_session->migrate_thread(_thread_cap, loc);
+ _affinity = loc;
+}
Thread::Thread(size_t weight, const char *name, size_t stack_size,
Type type, Cpu_session *cpu_session, Affinity::Location affinity)
diff --git a/repos/base/src/lib/ldso/include/config.h b/repos/base/src/lib/ldso/include/config.h
index 5708df0930..2ad11c87a2 100644
--- a/repos/base/src/lib/ldso/include/config.h
+++ b/repos/base/src/lib/ldso/include/config.h
@@ -68,7 +68,7 @@ class Linker::Config : Noncopyable
template
void for_each_library(FN const &fn) const
{
- _config.with_sub_node("ld", [&] (Xml_node ld) {
+ _config.with_optional_sub_node("ld", [&] (Xml_node ld) {
ld.for_each_sub_node("library", [&] (Xml_node lib) {
diff --git a/repos/base/src/lib/target.mk b/repos/base/src/lib/target.mk
deleted file mode 100644
index c7315d49ca..0000000000
--- a/repos/base/src/lib/target.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# This is a dummy target description file with the sole purpose of building
-# all libraries.
-#
-TARGET = libs
-
-#
-# Determine all 'lib/mk' sub directories residing within the repositories.
-# Use 'wildcard' to handle the case when a repository does not host any
-# 'lib/mk' sub directory.
-#
-LIB_MK_DIRS := $(wildcard $(addsuffix /lib/mk,$(REPOSITORIES)))
-
-#
-# Scan the 'lib/mk' directories of all repositories for library description
-# files.
-#
-ALL_LIB_MK_FILES := $(notdir $(foreach DIR,$(LIB_MK_DIRS),$(shell find $(DIR) -name "*.mk")))
-
-#
-# Make the pseudo target depend on all libraries, for which an lib.mk file
-# exists. Discard the '.mk' suffix and remove duplicates (via 'sort').
-#
-LIBS = $(sort $(ALL_LIB_MK_FILES:.mk=))
-
-#
-# Among all libraries found above, there may be several libraries with
-# unsatisfied build requirements. Normally, the build system won't attempt to
-# build the target (and its library dependencies) if one or more libraries
-# cannot be built. By enabling 'FORCE_BUILD_LIBS', we let the build system
-# visit all non-invalid libraries even in the presence of invalid libraries.
-#
-FORCE_BUILD_LIBS = yes
diff --git a/repos/base/src/test/xml_node/test.cc b/repos/base/src/test/xml_node/test.cc
index 494cdabd6b..4d26d66147 100644
--- a/repos/base/src/test/xml_node/test.cc
+++ b/repos/base/src/test/xml_node/test.cc
@@ -152,6 +152,10 @@ static const char *xml_test_comments =
static const char *xml_test_backslash =
"";
+/* withspace around attribute assignment character */
+static const char *xml_test_whitespace_assign =
+ "";
+
/******************
** Test program **
@@ -415,6 +419,12 @@ void Component::construct(Genode::Env &env)
log("attribute value: '", node.attribute_value("attr", String<10>()), "'\n");
}
+ log("-- Test whitespace around assignment character --");
+ {
+ Xml_node const node(xml_test_whitespace_assign);
+ log("attribute value: '", node.attribute_value("attr", String<10>()), "'\n");
+ }
+
log("-- Test exporting decoded content from XML node --");
test_decoded_content<~0UL>(env, 1, xml_test_comments, 8, 119);
test_decoded_content<119 >(env, 2, xml_test_comments, 8, 119);
diff --git a/repos/dde_bsd/README b/repos/dde_bsd/README
index 9bdd3e131c..9f30b6d92c 100644
--- a/repos/dde_bsd/README
+++ b/repos/dde_bsd/README
@@ -4,10 +4,8 @@ Audio
#####
The audio driver is ported from OpenBSD 6.6 and includes support for
-Intel HD Audio, ICH as well as for Ensoniq AudioPCI (ES1370) compatible
-soundcards. The HDA driver works on real hardware and Virtualbox
-whereas the ES1370 driver is only used in Qemu. The ICH driver is only
-tested in Virtualbox where it produces audible artifacts.
+Intel HD Audio devices. The HDA driver works on real hardware and
+supposedly in VirtualBox.
Usage and configuration
diff --git a/repos/dde_bsd/audio.list b/repos/dde_bsd/audio.list
index fa48dbcc7a..af13f3c404 100644
--- a/repos/dde_bsd/audio.list
+++ b/repos/dde_bsd/audio.list
@@ -1,18 +1,13 @@
sys/lib/libkern/strlcpy.c
sys/dev/audio.c
sys/dev/audio_if.h
-sys/dev/pci/auich.c
sys/dev/pci/azalia.c
sys/dev/pci/azalia.h
sys/dev/pci/azalia_codec.c
-sys/dev/pci/eap.c
-sys/dev/pci/eapreg.h
sys/dev/pci/pcidevs.h
sys/dev/pci/pcidevs_data.h
sys/dev/mulaw.c
sys/dev/mulaw.h
-sys/dev/ic/ac97.c
-sys/dev/ic/ac97.h
sys/sys/audioio.h
sys/sys/device.h
sys/sys/queue.h
diff --git a/repos/dde_bsd/lib/mk/dde_bsd_audio.inc b/repos/dde_bsd/lib/mk/dde_bsd_audio.inc
index 2bb34dc03c..75a3b1d454 100644
--- a/repos/dde_bsd/lib/mk/dde_bsd_audio.inc
+++ b/repos/dde_bsd/lib/mk/dde_bsd_audio.inc
@@ -13,7 +13,7 @@ INC_DIR += $(AUDIO_CONTRIB_DIR)
LIBS += dde_bsd_audio_include
-SRC_CC += dummies.cc driver.cc irq.cc mem.cc misc.cc scheduler.cc timer.cc
+SRC_CC += dummies.cc driver.cc mem.cc misc.cc scheduler.cc timer.cc
SRC_C += bsd_emul.c
SRC_S += setjmp.S
diff --git a/repos/dde_bsd/lib/mk/dde_bsd_audio_pci.inc b/repos/dde_bsd/lib/mk/dde_bsd_audio_pci.inc
new file mode 100644
index 0000000000..448f2f3c94
--- /dev/null
+++ b/repos/dde_bsd/lib/mk/dde_bsd_audio_pci.inc
@@ -0,0 +1,13 @@
+include $(REP_DIR)/lib/mk/dde_bsd_audio.inc
+
+SRC_C += bsd_emul_pci.c
+SRC_CC += pci.cc
+
+# enable when debugging
+#CC_OPT += -DAZALIA_DEBUG
+#CC_OPT += -DDIAGNOSTIC
+
+# HDA driver
+SRC_C += dev/pci/azalia.c dev/pci/azalia_codec.c
+
+# vi: set ft=make :
diff --git a/repos/dde_bsd/lib/mk/dde_bsd_audio_pci.mk b/repos/dde_bsd/lib/mk/dde_bsd_audio_pci.mk
deleted file mode 100644
index 6518114a49..0000000000
--- a/repos/dde_bsd/lib/mk/dde_bsd_audio_pci.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-LIB_DIR = $(REP_DIR)/src/lib/audio
-LIB_INC_DIR = $(LIB_DIR)/include
-
-AUDIO_CONTRIB_DIR := $(call select_from_ports,dde_bsd)/src/lib/audio
-
-#
-# Set include paths up before adding the dde_bsd_audio_include library
-# because it will use INC_DIR += and must be at the end
-#
-INC_DIR += $(LIB_DIR)
-INC_DIR += $(LIB_INC_DIR)
-INC_DIR += $(AUDIO_CONTRIB_DIR)
-
-LIBS += dde_bsd_audio_include
-
-SRC_C := bsd_emul_pci.c
-SRC_CC += pci.cc
-
-CC_OPT += -Wno-unused-but-set-variable
-
-# disable builtins
-CC_OPT += -fno-builtin-printf -fno-builtin-snprintf -fno-builtin-vsnprintf \
- -fno-builtin-malloc -fno-builtin-free -fno-builtin-log -fno-builtin-log2
-
-CC_OPT += -D_KERNEL
-
-# enable when debugging
-#CC_OPT += -DAC97_DEBUG
-#CC_OPT += -DAUICH_DEBUG
-#CC_OPT += -DAZALIA_DEBUG
-#CC_OPT += -DDIAGNOSTIC
-
-# AC97 codec
-SRC_C += dev/ic/ac97.c
-
-# HDA driver
-SRC_C += dev/pci/azalia.c dev/pci/azalia_codec.c
-
-# ICH driver
-SRC_C += dev/pci/auich.c
-
-# ES1370
-SRC_C += dev/pci/eap.c
-
-vpath %.c $(AUDIO_CONTRIB_DIR)
-vpath %.c $(LIB_DIR)
-vpath %.cc $(LIB_DIR)
-
-# vi: set ft=make :
diff --git a/repos/dde_bsd/lib/mk/spec/x86_32/dde_bsd_audio.mk b/repos/dde_bsd/lib/mk/spec/x86_32/dde_bsd_audio.mk
index 98f3796d58..357ca1c22c 100644
--- a/repos/dde_bsd/lib/mk/spec/x86_32/dde_bsd_audio.mk
+++ b/repos/dde_bsd/lib/mk/spec/x86_32/dde_bsd_audio.mk
@@ -1,6 +1,6 @@
INC_DIR += $(LIB_INC_DIR)/spec/x86_32 $(LIB_INC_DIR)/spec/x86
-include $(REP_DIR)/lib/mk/dde_bsd_audio.inc
+include $(REP_DIR)/lib/mk/dde_bsd_audio_pci.inc
vpath %.S $(LIB_DIR)/spec/x86_32
diff --git a/repos/dde_bsd/lib/mk/spec/x86_64/dde_bsd_audio.mk b/repos/dde_bsd/lib/mk/spec/x86_64/dde_bsd_audio.mk
index fe3e57dfae..e573623a53 100644
--- a/repos/dde_bsd/lib/mk/spec/x86_64/dde_bsd_audio.mk
+++ b/repos/dde_bsd/lib/mk/spec/x86_64/dde_bsd_audio.mk
@@ -1,6 +1,6 @@
INC_DIR += $(LIB_INC_DIR)/spec/x86_64 $(LIB_INC_DIR)/spec/x86
-include $(REP_DIR)/lib/mk/dde_bsd_audio.inc
+include $(REP_DIR)/lib/mk/dde_bsd_audio_pci.inc
vpath %.S $(LIB_DIR)/spec/x86_64
diff --git a/repos/dde_bsd/patches/attach.patch b/repos/dde_bsd/patches/attach.patch
new file mode 100644
index 0000000000..e1a4f9fd5f
--- /dev/null
+++ b/repos/dde_bsd/patches/attach.patch
@@ -0,0 +1,14 @@
+To signal an successful attach attempt we set the ref counter
+of the parent, i.e., the dummy pci bus and check that in our
+'probe_cfdata' function.
+
+--- a/dev/pci/azalia.c
++++ b/dev/pci/azalia.c
+@@ -591,6 +591,7 @@
+
+ audio_attach_mi(&azalia_hw_if, sc, NULL, &sc->dev);
+
++ parent->dv_ref = 1;
+ return;
+
+ err_exit:
diff --git a/repos/dde_bsd/patches/azalia_c.patch b/repos/dde_bsd/patches/azalia_c.patch
deleted file mode 100644
index 2c0526d870..0000000000
--- a/repos/dde_bsd/patches/azalia_c.patch
+++ /dev/null
@@ -1,55 +0,0 @@
---- a/dev/pci/azalia.c
-+++ b/dev/pci/azalia.c
-@@ -492,7 +492,7 @@
- azalia_t *sc;
- struct pci_attach_args *pa;
- pcireg_t v;
-- uint8_t reg;
-+ // uint8_t reg;
- pci_intr_handle_t ih;
- const char *interrupt_str;
-
-@@ -518,12 +518,18 @@
-
- azalia_configure_pci(sc);
-
-- /* disable MSI, use INTx instead */
-- if (PCI_VENDOR(sc->pciid) == PCI_VENDOR_INTEL) {
-- reg = azalia_pci_read(sc->pc, sc->tag, ICH_PCI_MMC);
-- reg &= ~(ICH_PCI_MMC_ME);
-- azalia_pci_write(sc->pc, sc->tag, ICH_PCI_MMC, reg);
-- }
-+ // This was added in CVS rev 1.168 because certain devices do not
-+ // support MSIs. For reasons that are not clear yet, this breaks
-+ // when using the platform_drv on x86 with MSI support and IOMMU
-+ // enabled. All hw we tested seems to work fine when it is removed,
-+ // even older kernels, e.g. OKL4, that use legacy IRQs,
-+ //
-+ // /* disable MSI, use INTx instead */
-+ // if (PCI_VENDOR(sc->pciid) == PCI_VENDOR_INTEL) {
-+ // reg = azalia_pci_read(sc->pc, sc->tag, ICH_PCI_MMC);
-+ // reg &= ~(ICH_PCI_MMC_ME);
-+ // azalia_pci_write(sc->pc, sc->tag, ICH_PCI_MMC, reg);
-+ // }
-
- /* disable MSI for AMD Summit Ridge/Raven Ridge HD Audio */
- if (PCI_VENDOR(sc->pciid) == PCI_VENDOR_AMD) {
-@@ -3973,6 +3979,10 @@
- azalia_set_blksz(void *v, int mode,
- struct audio_params *p, struct audio_params *r, unsigned int blksz)
- {
-+ // XXX using mult leads to a blksz of 416 in case of a
-+ // requested blksz of 441 which in return results in distored
-+ // playback.
-+#if 0
- int mult;
-
- /* must be multiple of 128 bytes */
-@@ -3981,6 +3991,7 @@
- blksz -= blksz % mult;
- if (blksz == 0)
- blksz = mult;
-+#endif
-
- return blksz;
- }
diff --git a/repos/dde_bsd/patches/azalia_codec_c.patch b/repos/dde_bsd/patches/azalia_codec_c.patch
deleted file mode 100644
index 06b26f6677..0000000000
--- a/repos/dde_bsd/patches/azalia_codec_c.patch
+++ /dev/null
@@ -1,42 +0,0 @@
---- a/dev/pci/azalia_codec.c
-+++ b/dev/pci/azalia_codec.c
-@@ -83,6 +83,13 @@
- this->name = "Realtek ALC221";
- this->qrks |= AZ_QRK_WID_CDIN_1C | AZ_QRK_WID_BEEP_1D;
- break;
-+ case 0x10ec0255:
-+ this->name = "Realtek ALC255";
-+ DPRINTF(("Realtek ALC255 0x%8x\n", this->subid));
-+ if (this->subid == 0x193e10cf) { /* FUJITSU S938 */
-+ this->qrks |= AZ_QRK_WID_HEADSET;
-+ }
-+ break;
- case 0x10ec0260:
- this->name = "Realtek ALC260";
- if (this->subid == 0x008f1025)
-@@ -656,6 +663,10 @@
- CORB_GET_PIN_SENSE, 0, &result);
- if (!err && (result & CORB_PS_PRESENCE))
- vol = 1;
-+
-+ // switch microphone to mic2
-+ if (!err)
-+ notify_hp_sense(result & CORB_PS_PRESENCE);
- }
- if (err)
- break;
-@@ -2590,6 +2601,14 @@
- w->enable = 1;
- }
-
-+ if (this->qrks & AZ_QRK_WID_HEADSET &&
-+ nid == 0x19) {
-+ /* Fujitsu S398 headphone jack */
-+ w->d.pin.config = 0x03a19120;
-+ azalia_pin_config_ov(w, CORB_CD_DEVICE_MASK, CORB_CD_MICIN);
-+ w->enable = 1;
-+ }
-+
- if (this->qrks & AZ_QRK_WID_CDIN_1C &&
- nid == 0x1c && w->enable == 0 && w->d.pin.device == CORB_CD_CD) {
- azalia_pin_config_ov(w, CORB_CD_PORT_MASK, CORB_CD_FIXED);
diff --git a/repos/dde_bsd/patches/azalia_h.patch b/repos/dde_bsd/patches/azalia_h.patch
deleted file mode 100644
index 7cfe946401..0000000000
--- a/repos/dde_bsd/patches/azalia_h.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/dev/pci/azalia.h
-+++ b/dev/pci/azalia.h
-@@ -513,6 +513,7 @@
- #define AZ_QRK_WID_TPDOCK1 0x00010000
- #define AZ_QRK_WID_TPDOCK2 0x00020000
- #define AZ_QRK_WID_TPDOCK3 0x00040000
-+#define AZ_QRK_WID_HEADSET 0x00080000
- #define AZ_QRK_WID_DOLBY_ATMOS 0x00100000
- #define AZ_QRK_WID_SPKR2_DAC 0x00200000
-
diff --git a/repos/dde_bsd/patches/halt_corb.patch b/repos/dde_bsd/patches/halt_corb.patch
new file mode 100644
index 0000000000..9c313a7151
--- /dev/null
+++ b/repos/dde_bsd/patches/halt_corb.patch
@@ -0,0 +1,25 @@
+--- a/dev/pci/azalia.c
++++ b/dev/pci/azalia.c
+@@ -1063,10 +1063,6 @@
+ uint16_t corbrp, corbwp;
+ uint8_t corbctl;
+
+- err = azalia_halt_corb(az);
+- if (err)
+- return(err);
+-
+ if (!resuming) {
+ err = azalia_alloc_dmamem(az,
+ az->corb_entries * sizeof(corb_entry_t), 128,
+@@ -1079,6 +1075,11 @@
+ }
+ timeout_set(&az->unsol_to, azalia_rirb_kick_unsol_events, az);
+
++ /* do after the allocation as it will access 'corb_dma' */
++ err = azalia_halt_corb(az);
++ if (err)
++ return(err);
++
+ AZ_WRITE_4(az, CORBLBASE, (uint32_t)AZALIA_DMA_DMAADDR(&az->corb_dma));
+ AZ_WRITE_4(az, CORBUBASE, PTR_UPPER32(AZALIA_DMA_DMAADDR(&az->corb_dma)));
+ AZ_WRITE_1(az, CORBSIZE, az->corbsize);
diff --git a/repos/dde_bsd/patches/notify.patch b/repos/dde_bsd/patches/notify.patch
index fa15ae5e63..17f069cf16 100644
--- a/repos/dde_bsd/patches/notify.patch
+++ b/repos/dde_bsd/patches/notify.patch
@@ -1,19 +1,20 @@
-diff --git a/dev/audio.c b/dev/audio.c
-index 1271bc7..6535d10 100644
+Instead of implementing softintr handling add our notification
+functions directly.
+
--- a/dev/audio.c
+++ b/dev/audio.c
-@@ -411,6 +411,8 @@ audio_pintr(void *addr)
- }
- selwakeup(&sc->play.sel);
+@@ -572,6 +572,8 @@ audio_pintr(void *addr)
+ */
+ softintr_schedule(sc->play.softintr);
}
+
+ notify_play();
}
/*
-@@ -486,6 +488,8 @@ audio_rintr(void *addr)
- }
- selwakeup(&sc->rec.sel);
+@@ -655,6 +657,8 @@ audio_rintr(void *addr)
+ */
+ softintr_schedule(sc->rec.softintr);
}
+
+ notify_record();
diff --git a/repos/dde_bsd/patches/oppress_warning.patch b/repos/dde_bsd/patches/oppress_warning.patch
deleted file mode 100644
index 0b3e1ec97f..0000000000
--- a/repos/dde_bsd/patches/oppress_warning.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-dev/audio.c:XXX:Y: warning: ‘type’ may be used uninitialized in this function [-Wmaybe-uninitialized]
-diff --git a/dev/audio.c b/dev/audio.c
-index a9fa22b..da8a783 100644
---- a/dev/audio.c
-+++ b/dev/audio.c
-@@ -639,7 +639,7 @@ int
- audioprint(void *aux, const char *pnp)
- {
- struct audio_attach_args *arg = aux;
-- const char *type;
-+ const char *type = "never printed";
-
- if (pnp != NULL) {
- switch (arg->type) {
diff --git a/repos/dde_bsd/patches/s938_headset_quirk.patch b/repos/dde_bsd/patches/s938_headset_quirk.patch
new file mode 100644
index 0000000000..59f12019fc
--- /dev/null
+++ b/repos/dde_bsd/patches/s938_headset_quirk.patch
@@ -0,0 +1,48 @@
+diff --git a/dev/pci/azalia.h b/dev/pci/azalia.h
+index 8dd7641..2d3ce3a 100644
+--- a/dev/pci/azalia.h
++++ b/dev/pci/azalia.h
+@@ -516,6 +516,7 @@
+ #define AZ_QRK_WID_CLOSE_PCBEEP 0x00080000
++#define AZ_QRK_WID_HEADSET 0x00100000
+ #define AZ_QRK_ROUTE_SPKR2_DAC 0x01000000
+ #define AZ_QRK_DOLBY_ATMOS 0x02000000
+
+ /* memory-mapped types */
+ typedef struct {
+diff --git a/dev/pci/azalia_codec.c b/dev/pci/azalia_codec.c
+index 05d157b..8046b3b 100644
+--- a/dev/pci/azalia_codec.c
++++ b/dev/pci/azalia_codec.c
+@@ -100,6 +100,8 @@ azalia_codec_init_vtbl(codec_t *this)
+ break;
+ case 0x10ec0255:
+ this->name = "Realtek ALC255";
++ if (this->subid == 0x193e10cf)
++ this->qrks |= AZ_QRK_WID_HEADSET;
+ break;
+ case 0x10ec0256:
+ this->name = "Realtek ALC256";
+@@ -747,6 +749,9 @@ azalia_unsol_event(codec_t *this, int tag)
+ CORB_GET_PIN_SENSE, 0, &result);
+ if (!err && (result & CORB_PS_PRESENCE))
+ vol = 1;
++ // switch microphone to mic2
++ if (!err)
++ notify_hp_sense(result & CORB_PS_PRESENCE);
+ }
+ if (err)
+ break;
+@@ -2702,6 +2707,12 @@ azalia_codec_widget_quirks(codec_t *this, nid_t nid)
+ 0x57d7, NULL);
+ }
+
++ if (this->qrks & AZ_QRK_WID_HEADSET && nid == 0x19) {
++ w->d.pin.config = 0x03a19120;
++ azalia_pin_config_ov(w, CORB_CD_DEVICE_MASK, CORB_CD_MICIN);
++ w->enable = 1;
++ }
++
+ return(0);
+ }
+
diff --git a/repos/dde_bsd/ports/dde_bsd.hash b/repos/dde_bsd/ports/dde_bsd.hash
index a0f7b8dd2c..025ba4ecf6 100644
--- a/repos/dde_bsd/ports/dde_bsd.hash
+++ b/repos/dde_bsd/ports/dde_bsd.hash
@@ -1 +1 @@
-4d3a973ccec12ca00589f9213c2ce663d4a4e496
+771f320f0d4e11510d8f565fda456400b4793230
diff --git a/repos/dde_bsd/ports/dde_bsd.port b/repos/dde_bsd/ports/dde_bsd.port
index 35f3b41e20..b4dfb5b6d9 100644
--- a/repos/dde_bsd/ports/dde_bsd.port
+++ b/repos/dde_bsd/ports/dde_bsd.port
@@ -3,13 +3,13 @@ VERSION := 1
DOWNLOADS := audio.archive
#
-# Audio drivers from OpenBSD 6.6
+# Audio drivers from OpenBSD 7.1
#
SRC_DIR_AUDIO := src/lib/audio
-VERSION_AUDIO := 6.6
-BASE_URL := https://ftp.openbsd.org/pub/OpenBSD
+VERSION_AUDIO := 7.1
+BASE_URL := https://cdn.openbsd.org/pub/OpenBSD
URL(audio) := $(BASE_URL)/$(VERSION_AUDIO)/sys.tar.gz
-SHA(audio) := a1b19665989c02a2017a639d47a042f4fe7f584b6298727e982a5536020b832d
+SHA(audio) := 890cb97c01052f26cefe5430d635e0fdf6047ca701a99992968e16801e2a6565
DIR(audio) := $(SRC_DIR_AUDIO)
TAR_OPT(audio) := --strip-components=1 --files-from $(REP_DIR)/audio.list
HASH_INPUT += $(REP_DIR)/audio.list
@@ -18,12 +18,6 @@ HASH_INPUT += $(REP_DIR)/audio.list
# Patches
#
PATCHES := $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/*.patch)))
-
-AUDIO_OPT := -p1 -d$(SRC_DIR_AUDIO)
-PATCH_OPT(patches/oppress_warning.patch) := $(AUDIO_OPT)
-PATCH_OPT(patches/azalia_c.patch) := $(AUDIO_OPT)
-PATCH_OPT(patches/azalia_h.patch) := $(AUDIO_OPT)
-PATCH_OPT(patches/azalia_codec_c.patch) := $(AUDIO_OPT)
-PATCH_OPT(patches/notify.patch) := $(AUDIO_OPT)
+PATCH_OPT := -p1 -d$(SRC_DIR_AUDIO)
# vi: set ft=make :
diff --git a/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash b/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash
index 19fe882a08..d0a0da2612 100644
--- a/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash
+++ b/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash
@@ -1 +1 @@
-2022-05-24 1457c977583577de2e68eae2ac492c7a95ba9e4c
+2022-10-11 c9953284ebe0570c926982c35f37647a3132549d
diff --git a/repos/dde_bsd/recipes/src/bsd_audio_drv/content.mk b/repos/dde_bsd/recipes/src/bsd_audio_drv/content.mk
index f104af33c5..01764c9ed0 100644
--- a/repos/dde_bsd/recipes/src/bsd_audio_drv/content.mk
+++ b/repos/dde_bsd/recipes/src/bsd_audio_drv/content.mk
@@ -1,6 +1,6 @@
PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_bsd)
-MK_FILES := dde_bsd_audio.inc dde_bsd_audio_include.mk dde_bsd_audio_pci.mk
+MK_FILES := dde_bsd_audio.inc dde_bsd_audio_include.mk dde_bsd_audio_pci.inc
LIB_MK := $(addprefix lib/mk/, $(MK_FILES)) \
$(foreach SPEC,x86_32 x86_64,lib/mk/spec/$(SPEC)/dde_bsd_audio.mk) \
@@ -11,18 +11,13 @@ MIRROR_FROM_REP_DIR := $(LIB_MK) src/lib src/drivers patches include
MIRROR_FROM_PORT_DIR := $(addprefix src/lib/audio/, \
dev/pci/azalia_codec.c \
dev/pci/pcidevs.h \
- dev/pci/eap.c \
dev/pci/pcidevs_data.h \
dev/pci/azalia.h \
- dev/pci/eapreg.h \
dev/pci/azalia.c \
- dev/pci/auich.c \
dev/mulaw.h \
dev/audio_if.h \
dev/mulaw.c \
dev/audio.c \
- dev/ic/ac97.h \
- dev/ic/ac97.c \
lib/libkern \
sys/device.h \
sys/audioio.h \
diff --git a/repos/dde_bsd/recipes/src/bsd_audio_drv/hash b/repos/dde_bsd/recipes/src/bsd_audio_drv/hash
index 17fbba3f23..7893b4e706 100644
--- a/repos/dde_bsd/recipes/src/bsd_audio_drv/hash
+++ b/repos/dde_bsd/recipes/src/bsd_audio_drv/hash
@@ -1 +1 @@
-2022-05-24 d468d19c3211d09086b582583fa745223ff47594
+2022-10-11 eeb4565fb902ca980c98c6225c5c8141c8744011
diff --git a/repos/dde_bsd/run/audio_in.run b/repos/dde_bsd/run/audio_in.run
index 03bce3867e..681ee398a2 100644
--- a/repos/dde_bsd/run/audio_in.run
+++ b/repos/dde_bsd/run/audio_in.run
@@ -17,13 +17,14 @@ if {[have_spec linux]} {
set build_components {
core init timer
+ drivers/acpi
+ drivers/platform
+ app/pci_decode
+ server/report_rom
drivers/audio
test/audio_in
}
-source ${genode_dir}/repos/base/run/platform_drv.inc
-append_platform_drv_build_components
-
build $build_components
create_boot_directory
@@ -51,14 +52,68 @@ append config {
- }
+
-append_platform_drv_config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-append config {
-
-
+
+
@@ -83,13 +138,11 @@ install_config $config
#
set boot_modules {
- core ld.lib.so init timer test-audio_in
+ core ld.lib.so init timer
+ platform_drv acpi_drv pci_decode report_rom
+ pci_audio_drv test-audio_in
}
-append boot_modules [audio_drv_binary]
-
-append_platform_drv_boot_modules
-
build_boot_image $boot_modules
run_genode_until forever
diff --git a/repos/dde_bsd/run/audio_out.run b/repos/dde_bsd/run/audio_out.run
index 462a23d43f..86bd1dc7ce 100644
--- a/repos/dde_bsd/run/audio_out.run
+++ b/repos/dde_bsd/run/audio_out.run
@@ -1,47 +1,33 @@
assert_spec x86
-#
-# Check used commands
-#
+if {[have_include "power_on/qemu"]} {
+ puts "\nAudio_out test running on Qemu is not supported.\n"
+ exit 0
+}
-set wget [installed_command wget]
+if {[have_spec linux]} {
+ puts"\nAudio_out test running on Linux is not supported.\n"
+ exit 0
+}
-#
-# Configure
-#
-set use_mixer 0
-
-#
-# Build
-#
-
-set build_components {
+create_boot_directory
+build {
core init timer
+ drivers/acpi
+ drivers/platform
+ app/pci_decode
+ server/report_rom
drivers/audio
test/audio_out
}
-lappend_if $use_mixer build_components server/mixer
-
-source ${genode_dir}/repos/base/run/platform_drv.inc
-append_platform_drv_build_components
-
-build $build_components
-
-create_boot_directory
-
-#
-# Config
-#
-
-append config {
-
+install_config {
+
-
@@ -54,60 +40,87 @@ append config {
- }
+
-append_platform_drv_config
-
-append_if $use_mixer config {
-
+
-
-
-
-
-
- }
+
+
+
+
+
+
-append_if [have_spec linux] config {
- }
-append_if [expr ![have_spec linux]] config {
- }
-append config {
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
sample.raw
- }
-append_if $use_mixer config {
- }
-append config {
+
}
-install_config $config
-
-
#
# Get sample file
#
-if {[info exists env(GENODE_SAMPLE_RAW)]} {
- catch { exec $wget $::env(GENODE_SAMPLE_RAW) -O bin/sample.raw }
-}
-
if {![file exists bin/sample.raw]} {
puts ""
puts "The sample file is missing. Please take a look at"
@@ -117,22 +130,12 @@ if {![file exists bin/sample.raw]} {
exit 1
}
-#
-# Boot modules
-#
-
-append boot_modules {
- core ld.lib.so init timer } [audio_drv_binary] {
- test-audio_out sample.raw
+build_boot_image {
+ core ld.lib.so init timer
+ platform_drv acpi_drv pci_decode report_rom
+ pci_audio_drv test-audio_out sample.raw
}
-lappend_if $use_mixer boot_modules mixer
-
-append_platform_drv_boot_modules
-
-build_boot_image $boot_modules
-
-append qemu_args " -nographic -soundhw es1370 "
#
# For obvious reasons the timeout depends on the total
diff --git a/repos/dde_bsd/src/drivers/audio/main.cc b/repos/dde_bsd/src/drivers/audio/main.cc
index 48f5471748..c16e791b19 100644
--- a/repos/dde_bsd/src/drivers/audio/main.cc
+++ b/repos/dde_bsd/src/drivers/audio/main.cc
@@ -142,6 +142,7 @@ class Audio_out::Out
} else {
_play_silence();
+ return;
}
_advance_position(p_left, p_right);
@@ -221,13 +222,10 @@ struct Audio_out::Root_policy
{
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
- size_t session_size =
- align_addr(sizeof(Audio_out::Session_component), 12);
- if ((ram_quota < session_size) ||
- (sizeof(Stream) > ram_quota - session_size)) {
+ if (sizeof(Stream) > ram_quota) {
Genode::error("insufficient 'ram_quota', got ", ram_quota,
- " need ", sizeof(Stream) + session_size);
+ " need ", sizeof(Stream));
throw Genode::Insufficient_ram_quota();
}
@@ -412,13 +410,11 @@ struct Audio_in::Root_policy
void aquire(char const *args)
{
size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
- size_t session_size = align_addr(sizeof(Audio_in::Session_component), 12);
- if ((ram_quota < session_size) ||
- (sizeof(Stream) > (ram_quota - session_size))) {
+ if (sizeof(Stream) > ram_quota) {
Genode::error("insufficient 'ram_quota', got ", ram_quota,
- " need ", sizeof(Stream) + session_size,
- ", denying '",Genode::label_from_args(args),"'");
+ " need ", sizeof(Stream),
+ ", denying '", Genode::label_from_args(args),"'");
throw Genode::Insufficient_ram_quota();
}
diff --git a/repos/dde_bsd/src/drivers/audio/pci_audio_drv/target.mk b/repos/dde_bsd/src/drivers/audio/pci_audio_drv/target.mk
index 9f089ea4bd..00a3f837c9 100644
--- a/repos/dde_bsd/src/drivers/audio/pci_audio_drv/target.mk
+++ b/repos/dde_bsd/src/drivers/audio/pci_audio_drv/target.mk
@@ -1,7 +1,7 @@
REQUIRES = x86
TARGET = pci_audio_drv
SRC_CC = main.cc
-LIBS = dde_bsd_audio dde_bsd_audio_pci base
+LIBS = dde_bsd_audio base
INC_DIR += $(REP_DIR)/include
vpath %.cc $(REP_DIR)/src/drivers/audio
diff --git a/repos/dde_bsd/src/lib/audio/bsd.h b/repos/dde_bsd/src/lib/audio/bsd.h
index 8f60c79df7..919a9a05c1 100644
--- a/repos/dde_bsd/src/lib/audio/bsd.h
+++ b/repos/dde_bsd/src/lib/audio/bsd.h
@@ -24,25 +24,8 @@ namespace Bsd {
int probe_drivers(Genode::Env&, Genode::Allocator&);
void mem_init(Genode::Env&, Genode::Allocator &);
- void irq_init(Genode::Entrypoint&, Genode::Allocator&);
void timer_init(Genode::Env&);
void update_time();
-
-
- /**************************
- ** Bus_driver interface **
- **************************/
-
- struct Bus_driver
- {
- virtual Genode::Irq_session_capability irq_session() = 0;
-
- virtual Genode::addr_t alloc(Genode::size_t size, int align) = 0;
- virtual void free(Genode::addr_t virt, Genode::size_t size) = 0;
- virtual Genode::addr_t virt_to_phys(Genode::addr_t virt) = 0;
- virtual Genode::addr_t phys_to_virt(Genode::addr_t phys) = 0;
- };
-
}
#endif /* _BSD_H_ */
diff --git a/repos/dde_bsd/src/lib/audio/bsd_emul_pci.c b/repos/dde_bsd/src/lib/audio/bsd_emul_pci.c
index ad0886c663..2b2a0a26d3 100644
--- a/repos/dde_bsd/src/lib/audio/bsd_emul_pci.c
+++ b/repos/dde_bsd/src/lib/audio/bsd_emul_pci.c
@@ -40,13 +40,16 @@ short pv[] = { -1, PCI_BUS_PARENT };
struct cfdata cfdata[] = {
{&audio_ca, &audio_cd, 0, 0, 0, 0, pv+0, 0, 0},
{&azalia_ca, &azalia_cd, 0, 0, 0, 0, pv+1, 0, 0},
- {&eap_ca, &eap_cd, 0, 0, 0, 0, pv+1, 0, 0},
- {&auich_ca, &auich_cd, 0, 0, 0, 0, pv+1, 0, 0},
};
struct device pci_bus = { DV_DULL, { 0, 0 }, 0, 0, { 'p', 'c', 'i', '0'}, 0, 0, 0 };
+
+/* global unit counter */
+static int dv_unit;
+
+
/**
* This function is our little helper that matches and attaches
* the driver to the device.
@@ -74,12 +77,23 @@ int probe_cfdata(struct pci_attach_args *pa)
M_DEVBUF, M_NOWAIT|M_ZERO);
dev->dv_cfdata = cf;
+ dev->dv_unit = dv_unit++;
snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d", cd->cd_name,
dev->dv_unit);
- printf("%s at %s\n", dev->dv_xname, pci_bus.dv_xname);
+ printf("%s [%x:%x]\n", dev->dv_xname,
+ pa->pa_id & 0xffffu, (pa->pa_id >> 16u) & 0xffffu);
ca->ca_attach(&pci_bus, dev, pa);
+ /*
+ * The contrib code is patched to set the dv_ref when the
+ * driver attached successfully.
+ */
+ if (!pci_bus.dv_ref) {
+ free(dev, M_DEVBUF, ca->ca_devsize);
+ return 0;
+ }
+
return 1;
}
}
diff --git a/repos/dde_bsd/src/lib/audio/driver.cc b/repos/dde_bsd/src/lib/audio/driver.cc
index bf8311fef3..ba34fa8e28 100644
--- a/repos/dde_bsd/src/lib/audio/driver.cc
+++ b/repos/dde_bsd/src/lib/audio/driver.cc
@@ -33,8 +33,8 @@
extern struct cfdriver audio_cd;
-static dev_t const adev = 0x00; /* audio0 (minor nr 0) */
-static dev_t const mdev = 0x10; /* mixer0 (minor nr 16) */
+static dev_t const adev = 0x00; /* /dev/audio0 */
+static dev_t const mdev = 0xc0; /* /dev/audioctl */
static bool adev_usuable = false;
@@ -327,6 +327,11 @@ static bool open_audio_device(dev_t dev)
return false;
int err = audioopen(dev, FWRITE|FREAD, 0 /* ifmt */, 0 /* proc */);
+
+ /* try to open playback only, if capturing potentially failed */
+ if (err == ENODEV)
+ err = audioopen(dev, FWRITE, 0 /* ifmt */, 0 /* proc */);
+
if (err)
return false;
@@ -616,7 +621,6 @@ void Audio::init_driver(Genode::Env &env, Genode::Allocator &alloc,
Genode::Signal_context_capability announce_sigh)
{
Bsd::mem_init(env, alloc);
- Bsd::irq_init(env.ep(), alloc);
Bsd::timer_init(env);
static Task bsd_task(env, alloc, config, announce_sigh);
diff --git a/repos/dde_bsd/src/lib/audio/dummies.cc b/repos/dde_bsd/src/lib/audio/dummies.cc
index cbcfcc74f9..28eea52e1b 100644
--- a/repos/dde_bsd/src/lib/audio/dummies.cc
+++ b/repos/dde_bsd/src/lib/audio/dummies.cc
@@ -46,21 +46,35 @@ DUMMY name(void) { \
DUMMY_RET(1, pci_intr_map_msi) /* do not support MSI API */
DUMMY_RET(0, pci_intr_string)
+DUMMY(0, bus_dmamap_unload)
+DUMMY(0, bus_dmamem_mmap)
+DUMMY(0, bus_dmamem_unmap)
DUMMY(0, bus_space_unmap)
DUMMY(0, config_activate_children)
DUMMY(0, config_deactivate)
DUMMY(0, config_detach)
DUMMY(0, config_detach_children)
DUMMY(0, cpu_info_primary)
+DUMMY(0, device_unref)
+DUMMY(0, klist_free)
+DUMMY(0, klist_init_mutex)
+DUMMY(0, klist_insert_locked)
+DUMMY(0, klist_invalidate)
+DUMMY(0, klist_remove)
+DUMMY(0, klist_remove_locked)
+DUMMY(0, knote_modify)
+DUMMY(0, knote_process)
DUMMY(0, pci_findvendor)
DUMMY(0, pci_intr_disestablish)
DUMMY(0, pci_set_powerstate)
DUMMY(0, psignal)
DUMMY(0, selrecord)
DUMMY(0, selwakeup)
+DUMMY(0, softintr_disestablish)
+DUMMY(0, softintr_schedule)
DUMMY(0, tsleep)
DUMMY(0, tsleep_nsec)
DUMMY(0, vdevgone)
-DUMMY(0, device_unref)
+DUMMY(1, softintr_establish)
} /* extern "C" */
diff --git a/repos/dde_bsd/src/lib/audio/include/bsd_emul.h b/repos/dde_bsd/src/lib/audio/include/bsd_emul.h
index 379ed9afeb..cc09802601 100644
--- a/repos/dde_bsd/src/lib/audio/include/bsd_emul.h
+++ b/repos/dde_bsd/src/lib/audio/include/bsd_emul.h
@@ -65,6 +65,43 @@ typedef signed long long off_t;
#define minor(x) ((int32_t)((x) & 0xff) | (((x) & 0xffff0000) >> 8))
+/*******************
+ ** machine/cpu.h **
+ *******************/
+
+struct cpu_info { };
+extern struct cpu_info cpu_info_primary;
+
+#define curcpu() (&cpu_info_primary)
+
+
+/*********************
+ ** machine/mutex.h **
+ *********************/
+
+#define MUTEX_INITIALIZER(ipl) { 0, (ipl), 0, NULL }
+#define MUTEX_ASSERT_UNLOCK(mtx) do { \
+ if ((mtx)->mtx_owner != curcpu()) \
+ panic("mutex %p not held in %s\n", (mtx), __func__); \
+} while (0)
+#define MUTEX_ASSERT_LOCKED(mtx) do { \
+ if ((mtx)->mtx_owner != curcpu()) \
+ panic("mutex %p not held in %s\n", (mtx), __func__); \
+} while (0)
+#define MUTEX_ASSERT_UNLOCKED(mtx) do { \
+ if ((mtx)->mtx_owner == curcpu()) \
+ panic("mutex %p held in %s\n", (mtx), __func__); \
+} while (0)
+
+struct mutex
+{
+ volatile int mtx_lock;
+ int mtx_wantipl; /* interrupt priority level */
+ int mtx_oldipl;
+ void *mtx_owner;
+};
+
+
/*****************
** sys/errno.h **
*****************/
@@ -215,12 +252,17 @@ struct kevent
struct knote;
SLIST_HEAD(klist, knote);
+#define FILTEROP_ISFD 0x00000001
+#define FILTEROP_MPSAFE 0x00000002
+
struct filterops
{
- int f_isfd;
+ int f_flags;
int (*f_attach)(struct knote*);
void (*f_detach)(struct knote*);
int (*f_event)(struct knote*, long);
+ int (*f_modify)(struct kevent *, struct knote *);
+ int (*f_process)(struct knote *, struct kevent *);
};
struct knote
@@ -233,6 +275,15 @@ struct knote
void *kn_hook;
};
+int knote_modify(const struct kevent *kev, struct knote *kn);
+int knote_process(struct knote *kn, struct kevent *kev);
+
+extern void klist_free(struct klist *);
+extern void klist_init_mutex(struct klist *, struct mutex *);
+extern void klist_insert(struct klist *, struct knote *);
+extern void klist_invalidate(struct klist *);
+extern void klist_remove(struct klist *, struct knote *);
+
/*******************
** sys/selinfo.h **
@@ -247,43 +298,6 @@ void selrecord(struct proc *selector, struct selinfo *);
void selwakeup(struct selinfo *);
-/*******************
- ** machine/cpu.h **
- *******************/
-
-struct cpu_info { };
-extern struct cpu_info cpu_info_primary;
-
-#define curcpu() (&cpu_info_primary)
-
-
-/*********************
- ** machine/mutex.h **
- *********************/
-
-#define MUTEX_INITIALIZER(ipl) { 0, (ipl), 0, NULL }
-#define MUTEX_ASSERT_UNLOCK(mtx) do { \
- if ((mtx)->mtx_owner != curcpu()) \
- panic("mutex %p not held in %s\n", (mtx), __func__); \
-} while (0)
-#define MUTEX_ASSERT_LOCKED(mtx) do { \
- if ((mtx)->mtx_owner != curcpu()) \
- panic("mutex %p not held in %s\n", (mtx), __func__); \
-} while (0)
-#define MUTEX_ASSERT_UNLOCKED(mtx) do { \
- if ((mtx)->mtx_owner == curcpu()) \
- panic("mutex %p held in %s\n", (mtx), __func__); \
-} while (0)
-
-struct mutex
-{
- volatile int mtx_lock;
- int mtx_wantipl; /* interrupt priority level */
- int mtx_oldipl;
- void *mtx_owner;
-};
-
-
/*****************
** sys/mutex.h **
*****************/
@@ -298,6 +312,8 @@ void mtx_leave(struct mutex *);
#define INFSLP __UINT64_MAX__
+#define KERNEL_ASSERT_LOCKED()
+
extern int nchrdev;
int enodev(void);
@@ -315,6 +331,7 @@ void wakeup(const volatile void*);
int tsleep(const volatile void *, int, const char *, int);
int tsleep_nsec(const volatile void *, int, const char *, uint64_t);
int msleep(const volatile void *, struct mutex *, int, const char*, int);
+int msleep_nsec(const volatile void *, struct mutex *, int, const char*, uint64_t);
int uiomove(void *, int, struct uio *);
@@ -708,6 +725,13 @@ int timeout_del(struct timeout *);
#define htole32(x) ((uint32_t)(x))
+/******************
+ ** sys/stdint.h **
+ ******************/
+
+#define UINT64_MAX 0xffffffffffffffffULL
+
+
/****************
** sys/time.h **
****************/
@@ -720,6 +744,24 @@ struct timeval
void microuptime(struct timeval *);
+static inline uint64_t SEC_TO_NSEC(uint64_t seconds)
+{
+ if (seconds > UINT64_MAX / 1000000000ULL)
+ return UINT64_MAX;
+ return seconds * 1000000000ULL;
+}
+
+
+/*************************
+ ** arch specifc intr.h **
+ *************************/
+
+#define IPL_SOFTNET 3
+
+void *softintr_establish(int, void (*)(void *), void *);
+void softintr_schedule(void *);
+void softintr_disestablish(void *);
+
/***************************
** lib/libkern/libkern.h **
diff --git a/repos/dde_bsd/src/lib/audio/irq.cc b/repos/dde_bsd/src/lib/audio/irq.cc
deleted file mode 100644
index 1075b33f90..0000000000
--- a/repos/dde_bsd/src/lib/audio/irq.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * \brief Signal context for IRQ's
- * \author Josef Soentgen
- * \date 2014-10-14
- */
-
-/*
- * Copyright (C) 2014-2020 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU Affero General Public License version 3.
- */
-
-/* Genode includes */
-#include
-#include
-#include
-#include
-#include
-
-/* local includes */
-#include