diff --git a/VERSION b/VERSION index 60f48c4cb..b5bf6a3eb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -19.08 +19.11 diff --git a/doc/challenges.txt b/doc/challenges.txt index 62f12d23a..64cef6313 100644 --- a/doc/challenges.txt +++ b/doc/challenges.txt @@ -391,6 +391,22 @@ Platforms laptops. +System management +################# + +:Remote management of Sculpt OS via Puppet: + + [https://en.wikipedia.org/wiki/Puppet_(company)#Puppet - Puppet] is a + software-configuration management tool for administering a large amount + of machines from one central place. Genode's + [https://genode.org/download/sculpt - Sculpt OS] lends itself to such + an approach of remote configuration management by the means of the + "config" file system (for configuring components and deployments) and + the "report" file system (for obtaining the runtime state of components). + The project would explore the application of the Puppet approach and tools + to Sculpt OS. + + Optimizations ############# diff --git a/doc/news.txt b/doc/news.txt index 12a134c14..dd3663390 100644 --- a/doc/news.txt +++ b/doc/news.txt @@ -3,6 +3,54 @@ Genode News =========== +Genode OS Framework release 19.11 | 2019-11-28 +############################################## + +| Following this year's theme of "bridging worlds", Genode 19.11 adds the +| ability to use popular build tools like CMake for application development, +| introduces a new virtual-machine monitor for 64-bit ARM, and enhances +| POSIX compatibility. As another highlight, it features the first version +| of our custom block-device encrypter. + +Block-device encryption is a feature often requested by users of our Sculpt OS. +Until now, we deliberately left this topic unaddressed because we felt that a +profound answer was beyond our expertise. However, during the past year, we +dived deep into it. The result is the prototype for a new block encrypter that +encrypts data but also protects integrity and freshness. For us, the +implementation of the encrypter is especially intriguing because - with about +7000 lines of code - it is Genode's first non-trivial component written in the +[https://en.wikipedia.org/wiki/SPARK_(programming_language) - SPARK] +programming language. + +The second major addition is a new virtual machine monitor (VMM) for 64-bit +ARM platforms such as the NXP i.MX8. It leverages the +[https://genode.org/documentation/articles/arm_virtualization - proof of concept] +we developed in 2015 for ARMv7, which we pursued as a technology exploration. +In contrast, our aspiration with the new VMM is a product-quality solution. + +In our [https://genode.org/about/road-map - road map] for 2019, we stated +the "bridging of worlds" as our overall theme for this year. On that account, +the current release moves the project forward on two levels. First, by +successively increasing the scope of POSIX compatibility, we reduce the +friction when porting existing application software to Genode. We managed +to bridge several gaps in our POSIX support that we considered as impossible +to cover some years ago. In particular, we identified ways to emulate certain +POSIX signals, ioctl calls, and fork/execve semantics. This way, popular +software such as bash, coreutils, or Vim can now be executed as regular +Genode components with no additional runtime environment (like Noux or a VMM) +required. + +At a higher level, the current release introduces new tooling especially +geared at the development and porting of application software. Compared to +Genode's regular development tools, which were designed for whole-system +development, the new tool called Goa relieves the developer from the +complexity of Genode's custom build system and instead promotes the use of +popular commodity solutions like CMake. + +These and more topics are described in the +[https:/documentation/release-notes/19.11 - release documentation of version 19.11...] + + Genode OS Framework release 19.08 | 2019-08-28 ############################################## diff --git a/doc/release_notes-19-08.txt b/doc/release_notes-19-08.txt index de59a3606..791ea40cf 100644 --- a/doc/release_notes-19-08.txt +++ b/doc/release_notes-19-08.txt @@ -143,8 +143,8 @@ corresponds to Shift, '' to Control, '' to AltGr, and '' to Caps Lock. ! -! -! +! +! ! As outlined above, the '' nodes generated by xkb2ifcfg always use the diff --git a/doc/release_notes-19-11.txt b/doc/release_notes-19-11.txt new file mode 100644 index 000000000..7df467cb1 --- /dev/null +++ b/doc/release_notes-19-11.txt @@ -0,0 +1,815 @@ + + + =============================================== + Release notes for the Genode OS Framework 19.11 + =============================================== + + Genode Labs + + + +On our [https://genode.org/about/road-map - road map] for this year, we stated +"bridging worlds" as our guiding theme of 2019. The current release pays +tribute to this ambition on several accounts. + +First, acknowledging the role of POSIX in the real world outside the heavens +of Genode, the release vastly improves our (optional) C runtime with respect +to the emulation of POSIX signals, execve, and ioctl calls. With the line of +work described in Section [C runtime with improved POSIX compatibility], we +hope to greatly reduce the friction when porting and hosting existing +application software directly on Genode. + +Second, we identified the process of porting or developing application +software worth improving. Our existing tools were primarily geared to +operating-system development, not application development. Application +developers demand different work flows and tools, including the freedom to use +a build system of their choice. +Section [New tooling for bridging existing build systems with Genode] +introduces our new take on this productivity issue. + +Third, in cases where the porting of software to Genode is considered +infeasible, virtualization comes to the rescue. With the current release, a +new virtual machine monitor for the 64-bit ARM architecture enters the +framework. It is presented in Section [Virtualization of 64-bit ARM platforms]. + +As another goal for 2019, we envisioned a solution for block-level device +encryption, which is a highly anticipated feature among Genode users. We are +proud to present the preliminary result of our year-long development in +Section [Preliminary block-device encrypter]. + + +Preliminary block-device encrypter +################################## + +Over the past year, we worked on implementing a block-device encryption +component that makes use of the +[https://en.wikipedia.org/wiki/SPARK_(programming_language) - SPARK] +programming language for its core logic. In contrast to common +block-device encryption techniques where normally is little done besides +the encryption of the on-disk blocks, the _consistent block encrypter (CBE)_ +aims for more. It combines multiple techniques to ensure integrity - +the detection of unauthorized modifications of the block-device - +and robustness against data loss. Robustness is achieved by keeping snapshots +of old states of the device that remain unaffected by the further operation of +the device. A copy-on-write mechanism (only the differential changes to the +last snapshot are stored) is employed to maintain this snapshot history with +low overhead. To be able to access all states of the device in the same manner, +some kind of translation from virtual blocks to blocks on the device is needed. +Hash-trees, where each node contains the hash of its sub-nodes, combine the +aspect of translating blocks and ensuring their integrity in an elegant way. +During the tree traversal, the computed hash of each node can be easily checked +against the hash stored in the parent node. + +The CBE does not perform any cryptography by itself but delegates +cryptographic operations to another entity. It neither knows nor cares about +the used algorithm. Of all the nodes in the virtual block device (VBD), only +the leaf nodes, which contain the data, are encrypted. All other nodes, which +only contain meta-data, are stored unencrypted. + +Design +------ + +As depicted in Figure [cbe_trees], all information describing the various +parts of the CBE is stored in the superblock. The referenced VBD is a set of +several hash trees, each representing a certain device state including the +current working state. Only the tree of the current working state is used to +write data to the block device. All other trees represent snapshots of older +states and are immutable. Each stored device state has a generation number +that provides the chronological order of the states. + +As you can see, in the depicted situation, there exist four device states - the +snapshot with generation 3 is the oldest, followed by two newer snapshots and +generation 6 that marks the working state of the virtual device. The tree with +generation 6 is the current working tree. Each tree contains all changes done +to the VBD since the previous generation (for generation 6 the red nodes). All +parts of a tree that didn't change since the previous generation are references +into older trees (for generation 6 the gray nodes). Note that in the picture, +nodes that are not relevant for generation 6 are omitted to keep it manageable. +The actual data blocks of the virtual device are the leaf nodes of the trees, +shown as squares. + +[image cbe_trees] + +Whenever a block request from the client would override data blocks in +generation 6 that are still referenced from an older generation, new blocks for +storing the changes are needed. Here is where the so-called _Free Tree_ enters +the picture. This tree contains and manages the spare blocks. Spare blocks are +a certain amount of blocks that the CBE has in addition to the number of blocks +needed for initializing the virtual device. So, after having initialized a +virtual device, they remain unused and are only referenced by the Free Tree. +Therefore, in case the VBD needs new blocks, it consults the Free Tree (red +arrow). + +In the depicted situation, writing the first data block (red square) would +require allocating 4 new blocks as all nodes in the branch leading to the +corresponding leaf node - including the leaf node itself - have to be written. +In contrast, writing the second data block would require allocating only one +new block as the inner nodes (red circles) now already exist. Subsequent write +requests affecting only the new blocks will not trigger further block +allocations because they still belong to the current generation and will be +changed in-place. To make them immutable we have to create a new snapshot. + +The blocks in generation 5 that were replaced by the change to generation 6 +(blue nodes) are not needed for the working state of the virtual device +anymore. They are therefore, in exchange for the allocated blocks, added to +the Free Tree. But don't be fooled by the name, they are not free for +allocation yet, but marked as "reserved" only. This means, they are +potentially still part of a snapshot (as is the case in our example) but the +Free Tree shall keep checking, because once all snapshots that referenced the +blue blocks have disappeared, they become free blocks and can be allocated +again. + +To create a new snapshot, we first have to make all changes done to the VBDs +working state as well as the Free Tree persistent by writing all corresponding +blocks to the block-device. After that, the new superblock state is written to +the block-device. To safeguard this operation, the CBE always maintains several +older states of the superblock on the block device. In case writing the new +state of the superblock fails, the CBE could fall back to the last state that, +in our example, would contain only generations 3, 4, and 5. Finally, the +current generation of the superblock in RAM is incremented by one (in the +example to generation 7). Thereby, generation 6 becomes immutable. + +A question that remains is when to create snapshots. Triggering a snapshot +according to some heuristics inside the CBE might result in unnecessary +overhead. For instance, the inner nodes of the tree change frequently during a +sequential operation. We might not want them to be re-allocated all the time. +Therefore, the creation of a snapshot must be triggered explicitly from the +outside world. This way, we can accommodate different strategies, for +instance, client-triggered, time-based, or based on the amount of data +written. + +When creating a snapshot, it can be specified whether it shall be disposable +or persistent. A disposable snapshot will be removed automatically by the CBE +in two situations, either + +* When there are not enough usable nodes in the Free Tree left to + satisfy a write request, or +* When creating a new snapshot and all slots in the superblock that might + reference snapshots are already occupied. + +A persistent snapshot, or quarantine snapshot, on the other hand will never be +removed automatically. Its removal must be requested explicitly. + +During initialization, the CBE selects the most recent superblock and reads the +last generation value from it. The current generation (or working state +generation) is then set to the value incremented by one. Since all old blocks, +that are still referenced by a snapshot, are never changed again, overall +consistency is guaranteed for every generation whose superblock was stored +safely on disk. + +Implementation +-------------- + +Although we aimed for a SPARK implementation of the CBE, we saw several +obstacles with developing it in SPARK right from the beginning. These obstacles +mainly came from the fact that none of us was experienced in designing +complex software in SPARK. So we started by conducting a rapid design-space +exploration using our mother tongue (C++) while using only language features +that can be mapped 1:1 to SPARK concepts. Additionally, we applied a clear +design methodology that allowed us to keep implementation-to-test cycles +small and perform a seamless and gradual translation into SPARK: + +* _Control flow_ + + The core logic of the CBE is a big state machine that doesn't block. On each + external event, the state machine gets poked to update itself accordingly. + C++ can call SPARK but SPARK never calls C++. The SPARK code therefore + evolves as self-contained library. + +* _Modularity_ + + The complex state machine of the CBE as a whole is split-up into smaller + manageable sub-state-machines, working independently from each other. These + modules don't call each other directly. Instead, an additional superior + module handles the interplay. This is done by constantly iterating over all + modules with the following procedure until no further progress can be made: + + # Try to enter requests of other modules into the current one + # Poke the state machine of the current module + # The current module may have generated requests - Try to enter them into + the targeted modules + # The current module may have finished requests - Acknowledge them at the + modules they came from + + Each module is represented through a class (C++) respectively a package with + a private state record (SPARK). + +* _No global state_ + + There are no static (C++) or package (SPARK) variables. All state is kept in + members of objects (C++) respectively records (SPARK). All packages are pure + and sub-programs have no side-effects. Therefore, memory management and + communication with other components is left to OS glue-code outside the + core logic. + +This approach worked out well. Module by module, we were able to translate the +C++ prototype to SPARK without long untested phases, rendering all regression +bugs manageable. In Genode, the CBE library is currently integrated through +the CBE-VFS plugin. Figure [cbe_modules] depicts its current structure and the +integration via VFS plugin. + +[image cbe_modules] + +The green and blue boxes each represent an Ada/SPARK package. The translation +to SPARK started at the bottom of the picture moving up to the more abstract +levels until it reached the Library module. This is the module that handles +the interplay of all other modules. Its interface is the front end of the CBE +library. So, all green packages are now completely written in SPARK and +together form the CBE library. Positioned above, the CXX library in blue is +brought in by a separate library and exports the CBE interface to C++. This +way, the CBE can also be used in other environments including pure SPARK +programs. The CXX Library package is not written in SPARK but Ada and performs +all the conversions and checks required to meet the preconditions set by the +SPARK packages below. + +At the C++ side, we have the VFS plugin. Even at this level, the already +mentioned procedure applies: The plugin continuously tries to enter requests +coming from the VFS client (above) into the CBE (below), pokes the CBE state +machine, and puts thereby generated block/crypto requests of the CBE into the +corresponding back-ends (left). This process is repeated until there is no +further progress without waiting for an external event. + +Current state +------------- + +In its current state, the CBE library is still pretty much in flux and is not +meant for productive use. + +As the Free Tree does not employ copy-on-write semantics for its meta-data, a +crash, software- or hardware-wise, will corrupt the tree structure and renders +the CBE unusable on the next start. + +This issue is subject to ongoing work. That being said, there are +components that, besides being used for testing, show how the interface of the +CBE library lends itself to be integrated in components in different ways. At +the moment, there are two components making use of the CBE library as +block-device provider. + +The first one is the aforementioned CBE-VFS plugin. Besides r/w access to the +working tree and r/o access to all persistent snapshots, it also provides a +management interface where persistent snapshots can be created or discarded. +Its current layout is illustrated by Figure [cbe_vfs]. The VFS plugin +generates three top directories in its root directory. The first one is the +_control_ directory. It contains several pseudo files for managing the CBE: + +[image cbe_vfs] + +:'key': set a key by writing a string into the file. +:'create_snapshot': writing 'true' to this file will attempt to create + a new snapshot. (Eventually the snapshot will + appear in the 'snapshots' directory if it could be + created successfully.) +:'discard_snapshot': writing a snapshot ID into this file will discard + the snapshot + +The second is the 'current' directory. It gives access to the current +working tree of the CBE and contains the following file: + +:'data': this file represents the virtual block device and gives + read and write access to the data stored by the CBE. + +The third and last is the 'snapshots' directory. For each persistent snapshot, +there is a sub-directory named after the ID of the snapshot. This directory, +like the 'current' directory, contains a 'data' file. This file, however, +gives only read access to the data belonging to the snapshot. + +The CBE-VFS plugin itself uses the VFS to access the underlying block device. +It utilizes the file specified in its configuration. Here is a '' +snippet that shows a configured CBE-VFS plugin where the block device is +provided by the block VFS plugin. + +! +! +! +! +! +! + +An exemplary ready-to-use run script can be found in the CBE repository +at _run/cbe_vfs_snaps.run_. This run script uses a bash script to +automatically perform a few operations on the CBE using the VFS plugin. +Afterwards it will drop the user into a shell where further operations +can be performed manually, e.g.: + +! dd if=/dev/zero of=/dev/cbe/current/data bs=4K + +The second component is the CBE server. In contrast to the CBE-VFS plugin, +it is just a simple block-session proxy component that uses a block connection +as back end to access a block-device. It provides a front-end block session to +its client, creates disposable snapshots every few seconds, and uses the +'External_Crypto' library to encrypt the data blocks using AES-CBC-ESSIV. The +used key is a plain passphrase. The following snippet illustrates its +configuration: + +! +! +! +! +! + +The _run/cbe.run_ run script in the CBE repository showcases the use of the +CBE server. + +Both run scripts will create the initial CBE state in a RAM-backed +block device that is then accessed by the CBE server or the CBE-VFS +plugin. + +The run-script and the code itself can be found on the +[https://github.com/cnuke/cbe/tree/cbe_19.11 - cbe/cbe_19.11] branch on +GitHub. If you intend to try it out, you have to checkout +the corresponding +[https://github.com/cnuke/genode/tree/cbe_19.11 - genode/cbe_19.11] +branch in the Genode repository as well. + +Future plans +------------ + +Besides addressing the current shortcomings and getting the CBE library +production-ready so that it can be used in Sculpt, there are still +a few features that are currently unimplemented. For one we would like +to add support for making it possible to resize the VBD as well as the +Free Tree. For now the geometry is fixed at initialization time and cannot +be changed afterwards. Furthermore, we would like to enable re-keying, +i.e., changing the used cryptographic key and re-encrypting the tree +set of the VBD afterwards. In addition to implementing those features, the +overall tooling for the CBE needs to be improved. E.g., there is currently +no proper initialization component. For now, we rely on a component +that was built merely as a test vehicle to generate the initial trees. + + +Virtualization of 64-bit ARM platforms +###################################### + +Genode has a long history regarding support of all kinds of +virtualization-related techniques including +[https://genode.org/documentation/release-notes/9.11#Paravirtualized_Linux_on_Genode_OKL4 - para-virtualization], +[https://genode.org/documentation/articles/trustzone - TrustZone], +hardware-assisted virtualization on +[https://genode.org/documentation/articles/arm_virtualization - ARM], +[https://genode.org/documentation/release-notes/13.02#Full_virtualization_on_NOVA_x86 - x86], +up to the full virtualization stack of +[https://genode.org/documentation/release-notes/14.02#VirtualBox_on_top_of_the_NOVA_microhypervisor - VirtualBox]. + +We regard those techniques as welcome stop-gap solutions for using non-trivial +existing software stacks on top of Genode's clean-slate OS architecture. The +[https://genode.org/documentation/release-notes/19.05#Kernel-agnostic_virtual-machine_monitors - recent] +introduction of a kernel-agnostic interface to control virtual machines (VM) +ushered a new level for the construction respectively porting of +virtual-machine monitors (VMM). By introducing a new ARMv8-compliant VMM +developed from scratch, we continue this line of work. + +The new VMM builds upon our existing proof-of-concept (PoC) implementation for +ARMv7 as introduced in release +[https://genode.org/documentation/release-notes/15.02#Virtualization_on_ARM - 15.02]. +In contrast to the former PoC implementation, however, it aims to be complete +to a greater extent. Currently, it comprises device models for the following +virtual hardware: + +* RAM +* System Bus +* CPU +* Generic Interrupt Controller v2 and v3 +* Generic Timer +* PL011 UART (limited) +* Pass-through devices + +The VMM is able to load diverse 64-bit Linux kernels including +Device-Tree-Binary (DTB) and Initramfs. Currently, the implementation uses a +fixed memory layout for the guest-physical memory view, which needs to be +reflected by the DTB used by the guest OS. An example device-tree source file +can be found at _repos/os/src/server/vmm/spec/arm_v8/virt.dts_. The actual VMM +is located in the same directory. + +Although support for multi-core VMs is already considered internally, it is +not yet finished. Further outstanding features that are already in development +are Virtio device model support for networking and console. As the first - and +by now only - back end, we tied the VMM to the ARMv8 broadened Kernel-agnostic +VM-session interface as implemented by Genode's custom base-hw kernel. As a +side effect of this work, we consolidated the generic VM session interface +slightly. The RPC call to create a new virtual-CPU now returns an identifier +for identification. + +The VMM has a strict dependency on ARM's hardware virtualization support +(EL2), which comprises extensions for the ARMv8-A CPU, ARM's generic timer, +and ARM's GIC. This rules out the Raspberry Pi 3 board as a base platform +because it does not include a GIC but a custom interrupt-controller without +hardware-assisted virtualization of interrupts. To give the new VMM a try, we +recommend using the run script _repos/os/run/vmm_arm.run_ as a starting point +for executing the VMM on top of the i.MX8 Evaluation Kit board. + + +New tooling for bridging existing build systems with Genode +########################################################### + +Genode's development tools are powerful and intimidating at the same time. +Being designed from the perspective of a whole-systems developer, they put +emphasis on the modularity of the code base (separating concerns like +different kernels or system abstraction levels), transitive dependency +tracking between libraries, scripting of a wide variety of system-integration +tasks, and the continuous integration of complete Genode-based +operating-system scenarios. Those tools are a two-edged sword though. + +On the one hand, the tools are key for the productivity of seasoned Genode +developers once the potential of the tools is fully understood and leveraged. +For example, during the development of Sculpt OS, we are able to +change an arbitrary line of code in any system component and can test-drive +the resulting Sculpt system on real hardware within a couple of seconds. +As another example, the almost seamless switching from one OS kernel to +another has become a daily routine that we just take for granted without +even thinking about it. + +On the other hand, the sophistication of the tools stands in the way of +application developers who are focused on a particular component instead +of the holistic Genode system. In this case, the powerful system-integration +features remain unused but the complexity of the tools and the build system +prevails. Speaking of build systems, this topic is ripe of emotions +anyway. _Developers use to hate build systems._ Forcing Genode's build +system down the throats of application developers is probably not the best +idea to make Genode popular. + +This line of thoughts prompted us to re-approach the tooling for Genode from +the perspective of an application developer. The intermediate result is a new +tool called Goa: + +:Goa project at GitHub: + + [https://github.com/nfeske/goa] + +Unlike Genode's regular tools, Goa's work flow is project-centered. A project +is a directory that may contain source code, data, instructions how to +download source codes from a 3rd party, descriptions of system scenarios, or +combinations thereof. Goa is independent from Genode's regular build system. +It combines Genode's package management (depot) with commodity build systems +such a CMake. In addition to building and test-driving application software +directly on a Linux-based development system, Goa is able to aid the process +of exporting and packaging the software in the format expected by Genode +systems like Sculpt OS. + +At the current stage, Goa should be considered as work in progress. It's a new +approach and its success is anything but proven. That said, if you are +interested in developing or porting application software for Genode, your +feedback would be especially valuable. As a starting point, you may find the +following introductory article helpful: + +:Goa - streamlining the development of Genode applications: + + [https://genodians.org/nfeske/2019-11-25-goa] + + +Base framework and OS-level infrastructure +########################################## + +File-system session +=================== + +The file-system session interface received a much anticipated update. + +Writing modification times +-------------------------- + +The new operation WRITE_TIMESTAMP allows a client to update the modification +time of a file-system node. The time is defined by the client to keep +file-system servers free from time-related concerns. The VFS server implements +the operation by forwarding it to the VFS plugin interface. At present, this +new interface is implemented by the rump VFS plugin to store modification +times on EXT2 file systems. + + +Enhanced file-status info +------------------------- + +The status of a file-system node as returned by the 'File_system::Status' +operation has been revisited. First, we replaced the fairly opaque "mode" bits - +which were an ad-hoc attempt to stay compatible with Unix - with the explicit +notion of 'readable', 'writeable', and 'executable' attributes. We completely +dropped the notion of users and groups. Second, we added the distinction +between *continuous* and *transactional* files to allow for the robust +implementation of continuous write operations across component boundaries. A +continuous file can be written-to via a sequence of arbitrarily sized chunks +of data. For such files, a client can split a large write operation into any +number of smaller operations in accordance to the size of the used I/O +buffers. In contrast, a write to a transactional file is regarded as a +distinct operation. The canonical example of a transactional file is a +socket-control pseudo file. + + +Virtual file-system infrastructure +================================== + +First fragments of a front-end API +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The VFS is mostly used indirectly via the C runtime. However, it is also +useful for a few components that use the Genode API directly without any +libc. To accommodate such users of the VFS, we introduced the front-end +API at _os/vfs.h_ that covers a variety of current use cases. Currently, those +use cases revolve around the watching, reading, and parsing of files and +file-system structures - as performed by Sculpt's deployment mechanism. +Writing to files is not covered. + + +Improved file-watching support +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All pseudo files that use the VFS-internal 'Readonly_value_file_system' +utility have become able to deliver watch notifications. This change enables +VFS clients to respond to VFS-plugin events (think of terminal resize) +dynamically. + +Speaking of the *terminal VFS plugin*, the current release enhances the plugin +in several respects. First, it now delivers status information such as the +terminal size via pseudo files. Second, we equipped the VFS terminal file +system with the ability to detect user interrupts in the incoming data stream, +and propagate this information via the new pseudo file '.terminal/interrupts'. +Each time, the user presses control-c in the terminal, the value stored in +this pseudo file is increased. Thereby, a VFS client can watch this file to +get notified about the occurrences of user interrupts. + + +VFS plugin for emulating POSIX pipes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We added a new VFS plugin for emulating POSIX pipes. The new plugin creates +pipes between pairs of VFS handles. It replaces the deprecated libc_pipe +plugin. In contrast to the libc_pipe plugin, which was limited to pipes within +one component, the new VFS plugin can also be used to establish pipes between +different components by mounting the plugin at a shared VFS server. + + +C runtime with improved POSIX compatibility +=========================================== + +Within Genode, we used to think of POSIX as a legacy that is best avoided. +In fact, the foundational components of the framework do not depend on a +C runtime at all. However, higher up the software stack - at the latest when +3rd-party libraries enter the picture - a working C runtime is unavoidable. In +this statement, the term "working" is rather muddy though. Since we have never +fully embraced POSIX, we were content with cutting corners here and there. For +example, given Genode's architecture, supporting 'fork' and 'execve' seemed +totally out of question because those mechanisms would go against the grain of +Genode. + +However, our growing aspiration to bridge the gap between existing popular +applications and Genode made us re-evaluate our stance towards POSIX. +All technical criticism aside, POSIX is immensely useful because it is +a universally accepted stable interface. To dissolve friction between +Genode and popular application software, we have to satisfy the application's +expectations. This ignited a series of developments, in particular +the added support for 'fork' and 'execve' - of all things - in +[https://genode.org/documentation/release-notes/19.08#Consolidation_of_the_C_runtime_and_Noux - Genode 19.08], +which was nothing short of surprising, even to us. +The current release continues this line of development and brings the +following improvements. + + +Execve +------ + +The libc's 'execve' implementation got enhanced to evaluate the path of the +executable binary according to the information found on the VFS, in particular +by traversing directories and following symbolic links. This enables the libc +to execute files stored at sub directories of the file system. + +Furthermore, 'execve' received handling for *executing shell scripts* by +parsing the shebang marker at the beginning of the executable file. This way, +the 'execve' mechanism of the libc reaches parity with the feature set of the +Noux runtime that we traditionally used to host Unix software on top of +Genode. + + +Modification-time handling +-------------------------- + +By default, the libc uses the just added facility for updating the timestamp +of file-system nodes when closing a written-to file, which clears the path +towards using tools like 'make' that rely on file-modifications times. + +The libc's mechanism can be explicitly disabled by specifying +! +This is useful for applications that have no legitimate access to a time +source. + + +Emulation of 'ioctl' operations via pseudo files +------------------------------------------------ + +With the current release, we introduce a new scheme of handling ioctl +operations, which maps 'ioctl' calls to pseudo-file accesses, similar to how +the libc already maps socket calls to socket-fs operations. + +A device file can be accompanied with a (hidden) directory that is named after +the device file and hosts pseudo files for triggering the various device +operations. For example, for accessing a terminal, the directory structure +looks like this: + +! /dev/terminal +! /dev/.terminal/info +! /dev/.terminal/rows +! /dev/.terminal/columns +! /dev/.terminal/interrupts + +The 'info' file contains device information in XML format. The type of the XML +node corresponds to the device type. Whenever the libc receives a TIOCGWINSZ +ioctl for _/dev/terminal_, it reads the content of _/dev/.terminal/info_ to +obtain the terminal-size information. In this case, the _info_ file looks as +follows: + +! +! +! +! +! +! +! + +The second attribute decides whether to trigger a report update each time the +link state of an interface changes. By default, both attributes are set to +"false". + + +Device drivers +============== + +Platform driver on x86 +~~~~~~~~~~~~~~~~~~~~~~ + +During our enablement of Genode on a +[https://genodians.org/chelmuth/2019-10-21-sculpt-elitebook - recent notebook], +we spotted some PC platform shortcomings, we address with this release. Most +prominently we added support for +[https://en.wikipedia.org/wiki/PCI_configuration_space#Bus_enumeration - 64-bit PCI base address registers] +to the x86 platform driver. This allows the use of PCI devices that are +assigned to physical I/O-memory regions beyond 4 GiB by the boot firmware. + + +Wireless driver +~~~~~~~~~~~~~~~ + +We added the firmware images for the 5000 and 9000 series of Intel wireless +devices to the firmware white-list in the _wifi_drv_ component. Such devices +as 5100AGN, 5300AGN and 5350AGN as well as 9461, 9462 and 9560 should now be +usable on Genode. + + +Libraries and applications +########################## + +VirtualBox improvements +======================= + +The GUI handling of our VirtualBox port got improved to react on window-size +changes more instantly. The effect is that an interactive adjustment of the +window size, e.g., on Sculpt, becomes quickly visible to the user. Still, the +VM may take some time to adjust to the resolution change, which ultimately +depends on the behavior of the driver of the VirtualBox guest additions. + + +Updated 3rd-party software +========================== + +With the addition of the 64-bit ARM architecture (AARCH64) with the +[https://genode.org/documentation/release-notes/19.05#Broadened_CPU_architecture_support_and_updated_tool_chain - 19.05] +release, it became necessary to update the libraries the Genode tool chain +(gcc) depends on in order to support AARCH64 properly. This concerns the GNU +multi precision arithmetic library (gmp), which has been updated from version +4.3.2 to 6.1.2, as well as the libraries that depend on it: Multi precision +floating point (mpfr) and multi precision complex arithmetic (mpc). All those +old versions did not offer support for the AARCH64 architecture, which is a +requirement to make Genode self hosting. Targets for building binutils and GCC +within Genode for AARCH64 are in place, GNU make is in place, and even code +coverage (gcov) has been added. This work puts AARCH64 in line with other +supported CPU architectures and emphasizes our interest in the ARM 64-bit +architecture. + + +Platforms +######### + +Execution on bare hardware (base-hw) +==================================== + +With the previous release, Genode's base-hw kernel got extended to support the +ARMv8-A architecture in principle. The first hardware supported was the +Raspberry Pi 3 as well as the i.MX8 evaluation kit (EVK). But only a single +CPU-core was usable at that time. Now, we lifted this limitation. On both +boards, all four CPU-cores are available henceforth. + + +Removed components +################## + +The current release removes the following components: + +:gems/src/app/launcher: + + The graphical launcher remained unused for a few years now. It is not + suitable for systems as flexible as Sculpt OS. + +:os/src/app/cli_monitor: + + CLI monitor was a runtime environment with a custom command-line interface + to start and stop subsystems. It was part of the user interface of our + first take on a Genode-based desktop OS called + [https://genode.org/documentation/release-notes/15.11#Genode_as_desktop_OS - Turmvilla]. + + Nowadays, we use standard command-line tools like Vim to edit init + configurations dynamically, which is more flexible and - at the same time - + alleviates the need for a custom CLI. The CLI-monitor component was too + limited for use cases like Sculpt anyway. + + Along with the CLI monitor, we removed the ancient (and untested for long + time) _terminal_mux.run_ script, which was the only remaining user of the CLI + monitor. + +:fatfs_fs, rump_fs, and libc_fatfs plugin: + + The stand-alone file-system servers fatfs_fs and rump_fs as well as the + fatfs libc plugin have been superseded by the fatfs and rump VFS plugins. + The stand-alone servers can be replaced by using the VFS server plus the + corresponding VFS plugin as a drop-in replacement. + diff --git a/repos/base-fiasco/recipes/src/base-fiasco/hash b/repos/base-fiasco/recipes/src/base-fiasco/hash index 3e9c4f791..876054362 100644 --- a/repos/base-fiasco/recipes/src/base-fiasco/hash +++ b/repos/base-fiasco/recipes/src/base-fiasco/hash @@ -1 +1 @@ -2019-09-19 b0d371ca01b27c5b09fd55732681ab9e2cede5d5 +2019-11-25 c7e2a3eca5820b2304b4520d0fc831ede73691f2 diff --git a/repos/base-foc/recipes/src/base-foc-arndale/hash b/repos/base-foc/recipes/src/base-foc-arndale/hash index faa9a5c27..ffa7b331b 100644 --- a/repos/base-foc/recipes/src/base-foc-arndale/hash +++ b/repos/base-foc/recipes/src/base-foc-arndale/hash @@ -1 +1 @@ -2019-09-19 59410c274229c50f68d0fd65d52cc730a4b0f55b +2019-11-25 9a459c4fd8a907810d91041751affcf3e119fcb1 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 607f32647..675dcfaeb 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 @@ -2019-09-19 30eff00614afebb83d4be10a61d8d0f3b3fa8c33 +2019-11-25 d8ff4913b8aa117aef77a7918bc82808e38a4ee7 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 d5fd2a1b5..5034bab4e 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 @@ -2019-09-19 e2ce197e4ed2239ed2688c8bab5ea98f5e87d439 +2019-11-25 a750c8988106d5c26e46dcceb1f76bfd7bfa1457 diff --git a/repos/base-foc/recipes/src/base-foc-pbxa9/hash b/repos/base-foc/recipes/src/base-foc-pbxa9/hash index 52e452ea8..a895350ea 100644 --- a/repos/base-foc/recipes/src/base-foc-pbxa9/hash +++ b/repos/base-foc/recipes/src/base-foc-pbxa9/hash @@ -1 +1 @@ -2019-09-19 d3481851efe9091caf413496883a03875a298b90 +2019-11-25 0c0a26b6ddb0ee5261f0be30f229e9ce04b61eda diff --git a/repos/base-foc/recipes/src/base-foc-pc/hash b/repos/base-foc/recipes/src/base-foc-pc/hash index 6902e2730..57239fec1 100644 --- a/repos/base-foc/recipes/src/base-foc-pc/hash +++ b/repos/base-foc/recipes/src/base-foc-pc/hash @@ -1 +1 @@ -2019-09-19 c842719c606b0ec3eed05255761665737cecf208 +2019-11-25 bce6f0a8f1f46f8edf62ef2180dbfc949123432d diff --git a/repos/base-foc/recipes/src/base-foc-rpi3/hash b/repos/base-foc/recipes/src/base-foc-rpi3/hash index 32ca7e604..61bc6cab4 100644 --- a/repos/base-foc/recipes/src/base-foc-rpi3/hash +++ b/repos/base-foc/recipes/src/base-foc-rpi3/hash @@ -1 +1 @@ -2019-09-19 d3bf4e77c5f352efcf384b57be11668d6047ecf3 +2019-11-25 307d01e531dbbcd672463a4ea090f40bb399cae8 diff --git a/repos/base-foc/src/core/include/vm_session_component.h b/repos/base-foc/src/core/include/vm_session_component.h index 8757aa98f..b0408087c 100644 --- a/repos/base-foc/src/core/include/vm_session_component.h +++ b/repos/base-foc/src/core/include/vm_session_component.h @@ -108,7 +108,7 @@ class Genode::Vm_session_component void attach(Dataspace_capability, addr_t, Attach_attr) override; void attach_pic(addr_t) override { } void detach(addr_t, size_t) override; - void _create_vcpu(Thread_capability); + Vcpu_id _create_vcpu(Thread_capability); }; #endif /* _CORE__VM_SESSION_COMPONENT_H_ */ diff --git a/repos/base-foc/src/core/vm_session_component.cc b/repos/base-foc/src/core/vm_session_component.cc index 7e9cbe7fb..cc0dc5587 100644 --- a/repos/base-foc/src/core/vm_session_component.cc +++ b/repos/base-foc/src/core/vm_session_component.cc @@ -107,10 +107,12 @@ Vcpu::~Vcpu() _ram_alloc.free(_ds_cap); } -void Vm_session_component::_create_vcpu(Thread_capability cap) +Vm_session::Vcpu_id Vm_session_component::_create_vcpu(Thread_capability cap) { + Vcpu_id ret; + if (!cap.valid()) - return; + return ret; auto lambda = [&] (Cpu_thread_component *thread) { if (!thread) @@ -146,10 +148,11 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) } _vcpus.insert(vcpu); - _id_alloc++; + ret.id = _id_alloc++; }; _ep.apply(cap, lambda); + return ret; } Dataspace_capability Vm_session_component::_cpu_state(Vcpu_id const vcpu_id) diff --git a/repos/base-foc/src/lib/base/x86/vm_session.cc b/repos/base-foc/src/lib/base/x86/vm_session.cc index 5de6c8f69..5911003ae 100644 --- a/repos/base-foc/src/lib/base/x86/vm_session.cc +++ b/repos/base-foc/src/lib/base/x86/vm_session.cc @@ -50,7 +50,6 @@ static bool svm_np() { return svm_features() & (1U << 0); } struct Vcpu; static Genode::Registry > vcpus; -static unsigned vcpu_id = 0; struct Vcpu : Genode::Thread { @@ -202,7 +201,7 @@ struct Vcpu : Genode::Thread Semaphore _wake_up { 0 }; Semaphore &_handler_ready; Allocator &_alloc; - Vm_session_client::Vcpu_id _id; + Vm_session_client::Vcpu_id _id { Vm_session_client::Vcpu_id::INVALID }; addr_t _state { 0 }; addr_t _task { 0 }; enum Virt const _vm_type; @@ -1184,20 +1183,20 @@ struct Vcpu : Genode::Thread public: Vcpu(Env &env, Signal_context_capability &cap, - Semaphore &handler_ready, - Vm_session_client::Vcpu_id &id, enum Virt type, + Semaphore &handler_ready, enum Virt type, Allocator &alloc, Affinity::Location location) : Thread(env, "vcpu_thread", STACK_SIZE, location, Weight(), env.cpu()), _signal(cap), _handler_ready(handler_ready), _alloc(alloc), - _id(id), _vm_type(type) + _vm_type(type) { } Allocator &allocator() const { return _alloc; } bool match(Vm_session_client::Vcpu_id id) { return id.id == _id.id; } - Genode::Vm_session_client::Vcpu_id id() const { return _id; } + Genode::Vm_session_client::Vcpu_id id() const { return _id; } + void id(Genode::Vm_session_client::Vcpu_id id) { _id = id; } void assign_ds_state(Region_map &rm, Dataspace_capability cap) { @@ -1266,12 +1265,10 @@ Vm_session_client::Vcpu_id Vm_session_client::create_vcpu(Allocator &alloc, Env &env, Vm_handler_base &handler) { - Vm_session_client::Vcpu_id id = { vcpu_id }; - enum Virt vm_type = virt_type(env); if (vm_type == Virt::UNKNOWN) { Genode::error("unsupported hardware virtualisation"); - return id; + return Vm_session::Vcpu_id(); } Thread * ep = reinterpret_cast(&handler._rpc_ep); @@ -1279,17 +1276,17 @@ Vm_session_client::create_vcpu(Allocator &alloc, Env &env, /* create thread that switches modes between thread/cpu */ Vcpu * vcpu = new (alloc) Registered(vcpus, env, handler._cap, - handler._done, id, vm_type, + handler._done, vm_type, alloc, location); try { /* now it gets actually valid - vcpu->cap() becomes valid */ vcpu->start(); - call(handler._cap, vcpu->id()); - /* instruct core to let it become a vCPU */ - call(vcpu->cap()); + vcpu->id(call(vcpu->cap())); + + call(handler._cap, vcpu->id()); vcpu->assign_ds_state(env.rm(), call(vcpu->id())); } catch (...) { @@ -1299,9 +1296,7 @@ Vm_session_client::create_vcpu(Allocator &alloc, Env &env, destroy(alloc, vcpu); throw; } - - vcpu_id ++; - return id; + return vcpu->id(); } void Vm_session_client::run(Vcpu_id vcpu_id) diff --git a/repos/base-hw/include/spec/arm_64/cpu/vm_state_virtualization.h b/repos/base-hw/include/spec/arm_64/cpu/vm_state_virtualization.h new file mode 100644 index 000000000..ef0a8ac14 --- /dev/null +++ b/repos/base-hw/include/spec/arm_64/cpu/vm_state_virtualization.h @@ -0,0 +1,109 @@ +/* + * \brief CPU, PIC, and timer context of a virtual machine + * \author Stefan Kalkowski + * \date 2015-02-10 + */ + +/* + * Copyright (C) 2015-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__SPEC__ARM_64__CPU__VM_STATE_VIRTUALIZATION_H_ +#define _INCLUDE__SPEC__ARM_64__CPU__VM_STATE_VIRTUALIZATION_H_ + +/* Genode includes */ +#include + +namespace Genode +{ + /** + * CPU context of a virtual machine + */ + struct Vm_state; + + using uint128_t = __uint128_t; +} + +struct Genode::Vm_state : Genode::Cpu_state +{ + Genode::uint64_t pstate { 0 }; + Genode::uint64_t exception_type { 0 }; + Genode::uint64_t esr_el2 { 0 }; + + /** Fpu registers **/ + Genode::uint128_t q[32] { 0 }; + Genode::uint32_t fpcr { 0 }; + Genode::uint32_t fpsr { 0 }; + + Genode::uint64_t elr_el1 { 0 }; + Genode::uint64_t sp_el1 { 0 }; + Genode::uint32_t spsr_el1 { 0 }; + Genode::uint32_t esr_el1 { 0 }; + + Genode::uint64_t sctlr_el1 { 0 }; + Genode::uint64_t actlr_el1 { 0 }; + Genode::uint64_t vbar_el1 { 0 }; + Genode::uint32_t cpacr_el1 { 0 }; + Genode::uint32_t afsr0_el1 { 0 }; + Genode::uint32_t afsr1_el1 { 0 }; + Genode::uint32_t contextidr_el1 { 0 }; + + Genode::uint64_t ttbr0_el1 { 0 }; + Genode::uint64_t ttbr1_el1 { 0 }; + Genode::uint64_t tcr_el1 { 0 }; + Genode::uint64_t mair_el1 { 0 }; + Genode::uint64_t amair_el1 { 0 }; + Genode::uint64_t far_el1 { 0 }; + Genode::uint64_t par_el1 { 0 }; + + Genode::uint64_t tpidrro_el0 { 0 }; + Genode::uint64_t tpidr_el0 { 0 }; + Genode::uint64_t tpidr_el1 { 0 }; + + Genode::uint64_t vmpidr_el2 { 0 }; + + Genode::uint64_t far_el2 { 0 }; + Genode::uint64_t hpfar_el2 { 0 }; + + /** + * Timer related registers + */ + struct Timer { + Genode::uint64_t offset { 0 }; + Genode::uint64_t compare { 0 }; + Genode::uint32_t control { 0 }; + Genode::uint32_t kcontrol { 0 }; + bool irq { false }; + } timer {}; + + /** + * Interrupt related values + */ + struct Pic + { + unsigned last_irq { 1023 }; + unsigned virtual_irq { 1023 }; + } irqs {}; + + /************************** + ** Platform information ** + **************************/ + + Genode::uint64_t id_aa64isar0_el1 { 0 }; + Genode::uint64_t id_aa64isar1_el1 { 0 }; + Genode::uint64_t id_aa64mmfr0_el1 { 0 }; + Genode::uint64_t id_aa64mmfr1_el1 { 0 }; + Genode::uint64_t id_aa64mmfr2_el1 { 0 }; + Genode::uint64_t id_aa64pfr0_el1 { 0 }; + Genode::uint64_t id_aa64pfr1_el1 { 0 }; + Genode::uint64_t id_aa64zfr0_el1 { 0 }; + + Genode::uint32_t ccsidr_inst_el1[7] { 0 }; + Genode::uint32_t ccsidr_data_el1[7] { 0 }; + Genode::uint64_t clidr_el1 { 0 }; +}; + +#endif /* _INCLUDE__SPEC__ARM_64__CPU__VM_STATE_VIRTUALIZATION_H_ */ diff --git a/repos/base-hw/lib/mk/bootstrap-hw.inc b/repos/base-hw/lib/mk/bootstrap-hw.inc index d570a3cdd..f5cc198bb 100644 --- a/repos/base-hw/lib/mk/bootstrap-hw.inc +++ b/repos/base-hw/lib/mk/bootstrap-hw.inc @@ -17,6 +17,7 @@ SRC_CC += lib/base/heap.cc SRC_CC += lib/base/registry.cc SRC_CC += lib/base/log.cc SRC_CC += lib/base/output.cc +SRC_CC += lib/base/raw_output.cc SRC_CC += lib/base/slab.cc SRC_CC += lib/base/sleep.cc SRC_CC += lib/base/sliced_heap.cc diff --git a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-arndale.mk b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-arndale.mk index cec0957f3..81304cc35 100644 --- a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-arndale.mk +++ b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-arndale.mk @@ -6,16 +6,16 @@ # add include paths INC_DIR += $(REP_DIR)/src/core/spec/arndale -INC_DIR += $(REP_DIR)/src/core/spec/arm_v7/virtualization +INC_DIR += $(REP_DIR)/src/core/spec/arm/virtualization # add C++ sources SRC_CC += kernel/vm_thread_on.cc SRC_CC += spec/arm/gicv2.cc SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc -SRC_CC += spec/arm_v7/virtualization/platform_services.cc -SRC_CC += spec/arm_v7/virtualization/vm_session_component.cc -SRC_CC += spec/arm_v7/vm_session_component.cc +SRC_CC += spec/arm/virtualization/platform_services.cc +SRC_CC += spec/arm/virtualization/vm_session_component.cc SRC_CC += vm_session_common.cc +SRC_CC += vm_session_component.cc # add assembly sources SRC_S += spec/arm_v7/virtualization/exception_vector.s diff --git a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx53_qsb_tz.mk b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx53_qsb_tz.mk index 734243c2b..c738b6b82 100644 --- a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx53_qsb_tz.mk +++ b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx53_qsb_tz.mk @@ -5,7 +5,8 @@ SRC_CC += kernel/vm_thread_on.cc SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc SRC_CC += spec/arm_v7/trustzone/platform_services.cc SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc -SRC_CC += spec/arm_v7/vm_session_component.cc +SRC_CC += vm_session_common.cc +SRC_CC += vm_session_component.cc SRC_S += spec/arm_v7/trustzone/exception_vector.s diff --git a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx7d_sabre.mk b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx7d_sabre.mk index 838137de0..47dfa9439 100644 --- a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx7d_sabre.mk +++ b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-imx7d_sabre.mk @@ -6,17 +6,18 @@ # add include paths INC_DIR += $(REP_DIR)/src/core/spec/imx7d_sabre -INC_DIR += $(REP_DIR)/src/core/spec/arm_v7/virtualization +INC_DIR += $(REP_DIR)/src/core/spec/arm/virtualization # add C++ sources SRC_CC += kernel/vm_thread_on.cc SRC_CC += spec/arm/generic_timer.cc SRC_CC += spec/arm/gicv2.cc SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc -SRC_CC += spec/arm_v7/virtualization/platform_services.cc -SRC_CC += spec/arm_v7/virtualization/vm_session_component.cc -SRC_CC += spec/arm_v7/vm_session_component.cc +SRC_CC += spec/arm/virtualization/gicv2.cc +SRC_CC += spec/arm/virtualization/platform_services.cc +SRC_CC += spec/arm/virtualization/vm_session_component.cc SRC_CC += vm_session_common.cc +SRC_CC += vm_session_component.cc # add assembly sources SRC_S += spec/arm_v7/virtualization/exception_vector.s diff --git a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-usb_armory.mk b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-usb_armory.mk index 0a86704d2..fd18a9476 100644 --- a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-usb_armory.mk +++ b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-usb_armory.mk @@ -17,7 +17,8 @@ SRC_CC += spec/arm/imx_tzic.cc SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc SRC_CC += spec/arm_v7/trustzone/platform_services.cc SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc -SRC_CC += spec/arm_v7/vm_session_component.cc +SRC_CC += vm_session_common.cc +SRC_CC += vm_session_component.cc # add assembly sources SRC_S += spec/arm_v7/trustzone/exception_vector.s diff --git a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-imx8q_evk.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-imx8q_evk.mk index 1df46954b..5767adc50 100644 --- a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-imx8q_evk.mk +++ b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-imx8q_evk.mk @@ -7,6 +7,8 @@ SRC_CC += lib/base/arm_64/kernel/interface.cc SRC_CC += spec/64bit/memory_map.cc SRC_S += bootstrap/spec/arm_64/crt0.s +NR_OF_CPUS = 4 + vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk index 788be2348..cc1c4f4b0 100644 --- a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk +++ b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk @@ -8,4 +8,6 @@ SRC_S += bootstrap/spec/arm_64/crt0.s vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw +NR_OF_CPUS = 4 + include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-imx8q_evk.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-imx8q_evk.mk index 626d7cfde..48df73c8e 100644 --- a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-imx8q_evk.mk +++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-imx8q_evk.mk @@ -1,24 +1,32 @@ INC_DIR += $(REP_DIR)/src/core/spec/imx8q_evk INC_DIR += $(REP_DIR)/src/core/spec/arm_v8 +INC_DIR += $(REP_DIR)/src/core/spec/arm/virtualization # add C++ sources -SRC_CC += kernel/cpu_up.cc -SRC_CC += kernel/lock.cc -SRC_CC += kernel/vm_thread_off.cc -SRC_CC += platform_services.cc +SRC_CC += kernel/cpu_mp.cc +SRC_CC += kernel/vm_thread_on.cc SRC_CC += spec/64bit/memory_map.cc SRC_CC += spec/arm/generic_timer.cc SRC_CC += spec/arm/gicv3.cc +SRC_CC += spec/arm/kernel/lock.cc SRC_CC += spec/arm/platform_support.cc SRC_CC += spec/arm_v8/cpu.cc SRC_CC += spec/arm_v8/kernel/cpu.cc SRC_CC += spec/arm_v8/kernel/thread.cc +SRC_CC += spec/arm_v8/virtualization/kernel/vm.cc +SRC_CC += spec/arm/virtualization/platform_services.cc +SRC_CC += spec/arm/virtualization/vm_session_component.cc +SRC_CC += vm_session_common.cc +SRC_CC += vm_session_component.cc #add assembly sources SRC_S += spec/arm_v8/exception_vector.s SRC_S += spec/arm_v8/crt0.s +SRC_S += spec/arm_v8/virtualization/exception_vector.s vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw +NR_OF_CPUS = 4 + # include less specific configuration include $(REP_DIR)/lib/mk/core-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk index cc0dd41dd..87a026754 100644 --- a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk +++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk @@ -2,17 +2,17 @@ INC_DIR += $(REP_DIR)/src/core/spec/rpi3 INC_DIR += $(REP_DIR)/src/core/spec/arm_v8 # add C++ sources -SRC_CC += platform_services.cc +SRC_CC += kernel/cpu_mp.cc SRC_CC += kernel/vm_thread_off.cc -SRC_CC += kernel/cpu_up.cc -SRC_CC += kernel/lock.cc -SRC_CC += spec/arm_v8/cpu.cc -SRC_CC += spec/arm_v8/kernel/thread.cc -SRC_CC += spec/arm_v8/kernel/cpu.cc -SRC_CC += spec/arm/platform_support.cc +SRC_CC += platform_services.cc +SRC_CC += spec/64bit/memory_map.cc SRC_CC += spec/arm/bcm2837_pic.cc SRC_CC += spec/arm/generic_timer.cc -SRC_CC += spec/64bit/memory_map.cc +SRC_CC += spec/arm/kernel/lock.cc +SRC_CC += spec/arm/platform_support.cc +SRC_CC += spec/arm_v8/cpu.cc +SRC_CC += spec/arm_v8/kernel/cpu.cc +SRC_CC += spec/arm_v8/kernel/thread.cc #add assembly sources SRC_S += spec/arm_v8/exception_vector.s @@ -20,5 +20,7 @@ SRC_S += spec/arm_v8/crt0.s vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw +NR_OF_CPUS = 4 + # include less specific configuration include $(REP_DIR)/lib/mk/core-hw.inc diff --git a/repos/base-hw/lib/mk/spec/x86_64/core-hw-muen.mk b/repos/base-hw/lib/mk/spec/x86_64/core-hw-muen.mk index 1eb9c661d..d4c7550a4 100644 --- a/repos/base-hw/lib/mk/spec/x86_64/core-hw-muen.mk +++ b/repos/base-hw/lib/mk/spec/x86_64/core-hw-muen.mk @@ -35,7 +35,10 @@ SRC_CC += spec/x86_64/muen/platform_services.cc SRC_CC += spec/x86_64/muen/platform_support.cc SRC_CC += spec/x86_64/muen/sinfo_instance.cc SRC_CC += spec/x86_64/muen/timer.cc +SRC_CC += spec/x86_64/muen/vm_session_component.cc SRC_CC += spec/x86_64/platform_support_common.cc +SRC_CC += vm_session_common.cc +SRC_CC += vm_session_component.cc SRC_CC += spec/64bit/memory_map.cc diff --git a/repos/base-hw/recipes/api/base-hw/hash b/repos/base-hw/recipes/api/base-hw/hash index 520577419..f9c697e11 100644 --- a/repos/base-hw/recipes/api/base-hw/hash +++ b/repos/base-hw/recipes/api/base-hw/hash @@ -1 +1 @@ -2019-07-08 abc6d82ca4a240319850c788f29cde2655eab1d1 +2019-11-25 6593319a4dec74af9dc15554139e4343ef4312a9 diff --git a/repos/base-hw/recipes/src/base-hw-arndale/hash b/repos/base-hw/recipes/src/base-hw-arndale/hash index 5609c4c3b..f24238a59 100644 --- a/repos/base-hw/recipes/src/base-hw-arndale/hash +++ b/repos/base-hw/recipes/src/base-hw-arndale/hash @@ -1 +1 @@ -2019-09-19 1c57558662fd8474e71ac732af797c3585322017 +2019-11-25 c60d834ce54a46a946c36249784e734e06274d97 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 891f5d101..7f51d145d 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 @@ -2019-09-19 47d633f15a78dba4ce4a0ece9fd301ec59476d18 +2019-11-25 e9232754efd81c14aa65d4852d276852f591f3e5 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 3d1028138..e4bdcb674 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 @@ -2019-09-19 a922228b96330109da7ddb61450a385ef485a93b +2019-11-25 2ab0250606cee0da4f08ac08f7f33c743f32c88c 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 6b28353ab..85a9f80c2 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 @@ -2019-09-19 d4514d968b7e55b42247e0231ad95bd77e92d253 +2019-11-25 7780e0570ac0277d678dee76a579a9d9f9a1a776 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 ebebe01f0..655aac8c9 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 @@ -2019-09-19 742a48fd23606d2b6763b2f4f2ae4a199e3d6e56 +2019-11-25 2dee497b7892f706236fdbfabae53bbd4e62463b diff --git a/repos/base-hw/recipes/src/base-hw-imx8q_evk/hash b/repos/base-hw/recipes/src/base-hw-imx8q_evk/hash index 6136b8d03..4a0012d49 100644 --- a/repos/base-hw/recipes/src/base-hw-imx8q_evk/hash +++ b/repos/base-hw/recipes/src/base-hw-imx8q_evk/hash @@ -1 +1 @@ -2019-09-19 16b8071d8d3eee712181720ddf018c26e72f0f56 +2019-11-25 efd164d66086a998484d7413c5416e3aa128e560 diff --git a/repos/base-hw/recipes/src/base-hw-muen/hash b/repos/base-hw/recipes/src/base-hw-muen/hash index b9fd3d56d..b4805548f 100644 --- a/repos/base-hw/recipes/src/base-hw-muen/hash +++ b/repos/base-hw/recipes/src/base-hw-muen/hash @@ -1 +1 @@ -2019-09-19 b1342fe0f4a662c502b296b11d2524d64d2a482e +2019-11-25 25f54b8744778f0860ac2a93c11ee6b1cd16d0c9 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 845a1c61e..26192f07e 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 @@ -2019-09-19 f5acd9b2761cb465a885ecff6ddb436bacff0788 +2019-11-25 ceeaef3ad58fc5b88cf4686aa42f50fd254063e3 diff --git a/repos/base-hw/recipes/src/base-hw-odroid_xu/hash b/repos/base-hw/recipes/src/base-hw-odroid_xu/hash index df68ddf98..f0f5ba688 100644 --- a/repos/base-hw/recipes/src/base-hw-odroid_xu/hash +++ b/repos/base-hw/recipes/src/base-hw-odroid_xu/hash @@ -1 +1 @@ -2019-09-19 b078e13e4c53a1b0db0bd0336d64b3abf50e88e3 +2019-11-25 aee36abdef456d2d1c6bba023f16cbca08eceabe diff --git a/repos/base-hw/recipes/src/base-hw-panda/hash b/repos/base-hw/recipes/src/base-hw-panda/hash index 0c4303055..c28cd2b23 100644 --- a/repos/base-hw/recipes/src/base-hw-panda/hash +++ b/repos/base-hw/recipes/src/base-hw-panda/hash @@ -1 +1 @@ -2019-09-19 cdaaf832a7be3789c06a88888b11fafe6044b6ac +2019-11-25 ede7ce464c3f4b8486fd93413088a1b83fbf796a diff --git a/repos/base-hw/recipes/src/base-hw-pbxa9/hash b/repos/base-hw/recipes/src/base-hw-pbxa9/hash index 72e5de386..dc233818c 100644 --- a/repos/base-hw/recipes/src/base-hw-pbxa9/hash +++ b/repos/base-hw/recipes/src/base-hw-pbxa9/hash @@ -1 +1 @@ -2019-09-19 2f375cd8feabedf1fcee6228faef30a8165e9f5b +2019-11-25 2bea4132b9ab877e802cfb81ad3c62bda0c2bc50 diff --git a/repos/base-hw/recipes/src/base-hw-pc/hash b/repos/base-hw/recipes/src/base-hw-pc/hash index b2d9febfc..c9662b46f 100644 --- a/repos/base-hw/recipes/src/base-hw-pc/hash +++ b/repos/base-hw/recipes/src/base-hw-pc/hash @@ -1 +1 @@ -2019-09-19 e66163f4025a92d475058a1ab1aeb911dd0c7540 +2019-11-25 807893480c51457cad7e00e1275eff9749c91c68 diff --git a/repos/base-hw/recipes/src/base-hw-rpi/hash b/repos/base-hw/recipes/src/base-hw-rpi/hash index 5f5c5058e..5f28bdb45 100644 --- a/repos/base-hw/recipes/src/base-hw-rpi/hash +++ b/repos/base-hw/recipes/src/base-hw-rpi/hash @@ -1 +1 @@ -2019-09-19 fdbdc1b821fdf215203eae20dd1d5482f60f2685 +2019-11-25 6a3f12cd6429f5d5bcf617cdd3ea9d345e8614ad diff --git a/repos/base-hw/recipes/src/base-hw-rpi3/hash b/repos/base-hw/recipes/src/base-hw-rpi3/hash index b756f921b..97d101846 100644 --- a/repos/base-hw/recipes/src/base-hw-rpi3/hash +++ b/repos/base-hw/recipes/src/base-hw-rpi3/hash @@ -1 +1 @@ -2019-09-19 f2def44f31f4491e5ad1e13e3d980608e647fb91 +2019-11-25 a318db7d985930e3f58ce3bccce290bc13aaedab diff --git a/repos/base-hw/recipes/src/base-hw-zynq_qemu/hash b/repos/base-hw/recipes/src/base-hw-zynq_qemu/hash index ae88dc0c2..7534f450e 100644 --- a/repos/base-hw/recipes/src/base-hw-zynq_qemu/hash +++ b/repos/base-hw/recipes/src/base-hw-zynq_qemu/hash @@ -1 +1 @@ -2019-09-19 30958dd0b796aed5ea5a80d43fc660fa230eed34 +2019-11-25 75f1b89ea50fdfd0a69c33dee4ba1e120d49fad5 diff --git a/repos/base-hw/src/bootstrap/log.cc b/repos/base-hw/src/bootstrap/log.cc index 2f77fa32a..6183b08c5 100644 --- a/repos/base-hw/src/bootstrap/log.cc +++ b/repos/base-hw/src/bootstrap/log.cc @@ -19,6 +19,7 @@ /* base-internal includes */ #include #include +#include #include #include @@ -57,3 +58,5 @@ struct Buffer Genode::Log &Genode::Log::log() { return unmanaged_singleton()->log; } + +void Genode::raw_write_string(char const *str) { log(str); } diff --git a/repos/base-hw/src/bootstrap/platform.h b/repos/base-hw/src/bootstrap/platform.h index ea7bee31a..336442bf4 100644 --- a/repos/base-hw/src/bootstrap/platform.h +++ b/repos/base-hw/src/bootstrap/platform.h @@ -47,7 +47,6 @@ class Bootstrap::Platform Mmio_space const core_mmio; unsigned cpus { NR_OF_CPUS }; ::Board::Boot_info info { }; - ::Board::Pic pic { }; Board(); }; diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_mmu.cc b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_mmu.cc index e7fdddd97..0bd885b1b 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_mmu.cc +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_mmu.cc @@ -15,6 +15,7 @@ unsigned Bootstrap::Platform::enable_mmu() { + ::Board::Pic pic { }; ::Board::Cpu::Sctlr::init(); ::Board::Cpu::enable_mmu_and_caches((addr_t)core_pd->table_base); diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc index e7800f99f..de148528a 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc @@ -118,7 +118,7 @@ unsigned Bootstrap::Platform::enable_mmu() Actlr::disable_smp(); /* locally initialize interrupt controller */ - board.pic.init_cpu_local(); + ::Board::Pic pic { }; Cpu::invalidate_data_cache(); data_cache_invalidated.inc(); diff --git a/repos/base-hw/src/bootstrap/spec/arm/gicv2.cc b/repos/base-hw/src/bootstrap/spec/arm/gicv2.cc index 7610e3e57..026a9a945 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/gicv2.cc +++ b/repos/base-hw/src/bootstrap/spec/arm/gicv2.cc @@ -13,8 +13,41 @@ #include -void Board::Pic::init_cpu_local() +Hw::Gicv2::Gicv2() +: _distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE), + _cpui (Board::Cpu_mmio::IRQ_CONTROLLER_CPU_BASE), + _last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)), + _max_irq(_distr.max_irq()) { + static bool distributor_initialized = false; + + if (!distributor_initialized) { + distributor_initialized = true; + + /* disable device */ + _distr.write(0); + + /* configure every shared peripheral interrupt */ + for (unsigned i = min_spi; i <= _max_irq; i++) { + if (Board::NON_SECURE) { + _distr.write(1, i); + } + _distr.write(0, i); + _distr.write(0, i); + _distr.write(1, i); + } + + /* enable device */ + Distributor::Ctlr::access_t v = 0; + if (Board::NON_SECURE) { + Distributor::Ctlr::Enable_grp0::set(v, 1); + Distributor::Ctlr::Enable_grp1::set(v, 1); + } else { + Distributor::Ctlr::Enable::set(v, 1); + } + _distr.write(v); + } + if (Board::NON_SECURE) { _cpui.write(0); @@ -40,34 +73,3 @@ void Board::Pic::init_cpu_local() } _cpui.write(v); } - - -Hw::Gicv2::Gicv2() -: _distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE), - _cpui (Board::Cpu_mmio::IRQ_CONTROLLER_CPU_BASE), - _last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)), - _max_irq(_distr.max_irq()) -{ - /* disable device */ - _distr.write(0); - - /* configure every shared peripheral interrupt */ - for (unsigned i = min_spi; i <= _max_irq; i++) { - if (Board::NON_SECURE) { - _distr.write(1, i); - } - _distr.write(0, i); - _distr.write(0, i); - _distr.write(1, i); - } - - /* enable device */ - Distributor::Ctlr::access_t v = 0; - if (Board::NON_SECURE) { - Distributor::Ctlr::Enable_grp0::set(v, 1); - Distributor::Ctlr::Enable_grp1::set(v, 1); - } else { - Distributor::Ctlr::Enable::set(v, 1); - } - _distr.write(v); -} diff --git a/repos/base-hw/src/bootstrap/spec/arm/gicv2.h b/repos/base-hw/src/bootstrap/spec/arm/gicv2.h deleted file mode 100644 index d9c19b692..000000000 --- a/repos/base-hw/src/bootstrap/spec/arm/gicv2.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * \brief Interrupt controller definitions for ARM - * \author Stefan Kalkowski - * \date 2017-02-22 - */ - -/* - * Copyright (C) 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 _SRC__BOOTSTRAP__SPEC__ARM__GICV2_H_ -#define _SRC__BOOTSTRAP__SPEC__ARM__GICV2_H_ - -#include - -namespace Board { struct Pic; } - -struct Board::Pic : Hw::Gicv2 -{ - void init_cpu_local(); -}; - -#endif /* _SRC__BOOTSTRAP__SPEC__ARM__GICV2_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc b/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc index f0e24e7cc..f8d9536e0 100644 --- a/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc +++ b/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc @@ -11,10 +11,12 @@ * under the terms of the GNU Affero General Public License version 3. */ +#include #include using Board::Cpu; +extern "C" void * _crt0_enable_fpu; static inline void prepare_non_secure_world() { @@ -56,11 +58,54 @@ static inline void prepare_non_secure_world() } -static inline void prepare_hypervisor() +static inline void prepare_hypervisor(Cpu::Ttbr::access_t const ttbr) { - Cpu::Hcr::access_t scr = Cpu::Hcr::read(); - Cpu::Hcr::Rw::set(scr, 1); /* exec in aarch64 */ - Cpu::Hcr::write(scr); + using namespace Hw::Mm; + + /* forbid trace access */ + Cpu::Cptr_el2::access_t cptr = Cpu::Cptr_el2::read(); + Cpu::Cptr_el2::Tta::set(cptr, 1); + Cpu::Cptr_el2::write(cptr); + + /* allow physical counter/timer access without trapping */ + Cpu::Cnthctl_el2::write(0b111); + + /* forbid any 32bit access to coprocessor/sysregs */ + Cpu::Hstr_el2::write(0xffff); + + Cpu::Hcr_el2::access_t hcr = Cpu::Hcr_el2::read(); + Cpu::Hcr_el2::Rw::set(hcr, 1); /* exec in aarch64 */ + Cpu::Hcr_el2::write(hcr); + + /* set hypervisor exception vector */ + Cpu::Vbar_el2::write(el2_addr(hypervisor_exception_vector().base)); + Genode::addr_t const stack_el2 = el2_addr(hypervisor_stack().base + + hypervisor_stack().size); + + /* set hypervisor's translation table */ + Cpu::Ttbr0_el2::write(ttbr); + + Cpu::Tcr_el2::access_t tcr_el2 = 0; + Cpu::Tcr_el2::T0sz::set(tcr_el2, 25); + Cpu::Tcr_el2::Irgn0::set(tcr_el2, 1); + Cpu::Tcr_el2::Orgn0::set(tcr_el2, 1); + Cpu::Tcr_el2::Sh0::set(tcr_el2, 0b10); + + /* prepare MMU usage by hypervisor code */ + Cpu::Tcr_el2::write(tcr_el2); + + /* set memory attributes in indirection register */ + Cpu::Mair::access_t mair = 0; + Cpu::Mair::Attr0::set(mair, Cpu::Mair::NORMAL_MEMORY_UNCACHED); + Cpu::Mair::Attr1::set(mair, Cpu::Mair::DEVICE_MEMORY); + Cpu::Mair::Attr2::set(mair, Cpu::Mair::NORMAL_MEMORY_CACHED); + Cpu::Mair::Attr3::set(mair, Cpu::Mair::DEVICE_MEMORY); + Cpu::Mair_el2::write(mair); + + Cpu::Vtcr_el2::access_t vtcr = 0; + Cpu::Vtcr_el2::T0sz::set(vtcr, 25); + Cpu::Vtcr_el2::Sl0::set(vtcr, 1); /* set to starting level 1 */ + Cpu::Vtcr_el2::write(vtcr); Cpu::Spsr::access_t pstate = 0; Cpu::Spsr::Sp::set(pstate, 1); /* select non-el0 stack pointer */ @@ -71,27 +116,52 @@ static inline void prepare_hypervisor() Cpu::Spsr::D::set(pstate, 1); Cpu::Spsr_el2::write(pstate); + Cpu::Sctlr::access_t sctlr = Cpu::Sctlr_el2::read(); + Cpu::Sctlr::M::set(sctlr, 1); + Cpu::Sctlr::A::set(sctlr, 0); + Cpu::Sctlr::C::set(sctlr, 1); + Cpu::Sctlr::Sa::set(sctlr, 0); + Cpu::Sctlr::I::set(sctlr, 1); + Cpu::Sctlr::Wxn::set(sctlr, 0); + Cpu::Sctlr_el2::write(sctlr); + asm volatile("mov x0, sp \n" "msr sp_el1, x0 \n" "adr x0, 1f \n" "msr elr_el2, x0 \n" + "mov sp, %0 \n" "eret \n" - "1:"); + "1:": : "r"(stack_el2): "x0"); } unsigned Bootstrap::Platform::enable_mmu() { + static volatile bool primary_cpu = true; + bool primary = primary_cpu; + if (primary) primary_cpu = false; + + Cpu::Ttbr::access_t ttbr = + Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base); + while (Cpu::current_privilege_level() > Cpu::Current_el::EL1) { - if (Cpu::current_privilege_level() == Cpu::Current_el::EL3) + if (Cpu::current_privilege_level() == Cpu::Current_el::EL3) { prepare_non_secure_world(); - else - prepare_hypervisor(); + } else { + ::Board::Pic pic __attribute__((unused)) {}; + prepare_hypervisor(ttbr); + } } + /* primary cpu wakes up all others */ + if (primary && NR_OF_CPUS > 1) Cpu::wake_up_all_cpus(&_crt0_enable_fpu); + /* enable performance counter for user-land */ Cpu::Pmuserenr_el0::write(0b1111); + /* enable user-level access of physical/virtual counter */ + Cpu::Cntkctl_el1::write(0b11); + Cpu::Vbar_el1::write(Hw::Mm::supervisor_exception_vector().base); /* set memory attributes in indirection register */ @@ -100,9 +170,8 @@ unsigned Bootstrap::Platform::enable_mmu() Cpu::Mair::Attr1::set(mair, Cpu::Mair::DEVICE_MEMORY); Cpu::Mair::Attr2::set(mair, Cpu::Mair::NORMAL_MEMORY_CACHED); Cpu::Mair::Attr3::set(mair, Cpu::Mair::DEVICE_MEMORY); - Cpu::Mair::write(mair); + Cpu::Mair_el1::write(mair); - Cpu::Ttbr::access_t ttbr = Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base); Cpu::Ttbr0_el1::write(ttbr); Cpu::Ttbr1_el1::write(ttbr); @@ -119,13 +188,14 @@ unsigned Bootstrap::Platform::enable_mmu() Cpu::Tcr_el1::As::set(tcr, 1); Cpu::Tcr_el1::write(tcr); - Cpu::Sctlr_el1::access_t sctlr = Cpu::Sctlr_el1::read(); - Cpu::Sctlr_el1::C::set(sctlr, 1); - Cpu::Sctlr_el1::I::set(sctlr, 1); - Cpu::Sctlr_el1::A::set(sctlr, 0); - Cpu::Sctlr_el1::M::set(sctlr, 1); - Cpu::Sctlr_el1::Sa0::set(sctlr, 1); - Cpu::Sctlr_el1::Sa::set(sctlr, 0); + Cpu::Sctlr::access_t sctlr = Cpu::Sctlr_el1::read(); + Cpu::Sctlr::C::set(sctlr, 1); + Cpu::Sctlr::I::set(sctlr, 1); + Cpu::Sctlr::A::set(sctlr, 0); + Cpu::Sctlr::M::set(sctlr, 1); + Cpu::Sctlr::Sa0::set(sctlr, 1); + Cpu::Sctlr::Sa::set(sctlr, 0); + Cpu::Sctlr::Uct::set(sctlr, 1); Cpu::Sctlr_el1::write(sctlr); return 0; diff --git a/repos/base-hw/src/bootstrap/spec/arm_64/crt0.s b/repos/base-hw/src/bootstrap/spec/arm_64/crt0.s index 98de01e67..ce046ce0a 100644 --- a/repos/base-hw/src/bootstrap/spec/arm_64/crt0.s +++ b/repos/base-hw/src/bootstrap/spec/arm_64/crt0.s @@ -23,8 +23,19 @@ mrs x0, mpidr_el1 and x0, x0, #0b11111111 cbz x0, _crt0_fill_bss_zero + + /** + * Hack for Qemu, which starts all cpus at once + */ + 1: + ldr x1, =_crt0_qemu_start_secondary_cpus + ldr w1, [x1] + cbnz w1, _crt0_enable_fpu wfe - b _start + b 1b + .global _crt0_qemu_start_secondary_cpus + _crt0_qemu_start_secondary_cpus: + .long 0 /*************************** @@ -32,12 +43,12 @@ ***************************/ _crt0_fill_bss_zero: - ldr x0, =_bss_start - ldr x1, =_bss_end + ldr x1, =_bss_start + ldr x2, =_bss_end 1: - cmp x1, x0 + cmp x2, x1 b.eq _crt0_enable_fpu - str xzr, [x0], #8 + str xzr, [x1], #8 b 1b @@ -45,20 +56,30 @@ ** Enable FPU ** ****************/ + .global _crt0_enable_fpu _crt0_enable_fpu: - mov x0, #0b11 - lsl x0, x0, #20 - msr cpacr_el1, x0 + mov x1, #0b11 + lsl x1, x1, #20 + msr cpacr_el1, x1 /********************** ** Initialize stack ** **********************/ - ldr x0, =_crt0_start_stack - mov sp, x0 + .set STACK_SIZE, 0x2000 + + ldr x1, =_crt0_start_stack + ldr x2, [x1] + mul x0, x0, x2 + add x1, x1, x0 + mov sp, x1 bl init .p2align 4 - .space 0x4000 + .rept NR_OF_CPUS + .space STACK_SIZE + .endr _crt0_start_stack: + .long STACK_SIZE + diff --git a/repos/base-hw/src/bootstrap/spec/arndale/board.h b/repos/base-hw/src/bootstrap/spec/arndale/board.h index a8fdafcb4..12f8b46d9 100644 --- a/repos/base-hw/src/bootstrap/spec/arndale/board.h +++ b/repos/base-hw/src/bootstrap/spec/arndale/board.h @@ -17,11 +17,11 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Arndale_board; - + using Pic = Hw::Gicv2; static constexpr bool NON_SECURE = true; } diff --git a/repos/base-hw/src/bootstrap/spec/arndale/platform.cc b/repos/base-hw/src/bootstrap/spec/arndale/platform.cc index adbd9d877..7913055f6 100644 --- a/repos/base-hw/src/bootstrap/spec/arndale/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/arndale/platform.cc @@ -155,7 +155,9 @@ unsigned Bootstrap::Platform::enable_mmu() using namespace ::Board; static volatile bool primary_cpu = true; - board.pic.init_cpu_local(); + + /* locally initialize interrupt controller */ + ::Board::Pic pic { }; prepare_nonsecure_world(); prepare_hypervisor((addr_t)core_pd->table_base); diff --git a/repos/base-hw/src/bootstrap/spec/imx6q_sabrelite/board.h b/repos/base-hw/src/bootstrap/spec/imx6q_sabrelite/board.h index 218438d94..42dac5740 100644 --- a/repos/base-hw/src/bootstrap/spec/imx6q_sabrelite/board.h +++ b/repos/base-hw/src/bootstrap/spec/imx6q_sabrelite/board.h @@ -18,11 +18,11 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Imx6q_sabrelite_board; - + using Pic = Hw::Gicv2; struct L2_cache; static constexpr bool NON_SECURE = false; diff --git a/repos/base-hw/src/bootstrap/spec/imx7d_sabre/board.h b/repos/base-hw/src/bootstrap/spec/imx7d_sabre/board.h index ec1de436f..86204a6ea 100644 --- a/repos/base-hw/src/bootstrap/spec/imx7d_sabre/board.h +++ b/repos/base-hw/src/bootstrap/spec/imx7d_sabre/board.h @@ -17,11 +17,11 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Imx7d_sabre_board; - + using Pic = Hw::Gicv2; static constexpr bool NON_SECURE = true; } diff --git a/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc b/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc index 23cc11e3e..cf65b6969 100644 --- a/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc @@ -287,7 +287,9 @@ unsigned Bootstrap::Platform::enable_mmu() { static volatile bool primary_cpu = true; static unsigned long timer_freq = Cpu::Cntfrq::read(); - board.pic.init_cpu_local(); + + /* locally initialize interrupt controller */ + ::Board::Pic pic { }; prepare_nonsecure_world(timer_freq); prepare_hypervisor((addr_t)core_pd->table_base); diff --git a/repos/base-hw/src/bootstrap/spec/imx8q_evk/board.h b/repos/base-hw/src/bootstrap/spec/imx8q_evk/board.h index 2784a3b13..0f2cbec44 100644 --- a/repos/base-hw/src/bootstrap/spec/imx8q_evk/board.h +++ b/repos/base-hw/src/bootstrap/spec/imx8q_evk/board.h @@ -21,7 +21,12 @@ namespace Board { using namespace Hw::Imx8q_evk_board; - using Cpu = Hw::Arm_64_cpu; + + struct Cpu : Hw::Arm_64_cpu + { + static void wake_up_all_cpus(void*); + }; + using Hw::Pic; }; diff --git a/repos/base-hw/src/bootstrap/spec/imx8q_evk/platform.cc b/repos/base-hw/src/bootstrap/spec/imx8q_evk/platform.cc index 72bb6e49a..cbde68e46 100644 --- a/repos/base-hw/src/bootstrap/spec/imx8q_evk/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/imx8q_evk/platform.cc @@ -24,4 +24,269 @@ Bootstrap::Platform::Board::Board() Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE, ::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_SIZE }, Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE, - ::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE }) {} + ::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE }) +{ + ::Board::Pic pic {}; + + static volatile unsigned long initial_values[][2] { + // GPC values + { 0x303A0004, 0x5050424 }, + { 0x303A0030, 0xEB22DE22 }, + { 0x303A0034, 0xFFFFF1C7 }, + { 0x303A0038, 0x7BFFBC00 }, + { 0x303A003C, 0xFA3BF12A }, + { 0x303A004C, 0xFFFFDFFF }, + { 0x303A01B4, 0x3980 }, + { 0x303A01CC, 0xFFFFBFFF }, + { 0x303A01D4, 0xFFFF7FFF }, + { 0x303A01DC, 0xFFFF7FFF }, + { 0x303A01FC, 0x107FF9F }, + { 0x303A080C, 0x1 }, + { 0x303A0840, 0x1 }, + { 0x303A084C, 0x1 }, + { 0x303A0880, 0x1 }, + { 0x303A088C, 0x1 }, + { 0x303A08C0, 0x1 }, + { 0x303A08CC, 0x1 }, + { 0x303A0C8C, 0x1 }, + { 0x303A0DCC, 0x1 }, + { 0x303A0E0C, 0x1 }, + { 0x303A0ECC, 0x1 }, + { 0x303A0F00, 0x1 }, + { 0x303A0F0C, 0x1 }, + + // CCM values + { 0x303840B0, 0x2 }, + { 0x303840B4, 0x2 }, + { 0x303840B8, 0x2 }, + { 0x303840BC, 0x2 }, + { 0x303840C0, 0x2 }, + { 0x303840C4, 0x2 }, + { 0x303840C8, 0x2 }, + { 0x303840CC, 0x2 }, + { 0x303840D0, 0x2 }, + { 0x303840D4, 0x2 }, + { 0x303840D8, 0x2 }, + { 0x303840DC, 0x2 }, + { 0x303840E0, 0x2 }, + { 0x303840E4, 0x2 }, + { 0x303840E8, 0x2 }, + { 0x303840EC, 0x2 }, + { 0x303840F0, 0x2 }, + { 0x303840F4, 0x2 }, + { 0x303840F8, 0x2 }, + { 0x303840FC, 0x2 }, + { 0x30384250, 0x3 }, + { 0x30384254, 0x3 }, + { 0x30384258, 0x3 }, + { 0x3038425C, 0x3 }, + { 0x303843A0, 0x3 }, + { 0x303843A4, 0x3 }, + { 0x303843A8, 0x3 }, + { 0x303843AC, 0x3 }, + { 0x303844D0, 0x3 }, + { 0x303844D4, 0x3 }, + { 0x303844D8, 0x3 }, + { 0x303844DC, 0x3 }, + { 0x303844F0, 0x3 }, + { 0x303844F4, 0x3 }, + { 0x303844F8, 0x3 }, + { 0x303844FC, 0x3 }, + { 0x30384560, 0x0 }, + { 0x30384564, 0x0 }, + { 0x30384568, 0x0 }, + { 0x3038456C, 0x0 }, + { 0x303845D0, 0x3 }, + { 0x303845D4, 0x3 }, + { 0x303845D8, 0x3 }, + { 0x303845DC, 0x3 }, + { 0x30388010, 0x0 }, + { 0x30388014, 0x0 }, + { 0x30388018, 0x0 }, + { 0x3038801C, 0x0 }, + { 0x30388020, 0x0 }, + { 0x30388024, 0x0 }, + { 0x30388028, 0x0 }, + { 0x3038802C, 0x0 }, + { 0x30388030, 0x11000400 }, + { 0x30388034, 0x11000400 }, + { 0x30388038, 0x11000400 }, + { 0x3038803C, 0x11000400 }, + { 0x30388080, 0x11000000 }, + { 0x30388084, 0x11000000 }, + { 0x30388088, 0x11000000 }, + { 0x3038808C, 0x11000000 }, + { 0x30388090, 0x0 }, + { 0x30388094, 0x0 }, + { 0x30388098, 0x0 }, + { 0x3038809C, 0x0 }, + { 0x303880B0, 0x1100 }, + { 0x303880B4, 0x1100 }, + { 0x303880B8, 0x1100 }, + { 0x303880BC, 0x1100 }, + { 0x30388110, 0x0 }, + { 0x30388114, 0x0 }, + { 0x30388118, 0x0 }, + { 0x3038811C, 0x0 }, + { 0x30388180, 0x1000000 }, + { 0x30388184, 0x1000000 }, + { 0x30388188, 0x1000000 }, + { 0x3038818C, 0x1000000 }, + { 0x303881A0, 0x10000000 }, + { 0x303881A4, 0x10000000 }, + { 0x303881A8, 0x10000000 }, + { 0x303881AC, 0x10000000 }, + { 0x303881B0, 0x1000100 }, + { 0x303881B4, 0x1000100 }, + { 0x303881B8, 0x1000100 }, + { 0x303881BC, 0x1000100 }, + { 0x30388200, 0x1000000 }, + { 0x30388204, 0x1000000 }, + { 0x30388208, 0x1000000 }, + { 0x3038820C, 0x1000000 }, + { 0x30388220, 0x10000000 }, + { 0x30388224, 0x10000000 }, + { 0x30388228, 0x10000000 }, + { 0x3038822C, 0x10000000 }, + { 0x30388230, 0x1000100 }, + { 0x30388234, 0x1000100 }, + { 0x30388238, 0x1000100 }, + { 0x3038823C, 0x1000100 }, + + // CCMA values + { 0x30360000, 0x88080 }, + { 0x30360004, 0x292A2FA6 }, + { 0x30360004, 0x292A2FA6 }, + { 0x30360008, 0x88080 }, + { 0x30360008, 0x88080 }, + { 0x3036000C, 0x10385BA3 }, + { 0x3036000C, 0x10385BA3 }, + { 0x30360010, 0x98080 }, + { 0x30360010, 0x98080 }, + { 0x30360014, 0x3FFFFF1A }, + { 0x30360014, 0x3FFFFF1A }, + { 0x30360018, 0x88081 }, + { 0x30360054, 0x2B9 }, + + // IOMUXC + { 0x30330064, 0x6 }, + { 0x30330140, 0x0 }, + { 0x30330144, 0x0 }, + { 0x30330148, 0x0 }, + { 0x3033014C, 0x0 }, + { 0x30330150, 0x0 }, + { 0x30330154, 0x0 }, + { 0x30330158, 0x0 }, + { 0x30330180, 0x2 }, + { 0x30330184, 0x0 }, + { 0x30330188, 0x0 }, + { 0x3033018C, 0x0 }, + { 0x30330190, 0x0 }, + { 0x30330194, 0x0 }, + { 0x30330198, 0x0 }, + { 0x3033019C, 0x0 }, + { 0x303301A0, 0x0 }, + { 0x303301A4, 0x0 }, + { 0x303301A8, 0x0 }, + { 0x303301AC, 0x0 }, + { 0x303301BC, 0x0 }, + { 0x303301C0, 0x0 }, + { 0x303301C4, 0x0 }, + { 0x303301C8, 0x0 }, + { 0x303301E8, 0x0 }, + { 0x303301EC, 0x0 }, + { 0x303301FC, 0x1 }, + { 0x30330200, 0x1 }, + { 0x3033021C, 0x10 }, + { 0x30330220, 0x10 }, + { 0x30330224, 0x10 }, + { 0x30330228, 0x10 }, + { 0x3033022C, 0x12 }, + { 0x30330230, 0x12 }, + { 0x30330244, 0x0 }, + { 0x30330248, 0x0 }, + { 0x3033029C, 0x19 }, + { 0x303302A4, 0x19 }, + { 0x303302A8, 0x19 }, + { 0x303302B0, 0xD6 }, + { 0x303302C0, 0x4F }, + { 0x303302C4, 0x16 }, + { 0x303302CC, 0x59 }, + { 0x3033033C, 0x9F }, + { 0x30330340, 0xDF }, + { 0x30330344, 0xDF }, + { 0x30330348, 0xDF }, + { 0x3033034C, 0xDF }, + { 0x30330350, 0xDF }, + { 0x30330368, 0x59 }, + { 0x30330370, 0x19 }, + { 0x3033039C, 0x19 }, + { 0x303303A0, 0x19 }, + { 0x303303A4, 0x19 }, + { 0x303303A8, 0xD6 }, + { 0x303303AC, 0xD6 }, + { 0x303303B0, 0xD6 }, + { 0x303303B4, 0xD6 }, + { 0x303303B8, 0xD6 }, + { 0x303303BC, 0xD6 }, + { 0x303303C0, 0xD6 }, + { 0x303303E8, 0xD6 }, + { 0x303303EC, 0xD6 }, + { 0x303303F0, 0xD6 }, + { 0x303303F4, 0xD6 }, + { 0x303303F8, 0xD6 }, + { 0x303303FC, 0xD6 }, + { 0x30330400, 0xD6 }, + { 0x30330404, 0xD6 }, + { 0x30330408, 0xD6 }, + { 0x3033040C, 0xD6 }, + { 0x30330410, 0xD6 }, + { 0x30330414, 0xD6 }, + { 0x30330424, 0xD6 }, + { 0x30330428, 0xD6 }, + { 0x3033042C, 0xD6 }, + { 0x30330430, 0xD6 }, + { 0x30330450, 0xD6 }, + { 0x30330454, 0xD6 }, + { 0x30330464, 0x49 }, + { 0x30330468, 0x49 }, + { 0x3033046C, 0x16 }, + { 0x30330484, 0x67 }, + { 0x30330488, 0x67 }, + { 0x3033048C, 0x67 }, + { 0x30330490, 0x67 }, + { 0x30330494, 0x76 }, + { 0x30330498, 0x76 }, + { 0x303304AC, 0x49 }, + { 0x303304B0, 0x49 }, + { 0x303304C8, 0x1 }, + { 0x303304CC, 0x4 }, + { 0x30330500, 0x1 }, + { 0x30330504, 0x2 }, + { 0x30340038, 0x49409600 }, + { 0x30340040, 0x49409200 } + }; + + unsigned num_values = sizeof(initial_values) / (2*sizeof(unsigned long)); + for (unsigned i = 0; i < num_values; i++) + *((volatile Genode::uint32_t*)initial_values[i][0]) = (Genode::uint32_t)initial_values[i][1]; +} + + +void Board::Cpu::wake_up_all_cpus(void * ip) +{ + enum Function_id { CPU_ON = 0xC4000003 }; + + unsigned long result = 0; + for (unsigned i = 1; i < NR_OF_CPUS; i++) { + asm volatile("mov x0, %1 \n" + "mov x1, %2 \n" + "mov x2, %3 \n" + "mov x3, %2 \n" + "smc #0 \n" + "mov %0, x0 \n" + : "=r" (result) : "r" (CPU_ON), "r" (i), "r" (ip) + : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", + "x8", "x9", "x10", "x11", "x12", "x13", "x14"); + } +} diff --git a/repos/base-hw/src/bootstrap/spec/nit6_solox/board.h b/repos/base-hw/src/bootstrap/spec/nit6_solox/board.h index 886078e90..eccb76fc5 100644 --- a/repos/base-hw/src/bootstrap/spec/nit6_solox/board.h +++ b/repos/base-hw/src/bootstrap/spec/nit6_solox/board.h @@ -18,11 +18,11 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Nit6_solox_board; - + using Pic = Hw::Gicv2; struct L2_cache; static constexpr bool NON_SECURE = false; diff --git a/repos/base-hw/src/bootstrap/spec/odroid_xu/board.h b/repos/base-hw/src/bootstrap/spec/odroid_xu/board.h index e6cd3ea7c..6e87c82d7 100644 --- a/repos/base-hw/src/bootstrap/spec/odroid_xu/board.h +++ b/repos/base-hw/src/bootstrap/spec/odroid_xu/board.h @@ -17,10 +17,11 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Odroid_xu_board; + using Pic = Hw::Gicv2; static constexpr bool NON_SECURE = false; } diff --git a/repos/base-hw/src/bootstrap/spec/odroid_xu/platform.cc b/repos/base-hw/src/bootstrap/spec/odroid_xu/platform.cc index a56ae8eff..2537ec88c 100644 --- a/repos/base-hw/src/bootstrap/spec/odroid_xu/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/odroid_xu/platform.cc @@ -25,7 +25,9 @@ Bootstrap::Platform::Board::Board() unsigned Bootstrap::Platform::enable_mmu() { - board.pic.init_cpu_local(); + /* locally initialize interrupt controller */ + ::Board::Pic pic { }; + Cpu::Sctlr::init(); Cpu::Cpsr::init(); Cpu::invalidate_data_cache(); diff --git a/repos/base-hw/src/bootstrap/spec/panda/board.h b/repos/base-hw/src/bootstrap/spec/panda/board.h index 3ee45d532..a2e233b86 100644 --- a/repos/base-hw/src/bootstrap/spec/panda/board.h +++ b/repos/base-hw/src/bootstrap/spec/panda/board.h @@ -17,11 +17,11 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Panda_board; - + using Pic = Hw::Gicv2; static constexpr bool NON_SECURE = false; class L2_cache; diff --git a/repos/base-hw/src/bootstrap/spec/pbxa9/board.h b/repos/base-hw/src/bootstrap/spec/pbxa9/board.h index 92089d0c0..fc541a982 100644 --- a/repos/base-hw/src/bootstrap/spec/pbxa9/board.h +++ b/repos/base-hw/src/bootstrap/spec/pbxa9/board.h @@ -19,11 +19,13 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Pbxa9_board; + using Pic = Hw::Gicv2; + static constexpr bool NON_SECURE = false; } diff --git a/repos/base-hw/src/bootstrap/spec/riscv/board.h b/repos/base-hw/src/bootstrap/spec/riscv/board.h index 433f317c7..d19b3c75a 100644 --- a/repos/base-hw/src/bootstrap/spec/riscv/board.h +++ b/repos/base-hw/src/bootstrap/spec/riscv/board.h @@ -16,10 +16,7 @@ #include -namespace Board { - using namespace Hw::Riscv_board; - struct Pic {}; -} +namespace Board { using namespace Hw::Riscv_board; } template void Sv39::Level_x_translation_table::_translation_added(addr_t, size_t) diff --git a/repos/base-hw/src/bootstrap/spec/rpi/board.h b/repos/base-hw/src/bootstrap/spec/rpi/board.h index dc26e071c..f81f52192 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi/board.h +++ b/repos/base-hw/src/bootstrap/spec/rpi/board.h @@ -18,11 +18,7 @@ #include #include -namespace Board { - using namespace Hw::Rpi_board; - - struct Pic {}; -} +namespace Board { using namespace Hw::Rpi_board; } constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() { diff --git a/repos/base-hw/src/bootstrap/spec/rpi3/board.h b/repos/base-hw/src/bootstrap/spec/rpi3/board.h index 2018178c7..f6f3e1a94 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi3/board.h +++ b/repos/base-hw/src/bootstrap/spec/rpi3/board.h @@ -20,8 +20,13 @@ namespace Board { using namespace Hw::Rpi3_board; - using Cpu = Hw::Arm_64_cpu; - struct Pic {}; + + struct Cpu : Hw::Arm_64_cpu + { + static void wake_up_all_cpus(void*); + }; + + struct Pic { }; /* dummy object */ }; #endif /* _BOOTSTRAP__SPEC__RPI3__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc index 772147938..de7d6819f 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc @@ -26,3 +26,12 @@ Bootstrap::Platform::Board::Board() ::Board::LOCAL_IRQ_CONTROLLER_SIZE }, Memory_region { ::Board::IRQ_CONTROLLER_BASE, ::Board::IRQ_CONTROLLER_SIZE }) {} + + +extern unsigned int _crt0_qemu_start_secondary_cpus; + +void Board::Cpu::wake_up_all_cpus(void *) +{ + _crt0_qemu_start_secondary_cpus = 1; + asm volatile("dsb #0; sev"); +} diff --git a/repos/base-hw/src/bootstrap/spec/usb_armory/platform.cc b/repos/base-hw/src/bootstrap/spec/usb_armory/platform.cc index 5549141a3..2de5cc9f2 100644 --- a/repos/base-hw/src/bootstrap/spec/usb_armory/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/usb_armory/platform.cc @@ -38,6 +38,8 @@ Bootstrap::Platform::Board::Board() Aipstz aipstz_1(AIPS_1_MMIO_BASE); Aipstz aipstz_2(AIPS_2_MMIO_BASE); + Pic pic {}; + /* set monitor mode exception vector entry */ Cpu::Mvbar::write(Hw::Mm::system_exception_vector().base); diff --git a/repos/base-hw/src/bootstrap/spec/wand_quad/board.h b/repos/base-hw/src/bootstrap/spec/wand_quad/board.h index 16e318f2d..226e9f32d 100644 --- a/repos/base-hw/src/bootstrap/spec/wand_quad/board.h +++ b/repos/base-hw/src/bootstrap/spec/wand_quad/board.h @@ -18,11 +18,13 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Wand_quad_board; + using Pic = Hw::Gicv2; + struct L2_cache; static constexpr bool NON_SECURE = false; diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/board.h b/repos/base-hw/src/bootstrap/spec/x86_64/board.h index 67af752cd..8517eb475 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/board.h +++ b/repos/base-hw/src/bootstrap/spec/x86_64/board.h @@ -22,7 +22,6 @@ namespace Board { using namespace Hw::Pc_board; using Cpu = Hw::X86_64_cpu; - struct Pic {}; } #endif /* _SRC__BOOTSTRAP__SPEC__X86_64__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/zynq_qemu/board.h b/repos/base-hw/src/bootstrap/spec/zynq_qemu/board.h index 63cff449c..8b9920be6 100644 --- a/repos/base-hw/src/bootstrap/spec/zynq_qemu/board.h +++ b/repos/base-hw/src/bootstrap/spec/zynq_qemu/board.h @@ -18,10 +18,11 @@ #include #include #include -#include +#include namespace Board { using namespace Hw::Zynq_qemu_board; + using Pic = Hw::Gicv2; static constexpr bool NON_SECURE = false; } diff --git a/repos/base-hw/src/core/irq_session_component.cc b/repos/base-hw/src/core/irq_session_component.cc index 744e133c4..ea563a432 100644 --- a/repos/base-hw/src/core/irq_session_component.cc +++ b/repos/base-hw/src/core/irq_session_component.cc @@ -18,7 +18,6 @@ /* core includes */ #include "kernel/irq.h" #include -#include #include /* base-internal includes */ @@ -35,10 +34,7 @@ unsigned Irq_session_component::_find_irq_number(const char * const args) void Irq_session_component::ack_irq() { - using Kernel::User_irq; - if (!_sig_cap.valid()) { return; } - User_irq * const kirq = reinterpret_cast(&_kernel_object); - Kernel::ack_irq(kirq); + if (_kobj.constructed()) Kernel::ack_irq(*_kobj); } @@ -51,8 +47,8 @@ void Irq_session_component::sigh(Signal_context_capability cap) _sig_cap = cap; - if (Kernel::new_irq((addr_t)&_kernel_object, _irq_number, - Capability_space::capid(_sig_cap))) + if (!_kobj.create(_irq_number, _irq_args.trigger(), _irq_args.polarity(), + Capability_space::capid(_sig_cap))) warning("invalid signal handler for IRQ ", _irq_number); } @@ -61,18 +57,16 @@ Irq_session_component::~Irq_session_component() { using namespace Kernel; - User_irq * kirq = reinterpret_cast(&_kernel_object); _irq_alloc.free((void *)(addr_t)_irq_number); - if (_sig_cap.valid()) - Kernel::delete_irq(kirq); } Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, const char * const args) -: - _irq_number(Platform::irq(_find_irq_number(args))), _irq_alloc(irq_alloc), - _is_msi(false), _address(0), _value(0) +: _irq_args(args), + _irq_number(Platform::irq(_irq_args.irq_number())), + _irq_alloc(irq_alloc), + _kobj(), _is_msi(false), _address(0), _value(0) { const long mmconf = Arg_string::find_arg(args, "device_config_phys").long_value(0); @@ -89,8 +83,4 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, error("unavailable interrupt ", _irq_number, " requested"); throw Service_denied(); } - - Irq_args const irq_args(args); - - Kernel::irq_mode(_irq_number, irq_args.trigger(), irq_args.polarity()); } diff --git a/repos/base-hw/src/core/kernel/core_interface.h b/repos/base-hw/src/core/kernel/core_interface.h index 8620df663..557ccf835 100644 --- a/repos/base-hw/src/core/kernel/core_interface.h +++ b/repos/base-hw/src/core/kernel/core_interface.h @@ -31,6 +31,7 @@ namespace Kernel class Vm; class User_irq; using Native_utcb = Genode::Native_utcb; + template class Core_object_identity; /** * Kernel names of the kernel calls @@ -60,15 +61,14 @@ namespace Kernel constexpr Call_arg call_id_delete_obj() { return 122; } constexpr Call_arg call_id_cancel_thread_blocking() { return 123; } constexpr Call_arg call_id_new_core_thread() { return 124; } - constexpr Call_arg call_id_irq_mode() { return 125; } /** * Invalidate TLB entries for the `pd` in region `addr`, `sz` */ - inline void invalidate_tlb(Pd * const pd, addr_t const addr, + inline void invalidate_tlb(Pd & pd, addr_t const addr, size_t const sz) { - call(call_id_invalidate_tlb(), (Call_arg)pd, (Call_arg)addr, + call(call_id_invalidate_tlb(), (Call_arg)&pd, (Call_arg)addr, (Call_arg)sz); } @@ -79,9 +79,9 @@ namespace Kernel * \param thread kernel object of the targeted thread * \param quota new CPU quota value */ - inline void thread_quota(Kernel::Thread * const thread, size_t const quota) + inline void thread_quota(Kernel::Thread & thread, size_t const quota) { - call(call_id_thread_quota(), (Call_arg)thread, (Call_arg)quota); + call(call_id_thread_quota(), (Call_arg)&thread, (Call_arg)quota); } @@ -104,9 +104,9 @@ namespace Kernel * continue the execution of a thread no matter what state the thread is * in. */ - inline void pause_thread(Thread * const thread) + inline void pause_thread(Thread & thread) { - call(call_id_pause_thread(), (Call_arg)thread); + call(call_id_pause_thread(), (Call_arg)&thread); } @@ -115,9 +115,9 @@ namespace Kernel * * \param thread pointer to thread kernel object */ - inline void resume_thread(Thread * const thread) + inline void resume_thread(Thread & thread) { - call(call_id_resume_thread(), (Call_arg)thread); + call(call_id_resume_thread(), (Call_arg)&thread); } @@ -132,11 +132,11 @@ namespace Kernel * \retval 0 suceeded * \retval !=0 failed */ - inline int start_thread(Thread * const thread, unsigned const cpu_id, - Pd * const pd, Native_utcb * const utcb) + inline int start_thread(Thread & thread, unsigned const cpu_id, + Pd & pd, Native_utcb & utcb) { - return call(call_id_start_thread(), (Call_arg)thread, cpu_id, - (Call_arg)pd, (Call_arg)utcb); + return call(call_id_start_thread(), (Call_arg)&thread, cpu_id, + (Call_arg)&pd, (Call_arg)&utcb); } @@ -155,9 +155,9 @@ namespace Kernel * limit the time a parent waits for a server when closing a session * of one of its children. */ - inline void cancel_thread_blocking(Thread * const thread) + inline void cancel_thread_blocking(Thread & thread) { - call(call_id_cancel_thread_blocking(), (Call_arg)thread); + call(call_id_cancel_thread_blocking(), (Call_arg)&thread); } @@ -167,10 +167,10 @@ namespace Kernel * \param thread pointer to thread kernel object * \param signal_context_id capability id of the page-fault handler */ - inline void thread_pager(Thread * const thread, - capid_t const signal_context_id) + inline void thread_pager(Thread & thread, + capid_t const signal_context_id) { - call(call_id_thread_pager(), (Call_arg)thread, signal_context_id); + call(call_id_thread_pager(), (Call_arg)&thread, signal_context_id); } @@ -179,9 +179,9 @@ namespace Kernel * * \param vm pointer to vm kernel object */ - inline void run_vm(Vm * const vm) + inline void run_vm(Vm & vm) { - call(call_id_run_vm(), (Call_arg) vm); + call(call_id_run_vm(), (Call_arg) &vm); } @@ -190,33 +190,9 @@ namespace Kernel * * \param vm pointer to vm kernel object */ - inline void pause_vm(Vm * const vm) + inline void pause_vm(Vm & vm) { - call(call_id_pause_vm(), (Call_arg) vm); - } - - /** - * Create an interrupt object - * - * \param p memory donation for the irq object - * \param irq_nr interrupt number - * \param signal_context_id capability id of the signal context - */ - inline int new_irq(addr_t const p, unsigned irq_nr, - capid_t signal_context_id) - { - return call(call_id_new_irq(), (Call_arg) p, irq_nr, signal_context_id); - } - - /** - * Set trigger/polaruty of IRQ - * \param irq_nr interrupt number - * \param trigger low or edge - * \param polarity low or high - */ - inline void irq_mode(unsigned irq_nr, unsigned trigger, unsigned polarity) - { - call(call_id_irq_mode(), irq_nr, trigger, polarity); + call(call_id_pause_vm(), (Call_arg) &vm); } /** @@ -224,40 +200,9 @@ namespace Kernel * * \param irq pointer to interrupt kernel object */ - inline void ack_irq(User_irq * const irq) + inline void ack_irq(User_irq & irq) { - call(call_id_ack_irq(), (Call_arg) irq); - } - - /** - * Destruct an interrupt object - * - * \param irq pointer to interrupt kernel object - */ - inline void delete_irq(User_irq * const irq) - { - call(call_id_delete_irq(), (Call_arg) irq); - } - - /** - * Create a new object identity for a thread - * - * \param dst memory donation for the new object - * \param cap capability id of the targeted thread - */ - inline capid_t new_obj(void * const dst, capid_t const cap) - { - return call(call_id_new_obj(), (Call_arg)dst, (Call_arg)cap); - } - - /** - * Destroy an object identity - * - * \param dst pointer to the object identity object - */ - inline void delete_obj(void * const dst) - { - call(call_id_delete_obj(), (Call_arg)dst); + call(call_id_ack_irq(), (Call_arg) &irq); } } diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index 2f4c56e82..c7d3d23af 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -157,10 +157,10 @@ addr_t Cpu::stack_start() { return (addr_t)&kernel_stack + KERNEL_STACK_SIZE * (_id+1); } -Cpu::Cpu(unsigned const id, Board::Pic & pic, +Cpu::Cpu(unsigned const id, Inter_processor_work_list & global_work_list) : - _id(id), _pic(pic), _timer(*this), + _id(id), _timer(*this), _scheduler(&_idle, _quota(), _fill()), _idle(*this), _ipi_irq(*this), _global_work_list(global_work_list) @@ -174,7 +174,7 @@ Cpu::Cpu(unsigned const id, Board::Pic & pic, bool Cpu_pool::initialize() { unsigned id = Cpu::executing_id(); - _cpus[id].construct(id, _pic, _global_work_list); + _cpus[id].construct(id, _global_work_list); return --_initialized == 0; } diff --git a/repos/base-hw/src/core/kernel/cpu.h b/repos/base-hw/src/core/kernel/cpu.h index 067f3d849..189b23d79 100644 --- a/repos/base-hw/src/core/kernel/cpu.h +++ b/repos/base-hw/src/core/kernel/cpu.h @@ -113,7 +113,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout unsigned const _id; - Board::Pic &_pic; + Board::Pic _pic {}; Timer _timer; Cpu_scheduler _scheduler; Idle_thread _idle; @@ -133,7 +133,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout /** * Construct object for CPU 'id' */ - Cpu(unsigned const id, Board::Pic & pic, + Cpu(unsigned const id, Inter_processor_work_list & global_work_list); static inline unsigned primary_id() { return 0; } @@ -192,7 +192,6 @@ class Kernel::Cpu_pool { private: - Board::Pic _pic {}; Inter_processor_work_list _global_work_list {}; unsigned _count; unsigned _initialized { _count }; diff --git a/repos/base-hw/src/core/kernel/cpu_mp.cc b/repos/base-hw/src/core/kernel/cpu_mp.cc index acedbe034..68d241729 100644 --- a/repos/base-hw/src/core/kernel/cpu_mp.cc +++ b/repos/base-hw/src/core/kernel/cpu_mp.cc @@ -46,4 +46,6 @@ void Cpu::trigger_ip_interrupt() } -Cpu::Ipi::Ipi(Cpu & cpu) : Irq(Board::Pic::IPI, cpu), cpu(cpu) { } +Cpu::Ipi::Ipi(Cpu & cpu) +: Irq(Board::Pic::IPI, cpu), cpu(cpu) { + cpu.pic().unmask(Board::Pic::IPI, cpu.id()); } diff --git a/repos/base-hw/src/core/kernel/ipc_node.h b/repos/base-hw/src/core/kernel/ipc_node.h index 1ef2deeff..135546d20 100644 --- a/repos/base-hw/src/core/kernel/ipc_node.h +++ b/repos/base-hw/src/core/kernel/ipc_node.h @@ -15,9 +15,6 @@ #ifndef _CORE__KERNEL__IPC_NODE_H_ #define _CORE__KERNEL__IPC_NODE_H_ -/* Genode includes */ -#include - /* base-local includes */ #include diff --git a/repos/base-hw/src/core/kernel/irq.cc b/repos/base-hw/src/core/kernel/irq.cc index f8b3cd02e..d00757d2c 100644 --- a/repos/base-hw/src/core/kernel/irq.cc +++ b/repos/base-hw/src/core/kernel/irq.cc @@ -30,3 +30,14 @@ Kernel::Irq::Pool &Kernel::User_irq::_pool() static Irq::Pool p; return p; } + + +Kernel::User_irq::User_irq(unsigned const irq, + Genode::Irq_session::Trigger trigger, + Genode::Irq_session::Polarity polarity, + Signal_context & context) +: Irq(irq, _pool()), _context(context) +{ + disable(); + cpu_pool().executing_cpu().pic().irq_mode(_irq_nr, trigger, polarity); +} diff --git a/repos/base-hw/src/core/kernel/irq.h b/repos/base-hw/src/core/kernel/irq.h index 2994bee90..041650213 100644 --- a/repos/base-hw/src/core/kernel/irq.h +++ b/repos/base-hw/src/core/kernel/irq.h @@ -135,8 +135,10 @@ class Kernel::User_irq : public Kernel::Irq, public Kernel::Object /** * Construct object that signals interrupt 'irq' via signal 'context' */ - User_irq(unsigned const irq, Signal_context &context) - : Irq(irq, _pool()), _context(context) { disable(); } + User_irq(unsigned const irq, + Genode::Irq_session::Trigger trigger, + Genode::Irq_session::Polarity polarity, + Signal_context & context); /** * Destructor @@ -157,6 +159,33 @@ class Kernel::User_irq : public Kernel::Irq, public Kernel::Object */ static User_irq * object(unsigned const irq) { return dynamic_cast(_pool().object(irq)); } + + /** + * Syscall to create user irq object + * + * \param irq reference to constructible object + * \param nr interrupt number + * \param trigger level or edge + * \param polarity low or high + * \param sig capability of signal context + */ + static capid_t syscall_create(Genode::Kernel_object & irq, + unsigned nr, + Genode::Irq_session::Trigger trigger, + Genode::Irq_session::Polarity polarity, + capid_t sig) + { + return call(call_id_new_irq(), (Call_arg)&irq, nr, + (trigger << 2) | polarity, sig); + } + + /** + * Syscall to delete user irq object + * + * \param irq reference to constructible object + */ + static void syscall_destroy(Genode::Kernel_object &irq) { + call(call_id_delete_irq(), (Call_arg) &irq); } }; #endif /* _CORE__KERNEL__IRQ_H_ */ diff --git a/repos/base-hw/src/core/kernel/lock.h b/repos/base-hw/src/core/kernel/lock.h index 2874960f7..3abb5f133 100644 --- a/repos/base-hw/src/core/kernel/lock.h +++ b/repos/base-hw/src/core/kernel/lock.h @@ -31,7 +31,7 @@ class Kernel::Lock enum State { UNLOCKED, LOCKED }; - State volatile _locked { UNLOCKED }; + int volatile _locked { UNLOCKED }; unsigned volatile _current_cpu { INVALID }; public: diff --git a/repos/base-hw/src/core/kernel/object.h b/repos/base-hw/src/core/kernel/object.h index d4ab101c5..fecade269 100644 --- a/repos/base-hw/src/core/kernel/object.h +++ b/repos/base-hw/src/core/kernel/object.h @@ -18,8 +18,10 @@ #include #include #include +#include /* core includes */ +#include #include #include "kernel.h" @@ -192,6 +194,13 @@ class Kernel::Core_object_identity : public Object_identity, Object_identity_reference(this, core_pd()) { } capid_t core_capid() { return capid(); } + + static capid_t syscall_create(Genode::Constructible> & t, + capid_t const cap) { + return call(call_id_new_obj(), (Call_arg)&t, (Call_arg)cap); } + + static void syscall_destroy(Genode::Constructible> & t) { + call(call_id_delete_obj(), (Call_arg)&t); } }; diff --git a/repos/base-hw/src/core/kernel/pd.h b/repos/base-hw/src/core/kernel/pd.h index 941f720bd..18b7af7e6 100644 --- a/repos/base-hw/src/core/kernel/pd.h +++ b/repos/base-hw/src/core/kernel/pd.h @@ -18,10 +18,12 @@ /* core includes */ #include #include -#include "core_interface.h" -#include "object.h" +#include +#include #include +#include + namespace Genode { class Platform_pd; } @@ -51,6 +53,7 @@ class Kernel::Pd : public Kernel::Object Genode::Platform_pd &_platform_pd; Capid_allocator _capid_alloc { }; Object_identity_reference_tree _cap_tree { }; + bool _core_pd { false }; public: @@ -69,6 +72,12 @@ class Kernel::Pd : public Kernel::Object { capid_t invalid = _capid_alloc.alloc(); assert(invalid == cap_id_invalid()); + + static bool first_pd = true; + if (first_pd) { + _core_pd = true; + first_pd = false; + } } ~Pd() @@ -77,16 +86,16 @@ class Kernel::Pd : public Kernel::Object oir->~Object_identity_reference(); } - static capid_t syscall_create(void * const dst, - Hw::Page_table &tt, - Genode::Platform_pd &pd) + static capid_t syscall_create(Genode::Kernel_object & p, + Hw::Page_table & tt, + Genode::Platform_pd & pd) { - return call(call_id_new_pd(), (Call_arg)dst, + return call(call_id_new_pd(), (Call_arg)&p, (Call_arg)&tt, (Call_arg)&pd); } - static void syscall_destroy(Pd * const pd) { - call(call_id_delete_pd(), (Call_arg)pd); } + static void syscall_destroy(Genode::Kernel_object & p) { + call(call_id_delete_pd(), (Call_arg)&p); } /** * Check whether the given 'cpu' needs to do some maintainance @@ -103,6 +112,13 @@ class Kernel::Pd : public Kernel::Object Hw::Page_table &translation_table() { return _table; } Capid_allocator &capid_alloc() { return _capid_alloc; } Object_identity_reference_tree &cap_tree() { return _cap_tree; } + bool core_pd() const { return _core_pd; } }; + +template<> +inline Kernel::Core_object_identity::Core_object_identity(Kernel::Pd & pd) +: Object_identity(pd), + Object_identity_reference(this, pd.core_pd() ? pd : core_pd()) { } + #endif /* _CORE__KERNEL__PD_H_ */ diff --git a/repos/base-hw/src/core/kernel/signal_receiver.cc b/repos/base-hw/src/core/kernel/signal_receiver.cc index a1973c27e..0c533919f 100644 --- a/repos/base-hw/src/core/kernel/signal_receiver.cc +++ b/repos/base-hw/src/core/kernel/signal_receiver.cc @@ -55,7 +55,7 @@ Signal_context_killer::~Signal_context_killer() { cancel_waiting(); } void Signal_context::_deliverable() { - if (_submits) { _receiver->_add_deliverable(this); } + if (_submits) { _receiver._add_deliverable(this); } } @@ -118,16 +118,15 @@ int Signal_context::kill(Signal_context_killer * const k) Signal_context::~Signal_context() { if (_killer) { _killer->_signal_context_kill_failed(); } - _receiver->_context_destructed(this); + _receiver._context_destructed(this); } -Signal_context::Signal_context(Signal_receiver * const r, addr_t const imprint) -: - _receiver(r), - _imprint(imprint) +Signal_context::Signal_context(Signal_receiver & r, addr_t const imprint) +: _receiver(r), + _imprint(imprint) { - r->_add_context(this); + r._add_context(this); } @@ -164,7 +163,7 @@ void Signal_receiver::_listen() /* communicate signal data to handler */ _handlers.dequeue([&] (Signal_handler::Fifo_element &elem) { auto const handler = &elem.object(); - handler->_receiver = 0; + handler->_receiver = nullptr; handler->_receive_signal(&data, sizeof(data)); }); context->_delivered(); diff --git a/repos/base-hw/src/core/kernel/signal_receiver.h b/repos/base-hw/src/core/kernel/signal_receiver.h index a339db75a..d31f14aa9 100644 --- a/repos/base-hw/src/core/kernel/signal_receiver.h +++ b/repos/base-hw/src/core/kernel/signal_receiver.h @@ -16,9 +16,10 @@ /* Genode includes */ #include +#include -#include "core_interface.h" -#include "object.h" +#include +#include namespace Kernel { @@ -160,7 +161,7 @@ class Kernel::Signal_context : public Kernel::Object Fifo_element _deliver_fe { *this }; Fifo_element _contexts_fe { *this }; - Signal_receiver * const _receiver; + Signal_receiver & _receiver; addr_t const _imprint; Signal_context_killer * _killer { nullptr }; unsigned _submits { 0 }; @@ -197,7 +198,7 @@ class Kernel::Signal_context : public Kernel::Object * * \throw Assign_to_receiver_failed */ - Signal_context(Signal_receiver * const r, addr_t const imprint); + Signal_context(Signal_receiver & r, addr_t const imprint); /** * Submit the signal @@ -233,12 +234,12 @@ class Kernel::Signal_context : public Kernel::Object * * \retval capability id of the new kernel object */ - static capid_t syscall_create(void * p, - Signal_receiver * const receiver, + static capid_t syscall_create(Genode::Kernel_object &c, + Signal_receiver & receiver, addr_t const imprint) { - return call(call_id_new_signal_context(), (Call_arg)p, - (Call_arg)receiver, (Call_arg)imprint); + return call(call_id_new_signal_context(), (Call_arg)&c, + (Call_arg)&receiver, (Call_arg)imprint); } /** @@ -246,8 +247,8 @@ class Kernel::Signal_context : public Kernel::Object * * \param context pointer to signal context kernel object */ - static void syscall_destroy(Signal_context * const context) { - call(call_id_delete_signal_context(), (Call_arg)context); } + static void syscall_destroy(Genode::Kernel_object &c) { + call(call_id_delete_signal_context(), (Call_arg)&c); } }; class Kernel::Signal_receiver : public Kernel::Object @@ -311,16 +312,16 @@ class Kernel::Signal_receiver : public Kernel::Object * * \retval capability id of the new kernel object */ - static capid_t syscall_create(void * p) { - return call(call_id_new_signal_receiver(), (Call_arg)p); } + static capid_t syscall_create(Genode::Kernel_object &r) { + return call(call_id_new_signal_receiver(), (Call_arg)&r); } /** * Syscall to destruct a signal receiver * * \param receiver pointer to signal receiver kernel object */ - static void syscall_destroy(Signal_receiver * const receiver) { - call(call_id_delete_signal_receiver(), (Call_arg)receiver); } + static void syscall_destroy(Genode::Kernel_object &r) { + call(call_id_delete_signal_receiver(), (Call_arg)&r); } }; #endif /* _CORE__KERNEL__SIGNAL_RECEIVER_H_ */ diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index 7b51ec723..92f821a7c 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -15,7 +15,6 @@ /* Genode includes */ #include #include -#include /* base-internal includes */ #include @@ -47,17 +46,17 @@ Thread::Tlb_invalidation::Tlb_invalidation(Thread & caller, Pd & pd, } -Thread::Destroy::Destroy(Thread & caller, Thread & to_delete) +Thread::Destroy::Destroy(Thread & caller, Genode::Kernel_object & to_delete) : caller(caller), thread_to_destroy(to_delete) { - thread_to_destroy._cpu->work_list().insert(&_le); + thread_to_destroy->_cpu->work_list().insert(&_le); caller._become_inactive(AWAITS_RESTART); } void Thread::Destroy::execute() { - thread_to_destroy.~Thread(); + thread_to_destroy.destruct(); cpu_pool().executing_cpu().work_list().remove(&_le); caller._restart(); } @@ -193,28 +192,6 @@ size_t Thread::_core_to_kernel_quota(size_t const quota) const } -void Thread::_call_new_thread() -{ - void * const p = (void *)user_arg_1(); - unsigned const priority = user_arg_2(); - unsigned const quota = _core_to_kernel_quota(user_arg_3()); - char const * const label = (char *)user_arg_4(); - Core_object * co = - Genode::construct_at >(p, priority, quota, label); - user_arg_0(co->core_capid()); -} - - -void Thread::_call_new_core_thread() -{ - void * const p = (void *)user_arg_1(); - char const * const label = (char *)user_arg_2(); - Core_object * co = - Genode::construct_at >(p, label); - user_arg_0(co->core_capid()); -} - - void Thread::_call_thread_quota() { Thread * const thread = (Thread *)user_arg_1(); @@ -227,7 +204,7 @@ void Thread::_call_start_thread() /* lookup CPU */ Cpu & cpu = cpu_pool().cpu(user_arg_2()); user_arg_0(0); - Thread &thread = *(Thread *)user_arg_1(); + Thread &thread = *(Thread*)user_arg_1(); assert(thread._state == AWAITS_START); @@ -338,7 +315,8 @@ void Thread::_call_yield_thread() void Thread::_call_delete_thread() { - Thread * to_delete = reinterpret_cast(user_arg_1()); + Genode::Kernel_object & to_delete = + *(Genode::Kernel_object*)user_arg_1(); /** * Delete a thread immediately if it has no cpu assigned yet, @@ -346,7 +324,7 @@ void Thread::_call_delete_thread() */ if (!to_delete->_cpu || (to_delete->_cpu->id() == Cpu::executing_id() || - &to_delete->_cpu->scheduled_job() != to_delete)) { + &to_delete->_cpu->scheduled_job() != &*to_delete)) { _call_delete(); return; } @@ -354,7 +332,7 @@ void Thread::_call_delete_thread() /** * Construct a cross-cpu work item and send an IPI */ - _destroy.construct(*this, *to_delete); + _destroy.construct(*this, to_delete); to_delete->_cpu->trigger_ip_interrupt(); } @@ -566,21 +544,19 @@ void Thread::_call_kill_signal_context() void Thread::_call_new_irq() { - Signal_context * const c = pd().cap_tree().find(user_arg_3()); + Signal_context * const c = pd().cap_tree().find(user_arg_4()); if (!c) { Genode::raw(*this, ": invalid signal context for interrupt"); user_arg_0(-1); return; } - new ((void *)user_arg_1()) User_irq(user_arg_2(), *c); - user_arg_0(0); -} + Genode::Irq_session::Trigger trigger = + (Genode::Irq_session::Trigger) (user_arg_3() & 0b1100); + Genode::Irq_session::Polarity polarity = + (Genode::Irq_session::Polarity) (user_arg_3() & 0b11); -void Thread::_call_irq_mode() -{ - cpu_pool().executing_cpu().pic().irq_mode(user_arg_1(), user_arg_2(), - user_arg_3()); + _call_new((unsigned)user_arg_2(), trigger, polarity, *c); } @@ -601,17 +577,18 @@ void Thread::_call_new_obj() return; } - using Thread_identity = Core_object_identity; - Thread_identity * coi = - Genode::construct_at((void *)user_arg_1(), *thread); + using Thread_identity = Genode::Constructible>; + Thread_identity & coi = *(Thread_identity*)user_arg_1(); + coi.construct(*thread); user_arg_0(coi->core_capid()); } void Thread::_call_delete_obj() { - using Object = Core_object_identity; - reinterpret_cast(user_arg_1())->~Object(); + using Thread_identity = Genode::Constructible>; + Thread_identity & coi = *(Thread_identity*)user_arg_1(); + coi.destruct(); } @@ -686,8 +663,14 @@ void Thread::_call() } /* switch over kernel calls that are restricted to core */ switch (call_id) { - case call_id_new_thread(): _call_new_thread(); return; - case call_id_new_core_thread(): _call_new_core_thread(); return; + case call_id_new_thread(): + _call_new((unsigned) user_arg_2(), + (unsigned) _core_to_kernel_quota(user_arg_3()), + (char const *) user_arg_4()); + return; + case call_id_new_core_thread(): + _call_new((char const *) user_arg_2()); + return; case call_id_thread_quota(): _call_thread_quota(); return; case call_id_delete_thread(): _call_delete_thread(); return; case call_id_start_thread(): _call_start_thread(); return; @@ -702,7 +685,7 @@ void Thread::_call() case call_id_delete_pd(): _call_delete(); 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()); + _call_new(*(Signal_receiver*) user_arg_2(), user_arg_3()); return; case call_id_delete_signal_context(): _call_delete(); return; case call_id_delete_signal_receiver(): _call_delete(); return; @@ -712,8 +695,7 @@ void Thread::_call() case call_id_pause_vm(): _call_pause_vm(); return; case call_id_pause_thread(): _call_pause_thread(); return; case call_id_new_irq(): _call_new_irq(); return; - case call_id_irq_mode(): _call_irq_mode(); return; - case call_id_delete_irq(): _call_delete(); return; + case call_id_delete_irq(): _call_delete(); return; case call_id_ack_irq(): _call_ack_irq(); return; case call_id_new_obj(): _call_new_obj(); return; case call_id_delete_obj(): _call_delete_obj(); return; diff --git a/repos/base-hw/src/core/kernel/thread.h b/repos/base-hw/src/core/kernel/thread.h index cdf848df3..c3a458458 100644 --- a/repos/base-hw/src/core/kernel/thread.h +++ b/repos/base-hw/src/core/kernel/thread.h @@ -19,11 +19,11 @@ /* core includes */ #include -#include "cpu_context.h" -#include "inter_processor_work.h" -#include "signal_receiver.h" -#include "ipc_node.h" -#include "object.h" +#include +#include +#include +#include +#include namespace Kernel { @@ -89,10 +89,12 @@ class Kernel::Thread */ struct Destroy : Inter_processor_work { - Thread & caller; /* the caller gets blocked till the end */ - Thread & thread_to_destroy; /* thread to be destroyed */ + using Kthread = Genode::Kernel_object; - Destroy(Thread & caller, Thread & to_destroy); + Thread & caller; /* the caller gets blocked till the end */ + Kthread & thread_to_destroy; /* thread to be destroyed */ + + Destroy(Thread & caller, Kthread & to_destroy); /************************************ ** Inter_processor_work interface ** @@ -241,18 +243,19 @@ class Kernel::Thread template void _call_new(ARGS &&... args) { - using Object = Core_object; - void * dst = (void *)user_arg_1(); - Object * o = Genode::construct_at(dst, args...); - user_arg_0(o->core_capid()); + Genode::Kernel_object & kobj = + *(Genode::Kernel_object*)user_arg_1(); + kobj.construct(args...); + user_arg_0(kobj->core_capid()); } template void _call_delete() { - using Object = Core_object; - reinterpret_cast(user_arg_1())->~Object(); + Genode::Kernel_object & kobj = + *(Genode::Kernel_object*)user_arg_1(); + kobj.destruct(); } @@ -317,12 +320,14 @@ class Kernel::Thread void user_arg_2(Kernel::Call_arg const arg); void user_arg_3(Kernel::Call_arg const arg); void user_arg_4(Kernel::Call_arg const arg); + void user_arg_5(Kernel::Call_arg const arg); Kernel::Call_arg user_arg_0() const; Kernel::Call_arg user_arg_1() const; Kernel::Call_arg user_arg_2() const; Kernel::Call_arg user_arg_3() const; Kernel::Call_arg user_arg_4() const; + Kernel::Call_arg user_arg_5() const; /** * Syscall to create a thread @@ -334,11 +339,12 @@ class Kernel::Thread * * \retval capability id of the new kernel object */ - static capid_t syscall_create(void * const p, unsigned const priority, - size_t const quota, - char const * const label) + static capid_t syscall_create(Genode::Kernel_object & t, + unsigned const priority, + size_t const quota, + char const * const label) { - return call(call_id_new_thread(), (Call_arg)p, (Call_arg)priority, + return call(call_id_new_thread(), (Call_arg)&t, (Call_arg)priority, (Call_arg)quota, (Call_arg)label); } @@ -350,9 +356,10 @@ class Kernel::Thread * * \retval capability id of the new kernel object */ - static capid_t syscall_create(void * const p, char const * const label) + static capid_t syscall_create(Genode::Kernel_object & t, + char const * const label) { - return call(call_id_new_core_thread(), (Call_arg)p, + return call(call_id_new_core_thread(), (Call_arg)&t, (Call_arg)label); } @@ -361,8 +368,8 @@ class Kernel::Thread * * \param thread pointer to thread kernel object */ - static void syscall_destroy(Thread * thread) { - call(call_id_delete_thread(), (Call_arg)thread); } + static void syscall_destroy(Genode::Kernel_object & t) { + call(call_id_delete_thread(), (Call_arg)&t); } void print(Genode::Output &out) const; diff --git a/repos/base-hw/src/core/kernel/timer.h b/repos/base-hw/src/core/kernel/timer.h index 32e849e5e..77f73b100 100644 --- a/repos/base-hw/src/core/kernel/timer.h +++ b/repos/base-hw/src/core/kernel/timer.h @@ -105,8 +105,6 @@ class Kernel::Timer unsigned interrupt_id() const; - static void init_cpu_local(); - time_t time() const { return _time + _duration(); } }; diff --git a/repos/base-hw/src/core/kernel/vm.h b/repos/base-hw/src/core/kernel/vm.h index 041c541a4..4ed71a912 100644 --- a/repos/base-hw/src/core/kernel/vm.h +++ b/repos/base-hw/src/core/kernel/vm.h @@ -22,6 +22,8 @@ namespace Genode { class Vm_state; } #include "pd.h" #include "signal_receiver.h" +#include + namespace Kernel { /** @@ -36,19 +38,22 @@ class Kernel::Vm : public Cpu_job, { private: + using State = Board::Vm_state; + /* * Noncopyable */ Vm(Vm const &); Vm &operator = (Vm const &); - enum State { ACTIVE, INACTIVE }; + enum Scheduler_state { ACTIVE, INACTIVE }; - unsigned _id = 0; - Genode::Vm_state * const _state; - Signal_context * const _context; - void * const _table; - State _scheduled = INACTIVE; + unsigned _id = 0; + State & _state; + Signal_context & _context; + void * const _table; + Scheduler_state _scheduled = INACTIVE; + Board::Vcpu_context _vcpu_context; public: @@ -59,9 +64,10 @@ class Kernel::Vm : public Cpu_job, * \param context signal for VM exceptions other than interrupts * \param table translation table for guest to host physical memory */ - Vm(void * const state, - Signal_context * const context, - void * const table); + Vm(unsigned cpu, + State & state, + Signal_context & context, + void * const table); ~Vm(); @@ -84,12 +90,14 @@ class Kernel::Vm : public Cpu_job, * * \retval cap id when successful, otherwise invalid cap id */ - static capid_t syscall_create(void * const dst, void * const state, - capid_t const signal_context_id, - void * const table) + static capid_t syscall_create(Genode::Kernel_object & vm, + unsigned cpu, + void * const state, + capid_t const signal_context_id, + void * const table) { - return call(call_id_new_vm(), (Call_arg)dst, (Call_arg)state, - (Call_arg)table, signal_context_id); + return call(call_id_new_vm(), (Call_arg)&vm, (Call_arg)cpu, + (Call_arg)state, (Call_arg)table, signal_context_id); } /** @@ -99,8 +107,8 @@ class Kernel::Vm : public Cpu_job, * * \retval 0 when successful, otherwise !=0 */ - static void syscall_destroy(Vm * const vm) { - call(call_id_delete_vm(), (Call_arg) vm); } + static void syscall_destroy(Genode::Kernel_object & vm) { + call(call_id_delete_vm(), (Call_arg) &vm); } /**************** diff --git a/repos/base-hw/src/core/kernel/vm_thread_on.cc b/repos/base-hw/src/core/kernel/vm_thread_on.cc index 8252c9ded..dde209a14 100644 --- a/repos/base-hw/src/core/kernel/vm_thread_on.cc +++ b/repos/base-hw/src/core/kernel/vm_thread_on.cc @@ -18,13 +18,14 @@ void Kernel::Thread::_call_new_vm() { Signal_context * context = - pd().cap_tree().find(user_arg_4()); + pd().cap_tree().find(user_arg_5()); if (!context) { user_arg_0(cap_id_invalid()); return; } - _call_new((void*)user_arg_2(), context, (void*)user_arg_3()); + _call_new((unsigned)user_arg_2(), *(Board::Vm_state*)user_arg_3(), + *context, (void*)user_arg_4()); } diff --git a/repos/base-hw/src/core/object.h b/repos/base-hw/src/core/object.h index 7461a4dc0..701c08f8e 100644 --- a/repos/base-hw/src/core/object.h +++ b/repos/base-hw/src/core/object.h @@ -15,7 +15,7 @@ #define _CORE__OBJECT_H_ /* Genode includes */ -#include +#include /* base-internal includes */ #include @@ -35,13 +35,8 @@ namespace Genode { template -class Genode::Kernel_object +class Genode::Kernel_object : public Genode::Constructible> { - private: - - uint8_t _data[sizeof(Kernel::Core_object)] - __attribute__((aligned(sizeof(addr_t)))); - protected: Untyped_capability _cap { }; @@ -55,15 +50,17 @@ class Genode::Kernel_object */ template Kernel_object(bool syscall, ARGS &&... args) - : _cap(Capability_space::import(syscall ? T::syscall_create(&_data, args...) + : _cap(Capability_space::import(syscall ? T::syscall_create(*this, args...) : Kernel::cap_id_invalid())) { - if (!syscall) construct_at(&_data, args...); + if (!syscall) Genode::Constructible>::construct(args...); } - ~Kernel_object() { T::syscall_destroy(kernel_object()); } - - T * kernel_object() { return reinterpret_cast(_data); } + ~Kernel_object() + { + if (Genode::Constructible>::constructed()) + T::syscall_destroy(*this); + } Untyped_capability cap() { return _cap; } @@ -73,8 +70,10 @@ class Genode::Kernel_object template bool create(ARGS &&... args) { - if (_cap.valid()) return false; - _cap = Capability_space::import(T::syscall_create(&_data, args...)); + if (Genode::Constructible>::constructed()) + return false; + + _cap = Capability_space::import(T::syscall_create(*this, args...)); return _cap.valid(); } }; diff --git a/repos/base-hw/src/core/pager.cc b/repos/base-hw/src/core/pager.cc index 43da9bdc7..d4ebbcf50 100644 --- a/repos/base-hw/src/core/pager.cc +++ b/repos/base-hw/src/core/pager.cc @@ -53,12 +53,12 @@ void Pager_object::wake_up() if (pt) pt->restart(); } -void Pager_object::start_paging(Kernel::Signal_receiver * receiver) +void Pager_object::start_paging(Kernel_object & receiver) { using Object = Kernel_object; using Entry = Object_pool::Entry; - create(receiver, (unsigned long)this); + create(*receiver, (unsigned long)this); Entry::cap(Object::_cap); } @@ -103,13 +103,13 @@ void Pager_entrypoint::dissolve(Pager_object &o) Pager_entrypoint::Pager_entrypoint(Rpc_cap_factory &) : Thread_deprecated("pager_ep"), - Kernel_object(true) + _kobj(true) { start(); } Pager_capability Pager_entrypoint::manage(Pager_object &o) { - o.start_paging(kernel_object()); + o.start_paging(_kobj); insert(&o); return reinterpret_cap_cast(o.cap()); } diff --git a/repos/base-hw/src/core/platform_pd.cc b/repos/base-hw/src/core/platform_pd.cc index d5976538a..3ae9ab583 100644 --- a/repos/base-hw/src/core/platform_pd.cc +++ b/repos/base-hw/src/core/platform_pd.cc @@ -69,26 +69,29 @@ void Hw::Address_space::flush(addr_t virt, size_t size, Core_local_addr) try { _tt.remove_translation(virt, size, _tt_alloc); - Kernel::invalidate_tlb(&_kernel_pd, virt, size); + Kernel::invalidate_tlb(*_kobj, virt, size); } catch(...) { error("tried to remove invalid region!"); } } -Hw::Address_space::Address_space(Kernel::Pd & pd, Page_table & tt, - Page_table::Allocator & tt_alloc) -: _tt(tt), _tt_phys(Platform::core_page_table()), - _tt_alloc(tt_alloc), _kernel_pd(pd) { } +Hw::Address_space::Address_space(Page_table & tt, + Page_table::Allocator & tt_alloc, + Platform_pd & pd) +: _tt(tt), + _tt_phys(Platform::core_page_table()), + _tt_alloc(tt_alloc), + _kobj(false, *(Page_table*)translation_table_phys(), pd) {} -Hw::Address_space::Address_space(Kernel::Pd & pd) +Hw::Address_space::Address_space(Platform_pd & pd) : _tt(*construct_at(_table_alloc(), *((Page_table*)Hw::Mm::core_page_tables().base))), _tt_phys((addr_t)_cma().phys_addr(&_tt)), _tt_array(new (_cma()) Array([] (void * virt) { return (addr_t)_cma().phys_addr(virt);})), _tt_alloc(_tt_array->alloc()), - _kernel_pd(pd) { } + _kobj(true, *(Page_table*)translation_table_phys(), pd) { } Hw::Address_space::~Address_space() @@ -142,20 +145,13 @@ void Platform_pd::assign_parent(Native_capability parent) Platform_pd::Platform_pd(Page_table & tt, Page_table::Allocator & alloc) -: - Hw::Address_space(*kernel_object(), tt, alloc), - Kernel_object(false, *(Page_table*)translation_table_phys(), *this), - _label("core") -{ } +: Hw::Address_space(tt, alloc, *this), _label("core") { } Platform_pd::Platform_pd(Allocator &, char const *label) -: - Hw::Address_space(*kernel_object()), - Kernel_object(true, *(Page_table*)translation_table_phys(), *this), - _label(label) +: Hw::Address_space(*this), _label(label) { - if (!_cap.valid()) { + if (!_kobj.cap().valid()) { error("failed to create kernel object"); throw Service_denied(); } diff --git a/repos/base-hw/src/core/platform_thread.cc b/repos/base-hw/src/core/platform_thread.cc index a2169f4aa..07aee03e1 100644 --- a/repos/base-hw/src/core/platform_thread.cc +++ b/repos/base-hw/src/core/platform_thread.cc @@ -54,7 +54,7 @@ Platform_thread::~Platform_thread() void Platform_thread::quota(size_t const quota) { _quota = quota; - Kernel::thread_quota(_kobj.kernel_object(), quota); + Kernel::thread_quota(*_kobj, quota); } @@ -158,8 +158,8 @@ int Platform_thread::start(void * const ip, void * const sp) } /* initialize thread registers */ - _kobj.kernel_object()->regs->ip = reinterpret_cast(ip); - _kobj.kernel_object()->regs->sp = reinterpret_cast(sp); + _kobj->regs->ip = reinterpret_cast(ip); + _kobj->regs->sp = reinterpret_cast(sp); /* start executing new thread */ if (!_pd) { @@ -179,8 +179,7 @@ int Platform_thread::start(void * const ip, void * const sp) utcb.cap_add(Capability_space::capid(_pd->parent())); utcb.cap_add(Capability_space::capid(_utcb)); } - Kernel::start_thread(_kobj.kernel_object(), cpu, &_pd->kernel_pd(), - _utcb_core_addr); + Kernel::start_thread(*_kobj, cpu, _pd->kernel_pd(), *_utcb_core_addr); return 0; } @@ -189,7 +188,7 @@ void Platform_thread::pager(Pager_object &pager) { using namespace Kernel; - thread_pager(_kobj.kernel_object(), Capability_space::capid(pager.cap())); + thread_pager(*_kobj, Capability_space::capid(pager.cap())); _pager = &pager; } @@ -205,14 +204,14 @@ Genode::Pager_object &Platform_thread::pager() Thread_state Platform_thread::state() { - Thread_state bstate(*_kobj.kernel_object()->regs); + Thread_state bstate(*_kobj->regs); return Thread_state(bstate); } void Platform_thread::state(Thread_state thread_state) { - Cpu_state * cstate = static_cast(&*_kobj.kernel_object()->regs); + Cpu_state * cstate = static_cast(&*_kobj->regs); *cstate = static_cast(thread_state); } diff --git a/repos/base-hw/src/core/region_map_support.cc b/repos/base-hw/src/core/region_map_support.cc index d14c5058b..b045056cf 100644 --- a/repos/base-hw/src/core/region_map_support.cc +++ b/repos/base-hw/src/core/region_map_support.cc @@ -36,7 +36,7 @@ void Pager_entrypoint::entry() if (cap.valid()) Kernel::ack_signal(Capability_space::capid(cap)); /* receive fault */ - if (Kernel::await_signal(Capability_space::capid(_cap))) continue; + if (Kernel::await_signal(Capability_space::capid(_kobj.cap()))) continue; Pager_object *po = *(Pager_object**)Thread::myself()->utcb()->data(); cap = po->cap(); diff --git a/repos/base-hw/src/core/signal_source_component.h b/repos/base-hw/src/core/signal_source_component.h index 1ee8ab150..103927fa5 100644 --- a/repos/base-hw/src/core/signal_source_component.h +++ b/repos/base-hw/src/core/signal_source_component.h @@ -55,19 +55,21 @@ struct Genode::Signal_source_component : private Kernel_object(true), - Signal_source_pool::Entry(Kernel_object::_cap) + : Kernel_object(true), + Signal_source_pool::Entry(Kernel_object::cap()) { } void submit(Signal_context_component *, unsigned long) { ASSERT_NEVER_CALLED; } + + Kernel::Signal_receiver & signal_receiver() { + return **static_cast*>(this); } }; Genode::Signal_context_component::Signal_context_component(Signal_source_component &s, addr_t const imprint) : - Kernel_object(true, s.kernel_object(), imprint), + Kernel_object(true, s.signal_receiver(), imprint), Signal_context_pool::Entry(Kernel_object::_cap) { } diff --git a/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc b/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc index 85894c625..14418c634 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc +++ b/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc @@ -12,6 +12,7 @@ */ #include +#include #include @@ -21,41 +22,109 @@ Board::Pic::Pic() bool Board::Pic::take_request(unsigned & irq) { - Core0_irq_source::access_t src = read(); + unsigned cpu = Genode::Cpu::executing_id(); + Core_irq_source<0>::access_t src = 0; + switch (cpu) { + case 0: src = read>(); break; + case 1: src = read>(); break; + case 2: src = read>(); break; + case 3: src = read>(); break; + } + if ((1 << TIMER_IRQ) & src) { irq = TIMER_IRQ; return true; } + + if (0xf0 & src) { + irq = IPI; + switch (cpu) { + case 0: write>(1); break; + case 1: write>(1); break; + case 2: write>(1); break; + case 3: write>(1); break; + } + return true; + } + return false; } -void Board::Pic::mask() { } +void Board::Pic::_timer_irq(unsigned cpu, bool enable) +{ + unsigned v = enable ? 1 : 0; + switch (cpu) { + case 0: + write::Cnt_p_ns_irq>(v); + return; + case 1: + write::Cnt_p_ns_irq>(v); + return; + case 2: + write::Cnt_p_ns_irq>(v); + return; + case 3: + write::Cnt_p_ns_irq>(v); + return; + default: ; + } +} + + +void Board::Pic::_ipi(unsigned cpu, bool enable) +{ + unsigned v = enable ? 1 : 0; + switch (cpu) { + case 0: + write>(v); + return; + case 1: + write>(v); + return; + case 2: + write>(v); + return; + case 3: + write>(v); + return; + default: ; + } +} void Board::Pic::unmask(unsigned const i, unsigned cpu) { - if (cpu > 0) - Genode::raw("multi-core irq controller not implemented yet"); - - if (i == TIMER_IRQ) { - write(1); - return; + switch (i) { + case TIMER_IRQ: _timer_irq(cpu, true); return; + case IPI: _ipi(cpu, true); return; } - Genode::raw("irq of peripherals != timer not implemented yet!"); + Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")"); } void Board::Pic::mask(unsigned const i) { - if (i == TIMER_IRQ) { - write(0); - return; + unsigned cpu = Genode::Cpu::executing_id(); + switch (i) { + case TIMER_IRQ: _timer_irq(cpu, false); return; + case IPI: _ipi(cpu, false); return; } - Genode::raw("irq of peripherals != timer not implemented yet!"); + Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")"); } void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { } + + +void Board::Pic::send_ipi(unsigned cpu_target) +{ + switch (cpu_target) { + case 0: write>(1); return; + case 1: write>(1); return; + case 2: write>(1); return; + case 3: write>(1); return; + } +} diff --git a/repos/base-hw/src/core/spec/arm/bcm2837_pic.h b/repos/base-hw/src/core/spec/arm/bcm2837_pic.h index f5f65998f..64e6fe2de 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2837_pic.h +++ b/repos/base-hw/src/core/spec/arm/bcm2837_pic.h @@ -23,43 +23,45 @@ class Board::Pic : Genode::Mmio public: enum { + IPI = 0, NR_OF_IRQ = 64, - - /* - * dummy IPI value on non-SMP platform, - * only used in interrupt reservation within generic code - */ - IPI, }; private: - struct Core0_timer_irq_control : Register<0x40, 32> + template + struct Core_timer_irq_control : Register<0x40+CPU_NUM*0x4, 32> { - struct Cnt_p_ns_irq : Bitfield<1, 1> {}; + struct Cnt_p_ns_irq + : Register<0x40+CPU_NUM*0x4, 32>::template Bitfield<1, 1> {}; }; - struct Core1_timer_irq_control : Register<0x44, 32> {}; - struct Core2_timer_irq_control : Register<0x48, 32> {}; - struct Core3_timer_irq_control : Register<0x4c, 32> {}; + template + struct Core_mailbox_irq_control : Register<0x50+CPU_NUM*0x4, 32> {}; - struct Core0_irq_source : Register<0x60, 32> {}; - struct Core1_irq_source : Register<0x64, 32> {}; - struct Core2_irq_source : Register<0x68, 32> {}; - struct Core3_irq_source : Register<0x6c, 32> {}; + template + struct Core_irq_source : Register<0x60+CPU_NUM*0x4, 32> {}; + + template + struct Core_mailbox_set : Register<0x80+CPU_NUM*0x10, 32> {}; + + template + struct Core_mailbox_clear : Register<0xc0+CPU_NUM*0x10, 32> {}; + + void _ipi(unsigned cpu, bool enable); + void _timer_irq(unsigned cpu, bool enable); public: Pic(); - void init_cpu_local(); bool take_request(unsigned &irq); void finish_request() { } - void mask(); void unmask(unsigned const i, unsigned); void mask(unsigned const i); void irq_mode(unsigned, unsigned, unsigned); + void send_ipi(unsigned); static constexpr bool fast_interrupts() { return false; } }; diff --git a/repos/base-hw/src/core/spec/arm/gicv3.cc b/repos/base-hw/src/core/spec/arm/gicv3.cc index 1e0a02c7b..c0b2f284f 100644 --- a/repos/base-hw/src/core/spec/arm/gicv3.cc +++ b/repos/base-hw/src/core/spec/arm/gicv3.cc @@ -17,11 +17,16 @@ using namespace Genode; +static inline Genode::addr_t redistributor_addr() +{ + return Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE + + (Cpu::executing_id() * 0x20000)); +}; + Hw::Pic::Pic() : _distr(Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE)), - _redistr(Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE)), - _redistr_sgi(Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE) - + Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE / 2), + _redistr(redistributor_addr()), + _redistr_sgi(redistributor_addr() + 0x10000), _max_irq(_distr.max_irq()) { _redistributor_init(); 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 cd3d61391..dd6cb5ac5 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/thread.cc @@ -104,9 +104,11 @@ void Thread::user_arg_1(Kernel::Call_arg const arg) { regs->r1 = arg; } void Thread::user_arg_2(Kernel::Call_arg const arg) { regs->r2 = arg; } void Thread::user_arg_3(Kernel::Call_arg const arg) { regs->r3 = arg; } void Thread::user_arg_4(Kernel::Call_arg const arg) { regs->r4 = arg; } +void Thread::user_arg_5(Kernel::Call_arg const arg) { regs->r5 = arg; } Kernel::Call_arg Thread::user_arg_0() const { return regs->r0; } Kernel::Call_arg Thread::user_arg_1() const { return regs->r1; } Kernel::Call_arg Thread::user_arg_2() const { return regs->r2; } Kernel::Call_arg Thread::user_arg_3() const { return regs->r3; } Kernel::Call_arg Thread::user_arg_4() const { return regs->r4; } +Kernel::Call_arg Thread::user_arg_5() const { return regs->r5; } diff --git a/repos/base-hw/src/core/spec/arm/trustzone_board.h b/repos/base-hw/src/core/spec/arm/trustzone_board.h new file mode 100644 index 000000000..6f589b426 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/trustzone_board.h @@ -0,0 +1,33 @@ +/* + * \brief Board driver + * \author Stefan Kalkowski + * \date 2019-11-11 + */ + +/* + * Copyright (C) 2019 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 _CORE__SPEC__ARM_TRUSTZONE_BOARD_H_ +#define _CORE__SPEC__ARM_TRUSTZONE_BOARD_H_ + +#include + +namespace Kernel { class Cpu; } + +namespace Board { + using Genode::Vm_state; + + enum { VCPU_MAX = 1 }; + + struct Vm_page_table {}; + struct Vm_page_table_array {}; + + struct Pic : Hw::Pic { struct Virtual_context {}; }; + struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} }; +} + +#endif /* _CORE__SPEC__ARM_TRUSTZONE_BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/arm/virtualization/gicv2.cc b/repos/base-hw/src/core/spec/arm/virtualization/gicv2.cc new file mode 100644 index 000000000..9d3cb8fe2 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/virtualization/gicv2.cc @@ -0,0 +1,62 @@ +/* + * \brief Gicv2 with virtualization extensions + * \author Stefan Kalkowski + * \date 2019-09-02 + */ + +/* + * Copyright (C) 2019 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 + +using Board::Pic; + +Pic::Gich::Gich() +: Genode::Mmio(Genode::Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_VT_CTRL_BASE)) { } + + +bool Pic::ack_virtual_irq(Pic::Virtual_context & c) +{ + c.misr = _gich.read(); + c.vmcr = _gich.read(); + c.apr = _gich.read(); + c.eisr = _gich.read(); + c.elrsr = _gich.read(); + c.lr = _gich.read(); + _gich.write(0); + + if (c.eisr & 1) { + c.lr = 0; + c.elrsr = 0xffffffff; + c.misr = 0; + c.eisr = 0; + return true; + } + + return false; +} + + +void Pic::insert_virtual_irq(Pic::Virtual_context & c, unsigned irq) +{ + enum { SPURIOUS = 1023 }; + + if (irq != SPURIOUS && !c.lr) { + c.elrsr &= 0x7ffffffe; + c.lr = irq | 1 << 28 | 1 << 19; + } + + _gich.write(c.misr); + _gich.write(c.vmcr); + _gich.write(c.apr); + _gich.write(c.elrsr); + _gich.write(c.lr); + _gich.write(0b1); +} diff --git a/repos/base-hw/src/core/spec/arm/virtualization/gicv2.h b/repos/base-hw/src/core/spec/arm/virtualization/gicv2.h new file mode 100644 index 000000000..c1bfb7842 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/virtualization/gicv2.h @@ -0,0 +1,55 @@ +/* + * \brief Gicv2 with virtualization extensions + * \author Stefan Kalkowski + * \date 2019-09-02 + */ + +/* + * Copyright (C) 2019 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 _CORE__SPEC__ARM__VIRTUALIZATION__GICV2_H_ +#define _CORE__SPEC__ARM__VIRTUALIZATION__GICV2_H_ + +#include + +namespace Board { struct Pic; }; + + +class Board::Pic : public Hw::Gicv2 +{ + private: + + struct Gich : Genode::Mmio + { + struct Gich_hcr : Register<0x00, 32> { }; + struct Gich_vmcr : Register<0x08, 32> { }; + struct Gich_misr : Register<0x10, 32> { }; + struct Gich_eisr0 : Register<0x20, 32> { }; + struct Gich_elrsr0 : Register<0x30, 32> { }; + struct Gich_apr : Register<0xf0, 32> { }; + struct Gich_lr0 : Register<0x100, 32> { }; + + Gich(); + } _gich {}; + + public: + + struct Virtual_context + { + Genode::uint32_t lr { 0 }; + Genode::uint32_t apr { 0 }; + Genode::uint32_t vmcr { 0x4c0000 }; + Genode::uint32_t misr { 0 }; + Genode::uint32_t eisr { 0 }; + Genode::uint32_t elrsr { 0xffffffff }; + }; + + bool ack_virtual_irq(Virtual_context & c); + void insert_virtual_irq(Virtual_context & c, unsigned irq); +}; + +#endif /* _CORE__SPEC__ARM__VIRTUALIZATION__GICV2_H_ */ diff --git a/repos/base-hw/src/core/spec/arm/virtualization/gicv3.h b/repos/base-hw/src/core/spec/arm/virtualization/gicv3.h new file mode 100644 index 000000000..0302bf334 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/virtualization/gicv3.h @@ -0,0 +1,56 @@ +/* + * \brief Gicv2 with virtualization extensions + * \author Stefan Kalkowski + * \date 2019-09-02 + */ + +/* + * Copyright (C) 2019 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 _CORE__SPEC__ARM__VIRTUALIZATION__GICV3_H_ +#define _CORE__SPEC__ARM__VIRTUALIZATION__GICV3_H_ + +#include + +namespace Board { class Pic; }; + +class Board::Pic : public Hw::Pic +{ + public: + + struct Virtual_context { + Genode::uint64_t lr { 0 }; + Genode::uint32_t apr { 0 }; + Genode::uint32_t vmcr { 0x4c0000 }; + Genode::uint32_t misr { 0 }; + Genode::uint32_t eisr { 0 }; + Genode::uint32_t elrsr { 0xffffffff }; + }; + + bool ack_virtual_irq(Virtual_context & c) + { + if (!(c.eisr & 1)) return false; + + c.lr = 0; + c.elrsr = 0xffffffff; + c.misr = 0; + c.eisr = 0; + return true; + } + + void insert_virtual_irq(Virtual_context & c, unsigned irq) + { + enum { SPURIOUS = 1023 }; + + if (irq == SPURIOUS || c.lr) return; + + c.lr = irq | 1ULL << 41 | 1ULL << 60 | 1ULL << 62; + } +}; + +#endif /* _CORE__SPEC__ARM__VIRTUALIZATION__GICV3_H_ */ + diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/platform_services.cc b/repos/base-hw/src/core/spec/arm/virtualization/platform_services.cc similarity index 70% rename from repos/base-hw/src/core/spec/arm_v7/virtualization/platform_services.cc rename to repos/base-hw/src/core/spec/arm/virtualization/platform_services.cc index 43e3757a8..78fd3176d 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/platform_services.cc +++ b/repos/base-hw/src/core/spec/arm/virtualization/platform_services.cc @@ -37,9 +37,19 @@ void Genode::platform_add_local_services(Rpc_entrypoint &ep, using namespace Genode; map_local(Platform::core_phys_addr((addr_t)&hypervisor_exception_vector), - Hw::Mm::hypervisor_exception_vector().base, 1, + Hw::Mm::hypervisor_exception_vector().base, + Hw::Mm::hypervisor_exception_vector().size / get_page_size(), Hw::PAGE_FLAGS_KERN_TEXT); + void * stack = nullptr; + assert(platform().ram_alloc().alloc_aligned(Hw::Mm::hypervisor_stack().size, + (void**)&stack, + get_page_size_log2()).ok()); + map_local((addr_t)stack, + Hw::Mm::hypervisor_stack().base, + Hw::Mm::hypervisor_stack().size / get_page_size(), + Hw::PAGE_FLAGS_KERN_DATA); + static Vm_root vm_root(ep, sh, core_env().ram_allocator(), core_env().local_rm(), trace_sources); static Core_service vm_service(services, vm_root); diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc b/repos/base-hw/src/core/spec/arm/virtualization/vm_session_component.cc similarity index 72% rename from repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc rename to repos/base-hw/src/core/spec/arm/virtualization/vm_session_component.cc index 35cf28b83..c80d4dc47 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm/virtualization/vm_session_component.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include using namespace Genode; @@ -26,14 +27,6 @@ static Core_mem_allocator & cma() { return static_cast(platform().core_mem_alloc()); } -void Vm_session_component::_exception_handler(Signal_context_capability handler, Vcpu_id) -{ - if (!create(_ds_addr, Capability_space::capid(handler), - cma().phys_addr(&_table))) - Genode::warning("Cannot instantiate vm kernel object, invalid signal context?"); -} - - void Vm_session_component::_attach(addr_t phys_addr, addr_t vm_addr, size_t size) { using namespace Hw; @@ -78,8 +71,8 @@ void * Vm_session_component::_alloc_table() { void * table; /* get some aligned space for the translation table */ - if (!cma().alloc_aligned(sizeof(Table), (void**)&table, - Table::ALIGNM_LOG2).ok()) { + if (!cma().alloc_aligned(sizeof(Board::Vm_page_table), (void**)&table, + Board::Vm_page_table::ALIGNM_LOG2).ok()) { error("failed to allocate kernel object"); throw Insufficient_ram_quota(); } @@ -95,26 +88,16 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep, Region_map ®ion_map, unsigned, Trace::Source_registry &) -: - Ram_quota_guard(resources.ram_quota), - Cap_quota_guard(resources.cap_quota), - _ep(ds_ep), - _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), - _sliced_heap(_constrained_md_ram_alloc, region_map), - _region_map(region_map), - _table(*construct_at(_alloc_table())), - _table_array(*(new (cma()) Array([this] (void * virt) { - return (addr_t)cma().phys_addr(virt);}))) +: Ram_quota_guard(resources.ram_quota), + Cap_quota_guard(resources.cap_quota), + _ep(ds_ep), + _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), + _sliced_heap(_constrained_md_ram_alloc, region_map), + _region_map(region_map), + _table(*construct_at(_alloc_table())), + _table_array(*(new (cma()) Board::Vm_page_table_array([this] (void * virt) { + return (addr_t)cma().phys_addr(virt);}))) { - _ds_cap = _constrained_md_ram_alloc.alloc(_ds_size(), Genode::Cache_attribute::UNCACHED); - - try { - _ds_addr = region_map.attach(_ds_cap); - } catch (...) { - _constrained_md_ram_alloc.free(_ds_cap); - throw; - } - /* configure managed VM area */ _map.add_range(0, 0UL - 0x1000); _map.add_range(0UL - 0x1000, 0x1000); @@ -134,9 +117,12 @@ Vm_session_component::~Vm_session_component() } /* free region in allocator */ - if (_ds_cap.valid()) { - _region_map.detach(_ds_addr); - _constrained_md_ram_alloc.free(_ds_cap); + for (unsigned i = 0; i < _id_alloc; i++) { + Vcpu & vcpu = _vcpus[i]; + if (vcpu.ds_cap.valid()) { + _region_map.detach(vcpu.ds_addr); + _constrained_md_ram_alloc.free(vcpu.ds_cap); + } } /* free guest-to-host page tables */ 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 38e6fd966..4d7957d0c 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 @@ -20,13 +20,16 @@ using namespace Kernel; -Kernel::Vm::Vm(void * const state, - Kernel::Signal_context * const context, - void * const /* table */) +Kernel::Vm::Vm(unsigned, + Genode::Vm_state & state, + Kernel::Signal_context & context, + void * const) : Cpu_job(Cpu_priority::MIN, 0), - _state((Genode::Vm_state *)state), - _context(context), _table(0) + _state(state), + _context(context), + _table(0), + _vcpu_context(cpu_pool().primary_cpu()) { affinity(cpu_pool().primary_cpu()); } @@ -37,16 +40,17 @@ Kernel::Vm::~Vm() {} void Vm::exception(Cpu & cpu) { - switch(_state->cpu_exception) { - case Genode::Cpu_state::INTERRUPT_REQUEST: + switch(_state.cpu_exception) { + case Genode::Cpu_state::INTERRUPT_REQUEST: [[fallthrough]] case Genode::Cpu_state::FAST_INTERRUPT_REQUEST: _interrupt(cpu.id()); return; case Genode::Cpu_state::DATA_ABORT: - _state->dfar = Cpu::Dfar::read(); + _state.dfar = Cpu::Dfar::read(); + [[fallthrough]]; default: pause(); - _context->submit(1); + _context.submit(1); } } @@ -54,22 +58,21 @@ void Vm::exception(Cpu & cpu) bool secure_irq(unsigned const i); -extern "C" void monitor_mode_enter_normal_world(Cpu::Context*, void*); +extern "C" void monitor_mode_enter_normal_world(Genode::Vm_state&, void*); extern void * kernel_stack; void Vm::proceed(Cpu & cpu) { - unsigned const irq = _state->irq_injection; + unsigned const irq = _state.irq_injection; if (irq) { if (cpu.pic().secure(irq)) { Genode::raw("Refuse to inject secure IRQ into VM"); } else { cpu.pic().trigger(irq); - _state->irq_injection = 0; + _state.irq_injection = 0; } } - monitor_mode_enter_normal_world(reinterpret_cast(_state), - (void*) cpu.stack_start()); + monitor_mode_enter_normal_world(_state, (void*) cpu.stack_start()); } diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc index 2ceff5179..08ec48d9d 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc @@ -11,24 +11,44 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include +/* Genode includes */ +#include + +/* core includes */ #include -#include +#include using namespace Genode; - -void Vm_session_component::_exception_handler(Signal_context_capability handler, Vcpu_id) +static Board::Vm_page_table_array & dummy_array() { - if (!create(_ds_addr, Capability_space::capid(handler), nullptr)) - { - warning("Cannot instantiate vm kernel object twice," - "or invalid signal context?"); - } + static Board::Vm_page_table_array a; + return a; } -Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep, +void Vm_session_component::_attach(addr_t, addr_t, size_t) { } + + +void Vm_session_component::_attach_vm_memory(Dataspace_component &, + addr_t const, + Attach_attr const) { } + + +void Vm_session_component::attach_pic(addr_t) { } + + +void Vm_session_component::_detach_vm_memory(addr_t, size_t) { } + + +void * Vm_session_component::_alloc_table() +{ + static Board::Vm_page_table table; + return (void*) &table; +} + + +Vm_session_component::Vm_session_component(Rpc_entrypoint &ep, Resources resources, Label const &, Diag, @@ -38,26 +58,32 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep, : Ram_quota_guard(resources.ram_quota), Cap_quota_guard(resources.cap_quota), - _ds_ep(&ds_ep), + _ep(ep), _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), - _region_map(region_map) -{ - _ds_cap = _constrained_md_ram_alloc.alloc(_ds_size(), Genode::Cache_attribute::UNCACHED); - - try { - _ds_addr = region_map.attach(_ds_cap); - } catch (...) { - _constrained_md_ram_alloc.free(_ds_cap); - throw; - } -} + _sliced_heap(_constrained_md_ram_alloc, region_map), + _region_map(region_map), + _table(*construct_at(_alloc_table())), + _table_array(dummy_array()) { } Vm_session_component::~Vm_session_component() { + /* detach all regions */ + while (true) { + addr_t out_addr = 0; + + if (!_map.any_block_addr(&out_addr)) + break; + + detach(out_addr); + } + /* free region in allocator */ - if (_ds_cap.valid()) { - _region_map.detach(_ds_addr); - _constrained_md_ram_alloc.free(_ds_cap); + for (unsigned i = 0; i < _id_alloc; i++) { + Vcpu & vcpu = _vcpus[i]; + if (vcpu.ds_cap.valid()) { + _region_map.detach(vcpu.ds_addr); + _constrained_md_ram_alloc.free(vcpu.ds_cap); + } } } diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h deleted file mode 100644 index 4f778d842..000000000 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * \brief Core-specific instance of the VM session interface - * \author Stefan Kalkowski - * \date 2012-10-08 - */ - -/* - * Copyright (C) 2012-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 _CORE__SPEC__ARM_V7__TRUSTZONE__VM_SESSION_COMPONENT_H_ -#define _CORE__SPEC__ARM_V7__TRUSTZONE__VM_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* Core includes */ -#include -#include - -namespace Genode { - class Vm_session_component; -} - -class Genode::Vm_session_component -: - private Ram_quota_guard, - private Cap_quota_guard, - public Rpc_object, - private Kernel_object -{ - private: - - /* - * Noncopyable - */ - Vm_session_component(Vm_session_component const &); - Vm_session_component &operator = (Vm_session_component const &); - - Rpc_entrypoint *_ds_ep; - Constrained_ram_allocator _constrained_md_ram_alloc; - Region_map &_region_map; - Ram_dataspace_capability _ds_cap { }; - Region_map::Local_addr _ds_addr { 0 }; - - static size_t _ds_size() { - return align_addr(sizeof(Cpu_state_modes), - get_page_size_log2()); } - - addr_t _alloc_ds(); - - protected: - - Ram_quota_guard &_ram_quota_guard() { return *this; } - Cap_quota_guard &_cap_quota_guard() { return *this; } - - public: - - using Ram_quota_guard::upgrade; - using Cap_quota_guard::upgrade; - using Rpc_object::cap; - - Vm_session_component(Rpc_entrypoint &, Resources, Label const &, - Diag, Ram_allocator &ram, Region_map &, - unsigned priority, Trace::Source_registry &); - ~Vm_session_component(); - - /************************** - ** Vm session interface ** - **************************/ - - Dataspace_capability _cpu_state(Vcpu_id) { return _ds_cap; } - void _exception_handler(Signal_context_capability handler, Vcpu_id); - void _run(Vcpu_id); - void _pause(Vcpu_id); - - void attach(Dataspace_capability, addr_t, Attach_attr) override { - warning("Not implemented for TrustZone case"); } - - void attach_pic(addr_t /* vm_addr */) override { - warning("Not implemented for TrustZone case"); } - - void detach(addr_t /* vm_addr */, size_t /* size */) override { - warning("Not implemented for TrustZone case"); } - void _create_vcpu(Thread_capability) {} -}; - -#endif /* _CORE__SPEC__ARM_V7__TRUSTZONE__VM_SESSION_COMPONENT_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 a256d366b..255236c26 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 @@ -41,7 +41,7 @@ using namespace Kernel; extern "C" void kernel(); extern void * kernel_stack; -extern "C" void hypervisor_enter_vm(Cpu::Context*); +extern "C" void hypervisor_enter_vm(Genode::Vm_state&); struct Host_context { addr_t sp; @@ -103,18 +103,18 @@ struct Kernel::Virtual_pic : Genode::Mmio /** * Save the virtual interrupt controller state to VM state */ - static void save (Genode::Vm_state *s) + static void save (Genode::Vm_state &s) { - s->gic_hcr = pic().read(); - s->gic_misr = pic().read(); - s->gic_vmcr = pic().read(); - s->gic_apr = pic().read(); - s->gic_eisr = pic().read(); - s->gic_elrsr0 = pic().read(); - s->gic_lr[0] = pic().read >(); - s->gic_lr[1] = pic().read >(); - s->gic_lr[2] = pic().read >(); - s->gic_lr[3] = pic().read >(); + s.gic_hcr = pic().read(); + s.gic_misr = pic().read(); + s.gic_vmcr = pic().read(); + s.gic_apr = pic().read(); + s.gic_eisr = pic().read(); + s.gic_elrsr0 = pic().read(); + s.gic_lr[0] = pic().read >(); + s.gic_lr[1] = pic().read >(); + s.gic_lr[2] = pic().read >(); + s.gic_lr[3] = pic().read >(); /* disable virtual PIC CPU interface */ pic().write(0); @@ -123,17 +123,17 @@ struct Kernel::Virtual_pic : Genode::Mmio /** * Load the virtual interrupt controller state from VM state */ - static void load (Genode::Vm_state *s) + static void load (Genode::Vm_state &s) { - pic().write(s->gic_hcr ); - pic().write(s->gic_misr); - pic().write(s->gic_vmcr); - pic().write(s->gic_apr ); - pic().write(s->gic_elrsr0); - pic().write >(s->gic_lr[0]); - pic().write >(s->gic_lr[1]); - pic().write >(s->gic_lr[2]); - pic().write >(s->gic_lr[3]); + pic().write(s.gic_hcr ); + pic().write(s.gic_misr); + pic().write(s.gic_vmcr); + pic().write(s.gic_apr ); + pic().write(s.gic_elrsr0); + pic().write >(s.gic_lr[0]); + pic().write >(s.gic_lr[1]); + pic().write >(s.gic_lr[2]); + pic().write >(s.gic_lr[3]); } }; @@ -166,25 +166,25 @@ struct Kernel::Virtual_timer /** * Save the virtual timer state to VM state */ - static void save(Genode::Vm_state *s) + static void save(Genode::Vm_state &s) { asm volatile("mrc p15, 0, %0, c14, c3, 0 \n" "mrc p15, 0, %1, c14, c3, 1" : - "=r" (s->timer_val), "=r" (s->timer_ctrl)); + "=r" (s.timer_val), "=r" (s.timer_ctrl)); } /** * Load the virtual timer state from VM state */ - static void load(Genode::Vm_state *s) + static void load(Genode::Vm_state &s) { - if (s->timer_irq) timer().irq.enable(); + if (s.timer_irq) timer().irq.enable(); asm volatile("mcr p15, 0, %0, c14, c3, 1 \n" "mcr p15, 0, %1, c14, c3, 0 \n" "mcr p15, 0, %2, c14, c3, 1" :: "r" (0), - "r" (s->timer_val), "r" (s->timer_ctrl)); + "r" (s.timer_val), "r" (s.timer_ctrl)); } }; @@ -205,14 +205,16 @@ static Vmid_allocator &alloc() } -Kernel::Vm::Vm(void * const state, - Kernel::Signal_context * const context, +Kernel::Vm::Vm(unsigned, /* FIXME: smp support */ + Genode::Vm_state & state, + Kernel::Signal_context & context, void * const table) : Cpu_job(Cpu_priority::MIN, 0), _id(alloc().alloc()), - _state((Genode::Vm_state *)state), + _state(state), _context(context), - _table(table) + _table(table), + _vcpu_context(cpu_pool().primary_cpu()) { affinity(cpu_pool().primary_cpu()); Virtual_pic::pic().irq.enable(); @@ -235,15 +237,15 @@ void Kernel::Vm::exception(Cpu & cpu) { Virtual_timer::save(_state); - switch(_state->cpu_exception) { + switch(_state.cpu_exception) { case Genode::Cpu_state::INTERRUPT_REQUEST: case Genode::Cpu_state::FAST_INTERRUPT_REQUEST: - _state->gic_irq = Board::VT_MAINTAINANCE_IRQ; + _state.gic_irq = Board::VT_MAINTAINANCE_IRQ; _interrupt(cpu.id()); break; default: pause(); - _context->submit(1); + _context.submit(1); } Virtual_pic::save(_state); @@ -256,27 +258,27 @@ void Kernel::Vm::proceed(Cpu &) /* * the following values have to be enforced by the hypervisor */ - _state->vttbr = Cpu::Ttbr_64bit::Ba::masked((Cpu::Ttbr_64bit::access_t)_table); - Cpu::Ttbr_64bit::Asid::set(_state->vttbr, _id); + _state.vttbr = Cpu::Ttbr_64bit::Ba::masked((Cpu::Ttbr_64bit::access_t)_table); + Cpu::Ttbr_64bit::Asid::set(_state.vttbr, _id); /* * use the following report fields not needed for loading the context * to transport the HSTR and HCR register descriptions into the assembler * path in a dense way */ - _state->hsr = Cpu::Hstr::init(); - _state->hpfar = Cpu::Hcr::init(); + _state.hsr = Cpu::Hstr::init(); + _state.hpfar = Cpu::Hcr::init(); Virtual_pic::load(_state); Virtual_timer::load(_state); - hypervisor_enter_vm(reinterpret_cast(_state)); + hypervisor_enter_vm(_state); } void Vm::inject_irq(unsigned irq) { - _state->gic_irq = irq; + _state.gic_irq = irq; pause(); - _context->submit(1); + _context.submit(1); } diff --git a/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc deleted file mode 100644 index a2125e665..000000000 --- a/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* - * \brief VM session component for 'base-hw' - * \author Stefan Kalkowski - * \date 2012-10-08 - */ - -/* - * Copyright (C) 2012-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 - -using namespace Genode; - - -addr_t Vm_session_component::_alloc_ds() -{ - addr_t addr; - if (platform().ram_alloc().alloc_aligned(_ds_size(), (void**)&addr, - get_page_size_log2()).error()) - throw Insufficient_ram_quota(); - return addr; -} - - -void Vm_session_component::_run(Vcpu_id) -{ - if (Kernel_object::_cap.valid()) - Kernel::run_vm(kernel_object()); -} - - -void Vm_session_component::_pause(Vcpu_id) -{ - if (Kernel_object::_cap.valid()) - Kernel::pause_vm(kernel_object()); -} 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 ed1284488..73505d8c9 100644 --- a/repos/base-hw/src/core/spec/arm_v8/cpu.h +++ b/repos/base-hw/src/core/spec/arm_v8/cpu.h @@ -83,7 +83,7 @@ struct Genode::Cpu : Hw::Arm_64_cpu /** * Return kernel name of the executing CPU */ - static unsigned executing_id() { return 0; } + static unsigned executing_id() { return Cpu::Mpidr::read() & 0xff; } static void clean_data_cache_by_virt_region(addr_t, size_t); diff --git a/repos/base-hw/src/core/spec/arm_v8/exception_vector.s b/repos/base-hw/src/core/spec/arm_v8/exception_vector.s index d96c35e59..2454b8a26 100644 --- a/repos/base-hw/src/core/spec/arm_v8/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm_v8/exception_vector.s @@ -77,6 +77,7 @@ _kernel_entry: .global idle_thread_main idle_thread_main: + wfi b idle_thread_main 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 d8f2e0de8..196bf10e4 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 @@ -136,9 +136,11 @@ void Thread::user_arg_1(Kernel::Call_arg const arg) { regs->r[1] = arg; } void Thread::user_arg_2(Kernel::Call_arg const arg) { regs->r[2] = arg; } void Thread::user_arg_3(Kernel::Call_arg const arg) { regs->r[3] = arg; } void Thread::user_arg_4(Kernel::Call_arg const arg) { regs->r[4] = arg; } +void Thread::user_arg_5(Kernel::Call_arg const arg) { regs->r[5] = arg; } Kernel::Call_arg Thread::user_arg_0() const { return regs->r[0]; } Kernel::Call_arg Thread::user_arg_1() const { return regs->r[1]; } Kernel::Call_arg Thread::user_arg_2() const { return regs->r[2]; } Kernel::Call_arg Thread::user_arg_3() const { return regs->r[3]; } Kernel::Call_arg Thread::user_arg_4() const { return regs->r[4]; } +Kernel::Call_arg Thread::user_arg_5() const { return regs->r[5]; } 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 new file mode 100644 index 000000000..8011bfeea --- /dev/null +++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s @@ -0,0 +1,369 @@ +/* + * \brief Transition between virtual/host mode + * \author Alexander Boettcher + * \author Stefan Kalkowski + * \date 2019-06-25 + */ + +/* + * Copyright (C) 2019 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. + */ + + +.section .text + +/* + * see D1.10.2 Exception vectors chapter + */ +.p2align 12 +.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 + .balign 128 + .endr + +_host_to_vm: + + add sp, sp, #-16 /* push arg2 (vm pic state) to stack */ + str x2, [sp] + + msr vttbr_el2, x3 /* stage2 table pointer was arg3 */ + + add x0, x0, #31*8 /* skip x0...x30, loaded later */ + + ldr x1, [x0], #1*8 /* sp */ + ldp x2, x3, [x0], #2*8 /* ip, pstate */ + msr sp_el0, x1 + msr elr_el2, x2 + msr spsr_el2, x3 + + add x0, x0, #2*8 /* skip exception_type and esr_el2 */ + + /** FPU register **/ + ldp q0, q1, [x0], #2*16 + ldp q2, q3, [x0], #2*16 + ldp q4, q5, [x0], #2*16 + ldp q6, q7, [x0], #2*16 + ldp q8, q9, [x0], #2*16 + ldp q10, q11, [x0], #2*16 + ldp q12, q13, [x0], #2*16 + ldp q14, q15, [x0], #2*16 + ldp q16, q17, [x0], #2*16 + ldp q18, q19, [x0], #2*16 + ldp q20, q21, [x0], #2*16 + ldp q22, q23, [x0], #2*16 + ldp q24, q25, [x0], #2*16 + ldp q26, q27, [x0], #2*16 + ldp q28, q29, [x0], #2*16 + ldp q30, q31, [x0], #2*16 + ldp w1, w2, [x0], #2*4 + msr fpcr, x1 + msr fpsr, x2 + + /** system register **/ + ldp x1, x2, [x0], #2*8 /* elr_el1, sp_el1 */ + ldp w3, w4, [x0], #2*4 /* spsr_el1, esr_el1 */ + ldp x5, x6, [x0], #2*8 /* sctlr_el1, actlr_el1 */ + ldr x7, [x0], #8 /* vbar_el1 */ + ldp w8, w9, [x0], #2*4 /* cpacr_el1, afsr0_el1 */ + ldp w10, w11, [x0], #2*4 /* afsr1_el1, contextidr_el1 */ + ldp x12, x13, [x0], #2*8 /* ttbr0_el1, ttbr1_el1 */ + ldp x14, x15, [x0], #2*8 /* tcr_el1, mair_el1 */ + ldp x16, x17, [x0], #2*8 /* amair_el1, far_el1 */ + ldp x18, x19, [x0], #2*8 /* par_el1, tpidrro_el0 */ + ldp x20, x21, [x0], #2*8 /* tpidr_el0, tpidr_el1 */ + ldr x22, [x0], #3*8 /* vmpidr_el2 */ + msr elr_el1, x1 + msr sp_el1, x2 + msr spsr_el1, x3 + msr esr_el1, x4 + msr sctlr_el1, x5 + msr actlr_el1, x6 + msr vbar_el1, x7 + msr cpacr_el1, x8 + msr afsr0_el1, x9 + msr afsr1_el1, x10 + msr contextidr_el1, x11 + msr ttbr0_el1, x12 + msr ttbr1_el1, x13 + msr tcr_el1, x14 + msr mair_el1, x15 + msr amair_el1, x16 + msr far_el1, x17 + msr par_el1, x18 + msr tpidrro_el0, x19 + msr tpidr_el0, x20 + msr tpidr_el1, x21 + msr vmpidr_el2, x22 + + + /********************** + ** load timer state ** + **********************/ + + ldp x22, x23, [x0], #2*8 /* timer.offset, timer.compare */ + ldp w24, w25, [x0] /* timer.control, kcontrol */ + msr cntvoff_el2, x22 + msr cntv_cval_el0, x23 + msr cntv_ctl_el0, x24 + msr cntkctl_el1, x25 + + mov x0, #0b100 + msr cnthctl_el2, x0 + + + /************************ + ** debug/perfm access ** + ************************/ + + mrs x0, mdcr_el2 + movz x1, #0b111101100000 + orr x0, x0, x1 + msr mdcr_el2, x0 + + + /********************** + ** Load pic context ** + **********************/ + + ldr x0, [sp] + + ldr x1, [x0], #8 /* lr0 */ + ldp w2, w3, [x0] /* apr, vmcr */ + + msr S3_4_C12_C12_0, x1 + msr S3_4_C12_C9_0, x2 + msr S3_4_C12_C11_7, x3 + + mov x0, #1 /* enable PIC virtualization */ + msr S3_4_C12_C11_0, x0 + + /** enable VM mode **/ + movz x1, #0b1110000000111001 + movk x1, #0b10111, lsl 16 + mrs x0, hcr_el2 + orr x0, x0, x1 + msr hcr_el2, x0 + + ldr x30, [sp, #16] /* load head of Vm_state again */ + + /** general-purpose registers **/ + ldp x0, x1, [x30], #2*8 + ldp x2, x3, [x30], #2*8 + ldp x4, x5, [x30], #2*8 + ldp x6, x7, [x30], #2*8 + ldp x8, x9, [x30], #2*8 + ldp x10, x11, [x30], #2*8 + ldp x12, x13, [x30], #2*8 + ldp x14, x15, [x30], #2*8 + ldp x16, x17, [x30], #2*8 + ldp x18, x19, [x30], #2*8 + ldp x20, x21, [x30], #2*8 + ldp x22, x23, [x30], #2*8 + ldp x24, x25, [x30], #2*8 + ldp x26, x27, [x30], #2*8 + ldp x28, x29, [x30], #2*8 + ldr x30, [x30] + + eret + +_vm_to_host: + + /********************* + ** 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 x28, x29, [x0], #2*8 + str x30, [x0], #1*8 + + /** save sp, ip, pstate and exception reason **/ + mrs x2, sp_el0 + mrs x3, elr_el2 + mrs x4, spsr_el2 + mrs x5, esr_el2 + stp x2, x3, [x0], #2*8 + stp x4, x1, [x0], #2*8 + str x5, [x0], #1*8 + + /** fpu registers **/ + stp q0, q1, [x0], #32 + stp q2, q3, [x0], #32 + stp q4, q5, [x0], #32 + stp q6, q7, [x0], #32 + stp q8, q9, [x0], #32 + stp q10, q11, [x0], #32 + stp q12, q13, [x0], #32 + stp q14, q15, [x0], #32 + stp q16, q17, [x0], #32 + stp q18, q19, [x0], #32 + stp q20, q21, [x0], #32 + stp q22, q23, [x0], #32 + stp q24, q25, [x0], #32 + stp q26, q27, [x0], #32 + stp q28, q29, [x0], #32 + stp q30, q31, [x0], #32 + + mrs x1, fpcr + mrs x2, fpsr + mrs x3, elr_el1 + mrs x4, sp_el1 + mrs x5, spsr_el1 + mrs x6, esr_el1 + mrs x7, sctlr_el1 + mrs x8, actlr_el1 + mrs x9, vbar_el1 + mrs x10, cpacr_el1 + mrs x11, afsr0_el1 + mrs x12, afsr1_el1 + mrs x13, contextidr_el1 + mrs x14, ttbr0_el1 + mrs x15, ttbr1_el1 + mrs x16, tcr_el1 + mrs x17, mair_el1 + mrs x18, amair_el1 + mrs x19, far_el1 + mrs x20, par_el1 + mrs x21, tpidrro_el0 + mrs x22, tpidr_el0 + mrs x23, tpidr_el1 + mrs x24, far_el2 + mrs x25, hpfar_el2 + stp w1, w2, [x0], #2*4 + stp x3, x4, [x0], #2*8 + stp w5, w6, [x0], #2*4 + stp x7, x8, [x0], #2*8 + str x9, [x0], #1*8 + stp w10, w11, [x0], #2*4 + stp w12, w13, [x0], #2*4 + 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], #3*8 + stp x24, x25, [x0], #2*8 + + + /********************** + ** save timer state ** + **********************/ + + mrs x26, cntvoff_el2 + mrs x27, cntv_cval_el0 + mrs x28, cntv_ctl_el0 + mrs x29, cntkctl_el1 + stp x26, x27, [x0], #2*8 + stp w28, w29, [x0] + + 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 */ + + + /********************** + ** Save pic context ** + **********************/ + + mrs x10, S3_4_C12_C12_0 + mrs x11, S3_4_C12_C9_0 + mrs x12, S3_4_C12_C11_7 + mrs x13, S3_4_C12_C11_2 + mrs x14, S3_4_C12_C11_3 + mrs x15, S3_4_C12_C11_5 + + str x10, [x29], #8 /* lr0 */ + stp w11, w12, [x29], #2*4 /* apr, vmcr */ + stp w13, w14, [x29], #2*4 /* misr, eisr */ + str w15, [x29] /* elrsr */ + + msr S3_4_C12_C11_0, xzr /* disable PIC virtualization */ + + + /*********************** + ** Load host context ** + ***********************/ + + add x30, x30, #32*8 /* skip general-purpose regs, sp */ + ldp x0, x1, [x30] /* host state ip, and pstate */ + add x30, x30, #34*16 /* skip fpu regs etc. */ + ldp w2, w3, [x30], #4*4 /* fpcr and fpsr */ + ldr x4, [x30], #2*8 /* sp_el1 */ + ldp x5, x6, [x30], #2*8 /* sctlr_el1, actlr_el1 */ + ldr x7, [x30], #1*8 /* vbar_el1 */ + ldr w8, [x30], #4*4 /* cpacr_el1 */ + ldp x9, x10, [x30], #2*8 /* ttbr0_el1, ttbr1_el1 */ + ldp x11, x12, [x30], #2*8 /* tcr_el1, mair_el1 */ + ldr x13, [x30] /* amair_el1 */ + + msr elr_el2, x0 + msr spsr_el2, x1 + msr fpcr, x2 + msr fpsr, x3 + msr sp_el1, x4 + msr sctlr_el1, x5 + msr actlr_el1, x6 + msr vbar_el1, x7 + msr cpacr_el1, x8 + msr ttbr0_el1, x9 + msr ttbr1_el1, x10 + msr tcr_el1, x11 + msr mair_el1, x12 + msr amair_el1, x13 + mrs x0, mpidr_el1 + msr vmpidr_el2, x0 + + + /************************ + ** debug/perfm access ** + ************************/ + + mrs x0, mdcr_el2 + movz x1, #0b111101100000 + bic x0, x0, x1 + msr mdcr_el2, x0 + + /** disable VM mode **/ + movz x1, #0b1110000000111001 + movk x1, #0b10111, lsl 16 + mrs x0, hcr_el2 + msr vttbr_el2, xzr /* stage2 table pointer zeroing */ + bic x0, x0, x1 + msr hcr_el2, x0 + + eret + +/* host kernel must jump to this point to switch to a vm */ +.global hypervisor_enter_vm +hypervisor_enter_vm: + hvc #0 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 new file mode 100644 index 000000000..58810fcdb --- /dev/null +++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc @@ -0,0 +1,215 @@ +/* + * \brief Kernel backend for virtual machines + * \author Stefan Kalkowski + * \date 2015-02-10 + */ + +/* + * Copyright (C) 2015-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 +#include +#include +#include +#include +#include + +using Genode::addr_t; +using Kernel::Cpu; +using Kernel::Vm; + +extern "C" void kernel(); +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() +{ + static Genode::Constructible host_context; + if (!host_context.constructed()) { + host_context.construct(); + host_context->ip = (addr_t) &kernel; + host_context->pstate = 0; + Cpu::Spsr::Sp::set(host_context->pstate, 1); /* select non-el0 stack pointer */ + Cpu::Spsr::El::set(host_context->pstate, Cpu::Current_el::EL1); + Cpu::Spsr::F::set(host_context->pstate, 1); + Cpu::Spsr::I::set(host_context->pstate, 1); + Cpu::Spsr::A::set(host_context->pstate, 1); + Cpu::Spsr::D::set(host_context->pstate, 1); + host_context->fpcr = Cpu::Fpcr::read(); + host_context->fpsr = 0; + host_context->sctlr_el1 = Cpu::Sctlr_el1::read(); + host_context->actlr_el1 = Cpu::Actlr_el1::read(); + host_context->vbar_el1 = Cpu::Vbar_el1::read(); + host_context->cpacr_el1 = Cpu::Cpacr_el1::read(); + host_context->ttbr0_el1 = Cpu::Ttbr0_el1::read(); + host_context->ttbr1_el1 = Cpu::Ttbr1_el1::read(); + host_context->tcr_el1 = Cpu::Tcr_el1::read(); + host_context->mair_el1 = Cpu::Mair_el1::read(); + host_context->amair_el1 = Cpu::Amair_el1::read(); + } + return *host_context; +} + + +Board::Vcpu_context::Vm_irq::Vm_irq(unsigned const irq, Cpu & cpu) +: Kernel::Irq(irq, cpu.irq_pool()) +{ } + + +void Board::Vcpu_context::Vm_irq::handle(Cpu &, Vm & vm, unsigned irq) { + vm.inject_irq(irq); } + + +void Board::Vcpu_context::Vm_irq::occurred() +{ + Cpu & cpu = Kernel::cpu_pool().executing_cpu(); + Vm *vm = dynamic_cast(&cpu.scheduled_job()); + if (!vm) Genode::raw("VM interrupt while VM is not runnning!"); + else handle(cpu, *vm, _irq_nr); +} + + +Board::Vcpu_context::Pic_maintainance_irq::Pic_maintainance_irq(Cpu & cpu) +: Board::Vcpu_context::Vm_irq(Board::VT_MAINTAINANCE_IRQ, cpu) { + //FIXME Irq::enable only enables caller cpu + cpu.pic().unmask(_irq_nr, cpu.id()); } + +Board::Vcpu_context::Virtual_timer_irq::Virtual_timer_irq(Cpu & cpu) +: irq(Board::VT_TIMER_IRQ, cpu) {} + + +void Board::Vcpu_context::Virtual_timer_irq::enable() { irq.enable(); } + + +void Board::Vcpu_context::Virtual_timer_irq::disable() +{ + irq.disable(); + asm volatile("msr cntv_ctl_el0, xzr"); + asm volatile("msr cntkctl_el1, %0" :: "r" (0b11)); +} + + +using Vmid_allocator = Genode::Bit_allocator<256>; + +static Vmid_allocator &alloc() +{ + static Vmid_allocator * allocator = nullptr; + if (!allocator) { + allocator = unmanaged_singleton(); + + /* reserve VM ID 0 for the hypervisor */ + unsigned id = allocator->alloc(); + assert (id == 0); + } + return *allocator; +} + + +Vm::Vm(unsigned cpu, + Genode::Vm_state & state, + Kernel::Signal_context & context, + void * const table) +: Cpu_job(Cpu_priority::MIN, 0), + _id(alloc().alloc()), + _state(state), + _context(context), + _table(table), + _vcpu_context(cpu_pool().cpu(cpu)) +{ + affinity(cpu_pool().cpu(cpu)); + + _state.id_aa64isar0_el1 = Cpu::Id_aa64isar0_el1::read(); + _state.id_aa64isar1_el1 = Cpu::Id_aa64isar1_el1::read(); + _state.id_aa64mmfr0_el1 = Cpu::Id_aa64mmfr0_el1::read(); + _state.id_aa64mmfr1_el1 = Cpu::Id_aa64mmfr1_el1::read(); + _state.id_aa64mmfr2_el1 = /* FIXME Cpu::Id_aa64mmfr2_el1::read(); */ 0; + + Cpu::Clidr_el1::access_t clidr = Cpu::Clidr_el1::read(); + for (unsigned i = 0; i < 7; i++) { + unsigned level = clidr >> (i*3) & 0b111; + + if (level == Cpu::Clidr_el1::NO_CACHE) break; + + if ((level == Cpu::Clidr_el1::INSTRUCTION_CACHE) || + (level == Cpu::Clidr_el1::SEPARATE_CACHE)) { + Cpu::Csselr_el1::access_t csselr = 0; + Cpu::Csselr_el1::Instr::set(csselr, 1); + Cpu::Csselr_el1::Level::set(csselr, level); + Cpu::Csselr_el1::write(csselr); + _state.ccsidr_inst_el1[level] = Cpu::Ccsidr_el1::read(); + } + + if (level != Cpu::Clidr_el1::INSTRUCTION_CACHE) { + Cpu::Csselr_el1::write(Cpu::Csselr_el1::Level::bits(level)); + _state.ccsidr_data_el1[level] = Cpu::Ccsidr_el1::read(); + } + } +} + + +Vm::~Vm() { alloc().free(_id); } + + +void Vm::exception(Cpu & cpu) +{ + switch (_state.exception_type) { + case Cpu::IRQ_LEVEL_EL0: [[fallthrough]] + case Cpu::IRQ_LEVEL_EL1: [[fallthrough]] + case Cpu::FIQ_LEVEL_EL0: [[fallthrough]] + case Cpu::FIQ_LEVEL_EL1: + _interrupt(cpu.id()); + break; + case Cpu::SYNC_LEVEL_EL0: [[fallthrough]] + case Cpu::SYNC_LEVEL_EL1: [[fallthrough]] + case Cpu::SERR_LEVEL_EL0: [[fallthrough]] + case Cpu::SERR_LEVEL_EL1: + pause(); + _context.submit(1); + break; + default: + Genode::raw("Exception vector: ", (void*)_state.exception_type, + " not implemented!"); + }; + + if (cpu.pic().ack_virtual_irq(_vcpu_context.pic)) + inject_irq(Board::VT_MAINTAINANCE_IRQ); + _vcpu_context.vtimer_irq.disable(); +} + + +void Vm::proceed(Cpu & cpu) +{ + if (_state.timer.irq) _vcpu_context.vtimer_irq.enable(); + + cpu.pic().insert_virtual_irq(_vcpu_context.pic, _state.irqs.virtual_irq); + + /* + * the following values have to be enforced by the hypervisor + */ + Cpu::Vttbr_el2::access_t vttbr_el2 = + Cpu::Vttbr_el2::Ba::masked((Cpu::Vttbr_el2::access_t)_table); + Cpu::Vttbr_el2::Asid::set(vttbr_el2, _id); + addr_t guest = Hw::Mm::el2_addr(&_state); + addr_t pic = Hw::Mm::el2_addr(&_vcpu_context.pic); + addr_t host = Hw::Mm::el2_addr(&host_context()); + host_context().sp_el1 = cpu.stack_start(); + + hypervisor_enter_vm(guest, host, pic, vttbr_el2); +} + +void Vm::inject_irq(unsigned irq) +{ + _state.irqs.last_irq = irq; + pause(); + _context.submit(1); +} diff --git a/repos/base-hw/src/core/spec/arndale/board.h b/repos/base-hw/src/core/spec/arndale/board.h index 2bcc73058..f45c010b7 100644 --- a/repos/base-hw/src/core/spec/arndale/board.h +++ b/repos/base-hw/src/core/spec/arndale/board.h @@ -17,11 +17,25 @@ #include #include #include +#include +#include +#include + +namespace Kernel { class Cpu; } namespace Board { using namespace Hw::Arndale_board; using Pic = Hw::Gicv2; + + enum { VCPU_MAX = 1 }; + + using Vm_state = Genode::Vm_state; + using Vm_page_table = Hw::Level_1_stage_2_translation_table; + using Vm_page_table_array = + Vm_page_table::Allocator::Array; + + struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} }; } #endif /* _CORE__SPEC__ARNDALE__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/imx53_qsb/board.h b/repos/base-hw/src/core/spec/imx53_qsb/board.h index 018e076fa..241b84955 100644 --- a/repos/base-hw/src/core/spec/imx53_qsb/board.h +++ b/repos/base-hw/src/core/spec/imx53_qsb/board.h @@ -18,10 +18,8 @@ #include #include #include +#include -namespace Board { - using namespace Hw::Imx53_qsb_board; - using Hw::Pic; -} +namespace Board { using namespace Hw::Imx53_qsb_board; } #endif /* _CORE__SPEC__IMX53_QSB__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/imx6q_sabrelite/board.h b/repos/base-hw/src/core/spec/imx6q_sabrelite/board.h index 0176522ec..800304f37 100644 --- a/repos/base-hw/src/core/spec/imx6q_sabrelite/board.h +++ b/repos/base-hw/src/core/spec/imx6q_sabrelite/board.h @@ -26,6 +26,11 @@ namespace Board { using L2_cache = Hw::Pl310; L2_cache & l2_cache(); + + enum { + CORTEX_A9_PRIVATE_TIMER_CLK = 396000000, /* timer clk runs half the CPU freq */ + CORTEX_A9_PRIVATE_TIMER_DIV = 100, + }; } #endif /* _CORE__SPEC__WAND_QUAD__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/imx7d_sabre/board.h b/repos/base-hw/src/core/spec/imx7d_sabre/board.h index e5bb0a636..b5a32cb20 100644 --- a/repos/base-hw/src/core/spec/imx7d_sabre/board.h +++ b/repos/base-hw/src/core/spec/imx7d_sabre/board.h @@ -14,16 +14,28 @@ #ifndef _CORE__SPEC__IMX7D_SABRE__BOARD_H_ #define _CORE__SPEC__IMX7D_SABRE__BOARD_H_ -#include #include +#include #include +#include +#include +#include + +namespace Kernel { class Cpu; } namespace Board { using namespace Hw::Imx7d_sabre_board; - using Pic = Hw::Gicv2; + struct Virtual_local_pic {}; - enum { TIMER_IRQ = 30 }; + enum { TIMER_IRQ = 30, VCPU_MAX = 1 }; + + using Vm_state = Genode::Vm_state; + using Vm_page_table = Hw::Level_1_stage_2_translation_table; + using Vm_page_table_array = + Vm_page_table::Allocator::Array; + + struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} }; } #endif /* _CORE__SPEC__IMX7_SABRELITE__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/imx8q_evk/board.h b/repos/base-hw/src/core/spec/imx8q_evk/board.h index 35a58c826..805e5287c 100644 --- a/repos/base-hw/src/core/spec/imx8q_evk/board.h +++ b/repos/base-hw/src/core/spec/imx8q_evk/board.h @@ -15,14 +15,73 @@ #define _CORE__SPEC__IMX8Q_EVK__BOARD_H_ #include -#include #include +#include +#include +#include +#include +#include namespace Board { using namespace Hw::Imx8q_evk_board; - using Hw::Pic; - enum { TIMER_IRQ = 30 }; + enum { + TIMER_IRQ = 14 + 16, + VT_TIMER_IRQ = 11 + 16, + VT_MAINTAINANCE_IRQ = 9 + 16, + VCPU_MAX = 16 + }; + + using Vm_page_table = Hw::Level_1_stage_2_translation_table; + using Vm_page_table_array = + Vm_page_table::Allocator::Array; + + struct Vcpu_context; + + using Vm_state = Genode::Vm_state; +}; + +namespace Kernel { + class Cpu; + class Vm; +}; + +struct Board::Vcpu_context +{ + struct Vm_irq : Kernel::Irq + { + Vm_irq(unsigned const irq, Kernel::Cpu &); + virtual ~Vm_irq() {}; + + virtual void handle(Kernel::Cpu &, Kernel::Vm & vm, unsigned irq); + void occurred() override; + }; + + + struct Pic_maintainance_irq : Vm_irq + { + Pic_maintainance_irq(Kernel::Cpu &); + + void handle(Kernel::Cpu &, Kernel::Vm &, unsigned) override { } + }; + + + struct Virtual_timer_irq + { + Vm_irq irq; + + Virtual_timer_irq(Kernel::Cpu &); + + void enable(); + void disable(); + }; + + Vcpu_context(Kernel::Cpu & cpu) + : pic_irq(cpu), vtimer_irq(cpu) {} + + Pic::Virtual_context pic {}; + Pic_maintainance_irq pic_irq; + Virtual_timer_irq vtimer_irq; }; #endif /* _CORE__SPEC__IMX8Q_EVK__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/nit6_solox/board.h b/repos/base-hw/src/core/spec/nit6_solox/board.h index 6f75b227e..2d94bfb60 100644 --- a/repos/base-hw/src/core/spec/nit6_solox/board.h +++ b/repos/base-hw/src/core/spec/nit6_solox/board.h @@ -25,6 +25,11 @@ namespace Board { using L2_cache = Hw::Pl310; L2_cache & l2_cache(); + + enum { + CORTEX_A9_PRIVATE_TIMER_CLK = 500000000, /* timer clk runs half the CPU freq */ + CORTEX_A9_PRIVATE_TIMER_DIV = 100, + }; } #endif /* _CORE__SPEC__NIT6_SOLOX__BOARD_H_ */ 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 e843499ce..fd81e095d 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/thread.cc @@ -84,8 +84,10 @@ void Thread::user_arg_1(Kernel::Call_arg const arg) { regs->a1 = arg; } void Thread::user_arg_2(Kernel::Call_arg const arg) { regs->a2 = arg; } void Thread::user_arg_3(Kernel::Call_arg const arg) { regs->a3 = arg; } void Thread::user_arg_4(Kernel::Call_arg const arg) { regs->a4 = arg; } +void Thread::user_arg_5(Kernel::Call_arg const arg) { regs->a5 = arg; } Kernel::Call_arg Thread::user_arg_0() const { return regs->a0; } Kernel::Call_arg Thread::user_arg_1() const { return regs->a1; } Kernel::Call_arg Thread::user_arg_2() const { return regs->a2; } Kernel::Call_arg Thread::user_arg_3() const { return regs->a3; } Kernel::Call_arg Thread::user_arg_4() const { return regs->a4; } +Kernel::Call_arg Thread::user_arg_5() const { return regs->a5; } diff --git a/repos/base-hw/src/core/spec/usb_armory/board.h b/repos/base-hw/src/core/spec/usb_armory/board.h index 9a4c30f6c..adb4446ec 100644 --- a/repos/base-hw/src/core/spec/usb_armory/board.h +++ b/repos/base-hw/src/core/spec/usb_armory/board.h @@ -18,10 +18,8 @@ #include #include #include +#include -namespace Board { - using namespace Hw::Usb_armory_board; - using Hw::Pic; -} +namespace Board { using namespace Hw::Usb_armory_board; } #endif /* _CORE__SPEC__USB_ARMORY__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/wand_quad/board.h b/repos/base-hw/src/core/spec/wand_quad/board.h index 1426385f9..792a86c47 100644 --- a/repos/base-hw/src/core/spec/wand_quad/board.h +++ b/repos/base-hw/src/core/spec/wand_quad/board.h @@ -26,6 +26,11 @@ namespace Board { using Pic = Hw::Gicv2; L2_cache & l2_cache(); + + enum { + CORTEX_A9_PRIVATE_TIMER_CLK = 500000000, /* timer clk runs half the CPU freq */ + CORTEX_A9_PRIVATE_TIMER_DIV = 100, + }; } #endif /* _CORE__SPEC__WAND_QUAD__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc index 4a075fb04..d15066152 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc @@ -22,8 +22,6 @@ void Kernel::Cpu::_arch_init() Idt::init(); Tss::init(); - Timer::init_cpu_local(); - /* enable timer interrupt */ _pic.store_apic_id(id()); _pic.unmask(_timer.interrupt_id(), id()); 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 efd97e625..bfc64ae7d 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 @@ -70,9 +70,11 @@ void Kernel::Thread::user_arg_1(Kernel::Call_arg const arg) { regs->rsi = arg; } void Kernel::Thread::user_arg_2(Kernel::Call_arg const arg) { regs->rdx = arg; } void Kernel::Thread::user_arg_3(Kernel::Call_arg const arg) { regs->rcx = arg; } void Kernel::Thread::user_arg_4(Kernel::Call_arg const arg) { regs->r8 = arg; } +void Kernel::Thread::user_arg_5(Kernel::Call_arg const arg) { regs->r9 = arg; } Kernel::Call_arg Kernel::Thread::user_arg_0() const { return regs->rdi; } Kernel::Call_arg Kernel::Thread::user_arg_1() const { return regs->rsi; } Kernel::Call_arg Kernel::Thread::user_arg_2() const { return regs->rdx; } Kernel::Call_arg Kernel::Thread::user_arg_3() const { return regs->rcx; } Kernel::Call_arg Kernel::Thread::user_arg_4() const { return regs->r8; } +Kernel::Call_arg Kernel::Thread::user_arg_5() const { return regs->r9; } diff --git a/repos/base-hw/src/core/spec/x86_64/muen/board.h b/repos/base-hw/src/core/spec/x86_64/muen/board.h index a9d939254..76eb31c96 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/board.h +++ b/repos/base-hw/src/core/spec/x86_64/muen/board.h @@ -17,6 +17,9 @@ #include #include #include +#include + +namespace Kernel { class Cpu; } namespace Board { using namespace Hw::Pc_board; @@ -33,6 +36,15 @@ namespace Board { TIMER_VECTOR_KERNEL = 32, TIMER_VECTOR_USER = 50, }; + + using Vm_state = Genode::Cpu_state; + + enum { VCPU_MAX = 1 }; + + struct Vm_page_table {}; + struct Vm_page_table_array {}; + + struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} }; } #endif /* _CORE__SPEC__X86_64__MUEN__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc index f3a32bd34..4f73871d2 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc @@ -17,14 +17,16 @@ #include #include #include -#include -Kernel::Vm::Vm(void * const state, Kernel::Signal_context * const context, +Kernel::Vm::Vm(unsigned, + Board::Vm_state & state, + Kernel::Signal_context & context, void * const) : Cpu_job(Cpu_priority::MIN, 0), - _state((Genode::Vm_state *) state), + _state(state), _context(context), - _table(nullptr) + _table(nullptr), + _vcpu_context(cpu_pool().primary_cpu()) { affinity(cpu_pool().primary_cpu()); } @@ -36,20 +38,20 @@ Kernel::Vm::~Vm() { } void Kernel::Vm::exception(Cpu & cpu) { pause(); - if (_state->trapno == 200) { - _context->submit(1); + if (_state.trapno == 200) { + _context.submit(1); return; } - if (_state->trapno >= Genode::Cpu_state::INTERRUPTS_START && - _state->trapno <= Genode::Cpu_state::INTERRUPTS_END) { - cpu.pic().irq_occurred(_state->trapno); + if (_state.trapno >= Genode::Cpu_state::INTERRUPTS_START && + _state.trapno <= Genode::Cpu_state::INTERRUPTS_END) { + cpu.pic().irq_occurred(_state.trapno); _interrupt(cpu.id()); - _context->submit(1); + _context.submit(1); return; } - Genode::raw("VM: triggered unknown exception ", _state->trapno, - " with error code ", _state->errcode); + Genode::raw("VM: triggered unknown exception ", _state.trapno, + " with error code ", _state.errcode); ASSERT_NEVER_CALLED; } @@ -57,7 +59,7 @@ void Kernel::Vm::exception(Cpu & cpu) void Kernel::Vm::proceed(Cpu & cpu) { - cpu.tss.ist[0] = (addr_t)_state + sizeof(Genode::Cpu_state); + cpu.tss.ist[0] = (addr_t)&_state + sizeof(Genode::Cpu_state); asm volatile("sti \n" "mov $1, %rax \n" diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm_state.h b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm_state.h deleted file mode 100644 index f9db21c7f..000000000 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm_state.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief CPU context of a virtual machine - * \author Stefan Kalkowski - * \date 2015-06-03 - */ - -/* - * Copyright (C) 2015-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 _CORE__SPEC__X86_64__MUEN__VM_STATE_H_ -#define _CORE__SPEC__X86_64__MUEN__VM_STATE_H_ - -namespace Genode -{ - struct Vm_state : Cpu_state {}; -} - -#endif /* _CORE__SPEC__X86_64__MUEN__VM_STATE_H_ */ diff --git a/repos/base-hw/src/core/spec/x86_64/muen/pic.h b/repos/base-hw/src/core/spec/x86_64/muen/pic.h index ef28aee6a..00f859138 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/pic.h +++ b/repos/base-hw/src/core/spec/x86_64/muen/pic.h @@ -26,6 +26,8 @@ class Board::Pic { public: + struct Virtual_context {}; + enum { /* * FIXME: dummy ipi value on non-SMP platform, should be removed diff --git a/repos/base-hw/src/core/spec/x86_64/muen/timer.cc b/repos/base-hw/src/core/spec/x86_64/muen/timer.cc index 4eb52f8f4..fbfd68f2c 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/timer.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/timer.cc @@ -56,9 +56,6 @@ Board::Timer::Timer(unsigned) : ticks_per_ms(sinfo()->get_tsc_khz()), start(0) } -void Timer::init_cpu_local() { } - - unsigned Timer::interrupt_id() const { return Board::TIMER_VECTOR_KERNEL; } diff --git a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.cc b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.cc new file mode 100644 index 000000000..265bf6097 --- /dev/null +++ b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.cc @@ -0,0 +1,89 @@ +/* + * \brief Core-specific instance of the VM session interface + * \author Stefan Kalkowski + * \date 2015-06-03 + */ + +/* + * Copyright (C) 2015-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. + */ + +/* Genode includes */ +#include + +/* core includes */ +#include +#include + +using namespace Genode; + +static Board::Vm_page_table_array & dummy_array() +{ + static Board::Vm_page_table_array a; + return a; +} + + +void Vm_session_component::_attach(addr_t, addr_t, size_t) { } + + +void Vm_session_component::_attach_vm_memory(Dataspace_component &, + addr_t const, + Attach_attr const) { } + + +void Vm_session_component::attach_pic(addr_t) { } + + +void Vm_session_component::_detach_vm_memory(addr_t, size_t) { } + + +void * Vm_session_component::_alloc_table() +{ + static Board::Vm_page_table table; + return (void*) &table; +} + + +Vm_session_component::Vm_session_component(Rpc_entrypoint &ep, + Resources resources, + Label const &, + Diag, + Ram_allocator &ram_alloc, + Region_map ®ion_map, + unsigned, Trace::Source_registry &) +: + Ram_quota_guard(resources.ram_quota), + Cap_quota_guard(resources.cap_quota), + _ep(ep), + _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), + _sliced_heap(_constrained_md_ram_alloc, region_map), + _region_map(region_map), + _table(*construct_at(_alloc_table())), + _table_array(dummy_array()) { } + + +Vm_session_component::~Vm_session_component() +{ + /* detach all regions */ + while (true) { + addr_t out_addr = 0; + + if (!_map.any_block_addr(&out_addr)) + break; + + detach(out_addr); + } + + /* free region in allocator */ + for (unsigned i = 0; i < _id_alloc; i++) { + Vcpu & vcpu = _vcpus[i]; + if (vcpu.ds_cap.valid()) { + _region_map.detach(vcpu.ds_addr); + _constrained_md_ram_alloc.free(vcpu.ds_cap); + } + } +} diff --git a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h deleted file mode 100644 index ee1774248..000000000 --- a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * \brief Core-specific instance of the VM session interface - * \author Stefan Kalkowski - * \date 2015-06-03 - */ - -/* - * Copyright (C) 2015-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 _CORE__SPEC__X86_64__MUEN__VM_SESSION_COMPONENT_H_ -#define _CORE__SPEC__X86_64__MUEN__VM_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* Core includes */ -#include -#include -#include -#include - -namespace Genode { - class Vm_session_component; -} - -class Genode::Vm_session_component -: - private Ram_quota_guard, - private Cap_quota_guard, - public Rpc_object, - private Kernel_object -{ - private: - - Vm_state _state; - - public: - - Vm_session_component(Rpc_entrypoint &, Resources resources, - Label const &, Diag, Ram_allocator &, - Region_map &, unsigned, - Trace::Source_registry &) - : - Ram_quota_guard(resources.ram_quota), - Cap_quota_guard(resources.cap_quota), - _state() - { } - - ~Vm_session_component() { } - - using Ram_quota_guard::upgrade; - using Cap_quota_guard::upgrade; - using Genode::Rpc_object::cap; - - /************************** - ** Vm session interface ** - **************************/ - - Dataspace_capability _cpu_state(Vcpu_id) { return Dataspace_capability(); } - - void _exception_handler(Signal_context_capability handler, Vcpu_id) - { - if (!create(&_state, Capability_space::capid(handler), nullptr)) - warning("Cannot instantiate vm kernel object, " - "invalid signal context?"); - } - - void _run(Vcpu_id) - { - if (Kernel_object::_cap.valid()) - Kernel::run_vm(kernel_object()); - } - - void _pause(Vcpu_id) - { - if (Kernel_object::_cap.valid()) - Kernel::pause_vm(kernel_object()); - } - - void attach(Dataspace_capability, addr_t, Attach_attr) override { } - void attach_pic(addr_t) override { } - void detach(addr_t, size_t) override { } - void _create_vcpu(Thread_capability) { } -}; - -#endif /* _CORE__SPEC__X86_64__MUEN__VM_SESSION_COMPONENT_H_ */ diff --git a/repos/base-hw/src/core/spec/x86_64/pit.cc b/repos/base-hw/src/core/spec/x86_64/pit.cc index da9ad8452..3ae318abb 100644 --- a/repos/base-hw/src/core/spec/x86_64/pit.cc +++ b/repos/base-hw/src/core/spec/x86_64/pit.cc @@ -75,11 +75,7 @@ Board::Timer::Timer(unsigned) /* Calculate timer frequency */ ticks_per_ms = pit_calc_timer_freq(); } -} - -void Timer::init_cpu_local() -{ /** * Disable PIT timer channel. This is necessary since BIOS sets up * channel 0 to fire periodically. diff --git a/repos/base-hw/src/core/vm_session_component.cc b/repos/base-hw/src/core/vm_session_component.cc new file mode 100644 index 000000000..4f7aa9153 --- /dev/null +++ b/repos/base-hw/src/core/vm_session_component.cc @@ -0,0 +1,114 @@ +/* + * \brief VM session component for 'base-hw' + * \author Stefan Kalkowski + * \date 2012-10-08 + */ + +/* + * Copyright (C) 2012-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. + */ + +/* Genode includes */ +#include + +/* core includes */ +#include +#include +#include +#include +#include + +using namespace Genode; + +static Core_mem_allocator & cma() { + return static_cast(platform().core_mem_alloc()); } + + +size_t Vm_session_component::_ds_size() { + return align_addr(sizeof(Board::Vm_state), get_page_size_log2()); } + + +addr_t Vm_session_component::_alloc_ds() +{ + addr_t addr; + if (platform().ram_alloc().alloc_aligned(_ds_size(), (void**)&addr, + get_page_size_log2()).error()) + throw Insufficient_ram_quota(); + return addr; +} + + +void Vm_session_component::_run(Vcpu_id id) +{ + if (_valid_id(id) && _vcpus[id.id].kobj.constructed()) + Kernel::run_vm(*_vcpus[id.id].kobj); +} + + +void Vm_session_component::_pause(Vcpu_id id) +{ + if (_valid_id(id) && _vcpus[id.id].kobj.constructed()) + Kernel::pause_vm(*_vcpus[id.id].kobj); +} + + +void Vm_session_component::_exception_handler(Signal_context_capability handler, + Vcpu_id id) +{ + if (!_valid_id(id)) { + Genode::warning("invalid vcpu id ", id.id); + return; + } + + Vcpu & vcpu = _vcpus[id.id]; + if (vcpu.kobj.constructed()) { + Genode::warning("Cannot register vcpu handler twice"); + return; + } + + unsigned const cpu = vcpu.location.valid() ? vcpu.location.xpos() : 0; + + if (!vcpu.kobj.create(cpu, vcpu.ds_addr, Capability_space::capid(handler), + cma().phys_addr(&_table))) + Genode::warning("Cannot instantiate vm kernel object, ", + "invalid signal context?"); +} + + +Vm_session::Vcpu_id Vm_session_component::_create_vcpu(Thread_capability tcap) +{ + using namespace Genode; + + if (_id_alloc == Board::VCPU_MAX) return Vcpu_id{Vcpu_id::INVALID}; + + Affinity::Location vcpu_location; + auto lambda = [&] (Cpu_thread_component *ptr) { + if (!ptr) return; + vcpu_location = ptr->platform_thread().affinity(); + }; + _ep.apply(tcap, lambda); + + Vcpu & vcpu = _vcpus[_id_alloc]; + vcpu.ds_cap = _constrained_md_ram_alloc.alloc(_ds_size(), + Cache_attribute::UNCACHED); + try { + vcpu.ds_addr = _region_map.attach(vcpu.ds_cap); + } catch (...) { + _constrained_md_ram_alloc.free(vcpu.ds_cap); + throw; + } + + vcpu.location = vcpu_location; + return Vcpu_id { _id_alloc++ }; +} + + +Genode::Dataspace_capability +Vm_session_component::_cpu_state(Vm_session::Vcpu_id id) +{ + return (_valid_id(id)) ? _vcpus[id.id].ds_cap + : Genode::Ram_dataspace_capability(); +} diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h b/repos/base-hw/src/core/vm_session_component.h similarity index 56% rename from repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h rename to repos/base-hw/src/core/vm_session_component.h index 58a627737..19dcc1506 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h +++ b/repos/base-hw/src/core/vm_session_component.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE__SPEC__ARM_V7__VIRTUALIZATION__VM_SESSION_COMPONENT_H_ -#define _CORE__SPEC__ARM_V7__VIRTUALIZATION__VM_SESSION_COMPONENT_H_ +#ifndef _CORE__VM_SESSION_COMPONENT_H_ +#define _CORE__VM_SESSION_COMPONENT_H_ /* Genode includes */ #include @@ -20,7 +20,6 @@ #include #include #include -#include /* Core includes */ #include @@ -38,9 +37,8 @@ class Genode::Vm_session_component : private Ram_quota_guard, private Cap_quota_guard, - public Rpc_object, - public Region_map_detach, - private Kernel_object + public Rpc_object, + public Region_map_detach { private: @@ -52,29 +50,31 @@ class Genode::Vm_session_component Vm_session_component(Vm_session_component const &); Vm_session_component &operator = (Vm_session_component const &); - using Table = Hw::Level_1_stage_2_translation_table; - using Array = Table::Allocator::Array; + struct Vcpu + { + Ram_dataspace_capability ds_cap { }; + Region_map::Local_addr ds_addr { nullptr }; + Kernel_object kobj {}; + Affinity::Location location {}; + } _vcpus[Board::VCPU_MAX]; - Rpc_entrypoint &_ep; - Constrained_ram_allocator _constrained_md_ram_alloc; - Sliced_heap _sliced_heap; - Avl_region _map { &_sliced_heap }; - Region_map &_region_map; - Ram_dataspace_capability _ds_cap { }; - Region_map::Local_addr _ds_addr { 0 }; - Table &_table; - Array &_table_array; + Rpc_entrypoint &_ep; + Constrained_ram_allocator _constrained_md_ram_alloc; + Sliced_heap _sliced_heap; + Avl_region _map { &_sliced_heap }; + Region_map &_region_map; + Board::Vm_page_table &_table; + Board::Vm_page_table_array &_table_array; + unsigned _id_alloc { 0 }; - static size_t _ds_size() { - return align_addr(sizeof(Cpu_state_modes), - get_page_size_log2()); } - - addr_t _alloc_ds(); - void * _alloc_table(); - void _attach(addr_t phys_addr, addr_t vm_addr, size_t size); - - void _attach_vm_memory(Dataspace_component &, addr_t, Attach_attr); - void _detach_vm_memory(addr_t, size_t); + static size_t _ds_size(); + bool _valid_id(Vcpu_id id) { return id.id < Board::VCPU_MAX; } + addr_t _alloc_ds(); + void * _alloc_table(); + void _attach(addr_t phys_addr, addr_t vm_addr, size_t size); + void _attach_vm_memory(Dataspace_component &, addr_t, + Attach_attr); + void _detach_vm_memory(addr_t, size_t); protected: @@ -103,14 +103,16 @@ class Genode::Vm_session_component ** Vm session interface ** **************************/ - Dataspace_capability _cpu_state(Vcpu_id) { return _ds_cap; } - void _exception_handler(Signal_context_capability, Vcpu_id); - void _run(Vcpu_id); - void _pause(Vcpu_id); void attach(Dataspace_capability, addr_t, Attach_attr) override; void attach_pic(addr_t) override; void detach(addr_t, size_t) override; - void _create_vcpu(Thread_capability) {} + + Dataspace_capability _cpu_state(Vcpu_id); + Vcpu_id _create_vcpu(Thread_capability); + void _exception_handler(Signal_context_capability, + Vcpu_id); + void _run(Vcpu_id); + void _pause(Vcpu_id); }; -#endif /* _CORE__SPEC__ARM_V7__VIRTUALIZATION__VM_SESSION_COMPONENT_H_ */ +#endif /* _CORE__VM_SESSION_COMPONENT_H_ */ diff --git a/repos/base-hw/src/include/hw/memory_map.h b/repos/base-hw/src/include/hw/memory_map.h index 7ed077309..377ee7422 100644 --- a/repos/base-hw/src/include/hw/memory_map.h +++ b/repos/base-hw/src/include/hw/memory_map.h @@ -30,6 +30,7 @@ namespace Hw { Memory_region const core_heap(); Memory_region const system_exception_vector(); Memory_region const hypervisor_exception_vector(); + Memory_region const hypervisor_stack(); Memory_region const supervisor_exception_vector(); Memory_region const boot_info(); } diff --git a/repos/base-hw/src/include/hw/spec/arm/gicv2.h b/repos/base-hw/src/include/hw/spec/arm/gicv2.h index c98065f56..0a72bc844 100644 --- a/repos/base-hw/src/include/hw/spec/arm/gicv2.h +++ b/repos/base-hw/src/include/hw/spec/arm/gicv2.h @@ -168,9 +168,7 @@ class Hw::Gicv2 Distributor _distr; Cpu_interface _cpui; Cpu_interface::Iar::access_t _last_iar; - unsigned const _max_irq; - - void _init(); + unsigned const _max_irq; bool _valid(unsigned const irq_id) const { return irq_id <= _max_irq; } diff --git a/repos/base-hw/src/include/hw/spec/arm/gicv3.h b/repos/base-hw/src/include/hw/spec/arm/gicv3.h index 7da0c2adb..ff13a7f92 100644 --- a/repos/base-hw/src/include/hw/spec/arm/gicv3.h +++ b/repos/base-hw/src/include/hw/spec/arm/gicv3.h @@ -60,35 +60,35 @@ class Hw::Pic struct Typer : Register<0x004, 32> { struct It_lines_number : Bitfield<0,5> { }; }; - struct Igroup0r : Register_array<0x80, 32, 32*32, 1> { + struct Igroup0r : Register_array<0x80, 32, nr_of_irq, 1> { struct Group1 : Bitfield<0, 1> { }; }; /** * Interrupt Set-Enable register */ - struct Isenabler : Register_array<0x100, 32, 32*32, 1, true> { + struct Isenabler : Register_array<0x100, 32, nr_of_irq, 1, true> { struct Set_enable : Bitfield<0, 1> { }; }; /** * Interrupt clear enable registers */ - struct Icenabler : Register_array<0x180, 32, 32*32, 1, true> { + struct Icenabler : Register_array<0x180, 32, nr_of_irq, 1, true> { struct Clear_enable : Bitfield<0, 1> { }; }; /** * Interrupt clear pending registers */ - struct Icpendr : Register_array<0x280, 32, 32*32, 1, true> { + struct Icpendr : Register_array<0x280, 32, nr_of_irq, 1, true> { struct Clear_pending : Bitfield<0, 1> { }; }; /** * Interrupt priority level registers */ - struct Ipriorityr : Register_array<0x400, 32, 255*4, 8> { + struct Ipriorityr : Register_array<0x400, 32, nr_of_irq, 8> { struct Priority : Bitfield<0, 8> { }; }; - struct Icfgr : Register_array<0xc00, 32, 64*16, 2> { + struct Icfgr : Register_array<0xc00, 32, nr_of_irq, 2> { struct Edge_triggered : Bitfield<1, 1> { }; }; struct Irouter : Register_array<0x6000, 64, 1020, 64, true> { }; @@ -132,13 +132,13 @@ class Hw::Pic { struct Igroupr0 : Register<0x80, 32> { }; - struct Isenabler0 : Register_array<0x100, 32, 32, 1> + struct Isenabler0 : Register_array<0x100, 32, min_spi, 1, true> { }; - struct Icenabler0 : Register_array<0x180, 32, 32, 1> + struct Icenabler0 : Register_array<0x180, 32, min_spi, 1, true> { }; - struct Icactiver0 : Register<0x380, 32> { }; + struct Icactiver0 : Register<0x380, 32, true> { }; struct Ipriorityr : Register_array<0x400, 32, min_spi, 8> { struct Priority : Bitfield<0, 8> { }; }; @@ -161,6 +161,7 @@ class Hw::Pic SYSTEM_REGISTER(32, Icc_pmr_el1, "S3_0_C4_C6_0"); SYSTEM_REGISTER(32, Icc_igrpen1_el1, "S3_0_C12_C12_7"); SYSTEM_REGISTER(32, Icc_eoir1_el1, "S3_0_C12_C12_1"); + SYSTEM_REGISTER(64, Icc_sgi1r_el1, "S3_0_C12_C11_5"); void init() { @@ -257,6 +258,11 @@ class Hw::Pic } void irq_mode(unsigned, unsigned, unsigned) { } + + void send_ipi(unsigned const cpu_id) + { + Cpu_interface::Icc_sgi1r_el1::write(1ULL << cpu_id); + } }; #undef SYSTEM_REGISTER diff --git a/repos/base-hw/src/include/hw/spec/arm_64/cpu.h b/repos/base-hw/src/include/hw/spec/arm_64/cpu.h index a867dd0ba..5dee63eb5 100644 --- a/repos/base-hw/src/include/hw/spec/arm_64/cpu.h +++ b/repos/base-hw/src/include/hw/spec/arm_64/cpu.h @@ -35,11 +35,31 @@ namespace Hw { struct Arm_64_cpu; } struct Hw::Arm_64_cpu { - SYSTEM_REGISTER(64, Id_pfr0, id_aa64pfr0_el1, - struct El2 : Bitfield<8, 4> {}; - struct El3 : Bitfield<8, 4> {}; + SYSTEM_REGISTER(64, Actlr_el1, actlr_el1); + SYSTEM_REGISTER(64, Amair_el1, amair_el1); + + SYSTEM_REGISTER(32, Ccsidr_el1, ccsidr_el1); + + SYSTEM_REGISTER(64, Clidr_el1, clidr_el1, + enum Cache_type { + NO_CACHE, + INSTRUCTION_CACHE, + DATA_CACHE, + SEPARATE_CACHE, + UNIFIED_CACHE + }; ); + SYSTEM_REGISTER(32, Csselr_el1, csselr_el1, + struct Instr : Bitfield<0, 1> {}; + struct Level : Bitfield<1, 3> {}; + ); + + SYSTEM_REGISTER(32, Cpacr_el1, cpacr_el1); + + SYSTEM_REGISTER(32, Cptr_el2, cptr_el2, + struct Tta : Bitfield<20, 1> {}; ); + SYSTEM_REGISTER(64, Current_el, currentel, enum Level { EL0, EL1, EL2, EL3 }; struct El : Bitfield<2, 2> {}; @@ -80,12 +100,27 @@ struct Hw::Arm_64_cpu SYSTEM_REGISTER(64, Esr_el1, esr_el1); SYSTEM_REGISTER(64, Far_el1, far_el1); + SYSTEM_REGISTER(32, Fpcr, fpcr); - SYSTEM_REGISTER(64, Hcr, hcr_el2, + SYSTEM_REGISTER(64, Hcr_el2, hcr_el2, struct Rw : Bitfield<31, 1> {}; ); - SYSTEM_REGISTER(64, Mair, mair_el1, + SYSTEM_REGISTER(32, Hstr_el2, hstr_el2); + + SYSTEM_REGISTER(64, Id_aa64isar0_el1, id_aa64isar0_el1); + SYSTEM_REGISTER(64, Id_aa64isar1_el1, id_aa64isar1_el1); + SYSTEM_REGISTER(64, Id_aa64mmfr0_el1, id_aa64mmfr0_el1); + SYSTEM_REGISTER(64, Id_aa64mmfr1_el1, id_aa64mmfr1_el1); + SYSTEM_REGISTER(64, Id_aa64mmfr2_el1, id_aa64mmfr2_el1); + + SYSTEM_REGISTER(64, Id_pfr0, id_aa64pfr0_el1, + struct El2 : Bitfield<8, 4> {}; + struct El3 : Bitfield<8, 4> {}; + ); + + struct Mair : Genode::Register<64> + { enum Attributes { DEVICE_MEMORY = 0x04, NORMAL_MEMORY_UNCACHED = 0x44, @@ -95,7 +130,12 @@ struct Hw::Arm_64_cpu struct Attr1 : Bitfield<8, 8> {}; struct Attr2 : Bitfield<16, 8> {}; struct Attr3 : Bitfield<24, 8> {}; - ); + }; + + SYSTEM_REGISTER(64, Mair_el1, mair_el1); + SYSTEM_REGISTER(64, Mair_el2, mair_el2); + + SYSTEM_REGISTER(64, Mpidr, mpidr_el1); SYSTEM_REGISTER(32, Pmuserenr_el0, pmuserenr_el0); @@ -105,14 +145,20 @@ struct Hw::Arm_64_cpu struct Rw : Bitfield<10, 1> {}; ); - SYSTEM_REGISTER(64, Sctlr_el1, sctlr_el1, + struct Sctlr : Genode::Register<64> + { struct M : Bitfield<0, 1> { }; struct A : Bitfield<1, 1> { }; struct C : Bitfield<2, 1> { }; struct Sa : Bitfield<3, 1> { }; struct Sa0 : Bitfield<4, 1> { }; struct I : Bitfield<12, 1> { }; - ); + struct Uct : Bitfield<15, 1> { }; + struct Wxn : Bitfield<19, 1> { }; + }; + + SYSTEM_REGISTER(64, Sctlr_el1, sctlr_el1); + SYSTEM_REGISTER(64, Sctlr_el2, sctlr_el2); struct Spsr : Genode::Register<64> { @@ -145,6 +191,13 @@ struct Hw::Arm_64_cpu struct As : Bitfield<36, 1> { }; ); + SYSTEM_REGISTER(64, Tcr_el2, tcr_el2, + struct T0sz : Bitfield<0, 6> { }; + struct Irgn0 : Bitfield<8, 2> { }; + struct Orgn0 : Bitfield<10, 2> { }; + struct Sh0 : Bitfield<12, 2> { }; + ); + struct Ttbr : Genode::Register<64> { struct Baddr : Bitfield<0, 48> { }; @@ -152,10 +205,24 @@ struct Hw::Arm_64_cpu }; SYSTEM_REGISTER(64, Ttbr0_el1, ttbr0_el1); + SYSTEM_REGISTER(64, Ttbr0_el2, ttbr0_el2); SYSTEM_REGISTER(64, Ttbr1_el1, ttbr1_el1); SYSTEM_REGISTER(64, Vbar_el1, vbar_el1); + SYSTEM_REGISTER(64, Vbar_el2, vbar_el2); + + SYSTEM_REGISTER(32, Vtcr_el2, vtcr_el2, + struct T0sz : Bitfield<0, 6> {}; + struct Sl0 : Bitfield<6, 2> {}; + ); + + SYSTEM_REGISTER(64, Vttbr_el2, vttbr_el2, + struct CnP : Bitfield<0, 1> { }; + struct Ba : Bitfield<1, 47> { }; + struct Asid : Bitfield<48, 8> { }; + ); + static inline unsigned current_privilege_level() { return Current_el::El::get(Current_el::read()); } @@ -173,11 +240,44 @@ struct Hw::Arm_64_cpu SYSTEM_REGISTER(64, Cntpct_el0, cntpct_el0); SYSTEM_REGISTER(32, Cntp_tval_el0, cntp_tval_el0); + SYSTEM_REGISTER(32, Cntkctl_el1, cntkctl_el1); + SYSTEM_REGISTER(32, Cnthctl_el2, cnthctl_el2); using Cntfrq = Cntfrq_el0; using Cntp_ctl = Cntp_ctl_el0; using Cntpct = Cntpct_el0; using Cntp_tval = Cntp_tval_el0; + + static inline void wait_for_xchg(volatile int * addr, + int new_value, + int expected_value) + { + asm volatile( + /* check if load value of 'addr' is as expected */ + "1: ldxr w7, [%0] \n" + "cmp w7, %w2 \n" + "b.eq 2f \n" + + /* if not, wait for other CPU to send us an event */ + "wfe \n" + "b.ne 1b \n" + + /* if yes, attempt to write 'new_value' to 'addr' */ + "2: stxr w7, %w1, [%0]\n" + + /* if write failed, restart */ + "cbnz w7, 1b \n" + "dmb #0 \n" + :: "r"(addr), "r"(new_value), "r"(expected_value) : "cc", "x7"); + } + + static inline void wakeup_waiting_cpus() + { + asm volatile( + "dsb #0 \n" + "sev \n" + ); + } }; diff --git a/repos/base-hw/src/include/hw/spec/arm_64/imx8q_evk_board.h b/repos/base-hw/src/include/hw/spec/arm_64/imx8q_evk_board.h index 4b199b4e8..055465106 100644 --- a/repos/base-hw/src/include/hw/spec/arm_64/imx8q_evk_board.h +++ b/repos/base-hw/src/include/hw/spec/arm_64/imx8q_evk_board.h @@ -35,8 +35,10 @@ namespace Hw::Imx8q_evk_board { enum { IRQ_CONTROLLER_DISTR_BASE = 0x38800000, IRQ_CONTROLLER_DISTR_SIZE = 0x10000, + IRQ_CONTROLLER_VT_CPU_BASE = 0x31020000, + IRQ_CONTROLLER_VT_CPU_SIZE = 0x2000, IRQ_CONTROLLER_REDIST_BASE = 0x38880000, - IRQ_CONTROLLER_REDIST_SIZE = 0x20000, /* per core */ + IRQ_CONTROLLER_REDIST_SIZE = 0xc0000, }; }; }; diff --git a/repos/base-hw/src/include/hw/spec/arm_64/memory_map.h b/repos/base-hw/src/include/hw/spec/arm_64/memory_map.h new file mode 100644 index 000000000..e6ec5afda --- /dev/null +++ b/repos/base-hw/src/include/hw/spec/arm_64/memory_map.h @@ -0,0 +1,31 @@ +/* + * \brief Memory map specific to ARM 64 + * \author Stefan Kalkowski + * \date 2019-09-02 + */ + +/* + * Copyright (C) 2016-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 _SRC__LIB__HW__SPEC__ARM_64__MEMORY_MAP_H_ +#define _SRC__LIB__HW__SPEC__ARM_64__MEMORY_MAP_H_ + +#include + +namespace Hw { + namespace Mm { + + template + Genode::addr_t el2_addr(T t) + { + static constexpr Genode::addr_t OFF = 0xffffff8000000000UL; + return (Genode::addr_t)t - OFF; + } + }; +}; + +#endif /* _SRC__LIB__HW__SPEC__ARM_64__MEMORY_MAP_H_ */ diff --git a/repos/base-hw/src/include/irq_session_component.h b/repos/base-hw/src/include/irq_session_component.h index 8eaf93ad3..74ca09fa8 100644 --- a/repos/base-hw/src/include/irq_session_component.h +++ b/repos/base-hw/src/include/irq_session_component.h @@ -16,11 +16,12 @@ /* Genode includes */ #include -#include #include #include -#include "../core/kernel/irq.h" +#include +#include +#include namespace Genode { class Irq_session_component; } @@ -32,13 +33,13 @@ class Genode::Irq_session_component : public Rpc_object, friend class List; - unsigned _irq_number; - Range_allocator &_irq_alloc; - Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)]; - bool _is_msi; - addr_t _address, _value; - - Signal_context_capability _sig_cap { }; + Irq_args const _irq_args; + unsigned _irq_number; + Range_allocator & _irq_alloc; + Kernel_object _kobj; + bool _is_msi; + addr_t _address, _value; + Signal_context_capability _sig_cap { }; unsigned _find_irq_number(const char * const args); diff --git a/repos/base-hw/src/include/pager.h b/repos/base-hw/src/include/pager.h index 6bebe2a6f..d72dd5d75 100644 --- a/repos/base-hw/src/include/pager.h +++ b/repos/base-hw/src/include/pager.h @@ -158,7 +158,7 @@ class Genode::Pager_object : private Object_pool::Entry, * * \param receiver signal receiver that receives the page faults */ - void start_paging(Kernel::Signal_receiver * receiver); + void start_paging(Kernel_object & receiver); /** * Called when a page-fault finally could not be resolved @@ -196,9 +196,12 @@ class Genode::Pager_object : private Object_pool::Entry, class Genode::Pager_entrypoint : public Object_pool, public Thread_deprecated, - private Kernel_object, private Ipc_pager { + private: + + Kernel_object _kobj; + public: /** diff --git a/repos/base-hw/src/include/platform_pd.h b/repos/base-hw/src/include/platform_pd.h index 21eda53d3..7642ab530 100644 --- a/repos/base-hw/src/include/platform_pd.h +++ b/repos/base-hw/src/include/platform_pd.h @@ -72,12 +72,11 @@ class Hw::Address_space : public Genode::Address_space using Table = Hw::Page_table; using Array = Table::Allocator::Array; - Genode::Lock _lock { }; /* table lock */ - Table & _tt; /* table virt addr */ - Genode::addr_t _tt_phys; /* table phys addr */ - Array * _tt_array = nullptr; - Table::Allocator & _tt_alloc; /* table allocator */ - Kernel::Pd & _kernel_pd; + Genode::Lock _lock { }; /* table lock */ + Table & _tt; /* table virt addr */ + Genode::addr_t _tt_phys; /* table phys addr */ + Array * _tt_array = nullptr; + Table::Allocator & _tt_alloc; /* table allocator */ static inline Genode::Core_mem_allocator &_cma(); @@ -85,25 +84,27 @@ class Hw::Address_space : public Genode::Address_space protected: + Kernel_object _kobj; + /** * Core-specific constructor * - * \param pd pointer to kernel's pd object - * \param tt pointer to translation table - * \param tt_alloc pointer to translation table allocator + * \param tt reference to translation table + * \param tt_alloc reference to translation table allocator + * \param pd reference to platform pd object */ - Address_space(Kernel::Pd & pd, - Hw::Page_table & tt, - Hw::Page_table::Allocator & tt_alloc); + Address_space(Hw::Page_table & tt, + Hw::Page_table::Allocator & tt_alloc, + Platform_pd & pd); public: /** * Constructor * - * \param pd pointer to kernel's pd object + * \param pd reference to platform pd object */ - Address_space(Kernel::Pd & pd); + Address_space(Platform_pd & pd); ~Address_space(); @@ -132,9 +133,9 @@ class Hw::Address_space : public Genode::Address_space ** Accessors ** ***************/ - Kernel::Pd & kernel_pd() { return _kernel_pd; } - Hw::Page_table & translation_table() { return _tt; } - Genode::addr_t translation_table_phys() { return _tt_phys; } + Kernel::Pd & kernel_pd() { return *_kobj; } + Hw::Page_table & translation_table() { return _tt; } + Genode::addr_t translation_table_phys() { return _tt_phys; } }; @@ -161,8 +162,7 @@ class Genode::Cap_space class Genode::Platform_pd : public Hw::Address_space, - private Cap_space, - private Kernel_object + private Cap_space { private: diff --git a/repos/base-hw/src/include/platform_thread.h b/repos/base-hw/src/include/platform_thread.h index 0be960c9e..56c398665 100644 --- a/repos/base-hw/src/include/platform_thread.h +++ b/repos/base-hw/src/include/platform_thread.h @@ -122,7 +122,7 @@ namespace Genode { /** * Return information about current fault */ - Kernel::Thread_fault fault_info() { return _kobj.kernel_object()->fault(); } + Kernel::Thread_fault fault_info() { return _kobj->fault(); } /** * Join a protection domain @@ -150,7 +150,7 @@ namespace Genode { /** * Pause this thread */ - void pause() { Kernel::pause_thread(_kobj.kernel_object()); } + void pause() { Kernel::pause_thread(*_kobj); } /** * Enable/disable single stepping @@ -160,13 +160,13 @@ namespace Genode { /** * Resume this thread */ - void resume() { Kernel::resume_thread(_kobj.kernel_object()); } + void resume() { Kernel::resume_thread(*_kobj); } /** * Cancel currently blocking operation */ void cancel_blocking() { - Kernel::cancel_thread_blocking(_kobj.kernel_object()); } + Kernel::cancel_thread_blocking(*_kobj); } /** * Set CPU quota of the thread to 'quota' diff --git a/repos/base-hw/src/include/rpc_cap_factory.h b/repos/base-hw/src/include/rpc_cap_factory.h index 957e56e49..16ef1e789 100644 --- a/repos/base-hw/src/include/rpc_cap_factory.h +++ b/repos/base-hw/src/include/rpc_cap_factory.h @@ -39,14 +39,18 @@ class Genode::Rpc_cap_factory /** * Kernel object placeholder held in a list */ - struct Kobject : List::Element + struct Kobject + : List::Element { - using Identity = Kernel::Core_object_identity; + using O = Kernel::Core_object_identity; - Native_capability cap { }; + Constructible kobj {}; + Native_capability cap; - uint8_t data[sizeof(Identity)] - __attribute__((aligned(sizeof(addr_t)))); + Kobject(Native_capability ep) + : cap(Capability_space::import(O::syscall_create(kobj, Capability_space::capid(ep)))) {} + + void destruct() { O::syscall_destroy(kobj); } }; using Slab = Tslab; @@ -68,7 +72,6 @@ class Genode::Rpc_cap_factory Lock::Guard guard(_lock); while (Kobject * obj = _list.first()) { - Kernel::delete_obj(obj->data); _list.remove(obj); destroy(&_slab, obj); } @@ -87,11 +90,8 @@ class Genode::Rpc_cap_factory Kobject * obj; if (!_slab.alloc(sizeof(Kobject), (void**)&obj)) throw Allocator::Out_of_memory(); - construct_at(obj); + construct_at(obj, ep); - /* create kernel object via syscall */ - Kernel::capid_t capid = Kernel::new_obj(obj->data, Capability_space::capid(ep)); - obj->cap = Capability_space::import(capid); if (!obj->cap.valid()) { raw("Invalid entrypoint ", (addr_t)Capability_space::capid(ep), " for allocating a capability!"); @@ -110,7 +110,7 @@ class Genode::Rpc_cap_factory for (Kobject * obj = _list.first(); obj; obj = obj->next()) { if (obj->cap.data() == cap.data()) { - Kernel::delete_obj(obj->data); + obj->destruct(); _list.remove(obj); destroy(&_slab, obj); return; diff --git a/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc b/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc index 223d7ead4..a572e3f4b 100644 --- a/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc +++ b/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc @@ -45,6 +45,9 @@ Memory_region const Hw::Mm::system_exception_vector() { Memory_region const Hw::Mm::hypervisor_exception_vector() { return Memory_region(0xfff10000UL, 0x1000UL); } +Memory_region const Hw::Mm::hypervisor_stack() { + return Memory_region(0xfff12000UL, 0x1000UL); } + Memory_region const Hw::Mm::boot_info() { return Memory_region(0xfffe0000UL, 0x1000UL); } diff --git a/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc b/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc index ef846ef81..cf5c8a8c1 100644 --- a/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc +++ b/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc @@ -20,12 +20,14 @@ using Hw::Memory_region; using Genode::addr_t; using Genode::Native_utcb; -static constexpr addr_t USER_START = Genode::user_utcb_main_thread() - + sizeof(Native_utcb); +static constexpr addr_t USER_START = Genode::user_utcb_main_thread() + + sizeof(Native_utcb); +static constexpr addr_t USER_END = (1ULL << (39 - 1)); static constexpr addr_t KERNEL_START = 0xffffffc000000000UL; + Memory_region const Hw::Mm::user() { - return Memory_region(USER_START, 0x800000000000 - USER_START); } + return Memory_region(USER_START, USER_END - USER_START); } Memory_region const Hw::Mm::core_heap() { return Memory_region(0xffffffd000000000UL, 0x1000000000UL); } @@ -45,5 +47,11 @@ Memory_region const Hw::Mm::core_mmio() { Memory_region const Hw::Mm::boot_info() { return Memory_region(0xffffffe040000000UL, 0x1000UL); } +Memory_region const Hw::Mm::hypervisor_exception_vector() { + return Memory_region(0xffffffe050000000UL, 0x2000UL); } + +Memory_region const Hw::Mm::hypervisor_stack() { + return Memory_region(0xffffffe050003000UL, 0x1000UL); } + Memory_region const Hw::Mm::supervisor_exception_vector() { return Memory_region(KERNEL_START, 0x1000UL); } diff --git a/repos/base-linux/recipes/api/base-linux/hash b/repos/base-linux/recipes/api/base-linux/hash index 8fe9ac39e..ed6fd5237 100644 --- a/repos/base-linux/recipes/api/base-linux/hash +++ b/repos/base-linux/recipes/api/base-linux/hash @@ -1 +1 @@ -2019-09-19 9da8e9d0dfbb168395885eec15d6ab58e299105c +2019-11-25 531276b0d4d8eecf34a75dbc10120a7e0760fcc7 diff --git a/repos/base-linux/recipes/src/base-linux/hash b/repos/base-linux/recipes/src/base-linux/hash index dfd9af032..88904b6b2 100644 --- a/repos/base-linux/recipes/src/base-linux/hash +++ b/repos/base-linux/recipes/src/base-linux/hash @@ -1 +1 @@ -2019-09-19 ef6c0f4e89f86a63871d53ef5599157e1b307fdc +2019-11-25 a8aa0fd71305a04386a60c140c9abc08d9e49b16 diff --git a/repos/base-nova/recipes/api/base-nova/hash b/repos/base-nova/recipes/api/base-nova/hash index c5bca7965..739f5c92e 100644 --- a/repos/base-nova/recipes/api/base-nova/hash +++ b/repos/base-nova/recipes/api/base-nova/hash @@ -1 +1 @@ -2019-08-13 d6999479b98afb85de5ded3aff4afb707e770280 +2019-11-25 7a4527cf36193e0f4f66bb1bfeb548ba9790a62c diff --git a/repos/base-nova/recipes/src/base-nova/hash b/repos/base-nova/recipes/src/base-nova/hash index a2f2a04cf..b1168f42c 100644 --- a/repos/base-nova/recipes/src/base-nova/hash +++ b/repos/base-nova/recipes/src/base-nova/hash @@ -1 +1 @@ -2019-09-19 47a67c775afee8c02cb15a8c70807d3fe9f6aa66 +2019-11-25 ceacce158e365157d156298c28c6d772831422f0 diff --git a/repos/base-nova/src/core/include/vm_session_component.h b/repos/base-nova/src/core/include/vm_session_component.h index 3a9673a8f..748d0397f 100644 --- a/repos/base-nova/src/core/include/vm_session_component.h +++ b/repos/base-nova/src/core/include/vm_session_component.h @@ -78,6 +78,7 @@ class Genode::Vm_session_component addr_t new_pt_id(); + Vcpu_id id() { return _id; } bool match(Vcpu_id const id) const { return id.id == _id.id; } Ram_dataspace_capability ds_cap() const { return _ds_cap; } @@ -180,7 +181,7 @@ class Genode::Vm_session_component void attach(Dataspace_capability, addr_t, Attach_attr) override; void attach_pic(addr_t) override {} void detach(addr_t, size_t) override; - void _create_vcpu(Thread_capability); + Vcpu_id _create_vcpu(Thread_capability); }; #endif /* _CORE__VM_SESSION_COMPONENT_H_ */ diff --git a/repos/base-nova/src/core/vm_session_component.cc b/repos/base-nova/src/core/vm_session_component.cc index 55f6c91f2..f801f5890 100644 --- a/repos/base-nova/src/core/vm_session_component.cc +++ b/repos/base-nova/src/core/vm_session_component.cc @@ -33,6 +33,7 @@ using Genode::addr_t; using Genode::Vm_session_component; +using Vcpu_id = Genode::Vm_session::Vcpu_id; enum { CAP_RANGE_LOG2 = 2, CAP_RANGE = 1 << CAP_RANGE_LOG2 }; @@ -153,10 +154,10 @@ static Genode::uint8_t _with_kernel_quota_upgrade(addr_t const pd_target, return res; } -void Vm_session_component::_create_vcpu(Thread_capability cap) +Vcpu_id Vm_session_component::_create_vcpu(Thread_capability cap) { - if (!cap.valid()) - return; + Vcpu_id ret; + if (!cap.valid()) return ret; /* lookup vmm pd and cpu location of handler thread in VMM */ addr_t kernel_cpu_id = 0; @@ -178,7 +179,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) /* if VMM pd lookup failed then deny to create vCPU */ if (!vmm_pd_sel || vmm_pd_sel == Vcpu::invalid()) - return; + return ret; /* allocate vCPU object */ Vcpu &vcpu = *new (_heap) Vcpu(_constrained_md_ram_alloc, @@ -191,7 +192,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) /* we ran out of caps in core */ if (!vcpu.ds_cap().valid()) - return; + return ret; /* core PD selector */ addr_t const core_pd = platform_specific().core_pd_sel(); @@ -204,7 +205,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) if (res != Nova::NOVA_OK) { error("create_sm = ", res); destroy(_heap, &vcpu); - return; + return ret; } addr_t const event_base = (1U << Nova::NUM_INITIAL_VCPU_PT_LOG2) * _id_alloc; @@ -217,7 +218,7 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) if (res != Nova::NOVA_OK) { error("create_ec = ", res); destroy(_heap, &vcpu); - return; + return ret; } addr_t const dst_sm_ec_sel = Nova::NUM_INITIAL_PT_RESERVED @@ -239,11 +240,12 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) { error("map sm ", res, " ", _id_alloc); destroy(_heap, &vcpu); - return; + return ret; } - _id_alloc++; _vcpus.insert(&vcpu); + _id_alloc++; + return vcpu.id(); } void Vm_session_component::_run(Vcpu_id const vcpu_id) diff --git a/repos/base-nova/src/lib/base/vm_session.cc b/repos/base-nova/src/lib/base/vm_session.cc index 30daf44ca..922260cbd 100644 --- a/repos/base-nova/src/lib/base/vm_session.cc +++ b/repos/base-nova/src/lib/base/vm_session.cc @@ -29,7 +29,6 @@ using namespace Genode; struct Vcpu; static Genode::Registry > vcpus; -static unsigned vcpu_id = 0; struct Vcpu { @@ -425,8 +424,9 @@ struct Vcpu { public: - Vcpu(Vm_handler_base &o, unsigned id, Allocator &alloc) - : _obj(o), _alloc(alloc), _id({id}) { } + Vcpu(Vm_handler_base &o, Vm_session::Vcpu_id const id, + Allocator &alloc) + : _obj(o), _alloc(alloc), _id(id) { } virtual ~Vcpu() { } @@ -703,9 +703,10 @@ Vm_session_client::create_vcpu(Allocator &alloc, Env &env, Vm_handler_base &handler) { Thread * ep = reinterpret_cast(&handler._rpc_ep); - call(ep->cap()); - Vcpu * vcpu = new (alloc) Registered (vcpus, handler, vcpu_id++, alloc); + Vcpu * vcpu = new (alloc) Registered (vcpus, handler, + call(ep->cap()), + alloc); vcpu->assign_ds_state(env.rm(), call(vcpu->id())); Signal_context_capability dontcare_exit; diff --git a/repos/base-okl4/recipes/src/base-okl4/hash b/repos/base-okl4/recipes/src/base-okl4/hash index a4ece9375..99c964541 100644 --- a/repos/base-okl4/recipes/src/base-okl4/hash +++ b/repos/base-okl4/recipes/src/base-okl4/hash @@ -1 +1 @@ -2019-09-19 c7ff0a4757680a1a8614865018258c2c85929b4c +2019-11-25 beb7e752d7ac11fb0b0bd34b04e6fc64ae679032 diff --git a/repos/base-pistachio/recipes/src/base-pistachio/hash b/repos/base-pistachio/recipes/src/base-pistachio/hash index 294fb0757..2180bc3a9 100644 --- a/repos/base-pistachio/recipes/src/base-pistachio/hash +++ b/repos/base-pistachio/recipes/src/base-pistachio/hash @@ -1 +1 @@ -2019-09-19 7c96cb86fc13d4b261fb61102351134ffcf14ee1 +2019-11-25 5c6e2cbb93352d0424b051e6ebaed5096d9060c9 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 22b527c15..b21f688b2 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 @@ -2019-09-19 bd8eea8f69015c04c14dffeac88e3af108ce3cb3 +2019-11-25 8adcce8fb49750ef9cf727247f252cb57dbda0fa 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 9e4b00bcc..7a0f8d4a4 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 @@ -2019-09-19 f323d1bbeab965174f0d31d77f3176b3bf1322b0 +2019-11-25 7c4b8f0b4d5f3d9618f2bd7a09e185049a8707d0 diff --git a/repos/base-sel4/recipes/src/base-sel4-x86/hash b/repos/base-sel4/recipes/src/base-sel4-x86/hash index 7f746a1ff..d3604ae22 100644 --- a/repos/base-sel4/recipes/src/base-sel4-x86/hash +++ b/repos/base-sel4/recipes/src/base-sel4-x86/hash @@ -1 +1 @@ -2019-09-19 4829db8f15fd4a4567f1799d279d497d3e3e1aec +2019-11-25 797da0dccf118a3de415db45ca36c09e6e649d09 diff --git a/repos/base-sel4/src/core/include/vm_session_component.h b/repos/base-sel4/src/core/include/vm_session_component.h index de814b2d8..63544ea75 100644 --- a/repos/base-sel4/src/core/include/vm_session_component.h +++ b/repos/base-sel4/src/core/include/vm_session_component.h @@ -121,7 +121,7 @@ class Genode::Vm_session_component void attach(Dataspace_capability, addr_t, Attach_attr) override; void attach_pic(addr_t) override {} void detach(addr_t, size_t) override; - void _create_vcpu(Thread_capability); + Vcpu_id _create_vcpu(Thread_capability); }; #endif /* _CORE__VM_SESSION_COMPONENT_H_ */ diff --git a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc index 642fd288a..ee9b907f4 100644 --- a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc +++ b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc @@ -177,10 +177,12 @@ Vm_session_component::~Vm_session_component() Platform_pd::pd_id_alloc().free(_pd_id); } -void Vm_session_component::_create_vcpu(Thread_capability cap) +Vm_session::Vcpu_id Vm_session_component::_create_vcpu(Thread_capability cap) { + Vcpu_id ret; + if (!cap.valid()) - return; + return ret; auto lambda = [&] (Cpu_thread_component *thread) { if (!thread) @@ -218,10 +220,11 @@ void Vm_session_component::_create_vcpu(Thread_capability cap) } _vcpus.insert(vcpu); - _id_alloc++; + ret.id = _id_alloc++; }; _ep.apply(cap, lambda); + return ret; } Dataspace_capability Vm_session_component::_cpu_state(Vcpu_id const vcpu_id) diff --git a/repos/base-sel4/src/lib/base/x86/vm_session.cc b/repos/base-sel4/src/lib/base/x86/vm_session.cc index 062000f57..5d7155404 100644 --- a/repos/base-sel4/src/lib/base/x86/vm_session.cc +++ b/repos/base-sel4/src/lib/base/x86/vm_session.cc @@ -32,7 +32,6 @@ using namespace Genode; struct Vcpu; static Genode::Registry > vcpus; -static unsigned vcpu_id = 0; struct Vcpu : Genode::Thread { @@ -43,7 +42,7 @@ struct Vcpu : Genode::Thread Semaphore &_handler_ready; Allocator &_alloc; Lock _startup { Genode::Lock::LOCKED }; - Vm_session_client::Vcpu_id _id; + Vm_session_client::Vcpu_id _id {}; addr_t _state { 0 }; addr_t _recall { 0 }; uint64_t _tsc_offset { 0 }; @@ -713,12 +712,12 @@ struct Vcpu : Genode::Thread public: Vcpu(Genode::Env &env, Genode::Signal_context_capability &cap, - Semaphore &handler_ready, unsigned id, Allocator &alloc, + Semaphore &handler_ready, Allocator &alloc, Affinity::Location &location) : Thread(env, "vcpu_thread", STACK_SIZE, location, Weight(), env.cpu()), _signal(cap), - _handler_ready(handler_ready), _alloc(alloc), _id({id}) + _handler_ready(handler_ready), _alloc(alloc) { } Allocator &allocator() { return _alloc; } @@ -728,7 +727,8 @@ struct Vcpu : Genode::Thread _startup.lock(); } - Genode::Vm_session_client::Vcpu_id id() const { return _id; } + Genode::Vm_session_client::Vcpu_id id() const { return _id; } + void id(Genode::Vm_session_client::Vcpu_id id) { _id = id; } void assign_ds_state(Region_map &rm, Dataspace_capability cap) { _state = rm.attach(cap); } @@ -775,7 +775,7 @@ Genode::Vm_session_client::create_vcpu(Allocator &alloc, Env &env, Vcpu * vcpu = new (alloc) Genode::Registered (vcpus, env, handler._cap, handler._done, - vcpu_id, alloc, + alloc, location); try { @@ -783,8 +783,8 @@ Genode::Vm_session_client::create_vcpu(Allocator &alloc, Env &env, vcpu->start(); /* instruct core to let it become a vCPU */ + vcpu->id(call(vcpu->cap())); call(handler._cap, vcpu->id()); - call(vcpu->cap()); vcpu->assign_ds_state(env.rm(), call(vcpu->id())); } catch (...) { @@ -794,7 +794,6 @@ Genode::Vm_session_client::create_vcpu(Allocator &alloc, Env &env, vcpu->initial_resume(); - vcpu_id++; return vcpu->id(); } diff --git a/repos/base/etc/tools.conf b/repos/base/etc/tools.conf index 961cf07b0..f0182612f 100644 --- a/repos/base/etc/tools.conf +++ b/repos/base/etc/tools.conf @@ -24,15 +24,15 @@ endif ifeq ($(filter-out $(SPECS),x86_64),) CROSS_DEV_PREFIX ?= /usr/local/genode/tool/19.05/bin/genode-x86- endif +ifeq ($(filter-out $(SPECS),arm_64),) +CROSS_DEV_PREFIX ?= /usr/local/genode/tool/19.05/bin/genode-aarch64- +endif ifeq ($(filter-out $(SPECS),arm),) CROSS_DEV_PREFIX ?= /usr/local/genode/tool/19.05/bin/genode-arm- endif ifeq ($(filter-out $(SPECS),riscv),) CROSS_DEV_PREFIX ?= /usr/local/genode/tool/19.05/bin/genode-riscv- endif -ifeq ($(filter-out $(SPECS),arm_64),) -CROSS_DEV_PREFIX ?= /usr/local/genode/tool/19.05/bin/genode-aarch64- -endif # # We use libsupc++ from g++ version 3 because diff --git a/repos/base/include/drivers/defs/imx6.h b/repos/base/include/drivers/defs/imx6.h index bc374cbde..a34a768a3 100644 --- a/repos/base/include/drivers/defs/imx6.h +++ b/repos/base/include/drivers/defs/imx6.h @@ -44,8 +44,6 @@ namespace Imx6 { /* CPU */ CORTEX_A9_PRIVATE_MEM_BASE = 0x00a00000, CORTEX_A9_PRIVATE_MEM_SIZE = 0x00002000, - CORTEX_A9_PRIVATE_TIMER_CLK = 500000000, /* timer clk runs half the CPU freq */ - CORTEX_A9_PRIVATE_TIMER_DIV = 100, /* L2 cache controller */ PL310_MMIO_BASE = 0x00a02000, diff --git a/repos/base/include/drivers/uart/imx.h b/repos/base/include/drivers/uart/imx.h index bc628b573..bcb6f102c 100644 --- a/repos/base/include/drivers/uart/imx.h +++ b/repos/base/include/drivers/uart/imx.h @@ -259,12 +259,6 @@ class Genode::Imx_uart: Mmio */ void put_char(char c) { - enum { ASCII_LINE_FEED = 10, - ASCII_CARRIAGE_RETURN = 13 }; - - /* prepend line feed with carriage return */ - if (c == ASCII_LINE_FEED) _put_char(ASCII_CARRIAGE_RETURN); - /* transmit character */ _put_char(c); } diff --git a/repos/base/include/timer_session/connection.h b/repos/base/include/timer_session/connection.h index 3e2c2d272..5a8c99756 100644 --- a/repos/base/include/timer_session/connection.h +++ b/repos/base/include/timer_session/connection.h @@ -258,6 +258,18 @@ class Timer::Connection : public Genode::Connection, /** * Constructor + * + * \param env environment used for construction (e.g. quota trading) + * \param ep entrypoint used as timeout handler execution context + * \param label optional label used in session routing + */ + Connection(Genode::Env &env, + Genode::Entrypoint & ep, + char const *label = ""); + + /** + * Convenience constructor wrapper using the environment's entrypoint as + * timeout handler execution context */ Connection(Genode::Env &env, char const *label = ""); diff --git a/repos/base/include/util/fifo.h b/repos/base/include/util/fifo.h index 73524ccd0..83db99d1c 100644 --- a/repos/base/include/util/fifo.h +++ b/repos/base/include/util/fifo.h @@ -47,7 +47,7 @@ class Genode::Fifo /** * Return true is fifo element is enqueued in a fifo */ - bool enqueued() { return _enqueued; } + bool enqueued() const { return _enqueued; } /** * Return next element in queue diff --git a/repos/base/include/vm_session/vm_session.h b/repos/base/include/vm_session/vm_session.h index 8a050c71e..0a2c6b325 100644 --- a/repos/base/include/vm_session/vm_session.h +++ b/repos/base/include/vm_session/vm_session.h @@ -27,7 +27,12 @@ struct Genode::Vm_session : Session { static const char *service_name() { return "VM"; } - struct Vcpu_id { unsigned id; }; + struct Vcpu_id + { + enum { INVALID = ~0U }; + unsigned id { INVALID }; + }; + struct Attach_attr { addr_t offset; @@ -88,7 +93,7 @@ struct Genode::Vm_session : Session Dataspace_capability, addr_t, Attach_attr); GENODE_RPC(Rpc_detach, void, detach, addr_t, size_t); GENODE_RPC(Rpc_attach_pic, void, attach_pic, addr_t); - GENODE_RPC_THROW(Rpc_create_vcpu, void, _create_vcpu, + GENODE_RPC_THROW(Rpc_create_vcpu, Vcpu_id, _create_vcpu, GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), Thread_capability); diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index c8874645e..2e76e157d 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -53,6 +53,8 @@ _ZN5Timer10Connection8_discardERN6Genode7TimeoutE T _ZN5Timer10Connection9curr_timeEv T _ZN5Timer10ConnectionC1ERN6Genode3EnvEPKc T _ZN5Timer10ConnectionC2ERN6Genode3EnvEPKc T +_ZN5Timer10ConnectionC1ERN6Genode3EnvERNS1_10EntrypointEPKc T +_ZN5Timer10ConnectionC2ERN6Genode3EnvERNS1_10EntrypointEPKc T _ZN6Genode10Entrypoint16_dispatch_signalERNS_6SignalE T _ZN6Genode10Entrypoint16schedule_suspendEPFvvES2_ T _ZN6Genode10Entrypoint22Signal_proxy_component6signalEv T diff --git a/repos/base/recipes/api/base/hash b/repos/base/recipes/api/base/hash index 0bcfb89a3..51f8851c0 100644 --- a/repos/base/recipes/api/base/hash +++ b/repos/base/recipes/api/base/hash @@ -1 +1 @@ -2019-09-19 4ce950778a778619e1e7040104d513232bcb2511 +2019-11-25 9e9950ded74a7002cc9b21cf362cdf7b6ee2a2f2 diff --git a/repos/base/recipes/api/timer_session/hash b/repos/base/recipes/api/timer_session/hash index b816f5d46..38d5602b8 100644 --- a/repos/base/recipes/api/timer_session/hash +++ b/repos/base/recipes/api/timer_session/hash @@ -1 +1 @@ -2019-05-05 560fb6115debdfe4344d797867f7bd628e26de48 +2019-11-25 75109d6130a0026d3efedff2ee0bdea41c343729 diff --git a/repos/base/recipes/api/vm_session/hash b/repos/base/recipes/api/vm_session/hash index 174656330..d0a7b785e 100644 --- a/repos/base/recipes/api/vm_session/hash +++ b/repos/base/recipes/api/vm_session/hash @@ -1 +1 @@ -2019-05-20 2a0981ba2dbee8f45f581d26c63ca20649172946 +2019-11-25 2cd304bdb9c0becf81f4b33a425d7e9fcbde5d62 diff --git a/repos/base/recipes/pkg/test-ds_ownership/hash b/repos/base/recipes/pkg/test-ds_ownership/hash index f0059e138..892aa0c9d 100644 --- a/repos/base/recipes/pkg/test-ds_ownership/hash +++ b/repos/base/recipes/pkg/test-ds_ownership/hash @@ -1 +1 @@ -2019-09-19 ab5eeaa58a8c2c9c9c71cb95ddc56571260aaafd +2019-11-25 94f02f1acb45949fdf927da464b492ca99d397f5 diff --git a/repos/base/recipes/pkg/test-log/hash b/repos/base/recipes/pkg/test-log/hash index 5035d6f7f..1cd975ef8 100644 --- a/repos/base/recipes/pkg/test-log/hash +++ b/repos/base/recipes/pkg/test-log/hash @@ -1 +1 @@ -2019-09-19 3672165078130d68da62d988dbf70aa0cd3a2e65 +2019-11-25 0d59b1a1b390435c60320adceca7e37eaea75703 diff --git a/repos/base/recipes/pkg/test-mmio/hash b/repos/base/recipes/pkg/test-mmio/hash index 1d85dd3dc..b0df19107 100644 --- a/repos/base/recipes/pkg/test-mmio/hash +++ b/repos/base/recipes/pkg/test-mmio/hash @@ -1 +1 @@ -2019-09-19 9168a2e181dc66eccd3376df8343c6d1876546bb +2019-11-25 1e2d2be1b897336cbb963b6d2c4e41a5269f3bc7 diff --git a/repos/base/recipes/pkg/test-new_delete/hash b/repos/base/recipes/pkg/test-new_delete/hash index f49dcdf61..1ba491845 100644 --- a/repos/base/recipes/pkg/test-new_delete/hash +++ b/repos/base/recipes/pkg/test-new_delete/hash @@ -1 +1 @@ -2019-09-19 e4c028b411de22e979d3ff1f45189490cf31bb2f +2019-11-25 40e5c22666d5a5d4f5c062c0c454459928b91a13 diff --git a/repos/base/recipes/pkg/test-reconstructible/hash b/repos/base/recipes/pkg/test-reconstructible/hash index 6e877dc80..6f41865fc 100644 --- a/repos/base/recipes/pkg/test-reconstructible/hash +++ b/repos/base/recipes/pkg/test-reconstructible/hash @@ -1 +1 @@ -2019-09-19 ad154e94b71f9099e0cf2aa18b10d21f9b383e36 +2019-11-25 57e0cc0e30c33a2d5deb33535ba0ba9b45c99150 diff --git a/repos/base/recipes/pkg/test-registry/hash b/repos/base/recipes/pkg/test-registry/hash index fbd57ad23..59ac03f97 100644 --- a/repos/base/recipes/pkg/test-registry/hash +++ b/repos/base/recipes/pkg/test-registry/hash @@ -1 +1 @@ -2019-09-19 3d53508a9adab60f776875454425ba31231d0186 +2019-11-25 37c07c81e6dd61b10fc48ed445c4f46ff008001a diff --git a/repos/base/recipes/pkg/test-rm_fault/hash b/repos/base/recipes/pkg/test-rm_fault/hash index 1b54efdb1..c8f671054 100644 --- a/repos/base/recipes/pkg/test-rm_fault/hash +++ b/repos/base/recipes/pkg/test-rm_fault/hash @@ -1 +1 @@ -2019-09-19 080866be42473db2ba3baa28f81c45c76a5a5562 +2019-11-25 111b8785f8b9e039c8a311ccc07d7becc6ed0810 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 bd54ed967..203016f0a 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 @@ -2019-09-19 294b2f4be2649455e742bb3abc07ad26780dd3bd +2019-11-25 017e1d77bff2e85496cde341234a0bd595640869 diff --git a/repos/base/recipes/pkg/test-rm_nested/hash b/repos/base/recipes/pkg/test-rm_nested/hash index f549ff231..172942af2 100644 --- a/repos/base/recipes/pkg/test-rm_nested/hash +++ b/repos/base/recipes/pkg/test-rm_nested/hash @@ -1 +1 @@ -2019-09-19 83176300a7f5c88368b9a08fb183f1749bedca2d +2019-11-25 1ed8144bacdf05cfd671a1c5f6cc824e344a4919 diff --git a/repos/base/recipes/pkg/test-sanitizer/hash b/repos/base/recipes/pkg/test-sanitizer/hash index 5bb34b917..f533974bb 100644 --- a/repos/base/recipes/pkg/test-sanitizer/hash +++ b/repos/base/recipes/pkg/test-sanitizer/hash @@ -1 +1 @@ -2019-09-19 32d9fb864e5982ac9586de4a7c1432e94e5c8a17 +2019-11-25 c9fb204c40ab71d824ca74f4c16205dd5a9cab04 diff --git a/repos/base/recipes/pkg/test-stack_smash/hash b/repos/base/recipes/pkg/test-stack_smash/hash index 7fb67e160..9e241d78b 100644 --- a/repos/base/recipes/pkg/test-stack_smash/hash +++ b/repos/base/recipes/pkg/test-stack_smash/hash @@ -1 +1 @@ -2019-09-19 c5cfd9f518c425e5ea76399fbd7ede87443b0c6b +2019-11-25 dcec001f875d11749db0f392c4a66114143b55fa diff --git a/repos/base/recipes/pkg/test-synced_interface/hash b/repos/base/recipes/pkg/test-synced_interface/hash index 03b92e1c8..a8474cf2e 100644 --- a/repos/base/recipes/pkg/test-synced_interface/hash +++ b/repos/base/recipes/pkg/test-synced_interface/hash @@ -1 +1 @@ -2019-09-19 2eb3326ea3c82c0cf3cddffed7c36ff68f65dfc6 +2019-11-25 c9dcee6b07fc4e962dc3e0bd84a2aabbb5b1bb2f diff --git a/repos/base/recipes/pkg/test-timer/hash b/repos/base/recipes/pkg/test-timer/hash index 2c24cd428..3b83894ab 100644 --- a/repos/base/recipes/pkg/test-timer/hash +++ b/repos/base/recipes/pkg/test-timer/hash @@ -1 +1 @@ -2019-09-19 1f6f0c1f76e93daf74e64f364c47f28a73603755 +2019-11-25 6764f23e39dcc6e173ea8195ff92bfdfec24bedc diff --git a/repos/base/recipes/pkg/test-tls/hash b/repos/base/recipes/pkg/test-tls/hash index f2f913565..3feaee3f0 100644 --- a/repos/base/recipes/pkg/test-tls/hash +++ b/repos/base/recipes/pkg/test-tls/hash @@ -1 +1 @@ -2019-09-19 d70d5e7c055cc254adc055f5151491a6693bf733 +2019-11-25 07d2e197f5121cdea45e2b7ce0572c3aa70d6983 diff --git a/repos/base/recipes/pkg/test-xml_generator/hash b/repos/base/recipes/pkg/test-xml_generator/hash index 8e0114716..544a23e9c 100644 --- a/repos/base/recipes/pkg/test-xml_generator/hash +++ b/repos/base/recipes/pkg/test-xml_generator/hash @@ -1 +1 @@ -2019-09-19 cfe768e01d66ce8b0ef7a7d6d2b9e89d4dc39393 +2019-11-25 f1bb9c16d8ed42a15dd19a924d7c0f6529669fb8 diff --git a/repos/base/recipes/pkg/test-xml_node/hash b/repos/base/recipes/pkg/test-xml_node/hash index 6a92a7e91..b433906df 100644 --- a/repos/base/recipes/pkg/test-xml_node/hash +++ b/repos/base/recipes/pkg/test-xml_node/hash @@ -1 +1 @@ -2019-09-19 f050750a9450e7e96ddfcbc83d9a69de98487356 +2019-11-25 eb6ed19fa5fb8d2f5e5a9bc06f550e45cd521088 diff --git a/repos/base/recipes/src/test-ds_ownership/hash b/repos/base/recipes/src/test-ds_ownership/hash index d2ef35cf5..d3d379249 100644 --- a/repos/base/recipes/src/test-ds_ownership/hash +++ b/repos/base/recipes/src/test-ds_ownership/hash @@ -1 +1 @@ -2019-09-19 9368062504d876596c1c59624d93436432a01045 +2019-11-25 e9325cec031a8ceaef16b3cc0d2d40160df4c3e9 diff --git a/repos/base/recipes/src/test-log/hash b/repos/base/recipes/src/test-log/hash index c95e3825d..c2a9845a2 100644 --- a/repos/base/recipes/src/test-log/hash +++ b/repos/base/recipes/src/test-log/hash @@ -1 +1 @@ -2019-09-19 90dffca9b6441910d98efb080eb7fcad4c9c95e4 +2019-11-25 a6d3c083a3bafd4b4db616d307e1741b824f6edf diff --git a/repos/base/recipes/src/test-mmio/hash b/repos/base/recipes/src/test-mmio/hash index 02a6d8888..e42a02bb1 100644 --- a/repos/base/recipes/src/test-mmio/hash +++ b/repos/base/recipes/src/test-mmio/hash @@ -1 +1 @@ -2019-09-19 b31ab9af06931737f2a65b47f9e74248c7766f62 +2019-11-25 32019c81f49cc2cc2f40c8fe36029314ec82704f diff --git a/repos/base/recipes/src/test-new_delete/hash b/repos/base/recipes/src/test-new_delete/hash index 3251dad73..261cc6f91 100644 --- a/repos/base/recipes/src/test-new_delete/hash +++ b/repos/base/recipes/src/test-new_delete/hash @@ -1 +1 @@ -2019-09-19 f79d6093d873fa74ad68ca4eadcc435112e9cb92 +2019-11-25 5c78b48e68489d05d96409b85636cedb5d7e312c diff --git a/repos/base/recipes/src/test-reconstructible/hash b/repos/base/recipes/src/test-reconstructible/hash index edee7f735..f944a656e 100644 --- a/repos/base/recipes/src/test-reconstructible/hash +++ b/repos/base/recipes/src/test-reconstructible/hash @@ -1 +1 @@ -2019-09-19 76cfc2b0253a852a84c32ee371e49d4b0cd6ccfa +2019-11-25 2c0514614ca68e61a95feef7cae8f6256e0e6c04 diff --git a/repos/base/recipes/src/test-registry/hash b/repos/base/recipes/src/test-registry/hash index 2eecdb56d..b48969013 100644 --- a/repos/base/recipes/src/test-registry/hash +++ b/repos/base/recipes/src/test-registry/hash @@ -1 +1 @@ -2019-09-19 ddcfb33db820972ddb541a2960108b42e414caf7 +2019-11-25 2eee12c93f09004a191f2ff574865be1ef22b097 diff --git a/repos/base/recipes/src/test-rm_fault/hash b/repos/base/recipes/src/test-rm_fault/hash index ab223afc4..e218887e6 100644 --- a/repos/base/recipes/src/test-rm_fault/hash +++ b/repos/base/recipes/src/test-rm_fault/hash @@ -1 +1 @@ -2019-09-19 e7579152f4b5aa58925367c323400f8dee05af37 +2019-11-25 01c780e654a92253989dc3ebc43c05957da49d71 diff --git a/repos/base/recipes/src/test-rm_nested/hash b/repos/base/recipes/src/test-rm_nested/hash index 804179b50..1cc4c9fdf 100644 --- a/repos/base/recipes/src/test-rm_nested/hash +++ b/repos/base/recipes/src/test-rm_nested/hash @@ -1 +1 @@ -2019-09-19 7a2129272b64ad70f2aa606cb9da5c028654d166 +2019-11-25 714ceba8ad105eefc93a4498f6e0e3eccc98d2d1 diff --git a/repos/base/recipes/src/test-sanitizer/hash b/repos/base/recipes/src/test-sanitizer/hash index 0ecc77116..6289db9f7 100644 --- a/repos/base/recipes/src/test-sanitizer/hash +++ b/repos/base/recipes/src/test-sanitizer/hash @@ -1 +1 @@ -2019-09-19 2c10f1df05dc2feabbc27ccaeb2b481d6de6d98c +2019-11-25 3f16e72571bd65dbbcf8dd184e3dcbb33896747e diff --git a/repos/base/recipes/src/test-segfault/hash b/repos/base/recipes/src/test-segfault/hash index e86e4a870..9a5fc8030 100644 --- a/repos/base/recipes/src/test-segfault/hash +++ b/repos/base/recipes/src/test-segfault/hash @@ -1 +1 @@ -2019-09-19 7dada3028e4034313341fa370571401a7d26079b +2019-11-25 11ee94b5804b7cac134bb6630a6f0bdd946457cf diff --git a/repos/base/recipes/src/test-stack_smash/hash b/repos/base/recipes/src/test-stack_smash/hash index 8edd6367b..c9c07863c 100644 --- a/repos/base/recipes/src/test-stack_smash/hash +++ b/repos/base/recipes/src/test-stack_smash/hash @@ -1 +1 @@ -2019-09-19 c68dbf6a6223967de927e92a576bc5faaa0d7fa3 +2019-11-25 e1757371d0dfeae26b15014f6539dab85cab54f2 diff --git a/repos/base/recipes/src/test-synced_interface/hash b/repos/base/recipes/src/test-synced_interface/hash index dcb9f29e6..93487e88b 100644 --- a/repos/base/recipes/src/test-synced_interface/hash +++ b/repos/base/recipes/src/test-synced_interface/hash @@ -1 +1 @@ -2019-09-19 2ffe4086ff30b53de3e1a9902cbd10a0040a0a4b +2019-11-25 1d107103e51e89792b39e27f0a97fe446740fe97 diff --git a/repos/base/recipes/src/test-timer/hash b/repos/base/recipes/src/test-timer/hash index ced5b6cc1..325686eaf 100644 --- a/repos/base/recipes/src/test-timer/hash +++ b/repos/base/recipes/src/test-timer/hash @@ -1 +1 @@ -2019-09-19 2f5cad44bdb74467fc180b3e7a7bf202ca3d43b5 +2019-11-25 86a59ecf65c977a9eb6abd3bfc9b0c8466fe7736 diff --git a/repos/base/recipes/src/test-tls/hash b/repos/base/recipes/src/test-tls/hash index 4415a80cc..f27b54b5d 100644 --- a/repos/base/recipes/src/test-tls/hash +++ b/repos/base/recipes/src/test-tls/hash @@ -1 +1 @@ -2019-09-19 422089c3823de9d373a4eefc13d3b7e0a14646c6 +2019-11-25 865bc5bfdb4c5954cf11e4c172301a007923ccc3 diff --git a/repos/base/recipes/src/test-xml_generator/hash b/repos/base/recipes/src/test-xml_generator/hash index a6422bbb6..1cfe044fa 100644 --- a/repos/base/recipes/src/test-xml_generator/hash +++ b/repos/base/recipes/src/test-xml_generator/hash @@ -1 +1 @@ -2019-09-19 75ca60a8b544f4f3594693b9ef053f3a5a1a1fb4 +2019-11-25 8945ff664c64264aae3ec0e791db2d4111bf0c72 diff --git a/repos/base/recipes/src/test-xml_node/hash b/repos/base/recipes/src/test-xml_node/hash index 5b7b79537..960cbebd9 100644 --- a/repos/base/recipes/src/test-xml_node/hash +++ b/repos/base/recipes/src/test-xml_node/hash @@ -1 +1 @@ -2019-09-19 bdba8d88dce97f0370a38a205866ae4c9f5a19c0 +2019-11-25 f6db99fb1e22844685f6289311b456345fcc948a diff --git a/repos/base/run/platform_drv.inc b/repos/base/run/platform_drv.inc index ea2ed0d98..fda7a0062 100644 --- a/repos/base/run/platform_drv.inc +++ b/repos/base/run/platform_drv.inc @@ -185,7 +185,7 @@ proc platform_drv_config {} { if {[have_spec x86] && ![have_spec muen] && ![have_spec linux]} { append drv_config { - + } if {[acpi_drv_name] eq "acpica"} { diff --git a/repos/base/src/core/include/trace/subject_registry.h b/repos/base/src/core/include/trace/subject_registry.h index 3173b44ac..562c17920 100644 --- a/repos/base/src/core/include/trace/subject_registry.h +++ b/repos/base/src/core/include/trace/subject_registry.h @@ -349,7 +349,7 @@ class Genode::Trace::Subject_registry Session_label const &label, Thread_name const &name) { Subject *subject = new (®istry._md_alloc) - Subject(Subject_id(registry._id_cnt++), source_id, source, label, name); + Subject(Subject_id(++registry._id_cnt), source_id, source, label, name); registry._entries.insert(subject); } diff --git a/repos/base/src/ld/genode_dyn.ld b/repos/base/src/ld/genode_dyn.ld index ba9091837..5fa6ddc29 100644 --- a/repos/base/src/ld/genode_dyn.ld +++ b/repos/base/src/ld/genode_dyn.ld @@ -213,7 +213,17 @@ SECTIONS } .jcr : { KEEP (*(.jcr)) } .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } - .dynamic : { *(.dynamic) } : rw : dynamic + .dynamic : + { + *(.dynamic) + + /* + * Make sure to have a least one entry within the dynamic section, so the + * dynamic sgement point to something valid in case there are no dynamic + * symbols + */ + LONG(0x0); + } : rw : dynamic /* merge .got.plt and .got into .got, since the ARM toolchain for OKL4 * set's * DT_PLTGOT to .got instead of .got.plt */ diff --git a/repos/base/src/lib/base-common/heap.cc b/repos/base/src/lib/base-common/heap.cc index 370ad2ef8..11bd07539 100644 --- a/repos/base/src/lib/base-common/heap.cc +++ b/repos/base/src/lib/base-common/heap.cc @@ -221,7 +221,7 @@ bool Heap::_unsynchronized_alloc(size_t size, void **out_addr) bool Heap::alloc(size_t size, void **out_addr) { if (size == 0) - error("attempt to allocated zero-size block from heap"); + error("attempt to allocate zero-size block from heap"); /* serialize access of heap functions */ Lock::Guard lock_guard(_lock); diff --git a/repos/base/src/lib/base-common/vm_session.cc b/repos/base/src/lib/base-common/vm_session.cc index fe8be6307..2fe995908 100644 --- a/repos/base/src/lib/base-common/vm_session.cc +++ b/repos/base/src/lib/base-common/vm_session.cc @@ -18,9 +18,8 @@ using namespace Genode; Vm_session::Vcpu_id Vm_session_client::create_vcpu(Allocator &, Env &, Vm_handler_base &handler) { - Vcpu_id vcpu_id { 0 }; - - call(Thread_capability()); + Thread * ep = reinterpret_cast(&handler._rpc_ep); + Vcpu_id vcpu_id { call(ep->cap()) }; call(handler._cap, vcpu_id); return vcpu_id; } diff --git a/repos/base/src/lib/ldso/dependency.cc b/repos/base/src/lib/ldso/dependency.cc index 50d8dafaa..cb30c0c62 100644 --- a/repos/base/src/lib/ldso/dependency.cc +++ b/repos/base/src/lib/ldso/dependency.cc @@ -111,7 +111,7 @@ Linker::Root_object::Root_object(Env &env, Allocator &md_alloc, /* relocate and call constructors */ try { - Init::list()->initialize(bind, STAGE_SO); + Init::list()->initialize(bind, Linker::stage); } catch (...) { Init::list()->flush(); _deps.dequeue_all([&] (Dependency &d) { diff --git a/repos/base/src/lib/ldso/include/linker.h b/repos/base/src/lib/ldso/include/linker.h index d917c1c50..3692bab00 100644 --- a/repos/base/src/lib/ldso/include/linker.h +++ b/repos/base/src/lib/ldso/include/linker.h @@ -47,6 +47,23 @@ namespace Linker { */ extern bool verbose; + /** + * Stage of execution + * + * This state variable is used to control the implicit execution of global + * static constructors as a side effect of loading a shared library. + * + * At STAGE_BINARY, the binary is initialized and 'Component::construct' + * is executed. At this early stage, no global static constructor must be + * executed. + * + * Once, 'Env::exec_static_constructors' is called, or + * 'Component::construct' returned, we enter the 'STAGE_SO'. At this stage, + * global static constructors can safely be executed, i.e., as side effect + * of loading a shared library. + */ + extern Stage stage; + /** * Find symbol via index * diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index 2aaeaaac0..6eed30430 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -44,6 +44,7 @@ namespace Linker { static Binary *binary_ptr = nullptr; bool Linker::verbose = false; +Stage Linker::stage = STAGE_BINARY; Link_map *Link_map::first; /** @@ -103,7 +104,7 @@ class Linker::Elf_object : public Object, private Fifo::Element bool _init_elf_file(Env &env, Allocator &md_alloc, char const *path) { - _elf_file.construct(env, md_alloc, Linker::file(path), true); + _elf_file.construct(env, md_alloc, path, true); Object::init(Linker::file(path), *_elf_file); return true; } @@ -415,6 +416,7 @@ struct Linker::Binary : private Root_object, public Elf_object for (Func * dtor = dtors_start; dtor != dtors_end; genode_atexit(*dtor++)); static_construction_finished = true; + stage = STAGE_SO; } void call_entry_point(Env &env) @@ -439,6 +441,8 @@ struct Linker::Binary : private Root_object, public Elf_object "Genode::Env::exec_static_constructors())"); throw Fatal(); } + + stage = STAGE_SO; return; } diff --git a/repos/base/src/lib/timeout/timer_connection.cc b/repos/base/src/lib/timeout/timer_connection.cc index 614dd2315..6fb791653 100644 --- a/repos/base/src/lib/timeout/timer_connection.cc +++ b/repos/base/src/lib/timeout/timer_connection.cc @@ -127,19 +127,24 @@ void Timer::Connection::_enable_modern_mode() } -Timer::Connection::Connection(Genode::Env &env, char const *label) +Timer::Connection::Connection(Genode::Env &env, Genode::Entrypoint &ep, + char const *label) : Genode::Connection(env, session(env.parent(), "ram_quota=10K, cap_quota=%u, label=\"%s\"", CAP_QUOTA, label)), Session_client(cap()), - _signal_handler(env.ep(), *this, &Connection::_handle_timeout) + _signal_handler(ep, *this, &Connection::_handle_timeout) { /* register default signal handler */ Session_client::sigh(_default_sigh_cap); } +Timer::Connection::Connection(Genode::Env &env, char const *label) +: Timer::Connection(env, env.ep(), label) {} + + void Timer::Connection::_schedule_one_shot(Timeout &timeout, Microseconds duration) { _enable_modern_mode(); diff --git a/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash b/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash index 0a37eac6b..7fabf135c 100644 --- a/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash +++ b/repos/dde_bsd/recipes/pkg/bsd_audio_drv/hash @@ -1 +1 @@ -2019-09-19 93dc8a9254f3bb33c2aeba9bb58005f60361b948 +2019-11-25 18a51f3b40496c6d940ef57ca78e237e9aecee3e diff --git a/repos/dde_bsd/recipes/src/bsd_audio_drv/hash b/repos/dde_bsd/recipes/src/bsd_audio_drv/hash index 31c668fe4..2ffa009a3 100644 --- a/repos/dde_bsd/recipes/src/bsd_audio_drv/hash +++ b/repos/dde_bsd/recipes/src/bsd_audio_drv/hash @@ -1 +1 @@ -2019-09-19 12aa13886006c7bc6fdd55821a358b76a2664ee7 +2019-11-25 06674b444fc31908c339b136e54ecc0e8e167abc diff --git a/repos/dde_ipxe/recipes/pkg/ipxe_nic_drv/hash b/repos/dde_ipxe/recipes/pkg/ipxe_nic_drv/hash index c5f675da3..ae37fde7e 100644 --- a/repos/dde_ipxe/recipes/pkg/ipxe_nic_drv/hash +++ b/repos/dde_ipxe/recipes/pkg/ipxe_nic_drv/hash @@ -1 +1 @@ -2019-09-19 b9ee19221e0712623f23e161ae9979a123b3f061 +2019-11-25 cf0e047500ba7e63b11c0910c189b4fd191afb1e diff --git a/repos/dde_ipxe/recipes/src/ipxe_nic_drv/hash b/repos/dde_ipxe/recipes/src/ipxe_nic_drv/hash index 9fa7ec864..2e0e0a029 100644 --- a/repos/dde_ipxe/recipes/src/ipxe_nic_drv/hash +++ b/repos/dde_ipxe/recipes/src/ipxe_nic_drv/hash @@ -1 +1 @@ -2019-09-19 396abd627225fd20fbe5bcc361036c11eccee8b0 +2019-11-25 4484bc38fc64d5d3a91aecf47d9745780512fd79 diff --git a/repos/dde_linux/lib/import/import-usb_arch_include.mk b/repos/dde_linux/lib/import/import-usb_arch_include.mk new file mode 100644 index 000000000..851563d1b --- /dev/null +++ b/repos/dde_linux/lib/import/import-usb_arch_include.mk @@ -0,0 +1,27 @@ +# architecture-dependent includes +ifeq ($(filter-out $(SPECS),x86),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86 + ifeq ($(filter-out $(SPECS),32bit),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32 + endif # 32bit + ifeq ($(filter-out $(SPECS),64bit),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64 + endif # 64bit +endif # x86 + +ifeq ($(filter-out $(SPECS),arm),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm + ifeq ($(filter-out $(SPECS),arm_v6),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6 + endif # arm_v6 + ifeq ($(filter-out $(SPECS),arm_v7),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 + endif # arm_v7 +endif # arm + +ifeq ($(filter-out $(SPECS),arm_64),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_64 + ifeq ($(filter-out $(SPECS),arm_v8),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v8 + endif # arm_v8 +endif # arm_64 diff --git a/repos/dde_linux/lib/import/import-usb_hid_include.mk b/repos/dde_linux/lib/import/import-usb_hid_include.mk index 75476a3be..84edf2e3c 100644 --- a/repos/dde_linux/lib/import/import-usb_hid_include.mk +++ b/repos/dde_linux/lib/import/import-usb_hid_include.mk @@ -1,26 +1,6 @@ USB_HID_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_hid -# architecture-dependent includes -ifeq ($(filter-out $(SPECS),x86),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86 - ifeq ($(filter-out $(SPECS),32bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32 - endif # 32bit - ifeq ($(filter-out $(SPECS),64bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64 - endif # 64bit -endif # x86 - -ifeq ($(filter-out $(SPECS),arm),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm - ifeq ($(filter-out $(SPECS),arm_v6),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6 - endif # arm_v6 - ifeq ($(filter-out $(SPECS),arm_v7),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 - endif # arm_v7 -endif # arm - +include $(call select_from_repositories,lib/import/import-usb_arch_include.mk) # # The order of include-search directories is important, we need to look into diff --git a/repos/dde_linux/lib/import/import-usb_host_include.mk b/repos/dde_linux/lib/import/import-usb_host_include.mk index f9ab34188..a1686ef75 100644 --- a/repos/dde_linux/lib/import/import-usb_host_include.mk +++ b/repos/dde_linux/lib/import/import-usb_host_include.mk @@ -1,26 +1,6 @@ USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_host -# architecture-dependent includes -ifeq ($(filter-out $(SPECS),x86),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86 - ifeq ($(filter-out $(SPECS),32bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32 - endif # 32bit - ifeq ($(filter-out $(SPECS),64bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64 - endif # 64bit -endif # x86 - -ifeq ($(filter-out $(SPECS),arm),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm - ifeq ($(filter-out $(SPECS),arm_v6),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6 - endif # arm_v6 - ifeq ($(filter-out $(SPECS),arm_v7),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 - endif # arm_v7 -endif # arm - +include $(call select_from_repositories,lib/import/import-usb_arch_include.mk) # # The order of include-search directories is important, we need to look into diff --git a/repos/dde_linux/lib/import/import-usb_include.mk b/repos/dde_linux/lib/import/import-usb_include.mk index bad980972..ca354c063 100644 --- a/repos/dde_linux/lib/import/import-usb_include.mk +++ b/repos/dde_linux/lib/import/import-usb_include.mk @@ -3,27 +3,7 @@ USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/lib/usb LIB_DIR := $(REP_DIR)/src/drivers/usb LIB_INC_DIR := $(LIB_DIR)/include -# architecture-dependent includes -ifeq ($(filter-out $(SPECS),x86),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86 - ifeq ($(filter-out $(SPECS),32bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32 - endif # 32bit - ifeq ($(filter-out $(SPECS),64bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64 - endif # 64bit -endif # x86 - -ifeq ($(filter-out $(SPECS),arm),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm - ifeq ($(filter-out $(SPECS),arm_v6),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6 - endif # arm_v6 - ifeq ($(filter-out $(SPECS),arm_v7),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 - endif # arm_v7 -endif # arm - +include $(call select_from_repositories,lib/import/import-usb_arch_include.mk) # # The order of include-search directories is important, we need to look into diff --git a/repos/dde_linux/lib/import/import-usb_net_include.mk b/repos/dde_linux/lib/import/import-usb_net_include.mk index 79e6fb4c9..a40775d00 100644 --- a/repos/dde_linux/lib/import/import-usb_net_include.mk +++ b/repos/dde_linux/lib/import/import-usb_net_include.mk @@ -1,26 +1,6 @@ USB_NET_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_net -# architecture-dependent includes -ifeq ($(filter-out $(SPECS),x86),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86 - ifeq ($(filter-out $(SPECS),32bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32 - endif # 32bit - ifeq ($(filter-out $(SPECS),64bit),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64 - endif # 64bit -endif # x86 - -ifeq ($(filter-out $(SPECS),arm),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm - ifeq ($(filter-out $(SPECS),arm_v6),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6 - endif # arm_v6 - ifeq ($(filter-out $(SPECS),arm_v7),) - ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 - endif # arm_v7 -endif # arm - +include $(call select_from_repositories,lib/import/import-usb_arch_include.mk) # # The order of include-search directories is important, we need to look into diff --git a/repos/dde_linux/ports/dde_linux.hash b/repos/dde_linux/ports/dde_linux.hash index 914809fc3..7b5dd58c1 100644 --- a/repos/dde_linux/ports/dde_linux.hash +++ b/repos/dde_linux/ports/dde_linux.hash @@ -1 +1 @@ -aa28d681fc4c5c74f8e287608db1aedcb5cc35fc +234e76f366dc583176c0695d33886fb6576765c2 diff --git a/repos/dde_linux/ports/dde_linux.port b/repos/dde_linux/ports/dde_linux.port index ac25d38e6..b4149d1aa 100644 --- a/repos/dde_linux/ports/dde_linux.port +++ b/repos/dde_linux/ports/dde_linux.port @@ -133,9 +133,9 @@ DIR(wpa_supplicant) := src/app/wpa_supplicant # # Firmware images # -FW_REV := f92004aacf48a9e60c9d90f7e972bc3bb5184fb3 +FW_REV := 73f503c65139f368e6155eed8c74d006a2f0219d URL(fw) := https://github.com/cnuke/dde_linux_firmware/archive/$(FW_REV).tar.gz -SHA(fw) := b927a83c4a5a20c9cc3f8bfb453f07278e222f84da4f17a44ab26f362eebad38 +SHA(fw) := d5a61cb07384a828560b8f869e4e899cb723d462646a48b45c398514bb246925 DIR(fw) := firmware # diff --git a/repos/dde_linux/recipes/pkg/drivers_interactive-rpi/hash b/repos/dde_linux/recipes/pkg/drivers_interactive-rpi/hash index e7d7a8c15..4771aa60f 100644 --- a/repos/dde_linux/recipes/pkg/drivers_interactive-rpi/hash +++ b/repos/dde_linux/recipes/pkg/drivers_interactive-rpi/hash @@ -1 +1 @@ -2019-09-19 6760ba25ae3e519485112590855fe4a46cc4f366 +2019-11-25 ff269722feae30e41b39bbeb418e6eafe1a25376 diff --git a/repos/dde_linux/recipes/pkg/drivers_nic-imx53_qsb/hash b/repos/dde_linux/recipes/pkg/drivers_nic-imx53_qsb/hash index 0eefbe40d..87dd0b185 100644 --- a/repos/dde_linux/recipes/pkg/drivers_nic-imx53_qsb/hash +++ b/repos/dde_linux/recipes/pkg/drivers_nic-imx53_qsb/hash @@ -1 +1 @@ -2019-09-19 2489346103cd672e7d56063074d7ad5ffa84cce9 +2019-11-25 451694569f53e996ac0fdd83c236f726ca217ae7 diff --git a/repos/dde_linux/recipes/pkg/drivers_nic-imx6q_sabrelite/hash b/repos/dde_linux/recipes/pkg/drivers_nic-imx6q_sabrelite/hash index 02b291ad4..993994899 100644 --- a/repos/dde_linux/recipes/pkg/drivers_nic-imx6q_sabrelite/hash +++ b/repos/dde_linux/recipes/pkg/drivers_nic-imx6q_sabrelite/hash @@ -1 +1 @@ -2019-09-19 76a1e8fe2f24ab701548c48a2eccc43ea573c9b1 +2019-11-25 396027871987594f6dcf59da4ae1448e23567128 diff --git a/repos/dde_linux/recipes/pkg/drivers_nic-imx7d_sabre/hash b/repos/dde_linux/recipes/pkg/drivers_nic-imx7d_sabre/hash index 29b24f418..2a94b9455 100644 --- a/repos/dde_linux/recipes/pkg/drivers_nic-imx7d_sabre/hash +++ b/repos/dde_linux/recipes/pkg/drivers_nic-imx7d_sabre/hash @@ -1 +1 @@ -2019-09-19 712b415b293b0c152b064434fe0063dabf8c3548 +2019-11-25 0f218e8cade0b91d64646779d5e19220713ba57c diff --git a/repos/dde_linux/recipes/pkg/drivers_nic-imx8q_evk/hash b/repos/dde_linux/recipes/pkg/drivers_nic-imx8q_evk/hash index 8dd6643ab..851101525 100644 --- a/repos/dde_linux/recipes/pkg/drivers_nic-imx8q_evk/hash +++ b/repos/dde_linux/recipes/pkg/drivers_nic-imx8q_evk/hash @@ -1 +1 @@ -2019-09-19 023a58f7d369a15db60743ec66791036d273f471 +2019-11-25 a9dcaf63ab9659ba7db43550d5ad8f15d6cb7efa diff --git a/repos/dde_linux/recipes/pkg/wifi/hash b/repos/dde_linux/recipes/pkg/wifi/hash index 287621eaf..d7c01e543 100644 --- a/repos/dde_linux/recipes/pkg/wifi/hash +++ b/repos/dde_linux/recipes/pkg/wifi/hash @@ -1 +1 @@ -2019-09-19 28e5361d71ca3bebe83336b6bf3ad6e06e8ba137 +2019-11-25 925a75fe95ea39bdb037d8b34e61d2d9f9642aed diff --git a/repos/dde_linux/recipes/pkg/wifi/runtime b/repos/dde_linux/recipes/pkg/wifi/runtime index e2324eefd..ada54c166 100644 --- a/repos/dde_linux/recipes/pkg/wifi/runtime +++ b/repos/dde_linux/recipes/pkg/wifi/runtime @@ -28,6 +28,7 @@ + @@ -36,5 +37,6 @@ + diff --git a/repos/dde_linux/recipes/raw/wifi_firmware/hash b/repos/dde_linux/recipes/raw/wifi_firmware/hash index bb25642d0..c1f691ebb 100644 --- a/repos/dde_linux/recipes/raw/wifi_firmware/hash +++ b/repos/dde_linux/recipes/raw/wifi_firmware/hash @@ -1 +1 @@ -2019-02-25 c617fcdb2cd5a324fc37aad449b75dca38a03afc +2019-11-25 ff24f3bafaeeb47c053670264b5096dbc4b9a36d diff --git a/repos/dde_linux/recipes/src/fec_nic_drv/hash b/repos/dde_linux/recipes/src/fec_nic_drv/hash index d5033a8cd..48bf18a15 100644 --- a/repos/dde_linux/recipes/src/fec_nic_drv/hash +++ b/repos/dde_linux/recipes/src/fec_nic_drv/hash @@ -1 +1 @@ -2019-09-19 83483b561ed39e51cc5861536801a9480a55d3cd +2019-11-25 894fd0558066e1da235c5a1d4668ddbbae196602 diff --git a/repos/dde_linux/recipes/src/intel_fb_drv/hash b/repos/dde_linux/recipes/src/intel_fb_drv/hash index 591c673bc..c058a26a4 100644 --- a/repos/dde_linux/recipes/src/intel_fb_drv/hash +++ b/repos/dde_linux/recipes/src/intel_fb_drv/hash @@ -1 +1 @@ -2019-09-19 a310d9eecd470b8b16f3d14a1703fe44295470ad +2019-11-25 d91e0586dd7a4b518b28df485dc71a7efa8f20a3 diff --git a/repos/dde_linux/recipes/src/usb_drv/content.mk b/repos/dde_linux/recipes/src/usb_drv/content.mk index a3cd1259d..9be6e28b4 100644 --- a/repos/dde_linux/recipes/src/usb_drv/content.mk +++ b/repos/dde_linux/recipes/src/usb_drv/content.mk @@ -1,4 +1,5 @@ LIB_MK := lib/import/import-usb_include.mk lib/mk/usb_include.mk lib/mk/rpi_usb.mk \ + lib/import/import-usb_arch_include.mk \ $(foreach SPEC,x86_32 x86_64 arm,lib/mk/spec/$(SPEC)/lx_kit_setjmp.mk) PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_linux) diff --git a/repos/dde_linux/recipes/src/usb_drv/hash b/repos/dde_linux/recipes/src/usb_drv/hash index cfd6e8b26..cfc802554 100644 --- a/repos/dde_linux/recipes/src/usb_drv/hash +++ b/repos/dde_linux/recipes/src/usb_drv/hash @@ -1 +1 @@ -2019-09-19 9d229dad952cff53c23855c1ab7b7991e22dc117 +2019-11-25 0917226acd966fba648501943d178739f496ea90 diff --git a/repos/dde_linux/recipes/src/vfs_lxip/hash b/repos/dde_linux/recipes/src/vfs_lxip/hash index d879a050b..30a19d696 100644 --- a/repos/dde_linux/recipes/src/vfs_lxip/hash +++ b/repos/dde_linux/recipes/src/vfs_lxip/hash @@ -1 +1 @@ -2019-09-19 1351f59edca89d10adc23fd94fb3e6cfbceeb88a +2019-11-25 75467294387b832bb8a1b29e4c694c573acd51b3 diff --git a/repos/dde_linux/recipes/src/wifi_drv/hash b/repos/dde_linux/recipes/src/wifi_drv/hash index c9df36823..2dedb1ad6 100644 --- a/repos/dde_linux/recipes/src/wifi_drv/hash +++ b/repos/dde_linux/recipes/src/wifi_drv/hash @@ -1 +1 @@ -2019-09-19 96a3f0cf4f8fbb2d9693d83b43ec663b057adce1 +2019-11-25 3f4b5bd36ca0f4e647e87b163b98858458561c4d diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/include/lx_emul.h b/repos/dde_linux/src/drivers/framebuffer/intel/include/lx_emul.h index 226e688e3..f53a117d5 100644 --- a/repos/dde_linux/src/drivers/framebuffer/intel/include/lx_emul.h +++ b/repos/dde_linux/src/drivers/framebuffer/intel/include/lx_emul.h @@ -388,8 +388,15 @@ static inline u64 get_jiffies_64(void) { return jiffies; } #include #include + #include +LX_MUTEX_INIT_DECLARE(bridge_lock); +LX_MUTEX_INIT_DECLARE(core_lock); + +#define bridge_lock LX_MUTEX(bridge_lock) +#define core_lock LX_MUTEX(core_lock) + static inline int mutex_lock_interruptible(struct mutex *lock) { mutex_lock(lock); diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/main.cc b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc index 1553189e7..352055d9e 100644 --- a/repos/dde_linux/src/drivers/framebuffer/intel/main.cc +++ b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc @@ -60,6 +60,9 @@ struct Main Lx_kit::construct_env(env); + LX_MUTEX_INIT(bridge_lock); + LX_MUTEX_INIT(core_lock); + /* init singleton Lx::Scheduler */ Lx::scheduler(&env); diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.h b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h index 685e04125..e006905f9 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.h +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.h @@ -145,6 +145,13 @@ size_t iov_iter_count(struct iov_iter *i); container_of(callback_timer, typeof(*var), timer_fieldname) #include + +LX_MUTEX_INIT_DECLARE(mdio_board_lock); +LX_MUTEX_INIT_DECLARE(phy_fixup_lock); + +#define mdio_board_lock LX_MUTEX(mdio_board_lock) +#define phy_fixup_lock LX_MUTEX(phy_fixup_lock) + #include #include #include diff --git a/repos/dde_linux/src/drivers/nic/fec/main.cc b/repos/dde_linux/src/drivers/nic/fec/main.cc index 122b00a27..f6e7b0d3a 100644 --- a/repos/dde_linux/src/drivers/nic/fec/main.cc +++ b/repos/dde_linux/src/drivers/nic/fec/main.cc @@ -56,6 +56,9 @@ struct Main Lx_kit::construct_env(env); + LX_MUTEX_INIT(mdio_board_lock); + LX_MUTEX_INIT(phy_fixup_lock); + /* init singleton Lx::Scheduler */ Lx::scheduler(&env); diff --git a/repos/dde_linux/src/drivers/usb/include/lx_emul.h b/repos/dde_linux/src/drivers/usb/include/lx_emul.h index 13590df58..5252a166a 100644 --- a/repos/dde_linux/src/drivers/usb/include/lx_emul.h +++ b/repos/dde_linux/src/drivers/usb/include/lx_emul.h @@ -563,6 +563,22 @@ void *kmalloc_array(size_t n, size_t size, gfp_t flags); #include +LX_MUTEX_INIT_DECLARE(hid_open_mut); +LX_MUTEX_INIT_DECLARE(host_cmd_pool_mutex); +LX_MUTEX_INIT_DECLARE(input_mutex); +LX_MUTEX_INIT_DECLARE(usb_bus_list_lock); +LX_MUTEX_INIT_DECLARE(usb_port_peer_mutex); +LX_MUTEX_INIT_DECLARE(usbfs_mutex); +LX_MUTEX_INIT_DECLARE(wacom_udev_list_lock); + +#define hid_open_mut LX_MUTEX(hid_open_mut) +#define host_cmd_pool_mutex LX_MUTEX(host_cmd_pool_mutex) +#define input_mutex LX_MUTEX(input_mutex) +#define usb_bus_list_lock LX_MUTEX(usb_bus_list_lock) +#define usb_port_peer_mutex LX_MUTEX(usb_port_peer_mutex) +#define usbfs_mutex LX_MUTEX(usbfs_mutex) +#define wacom_udev_list_lock LX_MUTEX(wacom_udev_list_lock) + int mutex_lock_interruptible(struct mutex *m); diff --git a/repos/dde_linux/src/drivers/usb/main.cc b/repos/dde_linux/src/drivers/usb/main.cc index ac963204c..36aef61a3 100644 --- a/repos/dde_linux/src/drivers/usb/main.cc +++ b/repos/dde_linux/src/drivers/usb/main.cc @@ -106,6 +106,14 @@ void start_usb_driver(Genode::Env &env) /* initialize USB env */ Lx_kit::construct_env(env); + LX_MUTEX_INIT(hid_open_mut); + LX_MUTEX_INIT(host_cmd_pool_mutex); + LX_MUTEX_INIT(input_mutex); + LX_MUTEX_INIT(usb_bus_list_lock); + LX_MUTEX_INIT(usb_port_peer_mutex); + LX_MUTEX_INIT(usbfs_mutex); + LX_MUTEX_INIT(wacom_udev_list_lock); + /* sets up backend alloc needed by malloc */ backend_alloc_init(env, env.ram(), Lx_kit::env().heap()); diff --git a/repos/dde_linux/src/drivers/usb/nic/nic.cc b/repos/dde_linux/src/drivers/usb/nic/nic.cc index cb571ac0a..01fcd16d9 100644 --- a/repos/dde_linux/src/drivers/usb/nic/nic.cc +++ b/repos/dde_linux/src/drivers/usb/nic/nic.cc @@ -73,7 +73,7 @@ class Skb { unsigned const IDX = _entries / ENTRY_ELEMENT_SIZE; - for (register unsigned i = 0; i < IDX; i++) { + for (unsigned i = 0; i < IDX; i++) { if (_free[_idx] != 0) { unsigned msb = Genode::log2(_free[_idx]); _free[_idx] ^= (1 << msb); @@ -666,7 +666,7 @@ struct sk_buff *skb_dequeue(struct sk_buff_head *list) ** linux/inerrupt.h ** **********************/ -static void snprint_mac(u8 *buf, u8 *mac) +static void snprint_mac(char *buf, u8 *mac) { for (int i = 0; i < ETH_ALEN; i++) { @@ -698,7 +698,7 @@ void eth_random_addr(u8 *addr) void random_ether_addr(u8 *addr) { using namespace Genode; - u8 str[MAC_LEN + 1]; + char str[MAC_LEN + 1]; u8 fallback[] = { 0x2e, 0x60, 0x90, 0x0c, 0x4e, 0x01 }; Nic::Mac_address mac; @@ -712,7 +712,7 @@ void random_ether_addr(u8 *addr) } catch (...) { /* use fallback mac */ snprint_mac(str, fallback); - Genode::warning("No mac address or wrong format attribute in - using fallback (", str, ")"); + Genode::warning("No mac address or wrong format attribute in - using fallback (", Genode::Cstring(str), ")"); Genode::memcpy(addr, fallback, ETH_ALEN); return; @@ -721,7 +721,7 @@ void random_ether_addr(u8 *addr) /* use configured mac*/ Genode::memcpy(addr, mac.addr, ETH_ALEN); snprint_mac(str, (u8 *)mac.addr); - Genode::log("Using configured mac: ", str); + Genode::log("Using configured mac: ", Genode::Cstring(str)); #ifdef GENODE_NET_STAT _stat.set_mac(mac.addr); diff --git a/repos/dde_linux/src/drivers/usb_hid/lx_emul.h b/repos/dde_linux/src/drivers/usb_hid/lx_emul.h index 368020338..6549ca6af 100644 --- a/repos/dde_linux/src/drivers/usb_hid/lx_emul.h +++ b/repos/dde_linux/src/drivers/usb_hid/lx_emul.h @@ -34,8 +34,18 @@ typedef int clockid_t; #include #include + #include +LX_MUTEX_INIT_DECLARE(dquirks_lock); +LX_MUTEX_INIT_DECLARE(input_mutex); +LX_MUTEX_INIT_DECLARE(wacom_udev_list_lock); + +#define dquirks_lock LX_MUTEX(dquirks_lock) +#define input_mutex LX_MUTEX(input_mutex) +#define wacom_udev_list_lock LX_MUTEX(wacom_udev_list_lock) + + typedef __u16 __le16; typedef __u32 __le32; typedef __u64 __le64; diff --git a/repos/dde_linux/src/drivers/usb_hid/main.cc b/repos/dde_linux/src/drivers/usb_hid/main.cc index 8f61f6301..dd6ff26f9 100644 --- a/repos/dde_linux/src/drivers/usb_hid/main.cc +++ b/repos/dde_linux/src/drivers/usb_hid/main.cc @@ -270,6 +270,11 @@ Driver::Driver(Genode::Env &env) : env(env) Genode::log("--- USB HID input driver ---"); Lx_kit::construct_env(env); + + LX_MUTEX_INIT(dquirks_lock); + LX_MUTEX_INIT(input_mutex); + LX_MUTEX_INIT(wacom_udev_list_lock); + Lx::scheduler(&env); Lx::malloc_init(env, heap); Lx::timer(&env, &ep, &heap, &jiffies); diff --git a/repos/dde_linux/src/drivers/usb_host/lx_emul.h b/repos/dde_linux/src/drivers/usb_host/lx_emul.h index 64de8c0ca..43156e18b 100644 --- a/repos/dde_linux/src/drivers/usb_host/lx_emul.h +++ b/repos/dde_linux/src/drivers/usb_host/lx_emul.h @@ -437,6 +437,16 @@ void *kmalloc_array(size_t n, size_t size, gfp_t flags); #include +LX_MUTEX_INIT_DECLARE(init_usb_class_mutex); +LX_MUTEX_INIT_DECLARE(usb_bus_idr_lock); +LX_MUTEX_INIT_DECLARE(usb_port_peer_mutex); +LX_MUTEX_INIT_DECLARE(usbfs_mutex); + +#define init_usb_class_mutex LX_MUTEX(init_usb_class_mutex) +#define usb_bus_idr_lock LX_MUTEX(usb_bus_idr_lock) +#define usb_port_peer_mutex LX_MUTEX(usb_port_peer_mutex) +#define usbfs_mutex LX_MUTEX(usbfs_mutex) + /******************* ** linux/rwsem.h ** diff --git a/repos/dde_linux/src/drivers/usb_host/main.cc b/repos/dde_linux/src/drivers/usb_host/main.cc index dc9664d49..080df0fbd 100644 --- a/repos/dde_linux/src/drivers/usb_host/main.cc +++ b/repos/dde_linux/src/drivers/usb_host/main.cc @@ -69,6 +69,11 @@ static void start_usb_driver(Genode::Env &env) /* initialize USB env */ Lx_kit::construct_env(env); + LX_MUTEX_INIT(init_usb_class_mutex); + LX_MUTEX_INIT(usb_bus_idr_lock); + LX_MUTEX_INIT(usb_port_peer_mutex); + LX_MUTEX_INIT(usbfs_mutex); + /* sets up backend alloc needed by malloc */ backend_alloc_init(env, env.ram(), Lx_kit::env().heap()); diff --git a/repos/dde_linux/src/drivers/usb_net/lx_emul.cc b/repos/dde_linux/src/drivers/usb_net/lx_emul.cc index df114c392..47545fc96 100644 --- a/repos/dde_linux/src/drivers/usb_net/lx_emul.cc +++ b/repos/dde_linux/src/drivers/usb_net/lx_emul.cc @@ -275,7 +275,7 @@ u32 get_unaligned_le32(const void *p) enum { MAC_LEN = 17 }; -static void snprint_mac(u8 *buf, u8 *mac) +static void snprint_mac(char *buf, u8 *mac) { for (int i = 0; i < ETH_ALEN; i++) { Genode::snprintf((char *)&buf[i * 3], 3, "%02x", mac[i]); @@ -291,7 +291,7 @@ static void random_ether_addr(u8 *addr) { using namespace Genode; - u8 str[MAC_LEN + 1]; + char str[MAC_LEN + 1]; u8 fallback[] = { 0x2e, 0x60, 0x90, 0x0c, 0x4e, 0x01 }; Nic::Mac_address mac; @@ -304,7 +304,7 @@ static void random_ether_addr(u8 *addr) } catch (...) { /* use fallback mac */ snprint_mac(str, fallback); - Genode::warning("No mac address or wrong format attribute in - using fallback (", str, ")"); + Genode::warning("No mac address or wrong format attribute in - using fallback (", Genode::Cstring(str), ")"); Genode::memcpy(addr, fallback, ETH_ALEN); return; @@ -313,7 +313,7 @@ static void random_ether_addr(u8 *addr) /* use configured mac*/ Genode::memcpy(addr, mac.addr, ETH_ALEN); snprint_mac(str, (u8 *)mac.addr); - Genode::log("Using configured mac: ", str); + Genode::log("Using configured mac: ", Genode::Cstring(str)); } diff --git a/repos/dde_linux/src/include/lx_emul/mutex.h b/repos/dde_linux/src/include/lx_emul/mutex.h index bb90995f7..9cc7d2e4f 100644 --- a/repos/dde_linux/src/include/lx_emul/mutex.h +++ b/repos/dde_linux/src/include/lx_emul/mutex.h @@ -3,6 +3,7 @@ * \author Norman Feske * \author Sebastian Sumpf * \author Josef Soentgen + * \author Christian Helmuth * \date 2014-08-21 * * Based on the prototypes found in the Linux kernel's 'include/'. @@ -29,9 +30,26 @@ struct mutex }; #define DEFINE_MUTEX(mutexname) \ - struct mutex mutexname; \ - static void __attribute__((constructor)) mutex_init_ ## mutexname(void) \ - { mutex_init(&mutexname); } + struct mutex lx_mutex_ ## mutexname; \ + void lx_mutex_init_ ## mutexname(void) \ + { mutex_init(&lx_mutex_ ## mutexname); } + +/* + * Note, you must define a rename for 'mutexname' in lx_emul.h and explicitly + * call the LX_MUTEX_INIT() initializer on startup. + * + * lx_emul.h: + * + * LX_MUTEX_INIT_DECLARE(mutexname) + * #define mutexname LX_MUTEX(mutexname) + * + * lx_emul.cc: + * + * LX_MUTEX_INIT(mutexname); + */ +#define LX_MUTEX(mutexname) lx_mutex_ ## mutexname +#define LX_MUTEX_INIT(mutexname) lx_mutex_init_ ## mutexname() +#define LX_MUTEX_INIT_DECLARE(mutexname) extern void LX_MUTEX_INIT(mutexname) void mutex_init(struct mutex *m); void mutex_destroy(struct mutex *m); diff --git a/repos/dde_linux/src/lib/lxip/include/lx_emul.h b/repos/dde_linux/src/lib/lxip/include/lx_emul.h index b5d08e939..29e355ddb 100644 --- a/repos/dde_linux/src/lib/lxip/include/lx_emul.h +++ b/repos/dde_linux/src/lib/lxip/include/lx_emul.h @@ -877,6 +877,12 @@ void debug_check_no_locks_freed(const void *from, unsigned long len); #include +LX_MUTEX_INIT_DECLARE(dst_gc_mutex); +LX_MUTEX_INIT_DECLARE(proto_list_mutex); + +#define dst_gc_mutex LX_MUTEX(dst_gc_mutex) +#define proto_list_mutex LX_MUTEX(proto_list_mutex) + /*********************************** ** linux/rwlock_types.h/rwlock.h ** diff --git a/repos/dde_linux/src/lib/lxip/lxcc_emul.cc b/repos/dde_linux/src/lib/lxip/lxcc_emul.cc index 2672f13a4..9857e1f64 100644 --- a/repos/dde_linux/src/lib/lxip/lxcc_emul.cc +++ b/repos/dde_linux/src/lib/lxip/lxcc_emul.cc @@ -37,13 +37,26 @@ #include +struct Memory_object_base; + static Lx_kit::Env *lx_env; +static Genode::Object_pool *memory_pool_ptr; + + void Lx::lxcc_emul_init(Lx_kit::Env &env) { + static Genode::Object_pool memory_pool; + + memory_pool_ptr = &memory_pool; + lx_env = &env; + + LX_MUTEX_INIT(dst_gc_mutex); + LX_MUTEX_INIT(proto_list_mutex); } + struct Memory_object_base : Genode::Object_pool::Entry { Memory_object_base(Genode::Ram_dataspace_capability cap) @@ -59,9 +72,6 @@ struct Memory_object_base : Genode::Object_pool::Entry }; -static Genode::Object_pool memory_pool; - - Genode::Ram_dataspace_capability Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) { @@ -70,7 +80,7 @@ Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) Genode::Ram_dataspace_capability cap = lx_env->ram().alloc(size); Memory_object_base *o = new (lx_env->heap()) Memory_object_base(cap); - memory_pool.insert(o); + memory_pool_ptr->insert(o); return cap; } @@ -80,11 +90,11 @@ void Lx::backend_free(Genode::Ram_dataspace_capability cap) using namespace Genode; Memory_object_base *object; - memory_pool.apply(cap, [&] (Memory_object_base *o) { + memory_pool_ptr->apply(cap, [&] (Memory_object_base *o) { if (!o) return; o->free(); - memory_pool.remove(o); + memory_pool_ptr->remove(o); object = o; /* save for destroy */ }); @@ -359,7 +369,11 @@ class Avl_page : public Genode::Avl_node }; -static Genode::Avl_tree tree; +static Genode::Avl_tree & tree() +{ + static Genode::Avl_tree _tree; + return _tree; +} struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) @@ -367,7 +381,7 @@ struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) Avl_page *p; try { p = (Avl_page *)new (lx_env->heap()) Avl_page(PAGE_SIZE << order); - tree.insert(p); + tree().insert(p); } catch (...) { return 0; } return p->page(); @@ -386,9 +400,9 @@ void *__alloc_page_frag(struct page_frag_cache *nc, void __free_page_frag(void *addr) { - Avl_page *p = tree.first()->find_by_address((Genode::addr_t)addr); + Avl_page *p = tree().first()->find_by_address((Genode::addr_t)addr); - tree.remove(p); + tree().remove(p); destroy(lx_env->heap(), p); } @@ -399,7 +413,7 @@ void __free_page_frag(void *addr) struct page *virt_to_head_page(const void *x) { - Avl_page *p = tree.first()->find_by_address((Genode::addr_t)x); + Avl_page *p = tree().first()->find_by_address((Genode::addr_t)x); lx_log(DEBUG_SLAB, "virt_to_head_page: %p page %p\n", x,p ? p->page() : 0); return p ? p->page() : 0; @@ -412,9 +426,9 @@ void put_page(struct page *page) return; lx_log(DEBUG_SLAB, "put_page: %p", page); - Avl_page *p = tree.first()->find_by_address((Genode::addr_t)page->addr); + Avl_page *p = tree().first()->find_by_address((Genode::addr_t)page->addr); - tree.remove(p); + tree().remove(p); destroy(lx_env->heap(), p); } diff --git a/repos/dde_linux/src/lib/lxip/random.cc b/repos/dde_linux/src/lib/lxip/random.cc index 5fe9e8c02..4a7f5b497 100644 --- a/repos/dde_linux/src/lib/lxip/random.cc +++ b/repos/dde_linux/src/lib/lxip/random.cc @@ -65,7 +65,11 @@ struct Xoroshiro }; -static Xoroshiro xoroshiro(42); +static Xoroshiro & xoroshiro() +{ + static Xoroshiro xoroshiro(42); + return xoroshiro; +} /******************** @@ -82,7 +86,7 @@ extern "C" void get_random_bytes(void *buf, int nbytes) int const rounds = nbytes / 8; for (int i = 0; i < rounds; i++) { - uint64_t const v = xoroshiro.get(); + uint64_t const v = xoroshiro().get(); Genode::memcpy(p, &v, 8); p += 8; @@ -93,12 +97,12 @@ extern "C" void get_random_bytes(void *buf, int nbytes) return; } - uint64_t const v = xoroshiro.get(); + uint64_t const v = xoroshiro().get(); Genode::memcpy(p, &v, remain); } extern "C" unsigned int prandom_u32(void) { - return xoroshiro.get(); + return xoroshiro().get(); } diff --git a/repos/dde_linux/src/lib/vfs/lxip/vfs.cc b/repos/dde_linux/src/lib/vfs/lxip/vfs.cc index 3ac47e938..7f25cb88e 100644 --- a/repos/dde_linux/src/lib/vfs/lxip/vfs.cc +++ b/repos/dde_linux/src/lib/vfs/lxip/vfs.cc @@ -381,31 +381,31 @@ struct Vfs::Lxip_vfs_dir_handle final : Vfs::Lxip_vfs_handle /** * Queues of open handles to poll */ -static Vfs::Lxip_vfs_file_handle::Fifo _io_progress_waiters; -static Vfs::Lxip_vfs_file_handle::Fifo _read_ready_waiters; +static Vfs::Lxip_vfs_file_handle::Fifo *_io_progress_waiters_ptr; +static Vfs::Lxip_vfs_file_handle::Fifo *_read_ready_waiters_ptr; static void poll_all() { - _io_progress_waiters.for_each( + _io_progress_waiters_ptr->for_each( [&] (Vfs::Lxip_vfs_file_handle::Fifo_element &elem) { Vfs::Lxip_vfs_file_handle &handle = elem.object(); if (handle.file) { if (handle.file->poll()) { /* do not notify again until some I/O queues */ - _io_progress_waiters.remove(elem); + _io_progress_waiters_ptr->remove(elem); handle.io_progress_response(); } } }); - _read_ready_waiters.for_each( + _read_ready_waiters_ptr->for_each( [&] (Vfs::Lxip_vfs_file_handle::Fifo_element &elem) { Vfs::Lxip_vfs_file_handle &handle = elem.object(); if (handle.file) { if (handle.file->poll()) { /* do not notify again until notify_read_ready */ - _read_ready_waiters.remove(elem); + _read_ready_waiters_ptr->remove(elem); handle.read_ready_response(); } @@ -513,7 +513,7 @@ class Vfs::Lxip_data_file final : public Vfs::Lxip_file Lxip::ssize_t ret = _sock.ops->recvmsg(&_sock, &msg, len, MSG_DONTWAIT); if (ret == -EAGAIN) { - handle.io_enqueue(_io_progress_waiters); + handle.io_enqueue(*_io_progress_waiters_ptr); throw Would_block(); } return ret; @@ -695,6 +695,7 @@ class Vfs::Lxip_connect_file final : public Vfs::Lxip_file switch (_write_err) { case Lxip::Io_result::LINUX_EINPROGRESS: _connecting = true; + _write_err = 0; return len; case Lxip::Io_result::LINUX_EALREADY: @@ -708,6 +709,7 @@ class Vfs::Lxip_connect_file final : public Vfs::Lxip_file */ if (_is_connected || !_connecting) return -1; _is_connected = true; + _write_err = 0; break; default: @@ -843,10 +845,10 @@ class Vfs::Lxip_remote_file final : public Vfs::Lxip_file int const res = _sock.ops->recvmsg(&_sock, &msg, 0, MSG_DONTWAIT|MSG_PEEK); if (res == -EAGAIN) { - handle.io_enqueue(_io_progress_waiters); + handle.io_enqueue(*_io_progress_waiters_ptr); throw Would_block(); } - if (res < 0) return -1; + if (res < 0) return -1; } break; case Lxip::Protocol_dir::TYPE_STREAM: @@ -924,7 +926,7 @@ class Vfs::Lxip_accept_file final : public Vfs::Lxip_file return Genode::strlen(dst); } - handle.io_enqueue(_io_progress_waiters); + handle.io_enqueue(*_io_progress_waiters_ptr); throw Would_block(); } }; @@ -1107,11 +1109,7 @@ class Vfs::Lxip_socket_dir final : public Lxip::Socket_dir Vfs::file_size index = seek_offset / sizeof(Dirent); - Dirent *out = (Dirent*)dst; - - out->fileno = index+1; - out->type = Directory_service::DIRENT_TYPE_END; - out->name[0] = '\0'; + Dirent &out = *(Dirent*)dst; Vfs::Node *node = nullptr; for (Vfs::File *n : _files) { @@ -1123,11 +1121,21 @@ class Vfs::Lxip_socket_dir final : public Lxip::Socket_dir --index; } } - if (!node) return -1; + if (!node) { + out = { + .fileno = index + 1, + .type = Directory_service::Dirent_type::END, + .rwx = { }, + .name = { } }; - out->type = Directory_service::DIRENT_TYPE_FILE; + return -1; + } - strncpy(out->name, node->name(), sizeof(out->name)); + out = { + .fileno = index + 1, + .type = Directory_service::Dirent_type::TRANSACTIONAL_FILE, + .rwx = Node_rwx::rw(), + .name = { node->name() } }; return sizeof(Dirent); } @@ -1435,11 +1443,7 @@ class Lxip::Protocol_dir_impl : public Protocol_dir Vfs::file_size index = seek_offset / sizeof(Dirent); - Dirent *out = (Dirent*)dst; - - out->fileno = index+1; - out->type = Vfs::Directory_service::DIRENT_TYPE_END; - out->name[0] = '\0'; + Dirent &out = *(Dirent*)dst; Vfs::Node *node = nullptr; for (Vfs::Node *n : _nodes) { @@ -1451,15 +1455,32 @@ class Lxip::Protocol_dir_impl : public Protocol_dir --index; } } - if (!node) return -1; + if (!node) { + out = { + .fileno = index + 1, + .type = Vfs::Directory_service::Dirent_type::END, + .rwx = { }, + .name = { } }; - if (dynamic_cast(node)) - out->type = Vfs::Directory_service::DIRENT_TYPE_DIRECTORY; + return -1; + } - if (dynamic_cast(node)) - out->type = Vfs::Directory_service::DIRENT_TYPE_FILE; + typedef Vfs::Directory_service::Dirent_type Dirent_type; - Genode::strncpy(out->name, node->name(), sizeof(out->name)); + Dirent_type const type = + dynamic_cast(node) ? Dirent_type::DIRECTORY : + dynamic_cast(node) ? Dirent_type::TRANSACTIONAL_FILE + : Dirent_type::END; + + Vfs::Node_rwx const rwx = (type == Dirent_type::DIRECTORY) + ? Vfs::Node_rwx::rwx() + : Vfs::Node_rwx::rw(); + + out = { + .fileno = index + 1, + .type = type, + .rwx = rwx, + .name = { node->name() } }; return sizeof(Dirent); } @@ -1692,44 +1713,38 @@ class Vfs::Lxip_file_system : public Vfs::File_system, if (len < sizeof(Dirent)) return -1; - file_size index = seek_offset / sizeof(Dirent); + file_size const index = seek_offset / sizeof(Dirent); - Dirent *out = (Dirent*)dst; + struct Entry + { + void const *fileno; + Dirent_type type; + char const *name; + }; - if (index == 0) { - out->fileno = (Genode::addr_t)&_tcp_dir; - out->type = Directory_service::DIRENT_TYPE_DIRECTORY; - Genode::strncpy(out->name, "tcp", sizeof(out->name)); - } else if (index == 1) { - out->fileno = (Genode::addr_t)&_udp_dir; - out->type = Directory_service::DIRENT_TYPE_DIRECTORY; - Genode::strncpy(out->name, "udp", sizeof(out->name)); - } else if (index == 2) { - out->fileno = (Genode::addr_t)&_address; - out->type = Directory_service::DIRENT_TYPE_FILE; - Genode::strncpy(out->name, "address", sizeof(out->name)); - } else if (index == 3) { - out->fileno = (Genode::addr_t)&_netmask; - out->type = Directory_service::DIRENT_TYPE_FILE; - Genode::strncpy(out->name, "netmask", sizeof(out->name)); - } else if (index == 4) { - out->fileno = (Genode::addr_t)&_gateway; - out->type = Directory_service::DIRENT_TYPE_FILE; - Genode::strncpy(out->name, "gateway", sizeof(out->name)); - } else if (index == 5) { - out->fileno = (Genode::addr_t)&_nameserver; - out->type = Directory_service::DIRENT_TYPE_FILE; - Genode::strncpy(out->name, "nameserver", sizeof(out->name)); - } else if (index == 6) { - out->fileno = (Genode::addr_t)&_link_state; - out->type = Directory_service::DIRENT_TYPE_FILE; - Genode::strncpy(out->name, "link_state", sizeof(out->name)); - } else { - out->fileno = 0; - out->type = Directory_service::DIRENT_TYPE_END; - out->name[0] = '\0'; - } + enum { NUM_ENTRIES = 8U }; + static Entry const entries[NUM_ENTRIES] = { + { &_tcp_dir, Dirent_type::DIRECTORY, "tcp" }, + { &_udp_dir, Dirent_type::DIRECTORY, "udp" }, + { &_address, Dirent_type::TRANSACTIONAL_FILE, "address" }, + { &_netmask, Dirent_type::TRANSACTIONAL_FILE, "netmask" }, + { &_gateway, Dirent_type::TRANSACTIONAL_FILE, "gateway" }, + { &_nameserver, Dirent_type::TRANSACTIONAL_FILE, "nameserver" }, + { &_link_state, Dirent_type::TRANSACTIONAL_FILE, "link_state" }, + { nullptr, Dirent_type::END, "" } + }; + Entry const &entry = entries[min(index, NUM_ENTRIES - 1U)]; + + Dirent &out = *(Dirent*)dst; + + out = { + .fileno = (Genode::addr_t)entry.fileno, + .type = entry.type, + .rwx = entry.type == Dirent_type::DIRECTORY + ? Node_rwx::rwx() : Node_rwx::rw(), + .name = { entry.name } + }; return sizeof(Dirent); } @@ -1746,23 +1761,27 @@ class Vfs::Lxip_file_system : public Vfs::File_system, Stat_result stat(char const *path, Stat &out) override { - Vfs::Node *node = _lookup(path); + Node *node = _lookup(path); if (!node) return STAT_ERR_NO_ENTRY; - Vfs::Directory *dir = dynamic_cast(node); - if (dir) { - out.mode = STAT_MODE_DIRECTORY | 0777; + out = { }; + + if (dynamic_cast(node)) { + out.type = Node_type::DIRECTORY; + out.rwx = Node_rwx::rwx(); return STAT_OK; } if (dynamic_cast(node)) { - out.mode = STAT_MODE_FILE | 0666; + out.type = Node_type::TRANSACTIONAL_FILE; + out.rwx = Node_rwx::rw(); out.size = 0; return STAT_OK; } if (dynamic_cast(node)) { - out.mode = STAT_MODE_FILE | 0666; + out.type = Node_type::TRANSACTIONAL_FILE; + out.rwx = Node_rwx::rw(); out.size = 0x1000; /* there may be something to read */ return STAT_OK; } @@ -1855,8 +1874,8 @@ class Vfs::Lxip_file_system : public Vfs::File_system, dynamic_cast(handle); if (file_handle) { - _io_progress_waiters.remove(file_handle->io_progress_elem); - _read_ready_waiters.remove(file_handle->read_ready_elem); + _io_progress_waiters_ptr->remove(file_handle->io_progress_elem); + _read_ready_waiters_ptr->remove(file_handle->read_ready_elem); } Genode::destroy(handle->alloc(), handle); @@ -1913,7 +1932,7 @@ class Vfs::Lxip_file_system : public Vfs::File_system, if (handle) { if (!handle->read_ready_elem.enqueued()) - _read_ready_waiters.enqueue(handle->read_ready_elem); + _read_ready_waiters_ptr->enqueue(handle->read_ready_elem); return true; } @@ -1971,6 +1990,12 @@ struct Lxip_factory : Vfs::File_system_factory extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) { + static Vfs::Lxip_vfs_file_handle::Fifo io_progress_waiters; + static Vfs::Lxip_vfs_file_handle::Fifo read_ready_waiters; + + _io_progress_waiters_ptr = &io_progress_waiters; + _read_ready_waiters_ptr = &read_ready_waiters; + static Lxip_factory factory; return &factory; } diff --git a/repos/dde_linux/src/lib/wifi/firmware.cc b/repos/dde_linux/src/lib/wifi/firmware.cc index d2797b87f..65118ddd1 100644 --- a/repos/dde_linux/src/lib/wifi/firmware.cc +++ b/repos/dde_linux/src/lib/wifi/firmware.cc @@ -25,6 +25,7 @@ Firmware_list fw_list[] = { { "iwlwifi-1000-5.ucode", 337520, nullptr }, { "iwlwifi-3160-17.ucode", 918268, nullptr }, + { "iwlwifi-5000-5.ucode", 340696, nullptr }, { "iwlwifi-6000-4.ucode", 454608, nullptr }, { "iwlwifi-6000-6.ucode", 454608, "iwlwifi-6000-4.ucode" }, { "iwlwifi-6000g2a-6.ucode", 677296, nullptr }, @@ -36,7 +37,10 @@ Firmware_list fw_list[] = { { "iwlwifi-8000C-22.ucode", 2120860, nullptr }, { "iwlwifi-8000C-36.ucode", 2486572, nullptr }, { "iwlwifi-8265-22.ucode", 1811984, nullptr }, - { "iwlwifi-8265-36.ucode", 2498044, nullptr } + { "iwlwifi-8265-36.ucode", 2498044, nullptr }, + + { "iwlwifi-9000-pu-b0-jf-b0-34.ucode", 2678284, nullptr }, + { "iwlwifi-9000-pu-b0-jf-b0-36.ucode", 2678284, "iwlwifi-9000-pu-b0-jf-b0-34.ucode" } }; diff --git a/repos/dde_linux/src/lib/wifi/include/lx_emul.h b/repos/dde_linux/src/lib/wifi/include/lx_emul.h index bb7b3e86a..8fd54cb31 100644 --- a/repos/dde_linux/src/lib/wifi/include/lx_emul.h +++ b/repos/dde_linux/src/lib/wifi/include/lx_emul.h @@ -484,6 +484,24 @@ int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask, #include +LX_MUTEX_INIT_DECLARE(crypto_default_rng_lock); +LX_MUTEX_INIT_DECLARE(fanout_mutex); +LX_MUTEX_INIT_DECLARE(genl_mutex); +LX_MUTEX_INIT_DECLARE(proto_list_mutex); +LX_MUTEX_INIT_DECLARE(rate_ctrl_mutex); +LX_MUTEX_INIT_DECLARE(reg_regdb_apply_mutex); +LX_MUTEX_INIT_DECLARE(rfkill_global_mutex); +LX_MUTEX_INIT_DECLARE(rtnl_mutex); + +#define crypto_default_rng_lock LX_MUTEX(crypto_default_rng_lock) +#define fanout_mutex LX_MUTEX(fanout_mutex) +#define genl_mutex LX_MUTEX(genl_mutex) +#define proto_list_mutex LX_MUTEX(proto_list_mutex) +#define rate_ctrl_mutex LX_MUTEX(rate_ctrl_mutex) +#define reg_regdb_apply_mutex LX_MUTEX(reg_regdb_apply_mutex) +#define rfkill_global_mutex LX_MUTEX(rfkill_global_mutex) +#define rtnl_mutex LX_MUTEX(rtnl_mutex) + /******************* ** linux/rwsem.h ** diff --git a/repos/dde_linux/src/lib/wifi/init.cc b/repos/dde_linux/src/lib/wifi/init.cc index 76f4a46e9..1cc4500e8 100644 --- a/repos/dde_linux/src/lib/wifi/init.cc +++ b/repos/dde_linux/src/lib/wifi/init.cc @@ -185,6 +185,15 @@ void wifi_init(Genode::Env &env, Genode::Lock &lock, bool disable_11n, { Lx_kit::construct_env(env); + LX_MUTEX_INIT(crypto_default_rng_lock); + LX_MUTEX_INIT(fanout_mutex); + LX_MUTEX_INIT(genl_mutex); + LX_MUTEX_INIT(proto_list_mutex); + LX_MUTEX_INIT(rate_ctrl_mutex); + LX_MUTEX_INIT(reg_regdb_apply_mutex); + LX_MUTEX_INIT(rfkill_global_mutex); + LX_MUTEX_INIT(rtnl_mutex); + _wpa_lock = &lock; INIT_LIST_HEAD(&init_net.dev_base_head); diff --git a/repos/dde_linux/src/lx_kit/env.cc b/repos/dde_linux/src/lx_kit/env.cc index be6d163fb..9595c00f8 100644 --- a/repos/dde_linux/src/lx_kit/env.cc +++ b/repos/dde_linux/src/lx_kit/env.cc @@ -13,20 +13,18 @@ #include -/* - * Lx_kit enviroment instance - */ -static Genode::Constructible _env; +static Lx_kit::Env *_env_ptr; Lx_kit::Env &Lx_kit::env() { - return *_env; + return *_env_ptr; } Lx_kit::Env &Lx_kit::construct_env(Genode::Env &env) { - _env.construct(env); - return *_env; + static Lx_kit::Env _env(env); + _env_ptr = &_env; + return _env; } diff --git a/repos/dde_linux/src/lx_kit/malloc.cc b/repos/dde_linux/src/lx_kit/malloc.cc index 9fb6e456f..fa0dd8f27 100644 --- a/repos/dde_linux/src/lx_kit/malloc.cc +++ b/repos/dde_linux/src/lx_kit/malloc.cc @@ -335,19 +335,26 @@ class Lx_kit::Malloc : public Lx::Malloc ** Lx::Malloc implementation ** *******************************/ -static Genode::Constructible _mem_backend_alloc; -static Genode::Constructible _dma_backend_alloc; -static Genode::Constructible _mem_alloc; -static Genode::Constructible _dma_alloc; +static Lx_kit::Slab_backend_alloc *_mem_backend_alloc_ptr; +static Lx_kit::Slab_backend_alloc *_dma_backend_alloc_ptr; + +static Lx_kit::Malloc *_mem_alloc_ptr; +static Lx_kit::Malloc *_dma_alloc_ptr; void Lx::malloc_init(Genode::Env &env, Genode::Allocator &md_alloc) { - _mem_backend_alloc.construct(env, md_alloc, Genode::CACHED); - _dma_backend_alloc.construct(env, md_alloc, Genode::UNCACHED); + static Lx_kit::Slab_backend_alloc mem_backend_alloc(env, md_alloc, Genode::CACHED); + static Lx_kit::Slab_backend_alloc dma_backend_alloc(env, md_alloc, Genode::UNCACHED); - _mem_alloc.construct(*_mem_backend_alloc, Genode::CACHED); - _dma_alloc.construct(*_dma_backend_alloc, Genode::UNCACHED); + _mem_backend_alloc_ptr = &mem_backend_alloc; + _dma_backend_alloc_ptr = &dma_backend_alloc; + + static Lx_kit::Malloc mem_alloc(mem_backend_alloc, Genode::CACHED); + static Lx_kit::Malloc dma_alloc(dma_backend_alloc, Genode::UNCACHED); + + _mem_alloc_ptr = &mem_alloc; + _dma_alloc_ptr = &dma_alloc; } @@ -355,22 +362,22 @@ void Lx::malloc_init(Genode::Env &env, Genode::Allocator &md_alloc) * Cached memory backend allocator */ Lx::Slab_backend_alloc &Lx::Slab_backend_alloc::mem() { - return *_mem_backend_alloc; } + return *_mem_backend_alloc_ptr; } /** * DMA memory backend allocator */ Lx::Slab_backend_alloc &Lx::Slab_backend_alloc::dma() { - return *_dma_backend_alloc; } + return *_dma_backend_alloc_ptr; } /** * Cached memory allocator */ -Lx::Malloc &Lx::Malloc::mem() { return *_mem_alloc; } +Lx::Malloc &Lx::Malloc::mem() { return *_mem_alloc_ptr; } /** * DMA memory allocator */ -Lx::Malloc &Lx::Malloc::dma() { return *_dma_alloc; } +Lx::Malloc &Lx::Malloc::dma() { return *_dma_alloc_ptr; } diff --git a/repos/dde_rump/include/rump/env.h b/repos/dde_rump/include/rump/env.h index 1b94bd5ff..76cdf2159 100644 --- a/repos/dde_rump/include/rump/env.h +++ b/repos/dde_rump/include/rump/env.h @@ -39,7 +39,7 @@ class Rump::Env public: - Env(Genode::Env &env) : _env(env) { } + Env(Genode::Env &env); Genode::Env &env() { return _env; } Timeout_entrypoint &timeout_ep() { return _timeout_ep; } diff --git a/repos/dde_rump/lib/mk/rump_prefix.inc b/repos/dde_rump/lib/mk/rump_prefix.inc index 1c727094a..9a72af49a 100644 --- a/repos/dde_rump/lib/mk/rump_prefix.inc +++ b/repos/dde_rump/lib/mk/rump_prefix.inc @@ -17,4 +17,6 @@ $(OBJ_PREFIX): $(SRC_NOLINK_OBJ) $(SRC_NOLINK) $(RUMP_LIB_BASE)/$(subst rmpns_,,$@) $(RUMP_LIB_BASE)/$@ $(VERBOSE_MK)rm $(RUMP_LIB_BASE)/_$@ +-include $(SRC_NOLINK_OBJ:.o=.d) + # vi:set ft=make : diff --git a/repos/dde_rump/patches/vm_vfs.patch b/repos/dde_rump/patches/rump.patch similarity index 56% rename from repos/dde_rump/patches/vm_vfs.patch rename to repos/dde_rump/patches/rump.patch index 8a01c8955..fe19a25b9 100644 --- a/repos/dde_rump/patches/vm_vfs.patch +++ b/repos/dde_rump/patches/rump.patch @@ -1,3 +1,36 @@ +--- src/lib/dde_rump/src/sys/rump/librump/rumpkern/rump_private.h ++++ src/lib/dde_rump/src/sys/rump/librump/rumpkern/rump_private.h +@@ -70,6 +70,9 @@ + RUMP__FACTION_NET, + + RUMP_COMPONENT_MAX, ++ ++ /* alias for syscall type used to create ctor symbol */ ++ RUMP_COMPONENT_KERN_SYSCALL = RUMP_COMPONENT_SYSCALL, + }; + struct rump_component { + enum rump_component_type rc_type; +@@ -86,8 +89,7 @@ + + #ifdef RUMP_USE_CTOR + #define _RUMP_COMPONENT_REGISTER(type) \ +-static void rumpcomp_ctor##type(void) __attribute__((constructor)); \ +-static void rumpcomp_ctor##type(void) \ ++void rumpcompctor_##type(void) \ + { \ + rump_component_load(&rumpcomp##type); \ + } +--- src/lib/dde_rump/src/sys/rump/librump/rumpkern/rumpkern_syscalls.c ++++ src/lib/dde_rump/src/sys/rump/librump/rumpkern/rumpkern_syscalls.c +@@ -147,7 +147,7 @@ + { 477, sys_clock_nanosleep }, + }; + +-RUMP_COMPONENT(RUMP_COMPONENT_SYSCALL) ++RUMP_COMPONENT(RUMP_COMPONENT_KERN_SYSCALL) + { + + rump_syscall_boot_establish(mysys, __arraycount(mysys)); --- src/lib/dde_rump/src/sys/rump/librump/rumpvfs/vm_vfs.c +++ src/lib/dde_rump/src/sys/rump/librump/rumpvfs/vm_vfs.c @@ -49,6 +49,7 @@ @@ -66,3 +99,15 @@ mutex_enter(bp->b_objlock); vwakeup(bp); mutex_exit(bp->b_objlock); +--- src/lib/dde_rump/src/sys/sys/module.h ++++ src/lib/dde_rump/src/sys/sys/module.h +@@ -114,8 +114,7 @@ + }; + LIST_HEAD(modinfo_boot_chain, modinfo_chain); + #define _MODULE_REGISTER(name) \ +-static void modctor_##name(void) __attribute__((constructor)); \ +-static void modctor_##name(void) \ ++void modctor_##name(void) \ + { \ + static struct modinfo_chain mc = { \ + .mc_info = &name##_modinfo, \ diff --git a/repos/dde_rump/ports/dde_rump.hash b/repos/dde_rump/ports/dde_rump.hash index ab3038b1c..b0473edb8 100644 --- a/repos/dde_rump/ports/dde_rump.hash +++ b/repos/dde_rump/ports/dde_rump.hash @@ -1 +1 @@ -e82aa761750a0a1e76e886fa7ad37da043afe931 +b81e1b234bf98a6b0a35dec429e8a826b735bc08 diff --git a/repos/dde_rump/ports/dde_rump.port b/repos/dde_rump/ports/dde_rump.port index 61936a6f6..2ba10f713 100644 --- a/repos/dde_rump/ports/dde_rump.port +++ b/repos/dde_rump/ports/dde_rump.port @@ -5,4 +5,4 @@ URL(rump) := https://github.com/ssumpf/rump.git DIR(rump) := src/lib/dde_rump REV(rump) := 206ffa06cedd0779af0043997fd182b00ff4688c -PATCHES := patches/vm_vfs.patch +PATCHES := patches/rump.patch diff --git a/repos/dde_rump/recipes/src/rump/content.mk b/repos/dde_rump/recipes/src/rump/content.mk index 0db9e925c..6c51c63f2 100644 --- a/repos/dde_rump/recipes/src/rump/content.mk +++ b/repos/dde_rump/recipes/src/rump/content.mk @@ -14,7 +14,7 @@ PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_rump) MIRROR_FROM_REP_DIR := $(LIB_MK) \ lib/import/import-rump.mk \ - src/lib src/server/rump_fs \ + src/lib \ include/rump include/rump_fs \ include/util diff --git a/repos/dde_rump/recipes/src/rump/hash b/repos/dde_rump/recipes/src/rump/hash index e2a818853..cb10c57c8 100644 --- a/repos/dde_rump/recipes/src/rump/hash +++ b/repos/dde_rump/recipes/src/rump/hash @@ -1 +1 @@ -2019-09-19 3e21cc9ee919b0db6eed00cf2581c1a4fd64041f +2019-11-25 d8ae674eb3c60b84e2e6fea39c5896ea2eb4ae2b diff --git a/repos/dde_rump/run/rump_ext2.run b/repos/dde_rump/run/rump_ext2.run index 2efa8d72a..48919d8f0 100644 --- a/repos/dde_rump/run/rump_ext2.run +++ b/repos/dde_rump/run/rump_ext2.run @@ -14,7 +14,8 @@ set dd [installed_command dd] set build_components { core init timer server/ram_block - server/rump_fs + server/vfs + lib/vfs/rump test/libc_vfs } @@ -56,10 +57,13 @@ append config { - + - + + + + @@ -82,7 +86,7 @@ install_config $config # generic modules set boot_modules { core ld.lib.so init timer test-libc_vfs ram_block - rump.lib.so rump_fs.lib.so rump_fs + rump.lib.so rump_fs.lib.so vfs vfs_rump.lib.so ext2.raw libc.lib.so vfs.lib.so } diff --git a/repos/dde_rump/run/rump_fat.run b/repos/dde_rump/run/rump_fat.run index 9183cf2d0..5670742c2 100644 --- a/repos/dde_rump/run/rump_fat.run +++ b/repos/dde_rump/run/rump_fat.run @@ -14,7 +14,8 @@ set dd [installed_command dd] set build_components { core init timer server/ram_block - server/rump_fs + server/vfs + lib/vfs/rump test/libc_vfs } @@ -56,20 +57,24 @@ append config { - + - + + + + + + - - - - - - + + + + + } @@ -83,7 +88,7 @@ install_config $config # generic modules set boot_modules { core ld.lib.so init timer test-libc_vfs ram_block - rump.lib.so rump_fs.lib.so rump_fs + rump.lib.so rump_fs.lib.so vfs vfs_rump.lib.so fs.raw libc.lib.so vfs.lib.so } diff --git a/repos/dde_rump/run/rump_iso.run b/repos/dde_rump/run/rump_iso.run index e2ea035d8..c61d01416 100644 --- a/repos/dde_rump/run/rump_iso.run +++ b/repos/dde_rump/run/rump_iso.run @@ -14,7 +14,8 @@ set build_components { core init timer server/fs_rom server/rom_block - server/rump_fs + server/vfs + lib/vfs/rump test/iso } @@ -49,10 +50,13 @@ append config { - - + + - + + + + @@ -88,7 +92,7 @@ install_config $config # set boot_modules { core ld.lib.so init timer test-iso rom_block - rump.lib.so rump_fs.lib.so rump_fs + rump.lib.so rump_fs.lib.so vfs_rump.lib.so vfs vfs.lib.so fs.iso fs_rom } diff --git a/repos/dde_rump/run/vfs_stress_rump_fs.run b/repos/dde_rump/run/vfs_stress_rump_fs.run index 222ca5a21..37284400a 100644 --- a/repos/dde_rump/run/vfs_stress_rump_fs.run +++ b/repos/dde_rump/run/vfs_stress_rump_fs.run @@ -10,7 +10,7 @@ set mke2fs [installed_command mke2fs] set dd [installed_command dd] -build "core init timer test/vfs_stress server/ram_block server/rump_fs" +build "core init timer test/vfs_stress server/ram_block server/vfs lib/vfs/rump" # # Build EXT2-file-system image @@ -50,10 +50,11 @@ install_config { - + - + + @@ -62,7 +63,7 @@ install_config { set boot_modules { core init ld.lib.so timer vfs_stress - rump.lib.so rump_fs.lib.so rump_fs + rump.lib.so rump_fs.lib.so vfs vfs_rump.lib.so ram_block ext2.raw vfs.lib.so } diff --git a/repos/dde_rump/src/lib/rump/env.cc b/repos/dde_rump/src/lib/rump/env.cc index 0b322eae9..e82a914ad 100644 --- a/repos/dde_rump/src/lib/rump/env.cc +++ b/repos/dde_rump/src/lib/rump/env.cc @@ -13,19 +13,29 @@ #include -/* - * Genode enviroment instance - */ -static Genode::Constructible _env; +static Rump::Env *_env_ptr; Rump::Env &Rump::env() { - return *_env; + return *_env_ptr; } void Rump::construct_env(Genode::Env &env) { - _env.construct(env); + static Rump::Env _env(env); + _env_ptr = &_env; +} + + +/* constructors in rump.lib.so */ +extern "C" void rumpns_modctor_ksem(void); +extern "C" void rumpns_modctor_suser(void); + +Rump::Env::Env(Genode::Env &env) : _env(env) +{ + /* call init/constructor functions of rump.lib.so */ + rumpns_modctor_ksem(); + rumpns_modctor_suser(); } diff --git a/repos/dde_rump/src/lib/rump/io.cc b/repos/dde_rump/src/lib/rump/io.cc index f63afea9b..975646a5f 100644 --- a/repos/dde_rump/src/lib/rump/io.cc +++ b/repos/dde_rump/src/lib/rump/io.cc @@ -166,8 +166,33 @@ void rump_io_backend_sync() } +/* constructors in rump_fs.lib.so */ +extern "C" void rumpcompctor_RUMP_COMPONENT_KERN_SYSCALL(void); +extern "C" void rumpcompctor_RUMP_COMPONENT_SYSCALL(void); +extern "C" void rumpcompctor_RUMP__FACTION_VFS(void); +extern "C" void rumpcompctor_RUMP__FACTION_DEV(void); +extern "C" void rumpns_modctor_cd9660(void); +extern "C" void rumpns_modctor_dk_subr(void); +extern "C" void rumpns_modctor_ext2fs(void); +extern "C" void rumpns_modctor_ffs(void); +extern "C" void rumpns_modctor_msdos(void); +extern "C" void rumpns_modctor_wapbl(void); + + void rump_io_backend_init() { + /* call init/constructor functions of rump_fs.lib.so (order is important!) */ + rumpcompctor_RUMP_COMPONENT_KERN_SYSCALL(); + rumpns_modctor_wapbl(); + rumpcompctor_RUMP_COMPONENT_SYSCALL(); + rumpcompctor_RUMP__FACTION_VFS(); + rumpcompctor_RUMP__FACTION_DEV(); + rumpns_modctor_msdos(); + rumpns_modctor_ffs(); + rumpns_modctor_ext2fs(); + rumpns_modctor_dk_subr(); + rumpns_modctor_cd9660(); + /* create back end */ backend(); } diff --git a/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc b/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc index 997e37118..8127a9134 100644 --- a/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc +++ b/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc @@ -91,6 +91,8 @@ class Vfs::Rump_file_system : public File_system Genode::error("Rump_vfs_handle::write() called"); return WRITE_ERR_INVALID; } + + virtual void update_modification_timestamp(Vfs::Timestamp) { } }; class Rump_vfs_file_handle : @@ -163,6 +165,17 @@ class Vfs::Rump_file_system : public File_system out_count = n; return WRITE_OK; } + + void update_modification_timestamp(Vfs::Timestamp time) override + { + struct timespec ts[2] = { + { .tv_sec = 0, .tv_nsec = 0 }, + { .tv_sec = time.value, .tv_nsec = 0 } + }; + + /* silently igore error */ + rump_sys_futimens(_fd, (const timespec*)&ts); + } }; class Rump_vfs_dir_handle : public Rump_vfs_handle @@ -181,28 +194,31 @@ class Vfs::Rump_file_system : public File_system * We cannot use 'd_type' member of 'dirent' here since the EXT2 * implementation sets the type to unkown. Hence we use stat. */ - struct stat s; + struct stat s { }; rump_sys_lstat(path, &s); - vfs_dir.fileno = s.st_ino; + auto dirent_type = [] (unsigned mode) + { + if (S_ISREG (mode)) return Dirent_type::CONTINUOUS_FILE; + if (S_ISDIR (mode)) return Dirent_type::DIRECTORY; + if (S_ISLNK (mode)) return Dirent_type::SYMLINK; + if (S_ISBLK (mode)) return Dirent_type::CONTINUOUS_FILE; + if (S_ISCHR (mode)) return Dirent_type::CONTINUOUS_FILE; + if (S_ISFIFO(mode)) return Dirent_type::CONTINUOUS_FILE; - if (S_ISREG(s.st_mode)) - vfs_dir.type = Dirent_type::DIRENT_TYPE_FILE; - else if (S_ISDIR(s.st_mode)) - vfs_dir.type = Dirent_type::DIRENT_TYPE_DIRECTORY; - else if (S_ISLNK(s.st_mode)) - vfs_dir.type = Dirent_type::DIRENT_TYPE_SYMLINK; - else if (S_ISBLK(s.st_mode)) - vfs_dir.type = Dirent_type::DIRENT_TYPE_BLOCKDEV; - else if (S_ISCHR(s.st_mode)) - vfs_dir.type = Dirent_type::DIRENT_TYPE_CHARDEV; - else if (S_ISFIFO(s.st_mode)) - vfs_dir.type = Dirent_type::DIRENT_TYPE_FIFO; - else - vfs_dir.type = Dirent_type::DIRENT_TYPE_FILE; + return Dirent_type::END; + }; - strncpy(vfs_dir.name, dent->d_name, sizeof(Dirent::name)); + Node_rwx const rwx { .readable = true, + .writeable = true, + .executable = (s.st_mode & S_IXUSR) }; + vfs_dir = { + .fileno = s.st_ino, + .type = dirent_type(s.st_mode), + .rwx = rwx, + .name = { dent->d_name } + }; return READ_OK; } @@ -683,15 +699,28 @@ class Vfs::Rump_file_system : public File_system Stat_result stat(char const *path, Stat &stat) { - struct stat sb; + struct stat sb { }; if (rump_sys_lstat(path, &sb) != 0) return STAT_ERR_NO_ENTRY; - stat.size = sb.st_size; - stat.mode = sb.st_mode; - stat.uid = sb.st_uid; - stat.gid = sb.st_gid; - stat.inode = sb.st_ino; - stat.device = sb.st_dev; + auto type = [] (unsigned mode) + { + if (S_ISDIR(mode)) return Node_type::DIRECTORY; + if (S_ISLNK(mode)) return Node_type::SYMLINK; + + return Node_type::CONTINUOUS_FILE; + }; + + stat = { + .size = (file_size)sb.st_size, + .type = type(sb.st_mode), + .rwx = { .readable = true, + .writeable = true, + .executable = (sb.st_mode & S_IXUSR) }, + .inode = sb.st_ino, + .device = sb.st_dev, + + .modification_time = { 0 } + }; return STAT_OK; } @@ -806,6 +835,12 @@ class Vfs::Rump_file_system : public File_system _notify_files(); return SYNC_OK; } + + bool update_modification_timestamp(Vfs_handle *vfs_handle, + Vfs::Timestamp ts) + { + return true; + } }; diff --git a/repos/dde_rump/src/server/rump_fs/directory.h b/repos/dde_rump/src/server/rump_fs/directory.h deleted file mode 100644 index cfd69ea6a..000000000 --- a/repos/dde_rump/src/server/rump_fs/directory.h +++ /dev/null @@ -1,286 +0,0 @@ -/** - * \brief File-system directory node - * \author Norman Feske - * \author Christian Helmuth - * \author Sebastian Sumpf - * \date 2013-11-11 - */ - -/* - * Copyright (C) 2013-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 _DIRECTORY_H_ -#define _DIRECTORY_H_ - -/* Genode include */ -#include -#include -#include - -/* local includes */ -#include "node.h" -#include "file.h" -#include "symlink.h" - -namespace Rump_fs { - class Directory; -} - -class Rump_fs::Directory : public Node -{ - private: - - enum { BUFFER_SIZE = 4096 }; - - typedef Genode::Path Path; - - int _fd; - Path _path; - Allocator &_alloc; - - unsigned long _inode(char const *path, bool create) - { - int ret; - - if (create) { - mode_t ugo = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - ret = rump_sys_mkdir(path, ugo); - if (ret == -1) - switch (errno) { - case ENAMETOOLONG: throw Name_too_long(); - case EACCES: throw Permission_denied(); - case ENOENT: throw Lookup_failed(); - case EEXIST: throw Node_already_exists(); - case ENOSPC: - default: throw No_space(); - } - } - - struct stat s; - - ret = rump_sys_lstat(path, &s); - if (ret == -1) - throw Lookup_failed(); - return s.st_ino; - } - - int _open(char const *path) - { - struct stat s; - int ret = rump_sys_lstat(path, &s); - if (ret == -1 || !S_ISDIR(s.st_mode)) - throw Lookup_failed(); - - int fd = rump_sys_open(path, O_RDONLY); - if (fd == -1) - throw Lookup_failed(); - - return fd; - } - - static char *_buffer() - { - /* buffer for directory entries */ - static char buf[BUFFER_SIZE]; - return buf; - } - - public: - - Directory(Allocator &alloc, char const *path, bool create) - : - Node(_inode(path, create)), - _fd(_open(path)), - _path(path, "./"), - _alloc(alloc) - { - Node::name(basename(path)); - } - - virtual ~Directory() - { - rump_sys_close(_fd); - } - - int fd() const override { return _fd; } - - File * file(char const *name, Mode mode, bool create) override - { - return new (&_alloc) File(_fd, name, mode, create); - } - - Symlink * symlink(char const *name, bool create) override - { - return new (&_alloc) Symlink(_path.base(), name, create); - } - - Directory * subdir(char const *path, bool create) - { - Path dir_path(path, _path.base()); - Directory *dir = new (&_alloc) Directory(_alloc, dir_path.base(), create); - return dir; - } - - Node * node(char const *path) - { - Path node_path(path, _path.base()); - - struct stat s; - int ret = rump_sys_lstat(node_path.base(), &s); - if (ret == -1) - throw Lookup_failed(); - - Node *node = 0; - - if (S_ISDIR(s.st_mode)) - node = new (&_alloc) Directory(_alloc, node_path.base(), false); - else if (S_ISREG(s.st_mode)) - node = new (&_alloc) File(node_path.base(), STAT_ONLY); - else if (S_ISLNK(s.st_mode)) - node = new (&_alloc)Symlink(node_path.base()); - else - throw Lookup_failed(); - - return node; - } - - size_t read(char *dst, size_t len, seek_off_t seek_offset) override - { - if (len < sizeof(Directory_entry)) { - Genode::error("read buffer too small for directory entry"); - return 0; - } - - if (seek_offset % sizeof(Directory_entry)) { - Genode::error("seek offset not aligned to sizeof(Directory_entry)"); - return 0; - } - - seek_off_t index = seek_offset / sizeof(Directory_entry); - - int bytes; - rump_sys_lseek(_fd, 0, SEEK_SET); - - struct dirent *dent = 0; - seek_off_t i = 0; - char *buf = _buffer(); - do { - bytes = rump_sys_getdents(_fd, buf, BUFFER_SIZE); - void *current, *end; - for (current = buf, end = &buf[bytes]; - current < end; - current = _DIRENT_NEXT((dirent *)current)) - { - struct ::dirent *d = (dirent*)current; - if (strcmp(".", d->d_name) && strcmp("..", d->d_name)) { - if (i == index) { - dent = d; - break; - } - ++i; - } - } - } while(bytes && !dent); - - if (!dent) - return 0; - - /* - * Build absolute path, this becomes necessary as our 'Path' class strips - * trailing dots, which will not work for '.' and '..' directories. - */ - size_t base_len = strlen(_path.base()); - char path[dent->d_namlen + base_len + 2]; - - memcpy(path, _path.base(), base_len); - path[base_len] = '/'; - strncpy(path + base_len + 1, dent->d_name, dent->d_namlen + 1); - - /* - * We cannot use 'd_type' member of 'dirent' here since the EXT2 - * implementation sets the type to unkown. Hence we use stat. - */ - struct stat s; - rump_sys_lstat(path, &s); - - Directory_entry *e = (Directory_entry *)(dst); - if (S_ISDIR(s.st_mode)) - e->type = Directory_entry::TYPE_DIRECTORY; - else if (S_ISREG(s.st_mode)) - e->type = Directory_entry::TYPE_FILE; - else if (S_ISLNK(s.st_mode)) - e->type = Directory_entry::TYPE_SYMLINK; - else - return 0; - - e->inode = s.st_ino; - strncpy(e->name, dent->d_name, dent->d_namlen + 1); - return sizeof(Directory_entry); - } - - size_t write(char const *src, size_t len, seek_off_t seek_offset) override - { - /* writing to directory nodes is not supported */ - return 0; - } - - Status status() override - { - Status s; - s.inode = inode(); - s.size = num_entries() * sizeof (Directory_entry); - s.mode = File_system::Status::MODE_DIRECTORY; - - return s; - } - - size_t num_entries() const - { - int bytes = 0; - int count = 0; - - rump_sys_lseek(_fd, 0, SEEK_SET); - - char *buf = _buffer(); - do { - bytes = rump_sys_getdents(_fd, buf, BUFFER_SIZE); - void *current, *end; - for (current = buf, end = &buf[bytes]; - current < end; - current = _DIRENT_NEXT((dirent *)current)) - { - struct ::dirent *d = (dirent*)current; - if (strcmp(".", d->d_name) && strcmp("..", d->d_name)) - count++; - } - } while(bytes); - - return count; - } - - void unlink(char const *path) override - { - Path node_path(path, _path.base()); - - struct stat s; - int ret = rump_sys_lstat(node_path.base(), &s); - if (ret == -1) - throw Lookup_failed(); - - if (S_ISDIR(s.st_mode)) - ret = rump_sys_rmdir(node_path.base()); - else if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) - ret = rump_sys_unlink(node_path.base()); - else - throw Lookup_failed(); - - if (ret == -1) - Genode::error("error during unlink of ", node_path); - } -}; - -#endif /* _DIRECTORY_H_ */ diff --git a/repos/dde_rump/src/server/rump_fs/file.h b/repos/dde_rump/src/server/rump_fs/file.h deleted file mode 100644 index 67b6114e5..000000000 --- a/repos/dde_rump/src/server/rump_fs/file.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * \brief File node - * \author Norman Feske - * \author Christian Helmuth - * \auhtor Sebastian Sumpf - * \date 2013-11-11 - */ - -/* - * Copyright (C) 2013-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 _FILE_H_ -#define _FILE_H_ - -/* Genode includes */ -#include - -#include "node.h" - -namespace Rump_fs { - class File; -} - -class Rump_fs::File : public Node -{ - private: - - int _fd; - - int _access_mode(Mode const &mode) - { - switch (mode) { - case STAT_ONLY: - case READ_ONLY: return O_RDONLY; - case WRITE_ONLY: return O_WRONLY; - case READ_WRITE: return O_RDWR; - default: return O_RDONLY; - } - } - - unsigned long _inode(int dir, char const *name, bool create) - { - int ret; - - if (create) { - mode_t ugo = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - ret = rump_sys_mknodat(dir, name, S_IFREG | ugo, 0); - if (ret == -1 && errno != EEXIST) - throw No_space(); - } - - struct stat s; - - ret = rump_sys_fstatat(dir, name, &s, 0); - if (ret == -1) - throw Lookup_failed(); - - return s.st_ino; - } - - unsigned long _inode_path(char const *path) - { - int ret; - struct stat s; - - ret = rump_sys_stat(path, &s); - if (ret == -1) - throw Lookup_failed(); - - return s.st_ino; - } - - int _open(int dir, char const *name, Mode mode) - { - int fd = rump_sys_openat(dir, name, _access_mode(mode)); - if (fd == -1) - throw Lookup_failed(); - - return fd; - } - - int _open_path(char const *path, Mode mode) - { - int fd = rump_sys_open(path, _access_mode(mode)); - if (fd == -1) - throw Lookup_failed(); - - return fd; - } - - public: - - File(int dir, - char const *name, - Mode mode, - bool create) - : Node(_inode(dir, name, create)), - _fd(_open(dir, name, mode)) - { - Node::name(name); - } - - File(char const *path, Mode mode) - : - Node(_inode_path(path)), - _fd(_open_path(path, mode)) - { - Node::name(basename(path)); - } - - virtual ~File() { rump_sys_close(_fd); } - - size_t read(char *dst, size_t len, seek_off_t seek_offset) override - { - ssize_t ret; - - if (seek_offset == SEEK_TAIL) - ret = rump_sys_lseek(_fd, -len, SEEK_END) != -1 ? - rump_sys_read(_fd, dst, len) : 0; - else - ret = rump_sys_pread(_fd, dst, len, seek_offset); - - return ret == -1 ? 0 : ret; - } - - size_t write(char const *src, size_t len, seek_off_t seek_offset) override - { - ssize_t ret; - - if (seek_offset == SEEK_TAIL) - ret = rump_sys_lseek(_fd, 0, SEEK_END) != -1 ? - rump_sys_write(_fd, src, len) : 0; - else - ret = rump_sys_pwrite(_fd, src, len, seek_offset); - - return ret == -1 ? 0 : ret; - } - - virtual Status status() override - { - Status s; - - s.inode = inode(); - s.size = length(); - s.mode = File_system::Status::MODE_FILE; - - return s; - } - - file_size_t length() const - { - struct stat s; - - if(rump_sys_fstat(_fd, &s) < 0) - return 0; - - return s.st_size; - } - - void truncate(file_size_t size) override - { - rump_sys_ftruncate(_fd, size); - - mark_as_updated(); - } -}; - -#endif /* _FILE_H_ */ diff --git a/repos/dde_rump/src/server/rump_fs/file_system.cc b/repos/dde_rump/src/server/rump_fs/file_system.cc deleted file mode 100644 index 9d4e427dd..000000000 --- a/repos/dde_rump/src/server/rump_fs/file_system.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* - * \brief Rump initialization - * \author Sebastian Sumpf - * \date 2014-01-17 - */ - -/* - * Copyright (C) 2014-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 -#include -#include - -#include "file_system.h" - -/** - * We define our own fs arg structure to fit all sizes used by the different - * file system implementations, we assume that 'fspec' * is the only valid - * argument and all other fields are unused. - */ -struct fs_args -{ - char *fspec; - char pad[164]; - - fs_args() { Genode::memset(pad, 0, sizeof(pad)); } -}; - - -namespace File_system { class Sync; }; - - -static char const *fs_types[] = { RUMP_MOUNT_CD9660, RUMP_MOUNT_EXT2FS, - RUMP_MOUNT_FFS, RUMP_MOUNT_MSDOS, - RUMP_MOUNT_NTFS, RUMP_MOUNT_UDF, 0 }; - -typedef Genode::String<16> Fs_type; - - -static bool _supports_symlinks; - - -static bool _check_type(Fs_type const &type) -{ - for (int i = 0; fs_types[i]; i++) - if (!Genode::strcmp(type.string(), fs_types[i])) - return true; - return false; -} - - -static void _print_types() -{ - Genode::error("fs types:"); - for (int i = 0; fs_types[i]; ++i) - Genode::error("\t", fs_types[i]); -} - - -static bool check_symlinks(Fs_type const &fs_type) -{ - return (fs_type == RUMP_MOUNT_EXT2FS) - || (fs_type == RUMP_MOUNT_FFS); -} - - -static bool check_read_only(Fs_type const &fs_type) -{ - return fs_type == RUMP_MOUNT_CD9660; -} - - -void File_system::init() -{ - Fs_type const fs_type = Rump::env().config_rom().xml().attribute_value("fs", Fs_type()); - - if (!_check_type(fs_type)) { - Genode::error("Invalid or no file system given (use \'\"/>)"); - _print_types(); - throw Genode::Exception(); - } - - Genode::log("Using ", fs_type, " as file system"); - - size_t const avail = Rump::env().env().pd().avail_ram().value; - rump_set_memlimit(avail); - - /* start rump kernel */ - try { rump_init(); } - catch (...) { throw Genode::Exception(); } - - /* register block device */ - rump_pub_etfs_register(GENODE_DEVICE, GENODE_BLOCK_SESSION, RUMP_ETFS_BLK); - - /* create mount directory */ - rump_sys_mkdir(GENODE_MOUNT_DIR, 0777); - - /* check support for symlinks */ - _supports_symlinks = check_symlinks(fs_type); - - /* - * Try to mount the file system just to check if it - * is working as intended. In case it is not that gives - * us a change to react upon before any client may - * hang. - */ - try { - mount_fs(); - unmount_fs(); - } catch (...) { - Genode::error("dry mount attempt failed, aborting"); - throw Genode::Exception(); - } -} - - -static int root_fd = -42; - - -void File_system::mount_fs() -{ - /* mount into extra-terrestrial-file system */ - struct fs_args args; - args.fspec = (char *)GENODE_DEVICE; - - Fs_type const fs_type = Rump::env().config_rom().xml().attribute_value("fs", Fs_type()); - - int opts = check_read_only(fs_type) ? RUMP_MNT_RDONLY : 0; - opts |= RUMP_MNT_NOATIME; - - if (root_fd == -42) { - root_fd = rump_sys_open("/", O_DIRECTORY | O_RDONLY); - if (root_fd == -1) { - Genode::error("opening root directory failed"); - throw Genode::Exception(); - } - } - - int err = rump_sys_mount(fs_type.string(), GENODE_MOUNT_DIR, - opts, &args, sizeof(args)); - if (err == -1) { - Genode::error("mounting file system failed (errno ", errno, " )"); - throw Genode::Exception(); - } - - int const mnt_fd = rump_sys_open(GENODE_MOUNT_DIR, O_DIRECTORY | O_RDONLY); - if (mnt_fd == -1) { - Genode::error("opening mnt directory failed"); - throw Genode::Exception(); - } - - err = rump_sys_fchroot(mnt_fd); - if (err == -1) { - Genode::error("fchroot to '", GENODE_MOUNT_DIR, "' failed ", - "(errno ", errno, " )"); - throw Genode::Exception(); - } -} - - -void File_system::unmount_fs() -{ - /* try to flush all outstanding modifications */ - rump_sys_sync(); - - int err = rump_sys_fchroot(root_fd); - if (err == -1) { - Genode::error("fchroot to '/' failed ", "(errno ", errno, " )"); - throw Genode::Exception(); - } - - bool const force = true; - - err = rump_sys_unmount(GENODE_MOUNT_DIR, force ? RUMP_MNT_FORCE : 0); - if (err == -1) { - Genode::error("unmounting file system failed (errno ", errno, " )"); - throw Genode::Exception(); - } -} - - -bool File_system::supports_symlinks() { return _supports_symlinks; } diff --git a/repos/dde_rump/src/server/rump_fs/file_system.h b/repos/dde_rump/src/server/rump_fs/file_system.h deleted file mode 100644 index 795968ed1..000000000 --- a/repos/dde_rump/src/server/rump_fs/file_system.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * \brief Rump initialization and required header - * \author Sebastian Sumpf - * \date 2014-01-17 - */ - -/* - * Copyright (C) 2014-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 _FILE_SYSTEM_H_ -#define _FILE_SYSTEM_H_ - -/* Genode includes */ -#include -#include -#include - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -#include -} - -namespace File_system { - void init(); - void mount_fs(); - void unmount_fs(); - bool supports_symlinks(); -} - -extern int errno; - -#endif /* _FILE_SYSTEM_H_ */ diff --git a/repos/dde_rump/src/server/rump_fs/main.cc b/repos/dde_rump/src/server/rump_fs/main.cc deleted file mode 100644 index 6d17e2645..000000000 --- a/repos/dde_rump/src/server/rump_fs/main.cc +++ /dev/null @@ -1,617 +0,0 @@ -/** - * \brief RUMP file system interface implementation - * \author Christian Helmuth - * \author Sebastian Sumpf - * \date 2014-01-14 - */ - -/* - * Copyright (C) 2014-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. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include - -#include "undef.h" - -#include -#include -#include -#include "file_system.h" -#include "directory.h" -#include "open_node.h" - - -namespace Rump_fs { - - using File_system::Packet_descriptor; - using File_system::Path; - - struct Main; - struct Root; - struct Session_component; -} - -class Rump_fs::Session_component : public Session_rpc_object -{ - private: - - typedef File_system::Open_node Open_node; - - Allocator &_md_alloc; - Directory &_root; - Id_space _open_node_registry; - bool _writable; - - Signal_handler _process_packet_handler; - - - /****************************** - ** Packet-stream processing ** - ******************************/ - - /** - * Perform packet operation - * - * \return true on success, false on failure - */ - void _process_packet_op(Packet_descriptor &packet, Open_node &open_node) - { - size_t const length = packet.length(); - - /* resulting length */ - size_t res_length = 0; - bool succeeded = false; - - switch (packet.operation()) { - - case Packet_descriptor::READ: - if (tx_sink()->packet_valid(packet) && packet.length() <= packet.size()) { - res_length = open_node.node().read((char *)tx_sink()->packet_content(packet), - length, packet.position()); - - /* read data or EOF is a success */ - succeeded = res_length || (packet.position() >= open_node.node().status().size); - } - break; - - case Packet_descriptor::WRITE: - if (tx_sink()->packet_valid(packet) && packet.length() <= packet.size()) { - res_length = open_node.node().write((char const *)tx_sink()->packet_content(packet), - length, - packet.position()); - /* File system session can't handle partial writes */ - if (res_length != length) { - Genode::error("partial write detected ", - res_length, " vs ", length); - /* don't acknowledge */ - return; - } - succeeded = true; - } - break; - - case Packet_descriptor::CONTENT_CHANGED: - open_node.register_notify(*tx_sink()); - /* notify_listeners may bounce the packet back*/ - open_node.node().notify_listeners(); - /* otherwise defer acknowledgement of this packet */ - return; - - case Packet_descriptor::READ_READY: - /* not supported */ - succeeded = true; - break; - - case Packet_descriptor::SYNC: - rump_sys_sync(); - succeeded = true; - break; - } - - packet.length(res_length); - packet.succeeded(succeeded); - tx_sink()->acknowledge_packet(packet); - } - - void _process_packet() - { - Packet_descriptor packet = tx_sink()->get_packet(); - - /* assume failure by default */ - packet.succeeded(false); - - auto process_packet_fn = [&] (Open_node &open_node) { - _process_packet_op(packet, open_node); - }; - - try { - _open_node_registry.apply(packet.handle(), process_packet_fn); - } catch (Id_space::Unknown_id const &) { - Genode::error("Invalid_handle"); - tx_sink()->acknowledge_packet(packet); - } - } - - /** - * Called by signal dispatcher, executed in the context of the main - * thread (not serialized with the RPC functions) - */ - void _process_packets() - { - while (tx_sink()->packet_avail()) { - - /* - * Make sure that the '_process_packet' function does not - * block. - * - * If the acknowledgement queue is full, we defer packet - * processing until the client processed pending - * acknowledgements and thereby emitted a ready-to-ack - * signal. Otherwise, the call of 'acknowledge_packet()' - * in '_process_packet' would infinitely block the context - * of the main thread. The main thread is however needed - * for receiving any subsequent 'ready-to-ack' signals. - */ - if (!tx_sink()->ready_to_ack()) - return; - - _process_packet(); - } - } - - /** - * Check if string represents a valid path (must start with '/') - */ - static void _assert_valid_path(char const *path) - { - if (!path || path[0] != '/') - throw Lookup_failed(); - } - - public: - - /** - * Constructor - */ - Session_component(Genode::Env &env, - size_t tx_buf_size, - char const *root_dir, - bool writeable, - Allocator &md_alloc) - : - Session_rpc_object(env.ram().alloc(tx_buf_size), env.rm(), env.ep().rpc_ep()), - _md_alloc(md_alloc), - _root(*new (&_md_alloc) Directory(_md_alloc, root_dir, false)), - _writable(writeable), - _process_packet_handler(env.ep(), *this, &Session_component::_process_packets) - { - /* - * Register '_process_packets' dispatch function as signal - * handler for packet-avail and ready-to-ack signals. - */ - _tx.sigh_packet_avail(_process_packet_handler); - _tx.sigh_ready_to_ack(_process_packet_handler); - } - - /** - * Destructor - */ - ~Session_component() - { - Dataspace_capability ds = tx_sink()->dataspace(); - Rump::env().env().ram().free(static_cap_cast(ds)); - destroy(&_md_alloc, &_root); - } - - /*************************** - ** File_system interface ** - ***************************/ - - File_handle file(Dir_handle dir_handle, Name const &name, Mode mode, bool create) - { - if (!valid_name(name.string())) - throw Invalid_name(); - - auto file_fn = [&] (Open_node &open_node) { - - Node &dir = open_node.node(); - - if (!_writable) - if (create || (mode != STAT_ONLY && mode != READ_ONLY)) - throw Permission_denied(); - - File *file = dir.file(name.string(), mode, create); - - Open_node *open_file = - new (_md_alloc) Open_node(*file, _open_node_registry); - - return open_file->id(); - }; - - try { - return File_handle { - _open_node_registry.apply(dir_handle, file_fn).value - }; - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - } - - Symlink_handle symlink(Dir_handle dir_handle, Name const &name, bool create) - { - if (!File_system::supports_symlinks()) - throw Permission_denied(); - - if (!valid_name(name.string())) - throw Invalid_name(); - - auto symlink_fn = [&] (Open_node &open_node) { - - Node &dir = open_node.node(); - - if (create && !_writable) - throw Permission_denied(); - - Symlink *link = dir.symlink(name.string(), create); - - Open_node *open_symlink = - new (_md_alloc) Open_node(*link, _open_node_registry); - - return open_symlink->id(); - }; - - try { - return Symlink_handle { - _open_node_registry.apply(dir_handle, symlink_fn).value - }; - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - } - - Dir_handle dir(Path const &path, bool create) - { - char const *path_str = path.string(); - _assert_valid_path(path_str); - - /* skip leading '/' */ - path_str++; - - if (!_writable && create) - throw Permission_denied(); - - if (!path.valid_string()) - throw Name_too_long(); - - Directory *dir = _root.subdir(path_str, create); - - Open_node *open_dir = - new (_md_alloc) Open_node(*dir, _open_node_registry); - - return Dir_handle { open_dir->id().value }; - } - - Node_handle node(Path const &path) - { - char const *path_str = path.string(); - - _assert_valid_path(path_str); - Node *node = _root.node(path_str + 1); - - Open_node *open_node = - new (_md_alloc) Open_node(*node, _open_node_registry); - - return open_node->id(); - } - - void close(Node_handle handle) - { - auto close_fn = [&] (Open_node &open_node) { - Node &node = open_node.node(); - destroy(_md_alloc, &open_node); - destroy(_md_alloc, &node); - }; - - try { - _open_node_registry.apply(handle, close_fn); - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - } - - Status status(Node_handle node_handle) - { - auto status_fn = [&] (Open_node &open_node) { - return open_node.node().status(); - }; - - try { - return _open_node_registry.apply(node_handle, status_fn); - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - } - - void control(Node_handle, Control) override { } - - void unlink(Dir_handle dir_handle, Name const &name) - { - if (!valid_name(name.string())) - throw Invalid_name(); - - if (!_writable) - throw Permission_denied(); - - auto unlink_fn = [&] (Open_node &open_node) { - Node &dir = open_node.node(); - dir.unlink(name.string()); - }; - - try { - _open_node_registry.apply(dir_handle, unlink_fn); - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - } - - void truncate(File_handle file_handle, file_size_t size) - { - if (!_writable) - throw Permission_denied(); - - auto truncate_fn = [&] (Open_node &open_node) { - open_node.node().truncate(size); - }; - - try { - _open_node_registry.apply(file_handle, truncate_fn); - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - } - - void move(Dir_handle from_dir_handle, Name const &from_name, - Dir_handle to_dir_handle, Name const &to_name) - { - if (!_writable) - throw Permission_denied(); - - auto move_fn = [&] (Open_node &open_from_dir_node) { - - auto inner_move_fn = [&] (Open_node &open_to_dir_node) { - - Node &from_dir = open_from_dir_node.node(); - Node &to_dir = open_to_dir_node.node(); - - char const *from_str = from_name.string(); - char const *to_str = to_name.string(); - - if (!(valid_name(from_str) && valid_name(to_str))) - throw Lookup_failed(); - - if (rump_sys_renameat(from_dir.fd(), from_str, - to_dir.fd(), to_str) == 0) { - from_dir.mark_as_updated(); - from_dir.notify_listeners(); - if (&from_dir != &to_dir) { - to_dir.mark_as_updated(); - to_dir.notify_listeners(); - } - - return; - } - - switch (errno) { - case ENOTEMPTY: throw Node_already_exists(); - case ENOENT: throw Lookup_failed(); - } - - Genode::warning("renameat produced unhandled error ", errno, ", ", from_str, " -> ", to_str); - throw Permission_denied(); - - }; - - try { - _open_node_registry.apply(to_dir_handle, inner_move_fn); - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - }; - - try { - _open_node_registry.apply(from_dir_handle, move_fn); - } catch (Id_space::Unknown_id const &) { - throw Invalid_handle(); - } - } -}; - -class Rump_fs::Root : public Root_component -{ - private: - - Genode::Env &_env; - - int _sessions { 0 }; - - Genode::Attached_rom_dataspace _config { _env, "config" }; - - protected: - - Session_component *_create_session(const char *args) - { - using namespace Genode; - - /* - * Determine client-specific policy defined implicitly by - * the client's label. - */ - - Genode::Path session_root; - bool writeable = false; - - Session_label const label = label_from_args(args); - - size_t ram_quota = - Arg_string::find_arg(args, "ram_quota").aligned_size(); - size_t tx_buf_size = - Arg_string::find_arg(args, "tx_buf_size").aligned_size(); - - if (!tx_buf_size) - throw Service_denied(); - - /* - * Check if donated ram quota suffices for session data, - * and communication buffer. - */ - size_t session_size = - max((size_t)4096, sizeof(Session_component)) + - tx_buf_size; - - if (session_size > ram_quota) { - Genode::error("insufficient 'ram_quota' from ", label.string(), - " got ", ram_quota, "need ", session_size); - throw Insufficient_ram_quota(); - } - ram_quota -= session_size; - - Session_policy const policy(label, _config.xml()); - - /* determine policy root offset */ - typedef String Root; - session_root.import(policy.attribute_value("root", Root()).string(), "/mnt"); - - /* - * Determine if the session is writeable. - * Policy overrides client argument, both default to false. - */ - if (policy.attribute_value("writeable", false)) - writeable = Arg_string::find_arg(args, "writeable").bool_value(false); - - /* apply client's root offset */ - { - char tmp[MAX_PATH_LEN] { }; - Arg_string::find_arg(args, "root").string(tmp, sizeof(tmp), "/"); - if (Genode::strcmp("/", tmp, sizeof(tmp))) { - session_root.append("/"); - session_root.append(tmp); - } - } - session_root.remove_trailing('/'); - - char const *root_dir = session_root.base(); - - try { - if (++_sessions == 1) { File_system::mount_fs(); } - } catch (...) { - Genode::error("could not mount file system"); - throw Service_denied(); - } - - try { - return new (md_alloc()) - Session_component(_env, tx_buf_size, root_dir, writeable, *md_alloc()); - - } catch (Lookup_failed) { - Genode::error("File system root directory \"", root_dir, "\" does not exist"); - throw Service_denied(); - } - } - - void _destroy_session(Session_component *session) - { - Genode::destroy(md_alloc(), session); - - try { - if (--_sessions == 0) { File_system::unmount_fs(); } - } catch (...) { } - } - - public: - - /** - * Constructor - */ - Root(Genode::Env &env, Allocator &md_alloc) - : - Root_component(env.ep(), md_alloc), - _env(env) - { } -}; - - -struct Rump_fs::Main -{ - Genode::Env &env; - - Timer::Connection _timer { env }; - - /* return immediately from resource requests */ - void ignore_resource() { } - - Genode::Signal_handler
resource_handler - { env.ep(), *this, &Main::ignore_resource }; - - /* periodic sync */ - void sync() - { - /* sync through front-end */ - rump_sys_sync(); - /* sync Genode back-end */ - rump_io_backend_sync(); - } - - Genode::Signal_handler
sync_handler - { env.ep(), *this, &Main::sync }; - - Heap heap { env.ram(), env.rm() }; - - /* - * Initialize root interface - */ - Sliced_heap sliced_heap { env.ram(), env.rm() }; - - Root fs_root { env, sliced_heap }; - - Main(Genode::Env &env) : env(env) - { - Rump::construct_env(env); - - rump_io_backend_init(); - - File_system::init(); - - /* set all bits but the stickies */ - rump_sys_umask(S_ISUID|S_ISGID|S_ISVTX); - - /* set open file limit to maximum (256) */ - struct rlimit rl { RLIM_INFINITY, RLIM_INFINITY }; - if (rump_sys_setrlimit(RLIMIT_NOFILE, &rl) != 0) - Genode::error("rump_sys_setrlimit(RLIMIT_NOFILE, ...) failed, errno ", errno); - - env.parent().announce(env.ep().manage(fs_root)); - env.parent().resource_avail_sigh(resource_handler); - - _timer.sigh(sync_handler); - _timer.trigger_periodic(2*1000*1000); - } -}; - - -void Component::construct(Genode::Env &env) -{ - /* XXX execute constructors of global statics (uses shared objects) */ - env.exec_static_constructors(); - - static Rump_fs::Main inst(env); -} diff --git a/repos/dde_rump/src/server/rump_fs/node.h b/repos/dde_rump/src/server/rump_fs/node.h deleted file mode 100644 index cfd8b3054..000000000 --- a/repos/dde_rump/src/server/rump_fs/node.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * \brief File-system node - * \author Norman Feske - * \author Christian Helmuth - * \author Sebastian Sumpf - * \date 2013-11-11 - */ - -/* - * Copyright (C) 2013-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 _NODE_H_ -#define _NODE_H_ - -/* Genode includes */ -#include -#include - - -namespace Rump_fs { - using namespace File_system; - using namespace Genode; - using Genode::size_t; - class Node; - class File; - class Directory; - class Symlink; -} - -class Rump_fs::Node : public Node_base -{ - public: - - typedef char Name[128]; - - private: - - Name _name; - unsigned long const _inode; - - public: - - Node(unsigned long inode) : _inode(inode) { _name[0] = 0; } - - unsigned long inode() const { return _inode; } - char const *name() const { return _name; } - - /** - * Assign name - */ - void name(char const *name) { strncpy(_name, name, sizeof(_name)); } - - virtual size_t read(char *dst, size_t len, seek_off_t) = 0; - virtual size_t write(char const *src, size_t len, seek_off_t) = 0; - virtual Status status() = 0; - - /* - * Directory functionality - */ - virtual int fd() const - { - Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node"); - return -1; - } - - virtual File *file(char const *name, Mode mode, bool create) - { - Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node"); - return nullptr; - } - - virtual Symlink *symlink(char const *name, bool create) - { - Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node"); - return nullptr; - } - - virtual void unlink(char const *path) - { - Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node"); - } - - /* - * File functionality - */ - virtual void truncate(file_size_t size) - { - Genode::error(__PRETTY_FUNCTION__, " called on a non-file node"); - } -}; - -#endif /* _NODE_H_ */ diff --git a/repos/dde_rump/src/server/rump_fs/open_node.h b/repos/dde_rump/src/server/rump_fs/open_node.h deleted file mode 100644 index 942976828..000000000 --- a/repos/dde_rump/src/server/rump_fs/open_node.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * \brief Representation of an open file system node within the component (deprecated) - * \author Christian Prochaska - * \date 2017-06-09 - */ - -/* - * Copyright (C) 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 _OPEN_NODE_H_ -#define _OPEN_NODE_H_ - -/* Genode includes */ -#include -#include - -namespace File_system { - /* - * \param NODE component-specific node type - */ - template class Open_node; -} - -template -class File_system::Open_node : public File_system::Node -{ - private: - - Genode::Id_space::Element _element; - - NODE &_node; - Genode::Constructible _listener; - - Listener::Version const _version_when_opened = _node.curr_version(); - - /* - * Flag to track whether the underlying file-system node was - * modified via this 'Open_node'. That is, if closing the 'Open_node' - * should notify listeners of the file. - */ - bool _was_written = false; - - public: - - Open_node(NODE &node, Genode::Id_space &id_space) - : _element(*this, id_space), _node(node) { } - - ~Open_node() - { - if (_listener.constructed()) { - _node.remove_listener(&*_listener); - _listener.destruct(); - } - - /* - * Notify remaining listeners about the changed file - */ - if (_was_written) - _node.notify_listeners(); - } - - NODE &node() { return _node; } - File_system::Listener &listener() { return *_listener; } - - Genode::Id_space::Id id() { return _element.id(); } - - /** - * Register packet stream sink to be notified of node changes - */ - void register_notify(File_system::Sink &sink) - { - /* - * If there was already a handler registered for the node, - * remove the old handler. - */ - if (_listener.constructed()) { - _node.remove_listener(&*_listener); - _listener.destruct(); - } - - /* - * Register new handler - */ - _listener.construct(sink, id(), _version_when_opened); - _node.add_listener(&*_listener); - } - - void mark_as_written() { _was_written = true; } -}; - -#endif /* _OPEN_NODE_H_ */ diff --git a/repos/dde_rump/src/server/rump_fs/random.cc b/repos/dde_rump/src/server/rump_fs/random.cc deleted file mode 100644 index 80f721300..000000000 --- a/repos/dde_rump/src/server/rump_fs/random.cc +++ /dev/null @@ -1,21 +0,0 @@ -/** - * \brief Dummy random support - * \author Sebastian Sumpf - * \date 2015-02-16 - */ - -/* - * Copyright (C) 2015-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 - - -int rumpuser_getrandom_backend(void *buf, Genode::size_t buflen, int flags, Genode::size_t *retp) -{ - *retp = buflen; - return 0; -} diff --git a/repos/dde_rump/src/server/rump_fs/symlink.h b/repos/dde_rump/src/server/rump_fs/symlink.h deleted file mode 100644 index f9fc7b58e..000000000 --- a/repos/dde_rump/src/server/rump_fs/symlink.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * \brief Rump symlink node - * \author Sebastian Sumpf - * \date 2014-01-20 - */ - -/* - * Copyright (C) 2014-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 _SYMLINK_H_ -#define _SYMLINK_H_ - -/* Genode includes */ -#include -#include - -#include "node.h" - -namespace Rump_fs { - class Symlink; -} - -class Rump_fs::Symlink : public Node -{ - private: - - typedef Genode::Path Path; - - Path _path; - bool _create; - - public: - - Symlink(char const *dir, char const *name, bool create) - : Node(0), _path(name, dir), _create(create) - { - Node::name(name); - } - - Symlink(char const *path) - : Node(0), _path(path), _create(false) - { - Node::name(basename(path)); - } - - size_t write(char const *src, size_t const len, seek_off_t seek_offset) override - { - /* Ideal symlink operations are atomic. */ - if (!_create || seek_offset) - return 0; - - /* src may not be null-terminated */ - Genode::String target(Genode::Cstring(src, len)); - - int ret = rump_sys_symlink(target.string(), _path.base()); - return ret == -1 ? 0 : len; - } - - size_t read(char *dst, size_t len, seek_off_t seek_offset) override - { - int ret = rump_sys_readlink(_path.base(), dst, len); - return ret == -1 ? 0 : ret; - } - - Status status() override - { - Status s; - s.inode = inode(); - s.size = length(); - s.mode = File_system::Status::MODE_SYMLINK; - - return s; - } - - file_size_t length() - { - char link_to[MAX_PATH_LEN]; - return read(link_to, MAX_PATH_LEN, 0); - } -}; - -#endif /* _SYMLINK_H_ */ diff --git a/repos/dde_rump/src/server/rump_fs/target.mk b/repos/dde_rump/src/server/rump_fs/target.mk deleted file mode 100644 index b3108ed02..000000000 --- a/repos/dde_rump/src/server/rump_fs/target.mk +++ /dev/null @@ -1,5 +0,0 @@ -TARGET = rump_fs -SRC_CC = main.cc file_system.cc random.cc -LIBS = base rump rump_fs - -CC_CXX_WARN_STRICT = diff --git a/repos/dde_rump/src/server/rump_fs/undef.h b/repos/dde_rump/src/server/rump_fs/undef.h deleted file mode 100644 index 413419e53..000000000 --- a/repos/dde_rump/src/server/rump_fs/undef.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * \brief Undef macro clashes - * \author Sebastian Sumpf - * \date 2014-01-24 - */ - -/* - * Copyright (C) 2014-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 _UNDEF_H_ -#define _UNDEF_H_ - -extern "C" { -#include -} - -#endif /* _UNDEF_H_ */ diff --git a/repos/dde_zircon/ports/dde_zircon.hash b/repos/dde_zircon/ports/dde_zircon.hash index f7fe8c510..37fc90f16 100644 --- a/repos/dde_zircon/ports/dde_zircon.hash +++ b/repos/dde_zircon/ports/dde_zircon.hash @@ -1 +1 @@ -cb1a09b52cc0c47fb67647b48ffb1678b32ec325 +49e3d96e6feeea70dca5a12b8fe008c77ee08cf6 diff --git a/repos/dde_zircon/ports/dde_zircon.port b/repos/dde_zircon/ports/dde_zircon.port index 6288e6a1f..b90d16b96 100644 --- a/repos/dde_zircon/ports/dde_zircon.port +++ b/repos/dde_zircon/ports/dde_zircon.port @@ -2,6 +2,6 @@ LICENSE := MIT VERSION := git DOWNLOADS := zircon.git -URL(zircon) := https://github.com/fuchsia-mirror/zircon.git +URL(zircon) := https://github.com/jklmnn/zircon.git REV(zircon) := eaed741a38d648f6f2236d3dd171059d4b0c4c7a DIR(zircon) := zircon/src diff --git a/repos/demo/recipes/src/demo/hash b/repos/demo/recipes/src/demo/hash index f891abf8b..f681b693d 100644 --- a/repos/demo/recipes/src/demo/hash +++ b/repos/demo/recipes/src/demo/hash @@ -1 +1 @@ -2019-09-19 4ff18b36f3e45251030e15a733868ac0ca1520dd +2019-11-25 9f9c65c7fff03f784c1d24894e8695ff39c8e3e8 diff --git a/repos/gems/include/gems/vfs_font.h b/repos/gems/include/gems/vfs_font.h index b0512fea6..d2c471675 100644 --- a/repos/gems/include/gems/vfs_font.h +++ b/repos/gems/include/gems/vfs_font.h @@ -14,7 +14,7 @@ #ifndef _INCLUDE__GEMS__VFS_FONT_T_ #define _INCLUDE__GEMS__VFS_FONT_T_ -#include +#include #include namespace Genode { class Vfs_font; } diff --git a/repos/gems/lib/mk/vfs_pipe.mk b/repos/gems/lib/mk/vfs_pipe.mk new file mode 100644 index 000000000..9b3ef9a3d --- /dev/null +++ b/repos/gems/lib/mk/vfs_pipe.mk @@ -0,0 +1,5 @@ +SRC_CC = plugin.cc + +vpath %.cc $(REP_DIR)/src/lib/vfs/pipe + +SHARED_LIB = yes diff --git a/repos/gems/recipes/api/gems/hash b/repos/gems/recipes/api/gems/hash index 434bd18f2..f55e87fd1 100644 --- a/repos/gems/recipes/api/gems/hash +++ b/repos/gems/recipes/api/gems/hash @@ -1 +1 @@ -2019-07-08 18750ec486b7d438efd2c051b94d373eaa8ee7fd +2019-11-18 904ae42c3bb934a4dfd723f7c39b507c2d370b29 diff --git a/repos/gems/recipes/pkg/backdrop/hash b/repos/gems/recipes/pkg/backdrop/hash index d457e8012..55ba1de71 100644 --- a/repos/gems/recipes/pkg/backdrop/hash +++ b/repos/gems/recipes/pkg/backdrop/hash @@ -1 +1 @@ -2019-09-19 893893e7882f981a18ab0a6d7128dc359b28e2d3 +2019-11-25 4b200f0b8b3473539dd6fdbf6e8f3df20892f387 diff --git a/repos/gems/recipes/pkg/depot_download/hash b/repos/gems/recipes/pkg/depot_download/hash index 123aa71e7..90e01f330 100644 --- a/repos/gems/recipes/pkg/depot_download/hash +++ b/repos/gems/recipes/pkg/depot_download/hash @@ -1 +1 @@ -2019-09-19 0ab29e65ce4d6a46edc65d962809fdc354290bb4 +2019-11-25 b612b2891be45e8cbd78de8f2ccc4dfd5269bf27 diff --git a/repos/gems/recipes/pkg/drivers_managed-pc/hash b/repos/gems/recipes/pkg/drivers_managed-pc/hash index 29989c0cf..398ded833 100644 --- a/repos/gems/recipes/pkg/drivers_managed-pc/hash +++ b/repos/gems/recipes/pkg/drivers_managed-pc/hash @@ -1 +1 @@ -2019-09-19 5c4acfdd8906ba9b34c821a2488a0cb3a7bff859 +2019-11-25 ea1b715e1c6c98e6dac36f07f76e84bf8d673f3e diff --git a/repos/gems/recipes/pkg/drivers_nic-muen/hash b/repos/gems/recipes/pkg/drivers_nic-muen/hash index f9f345c4c..00f4ea425 100644 --- a/repos/gems/recipes/pkg/drivers_nic-muen/hash +++ b/repos/gems/recipes/pkg/drivers_nic-muen/hash @@ -1 +1 @@ -2019-09-19 a9a85251ba9f71e7a82c43dad98153a08cb57a84 +2019-11-25 7dbd5e82676cf17750200493f268701990c677a5 diff --git a/repos/gems/recipes/pkg/drivers_nic-pc/hash b/repos/gems/recipes/pkg/drivers_nic-pc/hash index d90ede60c..c8b979b45 100644 --- a/repos/gems/recipes/pkg/drivers_nic-pc/hash +++ b/repos/gems/recipes/pkg/drivers_nic-pc/hash @@ -1 +1 @@ -2019-09-19 ef3b74eaa9e14632e27fecc6ef1f072436d93ebb +2019-11-25 478d11b920bb1a93392c6a9767a154f5b3f96a42 diff --git a/repos/gems/recipes/pkg/drivers_nic-rpi/hash b/repos/gems/recipes/pkg/drivers_nic-rpi/hash index da250e7bc..0536d15c3 100644 --- a/repos/gems/recipes/pkg/drivers_nic-rpi/hash +++ b/repos/gems/recipes/pkg/drivers_nic-rpi/hash @@ -1 +1 @@ -2019-09-19 03eb03d20bad6aba4562abd7869ed32412c4ead2 +2019-11-25 7eeec1839cf0487bbd125bce36f0e76bdd61893e diff --git a/repos/gems/recipes/pkg/drivers_rtc-pc/hash b/repos/gems/recipes/pkg/drivers_rtc-pc/hash index 5a5f2c511..321e7971a 100644 --- a/repos/gems/recipes/pkg/drivers_rtc-pc/hash +++ b/repos/gems/recipes/pkg/drivers_rtc-pc/hash @@ -1 +1 @@ -2019-09-19 3ebbc9ca44e353d7516dd25432089ffc5f74d3d0 +2019-11-25 fb1ce4c2fc3ce877f5cc8401c4735557c19f754c diff --git a/repos/gems/recipes/pkg/fonts_fs/hash b/repos/gems/recipes/pkg/fonts_fs/hash index 3a071a3d7..d7f24a596 100644 --- a/repos/gems/recipes/pkg/fonts_fs/hash +++ b/repos/gems/recipes/pkg/fonts_fs/hash @@ -1 +1 @@ -2019-09-19 beec9d1ee9fa151253c13faadc1886abbc700491 +2019-11-25 38b15214553e59d1a87a22752709bd7f55156805 diff --git a/repos/gems/recipes/pkg/motif_decorator/hash b/repos/gems/recipes/pkg/motif_decorator/hash index 7c753a925..238cba99a 100644 --- a/repos/gems/recipes/pkg/motif_decorator/hash +++ b/repos/gems/recipes/pkg/motif_decorator/hash @@ -1 +1 @@ -2019-09-19 89d1990e070ccc7c4dfce688e4683ae5953ef3ca +2019-11-25 0c188727b541f67b7a6de05db4c84ddf716c7196 diff --git a/repos/gems/recipes/pkg/motif_wm/hash b/repos/gems/recipes/pkg/motif_wm/hash index 3b7b6eb63..289958d52 100644 --- a/repos/gems/recipes/pkg/motif_wm/hash +++ b/repos/gems/recipes/pkg/motif_wm/hash @@ -1 +1 @@ -2019-09-19 d016dc63e02a89258c5c3a7cbf8285a22fb1cd2f +2019-11-25 4df63d53cc1b291c934cd1aaff95ffb0bdf3c957 diff --git a/repos/gems/recipes/pkg/nano3d/hash b/repos/gems/recipes/pkg/nano3d/hash index 870e02030..e97ff4902 100644 --- a/repos/gems/recipes/pkg/nano3d/hash +++ b/repos/gems/recipes/pkg/nano3d/hash @@ -1 +1 @@ -2019-09-19 083b5380dd3d08cf36f1d70d55e9724500d54889 +2019-11-25 5bc3093dc9f91de2ec3c18d4164a567dbfbf5259 diff --git a/repos/gems/recipes/pkg/sculpt-installation/hash b/repos/gems/recipes/pkg/sculpt-installation/hash index 7ce3bbdef..4e09581ce 100644 --- a/repos/gems/recipes/pkg/sculpt-installation/hash +++ b/repos/gems/recipes/pkg/sculpt-installation/hash @@ -1 +1 @@ -2019-09-19 1aa37f5fcbe2bb97155b87be42009e52cc02cc87 +2019-11-25 b4d99abd8b58cd7ff55f9b2d58a452f62b90094f diff --git a/repos/gems/recipes/pkg/sculpt/hash b/repos/gems/recipes/pkg/sculpt/hash index 6780dfe54..09a589c3f 100644 --- a/repos/gems/recipes/pkg/sculpt/hash +++ b/repos/gems/recipes/pkg/sculpt/hash @@ -1 +1 @@ -2019-09-19 cf1a1849fc2535919328c70223e549fca1f3e457 +2019-11-27 2700d23a0e54e22aab30bd204b572f3bee16b46f diff --git a/repos/gems/recipes/pkg/sticks_blue_backdrop/hash b/repos/gems/recipes/pkg/sticks_blue_backdrop/hash index c499f5970..bbed638f0 100644 --- a/repos/gems/recipes/pkg/sticks_blue_backdrop/hash +++ b/repos/gems/recipes/pkg/sticks_blue_backdrop/hash @@ -1 +1 @@ -2019-09-19 50611bb5af751c1a1603b8dd42b1eb14586e2104 +2019-11-25 0aceea8329def17b70c2f7231d8c8f2ffdc78638 diff --git a/repos/gems/recipes/pkg/terminal/hash b/repos/gems/recipes/pkg/terminal/hash index 13f1d99ca..ce89bacc8 100644 --- a/repos/gems/recipes/pkg/terminal/hash +++ b/repos/gems/recipes/pkg/terminal/hash @@ -1 +1 @@ -2019-09-19 9b9176318800aa3db6406d6098ff137da69e42ee +2019-11-25 23bbaef0ca83f32b4bd13179ac428066d0b34067 diff --git a/repos/gems/recipes/pkg/test-depot_query_index/hash b/repos/gems/recipes/pkg/test-depot_query_index/hash index c68a45524..0f021cd3d 100644 --- a/repos/gems/recipes/pkg/test-depot_query_index/hash +++ b/repos/gems/recipes/pkg/test-depot_query_index/hash @@ -1 +1 @@ -2019-09-19 ad3c452a5a743563608d3b3cb62de3a7f36eec10 +2019-11-25 43bce7325a97d360f9d5f1f54396263b355b7587 diff --git a/repos/gems/recipes/pkg/test-fs_tool/hash b/repos/gems/recipes/pkg/test-fs_tool/hash index 07cea989b..14af3add3 100644 --- a/repos/gems/recipes/pkg/test-fs_tool/hash +++ b/repos/gems/recipes/pkg/test-fs_tool/hash @@ -1 +1 @@ -2019-09-19 fd7dec5ab41e7068edaca7e0e61cac4457c8a4ee +2019-11-25 4a1dcaf4eaa43b68f0028c1b6045066185e01a4c diff --git a/repos/gems/recipes/pkg/test-libc_vfs_audit/hash b/repos/gems/recipes/pkg/test-libc_vfs_audit/hash index 248fd99ae..e15a0b43e 100644 --- a/repos/gems/recipes/pkg/test-libc_vfs_audit/hash +++ b/repos/gems/recipes/pkg/test-libc_vfs_audit/hash @@ -1 +1 @@ -2019-09-19 96d1d288fef7fcd93c16123b42bad91277cad422 +2019-11-25 1cd992b13f33d6d68fe15ca5f8f38b918cabd3d2 diff --git a/repos/gems/recipes/pkg/test-magic_ring_buffer/hash b/repos/gems/recipes/pkg/test-magic_ring_buffer/hash index 70f112bd2..933c63ba3 100644 --- a/repos/gems/recipes/pkg/test-magic_ring_buffer/hash +++ b/repos/gems/recipes/pkg/test-magic_ring_buffer/hash @@ -1 +1 @@ -2019-09-19 678cbf67f62f16b5d0bbea7b12ab20f068996f67 +2019-11-25 8bd050dec349fe88ca8eebfc4f32118c2cd4509a diff --git a/repos/gems/recipes/pkg/test-pipe/hash b/repos/gems/recipes/pkg/test-pipe/hash index 74a2491b0..0d83c6996 100644 --- a/repos/gems/recipes/pkg/test-pipe/hash +++ b/repos/gems/recipes/pkg/test-pipe/hash @@ -1 +1 @@ -2019-09-19 2b52afc0b18ff77e13f449c91d7e8472d95d6773 +2019-11-25 8c555960e1a91c5a9a014c254e3eba80e9aa5fb4 diff --git a/repos/gems/recipes/pkg/themed_decorator/hash b/repos/gems/recipes/pkg/themed_decorator/hash index 4d2d437fc..c964bd1d4 100644 --- a/repos/gems/recipes/pkg/themed_decorator/hash +++ b/repos/gems/recipes/pkg/themed_decorator/hash @@ -1 +1 @@ -2019-09-19 341ad5178adf213d0e15f16200136587b875101e +2019-11-25 f01de6158336b5639344d1df17bbeeb817fd406d diff --git a/repos/gems/recipes/pkg/themed_wm/hash b/repos/gems/recipes/pkg/themed_wm/hash index 52db544e2..033ce5066 100644 --- a/repos/gems/recipes/pkg/themed_wm/hash +++ b/repos/gems/recipes/pkg/themed_wm/hash @@ -1 +1 @@ -2019-09-19 b9510ed8c7289136d45bfe176610f454828b5ff8 +2019-11-25 2cd1c104d207d6c70e161177bd62f2863cc69ff6 diff --git a/repos/gems/recipes/pkg/trace_fs/hash b/repos/gems/recipes/pkg/trace_fs/hash index 81e25ed02..deaed0a29 100644 --- a/repos/gems/recipes/pkg/trace_fs/hash +++ b/repos/gems/recipes/pkg/trace_fs/hash @@ -1 +1 @@ -2019-09-19 ec65d1d67bca5ec9c4891036fba2756c6a6843e7 +2019-11-25 c8b208f0ba3c3302839e3568cb3ca4319d79d1ab diff --git a/repos/gems/recipes/pkg/window_layouter/hash b/repos/gems/recipes/pkg/window_layouter/hash index a0d218012..cd55a0f15 100644 --- a/repos/gems/recipes/pkg/window_layouter/hash +++ b/repos/gems/recipes/pkg/window_layouter/hash @@ -1 +1 @@ -2019-09-19 b620ac8acc4d1eeb9a34cd83a15cacff71d98de8 +2019-11-25 8e7fbee8520aa3b5c4351ec7754138921b4ec672 diff --git a/repos/gems/recipes/pkg/wm/hash b/repos/gems/recipes/pkg/wm/hash index 7a4529bb5..a96d854dc 100644 --- a/repos/gems/recipes/pkg/wm/hash +++ b/repos/gems/recipes/pkg/wm/hash @@ -1 +1 @@ -2019-09-19 004777af7089699e099f2c2745b7e7051051b97e +2019-11-25 13382c1901f03d3599b4db47f04555f494d416cb diff --git a/repos/gems/recipes/pkg/wm/runtime b/repos/gems/recipes/pkg/wm/runtime index 9c92c01a9..e9954f96d 100644 --- a/repos/gems/recipes/pkg/wm/runtime +++ b/repos/gems/recipes/pkg/wm/runtime @@ -1,4 +1,4 @@ - + diff --git a/repos/gems/recipes/raw/drivers_managed-pc/hash b/repos/gems/recipes/raw/drivers_managed-pc/hash index f7afd8aec..a79714584 100644 --- a/repos/gems/recipes/raw/drivers_managed-pc/hash +++ b/repos/gems/recipes/raw/drivers_managed-pc/hash @@ -1 +1 @@ -2019-08-27 13a85452fb4899c5fbe005f6e73d9676603a2419 +2019-11-18 ea6827a7199ff4b425bea8eaede599014e3a50cd diff --git a/repos/gems/recipes/raw/drivers_managed-pc/numlock_remap.config b/repos/gems/recipes/raw/drivers_managed-pc/numlock_remap.config index d8d6e904f..673483c43 100644 --- a/repos/gems/recipes/raw/drivers_managed-pc/numlock_remap.config +++ b/repos/gems/recipes/raw/drivers_managed-pc/numlock_remap.config @@ -12,7 +12,7 @@ - + diff --git a/repos/gems/recipes/src/backdrop/hash b/repos/gems/recipes/src/backdrop/hash index d676f385a..0bb6eb9e2 100644 --- a/repos/gems/recipes/src/backdrop/hash +++ b/repos/gems/recipes/src/backdrop/hash @@ -1 +1 @@ -2019-09-19 039cf639c690980b77e67baca0265304561cca73 +2019-11-25 811aa8b2f4517c2633c0e7a4bff53a1152a392a4 diff --git a/repos/gems/recipes/src/cpu_load_display/hash b/repos/gems/recipes/src/cpu_load_display/hash index 99ad19c1f..b61573f91 100644 --- a/repos/gems/recipes/src/cpu_load_display/hash +++ b/repos/gems/recipes/src/cpu_load_display/hash @@ -1 +1 @@ -2019-09-19 0150a1e4db7192d6b26defc457300d2a2d14a1c0 +2019-11-25 ab834edf02a1b869220d04a6265a76d2f3c16f09 diff --git a/repos/gems/recipes/src/decorator/hash b/repos/gems/recipes/src/decorator/hash index c2eeeede9..a184d90b2 100644 --- a/repos/gems/recipes/src/decorator/hash +++ b/repos/gems/recipes/src/decorator/hash @@ -1 +1 @@ -2019-09-19 f8134eaa4371c818459b4d06dadd72508d026c47 +2019-11-25 b94b2c9bd10dc7527e6ce8d6909cc1180adab20e diff --git a/repos/gems/recipes/src/depot_deploy/hash b/repos/gems/recipes/src/depot_deploy/hash index 1625c9496..25466d3fe 100644 --- a/repos/gems/recipes/src/depot_deploy/hash +++ b/repos/gems/recipes/src/depot_deploy/hash @@ -1 +1 @@ -2019-09-19 85043103f701f4118c153a92abc7380ab85e3821 +2019-11-25 e3c72094faf411fc27f50a8efdcc74185f52a71d diff --git a/repos/gems/recipes/src/depot_download_manager/hash b/repos/gems/recipes/src/depot_download_manager/hash index fdce998cc..7f9834136 100644 --- a/repos/gems/recipes/src/depot_download_manager/hash +++ b/repos/gems/recipes/src/depot_download_manager/hash @@ -1 +1 @@ -2019-09-19 f6e29600aaf413382f89900d990eb5de0d5405e5 +2019-11-25 6718e3c7286fbdaa332935d841b4a8a5c4350f21 diff --git a/repos/gems/recipes/src/depot_query/content.mk b/repos/gems/recipes/src/depot_query/content.mk index 19ba54374..60237cf4e 100644 --- a/repos/gems/recipes/src/depot_query/content.mk +++ b/repos/gems/recipes/src/depot_query/content.mk @@ -2,7 +2,7 @@ SRC_DIR := src/app/depot_query include $(GENODE_DIR)/repos/base/recipes/src/content.inc -MIRROR_FROM_REP_DIR := include/depot include/gems/vfs.h include/gems/lru_cache.h +MIRROR_FROM_REP_DIR := include/depot include/gems/lru_cache.h content: $(MIRROR_FROM_REP_DIR) diff --git a/repos/gems/recipes/src/depot_query/hash b/repos/gems/recipes/src/depot_query/hash index 008bdfa16..61c0edae4 100644 --- a/repos/gems/recipes/src/depot_query/hash +++ b/repos/gems/recipes/src/depot_query/hash @@ -1 +1 @@ -2019-09-19 c067fb4d3ca81f2c4867d9ddcb2693e98d533d20 +2019-11-25 108b5e48e89ae82ffbf1a4e3a774c85df5a67a8a diff --git a/repos/gems/recipes/src/driver_manager/hash b/repos/gems/recipes/src/driver_manager/hash index f99ae52c6..d3a1ae3aa 100644 --- a/repos/gems/recipes/src/driver_manager/hash +++ b/repos/gems/recipes/src/driver_manager/hash @@ -1 +1 @@ -2019-09-19 66239d27d1153d8738fcf2a858d8dc615423a61a +2019-11-25 ee43dc9c49bd304318f90f3780a56830fe64ec6c diff --git a/repos/gems/recipes/src/exec_terminal/hash b/repos/gems/recipes/src/exec_terminal/hash index 7621862a1..0c51e01be 100644 --- a/repos/gems/recipes/src/exec_terminal/hash +++ b/repos/gems/recipes/src/exec_terminal/hash @@ -1 +1 @@ -2019-09-19 90e5a6040e6f8e27b8644722c75654a05bba7468 +2019-11-25 20f0340672133c8bf4e5dd00dc8a87ff235735fe diff --git a/repos/gems/recipes/src/file_terminal/hash b/repos/gems/recipes/src/file_terminal/hash index 839eaac3c..7b2c90339 100644 --- a/repos/gems/recipes/src/file_terminal/hash +++ b/repos/gems/recipes/src/file_terminal/hash @@ -1 +1 @@ -2019-09-19 bb985ac6347b5e0cea434f537fcafd559e7bca0e +2019-11-25 f807ebb83892057f2887339ef2d73f90d54da213 diff --git a/repos/gems/recipes/src/fs_query/content.mk b/repos/gems/recipes/src/fs_query/content.mk index f00e37475..2431cd726 100644 --- a/repos/gems/recipes/src/fs_query/content.mk +++ b/repos/gems/recipes/src/fs_query/content.mk @@ -2,8 +2,6 @@ SRC_DIR := src/app/fs_query include $(GENODE_DIR)/repos/base/recipes/src/content.inc -MIRROR_FROM_REP_DIR := include/gems/vfs.h - content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_REP_DIR): diff --git a/repos/gems/recipes/src/fs_query/hash b/repos/gems/recipes/src/fs_query/hash index eaaf2f6ef..a072cc012 100644 --- a/repos/gems/recipes/src/fs_query/hash +++ b/repos/gems/recipes/src/fs_query/hash @@ -1 +1 @@ -2019-09-19 98fe540b42bf7df311eee5f927daf6bace128b68 +2019-11-25 6841967aa4ee60055e3919c17ad085cb10249cbc diff --git a/repos/gems/recipes/src/fs_tool/content.mk b/repos/gems/recipes/src/fs_tool/content.mk index bc1067503..5ac42d5d7 100644 --- a/repos/gems/recipes/src/fs_tool/content.mk +++ b/repos/gems/recipes/src/fs_tool/content.mk @@ -2,8 +2,6 @@ SRC_DIR := src/app/fs_tool include $(GENODE_DIR)/repos/base/recipes/src/content.inc -MIRROR_FROM_REP_DIR := include/gems/vfs.h - content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_REP_DIR): diff --git a/repos/gems/recipes/src/fs_tool/hash b/repos/gems/recipes/src/fs_tool/hash index 7f33b1760..cff907985 100644 --- a/repos/gems/recipes/src/fs_tool/hash +++ b/repos/gems/recipes/src/fs_tool/hash @@ -1 +1 @@ -2019-09-19 b8e4a902379b3a4649cbbc91e2cdd09e7ef58d5d +2019-11-25 a9832a77d1a157dd00c7a2ad016993793e07883e diff --git a/repos/gems/recipes/src/gpt_write/hash b/repos/gems/recipes/src/gpt_write/hash index 04f85d519..8b38536bf 100644 --- a/repos/gems/recipes/src/gpt_write/hash +++ b/repos/gems/recipes/src/gpt_write/hash @@ -1 +1 @@ -2019-09-19 fc84d50520923fc5d0533cd8ba540c4fec37f304 +2019-11-25 f0b6175acf66a2d04a1226796de3b3061a52a753 diff --git a/repos/gems/recipes/src/menu_view/hash b/repos/gems/recipes/src/menu_view/hash index da7116e3d..46dd526f6 100644 --- a/repos/gems/recipes/src/menu_view/hash +++ b/repos/gems/recipes/src/menu_view/hash @@ -1 +1 @@ -2019-09-19 f14acd30d69f4e72ca1f71f3386b66fc6209fe18 +2019-11-25 410499fec7720a6197ddacce7fc485a51280e755 diff --git a/repos/gems/recipes/src/mixer_gui_qt/hash b/repos/gems/recipes/src/mixer_gui_qt/hash index 5021deeb5..e4fc63735 100644 --- a/repos/gems/recipes/src/mixer_gui_qt/hash +++ b/repos/gems/recipes/src/mixer_gui_qt/hash @@ -1 +1 @@ -2019-09-19 7b3394d2e1ff73e810bc02d25c92142a9fae3b22 +2019-11-25 ff1fa1148789cff421861aabde3f9860d7c26b8a diff --git a/repos/gems/recipes/src/nano3d/hash b/repos/gems/recipes/src/nano3d/hash index af149ef2c..81ac61b41 100644 --- a/repos/gems/recipes/src/nano3d/hash +++ b/repos/gems/recipes/src/nano3d/hash @@ -1 +1 @@ -2019-09-19 81429cd7fe7b28a59f3a18fa37068f0f4d946419 +2019-11-25 54976513bb3fd9f8d67e52c5695c882ec4fd5638 diff --git a/repos/gems/recipes/src/nit_fader/hash b/repos/gems/recipes/src/nit_fader/hash index 2194750b6..82a627cee 100644 --- a/repos/gems/recipes/src/nit_fader/hash +++ b/repos/gems/recipes/src/nit_fader/hash @@ -1 +1 @@ -2019-09-19 dbb92feddf9dbf85f5c5b0c1c509cd319d41379f +2019-11-25 e7ca6a86f9e117f9643ff44d1210e66835fc6efb diff --git a/repos/gems/recipes/src/pipe/hash b/repos/gems/recipes/src/pipe/hash index 8d9f21cbc..1d050ac92 100644 --- a/repos/gems/recipes/src/pipe/hash +++ b/repos/gems/recipes/src/pipe/hash @@ -1 +1 @@ -2019-09-19 0ca3de2b8f0d6e3f0ec0c1ba66c71e09ec3bbbad +2019-11-25 c339958dc4c8b377a90fc559d28cf6fb8c512863 diff --git a/repos/gems/recipes/src/sculpt_manager/hash b/repos/gems/recipes/src/sculpt_manager/hash index bddf25ead..191dd11c6 100644 --- a/repos/gems/recipes/src/sculpt_manager/hash +++ b/repos/gems/recipes/src/sculpt_manager/hash @@ -1 +1 @@ -2019-09-19 2424198f417ad5207a736647cd7503828da39839 +2019-11-27 66de807f7f69ef502549d7f3af2b8e0571990638 diff --git a/repos/gems/recipes/src/ssh_terminal/hash b/repos/gems/recipes/src/ssh_terminal/hash index c6e7a94c9..318473f6f 100644 --- a/repos/gems/recipes/src/ssh_terminal/hash +++ b/repos/gems/recipes/src/ssh_terminal/hash @@ -1 +1 @@ -2019-09-19 b8b2cb67af68217e158352d930101ddffa00f02e +2019-11-25 e1392c56e3387d1b5cda9553d4948b29a8c6da1d diff --git a/repos/gems/recipes/src/terminal/hash b/repos/gems/recipes/src/terminal/hash index 02d13f296..f7a8719f9 100644 --- a/repos/gems/recipes/src/terminal/hash +++ b/repos/gems/recipes/src/terminal/hash @@ -1 +1 @@ -2019-09-19 c06ff932c47f4bfae86c5d4804cd0a222bb8d401 +2019-11-25 da6d2b142f7004a1945fbeb06b9c4e3ff54ebb3e diff --git a/repos/gems/recipes/src/test-magic_ring_buffer/hash b/repos/gems/recipes/src/test-magic_ring_buffer/hash index 74f6e953b..b87eb4b39 100644 --- a/repos/gems/recipes/src/test-magic_ring_buffer/hash +++ b/repos/gems/recipes/src/test-magic_ring_buffer/hash @@ -1 +1 @@ -2019-09-19 cd71aeeea8e23b8544662623fabae2441a73720b +2019-11-25 e7c7a4be584a45b3404a805a3af2a040eadf5fe2 diff --git a/repos/gems/recipes/src/test-tiled_wm/hash b/repos/gems/recipes/src/test-tiled_wm/hash index cd7763487..1f7a077d7 100644 --- a/repos/gems/recipes/src/test-tiled_wm/hash +++ b/repos/gems/recipes/src/test-tiled_wm/hash @@ -1 +1 @@ -2019-09-19 a3dd4a113f715fb295edbd2292e76fd2fc4ca296 +2019-11-25 03c39635150f06af54e6bb2b4393c7ed87fa9644 diff --git a/repos/gems/recipes/src/themed_decorator/hash b/repos/gems/recipes/src/themed_decorator/hash index caa617cd7..5ed6ab6c2 100644 --- a/repos/gems/recipes/src/themed_decorator/hash +++ b/repos/gems/recipes/src/themed_decorator/hash @@ -1 +1 @@ -2019-09-19 555f792df373572505788f9996eb45c01eea6a37 +2019-11-25 8a2700a6b388a7c1455a286e108f9fb7e202ea5b diff --git a/repos/gems/recipes/src/vfs_audit/hash b/repos/gems/recipes/src/vfs_audit/hash index 38b0465e0..80b954490 100644 --- a/repos/gems/recipes/src/vfs_audit/hash +++ b/repos/gems/recipes/src/vfs_audit/hash @@ -1 +1 @@ -2019-09-19 66450f8bd2a927f3425094c91f20247611c38d7e +2019-11-25 7fab6698667eae958794e6554d6d1c6d101427f5 diff --git a/repos/gems/recipes/src/vfs_import/hash b/repos/gems/recipes/src/vfs_import/hash index 536a26226..83ab0600a 100644 --- a/repos/gems/recipes/src/vfs_import/hash +++ b/repos/gems/recipes/src/vfs_import/hash @@ -1 +1 @@ -2019-09-19 f561e566b5dfd917f356bb270b7841da0b4dd1ae +2019-11-25 9fbaad77735e9e6a9f50a840f8fd3df124a0a316 diff --git a/repos/gems/recipes/src/vfs_pipe/content.mk b/repos/gems/recipes/src/vfs_pipe/content.mk new file mode 100644 index 000000000..9e0246b49 --- /dev/null +++ b/repos/gems/recipes/src/vfs_pipe/content.mk @@ -0,0 +1,9 @@ +MIRROR_FROM_REP_DIR := lib/mk/vfs_pipe.mk src/lib/vfs/pipe + +content: $(MIRROR_FROM_REP_DIR) LICENSE + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +LICENSE: + cp $(GENODE_DIR)/LICENSE $@ diff --git a/repos/gems/recipes/src/vfs_pipe/hash b/repos/gems/recipes/src/vfs_pipe/hash new file mode 100644 index 000000000..3c9fdb1ff --- /dev/null +++ b/repos/gems/recipes/src/vfs_pipe/hash @@ -0,0 +1 @@ +2019-11-25 5f54077b7f54b812aa50f8c25c3b8f29a5095ded diff --git a/repos/gems/recipes/src/vfs_pipe/used_apis b/repos/gems/recipes/src/vfs_pipe/used_apis new file mode 100644 index 000000000..6069d7955 --- /dev/null +++ b/repos/gems/recipes/src/vfs_pipe/used_apis @@ -0,0 +1,4 @@ +base +os +so +vfs diff --git a/repos/gems/recipes/src/vfs_trace/hash b/repos/gems/recipes/src/vfs_trace/hash index a762457d4..32e389d16 100644 --- a/repos/gems/recipes/src/vfs_trace/hash +++ b/repos/gems/recipes/src/vfs_trace/hash @@ -1 +1 @@ -2019-09-19 26a30f4dee93ba9052fe8fd150ea82e926928a84 +2019-11-25 c8350241ed7ed7d33aeb0553c3c254025df1d630 diff --git a/repos/gems/recipes/src/vfs_ttf/hash b/repos/gems/recipes/src/vfs_ttf/hash index 4f077c8a9..556d53fef 100644 --- a/repos/gems/recipes/src/vfs_ttf/hash +++ b/repos/gems/recipes/src/vfs_ttf/hash @@ -1 +1 @@ -2019-09-19 f2b6ff6bdc5f166c6e172b3ffad579f1c192255d +2019-11-25 0a1c475bf28bcbc268eeb9cc3100f5d6613e13fd diff --git a/repos/gems/recipes/src/window_layouter/hash b/repos/gems/recipes/src/window_layouter/hash index ab9514b04..47caa9641 100644 --- a/repos/gems/recipes/src/window_layouter/hash +++ b/repos/gems/recipes/src/window_layouter/hash @@ -1 +1 @@ -2019-09-19 41e02ab2aec84e742cd11f4615fcfb9b61ab28a4 +2019-11-25 67ecd042d2f0297bd8ec84819104747a7bafa7e8 diff --git a/repos/gems/recipes/src/wm/hash b/repos/gems/recipes/src/wm/hash index 12088fc69..e04b18f29 100644 --- a/repos/gems/recipes/src/wm/hash +++ b/repos/gems/recipes/src/wm/hash @@ -1 +1 @@ -2019-09-19 0430e445f8e6461766b7ffcb40b889797863fbd1 +2019-11-25 9d6ba25e093547b5ee47554b535037aba3236749 diff --git a/repos/gems/run/depot_autopilot.run b/repos/gems/run/depot_autopilot.run index f0d4dfc7b..00ef32561 100644 --- a/repos/gems/run/depot_autopilot.run +++ b/repos/gems/run/depot_autopilot.run @@ -770,8 +770,6 @@ set skip_test(test-solo5) [expr ![have_spec x86_64]] set skip_test(test-spark_exception) [expr [have_spec arm]] set skip_test(test-tcp_bulk_lwip) [expr ![have_spec x86]] set skip_test(test-tcp_bulk_lxip) [expr ![have_spec x86]] -set skip_test(test-xml_generator) [expr [have_spec arm_v8a]] -set skip_test(gcov) [expr [have_spec arm_v8a]] set skip_test(test-rust) [expr [have_spec arm_v8a]] # diff --git a/repos/gems/run/launcher.run b/repos/gems/run/launcher.run deleted file mode 100644 index e672faa8a..000000000 --- a/repos/gems/run/launcher.run +++ /dev/null @@ -1,306 +0,0 @@ -create_boot_directory - -import_from_depot [depot_user]/src/[base_src] \ - [depot_user]/pkg/[drivers_interactive_pkg] \ - [depot_user]/pkg/motif_wm \ - [depot_user]/raw/genode_bg \ - [depot_user]/pkg/fonts_fs \ - [depot_user]/pkg/backdrop \ - [depot_user]/src/demo \ - [depot_user]/src/init \ - [depot_user]/src/nitpicker \ - [depot_user]/src/nit_fb \ - [depot_user]/src/nit_fader \ - [depot_user]/src/rom_filter \ - [depot_user]/src/menu_view - -install_config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <minimizer/> <maximizer/> <closer/> - </controls> - </inline> - <if> - <has_value input="xray_enabled" value="yes" /> - <then> - <inline> - <default-policy color="#ff0000" gradient="75" /> - </inline> - </then> - </if> - </output> - - </config> - <route> - <service name="ROM" label="xray"> <child name="report_rom"/> </service> - <any-service> <parent/> </any-service> - </route> - </start> - - <start name="fonts_fs" caps="300"> - <resource name="RAM" quantum="8M"/> - <binary name="vfs"/> - <route> - <service name="ROM" label="config"> <parent label="fonts_fs.config"/> </service> - <any-service> <parent/> </any-service> - </route> - <provides> <service name="File_system"/> </provides> - </start> - - <start name="launcher" caps="10000"> - <resource name="RAM" quantum="60M" /> - <config focus_prefix="wm -> launcher -> "> - <subsystem name="scout" title="Scout" caps="200"> - <resource name="RAM" quantum="20M" /> - <binary name="scout" /> - </subsystem> - <subsystem name="testnit1" title="Nitpicker Test" caps="100"> - <resource name="RAM" quantum="2M" /> - <binary name="testnit" /> - </subsystem> - <subsystem name="testnit2" title="Nitpicker Test 2" caps="100"> - <resource name="RAM" quantum="2M" /> - <binary name="testnit" /> - </subsystem> - <subsystem name="testnit3" title="Nitpicker Test 3" caps="100"> - <resource name="RAM" quantum="2M" /> - <binary name="testnit" /> - </subsystem> - <subsystem name="scout2" title="Scoutx" caps="200"> - <resource name="RAM" quantum="20M" /> - <binary name="scout" /> - </subsystem> - <subsystem name="testnit4" title="Nitpicker Testx" caps="100"> - <resource name="RAM" quantum="2M" /> - <binary name="testnit" /> - </subsystem> - <subsystem name="testnit5" title="Nitpicker Test5" caps="100"> - <resource name="RAM" quantum="2M" /> - <binary name="testnit" /> - </subsystem> - <subsystem name="backdrop" title="Backdrop" caps="100"> - <resource name="RAM" quantum="8M"/> - <binary name="backdrop" /> - <config> - <libc> - <vfs> - </vfs> - </libc> - <fill color="#224433" /> - </config> - </subsystem> - - </config> - <route> - <service name="ROM" label="focus"> <child name="report_rom" /> </service> - <service name="File_system" label="fonts"> <child name="fonts_fs"/> </service> - <any-service> <child name="wm"/> <parent/> <any-child/> </any-service> - </route> - </start> -</config>} - -build { app/launcher test/nitpicker app/status_bar app/global_keys_handler } - -build_boot_image { testnit launcher global_keys_handler status_bar } - -run_genode_until forever diff --git a/repos/gems/run/sculpt.run b/repos/gems/run/sculpt.run index 6ea1a51d4..546a63cc3 100644 --- a/repos/gems/run/sculpt.run +++ b/repos/gems/run/sculpt.run @@ -534,7 +534,7 @@ exec gzip -dc [genode_dir]/repos/gems/run/sculpt/machine.vdi.gz > [run_dir]/geno # Note: the string must be exactly 5 bytes long. # proc sculpt_version { } { - return "19.08" } + return "19.11" } # write file with newline (for producing nice output when using 'cat /VERSION') set fd [open [run_dir]/genode/VERSION w] diff --git a/repos/gems/run/terminal_mux.run b/repos/gems/run/terminal_mux.run deleted file mode 100644 index 84c7ccd10..000000000 --- a/repos/gems/run/terminal_mux.run +++ /dev/null @@ -1,164 +0,0 @@ -# -# \brief Example for using the terminal_mux server over UART -# \author Norman Feske -# \date 2013-02-20 -# - -assert_spec x86 - -# -# On Linux, we don't have a UART driver, on which this run script depends. -# -if {[have_spec linux]} { puts "Run script does not support Linux"; exit 0 } - -set build_components { - core init noux lib/libc_noux app/cli_monitor test/bomb test/signal - test/resource_yield timer drivers/uart server/terminal_mux - server/terminal_log noux-pkg/vim -} - -build $build_components - -create_boot_directory - -append config { - <config> - <parent-provides> - <service name="ROM"/> - <service name="LOG"/> - <service name="RM"/> - <service name="CPU"/> - <service name="PD"/> - <service name="IRQ"/> - <service name="IO_PORT"/> - <service name="IO_MEM"/> - </parent-provides> - <default-route> - <any-service> <any-child/> <parent/> </any-service> - </default-route> - <default caps="100"/> - <start name="timer"> - <resource name="RAM" quantum="1M"/> - <provides><service name="Timer"/></provides> - <route> <any-service> <parent/> </any-service> </route> - </start> - <start name="pc_uart_drv"> - <resource name="RAM" quantum="1M"/> - <provides> - <service name="Uart"/> - <service name="Terminal"/> - </provides> - <config> - <policy label_prefix="terminal_mux" uart="1" detect_size="yes"/> - </config> - <route> <any-service> <parent/> <any-child/> </any-service> </route> - </start> - <start name="terminal_mux"> - <resource name="RAM" quantum="4M"/> - <provides> - <service name="Terminal"/> - </provides> - <route> - <service name="Terminal"> <child name="pc_uart_drv" /> </service> - <any-service> <parent/> <any-child /> </any-service> - </route> - </start> - <start name="terminal_log"> - <resource name="RAM" quantum="2M"/> - <provides> - <service name="LOG"/> - </provides> - <route> - <service name="Terminal"> <child name="terminal_mux" /> </service> - <any-service> <parent/> <any-child/> </any-service> - </route> - </start> - <start name="cli_monitor"> - <resource name="RAM" quantum="100M"/> - <config> - <preservation name="RAM" quantum="16M" /> - <vfs> - <dir name="subsystems"> - <inline name="noux.subsystem"> - <subsystem name="noux" help="VIM executed in the noux runtime"> - <resource name="RAM" quantum="16M" /> - <config> - <fstab> <tar name="vim.tar" /> </fstab> - <start name="/bin/vim"> - <env name="TERM" value="screen" /> - - <!-- Deactivate the loading of plugins. Otherwise, vim will - attempt to use a sub shell for pattern matching --> - <arg value="--noplugin" /> - - <!-- Do not use swap file. Any attempt to create of would - fail because we are on a read-only file system --> - <arg value="-n" /> - - <!-- Use the nocompatible mode, which is much nicer than - the plain vi mode --> - <arg value="-N" /> - - <!-- Permanently display status bar --> - <arg value="--cmd" /> - <arg value="set laststatus=2" /> - - <!-- Enable highlighted search results --> - <arg value="--cmd" /> - <arg value="set hls" /> - </start> - </config> - </subsystem> - </inline> - <inline name="ram_eater.subsystem"> - <subsystem name="ram_eater" help="resource-yield test program"> - <resource name="RAM" quantum="25M" /> - <binary name="test-resource_yield" /> - <config child="yes" expand="yes" period_ms="100" /> - </subsystem> - </inline> - <inline name="signal.subsystem"> - <subsystem name="signal" help="signalling test program"> - <resource name="RAM" quantum="5M" /> - <binary name="test-signal" /> - </subsystem> - </inline> - </dir> - </vfs> - </config> - <route> - <any-service> <child name="terminal_mux" /> <any-child/> <parent/> </any-service> - </route> - </start> - </config> -} - -install_config $config - - -# -# Boot modules -# - -# generic modules -set boot_modules { - core init timer ld.lib.so noux terminal_mux terminal_log - test-signal cli_monitor test-resource_yield posix.lib.so - libc.lib.so vfs.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so - vim.tar pc_uart_drv -} - -set fiasco_serial_esc_arg "" - -build_boot_image $boot_modules - -append qemu_args " -nographic " - -# -# On all kernels, we write the core debug output to the kdb.log file, -# and use qemu's stdio as the UART used by terminal_mux. -# -append qemu_args " -serial file:kdb.log " -append qemu_args " -serial mon:stdio" - -run_genode_until forever diff --git a/repos/gems/src/app/depot_deploy/child.h b/repos/gems/src/app/depot_deploy/child.h index 96b820550..d542dbb5c 100644 --- a/repos/gems/src/app/depot_deploy/child.h +++ b/repos/gems/src/app/depot_deploy/child.h @@ -97,6 +97,7 @@ class Depot_deploy::Child : public List_model<Child>::Element */ Number_of_bytes _pkg_ram_quota { 0 }; unsigned long _pkg_cap_quota { 0 }; + unsigned long _pkg_cpu_quota { 0 }; Binary_name _binary_name { }; Config_name _config_name { }; @@ -181,6 +182,7 @@ class Depot_deploy::Child : public List_model<Child>::Element _pkg_ram_quota = runtime.attribute_value("ram", Number_of_bytes()); _pkg_cap_quota = runtime.attribute_value("caps", 0UL); + _pkg_cpu_quota = runtime.attribute_value("cpu", 0UL); _binary_name = runtime.attribute_value("binary", Binary_name()); _config_name = runtime.attribute_value("config", Config_name()); @@ -356,6 +358,16 @@ void Depot_deploy::Child::gen_start_node(Xml_generator &xml, Xml_node common, xml.attribute("quantum", String<32>(ram)); }); + unsigned long cpu_quota = _pkg_cpu_quota; + if (_defined_by_launcher()) + cpu_quota = _launcher_xml->xml().attribute_value("cpu", cpu_quota); + cpu_quota = _start_xml->xml().attribute_value("cpu", cpu_quota); + + xml.node("resource", [&] () { + xml.attribute("name", "CPU"); + xml.attribute("quantum", cpu_quota); + }); + Xml_node const runtime = _pkg_xml->xml().sub_node("runtime"); /* diff --git a/repos/gems/src/app/depot_deploy/children.h b/repos/gems/src/app/depot_deploy/children.h index 558e6795a..04fcbc24d 100644 --- a/repos/gems/src/app/depot_deploy/children.h +++ b/repos/gems/src/app/depot_deploy/children.h @@ -133,6 +133,14 @@ class Depot_deploy::Children child.gen_installation_entry(xml); }); } + size_t count() const + { + size_t count = 0; + _children.for_each([&] (Child const &) { + ++count; }); + return count; + } + bool any_incomplete() const { bool result = false; diff --git a/repos/gems/src/app/depot_deploy/main.cc b/repos/gems/src/app/depot_deploy/main.cc index 683f385cb..eac86d841 100644 --- a/repos/gems/src/app/depot_deploy/main.cc +++ b/repos/gems/src/app/depot_deploy/main.cc @@ -13,6 +13,7 @@ /* Genode includes */ #include <util/retry.h> +#include <util/reconstructible.h> #include <base/component.h> #include <base/attached_rom_dataspace.h> #include <base/heap.h> @@ -34,6 +35,8 @@ struct Depot_deploy::Main Expanding_reporter _query_reporter { _env, "query" , "query"}; Expanding_reporter _init_config_reporter { _env, "config", "init.config"}; + Constructible<Expanding_reporter> _state_reporter { }; + Heap _heap { _env.ram(), _env.rm() }; Children _children { _heap }; @@ -48,6 +51,16 @@ struct Depot_deploy::Main _config.update(); _blueprint.update(); + bool const report_state = + _config.xml().has_sub_node("report") && + _config.xml().sub_node("report").attribute_value("state", false); + + _state_reporter.conditional(report_state, _env, "state", "state"); + + if (_state_reporter.constructed()) + _state_reporter->generate([&] (Xml_generator xml) { + xml.attribute("running", true); }); + Xml_node const config = _config.xml(); _children.apply_config(config); @@ -76,6 +89,17 @@ struct Depot_deploy::Main _children.gen_queries(xml); }); } + + if ((_children.count() > 0UL) + && !_children.any_incomplete() + && !_children.any_blueprint_needed() + && _state_reporter.constructed()) { + + _state_reporter->generate([&] (Xml_generator xml) { + xml.attribute("running", false); + xml.attribute("count", _children.count()); + }); + } } Main(Env &env) : _env(env) @@ -83,6 +107,7 @@ struct Depot_deploy::Main _config .sigh(_config_handler); _blueprint.sigh(_config_handler); + _handle_config(); } }; diff --git a/repos/gems/src/app/depot_download_manager/gen_extract.cc b/repos/gems/src/app/depot_download_manager/gen_extract.cc index 2ea6504a8..4c1c66379 100644 --- a/repos/gems/src/app/depot_download_manager/gen_extract.cc +++ b/repos/gems/src/app/depot_download_manager/gen_extract.cc @@ -25,10 +25,11 @@ void Depot_download_manager::gen_extract_start_content(Xml_generator &xml, xml.attribute("verbose", "yes"); xml.node("libc", [&] () { - xml.attribute("stdout", "/dev/log"); - xml.attribute("stderr", "/dev/log"); - xml.attribute("rtc", "/dev/null"); - xml.attribute("cwd", user_path); + xml.attribute("stdout", "/dev/log"); + xml.attribute("stderr", "/dev/log"); + xml.attribute("rtc", "/dev/null"); + xml.attribute("cwd", user_path); + xml.attribute("update_mtime", "no"); }); xml.node("vfs", [&] () { diff --git a/repos/gems/src/app/depot_query/main.cc b/repos/gems/src/app/depot_query/main.cc index c983c0975..fdedbbf26 100644 --- a/repos/gems/src/app/depot_query/main.cc +++ b/repos/gems/src/app/depot_query/main.cc @@ -16,7 +16,7 @@ #include <base/heap.h> #include <base/attached_rom_dataspace.h> #include <os/reporter.h> -#include <gems/vfs.h> +#include <os/vfs.h> #include <depot/archive.h> #include <gems/lru_cache.h> diff --git a/repos/gems/src/app/fs_query/main.cc b/repos/gems/src/app/fs_query/main.cc index 859105110..28b93778f 100644 --- a/repos/gems/src/app/fs_query/main.cc +++ b/repos/gems/src/app/fs_query/main.cc @@ -17,7 +17,7 @@ #include <base/heap.h> #include <base/attached_rom_dataspace.h> #include <os/reporter.h> -#include <gems/vfs.h> +#include <os/vfs.h> namespace Fs_query { using namespace Genode; @@ -104,7 +104,11 @@ struct Fs_query::Watched_directory _dir(other, rel_path), _watcher(other, rel_path, handler) { _dir.for_each_entry([&] (Directory::Entry const &entry) { - if (entry.type() == Vfs::Directory_service::DIRENT_TYPE_FILE) { + + using Dirent_type = Vfs::Directory_service::Dirent_type; + bool const file = (entry.type() == Dirent_type::CONTINUOUS_FILE) + || (entry.type() == Dirent_type::TRANSACTIONAL_FILE); + if (file) { try { new (_alloc) Registered<Watched_file>(_files, _dir, entry.name(), handler); } catch (...) { } diff --git a/repos/gems/src/app/fs_tool/main.cc b/repos/gems/src/app/fs_tool/main.cc index 54ba93c97..3b5e07b90 100644 --- a/repos/gems/src/app/fs_tool/main.cc +++ b/repos/gems/src/app/fs_tool/main.cc @@ -16,7 +16,7 @@ #include <base/sleep.h> #include <base/attached_rom_dataspace.h> #include <base/heap.h> -#include <gems/vfs.h> +#include <os/vfs.h> namespace Fs_tool { using namespace Genode; diff --git a/repos/gems/src/app/launcher/context_dialog.h b/repos/gems/src/app/launcher/context_dialog.h deleted file mode 100644 index 859d51764..000000000 --- a/repos/gems/src/app/launcher/context_dialog.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * \brief Context dialog - * \author Norman Feske - * \date 2014-10-04 - */ - -/* - * Copyright (C) 2014-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 _CONTEXT_DIALOG_H_ -#define _CONTEXT_DIALOG_H_ - -/* local includes */ -#include <fading_dialog.h> - -namespace Launcher { struct Context_dialog; } - - -class Launcher::Context_dialog : Input_event_handler, Dialog_generator, - Hover_handler, Dialog_model -{ - public: - - struct Response_handler - { - virtual void handle_context_kill() = 0; - virtual void handle_context_hide() = 0; - }; - - private: - - struct Element : List<Element>::Element - { - Label label; - - bool hovered = false; - bool touched = false; - bool selected = false; - - Element(char const *label) : label(label) { } - }; - - Label _hovered() const - { - for (Element const *e = _elements.first(); e; e = e->next()) - if (e->hovered) - return e->label; - - return Label(""); - } - - List<Element> _elements; - - void _generate_dialog_elements(Xml_generator &xml) - { - for (Element const *e = _elements.first(); e; e = e->next()) { - - xml.node("button", [&] () { - xml.attribute("name", e->label.string()); - - if ((e->hovered && !_click_in_progress) - || (e->hovered && e->touched)) - xml.attribute("hovered", "yes"); - - if (e->selected || e->touched) - xml.attribute("selected", "yes"); - - xml.node("label", [&] () { - xml.attribute("text", e->label.string()); - }); - }); - } - } - - void _touch(Label const &label) - { - for (Element *e = _elements.first(); e; e = e->next()) - e->touched = (e->label == label); - } - - void _reset_hover() - { - for (Element *e = _elements.first(); e; e = e->next()) - e->hovered = false; - } - - Element _hide_button { "Hide" }; - Element _kill_button { "Kill" }; - - Fading_dialog _dialog; - - bool _open = false; - - unsigned _key_cnt = 0; - Label _clicked; - bool _click_in_progress = false; - - Label _subsystem; - - Response_handler &_response_handler; - - public: - - Context_dialog(Env &env, - Report_rom_slave &report_rom_slave, - Response_handler &response_handler) - : - _dialog(env, report_rom_slave, - "context_dialog", "context_hover", - *this, *this, *this, *this, - Fading_dialog::Position(364, 64)), - _response_handler(response_handler) - { - _elements.insert(&_hide_button); - _elements.insert(&_kill_button); - - _dialog.update(); - } - - /** - * Dialog_generator interface - */ - void generate_dialog(Xml_generator &xml) override - { - xml.node("frame", [&] () { - xml.node("vbox", [&] () { - _generate_dialog_elements(xml); - }); - }); - } - - /** - * Hover_handler interface - */ - void hover_changed(Xml_node hover) override - { - Label const old_hovered = _hovered(); - - _reset_hover(); - - try { - Xml_node button = hover.sub_node("dialog") - .sub_node("frame") - .sub_node("vbox") - .sub_node("button"); - - for (Element *e = _elements.first(); e; e = e->next()) { - - Label const label = button.attribute_value("name", Label("")); - - if (e->label == label) - e->hovered = true; - } - } catch (Xml_node::Nonexistent_sub_node) { } - - Label const new_hovered = _hovered(); - - if (old_hovered != new_hovered) - dialog_changed(); - } - - /** - * Input_event_handler interface - */ - bool handle_input_event(Input::Event const &ev) override - { - if (ev.absolute_motion()) { - - /* - * Re-enable the visibility of the menu if we detect motion - * events over the menu. This way, it reappears in situations - * where the pointer temporarily leaves the view and returns. - */ - if (_open) - visible(true); - - return true; - } - - if (ev.hover_leave()) { - visible(false); - return true; - } - - if (ev.press()) _key_cnt++; - if (ev.release()) _key_cnt--; - - if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) { - - Label const hovered = _hovered(); - - _click_in_progress = true; - _clicked = hovered; - _touch(hovered); - dialog_changed(); - } - - if (ev.release() && _click_in_progress && _key_cnt == 0) { - - Label const hovered = _hovered(); - - if (_clicked == hovered) { - - if (_kill_button.hovered) - _response_handler.handle_context_kill(); - - if (_hide_button.hovered) - _response_handler.handle_context_hide(); - } else { - _touch(""); - } - - _clicked = Label(""); - _click_in_progress = false; - dialog_changed(); - } - - return false; - } - - void visible(bool visible) - { - if (visible == _dialog.visible()) - return; - - /* reset touch state when (re-)opening the context dialog */ - if (visible) { - _open = true; - _touch(""); - _reset_hover(); - dialog_changed(); - _dialog.update(); - } - - _dialog.visible(visible); - } - - void close() - { - _open = false; - visible(false); - } - - void position(Fading_dialog::Position position) - { - _dialog.position(position); - } -}; - -#endif /* _CONTEXT_DIALOG_H_ */ diff --git a/repos/gems/src/app/launcher/dialog_nitpicker.h b/repos/gems/src/app/launcher/dialog_nitpicker.h deleted file mode 100644 index b89d0b5c5..000000000 --- a/repos/gems/src/app/launcher/dialog_nitpicker.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * \brief Local nitpicker service provided to dialog slaves - * \author Norman Feske - * \date 2014-10-01 - * - * This implementation of the nitpicker interface intercepts the input events - * of a dialog slave to let the launcher respond to events (like mouse clicks) - * directly. - */ - -/* - * Copyright (C) 2014-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 _DIALOG_NITPICKER_H_ -#define _DIALOG_NITPICKER_H_ - -/* Genode includes */ -#include <util/string.h> -#include <base/entrypoint.h> -#include <base/attached_dataspace.h> -#include <nitpicker_session/nitpicker_session.h> -#include <input_session/client.h> -#include <input/event.h> -#include <input/component.h> - -/* gems includes */ -#include <gems/wrapped_nitpicker_session.h> - -/* local includes */ -#include <types.h> - -namespace Launcher { - - struct Dialog_nitpicker_session; - struct Dialog_nitpicker_service; -} - - -struct Launcher::Dialog_nitpicker_session : Wrapped_nitpicker_session -{ - struct Input_event_handler - { - /** - * Handle input event - * - * \return true if the event should be propagated to the wrapped - * nitpicker session - */ - virtual bool handle_input_event(Input::Event const &ev) = 0; - }; - - Env &_env; - - Input_event_handler &_input_event_handler; - - Rpc_entrypoint &_session_ep; - - Nitpicker::Session &_nitpicker_session; - - Input::Session_client _nitpicker_input { _env.rm(), _nitpicker_session.input_session() }; - - Attached_dataspace _nitpicker_input_ds { _env.rm(), _nitpicker_input.dataspace() }; - - Signal_handler<Dialog_nitpicker_session> _input_handler; - - Input::Session_component _input_session { _env, _env.ram() }; - - /** - * Constructor - * - * \param input_sigh_ep entrypoint where the input signal handler is - * installed ('env.ep') - * \param service_ep entrypoint providing the nitpicker session - * (slave-specific ep) - */ - Dialog_nitpicker_session(Env &env, Nitpicker::Session &nitpicker_session, - Entrypoint &input_sigh_ep, - Rpc_entrypoint &session_ep, - Input_event_handler &input_event_handler) - : - Wrapped_nitpicker_session(nitpicker_session), - _env(env), - _input_event_handler(input_event_handler), - _session_ep(session_ep), - _nitpicker_session(nitpicker_session), - _input_handler(input_sigh_ep, *this, &Dialog_nitpicker_session::_handle_input) - { - _session_ep.manage(this); - _session_ep.manage(&_input_session); - _nitpicker_input.sigh(_input_handler); - - _input_session.event_queue().enabled(true); - } - - ~Dialog_nitpicker_session() - { - _session_ep.dissolve(&_input_session); - _session_ep.dissolve(this); - } - - void _handle_input() - { - Input::Event const * const events = - _nitpicker_input_ds.local_addr<Input::Event>(); - - while (_nitpicker_input.pending()) { - - size_t const num_events = _nitpicker_input.flush(); - for (size_t i = 0; i < num_events; i++) { - - Input::Event const &ev = events[i]; - - if (_input_event_handler.handle_input_event(ev)) - _input_session.submit(ev); - } - } - } - - - /********************************* - ** Nitpicker session interface ** - *********************************/ - - Input::Session_capability input_session() override - { - return _input_session.cap(); - } -}; - -#endif /* _DIALOG_NITPICKER_H_ */ diff --git a/repos/gems/src/app/launcher/fading_dialog.h b/repos/gems/src/app/launcher/fading_dialog.h deleted file mode 100644 index a2cad987d..000000000 --- a/repos/gems/src/app/launcher/fading_dialog.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * \brief Dialog - * \author Norman Feske - * \date 2014-10-02 - */ - -/* - * Copyright (C) 2014-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 _FADING_DIALOG_H_ -#define _FADING_DIALOG_H_ - -/* gems includes */ -#include <gems/report_rom_slave.h> -#include <gems/local_reporter.h> - -/* local includes */ -#include <nit_fader_slave.h> -#include <menu_view_slave.h> -#include <dialog_nitpicker.h> -#include <types.h> - -namespace Launcher -{ - struct Dialog_generator { virtual void generate_dialog(Xml_generator &) = 0; }; - - struct Hover_handler { virtual void hover_changed(Xml_node hover) = 0; }; - - typedef Dialog_nitpicker_session::Input_event_handler Input_event_handler; - - class Fading_dialog; - - class Dialog_model - { - private: - - bool _up_to_date = true; - - friend class Fading_dialog; - - public: - - void dialog_changed() { _up_to_date = false; } - }; -} - - - -class Launcher::Fading_dialog : private Input_event_handler -{ - private: - - Region_map &_rm; - - Slave::Connection<Rom_connection> _dialog_rom; - - /* dialog reported locally */ - Slave::Connection<Report::Connection> _dialog_report; - - Slave::Connection<Rom_connection> _hover_rom; - - Constructible<Attached_dataspace> _hover_ds; - - /* hovered element reported by menu view */ - Slave::Connection<Report::Connection> _hover_report; - - Local_reporter _dialog_reporter; - - Input_event_handler &_dialog_input_event_handler; - - Hover_handler &_hover_handler; - - Dialog_generator &_dialog_generator; - - Dialog_model &_dialog_model; - - void _update_dialog() - { - bool const dialog_needs_update = !_dialog_model._up_to_date; - - _dialog_model._up_to_date = false; - - if (dialog_needs_update) { - Local_reporter::Xml_generator xml(_dialog_reporter, [&] () - { - _dialog_generator.generate_dialog(xml); - }); - } - } - - /** - * Input_event_handler interface - */ - bool handle_input_event(Input::Event const &ev) override - { - bool const forward_event = _dialog_input_event_handler.handle_input_event(ev); - _update_dialog(); - return forward_event; - } - - void _handle_hover_update() - { - try { - if (!_hover_ds.constructed() || _hover_rom.update() == false) { - if (_hover_ds.constructed()) - _hover_ds->invalidate(); - _hover_ds.construct(_rm, _hover_rom.dataspace()); - } - - Xml_node hover(_hover_ds->local_addr<char>()); - - _hover_handler.hover_changed(hover); - - bool const dialog_needs_update = !_dialog_model._up_to_date; - - _dialog_model._up_to_date = true; - - if (dialog_needs_update) { - Local_reporter::Xml_generator xml(_dialog_reporter, [&] () - { - _dialog_generator.generate_dialog(xml); - }); - } - - } catch (...) { - Genode::warning("no menu hover model available"); - } - } - - Signal_handler<Fading_dialog> _hover_update_handler; - - private: - - /* - * Entrypoint for the fader slave - * - * This entrypoint is used for handling the parent interface for the - * fader slave and for providing the wrapped nitpicker service to the - * slave. The latter cannot be provided by the main entrypoint because - * during the construction of the 'nit_fader_slave' (executed in the - * context of the main entrypoint), the slave tries to create a - * nitpicker session (to be answered with the wrapped session). - */ - size_t const _fader_slave_ep_stack_size = 4*1024*sizeof(addr_t); - Rpc_entrypoint _fader_slave_ep; - - /* - * Provide wrapped nitpicker connection as a service handed out to - * the menu-view slave - */ - typedef Genode::Local_service<Dialog_nitpicker_session> Nitpicker_service; - typedef Nitpicker_service::Single_session_factory Nitpicker_factory; - - Nitpicker::Connection _nitpicker_connection; - Dialog_nitpicker_session _nitpicker_session; - Nitpicker_factory _nitpicker_factory { _nitpicker_session }; - Nitpicker_service _nitpicker_service { _nitpicker_factory }; - - Nit_fader_slave _nit_fader_slave; - Slave::Connection<Nitpicker::Connection> _nit_fader_connection; - Menu_view_slave _menu_view_slave; - - bool _visible = false; - - public: - - typedef Menu_view_slave::Position Position; - - Fading_dialog(Env &env, - Report_rom_slave &report_rom_slave, - char const *dialog_name, - char const *hover_name, - Input_event_handler &input_event_handler, - Hover_handler &hover_handler, - Dialog_generator &dialog_generator, - Dialog_model &dialog_model, - Position initial_position) - : - _rm(env.rm()), - _dialog_rom(report_rom_slave.policy(), Slave::Args("label=", dialog_name)), - _dialog_report(report_rom_slave.policy(), - Slave::Args("label=", dialog_name, ", buffer_size=4096")), - _hover_rom(report_rom_slave.policy(), Slave::Args("label=", hover_name)), - _hover_report(report_rom_slave.policy(), - Slave::Args("label=", hover_name, ", buffer_size=4096")), - _dialog_reporter(env.rm(), "dialog", _dialog_report.rpc_cap()), - _dialog_input_event_handler(input_event_handler), - _hover_handler(hover_handler), - _dialog_generator(dialog_generator), - _dialog_model(dialog_model), - _hover_update_handler(env.ep(), *this, &Fading_dialog::_handle_hover_update), - _fader_slave_ep(&env.pd(), _fader_slave_ep_stack_size, "nit_fader"), - _nitpicker_connection(env, "menu"), - _nitpicker_session(env, _nitpicker_connection, env.ep(), _fader_slave_ep, *this), - _nit_fader_slave(env, _fader_slave_ep, _nitpicker_service), - _nit_fader_connection(env.rm(), _nit_fader_slave.policy(), Slave::Args("label=menu")), - _menu_view_slave(env, _nit_fader_connection.rpc_cap(), - _dialog_rom.rpc_cap(), _hover_report.rpc_cap(), - initial_position) - { - Rom_session_client(_hover_rom).sigh(_hover_update_handler); - } - - void update() - { - Local_reporter::Xml_generator xml(_dialog_reporter, [&] () - { - _dialog_generator.generate_dialog(xml); - }); - } - - void visible(bool visible) - { - _nit_fader_slave.visible(visible); - _visible = visible; - } - - bool visible() const { return _visible; } - - void position(Position position) { _menu_view_slave.position(position); } -}; - -#endif /* _FADING_DIALOG_H_ */ diff --git a/repos/gems/src/app/launcher/main.cc b/repos/gems/src/app/launcher/main.cc deleted file mode 100644 index c5bc2b01d..000000000 --- a/repos/gems/src/app/launcher/main.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* - * \brief Launcher - * \author Norman Feske - * \date 2014-09-30 - */ - -/* - * Copyright (C) 2014-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. - */ - -/* Genode includes */ -#include <base/component.h> -#include <decorator/xml_utils.h> -#include <util/reconstructible.h> -#include <base/attached_rom_dataspace.h> -#include <nitpicker_session/connection.h> - -/* local includes */ -#include <panel_dialog.h> - -namespace Launcher { - - using namespace Genode; - struct Main; -} - - -struct Launcher::Main -{ - Env &_env; - - char const *_report_rom_config = - "<config>" - " <policy label=\"menu_dialog\" report=\"menu_dialog\"/>" - " <policy label=\"menu_hover\" report=\"menu_hover\"/>" - " <policy label=\"panel_dialog\" report=\"panel_dialog\"/>" - " <policy label=\"panel_hover\" report=\"panel_hover\"/>" - " <policy label=\"context_dialog\" report=\"context_dialog\"/>" - " <policy label=\"context_hover\" report=\"context_hover\"/>" - "</config>"; - - Report_rom_slave _report_rom_slave { _env, _report_rom_config }; - - /** - * Nitpicker session used to perform session-control operations on the - * subsystem's nitpicker sessions and to receive global keyboard - * shortcuts. - */ - Nitpicker::Connection _nitpicker { _env }; - - Signal_handler<Main> _input_handler = - { _env.ep(), *this, &Main::_handle_input }; - - void _handle_input(); - - unsigned _key_cnt = 0; - - Signal_handler<Main> _exited_child_handler = - { _env.ep(), *this, &Main::_handle_exited_child }; - - Attached_rom_dataspace _config { _env, "config" }; - - static size_t _ram_preservation(Xml_node config) - { - char const * const node_name = "preservation"; - - if (config.has_sub_node(node_name)) { - - Xml_node const node = config.sub_node(node_name); - if (node.attribute_value("name", Genode::String<16>()) == "RAM") - return node.attribute_value("quantum", Genode::Number_of_bytes()); - } - - return 0; - } - - Subsystem_manager _subsystem_manager { _env, - _ram_preservation(_config.xml()), - _exited_child_handler }; - - Heap _heap { _env.ram(), _env.rm() }; - - Panel_dialog _panel_dialog { _env, _heap, _report_rom_slave, - _subsystem_manager, _nitpicker }; - - void _handle_config(); - - void _handle_exited_child() - { - auto kill_child_fn = [&] (Label const &label) { _panel_dialog.kill(label); }; - - _subsystem_manager.for_each_exited_child(kill_child_fn); - } - - Label _focus_prefix; - - Genode::Attached_rom_dataspace _focus_rom { _env, "focus" }; - - void _handle_focus_update(); - - Signal_handler<Main> _focus_update_handler = - { _env.ep(), *this, &Main::_handle_focus_update }; - - /** - * Constructor - */ - Main(Env &env) : _env(env) - { - _nitpicker.input()->sigh(_input_handler); - _focus_rom.sigh(_focus_update_handler); - - _handle_config(); - - _panel_dialog.visible(true); - } -}; - - -void Launcher::Main::_handle_config() -{ - _config.update(); - - _focus_prefix = _config.xml().attribute_value("focus_prefix", Label()); - - try { - _panel_dialog.update(_config.xml()); } - catch (Allocator::Out_of_memory) { - error("out of memory while applying configuration"); } -} - - -void Launcher::Main::_handle_input() -{ - _nitpicker.input()->for_each_event([&] (Input::Event const &e) { - if (e.press()) _key_cnt++; - if (e.release()) _key_cnt--; - - /* - * The _key_cnt can become 2 only when the global key (as configured - * in the nitpicker config) is pressed together with another key. - * Hence, the following condition triggers on key combinations with - * the global modifier key, whatever the global modifier key is. - */ - if (e.key_press(Input::KEY_TAB) && _key_cnt == 2) - _panel_dialog.focus_next(); - }); -} - - -void Launcher::Main::_handle_focus_update() -{ - try { - _focus_rom.update(); - - Xml_node focus_node(_focus_rom.local_addr<char>()); - - /* - * Propagate focus information to panel such that the focused - * subsystem gets highlighted. - */ - Label label = focus_node.attribute_value("label", Label()); - - size_t const prefix_len = Genode::strlen(_focus_prefix.string()); - if (!Genode::strcmp(_focus_prefix.string(), label.string(), prefix_len)) { - label = Label(label.string() + prefix_len); - - } else { - - /* - * A foreign nitpicker client not started by ourself has the focus. - */ - label = Label(); - } - - _panel_dialog.focus_changed(label); - - } catch (...) { - Genode::warning("no focus model available"); - } -} - - -void Component::construct(Genode::Env &env) { static Launcher::Main main(env); } diff --git a/repos/gems/src/app/launcher/menu_dialog.h b/repos/gems/src/app/launcher/menu_dialog.h deleted file mode 100644 index 0a0290cac..000000000 --- a/repos/gems/src/app/launcher/menu_dialog.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * \brief Menu dialog - * \author Norman Feske - * \date 2014-10-04 - */ - -/* - * Copyright (C) 2014-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 _MENU_DIALOG_H_ -#define _MENU_DIALOG_H_ - -/* Genode includes */ -#include <timer_session/connection.h> - -/* local includes */ -#include <fading_dialog.h> -#include <subsystem_manager.h> -#include <context_dialog.h> - -namespace Launcher { struct Menu_dialog; } - - -class Launcher::Menu_dialog : Input_event_handler, Dialog_generator, - Hover_handler, Dialog_model -{ - public: - - struct Response_handler - { - virtual void handle_selection(Label const &) = 0; - virtual void handle_menu_leave() = 0; - virtual void handle_menu_motion() = 0; - }; - - private: - - Allocator &_alloc; - - Response_handler &_response_handler; - - typedef String<128> Title; - - struct Element : List<Element>::Element - { - Label label; - Title title; - - bool hovered = false; - bool touched = false; - bool running = false; - - Element(Xml_node node) - : - label(node.attribute_value("name", Label(""))), - title(node.attribute_value("title", Title(label.string()))) - { } - }; - - List<Element> _elements; - - void _generate_dialog_elements(Xml_generator &xml) - { - for (Element const *e = _elements.first(); e; e = e->next()) { - - xml.node("button", [&] () { - xml.attribute("name", e->label.string()); - - if ((e->hovered) - || (e->hovered && e->touched)) - xml.attribute("hovered", "yes"); - - if (e->running || e->touched) - xml.attribute("selected", "yes"); - - xml.node("label", [&] () { - xml.attribute("text", e->title.string()); - }); - }); - } - } - - Fading_dialog::Position _position { 0 - 4, 28 - 4 }; - - Fading_dialog _dialog; - - Rect _hovered_rect; - - bool _open = false; - - unsigned _key_cnt = 0; - - Label _hovered() const - { - for (Element const *e = _elements.first(); e; e = e->next()) - if (e->hovered) - return e->label; - - return Label(""); - } - - public: - - Menu_dialog(Env &env, - Allocator &alloc, - Report_rom_slave &report_rom_slave, - Response_handler &response_handler) - : - _alloc(alloc), _response_handler(response_handler), - _dialog(env, report_rom_slave, "menu_dialog", "menu_hover", - *this, *this, *this, *this, _position) - { } - - /** - * Dialog_generator interface - */ - void generate_dialog(Xml_generator &xml) override - { - xml.node("frame", [&] () { - xml.node("vbox", [&] () { - _generate_dialog_elements(xml); - }); - }); - } - - Rect _hovered_button_rect(Xml_node hover) const - { - Point p(0, 0); - - for (;; hover = hover.sub_node()) { - - p = p + Point(point_attribute(hover)); - - if (hover.has_type("button")) - return Rect(p, area_attribute(hover)); - - if (!hover.num_sub_nodes()) - break; - } - - return Rect(); - } - - /** - * Hover_handler interface - */ - void hover_changed(Xml_node hover) override - { - Label const old_hovered = _hovered(); - - for (Element *e = _elements.first(); e; e = e->next()) - e->hovered = false; - - try { - Xml_node button = hover.sub_node("dialog") - .sub_node("frame") - .sub_node("vbox") - .sub_node("button"); - - for (Element *e = _elements.first(); e; e = e->next()) { - - Label const label = button.attribute_value("name", Label("")); - - if (e->label == label) { - e->hovered = true; - - _hovered_rect = _hovered_button_rect(hover); - } - } - } catch (Xml_node::Nonexistent_sub_node) { } - - Label const new_hovered = _hovered(); - - if (old_hovered != new_hovered) - dialog_changed(); - } - - /** - * Input_event_handler interface - */ - bool handle_input_event(Input::Event const &ev) override - { - if (ev.hover_leave()) { - _response_handler.handle_menu_leave(); - return false; - } - - if (ev.absolute_motion()) { - - _response_handler.handle_menu_motion(); - - /* - * Re-enable the visibility of the menu if we detect motion - * events over the menu. This way, it reappears in situations - * where the pointer temporarily leaves the view and returns. - */ - if (_open) - visible(true); - - return true; - } - - if (ev.press()) _key_cnt++; - if (ev.release()) _key_cnt--; - - if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) - _response_handler.handle_selection(_hovered()); - - return false; - } - - void visible(bool visible) - { - if (visible == _dialog.visible()) - return; - - _dialog.visible(visible); - - if (visible) - _open = true; - } - - void close() - { - _open = false; - visible(false); - } - - void running(Label const &label, bool running) - { - for (Element *e = _elements.first(); e; e = e->next()) - if (e->label == label) - e->running = running; - - _dialog.update(); - } - - void update(Xml_node subsystems) - { - if (_elements.first()) { - Genode::error("subsequent updates are not supported"); - return; - } - - Element *last = nullptr; - - subsystems.for_each_sub_node("subsystem", - [&] (Xml_node subsystem) - { - Element * const e = new (_alloc) Element(subsystem); - - _elements.insert(e, last); - last = e; - }); - - _dialog.update(); - } -}; - -#endif /* _MENU_DIALOG_H_ */ diff --git a/repos/gems/src/app/launcher/menu_view_slave.h b/repos/gems/src/app/launcher/menu_view_slave.h deleted file mode 100644 index e8ef3cdf3..000000000 --- a/repos/gems/src/app/launcher/menu_view_slave.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * \brief Slave used for presenting the menu - * \author Norman Feske - * \date 2014-09-30 - */ - -/* - * Copyright (C) 2014-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 _MENU_VIEW_SLAVE_H_ -#define _MENU_VIEW_SLAVE_H_ - -/* Genode includes */ -#include <os/static_parent_services.h> -#include <os/slave.h> -#include <nitpicker_session/nitpicker_session.h> -#include <file_system_session/file_system_session.h> - -/* gems includes */ -#include <os/single_session_service.h> - -/* local includes */ -#include <types.h> - -namespace Launcher { class Menu_view_slave; } - - -class Launcher::Menu_view_slave -{ - public: - - typedef Surface_base::Point Position; - - private: - - struct Policy_base - { - Genode::Static_parent_services<Genode::Cpu_session, - Genode::Pd_session, - Genode::Rom_session, - Genode::Log_session, - File_system::Session, - Timer::Session> - _parent_services; - - Policy_base(Env &env) : _parent_services(env) { } - }; - - class Policy : Policy_base, public Genode::Slave::Policy - { - private: - - Genode::Single_session_service<Nitpicker::Session> _nitpicker; - Genode::Single_session_service<Genode::Rom_session> _dialog_rom; - Genode::Single_session_service<Report::Session> _hover_report; - - Position _position; - - private: - - void _configure(Position pos) - { - char config[1024]; - - snprintf(config, sizeof(config), - "<config xpos=\"%d\" ypos=\"%d\">\n" - " <report hover=\"yes\"/>\n" - " <libc stderr=\"/dev/log\"/>\n" - " <vfs>\n" - " <tar name=\"menu_view_styles.tar\" />\n" - " <dir name=\"fonts\"> <fs label=\"fonts\"/> </dir>\n" - " </vfs>\n" - "</config>", - pos.x(), pos.y()); - - configure(config); - } - - static Name _name() { return "menu_view"; } - static Genode::Ram_quota _quota() { return { 6*1024*1024 }; } - static Genode::Cap_quota _caps() { return { 100 }; } - - Service &_matching_service(Genode::Service::Name const &service, - Genode::Session_label const &label) - { - if (service == "Nitpicker") - return _nitpicker.service(); - - if ((service == "ROM") && (label == "menu_view -> dialog")) - return _dialog_rom.service(); - - if ((service == "Report") && (label == "menu_view -> hover")) - return _hover_report.service(); - - throw Genode::Service_denied(); - } - - public: - - Policy(Genode::Env &env, - Genode::Rpc_entrypoint &ep, - Capability<Nitpicker::Session> nitpicker_session, - Capability<Rom_session> dialog_rom_session, - Capability<Report::Session> hover_report_session, - Position position) - : - Policy_base(env), - Genode::Slave::Policy(env, _name(), _name(), - Policy_base::_parent_services, - ep, _caps(), _quota()), - _nitpicker(env.rm(), nitpicker_session), - _dialog_rom(dialog_rom_session), - _hover_report(hover_report_session), - _position(position) - { - _configure(position); - } - - void position(Position pos) { _configure(pos); } - - Route resolve_session_request(Genode::Service::Name const &name, - Genode::Session_label const &label) override - { - try { - return Route { .service = _matching_service(name, label), - .label = label, - .diag = Genode::Session::Diag() }; - } - catch (Genode::Service_denied) { } - - return Genode::Slave::Policy::resolve_session_request(name, label); - } - }; - - Genode::size_t const _ep_stack_size = 4*1024*sizeof(Genode::addr_t); - Genode::Rpc_entrypoint _ep; - Policy _policy; - Genode::Child _child; - - public: - - /** - * Constructor - */ - Menu_view_slave(Genode::Env &env, - Capability<Nitpicker::Session> nitpicker_session, - Capability<Rom_session> dialog_rom_session, - Capability<Report::Session> hover_report_session, - Position initial_position) - : - _ep(&env.pd(), _ep_stack_size, "nit_fader"), - _policy(env, _ep, - nitpicker_session, dialog_rom_session, - hover_report_session, initial_position), - _child(env.rm(), _ep, _policy) - { } - - void position(Position position) { _policy.position(position); } -}; - -#endif /* _NIT_FADER_SLAVE_H_ */ diff --git a/repos/gems/src/app/launcher/nit_fader_slave.h b/repos/gems/src/app/launcher/nit_fader_slave.h deleted file mode 100644 index e551927fc..000000000 --- a/repos/gems/src/app/launcher/nit_fader_slave.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * \brief Slave used for toggling the visibility of a nitpicker session - * \author Norman Feske - * \date 2014-09-30 - */ - -/* - * Copyright (C) 2014-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 _NIT_FADER_SLAVE_H_ -#define _NIT_FADER_SLAVE_H_ - -/* Genode includes */ -#include <os/static_parent_services.h> -#include <os/slave.h> -#include <nitpicker_session/nitpicker_session.h> - -/* local includes */ -#include <types.h> - -namespace Launcher { class Nit_fader_slave; } - - -class Launcher::Nit_fader_slave -{ - private: - - struct Policy_base - { - Genode::Static_parent_services<Genode::Cpu_session, - Genode::Pd_session, - Genode::Rom_session, - Genode::Log_session, - Timer::Session> - _parent_services; - - Policy_base(Env &env) : _parent_services(env) { } - }; - - class Policy : Policy_base, public Slave::Policy - { - private: - - Genode::Service &_nitpicker_service; - - protected: - - static Name _name() { return "nit_fader"; } - static Genode::Ram_quota _quota() { return { 2*1024*1024 }; } - static Genode::Cap_quota _caps() { return { 50 }; } - - public: - - Policy(Env &env, - Rpc_entrypoint &ep, - Genode::Service &nitpicker_service) - : - Policy_base(env), - Genode::Slave::Policy(env, _name(), _name(), - Policy_base::_parent_services, - ep, _caps(), _quota()), - _nitpicker_service(nitpicker_service) - { - visible(false); - } - - void visible(bool visible) - { - char config[256]; - snprintf(config, sizeof(config), - "<config alpha=\"%d\" />", visible ? 255 : 0); - configure(config, strlen(config) + 1); - } - - Route resolve_session_request(Genode::Service::Name const &service, - Genode::Session_label const &label) override - { - if (service == Nitpicker::Session::service_name()) - return Route { .service = _nitpicker_service, - .label = label, - .diag = Session::Diag() }; - - return Genode::Slave::Policy::resolve_session_request(service, label); - } - }; - - Policy _policy; - Child _child; - - public: - - /** - * Constructor - * - * \param ep entrypoint used for nitpicker child thread - */ - Nit_fader_slave(Env &env, - Rpc_entrypoint &ep, - Genode::Service &nitpicker_service) - : - _policy(env, ep, nitpicker_service), - _child(env.rm(), ep, _policy) - { - visible(false); - } - - Genode::Slave::Policy &policy() { return _policy; } - - void visible(bool visible) - { - _policy.visible(visible); - } -}; - -#endif /* _NIT_FADER_SLAVE_H_ */ diff --git a/repos/gems/src/app/launcher/panel_dialog.h b/repos/gems/src/app/launcher/panel_dialog.h deleted file mode 100644 index 5ee6a684b..000000000 --- a/repos/gems/src/app/launcher/panel_dialog.h +++ /dev/null @@ -1,559 +0,0 @@ -/* - * \brief Panel dialog - * \author Norman Feske - * \date 2015-10-07 - */ - -/* - * Copyright (C) 2015-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 _PANEL_DIALOG_H_ -#define _PANEL_DIALOG_H_ - -/* Genode includes */ -#include <timer_session/connection.h> -#include <os/buffered_xml.h> - -/* local includes */ -#include <fading_dialog.h> -#include <subsystem_manager.h> -#include <context_dialog.h> -#include <menu_dialog.h> - -namespace Launcher { struct Panel_dialog; } - - -class Launcher::Panel_dialog : Input_event_handler, Dialog_generator, - Hover_handler, Dialog_model, - Context_dialog::Response_handler, - Menu_dialog::Response_handler -{ - private: - - typedef String<128> Title; - - struct Element : List<Element>::Element - { - Label const label; - Title const title; - - bool hovered = false; - bool touched = false; - bool selected = false; - - Element(Label label, Title title) : label(label), title(title) - { } - }; - - Genode::Allocator &_alloc; - - Constructible<Buffered_xml> _config; - - List<Element> _elements; - - Label _focus; - - static char const *_menu_button_label() { return "_menu"; } - - Element _menu_button { _menu_button_label(), "Menu" }; - - bool _focused(Element const &e) - { - size_t const label_len = strlen(e.label.string()); - - if (strcmp(e.label.string(), _focus.string(), label_len)) - return false; - - /* - * Even when the strcmp suceeded, the element's label might - * not match the focus. E.g., if two subsystems "scout" and - * "scoutx" are present the focus of "scoutx" would match both - * subsystem labels because the strcmp is limited to the length - * of the subsystem label. Hence, we need to make sure that - * the focus matched at a separator boundary. - */ - char const *char_after_label = _focus.string() + label_len; - - if (*char_after_label == 0 || !strcmp(" -> ", char_after_label, 4)) - return true; - - return false; - } - - void _generate_dialog_element(Xml_generator &xml, Element const &e) - { - xml.node("button", [&] () { - xml.attribute("name", e.label.string()); - - if (&e != &_menu_button) - xml.attribute("style", "subdued"); - - if ((e.hovered && !_click_in_progress) - || (e.hovered && e.touched)) - xml.attribute("hovered", "yes"); - - if (e.selected || e.touched || _focused(e)) - xml.attribute("selected", "yes"); - - xml.node("label", [&] () { - xml.attribute("text", e.title.string()); - }); - }); - } - - class Lookup_failed { }; - - Element const &_lookup_const(Label const &label) const - { - for (Element const *e = _elements.first(); e; e = e->next()) - if (e->label == label) - return *e; - - throw Lookup_failed(); - } - - Element &_lookup(Label const &label) - { - for (Element *e = _elements.first(); e; e = e->next()) - if (e->label == label) - return *e; - - throw Lookup_failed(); - } - - Fading_dialog::Position _position { 0, 0 }; - - Timer::Connection _timer; - Subsystem_manager &_subsystem_manager; - Nitpicker::Session &_nitpicker; - Fading_dialog _dialog; - - Rect _hovered_rect; - - unsigned _key_cnt = 0; - Element *_clicked = nullptr; - bool _click_in_progress = false; - - Signal_handler<Panel_dialog> _timer_handler; - - Label _context_subsystem; - Context_dialog _context_dialog; - - Menu_dialog _menu_dialog; - - Element *_hovered() - { - for (Element *e = _elements.first(); e; e = e->next()) - if (e->hovered) - return e; - - return nullptr; - } - - /** - * Lookup subsystem in config - */ - static Xml_node _subsystem(Xml_node config, char const *name) - { - Xml_node node = config.sub_node("subsystem"); - for (;; node = node.next("subsystem")) { - if (node.attribute("name").has_value(name)) - return node; - } - } - - void _start(Label const &label) - { - if (!_config.constructed()) { - warning("attempt to start subsystem without prior configuration"); - return; - } - - try { - Xml_node subsystem = _subsystem(_config->xml(), label.string()); - _subsystem_manager.start(subsystem); - - Title const title = subsystem.attribute_value("title", Title()); - - Element *e = new (_alloc) Element(label, title); - - /* find last element of the list */ - Element *at = _elements.first(); - for (; at && at->next(); at = at->next()); - - _elements.insert(e, at); - - dialog_changed(); - - } catch (Xml_node::Nonexistent_sub_node) { - Genode::error("no subsystem config found for \"", label, "\""); - } catch (Subsystem_manager::Invalid_config) { - Genode::error("invalid subsystem configuration for \"", label, "\""); - } - } - - void _kill(Label const &label) - { - Element &e = _lookup(label); - - _subsystem_manager.kill(label.string()); - - _elements.remove(&e); - - if (_clicked == &e) - _clicked = nullptr; - - Genode::destroy(_alloc, &e); - - dialog_changed(); - _dialog.update(); - - _context_dialog.close(); - - _menu_dialog.running(label, false); - } - - void _hide(Label const &label) - { - _nitpicker.session_control(selector(label.string()), - Nitpicker::Session::SESSION_CONTROL_HIDE); - - _context_dialog.close(); - } - - void _open_context_dialog(Label const &label) - { - /* reset touch state in each element */ - for (Element *e = _elements.first(); e; e = e->next()) - e->touched = false; - - Fading_dialog::Position position(_hovered_rect.p1().x(), - _hovered_rect.p2().y()); - - _context_subsystem = label; - _context_dialog.position(_position + position); - _context_dialog.visible(true); - } - - void _handle_timer() - { - if (_click_in_progress && _clicked && _hovered() == _clicked) { - _open_context_dialog(_clicked->label); - } - _click_in_progress = false; - } - - void _to_front(Label const &label) - { - _nitpicker.session_control(selector(label.string()), - Nitpicker::Session::SESSION_CONTROL_TO_FRONT); - _nitpicker.session_control(selector(label.string()), - Nitpicker::Session::SESSION_CONTROL_SHOW); - } - - public: - - Panel_dialog(Env &env, - Genode::Allocator &alloc, - Report_rom_slave &report_rom_slave, - Subsystem_manager &subsystem_manager, - Nitpicker::Session &nitpicker) - : - _alloc(alloc), - _timer(env), - _subsystem_manager(subsystem_manager), - _nitpicker(nitpicker), - _dialog(env, report_rom_slave, "panel_dialog", "panel_hover", - *this, *this, *this, *this, _position), - _timer_handler(env.ep(), *this, &Panel_dialog::_handle_timer), - _context_dialog(env, report_rom_slave, *this), - _menu_dialog(env, alloc, report_rom_slave, *this) - { - _elements.insert(&_menu_button); - _timer.sigh(_timer_handler); - } - - /** - * Dialog_generator interface - */ - void generate_dialog(Xml_generator &xml) override - { - xml.node("hbox", [&] () { - for (Element const *e = _elements.first(); e; e = e->next()) - _generate_dialog_element(xml, *e); - }); - } - - Rect _hovered_button_rect(Xml_node hover) const - { - Point p(0, 0); - - for (;; hover = hover.sub_node()) { - - p = p + Point(point_attribute(hover)); - - if (hover.has_type("button")) - return Rect(p, area_attribute(hover)); - - if (!hover.num_sub_nodes()) - break; - } - - return Rect(); - } - - /** - * Hover_handler interface - */ - void hover_changed(Xml_node hover) override - { - Element *old_hovered = _hovered(); - - for (Element *e = _elements.first(); e; e = e->next()) - e->hovered = false; - - try { - Xml_node button = hover.sub_node("dialog") - .sub_node("hbox") - .sub_node("button"); - - for (Element *e = _elements.first(); e; e = e->next()) { - - Label const label = button.attribute_value("name", Label("")); - - if (e->label == label) { - e->hovered = true; - - _hovered_rect = _hovered_button_rect(hover); - } - } - } catch (Xml_node::Nonexistent_sub_node) { } - - Element *new_hovered = _hovered(); - - if (old_hovered != new_hovered) - dialog_changed(); - } - - /** - * Input_event_handler interface - */ - bool handle_input_event(Input::Event const &ev) override - { - if (ev.hover_leave()) { - - /* - * Let menu dialog disappear when the panel is unhovered. One - * would expect that the user had no chance to select an item - * from the menu because when entering the menu, we will no - * longer hover the panel. However, the menu disappears slowly. - * If the pointer moves over to the menu in a reasonable time, - * the visiblity of the menu is re-enabled. - */ - _menu_dialog.visible(false); - _context_dialog.visible(false); - _menu_button.selected = false; - _dialog.update(); - return true; - } - - if (ev.absolute_motion()) - return true; - - if (ev.press()) _key_cnt++; - if (ev.release()) _key_cnt--; - - if (ev.key_press(Input::BTN_LEFT) && _key_cnt == 1) { - - _context_dialog.visible(false); - - Element *hovered = _hovered(); - - _click_in_progress = true; - _clicked = hovered; - - if (!hovered) - return false; - - hovered->touched = true; - - if (hovered == &_menu_button) { - - /* menu button presses */ - if (_menu_button.selected) - _menu_dialog.close(); - else - _menu_dialog.visible(true); - - _menu_button.selected = !_menu_button.selected; - _dialog.update(); - return false; - } - - _menu_dialog.close(); - - _to_front(hovered->label); - - /* - * Open the context dialog after the user keeps pressing the - * button for a while. - */ - enum { CONTEXT_DELAY = 500 }; - _timer.trigger_once((Genode::uint64_t)CONTEXT_DELAY*1000); - } - - /* - * Open context dialog on right click - */ - if (ev.key_press(Input::BTN_RIGHT) && _key_cnt == 1) { - - Element *hovered = _hovered(); - - if (hovered && hovered != &_menu_button) - _open_context_dialog(hovered->label); - } - - if (ev.release() && _click_in_progress && _key_cnt == 0) { - - Element *hovered = _hovered(); - - if (hovered) - hovered->touched = false; - - _clicked = nullptr; - _click_in_progress = false; - } - - return false; - } - - /** - * Context_dialog::Response_handler interface - */ - void handle_context_kill() override - { - _kill(_context_subsystem); - } - - /** - * Context_dialog::Response_handler interface - */ - void handle_context_hide() override - { - _hide(_context_subsystem); - } - - /** - * Menu_dialog::Response_handler interface - */ - void handle_menu_motion() - { - _menu_button.selected = true; - _dialog.update(); - } - - /** - * Menu_dialog::Response_handler interface - */ - void handle_menu_leave() - { - /* XXX eventually revert the state of the menu button */ - _menu_button.selected = false; - - _dialog.update(); - - _menu_dialog.visible(false); - } - - /** - * Menu_dialog::Response_handler interface - */ - void handle_selection(Label const &label) override - { - /* - * If subsystem of the specified label is already running, ignore - * the click. - */ - bool already_running = false; - for (Element *e = _elements.first(); e; e = e->next()) - if (e->label == label) - already_running = true; - - if (already_running) { - _to_front(label); - - } else { - - _start(label); - - _dialog.update(); - - /* propagate running state of subsystem to menu dialog */ - _menu_dialog.running(label, true); - } - - /* let menu disappear */ - _menu_dialog.close(); - } - - void visible(bool visible) - { - _dialog.visible(visible); - - if (!visible) - _context_dialog.visible(false); - } - - void kill(Label const &label) - { - _kill(label); - } - - /** - * \throw Allocator::Out_of_memory - */ - void update(Xml_node config) - { - _config.construct(_alloc, config); - - /* populate menu dialog with one item per subsystem */ - _menu_dialog.update(_config->xml()); - - /* evaluate configuration */ - _dialog.update(); - } - - void focus_changed(Label const &label) - { - _focus = label; - - _dialog.update(); - } - - void focus_next() - { - /* find focused element */ - Element *e = _elements.first(); - - for (; e && !_focused(*e); e = e->next()); - - /* none of our subsystems is focused, start with the first one */ - if (!e) - e = _elements.first(); - - /* - * Determine next session in the list, if we reach the end, start - * at the beginning (the element right after the menu button. - */ - Element *new_focused = e->next() ? e->next() : _menu_button.next(); - - if (new_focused) - _to_front(new_focused->label); - } -}; - -#endif /* _PANEL_DIALOG_H_ */ diff --git a/repos/gems/src/app/launcher/subsystem_manager.h b/repos/gems/src/app/launcher/subsystem_manager.h deleted file mode 100644 index 2543e2554..000000000 --- a/repos/gems/src/app/launcher/subsystem_manager.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * \brief Management of subsystems - * \author Norman Feske - * \date 2014-10-02 - */ - -/* - * Copyright (C) 2014-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 _SUBSYSTEM_MANAGER_H_ -#define _SUBSYSTEM_MANAGER_H_ - -/* Genode includes */ -#include <base/component.h> -#include <decorator/xml_utils.h> - -/* CLI-monitor includes */ -#include <cli_monitor/child.h> - -namespace Launcher { - - class Subsystem_manager; - using Cli_monitor::Ram; - using namespace Genode; -} - - -class Launcher::Subsystem_manager -{ - public: - - /** - * Exception types - */ - class Invalid_config { }; - - private: - - Env & _env; - Heap _heap { _env.ram(), _env.rm() }; - size_t const _ram_preservation; - - struct Child : Cli_monitor::Child_base, List<Child>::Element - { - template <typename... ARGS> - Child(ARGS &&... args) : Child_base(args...) { } - }; - - List<Child> _children; - - void _try_response_to_resource_request() - { - for (Child *child = _children.first(); child; child = child->next()) - child->try_response_to_resource_request(); - } - - Signal_handler<Subsystem_manager> _yield_broadcast_handler = - { _env.ep(), *this, &Subsystem_manager::_handle_yield_broadcast }; - - void _handle_yield_broadcast() - { - _try_response_to_resource_request(); - - /* - * XXX copied from 'cli_monitor/main.cc' - */ - - /* - * Compute argument of yield request to be broadcasted to all - * processes. - */ - size_t amount = 0; - - /* amount needed to reach preservation limit */ - Ram::Status ram_status = _ram.status(); - if (ram_status.avail < ram_status.preserve) - amount += ram_status.preserve - ram_status.avail; - - /* sum of pending resource requests */ - for (Child *child = _children.first(); child; child = child->next()) - amount += child->requested_ram_quota(); - - for (Child *child = _children.first(); child; child = child->next()) - child->yield(amount, true); - } - - Signal_handler<Subsystem_manager> _resource_avail_handler = - { _env.ep(), *this, &Subsystem_manager::_handle_resource_avail }; - - void _handle_resource_avail() - { - _try_response_to_resource_request(); - } - - Signal_handler<Subsystem_manager> _yield_response_handler = - { _env.ep(), *this, &Subsystem_manager::_handle_yield_response }; - - void _handle_yield_response() - { - _try_response_to_resource_request(); - } - - Genode::Signal_context_capability _exited_child_sig_cap; - - Ram _ram { _env.pd(), - _env.pd_session_cap(), - _ram_preservation, - _yield_broadcast_handler, - _resource_avail_handler }; - - static Child::Binary_name _binary_name(Xml_node subsystem) - { - try { - return subsystem.sub_node("binary") - .attribute_value("name", Child::Binary_name()); - } catch (Xml_node::Nonexistent_sub_node) { - Genode::error("missing <binary> definition"); - throw Invalid_config(); - } - } - - struct Ram_config { Number_of_bytes quantum, limit; }; - - static Ram_config _ram_config(Xml_node subsystem) - { - Number_of_bytes quantum = 0, limit = 0; - try { - subsystem.for_each_sub_node("resource", [&] (Xml_node rsc) { - if (rsc.attribute("name").has_value("RAM")) { - - rsc.attribute("quantum").value(quantum); - - if (rsc.has_attribute("limit")) - rsc.attribute("limit").value(limit); - } - }); - } catch (...) { - Genode::error("invalid RAM resource declaration"); - throw Invalid_config(); - } - - return Ram_config { quantum, limit }; - } - - static Cap_quota _caps_config(Xml_node subsystem) - { - Cap_quota const caps { subsystem.attribute_value("caps", 0UL) }; - - if (caps.value) - return caps; - - Genode::error("missing 'caps' attribute for ", - subsystem.attribute_value("name", Label())); - throw Invalid_config(); - } - - public: - - Subsystem_manager(Genode::Env & env, - size_t ram_preservation, - Genode::Signal_context_capability exited_child_sig_cap) - : - _env(env), _ram_preservation(ram_preservation), - _exited_child_sig_cap(exited_child_sig_cap) - { } - - /** - * Start subsystem - * - * \throw Invalid_config - */ - void start(Xml_node subsystem) - { - Child::Binary_name const binary_name = _binary_name(subsystem); - - Label const label = subsystem.attribute_value("name", Label("")); - - Ram_config const ram_config = _ram_config(subsystem); - - Genode::log("starting child '", label.string(), "'"); - - try { - Child *child = new (_heap) - Child(_env, _ram, _heap, label, binary_name.string(), - _env.pd(), - _env.pd_session_cap(), - _env.rm(), - _caps_config(subsystem), - ram_config.quantum, ram_config.limit, - _yield_broadcast_handler, - _exited_child_sig_cap); - - auto configure_with_xml = [&] (Xml_node config) - { - config.with_raw_node([&] (char const *start, size_t length) { - child->configure(start, length); }); - }; - - /* configure child */ - try { - if (subsystem.has_sub_node("configfile")) { - Xml_node const node = subsystem.sub_node("configfile"); - - typedef Genode::String<96> Name; - Name const name = node.attribute_value("name", Name()); - - Attached_rom_dataspace rom(_env, name.string()); - configure_with_xml(rom.xml()); - - } else if (subsystem.has_sub_node("config")) { - configure_with_xml(subsystem.sub_node("config")); - } else { - configure_with_xml(Xml_node("<config/>")); - } - } catch (...) { warning("failed to configure child ", label); } - - _children.insert(child); - - child->start(); - } - catch (Service_denied) { - Genode::error("failed to start ", binary_name); - throw Invalid_config(); - } - } - - void kill(char const *label) - { - for (Child *c = _children.first(); c; c = c->next()) { - if (c->label() == Label(label)) { - _children.remove(c); - destroy(_heap, c); - return; - } - } - } - - /** - * Call functor for each exited child - * - * The functor takes a 'Label' as argument. - */ - template <typename FUNC> - void for_each_exited_child(FUNC const &func) - { - Child *next = nullptr; - for (Child *child = _children.first(); child; child = next) { - next = child->next(); - if (child->exited()) - func(Label(child->label().string())); - } - } -}; - -#endif /* _SUBSYSTEM_MANAGER_H_ */ diff --git a/repos/gems/src/app/launcher/target.mk b/repos/gems/src/app/launcher/target.mk deleted file mode 100644 index ed3fda2bd..000000000 --- a/repos/gems/src/app/launcher/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = launcher -SRC_CC = main.cc -LIBS = base -INC_DIR += $(PRG_DIR) - -CC_CXX_WARN_STRICT = diff --git a/repos/gems/src/app/launcher/types.h b/repos/gems/src/app/launcher/types.h deleted file mode 100644 index cd2fe22e6..000000000 --- a/repos/gems/src/app/launcher/types.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * \brief Common types for launcher - * \author Norman Feske - * \date 2014-09-30 - */ - -/* - * Copyright (C) 2014-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 _TYPES_H_ -#define _TYPES_H_ - -/* Genode includes */ -#include <decorator/xml_utils.h> -#include <nitpicker_session/nitpicker_session.h> - -namespace Launcher { - using namespace Genode; - - typedef String<128> Label; - - static Nitpicker::Session::Label selector(Label label) - { - /* - * Append label separator to uniquely identify the subsystem. - * Otherwise, the selector may be ambiguous if the label of one - * subsystem starts with the label of another subsystem. - */ - char selector[Nitpicker::Session::Label::size()]; - snprintf(selector, sizeof(selector), "%s ->", label.string()); - return Nitpicker::Session::Label(Cstring(selector)); - } - - using Decorator::area_attribute; - using Decorator::point_attribute; - - typedef Nitpicker::Point Point; - typedef Nitpicker::Rect Rect; -} - -#endif /* _TYPES_H_ */ diff --git a/repos/gems/src/app/menu_view/main.cc b/repos/gems/src/app/menu_view/main.cc index 42b6c1cb6..9f085d3bb 100644 --- a/repos/gems/src/app/menu_view/main.cc +++ b/repos/gems/src/app/menu_view/main.cc @@ -25,10 +25,10 @@ #include <input/event.h> #include <os/reporter.h> #include <timer_session/connection.h> +#include <os/vfs.h> /* gems includes */ #include <gems/nitpicker_buffer.h> -#include <gems/vfs.h> namespace Menu_view { struct Main; } diff --git a/repos/gems/src/app/sculpt_manager/deploy.h b/repos/gems/src/app/sculpt_manager/deploy.h index 80c962307..c8805b29f 100644 --- a/repos/gems/src/app/sculpt_manager/deploy.h +++ b/repos/gems/src/app/sculpt_manager/deploy.h @@ -74,6 +74,15 @@ struct Sculpt::Deploy void update_managed_deploy_config(Xml_node deploy) { + /* + * Ignore intermediate states that may occur when manually updating + * the config/deploy configuration. Depending on the tool used, + * the original file may be unlinked before the new version is + * created. The temporary empty configuration must not be applied. + */ + if (deploy.type() == "empty") + return; + _managed_deploy_config.generate([&] (Xml_generator &xml) { Arch const arch = deploy.attribute_value("arch", Arch()); diff --git a/repos/gems/src/app/sculpt_manager/network.cc b/repos/gems/src/app/sculpt_manager/network.cc index 21292f38f..1aaeb17b2 100644 --- a/repos/gems/src/app/sculpt_manager/network.cc +++ b/repos/gems/src/app/sculpt_manager/network.cc @@ -40,7 +40,7 @@ void Sculpt::Network::handle_key_press(Codepoint code) wpa_passphrase.remove_last_character(); else if (code.value == ENTER) wifi_connect(dialog.selected_ap()); - else if (code.value != 0) + else if (code.valid()) wpa_passphrase.append_character(code); /* diff --git a/repos/gems/src/app/sculpt_manager/runtime/e2fs.cc b/repos/gems/src/app/sculpt_manager/runtime/e2fs.cc index 8fe86c0f1..1ae68e4dc 100644 --- a/repos/gems/src/app/sculpt_manager/runtime/e2fs.cc +++ b/repos/gems/src/app/sculpt_manager/runtime/e2fs.cc @@ -81,8 +81,9 @@ void Sculpt::gen_mkfs_ext2_start_content(Xml_generator &xml, Storage_target const &target) { auto gen_args = [&] (Xml_generator &xml) { - xml.node("arg", [&] () { - xml.attribute("value", "/dev/block"); }); }; + xml.node("arg", [&] () { xml.attribute("value", "-F"); }); + xml.node("arg", [&] () { xml.attribute("value", "/dev/block"); }); + }; gen_e2fs_start_content(xml, target, "mkfs.ext2", gen_args); } diff --git a/repos/gems/src/app/sculpt_manager/runtime/wifi_drv.cc b/repos/gems/src/app/sculpt_manager/runtime/wifi_drv.cc index 4c055ca23..f32d7986c 100644 --- a/repos/gems/src/app/sculpt_manager/runtime/wifi_drv.cc +++ b/repos/gems/src/app/sculpt_manager/runtime/wifi_drv.cc @@ -58,6 +58,7 @@ void Sculpt::gen_wifi_drv_start_content(Xml_generator &xml) gen_parent_rom_route(xml, "iwlwifi-1000-5.ucode"); gen_parent_rom_route(xml, "iwlwifi-3160-17.ucode"); gen_parent_rom_route(xml, "iwlwifi-3168-17.ucode"); + gen_parent_rom_route(xml, "iwlwifi-5000-5.ucode"); gen_parent_rom_route(xml, "iwlwifi-6000-4.ucode"); gen_parent_rom_route(xml, "iwlwifi-6000g2a-6.ucode"); gen_parent_rom_route(xml, "iwlwifi-6000g2b-6.ucode"); @@ -66,6 +67,7 @@ void Sculpt::gen_wifi_drv_start_content(Xml_generator &xml) gen_parent_rom_route(xml, "iwlwifi-7265D-29.ucode"); gen_parent_rom_route(xml, "iwlwifi-8000C-36.ucode"); gen_parent_rom_route(xml, "iwlwifi-8265-36.ucode"); + gen_parent_rom_route(xml, "iwlwifi-9000-pu-b0-jf-b0-34.ucode"); gen_parent_rom_route(xml, "regulatory.db"); gen_parent_route<Cpu_session> (xml); gen_parent_route<Pd_session> (xml); diff --git a/repos/gems/src/app/sculpt_manager/types.h b/repos/gems/src/app/sculpt_manager/types.h index a56810468..cf29f1442 100644 --- a/repos/gems/src/app/sculpt_manager/types.h +++ b/repos/gems/src/app/sculpt_manager/types.h @@ -37,7 +37,7 @@ namespace Sculpt { using namespace Genode; - typedef String<32> Rom_name; + typedef String<64> Rom_name; typedef String<128> Path; typedef String<36> Start_name; typedef String<64> Label; diff --git a/repos/gems/src/lib/vfs/import/plugin.cc b/repos/gems/src/lib/vfs/import/plugin.cc index a2218090a..2b7bb73ac 100644 --- a/repos/gems/src/lib/vfs/import/plugin.cc +++ b/repos/gems/src/lib/vfs/import/plugin.cc @@ -11,7 +11,7 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include <gems/vfs.h> +#include <os/vfs.h> #include <vfs/print.h> #include <base/heap.h> @@ -189,19 +189,20 @@ class Vfs_import::File_system : public Vfs::File_system dir.for_each_entry([&] (Directory::Entry const &e) { auto entry_path = Directory::join(path, e.name()); switch (e.type()) { - case DIRENT_TYPE_FILE: + case Dirent_type::TRANSACTIONAL_FILE: + case Dirent_type::CONTINUOUS_FILE: copy_file(env, src, entry_path, alloc, overwrite); - break; - case DIRENT_TYPE_DIRECTORY: + return; + case Dirent_type::DIRECTORY: copy_dir(env, src, entry_path, alloc, overwrite); - break; - case DIRENT_TYPE_SYMLINK: + return; + case Dirent_type::SYMLINK: copy_symlink(env, src, entry_path, alloc, overwrite); - break; - default: - Genode::warning("skipping copy of ", e); - break; + return; + case Dirent_type::END: + return; } + Genode::warning("skipping copy of ", e); }); } } diff --git a/repos/gems/src/lib/vfs/pipe/README b/repos/gems/src/lib/vfs/pipe/README new file mode 100644 index 000000000..95e40e6fc --- /dev/null +++ b/repos/gems/src/lib/vfs/pipe/README @@ -0,0 +1,12 @@ +The VFS pipe plugin exposes a control file for creating pipes and a set of pipe +directories. Opening and reading the "/new" returns a relative path to a +directory. That directory represents a pipe and contains an "in" and "out" file +for writing and reading respectively to the pipe. + +Reads and writes are non-blocking and will complete short operations without +error, with the exception of reads on an empty pipe, which return READ_QUEUED. +The read and write capacity of a pipe may be queried by stat'ing the size of +"out" and "in" files. + +When all "in" and "out" handles on a pipe as well as the initial handle on "new" +are closed, the pipe is destroyed. diff --git a/repos/gems/src/lib/vfs/pipe/plugin.cc b/repos/gems/src/lib/vfs/pipe/plugin.cc new file mode 100644 index 000000000..bf880f53a --- /dev/null +++ b/repos/gems/src/lib/vfs/pipe/plugin.cc @@ -0,0 +1,618 @@ +/* + * \brief VFS pipe plugin + * \author Emery Hemingway + * \date 2019-05-29 + */ + +/* + * Copyright (C) 2019 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 <vfs/file_system_factory.h> +#include <os/path.h> +#include <os/ring_buffer.h> +#include <base/registry.h> + +namespace Vfs_pipe { + using namespace Vfs; + typedef Vfs::Directory_service::Open_result Open_result; + typedef Vfs::File_io_service::Write_result Write_result; + typedef Vfs::File_io_service::Read_result Read_result; + typedef Genode::Path<32> Path; + + enum { PIPE_BUF_SIZE = 8192U }; + typedef Genode::Ring_buffer<unsigned char, PIPE_BUF_SIZE+1> Pipe_buffer; + + struct Pipe_handle; + typedef Genode::Fifo_element<Pipe_handle> Handle_element; + typedef Genode::Fifo<Handle_element> Handle_fifo; + typedef Genode::Registry<Pipe_handle>::Element Pipe_handle_registry_element; + typedef Genode::Registry<Pipe_handle> Pipe_handle_registry; + + class Pipe; + typedef Genode::Id_space<Pipe> Pipe_space; + + struct New_pipe_handle; + + class File_system; +} + + +struct Vfs_pipe::Pipe_handle : Vfs::Vfs_handle, private Pipe_handle_registry_element +{ + Pipe &pipe; + + Handle_element io_progress_elem { *this }; + Handle_element read_ready_elem { *this }; + + bool const writer; + + Pipe_handle(Vfs::File_system &fs, + Genode::Allocator &alloc, + unsigned flags, + Pipe_handle_registry ®istry, + Pipe &p) + : + Vfs::Vfs_handle(fs, fs, alloc, flags), + Pipe_handle_registry_element(registry, *this), + pipe(p), + writer(flags == Directory_service::OPEN_MODE_WRONLY) + { } + + virtual ~Pipe_handle(); + + Write_result write(const char *buf, + file_size count, + file_size &out_count); + + Read_result read(char *buf, + file_size count, + file_size &out_count); + + bool read_ready(); + bool notify_read_ready(); +}; + + +struct Vfs_pipe::Pipe +{ + Genode::Allocator &alloc; + Pipe_space::Element space_elem; + Pipe_buffer buffer { }; + Pipe_handle_registry registry { }; + Handle_fifo io_progress_waiters { }; + Handle_fifo read_ready_waiters { }; + unsigned num_writers = 0; + + Genode::Signal_context_capability ¬ify_sigh; + + bool new_handle_active { true }; + + Pipe(Genode::Allocator &alloc, Pipe_space &space, + Genode::Signal_context_capability ¬ify_sigh) + : alloc(alloc), space_elem(*this, space), notify_sigh(notify_sigh) { } + + ~Pipe() { } + + typedef Genode::String<8> Name; + Name name() const + { + return Name(space_elem.id().value); + } + + /** + * Check if pipe is referenced, if not, destroy + */ + void cleanup() + { + bool alive = new_handle_active; + if (!alive) + registry.for_each([&alive] (Pipe_handle&) { + alive = true; }); + if (!alive) + destroy(alloc, this); + } + + /** + * Remove "/new" handle reference + */ + void remove_new_handle() { + new_handle_active = false; } + + /** + * Detach a handle + */ + void remove(Pipe_handle &handle) + { + if (handle.io_progress_elem.enqueued()) + io_progress_waiters.remove(handle.io_progress_elem); + if (handle.read_ready_elem.enqueued()) + read_ready_waiters.remove(handle.read_ready_elem); + } + + /** + * Open a write or read handle + */ + Open_result open(Vfs::File_system &fs, + Path const &filename, + Vfs::Vfs_handle **handle, + Genode::Allocator &alloc) + { + if (filename == "/in") { + *handle = new (alloc) + Pipe_handle(fs, alloc, Directory_service::OPEN_MODE_WRONLY, registry, *this); + num_writers++; + return Open_result::OPEN_OK; + } + + if (filename == "/out") { + *handle = new (alloc) + Pipe_handle(fs, alloc, Directory_service::OPEN_MODE_RDONLY, registry, *this); + return Open_result::OPEN_OK; + } + + return Open_result::OPEN_ERR_UNACCESSIBLE; + } + + /** + * Use a signal as a hack to defer notifications + * until the "io_progress_handler". + */ + void submit_signal() { + Genode::Signal_transmitter(notify_sigh).submit(); } + + /** + * Notify handles waiting for activity + */ + void notify() + { + io_progress_waiters.dequeue_all([] (Handle_element &elem) { + elem.object().io_progress_response(); }); + read_ready_waiters.dequeue_all([] (Handle_element &elem) { + elem.object().read_ready_response(); }); + } + + Write_result write(Pipe_handle &handle, + const char *buf, file_size count, + file_size &out_count) + { + file_size out = 0; + bool notify = buffer.empty(); + + while (out < count && 0 < buffer.avail_capacity()) { + buffer.add(*(buf++)); + ++out; + } + + out_count = out; + if (out < count) + io_progress_waiters.enqueue(handle.io_progress_elem); + + if (notify) + submit_signal(); + + return Write_result::WRITE_OK; + } + + Read_result read(Pipe_handle &handle, + char *buf, file_size count, + file_size &out_count) + { + bool notify = buffer.avail_capacity() == 0; + + file_size out = 0; + while (out < count && !buffer.empty()) { + *(buf++) = buffer.get(); + ++out; + } + + out_count = out; + if (!out) { + + if (num_writers == 0) + return Read_result::READ_OK; /* EOF */ + + io_progress_waiters.enqueue(handle.io_progress_elem); + return Read_result::READ_QUEUED; + } + + if (notify) + submit_signal(); + + return Read_result::READ_OK; + } +}; + + +Vfs_pipe::Pipe_handle::~Pipe_handle() { + pipe.remove(*this); } + + +Vfs_pipe::Write_result +Vfs_pipe::Pipe_handle::write(const char *buf, + file_size count, + file_size &out_count) { + return Pipe_handle::pipe.write(*this, buf, count, out_count); } + + +Vfs_pipe::Read_result +Vfs_pipe::Pipe_handle::read(char *buf, + file_size count, + file_size &out_count) { + return Pipe_handle::pipe.read(*this, buf, count, out_count); } + + +bool +Vfs_pipe::Pipe_handle::read_ready() { + return !pipe.buffer.empty(); } + + +bool +Vfs_pipe::Pipe_handle::notify_read_ready() +{ + if (!read_ready_elem.enqueued()) + pipe.read_ready_waiters.enqueue(read_ready_elem); + return true; +} + + +struct Vfs_pipe::New_pipe_handle : Vfs::Vfs_handle +{ + Pipe &pipe; + + New_pipe_handle(Vfs::File_system &fs, + Genode::Allocator &alloc, + unsigned flags, + Pipe_space &pipe_space, + Genode::Signal_context_capability ¬ify_sigh) + : Vfs::Vfs_handle(fs, fs, alloc, flags), + pipe(*(new (alloc) Pipe(alloc, pipe_space, notify_sigh))) + { } + + ~New_pipe_handle() + { + pipe.remove_new_handle(); + } + + Read_result read(char *buf, + file_size count, + file_size &out_count) + { + auto name = pipe.name(); + if (name.length() < count) { + memcpy(buf, name.string(), name.length()); + out_count = name.length(); + return Read_result::READ_OK; + } + return Read_result::READ_ERR_INVALID; + } +}; + + +class Vfs_pipe::File_system : public Vfs::File_system +{ + private: + + Pipe_space _pipe_space { }; + + /* + * XXX: a hack to defer cross-thread notifications at + * the libc until the io_progress handler + */ + Genode::Io_signal_handler<File_system> _notify_handler; + Genode::Signal_context_capability _notify_cap { _notify_handler }; + + void _notify_any() + { + _pipe_space.for_each<Pipe&>([] (Pipe &pipe) { + pipe.notify(); }); + } + + public: + + File_system(Vfs::Env &env) + : _notify_handler(env.env().ep(), *this, &File_system::_notify_any) { } + + const char* type() override { return "pipe"; } + + /*********************** + ** Directory service ** + ***********************/ + + Genode::Dataspace_capability dataspace(char const*) override { + return Genode::Dataspace_capability(); } + + void release(char const*, Dataspace_capability) override { } + + Open_result open(const char *cpath, + unsigned mode, + Vfs::Vfs_handle **handle, + Genode::Allocator &alloc) override + { + Path path(cpath); + + if (path == "/new") { + if ((Directory_service::OPEN_MODE_ACCMODE & mode) == Directory_service::OPEN_MODE_WRONLY) + return Open_result::OPEN_ERR_NO_PERM; + *handle = new (alloc) + New_pipe_handle(*this, alloc, mode, _pipe_space, _notify_cap); + return Open_result::OPEN_OK; + } + + path.strip_last_element(); + if (!path.has_single_element()) + return Open_result::OPEN_ERR_UNACCESSIBLE; + + Pipe_space::Id id { ~0UL }; + if (!ascii_to(path.last_element(), id.value)) + return Open_result::OPEN_ERR_UNACCESSIBLE; + + Open_result result = Open_result::OPEN_ERR_UNACCESSIBLE; + try { + _pipe_space.apply<Pipe&>(id, [&] (Pipe &pipe) { + Path filename(cpath); + filename.keep_only_last_element(); + result = pipe.open(*this, filename, handle, alloc); + }); + } + catch (Pipe_space::Unknown_id) { } + + return result; + } + + Opendir_result opendir(char const *cpath, bool create, + Vfs_handle **handle, + Allocator &alloc) override + { + /* open dummy handles on directories */ + + if (create) return OPENDIR_ERR_PERMISSION_DENIED; + Path path(cpath); + + if (path == "/") { + *handle = new (alloc) + Vfs_handle(*this, *this, alloc, 0); + return OPENDIR_OK; + } + + Opendir_result result { OPENDIR_ERR_LOOKUP_FAILED }; + + if (path.has_single_element()) { + Pipe_space::Id id { ~0UL }; + if (ascii_to(path.last_element(), id.value)) try { + _pipe_space.apply<Pipe&>(id, [&] (Pipe&) { + *handle = new (alloc) + Vfs_handle(*this, *this, alloc, 0); + result = OPENDIR_OK; + }); + } + catch (Pipe_space::Unknown_id) { } + } + + return result; + } + + void close(Vfs::Vfs_handle *vfs_handle) override + { + Pipe *pipe = nullptr; + if (Pipe_handle *handle = dynamic_cast<Pipe_handle*>(vfs_handle)) { + pipe = &handle->pipe; + if (handle->writer) + pipe->num_writers--; + } else + if (New_pipe_handle *handle = dynamic_cast<New_pipe_handle*>(vfs_handle)) + pipe = &handle->pipe; + + destroy(vfs_handle->alloc(), vfs_handle); + + if (pipe) + pipe->cleanup(); + } + + Stat_result stat(const char *cpath, Stat &out) override + { + Stat_result result { STAT_ERR_NO_ENTRY }; + Path path(cpath); + + out = Stat { }; + + if (path == "/new") { + out = Stat { + .size = 1, + .type = Node_type::TRANSACTIONAL_FILE, + .rwx = Node_rwx::wo(), + .inode = Genode::addr_t(this), + .device = Genode::addr_t(this), + .modification_time = { } + }; + return STAT_OK; + } + + if (path.has_single_element()) { + Pipe_space::Id id { ~0UL }; + if (ascii_to(path.last_element(), id.value)) try { + _pipe_space.apply<Pipe&>(id, [&] (Pipe &pipe) { + out = Stat { + .size = 2, + .type = Node_type::DIRECTORY, + .rwx = Node_rwx::rwx(), + .inode = Genode::addr_t(&pipe), + .device = Genode::addr_t(this), + .modification_time = { } + }; + result = STAT_OK; + }); + } + catch (Pipe_space::Unknown_id) { } + } else { + /* maybe this is /N/in or /N/out */ + path.strip_last_element(); + if (!path.has_single_element()) + /* too many directory levels */ + return result; + + Pipe_space::Id id { ~0UL }; + if (ascii_to(path.last_element(), id.value)) try { + _pipe_space.apply<Pipe&>(id, [&] (Pipe &pipe) { + Path filename(cpath); + filename.keep_only_last_element(); + if (filename == "/in") { + out = Stat { + .size = file_size(pipe.buffer.avail_capacity()), + .type = Node_type::CONTINUOUS_FILE, + .rwx = Node_rwx::wo(), + .inode = Genode::addr_t(&pipe) + 1, + .device = Genode::addr_t(this), + .modification_time = { } + }; + result = STAT_OK; + } else + if (filename == "/out") { + out = Stat { + .size = file_size(PIPE_BUF_SIZE + - pipe.buffer.avail_capacity()), + .type = Node_type::CONTINUOUS_FILE, + .rwx = Node_rwx::ro(), + .inode = Genode::addr_t(&pipe) + 2, + .device = Genode::addr_t(this), + .modification_time = { } + }; + result = STAT_OK; + } + }); + } + catch (Pipe_space::Unknown_id) { } + } + + return result; + } + + Unlink_result unlink(const char*) override { + return UNLINK_ERR_NO_ENTRY; } + + Rename_result rename(const char*, const char*) override { + return RENAME_ERR_NO_ENTRY; } + + file_size num_dirent(char const *) override { + return ~0UL; } + + bool directory(char const *cpath) override + { + Path path(cpath); + if (path == "/") return true; + + if (!path.has_single_element()) + return Open_result::OPEN_ERR_UNACCESSIBLE; + + Pipe_space::Id id { ~0UL }; + if (!ascii_to(path.last_element(), id.value)) + return false; + + bool result = false; + try { + _pipe_space.apply<Pipe&>(id, [&] (Pipe &) { + result = true; }); + } + catch (Pipe_space::Unknown_id) { } + + return result; + } + + const char* leaf_path(const char *cpath) override + { + Path path(cpath); + if (path == "/") return cpath; + if (path == "/new") return cpath; + + char const *result = nullptr; + if (!path.has_single_element()) { + /* maybe this is /N/in or /N/out */ + path.strip_last_element(); + if (!path.has_single_element()) + /* too many directory levels */ + return nullptr; + + Path filename(cpath); + filename.keep_only_last_element(); + if (filename != "/in" && filename != "/out") + /* not a pipe file */ + return nullptr; + } + + Pipe_space::Id id { ~0UL }; + if (ascii_to(path.last_element(), id.value)) try { + /* check if the pipe directory exists */ + _pipe_space.apply<Pipe&>(id, [&] (Pipe &) { + result = cpath; }); + } + catch (Pipe_space::Unknown_id) { } + + return result; + } + + /********************** + ** File I/O service ** + **********************/ + + Write_result write(Vfs_handle *vfs_handle, + const char *src, file_size count, + file_size &out_count) override + { + if (Pipe_handle *handle = dynamic_cast<Pipe_handle*>(vfs_handle)) + return handle->write(src, count, out_count); + + return WRITE_ERR_INVALID; + } + + Read_result complete_read(Vfs_handle *vfs_handle, + char *dst, file_size count, + file_size &out_count) override + { + if (Pipe_handle *handle = dynamic_cast<Pipe_handle*>(vfs_handle)) + return handle->read(dst, count, out_count); + + if (New_pipe_handle *handle = dynamic_cast<New_pipe_handle*>(vfs_handle)) + return handle->read(dst, count, out_count); + + return READ_ERR_INVALID; + } + + bool read_ready(Vfs_handle *vfs_handle) override + { + if (Pipe_handle *handle = dynamic_cast<Pipe_handle*>(vfs_handle)) + return handle->read_ready(); + return true; + } + + bool notify_read_ready(Vfs_handle *vfs_handle) override + { + if (Pipe_handle *handle = dynamic_cast<Pipe_handle*>(vfs_handle)) + return handle->notify_read_ready(); + return false; + } + + Ftruncate_result ftruncate(Vfs_handle*, file_size) override { + return FTRUNCATE_ERR_NO_PERM; } + + Sync_result complete_sync(Vfs_handle*) override { + return SYNC_OK; } +}; + + +extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) +{ + struct Factory : Vfs::File_system_factory + { + Vfs::File_system *create(Vfs::Env &env, Genode::Xml_node) override + { + return new (env.alloc()) + Vfs_pipe::File_system(env); + } + }; + + static Factory f; + return &f; +} diff --git a/repos/gems/src/lib/vfs/pipe/target.mk b/repos/gems/src/lib/vfs/pipe/target.mk new file mode 100644 index 000000000..d2d34db6b --- /dev/null +++ b/repos/gems/src/lib/vfs/pipe/target.mk @@ -0,0 +1,2 @@ +TARGET = dummy-vfs_pipe +LIBS = vfs_pipe diff --git a/repos/gems/src/lib/vfs/trace/value_file_system.h b/repos/gems/src/lib/vfs/trace/value_file_system.h index 6c62c48c4..f498fde05 100644 --- a/repos/gems/src/lib/vfs/trace/value_file_system.h +++ b/repos/gems/src/lib/vfs/trace/value_file_system.h @@ -128,8 +128,8 @@ class Vfs::Value_file_system : public Vfs::Single_file_system Value_file_system(Name const &name, Buffer const &initial_value) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, type(), - Xml_node(_config(name).string())), + Single_file_system(Node_type::TRANSACTIONAL_FILE, type(), + Node_rwx::rw(), Xml_node(_config(name).string())), _file_name(name) { value(initial_value); @@ -196,7 +196,6 @@ class Vfs::Value_file_system : public Vfs::Single_file_system Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.mode |= 0666; out.size = BUF_SIZE + 1; return result; } diff --git a/repos/gems/src/lib/vfs/trace/vfs.cc b/repos/gems/src/lib/vfs/trace/vfs.cc index aa19e90e9..6dcc7ac26 100644 --- a/repos/gems/src/lib/vfs/trace/vfs.cc +++ b/repos/gems/src/lib/vfs/trace/vfs.cc @@ -15,8 +15,7 @@ #include <vfs/dir_file_system.h> #include <vfs/single_file_system.h> - -#include <gems/vfs.h> +#include <os/vfs.h> #include <util/xml_generator.h> #include <trace_session/connection.h> @@ -155,8 +154,8 @@ class Vfs_trace::Trace_buffer_file_system : public Single_file_system Trace::Connection &trace, Trace::Policy_id policy, Trace::Subject_id id) - : Single_file_system(NODE_TYPE_CHAR_DEVICE, - type_name(), Xml_node(_config().string())), + : Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), + Node_rwx::rw(), Xml_node(_config().string())), _env(env), _trace(trace), _policy(policy), _id(id) { } diff --git a/repos/gems/src/lib/vfs/ttf/glyphs_file_system.h b/repos/gems/src/lib/vfs/ttf/glyphs_file_system.h index a6e99ac39..7e0ace54f 100644 --- a/repos/gems/src/lib/vfs/ttf/glyphs_file_system.h +++ b/repos/gems/src/lib/vfs/ttf/glyphs_file_system.h @@ -113,7 +113,8 @@ class Vfs::Glyphs_file_system : public Vfs::Single_file_system Glyphs_file_system(Font const &font) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, type(), Xml_node("<glyphs/>")), + Single_file_system(Node_type::TRANSACTIONAL_FILE, type(), + Node_rwx::ro(), Xml_node("<glyphs/>")), _font(font) { } @@ -145,7 +146,6 @@ class Vfs::Glyphs_file_system : public Vfs::Single_file_system Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.mode |= 0444; out.size = FILE_SIZE; return result; } diff --git a/repos/gems/src/lib/vfs/ttf/vfs.cc b/repos/gems/src/lib/vfs/ttf/vfs.cc index e1ec7a390..8913eac71 100644 --- a/repos/gems/src/lib/vfs/ttf/vfs.cc +++ b/repos/gems/src/lib/vfs/ttf/vfs.cc @@ -14,10 +14,10 @@ /* Genode includes */ #include <vfs/dir_file_system.h> #include <vfs/readonly_value_file_system.h> +#include <os/vfs.h> /* gems includes */ #include <gems/ttf_font.h> -#include <gems/vfs.h> #include <gems/cached_font.h> /* local includes */ diff --git a/repos/gems/src/server/terminal/main.cc b/repos/gems/src/server/terminal/main.cc index 870a2a182..c169d22c9 100644 --- a/repos/gems/src/server/terminal/main.cc +++ b/repos/gems/src/server/terminal/main.cc @@ -22,7 +22,7 @@ #include <base/attached_ram_dataspace.h> #include <input/event.h> #include <os/reporter.h> -#include <gems/vfs.h> +#include <os/vfs.h> #include <gems/vfs_font.h> #include <gems/cached_font.h> @@ -90,6 +90,8 @@ struct Terminal::Main : Character_consumer bool _shift_pressed = false; + unsigned _ctrl_pressed = 0; /* number of control keys pressed */ + bool _selecting = false; struct Paste_buffer { char buffer[READ_BUFFER_SIZE]; } _paste_buffer { }; @@ -320,11 +322,26 @@ void Terminal::Main::_handle_input() } } + if (event.key_press(Input::KEY_LEFTCTRL) + || event.key_press(Input::KEY_RIGHTCTRL)) + ++_ctrl_pressed; + + if (event.key_release(Input::KEY_LEFTCTRL) + || event.key_release(Input::KEY_RIGHTCTRL)) + --_ctrl_pressed; + if (event.key_press(Input::BTN_MIDDLE)) _paste_clipboard_content(); event.handle_press([&] (Input::Keycode, Codepoint codepoint) { + /* control-key combinations */ + if (_ctrl_pressed + && codepoint.value >= 'a' && codepoint.value <= 'z') { + _read_buffer.add(Codepoint { codepoint.value - 'a' + 1 } ); + return; + } + /* function-key unicodes */ enum { CODEPOINT_UP = 0xf700, CODEPOINT_DOWN = 0xf701, diff --git a/repos/gems/src/test/text_painter/main.cc b/repos/gems/src/test/text_painter/main.cc index 1e39eeaaa..1a2326653 100644 --- a/repos/gems/src/test/text_painter/main.cc +++ b/repos/gems/src/test/text_painter/main.cc @@ -23,10 +23,10 @@ #include <nitpicker_gfx/box_painter.h> #include <util/bezier.h> #include <timer_session/connection.h> +#include <os/vfs.h> /* gems includes */ #include <gems/ttf_font.h> -#include <gems/vfs.h> #include <gems/vfs_font.h> #include <gems/cached_font.h> diff --git a/repos/libports/include/libc-plugin/fd_alloc.h b/repos/libports/include/libc-plugin/fd_alloc.h index 743c9df13..e03dfa739 100644 --- a/repos/libports/include/libc-plugin/fd_alloc.h +++ b/repos/libports/include/libc-plugin/fd_alloc.h @@ -53,8 +53,9 @@ namespace Libc { Plugin *plugin; Plugin_context *context; - int flags = 0; /* for 'fcntl' */ - bool cloexec = 0; /* for 'fcntl' */ + int flags = 0; /* for 'fcntl' */ + bool cloexec = 0; /* for 'fcntl' */ + bool modified = false; File_descriptor(Id_space &id_space, Plugin &plugin, Plugin_context &context) : _elem(*this, id_space), plugin(&plugin), context(&context) { } diff --git a/repos/libports/include/libc/select.h b/repos/libports/include/libc/select.h index c4b7dbb39..b5f87e947 100644 --- a/repos/libports/include/libc/select.h +++ b/repos/libports/include/libc/select.h @@ -14,7 +14,10 @@ #ifndef _INCLUDE__LIBC__SELECT_H_ #define _INCLUDE__LIBC__SELECT_H_ -/* Libc includes */ +/* Genode includes */ +#include <util/reconstructible.h> + +/* libc includes */ #include <sys/select.h> /* for fd_set */ diff --git a/repos/libports/include/lwip/arch/cc.h b/repos/libports/include/lwip/arch/cc.h index 8b561c7d5..5ab668dd8 100644 --- a/repos/libports/include/lwip/arch/cc.h +++ b/repos/libports/include/lwip/arch/cc.h @@ -53,7 +53,11 @@ typedef int64_t s64_t; typedef uintptr_t mem_ptr_t; #ifndef NULL -#define NULL (uintptr_t)0 +#ifndef __cplusplus +#define NULL ((void *)0) +#else +#define NULL (nullptr) +#endif #endif #endif /* LWIP_NO_STDINT_H */ diff --git a/repos/libports/include/qt5/qpa_nitpicker/qnitpickerplatformwindow.h b/repos/libports/include/qt5/qpa_nitpicker/qnitpickerplatformwindow.h index caa1caf39..858950960 100644 --- a/repos/libports/include/qt5/qpa_nitpicker/qnitpickerplatformwindow.h +++ b/repos/libports/include/qt5/qpa_nitpicker/qnitpickerplatformwindow.h @@ -1,11 +1,12 @@ /* * \brief QNitpickerPlatformWindow * \author Christian Prochaska + * \author Christian Helmuth * \date 2013-05-08 */ /* - * Copyright (C) 2013-2017 Genode Labs GmbH + * Copyright (C) 2013-2019 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. @@ -25,7 +26,6 @@ /* Qt includes */ #include <qpa/qplatformwindow.h> #include <qpa/qwindowsysteminterface.h> -#include <QtInputSupport/private/qevdevkeyboardhandler_p.h> #include <qtouchdevice.h> /* Qoost includes */ @@ -66,6 +66,23 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow _mouse_position.y() - geometry().y()); } + + typedef Genode::Codepoint Codepoint; + + struct Mapped_key + { + enum Event { PRESSED, RELEASED, REPEAT }; + + Qt::Key key { Qt::Key_unknown }; + Codepoint codepoint { Codepoint::INVALID }; + }; + + QHash<Input::Keycode, Qt::Key> _pressed; + + Mapped_key _map_key(Input::Keycode, Codepoint, Mapped_key::Event); + void _key_event(Input::Keycode, Codepoint, Mapped_key::Event); + void _mouse_button_event(Input::Keycode, bool press); + Genode::Signal_handler<QNitpickerPlatformWindow> _input_signal_handler; Genode::Signal_handler<QNitpickerPlatformWindow> _mode_changed_signal_handler; diff --git a/repos/libports/include/spec/32bit/gmp/fac_table.h b/repos/libports/include/spec/32bit/gmp/fac_table.h new file mode 100644 index 000000000..db925816b --- /dev/null +++ b/repos/libports/include/spec/32bit/gmp/fac_table.h @@ -0,0 +1,49 @@ +/* This file is automatically generated by gen-fac.c */ + +#if GMP_NUMB_BITS != 32 +Error , error this data is for 32 GMP_NUMB_BITS only +#endif +/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x2),CNST_LIMB(0x6),CNST_LIMB(0x18),CNST_LIMB(0x78),CNST_LIMB(0x2d0),CNST_LIMB(0x13b0),CNST_LIMB(0x9d80),CNST_LIMB(0x58980),CNST_LIMB(0x375f00),CNST_LIMB(0x2611500),CNST_LIMB(0x1c8cfc00) + +/* This table is 0!,1!,2!/2,3!/2,...,n!/2^sn where n!/2^sn is an */ +/* odd integer for each n, and n!/2^sn has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_ODD_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x3),CNST_LIMB(0x3),CNST_LIMB(0xf),CNST_LIMB(0x2d),CNST_LIMB(0x13b),CNST_LIMB(0x13b),CNST_LIMB(0xb13),CNST_LIMB(0x375f),CNST_LIMB(0x26115),CNST_LIMB(0x7233f),CNST_LIMB(0x5cca33),CNST_LIMB(0x2898765),CNST_LIMB(0x260eeeeb),CNST_LIMB(0x260eeeeb) +#define ODD_FACTORIAL_TABLE_MAX CNST_LIMB(0x260eeeeb) +#define ODD_FACTORIAL_TABLE_LIMIT (16) + +/* Previous table, continued, values modulo 2^GMP_NUMB_BITS */ +#define ONE_LIMB_ODD_FACTORIAL_EXTTABLE CNST_LIMB(0x86fddd9b),CNST_LIMB(0xbeecca73),CNST_LIMB(0x2b930689),CNST_LIMB(0xd9df20ad),CNST_LIMB(0xdf4dae31),CNST_LIMB(0x98567c1b),CNST_LIMB(0xafc5266d),CNST_LIMB(0xf4f7347),CNST_LIMB(0x7ec241ef),CNST_LIMB(0x6fdd5923),CNST_LIMB(0xcc5866b1),CNST_LIMB(0x966aced7),CNST_LIMB(0xa196e5b),CNST_LIMB(0x977d7755),CNST_LIMB(0x5831734b),CNST_LIMB(0x5831734b),CNST_LIMB(0x5e5fdcab),CNST_LIMB(0x445da75b) +#define ODD_FACTORIAL_EXTTABLE_LIMIT (34) + +/* This table is 1!!,3!!,...,(2n+1)!! where (2n+1)!! has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x3),CNST_LIMB(0xf),CNST_LIMB(0x69),CNST_LIMB(0x3b1),CNST_LIMB(0x289b),CNST_LIMB(0x20fdf),CNST_LIMB(0x1eee11),CNST_LIMB(0x20dcf21),CNST_LIMB(0x27065f73) +#define ODD_DOUBLEFACTORIAL_TABLE_MAX CNST_LIMB(0x27065f73) +#define ODD_DOUBLEFACTORIAL_TABLE_LIMIT (19) + +/* This table x_1, x_2,... contains values s.t. x_n^n has <= GMP_NUMB_BITS bits */ +#define NTH_ROOT_NUMB_MASK_TABLE (GMP_NUMB_MASK),CNST_LIMB(0xffff),CNST_LIMB(0x659),CNST_LIMB(0xff),CNST_LIMB(0x54),CNST_LIMB(0x28),CNST_LIMB(0x17),CNST_LIMB(0xf) + +/* This table contains inverses of odd factorials, modulo 2^GMP_NUMB_BITS */ + +/* It begins with (2!/2)^-1=1 */ +#define ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE CNST_LIMB(0x1),CNST_LIMB(0xaaaaaaab),CNST_LIMB(0xaaaaaaab),CNST_LIMB(0xeeeeeeef),CNST_LIMB(0xa4fa4fa5),CNST_LIMB(0xf2ff2ff3),CNST_LIMB(0xf2ff2ff3),CNST_LIMB(0x53e3771b),CNST_LIMB(0xdd93e49f),CNST_LIMB(0xfcdee63d),CNST_LIMB(0x544a4cbf),CNST_LIMB(0x7ca340fb),CNST_LIMB(0xa417526d),CNST_LIMB(0xd7bd49c3),CNST_LIMB(0xd7bd49c3),CNST_LIMB(0x85294093),CNST_LIMB(0xf259eabb),CNST_LIMB(0xd6dc4fb9),CNST_LIMB(0x915f4325),CNST_LIMB(0x131cead1),CNST_LIMB(0xea76fe13),CNST_LIMB(0x633cd365),CNST_LIMB(0x21144677),CNST_LIMB(0x200b0d0f),CNST_LIMB(0x8c4f9e8b),CNST_LIMB(0x21a42251),CNST_LIMB(0xe03c04e7),CNST_LIMB(0x600211d3),CNST_LIMB(0x4aaacdfd),CNST_LIMB(0x33f4fe63),CNST_LIMB(0x33f4fe63) + +/* This table contains 2n-popc(2n) for small n */ + +/* It begins with 2-1=1 (n=1) */ +#define TABLE_2N_MINUS_POPC_2N 1,3,4,7,8,10,11,15,16,18,19,22,23,25,26,31,32,34,35,38,39,41,42,46 +#define TABLE_LIMIT_2N_MINUS_POPC_2N 49 +#define ODD_CENTRAL_BINOMIAL_OFFSET (8) + +/* This table contains binomial(2k,k)/2^t */ + +/* It begins with ODD_CENTRAL_BINOMIAL_TABLE_MIN */ +#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE CNST_LIMB(0x1923),CNST_LIMB(0x2f7b),CNST_LIMB(0xb46d),CNST_LIMB(0x15873),CNST_LIMB(0xa50c7),CNST_LIMB(0x13d66b),CNST_LIMB(0x4c842f),CNST_LIMB(0x93ee7d),CNST_LIMB(0x11e9e123),CNST_LIMB(0x22c60053),CNST_LIMB(0x873ae4d1) +#define ODD_CENTRAL_BINOMIAL_TABLE_LIMIT (18) + +/* This table contains the inverses of elements in the previous table. */ +#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE CNST_LIMB(0x16a2de8b),CNST_LIMB(0x847457b3),CNST_LIMB(0xfa6f7565),CNST_LIMB(0xf0e50cbb),CNST_LIMB(0xdca370f7),CNST_LIMB(0x9bb12643),CNST_LIMB(0xdc8342cf),CNST_LIMB(0x4ebf7ad5),CNST_LIMB(0x86ab568b),CNST_LIMB(0x265843db),CNST_LIMB(0x8633f431) + +/* This table contains the values t in the formula binomial(2k,k)/2^t */ +#define CENTRAL_BINOMIAL_2FAC_TABLE 1,2,2,3,2,3,3,4,1,2,2 diff --git a/repos/libports/include/spec/32bit/gmp/fac_ui.h b/repos/libports/include/spec/32bit/gmp/fac_ui.h deleted file mode 100644 index 09ddf43c6..000000000 --- a/repos/libports/include/spec/32bit/gmp/fac_ui.h +++ /dev/null @@ -1,19 +0,0 @@ -/* This file is automatically generated by gen-fac_ui.c */ - -#if GMP_NUMB_BITS != 32 -Error , error this data is for 32 GMP_NUMB_BITS only -#endif -#if GMP_LIMB_BITS != 32 -Error , error this data is for 32 GMP_LIMB_BITS only -#endif -/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */ -#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x2),CNST_LIMB(0x6),CNST_LIMB(0x18),CNST_LIMB(0x78),CNST_LIMB(0x2d0),CNST_LIMB(0x13b0),CNST_LIMB(0x9d80),CNST_LIMB(0x58980),CNST_LIMB(0x375f00),CNST_LIMB(0x2611500),CNST_LIMB(0x1c8cfc00) - -/* is 2^(GMP_LIMB_BITS+1)/exp(1) */ -#define FAC2OVERE CNST_LIMB(0xbc5c254b) - -/* FACMULn is largest odd x such that x*(x+2)*...*(x+2(n-1))<=2^GMP_NUMB_BITS-1 */ - -#define FACMUL2 CNST_LIMB(0xffff) -#define FACMUL3 CNST_LIMB(0x657) -#define FACMUL4 CNST_LIMB(0xfd) diff --git a/repos/libports/include/spec/32bit/gmp/gmp.h b/repos/libports/include/spec/32bit/gmp/gmp.h index 607616997..c635aa0d6 100644 --- a/repos/libports/include/spec/32bit/gmp/gmp.h +++ b/repos/libports/include/spec/32bit/gmp/gmp.h @@ -1,22 +1,32 @@ /* Definitions for GNU multiple precision functions. -*- mode: c -*- -Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, -2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +Copyright 1991, 1993-1997, 1999-2016 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 3 of the License, or (at your -option) any later version. +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. -You should have received a copy of the GNU Lesser General Public License -along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ #ifndef __GMP_H__ @@ -28,7 +38,6 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ /* Instantiated by configure. */ #if ! defined (__GMP_WITHIN_CONFIGURE) -#define __GMP_BITS_PER_MP_LIMB 32 #define __GMP_HAVE_HOST_CPU_FAMILY_power 0 #define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0 #define GMP_LIMB_BITS 32 @@ -40,19 +49,11 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #define GMP_NAIL_MASK (~ GMP_NUMB_MASK) -/* The following (everything under ifndef __GNU_MP__) must be identical in - gmp.h and mp.h to allow both to be included in an application or during - the library build. */ #ifndef __GNU_MP__ -#define __GNU_MP__ 4 +#define __GNU_MP__ 6 -#define __need_size_t /* tell gcc stddef.h we only want size_t */ -#if defined (__cplusplus) -#include <cstddef> /* for size_t */ -#else #include <stddef.h> /* for size_t */ -#endif -#undef __need_size_t +#include <limits.h> /* Instantiated by configure. */ #if ! defined (__GMP_WITHIN_CONFIGURE) @@ -61,57 +62,6 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #endif -/* __STDC__ - some ANSI compilers define this only to 0, hence the use of - "defined" and not "__STDC__-0". In particular Sun workshop C 5.0 - sets __STDC__ to 0, but requires "##" for token pasting. - - _AIX - gnu ansidecl.h asserts that all known AIX compilers are ANSI but - don't always define __STDC__. - - __DECC - current versions of DEC C (5.9 for instance) for alpha are ANSI, - but don't define __STDC__ in their default mode. Don't know if old - versions might have been K&R, but let's not worry about that unless - someone is still using one. - - _mips - gnu ansidecl.h says the RISC/OS MIPS compiler is ANSI in SVR4 - mode, but doesn't define __STDC__. - - _MSC_VER - Microsoft C is ANSI, but __STDC__ is undefined unless the /Za - option is given (in which case it's 1). - - _WIN32 - tested for by gnu ansidecl.h, no doubt on the assumption that - all w32 compilers are ansi. - - Note: This same set of tests is used by gen-psqr.c and - demos/expr/expr-impl.h, so if anything needs adding, then be sure to - update those too. */ - -#if defined (__STDC__) \ - || defined (__cplusplus) \ - || defined (_AIX) \ - || defined (__DECC) \ - || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ - || defined (_MSC_VER) \ - || defined (_WIN32) -#define __GMP_HAVE_CONST 1 -#define __GMP_HAVE_PROTOTYPES 1 -#define __GMP_HAVE_TOKEN_PASTE 1 -#else -#define __GMP_HAVE_CONST 0 -#define __GMP_HAVE_PROTOTYPES 0 -#define __GMP_HAVE_TOKEN_PASTE 0 -#endif - - -#if __GMP_HAVE_CONST -#define __gmp_const const -#define __gmp_signed signed -#else -#define __gmp_const -#define __gmp_signed -#endif - - /* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in all other circumstances. @@ -124,9 +74,6 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ indicates when building libgmpxx, and in that case libgmpxx functions are exports, but libgmp functions which might get called are imports. - libmp.la uses __GMP_DECLSPEC, just as if it were libgmp.la. libgmp and - libmp don't call each other, so there's no conflict or confusion. - Libtool DLL_EXPORT define is not used. There's no attempt to support GMP built both static and DLL. Doing so @@ -170,7 +117,7 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #endif #if __GMP_LIBGMP_DLL -#if __GMP_WITHIN_GMP +#ifdef __GMP_WITHIN_GMP /* compiling to go into a DLL libgmp */ #define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT #else @@ -195,6 +142,7 @@ typedef unsigned long int mp_limb_t; typedef long int mp_limb_signed_t; #endif #endif +typedef unsigned long int mp_bitcnt_t; /* For reference, note that the name __mpz_struct gets into C++ mangled function names, which means although the "__" suggests an internal, we @@ -216,7 +164,7 @@ typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ typedef __mpz_struct mpz_t[1]; typedef mp_limb_t * mp_ptr; -typedef __gmp_const mp_limb_t * mp_srcptr; +typedef const mp_limb_t * mp_srcptr; #if defined (_CRAY) && ! defined (_CRAYMPP) /* plain `int' is much faster (48 bits) */ #define __GMP_MP_SIZE_T_INT 1 @@ -273,18 +221,16 @@ typedef __gmp_randstate_struct gmp_randstate_t[1]; /* Types for function declarations in gmp files. */ /* ??? Should not pollute user name space with these ??? */ -typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef const __mpz_struct *mpz_srcptr; typedef __mpz_struct *mpz_ptr; -typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef const __mpf_struct *mpf_srcptr; typedef __mpf_struct *mpf_ptr; -typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef const __mpq_struct *mpq_srcptr; typedef __mpq_struct *mpq_ptr; -/* This is not wanted in mp.h, so put it outside the __GNU_MP__ common - section. */ #if __GMP_LIBGMP_DLL -#if __GMP_WITHIN_GMPXX +#ifdef __GMP_WITHIN_GMPXX /* compiling to go into a DLL libgmpxx */ #define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT #else @@ -297,18 +243,8 @@ typedef __mpq_struct *mpq_ptr; #endif -#if __GMP_HAVE_PROTOTYPES -#define __GMP_PROTO(x) x -#else -#define __GMP_PROTO(x) () -#endif - #ifndef __MPN -#if __GMP_HAVE_TOKEN_PASTE #define __MPN(x) __gmpn_##x -#else -#define __MPN(x) __gmpn_/**/x -#endif #endif /* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, @@ -326,7 +262,9 @@ typedef __mpq_struct *mpq_ptr; || defined (__STDIO__) /* Apple MPW MrC */ \ || defined (_MSL_STDIO_H) /* Metrowerks */ \ || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ - || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \ + || defined (__STDIO_LOADED) /* VMS */ \ + || defined (__DEFINED_FILE) /* musl */ #define _GMP_H_HAVE_FILE 1 #endif @@ -338,16 +276,14 @@ typedef __mpq_struct *mpq_ptr; #define _GMP_H_HAVE_OBSTACK 1 #endif -/* The prototypes for gmp_vprintf etc are provided only if va_list is - available, via an application having included <stdarg.h> or <varargs.h>. - Usually va_list is a typedef so can't be tested directly, but C99 - specifies that va_start is a macro (and it was normally a macro on past - systems too), so look for that. +/* The prototypes for gmp_vprintf etc are provided only if va_list is defined, + via an application having included <stdarg.h>. Usually va_list is a typedef + so can't be tested directly, but C99 specifies that va_start is a macro. <stdio.h> will define some sort of va_list for vprintf and vfprintf, but let's not bother trying to use that since it's not standard and since application uses for gmp_vprintf etc will almost certainly require the - whole <stdarg.h> or <varargs.h> anyway. */ + whole <stdarg.h> anyway. */ #ifdef va_start #define _GMP_H_HAVE_VA_LIST 1 @@ -421,7 +357,8 @@ typedef __mpq_struct *mpq_ptr; GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 inline semantics, unless -fgnu89-inline is used. */ #ifdef __GNUC__ -#if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2) +#if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2) \ + || (defined __GNUC_GNU_INLINE__ && defined __cplusplus) #define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__)) #else #define __GMP_EXTERN_INLINE extern __inline__ @@ -460,13 +397,13 @@ typedef __mpq_struct *mpq_ptr; #define __GMP_EXTERN_INLINE __inline #endif -/* Recent enough Sun C compilers accept "extern inline" */ +/* Recent enough Sun C compilers want "inline" */ #if defined (__SUNPRO_C) && __SUNPRO_C >= 0x560 \ && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE extern inline +#define __GMP_EXTERN_INLINE inline #endif -/* Somewhat older Sun C compilers accept "static inline" */ +/* Somewhat older Sun C compilers want "static inline" */ #if defined (__SUNPRO_C) && __SUNPRO_C >= 0x540 \ && ! defined (__GMP_EXTERN_INLINE) #define __GMP_EXTERN_INLINE static inline @@ -505,12 +442,6 @@ typedef __mpq_struct *mpq_ptr; #define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) #define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) -/* __GMP_USHRT_MAX is not "~ (unsigned short) 0" because short is promoted - to int by "~". */ -#define __GMP_UINT_MAX (~ (unsigned) 0) -#define __GMP_ULONG_MAX (~ (unsigned long) 0) -#define __GMP_USHRT_MAX ((unsigned short) ~0) - /* __builtin_expect is in gcc 3.0, and not in 2.95. */ #if __GMP_GNUC_PREREQ (3,0) @@ -528,7 +459,7 @@ typedef __mpq_struct *mpq_ptr; #endif -/* Allow direct user access to numerator and denominator of a mpq_t object. */ +/* Allow direct user access to numerator and denominator of an mpq_t object. */ #define mpq_numref(Q) (&((Q)->_mp_num)) #define mpq_denref(Q) (&((Q)->_mp_den)) @@ -539,116 +470,114 @@ using std::FILE; #endif #define mp_set_memory_functions __gmp_set_memory_functions -__GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), +__GMP_DECLSPEC void mp_set_memory_functions (void *(*) (size_t), void *(*) (void *, size_t, size_t), - void (*) (void *, size_t))) __GMP_NOTHROW; + void (*) (void *, size_t)) __GMP_NOTHROW; #define mp_get_memory_functions __gmp_get_memory_functions -__GMP_DECLSPEC void mp_get_memory_functions __GMP_PROTO ((void *(**) (size_t), - void *(**) (void *, size_t, size_t), - void (**) (void *, size_t))) __GMP_NOTHROW; +__GMP_DECLSPEC void mp_get_memory_functions (void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t)) __GMP_NOTHROW; #define mp_bits_per_limb __gmp_bits_per_limb -__GMP_DECLSPEC extern __gmp_const int mp_bits_per_limb; +__GMP_DECLSPEC extern const int mp_bits_per_limb; #define gmp_errno __gmp_errno __GMP_DECLSPEC extern int gmp_errno; #define gmp_version __gmp_version -__GMP_DECLSPEC extern __gmp_const char * __gmp_const gmp_version; +__GMP_DECLSPEC extern const char * const gmp_version; /**************** Random number routines. ****************/ /* obsolete */ #define gmp_randinit __gmp_randinit -__GMP_DECLSPEC void gmp_randinit __GMP_PROTO ((gmp_randstate_t, gmp_randalg_t, ...)); +__GMP_DECLSPEC void gmp_randinit (gmp_randstate_t, gmp_randalg_t, ...); #define gmp_randinit_default __gmp_randinit_default -__GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); +__GMP_DECLSPEC void gmp_randinit_default (gmp_randstate_t); #define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp -__GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, - mpz_srcptr, unsigned long int, - unsigned long int)); +__GMP_DECLSPEC void gmp_randinit_lc_2exp (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t); #define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size -__GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, unsigned long)); +__GMP_DECLSPEC int gmp_randinit_lc_2exp_size (gmp_randstate_t, mp_bitcnt_t); #define gmp_randinit_mt __gmp_randinit_mt -__GMP_DECLSPEC void gmp_randinit_mt __GMP_PROTO ((gmp_randstate_t)); +__GMP_DECLSPEC void gmp_randinit_mt (gmp_randstate_t); #define gmp_randinit_set __gmp_randinit_set -__GMP_DECLSPEC void gmp_randinit_set __GMP_PROTO ((gmp_randstate_t, __gmp_const __gmp_randstate_struct *)); +__GMP_DECLSPEC void gmp_randinit_set (gmp_randstate_t, const __gmp_randstate_struct *); #define gmp_randseed __gmp_randseed -__GMP_DECLSPEC void gmp_randseed __GMP_PROTO ((gmp_randstate_t, mpz_srcptr)); +__GMP_DECLSPEC void gmp_randseed (gmp_randstate_t, mpz_srcptr); #define gmp_randseed_ui __gmp_randseed_ui -__GMP_DECLSPEC void gmp_randseed_ui __GMP_PROTO ((gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void gmp_randseed_ui (gmp_randstate_t, unsigned long int); #define gmp_randclear __gmp_randclear -__GMP_DECLSPEC void gmp_randclear __GMP_PROTO ((gmp_randstate_t)); +__GMP_DECLSPEC void gmp_randclear (gmp_randstate_t); #define gmp_urandomb_ui __gmp_urandomb_ui -__GMP_DECLSPEC unsigned long gmp_urandomb_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); +__GMP_DECLSPEC unsigned long gmp_urandomb_ui (gmp_randstate_t, unsigned long); #define gmp_urandomm_ui __gmp_urandomm_ui -__GMP_DECLSPEC unsigned long gmp_urandomm_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); +__GMP_DECLSPEC unsigned long gmp_urandomm_ui (gmp_randstate_t, unsigned long); /**************** Formatted output routines. ****************/ #define gmp_asprintf __gmp_asprintf -__GMP_DECLSPEC int gmp_asprintf __GMP_PROTO ((char **, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_asprintf (char **, const char *, ...); #define gmp_fprintf __gmp_fprintf #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fprintf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_fprintf (FILE *, const char *, ...); #endif #define gmp_obstack_printf __gmp_obstack_printf #if defined (_GMP_H_HAVE_OBSTACK) -__GMP_DECLSPEC int gmp_obstack_printf __GMP_PROTO ((struct obstack *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_obstack_printf (struct obstack *, const char *, ...); #endif #define gmp_obstack_vprintf __gmp_obstack_vprintf #if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_obstack_vprintf __GMP_PROTO ((struct obstack *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_obstack_vprintf (struct obstack *, const char *, va_list); #endif #define gmp_printf __gmp_printf -__GMP_DECLSPEC int gmp_printf __GMP_PROTO ((__gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_printf (const char *, ...); #define gmp_snprintf __gmp_snprintf -__GMP_DECLSPEC int gmp_snprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_snprintf (char *, size_t, const char *, ...); #define gmp_sprintf __gmp_sprintf -__GMP_DECLSPEC int gmp_sprintf __GMP_PROTO ((char *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_sprintf (char *, const char *, ...); #define gmp_vasprintf __gmp_vasprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vasprintf __GMP_PROTO ((char **, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vasprintf (char **, const char *, va_list); #endif #define gmp_vfprintf __gmp_vfprintf #if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfprintf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vfprintf (FILE *, const char *, va_list); #endif #define gmp_vprintf __gmp_vprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vprintf __GMP_PROTO ((__gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vprintf (const char *, va_list); #endif #define gmp_vsnprintf __gmp_vsnprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsnprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vsnprintf (char *, size_t, const char *, va_list); #endif #define gmp_vsprintf __gmp_vsprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vsprintf (char *, const char *, va_list); #endif @@ -656,28 +585,28 @@ __GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_lis #define gmp_fscanf __gmp_fscanf #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fscanf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_fscanf (FILE *, const char *, ...); #endif #define gmp_scanf __gmp_scanf -__GMP_DECLSPEC int gmp_scanf __GMP_PROTO ((__gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_scanf (const char *, ...); #define gmp_sscanf __gmp_sscanf -__GMP_DECLSPEC int gmp_sscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_sscanf (const char *, const char *, ...); #define gmp_vfscanf __gmp_vfscanf #if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfscanf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vfscanf (FILE *, const char *, va_list); #endif #define gmp_vscanf __gmp_vscanf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vscanf __GMP_PROTO ((__gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vscanf (const char *, va_list); #endif #define gmp_vsscanf __gmp_vsscanf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vsscanf (const char *, const char *, va_list); #endif @@ -685,790 +614,842 @@ __GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const cha #define _mpz_realloc __gmpz_realloc #define mpz_realloc __gmpz_realloc -__GMP_DECLSPEC void *_mpz_realloc __GMP_PROTO ((mpz_ptr, mp_size_t)); +__GMP_DECLSPEC void *_mpz_realloc (mpz_ptr, mp_size_t); #define mpz_abs __gmpz_abs #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) -__GMP_DECLSPEC void mpz_abs __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_abs (mpz_ptr, mpz_srcptr); #endif #define mpz_add __gmpz_add -__GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_add (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_add_ui __gmpz_add_ui -__GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_add_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_addmul __gmpz_addmul -__GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_addmul (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_addmul_ui __gmpz_addmul_ui -__GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_addmul_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_and __gmpz_and -__GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_and (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_array_init __gmpz_array_init -__GMP_DECLSPEC void mpz_array_init __GMP_PROTO ((mpz_ptr, mp_size_t, mp_size_t)); +__GMP_DECLSPEC void mpz_array_init (mpz_ptr, mp_size_t, mp_size_t); #define mpz_bin_ui __gmpz_bin_ui -__GMP_DECLSPEC void mpz_bin_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_bin_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_bin_uiui __gmpz_bin_uiui -__GMP_DECLSPEC void mpz_bin_uiui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); +__GMP_DECLSPEC void mpz_bin_uiui (mpz_ptr, unsigned long int, unsigned long int); #define mpz_cdiv_q __gmpz_cdiv_q -__GMP_DECLSPEC void mpz_cdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_cdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp -__GMP_DECLSPEC void mpz_cdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_cdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_cdiv_q_ui __gmpz_cdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_cdiv_qr __gmpz_cdiv_qr -__GMP_DECLSPEC void mpz_cdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_cdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_cdiv_r __gmpz_cdiv_r -__GMP_DECLSPEC void mpz_cdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_cdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp -__GMP_DECLSPEC void mpz_cdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_cdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_cdiv_r_ui __gmpz_cdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_cdiv_ui __gmpz_cdiv_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_cdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; #define mpz_clear __gmpz_clear -__GMP_DECLSPEC void mpz_clear __GMP_PROTO ((mpz_ptr)); +__GMP_DECLSPEC void mpz_clear (mpz_ptr); + +#define mpz_clears __gmpz_clears +__GMP_DECLSPEC void mpz_clears (mpz_ptr, ...); #define mpz_clrbit __gmpz_clrbit -__GMP_DECLSPEC void mpz_clrbit __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_clrbit (mpz_ptr, mp_bitcnt_t); #define mpz_cmp __gmpz_cmp -__GMP_DECLSPEC int mpz_cmp __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmp (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_cmp_d __gmpz_cmp_d -__GMP_DECLSPEC int mpz_cmp_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmp_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; #define _mpz_cmp_si __gmpz_cmp_si -__GMP_DECLSPEC int _mpz_cmp_si __GMP_PROTO ((mpz_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpz_cmp_si (mpz_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define _mpz_cmp_ui __gmpz_cmp_ui -__GMP_DECLSPEC int _mpz_cmp_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpz_cmp_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_cmpabs __gmpz_cmpabs -__GMP_DECLSPEC int mpz_cmpabs __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmpabs (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_cmpabs_d __gmpz_cmpabs_d -__GMP_DECLSPEC int mpz_cmpabs_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmpabs_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; #define mpz_cmpabs_ui __gmpz_cmpabs_ui -__GMP_DECLSPEC int mpz_cmpabs_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmpabs_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_com __gmpz_com -__GMP_DECLSPEC void mpz_com __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_com (mpz_ptr, mpz_srcptr); #define mpz_combit __gmpz_combit -__GMP_DECLSPEC void mpz_combit __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_combit (mpz_ptr, mp_bitcnt_t); #define mpz_congruent_p __gmpz_congruent_p -__GMP_DECLSPEC int mpz_congruent_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_congruent_p (mpz_srcptr, mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_congruent_2exp_p __gmpz_congruent_2exp_p -__GMP_DECLSPEC int mpz_congruent_2exp_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_congruent_2exp_p (mpz_srcptr, mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_congruent_ui_p __gmpz_congruent_ui_p -__GMP_DECLSPEC int mpz_congruent_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_congruent_ui_p (mpz_srcptr, unsigned long, unsigned long) __GMP_ATTRIBUTE_PURE; #define mpz_divexact __gmpz_divexact -__GMP_DECLSPEC void mpz_divexact __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_divexact (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_divexact_ui __gmpz_divexact_ui -__GMP_DECLSPEC void mpz_divexact_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_divexact_ui (mpz_ptr, mpz_srcptr, unsigned long); #define mpz_divisible_p __gmpz_divisible_p -__GMP_DECLSPEC int mpz_divisible_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_divisible_p (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_divisible_ui_p __gmpz_divisible_ui_p -__GMP_DECLSPEC int mpz_divisible_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_divisible_ui_p (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; #define mpz_divisible_2exp_p __gmpz_divisible_2exp_p -__GMP_DECLSPEC int mpz_divisible_2exp_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_divisible_2exp_p (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_dump __gmpz_dump -__GMP_DECLSPEC void mpz_dump __GMP_PROTO ((mpz_srcptr)); +__GMP_DECLSPEC void mpz_dump (mpz_srcptr); #define mpz_export __gmpz_export -__GMP_DECLSPEC void *mpz_export __GMP_PROTO ((void *, size_t *, int, size_t, int, size_t, mpz_srcptr)); +__GMP_DECLSPEC void *mpz_export (void *, size_t *, int, size_t, int, size_t, mpz_srcptr); #define mpz_fac_ui __gmpz_fac_ui -__GMP_DECLSPEC void mpz_fac_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fac_ui (mpz_ptr, unsigned long int); + +#define mpz_2fac_ui __gmpz_2fac_ui +__GMP_DECLSPEC void mpz_2fac_ui (mpz_ptr, unsigned long int); + +#define mpz_mfac_uiui __gmpz_mfac_uiui +__GMP_DECLSPEC void mpz_mfac_uiui (mpz_ptr, unsigned long int, unsigned long int); + +#define mpz_primorial_ui __gmpz_primorial_ui +__GMP_DECLSPEC void mpz_primorial_ui (mpz_ptr, unsigned long int); #define mpz_fdiv_q __gmpz_fdiv_q -__GMP_DECLSPEC void mpz_fdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_fdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp -__GMP_DECLSPEC void mpz_fdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_fdiv_q_ui __gmpz_fdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_fdiv_qr __gmpz_fdiv_qr -__GMP_DECLSPEC void mpz_fdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_fdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_fdiv_r __gmpz_fdiv_r -__GMP_DECLSPEC void mpz_fdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_fdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp -__GMP_DECLSPEC void mpz_fdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_fdiv_r_ui __gmpz_fdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_fdiv_ui __gmpz_fdiv_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_fdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; #define mpz_fib_ui __gmpz_fib_ui -__GMP_DECLSPEC void mpz_fib_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fib_ui (mpz_ptr, unsigned long int); #define mpz_fib2_ui __gmpz_fib2_ui -__GMP_DECLSPEC void mpz_fib2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fib2_ui (mpz_ptr, mpz_ptr, unsigned long int); #define mpz_fits_sint_p __gmpz_fits_sint_p -__GMP_DECLSPEC int mpz_fits_sint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_sint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_fits_slong_p __gmpz_fits_slong_p -__GMP_DECLSPEC int mpz_fits_slong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_slong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_fits_sshort_p __gmpz_fits_sshort_p -__GMP_DECLSPEC int mpz_fits_sshort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_sshort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_fits_uint_p __gmpz_fits_uint_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) -__GMP_DECLSPEC int mpz_fits_uint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_uint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_fits_ulong_p __gmpz_fits_ulong_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) -__GMP_DECLSPEC int mpz_fits_ulong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_ulong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_fits_ushort_p __gmpz_fits_ushort_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) -__GMP_DECLSPEC int mpz_fits_ushort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_ushort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_gcd __gmpz_gcd -__GMP_DECLSPEC void mpz_gcd __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_gcd (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_gcd_ui __gmpz_gcd_ui -__GMP_DECLSPEC unsigned long int mpz_gcd_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_gcd_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_gcdext __gmpz_gcdext -__GMP_DECLSPEC void mpz_gcdext __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_gcdext (mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_get_d __gmpz_get_d -__GMP_DECLSPEC double mpz_get_d __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC double mpz_get_d (mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_get_d_2exp __gmpz_get_d_2exp -__GMP_DECLSPEC double mpz_get_d_2exp __GMP_PROTO ((signed long int *, mpz_srcptr)); +__GMP_DECLSPEC double mpz_get_d_2exp (signed long int *, mpz_srcptr); #define mpz_get_si __gmpz_get_si -__GMP_DECLSPEC /* signed */ long int mpz_get_si __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC /* signed */ long int mpz_get_si (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_get_str __gmpz_get_str -__GMP_DECLSPEC char *mpz_get_str __GMP_PROTO ((char *, int, mpz_srcptr)); +__GMP_DECLSPEC char *mpz_get_str (char *, int, mpz_srcptr); #define mpz_get_ui __gmpz_get_ui #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) -__GMP_DECLSPEC unsigned long int mpz_get_ui __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_get_ui (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_getlimbn __gmpz_getlimbn #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) -__GMP_DECLSPEC mp_limb_t mpz_getlimbn __GMP_PROTO ((mpz_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpz_getlimbn (mpz_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_hamdist __gmpz_hamdist -__GMP_DECLSPEC unsigned long int mpz_hamdist __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_hamdist (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_import __gmpz_import -__GMP_DECLSPEC void mpz_import __GMP_PROTO ((mpz_ptr, size_t, int, size_t, int, size_t, __gmp_const void *)); +__GMP_DECLSPEC void mpz_import (mpz_ptr, size_t, int, size_t, int, size_t, const void *); #define mpz_init __gmpz_init -__GMP_DECLSPEC void mpz_init __GMP_PROTO ((mpz_ptr)); +__GMP_DECLSPEC void mpz_init (mpz_ptr); #define mpz_init2 __gmpz_init2 -__GMP_DECLSPEC void mpz_init2 __GMP_PROTO ((mpz_ptr, unsigned long)); +__GMP_DECLSPEC void mpz_init2 (mpz_ptr, mp_bitcnt_t); + +#define mpz_inits __gmpz_inits +__GMP_DECLSPEC void mpz_inits (mpz_ptr, ...); #define mpz_init_set __gmpz_init_set -__GMP_DECLSPEC void mpz_init_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_init_set (mpz_ptr, mpz_srcptr); #define mpz_init_set_d __gmpz_init_set_d -__GMP_DECLSPEC void mpz_init_set_d __GMP_PROTO ((mpz_ptr, double)); +__GMP_DECLSPEC void mpz_init_set_d (mpz_ptr, double); #define mpz_init_set_si __gmpz_init_set_si -__GMP_DECLSPEC void mpz_init_set_si __GMP_PROTO ((mpz_ptr, signed long int)); +__GMP_DECLSPEC void mpz_init_set_si (mpz_ptr, signed long int); #define mpz_init_set_str __gmpz_init_set_str -__GMP_DECLSPEC int mpz_init_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpz_init_set_str (mpz_ptr, const char *, int); #define mpz_init_set_ui __gmpz_init_set_ui -__GMP_DECLSPEC void mpz_init_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_init_set_ui (mpz_ptr, unsigned long int); #define mpz_inp_raw __gmpz_inp_raw #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_raw __GMP_PROTO ((mpz_ptr, FILE *)); +__GMP_DECLSPEC size_t mpz_inp_raw (mpz_ptr, FILE *); #endif #define mpz_inp_str __gmpz_inp_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_str __GMP_PROTO ((mpz_ptr, FILE *, int)); +__GMP_DECLSPEC size_t mpz_inp_str (mpz_ptr, FILE *, int); #endif #define mpz_invert __gmpz_invert -__GMP_DECLSPEC int mpz_invert __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC int mpz_invert (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_ior __gmpz_ior -__GMP_DECLSPEC void mpz_ior __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_ior (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_jacobi __gmpz_jacobi -__GMP_DECLSPEC int mpz_jacobi __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_jacobi (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_kronecker mpz_jacobi /* alias */ #define mpz_kronecker_si __gmpz_kronecker_si -__GMP_DECLSPEC int mpz_kronecker_si __GMP_PROTO ((mpz_srcptr, long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_kronecker_si (mpz_srcptr, long) __GMP_ATTRIBUTE_PURE; #define mpz_kronecker_ui __gmpz_kronecker_ui -__GMP_DECLSPEC int mpz_kronecker_ui __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_kronecker_ui (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; #define mpz_si_kronecker __gmpz_si_kronecker -__GMP_DECLSPEC int mpz_si_kronecker __GMP_PROTO ((long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_si_kronecker (long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_ui_kronecker __gmpz_ui_kronecker -__GMP_DECLSPEC int mpz_ui_kronecker __GMP_PROTO ((unsigned long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_ui_kronecker (unsigned long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_lcm __gmpz_lcm -__GMP_DECLSPEC void mpz_lcm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_lcm (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_lcm_ui __gmpz_lcm_ui -__GMP_DECLSPEC void mpz_lcm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_lcm_ui (mpz_ptr, mpz_srcptr, unsigned long); #define mpz_legendre mpz_jacobi /* alias */ #define mpz_lucnum_ui __gmpz_lucnum_ui -__GMP_DECLSPEC void mpz_lucnum_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_lucnum_ui (mpz_ptr, unsigned long int); #define mpz_lucnum2_ui __gmpz_lucnum2_ui -__GMP_DECLSPEC void mpz_lucnum2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_lucnum2_ui (mpz_ptr, mpz_ptr, unsigned long int); #define mpz_millerrabin __gmpz_millerrabin -__GMP_DECLSPEC int mpz_millerrabin __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_millerrabin (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; #define mpz_mod __gmpz_mod -__GMP_DECLSPEC void mpz_mod __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_mod (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ #define mpz_mul __gmpz_mul -__GMP_DECLSPEC void mpz_mul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_mul (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_mul_2exp __gmpz_mul_2exp -__GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_mul_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_mul_si __gmpz_mul_si -__GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int)); +__GMP_DECLSPEC void mpz_mul_si (mpz_ptr, mpz_srcptr, long int); #define mpz_mul_ui __gmpz_mul_ui -__GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_mul_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_neg __gmpz_neg #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) -__GMP_DECLSPEC void mpz_neg __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_neg (mpz_ptr, mpz_srcptr); #endif #define mpz_nextprime __gmpz_nextprime -__GMP_DECLSPEC void mpz_nextprime __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_nextprime (mpz_ptr, mpz_srcptr); #define mpz_out_raw __gmpz_out_raw #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_raw __GMP_PROTO ((FILE *, mpz_srcptr)); +__GMP_DECLSPEC size_t mpz_out_raw (FILE *, mpz_srcptr); #endif #define mpz_out_str __gmpz_out_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_str __GMP_PROTO ((FILE *, int, mpz_srcptr)); +__GMP_DECLSPEC size_t mpz_out_str (FILE *, int, mpz_srcptr); #endif #define mpz_perfect_power_p __gmpz_perfect_power_p -__GMP_DECLSPEC int mpz_perfect_power_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_perfect_power_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_perfect_square_p __gmpz_perfect_square_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) -__GMP_DECLSPEC int mpz_perfect_square_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_perfect_square_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; #endif #define mpz_popcount __gmpz_popcount #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) -__GMP_DECLSPEC unsigned long int mpz_popcount __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_popcount (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_pow_ui __gmpz_pow_ui -__GMP_DECLSPEC void mpz_pow_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_pow_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_powm __gmpz_powm -__GMP_DECLSPEC void mpz_powm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_powm (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); + +#define mpz_powm_sec __gmpz_powm_sec +__GMP_DECLSPEC void mpz_powm_sec (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); #define mpz_powm_ui __gmpz_powm_ui -__GMP_DECLSPEC void mpz_powm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); +__GMP_DECLSPEC void mpz_powm_ui (mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr); #define mpz_probab_prime_p __gmpz_probab_prime_p -__GMP_DECLSPEC int mpz_probab_prime_p __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_probab_prime_p (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; #define mpz_random __gmpz_random -__GMP_DECLSPEC void mpz_random __GMP_PROTO ((mpz_ptr, mp_size_t)); +__GMP_DECLSPEC void mpz_random (mpz_ptr, mp_size_t); #define mpz_random2 __gmpz_random2 -__GMP_DECLSPEC void mpz_random2 __GMP_PROTO ((mpz_ptr, mp_size_t)); +__GMP_DECLSPEC void mpz_random2 (mpz_ptr, mp_size_t); #define mpz_realloc2 __gmpz_realloc2 -__GMP_DECLSPEC void mpz_realloc2 __GMP_PROTO ((mpz_ptr, unsigned long)); +__GMP_DECLSPEC void mpz_realloc2 (mpz_ptr, mp_bitcnt_t); #define mpz_remove __gmpz_remove -__GMP_DECLSPEC unsigned long int mpz_remove __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC mp_bitcnt_t mpz_remove (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_root __gmpz_root -__GMP_DECLSPEC int mpz_root __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC int mpz_root (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_rootrem __gmpz_rootrem -__GMP_DECLSPEC void mpz_rootrem __GMP_PROTO ((mpz_ptr,mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_rootrem (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_rrandomb __gmpz_rrandomb -__GMP_DECLSPEC void mpz_rrandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void mpz_rrandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); #define mpz_scan0 __gmpz_scan0 -__GMP_DECLSPEC unsigned long int mpz_scan0 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_scan0 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_scan1 __gmpz_scan1 -__GMP_DECLSPEC unsigned long int mpz_scan1 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_scan1 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_set __gmpz_set -__GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_set (mpz_ptr, mpz_srcptr); #define mpz_set_d __gmpz_set_d -__GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double)); +__GMP_DECLSPEC void mpz_set_d (mpz_ptr, double); #define mpz_set_f __gmpz_set_f -__GMP_DECLSPEC void mpz_set_f __GMP_PROTO ((mpz_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpz_set_f (mpz_ptr, mpf_srcptr); #define mpz_set_q __gmpz_set_q #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) -__GMP_DECLSPEC void mpz_set_q __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpz_set_q (mpz_ptr, mpq_srcptr); #endif #define mpz_set_si __gmpz_set_si -__GMP_DECLSPEC void mpz_set_si __GMP_PROTO ((mpz_ptr, signed long int)); +__GMP_DECLSPEC void mpz_set_si (mpz_ptr, signed long int); #define mpz_set_str __gmpz_set_str -__GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpz_set_str (mpz_ptr, const char *, int); #define mpz_set_ui __gmpz_set_ui -__GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_set_ui (mpz_ptr, unsigned long int); #define mpz_setbit __gmpz_setbit -__GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_setbit (mpz_ptr, mp_bitcnt_t); #define mpz_size __gmpz_size #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) -__GMP_DECLSPEC size_t mpz_size __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC size_t mpz_size (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_sizeinbase __gmpz_sizeinbase -__GMP_DECLSPEC size_t mpz_sizeinbase __GMP_PROTO ((mpz_srcptr, int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC size_t mpz_sizeinbase (mpz_srcptr, int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_sqrt __gmpz_sqrt -__GMP_DECLSPEC void mpz_sqrt __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_sqrt (mpz_ptr, mpz_srcptr); #define mpz_sqrtrem __gmpz_sqrtrem -__GMP_DECLSPEC void mpz_sqrtrem __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_sqrtrem (mpz_ptr, mpz_ptr, mpz_srcptr); #define mpz_sub __gmpz_sub -__GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_sub (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_sub_ui __gmpz_sub_ui -__GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_sub_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_ui_sub __gmpz_ui_sub -__GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, unsigned long int, mpz_srcptr)); +__GMP_DECLSPEC void mpz_ui_sub (mpz_ptr, unsigned long int, mpz_srcptr); #define mpz_submul __gmpz_submul -__GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_submul (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_submul_ui __gmpz_submul_ui -__GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_submul_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_swap __gmpz_swap -__GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpz_swap (mpz_ptr, mpz_ptr) __GMP_NOTHROW; #define mpz_tdiv_ui __gmpz_tdiv_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_tdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; #define mpz_tdiv_q __gmpz_tdiv_q -__GMP_DECLSPEC void mpz_tdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_tdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp -__GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_tdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_tdiv_q_ui __gmpz_tdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_tdiv_qr __gmpz_tdiv_qr -__GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_tdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_tdiv_r __gmpz_tdiv_r -__GMP_DECLSPEC void mpz_tdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_tdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp -__GMP_DECLSPEC void mpz_tdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_tdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_tdiv_r_ui __gmpz_tdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_tstbit __gmpz_tstbit -__GMP_DECLSPEC int mpz_tstbit __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_tstbit (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_ui_pow_ui __gmpz_ui_pow_ui -__GMP_DECLSPEC void mpz_ui_pow_ui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); +__GMP_DECLSPEC void mpz_ui_pow_ui (mpz_ptr, unsigned long int, unsigned long int); #define mpz_urandomb __gmpz_urandomb -__GMP_DECLSPEC void mpz_urandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void mpz_urandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); #define mpz_urandomm __gmpz_urandomm -__GMP_DECLSPEC void mpz_urandomm __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mpz_srcptr)); +__GMP_DECLSPEC void mpz_urandomm (mpz_ptr, gmp_randstate_t, mpz_srcptr); #define mpz_xor __gmpz_xor #define mpz_eor __gmpz_xor -__GMP_DECLSPEC void mpz_xor __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_xor (mpz_ptr, mpz_srcptr, mpz_srcptr); +#define mpz_limbs_read __gmpz_limbs_read +__GMP_DECLSPEC mp_srcptr mpz_limbs_read (mpz_srcptr); + +#define mpz_limbs_write __gmpz_limbs_write +__GMP_DECLSPEC mp_ptr mpz_limbs_write (mpz_ptr, mp_size_t); + +#define mpz_limbs_modify __gmpz_limbs_modify +__GMP_DECLSPEC mp_ptr mpz_limbs_modify (mpz_ptr, mp_size_t); + +#define mpz_limbs_finish __gmpz_limbs_finish +__GMP_DECLSPEC void mpz_limbs_finish (mpz_ptr, mp_size_t); + +#define mpz_roinit_n __gmpz_roinit_n +__GMP_DECLSPEC mpz_srcptr mpz_roinit_n (mpz_ptr, mp_srcptr, mp_size_t); + +#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} /**************** Rational (i.e. Q) routines. ****************/ #define mpq_abs __gmpq_abs #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) -__GMP_DECLSPEC void mpq_abs __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_abs (mpq_ptr, mpq_srcptr); #endif #define mpq_add __gmpq_add -__GMP_DECLSPEC void mpq_add __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_add (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_canonicalize __gmpq_canonicalize -__GMP_DECLSPEC void mpq_canonicalize __GMP_PROTO ((mpq_ptr)); +__GMP_DECLSPEC void mpq_canonicalize (mpq_ptr); #define mpq_clear __gmpq_clear -__GMP_DECLSPEC void mpq_clear __GMP_PROTO ((mpq_ptr)); +__GMP_DECLSPEC void mpq_clear (mpq_ptr); + +#define mpq_clears __gmpq_clears +__GMP_DECLSPEC void mpq_clears (mpq_ptr, ...); #define mpq_cmp __gmpq_cmp -__GMP_DECLSPEC int mpq_cmp __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpq_cmp (mpq_srcptr, mpq_srcptr) __GMP_ATTRIBUTE_PURE; #define _mpq_cmp_si __gmpq_cmp_si -__GMP_DECLSPEC int _mpq_cmp_si __GMP_PROTO ((mpq_srcptr, long, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpq_cmp_si (mpq_srcptr, long, unsigned long) __GMP_ATTRIBUTE_PURE; #define _mpq_cmp_ui __gmpq_cmp_ui -__GMP_DECLSPEC int _mpq_cmp_ui __GMP_PROTO ((mpq_srcptr, unsigned long int, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpq_cmp_ui (mpq_srcptr, unsigned long int, unsigned long int) __GMP_ATTRIBUTE_PURE; + +#define mpq_cmp_z __gmpq_cmp_z +__GMP_DECLSPEC int mpq_cmp_z (mpq_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpq_div __gmpq_div -__GMP_DECLSPEC void mpq_div __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_div (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_div_2exp __gmpq_div_2exp -__GMP_DECLSPEC void mpq_div_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); +__GMP_DECLSPEC void mpq_div_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); #define mpq_equal __gmpq_equal -__GMP_DECLSPEC int mpq_equal __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpq_equal (mpq_srcptr, mpq_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpq_get_num __gmpq_get_num -__GMP_DECLSPEC void mpq_get_num __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_get_num (mpz_ptr, mpq_srcptr); #define mpq_get_den __gmpq_get_den -__GMP_DECLSPEC void mpq_get_den __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_get_den (mpz_ptr, mpq_srcptr); #define mpq_get_d __gmpq_get_d -__GMP_DECLSPEC double mpq_get_d __GMP_PROTO ((mpq_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC double mpq_get_d (mpq_srcptr) __GMP_ATTRIBUTE_PURE; #define mpq_get_str __gmpq_get_str -__GMP_DECLSPEC char *mpq_get_str __GMP_PROTO ((char *, int, mpq_srcptr)); +__GMP_DECLSPEC char *mpq_get_str (char *, int, mpq_srcptr); #define mpq_init __gmpq_init -__GMP_DECLSPEC void mpq_init __GMP_PROTO ((mpq_ptr)); +__GMP_DECLSPEC void mpq_init (mpq_ptr); + +#define mpq_inits __gmpq_inits +__GMP_DECLSPEC void mpq_inits (mpq_ptr, ...); #define mpq_inp_str __gmpq_inp_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_inp_str __GMP_PROTO ((mpq_ptr, FILE *, int)); +__GMP_DECLSPEC size_t mpq_inp_str (mpq_ptr, FILE *, int); #endif #define mpq_inv __gmpq_inv -__GMP_DECLSPEC void mpq_inv __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_inv (mpq_ptr, mpq_srcptr); #define mpq_mul __gmpq_mul -__GMP_DECLSPEC void mpq_mul __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_mul (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_mul_2exp __gmpq_mul_2exp -__GMP_DECLSPEC void mpq_mul_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); +__GMP_DECLSPEC void mpq_mul_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); #define mpq_neg __gmpq_neg #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) -__GMP_DECLSPEC void mpq_neg __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_neg (mpq_ptr, mpq_srcptr); #endif #define mpq_out_str __gmpq_out_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr)); +__GMP_DECLSPEC size_t mpq_out_str (FILE *, int, mpq_srcptr); #endif #define mpq_set __gmpq_set -__GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_set (mpq_ptr, mpq_srcptr); #define mpq_set_d __gmpq_set_d -__GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double)); +__GMP_DECLSPEC void mpq_set_d (mpq_ptr, double); #define mpq_set_den __gmpq_set_den -__GMP_DECLSPEC void mpq_set_den __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpq_set_den (mpq_ptr, mpz_srcptr); #define mpq_set_f __gmpq_set_f -__GMP_DECLSPEC void mpq_set_f __GMP_PROTO ((mpq_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpq_set_f (mpq_ptr, mpf_srcptr); #define mpq_set_num __gmpq_set_num -__GMP_DECLSPEC void mpq_set_num __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpq_set_num (mpq_ptr, mpz_srcptr); #define mpq_set_si __gmpq_set_si -__GMP_DECLSPEC void mpq_set_si __GMP_PROTO ((mpq_ptr, signed long int, unsigned long int)); +__GMP_DECLSPEC void mpq_set_si (mpq_ptr, signed long int, unsigned long int); #define mpq_set_str __gmpq_set_str -__GMP_DECLSPEC int mpq_set_str __GMP_PROTO ((mpq_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpq_set_str (mpq_ptr, const char *, int); #define mpq_set_ui __gmpq_set_ui -__GMP_DECLSPEC void mpq_set_ui __GMP_PROTO ((mpq_ptr, unsigned long int, unsigned long int)); +__GMP_DECLSPEC void mpq_set_ui (mpq_ptr, unsigned long int, unsigned long int); #define mpq_set_z __gmpq_set_z -__GMP_DECLSPEC void mpq_set_z __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpq_set_z (mpq_ptr, mpz_srcptr); #define mpq_sub __gmpq_sub -__GMP_DECLSPEC void mpq_sub __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_sub (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_swap __gmpq_swap -__GMP_DECLSPEC void mpq_swap __GMP_PROTO ((mpq_ptr, mpq_ptr)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpq_swap (mpq_ptr, mpq_ptr) __GMP_NOTHROW; /**************** Float (i.e. F) routines. ****************/ #define mpf_abs __gmpf_abs -__GMP_DECLSPEC void mpf_abs __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_abs (mpf_ptr, mpf_srcptr); #define mpf_add __gmpf_add -__GMP_DECLSPEC void mpf_add __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_add (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_add_ui __gmpf_add_ui -__GMP_DECLSPEC void mpf_add_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_add_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_ceil __gmpf_ceil -__GMP_DECLSPEC void mpf_ceil __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_ceil (mpf_ptr, mpf_srcptr); #define mpf_clear __gmpf_clear -__GMP_DECLSPEC void mpf_clear __GMP_PROTO ((mpf_ptr)); +__GMP_DECLSPEC void mpf_clear (mpf_ptr); + +#define mpf_clears __gmpf_clears +__GMP_DECLSPEC void mpf_clears (mpf_ptr, ...); #define mpf_cmp __gmpf_cmp -__GMP_DECLSPEC int mpf_cmp __GMP_PROTO ((mpf_srcptr, mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp (mpf_srcptr, mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_z __gmpf_cmp_z +__GMP_DECLSPEC int mpf_cmp_z (mpf_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_cmp_d __gmpf_cmp_d -__GMP_DECLSPEC int mpf_cmp_d __GMP_PROTO ((mpf_srcptr, double)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp_d (mpf_srcptr, double) __GMP_ATTRIBUTE_PURE; #define mpf_cmp_si __gmpf_cmp_si -__GMP_DECLSPEC int mpf_cmp_si __GMP_PROTO ((mpf_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp_si (mpf_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_cmp_ui __gmpf_cmp_ui -__GMP_DECLSPEC int mpf_cmp_ui __GMP_PROTO ((mpf_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp_ui (mpf_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_div __gmpf_div -__GMP_DECLSPEC void mpf_div __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_div (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_div_2exp __gmpf_div_2exp -__GMP_DECLSPEC void mpf_div_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_div_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); #define mpf_div_ui __gmpf_div_ui -__GMP_DECLSPEC void mpf_div_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_div_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_dump __gmpf_dump -__GMP_DECLSPEC void mpf_dump __GMP_PROTO ((mpf_srcptr)); +__GMP_DECLSPEC void mpf_dump (mpf_srcptr); #define mpf_eq __gmpf_eq -__GMP_DECLSPEC int mpf_eq __GMP_PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_eq (mpf_srcptr, mpf_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; #define mpf_fits_sint_p __gmpf_fits_sint_p -__GMP_DECLSPEC int mpf_fits_sint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_sint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_slong_p __gmpf_fits_slong_p -__GMP_DECLSPEC int mpf_fits_slong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_slong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_sshort_p __gmpf_fits_sshort_p -__GMP_DECLSPEC int mpf_fits_sshort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_sshort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_uint_p __gmpf_fits_uint_p -__GMP_DECLSPEC int mpf_fits_uint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_uint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_ulong_p __gmpf_fits_ulong_p -__GMP_DECLSPEC int mpf_fits_ulong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_ulong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_ushort_p __gmpf_fits_ushort_p -__GMP_DECLSPEC int mpf_fits_ushort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_ushort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_floor __gmpf_floor -__GMP_DECLSPEC void mpf_floor __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_floor (mpf_ptr, mpf_srcptr); #define mpf_get_d __gmpf_get_d -__GMP_DECLSPEC double mpf_get_d __GMP_PROTO ((mpf_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC double mpf_get_d (mpf_srcptr) __GMP_ATTRIBUTE_PURE; #define mpf_get_d_2exp __gmpf_get_d_2exp -__GMP_DECLSPEC double mpf_get_d_2exp __GMP_PROTO ((signed long int *, mpf_srcptr)); +__GMP_DECLSPEC double mpf_get_d_2exp (signed long int *, mpf_srcptr); #define mpf_get_default_prec __gmpf_get_default_prec -__GMP_DECLSPEC unsigned long int mpf_get_default_prec __GMP_PROTO ((void)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpf_get_default_prec (void) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_get_prec __gmpf_get_prec -__GMP_DECLSPEC unsigned long int mpf_get_prec __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpf_get_prec (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_get_si __gmpf_get_si -__GMP_DECLSPEC long mpf_get_si __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC long mpf_get_si (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_get_str __gmpf_get_str -__GMP_DECLSPEC char *mpf_get_str __GMP_PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); +__GMP_DECLSPEC char *mpf_get_str (char *, mp_exp_t *, int, size_t, mpf_srcptr); #define mpf_get_ui __gmpf_get_ui -__GMP_DECLSPEC unsigned long mpf_get_ui __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long mpf_get_ui (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_init __gmpf_init -__GMP_DECLSPEC void mpf_init __GMP_PROTO ((mpf_ptr)); +__GMP_DECLSPEC void mpf_init (mpf_ptr); #define mpf_init2 __gmpf_init2 -__GMP_DECLSPEC void mpf_init2 __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_init2 (mpf_ptr, mp_bitcnt_t); + +#define mpf_inits __gmpf_inits +__GMP_DECLSPEC void mpf_inits (mpf_ptr, ...); #define mpf_init_set __gmpf_init_set -__GMP_DECLSPEC void mpf_init_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_init_set (mpf_ptr, mpf_srcptr); #define mpf_init_set_d __gmpf_init_set_d -__GMP_DECLSPEC void mpf_init_set_d __GMP_PROTO ((mpf_ptr, double)); +__GMP_DECLSPEC void mpf_init_set_d (mpf_ptr, double); #define mpf_init_set_si __gmpf_init_set_si -__GMP_DECLSPEC void mpf_init_set_si __GMP_PROTO ((mpf_ptr, signed long int)); +__GMP_DECLSPEC void mpf_init_set_si (mpf_ptr, signed long int); #define mpf_init_set_str __gmpf_init_set_str -__GMP_DECLSPEC int mpf_init_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpf_init_set_str (mpf_ptr, const char *, int); #define mpf_init_set_ui __gmpf_init_set_ui -__GMP_DECLSPEC void mpf_init_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_init_set_ui (mpf_ptr, unsigned long int); #define mpf_inp_str __gmpf_inp_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_inp_str __GMP_PROTO ((mpf_ptr, FILE *, int)); +__GMP_DECLSPEC size_t mpf_inp_str (mpf_ptr, FILE *, int); #endif #define mpf_integer_p __gmpf_integer_p -__GMP_DECLSPEC int mpf_integer_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_integer_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_mul __gmpf_mul -__GMP_DECLSPEC void mpf_mul __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_mul (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_mul_2exp __gmpf_mul_2exp -__GMP_DECLSPEC void mpf_mul_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_mul_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); #define mpf_mul_ui __gmpf_mul_ui -__GMP_DECLSPEC void mpf_mul_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_mul_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_neg __gmpf_neg -__GMP_DECLSPEC void mpf_neg __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_neg (mpf_ptr, mpf_srcptr); #define mpf_out_str __gmpf_out_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_out_str __GMP_PROTO ((FILE *, int, size_t, mpf_srcptr)); +__GMP_DECLSPEC size_t mpf_out_str (FILE *, int, size_t, mpf_srcptr); #endif #define mpf_pow_ui __gmpf_pow_ui -__GMP_DECLSPEC void mpf_pow_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_pow_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_random2 __gmpf_random2 -__GMP_DECLSPEC void mpf_random2 __GMP_PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); +__GMP_DECLSPEC void mpf_random2 (mpf_ptr, mp_size_t, mp_exp_t); #define mpf_reldiff __gmpf_reldiff -__GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_reldiff (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_set __gmpf_set -__GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_set (mpf_ptr, mpf_srcptr); #define mpf_set_d __gmpf_set_d -__GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double)); +__GMP_DECLSPEC void mpf_set_d (mpf_ptr, double); #define mpf_set_default_prec __gmpf_set_default_prec -__GMP_DECLSPEC void mpf_set_default_prec __GMP_PROTO ((unsigned long int)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpf_set_default_prec (mp_bitcnt_t) __GMP_NOTHROW; #define mpf_set_prec __gmpf_set_prec -__GMP_DECLSPEC void mpf_set_prec __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_set_prec (mpf_ptr, mp_bitcnt_t); #define mpf_set_prec_raw __gmpf_set_prec_raw -__GMP_DECLSPEC void mpf_set_prec_raw __GMP_PROTO ((mpf_ptr, unsigned long int)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpf_set_prec_raw (mpf_ptr, mp_bitcnt_t) __GMP_NOTHROW; #define mpf_set_q __gmpf_set_q -__GMP_DECLSPEC void mpf_set_q __GMP_PROTO ((mpf_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpf_set_q (mpf_ptr, mpq_srcptr); #define mpf_set_si __gmpf_set_si -__GMP_DECLSPEC void mpf_set_si __GMP_PROTO ((mpf_ptr, signed long int)); +__GMP_DECLSPEC void mpf_set_si (mpf_ptr, signed long int); #define mpf_set_str __gmpf_set_str -__GMP_DECLSPEC int mpf_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpf_set_str (mpf_ptr, const char *, int); #define mpf_set_ui __gmpf_set_ui -__GMP_DECLSPEC void mpf_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_set_ui (mpf_ptr, unsigned long int); #define mpf_set_z __gmpf_set_z -__GMP_DECLSPEC void mpf_set_z __GMP_PROTO ((mpf_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpf_set_z (mpf_ptr, mpz_srcptr); #define mpf_size __gmpf_size -__GMP_DECLSPEC size_t mpf_size __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC size_t mpf_size (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_sqrt __gmpf_sqrt -__GMP_DECLSPEC void mpf_sqrt __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_sqrt (mpf_ptr, mpf_srcptr); #define mpf_sqrt_ui __gmpf_sqrt_ui -__GMP_DECLSPEC void mpf_sqrt_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_sqrt_ui (mpf_ptr, unsigned long int); #define mpf_sub __gmpf_sub -__GMP_DECLSPEC void mpf_sub __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_sub (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_sub_ui __gmpf_sub_ui -__GMP_DECLSPEC void mpf_sub_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_sub_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_swap __gmpf_swap -__GMP_DECLSPEC void mpf_swap __GMP_PROTO ((mpf_ptr, mpf_ptr)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpf_swap (mpf_ptr, mpf_ptr) __GMP_NOTHROW; #define mpf_trunc __gmpf_trunc -__GMP_DECLSPEC void mpf_trunc __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_trunc (mpf_ptr, mpf_srcptr); #define mpf_ui_div __gmpf_ui_div -__GMP_DECLSPEC void mpf_ui_div __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +__GMP_DECLSPEC void mpf_ui_div (mpf_ptr, unsigned long int, mpf_srcptr); #define mpf_ui_sub __gmpf_ui_sub -__GMP_DECLSPEC void mpf_ui_sub __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +__GMP_DECLSPEC void mpf_ui_sub (mpf_ptr, unsigned long int, mpf_srcptr); #define mpf_urandomb __gmpf_urandomb -__GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void mpf_urandomb (mpf_t, gmp_randstate_t, mp_bitcnt_t); /************ Low level positive-integer (i.e. N) routines. ************/ @@ -1477,139 +1458,233 @@ __GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned #define mpn_add __MPN(add) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) -__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #endif #define mpn_add_1 __MPN(add_1) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) -__GMP_DECLSPEC mp_limb_t mpn_add_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +__GMP_DECLSPEC mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; #endif #define mpn_add_n __MPN(add_n) -__GMP_DECLSPEC mp_limb_t mpn_add_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #define mpn_addmul_1 __MPN(addmul_1) -__GMP_DECLSPEC mp_limb_t mpn_addmul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); - -#define mpn_bdivmod __MPN(bdivmod) -__GMP_DECLSPEC mp_limb_t mpn_bdivmod __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); +__GMP_DECLSPEC mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_cmp __MPN(cmp) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) -__GMP_DECLSPEC int mpn_cmp __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif +#define mpn_zero_p __MPN(zero_p) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_zero_p) +__GMP_DECLSPEC int mpn_zero_p (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_divexact_1 __MPN(divexact_1) +__GMP_DECLSPEC void mpn_divexact_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + #define mpn_divexact_by3(dst,src,size) \ mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) #define mpn_divexact_by3c __MPN(divexact_by3c) -__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_divmod_1(qp,np,nsize,dlimb) \ mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) #define mpn_divrem __MPN(divrem) -__GMP_DECLSPEC mp_limb_t mpn_divrem __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_divrem (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t); #define mpn_divrem_1 __MPN(divrem_1) -__GMP_DECLSPEC mp_limb_t mpn_divrem_1 __GMP_PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_divrem_1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_divrem_2 __MPN(divrem_2) -__GMP_DECLSPEC mp_limb_t mpn_divrem_2 __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr)); +__GMP_DECLSPEC mp_limb_t mpn_divrem_2 (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr); + +#define mpn_div_qr_1 __MPN(div_qr_1) +__GMP_DECLSPEC mp_limb_t mpn_div_qr_1 (mp_ptr, mp_limb_t *, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_div_qr_2 __MPN(div_qr_2) +__GMP_DECLSPEC mp_limb_t mpn_div_qr_2 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); #define mpn_gcd __MPN(gcd) -__GMP_DECLSPEC mp_size_t mpn_gcd __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +__GMP_DECLSPEC mp_size_t mpn_gcd (mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t); #define mpn_gcd_1 __MPN(gcd_1) -__GMP_DECLSPEC mp_limb_t mpn_gcd_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpn_gcd_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; #define mpn_gcdext_1 __MPN(gcdext_1) -__GMP_DECLSPEC mp_limb_t mpn_gcdext_1 __GMP_PROTO ((mp_limb_signed_t *, mp_limb_signed_t *, mp_limb_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_gcdext_1 (mp_limb_signed_t *, mp_limb_signed_t *, mp_limb_t, mp_limb_t); #define mpn_gcdext __MPN(gcdext) -__GMP_DECLSPEC mp_size_t mpn_gcdext __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +__GMP_DECLSPEC mp_size_t mpn_gcdext (mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t); #define mpn_get_str __MPN(get_str) -__GMP_DECLSPEC size_t mpn_get_str __GMP_PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); +__GMP_DECLSPEC size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t); #define mpn_hamdist __MPN(hamdist) -__GMP_DECLSPEC unsigned long int mpn_hamdist __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_hamdist (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpn_lshift __MPN(lshift) -__GMP_DECLSPEC mp_limb_t mpn_lshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +__GMP_DECLSPEC mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); #define mpn_mod_1 __MPN(mod_1) -__GMP_DECLSPEC mp_limb_t mpn_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpn_mod_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; #define mpn_mul __MPN(mul) -__GMP_DECLSPEC mp_limb_t mpn_mul __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #define mpn_mul_1 __MPN(mul_1) -__GMP_DECLSPEC mp_limb_t mpn_mul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_mul_n __MPN(mul_n) -__GMP_DECLSPEC void mpn_mul_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #define mpn_sqr __MPN(sqr) -__GMP_DECLSPEC void mpn_sqr __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); -#define mpn_neg_n __MPN(neg_n) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_neg_n) -__GMP_DECLSPEC mp_limb_t mpn_neg_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_neg __MPN(neg) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_neg) +__GMP_DECLSPEC mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t); #endif +#define mpn_com __MPN(com) +__GMP_DECLSPEC void mpn_com (mp_ptr, mp_srcptr, mp_size_t); + #define mpn_perfect_square_p __MPN(perfect_square_p) -__GMP_DECLSPEC int mpn_perfect_square_p __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpn_perfect_square_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_perfect_power_p __MPN(perfect_power_p) +__GMP_DECLSPEC int mpn_perfect_power_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; #define mpn_popcount __MPN(popcount) -__GMP_DECLSPEC unsigned long int mpn_popcount __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpn_pow_1 __MPN(pow_1) -__GMP_DECLSPEC mp_size_t mpn_pow_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr)); +__GMP_DECLSPEC mp_size_t mpn_pow_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); /* undocumented now, but retained here for upward compatibility */ #define mpn_preinv_mod_1 __MPN(preinv_mod_1) -__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; #define mpn_random __MPN(random) -__GMP_DECLSPEC void mpn_random __GMP_PROTO ((mp_ptr, mp_size_t)); +__GMP_DECLSPEC void mpn_random (mp_ptr, mp_size_t); #define mpn_random2 __MPN(random2) -__GMP_DECLSPEC void mpn_random2 __GMP_PROTO ((mp_ptr, mp_size_t)); +__GMP_DECLSPEC void mpn_random2 (mp_ptr, mp_size_t); #define mpn_rshift __MPN(rshift) -__GMP_DECLSPEC mp_limb_t mpn_rshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +__GMP_DECLSPEC mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); #define mpn_scan0 __MPN(scan0) -__GMP_DECLSPEC unsigned long int mpn_scan0 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; #define mpn_scan1 __MPN(scan1) -__GMP_DECLSPEC unsigned long int mpn_scan1 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; #define mpn_set_str __MPN(set_str) -__GMP_DECLSPEC mp_size_t mpn_set_str __GMP_PROTO ((mp_ptr, __gmp_const unsigned char *, size_t, int)); +__GMP_DECLSPEC mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int); + +#define mpn_sizeinbase __MPN(sizeinbase) +__GMP_DECLSPEC size_t mpn_sizeinbase (mp_srcptr, mp_size_t, int); #define mpn_sqrtrem __MPN(sqrtrem) -__GMP_DECLSPEC mp_size_t mpn_sqrtrem __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); #define mpn_sub __MPN(sub) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) -__GMP_DECLSPEC mp_limb_t mpn_sub __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #endif #define mpn_sub_1 __MPN(sub_1) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) -__GMP_DECLSPEC mp_limb_t mpn_sub_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +__GMP_DECLSPEC mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; #endif #define mpn_sub_n __MPN(sub_n) -__GMP_DECLSPEC mp_limb_t mpn_sub_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #define mpn_submul_1 __MPN(submul_1) -__GMP_DECLSPEC mp_limb_t mpn_submul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_tdiv_qr __MPN(tdiv_qr) -__GMP_DECLSPEC void mpn_tdiv_qr __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC void mpn_tdiv_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_and_n __MPN(and_n) +__GMP_DECLSPEC void mpn_and_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_andn_n __MPN(andn_n) +__GMP_DECLSPEC void mpn_andn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_nand_n __MPN(nand_n) +__GMP_DECLSPEC void mpn_nand_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_ior_n __MPN(ior_n) +__GMP_DECLSPEC void mpn_ior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_iorn_n __MPN(iorn_n) +__GMP_DECLSPEC void mpn_iorn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_nior_n __MPN(nior_n) +__GMP_DECLSPEC void mpn_nior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_xor_n __MPN(xor_n) +__GMP_DECLSPEC void mpn_xor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_xnor_n __MPN(xnor_n) +__GMP_DECLSPEC void mpn_xnor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_copyi __MPN(copyi) +__GMP_DECLSPEC void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); +#define mpn_copyd __MPN(copyd) +__GMP_DECLSPEC void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); +#define mpn_zero __MPN(zero) +__GMP_DECLSPEC void mpn_zero (mp_ptr, mp_size_t); + +#define mpn_cnd_add_n __MPN(cnd_add_n) +__GMP_DECLSPEC mp_limb_t mpn_cnd_add_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_cnd_sub_n __MPN(cnd_sub_n) +__GMP_DECLSPEC mp_limb_t mpn_cnd_sub_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_sec_add_1 __MPN(sec_add_1) +__GMP_DECLSPEC mp_limb_t mpn_sec_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_sec_add_1_itch __MPN(sec_add_1_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_add_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_sub_1 __MPN(sec_sub_1) +__GMP_DECLSPEC mp_limb_t mpn_sec_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_sec_sub_1_itch __MPN(sec_sub_1_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_sub_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_cnd_swap __MPN(cnd_swap) +__GMP_DECLSPEC void mpn_cnd_swap (mp_limb_t, volatile mp_limb_t *, volatile mp_limb_t *, mp_size_t); + +#define mpn_sec_mul __MPN(sec_mul) +__GMP_DECLSPEC void mpn_sec_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_mul_itch __MPN(sec_mul_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_mul_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_sqr __MPN(sec_sqr) +__GMP_DECLSPEC void mpn_sec_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_sqr_itch __MPN(sec_sqr_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_sqr_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_powm __MPN(sec_powm) +__GMP_DECLSPEC void mpn_sec_powm (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_bitcnt_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_powm_itch __MPN(sec_powm_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_powm_itch (mp_size_t, mp_bitcnt_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_tabselect __MPN(sec_tabselect) +__GMP_DECLSPEC void mpn_sec_tabselect (volatile mp_limb_t *, volatile const mp_limb_t *, mp_size_t, mp_size_t, mp_size_t); + +#define mpn_sec_div_qr __MPN(sec_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_sec_div_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_div_qr_itch __MPN(sec_div_qr_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_div_qr_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; +#define mpn_sec_div_r __MPN(sec_div_r) +__GMP_DECLSPEC void mpn_sec_div_r (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_div_r_itch __MPN(sec_div_r_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_div_r_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_invert __MPN(sec_invert) +__GMP_DECLSPEC int mpn_sec_invert (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_bitcnt_t, mp_ptr); +#define mpn_sec_invert_itch __MPN(sec_invert_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_invert_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; /**************** mpz inlines ****************/ @@ -1658,7 +1733,7 @@ __GMP_EXTERN_INLINE int mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW { - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_UINT_MAX); + __GMPZ_FITS_UTYPE_P (__gmp_z, UINT_MAX); } #endif @@ -1669,7 +1744,7 @@ __GMP_EXTERN_INLINE int mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW { - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_ULONG_MAX); + __GMPZ_FITS_UTYPE_P (__gmp_z, ULONG_MAX); } #endif @@ -1680,7 +1755,7 @@ __GMP_EXTERN_INLINE int mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW { - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_USHRT_MAX); + __GMPZ_FITS_UTYPE_P (__gmp_z, USHRT_MAX); } #endif @@ -1697,7 +1772,7 @@ mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland C++ 6.0 warnings about condition always true for something like - "__GMP_ULONG_MAX < GMP_NUMB_MASK". */ + "ULONG_MAX < GMP_NUMB_MASK". */ #if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) /* limb==long and no nails, or limb==longlong, one limb is enough */ return (__gmp_n != 0 ? __gmp_l : 0); @@ -1758,14 +1833,14 @@ mpz_perfect_square_p (mpz_srcptr __gmp_a) #if ! defined (__GMP_FORCE_mpz_popcount) __GMP_EXTERN_INLINE #endif -unsigned long +mp_bitcnt_t mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW { mp_size_t __gmp_usize; - unsigned long __gmp_result; + mp_bitcnt_t __gmp_result; __gmp_usize = __gmp_u->_mp_size; - __gmp_result = (__gmp_usize < 0 ? __GMP_ULONG_MAX : 0); + __gmp_result = (__gmp_usize < 0 ? ULONG_MAX : 0); if (__GMP_LIKELY (__gmp_usize > 0)) __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); return __gmp_result; @@ -2088,6 +2163,22 @@ mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOT } #endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_zero_p) +#if ! defined (__GMP_FORCE_mpn_zero_p) +__GMP_EXTERN_INLINE +#endif +int +mpn_zero_p (mp_srcptr __gmp_p, mp_size_t __gmp_n) __GMP_NOTHROW +{ + /* if (__GMP_LIKELY (__gmp_n > 0)) */ + do { + if (__gmp_p[--__gmp_n] != 0) + return 0; + } while (__gmp_n != 0); + return 1; +} +#endif + #if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) #if ! defined (__GMP_FORCE_mpn_sub) __GMP_EXTERN_INLINE @@ -2114,21 +2205,27 @@ mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_ } #endif -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_neg_n) -#if ! defined (__GMP_FORCE_mpn_neg_n) +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_neg) +#if ! defined (__GMP_FORCE_mpn_neg) __GMP_EXTERN_INLINE #endif mp_limb_t -mpn_neg_n (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) +mpn_neg (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) { - mp_limb_t __gmp_ul, __gmp_cy; - __gmp_cy = 0; - do { - __gmp_ul = *__gmp_up++; - *__gmp_rp++ = -__gmp_ul - __gmp_cy; - __gmp_cy |= __gmp_ul != 0; - } while (--__gmp_n != 0); - return __gmp_cy; + while (*__gmp_up == 0) /* Low zero limbs are unchanged by negation. */ + { + *__gmp_rp = 0; + if (!--__gmp_n) /* All zero */ + return 0; + ++__gmp_up; ++__gmp_rp; + } + + *__gmp_rp = (- *__gmp_up) & GMP_NUMB_MASK; + + if (--__gmp_n) /* Higher limbs get complemented. */ + mpn_com (++__gmp_rp, ++__gmp_up, __gmp_n); + + return 1; } #endif @@ -2147,17 +2244,18 @@ mpn_neg_n (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) #define mpz_cmp_ui(Z,UI) \ (__builtin_constant_p (UI) && (UI) == 0 \ ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) -#define mpz_cmp_si(Z,SI) \ - (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ - : __builtin_constant_p (SI) && (SI) > 0 \ - ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ +#define mpz_cmp_si(Z,SI) \ + (__builtin_constant_p ((SI) >= 0) && (SI) >= 0 \ + ? mpz_cmp_ui (Z, __GMP_CAST (unsigned long, SI)) \ : _mpz_cmp_si (Z,SI)) -#define mpq_cmp_ui(Q,NUI,DUI) \ - (__builtin_constant_p (NUI) && (NUI) == 0 \ - ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) -#define mpq_cmp_si(q,n,d) \ - (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ - ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 ? mpq_sgn (Q) \ + : __builtin_constant_p ((NUI) == (DUI)) && (NUI) == (DUI) \ + ? mpz_cmp (mpq_numref (Q), mpq_denref (Q)) \ + : _mpq_cmp_ui (Q,NUI,DUI)) +#define mpq_cmp_si(q,n,d) \ + (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ + ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ : _mpq_cmp_si (q, n, d)) #else #define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) @@ -2218,13 +2316,14 @@ enum }; /* Define CC and CFLAGS which were used to build this version of GMP */ -#define __GMP_CC "gcc -std=gnu99" -#define __GMP_CFLAGS "-O2 -pedantic -fomit-frame-pointer" +#define __GMP_CC "gcc" +#define __GMP_CFLAGS "-m32 -O2 -pedantic -fomit-frame-pointer -mtune=core2 -march=core2" -/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */ -#define __GNU_MP_VERSION 4 -#define __GNU_MP_VERSION_MINOR 3 +/* Major version number is the value of __GNU_MP__ too, above. */ +#define __GNU_MP_VERSION 6 +#define __GNU_MP_VERSION_MINOR 1 #define __GNU_MP_VERSION_PATCHLEVEL 2 +#define __GNU_MP_RELEASE (__GNU_MP_VERSION * 10000 + __GNU_MP_VERSION_MINOR * 100 + __GNU_MP_VERSION_PATCHLEVEL) #define __GMP_H__ #endif /* __GMP_H__ */ diff --git a/repos/libports/include/spec/32bit/gmp/jacobitab.h b/repos/libports/include/spec/32bit/gmp/jacobitab.h new file mode 100644 index 000000000..4bdbfcc09 --- /dev/null +++ b/repos/libports/include/spec/32bit/gmp/jacobitab.h @@ -0,0 +1,13 @@ + 0, 0, 0, 0, 0,12, 8, 4, 1, 1, 1, 1, 1,13, 9, 5, + 2, 2, 2, 2, 2, 6,10,14, 3, 3, 3, 3, 3, 7,11,15, + 4,16, 6,18, 4, 0,12, 8, 5,17, 7,19, 5, 1,13, 9, + 6,18, 4,16, 6,10,14, 2, 7,19, 5,17, 7,11,15, 3, + 8,10, 9,11, 8, 4, 0,12, 9,11, 8,10, 9, 5, 1,13, +10, 9,11, 8,10,14, 2, 6,11, 8,10, 9,11,15, 3, 7, +12,22,24,20,12, 8, 4, 0,13,23,25,21,13, 9, 5, 1, +25,21,13,23,14, 2, 6,10,24,20,12,22,15, 3, 7,11, +16, 6,18, 4,16,16,16,16,17, 7,19, 5,17,17,17,17, +18, 4,16, 6,18,22,19,23,19, 5,17, 7,19,23,18,22, +20,12,22,24,20,20,20,20,21,13,23,25,21,21,21,21, +22,24,20,12,22,19,23,18,23,25,21,13,23,18,22,19, +24,20,12,22,15, 3, 7,11,25,21,13,23,14, 2, 6,10, diff --git a/repos/libports/include/spec/32bit/gmp/trialdivtab.h b/repos/libports/include/spec/32bit/gmp/trialdivtab.h new file mode 100644 index 000000000..898881ee2 --- /dev/null +++ b/repos/libports/include/spec/32bit/gmp/trialdivtab.h @@ -0,0 +1,1480 @@ +#if GMP_LIMB_BITS != 32 +#error This table is for GMP_LIMB_BITS = 32 +#endif + +#if GMP_NAIL_BITS != 0 +#error This table does not support nails +#endif + +#ifdef WANT_dtab + P(3,CNST_LIMB(0xaaaaaaab),CNST_LIMB(0x55555555)), + P(5,CNST_LIMB(0xcccccccd),CNST_LIMB(0x33333333)), + P(7,CNST_LIMB(0xb6db6db7),CNST_LIMB(0x24924924)), + P(11,CNST_LIMB(0xba2e8ba3),CNST_LIMB(0x1745d174)), + P(13,CNST_LIMB(0xc4ec4ec5),CNST_LIMB(0x13b13b13)), + P(17,CNST_LIMB(0xf0f0f0f1),CNST_LIMB(0xf0f0f0f)), + P(19,CNST_LIMB(0x286bca1b),CNST_LIMB(0xd79435e)), + P(23,CNST_LIMB(0xe9bd37a7),CNST_LIMB(0xb21642c)), + P(29,CNST_LIMB(0x4f72c235),CNST_LIMB(0x8d3dcb0)), + P(31,CNST_LIMB(0xbdef7bdf),CNST_LIMB(0x8421084)), + P(37,CNST_LIMB(0x914c1bad),CNST_LIMB(0x6eb3e45)), + P(41,CNST_LIMB(0xc18f9c19),CNST_LIMB(0x63e7063)), + P(43,CNST_LIMB(0x2fa0be83),CNST_LIMB(0x5f417d0)), + P(47,CNST_LIMB(0x677d46cf),CNST_LIMB(0x572620a)), + P(53,CNST_LIMB(0x8c13521d),CNST_LIMB(0x4d4873e)), + P(59,CNST_LIMB(0xa08ad8f3),CNST_LIMB(0x456c797)), + P(61,CNST_LIMB(0xc10c9715),CNST_LIMB(0x4325c53)), + P(67,CNST_LIMB(0x7a44c6b),CNST_LIMB(0x3d22635)), + P(71,CNST_LIMB(0xe327a977),CNST_LIMB(0x39b0ad1)), + P(73,CNST_LIMB(0xc7e3f1f9),CNST_LIMB(0x381c0e0)), + P(79,CNST_LIMB(0x613716af),CNST_LIMB(0x33d91d2)), + P(83,CNST_LIMB(0x2b2e43db),CNST_LIMB(0x3159721)), + P(89,CNST_LIMB(0xfa3f47e9),CNST_LIMB(0x2e05c0b)), + P(97,CNST_LIMB(0x5f02a3a1),CNST_LIMB(0x2a3a0fd)), + P(101,CNST_LIMB(0x7c32b16d),CNST_LIMB(0x288df0c)), + P(103,CNST_LIMB(0xd3431b57),CNST_LIMB(0x27c4597)), + P(107,CNST_LIMB(0x8d28ac43),CNST_LIMB(0x2647c69)), + P(109,CNST_LIMB(0xda6c0965),CNST_LIMB(0x2593f69)), + P(113,CNST_LIMB(0xfdbc091),CNST_LIMB(0x243f6f0)), + P(127,CNST_LIMB(0xefdfbf7f),CNST_LIMB(0x2040810)), + P(131,CNST_LIMB(0xc9484e2b),CNST_LIMB(0x1f44659)), + P(137,CNST_LIMB(0x77975b9),CNST_LIMB(0x1de5d6e)), + P(139,CNST_LIMB(0x70586723),CNST_LIMB(0x1d77b65)), + P(149,CNST_LIMB(0x8ce2cabd),CNST_LIMB(0x1b7d6c3)), + P(151,CNST_LIMB(0xbf937f27),CNST_LIMB(0x1b20364)), + P(157,CNST_LIMB(0x2c0685b5),CNST_LIMB(0x1a16d3f)), + P(163,CNST_LIMB(0x451ab30b),CNST_LIMB(0x1920fb4)), + P(167,CNST_LIMB(0xdb35a717),CNST_LIMB(0x1886e5f)), + P(173,CNST_LIMB(0xd516325),CNST_LIMB(0x17ad220)), + P(179,CNST_LIMB(0xd962ae7b),CNST_LIMB(0x16e1f76)), + P(181,CNST_LIMB(0x10f8ed9d),CNST_LIMB(0x16a13cd)), + P(191,CNST_LIMB(0xee936f3f),CNST_LIMB(0x1571ed3)), + P(193,CNST_LIMB(0x90948f41),CNST_LIMB(0x1539094)), + P(197,CNST_LIMB(0x3d137e0d),CNST_LIMB(0x14cab88)), + P(199,CNST_LIMB(0xef46c0f7),CNST_LIMB(0x149539e)), + P(211,CNST_LIMB(0x6e68575b),CNST_LIMB(0x13698df)), + P(223,CNST_LIMB(0xdb43bb1f),CNST_LIMB(0x125e227)), + P(227,CNST_LIMB(0x9ba144cb),CNST_LIMB(0x120b470)), + P(229,CNST_LIMB(0x478bbced),CNST_LIMB(0x11e2ef3)), + P(233,CNST_LIMB(0x1fdcd759),CNST_LIMB(0x1194538)), + P(239,CNST_LIMB(0x437b2e0f),CNST_LIMB(0x112358e)), + P(241,CNST_LIMB(0x10fef011),CNST_LIMB(0x10fef01)), + P(251,CNST_LIMB(0x9a020a33),CNST_LIMB(0x105197f)), + P(257,CNST_LIMB(0xff00ff01),CNST_LIMB(0xff00ff)), + P(263,CNST_LIMB(0x70e99cb7),CNST_LIMB(0xf92fb2)), + P(269,CNST_LIMB(0x6205b5c5),CNST_LIMB(0xf3a0d5)), + P(271,CNST_LIMB(0xa27acdef),CNST_LIMB(0xf1d48b)), + P(277,CNST_LIMB(0x25e4463d),CNST_LIMB(0xec9791)), + P(281,CNST_LIMB(0x749cb29),CNST_LIMB(0xe93965)), + P(283,CNST_LIMB(0xc9b97113),CNST_LIMB(0xe79372)), + P(293,CNST_LIMB(0x84ce32ad),CNST_LIMB(0xdfac1f)), + P(307,CNST_LIMB(0xc74be1fb),CNST_LIMB(0xd578e9)), + P(311,CNST_LIMB(0xa7198487),CNST_LIMB(0xd2ba08)), + P(313,CNST_LIMB(0x39409d09),CNST_LIMB(0xd16154)), + P(317,CNST_LIMB(0x6f71de15),CNST_LIMB(0xcebcf8)), + P(331,CNST_LIMB(0xbfce8063),CNST_LIMB(0xc5fe74)), + P(337,CNST_LIMB(0xf61fe7b1),CNST_LIMB(0xc27806)), + P(347,CNST_LIMB(0x70e046d3),CNST_LIMB(0xbcdd53)), + P(349,CNST_LIMB(0xf1545af5),CNST_LIMB(0xbbc840)), + P(353,CNST_LIMB(0x9a7862a1),CNST_LIMB(0xb9a786)), + P(359,CNST_LIMB(0x2a128a57),CNST_LIMB(0xb68d31)), + P(367,CNST_LIMB(0xb7747d8f),CNST_LIMB(0xb2927c)), + P(373,CNST_LIMB(0xbb5e06dd),CNST_LIMB(0xafb321)), + P(379,CNST_LIMB(0x12e9b5b3),CNST_LIMB(0xaceb0f)), + P(383,CNST_LIMB(0xec9dbe7f),CNST_LIMB(0xab1cbd)), + P(389,CNST_LIMB(0xec41cf4d),CNST_LIMB(0xa87917)), + P(397,CNST_LIMB(0xaec02945),CNST_LIMB(0xa513fd)), + P(401,CNST_LIMB(0x8382df71),CNST_LIMB(0xa36e71)), + P(409,CNST_LIMB(0x84b1c2a9),CNST_LIMB(0xa03c16)), + P(419,CNST_LIMB(0x75eb3a0b),CNST_LIMB(0x9c6916)), + P(421,CNST_LIMB(0xfa86fe2d),CNST_LIMB(0x9baade)), + P(431,CNST_LIMB(0x3f8df54f),CNST_LIMB(0x980e41)), + P(433,CNST_LIMB(0x975a751),CNST_LIMB(0x975a75)), + P(439,CNST_LIMB(0xc3efac07),CNST_LIMB(0x9548e4)), + P(443,CNST_LIMB(0xa8299b73),CNST_LIMB(0x93efd1)), + P(449,CNST_LIMB(0x9ba70e41),CNST_LIMB(0x91f5bc)), + P(457,CNST_LIMB(0x23d9e879),CNST_LIMB(0x8f67a1)), + P(461,CNST_LIMB(0xc494d305),CNST_LIMB(0x8e2917)), + P(463,CNST_LIMB(0xab67652f),CNST_LIMB(0x8d8be3)), + P(467,CNST_LIMB(0xfb10fe5b),CNST_LIMB(0x8c5584)), + P(479,CNST_LIMB(0xbf54fa1f),CNST_LIMB(0x88d180)), + P(487,CNST_LIMB(0xb98f81d7),CNST_LIMB(0x869222)), + P(491,CNST_LIMB(0xe90f1ec3),CNST_LIMB(0x85797b)), + P(499,CNST_LIMB(0xbed87f3b),CNST_LIMB(0x8355ac)), + P(503,CNST_LIMB(0x16e70fc7),CNST_LIMB(0x824a4e)), + P(509,CNST_LIMB(0x9dece355),CNST_LIMB(0x80c121)), + P(521,CNST_LIMB(0x73f62c39),CNST_LIMB(0x7dc9f3)), + P(523,CNST_LIMB(0xad46f9a3),CNST_LIMB(0x7d4ece)), + P(541,CNST_LIMB(0x24e8d035),CNST_LIMB(0x79237d)), + P(547,CNST_LIMB(0x2319bd8b),CNST_LIMB(0x77cf53)), + P(557,CNST_LIMB(0xc7ed9da5),CNST_LIMB(0x75a8ac)), + P(563,CNST_LIMB(0xfea2c8fb),CNST_LIMB(0x7467ac)), + P(569,CNST_LIMB(0xce0f4c09),CNST_LIMB(0x732d70)), + P(571,CNST_LIMB(0x544986f3),CNST_LIMB(0x72c62a)), + P(577,CNST_LIMB(0x55a10dc1),CNST_LIMB(0x7194a1)), + P(587,CNST_LIMB(0x85e33763),CNST_LIMB(0x6fa549)), + P(593,CNST_LIMB(0xd84886b1),CNST_LIMB(0x6e8419)), + P(599,CNST_LIMB(0x31260967),CNST_LIMB(0x6d68b5)), + P(601,CNST_LIMB(0xd1ff25e9),CNST_LIMB(0x6d0b80)), + P(607,CNST_LIMB(0x5b84d99f),CNST_LIMB(0x6bf790)), + P(613,CNST_LIMB(0x1335df6d),CNST_LIMB(0x6ae907)), + P(617,CNST_LIMB(0x75d5add9),CNST_LIMB(0x6a3799)), + P(619,CNST_LIMB(0x3c619a43),CNST_LIMB(0x69dfbd)), + P(631,CNST_LIMB(0x4767747),CNST_LIMB(0x67dc4c)), + P(641,CNST_LIMB(0x663d81),CNST_LIMB(0x663d80)), + P(643,CNST_LIMB(0x671ddc2b),CNST_LIMB(0x65ec17)), + P(647,CNST_LIMB(0xc1e12337),CNST_LIMB(0x654ac8)), + P(653,CNST_LIMB(0x9cd09045),CNST_LIMB(0x645c85)), + P(659,CNST_LIMB(0x91496b9b),CNST_LIMB(0x637299)), + P(661,CNST_LIMB(0xc7d7b8bd),CNST_LIMB(0x632591)), + P(673,CNST_LIMB(0x9f006161),CNST_LIMB(0x6160ff)), + P(677,CNST_LIMB(0x5e28152d),CNST_LIMB(0x60cdb5)), + P(683,CNST_LIMB(0xbfe803),CNST_LIMB(0x5ff401)), + P(691,CNST_LIMB(0x9e907c7b),CNST_LIMB(0x5ed79e)), + P(701,CNST_LIMB(0x76528895),CNST_LIMB(0x5d7d42)), + P(709,CNST_LIMB(0x1ce2c0d),CNST_LIMB(0x5c6f35)), + P(719,CNST_LIMB(0xbed7c42f),CNST_LIMB(0x5b2618)), + P(727,CNST_LIMB(0xd4b010e7),CNST_LIMB(0x5a2553)), + P(733,CNST_LIMB(0x1ebbe575),CNST_LIMB(0x59686c)), + P(739,CNST_LIMB(0xb47b52cb),CNST_LIMB(0x58ae97)), + P(743,CNST_LIMB(0x64f3f0d7),CNST_LIMB(0x58345f)), + P(751,CNST_LIMB(0x316d6c0f),CNST_LIMB(0x5743d5)), + P(757,CNST_LIMB(0x91c1195d),CNST_LIMB(0x5692c4)), + P(761,CNST_LIMB(0xa27b1f49),CNST_LIMB(0x561e46)), + P(769,CNST_LIMB(0xe508fd01),CNST_LIMB(0x5538ed)), + P(773,CNST_LIMB(0x133551cd),CNST_LIMB(0x54c807)), + P(787,CNST_LIMB(0x2d8a3f1b),CNST_LIMB(0x5345ef)), + P(797,CNST_LIMB(0xc34ad735),CNST_LIMB(0x523a75)), + P(809,CNST_LIMB(0xa714919),CNST_LIMB(0x510237)), + P(811,CNST_LIMB(0x24eea383),CNST_LIMB(0x50cf12)), + P(821,CNST_LIMB(0x42ba771d),CNST_LIMB(0x4fd319)), + P(823,CNST_LIMB(0x7772287),CNST_LIMB(0x4fa170)), + P(827,CNST_LIMB(0x5e69ddf3),CNST_LIMB(0x4f3ed6)), + P(829,CNST_LIMB(0x3b4a6c15),CNST_LIMB(0x4f0de5)), + P(839,CNST_LIMB(0xc606b677),CNST_LIMB(0x4e1cae)), + P(853,CNST_LIMB(0x46d3e1fd),CNST_LIMB(0x4cd47b)), + P(857,CNST_LIMB(0x484a14e9),CNST_LIMB(0x4c78ae)), + P(859,CNST_LIMB(0x1ce874d3),CNST_LIMB(0x4c4b19)), + P(863,CNST_LIMB(0x473189f),CNST_LIMB(0x4bf093)), + P(877,CNST_LIMB(0x372b7e65),CNST_LIMB(0x4aba3c)), + P(881,CNST_LIMB(0x4f9e5d91),CNST_LIMB(0x4a6360)), + P(883,CNST_LIMB(0x446bd9bb),CNST_LIMB(0x4a383e)), + P(887,CNST_LIMB(0xe777c647),CNST_LIMB(0x49e28f)), + P(907,CNST_LIMB(0xf61f0c23),CNST_LIMB(0x48417b)), + P(911,CNST_LIMB(0xa5cbbb6f),CNST_LIMB(0x47f043)), + P(919,CNST_LIMB(0x69daac27),CNST_LIMB(0x474ff2)), + P(929,CNST_LIMB(0x637aa061),CNST_LIMB(0x468b6f)), + P(937,CNST_LIMB(0x1fb15099),CNST_LIMB(0x45f13f)), + P(941,CNST_LIMB(0x712c5825),CNST_LIMB(0x45a522)), + P(947,CNST_LIMB(0xff30637b),CNST_LIMB(0x45342c)), + P(953,CNST_LIMB(0x1131289),CNST_LIMB(0x44c4a2)), + P(967,CNST_LIMB(0xf5acdf7),CNST_LIMB(0x43c5c2)), + P(971,CNST_LIMB(0x4d3f89e3),CNST_LIMB(0x437e49)), + P(977,CNST_LIMB(0xd2253531),CNST_LIMB(0x43142d)), + P(983,CNST_LIMB(0x7bf69fe7),CNST_LIMB(0x42ab5c)), + P(991,CNST_LIMB(0xcfb1781f),CNST_LIMB(0x422195)), + P(997,CNST_LIMB(0x318e81ed),CNST_LIMB(0x41bbb2)), + P(1009,CNST_LIMB(0x9f148d11),CNST_LIMB(0x40f391)), + P(1013,CNST_LIMB(0x2c7a505d),CNST_LIMB(0x40b1e9)), + P(1019,CNST_LIMB(0x28728f33),CNST_LIMB(0x405064)), + P(1021,CNST_LIMB(0xe5ec7155),CNST_LIMB(0x403024)), + P(1031,CNST_LIMB(0x9fe829b7),CNST_LIMB(0x3f90c2)), + P(1033,CNST_LIMB(0x6a50ca39),CNST_LIMB(0x3f7141)), + P(1039,CNST_LIMB(0xb6d26aef),CNST_LIMB(0x3f1377)), + P(1049,CNST_LIMB(0xa8251829),CNST_LIMB(0x3e7988)), + P(1051,CNST_LIMB(0x1b863613),CNST_LIMB(0x3e5b19)), + P(1061,CNST_LIMB(0x20d077ad),CNST_LIMB(0x3dc4a5)), + P(1063,CNST_LIMB(0x2e3d2b97),CNST_LIMB(0x3da6e4)), + P(1069,CNST_LIMB(0x3dc8eba5),CNST_LIMB(0x3d4e4f)), + P(1087,CNST_LIMB(0x3229ebbf),CNST_LIMB(0x3c4a6b)), + P(1091,CNST_LIMB(0x7e01686b),CNST_LIMB(0x3c11d5)), + P(1093,CNST_LIMB(0x2c086e8d),CNST_LIMB(0x3bf5b1)), + P(1097,CNST_LIMB(0x9f632df9),CNST_LIMB(0x3bbdb9)), + P(1103,CNST_LIMB(0xdff892af),CNST_LIMB(0x3b6a88)), + P(1109,CNST_LIMB(0x3f04d8fd),CNST_LIMB(0x3b183c)), + P(1117,CNST_LIMB(0x9cfdeff5),CNST_LIMB(0x3aabe3)), + P(1123,CNST_LIMB(0xbda9d4b),CNST_LIMB(0x3a5ba3)), + P(1129,CNST_LIMB(0x24f5cbd9),CNST_LIMB(0x3a0c3e)), + P(1151,CNST_LIMB(0x94cbbb7f),CNST_LIMB(0x38f035)), + P(1153,CNST_LIMB(0xb4f43b81),CNST_LIMB(0x38d6ec)), + P(1163,CNST_LIMB(0x34d4323),CNST_LIMB(0x3859cf)), + P(1171,CNST_LIMB(0x74f5b99b),CNST_LIMB(0x37f741)), + P(1181,CNST_LIMB(0xc68ea1b5),CNST_LIMB(0x377df0)), + P(1187,CNST_LIMB(0x96c0cf0b),CNST_LIMB(0x373622)), + P(1193,CNST_LIMB(0xe33edf99),CNST_LIMB(0x36ef0c)), + P(1201,CNST_LIMB(0xb897c451),CNST_LIMB(0x36915f)), + P(1213,CNST_LIMB(0x8fb91695),CNST_LIMB(0x36072c)), + P(1217,CNST_LIMB(0xe5ea8b41),CNST_LIMB(0x35d9b7)), + P(1223,CNST_LIMB(0x93fd7cf7),CNST_LIMB(0x359615)), + P(1229,CNST_LIMB(0xb3f8805),CNST_LIMB(0x35531c)), + P(1231,CNST_LIMB(0xa912822f),CNST_LIMB(0x353cee)), + P(1237,CNST_LIMB(0x13a9147d),CNST_LIMB(0x34fad3)), + P(1249,CNST_LIMB(0xc4c3f21),CNST_LIMB(0x347884)), + P(1259,CNST_LIMB(0x7a6883c3),CNST_LIMB(0x340dd3)), + P(1277,CNST_LIMB(0x2ab33855),CNST_LIMB(0x3351fd)), + P(1279,CNST_LIMB(0x82e6faff),CNST_LIMB(0x333d72)), + P(1283,CNST_LIMB(0x17be8dab),CNST_LIMB(0x33148d)), + P(1289,CNST_LIMB(0x7cb91939),CNST_LIMB(0x32d7ae)), + P(1291,CNST_LIMB(0x42a09ea3),CNST_LIMB(0x32c385)), + P(1297,CNST_LIMB(0x6d8b8bf1),CNST_LIMB(0x328766)), + P(1301,CNST_LIMB(0xba8a223d),CNST_LIMB(0x325fa1)), + P(1303,CNST_LIMB(0x9c3182a7),CNST_LIMB(0x324bd6)), + P(1307,CNST_LIMB(0x474bcd13),CNST_LIMB(0x32246e)), + P(1319,CNST_LIMB(0xc5311a97),CNST_LIMB(0x31afa5)), + P(1321,CNST_LIMB(0xc00c6719),CNST_LIMB(0x319c63)), + P(1327,CNST_LIMB(0x4b0b61cf),CNST_LIMB(0x3162f7)), + P(1361,CNST_LIMB(0x9b8e63b1),CNST_LIMB(0x30271f)), + P(1367,CNST_LIMB(0x41eb667),CNST_LIMB(0x2ff104)), + P(1373,CNST_LIMB(0x896a76f5),CNST_LIMB(0x2fbb62)), + P(1381,CNST_LIMB(0x4a55a46d),CNST_LIMB(0x2f7499)), + P(1399,CNST_LIMB(0x58046447),CNST_LIMB(0x2ed84a)), + P(1409,CNST_LIMB(0x69be3a81),CNST_LIMB(0x2e832d)), + P(1423,CNST_LIMB(0xd053796f),CNST_LIMB(0x2e0e08)), + P(1427,CNST_LIMB(0x89f4e09b),CNST_LIMB(0x2decfb)), + P(1429,CNST_LIMB(0xb7721dbd),CNST_LIMB(0x2ddc87)), + P(1433,CNST_LIMB(0x35f37ea9),CNST_LIMB(0x2dbbc1)), + P(1439,CNST_LIMB(0xf2d5d65f),CNST_LIMB(0x2d8af0)), + P(1447,CNST_LIMB(0x36505217),CNST_LIMB(0x2d4a7b)), + P(1451,CNST_LIMB(0x7062cd03),CNST_LIMB(0x2d2a85)), + P(1453,CNST_LIMB(0xfdb5a625),CNST_LIMB(0x2d1a9a)), + P(1459,CNST_LIMB(0x7e82317b),CNST_LIMB(0x2ceb1e)), + P(1471,CNST_LIMB(0x60c2ea3f),CNST_LIMB(0x2c8d50)), + P(1481,CNST_LIMB(0xf0452479),CNST_LIMB(0x2c404d)), + P(1483,CNST_LIMB(0x82acf7e3),CNST_LIMB(0x2c3106)), + P(1487,CNST_LIMB(0x73dce12f),CNST_LIMB(0x2c1297)), + P(1489,CNST_LIMB(0x85c27331),CNST_LIMB(0x2c0370)), + P(1493,CNST_LIMB(0xfe490b7d),CNST_LIMB(0x2be540)), + P(1499,CNST_LIMB(0x9a8e6e53),CNST_LIMB(0x2bb845)), + P(1511,CNST_LIMB(0xd4753dd7),CNST_LIMB(0x2b5f62)), + P(1523,CNST_LIMB(0xc4aa1b3b),CNST_LIMB(0x2b07e6)), + P(1531,CNST_LIMB(0x81163d33),CNST_LIMB(0x2ace56)), + P(1543,CNST_LIMB(0x594287b7),CNST_LIMB(0x2a791d)), + P(1549,CNST_LIMB(0x13aab8c5),CNST_LIMB(0x2a4eff)), + P(1553,CNST_LIMB(0x8dc3aaf1),CNST_LIMB(0x2a3319)), + P(1559,CNST_LIMB(0x565f91a7),CNST_LIMB(0x2a0986)), + P(1567,CNST_LIMB(0x8c01f5df),CNST_LIMB(0x29d295)), + P(1571,CNST_LIMB(0x8c23d98b),CNST_LIMB(0x29b752)), + P(1579,CNST_LIMB(0x1228883),CNST_LIMB(0x298137)), + P(1583,CNST_LIMB(0xfbf500cf),CNST_LIMB(0x29665e)), + P(1597,CNST_LIMB(0xc8b24115),CNST_LIMB(0x290975)), + P(1601,CNST_LIMB(0xad0309c1),CNST_LIMB(0x28ef35)), + P(1607,CNST_LIMB(0x24a3c377),CNST_LIMB(0x28c815)), + P(1609,CNST_LIMB(0x8b0ecbf9),CNST_LIMB(0x28bb1b)), + P(1613,CNST_LIMB(0xec00a285),CNST_LIMB(0x28a13f)), + P(1619,CNST_LIMB(0xdea2ddb),CNST_LIMB(0x287ab3)), + P(1621,CNST_LIMB(0x9ac4c6fd),CNST_LIMB(0x286dea)), + P(1627,CNST_LIMB(0xbd99b9d3),CNST_LIMB(0x2847bf)), + P(1637,CNST_LIMB(0xca343b6d),CNST_LIMB(0x2808c1)), + P(1657,CNST_LIMB(0xe34383c9),CNST_LIMB(0x278d0e)), + P(1663,CNST_LIMB(0xdd35b97f),CNST_LIMB(0x276886)), + P(1667,CNST_LIMB(0x7090f82b),CNST_LIMB(0x275051)), + P(1669,CNST_LIMB(0xdd7d024d),CNST_LIMB(0x274441)), + P(1693,CNST_LIMB(0x746eafb5),CNST_LIMB(0x26b5c1)), + P(1697,CNST_LIMB(0x36755d61),CNST_LIMB(0x269e65)), + P(1699,CNST_LIMB(0x51f7dd0b),CNST_LIMB(0x2692c2)), + P(1709,CNST_LIMB(0xce914d25),CNST_LIMB(0x2658fa)), + P(1721,CNST_LIMB(0xe28c1f89),CNST_LIMB(0x261487)), + P(1723,CNST_LIMB(0x32d04e73),CNST_LIMB(0x260936)), + P(1733,CNST_LIMB(0x893b880d),CNST_LIMB(0x25d106)), + P(1741,CNST_LIMB(0x6e935605),CNST_LIMB(0x25a48a)), + P(1747,CNST_LIMB(0x2376415b),CNST_LIMB(0x258371)), + P(1753,CNST_LIMB(0xbaa21969),CNST_LIMB(0x256292)), + P(1759,CNST_LIMB(0x42cd351f),CNST_LIMB(0x2541ed)), + P(1777,CNST_LIMB(0x49c2a11),CNST_LIMB(0x24e150)), + P(1783,CNST_LIMB(0x3e069ac7),CNST_LIMB(0x24c18b)), + P(1787,CNST_LIMB(0xdfe91433),CNST_LIMB(0x24ac7b)), + P(1789,CNST_LIMB(0x37cec655),CNST_LIMB(0x24a1fc)), + P(1801,CNST_LIMB(0x71ffb739),CNST_LIMB(0x246380)), + P(1811,CNST_LIMB(0x6286db1b),CNST_LIMB(0x24300f)), + P(1823,CNST_LIMB(0xfe08b4df),CNST_LIMB(0x23f314)), + P(1831,CNST_LIMB(0x7742f897),CNST_LIMB(0x23cade)), + P(1847,CNST_LIMB(0x2c5a5e87),CNST_LIMB(0x237b7e)), + P(1861,CNST_LIMB(0xd958738d),CNST_LIMB(0x233729)), + P(1867,CNST_LIMB(0x1d34ca63),CNST_LIMB(0x231a30)), + P(1871,CNST_LIMB(0xd644afaf),CNST_LIMB(0x2306fa)), + P(1873,CNST_LIMB(0xcf11a1b1),CNST_LIMB(0x22fd67)), + P(1877,CNST_LIMB(0x3253bdfd),CNST_LIMB(0x22ea50)), + P(1879,CNST_LIMB(0x80bfd467),CNST_LIMB(0x22e0cc)), + P(1889,CNST_LIMB(0xf024dca1),CNST_LIMB(0x22b188)), + P(1901,CNST_LIMB(0xcaac1a65),CNST_LIMB(0x227977)), + P(1907,CNST_LIMB(0xae6175bb),CNST_LIMB(0x225db3)), + P(1913,CNST_LIMB(0xf708b2c9),CNST_LIMB(0x22421b)), + P(1931,CNST_LIMB(0x389be823),CNST_LIMB(0x21f05b)), + P(1933,CNST_LIMB(0x4c489345),CNST_LIMB(0x21e75d)), + P(1949,CNST_LIMB(0x3e85b6b5),CNST_LIMB(0x21a01d)), + P(1951,CNST_LIMB(0x1563545f),CNST_LIMB(0x21974a)), + P(1973,CNST_LIMB(0xe62dee9d),CNST_LIMB(0x213767)), + P(1979,CNST_LIMB(0x6673a573),CNST_LIMB(0x211d9f)), + P(1987,CNST_LIMB(0xe575a0eb),CNST_LIMB(0x20fb7d)), + P(1993,CNST_LIMB(0xe066c279),CNST_LIMB(0x20e212)), + P(1997,CNST_LIMB(0x8ab43d05),CNST_LIMB(0x20d135)), + P(1999,CNST_LIMB(0x16cb9f2f),CNST_LIMB(0x20c8cd)), + P(2003,CNST_LIMB(0xe9c2e85b),CNST_LIMB(0x20b80b)), + P(2011,CNST_LIMB(0x21dc9c53),CNST_LIMB(0x2096b9)), + P(2017,CNST_LIMB(0xc9ee7c21),CNST_LIMB(0x207de7)), + P(2027,CNST_LIMB(0x4c27e8c3),CNST_LIMB(0x2054de)), + P(2029,CNST_LIMB(0x19dd6de5),CNST_LIMB(0x204cb6)), + P(2039,CNST_LIMB(0xa296e9c7),CNST_LIMB(0x202428)), + P(2053,CNST_LIMB(0x872b84cd),CNST_LIMB(0x1fec0c)), + P(2063,CNST_LIMB(0x3895e6ef),CNST_LIMB(0x1fc46f)), + P(2069,CNST_LIMB(0x988f873d),CNST_LIMB(0x1facda)), + P(2081,CNST_LIMB(0xb5f17be1),CNST_LIMB(0x1f7e17)), + P(2083,CNST_LIMB(0xfd0ce78b),CNST_LIMB(0x1f765a)), + P(2087,CNST_LIMB(0x660e797),CNST_LIMB(0x1f66ea)), + P(2089,CNST_LIMB(0x1ffc1419),CNST_LIMB(0x1f5f38)), + P(2099,CNST_LIMB(0xc22a32fb),CNST_LIMB(0x1f38f4)), + P(2111,CNST_LIMB(0xd37e7bf),CNST_LIMB(0x1f0b85)), + P(2113,CNST_LIMB(0xfc007c1),CNST_LIMB(0x1f03ff)), + P(2129,CNST_LIMB(0xc0640b1),CNST_LIMB(0x1ec853)), + P(2131,CNST_LIMB(0x31037bdb),CNST_LIMB(0x1ec0ee)), + P(2137,CNST_LIMB(0xfeebfe9),CNST_LIMB(0x1eaad3)), + P(2141,CNST_LIMB(0x544c0bf5),CNST_LIMB(0x1e9c28)), + P(2143,CNST_LIMB(0x593c539f),CNST_LIMB(0x1e94d8)), + P(2153,CNST_LIMB(0xfa0e07d9),CNST_LIMB(0x1e707b)), + P(2161,CNST_LIMB(0xbd8ab891),CNST_LIMB(0x1e53a2)), + P(2179,CNST_LIMB(0x7c2e862b),CNST_LIMB(0x1e1380)), + P(2203,CNST_LIMB(0x595c9d93),CNST_LIMB(0x1dbf9f)), + P(2207,CNST_LIMB(0x5d07135f),CNST_LIMB(0x1db1d1)), + P(2213,CNST_LIMB(0x6e209f2d),CNST_LIMB(0x1d9d35)), + P(2221,CNST_LIMB(0x47769b25),CNST_LIMB(0x1d81e6)), + P(2237,CNST_LIMB(0xaabe3295),CNST_LIMB(0x1d4bdf)), + P(2239,CNST_LIMB(0xd0c7673f),CNST_LIMB(0x1d452c)), + P(2243,CNST_LIMB(0x26b0e7eb),CNST_LIMB(0x1d37cf)), + P(2251,CNST_LIMB(0x56c61ce3),CNST_LIMB(0x1d1d3a)), + P(2267,CNST_LIMB(0xa124b353),CNST_LIMB(0x1ce89f)), + P(2269,CNST_LIMB(0xba630f75),CNST_LIMB(0x1ce219)), + P(2273,CNST_LIMB(0xbd533b21),CNST_LIMB(0x1cd516)), + P(2281,CNST_LIMB(0xdd354f59),CNST_LIMB(0x1cbb33)), + P(2287,CNST_LIMB(0x7414260f),CNST_LIMB(0x1ca7e7)), + P(2293,CNST_LIMB(0x8eae635d),CNST_LIMB(0x1c94b5)), + P(2297,CNST_LIMB(0xfb6e3949),CNST_LIMB(0x1c87f7)), + P(2309,CNST_LIMB(0x14f45bcd),CNST_LIMB(0x1c6202)), + P(2311,CNST_LIMB(0xde5314b7),CNST_LIMB(0x1c5bb8)), + P(2333,CNST_LIMB(0xf2b90135),CNST_LIMB(0x1c1743)), + P(2339,CNST_LIMB(0xdf9a6e8b),CNST_LIMB(0x1c04d0)), + P(2341,CNST_LIMB(0xc1c6eaad),CNST_LIMB(0x1bfeb0)), + P(2347,CNST_LIMB(0x823c6d83),CNST_LIMB(0x1bec5d)), + P(2351,CNST_LIMB(0xfe5ddcf),CNST_LIMB(0x1be034)), + P(2357,CNST_LIMB(0xc496c11d),CNST_LIMB(0x1bce09)), + P(2371,CNST_LIMB(0xf88ccb6b),CNST_LIMB(0x1ba402)), + P(2377,CNST_LIMB(0x457738f9),CNST_LIMB(0x1b9225)), + P(2381,CNST_LIMB(0xb71a5785),CNST_LIMB(0x1b864a)), + P(2383,CNST_LIMB(0x8d0d6daf),CNST_LIMB(0x1b8060)), + P(2389,CNST_LIMB(0xb6cfabfd),CNST_LIMB(0x1b6eb1)), + P(2393,CNST_LIMB(0xe5e5aee9),CNST_LIMB(0x1b62f4)), + P(2399,CNST_LIMB(0xe9e929f),CNST_LIMB(0x1b516b)), + P(2411,CNST_LIMB(0x588ddb43),CNST_LIMB(0x1b2e9c)), + P(2417,CNST_LIMB(0xc4799791),CNST_LIMB(0x1b1d56)), + P(2423,CNST_LIMB(0x3b45a047),CNST_LIMB(0x1b0c26)), + P(2437,CNST_LIMB(0x4498874d),CNST_LIMB(0x1ae45f)), + P(2441,CNST_LIMB(0xa9953cb9),CNST_LIMB(0x1ad917)), + P(2447,CNST_LIMB(0xd4caf56f),CNST_LIMB(0x1ac83d)), + P(2459,CNST_LIMB(0x4a053493),CNST_LIMB(0x1aa6c7)), + P(2467,CNST_LIMB(0x6ac7720b),CNST_LIMB(0x1a90a7)), + P(2473,CNST_LIMB(0xc710aa99),CNST_LIMB(0x1a8027)), + P(2477,CNST_LIMB(0xa3804225),CNST_LIMB(0x1a7533)), + P(2503,CNST_LIMB(0xefbce7f7),CNST_LIMB(0x1a2ed7)), + P(2521,CNST_LIMB(0xcf5be669),CNST_LIMB(0x19fefc)), + P(2531,CNST_LIMB(0x31c383cb),CNST_LIMB(0x19e4b0)), + P(2539,CNST_LIMB(0x1d8ad6c3),CNST_LIMB(0x19cfcd)), + P(2543,CNST_LIMB(0xf1ce450f),CNST_LIMB(0x19c569)), + P(2549,CNST_LIMB(0x37a39a5d),CNST_LIMB(0x19b5e1)), + P(2551,CNST_LIMB(0x654187c7),CNST_LIMB(0x19b0b8)), + P(2557,CNST_LIMB(0xda5b1b55),CNST_LIMB(0x19a149)), + P(2579,CNST_LIMB(0x7ae3501b),CNST_LIMB(0x196951)), + P(2591,CNST_LIMB(0x1b90f1df),CNST_LIMB(0x194b30)), + P(2593,CNST_LIMB(0x847df9e1),CNST_LIMB(0x194631)), + P(2609,CNST_LIMB(0x42b90ed1),CNST_LIMB(0x191e84)), + P(2617,CNST_LIMB(0x698cc409),CNST_LIMB(0x190adb)), + P(2621,CNST_LIMB(0x7cd35d15),CNST_LIMB(0x190113)), + P(2633,CNST_LIMB(0x723e07f9),CNST_LIMB(0x18e3e6)), + P(2647,CNST_LIMB(0xabaa8167),CNST_LIMB(0x18c233)), + P(2657,CNST_LIMB(0x5eb619a1),CNST_LIMB(0x18aa58)), + P(2659,CNST_LIMB(0x878ec74b),CNST_LIMB(0x18a598)), + P(2663,CNST_LIMB(0x4537157),CNST_LIMB(0x189c1e)), + P(2671,CNST_LIMB(0x862e948f),CNST_LIMB(0x18893f)), + P(2677,CNST_LIMB(0xcd81f5dd),CNST_LIMB(0x187b2b)), + P(2683,CNST_LIMB(0xc89044b3),CNST_LIMB(0x186d27)), + P(2687,CNST_LIMB(0x69f1b57f),CNST_LIMB(0x1863d8)), + P(2689,CNST_LIMB(0x8ace3581),CNST_LIMB(0x185f33)), + P(2693,CNST_LIMB(0x95a05e4d),CNST_LIMB(0x1855ef)), + P(2699,CNST_LIMB(0xa4908d23),CNST_LIMB(0x184816)), + P(2707,CNST_LIMB(0x628aa39b),CNST_LIMB(0x1835b7)), + P(2711,CNST_LIMB(0x7de01527),CNST_LIMB(0x182c92)), + P(2713,CNST_LIMB(0x670aa9a9),CNST_LIMB(0x182802)), + P(2719,CNST_LIMB(0x3b08915f),CNST_LIMB(0x181a5c)), + P(2729,CNST_LIMB(0xdb0a3999),CNST_LIMB(0x1803c0)), + P(2731,CNST_LIMB(0xbffa003),CNST_LIMB(0x17ff40)), + P(2741,CNST_LIMB(0xe936139d),CNST_LIMB(0x17e8d6)), + P(2749,CNST_LIMB(0x4c5cc095),CNST_LIMB(0x17d706)), + P(2753,CNST_LIMB(0x17278541),CNST_LIMB(0x17ce28)), + P(2767,CNST_LIMB(0xd292bc2f),CNST_LIMB(0x17af52)), + P(2777,CNST_LIMB(0x237dd569),CNST_LIMB(0x17997d)), + P(2789,CNST_LIMB(0x56bda2ed),CNST_LIMB(0x177f7e)), + P(2791,CNST_LIMB(0xe80f68d7),CNST_LIMB(0x177b2f)), + P(2797,CNST_LIMB(0xd875e2e5),CNST_LIMB(0x176e4a)), + P(2801,CNST_LIMB(0x5157a611),CNST_LIMB(0x1765b9)), + P(2803,CNST_LIMB(0xe9b71e3b),CNST_LIMB(0x176173)), + P(2819,CNST_LIMB(0xb38937ab),CNST_LIMB(0x173f7a)), + P(2833,CNST_LIMB(0x895a45f1),CNST_LIMB(0x172211)), + P(2837,CNST_LIMB(0x182eec3d),CNST_LIMB(0x1719b7)), + P(2843,CNST_LIMB(0x173b5713),CNST_LIMB(0x170d3c)), + P(2851,CNST_LIMB(0x3ae77c8b),CNST_LIMB(0x16fcad)), + P(2857,CNST_LIMB(0x828dc119),CNST_LIMB(0x16f051)), + P(2861,CNST_LIMB(0xc22b7ca5),CNST_LIMB(0x16e81b)), + P(2879,CNST_LIMB(0x1ead64bf),CNST_LIMB(0x16c372)), + P(2887,CNST_LIMB(0xe46c2e77),CNST_LIMB(0x16b34c)), + P(2897,CNST_LIMB(0x7b01db1),CNST_LIMB(0x169f3c)), + P(2903,CNST_LIMB(0x152a1067),CNST_LIMB(0x169344)), + P(2909,CNST_LIMB(0x997a0f5),CNST_LIMB(0x168759)), + P(2917,CNST_LIMB(0x10c32e6d),CNST_LIMB(0x167787)), + P(2927,CNST_LIMB(0x635b38f),CNST_LIMB(0x1663e1)), + P(2939,CNST_LIMB(0x97a61bb3),CNST_LIMB(0x164c7a)), + P(2953,CNST_LIMB(0x62bddab9),CNST_LIMB(0x16316a)), + P(2957,CNST_LIMB(0x2ed62f45),CNST_LIMB(0x1629ba)), + P(2963,CNST_LIMB(0x1a2dca9b),CNST_LIMB(0x161e3d)), + P(2969,CNST_LIMB(0x733218a9),CNST_LIMB(0x1612cc)), + P(2971,CNST_LIMB(0x7f186293),CNST_LIMB(0x160efe)), + P(2999,CNST_LIMB(0x3fd9c207),CNST_LIMB(0x15da45)), + P(3001,CNST_LIMB(0x2ae88a89),CNST_LIMB(0x15d68a)), + P(3011,CNST_LIMB(0x4046bceb),CNST_LIMB(0x15c3f9)), + P(3019,CNST_LIMB(0x60541e3),CNST_LIMB(0x15b535)), + P(3023,CNST_LIMB(0xea111b2f),CNST_LIMB(0x15addb)), + P(3037,CNST_LIMB(0xa855a475),CNST_LIMB(0x159445)), + P(3041,CNST_LIMB(0x600d7821),CNST_LIMB(0x158d01)), + P(3049,CNST_LIMB(0xa11f7c59),CNST_LIMB(0x157e87)), + P(3061,CNST_LIMB(0xbbac085d),CNST_LIMB(0x1568f5)), + P(3067,CNST_LIMB(0xc3114733),CNST_LIMB(0x155e3c)), + P(3079,CNST_LIMB(0x58a1a1b7),CNST_LIMB(0x1548ea)), + P(3083,CNST_LIMB(0xea691fa3),CNST_LIMB(0x1541d8)), + P(3089,CNST_LIMB(0xbd5e64f1),CNST_LIMB(0x153747)), + P(3109,CNST_LIMB(0x2bb92fad),CNST_LIMB(0x151456)), + P(3119,CNST_LIMB(0x27a4bacf),CNST_LIMB(0x150309)), + P(3121,CNST_LIMB(0x3d6fccd1),CNST_LIMB(0x14ff97)), + P(3137,CNST_LIMB(0x535203c1),CNST_LIMB(0x14e42c)), + P(3163,CNST_LIMB(0xfb4e43d3),CNST_LIMB(0x14b835)), + P(3167,CNST_LIMB(0xa5394f9f),CNST_LIMB(0x14b182)), + P(3169,CNST_LIMB(0x408b97a1),CNST_LIMB(0x14ae2a)), + P(3181,CNST_LIMB(0xdfa5dd65),CNST_LIMB(0x149a32)), + P(3187,CNST_LIMB(0x2e1b78bb),CNST_LIMB(0x149044)), + P(3191,CNST_LIMB(0x2a998d47),CNST_LIMB(0x1489aa)), + P(3203,CNST_LIMB(0xb131a22b),CNST_LIMB(0x1475f8)), + P(3209,CNST_LIMB(0xc30d29b9),CNST_LIMB(0x146c2c)), + P(3217,CNST_LIMB(0x11d3471),CNST_LIMB(0x145f2c)), + P(3221,CNST_LIMB(0xdff85ebd),CNST_LIMB(0x1458b2)), + P(3229,CNST_LIMB(0xc07ed9b5),CNST_LIMB(0x144bcb)), + P(3251,CNST_LIMB(0x71dd827b),CNST_LIMB(0x1428a1)), + P(3253,CNST_LIMB(0x1eed819d),CNST_LIMB(0x142575)), + P(3257,CNST_LIMB(0x7c443989),CNST_LIMB(0x141f20)), + P(3259,CNST_LIMB(0xf62e5873),CNST_LIMB(0x141bf6)), + P(3271,CNST_LIMB(0xec0af4f7),CNST_LIMB(0x140914)), + P(3299,CNST_LIMB(0xcea598cb),CNST_LIMB(0x13dd8b)), + P(3301,CNST_LIMB(0x61f2d0ed),CNST_LIMB(0x13da76)), + P(3307,CNST_LIMB(0xc7f43bc3),CNST_LIMB(0x13d13e)), + P(3313,CNST_LIMB(0xce016411),CNST_LIMB(0x13c80e)), + P(3319,CNST_LIMB(0x5f1a74c7),CNST_LIMB(0x13bee6)), + P(3323,CNST_LIMB(0xc1e81e33),CNST_LIMB(0x13b8d0)), + P(3329,CNST_LIMB(0x6ba8f301),CNST_LIMB(0x13afb7)), + P(3331,CNST_LIMB(0xdfcc5ab),CNST_LIMB(0x13acb0)), + P(3343,CNST_LIMB(0x3f2d41ef),CNST_LIMB(0x139a9c)), + P(3347,CNST_LIMB(0xdb35c51b),CNST_LIMB(0x13949c)), + P(3359,CNST_LIMB(0x66472edf),CNST_LIMB(0x1382b4)), + P(3361,CNST_LIMB(0xcbbfb6e1),CNST_LIMB(0x137fbb)), + P(3371,CNST_LIMB(0x8a84983),CNST_LIMB(0x1370ec)), + P(3373,CNST_LIMB(0x7b1acaa5),CNST_LIMB(0x136df9)), + P(3389,CNST_LIMB(0x4b9d3215),CNST_LIMB(0x13567d)), + P(3391,CNST_LIMB(0x781c62bf),CNST_LIMB(0x135392)), + P(3407,CNST_LIMB(0x1c06e9af),CNST_LIMB(0x133c56)), + P(3413,CNST_LIMB(0xed3f87fd),CNST_LIMB(0x1333ae)), + P(3433,CNST_LIMB(0x744152d9),CNST_LIMB(0x13170a)), + P(3449,CNST_LIMB(0xf5c1ccc9),CNST_LIMB(0x13005f)), + P(3457,CNST_LIMB(0x74563281),CNST_LIMB(0x12f51d)), + P(3461,CNST_LIMB(0x80b3e34d),CNST_LIMB(0x12ef81)), + P(3463,CNST_LIMB(0x8b202837),CNST_LIMB(0x12ecb4)), + P(3467,CNST_LIMB(0x52b3223),CNST_LIMB(0x12e71d)), + P(3469,CNST_LIMB(0x9af8fd45),CNST_LIMB(0x12e453)), + P(3491,CNST_LIMB(0x3ec58e0b),CNST_LIMB(0x12c5d9)), + P(3499,CNST_LIMB(0x68b28503),CNST_LIMB(0x12badc)), + P(3511,CNST_LIMB(0xfbfd6007),CNST_LIMB(0x12aa78)), + P(3517,CNST_LIMB(0x40ed9595),CNST_LIMB(0x12a251)), + P(3527,CNST_LIMB(0x236ba3f7),CNST_LIMB(0x1294cb)), + P(3529,CNST_LIMB(0x987b9c79),CNST_LIMB(0x129219)), + P(3533,CNST_LIMB(0x2bfba705),CNST_LIMB(0x128cb7)), + P(3539,CNST_LIMB(0x7e4cd25b),CNST_LIMB(0x1284aa)), + P(3541,CNST_LIMB(0x27b0c37d),CNST_LIMB(0x1281fc)), + P(3547,CNST_LIMB(0x81d72653),CNST_LIMB(0x1279f9)), + P(3557,CNST_LIMB(0xcb2c67ed),CNST_LIMB(0x126cad)), + P(3559,CNST_LIMB(0x54e0b5d7),CNST_LIMB(0x126a06)), + P(3571,CNST_LIMB(0x896d533b),CNST_LIMB(0x125a2f)), + P(3581,CNST_LIMB(0xb5023755),CNST_LIMB(0x124d10)), + P(3583,CNST_LIMB(0x473bf1ff),CNST_LIMB(0x124a73)), + P(3593,CNST_LIMB(0xa34de039),CNST_LIMB(0x123d6a)), + P(3607,CNST_LIMB(0xdf4809a7),CNST_LIMB(0x122b4b)), + P(3613,CNST_LIMB(0xba352435),CNST_LIMB(0x122391)), + P(3617,CNST_LIMB(0x58aef5e1),CNST_LIMB(0x121e6f)), + P(3623,CNST_LIMB(0x9c3a8197),CNST_LIMB(0x1216c0)), + P(3631,CNST_LIMB(0x2279f8cf),CNST_LIMB(0x120c8c)), + P(3637,CNST_LIMB(0x5ca1541d),CNST_LIMB(0x1204ed)), + P(3643,CNST_LIMB(0x60f99af3),CNST_LIMB(0x11fd54)), + P(3659,CNST_LIMB(0x72cfcb63),CNST_LIMB(0x11e931)), + P(3671,CNST_LIMB(0x8f3cbd67),CNST_LIMB(0x11da34)), + P(3673,CNST_LIMB(0xefe659e9),CNST_LIMB(0x11d7b6)), + P(3677,CNST_LIMB(0xa74d35f5),CNST_LIMB(0x11d2be)), + P(3691,CNST_LIMB(0x776f2e43),CNST_LIMB(0x11c170)), + P(3697,CNST_LIMB(0xd1e1f291),CNST_LIMB(0x11ba0f)), + P(3701,CNST_LIMB(0xcaced1dd),CNST_LIMB(0x11b528)), + P(3709,CNST_LIMB(0x110c5ad5),CNST_LIMB(0x11ab61)), + P(3719,CNST_LIMB(0x5acb5737),CNST_LIMB(0x119f37)), + P(3727,CNST_LIMB(0x1443506f),CNST_LIMB(0x119588)), + P(3733,CNST_LIMB(0x91dd4cbd),CNST_LIMB(0x118e4c)), + P(3739,CNST_LIMB(0xa61a2793),CNST_LIMB(0x118716)), + P(3761,CNST_LIMB(0x656b7a51),CNST_LIMB(0x116cd6)), + P(3767,CNST_LIMB(0xe1142f07),CNST_LIMB(0x1165bb)), + P(3769,CNST_LIMB(0x65119789),CNST_LIMB(0x11635e)), + P(3779,CNST_LIMB(0x3cb291eb),CNST_LIMB(0x115797)), + P(3793,CNST_LIMB(0xfd190a31),CNST_LIMB(0x114734)), + P(3797,CNST_LIMB(0xd6aba7d),CNST_LIMB(0x11428b)), + P(3803,CNST_LIMB(0xc5a33d53),CNST_LIMB(0x113b92)), + P(3821,CNST_LIMB(0x2dc27ee5),CNST_LIMB(0x1126ca)), + P(3823,CNST_LIMB(0x7bf2e00f),CNST_LIMB(0x11247e)), + P(3833,CNST_LIMB(0x4f695349),CNST_LIMB(0x11190b)), + P(3847,CNST_LIMB(0xe62e2eb7),CNST_LIMB(0x11091d)), + P(3851,CNST_LIMB(0xec96c4a3),CNST_LIMB(0x110496)), + P(3853,CNST_LIMB(0x187357c5),CNST_LIMB(0x110253)), + P(3863,CNST_LIMB(0x2d5418a7),CNST_LIMB(0x10f70d)), + P(3877,CNST_LIMB(0xa9e574ad),CNST_LIMB(0x10e75e)), + P(3881,CNST_LIMB(0x804bfd19),CNST_LIMB(0x10e2e9)), + P(3889,CNST_LIMB(0xcc20e9d1),CNST_LIMB(0x10da04)), + P(3907,CNST_LIMB(0x1300756b),CNST_LIMB(0x10c624)), + P(3911,CNST_LIMB(0x52eeea77),CNST_LIMB(0x10c1c0)), + P(3917,CNST_LIMB(0xacabc185),CNST_LIMB(0x10bb2e)), + P(3919,CNST_LIMB(0x9437a7af),CNST_LIMB(0x10b8fe)), + P(3923,CNST_LIMB(0x1b790cdb),CNST_LIMB(0x10b4a1)), + P(3929,CNST_LIMB(0x4d8948e9),CNST_LIMB(0x10ae19)), + P(3931,CNST_LIMB(0x145188d3),CNST_LIMB(0x10abec)), + P(3943,CNST_LIMB(0x6da89c57),CNST_LIMB(0x109eef)), + P(3947,CNST_LIMB(0x2124a543),CNST_LIMB(0x109a9f)), + P(3967,CNST_LIMB(0x632fb07f),CNST_LIMB(0x108531)), + P(3989,CNST_LIMB(0xf63ec3bd),CNST_LIMB(0x106dde)), + P(4001,CNST_LIMB(0xe5519461),CNST_LIMB(0x106141)), + P(4003,CNST_LIMB(0xb7289c0b),CNST_LIMB(0x105f29)), + P(4007,CNST_LIMB(0x7b9fa817),CNST_LIMB(0x105afa)), + P(4013,CNST_LIMB(0xabfc2c25),CNST_LIMB(0x1054b7)), + P(4019,CNST_LIMB(0x3c83377b),CNST_LIMB(0x104e79)), + P(4021,CNST_LIMB(0xc50ba69d),CNST_LIMB(0x104c66)), + P(4027,CNST_LIMB(0x65a65d73),CNST_LIMB(0x10462e)), + P(4049,CNST_LIMB(0x6bcca931),CNST_LIMB(0x102f8b)), + P(4051,CNST_LIMB(0x4a00205b),CNST_LIMB(0x102d7f)), + P(4057,CNST_LIMB(0x3d558069),CNST_LIMB(0x10275f)), + P(4073,CNST_LIMB(0xec53b859),CNST_LIMB(0x101721)), + P(4079,CNST_LIMB(0xf1e0ff0f),CNST_LIMB(0x101112)), + P(4091,CNST_LIMB(0x6870a333),CNST_LIMB(0x100501)), + P(4093,CNST_LIMB(0x971c555),CNST_LIMB(0x100300)), + P(4099,CNST_LIMB(0x84c71aab),CNST_LIMB(0xffd00)), + P(4111,CNST_LIMB(0x69bcdeef),CNST_LIMB(0xff10e)), + P(4127,CNST_LIMB(0x3c2b6bdf),CNST_LIMB(0xfe13b)), + P(4129,CNST_LIMB(0xfe5373e1),CNST_LIMB(0xfdf43)), + P(4133,CNST_LIMB(0xa71d8bad),CNST_LIMB(0xfdb54)), + P(4139,CNST_LIMB(0x5f302e83),CNST_LIMB(0xfd572)), + P(4153,CNST_LIMB(0xe55ede09),CNST_LIMB(0xfc7c8)), + P(4157,CNST_LIMB(0xd1910715),CNST_LIMB(0xfc3e5)), + P(4159,CNST_LIMB(0xfaf3dfbf),CNST_LIMB(0xfc1f4)), + P(4177,CNST_LIMB(0x287338b1),CNST_LIMB(0xfb092)), + P(4201,CNST_LIMB(0x3f9e7fd9),CNST_LIMB(0xf999f)), + P(4211,CNST_LIMB(0x62e914bb),CNST_LIMB(0xf9023)), + P(4217,CNST_LIMB(0x47c159c9),CNST_LIMB(0xf8a78)), + P(4219,CNST_LIMB(0x471d4eb3),CNST_LIMB(0xf8895)), + P(4229,CNST_LIMB(0x1c1684d),CNST_LIMB(0xf7f2e)), + P(4231,CNST_LIMB(0xed8bb537),CNST_LIMB(0xf7d4e)), + P(4241,CNST_LIMB(0x65c5b071),CNST_LIMB(0xf73f5)), + P(4243,CNST_LIMB(0xc3f78d9b),CNST_LIMB(0xf7217)), + P(4253,CNST_LIMB(0x1fe6f5b5),CNST_LIMB(0xf68cb)), + P(4259,CNST_LIMB(0x31f3230b),CNST_LIMB(0xf633d)), + P(4261,CNST_LIMB(0xe3f1572d),CNST_LIMB(0xf6163)), + P(4271,CNST_LIMB(0xd805464f),CNST_LIMB(0xf582b)), + P(4273,CNST_LIMB(0x36943851),CNST_LIMB(0xf5654)), + P(4283,CNST_LIMB(0xf7cfb473),CNST_LIMB(0xf4d2a)), + P(4289,CNST_LIMB(0x36ac7f41),CNST_LIMB(0xf47af)), + P(4297,CNST_LIMB(0x1dd90979),CNST_LIMB(0xf4066)), + P(4327,CNST_LIMB(0x77b002d7),CNST_LIMB(0xf2555)), + P(4337,CNST_LIMB(0x83ece011),CNST_LIMB(0xf1c64)), + P(4339,CNST_LIMB(0x43d9883b),CNST_LIMB(0xf1a9b)), + P(4349,CNST_LIMB(0x28708c55),CNST_LIMB(0xf11b7)), + P(4357,CNST_LIMB(0xef2313cd),CNST_LIMB(0xf0aa2)), + P(4363,CNST_LIMB(0x4c8332a3),CNST_LIMB(0xf0556)), + P(4373,CNST_LIMB(0xf43bb63d),CNST_LIMB(0xefc8b)), + P(4391,CNST_LIMB(0x2ce44e97),CNST_LIMB(0xeecd1)), + P(4397,CNST_LIMB(0x1db166a5),CNST_LIMB(0xee79a)), + P(4409,CNST_LIMB(0xd19b8d09),CNST_LIMB(0xedd38)), + P(4421,CNST_LIMB(0x45b7d98d),CNST_LIMB(0xed2e4)), + P(4423,CNST_LIMB(0x9a044877),CNST_LIMB(0xed12c)), + P(4441,CNST_LIMB(0x67a526e9),CNST_LIMB(0xec1cd)), + P(4447,CNST_LIMB(0x18688a9f),CNST_LIMB(0xebcb4)), + P(4451,CNST_LIMB(0xf741f84b),CNST_LIMB(0xeb950)), + P(4457,CNST_LIMB(0x41e18ed9),CNST_LIMB(0xeb43d)), + P(4463,CNST_LIMB(0x97166d8f),CNST_LIMB(0xeaf2d)), + P(4481,CNST_LIMB(0x21d22e81),CNST_LIMB(0xea014)), + P(4483,CNST_LIMB(0xec4c852b),CNST_LIMB(0xe9e68)), + P(4493,CNST_LIMB(0x78f69945),CNST_LIMB(0xe9614)), + P(4507,CNST_LIMB(0xc61ec93),CNST_LIMB(0xe8a7a)), + P(4513,CNST_LIMB(0xbd3c1261),CNST_LIMB(0xe8587)), + P(4517,CNST_LIMB(0x5a486e2d),CNST_LIMB(0xe823d)), + P(4519,CNST_LIMB(0x31578617),CNST_LIMB(0xe8098)), + P(4523,CNST_LIMB(0x79ea6103),CNST_LIMB(0xe7d4f)), + P(4547,CNST_LIMB(0x19f466eb),CNST_LIMB(0xe69bb)), + P(4549,CNST_LIMB(0xab1450d),CNST_LIMB(0xe681c)), + P(4561,CNST_LIMB(0x2a99e731),CNST_LIMB(0xe5e68)), + P(4567,CNST_LIMB(0xe67071e7),CNST_LIMB(0xe5993)), + P(4583,CNST_LIMB(0xba6671d7),CNST_LIMB(0xe4cbf)), + P(4591,CNST_LIMB(0xd4d73d0f),CNST_LIMB(0xe465e)), + P(4597,CNST_LIMB(0x28b5525d),CNST_LIMB(0xe4199)), + P(4603,CNST_LIMB(0xe9245133),CNST_LIMB(0xe3cd8)), + P(4621,CNST_LIMB(0xc09f8cc5),CNST_LIMB(0xe2ea5)), + P(4637,CNST_LIMB(0x4f394035),CNST_LIMB(0xe221e)), + P(4639,CNST_LIMB(0x564ee9df),CNST_LIMB(0xe208f)), + P(4643,CNST_LIMB(0xd822d8b),CNST_LIMB(0xe1d71)), + P(4649,CNST_LIMB(0x8857aa19),CNST_LIMB(0xe18c7)), + P(4651,CNST_LIMB(0x4eee1c83),CNST_LIMB(0xe173a)), + P(4657,CNST_LIMB(0xb2c406d1),CNST_LIMB(0xe1294)), + P(4663,CNST_LIMB(0x8d5e4387),CNST_LIMB(0xe0df1)), + P(4673,CNST_LIMB(0xa3e8fdc1),CNST_LIMB(0xe063e)), + P(4679,CNST_LIMB(0xcc83f777),CNST_LIMB(0xe01a4)), + P(4691,CNST_LIMB(0xc0ea01db),CNST_LIMB(0xdf878)), + P(4703,CNST_LIMB(0xcb78c99f),CNST_LIMB(0xdef57)), + P(4721,CNST_LIMB(0x5b196e91),CNST_LIMB(0xde1bd)), + P(4723,CNST_LIMB(0x4273e2bb),CNST_LIMB(0xde03c)), + P(4729,CNST_LIMB(0xb165b7c9),CNST_LIMB(0xddbba)), + P(4733,CNST_LIMB(0x2e0776d5),CNST_LIMB(0xdd8bb)), + P(4751,CNST_LIMB(0x3af2cc6f),CNST_LIMB(0xdcb4d)), + P(4759,CNST_LIMB(0x30408d27),CNST_LIMB(0xdc55d)), + P(4783,CNST_LIMB(0x6528844f),CNST_LIMB(0xdb3ad)), + P(4787,CNST_LIMB(0x2b5eec7b),CNST_LIMB(0xdb0be)), + P(4789,CNST_LIMB(0x7503cb9d),CNST_LIMB(0xdaf48)), + P(4793,CNST_LIMB(0xa7045389),CNST_LIMB(0xdac5b)), + P(4799,CNST_LIMB(0x4dd45d3f),CNST_LIMB(0xda7fb)), + P(4801,CNST_LIMB(0xb2937d41),CNST_LIMB(0xda686)), + P(4813,CNST_LIMB(0x54922a05),CNST_LIMB(0xd9dd0)), + P(4817,CNST_LIMB(0x6eb38631),CNST_LIMB(0xd9aeb)), + P(4831,CNST_LIMB(0x5a08291f),CNST_LIMB(0xd90d3)), + P(4861,CNST_LIMB(0x91fc1a55),CNST_LIMB(0xd7b64)), + P(4871,CNST_LIMB(0x5382eab7),CNST_LIMB(0xd744e)), + P(4877,CNST_LIMB(0xde4cf3c5),CNST_LIMB(0xd7011)), + P(4889,CNST_LIMB(0x68b9929),CNST_LIMB(0xd67a0)), + P(4903,CNST_LIMB(0x40462c97),CNST_LIMB(0xd5dd3)), + P(4909,CNST_LIMB(0xa758b4a5),CNST_LIMB(0xd59a4)), + P(4919,CNST_LIMB(0x3c441287),CNST_LIMB(0xd52b2)), + P(4931,CNST_LIMB(0xec45916b),CNST_LIMB(0xd4a65)), + P(4933,CNST_LIMB(0xf55c878d),CNST_LIMB(0xd4904)), + P(4937,CNST_LIMB(0x2ca54ef9),CNST_LIMB(0xd4642)), + P(4943,CNST_LIMB(0xf60123af),CNST_LIMB(0xd4222)), + P(4951,CNST_LIMB(0x6a9e8867),CNST_LIMB(0xd3ca6)), + P(4957,CNST_LIMB(0xb383d8f5),CNST_LIMB(0xd388c)), + P(4967,CNST_LIMB(0x89825857),CNST_LIMB(0xd31bc)), + P(4969,CNST_LIMB(0xc01dacd9),CNST_LIMB(0xd3060)), + P(4973,CNST_LIMB(0x7aedee65),CNST_LIMB(0xd2da9)), + P(4987,CNST_LIMB(0xa86cd3b3),CNST_LIMB(0xd2430)), + P(4993,CNST_LIMB(0x1a9c2c81),CNST_LIMB(0xd2025)), + P(4999,CNST_LIMB(0x90354237),CNST_LIMB(0xd1c1d)), + P(5003,CNST_LIMB(0x9c527c23),CNST_LIMB(0xd196e)), + P(5009,CNST_LIMB(0x30e90d71),CNST_LIMB(0xd156a)), + P(5011,CNST_LIMB(0x7b1f029b),CNST_LIMB(0xd1413)), + P(5021,CNST_LIMB(0x37860ab5),CNST_LIMB(0xd0d68)), + P(5023,CNST_LIMB(0x910c485f),CNST_LIMB(0xd0c14)), + P(5039,CNST_LIMB(0x2487234f),CNST_LIMB(0xd0179)), + P(5051,CNST_LIMB(0x614fb973),CNST_LIMB(0xcf990)), + P(5059,CNST_LIMB(0x8508f4eb),CNST_LIMB(0xcf44f)), + P(5077,CNST_LIMB(0x27e28d7d),CNST_LIMB(0xce88d)), + P(5081,CNST_LIMB(0x10393c69),CNST_LIMB(0xce5f3)), + P(5087,CNST_LIMB(0x7d75681f),CNST_LIMB(0xce20e)), + P(5099,CNST_LIMB(0xef217cc3),CNST_LIMB(0xcda4b)), + P(5101,CNST_LIMB(0x87b41e5),CNST_LIMB(0xcd901)), + P(5107,CNST_LIMB(0x96fbbd3b),CNST_LIMB(0xcd524)), + P(5113,CNST_LIMB(0x55443e49),CNST_LIMB(0xcd149)), + P(5119,CNST_LIMB(0xbe6febff),CNST_LIMB(0xccd70)), + P(5147,CNST_LIMB(0xe62fa613),CNST_LIMB(0xcbb9c)), + P(5153,CNST_LIMB(0xd0b46fe1),CNST_LIMB(0xcb7d0)), + P(5167,CNST_LIMB(0x37c9b2cf),CNST_LIMB(0xcaefe)), + P(5171,CNST_LIMB(0x27c106fb),CNST_LIMB(0xcac7b)), + P(5179,CNST_LIMB(0xdc75a4f3),CNST_LIMB(0xca778)), + P(5189,CNST_LIMB(0x696dde8d),CNST_LIMB(0xca13a)), + P(5197,CNST_LIMB(0xb1554485),CNST_LIMB(0xc9c40)), + P(5209,CNST_LIMB(0x61e5f3e9),CNST_LIMB(0xc94d0)), + P(5227,CNST_LIMB(0x3959f843),CNST_LIMB(0xc89b8)), + P(5231,CNST_LIMB(0x9fbca8f),CNST_LIMB(0xc8744)), + P(5233,CNST_LIMB(0x68012c91),CNST_LIMB(0xc860a)), + P(5237,CNST_LIMB(0xf5ee1bdd),CNST_LIMB(0xc8397)), + P(5261,CNST_LIMB(0x7775ce45),CNST_LIMB(0xc74fa)), + P(5273,CNST_LIMB(0xfd9effa9),CNST_LIMB(0xc6db8)), + P(5279,CNST_LIMB(0x9f98075f),CNST_LIMB(0xc6a1a)), + P(5281,CNST_LIMB(0x810acf61),CNST_LIMB(0xc68e6)), + P(5297,CNST_LIMB(0x77db451),CNST_LIMB(0xc5f4e)), + P(5303,CNST_LIMB(0x67e30907),CNST_LIMB(0xc5bb8)), + P(5309,CNST_LIMB(0xbd8d8695),CNST_LIMB(0xc5825)), + P(5323,CNST_LIMB(0xa2a6b0e3),CNST_LIMB(0xc4fd5)), + P(5333,CNST_LIMB(0x9c58847d),CNST_LIMB(0xc49ec)), + P(5347,CNST_LIMB(0x2dddd0cb),CNST_LIMB(0xc41b0)), + P(5351,CNST_LIMB(0x53ddbed7),CNST_LIMB(0xc3f57)), + P(5381,CNST_LIMB(0xb42a6fcd),CNST_LIMB(0xc2ddc)), + P(5387,CNST_LIMB(0x63e40ea3),CNST_LIMB(0xc2a63)), + P(5393,CNST_LIMB(0xe4fd7bf1),CNST_LIMB(0xc26ec)), + P(5399,CNST_LIMB(0x12a272a7),CNST_LIMB(0xc2377)), + P(5407,CNST_LIMB(0x56d526df),CNST_LIMB(0xc1ede)), + P(5413,CNST_LIMB(0xdaebfead),CNST_LIMB(0xc1b6e)), + P(5417,CNST_LIMB(0xf7055719),CNST_LIMB(0xc1924)), + P(5419,CNST_LIMB(0xcfa00183),CNST_LIMB(0xc17ff)), + P(5431,CNST_LIMB(0x9919b087),CNST_LIMB(0xc1128)), + P(5437,CNST_LIMB(0x652f6a15),CNST_LIMB(0xc0dbf)), + P(5441,CNST_LIMB(0xf70f7ac1),CNST_LIMB(0xc0b7a)), + P(5443,CNST_LIMB(0x4cc1f6b),CNST_LIMB(0xc0a58)), + P(5449,CNST_LIMB(0xe5ececf9),CNST_LIMB(0xc06f4)), + P(5471,CNST_LIMB(0x171d869f),CNST_LIMB(0xbfa92)), + P(5477,CNST_LIMB(0x21ef146d),CNST_LIMB(0xbf736)), + P(5479,CNST_LIMB(0x22c33657),CNST_LIMB(0xbf618)), + P(5483,CNST_LIMB(0x4f536f43),CNST_LIMB(0xbf3dc)), + P(5501,CNST_LIMB(0x8fb4cbd5),CNST_LIMB(0xbe9d9)), + P(5503,CNST_LIMB(0x1bd1aa7f),CNST_LIMB(0xbe8bd)), + P(5507,CNST_LIMB(0x4ea7a12b),CNST_LIMB(0xbe686)), + P(5519,CNST_LIMB(0xdd71696f),CNST_LIMB(0xbdfe6)), + P(5521,CNST_LIMB(0x88d54b71),CNST_LIMB(0xbdecc)), + P(5527,CNST_LIMB(0x8dbbba27),CNST_LIMB(0xbdb80)), + P(5531,CNST_LIMB(0x7ba04893),CNST_LIMB(0xbd94e)), + P(5557,CNST_LIMB(0xecd5f09d),CNST_LIMB(0xbcb1d)), + P(5563,CNST_LIMB(0x96286773),CNST_LIMB(0xbc7db)), + P(5569,CNST_LIMB(0x31bcfa41),CNST_LIMB(0xbc49b)), + P(5573,CNST_LIMB(0x5bf6a10d),CNST_LIMB(0xbc272)), + P(5581,CNST_LIMB(0x5f0adf05),CNST_LIMB(0xbbe21)), + P(5591,CNST_LIMB(0xfee6ade7),CNST_LIMB(0xbb8c1)), + P(5623,CNST_LIMB(0x68593bc7),CNST_LIMB(0xba7ad)), + P(5639,CNST_LIMB(0xd7f577b7),CNST_LIMB(0xb9f36)), + P(5641,CNST_LIMB(0xf285839),CNST_LIMB(0xb9e28)), + P(5647,CNST_LIMB(0x6e8618ef),CNST_LIMB(0xb9aff)), + P(5651,CNST_LIMB(0x97f1241b),CNST_LIMB(0xb98e4)), + P(5653,CNST_LIMB(0xa364093d),CNST_LIMB(0xb97d7)), + P(5657,CNST_LIMB(0x5d72e629),CNST_LIMB(0xb95be)), + P(5659,CNST_LIMB(0x6410d413),CNST_LIMB(0xb94b2)), + P(5669,CNST_LIMB(0x5ba015ad),CNST_LIMB(0xb8f77)), + P(5683,CNST_LIMB(0x8458d4fb),CNST_LIMB(0xb882d)), + P(5689,CNST_LIMB(0x7e38f809),CNST_LIMB(0xb850f)), + P(5693,CNST_LIMB(0xfaf6b115),CNST_LIMB(0xb82fd)), + P(5701,CNST_LIMB(0x8c0e8c8d),CNST_LIMB(0xb7eda)), + P(5711,CNST_LIMB(0x659340af),CNST_LIMB(0xb79b3)), + P(5717,CNST_LIMB(0x3a6436fd),CNST_LIMB(0xb769e)), + P(5737,CNST_LIMB(0x93bed9d9),CNST_LIMB(0xb6c63)), + P(5741,CNST_LIMB(0x91976365),CNST_LIMB(0xb6a59)), + P(5743,CNST_LIMB(0x94c0088f),CNST_LIMB(0xb6955)), + P(5749,CNST_LIMB(0xb74889dd),CNST_LIMB(0xb6648)), + P(5779,CNST_LIMB(0x893c779b),CNST_LIMB(0xb5722)), + P(5783,CNST_LIMB(0x8bc0c927),CNST_LIMB(0xb5520)), + P(5791,CNST_LIMB(0x3369855f),CNST_LIMB(0xb511e)), + P(5801,CNST_LIMB(0x638ed99),CNST_LIMB(0xb4c1f)), + P(5807,CNST_LIMB(0xfdd7004f),CNST_LIMB(0xb4922)), + P(5813,CNST_LIMB(0xfdaa79d),CNST_LIMB(0xb4627)), + P(5821,CNST_LIMB(0x5f9c1495),CNST_LIMB(0xb4230)), + P(5827,CNST_LIMB(0xf104c9eb),CNST_LIMB(0xb3f38)), + P(5839,CNST_LIMB(0x263b302f),CNST_LIMB(0xb394d)), + P(5843,CNST_LIMB(0x9110b15b),CNST_LIMB(0xb3756)), + P(5849,CNST_LIMB(0x18d10969),CNST_LIMB(0xb3463)), + P(5851,CNST_LIMB(0xd31bf553),CNST_LIMB(0xb3368)), + P(5857,CNST_LIMB(0x3c67ad21),CNST_LIMB(0xb3078)), + P(5861,CNST_LIMB(0x72d4b6ed),CNST_LIMB(0xb2e84)), + P(5867,CNST_LIMB(0x24dee1c3),CNST_LIMB(0xb2b97)), + P(5869,CNST_LIMB(0x633bb6e5),CNST_LIMB(0xb2a9d)), + P(5879,CNST_LIMB(0x549b8ac7),CNST_LIMB(0xb25c0)), + P(5881,CNST_LIMB(0xa252cb49),CNST_LIMB(0xb24c8)), + P(5897,CNST_LIMB(0xd254a739),CNST_LIMB(0xb1d0a)), + P(5903,CNST_LIMB(0x23a5f7ef),CNST_LIMB(0xb1a26)), + P(5923,CNST_LIMB(0x742dd08b),CNST_LIMB(0xb108d)), + P(5927,CNST_LIMB(0x6fb1e897),CNST_LIMB(0xb0ea4)), + P(5939,CNST_LIMB(0xb92dbbfb),CNST_LIMB(0xb08ec)), + P(5953,CNST_LIMB(0x7b0878c1),CNST_LIMB(0xb0247)), + P(5981,CNST_LIMB(0xdee9f4f5),CNST_LIMB(0xaf515)), + P(5987,CNST_LIMB(0x910a224b),CNST_LIMB(0xaf246)), + P(6007,CNST_LIMB(0xbd4df247),CNST_LIMB(0xae8f1)), + P(6011,CNST_LIMB(0x50e02fb3),CNST_LIMB(0xae715)), + P(6029,CNST_LIMB(0x43f0345),CNST_LIMB(0xadec0)), + P(6037,CNST_LIMB(0x93b27bbd),CNST_LIMB(0xadb10)), + P(6043,CNST_LIMB(0x8ec37693),CNST_LIMB(0xad84e)), + P(6047,CNST_LIMB(0xacaf445f),CNST_LIMB(0xad678)), + P(6053,CNST_LIMB(0x5884f82d),CNST_LIMB(0xad3b8)), + P(6067,CNST_LIMB(0x7c9a6f7b),CNST_LIMB(0xacd52)), + P(6073,CNST_LIMB(0xdd18be89),CNST_LIMB(0xaca97)), + P(6079,CNST_LIMB(0x684fd83f),CNST_LIMB(0xac7dd)), + P(6089,CNST_LIMB(0x8f93b279),CNST_LIMB(0xac354)), + P(6091,CNST_LIMB(0x2a7dd5e3),CNST_LIMB(0xac26d)), + P(6101,CNST_LIMB(0x1276697d),CNST_LIMB(0xabde9)), + P(6113,CNST_LIMB(0x6b2a6c21),CNST_LIMB(0xab883)), + P(6121,CNST_LIMB(0xae1c3059),CNST_LIMB(0xab4ed)), + P(6131,CNST_LIMB(0x227d593b),CNST_LIMB(0xab074)), + P(6133,CNST_LIMB(0xf7269c5d),CNST_LIMB(0xaaf90)), + P(6143,CNST_LIMB(0xfdbfe7ff),CNST_LIMB(0xaab1c)), + P(6151,CNST_LIMB(0x2e47d5b7),CNST_LIMB(0xaa78f)), + P(6163,CNST_LIMB(0x9847721b),CNST_LIMB(0xaa23f)), + P(6173,CNST_LIMB(0x83cb6a35),CNST_LIMB(0xa9dd6)), + P(6197,CNST_LIMB(0xf9247a1d),CNST_LIMB(0xa9350)), + P(6199,CNST_LIMB(0x87f31d87),CNST_LIMB(0xa9270)), + P(6203,CNST_LIMB(0xea2b00f3),CNST_LIMB(0xa90b1)), + P(6211,CNST_LIMB(0x4972f46b),CNST_LIMB(0xa8d35)), + P(6217,CNST_LIMB(0x11bf59f9),CNST_LIMB(0xa8a9a)), + P(6221,CNST_LIMB(0xed70e085),CNST_LIMB(0xa88de)), + P(6229,CNST_LIMB(0xf68c24fd),CNST_LIMB(0xa8567)), + P(6247,CNST_LIMB(0xafcd8357),CNST_LIMB(0xa7da4)), + P(6257,CNST_LIMB(0x2268a891),CNST_LIMB(0xa7959)), + P(6263,CNST_LIMB(0xc8154147),CNST_LIMB(0xa76c8)), + P(6269,CNST_LIMB(0xe30c20d5),CNST_LIMB(0xa7438)), + P(6271,CNST_LIMB(0x7b87a77f),CNST_LIMB(0xa735d)), + P(6277,CNST_LIMB(0x11c8204d),CNST_LIMB(0xa70ce)), + P(6287,CNST_LIMB(0x77e066f),CNST_LIMB(0xa6c8e)), + P(6299,CNST_LIMB(0x4a360d93),CNST_LIMB(0xa6779)), + P(6301,CNST_LIMB(0x23972db5),CNST_LIMB(0xa66a0)), + P(6311,CNST_LIMB(0x12940f17),CNST_LIMB(0xa6268)), + P(6317,CNST_LIMB(0x7410b25),CNST_LIMB(0xa5fe2)), + P(6323,CNST_LIMB(0x6db8567b),CNST_LIMB(0xa5d5c)), + P(6329,CNST_LIMB(0x52cc6d89),CNST_LIMB(0xa5ad9)), + P(6337,CNST_LIMB(0xda787741),CNST_LIMB(0xa5780)), + P(6343,CNST_LIMB(0x94af28f7),CNST_LIMB(0xa54ff)), + P(6353,CNST_LIMB(0x8f174031),CNST_LIMB(0xa50d5)), + P(6359,CNST_LIMB(0x36825ae7),CNST_LIMB(0xa4e57)), + P(6361,CNST_LIMB(0x4f9ae769),CNST_LIMB(0xa4d83)), + P(6367,CNST_LIMB(0xe9b9a31f),CNST_LIMB(0xa4b06)), + P(6373,CNST_LIMB(0xb7f9e4ed),CNST_LIMB(0xa488b)), + P(6379,CNST_LIMB(0x8195cfc3),CNST_LIMB(0xa4611)), + P(6389,CNST_LIMB(0xc2b1d35d),CNST_LIMB(0xa41f4)), + P(6397,CNST_LIMB(0x7b0ec455),CNST_LIMB(0xa3eab)), + P(6421,CNST_LIMB(0x57276e3d),CNST_LIMB(0xa34dd)), + P(6427,CNST_LIMB(0x17c79913),CNST_LIMB(0xa326d)), + P(6449,CNST_LIMB(0xa3269fd1),CNST_LIMB(0xa2985)), + P(6451,CNST_LIMB(0xf1e989fb),CNST_LIMB(0xa28b7)), + P(6469,CNST_LIMB(0xd83a918d),CNST_LIMB(0xa217a)), + P(6473,CNST_LIMB(0x305428f9),CNST_LIMB(0xa1fe0)), + P(6481,CNST_LIMB(0x3696cfb1),CNST_LIMB(0xa1cad)), + P(6491,CNST_LIMB(0x87f26ed3),CNST_LIMB(0xa18b0)), + P(6521,CNST_LIMB(0xf04c00c9),CNST_LIMB(0xa0ccc)), + P(6529,CNST_LIMB(0x4d2a2681),CNST_LIMB(0xa09a5)), + P(6547,CNST_LIMB(0x6c4fec9b),CNST_LIMB(0xa0294)), + P(6551,CNST_LIMB(0x4e63f627),CNST_LIMB(0xa0104)), + P(6553,CNST_LIMB(0x71c2aa9),CNST_LIMB(0xa003c)), + P(6563,CNST_LIMB(0x20ffe20b),CNST_LIMB(0x9fc55)), + P(6569,CNST_LIMB(0x57199a99),CNST_LIMB(0x9f9ff)), + P(6571,CNST_LIMB(0x467a1903),CNST_LIMB(0x9f938)), + P(6577,CNST_LIMB(0xb4fe8f51),CNST_LIMB(0x9f6e4)), + P(6581,CNST_LIMB(0xd624cc9d),CNST_LIMB(0x9f557)), + P(6599,CNST_LIMB(0x9bb7d7f7),CNST_LIMB(0x9ee63)), + P(6607,CNST_LIMB(0x6a484d2f),CNST_LIMB(0x9eb4f)), + P(6619,CNST_LIMB(0x6f143a53),CNST_LIMB(0x9e6b4)), + P(6637,CNST_LIMB(0xe0062be5),CNST_LIMB(0x9dfd4)), + P(6653,CNST_LIMB(0x36b78b55),CNST_LIMB(0x9d9c0)), + P(6659,CNST_LIMB(0x4064e0ab),CNST_LIMB(0x9d77a)), + P(6661,CNST_LIMB(0x27e4a2cd),CNST_LIMB(0x9d6b9)), + P(6673,CNST_LIMB(0x690a16f1),CNST_LIMB(0x9d231)), + P(6679,CNST_LIMB(0x6034bda7),CNST_LIMB(0x9cfef)), + P(6689,CNST_LIMB(0xe01e9e1),CNST_LIMB(0x9cc2e)), + P(6691,CNST_LIMB(0x48f6658b),CNST_LIMB(0x9cb6e)), + P(6701,CNST_LIMB(0xe0545a5),CNST_LIMB(0x9c7b0)), + P(6703,CNST_LIMB(0x14516ccf),CNST_LIMB(0x9c6f0)), + P(6709,CNST_LIMB(0x96e9e81d),CNST_LIMB(0x9c4b3)), + P(6719,CNST_LIMB(0xf46ad5bf),CNST_LIMB(0x9c0fb)), + P(6733,CNST_LIMB(0xeb5aae85),CNST_LIMB(0x9bbca)), + P(6737,CNST_LIMB(0x73ef6eb1),CNST_LIMB(0x9ba4f)), + P(6761,CNST_LIMB(0xc1e715d9),CNST_LIMB(0x9b178)), + P(6763,CNST_LIMB(0xa8dcc243),CNST_LIMB(0x9b0bc)), + P(6779,CNST_LIMB(0x7a3db4b3),CNST_LIMB(0x9aae1)), + P(6781,CNST_LIMB(0x50ddaed5),CNST_LIMB(0x9aa26)), + P(6791,CNST_LIMB(0xb7958b37),CNST_LIMB(0x9a681)), + P(6793,CNST_LIMB(0x5a857bb9),CNST_LIMB(0x9a5c7)), + P(6803,CNST_LIMB(0x198d139b),CNST_LIMB(0x9a226)), + P(6823,CNST_LIMB(0xc547ed17),CNST_LIMB(0x99aeb)), + P(6827,CNST_LIMB(0x4aff1003),CNST_LIMB(0x9997a)), + P(6829,CNST_LIMB(0xee4e5925),CNST_LIMB(0x998c2)), + P(6833,CNST_LIMB(0x6557ee51),CNST_LIMB(0x99752)), + P(6841,CNST_LIMB(0xac49cb89),CNST_LIMB(0x99473)), + P(6857,CNST_LIMB(0x5c8d1f79),CNST_LIMB(0x98eba)), + P(6863,CNST_LIMB(0x5088ac2f),CNST_LIMB(0x98c96)), + P(6869,CNST_LIMB(0x4fae4e7d),CNST_LIMB(0x98a74)), + P(6871,CNST_LIMB(0x77e578e7),CNST_LIMB(0x989be)), + P(6883,CNST_LIMB(0x2703facb),CNST_LIMB(0x9857c)), + P(6899,CNST_LIMB(0x6e9d8e3b),CNST_LIMB(0x97fd5)), + P(6907,CNST_LIMB(0x6aede033),CNST_LIMB(0x97d04)), + P(6911,CNST_LIMB(0x1a26e4ff),CNST_LIMB(0x97b9c)), + P(6917,CNST_LIMB(0x31a179cd),CNST_LIMB(0x97981)), + P(6947,CNST_LIMB(0xdeafec8b),CNST_LIMB(0x96f07)), + P(6949,CNST_LIMB(0x44da88ad),CNST_LIMB(0x96e55)), + P(6959,CNST_LIMB(0x31710bcf),CNST_LIMB(0x96add)), + P(6961,CNST_LIMB(0x22595dd1),CNST_LIMB(0x96a2c)), + P(6967,CNST_LIMB(0xf7ea8a87),CNST_LIMB(0x96818)), + P(6971,CNST_LIMB(0x3c3a05f3),CNST_LIMB(0x966b7)), + P(6977,CNST_LIMB(0xc91274c1),CNST_LIMB(0x964a5)), + P(6983,CNST_LIMB(0x1bb71e77),CNST_LIMB(0x96294)), + P(6991,CNST_LIMB(0x3f341baf),CNST_LIMB(0x95fd4)), + P(6997,CNST_LIMB(0x593309fd),CNST_LIMB(0x95dc5)), + P(7001,CNST_LIMB(0x3ae87ce9),CNST_LIMB(0x95c67)), + P(7013,CNST_LIMB(0x301c9e6d),CNST_LIMB(0x9584d)), + P(7019,CNST_LIMB(0xd31a3943),CNST_LIMB(0x95641)), + P(7027,CNST_LIMB(0x6dcd81bb),CNST_LIMB(0x95389)), + P(7039,CNST_LIMB(0xb02ba47f),CNST_LIMB(0x94f77)), + P(7043,CNST_LIMB(0xc8a44b2b),CNST_LIMB(0x94e1c)), + P(7057,CNST_LIMB(0xcfca0571),CNST_LIMB(0x94962)), + P(7069,CNST_LIMB(0x5a642b5),CNST_LIMB(0x94559)), + P(7079,CNST_LIMB(0xb536dc17),CNST_LIMB(0x941ff)), + P(7103,CNST_LIMB(0x82c1d43f),CNST_LIMB(0x939fd)), + P(7109,CNST_LIMB(0x34caab0d),CNST_LIMB(0x937ff)), + P(7121,CNST_LIMB(0x68941d31),CNST_LIMB(0x93405)), + P(7127,CNST_LIMB(0x357c07e7),CNST_LIMB(0x93209)), + P(7129,CNST_LIMB(0x7360b469),CNST_LIMB(0x93160)), + P(7151,CNST_LIMB(0x79ae730f),CNST_LIMB(0x92a22)), + P(7159,CNST_LIMB(0x319915c7),CNST_LIMB(0x92783)), + P(7177,CNST_LIMB(0xc6803239),CNST_LIMB(0x921a2)), + P(7187,CNST_LIMB(0x2e3c0e1b),CNST_LIMB(0x91e62)), + P(7193,CNST_LIMB(0x3f478029),CNST_LIMB(0x91c6f)), + P(7207,CNST_LIMB(0x8c339397),CNST_LIMB(0x917e7)), + P(7211,CNST_LIMB(0xfe4bc283),CNST_LIMB(0x9169d)), + P(7213,CNST_LIMB(0xc6c093a5),CNST_LIMB(0x915f8)), + P(7219,CNST_LIMB(0x12b03efb),CNST_LIMB(0x91409)), + P(7229,CNST_LIMB(0xe9045b15),CNST_LIMB(0x910d2)), + P(7237,CNST_LIMB(0x17e0968d),CNST_LIMB(0x90e41)), + P(7243,CNST_LIMB(0xe1c7cd63),CNST_LIMB(0x90c55)), + P(7247,CNST_LIMB(0x9fe17aaf),CNST_LIMB(0x90b0e)), + P(7253,CNST_LIMB(0xe45400fd),CNST_LIMB(0x90924)), + P(7283,CNST_LIMB(0xd391e8bb),CNST_LIMB(0x8ff9d)), + P(7297,CNST_LIMB(0xa60c2381),CNST_LIMB(0x8fb31)), + P(7307,CNST_LIMB(0x37ea6b23),CNST_LIMB(0x8f80c)), + P(7309,CNST_LIMB(0x9dc10645),CNST_LIMB(0x8f76b)), + P(7321,CNST_LIMB(0x7af277a9),CNST_LIMB(0x8f3a8)), + P(7331,CNST_LIMB(0xc685770b),CNST_LIMB(0x8f087)), + P(7333,CNST_LIMB(0xba5a6b2d),CNST_LIMB(0x8efe7)), + P(7349,CNST_LIMB(0xca48f19d),CNST_LIMB(0x8eaec)), + P(7351,CNST_LIMB(0xa1b18107),CNST_LIMB(0x8ea4d)), + P(7369,CNST_LIMB(0x5822bd79),CNST_LIMB(0x8e4ba)), + P(7393,CNST_LIMB(0x48562721),CNST_LIMB(0x8dd56)), + P(7411,CNST_LIMB(0x10a65c3b),CNST_LIMB(0x8d7d3)), + P(7417,CNST_LIMB(0x3ab5e549),CNST_LIMB(0x8d5fe)), + P(7433,CNST_LIMB(0x14988139),CNST_LIMB(0x8d120)), + P(7451,CNST_LIMB(0x6d99f513),CNST_LIMB(0x8cbac)), + P(7457,CNST_LIMB(0x41a3a6e1),CNST_LIMB(0x8c9dc)), + P(7459,CNST_LIMB(0x9c54fa8b),CNST_LIMB(0x8c942)), + P(7477,CNST_LIMB(0x619d0d1d),CNST_LIMB(0x8c3d7)), + P(7481,CNST_LIMB(0x70afc109),CNST_LIMB(0x8c2a4)), + P(7487,CNST_LIMB(0xca7452bf),CNST_LIMB(0x8c0d8)), + P(7489,CNST_LIMB(0x332372c1),CNST_LIMB(0x8c03f)), + P(7499,CNST_LIMB(0x8c4e8463),CNST_LIMB(0x8bd42)), + P(7507,CNST_LIMB(0x84962edb),CNST_LIMB(0x8bae0)), + P(7517,CNST_LIMB(0x140f1ef5),CNST_LIMB(0x8b7e7)), + P(7523,CNST_LIMB(0xd72a4c4b),CNST_LIMB(0x8b61f)), + P(7529,CNST_LIMB(0xa18242d9),CNST_LIMB(0x8b458)), + P(7537,CNST_LIMB(0x89870391),CNST_LIMB(0x8b1fb)), + P(7541,CNST_LIMB(0x6bc00add),CNST_LIMB(0x8b0cc)), + P(7547,CNST_LIMB(0x9da139b3),CNST_LIMB(0x8af07)), + P(7549,CNST_LIMB(0x4efb03d5),CNST_LIMB(0x8ae71)), + P(7559,CNST_LIMB(0x5e631837),CNST_LIMB(0x8ab80)), + P(7561,CNST_LIMB(0xbcd368b9),CNST_LIMB(0x8aaea)), + P(7573,CNST_LIMB(0x1ed45bd),CNST_LIMB(0x8a766)), + P(7577,CNST_LIMB(0xc31de6a9),CNST_LIMB(0x8a63a)), + P(7583,CNST_LIMB(0xa167be5f),CNST_LIMB(0x8a47a)), + P(7589,CNST_LIMB(0xb3a9822d),CNST_LIMB(0x8a2ba)), + P(7591,CNST_LIMB(0xe43eba17),CNST_LIMB(0x8a225)), + P(7603,CNST_LIMB(0xdda7d97b),CNST_LIMB(0x89ea8)), + P(7607,CNST_LIMB(0x9efa5007),CNST_LIMB(0x89d7f)), + P(7621,CNST_LIMB(0xd661590d),CNST_LIMB(0x89972)), + P(7639,CNST_LIMB(0x8c7325e7),CNST_LIMB(0x89442)), + P(7643,CNST_LIMB(0xa0e89653),CNST_LIMB(0x8931b)), + P(7649,CNST_LIMB(0xe1a4e621),CNST_LIMB(0x89163)), + P(7669,CNST_LIMB(0x16ffe65d),CNST_LIMB(0x88baa)), + P(7673,CNST_LIMB(0xd2a01449),CNST_LIMB(0x88a86)), + P(7681,CNST_LIMB(0x8b83e201),CNST_LIMB(0x8883f)), + P(7687,CNST_LIMB(0xe48eefb7),CNST_LIMB(0x8868b)), + P(7691,CNST_LIMB(0x5834fda3),CNST_LIMB(0x88568)), + P(7699,CNST_LIMB(0x63da5c1b),CNST_LIMB(0x88324)), + P(7703,CNST_LIMB(0x4398f9a7),CNST_LIMB(0x88202)), + P(7717,CNST_LIMB(0xca28cdad),CNST_LIMB(0x87e0f)), + P(7723,CNST_LIMB(0x6b19b083),CNST_LIMB(0x87c5e)), + P(7727,CNST_LIMB(0x9603e8cf),CNST_LIMB(0x87b3e)), + P(7741,CNST_LIMB(0xf5d8e915),CNST_LIMB(0x87751)), + P(7753,CNST_LIMB(0x730a33f9),CNST_LIMB(0x873f6)), + P(7757,CNST_LIMB(0xb6e64a85),CNST_LIMB(0x872d9)), + P(7759,CNST_LIMB(0x999638af),CNST_LIMB(0x8724a)), + P(7789,CNST_LIMB(0xea89b65),CNST_LIMB(0x869f6)), + P(7793,CNST_LIMB(0xfb7fe291),CNST_LIMB(0x868db)), + P(7817,CNST_LIMB(0xe3e6b7b9),CNST_LIMB(0x8623f)), + P(7823,CNST_LIMB(0x6a41406f),CNST_LIMB(0x86099)), + P(7829,CNST_LIMB(0x8aa4bcbd),CNST_LIMB(0x85ef5)), + P(7841,CNST_LIMB(0x19d34561),CNST_LIMB(0x85bad)), + P(7853,CNST_LIMB(0xe120f525),CNST_LIMB(0x85868)), + P(7867,CNST_LIMB(0xccd87673),CNST_LIMB(0x8549b)), + P(7873,CNST_LIMB(0x20a57141),CNST_LIMB(0x852fb)), + P(7877,CNST_LIMB(0xbcebb00d),CNST_LIMB(0x851e6)), + P(7879,CNST_LIMB(0xe17542f7),CNST_LIMB(0x8515b)), + P(7883,CNST_LIMB(0xae95d6e3),CNST_LIMB(0x85047)), + P(7901,CNST_LIMB(0xbbaa975),CNST_LIMB(0x84b6d)), + P(7907,CNST_LIMB(0x51c016cb),CNST_LIMB(0x849d1)), + P(7919,CNST_LIMB(0x46e4d00f),CNST_LIMB(0x8469a)), + P(7927,CNST_LIMB(0x112602c7),CNST_LIMB(0x84476)), + P(7933,CNST_LIMB(0x76c96e55),CNST_LIMB(0x842dd)), + P(7937,CNST_LIMB(0xa4c0e101),CNST_LIMB(0x841cc)), + P(7949,CNST_LIMB(0x7d99c7c5),CNST_LIMB(0x83e9b)), + P(7951,CNST_LIMB(0xaedcefef),CNST_LIMB(0x83e13)), +#define SMALLEST_OMITTED_PRIME 7963 +#endif +#ifdef WANT_ptab + {CNST_LIMB(0x6a61043),{CNST_LIMB(0x3407e2f4),5,CNST_LIMB(0x359960e),CNST_LIMB(0x280d2ab),CNST_LIMB(0x356bfe7),CNST_LIMB(0x26f3e6),CNST_LIMB(0x3219349)},0,8}, + {CNST_LIMB(0x37ed0ed),{CNST_LIMB(0x24f56131),6,CNST_LIMB(0xd66c6b),CNST_LIMB(0x25cccb7),CNST_LIMB(0xd960c3),CNST_LIMB(0x1cfe319),CNST_LIMB(0x101d79a)},8,5}, + {CNST_LIMB(0x23cd611f),{CNST_LIMB(0xc99fec6b),2,CNST_LIMB(0x5625827),CNST_LIMB(0x5adef0d),CNST_LIMB(0x1642bcf1),CNST_LIMB(0x1949f611),CNST_LIMB(0x1e01afdb)},13,5}, + {CNST_LIMB(0x20691a3),{CNST_LIMB(0xf983aa48),6,CNST_LIMB(0xc451c6),CNST_LIMB(0x1f30a00),CNST_LIMB(0x1882017),CNST_LIMB(0x13584ab),CNST_LIMB(0x1dc4b51)},18,4}, + {CNST_LIMB(0x55a60cb),{CNST_LIMB(0x7e961d36),5,CNST_LIMB(0x4683abb),CNST_LIMB(0xb480fe),CNST_LIMB(0x11ac11e),CNST_LIMB(0x4e42709),CNST_LIMB(0x485b829)},22,4}, + {CNST_LIMB(0x9f9f361),{CNST_LIMB(0x9a91f75d),4,CNST_LIMB(0x6973b87),CNST_LIMB(0x902120d),CNST_LIMB(0x1b39c8b),CNST_LIMB(0x2243a6d),CNST_LIMB(0x39cc32a)},26,4}, + {CNST_LIMB(0x1627b25d),{CNST_LIMB(0x71c1e6d9),3,CNST_LIMB(0xc4b5601),CNST_LIMB(0x572f241),CNST_LIMB(0x123561d3),CNST_LIMB(0xacd1a4e),CNST_LIMB(0xe50caef)},30,4}, + {CNST_LIMB(0x2676ed77),{CNST_LIMB(0xa9f355bd),2,CNST_LIMB(0x19366f36),CNST_LIMB(0x262fe82f),CNST_LIMB(0x19f58916),CNST_LIMB(0x1d3362e9),CNST_LIMB(0x1ce7cbf5)},34,4}, + {CNST_LIMB(0x3fcf739d),{CNST_LIMB(0xc2c54b),2,CNST_LIMB(0xc2318c),CNST_LIMB(0x351d4004),CNST_LIMB(0x1fd221a2),CNST_LIMB(0x9cd3902),CNST_LIMB(0x18b387c)},38,4}, + {CNST_LIMB(0x5f281a99),{CNST_LIMB(0x585bc466),1,CNST_LIMB(0x41afcace),CNST_LIMB(0x4b626b7b),CNST_LIMB(0x1a993cb2),CNST_LIMB(0x348290b9),CNST_LIMB(0x148c969a)},42,4}, + {CNST_LIMB(0xb0e211),{CNST_LIMB(0x72813080),8,CNST_LIMB(0x59436e),CNST_LIMB(0x1b120),CNST_LIMB(0x2131fd),CNST_LIMB(0x65359c),CNST_LIMB(0x6c36d8)},46,3}, + {CNST_LIMB(0xccc817),{CNST_LIMB(0x40075c3b),8,CNST_LIMB(0x5e340),CNST_LIMB(0xa0435d),CNST_LIMB(0xb7b3f4),CNST_LIMB(0xbc8eaa),CNST_LIMB(0x7f505d)},49,3}, + {CNST_LIMB(0x102dedd),{CNST_LIMB(0xfa529227),7,CNST_LIMB(0x29bf97),CNST_LIMB(0xd2b1f),CNST_LIMB(0x48ce87),CNST_LIMB(0x27dbb5),CNST_LIMB(0xbc2d73)},52,3}, + {CNST_LIMB(0x1341eff),{CNST_LIMB(0xa96426ad),7,CNST_LIMB(0xd654d4),CNST_LIMB(0x6292bc),CNST_LIMB(0x21e29),CNST_LIMB(0x8ee815),CNST_LIMB(0x4b678e)},55,3}, + {CNST_LIMB(0x163888f),{CNST_LIMB(0x70a9b660),7,CNST_LIMB(0x75d938),CNST_LIMB(0xaf0b1d),CNST_LIMB(0x30460d),CNST_LIMB(0x732299),CNST_LIMB(0xce6686)},58,3}, + {CNST_LIMB(0x1c7ff8d),{CNST_LIMB(0x1f709059),7,CNST_LIMB(0x148403d),CNST_LIMB(0x9c1ebe),CNST_LIMB(0xeee5da),CNST_LIMB(0x3bed2f),CNST_LIMB(0x1bc276d)},61,3}, + {CNST_LIMB(0x21b8e8f),{CNST_LIMB(0xe5d9bd6c),6,CNST_LIMB(0xf99e69),CNST_LIMB(0x13de9a),CNST_LIMB(0x13ae4f9),CNST_LIMB(0x90e465),CNST_LIMB(0x75aa6a)},64,3}, + {CNST_LIMB(0x28c4daf),{CNST_LIMB(0x91dfd2d4),6,CNST_LIMB(0x131a7a4),CNST_LIMB(0xced3f9),CNST_LIMB(0x5fc1d1),CNST_LIMB(0x1a63184),CNST_LIMB(0xd36406)},67,3}, + {CNST_LIMB(0x2ede03d),{CNST_LIMB(0x5d954a31),6,CNST_LIMB(0x128cb45),CNST_LIMB(0x21aecb),CNST_LIMB(0x1981fad),CNST_LIMB(0x6e6aac),CNST_LIMB(0x1a5536c)},70,3}, + {CNST_LIMB(0x35d9a99),{CNST_LIMB(0x30404d26),6,CNST_LIMB(0x361a94),CNST_LIMB(0x2ab8034),CNST_LIMB(0x196715e),CNST_LIMB(0xe04b2b),CNST_LIMB(0x2bf7b04)},73,3}, + {CNST_LIMB(0x3e18615),{CNST_LIMB(0x7da4f6c),6,CNST_LIMB(0x3bcf4ab),CNST_LIMB(0x1432229),CNST_LIMB(0x2dc22df),CNST_LIMB(0x1253154),CNST_LIMB(0x7da79b)},76,3}, + {CNST_LIMB(0x4881841),{CNST_LIMB(0xc3ef7d16),5,CNST_LIMB(0x23ab1c8),CNST_LIMB(0x23d33fb),CNST_LIMB(0x277d7e7),CNST_LIMB(0x749798),CNST_LIMB(0x3faa198)},79,3}, + {CNST_LIMB(0x504eb9d),{CNST_LIMB(0x98081137),5,CNST_LIMB(0x50fb9),CNST_LIMB(0x31734bf),CNST_LIMB(0x2d9f6b8),CNST_LIMB(0x3b1b0a3),CNST_LIMB(0x4b3b8d4)},82,3}, + {CNST_LIMB(0x5a363b5),{CNST_LIMB(0x6b3be150),5,CNST_LIMB(0x247792f),CNST_LIMB(0x20e22e1),CNST_LIMB(0x454996c),CNST_LIMB(0x3f72ee2),CNST_LIMB(0x16067a8)},85,3}, + {CNST_LIMB(0x62c59c3),{CNST_LIMB(0x4bc114ed),5,CNST_LIMB(0x2e59fc5),CNST_LIMB(0x3008b15),CNST_LIMB(0x5162c12),CNST_LIMB(0x38af0a6),CNST_LIMB(0x364f36e)},88,3}, + {CNST_LIMB(0x71cab57),{CNST_LIMB(0x1ff6e506),5,CNST_LIMB(0x714931b),CNST_LIMB(0x3f91ab6),CNST_LIMB(0x22aa414),CNST_LIMB(0x146a171),CNST_LIMB(0x709d520)},91,3}, + {CNST_LIMB(0x7f35ef3),{CNST_LIMB(0x196a38f),5,CNST_LIMB(0x19421a0),CNST_LIMB(0x7b1b930),CNST_LIMB(0x35f1501),CNST_LIMB(0x5d2c30b),CNST_LIMB(0x17120c5)},94,3}, + {CNST_LIMB(0x939999d),{CNST_LIMB(0xbc02c5c7),4,CNST_LIMB(0x6eccc71),CNST_LIMB(0xef9279),CNST_LIMB(0x413d0c3),CNST_LIMB(0xc99b8c),CNST_LIMB(0x4fea894)},97,3}, + {CNST_LIMB(0xaa2acff),{CNST_LIMB(0x81208448),4,CNST_LIMB(0xbfc818),CNST_LIMB(0x2d5bd83),CNST_LIMB(0x3d8740b),CNST_LIMB(0x93899fb),CNST_LIMB(0x25ffe98)},100,3}, + {CNST_LIMB(0xb870189),{CNST_LIMB(0x63540cb5),4,CNST_LIMB(0x265de3a),CNST_LIMB(0x27cce3b),CNST_LIMB(0x76fde07),CNST_LIMB(0x447bb87),CNST_LIMB(0x3206a2e)},103,3}, + {CNST_LIMB(0xcb96fef),{CNST_LIMB(0x41e6f245),4,CNST_LIMB(0x1834154),CNST_LIMB(0x1e2e9d8),CNST_LIMB(0x35efcdf),CNST_LIMB(0x3bf7538),CNST_LIMB(0x7a94328)},106,3}, + {CNST_LIMB(0xdaf1d73),{CNST_LIMB(0x2b53a52a),4,CNST_LIMB(0x9afedea),CNST_LIMB(0x46f3fb),CNST_LIMB(0x8e3c610),CNST_LIMB(0xced433a),CNST_LIMB(0x92db975)},109,3}, + {CNST_LIMB(0xeec4e3d),{CNST_LIMB(0x127970b1),4,CNST_LIMB(0x24ecdf3),CNST_LIMB(0x1810b48),CNST_LIMB(0x49df38a),CNST_LIMB(0xd5b6aa3),CNST_LIMB(0xdad9873)},112,3}, + {CNST_LIMB(0x10313a91),{CNST_LIMB(0xf9eb6341),3,CNST_LIMB(0xd1d9181),CNST_LIMB(0xcd11212),CNST_LIMB(0xf6be0a7),CNST_LIMB(0xbf8f806),CNST_LIMB(0x10178f82)},115,3}, + {CNST_LIMB(0x11793cef),{CNST_LIMB(0xd4d268ca),3,CNST_LIMB(0xb5eaaee),CNST_LIMB(0x35f2db6),CNST_LIMB(0x76a2eec),CNST_LIMB(0x8d5e9c7),CNST_LIMB(0xd05406b)},118,3}, + {CNST_LIMB(0x130b5e75),{CNST_LIMB(0xae270832),3,CNST_LIMB(0x86c340f),CNST_LIMB(0x4fbcabb),CNST_LIMB(0xc5f1cb2),CNST_LIMB(0x52847a),CNST_LIMB(0x1262c44f)},121,3}, + {CNST_LIMB(0x154cb85f),{CNST_LIMB(0x809b4803),3,CNST_LIMB(0x675b8c),CNST_LIMB(0x9e159c),CNST_LIMB(0x91d79ec),CNST_LIMB(0x12b718f9),CNST_LIMB(0x14df0cea)},124,3}, + {CNST_LIMB(0x17790271),{CNST_LIMB(0x5d0053ab),3,CNST_LIMB(0x1545e796),CNST_LIMB(0x49ad4d5),CNST_LIMB(0x6cc0e13),CNST_LIMB(0x14f6fefc),CNST_LIMB(0x75bdf93)},127,3}, + {CNST_LIMB(0x192d52bd),{CNST_LIMB(0x4560327b),3,CNST_LIMB(0x43ac49e),CNST_LIMB(0x1272b91a),CNST_LIMB(0x6ea322),CNST_LIMB(0x6662f7b),CNST_LIMB(0x24444a0)},130,3}, + {CNST_LIMB(0x1af690dd),{CNST_LIMB(0x2fd27496),3,CNST_LIMB(0xd54e83b),CNST_LIMB(0x5f6ffbf),CNST_LIMB(0x894a706),CNST_LIMB(0x4787264),CNST_LIMB(0x632d5f1)},133,3}, + {CNST_LIMB(0x1e3edd3f),{CNST_LIMB(0xed98211),3,CNST_LIMB(0xe091608),CNST_LIMB(0x1158344d),CNST_LIMB(0x849e6ec),CNST_LIMB(0x1e3d6afd),CNST_LIMB(0xd2b549e)},136,3}, + {CNST_LIMB(0x20a97ea1),{CNST_LIMB(0xf59f0efa),2,CNST_LIMB(0x1b5d8999),CNST_LIMB(0x83da735),CNST_LIMB(0x289697c),CNST_LIMB(0x18842148),CNST_LIMB(0x971b719)},139,3}, + {CNST_LIMB(0x2248eb29),{CNST_LIMB(0xdde0fe12),2,CNST_LIMB(0x100191e1),CNST_LIMB(0xe214e26),CNST_LIMB(0xe25d5b),CNST_LIMB(0x15448475),CNST_LIMB(0x18e0bf43)},142,3}, + {CNST_LIMB(0x256db61f),{CNST_LIMB(0xb5bd9743),2,CNST_LIMB(0x1f6dbb46),CNST_LIMB(0x79f112f),CNST_LIMB(0x180b837),CNST_LIMB(0x1fabd504),CNST_LIMB(0xcd4316b)},145,3}, + {CNST_LIMB(0x27be57c3),{CNST_LIMB(0x9c3e44a9),2,CNST_LIMB(0x1189f16e),CNST_LIMB(0x3fe09cb),CNST_LIMB(0x200576bc),CNST_LIMB(0xee0400),CNST_LIMB(0x94268c7)},148,3}, + {CNST_LIMB(0x2a578f87),{CNST_LIMB(0x82f1b049),2,CNST_LIMB(0x1f2a2d6),CNST_LIMB(0xeb97a7d),CNST_LIMB(0x3cbd8b2),CNST_LIMB(0x147ae1f2),CNST_LIMB(0x21252a67)},151,3}, + {CNST_LIMB(0x2e5bc8f9),{CNST_LIMB(0x616b55ac),2,CNST_LIMB(0x18351323),CNST_LIMB(0x1e1d2ed0),CNST_LIMB(0xd05ce1b),CNST_LIMB(0xb659390),CNST_LIMB(0x181b4ed6)},154,3}, + {CNST_LIMB(0x31c4e00f),{CNST_LIMB(0x49335bb4),2,CNST_LIMB(0x7279fb5),CNST_LIMB(0xc36c1b2),CNST_LIMB(0x22bcdb49),CNST_LIMB(0x1b0c3f08),CNST_LIMB(0x3ba3ff9)},157,3}, + {CNST_LIMB(0x3555f625),{CNST_LIMB(0x332f94f8),2,CNST_LIMB(0x2aa8276c),CNST_LIMB(0x152eaa7b),CNST_LIMB(0x114a5023),CNST_LIMB(0x247d32c3),CNST_LIMB(0x29d13845)},160,3}, + {CNST_LIMB(0x38ba8399),{CNST_LIMB(0x20d05c1a),2,CNST_LIMB(0x1d15f19c),CNST_LIMB(0x345992a6),CNST_LIMB(0xd3afbd2),CNST_LIMB(0x2977445b),CNST_LIMB(0x17db69bc)},163,3}, + {CNST_LIMB(0x3cbd7a99),{CNST_LIMB(0xdbd3c38),2,CNST_LIMB(0xd0a159c),CNST_LIMB(0x17714a20),CNST_LIMB(0x987d1b4),CNST_LIMB(0x1ff46fe1),CNST_LIMB(0x10074b7f)},166,3}, + {CNST_LIMB(0x3fef5c69),{CNST_LIMB(0x429fae),2,CNST_LIMB(0x428e5c),CNST_LIMB(0x375fe688),CNST_LIMB(0x2e5e8e22),CNST_LIMB(0x2d4e3a4d),CNST_LIMB(0x32fd826f)},169,3}, + {CNST_LIMB(0x431b892f),{CNST_LIMB(0xe84a6cd9),1,CNST_LIMB(0x36ad6473),CNST_LIMB(0x3d4a3d23),CNST_LIMB(0x34accf4f),CNST_LIMB(0x24439410),CNST_LIMB(0x18acba75)},172,3}, + {CNST_LIMB(0x46a73431),{CNST_LIMB(0xcfc97180),1,CNST_LIMB(0x2c0a636d),CNST_LIMB(0x431f58cf),CNST_LIMB(0x24e5def5),CNST_LIMB(0x1ebd41f6),CNST_LIMB(0x207ddce5)},175,3}, + {CNST_LIMB(0x4b9041f9),{CNST_LIMB(0xb1a602f3),1,CNST_LIMB(0x1d4f3a15),CNST_LIMB(0x1e9e9b51),CNST_LIMB(0xfd2a2a2),CNST_LIMB(0x1a320dd0),CNST_LIMB(0xeb319b2)},178,3}, + {CNST_LIMB(0x4ed40e63),{CNST_LIMB(0x9fb0235c),1,CNST_LIMB(0x1383d4d7),CNST_LIMB(0x4ab28875),CNST_LIMB(0x3135ea2),CNST_LIMB(0x45c1a29c),CNST_LIMB(0x4d986e12)},181,3}, + {CNST_LIMB(0x52eacd03),{CNST_LIMB(0x8b308095),1,CNST_LIMB(0x73f98f7),CNST_LIMB(0x379f8d7f),CNST_LIMB(0x350cc9ef),CNST_LIMB(0xca8a646),CNST_LIMB(0x454fabcd)},184,3}, + {CNST_LIMB(0x594e3b97),{CNST_LIMB(0x6eeb7e19),1,CNST_LIMB(0x4d6388d2),CNST_LIMB(0x7877ceb),CNST_LIMB(0xf0387ea),CNST_LIMB(0x88049bf),CNST_LIMB(0x2de28acd)},187,3}, + {CNST_LIMB(0x5fddcf2d),{CNST_LIMB(0x55cf11d7),1,CNST_LIMB(0x404461a6),CNST_LIMB(0x3746393d),CNST_LIMB(0x37ed7c13),CNST_LIMB(0x917953f),CNST_LIMB(0x3ec81bd3)},190,3}, + {CNST_LIMB(0x159b9b),{CNST_LIMB(0x7b1f2ba6),11,CNST_LIMB(0x150c38),CNST_LIMB(0xab37c),CNST_LIMB(0x322dd),CNST_LIMB(0x69b79),CNST_LIMB(0xd3898)},193,2}, + {CNST_LIMB(0x163aad),{CNST_LIMB(0x708634f7),11,CNST_LIMB(0x44fcc),CNST_LIMB(0x731ab),CNST_LIMB(0xb426c),CNST_LIMB(0x93985),CNST_LIMB(0x136433)},195,2}, + {CNST_LIMB(0x6d07df9b),{CNST_LIMB(0x2c89ff56),1,CNST_LIMB(0x25f040ca),CNST_LIMB(0x6511a41),CNST_LIMB(0x1f1c52b0),CNST_LIMB(0x31d9ad5c),CNST_LIMB(0x396be62c)},197,3}, + {CNST_LIMB(0x715cdbdb),{CNST_LIMB(0x210def92),1,CNST_LIMB(0x1d46484a),CNST_LIMB(0x13f77459),CNST_LIMB(0x4c2c7015),CNST_LIMB(0xbf5959),CNST_LIMB(0x122860d0)},200,3}, + {CNST_LIMB(0x7a90b2c1),{CNST_LIMB(0xb59fd46),1,CNST_LIMB(0xade9a7e),CNST_LIMB(0x175ac474),CNST_LIMB(0x5d61f1e4),CNST_LIMB(0x3f32b10e),CNST_LIMB(0xe1a8f21)},203,3}, + {CNST_LIMB(0x193c1b),{CNST_LIMB(0x44a19872),11,CNST_LIMB(0x14219),CNST_LIMB(0x6b0dc),CNST_LIMB(0x1913ba),CNST_LIMB(0xf32f3),CNST_LIMB(0x529bb)},206,2}, + {CNST_LIMB(0x198cbb),{CNST_LIMB(0x40a12f87),11,CNST_LIMB(0xf259),CNST_LIMB(0x131c53),CNST_LIMB(0x82974),CNST_LIMB(0x4002b),CNST_LIMB(0xea52d)},208,2}, + {CNST_LIMB(0x19dde3),{CNST_LIMB(0x3cb337e9),11,CNST_LIMB(0xf88f1),CNST_LIMB(0x16c9e8),CNST_LIMB(0x400af),CNST_LIMB(0x7df4d),CNST_LIMB(0x19a73b)},210,2}, + {CNST_LIMB(0x1a4e1d),{CNST_LIMB(0x376c11ab),11,CNST_LIMB(0x9ebd1),CNST_LIMB(0x122d59),CNST_LIMB(0x10dc87),CNST_LIMB(0x183d1a),CNST_LIMB(0x14c9bb)},212,2}, + {CNST_LIMB(0x1abf87),{CNST_LIMB(0x32439dfa),11,CNST_LIMB(0x30602),CNST_LIMB(0x9b219),CNST_LIMB(0x39642),CNST_LIMB(0xd8777),CNST_LIMB(0x162303)},214,2}, + {CNST_LIMB(0x1c6387),{CNST_LIMB(0x2090918d),11,CNST_LIMB(0xeb2e4),CNST_LIMB(0x10a775),CNST_LIMB(0x1a36de),CNST_LIMB(0xec08b),CNST_LIMB(0x53db3)},216,2}, + {CNST_LIMB(0x1ceeb1),{CNST_LIMB(0x1b249459),11,CNST_LIMB(0x423f7),CNST_LIMB(0x16f7a1),CNST_LIMB(0x12d4fa),CNST_LIMB(0x1b3f0a),CNST_LIMB(0x7ac5)},218,2}, + {CNST_LIMB(0x1e13f7),{CNST_LIMB(0x105bd03b),11,CNST_LIMB(0x1a2492),CNST_LIMB(0xc7005),CNST_LIMB(0xce5e5),CNST_LIMB(0xe29b9),CNST_LIMB(0x1155c7)},220,2}, + {CNST_LIMB(0x1efc1d),{CNST_LIMB(0x8633680),11,CNST_LIMB(0x31c69),CNST_LIMB(0x9ec33),CNST_LIMB(0xabcac),CNST_LIMB(0x17d357),CNST_LIMB(0x18635b)},222,2}, + {CNST_LIMB(0x1f3f0d),{CNST_LIMB(0x62cd3db),11,CNST_LIMB(0xc8683),CNST_LIMB(0x1f3e50),CNST_LIMB(0x76925),CNST_LIMB(0x8b89),CNST_LIMB(0x574f8)},224,2}, + {CNST_LIMB(0x1fc5b9),{CNST_LIMB(0x1d58f25),11,CNST_LIMB(0x1567e2),CNST_LIMB(0xf443f),CNST_LIMB(0x3652a),CNST_LIMB(0x12ead9),CNST_LIMB(0x1d5afd)},226,2}, + {CNST_LIMB(0x202b8f),{CNST_LIMB(0xfd4abfa8),10,CNST_LIMB(0x56725),CNST_LIMB(0x1a7074),CNST_LIMB(0x9dd13),CNST_LIMB(0x165993),CNST_LIMB(0x383dc)},228,2}, + {CNST_LIMB(0x20bf8d),{CNST_LIMB(0xf44d36ad),10,CNST_LIMB(0x6c2e3),CNST_LIMB(0x1c5d9d),CNST_LIMB(0x183984),CNST_LIMB(0x20332c),CNST_LIMB(0xbfec9)},230,2}, + {CNST_LIMB(0x218363),{CNST_LIMB(0xe8e1ae33),10,CNST_LIMB(0x11a2f7),CNST_LIMB(0x109739),CNST_LIMB(0x19b93c),CNST_LIMB(0x26caf),CNST_LIMB(0x15e0d0)},232,2}, + {CNST_LIMB(0x21c8ff),{CNST_LIMB(0xe4f26938),10,CNST_LIMB(0x1a9c93),CNST_LIMB(0xc877c),CNST_LIMB(0x9b8a6),CNST_LIMB(0x8f28f),CNST_LIMB(0x14db52)},234,2}, + {CNST_LIMB(0x222637),{CNST_LIMB(0xdfc6a16c),10,CNST_LIMB(0x389b7),CNST_LIMB(0x139a0e),CNST_LIMB(0x2186ab),CNST_LIMB(0xfc424),CNST_LIMB(0xed95b)},236,2}, + {CNST_LIMB(0x231d45),{CNST_LIMB(0xd2970f8e),10,CNST_LIMB(0xca70e),CNST_LIMB(0xe8638),CNST_LIMB(0x22ac81),CNST_LIMB(0x546f2),CNST_LIMB(0xd0099)},238,2}, + {CNST_LIMB(0x240bdd),{CNST_LIMB(0xc686a975),10,CNST_LIMB(0x3c08e),CNST_LIMB(0x172a38),CNST_LIMB(0x44c51),CNST_LIMB(0x235d86),CNST_LIMB(0x8588c)},240,2}, + {CNST_LIMB(0x24b4dd),{CNST_LIMB(0xbe59fbc2),10,CNST_LIMB(0xee70b),CNST_LIMB(0x16f1f6),CNST_LIMB(0x176ca4),CNST_LIMB(0x7286b),CNST_LIMB(0xe5af)},242,2}, + {CNST_LIMB(0x2546c9),{CNST_LIMB(0xb786b460),10,CNST_LIMB(0x3e7b2),CNST_LIMB(0x7a1ba),CNST_LIMB(0x1cd511),CNST_LIMB(0x7f8b6),CNST_LIMB(0x149e84)},244,2}, + {CNST_LIMB(0x25d9e1),{CNST_LIMB(0xb0daa78f),10,CNST_LIMB(0xfc39d),CNST_LIMB(0x18232c),CNST_LIMB(0x21f9e1),CNST_LIMB(0x1df466),CNST_LIMB(0x125598)},246,2}, + {CNST_LIMB(0x269333),{CNST_LIMB(0xa8bb27dd),10,CNST_LIMB(0x23a7ba),CNST_LIMB(0x21b0e8),CNST_LIMB(0x35afa),CNST_LIMB(0x1354d5),CNST_LIMB(0x20b568)},248,2}, + {CNST_LIMB(0x274207),{CNST_LIMB(0xa157b119),10,CNST_LIMB(0xe885d),CNST_LIMB(0x10d941),CNST_LIMB(0xa5b8),CNST_LIMB(0x1b9670),CNST_LIMB(0x121bdf)},250,2}, + {CNST_LIMB(0x2799f5),{CNST_LIMB(0x9db9099e),10,CNST_LIMB(0x234b12),CNST_LIMB(0x24712),CNST_LIMB(0x1a8b45),CNST_LIMB(0x209e1c),CNST_LIMB(0x64e0)},252,2}, + {CNST_LIMB(0x280b8f),{CNST_LIMB(0x99235f9a),10,CNST_LIMB(0x162224),CNST_LIMB(0x1f2e9b),CNST_LIMB(0x7db4d),CNST_LIMB(0x17cade),CNST_LIMB(0x263b83)},254,2}, + {CNST_LIMB(0x28a3e7),{CNST_LIMB(0x9325ae46),10,CNST_LIMB(0x17ed6c),CNST_LIMB(0xd6dea),CNST_LIMB(0x25bb74),CNST_LIMB(0xda2de),CNST_LIMB(0x789e2)},256,2}, + {CNST_LIMB(0x2a0c07),{CNST_LIMB(0x85a8cbc8),10,CNST_LIMB(0x1acd66),CNST_LIMB(0x258a3),CNST_LIMB(0xef7e0),CNST_LIMB(0x15d2d),CNST_LIMB(0x272ee9)},258,2}, + {CNST_LIMB(0x2a740f),{CNST_LIMB(0x81edf12f),10,CNST_LIMB(0x1e7997),CNST_LIMB(0x18fa07),CNST_LIMB(0x26e84d),CNST_LIMB(0x1d7510),CNST_LIMB(0x24b8b1)},260,2}, + {CNST_LIMB(0x2bd6bd),{CNST_LIMB(0x75bb9098),10,CNST_LIMB(0x28cd02),CNST_LIMB(0x147688),CNST_LIMB(0x275790),CNST_LIMB(0x1c11b1),CNST_LIMB(0x29cecd)},262,2}, + {CNST_LIMB(0x2c4e27),{CNST_LIMB(0x71cc427d),10,CNST_LIMB(0x87caf),CNST_LIMB(0x35c03),CNST_LIMB(0x25d1b),CNST_LIMB(0x2012f6),CNST_LIMB(0x20400a)},264,2}, + {CNST_LIMB(0x2d3f23),{CNST_LIMB(0x6a1ab597),10,CNST_LIMB(0x12e208),CNST_LIMB(0xaf62b),CNST_LIMB(0x1ce5a7),CNST_LIMB(0x248d3d),CNST_LIMB(0x25f3e6)},266,2}, + {CNST_LIMB(0x2e09c1),{CNST_LIMB(0x63e10f84),10,CNST_LIMB(0x17c831),CNST_LIMB(0x10ada4),CNST_LIMB(0x226591),CNST_LIMB(0x200f4c),CNST_LIMB(0x30e23)},268,2}, + {CNST_LIMB(0x2ebadb),{CNST_LIMB(0x5e9c50a5),10,CNST_LIMB(0x14aca2),CNST_LIMB(0x168e8),CNST_LIMB(0xcb2ac),CNST_LIMB(0x11140f),CNST_LIMB(0x218d55)},270,2}, + {CNST_LIMB(0x2fb1ef),{CNST_LIMB(0x57840587),10,CNST_LIMB(0x2ff3e),CNST_LIMB(0x83a9a),CNST_LIMB(0x1f539b),CNST_LIMB(0x1f9f58),CNST_LIMB(0xf511)},272,2}, + {CNST_LIMB(0x309e2d),{CNST_LIMB(0x50fed29b),10,CNST_LIMB(0x2fb939),CNST_LIMB(0x97712),CNST_LIMB(0x90aaf),CNST_LIMB(0x1d6765),CNST_LIMB(0x228501)},274,2}, + {CNST_LIMB(0x3129e5),{CNST_LIMB(0x4d411c8e),10,CNST_LIMB(0xda97),CNST_LIMB(0x2b9d7a),CNST_LIMB(0x1cacbf),CNST_LIMB(0x950f3),CNST_LIMB(0x2b7d9e)},276,2}, + {CNST_LIMB(0x32604d),{CNST_LIMB(0x453bad0b),10,CNST_LIMB(0x2ef8fc),CNST_LIMB(0x1752db),CNST_LIMB(0x2cc297),CNST_LIMB(0x2f295c),CNST_LIMB(0x26403c)},278,2}, + {CNST_LIMB(0x339a61),{CNST_LIMB(0x3d802b25),10,CNST_LIMB(0x22ca),CNST_LIMB(0x1768ad),CNST_LIMB(0x347ba),CNST_LIMB(0x5fa4e),CNST_LIMB(0x2320e5)},280,2}, + {CNST_LIMB(0x350437),{CNST_LIMB(0x35093c30),10,CNST_LIMB(0x7a674),CNST_LIMB(0x9857a),CNST_LIMB(0x1c2289),CNST_LIMB(0x1edad),CNST_LIMB(0x20a280)},282,2}, + {CNST_LIMB(0x3578ff),{CNST_LIMB(0x32665151),10,CNST_LIMB(0x2003c9),CNST_LIMB(0x679be),CNST_LIMB(0x9c5b1),CNST_LIMB(0x2b31c4),CNST_LIMB(0x233d52)},284,2}, + {CNST_LIMB(0x35d0e3),{CNST_LIMB(0x3071ea33),10,CNST_LIMB(0x29f8dd),CNST_LIMB(0x4d86),CNST_LIMB(0xf400c),CNST_LIMB(0x244fb7),CNST_LIMB(0x2ff843)},286,2}, + {CNST_LIMB(0x36cb4d),{CNST_LIMB(0x2b029311),10,CNST_LIMB(0x23444),CNST_LIMB(0x29b886),CNST_LIMB(0x8c091),CNST_LIMB(0x95397),CNST_LIMB(0xb43cd)},288,2}, + {CNST_LIMB(0x37aa5b),{CNST_LIMB(0x26546c82),10,CNST_LIMB(0x11c39d),CNST_LIMB(0xdd8e4),CNST_LIMB(0x1565b9),CNST_LIMB(0x344bc5),CNST_LIMB(0x2511e4)},290,2}, + {CNST_LIMB(0x38f48f),{CNST_LIMB(0x1faa05c2),10,CNST_LIMB(0x25659e),CNST_LIMB(0xe5041),CNST_LIMB(0x17a9d2),CNST_LIMB(0x37a90e),CNST_LIMB(0x1d13e7)},292,2}, + {CNST_LIMB(0x3a0583),{CNST_LIMB(0x1a60c07e),10,CNST_LIMB(0x1db145),CNST_LIMB(0x83946),CNST_LIMB(0x6ab41),CNST_LIMB(0x1b99f8),CNST_LIMB(0x2297d8)},294,2}, + {CNST_LIMB(0x3b9437),{CNST_LIMB(0x12ff1352),10,CNST_LIMB(0x3ab7e3),CNST_LIMB(0x2f34ae),CNST_LIMB(0x30ac7d),CNST_LIMB(0x2a6fc),CNST_LIMB(0x36cc9)},296,2}, + {CNST_LIMB(0x3c6d1b),{CNST_LIMB(0xf24048d),10,CNST_LIMB(0x2201ac),CNST_LIMB(0xfe4dc),CNST_LIMB(0x120481),CNST_LIMB(0x3030bc),CNST_LIMB(0x27aea3)},298,2}, + {CNST_LIMB(0x3ce9c3),{CNST_LIMB(0xcf923ad),10,CNST_LIMB(0x366227),CNST_LIMB(0x9cfbd),CNST_LIMB(0x23ff57),CNST_LIMB(0x382453),CNST_LIMB(0x131d33)},300,2}, + {CNST_LIMB(0x3d7681),{CNST_LIMB(0xa9139a4),10,CNST_LIMB(0x108ad6),CNST_LIMB(0x4599d),CNST_LIMB(0x2bb386),CNST_LIMB(0x3af379),CNST_LIMB(0x2ba962)},302,2}, + {CNST_LIMB(0x3e628b),{CNST_LIMB(0x6a0a4c4),10,CNST_LIMB(0x1fd1e2),CNST_LIMB(0x2e9e10),CNST_LIMB(0x1eee9c),CNST_LIMB(0x271d68),CNST_LIMB(0x2d46e3)},304,2}, + {CNST_LIMB(0x3f20ab),{CNST_LIMB(0x389ac67),10,CNST_LIMB(0x98aa6),CNST_LIMB(0x196693),CNST_LIMB(0x1c1e5f),CNST_LIMB(0x1ea4ee),CNST_LIMB(0x13746a)},306,2}, + {CNST_LIMB(0x40a04b),{CNST_LIMB(0xfb0a149c),9,CNST_LIMB(0x516ee),CNST_LIMB(0x1a3590),CNST_LIMB(0x2cfdb3),CNST_LIMB(0x2c80ba),CNST_LIMB(0x72d39)},308,2}, + {CNST_LIMB(0x41b2b5),{CNST_LIMB(0xf2c43abe),9,CNST_LIMB(0x230517),CNST_LIMB(0x2d7e13),CNST_LIMB(0x40f993),CNST_LIMB(0x3fda62),CNST_LIMB(0x8edd4)},310,2}, + {CNST_LIMB(0x425555),{CNST_LIMB(0xedfd6fd4),9,CNST_LIMB(0x410149),CNST_LIMB(0xce2d5),CNST_LIMB(0x563ff),CNST_LIMB(0x2cf02b),CNST_LIMB(0x33aa87)},312,2}, + {CNST_LIMB(0x42e82b),{CNST_LIMB(0xe9c14fb3),9,CNST_LIMB(0x22238f),CNST_LIMB(0x1ee371),CNST_LIMB(0x651b6),CNST_LIMB(0x30195b),CNST_LIMB(0x171164)},314,2}, + {CNST_LIMB(0x440fff),{CNST_LIMB(0xe170a148),9,CNST_LIMB(0x3be3c2),CNST_LIMB(0x1651c4),CNST_LIMB(0x3b633),CNST_LIMB(0x3dffbf),CNST_LIMB(0x759a4)},316,2}, + {CNST_LIMB(0x453a43),{CNST_LIMB(0xd9565b19),9,CNST_LIMB(0x2eb46a),CNST_LIMB(0x2bcf88),CNST_LIMB(0x22a939),CNST_LIMB(0x1b5543),CNST_LIMB(0x44508a)},318,2}, + {CNST_LIMB(0x45d055),{CNST_LIMB(0xd55ce12d),9,CNST_LIMB(0x32a88e),CNST_LIMB(0x12ee30),CNST_LIMB(0x3dd875),CNST_LIMB(0x205906),CNST_LIMB(0x10eda0)},320,2}, + {CNST_LIMB(0x4666f7),{CNST_LIMB(0xd170a116),9,CNST_LIMB(0x3df2b2),CNST_LIMB(0x3f019d),CNST_LIMB(0x21137e),CNST_LIMB(0x2897ba),CNST_LIMB(0x32e1ec)},322,2}, + {CNST_LIMB(0x47d9d3),{CNST_LIMB(0xc80e4100),9,CNST_LIMB(0x80050),CNST_LIMB(0x43c138),CNST_LIMB(0x2664c2),CNST_LIMB(0x2779d4),CNST_LIMB(0xffdf3)},324,2}, + {CNST_LIMB(0x4a3045),{CNST_LIMB(0xb9af75ce),9,CNST_LIMB(0x1b8201),CNST_LIMB(0x26d180),CNST_LIMB(0x3607d),CNST_LIMB(0x27c590),CNST_LIMB(0x287097)},326,2}, + {CNST_LIMB(0x4aff81),{CNST_LIMB(0xb4eaff27),9,CNST_LIMB(0x3eb117),CNST_LIMB(0xf37f2),CNST_LIMB(0x29f514),CNST_LIMB(0x3911b5),CNST_LIMB(0x3b3dd7)},328,2}, + {CNST_LIMB(0x4c6d03),{CNST_LIMB(0xacc16dde),9,CNST_LIMB(0x2710f5),CNST_LIMB(0x324e0d),CNST_LIMB(0x1cce01),CNST_LIMB(0x46d9f6),CNST_LIMB(0x263ef1)},330,2}, + {CNST_LIMB(0x4d0aa1),{CNST_LIMB(0xa9543fe3),9,CNST_LIMB(0x32b56e),CNST_LIMB(0x386985),CNST_LIMB(0x2f585f),CNST_LIMB(0x7b632),CNST_LIMB(0x1049d2)},332,2}, + {CNST_LIMB(0x4e7d0f),{CNST_LIMB(0xa17ce448),9,CNST_LIMB(0x4c9522),CNST_LIMB(0xfeab2),CNST_LIMB(0x2b8e73),CNST_LIMB(0x4ae623),CNST_LIMB(0x274dcc)},334,2}, + {CNST_LIMB(0x4f1cc9),{CNST_LIMB(0x9e31fdcf),9,CNST_LIMB(0x1ee5e4),CNST_LIMB(0x3997e3),CNST_LIMB(0x208214),CNST_LIMB(0x21acc7),CNST_LIMB(0x12be82)},336,2}, + {CNST_LIMB(0x5004bb),{CNST_LIMB(0x998162b6),9,CNST_LIMB(0xddbf),CNST_LIMB(0x27fbff),CNST_LIMB(0x440282),CNST_LIMB(0x3c9211),CNST_LIMB(0xfa371)},338,2}, + {CNST_LIMB(0x50eddd),{CNST_LIMB(0x94e5b8eb),9,CNST_LIMB(0x40509b),CNST_LIMB(0x1b6be5),CNST_LIMB(0xe1be7),CNST_LIMB(0x18b0cf),CNST_LIMB(0x45bc9f)},340,2}, + {CNST_LIMB(0x5244cb),{CNST_LIMB(0x8e4df1cd),9,CNST_LIMB(0x3218cc),CNST_LIMB(0x6ef6),CNST_LIMB(0x31640d),CNST_LIMB(0x364a3d),CNST_LIMB(0x4333ff)},342,2}, + {CNST_LIMB(0x538d0f),{CNST_LIMB(0x8831094a),9,CNST_LIMB(0x200210),CNST_LIMB(0x41e65c),CNST_LIMB(0x2d6247),CNST_LIMB(0x1d04ba),CNST_LIMB(0x1b1cea)},344,2}, + {CNST_LIMB(0x5431e5),{CNST_LIMB(0x85313523),9,CNST_LIMB(0x205e0e),CNST_LIMB(0x222daf),CNST_LIMB(0x2bbad1),CNST_LIMB(0x377677),CNST_LIMB(0x111ca2)},346,2}, + {CNST_LIMB(0x5545df),{CNST_LIMB(0x8045a11d),9,CNST_LIMB(0x2e6300),CNST_LIMB(0x1dede1),CNST_LIMB(0x291dc7),CNST_LIMB(0x1bb88e),CNST_LIMB(0xd0481)},348,2}, + {CNST_LIMB(0x565bf5),{CNST_LIMB(0x7b703b72),9,CNST_LIMB(0x4bb892),CNST_LIMB(0x2f6e92),CNST_LIMB(0xbf5d1),CNST_LIMB(0x4bd43e),CNST_LIMB(0x4dcd8b)},350,2}, + {CNST_LIMB(0x56de3b),{CNST_LIMB(0x7937332f),9,CNST_LIMB(0x25763a),CNST_LIMB(0x4bc847),CNST_LIMB(0x1b22e2),CNST_LIMB(0x32ea7),CNST_LIMB(0x2d562b)},352,2}, + {CNST_LIMB(0x579907),{CNST_LIMB(0x7612cf88),9,CNST_LIMB(0xcdf8c),CNST_LIMB(0x53586e),CNST_LIMB(0x29c831),CNST_LIMB(0x165189),CNST_LIMB(0x53c262)},354,2}, + {CNST_LIMB(0x58eb3b),{CNST_LIMB(0x70840575),9,CNST_LIMB(0x2cb25),CNST_LIMB(0x3b48ec),CNST_LIMB(0x4db0a2),CNST_LIMB(0x337553),CNST_LIMB(0x36704b)},356,2}, + {CNST_LIMB(0x5a19d3),{CNST_LIMB(0x6bae6703),9,CNST_LIMB(0x20a9cb),CNST_LIMB(0x2893af),CNST_LIMB(0x48b077),CNST_LIMB(0x3e877f),CNST_LIMB(0x1df069)},358,2}, + {CNST_LIMB(0x5b2487),{CNST_LIMB(0x67863155),9,CNST_LIMB(0x468d7),CNST_LIMB(0xd83c6),CNST_LIMB(0x420e9c),CNST_LIMB(0x512408),CNST_LIMB(0x11f4fe)},360,2}, + {CNST_LIMB(0x5c90b1),{CNST_LIMB(0x61ffc697),9,CNST_LIMB(0x5c672d),CNST_LIMB(0x395f9e),CNST_LIMB(0x35ef84),CNST_LIMB(0x1ca5d1),CNST_LIMB(0x4789f6)},362,2}, + {CNST_LIMB(0x5d7835),{CNST_LIMB(0x5e92f3b6),9,CNST_LIMB(0xdd6df),CNST_LIMB(0x2043c),CNST_LIMB(0x20fd49),CNST_LIMB(0x1037d1),CNST_LIMB(0x2de08d)},364,2}, + {CNST_LIMB(0x6048af),{CNST_LIMB(0x5453aa32),9,CNST_LIMB(0x3eef28),CNST_LIMB(0x2663a2),CNST_LIMB(0x31f4d6),CNST_LIMB(0x3e8a4f),CNST_LIMB(0x39325f)},366,2}, + {CNST_LIMB(0x620e61),{CNST_LIMB(0x4e2d0265),9,CNST_LIMB(0x227ae4),CNST_LIMB(0x262bd7),CNST_LIMB(0x31c95c),CNST_LIMB(0x5af738),CNST_LIMB(0x3b9063)},368,2}, + {CNST_LIMB(0x62e8bb),{CNST_LIMB(0x4b4b488d),9,CNST_LIMB(0x3a2c6e),CNST_LIMB(0x54e989),CNST_LIMB(0x410871),CNST_LIMB(0x5fc114),CNST_LIMB(0x22afa0)},370,2}, + {CNST_LIMB(0x63881b),{CNST_LIMB(0x4938cc8c),9,CNST_LIMB(0x2c2a9a),CNST_LIMB(0x4b83d7),CNST_LIMB(0x87dbd),CNST_LIMB(0x284a16),CNST_LIMB(0x5c9fd3)},372,2}, + {CNST_LIMB(0x65f64d),{CNST_LIMB(0x415fd083),9,CNST_LIMB(0x4c52e6),CNST_LIMB(0x4985c5),CNST_LIMB(0x21215),CNST_LIMB(0x98dcf),CNST_LIMB(0x591fb7)},374,2}, + {CNST_LIMB(0x673a51),{CNST_LIMB(0x3d6f1262),9,CNST_LIMB(0x599366),CNST_LIMB(0x165af4),CNST_LIMB(0x3f4a93),CNST_LIMB(0x4c9330),CNST_LIMB(0x23018d)},376,2}, + {CNST_LIMB(0x68a995),{CNST_LIMB(0x39152e42),9,CNST_LIMB(0x1151a6),CNST_LIMB(0x403671),CNST_LIMB(0x3fbee7),CNST_LIMB(0x501cd3),CNST_LIMB(0x515b8c)},378,2}, + {CNST_LIMB(0x6a58cf),{CNST_LIMB(0x341fa8fb),9,CNST_LIMB(0x1a4de8),CNST_LIMB(0x165858),CNST_LIMB(0x19bc95),CNST_LIMB(0x1aeece),CNST_LIMB(0x2308d4)},380,2}, + {CNST_LIMB(0x6bcd83),{CNST_LIMB(0x2ff664d7),9,CNST_LIMB(0x63b663),CNST_LIMB(0x5624b6),CNST_LIMB(0x44c1c3),CNST_LIMB(0x1d188),CNST_LIMB(0xea7d0)},382,2}, + {CNST_LIMB(0x6c88a9),{CNST_LIMB(0x2dea42ee),9,CNST_LIMB(0x5a19ed),CNST_LIMB(0x57ef0c),CNST_LIMB(0x237c03),CNST_LIMB(0x47b287),CNST_LIMB(0x4948de)},384,2}, + {CNST_LIMB(0x6d9837),{CNST_LIMB(0x2afe2c44),9,CNST_LIMB(0x6c07bd),CNST_LIMB(0x2c97d3),CNST_LIMB(0x4dd7de),CNST_LIMB(0x223d20),CNST_LIMB(0x579032)},386,2}, + {CNST_LIMB(0x6e3fff),{CNST_LIMB(0x2937286d),9,CNST_LIMB(0x2f8252),CNST_LIMB(0x47db44),CNST_LIMB(0x1f7ab1),CNST_LIMB(0x277f5b),CNST_LIMB(0x508658)},388,2}, + {CNST_LIMB(0x6ee837),{CNST_LIMB(0x27745af1),9,CNST_LIMB(0x64d13e),CNST_LIMB(0x14e20d),CNST_LIMB(0x5f8e8),CNST_LIMB(0x389880),CNST_LIMB(0x5ab271)},390,2}, + {CNST_LIMB(0x6ffab5),{CNST_LIMB(0x24a01d63),9,CNST_LIMB(0x1c1863),CNST_LIMB(0xa1f4d),CNST_LIMB(0x1689e9),CNST_LIMB(0x6f88bd),CNST_LIMB(0x5d4f45)},392,2}, + {CNST_LIMB(0x708f07),{CNST_LIMB(0x231e848d),9,CNST_LIMB(0x1ad616),CNST_LIMB(0x4f0723),CNST_LIMB(0x19cd6d),CNST_LIMB(0x1b34c),CNST_LIMB(0x436210)},394,2}, + {CNST_LIMB(0x71b8e3),{CNST_LIMB(0x202405e8),9,CNST_LIMB(0x200140),CNST_LIMB(0x209104),CNST_LIMB(0x59562),CNST_LIMB(0x3f6f51),CNST_LIMB(0x3f820c)},396,2}, + {CNST_LIMB(0x72f9a1),{CNST_LIMB(0x1d0034e8),9,CNST_LIMB(0x2f86),CNST_LIMB(0x49f331),CNST_LIMB(0x6e0216),CNST_LIMB(0x30d10c),CNST_LIMB(0x382afb)},398,2}, + {CNST_LIMB(0x743c0f),{CNST_LIMB(0x19e9a07f),9,CNST_LIMB(0x5feb03),CNST_LIMB(0x4a2c46),CNST_LIMB(0x3f6f04),CNST_LIMB(0x1173f7),CNST_LIMB(0x6c97c7)},400,2}, + {CNST_LIMB(0x762e1d),{CNST_LIMB(0x15458b0d),9,CNST_LIMB(0x40353e),CNST_LIMB(0x6c69fd),CNST_LIMB(0x5933fe),CNST_LIMB(0x4df08e),CNST_LIMB(0x680489)},402,2}, + {CNST_LIMB(0x771ddb),{CNST_LIMB(0x13177cc9),9,CNST_LIMB(0x15db7e),CNST_LIMB(0x55d59f),CNST_LIMB(0x5e0b92),CNST_LIMB(0x4e3f0b),CNST_LIMB(0x2b65f6)},404,2}, + {CNST_LIMB(0x77ccc3),{CNST_LIMB(0x1185db65),9,CNST_LIMB(0x57b57),CNST_LIMB(0x5cc66f),CNST_LIMB(0x35f8aa),CNST_LIMB(0x6cfd1e),CNST_LIMB(0x551b9c)},406,2}, + {CNST_LIMB(0x79dc33),{CNST_LIMB(0xce5fd6c),9,CNST_LIMB(0x611905),CNST_LIMB(0x6b8d18),CNST_LIMB(0x1649b9),CNST_LIMB(0x4c7c79),CNST_LIMB(0x3a734b)},408,2}, + {CNST_LIMB(0x7b1237),{CNST_LIMB(0xa40a2dd),9,CNST_LIMB(0x3e25b4),CNST_LIMB(0x3dd2a5),CNST_LIMB(0x2735e0),CNST_LIMB(0x1757f4),CNST_LIMB(0x629d65)},410,2}, + {CNST_LIMB(0x7c499b),{CNST_LIMB(0x7a590d7),9,CNST_LIMB(0x2479eb),CNST_LIMB(0x430dcd),CNST_LIMB(0x5d4660),CNST_LIMB(0x7e714),CNST_LIMB(0x730ed)},412,2}, + {CNST_LIMB(0x7daf13),{CNST_LIMB(0x4b7b45e),9,CNST_LIMB(0x36b255),CNST_LIMB(0x4daef0),CNST_LIMB(0x30e1aa),CNST_LIMB(0x344a6a),CNST_LIMB(0x5c31ba)},414,2}, + {CNST_LIMB(0x7f9e77),{CNST_LIMB(0xc3a716),9,CNST_LIMB(0x437389),CNST_LIMB(0x74307),CNST_LIMB(0x2e66cf),CNST_LIMB(0x3c0e39),CNST_LIMB(0x5ce507)},416,2}, + {CNST_LIMB(0x80db9b),{CNST_LIMB(0xfc976d0c),8,CNST_LIMB(0x4c386c),CNST_LIMB(0x28ddeb),CNST_LIMB(0x379ea),CNST_LIMB(0xc5c2c),CNST_LIMB(0x649115)},418,2}, + {CNST_LIMB(0x8247cb),{CNST_LIMB(0xf709b404),8,CNST_LIMB(0x4f023),CNST_LIMB(0x15c03b),CNST_LIMB(0x52a1c2),CNST_LIMB(0x8e48d),CNST_LIMB(0x6ac464)},420,2}, + {CNST_LIMB(0x846dd3),{CNST_LIMB(0xeee06215),8,CNST_LIMB(0x7412d6),CNST_LIMB(0x3429c8),CNST_LIMB(0x3cb39f),CNST_LIMB(0xab613),CNST_LIMB(0x2009b1)},422,2}, + {CNST_LIMB(0x85b0f7),{CNST_LIMB(0xea343be5),8,CNST_LIMB(0x1b473a),CNST_LIMB(0x5c47c5),CNST_LIMB(0x37a025),CNST_LIMB(0x319645),CNST_LIMB(0x171dc2)},424,2}, + {CNST_LIMB(0x8698a3),{CNST_LIMB(0xe6e87a28),8,CNST_LIMB(0x7a3a8e),CNST_LIMB(0x14aa18),CNST_LIMB(0xfcc0a),CNST_LIMB(0x6f70f6),CNST_LIMB(0x517250)},426,2}, + {CNST_LIMB(0x89543f),{CNST_LIMB(0xdd37f8e3),8,CNST_LIMB(0x1e069d),CNST_LIMB(0x6af5e5),CNST_LIMB(0x2b4602),CNST_LIMB(0x58ba56),CNST_LIMB(0x628249)},428,2}, + {CNST_LIMB(0x8ab4a1),{CNST_LIMB(0xd87b9806),8,CNST_LIMB(0x42f728),CNST_LIMB(0x543f3c),CNST_LIMB(0x3c8357),CNST_LIMB(0x24d14e),CNST_LIMB(0x5a87a3)},430,2}, + {CNST_LIMB(0x8c16b3),{CNST_LIMB(0xd3d1680a),8,CNST_LIMB(0x729777),CNST_LIMB(0x2a00c3),CNST_LIMB(0x1c0ce2),CNST_LIMB(0x7a0870),CNST_LIMB(0x6d3e0f)},432,2}, + {CNST_LIMB(0x8d7ac9),{CNST_LIMB(0xcf37f810),8,CNST_LIMB(0x1eee79),CNST_LIMB(0x87295d),CNST_LIMB(0x4a0d02),CNST_LIMB(0x5f2c06),CNST_LIMB(0x7fab01)},434,2}, + {CNST_LIMB(0x8f4037),{CNST_LIMB(0xc97dc00a),8,CNST_LIMB(0x465dd1),CNST_LIMB(0x3273f9),CNST_LIMB(0x5fd14a),CNST_LIMB(0xe948c),CNST_LIMB(0x363984)},436,2}, + {CNST_LIMB(0x90d84d),{CNST_LIMB(0xc474d09d),8,CNST_LIMB(0x42180c),CNST_LIMB(0x6d2683),CNST_LIMB(0x8fc9c3),CNST_LIMB(0x8b1f),CNST_LIMB(0x3c8d75)},438,2}, + {CNST_LIMB(0x928a75),{CNST_LIMB(0xbf3852d6),8,CNST_LIMB(0x203db5),CNST_LIMB(0x3f8633),CNST_LIMB(0x473792),CNST_LIMB(0x4f57eb),CNST_LIMB(0x1caa1f)},440,2}, + {CNST_LIMB(0x9488ff),{CNST_LIMB(0xb9372823),8,CNST_LIMB(0x2000b9),CNST_LIMB(0x32dedd),CNST_LIMB(0x3fd090),CNST_LIMB(0x4527e0),CNST_LIMB(0x68649)},442,2}, + {CNST_LIMB(0x97671b),{CNST_LIMB(0xb0dbd3c0),8,CNST_LIMB(0x820270),CNST_LIMB(0x61b63b),CNST_LIMB(0x1d1e83),CNST_LIMB(0x12ef40),CNST_LIMB(0x1cfa09)},444,2}, + {CNST_LIMB(0x9923ff),{CNST_LIMB(0xabf252fb),8,CNST_LIMB(0x90f5ab),CNST_LIMB(0x6e1771),CNST_LIMB(0x46a353),CNST_LIMB(0x17fcbb),CNST_LIMB(0x2be098)},446,2}, + {CNST_LIMB(0x9ab0f7),{CNST_LIMB(0xa7a820aa),8,CNST_LIMB(0x6597df),CNST_LIMB(0x80b1e1),CNST_LIMB(0x3e615e),CNST_LIMB(0x2f8e95),CNST_LIMB(0x1f7c86)},448,2}, + {CNST_LIMB(0x9bf4e5),{CNST_LIMB(0xa4382bde),8,CNST_LIMB(0x22384c),CNST_LIMB(0x88004f),CNST_LIMB(0x722b79),CNST_LIMB(0x1991ed),CNST_LIMB(0x5ff57b)},450,2}, + {CNST_LIMB(0x9d8599),{CNST_LIMB(0xa00b3849),8,CNST_LIMB(0x6e760),CNST_LIMB(0x715013),CNST_LIMB(0x859556),CNST_LIMB(0x6d6b1f),CNST_LIMB(0x199f9f)},452,2}, + {CNST_LIMB(0x9eb361),{CNST_LIMB(0x9cf414d7),8,CNST_LIMB(0x974fe4),CNST_LIMB(0x8a105a),CNST_LIMB(0x241b35),CNST_LIMB(0x368b5),CNST_LIMB(0x598c01)},454,2}, + {CNST_LIMB(0xa15e8f),{CNST_LIMB(0x961fc918),8,CNST_LIMB(0x140936),CNST_LIMB(0x6f0d9e),CNST_LIMB(0x48ac16),CNST_LIMB(0x761bd0),CNST_LIMB(0x348d35)},456,2}, + {CNST_LIMB(0xa1f723),{CNST_LIMB(0x94a1331d),8,CNST_LIMB(0x65fcc4),CNST_LIMB(0x45b694),CNST_LIMB(0x54be56),CNST_LIMB(0x844f1b),CNST_LIMB(0x9b1cb)},458,2}, + {CNST_LIMB(0xa4a875),{CNST_LIMB(0x8e03449b),8,CNST_LIMB(0x21a1a),CNST_LIMB(0x54772e),CNST_LIMB(0x475f04),CNST_LIMB(0x5f6d87),CNST_LIMB(0x5c969f)},460,2}, + {CNST_LIMB(0xa69237),{CNST_LIMB(0x897104a6),8,CNST_LIMB(0x498991),CNST_LIMB(0x461e8),CNST_LIMB(0x836d4b),CNST_LIMB(0x3e02e4),CNST_LIMB(0x93303)},462,2}, + {CNST_LIMB(0xa7c887),{CNST_LIMB(0x86995ac4),8,CNST_LIMB(0x648256),CNST_LIMB(0x40fa2c),CNST_LIMB(0x16b3e6),CNST_LIMB(0x16f7cd),CNST_LIMB(0x2d7a2c)},464,2}, + {CNST_LIMB(0xa8cbfb),{CNST_LIMB(0x8440f99b),8,CNST_LIMB(0x2ad794),CNST_LIMB(0x84d3e2),CNST_LIMB(0x57d90f),CNST_LIMB(0x434d43),CNST_LIMB(0x98e467)},466,2}, + {CNST_LIMB(0xa9ea2d),{CNST_LIMB(0x81b30566),8,CNST_LIMB(0x76d253),CNST_LIMB(0x71986c),CNST_LIMB(0x9da46c),CNST_LIMB(0x847d02),CNST_LIMB(0x8d56af)},468,2}, + {CNST_LIMB(0xab8c4d),{CNST_LIMB(0x7e06ee7c),8,CNST_LIMB(0x4a51a),CNST_LIMB(0x3f7f9a),CNST_LIMB(0x299883),CNST_LIMB(0x1ccf57),CNST_LIMB(0x94b94c)},470,2}, + {CNST_LIMB(0xace18b),{CNST_LIMB(0x7b14dd84),8,CNST_LIMB(0xe1737),CNST_LIMB(0x6c6a46),CNST_LIMB(0x33604b),CNST_LIMB(0x61a65f),CNST_LIMB(0x613dff)},472,2}, + {CNST_LIMB(0xae6cb9),{CNST_LIMB(0x77ba02f3),8,CNST_LIMB(0x7ebd01),CNST_LIMB(0x6da379),CNST_LIMB(0x404bf8),CNST_LIMB(0x98a441),CNST_LIMB(0x5fa230)},474,2}, + {CNST_LIMB(0xb04971),{CNST_LIMB(0x73c1f6ae),8,CNST_LIMB(0x85913d),CNST_LIMB(0x730406),CNST_LIMB(0x935a52),CNST_LIMB(0x141c45),CNST_LIMB(0x9ed7c1)},476,2}, + {CNST_LIMB(0xb2c8dd),{CNST_LIMB(0x6e906003),8,CNST_LIMB(0x64d40a),CNST_LIMB(0x548466),CNST_LIMB(0x195c00),CNST_LIMB(0x955606),CNST_LIMB(0x6cbd0b)},478,2}, + {CNST_LIMB(0xb5eef9),{CNST_LIMB(0x683834dc),8,CNST_LIMB(0x27f1d8),CNST_LIMB(0x99504a),CNST_LIMB(0x8fc0f8),CNST_LIMB(0x596d83),CNST_LIMB(0xc567c)},480,2}, + {CNST_LIMB(0xb6e223),{CNST_LIMB(0x66594100),8,CNST_LIMB(0x3fc30e),CNST_LIMB(0x6243c4),CNST_LIMB(0x6824f2),CNST_LIMB(0x891241),CNST_LIMB(0x63535c)},482,2}, + {CNST_LIMB(0xb7848f),{CNST_LIMB(0x651c1939),8,CNST_LIMB(0x142495),CNST_LIMB(0x4c26f5),CNST_LIMB(0x9052ac),CNST_LIMB(0x5383af),CNST_LIMB(0x9b6cec)},484,2}, + {CNST_LIMB(0xba62e1),{CNST_LIMB(0x5f9d2a63),8,CNST_LIMB(0x726d81),CNST_LIMB(0x8ed027),CNST_LIMB(0x9cb3fa),CNST_LIMB(0x86007),CNST_LIMB(0x3b4e20)},486,2}, + {CNST_LIMB(0xbc6b1b),{CNST_LIMB(0x5bd25a68),8,CNST_LIMB(0x9ad267),CNST_LIMB(0xa87a2a),CNST_LIMB(0x50c0b4),CNST_LIMB(0x5c1a64),CNST_LIMB(0x8787d)},488,2}, + {CNST_LIMB(0xbdec3f),{CNST_LIMB(0x5911033f),8,CNST_LIMB(0xc9f19),CNST_LIMB(0x7bacea),CNST_LIMB(0x2671a7),CNST_LIMB(0xb37e57),CNST_LIMB(0x892aa9)},490,2}, + {CNST_LIMB(0xbec8f7),{CNST_LIMB(0x5781ce5c),8,CNST_LIMB(0x60bd0f),CNST_LIMB(0x702718),CNST_LIMB(0x19e5b),CNST_LIMB(0xa53836),CNST_LIMB(0x811bc)},492,2}, + {CNST_LIMB(0xbfa637),{CNST_LIMB(0x55f53e55),8,CNST_LIMB(0xb798bd),CNST_LIMB(0x368e32),CNST_LIMB(0x673db8),CNST_LIMB(0x6e6cac),CNST_LIMB(0xa60037)},494,2}, + {CNST_LIMB(0xc12aa3),{CNST_LIMB(0x5345a13b),8,CNST_LIMB(0x348a27),CNST_LIMB(0x882118),CNST_LIMB(0x212db0),CNST_LIMB(0xb63011),CNST_LIMB(0x5ee59e)},496,2}, + {CNST_LIMB(0xc32027),{CNST_LIMB(0x4fdda055),8,CNST_LIMB(0xa8ecf7),CNST_LIMB(0x9e3626),CNST_LIMB(0x69e537),CNST_LIMB(0x1c194c),CNST_LIMB(0x9ee26b)},498,2}, + {CNST_LIMB(0xc46ff7),{CNST_LIMB(0x4d9f7581),8,CNST_LIMB(0x7a5bb5),CNST_LIMB(0x328e10),CNST_LIMB(0x588a40),CNST_LIMB(0x9269c9),CNST_LIMB(0x388845)},500,2}, + {CNST_LIMB(0xc6da9b),{CNST_LIMB(0x49918c4c),8,CNST_LIMB(0x710ecd),CNST_LIMB(0x18ede1),CNST_LIMB(0x20d6b),CNST_LIMB(0x6f30ac),CNST_LIMB(0x4eeca1)},502,2}, + {CNST_LIMB(0xc7f507),{CNST_LIMB(0x47c00fbb),8,CNST_LIMB(0x96040f),CNST_LIMB(0x3f840c),CNST_LIMB(0x2fac24),CNST_LIMB(0xc5a1e4),CNST_LIMB(0x23556c)},504,2}, + {CNST_LIMB(0xc981bb),{CNST_LIMB(0x453ad327),8,CNST_LIMB(0x2e4d99),CNST_LIMB(0x887f8a),CNST_LIMB(0x2577a1),CNST_LIMB(0x9e767e),CNST_LIMB(0x48120a)},506,2}, + {CNST_LIMB(0xcb6549),{CNST_LIMB(0x42359eda),8,CNST_LIMB(0x2a9a2e),CNST_LIMB(0xca789a),CNST_LIMB(0xb7b9c2),CNST_LIMB(0x555236),CNST_LIMB(0x839f8e)},508,2}, + {CNST_LIMB(0xcdbe3f),{CNST_LIMB(0x3e887849),8,CNST_LIMB(0x6dadbe),CNST_LIMB(0x4075a),CNST_LIMB(0x569198),CNST_LIMB(0xc7b595),CNST_LIMB(0xb632a3)},510,2}, + {CNST_LIMB(0xcf16df),{CNST_LIMB(0x3c766321),8,CNST_LIMB(0x5fc4bc),CNST_LIMB(0x515054),CNST_LIMB(0x6d7393),CNST_LIMB(0xbdbd7b),CNST_LIMB(0x93b24)},512,2}, + {CNST_LIMB(0xd0c7a5),{CNST_LIMB(0x39e666de),8,CNST_LIMB(0xbbe743),CNST_LIMB(0x59ebc6),CNST_LIMB(0xb78ce9),CNST_LIMB(0xa5b5f9),CNST_LIMB(0x98247)},514,2}, + {CNST_LIMB(0xd279eb),{CNST_LIMB(0x375ebc36),8,CNST_LIMB(0x4de383),CNST_LIMB(0xbd2dda),CNST_LIMB(0x4474ea),CNST_LIMB(0x63dc28),CNST_LIMB(0xa82fcd)},516,2}, + {CNST_LIMB(0xd44b3b),{CNST_LIMB(0x34b443ac),8,CNST_LIMB(0x957d04),CNST_LIMB(0x160567),CNST_LIMB(0x8a3732),CNST_LIMB(0x7d4980),CNST_LIMB(0x6fcafc)},518,2}, + {CNST_LIMB(0xd6932b),{CNST_LIMB(0x316c2a92),8,CNST_LIMB(0x5aa9c5),CNST_LIMB(0xae43b3),CNST_LIMB(0x3ce391),CNST_LIMB(0x46a10a),CNST_LIMB(0x6cf4d)},520,2}, + {CNST_LIMB(0xd8a43f),{CNST_LIMB(0x2e8244dc),8,CNST_LIMB(0x6e3dae),CNST_LIMB(0x7eb8fd),CNST_LIMB(0x89a77c),CNST_LIMB(0xbf3d9b),CNST_LIMB(0x826cd3)},522,2}, + {CNST_LIMB(0xdab733),{CNST_LIMB(0x2ba3e655),8,CNST_LIMB(0x8c076f),CNST_LIMB(0xacc46),CNST_LIMB(0x98a8b5),CNST_LIMB(0x9eab3c),CNST_LIMB(0xd15cf9)},524,2}, + {CNST_LIMB(0xdc5637),{CNST_LIMB(0x296f8311),8,CNST_LIMB(0x5ffa31),CNST_LIMB(0xb5456f),CNST_LIMB(0x63ef9),CNST_LIMB(0x879429),CNST_LIMB(0xba25f8)},526,2}, + {CNST_LIMB(0xdee543),{CNST_LIMB(0x26056807),8,CNST_LIMB(0x4b50e),CNST_LIMB(0xd729ee),CNST_LIMB(0x1fa01),CNST_LIMB(0x8f0a41),CNST_LIMB(0x8ee0d5)},528,2}, + {CNST_LIMB(0xe0ffcf),{CNST_LIMB(0x2345a6f8),8,CNST_LIMB(0x3d37b3),CNST_LIMB(0xac8c19),CNST_LIMB(0x3b538),CNST_LIMB(0x2d2cfb),CNST_LIMB(0x93a737)},530,2}, + {CNST_LIMB(0xe2688f),{CNST_LIMB(0x21758d16),8,CNST_LIMB(0x67f691),CNST_LIMB(0x400d5d),CNST_LIMB(0x79ce95),CNST_LIMB(0x9778c0),CNST_LIMB(0x98b2ca)},532,2}, + {CNST_LIMB(0xe48753),{CNST_LIMB(0x1ec6129a),8,CNST_LIMB(0xb0d146),CNST_LIMB(0xc2e775),CNST_LIMB(0xa20714),CNST_LIMB(0x347b8),CNST_LIMB(0x4dbba1)},534,2}, + {CNST_LIMB(0xe64dd9),{CNST_LIMB(0x1c901a18),8,CNST_LIMB(0x81a344),CNST_LIMB(0x35a50b),CNST_LIMB(0x12bdce),CNST_LIMB(0xd99aec),CNST_LIMB(0x453855)},536,2}, + {CNST_LIMB(0xe92895),{CNST_LIMB(0x19144348),8,CNST_LIMB(0x127473),CNST_LIMB(0x9af5cf),CNST_LIMB(0x2d7e77),CNST_LIMB(0x33c1e7),CNST_LIMB(0x5a5f05)},538,2}, + {CNST_LIMB(0xea3bc3),{CNST_LIMB(0x17ca0c60),8,CNST_LIMB(0xb8de7b),CNST_LIMB(0x2ea8e2),CNST_LIMB(0xc4d2cd),CNST_LIMB(0xca2134),CNST_LIMB(0xbe5214)},540,2}, + {CNST_LIMB(0xeb30db),{CNST_LIMB(0x16a67a74),8,CNST_LIMB(0x98f22e),CNST_LIMB(0x95837e),CNST_LIMB(0x2ff38c),CNST_LIMB(0x8dc4f4),CNST_LIMB(0x5e8e36)},542,2}, + {CNST_LIMB(0xec829d),{CNST_LIMB(0x15188a69),8,CNST_LIMB(0x16ac1f),CNST_LIMB(0x1127d0),CNST_LIMB(0xe5bf6),CNST_LIMB(0x888ab0),CNST_LIMB(0xb4e5e9)},544,2}, + {CNST_LIMB(0xeeeb15),{CNST_LIMB(0x124d9074),8,CNST_LIMB(0x486386),CNST_LIMB(0x22bbbc),CNST_LIMB(0xda4918),CNST_LIMB(0x63f048),CNST_LIMB(0x2aaebe)},546,2}, + {CNST_LIMB(0xf387b5),{CNST_LIMB(0xd1bc0e4),8,CNST_LIMB(0x1a66cf),CNST_LIMB(0x746675),CNST_LIMB(0xead6b1),CNST_LIMB(0x105a5c),CNST_LIMB(0xcdf42)},548,2}, + {CNST_LIMB(0xf4c055),{CNST_LIMB(0xbc40448),8,CNST_LIMB(0xbb6759),CNST_LIMB(0x805107),CNST_LIMB(0xb92d29),CNST_LIMB(0x3a3c25),CNST_LIMB(0xa2e734)},550,2}, + {CNST_LIMB(0xf618f7),{CNST_LIMB(0xa4d0a3d),8,CNST_LIMB(0x4a0f5a),CNST_LIMB(0x54cdd8),CNST_LIMB(0x3d17ae),CNST_LIMB(0xceec3c),CNST_LIMB(0xa1cd0c)},552,2}, + {CNST_LIMB(0xf71437),{CNST_LIMB(0x93e3e57),8,CNST_LIMB(0x3c1311),CNST_LIMB(0x564098),CNST_LIMB(0xd2e6e),CNST_LIMB(0x64ea62),CNST_LIMB(0x1f88d1)},554,2}, + {CNST_LIMB(0xfa4843),{CNST_LIMB(0x5d92d74),8,CNST_LIMB(0xd453b1),CNST_LIMB(0x99575),CNST_LIMB(0xc6affc),CNST_LIMB(0xa2c123),CNST_LIMB(0x6b235f)},556,2}, + {CNST_LIMB(0xfc2381),{CNST_LIMB(0x3eba258),8,CNST_LIMB(0xe8147d),CNST_LIMB(0xe1d88e),CNST_LIMB(0x6a09d3),CNST_LIMB(0x896344),CNST_LIMB(0xb21675)},558,2}, + {CNST_LIMB(0xfea055),{CNST_LIMB(0x16190b1),8,CNST_LIMB(0x610aab),CNST_LIMB(0x19ab85),CNST_LIMB(0xacd1ac),CNST_LIMB(0xf8fa99),CNST_LIMB(0x9ea5c2)},560,2}, + {CNST_LIMB(0xfffff7),{CNST_LIMB(0x900),8,CNST_LIMB(0x900),CNST_LIMB(0x510000),CNST_LIMB(0x19a1),CNST_LIMB(0xe6a900),CNST_LIMB(0xf148f3)},562,2}, + {CNST_LIMB(0x102e1d1),{CNST_LIMB(0xfa4ccb91),7,CNST_LIMB(0x26d473),CNST_LIMB(0x529560),CNST_LIMB(0xe9e54f),CNST_LIMB(0x813af5),CNST_LIMB(0xea421e)},564,2}, + {CNST_LIMB(0x10464c5),{CNST_LIMB(0xf75c6ae0),7,CNST_LIMB(0xb132d9),CNST_LIMB(0xc5b735),CNST_LIMB(0xb4c6b6),CNST_LIMB(0x279b4a),CNST_LIMB(0xd636aa)},566,2}, + {CNST_LIMB(0x1064993),{CNST_LIMB(0xf3ba04e3),7,CNST_LIMB(0xe27005),CNST_LIMB(0xcea832),CNST_LIMB(0x4b38b6),CNST_LIMB(0x1007cca),CNST_LIMB(0x4fb71b)},568,2}, + {CNST_LIMB(0x107cf03),{CNST_LIMB(0xf0d8510c),7,CNST_LIMB(0x6f7518),CNST_LIMB(0xea9722),CNST_LIMB(0x53381),CNST_LIMB(0x342e71),CNST_LIMB(0x4f960a)},570,2}, + {CNST_LIMB(0x10bc139),{CNST_LIMB(0xe985c5a8),7,CNST_LIMB(0xcbd5ac),CNST_LIMB(0x283948),CNST_LIMB(0x89eeb4),CNST_LIMB(0xa48aed),CNST_LIMB(0xd9073a)},572,2}, + {CNST_LIMB(0x10ef65b),{CNST_LIMB(0xe3ba4eb7),7,CNST_LIMB(0xea1455),CNST_LIMB(0x350a2b),CNST_LIMB(0xad68ad),CNST_LIMB(0x55454f),CNST_LIMB(0x453090)},574,2}, + {CNST_LIMB(0x1103fe7),{CNST_LIMB(0xe170c66b),7,CNST_LIMB(0xc41770),CNST_LIMB(0xdac1e6),CNST_LIMB(0x529224),CNST_LIMB(0xcdbda1),CNST_LIMB(0x575e1f)},576,2}, + {CNST_LIMB(0x111cc77),{CNST_LIMB(0xdeb77848),7,CNST_LIMB(0x621ce7),CNST_LIMB(0x29475a),CNST_LIMB(0x375d01),CNST_LIMB(0x7b011e),CNST_LIMB(0xdb52b5)},578,2}, + {CNST_LIMB(0x1135a27),{CNST_LIMB(0xdc0410ce),7,CNST_LIMB(0x22fbe),CNST_LIMB(0xebe9cd),CNST_LIMB(0xf9200f),CNST_LIMB(0x781387),CNST_LIMB(0x4a78a)},580,2}, + {CNST_LIMB(0x114e90f),{CNST_LIMB(0xd95655f8),7,CNST_LIMB(0xb9262c),CNST_LIMB(0x4a3c6),CNST_LIMB(0xc0f574),CNST_LIMB(0xe03caa),CNST_LIMB(0x66a8a4)},582,2}, + {CNST_LIMB(0x11678ff),{CNST_LIMB(0xd6ae8986),7,CNST_LIMB(0x5eedeb),CNST_LIMB(0x6ec813),CNST_LIMB(0x54431),CNST_LIMB(0xd8db91),CNST_LIMB(0xec42f8)},584,2}, + {CNST_LIMB(0x1184cfb),{CNST_LIMB(0xd39cb249),7,CNST_LIMB(0xe1ef8d),CNST_LIMB(0x3676d9),CNST_LIMB(0xd48882),CNST_LIMB(0xa68adc),CNST_LIMB(0x3fd4d3)},586,2}, + {CNST_LIMB(0x11bb55f),{CNST_LIMB(0xcdfecf82),7,CNST_LIMB(0x11b0ca6),CNST_LIMB(0x607c95),CNST_LIMB(0x81c5b1),CNST_LIMB(0x1042529),CNST_LIMB(0x6c54e9)},588,2}, + {CNST_LIMB(0x11f24c3),{CNST_LIMB(0xc877eda7),7,CNST_LIMB(0x434254),CNST_LIMB(0xe086aa),CNST_LIMB(0x880a3c),CNST_LIMB(0x543e9e),CNST_LIMB(0x5fb6e0)},590,2}, + {CNST_LIMB(0x12121f1),{CNST_LIMB(0xc5540f69),7,CNST_LIMB(0xc0093e),CNST_LIMB(0x10f89ba),CNST_LIMB(0x103c37b),CNST_LIMB(0x603b39),CNST_LIMB(0x6d8025)},592,2}, + {CNST_LIMB(0x12320e7),{CNST_LIMB(0xc2386bef),7,CNST_LIMB(0x2014f9),CNST_LIMB(0xbb6e8f),CNST_LIMB(0xa183a),CNST_LIMB(0x2740d9),CNST_LIMB(0x320d3f)},594,2}, + {CNST_LIMB(0x1269adb),{CNST_LIMB(0xbce8612d),7,CNST_LIMB(0x85b616),CNST_LIMB(0x11adf8e),CNST_LIMB(0x1549c5),CNST_LIMB(0xbfd621),CNST_LIMB(0x439206)},596,2}, + {CNST_LIMB(0x1296d5d),{CNST_LIMB(0xb8af9cfd),7,CNST_LIMB(0x660414),CNST_LIMB(0xbc3e14),CNST_LIMB(0xa5260),CNST_LIMB(0x7c5b6),CNST_LIMB(0xed8cb7)},598,2}, + {CNST_LIMB(0x12bb8af),{CNST_LIMB(0xb55010b4),7,CNST_LIMB(0xc4bafa),CNST_LIMB(0x174ff3),CNST_LIMB(0x3126a8),CNST_LIMB(0xddc888),CNST_LIMB(0x952d35)},600,2}, + {CNST_LIMB(0x12e06bd),{CNST_LIMB(0xb1f9b531),7,CNST_LIMB(0x12a5088),CNST_LIMB(0x88ba40),CNST_LIMB(0x387b05),CNST_LIMB(0x735661),CNST_LIMB(0x10441d1)},602,2}, + {CNST_LIMB(0x12f8587),{CNST_LIMB(0xafd6654a),7,CNST_LIMB(0x116db9f),CNST_LIMB(0x1174dde),CNST_LIMB(0x6b7abe),CNST_LIMB(0xefeaf9),CNST_LIMB(0x769d08)},604,2}, + {CNST_LIMB(0x1328603),{CNST_LIMB(0xab9bbca0),7,CNST_LIMB(0xf67f81),CNST_LIMB(0x749483),CNST_LIMB(0x6a9685),CNST_LIMB(0xa81ebd),CNST_LIMB(0x10a0069)},606,2}, + {CNST_LIMB(0x134fd5f),{CNST_LIMB(0xa83200f8),7,CNST_LIMB(0x1e2d54),CNST_LIMB(0xff18eb),CNST_LIMB(0xac6c46),CNST_LIMB(0x76c79e),CNST_LIMB(0x1305fef)},608,2}, + {CNST_LIMB(0x1370dc5),{CNST_LIMB(0xa561685d),7,CNST_LIMB(0xd6b466),CNST_LIMB(0x4769f0),CNST_LIMB(0xa9f428),CNST_LIMB(0x4e0d0e),CNST_LIMB(0x17e847)},610,2}, + {CNST_LIMB(0x137e18d),{CNST_LIMB(0xa4434579),7,CNST_LIMB(0x28fa56),CNST_LIMB(0xe4bd47),CNST_LIMB(0xd54364),CNST_LIMB(0x11045cb),CNST_LIMB(0x40032e)},612,2}, + {CNST_LIMB(0x13b9e0f),{CNST_LIMB(0x9f49a048),7,CNST_LIMB(0xcb31df),CNST_LIMB(0x682ee9),CNST_LIMB(0x46a099),CNST_LIMB(0xb1fdb5),CNST_LIMB(0x8de6fa)},614,2}, + {CNST_LIMB(0x13dd787),{CNST_LIMB(0x9c619108),7,CNST_LIMB(0x3c915e),CNST_LIMB(0x9ffca6),CNST_LIMB(0x4311ab),CNST_LIMB(0xaa8ce2),CNST_LIMB(0xc03cfc)},616,2}, + {CNST_LIMB(0x1410da9),{CNST_LIMB(0x98419145),7,CNST_LIMB(0x291d54),CNST_LIMB(0xb4cbb5),CNST_LIMB(0xf576fc),CNST_LIMB(0xbae570),CNST_LIMB(0x270f58)},618,2}, + {CNST_LIMB(0x142e037),{CNST_LIMB(0x95f3a375),7,CNST_LIMB(0x13b149a),CNST_LIMB(0x79c467),CNST_LIMB(0x68f190),CNST_LIMB(0x103c57e),CNST_LIMB(0x484abd)},620,2}, + {CNST_LIMB(0x146f579),{CNST_LIMB(0x90e1d908),7,CNST_LIMB(0x903978),CNST_LIMB(0x12e0c75),CNST_LIMB(0xbde066),CNST_LIMB(0xa3f77f),CNST_LIMB(0x751ee4)},622,2}, + {CNST_LIMB(0x148a83d),{CNST_LIMB(0x8ecf89f8),7,CNST_LIMB(0x853895),CNST_LIMB(0x97860b),CNST_LIMB(0x57dd79),CNST_LIMB(0xfeb2d2),CNST_LIMB(0x481284)},624,2}, + {CNST_LIMB(0x149eee3),{CNST_LIMB(0x8d44b2dc),7,CNST_LIMB(0xd13c6e),CNST_LIMB(0x11c7ae5),CNST_LIMB(0x6ee9b4),CNST_LIMB(0x1472db2),CNST_LIMB(0xd31f9a)},626,2}, + {CNST_LIMB(0x14b5a87),{CNST_LIMB(0x8b90b87a),7,CNST_LIMB(0x103561d),CNST_LIMB(0x8f00c8),CNST_LIMB(0xceccba),CNST_LIMB(0x3eb1e6),CNST_LIMB(0xbbd310)},628,2}, + {CNST_LIMB(0x14da207),{CNST_LIMB(0x88dce7c1),7,CNST_LIMB(0x8ff2a4),CNST_LIMB(0x144a52a),CNST_LIMB(0xb74f7b),CNST_LIMB(0xda4eec),CNST_LIMB(0xee9e1a)},630,2}, + {CNST_LIMB(0x150a2cd),{CNST_LIMB(0x855bba07),7,CNST_LIMB(0xe4a0a6),CNST_LIMB(0x45c4da),CNST_LIMB(0x5dcfb5),CNST_LIMB(0x14fd54c),CNST_LIMB(0x884644)},632,2}, + {CNST_LIMB(0x1543ac3),{CNST_LIMB(0x813eeca5),7,CNST_LIMB(0xd3edc0),CNST_LIMB(0x4f45a6),CNST_LIMB(0x10c3a11),CNST_LIMB(0x12dfce5),CNST_LIMB(0x58014e)},634,2}, + {CNST_LIMB(0x1558715),{CNST_LIMB(0x7fc81087),7,CNST_LIMB(0x1303755),CNST_LIMB(0xe3da2c),CNST_LIMB(0x2217aa),CNST_LIMB(0x2eecc1),CNST_LIMB(0xe3364a)},636,2}, + {CNST_LIMB(0x1590059),{CNST_LIMB(0x7bead720),7,CNST_LIMB(0x14abe4b),CNST_LIMB(0x146c7ac),CNST_LIMB(0x9fae47),CNST_LIMB(0x1357e94),CNST_LIMB(0x41495e)},638,2}, + {CNST_LIMB(0x15d5e5d),{CNST_LIMB(0x772b10cb),7,CNST_LIMB(0xcc1211),CNST_LIMB(0xba039b),CNST_LIMB(0x15d4d67),CNST_LIMB(0x111bb4f),CNST_LIMB(0x4310f6)},640,2}, + {CNST_LIMB(0x15e3ecd),{CNST_LIMB(0x763aa850),7,CNST_LIMB(0x282041),CNST_LIMB(0x5d9b89),CNST_LIMB(0x68f0b5),CNST_LIMB(0x5a801),CNST_LIMB(0x2db8ad)},642,2}, + {CNST_LIMB(0x15f8fff),{CNST_LIMB(0x74d3b8c9),7,CNST_LIMB(0x9160ba),CNST_LIMB(0x108e4f8),CNST_LIMB(0x1548626),CNST_LIMB(0x3f17cb),CNST_LIMB(0xd0d091)},644,2}, + {CNST_LIMB(0x161c35d),{CNST_LIMB(0x7281fed3),7,CNST_LIMB(0x59d1cb),CNST_LIMB(0x125ce86),CNST_LIMB(0xd3226b),CNST_LIMB(0x5bbc3c),CNST_LIMB(0x8ca873)},646,2}, + {CNST_LIMB(0x1665463),{CNST_LIMB(0x6dc93ddc),7,CNST_LIMB(0x140019e),CNST_LIMB(0x1135f13),CNST_LIMB(0x1c7914),CNST_LIMB(0x1578af),CNST_LIMB(0x7a9692)},648,2}, + {CNST_LIMB(0x16a7c5b),{CNST_LIMB(0x699795f3),7,CNST_LIMB(0x1209004),CNST_LIMB(0x8d6bc6),CNST_LIMB(0x11196b),CNST_LIMB(0xd5b8fa),CNST_LIMB(0x1108ed2)},650,2}, + {CNST_LIMB(0x16dc3cf),{CNST_LIMB(0x6659b596),7,CNST_LIMB(0x401643),CNST_LIMB(0x93a8d2),CNST_LIMB(0x49d87d),CNST_LIMB(0xbf9e69),CNST_LIMB(0x52624a)},652,2}, + {CNST_LIMB(0x17075ab),{CNST_LIMB(0x63bac6f8),7,CNST_LIMB(0x13ea4c5),CNST_LIMB(0xaf8993),CNST_LIMB(0x76bc76),CNST_LIMB(0x9007dc),CNST_LIMB(0x1456c61)},654,2}, + {CNST_LIMB(0x1732a0f),{CNST_LIMB(0x61232de9),7,CNST_LIMB(0xd315b0),CNST_LIMB(0x4cfeb1),CNST_LIMB(0x2513c9),CNST_LIMB(0x14a0231),CNST_LIMB(0xcc3b26)},656,2}, + {CNST_LIMB(0x1745e87),{CNST_LIMB(0x5ffea463),7,CNST_LIMB(0x17361b7),CNST_LIMB(0xef04d3),CNST_LIMB(0x240601),CNST_LIMB(0x1525d6a),CNST_LIMB(0x3b32f6)},658,2}, + {CNST_LIMB(0x1767b9b),{CNST_LIMB(0x5e020e70),7,CNST_LIMB(0x1810b),CNST_LIMB(0x1515e50),CNST_LIMB(0x1233c35),CNST_LIMB(0xee3741),CNST_LIMB(0x15e7ab1)},660,2}, + {CNST_LIMB(0x1789a3f),{CNST_LIMB(0x5c09bc40),7,CNST_LIMB(0x7292e),CNST_LIMB(0x7b725f),CNST_LIMB(0x3a8778),CNST_LIMB(0x10616f6),CNST_LIMB(0xf1a8f8)},662,2}, + {CNST_LIMB(0x17a6c5f),{CNST_LIMB(0x5a5d09a0),7,CNST_LIMB(0x44c3cd),CNST_LIMB(0x1247ae4),CNST_LIMB(0xa073a6),CNST_LIMB(0x1babb4),CNST_LIMB(0x989279)},664,2}, + {CNST_LIMB(0x17cdc07),{CNST_LIMB(0x5825de58),7,CNST_LIMB(0x1c2b4c),CNST_LIMB(0xf8f90c),CNST_LIMB(0xd444be),CNST_LIMB(0x8dc45e),CNST_LIMB(0xccd421)},666,2}, + {CNST_LIMB(0x17e62bb),{CNST_LIMB(0x56c63c21),7,CNST_LIMB(0x940d17),CNST_LIMB(0x3a1810),CNST_LIMB(0x13a9810),CNST_LIMB(0xffae30),CNST_LIMB(0x1255dff)},668,2}, + {CNST_LIMB(0x17fea27),{CNST_LIMB(0x5568c1fe),7,CNST_LIMB(0x10e821a),CNST_LIMB(0x12845dc),CNST_LIMB(0x699ab8),CNST_LIMB(0x106b79c),CNST_LIMB(0xb698dc)},670,2}, + {CNST_LIMB(0x18236b1),{CNST_LIMB(0x53607eac),7,CNST_LIMB(0x109e527),CNST_LIMB(0xe9b18e),CNST_LIMB(0x158d760),CNST_LIMB(0x16d26de),CNST_LIMB(0x1737873)},672,2}, + {CNST_LIMB(0x185e871),{CNST_LIMB(0x50294fbf),7,CNST_LIMB(0x1f75d8),CNST_LIMB(0x585eca),CNST_LIMB(0x13703b6),CNST_LIMB(0x6b54a3),CNST_LIMB(0x10c206a)},674,2}, + {CNST_LIMB(0x1899e8d),{CNST_LIMB(0x4cfde492),7,CNST_LIMB(0xc33092),CNST_LIMB(0x107dd7d),CNST_LIMB(0xb61ca4),CNST_LIMB(0x173e631),CNST_LIMB(0x572e64)},676,2}, + {CNST_LIMB(0x18bcab5),{CNST_LIMB(0x4b29fb49),7,CNST_LIMB(0xe65957),CNST_LIMB(0x5d77c),CNST_LIMB(0xa29563),CNST_LIMB(0xf9b556),CNST_LIMB(0x1480a64)},678,2}, + {CNST_LIMB(0x18d80f7),{CNST_LIMB(0x49bcdd73),7,CNST_LIMB(0x15961c4),CNST_LIMB(0xdbcd8a),CNST_LIMB(0xb5ae6f),CNST_LIMB(0x7fd9d),CNST_LIMB(0x16dc3a6)},680,2}, + {CNST_LIMB(0x18f6007),{CNST_LIMB(0x483155ab),7,CNST_LIMB(0x267b84),CNST_LIMB(0xd76742),CNST_LIMB(0x10c2a14),CNST_LIMB(0x13f8e0d),CNST_LIMB(0xb5f3c4)},682,2}, + {CNST_LIMB(0x194b37b),{CNST_LIMB(0x43dfa420),7,CNST_LIMB(0x17b1fa5),CNST_LIMB(0x796608),CNST_LIMB(0x17f337e),CNST_LIMB(0xaf0145),CNST_LIMB(0x11175e6)},684,2}, + {CNST_LIMB(0x197b15d),{CNST_LIMB(0x417f3822),7,CNST_LIMB(0x13125e0),CNST_LIMB(0x14b3f7b),CNST_LIMB(0x14f83a7),CNST_LIMB(0xc446ec),CNST_LIMB(0xe0bb76)},686,2}, + {CNST_LIMB(0x19a0fe7),{CNST_LIMB(0x3fa3ae32),7,CNST_LIMB(0x1501f87),CNST_LIMB(0xd76119),CNST_LIMB(0x198140b),CNST_LIMB(0x11483c2),CNST_LIMB(0x13eedd)},688,2}, + {CNST_LIMB(0x19d12c5),{CNST_LIMB(0x3d4f2d68),7,CNST_LIMB(0x10e6a6a),CNST_LIMB(0x113f89d),CNST_LIMB(0x43dfce),CNST_LIMB(0x676d88),CNST_LIMB(0x1051322)},690,2}, + {CNST_LIMB(0x1a13665),{CNST_LIMB(0x3a2948a7),7,CNST_LIMB(0x21a40f),CNST_LIMB(0x6c1b74),CNST_LIMB(0x18f9cbf),CNST_LIMB(0x163710c),CNST_LIMB(0xba45e3)},692,2}, + {CNST_LIMB(0x1a22ba5),{CNST_LIMB(0x39710891),7,CNST_LIMB(0x12d6774),CNST_LIMB(0xaf27ce),CNST_LIMB(0xa33302),CNST_LIMB(0x3b7d32),CNST_LIMB(0xa9ee6b)},694,2}, + {CNST_LIMB(0x1a74c45),{CNST_LIMB(0x35a51145),7,CNST_LIMB(0x15c1e7e),CNST_LIMB(0x121dbf4),CNST_LIMB(0x3547a9),CNST_LIMB(0xe70f16),CNST_LIMB(0x15f9fda)},696,2}, + {CNST_LIMB(0x1a963ff),{CNST_LIMB(0x341f1bbd),7,CNST_LIMB(0x19d89a),CNST_LIMB(0x155a2a7),CNST_LIMB(0xd7f651),CNST_LIMB(0x684fd7),CNST_LIMB(0x7e55d2)},698,2}, + {CNST_LIMB(0x1ac9e87),{CNST_LIMB(0x31ccf099),7,CNST_LIMB(0x181dfd8),CNST_LIMB(0xfaef30),CNST_LIMB(0xb27ad0),CNST_LIMB(0x1863b8d),CNST_LIMB(0xd48d51)},700,2}, + {CNST_LIMB(0x1af35df),{CNST_LIMB(0x2ff68490),7,CNST_LIMB(0x1a73977),CNST_LIMB(0x131639c),CNST_LIMB(0x11bca9f),CNST_LIMB(0x1fac8d),CNST_LIMB(0x11a070c)},702,2}, + {CNST_LIMB(0x1b31cdf),{CNST_LIMB(0x2d3ca1d1),7,CNST_LIMB(0x10d1556),CNST_LIMB(0x6689da),CNST_LIMB(0x158be38),CNST_LIMB(0x68ad8b),CNST_LIMB(0x396903)},704,2}, + {CNST_LIMB(0x1b75b83),{CNST_LIMB(0x2a539925),7,CNST_LIMB(0x47bcc1),CNST_LIMB(0xd524d7),CNST_LIMB(0x270769),CNST_LIMB(0x32c409),CNST_LIMB(0x1591be7)},706,2}, + {CNST_LIMB(0x1bb4cbb),{CNST_LIMB(0x27ac6d1f),7,CNST_LIMB(0x172f09f),CNST_LIMB(0x10b2d80),CNST_LIMB(0xa223e2),CNST_LIMB(0xa8425f),CNST_LIMB(0x144ec74)},708,2}, + {CNST_LIMB(0x1bd70c9),{CNST_LIMB(0x2640a3c6),7,CNST_LIMB(0x383c95),CNST_LIMB(0x1318d72),CNST_LIMB(0x267c57),CNST_LIMB(0xa0c479),CNST_LIMB(0x19a3e5a)},710,2}, + {CNST_LIMB(0x1bf6bed),{CNST_LIMB(0x24f31cbc),7,CNST_LIMB(0xd472d6),CNST_LIMB(0x6ef6fb),CNST_LIMB(0x1053c48),CNST_LIMB(0x18724cf),CNST_LIMB(0x10e2f8e)},712,2}, + {CNST_LIMB(0x1c1133d),{CNST_LIMB(0x23def7f6),7,CNST_LIMB(0x1a41a73),CNST_LIMB(0xc5b49b),CNST_LIMB(0xf60eb5),CNST_LIMB(0x101d1be),CNST_LIMB(0x675121)},714,2}, + {CNST_LIMB(0x1c3657d),{CNST_LIMB(0x225ebaa9),7,CNST_LIMB(0x538433),CNST_LIMB(0x1beeece),CNST_LIMB(0x7e9162),CNST_LIMB(0x11f4b85),CNST_LIMB(0x169874d)},716,2}, + {CNST_LIMB(0x1c48f1b),{CNST_LIMB(0x219fc5c7),7,CNST_LIMB(0x16f80d0),CNST_LIMB(0xc667b),CNST_LIMB(0x1b51bf2),CNST_LIMB(0xc2dda0),CNST_LIMB(0xda636d)},718,2}, + {CNST_LIMB(0x1c9397b),{CNST_LIMB(0x1eab354c),7,CNST_LIMB(0x98e44b),CNST_LIMB(0xbb1946),CNST_LIMB(0x171c294),CNST_LIMB(0x11e33e),CNST_LIMB(0x19699ef)},720,2}, + {CNST_LIMB(0x1ca650d),{CNST_LIMB(0x1defdd42),7,CNST_LIMB(0x1bbf2ca),CNST_LIMB(0x103160),CNST_LIMB(0x14a0f41),CNST_LIMB(0x122a95d),CNST_LIMB(0x39ebdd)},722,2}, + {CNST_LIMB(0x1cdea03),{CNST_LIMB(0x1bc22553),7,CNST_LIMB(0x1961c59),CNST_LIMB(0x4ddf62),CNST_LIMB(0xbe280c),CNST_LIMB(0x88f8ff),CNST_LIMB(0x9d662b)},724,2}, + {CNST_LIMB(0x1cfc32d),{CNST_LIMB(0x1aa0a289),7,CNST_LIMB(0x918037),CNST_LIMB(0x14c4f64),CNST_LIMB(0xa3bff3),CNST_LIMB(0xf0b9ca),CNST_LIMB(0xab58f4)},726,2}, + {CNST_LIMB(0x1d19d87),{CNST_LIMB(0x1980b45d),7,CNST_LIMB(0x15dda2c),CNST_LIMB(0x189acf7),CNST_LIMB(0x6e7d9c),CNST_LIMB(0xc27d69),CNST_LIMB(0xe8330e)},728,2}, + {CNST_LIMB(0x1d4fd97),{CNST_LIMB(0x177a113d),7,CNST_LIMB(0x15a4f03),CNST_LIMB(0x7b4d37),CNST_LIMB(0xc42d0d),CNST_LIMB(0x10671cc),CNST_LIMB(0x16e2e65)},730,2}, + {CNST_LIMB(0x1d8b8fb),{CNST_LIMB(0x15453bde),7,CNST_LIMB(0x12c48b2),CNST_LIMB(0x1805f09),CNST_LIMB(0x428d9b),CNST_LIMB(0x37dc1d),CNST_LIMB(0xfedeea)},732,2}, + {CNST_LIMB(0x1da97c1),{CNST_LIMB(0x142d855d),7,CNST_LIMB(0x2a31f6),CNST_LIMB(0x190d843),CNST_LIMB(0x13252b7),CNST_LIMB(0x17b628b),CNST_LIMB(0x1c54857)},734,2}, + {CNST_LIMB(0x1dfb571),{CNST_LIMB(0x113b820a),7,CNST_LIMB(0x1279bf8),CNST_LIMB(0x1790dc7),CNST_LIMB(0x68e2ea),CNST_LIMB(0x1660d52),CNST_LIMB(0x15d106e)},736,2}, + {CNST_LIMB(0x1e5603f),{CNST_LIMB(0xe0acea4),7,CNST_LIMB(0xa3ec7),CNST_LIMB(0xd4df0d),CNST_LIMB(0xd29620),CNST_LIMB(0x161e9cc),CNST_LIMB(0x193e43b)},738,2}, + {CNST_LIMB(0x1e6ed1d),{CNST_LIMB(0xd2eb5dd),7,CNST_LIMB(0x11fe2d2),CNST_LIMB(0xa755e8),CNST_LIMB(0x794624),CNST_LIMB(0x308681),CNST_LIMB(0x1480d48)},740,2}, + {CNST_LIMB(0x1e7f60d),{CNST_LIMB(0xc9c8ef0),7,CNST_LIMB(0x953532),CNST_LIMB(0x1cf3798),CNST_LIMB(0x1c48663),CNST_LIMB(0x12dadbb),CNST_LIMB(0x12af68b)},742,2}, + {CNST_LIMB(0x1e983e7),{CNST_LIMB(0xbc23ed1),7,CNST_LIMB(0x1ae78fd),CNST_LIMB(0x1b45abf),CNST_LIMB(0x44a316),CNST_LIMB(0x3e6ab0),CNST_LIMB(0x34f195)},744,2}, + {CNST_LIMB(0x1ed535b),{CNST_LIMB(0x9b0ce45),7,CNST_LIMB(0x1a10514),CNST_LIMB(0x8cc542),CNST_LIMB(0x27aea6),CNST_LIMB(0x156d2b0),CNST_LIMB(0x12b79c5)},746,2}, + {CNST_LIMB(0x1ef3c71),{CNST_LIMB(0x8aa6a24),7,CNST_LIMB(0xa4d5bc),CNST_LIMB(0x99919d),CNST_LIMB(0x3aaa8d),CNST_LIMB(0x84b962),CNST_LIMB(0x8fcd77)},748,2}, + {CNST_LIMB(0x1f2323b),{CNST_LIMB(0x717d73d),7,CNST_LIMB(0x1104bcf),CNST_LIMB(0x18b4484),CNST_LIMB(0x130c4bc),CNST_LIMB(0x131fde3),CNST_LIMB(0x62cf9)},750,2}, + {CNST_LIMB(0x1f690b5),{CNST_LIMB(0x4ce515c),7,CNST_LIMB(0xca8416),CNST_LIMB(0x10b3035),CNST_LIMB(0x1ed0c6c),CNST_LIMB(0xed6c5b),CNST_LIMB(0xbeb523)},752,2}, + {CNST_LIMB(0x1f7cabb),{CNST_LIMB(0x42bc099),7,CNST_LIMB(0x2b0d0a),CNST_LIMB(0x4eadd6),CNST_LIMB(0x8fecd6),CNST_LIMB(0xe704),CNST_LIMB(0x173ad19)},754,2}, + {CNST_LIMB(0x1fdf2b5),{CNST_LIMB(0x107b40c),7,CNST_LIMB(0x106a580),CNST_LIMB(0x1f0b0d5),CNST_LIMB(0x1e386b5),CNST_LIMB(0xbe5c49),CNST_LIMB(0x15bfc48)},756,2}, + {CNST_LIMB(0x20098f7),{CNST_LIMB(0xff6736a5),6,CNST_LIMB(0x1b41d77),CNST_LIMB(0x12d57),CNST_LIMB(0x1aa91d1),CNST_LIMB(0x4bf0ca),CNST_LIMB(0x93f7eb)},758,2}, + {CNST_LIMB(0x20313bb),{CNST_LIMB(0xfcf0f9b6),6,CNST_LIMB(0x79363b),CNST_LIMB(0x1a9d1ed),CNST_LIMB(0x12fe351),CNST_LIMB(0x223b15),CNST_LIMB(0x1c40b0c)},760,2}, + {CNST_LIMB(0x2058ff7),{CNST_LIMB(0xfa7f56bd),6,CNST_LIMB(0x143246e),CNST_LIMB(0x50bb77),CNST_LIMB(0x77cf84),CNST_LIMB(0x192b7bc),CNST_LIMB(0x172152c)},762,2}, + {CNST_LIMB(0x208969d),{CNST_LIMB(0xf78da874),6,CNST_LIMB(0x1ce7557),CNST_LIMB(0x10d44a8),CNST_LIMB(0x44b4d2),CNST_LIMB(0x1e125ce),CNST_LIMB(0x7ba524)},764,2}, + {CNST_LIMB(0x20a31a3),{CNST_LIMB(0xf6014e85),6,CNST_LIMB(0x105c369),CNST_LIMB(0x1ff720c),CNST_LIMB(0x13ac05e),CNST_LIMB(0x1df99eb),CNST_LIMB(0x1ebde3d)},766,2}, + {CNST_LIMB(0x20bcd45),{CNST_LIMB(0xf476cd92),6,CNST_LIMB(0x3cc54f),CNST_LIMB(0x193cef6),CNST_LIMB(0x3fb058),CNST_LIMB(0x912b61),CNST_LIMB(0xa594bb)},768,2}, + {CNST_LIMB(0x20d698f),{CNST_LIMB(0xf2ee173b),6,CNST_LIMB(0x180debc),CNST_LIMB(0x4bcb0e),CNST_LIMB(0x2059038),CNST_LIMB(0x63c38f),CNST_LIMB(0x16e4622)},770,2}, + {CNST_LIMB(0x20f903f),{CNST_LIMB(0xf0e54aae),6,CNST_LIMB(0x76217c),CNST_LIMB(0x122212a),CNST_LIMB(0x115fcab),CNST_LIMB(0xdbfb1b),CNST_LIMB(0x1f8c186)},772,2}, + {CNST_LIMB(0x2132887),{CNST_LIMB(0xed885faa),6,CNST_LIMB(0xcb8723),CNST_LIMB(0xcce10),CNST_LIMB(0xc519a4),CNST_LIMB(0x16924d6),CNST_LIMB(0x46b2e1)},774,2}, + {CNST_LIMB(0x217ab55),{CNST_LIMB(0xe960685e),6,CNST_LIMB(0xb8597e),CNST_LIMB(0xd3f733),CNST_LIMB(0x5efef6),CNST_LIMB(0x72b185),CNST_LIMB(0xabf608)},776,2}, + {CNST_LIMB(0x21b78f3),{CNST_LIMB(0xe5ed338f),6,CNST_LIMB(0x103d525),CNST_LIMB(0xdb2330),CNST_LIMB(0x151ad55),CNST_LIMB(0x2067b60),CNST_LIMB(0xd8a0ed)},778,2}, + {CNST_LIMB(0x22263f7),{CNST_LIMB(0xdfc62ae1),6,CNST_LIMB(0x203882f),CNST_LIMB(0x7dba8),CNST_LIMB(0x7b023b),CNST_LIMB(0xc0ea9e),CNST_LIMB(0x6293aa)},780,2}, + {CNST_LIMB(0x226f72d),{CNST_LIMB(0xdbca4a8f),6,CNST_LIMB(0x20a1142),CNST_LIMB(0x833dd8),CNST_LIMB(0xe8e909),CNST_LIMB(0xe7c4ae),CNST_LIMB(0x201d646)},782,2}, + {CNST_LIMB(0x22b6011),{CNST_LIMB(0xd8032b92),6,CNST_LIMB(0x1b82a),CNST_LIMB(0x1d9cfc8),CNST_LIMB(0x9a06fb),CNST_LIMB(0x4451eb),CNST_LIMB(0x178e019)},784,2}, + {CNST_LIMB(0x22d9645),{CNST_LIMB(0xd623dd31),6,CNST_LIMB(0x12a5277),CNST_LIMB(0x1b82a20),CNST_LIMB(0x21bb9fc),CNST_LIMB(0xc2c179),CNST_LIMB(0x2045e8)},786,2}, + {CNST_LIMB(0x2305b5f),{CNST_LIMB(0xd3d0ed50),6,CNST_LIMB(0x21698f4),CNST_LIMB(0x19a0e5d),CNST_LIMB(0x1f0f05c),CNST_LIMB(0x1554132),CNST_LIMB(0x223ac81)},788,2}, + {CNST_LIMB(0x2335207),{CNST_LIMB(0xd15ae456),6,CNST_LIMB(0xbed4d4),CNST_LIMB(0x262b4f),CNST_LIMB(0x19ec69),CNST_LIMB(0xa71fd5),CNST_LIMB(0x158d7c1)},790,2}, + {CNST_LIMB(0x235eb63),{CNST_LIMB(0xcf37c47e),6,CNST_LIMB(0x1c74287),CNST_LIMB(0x54e875),CNST_LIMB(0x1c14b6),CNST_LIMB(0x19717e2),CNST_LIMB(0x20108e1)},792,2}, + {CNST_LIMB(0x2391535),{CNST_LIMB(0xcca49894),6,CNST_LIMB(0x5b7931),CNST_LIMB(0x2b434f),CNST_LIMB(0x202fc52),CNST_LIMB(0x44ca09),CNST_LIMB(0xdc2fa2)},794,2}, + {CNST_LIMB(0x23ca12b),{CNST_LIMB(0xc9ca3371),6,CNST_LIMB(0x1003ada),CNST_LIMB(0x1a39b69),CNST_LIMB(0x1c6b1b8),CNST_LIMB(0xd07d94),CNST_LIMB(0x22e6ba7)},796,2}, + {CNST_LIMB(0x23ee00b),{CNST_LIMB(0xc8006946),6,CNST_LIMB(0x3b1a),CNST_LIMB(0x2bbe62),CNST_LIMB(0xa09a7f),CNST_LIMB(0x1fc8050),CNST_LIMB(0x451913)},798,2}, + {CNST_LIMB(0x2427085),{CNST_LIMB(0xc53113f7),6,CNST_LIMB(0xac554b),CNST_LIMB(0x1dafbaa),CNST_LIMB(0xc9c336),CNST_LIMB(0x23017b3),CNST_LIMB(0x1f6ad8f)},800,2}, + {CNST_LIMB(0x247b601),{CNST_LIMB(0xc119577b),6,CNST_LIMB(0xa05f90),CNST_LIMB(0x1ba5914),CNST_LIMB(0x8d5684),CNST_LIMB(0x20b7130),CNST_LIMB(0x12fb079)},802,2}, + {CNST_LIMB(0x24abcad),{CNST_LIMB(0xbec864df),6,CNST_LIMB(0x19830fd),CNST_LIMB(0x22b0d68),CNST_LIMB(0x23ece75),CNST_LIMB(0x6fbb38),CNST_LIMB(0x17d4042)},804,2}, + {CNST_LIMB(0x24d331b),{CNST_LIMB(0xbcea58d5),6,CNST_LIMB(0x86d74b),CNST_LIMB(0xa23fd2),CNST_LIMB(0x1e70bce),CNST_LIMB(0x7d1039),CNST_LIMB(0x12f0f39)},806,2}, + {CNST_LIMB(0x24f4991),{CNST_LIMB(0xbb5830d5),6,CNST_LIMB(0x1ee63b2),CNST_LIMB(0x161ab3a),CNST_LIMB(0xa86654),CNST_LIMB(0x5490b6),CNST_LIMB(0x14d7b8c)},808,2}, + {CNST_LIMB(0x2546d77),{CNST_LIMB(0xb7860a25),6,CNST_LIMB(0x20d6455),CNST_LIMB(0xe76276),CNST_LIMB(0x1d4d55b),CNST_LIMB(0x1b2086b),CNST_LIMB(0x235d76)},810,2}, + {CNST_LIMB(0x2571a1b),{CNST_LIMB(0xb58fc2fd),6,CNST_LIMB(0xe9e281),CNST_LIMB(0x619e58),CNST_LIMB(0x1259b65),CNST_LIMB(0xca4b4e),CNST_LIMB(0x260f7f)},812,2}, + {CNST_LIMB(0x258a1fb),{CNST_LIMB(0xb47247c4),6,CNST_LIMB(0x430821),CNST_LIMB(0xd707c3),CNST_LIMB(0xaad74e),CNST_LIMB(0xf903c3),CNST_LIMB(0x1369fe)},814,2}, + {CNST_LIMB(0x25c4695),{CNST_LIMB(0xb1d0b233),6,CNST_LIMB(0x1123924),CNST_LIMB(0x2424544),CNST_LIMB(0x1cfeb3c),CNST_LIMB(0x1d441b6),CNST_LIMB(0xb85f99)},816,2}, + {CNST_LIMB(0x25ec66b),{CNST_LIMB(0xb0073e72),6,CNST_LIMB(0x44adc),CNST_LIMB(0x9894e),CNST_LIMB(0x61f531),CNST_LIMB(0xdfd67a),CNST_LIMB(0x1ee38f9)},818,2}, + {CNST_LIMB(0x26178f7),{CNST_LIMB(0xae1dbede),6,CNST_LIMB(0x14270c3),CNST_LIMB(0x2e371e),CNST_LIMB(0x21745ed),CNST_LIMB(0xda5fb6),CNST_LIMB(0x61308f)},820,2}, + {CNST_LIMB(0x263fb79),{CNST_LIMB(0xac5a2ce1),6,CNST_LIMB(0x35e46d),CNST_LIMB(0xb0c6f9),CNST_LIMB(0x11202a9),CNST_LIMB(0x10d25a7),CNST_LIMB(0x76e6d8)},822,2}, + {CNST_LIMB(0x266e277),{CNST_LIMB(0xaa549413),6,CNST_LIMB(0x1663aba),CNST_LIMB(0x1c78f77),CNST_LIMB(0x224edd6),CNST_LIMB(0x18ec2ba),CNST_LIMB(0x73f824)},824,2}, + {CNST_LIMB(0x269363f),{CNST_LIMB(0xa8b90d0b),6,CNST_LIMB(0x6f89ea),CNST_LIMB(0xc7c87a),CNST_LIMB(0x1976147),CNST_LIMB(0x1ee45a9),CNST_LIMB(0x235619b)},826,2}, + {CNST_LIMB(0x26b277b),{CNST_LIMB(0xa763f637),6,CNST_LIMB(0x20cce8d),CNST_LIMB(0x1a103),CNST_LIMB(0x15a237a),CNST_LIMB(0x2179781),CNST_LIMB(0x1191a93)},828,2}, + {CNST_LIMB(0x26de0e7),{CNST_LIMB(0xa58923b6),6,CNST_LIMB(0xeec141),CNST_LIMB(0x2246e4f),CNST_LIMB(0xf7c495),CNST_LIMB(0xd444bb),CNST_LIMB(0x25de8ea)},830,2}, + {CNST_LIMB(0x272c1c1),{CNST_LIMB(0xa2413425),6,CNST_LIMB(0x1614998),CNST_LIMB(0x1b0a9cb),CNST_LIMB(0x9a1513),CNST_LIMB(0x1c33210),CNST_LIMB(0x1c9d351)},832,2}, + {CNST_LIMB(0x278712b),{CNST_LIMB(0x9e7eb0ca),6,CNST_LIMB(0x18a77b3),CNST_LIMB(0x1ca78ef),CNST_LIMB(0x139eb9d),CNST_LIMB(0x270c29d),CNST_LIMB(0x2bcbd)},834,2}, + {CNST_LIMB(0x27cc5bf),{CNST_LIMB(0x9bad1532),6,CNST_LIMB(0x24935e6),CNST_LIMB(0x1873e88),CNST_LIMB(0x1a6e03f),CNST_LIMB(0x1bb4e6c),CNST_LIMB(0x202cb45)},836,2}, + {CNST_LIMB(0x2802119),{CNST_LIMB(0x99846bf9),6,CNST_LIMB(0xf2d00a),CNST_LIMB(0x917da6),CNST_LIMB(0x9fc6c1),CNST_LIMB(0x4144a2),CNST_LIMB(0x8b1c29)},838,2}, + {CNST_LIMB(0x285df03),{CNST_LIMB(0x95e06aab),6,CNST_LIMB(0x12f03d1),CNST_LIMB(0x15aae93),CNST_LIMB(0x2675e30),CNST_LIMB(0x1a89870),CNST_LIMB(0xb7b763)},840,2}, + {CNST_LIMB(0x28c3e13),{CNST_LIMB(0x91e970ef),6,CNST_LIMB(0x137c094),CNST_LIMB(0x1c55dc8),CNST_LIMB(0x48d2f5),CNST_LIMB(0x18fa705),CNST_LIMB(0x25fced5)},842,2}, + {CNST_LIMB(0x28f0a3f),{CNST_LIMB(0x9032054c),6,CNST_LIMB(0x1fff64),CNST_LIMB(0x1fe92b2),CNST_LIMB(0x814cd6),CNST_LIMB(0x1f915c3),CNST_LIMB(0xa79c19)},844,2}, + {CNST_LIMB(0x291d79b),{CNST_LIMB(0x8e7d9e49),6,CNST_LIMB(0x1999f0f),CNST_LIMB(0x1193990),CNST_LIMB(0xd828b3),CNST_LIMB(0x3e0944),CNST_LIMB(0x1134cfe)},846,2}, + {CNST_LIMB(0x293723b),{CNST_LIMB(0x8d857c49),6,CNST_LIMB(0xfad32f),CNST_LIMB(0x6395b8),CNST_LIMB(0x1114ed6),CNST_LIMB(0x262ada0),CNST_LIMB(0x21a067f)},848,2}, + {CNST_LIMB(0x296a8b3),{CNST_LIMB(0x8b981896),6,CNST_LIMB(0x2536b7a),CNST_LIMB(0x143e503),CNST_LIMB(0x1838909),CNST_LIMB(0x6823c6),CNST_LIMB(0x5a5b0)},850,2}, + {CNST_LIMB(0x29b4b15),{CNST_LIMB(0x88d8c49c),6,CNST_LIMB(0x8d41f6),CNST_LIMB(0x6441a7),CNST_LIMB(0x627b6d),CNST_LIMB(0x1d2e0f9),CNST_LIMB(0x3b9a39)},852,2}, + {CNST_LIMB(0x2a1c439),{CNST_LIMB(0x85128df2),6,CNST_LIMB(0xb4a667),CNST_LIMB(0x9ce228),CNST_LIMB(0x292c766),CNST_LIMB(0x1caaebe),CNST_LIMB(0x28db44c)},854,2}, + {CNST_LIMB(0x2a4d00f),{CNST_LIMB(0x83524212),6,CNST_LIMB(0x231fa60),CNST_LIMB(0x1118b27),CNST_LIMB(0xa7cbc8),CNST_LIMB(0x6be6cb),CNST_LIMB(0x2289199)},856,2}, + {CNST_LIMB(0x2a81187),{CNST_LIMB(0x817791fd),6,CNST_LIMB(0xf96d60),CNST_LIMB(0x103a8f5),CNST_LIMB(0x1c591e4),CNST_LIMB(0x11e9b1f),CNST_LIMB(0x59af3)},858,2}, + {CNST_LIMB(0x2aaec83),{CNST_LIMB(0x7fdaf9e2),6,CNST_LIMB(0x2923b63),CNST_LIMB(0x6f405c),CNST_LIMB(0x17e70ba),CNST_LIMB(0x14b8854),CNST_LIMB(0xa0b78)},860,2}, + {CNST_LIMB(0x2ad6043),{CNST_LIMB(0x7e7b6523),6,CNST_LIMB(0x1a94723),CNST_LIMB(0x27e2ef2),CNST_LIMB(0x212642a),CNST_LIMB(0x2106401),CNST_LIMB(0x209abca)},862,2}, + {CNST_LIMB(0x2afd50b),{CNST_LIMB(0x7d1dbfdb),6,CNST_LIMB(0xbff0eb),CNST_LIMB(0x22c0b58),CNST_LIMB(0x20a8a16),CNST_LIMB(0x3b5b00),CNST_LIMB(0x1eebcda)},864,2}, + {CNST_LIMB(0x2b4245d),{CNST_LIMB(0x7abe3995),6,CNST_LIMB(0x1daa5da),CNST_LIMB(0x416650),CNST_LIMB(0xf459b3),CNST_LIMB(0x28ab2ff),CNST_LIMB(0x12ec62d)},866,2}, + {CNST_LIMB(0x2b9b3e3),{CNST_LIMB(0x77b979a0),6,CNST_LIMB(0x289a689),CNST_LIMB(0x26090df),CNST_LIMB(0x6a5f83),CNST_LIMB(0x6533c9),CNST_LIMB(0x2c1d0c)},868,2}, + {CNST_LIMB(0x2bd6c0f),{CNST_LIMB(0x75bb6f07),6,CNST_LIMB(0x12fbe8d),CNST_LIMB(0x19df067),CNST_LIMB(0xf3b93d),CNST_LIMB(0x9c6a69),CNST_LIMB(0x19a5df3)},870,2}, + {CNST_LIMB(0x2bfe83f),{CNST_LIMB(0x7469a817),6,CNST_LIMB(0x48a11d),CNST_LIMB(0xf7f77a),CNST_LIMB(0x1cac3a6),CNST_LIMB(0x19a3e2c),CNST_LIMB(0x22d2573)},872,2}, + {CNST_LIMB(0x2c443e5),{CNST_LIMB(0x721f09af),6,CNST_LIMB(0x17799b4),CNST_LIMB(0x259ebca),CNST_LIMB(0x5da4e6),CNST_LIMB(0x21730b9),CNST_LIMB(0xb4ca16)},874,2}, + {CNST_LIMB(0x2c7638f),{CNST_LIMB(0x707efd23),6,CNST_LIMB(0x58389c),CNST_LIMB(0xa18e76),CNST_LIMB(0x18318ef),CNST_LIMB(0x1e43fc6),CNST_LIMB(0xeeb056)},876,2}, + {CNST_LIMB(0x2c943e9),{CNST_LIMB(0x6f86d2d5),6,CNST_LIMB(0x274dc2d),CNST_LIMB(0x8e09d),CNST_LIMB(0x96343b),CNST_LIMB(0x1146d8),CNST_LIMB(0x281577b)},878,2}, + {CNST_LIMB(0x2ce1287),{CNST_LIMB(0x6d10f6d5),6,CNST_LIMB(0xbf6a03),CNST_LIMB(0x1ded1f5),CNST_LIMB(0xee798f),CNST_LIMB(0x285e9ca),CNST_LIMB(0x2b6f551)},880,2}, + {CNST_LIMB(0x2d02ae3),{CNST_LIMB(0x6c0112dd),6,CNST_LIMB(0xc14f),CNST_LIMB(0x27fab28),CNST_LIMB(0x13b5b9f),CNST_LIMB(0x55d9df),CNST_LIMB(0xf31e10)},882,2}, + {CNST_LIMB(0x2d49379),{CNST_LIMB(0x69ca1b8f),6,CNST_LIMB(0x1442776),CNST_LIMB(0x20b8c7d),CNST_LIMB(0x8e8a19),CNST_LIMB(0xd11bbc),CNST_LIMB(0x102e860)},884,2}, + {CNST_LIMB(0x2d85e05),{CNST_LIMB(0x67e80640),6,CNST_LIMB(0x2c75043),CNST_LIMB(0x28f15f1),CNST_LIMB(0x2bca8f7),CNST_LIMB(0x18b23d),CNST_LIMB(0x744ae9)},886,2}, + {CNST_LIMB(0x2dd38af),{CNST_LIMB(0x65860e10),6,CNST_LIMB(0x1174b29),CNST_LIMB(0xb19667),CNST_LIMB(0x2081237),CNST_LIMB(0x22dd423),CNST_LIMB(0x2a01ecf)},888,2}, + {CNST_LIMB(0x2e1e2cb),{CNST_LIMB(0x63437add),6,CNST_LIMB(0x25a0a38),CNST_LIMB(0x15e20c5),CNST_LIMB(0x94ff4f),CNST_LIMB(0xd0c798),CNST_LIMB(0x421ce6)},890,2}, + {CNST_LIMB(0x2e40287),{CNST_LIMB(0x623e71b6),6,CNST_LIMB(0x19f2198),CNST_LIMB(0xaecd3e),CNST_LIMB(0x1b7ca1d),CNST_LIMB(0x2452d51),CNST_LIMB(0x27c8d08)},892,2}, + {CNST_LIMB(0x2e622fb),{CNST_LIMB(0x613a8f7d),6,CNST_LIMB(0xe3f9b8),CNST_LIMB(0x2951054),CNST_LIMB(0x18c020f),CNST_LIMB(0xbf1363),CNST_LIMB(0x720d40)},894,2}, + {CNST_LIMB(0x2e8e7e9),{CNST_LIMB(0x5fea6432),6,CNST_LIMB(0x2d92fd1),CNST_LIMB(0x2361346),CNST_LIMB(0x2957acf),CNST_LIMB(0xcdb812),CNST_LIMB(0x23c15c4)},896,2}, + {CNST_LIMB(0x2eb778d),{CNST_LIMB(0x5eb5b56a),6,CNST_LIMB(0x1fa5f15),CNST_LIMB(0x364df6),CNST_LIMB(0x1f8e741),CNST_LIMB(0xc715f1),CNST_LIMB(0x227497f)},898,2}, + {CNST_LIMB(0x2ef1a37),{CNST_LIMB(0x5d03281e),6,CNST_LIMB(0xbe174f),CNST_LIMB(0x2807930),CNST_LIMB(0x28a4ffe),CNST_LIMB(0x74f6c8),CNST_LIMB(0xb409b8)},900,2}, + {CNST_LIMB(0x2f2bf0d),{CNST_LIMB(0x5b53caa4),6,CNST_LIMB(0x273d1a2),CNST_LIMB(0x4bca53),CNST_LIMB(0x319b72),CNST_LIMB(0x5dbf64),CNST_LIMB(0x1fb18a9)},902,2}, + {CNST_LIMB(0x2f66633),{CNST_LIMB(0x59a78486),6,CNST_LIMB(0x139aade),CNST_LIMB(0xd6ed4d),CNST_LIMB(0xd1c371),CNST_LIMB(0x1b4cceb),CNST_LIMB(0x1f352d3)},904,2}, + {CNST_LIMB(0x2fb926b),{CNST_LIMB(0x575011ba),6,CNST_LIMB(0x2786279),CNST_LIMB(0x63a61c),CNST_LIMB(0x292a024),CNST_LIMB(0x2474ed),CNST_LIMB(0x28b981e)},906,2}, + {CNST_LIMB(0x3027efb),{CNST_LIMB(0x543a4312),6,CNST_LIMB(0x2bd6a9),CNST_LIMB(0x1fe7b34),CNST_LIMB(0xcc7066),CNST_LIMB(0x286e11b),CNST_LIMB(0x2fb5169)},908,2}, + {CNST_LIMB(0x3066787),{CNST_LIMB(0x5282ae46),6,CNST_LIMB(0x1e607b4),CNST_LIMB(0x4872bc),CNST_LIMB(0x10c6fdb),CNST_LIMB(0xd4b64c),CNST_LIMB(0xc6ccfe)},910,2}, + {CNST_LIMB(0x309e297),{CNST_LIMB(0x50feeb4d),6,CNST_LIMB(0xc1a674),CNST_LIMB(0x117c481),CNST_LIMB(0x17cdfd3),CNST_LIMB(0x302ff4d),CNST_LIMB(0x2ed0029)},912,2}, + {CNST_LIMB(0x30fffaf),{CNST_LIMB(0x4e5e2cfe),6,CNST_LIMB(0x1d01a43),CNST_LIMB(0x8f2428),CNST_LIMB(0x2821157),CNST_LIMB(0x1302b0e),CNST_LIMB(0xd36302)},914,2}, + {CNST_LIMB(0x314d1db),{CNST_LIMB(0x4c5307c5),6,CNST_LIMB(0x3ff5ff),CNST_LIMB(0x218dfdd),CNST_LIMB(0x953e3b),CNST_LIMB(0xb3c906),CNST_LIMB(0x1990b82)},916,2}, + {CNST_LIMB(0x318fe8d),{CNST_LIMB(0x4a932aa3),6,CNST_LIMB(0x1fe76d6),CNST_LIMB(0x1439865),CNST_LIMB(0xeab112),CNST_LIMB(0x30a2ca7),CNST_LIMB(0xd03dd3)},918,2}, + {CNST_LIMB(0x31a88f7),{CNST_LIMB(0x49ef10fa),6,CNST_LIMB(0x18020e2),CNST_LIMB(0x268d4df),CNST_LIMB(0x491407),CNST_LIMB(0x1cec3f2),CNST_LIMB(0x1b8c9a8)},920,2}, + {CNST_LIMB(0x31e4871),{CNST_LIMB(0x486282ad),6,CNST_LIMB(0x4ccbce),CNST_LIMB(0x3b9456),CNST_LIMB(0x1fc82a8),CNST_LIMB(0x20a0b9b),CNST_LIMB(0x439d2f)},922,2}, + {CNST_LIMB(0x320ef25),{CNST_LIMB(0x474c3d9b),6,CNST_LIMB(0x294554b),CNST_LIMB(0x2b7f71b),CNST_LIMB(0x483ff7),CNST_LIMB(0x108e9e8),CNST_LIMB(0xcfc616)},924,2}, + {CNST_LIMB(0x326062f),{CNST_LIMB(0x453b1f69),6,CNST_LIMB(0xf80b21),CNST_LIMB(0x13a0dc9),CNST_LIMB(0x312d378),CNST_LIMB(0x15eec28),CNST_LIMB(0xc51561)},926,2}, + {CNST_LIMB(0x32d960b),{CNST_LIMB(0x4235435e),6,CNST_LIMB(0x1c11c90),CNST_LIMB(0x14388e6),CNST_LIMB(0x2cda525),CNST_LIMB(0xcffa69),CNST_LIMB(0xa7d07d)},928,2}, + {CNST_LIMB(0x3307c45),{CNST_LIMB(0x41105c17),6,CNST_LIMB(0xd92a70),CNST_LIMB(0x18c23bf),CNST_LIMB(0x2f3587a),CNST_LIMB(0x18510ba),CNST_LIMB(0x25248ba)},930,2}, + {CNST_LIMB(0x334490f),{CNST_LIMB(0x3f939ae8),6,CNST_LIMB(0x2dd745f),CNST_LIMB(0x3cd0f1),CNST_LIMB(0x1c279f5),CNST_LIMB(0x420f9a),CNST_LIMB(0x8ce5a5)},932,2}, + {CNST_LIMB(0x3385163),{CNST_LIMB(0x3e0362c7),6,CNST_LIMB(0x19ee273),CNST_LIMB(0x2d1bf71),CNST_LIMB(0x1df242e),CNST_LIMB(0x192bbec),CNST_LIMB(0x15dfbf0)},934,2}, + {CNST_LIMB(0x33f48a9),{CNST_LIMB(0x3b592ebe),6,CNST_LIMB(0x2b7dc82),CNST_LIMB(0x28bf01d),CNST_LIMB(0x31be9d4),CNST_LIMB(0x2e47af2),CNST_LIMB(0x171a062)},936,2}, + {CNST_LIMB(0x346bc5b),{CNST_LIMB(0x388bed1a),6,CNST_LIMB(0x729c46),CNST_LIMB(0x613964),CNST_LIMB(0x12a1db9),CNST_LIMB(0x2f4d1c1),CNST_LIMB(0x3171c6f)},938,2}, + {CNST_LIMB(0x34d14f3),{CNST_LIMB(0x36331560),6,CNST_LIMB(0x1d0b2e9),CNST_LIMB(0x5c5bee),CNST_LIMB(0x2508ab6),CNST_LIMB(0x1014de0),CNST_LIMB(0x154910)},940,2}, + {CNST_LIMB(0x350b883),{CNST_LIMB(0x34de9b27),6,CNST_LIMB(0xb88099),CNST_LIMB(0x2720572),CNST_LIMB(0x21cb80a),CNST_LIMB(0x2c8c901),CNST_LIMB(0x1ec5560)},942,2}, + {CNST_LIMB(0x35581cd),{CNST_LIMB(0x332331e9),6,CNST_LIMB(0x29d7724),CNST_LIMB(0x15ce94d),CNST_LIMB(0x14a4a3),CNST_LIMB(0x1637c80),CNST_LIMB(0x10b918f)},944,2}, + {CNST_LIMB(0x3578fff),{CNST_LIMB(0x32664bf2),6,CNST_LIMB(0x201404c),CNST_LIMB(0x24f1cae),CNST_LIMB(0x2ac8f31),CNST_LIMB(0x220dd2d),CNST_LIMB(0x2cbd663)},946,2}, + {CNST_LIMB(0x35afe51),{CNST_LIMB(0x312d00d5),6,CNST_LIMB(0xfc7ff4),CNST_LIMB(0x359a6c0),CNST_LIMB(0x12b932a),CNST_LIMB(0x163c6c8),CNST_LIMB(0x100a4a8)},948,2}, + {CNST_LIMB(0x35ee3f7),{CNST_LIMB(0x2fcc2b04),6,CNST_LIMB(0x33336a3),CNST_LIMB(0x1e48d3f),CNST_LIMB(0x24b5ef2),CNST_LIMB(0x10b9242),CNST_LIMB(0x6443a8)},950,2}, + {CNST_LIMB(0x361e059),{CNST_LIMB(0x2ebffae6),6,CNST_LIMB(0x25345ed),CNST_LIMB(0x2cebf06),CNST_LIMB(0x1e64d27),CNST_LIMB(0x242f72d),CNST_LIMB(0x21e027d)},952,2}, + {CNST_LIMB(0x3646837),{CNST_LIMB(0x2dde1dc3),6,CNST_LIMB(0x19577e3),CNST_LIMB(0x118c6c0),CNST_LIMB(0x27408e7),CNST_LIMB(0x2500b7d),CNST_LIMB(0x31fa1b0)},954,2}, + {CNST_LIMB(0x366b5eb),{CNST_LIMB(0x2d11abe2),6,CNST_LIMB(0xe8b427),CNST_LIMB(0x2e740bf),CNST_LIMB(0x388a42),CNST_LIMB(0x243855b),CNST_LIMB(0x3494bec)},956,2}, + {CNST_LIMB(0x369b5bd),{CNST_LIMB(0x2c09172f),6,CNST_LIMB(0x7c1a1),CNST_LIMB(0x21f0421),CNST_LIMB(0x23a3cfd),CNST_LIMB(0x1413873),CNST_LIMB(0x2d46a5f)},958,2}, + {CNST_LIMB(0x36cb707),{CNST_LIMB(0x2b01d1af),6,CNST_LIMB(0x29317fa),CNST_LIMB(0x14fe81c),CNST_LIMB(0x2f7ce77),CNST_LIMB(0x10c1d81),CNST_LIMB(0xbcbd91)},960,2}, + {CNST_LIMB(0x36f07a3),{CNST_LIMB(0x2a383d54),6,CNST_LIMB(0x1e7cae2),CNST_LIMB(0x13d4844),CNST_LIMB(0x15ef906),CNST_LIMB(0x1ee481a),CNST_LIMB(0x326272c)},962,2}, + {CNST_LIMB(0x37281f5),{CNST_LIMB(0x290b613a),6,CNST_LIMB(0xe66f2e),CNST_LIMB(0x1a50d4e),CNST_LIMB(0x27b2f2a),CNST_LIMB(0x2c8e0f5),CNST_LIMB(0x1b86ce)},964,2}, + {CNST_LIMB(0x3785173),{CNST_LIMB(0x2719fa4b),6,CNST_LIMB(0x2b0c635),CNST_LIMB(0x354257e),CNST_LIMB(0x5f40cd),CNST_LIMB(0x7517bc),CNST_LIMB(0x112372c)},966,2}, + {CNST_LIMB(0x37c0c7b),{CNST_LIMB(0x25de0a72),6,CNST_LIMB(0x1a070ed),CNST_LIMB(0x944537),CNST_LIMB(0x1547a05),CNST_LIMB(0x1b383c7),CNST_LIMB(0x292f77f)},968,2}, + {CNST_LIMB(0x381e44d),{CNST_LIMB(0x23f47ad8),6,CNST_LIMB(0x377ca58),CNST_LIMB(0x23d888e),CNST_LIMB(0x218f676),CNST_LIMB(0x28c8577),CNST_LIMB(0x290eb12)},970,2}, + {CNST_LIMB(0x384f007),{CNST_LIMB(0x22f7cddc),6,CNST_LIMB(0x29c7e08),CNST_LIMB(0x1829e9e),CNST_LIMB(0xc5163),CNST_LIMB(0x411a7d),CNST_LIMB(0x27bb4a0)},972,2}, + {CNST_LIMB(0x38784d1),{CNST_LIMB(0x22230128),6,CNST_LIMB(0x1e2a538),CNST_LIMB(0xf9d763),CNST_LIMB(0x16d2cb2),CNST_LIMB(0x2872397),CNST_LIMB(0x5fa4aa)},974,2}, + {CNST_LIMB(0x38b0b53),{CNST_LIMB(0x210251a0),6,CNST_LIMB(0xe4d0a8),CNST_LIMB(0x2449e23),CNST_LIMB(0xa9e498),CNST_LIMB(0xc34ce7),CNST_LIMB(0x21d1bf5)},976,2}, + {CNST_LIMB(0x38e93e5),{CNST_LIMB(0x1fe3376b),6,CNST_LIMB(0x374fb7d),CNST_LIMB(0x1207f1a),CNST_LIMB(0x2743dc1),CNST_LIMB(0x2758558),CNST_LIMB(0x1677369)},978,2}, + {CNST_LIMB(0x393c565),{CNST_LIMB(0x1e414438),6,CNST_LIMB(0x20440fd),CNST_LIMB(0x1b201da),CNST_LIMB(0xe80b49),CNST_LIMB(0x1be94b0),CNST_LIMB(0x2cea1c8)},980,2}, + {CNST_LIMB(0x3965fc3),{CNST_LIMB(0x1d718fbc),6,CNST_LIMB(0x14b70eb),CNST_LIMB(0x2a0db57),CNST_LIMB(0x242c769),CNST_LIMB(0x1d45ed8),CNST_LIMB(0x2f69047)},982,2}, + {CNST_LIMB(0x39e341d),{CNST_LIMB(0x1b07d8d6),6,CNST_LIMB(0x2bdc012),CNST_LIMB(0x9cd089),CNST_LIMB(0x1eb38ba),CNST_LIMB(0x261e54d),CNST_LIMB(0xa7269d)},984,2}, + {CNST_LIMB(0x3a51c87),{CNST_LIMB(0x18ef73f8),6,CNST_LIMB(0xda3316),CNST_LIMB(0x22bd1f6),CNST_LIMB(0x3690f3f),CNST_LIMB(0x15d87a1),CNST_LIMB(0x26dec6b)},986,2}, + {CNST_LIMB(0x3a8b1b5),{CNST_LIMB(0x17dc5ed7),6,CNST_LIMB(0x3881a37),CNST_LIMB(0x270b2de),CNST_LIMB(0x1d4c82),CNST_LIMB(0x6d08c6),CNST_LIMB(0x107e7ba)},988,2}, + {CNST_LIMB(0x3aeae5f),{CNST_LIMB(0x16155b63),6,CNST_LIMB(0x1eb0065),CNST_LIMB(0x2f6275f),CNST_LIMB(0xdbdd23),CNST_LIMB(0x317d7e8),CNST_LIMB(0xff5b75)},990,2}, + {CNST_LIMB(0x3b24885),{CNST_LIMB(0x15065db5),6,CNST_LIMB(0xf27427),CNST_LIMB(0x280f69),CNST_LIMB(0x3393578),CNST_LIMB(0x2a2f2ce),CNST_LIMB(0x418ee)},992,2}, + {CNST_LIMB(0x3b3b9cd),{CNST_LIMB(0x149a6c60),6,CNST_LIMB(0x8eebbf),CNST_LIMB(0x1ede4fd),CNST_LIMB(0x24b2152),CNST_LIMB(0x1f52540),CNST_LIMB(0x92b2ec)},994,2}, + {CNST_LIMB(0x3b943f7),{CNST_LIMB(0x12feec60),6,CNST_LIMB(0x2c9f264),CNST_LIMB(0x7719b0),CNST_LIMB(0x13a219d),CNST_LIMB(0x161553c),CNST_LIMB(0x187e2d2)},996,2}, + {CNST_LIMB(0x3bdda99),{CNST_LIMB(0x11adb0f5),6,CNST_LIMB(0x191ef5c),CNST_LIMB(0x3455274),CNST_LIMB(0xaaf362),CNST_LIMB(0x274be9f),CNST_LIMB(0x2c2c8d9)},998,2}, + {CNST_LIMB(0x3c0c1fd),{CNST_LIMB(0x10d9ee69),6,CNST_LIMB(0xcc78cc),CNST_LIMB(0x173072c),CNST_LIMB(0x1d8ad05),CNST_LIMB(0xf35421),CNST_LIMB(0x7f27fd)},1000,2}, + {CNST_LIMB(0x3c464c3),{CNST_LIMB(0xfd2978d),6,CNST_LIMB(0x399a0f7),CNST_LIMB(0x18024eb),CNST_LIMB(0x31c2569),CNST_LIMB(0xeaa62),CNST_LIMB(0xead45c)},1002,2} +#endif diff --git a/repos/libports/include/spec/64bit/gmp/fac_table.h b/repos/libports/include/spec/64bit/gmp/fac_table.h new file mode 100644 index 000000000..670834817 --- /dev/null +++ b/repos/libports/include/spec/64bit/gmp/fac_table.h @@ -0,0 +1,49 @@ +/* This file is automatically generated by gen-fac.c */ + +#if GMP_NUMB_BITS != 64 +Error , error this data is for 64 GMP_NUMB_BITS only +#endif +/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x2),CNST_LIMB(0x6),CNST_LIMB(0x18),CNST_LIMB(0x78),CNST_LIMB(0x2d0),CNST_LIMB(0x13b0),CNST_LIMB(0x9d80),CNST_LIMB(0x58980),CNST_LIMB(0x375f00),CNST_LIMB(0x2611500),CNST_LIMB(0x1c8cfc00),CNST_LIMB(0x17328cc00),CNST_LIMB(0x144c3b2800),CNST_LIMB(0x13077775800),CNST_LIMB(0x130777758000),CNST_LIMB(0x1437eeecd8000),CNST_LIMB(0x16beecca730000),CNST_LIMB(0x1b02b9306890000),CNST_LIMB(0x21c3677c82b40000) + +/* This table is 0!,1!,2!/2,3!/2,...,n!/2^sn where n!/2^sn is an */ +/* odd integer for each n, and n!/2^sn has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_ODD_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x3),CNST_LIMB(0x3),CNST_LIMB(0xf),CNST_LIMB(0x2d),CNST_LIMB(0x13b),CNST_LIMB(0x13b),CNST_LIMB(0xb13),CNST_LIMB(0x375f),CNST_LIMB(0x26115),CNST_LIMB(0x7233f),CNST_LIMB(0x5cca33),CNST_LIMB(0x2898765),CNST_LIMB(0x260eeeeb),CNST_LIMB(0x260eeeeb),CNST_LIMB(0x286fddd9b),CNST_LIMB(0x16beecca73),CNST_LIMB(0x1b02b930689),CNST_LIMB(0x870d9df20ad),CNST_LIMB(0xb141df4dae31),CNST_LIMB(0x79dd498567c1b),CNST_LIMB(0xaf2e19afc5266d),CNST_LIMB(0x20d8a4d0f4f7347),CNST_LIMB(0x335281867ec241ef) +#define ODD_FACTORIAL_TABLE_MAX CNST_LIMB(0x335281867ec241ef) +#define ODD_FACTORIAL_TABLE_LIMIT (25) + +/* Previous table, continued, values modulo 2^GMP_NUMB_BITS */ +#define ONE_LIMB_ODD_FACTORIAL_EXTTABLE CNST_LIMB(0x9b3093d46fdd5923),CNST_LIMB(0x5e1f9767cc5866b1),CNST_LIMB(0x92dd23d6966aced7),CNST_LIMB(0xa30d0f4f0a196e5b),CNST_LIMB(0x8dc3e5a1977d7755),CNST_LIMB(0x2ab8ce915831734b),CNST_LIMB(0x2ab8ce915831734b),CNST_LIMB(0x81d2a0bc5e5fdcab),CNST_LIMB(0x9efcac82445da75b),CNST_LIMB(0xbc8b95cf58cde171),CNST_LIMB(0xa0e8444a1f3cecf9),CNST_LIMB(0x4191deb683ce3ffd),CNST_LIMB(0xddd3878bc84ebfc7),CNST_LIMB(0xcb39a64b83ff3751),CNST_LIMB(0xf8203f7993fc1495),CNST_LIMB(0xbd2a2a78b35f4bdd),CNST_LIMB(0x84757be6b6d13921),CNST_LIMB(0x3fbbcfc0b524988b),CNST_LIMB(0xbd11ed47c8928df9),CNST_LIMB(0x3c26b59e41c2f4c5),CNST_LIMB(0x677a5137e883fdb3),CNST_LIMB(0xff74e943b03b93dd),CNST_LIMB(0xfe5ebbcb10b2bb97),CNST_LIMB(0xb021f1de3235e7e7),CNST_LIMB(0x33509eb2e743a58f),CNST_LIMB(0x390f9da41279fb7d),CNST_LIMB(0xe5cb0154f031c559),CNST_LIMB(0x93074695ba4ddb6d),CNST_LIMB(0x81c471caa636247f),CNST_LIMB(0xe1347289b5a1d749),CNST_LIMB(0x286f21c3f76ce2ff),CNST_LIMB(0xbe84a2173e8ac7),CNST_LIMB(0x1595065ca215b88b),CNST_LIMB(0xf95877595b018809),CNST_LIMB(0x9c2efe3c5516f887),CNST_LIMB(0x373294604679382b),CNST_LIMB(0xaf1ff7a888adcd35),CNST_LIMB(0x18ddf279a2c5800b),CNST_LIMB(0x18ddf279a2c5800b),CNST_LIMB(0x505a90e2542582cb),CNST_LIMB(0x5bacad2cd8d5dc2b),CNST_LIMB(0xfe3152bcbff89f41) +#define ODD_FACTORIAL_EXTTABLE_LIMIT (67) + +/* This table is 1!!,3!!,...,(2n+1)!! where (2n+1)!! has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x3),CNST_LIMB(0xf),CNST_LIMB(0x69),CNST_LIMB(0x3b1),CNST_LIMB(0x289b),CNST_LIMB(0x20fdf),CNST_LIMB(0x1eee11),CNST_LIMB(0x20dcf21),CNST_LIMB(0x27065f73),CNST_LIMB(0x33385d46f),CNST_LIMB(0x49a10615f9),CNST_LIMB(0x730b9982551),CNST_LIMB(0xc223930bef8b),CNST_LIMB(0x15fe07a85a22bf),CNST_LIMB(0x2a9c2ed62ea3521),CNST_LIMB(0x57e22099c030d941) +#define ODD_DOUBLEFACTORIAL_TABLE_MAX CNST_LIMB(0x57e22099c030d941) +#define ODD_DOUBLEFACTORIAL_TABLE_LIMIT (33) + +/* This table x_1, x_2,... contains values s.t. x_n^n has <= GMP_NUMB_BITS bits */ +#define NTH_ROOT_NUMB_MASK_TABLE (GMP_NUMB_MASK),CNST_LIMB(0xffffffff),CNST_LIMB(0x285145),CNST_LIMB(0xffff),CNST_LIMB(0x1bdb),CNST_LIMB(0x659),CNST_LIMB(0x235),CNST_LIMB(0xff) + +/* This table contains inverses of odd factorials, modulo 2^GMP_NUMB_BITS */ + +/* It begins with (2!/2)^-1=1 */ +#define ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE CNST_LIMB(0x1),CNST_LIMB(0xaaaaaaaaaaaaaaab),CNST_LIMB(0xaaaaaaaaaaaaaaab),CNST_LIMB(0xeeeeeeeeeeeeeeef),CNST_LIMB(0x4fa4fa4fa4fa4fa5),CNST_LIMB(0x2ff2ff2ff2ff2ff3),CNST_LIMB(0x2ff2ff2ff2ff2ff3),CNST_LIMB(0x938cc70553e3771b),CNST_LIMB(0xb71c27cddd93e49f),CNST_LIMB(0xb38e3229fcdee63d),CNST_LIMB(0xe684bb63544a4cbf),CNST_LIMB(0xc2f684917ca340fb),CNST_LIMB(0xf747c9cba417526d),CNST_LIMB(0xbb26eb51d7bd49c3),CNST_LIMB(0xbb26eb51d7bd49c3),CNST_LIMB(0xb0a7efb985294093),CNST_LIMB(0xbe4b8c69f259eabb),CNST_LIMB(0x6854d17ed6dc4fb9),CNST_LIMB(0xe1aa904c915f4325),CNST_LIMB(0x3b8206df131cead1),CNST_LIMB(0x79c6009fea76fe13),CNST_LIMB(0xd8c5d381633cd365),CNST_LIMB(0x4841f12b21144677),CNST_LIMB(0x4a91ff68200b0d0f),CNST_LIMB(0x8f9513a58c4f9e8b),CNST_LIMB(0x2b3e690621a42251),CNST_LIMB(0x4f520f00e03c04e7),CNST_LIMB(0x2edf84ee600211d3),CNST_LIMB(0xadcaa2764aaacdfd),CNST_LIMB(0x161f4f9033f4fe63),CNST_LIMB(0x161f4f9033f4fe63),CNST_LIMB(0xbada2932ea4d3e03),CNST_LIMB(0xcec189f3efaa30d3),CNST_LIMB(0xf7475bb68330bf91),CNST_LIMB(0x37eb7bf7d5b01549),CNST_LIMB(0x46b35660a4e91555),CNST_LIMB(0xa567c12d81f151f7),CNST_LIMB(0x4c724007bb2071b1),CNST_LIMB(0xf4a0cce58a016bd),CNST_LIMB(0xfa21068e66106475),CNST_LIMB(0x244ab72b5a318ae1),CNST_LIMB(0x366ce67e080d0f23),CNST_LIMB(0xd666fdae5dd2a449),CNST_LIMB(0xd740ddd0acc06a0d),CNST_LIMB(0xb050bbbb28e6f97b),CNST_LIMB(0x70b003fe890a5c75),CNST_LIMB(0xd03aabff83037427),CNST_LIMB(0x13ec4ca72c783bd7),CNST_LIMB(0x90282c06afdbd96f),CNST_LIMB(0x4414ddb9db4a95d5),CNST_LIMB(0xa2c68735ae6832e9),CNST_LIMB(0xbf72d71455676665),CNST_LIMB(0xa8469fab6b759b7f),CNST_LIMB(0xc1e55b56e606caf9),CNST_LIMB(0x40455630fc4a1cff),CNST_LIMB(0x120a7b0046d16f7),CNST_LIMB(0xa7c3553b08faef23),CNST_LIMB(0x9f0bfd1b08d48639),CNST_LIMB(0xa433ffce9a304d37),CNST_LIMB(0xa22ad1d53915c683),CNST_LIMB(0xcb6cbc723ba5dd1d),CNST_LIMB(0x547fb1b8ab9d0ba3),CNST_LIMB(0x547fb1b8ab9d0ba3),CNST_LIMB(0x8f15a826498852e3) + +/* This table contains 2n-popc(2n) for small n */ + +/* It begins with 2-1=1 (n=1) */ +#define TABLE_2N_MINUS_POPC_2N 1,3,4,7,8,10,11,15,16,18,19,22,23,25,26,31,32,34,35,38,39,41,42,46,47,49,50,53,54,56,57,63,64,66,67,70,71,73,74,78 +#define TABLE_LIMIT_2N_MINUS_POPC_2N 81 +#define ODD_CENTRAL_BINOMIAL_OFFSET (13) + +/* This table contains binomial(2k,k)/2^t */ + +/* It begins with ODD_CENTRAL_BINOMIAL_TABLE_MIN */ +#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE CNST_LIMB(0x13d66b),CNST_LIMB(0x4c842f),CNST_LIMB(0x93ee7d),CNST_LIMB(0x11e9e123),CNST_LIMB(0x22c60053),CNST_LIMB(0x873ae4d1),CNST_LIMB(0x10757bd97),CNST_LIMB(0x80612c6cd),CNST_LIMB(0xfaa556bc1),CNST_LIMB(0x3d3cc24821),CNST_LIMB(0x77cfeb6bbb),CNST_LIMB(0x7550ebd97c7),CNST_LIMB(0xe5f08695caf),CNST_LIMB(0x386120ffce11),CNST_LIMB(0x6eabb28dd6df),CNST_LIMB(0x3658e31c82a8f),CNST_LIMB(0x6ad2050312783),CNST_LIMB(0x1a42902a5af0bf),CNST_LIMB(0x33ac44f881661d),CNST_LIMB(0xcb764f927d82123),CNST_LIMB(0x190c23fa46b93983),CNST_LIMB(0x62b7609e25caf1b9),CNST_LIMB(0xc29cb72925ef2cff) +#define ODD_CENTRAL_BINOMIAL_TABLE_LIMIT (35) + +/* This table contains the inverses of elements in the previous table. */ +#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE CNST_LIMB(0x61e5bd199bb12643),CNST_LIMB(0x78321494dc8342cf),CNST_LIMB(0x4fd348704ebf7ad5),CNST_LIMB(0x7e722ba086ab568b),CNST_LIMB(0xa5fcc124265843db),CNST_LIMB(0x89c4a6b18633f431),CNST_LIMB(0x4daa2c15f8ce9227),CNST_LIMB(0x801c618ca9be9605),CNST_LIMB(0x32dc192f948a441),CNST_LIMB(0xd02b90c2bf3be1),CNST_LIMB(0xd897e8c1749aa173),CNST_LIMB(0x54a234fc01fef9f7),CNST_LIMB(0x83ff2ab4d1ff7a4f),CNST_LIMB(0xa427f1c9b304e2f1),CNST_LIMB(0x9c14595d1793651f),CNST_LIMB(0x883a71c607a7b46f),CNST_LIMB(0xd089863c54bc9f2b),CNST_LIMB(0x9022f6bce5d07f3f),CNST_LIMB(0xbec207e218768c35),CNST_LIMB(0x9d70cb4cbb4f168b),CNST_LIMB(0x3c3d3403828a9d2b),CNST_LIMB(0x7672df58c56bc489),CNST_LIMB(0x1e66ca55d727d2ff) + +/* This table contains the values t in the formula binomial(2k,k)/2^t */ +#define CENTRAL_BINOMIAL_2FAC_TABLE 3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3 diff --git a/repos/libports/include/spec/64bit/gmp/fac_ui.h b/repos/libports/include/spec/64bit/gmp/fac_ui.h deleted file mode 100644 index dd814c7e4..000000000 --- a/repos/libports/include/spec/64bit/gmp/fac_ui.h +++ /dev/null @@ -1,19 +0,0 @@ -/* This file is automatically generated by gen-fac_ui.c */ - -#if GMP_NUMB_BITS != 64 -Error , error this data is for 64 GMP_NUMB_BITS only -#endif -#if GMP_LIMB_BITS != 64 -Error , error this data is for 64 GMP_LIMB_BITS only -#endif -/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */ -#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x2),CNST_LIMB(0x6),CNST_LIMB(0x18),CNST_LIMB(0x78),CNST_LIMB(0x2d0),CNST_LIMB(0x13b0),CNST_LIMB(0x9d80),CNST_LIMB(0x58980),CNST_LIMB(0x375f00),CNST_LIMB(0x2611500),CNST_LIMB(0x1c8cfc00),CNST_LIMB(0x17328cc00),CNST_LIMB(0x144c3b2800),CNST_LIMB(0x13077775800),CNST_LIMB(0x130777758000),CNST_LIMB(0x1437eeecd8000),CNST_LIMB(0x16beecca730000),CNST_LIMB(0x1b02b9306890000),CNST_LIMB(0x21c3677c82b40000) - -/* is 2^(GMP_LIMB_BITS+1)/exp(1) */ -#define FAC2OVERE CNST_LIMB(0xbc5c254b96be9524) - -/* FACMULn is largest odd x such that x*(x+2)*...*(x+2(n-1))<=2^GMP_NUMB_BITS-1 */ - -#define FACMUL2 CNST_LIMB(0xffffffff) -#define FACMUL3 CNST_LIMB(0x285143) -#define FACMUL4 CNST_LIMB(0xfffd) diff --git a/repos/libports/include/spec/64bit/gmp/gmp.h b/repos/libports/include/spec/64bit/gmp/gmp.h index 1c5adce3f..5f5ca9601 100644 --- a/repos/libports/include/spec/64bit/gmp/gmp.h +++ b/repos/libports/include/spec/64bit/gmp/gmp.h @@ -1,22 +1,32 @@ /* Definitions for GNU multiple precision functions. -*- mode: c -*- -Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, -2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +Copyright 1991, 1993-1997, 1999-2016 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 3 of the License, or (at your -option) any later version. +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. -You should have received a copy of the GNU Lesser General Public License -along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ #ifndef __GMP_H__ @@ -28,7 +38,6 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ /* Instantiated by configure. */ #if ! defined (__GMP_WITHIN_CONFIGURE) -#define __GMP_BITS_PER_MP_LIMB 64 #define __GMP_HAVE_HOST_CPU_FAMILY_power 0 #define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0 #define GMP_LIMB_BITS 64 @@ -40,19 +49,11 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #define GMP_NAIL_MASK (~ GMP_NUMB_MASK) -/* The following (everything under ifndef __GNU_MP__) must be identical in - gmp.h and mp.h to allow both to be included in an application or during - the library build. */ #ifndef __GNU_MP__ -#define __GNU_MP__ 4 +#define __GNU_MP__ 6 -#define __need_size_t /* tell gcc stddef.h we only want size_t */ -#if defined (__cplusplus) -#include <cstddef> /* for size_t */ -#else #include <stddef.h> /* for size_t */ -#endif -#undef __need_size_t +#include <limits.h> /* Instantiated by configure. */ #if ! defined (__GMP_WITHIN_CONFIGURE) @@ -61,57 +62,6 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #endif -/* __STDC__ - some ANSI compilers define this only to 0, hence the use of - "defined" and not "__STDC__-0". In particular Sun workshop C 5.0 - sets __STDC__ to 0, but requires "##" for token pasting. - - _AIX - gnu ansidecl.h asserts that all known AIX compilers are ANSI but - don't always define __STDC__. - - __DECC - current versions of DEC C (5.9 for instance) for alpha are ANSI, - but don't define __STDC__ in their default mode. Don't know if old - versions might have been K&R, but let's not worry about that unless - someone is still using one. - - _mips - gnu ansidecl.h says the RISC/OS MIPS compiler is ANSI in SVR4 - mode, but doesn't define __STDC__. - - _MSC_VER - Microsoft C is ANSI, but __STDC__ is undefined unless the /Za - option is given (in which case it's 1). - - _WIN32 - tested for by gnu ansidecl.h, no doubt on the assumption that - all w32 compilers are ansi. - - Note: This same set of tests is used by gen-psqr.c and - demos/expr/expr-impl.h, so if anything needs adding, then be sure to - update those too. */ - -#if defined (__STDC__) \ - || defined (__cplusplus) \ - || defined (_AIX) \ - || defined (__DECC) \ - || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ - || defined (_MSC_VER) \ - || defined (_WIN32) -#define __GMP_HAVE_CONST 1 -#define __GMP_HAVE_PROTOTYPES 1 -#define __GMP_HAVE_TOKEN_PASTE 1 -#else -#define __GMP_HAVE_CONST 0 -#define __GMP_HAVE_PROTOTYPES 0 -#define __GMP_HAVE_TOKEN_PASTE 0 -#endif - - -#if __GMP_HAVE_CONST -#define __gmp_const const -#define __gmp_signed signed -#else -#define __gmp_const -#define __gmp_signed -#endif - - /* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in all other circumstances. @@ -124,9 +74,6 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ indicates when building libgmpxx, and in that case libgmpxx functions are exports, but libgmp functions which might get called are imports. - libmp.la uses __GMP_DECLSPEC, just as if it were libgmp.la. libgmp and - libmp don't call each other, so there's no conflict or confusion. - Libtool DLL_EXPORT define is not used. There's no attempt to support GMP built both static and DLL. Doing so @@ -170,7 +117,7 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #endif #if __GMP_LIBGMP_DLL -#if __GMP_WITHIN_GMP +#ifdef __GMP_WITHIN_GMP /* compiling to go into a DLL libgmp */ #define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT #else @@ -195,6 +142,7 @@ typedef unsigned long int mp_limb_t; typedef long int mp_limb_signed_t; #endif #endif +typedef unsigned long int mp_bitcnt_t; /* For reference, note that the name __mpz_struct gets into C++ mangled function names, which means although the "__" suggests an internal, we @@ -216,7 +164,7 @@ typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ typedef __mpz_struct mpz_t[1]; typedef mp_limb_t * mp_ptr; -typedef __gmp_const mp_limb_t * mp_srcptr; +typedef const mp_limb_t * mp_srcptr; #if defined (_CRAY) && ! defined (_CRAYMPP) /* plain `int' is much faster (48 bits) */ #define __GMP_MP_SIZE_T_INT 1 @@ -273,18 +221,16 @@ typedef __gmp_randstate_struct gmp_randstate_t[1]; /* Types for function declarations in gmp files. */ /* ??? Should not pollute user name space with these ??? */ -typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef const __mpz_struct *mpz_srcptr; typedef __mpz_struct *mpz_ptr; -typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef const __mpf_struct *mpf_srcptr; typedef __mpf_struct *mpf_ptr; -typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef const __mpq_struct *mpq_srcptr; typedef __mpq_struct *mpq_ptr; -/* This is not wanted in mp.h, so put it outside the __GNU_MP__ common - section. */ #if __GMP_LIBGMP_DLL -#if __GMP_WITHIN_GMPXX +#ifdef __GMP_WITHIN_GMPXX /* compiling to go into a DLL libgmpxx */ #define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT #else @@ -297,18 +243,8 @@ typedef __mpq_struct *mpq_ptr; #endif -#if __GMP_HAVE_PROTOTYPES -#define __GMP_PROTO(x) x -#else -#define __GMP_PROTO(x) () -#endif - #ifndef __MPN -#if __GMP_HAVE_TOKEN_PASTE #define __MPN(x) __gmpn_##x -#else -#define __MPN(x) __gmpn_/**/x -#endif #endif /* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, @@ -326,7 +262,9 @@ typedef __mpq_struct *mpq_ptr; || defined (__STDIO__) /* Apple MPW MrC */ \ || defined (_MSL_STDIO_H) /* Metrowerks */ \ || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ - || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \ + || defined (__STDIO_LOADED) /* VMS */ \ + || defined (__DEFINED_FILE) /* musl */ #define _GMP_H_HAVE_FILE 1 #endif @@ -338,16 +276,14 @@ typedef __mpq_struct *mpq_ptr; #define _GMP_H_HAVE_OBSTACK 1 #endif -/* The prototypes for gmp_vprintf etc are provided only if va_list is - available, via an application having included <stdarg.h> or <varargs.h>. - Usually va_list is a typedef so can't be tested directly, but C99 - specifies that va_start is a macro (and it was normally a macro on past - systems too), so look for that. +/* The prototypes for gmp_vprintf etc are provided only if va_list is defined, + via an application having included <stdarg.h>. Usually va_list is a typedef + so can't be tested directly, but C99 specifies that va_start is a macro. <stdio.h> will define some sort of va_list for vprintf and vfprintf, but let's not bother trying to use that since it's not standard and since application uses for gmp_vprintf etc will almost certainly require the - whole <stdarg.h> or <varargs.h> anyway. */ + whole <stdarg.h> anyway. */ #ifdef va_start #define _GMP_H_HAVE_VA_LIST 1 @@ -421,7 +357,8 @@ typedef __mpq_struct *mpq_ptr; GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 inline semantics, unless -fgnu89-inline is used. */ #ifdef __GNUC__ -#if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2) +#if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2) \ + || (defined __GNUC_GNU_INLINE__ && defined __cplusplus) #define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__)) #else #define __GMP_EXTERN_INLINE extern __inline__ @@ -460,13 +397,13 @@ typedef __mpq_struct *mpq_ptr; #define __GMP_EXTERN_INLINE __inline #endif -/* Recent enough Sun C compilers accept "extern inline" */ +/* Recent enough Sun C compilers want "inline" */ #if defined (__SUNPRO_C) && __SUNPRO_C >= 0x560 \ && ! defined (__GMP_EXTERN_INLINE) -#define __GMP_EXTERN_INLINE extern inline +#define __GMP_EXTERN_INLINE inline #endif -/* Somewhat older Sun C compilers accept "static inline" */ +/* Somewhat older Sun C compilers want "static inline" */ #if defined (__SUNPRO_C) && __SUNPRO_C >= 0x540 \ && ! defined (__GMP_EXTERN_INLINE) #define __GMP_EXTERN_INLINE static inline @@ -505,12 +442,6 @@ typedef __mpq_struct *mpq_ptr; #define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) #define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) -/* __GMP_USHRT_MAX is not "~ (unsigned short) 0" because short is promoted - to int by "~". */ -#define __GMP_UINT_MAX (~ (unsigned) 0) -#define __GMP_ULONG_MAX (~ (unsigned long) 0) -#define __GMP_USHRT_MAX ((unsigned short) ~0) - /* __builtin_expect is in gcc 3.0, and not in 2.95. */ #if __GMP_GNUC_PREREQ (3,0) @@ -528,7 +459,7 @@ typedef __mpq_struct *mpq_ptr; #endif -/* Allow direct user access to numerator and denominator of a mpq_t object. */ +/* Allow direct user access to numerator and denominator of an mpq_t object. */ #define mpq_numref(Q) (&((Q)->_mp_num)) #define mpq_denref(Q) (&((Q)->_mp_den)) @@ -539,116 +470,114 @@ using std::FILE; #endif #define mp_set_memory_functions __gmp_set_memory_functions -__GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), +__GMP_DECLSPEC void mp_set_memory_functions (void *(*) (size_t), void *(*) (void *, size_t, size_t), - void (*) (void *, size_t))) __GMP_NOTHROW; + void (*) (void *, size_t)) __GMP_NOTHROW; #define mp_get_memory_functions __gmp_get_memory_functions -__GMP_DECLSPEC void mp_get_memory_functions __GMP_PROTO ((void *(**) (size_t), - void *(**) (void *, size_t, size_t), - void (**) (void *, size_t))) __GMP_NOTHROW; +__GMP_DECLSPEC void mp_get_memory_functions (void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t)) __GMP_NOTHROW; #define mp_bits_per_limb __gmp_bits_per_limb -__GMP_DECLSPEC extern __gmp_const int mp_bits_per_limb; +__GMP_DECLSPEC extern const int mp_bits_per_limb; #define gmp_errno __gmp_errno __GMP_DECLSPEC extern int gmp_errno; #define gmp_version __gmp_version -__GMP_DECLSPEC extern __gmp_const char * __gmp_const gmp_version; +__GMP_DECLSPEC extern const char * const gmp_version; /**************** Random number routines. ****************/ /* obsolete */ #define gmp_randinit __gmp_randinit -__GMP_DECLSPEC void gmp_randinit __GMP_PROTO ((gmp_randstate_t, gmp_randalg_t, ...)); +__GMP_DECLSPEC void gmp_randinit (gmp_randstate_t, gmp_randalg_t, ...); #define gmp_randinit_default __gmp_randinit_default -__GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); +__GMP_DECLSPEC void gmp_randinit_default (gmp_randstate_t); #define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp -__GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, - mpz_srcptr, unsigned long int, - unsigned long int)); +__GMP_DECLSPEC void gmp_randinit_lc_2exp (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t); #define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size -__GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, unsigned long)); +__GMP_DECLSPEC int gmp_randinit_lc_2exp_size (gmp_randstate_t, mp_bitcnt_t); #define gmp_randinit_mt __gmp_randinit_mt -__GMP_DECLSPEC void gmp_randinit_mt __GMP_PROTO ((gmp_randstate_t)); +__GMP_DECLSPEC void gmp_randinit_mt (gmp_randstate_t); #define gmp_randinit_set __gmp_randinit_set -__GMP_DECLSPEC void gmp_randinit_set __GMP_PROTO ((gmp_randstate_t, __gmp_const __gmp_randstate_struct *)); +__GMP_DECLSPEC void gmp_randinit_set (gmp_randstate_t, const __gmp_randstate_struct *); #define gmp_randseed __gmp_randseed -__GMP_DECLSPEC void gmp_randseed __GMP_PROTO ((gmp_randstate_t, mpz_srcptr)); +__GMP_DECLSPEC void gmp_randseed (gmp_randstate_t, mpz_srcptr); #define gmp_randseed_ui __gmp_randseed_ui -__GMP_DECLSPEC void gmp_randseed_ui __GMP_PROTO ((gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void gmp_randseed_ui (gmp_randstate_t, unsigned long int); #define gmp_randclear __gmp_randclear -__GMP_DECLSPEC void gmp_randclear __GMP_PROTO ((gmp_randstate_t)); +__GMP_DECLSPEC void gmp_randclear (gmp_randstate_t); #define gmp_urandomb_ui __gmp_urandomb_ui -__GMP_DECLSPEC unsigned long gmp_urandomb_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); +__GMP_DECLSPEC unsigned long gmp_urandomb_ui (gmp_randstate_t, unsigned long); #define gmp_urandomm_ui __gmp_urandomm_ui -__GMP_DECLSPEC unsigned long gmp_urandomm_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); +__GMP_DECLSPEC unsigned long gmp_urandomm_ui (gmp_randstate_t, unsigned long); /**************** Formatted output routines. ****************/ #define gmp_asprintf __gmp_asprintf -__GMP_DECLSPEC int gmp_asprintf __GMP_PROTO ((char **, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_asprintf (char **, const char *, ...); #define gmp_fprintf __gmp_fprintf #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fprintf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_fprintf (FILE *, const char *, ...); #endif #define gmp_obstack_printf __gmp_obstack_printf #if defined (_GMP_H_HAVE_OBSTACK) -__GMP_DECLSPEC int gmp_obstack_printf __GMP_PROTO ((struct obstack *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_obstack_printf (struct obstack *, const char *, ...); #endif #define gmp_obstack_vprintf __gmp_obstack_vprintf #if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_obstack_vprintf __GMP_PROTO ((struct obstack *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_obstack_vprintf (struct obstack *, const char *, va_list); #endif #define gmp_printf __gmp_printf -__GMP_DECLSPEC int gmp_printf __GMP_PROTO ((__gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_printf (const char *, ...); #define gmp_snprintf __gmp_snprintf -__GMP_DECLSPEC int gmp_snprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_snprintf (char *, size_t, const char *, ...); #define gmp_sprintf __gmp_sprintf -__GMP_DECLSPEC int gmp_sprintf __GMP_PROTO ((char *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_sprintf (char *, const char *, ...); #define gmp_vasprintf __gmp_vasprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vasprintf __GMP_PROTO ((char **, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vasprintf (char **, const char *, va_list); #endif #define gmp_vfprintf __gmp_vfprintf #if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfprintf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vfprintf (FILE *, const char *, va_list); #endif #define gmp_vprintf __gmp_vprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vprintf __GMP_PROTO ((__gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vprintf (const char *, va_list); #endif #define gmp_vsnprintf __gmp_vsnprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsnprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vsnprintf (char *, size_t, const char *, va_list); #endif #define gmp_vsprintf __gmp_vsprintf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vsprintf (char *, const char *, va_list); #endif @@ -656,28 +585,28 @@ __GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_lis #define gmp_fscanf __gmp_fscanf #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC int gmp_fscanf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_fscanf (FILE *, const char *, ...); #endif #define gmp_scanf __gmp_scanf -__GMP_DECLSPEC int gmp_scanf __GMP_PROTO ((__gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_scanf (const char *, ...); #define gmp_sscanf __gmp_sscanf -__GMP_DECLSPEC int gmp_sscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, ...)); +__GMP_DECLSPEC int gmp_sscanf (const char *, const char *, ...); #define gmp_vfscanf __gmp_vfscanf #if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vfscanf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vfscanf (FILE *, const char *, va_list); #endif #define gmp_vscanf __gmp_vscanf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vscanf __GMP_PROTO ((__gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vscanf (const char *, va_list); #endif #define gmp_vsscanf __gmp_vsscanf #if defined (_GMP_H_HAVE_VA_LIST) -__GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, va_list)); +__GMP_DECLSPEC int gmp_vsscanf (const char *, const char *, va_list); #endif @@ -685,790 +614,842 @@ __GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const cha #define _mpz_realloc __gmpz_realloc #define mpz_realloc __gmpz_realloc -__GMP_DECLSPEC void *_mpz_realloc __GMP_PROTO ((mpz_ptr, mp_size_t)); +__GMP_DECLSPEC void *_mpz_realloc (mpz_ptr, mp_size_t); #define mpz_abs __gmpz_abs #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) -__GMP_DECLSPEC void mpz_abs __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_abs (mpz_ptr, mpz_srcptr); #endif #define mpz_add __gmpz_add -__GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_add (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_add_ui __gmpz_add_ui -__GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_add_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_addmul __gmpz_addmul -__GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_addmul (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_addmul_ui __gmpz_addmul_ui -__GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_addmul_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_and __gmpz_and -__GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_and (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_array_init __gmpz_array_init -__GMP_DECLSPEC void mpz_array_init __GMP_PROTO ((mpz_ptr, mp_size_t, mp_size_t)); +__GMP_DECLSPEC void mpz_array_init (mpz_ptr, mp_size_t, mp_size_t); #define mpz_bin_ui __gmpz_bin_ui -__GMP_DECLSPEC void mpz_bin_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_bin_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_bin_uiui __gmpz_bin_uiui -__GMP_DECLSPEC void mpz_bin_uiui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); +__GMP_DECLSPEC void mpz_bin_uiui (mpz_ptr, unsigned long int, unsigned long int); #define mpz_cdiv_q __gmpz_cdiv_q -__GMP_DECLSPEC void mpz_cdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_cdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp -__GMP_DECLSPEC void mpz_cdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_cdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_cdiv_q_ui __gmpz_cdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_cdiv_qr __gmpz_cdiv_qr -__GMP_DECLSPEC void mpz_cdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_cdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_cdiv_r __gmpz_cdiv_r -__GMP_DECLSPEC void mpz_cdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_cdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp -__GMP_DECLSPEC void mpz_cdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_cdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_cdiv_r_ui __gmpz_cdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_cdiv_ui __gmpz_cdiv_ui -__GMP_DECLSPEC unsigned long int mpz_cdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_cdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; #define mpz_clear __gmpz_clear -__GMP_DECLSPEC void mpz_clear __GMP_PROTO ((mpz_ptr)); +__GMP_DECLSPEC void mpz_clear (mpz_ptr); + +#define mpz_clears __gmpz_clears +__GMP_DECLSPEC void mpz_clears (mpz_ptr, ...); #define mpz_clrbit __gmpz_clrbit -__GMP_DECLSPEC void mpz_clrbit __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_clrbit (mpz_ptr, mp_bitcnt_t); #define mpz_cmp __gmpz_cmp -__GMP_DECLSPEC int mpz_cmp __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmp (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_cmp_d __gmpz_cmp_d -__GMP_DECLSPEC int mpz_cmp_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmp_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; #define _mpz_cmp_si __gmpz_cmp_si -__GMP_DECLSPEC int _mpz_cmp_si __GMP_PROTO ((mpz_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpz_cmp_si (mpz_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define _mpz_cmp_ui __gmpz_cmp_ui -__GMP_DECLSPEC int _mpz_cmp_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpz_cmp_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_cmpabs __gmpz_cmpabs -__GMP_DECLSPEC int mpz_cmpabs __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmpabs (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_cmpabs_d __gmpz_cmpabs_d -__GMP_DECLSPEC int mpz_cmpabs_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmpabs_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; #define mpz_cmpabs_ui __gmpz_cmpabs_ui -__GMP_DECLSPEC int mpz_cmpabs_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_cmpabs_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_com __gmpz_com -__GMP_DECLSPEC void mpz_com __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_com (mpz_ptr, mpz_srcptr); #define mpz_combit __gmpz_combit -__GMP_DECLSPEC void mpz_combit __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_combit (mpz_ptr, mp_bitcnt_t); #define mpz_congruent_p __gmpz_congruent_p -__GMP_DECLSPEC int mpz_congruent_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_congruent_p (mpz_srcptr, mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_congruent_2exp_p __gmpz_congruent_2exp_p -__GMP_DECLSPEC int mpz_congruent_2exp_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_congruent_2exp_p (mpz_srcptr, mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_congruent_ui_p __gmpz_congruent_ui_p -__GMP_DECLSPEC int mpz_congruent_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_congruent_ui_p (mpz_srcptr, unsigned long, unsigned long) __GMP_ATTRIBUTE_PURE; #define mpz_divexact __gmpz_divexact -__GMP_DECLSPEC void mpz_divexact __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_divexact (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_divexact_ui __gmpz_divexact_ui -__GMP_DECLSPEC void mpz_divexact_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_divexact_ui (mpz_ptr, mpz_srcptr, unsigned long); #define mpz_divisible_p __gmpz_divisible_p -__GMP_DECLSPEC int mpz_divisible_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_divisible_p (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_divisible_ui_p __gmpz_divisible_ui_p -__GMP_DECLSPEC int mpz_divisible_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_divisible_ui_p (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; #define mpz_divisible_2exp_p __gmpz_divisible_2exp_p -__GMP_DECLSPEC int mpz_divisible_2exp_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_divisible_2exp_p (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_dump __gmpz_dump -__GMP_DECLSPEC void mpz_dump __GMP_PROTO ((mpz_srcptr)); +__GMP_DECLSPEC void mpz_dump (mpz_srcptr); #define mpz_export __gmpz_export -__GMP_DECLSPEC void *mpz_export __GMP_PROTO ((void *, size_t *, int, size_t, int, size_t, mpz_srcptr)); +__GMP_DECLSPEC void *mpz_export (void *, size_t *, int, size_t, int, size_t, mpz_srcptr); #define mpz_fac_ui __gmpz_fac_ui -__GMP_DECLSPEC void mpz_fac_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fac_ui (mpz_ptr, unsigned long int); + +#define mpz_2fac_ui __gmpz_2fac_ui +__GMP_DECLSPEC void mpz_2fac_ui (mpz_ptr, unsigned long int); + +#define mpz_mfac_uiui __gmpz_mfac_uiui +__GMP_DECLSPEC void mpz_mfac_uiui (mpz_ptr, unsigned long int, unsigned long int); + +#define mpz_primorial_ui __gmpz_primorial_ui +__GMP_DECLSPEC void mpz_primorial_ui (mpz_ptr, unsigned long int); #define mpz_fdiv_q __gmpz_fdiv_q -__GMP_DECLSPEC void mpz_fdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_fdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp -__GMP_DECLSPEC void mpz_fdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_fdiv_q_ui __gmpz_fdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_fdiv_qr __gmpz_fdiv_qr -__GMP_DECLSPEC void mpz_fdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_fdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_fdiv_r __gmpz_fdiv_r -__GMP_DECLSPEC void mpz_fdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_fdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp -__GMP_DECLSPEC void mpz_fdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_fdiv_r_ui __gmpz_fdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_fdiv_ui __gmpz_fdiv_ui -__GMP_DECLSPEC unsigned long int mpz_fdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_fdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; #define mpz_fib_ui __gmpz_fib_ui -__GMP_DECLSPEC void mpz_fib_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fib_ui (mpz_ptr, unsigned long int); #define mpz_fib2_ui __gmpz_fib2_ui -__GMP_DECLSPEC void mpz_fib2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_fib2_ui (mpz_ptr, mpz_ptr, unsigned long int); #define mpz_fits_sint_p __gmpz_fits_sint_p -__GMP_DECLSPEC int mpz_fits_sint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_sint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_fits_slong_p __gmpz_fits_slong_p -__GMP_DECLSPEC int mpz_fits_slong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_slong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_fits_sshort_p __gmpz_fits_sshort_p -__GMP_DECLSPEC int mpz_fits_sshort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_sshort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_fits_uint_p __gmpz_fits_uint_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) -__GMP_DECLSPEC int mpz_fits_uint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_uint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_fits_ulong_p __gmpz_fits_ulong_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) -__GMP_DECLSPEC int mpz_fits_ulong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_ulong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_fits_ushort_p __gmpz_fits_ushort_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) -__GMP_DECLSPEC int mpz_fits_ushort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_fits_ushort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_gcd __gmpz_gcd -__GMP_DECLSPEC void mpz_gcd __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_gcd (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_gcd_ui __gmpz_gcd_ui -__GMP_DECLSPEC unsigned long int mpz_gcd_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_gcd_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_gcdext __gmpz_gcdext -__GMP_DECLSPEC void mpz_gcdext __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_gcdext (mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_get_d __gmpz_get_d -__GMP_DECLSPEC double mpz_get_d __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC double mpz_get_d (mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_get_d_2exp __gmpz_get_d_2exp -__GMP_DECLSPEC double mpz_get_d_2exp __GMP_PROTO ((signed long int *, mpz_srcptr)); +__GMP_DECLSPEC double mpz_get_d_2exp (signed long int *, mpz_srcptr); #define mpz_get_si __gmpz_get_si -__GMP_DECLSPEC /* signed */ long int mpz_get_si __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC /* signed */ long int mpz_get_si (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_get_str __gmpz_get_str -__GMP_DECLSPEC char *mpz_get_str __GMP_PROTO ((char *, int, mpz_srcptr)); +__GMP_DECLSPEC char *mpz_get_str (char *, int, mpz_srcptr); #define mpz_get_ui __gmpz_get_ui #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) -__GMP_DECLSPEC unsigned long int mpz_get_ui __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_get_ui (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_getlimbn __gmpz_getlimbn #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) -__GMP_DECLSPEC mp_limb_t mpz_getlimbn __GMP_PROTO ((mpz_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpz_getlimbn (mpz_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_hamdist __gmpz_hamdist -__GMP_DECLSPEC unsigned long int mpz_hamdist __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_hamdist (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_import __gmpz_import -__GMP_DECLSPEC void mpz_import __GMP_PROTO ((mpz_ptr, size_t, int, size_t, int, size_t, __gmp_const void *)); +__GMP_DECLSPEC void mpz_import (mpz_ptr, size_t, int, size_t, int, size_t, const void *); #define mpz_init __gmpz_init -__GMP_DECLSPEC void mpz_init __GMP_PROTO ((mpz_ptr)); +__GMP_DECLSPEC void mpz_init (mpz_ptr); #define mpz_init2 __gmpz_init2 -__GMP_DECLSPEC void mpz_init2 __GMP_PROTO ((mpz_ptr, unsigned long)); +__GMP_DECLSPEC void mpz_init2 (mpz_ptr, mp_bitcnt_t); + +#define mpz_inits __gmpz_inits +__GMP_DECLSPEC void mpz_inits (mpz_ptr, ...); #define mpz_init_set __gmpz_init_set -__GMP_DECLSPEC void mpz_init_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_init_set (mpz_ptr, mpz_srcptr); #define mpz_init_set_d __gmpz_init_set_d -__GMP_DECLSPEC void mpz_init_set_d __GMP_PROTO ((mpz_ptr, double)); +__GMP_DECLSPEC void mpz_init_set_d (mpz_ptr, double); #define mpz_init_set_si __gmpz_init_set_si -__GMP_DECLSPEC void mpz_init_set_si __GMP_PROTO ((mpz_ptr, signed long int)); +__GMP_DECLSPEC void mpz_init_set_si (mpz_ptr, signed long int); #define mpz_init_set_str __gmpz_init_set_str -__GMP_DECLSPEC int mpz_init_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpz_init_set_str (mpz_ptr, const char *, int); #define mpz_init_set_ui __gmpz_init_set_ui -__GMP_DECLSPEC void mpz_init_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_init_set_ui (mpz_ptr, unsigned long int); #define mpz_inp_raw __gmpz_inp_raw #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_raw __GMP_PROTO ((mpz_ptr, FILE *)); +__GMP_DECLSPEC size_t mpz_inp_raw (mpz_ptr, FILE *); #endif #define mpz_inp_str __gmpz_inp_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_inp_str __GMP_PROTO ((mpz_ptr, FILE *, int)); +__GMP_DECLSPEC size_t mpz_inp_str (mpz_ptr, FILE *, int); #endif #define mpz_invert __gmpz_invert -__GMP_DECLSPEC int mpz_invert __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC int mpz_invert (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_ior __gmpz_ior -__GMP_DECLSPEC void mpz_ior __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_ior (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_jacobi __gmpz_jacobi -__GMP_DECLSPEC int mpz_jacobi __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_jacobi (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_kronecker mpz_jacobi /* alias */ #define mpz_kronecker_si __gmpz_kronecker_si -__GMP_DECLSPEC int mpz_kronecker_si __GMP_PROTO ((mpz_srcptr, long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_kronecker_si (mpz_srcptr, long) __GMP_ATTRIBUTE_PURE; #define mpz_kronecker_ui __gmpz_kronecker_ui -__GMP_DECLSPEC int mpz_kronecker_ui __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_kronecker_ui (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; #define mpz_si_kronecker __gmpz_si_kronecker -__GMP_DECLSPEC int mpz_si_kronecker __GMP_PROTO ((long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_si_kronecker (long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_ui_kronecker __gmpz_ui_kronecker -__GMP_DECLSPEC int mpz_ui_kronecker __GMP_PROTO ((unsigned long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_ui_kronecker (unsigned long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_lcm __gmpz_lcm -__GMP_DECLSPEC void mpz_lcm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_lcm (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_lcm_ui __gmpz_lcm_ui -__GMP_DECLSPEC void mpz_lcm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); +__GMP_DECLSPEC void mpz_lcm_ui (mpz_ptr, mpz_srcptr, unsigned long); #define mpz_legendre mpz_jacobi /* alias */ #define mpz_lucnum_ui __gmpz_lucnum_ui -__GMP_DECLSPEC void mpz_lucnum_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_lucnum_ui (mpz_ptr, unsigned long int); #define mpz_lucnum2_ui __gmpz_lucnum2_ui -__GMP_DECLSPEC void mpz_lucnum2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_lucnum2_ui (mpz_ptr, mpz_ptr, unsigned long int); #define mpz_millerrabin __gmpz_millerrabin -__GMP_DECLSPEC int mpz_millerrabin __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_millerrabin (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; #define mpz_mod __gmpz_mod -__GMP_DECLSPEC void mpz_mod __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_mod (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ #define mpz_mul __gmpz_mul -__GMP_DECLSPEC void mpz_mul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_mul (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_mul_2exp __gmpz_mul_2exp -__GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_mul_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_mul_si __gmpz_mul_si -__GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int)); +__GMP_DECLSPEC void mpz_mul_si (mpz_ptr, mpz_srcptr, long int); #define mpz_mul_ui __gmpz_mul_ui -__GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_mul_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_neg __gmpz_neg #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) -__GMP_DECLSPEC void mpz_neg __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_neg (mpz_ptr, mpz_srcptr); #endif #define mpz_nextprime __gmpz_nextprime -__GMP_DECLSPEC void mpz_nextprime __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_nextprime (mpz_ptr, mpz_srcptr); #define mpz_out_raw __gmpz_out_raw #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_raw __GMP_PROTO ((FILE *, mpz_srcptr)); +__GMP_DECLSPEC size_t mpz_out_raw (FILE *, mpz_srcptr); #endif #define mpz_out_str __gmpz_out_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpz_out_str __GMP_PROTO ((FILE *, int, mpz_srcptr)); +__GMP_DECLSPEC size_t mpz_out_str (FILE *, int, mpz_srcptr); #endif #define mpz_perfect_power_p __gmpz_perfect_power_p -__GMP_DECLSPEC int mpz_perfect_power_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_perfect_power_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpz_perfect_square_p __gmpz_perfect_square_p #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) -__GMP_DECLSPEC int mpz_perfect_square_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_perfect_square_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; #endif #define mpz_popcount __gmpz_popcount #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) -__GMP_DECLSPEC unsigned long int mpz_popcount __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_popcount (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_pow_ui __gmpz_pow_ui -__GMP_DECLSPEC void mpz_pow_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_pow_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_powm __gmpz_powm -__GMP_DECLSPEC void mpz_powm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_powm (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); + +#define mpz_powm_sec __gmpz_powm_sec +__GMP_DECLSPEC void mpz_powm_sec (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); #define mpz_powm_ui __gmpz_powm_ui -__GMP_DECLSPEC void mpz_powm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); +__GMP_DECLSPEC void mpz_powm_ui (mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr); #define mpz_probab_prime_p __gmpz_probab_prime_p -__GMP_DECLSPEC int mpz_probab_prime_p __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_probab_prime_p (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; #define mpz_random __gmpz_random -__GMP_DECLSPEC void mpz_random __GMP_PROTO ((mpz_ptr, mp_size_t)); +__GMP_DECLSPEC void mpz_random (mpz_ptr, mp_size_t); #define mpz_random2 __gmpz_random2 -__GMP_DECLSPEC void mpz_random2 __GMP_PROTO ((mpz_ptr, mp_size_t)); +__GMP_DECLSPEC void mpz_random2 (mpz_ptr, mp_size_t); #define mpz_realloc2 __gmpz_realloc2 -__GMP_DECLSPEC void mpz_realloc2 __GMP_PROTO ((mpz_ptr, unsigned long)); +__GMP_DECLSPEC void mpz_realloc2 (mpz_ptr, mp_bitcnt_t); #define mpz_remove __gmpz_remove -__GMP_DECLSPEC unsigned long int mpz_remove __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC mp_bitcnt_t mpz_remove (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_root __gmpz_root -__GMP_DECLSPEC int mpz_root __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC int mpz_root (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_rootrem __gmpz_rootrem -__GMP_DECLSPEC void mpz_rootrem __GMP_PROTO ((mpz_ptr,mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_rootrem (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_rrandomb __gmpz_rrandomb -__GMP_DECLSPEC void mpz_rrandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void mpz_rrandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); #define mpz_scan0 __gmpz_scan0 -__GMP_DECLSPEC unsigned long int mpz_scan0 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_scan0 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_scan1 __gmpz_scan1 -__GMP_DECLSPEC unsigned long int mpz_scan1 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpz_scan1 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_set __gmpz_set -__GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_set (mpz_ptr, mpz_srcptr); #define mpz_set_d __gmpz_set_d -__GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double)); +__GMP_DECLSPEC void mpz_set_d (mpz_ptr, double); #define mpz_set_f __gmpz_set_f -__GMP_DECLSPEC void mpz_set_f __GMP_PROTO ((mpz_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpz_set_f (mpz_ptr, mpf_srcptr); #define mpz_set_q __gmpz_set_q #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) -__GMP_DECLSPEC void mpz_set_q __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpz_set_q (mpz_ptr, mpq_srcptr); #endif #define mpz_set_si __gmpz_set_si -__GMP_DECLSPEC void mpz_set_si __GMP_PROTO ((mpz_ptr, signed long int)); +__GMP_DECLSPEC void mpz_set_si (mpz_ptr, signed long int); #define mpz_set_str __gmpz_set_str -__GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpz_set_str (mpz_ptr, const char *, int); #define mpz_set_ui __gmpz_set_ui -__GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_set_ui (mpz_ptr, unsigned long int); #define mpz_setbit __gmpz_setbit -__GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, unsigned long int)); +__GMP_DECLSPEC void mpz_setbit (mpz_ptr, mp_bitcnt_t); #define mpz_size __gmpz_size #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) -__GMP_DECLSPEC size_t mpz_size __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC size_t mpz_size (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif #define mpz_sizeinbase __gmpz_sizeinbase -__GMP_DECLSPEC size_t mpz_sizeinbase __GMP_PROTO ((mpz_srcptr, int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC size_t mpz_sizeinbase (mpz_srcptr, int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_sqrt __gmpz_sqrt -__GMP_DECLSPEC void mpz_sqrt __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_sqrt (mpz_ptr, mpz_srcptr); #define mpz_sqrtrem __gmpz_sqrtrem -__GMP_DECLSPEC void mpz_sqrtrem __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_sqrtrem (mpz_ptr, mpz_ptr, mpz_srcptr); #define mpz_sub __gmpz_sub -__GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_sub (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_sub_ui __gmpz_sub_ui -__GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_sub_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_ui_sub __gmpz_ui_sub -__GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, unsigned long int, mpz_srcptr)); +__GMP_DECLSPEC void mpz_ui_sub (mpz_ptr, unsigned long int, mpz_srcptr); #define mpz_submul __gmpz_submul -__GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_submul (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_submul_ui __gmpz_submul_ui -__GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_submul_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_swap __gmpz_swap -__GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpz_swap (mpz_ptr, mpz_ptr) __GMP_NOTHROW; #define mpz_tdiv_ui __gmpz_tdiv_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long int mpz_tdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; #define mpz_tdiv_q __gmpz_tdiv_q -__GMP_DECLSPEC void mpz_tdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_tdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp -__GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_tdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_tdiv_q_ui __gmpz_tdiv_q_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_tdiv_qr __gmpz_tdiv_qr -__GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_tdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_tdiv_r __gmpz_tdiv_r -__GMP_DECLSPEC void mpz_tdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_tdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); #define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp -__GMP_DECLSPEC void mpz_tdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpz_tdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); #define mpz_tdiv_r_ui __gmpz_tdiv_r_ui -__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); #define mpz_tstbit __gmpz_tstbit -__GMP_DECLSPEC int mpz_tstbit __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpz_tstbit (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpz_ui_pow_ui __gmpz_ui_pow_ui -__GMP_DECLSPEC void mpz_ui_pow_ui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); +__GMP_DECLSPEC void mpz_ui_pow_ui (mpz_ptr, unsigned long int, unsigned long int); #define mpz_urandomb __gmpz_urandomb -__GMP_DECLSPEC void mpz_urandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void mpz_urandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); #define mpz_urandomm __gmpz_urandomm -__GMP_DECLSPEC void mpz_urandomm __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mpz_srcptr)); +__GMP_DECLSPEC void mpz_urandomm (mpz_ptr, gmp_randstate_t, mpz_srcptr); #define mpz_xor __gmpz_xor #define mpz_eor __gmpz_xor -__GMP_DECLSPEC void mpz_xor __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +__GMP_DECLSPEC void mpz_xor (mpz_ptr, mpz_srcptr, mpz_srcptr); +#define mpz_limbs_read __gmpz_limbs_read +__GMP_DECLSPEC mp_srcptr mpz_limbs_read (mpz_srcptr); + +#define mpz_limbs_write __gmpz_limbs_write +__GMP_DECLSPEC mp_ptr mpz_limbs_write (mpz_ptr, mp_size_t); + +#define mpz_limbs_modify __gmpz_limbs_modify +__GMP_DECLSPEC mp_ptr mpz_limbs_modify (mpz_ptr, mp_size_t); + +#define mpz_limbs_finish __gmpz_limbs_finish +__GMP_DECLSPEC void mpz_limbs_finish (mpz_ptr, mp_size_t); + +#define mpz_roinit_n __gmpz_roinit_n +__GMP_DECLSPEC mpz_srcptr mpz_roinit_n (mpz_ptr, mp_srcptr, mp_size_t); + +#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} /**************** Rational (i.e. Q) routines. ****************/ #define mpq_abs __gmpq_abs #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) -__GMP_DECLSPEC void mpq_abs __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_abs (mpq_ptr, mpq_srcptr); #endif #define mpq_add __gmpq_add -__GMP_DECLSPEC void mpq_add __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_add (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_canonicalize __gmpq_canonicalize -__GMP_DECLSPEC void mpq_canonicalize __GMP_PROTO ((mpq_ptr)); +__GMP_DECLSPEC void mpq_canonicalize (mpq_ptr); #define mpq_clear __gmpq_clear -__GMP_DECLSPEC void mpq_clear __GMP_PROTO ((mpq_ptr)); +__GMP_DECLSPEC void mpq_clear (mpq_ptr); + +#define mpq_clears __gmpq_clears +__GMP_DECLSPEC void mpq_clears (mpq_ptr, ...); #define mpq_cmp __gmpq_cmp -__GMP_DECLSPEC int mpq_cmp __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpq_cmp (mpq_srcptr, mpq_srcptr) __GMP_ATTRIBUTE_PURE; #define _mpq_cmp_si __gmpq_cmp_si -__GMP_DECLSPEC int _mpq_cmp_si __GMP_PROTO ((mpq_srcptr, long, unsigned long)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpq_cmp_si (mpq_srcptr, long, unsigned long) __GMP_ATTRIBUTE_PURE; #define _mpq_cmp_ui __gmpq_cmp_ui -__GMP_DECLSPEC int _mpq_cmp_ui __GMP_PROTO ((mpq_srcptr, unsigned long int, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int _mpq_cmp_ui (mpq_srcptr, unsigned long int, unsigned long int) __GMP_ATTRIBUTE_PURE; + +#define mpq_cmp_z __gmpq_cmp_z +__GMP_DECLSPEC int mpq_cmp_z (mpq_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; #define mpq_div __gmpq_div -__GMP_DECLSPEC void mpq_div __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_div (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_div_2exp __gmpq_div_2exp -__GMP_DECLSPEC void mpq_div_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); +__GMP_DECLSPEC void mpq_div_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); #define mpq_equal __gmpq_equal -__GMP_DECLSPEC int mpq_equal __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpq_equal (mpq_srcptr, mpq_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpq_get_num __gmpq_get_num -__GMP_DECLSPEC void mpq_get_num __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_get_num (mpz_ptr, mpq_srcptr); #define mpq_get_den __gmpq_get_den -__GMP_DECLSPEC void mpq_get_den __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_get_den (mpz_ptr, mpq_srcptr); #define mpq_get_d __gmpq_get_d -__GMP_DECLSPEC double mpq_get_d __GMP_PROTO ((mpq_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC double mpq_get_d (mpq_srcptr) __GMP_ATTRIBUTE_PURE; #define mpq_get_str __gmpq_get_str -__GMP_DECLSPEC char *mpq_get_str __GMP_PROTO ((char *, int, mpq_srcptr)); +__GMP_DECLSPEC char *mpq_get_str (char *, int, mpq_srcptr); #define mpq_init __gmpq_init -__GMP_DECLSPEC void mpq_init __GMP_PROTO ((mpq_ptr)); +__GMP_DECLSPEC void mpq_init (mpq_ptr); + +#define mpq_inits __gmpq_inits +__GMP_DECLSPEC void mpq_inits (mpq_ptr, ...); #define mpq_inp_str __gmpq_inp_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_inp_str __GMP_PROTO ((mpq_ptr, FILE *, int)); +__GMP_DECLSPEC size_t mpq_inp_str (mpq_ptr, FILE *, int); #endif #define mpq_inv __gmpq_inv -__GMP_DECLSPEC void mpq_inv __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_inv (mpq_ptr, mpq_srcptr); #define mpq_mul __gmpq_mul -__GMP_DECLSPEC void mpq_mul __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_mul (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_mul_2exp __gmpq_mul_2exp -__GMP_DECLSPEC void mpq_mul_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); +__GMP_DECLSPEC void mpq_mul_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); #define mpq_neg __gmpq_neg #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) -__GMP_DECLSPEC void mpq_neg __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_neg (mpq_ptr, mpq_srcptr); #endif #define mpq_out_str __gmpq_out_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr)); +__GMP_DECLSPEC size_t mpq_out_str (FILE *, int, mpq_srcptr); #endif #define mpq_set __gmpq_set -__GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_set (mpq_ptr, mpq_srcptr); #define mpq_set_d __gmpq_set_d -__GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double)); +__GMP_DECLSPEC void mpq_set_d (mpq_ptr, double); #define mpq_set_den __gmpq_set_den -__GMP_DECLSPEC void mpq_set_den __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpq_set_den (mpq_ptr, mpz_srcptr); #define mpq_set_f __gmpq_set_f -__GMP_DECLSPEC void mpq_set_f __GMP_PROTO ((mpq_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpq_set_f (mpq_ptr, mpf_srcptr); #define mpq_set_num __gmpq_set_num -__GMP_DECLSPEC void mpq_set_num __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpq_set_num (mpq_ptr, mpz_srcptr); #define mpq_set_si __gmpq_set_si -__GMP_DECLSPEC void mpq_set_si __GMP_PROTO ((mpq_ptr, signed long int, unsigned long int)); +__GMP_DECLSPEC void mpq_set_si (mpq_ptr, signed long int, unsigned long int); #define mpq_set_str __gmpq_set_str -__GMP_DECLSPEC int mpq_set_str __GMP_PROTO ((mpq_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpq_set_str (mpq_ptr, const char *, int); #define mpq_set_ui __gmpq_set_ui -__GMP_DECLSPEC void mpq_set_ui __GMP_PROTO ((mpq_ptr, unsigned long int, unsigned long int)); +__GMP_DECLSPEC void mpq_set_ui (mpq_ptr, unsigned long int, unsigned long int); #define mpq_set_z __gmpq_set_z -__GMP_DECLSPEC void mpq_set_z __GMP_PROTO ((mpq_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpq_set_z (mpq_ptr, mpz_srcptr); #define mpq_sub __gmpq_sub -__GMP_DECLSPEC void mpq_sub __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +__GMP_DECLSPEC void mpq_sub (mpq_ptr, mpq_srcptr, mpq_srcptr); #define mpq_swap __gmpq_swap -__GMP_DECLSPEC void mpq_swap __GMP_PROTO ((mpq_ptr, mpq_ptr)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpq_swap (mpq_ptr, mpq_ptr) __GMP_NOTHROW; /**************** Float (i.e. F) routines. ****************/ #define mpf_abs __gmpf_abs -__GMP_DECLSPEC void mpf_abs __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_abs (mpf_ptr, mpf_srcptr); #define mpf_add __gmpf_add -__GMP_DECLSPEC void mpf_add __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_add (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_add_ui __gmpf_add_ui -__GMP_DECLSPEC void mpf_add_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_add_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_ceil __gmpf_ceil -__GMP_DECLSPEC void mpf_ceil __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_ceil (mpf_ptr, mpf_srcptr); #define mpf_clear __gmpf_clear -__GMP_DECLSPEC void mpf_clear __GMP_PROTO ((mpf_ptr)); +__GMP_DECLSPEC void mpf_clear (mpf_ptr); + +#define mpf_clears __gmpf_clears +__GMP_DECLSPEC void mpf_clears (mpf_ptr, ...); #define mpf_cmp __gmpf_cmp -__GMP_DECLSPEC int mpf_cmp __GMP_PROTO ((mpf_srcptr, mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp (mpf_srcptr, mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_z __gmpf_cmp_z +__GMP_DECLSPEC int mpf_cmp_z (mpf_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_cmp_d __gmpf_cmp_d -__GMP_DECLSPEC int mpf_cmp_d __GMP_PROTO ((mpf_srcptr, double)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp_d (mpf_srcptr, double) __GMP_ATTRIBUTE_PURE; #define mpf_cmp_si __gmpf_cmp_si -__GMP_DECLSPEC int mpf_cmp_si __GMP_PROTO ((mpf_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp_si (mpf_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_cmp_ui __gmpf_cmp_ui -__GMP_DECLSPEC int mpf_cmp_ui __GMP_PROTO ((mpf_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_cmp_ui (mpf_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_div __gmpf_div -__GMP_DECLSPEC void mpf_div __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_div (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_div_2exp __gmpf_div_2exp -__GMP_DECLSPEC void mpf_div_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_div_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); #define mpf_div_ui __gmpf_div_ui -__GMP_DECLSPEC void mpf_div_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_div_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_dump __gmpf_dump -__GMP_DECLSPEC void mpf_dump __GMP_PROTO ((mpf_srcptr)); +__GMP_DECLSPEC void mpf_dump (mpf_srcptr); #define mpf_eq __gmpf_eq -__GMP_DECLSPEC int mpf_eq __GMP_PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_eq (mpf_srcptr, mpf_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; #define mpf_fits_sint_p __gmpf_fits_sint_p -__GMP_DECLSPEC int mpf_fits_sint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_sint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_slong_p __gmpf_fits_slong_p -__GMP_DECLSPEC int mpf_fits_slong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_slong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_sshort_p __gmpf_fits_sshort_p -__GMP_DECLSPEC int mpf_fits_sshort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_sshort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_uint_p __gmpf_fits_uint_p -__GMP_DECLSPEC int mpf_fits_uint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_uint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_ulong_p __gmpf_fits_ulong_p -__GMP_DECLSPEC int mpf_fits_ulong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_ulong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_fits_ushort_p __gmpf_fits_ushort_p -__GMP_DECLSPEC int mpf_fits_ushort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_fits_ushort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_floor __gmpf_floor -__GMP_DECLSPEC void mpf_floor __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_floor (mpf_ptr, mpf_srcptr); #define mpf_get_d __gmpf_get_d -__GMP_DECLSPEC double mpf_get_d __GMP_PROTO ((mpf_srcptr)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC double mpf_get_d (mpf_srcptr) __GMP_ATTRIBUTE_PURE; #define mpf_get_d_2exp __gmpf_get_d_2exp -__GMP_DECLSPEC double mpf_get_d_2exp __GMP_PROTO ((signed long int *, mpf_srcptr)); +__GMP_DECLSPEC double mpf_get_d_2exp (signed long int *, mpf_srcptr); #define mpf_get_default_prec __gmpf_get_default_prec -__GMP_DECLSPEC unsigned long int mpf_get_default_prec __GMP_PROTO ((void)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpf_get_default_prec (void) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_get_prec __gmpf_get_prec -__GMP_DECLSPEC unsigned long int mpf_get_prec __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpf_get_prec (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_get_si __gmpf_get_si -__GMP_DECLSPEC long mpf_get_si __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC long mpf_get_si (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_get_str __gmpf_get_str -__GMP_DECLSPEC char *mpf_get_str __GMP_PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); +__GMP_DECLSPEC char *mpf_get_str (char *, mp_exp_t *, int, size_t, mpf_srcptr); #define mpf_get_ui __gmpf_get_ui -__GMP_DECLSPEC unsigned long mpf_get_ui __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC unsigned long mpf_get_ui (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_init __gmpf_init -__GMP_DECLSPEC void mpf_init __GMP_PROTO ((mpf_ptr)); +__GMP_DECLSPEC void mpf_init (mpf_ptr); #define mpf_init2 __gmpf_init2 -__GMP_DECLSPEC void mpf_init2 __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_init2 (mpf_ptr, mp_bitcnt_t); + +#define mpf_inits __gmpf_inits +__GMP_DECLSPEC void mpf_inits (mpf_ptr, ...); #define mpf_init_set __gmpf_init_set -__GMP_DECLSPEC void mpf_init_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_init_set (mpf_ptr, mpf_srcptr); #define mpf_init_set_d __gmpf_init_set_d -__GMP_DECLSPEC void mpf_init_set_d __GMP_PROTO ((mpf_ptr, double)); +__GMP_DECLSPEC void mpf_init_set_d (mpf_ptr, double); #define mpf_init_set_si __gmpf_init_set_si -__GMP_DECLSPEC void mpf_init_set_si __GMP_PROTO ((mpf_ptr, signed long int)); +__GMP_DECLSPEC void mpf_init_set_si (mpf_ptr, signed long int); #define mpf_init_set_str __gmpf_init_set_str -__GMP_DECLSPEC int mpf_init_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpf_init_set_str (mpf_ptr, const char *, int); #define mpf_init_set_ui __gmpf_init_set_ui -__GMP_DECLSPEC void mpf_init_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_init_set_ui (mpf_ptr, unsigned long int); #define mpf_inp_str __gmpf_inp_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_inp_str __GMP_PROTO ((mpf_ptr, FILE *, int)); +__GMP_DECLSPEC size_t mpf_inp_str (mpf_ptr, FILE *, int); #endif #define mpf_integer_p __gmpf_integer_p -__GMP_DECLSPEC int mpf_integer_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpf_integer_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_mul __gmpf_mul -__GMP_DECLSPEC void mpf_mul __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_mul (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_mul_2exp __gmpf_mul_2exp -__GMP_DECLSPEC void mpf_mul_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_mul_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); #define mpf_mul_ui __gmpf_mul_ui -__GMP_DECLSPEC void mpf_mul_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_mul_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_neg __gmpf_neg -__GMP_DECLSPEC void mpf_neg __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_neg (mpf_ptr, mpf_srcptr); #define mpf_out_str __gmpf_out_str #ifdef _GMP_H_HAVE_FILE -__GMP_DECLSPEC size_t mpf_out_str __GMP_PROTO ((FILE *, int, size_t, mpf_srcptr)); +__GMP_DECLSPEC size_t mpf_out_str (FILE *, int, size_t, mpf_srcptr); #endif #define mpf_pow_ui __gmpf_pow_ui -__GMP_DECLSPEC void mpf_pow_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_pow_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_random2 __gmpf_random2 -__GMP_DECLSPEC void mpf_random2 __GMP_PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); +__GMP_DECLSPEC void mpf_random2 (mpf_ptr, mp_size_t, mp_exp_t); #define mpf_reldiff __gmpf_reldiff -__GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_reldiff (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_set __gmpf_set -__GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_set (mpf_ptr, mpf_srcptr); #define mpf_set_d __gmpf_set_d -__GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double)); +__GMP_DECLSPEC void mpf_set_d (mpf_ptr, double); #define mpf_set_default_prec __gmpf_set_default_prec -__GMP_DECLSPEC void mpf_set_default_prec __GMP_PROTO ((unsigned long int)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpf_set_default_prec (mp_bitcnt_t) __GMP_NOTHROW; #define mpf_set_prec __gmpf_set_prec -__GMP_DECLSPEC void mpf_set_prec __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_set_prec (mpf_ptr, mp_bitcnt_t); #define mpf_set_prec_raw __gmpf_set_prec_raw -__GMP_DECLSPEC void mpf_set_prec_raw __GMP_PROTO ((mpf_ptr, unsigned long int)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpf_set_prec_raw (mpf_ptr, mp_bitcnt_t) __GMP_NOTHROW; #define mpf_set_q __gmpf_set_q -__GMP_DECLSPEC void mpf_set_q __GMP_PROTO ((mpf_ptr, mpq_srcptr)); +__GMP_DECLSPEC void mpf_set_q (mpf_ptr, mpq_srcptr); #define mpf_set_si __gmpf_set_si -__GMP_DECLSPEC void mpf_set_si __GMP_PROTO ((mpf_ptr, signed long int)); +__GMP_DECLSPEC void mpf_set_si (mpf_ptr, signed long int); #define mpf_set_str __gmpf_set_str -__GMP_DECLSPEC int mpf_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); +__GMP_DECLSPEC int mpf_set_str (mpf_ptr, const char *, int); #define mpf_set_ui __gmpf_set_ui -__GMP_DECLSPEC void mpf_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_set_ui (mpf_ptr, unsigned long int); #define mpf_set_z __gmpf_set_z -__GMP_DECLSPEC void mpf_set_z __GMP_PROTO ((mpf_ptr, mpz_srcptr)); +__GMP_DECLSPEC void mpf_set_z (mpf_ptr, mpz_srcptr); #define mpf_size __gmpf_size -__GMP_DECLSPEC size_t mpf_size __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC size_t mpf_size (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpf_sqrt __gmpf_sqrt -__GMP_DECLSPEC void mpf_sqrt __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_sqrt (mpf_ptr, mpf_srcptr); #define mpf_sqrt_ui __gmpf_sqrt_ui -__GMP_DECLSPEC void mpf_sqrt_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); +__GMP_DECLSPEC void mpf_sqrt_ui (mpf_ptr, unsigned long int); #define mpf_sub __gmpf_sub -__GMP_DECLSPEC void mpf_sub __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_sub (mpf_ptr, mpf_srcptr, mpf_srcptr); #define mpf_sub_ui __gmpf_sub_ui -__GMP_DECLSPEC void mpf_sub_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +__GMP_DECLSPEC void mpf_sub_ui (mpf_ptr, mpf_srcptr, unsigned long int); #define mpf_swap __gmpf_swap -__GMP_DECLSPEC void mpf_swap __GMP_PROTO ((mpf_ptr, mpf_ptr)) __GMP_NOTHROW; +__GMP_DECLSPEC void mpf_swap (mpf_ptr, mpf_ptr) __GMP_NOTHROW; #define mpf_trunc __gmpf_trunc -__GMP_DECLSPEC void mpf_trunc __GMP_PROTO ((mpf_ptr, mpf_srcptr)); +__GMP_DECLSPEC void mpf_trunc (mpf_ptr, mpf_srcptr); #define mpf_ui_div __gmpf_ui_div -__GMP_DECLSPEC void mpf_ui_div __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +__GMP_DECLSPEC void mpf_ui_div (mpf_ptr, unsigned long int, mpf_srcptr); #define mpf_ui_sub __gmpf_ui_sub -__GMP_DECLSPEC void mpf_ui_sub __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +__GMP_DECLSPEC void mpf_ui_sub (mpf_ptr, unsigned long int, mpf_srcptr); #define mpf_urandomb __gmpf_urandomb -__GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned long int)); +__GMP_DECLSPEC void mpf_urandomb (mpf_t, gmp_randstate_t, mp_bitcnt_t); /************ Low level positive-integer (i.e. N) routines. ************/ @@ -1477,139 +1458,233 @@ __GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned #define mpn_add __MPN(add) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) -__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #endif #define mpn_add_1 __MPN(add_1) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) -__GMP_DECLSPEC mp_limb_t mpn_add_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +__GMP_DECLSPEC mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; #endif #define mpn_add_n __MPN(add_n) -__GMP_DECLSPEC mp_limb_t mpn_add_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #define mpn_addmul_1 __MPN(addmul_1) -__GMP_DECLSPEC mp_limb_t mpn_addmul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); - -#define mpn_bdivmod __MPN(bdivmod) -__GMP_DECLSPEC mp_limb_t mpn_bdivmod __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); +__GMP_DECLSPEC mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_cmp __MPN(cmp) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) -__GMP_DECLSPEC int mpn_cmp __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #endif +#define mpn_zero_p __MPN(zero_p) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_zero_p) +__GMP_DECLSPEC int mpn_zero_p (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_divexact_1 __MPN(divexact_1) +__GMP_DECLSPEC void mpn_divexact_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + #define mpn_divexact_by3(dst,src,size) \ mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) #define mpn_divexact_by3c __MPN(divexact_by3c) -__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_divmod_1(qp,np,nsize,dlimb) \ mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) #define mpn_divrem __MPN(divrem) -__GMP_DECLSPEC mp_limb_t mpn_divrem __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_divrem (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t); #define mpn_divrem_1 __MPN(divrem_1) -__GMP_DECLSPEC mp_limb_t mpn_divrem_1 __GMP_PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_divrem_1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_divrem_2 __MPN(divrem_2) -__GMP_DECLSPEC mp_limb_t mpn_divrem_2 __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr)); +__GMP_DECLSPEC mp_limb_t mpn_divrem_2 (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr); + +#define mpn_div_qr_1 __MPN(div_qr_1) +__GMP_DECLSPEC mp_limb_t mpn_div_qr_1 (mp_ptr, mp_limb_t *, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_div_qr_2 __MPN(div_qr_2) +__GMP_DECLSPEC mp_limb_t mpn_div_qr_2 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); #define mpn_gcd __MPN(gcd) -__GMP_DECLSPEC mp_size_t mpn_gcd __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +__GMP_DECLSPEC mp_size_t mpn_gcd (mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t); #define mpn_gcd_1 __MPN(gcd_1) -__GMP_DECLSPEC mp_limb_t mpn_gcd_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpn_gcd_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; #define mpn_gcdext_1 __MPN(gcdext_1) -__GMP_DECLSPEC mp_limb_t mpn_gcdext_1 __GMP_PROTO ((mp_limb_signed_t *, mp_limb_signed_t *, mp_limb_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_gcdext_1 (mp_limb_signed_t *, mp_limb_signed_t *, mp_limb_t, mp_limb_t); #define mpn_gcdext __MPN(gcdext) -__GMP_DECLSPEC mp_size_t mpn_gcdext __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +__GMP_DECLSPEC mp_size_t mpn_gcdext (mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t); #define mpn_get_str __MPN(get_str) -__GMP_DECLSPEC size_t mpn_get_str __GMP_PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); +__GMP_DECLSPEC size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t); #define mpn_hamdist __MPN(hamdist) -__GMP_DECLSPEC unsigned long int mpn_hamdist __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_hamdist (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpn_lshift __MPN(lshift) -__GMP_DECLSPEC mp_limb_t mpn_lshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +__GMP_DECLSPEC mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); #define mpn_mod_1 __MPN(mod_1) -__GMP_DECLSPEC mp_limb_t mpn_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpn_mod_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; #define mpn_mul __MPN(mul) -__GMP_DECLSPEC mp_limb_t mpn_mul __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #define mpn_mul_1 __MPN(mul_1) -__GMP_DECLSPEC mp_limb_t mpn_mul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_mul_n __MPN(mul_n) -__GMP_DECLSPEC void mpn_mul_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #define mpn_sqr __MPN(sqr) -__GMP_DECLSPEC void mpn_sqr __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); -#define mpn_neg_n __MPN(neg_n) -#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_neg_n) -__GMP_DECLSPEC mp_limb_t mpn_neg_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t)); +#define mpn_neg __MPN(neg) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_neg) +__GMP_DECLSPEC mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t); #endif +#define mpn_com __MPN(com) +__GMP_DECLSPEC void mpn_com (mp_ptr, mp_srcptr, mp_size_t); + #define mpn_perfect_square_p __MPN(perfect_square_p) -__GMP_DECLSPEC int mpn_perfect_square_p __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC int mpn_perfect_square_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_perfect_power_p __MPN(perfect_power_p) +__GMP_DECLSPEC int mpn_perfect_power_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; #define mpn_popcount __MPN(popcount) -__GMP_DECLSPEC unsigned long int mpn_popcount __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; #define mpn_pow_1 __MPN(pow_1) -__GMP_DECLSPEC mp_size_t mpn_pow_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr)); +__GMP_DECLSPEC mp_size_t mpn_pow_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); /* undocumented now, but retained here for upward compatibility */ #define mpn_preinv_mod_1 __MPN(preinv_mod_1) -__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; #define mpn_random __MPN(random) -__GMP_DECLSPEC void mpn_random __GMP_PROTO ((mp_ptr, mp_size_t)); +__GMP_DECLSPEC void mpn_random (mp_ptr, mp_size_t); #define mpn_random2 __MPN(random2) -__GMP_DECLSPEC void mpn_random2 __GMP_PROTO ((mp_ptr, mp_size_t)); +__GMP_DECLSPEC void mpn_random2 (mp_ptr, mp_size_t); #define mpn_rshift __MPN(rshift) -__GMP_DECLSPEC mp_limb_t mpn_rshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +__GMP_DECLSPEC mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); #define mpn_scan0 __MPN(scan0) -__GMP_DECLSPEC unsigned long int mpn_scan0 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; #define mpn_scan1 __MPN(scan1) -__GMP_DECLSPEC unsigned long int mpn_scan1 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; +__GMP_DECLSPEC mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; #define mpn_set_str __MPN(set_str) -__GMP_DECLSPEC mp_size_t mpn_set_str __GMP_PROTO ((mp_ptr, __gmp_const unsigned char *, size_t, int)); +__GMP_DECLSPEC mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int); + +#define mpn_sizeinbase __MPN(sizeinbase) +__GMP_DECLSPEC size_t mpn_sizeinbase (mp_srcptr, mp_size_t, int); #define mpn_sqrtrem __MPN(sqrtrem) -__GMP_DECLSPEC mp_size_t mpn_sqrtrem __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); #define mpn_sub __MPN(sub) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) -__GMP_DECLSPEC mp_limb_t mpn_sub __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); #endif #define mpn_sub_1 __MPN(sub_1) #if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) -__GMP_DECLSPEC mp_limb_t mpn_sub_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +__GMP_DECLSPEC mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; #endif #define mpn_sub_n __MPN(sub_n) -__GMP_DECLSPEC mp_limb_t mpn_sub_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); #define mpn_submul_1 __MPN(submul_1) -__GMP_DECLSPEC mp_limb_t mpn_submul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +__GMP_DECLSPEC mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); #define mpn_tdiv_qr __MPN(tdiv_qr) -__GMP_DECLSPEC void mpn_tdiv_qr __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +__GMP_DECLSPEC void mpn_tdiv_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_and_n __MPN(and_n) +__GMP_DECLSPEC void mpn_and_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_andn_n __MPN(andn_n) +__GMP_DECLSPEC void mpn_andn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_nand_n __MPN(nand_n) +__GMP_DECLSPEC void mpn_nand_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_ior_n __MPN(ior_n) +__GMP_DECLSPEC void mpn_ior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_iorn_n __MPN(iorn_n) +__GMP_DECLSPEC void mpn_iorn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_nior_n __MPN(nior_n) +__GMP_DECLSPEC void mpn_nior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_xor_n __MPN(xor_n) +__GMP_DECLSPEC void mpn_xor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_xnor_n __MPN(xnor_n) +__GMP_DECLSPEC void mpn_xnor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_copyi __MPN(copyi) +__GMP_DECLSPEC void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); +#define mpn_copyd __MPN(copyd) +__GMP_DECLSPEC void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); +#define mpn_zero __MPN(zero) +__GMP_DECLSPEC void mpn_zero (mp_ptr, mp_size_t); + +#define mpn_cnd_add_n __MPN(cnd_add_n) +__GMP_DECLSPEC mp_limb_t mpn_cnd_add_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_cnd_sub_n __MPN(cnd_sub_n) +__GMP_DECLSPEC mp_limb_t mpn_cnd_sub_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_sec_add_1 __MPN(sec_add_1) +__GMP_DECLSPEC mp_limb_t mpn_sec_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_sec_add_1_itch __MPN(sec_add_1_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_add_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_sub_1 __MPN(sec_sub_1) +__GMP_DECLSPEC mp_limb_t mpn_sec_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_sec_sub_1_itch __MPN(sec_sub_1_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_sub_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_cnd_swap __MPN(cnd_swap) +__GMP_DECLSPEC void mpn_cnd_swap (mp_limb_t, volatile mp_limb_t *, volatile mp_limb_t *, mp_size_t); + +#define mpn_sec_mul __MPN(sec_mul) +__GMP_DECLSPEC void mpn_sec_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_mul_itch __MPN(sec_mul_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_mul_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_sqr __MPN(sec_sqr) +__GMP_DECLSPEC void mpn_sec_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_sqr_itch __MPN(sec_sqr_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_sqr_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_powm __MPN(sec_powm) +__GMP_DECLSPEC void mpn_sec_powm (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_bitcnt_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_powm_itch __MPN(sec_powm_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_powm_itch (mp_size_t, mp_bitcnt_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_tabselect __MPN(sec_tabselect) +__GMP_DECLSPEC void mpn_sec_tabselect (volatile mp_limb_t *, volatile const mp_limb_t *, mp_size_t, mp_size_t, mp_size_t); + +#define mpn_sec_div_qr __MPN(sec_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_sec_div_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_div_qr_itch __MPN(sec_div_qr_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_div_qr_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; +#define mpn_sec_div_r __MPN(sec_div_r) +__GMP_DECLSPEC void mpn_sec_div_r (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_div_r_itch __MPN(sec_div_r_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_div_r_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_invert __MPN(sec_invert) +__GMP_DECLSPEC int mpn_sec_invert (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_bitcnt_t, mp_ptr); +#define mpn_sec_invert_itch __MPN(sec_invert_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_invert_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; /**************** mpz inlines ****************/ @@ -1658,7 +1733,7 @@ __GMP_EXTERN_INLINE int mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW { - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_UINT_MAX); + __GMPZ_FITS_UTYPE_P (__gmp_z, UINT_MAX); } #endif @@ -1669,7 +1744,7 @@ __GMP_EXTERN_INLINE int mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW { - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_ULONG_MAX); + __GMPZ_FITS_UTYPE_P (__gmp_z, ULONG_MAX); } #endif @@ -1680,7 +1755,7 @@ __GMP_EXTERN_INLINE int mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW { - __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_USHRT_MAX); + __GMPZ_FITS_UTYPE_P (__gmp_z, USHRT_MAX); } #endif @@ -1697,7 +1772,7 @@ mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland C++ 6.0 warnings about condition always true for something like - "__GMP_ULONG_MAX < GMP_NUMB_MASK". */ + "ULONG_MAX < GMP_NUMB_MASK". */ #if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) /* limb==long and no nails, or limb==longlong, one limb is enough */ return (__gmp_n != 0 ? __gmp_l : 0); @@ -1758,14 +1833,14 @@ mpz_perfect_square_p (mpz_srcptr __gmp_a) #if ! defined (__GMP_FORCE_mpz_popcount) __GMP_EXTERN_INLINE #endif -unsigned long +mp_bitcnt_t mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW { mp_size_t __gmp_usize; - unsigned long __gmp_result; + mp_bitcnt_t __gmp_result; __gmp_usize = __gmp_u->_mp_size; - __gmp_result = (__gmp_usize < 0 ? __GMP_ULONG_MAX : 0); + __gmp_result = (__gmp_usize < 0 ? ULONG_MAX : 0); if (__GMP_LIKELY (__gmp_usize > 0)) __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); return __gmp_result; @@ -2088,6 +2163,22 @@ mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOT } #endif +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_zero_p) +#if ! defined (__GMP_FORCE_mpn_zero_p) +__GMP_EXTERN_INLINE +#endif +int +mpn_zero_p (mp_srcptr __gmp_p, mp_size_t __gmp_n) __GMP_NOTHROW +{ + /* if (__GMP_LIKELY (__gmp_n > 0)) */ + do { + if (__gmp_p[--__gmp_n] != 0) + return 0; + } while (__gmp_n != 0); + return 1; +} +#endif + #if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) #if ! defined (__GMP_FORCE_mpn_sub) __GMP_EXTERN_INLINE @@ -2114,21 +2205,27 @@ mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_ } #endif -#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_neg_n) -#if ! defined (__GMP_FORCE_mpn_neg_n) +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_neg) +#if ! defined (__GMP_FORCE_mpn_neg) __GMP_EXTERN_INLINE #endif mp_limb_t -mpn_neg_n (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) +mpn_neg (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) { - mp_limb_t __gmp_ul, __gmp_cy; - __gmp_cy = 0; - do { - __gmp_ul = *__gmp_up++; - *__gmp_rp++ = -__gmp_ul - __gmp_cy; - __gmp_cy |= __gmp_ul != 0; - } while (--__gmp_n != 0); - return __gmp_cy; + while (*__gmp_up == 0) /* Low zero limbs are unchanged by negation. */ + { + *__gmp_rp = 0; + if (!--__gmp_n) /* All zero */ + return 0; + ++__gmp_up; ++__gmp_rp; + } + + *__gmp_rp = (- *__gmp_up) & GMP_NUMB_MASK; + + if (--__gmp_n) /* Higher limbs get complemented. */ + mpn_com (++__gmp_rp, ++__gmp_up, __gmp_n); + + return 1; } #endif @@ -2147,17 +2244,18 @@ mpn_neg_n (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) #define mpz_cmp_ui(Z,UI) \ (__builtin_constant_p (UI) && (UI) == 0 \ ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) -#define mpz_cmp_si(Z,SI) \ - (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ - : __builtin_constant_p (SI) && (SI) > 0 \ - ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ +#define mpz_cmp_si(Z,SI) \ + (__builtin_constant_p ((SI) >= 0) && (SI) >= 0 \ + ? mpz_cmp_ui (Z, __GMP_CAST (unsigned long, SI)) \ : _mpz_cmp_si (Z,SI)) -#define mpq_cmp_ui(Q,NUI,DUI) \ - (__builtin_constant_p (NUI) && (NUI) == 0 \ - ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) -#define mpq_cmp_si(q,n,d) \ - (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ - ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 ? mpq_sgn (Q) \ + : __builtin_constant_p ((NUI) == (DUI)) && (NUI) == (DUI) \ + ? mpz_cmp (mpq_numref (Q), mpq_denref (Q)) \ + : _mpq_cmp_ui (Q,NUI,DUI)) +#define mpq_cmp_si(q,n,d) \ + (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ + ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ : _mpq_cmp_si (q, n, d)) #else #define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) @@ -2218,13 +2316,14 @@ enum }; /* Define CC and CFLAGS which were used to build this version of GMP */ -#define __GMP_CC "gcc -std=gnu99" -#define __GMP_CFLAGS "-O2 -pedantic -m64 -mtune=core2" +#define __GMP_CC "gcc" +#define __GMP_CFLAGS "-O2 -pedantic -fomit-frame-pointer -m64 -mtune=skylake -march=broadwell" -/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */ -#define __GNU_MP_VERSION 4 -#define __GNU_MP_VERSION_MINOR 3 +/* Major version number is the value of __GNU_MP__ too, above. */ +#define __GNU_MP_VERSION 6 +#define __GNU_MP_VERSION_MINOR 1 #define __GNU_MP_VERSION_PATCHLEVEL 2 +#define __GNU_MP_RELEASE (__GNU_MP_VERSION * 10000 + __GNU_MP_VERSION_MINOR * 100 + __GNU_MP_VERSION_PATCHLEVEL) #define __GMP_H__ #endif /* __GMP_H__ */ diff --git a/repos/libports/include/spec/64bit/gmp/jacobitab.h b/repos/libports/include/spec/64bit/gmp/jacobitab.h new file mode 100644 index 000000000..4bdbfcc09 --- /dev/null +++ b/repos/libports/include/spec/64bit/gmp/jacobitab.h @@ -0,0 +1,13 @@ + 0, 0, 0, 0, 0,12, 8, 4, 1, 1, 1, 1, 1,13, 9, 5, + 2, 2, 2, 2, 2, 6,10,14, 3, 3, 3, 3, 3, 7,11,15, + 4,16, 6,18, 4, 0,12, 8, 5,17, 7,19, 5, 1,13, 9, + 6,18, 4,16, 6,10,14, 2, 7,19, 5,17, 7,11,15, 3, + 8,10, 9,11, 8, 4, 0,12, 9,11, 8,10, 9, 5, 1,13, +10, 9,11, 8,10,14, 2, 6,11, 8,10, 9,11,15, 3, 7, +12,22,24,20,12, 8, 4, 0,13,23,25,21,13, 9, 5, 1, +25,21,13,23,14, 2, 6,10,24,20,12,22,15, 3, 7,11, +16, 6,18, 4,16,16,16,16,17, 7,19, 5,17,17,17,17, +18, 4,16, 6,18,22,19,23,19, 5,17, 7,19,23,18,22, +20,12,22,24,20,20,20,20,21,13,23,25,21,21,21,21, +22,24,20,12,22,19,23,18,23,25,21,13,23,18,22,19, +24,20,12,22,15, 3, 7,11,25,21,13,23,14, 2, 6,10, diff --git a/repos/libports/include/spec/64bit/gmp/trialdivtab.h b/repos/libports/include/spec/64bit/gmp/trialdivtab.h new file mode 100644 index 000000000..eb81d7f0a --- /dev/null +++ b/repos/libports/include/spec/64bit/gmp/trialdivtab.h @@ -0,0 +1,1214 @@ +#if GMP_LIMB_BITS != 64 +#error This table is for GMP_LIMB_BITS = 64 +#endif + +#if GMP_NAIL_BITS != 0 +#error This table does not support nails +#endif + +#ifdef WANT_dtab + P(3,CNST_LIMB(0xaaaaaaaaaaaaaaab),CNST_LIMB(0x5555555555555555)), + P(5,CNST_LIMB(0xcccccccccccccccd),CNST_LIMB(0x3333333333333333)), + P(7,CNST_LIMB(0x6db6db6db6db6db7),CNST_LIMB(0x2492492492492492)), + P(11,CNST_LIMB(0x2e8ba2e8ba2e8ba3),CNST_LIMB(0x1745d1745d1745d1)), + P(13,CNST_LIMB(0x4ec4ec4ec4ec4ec5),CNST_LIMB(0x13b13b13b13b13b1)), + P(17,CNST_LIMB(0xf0f0f0f0f0f0f0f1),CNST_LIMB(0xf0f0f0f0f0f0f0f)), + P(19,CNST_LIMB(0x86bca1af286bca1b),CNST_LIMB(0xd79435e50d79435)), + P(23,CNST_LIMB(0xd37a6f4de9bd37a7),CNST_LIMB(0xb21642c8590b216)), + P(29,CNST_LIMB(0x34f72c234f72c235),CNST_LIMB(0x8d3dcb08d3dcb08)), + P(31,CNST_LIMB(0xef7bdef7bdef7bdf),CNST_LIMB(0x842108421084210)), + P(37,CNST_LIMB(0x14c1bacf914c1bad),CNST_LIMB(0x6eb3e45306eb3e4)), + P(41,CNST_LIMB(0x8f9c18f9c18f9c19),CNST_LIMB(0x63e7063e7063e70)), + P(43,CNST_LIMB(0x82fa0be82fa0be83),CNST_LIMB(0x5f417d05f417d05)), + P(47,CNST_LIMB(0x51b3bea3677d46cf),CNST_LIMB(0x572620ae4c415c9)), + P(53,CNST_LIMB(0x21cfb2b78c13521d),CNST_LIMB(0x4d4873ecade304d)), + P(59,CNST_LIMB(0xcbeea4e1a08ad8f3),CNST_LIMB(0x456c797dd49c341)), + P(61,CNST_LIMB(0x4fbcda3ac10c9715),CNST_LIMB(0x4325c53ef368eb0)), + P(67,CNST_LIMB(0xf0b7672a07a44c6b),CNST_LIMB(0x3d226357e16ece5)), + P(71,CNST_LIMB(0x193d4bb7e327a977),CNST_LIMB(0x39b0ad12073615a)), + P(73,CNST_LIMB(0x7e3f1f8fc7e3f1f9),CNST_LIMB(0x381c0e070381c0e)), + P(79,CNST_LIMB(0x9b8b577e613716af),CNST_LIMB(0x33d91d2a2067b23)), + P(83,CNST_LIMB(0xa3784a062b2e43db),CNST_LIMB(0x3159721ed7e7534)), + P(89,CNST_LIMB(0xf47e8fd1fa3f47e9),CNST_LIMB(0x2e05c0b81702e05)), + P(97,CNST_LIMB(0xa3a0fd5c5f02a3a1),CNST_LIMB(0x2a3a0fd5c5f02a3)), + P(101,CNST_LIMB(0x3a4c0a237c32b16d),CNST_LIMB(0x288df0cac5b3f5d)), + P(103,CNST_LIMB(0xdab7ec1dd3431b57),CNST_LIMB(0x27c45979c95204f)), + P(107,CNST_LIMB(0x77a04c8f8d28ac43),CNST_LIMB(0x2647c69456217ec)), + P(109,CNST_LIMB(0xa6c0964fda6c0965),CNST_LIMB(0x2593f69b02593f6)), + P(113,CNST_LIMB(0x90fdbc090fdbc091),CNST_LIMB(0x243f6f0243f6f02)), + P(127,CNST_LIMB(0x7efdfbf7efdfbf7f),CNST_LIMB(0x204081020408102)), + P(131,CNST_LIMB(0x3e88cb3c9484e2b),CNST_LIMB(0x1f44659e4a42715)), + P(137,CNST_LIMB(0xe21a291c077975b9),CNST_LIMB(0x1de5d6e3f8868a4)), + P(139,CNST_LIMB(0x3aef6ca970586723),CNST_LIMB(0x1d77b654b82c339)), + P(149,CNST_LIMB(0xdf5b0f768ce2cabd),CNST_LIMB(0x1b7d6c3dda338b2)), + P(151,CNST_LIMB(0x6fe4dfc9bf937f27),CNST_LIMB(0x1b2036406c80d90)), + P(157,CNST_LIMB(0x5b4fe5e92c0685b5),CNST_LIMB(0x1a16d3f97a4b01a)), + P(163,CNST_LIMB(0x1f693a1c451ab30b),CNST_LIMB(0x1920fb49d0e228d)), + P(167,CNST_LIMB(0x8d07aa27db35a717),CNST_LIMB(0x1886e5f0abb0499)), + P(173,CNST_LIMB(0x882383b30d516325),CNST_LIMB(0x17ad2208e0ecc35)), + P(179,CNST_LIMB(0xed6866f8d962ae7b),CNST_LIMB(0x16e1f76b4337c6c)), + P(181,CNST_LIMB(0x3454dca410f8ed9d),CNST_LIMB(0x16a13cd15372904)), + P(191,CNST_LIMB(0x1d7ca632ee936f3f),CNST_LIMB(0x1571ed3c506b39a)), + P(193,CNST_LIMB(0x70bf015390948f41),CNST_LIMB(0x15390948f40feac)), + P(197,CNST_LIMB(0xc96bdb9d3d137e0d),CNST_LIMB(0x14cab88725af6e7)), + P(199,CNST_LIMB(0x2697cc8aef46c0f7),CNST_LIMB(0x149539e3b2d066e)), + P(211,CNST_LIMB(0xc0e8f2a76e68575b),CNST_LIMB(0x13698df3de07479)), + P(223,CNST_LIMB(0x687763dfdb43bb1f),CNST_LIMB(0x125e22708092f11)), + P(227,CNST_LIMB(0x1b10ea929ba144cb),CNST_LIMB(0x120b470c67c0d88)), + P(229,CNST_LIMB(0x1d10c4c0478bbced),CNST_LIMB(0x11e2ef3b3fb8744)), + P(233,CNST_LIMB(0x63fb9aeb1fdcd759),CNST_LIMB(0x119453808ca29c0)), + P(239,CNST_LIMB(0x64afaa4f437b2e0f),CNST_LIMB(0x112358e75d30336)), + P(241,CNST_LIMB(0xf010fef010fef011),CNST_LIMB(0x10fef010fef010f)), + P(251,CNST_LIMB(0x28cbfbeb9a020a33),CNST_LIMB(0x105197f7d734041)), + P(257,CNST_LIMB(0xff00ff00ff00ff01),CNST_LIMB(0xff00ff00ff00ff)), + P(263,CNST_LIMB(0xd624fd1470e99cb7),CNST_LIMB(0xf92fb2211855a8)), + P(269,CNST_LIMB(0x8fb3ddbd6205b5c5),CNST_LIMB(0xf3a0d52cba8723)), + P(271,CNST_LIMB(0xd57da36ca27acdef),CNST_LIMB(0xf1d48bcee0d399)), + P(277,CNST_LIMB(0xee70c03b25e4463d),CNST_LIMB(0xec979118f3fc4d)), + P(281,CNST_LIMB(0xc5b1a6b80749cb29),CNST_LIMB(0xe939651fe2d8d3)), + P(283,CNST_LIMB(0x47768073c9b97113),CNST_LIMB(0xe79372e225fe30)), + P(293,CNST_LIMB(0x2591e94884ce32ad),CNST_LIMB(0xdfac1f74346c57)), + P(307,CNST_LIMB(0xf02806abc74be1fb),CNST_LIMB(0xd578e97c3f5fe5)), + P(311,CNST_LIMB(0x7ec3e8f3a7198487),CNST_LIMB(0xd2ba083b445250)), + P(313,CNST_LIMB(0x58550f8a39409d09),CNST_LIMB(0xd161543e28e502)), + P(317,CNST_LIMB(0xec9e48ae6f71de15),CNST_LIMB(0xcebcf8bb5b4169)), + P(331,CNST_LIMB(0x2ff3a018bfce8063),CNST_LIMB(0xc5fe740317f9d0)), + P(337,CNST_LIMB(0x7f9ec3fcf61fe7b1),CNST_LIMB(0xc2780613c0309e)), + P(347,CNST_LIMB(0x89f5abe570e046d3),CNST_LIMB(0xbcdd535db1cc5b)), + P(349,CNST_LIMB(0xda971b23f1545af5),CNST_LIMB(0xbbc8408cd63069)), + P(353,CNST_LIMB(0x79d5f00b9a7862a1),CNST_LIMB(0xb9a7862a0ff465)), + P(359,CNST_LIMB(0x4dba1df32a128a57),CNST_LIMB(0xb68d31340e4307)), + P(367,CNST_LIMB(0x87530217b7747d8f),CNST_LIMB(0xb2927c29da5519)), + P(373,CNST_LIMB(0x30baae53bb5e06dd),CNST_LIMB(0xafb321a1496fdf)), + P(379,CNST_LIMB(0xee70206c12e9b5b3),CNST_LIMB(0xaceb0f891e6551)), + P(383,CNST_LIMB(0xcdde9462ec9dbe7f),CNST_LIMB(0xab1cbdd3e2970f)), + P(389,CNST_LIMB(0xafb64b05ec41cf4d),CNST_LIMB(0xa87917088e262b)), + P(397,CNST_LIMB(0x2944ff5aec02945),CNST_LIMB(0xa513fd6bb00a51)), + P(401,CNST_LIMB(0x2cb033128382df71),CNST_LIMB(0xa36e71a2cb0331)), + P(409,CNST_LIMB(0x1ccacc0c84b1c2a9),CNST_LIMB(0xa03c1688732b30)), + P(419,CNST_LIMB(0x19a93db575eb3a0b),CNST_LIMB(0x9c69169b30446d)), + P(421,CNST_LIMB(0xcebeef94fa86fe2d),CNST_LIMB(0x9baade8e4a2f6e)), + P(431,CNST_LIMB(0x6faa77fb3f8df54f),CNST_LIMB(0x980e4156201301)), + P(433,CNST_LIMB(0x68a58af00975a751),CNST_LIMB(0x975a750ff68a58)), + P(439,CNST_LIMB(0xd56e36d0c3efac07),CNST_LIMB(0x9548e4979e0829)), + P(443,CNST_LIMB(0xd8b44c47a8299b73),CNST_LIMB(0x93efd1c50e726b)), + P(449,CNST_LIMB(0x2d9ccaf9ba70e41),CNST_LIMB(0x91f5bcb8bb02d9)), + P(457,CNST_LIMB(0x985e1c023d9e879),CNST_LIMB(0x8f67a1e3fdc261)), + P(461,CNST_LIMB(0x2a343316c494d305),CNST_LIMB(0x8e2917e0e702c6)), + P(463,CNST_LIMB(0x70cb7916ab67652f),CNST_LIMB(0x8d8be33f95d715)), + P(467,CNST_LIMB(0xd398f132fb10fe5b),CNST_LIMB(0x8c55841c815ed5)), + P(479,CNST_LIMB(0x6f2a38a6bf54fa1f),CNST_LIMB(0x88d180cd3a4133)), + P(487,CNST_LIMB(0x211df689b98f81d7),CNST_LIMB(0x869222b1acf1ce)), + P(491,CNST_LIMB(0xe994983e90f1ec3),CNST_LIMB(0x85797b917765ab)), + P(499,CNST_LIMB(0xad671e44bed87f3b),CNST_LIMB(0x8355ace3c897db)), + P(503,CNST_LIMB(0xf9623a0516e70fc7),CNST_LIMB(0x824a4e60b3262b)), + P(509,CNST_LIMB(0x4b7129be9dece355),CNST_LIMB(0x80c121b28bd1ba)), + P(521,CNST_LIMB(0x190f3b7473f62c39),CNST_LIMB(0x7dc9f3397d4c29)), + P(523,CNST_LIMB(0x63dacc9aad46f9a3),CNST_LIMB(0x7d4ece8fe88139)), + P(541,CNST_LIMB(0xc1108fda24e8d035),CNST_LIMB(0x79237d65bcce50)), + P(547,CNST_LIMB(0xb77578472319bd8b),CNST_LIMB(0x77cf53c5f7936c)), + P(557,CNST_LIMB(0x473d20a1c7ed9da5),CNST_LIMB(0x75a8accfbdd11e)), + P(563,CNST_LIMB(0xfbe85af0fea2c8fb),CNST_LIMB(0x7467ac557c228e)), + P(569,CNST_LIMB(0x58a1f7e6ce0f4c09),CNST_LIMB(0x732d70ed8db8e9)), + P(571,CNST_LIMB(0x1a00e58c544986f3),CNST_LIMB(0x72c62a24c3797f)), + P(577,CNST_LIMB(0x7194a17f55a10dc1),CNST_LIMB(0x7194a17f55a10d)), + P(587,CNST_LIMB(0x7084944785e33763),CNST_LIMB(0x6fa549b41da7e7)), + P(593,CNST_LIMB(0xba10679bd84886b1),CNST_LIMB(0x6e8419e6f61221)), + P(599,CNST_LIMB(0xebe9c6bb31260967),CNST_LIMB(0x6d68b5356c207b)), + P(601,CNST_LIMB(0x97a3fe4bd1ff25e9),CNST_LIMB(0x6d0b803685c01b)), + P(607,CNST_LIMB(0x6c6388395b84d99f),CNST_LIMB(0x6bf790a8b2d207)), + P(613,CNST_LIMB(0x8c51da6a1335df6d),CNST_LIMB(0x6ae907ef4b96c2)), + P(617,CNST_LIMB(0x46f3234475d5add9),CNST_LIMB(0x6a37991a23aead)), + P(619,CNST_LIMB(0x905605ca3c619a43),CNST_LIMB(0x69dfbdd4295b66)), + P(631,CNST_LIMB(0xcee8dff304767747),CNST_LIMB(0x67dc4c45c8033e)), + P(641,CNST_LIMB(0xff99c27f00663d81),CNST_LIMB(0x663d80ff99c27f)), + P(643,CNST_LIMB(0xacca407f671ddc2b),CNST_LIMB(0x65ec17e3559948)), + P(647,CNST_LIMB(0xe71298bac1e12337),CNST_LIMB(0x654ac835cfba5c)), + P(653,CNST_LIMB(0xfa1e94309cd09045),CNST_LIMB(0x645c854ae10772)), + P(659,CNST_LIMB(0xbebccb8e91496b9b),CNST_LIMB(0x6372990e5f901f)), + P(661,CNST_LIMB(0x312fa30cc7d7b8bd),CNST_LIMB(0x6325913c07beef)), + P(673,CNST_LIMB(0x6160ff9e9f006161),CNST_LIMB(0x6160ff9e9f0061)), + P(677,CNST_LIMB(0x6b03673b5e28152d),CNST_LIMB(0x60cdb520e5e88e)), + P(683,CNST_LIMB(0xfe802ffa00bfe803),CNST_LIMB(0x5ff4017fd005ff)), + P(691,CNST_LIMB(0xe66fe25c9e907c7b),CNST_LIMB(0x5ed79e31a4dccd)), + P(701,CNST_LIMB(0x3f8b236c76528895),CNST_LIMB(0x5d7d42d48ac5ef)), + P(709,CNST_LIMB(0xf6f923bf01ce2c0d),CNST_LIMB(0x5c6f35ccba5028)), + P(719,CNST_LIMB(0x6c3d3d98bed7c42f),CNST_LIMB(0x5b2618ec6ad0a5)), + P(727,CNST_LIMB(0x30981efcd4b010e7),CNST_LIMB(0x5a2553748e42e7)), + P(733,CNST_LIMB(0x6f691fc81ebbe575),CNST_LIMB(0x59686cf744cd5b)), + P(739,CNST_LIMB(0xb10480ddb47b52cb),CNST_LIMB(0x58ae97bab79976)), + P(743,CNST_LIMB(0x74cd59ed64f3f0d7),CNST_LIMB(0x58345f1876865f)), + P(751,CNST_LIMB(0x105cb81316d6c0f),CNST_LIMB(0x5743d5bb24795a)), + P(757,CNST_LIMB(0x9be64c6d91c1195d),CNST_LIMB(0x5692c4d1ab74ab)), + P(761,CNST_LIMB(0x71b3f945a27b1f49),CNST_LIMB(0x561e46a4d5f337)), + P(769,CNST_LIMB(0x77d80d50e508fd01),CNST_LIMB(0x5538ed06533997)), + P(773,CNST_LIMB(0xa5eb778e133551cd),CNST_LIMB(0x54c807f2c0bec2)), + P(787,CNST_LIMB(0x18657d3c2d8a3f1b),CNST_LIMB(0x5345efbc572d36)), + P(797,CNST_LIMB(0x2e40e220c34ad735),CNST_LIMB(0x523a758f941345)), + P(809,CNST_LIMB(0xa76593c70a714919),CNST_LIMB(0x5102370f816c89)), + P(811,CNST_LIMB(0x1eef452124eea383),CNST_LIMB(0x50cf129fb94acf)), + P(821,CNST_LIMB(0x38206dc242ba771d),CNST_LIMB(0x4fd31941cafdd1)), + P(823,CNST_LIMB(0x4cd4c35807772287),CNST_LIMB(0x4fa1704aa75945)), + P(827,CNST_LIMB(0x83de917d5e69ddf3),CNST_LIMB(0x4f3ed6d45a63ad)), + P(829,CNST_LIMB(0x882ef0403b4a6c15),CNST_LIMB(0x4f0de57154ebed)), + P(839,CNST_LIMB(0xf8fb6c51c606b677),CNST_LIMB(0x4e1cae8815f811)), + P(853,CNST_LIMB(0xb4abaac446d3e1fd),CNST_LIMB(0x4cd47ba5f6ff19)), + P(857,CNST_LIMB(0xa9f83bbe484a14e9),CNST_LIMB(0x4c78ae734df709)), + P(859,CNST_LIMB(0xbebbc0d1ce874d3),CNST_LIMB(0x4c4b19ed85cfb8)), + P(863,CNST_LIMB(0xbd418eaf0473189f),CNST_LIMB(0x4bf093221d1218)), + P(877,CNST_LIMB(0x44e3af6f372b7e65),CNST_LIMB(0x4aba3c21dc633f)), + P(881,CNST_LIMB(0xc87fdace4f9e5d91),CNST_LIMB(0x4a6360c344de00)), + P(883,CNST_LIMB(0xec93479c446bd9bb),CNST_LIMB(0x4a383e9f74d68a)), + P(887,CNST_LIMB(0xdac4d592e777c647),CNST_LIMB(0x49e28fbabb9940)), + P(907,CNST_LIMB(0xa63ea8c8f61f0c23),CNST_LIMB(0x48417b57c78cd7)), + P(911,CNST_LIMB(0xe476062ea5cbbb6f),CNST_LIMB(0x47f043713f3a2b)), + P(919,CNST_LIMB(0xdf68761c69daac27),CNST_LIMB(0x474ff2a10281cf)), + P(929,CNST_LIMB(0xb813d737637aa061),CNST_LIMB(0x468b6f9a978f91)), + P(937,CNST_LIMB(0xa3a77aac1fb15099),CNST_LIMB(0x45f13f1caff2e2)), + P(941,CNST_LIMB(0x17f0c3e0712c5825),CNST_LIMB(0x45a5228cec23e9)), + P(947,CNST_LIMB(0xfd912a70ff30637b),CNST_LIMB(0x45342c556c66b9)), + P(953,CNST_LIMB(0xfbb3b5dc01131289),CNST_LIMB(0x44c4a23feeced7)), + P(967,CNST_LIMB(0x856d560a0f5acdf7),CNST_LIMB(0x43c5c20d3c9fe6)), + P(971,CNST_LIMB(0x96472f314d3f89e3),CNST_LIMB(0x437e494b239798)), + P(977,CNST_LIMB(0xa76f5c7ed2253531),CNST_LIMB(0x43142d118e47cb)), + P(983,CNST_LIMB(0x816eae7c7bf69fe7),CNST_LIMB(0x42ab5c73a13458)), + P(991,CNST_LIMB(0xb6a2bea4cfb1781f),CNST_LIMB(0x4221950db0f3db)), + P(997,CNST_LIMB(0xa3900c53318e81ed),CNST_LIMB(0x41bbb2f80a4553)), + P(1009,CNST_LIMB(0x60aa7f5d9f148d11),CNST_LIMB(0x40f391612c6680)), + P(1013,CNST_LIMB(0x6be8c0102c7a505d),CNST_LIMB(0x40b1e94173fefd)), + P(1019,CNST_LIMB(0x8ff3f0ed28728f33),CNST_LIMB(0x4050647d9d0445)), + P(1021,CNST_LIMB(0x680e0a87e5ec7155),CNST_LIMB(0x4030241b144f3b)), + P(1031,CNST_LIMB(0xbbf70fa49fe829b7),CNST_LIMB(0x3f90c2ab542cb1)), + P(1033,CNST_LIMB(0xd69d1e7b6a50ca39),CNST_LIMB(0x3f71412d59f597)), + P(1039,CNST_LIMB(0x1a1e0f46b6d26aef),CNST_LIMB(0x3f137701b98841)), + P(1049,CNST_LIMB(0x7429f9a7a8251829),CNST_LIMB(0x3e79886b60e278)), + P(1051,CNST_LIMB(0xd9c2219d1b863613),CNST_LIMB(0x3e5b1916a7181d)), + P(1061,CNST_LIMB(0x91406c1820d077ad),CNST_LIMB(0x3dc4a50968f524)), + P(1063,CNST_LIMB(0x521f4ec02e3d2b97),CNST_LIMB(0x3da6e4c9550321)), + P(1069,CNST_LIMB(0xbb8283b63dc8eba5),CNST_LIMB(0x3d4e4f06f1def3)), + P(1087,CNST_LIMB(0x431eda153229ebbf),CNST_LIMB(0x3c4a6bdd24f9a4)), + P(1091,CNST_LIMB(0xaf0bf78d7e01686b),CNST_LIMB(0x3c11d54b525c73)), + P(1093,CNST_LIMB(0xa9ced0742c086e8d),CNST_LIMB(0x3bf5b1c5721065)), + P(1097,CNST_LIMB(0xc26458ad9f632df9),CNST_LIMB(0x3bbdb9862f23b4)), + P(1103,CNST_LIMB(0xbbff1255dff892af),CNST_LIMB(0x3b6a8801db5440)), + P(1109,CNST_LIMB(0xcbd49a333f04d8fd),CNST_LIMB(0x3b183cf0fed886)), + P(1117,CNST_LIMB(0xec84ed6f9cfdeff5),CNST_LIMB(0x3aabe394bdc3f4)), + P(1123,CNST_LIMB(0x97980cc40bda9d4b),CNST_LIMB(0x3a5ba3e76156da)), + P(1129,CNST_LIMB(0x777f34d524f5cbd9),CNST_LIMB(0x3a0c3e953378db)), + P(1151,CNST_LIMB(0x2797051d94cbbb7f),CNST_LIMB(0x38f03561320b1e)), + P(1153,CNST_LIMB(0xea769051b4f43b81),CNST_LIMB(0x38d6ecaef5908a)), + P(1163,CNST_LIMB(0xce7910f3034d4323),CNST_LIMB(0x3859cf221e6069)), + P(1171,CNST_LIMB(0x92791d1374f5b99b),CNST_LIMB(0x37f7415dc9588a)), + P(1181,CNST_LIMB(0x89a5645cc68ea1b5),CNST_LIMB(0x377df0d3902626)), + P(1187,CNST_LIMB(0x5f8aacf796c0cf0b),CNST_LIMB(0x373622136907fa)), + P(1193,CNST_LIMB(0xf2e90a15e33edf99),CNST_LIMB(0x36ef0c3b39b92f)), + P(1201,CNST_LIMB(0x8e99e5feb897c451),CNST_LIMB(0x36915f47d55e6d)), + P(1213,CNST_LIMB(0xaca2eda38fb91695),CNST_LIMB(0x36072cf3f866fd)), + P(1217,CNST_LIMB(0x5d9b737be5ea8b41),CNST_LIMB(0x35d9b737be5ea8)), + P(1223,CNST_LIMB(0x4aefe1db93fd7cf7),CNST_LIMB(0x35961559cc81c7)), + P(1229,CNST_LIMB(0xa0994ef20b3f8805),CNST_LIMB(0x35531c897a4592)), + P(1231,CNST_LIMB(0x103890bda912822f),CNST_LIMB(0x353ceebd3e98a4)), + P(1237,CNST_LIMB(0xb441659d13a9147d),CNST_LIMB(0x34fad381585e5e)), + P(1249,CNST_LIMB(0x1e2134440c4c3f21),CNST_LIMB(0x347884d1103130)), + P(1259,CNST_LIMB(0x263a27727a6883c3),CNST_LIMB(0x340dd3ac39bf56)), + P(1277,CNST_LIMB(0x78e221472ab33855),CNST_LIMB(0x3351fdfecc140c)), + P(1279,CNST_LIMB(0x95eac88e82e6faff),CNST_LIMB(0x333d72b089b524)), + P(1283,CNST_LIMB(0xf66c258317be8dab),CNST_LIMB(0x33148d44d6b261)), + P(1289,CNST_LIMB(0x9ee202c7cb91939),CNST_LIMB(0x32d7aef8412458)), + P(1291,CNST_LIMB(0x8d2fca1042a09ea3),CNST_LIMB(0x32c3850e79c0f1)), + P(1297,CNST_LIMB(0x82779c856d8b8bf1),CNST_LIMB(0x328766d59048a2)), + P(1301,CNST_LIMB(0x3879361cba8a223d),CNST_LIMB(0x325fa18cb11833)), + P(1303,CNST_LIMB(0xf23f43639c3182a7),CNST_LIMB(0x324bd659327e22)), + P(1307,CNST_LIMB(0xa03868fc474bcd13),CNST_LIMB(0x32246e784360f4)), + P(1319,CNST_LIMB(0x651e78b8c5311a97),CNST_LIMB(0x31afa5f1a33a08)), + P(1321,CNST_LIMB(0x8ffce639c00c6719),CNST_LIMB(0x319c63ff398e70)), + P(1327,CNST_LIMB(0xf7b460754b0b61cf),CNST_LIMB(0x3162f7519a86a7)), + P(1361,CNST_LIMB(0x7b03f3359b8e63b1),CNST_LIMB(0x30271fc9d3fc3c)), + P(1367,CNST_LIMB(0xa55c5326041eb667),CNST_LIMB(0x2ff104ae89750b)), + P(1373,CNST_LIMB(0x647f88ab896a76f5),CNST_LIMB(0x2fbb62a236d133)), + P(1381,CNST_LIMB(0x8fd971434a55a46d),CNST_LIMB(0x2f74997d2070b4)), + P(1399,CNST_LIMB(0x9fbf969958046447),CNST_LIMB(0x2ed84aa8b6fce3)), + P(1409,CNST_LIMB(0x9986feba69be3a81),CNST_LIMB(0x2e832df7a46dbd)), + P(1423,CNST_LIMB(0xa668b3e6d053796f),CNST_LIMB(0x2e0e0846857cab)), + P(1427,CNST_LIMB(0x97694e6589f4e09b),CNST_LIMB(0x2decfbdfb55ee6)), + P(1429,CNST_LIMB(0x37890c00b7721dbd),CNST_LIMB(0x2ddc876f3ff488)), + P(1433,CNST_LIMB(0x5ac094a235f37ea9),CNST_LIMB(0x2dbbc1d4c482c4)), + P(1439,CNST_LIMB(0x31cff775f2d5d65f),CNST_LIMB(0x2d8af0e0de0556)), + P(1447,CNST_LIMB(0xddad8e6b36505217),CNST_LIMB(0x2d4a7b7d14b30a)), + P(1451,CNST_LIMB(0x5a27df897062cd03),CNST_LIMB(0x2d2a85073bcf4e)), + P(1453,CNST_LIMB(0xe2396fe0fdb5a625),CNST_LIMB(0x2d1a9ab13e8be4)), + P(1459,CNST_LIMB(0xb352a4957e82317b),CNST_LIMB(0x2ceb1eb4b9fd8b)), + P(1471,CNST_LIMB(0xd8ab3f2c60c2ea3f),CNST_LIMB(0x2c8d503a79794c)), + P(1481,CNST_LIMB(0x6893f702f0452479),CNST_LIMB(0x2c404d708784ed)), + P(1483,CNST_LIMB(0x9686fdc182acf7e3),CNST_LIMB(0x2c31066315ec52)), + P(1487,CNST_LIMB(0x6854037173dce12f),CNST_LIMB(0x2c1297d80f2664)), + P(1489,CNST_LIMB(0x7f0ded1685c27331),CNST_LIMB(0x2c037044c55f6b)), + P(1493,CNST_LIMB(0xeeda72e1fe490b7d),CNST_LIMB(0x2be5404cd13086)), + P(1499,CNST_LIMB(0x9e7bfc959a8e6e53),CNST_LIMB(0x2bb845adaf0cce)), + P(1511,CNST_LIMB(0x49b314d6d4753dd7),CNST_LIMB(0x2b5f62c639f16d)), + P(1523,CNST_LIMB(0x2e8f8c5ac4aa1b3b),CNST_LIMB(0x2b07e6734f2b88)), + P(1531,CNST_LIMB(0xb8ef723481163d33),CNST_LIMB(0x2ace569d8342b7)), + P(1543,CNST_LIMB(0x6a2ec96a594287b7),CNST_LIMB(0x2a791d5dbd4dcf)), + P(1549,CNST_LIMB(0xdba41c6d13aab8c5),CNST_LIMB(0x2a4eff8113017c)), + P(1553,CNST_LIMB(0xc2adbe648dc3aaf1),CNST_LIMB(0x2a3319e156df32)), + P(1559,CNST_LIMB(0x87a2bade565f91a7),CNST_LIMB(0x2a0986286526ea)), + P(1567,CNST_LIMB(0x4d6fe8798c01f5df),CNST_LIMB(0x29d29551d91e39)), + P(1571,CNST_LIMB(0x3791310c8c23d98b),CNST_LIMB(0x29b7529e109f0a)), + P(1579,CNST_LIMB(0xf80e446b01228883),CNST_LIMB(0x298137491ea465)), + P(1583,CNST_LIMB(0x9aed1436fbf500cf),CNST_LIMB(0x29665e1eb9f9da)), + P(1597,CNST_LIMB(0x7839b54cc8b24115),CNST_LIMB(0x2909752e019a5e)), + P(1601,CNST_LIMB(0xc128c646ad0309c1),CNST_LIMB(0x28ef35e2e5efb0)), + P(1607,CNST_LIMB(0x14de631624a3c377),CNST_LIMB(0x28c815aa4b8278)), + P(1609,CNST_LIMB(0x3f7b9fe68b0ecbf9),CNST_LIMB(0x28bb1b867199da)), + P(1613,CNST_LIMB(0x284ffd75ec00a285),CNST_LIMB(0x28a13ff5d7b002)), + P(1619,CNST_LIMB(0x37803cb80dea2ddb),CNST_LIMB(0x287ab3f173e755)), + P(1621,CNST_LIMB(0x86b63f7c9ac4c6fd),CNST_LIMB(0x286dead67713bd)), + P(1627,CNST_LIMB(0x8b6851d1bd99b9d3),CNST_LIMB(0x2847bfcda6503e)), + P(1637,CNST_LIMB(0xb62fda77ca343b6d),CNST_LIMB(0x2808c1ea6b4777)), + P(1657,CNST_LIMB(0x1f0dc009e34383c9),CNST_LIMB(0x278d0e0f23ff61)), + P(1663,CNST_LIMB(0x496dc21ddd35b97f),CNST_LIMB(0x2768863c093c7f)), + P(1667,CNST_LIMB(0xb0e96ce17090f82b),CNST_LIMB(0x27505115a73ca8)), + P(1669,CNST_LIMB(0xaadf05acdd7d024d),CNST_LIMB(0x274441a61dc1b9)), + P(1693,CNST_LIMB(0xcb138196746eafb5),CNST_LIMB(0x26b5c166113cf0)), + P(1697,CNST_LIMB(0x347f523736755d61),CNST_LIMB(0x269e65ad07b18e)), + P(1699,CNST_LIMB(0xd14a48a051f7dd0b),CNST_LIMB(0x2692c25f877560)), + P(1709,CNST_LIMB(0x474d71b1ce914d25),CNST_LIMB(0x2658fa7523cd11)), + P(1721,CNST_LIMB(0x386063f5e28c1f89),CNST_LIMB(0x26148710cf0f9e)), + P(1723,CNST_LIMB(0x1db7325e32d04e73),CNST_LIMB(0x2609363b22524f)), + P(1733,CNST_LIMB(0xfef748d3893b880d),CNST_LIMB(0x25d1065a1c1122)), + P(1741,CNST_LIMB(0x2f3351506e935605),CNST_LIMB(0x25a48a382b863f)), + P(1747,CNST_LIMB(0x7a3637fa2376415b),CNST_LIMB(0x25837190eccdbc)), + P(1753,CNST_LIMB(0x4ac525d2baa21969),CNST_LIMB(0x256292e95d510c)), + P(1759,CNST_LIMB(0x3a11c16b42cd351f),CNST_LIMB(0x2541eda98d068c)), + P(1777,CNST_LIMB(0x6c7abde0049c2a11),CNST_LIMB(0x24e15087fed8f5)), + P(1783,CNST_LIMB(0x54dad0303e069ac7),CNST_LIMB(0x24c18b20979e5d)), + P(1787,CNST_LIMB(0xebf1ac9fdfe91433),CNST_LIMB(0x24ac7b336de0c5)), + P(1789,CNST_LIMB(0xfafdda8237cec655),CNST_LIMB(0x24a1fc478c60bb)), + P(1801,CNST_LIMB(0xdce3ff6e71ffb739),CNST_LIMB(0x2463801231c009)), + P(1811,CNST_LIMB(0xbed5737d6286db1b),CNST_LIMB(0x24300fd506ed33)), + P(1823,CNST_LIMB(0xe479e431fe08b4df),CNST_LIMB(0x23f314a494da81)), + P(1831,CNST_LIMB(0x9dd9b0dd7742f897),CNST_LIMB(0x23cadedd2fad3a)), + P(1847,CNST_LIMB(0x8f09d7402c5a5e87),CNST_LIMB(0x237b7ed2664a03)), + P(1861,CNST_LIMB(0x9216d5c4d958738d),CNST_LIMB(0x23372967dbaf1d)), + P(1867,CNST_LIMB(0xb3139ba11d34ca63),CNST_LIMB(0x231a308a371f20)), + P(1871,CNST_LIMB(0x47d54f7ed644afaf),CNST_LIMB(0x2306fa63e1e600)), + P(1873,CNST_LIMB(0x92a81d85cf11a1b1),CNST_LIMB(0x22fd6731575684)), + P(1877,CNST_LIMB(0x754b26533253bdfd),CNST_LIMB(0x22ea507805749c)), + P(1879,CNST_LIMB(0xbbe0efc980bfd467),CNST_LIMB(0x22e0cce8b3d720)), + P(1889,CNST_LIMB(0xc0d8d594f024dca1),CNST_LIMB(0x22b1887857d161)), + P(1901,CNST_LIMB(0x8238d43bcaac1a65),CNST_LIMB(0x227977fcc49cc0)), + P(1907,CNST_LIMB(0x27779c1fae6175bb),CNST_LIMB(0x225db37b5e5f4f)), + P(1913,CNST_LIMB(0xa746ca9af708b2c9),CNST_LIMB(0x22421b91322ed6)), + P(1931,CNST_LIMB(0x93f3cd9f389be823),CNST_LIMB(0x21f05b35f52102)), + P(1933,CNST_LIMB(0x5cb4a4c04c489345),CNST_LIMB(0x21e75de5c70d60)), + P(1949,CNST_LIMB(0xbf6047743e85b6b5),CNST_LIMB(0x21a01d6c19be96)), + P(1951,CNST_LIMB(0x61c147831563545f),CNST_LIMB(0x21974a6615c81a)), + P(1973,CNST_LIMB(0xedb47c0ae62dee9d),CNST_LIMB(0x213767697cf36a)), + P(1979,CNST_LIMB(0xa3824386673a573),CNST_LIMB(0x211d9f7fad35f1)), + P(1987,CNST_LIMB(0xa4a77d19e575a0eb),CNST_LIMB(0x20fb7d9dd36c18)), + P(1993,CNST_LIMB(0xa2bee045e066c279),CNST_LIMB(0x20e2123d661e0e)), + P(1997,CNST_LIMB(0xc23618de8ab43d05),CNST_LIMB(0x20d135b66ae990)), + P(1999,CNST_LIMB(0x266b515216cb9f2f),CNST_LIMB(0x20c8cded4d7a8e)), + P(2003,CNST_LIMB(0xe279edd9e9c2e85b),CNST_LIMB(0x20b80b3f43ddbf)), + P(2011,CNST_LIMB(0xd0c591c221dc9c53),CNST_LIMB(0x2096b9180f46a6)), + P(2017,CNST_LIMB(0x6da8ee9c9ee7c21),CNST_LIMB(0x207de7e28de5da)), + P(2027,CNST_LIMB(0x9dfebcaf4c27e8c3),CNST_LIMB(0x2054dec8cf1fb3)), + P(2029,CNST_LIMB(0x49aeff9f19dd6de5),CNST_LIMB(0x204cb630b3aab5)), + P(2039,CNST_LIMB(0x86976a57a296e9c7),CNST_LIMB(0x202428adc37beb)), + P(2053,CNST_LIMB(0xa3b9abf4872b84cd),CNST_LIMB(0x1fec0c7834def4)), + P(2063,CNST_LIMB(0x34fca6483895e6ef),CNST_LIMB(0x1fc46fae98a1d0)), + P(2069,CNST_LIMB(0x34b5a333988f873d),CNST_LIMB(0x1facda430ff619)), + P(2081,CNST_LIMB(0xd9dd4f19b5f17be1),CNST_LIMB(0x1f7e17dd8e15e5)), + P(2083,CNST_LIMB(0xb935b507fd0ce78b),CNST_LIMB(0x1f765a3556a4ee)), + P(2087,CNST_LIMB(0xb450f5540660e797),CNST_LIMB(0x1f66ea49d802f1)), + P(2089,CNST_LIMB(0x63ff82831ffc1419),CNST_LIMB(0x1f5f3800faf9c0)), + P(2099,CNST_LIMB(0x8992f718c22a32fb),CNST_LIMB(0x1f38f4e6c0f1f9)), + P(2111,CNST_LIMB(0x5f3253ad0d37e7bf),CNST_LIMB(0x1f0b8546752578)), + P(2113,CNST_LIMB(0x7c0ffe0fc007c1),CNST_LIMB(0x1f03ff83f001f0)), + P(2129,CNST_LIMB(0x4d8ebadc0c0640b1),CNST_LIMB(0x1ec853b0a3883c)), + P(2131,CNST_LIMB(0xe2729af831037bdb),CNST_LIMB(0x1ec0ee573723eb)), + P(2137,CNST_LIMB(0xb8f64bf30feebfe9),CNST_LIMB(0x1eaad38e6f6894)), + P(2141,CNST_LIMB(0xda93124b544c0bf5),CNST_LIMB(0x1e9c28a765fe53)), + P(2143,CNST_LIMB(0x9cf7ff0b593c539f),CNST_LIMB(0x1e94d8758c2003)), + P(2153,CNST_LIMB(0xd6bd8861fa0e07d9),CNST_LIMB(0x1e707ba8f65e68)), + P(2161,CNST_LIMB(0x5cfe75c0bd8ab891),CNST_LIMB(0x1e53a2a68f574e)), + P(2179,CNST_LIMB(0x43e808757c2e862b),CNST_LIMB(0x1e1380a56b438d)), + P(2203,CNST_LIMB(0x90caa96d595c9d93),CNST_LIMB(0x1dbf9f513a3802)), + P(2207,CNST_LIMB(0x8fd550625d07135f),CNST_LIMB(0x1db1d1d58bc600)), + P(2213,CNST_LIMB(0x76b010a86e209f2d),CNST_LIMB(0x1d9d358f53de38)), + P(2221,CNST_LIMB(0xecc0426447769b25),CNST_LIMB(0x1d81e6df6165c7)), + P(2237,CNST_LIMB(0xe381339caabe3295),CNST_LIMB(0x1d4bdf7fd40e30)), + P(2239,CNST_LIMB(0xd1b190a2d0c7673f),CNST_LIMB(0x1d452c7a1c958d)), + P(2243,CNST_LIMB(0xc3bce3cf26b0e7eb),CNST_LIMB(0x1d37cf9b902659)), + P(2251,CNST_LIMB(0x5f87e76f56c61ce3),CNST_LIMB(0x1d1d3a5791e97b)), + P(2267,CNST_LIMB(0xc06c6857a124b353),CNST_LIMB(0x1ce89fe6b47416)), + P(2269,CNST_LIMB(0x38c040fcba630f75),CNST_LIMB(0x1ce219f3235071)), + P(2273,CNST_LIMB(0xd078bc4fbd533b21),CNST_LIMB(0x1cd516dcf92139)), + P(2281,CNST_LIMB(0xde8e15c5dd354f59),CNST_LIMB(0x1cbb33bd1c2b8b)), + P(2287,CNST_LIMB(0xca61d53d7414260f),CNST_LIMB(0x1ca7e7d2546688)), + P(2293,CNST_LIMB(0xb56bf5ba8eae635d),CNST_LIMB(0x1c94b5c1b3dbd3)), + P(2297,CNST_LIMB(0x44a72cb0fb6e3949),CNST_LIMB(0x1c87f7f9c241c1)), + P(2309,CNST_LIMB(0x879839a714f45bcd),CNST_LIMB(0x1c6202706c35a9)), + P(2311,CNST_LIMB(0x2a8994fde5314b7),CNST_LIMB(0x1c5bb8a9437632)), + P(2333,CNST_LIMB(0xb971920cf2b90135),CNST_LIMB(0x1c174343b4111e)), + P(2339,CNST_LIMB(0x8a8fd0b7df9a6e8b),CNST_LIMB(0x1c04d0d3e46b42)), + P(2341,CNST_LIMB(0xb31f9a84c1c6eaad),CNST_LIMB(0x1bfeb00fbf4308)), + P(2347,CNST_LIMB(0x92293b02823c6d83),CNST_LIMB(0x1bec5dce0b202d)), + P(2351,CNST_LIMB(0xeee77ff20fe5ddcf),CNST_LIMB(0x1be03444620037)), + P(2357,CNST_LIMB(0xe1ea0f6c496c11d),CNST_LIMB(0x1bce09c66f6fc3)), + P(2371,CNST_LIMB(0xfdf2d3d6f88ccb6b),CNST_LIMB(0x1ba40228d02b30)), + P(2377,CNST_LIMB(0xfa9d74a3457738f9),CNST_LIMB(0x1b9225b1cf8919)), + P(2381,CNST_LIMB(0xefc3ca3db71a5785),CNST_LIMB(0x1b864a2ff3f53f)), + P(2383,CNST_LIMB(0x8e2071718d0d6daf),CNST_LIMB(0x1b80604150e49b)), + P(2389,CNST_LIMB(0xbc0fdbfeb6cfabfd),CNST_LIMB(0x1b6eb1aaeaacf3)), + P(2393,CNST_LIMB(0x1eeab613e5e5aee9),CNST_LIMB(0x1b62f48da3c8cc)), + P(2399,CNST_LIMB(0x2d2388e90e9e929f),CNST_LIMB(0x1b516babe96092)), + P(2411,CNST_LIMB(0x81dbafba588ddb43),CNST_LIMB(0x1b2e9cef1e0c87)), + P(2417,CNST_LIMB(0x52eebc51c4799791),CNST_LIMB(0x1b1d56bedc849b)), + P(2423,CNST_LIMB(0x1c6bc4693b45a047),CNST_LIMB(0x1b0c267546aec0)), + P(2437,CNST_LIMB(0x6eee0974498874d),CNST_LIMB(0x1ae45f62024fa0)), + P(2441,CNST_LIMB(0xd85b7377a9953cb9),CNST_LIMB(0x1ad917631b5f54)), + P(2447,CNST_LIMB(0x4b6df412d4caf56f),CNST_LIMB(0x1ac83d18cb608f)), + P(2459,CNST_LIMB(0x6b8afbbb4a053493),CNST_LIMB(0x1aa6c7ad8c063f)), + P(2467,CNST_LIMB(0xcc5299c96ac7720b),CNST_LIMB(0x1a90a7b1228e2a)), + P(2473,CNST_LIMB(0xadce84b5c710aa99),CNST_LIMB(0x1a8027c03ba059)), + P(2477,CNST_LIMB(0x9d673f5aa3804225),CNST_LIMB(0x1a7533289deb89)), + P(2503,CNST_LIMB(0xe6541268efbce7f7),CNST_LIMB(0x1a2ed7ce16b49f)), + P(2521,CNST_LIMB(0xfcf41e76cf5be669),CNST_LIMB(0x19fefc0a279a73)), + P(2531,CNST_LIMB(0x5c3eb5dc31c383cb),CNST_LIMB(0x19e4b0cd873b5f)), + P(2539,CNST_LIMB(0x301832d11d8ad6c3),CNST_LIMB(0x19cfcdfd60e514)), + P(2543,CNST_LIMB(0x2e9c0942f1ce450f),CNST_LIMB(0x19c56932d66c85)), + P(2549,CNST_LIMB(0x97f3f2be37a39a5d),CNST_LIMB(0x19b5e1ab6fc7c2)), + P(2551,CNST_LIMB(0xe8b7d8a9654187c7),CNST_LIMB(0x19b0b8a62f2a73)), + P(2557,CNST_LIMB(0xb5d024d7da5b1b55),CNST_LIMB(0x19a149fc98942c)), + P(2579,CNST_LIMB(0xb8ba9d6e7ae3501b),CNST_LIMB(0x1969517ec25b85)), + P(2591,CNST_LIMB(0xf50865f71b90f1df),CNST_LIMB(0x194b3083360ba8)), + P(2593,CNST_LIMB(0x739c1682847df9e1),CNST_LIMB(0x194631f4bebdc1)), + P(2609,CNST_LIMB(0xc470a4d842b90ed1),CNST_LIMB(0x191e84127268fd)), + P(2617,CNST_LIMB(0x1fb1be11698cc409),CNST_LIMB(0x190adbb543984f)), + P(2621,CNST_LIMB(0xd8d5512a7cd35d15),CNST_LIMB(0x1901130bd18200)), + P(2633,CNST_LIMB(0xa5496821723e07f9),CNST_LIMB(0x18e3e6b889ac94)), + P(2647,CNST_LIMB(0xbcc8c6d7abaa8167),CNST_LIMB(0x18c233420e1ec1)), + P(2657,CNST_LIMB(0x52c396c95eb619a1),CNST_LIMB(0x18aa5872d92bd6)), + P(2659,CNST_LIMB(0x6eb7e380878ec74b),CNST_LIMB(0x18a5989945ccf9)), + P(2663,CNST_LIMB(0x3d5513b504537157),CNST_LIMB(0x189c1e60b57f60)), + P(2671,CNST_LIMB(0x314391f8862e948f),CNST_LIMB(0x18893fbc8690b9)), + P(2677,CNST_LIMB(0xdc0b17cfcd81f5dd),CNST_LIMB(0x187b2bb3e1041c)), + P(2683,CNST_LIMB(0x2f6bea3ec89044b3),CNST_LIMB(0x186d27c9cdcfb8)), + P(2687,CNST_LIMB(0xce13a05869f1b57f),CNST_LIMB(0x1863d8bf4f2c1c)), + P(2689,CNST_LIMB(0x7593474e8ace3581),CNST_LIMB(0x185f33e2ad7593)), + P(2693,CNST_LIMB(0x7fc329295a05e4d),CNST_LIMB(0x1855ef75973e13)), + P(2699,CNST_LIMB(0xb05377cba4908d23),CNST_LIMB(0x1848160153f134)), + P(2707,CNST_LIMB(0xe7b2131a628aa39b),CNST_LIMB(0x1835b72e6f0656)), + P(2711,CNST_LIMB(0x9031dbed7de01527),CNST_LIMB(0x182c922d83eb39)), + P(2713,CNST_LIMB(0x76844b1c670aa9a9),CNST_LIMB(0x18280243c0365a)), + P(2719,CNST_LIMB(0x6a03f4533b08915f),CNST_LIMB(0x181a5cd5898e73)), + P(2729,CNST_LIMB(0x1dbca579db0a3999),CNST_LIMB(0x1803c0961773aa)), + P(2731,CNST_LIMB(0x2ffe800bffa003),CNST_LIMB(0x17ff4005ffd001)), + P(2741,CNST_LIMB(0x478ab1a3e936139d),CNST_LIMB(0x17e8d670433edb)), + P(2749,CNST_LIMB(0x66e722bc4c5cc095),CNST_LIMB(0x17d7066cf4bb5d)), + P(2753,CNST_LIMB(0x7a8f63c717278541),CNST_LIMB(0x17ce285b806b1f)), + P(2767,CNST_LIMB(0xdf6eee24d292bc2f),CNST_LIMB(0x17af52cdf27e02)), + P(2777,CNST_LIMB(0x9fc20d17237dd569),CNST_LIMB(0x17997d47d01039)), + P(2789,CNST_LIMB(0xcdf9932356bda2ed),CNST_LIMB(0x177f7ec2c6d0ba)), + P(2791,CNST_LIMB(0x97b5e332e80f68d7),CNST_LIMB(0x177b2f3cd00756)), + P(2797,CNST_LIMB(0x46eee26fd875e2e5),CNST_LIMB(0x176e4a22f692a0)), + P(2801,CNST_LIMB(0x3548a8e65157a611),CNST_LIMB(0x1765b94271e11b)), + P(2803,CNST_LIMB(0xc288d03be9b71e3b),CNST_LIMB(0x1761732b044ae4)), + P(2819,CNST_LIMB(0x8151186db38937ab),CNST_LIMB(0x173f7a5300a2bc)), + P(2833,CNST_LIMB(0x7800b910895a45f1),CNST_LIMB(0x1722112b48be1f)), + P(2837,CNST_LIMB(0xaee0b024182eec3d),CNST_LIMB(0x1719b7a16eb843)), + P(2843,CNST_LIMB(0x96323eda173b5713),CNST_LIMB(0x170d3c99cc5052)), + P(2851,CNST_LIMB(0xed0dbd03ae77c8b),CNST_LIMB(0x16fcad7aed3bb6)), + P(2857,CNST_LIMB(0xf73800b7828dc119),CNST_LIMB(0x16f051b8231ffd)), + P(2861,CNST_LIMB(0x1b61715ec22b7ca5),CNST_LIMB(0x16e81beae20643)), + P(2879,CNST_LIMB(0xa8533a991ead64bf),CNST_LIMB(0x16c3721584c1d8)), + P(2887,CNST_LIMB(0x7f6c7290e46c2e77),CNST_LIMB(0x16b34c2ba09663)), + P(2897,CNST_LIMB(0x6325e8d907b01db1),CNST_LIMB(0x169f3ce292ddcd)), + P(2903,CNST_LIMB(0x28909f70152a1067),CNST_LIMB(0x169344b2220a0d)), + P(2909,CNST_LIMB(0xea7077af0997a0f5),CNST_LIMB(0x1687592593c1b1)), + P(2917,CNST_LIMB(0x7e605cad10c32e6d),CNST_LIMB(0x167787f1418ec9)), + P(2927,CNST_LIMB(0x471b33570635b38f),CNST_LIMB(0x1663e190395ff2)), + P(2939,CNST_LIMB(0xab559fa997a61bb3),CNST_LIMB(0x164c7a4b6eb5b3)), + P(2953,CNST_LIMB(0xad4bdae562bddab9),CNST_LIMB(0x16316a061182fd)), + P(2957,CNST_LIMB(0x55e1b2f2ed62f45),CNST_LIMB(0x1629ba914584e4)), + P(2963,CNST_LIMB(0x3cd328b1a2dca9b),CNST_LIMB(0x161e3d57de21b2)), + P(2969,CNST_LIMB(0xd28f4e08733218a9),CNST_LIMB(0x1612cc01b977f0)), + P(2971,CNST_LIMB(0xb6800b077f186293),CNST_LIMB(0x160efe30c525ff)), + P(2999,CNST_LIMB(0x6fbd138c3fd9c207),CNST_LIMB(0x15da45249ec5de)), + P(3001,CNST_LIMB(0xb117ccd12ae88a89),CNST_LIMB(0x15d68ab4acff92)), + P(3011,CNST_LIMB(0x2f1a1a044046bceb),CNST_LIMB(0x15c3f989d1eb15)), + P(3019,CNST_LIMB(0x548aba0b060541e3),CNST_LIMB(0x15b535ad11b8f0)), + P(3023,CNST_LIMB(0xcf4e808cea111b2f),CNST_LIMB(0x15addb3f424ec1)), + P(3037,CNST_LIMB(0xdbec1b4fa855a475),CNST_LIMB(0x159445cb91be6b)), + P(3041,CNST_LIMB(0xe3f794eb600d7821),CNST_LIMB(0x158d0199771e63)), + P(3049,CNST_LIMB(0x34fae0d9a11f7c59),CNST_LIMB(0x157e87d9b69e04)), + P(3061,CNST_LIMB(0xf006b0ccbbac085d),CNST_LIMB(0x1568f58bc01ac3)), + P(3067,CNST_LIMB(0x3f45076dc3114733),CNST_LIMB(0x155e3c993fda9b)), + P(3079,CNST_LIMB(0xeef49bfa58a1a1b7),CNST_LIMB(0x1548eacc5e1e6e)), + P(3083,CNST_LIMB(0x12c4218bea691fa3),CNST_LIMB(0x1541d8f91ba6a7)), + P(3089,CNST_LIMB(0xbc7504e3bd5e64f1),CNST_LIMB(0x153747060cc340)), + P(3109,CNST_LIMB(0x4ee21c292bb92fad),CNST_LIMB(0x1514569f93f7c4)), + P(3119,CNST_LIMB(0x34338b7327a4bacf),CNST_LIMB(0x150309705d3d79)), + P(3121,CNST_LIMB(0x3fe5c0833d6fccd1),CNST_LIMB(0x14ff97020cf5bf)), + P(3137,CNST_LIMB(0xb1e70743535203c1),CNST_LIMB(0x14e42c114cf47e)), + P(3163,CNST_LIMB(0xefbb5dcdfb4e43d3),CNST_LIMB(0x14b835bdcb6447)), + P(3167,CNST_LIMB(0xca68467ca5394f9f),CNST_LIMB(0x14b182b53a9ab7)), + P(3169,CNST_LIMB(0x8c51c081408b97a1),CNST_LIMB(0x14ae2ad094a3d3)), + P(3181,CNST_LIMB(0x3275a899dfa5dd65),CNST_LIMB(0x149a320ea59f96)), + P(3187,CNST_LIMB(0x9e674cb62e1b78bb),CNST_LIMB(0x1490441de1a2fb)), + P(3191,CNST_LIMB(0xa37ff5bb2a998d47),CNST_LIMB(0x1489aacce57200)), + P(3203,CNST_LIMB(0x792a999db131a22b),CNST_LIMB(0x1475f82ad6ff99)), + P(3209,CNST_LIMB(0x1b48841bc30d29b9),CNST_LIMB(0x146c2cfe53204f)), + P(3217,CNST_LIMB(0xf06721d2011d3471),CNST_LIMB(0x145f2ca490d4a1)), + P(3221,CNST_LIMB(0x93fd2386dff85ebd),CNST_LIMB(0x1458b2aae0ec87)), + P(3229,CNST_LIMB(0x4ce72f54c07ed9b5),CNST_LIMB(0x144bcb0a3a3150)), + P(3251,CNST_LIMB(0xd6d0fd3e71dd827b),CNST_LIMB(0x1428a1e65441d4)), + P(3253,CNST_LIMB(0x856405fb1eed819d),CNST_LIMB(0x142575a6c210d7)), + P(3257,CNST_LIMB(0x8ea8aceb7c443989),CNST_LIMB(0x141f2025ba5c46)), + P(3259,CNST_LIMB(0x34a13026f62e5873),CNST_LIMB(0x141bf6e35420fd)), + P(3271,CNST_LIMB(0x1eea0208ec0af4f7),CNST_LIMB(0x1409141d1d313a)), + P(3299,CNST_LIMB(0x63679853cea598cb),CNST_LIMB(0x13dd8bc19c3513)), + P(3301,CNST_LIMB(0xc30b3ebd61f2d0ed),CNST_LIMB(0x13da76f714dc8f)), + P(3307,CNST_LIMB(0x7eb9037bc7f43bc3),CNST_LIMB(0x13d13e50f8f49e)), + P(3313,CNST_LIMB(0xa583e6f6ce016411),CNST_LIMB(0x13c80e37ca3819)), + P(3319,CNST_LIMB(0xf1938d895f1a74c7),CNST_LIMB(0x13bee69fa99ccf)), + P(3323,CNST_LIMB(0x80cf1491c1e81e33),CNST_LIMB(0x13b8d0ede55835)), + P(3329,CNST_LIMB(0x3c0f12886ba8f301),CNST_LIMB(0x13afb7680bb054)), + P(3331,CNST_LIMB(0xe4b786e0dfcc5ab),CNST_LIMB(0x13acb0c3841c96)), + P(3343,CNST_LIMB(0x672684c93f2d41ef),CNST_LIMB(0x139a9c5f434fde)), + P(3347,CNST_LIMB(0xe00757badb35c51b),CNST_LIMB(0x13949cf33a0d9d)), + P(3359,CNST_LIMB(0xd6d84afe66472edf),CNST_LIMB(0x1382b4a00c31b0)), + P(3361,CNST_LIMB(0xfbbc0eedcbbfb6e1),CNST_LIMB(0x137fbbc0eedcbb)), + P(3371,CNST_LIMB(0x250f43aa08a84983),CNST_LIMB(0x1370ecf047b069)), + P(3373,CNST_LIMB(0x4400e927b1acaa5),CNST_LIMB(0x136df9790e3155)), + P(3389,CNST_LIMB(0x56572be34b9d3215),CNST_LIMB(0x13567dd8defd5b)), + P(3391,CNST_LIMB(0x87964ef7781c62bf),CNST_LIMB(0x13539261fdbc34)), + P(3407,CNST_LIMB(0x29ed84051c06e9af),CNST_LIMB(0x133c564292d28a)), + P(3413,CNST_LIMB(0xb00acd11ed3f87fd),CNST_LIMB(0x1333ae178d6388)), + P(3433,CNST_LIMB(0x6307881744152d9),CNST_LIMB(0x13170ad00d1fd7)), + P(3449,CNST_LIMB(0x7a786459f5c1ccc9),CNST_LIMB(0x13005f01db0947)), + P(3457,CNST_LIMB(0x1308125d74563281),CNST_LIMB(0x12f51d40342210)), + P(3461,CNST_LIMB(0x395310a480b3e34d),CNST_LIMB(0x12ef815e4ed950)), + P(3463,CNST_LIMB(0x35985baa8b202837),CNST_LIMB(0x12ecb4abccd827)), + P(3467,CNST_LIMB(0x96304a6e052b3223),CNST_LIMB(0x12e71dc1d3d820)), + P(3469,CNST_LIMB(0xbd8265fc9af8fd45),CNST_LIMB(0x12e45389a16495)), + P(3491,CNST_LIMB(0x1b6d0b383ec58e0b),CNST_LIMB(0x12c5d9226476cc)), + P(3499,CNST_LIMB(0xc21a7c3b68b28503),CNST_LIMB(0x12badc391156fd)), + P(3511,CNST_LIMB(0x236fa180fbfd6007),CNST_LIMB(0x12aa78e412f522)), + P(3517,CNST_LIMB(0xc42accd440ed9595),CNST_LIMB(0x12a251f5f47fd1)), + P(3527,CNST_LIMB(0x7acf7128236ba3f7),CNST_LIMB(0x1294cb85c53534)), + P(3529,CNST_LIMB(0xf909367a987b9c79),CNST_LIMB(0x12921963beb65e)), + P(3533,CNST_LIMB(0xb64efb252bfba705),CNST_LIMB(0x128cb777c69ca8)), + P(3539,CNST_LIMB(0x980d4f5a7e4cd25b),CNST_LIMB(0x1284aa6cf07294)), + P(3541,CNST_LIMB(0xe1ecc4ef27b0c37d),CNST_LIMB(0x1281fcf6ac7f87)), + P(3547,CNST_LIMB(0x9111aebb81d72653),CNST_LIMB(0x1279f937367db9)), + P(3557,CNST_LIMB(0x8951f985cb2c67ed),CNST_LIMB(0x126cad0488be94)), + P(3559,CNST_LIMB(0xc439d4fc54e0b5d7),CNST_LIMB(0x126a06794646a2)), + P(3571,CNST_LIMB(0xe857bf31896d533b),CNST_LIMB(0x125a2f2bcd3e95)), + P(3581,CNST_LIMB(0xb614bb4cb5023755),CNST_LIMB(0x124d108389e6b1)), + P(3583,CNST_LIMB(0x938a89e5473bf1ff),CNST_LIMB(0x124a73083771ac)), + P(3593,CNST_LIMB(0xeac481aca34de039),CNST_LIMB(0x123d6acda0620a)), + P(3607,CNST_LIMB(0x14b961badf4809a7),CNST_LIMB(0x122b4b2917eafd)), + P(3613,CNST_LIMB(0x76784fecba352435),CNST_LIMB(0x122391bfce1e2f)), + P(3617,CNST_LIMB(0xefa689bb58aef5e1),CNST_LIMB(0x121e6f1ea579f2)), + P(3623,CNST_LIMB(0xb2b2c4db9c3a8197),CNST_LIMB(0x1216c09e471568)), + P(3631,CNST_LIMB(0x2503bc992279f8cf),CNST_LIMB(0x120c8cb9d93909)), + P(3637,CNST_LIMB(0xd2ab9aec5ca1541d),CNST_LIMB(0x1204ed58e64ef9)), + P(3643,CNST_LIMB(0x3e78ba1460f99af3),CNST_LIMB(0x11fd546578f00c)), + P(3659,CNST_LIMB(0xa01426572cfcb63),CNST_LIMB(0x11e9310b8b4c9c)), + P(3671,CNST_LIMB(0xbea857968f3cbd67),CNST_LIMB(0x11da3405db9911)), + P(3673,CNST_LIMB(0x78db213eefe659e9),CNST_LIMB(0x11d7b6f4eb055d)), + P(3677,CNST_LIMB(0x963e8541a74d35f5),CNST_LIMB(0x11d2bee748c145)), + P(3691,CNST_LIMB(0x9e22d152776f2e43),CNST_LIMB(0x11c1706ddce7a7)), + P(3697,CNST_LIMB(0x5d10d39d1e1f291),CNST_LIMB(0x11ba0fed2a4f14)), + P(3701,CNST_LIMB(0x374468dccaced1dd),CNST_LIMB(0x11b528538ed64a)), + P(3709,CNST_LIMB(0x8d145c7d110c5ad5),CNST_LIMB(0x11ab61404242ac)), + P(3719,CNST_LIMB(0x3251a39f5acb5737),CNST_LIMB(0x119f378ce81d2f)), + P(3727,CNST_LIMB(0xa66e50171443506f),CNST_LIMB(0x1195889ece79da)), + P(3733,CNST_LIMB(0x124f69ad91dd4cbd),CNST_LIMB(0x118e4c65387077)), + P(3739,CNST_LIMB(0xec24f8f2a61a2793),CNST_LIMB(0x1187161d70e725)), + P(3761,CNST_LIMB(0xb472148e656b7a51),CNST_LIMB(0x116cd6d1c85239)), + P(3767,CNST_LIMB(0xadf9570e1142f07),CNST_LIMB(0x1165bbe7ce86b1)), + P(3769,CNST_LIMB(0x89bf33b065119789),CNST_LIMB(0x11635ee344ce36)), + P(3779,CNST_LIMB(0x8f0149803cb291eb),CNST_LIMB(0x11579767b6d679)), + P(3793,CNST_LIMB(0x8334b63afd190a31),CNST_LIMB(0x114734711e2b54)), + P(3797,CNST_LIMB(0x920908d50d6aba7d),CNST_LIMB(0x11428b90147f05)), + P(3803,CNST_LIMB(0x57d8b018c5a33d53),CNST_LIMB(0x113b92f3021636)), + P(3821,CNST_LIMB(0xea1773092dc27ee5),CNST_LIMB(0x1126cabc886884)), + P(3823,CNST_LIMB(0xcae5f38b7bf2e00f),CNST_LIMB(0x11247eb1b85976)), + P(3833,CNST_LIMB(0x2bd02df34f695349),CNST_LIMB(0x11190bb01efd65)), + P(3847,CNST_LIMB(0xddfecd5be62e2eb7),CNST_LIMB(0x11091de0fd679c)), + P(3851,CNST_LIMB(0xdbf849ebec96c4a3),CNST_LIMB(0x1104963c7e4e0b)), + P(3853,CNST_LIMB(0xda31d4d0187357c5),CNST_LIMB(0x110253516420b0)), + P(3863,CNST_LIMB(0xe34e21cc2d5418a7),CNST_LIMB(0x10f70db7c41797)), + P(3877,CNST_LIMB(0x68ca5137a9e574ad),CNST_LIMB(0x10e75ee2bf9ecd)), + P(3881,CNST_LIMB(0x3eaa0d0f804bfd19),CNST_LIMB(0x10e2e91c6e0676)), + P(3889,CNST_LIMB(0x554fb753cc20e9d1),CNST_LIMB(0x10da049b9d428d)), + P(3907,CNST_LIMB(0x797afcca1300756b),CNST_LIMB(0x10c6248fe3b1a2)), + P(3911,CNST_LIMB(0x8b8d950b52eeea77),CNST_LIMB(0x10c1c03ed690eb)), + P(3917,CNST_LIMB(0xfb6cd166acabc185),CNST_LIMB(0x10bb2e1379e3a2)), + P(3919,CNST_LIMB(0x4eb6c5ed9437a7af),CNST_LIMB(0x10b8fe7f61228e)), + P(3923,CNST_LIMB(0xd1eddbd91b790cdb),CNST_LIMB(0x10b4a10d60a4f7)), + P(3929,CNST_LIMB(0x93d714ea4d8948e9),CNST_LIMB(0x10ae192681ec0f)), + P(3931,CNST_LIMB(0x3ca13ed8145188d3),CNST_LIMB(0x10abecfbe5b0ae)), + P(3943,CNST_LIMB(0x829086016da89c57),CNST_LIMB(0x109eefd568b96d)), + P(3947,CNST_LIMB(0xd7da1f432124a543),CNST_LIMB(0x109a9ff178b40c)), + P(3967,CNST_LIMB(0x7ead5581632fb07f),CNST_LIMB(0x108531e22f9ff9)), + P(3989,CNST_LIMB(0x35443837f63ec3bd),CNST_LIMB(0x106ddec1af4417)), + P(4001,CNST_LIMB(0x89e2b200e5519461),CNST_LIMB(0x10614174a4911d)), + P(4003,CNST_LIMB(0xe9ae44f0b7289c0b),CNST_LIMB(0x105f291f0448e7)), + P(4007,CNST_LIMB(0x94387a277b9fa817),CNST_LIMB(0x105afa0ef32891)), + P(4013,CNST_LIMB(0xc84f1a58abfc2c25),CNST_LIMB(0x1054b777bd2530)), + P(4019,CNST_LIMB(0x71101d8e3c83377b),CNST_LIMB(0x104e79a97fb69e)), + P(4021,CNST_LIMB(0xc024abe5c50ba69d),CNST_LIMB(0x104c661eafd845)), + P(4027,CNST_LIMB(0x15de4eb365a65d73),CNST_LIMB(0x10462ea939c933)), + P(4049,CNST_LIMB(0x9ed28a76bcca931),CNST_LIMB(0x102f8baa442836)), + P(4051,CNST_LIMB(0x816bffbf4a00205b),CNST_LIMB(0x102d7ff7e94004)), + P(4057,CNST_LIMB(0x1f5c71543d558069),CNST_LIMB(0x10275ff9f13c02)), + P(4073,CNST_LIMB(0xf25c64d0ec53b859),CNST_LIMB(0x1017213fcbb4d3)), + P(4079,CNST_LIMB(0x96c02c2ef1e0ff0f),CNST_LIMB(0x101112234579d1)), + P(4091,CNST_LIMB(0x19a804816870a333),CNST_LIMB(0x100501907d271c)), + P(4093,CNST_LIMB(0x6de49add0971c555),CNST_LIMB(0x100300901b0510)), + P(4099,CNST_LIMB(0x528087e684c71aab),CNST_LIMB(0xffd008fe5050f)), + P(4111,CNST_LIMB(0xa94152c269bcdeef),CNST_LIMB(0xff10e02dd5084)), + P(4127,CNST_LIMB(0x379450a3c2b6bdf),CNST_LIMB(0xfe13b9c80c67f)), + P(4129,CNST_LIMB(0xd2cd38bafe5373e1),CNST_LIMB(0xfdf4384be37ad)), + P(4133,CNST_LIMB(0xc29df2bea71d8bad),CNST_LIMB(0xfdb54cbe8766e)), + P(4139,CNST_LIMB(0xc15862775f302e83),CNST_LIMB(0xfd5725ca6ff32)), + P(4153,CNST_LIMB(0x1016af2fe55ede09),CNST_LIMB(0xfc7c84684c6fb)), + P(4157,CNST_LIMB(0x3d26dbd9d1910715),CNST_LIMB(0xfc3e5265dbaa8)), + P(4159,CNST_LIMB(0x621dab2dfaf3dfbf),CNST_LIMB(0xfc1f44e0cae12)), + P(4177,CNST_LIMB(0xb6f1d7ac287338b1),CNST_LIMB(0xfb0921c50a7af)), + P(4201,CNST_LIMB(0x8d9e9f0c3f9e7fd9),CNST_LIMB(0xf999fd70cbc6b)), + P(4211,CNST_LIMB(0x60a93f8762e914bb),CNST_LIMB(0xf9023fd5339d0)), + P(4217,CNST_LIMB(0xb14371f247c159c9),CNST_LIMB(0xf8a78ce671475)), + P(4219,CNST_LIMB(0x6dd3b484471d4eb3),CNST_LIMB(0xf8895fee86574)), + P(4229,CNST_LIMB(0xcd172f4701c1684d),CNST_LIMB(0xf7f2ecb084b10)), + P(4231,CNST_LIMB(0x372e686ed8bb537),CNST_LIMB(0xf7d4eb7d10c29)), + P(4241,CNST_LIMB(0xbc07f7ca65c5b071),CNST_LIMB(0xf73f52277a3c3)), + P(4243,CNST_LIMB(0xab2b6170c3f78d9b),CNST_LIMB(0xf7217c598961c)), + P(4253,CNST_LIMB(0xf3d74f461fe6f5b5),CNST_LIMB(0xf68cbb1448f42)), + P(4259,CNST_LIMB(0xdbc13f4b31f3230b),CNST_LIMB(0xf633d0276e4c5)), + P(4261,CNST_LIMB(0xd1420716e3f1572d),CNST_LIMB(0xf6163ac20ec79)), + P(4271,CNST_LIMB(0xd5be2fd4d805464f),CNST_LIMB(0xf582ba2bc16c6)), + P(4273,CNST_LIMB(0xc68b97c136943851),CNST_LIMB(0xf5654f43290a0)), + P(4283,CNST_LIMB(0x9e27918af7cfb473),CNST_LIMB(0xf4d2a23810bc6)), + P(4289,CNST_LIMB(0x5ec8ab6c36ac7f41),CNST_LIMB(0xf47af4d6a2f27)), + P(4297,CNST_LIMB(0x964076331dd90979),CNST_LIMB(0xf4066f2b6e652)), + P(4327,CNST_LIMB(0x30198eff77b002d7),CNST_LIMB(0xf2555048e3a92)), + P(4337,CNST_LIMB(0x3af7cb9583ece011),CNST_LIMB(0xf1c64588a5bf6)), + P(4339,CNST_LIMB(0x34ce06f643d9883b),CNST_LIMB(0xf1a9be09cb411)), + P(4349,CNST_LIMB(0x79f767e528708c55),CNST_LIMB(0xf11b7d5259d39)), + P(4357,CNST_LIMB(0x185332d2ef2313cd),CNST_LIMB(0xf0aa284e7f802)), + P(4363,CNST_LIMB(0x43b611b84c8332a3),CNST_LIMB(0xf0556e5e3b7f2)), + P(4373,CNST_LIMB(0xc2e215e4f43bb63d),CNST_LIMB(0xefc8bcbc808e5)), + P(4391,CNST_LIMB(0xf94b9dd22ce44e97),CNST_LIMB(0xeecd1a690efbb)), + P(4397,CNST_LIMB(0xd895834a1db166a5),CNST_LIMB(0xee79aed6d65f2)), + P(4409,CNST_LIMB(0x347d2f16d19b8d09),CNST_LIMB(0xedd386114d83a)), + P(4421,CNST_LIMB(0x1b54d4dc45b7d98d),CNST_LIMB(0xed2e44366e5e2)), + P(4423,CNST_LIMB(0x117ac30d9a044877),CNST_LIMB(0xed12cf8e17f64)), + P(4441,CNST_LIMB(0xe10b78a67a526e9),CNST_LIMB(0xec1cd284b2b2d)), + P(4447,CNST_LIMB(0x92da68a818688a9f),CNST_LIMB(0xebcb44cadda1e)), + P(4451,CNST_LIMB(0xcf2b6c87f741f84b),CNST_LIMB(0xeb9505943771d)), + P(4457,CNST_LIMB(0xd264f9bd41e18ed9),CNST_LIMB(0xeb43d57efeadc)), + P(4463,CNST_LIMB(0x733cbeaa97166d8f),CNST_LIMB(0xeaf2dd4c00b03)), + P(4481,CNST_LIMB(0xc9f475b021d22e81),CNST_LIMB(0xea0141c1ba6a6)), + P(4483,CNST_LIMB(0x731f76f2ec4c852b),CNST_LIMB(0xe9e68805f05a7)), + P(4493,CNST_LIMB(0xdaf6f0c978f69945),CNST_LIMB(0xe96142b87e431)), + P(4507,CNST_LIMB(0x749c8ad20c61ec93),CNST_LIMB(0xe8a7acd811b8c)), + P(4513,CNST_LIMB(0x9307ff8bd3c1261),CNST_LIMB(0xe8587db3e001d)), + P(4517,CNST_LIMB(0x334a69fb5a486e2d),CNST_LIMB(0xe823d186d44dc)), + P(4519,CNST_LIMB(0x1f36c7bf31578617),CNST_LIMB(0xe8098463ee194)), + P(4523,CNST_LIMB(0x31ebbcc279ea6103),CNST_LIMB(0xe7d4fbfb3ee1d)), + P(4547,CNST_LIMB(0x42e2aad119f466eb),CNST_LIMB(0xe69bba6981ffa)), + P(4549,CNST_LIMB(0x106ec05a0ab1450d),CNST_LIMB(0xe681c5cf7d707)), + P(4561,CNST_LIMB(0xb1b38db92a99e731),CNST_LIMB(0xe5e684930e334)), + P(4567,CNST_LIMB(0x784ae377e67071e7),CNST_LIMB(0xe5993247dc92d)), + P(4583,CNST_LIMB(0x3e9e1471ba6671d7),CNST_LIMB(0xe4cbfee201016)), + P(4591,CNST_LIMB(0x82c29b59d4d73d0f),CNST_LIMB(0xe465ee7daf979)), + P(4597,CNST_LIMB(0xc23dd07128b5525d),CNST_LIMB(0xe4199de07af5c)), + P(4603,CNST_LIMB(0x4d4e5ce0e9245133),CNST_LIMB(0xe3cd8031d4f40)), + P(4621,CNST_LIMB(0xc8fd1057c09f8cc5),CNST_LIMB(0xe2ea56c157eb2)), + P(4637,CNST_LIMB(0xea1516e94f394035),CNST_LIMB(0xe221e5d4d3c73)), + P(4639,CNST_LIMB(0xb5e3319c564ee9df),CNST_LIMB(0xe208f09a841c7)), + P(4643,CNST_LIMB(0x126a69f90d822d8b),CNST_LIMB(0xe1d716a945161)), + P(4649,CNST_LIMB(0x501ed6348857aa19),CNST_LIMB(0xe18c78ec8fd4d)), + P(4651,CNST_LIMB(0xde344a324eee1c83),CNST_LIMB(0xe173a4a162079)), + P(4657,CNST_LIMB(0x1dd9690cb2c406d1),CNST_LIMB(0xe1294881bb494)), + P(4663,CNST_LIMB(0x8d6c5178d5e4387),CNST_LIMB(0xe0df1d5f24661)), + P(4673,CNST_LIMB(0x4cea4050a3e8fdc1),CNST_LIMB(0xe063ec7f50b1e)), + P(4679,CNST_LIMB(0xc114a06acc83f777),CNST_LIMB(0xe01a4313dc53d)), + P(4691,CNST_LIMB(0x20b060ebc0ea01db),CNST_LIMB(0xdf8780f47c350)), + P(4703,CNST_LIMB(0xfe50045acb78c99f),CNST_LIMB(0xdef57e8eb9666)), + P(4721,CNST_LIMB(0x291a68705b196e91),CNST_LIMB(0xde1bdf3f63d46)), + P(4723,CNST_LIMB(0xc1042c724273e2bb),CNST_LIMB(0xde03cb5099809)), + P(4729,CNST_LIMB(0x2cee680bb165b7c9),CNST_LIMB(0xddbbaecc84bc9)), + P(4733,CNST_LIMB(0xfd2ff9f12e0776d5),CNST_LIMB(0xdd8bb5ca73db6)), + P(4751,CNST_LIMB(0x166a5da63af2cc6f),CNST_LIMB(0xdcb4d529a6e07)), + P(4759,CNST_LIMB(0xedd16a5930408d27),CNST_LIMB(0xdc55da73dea60)), + P(4783,CNST_LIMB(0x2adf30c26528844f),CNST_LIMB(0xdb3ad2585011f)), + P(4787,CNST_LIMB(0x9a48d6572b5eec7b),CNST_LIMB(0xdb0becf636a79)), + P(4789,CNST_LIMB(0x6e8bf2877503cb9d),CNST_LIMB(0xdaf481ca6fefb)), + P(4793,CNST_LIMB(0xea27a191a7045389),CNST_LIMB(0xdac5ba7565dae)), + P(4799,CNST_LIMB(0x6eb091f34dd45d3f),CNST_LIMB(0xda7fb4e419d19)), + P(4801,CNST_LIMB(0xdc8a6cabb2937d41),CNST_LIMB(0xda6867a88d327)), + P(4813,CNST_LIMB(0xbc2f04f254922a05),CNST_LIMB(0xd9dd005f50b02)), + P(4817,CNST_LIMB(0x41431f4d6eb38631),CNST_LIMB(0xd9aeb01f763f7)), + P(4831,CNST_LIMB(0x7bd717435a08291f),CNST_LIMB(0xd90d31dd5804a)), + P(4861,CNST_LIMB(0x4232df9c91fc1a55),CNST_LIMB(0xd7b6453358f31)), + P(4871,CNST_LIMB(0xa4651e1d5382eab7),CNST_LIMB(0xd744e69d900e4)), + P(4877,CNST_LIMB(0x7cfb5409de4cf3c5),CNST_LIMB(0xd7011a317260e)), + P(4889,CNST_LIMB(0xcdd636fb068b9929),CNST_LIMB(0xd67a0126e7c19)), + P(4903,CNST_LIMB(0xee8f95e740462c97),CNST_LIMB(0xd5dd39e775bd7)), + P(4909,CNST_LIMB(0x490f97b3a758b4a5),CNST_LIMB(0xd59a4f2990168)), + P(4919,CNST_LIMB(0x641431563c441287),CNST_LIMB(0xd52b24cb6269d)), + P(4931,CNST_LIMB(0xb743dad3ec45916b),CNST_LIMB(0xd4a6571da4f04)), + P(4933,CNST_LIMB(0x7b188be8f55c878d),CNST_LIMB(0xd49044eac6581)), + P(4937,CNST_LIMB(0xd805648b2ca54ef9),CNST_LIMB(0xd4642e40d1129)), + P(4943,CNST_LIMB(0x76dbe6eef60123af),CNST_LIMB(0xd4222e81fe723)), + P(4951,CNST_LIMB(0x3711525e6a9e8867),CNST_LIMB(0xd3ca6e8c89f41)), + P(4957,CNST_LIMB(0x85c2215cb383d8f5),CNST_LIMB(0xd388ce29d4edc)), + P(4967,CNST_LIMB(0xe58f554c89825857),CNST_LIMB(0xd31bc7b7d8013)), + P(4969,CNST_LIMB(0x8fbd3b17c01dacd9),CNST_LIMB(0xd306071c13fd5)), + P(4973,CNST_LIMB(0x4c8c39dc7aedee65),CNST_LIMB(0xd2da935479b1a)), + P(4987,CNST_LIMB(0x653ac6dda86cd3b3),CNST_LIMB(0xd2430aa043597)), + P(4993,CNST_LIMB(0xd61c6791a9c2c81),CNST_LIMB(0xd2025bc6c7db7)), + P(4999,CNST_LIMB(0xb627a30090354237),CNST_LIMB(0xd1c1d4ad1732b)), + P(5003,CNST_LIMB(0x83a89a539c527c23),CNST_LIMB(0xd196e5f46f8c8)), + P(5009,CNST_LIMB(0x28c8c09330e90d71),CNST_LIMB(0xd156a0c9293e8)), + P(5011,CNST_LIMB(0xee1178d27b1f029b),CNST_LIMB(0xd1413d26e0aee)), + P(5021,CNST_LIMB(0xcecc740b37860ab5),CNST_LIMB(0xd0d68c6a4128f)), + P(5023,CNST_LIMB(0x79736fde910c485f),CNST_LIMB(0xd0c142eaf3837)), + P(5039,CNST_LIMB(0x6873d51f2487234f),CNST_LIMB(0xd01792ab9d70d)), + P(5051,CNST_LIMB(0x2a112180614fb973),CNST_LIMB(0xcf990317775bc)), + P(5059,CNST_LIMB(0xcb04cea98508f4eb),CNST_LIMB(0xcf44f8c38790a)), + P(5077,CNST_LIMB(0xc2fcd2c527e28d7d),CNST_LIMB(0xce88d96d10e45)), + P(5081,CNST_LIMB(0x980203ee10393c69),CNST_LIMB(0xce5f39b07e906)), + P(5087,CNST_LIMB(0x3fa90a1d7d75681f),CNST_LIMB(0xce20e98148847)), + P(5099,CNST_LIMB(0xdbf3bfefef217cc3),CNST_LIMB(0xcda4b9c30ccd7)), + P(5101,CNST_LIMB(0x66a17fd3087b41e5),CNST_LIMB(0xcd9015ae32495)), + P(5107,CNST_LIMB(0x962195d496fbbd3b),CNST_LIMB(0xcd524244aca36)), + P(5113,CNST_LIMB(0xc705a86155443e49),CNST_LIMB(0xcd14940099cf6)), + P(5119,CNST_LIMB(0x3f298ee0be6febff),CNST_LIMB(0xccd70ac089a07)), + P(5147,CNST_LIMB(0xaa99b084e62fa613),CNST_LIMB(0xcbb9c535c4371)), + P(5153,CNST_LIMB(0x1f000cb7d0b46fe1),CNST_LIMB(0xcb7d0b46fe0ff)), + P(5167,CNST_LIMB(0x9ed7858637c9b2cf),CNST_LIMB(0xcaefe5d7135f4)), + P(5171,CNST_LIMB(0x4d871aaf27c106fb),CNST_LIMB(0xcac7b5f00f0cd)), + P(5179,CNST_LIMB(0x2e6a467cdc75a4f3),CNST_LIMB(0xca7785ceddbea)), + P(5189,CNST_LIMB(0xe9d938fb696dde8d),CNST_LIMB(0xca13a2a86e1db)), + P(5197,CNST_LIMB(0x40ec71b0b1554485),CNST_LIMB(0xc9c4009753007)), + P(5209,CNST_LIMB(0x3aae12f861e5f3e9),CNST_LIMB(0xc94d02e64bfab)), + P(5227,CNST_LIMB(0xa97565873959f843),CNST_LIMB(0xc89b8c9c875ef)), + P(5231,CNST_LIMB(0xb5a960c09fbca8f),CNST_LIMB(0xc87447737277e)), + P(5233,CNST_LIMB(0x463fe3d268012c91),CNST_LIMB(0xc860aaa2514e3)), + P(5237,CNST_LIMB(0xe59a6bd5f5ee1bdd),CNST_LIMB(0xc8397c813f1b9)), + P(5261,CNST_LIMB(0x6542e84d7775ce45),CNST_LIMB(0xc74fa805d6d56)), + P(5273,CNST_LIMB(0x8b6eef58fd9effa9),CNST_LIMB(0xc6db8a1f5cdfe)), + P(5279,CNST_LIMB(0x58993dbb9f98075f),CNST_LIMB(0xc6a1add9e2398)), + P(5281,CNST_LIMB(0x2997955a810acf61),CNST_LIMB(0xc68e6be826648)), + P(5297,CNST_LIMB(0x76e3d2f5077db451),CNST_LIMB(0xc5f4e25fc9df0)), + P(5303,CNST_LIMB(0xb37c1d2867e30907),CNST_LIMB(0xc5bb8bf2ad1cd)), + P(5309,CNST_LIMB(0x53ce6e09bd8d8695),CNST_LIMB(0xc58256b316ced)), + P(5323,CNST_LIMB(0x39db291ea2a6b0e3),CNST_LIMB(0xc4fd5ad917b5b)), + P(5333,CNST_LIMB(0xddd265ab9c58847d),CNST_LIMB(0xc49ecb3ea4d7a)), + P(5347,CNST_LIMB(0x5beca8562dddd0cb),CNST_LIMB(0xc41b00b7d950a)), + P(5351,CNST_LIMB(0xb69031c153ddbed7),CNST_LIMB(0xc3f57990b87a1)), + P(5381,CNST_LIMB(0xd03c2271b42a6fcd),CNST_LIMB(0xc2ddcb31250f8)), + P(5387,CNST_LIMB(0xcd6fd19e63e40ea3),CNST_LIMB(0xc2a63b3651432)), + P(5393,CNST_LIMB(0xf7687aa8e4fd7bf1),CNST_LIMB(0xc26ecae1db72e)), + P(5399,CNST_LIMB(0x649dfda112a272a7),CNST_LIMB(0xc2377a18c051e)), + P(5407,CNST_LIMB(0xecf7866a56d526df),CNST_LIMB(0xc1ede9efcec29)), + P(5413,CNST_LIMB(0x72bbf1cfdaebfead),CNST_LIMB(0xc1b6e258d13a0)), + P(5417,CNST_LIMB(0x55f6a48df7055719),CNST_LIMB(0xc19243f5399bb)), + P(5419,CNST_LIMB(0x80060bffcfa00183),CNST_LIMB(0xc17ff9f400305)), + P(5431,CNST_LIMB(0x8a104f309919b087),CNST_LIMB(0xc112865703b94)), + P(5437,CNST_LIMB(0x98fa7db7652f6a15),CNST_LIMB(0xc0dbfaea33225)), + P(5441,CNST_LIMB(0x5d7d1b3df70f7ac1),CNST_LIMB(0xc0b7af12ddfb9)), + P(5443,CNST_LIMB(0x16ab7b5e04cc1f6b),CNST_LIMB(0xc0a58e464462c)), + P(5449,CNST_LIMB(0x78a5bfd2e5ececf9),CNST_LIMB(0xc06f40512eef2)), + P(5471,CNST_LIMB(0x6506392e171d869f),CNST_LIMB(0xbfa9275a2b247)), + P(5477,CNST_LIMB(0xc3fc12e221ef146d),CNST_LIMB(0xbf7367402cdf0)), + P(5479,CNST_LIMB(0xf8aa132822c33657),CNST_LIMB(0xbf61833f4f921)), + P(5483,CNST_LIMB(0x894496574f536f43),CNST_LIMB(0xbf3dc543a74a1)), + P(5501,CNST_LIMB(0x8b2546b08fb4cbd5),CNST_LIMB(0xbe9d9302a7115)), + P(5503,CNST_LIMB(0x43bbb561bd1aa7f),CNST_LIMB(0xbe8bd6e051e01)), + P(5507,CNST_LIMB(0x2412c7cc4ea7a12b),CNST_LIMB(0xbe6868804d5a6)), + P(5519,CNST_LIMB(0x6f0bd406dd71696f),CNST_LIMB(0xbdfe6c4359f0e)), + P(5521,CNST_LIMB(0xad475c6988d54b71),CNST_LIMB(0xbdeccdb0b5c3a)), + P(5527,CNST_LIMB(0xd812e5d48dbbba27),CNST_LIMB(0xbdb8058ee429a)), + P(5531,CNST_LIMB(0x22aaca437ba04893),CNST_LIMB(0xbd94e5c1b371f)), + P(5557,CNST_LIMB(0xdba6ff1fecd5f09d),CNST_LIMB(0xbcb1d293b1af3)), + P(5563,CNST_LIMB(0x13016d3396286773),CNST_LIMB(0xbc7db8db0c1a5)), + P(5569,CNST_LIMB(0xc746494631bcfa41),CNST_LIMB(0xbc49bbdfd2662)), + P(5573,CNST_LIMB(0xd14888565bf6a10d),CNST_LIMB(0xbc2723240f402)), + P(5581,CNST_LIMB(0xc002ef885f0adf05),CNST_LIMB(0xbbe217c2b7c13)), + P(5591,CNST_LIMB(0xe5a04da7fee6ade7),CNST_LIMB(0xbb8c10aab27b2)), + P(5623,CNST_LIMB(0xc114ce5468593bc7),CNST_LIMB(0xba7ad528a7e79)), + P(5639,CNST_LIMB(0xbb6747dd7f577b7),CNST_LIMB(0xb9f3611b48c5e)), + P(5641,CNST_LIMB(0x395ce5a20f285839),CNST_LIMB(0xb9e2806e5e7c4)), + P(5647,CNST_LIMB(0x6eee8be66e8618ef),CNST_LIMB(0xb9aff0c4913fe)), + P(5651,CNST_LIMB(0x52acf64297f1241b),CNST_LIMB(0xb98e4aedd581c)), + P(5653,CNST_LIMB(0x361dcc48a364093d),CNST_LIMB(0xb97d7c94b7dc2)), + P(5657,CNST_LIMB(0x342d6f475d72e629),CNST_LIMB(0xb95be902d9d9e)), + P(5659,CNST_LIMB(0x5e978bd46410d413),CNST_LIMB(0xb94b23c872b90)), + P(5669,CNST_LIMB(0xcc3433d75ba015ad),CNST_LIMB(0xb8f77714d15a1)), + P(5683,CNST_LIMB(0x1c83b7628458d4fb),CNST_LIMB(0xb882d0beff6a1)), + P(5689,CNST_LIMB(0xf9ca45637e38f809),CNST_LIMB(0xb850ff9852703)), + P(5693,CNST_LIMB(0xcbed792ffaf6b115),CNST_LIMB(0xb82fd86db8806)), + P(5701,CNST_LIMB(0x9abd961d8c0e8c8d),CNST_LIMB(0xb7edadd32f76c)), + P(5711,CNST_LIMB(0xe69572fa659340af),CNST_LIMB(0xb79b3b4df3b7b)), + P(5717,CNST_LIMB(0x9187e7483a6436fd),CNST_LIMB(0xb769e6d59833f)), + P(5737,CNST_LIMB(0x1e9c726993bed9d9),CNST_LIMB(0xb6c636b5141ff)), + P(5741,CNST_LIMB(0x243554db91976365),CNST_LIMB(0xb6a59ceae8801)), + P(5743,CNST_LIMB(0x4d06ff994c0088f),CNST_LIMB(0xb6955461e38f7)), + P(5749,CNST_LIMB(0x25b76abcb74889dd),CNST_LIMB(0xb6648c2dc6bc2)), + P(5779,CNST_LIMB(0x3a409642893c779b),CNST_LIMB(0xb572282260209)), + P(5783,CNST_LIMB(0x8f8f620d8bc0c927),CNST_LIMB(0xb552072bde889)), + P(5791,CNST_LIMB(0x6f9f196b3369855f),CNST_LIMB(0xb511e7552f9c4)), + P(5801,CNST_LIMB(0x92a522bb0638ed99),CNST_LIMB(0xb4c1ff34a5c0e)), + P(5807,CNST_LIMB(0x96270f1efdd7004f),CNST_LIMB(0xb4922f58d4aa2)), + P(5813,CNST_LIMB(0xb4844b380fdaa79d),CNST_LIMB(0xb46278c16b967)), + P(5821,CNST_LIMB(0x108936aa5f9c1495),CNST_LIMB(0xb42301cd99b49)), + P(5827,CNST_LIMB(0xb60f606f104c9eb),CNST_LIMB(0xb3f385dd77e4e)), + P(5839,CNST_LIMB(0xc663dfe8263b302f),CNST_LIMB(0xb394d8ef8f0f6)), + P(5843,CNST_LIMB(0xc91a280b9110b15b),CNST_LIMB(0xb375601507c14)), + P(5849,CNST_LIMB(0x904287118d10969),CNST_LIMB(0xb3463f76be376)), + P(5851,CNST_LIMB(0x160d36a5d31bf553),CNST_LIMB(0xb3368f6c4a07c)), + P(5857,CNST_LIMB(0xe84f5fda3c67ad21),CNST_LIMB(0xb3078fc1c25f0)), + P(5861,CNST_LIMB(0xbd85701f72d4b6ed),CNST_LIMB(0xb2e84854e93e5)), + P(5867,CNST_LIMB(0x4c50cf5924dee1c3),CNST_LIMB(0xb2b971aa909a4)), + P(5869,CNST_LIMB(0x2455aaf1633bb6e5),CNST_LIMB(0xb2a9da39d6bc8)), + P(5879,CNST_LIMB(0xd775b39f549b8ac7),CNST_LIMB(0xb25c0dc29a0fc)), + P(5881,CNST_LIMB(0x87fcdda7a252cb49),CNST_LIMB(0xb24c8698449a7)), + P(5897,CNST_LIMB(0x53df2e3bd254a739),CNST_LIMB(0xb1d0ae579aefe)), + P(5903,CNST_LIMB(0x8915e69623a5f7ef),CNST_LIMB(0xb1a2698ea2f9e)), + P(5923,CNST_LIMB(0x1ef24c80742dd08b),CNST_LIMB(0xb108dc4186078)), + P(5927,CNST_LIMB(0xb4d87aaa6fb1e897),CNST_LIMB(0xb0ea463b00212)), + P(5939,CNST_LIMB(0x788573e8b92dbbfb),CNST_LIMB(0xb08ec37007962)), + P(5953,CNST_LIMB(0x2527b137b0878c1),CNST_LIMB(0xb024778cc023c)), + P(5981,CNST_LIMB(0x1870a7c8dee9f4f5),CNST_LIMB(0xaf515df36a88e)), + P(5987,CNST_LIMB(0x39b99e40910a224b),CNST_LIMB(0xaf24635f6561e)), + P(6007,CNST_LIMB(0x45821c0abd4df247),CNST_LIMB(0xae8f1b92baeaf)), + P(6011,CNST_LIMB(0x10fe2b2f50e02fb3),CNST_LIMB(0xae715eee11f8e)), + P(6029,CNST_LIMB(0x5762b90c043f0345),CNST_LIMB(0xadec0b0a3bb36)), + P(6037,CNST_LIMB(0x82a67b9193b27bbd),CNST_LIMB(0xadb10aa4c956f)), + P(6043,CNST_LIMB(0xa6e914e28ec37693),CNST_LIMB(0xad84e49752245)), + P(6047,CNST_LIMB(0x835d9a4facaf445f),CNST_LIMB(0xad6782597f0c2)), + P(6053,CNST_LIMB(0x48def8175884f82d),CNST_LIMB(0xad3b81a0d72fe)), + P(6067,CNST_LIMB(0xae900e2d7c9a6f7b),CNST_LIMB(0xacd52beced79e)), + P(6073,CNST_LIMB(0x1c08431bdd18be89),CNST_LIMB(0xaca9755063254)), + P(6079,CNST_LIMB(0xb370a66d684fd83f),CNST_LIMB(0xac7dd4cafb12a)), + P(6089,CNST_LIMB(0xb4be33e18f93b279),CNST_LIMB(0xac354f80dca44)), + P(6091,CNST_LIMB(0x310c50872a7dd5e3),CNST_LIMB(0xac26d5c2b8ad2)), + P(6101,CNST_LIMB(0x447ab1281276697d),CNST_LIMB(0xabde997dabd3d)), + P(6113,CNST_LIMB(0xc2f122216b2a6c21),CNST_LIMB(0xab883aa1100a0)), + P(6121,CNST_LIMB(0xab99c8b5ae1c3059),CNST_LIMB(0xab4ed637f5a0b)), + P(6131,CNST_LIMB(0xb78e17a2227d593b),CNST_LIMB(0xab074e9febf52)), + P(6133,CNST_LIMB(0xabf97d03f7269c5d),CNST_LIMB(0xaaf90778c2039)), + P(6143,CNST_LIMB(0x867aefc9fdbfe7ff),CNST_LIMB(0xaab1c7684f034)), + P(6151,CNST_LIMB(0xf7f7ad182e47d5b7),CNST_LIMB(0xaa78f20ebbb3e)), + P(6163,CNST_LIMB(0x50dff95a9847721b),CNST_LIMB(0xaa23f8dafd4cc)), + P(6173,CNST_LIMB(0xe4cb8a0e83cb6a35),CNST_LIMB(0xa9dd69cad5934)), + P(6197,CNST_LIMB(0x8da72ecdf9247a1d),CNST_LIMB(0xa935004a07302)), + P(6199,CNST_LIMB(0xc5b04bfc87f31d87),CNST_LIMB(0xa9270690f3d14)), + P(6203,CNST_LIMB(0xe2dcf622ea2b00f3),CNST_LIMB(0xa90b1a0aa5d30)), + P(6211,CNST_LIMB(0xb9ce9f2e4972f46b),CNST_LIMB(0xa8d35c9d731e9)), + P(6217,CNST_LIMB(0x1ed785c911bf59f9),CNST_LIMB(0xa8a9a6a51f16c)), + P(6221,CNST_LIMB(0x4ddb8a4eed70e085),CNST_LIMB(0xa88de370f596b)), + P(6229,CNST_LIMB(0x81e93b4df68c24fd),CNST_LIMB(0xa856786adae36)), + P(6247,CNST_LIMB(0xee0d0812afcd8357),CNST_LIMB(0xa7da4c77d3161)), + P(6257,CNST_LIMB(0xf62e3ba72268a891),CNST_LIMB(0xa7959f863d4a1)), + P(6263,CNST_LIMB(0x3194d367c8154147),CNST_LIMB(0xa76c85e80c195)), + P(6269,CNST_LIMB(0xd096ede8e30c20d5),CNST_LIMB(0xa743806dc44c4)), + P(6271,CNST_LIMB(0xd68624d27b87a77f),CNST_LIMB(0xa735d866dfa0a)), + P(6277,CNST_LIMB(0xb728fcdc11c8204d),CNST_LIMB(0xa70cedb02531e)), + P(6287,CNST_LIMB(0x9d6b6038077e066f),CNST_LIMB(0xa6c8e842c770f)), + P(6299,CNST_LIMB(0xaa732d7a4a360d93),CNST_LIMB(0xa67791215dd74)), + P(6301,CNST_LIMB(0x36af98a423972db5),CNST_LIMB(0xa66a0a51d363d)), + P(6311,CNST_LIMB(0xc31d00da12940f17),CNST_LIMB(0xa626893011861)), + P(6317,CNST_LIMB(0xed85352107410b25),CNST_LIMB(0xa5fe22c55c089)), + P(6323,CNST_LIMB(0x829c85ee6db8567b),CNST_LIMB(0xa5d5cffb77275)), + P(6329,CNST_LIMB(0xef60258952cc6d89),CNST_LIMB(0xa5ad90c4186e5)), + P(6337,CNST_LIMB(0xcf28c2e0da787741),CNST_LIMB(0xa578057e7c2eb)), + P(6343,CNST_LIMB(0x57567d8494af28f7),CNST_LIMB(0xa54ff3bb10e91)), + P(6353,CNST_LIMB(0x2c7c98518f174031),CNST_LIMB(0xa50d5683edc94)), + P(6359,CNST_LIMB(0xb28b363a36825ae7),CNST_LIMB(0xa4e57854b3df4)), + P(6361,CNST_LIMB(0xed1ffeb64f9ae769),CNST_LIMB(0xa4d8328c4b800)), + P(6367,CNST_LIMB(0xcbbb0115e9b9a31f),CNST_LIMB(0xa4b06e01d97b3)), + P(6373,CNST_LIMB(0x8d3c5fecb7f9e4ed),CNST_LIMB(0xa488bca2c4449)), + P(6379,CNST_LIMB(0x816271698195cfc3),CNST_LIMB(0xa4611e6132ed5)), + P(6389,CNST_LIMB(0x9ac939d1c2b1d35d),CNST_LIMB(0xa41f40f39e646)), + P(6397,CNST_LIMB(0xdd9fb7017b0ec455),CNST_LIMB(0xa3eab5c3e44e9)), + P(6421,CNST_LIMB(0xc94cab1e57276e3d),CNST_LIMB(0xa34ddd50561e0)), + P(6427,CNST_LIMB(0x8b8806b117c79913),CNST_LIMB(0xa326d60e94186)), + P(6449,CNST_LIMB(0xa9e63292a3269fd1),CNST_LIMB(0xa2985a81ce614)), + P(6451,CNST_LIMB(0x76da5710f1e989fb),CNST_LIMB(0xa28b72e26f82e)), + P(6469,CNST_LIMB(0xdded6688d83a918d),CNST_LIMB(0xa217aa3479693)), + P(6473,CNST_LIMB(0x4e446b6a305428f9),CNST_LIMB(0xa1fe05c62df4b)), + P(6481,CNST_LIMB(0x4ddaca7a3696cfb1),CNST_LIMB(0xa1cad538aebf9)), + P(6491,CNST_LIMB(0x7eadc4eb87f26ed3),CNST_LIMB(0xa18b05f490083)), + P(6521,CNST_LIMB(0x76c13a0ff04c00c9),CNST_LIMB(0xa0ccc4c28fc31)), + P(6529,CNST_LIMB(0xcbf800504d2a2681),CNST_LIMB(0xa09a544d01ffe)), + P(6547,CNST_LIMB(0x731dada6c4fec9b),CNST_LIMB(0xa0294aa53e9a2)), + P(6551,CNST_LIMB(0xbcb52a664e63f627),CNST_LIMB(0xa01041a6aaed5)), + P(6553,CNST_LIMB(0xf1f9abda071c2aa9),CNST_LIMB(0xa003c01680870)), + P(6563,CNST_LIMB(0xf262ffa620ffe20b),CNST_LIMB(0x9fc5558a971c8)), + P(6569,CNST_LIMB(0x93774a3d57199a99),CNST_LIMB(0x9f9ff9c3c03e5)), + P(6571,CNST_LIMB(0xfb3541cd467a1903),CNST_LIMB(0x9f9389b864ab9)), + P(6577,CNST_LIMB(0x6828cab6b4fe8f51),CNST_LIMB(0x9f6e4534bdca8)), + P(6581,CNST_LIMB(0x12ac03e3d624cc9d),CNST_LIMB(0x9f557687235c2)), + P(6599,CNST_LIMB(0x6363bd1e9bb7d7f7),CNST_LIMB(0x9ee633c0391ab)), + P(6607,CNST_LIMB(0x334cfd676a484d2f),CNST_LIMB(0x9eb4f28e0bb39)), + P(6619,CNST_LIMB(0xd511acd86f143a53),CNST_LIMB(0x9e6b49e92e4bb)), + P(6637,CNST_LIMB(0x73fc2490e0062be5),CNST_LIMB(0x9dfd4ccbd0045)), + P(6653,CNST_LIMB(0x10780dda36b78b55),CNST_LIMB(0x9d9c0828536c1)), + P(6659,CNST_LIMB(0xabf601274064e0ab),CNST_LIMB(0x9d77ad449f777)), + P(6661,CNST_LIMB(0x3ef3e4ca27e4a2cd),CNST_LIMB(0x9d6b92b28ee48)), + P(6673,CNST_LIMB(0x9216a26e690a16f1),CNST_LIMB(0x9d231a476ed51)), + P(6679,CNST_LIMB(0xbae4849e6034bda7),CNST_LIMB(0x9cfef711bf120)), + P(6689,CNST_LIMB(0xf943a0520e01e9e1),CNST_LIMB(0x9cc2e1448b765)), + P(6691,CNST_LIMB(0x7c89958f48f6658b),CNST_LIMB(0x9cb6e26cbc64d)), + P(6701,CNST_LIMB(0xe67128750e0545a5),CNST_LIMB(0x9c7b03b4a9c67)), + P(6703,CNST_LIMB(0xc6c9e1d414516ccf),CNST_LIMB(0x9c6f0fd980ab1)), + P(6709,CNST_LIMB(0x805307f996e9e81d),CNST_LIMB(0x9c4b3f3a30c3f)), + P(6719,CNST_LIMB(0x3eddd2cff46ad5bf),CNST_LIMB(0x9c0fb29436687)), + P(6733,CNST_LIMB(0x35582c1aeb5aae85),CNST_LIMB(0x9bbca025b7aec)), + P(6737,CNST_LIMB(0x4973c88573ef6eb1),CNST_LIMB(0x9ba4f4421e52c)), + P(6761,CNST_LIMB(0x3063f627c1e715d9),CNST_LIMB(0x9b1783809ff03)), + P(6763,CNST_LIMB(0x711ad679a8dcc243),CNST_LIMB(0x9b0bc5b4d2eac)), + P(6779,CNST_LIMB(0x51c224a17a3db4b3),CNST_LIMB(0x9aae172fd8b9c)), + P(6781,CNST_LIMB(0x612325ca50ddaed5),CNST_LIMB(0x9aa26954607ed)), + P(6791,CNST_LIMB(0x9929a7b6b7958b37),CNST_LIMB(0x9a681e758a022)), + P(6793,CNST_LIMB(0xa78d222e5a857bb9),CNST_LIMB(0x9a5c7b284942e)), + P(6803,CNST_LIMB(0x3ad0ffe3198d139b),CNST_LIMB(0x9a2264ecc5558)), + P(6823,CNST_LIMB(0x8b4659ac547ed17),CNST_LIMB(0x99aebb39be56f)), + P(6827,CNST_LIMB(0x1752e8904aff1003),CNST_LIMB(0x9997ae1a9faac)), + P(6829,CNST_LIMB(0x60745c37ee4e5925),CNST_LIMB(0x998c2a22b6900)), + P(6833,CNST_LIMB(0x29e2da1f6557ee51),CNST_LIMB(0x997527603f8a8)), + P(6841,CNST_LIMB(0x80d78c24ac49cb89),CNST_LIMB(0x99473685e4d50)), + P(6857,CNST_LIMB(0xc56c3b495c8d1f79),CNST_LIMB(0x98eba72512a13)), + P(6863,CNST_LIMB(0xcf5bdf9f5088ac2f),CNST_LIMB(0x98c96d8dee9e1)), + P(6869,CNST_LIMB(0x8a44800e4fae4e7d),CNST_LIMB(0x98a743453554e)), + P(6871,CNST_LIMB(0xdd76384277e578e7),CNST_LIMB(0x989be33c9e6bd)), + P(6883,CNST_LIMB(0x20b1562d2703facb),CNST_LIMB(0x9857c692e9a59)), + P(6899,CNST_LIMB(0xef56caf96e9d8e3b),CNST_LIMB(0x97fd540c05c9e)), + P(6907,CNST_LIMB(0xf54061416aede033),CNST_LIMB(0x97d04302ed944)), + P(6911,CNST_LIMB(0xe0bc78c21a26e4ff),CNST_LIMB(0x97b9c48289935)), + P(6917,CNST_LIMB(0x524f92731a179cd),CNST_LIMB(0x9798133ece717)), + P(6947,CNST_LIMB(0x5d3b4ad7deafec8b),CNST_LIMB(0x96f07c683689e)), + P(6949,CNST_LIMB(0x508828f744da88ad),CNST_LIMB(0x96e55d6393fc5)), + P(6959,CNST_LIMB(0x6e82014031710bcf),CNST_LIMB(0x96addad861696)), + P(6961,CNST_LIMB(0xadf3b77a22595dd1),CNST_LIMB(0x96a2c5a2cf0cf)), + P(6967,CNST_LIMB(0xd8f0c03f7ea8a87),CNST_LIMB(0x96818fc825eba)), + P(6971,CNST_LIMB(0x2c49e3483c3a05f3),CNST_LIMB(0x966b74027f48a)), + P(6977,CNST_LIMB(0xccecbc98c91274c1),CNST_LIMB(0x964a56850b8ed)), + P(6983,CNST_LIMB(0x273a08941bb71e77),CNST_LIMB(0x962947990eb36)), + P(6991,CNST_LIMB(0xdead5a1e3f341baf),CNST_LIMB(0x95fd4a4c885e0)), + P(6997,CNST_LIMB(0x83eee092593309fd),CNST_LIMB(0x95dc5d3954fde)), + P(7001,CNST_LIMB(0x4af5f1bd3ae87ce9),CNST_LIMB(0x95c671ddfe516)), + P(7013,CNST_LIMB(0x4ca85ad2301c9e6d),CNST_LIMB(0x9584d6340ddf1)), + P(7019,CNST_LIMB(0x1b19592cd31a3943),CNST_LIMB(0x95641de84afcc)), + P(7027,CNST_LIMB(0x3e7aa05e6dcd81bb),CNST_LIMB(0x953893c386521)), + P(7039,CNST_LIMB(0x86336cecb02ba47f),CNST_LIMB(0x94f7740d87794)), + P(7043,CNST_LIMB(0xa96b30d0c8a44b2b),CNST_LIMB(0x94e1cb70c9ce0)), + P(7057,CNST_LIMB(0xb7c63fa0cfca0571),CNST_LIMB(0x94962ecbcc7ce)), + P(7069,CNST_LIMB(0x8eaf59b405a642b5),CNST_LIMB(0x94559c69059cf)), + P(7079,CNST_LIMB(0xdf29e9cbb536dc17),CNST_LIMB(0x941ff7e640716)), + P(7103,CNST_LIMB(0xed14132c82c1d43f),CNST_LIMB(0x939fd7a24b099)), + P(7109,CNST_LIMB(0xaf68778e34caab0d),CNST_LIMB(0x937ff22c014bd)), + P(7121,CNST_LIMB(0xa4f04a3368941d31),CNST_LIMB(0x934050872c09e)), + P(7127,CNST_LIMB(0xe9960969357c07e7),CNST_LIMB(0x93209446d56f6)), + P(7129,CNST_LIMB(0xeb47b62b7360b469),CNST_LIMB(0x9316033b5bd22)), + P(7151,CNST_LIMB(0x64c653d779ae730f),CNST_LIMB(0x92a22b9a79374)), + P(7159,CNST_LIMB(0x479702d3319915c7),CNST_LIMB(0x927838edba206)), + P(7177,CNST_LIMB(0xef3c3eebc6803239),CNST_LIMB(0x921a2e7112833)), + P(7187,CNST_LIMB(0x93807b1a2e3c0e1b),CNST_LIMB(0x91e623d5660d0)), + P(7193,CNST_LIMB(0x8167e33e3f478029),CNST_LIMB(0x91c6fc0cab8b6)), + P(7207,CNST_LIMB(0x60cb76e38c339397),CNST_LIMB(0x917e7d88028eb)), + P(7211,CNST_LIMB(0xae34788ffe4bc283),CNST_LIMB(0x9169d455585cd)), + P(7213,CNST_LIMB(0x4b6246a0c6c093a5),CNST_LIMB(0x915f81ef2d529)), + P(7219,CNST_LIMB(0x872e594b12b03efb),CNST_LIMB(0x9140938595d3a)), + P(7229,CNST_LIMB(0xbc0ae83ce9045b15),CNST_LIMB(0x910d2360a450e)), + P(7237,CNST_LIMB(0xad30a3917e0968d),CNST_LIMB(0x90e417104eabd)), + P(7243,CNST_LIMB(0x124ef5a4e1c7cd63),CNST_LIMB(0x90c55d0fdea28)), + P(7247,CNST_LIMB(0x5b98fe0e9fe17aaf),CNST_LIMB(0x90b0e84c04f20)), + P(7253,CNST_LIMB(0x414306cfe45400fd),CNST_LIMB(0x909243fac6b70)), + P(7283,CNST_LIMB(0xa06d1b4fd391e8bb),CNST_LIMB(0x8ff9d0440d137)), + P(7297,CNST_LIMB(0x11939803a60c2381),CNST_LIMB(0x8fb3192789d73)), + P(7307,CNST_LIMB(0x668c11cc37ea6b23),CNST_LIMB(0x8f80c0d5031e3)), + P(7309,CNST_LIMB(0x83f9b2089dc10645),CNST_LIMB(0x8f76b3664f164)), + P(7321,CNST_LIMB(0x65dc8ae47af277a9),CNST_LIMB(0x8f3a80550abc3)), + P(7331,CNST_LIMB(0x6e2368b9c685770b),CNST_LIMB(0x8f087c50e00c4)), + P(7333,CNST_LIMB(0x3ea137aeba5a6b2d),CNST_LIMB(0x8efe7fb408cc2)), + P(7349,CNST_LIMB(0x735f57adca48f19d),CNST_LIMB(0x8eaecce5c4fd7)), + P(7351,CNST_LIMB(0x69a8de0ba1b18107),CNST_LIMB(0x8ea4dccaaec0b)), + P(7369,CNST_LIMB(0x8fb84bdf5822bd79),CNST_LIMB(0x8e4ba9fbc2ff0)), + P(7393,CNST_LIMB(0xb8fab3b748562721),CNST_LIMB(0x8dd5688a3b7d6)), + P(7411,CNST_LIMB(0xa6c658ea10a65c3b),CNST_LIMB(0x8d7d3821fd94f)), + P(7417,CNST_LIMB(0xe56381f33ab5e549),CNST_LIMB(0x8d5feb03c31d7)), + P(7433,CNST_LIMB(0xe3c224da14988139),CNST_LIMB(0x8d12033cc9d30)), + P(7451,CNST_LIMB(0x438c253e6d99f513),CNST_LIMB(0x8cbac4dec6a82)), + P(7457,CNST_LIMB(0xc1b99f8841a3a6e1),CNST_LIMB(0x8c9dc80ab604b)), + P(7459,CNST_LIMB(0x63fa18c79c54fa8b),CNST_LIMB(0x8c942115dcc96)), + P(7477,CNST_LIMB(0xe7f6f609619d0d1d),CNST_LIMB(0x8c3d7df67b539)), + P(7481,CNST_LIMB(0x7b39ef3b70afc109),CNST_LIMB(0x8c2a4bc35cb3b)), + P(7487,CNST_LIMB(0x73922c61ca7452bf),CNST_LIMB(0x8c0d8a4f1f264)), + P(7489,CNST_LIMB(0x28d96828332372c1),CNST_LIMB(0x8c03f71cbf906)), + P(7499,CNST_LIMB(0x6b6e92968c4e8463),CNST_LIMB(0x8bd42abd9a107)), + P(7507,CNST_LIMB(0x571861f084962edb),CNST_LIMB(0x8bae051d7f6ff)), + P(7517,CNST_LIMB(0xd935c64f140f1ef5),CNST_LIMB(0x8b7e735068135)), + P(7523,CNST_LIMB(0x96459f8fd72a4c4b),CNST_LIMB(0x8b61f82c5fb08)), + P(7529,CNST_LIMB(0x410ba9a2a18242d9),CNST_LIMB(0x8b4588a74a05a)), + P(7537,CNST_LIMB(0xcf90979f89870391),CNST_LIMB(0x8b1fb0a7ed403)), + P(7541,CNST_LIMB(0x10f94ff26bc00add),CNST_LIMB(0x8b0ccc5d8f5c8)), + P(7547,CNST_LIMB(0xa6619fbb9da139b3),CNST_LIMB(0x8af07f8ac5146)), + P(7549,CNST_LIMB(0x765a23334efb03d5),CNST_LIMB(0x8ae71328ffd49)), + P(7559,CNST_LIMB(0x6f2f613b5e631837),CNST_LIMB(0x8ab8086624822)), + P(7561,CNST_LIMB(0x666b99bfbcd368b9),CNST_LIMB(0x8aaea3ab5ae89)), + P(7573,CNST_LIMB(0x922b78eb01ed45bd),CNST_LIMB(0x8a7661f7020fe)), + P(7577,CNST_LIMB(0x7079a199c31de6a9),CNST_LIMB(0x8a63ab88aa8dd)), + P(7583,CNST_LIMB(0xa181abcda167be5f),CNST_LIMB(0x8a47a35d020f3)), + P(7589,CNST_LIMB(0x2f6dbbcab3a9822d),CNST_LIMB(0x8a2ba68a3cebf)), + P(7591,CNST_LIMB(0xc5a83ff0e43eba17),CNST_LIMB(0x8a2254c852497)), + P(7603,CNST_LIMB(0x28c68613dda7d97b),CNST_LIMB(0x89ea849898bb3)), + P(7607,CNST_LIMB(0x5cf33ed49efa5007),CNST_LIMB(0x89d7f3e285109)), + P(7621,CNST_LIMB(0x9125fdead661590d),CNST_LIMB(0x899720af36739)), + P(7639,CNST_LIMB(0xaee67f478c7325e7),CNST_LIMB(0x89442160d11dc)), + P(7643,CNST_LIMB(0x735b1274a0e89653),CNST_LIMB(0x8931bd5875a22)), + P(7649,CNST_LIMB(0x733b56eae1a4e621),CNST_LIMB(0x891630877aedf)), + P(7669,CNST_LIMB(0x1944ffb316ffe65d),CNST_LIMB(0x88baaad83e38f)), + P(7673,CNST_LIMB(0xf26bc3cfd2a01449),CNST_LIMB(0x88a86b9090aa4)), + P(7681,CNST_LIMB(0xb5827ba68b83e201),CNST_LIMB(0x8883fb99bf244)), + P(7687,CNST_LIMB(0xac139507e48eefb7),CNST_LIMB(0x8868b45e727ee)), + P(7691,CNST_LIMB(0xeb7676b25834fda3),CNST_LIMB(0x88568aef30d47)), + P(7699,CNST_LIMB(0xad898f4763da5c1b),CNST_LIMB(0x8832468f0bcdd)), + P(7703,CNST_LIMB(0xea906f224398f9a7),CNST_LIMB(0x88202b9a4df76)), + P(7717,CNST_LIMB(0xa8aff3caca28cdad),CNST_LIMB(0x87e0f31872e9b)), + P(7723,CNST_LIMB(0x46c53aa36b19b083),CNST_LIMB(0x87c5ecd731f42)), + P(7727,CNST_LIMB(0x9ada32b09603e8cf),CNST_LIMB(0x87b3eea3bb388)), + P(7741,CNST_LIMB(0xd31f842ef5d8e915),CNST_LIMB(0x87751a6c67d78)), + P(7753,CNST_LIMB(0x6124af44730a33f9),CNST_LIMB(0x873f6e2f9d34a)), + P(7757,CNST_LIMB(0x828ec4c2b6e64a85),CNST_LIMB(0x872d938dcfc01)), + P(7759,CNST_LIMB(0x3d6f49df999638af),CNST_LIMB(0x8724a80151dba)), + P(7789,CNST_LIMB(0x7641460a0ea89b65),CNST_LIMB(0x869f677f6cc1a)), + P(7793,CNST_LIMB(0x97703f98fb7fe291),CNST_LIMB(0x868db701df58d)), + P(7817,CNST_LIMB(0xd343c209e3e6b7b9),CNST_LIMB(0x8623f563a7d6d)), + P(7823,CNST_LIMB(0x4e5fc01f6a41406f),CNST_LIMB(0x86099ef0c8886)), + P(7829,CNST_LIMB(0xb78a05b08aa4bcbd),CNST_LIMB(0x85ef52d38fe87)), + P(7841,CNST_LIMB(0x3434a14919d34561),CNST_LIMB(0x85bad981c7847)), + P(7853,CNST_LIMB(0xccead7dee120f525),CNST_LIMB(0x8586893de7cfc)), + P(7867,CNST_LIMB(0xe1375a2bccd87673),CNST_LIMB(0x8549b491e9efe)), + P(7873,CNST_LIMB(0xf727d51420a57141),CNST_LIMB(0x852fb3859bea4)), + P(7877,CNST_LIMB(0x2c3b68cfbcebb00d),CNST_LIMB(0x851e631fc08f8)), + P(7879,CNST_LIMB(0xda91e2f3e17542f7),CNST_LIMB(0x8515bc9cde5f1)), + P(7883,CNST_LIMB(0xb55f6100ae95d6e3),CNST_LIMB(0x850472f6185b3)), + P(7901,CNST_LIMB(0x6a0c608e0bbaa975),CNST_LIMB(0x84b6defbc166b)), + P(7907,CNST_LIMB(0xac5f2fc151c016cb),CNST_LIMB(0x849d17159854b)), + P(7919,CNST_LIMB(0xb1e5af8146e4d00f),CNST_LIMB(0x8469a54a20645)), + P(7927,CNST_LIMB(0x6e283d3b112602c7),CNST_LIMB(0x84476f9401ade)), + P(7933,CNST_LIMB(0xf9a48bcb76c96e55),CNST_LIMB(0x842dd2e2dc25d)), + P(7937,CNST_LIMB(0xa776780ca4c0e101),CNST_LIMB(0x841cc543f58cb)), +#define SMALLEST_OMITTED_PRIME 7949 +#endif +#ifdef WANT_ptab + {CNST_LIMB(0x444437fed9a2349),{CNST_LIMB(0xe00056482545e92a),5,CNST_LIMB(0x2e044fdfbae4),CNST_LIMB(0x2c8f9615733fe6),CNST_LIMB(0x15319a745d44889),CNST_LIMB(0x30314bfee31fe08),CNST_LIMB(0x213845b5eb1d02b)},0,14}, + {CNST_LIMB(0x34091fa96ffdf47b),{CNST_LIMB(0x3adc72bf62f96a49),2,CNST_LIMB(0x2fdb815a40082e14),CNST_LIMB(0xa2fb4713ee182be),CNST_LIMB(0x6691fcc7a3042b5),CNST_LIMB(0xd7baca281bd7bfe),CNST_LIMB(0x31645ad7700b6fe1)},14,10}, + {CNST_LIMB(0x3c47d8d728a77ebb),{CNST_LIMB(0xfcb9aee19f3d0ca),2,CNST_LIMB(0xee09ca35d620514),CNST_LIMB(0x25e3c1639f7dc597),CNST_LIMB(0x176f977d1145f08f),CNST_LIMB(0x4a431b566c292ba),CNST_LIMB(0x100ae9d9482d6937)},24,9}, + {CNST_LIMB(0x77ab7da9d709ea9),{CNST_LIMB(0x11d1e7012ab3aa25),5,CNST_LIMB(0x1b394f7170aed8e),CNST_LIMB(0x546efaf8f3107d0),CNST_LIMB(0x42ed2efa9db39d8),CNST_LIMB(0xcf1c08fc6f825e),CNST_LIMB(0x252dd3fc3932c60)},33,8}, + {CNST_LIMB(0x310df3e7bd4bc897),{CNST_LIMB(0x4dfeef7ace095886),2,CNST_LIMB(0xaba3c794d85150d),CNST_LIMB(0x17a7ea757afc9b41),CNST_LIMB(0x27386bf8f31e3ba7),CNST_LIMB(0x14f913784ca1b09a),CNST_LIMB(0x19a5850266378808)},41,8}, + {CNST_LIMB(0xd997f089e8af1f),{CNST_LIMB(0x2d2f79839e6b7329),8,CNST_LIMB(0x285a2dd96a188d),CNST_LIMB(0x334ffbd384a516),CNST_LIMB(0xd9f5c4d959d8c),CNST_LIMB(0x1a7b0c8f9e2a8),CNST_LIMB(0x51d4df5ea86eca)},49,7}, + {CNST_LIMB(0x2514ab8fece6d79),{CNST_LIMB(0xb9d8ba8530d526d2),6,CNST_LIMB(0x111e482834cf602),CNST_LIMB(0x2099b9b4399ea77),CNST_LIMB(0xa7e65453d2c58b),CNST_LIMB(0x1543e97a71ba902),CNST_LIMB(0x13c9258fa65ea5c)},56,7}, + {CNST_LIMB(0x690efbefde431f9),{CNST_LIMB(0x37e6fe9321e30a89),5,CNST_LIMB(0x67c69a65020950a),CNST_LIMB(0x3d4da34fd3fb29d),CNST_LIMB(0x4481530580bf270),CNST_LIMB(0x53418b541a702fb),CNST_LIMB(0x5a63ba140615695)},63,7}, + {CNST_LIMB(0xf49e199a5f2f371),{CNST_LIMB(0xbe97cf50195e4cf),4,CNST_LIMB(0xb61e665a0d0c8f0),CNST_LIMB(0x12404319392532e),CNST_LIMB(0xc11fa27489010aa),CNST_LIMB(0x9486cdb3a063f1d),CNST_LIMB(0x90fb58fe1716f29)},70,7}, + {CNST_LIMB(0x20e4ce7eee0a5edf),{CNST_LIMB(0xf216910d87cce9ec),2,CNST_LIMB(0x19be5a877db767e7),CNST_LIMB(0x14174edbad8e4db0),CNST_LIMB(0x13aa47a54ebc0ab3),CNST_LIMB(0x34e03d849eed1a0),CNST_LIMB(0x1c348c675b2b87a9)},77,7}, + {CNST_LIMB(0x3c3b299a83e166e5),{CNST_LIMB(0x1004d8385b0845e0),2,CNST_LIMB(0xf135995f07a646c),CNST_LIMB(0x39f996f3e7c62cb6),CNST_LIMB(0x10e385c8b908ec46),CNST_LIMB(0x108780c61cd93a1),CNST_LIMB(0xece590a749ce9e6)},84,7}, + {CNST_LIMB(0x7385117dabf89767),{CNST_LIMB(0x1ba83180cf48fd02),1,CNST_LIMB(0x18f5dd04a80ed132),CNST_LIMB(0x134aacf48cf374fd),CNST_LIMB(0x5f5e8ab304a603e1),CNST_LIMB(0x8196d4d84952f0b),CNST_LIMB(0x27fbce261e06981)},91,7}, + {CNST_LIMB(0x6b1dd94152d113),{CNST_LIMB(0x31e8de86cb665558),9,CNST_LIMB(0x57c2791756ffa7),CNST_LIMB(0x155d1b6359e72e),CNST_LIMB(0x26e2dd434311d6),CNST_LIMB(0x2d6624583bf57f),CNST_LIMB(0x4b3c0311592466)},98,6}, + {CNST_LIMB(0x9bed1488742f9b),{CNST_LIMB(0xa44d3b1c6d785d44),8,CNST_LIMB(0x2f0a502161e5b4),CNST_LIMB(0x9197cc3e5a5b04),CNST_LIMB(0x58ecad625341f6),CNST_LIMB(0x2c8e81222f4972),CNST_LIMB(0x1f80904334e61e)},104,6}, + {CNST_LIMB(0xd851b0362c316b),{CNST_LIMB(0x2ef5b88db4540035),8,CNST_LIMB(0xcfa22017ddb3c6),CNST_LIMB(0x213062fd865691),CNST_LIMB(0x81822846481a0d),CNST_LIMB(0x4b3f5844dfd386),CNST_LIMB(0x746b08e79bff57)},110,6}, + {CNST_LIMB(0x129e6025385b5e9),{CNST_LIMB(0xb7fd23d5247f5d33),7,CNST_LIMB(0x1283c028c9d61ad),CNST_LIMB(0x8a2496a2184268),CNST_LIMB(0x702aa9d6cae97c),CNST_LIMB(0x8700d0e7b38adb),CNST_LIMB(0x562031b42d3873)},116,6}, + {CNST_LIMB(0x1b399405df9e1d9),{CNST_LIMB(0x2ce69e058ed22408),7,CNST_LIMB(0xc43448ef95aada),CNST_LIMB(0x2a35f6f5397332),CNST_LIMB(0x18bba0a2b06f9b5),CNST_LIMB(0x1bf0769bdd0a51),CNST_LIMB(0xdaf86a9dd4f157)},122,6}, + {CNST_LIMB(0x26a9c83b1da0183),{CNST_LIMB(0xa7c312b1de2834bc),6,CNST_LIMB(0x245cdfc0d956145),CNST_LIMB(0xcfb5812fdbb80b),CNST_LIMB(0x7f9bd0fd4d9771),CNST_LIMB(0x206d41f157b339d),CNST_LIMB(0x1597d040f39bed6)},128,6}, + {CNST_LIMB(0x36518f1ed35fae9),{CNST_LIMB(0x2da0bb538e68c61b),6,CNST_LIMB(0x161b11f812f7dbd),CNST_LIMB(0x1912054119f8337),CNST_LIMB(0x28b68baf0254a33),CNST_LIMB(0x1febc2a846ec627),CNST_LIMB(0x106e286e91657ac)},134,6}, + {CNST_LIMB(0x499cea9952ffcb7),{CNST_LIMB(0xbd2398239911cb86),5,CNST_LIMB(0x2f49990f2b0b4af),CNST_LIMB(0x3efc376b6d3879a),CNST_LIMB(0x16bf595684e7cae),CNST_LIMB(0x2096f989291e15a),CNST_LIMB(0x3f877653fe30a29)},140,6}, + {CNST_LIMB(0x603dc1f0578e36b),{CNST_LIMB(0x547a4d1f60bb6de6),5,CNST_LIMB(0x35de2e91a2ab072),CNST_LIMB(0x3ae19a039d933f9),CNST_LIMB(0x49f04fa32aed515),CNST_LIMB(0x49f39ce5e69737b),CNST_LIMB(0x48e7a8d6354cb3f)},146,6}, + {CNST_LIMB(0x822f4ff1bb75c7d),{CNST_LIMB(0xf7684c1a915fd94f),4,CNST_LIMB(0x3c4551ba4cbccdd),CNST_LIMB(0x3e072857c5d22e8),CNST_LIMB(0x757d8256f24de27),CNST_LIMB(0x256d9df09b5df5c),CNST_LIMB(0x19974713584ab80)},152,6}, + {CNST_LIMB(0xacfc9fbdf683023),{CNST_LIMB(0x7ad9852da99412df),4,CNST_LIMB(0x754da5eeda3acdb),CNST_LIMB(0x91f55d002dee623),CNST_LIMB(0x96936cc5e49d5ea),CNST_LIMB(0x766649a4996390),CNST_LIMB(0xaa8c52b8eea17dd)},158,6}, + {CNST_LIMB(0xe09d410f1fe4edb),{CNST_LIMB(0x23c5744aa32cf453),4,CNST_LIMB(0x34f16cefc1e749a),CNST_LIMB(0x2668179180c1b62),CNST_LIMB(0xdb241be2f133397),CNST_LIMB(0xa7c11527a49744e),CNST_LIMB(0x67d18e0669fea5b)},164,6}, + {CNST_LIMB(0x1149424a578f0ce7),{CNST_LIMB(0xd9e7a906d91cf1db),3,CNST_LIMB(0xdfe5fef362d4b5e),CNST_LIMB(0xcf056a84b77c77c),CNST_LIMB(0x985dfab0d2bd76b),CNST_LIMB(0xf57931f6922ec07),CNST_LIMB(0x44b19bfab74d6)},170,6}, + {CNST_LIMB(0x15b025d5fd579777),{CNST_LIMB(0x79b813c3ed8f4fd2),3,CNST_LIMB(0x116e5fce1d3c7de3),CNST_LIMB(0x1468c60d0220a399),CNST_LIMB(0xf10192b1089742d),CNST_LIMB(0xeae0b108eba5be6),CNST_LIMB(0xf0e98ff5e4d57d4)},176,6}, + {CNST_LIMB(0x1a5f81f6e38d3f1d),{CNST_LIMB(0x369eab91d724ae89),3,CNST_LIMB(0x12a46e520008c7fb),CNST_LIMB(0x638a97340d45e81),CNST_LIMB(0x12b4b0c893a62d44),CNST_LIMB(0x1072dcd55e5547d0),CNST_LIMB(0x18ce18c4a086d95f)},182,6}, + {CNST_LIMB(0x23293bf9b6fe2259),{CNST_LIMB(0xd1f849a43b917c65),2,CNST_LIMB(0x9df5c2bff0d0f91),CNST_LIMB(0xff1fdef6c15b8c),CNST_LIMB(0xec1383d93946006),CNST_LIMB(0x20ce6fd4fbbb8838),CNST_LIMB(0x55871453993a979)},188,6}, + {CNST_LIMB(0x2c1eaa6645e21b17),{CNST_LIMB(0x735a473662e09835),2,CNST_LIMB(0x2366ac00a295788d),CNST_LIMB(0xf8778468c26bac6),CNST_LIMB(0x10ecc751d2724c63),CNST_LIMB(0x4882fbd9d3d43e1),CNST_LIMB(0x2de76607a7f1541)},194,6}, + {CNST_LIMB(0x3646542a1110061b),{CNST_LIMB(0x2ddf24b018173a2c),2,CNST_LIMB(0x26e6af57bbbfe794),CNST_LIMB(0x1974e8d33a8f431f),CNST_LIMB(0x34da7258db6f7b4f),CNST_LIMB(0x2af310e921f874f8),CNST_LIMB(0x3cfeed9d4afc97)},200,6}, + {CNST_LIMB(0x4125602df5b7fa0b),{CNST_LIMB(0xf6fe47f7e339f3ce),1,CNST_LIMB(0x3c8fdf761ed811df),CNST_LIMB(0x145648c8769aba41),CNST_LIMB(0x3270209c06bd9a17),CNST_LIMB(0x2c03f98e45b9dca3),CNST_LIMB(0x3341dcfe340ee93e)},206,6}, + {CNST_LIMB(0x4e06bb83aa64f48d),{CNST_LIMB(0xa3f6020ab0b7e0d3),1,CNST_LIMB(0x15ebcd7500d12259),CNST_LIMB(0x786bf28f0081f92),CNST_LIMB(0x15d832d09f03b587),CNST_LIMB(0xaa3e94d54c2a575),CNST_LIMB(0x471850a042d21386)},212,6}, + {CNST_LIMB(0x6953db39a8298d8b),{CNST_LIMB(0x371b0bbe24632f20),1,CNST_LIMB(0x2d58498caface4ea),CNST_LIMB(0x557c399022219340),CNST_LIMB(0x2cb32a1a8fdd68c2),CNST_LIMB(0x122684249d42b9a9),CNST_LIMB(0x13c80507e77a929c)},218,6}, + {CNST_LIMB(0x15fafabe1c1777),{CNST_LIMB(0x74b22475baab0cce),11,CNST_LIMB(0xc763842e2c34d),CNST_LIMB(0x77d3f710b457b),CNST_LIMB(0x155a43f5525196),CNST_LIMB(0x148e30e0a5dee3),CNST_LIMB(0x13aa97836b8150)},224,5}, + {CNST_LIMB(0x18552ab4f8303b),{CNST_LIMB(0x50aaa1ed4d926e62),11,CNST_LIMB(0x815be492ca359),CNST_LIMB(0x1b55fe26d36ad),CNST_LIMB(0x113a54ceb7846),CNST_LIMB(0x1688511dfe47f),CNST_LIMB(0x66ccabff6c6c8)},229,5}, + {CNST_LIMB(0x1a99c2502dda5f),{CNST_LIMB(0x33f675a22ebecef5),11,CNST_LIMB(0x12ab7e96d807ff),CNST_LIMB(0x1d3db891dce3b),CNST_LIMB(0x19511de2e3095c),CNST_LIMB(0x2741e555a0bff),CNST_LIMB(0x51c7d31a19281)},234,5}, + {CNST_LIMB(0x1ebf9e78cd7ecb),{CNST_LIMB(0xa6b5da36fa2470c),11,CNST_LIMB(0xaebd869698c2f),CNST_LIMB(0x18e178fc70e26a),CNST_LIMB(0x64439ec9707b5),CNST_LIMB(0x116d1f70d29f20),CNST_LIMB(0xeea2317a9a585)},239,5}, + {CNST_LIMB(0x2214c7d5d9ce07),{CNST_LIMB(0xe0bc0f6215d26cf9),10,CNST_LIMB(0x1ffbac72c32f72),CNST_LIMB(0x1447f31b055129),CNST_LIMB(0x122d28bd754f9a),CNST_LIMB(0x106685d95b6d85),CNST_LIMB(0x18c9fdf391bdff)},244,5}, + {CNST_LIMB(0x25e2755d49ffa7),{CNST_LIMB(0xb078a0cae16506b6),10,CNST_LIMB(0x218554ef385919),CNST_LIMB(0xe00c975692d8e),CNST_LIMB(0x1afd2511d2f776),CNST_LIMB(0x108b0b031673f7),CNST_LIMB(0x8d919ed067cf0)},249,5}, + {CNST_LIMB(0x2925e3d5425d41),{CNST_LIMB(0x8e2c20d6f8f795ce),10,CNST_LIMB(0x1c5f29cb4c13c8),CNST_LIMB(0x15e11f6e5f634),CNST_LIMB(0xb32166d7982b3),CNST_LIMB(0xa636cf5c4f642),CNST_LIMB(0x28f997d81938bc)},254,5}, + {CNST_LIMB(0x2f39e99d11c26d),{CNST_LIMB(0x5aed08e710697213),10,CNST_LIMB(0x213b4a00c79b71),CNST_LIMB(0x1bd2737e294111),CNST_LIMB(0xd01c8aaaae314),CNST_LIMB(0xb00f1e27ed99e),CNST_LIMB(0x1d21748adab7e4)},259,5}, + {CNST_LIMB(0x3502a3ce62a769),{CNST_LIMB(0x35126ab40383fc5c),10,CNST_LIMB(0xf411f8bafb90c),CNST_LIMB(0x1fa38c975e6347),CNST_LIMB(0xf4058b043df4e),CNST_LIMB(0x2af2733656b159),CNST_LIMB(0x196e94f446c597)},264,5}, + {CNST_LIMB(0x3b357b23b014b1),{CNST_LIMB(0x14b711563eba7d77),10,CNST_LIMB(0x32f1ffd1469b4e),CNST_LIMB(0x197f48859c01a3),CNST_LIMB(0x29509dc5352d40),CNST_LIMB(0x335e5c9ef5d7fe),CNST_LIMB(0x284e1a5376a683)},269,5}, + {CNST_LIMB(0x420d06773114d3),{CNST_LIMB(0xf01a36d7bbf66dfc),9,CNST_LIMB(0xd86f221cf4e60),CNST_LIMB(0x728955d2f4a8d),CNST_LIMB(0x1a631ed35adca5),CNST_LIMB(0x2d592810a2cd39),CNST_LIMB(0x1215b15f856f68)},274,5}, + {CNST_LIMB(0x4c19f733c90d09),{CNST_LIMB(0xae954f9b28df48d8),9,CNST_LIMB(0xcab96d4cf28bb),CNST_LIMB(0x42b5fc3fd6e7ec),CNST_LIMB(0x2b7f897adc30de),CNST_LIMB(0x1a97bb06e110c0),CNST_LIMB(0x304db431256118)},279,5}, + {CNST_LIMB(0x52f224bf890ffd),{CNST_LIMB(0x8b0d84b8653cb09f),9,CNST_LIMB(0x8c298ef08a942),CNST_LIMB(0x2999ac4ebb9e26),CNST_LIMB(0x3dd9eb9ca2c026),CNST_LIMB(0x43401c4563f790),CNST_LIMB(0x38d5e8bf6d2c89)},284,5}, + {CNST_LIMB(0x5bf703dda941b1),{CNST_LIMB(0x644f51d4add132a4),9,CNST_LIMB(0x38fd3f81414bb8),CNST_LIMB(0x20049119d93b7c),CNST_LIMB(0x4e479d97844206),CNST_LIMB(0x294a3066f3b775),CNST_LIMB(0x1c21bda84cf2fc)},289,5}, + {CNST_LIMB(0x68cf321fe6202f),{CNST_LIMB(0x38a4d27caeef8e91),9,CNST_LIMB(0x1e26a01f2b6d41),CNST_LIMB(0x9e9e8993d282b),CNST_LIMB(0x417ad2819cd4fb),CNST_LIMB(0x627fb183ab0b1a),CNST_LIMB(0x278b9f029564e7)},294,5}, + {CNST_LIMB(0x71dad4e06cde9b),{CNST_LIMB(0x1fce1dcd4eb47a27),9,CNST_LIMB(0x457bdbeb7801db),CNST_LIMB(0x1f2b3df5db8f09),CNST_LIMB(0x2149ca25813ef0),CNST_LIMB(0x17d20c710e4487),CNST_LIMB(0x40ceb8ee4ca73d)},299,5}, + {CNST_LIMB(0x7b5e9ca091c63d),{CNST_LIMB(0x99bc23041414782),9,CNST_LIMB(0x1ac11ef1a1cf79),CNST_LIMB(0x313f0652fefffc),CNST_LIMB(0x12f34ea4e7a5db),CNST_LIMB(0x2aa2b3b3300bfd),CNST_LIMB(0x3245caffd0690c)},304,5}, + {CNST_LIMB(0x892f2017af4a77),{CNST_LIMB(0xddb91a666e887a07),8,CNST_LIMB(0x633133de624045),CNST_LIMB(0x7f207860875935),CNST_LIMB(0x702aff29ff7777),CNST_LIMB(0x1cc53fa2f53db9),CNST_LIMB(0x2c5ff88b6e27ee)},309,5}, + {CNST_LIMB(0x93efab3d98e265),{CNST_LIMB(0xbb00736076c6c8fc),8,CNST_LIMB(0x42ac68703b39),CNST_LIMB(0x4d4d015d5d1bd7),CNST_LIMB(0x85c801afb0f411),CNST_LIMB(0x4579d8022d0a69),CNST_LIMB(0x32ea2e520e3d23)},314,5}, + {CNST_LIMB(0x9fd1e9a289b8f9),{CNST_LIMB(0x9a0fb77008192e78),8,CNST_LIMB(0x9cfd1af6dc136),CNST_LIMB(0x23a28bc352c87c),CNST_LIMB(0x582383446e53c2),CNST_LIMB(0x3d52e0695b07e4),CNST_LIMB(0x83c6fc0e7cfd23)},319,5}, + {CNST_LIMB(0xb3ffc82a3b00bb),{CNST_LIMB(0x6c17325c7676de1f),8,CNST_LIMB(0x104f63f41af61c),CNST_LIMB(0x838ff92da5d267),CNST_LIMB(0xb37001a22f0194),CNST_LIMB(0x4487295b668b16),CNST_LIMB(0xa06ce4ed65729d)},324,5}, + {CNST_LIMB(0xc78aab3260ed67),{CNST_LIMB(0x486ec1d048657b5d),8,CNST_LIMB(0x5654a773cfd408),CNST_LIMB(0xb3f20a79edde43),CNST_LIMB(0xaebbd1a69724dd),CNST_LIMB(0x81191f0503a9),CNST_LIMB(0x3b54fc6e1ed034)},329,5}, + {CNST_LIMB(0xd8b06a4b9eddc9),{CNST_LIMB(0x2e7147c081441aeb),8,CNST_LIMB(0x5fe29aca965ce2),CNST_LIMB(0x9cb19caad665ca),CNST_LIMB(0x147b04c65844fd),CNST_LIMB(0x7a1c878be8db45),CNST_LIMB(0x8f4f4d51c80dfd)},334,5}, + {CNST_LIMB(0xe8f35bfe49ae4b),{CNST_LIMB(0x19547b44fa632b82),8,CNST_LIMB(0x4ce005e11fafad),CNST_LIMB(0x57f2d94de4ea00),CNST_LIMB(0xb885b9e976e473),CNST_LIMB(0x1eb25c197e9b39),CNST_LIMB(0xe2c45221f5cdb7)},339,5}, + {CNST_LIMB(0xfcff7f19788a27),{CNST_LIMB(0x3099f4bf7423272),8,CNST_LIMB(0x982693b0c3a8b),CNST_LIMB(0xa6eee9dce0fc63),CNST_LIMB(0xf1290f2b74223c),CNST_LIMB(0x36c85e11826e0b),CNST_LIMB(0xbe15668a4d3771)},344,5}, + {CNST_LIMB(0x10f681c21a80325),{CNST_LIMB(0xe2ef902951d2322d),7,CNST_LIMB(0x7efd8450d50a2b),CNST_LIMB(0x37c115b60abfde),CNST_LIMB(0x4a31517b3a2c0),CNST_LIMB(0x8ee426b2c25e26),CNST_LIMB(0xaf5e09c0582f8)},349,5}, + {CNST_LIMB(0x11ffa8ecf7814fb),{CNST_LIMB(0xc7250b86192832ab),7,CNST_LIMB(0xa4d35e0885656f),CNST_LIMB(0x6d14e9be5101ec),CNST_LIMB(0x93b36726a244a),CNST_LIMB(0xb56f38bde55186),CNST_LIMB(0x11443988cbd610f)},354,5}, + {CNST_LIMB(0x139b8ddf439b133),{CNST_LIMB(0xa1cbe52ffcdca969),7,CNST_LIMB(0x119cba991200690),CNST_LIMB(0xa8a1be12145159),CNST_LIMB(0x49831f7f1eb091),CNST_LIMB(0x5fe3a0bd210422),CNST_LIMB(0x11b90612ebf719f)},359,5}, + {CNST_LIMB(0x15b90aaef040351),{CNST_LIMB(0x791d6da971f79fb1),7,CNST_LIMB(0xc1c278790d9084),CNST_LIMB(0xa6bc771172ca70),CNST_LIMB(0x1219044d36b161b),CNST_LIMB(0x9363a00d9d3f5f),CNST_LIMB(0x14079ec2a37ea93)},364,5}, + {CNST_LIMB(0x17d664f86c88bd3),{CNST_LIMB(0x57a9176de3f40918),7,CNST_LIMB(0x13ca8e0f80a9a0f),CNST_LIMB(0xfc1ecc66c0c93b),CNST_LIMB(0x15be6192051cb1a),CNST_LIMB(0x136f263b7a50fcc),CNST_LIMB(0x3820db8623a7)},369,5}, + {CNST_LIMB(0x1a44cc5ef4c16b5),{CNST_LIMB(0x37da80020a7d1f74),7,CNST_LIMB(0x18584281cee4069),CNST_LIMB(0x178a63d22596ba9),CNST_LIMB(0x6739c7c5ac4f2d),CNST_LIMB(0x14c57a38e4d612a),CNST_LIMB(0x13d2e7fd35623ae)},374,5}, + {CNST_LIMB(0x1ca80b29773de79),{CNST_LIMB(0x1dde9f723a4f55dc),7,CNST_LIMB(0x1ac9ceffdba98e2),CNST_LIMB(0xf4618a5f0fdaa9),CNST_LIMB(0x17b96b4ded53ebb),CNST_LIMB(0x7faf749bdd9cb1),CNST_LIMB(0xfa9d50111fc549)},379,5}, + {CNST_LIMB(0x1e7b019a7fa8931),{CNST_LIMB(0xcc3160c520cdb96),7,CNST_LIMB(0xb9d29212dc305a),CNST_LIMB(0x91586fa7d2facc),CNST_LIMB(0x2638c4c9135f19),CNST_LIMB(0x1c315565816b84a),CNST_LIMB(0xa92e9c918ad70f)},384,5}, + {CNST_LIMB(0x1fd932c2a6c3463),{CNST_LIMB(0x137e41a0c0b8d4f),7,CNST_LIMB(0x13669eac9e5ce80),CNST_LIMB(0x94dc55b30276b5),CNST_LIMB(0x1c52a400cc7dae6),CNST_LIMB(0x1cd876c8023e81b),CNST_LIMB(0x8e06dbbb7e4c2d)},389,5}, + {CNST_LIMB(0x2175e8bd7050e79),{CNST_LIMB(0xe9a698d03a5e604b),6,CNST_LIMB(0xdcf15b87971a56),CNST_LIMB(0x2e9e439e7517fb),CNST_LIMB(0x85bbfca7ac6da9),CNST_LIMB(0x500c9508abde31),CNST_LIMB(0x1c9d7aa292a48b0)},394,5}, + {CNST_LIMB(0x24033b205fe4527),{CNST_LIMB(0xc6f39cee1695e79a),6,CNST_LIMB(0x1a92e6b5ac379c9),CNST_LIMB(0x1f1b86c0e7f8d15),CNST_LIMB(0x1e362d27d79fda9),CNST_LIMB(0x4dcd13ebf2a00a),CNST_LIMB(0x408b8bd354f1b4)},399,5}, + {CNST_LIMB(0x265d2eb09cdc073),{CNST_LIMB(0xab112e468a91ceb0),6,CNST_LIMB(0x1d6aaadf0ce5062),CNST_LIMB(0x8cb5be41003782),CNST_LIMB(0x52b9980c0c4bec),CNST_LIMB(0x2228f2e6cbe8667),CNST_LIMB(0xca6f7400df044e)},404,5}, + {CNST_LIMB(0x2953a0e65ca6a1d),{CNST_LIMB(0x8c7372d9ab5569c1),6,CNST_LIMB(0x4a8c6ea2b8f6c9),CNST_LIMB(0x3588f2393801ce),CNST_LIMB(0x1fce38ab648e336),CNST_LIMB(0x89544c1c4d5e80),CNST_LIMB(0x6e5d409692ed37)},409,5}, + {CNST_LIMB(0x2c67f25a6bc9c63),{CNST_LIMB(0x70f57416f0cce89e),6,CNST_LIMB(0xaa4e781437cc6c),CNST_LIMB(0x1c38f9d456ca8d),CNST_LIMB(0x2682eae3a0afadb),CNST_LIMB(0x2b54835e8a4f4ca),CNST_LIMB(0x1ff894f600fa94f)},414,5}, + {CNST_LIMB(0x2fdd1a7524ae76d),{CNST_LIMB(0x564e31abce2eba47),6,CNST_LIMB(0x1b96371ad2128cf),CNST_LIMB(0x35309a6895ab0d),CNST_LIMB(0x14de5531da96df1),CNST_LIMB(0x3a924ccc42ac90),CNST_LIMB(0x315a6b9b99a595)},419,5}, + {CNST_LIMB(0x33770e6e18aeb53),{CNST_LIMB(0x3e5a14fd0434a100),6,CNST_LIMB(0x1e428c066216163),CNST_LIMB(0x93d03854bffefa),CNST_LIMB(0x77e62b6df8d4a1),CNST_LIMB(0x8a8b138bb2ed69),CNST_LIMB(0x292d249664af8db)},424,5}, + {CNST_LIMB(0x379c7dff6334d3b),{CNST_LIMB(0x269dcc0c8d56e875),6,CNST_LIMB(0x2460122cb5efa2d),CNST_LIMB(0x28e51e3c7265f2e),CNST_LIMB(0x1efacb51926e686),CNST_LIMB(0xfc8248ae79bd5f),CNST_LIMB(0x2f3b91b1fe1f65)},429,5}, + {CNST_LIMB(0x3b82f15f7249c49),{CNST_LIMB(0x134ee332d51f0306),6,CNST_LIMB(0x3137e2a5a467c9c),CNST_LIMB(0x79d488798b4960),CNST_LIMB(0xb436578d1069bb),CNST_LIMB(0x10ad84e585582d0),CNST_LIMB(0x3215616c9b153bf)},434,5}, + {CNST_LIMB(0x3fff4dd17ad4ff9),{CNST_LIMB(0x2c8c1d50d30af),6,CNST_LIMB(0x2c8ba14ac01c0),CNST_LIMB(0x2bd06852b51e327),CNST_LIMB(0x30714e5452d2c1),CNST_LIMB(0x327ff42efc6d9c),CNST_LIMB(0x244bb5001864710)},439,5}, + {CNST_LIMB(0x465670cc294b181),{CNST_LIMB(0xd1ddf947b9d55be0),5,CNST_LIMB(0x106a71bea4fc8c6),CNST_LIMB(0xa255b26c45d27f),CNST_LIMB(0x460d26a6240e466),CNST_LIMB(0x1dda425d1868b60),CNST_LIMB(0x3d6eff8580e97e1)},444,5}, + {CNST_LIMB(0x4aaaab2fe3fee47),{CNST_LIMB(0xb6db6aa7d3a37a63),5,CNST_LIMB(0x3fffe3e5e83bd06),CNST_LIMB(0xa8a65f30809160),CNST_LIMB(0xbfd8fef4142370),CNST_LIMB(0x358c77f78c2a4d0),CNST_LIMB(0x3a89f0ee6796b95)},449,5}, + {CNST_LIMB(0x4f8bbff17c95ef7),{CNST_LIMB(0x9bf032ee57751395),5,CNST_LIMB(0x2728c2e42e214cb),CNST_LIMB(0x37fb2686e89761e),CNST_LIMB(0x4a264029edea029),CNST_LIMB(0x1d504d3aecaaa50),CNST_LIMB(0x45b5a7b35031756)},454,5}, + {CNST_LIMB(0x553ea1ce3216691),{CNST_LIMB(0x806643148e9063ef),5,CNST_LIMB(0x441a9569bcc4d0),CNST_LIMB(0x535ae4be3f071a1),CNST_LIMB(0x545a793067e09d8),CNST_LIMB(0xd5d15c09afe8cd),CNST_LIMB(0x4534c23a01c6a96)},459,5}, + {CNST_LIMB(0x59f7c9a4fefb517),{CNST_LIMB(0x6c37fd6421ef50ed),5,CNST_LIMB(0x2f718dff2dd2af5),CNST_LIMB(0x4aea82d40c5cc72),CNST_LIMB(0x4f7cec2a6861199),CNST_LIMB(0xe868a369a42529),CNST_LIMB(0x40e610cd320b2f7)},464,5}, + {CNST_LIMB(0x5e8d3fa86f95521),{CNST_LIMB(0x5a8fc0667cc240fe),5,CNST_LIMB(0x1e464eb541eb375),CNST_LIMB(0x3892fa43db27fd5),CNST_LIMB(0x4e5c7836ddc791a),CNST_LIMB(0x36e537bed96365e),CNST_LIMB(0x4375094ddcb8820)},469,5}, + {CNST_LIMB(0x64157c62c33e31d),{CNST_LIMB(0x4767bbee2675bc54),5,CNST_LIMB(0x5ca490917e48378),CNST_LIMB(0x11867a67aa79db0),CNST_LIMB(0x6198c4cbcaf84e6),CNST_LIMB(0x4338ebe5ab25fcf),CNST_LIMB(0x11e91c53e48fd1e)},474,5}, + {CNST_LIMB(0x6ceeed4c43f4183),{CNST_LIMB(0x2cced2b1dae4601a),5,CNST_LIMB(0x4177b3fa2db8811),CNST_LIMB(0x2b3db3648dc8a5),CNST_LIMB(0x50f060794aa127),CNST_LIMB(0x4f7cdc200df8c9a),CNST_LIMB(0x4525db055625df3)},479,5}, + {CNST_LIMB(0x7287ee7e5f96919),{CNST_LIMB(0x1e1b2205d593e3a6),5,CNST_LIMB(0x576a64b8ee6a195),CNST_LIMB(0x7bd2ea513c7027),CNST_LIMB(0x17c4152c6d55daa),CNST_LIMB(0x39f7aac6f902f57),CNST_LIMB(0x14765413bf9b5ca)},484,5}, + {CNST_LIMB(0x79886d10dfa5165),{CNST_LIMB(0xd9f57c223f379ca),5,CNST_LIMB(0x5569f0d32bb81fb),CNST_LIMB(0x6f08a7fc8e770a6),CNST_LIMB(0x2c14d325ec8479f),CNST_LIMB(0x4499d22e49d3c7),CNST_LIMB(0x53f1f1eecdc8c2)},489,5}, + {CNST_LIMB(0x7e13347ac1526bf),{CNST_LIMB(0x3e8a375cf0fb774),5,CNST_LIMB(0x3d9970a7d5b2820),CNST_LIMB(0x3664c9d670bba16),CNST_LIMB(0x6ba929ee3cbcd5c),CNST_LIMB(0xd5d262e6d92452),CNST_LIMB(0x2f545142add8d05)},494,5}, + {CNST_LIMB(0x8566f0377d15459),{CNST_LIMB(0xeb44411c1363bcf4),4,CNST_LIMB(0x5defd97f5781d92),CNST_LIMB(0x16eaae98cb00189),CNST_LIMB(0x986f4f6d77c243),CNST_LIMB(0x57c736925ddfd9),CNST_LIMB(0x10a756243dbe4ca)},499,5}, + {CNST_LIMB(0x8bfc83897e6cdaf),{CNST_LIMB(0xd428ea393317b9f2),4,CNST_LIMB(0x2465196cadab32d),CNST_LIMB(0x7594e9e684d904a),CNST_LIMB(0x19cd4a75383b2d1),CNST_LIMB(0x6a0e9c23f177e64),CNST_LIMB(0x56f0f2ae36c5465)},504,5}, + {CNST_LIMB(0x94ad790245385eb),{CNST_LIMB(0xb8cae8ae9a639526),4,CNST_LIMB(0x51b43cc2b30e037),CNST_LIMB(0x4cb133bb88b3adc),CNST_LIMB(0x3ede33df9c5e3e3),CNST_LIMB(0x665226a2d290ac4),CNST_LIMB(0x33db5ce835ec6e4)},509,5}, + {CNST_LIMB(0x9c30734d93b1379),{CNST_LIMB(0xa397f073b55bde0b),4,CNST_LIMB(0x23144a1f00005b6),CNST_LIMB(0x826ad253a3ed324),CNST_LIMB(0x940ad5d52b4806c),CNST_LIMB(0x1729e9d2d022730),CNST_LIMB(0x20a978fb381a6c2)},514,5}, + {CNST_LIMB(0xa57e1fd7a44fbb9),{CNST_LIMB(0x8c0164efd39df203),4,CNST_LIMB(0x7c2d03c898866a8),CNST_LIMB(0x4037558c6f1e4eb),CNST_LIMB(0x6694cdbbb8803c7),CNST_LIMB(0x99396c89bf97452),CNST_LIMB(0x436126c1b000fab)},519,5}, + {CNST_LIMB(0xaf9b9be9c8401d1),{CNST_LIMB(0x7531f66eca55c19b),4,CNST_LIMB(0x3904fdff023d639),CNST_LIMB(0x962f9b532413fb3),CNST_LIMB(0x27ec74df2758058),CNST_LIMB(0x5836483d1e34f66),CNST_LIMB(0x8384a37fad8866d)},524,5}, + {CNST_LIMB(0xb9ba711d6e4a84f),{CNST_LIMB(0x60dc0b5cc82154b3),4,CNST_LIMB(0x9fa47788598936),CNST_LIMB(0x82bd019c1fa5a56),CNST_LIMB(0x50db17c34711736),CNST_LIMB(0x739121f55c5b75d),CNST_LIMB(0x912fe4d49b6d56)},529,5}, + {CNST_LIMB(0xc41a8a6c63a70d1),{CNST_LIMB(0x4e30c99728e3c197),4,CNST_LIMB(0xaded2f8836f2fac),CNST_LIMB(0xab84ac5c6d525d9),CNST_LIMB(0x488aa0b1f301ccb),CNST_LIMB(0x5fdf2905d976ad6),CNST_LIMB(0x5cb75a7adbb8561)},534,5}, + {CNST_LIMB(0xcd79628a71801f7),{CNST_LIMB(0x3ef33887b9ad5b44),4,CNST_LIMB(0xbffdafb9937daab),CNST_LIMB(0x8c3722255b2b8c7),CNST_LIMB(0x63cd1bbc0e9c22a),CNST_LIMB(0xbd17bc2e12ad950),CNST_LIMB(0x15e9799e0d76f1e)},539,5}, + {CNST_LIMB(0xd6f67d4726eaaf5),{CNST_LIMB(0x30df0c865cc92a96),4,CNST_LIMB(0xbb4b3b81c94fd1),CNST_LIMB(0x2a20ca76128ce99),CNST_LIMB(0x4a4022bdd8f612e),CNST_LIMB(0x3bafa50d5be5f8b),CNST_LIMB(0xb86a67f06630908)},544,5}, + {CNST_LIMB(0xe5d3b047627f8e3),{CNST_LIMB(0x1d275ac8c78303ec),4,CNST_LIMB(0xbcf14b4275878ed),CNST_LIMB(0x5ee8b82b0662dd),CNST_LIMB(0x77e3de57e11f662),CNST_LIMB(0x5ed59e5dfb5cd16),CNST_LIMB(0xbe6a6366650aef1)},549,5}, + {CNST_LIMB(0xef42ae515bfb29d),{CNST_LIMB(0x11e922af2e24e769),4,CNST_LIMB(0x1c926c98e452393),CNST_LIMB(0xd26a458c9c34765),CNST_LIMB(0x5da54b52a8aa98a),CNST_LIMB(0xa2ed4f828338df7),CNST_LIMB(0xe69ac190926521a)},554,5}, + {CNST_LIMB(0xfd32459f0b3d4bb),{CNST_LIMB(0x2d5ace688e647e9),4,CNST_LIMB(0x2cdba60f4c2b450),CNST_LIMB(0x2577b742a8ed5db),CNST_LIMB(0x144ef4109272736),CNST_LIMB(0xbe9326c4f15e1a9),CNST_LIMB(0xb96de853277fb4f)},559,5}, + {CNST_LIMB(0x10a16ef6c96a16c7),{CNST_LIMB(0xec9602538c0df011),3,CNST_LIMB(0x68a7f8a32c8aa57),CNST_LIMB(0x1445e7d17b921f3),CNST_LIMB(0x81c8debc8176f0b),CNST_LIMB(0xe3a1c5b816e4a65),CNST_LIMB(0xa52ad5bb93c9f4b)},564,5}, + {CNST_LIMB(0x117c2fec47f5e013),{CNST_LIMB(0xd48355880989be17),3,CNST_LIMB(0xb356114108dbef6),CNST_LIMB(0xe7ddeca9ba6a20c),CNST_LIMB(0xf2d7618ea8a6953),CNST_LIMB(0x412256baaec5c27),CNST_LIMB(0x1f8e16ca6e5c0d7)},569,5}, + {CNST_LIMB(0x129a8c10ae1f364b),{CNST_LIMB(0xb857af53b5b43644),3,CNST_LIMB(0xe26e327286a3e31),CNST_LIMB(0xeef9d55a9d06dbf),CNST_LIMB(0xe61febd3beb02b6),CNST_LIMB(0x10d018a00b7fd6a5),CNST_LIMB(0x32009c46e7c1314)},574,5}, + {CNST_LIMB(0x134631392d507059),{CNST_LIMB(0xa9063d94bb92a978),3,CNST_LIMB(0x56f8018b2ea4b7b),CNST_LIMB(0x1270cb710b035935),CNST_LIMB(0x11033d859716c4f9),CNST_LIMB(0xd45bebac416a68c),CNST_LIMB(0xc08fe72fc6eef84)},579,5}, + {CNST_LIMB(0x13fde7755d5fd9ed),{CNST_LIMB(0x99c48a788248a856),3,CNST_LIMB(0x1019267f9f81c8e4),CNST_LIMB(0x394e4098ea8549),CNST_LIMB(0x33c85c2a1514436),CNST_LIMB(0xa1e569d4432f4bb),CNST_LIMB(0x128bfbc862fb3c58)},584,5}, + {CNST_LIMB(0x15698c0906cc26a5),{CNST_LIMB(0x7e957ed81f600c1e),3,CNST_LIMB(0x1476fb9cb53a56e9),CNST_LIMB(0xeff15504451beab),CNST_LIMB(0xdea55fc79c32599),CNST_LIMB(0x76a982d54d956a1),CNST_LIMB(0x4d131625675abd7)},589,5}, + {CNST_LIMB(0x168a1ee80f6d92f5),{CNST_LIMB(0x6b73459d204359d1),3,CNST_LIMB(0x810ac07564aaf79),CNST_LIMB(0x874d5996e15561a),CNST_LIMB(0xb75c73837694b49),CNST_LIMB(0xd4645617d29779b),CNST_LIMB(0x12af15ef931be940)},594,5}, + {CNST_LIMB(0x17daa6de32466fbf),{CNST_LIMB(0x576bc18853c72908),3,CNST_LIMB(0x11757b52093fa28a),CNST_LIMB(0xff4c0f212559944),CNST_LIMB(0x40af9872004a0a5),CNST_LIMB(0x2b2b7c424c54c2b),CNST_LIMB(0x1a2b7130739c4c7)},599,5}, + {CNST_LIMB(0x18ea5f2dbe212911),{CNST_LIMB(0x48ca86c98010be89),3,CNST_LIMB(0x6d8483692b46556),CNST_LIMB(0x305d89220ec48d2),CNST_LIMB(0x1772200dfc1938dc),CNST_LIMB(0xded80c44ca87607),CNST_LIMB(0xb498b0490dc55dd)},604,5}, + {CNST_LIMB(0x1a0fa1ef47787d1b),{CNST_LIMB(0x3a56b20c2d70e08a),3,CNST_LIMB(0x15734e967cc39a0d),CNST_LIMB(0x8fc968191dc0fd3),CNST_LIMB(0x1680d35f18721f8f),CNST_LIMB(0x197b4a3e18c9e8bc),CNST_LIMB(0xc0ad81d645f40c7)},609,5}, + {CNST_LIMB(0x1b673b66a023a93f),{CNST_LIMB(0x2af150ff9195ac0f),3,CNST_LIMB(0x95ee9645ebf0cc9),CNST_LIMB(0x1717202bbc3e0a78),CNST_LIMB(0x126d365df320adf6),CNST_LIMB(0x137d63165361ab0e),CNST_LIMB(0x19ca69d84cc1417c)},614,5}, + {CNST_LIMB(0x1ce34de10c258111),{CNST_LIMB(0x1b9430b6521be183),3,CNST_LIMB(0x18e590f79ed3f778),CNST_LIMB(0xbcbaeb9ec0a1624),CNST_LIMB(0x18f51ac04296ceb6),CNST_LIMB(0x161b15271d06a3e1),CNST_LIMB(0x5f0a62fb317dd86)},619,5}, + {CNST_LIMB(0x1e19674e354f4667),{CNST_LIMB(0x102a99b0acd64358),3,CNST_LIMB(0xf34c58e5585ccc8),CNST_LIMB(0x15fad9b7ef3a5cbd),CNST_LIMB(0x1874ea34e3e274f9),CNST_LIMB(0x841598977c90581),CNST_LIMB(0x1c04690158b888d)},624,5}, + {CNST_LIMB(0x1f3740adb603b24d),{CNST_LIMB(0x66e52892f80015e),3,CNST_LIMB(0x645fa924fe26d98),CNST_LIMB(0xc022a525d7f5a4f),CNST_LIMB(0x16d7e66846e5d65b),CNST_LIMB(0x10105a92c09c5aa9),CNST_LIMB(0xedddad56d23fc0e)},629,5}, + {CNST_LIMB(0x20e7b3c0e3b73671),{CNST_LIMB(0xf1eabc8c8352c9af),2,CNST_LIMB(0x19aa15b9c5fd82e9),CNST_LIMB(0x10fd7c871bd5d222),CNST_LIMB(0x4ee89a76e1259e0),CNST_LIMB(0x1280d75e6bf3c134),CNST_LIMB(0x85e103f1853c3d)},634,5}, + {CNST_LIMB(0x22b5b4fc40d4c35f),{CNST_LIMB(0xd807362226cc7e50),2,CNST_LIMB(0xd080d1a3a2ea867),CNST_LIMB(0x1f068368adc3fde1),CNST_LIMB(0x178240b1c3cf35a9),CNST_LIMB(0x1dc077b2ed00fd8c),CNST_LIMB(0x2e6e64a07f9c833)},639,5}, + {CNST_LIMB(0x23cff30e6fb8f7fd),{CNST_LIMB(0xc97f150b60a9e71b),2,CNST_LIMB(0x5505a9af1f13815),CNST_LIMB(0x22434bb477153d47),CNST_LIMB(0x87670d53a068a58),CNST_LIMB(0x21b754fa0ae7b745),CNST_LIMB(0x2182750984e9f50b)},644,5}, + {CNST_LIMB(0x266a30ee37cc7341),{CNST_LIMB(0xaa808f26b38df4ef),2,CNST_LIMB(0x1982da6ab1354c7a),CNST_LIMB(0xfda1381ca806f81),CNST_LIMB(0x1a31d30d06bd5b7b),CNST_LIMB(0xbc65e21d25000c6),CNST_LIMB(0x132d8167c6a0973b)},649,5}, + {CNST_LIMB(0x283e6bddfbebab6d),{CNST_LIMB(0x971e4733b2e0d2bf),2,CNST_LIMB(0xe8978cc1879fb72),CNST_LIMB(0x1c9e26afc4d767da),CNST_LIMB(0x1e376fcf488c8249),CNST_LIMB(0x977e63f145b0e1d),CNST_LIMB(0xe2db9891e737aa1)},654,5}, + {CNST_LIMB(0x298d29c47d06f16b),{CNST_LIMB(0x8a4e7f92da9842e7),2,CNST_LIMB(0x6b1056511d6577e),CNST_LIMB(0x592f6f3bbda49cc),CNST_LIMB(0x2692769f01fb0a5b),CNST_LIMB(0x5f3e5623e91d30d),CNST_LIMB(0x2104d5242a92b48d)},659,5}, + {CNST_LIMB(0x2afa8c16de374c13),{CNST_LIMB(0x7d364b6556c2b905),2,CNST_LIMB(0x291b438da8eb83a1),CNST_LIMB(0x14222ff3cbf7d671),CNST_LIMB(0x126ac7f90facd4d3),CNST_LIMB(0x46d452f540a8d2),CNST_LIMB(0xb0b0fc23426b0b7)},664,5}, + {CNST_LIMB(0x2c44b3413ab0dee7),{CNST_LIMB(0x721b37f337583151),2,CNST_LIMB(0x22a87fb9da8ba57d),CNST_LIMB(0x26943e2ad67b49d6),CNST_LIMB(0x1ef6cfa904bef1cd),CNST_LIMB(0x18e7d1baf5588938),CNST_LIMB(0x1ad24c5276c66d2f)},669,5}, + {CNST_LIMB(0x2e88fa7433ac7823),{CNST_LIMB(0x60141b17275393e2),2,CNST_LIMB(0x17531bbafda1a751),CNST_LIMB(0xf3ea18441a36068),CNST_LIMB(0x130110257a01259a),CNST_LIMB(0x14122cf2cde8eecc),CNST_LIMB(0x24d25acd522c56b7)},674,5}, + {CNST_LIMB(0x303fb77cc2bfe62b),{CNST_LIMB(0x539292e31ed6db25),2,CNST_LIMB(0xec16a9032408129),CNST_LIMB(0x22483ceeb16c18a3),CNST_LIMB(0x1dd1cf7128399e5a),CNST_LIMB(0x11b3d478af2cbe42),CNST_LIMB(0x2a86cb29ac9873d3)},679,5}, + {CNST_LIMB(0x32eeac8f8d221e55),{CNST_LIMB(0x41ae89b9e560d65a),2,CNST_LIMB(0x156a1323e556857),CNST_LIMB(0x865eccdcf192078),CNST_LIMB(0x29e9014382ce253e),CNST_LIMB(0x737a633527d55ef),CNST_LIMB(0xe3223c22b887658)},684,5}, + {CNST_LIMB(0x354d75b3270eaedd),{CNST_LIMB(0x336093f2bc204c55),2,CNST_LIMB(0x2aca293363c5448c),CNST_LIMB(0x17160152eb4aa39f),CNST_LIMB(0x16b50b70fa80acee),CNST_LIMB(0x2493bd25f34e1536),CNST_LIMB(0x18f710cf9496617c)},689,5}, + {CNST_LIMB(0x37b26a3f703f6027),{CNST_LIMB(0x2629d54caca5a93b),2,CNST_LIMB(0x213657023f027f64),CNST_LIMB(0x257ed9007720600c),CNST_LIMB(0xaf3dcc0f043ce98),CNST_LIMB(0x115787f3ada80173),CNST_LIMB(0x7071885da2772a7)},694,5}, + {CNST_LIMB(0x3a2d837d37f39e39),{CNST_LIMB(0x199e982941bda182),2,CNST_LIMB(0x1749f20b2031871c),CNST_LIMB(0x153d7d45eae3fbc6),CNST_LIMB(0x3035b3e81047b52f),CNST_LIMB(0x3096ed6d9a28fa5a),CNST_LIMB(0x221887c4142d7434)},699,5}, + {CNST_LIMB(0x3d6201596c85db3f),{CNST_LIMB(0xaea3e9ef4bf14aa),2,CNST_LIMB(0xa77fa9a4de89304),CNST_LIMB(0x140df851fb641569),CNST_LIMB(0x275b27f619d2cffb),CNST_LIMB(0x16df2d5134102662),CNST_LIMB(0x10ab318b9b8a8aef)},704,5}, + {CNST_LIMB(0x401080f68635f765),{CNST_LIMB(0xff7c1a4f020138fa),1,CNST_LIMB(0x3fce7d1c6d5e19d1),CNST_LIMB(0x1feb2b2abf929ebc),CNST_LIMB(0x279cb7a4291af740),CNST_LIMB(0x384bce4293f19637),CNST_LIMB(0x168a9776844c9b6f)},709,5}, + {CNST_LIMB(0x41c3dea2c7c4509b),{CNST_LIMB(0xf2421126ad7a2852),1,CNST_LIMB(0x3ab46417a8b30e2f),CNST_LIMB(0x35206295938b9c19),CNST_LIMB(0x317d8909a9980afe),CNST_LIMB(0x195b889376db752f),CNST_LIMB(0xeb8a8f47083a08e)},714,5}, + {CNST_LIMB(0x441255580dcabef7),{CNST_LIMB(0xe1601977719c2988),1,CNST_LIMB(0x33c8fff7d69fc31b),CNST_LIMB(0x3aa78ab59c61fb90),CNST_LIMB(0x3c41600b3a070fd7),CNST_LIMB(0x121266b65d774473),CNST_LIMB(0x5812c8f46959e7)},719,5}, + {CNST_LIMB(0x467e90ff075dfa77),{CNST_LIMB(0xd0d4ccbfd7fdb2ae),1,CNST_LIMB(0x2c844d02e9e6109b),CNST_LIMB(0x395a6f0c5abc0a3c),CNST_LIMB(0x30393c08245d18c3),CNST_LIMB(0xac042a1b1191d06),CNST_LIMB(0x1d0c88b0cc347eed)},724,5}, + {CNST_LIMB(0x35b7e6a52de6b),{CNST_LIMB(0x30ff8515bed6fc1f),14,CNST_LIMB(0x2f4533b937fab),CNST_LIMB(0xeb33cd2951b7),CNST_LIMB(0x28ce28b5e1739),CNST_LIMB(0x30d609f6bade3),CNST_LIMB(0x249a87bc9957)},729,4}, + {CNST_LIMB(0x4b9237b1fac55af1),{CNST_LIMB(0xb19ac3ed68fa0441),1,CNST_LIMB(0x1d4958ea0fafef2d),CNST_LIMB(0x4ba7c350e3c499e),CNST_LIMB(0xe26c59f6a4a42e5),CNST_LIMB(0x4acd391ac5c14c62),CNST_LIMB(0x38a0169051f4a371)},733,5}, + {CNST_LIMB(0x4fa265b31b73c6df),{CNST_LIMB(0x9b7b0be2fb2dbf62),1,CNST_LIMB(0x1118cee6ada4ab63),CNST_LIMB(0x2b4fe57f0434fb44),CNST_LIMB(0x2cffeb10b15bf6),CNST_LIMB(0xe12f06864906a7b),CNST_LIMB(0x2a0824475f11f823)},738,5}, + {CNST_LIMB(0x516d33f3efe608d5),{CNST_LIMB(0x926c85237f2dc355),1,CNST_LIMB(0xbb86424304de581),CNST_LIMB(0x3ec190a9cee7a48e),CNST_LIMB(0xd7d8bfe60d52602),CNST_LIMB(0xdff7561c9c07756),CNST_LIMB(0x3c1d2db82b327710)},743,5}, + {CNST_LIMB(0x545e342d68fbf683),{CNST_LIMB(0x8464ceb2fdd80297),1,CNST_LIMB(0x2e56377c50c1c77),CNST_LIMB(0x474ec2f4bd92576),CNST_LIMB(0x2a5da9663350db1),CNST_LIMB(0x220077cd63148dd2),CNST_LIMB(0x280dcbaf0c2ad61c)},748,5}, + {CNST_LIMB(0x57e94c457826bd6b),{CNST_LIMB(0x74bd3fdb5c8280eb),1,CNST_LIMB(0x502d67750fb2852a),CNST_LIMB(0x45149579eaa28023),CNST_LIMB(0x3bb53a4c0c4db579),CNST_LIMB(0x3a96a3180f221b2),CNST_LIMB(0x27f9af8526a8cf70)},753,5}, + {CNST_LIMB(0x5b9b45655ebf3b79),{CNST_LIMB(0x65b42a0f00510df2),1,CNST_LIMB(0x48c975354281890e),CNST_LIMB(0x2929df87cfd7453c),CNST_LIMB(0x1b6bb026965ae7ed),CNST_LIMB(0x52659a85b7df96c2),CNST_LIMB(0x21db715c0f72134)},758,5}, + {CNST_LIMB(0x5e6ad0d2eaa14c25),{CNST_LIMB(0x5b0e2387ccda26c3),1,CNST_LIMB(0x432a5e5a2abd67b6),CNST_LIMB(0x14b7571d1a05b77d),CNST_LIMB(0x498547c0b3350ce8),CNST_LIMB(0x9d4e28ce05c6c27),CNST_LIMB(0x4913b5ba5c5edc8)},763,5}, + {CNST_LIMB(0x60704759208cd21d),{CNST_LIMB(0x53c7ef8bdf16795b),1,CNST_LIMB(0x3f1f714dbee65bc6),CNST_LIMB(0x25fc61d1a473562),CNST_LIMB(0x158a2ce0171d5fd),CNST_LIMB(0x2f3bdc4b8520f24c),CNST_LIMB(0x4081386865e00703)},768,5}, + {CNST_LIMB(0x63bc6b32a19c883b),{CNST_LIMB(0x488c1dcdc113150a),1,CNST_LIMB(0x3887299abcc6ef8a),CNST_LIMB(0x2aab5731e10d2529),CNST_LIMB(0x5eeeb60320f0bef4),CNST_LIMB(0x18e4d9f1c279596e),CNST_LIMB(0xf478370d7e2465f)},773,5}, + {CNST_LIMB(0x47f6a9e8dab75),{CNST_LIMB(0xc7577d2a861d140e),13,CNST_LIMB(0x435dc14ffaf0e),CNST_LIMB(0x2557057e3745b),CNST_LIMB(0x450b5149277a6),CNST_LIMB(0xda1fae30c112),CNST_LIMB(0x3951ca3221a2d)},778,4}, + {CNST_LIMB(0x6e373b550764872f),{CNST_LIMB(0x294ecadbf29bc1cb),1,CNST_LIMB(0x23918955f136f1a2),CNST_LIMB(0x29cffcf11c6e3647),CNST_LIMB(0x4af7d1191966b3e0),CNST_LIMB(0x38ebd581ce6f80c6),CNST_LIMB(0x14ebbbc9200a6d59)},782,5}, + {CNST_LIMB(0x4ca8ed991d8b9),{CNST_LIMB(0xab7251b581f8c74d),13,CNST_LIMB(0x1639351769382),CNST_LIMB(0x3145f1b0a8e59),CNST_LIMB(0xff20704d1793),CNST_LIMB(0x1cd9e54d284e),CNST_LIMB(0x1602f3ac7db9c)},787,4}, + {CNST_LIMB(0x74b13dc12b016dc1),{CNST_LIMB(0x18ce87a5c4d39e85),1,CNST_LIMB(0x169d847da9fd247e),CNST_LIMB(0x286e093dede24bb5),CNST_LIMB(0x1854fa948ad9109d),CNST_LIMB(0x6b81a8b81781577c),CNST_LIMB(0xad44a3d15bc6be5)},791,5}, + {CNST_LIMB(0x78b0c5ae997e31ef),{CNST_LIMB(0xf811cf8a4bb1f80),1,CNST_LIMB(0xe9e74a2cd039c22),CNST_LIMB(0x30a04d242d0dfd11),CNST_LIMB(0x128fe81eea336414),CNST_LIMB(0x3639736d1defa144),CNST_LIMB(0x5eeb71b0497f58ff)},796,5}, + {CNST_LIMB(0x7dcf3e856f4612d7),{CNST_LIMB(0x47509bc7743383b),1,CNST_LIMB(0x46182f52173da52),CNST_LIMB(0x430e9fd64eeb40e6),CNST_LIMB(0x2774902fd5f53d5b),CNST_LIMB(0x4f5c0d7033943d05),CNST_LIMB(0x3be559075217f3a8)},801,5}, + {CNST_LIMB(0x550e24ca1a54b),{CNST_LIMB(0x81416693b884d74c),13,CNST_LIMB(0xee45b7c01c48),CNST_LIMB(0x3848946d8aec8),CNST_LIMB(0x541aec862a3ac),CNST_LIMB(0x4f2e818315dbc),CNST_LIMB(0xa8197f5fb2b)},806,4}, + {CNST_LIMB(0x573c8f376a18d),{CNST_LIMB(0x779f50fc3a19a6c9),13,CNST_LIMB(0x4fc81955d5129),CNST_LIMB(0xe80abe2896a1),CNST_LIMB(0x3a505801c159e),CNST_LIMB(0x162eeea75d4cd),CNST_LIMB(0x20dd0efbe8570)},810,4}, + {CNST_LIMB(0x589c3c614e917),{CNST_LIMB(0x71cc8c064f8788ee),13,CNST_LIMB(0x325d12375f7e1),CNST_LIMB(0x514f8f320e7d3),CNST_LIMB(0x55cf104cf51d3),CNST_LIMB(0x23278b29858c6),CNST_LIMB(0x3b956eecbdd30)},814,4}, + {CNST_LIMB(0x5a494bafe993d),{CNST_LIMB(0x6aef2ee9b04422dc),13,CNST_LIMB(0x5111950929bd7),CNST_LIMB(0x2c3779cd17b37),CNST_LIMB(0x2b7f886fc6966),CNST_LIMB(0x4f0b47ffa902d),CNST_LIMB(0x10bd268a51d6c)},818,4}, + {CNST_LIMB(0x5bdea84b0b73f),{CNST_LIMB(0x64adca063056bccb),13,CNST_LIMB(0x427b265a68455),CNST_LIMB(0x2ef4f15ac34a6),CNST_LIMB(0x493c4fd89b0ce),CNST_LIMB(0x7e61acb14b3a),CNST_LIMB(0x20d0328207c83)},822,4}, + {CNST_LIMB(0x5d4c55a25a945),{CNST_LIMB(0x5f37ce4e679bb0c3),13,CNST_LIMB(0x5b08caebb5502),CNST_LIMB(0x3d0eab29a51f1),CNST_LIMB(0x3c9ac2f5a187d),CNST_LIMB(0x29304bdf75a79),CNST_LIMB(0x14d681f7ea1f0)},826,4}, + {CNST_LIMB(0x5f286a042b527),{CNST_LIMB(0x585aa50035c6eb19),13,CNST_LIMB(0x1f74be8b4aa53),CNST_LIMB(0x47290f02b2679),CNST_LIMB(0x44c4bd1ee1378),CNST_LIMB(0x51286cbc40de1),CNST_LIMB(0xc379e189a860)},830,4}, + {CNST_LIMB(0x62521adc68615),{CNST_LIMB(0x4d46d1e25221a4ef),13,CNST_LIMB(0x53d112a3ea538),CNST_LIMB(0x26e6ad330e6d8),CNST_LIMB(0x56830d4191021),CNST_LIMB(0xed06536bee19),CNST_LIMB(0x5ba5998aa1cbd)},834,4}, + {CNST_LIMB(0x64f0108522a4b),{CNST_LIMB(0x44a2bea99b1fe52b),13,CNST_LIMB(0x22a1a59e3d4a4),CNST_LIMB(0x55422d57d71a4),CNST_LIMB(0x48b99527500ba),CNST_LIMB(0x5dffbfb3a890f),CNST_LIMB(0x618de61d17b82)},838,4}, + {CNST_LIMB(0x684eced8d04ad),{CNST_LIMB(0x3a25a4304e45cd70),13,CNST_LIMB(0x498e06ad4670c),CNST_LIMB(0x6397605c9b1d3),CNST_LIMB(0x1107048baaf16),CNST_LIMB(0x6292ac8aeb164),CNST_LIMB(0x4def8ba3a7552)},842,4}, + {CNST_LIMB(0x69e938da0b6b9),{CNST_LIMB(0x35644b98f3e9b802),13,CNST_LIMB(0x38dd6fce5c5b4),CNST_LIMB(0x6307e2db6000d),CNST_LIMB(0x56835d316819f),CNST_LIMB(0x2b1da7eb24a08),CNST_LIMB(0xf110b6d6a913)},846,4}, + {CNST_LIMB(0x6bf4be42947af),{CNST_LIMB(0x2f87eee6ccd631e7),13,CNST_LIMB(0x6b0e021f080f0),CNST_LIMB(0x4b469e0f2c53a),CNST_LIMB(0x50664c269b5e3),CNST_LIMB(0x4139b73b961d6),CNST_LIMB(0x13dc91bdbee0f)},850,4}, + {CNST_LIMB(0x6f54dbd6ccf57),{CNST_LIMB(0x26540878c92cd039),13,CNST_LIMB(0x382053afc295a),CNST_LIMB(0x2c8c19e89353d),CNST_LIMB(0x534384d9aa927),CNST_LIMB(0x249d03e328fc1),CNST_LIMB(0x2c57702938274)},854,4}, + {CNST_LIMB(0x71632fdcf6c15),{CNST_LIMB(0x20fdcdbf333d83af),13,CNST_LIMB(0x5242218aef575),CNST_LIMB(0x9ab7cecd8cd3),CNST_LIMB(0x4ea4e8bc18b4d),CNST_LIMB(0x16d9320fd98f4),CNST_LIMB(0x2d2b50a730c10)},858,4}, + {CNST_LIMB(0x7317fb257e1e1),{CNST_LIMB(0x1cb50c1361edfd6e),13,CNST_LIMB(0x489cb7c9fe32a),CNST_LIMB(0x258cf78a73422),CNST_LIMB(0x560fbee8c2cf2),CNST_LIMB(0x467156be8e294),CNST_LIMB(0xc593edc4d71f)},862,4}, + {CNST_LIMB(0x75e5d5c5e4577),{CNST_LIMB(0x15ef86e1cee16113),13,CNST_LIMB(0x6eece492ce925),CNST_LIMB(0x561b9134c02bf),CNST_LIMB(0x596b2a81ab56d),CNST_LIMB(0x296835004dd20),CNST_LIMB(0x3160915ef8c65)},866,4}, + {CNST_LIMB(0x788a813bc2fb1),{CNST_LIMB(0xfd74e4e944c107b),13,CNST_LIMB(0x6e15178139c26),CNST_LIMB(0x7828db84f90d2),CNST_LIMB(0x3e1e0cdc0bb1c),CNST_LIMB(0x4bbcd0685b013),CNST_LIMB(0x60b28bb37de31)},870,4}, + {CNST_LIMB(0x7b02c02e67beb),{CNST_LIMB(0xa621b97c2ae6cdb),13,CNST_LIMB(0x2068f6d99eb3c),CNST_LIMB(0x4ba3bacf8ed2f),CNST_LIMB(0x79baf6516f06a),CNST_LIMB(0x34fac2ffdfb3b),CNST_LIMB(0x601bda55ddca3)},874,4}, + {CNST_LIMB(0x7d0b0166731df),{CNST_LIMB(0x60dcab2ebe68654),13,CNST_LIMB(0x5a87235f786e1),CNST_LIMB(0x498c71a4f2c04),CNST_LIMB(0x6c4cf93aac90f),CNST_LIMB(0x2fc43a717ef2e),CNST_LIMB(0x61100c40f26dc)},878,4}, + {CNST_LIMB(0x7f65827009e4b),{CNST_LIMB(0x13671d16472022c),13,CNST_LIMB(0x66a0a221f20de),CNST_LIMB(0x1863cc32757a5),CNST_LIMB(0x72205d2b707de),CNST_LIMB(0x41eb3856479f4),CNST_LIMB(0x62a869dadecf2)},882,4}, + {CNST_LIMB(0x826267aca5d6b),{CNST_LIMB(0xf6a307f100c87643),12,CNST_LIMB(0x18b32a6e55cb2),CNST_LIMB(0x800c79d089746),CNST_LIMB(0x4df069eb6014f),CNST_LIMB(0xa67afd1d0f6b),CNST_LIMB(0x39654bc96e516)},886,4}, + {CNST_LIMB(0x854fadbb02f0d),{CNST_LIMB(0xeb99f80c181c04d8),12,CNST_LIMB(0x530f8982a799b),CNST_LIMB(0x488a5468d8f30),CNST_LIMB(0xcb498b28c81),CNST_LIMB(0x1d791c8466f6a),CNST_LIMB(0x583d384518de9)},890,4}, + {CNST_LIMB(0x86f75f67e5373),{CNST_LIMB(0xe592b4846fa38885),12,CNST_LIMB(0x16d1a804d8305),CNST_LIMB(0x3a9f7db1defba),CNST_LIMB(0x53fa43529d63d),CNST_LIMB(0x380980122856a),CNST_LIMB(0x59320408536cb)},894,4}, + {CNST_LIMB(0x89110415e014b),{CNST_LIMB(0xde220b6a3ca63611),12,CNST_LIMB(0x1183ea4dd5cca),CNST_LIMB(0x6cd0a51299316),CNST_LIMB(0x2c53d4f8b0ee6),CNST_LIMB(0x39ef54aed56eb),CNST_LIMB(0x7f71b2a9bf0fd)},898,4}, + {CNST_LIMB(0x8bbeefef93d97),{CNST_LIMB(0xd4f7338df110e1c1),12,CNST_LIMB(0x3ee5d151be367),CNST_LIMB(0x2e6b9dfc4bbcb),CNST_LIMB(0x225349b2e386e),CNST_LIMB(0x492ce15456b18),CNST_LIMB(0x856a0d6e68759)},902,4}, + {CNST_LIMB(0x8fa29248f38e9),{CNST_LIMB(0xc84479a2d3ad73b2),12,CNST_LIMB(0x282c97bed2bdc),CNST_LIMB(0x86b44220fa8e0),CNST_LIMB(0x497c548d39ada),CNST_LIMB(0x6928a8433805d),CNST_LIMB(0x1d2f77b091c29)},906,4}, + {CNST_LIMB(0x9311da8eb3ea1),{CNST_LIMB(0xbd9c9989aacc578d),12,CNST_LIMB(0x73d0b00fcee87),CNST_LIMB(0x44acd3ec00c9b),CNST_LIMB(0x3b8ead35b82f4),CNST_LIMB(0x7a1ca1fa55a8c),CNST_LIMB(0x98634149273d)},910,4}, + {CNST_LIMB(0x96fc1b51999b5),{CNST_LIMB(0xb20e950936df3d71),12,CNST_LIMB(0x899afa996b260),CNST_LIMB(0x2d7d06dae3233),CNST_LIMB(0x143e323027e28),CNST_LIMB(0x8483b9a26498e),CNST_LIMB(0x689b7b1e2fc91)},914,4}, + {CNST_LIMB(0x99d2dc5aa820b),{CNST_LIMB(0xaa0bd71d4333c056),12,CNST_LIMB(0x71d5124399b20),CNST_LIMB(0x62e94421a897f),CNST_LIMB(0x892c96c6ff4dc),CNST_LIMB(0x54dc6420d0ec4),CNST_LIMB(0x43a10331ebf4f)},918,4}, + {CNST_LIMB(0x9c18c1a21f755),{CNST_LIMB(0xa3d7a1305040e509),12,CNST_LIMB(0x4a6f652c96ebf),CNST_LIMB(0x92a1dbc9a1bc4),CNST_LIMB(0x7856fe0adb2e7),CNST_LIMB(0x65020d02f02aa),CNST_LIMB(0x7983e2f6dcbd)},922,4}, + {CNST_LIMB(0xa019a0d84ce05),{CNST_LIMB(0x99580856e1c2e36b),12,CNST_LIMB(0x5060429959a17),CNST_LIMB(0x8af3dd6c8fedb),CNST_LIMB(0x8521b97cefc72),CNST_LIMB(0x7289dc3848291),CNST_LIMB(0x51cb410c11cef)},926,4}, + {CNST_LIMB(0xa3837104af50b),{CNST_LIMB(0x90cc816ca127f31c),12,CNST_LIMB(0x7fcd3ea8e707c),CNST_LIMB(0x1ea9bdca73534),CNST_LIMB(0x3d0d37ad79bcf),CNST_LIMB(0x78befa2ea5ef8),CNST_LIMB(0x8c7846571c14b)},930,4}, + {CNST_LIMB(0xa74ba276e925b),{CNST_LIMB(0x87bcf3ca6aa1f420),12,CNST_LIMB(0x876dcb0272647),CNST_LIMB(0x63761f150b253),CNST_LIMB(0xa347a550c386b),CNST_LIMB(0xb7438cfe5ad4),CNST_LIMB(0x7bca2b8c0aabf)},934,4}, + {CNST_LIMB(0xad0c05b3ae661),{CNST_LIMB(0x7ab7cf1782b58dcf),12,CNST_LIMB(0x54750c4f56635),CNST_LIMB(0x2eac67167559c),CNST_LIMB(0x563c222f2aff7),CNST_LIMB(0x7b738313b7ac1),CNST_LIMB(0x65d997bccd9d9)},938,4}, + {CNST_LIMB(0xb0da5211cc3e7),{CNST_LIMB(0x72916ab867f7595c),12,CNST_LIMB(0xfa941ccadf01),CNST_LIMB(0x8d756d36295ea),CNST_LIMB(0x4f9f479e132fd),CNST_LIMB(0x18526df562fde),CNST_LIMB(0x434f07e1d9d33)},942,4}, + {CNST_LIMB(0xb36ca8c3991af),{CNST_LIMB(0x6d41bd767e129ba0),12,CNST_LIMB(0x13836edce5114),CNST_LIMB(0xa52c71bc138ab),CNST_LIMB(0x339d5f264e899),CNST_LIMB(0x65473fc2cfa57),CNST_LIMB(0x4714fd9da5ac0)},946,4}, + {CNST_LIMB(0xb6694790c60df),{CNST_LIMB(0x6746add17a9a2fee),12,CNST_LIMB(0x4c2521610f0f4),CNST_LIMB(0x1ef55755cab96),CNST_LIMB(0x3bb413c494cbb),CNST_LIMB(0x59bedca68abba),CNST_LIMB(0x618c95ba5598b)},950,4}, + {CNST_LIMB(0xb89a345c48d7d),{CNST_LIMB(0x6302ff6c309d06ee),12,CNST_LIMB(0x2296406fcba90),CNST_LIMB(0x4d697f4e83909),CNST_LIMB(0xa16067eedb775),CNST_LIMB(0xa50f824607f2b),CNST_LIMB(0x3d3946b54c9f9)},954,4}, + {CNST_LIMB(0xbb02a8b8a132b),{CNST_LIMB(0x5e70bfded3b337fc),12,CNST_LIMB(0x8c29c2d62d33),CNST_LIMB(0x3f082e296ef8f),CNST_LIMB(0x49afe57a19b90),CNST_LIMB(0xb7bd5be58da15),CNST_LIMB(0x8de61bd7e627f)},958,4}, + {CNST_LIMB(0xbd6468bb171ff),{CNST_LIMB(0x5a0880d51b052fd7),12,CNST_LIMB(0x64a7322bed5a0),CNST_LIMB(0x3f94ed2b89267),CNST_LIMB(0x980b9bde44b2d),CNST_LIMB(0x4a6676c0e7d13),CNST_LIMB(0xb24baad1f0c40)},962,4}, + {CNST_LIMB(0xc17671b548641),{CNST_LIMB(0x52c0b00a813a011e),12,CNST_LIMB(0x85095e7597d4),CNST_LIMB(0x55524352a702c),CNST_LIMB(0x868164742fab5),CNST_LIMB(0x3b3bcfdffb2cf),CNST_LIMB(0xab11b067d542f)},966,4}, + {CNST_LIMB(0xc57f07d496e1b),{CNST_LIMB(0x4bd58ed22f4b2aac),12,CNST_LIMB(0x449a9c42f9a11),CNST_LIMB(0x2b9c2279a88de),CNST_LIMB(0xa905cf41733e1),CNST_LIMB(0x206b2bfa8b896),CNST_LIMB(0xb378d16c66efd)},970,4}, + {CNST_LIMB(0xc814b88200ac3),{CNST_LIMB(0x478c251716699c98),12,CNST_LIMB(0x97df5b023b898),CNST_LIMB(0x5507d796eedc1),CNST_LIMB(0xb4a34312d58e3),CNST_LIMB(0x4324fc6d4f6f2),CNST_LIMB(0x29d3a7f3d88da)},974,4}, + {CNST_LIMB(0xcb958ba8e9259),{CNST_LIMB(0x41e93d5390ce4a3c),12,CNST_LIMB(0x75906ffdbe592),CNST_LIMB(0x35d1e8b619b02),CNST_LIMB(0x5535c122a3ba7),CNST_LIMB(0xb2c9d287f29c8),CNST_LIMB(0x7f9a7f1adf9d9)},978,4}, + {CNST_LIMB(0xcfaa956d67517),{CNST_LIMB(0x3b9549c76b39f2a8),12,CNST_LIMB(0x44a2e5454ad61),CNST_LIMB(0xa8d0541bab05b),CNST_LIMB(0x801e8693083d4),CNST_LIMB(0xc17c6af57bddf),CNST_LIMB(0xc7b4d9a0870d9)},982,4}, + {CNST_LIMB(0xd56380a0e8273),{CNST_LIMB(0x331ecd3feca3d608),12,CNST_LIMB(0xc5686ff8a7efd),CNST_LIMB(0x61e35c54a4f3f),CNST_LIMB(0x4bf5dc73ede0f),CNST_LIMB(0x2bf7f029f09a5),CNST_LIMB(0x718dc3463c882)},986,4}, + {CNST_LIMB(0xd9c8b65d94f5b),{CNST_LIMB(0x2cec062e71d179c4),12,CNST_LIMB(0xa3aaac38dbec6),CNST_LIMB(0x78cabf09fa56c),CNST_LIMB(0xcaf0fccc6b30b),CNST_LIMB(0xce30344eb1fac),CNST_LIMB(0x4ba46e5575b11)},990,4}, + {CNST_LIMB(0xdc90a482debcb),{CNST_LIMB(0x2920b89d6fc02e7f),12,CNST_LIMB(0x9f0f9b3b403a),CNST_LIMB(0x619327b332542),CNST_LIMB(0xa75eae1f8ff9f),CNST_LIMB(0x62350a1cba491),CNST_LIMB(0x22ac2e8eb19f9)},994,4}, + {CNST_LIMB(0xe0ac9922e6235),{CNST_LIMB(0x23b187206556b5c4),12,CNST_LIMB(0x157440c67a3c9),CNST_LIMB(0x696b5be3cc464),CNST_LIMB(0x2ebcde890e790),CNST_LIMB(0xae767f93832de),CNST_LIMB(0xcb1eade2d80a8)},998,4} +#endif diff --git a/repos/libports/lib/import/import-gmp.mk b/repos/libports/lib/import/import-gmp.mk index aabc59d7e..0ca6f3769 100644 --- a/repos/libports/lib/import/import-gmp.mk +++ b/repos/libports/lib/import/import-gmp.mk @@ -9,6 +9,10 @@ ifeq ($(filter-out $(SPECS),arm),) INC_DIR += $(GMP_PORT_DIR)/include/spec/arm endif +ifeq ($(filter-out $(SPECS),arm_64),) + REP_INC_DIR += include/spec/64bit/gmp + INC_DIR += $(GMP_PORT_DIR)/include/spec/arm_64 +endif ifeq ($(filter-out $(SPECS),x86_32),) REP_INC_DIR += include/spec/32bit/gmp INC_DIR += $(GMP_PORT_DIR)/include/spec/x86_32 diff --git a/repos/libports/lib/mk/gcov-libcommon.mk b/repos/libports/lib/mk/gcov-libcommon.mk index e8e9d98f2..0826458ed 100644 --- a/repos/libports/lib/mk/gcov-libcommon.mk +++ b/repos/libports/lib/mk/gcov-libcommon.mk @@ -33,6 +33,10 @@ ifeq ($(filter-out $(SPECS),arm),) INC_DIR += $(GCOV_PORT_DIR)/include/arm/gcc endif +ifeq ($(filter-out $(SPECS),arm_64),) + INC_DIR += $(GCOV_PORT_DIR)/include/arm_64/gcc +endif + ifeq ($(filter-out $(SPECS),x86_32),) INC_DIR += $(GCOV_PORT_DIR)/include/x86_32/gcc endif diff --git a/repos/libports/lib/mk/gcov-libcpp.mk b/repos/libports/lib/mk/gcov-libcpp.mk index 785c5809d..25a2e1333 100644 --- a/repos/libports/lib/mk/gcov-libcpp.mk +++ b/repos/libports/lib/mk/gcov-libcpp.mk @@ -13,6 +13,10 @@ ifeq ($(filter-out $(SPECS),arm),) INC_DIR += $(GCOV_PORT_DIR)/include/arm/libcpp endif +ifeq ($(filter-out $(SPECS),arm_64),) + INC_DIR += $(GCOV_PORT_DIR)/include/arm_64/libcpp +endif + ifeq ($(filter-out $(SPECS),x86_32),) INC_DIR += $(GCOV_PORT_DIR)/include/x86_32/libcpp endif diff --git a/repos/libports/lib/mk/gcov-libiberty.mk b/repos/libports/lib/mk/gcov-libiberty.mk index a8b700b98..654056f39 100644 --- a/repos/libports/lib/mk/gcov-libiberty.mk +++ b/repos/libports/lib/mk/gcov-libiberty.mk @@ -35,6 +35,10 @@ ifeq ($(filter-out $(SPECS),arm),) INC_DIR += $(GCOV_PORT_DIR)/include/arm/libiberty endif +ifeq ($(filter-out $(SPECS),arm_64),) + INC_DIR += $(GCOV_PORT_DIR)/include/arm_64/libiberty +endif + ifeq ($(filter-out $(SPECS),x86_32),) INC_DIR += $(GCOV_PORT_DIR)/include/x86_32/libiberty endif diff --git a/repos/libports/lib/mk/gmp.inc b/repos/libports/lib/mk/gmp.inc index e0d8ceb1a..f8c15e4b4 100644 --- a/repos/libports/lib/mk/gmp.inc +++ b/repos/libports/lib/mk/gmp.inc @@ -4,7 +4,7 @@ include $(REP_DIR)/lib/import/import-gmp.mk LIBS += libc -CC_OPT += -DHAVE_CONFIG_H -D__GMP_WITHIN_GMP +CC_OPT += -DHAVE_CONFIG_H -D__GMP_WITHIN_GMP -DCOUNT_LEADING_ZEROS_NEED_CLZ_TAB INC_DIR += $(REP_DIR)/include/gcc INC_DIR += $(GMP_DIR) diff --git a/repos/libports/lib/mk/gmp.mk b/repos/libports/lib/mk/gmp.mk index 28df961e8..17482e83d 100644 --- a/repos/libports/lib/mk/gmp.mk +++ b/repos/libports/lib/mk/gmp.mk @@ -21,6 +21,7 @@ SRC_C += $(notdir $(wildcard $(GMP_DIR)/scanf/*.c)) vpath %.c $(GMP_DIR) vpath %.c $(GMP_DIR)/printf vpath %.c $(GMP_DIR)/scanf +vpath %.c $(GMP_DIR)/rand SHARED_LIB = yes diff --git a/repos/libports/lib/mk/libc-mem.mk b/repos/libports/lib/mk/libc-mem.mk index afd682deb..c1f196759 100644 --- a/repos/libports/lib/mk/libc-mem.mk +++ b/repos/libports/lib/mk/libc-mem.mk @@ -2,6 +2,8 @@ SRC_CC = libc_mem_alloc.cc include $(REP_DIR)/lib/mk/libc-common.inc +INC_DIR += $(REP_DIR)/src/lib/libc + vpath libc_mem_alloc.cc $(REP_DIR)/src/lib/libc CC_CXX_WARN_STRICT = diff --git a/repos/libports/lib/mk/libc.mk b/repos/libports/lib/mk/libc.mk index e9596baf6..bd2bbbc33 100644 --- a/repos/libports/lib/mk/libc.mk +++ b/repos/libports/lib/mk/libc.mk @@ -17,14 +17,14 @@ SRC_CC = atexit.cc dummies.cc rlimit.cc sysctl.cc \ plugin.cc plugin_registry.cc select.cc exit.cc environ.cc sleep.cc \ pread_pwrite.cc readv_writev.cc poll.cc \ vfs_plugin.cc dynamic_linker.cc signal.cc \ - socket_operations.cc task.cc socket_fs_plugin.cc syscall.cc \ - getpwent.cc getrandom.cc fork.cc execve.cc + socket_operations.cc socket_fs_plugin.cc syscall.cc legacy.cc \ + getpwent.cc getrandom.cc fork.cc execve.cc kernel.cc component.cc # # Pthreads # SRC_CC += semaphore.cc rwlock.cc \ - thread.cc thread_create.cc + pthread.cc pthread_create.cc # # FreeBSD headers use the C99 restrict keyword diff --git a/repos/libports/lib/mk/libc_fatfs.mk b/repos/libports/lib/mk/libc_fatfs.mk deleted file mode 100644 index fa9d4699b..000000000 --- a/repos/libports/lib/mk/libc_fatfs.mk +++ /dev/null @@ -1,8 +0,0 @@ -SRC_CC = plugin.cc -LIBS += libc fatfs_block - -vpath plugin.cc $(REP_DIR)/src/lib/libc_fatfs - -SHARED_LIB = yes - -CC_CXX_WARN_STRICT = diff --git a/repos/libports/lib/mk/libgcov.mk b/repos/libports/lib/mk/libgcov.mk index c8cc89bd2..13ca536bb 100644 --- a/repos/libports/lib/mk/libgcov.mk +++ b/repos/libports/lib/mk/libgcov.mk @@ -50,6 +50,11 @@ ifeq ($(filter-out $(SPECS),arm),) $(GCOV_PORT_DIR)/include/arm/libgcc endif +ifeq ($(filter-out $(SPECS),arm_64),) + INC_DIR += $(GCOV_PORT_DIR)/include/arm_64/gcc \ + $(GCOV_PORT_DIR)/include/arm_64/libgcc +endif + ifeq ($(filter-out $(SPECS),x86_32),) INC_DIR += $(GCOV_PORT_DIR)/include/x86_32/gcc \ $(GCOV_PORT_DIR)/include/x86_32/libgcc diff --git a/repos/libports/lib/mk/mpfr.mk b/repos/libports/lib/mk/mpfr.mk index 5d7b50c64..028ce155f 100644 --- a/repos/libports/lib/mk/mpfr.mk +++ b/repos/libports/lib/mk/mpfr.mk @@ -1,14 +1,18 @@ MPFR_PORT_DIR := $(call select_from_ports,mpfr) LIBS = libc gmp -CC_OPT += -DHAVE_STDARG -DHAVE_VA_COPY -DHAVE_INTTYPES_H -INC_DIR += $(REP_DIR)/include/mpfr $(MPFR_PORT_DIR)/include/mpfr -MPFR_SRC_C := $(notdir $(wildcard $(MPFR_PORT_DIR)/src/lib/mpfr/*.c)) -FILTER_OUT := ansi2knr.c jyn_asympt.c round_raw_generic.c speed.c tuneup.c +CC_OPT += -DHAVE_STDARG -DHAVE_VA_COPY -DHAVE_INTTYPES_H -DHAVE_LITTLE_ENDIAN + +INC_DIR += $(REP_DIR)/include/mpfr \ + $(MPFR_PORT_DIR)/include/mpfr \ + $(MPFR_PORT_DIR)/include + +MPFR_SRC_C := $(notdir $(wildcard $(MPFR_PORT_DIR)/src/lib/mpfr/src/*.c)) +FILTER_OUT := jyn_asympt.c round_raw_generic.c SRC_C := $(filter-out $(FILTER_OUT),$(MPFR_SRC_C)) -vpath %.c $(MPFR_PORT_DIR)/src/lib/mpfr +vpath %.c $(MPFR_PORT_DIR)/src/lib/mpfr/src SHARED_LIB = 1 diff --git a/repos/libports/lib/mk/qt5_gui.mk b/repos/libports/lib/mk/qt5_gui.mk index 35f1b660d..bb0e0d7ba 100644 --- a/repos/libports/lib/mk/qt5_gui.mk +++ b/repos/libports/lib/mk/qt5_gui.mk @@ -15,6 +15,13 @@ QT_SOURCES_FILTER_OUT = \ qdrawhelper_sse2.cpp \ qimage_sse2.cpp +ifeq ($(filter-out $(SPECS),arm_64),) +QT_DEFINES += -UENABLE_PIXMAN_DRAWHELPERS +QT_SOURCES += qdrawhelper_neon.cpp \ + qimage_neon.cpp \ + qimagescale_neon.cpp +endif + # remove unneeded files to prevent moc warnings COMPILER_MOC_HEADER_MAKE_ALL_FILES_FILTER_OUT = \ moc_qsessionmanager.cpp \ diff --git a/repos/libports/lib/mk/spec/arm/gmp-mpn.mk b/repos/libports/lib/mk/spec/arm/gmp-mpn.mk index 153a55870..fe2d1c274 100644 --- a/repos/libports/lib/mk/spec/arm/gmp-mpn.mk +++ b/repos/libports/lib/mk/spec/arm/gmp-mpn.mk @@ -16,6 +16,8 @@ FILTER_OUT += add_n.c SRC_ASM += sub_n.asm FILTER_OUT += sub_n.c +FILTER_OUT += logops_n.c sec_div.c sec_pi1_div.c copyi.c copyd.c + SRC_C += $(notdir $(wildcard $(REP_DIR)/src/lib/gmp/mpn/spec/32bit/*.c)) SRC_C += $(filter-out $(FILTER_OUT),$(notdir $(wildcard $(GMP_MPN_DIR)/generic/*.c))) diff --git a/repos/libports/lib/mk/spec/arm/libc.mk b/repos/libports/lib/mk/spec/arm/libc.mk index 9dc4d9ca8..56dd9171f 100644 --- a/repos/libports/lib/mk/spec/arm/libc.mk +++ b/repos/libports/lib/mk/spec/arm/libc.mk @@ -1,6 +1,6 @@ include $(REP_DIR)/lib/mk/libc.mk -INC_DIR += $(REP_DIR)/src/lib/libc/include/spec/arm +INC_DIR += $(REP_DIR)/src/lib/libc/spec/arm INC_DIR += $(LIBC_DIR)/include/spec/arm CC_CXX_WARN_STRICT = diff --git a/repos/libports/lib/mk/spec/arm_64/gmp-mpn.mk b/repos/libports/lib/mk/spec/arm_64/gmp-mpn.mk new file mode 100644 index 000000000..3797c6366 --- /dev/null +++ b/repos/libports/lib/mk/spec/arm_64/gmp-mpn.mk @@ -0,0 +1,60 @@ + +GMP_MPN_DIR = $(GMP_DIR)/mpn + +# this file uses the 'sdiv_qrnnd' symbol which is not defined +FILTER_OUT += udiv_w_sdiv.c + +# add ARM-specific assembly files and filter out the generic C files if needed + +SRC_ASM += copyd.asm copyi.asm + +FILTER_OUT += popham.c +FILTER_OUT += logops_n.c sec_div.c sec_pi1_div.c copyi.c copyd.c + +SRC_C += $(notdir $(wildcard $(REP_DIR)/src/lib/gmp/mpn/spec/64bit/*.c)) +SRC_C += $(filter-out $(FILTER_OUT),$(notdir $(wildcard $(GMP_MPN_DIR)/generic/*.c))) + +include $(REP_DIR)/lib/mk/gmp.inc + +PWD := $(shell pwd) + +SRC_O += $(SRC_ASM:.asm=.o) hamdist.o popcount.o + +# +# Create execution environment for the m4-ccas tool, which is used by the gmp +# library to assemble asm files to object files. Make sure to execute this rule +# only from the actual build pass (not when called from 'dep_lib.mk'). This +# way, the 'm4env' gets created within the local build directory of the +# library, not the global build directory. +# +ifeq ($(called_from_lib_mk),yes) +all: m4env +endif + +m4env: + $(VERBOSE)mkdir -p $@/mpn/arm_64 + $(VERBOSE)ln -s $(REP_DIR)/src/lib/gmp/spec/arm_64/config.m4 m4env + $(VERBOSE)ln -s $(GMP_MPN_DIR)/asm-defs.m4 m4env/mpn + +# +# Create object files out of asm files +# +ifneq ($(VERBOSE),) +M4_OUTPUT_FILTER = > /dev/null +endif + +hamdist.o popcount.o: popham.c + $(MSG_COMP)$@ + $(VERBOSE)$(CC) $(CC_DEF) $(CC_C_OPT) -DOPERATION_${@:.o=} $(INCLUDES) -c $< -o $@ + +%.o: %.asm + $(MSG_ASSEM)$@ + $(VERBOSE)cd m4env/mpn; \ + $(GMP_MPN_DIR)/m4-ccas --m4=m4 $(CC) $(CC_MARCH) -std=gnu99 -fPIC -DPIC $(CC_OPT_$*) $(INCLUDES) -c $< -o $(PWD)/$@ \ + $(M4_OUTPUT_FILTER) + +vpath %.c $(REP_DIR)/src/lib/gmp/mpn/spec/64bit +vpath %.c $(GMP_MPN_DIR)/generic +vpath %.asm $(GMP_MPN_DIR)/arm64 + +CC_CXX_WARN_STRICT = diff --git a/repos/libports/lib/mk/spec/arm_64/libc.mk b/repos/libports/lib/mk/spec/arm_64/libc.mk index 7fd7c2137..582a70c9c 100644 --- a/repos/libports/lib/mk/spec/arm_64/libc.mk +++ b/repos/libports/lib/mk/spec/arm_64/libc.mk @@ -1,6 +1,6 @@ include $(REP_DIR)/lib/mk/libc.mk -INC_DIR += $(REP_DIR)/src/lib/libc/include/spec/arm_64 +INC_DIR += $(REP_DIR)/src/lib/libc/spec/arm_64 INC_DIR += $(LIBC_DIR)/include/spec/arm_64 CC_CXX_WARN_STRICT = diff --git a/repos/libports/lib/mk/spec/x86_32/gmp-mpn.mk b/repos/libports/lib/mk/spec/x86_32/gmp-mpn.mk index 25bfa8225..3deace498 100644 --- a/repos/libports/lib/mk/spec/x86_32/gmp-mpn.mk +++ b/repos/libports/lib/mk/spec/x86_32/gmp-mpn.mk @@ -12,7 +12,7 @@ FILTER_OUT += udiv_w_sdiv.c SRC_ASM += copyd.asm copyi.asm hamdist.asm SRC_ASM += popcount.asm -FILTER_OUT += popham.c +FILTER_OUT += popham.c logops_n.c sec_div.c sec_pi1_div.c copyi.c copyd.c SRC_ASM += add_n.asm FILTER_OUT += add_n.c diff --git a/repos/libports/lib/mk/spec/x86_32/libc.mk b/repos/libports/lib/mk/spec/x86_32/libc.mk index 9db361f55..3a4083e65 100644 --- a/repos/libports/lib/mk/spec/x86_32/libc.mk +++ b/repos/libports/lib/mk/spec/x86_32/libc.mk @@ -1,6 +1,6 @@ include $(REP_DIR)/lib/mk/libc.mk -INC_DIR += $(REP_DIR)/src/lib/libc/include/spec/x86_32 +INC_DIR += $(REP_DIR)/src/lib/libc/spec/x86_32 INC_DIR += $(LIBC_DIR)/include/spec/x86_32 SRC_C += msun/i387/fenv.c diff --git a/repos/libports/lib/mk/spec/x86_64/gmp-mpn.mk b/repos/libports/lib/mk/spec/x86_64/gmp-mpn.mk index fe9cd9c2a..27c516fd9 100644 --- a/repos/libports/lib/mk/spec/x86_64/gmp-mpn.mk +++ b/repos/libports/lib/mk/spec/x86_64/gmp-mpn.mk @@ -4,11 +4,12 @@ GMP_MPN_DIR = $(GMP_DIR)/mpn # this file uses the 'sdiv_qrnnd' symbol which is not defined FILTER_OUT += udiv_w_sdiv.c -FILTER_OUT += pre_divrem_1.c +FILTER_OUT += pre_divrem_1.c sec_div.c sec_pi1_div.c copyi.c copyd.c + # add x86_64-specific assembly files and filter out the generic C files if needed -SRC_ASM += copyd.asm copyi.asm +SRC_ASM += copyd.asm copyi.asm invert_limb.asm invert_limb_table.asm CC_OPT_add_n = -DOPERATION_add_n CC_OPT_sub_n = -DOPERATION_sub_n diff --git a/repos/libports/lib/mk/spec/x86_64/libc.mk b/repos/libports/lib/mk/spec/x86_64/libc.mk index 52889ad93..40e09d41b 100644 --- a/repos/libports/lib/mk/spec/x86_64/libc.mk +++ b/repos/libports/lib/mk/spec/x86_64/libc.mk @@ -1,8 +1,6 @@ include $(REP_DIR)/lib/mk/libc.mk - - -INC_DIR += $(REP_DIR)/src/lib/libc/include/spec/x86_64 +INC_DIR += $(REP_DIR)/src/lib/libc/spec/x86_64 INC_DIR += $(LIBC_DIR)/include/spec/x86_64 CC_CXX_WARN_STRICT = diff --git a/repos/libports/lib/symbols/gmp b/repos/libports/lib/symbols/gmp index 582cbdd4e..dc22e3b24 100644 --- a/repos/libports/lib/symbols/gmp +++ b/repos/libports/lib/symbols/gmp @@ -142,7 +142,7 @@ __gmpn_add_n T __gmpn_addmul_1 T __gmpn_addmul_2 T __gmpn_addsub_n T -__gmpn_bases R 8224 +__gmpn_bases R 10280 __gmpn_bc_set_str T __gmpn_bdiv_dbm1c T __gmpn_bdivmod T diff --git a/repos/libports/lib/symbols/libc b/repos/libports/lib/symbols/libc index 69e67d1c4..07815ac2a 100644 --- a/repos/libports/lib/symbols/libc +++ b/repos/libports/lib/symbols/libc @@ -962,9 +962,9 @@ _ZN4Libc19Select_handler_baseD2Ev T _ZN4Libc10resume_allEv T _ZN4Libc7suspendERNS_15Suspend_functorEm T _Z16pthread_registryv T -_ZN16Pthread_registry6insertEP7pthread T -_ZN16Pthread_registry6removeEP7pthread T -_ZN16Pthread_registry8containsEP7pthread T +_ZN4Libc16Pthread_registry6insertERNS_7PthreadE T +_ZN4Libc16Pthread_registry6removeERNS_7PthreadE T +_ZN4Libc16Pthread_registry8containsERNS_7PthreadE T _ZN4Libc14pthread_createEPP7pthreadPFPvS3_ES3_mPKcPN6Genode11Cpu_sessionENS8_8Affinity8LocationE T _ZN4Libc14pthread_createEPP7pthreadRN6Genode6ThreadE T diff --git a/repos/libports/lib/symbols/mpfr b/repos/libports/lib/symbols/mpfr index 613e103d8..93d6e9f53 100644 --- a/repos/libports/lib/symbols/mpfr +++ b/repos/libports/lib/symbols/mpfr @@ -12,7 +12,7 @@ mpfr_add_ui T mpfr_add_z T mpfr_agm T mpfr_ai T -mpfr_allocate_func B 8 +mpfr_allocate_func B 88 mpfr_asin T mpfr_asinh T mpfr_asprintf T @@ -123,7 +123,7 @@ mpfr_fms T mpfr_fprint_binary T mpfr_frac T mpfr_free_cache T -mpfr_free_func B 8 +mpfr_free_func B 100 mpfr_free_str T mpfr_gamma T mpfr_gamma_one_and_two_third T @@ -337,7 +337,7 @@ mpfr_printf T mpfr_rand_raw T mpfr_rands B 32 mpfr_rands_initialized B 1 -mpfr_reallocate_func B 8 +mpfr_reallocate_func B 104 mpfr_rec_sqrt T mpfr_regular_p T mpfr_reldiff T diff --git a/repos/libports/lib/symbols/stdcxx b/repos/libports/lib/symbols/stdcxx index a38ec5fcd..a1feefad0 100644 --- a/repos/libports/lib/symbols/stdcxx +++ b/repos/libports/lib/symbols/stdcxx @@ -666,7 +666,9 @@ _ZNSt12__basic_fileIcE7seekoffExSt12_Ios_Seekdir T _ZNSt12__basic_fileIcE8xsputn_2EPKclS2_l T _ZNSt12__basic_fileIcE9showmanycEv T _ZNSt12__basic_fileIcEC1EPi T +_ZNSt12__basic_fileIcEC2EPi T _ZNSt12__basic_fileIcED1Ev T +_ZNSt12__basic_fileIcED2Ev T _ZNSt5ctypeIcE2idE B 8 _ZNSt7codecvtIcc11__mbstate_tE2idE B 8 _ZSt7getlineIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RNSt7__cxx1112basic_stringIS4_S5_T1_EES4_ T @@ -709,9 +711,34 @@ _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEixEm W _ZNKSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE3strEv W _ZNKSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEE3strEv W _ZNKSt7__cxx1119basic_ostringstreamIcSt11char_traitsIcESaIcEE3strEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEE10exceptionsEv W _ZNKSt9basic_iosIcSt11char_traitsIcEE3badEv W _ZNKSt9basic_iosIcSt11char_traitsIcEE3eofEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEE3tieEv W _ZNKSt9basic_iosIcSt11char_traitsIcEE4failEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEE4fillEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEE4goodEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEE5rdbufEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEE5widenEc W +_ZNKSt9basic_iosIcSt11char_traitsIcEE6narrowEcc W +_ZNKSt9basic_iosIcSt11char_traitsIcEE7rdstateEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEEcvPvEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEEcvbEv W +_ZNKSt9basic_iosIcSt11char_traitsIcEEntEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE10exceptionsEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE3badEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE3eofEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE3tieEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE4failEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE4fillEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE4goodEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE5rdbufEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEE5widenEc W +_ZNKSt9basic_iosIwSt11char_traitsIwEE6narrowEwc W +_ZNKSt9basic_iosIwSt11char_traitsIwEE7rdstateEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEEcvPvEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEEcvbEv W +_ZNKSt9basic_iosIwSt11char_traitsIwEEntEv W _ZNSaIcEC1ERKS_ W _ZNSaIcEC1Ev W _ZNSaIcEC2ERKS_ W @@ -726,9 +753,16 @@ _ZNSi10_M_extractIjEERSiRT_ W _ZNSi10_M_extractImEERSiRT_ W _ZNSi10_M_extractIyEERSiRT_ W _ZNSi3getERc W +_ZNSi3getEv W _ZNSi4peekEv W +_ZNSi4readEPcl W +_ZNSi5seekgElSt12_Ios_Seekdir W +_ZNSi5tellgEv W +_ZNSi6ignoreEl W _ZNSi7getlineEPcl W _ZNSi7putbackEc W +_ZNSiC1EPSt15basic_streambufIcSt11char_traitsIcEE W +_ZNSiC2EPSt15basic_streambufIcSt11char_traitsIcEE W _ZNSirsERd W _ZNSirsERf W _ZNSirsERi W @@ -765,6 +799,8 @@ _ZNSt13basic_filebufIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode W _ZNSt13basic_filebufIcSt11char_traitsIcEE5closeEv W _ZNSt13basic_filebufIcSt11char_traitsIcEEC1Ev W _ZNSt13basic_filebufIcSt11char_traitsIcEED1Ev W +_ZNSt13basic_fstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode W +_ZNSt13basic_fstreamIcSt11char_traitsIcEED1Ev W _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode W _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev W _ZNSt14basic_ofstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode W @@ -776,8 +812,15 @@ _ZNSt15basic_streambufIcSt11char_traitsIcEE5gbumpEi W _ZNSt15basic_streambufIcSt11char_traitsIcEE5imbueERKSt6locale W _ZNSt15basic_streambufIcSt11char_traitsIcEE5pbumpEi W _ZNSt15basic_streambufIcSt11char_traitsIcEE5uflowEv W +_ZNSt15basic_streambufIcSt11char_traitsIcEE6setbufEPcl W _ZNSt15basic_streambufIcSt11char_traitsIcEE6xsgetnEPcl W _ZNSt15basic_streambufIcSt11char_traitsIcEE6xsputnEPKcl W +_ZNSt15basic_streambufIcSt11char_traitsIcEE7seekoffElSt12_Ios_SeekdirSt13_Ios_Openmode W +_ZNSt15basic_streambufIcSt11char_traitsIcEE7seekposESt4fposI11__mbstate_tESt13_Ios_Openmode W +_ZNSt15basic_streambufIcSt11char_traitsIcEE8overflowEi W +_ZNSt15basic_streambufIcSt11char_traitsIcEE9pbackfailEi W +_ZNSt15basic_streambufIcSt11char_traitsIcEE9showmanycEv W +_ZNSt15basic_streambufIcSt11char_traitsIcEE9underflowEv W _ZNSt15basic_streambufIcSt11char_traitsIcEEC1Ev W _ZNSt15basic_streambufIcSt11char_traitsIcEEC2Ev W _ZNSt15basic_streambufIcSt11char_traitsIcEED0Ev W @@ -831,6 +874,7 @@ _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2EPKcRKS3_ W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2ERKS4_ W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC2EmcRKS3_ W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev W +_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED2Ev W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEaSEOS4_ W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEaSEPKc W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEaSERKS4_ W @@ -838,9 +882,19 @@ _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEixEm W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEpLEPKc W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEpLERKS4_ W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEpLEc W +_ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE6setbufEPcl W _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE7_M_syncEPcmm W +_ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE7seekoffElSt12_Ios_SeekdirSt13_Ios_Openmode W +_ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE7seekposESt4fposI11__mbstate_tESt13_Ios_Openmode W +_ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE8overflowEi W +_ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE9pbackfailEi W +_ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE9showmanycEv W +_ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEE9underflowEv W +_ZNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEC1ERKNS_12basic_stringIcS2_S3_EESt13_Ios_Openmode W _ZNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEC1ESt13_Ios_Openmode W +_ZNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEED0Ev W _ZNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEED1Ev W +_ZNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEED2Ev W _ZNSt7__cxx1119basic_istringstreamIcSt11char_traitsIcESaIcEEC1ERKNS_12basic_stringIcS2_S3_EESt13_Ios_Openmode W _ZNSt7__cxx1119basic_istringstreamIcSt11char_traitsIcESaIcEED1Ev W _ZNSt7__cxx1119basic_ostringstreamIcSt11char_traitsIcESaIcEEC1ESt13_Ios_Openmode W @@ -848,6 +902,7 @@ _ZNSt7__cxx1119basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev W _ZNSt9basic_iosIcSt11char_traitsIcEE4initEPSt15basic_streambufIcS1_E W _ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate W _ZNSt9basic_iosIcSt11char_traitsIcEE5imbueERKSt6locale W +_ZNSt9basic_iosIcSt11char_traitsIcEE5rdbufEPSt15basic_streambufIcS1_E W _ZNSt9basic_iosIcSt11char_traitsIcEEC1Ev W _ZNSt9basic_iosIcSt11char_traitsIcEEC2Ev W _ZNSt9basic_iosIcSt11char_traitsIcEED0Ev W @@ -861,5 +916,60 @@ _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c W _ZStlsIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_St13_Setprecision W _ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE W _ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_RS3_ W +_ZTINSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE W +_ZTISi W +_ZTISt12bad_weak_ptr W +_ZTISt14basic_ifstreamIcSt11char_traitsIcEE W +_ZTISt14basic_ofstreamIcSt11char_traitsIcEE W +_ZTTSt13basic_fstreamIcSt11char_traitsIcEE W +_ZTVSo W +_ZTVSt12bad_weak_ptr W +_ZTVSt13basic_fstreamIcSt11char_traitsIcEE W +_ZTv0_n24_NSdD0Ev W +_ZTv0_n24_NSdD1Ev W +_ZTv0_n24_NSiD0Ev W +_ZTv0_n24_NSiD1Ev W _ZTv0_n24_NSoD0Ev W _ZTv0_n24_NSoD1Ev W +_ZTv0_n24_NSt13basic_fstreamIcSt11char_traitsIcEED0Ev W +_ZTv0_n24_NSt13basic_fstreamIcSt11char_traitsIcEED1Ev W +_ZTv0_n24_NSt13basic_fstreamIwSt11char_traitsIwEED0Ev W +_ZTv0_n24_NSt13basic_fstreamIwSt11char_traitsIwEED1Ev W +_ZTv0_n24_NSt13basic_istreamIwSt11char_traitsIwEED0Ev W +_ZTv0_n24_NSt13basic_istreamIwSt11char_traitsIwEED1Ev W +_ZTv0_n24_NSt13basic_ostreamIwSt11char_traitsIwEED0Ev W +_ZTv0_n24_NSt13basic_ostreamIwSt11char_traitsIwEED1Ev W +_ZTv0_n24_NSt14basic_ifstreamIcSt11char_traitsIcEED0Ev W +_ZTv0_n24_NSt14basic_ifstreamIcSt11char_traitsIcEED1Ev W +_ZTv0_n24_NSt14basic_ifstreamIwSt11char_traitsIwEED0Ev W +_ZTv0_n24_NSt14basic_ifstreamIwSt11char_traitsIwEED1Ev W +_ZTv0_n24_NSt14basic_iostreamIwSt11char_traitsIwEED0Ev W +_ZTv0_n24_NSt14basic_iostreamIwSt11char_traitsIwEED1Ev W +_ZTv0_n24_NSt14basic_ofstreamIcSt11char_traitsIcEED0Ev W +_ZTv0_n24_NSt14basic_ofstreamIcSt11char_traitsIcEED1Ev W +_ZTv0_n24_NSt14basic_ofstreamIwSt11char_traitsIwEED0Ev W +_ZTv0_n24_NSt14basic_ofstreamIwSt11char_traitsIwEED1Ev W +_ZTv0_n24_NSt18basic_stringstreamIcSt11char_traitsIcESaIcEED0Ev W +_ZTv0_n24_NSt18basic_stringstreamIcSt11char_traitsIcESaIcEED1Ev W +_ZTv0_n24_NSt18basic_stringstreamIwSt11char_traitsIwESaIwEED0Ev W +_ZTv0_n24_NSt18basic_stringstreamIwSt11char_traitsIwESaIwEED1Ev W +_ZTv0_n24_NSt19basic_istringstreamIcSt11char_traitsIcESaIcEED0Ev W +_ZTv0_n24_NSt19basic_istringstreamIcSt11char_traitsIcESaIcEED1Ev W +_ZTv0_n24_NSt19basic_istringstreamIwSt11char_traitsIwESaIwEED0Ev W +_ZTv0_n24_NSt19basic_istringstreamIwSt11char_traitsIwESaIwEED1Ev W +_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED0Ev W +_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev W +_ZTv0_n24_NSt19basic_ostringstreamIwSt11char_traitsIwESaIwEED0Ev W +_ZTv0_n24_NSt19basic_ostringstreamIwSt11char_traitsIwESaIwEED1Ev W +_ZTv0_n24_NSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEED0Ev W +_ZTv0_n24_NSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEED1Ev W +_ZTv0_n24_NSt7__cxx1118basic_stringstreamIwSt11char_traitsIwESaIwEED0Ev W +_ZTv0_n24_NSt7__cxx1118basic_stringstreamIwSt11char_traitsIwESaIwEED1Ev W +_ZTv0_n24_NSt7__cxx1119basic_istringstreamIcSt11char_traitsIcESaIcEED0Ev W +_ZTv0_n24_NSt7__cxx1119basic_istringstreamIcSt11char_traitsIcESaIcEED1Ev W +_ZTv0_n24_NSt7__cxx1119basic_istringstreamIwSt11char_traitsIwESaIwEED0Ev W +_ZTv0_n24_NSt7__cxx1119basic_istringstreamIwSt11char_traitsIwESaIwEED1Ev W +_ZTv0_n24_NSt7__cxx1119basic_ostringstreamIcSt11char_traitsIcESaIcEED0Ev W +_ZTv0_n24_NSt7__cxx1119basic_ostringstreamIcSt11char_traitsIcESaIcEED1Ev W +_ZTv0_n24_NSt7__cxx1119basic_ostringstreamIwSt11char_traitsIwESaIwEED0Ev W +_ZTv0_n24_NSt7__cxx1119basic_ostringstreamIwSt11char_traitsIwESaIwEED1Ev W diff --git a/repos/libports/ports/gcov.hash b/repos/libports/ports/gcov.hash index d79377f72..8175b94c7 100644 --- a/repos/libports/ports/gcov.hash +++ b/repos/libports/ports/gcov.hash @@ -1 +1 @@ -67d83ba99db93c0e67eda26b33e167aecf48d60d +a6f8522b8cd63162a9aeef8b5509138c3724af6e diff --git a/repos/libports/ports/gcov.port b/repos/libports/ports/gcov.port index 37dc11cf0..975f83ed5 100644 --- a/repos/libports/ports/gcov.port +++ b/repos/libports/ports/gcov.port @@ -9,7 +9,7 @@ SIG(gcov) := ${URL(gcov)} KEY(gcov) := GNU URL(generated) := https://github.com/cproc/genode-generated.git -REV(generated) := 21d621a326ac3f074647c0555144d1638ee495a8 +REV(generated) := 745e78b2ea6abd4a9c601de2cc40702bcb6c636a DIR(generated) := include TAR_OPT(gcov) := gcc-$(VERSION)/gcc/color-macros.h \ diff --git a/repos/libports/ports/gmp.hash b/repos/libports/ports/gmp.hash index 3cac82d23..724b0e618 100644 --- a/repos/libports/ports/gmp.hash +++ b/repos/libports/ports/gmp.hash @@ -1 +1 @@ -95c8f71ec42c9c8afe05ecbe7425312555171a4f +855680cf4411a440d5353ea01c55ee6289c67b26 diff --git a/repos/libports/ports/gmp.port b/repos/libports/ports/gmp.port index d7f926404..8115d6c91 100644 --- a/repos/libports/ports/gmp.port +++ b/repos/libports/ports/gmp.port @@ -1,9 +1,9 @@ LICENSE := GPLv3 -VERSION := 4.3.2 +VERSION := 6.1.2 DOWNLOADS := gmp.archive URL(gmp) := https://ftp.gnu.org/gnu/gmp/gmp-$(VERSION).tar.bz2 -SHA(gmp) := 936162c0312886c21581002b79932829aa048cfaf9937c6265aeaa14f1cd1775 +SHA(gmp) := 5275bb04f4863a13516b2f39392ac5e272f5e1bb8057b18aec1c9b79d73d8fb2 SIG(gmp) := ${URL(gmp)}.sig KEY(gmp) := "73D46C3667461E4BD93972495D6D47DFDB899F46 343C2FF0FBEE5EC2EDBEF399F3599FF828C67298" DIR(gmp) := src/lib/gmp @@ -11,7 +11,8 @@ DIR(gmp) := src/lib/gmp DIRS := include DIR_CONTENT(include) := ${DIR(gmp)}/gmp-impl.h -DIRS += $(addprefix include/spec/, x86_32 x86_64 arm) +DIRS += $(addprefix include/spec/, x86_32 x86_64 arm arm_64) DIR_CONTENT(include/spec/x86_32) := ${DIR(gmp)}/mpn/x86/pentium/gmp-mparam.h DIR_CONTENT(include/spec/x86_64) := ${DIR(gmp)}/mpn/x86_64/gmp-mparam.h DIR_CONTENT(include/spec/arm) := ${DIR(gmp)}/mpn/arm/gmp-mparam.h +DIR_CONTENT(include/spec/arm_64) := ${DIR(gmp)}/mpn/arm64/gmp-mparam.h diff --git a/repos/libports/ports/mpc.hash b/repos/libports/ports/mpc.hash index 5ff71afc2..321b1af56 100644 --- a/repos/libports/ports/mpc.hash +++ b/repos/libports/ports/mpc.hash @@ -1 +1 @@ -ee372121d61623d9ecf268d819ee4ed1da514262 +989fb4180b392cebc00aa6e4899da70f2a71cb4d diff --git a/repos/libports/ports/mpc.port b/repos/libports/ports/mpc.port index 7b8d4cb86..138200539 100644 --- a/repos/libports/ports/mpc.port +++ b/repos/libports/ports/mpc.port @@ -1,9 +1,9 @@ LICENSE := LGPL -VERSION := 0.9 +VERSION := 1.1.0 DOWNLOADS := mpc.archive -URL(mpc) := http://www.multiprecision.org/downloads/mpc-$(VERSION).tar.gz -SHA(mpc) := fd3efe422f0d454592059e80f2c00d1a2e381bf2beda424c5094abd4deb049ac +URL(mpc) := https://ftp.gnu.org/gnu/mpc/mpc-$(VERSION).tar.gz +SHA(mpc) := 6985c538143c1208dcb1ac42cedad6ff52e267b47e5f970183a3e75125b43c2e SIG(mpc) := ${URL(mpc)}.asc KEY(mpc) := AD17A21EF8AED8F1CC02DBD9F7D5C9BF765C61E3 DIR(mpc) := src/lib/mpc diff --git a/repos/libports/ports/mpfr.hash b/repos/libports/ports/mpfr.hash index 312155650..43f62bd93 100644 --- a/repos/libports/ports/mpfr.hash +++ b/repos/libports/ports/mpfr.hash @@ -1 +1 @@ -9055b2ad7de47518b84a4e213c65d43d4ffd146b +9237712a91c7c913dff2578bbc906192c7f67ab7 diff --git a/repos/libports/ports/mpfr.port b/repos/libports/ports/mpfr.port index cd9ca8e46..43e14632a 100644 --- a/repos/libports/ports/mpfr.port +++ b/repos/libports/ports/mpfr.port @@ -1,20 +1,23 @@ LICENSE := GPLv3 -VERSION := 3.0.0 +VERSION := 4.0.2 DOWNLOADS := mpfr.archive -URL(mpfr) := https://gforge.inria.fr/frs/download.php/file/27104/mpfr-3.0.0.tar.xz -SHA(mpfr) := 22de51fee8ccfae75eaea85938acf8c9d8e9415269d9abb7ced52ebf0a29b5d8 +URL(mpfr) := https://gforge.inria.fr/frs/download.php/file/37888/mpfr-4.0.2.tar.xz +SHA(mpfr) := 1d3be708604eae0e42d578ba93b390c2a145f17743a744d8f3f8c2ad5855a38a SIG(mpfr) := ${URL(mpfr)}.asc KEY(mpfr) := GNU DIR(mpfr) := src/lib/mpfr TAR_OPT(mpfr) := --strip-components=1 -DIRS := include/mpfr -DIR_CONTENT(include/mpfr) := src/lib/mpfr/mpfr.h +DIRS := include/mpfr include/generic include/arm include/x86 +DIR_CONTENT(include/mpfr) := src/lib/mpfr/src/mpfr.h +DIR_CONTENT(include/generic) := src/lib/mpfr/src/generic/* +DIR_CONTENT(include/arm) := src/lib/mpfr/src/generic/* +DIR_CONTENT(include/x86) := src/lib/mpfr/src/generic/* default: include/mpfr/mparam.h include/mpfr/mparam.h: _dirs @$(MSG_INSTALL)$@ - @cp src/lib/mpfr/mparam_h.in $@ + @cp src/lib/mpfr/src/mparam_h.in $@ diff --git a/repos/libports/ports/qt5.hash b/repos/libports/ports/qt5.hash index 06ad13b3f..087d22586 100644 --- a/repos/libports/ports/qt5.hash +++ b/repos/libports/ports/qt5.hash @@ -1 +1 @@ -62f761cdc81e54230ffa34fbc2b8556c9b4ef70c +3d6643d8817e3817cf6c80d7a57de698f6eb36b7 diff --git a/repos/libports/ports/qt5.port b/repos/libports/ports/qt5.port index fb96fa7d2..02c9e5545 100644 --- a/repos/libports/ports/qt5.port +++ b/repos/libports/ports/qt5.port @@ -21,7 +21,7 @@ SHA(${QTSCRIPTCLASSIC}) := 6a4c4ada6f0064f6c5d7663602a37c99250ed6c7398b1775f95de DIR(${QTSCRIPTCLASSIC}) := src/lib/qt5/${QTSCRIPTCLASSIC} URL(symbols) := https://github.com/cproc/genode-symbols.git -REV(symbols) := 9d68f3847d7f1570258d46ec38191897eb7f4aea +REV(symbols) := 4bd6a7cf73b9e654f81fe82983f98ea6778ba53a DIR(symbols) := lib/symbols diff --git a/repos/libports/ports/solo5.hash b/repos/libports/ports/solo5.hash index 35076bb9c..d1a8dd00b 100644 --- a/repos/libports/ports/solo5.hash +++ b/repos/libports/ports/solo5.hash @@ -1 +1 @@ -9d1dcd38b2f71a7e8062ceb13072d17ec725a536 +55dd4fb026c0d4a7cc192c8228e4a6344f5781ef diff --git a/repos/libports/ports/solo5.port b/repos/libports/ports/solo5.port index efe35889b..f2320e787 100644 --- a/repos/libports/ports/solo5.port +++ b/repos/libports/ports/solo5.port @@ -2,10 +2,8 @@ LICENSE := ISC VERSION := HEAD DOWNLOADS := solo5.archive -OWNER := ehmry -REPO := solo5 REV := 7dca1a677f548ea0bc911a209f34ceb55d8f10fd -URL(solo5) := https://github.com/$(OWNER)/$(REPO)/archive/$(REV).tar.gz +URL(solo5) := https://genode.org/files/solo5-$(REV).tar.gz SHA(solo5) := 87a8e8e047bc6fffe0384f1cbb2bfde1e4c88c545287899be29444ec9a4d6b95 DIR(solo5) := src/lib/solo5 diff --git a/repos/libports/recipes/api/gmp/hash b/repos/libports/recipes/api/gmp/hash index 36ee94af4..991cbf21c 100644 --- a/repos/libports/recipes/api/gmp/hash +++ b/repos/libports/recipes/api/gmp/hash @@ -1 +1 @@ -2019-02-25 447aaf37329d949df990ec5db04132433549b85c +2019-11-18 a4b6b4d87db7c3ad88d4a3128d96c3a4960ae392 diff --git a/repos/libports/recipes/api/libc/content.mk b/repos/libports/recipes/api/libc/content.mk index e994ff1da..b44625092 100644 --- a/repos/libports/recipes/api/libc/content.mk +++ b/repos/libports/recipes/api/libc/content.mk @@ -16,7 +16,7 @@ include: cp -r $(PORT_DIR)/include/* $@/ cp -r $(REP_DIR)/include/libc $@/ cp -r $(REP_DIR)/include/libc-genode $@/ - cp $(REP_DIR)/src/lib/libc/task.h $@/libc/ + cp $(REP_DIR)/src/lib/libc/internal/legacy.h $@/libc/ content: LICENSE diff --git a/repos/libports/recipes/api/libc/hash b/repos/libports/recipes/api/libc/hash index 0237b275d..cfee10ab3 100644 --- a/repos/libports/recipes/api/libc/hash +++ b/repos/libports/recipes/api/libc/hash @@ -1 +1 @@ -2019-09-19 9e11cdeef4b22aecbc02d3d225b39c240719269f +2019-11-18 c6237a1fd5ebd2603d25594c1390517bb63d3e4a diff --git a/repos/libports/recipes/api/libgcov/hash b/repos/libports/recipes/api/libgcov/hash index 6dc4d6311..f62eb3263 100644 --- a/repos/libports/recipes/api/libgcov/hash +++ b/repos/libports/recipes/api/libgcov/hash @@ -1 +1 @@ -2019-05-26 79976b2bb4ba6e769fad10b27c764e64d72d3b29 +2019-11-18 e1cfb7da24a5c5da2f5412853c397caff0403480 diff --git a/repos/libports/recipes/api/lwip/hash b/repos/libports/recipes/api/lwip/hash index f0d9f952c..3c003b270 100644 --- a/repos/libports/recipes/api/lwip/hash +++ b/repos/libports/recipes/api/lwip/hash @@ -1 +1 @@ -2019-09-19 e7504ac6c00157ec41b42876c6e4ae559325e39f +2019-11-18 315174323746656b6068a0c341cd621b19010731 diff --git a/repos/libports/recipes/api/mpc/content.mk b/repos/libports/recipes/api/mpc/content.mk index a41d2637b..c47f96199 100644 --- a/repos/libports/recipes/api/mpc/content.mk +++ b/repos/libports/recipes/api/mpc/content.mk @@ -12,4 +12,4 @@ $(MIRROR_FROM_REP_DIR): $(mirror_from_rep_dir) LICENSE: - cp $(PORT_DIR)/src/lib/mpc/COPYING.LIB $@ + cp $(PORT_DIR)/src/lib/mpc/COPYING.LESSER $@ diff --git a/repos/libports/recipes/api/mpc/hash b/repos/libports/recipes/api/mpc/hash index 82cf16870..a1a5c5b85 100644 --- a/repos/libports/recipes/api/mpc/hash +++ b/repos/libports/recipes/api/mpc/hash @@ -1 +1 @@ -2019-02-25 95c7d1f055dff0cd24c4702b3f9ed3eb9223ac45 +2019-11-18 6d5ccaf2034efee38be828c7fcb235f33e8b076b diff --git a/repos/libports/recipes/api/mpfr/content.mk b/repos/libports/recipes/api/mpfr/content.mk index 7658e09c1..7bac2f240 100644 --- a/repos/libports/recipes/api/mpfr/content.mk +++ b/repos/libports/recipes/api/mpfr/content.mk @@ -5,6 +5,9 @@ PORT_DIR := $(call port_dir,$(REP_DIR)/ports/mpfr) include: mkdir $@ cp -r $(PORT_DIR)/include/mpfr/* $@/ + cp -r $(PORT_DIR)/include/generic $@/ + cp -r $(PORT_DIR)/include/arm $@/ + cp -r $(PORT_DIR)/include/x86 $@/ lib/symbols/mpfr: $(mirror_from_rep_dir) diff --git a/repos/libports/recipes/api/mpfr/hash b/repos/libports/recipes/api/mpfr/hash index d77ab4ad0..89a992126 100644 --- a/repos/libports/recipes/api/mpfr/hash +++ b/repos/libports/recipes/api/mpfr/hash @@ -1 +1 @@ -2019-02-25 90e29e655baeeab94f0130e7be7a908106889d4b +2019-11-18 1ce482941a0485948a9746fe806c77134624e68c diff --git a/repos/libports/recipes/api/qt5_gui/hash b/repos/libports/recipes/api/qt5_gui/hash index 481feff61..9d9f384b0 100644 --- a/repos/libports/recipes/api/qt5_gui/hash +++ b/repos/libports/recipes/api/qt5_gui/hash @@ -1 +1 @@ -2019-08-28 6ba9938918704e2053d8f9e227147ba042fc0b54 +2019-11-18 e36032edf2fa4646293574a1d587ac3057ffc98a diff --git a/repos/libports/recipes/api/qt5_qml/hash b/repos/libports/recipes/api/qt5_qml/hash index c4ceb7f4b..5941af09a 100644 --- a/repos/libports/recipes/api/qt5_qml/hash +++ b/repos/libports/recipes/api/qt5_qml/hash @@ -1 +1 @@ -2019-09-19 9b74b0fe550d469cb261b262c43d8a32603a2613 +2019-11-18 41d6a9c65f6deade44e7d98f0cb284cc0279f46e diff --git a/repos/libports/recipes/api/qt5_qpa_nitpicker/hash b/repos/libports/recipes/api/qt5_qpa_nitpicker/hash index 92d8a6edf..bb9ffb10a 100644 --- a/repos/libports/recipes/api/qt5_qpa_nitpicker/hash +++ b/repos/libports/recipes/api/qt5_qpa_nitpicker/hash @@ -1 +1 @@ -2019-08-27 1112af675c7aac57e4c83dbfd9ffc5c2f5fc91ce +2019-11-18 f9261a81128260beb9d7344f5898833cc61c6086 diff --git a/repos/libports/recipes/api/stdcxx/hash b/repos/libports/recipes/api/stdcxx/hash index 43821977c..63807ffa0 100644 --- a/repos/libports/recipes/api/stdcxx/hash +++ b/repos/libports/recipes/api/stdcxx/hash @@ -1 +1 @@ -2019-08-27 76508a505b02e9893bf4b87f41bf9c52b3eb9ea1 +2019-11-18 430e75f03ade0e2e51336c9cad52f936e0d46658 diff --git a/repos/libports/recipes/pkg/acpica/hash b/repos/libports/recipes/pkg/acpica/hash index 165485df8..8d6ed4797 100644 --- a/repos/libports/recipes/pkg/acpica/hash +++ b/repos/libports/recipes/pkg/acpica/hash @@ -1 +1 @@ -2019-09-19 721e2a66e14d85f502ccd14fa7d4035e138ee98d +2019-11-25 a0189944a40eeef6e42434010e80605832b586aa diff --git a/repos/libports/recipes/pkg/gcov/hash b/repos/libports/recipes/pkg/gcov/hash index cf8582cd5..fb2a36e4c 100644 --- a/repos/libports/recipes/pkg/gcov/hash +++ b/repos/libports/recipes/pkg/gcov/hash @@ -1 +1 @@ -2019-09-19 90a380d8c29df3e1a83321bc921a4aa9d8aef32f +2019-11-25 f6efa8be6a01ee8604ea15e697cbf26291975f31 diff --git a/repos/libports/recipes/pkg/pdf_view/hash b/repos/libports/recipes/pkg/pdf_view/hash index c556c14e7..73edfb2ce 100644 --- a/repos/libports/recipes/pkg/pdf_view/hash +++ b/repos/libports/recipes/pkg/pdf_view/hash @@ -1 +1 @@ -2019-09-19 83b866474104be43739958f2a34b60137ba553c9 +2019-11-25 3344914f71cfd25591187f8df643b304c0ec7e98 diff --git a/repos/libports/recipes/pkg/qt5_textedit/hash b/repos/libports/recipes/pkg/qt5_textedit/hash index f53156521..dca748f78 100644 --- a/repos/libports/recipes/pkg/qt5_textedit/hash +++ b/repos/libports/recipes/pkg/qt5_textedit/hash @@ -1 +1 @@ -2019-09-19 d6599f2d242cbc81ca78070a5ad5bc540f703bc1 +2019-11-25 32fd14a0d0cc2a9bcc990b011ccfa2543e45d831 diff --git a/repos/libports/recipes/pkg/test-expat/hash b/repos/libports/recipes/pkg/test-expat/hash index 85e7d10e2..291099df6 100644 --- a/repos/libports/recipes/pkg/test-expat/hash +++ b/repos/libports/recipes/pkg/test-expat/hash @@ -1 +1 @@ -2019-09-19 e1a5ca1b51e23456fe3a2afdcc1c36813efa4191 +2019-11-25 5bd82044a349a7b522426964e6e075102e3071b2 diff --git a/repos/libports/recipes/pkg/test-ldso/hash b/repos/libports/recipes/pkg/test-ldso/hash index cbfeff3ed..df61186aa 100644 --- a/repos/libports/recipes/pkg/test-ldso/hash +++ b/repos/libports/recipes/pkg/test-ldso/hash @@ -1 +1 @@ -2019-09-19 b5aaa272f13e279945d9aa01a57bc3895e14c398 +2019-11-25 bbc9f2386b3baf2ededd1f826b925a6dc3e40d2b diff --git a/repos/libports/recipes/pkg/test-libc/hash b/repos/libports/recipes/pkg/test-libc/hash index 433382604..a3d15b314 100644 --- a/repos/libports/recipes/pkg/test-libc/hash +++ b/repos/libports/recipes/pkg/test-libc/hash @@ -1 +1 @@ -2019-09-19 52c6ec9fb2c35194acabb0158de8c0d64863177c +2019-11-25 9c531a7d77d66cbbe1759fc0de64204e5f3038e9 diff --git a/repos/libports/recipes/pkg/test-libc_connect_lwip/hash b/repos/libports/recipes/pkg/test-libc_connect_lwip/hash index d28d34901..646fdbd61 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_lwip/hash +++ b/repos/libports/recipes/pkg/test-libc_connect_lwip/hash @@ -1 +1 @@ -2019-09-19 df6fbaaf890ed10b0f61b24b3c2882f54d3e9c88 +2019-11-25 709edd4d07382058af5b49770697a76042478876 diff --git a/repos/libports/recipes/pkg/test-libc_connect_lxip/hash b/repos/libports/recipes/pkg/test-libc_connect_lxip/hash index 5324db778..6d200a722 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_lxip/hash +++ b/repos/libports/recipes/pkg/test-libc_connect_lxip/hash @@ -1 +1 @@ -2019-09-19 1caa4ed57788d927cbb0685d96d7da3fe43438a0 +2019-11-25 ac53fa043edfb3d451221e335b738a9e5656e6f6 diff --git a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/hash b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/hash index ad9d16a34..a02fc519c 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/hash +++ b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/hash @@ -1 +1 @@ -2019-09-19 1c352d40d39c1c792ca76a3c1379bc349ecda93e +2019-11-25 bf4a0ecd6e66782cecb8257b783c0d8342bf85e0 diff --git a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/hash b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/hash index cbe9e265c..0e63be5d5 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/hash +++ b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/hash @@ -1 +1 @@ -2019-09-19 ca9b44302ae104d93cfdaf9adf5d53c871539e6b +2019-11-25 af08e2153d090d9cb94614f059834d3f735416f6 diff --git a/repos/libports/recipes/pkg/test-libc_counter/hash b/repos/libports/recipes/pkg/test-libc_counter/hash index 359dbc39a..e27f7114c 100644 --- a/repos/libports/recipes/pkg/test-libc_counter/hash +++ b/repos/libports/recipes/pkg/test-libc_counter/hash @@ -1 +1 @@ -2019-09-19 d68cd807564b4cb021f458b488cf5e30a8dd5b33 +2019-11-25 06989d3cba4e7f5221f905b699c74e9cf90c8601 diff --git a/repos/libports/recipes/pkg/test-libc_getenv/hash b/repos/libports/recipes/pkg/test-libc_getenv/hash index aea3bd4a9..b471fe698 100644 --- a/repos/libports/recipes/pkg/test-libc_getenv/hash +++ b/repos/libports/recipes/pkg/test-libc_getenv/hash @@ -1 +1 @@ -2019-09-19 e55f942ce3375f78554c37f43042180f8307306c +2019-11-25 99c35355b19043a2dc34790d47310d854a07f9e3 diff --git a/repos/libports/recipes/pkg/test-libc_pipe/archives b/repos/libports/recipes/pkg/test-libc_pipe/archives index b9781b6a5..2e4192267 100644 --- a/repos/libports/recipes/pkg/test-libc_pipe/archives +++ b/repos/libports/recipes/pkg/test-libc_pipe/archives @@ -2,4 +2,6 @@ _/src/init _/src/test-libc_pipe _/src/libc _/src/vfs +_/src/vfs_pipe _/src/posix +_/src/sequence diff --git a/repos/libports/recipes/pkg/test-libc_pipe/hash b/repos/libports/recipes/pkg/test-libc_pipe/hash index 64c9bf4bf..f5695fe76 100644 --- a/repos/libports/recipes/pkg/test-libc_pipe/hash +++ b/repos/libports/recipes/pkg/test-libc_pipe/hash @@ -1 +1 @@ -2019-09-19 19b449dfb8cb03e0a6c0942f1eef18444337271c +2019-11-25 2155823bb91940d4d95da83e58da9ff22b70365e diff --git a/repos/libports/recipes/pkg/test-libc_pipe/runtime b/repos/libports/recipes/pkg/test-libc_pipe/runtime index a23f40ffd..ed0eb8f17 100644 --- a/repos/libports/recipes/pkg/test-libc_pipe/runtime +++ b/repos/libports/recipes/pkg/test-libc_pipe/runtime @@ -2,40 +2,71 @@ <events> <timeout meaning="failed" sec="30" /> - <log meaning="succeeded">child "test-libc_pipe" exited with exit value 0</log> + <log meaning="succeeded">child "sequence" exited with exit value 0</log> <log meaning="failed">Error: </log> </events> <content> <rom label="ld.lib.so"/> <rom label="libc.lib.so"/> - <rom label="vfs.lib.so"/> <rom label="libm.lib.so"/> - <rom label="libc_pipe.lib.so"/> <rom label="posix.lib.so"/> + <rom label="sequence"/> <rom label="test-libc_pipe"/> + <rom label="vfs"/> + <rom label="vfs.lib.so"/> + <rom label="vfs_pipe.lib.so"/> </content> <config> <parent-provides> <service name="ROM"/> - <service name="IRQ"/> - <service name="IO_MEM"/> - <service name="IO_PORT"/> <service name="PD"/> <service name="RM"/> <service name="CPU"/> <service name="LOG"/> + <service name="Timer"/> </parent-provides> <default-route> <any-service> <parent/> <any-child/> </any-service> </default-route> - <default caps="100"/> - <start name="test-libc_pipe"> + <default caps="256"/> + <start name="pipes_fs"> + <binary name="vfs"/> + <provides> <service name="File_system"/> </provides> <resource name="RAM" quantum="4M"/> <config> - <vfs> <dir name="dev"> <log/> </dir> </vfs> - <libc stdout="/dev/log" stderr="/dev/log"/> + <vfs> <pipe/> </vfs> + <default-policy root="/" writeable="yes"/> + </config> + </start> + <start name="sequence"> + <resource name="RAM" quantum="4M"/> + <config> + <start name="libc_pipe_local"> + <binary name="test-libc_pipe"/> + <config> + <vfs> + <dir name="dev"> + <dir name="pipe"> <pipe/> </dir> + <log/> + </dir> + </vfs> + <libc stdout="/dev/log" stderr="/dev/log" pipe="/dev/pipe"/> + </config> + </start> + <start name="libc_pipe_remote"> + <binary name="test-libc_pipe"/> + <config> + <vfs> + <dir name="dev"> + <dir name="pipe"> <fs/> </dir> + <log/> + </dir> + </vfs> + <libc stdout="/dev/log" stderr="/dev/log" pipe="/dev/pipe"/> + </config> + </start> </config> </start> </config> diff --git a/repos/libports/recipes/pkg/test-libc_vfs/hash b/repos/libports/recipes/pkg/test-libc_vfs/hash index d57a95ee8..55ede560a 100644 --- a/repos/libports/recipes/pkg/test-libc_vfs/hash +++ b/repos/libports/recipes/pkg/test-libc_vfs/hash @@ -1 +1 @@ -2019-09-19 107ec065423c2fd51ee4bb3a69aaf6ccbf70f331 +2019-11-25 f10cf479e5e8bf8e23208a460d7c93846475f906 diff --git a/repos/libports/recipes/pkg/test-libc_vfs_block/hash b/repos/libports/recipes/pkg/test-libc_vfs_block/hash index 0f8db1811..2e21e6218 100644 --- a/repos/libports/recipes/pkg/test-libc_vfs_block/hash +++ b/repos/libports/recipes/pkg/test-libc_vfs_block/hash @@ -1 +1 @@ -2019-09-19 98c5a14d4895998c52a32384912face9d3930f6d +2019-11-25 54fe2eff8b28e56c2efba00920632781d29df20b diff --git a/repos/libports/recipes/pkg/test-libc_vfs_counter/hash b/repos/libports/recipes/pkg/test-libc_vfs_counter/hash index 1d5ce699d..27758a15f 100644 --- a/repos/libports/recipes/pkg/test-libc_vfs_counter/hash +++ b/repos/libports/recipes/pkg/test-libc_vfs_counter/hash @@ -1 +1 @@ -2019-09-19 4b352f060cc292a7e725026e2f3653d9f6de2901 +2019-11-25 4383da5659385b5c103818039c41f43755ac0430 diff --git a/repos/libports/recipes/pkg/test-libc_vfs_fs/hash b/repos/libports/recipes/pkg/test-libc_vfs_fs/hash index 9a8977f33..d03cf48ee 100644 --- a/repos/libports/recipes/pkg/test-libc_vfs_fs/hash +++ b/repos/libports/recipes/pkg/test-libc_vfs_fs/hash @@ -1 +1 @@ -2019-09-19 ea2f6e53c9dae8eec89da95da0200e03a533f7fc +2019-11-25 7c41140f4fa9ea8eaa4c71626fd9375e046e28ea diff --git a/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/hash b/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/hash index 666eac676..424c13b1f 100644 --- a/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/hash +++ b/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/hash @@ -1 +1 @@ -2019-09-19 e4afeff8f9df85914782627b5a2a7ad9115d29f6 +2019-11-25 29e34063a30c5acef5931c8646cc4107e61af293 diff --git a/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/runtime b/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/runtime index 0943e9e26..0167fd2bd 100644 --- a/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/runtime +++ b/repos/libports/recipes/pkg/test-libc_vfs_fs_chained/runtime @@ -51,7 +51,7 @@ <start name="test-libc_vfs"> <resource name="RAM" quantum="4M"/> <config> - <iterations value="1"/>} + <iterations value="1"/> <write-read size="1M" buffer_size="8K"/> <vfs> <dir name="tmp"> <fs/> </dir> diff --git a/repos/libports/recipes/pkg/test-libc_vfs_ram/hash b/repos/libports/recipes/pkg/test-libc_vfs_ram/hash index f62e846a8..d58ec646e 100644 --- a/repos/libports/recipes/pkg/test-libc_vfs_ram/hash +++ b/repos/libports/recipes/pkg/test-libc_vfs_ram/hash @@ -1 +1 @@ -2019-09-19 39beac9de110d677a7e3d79a0bfe5b217ef9dcba +2019-11-25 1b30046d18f23c3a5084d1e52225c5484b6fa1dd diff --git a/repos/libports/recipes/pkg/test-pthread/hash b/repos/libports/recipes/pkg/test-pthread/hash index 81c8ac7f5..b7640f878 100644 --- a/repos/libports/recipes/pkg/test-pthread/hash +++ b/repos/libports/recipes/pkg/test-pthread/hash @@ -1 +1 @@ -2019-09-19 7e56fd3b4bc95732a9397bd21285e575b6c93d4b +2019-11-25 5fe99902ee2cf178fc028b294e010c2b36032cf8 diff --git a/repos/libports/recipes/pkg/test-pthread/runtime b/repos/libports/recipes/pkg/test-pthread/runtime index a70f24e9e..0483db5e5 100644 --- a/repos/libports/recipes/pkg/test-pthread/runtime +++ b/repos/libports/recipes/pkg/test-pthread/runtime @@ -1,7 +1,9 @@ <runtime ram="72M" caps="1000" binary="init"> + <requires> <timer/> </requires> + <events> - <timeout meaning="failed" sec="30" /> + <timeout meaning="failed" sec="70" /> <log meaning="succeeded">--- returning from main ---</log> <log meaning="failed">Error: </log> <log meaning="failed">child "test-pthread" exited</log> @@ -19,13 +21,10 @@ <config> <parent-provides> <service name="ROM"/> - <service name="IRQ"/> - <service name="IO_MEM"/> - <service name="IO_PORT"/> <service name="PD"/> - <service name="RM"/> <service name="CPU"/> <service name="LOG"/> + <service name="Timer"/> </parent-provides> <default-route> <any-service> <parent/> <any-child/> </any-service> diff --git a/repos/libports/recipes/pkg/test-python/hash b/repos/libports/recipes/pkg/test-python/hash index e2a5243e4..3e408e11f 100644 --- a/repos/libports/recipes/pkg/test-python/hash +++ b/repos/libports/recipes/pkg/test-python/hash @@ -1 +1 @@ -2019-09-19 5a81888d573cd0201749c221f925237999a1d1c5 +2019-11-25 8d556c164901d6bb1d9d2072f1b92796d9855e72 diff --git a/repos/libports/recipes/pkg/test-rust/hash b/repos/libports/recipes/pkg/test-rust/hash index 2b217a518..9e86dbac1 100644 --- a/repos/libports/recipes/pkg/test-rust/hash +++ b/repos/libports/recipes/pkg/test-rust/hash @@ -1 +1 @@ -2019-09-19 8ea57dbd9d9bfea98e6bdcfd9703d3a608ea7846 +2019-11-25 5e143e5c9139a54350192d876c99fa42b5842b6d diff --git a/repos/libports/recipes/pkg/test-sequence/hash b/repos/libports/recipes/pkg/test-sequence/hash index e2eb3ffdb..ff8abfe7a 100644 --- a/repos/libports/recipes/pkg/test-sequence/hash +++ b/repos/libports/recipes/pkg/test-sequence/hash @@ -1 +1 @@ -2019-09-19 82b8a4d6e4cd9afab44b1bf5aeec9b1b8194a189 +2019-11-25 1c3d24e64bdf3854e17516abd3dbb3a1eb808422 diff --git a/repos/libports/recipes/pkg/test-solo5/hash b/repos/libports/recipes/pkg/test-solo5/hash index 1d5a5d7cb..a1c472e6b 100644 --- a/repos/libports/recipes/pkg/test-solo5/hash +++ b/repos/libports/recipes/pkg/test-solo5/hash @@ -1 +1 @@ -2019-09-19 6ae19562222c5ebf1054f6f5a742542d97832856 +2019-11-25 9260ccdceb5a4c28f81361ccd77aa1e288b51f88 diff --git a/repos/libports/recipes/pkg/test-spark/hash b/repos/libports/recipes/pkg/test-spark/hash index 3bf4316b8..2efe8a55e 100644 --- a/repos/libports/recipes/pkg/test-spark/hash +++ b/repos/libports/recipes/pkg/test-spark/hash @@ -1 +1 @@ -2019-09-19 f7f5c8ad4b52b7f016bf67fb66b35b4871530cfb +2019-11-25 73bebb34107cae8c2de2c649937a85d5d8a47d0f diff --git a/repos/libports/recipes/pkg/test-spark_exception/hash b/repos/libports/recipes/pkg/test-spark_exception/hash index 86bdcaff1..6ae427fa7 100644 --- a/repos/libports/recipes/pkg/test-spark_exception/hash +++ b/repos/libports/recipes/pkg/test-spark_exception/hash @@ -1 +1 @@ -2019-09-19 c62ee7a1f9bfdb42a1129da477ffd08ac06e1e2c +2019-11-25 5adbdb7319062de1869f424572d9dda4d88d6015 diff --git a/repos/libports/recipes/pkg/test-spark_secondary_stack/hash b/repos/libports/recipes/pkg/test-spark_secondary_stack/hash index f99638ae8..8ced9d89e 100644 --- a/repos/libports/recipes/pkg/test-spark_secondary_stack/hash +++ b/repos/libports/recipes/pkg/test-spark_secondary_stack/hash @@ -1 +1 @@ -2019-09-19 03183c66cd6b567c2bb213739f1f4f8b6d5494b1 +2019-11-25 93bffed59c0cb063d1b99bd3313ddbf90e9d5e7f diff --git a/repos/libports/recipes/pkg/test-stdcxx/hash b/repos/libports/recipes/pkg/test-stdcxx/hash index 19f5b220c..c6097616c 100644 --- a/repos/libports/recipes/pkg/test-stdcxx/hash +++ b/repos/libports/recipes/pkg/test-stdcxx/hash @@ -1 +1 @@ -2019-09-19 307a4474c0177f6704b6a031d34e963c84365bc4 +2019-11-25 584b92d4b3f284660a7aeb265283839bd30af345 diff --git a/repos/libports/recipes/pkg/test-tcp_bulk_lwip/hash b/repos/libports/recipes/pkg/test-tcp_bulk_lwip/hash index af90bee05..9c913bb4a 100644 --- a/repos/libports/recipes/pkg/test-tcp_bulk_lwip/hash +++ b/repos/libports/recipes/pkg/test-tcp_bulk_lwip/hash @@ -1 +1 @@ -2019-09-19 88f66ae4b2c35ad1b4fe3b1f9ec84c8386d39a36 +2019-11-25 d91e0c4cd9274474b3df890f2dd878990918410e diff --git a/repos/libports/recipes/pkg/test-tcp_bulk_lwip/runtime b/repos/libports/recipes/pkg/test-tcp_bulk_lwip/runtime index d5984c845..e9f0b4625 100644 --- a/repos/libports/recipes/pkg/test-tcp_bulk_lwip/runtime +++ b/repos/libports/recipes/pkg/test-tcp_bulk_lwip/runtime @@ -14,7 +14,6 @@ <rom label="posix.lib.so"/> <rom label="vfs.lib.so"/> <rom label="vfs_lwip.lib.so"/> - <rom label="lwip.lib.so"/> <rom label="nic_bridge"/> <rom label="nic_loopback"/> <rom label="test-tcp"/> diff --git a/repos/libports/recipes/pkg/test-tcp_bulk_lxip/hash b/repos/libports/recipes/pkg/test-tcp_bulk_lxip/hash index 00db30b1c..1c992c299 100644 --- a/repos/libports/recipes/pkg/test-tcp_bulk_lxip/hash +++ b/repos/libports/recipes/pkg/test-tcp_bulk_lxip/hash @@ -1 +1 @@ -2019-09-19 cc5950232366130e51b3bdb5f69110ea2687dfda +2019-11-25 171f16098422bf46bba1d8a403a88b8e843cdbe6 diff --git a/repos/libports/recipes/pkg/test-timed_semaphore/hash b/repos/libports/recipes/pkg/test-timed_semaphore/hash index d2904a1a2..2098102ee 100644 --- a/repos/libports/recipes/pkg/test-timed_semaphore/hash +++ b/repos/libports/recipes/pkg/test-timed_semaphore/hash @@ -1 +1 @@ -2019-09-19 aabcc58b94e2f77f18ec093e103e5f792faf12aa +2019-11-25 3d78c34d87de731070e05be37bd8b2dbefef43c8 diff --git a/repos/libports/recipes/src/acpica/hash b/repos/libports/recipes/src/acpica/hash index d8add78b3..7dd84df9d 100644 --- a/repos/libports/recipes/src/acpica/hash +++ b/repos/libports/recipes/src/acpica/hash @@ -1 +1 @@ -2019-09-19 fb06125a8b2c99f92e9c4302826754a853ee00d3 +2019-11-25 38ce9037e899e2c049d4d04063ab14edcc51c89e diff --git a/repos/libports/recipes/src/curl/hash b/repos/libports/recipes/src/curl/hash index 76b4f9af0..c4ff85870 100644 --- a/repos/libports/recipes/src/curl/hash +++ b/repos/libports/recipes/src/curl/hash @@ -1 +1 @@ -2019-09-19 0a814418eedf46008d308254a06b9c5f3fbca6c6 +2019-11-18 65254f2f57dfeb7f71f84c96cab9a95a56506aec diff --git a/repos/libports/recipes/src/drm/hash b/repos/libports/recipes/src/drm/hash index 9e25690a0..d932bfc03 100644 --- a/repos/libports/recipes/src/drm/hash +++ b/repos/libports/recipes/src/drm/hash @@ -1 +1 @@ -2019-09-19 ab9ef37ed3310665e171c3a773d65f15992e4411 +2019-11-25 fb7e907c00ec19b6392a86add52d7c1dfc9d9730 diff --git a/repos/libports/recipes/src/expat/hash b/repos/libports/recipes/src/expat/hash index 01428f463..0f7bbc478 100644 --- a/repos/libports/recipes/src/expat/hash +++ b/repos/libports/recipes/src/expat/hash @@ -1 +1 @@ -2019-09-19 646cba0654d64f949943f19cd17a0c8ab3fdfda5 +2019-11-25 c25330a93957d3e618d0beb9b72bd6a877b18f7d diff --git a/repos/libports/recipes/src/extract/hash b/repos/libports/recipes/src/extract/hash index 66f73a5f9..0e8a2a6a7 100644 --- a/repos/libports/recipes/src/extract/hash +++ b/repos/libports/recipes/src/extract/hash @@ -1 +1 @@ -2019-09-19 f0ec023b92e96da2228c5eba08f6ef832ad8287d +2019-11-25 a9c5b76e759225179681c4f3f7a145e18923eaa2 diff --git a/repos/libports/recipes/src/fetchurl/hash b/repos/libports/recipes/src/fetchurl/hash index 9c716e3e3..6ae146a4a 100644 --- a/repos/libports/recipes/src/fetchurl/hash +++ b/repos/libports/recipes/src/fetchurl/hash @@ -1 +1 @@ -2019-09-19 4dc548b54b8336c166a50fe26c36ef5d2616e893 +2019-11-25 6c7e0bd996f704855036a845f038e67a3e2b3713 diff --git a/repos/libports/recipes/src/freetype/hash b/repos/libports/recipes/src/freetype/hash index 75fadd19d..9536cccfe 100644 --- a/repos/libports/recipes/src/freetype/hash +++ b/repos/libports/recipes/src/freetype/hash @@ -1 +1 @@ -2019-09-19 7da58fec1545430f8e5c30254d542d982a1f564d +2019-11-18 b02cea603f9492c5b2daac2188d8852a101e32b6 diff --git a/repos/libports/recipes/src/gcov/hash b/repos/libports/recipes/src/gcov/hash index 8b6e14044..93b92184f 100644 --- a/repos/libports/recipes/src/gcov/hash +++ b/repos/libports/recipes/src/gcov/hash @@ -1 +1 @@ -2019-09-19 d94c288e94f59c21d99341e14e690ef6c2dcc02a +2019-11-25 9d905c6c05e0014f9206adcd38b90ec6c2902ef7 diff --git a/repos/libports/recipes/src/gmp/content.mk b/repos/libports/recipes/src/gmp/content.mk index 17c828f4c..0acdfbd25 100644 --- a/repos/libports/recipes/src/gmp/content.mk +++ b/repos/libports/recipes/src/gmp/content.mk @@ -6,6 +6,7 @@ MIRROR_FROM_REP_DIR = \ lib/mk/gmp-mpq.mk \ lib/mk/gmp-mpz.mk \ lib/mk/spec/arm/gmp-mpn.mk \ + lib/mk/spec/arm_64/gmp-mpn.mk \ lib/mk/spec/x86_32/gmp-mpn.mk \ lib/mk/spec/x86_64/gmp-mpn.mk \ diff --git a/repos/libports/recipes/src/gmp/hash b/repos/libports/recipes/src/gmp/hash index d68fa9de4..0071c476f 100644 --- a/repos/libports/recipes/src/gmp/hash +++ b/repos/libports/recipes/src/gmp/hash @@ -1 +1 @@ -2019-09-19 cb1467ee2c2ec083712157a95c479858d4ee2cdd +2019-11-18 c3f7e6db7448fb4026a46ea98b28430dd5b97bd8 diff --git a/repos/libports/recipes/src/icu/hash b/repos/libports/recipes/src/icu/hash index 4a2aa7667..287c9a34e 100644 --- a/repos/libports/recipes/src/icu/hash +++ b/repos/libports/recipes/src/icu/hash @@ -1 +1 @@ -2019-09-19 de6a02346c4fd98cb1a6eb7e27aa2110ff4d1688 +2019-11-25 71c5583f8a0051d8296f54fa96602fc365833a9f diff --git a/repos/libports/recipes/src/jbig2dec/hash b/repos/libports/recipes/src/jbig2dec/hash index 5f18041fc..ef2a689ba 100644 --- a/repos/libports/recipes/src/jbig2dec/hash +++ b/repos/libports/recipes/src/jbig2dec/hash @@ -1 +1 @@ -2019-09-19 a4eab631eeb04aa3db3b2ccc8e2fb9243a44085b +2019-11-18 0ea8afd55a1ee402e0ab3fa2b55274ecbe8b93b7 diff --git a/repos/libports/recipes/src/jpeg/hash b/repos/libports/recipes/src/jpeg/hash index 1b161f6c0..5fd7422be 100644 --- a/repos/libports/recipes/src/jpeg/hash +++ b/repos/libports/recipes/src/jpeg/hash @@ -1 +1 @@ -2019-09-19 c2a8be5edd1284451affd28bce32332156d8f80d +2019-11-18 9a96e7a691b79291962b5cf737460acad990fcde diff --git a/repos/libports/recipes/src/libarchive/hash b/repos/libports/recipes/src/libarchive/hash index c58c735b8..9c447da28 100644 --- a/repos/libports/recipes/src/libarchive/hash +++ b/repos/libports/recipes/src/libarchive/hash @@ -1 +1 @@ -2019-09-19 088c3e0a420b47993a651c3ee505ef40afdbd45c +2019-11-18 343c8405f519b88e5214ff776eff2213d1c7cdf6 diff --git a/repos/libports/recipes/src/libc/hash b/repos/libports/recipes/src/libc/hash index 5b575c245..c8fa33464 100644 --- a/repos/libports/recipes/src/libc/hash +++ b/repos/libports/recipes/src/libc/hash @@ -1 +1 @@ -2019-09-19 d343e2dd48ea5d0b370b4e30d7410b4355dc77b3 +2019-11-25 51393b0b10c4ce241a5d66a50dca1f30e365e92e diff --git a/repos/libports/recipes/src/libcrypto/hash b/repos/libports/recipes/src/libcrypto/hash index 7c6f28e7c..0706a13c8 100644 --- a/repos/libports/recipes/src/libcrypto/hash +++ b/repos/libports/recipes/src/libcrypto/hash @@ -1 +1 @@ -2019-09-19 92660c1da3b7b41d61cce91ced78af4b0e7d8c3a +2019-11-18 3a1309b72946daa899f923c5ec189859c7dba04f diff --git a/repos/libports/recipes/src/libiconv/hash b/repos/libports/recipes/src/libiconv/hash index b825b8a10..5cf74702c 100644 --- a/repos/libports/recipes/src/libiconv/hash +++ b/repos/libports/recipes/src/libiconv/hash @@ -1 +1 @@ -2019-09-19 5c2f9948f2fee2fe2380411971d2086dba114b9f +2019-11-18 291f8198e89c754cdab19e8757720d9378edb72b diff --git a/repos/libports/recipes/src/liblzma/hash b/repos/libports/recipes/src/liblzma/hash index b6029ad33..031f44edd 100644 --- a/repos/libports/recipes/src/liblzma/hash +++ b/repos/libports/recipes/src/liblzma/hash @@ -1 +1 @@ -2019-09-19 2b73ded06a101f32d8b0d2f9f7af4181c0664132 +2019-11-18 881a350b8caa44df5913681d430892ad4ca321bb diff --git a/repos/libports/recipes/src/libpng/hash b/repos/libports/recipes/src/libpng/hash index 6bf6845a3..7e3b5dfc3 100644 --- a/repos/libports/recipes/src/libpng/hash +++ b/repos/libports/recipes/src/libpng/hash @@ -1 +1 @@ -2019-09-19 6defdbe4bb78af0d9c11ba6fb755889e9f34355d +2019-11-18 b0115fc46bcae5cb730cd54d126fa24c778d32cb diff --git a/repos/libports/recipes/src/libssh/hash b/repos/libports/recipes/src/libssh/hash index 9232a8e19..f4fd7c746 100644 --- a/repos/libports/recipes/src/libssh/hash +++ b/repos/libports/recipes/src/libssh/hash @@ -1 +1 @@ -2019-09-19 0add1228007a623750bf51c0fea6eb1cc193fcbe +2019-11-18 1f779ea74362c9d4cbca950725bfa4dab9d096d2 diff --git a/repos/libports/recipes/src/libssl/hash b/repos/libports/recipes/src/libssl/hash index ccd88bc99..04d04da1d 100644 --- a/repos/libports/recipes/src/libssl/hash +++ b/repos/libports/recipes/src/libssl/hash @@ -1 +1 @@ -2019-09-19 34e961575b1ac97f15a02e104d6189a47b0cb630 +2019-11-18 e945cebfcf0d58b05c4de39a8d99e52eb713ab92 diff --git a/repos/libports/recipes/src/mesa/hash b/repos/libports/recipes/src/mesa/hash index a7e419a16..55ab5bff8 100644 --- a/repos/libports/recipes/src/mesa/hash +++ b/repos/libports/recipes/src/mesa/hash @@ -1 +1 @@ -2019-09-19 7fb8364a203cdf04dc5d98259c2dfaf44b16fb58 +2019-11-25 656699a82077c9c02352a458ce1212cd88477696 diff --git a/repos/libports/recipes/src/mpc/content.mk b/repos/libports/recipes/src/mpc/content.mk index 2e32839bf..5fe7a23ad 100644 --- a/repos/libports/recipes/src/mpc/content.mk +++ b/repos/libports/recipes/src/mpc/content.mk @@ -13,4 +13,4 @@ $(MIRROR_FROM_REP_DIR): $(mirror_from_rep_dir) LICENSE: - cp $(PORT_DIR)/src/lib/mpc/COPYING.LIB $@ + cp $(PORT_DIR)/src/lib/mpc/COPYING.LESSER $@ diff --git a/repos/libports/recipes/src/mpc/hash b/repos/libports/recipes/src/mpc/hash index 99586f902..c71e430f7 100644 --- a/repos/libports/recipes/src/mpc/hash +++ b/repos/libports/recipes/src/mpc/hash @@ -1 +1 @@ -2019-09-19 74a8f2d1a55c769747e9ba74f1799857479f001e +2019-11-18 55e45f31d4a3ef4330a62b71c7df2304e7a0d8eb diff --git a/repos/libports/recipes/src/mpfr/hash b/repos/libports/recipes/src/mpfr/hash index 42206eb71..ed4c0f53d 100644 --- a/repos/libports/recipes/src/mpfr/hash +++ b/repos/libports/recipes/src/mpfr/hash @@ -1 +1 @@ -2019-09-19 b73d2891db6aa5beca468a5afe848a37bf087684 +2019-11-18 9dcb9bafa0cc0b6b2b82e2c95a3171a598dddb2f diff --git a/repos/libports/recipes/src/mupdf/hash b/repos/libports/recipes/src/mupdf/hash index d592e49cc..63eb3437d 100644 --- a/repos/libports/recipes/src/mupdf/hash +++ b/repos/libports/recipes/src/mupdf/hash @@ -1 +1 @@ -2019-09-19 466d0b6d51bece1686c32afe0e07ec8322553b4e +2019-11-18 883c02773dd5621204896efda139c0a48e8fd8a8 diff --git a/repos/libports/recipes/src/ncurses/hash b/repos/libports/recipes/src/ncurses/hash index 617b1c96c..09a69b427 100644 --- a/repos/libports/recipes/src/ncurses/hash +++ b/repos/libports/recipes/src/ncurses/hash @@ -1 +1 @@ -2019-09-19 fbec592da97644ea9d5ee693a2a755e6d99c1842 +2019-11-18 96ccfbb6473f8e31456529f8e0d02bb67012c9f9 diff --git a/repos/libports/recipes/src/openjpeg/hash b/repos/libports/recipes/src/openjpeg/hash index f7d0b45af..9e1c80350 100644 --- a/repos/libports/recipes/src/openjpeg/hash +++ b/repos/libports/recipes/src/openjpeg/hash @@ -1 +1 @@ -2019-09-19 8123da4754e9fa9a7f39b545739eceeac0d3475a +2019-11-18 304a4f749830b6cd02e41df2b819ed915fa1e1ed diff --git a/repos/libports/recipes/src/pcre/hash b/repos/libports/recipes/src/pcre/hash index d3a62e875..4e36db932 100644 --- a/repos/libports/recipes/src/pcre/hash +++ b/repos/libports/recipes/src/pcre/hash @@ -1 +1 @@ -2019-09-19 98ce914b42d5c9b6e55f7b4a1a9011aa358f91fa +2019-11-18 bbdab2bc387b4aa69cb36bf8184645b8f88f68ab diff --git a/repos/libports/recipes/src/pcre16/hash b/repos/libports/recipes/src/pcre16/hash index 040fc31ba..3f4f6fd6d 100644 --- a/repos/libports/recipes/src/pcre16/hash +++ b/repos/libports/recipes/src/pcre16/hash @@ -1 +1 @@ -2019-09-19 0827548346cb6a1e4a6b0d7328df6d2b3826805a +2019-11-25 6310b7f68b3e170642e839d38a44eff234096752 diff --git a/repos/libports/recipes/src/pdf_view/hash b/repos/libports/recipes/src/pdf_view/hash index f05e76f0a..8a4af32ad 100644 --- a/repos/libports/recipes/src/pdf_view/hash +++ b/repos/libports/recipes/src/pdf_view/hash @@ -1 +1 @@ -2019-09-19 4fa3d793450b28a2e351095b723521db257c6727 +2019-11-25 4e0837812fb711c91676f5787b9ce8ace1be6b2d diff --git a/repos/libports/recipes/src/posix/hash b/repos/libports/recipes/src/posix/hash index a540172c0..b250ce1ed 100644 --- a/repos/libports/recipes/src/posix/hash +++ b/repos/libports/recipes/src/posix/hash @@ -1 +1 @@ -2019-09-19 d273c340b45a70a886ced847e41aa49df4c8f2f1 +2019-11-25 4a457213d8d0e75f48bbf8c3f322c84a2cc9f4bf diff --git a/repos/libports/recipes/src/python/hash b/repos/libports/recipes/src/python/hash index ed789edfa..e6119eb7f 100644 --- a/repos/libports/recipes/src/python/hash +++ b/repos/libports/recipes/src/python/hash @@ -1 +1 @@ -2019-09-19 0ca03e852c54378cc4826d556ab03aeb686597e1 +2019-11-25 1c717e31cd911099474b32d9923cd779501c41e5 diff --git a/repos/libports/recipes/src/qt5_calculatorform/hash b/repos/libports/recipes/src/qt5_calculatorform/hash index 61920d45a..f86dc3267 100644 --- a/repos/libports/recipes/src/qt5_calculatorform/hash +++ b/repos/libports/recipes/src/qt5_calculatorform/hash @@ -1 +1 @@ -2019-09-19 b61fb4c956d86ea1523fa7e60dda572b75e5fca9 +2019-11-25 52eaa074151a0f82f2f8bb84f56a57c7b4cdbf90 diff --git a/repos/libports/recipes/src/qt5_component/hash b/repos/libports/recipes/src/qt5_component/hash index f03d79e7a..73408d3f5 100644 --- a/repos/libports/recipes/src/qt5_component/hash +++ b/repos/libports/recipes/src/qt5_component/hash @@ -1 +1 @@ -2019-09-19 8c1877873af4d7a86c8dc025e0ee6d39861b0bb0 +2019-11-25 adb24d131f42dfa5dcee7b1f5f0f499ac401cb37 diff --git a/repos/libports/recipes/src/qt5_core/hash b/repos/libports/recipes/src/qt5_core/hash index 478601bfb..0c14feba5 100644 --- a/repos/libports/recipes/src/qt5_core/hash +++ b/repos/libports/recipes/src/qt5_core/hash @@ -1 +1 @@ -2019-09-19 fbb0690a855900236455fd3a935b70dab5279a0f +2019-11-25 403c62cfeb8122d02a787b5683888a3bf688b189 diff --git a/repos/libports/recipes/src/qt5_gui/hash b/repos/libports/recipes/src/qt5_gui/hash index aa61d1063..837a9d226 100644 --- a/repos/libports/recipes/src/qt5_gui/hash +++ b/repos/libports/recipes/src/qt5_gui/hash @@ -1 +1 @@ -2019-09-19 c6ee43770aedf91c43fde41f4a1cf42e2f111c34 +2019-11-25 057db5931008d6e788db32078c353d2f199ec55f diff --git a/repos/libports/recipes/src/qt5_launchpad/hash b/repos/libports/recipes/src/qt5_launchpad/hash index fba15b63d..091f6cbb3 100644 --- a/repos/libports/recipes/src/qt5_launchpad/hash +++ b/repos/libports/recipes/src/qt5_launchpad/hash @@ -1 +1 @@ -2019-09-19 34dad5e5870178816e6da43020d1a6555583aeb3 +2019-11-25 61879b40cbe7825209a104c6824dbf748f7cc844 diff --git a/repos/libports/recipes/src/qt5_network/hash b/repos/libports/recipes/src/qt5_network/hash index d58fe97ae..d8f1877b9 100644 --- a/repos/libports/recipes/src/qt5_network/hash +++ b/repos/libports/recipes/src/qt5_network/hash @@ -1 +1 @@ -2019-09-19 aea4e65d65bc9e255f9ad7b9692150ca974742c0 +2019-11-25 5956cf1ebeb77326f4520cf004302e92776942d8 diff --git a/repos/libports/recipes/src/qt5_opengl/hash b/repos/libports/recipes/src/qt5_opengl/hash index 38cc1e67c..b97ef6aa2 100644 --- a/repos/libports/recipes/src/qt5_opengl/hash +++ b/repos/libports/recipes/src/qt5_opengl/hash @@ -1 +1 @@ -2019-09-19 db8f256601071d221b236325fed0268b5b2a5897 +2019-11-25 dabe40a8130c3b40099c58405f864b9480c42659 diff --git a/repos/libports/recipes/src/qt5_openglwindow/hash b/repos/libports/recipes/src/qt5_openglwindow/hash index 9d6cb2416..c44458aa8 100644 --- a/repos/libports/recipes/src/qt5_openglwindow/hash +++ b/repos/libports/recipes/src/qt5_openglwindow/hash @@ -1 +1 @@ -2019-09-19 a46381a9454993a1a4b47b6cf19968c46fcf1218 +2019-11-25 2f91d8c281a0842e7b53db4919554e3131abb5ae diff --git a/repos/libports/recipes/src/qt5_printsupport/hash b/repos/libports/recipes/src/qt5_printsupport/hash index 4c5043c77..807367769 100644 --- a/repos/libports/recipes/src/qt5_printsupport/hash +++ b/repos/libports/recipes/src/qt5_printsupport/hash @@ -1 +1 @@ -2019-09-19 867abfbbadf8239a8b8ed0d2e201a2a1b8717712 +2019-11-25 635fccc854f0340295c664f0dda5cd2d77ebb4ae diff --git a/repos/libports/recipes/src/qt5_qjpeg/hash b/repos/libports/recipes/src/qt5_qjpeg/hash index 3d9d08778..71bbe8163 100644 --- a/repos/libports/recipes/src/qt5_qjpeg/hash +++ b/repos/libports/recipes/src/qt5_qjpeg/hash @@ -1 +1 @@ -2019-09-19 cef69f3bdea642379b2ffea763a249b3233ad0f3 +2019-11-25 91dc796c2117f02060e494b433a1eea71bab5e30 diff --git a/repos/libports/recipes/src/qt5_qml/hash b/repos/libports/recipes/src/qt5_qml/hash index dfd5716f3..ad257a1aa 100644 --- a/repos/libports/recipes/src/qt5_qml/hash +++ b/repos/libports/recipes/src/qt5_qml/hash @@ -1 +1 @@ -2019-09-19 176cdfc3d09cc8fde92e58f24f6c2c8c1eeea24e +2019-11-25 d68d35e40c0bdd48f90cb2f7f9d0cb1abd6bac84 diff --git a/repos/libports/recipes/src/qt5_qnitpickerviewwidget/hash b/repos/libports/recipes/src/qt5_qnitpickerviewwidget/hash index f011932e1..85f88525d 100644 --- a/repos/libports/recipes/src/qt5_qnitpickerviewwidget/hash +++ b/repos/libports/recipes/src/qt5_qnitpickerviewwidget/hash @@ -1 +1 @@ -2019-09-19 7b2db6d494d9f7f99f5b3a8473c98f929c97d00a +2019-11-25 89a692a7b31aec5b0f24c53e79e381a6058fab49 diff --git a/repos/libports/recipes/src/qt5_qpa_nitpicker/hash b/repos/libports/recipes/src/qt5_qpa_nitpicker/hash index de78b0e66..818cbcba9 100644 --- a/repos/libports/recipes/src/qt5_qpa_nitpicker/hash +++ b/repos/libports/recipes/src/qt5_qpa_nitpicker/hash @@ -1 +1 @@ -2019-09-19 4d9e559c8424ad1121bc36fed14a0142eaabbd63 +2019-11-25 29d9bb3bb9bead68258dc60e8114d148d3b86a99 diff --git a/repos/libports/recipes/src/qt5_qpluginwidget/hash b/repos/libports/recipes/src/qt5_qpluginwidget/hash index 043f33e76..2edd81ed1 100644 --- a/repos/libports/recipes/src/qt5_qpluginwidget/hash +++ b/repos/libports/recipes/src/qt5_qpluginwidget/hash @@ -1 +1 @@ -2019-09-19 7c309cf377b376a913c86d504ba6804cd5f16592 +2019-11-25 506674381d107239d3be01c9ad38488309cfc9f0 diff --git a/repos/libports/recipes/src/qt5_qt_labs_folderlistmodel/hash b/repos/libports/recipes/src/qt5_qt_labs_folderlistmodel/hash index acf453b6c..9cfb9d3c7 100644 --- a/repos/libports/recipes/src/qt5_qt_labs_folderlistmodel/hash +++ b/repos/libports/recipes/src/qt5_qt_labs_folderlistmodel/hash @@ -1 +1 @@ -2019-09-19 4334d7d0dfc66cb3af8ecb71a4de996887538446 +2019-11-25 b559a83fdebcfa1cf1623d44cdb37b2aca2866d1 diff --git a/repos/libports/recipes/src/qt5_qtquick2/hash b/repos/libports/recipes/src/qt5_qtquick2/hash index 16c58893e..90a6936ac 100644 --- a/repos/libports/recipes/src/qt5_qtquick2/hash +++ b/repos/libports/recipes/src/qt5_qtquick2/hash @@ -1 +1 @@ -2019-09-19 42458e552050b0a026bef6d38fabd2738665c8fb +2019-11-25 6a9c59224ef8b24c14a888912525e4eb5a4a5ff6 diff --git a/repos/libports/recipes/src/qt5_qtquick_controls2/hash b/repos/libports/recipes/src/qt5_qtquick_controls2/hash index 0029b1ff1..93e0b53e4 100644 --- a/repos/libports/recipes/src/qt5_qtquick_controls2/hash +++ b/repos/libports/recipes/src/qt5_qtquick_controls2/hash @@ -1 +1 @@ -2019-09-19 6da97ca6b0947025785d6b17fcd8c672dfcfb64b +2019-11-25 ace5ea9ed3c9e564801b76511b0036efe58741b6 diff --git a/repos/libports/recipes/src/qt5_qtquick_layouts/hash b/repos/libports/recipes/src/qt5_qtquick_layouts/hash index 8fd889f70..2f19eb625 100644 --- a/repos/libports/recipes/src/qt5_qtquick_layouts/hash +++ b/repos/libports/recipes/src/qt5_qtquick_layouts/hash @@ -1 +1 @@ -2019-09-19 90d51c8c43a168fde1b11c07535dae2b457bfb86 +2019-11-25 cdce5424800640d4032cf6ee0b495d7be94cf598 diff --git a/repos/libports/recipes/src/qt5_qtquick_templates2/hash b/repos/libports/recipes/src/qt5_qtquick_templates2/hash index af992a416..f36b818fb 100644 --- a/repos/libports/recipes/src/qt5_qtquick_templates2/hash +++ b/repos/libports/recipes/src/qt5_qtquick_templates2/hash @@ -1 +1 @@ -2019-09-19 c308c0dd23c7ce8af29beee8c582432d989014c2 +2019-11-25 c76de343582e453252bef384fd1645945de76d86 diff --git a/repos/libports/recipes/src/qt5_qtquick_virtualkeyboard/hash b/repos/libports/recipes/src/qt5_qtquick_virtualkeyboard/hash index 32106a957..d705c12ab 100644 --- a/repos/libports/recipes/src/qt5_qtquick_virtualkeyboard/hash +++ b/repos/libports/recipes/src/qt5_qtquick_virtualkeyboard/hash @@ -1 +1 @@ -2019-09-19 7ed49797020b72db2db1cf5da4aae905e4df0afe +2019-11-25 d644683a55bd5e8232b21eaf1723b0c2811bbf19 diff --git a/repos/libports/recipes/src/qt5_qtquick_window/hash b/repos/libports/recipes/src/qt5_qtquick_window/hash index 271e638a0..51d372a4e 100644 --- a/repos/libports/recipes/src/qt5_qtquick_window/hash +++ b/repos/libports/recipes/src/qt5_qtquick_window/hash @@ -1 +1 @@ -2019-09-19 a9ccdd9565d7c1055f44935fa83cbb4d50ce26eb +2019-11-25 aa5084559bd52f3392a8065268e1ba2d62868c44 diff --git a/repos/libports/recipes/src/qt5_quick/hash b/repos/libports/recipes/src/qt5_quick/hash index 2c49e366d..84f68ec8c 100644 --- a/repos/libports/recipes/src/qt5_quick/hash +++ b/repos/libports/recipes/src/qt5_quick/hash @@ -1 +1 @@ -2019-09-19 b08d85a4aa21f53e1936bf5a8e0131b95000a4ec +2019-11-25 656476b0f3302c59b073d7a0a9496a51fc2c7895 diff --git a/repos/libports/recipes/src/qt5_quickcontrols2/hash b/repos/libports/recipes/src/qt5_quickcontrols2/hash index b26ac8596..8d6018d2c 100644 --- a/repos/libports/recipes/src/qt5_quickcontrols2/hash +++ b/repos/libports/recipes/src/qt5_quickcontrols2/hash @@ -1 +1 @@ -2019-09-19 bf91d810871c5c5f28db6c9fdd25a63fe60ad061 +2019-11-25 91f61e0c2e24f179c9bb04215953de586508b52e diff --git a/repos/libports/recipes/src/qt5_quicktemplates2/hash b/repos/libports/recipes/src/qt5_quicktemplates2/hash index b6883f347..a3a78716f 100644 --- a/repos/libports/recipes/src/qt5_quicktemplates2/hash +++ b/repos/libports/recipes/src/qt5_quicktemplates2/hash @@ -1 +1 @@ -2019-09-19 7d2af69b6b22dc3fec9e2f06b7040cca22dccb9f +2019-11-25 1eff972cab620744492e3735d3ecbf888d989456 diff --git a/repos/libports/recipes/src/qt5_samegame/hash b/repos/libports/recipes/src/qt5_samegame/hash index 4bcd2a500..328262f60 100644 --- a/repos/libports/recipes/src/qt5_samegame/hash +++ b/repos/libports/recipes/src/qt5_samegame/hash @@ -1 +1 @@ -2019-09-19 a487d84262367351534b36421375c7b0e9e636d4 +2019-11-25 67c0a819db550ec257d3df27757a4d326477db6f diff --git a/repos/libports/recipes/src/qt5_scriptclassic/hash b/repos/libports/recipes/src/qt5_scriptclassic/hash index 8e5c2ffdc..bbb266470 100644 --- a/repos/libports/recipes/src/qt5_scriptclassic/hash +++ b/repos/libports/recipes/src/qt5_scriptclassic/hash @@ -1 +1 @@ -2019-09-19 0f15dc154df5602724321d599159331244329c79 +2019-11-25 b10e58b6bf2b36e85e1a07aadfbe86e58c7c712c diff --git a/repos/libports/recipes/src/qt5_sql/hash b/repos/libports/recipes/src/qt5_sql/hash index 63da2f58a..761b904d0 100644 --- a/repos/libports/recipes/src/qt5_sql/hash +++ b/repos/libports/recipes/src/qt5_sql/hash @@ -1 +1 @@ -2019-09-19 ed4df7609f602e2ee2211ef71456b905e2509f3e +2019-11-25 b9645d85e543870d7c46c7bd6de2702dd80a9398 diff --git a/repos/libports/recipes/src/qt5_svg/hash b/repos/libports/recipes/src/qt5_svg/hash index 1e241eea6..35474dcfa 100644 --- a/repos/libports/recipes/src/qt5_svg/hash +++ b/repos/libports/recipes/src/qt5_svg/hash @@ -1 +1 @@ -2019-09-19 7ea5f23e28d75bf5f99f2dbd42c7dd5d4c5185a8 +2019-11-25 c4a3729f0ad1607a8859bc357f214d2b10f4f845 diff --git a/repos/libports/recipes/src/qt5_test/hash b/repos/libports/recipes/src/qt5_test/hash index 261d0bb16..a8d3217a3 100644 --- a/repos/libports/recipes/src/qt5_test/hash +++ b/repos/libports/recipes/src/qt5_test/hash @@ -1 +1 @@ -2019-09-19 4b1cc8fb0d3857f2a5e879db809e4087bd2a18ae +2019-11-25 f089a6f82fdd0050d6c6bf52e86c83d078faa93d diff --git a/repos/libports/recipes/src/qt5_testqstring/hash b/repos/libports/recipes/src/qt5_testqstring/hash index 961ca02e5..42f520d47 100644 --- a/repos/libports/recipes/src/qt5_testqstring/hash +++ b/repos/libports/recipes/src/qt5_testqstring/hash @@ -1 +1 @@ -2019-09-19 265a82259de004fe123a4c30037e372ef2145fd2 +2019-11-25 3b200a87d5099cc6a18d05d07c05e8d1eede3ca7 diff --git a/repos/libports/recipes/src/qt5_tetrix/hash b/repos/libports/recipes/src/qt5_tetrix/hash index 50e680245..6ca8360e3 100644 --- a/repos/libports/recipes/src/qt5_tetrix/hash +++ b/repos/libports/recipes/src/qt5_tetrix/hash @@ -1 +1 @@ -2019-09-19 ec9f31b225cb869b3ff20050745699a21e37a454 +2019-11-25 1018365706b0c72035d897495a295d45c09cb5da diff --git a/repos/libports/recipes/src/qt5_textedit/hash b/repos/libports/recipes/src/qt5_textedit/hash index 7f3ea4917..41139b3f2 100644 --- a/repos/libports/recipes/src/qt5_textedit/hash +++ b/repos/libports/recipes/src/qt5_textedit/hash @@ -1 +1 @@ -2019-09-19 a5b3fbf88ca8fbb19aab4b2e852fb588ee72ad25 +2019-11-25 be9b22c144e59432e27c683e7c4947b490143e5b diff --git a/repos/libports/recipes/src/qt5_ui_tools/hash b/repos/libports/recipes/src/qt5_ui_tools/hash index c3010f8b2..def9c6e6e 100644 --- a/repos/libports/recipes/src/qt5_ui_tools/hash +++ b/repos/libports/recipes/src/qt5_ui_tools/hash @@ -1 +1 @@ -2019-09-19 77f4fe80c1a5645aa62d25ccf319f42ef8b7588e +2019-11-25 f3ef6380dde8ed42b8cc1cdc3fcf7ccad1500a60 diff --git a/repos/libports/recipes/src/qt5_virtualkeyboard/hash b/repos/libports/recipes/src/qt5_virtualkeyboard/hash index c558b9362..392842b2e 100644 --- a/repos/libports/recipes/src/qt5_virtualkeyboard/hash +++ b/repos/libports/recipes/src/qt5_virtualkeyboard/hash @@ -1 +1 @@ -2019-09-19 d1468ea44df513ed9aac1a25f7e9cfd99b9319b2 +2019-11-25 bd6e33fcf3c041891bb503c1a1c7706e487ab364 diff --git a/repos/libports/recipes/src/qt5_virtualkeyboard_example/hash b/repos/libports/recipes/src/qt5_virtualkeyboard_example/hash index 75548bf5f..ed9278767 100644 --- a/repos/libports/recipes/src/qt5_virtualkeyboard_example/hash +++ b/repos/libports/recipes/src/qt5_virtualkeyboard_example/hash @@ -1 +1 @@ -2019-09-19 a7ebdad6dd6f3189594bb401ddb8ad37e20e94be +2019-11-25 c6a5239984a2320405b6d4ffc4ecbd4f0e495d99 diff --git a/repos/libports/recipes/src/qt5_webkit/hash b/repos/libports/recipes/src/qt5_webkit/hash index 874831deb..3ad46cd4b 100644 --- a/repos/libports/recipes/src/qt5_webkit/hash +++ b/repos/libports/recipes/src/qt5_webkit/hash @@ -1 +1 @@ -2019-09-19 c65aef2264260ee90aaf2fd44f2c24d5bfc2e7ff +2019-11-25 ddcfee7b15b693144dbbe146a77d04d018a7cd10 diff --git a/repos/libports/recipes/src/qt5_widgets/hash b/repos/libports/recipes/src/qt5_widgets/hash index c363c9e3a..c92b03ced 100644 --- a/repos/libports/recipes/src/qt5_widgets/hash +++ b/repos/libports/recipes/src/qt5_widgets/hash @@ -1 +1 @@ -2019-09-19 14628c30cb6d93aab6d0ee48faa2607a43673269 +2019-11-25 0a10c84a5f534415d256d254a80124e472979866 diff --git a/repos/libports/recipes/src/qt5_xml/hash b/repos/libports/recipes/src/qt5_xml/hash index 8ff3a8292..c0a1b2fd5 100644 --- a/repos/libports/recipes/src/qt5_xml/hash +++ b/repos/libports/recipes/src/qt5_xml/hash @@ -1 +1 @@ -2019-09-19 66ee90281c0a2dd0d6c5209baea2c6db422ad7e1 +2019-11-25 0c1962810d5305227c1202bbafce8759474bd73a diff --git a/repos/libports/recipes/src/sanitizer/hash b/repos/libports/recipes/src/sanitizer/hash index be45c3da1..f74a0709d 100644 --- a/repos/libports/recipes/src/sanitizer/hash +++ b/repos/libports/recipes/src/sanitizer/hash @@ -1 +1 @@ -2019-09-19 8710ee4100d60ed6c9db4b45e95a125b44dd93d9 +2019-11-25 ed0bbc152fbbabed8857df0658e4d6c32e8c0d9a diff --git a/repos/libports/recipes/src/solo5/hash b/repos/libports/recipes/src/solo5/hash index 4bcbcaa6d..d317ff7fb 100644 --- a/repos/libports/recipes/src/solo5/hash +++ b/repos/libports/recipes/src/solo5/hash @@ -1 +1 @@ -2019-09-19 2c1f9898de2d76bd8dee27521b154fd06cceb590 +2019-11-25 8d4865b3f54a796df29dd2f40d5f4826a1a4e45a diff --git a/repos/libports/recipes/src/spark/hash b/repos/libports/recipes/src/spark/hash index cefc8e37c..dce113fb0 100644 --- a/repos/libports/recipes/src/spark/hash +++ b/repos/libports/recipes/src/spark/hash @@ -1 +1 @@ -2019-09-19 26a674e40f5b682f20d581f89316385a26e7ba31 +2019-11-25 a368cafcc12146c917db341d57f840947b79cc07 diff --git a/repos/libports/recipes/src/stdcxx/hash b/repos/libports/recipes/src/stdcxx/hash index 72d2df4fd..221564dc9 100644 --- a/repos/libports/recipes/src/stdcxx/hash +++ b/repos/libports/recipes/src/stdcxx/hash @@ -1 +1 @@ -2019-09-19 b1de94e516c36e3eb358e7c965aa42e39903d34c +2019-11-18 4dd3b36c9ca98cb993e4f6bc55397db8caefd6c0 diff --git a/repos/libports/recipes/src/system_rtc/hash b/repos/libports/recipes/src/system_rtc/hash index 9e1124249..0feca92aa 100644 --- a/repos/libports/recipes/src/system_rtc/hash +++ b/repos/libports/recipes/src/system_rtc/hash @@ -1 +1 @@ -2019-09-19 fc6ba094f28d81ec65ad0929f17f8feed3e53a3b +2019-11-25 a7ea7e962f586b109b0cd034a4f2a0b984f3dc11 diff --git a/repos/libports/recipes/src/test-expat/hash b/repos/libports/recipes/src/test-expat/hash index 5bfd49e22..dab7f9f27 100644 --- a/repos/libports/recipes/src/test-expat/hash +++ b/repos/libports/recipes/src/test-expat/hash @@ -1 +1 @@ -2019-09-19 8fcd9c0a61e40a9acc42f243f29cf0452e8387b3 +2019-11-25 1f8f00550d7df1f6df7a903e0827ec9e05f5dca3 diff --git a/repos/libports/recipes/src/test-ldso/hash b/repos/libports/recipes/src/test-ldso/hash index a596dac42..66032fa6e 100644 --- a/repos/libports/recipes/src/test-ldso/hash +++ b/repos/libports/recipes/src/test-ldso/hash @@ -1 +1 @@ -2019-09-19 81032741e49fb42915687bdcef265132cbc5ea6a +2019-11-25 7df56f5c1d498be50610f96ff455d2adfc27dd99 diff --git a/repos/libports/recipes/src/test-libc/hash b/repos/libports/recipes/src/test-libc/hash index 1233c58e1..7a5e126dd 100644 --- a/repos/libports/recipes/src/test-libc/hash +++ b/repos/libports/recipes/src/test-libc/hash @@ -1 +1 @@ -2019-09-19 90ca4e96297415fd58c878ea10c0256b2a5b949a +2019-11-25 c15862f3dfffe48d2ccb5721f10d76b332d42e12 diff --git a/repos/libports/recipes/src/test-libc_connect/hash b/repos/libports/recipes/src/test-libc_connect/hash index 52c0cb98d..821f56c73 100644 --- a/repos/libports/recipes/src/test-libc_connect/hash +++ b/repos/libports/recipes/src/test-libc_connect/hash @@ -1 +1 @@ -2019-09-19 ff0f1a0dd8e97f18af756823030c25dd03096c23 +2019-11-25 0ad2af022a5d13d59f30e29c364c6cebc1d1536f diff --git a/repos/libports/recipes/src/test-libc_counter/hash b/repos/libports/recipes/src/test-libc_counter/hash index d7d3d294f..27e25ef22 100644 --- a/repos/libports/recipes/src/test-libc_counter/hash +++ b/repos/libports/recipes/src/test-libc_counter/hash @@ -1 +1 @@ -2019-09-19 13bcdef25121185ee692c79f243e9c2eb2dedcf9 +2019-11-25 96338716f41b952ba164ab3fbfdd33f0c8096b32 diff --git a/repos/libports/recipes/src/test-libc_getenv/hash b/repos/libports/recipes/src/test-libc_getenv/hash index c9e21a71e..d952b09e9 100644 --- a/repos/libports/recipes/src/test-libc_getenv/hash +++ b/repos/libports/recipes/src/test-libc_getenv/hash @@ -1 +1 @@ -2019-09-19 6c0525149a272b45538e070d921432d69b3e16f0 +2019-11-25 281b72caebbba3631c4336dd39c5e1d562f2827c diff --git a/repos/libports/recipes/src/test-libc_pipe/content.mk b/repos/libports/recipes/src/test-libc_pipe/content.mk index 7af7881c3..85d6481dc 100644 --- a/repos/libports/recipes/src/test-libc_pipe/content.mk +++ b/repos/libports/recipes/src/test-libc_pipe/content.mk @@ -1,11 +1,2 @@ SRC_DIR = src/test/libc_pipe include $(GENODE_DIR)/repos/base/recipes/src/content.inc - -MIRROR_FROM_REP_DIR := include/libc-plugin \ - lib/mk/libc_pipe.mk \ - src/lib/libc_pipe - -content: $(MIRROR_FROM_REP_DIR) - -$(MIRROR_FROM_REP_DIR): - $(mirror_from_rep_dir) diff --git a/repos/libports/recipes/src/test-libc_pipe/hash b/repos/libports/recipes/src/test-libc_pipe/hash index 0d4d6a33f..64abcaf5a 100644 --- a/repos/libports/recipes/src/test-libc_pipe/hash +++ b/repos/libports/recipes/src/test-libc_pipe/hash @@ -1 +1 @@ -2019-09-19 d31bdb4db06416146bcceae96f27376ff82e9805 +2019-11-25 076a95cc30fa62d88a88e67575982e5fcd23461c diff --git a/repos/libports/recipes/src/test-libc_vfs/hash b/repos/libports/recipes/src/test-libc_vfs/hash index 9e241670a..478812ba5 100644 --- a/repos/libports/recipes/src/test-libc_vfs/hash +++ b/repos/libports/recipes/src/test-libc_vfs/hash @@ -1 +1 @@ -2019-09-19 fc448a7e4ab0480bb7d0df21c1d6c355e8e2f33e +2019-11-25 e97bbcd904161e3e50d8bf0ac7da0b8c1cc0c239 diff --git a/repos/libports/recipes/src/test-libc_vfs_block/hash b/repos/libports/recipes/src/test-libc_vfs_block/hash index 9fd83ba31..8dd79e025 100644 --- a/repos/libports/recipes/src/test-libc_vfs_block/hash +++ b/repos/libports/recipes/src/test-libc_vfs_block/hash @@ -1 +1 @@ -2019-09-19 cb022108de68e2277166e142561f5f81c1f100c2 +2019-11-25 db25a0489ac9a5e503cf1c6b7da4cb2636007299 diff --git a/repos/libports/recipes/src/test-netty/hash b/repos/libports/recipes/src/test-netty/hash index c546918cf..af54232a1 100644 --- a/repos/libports/recipes/src/test-netty/hash +++ b/repos/libports/recipes/src/test-netty/hash @@ -1 +1 @@ -2019-09-19 30c5b93c6d88e2877b8a6962916039c12edac2c6 +2019-11-25 be160bfe9175f6d899297b451328c952824779b0 diff --git a/repos/libports/recipes/src/test-pthread/hash b/repos/libports/recipes/src/test-pthread/hash index bd4247d32..a0a7c863a 100644 --- a/repos/libports/recipes/src/test-pthread/hash +++ b/repos/libports/recipes/src/test-pthread/hash @@ -1 +1 @@ -2019-09-19 922c21e5032f9bb8cec6d3e8112ed9eaaca1048b +2019-11-25 1959c97bf59ff2d4a99b27a6f3ad421ca5e397fb diff --git a/repos/libports/recipes/src/test-python/hash b/repos/libports/recipes/src/test-python/hash index 617acf9c6..3a29e41f6 100644 --- a/repos/libports/recipes/src/test-python/hash +++ b/repos/libports/recipes/src/test-python/hash @@ -1 +1 @@ -2019-09-19 05a2aeef34f68e4348f85438e7e4c30f452e7264 +2019-11-25 6bc8d477c33e46fadd3c93cfe4c86e90e2eb0f16 diff --git a/repos/libports/recipes/src/test-qpluginwidget/hash b/repos/libports/recipes/src/test-qpluginwidget/hash index 3e71f0fec..b270fd0ca 100644 --- a/repos/libports/recipes/src/test-qpluginwidget/hash +++ b/repos/libports/recipes/src/test-qpluginwidget/hash @@ -1 +1 @@ -2019-09-19 e278ad295e5a18c71b4c6b65c5d3c4fcdf1cee58 +2019-11-25 a58c770ddfee4d5f741f86fd42236aa0cd6aa711 diff --git a/repos/libports/recipes/src/test-qt_core/hash b/repos/libports/recipes/src/test-qt_core/hash index 49bab3a8a..e5861bdf2 100644 --- a/repos/libports/recipes/src/test-qt_core/hash +++ b/repos/libports/recipes/src/test-qt_core/hash @@ -1 +1 @@ -2019-09-19 32f6813a9ecf4079d6ce8698ac6f4c30e3e6ab31 +2019-11-25 9346136b371e84247e081e2cbfc4448bfce4df16 diff --git a/repos/libports/recipes/src/test-qt_quick/hash b/repos/libports/recipes/src/test-qt_quick/hash index f47e25e8f..8d9ff1b22 100644 --- a/repos/libports/recipes/src/test-qt_quick/hash +++ b/repos/libports/recipes/src/test-qt_quick/hash @@ -1 +1 @@ -2019-09-19 8e144870a46d3ded412a0df454b2c7abb9016e2d +2019-11-25 08a486e4d932264a5a00d5300994aaecd12a2089 diff --git a/repos/libports/recipes/src/test-rust/hash b/repos/libports/recipes/src/test-rust/hash index eb9756a0b..665231661 100644 --- a/repos/libports/recipes/src/test-rust/hash +++ b/repos/libports/recipes/src/test-rust/hash @@ -1 +1 @@ -2019-09-19 c8644e18f2ed7c313b4bd490f5d56b429ed09434 +2019-11-25 36b6406fa644061d05a9738079dd5ae0cc3130f6 diff --git a/repos/libports/recipes/src/test-solo5/hash b/repos/libports/recipes/src/test-solo5/hash index 391097e0f..15ef42563 100644 --- a/repos/libports/recipes/src/test-solo5/hash +++ b/repos/libports/recipes/src/test-solo5/hash @@ -1 +1 @@ -2019-09-19 bf685c58e68f9de64f84fad3464129a4ee082902 +2019-11-25 e2913909aa11d2b6ce2510562128c2a040d60cb6 diff --git a/repos/libports/recipes/src/test-spark/hash b/repos/libports/recipes/src/test-spark/hash index 22486465c..cc9abef44 100644 --- a/repos/libports/recipes/src/test-spark/hash +++ b/repos/libports/recipes/src/test-spark/hash @@ -1 +1 @@ -2019-09-19 25c09d6171e776af91aa4424746ad0ae46da68ff +2019-11-25 7451505325ebb9effe20de4d9667ba7ca34eff91 diff --git a/repos/libports/recipes/src/test-spark_exception/hash b/repos/libports/recipes/src/test-spark_exception/hash index b405a8747..4be3ab74f 100644 --- a/repos/libports/recipes/src/test-spark_exception/hash +++ b/repos/libports/recipes/src/test-spark_exception/hash @@ -1 +1 @@ -2019-09-19 7c39ed3c3b1e0cdfe9bb9720575e78131abbe7e1 +2019-11-25 7c4392cbcbb8ecceb62d490776653abb5d061dfe diff --git a/repos/libports/recipes/src/test-spark_secondary_stack/hash b/repos/libports/recipes/src/test-spark_secondary_stack/hash index be06dc246..7d7ff963c 100644 --- a/repos/libports/recipes/src/test-spark_secondary_stack/hash +++ b/repos/libports/recipes/src/test-spark_secondary_stack/hash @@ -1 +1 @@ -2019-09-19 df57a1798fe92b1ddddb7ebc061bb936fa53ad0a +2019-11-25 8b0367486841516370927225cea479b2d48b656b diff --git a/repos/libports/recipes/src/test-stdcxx/hash b/repos/libports/recipes/src/test-stdcxx/hash index 1e0ce0c4f..3de3b1c51 100644 --- a/repos/libports/recipes/src/test-stdcxx/hash +++ b/repos/libports/recipes/src/test-stdcxx/hash @@ -1 +1 @@ -2019-09-19 ca3ac1f26c27b0f2af92c98d5a77756354634fb2 +2019-11-25 303c52b0817f30acb3c8aee2261a23bace6d591b diff --git a/repos/libports/recipes/src/test-tcp/hash b/repos/libports/recipes/src/test-tcp/hash index b00c3842e..fc4858067 100644 --- a/repos/libports/recipes/src/test-tcp/hash +++ b/repos/libports/recipes/src/test-tcp/hash @@ -1 +1 @@ -2019-09-19 edeefa2f120f908e9eeb7bbde62f432b146fcc63 +2019-11-25 42610eb89a01fb72d4d2a4c04c0a8fc7c9e83738 diff --git a/repos/libports/recipes/src/test-timed_semaphore/content.mk b/repos/libports/recipes/src/test-timed_semaphore/content.mk index 5066c0a00..c0c092f2c 100644 --- a/repos/libports/recipes/src/test-timed_semaphore/content.mk +++ b/repos/libports/recipes/src/test-timed_semaphore/content.mk @@ -1,7 +1,7 @@ SRC_DIR = src/test/timed_semaphore include $(GENODE_DIR)/repos/base/recipes/src/content.inc -MIRROR_FROM_REP_DIR := src/lib/libc/timed_semaphore.h +MIRROR_FROM_REP_DIR := src/lib/libc/internal/timed_semaphore.h content: $(MIRROR_FROM_REP_DIR) diff --git a/repos/libports/recipes/src/test-timed_semaphore/hash b/repos/libports/recipes/src/test-timed_semaphore/hash index de17977d7..ce4f5ec29 100644 --- a/repos/libports/recipes/src/test-timed_semaphore/hash +++ b/repos/libports/recipes/src/test-timed_semaphore/hash @@ -1 +1 @@ -2019-09-19 276292354c9a9612684e5bcfe2b4831bac889b01 +2019-11-25 86535919ce016903c8f76d5af3fc9e1fbed0ce44 diff --git a/repos/libports/recipes/src/vesa_drv/hash b/repos/libports/recipes/src/vesa_drv/hash index 3cd0dc737..bc8511e6e 100644 --- a/repos/libports/recipes/src/vesa_drv/hash +++ b/repos/libports/recipes/src/vesa_drv/hash @@ -1 +1 @@ -2019-09-19 7889b7a156eda32a372f180a33ed6f5b03b38edc +2019-11-25 f3b417d4df8704dd8a4fd3e6dfcbdcc870f694db diff --git a/repos/libports/recipes/src/vfs_fatfs/hash b/repos/libports/recipes/src/vfs_fatfs/hash index f5889e7f2..5f3eb170c 100644 --- a/repos/libports/recipes/src/vfs_fatfs/hash +++ b/repos/libports/recipes/src/vfs_fatfs/hash @@ -1 +1 @@ -2019-09-19 77523c8dcd78d56da6b96454c96655e7525c1423 +2019-11-25 53f2b11d11716f5912f6ff6e37431bae7c12768b diff --git a/repos/libports/recipes/src/vfs_jitterentropy/hash b/repos/libports/recipes/src/vfs_jitterentropy/hash index c71bb30e7..ff06f4fd9 100644 --- a/repos/libports/recipes/src/vfs_jitterentropy/hash +++ b/repos/libports/recipes/src/vfs_jitterentropy/hash @@ -1 +1 @@ -2019-09-19 7c1d824e12bc24d0dc247ca52ccfe2b0581a64fa +2019-11-25 5cae006c8704cee446d427080c21e77fed993bb8 diff --git a/repos/libports/recipes/src/vfs_lwip/hash b/repos/libports/recipes/src/vfs_lwip/hash index 1aa0f8a3e..8fedb4e4c 100644 --- a/repos/libports/recipes/src/vfs_lwip/hash +++ b/repos/libports/recipes/src/vfs_lwip/hash @@ -1 +1 @@ -2019-09-19 209cc35a05364bc8580cc26c34810eb4c78ef014 +2019-11-25 5eed22d916a3c651695076144c214535df42f124 diff --git a/repos/libports/recipes/src/zlib/hash b/repos/libports/recipes/src/zlib/hash index 0582c0bd1..216ee6875 100644 --- a/repos/libports/recipes/src/zlib/hash +++ b/repos/libports/recipes/src/zlib/hash @@ -1 +1 @@ -2019-09-19 7647c62283da5330edfd12f13a10c7348cfc151e +2019-11-18 862ca9dc967e640e6937ea722d203e0db3f2220e diff --git a/repos/libports/run/execve.run b/repos/libports/run/execve.run index 424c32dab..c20fcd75c 100644 --- a/repos/libports/run/execve.run +++ b/repos/libports/run/execve.run @@ -16,9 +16,13 @@ install_config { <arg value="name_of_executeable"/> <arg value="100"/> <libc stdin="/null" stdout="/log" stderr="/log"/> - <vfs> <null/> <log/> </vfs> + <vfs> <rom name="test-execve"/> <null/> <log/> </vfs> </config> - <route> <any-service> <parent/> </any-service> </route> + <route> + <service name="ROM" label="/test-execve"> + <parent label="test-execve"/> </service> + <any-service> <parent/> </any-service> + </route> </start> </config> } diff --git a/repos/libports/run/extract.run b/repos/libports/run/extract.run index c8da86016..4bf7419e1 100644 --- a/repos/libports/run/extract.run +++ b/repos/libports/run/extract.run @@ -18,7 +18,8 @@ install_config { <start name="extract" caps="200"> <resource name="RAM" quantum="12M"/> <config verbose="yes"> - <libc stdout="/dev/log" stderr="/dev/log"/> + <libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/null" + update_mtime="no"/> <vfs> <dir name="archived"> <rom name="test.tar.xz"/> diff --git a/repos/libports/run/libc_fatfs.run b/repos/libports/run/libc_fatfs.run deleted file mode 100644 index f837d6959..000000000 --- a/repos/libports/run/libc_fatfs.run +++ /dev/null @@ -1,12 +0,0 @@ -set mkfs_cmd [installed_command mkfs.vfat] -set mkfs_opts "-F32" -set filesystem fatfs - -# -# The fatfs_libc plugin opens a block session directly. If the VFS opened -# the block session, the plugin would try to open a second one, which -# would get denied by the block driver. -# -set libc_dev_blkdev "" - -source ${genode_dir}/repos/libports/run/libc_filesystem_test.inc diff --git a/repos/libports/run/libc_getpwent.run b/repos/libports/run/libc_getpwent.run index 62ded8340..d8e6d15cf 100644 --- a/repos/libports/run/libc_getpwent.run +++ b/repos/libports/run/libc_getpwent.run @@ -26,7 +26,7 @@ install_config { </config> </start> - <start name="test"> + <start name="test" caps="1000"> <binary name="sequence"/> <resource name="RAM" quantum="4M"/> <config> diff --git a/repos/libports/run/libc_vfs_fatfs_fs.run b/repos/libports/run/libc_vfs_fatfs_fs.run deleted file mode 100644 index 7095c665d..000000000 --- a/repos/libports/run/libc_vfs_fatfs_fs.run +++ /dev/null @@ -1,7 +0,0 @@ -set build_component server/fatfs_fs -set binary fatfs_fs -set mkfs_cmd mkfs.vfat -set mkfs_opts "-F32" -set vfs_dev_blkdev "" - -source ${genode_dir}/repos/libports/run/libc_vfs_fs_test.inc diff --git a/repos/libports/run/libc_vfs_filesystem_test.inc b/repos/libports/run/libc_vfs_filesystem_test.inc index ee71558a3..30cd4c832 100644 --- a/repos/libports/run/libc_vfs_filesystem_test.inc +++ b/repos/libports/run/libc_vfs_filesystem_test.inc @@ -137,14 +137,14 @@ append_if $use_ram_block config { append_if $use_vfs_server config " <start name=\"vfs\" caps=\"200\"> - <resource name=\"RAM\" quantum=\"8M\" /> + <resource name=\"RAM\" quantum=\"12M\" /> <provides><service name=\"File_system\"/></provides> <config> <vfs> <dir name=\"dev\"> <log/> </dir>} $test_vfs_config </vfs> - <policy label_prefix=\"test-libc_vfs\" writeable=\"yes\"/> + <policy label_prefix=\"test-libc_vfs\" root=\"/\" writeable=\"yes\"/> </config> </start>" @@ -154,6 +154,19 @@ append config { install_config $config +# +# Prepare hard-disk image for test (used by Qemu or in RAM) +# + +set disk_image "bin/test.hda" +set cmd "dd if=/dev/zero of=$disk_image bs=1024 count=65536" +puts "creating disk image: $cmd" +catch { exec sh -c $cmd } + +set cmd "$mkfs_cmd $mkfs_opts $disk_image" +puts "formating disk: $cmd" +catch { exec sh -c $cmd } + # # Boot modules # @@ -174,19 +187,6 @@ build_boot_image $boot_modules puts "#### boot_modules: $boot_modules" -# -# Execute test case -# - -set disk_image "bin/test.hda" -set cmd "dd if=/dev/zero of=$disk_image bs=1024 count=65536" -puts "creating disk image: $cmd" -catch { exec sh -c $cmd } - -set cmd "$mkfs_cmd $mkfs_opts $disk_image" -puts "formating disk: $cmd" -catch { exec sh -c $cmd } - # # Qemu # diff --git a/repos/libports/run/lwip_lx.run b/repos/libports/run/lwip_lx.run index eae526d35..aa930856c 100644 --- a/repos/libports/run/lwip_lx.run +++ b/repos/libports/run/lwip_lx.run @@ -62,7 +62,7 @@ install_config $config set boot_modules { core init timer linux_nic_drv - ld.lib.so libc.lib.so vfs.lib.so libm.lib.so posix.lib.so vfs_lwip.lib.so test-lwip_httpsrv + ld.lib.so libc.lib.so vfs.lib.so vfs_lwip.lib.so test-lwip_httpsrv } build_boot_image $boot_modules diff --git a/repos/libports/run/nic_router.run b/repos/libports/run/nic_router.run index 3c1607b88..4932f5a08 100644 --- a/repos/libports/run/nic_router.run +++ b/repos/libports/run/nic_router.run @@ -298,6 +298,8 @@ append config { config="yes" quota="no" stats="no" + link_state="yes" + link_state_triggers="yes" interval_sec="60" /> <uplink domain="uplink"/> diff --git a/repos/libports/run/qt5_drivers.inc b/repos/libports/run/qt5_drivers.inc index 886b511d5..25d8ac048 100644 --- a/repos/libports/run/qt5_drivers.inc +++ b/repos/libports/run/qt5_drivers.inc @@ -228,6 +228,7 @@ proc drivers_start_nodes { feature_arg } { <key name="KEY_KP2" to="KEY_DOWN"/> <key name="KEY_KP3" to="KEY_PAGEDOWN"/> <key name="KEY_KP4" to="KEY_LEFT"/> + <key name="KEY_KP5" to="KEY_RESERVED"/> <key name="KEY_KP6" to="KEY_RIGHT"/> <key name="KEY_KP7" to="KEY_HOME"/> <key name="KEY_KP8" to="KEY_UP"/> @@ -248,7 +249,7 @@ proc drivers_start_nodes { feature_arg } { append start_nodes { <start name="input_filter"> - <resource name="RAM" quantum="1M" /> + <resource name="RAM" quantum="1280K" /> <provides> <service name="Input" /> </provides> <config>} append_if [use_ps2_drv feature] start_nodes { @@ -274,7 +275,6 @@ proc drivers_start_nodes { feature_arg } { </remap> <mod1> <key name="KEY_LEFTSHIFT"/> <key name="KEY_RIGHTSHIFT"/> - <rom name="capslock"/> </mod1> <mod2> <key name="KEY_LEFTCTRL"/> <key name="KEY_RIGHTCTRL"/> @@ -282,6 +282,9 @@ proc drivers_start_nodes { feature_arg } { <mod3> <key name="KEY_RIGHTALT"/> <!-- AltGr --> </mod3> + <mod4> + <rom name="capslock"/> + </mod4> <repeat delay_ms="500" rate_ms="50"/>} append start_nodes " <include rom=\"[language_chargen].chargen\"/>" diff --git a/repos/libports/run/qt5_textedit.run b/repos/libports/run/qt5_textedit.run index ca9b3beb9..a8e78d740 100644 --- a/repos/libports/run/qt5_textedit.run +++ b/repos/libports/run/qt5_textedit.run @@ -3,7 +3,8 @@ source ${genode_dir}/repos/libports/run/qt5_common.inc import_from_depot [depot_user]/src/qt5_component \ [depot_user]/src/qt5_printsupport \ [depot_user]/src/qt5_textedit \ - [depot_user]/src/qt5_widgets + [depot_user]/src/qt5_widgets \ + [depot_user]/src/ram_fs # # Build @@ -16,13 +17,6 @@ if {[have_spec odroid_xu]} { append build_components [qt5_build_components feature] -set use_ahci_driver [expr [have_spec x86] && ![have_spec linux]] - -lappend_if $use_ahci_driver build_components drivers/ahci -lappend_if [have_spec acpi] build_components drivers/acpi -lappend_if [have_spec linux] build_components server/ram_fs -lappend_if [expr ![have_spec linux]] build_components server/fatfs_fs - build $build_components # @@ -32,7 +26,9 @@ build $build_components append config { <config> <parent-provides>} + append config [qt5_parent_provides feature] + append config { </parent-provides> <default caps="100"/> @@ -42,16 +38,7 @@ append config { append config [qt5_start_nodes feature] -append_if $use_ahci_driver config { - <start name="ahci_drv"> - <resource name="RAM" quantum="5M"/> - <provides> <service name="Block"/> </provides> - <config> - <policy label_prefix="fatfs_fs" device="0" /> - </config> - </start>} - -append_if [have_spec linux] config { +append config { <start name="ram_fs"> <resource name="RAM" quantum="10M"/> <provides><service name="File_system"/></provides> @@ -62,16 +49,6 @@ append_if [have_spec linux] config { </config> </start>} -append_if [expr ![have_spec linux]] config { - <start name="fatfs_fs"> - <resource name="RAM" quantum="10M"/> - <provides><service name="File_system"/></provides> - <config> - <!-- constrain sessions according to their labels --> - <policy label_prefix="textedit" root="/" writeable="yes" /> - </config> - </start>} - append config { <start name="textedit" caps="300"> <resource name="RAM" quantum="70M"/> @@ -125,22 +102,6 @@ install_config $config append boot_modules [qt5_boot_modules feature] -# platform-specific modules -lappend_if [have_spec linux] boot_modules ram_fs -lappend_if [expr ![have_spec linux]] boot_modules fatfs_fs -lappend_if $use_ahci_driver boot_modules ahci_drv - build_boot_image $boot_modules -set disk_image "bin/test.hda" -set cmd "dd if=/dev/zero of=$disk_image bs=1024 count=65536" -puts "creating disk image: $cmd" -catch { exec sh -c $cmd } - -set cmd "mkfs.vfat -F32 $disk_image" -puts "formating disk image with vfat file system: $cmd" -catch { exec sh -c $cmd } - -append_if $use_ahci_driver qemu_args " -drive id=disk,file=$disk_image,format=raw,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d" - run_genode_until forever diff --git a/repos/libports/run/sntp_client.run b/repos/libports/run/sntp_client.run index ca7c098a1..e8dd557e3 100644 --- a/repos/libports/run/sntp_client.run +++ b/repos/libports/run/sntp_client.run @@ -1,10 +1,15 @@ -assert_spec x86 +if { [get_cmd_switch --autopilot] } { assert_spec x86 } if { [have_spec linux] } { puts "Run script is not supported on this platform." exit 0 } +set host_tool [installed_command host] +set ntp_ip [exec $host_tool -t A pool.ntp.org | head -1 | cut -d " " -f 4] + +puts "Using NTP server $ntp_ip" + create_boot_directory import_from_depot [depot_user]/src/[base_src] \ @@ -56,7 +61,7 @@ append config { <start name="sntp_client"> <resource name="RAM" quantum="8M"/> - <config verbose="no" dst_ip="193.175.73.151" period_min="1"/> + <config verbose="no" dst_ip="} $ntp_ip {" period_min="1"/> </start> </config>} diff --git a/repos/libports/src/app/gcov/target.mk b/repos/libports/src/app/gcov/target.mk index 5306ba1ec..25ca480e9 100644 --- a/repos/libports/src/app/gcov/target.mk +++ b/repos/libports/src/app/gcov/target.mk @@ -16,6 +16,10 @@ ifeq ($(filter-out $(SPECS),arm),) INC_DIR += $(GCOV_PORT_DIR)/include/arm/gcc endif +ifeq ($(filter-out $(SPECS),arm_64),) + INC_DIR += $(GCOV_PORT_DIR)/include/arm_64/gcc +endif + ifeq ($(filter-out $(SPECS),x86_32),) INC_DIR += $(GCOV_PORT_DIR)/include/x86_32/gcc endif diff --git a/repos/libports/src/lib/gmp/mpn/spec/32bit/mp_bases.c b/repos/libports/src/lib/gmp/mpn/spec/32bit/mp_bases.c index 4dd14381b..4a99f0fd4 100644 --- a/repos/libports/src/lib/gmp/mpn/spec/32bit/mp_bases.c +++ b/repos/libports/src/lib/gmp/mpn/spec/32bit/mp_bases.c @@ -9,261 +9,261 @@ Error, error, this data is for 32 bits const struct bases mp_bases[257] = { - /* 0 */ { 0, 0.0, 0 }, - /* 1 */ { 0, 1e37, 0 }, - /* 2 */ { 32, 1.0000000000000000, 0x1 }, - /* 3 */ { 20, 0.6309297535714574, CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, - /* 4 */ { 16, 0.5000000000000000, 0x2 }, - /* 5 */ { 13, 0.4306765580733931, CNST_LIMB(0x48c27395), CNST_LIMB(0xc25c2684) }, - /* 6 */ { 12, 0.3868528072345416, CNST_LIMB(0x81bf1000), CNST_LIMB(0xf91bd1b6) }, - /* 7 */ { 11, 0.3562071871080222, CNST_LIMB(0x75db9c97), CNST_LIMB(0x1607a2cb) }, - /* 8 */ { 10, 0.3333333333333334, 0x3 }, - /* 9 */ { 10, 0.3154648767857287, CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, - /* 10 */ { 9, 0.3010299956639811, CNST_LIMB(0x3b9aca00), CNST_LIMB(0x12e0be82) }, - /* 11 */ { 9, 0.2890648263178878, CNST_LIMB(0x8c8b6d2b), CNST_LIMB(0xd24cde04) }, - /* 12 */ { 8, 0.2789429456511298, CNST_LIMB(0x19a10000), CNST_LIMB(0x3fa39ab5) }, - /* 13 */ { 8, 0.2702381544273197, CNST_LIMB(0x309f1021), CNST_LIMB(0x50f8ac5f) }, - /* 14 */ { 8, 0.2626495350371936, CNST_LIMB(0x57f6c100), CNST_LIMB(0x74843b1e) }, - /* 15 */ { 8, 0.2559580248098155, CNST_LIMB(0x98c29b81), CNST_LIMB(0xad0326c2) }, - /* 16 */ { 8, 0.2500000000000000, 0x4 }, - /* 17 */ { 7, 0.2446505421182260, CNST_LIMB(0x18754571), CNST_LIMB(0x4ef0b6bd) }, - /* 18 */ { 7, 0.2398124665681315, CNST_LIMB(0x247dbc80), CNST_LIMB(0xc0fc48a1) }, - /* 19 */ { 7, 0.2354089133666382, CNST_LIMB(0x3547667b), CNST_LIMB(0x33838942) }, - /* 20 */ { 7, 0.2313782131597592, CNST_LIMB(0x4c4b4000), CNST_LIMB(0xad7f29ab) }, - /* 21 */ { 7, 0.2276702486969530, CNST_LIMB(0x6b5a6e1d), CNST_LIMB(0x313c3d15) }, - /* 22 */ { 7, 0.2242438242175754, CNST_LIMB(0x94ace180), CNST_LIMB(0xb8cca9e0) }, - /* 23 */ { 7, 0.2210647294575037, CNST_LIMB(0xcaf18367), CNST_LIMB(0x42ed6de9) }, - /* 24 */ { 6, 0.2181042919855316, CNST_LIMB(0xb640000), CNST_LIMB(0x67980e0b) }, - /* 25 */ { 6, 0.2153382790366965, CNST_LIMB(0xe8d4a51), CNST_LIMB(0x19799812) }, - /* 26 */ { 6, 0.2127460535533632, CNST_LIMB(0x1269ae40), CNST_LIMB(0xbce85396) }, - /* 27 */ { 6, 0.2103099178571525, CNST_LIMB(0x17179149), CNST_LIMB(0x62c103a9) }, - /* 28 */ { 6, 0.2080145976765095, CNST_LIMB(0x1cb91000), CNST_LIMB(0x1d353d43) }, - /* 29 */ { 6, 0.2058468324604344, CNST_LIMB(0x23744899), CNST_LIMB(0xce1decea) }, - /* 30 */ { 6, 0.2037950470905062, CNST_LIMB(0x2b73a840), CNST_LIMB(0x790fc511) }, - /* 31 */ { 6, 0.2018490865820999, CNST_LIMB(0x34e63b41), CNST_LIMB(0x35b865a0) }, - /* 32 */ { 6, 0.2000000000000000, 0x5 }, - /* 33 */ { 6, 0.1982398631705605, CNST_LIMB(0x4cfa3cc1), CNST_LIMB(0xa9aed1b3) }, - /* 34 */ { 6, 0.1965616322328226, CNST_LIMB(0x5c13d840), CNST_LIMB(0x63dfc229) }, - /* 35 */ { 6, 0.1949590218937863, CNST_LIMB(0x6d91b519), CNST_LIMB(0x2b0fee30) }, - /* 36 */ { 6, 0.1934264036172708, CNST_LIMB(0x81bf1000), CNST_LIMB(0xf91bd1b6) }, - /* 37 */ { 6, 0.1919587200065601, CNST_LIMB(0x98ede0c9), CNST_LIMB(0xac89c3a9) }, - /* 38 */ { 6, 0.1905514124267734, CNST_LIMB(0xb3773e40), CNST_LIMB(0x6d2c32fe) }, - /* 39 */ { 6, 0.1892003595168700, CNST_LIMB(0xd1bbc4d1), CNST_LIMB(0x387907c9) }, - /* 40 */ { 6, 0.1879018247091076, CNST_LIMB(0xf4240000), CNST_LIMB(0xc6f7a0b) }, - /* 41 */ { 5, 0.1866524112389434, CNST_LIMB(0x6e7d349), CNST_LIMB(0x28928154) }, - /* 42 */ { 5, 0.1854490234153689, CNST_LIMB(0x7ca30a0), CNST_LIMB(0x6e8629d) }, - /* 43 */ { 5, 0.1842888331487062, CNST_LIMB(0x8c32bbb), CNST_LIMB(0xd373dca0) }, - /* 44 */ { 5, 0.1831692509136336, CNST_LIMB(0x9d46c00), CNST_LIMB(0xa0b17895) }, - /* 45 */ { 5, 0.1820879004699383, CNST_LIMB(0xaffacfd), CNST_LIMB(0x746811a5) }, - /* 46 */ { 5, 0.1810425967800402, CNST_LIMB(0xc46bee0), CNST_LIMB(0x4da6500f) }, - /* 47 */ { 5, 0.1800313266566926, CNST_LIMB(0xdab86ef), CNST_LIMB(0x2ba23582) }, - /* 48 */ { 5, 0.1790522317510413, CNST_LIMB(0xf300000), CNST_LIMB(0xdb20a88) }, - /* 49 */ { 5, 0.1781035935540111, CNST_LIMB(0x10d63af1), CNST_LIMB(0xe68d5ce4) }, - /* 50 */ { 5, 0.1771838201355579, CNST_LIMB(0x12a05f20), CNST_LIMB(0xb7cdfd9d) }, - /* 51 */ { 5, 0.1762914343888821, CNST_LIMB(0x1490aae3), CNST_LIMB(0x8e583933) }, - /* 52 */ { 5, 0.1754250635819545, CNST_LIMB(0x16a97400), CNST_LIMB(0x697cc3ea) }, - /* 53 */ { 5, 0.1745834300480449, CNST_LIMB(0x18ed2825), CNST_LIMB(0x48a5ca6c) }, - /* 54 */ { 5, 0.1737653428714400, CNST_LIMB(0x1b5e4d60), CNST_LIMB(0x2b52db16) }, - /* 55 */ { 5, 0.1729696904450771, CNST_LIMB(0x1dff8297), CNST_LIMB(0x111586a6) }, - /* 56 */ { 5, 0.1721954337940981, CNST_LIMB(0x20d38000), CNST_LIMB(0xf31d2b36) }, - /* 57 */ { 5, 0.1714416005739134, CNST_LIMB(0x23dd1799), CNST_LIMB(0xc8d76d19) }, - /* 58 */ { 5, 0.1707072796637201, CNST_LIMB(0x271f35a0), CNST_LIMB(0xa2cb1eb4) }, - /* 59 */ { 5, 0.1699916162869140, CNST_LIMB(0x2a9ce10b), CNST_LIMB(0x807c3ec3) }, - /* 60 */ { 5, 0.1692938075987814, CNST_LIMB(0x2e593c00), CNST_LIMB(0x617ec8bf) }, - /* 61 */ { 5, 0.1686130986895011, CNST_LIMB(0x3257844d), CNST_LIMB(0x45746cbe) }, - /* 62 */ { 5, 0.1679487789570419, CNST_LIMB(0x369b13e0), CNST_LIMB(0x2c0aa273) }, - /* 63 */ { 5, 0.1673001788101741, CNST_LIMB(0x3b27613f), CNST_LIMB(0x14f90805) }, - /* 64 */ { 5, 0.1666666666666667, 0x6 }, - /* 65 */ { 5, 0.1660476462159378, CNST_LIMB(0x4528a141), CNST_LIMB(0xd9cf0829) }, - /* 66 */ { 5, 0.1654425539190583, CNST_LIMB(0x4aa51420), CNST_LIMB(0xb6fc4841) }, - /* 67 */ { 5, 0.1648508567221604, CNST_LIMB(0x50794633), CNST_LIMB(0x973054cb) }, - /* 68 */ { 5, 0.1642720499620502, CNST_LIMB(0x56a94400), CNST_LIMB(0x7a1dbe4b) }, - /* 69 */ { 5, 0.1637056554452156, CNST_LIMB(0x5d393975), CNST_LIMB(0x5f7fcd7f) }, - /* 70 */ { 5, 0.1631512196835108, CNST_LIMB(0x642d7260), CNST_LIMB(0x47196c84) }, - /* 71 */ { 5, 0.1626083122716341, CNST_LIMB(0x6b8a5ae7), CNST_LIMB(0x30b43635) }, - /* 72 */ { 5, 0.1620765243931223, CNST_LIMB(0x73548000), CNST_LIMB(0x1c1fa5f6) }, - /* 73 */ { 5, 0.1615554674429964, CNST_LIMB(0x7b908fe9), CNST_LIMB(0x930634a) }, - /* 74 */ { 5, 0.1610447717564444, CNST_LIMB(0x84435aa0), CNST_LIMB(0xef7f4a3c) }, - /* 75 */ { 5, 0.1605440854340214, CNST_LIMB(0x8d71d25b), CNST_LIMB(0xcf5552d2) }, - /* 76 */ { 5, 0.1600530732548213, CNST_LIMB(0x97210c00), CNST_LIMB(0xb1a47c8e) }, - /* 77 */ { 5, 0.1595714156699382, CNST_LIMB(0xa1563f9d), CNST_LIMB(0x9634b43e) }, - /* 78 */ { 5, 0.1590988078692941, CNST_LIMB(0xac16c8e0), CNST_LIMB(0x7cd3817d) }, - /* 79 */ { 5, 0.1586349589155960, CNST_LIMB(0xb768278f), CNST_LIMB(0x65536761) }, - /* 80 */ { 5, 0.1581795909397823, CNST_LIMB(0xc3500000), CNST_LIMB(0x4f8b588e) }, - /* 81 */ { 5, 0.1577324383928644, CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, - /* 82 */ { 5, 0.1572932473495469, CNST_LIMB(0xdcfa6920), CNST_LIMB(0x28928154) }, - /* 83 */ { 5, 0.1568617748594410, CNST_LIMB(0xeac8fd83), CNST_LIMB(0x1721bfb0) }, - /* 84 */ { 5, 0.1564377883420716, CNST_LIMB(0xf9461400), CNST_LIMB(0x6e8629d) }, - /* 85 */ { 4, 0.1560210650222250, CNST_LIMB(0x31c84b1), CNST_LIMB(0x491cc17c) }, - /* 86 */ { 4, 0.1556113914024940, CNST_LIMB(0x342ab10), CNST_LIMB(0x3a11d83b) }, - /* 87 */ { 4, 0.1552085627701551, CNST_LIMB(0x36a2c21), CNST_LIMB(0x2be074cd) }, - /* 88 */ { 4, 0.1548123827357682, CNST_LIMB(0x3931000), CNST_LIMB(0x1e7a02e7) }, - /* 89 */ { 4, 0.1544226628011101, CNST_LIMB(0x3bd5ee1), CNST_LIMB(0x11d10edd) }, - /* 90 */ { 4, 0.1540392219542636, CNST_LIMB(0x3e92110), CNST_LIMB(0x5d92c68) }, - /* 91 */ { 4, 0.1536618862898642, CNST_LIMB(0x4165ef1), CNST_LIMB(0xf50dbfb2) }, - /* 92 */ { 4, 0.1532904886526781, CNST_LIMB(0x4452100), CNST_LIMB(0xdf9f1316) }, - /* 93 */ { 4, 0.1529248683028321, CNST_LIMB(0x4756fd1), CNST_LIMB(0xcb52a684) }, - /* 94 */ { 4, 0.1525648706011593, CNST_LIMB(0x4a75410), CNST_LIMB(0xb8163e97) }, - /* 95 */ { 4, 0.1522103467132434, CNST_LIMB(0x4dad681), CNST_LIMB(0xa5d8f269) }, - /* 96 */ { 4, 0.1518611533308632, CNST_LIMB(0x5100000), CNST_LIMB(0x948b0fcd) }, - /* 97 */ { 4, 0.1515171524096389, CNST_LIMB(0x546d981), CNST_LIMB(0x841e0215) }, - /* 98 */ { 4, 0.1511782109217764, CNST_LIMB(0x57f6c10), CNST_LIMB(0x74843b1e) }, - /* 99 */ { 4, 0.1508442006228941, CNST_LIMB(0x5b9c0d1), CNST_LIMB(0x65b11e6e) }, - /* 100 */ { 4, 0.1505149978319906, CNST_LIMB(0x5f5e100), CNST_LIMB(0x5798ee23) }, - /* 101 */ { 4, 0.1501904832236879, CNST_LIMB(0x633d5f1), CNST_LIMB(0x4a30b99b) }, - /* 102 */ { 4, 0.1498705416319474, CNST_LIMB(0x673a910), CNST_LIMB(0x3d6e4d94) }, - /* 103 */ { 4, 0.1495550618645152, CNST_LIMB(0x6b563e1), CNST_LIMB(0x314825b0) }, - /* 104 */ { 4, 0.1492439365274121, CNST_LIMB(0x6f91000), CNST_LIMB(0x25b55f2e) }, - /* 105 */ { 4, 0.1489370618588283, CNST_LIMB(0x73eb721), CNST_LIMB(0x1aadaccb) }, - /* 106 */ { 4, 0.1486343375718350, CNST_LIMB(0x7866310), CNST_LIMB(0x10294ba2) }, - /* 107 */ { 4, 0.1483356667053617, CNST_LIMB(0x7d01db1), CNST_LIMB(0x620f8f6) }, - /* 108 */ { 4, 0.1480409554829326, CNST_LIMB(0x81bf100), CNST_LIMB(0xf91bd1b6) }, - /* 109 */ { 4, 0.1477501131786861, CNST_LIMB(0x869e711), CNST_LIMB(0xe6d37b2a) }, - /* 110 */ { 4, 0.1474630519902391, CNST_LIMB(0x8ba0a10), CNST_LIMB(0xd55cff6e) }, - /* 111 */ { 4, 0.1471796869179852, CNST_LIMB(0x90c6441), CNST_LIMB(0xc4ad2db2) }, - /* 112 */ { 4, 0.1468999356504447, CNST_LIMB(0x9610000), CNST_LIMB(0xb4b985cf) }, - /* 113 */ { 4, 0.1466237184553111, CNST_LIMB(0x9b7e7c1), CNST_LIMB(0xa5782bef) }, - /* 114 */ { 4, 0.1463509580758620, CNST_LIMB(0xa112610), CNST_LIMB(0x96dfdd2a) }, - /* 115 */ { 4, 0.1460815796324244, CNST_LIMB(0xa6cc591), CNST_LIMB(0x88e7e509) }, - /* 116 */ { 4, 0.1458155105286054, CNST_LIMB(0xacad100), CNST_LIMB(0x7b8813d3) }, - /* 117 */ { 4, 0.1455526803620167, CNST_LIMB(0xb2b5331), CNST_LIMB(0x6eb8b595) }, - /* 118 */ { 4, 0.1452930208392428, CNST_LIMB(0xb8e5710), CNST_LIMB(0x627289db) }, - /* 119 */ { 4, 0.1450364656948130, CNST_LIMB(0xbf3e7a1), CNST_LIMB(0x56aebc07) }, - /* 120 */ { 4, 0.1447829506139581, CNST_LIMB(0xc5c1000), CNST_LIMB(0x4b66dc33) }, - /* 121 */ { 4, 0.1445324131589439, CNST_LIMB(0xcc6db61), CNST_LIMB(0x4094d8a3) }, - /* 122 */ { 4, 0.1442847926987864, CNST_LIMB(0xd345510), CNST_LIMB(0x3632f7a5) }, - /* 123 */ { 4, 0.1440400303421672, CNST_LIMB(0xda48871), CNST_LIMB(0x2c3bd1f0) }, - /* 124 */ { 4, 0.1437980688733775, CNST_LIMB(0xe178100), CNST_LIMB(0x22aa4d5f) }, - /* 125 */ { 4, 0.1435588526911310, CNST_LIMB(0xe8d4a51), CNST_LIMB(0x19799812) }, - /* 126 */ { 4, 0.1433223277500932, CNST_LIMB(0xf05f010), CNST_LIMB(0x10a523e5) }, - /* 127 */ { 4, 0.1430884415049874, CNST_LIMB(0xf817e01), CNST_LIMB(0x828a237) }, - /* 128 */ { 4, 0.1428571428571428, 0x7 }, - /* 129 */ { 4, 0.1426283821033600, CNST_LIMB(0x10818201), CNST_LIMB(0xf04ec452) }, - /* 130 */ { 4, 0.1424021108869747, CNST_LIMB(0x11061010), CNST_LIMB(0xe136444a) }, - /* 131 */ { 4, 0.1421782821510107, CNST_LIMB(0x118db651), CNST_LIMB(0xd2af9589) }, - /* 132 */ { 4, 0.1419568500933153, CNST_LIMB(0x12188100), CNST_LIMB(0xc4b42a83) }, - /* 133 */ { 4, 0.1417377701235801, CNST_LIMB(0x12a67c71), CNST_LIMB(0xb73dccf5) }, - /* 134 */ { 4, 0.1415209988221527, CNST_LIMB(0x1337b510), CNST_LIMB(0xaa4698c5) }, - /* 135 */ { 4, 0.1413064939005528, CNST_LIMB(0x13cc3761), CNST_LIMB(0x9dc8f729) }, - /* 136 */ { 4, 0.1410942141636095, CNST_LIMB(0x14641000), CNST_LIMB(0x91bf9a30) }, - /* 137 */ { 4, 0.1408841194731412, CNST_LIMB(0x14ff4ba1), CNST_LIMB(0x86257887) }, - /* 138 */ { 4, 0.1406761707131039, CNST_LIMB(0x159df710), CNST_LIMB(0x7af5c98c) }, - /* 139 */ { 4, 0.1404703297561400, CNST_LIMB(0x16401f31), CNST_LIMB(0x702c01a0) }, - /* 140 */ { 4, 0.1402665594314587, CNST_LIMB(0x16e5d100), CNST_LIMB(0x65c3ceb1) }, - /* 141 */ { 4, 0.1400648234939879, CNST_LIMB(0x178f1991), CNST_LIMB(0x5bb91502) }, - /* 142 */ { 4, 0.1398650865947379, CNST_LIMB(0x183c0610), CNST_LIMB(0x5207ec23) }, - /* 143 */ { 4, 0.1396673142523192, CNST_LIMB(0x18eca3c1), CNST_LIMB(0x48ac9c19) }, - /* 144 */ { 4, 0.1394714728255649, CNST_LIMB(0x19a10000), CNST_LIMB(0x3fa39ab5) }, - /* 145 */ { 4, 0.1392775294872041, CNST_LIMB(0x1a592841), CNST_LIMB(0x36e98912) }, - /* 146 */ { 4, 0.1390854521985406, CNST_LIMB(0x1b152a10), CNST_LIMB(0x2e7b3140) }, - /* 147 */ { 4, 0.1388952096850913, CNST_LIMB(0x1bd51311), CNST_LIMB(0x2655840b) }, - /* 148 */ { 4, 0.1387067714131417, CNST_LIMB(0x1c98f100), CNST_LIMB(0x1e7596ea) }, - /* 149 */ { 4, 0.1385201075671774, CNST_LIMB(0x1d60d1b1), CNST_LIMB(0x16d8a20d) }, - /* 150 */ { 4, 0.1383351890281539, CNST_LIMB(0x1e2cc310), CNST_LIMB(0xf7bfe87) }, - /* 151 */ { 4, 0.1381519873525671, CNST_LIMB(0x1efcd321), CNST_LIMB(0x85d2492) }, - /* 152 */ { 4, 0.1379704747522905, CNST_LIMB(0x1fd11000), CNST_LIMB(0x179a9f4) }, - /* 153 */ { 4, 0.1377906240751463, CNST_LIMB(0x20a987e1), CNST_LIMB(0xf59e80eb) }, - /* 154 */ { 4, 0.1376124087861776, CNST_LIMB(0x21864910), CNST_LIMB(0xe8b768db) }, - /* 155 */ { 4, 0.1374358029495937, CNST_LIMB(0x226761f1), CNST_LIMB(0xdc39d6d5) }, - /* 156 */ { 4, 0.1372607812113589, CNST_LIMB(0x234ce100), CNST_LIMB(0xd021c5d1) }, - /* 157 */ { 4, 0.1370873187823978, CNST_LIMB(0x2436d4d1), CNST_LIMB(0xc46b5e37) }, - /* 158 */ { 4, 0.1369153914223921, CNST_LIMB(0x25254c10), CNST_LIMB(0xb912f39c) }, - /* 159 */ { 4, 0.1367449754241439, CNST_LIMB(0x26185581), CNST_LIMB(0xae150294) }, - /* 160 */ { 4, 0.1365760475984821, CNST_LIMB(0x27100000), CNST_LIMB(0xa36e2eb1) }, - /* 161 */ { 4, 0.1364085852596902, CNST_LIMB(0x280c5a81), CNST_LIMB(0x991b4094) }, - /* 162 */ { 4, 0.1362425662114337, CNST_LIMB(0x290d7410), CNST_LIMB(0x8f19241e) }, - /* 163 */ { 4, 0.1360779687331669, CNST_LIMB(0x2a135bd1), CNST_LIMB(0x8564e6b7) }, - /* 164 */ { 4, 0.1359147715670014, CNST_LIMB(0x2b1e2100), CNST_LIMB(0x7bfbb5b4) }, - /* 165 */ { 4, 0.1357529539050150, CNST_LIMB(0x2c2dd2f1), CNST_LIMB(0x72dadcc8) }, - /* 166 */ { 4, 0.1355924953769863, CNST_LIMB(0x2d428110), CNST_LIMB(0x69ffc498) }, - /* 167 */ { 4, 0.1354333760385373, CNST_LIMB(0x2e5c3ae1), CNST_LIMB(0x6167f154) }, - /* 168 */ { 4, 0.1352755763596663, CNST_LIMB(0x2f7b1000), CNST_LIMB(0x5911016e) }, - /* 169 */ { 4, 0.1351190772136599, CNST_LIMB(0x309f1021), CNST_LIMB(0x50f8ac5f) }, - /* 170 */ { 4, 0.1349638598663645, CNST_LIMB(0x31c84b10), CNST_LIMB(0x491cc17c) }, - /* 171 */ { 4, 0.1348099059658079, CNST_LIMB(0x32f6d0b1), CNST_LIMB(0x417b26d8) }, - /* 172 */ { 4, 0.1346571975321549, CNST_LIMB(0x342ab100), CNST_LIMB(0x3a11d83b) }, - /* 173 */ { 4, 0.1345057169479844, CNST_LIMB(0x3563fc11), CNST_LIMB(0x32dee622) }, - /* 174 */ { 4, 0.1343554469488779, CNST_LIMB(0x36a2c210), CNST_LIMB(0x2be074cd) }, - /* 175 */ { 4, 0.1342063706143054, CNST_LIMB(0x37e71341), CNST_LIMB(0x2514bb58) }, - /* 176 */ { 4, 0.1340584713587980, CNST_LIMB(0x39310000), CNST_LIMB(0x1e7a02e7) }, - /* 177 */ { 4, 0.1339117329233981, CNST_LIMB(0x3a8098c1), CNST_LIMB(0x180ea5d0) }, - /* 178 */ { 4, 0.1337661393673756, CNST_LIMB(0x3bd5ee10), CNST_LIMB(0x11d10edd) }, - /* 179 */ { 4, 0.1336216750601996, CNST_LIMB(0x3d311091), CNST_LIMB(0xbbfb88e) }, - /* 180 */ { 4, 0.1334783246737591, CNST_LIMB(0x3e921100), CNST_LIMB(0x5d92c68) }, - /* 181 */ { 4, 0.1333360731748201, CNST_LIMB(0x3ff90031), CNST_LIMB(0x1c024c) }, - /* 182 */ { 4, 0.1331949058177136, CNST_LIMB(0x4165ef10), CNST_LIMB(0xf50dbfb2) }, - /* 183 */ { 4, 0.1330548081372441, CNST_LIMB(0x42d8eea1), CNST_LIMB(0xea30efa3) }, - /* 184 */ { 4, 0.1329157659418126, CNST_LIMB(0x44521000), CNST_LIMB(0xdf9f1316) }, - /* 185 */ { 4, 0.1327777653067443, CNST_LIMB(0x45d16461), CNST_LIMB(0xd555c0c9) }, - /* 186 */ { 4, 0.1326407925678156, CNST_LIMB(0x4756fd10), CNST_LIMB(0xcb52a684) }, - /* 187 */ { 4, 0.1325048343149731, CNST_LIMB(0x48e2eb71), CNST_LIMB(0xc193881f) }, - /* 188 */ { 4, 0.1323698773862368, CNST_LIMB(0x4a754100), CNST_LIMB(0xb8163e97) }, - /* 189 */ { 4, 0.1322359088617821, CNST_LIMB(0x4c0e0f51), CNST_LIMB(0xaed8b724) }, - /* 190 */ { 4, 0.1321029160581950, CNST_LIMB(0x4dad6810), CNST_LIMB(0xa5d8f269) }, - /* 191 */ { 4, 0.1319708865228925, CNST_LIMB(0x4f535d01), CNST_LIMB(0x9d15039d) }, - /* 192 */ { 4, 0.1318398080287045, CNST_LIMB(0x51000000), CNST_LIMB(0x948b0fcd) }, - /* 193 */ { 4, 0.1317096685686114, CNST_LIMB(0x52b36301), CNST_LIMB(0x8c394d1d) }, - /* 194 */ { 4, 0.1315804563506306, CNST_LIMB(0x546d9810), CNST_LIMB(0x841e0215) }, - /* 195 */ { 4, 0.1314521597928493, CNST_LIMB(0x562eb151), CNST_LIMB(0x7c3784f8) }, - /* 196 */ { 4, 0.1313247675185968, CNST_LIMB(0x57f6c100), CNST_LIMB(0x74843b1e) }, - /* 197 */ { 4, 0.1311982683517524, CNST_LIMB(0x59c5d971), CNST_LIMB(0x6d02985d) }, - /* 198 */ { 4, 0.1310726513121843, CNST_LIMB(0x5b9c0d10), CNST_LIMB(0x65b11e6e) }, - /* 199 */ { 4, 0.1309479056113158, CNST_LIMB(0x5d796e61), CNST_LIMB(0x5e8e5c64) }, - /* 200 */ { 4, 0.1308240206478128, CNST_LIMB(0x5f5e1000), CNST_LIMB(0x5798ee23) }, - /* 201 */ { 4, 0.1307009860033912, CNST_LIMB(0x614a04a1), CNST_LIMB(0x50cf7bde) }, - /* 202 */ { 4, 0.1305787914387386, CNST_LIMB(0x633d5f10), CNST_LIMB(0x4a30b99b) }, - /* 203 */ { 4, 0.1304574268895465, CNST_LIMB(0x65383231), CNST_LIMB(0x43bb66bd) }, - /* 204 */ { 4, 0.1303368824626505, CNST_LIMB(0x673a9100), CNST_LIMB(0x3d6e4d94) }, - /* 205 */ { 4, 0.1302171484322746, CNST_LIMB(0x69448e91), CNST_LIMB(0x374842ee) }, - /* 206 */ { 4, 0.1300982152363760, CNST_LIMB(0x6b563e10), CNST_LIMB(0x314825b0) }, - /* 207 */ { 4, 0.1299800734730872, CNST_LIMB(0x6d6fb2c1), CNST_LIMB(0x2b6cde75) }, - /* 208 */ { 4, 0.1298627138972530, CNST_LIMB(0x6f910000), CNST_LIMB(0x25b55f2e) }, - /* 209 */ { 4, 0.1297461274170591, CNST_LIMB(0x71ba3941), CNST_LIMB(0x2020a2c5) }, - /* 210 */ { 4, 0.1296303050907487, CNST_LIMB(0x73eb7210), CNST_LIMB(0x1aadaccb) }, - /* 211 */ { 4, 0.1295152381234257, CNST_LIMB(0x7624be11), CNST_LIMB(0x155b891f) }, - /* 212 */ { 4, 0.1294009178639407, CNST_LIMB(0x78663100), CNST_LIMB(0x10294ba2) }, - /* 213 */ { 4, 0.1292873358018581, CNST_LIMB(0x7aafdeb1), CNST_LIMB(0xb160fe9) }, - /* 214 */ { 4, 0.1291744835645007, CNST_LIMB(0x7d01db10), CNST_LIMB(0x620f8f6) }, - /* 215 */ { 4, 0.1290623529140715, CNST_LIMB(0x7f5c3a21), CNST_LIMB(0x14930ef) }, - /* 216 */ { 4, 0.1289509357448472, CNST_LIMB(0x81bf1000), CNST_LIMB(0xf91bd1b6) }, - /* 217 */ { 4, 0.1288402240804449, CNST_LIMB(0x842a70e1), CNST_LIMB(0xefdcb0c7) }, - /* 218 */ { 4, 0.1287302100711567, CNST_LIMB(0x869e7110), CNST_LIMB(0xe6d37b2a) }, - /* 219 */ { 4, 0.1286208859913518, CNST_LIMB(0x891b24f1), CNST_LIMB(0xddfeb94a) }, - /* 220 */ { 4, 0.1285122442369443, CNST_LIMB(0x8ba0a100), CNST_LIMB(0xd55cff6e) }, - /* 221 */ { 4, 0.1284042773229231, CNST_LIMB(0x8e2ef9d1), CNST_LIMB(0xcceced50) }, - /* 222 */ { 4, 0.1282969778809442, CNST_LIMB(0x90c64410), CNST_LIMB(0xc4ad2db2) }, - /* 223 */ { 4, 0.1281903386569819, CNST_LIMB(0x93669481), CNST_LIMB(0xbc9c75f9) }, - /* 224 */ { 4, 0.1280843525090381, CNST_LIMB(0x96100000), CNST_LIMB(0xb4b985cf) }, - /* 225 */ { 4, 0.1279790124049077, CNST_LIMB(0x98c29b81), CNST_LIMB(0xad0326c2) }, - /* 226 */ { 4, 0.1278743114199984, CNST_LIMB(0x9b7e7c10), CNST_LIMB(0xa5782bef) }, - /* 227 */ { 4, 0.1277702427352035, CNST_LIMB(0x9e43b6d1), CNST_LIMB(0x9e1771a9) }, - /* 228 */ { 4, 0.1276667996348261, CNST_LIMB(0xa1126100), CNST_LIMB(0x96dfdd2a) }, - /* 229 */ { 4, 0.1275639755045533, CNST_LIMB(0xa3ea8ff1), CNST_LIMB(0x8fd05c41) }, - /* 230 */ { 4, 0.1274617638294791, CNST_LIMB(0xa6cc5910), CNST_LIMB(0x88e7e509) }, - /* 231 */ { 4, 0.1273601581921741, CNST_LIMB(0xa9b7d1e1), CNST_LIMB(0x8225759d) }, - /* 232 */ { 4, 0.1272591522708010, CNST_LIMB(0xacad1000), CNST_LIMB(0x7b8813d3) }, - /* 233 */ { 4, 0.1271587398372755, CNST_LIMB(0xafac2921), CNST_LIMB(0x750eccf9) }, - /* 234 */ { 4, 0.1270589147554692, CNST_LIMB(0xb2b53310), CNST_LIMB(0x6eb8b595) }, - /* 235 */ { 4, 0.1269596709794558, CNST_LIMB(0xb5c843b1), CNST_LIMB(0x6884e923) }, - /* 236 */ { 4, 0.1268610025517973, CNST_LIMB(0xb8e57100), CNST_LIMB(0x627289db) }, - /* 237 */ { 4, 0.1267629036018709, CNST_LIMB(0xbc0cd111), CNST_LIMB(0x5c80c07b) }, - /* 238 */ { 4, 0.1266653683442337, CNST_LIMB(0xbf3e7a10), CNST_LIMB(0x56aebc07) }, - /* 239 */ { 4, 0.1265683910770258, CNST_LIMB(0xc27a8241), CNST_LIMB(0x50fbb19b) }, - /* 240 */ { 4, 0.1264719661804097, CNST_LIMB(0xc5c10000), CNST_LIMB(0x4b66dc33) }, - /* 241 */ { 4, 0.1263760881150453, CNST_LIMB(0xc91209c1), CNST_LIMB(0x45ef7c7c) }, - /* 242 */ { 4, 0.1262807514205999, CNST_LIMB(0xcc6db610), CNST_LIMB(0x4094d8a3) }, - /* 243 */ { 4, 0.1261859507142915, CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, - /* 244 */ { 4, 0.1260916806894653, CNST_LIMB(0xd3455100), CNST_LIMB(0x3632f7a5) }, - /* 245 */ { 4, 0.1259979361142023, CNST_LIMB(0xd6c16d31), CNST_LIMB(0x312a60c3) }, - /* 246 */ { 4, 0.1259047118299582, CNST_LIMB(0xda488710), CNST_LIMB(0x2c3bd1f0) }, - /* 247 */ { 4, 0.1258120027502338, CNST_LIMB(0xdddab5a1), CNST_LIMB(0x2766aa45) }, - /* 248 */ { 4, 0.1257198038592741, CNST_LIMB(0xe1781000), CNST_LIMB(0x22aa4d5f) }, - /* 249 */ { 4, 0.1256281102107963, CNST_LIMB(0xe520ad61), CNST_LIMB(0x1e06233c) }, - /* 250 */ { 4, 0.1255369169267456, CNST_LIMB(0xe8d4a510), CNST_LIMB(0x19799812) }, - /* 251 */ { 4, 0.1254462191960791, CNST_LIMB(0xec940e71), CNST_LIMB(0x15041c33) }, - /* 252 */ { 4, 0.1253560122735751, CNST_LIMB(0xf05f0100), CNST_LIMB(0x10a523e5) }, - /* 253 */ { 4, 0.1252662914786691, CNST_LIMB(0xf4359451), CNST_LIMB(0xc5c2749) }, - /* 254 */ { 4, 0.1251770521943144, CNST_LIMB(0xf817e010), CNST_LIMB(0x828a237) }, - /* 255 */ { 4, 0.1250882898658681, CNST_LIMB(0xfc05fc01), CNST_LIMB(0x40a1423) }, - /* 256 */ { 4, 0.1250000000000000, 0x8 }, + /* 0 */ { 0, 0, 0, 0, 0 }, + /* 1 */ { 0, 0, 0, 0, 0 }, + /* 2 */ { 32, CNST_LIMB(0xffffffff), CNST_LIMB(0x1fffffff), CNST_LIMB(0x1), CNST_LIMB(0x0) }, + /* 3 */ { 20, CNST_LIMB(0xa1849cc1), CNST_LIMB(0x32b80347), CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, + /* 4 */ { 16, CNST_LIMB(0x7fffffff), CNST_LIMB(0x3fffffff), CNST_LIMB(0x2), CNST_LIMB(0x0) }, + /* 5 */ { 13, CNST_LIMB(0x6e40d1a4), CNST_LIMB(0x4a4d3c25), CNST_LIMB(0x48c27395), CNST_LIMB(0xc25c2684) }, + /* 6 */ { 12, CNST_LIMB(0x6308c91b), CNST_LIMB(0x52b80347), CNST_LIMB(0x81bf1000), CNST_LIMB(0xf91bd1b6) }, + /* 7 */ { 11, CNST_LIMB(0x5b3064eb), CNST_LIMB(0x59d5d9fd), CNST_LIMB(0x75db9c97), CNST_LIMB(0x1607a2cb) }, + /* 8 */ { 10, CNST_LIMB(0x55555555), CNST_LIMB(0x5fffffff), CNST_LIMB(0x3), CNST_LIMB(0x0) }, + /* 9 */ { 10, CNST_LIMB(0x50c24e60), CNST_LIMB(0x6570068e), CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, + /* 10 */ { 9, CNST_LIMB(0x4d104d42), CNST_LIMB(0x6a4d3c25), CNST_LIMB(0x3b9aca00), CNST_LIMB(0x12e0be82) }, + /* 11 */ { 9, CNST_LIMB(0x4a002707), CNST_LIMB(0x6eb3a9f0), CNST_LIMB(0x8c8b6d2b), CNST_LIMB(0xd24cde04) }, + /* 12 */ { 8, CNST_LIMB(0x4768ce0d), CNST_LIMB(0x72b80347), CNST_LIMB(0x19a10000), CNST_LIMB(0x3fa39ab5) }, + /* 13 */ { 8, CNST_LIMB(0x452e53e3), CNST_LIMB(0x766a008e), CNST_LIMB(0x309f1021), CNST_LIMB(0x50f8ac5f) }, + /* 14 */ { 8, CNST_LIMB(0x433cfffb), CNST_LIMB(0x79d5d9fd), CNST_LIMB(0x57f6c100), CNST_LIMB(0x74843b1e) }, + /* 15 */ { 8, CNST_LIMB(0x41867711), CNST_LIMB(0x7d053f6d), CNST_LIMB(0x98c29b81), CNST_LIMB(0xad0326c2) }, + /* 16 */ { 8, CNST_LIMB(0x3fffffff), CNST_LIMB(0x7fffffff), CNST_LIMB(0x4), CNST_LIMB(0x0) }, + /* 17 */ { 7, CNST_LIMB(0x3ea16afd), CNST_LIMB(0x82cc7edf), CNST_LIMB(0x18754571), CNST_LIMB(0x4ef0b6bd) }, + /* 18 */ { 7, CNST_LIMB(0x3d64598d), CNST_LIMB(0x8570068e), CNST_LIMB(0x247dbc80), CNST_LIMB(0xc0fc48a1) }, + /* 19 */ { 7, CNST_LIMB(0x3c43c230), CNST_LIMB(0x87ef05ae), CNST_LIMB(0x3547667b), CNST_LIMB(0x33838942) }, + /* 20 */ { 7, CNST_LIMB(0x3b3b9a42), CNST_LIMB(0x8a4d3c25), CNST_LIMB(0x4c4b4000), CNST_LIMB(0xad7f29ab) }, + /* 21 */ { 7, CNST_LIMB(0x3a4898f0), CNST_LIMB(0x8c8ddd44), CNST_LIMB(0x6b5a6e1d), CNST_LIMB(0x313c3d15) }, + /* 22 */ { 7, CNST_LIMB(0x39680b13), CNST_LIMB(0x8eb3a9f0), CNST_LIMB(0x94ace180), CNST_LIMB(0xb8cca9e0) }, + /* 23 */ { 7, CNST_LIMB(0x3897b2b7), CNST_LIMB(0x90c10500), CNST_LIMB(0xcaf18367), CNST_LIMB(0x42ed6de9) }, + /* 24 */ { 6, CNST_LIMB(0x37d5aed1), CNST_LIMB(0x92b80347), CNST_LIMB(0xb640000), CNST_LIMB(0x67980e0b) }, + /* 25 */ { 6, CNST_LIMB(0x372068d2), CNST_LIMB(0x949a784b), CNST_LIMB(0xe8d4a51), CNST_LIMB(0x19799812) }, + /* 26 */ { 6, CNST_LIMB(0x3676867e), CNST_LIMB(0x966a008e), CNST_LIMB(0x1269ae40), CNST_LIMB(0xbce85396) }, + /* 27 */ { 6, CNST_LIMB(0x35d6deeb), CNST_LIMB(0x982809d5), CNST_LIMB(0x17179149), CNST_LIMB(0x62c103a9) }, + /* 28 */ { 6, CNST_LIMB(0x354071d6), CNST_LIMB(0x99d5d9fd), CNST_LIMB(0x1cb91000), CNST_LIMB(0x1d353d43) }, + /* 29 */ { 6, CNST_LIMB(0x34b260c5), CNST_LIMB(0x9b74948f), CNST_LIMB(0x23744899), CNST_LIMB(0xce1decea) }, + /* 30 */ { 6, CNST_LIMB(0x342be986), CNST_LIMB(0x9d053f6d), CNST_LIMB(0x2b73a840), CNST_LIMB(0x790fc511) }, + /* 31 */ { 6, CNST_LIMB(0x33ac61b9), CNST_LIMB(0x9e88c6b3), CNST_LIMB(0x34e63b41), CNST_LIMB(0x35b865a0) }, + /* 32 */ { 6, CNST_LIMB(0x33333333), CNST_LIMB(0x9fffffff), CNST_LIMB(0x5), CNST_LIMB(0x0) }, + /* 33 */ { 6, CNST_LIMB(0x32bfd901), CNST_LIMB(0xa16bad37), CNST_LIMB(0x4cfa3cc1), CNST_LIMB(0xa9aed1b3) }, + /* 34 */ { 6, CNST_LIMB(0x3251dcf6), CNST_LIMB(0xa2cc7edf), CNST_LIMB(0x5c13d840), CNST_LIMB(0x63dfc229) }, + /* 35 */ { 6, CNST_LIMB(0x31e8d59f), CNST_LIMB(0xa4231623), CNST_LIMB(0x6d91b519), CNST_LIMB(0x2b0fee30) }, + /* 36 */ { 6, CNST_LIMB(0x3184648d), CNST_LIMB(0xa570068e), CNST_LIMB(0x81bf1000), CNST_LIMB(0xf91bd1b6) }, + /* 37 */ { 6, CNST_LIMB(0x312434e8), CNST_LIMB(0xa6b3d78b), CNST_LIMB(0x98ede0c9), CNST_LIMB(0xac89c3a9) }, + /* 38 */ { 6, CNST_LIMB(0x30c7fa34), CNST_LIMB(0xa7ef05ae), CNST_LIMB(0xb3773e40), CNST_LIMB(0x6d2c32fe) }, + /* 39 */ { 6, CNST_LIMB(0x306f6f4c), CNST_LIMB(0xa92203d5), CNST_LIMB(0xd1bbc4d1), CNST_LIMB(0x387907c9) }, + /* 40 */ { 6, CNST_LIMB(0x301a557f), CNST_LIMB(0xaa4d3c25), CNST_LIMB(0xf4240000), CNST_LIMB(0xc6f7a0b) }, + /* 41 */ { 5, CNST_LIMB(0x2fc873d1), CNST_LIMB(0xab7110e6), CNST_LIMB(0x6e7d349), CNST_LIMB(0x28928154) }, + /* 42 */ { 5, CNST_LIMB(0x2f799652), CNST_LIMB(0xac8ddd44), CNST_LIMB(0x7ca30a0), CNST_LIMB(0x6e8629d) }, + /* 43 */ { 5, CNST_LIMB(0x2f2d8d8f), CNST_LIMB(0xada3f5fb), CNST_LIMB(0x8c32bbb), CNST_LIMB(0xd373dca0) }, + /* 44 */ { 5, CNST_LIMB(0x2ee42e16), CNST_LIMB(0xaeb3a9f0), CNST_LIMB(0x9d46c00), CNST_LIMB(0xa0b17895) }, + /* 45 */ { 5, CNST_LIMB(0x2e9d5009), CNST_LIMB(0xafbd42b4), CNST_LIMB(0xaffacfd), CNST_LIMB(0x746811a5) }, + /* 46 */ { 5, CNST_LIMB(0x2e58cec0), CNST_LIMB(0xb0c10500), CNST_LIMB(0xc46bee0), CNST_LIMB(0x4da6500f) }, + /* 47 */ { 5, CNST_LIMB(0x2e168874), CNST_LIMB(0xb1bf311e), CNST_LIMB(0xdab86ef), CNST_LIMB(0x2ba23582) }, + /* 48 */ { 5, CNST_LIMB(0x2dd65df7), CNST_LIMB(0xb2b80347), CNST_LIMB(0xf300000), CNST_LIMB(0xdb20a88) }, + /* 49 */ { 5, CNST_LIMB(0x2d983275), CNST_LIMB(0xb3abb3fa), CNST_LIMB(0x10d63af1), CNST_LIMB(0xe68d5ce4) }, + /* 50 */ { 5, CNST_LIMB(0x2d5beb38), CNST_LIMB(0xb49a784b), CNST_LIMB(0x12a05f20), CNST_LIMB(0xb7cdfd9d) }, + /* 51 */ { 5, CNST_LIMB(0x2d216f79), CNST_LIMB(0xb5848226), CNST_LIMB(0x1490aae3), CNST_LIMB(0x8e583933) }, + /* 52 */ { 5, CNST_LIMB(0x2ce8a82e), CNST_LIMB(0xb66a008e), CNST_LIMB(0x16a97400), CNST_LIMB(0x697cc3ea) }, + /* 53 */ { 5, CNST_LIMB(0x2cb17fea), CNST_LIMB(0xb74b1fd6), CNST_LIMB(0x18ed2825), CNST_LIMB(0x48a5ca6c) }, + /* 54 */ { 5, CNST_LIMB(0x2c7be2b0), CNST_LIMB(0xb82809d5), CNST_LIMB(0x1b5e4d60), CNST_LIMB(0x2b52db16) }, + /* 55 */ { 5, CNST_LIMB(0x2c47bddb), CNST_LIMB(0xb900e615), CNST_LIMB(0x1dff8297), CNST_LIMB(0x111586a6) }, + /* 56 */ { 5, CNST_LIMB(0x2c14fffc), CNST_LIMB(0xb9d5d9fd), CNST_LIMB(0x20d38000), CNST_LIMB(0xf31d2b36) }, + /* 57 */ { 5, CNST_LIMB(0x2be398c3), CNST_LIMB(0xbaa708f5), CNST_LIMB(0x23dd1799), CNST_LIMB(0xc8d76d19) }, + /* 58 */ { 5, CNST_LIMB(0x2bb378e7), CNST_LIMB(0xbb74948f), CNST_LIMB(0x271f35a0), CNST_LIMB(0xa2cb1eb4) }, + /* 59 */ { 5, CNST_LIMB(0x2b849210), CNST_LIMB(0xbc3e9ca2), CNST_LIMB(0x2a9ce10b), CNST_LIMB(0x807c3ec3) }, + /* 60 */ { 5, CNST_LIMB(0x2b56d6c7), CNST_LIMB(0xbd053f6d), CNST_LIMB(0x2e593c00), CNST_LIMB(0x617ec8bf) }, + /* 61 */ { 5, CNST_LIMB(0x2b2a3a60), CNST_LIMB(0xbdc899ab), CNST_LIMB(0x3257844d), CNST_LIMB(0x45746cbe) }, + /* 62 */ { 5, CNST_LIMB(0x2afeb0f1), CNST_LIMB(0xbe88c6b3), CNST_LIMB(0x369b13e0), CNST_LIMB(0x2c0aa273) }, + /* 63 */ { 5, CNST_LIMB(0x2ad42f3c), CNST_LIMB(0xbf45e08b), CNST_LIMB(0x3b27613f), CNST_LIMB(0x14f90805) }, + /* 64 */ { 5, CNST_LIMB(0x2aaaaaaa), CNST_LIMB(0xbfffffff), CNST_LIMB(0x6), CNST_LIMB(0x0) }, + /* 65 */ { 5, CNST_LIMB(0x2a82193a), CNST_LIMB(0xc0b73cb4), CNST_LIMB(0x4528a141), CNST_LIMB(0xd9cf0829) }, + /* 66 */ { 5, CNST_LIMB(0x2a5a7176), CNST_LIMB(0xc16bad37), CNST_LIMB(0x4aa51420), CNST_LIMB(0xb6fc4841) }, + /* 67 */ { 5, CNST_LIMB(0x2a33aa6e), CNST_LIMB(0xc21d6713), CNST_LIMB(0x50794633), CNST_LIMB(0x973054cb) }, + /* 68 */ { 5, CNST_LIMB(0x2a0dbbaa), CNST_LIMB(0xc2cc7edf), CNST_LIMB(0x56a94400), CNST_LIMB(0x7a1dbe4b) }, + /* 69 */ { 5, CNST_LIMB(0x29e89d24), CNST_LIMB(0xc3790848), CNST_LIMB(0x5d393975), CNST_LIMB(0x5f7fcd7f) }, + /* 70 */ { 5, CNST_LIMB(0x29c44740), CNST_LIMB(0xc4231623), CNST_LIMB(0x642d7260), CNST_LIMB(0x47196c84) }, + /* 71 */ { 5, CNST_LIMB(0x29a0b2c7), CNST_LIMB(0xc4caba78), CNST_LIMB(0x6b8a5ae7), CNST_LIMB(0x30b43635) }, + /* 72 */ { 5, CNST_LIMB(0x297dd8db), CNST_LIMB(0xc570068e), CNST_LIMB(0x73548000), CNST_LIMB(0x1c1fa5f6) }, + /* 73 */ { 5, CNST_LIMB(0x295bb2f9), CNST_LIMB(0xc6130af4), CNST_LIMB(0x7b908fe9), CNST_LIMB(0x930634a) }, + /* 74 */ { 5, CNST_LIMB(0x293a3aeb), CNST_LIMB(0xc6b3d78b), CNST_LIMB(0x84435aa0), CNST_LIMB(0xef7f4a3c) }, + /* 75 */ { 5, CNST_LIMB(0x29196acc), CNST_LIMB(0xc7527b93), CNST_LIMB(0x8d71d25b), CNST_LIMB(0xcf5552d2) }, + /* 76 */ { 5, CNST_LIMB(0x28f93cfb), CNST_LIMB(0xc7ef05ae), CNST_LIMB(0x97210c00), CNST_LIMB(0xb1a47c8e) }, + /* 77 */ { 5, CNST_LIMB(0x28d9ac1b), CNST_LIMB(0xc88983ed), CNST_LIMB(0xa1563f9d), CNST_LIMB(0x9634b43e) }, + /* 78 */ { 5, CNST_LIMB(0x28bab310), CNST_LIMB(0xc92203d5), CNST_LIMB(0xac16c8e0), CNST_LIMB(0x7cd3817d) }, + /* 79 */ { 5, CNST_LIMB(0x289c4cf8), CNST_LIMB(0xc9b89267), CNST_LIMB(0xb768278f), CNST_LIMB(0x65536761) }, + /* 80 */ { 5, CNST_LIMB(0x287e7529), CNST_LIMB(0xca4d3c25), CNST_LIMB(0xc3500000), CNST_LIMB(0x4f8b588e) }, + /* 81 */ { 5, CNST_LIMB(0x28612730), CNST_LIMB(0xcae00d1c), CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, + /* 82 */ { 5, CNST_LIMB(0x28445ec9), CNST_LIMB(0xcb7110e6), CNST_LIMB(0xdcfa6920), CNST_LIMB(0x28928154) }, + /* 83 */ { 5, CNST_LIMB(0x282817e1), CNST_LIMB(0xcc0052b1), CNST_LIMB(0xeac8fd83), CNST_LIMB(0x1721bfb0) }, + /* 84 */ { 5, CNST_LIMB(0x280c4e90), CNST_LIMB(0xcc8ddd44), CNST_LIMB(0xf9461400), CNST_LIMB(0x6e8629d) }, + /* 85 */ { 4, CNST_LIMB(0x27f0ff1b), CNST_LIMB(0xcd19bb05), CNST_LIMB(0x31c84b1), CNST_LIMB(0x491cc17c) }, + /* 86 */ { 4, CNST_LIMB(0x27d625ec), CNST_LIMB(0xcda3f5fb), CNST_LIMB(0x342ab10), CNST_LIMB(0x3a11d83b) }, + /* 87 */ { 4, CNST_LIMB(0x27bbbf95), CNST_LIMB(0xce2c97d6), CNST_LIMB(0x36a2c21), CNST_LIMB(0x2be074cd) }, + /* 88 */ { 4, CNST_LIMB(0x27a1c8c8), CNST_LIMB(0xceb3a9f0), CNST_LIMB(0x3931000), CNST_LIMB(0x1e7a02e7) }, + /* 89 */ { 4, CNST_LIMB(0x27883e5e), CNST_LIMB(0xcf393550), CNST_LIMB(0x3bd5ee1), CNST_LIMB(0x11d10edd) }, + /* 90 */ { 4, CNST_LIMB(0x276f1d4c), CNST_LIMB(0xcfbd42b4), CNST_LIMB(0x3e92110), CNST_LIMB(0x5d92c68) }, + /* 91 */ { 4, CNST_LIMB(0x275662a8), CNST_LIMB(0xd03fda8b), CNST_LIMB(0x4165ef1), CNST_LIMB(0xf50dbfb2) }, + /* 92 */ { 4, CNST_LIMB(0x273e0ba3), CNST_LIMB(0xd0c10500), CNST_LIMB(0x4452100), CNST_LIMB(0xdf9f1316) }, + /* 93 */ { 4, CNST_LIMB(0x2726158c), CNST_LIMB(0xd140c9fa), CNST_LIMB(0x4756fd1), CNST_LIMB(0xcb52a684) }, + /* 94 */ { 4, CNST_LIMB(0x270e7dc9), CNST_LIMB(0xd1bf311e), CNST_LIMB(0x4a75410), CNST_LIMB(0xb8163e97) }, + /* 95 */ { 4, CNST_LIMB(0x26f741dd), CNST_LIMB(0xd23c41d4), CNST_LIMB(0x4dad681), CNST_LIMB(0xa5d8f269) }, + /* 96 */ { 4, CNST_LIMB(0x26e05f5f), CNST_LIMB(0xd2b80347), CNST_LIMB(0x5100000), CNST_LIMB(0x948b0fcd) }, + /* 97 */ { 4, CNST_LIMB(0x26c9d3fe), CNST_LIMB(0xd3327c6a), CNST_LIMB(0x546d981), CNST_LIMB(0x841e0215) }, + /* 98 */ { 4, CNST_LIMB(0x26b39d7f), CNST_LIMB(0xd3abb3fa), CNST_LIMB(0x57f6c10), CNST_LIMB(0x74843b1e) }, + /* 99 */ { 4, CNST_LIMB(0x269db9bc), CNST_LIMB(0xd423b07e), CNST_LIMB(0x5b9c0d1), CNST_LIMB(0x65b11e6e) }, + /* 100 */ { 4, CNST_LIMB(0x268826a1), CNST_LIMB(0xd49a784b), CNST_LIMB(0x5f5e100), CNST_LIMB(0x5798ee23) }, + /* 101 */ { 4, CNST_LIMB(0x2672e22d), CNST_LIMB(0xd5101187), CNST_LIMB(0x633d5f1), CNST_LIMB(0x4a30b99b) }, + /* 102 */ { 4, CNST_LIMB(0x265dea72), CNST_LIMB(0xd5848226), CNST_LIMB(0x673a910), CNST_LIMB(0x3d6e4d94) }, + /* 103 */ { 4, CNST_LIMB(0x26493d93), CNST_LIMB(0xd5f7cff4), CNST_LIMB(0x6b563e1), CNST_LIMB(0x314825b0) }, + /* 104 */ { 4, CNST_LIMB(0x2634d9c2), CNST_LIMB(0xd66a008e), CNST_LIMB(0x6f91000), CNST_LIMB(0x25b55f2e) }, + /* 105 */ { 4, CNST_LIMB(0x2620bd41), CNST_LIMB(0xd6db196a), CNST_LIMB(0x73eb721), CNST_LIMB(0x1aadaccb) }, + /* 106 */ { 4, CNST_LIMB(0x260ce662), CNST_LIMB(0xd74b1fd6), CNST_LIMB(0x7866310), CNST_LIMB(0x10294ba2) }, + /* 107 */ { 4, CNST_LIMB(0x25f95385), CNST_LIMB(0xd7ba18f9), CNST_LIMB(0x7d01db1), CNST_LIMB(0x620f8f6) }, + /* 108 */ { 4, CNST_LIMB(0x25e60316), CNST_LIMB(0xd82809d5), CNST_LIMB(0x81bf100), CNST_LIMB(0xf91bd1b6) }, + /* 109 */ { 4, CNST_LIMB(0x25d2f390), CNST_LIMB(0xd894f74b), CNST_LIMB(0x869e711), CNST_LIMB(0xe6d37b2a) }, + /* 110 */ { 4, CNST_LIMB(0x25c02379), CNST_LIMB(0xd900e615), CNST_LIMB(0x8ba0a10), CNST_LIMB(0xd55cff6e) }, + /* 111 */ { 4, CNST_LIMB(0x25ad9165), CNST_LIMB(0xd96bdad2), CNST_LIMB(0x90c6441), CNST_LIMB(0xc4ad2db2) }, + /* 112 */ { 4, CNST_LIMB(0x259b3bf3), CNST_LIMB(0xd9d5d9fd), CNST_LIMB(0x9610000), CNST_LIMB(0xb4b985cf) }, + /* 113 */ { 4, CNST_LIMB(0x258921cb), CNST_LIMB(0xda3ee7f3), CNST_LIMB(0x9b7e7c1), CNST_LIMB(0xa5782bef) }, + /* 114 */ { 4, CNST_LIMB(0x257741a2), CNST_LIMB(0xdaa708f5), CNST_LIMB(0xa112610), CNST_LIMB(0x96dfdd2a) }, + /* 115 */ { 4, CNST_LIMB(0x25659a37), CNST_LIMB(0xdb0e4126), CNST_LIMB(0xa6cc591), CNST_LIMB(0x88e7e509) }, + /* 116 */ { 4, CNST_LIMB(0x25542a50), CNST_LIMB(0xdb74948f), CNST_LIMB(0xacad100), CNST_LIMB(0x7b8813d3) }, + /* 117 */ { 4, CNST_LIMB(0x2542f0c2), CNST_LIMB(0xdbda071c), CNST_LIMB(0xb2b5331), CNST_LIMB(0x6eb8b595) }, + /* 118 */ { 4, CNST_LIMB(0x2531ec64), CNST_LIMB(0xdc3e9ca2), CNST_LIMB(0xb8e5710), CNST_LIMB(0x627289db) }, + /* 119 */ { 4, CNST_LIMB(0x25211c1c), CNST_LIMB(0xdca258dc), CNST_LIMB(0xbf3e7a1), CNST_LIMB(0x56aebc07) }, + /* 120 */ { 4, CNST_LIMB(0x25107ed5), CNST_LIMB(0xdd053f6d), CNST_LIMB(0xc5c1000), CNST_LIMB(0x4b66dc33) }, + /* 121 */ { 4, CNST_LIMB(0x25001383), CNST_LIMB(0xdd6753e0), CNST_LIMB(0xcc6db61), CNST_LIMB(0x4094d8a3) }, + /* 122 */ { 4, CNST_LIMB(0x24efd921), CNST_LIMB(0xddc899ab), CNST_LIMB(0xd345510), CNST_LIMB(0x3632f7a5) }, + /* 123 */ { 4, CNST_LIMB(0x24dfceb3), CNST_LIMB(0xde29142e), CNST_LIMB(0xda48871), CNST_LIMB(0x2c3bd1f0) }, + /* 124 */ { 4, CNST_LIMB(0x24cff343), CNST_LIMB(0xde88c6b3), CNST_LIMB(0xe178100), CNST_LIMB(0x22aa4d5f) }, + /* 125 */ { 4, CNST_LIMB(0x24c045e1), CNST_LIMB(0xdee7b471), CNST_LIMB(0xe8d4a51), CNST_LIMB(0x19799812) }, + /* 126 */ { 4, CNST_LIMB(0x24b0c5a6), CNST_LIMB(0xdf45e08b), CNST_LIMB(0xf05f010), CNST_LIMB(0x10a523e5) }, + /* 127 */ { 4, CNST_LIMB(0x24a171b0), CNST_LIMB(0xdfa34e11), CNST_LIMB(0xf817e01), CNST_LIMB(0x828a237) }, + /* 128 */ { 4, CNST_LIMB(0x24924924), CNST_LIMB(0xdfffffff), CNST_LIMB(0x7), CNST_LIMB(0x0) }, + /* 129 */ { 4, CNST_LIMB(0x24834b2c), CNST_LIMB(0xe05bf942), CNST_LIMB(0x10818201), CNST_LIMB(0xf04ec452) }, + /* 130 */ { 4, CNST_LIMB(0x247476f9), CNST_LIMB(0xe0b73cb4), CNST_LIMB(0x11061010), CNST_LIMB(0xe136444a) }, + /* 131 */ { 4, CNST_LIMB(0x2465cbc0), CNST_LIMB(0xe111cd1d), CNST_LIMB(0x118db651), CNST_LIMB(0xd2af9589) }, + /* 132 */ { 4, CNST_LIMB(0x245748bc), CNST_LIMB(0xe16bad37), CNST_LIMB(0x12188100), CNST_LIMB(0xc4b42a83) }, + /* 133 */ { 4, CNST_LIMB(0x2448ed2f), CNST_LIMB(0xe1c4dfab), CNST_LIMB(0x12a67c71), CNST_LIMB(0xb73dccf5) }, + /* 134 */ { 4, CNST_LIMB(0x243ab85d), CNST_LIMB(0xe21d6713), CNST_LIMB(0x1337b510), CNST_LIMB(0xaa4698c5) }, + /* 135 */ { 4, CNST_LIMB(0x242ca992), CNST_LIMB(0xe27545fb), CNST_LIMB(0x13cc3761), CNST_LIMB(0x9dc8f729) }, + /* 136 */ { 4, CNST_LIMB(0x241ec01b), CNST_LIMB(0xe2cc7edf), CNST_LIMB(0x14641000), CNST_LIMB(0x91bf9a30) }, + /* 137 */ { 4, CNST_LIMB(0x2410fb4d), CNST_LIMB(0xe323142d), CNST_LIMB(0x14ff4ba1), CNST_LIMB(0x86257887) }, + /* 138 */ { 4, CNST_LIMB(0x24035a80), CNST_LIMB(0xe3790848), CNST_LIMB(0x159df710), CNST_LIMB(0x7af5c98c) }, + /* 139 */ { 4, CNST_LIMB(0x23f5dd10), CNST_LIMB(0xe3ce5d82), CNST_LIMB(0x16401f31), CNST_LIMB(0x702c01a0) }, + /* 140 */ { 4, CNST_LIMB(0x23e8825d), CNST_LIMB(0xe4231623), CNST_LIMB(0x16e5d100), CNST_LIMB(0x65c3ceb1) }, + /* 141 */ { 4, CNST_LIMB(0x23db49cc), CNST_LIMB(0xe4773465), CNST_LIMB(0x178f1991), CNST_LIMB(0x5bb91502) }, + /* 142 */ { 4, CNST_LIMB(0x23ce32c4), CNST_LIMB(0xe4caba78), CNST_LIMB(0x183c0610), CNST_LIMB(0x5207ec23) }, + /* 143 */ { 4, CNST_LIMB(0x23c13cb3), CNST_LIMB(0xe51daa7e), CNST_LIMB(0x18eca3c1), CNST_LIMB(0x48ac9c19) }, + /* 144 */ { 4, CNST_LIMB(0x23b46706), CNST_LIMB(0xe570068e), CNST_LIMB(0x19a10000), CNST_LIMB(0x3fa39ab5) }, + /* 145 */ { 4, CNST_LIMB(0x23a7b132), CNST_LIMB(0xe5c1d0b5), CNST_LIMB(0x1a592841), CNST_LIMB(0x36e98912) }, + /* 146 */ { 4, CNST_LIMB(0x239b1aac), CNST_LIMB(0xe6130af4), CNST_LIMB(0x1b152a10), CNST_LIMB(0x2e7b3140) }, + /* 147 */ { 4, CNST_LIMB(0x238ea2ef), CNST_LIMB(0xe663b741), CNST_LIMB(0x1bd51311), CNST_LIMB(0x2655840b) }, + /* 148 */ { 4, CNST_LIMB(0x23824976), CNST_LIMB(0xe6b3d78b), CNST_LIMB(0x1c98f100), CNST_LIMB(0x1e7596ea) }, + /* 149 */ { 4, CNST_LIMB(0x23760dc3), CNST_LIMB(0xe7036db3), CNST_LIMB(0x1d60d1b1), CNST_LIMB(0x16d8a20d) }, + /* 150 */ { 4, CNST_LIMB(0x2369ef58), CNST_LIMB(0xe7527b93), CNST_LIMB(0x1e2cc310), CNST_LIMB(0xf7bfe87) }, + /* 151 */ { 4, CNST_LIMB(0x235dedbb), CNST_LIMB(0xe7a102f9), CNST_LIMB(0x1efcd321), CNST_LIMB(0x85d2492) }, + /* 152 */ { 4, CNST_LIMB(0x23520874), CNST_LIMB(0xe7ef05ae), CNST_LIMB(0x1fd11000), CNST_LIMB(0x179a9f4) }, + /* 153 */ { 4, CNST_LIMB(0x23463f10), CNST_LIMB(0xe83c856d), CNST_LIMB(0x20a987e1), CNST_LIMB(0xf59e80eb) }, + /* 154 */ { 4, CNST_LIMB(0x233a911b), CNST_LIMB(0xe88983ed), CNST_LIMB(0x21864910), CNST_LIMB(0xe8b768db) }, + /* 155 */ { 4, CNST_LIMB(0x232efe26), CNST_LIMB(0xe8d602d9), CNST_LIMB(0x226761f1), CNST_LIMB(0xdc39d6d5) }, + /* 156 */ { 4, CNST_LIMB(0x232385c6), CNST_LIMB(0xe92203d5), CNST_LIMB(0x234ce100), CNST_LIMB(0xd021c5d1) }, + /* 157 */ { 4, CNST_LIMB(0x2318278e), CNST_LIMB(0xe96d887e), CNST_LIMB(0x2436d4d1), CNST_LIMB(0xc46b5e37) }, + /* 158 */ { 4, CNST_LIMB(0x230ce318), CNST_LIMB(0xe9b89267), CNST_LIMB(0x25254c10), CNST_LIMB(0xb912f39c) }, + /* 159 */ { 4, CNST_LIMB(0x2301b7fd), CNST_LIMB(0xea03231d), CNST_LIMB(0x26185581), CNST_LIMB(0xae150294) }, + /* 160 */ { 4, CNST_LIMB(0x22f6a5d9), CNST_LIMB(0xea4d3c25), CNST_LIMB(0x27100000), CNST_LIMB(0xa36e2eb1) }, + /* 161 */ { 4, CNST_LIMB(0x22ebac4c), CNST_LIMB(0xea96defe), CNST_LIMB(0x280c5a81), CNST_LIMB(0x991b4094) }, + /* 162 */ { 4, CNST_LIMB(0x22e0caf6), CNST_LIMB(0xeae00d1c), CNST_LIMB(0x290d7410), CNST_LIMB(0x8f19241e) }, + /* 163 */ { 4, CNST_LIMB(0x22d60179), CNST_LIMB(0xeb28c7f2), CNST_LIMB(0x2a135bd1), CNST_LIMB(0x8564e6b7) }, + /* 164 */ { 4, CNST_LIMB(0x22cb4f7a), CNST_LIMB(0xeb7110e6), CNST_LIMB(0x2b1e2100), CNST_LIMB(0x7bfbb5b4) }, + /* 165 */ { 4, CNST_LIMB(0x22c0b4a1), CNST_LIMB(0xebb8e95d), CNST_LIMB(0x2c2dd2f1), CNST_LIMB(0x72dadcc8) }, + /* 166 */ { 4, CNST_LIMB(0x22b63095), CNST_LIMB(0xec0052b1), CNST_LIMB(0x2d428110), CNST_LIMB(0x69ffc498) }, + /* 167 */ { 4, CNST_LIMB(0x22abc300), CNST_LIMB(0xec474e39), CNST_LIMB(0x2e5c3ae1), CNST_LIMB(0x6167f154) }, + /* 168 */ { 4, CNST_LIMB(0x22a16b90), CNST_LIMB(0xec8ddd44), CNST_LIMB(0x2f7b1000), CNST_LIMB(0x5911016e) }, + /* 169 */ { 4, CNST_LIMB(0x229729f1), CNST_LIMB(0xecd4011c), CNST_LIMB(0x309f1021), CNST_LIMB(0x50f8ac5f) }, + /* 170 */ { 4, CNST_LIMB(0x228cfdd4), CNST_LIMB(0xed19bb05), CNST_LIMB(0x31c84b10), CNST_LIMB(0x491cc17c) }, + /* 171 */ { 4, CNST_LIMB(0x2282e6e9), CNST_LIMB(0xed5f0c3c), CNST_LIMB(0x32f6d0b1), CNST_LIMB(0x417b26d8) }, + /* 172 */ { 4, CNST_LIMB(0x2278e4e3), CNST_LIMB(0xeda3f5fb), CNST_LIMB(0x342ab100), CNST_LIMB(0x3a11d83b) }, + /* 173 */ { 4, CNST_LIMB(0x226ef777), CNST_LIMB(0xede87974), CNST_LIMB(0x3563fc11), CNST_LIMB(0x32dee622) }, + /* 174 */ { 4, CNST_LIMB(0x22651e5a), CNST_LIMB(0xee2c97d6), CNST_LIMB(0x36a2c210), CNST_LIMB(0x2be074cd) }, + /* 175 */ { 4, CNST_LIMB(0x225b5944), CNST_LIMB(0xee705249), CNST_LIMB(0x37e71341), CNST_LIMB(0x2514bb58) }, + /* 176 */ { 4, CNST_LIMB(0x2251a7ee), CNST_LIMB(0xeeb3a9f0), CNST_LIMB(0x39310000), CNST_LIMB(0x1e7a02e7) }, + /* 177 */ { 4, CNST_LIMB(0x22480a11), CNST_LIMB(0xeef69fea), CNST_LIMB(0x3a8098c1), CNST_LIMB(0x180ea5d0) }, + /* 178 */ { 4, CNST_LIMB(0x223e7f69), CNST_LIMB(0xef393550), CNST_LIMB(0x3bd5ee10), CNST_LIMB(0x11d10edd) }, + /* 179 */ { 4, CNST_LIMB(0x223507b4), CNST_LIMB(0xef7b6b39), CNST_LIMB(0x3d311091), CNST_LIMB(0xbbfb88e) }, + /* 180 */ { 4, CNST_LIMB(0x222ba2af), CNST_LIMB(0xefbd42b4), CNST_LIMB(0x3e921100), CNST_LIMB(0x5d92c68) }, + /* 181 */ { 4, CNST_LIMB(0x22225019), CNST_LIMB(0xeffebccd), CNST_LIMB(0x3ff90031), CNST_LIMB(0x1c024c) }, + /* 182 */ { 4, CNST_LIMB(0x22190fb4), CNST_LIMB(0xf03fda8b), CNST_LIMB(0x4165ef10), CNST_LIMB(0xf50dbfb2) }, + /* 183 */ { 4, CNST_LIMB(0x220fe141), CNST_LIMB(0xf0809cf2), CNST_LIMB(0x42d8eea1), CNST_LIMB(0xea30efa3) }, + /* 184 */ { 4, CNST_LIMB(0x2206c483), CNST_LIMB(0xf0c10500), CNST_LIMB(0x44521000), CNST_LIMB(0xdf9f1316) }, + /* 185 */ { 4, CNST_LIMB(0x21fdb93f), CNST_LIMB(0xf10113b1), CNST_LIMB(0x45d16461), CNST_LIMB(0xd555c0c9) }, + /* 186 */ { 4, CNST_LIMB(0x21f4bf3a), CNST_LIMB(0xf140c9fa), CNST_LIMB(0x4756fd10), CNST_LIMB(0xcb52a684) }, + /* 187 */ { 4, CNST_LIMB(0x21ebd639), CNST_LIMB(0xf18028cf), CNST_LIMB(0x48e2eb71), CNST_LIMB(0xc193881f) }, + /* 188 */ { 4, CNST_LIMB(0x21e2fe06), CNST_LIMB(0xf1bf311e), CNST_LIMB(0x4a754100), CNST_LIMB(0xb8163e97) }, + /* 189 */ { 4, CNST_LIMB(0x21da3667), CNST_LIMB(0xf1fde3d3), CNST_LIMB(0x4c0e0f51), CNST_LIMB(0xaed8b724) }, + /* 190 */ { 4, CNST_LIMB(0x21d17f28), CNST_LIMB(0xf23c41d4), CNST_LIMB(0x4dad6810), CNST_LIMB(0xa5d8f269) }, + /* 191 */ { 4, CNST_LIMB(0x21c8d811), CNST_LIMB(0xf27a4c05), CNST_LIMB(0x4f535d01), CNST_LIMB(0x9d15039d) }, + /* 192 */ { 4, CNST_LIMB(0x21c040ef), CNST_LIMB(0xf2b80347), CNST_LIMB(0x51000000), CNST_LIMB(0x948b0fcd) }, + /* 193 */ { 4, CNST_LIMB(0x21b7b98f), CNST_LIMB(0xf2f56875), CNST_LIMB(0x52b36301), CNST_LIMB(0x8c394d1d) }, + /* 194 */ { 4, CNST_LIMB(0x21af41bc), CNST_LIMB(0xf3327c6a), CNST_LIMB(0x546d9810), CNST_LIMB(0x841e0215) }, + /* 195 */ { 4, CNST_LIMB(0x21a6d947), CNST_LIMB(0xf36f3ffb), CNST_LIMB(0x562eb151), CNST_LIMB(0x7c3784f8) }, + /* 196 */ { 4, CNST_LIMB(0x219e7ffd), CNST_LIMB(0xf3abb3fa), CNST_LIMB(0x57f6c100), CNST_LIMB(0x74843b1e) }, + /* 197 */ { 4, CNST_LIMB(0x219635af), CNST_LIMB(0xf3e7d937), CNST_LIMB(0x59c5d971), CNST_LIMB(0x6d02985d) }, + /* 198 */ { 4, CNST_LIMB(0x218dfa2e), CNST_LIMB(0xf423b07e), CNST_LIMB(0x5b9c0d10), CNST_LIMB(0x65b11e6e) }, + /* 199 */ { 4, CNST_LIMB(0x2185cd4c), CNST_LIMB(0xf45f3a98), CNST_LIMB(0x5d796e61), CNST_LIMB(0x5e8e5c64) }, + /* 200 */ { 4, CNST_LIMB(0x217daeda), CNST_LIMB(0xf49a784b), CNST_LIMB(0x5f5e1000), CNST_LIMB(0x5798ee23) }, + /* 201 */ { 4, CNST_LIMB(0x21759eac), CNST_LIMB(0xf4d56a5b), CNST_LIMB(0x614a04a1), CNST_LIMB(0x50cf7bde) }, + /* 202 */ { 4, CNST_LIMB(0x216d9c96), CNST_LIMB(0xf5101187), CNST_LIMB(0x633d5f10), CNST_LIMB(0x4a30b99b) }, + /* 203 */ { 4, CNST_LIMB(0x2165a86e), CNST_LIMB(0xf54a6e8c), CNST_LIMB(0x65383231), CNST_LIMB(0x43bb66bd) }, + /* 204 */ { 4, CNST_LIMB(0x215dc207), CNST_LIMB(0xf5848226), CNST_LIMB(0x673a9100), CNST_LIMB(0x3d6e4d94) }, + /* 205 */ { 4, CNST_LIMB(0x2155e939), CNST_LIMB(0xf5be4d0c), CNST_LIMB(0x69448e91), CNST_LIMB(0x374842ee) }, + /* 206 */ { 4, CNST_LIMB(0x214e1ddb), CNST_LIMB(0xf5f7cff4), CNST_LIMB(0x6b563e10), CNST_LIMB(0x314825b0) }, + /* 207 */ { 4, CNST_LIMB(0x21465fc4), CNST_LIMB(0xf6310b8f), CNST_LIMB(0x6d6fb2c1), CNST_LIMB(0x2b6cde75) }, + /* 208 */ { 4, CNST_LIMB(0x213eaecd), CNST_LIMB(0xf66a008e), CNST_LIMB(0x6f910000), CNST_LIMB(0x25b55f2e) }, + /* 209 */ { 4, CNST_LIMB(0x21370ace), CNST_LIMB(0xf6a2af9e), CNST_LIMB(0x71ba3941), CNST_LIMB(0x2020a2c5) }, + /* 210 */ { 4, CNST_LIMB(0x212f73a0), CNST_LIMB(0xf6db196a), CNST_LIMB(0x73eb7210), CNST_LIMB(0x1aadaccb) }, + /* 211 */ { 4, CNST_LIMB(0x2127e920), CNST_LIMB(0xf7133e9b), CNST_LIMB(0x7624be11), CNST_LIMB(0x155b891f) }, + /* 212 */ { 4, CNST_LIMB(0x21206b26), CNST_LIMB(0xf74b1fd6), CNST_LIMB(0x78663100), CNST_LIMB(0x10294ba2) }, + /* 213 */ { 4, CNST_LIMB(0x2118f98f), CNST_LIMB(0xf782bdbf), CNST_LIMB(0x7aafdeb1), CNST_LIMB(0xb160fe9) }, + /* 214 */ { 4, CNST_LIMB(0x21119436), CNST_LIMB(0xf7ba18f9), CNST_LIMB(0x7d01db10), CNST_LIMB(0x620f8f6) }, + /* 215 */ { 4, CNST_LIMB(0x210a3af8), CNST_LIMB(0xf7f13221), CNST_LIMB(0x7f5c3a21), CNST_LIMB(0x14930ef) }, + /* 216 */ { 4, CNST_LIMB(0x2102edb3), CNST_LIMB(0xf82809d5), CNST_LIMB(0x81bf1000), CNST_LIMB(0xf91bd1b6) }, + /* 217 */ { 4, CNST_LIMB(0x20fbac44), CNST_LIMB(0xf85ea0b0), CNST_LIMB(0x842a70e1), CNST_LIMB(0xefdcb0c7) }, + /* 218 */ { 4, CNST_LIMB(0x20f4768a), CNST_LIMB(0xf894f74b), CNST_LIMB(0x869e7110), CNST_LIMB(0xe6d37b2a) }, + /* 219 */ { 4, CNST_LIMB(0x20ed4c62), CNST_LIMB(0xf8cb0e3b), CNST_LIMB(0x891b24f1), CNST_LIMB(0xddfeb94a) }, + /* 220 */ { 4, CNST_LIMB(0x20e62dae), CNST_LIMB(0xf900e615), CNST_LIMB(0x8ba0a100), CNST_LIMB(0xd55cff6e) }, + /* 221 */ { 4, CNST_LIMB(0x20df1a4b), CNST_LIMB(0xf9367f6d), CNST_LIMB(0x8e2ef9d1), CNST_LIMB(0xcceced50) }, + /* 222 */ { 4, CNST_LIMB(0x20d8121c), CNST_LIMB(0xf96bdad2), CNST_LIMB(0x90c64410), CNST_LIMB(0xc4ad2db2) }, + /* 223 */ { 4, CNST_LIMB(0x20d11500), CNST_LIMB(0xf9a0f8d3), CNST_LIMB(0x93669481), CNST_LIMB(0xbc9c75f9) }, + /* 224 */ { 4, CNST_LIMB(0x20ca22d9), CNST_LIMB(0xf9d5d9fd), CNST_LIMB(0x96100000), CNST_LIMB(0xb4b985cf) }, + /* 225 */ { 4, CNST_LIMB(0x20c33b88), CNST_LIMB(0xfa0a7eda), CNST_LIMB(0x98c29b81), CNST_LIMB(0xad0326c2) }, + /* 226 */ { 4, CNST_LIMB(0x20bc5ef1), CNST_LIMB(0xfa3ee7f3), CNST_LIMB(0x9b7e7c10), CNST_LIMB(0xa5782bef) }, + /* 227 */ { 4, CNST_LIMB(0x20b58cf5), CNST_LIMB(0xfa7315d0), CNST_LIMB(0x9e43b6d1), CNST_LIMB(0x9e1771a9) }, + /* 228 */ { 4, CNST_LIMB(0x20aec579), CNST_LIMB(0xfaa708f5), CNST_LIMB(0xa1126100), CNST_LIMB(0x96dfdd2a) }, + /* 229 */ { 4, CNST_LIMB(0x20a8085e), CNST_LIMB(0xfadac1e7), CNST_LIMB(0xa3ea8ff1), CNST_LIMB(0x8fd05c41) }, + /* 230 */ { 4, CNST_LIMB(0x20a1558b), CNST_LIMB(0xfb0e4126), CNST_LIMB(0xa6cc5910), CNST_LIMB(0x88e7e509) }, + /* 231 */ { 4, CNST_LIMB(0x209aace2), CNST_LIMB(0xfb418734), CNST_LIMB(0xa9b7d1e1), CNST_LIMB(0x8225759d) }, + /* 232 */ { 4, CNST_LIMB(0x20940e49), CNST_LIMB(0xfb74948f), CNST_LIMB(0xacad1000), CNST_LIMB(0x7b8813d3) }, + /* 233 */ { 4, CNST_LIMB(0x208d79a5), CNST_LIMB(0xfba769b3), CNST_LIMB(0xafac2921), CNST_LIMB(0x750eccf9) }, + /* 234 */ { 4, CNST_LIMB(0x2086eedb), CNST_LIMB(0xfbda071c), CNST_LIMB(0xb2b53310), CNST_LIMB(0x6eb8b595) }, + /* 235 */ { 4, CNST_LIMB(0x20806dd2), CNST_LIMB(0xfc0c6d44), CNST_LIMB(0xb5c843b1), CNST_LIMB(0x6884e923) }, + /* 236 */ { 4, CNST_LIMB(0x2079f671), CNST_LIMB(0xfc3e9ca2), CNST_LIMB(0xb8e57100), CNST_LIMB(0x627289db) }, + /* 237 */ { 4, CNST_LIMB(0x2073889d), CNST_LIMB(0xfc7095ae), CNST_LIMB(0xbc0cd111), CNST_LIMB(0x5c80c07b) }, + /* 238 */ { 4, CNST_LIMB(0x206d243e), CNST_LIMB(0xfca258dc), CNST_LIMB(0xbf3e7a10), CNST_LIMB(0x56aebc07) }, + /* 239 */ { 4, CNST_LIMB(0x2066c93c), CNST_LIMB(0xfcd3e6a0), CNST_LIMB(0xc27a8241), CNST_LIMB(0x50fbb19b) }, + /* 240 */ { 4, CNST_LIMB(0x2060777e), CNST_LIMB(0xfd053f6d), CNST_LIMB(0xc5c10000), CNST_LIMB(0x4b66dc33) }, + /* 241 */ { 4, CNST_LIMB(0x205a2eed), CNST_LIMB(0xfd3663b2), CNST_LIMB(0xc91209c1), CNST_LIMB(0x45ef7c7c) }, + /* 242 */ { 4, CNST_LIMB(0x2053ef71), CNST_LIMB(0xfd6753e0), CNST_LIMB(0xcc6db610), CNST_LIMB(0x4094d8a3) }, + /* 243 */ { 4, CNST_LIMB(0x204db8f3), CNST_LIMB(0xfd981064), CNST_LIMB(0xcfd41b91), CNST_LIMB(0x3b563c24) }, + /* 244 */ { 4, CNST_LIMB(0x20478b5c), CNST_LIMB(0xfdc899ab), CNST_LIMB(0xd3455100), CNST_LIMB(0x3632f7a5) }, + /* 245 */ { 4, CNST_LIMB(0x20416696), CNST_LIMB(0xfdf8f020), CNST_LIMB(0xd6c16d31), CNST_LIMB(0x312a60c3) }, + /* 246 */ { 4, CNST_LIMB(0x203b4a8b), CNST_LIMB(0xfe29142e), CNST_LIMB(0xda488710), CNST_LIMB(0x2c3bd1f0) }, + /* 247 */ { 4, CNST_LIMB(0x20353725), CNST_LIMB(0xfe59063c), CNST_LIMB(0xdddab5a1), CNST_LIMB(0x2766aa45) }, + /* 248 */ { 4, CNST_LIMB(0x202f2c4e), CNST_LIMB(0xfe88c6b3), CNST_LIMB(0xe1781000), CNST_LIMB(0x22aa4d5f) }, + /* 249 */ { 4, CNST_LIMB(0x202929f0), CNST_LIMB(0xfeb855f8), CNST_LIMB(0xe520ad61), CNST_LIMB(0x1e06233c) }, + /* 250 */ { 4, CNST_LIMB(0x20232ff8), CNST_LIMB(0xfee7b471), CNST_LIMB(0xe8d4a510), CNST_LIMB(0x19799812) }, + /* 251 */ { 4, CNST_LIMB(0x201d3e50), CNST_LIMB(0xff16e281), CNST_LIMB(0xec940e71), CNST_LIMB(0x15041c33) }, + /* 252 */ { 4, CNST_LIMB(0x201754e5), CNST_LIMB(0xff45e08b), CNST_LIMB(0xf05f0100), CNST_LIMB(0x10a523e5) }, + /* 253 */ { 4, CNST_LIMB(0x201173a1), CNST_LIMB(0xff74aef0), CNST_LIMB(0xf4359451), CNST_LIMB(0xc5c2749) }, + /* 254 */ { 4, CNST_LIMB(0x200b9a71), CNST_LIMB(0xffa34e11), CNST_LIMB(0xf817e010), CNST_LIMB(0x828a237) }, + /* 255 */ { 4, CNST_LIMB(0x2005c942), CNST_LIMB(0xffd1be4c), CNST_LIMB(0xfc05fc01), CNST_LIMB(0x40a1423) }, + /* 256 */ { 4, CNST_LIMB(0x1fffffff), CNST_LIMB(0xffffffff), CNST_LIMB(0x8), CNST_LIMB(0x0) }, }; diff --git a/repos/libports/src/lib/gmp/mpn/spec/64bit/mp_bases.c b/repos/libports/src/lib/gmp/mpn/spec/64bit/mp_bases.c index 95bf6db6a..a5e79be6b 100644 --- a/repos/libports/src/lib/gmp/mpn/spec/64bit/mp_bases.c +++ b/repos/libports/src/lib/gmp/mpn/spec/64bit/mp_bases.c @@ -9,261 +9,261 @@ Error, error, this data is for 64 bits const struct bases mp_bases[257] = { - /* 0 */ { 0, 0.0, 0 }, - /* 1 */ { 0, 1e37, 0 }, - /* 2 */ { 64, 1.0000000000000000, 0x1 }, - /* 3 */ { 40, 0.6309297535714574, CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, - /* 4 */ { 32, 0.5000000000000000, 0x2 }, - /* 5 */ { 27, 0.4306765580733931, CNST_LIMB(0x6765c793fa10079d), CNST_LIMB(0x3ce9a36f23c0fc90) }, - /* 6 */ { 24, 0.3868528072345416, CNST_LIMB(0x41c21cb8e1000000), CNST_LIMB(0xf24f62335024a295) }, - /* 7 */ { 22, 0.3562071871080222, CNST_LIMB(0x3642798750226111), CNST_LIMB(0x2df495ccaa57147b) }, - /* 8 */ { 21, 0.3333333333333334, 0x3 }, - /* 9 */ { 20, 0.3154648767857287, CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, - /* 10 */ { 19, 0.3010299956639811, CNST_LIMB(0x8ac7230489e80000), CNST_LIMB(0xd83c94fb6d2ac34a) }, - /* 11 */ { 18, 0.2890648263178878, CNST_LIMB(0x4d28cb56c33fa539), CNST_LIMB(0xa8adf7ae45e7577b) }, - /* 12 */ { 17, 0.2789429456511298, CNST_LIMB(0x1eca170c00000000), CNST_LIMB(0xa10c2bec5da8f8f) }, - /* 13 */ { 17, 0.2702381544273197, CNST_LIMB(0x780c7372621bd74d), CNST_LIMB(0x10f4becafe412ec3) }, - /* 14 */ { 16, 0.2626495350371936, CNST_LIMB(0x1e39a5057d810000), CNST_LIMB(0xf08480f672b4e86) }, - /* 15 */ { 16, 0.2559580248098155, CNST_LIMB(0x5b27ac993df97701), CNST_LIMB(0x6779c7f90dc42f48) }, - /* 16 */ { 16, 0.2500000000000000, 0x4 }, - /* 17 */ { 15, 0.2446505421182260, CNST_LIMB(0x27b95e997e21d9f1), CNST_LIMB(0x9c71e11bab279323) }, - /* 18 */ { 15, 0.2398124665681315, CNST_LIMB(0x5da0e1e53c5c8000), CNST_LIMB(0x5dfaa697ec6f6a1c) }, - /* 19 */ { 15, 0.2354089133666382, CNST_LIMB(0xd2ae3299c1c4aedb), CNST_LIMB(0x3711783f6be7e9ec) }, - /* 20 */ { 14, 0.2313782131597592, CNST_LIMB(0x16bcc41e90000000), CNST_LIMB(0x6849b86a12b9b01e) }, - /* 21 */ { 14, 0.2276702486969530, CNST_LIMB(0x2d04b7fdd9c0ef49), CNST_LIMB(0x6bf097ba5ca5e239) }, - /* 22 */ { 14, 0.2242438242175754, CNST_LIMB(0x5658597bcaa24000), CNST_LIMB(0x7b8015c8d7af8f08) }, - /* 23 */ { 14, 0.2210647294575037, CNST_LIMB(0xa0e2073737609371), CNST_LIMB(0x975a24b3a3151b38) }, - /* 24 */ { 13, 0.2181042919855316, CNST_LIMB(0xc29e98000000000), CNST_LIMB(0x50bd367972689db1) }, - /* 25 */ { 13, 0.2153382790366965, CNST_LIMB(0x14adf4b7320334b9), CNST_LIMB(0x8c240c4aecb13bb5) }, - /* 26 */ { 13, 0.2127460535533632, CNST_LIMB(0x226ed36478bfa000), CNST_LIMB(0xdbd2e56854e118c9) }, - /* 27 */ { 13, 0.2103099178571525, CNST_LIMB(0x383d9170b85ff80b), CNST_LIMB(0x2351ffcaa9c7c4ae) }, - /* 28 */ { 13, 0.2080145976765095, CNST_LIMB(0x5a3c23e39c000000), CNST_LIMB(0x6b24188ca33b0636) }, - /* 29 */ { 13, 0.2058468324604344, CNST_LIMB(0x8e65137388122bcd), CNST_LIMB(0xcc3dceaf2b8ba99d) }, - /* 30 */ { 13, 0.2037950470905062, CNST_LIMB(0xdd41bb36d259e000), CNST_LIMB(0x2832e835c6c7d6b6) }, - /* 31 */ { 12, 0.2018490865820999, CNST_LIMB(0xaee5720ee830681), CNST_LIMB(0x76b6aa272e1873c5) }, - /* 32 */ { 12, 0.2000000000000000, 0x5 }, - /* 33 */ { 12, 0.1982398631705605, CNST_LIMB(0x172588ad4f5f0981), CNST_LIMB(0x61eaf5d402c7bf4f) }, - /* 34 */ { 12, 0.1965616322328226, CNST_LIMB(0x211e44f7d02c1000), CNST_LIMB(0xeeb658123ffb27ec) }, - /* 35 */ { 12, 0.1949590218937863, CNST_LIMB(0x2ee56725f06e5c71), CNST_LIMB(0x5d5e3762e6fdf509) }, - /* 36 */ { 12, 0.1934264036172708, CNST_LIMB(0x41c21cb8e1000000), CNST_LIMB(0xf24f62335024a295) }, - /* 37 */ { 12, 0.1919587200065601, CNST_LIMB(0x5b5b57f8a98a5dd1), CNST_LIMB(0x66ae7831762efb6f) }, - /* 38 */ { 12, 0.1905514124267734, CNST_LIMB(0x7dcff8986ea31000), CNST_LIMB(0x47388865a00f544) }, - /* 39 */ { 12, 0.1892003595168700, CNST_LIMB(0xabd4211662a6b2a1), CNST_LIMB(0x7d673c33a123b54c) }, - /* 40 */ { 12, 0.1879018247091076, CNST_LIMB(0xe8d4a51000000000), CNST_LIMB(0x19799812dea11197) }, - /* 41 */ { 11, 0.1866524112389434, CNST_LIMB(0x7a32956ad081b79), CNST_LIMB(0xc27e62e0686feae) }, - /* 42 */ { 11, 0.1854490234153689, CNST_LIMB(0x9f49aaff0e86800), CNST_LIMB(0x9b6e7507064ce7c7) }, - /* 43 */ { 11, 0.1842888331487062, CNST_LIMB(0xce583bb812d37b3), CNST_LIMB(0x3d9ac2bf66cfed94) }, - /* 44 */ { 11, 0.1831692509136336, CNST_LIMB(0x109b79a654c00000), CNST_LIMB(0xed46bc50ce59712a) }, - /* 45 */ { 11, 0.1820879004699383, CNST_LIMB(0x1543beff214c8b95), CNST_LIMB(0x813d97e2c89b8d46) }, - /* 46 */ { 11, 0.1810425967800402, CNST_LIMB(0x1b149a79459a3800), CNST_LIMB(0x2e81751956af8083) }, - /* 47 */ { 11, 0.1800313266566926, CNST_LIMB(0x224edfb5434a830f), CNST_LIMB(0xdd8e0a95e30c0988) }, - /* 48 */ { 11, 0.1790522317510413, CNST_LIMB(0x2b3fb00000000000), CNST_LIMB(0x7ad4dd48a0b5b167) }, - /* 49 */ { 11, 0.1781035935540111, CNST_LIMB(0x3642798750226111), CNST_LIMB(0x2df495ccaa57147b) }, - /* 50 */ { 11, 0.1771838201355579, CNST_LIMB(0x43c33c1937564800), CNST_LIMB(0xe392010175ee5962) }, - /* 51 */ { 11, 0.1762914343888821, CNST_LIMB(0x54411b2441c3cd8b), CNST_LIMB(0x84eaf11b2fe7738e) }, - /* 52 */ { 11, 0.1754250635819545, CNST_LIMB(0x6851455acd400000), CNST_LIMB(0x3a1e3971e008995d) }, - /* 53 */ { 11, 0.1745834300480449, CNST_LIMB(0x80a23b117c8feb6d), CNST_LIMB(0xfd7a462344ffce25) }, - /* 54 */ { 11, 0.1737653428714400, CNST_LIMB(0x9dff7d32d5dc1800), CNST_LIMB(0x9eca40b40ebcef8a) }, - /* 55 */ { 11, 0.1729696904450771, CNST_LIMB(0xc155af6faeffe6a7), CNST_LIMB(0x52fa161a4a48e43d) }, - /* 56 */ { 11, 0.1721954337940981, CNST_LIMB(0xebb7392e00000000), CNST_LIMB(0x1607a2cbacf930c1) }, - /* 57 */ { 10, 0.1714416005739134, CNST_LIMB(0x50633659656d971), CNST_LIMB(0x97a014f8e3be55f1) }, - /* 58 */ { 10, 0.1707072796637201, CNST_LIMB(0x5fa8624c7fba400), CNST_LIMB(0x568df8b76cbf212c) }, - /* 59 */ { 10, 0.1699916162869140, CNST_LIMB(0x717d9faa73c5679), CNST_LIMB(0x20ba7c4b4e6ef492) }, - /* 60 */ { 10, 0.1692938075987814, CNST_LIMB(0x86430aac6100000), CNST_LIMB(0xe81ee46b9ef492f5) }, - /* 61 */ { 10, 0.1686130986895011, CNST_LIMB(0x9e64d9944b57f29), CNST_LIMB(0x9dc0d10d51940416) }, - /* 62 */ { 10, 0.1679487789570419, CNST_LIMB(0xba5ca5392cb0400), CNST_LIMB(0x5fa8ed2f450272a5) }, - /* 63 */ { 10, 0.1673001788101741, CNST_LIMB(0xdab2ce1d022cd81), CNST_LIMB(0x2ba9eb8c5e04e641) }, - /* 64 */ { 10, 0.1666666666666667, 0x6 }, - /* 65 */ { 10, 0.1660476462159378, CNST_LIMB(0x12aeed5fd3e2d281), CNST_LIMB(0xb67759cc00287bf1) }, - /* 66 */ { 10, 0.1654425539190583, CNST_LIMB(0x15c3da1572d50400), CNST_LIMB(0x78621feeb7f4ed33) }, - /* 67 */ { 10, 0.1648508567221604, CNST_LIMB(0x194c05534f75ee29), CNST_LIMB(0x43d55b5f72943bc0) }, - /* 68 */ { 10, 0.1642720499620502, CNST_LIMB(0x1d56299ada100000), CNST_LIMB(0x173decb64d1d4409) }, - /* 69 */ { 10, 0.1637056554452156, CNST_LIMB(0x21f2a089a4ff4f79), CNST_LIMB(0xe29fb54fd6b6074f) }, - /* 70 */ { 10, 0.1631512196835108, CNST_LIMB(0x2733896c68d9a400), CNST_LIMB(0xa1f1f5c210d54e62) }, - /* 71 */ { 10, 0.1626083122716341, CNST_LIMB(0x2d2cf2c33b533c71), CNST_LIMB(0x6aac7f9bfafd57b2) }, - /* 72 */ { 10, 0.1620765243931223, CNST_LIMB(0x33f506e440000000), CNST_LIMB(0x3b563c2478b72ee2) }, - /* 73 */ { 10, 0.1615554674429964, CNST_LIMB(0x3ba43bec1d062211), CNST_LIMB(0x12b536b574e92d1b) }, - /* 74 */ { 10, 0.1610447717564444, CNST_LIMB(0x4455872d8fd4e400), CNST_LIMB(0xdf86c03020404fa5) }, - /* 75 */ { 10, 0.1605440854340214, CNST_LIMB(0x4e2694539f2f6c59), CNST_LIMB(0xa34adf02234eea8e) }, - /* 76 */ { 10, 0.1600530732548213, CNST_LIMB(0x5938006c18900000), CNST_LIMB(0x6f46eb8574eb59dd) }, - /* 77 */ { 10, 0.1595714156699382, CNST_LIMB(0x65ad9912474aa649), CNST_LIMB(0x42459b481df47cec) }, - /* 78 */ { 10, 0.1590988078692941, CNST_LIMB(0x73ae9ff4241ec400), CNST_LIMB(0x1b424b95d80ca505) }, - /* 79 */ { 10, 0.1586349589155960, CNST_LIMB(0x836612ee9c4ce1e1), CNST_LIMB(0xf2c1b982203a0dac) }, - /* 80 */ { 10, 0.1581795909397823, CNST_LIMB(0x9502f90000000000), CNST_LIMB(0xb7cdfd9d7bdbab7d) }, - /* 81 */ { 10, 0.1577324383928644, CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, - /* 82 */ { 10, 0.1572932473495469, CNST_LIMB(0xbebf59a07dab4400), CNST_LIMB(0x57931eeaf85cf64f) }, - /* 83 */ { 10, 0.1568617748594410, CNST_LIMB(0xd7540d4093bc3109), CNST_LIMB(0x305a944507c82f47) }, - /* 84 */ { 10, 0.1564377883420716, CNST_LIMB(0xf2b96616f1900000), CNST_LIMB(0xe007ccc9c22781a) }, - /* 85 */ { 9, 0.1560210650222250, CNST_LIMB(0x336de62af2bca35), CNST_LIMB(0x3e92c42e000eeed4) }, - /* 86 */ { 9, 0.1556113914024940, CNST_LIMB(0x39235ec33d49600), CNST_LIMB(0x1ebe59130db2795e) }, - /* 87 */ { 9, 0.1552085627701551, CNST_LIMB(0x3f674e539585a17), CNST_LIMB(0x268859e90f51b89) }, - /* 88 */ { 9, 0.1548123827357682, CNST_LIMB(0x4645b6958000000), CNST_LIMB(0xd24cde0463108cfa) }, - /* 89 */ { 9, 0.1544226628011101, CNST_LIMB(0x4dcb74afbc49c19), CNST_LIMB(0xa536009f37adc383) }, - /* 90 */ { 9, 0.1540392219542636, CNST_LIMB(0x56064e1d18d9a00), CNST_LIMB(0x7cea06ce1c9ace10) }, - /* 91 */ { 9, 0.1536618862898642, CNST_LIMB(0x5f04fe2cd8a39fb), CNST_LIMB(0x58db032e72e8ba43) }, - /* 92 */ { 9, 0.1532904886526781, CNST_LIMB(0x68d74421f5c0000), CNST_LIMB(0x388cc17cae105447) }, - /* 93 */ { 9, 0.1529248683028321, CNST_LIMB(0x738df1f6ab4827d), CNST_LIMB(0x1b92672857620ce0) }, - /* 94 */ { 9, 0.1525648706011593, CNST_LIMB(0x7f3afbc9cfb5e00), CNST_LIMB(0x18c6a9575c2ade4) }, - /* 95 */ { 9, 0.1522103467132434, CNST_LIMB(0x8bf187fba88f35f), CNST_LIMB(0xd44da7da8e44b24f) }, - /* 96 */ { 9, 0.1518611533308632, CNST_LIMB(0x99c600000000000), CNST_LIMB(0xaa2f78f1b4cc6794) }, - /* 97 */ { 9, 0.1515171524096389, CNST_LIMB(0xa8ce21eb6531361), CNST_LIMB(0x843c067d091ee4cc) }, - /* 98 */ { 9, 0.1511782109217764, CNST_LIMB(0xb92112c1a0b6200), CNST_LIMB(0x62005e1e913356e3) }, - /* 99 */ { 9, 0.1508442006228941, CNST_LIMB(0xcad7718b8747c43), CNST_LIMB(0x4316eed01dedd518) }, - /* 100 */ { 9, 0.1505149978319906, CNST_LIMB(0xde0b6b3a7640000), CNST_LIMB(0x2725dd1d243aba0e) }, - /* 101 */ { 9, 0.1501904832236879, CNST_LIMB(0xf2d8cf5fe6d74c5), CNST_LIMB(0xddd9057c24cb54f) }, - /* 102 */ { 9, 0.1498705416319474, CNST_LIMB(0x1095d25bfa712600), CNST_LIMB(0xedeee175a736d2a1) }, - /* 103 */ { 9, 0.1495550618645152, CNST_LIMB(0x121b7c4c3698faa7), CNST_LIMB(0xc4699f3df8b6b328) }, - /* 104 */ { 9, 0.1492439365274121, CNST_LIMB(0x13c09e8d68000000), CNST_LIMB(0x9ebbe7d859cb5a7c) }, - /* 105 */ { 9, 0.1489370618588283, CNST_LIMB(0x15876ccb0b709ca9), CNST_LIMB(0x7c828b9887eb2179) }, - /* 106 */ { 9, 0.1486343375718350, CNST_LIMB(0x17723c2976da2a00), CNST_LIMB(0x5d652ab99001adcf) }, - /* 107 */ { 9, 0.1483356667053617, CNST_LIMB(0x198384e9c259048b), CNST_LIMB(0x4114f1754e5d7b32) }, - /* 108 */ { 9, 0.1480409554829326, CNST_LIMB(0x1bbde41dfeec0000), CNST_LIMB(0x274b7c902f7e0188) }, - /* 109 */ { 9, 0.1477501131786861, CNST_LIMB(0x1e241d6e3337910d), CNST_LIMB(0xfc9e0fbb32e210c) }, - /* 110 */ { 9, 0.1474630519902391, CNST_LIMB(0x20b91cee9901ee00), CNST_LIMB(0xf4afa3e594f8ea1f) }, - /* 111 */ { 9, 0.1471796869179852, CNST_LIMB(0x237ff9079863dfef), CNST_LIMB(0xcd85c32e9e4437b0) }, - /* 112 */ { 9, 0.1468999356504447, CNST_LIMB(0x267bf47000000000), CNST_LIMB(0xa9bbb147e0dd92a8) }, - /* 113 */ { 9, 0.1466237184553111, CNST_LIMB(0x29b08039fbeda7f1), CNST_LIMB(0x8900447b70e8eb82) }, - /* 114 */ { 9, 0.1463509580758620, CNST_LIMB(0x2d213df34f65f200), CNST_LIMB(0x6b0a92adaad5848a) }, - /* 115 */ { 9, 0.1460815796324244, CNST_LIMB(0x30d201d957a7c2d3), CNST_LIMB(0x4f990ad8740f0ee5) }, - /* 116 */ { 9, 0.1458155105286054, CNST_LIMB(0x34c6d52160f40000), CNST_LIMB(0x3670a9663a8d3610) }, - /* 117 */ { 9, 0.1455526803620167, CNST_LIMB(0x3903f855d8f4c755), CNST_LIMB(0x1f5c44188057be3c) }, - /* 118 */ { 9, 0.1452930208392428, CNST_LIMB(0x3d8de5c8ec59b600), CNST_LIMB(0xa2bea956c4e4977) }, - /* 119 */ { 9, 0.1450364656948130, CNST_LIMB(0x4269541d1ff01337), CNST_LIMB(0xed68b23033c3637e) }, - /* 120 */ { 9, 0.1447829506139581, CNST_LIMB(0x479b38e478000000), CNST_LIMB(0xc99cf624e50549c5) }, - /* 121 */ { 9, 0.1445324131589439, CNST_LIMB(0x4d28cb56c33fa539), CNST_LIMB(0xa8adf7ae45e7577b) }, - /* 122 */ { 9, 0.1442847926987864, CNST_LIMB(0x5317871fa13aba00), CNST_LIMB(0x8a5bc740b1c113e5) }, - /* 123 */ { 9, 0.1440400303421672, CNST_LIMB(0x596d2f44de9fa71b), CNST_LIMB(0x6e6c7efb81cfbb9b) }, - /* 124 */ { 9, 0.1437980688733775, CNST_LIMB(0x602fd125c47c0000), CNST_LIMB(0x54aba5c5cada5f10) }, - /* 125 */ { 9, 0.1435588526911310, CNST_LIMB(0x6765c793fa10079d), CNST_LIMB(0x3ce9a36f23c0fc90) }, - /* 126 */ { 9, 0.1433223277500932, CNST_LIMB(0x6f15be069b847e00), CNST_LIMB(0x26fb43de2c8cd2a8) }, - /* 127 */ { 9, 0.1430884415049874, CNST_LIMB(0x7746b3e82a77047f), CNST_LIMB(0x12b94793db8486a1) }, - /* 128 */ { 9, 0.1428571428571428, 0x7 }, - /* 129 */ { 9, 0.1426283821033600, CNST_LIMB(0x894953f7ea890481), CNST_LIMB(0xdd5deca404c0156d) }, - /* 130 */ { 9, 0.1424021108869747, CNST_LIMB(0x932abffea4848200), CNST_LIMB(0xbd51373330291de0) }, - /* 131 */ { 9, 0.1421782821510107, CNST_LIMB(0x9dacb687d3d6a163), CNST_LIMB(0x9fa4025d66f23085) }, - /* 132 */ { 9, 0.1419568500933153, CNST_LIMB(0xa8d8102a44840000), CNST_LIMB(0x842530ee2db4949d) }, - /* 133 */ { 9, 0.1417377701235801, CNST_LIMB(0xb4b60f9d140541e5), CNST_LIMB(0x6aa7f2766b03dc25) }, - /* 134 */ { 9, 0.1415209988221527, CNST_LIMB(0xc15065d4856e4600), CNST_LIMB(0x53035ba7ebf32e8d) }, - /* 135 */ { 9, 0.1413064939005528, CNST_LIMB(0xceb1363f396d23c7), CNST_LIMB(0x3d12091fc9fb4914) }, - /* 136 */ { 9, 0.1410942141636095, CNST_LIMB(0xdce31b2488000000), CNST_LIMB(0x28b1cb81b1ef1849) }, - /* 137 */ { 9, 0.1408841194731412, CNST_LIMB(0xebf12a24bca135c9), CNST_LIMB(0x15c35be67ae3e2c9) }, - /* 138 */ { 9, 0.1406761707131039, CNST_LIMB(0xfbe6f8dbf88f4a00), CNST_LIMB(0x42a17bd09be1ff0) }, - /* 139 */ { 8, 0.1404703297561400, CNST_LIMB(0x1ef156c084ce761), CNST_LIMB(0x8bf461f03cf0bbf) }, - /* 140 */ { 8, 0.1402665594314587, CNST_LIMB(0x20c4e3b94a10000), CNST_LIMB(0xf3fbb43f68a32d05) }, - /* 141 */ { 8, 0.1400648234939879, CNST_LIMB(0x22b0695a08ba421), CNST_LIMB(0xd84f44c48564dc19) }, - /* 142 */ { 8, 0.1398650865947379, CNST_LIMB(0x24b4f35d7a4c100), CNST_LIMB(0xbe58ebcce7956abe) }, - /* 143 */ { 8, 0.1396673142523192, CNST_LIMB(0x26d397284975781), CNST_LIMB(0xa5fac463c7c134b7) }, - /* 144 */ { 8, 0.1394714728255649, CNST_LIMB(0x290d74100000000), CNST_LIMB(0x8f19241e28c7d757) }, - /* 145 */ { 8, 0.1392775294872041, CNST_LIMB(0x2b63b3a37866081), CNST_LIMB(0x799a6d046c0ae1ae) }, - /* 146 */ { 8, 0.1390854521985406, CNST_LIMB(0x2dd789f4d894100), CNST_LIMB(0x6566e37d746a9e40) }, - /* 147 */ { 8, 0.1388952096850913, CNST_LIMB(0x306a35e51b58721), CNST_LIMB(0x526887dbfb5f788f) }, - /* 148 */ { 8, 0.1387067714131417, CNST_LIMB(0x331d01712e10000), CNST_LIMB(0x408af3382b8efd3d) }, - /* 149 */ { 8, 0.1385201075671774, CNST_LIMB(0x35f14200a827c61), CNST_LIMB(0x2fbb374806ec05f1) }, - /* 150 */ { 8, 0.1383351890281539, CNST_LIMB(0x38e858b62216100), CNST_LIMB(0x1fe7c0f0afce87fe) }, - /* 151 */ { 8, 0.1381519873525671, CNST_LIMB(0x3c03b2c13176a41), CNST_LIMB(0x11003d517540d32e) }, - /* 152 */ { 8, 0.1379704747522905, CNST_LIMB(0x3f44c9b21000000), CNST_LIMB(0x2f5810f98eff0dc) }, - /* 153 */ { 8, 0.1377906240751463, CNST_LIMB(0x42ad23cef3113c1), CNST_LIMB(0xeb72e35e7840d910) }, - /* 154 */ { 8, 0.1376124087861776, CNST_LIMB(0x463e546b19a2100), CNST_LIMB(0xd27de19593dc3614) }, - /* 155 */ { 8, 0.1374358029495937, CNST_LIMB(0x49f9fc3f96684e1), CNST_LIMB(0xbaf391fd3e5e6fc2) }, - /* 156 */ { 8, 0.1372607812113589, CNST_LIMB(0x4de1c9c5dc10000), CNST_LIMB(0xa4bd38c55228c81d) }, - /* 157 */ { 8, 0.1370873187823978, CNST_LIMB(0x51f77994116d2a1), CNST_LIMB(0x8fc5a8de8e1de782) }, - /* 158 */ { 8, 0.1369153914223921, CNST_LIMB(0x563cd6bb3398100), CNST_LIMB(0x7bf9265bea9d3a3b) }, - /* 159 */ { 8, 0.1367449754241439, CNST_LIMB(0x5ab3bb270beeb01), CNST_LIMB(0x69454b325983dccd) }, - /* 160 */ { 8, 0.1365760475984821, CNST_LIMB(0x5f5e10000000000), CNST_LIMB(0x5798ee2308c39df9) }, - /* 161 */ { 8, 0.1364085852596902, CNST_LIMB(0x643dce0ec16f501), CNST_LIMB(0x46e40ba0fa66a753) }, - /* 162 */ { 8, 0.1362425662114337, CNST_LIMB(0x6954fe21e3e8100), CNST_LIMB(0x3717b0870b0db3a7) }, - /* 163 */ { 8, 0.1360779687331669, CNST_LIMB(0x6ea5b9755f440a1), CNST_LIMB(0x2825e6775d11cdeb) }, - /* 164 */ { 8, 0.1359147715670014, CNST_LIMB(0x74322a1c0410000), CNST_LIMB(0x1a01a1c09d1b4dac) }, - /* 165 */ { 8, 0.1357529539050150, CNST_LIMB(0x79fc8b6ae8a46e1), CNST_LIMB(0xc9eb0a8bebc8f3e) }, - /* 166 */ { 8, 0.1355924953769863, CNST_LIMB(0x80072a66d512100), CNST_LIMB(0xffe357ff59e6a004) }, - /* 167 */ { 8, 0.1354333760385373, CNST_LIMB(0x86546633b42b9c1), CNST_LIMB(0xe7dfd1be05fa61a8) }, - /* 168 */ { 8, 0.1352755763596663, CNST_LIMB(0x8ce6b0861000000), CNST_LIMB(0xd11ed6fc78f760e5) }, - /* 169 */ { 8, 0.1351190772136599, CNST_LIMB(0x93c08e16a022441), CNST_LIMB(0xbb8db609dd29ebfe) }, - /* 170 */ { 8, 0.1349638598663645, CNST_LIMB(0x9ae49717f026100), CNST_LIMB(0xa71aec8d1813d532) }, - /* 171 */ { 8, 0.1348099059658079, CNST_LIMB(0xa25577ae24c1a61), CNST_LIMB(0x93b612a9f20fbc02) }, - /* 172 */ { 8, 0.1346571975321549, CNST_LIMB(0xaa15f068e610000), CNST_LIMB(0x814fc7b19a67d317) }, - /* 173 */ { 8, 0.1345057169479844, CNST_LIMB(0xb228d6bf7577921), CNST_LIMB(0x6fd9a03f2e0a4b7c) }, - /* 174 */ { 8, 0.1343554469488779, CNST_LIMB(0xba91158ef5c4100), CNST_LIMB(0x5f4615a38d0d316e) }, - /* 175 */ { 8, 0.1342063706143054, CNST_LIMB(0xc351ad9aec0b681), CNST_LIMB(0x4f8876863479a286) }, - /* 176 */ { 8, 0.1340584713587980, CNST_LIMB(0xcc6db6100000000), CNST_LIMB(0x4094d8a3041b60eb) }, - /* 177 */ { 8, 0.1339117329233981, CNST_LIMB(0xd5e85d09025c181), CNST_LIMB(0x32600b8ed883a09b) }, - /* 178 */ { 8, 0.1337661393673756, CNST_LIMB(0xdfc4e816401c100), CNST_LIMB(0x24df8c6eb4b6d1f1) }, - /* 179 */ { 8, 0.1336216750601996, CNST_LIMB(0xea06b4c72947221), CNST_LIMB(0x18097a8ee151acef) }, - /* 180 */ { 8, 0.1334783246737591, CNST_LIMB(0xf4b139365210000), CNST_LIMB(0xbd48cc8ec1cd8e3) }, - /* 181 */ { 8, 0.1333360731748201, CNST_LIMB(0xffc80497d520961), CNST_LIMB(0x3807a8d67485fb) }, - /* 182 */ { 8, 0.1331949058177136, CNST_LIMB(0x10b4ebfca1dee100), CNST_LIMB(0xea5768860b62e8d8) }, - /* 183 */ { 8, 0.1330548081372441, CNST_LIMB(0x117492de921fc141), CNST_LIMB(0xd54faf5b635c5005) }, - /* 184 */ { 8, 0.1329157659418126, CNST_LIMB(0x123bb2ce41000000), CNST_LIMB(0xc14a56233a377926) }, - /* 185 */ { 8, 0.1327777653067443, CNST_LIMB(0x130a8b6157bdecc1), CNST_LIMB(0xae39a88db7cd329f) }, - /* 186 */ { 8, 0.1326407925678156, CNST_LIMB(0x13e15dede0e8a100), CNST_LIMB(0x9c10bde69efa7ab6) }, - /* 187 */ { 8, 0.1325048343149731, CNST_LIMB(0x14c06d941c0ca7e1), CNST_LIMB(0x8ac36c42a2836497) }, - /* 188 */ { 8, 0.1323698773862368, CNST_LIMB(0x15a7ff487a810000), CNST_LIMB(0x7a463c8b84f5ef67) }, - /* 189 */ { 8, 0.1322359088617821, CNST_LIMB(0x169859ddc5c697a1), CNST_LIMB(0x6a8e5f5ad090fd4b) }, - /* 190 */ { 8, 0.1321029160581950, CNST_LIMB(0x1791c60f6fed0100), CNST_LIMB(0x5b91a2943596fc56) }, - /* 191 */ { 8, 0.1319708865228925, CNST_LIMB(0x18948e8c0e6fba01), CNST_LIMB(0x4d4667b1c468e8f0) }, - /* 192 */ { 8, 0.1318398080287045, CNST_LIMB(0x19a1000000000000), CNST_LIMB(0x3fa39ab547994daf) }, - /* 193 */ { 8, 0.1317096685686114, CNST_LIMB(0x1ab769203dafc601), CNST_LIMB(0x32a0a9b2faee1e2a) }, - /* 194 */ { 8, 0.1315804563506306, CNST_LIMB(0x1bd81ab557f30100), CNST_LIMB(0x26357ceac0e96962) }, - /* 195 */ { 8, 0.1314521597928493, CNST_LIMB(0x1d0367a69fed1ba1), CNST_LIMB(0x1a5a6f65caa5859e) }, - /* 196 */ { 8, 0.1313247675185968, CNST_LIMB(0x1e39a5057d810000), CNST_LIMB(0xf08480f672b4e86) }, - /* 197 */ { 8, 0.1311982683517524, CNST_LIMB(0x1f7b2a18f29ac3e1), CNST_LIMB(0x4383340615612ca) }, - /* 198 */ { 8, 0.1310726513121843, CNST_LIMB(0x20c850694c2aa100), CNST_LIMB(0xf3c77969ee4be5a2) }, - /* 199 */ { 8, 0.1309479056113158, CNST_LIMB(0x222173cc014980c1), CNST_LIMB(0xe00993cc187c5ec9) }, - /* 200 */ { 8, 0.1308240206478128, CNST_LIMB(0x2386f26fc1000000), CNST_LIMB(0xcd2b297d889bc2b6) }, - /* 201 */ { 8, 0.1307009860033912, CNST_LIMB(0x24f92ce8af296d41), CNST_LIMB(0xbb214d5064862b22) }, - /* 202 */ { 8, 0.1305787914387386, CNST_LIMB(0x2678863cd0ece100), CNST_LIMB(0xa9e1a7ca7ea10e20) }, - /* 203 */ { 8, 0.1304574268895465, CNST_LIMB(0x280563f0a9472d61), CNST_LIMB(0x99626e72b39ea0cf) }, - /* 204 */ { 8, 0.1303368824626505, CNST_LIMB(0x29a02e1406210000), CNST_LIMB(0x899a5ba9c13fafd9) }, - /* 205 */ { 8, 0.1302171484322746, CNST_LIMB(0x2b494f4efe6d2e21), CNST_LIMB(0x7a80a705391e96ff) }, - /* 206 */ { 8, 0.1300982152363760, CNST_LIMB(0x2d0134ef21cbc100), CNST_LIMB(0x6c0cfe23de23042a) }, - /* 207 */ { 8, 0.1299800734730872, CNST_LIMB(0x2ec84ef4da2ef581), CNST_LIMB(0x5e377df359c944dd) }, - /* 208 */ { 8, 0.1298627138972530, CNST_LIMB(0x309f102100000000), CNST_LIMB(0x50f8ac5fc8f53985) }, - /* 209 */ { 8, 0.1297461274170591, CNST_LIMB(0x3285ee02a1420281), CNST_LIMB(0x44497266278e35b7) }, - /* 210 */ { 8, 0.1296303050907487, CNST_LIMB(0x347d6104fc324100), CNST_LIMB(0x382316831f7ee175) }, - /* 211 */ { 8, 0.1295152381234257, CNST_LIMB(0x3685e47dade53d21), CNST_LIMB(0x2c7f377833b8946e) }, - /* 212 */ { 8, 0.1294009178639407, CNST_LIMB(0x389ff6bb15610000), CNST_LIMB(0x2157c761ab4163ef) }, - /* 213 */ { 8, 0.1292873358018581, CNST_LIMB(0x3acc1912ebb57661), CNST_LIMB(0x16a7071803cc49a9) }, - /* 214 */ { 8, 0.1291744835645007, CNST_LIMB(0x3d0acff111946100), CNST_LIMB(0xc6781d80f8224fc) }, - /* 215 */ { 8, 0.1290623529140715, CNST_LIMB(0x3f5ca2e692eaf841), CNST_LIMB(0x294092d370a900b) }, - /* 216 */ { 8, 0.1289509357448472, CNST_LIMB(0x41c21cb8e1000000), CNST_LIMB(0xf24f62335024a295) }, - /* 217 */ { 8, 0.1288402240804449, CNST_LIMB(0x443bcb714399a5c1), CNST_LIMB(0xe03b98f103fad6d2) }, - /* 218 */ { 8, 0.1287302100711567, CNST_LIMB(0x46ca406c81af2100), CNST_LIMB(0xcee3d32cad2a9049) }, - /* 219 */ { 8, 0.1286208859913518, CNST_LIMB(0x496e106ac22aaae1), CNST_LIMB(0xbe3f9df9277fdada) }, - /* 220 */ { 8, 0.1285122442369443, CNST_LIMB(0x4c27d39fa5410000), CNST_LIMB(0xae46f0d94c05e933) }, - /* 221 */ { 8, 0.1284042773229231, CNST_LIMB(0x4ef825c296e43ca1), CNST_LIMB(0x9ef2280fb437a33d) }, - /* 222 */ { 8, 0.1282969778809442, CNST_LIMB(0x51dfa61f5ad88100), CNST_LIMB(0x9039ff426d3f284b) }, - /* 223 */ { 8, 0.1281903386569819, CNST_LIMB(0x54def7a6d2f16901), CNST_LIMB(0x82178c6d6b51f8f4) }, - /* 224 */ { 8, 0.1280843525090381, CNST_LIMB(0x57f6c10000000000), CNST_LIMB(0x74843b1ee4c1e053) }, - /* 225 */ { 8, 0.1279790124049077, CNST_LIMB(0x5b27ac993df97701), CNST_LIMB(0x6779c7f90dc42f48) }, - /* 226 */ { 8, 0.1278743114199984, CNST_LIMB(0x5e7268b9bbdf8100), CNST_LIMB(0x5af23c74f9ad9fe9) }, - /* 227 */ { 8, 0.1277702427352035, CNST_LIMB(0x61d7a7932ff3d6a1), CNST_LIMB(0x4ee7eae2acdc617e) }, - /* 228 */ { 8, 0.1276667996348261, CNST_LIMB(0x65581f53c8c10000), CNST_LIMB(0x43556aa2ac262a0b) }, - /* 229 */ { 8, 0.1275639755045533, CNST_LIMB(0x68f48a385b8320e1), CNST_LIMB(0x3835949593b8ddd1) }, - /* 230 */ { 8, 0.1274617638294791, CNST_LIMB(0x6cada69ed07c2100), CNST_LIMB(0x2d837fbe78458762) }, - /* 231 */ { 8, 0.1273601581921741, CNST_LIMB(0x70843718cdbf27c1), CNST_LIMB(0x233a7e150a54a555) }, - /* 232 */ { 8, 0.1272591522708010, CNST_LIMB(0x7479027ea1000000), CNST_LIMB(0x19561984a50ff8fe) }, - /* 233 */ { 8, 0.1271587398372755, CNST_LIMB(0x788cd40268f39641), CNST_LIMB(0xfd211159fe3490f) }, - /* 234 */ { 8, 0.1270589147554692, CNST_LIMB(0x7cc07b437ecf6100), CNST_LIMB(0x6aa563e655033e3) }, - /* 235 */ { 8, 0.1269596709794558, CNST_LIMB(0x8114cc6220762061), CNST_LIMB(0xfbb614b3f2d3b14c) }, - /* 236 */ { 8, 0.1268610025517973, CNST_LIMB(0x858aa0135be10000), CNST_LIMB(0xeac0f8837fb05773) }, - /* 237 */ { 8, 0.1267629036018709, CNST_LIMB(0x8a22d3b53c54c321), CNST_LIMB(0xda6e4c10e8615ca5) }, - /* 238 */ { 8, 0.1266653683442337, CNST_LIMB(0x8ede496339f34100), CNST_LIMB(0xcab755a8d01fa67f) }, - /* 239 */ { 8, 0.1265683910770258, CNST_LIMB(0x93bde80aec3a1481), CNST_LIMB(0xbb95a9ae71aa3e0c) }, - /* 240 */ { 8, 0.1264719661804097, CNST_LIMB(0x98c29b8100000000), CNST_LIMB(0xad0326c296b4f529) }, - /* 241 */ { 8, 0.1263760881150453, CNST_LIMB(0x9ded549671832381), CNST_LIMB(0x9ef9f21eed31b7c1) }, - /* 242 */ { 8, 0.1262807514205999, CNST_LIMB(0xa33f092e0b1ac100), CNST_LIMB(0x91747422be14b0b2) }, - /* 243 */ { 8, 0.1261859507142915, CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, - /* 244 */ { 8, 0.1260916806894653, CNST_LIMB(0xae5b564ac3a10000), CNST_LIMB(0x77df79e9a96c06f6) }, - /* 245 */ { 8, 0.1259979361142023, CNST_LIMB(0xb427f4b3be74c361), CNST_LIMB(0x6bc6019636c7d0c2) }, - /* 246 */ { 8, 0.1259047118299582, CNST_LIMB(0xba1f9a938041e100), CNST_LIMB(0x601c4205aebd9e47) }, - /* 247 */ { 8, 0.1258120027502338, CNST_LIMB(0xc0435871d1110f41), CNST_LIMB(0x54ddc59756f05016) }, - /* 248 */ { 8, 0.1257198038592741, CNST_LIMB(0xc694446f01000000), CNST_LIMB(0x4a0648979c838c18) }, - /* 249 */ { 8, 0.1256281102107963, CNST_LIMB(0xcd137a5b57ac3ec1), CNST_LIMB(0x3f91b6e0bb3a053d) }, - /* 250 */ { 8, 0.1255369169267456, CNST_LIMB(0xd3c21bcecceda100), CNST_LIMB(0x357c299a88ea76a5) }, - /* 251 */ { 8, 0.1254462191960791, CNST_LIMB(0xdaa150410b788de1), CNST_LIMB(0x2bc1e517aecc56e3) }, - /* 252 */ { 8, 0.1253560122735751, CNST_LIMB(0xe1b24521be010000), CNST_LIMB(0x225f56ceb3da9f5d) }, - /* 253 */ { 8, 0.1252662914786691, CNST_LIMB(0xe8f62df12777c1a1), CNST_LIMB(0x1951136d53ad63ac) }, - /* 254 */ { 8, 0.1251770521943144, CNST_LIMB(0xf06e445906fc0100), CNST_LIMB(0x1093d504b3cd7d93) }, - /* 255 */ { 8, 0.1250882898658681, CNST_LIMB(0xf81bc845c81bf801), CNST_LIMB(0x824794d1ec1814f) }, - /* 256 */ { 8, 0.1250000000000000, 0x8 }, + /* 0 */ { 0, 0, 0, 0, 0 }, + /* 1 */ { 0, 0, 0, 0, 0 }, + /* 2 */ { 64, CNST_LIMB(0xffffffffffffffff), CNST_LIMB(0x1fffffffffffffff), CNST_LIMB(0x1), CNST_LIMB(0x0) }, + /* 3 */ { 40, CNST_LIMB(0xa1849cc1a9a9e94e), CNST_LIMB(0x32b803473f7ad0f3), CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, + /* 4 */ { 32, CNST_LIMB(0x7fffffffffffffff), CNST_LIMB(0x3fffffffffffffff), CNST_LIMB(0x2), CNST_LIMB(0x0) }, + /* 5 */ { 27, CNST_LIMB(0x6e40d1a4143dcb94), CNST_LIMB(0x4a4d3c25e68dc57f), CNST_LIMB(0x6765c793fa10079d), CNST_LIMB(0x3ce9a36f23c0fc90) }, + /* 6 */ { 24, CNST_LIMB(0x6308c91b702a7cf4), CNST_LIMB(0x52b803473f7ad0f3), CNST_LIMB(0x41c21cb8e1000000), CNST_LIMB(0xf24f62335024a295) }, + /* 7 */ { 22, CNST_LIMB(0x5b3064eb3aa6d388), CNST_LIMB(0x59d5d9fd5010b366), CNST_LIMB(0x3642798750226111), CNST_LIMB(0x2df495ccaa57147b) }, + /* 8 */ { 21, CNST_LIMB(0x5555555555555555), CNST_LIMB(0x5fffffffffffffff), CNST_LIMB(0x3), CNST_LIMB(0x0) }, + /* 9 */ { 20, CNST_LIMB(0x50c24e60d4d4f4a7), CNST_LIMB(0x6570068e7ef5a1e7), CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, + /* 10 */ { 19, CNST_LIMB(0x4d104d427de7fbcc), CNST_LIMB(0x6a4d3c25e68dc57f), CNST_LIMB(0x8ac7230489e80000), CNST_LIMB(0xd83c94fb6d2ac34a) }, + /* 11 */ { 18, CNST_LIMB(0x4a00270775914e88), CNST_LIMB(0x6eb3a9f01975077f), CNST_LIMB(0x4d28cb56c33fa539), CNST_LIMB(0xa8adf7ae45e7577b) }, + /* 12 */ { 17, CNST_LIMB(0x4768ce0d05818e12), CNST_LIMB(0x72b803473f7ad0f3), CNST_LIMB(0x1eca170c00000000), CNST_LIMB(0xa10c2bec5da8f8f) }, + /* 13 */ { 17, CNST_LIMB(0x452e53e365907bda), CNST_LIMB(0x766a008e4788cbcd), CNST_LIMB(0x780c7372621bd74d), CNST_LIMB(0x10f4becafe412ec3) }, + /* 14 */ { 16, CNST_LIMB(0x433cfffb4b5aae55), CNST_LIMB(0x79d5d9fd5010b366), CNST_LIMB(0x1e39a5057d810000), CNST_LIMB(0xf08480f672b4e86) }, + /* 15 */ { 16, CNST_LIMB(0x41867711b4f85355), CNST_LIMB(0x7d053f6d26089673), CNST_LIMB(0x5b27ac993df97701), CNST_LIMB(0x6779c7f90dc42f48) }, + /* 16 */ { 16, CNST_LIMB(0x3fffffffffffffff), CNST_LIMB(0x7fffffffffffffff), CNST_LIMB(0x4), CNST_LIMB(0x0) }, + /* 17 */ { 15, CNST_LIMB(0x3ea16afd58b10966), CNST_LIMB(0x82cc7edf592262cf), CNST_LIMB(0x27b95e997e21d9f1), CNST_LIMB(0x9c71e11bab279323) }, + /* 18 */ { 15, CNST_LIMB(0x3d64598d154dc4de), CNST_LIMB(0x8570068e7ef5a1e7), CNST_LIMB(0x5da0e1e53c5c8000), CNST_LIMB(0x5dfaa697ec6f6a1c) }, + /* 19 */ { 15, CNST_LIMB(0x3c43c23018bb5563), CNST_LIMB(0x87ef05ae409a0288), CNST_LIMB(0xd2ae3299c1c4aedb), CNST_LIMB(0x3711783f6be7e9ec) }, + /* 20 */ { 14, CNST_LIMB(0x3b3b9a42873069c7), CNST_LIMB(0x8a4d3c25e68dc57f), CNST_LIMB(0x16bcc41e90000000), CNST_LIMB(0x6849b86a12b9b01e) }, + /* 21 */ { 14, CNST_LIMB(0x3a4898f06cf41ac9), CNST_LIMB(0x8c8ddd448f8b845a), CNST_LIMB(0x2d04b7fdd9c0ef49), CNST_LIMB(0x6bf097ba5ca5e239) }, + /* 22 */ { 14, CNST_LIMB(0x39680b13582e7c18), CNST_LIMB(0x8eb3a9f01975077f), CNST_LIMB(0x5658597bcaa24000), CNST_LIMB(0x7b8015c8d7af8f08) }, + /* 23 */ { 14, CNST_LIMB(0x3897b2b751ae561a), CNST_LIMB(0x90c10500d63aa658), CNST_LIMB(0xa0e2073737609371), CNST_LIMB(0x975a24b3a3151b38) }, + /* 24 */ { 13, CNST_LIMB(0x37d5aed131f19c98), CNST_LIMB(0x92b803473f7ad0f3), CNST_LIMB(0xc29e98000000000), CNST_LIMB(0x50bd367972689db1) }, + /* 25 */ { 13, CNST_LIMB(0x372068d20a1ee5ca), CNST_LIMB(0x949a784bcd1b8afe), CNST_LIMB(0x14adf4b7320334b9), CNST_LIMB(0x8c240c4aecb13bb5) }, + /* 26 */ { 13, CNST_LIMB(0x3676867e5d60de29), CNST_LIMB(0x966a008e4788cbcd), CNST_LIMB(0x226ed36478bfa000), CNST_LIMB(0xdbd2e56854e118c9) }, + /* 27 */ { 13, CNST_LIMB(0x35d6deeb388df86f), CNST_LIMB(0x982809d5be7072db), CNST_LIMB(0x383d9170b85ff80b), CNST_LIMB(0x2351ffcaa9c7c4ae) }, + /* 28 */ { 13, CNST_LIMB(0x354071d61c77fa2e), CNST_LIMB(0x99d5d9fd5010b366), CNST_LIMB(0x5a3c23e39c000000), CNST_LIMB(0x6b24188ca33b0636) }, + /* 29 */ { 13, CNST_LIMB(0x34b260c5671b18ac), CNST_LIMB(0x9b74948f5532da4b), CNST_LIMB(0x8e65137388122bcd), CNST_LIMB(0xcc3dceaf2b8ba99d) }, + /* 30 */ { 13, CNST_LIMB(0x342be986572b45cc), CNST_LIMB(0x9d053f6d26089673), CNST_LIMB(0xdd41bb36d259e000), CNST_LIMB(0x2832e835c6c7d6b6) }, + /* 31 */ { 12, CNST_LIMB(0x33ac61b998fbbdf2), CNST_LIMB(0x9e88c6b3626a72aa), CNST_LIMB(0xaee5720ee830681), CNST_LIMB(0x76b6aa272e1873c5) }, + /* 32 */ { 12, CNST_LIMB(0x3333333333333333), CNST_LIMB(0x9fffffffffffffff), CNST_LIMB(0x5), CNST_LIMB(0x0) }, + /* 33 */ { 12, CNST_LIMB(0x32bfd90114c12861), CNST_LIMB(0xa16bad3758efd873), CNST_LIMB(0x172588ad4f5f0981), CNST_LIMB(0x61eaf5d402c7bf4f) }, + /* 34 */ { 12, CNST_LIMB(0x3251dcf6169e45f2), CNST_LIMB(0xa2cc7edf592262cf), CNST_LIMB(0x211e44f7d02c1000), CNST_LIMB(0xeeb658123ffb27ec) }, + /* 35 */ { 12, CNST_LIMB(0x31e8d59f180dc630), CNST_LIMB(0xa4231623369e78e5), CNST_LIMB(0x2ee56725f06e5c71), CNST_LIMB(0x5d5e3762e6fdf509) }, + /* 36 */ { 12, CNST_LIMB(0x3184648db8153e7a), CNST_LIMB(0xa570068e7ef5a1e7), CNST_LIMB(0x41c21cb8e1000000), CNST_LIMB(0xf24f62335024a295) }, + /* 37 */ { 12, CNST_LIMB(0x312434e89c35dacd), CNST_LIMB(0xa6b3d78b6d3b24fb), CNST_LIMB(0x5b5b57f8a98a5dd1), CNST_LIMB(0x66ae7831762efb6f) }, + /* 38 */ { 12, CNST_LIMB(0x30c7fa349460a541), CNST_LIMB(0xa7ef05ae409a0288), CNST_LIMB(0x7dcff8986ea31000), CNST_LIMB(0x47388865a00f544) }, + /* 39 */ { 12, CNST_LIMB(0x306f6f4c8432bc6d), CNST_LIMB(0xa92203d587039cc1), CNST_LIMB(0xabd4211662a6b2a1), CNST_LIMB(0x7d673c33a123b54c) }, + /* 40 */ { 12, CNST_LIMB(0x301a557ffbfdd252), CNST_LIMB(0xaa4d3c25e68dc57f), CNST_LIMB(0xe8d4a51000000000), CNST_LIMB(0x19799812dea11197) }, + /* 41 */ { 11, CNST_LIMB(0x2fc873d1fda55f3b), CNST_LIMB(0xab7110e6ce866f2b), CNST_LIMB(0x7a32956ad081b79), CNST_LIMB(0xc27e62e0686feae) }, + /* 42 */ { 11, CNST_LIMB(0x2f799652a4e6dc49), CNST_LIMB(0xac8ddd448f8b845a), CNST_LIMB(0x9f49aaff0e86800), CNST_LIMB(0x9b6e7507064ce7c7) }, + /* 43 */ { 11, CNST_LIMB(0x2f2d8d8f64460aad), CNST_LIMB(0xada3f5fb9c415052), CNST_LIMB(0xce583bb812d37b3), CNST_LIMB(0x3d9ac2bf66cfed94) }, + /* 44 */ { 11, CNST_LIMB(0x2ee42e164e8f53a4), CNST_LIMB(0xaeb3a9f01975077f), CNST_LIMB(0x109b79a654c00000), CNST_LIMB(0xed46bc50ce59712a) }, + /* 45 */ { 11, CNST_LIMB(0x2e9d500984041dbd), CNST_LIMB(0xafbd42b465836767), CNST_LIMB(0x1543beff214c8b95), CNST_LIMB(0x813d97e2c89b8d46) }, + /* 46 */ { 11, CNST_LIMB(0x2e58cec05a6a8144), CNST_LIMB(0xb0c10500d63aa658), CNST_LIMB(0x1b149a79459a3800), CNST_LIMB(0x2e81751956af8083) }, + /* 47 */ { 11, CNST_LIMB(0x2e1688743ef9104c), CNST_LIMB(0xb1bf311e95d00de3), CNST_LIMB(0x224edfb5434a830f), CNST_LIMB(0xdd8e0a95e30c0988) }, + /* 48 */ { 11, CNST_LIMB(0x2dd65df7a583598f), CNST_LIMB(0xb2b803473f7ad0f3), CNST_LIMB(0x2b3fb00000000000), CNST_LIMB(0x7ad4dd48a0b5b167) }, + /* 49 */ { 11, CNST_LIMB(0x2d9832759d5369c4), CNST_LIMB(0xb3abb3faa02166cc), CNST_LIMB(0x3642798750226111), CNST_LIMB(0x2df495ccaa57147b) }, + /* 50 */ { 11, CNST_LIMB(0x2d5beb38dcd1394c), CNST_LIMB(0xb49a784bcd1b8afe), CNST_LIMB(0x43c33c1937564800), CNST_LIMB(0xe392010175ee5962) }, + /* 51 */ { 11, CNST_LIMB(0x2d216f7943e2ba6a), CNST_LIMB(0xb5848226989d33c3), CNST_LIMB(0x54411b2441c3cd8b), CNST_LIMB(0x84eaf11b2fe7738e) }, + /* 52 */ { 11, CNST_LIMB(0x2ce8a82efbb3ff2c), CNST_LIMB(0xb66a008e4788cbcd), CNST_LIMB(0x6851455acd400000), CNST_LIMB(0x3a1e3971e008995d) }, + /* 53 */ { 11, CNST_LIMB(0x2cb17fea7ad7e332), CNST_LIMB(0xb74b1fd64e0753c6), CNST_LIMB(0x80a23b117c8feb6d), CNST_LIMB(0xfd7a462344ffce25) }, + /* 54 */ { 11, CNST_LIMB(0x2c7be2b0cfa1ba50), CNST_LIMB(0xb82809d5be7072db), CNST_LIMB(0x9dff7d32d5dc1800), CNST_LIMB(0x9eca40b40ebcef8a) }, + /* 55 */ { 11, CNST_LIMB(0x2c47bddba92d7463), CNST_LIMB(0xb900e6160002ccfe), CNST_LIMB(0xc155af6faeffe6a7), CNST_LIMB(0x52fa161a4a48e43d) }, + /* 56 */ { 11, CNST_LIMB(0x2c14fffcaa8b131e), CNST_LIMB(0xb9d5d9fd5010b366), CNST_LIMB(0xebb7392e00000000), CNST_LIMB(0x1607a2cbacf930c1) }, + /* 57 */ { 10, CNST_LIMB(0x2be398c3a38be053), CNST_LIMB(0xbaa708f58014d37c), CNST_LIMB(0x50633659656d971), CNST_LIMB(0x97a014f8e3be55f1) }, + /* 58 */ { 10, CNST_LIMB(0x2bb378e758451068), CNST_LIMB(0xbb74948f5532da4b), CNST_LIMB(0x5fa8624c7fba400), CNST_LIMB(0x568df8b76cbf212c) }, + /* 59 */ { 10, CNST_LIMB(0x2b8492108be5e5f7), CNST_LIMB(0xbc3e9ca2e1a05533), CNST_LIMB(0x717d9faa73c5679), CNST_LIMB(0x20ba7c4b4e6ef492) }, + /* 60 */ { 10, CNST_LIMB(0x2b56d6c70d55481b), CNST_LIMB(0xbd053f6d26089673), CNST_LIMB(0x86430aac6100000), CNST_LIMB(0xe81ee46b9ef492f5) }, + /* 61 */ { 10, CNST_LIMB(0x2b2a3a608c72ddd5), CNST_LIMB(0xbdc899ab3ff56c5e), CNST_LIMB(0x9e64d9944b57f29), CNST_LIMB(0x9dc0d10d51940416) }, + /* 62 */ { 10, CNST_LIMB(0x2afeb0f1060c7e41), CNST_LIMB(0xbe88c6b3626a72aa), CNST_LIMB(0xba5ca5392cb0400), CNST_LIMB(0x5fa8ed2f450272a5) }, + /* 63 */ { 10, CNST_LIMB(0x2ad42f3c9aca595c), CNST_LIMB(0xbf45e08bcf06554e), CNST_LIMB(0xdab2ce1d022cd81), CNST_LIMB(0x2ba9eb8c5e04e641) }, + /* 64 */ { 10, CNST_LIMB(0x2aaaaaaaaaaaaaaa), CNST_LIMB(0xbfffffffffffffff), CNST_LIMB(0x6), CNST_LIMB(0x0) }, + /* 65 */ { 10, CNST_LIMB(0x2a82193a13425883), CNST_LIMB(0xc0b73cb42e16914c), CNST_LIMB(0x12aeed5fd3e2d281), CNST_LIMB(0xb67759cc00287bf1) }, + /* 66 */ { 10, CNST_LIMB(0x2a5a717672f66450), CNST_LIMB(0xc16bad3758efd873), CNST_LIMB(0x15c3da1572d50400), CNST_LIMB(0x78621feeb7f4ed33) }, + /* 67 */ { 10, CNST_LIMB(0x2a33aa6e56d9c71c), CNST_LIMB(0xc21d6713f453f356), CNST_LIMB(0x194c05534f75ee29), CNST_LIMB(0x43d55b5f72943bc0) }, + /* 68 */ { 10, CNST_LIMB(0x2a0dbbaa3bdfcea4), CNST_LIMB(0xc2cc7edf592262cf), CNST_LIMB(0x1d56299ada100000), CNST_LIMB(0x173decb64d1d4409) }, + /* 69 */ { 10, CNST_LIMB(0x29e89d244eb4bfaf), CNST_LIMB(0xc379084815b5774c), CNST_LIMB(0x21f2a089a4ff4f79), CNST_LIMB(0xe29fb54fd6b6074f) }, + /* 70 */ { 10, CNST_LIMB(0x29c44740d7db51e6), CNST_LIMB(0xc4231623369e78e5), CNST_LIMB(0x2733896c68d9a400), CNST_LIMB(0xa1f1f5c210d54e62) }, + /* 71 */ { 10, CNST_LIMB(0x29a0b2c743b14d74), CNST_LIMB(0xc4caba789e2b8687), CNST_LIMB(0x2d2cf2c33b533c71), CNST_LIMB(0x6aac7f9bfafd57b2) }, + /* 72 */ { 10, CNST_LIMB(0x297dd8dbb7c22a2d), CNST_LIMB(0xc570068e7ef5a1e7), CNST_LIMB(0x33f506e440000000), CNST_LIMB(0x3b563c2478b72ee2) }, + /* 73 */ { 10, CNST_LIMB(0x295bb2f9285c8c1b), CNST_LIMB(0xc6130af40bc0ecbf), CNST_LIMB(0x3ba43bec1d062211), CNST_LIMB(0x12b536b574e92d1b) }, + /* 74 */ { 10, CNST_LIMB(0x293a3aebe2be1c92), CNST_LIMB(0xc6b3d78b6d3b24fb), CNST_LIMB(0x4455872d8fd4e400), CNST_LIMB(0xdf86c03020404fa5) }, + /* 75 */ { 10, CNST_LIMB(0x29196acc815ebd9f), CNST_LIMB(0xc7527b930c965bf2), CNST_LIMB(0x4e2694539f2f6c59), CNST_LIMB(0xa34adf02234eea8e) }, + /* 76 */ { 10, CNST_LIMB(0x28f93cfb40f5c22a), CNST_LIMB(0xc7ef05ae409a0288), CNST_LIMB(0x5938006c18900000), CNST_LIMB(0x6f46eb8574eb59dd) }, + /* 77 */ { 10, CNST_LIMB(0x28d9ac1badc64117), CNST_LIMB(0xc88983ed6985bae5), CNST_LIMB(0x65ad9912474aa649), CNST_LIMB(0x42459b481df47cec) }, + /* 78 */ { 10, CNST_LIMB(0x28bab310a196b478), CNST_LIMB(0xc92203d587039cc1), CNST_LIMB(0x73ae9ff4241ec400), CNST_LIMB(0x1b424b95d80ca505) }, + /* 79 */ { 10, CNST_LIMB(0x289c4cf88b774469), CNST_LIMB(0xc9b892675266f66c), CNST_LIMB(0x836612ee9c4ce1e1), CNST_LIMB(0xf2c1b982203a0dac) }, + /* 80 */ { 10, CNST_LIMB(0x287e7529fb244e91), CNST_LIMB(0xca4d3c25e68dc57f), CNST_LIMB(0x9502f90000000000), CNST_LIMB(0xb7cdfd9d7bdbab7d) }, + /* 81 */ { 10, CNST_LIMB(0x286127306a6a7a53), CNST_LIMB(0xcae00d1cfdeb43cf), CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, + /* 82 */ { 10, CNST_LIMB(0x28445ec93f792b1e), CNST_LIMB(0xcb7110e6ce866f2b), CNST_LIMB(0xbebf59a07dab4400), CNST_LIMB(0x57931eeaf85cf64f) }, + /* 83 */ { 10, CNST_LIMB(0x282817e1038950fa), CNST_LIMB(0xcc0052b18b0e2a19), CNST_LIMB(0xd7540d4093bc3109), CNST_LIMB(0x305a944507c82f47) }, + /* 84 */ { 10, CNST_LIMB(0x280c4e90c9ab1f45), CNST_LIMB(0xcc8ddd448f8b845a), CNST_LIMB(0xf2b96616f1900000), CNST_LIMB(0xe007ccc9c22781a) }, + /* 85 */ { 9, CNST_LIMB(0x27f0ff1bc1ee87cd), CNST_LIMB(0xcd19bb053fb0284e), CNST_LIMB(0x336de62af2bca35), CNST_LIMB(0x3e92c42e000eeed4) }, + /* 86 */ { 9, CNST_LIMB(0x27d625ecf571c340), CNST_LIMB(0xcda3f5fb9c415052), CNST_LIMB(0x39235ec33d49600), CNST_LIMB(0x1ebe59130db2795e) }, + /* 87 */ { 9, CNST_LIMB(0x27bbbf95282fcd45), CNST_LIMB(0xce2c97d694adab3f), CNST_LIMB(0x3f674e539585a17), CNST_LIMB(0x268859e90f51b89) }, + /* 88 */ { 9, CNST_LIMB(0x27a1c8c8ddaf84da), CNST_LIMB(0xceb3a9f01975077f), CNST_LIMB(0x4645b6958000000), CNST_LIMB(0xd24cde0463108cfa) }, + /* 89 */ { 9, CNST_LIMB(0x27883e5e7df3f518), CNST_LIMB(0xcf393550f3aa6906), CNST_LIMB(0x4dcb74afbc49c19), CNST_LIMB(0xa536009f37adc383) }, + /* 90 */ { 9, CNST_LIMB(0x276f1d4c9847e90e), CNST_LIMB(0xcfbd42b465836767), CNST_LIMB(0x56064e1d18d9a00), CNST_LIMB(0x7cea06ce1c9ace10) }, + /* 91 */ { 9, CNST_LIMB(0x275662a841b30191), CNST_LIMB(0xd03fda8b97997f33), CNST_LIMB(0x5f04fe2cd8a39fb), CNST_LIMB(0x58db032e72e8ba43) }, + /* 92 */ { 9, CNST_LIMB(0x273e0ba38d15a47b), CNST_LIMB(0xd0c10500d63aa658), CNST_LIMB(0x68d74421f5c0000), CNST_LIMB(0x388cc17cae105447) }, + /* 93 */ { 9, CNST_LIMB(0x2726158c1b13cf03), CNST_LIMB(0xd140c9faa1e5439e), CNST_LIMB(0x738df1f6ab4827d), CNST_LIMB(0x1b92672857620ce0) }, + /* 94 */ { 9, CNST_LIMB(0x270e7dc9c01d8e9b), CNST_LIMB(0xd1bf311e95d00de3), CNST_LIMB(0x7f3afbc9cfb5e00), CNST_LIMB(0x18c6a9575c2ade4) }, + /* 95 */ { 9, CNST_LIMB(0x26f741dd3f070d61), CNST_LIMB(0xd23c41d42727c808), CNST_LIMB(0x8bf187fba88f35f), CNST_LIMB(0xd44da7da8e44b24f) }, + /* 96 */ { 9, CNST_LIMB(0x26e05f5f16c2159e), CNST_LIMB(0xd2b803473f7ad0f3), CNST_LIMB(0x99c600000000000), CNST_LIMB(0xaa2f78f1b4cc6794) }, + /* 97 */ { 9, CNST_LIMB(0x26c9d3fe61e80598), CNST_LIMB(0xd3327c6ab49ca6c8), CNST_LIMB(0xa8ce21eb6531361), CNST_LIMB(0x843c067d091ee4cc) }, + /* 98 */ { 9, CNST_LIMB(0x26b39d7fc6ddab08), CNST_LIMB(0xd3abb3faa02166cc), CNST_LIMB(0xb92112c1a0b6200), CNST_LIMB(0x62005e1e913356e3) }, + /* 99 */ { 9, CNST_LIMB(0x269db9bc7772a5cc), CNST_LIMB(0xd423b07e986aa967), CNST_LIMB(0xcad7718b8747c43), CNST_LIMB(0x4316eed01dedd518) }, + /* 100 */ { 9, CNST_LIMB(0x268826a13ef3fde6), CNST_LIMB(0xd49a784bcd1b8afe), CNST_LIMB(0xde0b6b3a7640000), CNST_LIMB(0x2725dd1d243aba0e) }, + /* 101 */ { 9, CNST_LIMB(0x2672e22d9dbdbd9f), CNST_LIMB(0xd510118708a8f8dd), CNST_LIMB(0xf2d8cf5fe6d74c5), CNST_LIMB(0xddd9057c24cb54f) }, + /* 102 */ { 9, CNST_LIMB(0x265dea72f169cc99), CNST_LIMB(0xd5848226989d33c3), CNST_LIMB(0x1095d25bfa712600), CNST_LIMB(0xedeee175a736d2a1) }, + /* 103 */ { 9, CNST_LIMB(0x26493d93a8cb2514), CNST_LIMB(0xd5f7cff41e09aeb8), CNST_LIMB(0x121b7c4c3698faa7), CNST_LIMB(0xc4699f3df8b6b328) }, + /* 104 */ { 9, CNST_LIMB(0x2634d9c282f3ef82), CNST_LIMB(0xd66a008e4788cbcd), CNST_LIMB(0x13c09e8d68000000), CNST_LIMB(0x9ebbe7d859cb5a7c) }, + /* 105 */ { 9, CNST_LIMB(0x2620bd41d8933adc), CNST_LIMB(0xd6db196a761949d9), CNST_LIMB(0x15876ccb0b709ca9), CNST_LIMB(0x7c828b9887eb2179) }, + /* 106 */ { 9, CNST_LIMB(0x260ce662ef04088a), CNST_LIMB(0xd74b1fd64e0753c6), CNST_LIMB(0x17723c2976da2a00), CNST_LIMB(0x5d652ab99001adcf) }, + /* 107 */ { 9, CNST_LIMB(0x25f95385547353fd), CNST_LIMB(0xd7ba18f93502e409), CNST_LIMB(0x198384e9c259048b), CNST_LIMB(0x4114f1754e5d7b32) }, + /* 108 */ { 9, CNST_LIMB(0x25e60316448db8e1), CNST_LIMB(0xd82809d5be7072db), CNST_LIMB(0x1bbde41dfeec0000), CNST_LIMB(0x274b7c902f7e0188) }, + /* 109 */ { 9, CNST_LIMB(0x25d2f390152f74f5), CNST_LIMB(0xd894f74b06ef8b40), CNST_LIMB(0x1e241d6e3337910d), CNST_LIMB(0xfc9e0fbb32e210c) }, + /* 110 */ { 9, CNST_LIMB(0x25c02379aa9ad043), CNST_LIMB(0xd900e6160002ccfe), CNST_LIMB(0x20b91cee9901ee00), CNST_LIMB(0xf4afa3e594f8ea1f) }, + /* 111 */ { 9, CNST_LIMB(0x25ad9165f2c18907), CNST_LIMB(0xd96bdad2acb5f5ef), CNST_LIMB(0x237ff9079863dfef), CNST_LIMB(0xcd85c32e9e4437b0) }, + /* 112 */ { 9, CNST_LIMB(0x259b3bf36735c90c), CNST_LIMB(0xd9d5d9fd5010b366), CNST_LIMB(0x267bf47000000000), CNST_LIMB(0xa9bbb147e0dd92a8) }, + /* 113 */ { 9, CNST_LIMB(0x258921cb955e7693), CNST_LIMB(0xda3ee7f38e181ed0), CNST_LIMB(0x29b08039fbeda7f1), CNST_LIMB(0x8900447b70e8eb82) }, + /* 114 */ { 9, CNST_LIMB(0x257741a2ac9170af), CNST_LIMB(0xdaa708f58014d37c), CNST_LIMB(0x2d213df34f65f200), CNST_LIMB(0x6b0a92adaad5848a) }, + /* 115 */ { 9, CNST_LIMB(0x25659a3711bc827d), CNST_LIMB(0xdb0e4126bcc86bd7), CNST_LIMB(0x30d201d957a7c2d3), CNST_LIMB(0x4f990ad8740f0ee5) }, + /* 116 */ { 9, CNST_LIMB(0x25542a50f84b9c39), CNST_LIMB(0xdb74948f5532da4b), CNST_LIMB(0x34c6d52160f40000), CNST_LIMB(0x3670a9663a8d3610) }, + /* 117 */ { 9, CNST_LIMB(0x2542f0c20000377d), CNST_LIMB(0xdbda071cc67e6db5), CNST_LIMB(0x3903f855d8f4c755), CNST_LIMB(0x1f5c44188057be3c) }, + /* 118 */ { 9, CNST_LIMB(0x2531ec64d772bd64), CNST_LIMB(0xdc3e9ca2e1a05533), CNST_LIMB(0x3d8de5c8ec59b600), CNST_LIMB(0xa2bea956c4e4977) }, + /* 119 */ { 9, CNST_LIMB(0x25211c1ce2fb5a6e), CNST_LIMB(0xdca258dca9331635), CNST_LIMB(0x4269541d1ff01337), CNST_LIMB(0xed68b23033c3637e) }, + /* 120 */ { 9, CNST_LIMB(0x25107ed5e7c3ec3b), CNST_LIMB(0xdd053f6d26089673), CNST_LIMB(0x479b38e478000000), CNST_LIMB(0xc99cf624e50549c5) }, + /* 121 */ { 9, CNST_LIMB(0x25001383bac8a744), CNST_LIMB(0xdd6753e032ea0efe), CNST_LIMB(0x4d28cb56c33fa539), CNST_LIMB(0xa8adf7ae45e7577b) }, + /* 122 */ { 9, CNST_LIMB(0x24efd921f390bce3), CNST_LIMB(0xddc899ab3ff56c5e), CNST_LIMB(0x5317871fa13aba00), CNST_LIMB(0x8a5bc740b1c113e5) }, + /* 123 */ { 9, CNST_LIMB(0x24dfceb3a26bb203), CNST_LIMB(0xde29142e0e01401f), CNST_LIMB(0x596d2f44de9fa71b), CNST_LIMB(0x6e6c7efb81cfbb9b) }, + /* 124 */ { 9, CNST_LIMB(0x24cff3430a0341a7), CNST_LIMB(0xde88c6b3626a72aa), CNST_LIMB(0x602fd125c47c0000), CNST_LIMB(0x54aba5c5cada5f10) }, + /* 125 */ { 9, CNST_LIMB(0x24c045e15c149931), CNST_LIMB(0xdee7b471b3a9507d), CNST_LIMB(0x6765c793fa10079d), CNST_LIMB(0x3ce9a36f23c0fc90) }, + /* 126 */ { 9, CNST_LIMB(0x24b0c5a679267ae2), CNST_LIMB(0xdf45e08bcf06554e), CNST_LIMB(0x6f15be069b847e00), CNST_LIMB(0x26fb43de2c8cd2a8) }, + /* 127 */ { 9, CNST_LIMB(0x24a171b0b31461c8), CNST_LIMB(0xdfa34e1177c23362), CNST_LIMB(0x7746b3e82a77047f), CNST_LIMB(0x12b94793db8486a1) }, + /* 128 */ { 9, CNST_LIMB(0x2492492492492492), CNST_LIMB(0xdfffffffffffffff), CNST_LIMB(0x7), CNST_LIMB(0x0) }, + /* 129 */ { 9, CNST_LIMB(0x24834b2c9d85cdfe), CNST_LIMB(0xe05bf942dbbc2145), CNST_LIMB(0x894953f7ea890481), CNST_LIMB(0xdd5deca404c0156d) }, + /* 130 */ { 9, CNST_LIMB(0x247476f924137501), CNST_LIMB(0xe0b73cb42e16914c), CNST_LIMB(0x932abffea4848200), CNST_LIMB(0xbd51373330291de0) }, + /* 131 */ { 9, CNST_LIMB(0x2465cbc00a40cec0), CNST_LIMB(0xe111cd1d5133412e), CNST_LIMB(0x9dacb687d3d6a163), CNST_LIMB(0x9fa4025d66f23085) }, + /* 132 */ { 9, CNST_LIMB(0x245748bc980e0427), CNST_LIMB(0xe16bad3758efd873), CNST_LIMB(0xa8d8102a44840000), CNST_LIMB(0x842530ee2db4949d) }, + /* 133 */ { 9, CNST_LIMB(0x2448ed2f49eb0633), CNST_LIMB(0xe1c4dfab90aab5ef), CNST_LIMB(0xb4b60f9d140541e5), CNST_LIMB(0x6aa7f2766b03dc25) }, + /* 134 */ { 9, CNST_LIMB(0x243ab85da36e3167), CNST_LIMB(0xe21d6713f453f356), CNST_LIMB(0xc15065d4856e4600), CNST_LIMB(0x53035ba7ebf32e8d) }, + /* 135 */ { 9, CNST_LIMB(0x242ca99203ea8c18), CNST_LIMB(0xe27545fba4fe385a), CNST_LIMB(0xceb1363f396d23c7), CNST_LIMB(0x3d12091fc9fb4914) }, + /* 136 */ { 9, CNST_LIMB(0x241ec01b7cce4ea0), CNST_LIMB(0xe2cc7edf592262cf), CNST_LIMB(0xdce31b2488000000), CNST_LIMB(0x28b1cb81b1ef1849) }, + /* 137 */ { 9, CNST_LIMB(0x2410fb4da9b3b0fc), CNST_LIMB(0xe323142dc8c66b55), CNST_LIMB(0xebf12a24bca135c9), CNST_LIMB(0x15c35be67ae3e2c9) }, + /* 138 */ { 9, CNST_LIMB(0x24035a808a0f315e), CNST_LIMB(0xe379084815b5774c), CNST_LIMB(0xfbe6f8dbf88f4a00), CNST_LIMB(0x42a17bd09be1ff0) }, + /* 139 */ { 8, CNST_LIMB(0x23f5dd105c67ab9d), CNST_LIMB(0xe3ce5d822ff4b643), CNST_LIMB(0x1ef156c084ce761), CNST_LIMB(0x8bf461f03cf0bbf) }, + /* 140 */ { 8, CNST_LIMB(0x23e8825d7b05abb1), CNST_LIMB(0xe4231623369e78e5), CNST_LIMB(0x20c4e3b94a10000), CNST_LIMB(0xf3fbb43f68a32d05) }, + /* 141 */ { 8, CNST_LIMB(0x23db49cc3a0866fe), CNST_LIMB(0xe4773465d54aded7), CNST_LIMB(0x22b0695a08ba421), CNST_LIMB(0xd84f44c48564dc19) }, + /* 142 */ { 8, CNST_LIMB(0x23ce32c4c6cfb9f5), CNST_LIMB(0xe4caba789e2b8687), CNST_LIMB(0x24b4f35d7a4c100), CNST_LIMB(0xbe58ebcce7956abe) }, + /* 143 */ { 8, CNST_LIMB(0x23c13cb308ab6ab7), CNST_LIMB(0xe51daa7e60fdd34c), CNST_LIMB(0x26d397284975781), CNST_LIMB(0xa5fac463c7c134b7) }, + /* 144 */ { 8, CNST_LIMB(0x23b4670682c0c709), CNST_LIMB(0xe570068e7ef5a1e7), CNST_LIMB(0x290d74100000000), CNST_LIMB(0x8f19241e28c7d757) }, + /* 145 */ { 8, CNST_LIMB(0x23a7b13237187c8b), CNST_LIMB(0xe5c1d0b53bc09fca), CNST_LIMB(0x2b63b3a37866081), CNST_LIMB(0x799a6d046c0ae1ae) }, + /* 146 */ { 8, CNST_LIMB(0x239b1aac8ac74728), CNST_LIMB(0xe6130af40bc0ecbf), CNST_LIMB(0x2dd789f4d894100), CNST_LIMB(0x6566e37d746a9e40) }, + /* 147 */ { 8, CNST_LIMB(0x238ea2ef2b24c379), CNST_LIMB(0xe663b741df9c37c0), CNST_LIMB(0x306a35e51b58721), CNST_LIMB(0x526887dbfb5f788f) }, + /* 148 */ { 8, CNST_LIMB(0x23824976f4045a26), CNST_LIMB(0xe6b3d78b6d3b24fb), CNST_LIMB(0x331d01712e10000), CNST_LIMB(0x408af3382b8efd3d) }, + /* 149 */ { 8, CNST_LIMB(0x23760dc3d6e4d729), CNST_LIMB(0xe7036db376537b90), CNST_LIMB(0x35f14200a827c61), CNST_LIMB(0x2fbb374806ec05f1) }, + /* 150 */ { 8, CNST_LIMB(0x2369ef58c30bd43e), CNST_LIMB(0xe7527b930c965bf2), CNST_LIMB(0x38e858b62216100), CNST_LIMB(0x1fe7c0f0afce87fe) }, + /* 151 */ { 8, CNST_LIMB(0x235dedbb8e82aa1c), CNST_LIMB(0xe7a102f9d39a9331), CNST_LIMB(0x3c03b2c13176a41), CNST_LIMB(0x11003d517540d32e) }, + /* 152 */ { 8, CNST_LIMB(0x23520874dfeb1ffd), CNST_LIMB(0xe7ef05ae409a0288), CNST_LIMB(0x3f44c9b21000000), CNST_LIMB(0x2f5810f98eff0dc) }, + /* 153 */ { 8, CNST_LIMB(0x23463f1019228dd7), CNST_LIMB(0xe83c856dd81804b7), CNST_LIMB(0x42ad23cef3113c1), CNST_LIMB(0xeb72e35e7840d910) }, + /* 154 */ { 8, CNST_LIMB(0x233a911b42aa9b3c), CNST_LIMB(0xe88983ed6985bae5), CNST_LIMB(0x463e546b19a2100), CNST_LIMB(0xd27de19593dc3614) }, + /* 155 */ { 8, CNST_LIMB(0x232efe26f7cf33f9), CNST_LIMB(0xe8d602d948f83829), CNST_LIMB(0x49f9fc3f96684e1), CNST_LIMB(0xbaf391fd3e5e6fc2) }, + /* 156 */ { 8, CNST_LIMB(0x232385c65381b485), CNST_LIMB(0xe92203d587039cc1), CNST_LIMB(0x4de1c9c5dc10000), CNST_LIMB(0xa4bd38c55228c81d) }, + /* 157 */ { 8, CNST_LIMB(0x2318278edde1b39b), CNST_LIMB(0xe96d887e26cd57b7), CNST_LIMB(0x51f77994116d2a1), CNST_LIMB(0x8fc5a8de8e1de782) }, + /* 158 */ { 8, CNST_LIMB(0x230ce3187a6c2be9), CNST_LIMB(0xe9b892675266f66c), CNST_LIMB(0x563cd6bb3398100), CNST_LIMB(0x7bf9265bea9d3a3b) }, + /* 159 */ { 8, CNST_LIMB(0x2301b7fd56ca21bb), CNST_LIMB(0xea03231d8d8224ba), CNST_LIMB(0x5ab3bb270beeb01), CNST_LIMB(0x69454b325983dccd) }, + /* 160 */ { 8, CNST_LIMB(0x22f6a5d9da38341c), CNST_LIMB(0xea4d3c25e68dc57f), CNST_LIMB(0x5f5e10000000000), CNST_LIMB(0x5798ee2308c39df9) }, + /* 161 */ { 8, CNST_LIMB(0x22ebac4c9580d89f), CNST_LIMB(0xea96defe264b59be), CNST_LIMB(0x643dce0ec16f501), CNST_LIMB(0x46e40ba0fa66a753) }, + /* 162 */ { 8, CNST_LIMB(0x22e0caf633834beb), CNST_LIMB(0xeae00d1cfdeb43cf), CNST_LIMB(0x6954fe21e3e8100), CNST_LIMB(0x3717b0870b0db3a7) }, + /* 163 */ { 8, CNST_LIMB(0x22d601796a418886), CNST_LIMB(0xeb28c7f233bdd372), CNST_LIMB(0x6ea5b9755f440a1), CNST_LIMB(0x2825e6775d11cdeb) }, + /* 164 */ { 8, CNST_LIMB(0x22cb4f7aec6fd8b4), CNST_LIMB(0xeb7110e6ce866f2b), CNST_LIMB(0x74322a1c0410000), CNST_LIMB(0x1a01a1c09d1b4dac) }, + /* 165 */ { 8, CNST_LIMB(0x22c0b4a15b80d83e), CNST_LIMB(0xebb8e95d3f7d9df2), CNST_LIMB(0x79fc8b6ae8a46e1), CNST_LIMB(0xc9eb0a8bebc8f3e) }, + /* 166 */ { 8, CNST_LIMB(0x22b630953a28f77a), CNST_LIMB(0xec0052b18b0e2a19), CNST_LIMB(0x80072a66d512100), CNST_LIMB(0xffe357ff59e6a004) }, + /* 167 */ { 8, CNST_LIMB(0x22abc300df54ca7c), CNST_LIMB(0xec474e39705912d2), CNST_LIMB(0x86546633b42b9c1), CNST_LIMB(0xe7dfd1be05fa61a8) }, + /* 168 */ { 8, CNST_LIMB(0x22a16b90698da5d2), CNST_LIMB(0xec8ddd448f8b845a), CNST_LIMB(0x8ce6b0861000000), CNST_LIMB(0xd11ed6fc78f760e5) }, + /* 169 */ { 8, CNST_LIMB(0x229729f1b2c83ded), CNST_LIMB(0xecd4011c8f11979a), CNST_LIMB(0x93c08e16a022441), CNST_LIMB(0xbb8db609dd29ebfe) }, + /* 170 */ { 8, CNST_LIMB(0x228cfdd444992f78), CNST_LIMB(0xed19bb053fb0284e), CNST_LIMB(0x9ae49717f026100), CNST_LIMB(0xa71aec8d1813d532) }, + /* 171 */ { 8, CNST_LIMB(0x2282e6e94ccb8588), CNST_LIMB(0xed5f0c3cbf8fa470), CNST_LIMB(0xa25577ae24c1a61), CNST_LIMB(0x93b612a9f20fbc02) }, + /* 172 */ { 8, CNST_LIMB(0x2278e4e392557ecf), CNST_LIMB(0xeda3f5fb9c415052), CNST_LIMB(0xaa15f068e610000), CNST_LIMB(0x814fc7b19a67d317) }, + /* 173 */ { 8, CNST_LIMB(0x226ef7776aa7fd29), CNST_LIMB(0xede87974f3c81855), CNST_LIMB(0xb228d6bf7577921), CNST_LIMB(0x6fd9a03f2e0a4b7c) }, + /* 174 */ { 8, CNST_LIMB(0x22651e5aaf5532d0), CNST_LIMB(0xee2c97d694adab3f), CNST_LIMB(0xba91158ef5c4100), CNST_LIMB(0x5f4615a38d0d316e) }, + /* 175 */ { 8, CNST_LIMB(0x225b5944b40b4694), CNST_LIMB(0xee7052491d2c3e64), CNST_LIMB(0xc351ad9aec0b681), CNST_LIMB(0x4f8876863479a286) }, + /* 176 */ { 8, CNST_LIMB(0x2251a7ee3cdfcca5), CNST_LIMB(0xeeb3a9f01975077f), CNST_LIMB(0xcc6db6100000000), CNST_LIMB(0x4094d8a3041b60eb) }, + /* 177 */ { 8, CNST_LIMB(0x22480a1174e913d9), CNST_LIMB(0xeef69fea211b2627), CNST_LIMB(0xd5e85d09025c181), CNST_LIMB(0x32600b8ed883a09b) }, + /* 178 */ { 8, CNST_LIMB(0x223e7f69e522683c), CNST_LIMB(0xef393550f3aa6906), CNST_LIMB(0xdfc4e816401c100), CNST_LIMB(0x24df8c6eb4b6d1f1) }, + /* 179 */ { 8, CNST_LIMB(0x223507b46b988abe), CNST_LIMB(0xef7b6b399471103e), CNST_LIMB(0xea06b4c72947221), CNST_LIMB(0x18097a8ee151acef) }, + /* 180 */ { 8, CNST_LIMB(0x222ba2af32dbbb9e), CNST_LIMB(0xefbd42b465836767), CNST_LIMB(0xf4b139365210000), CNST_LIMB(0xbd48cc8ec1cd8e3) }, + /* 181 */ { 8, CNST_LIMB(0x22225019a9b4d16c), CNST_LIMB(0xeffebccd41ffcd5c), CNST_LIMB(0xffc80497d520961), CNST_LIMB(0x3807a8d67485fb) }, + /* 182 */ { 8, CNST_LIMB(0x22190fb47b1af172), CNST_LIMB(0xf03fda8b97997f33), CNST_LIMB(0x10b4ebfca1dee100), CNST_LIMB(0xea5768860b62e8d8) }, + /* 183 */ { 8, CNST_LIMB(0x220fe14186679801), CNST_LIMB(0xf0809cf27f703d52), CNST_LIMB(0x117492de921fc141), CNST_LIMB(0xd54faf5b635c5005) }, + /* 184 */ { 8, CNST_LIMB(0x2206c483d7c6b786), CNST_LIMB(0xf0c10500d63aa658), CNST_LIMB(0x123bb2ce41000000), CNST_LIMB(0xc14a56233a377926) }, + /* 185 */ { 8, CNST_LIMB(0x21fdb93fa0e0ccc5), CNST_LIMB(0xf10113b153c8ea7b), CNST_LIMB(0x130a8b6157bdecc1), CNST_LIMB(0xae39a88db7cd329f) }, + /* 186 */ { 8, CNST_LIMB(0x21f4bf3a31bcdcaa), CNST_LIMB(0xf140c9faa1e5439e), CNST_LIMB(0x13e15dede0e8a100), CNST_LIMB(0x9c10bde69efa7ab6) }, + /* 187 */ { 8, CNST_LIMB(0x21ebd639f1d86584), CNST_LIMB(0xf18028cf72976a4e), CNST_LIMB(0x14c06d941c0ca7e1), CNST_LIMB(0x8ac36c42a2836497) }, + /* 188 */ { 8, CNST_LIMB(0x21e2fe06597361a6), CNST_LIMB(0xf1bf311e95d00de3), CNST_LIMB(0x15a7ff487a810000), CNST_LIMB(0x7a463c8b84f5ef67) }, + /* 189 */ { 8, CNST_LIMB(0x21da3667eb0e8ccb), CNST_LIMB(0xf1fde3d30e812642), CNST_LIMB(0x169859ddc5c697a1), CNST_LIMB(0x6a8e5f5ad090fd4b) }, + /* 190 */ { 8, CNST_LIMB(0x21d17f282d1a300e), CNST_LIMB(0xf23c41d42727c808), CNST_LIMB(0x1791c60f6fed0100), CNST_LIMB(0x5b91a2943596fc56) }, + /* 191 */ { 8, CNST_LIMB(0x21c8d811a3d3c9e1), CNST_LIMB(0xf27a4c0585cbf805), CNST_LIMB(0x18948e8c0e6fba01), CNST_LIMB(0x4d4667b1c468e8f0) }, + /* 192 */ { 8, CNST_LIMB(0x21c040efcb50f858), CNST_LIMB(0xf2b803473f7ad0f3), CNST_LIMB(0x19a1000000000000), CNST_LIMB(0x3fa39ab547994daf) }, + /* 193 */ { 8, CNST_LIMB(0x21b7b98f11b61c1a), CNST_LIMB(0xf2f56875eb3f2614), CNST_LIMB(0x1ab769203dafc601), CNST_LIMB(0x32a0a9b2faee1e2a) }, + /* 194 */ { 8, CNST_LIMB(0x21af41bcd19739ba), CNST_LIMB(0xf3327c6ab49ca6c8), CNST_LIMB(0x1bd81ab557f30100), CNST_LIMB(0x26357ceac0e96962) }, + /* 195 */ { 8, CNST_LIMB(0x21a6d9474c81adf0), CNST_LIMB(0xf36f3ffb6d916240), CNST_LIMB(0x1d0367a69fed1ba1), CNST_LIMB(0x1a5a6f65caa5859e) }, + /* 196 */ { 8, CNST_LIMB(0x219e7ffda5ad572a), CNST_LIMB(0xf3abb3faa02166cc), CNST_LIMB(0x1e39a5057d810000), CNST_LIMB(0xf08480f672b4e86) }, + /* 197 */ { 8, CNST_LIMB(0x219635afdcd3e46d), CNST_LIMB(0xf3e7d9379f70166a), CNST_LIMB(0x1f7b2a18f29ac3e1), CNST_LIMB(0x4383340615612ca) }, + /* 198 */ { 8, CNST_LIMB(0x218dfa2ec92d0643), CNST_LIMB(0xf423b07e986aa967), CNST_LIMB(0x20c850694c2aa100), CNST_LIMB(0xf3c77969ee4be5a2) }, + /* 199 */ { 8, CNST_LIMB(0x2185cd4c148e4ae2), CNST_LIMB(0xf45f3a98a20738a4), CNST_LIMB(0x222173cc014980c1), CNST_LIMB(0xe00993cc187c5ec9) }, + /* 200 */ { 8, CNST_LIMB(0x217daeda36ad7a5c), CNST_LIMB(0xf49a784bcd1b8afe), CNST_LIMB(0x2386f26fc1000000), CNST_LIMB(0xcd2b297d889bc2b6) }, + /* 201 */ { 8, CNST_LIMB(0x21759eac708452fe), CNST_LIMB(0xf4d56a5b33cec44a), CNST_LIMB(0x24f92ce8af296d41), CNST_LIMB(0xbb214d5064862b22) }, + /* 202 */ { 8, CNST_LIMB(0x216d9c96c7d490d4), CNST_LIMB(0xf510118708a8f8dd), CNST_LIMB(0x2678863cd0ece100), CNST_LIMB(0xa9e1a7ca7ea10e20) }, + /* 203 */ { 8, CNST_LIMB(0x2165a86e02cb358c), CNST_LIMB(0xf54a6e8ca5438db1), CNST_LIMB(0x280563f0a9472d61), CNST_LIMB(0x99626e72b39ea0cf) }, + /* 204 */ { 8, CNST_LIMB(0x215dc207a3c20fdf), CNST_LIMB(0xf5848226989d33c3), CNST_LIMB(0x29a02e1406210000), CNST_LIMB(0x899a5ba9c13fafd9) }, + /* 205 */ { 8, CNST_LIMB(0x2155e939e51e8b37), CNST_LIMB(0xf5be4d0cb51434aa), CNST_LIMB(0x2b494f4efe6d2e21), CNST_LIMB(0x7a80a705391e96ff) }, + /* 206 */ { 8, CNST_LIMB(0x214e1ddbb54cd933), CNST_LIMB(0xf5f7cff41e09aeb8), CNST_LIMB(0x2d0134ef21cbc100), CNST_LIMB(0x6c0cfe23de23042a) }, + /* 207 */ { 8, CNST_LIMB(0x21465fc4b2d68f98), CNST_LIMB(0xf6310b8f55304840), CNST_LIMB(0x2ec84ef4da2ef581), CNST_LIMB(0x5e377df359c944dd) }, + /* 208 */ { 8, CNST_LIMB(0x213eaecd2893dd60), CNST_LIMB(0xf66a008e4788cbcd), CNST_LIMB(0x309f102100000000), CNST_LIMB(0x50f8ac5fc8f53985) }, + /* 209 */ { 8, CNST_LIMB(0x21370ace09f681c6), CNST_LIMB(0xf6a2af9e5a0f0a08), CNST_LIMB(0x3285ee02a1420281), CNST_LIMB(0x44497266278e35b7) }, + /* 210 */ { 8, CNST_LIMB(0x212f73a0ef6db7cb), CNST_LIMB(0xf6db196a761949d9), CNST_LIMB(0x347d6104fc324100), CNST_LIMB(0x382316831f7ee175) }, + /* 211 */ { 8, CNST_LIMB(0x2127e92012e25004), CNST_LIMB(0xf7133e9b156c7be5), CNST_LIMB(0x3685e47dade53d21), CNST_LIMB(0x2c7f377833b8946e) }, + /* 212 */ { 8, CNST_LIMB(0x21206b264c4a39a7), CNST_LIMB(0xf74b1fd64e0753c6), CNST_LIMB(0x389ff6bb15610000), CNST_LIMB(0x2157c761ab4163ef) }, + /* 213 */ { 8, CNST_LIMB(0x2118f98f0e52c28f), CNST_LIMB(0xf782bdbfdda6577b), CNST_LIMB(0x3acc1912ebb57661), CNST_LIMB(0x16a7071803cc49a9) }, + /* 214 */ { 8, CNST_LIMB(0x211194366320dc66), CNST_LIMB(0xf7ba18f93502e409), CNST_LIMB(0x3d0acff111946100), CNST_LIMB(0xc6781d80f8224fc) }, + /* 215 */ { 8, CNST_LIMB(0x210a3af8e926bb78), CNST_LIMB(0xf7f1322182cf15d1), CNST_LIMB(0x3f5ca2e692eaf841), CNST_LIMB(0x294092d370a900b) }, + /* 216 */ { 8, CNST_LIMB(0x2102edb3d00e29a6), CNST_LIMB(0xf82809d5be7072db), CNST_LIMB(0x41c21cb8e1000000), CNST_LIMB(0xf24f62335024a295) }, + /* 217 */ { 8, CNST_LIMB(0x20fbac44d5b6edc2), CNST_LIMB(0xf85ea0b0b27b2610), CNST_LIMB(0x443bcb714399a5c1), CNST_LIMB(0xe03b98f103fad6d2) }, + /* 218 */ { 8, CNST_LIMB(0x20f4768a4348ad08), CNST_LIMB(0xf894f74b06ef8b40), CNST_LIMB(0x46ca406c81af2100), CNST_LIMB(0xcee3d32cad2a9049) }, + /* 219 */ { 8, CNST_LIMB(0x20ed4c62ea57b1f0), CNST_LIMB(0xf8cb0e3b4b3bbdb3), CNST_LIMB(0x496e106ac22aaae1), CNST_LIMB(0xbe3f9df9277fdada) }, + /* 220 */ { 8, CNST_LIMB(0x20e62dae221c087a), CNST_LIMB(0xf900e6160002ccfe), CNST_LIMB(0x4c27d39fa5410000), CNST_LIMB(0xae46f0d94c05e933) }, + /* 221 */ { 8, CNST_LIMB(0x20df1a4bc4ba6525), CNST_LIMB(0xf9367f6da0ab2e9c), CNST_LIMB(0x4ef825c296e43ca1), CNST_LIMB(0x9ef2280fb437a33d) }, + /* 222 */ { 8, CNST_LIMB(0x20d8121c2c9e506e), CNST_LIMB(0xf96bdad2acb5f5ef), CNST_LIMB(0x51dfa61f5ad88100), CNST_LIMB(0x9039ff426d3f284b) }, + /* 223 */ { 8, CNST_LIMB(0x20d1150031e51549), CNST_LIMB(0xf9a0f8d3b0e04fde), CNST_LIMB(0x54def7a6d2f16901), CNST_LIMB(0x82178c6d6b51f8f4) }, + /* 224 */ { 8, CNST_LIMB(0x20ca22d927d8f54d), CNST_LIMB(0xf9d5d9fd5010b366), CNST_LIMB(0x57f6c10000000000), CNST_LIMB(0x74843b1ee4c1e053) }, + /* 225 */ { 8, CNST_LIMB(0x20c33b88da7c29aa), CNST_LIMB(0xfa0a7eda4c112ce6), CNST_LIMB(0x5b27ac993df97701), CNST_LIMB(0x6779c7f90dc42f48) }, + /* 226 */ { 8, CNST_LIMB(0x20bc5ef18c233bdf), CNST_LIMB(0xfa3ee7f38e181ed0), CNST_LIMB(0x5e7268b9bbdf8100), CNST_LIMB(0x5af23c74f9ad9fe9) }, + /* 227 */ { 8, CNST_LIMB(0x20b58cf5f31e4526), CNST_LIMB(0xfa7315d02f20c7bd), CNST_LIMB(0x61d7a7932ff3d6a1), CNST_LIMB(0x4ee7eae2acdc617e) }, + /* 228 */ { 8, CNST_LIMB(0x20aec5793770a74d), CNST_LIMB(0xfaa708f58014d37c), CNST_LIMB(0x65581f53c8c10000), CNST_LIMB(0x43556aa2ac262a0b) }, + /* 229 */ { 8, CNST_LIMB(0x20a8085ef096d530), CNST_LIMB(0xfadac1e711c832d1), CNST_LIMB(0x68f48a385b8320e1), CNST_LIMB(0x3835949593b8ddd1) }, + /* 230 */ { 8, CNST_LIMB(0x20a1558b2359c4b1), CNST_LIMB(0xfb0e4126bcc86bd7), CNST_LIMB(0x6cada69ed07c2100), CNST_LIMB(0x2d837fbe78458762) }, + /* 231 */ { 8, CNST_LIMB(0x209aace23fafa72e), CNST_LIMB(0xfb418734a9008bd9), CNST_LIMB(0x70843718cdbf27c1), CNST_LIMB(0x233a7e150a54a555) }, + /* 232 */ { 8, CNST_LIMB(0x20940e491ea988d7), CNST_LIMB(0xfb74948f5532da4b), CNST_LIMB(0x7479027ea1000000), CNST_LIMB(0x19561984a50ff8fe) }, + /* 233 */ { 8, CNST_LIMB(0x208d79a5006d7a47), CNST_LIMB(0xfba769b39e49640e), CNST_LIMB(0x788cd40268f39641), CNST_LIMB(0xfd211159fe3490f) }, + /* 234 */ { 8, CNST_LIMB(0x2086eedb8a3cead3), CNST_LIMB(0xfbda071cc67e6db5), CNST_LIMB(0x7cc07b437ecf6100), CNST_LIMB(0x6aa563e655033e3) }, + /* 235 */ { 8, CNST_LIMB(0x20806dd2c486dcc6), CNST_LIMB(0xfc0c6d447c5dd362), CNST_LIMB(0x8114cc6220762061), CNST_LIMB(0xfbb614b3f2d3b14c) }, + /* 236 */ { 8, CNST_LIMB(0x2079f67119059fae), CNST_LIMB(0xfc3e9ca2e1a05533), CNST_LIMB(0x858aa0135be10000), CNST_LIMB(0xeac0f8837fb05773) }, + /* 237 */ { 8, CNST_LIMB(0x2073889d50e7bf63), CNST_LIMB(0xfc7095ae91e1c760), CNST_LIMB(0x8a22d3b53c54c321), CNST_LIMB(0xda6e4c10e8615ca5) }, + /* 238 */ { 8, CNST_LIMB(0x206d243e9303d929), CNST_LIMB(0xfca258dca9331635), CNST_LIMB(0x8ede496339f34100), CNST_LIMB(0xcab755a8d01fa67f) }, + /* 239 */ { 8, CNST_LIMB(0x2066c93c62170aa8), CNST_LIMB(0xfcd3e6a0ca8906c2), CNST_LIMB(0x93bde80aec3a1481), CNST_LIMB(0xbb95a9ae71aa3e0c) }, + /* 240 */ { 8, CNST_LIMB(0x2060777e9b0db0f6), CNST_LIMB(0xfd053f6d26089673), CNST_LIMB(0x98c29b8100000000), CNST_LIMB(0xad0326c296b4f529) }, + /* 241 */ { 8, CNST_LIMB(0x205a2eed73563032), CNST_LIMB(0xfd3663b27f31d529), CNST_LIMB(0x9ded549671832381), CNST_LIMB(0x9ef9f21eed31b7c1) }, + /* 242 */ { 8, CNST_LIMB(0x2053ef71773d7e6a), CNST_LIMB(0xfd6753e032ea0efe), CNST_LIMB(0xa33f092e0b1ac100), CNST_LIMB(0x91747422be14b0b2) }, + /* 243 */ { 8, CNST_LIMB(0x204db8f388552ea9), CNST_LIMB(0xfd9810643d6614c3), CNST_LIMB(0xa8b8b452291fe821), CNST_LIMB(0x846d550e37b5063d) }, + /* 244 */ { 8, CNST_LIMB(0x20478b5cdbe2bb2f), CNST_LIMB(0xfdc899ab3ff56c5e), CNST_LIMB(0xae5b564ac3a10000), CNST_LIMB(0x77df79e9a96c06f6) }, + /* 245 */ { 8, CNST_LIMB(0x20416696f957cfbf), CNST_LIMB(0xfdf8f02086af2c4b), CNST_LIMB(0xb427f4b3be74c361), CNST_LIMB(0x6bc6019636c7d0c2) }, + /* 246 */ { 8, CNST_LIMB(0x203b4a8bb8d356e7), CNST_LIMB(0xfe29142e0e01401f), CNST_LIMB(0xba1f9a938041e100), CNST_LIMB(0x601c4205aebd9e47) }, + /* 247 */ { 8, CNST_LIMB(0x2035372541ab0f0d), CNST_LIMB(0xfe59063c8822ce56), CNST_LIMB(0xc0435871d1110f41), CNST_LIMB(0x54ddc59756f05016) }, + /* 248 */ { 8, CNST_LIMB(0x202f2c4e08fd6dcc), CNST_LIMB(0xfe88c6b3626a72aa), CNST_LIMB(0xc694446f01000000), CNST_LIMB(0x4a0648979c838c18) }, + /* 249 */ { 8, CNST_LIMB(0x202929f0d04b99e9), CNST_LIMB(0xfeb855f8ca88fb0d), CNST_LIMB(0xcd137a5b57ac3ec1), CNST_LIMB(0x3f91b6e0bb3a053d) }, + /* 250 */ { 8, CNST_LIMB(0x20232ff8a41b45eb), CNST_LIMB(0xfee7b471b3a9507d), CNST_LIMB(0xd3c21bcecceda100), CNST_LIMB(0x357c299a88ea76a5) }, + /* 251 */ { 8, CNST_LIMB(0x201d3e50daa036db), CNST_LIMB(0xff16e281db76303b), CNST_LIMB(0xdaa150410b788de1), CNST_LIMB(0x2bc1e517aecc56e3) }, + /* 252 */ { 8, CNST_LIMB(0x201754e5126d446d), CNST_LIMB(0xff45e08bcf06554e), CNST_LIMB(0xe1b24521be010000), CNST_LIMB(0x225f56ceb3da9f5d) }, + /* 253 */ { 8, CNST_LIMB(0x201173a1312ca135), CNST_LIMB(0xff74aef0efafadd7), CNST_LIMB(0xe8f62df12777c1a1), CNST_LIMB(0x1951136d53ad63ac) }, + /* 254 */ { 8, CNST_LIMB(0x200b9a71625f3b13), CNST_LIMB(0xffa34e1177c23362), CNST_LIMB(0xf06e445906fc0100), CNST_LIMB(0x1093d504b3cd7d93) }, + /* 255 */ { 8, CNST_LIMB(0x2005c94216230568), CNST_LIMB(0xffd1be4c7f2af942), CNST_LIMB(0xf81bc845c81bf801), CNST_LIMB(0x824794d1ec1814f) }, + /* 256 */ { 8, CNST_LIMB(0x1fffffffffffffff), CNST_LIMB(0xffffffffffffffff), CNST_LIMB(0x8), CNST_LIMB(0x0) }, }; diff --git a/repos/libports/src/lib/gmp/spec/arm/config.m4 b/repos/libports/src/lib/gmp/spec/arm/config.m4 index 6493df5c9..a09c3b9ea 100644 --- a/repos/libports/src/lib/gmp/spec/arm/config.m4 +++ b/repos/libports/src/lib/gmp/spec/arm/config.m4 @@ -17,7 +17,8 @@ define(<SIZE>, <.size $1,$2>) define(<LSYM_PREFIX>, <.L>) define(<W32>, <.long>) define(<ALIGN_LOGARITHMIC>,<yes>) -define(<SQR_KARATSUBA_THRESHOLD>,<82>) +define(<SQR_TOOM2_THRESHOLD>,<56>) +define(<BMOD_1_TO_MOD_1_THRESHOLD>,<39>) define(<SIZEOF_UNSIGNED>,<4>) define(<GMP_LIMB_BITS>,32) define(<GMP_NAIL_BITS>,0) @@ -28,7 +29,7 @@ ifdef(`__CONFIG_M4_INCLUDED__',,` include(CONFIG_TOP_SRCDIR`/mpn/asm-defs.m4') include_mpn(`arm/arm-defs.m4') define_not_for_expansion(`HAVE_HOST_CPU_armv7l') -define_not_for_expansion(`HAVE_ABI_standard') +define_not_for_expansion(`HAVE_ABI_32') define_not_for_expansion(`HAVE_LIMB_LITTLE_ENDIAN') define_not_for_expansion(`HAVE_DOUBLE_IEEE_LITTLE_ENDIAN') ') diff --git a/repos/libports/src/lib/gmp/spec/arm_64/config.m4 b/repos/libports/src/lib/gmp/spec/arm_64/config.m4 new file mode 100644 index 000000000..9913ffbc3 --- /dev/null +++ b/repos/libports/src/lib/gmp/spec/arm_64/config.m4 @@ -0,0 +1,35 @@ +dnl config.m4. Generated automatically by configure. +changequote(<,>) +ifdef(<__CONFIG_M4_INCLUDED__>,,< +define(<CONFIG_TOP_SRCDIR>,<`../.'>) +define(<WANT_ASSERT>,0) +define(<WANT_PROFILING>,<`no'>) +define(<M4WRAP_SPURIOUS>,<no>) +define(<TEXT>, <.text>) +define(<DATA>, <.data>) +define(<LABEL_SUFFIX>, <:>) +define(<GLOBL>, <.globl>) +define(<GLOBL_ATTR>, <>) +define(<GSYM_PREFIX>, <>) +define(<RODATA>, < .section .rodata>) +define(<TYPE>, <.type $1,@$2>) +define(<SIZE>, <.size $1,$2>) +define(<LSYM_PREFIX>, <.L>) +define(<W32>, <.long>) +define(<ALIGN_LOGARITHMIC>,<yes>) +define(<SQR_TOOM2_THRESHOLD>,<28>) +define(<BMOD_1_TO_MOD_1_THRESHOLD>,<30>) +define(<SIZEOF_UNSIGNED>,<4>) +define(<GMP_LIMB_BITS>,64) +define(<GMP_NAIL_BITS>,0) +define(<GMP_NUMB_BITS>,eval(GMP_LIMB_BITS-GMP_NAIL_BITS)) +>) +changequote(`,') +ifdef(`__CONFIG_M4_INCLUDED__',,` +include(CONFIG_TOP_SRCDIR`/mpn/asm-defs.m4') +define_not_for_expansion(`HAVE_HOST_CPU_aarch64') +define_not_for_expansion(`HAVE_ABI_64') +define_not_for_expansion(`HAVE_LIMB_LITTLE_ENDIAN') +define_not_for_expansion(`HAVE_DOUBLE_IEEE_LITTLE_ENDIAN') +') +define(`__CONFIG_M4_INCLUDED__') diff --git a/repos/libports/src/lib/gmp/spec/x86_32/config.m4 b/repos/libports/src/lib/gmp/spec/x86_32/config.m4 index 445c3387e..2af7e167d 100644 --- a/repos/libports/src/lib/gmp/spec/x86_32/config.m4 +++ b/repos/libports/src/lib/gmp/spec/x86_32/config.m4 @@ -21,7 +21,8 @@ define(<ALIGN_FILL_0x90>,<yes>) define(<HAVE_COFF_TYPE>, <no>) define(<GOT_GSYM_PREFIX>, <>) define(<WANT_SHLDL_CL>, <1>) -define(<SQR_KARATSUBA_THRESHOLD>,<30>) +define(<SQR_TOOM2_THRESHOLD>,<34>) +define(<BMOD_1_TO_MOD_1_THRESHOLD>,<19>) define(<SIZEOF_UNSIGNED>,<4>) define(<GMP_LIMB_BITS>,32) define(<GMP_NAIL_BITS>,0) diff --git a/repos/libports/src/lib/gmp/spec/x86_64/config.m4 b/repos/libports/src/lib/gmp/spec/x86_64/config.m4 index b32aae0d8..bc96db109 100644 --- a/repos/libports/src/lib/gmp/spec/x86_64/config.m4 +++ b/repos/libports/src/lib/gmp/spec/x86_64/config.m4 @@ -18,7 +18,9 @@ define(<LSYM_PREFIX>, <.L>) define(<W32>, <.long>) define(<ALIGN_LOGARITHMIC>,<no>) define(<ALIGN_FILL_0x90>,<yes>) -define(<SQR_KARATSUBA_THRESHOLD>,<32>) +define(<LINUX>,1) +define(<SQR_TOOM2_THRESHOLD>,<34>) +define(<BMOD_1_TO_MOD_1_THRESHOLD>,<21>) define(<SIZEOF_UNSIGNED>,<4>) define(<GMP_LIMB_BITS>,64) define(<GMP_NAIL_BITS>,0) @@ -28,7 +30,7 @@ changequote(`,') ifdef(`__CONFIG_M4_INCLUDED__',,` include(CONFIG_TOP_SRCDIR`/mpn/asm-defs.m4') include_mpn(`x86_64/x86_64-defs.m4') -define_not_for_expansion(`HAVE_HOST_CPU_core2') +define_not_for_expansion(`HAVE_HOST_CPU_kabylake') define_not_for_expansion(`HAVE_ABI_64') define_not_for_expansion(`HAVE_LIMB_LITTLE_ENDIAN') define_not_for_expansion(`HAVE_DOUBLE_IEEE_LITTLE_ENDIAN') diff --git a/repos/libports/src/lib/libc/component.cc b/repos/libports/src/lib/libc/component.cc new file mode 100644 index 000000000..1adab4e67 --- /dev/null +++ b/repos/libports/src/lib/libc/component.cc @@ -0,0 +1,82 @@ +/* + * \brief Libc component startup + * \author Christian Helmuth + * \author Norman Feske + * \date 2016-01-22 + */ + +/* + * Copyright (C) 2016-2019 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 <base/component.h> + +/* libc includes */ +#include <libc-plugin/plugin_registry.h> + +/* base-internal includes */ +#include <base/internal/unmanaged_singleton.h> + +/* libc-internal includes */ +#include <internal/kernel.h> + + +extern char **environ; + + +Genode::size_t Component::stack_size() { return Libc::Component::stack_size(); } + + +void Component::construct(Genode::Env &env) +{ + /* initialize the global pointer to environment variables */ + static char *null_env = nullptr; + if (!environ) environ = &null_env; + + Genode::Allocator &heap = + *unmanaged_singleton<Genode::Heap>(env.ram(), env.rm()); + + /* pass Genode::Env to libc subsystems that depend on it */ + Libc::init_fd_alloc(heap); + Libc::init_mem_alloc(env); + Libc::init_dl(env); + Libc::sysctl_init(env); + + Libc::Kernel &kernel = *unmanaged_singleton<Libc::Kernel>(env, heap); + + Libc::libc_config_init(kernel.libc_env().libc_config()); + + /* + * XXX The following two steps leave us with the dilemma that we don't know + * which linked library may depend on the successfull initialization of a + * plugin. For example, some high-level library may try to open a network + * connection in its constructor before the network-stack library is + * initialized. But, we can't initialize plugins before calling static + * constructors as those are needed to know about the libc plugin. The only + * solution is to remove all libc plugins beside the VFS implementation, + * which is our final goal anyway. + */ + + /* finish static construction of component and libraries */ + Libc::with_libc([&] () { env.exec_static_constructors(); }); + + /* initialize plugins that require Genode::Env */ + auto init_plugin = [&] (Libc::Plugin &plugin) { + plugin.init(env); + }; + Libc::plugin_registry()->for_each_plugin(init_plugin); + + /* construct libc component on kernel stack */ + Libc::Component::construct(kernel.libc_env()); +} + + +/** + * Default stack size for libc-using components + */ +Genode::size_t Libc::Component::stack_size() __attribute__((weak)); +Genode::size_t Libc::Component::stack_size() { return 32UL*1024*sizeof(long); } diff --git a/repos/libports/src/lib/libc/dummies.cc b/repos/libports/src/lib/libc/dummies.cc index 40f25bc12..6b461b96d 100644 --- a/repos/libports/src/lib/libc/dummies.cc +++ b/repos/libports/src/lib/libc/dummies.cc @@ -116,7 +116,6 @@ DUMMY(int , -1, getpriority, (int, int)) DUMMY(int , -1, getrusage, (int, rusage *)) DUMMY(uid_t , 0, getuid, (void)) DUMMY_SILENT(int , 1, isatty, (int)) -DUMMY(int , -1, kill, (pid_t, int)) DUMMY(int , -1, link, (const char *, const char *)) DUMMY(int , 0, minherit, (void *, size_t, int)) DUMMY(int , -1, mknod, (const char *, mode_t, dev_t)) @@ -195,7 +194,6 @@ __SYS_DUMMY(int, -1, truncate, (const char *, off_t)) DUMMY(int, -1, sigblock, (int)) DUMMY(int, -1, thr_kill2, (pid_t pid, long id, int sig)); -__SYS_DUMMY_SILENT(int, -1, sigaction, (int, const struct sigaction *, struct sigaction *)); __SYS_DUMMY(int, -1, sigsuspend, (const sigset_t *)) __SYS_DUMMY(int, -1, sigtimedwait, (const sigset_t *, siginfo_t *, const struct timespec *)); __SYS_DUMMY(int, -1, sigwaitinfo, (const sigset_t *, siginfo_t *)); diff --git a/repos/libports/src/lib/libc/dynamic_linker.cc b/repos/libports/src/lib/libc/dynamic_linker.cc index 791c4d746..ba47856be 100644 --- a/repos/libports/src/lib/libc/dynamic_linker.cc +++ b/repos/libports/src/lib/libc/dynamic_linker.cc @@ -15,7 +15,7 @@ #include <libc/allocator.h> /* libc-internal includes */ -#include <libc_init.h> +#include <internal/init.h> /* libc includes */ extern "C" { @@ -76,8 +76,11 @@ void *dlopen(const char *name, int mode) try { static Libc::Allocator global_alloc; + return new (global_alloc) - Shared_object(*genode_env, global_alloc, name, bind, keep); + Shared_object(*genode_env, global_alloc, + name ? Genode::Path<128>(name).last_element() : nullptr, /* extract file name */ + bind, keep); } catch (...) { snprintf(err_str, MAX_ERR, "Unable to open file %s\n", name); } diff --git a/repos/libports/src/lib/libc/execve.cc b/repos/libports/src/lib/libc/execve.cc index 6ad1a0c84..044ab1044 100644 --- a/repos/libports/src/lib/libc/execve.cc +++ b/repos/libports/src/lib/libc/execve.cc @@ -14,24 +14,190 @@ /* Genode includes */ #include <base/shared_object.h> #include <base/log.h> +#include <base/attached_rom_dataspace.h> /* libc includes */ #include <unistd.h> #include <stdlib.h> #include <errno.h> +#include <string.h> +#include <libc/allocator.h> /* libc-internal includes */ -#include <libc/allocator.h> #include <internal/call_func.h> -#include <libc_init.h> -#include <libc_errno.h> -#include <task.h> +#include <internal/init.h> +#include <internal/errno.h> +#include <internal/file_operations.h> using namespace Genode; typedef int (*main_fn_ptr) (int, char **, char **); -namespace Libc { struct String_array; } +namespace Libc { + struct Interpreter; + struct String_array; +} + + +struct Libc::Interpreter +{ + Attached_rom_dataspace _rom; + + char **args = { nullptr }; + + /** + * Return true if file content starts with the specified C string + */ + bool _content_starts_with(char const *prefix) const + { + size_t const prefix_len = ::strlen(prefix); + + if (prefix_len > _rom.size()) + return false; + + return strncmp(prefix, _rom.local_addr<char const>(), prefix_len) == 0; + } + + bool script() const { return _content_starts_with("#!"); } + bool elf_executable() const { return _content_starts_with("\x7f" "ELF"); } + + struct Arg + { + /* pointer to first character */ + char const * const ptr; + + /* number of characters */ + size_t const length; + }; + + struct Constrained_ptr + { + char const *ptr; + + size_t remaining_bytes; + + /** + * Skip characters for which 'condition' is true + */ + template <typename COND> + void _skip(COND const &condition) + { + while (remaining_bytes > 0 && condition(*ptr)) { + ptr++; + remaining_bytes--; + } + } + + void skip_non_whitespace() { _skip([] (char c) { return !is_whitespace(c); }); }; + void skip_whitespace() { _skip([] (char c) { return is_whitespace(c); }); }; + + void skip_shebang() + { + _skip([] (char c) { return c == '#'; }); + _skip([] (char c) { return c == '!'; }); + } + + bool valid() const { return ptr && *ptr && *ptr != '\n' && remaining_bytes; } + }; + + template <typename FN> + void _for_each_arg(FN const &fn) const + { + if (!script()) + return; + + Constrained_ptr ptr { _rom.local_addr<char const>(), _rom.size() }; + + ptr.skip_shebang(); + + /* skip whitespace between shebang and interpreter */ + ptr.skip_whitespace(); + + /* skip path to interpreter */ + ptr.skip_non_whitespace(); + + while (ptr.valid()) { + + /* skip whitespace before argument */ + ptr.skip_whitespace(); + + /* find end of argument */ + char const * const arg_ptr = ptr.ptr; + unsigned const orig_remaining_bytes = ptr.remaining_bytes; + ptr.skip_non_whitespace(); + + size_t const length = orig_remaining_bytes - ptr.remaining_bytes; + + if (length) + fn(Arg { arg_ptr, length }); + } + } + + typedef String<Vfs::MAX_PATH_LEN> Path; + + Path path() const + { + if (!script()) + return Path(); + + Constrained_ptr ptr { _rom.local_addr<char const>(), _rom.size() }; + + ptr.skip_shebang(); + ptr.skip_whitespace(); + + /* find end of interpreter path */ + char const * const path_ptr = ptr.ptr; + unsigned const orig_remaining_bytes = ptr.remaining_bytes; + ptr.skip_non_whitespace(); + + size_t const length = orig_remaining_bytes - ptr.remaining_bytes; + + return Path(Cstring(path_ptr, length)); + } + + unsigned _count_args() const + { + unsigned count = 0; + + _for_each_arg([&] (Arg) { count++; }); + + return count; + } + + unsigned const num_args; + + Interpreter(Genode::Env &env, char const * const filename) + : + _rom(env, filename), num_args(_count_args() + 2 /* argv0 + filename */) + { + if (script()) { + args = (char **)malloc(sizeof(char *)*num_args); + + unsigned i = 0; + + /* argv0 */ + args[i++] = strdup(path().string()); + + _for_each_arg([&] (Arg arg) { + args[i++] = strndup(arg.ptr, arg.length); }); + + /* supply script file name as last argument */ + args[i++] = strdup(filename); + + + } + } + + ~Interpreter() + { + if (script()) { + for (unsigned i = 0; i < num_args; i++) + free(args[i]); + + free(args); + } + } +}; /** @@ -85,30 +251,48 @@ struct Libc::String_array : Noncopyable Constructible<Buffer> _buffer { }; - String_array(Allocator &alloc, char const * const * const src_array) + String_array(Allocator &alloc, + char const * const * const src_array_1, + char const * const * const src_array_2 = nullptr) : - _alloc(alloc), count(_num_entries(src_array)) + _alloc(alloc), + + /* if 'src_array_2' is supplied, we skip its first element (argv0) */ + count(_num_entries(src_array_1) + _num_entries(src_array_2) - + (src_array_2 ? 1 : 0)) { /* marshal array strings to buffer */ size_t size = 1024; for (;;) { - _buffer.construct(alloc, size); + _buffer.construct(_alloc, size); - unsigned i = 0; - for (i = 0; i < count; i++) { - array[i] = _buffer->pos_ptr(); - if (!_buffer->try_append(src_array[i])) - break; - } + unsigned dst_i = 0; /* index into destination array */ - bool const done = (i == count); + auto try_append_entries = [&] (char const * const * const src_array, + unsigned skip = 0) + { + if (!src_array) + return; + + size_t const n = _num_entries(src_array); + for (unsigned i = skip; i < n; i++) { + array[dst_i++] = _buffer->pos_ptr(); + if (!_buffer->try_append(src_array[i])) + break; + } + }; + + try_append_entries(src_array_1); + try_append_entries(src_array_2, 1); /* skip old argv0 */ + + bool const done = (dst_i == count); if (done) { - array[i] = nullptr; + array[dst_i] = nullptr; break; } - warning("env buffer ", size, " too small"); + warning("string-array buffer ", size, " exceeded"); size += 1024; } } @@ -166,11 +350,57 @@ extern "C" int execve(char const *filename, Libc::String_array *saved_env_vars = new (*_alloc_ptr) Libc::String_array(*_alloc_ptr, envp); + /* + * Resolve path of the executable and handle shebang arguments + */ + Libc::Absolute_path resolved_path; + + Libc::Interpreter::Path path(filename); + Libc::String_array *saved_args = new (*_alloc_ptr) Libc::String_array(*_alloc_ptr, argv); + enum { MAX_INTERPRETER_NESTING_LEVELS = 4 }; + + for (unsigned i = 0; i < MAX_INTERPRETER_NESTING_LEVELS; i++) { + + try { + Libc::resolve_symlinks(path.string(), resolved_path); } + catch (Libc::Symlink_resolve_error) { + warning("execve: executable binary does not exist"); + return Libc::Errno(ENOENT); + } + + Constructible<Libc::Interpreter> interpreter { }; + + try { + interpreter.construct(*_env_ptr, resolved_path.string()); } + catch (...) { + warning("execve: executable binary inaccessible as ROM module"); + return Libc::Errno(ENOENT); + } + + if (interpreter->elf_executable()) + break; + + if (!interpreter->script()) { + warning("invalid executable binary format: ", resolved_path.string()); + return Libc::Errno(ENOEXEC); + } + + path = interpreter->path(); + + /* concatenate shebang args with command-line args */ + Libc::String_array * const orig_saved_args = saved_args; + + saved_args = new (*_alloc_ptr) + Libc::String_array(*_alloc_ptr, interpreter->args, argv); + + destroy(*_alloc_ptr, orig_saved_args); + } + try { - _main_ptr = Dynamic_linker::respawn<main_fn_ptr>(*_env_ptr, filename, "main"); + _main_ptr = Dynamic_linker::respawn<main_fn_ptr>(*_env_ptr, resolved_path.string(), "main"); } catch (Dynamic_linker::Invalid_symbol) { error("Dynamic_linker::respawn could not obtain binary entry point"); diff --git a/repos/libports/src/lib/libc/fd_alloc.cc b/repos/libports/src/lib/libc/fd_alloc.cc index dffe77904..95eb4202f 100644 --- a/repos/libports/src/lib/libc/fd_alloc.cc +++ b/repos/libports/src/lib/libc/fd_alloc.cc @@ -17,6 +17,9 @@ #include <base/env.h> #include <base/log.h> +/* Genode-internal includes */ +#include <base/internal/unmanaged_singleton.h> + /* libc plugin interface */ #include <libc-plugin/fd_alloc.h> @@ -25,11 +28,9 @@ #include <unistd.h> /* libc-internal includes */ -#include <libc_init.h> -#include <base/internal/unmanaged_singleton.h> +#include <internal/init.h> using namespace Libc; -using namespace Genode; static Allocator *_alloc_ptr; @@ -147,7 +148,7 @@ void File_descriptor::path(char const *newpath) } if (newpath) { - Genode::size_t const path_size = ::strlen(newpath) + 1; + size_t const path_size = ::strlen(newpath) + 1; char *buf = (char*)_alloc_ptr->alloc(path_size); if (!buf) { error("could not allocate path buffer for libc_fd ", libc_fd); diff --git a/repos/libports/src/lib/libc/file_operations.cc b/repos/libports/src/lib/libc/file_operations.cc index a45a62e63..4b467baa7 100644 --- a/repos/libports/src/lib/libc/file_operations.cc +++ b/repos/libports/src/lib/libc/file_operations.cc @@ -39,10 +39,10 @@ extern "C" { } /* libc-internal includes */ -#include "libc_file.h" -#include "libc_mem_alloc.h" -#include "libc_mmap_registry.h" -#include "libc_errno.h" +#include <internal/file.h> +#include <internal/mem_alloc.h> +#include <internal/mmap_registry.h> +#include <internal/errno.h> using namespace Libc; @@ -56,7 +56,7 @@ using namespace Libc; Libc::Mmap_registry *Libc::mmap_registry() { - static Libc::Mmap_registry registry; + static Mmap_registry registry; return ®istry; } @@ -86,7 +86,7 @@ struct Scanner_policy_path_element } }; -typedef Genode::Token<Scanner_policy_path_element> Path_element_token; +typedef Token<Scanner_policy_path_element> Path_element_token; /** @@ -126,7 +126,7 @@ void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path) try { next_iteration_working_path.append_element(path_element); - } catch (Genode::Path_base::Path_too_long) { + } catch (Path_base::Path_too_long) { errno = ENAMETOOLONG; throw Symlink_resolve_error(); } @@ -160,7 +160,7 @@ void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path) next_iteration_working_path.strip_last_element(); try { next_iteration_working_path.append_element(symlink_target); - } catch (Genode::Path_base::Path_too_long) { + } catch (Path_base::Path_too_long) { errno = ENAMETOOLONG; throw Symlink_resolve_error(); } @@ -191,7 +191,7 @@ static void resolve_symlinks_except_last_element(char const *path, Absolute_path absolute_path_last_element.keep_only_last_element(); try { resolved_path.append_element(absolute_path_last_element.base()); - } catch (Genode::Path_base::Path_too_long) { + } catch (Path_base::Path_too_long) { errno = ENAMETOOLONG; throw Symlink_resolve_error(); } @@ -233,10 +233,9 @@ extern "C" int chdir(const char *path) */ __SYS_(int, close, (int libc_fd), { - Libc::File_descriptor *fd = - Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); return (!fd || !fd->plugin) - ? Libc::Errno(EBADF) + ? Errno(EBADF) : fd->plugin->close(fd); }) @@ -269,7 +268,7 @@ extern "C" int dup2(int libc_fd, int new_libc_fd) close(new_libc_fd); new_fd = file_descriptor_allocator()->alloc(fd->plugin, 0, new_libc_fd); - new_fd->path(fd->fd_path); + /* new_fd->context must be assigned by the plugin implementing 'dup2' */ return fd->plugin->dup2(fd, new_fd); } @@ -317,14 +316,13 @@ __SYS_(int, fstatat, (int libc_fd, char const *path, struct stat *buf, int flags return stat(path, buf); } - Libc::Absolute_path abs_path; + Absolute_path abs_path; if (libc_fd == AT_FDCWD) { abs_path = cwd(); abs_path.append_element(path); } else { - Libc::File_descriptor *fd = - Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) { errno = EBADF; return -1; @@ -398,7 +396,7 @@ __SYS_(void *, mmap, (void *addr, ::size_t length, /* handle requests for anonymous memory */ if (!addr && libc_fd == -1) { bool const executable = prot & PROT_EXEC; - void *start = Libc::mem_alloc(executable)->alloc(length, PAGE_SHIFT); + void *start = mem_alloc(executable)->alloc(length, PAGE_SHIFT); if (!start) { errno = ENOMEM; return MAP_FAILED; @@ -410,7 +408,7 @@ __SYS_(void *, mmap, (void *addr, ::size_t length, /* lookup plugin responsible for file descriptor */ File_descriptor *fd = libc_fd_to_fd(libc_fd, "mmap"); if (!fd || !fd->plugin || !fd->plugin->supports_mmap()) { - Genode::warning("mmap not supported for file descriptor ", libc_fd); + warning("mmap not supported for file descriptor ", libc_fd); errno = EBADF; return MAP_FAILED; } @@ -424,7 +422,7 @@ __SYS_(void *, mmap, (void *addr, ::size_t length, extern "C" int munmap(void *start, ::size_t length) { if (!mmap_registry()->registered(start)) { - Genode::warning("munmap: could not lookup plugin for address ", start); + warning("munmap: could not lookup plugin for address ", start); errno = EINVAL; return -1; } @@ -442,8 +440,8 @@ extern "C" int munmap(void *start, ::size_t length) else { bool const executable = true; /* XXX another metadata handling required to track anonymous memory */ - Libc::mem_alloc(!executable)->free(start); - Libc::mem_alloc(executable)->free(start); + mem_alloc(!executable)->free(start); + mem_alloc(executable)->free(start); } mmap_registry()->remove(start); @@ -454,7 +452,7 @@ extern "C" int munmap(void *start, ::size_t length) __SYS_(int, msync, (void *start, ::size_t len, int flags), { if (!mmap_registry()->registered(start)) { - Genode::warning("munmap: could not lookup plugin for address ", start); + warning("munmap: could not lookup plugin for address ", start); errno = EINVAL; return -1; } @@ -503,13 +501,13 @@ __SYS_(int, open, (const char *pathname, int flags, ...), plugin = plugin_registry()->get_plugin_for_open(resolved_path.base(), flags); if (!plugin) { - Genode::error("no plugin found for open(\"", pathname, "\", ", flags, ")"); + error("no plugin found for open(\"", pathname, "\", ", flags, ")"); return -1; } new_fdo = plugin->open(resolved_path.base(), flags); if (!new_fdo) { - Genode::error("plugin()->open(\"", pathname, "\") failed"); + error("plugin()->open(\"", pathname, "\") failed"); return -1; } new_fdo->path(resolved_path.base()); @@ -530,14 +528,13 @@ __SYS_(int, openat, (int libc_fd, const char *path, int flags, ...), return open(path, flags, mode); } - Libc::Absolute_path abs_path; + Absolute_path abs_path; if (libc_fd == AT_FDCWD) { abs_path = cwd(); abs_path.append_element(path); } else { - Libc::File_descriptor *fd = - Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) { errno = EBADF; return -1; @@ -561,12 +558,12 @@ extern "C" int pipe2(int pipefd[2], int flags) plugin = plugin_registry()->get_plugin_for_pipe(); if (!plugin) { - Genode::error("no plugin found for pipe()"); + error("no plugin found for pipe()"); return -1; } if (plugin->pipe(pipefdo) == -1) { - Genode::error("plugin()->pipe() failed"); + error("plugin()->pipe() failed"); return -1; } @@ -574,7 +571,7 @@ extern "C" int pipe2(int pipefd[2], int flags) int err = plugin->fcntl(pipefdo[0], F_SETFL, O_NONBLOCK) | plugin->fcntl(pipefdo[1], F_SETFL, O_NONBLOCK); if (err != 0) - Genode::warning("pipe plugin does not support O_NONBLOCK"); + warning("pipe plugin does not support O_NONBLOCK"); } pipefd[0] = pipefdo[0]->libc_fd; diff --git a/repos/libports/src/lib/libc/fork.cc b/repos/libports/src/lib/libc/fork.cc index 8eb792111..9cd01288f 100644 --- a/repos/libports/src/lib/libc/fork.cc +++ b/repos/libports/src/lib/libc/fork.cc @@ -32,34 +32,47 @@ #include <libc-plugin/fd_alloc.h> /* libc-internal includes */ -#include <task.h> -#include <libc_init.h> -#include <clone_session.h> +#include <internal/init.h> +#include <internal/clone_session.h> +#include <internal/legacy.h> +#include <internal/kernel_routine.h> +#include <internal/suspend.h> +#include <internal/resume.h> +#include <internal/signal.h> -using namespace Genode; +using namespace Libc; static pid_t fork_result; -static Env *_env_ptr; -static Allocator *_alloc_ptr; -static Heap *_malloc_heap_ptr; -static void *_user_stack_base_ptr; -static size_t _user_stack_size; -static int _pid; -static int _pid_cnt; - -static Libc::Config_accessor const *_config_accessor_ptr; +static Env *_env_ptr; +static Allocator *_alloc_ptr; +static Suspend *_suspend_ptr; +static Resume *_resume_ptr; +static Libc::Signal *_signal_ptr; +static Kernel_routine_scheduler *_kernel_routine_scheduler_ptr; +static Heap *_malloc_heap_ptr; +static void *_user_stack_base_ptr; +static size_t _user_stack_size; +static int _pid; +static int _pid_cnt; +static Config_accessor const *_config_accessor_ptr; void Libc::init_fork(Env &env, Config_accessor const &config_accessor, - Allocator &alloc, Heap &malloc_heap, pid_t pid) + Allocator &alloc, Heap &malloc_heap, pid_t pid, + Suspend &suspend, Resume &resume, Signal &signal, + Kernel_routine_scheduler &kernel_routine_scheduler) { - _env_ptr = &env; - _alloc_ptr = &alloc; - _malloc_heap_ptr = &malloc_heap; - _config_accessor_ptr = &config_accessor; - _pid = pid; + _env_ptr = &env; + _alloc_ptr = &alloc; + _suspend_ptr = &suspend; + _resume_ptr = &resume; + _signal_ptr = &signal; + _kernel_routine_scheduler_ptr = &kernel_routine_scheduler; + _malloc_heap_ptr = &malloc_heap; + _config_accessor_ptr = &config_accessor; + _pid = pid; } @@ -347,13 +360,15 @@ struct Libc::Local_clone_service : Noncopyable Child_ready &_child_ready; + Resume &_resume; + Io_signal_handler<Local_clone_service> _child_ready_handler; void _handle_child_ready() { _child_ready.child_ready(); - Libc::resume_all(); + _resume.resume_all(); } struct Factory : Local_service<Session>::Factory @@ -374,9 +389,10 @@ struct Libc::Local_clone_service : Noncopyable Service service { _factory }; - Local_clone_service(Env &env, Entrypoint &ep, Child_ready &child_ready) + Local_clone_service(Env &env, Entrypoint &ep, Child_ready &child_ready, + Resume &resume) : - _session(env, ep), _child_ready(child_ready), + _session(env, ep), _child_ready(child_ready), _resume(resume), _child_ready_handler(env.ep(), *this, &Local_clone_service::_handle_child_ready), _factory(_session, _child_ready_handler) { } @@ -387,6 +403,10 @@ struct Libc::Forked_child : Child_policy, Child_ready { Env &_env; + Resume &_resume; + + Signal &_signal; + pid_t const _pid; enum class State { STARTING_UP, RUNNING, EXITED } _state { State::STARTING_UP }; @@ -402,26 +422,30 @@ struct Libc::Forked_child : Child_policy, Child_ready Io_signal_handler<Libc::Forked_child> _exit_handler { _env.ep(), *this, &Forked_child::_handle_exit }; - void _handle_exit() { Libc::resume_all(); } + void _handle_exit() + { + _signal.charge(SIGCHLD); + _resume.resume_all(); + } - Libc::Child_config _child_config; + Child_config _child_config; Parent_services &_parent_services; Local_rom_services &_local_rom_services; Local_clone_service _local_clone_service; Local_rom_service _config_rom_service; - struct Wait_fork_ready : Libc::Kernel_routine + struct Wait_fork_ready : Kernel_routine { - Libc::Forked_child const &child; + Forked_child const &child; - Wait_fork_ready(Libc::Forked_child const &child) : child(child) { } + Wait_fork_ready(Forked_child const &child) : child(child) { } void execute_in_kernel() override { /* keep executing this kernel routine until child is running */ if (!child.running()) - register_kernel_routine(*this); + _kernel_routine_scheduler_ptr->register_kernel_routine(*this); } } wait_fork_ready { *this }; @@ -456,19 +480,28 @@ struct Libc::Forked_child : Child_policy, Child_ready { session.ref_account(_env.pd_session_cap()); - _env.pd().transfer_quota(cap, Ram_quota{2*1024*1024}); + _env.pd().transfer_quota(cap, Ram_quota{2500*1000}); _env.pd().transfer_quota(cap, Cap_quota{100}); } Route resolve_session_request(Service::Name const &name, Session_label const &label) override { + Session_label rewritten_label = label; + Service *service_ptr = nullptr; if (_state == State::STARTING_UP && name == Clone_session::service_name()) service_ptr = &_local_clone_service.service; if (name == Rom_session::service_name()) { + /* + * Strip off the originating child name to allow the application of + * routing rules based on the leading path elements, regardless + * of which child in the process hierarchy requests a ROM. + */ + rewritten_label = label.last_element(); + try { service_ptr = &_local_rom_services.matching_service(name, label); } catch (...) { } @@ -481,7 +514,7 @@ struct Libc::Forked_child : Child_policy, Child_ready if (service_ptr) return Route { .service = *service_ptr, - .label = label, + .label = rewritten_label, .diag = Session::Diag() }; throw Service_denied(); @@ -513,16 +546,18 @@ struct Libc::Forked_child : Child_policy, Child_ready Forked_child(Env &env, Entrypoint &fork_ep, Allocator &alloc, + Resume &resume, + Signal &signal, pid_t pid, Config_accessor const &config_accessor, Parent_services &parent_services, Local_rom_services &local_rom_services) : - _env(env), _pid(pid), + _env(env), _resume(resume), _signal(signal), _pid(pid), _child_config(env, config_accessor, pid), _parent_services(parent_services), _local_rom_services(local_rom_services), - _local_clone_service(env, fork_ep, *this), + _local_clone_service(env, fork_ep, *this, resume), _config_rom_service(fork_ep, "config", _child_config.ds_cap()), _child(env.rm(), fork_ep.rpc_ep(), *this) { } @@ -545,8 +580,10 @@ static void fork_kernel_routine() abort(); } - Env &env = *_env_ptr; - Allocator &alloc = *_alloc_ptr; + Env &env = *_env_ptr; + Allocator &alloc = *_alloc_ptr; + Resume &resume = *_resume_ptr; + Libc::Signal &signal = *_signal_ptr; pid_t const child_pid = ++_pid_cnt; @@ -555,25 +592,25 @@ static void fork_kernel_routine() static Libc::Parent_services parent_services(env, alloc); - static Libc::Local_rom_services local_rom_services(env, fork_ep, alloc); + static Local_rom_services local_rom_services(env, fork_ep, alloc); static Forked_children forked_children { }; _forked_children_ptr = &forked_children; - Registered<Libc::Forked_child> &child = *new (alloc) - Registered<Libc::Forked_child>(forked_children, env, fork_ep, alloc, - child_pid, *_config_accessor_ptr, - parent_services, local_rom_services); + Registered<Forked_child> &child = *new (alloc) + Registered<Forked_child>(forked_children, env, fork_ep, alloc, resume, + signal, child_pid, *_config_accessor_ptr, + parent_services, local_rom_services); fork_result = child_pid; - register_kernel_routine(child.wait_fork_ready); + _kernel_routine_scheduler_ptr->register_kernel_routine(child.wait_fork_ready); } -/************ - ** getpid ** - ************/ +/********** + ** fork ** + **********/ /* * We provide weak symbols to allow 'libc_noux' to override them. @@ -589,21 +626,25 @@ extern "C" pid_t __sys_fork(void) _user_stack_base_ptr = (void *)mystack.base; _user_stack_size = mystack.top - mystack.base; - struct Fork_kernel_routine : Libc::Kernel_routine + struct Fork_kernel_routine : Kernel_routine { void execute_in_kernel() override { fork_kernel_routine(); } } kernel_routine { }; - Libc::register_kernel_routine(kernel_routine); + struct Missing_call_of_init_fork : Exception { }; + if (!_kernel_routine_scheduler_ptr || !_suspend_ptr) + throw Missing_call_of_init_fork(); - struct Suspend_functor_impl : Libc::Suspend_functor + _kernel_routine_scheduler_ptr->register_kernel_routine(kernel_routine); + + struct Suspend_functor_impl : Suspend_functor { bool suspend() override { return false; } } suspend_functor { }; - Libc::suspend(suspend_functor, 0); + _suspend_ptr->suspend(suspend_functor, 0); return fork_result; } @@ -673,7 +714,6 @@ extern "C" pid_t __sys_wait4(pid_t pid, int *status, int options, rusage *rusage pid_t result = -1; int exit_code = 0; /* code and status */ - using namespace Genode; using namespace Libc; if (!_forked_children_ptr) { @@ -681,6 +721,10 @@ extern "C" pid_t __sys_wait4(pid_t pid, int *status, int options, rusage *rusage return -1; } + struct Missing_call_of_init_fork : Exception { }; + if (!_suspend_ptr) + throw Missing_call_of_init_fork(); + Wait4_suspend_functor suspend_functor { pid, *_forked_children_ptr }; for (;;) { @@ -694,7 +738,7 @@ extern "C" pid_t __sys_wait4(pid_t pid, int *status, int options, rusage *rusage if (result >= 0 || (options & WNOHANG)) break; - Libc::suspend(suspend_functor, 0); + _suspend_ptr->suspend(suspend_functor, 0); } /* diff --git a/repos/libports/src/lib/libc/getpwent.cc b/repos/libports/src/lib/libc/getpwent.cc index 5e7d5459d..e8fe3c356 100644 --- a/repos/libports/src/lib/libc/getpwent.cc +++ b/repos/libports/src/lib/libc/getpwent.cc @@ -1,184 +1,203 @@ /* * \brief Password database operations - * \author Emery Hemingway - * \date 2018-07-15 + * \author Norman Feske + * \date 2019-09-20 */ /* - * Copyright (C) 2018 Genode Labs GmbH + * Copyright (C) 2019 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 <base/log.h> #include <util/string.h> +#include <util/xml_node.h> -/* Libc includes */ +/* libc includes */ #include <sys/types.h> #include <pwd.h> #include <stdlib.h> -/* local includes */ -#include "libc_errno.h" -#include "task.h" +/* libc-local includes */ +#include <internal/legacy.h> +#include <internal/errno.h> +#include <internal/init.h> -typedef Genode::String<128> Passwd_string; +namespace Libc { -struct Passwd_fields { - Passwd_string name { "root" }; - Passwd_string passwd { }; - unsigned long uid = 0; - unsigned long gid = 0; - unsigned long change = 0; - Passwd_string clas { }; - Passwd_string gecos { }; - Passwd_string home { "/" }; - Passwd_string shell { }; - unsigned long expire = 0; - unsigned long fields = 0; + struct Passwd_fields; - Passwd_fields() { } -}; - - -static void _fill_passwd(struct passwd &db, Passwd_fields &fields) -{ - using namespace Genode; - - /* reset buffers */ - Genode::memset(&db, 0x00, sizeof(struct passwd)); - fields = Passwd_fields(); - - try { - Xml_node const passwd = Libc::libc_config().sub_node("passwd"); - - fields.name = passwd.attribute_value("name", fields.name); - fields.uid = passwd.attribute_value("uid", 0UL); - fields.gid = passwd.attribute_value("gid", 0UL); - fields.change = passwd.attribute_value("change", 0UL); - fields.passwd = passwd.attribute_value("passwd", fields.passwd); - fields.clas = passwd.attribute_value("class", fields.clas); - fields.gecos = passwd.attribute_value("gecos", fields.gecos); - fields.home = passwd.attribute_value("home", fields.home); - fields.shell = passwd.attribute_value("shell", fields.shell); - fields.expire = passwd.attribute_value("expire", 0UL); - fields.fields = passwd.attribute_value("fields", 0UL); - } - - catch (...) { } - - db.pw_name = (char *)fields.name.string(); - db.pw_uid = fields.uid; - db.pw_gid = fields.gid; - db.pw_change = fields.change; - db.pw_passwd = (char *)fields.passwd.string(); - db.pw_class = (char *)fields.clas.string(); - db.pw_gecos = (char *)fields.gecos.string(); - db.pw_dir = (char *)fields.home.string(); - db.pw_shell = (char *)fields.shell.string(); - db.pw_expire = fields.expire; - db.pw_fields = fields.fields; + typedef String<128> Passwd_string; } -static int _fill_r(struct passwd *in, - char *buffer, size_t bufsize, - struct passwd **out) +/* + * This struct must not contain any pointer because it is copied as + * plain old data. + */ +struct Libc::Passwd_fields { - if (!in || !buffer) return Libc::Errno(EINVAL); - if (bufsize < sizeof(Passwd_fields)) return Libc::Errno(ERANGE); + struct Buffer + { + char buf[Passwd_string::capacity()] { }; - Passwd_fields *fields = (Passwd_fields *)buffer; - _fill_passwd(*in, *fields); + Buffer(Passwd_string const &string) + { + Genode::strncpy(buf, string.string(), sizeof(buf)); + } + }; + + Buffer name; + Buffer passwd; + uid_t uid; + gid_t gid; + time_t change; + Buffer clas; + Buffer gecos; + Buffer home; + Buffer shell; + time_t expire; + int fields; +}; + +using namespace Libc; + +static Passwd_fields *_fields_ptr = nullptr; +static passwd *_passwd_ptr = nullptr; +static int _passwd_index = 0; + + +static passwd passwd_from_fields(Passwd_fields &fields) +{ + return passwd { + .pw_name = fields.name.buf, + .pw_passwd = fields.passwd.buf, + .pw_uid = fields.uid, + .pw_gid = fields.gid, + .pw_change = fields.change, + .pw_class = fields.clas.buf, + .pw_gecos = fields.gecos.buf, + .pw_dir = fields.home.buf, + .pw_shell = fields.shell.buf, + .pw_expire = fields.expire, + .pw_fields = fields.fields + }; +} + + +void Libc::init_passwd(Xml_node config) +{ + static Passwd_fields fields { + .name = config.attribute_value("name", Passwd_string("root")), + .passwd = config.attribute_value("passwd", Passwd_string("")), + .uid = config.attribute_value("uid", 0U), + .gid = config.attribute_value("gid", 0U), + .change = (time_t)config.attribute_value("change", 0U), + .clas = config.attribute_value("class", Passwd_string("")), + .gecos = config.attribute_value("gecos", Passwd_string("")), + .home = config.attribute_value("home", Passwd_string("/")), + .shell = config.attribute_value("shell", Passwd_string("")), + .expire = (time_t)config.attribute_value("expire", 0U), + .fields = (int)config.attribute_value("fields", 0U) + }; + + static passwd passwd = passwd_from_fields(fields); + + _fields_ptr = &fields; + _passwd_ptr = &passwd; +} + + +extern "C" passwd *getpwent() +{ + struct Missing_call_of_init_passwd : Exception { }; + if (!_passwd_ptr) + throw Missing_call_of_init_passwd(); + + return (_passwd_index++ == 0) ? _passwd_ptr : nullptr; +} + + +template <typename COND_FN> +static int copy_out_pwent(passwd *in, char *buffer, size_t bufsize, passwd **out, + COND_FN const &cond_fn) +{ + *out = nullptr; + + struct Missing_call_of_init_passwd : Exception { }; + if (!_fields_ptr || !_passwd_ptr) + throw Missing_call_of_init_passwd(); + + if (bufsize < sizeof(Passwd_fields)) + return Errno(ERANGE); + + if (!cond_fn(*_passwd_ptr)) + return Errno(ENOENT); + + Passwd_fields &dst = *(Passwd_fields *)buffer; + + dst = *_fields_ptr; + *in = passwd_from_fields(dst); *out = in; + return 0; } -static struct passwd *_fill_static() +extern "C" int getpwent_r(passwd *in, char *buffer, size_t bufsize, passwd **out) { - struct Passwd_storage { - struct passwd pwd; - Passwd_fields fields; - }; + auto match = [&] (passwd const &) { return _passwd_index++ == 0; }; - static Passwd_storage *db = nullptr; - if (!db) - db = (Passwd_storage *)malloc(sizeof(struct Passwd_storage)); - - _fill_passwd(db->pwd, db->fields); - return &db->pwd; + return copy_out_pwent(in, buffer, bufsize, out, match); } -static int _passwd_index = 0; - - -extern "C" { - -struct passwd *getpwent(void) +extern "C" struct passwd *getpwnam(const char *login) { - return (_passwd_index++ == 0) - ? _fill_static() - : NULL; + return (_passwd_ptr && Genode::strcmp(login, _passwd_ptr->pw_name) == 0) + ? _passwd_ptr : nullptr; } -int getpwent_r(struct passwd *in, - char *buffer, size_t bufsize, - struct passwd **out) +extern "C" int getpwnam_r(char const *login, passwd *in, + char *buffer, size_t bufsize, passwd **out) { - *out = NULL; - return _passwd_index++ == 0 - ? _fill_r(in, buffer, bufsize, out) - : 0; + auto match = [&] (passwd const &passwd) { + return !Genode::strcmp(passwd.pw_name, login); }; + + return copy_out_pwent(in, buffer, bufsize, out, match); } -struct passwd *getpwnam(const char *login) +extern "C" passwd *getpwuid(uid_t uid) { - struct passwd *result = _fill_static(); - return (Genode::strcmp(login, result->pw_name) == 0) - ? result : NULL; + return (_passwd_ptr && uid == _passwd_ptr->pw_uid) + ? _passwd_ptr : NULL; } -int getpwnam_r(const char *login, struct passwd *in, - char *buffer, size_t bufsize, - struct passwd **out) +extern "C" int getpwuid_r(uid_t uid, passwd *in, + char *buffer, size_t bufsize, passwd **out) { - int rc = _fill_r(in, buffer, bufsize, out); - if (rc == 0 && *out && Genode::strcmp(login, in->pw_name) != 0) - *out = NULL; - return rc; + auto match = [&] (passwd const &passwd) { return passwd.pw_uid == uid; }; + + return copy_out_pwent(in, buffer, bufsize, out, match); } -struct passwd *getpwuid(uid_t uid) +extern "C" int setpassent(int) { - struct passwd *result = _fill_static(); - return (uid == result->pw_uid) - ? result : NULL; + _passwd_index = 0; + return 0; } -int getpwuid_r(uid_t uid, struct passwd *in, - char *buffer, size_t bufsize, - struct passwd **out) +extern "C" void setpwent() { - int rc = _fill_r(in, buffer, bufsize, out); - if (rc == 0 && *out && uid != in->pw_uid) - *out = NULL; - return rc; + _passwd_index = 0; } -int setpassent(int) { _passwd_index = 0; return 0; } - -void setpwent(void) { _passwd_index = 0; } - -void endpwent(void) { } - -} /* extern "C" */ +extern "C" void endpwent() { } diff --git a/repos/libports/src/lib/libc/getrandom.cc b/repos/libports/src/lib/libc/getrandom.cc index 88fa63ffe..185536d6c 100644 --- a/repos/libports/src/lib/libc/getrandom.cc +++ b/repos/libports/src/lib/libc/getrandom.cc @@ -20,8 +20,9 @@ extern "C" { #include <sys/random.h> } -/* local includes */ -#include "libc_errno.h" +/* libc-internal includes */ +#include <internal/errno.h> +#include <internal/types.h> /* Genode includes */ #include <trace/timestamp.h> @@ -30,8 +31,9 @@ extern "C" { namespace Libc { extern char const *config_rng(); } -static -ssize_t read_rng(char *buf, size_t buflen) +using namespace Libc; + +static ssize_t read_rng(char *buf, size_t buflen) { static int rng_fd { -1 }; static bool fallback { false }; @@ -41,27 +43,27 @@ ssize_t read_rng(char *buf, size_t buflen) while (off < buflen) { /* collect 31 bits of random */ unsigned const nonce = random(); - size_t n = Genode::min(4U, buflen-off); - memcpy(buf+off, &nonce, n); + size_t n = min(4U, buflen-off); + ::memcpy(buf+off, &nonce, n); off += n; } return buflen; } if (rng_fd == -1) { - if (!Genode::strcmp(Libc::config_rng(), "")) { - Genode::warning("Libc RNG not configured"); + if (!::strcmp(config_rng(), "")) { + warning("Libc RNG not configured"); /* initialize the FreeBSD random facility */ - srandom(Genode::Trace::timestamp()|1); + srandom(Trace::timestamp()|1); fallback = true; return read_rng(buf, buflen); } - rng_fd = open(Libc::config_rng(), O_RDONLY); + rng_fd = open(config_rng(), O_RDONLY); if (rng_fd == -1) { - Genode::error("RNG device ", Genode::Cstring(Libc::config_rng()), " not readable!"); + error("RNG device ", Cstring(config_rng()), " not readable!"); exit(~0); } } @@ -76,7 +78,7 @@ getrandom(void *buf, size_t buflen, unsigned int flags) size_t off = 0; while (off < buflen && off < 256) { ssize_t n = read_rng((char*)buf+off, buflen-off); - if (n < 1) return Libc::Errno(EIO); + if (n < 1) return Errno(EIO); off += n; } return off; @@ -87,12 +89,12 @@ extern "C" int __attribute__((weak)) getentropy(void *buf, size_t buflen) { /* maximum permitted value for the length argument is 256 */ - if (256 < buflen) return Libc::Errno(EIO); + if (256 < buflen) return Errno(EIO); size_t off = 0; while (off < buflen) { ssize_t n = read_rng((char*)buf+off, buflen-off); - if (n < 1) return Libc::Errno(EIO); + if (n < 1) return Errno(EIO); off += n; } return 0; diff --git a/repos/libports/src/lib/libc/clone_session.h b/repos/libports/src/lib/libc/internal/clone_session.h similarity index 68% rename from repos/libports/src/lib/libc/clone_session.h rename to repos/libports/src/lib/libc/internal/clone_session.h index 5b544910d..c390822f4 100644 --- a/repos/libports/src/lib/libc/clone_session.h +++ b/repos/libports/src/lib/libc/internal/clone_session.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CLONE_SESSION_H_ -#define _CLONE_SESSION_H_ +#ifndef _LIBC__INTERNAL__CLONE_SESSION_H_ +#define _LIBC__INTERNAL__CLONE_SESSION_H_ /* Genode includes */ #include <base/rpc_server.h> @@ -29,7 +29,7 @@ namespace Libc { } -struct Libc::Clone_session : Genode::Session +struct Libc::Clone_session : Session { static const char *service_name() { return "Clone"; } @@ -43,25 +43,25 @@ struct Libc::Clone_session : Genode::Session size_t size; }; - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); + GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace); GENODE_RPC(Rpc_memory_content, void, memory_content, Memory_range); GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_memory_content); }; -struct Libc::Clone_connection : Genode::Connection<Clone_session>, - Genode::Rpc_client<Clone_session> +struct Libc::Clone_connection : Connection<Clone_session>, + Rpc_client<Clone_session> { - Genode::Attached_dataspace const _buffer; + Attached_dataspace const _buffer; Clone_connection(Genode::Env &env) : - Genode::Connection<Clone_session>(env, - session(env.parent(), - "ram_quota=%ld, cap_quota=%ld", - RAM_QUOTA, CAP_QUOTA)), - Genode::Rpc_client<Clone_session>(cap()), + Connection<Clone_session>(env, + session(env.parent(), + "ram_quota=%ld, cap_quota=%ld", + RAM_QUOTA, CAP_QUOTA)), + Rpc_client<Clone_session>(cap()), _buffer(env.rm(), call<Rpc_dataspace>()) { } @@ -75,7 +75,7 @@ struct Libc::Clone_connection : Genode::Connection<Clone_session>, while (remaining > 0) { - size_t const chunk_len = Genode::min((size_t)BUFFER_SIZE, remaining); + size_t const chunk_len = min((size_t)BUFFER_SIZE, remaining); /* instruct server to fill shared buffer */ call<Rpc_memory_content>(Memory_range{ ptr, chunk_len }); @@ -92,4 +92,4 @@ struct Libc::Clone_connection : Genode::Connection<Clone_session>, void object_content(OBJ &obj) { memory_content(&obj, sizeof(obj)); } }; -#endif /* _CLONE_SESSION_H_ */ +#endif /* _LIBC__INTERNAL__CLONE_SESSION_H_ */ diff --git a/repos/libports/src/lib/libc/internal/cloned_malloc_heap_range.h b/repos/libports/src/lib/libc/internal/cloned_malloc_heap_range.h new file mode 100644 index 000000000..93ccbd030 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/cloned_malloc_heap_range.h @@ -0,0 +1,59 @@ +/* + * \brief Heap content copied from parent via 'fork' + * \author Norman Feske + * \date 2019-08-14 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__CLONED_MALLOC_HEAP_RANGE_H_ +#define _LIBC__INTERNAL__CLONED_MALLOC_HEAP_RANGE_H_ + +/* Genode includes */ +#include <region_map/region_map.h> + +/* libc-internal includes */ +#include <internal/clone_session.h> + +namespace Libc { struct Cloned_malloc_heap_range; } + + +struct Libc::Cloned_malloc_heap_range +{ + Ram_allocator &ram; + Region_map &rm; + + Ram_dataspace_capability ds; + + size_t const size; + addr_t const local_addr; + + Cloned_malloc_heap_range(Ram_allocator &ram, Region_map &rm, + void *start, size_t size) + try : + ram(ram), rm(rm), ds(ram.alloc(size)), size(size), + local_addr(rm.attach_at(ds, (addr_t)start)) + { } + catch (Region_map::Region_conflict) { + error("could not clone heap region ", Hex_range(local_addr, size)); + throw; + } + + void import_content(Clone_connection &clone_connection) + { + clone_connection.memory_content((void *)local_addr, size); + } + + virtual ~Cloned_malloc_heap_range() + { + rm.detach(local_addr); + ram.free(ds); + } +}; + +#endif /* _LIBC__INTERNAL__CLONED_MALLOC_HEAP_RANGE_H_ */ diff --git a/repos/libports/src/lib/libc/internal/current_time.h b/repos/libports/src/lib/libc/internal/current_time.h new file mode 100644 index 000000000..518bfc0c9 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/current_time.h @@ -0,0 +1,31 @@ +/* + * \brief Interface for obtaining the current time + * \author Norman Feske + * \date 2019-09-18 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__CURRENT_TIME_H_ +#define _LIBC__INTERNAL__CURRENT_TIME_H_ + +/* Genode includes */ +#include <base/duration.h> + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + struct Current_time : Interface + { + virtual Duration current_time() = 0; + }; +} + +#endif /* _LIBC__INTERNAL__CURRENT_TIME_H_ */ diff --git a/repos/libports/src/lib/libc/internal/env.h b/repos/libports/src/lib/libc/internal/env.h new file mode 100644 index 000000000..0cd249c9b --- /dev/null +++ b/repos/libports/src/lib/libc/internal/env.h @@ -0,0 +1,134 @@ +/* + * \brief Libc environment + * \author Christian Helmuth + * \author Emery Hemingway + * \author Norman Feske + * \date 2016-01-22 + */ + +/* + * Copyright (C) 2016-2019 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 _LIBC__INTERNAL__ENV_H_ +#define _LIBC__INTERNAL__ENV_H_ + +/* Genode includes */ +#include <base/attached_rom_dataspace.h> +#include <vfs/simple_env.h> + +/* libc includes */ +#include <libc/component.h> /* 'Libc::Env' */ + +namespace Libc { class Env_implementation; } + + +class Libc::Env_implementation : public Libc::Env, public Config_accessor +{ + private: + + Genode::Env &_env; + + Attached_rom_dataspace _config { _env, "config" }; + + Xml_node _vfs_config() + { + try { return _config.xml().sub_node("vfs"); } + catch (Xml_node::Nonexistent_sub_node) { } + try { + Xml_node node = _config.xml().sub_node("libc").sub_node("vfs"); + warning("'<config> <libc> <vfs/>' is deprecated, " + "please move to '<config> <vfs/>'"); + return node; + } + catch (Xml_node::Nonexistent_sub_node) { } + + return Xml_node("<vfs/>"); + } + + Xml_node _libc_config() + { + try { return _config.xml().sub_node("libc"); } + catch (Xml_node::Nonexistent_sub_node) { } + + return Xml_node("<libc/>"); + } + + Vfs::Simple_env _vfs_env; + + Xml_node _config_xml() const override { + return _config.xml(); }; + + public: + + Env_implementation(Genode::Env &env, Allocator &alloc) + : _env(env), _vfs_env(_env, alloc, _vfs_config()) { } + + + Vfs::Env &vfs_env() { return _vfs_env; } + + + /************************* + ** Libc::Env interface ** + *************************/ + + Vfs::File_system &vfs() override { + return _vfs_env.root_dir(); } + + Xml_node libc_config() override { + return _libc_config(); } + + + /************************************* + ** Libc::Config_accessor interface ** + *************************************/ + + Xml_node config() const override { return _config.xml(); } + + + /*************************** + ** Genode::Env interface ** + ***************************/ + + Parent &parent() override { return _env.parent(); } + Cpu_session &cpu() override { return _env.cpu(); } + Region_map &rm() override { return _env.rm(); } + Pd_session &pd() override { return _env.pd(); } + Entrypoint &ep() override { return _env.ep(); } + + Cpu_session_capability cpu_session_cap() override { + return _env.cpu_session_cap(); } + + Pd_session_capability pd_session_cap() override { + return _env.pd_session_cap(); } + + Id_space<Parent::Client> &id_space() override { + return _env.id_space(); } + + Session_capability session(Parent::Service_name const &name, + Parent::Client::Id id, + Parent::Session_args const &args, + Affinity const &aff) override { + return _env.session(name, id, args, aff); } + + void upgrade(Parent::Client::Id id, + Parent::Upgrade_args const &args) override { + return _env.upgrade(id, args); } + + void close(Parent::Client::Id id) override { + return _env.close(id); } + + /* already done by the libc */ + void exec_static_constructors() override { } + + void reinit(Native_capability::Raw raw) override { + _env.reinit(raw); } + + void reinit_main_thread(Capability<Region_map> &stack_area_rm) override { + _env.reinit_main_thread(stack_area_rm); } +}; + +#endif /* _LIBC__INTERNAL__ENV_H_ */ diff --git a/repos/libports/src/lib/libc/libc_errno.h b/repos/libports/src/lib/libc/internal/errno.h similarity index 82% rename from repos/libports/src/lib/libc/libc_errno.h rename to repos/libports/src/lib/libc/internal/errno.h index cab3ee4e1..4e7725a5e 100644 --- a/repos/libports/src/lib/libc/libc_errno.h +++ b/repos/libports/src/lib/libc/internal/errno.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _LIBC_ERRNO_H_ -#define _LIBC_ERRNO_H_ +#ifndef _LIBC__INTERNAL__ERRNO_H_ +#define _LIBC__INTERNAL__ERRNO_H_ /* libc includes */ #include <errno.h> @@ -28,4 +28,4 @@ struct Libc::Errno operator int() const { return -1; } }; -#endif /* _LIBC_ERRNO_H_ */ +#endif /* _LIBC__INTERNAL__ERRNO_H_ */ diff --git a/repos/libports/src/lib/libc/libc_file.h b/repos/libports/src/lib/libc/internal/file.h similarity index 95% rename from repos/libports/src/lib/libc/libc_file.h rename to repos/libports/src/lib/libc/internal/file.h index d92d6e9d8..8ca2980cd 100644 --- a/repos/libports/src/lib/libc/libc_file.h +++ b/repos/libports/src/lib/libc/internal/file.h @@ -12,8 +12,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _LIBC_FILE_H_ -#define _LIBC_FILE_H_ +#ifndef _LIBC__INTERNAL__FILE_H_ +#define _LIBC__INTERNAL__FILE_H_ /* Genode includes */ #include <base/log.h> @@ -73,4 +73,4 @@ static inline Libc::File_descriptor *libc_fd_to_fd(int libc_fd, const char *func #define FNAME_FUNC_WRAPPER(func_name, path, ...) \ FNAME_FUNC_WRAPPER_GENERIC(return, func_name, path, ##__VA_ARGS__ ) -#endif /* _LIBC_FILE_H_ */ +#endif /* _LIBC__INTERNAL__FILE_H_ */ diff --git a/repos/libports/src/lib/libc/internal/file_operations.h b/repos/libports/src/lib/libc/internal/file_operations.h new file mode 100644 index 000000000..1d9366e79 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/file_operations.h @@ -0,0 +1,35 @@ +/* + * \brief Libc-internal file operations + * \author Norman Feske + * \date 2019-09-23 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__FILE_OPERATIONS_H_ +#define _LIBC__INTERNAL__FILE_OPERATIONS_H_ + +/* Genode includes */ +#include <os/path.h> + +/* libc includes */ +#include <limits.h> /* for 'PATH_MAX' */ + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + typedef Genode::Path<PATH_MAX> Absolute_path; + + class Symlink_resolve_error : Exception { }; + + void resolve_symlinks(char const *path, Absolute_path &resolved_path); +} + +#endif /* _LIBC__INTERNAL__FILE_OPERATIONS_H_ */ diff --git a/repos/libports/src/lib/libc/libc_init.h b/repos/libports/src/lib/libc/internal/init.h similarity index 53% rename from repos/libports/src/lib/libc/libc_init.h rename to repos/libports/src/lib/libc/internal/init.h index 0588fce35..8889a69ef 100644 --- a/repos/libports/src/lib/libc/libc_init.h +++ b/repos/libports/src/lib/libc/internal/init.h @@ -11,19 +11,32 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _LIBC_INIT_H_ -#define _LIBC_INIT_H_ +#ifndef _LIBC__INTERNAL__INIT_H_ +#define _LIBC__INTERNAL__INIT_H_ /* Genode includes */ #include <base/env.h> #include <base/heap.h> #include <util/xml_node.h> +#include <vfs/types.h> /* for 'MAX_PATH_LEN' */ /* libc includes */ #include <setjmp.h> /* for 'jmp_buf' type */ +/* libc-internal includes */ +#include <internal/types.h> + namespace Libc { + struct Resume; + struct Suspend; + struct Select; + struct Current_time; + struct Clone_connection; + struct Kernel_routine_scheduler; + struct Watch; + struct Signal; + /** * Support for shared libraries */ @@ -39,17 +52,35 @@ namespace Libc { */ void init_mem_alloc(Genode::Env &env); + /** + * Plugin interface + */ + void init_plugin(Resume &); + + /** + * Virtual file system + */ + void init_vfs_plugin(Suspend &); + + /** + * Select support + */ + void init_select(Suspend &, Resume &, Select &, Signal &); + /** * Support for querying available RAM quota in sysctl functions */ void sysctl_init(Genode::Env &env); + /** + * Support for getpwent + */ + void init_passwd(Xml_node); + /** * Set libc config node */ - void libc_config_init(Genode::Xml_node node); - - struct Clone_connection; + void libc_config_init(Xml_node node); /** * Malloc allocator @@ -58,24 +89,38 @@ namespace Libc { void init_malloc_cloned(Clone_connection &); void reinit_malloc(Genode::Allocator &); + typedef String<Vfs::MAX_PATH_LEN> Rtc_path; + + /** + * Init timing facilities + */ + void init_sleep(Suspend &); + void init_time(Current_time &, Rtc_path const &, Watch &); + + /** + * Socket fs + */ + void init_socket_fs(Suspend &); + /** * Allow thread.cc to access the 'Genode::Env' (needed for the * implementation of condition variables with timeout) */ - void init_pthread_support(Genode::Env &env); + void init_pthread_support(Genode::Env &env, Suspend &, Resume &); - struct Config_accessor : Genode::Interface + struct Config_accessor : Interface { - virtual Genode::Xml_node config() const = 0; + virtual Xml_node config() const = 0; }; /** * Fork mechanism */ void init_fork(Genode::Env &, Config_accessor const &, - Genode::Allocator &heap, Genode::Heap &malloc_heap, int pid); + Genode::Allocator &heap, Heap &malloc_heap, int pid, + Suspend &, Resume &, Signal &, Kernel_routine_scheduler &); - struct Reset_malloc_heap : Genode::Interface + struct Reset_malloc_heap : Interface { virtual void reset_malloc_heap() = 0; }; @@ -85,6 +130,11 @@ namespace Libc { */ void init_execve(Genode::Env &, Genode::Allocator &, void *user_stack, Reset_malloc_heap &); + + /** + * Signal handling + */ + void init_signal(Signal &); } -#endif /* _LIBC_INIT_H_ */ +#endif /* _LIBC__INTERNAL__INIT_H_ */ diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h new file mode 100644 index 000000000..e5edab542 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -0,0 +1,593 @@ +/* + * \brief Libc kernel for main and pthreads user contexts + * \author Christian Helmuth + * \author Emery Hemingway + * \author Norman Feske + * \date 2016-01-22 + */ + +/* + * Copyright (C) 2016-2019 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 _LIBC__INTERNAL__KERNEL_H_ +#define _LIBC__INTERNAL__KERNEL_H_ + +/* base-internal includes */ +#include <internal/call_func.h> + +/* libc includes */ +#include <libc/select.h> + +/* libc-internal includes */ +#include <internal/types.h> +#include <internal/malloc_ram_allocator.h> +#include <internal/cloned_malloc_heap_range.h> +#include <internal/timer.h> +#include <internal/pthread_pool.h> +#include <internal/init.h> +#include <internal/env.h> +#include <internal/vfs_plugin.h> +#include <internal/suspend.h> +#include <internal/resume.h> +#include <internal/select.h> +#include <internal/kernel_routine.h> +#include <internal/current_time.h> +#include <internal/kernel_timer_accessor.h> +#include <internal/watch.h> +#include <internal/signal.h> + +namespace Libc { class Kernel; } + + +/** + * Libc "kernel" + * + * This class represents the "kernel" of the libc-based application + * Blocking and deblocking happens here on libc functions like read() or + * select(). This combines blocking of the VFS backend and other signal sources + * (e.g., timers). The libc task runs on the component thread and allocates a + * secondary stack for the application task. Context switching uses + * setjmp/longjmp. + */ +struct Libc::Kernel final : Vfs::Io_response_handler, + Entrypoint::Io_progress_handler, + Reset_malloc_heap, + Resume, + Suspend, + Select, + Kernel_routine_scheduler, + Current_time, + Watch +{ + private: + + /** + * Pointer to singleton instance + */ + static Kernel *_kernel_ptr; + + Genode::Env &_env; + + /** + * Allocator for libc-internal data + * + * Not mirrored to forked processes. Preserved across 'execve' calls. + */ + Allocator &_heap; + + /** + * Allocator for application-owned data + * + * Mirrored to forked processes. Not preserved across 'execve' calls. + */ + Reconstructible<Malloc_ram_allocator> _malloc_ram { _heap, _env.ram() }; + + Constructible<Heap> _malloc_heap { }; + + Registry<Registered<Cloned_malloc_heap_range> > _cloned_heap_ranges { }; + + /** + * Reset_malloc_heap interface used by execve + */ + void reset_malloc_heap() override; + + Env_implementation _libc_env { _env, _heap }; + + bool const _update_mtime = _libc_env.libc_config().attribute_value("update_mtime", true); + + Vfs_plugin _vfs { _libc_env, _libc_env.vfs_env(), _heap, *this, + _update_mtime ? Vfs_plugin::Update_mtime::YES + : Vfs_plugin::Update_mtime::NO, + _libc_env.config() }; + + bool const _cloned = _libc_env.libc_config().attribute_value("cloned", false); + pid_t const _pid = _libc_env.libc_config().attribute_value("pid", 0U); + + Xml_node _passwd_config() + { + return _libc_env.libc_config().has_sub_node("passwd") + ? _libc_env.libc_config().sub_node("passwd") + : Xml_node("<empty/>"); + } + + typedef String<Vfs::MAX_PATH_LEN> Config_attr; + + Config_attr const _rtc_path = _libc_env.libc_config().attribute_value("rtc", Config_attr()); + + /* handler for watching the stdout's info pseudo file */ + Constructible<Watch_handler<Kernel>> _terminal_resize_handler { }; + + void _handle_terminal_resize(); + + /* handler for watching user interrupts (control-c) */ + Constructible<Watch_handler<Kernel>> _user_interrupt_handler { }; + + void _handle_user_interrupt(); + + Signal _signal { _pid }; + + Reconstructible<Io_signal_handler<Kernel>> _resume_main_handler { + _env.ep(), *this, &Kernel::_resume_main }; + + jmp_buf _kernel_context; + jmp_buf _user_context; + bool _valid_user_context = false; + bool _dispatch_pending_io_signals = false; + + /* io_progress_handler marker */ + bool _io_ready { false }; + + Thread &_myself { *Thread::myself() }; + + addr_t _kernel_stack = Thread::mystack().top; + + size_t _user_stack_size(); + + void *_user_stack = { + _myself.alloc_secondary_stack(_myself.name().string(), + _user_stack_size()) }; + + void (*_original_suspended_callback)() = nullptr; + + enum State { KERNEL, USER }; + + State _state = KERNEL; + + Application_code *_nested_app_code = nullptr; + + Application_code *_app_code = nullptr; + bool _app_returned = false; + + bool _resume_main_once = false; + bool _suspend_scheduled = false; + + Select_handler_base *_scheduled_select_handler = nullptr; + + Kernel_routine *_kernel_routine = nullptr; + + void _resume_main() { _resume_main_once = true; } + + Kernel_timer_accessor _timer_accessor { _env }; + + struct Main_timeout : Timeout_handler + { + Timer_accessor &_timer_accessor; + Constructible<Timeout> _timeout; + Kernel &_kernel; + + void _construct_timeout_once() + { + if (!_timeout.constructed()) + _timeout.construct(_timer_accessor, *this); + } + + Main_timeout(Timer_accessor &timer_accessor, Kernel &kernel) + : _timer_accessor(timer_accessor), _kernel(kernel) + { } + + void timeout(uint64_t timeout_ms) + { + _construct_timeout_once(); + _timeout->start(timeout_ms); + } + + uint64_t duration_left() + { + _construct_timeout_once(); + return _timeout->duration_left(); + } + + void handle_timeout() override + { + _kernel._resume_main(); + } + }; + + Main_timeout _main_timeout { _timer_accessor, *this }; + + Pthread_pool _pthreads { _timer_accessor }; + + Constructible<Clone_connection> _clone_connection { }; + + struct Resumer + { + GENODE_RPC(Rpc_resume, void, resume); + GENODE_RPC_INTERFACE(Rpc_resume); + }; + + struct Resumer_component : Rpc_object<Resumer, Resumer_component> + { + Kernel &_kernel; + + Resumer_component(Kernel &kernel) : _kernel(kernel) { } + + void resume() { _kernel.run_after_resume(); } + }; + + /** + * Trampoline to application (user) code + * + * This function is called by the main thread. + */ + static void _user_entry(Kernel *kernel) + { + struct Check : Suspend_functor { + bool suspend() override { return true; } + } check; + + kernel->_app_code->execute(); + kernel->_app_returned = true; + kernel->_suspend_main(check, 0); + } + + bool _main_context() const { return &_myself == Thread::myself(); } + + /** + * Utility to switch main context to kernel + * + * User context must be saved explicitly before this function is called + * to enable _switch_to_user() later. + */ + void _switch_to_kernel() + { + _state = KERNEL; + _longjmp(_kernel_context, 1); + } + + /** + * Utility to switch main context to user + * + * Kernel context must be saved explicitly before this function is called + * to enable _switch_to_kernel() later. + */ + void _switch_to_user() + { + if (!_valid_user_context) + error("switching to invalid user context"); + + _resume_main_once = false; + _state = USER; + _longjmp(_user_context, 1); + } + + uint64_t _suspend_main(Suspend_functor &check, uint64_t timeout_ms) + { + /* check that we're not running on libc kernel context */ + if (Thread::mystack().top == _kernel_stack) { + error("libc suspend() called from non-user context (", + __builtin_return_address(0), ") - aborting"); + exit(1); + } + + if (!check.suspend() && !_kernel_routine) + return 0; + + if (timeout_ms > 0) + _main_timeout.timeout(timeout_ms); + + if (!_setjmp(_user_context)) { + _valid_user_context = true; + _switch_to_kernel(); + } else { + _valid_user_context = false; + _signal.execute_signal_handlers(); + } + + /* + * During the suspension of the application code a nested + * Libc::with_libc() call took place, which will be executed + * before returning to the first Libc::with_libc() call. + */ + if (_nested_app_code) { + + /* + * We have to explicitly set the user context back to true + * because we are borrowing it to execute our nested application + * code. + */ + _valid_user_context = true; + + _nested_app_code->execute(); + _nested_app_code = nullptr; + _longjmp(_kernel_context, 1); + } + + return timeout_ms > 0 ? _main_timeout.duration_left() : 0; + } + + void _init_file_descriptors(); + + void _clone_state_from_parent(); + + public: + + Kernel(Genode::Env &env, Allocator &heap); + + ~Kernel() { error(__PRETTY_FUNCTION__, " should not be executed!"); } + + Libc::Env & libc_env() { return _libc_env; } + + /** + * Setup kernel context and run libc application main context + * + * This function is called by the component thread on with_libc(). + */ + void run(Application_code &app_code) + { + if (!_main_context() || _state != KERNEL) { + error(__PRETTY_FUNCTION__, " called from non-kernel context"); + return; + } + + _resume_main_once = false; + _app_returned = false; + _app_code = &app_code; + + /* save continuation of libc kernel (incl. current stack) */ + if (!_setjmp(_kernel_context)) { + /* _setjmp() returned directly -> switch to user stack and call application code */ + + if (_cloned) { + _switch_to_user(); + } else { + _state = USER; + call_func(_user_stack, (void *)_user_entry, (void *)this); + } + + /* never reached */ + } + + /* _setjmp() returned after _longjmp() - user context suspended */ + + while ((!_app_returned) && (!_suspend_scheduled)) { + + if (_kernel_routine) { + Kernel_routine &routine = *_kernel_routine; + + /* the 'kernel_routine' may install another kernel routine */ + _kernel_routine = nullptr; + routine.execute_in_kernel(); + if (!_kernel_routine) + _switch_to_user(); + } + + if (_dispatch_pending_io_signals) { + /* dispatch pending signals but don't block */ + while (_env.ep().dispatch_pending_io_signal()) ; + } else { + /* block for signals */ + _env.ep().wait_and_dispatch_one_io_signal(); + } + + if (!_kernel_routine && _resume_main_once && !_setjmp(_kernel_context)) + _switch_to_user(); + } + + _suspend_scheduled = false; + } + + /* + * Run libc application main context after suspend and resume + */ + void run_after_resume() + { + if (!_setjmp(_kernel_context)) + _switch_to_user(); + + while ((!_app_returned) && (!_suspend_scheduled)) { + _env.ep().wait_and_dispatch_one_io_signal(); + if (_resume_main_once && !_setjmp(_kernel_context)) + _switch_to_user(); + } + + _suspend_scheduled = false; + } + + /** + * Resume interface + */ + void resume_all() override + { + if (_app_returned) { + if (_scheduled_select_handler) + _scheduled_select_handler->dispatch_select(); + } else { + if (_main_context()) + _resume_main(); + else + Signal_transmitter(*_resume_main_handler).submit(); + } + + _pthreads.resume_all(); + } + + /** + * Suspend interface + */ + uint64_t suspend(Suspend_functor &check, uint64_t timeout_ms) override + { + if (timeout_ms > 0 + && timeout_ms > _timer_accessor.timer().max_timeout()) { + warning("libc: limiting exceeding timeout of ", + timeout_ms, " ms to maximum of ", + _timer_accessor.timer().max_timeout(), " ms"); + + timeout_ms = min(timeout_ms, _timer_accessor.timer().max_timeout()); + } + + return _main_context() ? _suspend_main(check, timeout_ms) + : _pthreads.suspend_myself(check, timeout_ms); + } + + void dispatch_pending_io_signals() + { + if (!_main_context()) return; + + if (!_setjmp(_user_context)) { + _valid_user_context = true; + _dispatch_pending_io_signals = true; + _resume_main_once = true; /* afterwards resume main */ + _switch_to_kernel(); + } else { + _valid_user_context = false; + _dispatch_pending_io_signals = false; + _signal.execute_signal_handlers(); + } + } + + /** + * Current_time interface + */ + Duration current_time() override + { + return _timer_accessor.timer().curr_time(); + } + + /** + * Called from the main context (by fork) + */ + void schedule_suspend(void(*original_suspended_callback) ()); + + /** + * Select interface + */ + void schedule_select(Select_handler_base &h) override + { + _scheduled_select_handler = &h; + } + + /** + * Select interface + */ + void deschedule_select() override + { + _scheduled_select_handler = nullptr; + } + + /** + * Called from the context of the initial thread (on fork) + */ + void entrypoint_suspended() + { + _resume_main_handler.destruct(); + + _original_suspended_callback(); + } + + /** + * Called from the context of the initial thread (after fork) + */ + void entrypoint_resumed() + { + _resume_main_handler.construct(_env.ep(), *this, &Kernel::_resume_main); + + Resumer_component resumer { *this }; + + Capability<Resumer> resumer_cap = + _env.ep().rpc_ep().manage(&resumer); + + resumer_cap.call<Resumer::Rpc_resume>(); + + _env.ep().rpc_ep().dissolve(&resumer); + } + + /** + * Return if main is currently suspended + */ + bool main_suspended() { return _state == KERNEL; } + + /** + * Public alias for _main_context() + */ + bool main_context() const { return _main_context(); } + + /** + * Execute application code while already executing in run() + */ + void nested_execution(Application_code &app_code) + { + _nested_app_code = &app_code; + + if (!_setjmp(_kernel_context)) { + _switch_to_user(); + } + } + + /** + * Watch interface + */ + Vfs::Vfs_watch_handle *alloc_watch_handle(char const *path) override + { + Vfs::Vfs_watch_handle *watch_handle { nullptr }; + typedef Vfs::Directory_service::Watch_result Result; + return _libc_env.vfs().watch(path, &watch_handle, _heap) == Result::WATCH_OK + ? watch_handle : nullptr; + } + + + /**************************************** + ** Vfs::Io_response_handler interface ** + ****************************************/ + + void read_ready_response() override { + _io_ready = true; } + + void io_progress_response() override { + _io_ready = true; } + + + /********************************************** + * Entrypoint::Io_progress_handler interface ** + **********************************************/ + + void handle_io_progress() override; + + /** + * Kernel_routine_scheduler interface + */ + void register_kernel_routine(Kernel_routine &kernel_routine) override + { + _kernel_routine = &kernel_routine; + } + + + /******************************** + ** Access to kernel singleton ** + ********************************/ + + struct Kernel_called_prior_initialization : Exception { }; + + static Kernel &kernel() + { + if (!_kernel_ptr) + throw Kernel_called_prior_initialization(); + + return *_kernel_ptr; + } +}; + +#endif /* _LIBC__INTERNAL__KERNEL_H_ */ diff --git a/repos/libports/src/lib/libc/internal/kernel_routine.h b/repos/libports/src/lib/libc/internal/kernel_routine.h new file mode 100644 index 000000000..78ad5edba --- /dev/null +++ b/repos/libports/src/lib/libc/internal/kernel_routine.h @@ -0,0 +1,46 @@ +/* + * \brief Interface executing code in the context of the libc kernel + * \author Norman Feske + * \date 2019-09-18 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__KERNEL_ROUTINE_H_ +#define _LIBC__INTERNAL__KERNEL_ROUTINE_H_ + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + /** + * Base class to be implemented by a kernel routine + */ + struct Kernel_routine : Interface + { + virtual void execute_in_kernel() = 0; + }; + + struct Kernel_routine_scheduler : Interface + { + /** + * Register routine to be called once on the next libc-kernel activation + * + * The specified routine is executed only once. For a repeated execution, + * the routine must call 'register_kernel_routine' with itself as + * argument. + * + * This mechanism is used by 'fork' to implement the blocking for the + * startup of a new child and for 'wait4'. + */ + virtual void register_kernel_routine(Kernel_routine &) = 0; + }; +} + +#endif /* _LIBC__INTERNAL__KERNEL_ROUTINE_H_ */ diff --git a/repos/libports/src/lib/libc/internal/kernel_timer_accessor.h b/repos/libports/src/lib/libc/internal/kernel_timer_accessor.h new file mode 100644 index 000000000..fad0cc35f --- /dev/null +++ b/repos/libports/src/lib/libc/internal/kernel_timer_accessor.h @@ -0,0 +1,50 @@ +/* + * \brief Interface for accessing the libc's kernel timer + * \author Norman Feske + * \date 2019-09-19 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__KERNEL_TIMER_ACCESSOR_H_ +#define _LIBC__INTERNAL__KERNEL_TIMER_ACCESSOR_H_ + +/* Genode includes */ +#include <base/env.h> +#include <base/lock.h> +#include <timer_session/connection.h> + +namespace Libc { struct Kernel_timer_accessor; } + +struct Libc::Kernel_timer_accessor : Timer_accessor +{ + Genode::Env &_env; + + /* + * The '_timer' is constructed by whatever thread (main thread + * of pthread) that uses a time-related function first. Hence, + * the construction must be protected by a lock. + */ + Lock _lock; + + Constructible<Timer> _timer; + + Kernel_timer_accessor(Genode::Env &env) : _env(env) { } + + Timer &timer() override + { + Lock::Guard guard(_lock); + + if (!_timer.constructed()) + _timer.construct(_env); + + return *_timer; + } +}; + +#endif /* _LIBC__INTERNAL__KERNEL_TIMER_ACCESSOR_H_ */ diff --git a/repos/libports/src/lib/libc/internal/legacy.h b/repos/libports/src/lib/libc/internal/legacy.h new file mode 100644 index 000000000..cea751316 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/legacy.h @@ -0,0 +1,36 @@ +/* + * \brief Globally available accessors to Libc kernel functionality + * \author Norman Feske + * \date 2019-09-18 + */ + +/* + * Copyright (C) 2016-2019 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 _LIBC__INTERNAL__LEGACY_H_ +#define _LIBC__INTERNAL__LEGACY_H_ + +/* Genode includes */ +#include <vfs/vfs_handle.h> /* needed for 'watch' */ + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + /* + * XXX called only by 'Libc::Vfs_plugin::read' + */ + void dispatch_pending_io_signals(); + + /* + * XXX this function is solely needed to support noux fork mechanism + */ + void schedule_suspend(void (*) ()); +} + +#endif /* _LIBC__INTERNAL__LEGACY_H_ */ diff --git a/repos/libports/src/lib/libc/internal/malloc_ram_allocator.h b/repos/libports/src/lib/libc/internal/malloc_ram_allocator.h new file mode 100644 index 000000000..e69059d87 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/malloc_ram_allocator.h @@ -0,0 +1,76 @@ +/* + * \brief Utility for tracking the allocation of dataspaces by the malloc heap + * \author Norman Feske + * \date 2019-08-20 + */ + +/* + * Copyright (C) 2016-2019 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 _LIBC__INTERNAL__MALLOC_RAM_ALLOCATOR_H_ +#define _LIBC__INTERNAL__MALLOC_RAM_ALLOCATOR_H_ + +/* Genode includes */ +#include <base/registry.h> +#include <base/allocator.h> +#include <base/ram_allocator.h> + +namespace Libc { struct Malloc_ram_allocator; } + + +struct Libc::Malloc_ram_allocator : Ram_allocator +{ + typedef Genode::Allocator Allocator; + + Allocator &_md_alloc; + Ram_allocator &_ram; + + struct Dataspace + { + Ram_dataspace_capability cap; + Dataspace(Ram_dataspace_capability cap) : cap(cap) { } + virtual ~Dataspace() { } + }; + + Registry<Registered<Dataspace> > _dataspaces { }; + + void _release(Registered<Dataspace> &ds) + { + _ram.free(ds.cap); + destroy(_md_alloc, &ds); + } + + Malloc_ram_allocator(Allocator &md_alloc, Ram_allocator &ram) + : _md_alloc(md_alloc), _ram(ram) { } + + ~Malloc_ram_allocator() + { + _dataspaces.for_each([&] (Registered<Dataspace> &ds) { + _release(ds); }); + } + + Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override + { + Ram_dataspace_capability cap = _ram.alloc(size, cached); + new (_md_alloc) Registered<Dataspace>(_dataspaces, cap); + return cap; + } + + void free(Ram_dataspace_capability ds_cap) override + { + _dataspaces.for_each([&] (Registered<Dataspace> &ds) { + if (ds_cap == ds.cap) + _release(ds); }); + } + + size_t dataspace_size(Ram_dataspace_capability ds_cap) const override + { + return _ram.dataspace_size(ds_cap); + } +}; + +#endif /* _LIBC__INTERNAL__MALLOC_RAM_ALLOCATOR_H_ */ diff --git a/repos/libports/src/lib/libc/libc_mem_alloc.h b/repos/libports/src/lib/libc/internal/mem_alloc.h similarity index 57% rename from repos/libports/src/lib/libc/libc_mem_alloc.h rename to repos/libports/src/lib/libc/internal/mem_alloc.h index 981ccaf86..6cce59f2f 100644 --- a/repos/libports/src/lib/libc/libc_mem_alloc.h +++ b/repos/libports/src/lib/libc/internal/mem_alloc.h @@ -4,8 +4,15 @@ * \date 2012-05-18 */ -#ifndef _LIBC_MEM_ALLOC_H_ -#define _LIBC_MEM_ALLOC_H_ +/* + * Copyright (C) 2012-2019 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 _LIBC__INTERNAL__MEM_ALLOC_H_ +#define _LIBC__INTERNAL__MEM_ALLOC_H_ /* Genode includes */ #include <base/ram_allocator.h> @@ -14,13 +21,16 @@ #include <util/list.h> #include <rm_session/rm_session.h> +/* libc-internal includes */ +#include <internal/types.h> + namespace Libc { struct Mem_alloc { - virtual void *alloc(Genode::size_t size, Genode::size_t align_log2) = 0; + virtual void *alloc(size_t size, size_t align_log2) = 0; virtual void free(void *ptr) = 0; - virtual Genode::size_t size_at(void const *ptr) const = 0; + virtual size_t size_at(void const *ptr) const = 0; }; /** @@ -37,14 +47,14 @@ namespace Libc { MAX_CHUNK_SIZE = 1024*1024 }; - class Dataspace : public Genode::List<Dataspace>::Element + class Dataspace : public List<Dataspace>::Element { public: - Genode::Ram_dataspace_capability cap; + Ram_dataspace_capability cap; void *local_addr; - Dataspace(Genode::Ram_dataspace_capability c, void *a) + Dataspace(Ram_dataspace_capability c, void *a) : cap(c), local_addr(a) {} inline void * operator new(__SIZE_TYPE__, void* addr) { @@ -53,21 +63,21 @@ namespace Libc { inline void operator delete(void*) { } }; - class Dataspace_pool : public Genode::List<Dataspace> + class Dataspace_pool : public List<Dataspace> { private: - Genode::Ram_allocator *_ram; /* ram session for backing store */ - Genode::Region_map *_region_map; /* region map of address space */ - bool const _executable; /* whether to allocate executable dataspaces */ + Ram_allocator *_ram; /* RAM session for backing store */ + Region_map *_region_map; /* region map of address space */ + bool const _executable; /* whether to allocate executable dataspaces */ public: /** * Constructor */ - Dataspace_pool(Genode::Ram_allocator *ram, - Genode::Region_map *rm, bool executable) : + Dataspace_pool(Ram_allocator *ram, + Region_map *rm, bool executable) : _ram(ram), _region_map(rm), _executable(executable) { } @@ -88,16 +98,16 @@ namespace Libc { * Region_map::Region_conflict * \return 0 on success or negative error code */ - int expand(Genode::size_t size, Genode::Range_allocator *alloc); + int expand(size_t size, Range_allocator *alloc); - void reassign_resources(Genode::Ram_allocator *ram, Genode::Region_map *rm) { + void reassign_resources(Ram_allocator *ram, Region_map *rm) { _ram = ram, _region_map = rm; } }; - Genode::Lock mutable _lock; - Dataspace_pool _ds_pool; /* list of dataspaces */ - Genode::Allocator_avl _alloc; /* local allocator */ - Genode::size_t _chunk_size; + Lock mutable _lock; + Dataspace_pool _ds_pool; /* list of dataspaces */ + Allocator_avl _alloc; /* local allocator */ + size_t _chunk_size; /** * Try to allocate block at our local allocator @@ -107,12 +117,11 @@ namespace Libc { * This function is a utility used by 'alloc' to avoid * code duplication. */ - bool _try_local_alloc(Genode::size_t size, void **out_addr); + bool _try_local_alloc(size_t size, void **out_addr); public: - Mem_alloc_impl(Genode::Region_map &rm, - Genode::Ram_allocator &ram, + Mem_alloc_impl(Region_map &rm, Ram_allocator &ram, bool executable = false) : _ds_pool(&ram, &rm, executable), @@ -120,10 +129,10 @@ namespace Libc { _chunk_size(MIN_CHUNK_SIZE) { } - void *alloc(Genode::size_t size, Genode::size_t align_log2); + void *alloc(size_t size, size_t align_log2); void free(void *ptr); - Genode::size_t size_at(void const *ptr) const; + size_t size_at(void const *ptr) const; }; } -#endif /* _LIBC_MEM_ALLOC_H_ */ +#endif /* _LIBC__INTERNAL__MEM_ALLOC_H_ */ diff --git a/repos/libports/src/lib/libc/libc_mmap_registry.h b/repos/libports/src/lib/libc/internal/mmap_registry.h similarity index 69% rename from repos/libports/src/lib/libc/libc_mmap_registry.h rename to repos/libports/src/lib/libc/internal/mmap_registry.h index 81339e30a..81abeba45 100644 --- a/repos/libports/src/lib/libc/libc_mmap_registry.h +++ b/repos/libports/src/lib/libc/internal/mmap_registry.h @@ -4,8 +4,15 @@ * \date 2012-08-16 */ -#ifndef _LIBC_MMAP_REGISTRY_H_ -#define _LIBC_MMAP_REGISTRY_H_ +/* + * Copyright (C) 2012-2019 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 _LIBC__INTERNAL__MMAP_REGISTRY_H_ +#define _LIBC__INTERNAL__MMAP_REGISTRY_H_ /* Genode includes */ #include <base/lock.h> @@ -13,11 +20,12 @@ #include <base/log.h> #include <libc/allocator.h> -/* libc-internal includes */ -#include <libc-plugin/plugin.h> - /* libc includes */ #include <errno.h> +#include <libc-plugin/plugin.h> + +/* libc-internal includes */ +#include <internal/types.h> namespace Libc { @@ -34,7 +42,7 @@ class Libc::Mmap_registry { public: - struct Entry : Genode::List<Entry>::Element + struct Entry : List<Entry>::Element { void * const start; Plugin * const plugin; @@ -47,9 +55,9 @@ class Libc::Mmap_registry Libc::Allocator _md_alloc; - Genode::List<Mmap_registry::Entry> _list; + List<Mmap_registry::Entry> _list; - Genode::Lock mutable _lock; + Lock mutable _lock; /* * Common for both const and non-const lookup functions @@ -76,13 +84,13 @@ class Libc::Mmap_registry public: - void insert(void *start, Genode::size_t len, Plugin *plugin) + void insert(void *start, size_t len, Plugin *plugin) { - Genode::Lock::Guard guard(_lock); + Lock::Guard guard(_lock); if (_lookup_by_addr_unsynchronized(start)) { - Genode::warning(__func__, ": mmap region at ", start, " " - "is already registered"); + warning(__func__, ": mmap region at ", start, " " + "is already registered"); return; } @@ -91,7 +99,7 @@ class Libc::Mmap_registry Plugin *lookup_plugin_by_addr(void *start) const { - Genode::Lock::Guard guard(_lock); + Lock::Guard guard(_lock); Entry const * const e = _lookup_by_addr_unsynchronized(start); return e ? e->plugin : 0; @@ -99,20 +107,20 @@ class Libc::Mmap_registry bool registered(void *start) const { - Genode::Lock::Guard guard(_lock); + Lock::Guard guard(_lock); return _lookup_by_addr_unsynchronized(start) != 0; } void remove(void *start) { - Genode::Lock::Guard guard(_lock); + Lock::Guard guard(_lock); Entry *e = _lookup_by_addr_unsynchronized(start); if (!e) { - Genode::warning("lookup for address ", start, " " - "in in mmap registry failed"); + warning("lookup for address ", start, " " + "in in mmap registry failed"); return; } @@ -122,4 +130,4 @@ class Libc::Mmap_registry }; -#endif /* _LIBC_MMAP_REGISTRY_H_ */ +#endif /* _LIBC__INTERNAL__MMAP_REGISTRY_H_ */ diff --git a/repos/libports/src/lib/libc/thread.h b/repos/libports/src/lib/libc/internal/pthread.h similarity index 72% rename from repos/libports/src/lib/libc/thread.h rename to repos/libports/src/lib/libc/internal/pthread.h index c4f3af108..674020c28 100644 --- a/repos/libports/src/lib/libc/thread.h +++ b/repos/libports/src/lib/libc/internal/pthread.h @@ -13,38 +13,49 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _INCLUDE__SRC_LIB_PTHREAD_THREAD_H_ -#define _INCLUDE__SRC_LIB_PTHREAD_THREAD_H_ +#ifndef _LIBC__INTERNAL__PTHREAD_H_ +#define _LIBC__INTERNAL__PTHREAD_H_ /* Genode includes */ #include <libc/component.h> #include <util/reconstructible.h> +/* libc includes */ #include <pthread.h> +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + struct Pthread; + struct Pthread_registry; +} + + /* * Used by 'pthread_self()' to find out if the current thread is an alien * thread. */ -class Pthread_registry +class Libc::Pthread_registry { private: enum { MAX_NUM_PTHREADS = 128 }; - pthread_t _array[MAX_NUM_PTHREADS] = { 0 }; + Pthread *_array[MAX_NUM_PTHREADS] = { 0 }; public: - void insert(pthread_t thread); + void insert(Pthread &thread); - void remove(pthread_t thread); + void remove(Pthread &thread); - bool contains(pthread_t thread); + bool contains(Pthread &thread); }; -Pthread_registry &pthread_registry(); +Libc::Pthread_registry &pthread_registry(); extern "C" { @@ -68,7 +79,7 @@ struct Genode::Thread::Tls::Base /** * Register thread-local-storage object at Genode thread */ - static void tls(Genode::Thread &thread, Tls::Base &tls) + static void tls(Thread &thread, Tls::Base &tls) { thread._tls = Tls { &tls }; } @@ -92,13 +103,13 @@ struct Genode::Thread::Tls::Base }; -struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base +struct Libc::Pthread : Noncopyable, Thread::Tls::Base { typedef void *(*start_routine_t) (void *); private: - struct Thread_object : Genode::Thread + struct Thread_object : Thread { start_routine_t _start_routine; void *_arg; @@ -106,16 +117,16 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base void *&_stack_addr; size_t &_stack_size; - enum { WEIGHT = Genode::Cpu_session::Weight::DEFAULT_WEIGHT }; + enum { WEIGHT = Cpu_session::Weight::DEFAULT_WEIGHT }; /* 'stack_addr_out' and 'stack_size_out' are written when the thread starts */ Thread_object(char const *name, size_t stack_size, - Genode::Cpu_session *cpu, - Genode::Affinity::Location location, + Cpu_session *cpu, + Affinity::Location location, start_routine_t start_routine, void *arg, void *&stack_addr_out, size_t &stack_size_out) : - Genode::Thread(WEIGHT, name, stack_size, Type::NORMAL, cpu, location), + Thread(WEIGHT, name, stack_size, Type::NORMAL, cpu, location), _start_routine(start_routine), _arg(arg), _stack_addr(stack_addr_out), _stack_size(stack_size_out) { } @@ -123,27 +134,27 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base void entry() override; }; - Genode::Constructible<Thread_object> _thread_object; + Constructible<Thread_object> _thread_object; /* * Helper to construct '_thread_object' in class initializer */ template <typename... ARGS> - Genode::Thread &_construct_thread_object(ARGS &&... args) + Thread &_construct_thread_object(ARGS &&... args) { _thread_object.construct(args...); return *_thread_object; } /* - * Refers to '_thread_object' or an external 'Genode::Thread' object + * Refers to '_thread_object' or an external 'Thread' object */ - Genode::Thread &_thread; + Thread &_thread; void _associate_thread_with_pthread() { - Genode::Thread::Tls::Base::tls(_thread, *this); - pthread_registry().insert(this); + Thread::Tls::Base::tls(_thread, *this); + pthread_registry().insert(*this); } bool _exiting = false; @@ -154,11 +165,11 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base * capability, which needs to be released before the thread can be * destroyed. * - * Also, we cannot use 'Genode::Thread::join()', because it only + * Also, we cannot use 'Thread::join()', because it only * returns when the thread entry function returns, which does not * happen with 'pthread_cancel()'. */ - Genode::Lock _join_lock { Genode::Lock::LOCKED }; + Lock _join_lock { Lock::LOCKED }; /* return value for 'pthread_join()' */ void *_retval = PTHREAD_CANCELED; @@ -172,9 +183,9 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base /** * Constructor for threads created via 'pthread_create' */ - pthread(start_routine_t start_routine, + Pthread(start_routine_t start_routine, void *arg, size_t stack_size, char const * name, - Genode::Cpu_session * cpu, Genode::Affinity::Location location) + Cpu_session * cpu, Affinity::Location location) : _thread(_construct_thread_object(name, stack_size, cpu, location, start_routine, arg, @@ -187,21 +198,21 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base * Constructor to create pthread object out of existing thread, * i.e., the main thread */ - pthread(Genode::Thread &existing_thread) + Pthread(Thread &existing_thread) : _thread(existing_thread) { /* obtain stack attributes of main thread */ - Genode::Thread::Stack_info info = Genode::Thread::mystack(); + Thread::Stack_info info = Thread::mystack(); _stack_addr = (void *)info.base; _stack_size = info.top - info.base; _associate_thread_with_pthread(); } - ~pthread() + ~Pthread() { - pthread_registry().remove(this); + pthread_registry().remove(*this); } void start() { _thread.start(); } @@ -225,6 +236,12 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base }; +struct pthread : Libc::Pthread +{ + using Libc::Pthread::Pthread; +}; + + namespace Libc { void init_pthread_support(Env &env); } -#endif /* _INCLUDE__SRC_LIB_PTHREAD_THREAD_H_ */ +#endif /* _LIBC__INTERNAL__PTHREAD_H_ */ diff --git a/repos/libports/src/lib/libc/internal/pthread_pool.h b/repos/libports/src/lib/libc/internal/pthread_pool.h new file mode 100644 index 000000000..c03343d90 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/pthread_pool.h @@ -0,0 +1,107 @@ +/* + * \brief Pthread handling + * \author Christian Prochaska + * \author Christian Helmuth + * \date 2016-12-13 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__PTHREAD_POOL_H_ +#define _LIBC__INTERNAL__PTHREAD_POOL_H_ + +/* libc-internal includes */ +#include <internal/legacy.h> +#include <internal/suspend.h> + +namespace Libc { class Pthread_pool; } + + +struct Libc::Pthread_pool +{ + struct Pthread : Timeout_handler + { + Lock lock { Lock::LOCKED }; + Pthread *next { nullptr }; + + Timer_accessor &_timer_accessor; + Constructible<Timeout> _timeout; + + void _construct_timeout_once() + { + if (!_timeout.constructed()) + _timeout.construct(_timer_accessor, *this); + } + + Pthread(Timer_accessor &timer_accessor, uint64_t timeout_ms) + : _timer_accessor(timer_accessor) + { + if (timeout_ms > 0) { + _construct_timeout_once(); + _timeout->start(timeout_ms); + } + } + + uint64_t duration_left() + { + _construct_timeout_once(); + return _timeout->duration_left(); + } + + void handle_timeout() override + { + lock.unlock(); + } + }; + + Lock mutex; + Pthread *pthreads = nullptr; + Timer_accessor &timer_accessor; + + + Pthread_pool(Timer_accessor &timer_accessor) + : timer_accessor(timer_accessor) { } + + void resume_all() + { + Lock::Guard g(mutex); + + for (Pthread *p = pthreads; p; p = p->next) + p->lock.unlock(); + } + + uint64_t suspend_myself(Suspend_functor & check, uint64_t timeout_ms) + { + Pthread myself { timer_accessor, timeout_ms }; + { + Lock::Guard g(mutex); + + myself.next = pthreads; + pthreads = &myself; + } + + if (check.suspend()) + myself.lock.lock(); + + { + Lock::Guard g(mutex); + + /* address of pointer to next pthread allows to change the head */ + for (Pthread **next = &pthreads; *next; next = &(*next)->next) { + if (*next == &myself) { + *next = myself.next; + break; + } + } + } + + return timeout_ms > 0 ? myself.duration_left() : 0; + } +}; + +#endif /* _LIBC__INTERNAL__PTHREAD_POOL_H_ */ diff --git a/repos/libports/src/lib/libc/internal/resume.h b/repos/libports/src/lib/libc/internal/resume.h new file mode 100644 index 000000000..6d5bd193c --- /dev/null +++ b/repos/libports/src/lib/libc/internal/resume.h @@ -0,0 +1,34 @@ +/* + * \brief Interface for resuming the execution of user contexts + * \author Norman Feske + * \date 2019-09-18 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__RESUME_H_ +#define _LIBC__INTERNAL__RESUME_H_ + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + /** + * Interface to resume all user contexts + */ + struct Resume : Interface + { + /** + * Resumes the main user context as well as any pthread context + */ + virtual void resume_all() = 0; + }; +} + +#endif /* _LIBC__INTERNAL__RESUME_H_ */ diff --git a/repos/libports/src/lib/libc/internal/select.h b/repos/libports/src/lib/libc/internal/select.h new file mode 100644 index 000000000..e1b65e62d --- /dev/null +++ b/repos/libports/src/lib/libc/internal/select.h @@ -0,0 +1,35 @@ +/* + * \brief Interface for registering select handler + * \author Norman Feske + * \date 2019-09-18 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__SELECT_H_ +#define _LIBC__INTERNAL__SELECT_H_ + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + struct Select_handler_base; + + struct Select : Interface + { + /** + * Schedule select handler that is deblocked by ready fd sets + */ + virtual void schedule_select(Select_handler_base &) = 0; + + virtual void deschedule_select() = 0; + }; +} + +#endif /* _LIBC__INTERNAL__SELECT_H_ */ diff --git a/repos/libports/src/lib/libc/internal/signal.h b/repos/libports/src/lib/libc/internal/signal.h new file mode 100644 index 000000000..691e86b18 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/signal.h @@ -0,0 +1,117 @@ +/* + * \brief POSIX signal handling + * \author Norman Feske + * \date 2019-10-11 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__SIGNAL_H_ +#define _LIBC__INTERNAL__SIGNAL_H_ + +/* Genode includes */ +#include <util/noncopyable.h> +#include <base/registry.h> + +/* libc includes */ +#include <signal.h> + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { struct Signal; } + + +struct Libc::Signal : Noncopyable +{ + public: + + struct sigaction signal_action[NSIG + 1] { }; + + private: + + struct Pending + { + virtual ~Pending() { } + + unsigned const n; + + Pending(unsigned n) : n(n) { } + }; + + Constructible<Registered<Pending>> _charged_signals[NSIG + 1]; + + Registry<Registered<Pending>> _pending_signals { }; + + void _execute_signal_handler(unsigned n); + + unsigned _count = 0; + + bool _exit = false; + + unsigned _exit_code = 0; + + unsigned _nesting_level = 0; + + pid_t const _local_pid; + + public: + + Signal(pid_t local_pid) : _local_pid(local_pid) { } + + void charge(unsigned n) + { + if (n > NSIG) + return; + + _charged_signals[n].construct(_pending_signals, n); + _count++; + } + + void execute_signal_handlers() + { + /* + * Prevent nested execution of signal handlers, which may happen + * if I/O operations are executed by a signal handler. + */ + if (_nesting_level > 0) { + warning("attempt to nested execution of signal handlers"); + return; + } + + _nesting_level++; + + _pending_signals.for_each([&] (Pending &pending) { + _execute_signal_handler(pending.n); + _charged_signals[pending.n].destruct(); + }); + + _nesting_level--; + + /* + * Exit application due to a signal such as SIGINT. + */ + if (_exit) + exit(_exit_code); + } + + /** + * Return number of triggered signals + * + * The value is intended to be used for tracking whether a signal + * occurred during a blocking operation ('select'). + */ + unsigned count() const { return _count; } + + /** + * Return true if specified PID belongs to the process itself + */ + bool local_pid(pid_t pid) const { return pid == _local_pid; } +}; + +#endif /* _LIBC__INTERNAL__SIGNAL_H_ */ diff --git a/repos/libports/src/lib/libc/socket_fs_plugin.h b/repos/libports/src/lib/libc/internal/socket_fs_plugin.h similarity index 90% rename from repos/libports/src/lib/libc/socket_fs_plugin.h rename to repos/libports/src/lib/libc/internal/socket_fs_plugin.h index 4a9228a4e..95a3d8e13 100644 --- a/repos/libports/src/lib/libc/socket_fs_plugin.h +++ b/repos/libports/src/lib/libc/internal/socket_fs_plugin.h @@ -12,8 +12,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _LIBC__SOCKET_FS_PLUGIN_H_ -#define _LIBC__SOCKET_FS_PLUGIN_H_ +#ifndef _LIBC__INTERNAL__SOCKET_FS_PLUGIN_H_ +#define _LIBC__INTERNAL__SOCKET_FS_PLUGIN_H_ /* Libc includes */ #include <sys/types.h> @@ -35,4 +35,4 @@ extern "C" int socket_fs_setsockopt(int, int, int, void const *, socklen_t); extern "C" int socket_fs_shutdown(int, int); extern "C" int socket_fs_socket(int, int, int); -#endif /* _LIBC__SOCKET_FS_PLUGIN_H_ */ +#endif /* _LIBC__INTERNAL__SOCKET_FS_PLUGIN_H_ */ diff --git a/repos/libports/src/lib/libc/internal/suspend.h b/repos/libports/src/lib/libc/internal/suspend.h new file mode 100644 index 000000000..808e0149c --- /dev/null +++ b/repos/libports/src/lib/libc/internal/suspend.h @@ -0,0 +1,49 @@ +/* + * \brief Interface for suspending the execution until I/O activity + * \author Norman Feske + * \date 2019-09-18 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__SUSPEND_H_ +#define _LIBC__INTERNAL__SUSPEND_H_ + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + /** + * Interface for requesting the condition for suspending + */ + struct Suspend_functor : Interface + { + virtual bool suspend() = 0; + }; + + struct Suspend : Interface + { + /** + * Suspend the execution of the calling user context + * + * \param timeout_ms maximum time to stay suspended in milliseconds, + * 0 for infinite suspend + * + * \return remaining duration until timeout, + * 0 if the timeout expired + * + * The context could be running on the component entrypoint as main context + * or as separate pthread. This function returns after the libc kernel + * resumed the user context execution. + */ + virtual uint64_t suspend(Suspend_functor &, uint64_t timeout_ms = 0) = 0; + }; +} + +#endif /* _LIBC__INTERNAL__SUSPEND_H_ */ diff --git a/repos/libports/src/lib/libc/thread_create.h b/repos/libports/src/lib/libc/internal/thread_create.h similarity index 64% rename from repos/libports/src/lib/libc/thread_create.h rename to repos/libports/src/lib/libc/internal/thread_create.h index c760cbf31..3f023c4a4 100644 --- a/repos/libports/src/lib/libc/thread_create.h +++ b/repos/libports/src/lib/libc/internal/thread_create.h @@ -13,19 +13,26 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _LIBC__THREAD_CREATE_H_ -#define _LIBC__THREAD_CREATE_H_ +#ifndef _LIBC__INTERNAL__THREAD_CREATE_H_ +#define _LIBC__INTERNAL__THREAD_CREATE_H_ -#include <pthread.h> +/* Genode includes */ #include <base/thread.h> +/* libc includes */ +#include <pthread.h> + +/* libc-internal includes */ +#include <internal/types.h> + namespace Libc { + int pthread_create(pthread_t *thread, void *(*start_routine) (void *), void *arg, size_t stack_size, char const * name, - Genode::Cpu_session * cpu, Genode::Affinity::Location location); + Cpu_session * cpu, Affinity::Location location); - int pthread_create(pthread_t *, Genode::Thread &); + int pthread_create(pthread_t *, Thread &); } -#endif /* _LIBC__THREAD_CREATE_H_ */ +#endif /* _LIBC__INTERNAL__THREAD_CREATE_H_ */ diff --git a/repos/libports/src/lib/libc/timed_semaphore.h b/repos/libports/src/lib/libc/internal/timed_semaphore.h similarity index 97% rename from repos/libports/src/lib/libc/timed_semaphore.h rename to repos/libports/src/lib/libc/internal/timed_semaphore.h index 537ce265d..d7853fe9c 100644 --- a/repos/libports/src/lib/libc/timed_semaphore.h +++ b/repos/libports/src/lib/libc/internal/timed_semaphore.h @@ -16,8 +16,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _TIMED_SEMAPHORE_H_ -#define _TIMED_SEMAPHORE_H_ +#ifndef _LIBC__INTERNAL__TIMED_SEMAPHORE_H_ +#define _LIBC__INTERNAL__TIMED_SEMAPHORE_H_ #include <base/thread.h> #include <base/semaphore.h> @@ -259,4 +259,4 @@ class Libc::Timed_semaphore : public Semaphore void up() { Semaphore::up(); } }; -#endif /* _TIMED_SEMAPHORE_H_ */ +#endif /* _LIBC__INTERNAL__TIMED_SEMAPHORE_H_ */ diff --git a/repos/libports/src/lib/libc/internal/timer.h b/repos/libports/src/lib/libc/internal/timer.h new file mode 100644 index 000000000..23f7ea503 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/timer.h @@ -0,0 +1,117 @@ +/* + * \brief Libc-internal timer handling + * \author Norman Feske + * \date 2019-09-16 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__TIMER_H_ +#define _LIBC__INTERNAL__TIMER_H_ + +/* Genode includes */ +#include <timer_session/connection.h> + +namespace Libc { + class Timer; + class Timer_accessor; + class Timeout; + class Timeout_handler; +} + + +struct Libc::Timer +{ + ::Timer::Connection _timer; + + Timer(Genode::Env &env) : _timer(env) { } + + Duration curr_time() + { + return _timer.curr_time(); + } + + static Microseconds microseconds(uint64_t timeout_ms) + { + return Microseconds(1000*timeout_ms); + } + + static uint64_t max_timeout() + { + return ~0UL/1000; + } +}; + + +/** + * Interface for obtaining the libc-global timer instance + * + * The 'Timer' is instantiated on demand whenever the 'Timer_accessor::timer' + * method is first called. This way, libc-using components do not depend of a + * timer connection unless they actually use time-related functionality. + */ +struct Libc::Timer_accessor +{ + virtual Timer &timer() = 0; +}; + + +struct Libc::Timeout_handler +{ + virtual void handle_timeout() = 0; +}; + + +/* + * TODO curr_time wrapping + */ +struct Libc::Timeout +{ + Timer_accessor &_timer_accessor; + Timeout_handler &_handler; + ::Timer::One_shot_timeout<Timeout> _timeout; + + bool _expired = true; + uint64_t _absolute_timeout_ms = 0; + + void _handle(Duration now) + { + _expired = true; + _absolute_timeout_ms = 0; + _handler.handle_timeout(); + } + + Timeout(Timer_accessor &timer_accessor, Timeout_handler &handler) + : + _timer_accessor(timer_accessor), + _handler(handler), + _timeout(_timer_accessor.timer()._timer, *this, &Timeout::_handle) + { } + + void start(uint64_t timeout_ms) + { + Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms(); + + _expired = false; + _absolute_timeout_ms = now.value + timeout_ms; + + _timeout.schedule(_timer_accessor.timer().microseconds(timeout_ms)); + } + + uint64_t duration_left() const + { + Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms(); + + if (_expired || _absolute_timeout_ms < now.value) + return 0; + + return _absolute_timeout_ms - now.value; + } +}; + +#endif /* _LIBC__INTERNAL__TIMER_H_ */ diff --git a/repos/libports/src/lib/libc/internal/types.h b/repos/libports/src/lib/libc/internal/types.h new file mode 100644 index 000000000..1945c066d --- /dev/null +++ b/repos/libports/src/lib/libc/internal/types.h @@ -0,0 +1,26 @@ +/* + * \brief Common libc-internal types + * \author Norman Feske + * \date 2019-09-16 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__TYPES_H_ +#define _LIBC__INTERNAL__TYPES_H_ + +#include <base/log.h> + +namespace Libc { + + using namespace Genode; + + typedef Genode::uint64_t uint64_t; +} + +#endif /* _LIBC__INTERNAL__TYPES_H_ */ diff --git a/repos/libports/src/lib/libc/internal/vfs_plugin.h b/repos/libports/src/lib/libc/internal/vfs_plugin.h new file mode 100644 index 000000000..81e8960a3 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/vfs_plugin.h @@ -0,0 +1,196 @@ +/* + * \brief Libc plugin for using a process-local virtual file system + * \author Norman Feske + * \author Emery Hemingway + * \author Christian Helmuth + * \date 2014-04-09 + */ + +/* + * Copyright (C) 2014-2019 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 _LIBC__INTERNAL__VFS_PLUGIN_H_ +#define _LIBC__INTERNAL__VFS_PLUGIN_H_ + +/* Genode includes */ +#include <libc/component.h> +#include <os/vfs.h> +#include <vfs/file_system.h> + +/* libc includes */ +#include <fcntl.h> +#include <unistd.h> + +/* libc plugin interface */ +#include <libc-plugin/plugin.h> +#include <libc-plugin/fd_alloc.h> + +/* libc-internal includes */ +#include <internal/errno.h> + + +namespace Libc { class Vfs_plugin; } + + +class Libc::Vfs_plugin : public Plugin +{ + public: + + enum class Update_mtime { NO, YES }; + + /** + * Return path to pseudo files used for ioctl operations of a given FD + * + * The 'fd' argument must feature a valid 'fd.fd_path' member. + * This assumption can be violated by the stdout, stdin, or stderr FDs + * if the <libc> configuration lacks the corresponding attribute. + */ + static Absolute_path ioctl_dir(File_descriptor const &fd) + { + if (!fd.fd_path) { + error("Libc::Vfs_plugin::ioctl_dir: fd lacks path information"); + class Fd_lacks_path : Exception { }; + throw Fd_lacks_path(); + } + + Absolute_path path(fd.fd_path); + + /* + * The pseudo files used for ioctl operations reside in a (hidden) + * directory named after the device path and prefixed with '.'. + */ + String<64> const ioctl_dir_name(".", path.last_element()); + + path.strip_last_element(); + path.append_element(ioctl_dir_name.string()); + + return path; + } + + private: + + Genode::Allocator &_alloc; + Vfs::File_system &_root_fs; + Constructible<Genode::Directory> _root_dir { }; + Vfs::Io_response_handler &_response_handler; + Update_mtime const _update_mtime; + bool const _pipe_configured; + + /** + * Sync a handle and propagate errors + */ + int _vfs_sync(Vfs::Vfs_handle&); + + /** + * Update modification time + */ + void _vfs_write_mtime(Vfs::Vfs_handle&); + + int _legacy_ioctl(File_descriptor *, int , char *); + + /** + * Call functor 'fn' with ioctl info for the given file descriptor 'fd' + * + * The functor is called with an 'Xml_node' of the ioctl information + * as argument. + * + * If no ioctl info is available, 'fn' is not called. + */ + template <typename FN> + void _with_info(File_descriptor &fd, FN const &fn); + + static bool _init_pipe_configured(Xml_node config) + { + bool result = false; + config.with_sub_node("libc", [&] (Xml_node libc_node) { + result = libc_node.has_attribute("pipe"); }); + return result; + } + + public: + + Vfs_plugin(Libc::Env &env, + Vfs::Env &vfs_env, + Genode::Allocator &alloc, + Vfs::Io_response_handler &handler, + Update_mtime update_mtime, + Xml_node config) + : + _alloc(alloc), + _root_fs(env.vfs()), + _response_handler(handler), + _update_mtime(update_mtime), + _pipe_configured(_init_pipe_configured(config)) + { + if (config.has_sub_node("libc")) + _root_dir.construct(vfs_env); + } + + ~Vfs_plugin() final { } + + template <typename FN> + void with_root_dir(FN const &fn) + { + if (_root_dir.constructed()) + fn(*_root_dir); + } + + bool root_dir_has_dirents() const { return _root_fs.num_dirent("/") > 0; } + + bool supports_access(const char *, int) override { return true; } + bool supports_mkdir(const char *, mode_t) override { return true; } + bool supports_open(const char *, int) override { return true; } + bool supports_pipe() override { return _pipe_configured; } + bool supports_poll() override { return true; } + bool supports_readlink(const char *, char *, ::size_t) override { return true; } + bool supports_rename(const char *, const char *) override { return true; } + bool supports_rmdir(const char *) override { return true; } + bool supports_stat(const char *) override { return true; } + bool supports_symlink(const char *, const char *) override { return true; } + bool supports_unlink(const char *) override { return true; } + bool supports_mmap() override { return true; } + + bool supports_select(int nfds, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) override; + + File_descriptor *open(const char *, int, int libc_fd); + + File_descriptor *open(const char *path, int flags) override + { + return open(path, flags, ANY_FD); + } + + int access(char const *, int) override; + int close(File_descriptor *) override; + File_descriptor *dup(File_descriptor *) override; + int dup2(File_descriptor *, File_descriptor *) override; + int fcntl(File_descriptor *, int, long) override; + int fstat(File_descriptor *, struct stat *) override; + int fstatfs(File_descriptor *, struct statfs *) override; + int fsync(File_descriptor *fd) override; + int ftruncate(File_descriptor *, ::off_t) override; + ssize_t getdirentries(File_descriptor *, char *, ::size_t , ::off_t *) override; + int ioctl(File_descriptor *, int , char *) override; + ::off_t lseek(File_descriptor *fd, ::off_t offset, int whence) override; + int mkdir(const char *, mode_t) override; + int pipe(File_descriptor *pipefdo[2]) override; + bool poll(File_descriptor &fdo, struct pollfd &pfd) override; + ssize_t read(File_descriptor *, void *, ::size_t) override; + ssize_t readlink(const char *, char *, ::size_t) override; + int rename(const char *, const char *) override; + int rmdir(const char *) override; + int stat(const char *, struct stat *) override; + int symlink(const char *, const char *) override; + int unlink(const char *) override; + ssize_t write(File_descriptor *, const void *, ::size_t ) override; + void *mmap(void *, ::size_t, int, int, File_descriptor *, ::off_t) override; + int munmap(void *, ::size_t) override; + int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) override; +}; + +#endif /* _LIBC__INTERNAL__VFS_PLUGIN_H_ */ diff --git a/repos/libports/src/lib/libc/internal/watch.h b/repos/libports/src/lib/libc/internal/watch.h new file mode 100644 index 000000000..77b494881 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/watch.h @@ -0,0 +1,31 @@ +/* + * \brief Interface for watching files + * \author Norman Feske + * \date 2019-09-20 + */ + +/* + * Copyright (C) 2019 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 _LIBC__INTERNAL__WATCH_H_ +#define _LIBC__INTERNAL__WATCH_H_ + +/* libc-internal includes */ +#include <internal/types.h> + +namespace Libc { + + struct Watch : Interface + { + /** + * Alloc new watch handler for given path + */ + virtual Vfs::Vfs_watch_handle *alloc_watch_handle(char const *path) = 0; + }; +} + +#endif /* _LIBC__INTERNAL__WATCH_H_ */ diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc new file mode 100644 index 000000000..892614bd2 --- /dev/null +++ b/repos/libports/src/lib/libc/kernel.cc @@ -0,0 +1,403 @@ +/* + * \brief Libc kernel for main and pthreads user contexts + * \author Christian Helmuth + * \author Emery Hemingway + * \author Norman Feske + * \date 2016-01-22 + */ + +/* + * Copyright (C) 2016-2019 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. + */ + +/* libc-internal includes */ +#include <internal/kernel.h> + +Libc::Kernel * Libc::Kernel::_kernel_ptr; + + +/** + * Main context execution was suspended (on fork) + * + * This function is executed in the context of the initial thread. + */ +static void suspended_callback() +{ + Libc::Kernel::kernel().entrypoint_suspended(); +} + + +/** + * Resume main context execution (after fork) + * + * This function is executed in the context of the initial thread. + */ +static void resumed_callback() +{ + Libc::Kernel::kernel().entrypoint_resumed(); +} + + +size_t Libc::Kernel::_user_stack_size() +{ + size_t size = Component::stack_size(); + if (!_cloned) + return size; + + _libc_env.libc_config().with_sub_node("stack", [&] (Xml_node stack) { + size = stack.attribute_value("size", 0UL); }); + + return size; +} + + +void Libc::Kernel::schedule_suspend(void(*original_suspended_callback) ()) +{ + if (_state != USER) { + error(__PRETTY_FUNCTION__, " called from non-user context"); + return; + } + + /* + * We hook into suspend-resume callback chain to destruct and + * reconstruct parts of the kernel from the context of the initial + * thread, i.e., without holding any object locks. + */ + _original_suspended_callback = original_suspended_callback; + _env.ep().schedule_suspend(suspended_callback, resumed_callback); + + if (!_setjmp(_user_context)) { + _valid_user_context = true; + _suspend_scheduled = true; + _switch_to_kernel(); + } else { + _valid_user_context = false; + } +} + + +void Libc::Kernel::reset_malloc_heap() +{ + _malloc_ram.construct(_heap, _env.ram()); + + _cloned_heap_ranges.for_each([&] (Registered<Cloned_malloc_heap_range> &r) { + destroy(_heap, &r); }); + + Heap &raw_malloc_heap = *_malloc_heap; + construct_at<Heap>(&raw_malloc_heap, *_malloc_ram, _env.rm()); + + reinit_malloc(raw_malloc_heap); +} + + +void Libc::Kernel::_init_file_descriptors() +{ + auto init_fd = [&] (Xml_node const &node, char const *attr, + int libc_fd, unsigned flags) + { + if (!node.has_attribute(attr)) + return; + + typedef String<Vfs::MAX_PATH_LEN> Path; + Path const path = node.attribute_value(attr, Path()); + + struct stat out_stat { }; + if (stat(path.string(), &out_stat) != 0) + return; + + File_descriptor *fd = _vfs.open(path.string(), flags, libc_fd); + if (!fd) + return; + + if (fd->libc_fd != libc_fd) { + error("could not allocate fd ",libc_fd," for ",path,", " + "got fd ",fd->libc_fd); + _vfs.close(fd); + return; + } + + /* + * We need to manually register the path. Normally this is done + * by '_open'. But we call the local 'open' function directly + * because we want to explicitly specify the libc fd ID. + */ + if (fd->fd_path) + warning("may leak former FD path memory"); + + { + char *dst = (char *)_heap.alloc(path.length()); + Genode::strncpy(dst, path.string(), path.length()); + fd->fd_path = dst; + } + + ::off_t const seek = node.attribute_value("seek", 0ULL); + if (seek) + _vfs.lseek(fd, seek, SEEK_SET); + }; + + if (_vfs.root_dir_has_dirents()) { + + Xml_node const node = _libc_env.libc_config(); + + typedef String<Vfs::MAX_PATH_LEN> Path; + + if (node.has_attribute("cwd")) + chdir(node.attribute_value("cwd", Path()).string()); + + init_fd(node, "stdin", 0, O_RDONLY); + init_fd(node, "stdout", 1, O_WRONLY); + init_fd(node, "stderr", 2, O_WRONLY); + + node.for_each_sub_node("fd", [&] (Xml_node fd) { + + unsigned const id = fd.attribute_value("id", 0U); + + bool const rd = fd.attribute_value("readable", false); + bool const wr = fd.attribute_value("writeable", false); + + unsigned const flags = rd ? (wr ? O_RDWR : O_RDONLY) + : (wr ? O_WRONLY : 0); + + if (!fd.has_attribute("path")) + warning("Invalid <fd> node, 'path' attribute is missing"); + + init_fd(fd, "path", id, flags); + }); + + /* prevent use of IDs of stdin, stdout, and stderr for other files */ + for (unsigned fd = 0; fd <= 2; fd++) + file_descriptor_allocator()->preserve(fd); + } + + /** + * Call 'fn' with root directory and path to ioctl pseudo file as arguments + * + * If no matching ioctl pseudo file exists, 'fn' is not called. + */ + auto with_ioctl_path = [&] (File_descriptor const *fd, char const *file, auto fn) + { + if (!fd || !fd->fd_path) + return; + + Absolute_path const ioctl_dir = Vfs_plugin::ioctl_dir(*fd); + Absolute_path path = ioctl_dir; + path.append_element(file); + + _vfs.with_root_dir([&] (Directory &root_dir) { + if (root_dir.file_exists(path.string())) + fn(root_dir, path.string()); }); + }; + + /* + * Watch stdout's 'info' pseudo file to detect terminal-resize events + */ + File_descriptor const * const stdout_fd = + file_descriptor_allocator()->find_by_libc_fd(STDOUT_FILENO); + + with_ioctl_path(stdout_fd, "info", [&] (Directory &root_dir, char const *path) { + _terminal_resize_handler.construct(root_dir, path, *this, + &Kernel::_handle_terminal_resize); }); + + /* + * Watch stdin's 'interrupts' pseudo file to detect control-c events + */ + File_descriptor const * const stdin_fd = + file_descriptor_allocator()->find_by_libc_fd(STDIN_FILENO); + + with_ioctl_path(stdin_fd, "interrupts", [&] (Directory &root_dir, char const *path) { + _user_interrupt_handler.construct(root_dir, path, + *this, &Kernel::_handle_user_interrupt); }); +} + + +void Libc::Kernel::_handle_terminal_resize() +{ + _signal.charge(SIGWINCH); + _resume_main(); +} + + +void Libc::Kernel::_handle_user_interrupt() +{ + _signal.charge(SIGINT); + _resume_main(); +} + + +void Libc::Kernel::_clone_state_from_parent() +{ + struct Range { void *at; size_t size; }; + + auto range_attr = [&] (Xml_node node) + { + return Range { + .at = (void *)node.attribute_value("at", 0UL), + .size = node.attribute_value("size", 0UL) + }; + }; + + /* + * Allocate local memory for the backing store of the application heap, + * mirrored from the parent. + * + * This step must precede the creation of the 'Clone_connection' because + * the shared-memory buffer of the clone session may otherwise potentially + * interfere with such a heap region. + */ + _libc_env.libc_config().for_each_sub_node("heap", [&] (Xml_node node) { + Range const range = range_attr(node); + new (_heap) + Registered<Cloned_malloc_heap_range>(_cloned_heap_ranges, + _env.ram(), _env.rm(), + range.at, range.size); }); + + _clone_connection.construct(_env); + + /* fetch heap content */ + _cloned_heap_ranges.for_each([&] (Cloned_malloc_heap_range &heap_range) { + heap_range.import_content(*_clone_connection); }); + + /* fetch user contex of the parent's application */ + _clone_connection->memory_content(&_user_context, sizeof(_user_context)); + _valid_user_context = true; + + _libc_env.libc_config().for_each_sub_node([&] (Xml_node node) { + + auto copy_from_parent = [&] (Range range) + { + _clone_connection->memory_content(range.at, range.size); + }; + + /* clone application stack */ + if (node.type() == "stack") + copy_from_parent(range_attr(node)); + + /* clone RW segment of a shared library or the binary */ + if (node.type() == "rw") { + typedef String<64> Name; + Name const name = node.attribute_value("name", Name()); + + /* + * The blacklisted segments are initialized via the + * regular startup of the child. + */ + bool const blacklisted = (name == "ld.lib.so") + || (name == "libc.lib.so") + || (name == "libm.lib.so") + || (name == "posix.lib.so") + || (strcmp(name.string(), "vfs", 3) == 0); + if (!blacklisted) + copy_from_parent(range_attr(node)); + } + }); + + /* import application-heap state from parent */ + _clone_connection->object_content(_malloc_heap); + init_malloc_cloned(*_clone_connection); +} + + +extern void (*libc_select_notify)(); + + +void Libc::Kernel::handle_io_progress() +{ + /* + * TODO: make VFS I/O completion checks during + * kernel time to avoid flapping between stacks + */ + + if (_io_ready) { + _io_ready = false; + + /* some contexts may have been deblocked from select() */ + if (libc_select_notify) + libc_select_notify(); + + /* + * resume all as any VFS context may have + * been deblocked from blocking I/O + */ + Kernel::resume_all(); + } +} + + +void Libc::execute_in_application_context(Application_code &app_code) +{ + /* + * The libc execution model builds on the main entrypoint, which handles + * all relevant signals (e.g., timing and VFS). Additional component + * entrypoints or pthreads should never call with_libc() but we catch this + * here and just execute the application code directly. + */ + if (!Kernel::kernel().main_context()) { + app_code.execute(); + return; + } + + static bool nested = false; + + if (nested) { + + if (Kernel::kernel().main_suspended()) { + Kernel::kernel().nested_execution(app_code); + } else { + app_code.execute(); + } + return; + } + + nested = true; + Kernel::kernel().run(app_code); + nested = false; +} + + +Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap) +: + _env(env), _heap(heap) +{ + init_pthread_support(env, *this, *this); + + _env.ep().register_io_progress_handler(*this); + + if (_cloned) { + _clone_state_from_parent(); + + } else { + _malloc_heap.construct(*_malloc_ram, _env.rm()); + init_malloc(*_malloc_heap); + } + + init_fork(_env, _libc_env, _heap, *_malloc_heap, _pid, *this, *this, _signal, *this); + init_execve(_env, _heap, _user_stack, *this); + init_plugin(*this); + init_sleep(*this); + init_vfs_plugin(*this); + init_time(*this, _rtc_path, *this); + init_select(*this, *this, *this, _signal); + init_socket_fs(*this); + init_passwd(_passwd_config()); + init_signal(_signal); + + _init_file_descriptors(); + + _kernel_ptr = this; + + /* + * Acknowledge the completion of 'fork' to the parent + * + * This must be done after '_init_file_descriptors' to ensure that pipe FDs + * of the parent are opened at the child before the parent continues. + * Otherwise, the parent would potentially proceed with closing the pipe + * FDs before the child has a chance to open them. In this situation, the + * pipe reference counter may reach an intermediate value of zero, + * triggering the destruction of the pipe. + */ + if (_cloned) + _clone_connection.destruct(); +} diff --git a/repos/libports/src/lib/libc/legacy.cc b/repos/libports/src/lib/libc/legacy.cc new file mode 100644 index 000000000..19f518cb2 --- /dev/null +++ b/repos/libports/src/lib/libc/legacy.cc @@ -0,0 +1,31 @@ +/* + * \brief Globally available accessors to Libc kernel functionality + * \author Norman Feske + * \date 2019-09-18 + * + * XXX eliminate the need for these functions, or + * turn them into regular members of 'Libc::Kernel' + */ + +/* + * Copyright (C) 2019 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. + */ + +/* libc-internal includes */ +#include <internal/legacy.h> +#include <internal/kernel.h> + + +void Libc::dispatch_pending_io_signals() +{ + Kernel::kernel().dispatch_pending_io_signals(); +} + + +void Libc::schedule_suspend(void (*suspended) ()) +{ + Kernel::kernel().schedule_suspend(suspended); +} diff --git a/repos/libports/src/lib/libc/libc_mem_alloc.cc b/repos/libports/src/lib/libc/libc_mem_alloc.cc index 7cb9e7379..36d77b569 100644 --- a/repos/libports/src/lib/libc/libc_mem_alloc.cc +++ b/repos/libports/src/lib/libc/libc_mem_alloc.cc @@ -17,9 +17,9 @@ #include <base/env.h> #include <base/allocator_avl.h> -/* local includes */ -#include "libc_mem_alloc.h" -#include "libc_init.h" +/* libc-internal includes */ +#include <internal/mem_alloc.h> +#include <internal/init.h> using namespace Genode; @@ -72,7 +72,7 @@ int Libc::Mem_alloc_impl::Dataspace_pool::expand(size_t size, Range_allocator *a /* now that we have new backing store, allocate Dataspace structure */ if (alloc->alloc_aligned(sizeof(Dataspace), &ds_addr, 2).error()) { - Genode::warning("libc: could not allocate meta data - this should never happen"); + warning("libc: could not allocate meta data - this should never happen"); return -1; } @@ -114,7 +114,7 @@ void *Libc::Mem_alloc_impl::alloc(size_t size, size_t align_log2) } if (_ds_pool.expand(align_addr(request_size, 12), &_alloc) < 0) { - Genode::warning("libc: could not expand dataspace pool"); + warning("libc: could not expand dataspace pool"); return 0; } @@ -133,7 +133,7 @@ void Libc::Mem_alloc_impl::free(void *addr) } -Genode::size_t Libc::Mem_alloc_impl::size_at(void const *addr) const +size_t Libc::Mem_alloc_impl::size_at(void const *addr) const { /* serialize access of heap functions */ Lock::Guard lock_guard(_lock); @@ -147,7 +147,7 @@ static Libc::Mem_alloc *_libc_mem_alloc_rw = nullptr; static Libc::Mem_alloc *_libc_mem_alloc_rwx = nullptr; -static void _init_mem_alloc(Genode::Region_map &rm, Genode::Ram_allocator &ram) +static void _init_mem_alloc(Region_map &rm, Ram_allocator &ram) { enum { MEMORY_EXECUTABLE = true }; @@ -159,12 +159,9 @@ static void _init_mem_alloc(Genode::Region_map &rm, Genode::Ram_allocator &ram) } -namespace Libc { - - void init_mem_alloc(Genode::Env &env) - { - _init_mem_alloc(env.rm(), env.ram()); - } +void Libc::init_mem_alloc(Genode::Env &env) +{ + _init_mem_alloc(env.rm(), env.ram()); } diff --git a/repos/libports/src/lib/libc/malloc.cc b/repos/libports/src/lib/libc/malloc.cc index 43116c7bd..980b74064 100644 --- a/repos/libports/src/lib/libc/malloc.cc +++ b/repos/libports/src/lib/libc/malloc.cc @@ -26,17 +26,17 @@ extern "C" { #include <stdlib.h> } -/* libc-internal includes */ -#include "libc_init.h" +/* Genode-internal includes */ #include <base/internal/unmanaged_singleton.h> -#include <clone_session.h> + +/* libc-internal includes */ +#include <internal/init.h> +#include <internal/clone_session.h> namespace Libc { class Slab_alloc; class Malloc; - - using namespace Genode; } @@ -224,7 +224,10 @@ class Libc::Malloc }; -static Libc::Malloc *mallocator; +using namespace Libc; + + +static Malloc *mallocator; extern "C" void *malloc(size_t size) @@ -261,16 +264,16 @@ extern "C" void *realloc(void *ptr, size_t size) } -static Genode::Constructible<Libc::Malloc> &constructible_malloc() +static Genode::Constructible<Malloc> &constructible_malloc() { - return *unmanaged_singleton<Genode::Constructible<Libc::Malloc> >(); + return *unmanaged_singleton<Genode::Constructible<Malloc> >(); } void Libc::init_malloc(Genode::Allocator &heap) { - Genode::Constructible<Libc::Malloc> &_malloc = constructible_malloc(); + Constructible<Malloc> &_malloc = constructible_malloc(); _malloc.construct(heap); @@ -288,7 +291,7 @@ void Libc::init_malloc_cloned(Clone_connection &clone_connection) void Libc::reinit_malloc(Genode::Allocator &heap) { - Libc::Malloc &malloc = *constructible_malloc(); + Malloc &malloc = *constructible_malloc(); - Genode::construct_at<Libc::Malloc>(&malloc, heap); + construct_at<Malloc>(&malloc, heap); } diff --git a/repos/libports/src/lib/libc/plugin.cc b/repos/libports/src/lib/libc/plugin.cc index dfdd77951..b4932944b 100644 --- a/repos/libports/src/lib/libc/plugin.cc +++ b/repos/libports/src/lib/libc/plugin.cc @@ -20,15 +20,28 @@ #include <libc-plugin/plugin.h> /* local includes */ -#include "task.h" +#include <internal/init.h> +#include <internal/resume.h> -using namespace Genode; using namespace Libc; +static Resume *_resume_ptr; + + +void Libc::init_plugin(Resume &resume) +{ + _resume_ptr = &resume; +} + + void Plugin::resume_all() { - Libc::resume_all(); + struct Missing_call_of_init_plugin : Exception { }; + if (!_resume_ptr) + throw Missing_call_of_init_plugin(); + + _resume_ptr->resume_all(); } @@ -142,7 +155,7 @@ bool Plugin::supports_mmap() #define DUMMY(ret_type, ret_val, name, args) \ ret_type Plugin::name args \ { \ - Genode::error(__func__, ": " #name " not implemented"); \ + error(__func__, ": " #name " not implemented"); \ return ret_val; \ } diff --git a/repos/libports/src/lib/libc/poll.cc b/repos/libports/src/lib/libc/poll.cc index 58e5e6e4d..177a369f1 100644 --- a/repos/libports/src/lib/libc/poll.cc +++ b/repos/libports/src/lib/libc/poll.cc @@ -1,6 +1,7 @@ /* * \brief poll() implementation * \author Josef Soentgen + * \author Christian Helmuth * \author Emery Hemingway * \date 2012-07-12 */ @@ -18,74 +19,95 @@ #include <sys/poll.h> /* internal includes */ -#include "libc_errno.h" -#include "libc_file.h" -#include "task.h" +#include <internal/errno.h> +#include <internal/file.h> +#include <internal/init.h> +#include <internal/suspend.h> + +using namespace Libc; -extern "C" __attribute__((weak)) -int poll(struct pollfd fds[], nfds_t nfds, int timeout_ms) +/** + * The poll function was taken from OpenSSH portable (bsd-poll.c) and adepted + * to better fit within Genode's libc. + * + * Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au). + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +extern "C" int +__attribute__((weak)) +poll(struct pollfd fds[], nfds_t nfds, int timeout) { - using namespace Libc; + nfds_t i; + int ret, fd, maxfd = 0; + fd_set readfds, writefds, exceptfds; + struct timeval tv, *tvp = NULL; - if (!fds || nfds == 0) return Errno(EINVAL); - - struct Check : Libc::Suspend_functor - { - pollfd *_fds; - nfds_t const _nfds; - - int nready { 0 }; - - Check(struct pollfd fds[], nfds_t nfds) - : _fds(fds), _nfds(nfds) { } - - bool suspend() override - { - bool polling = false; - - for (unsigned i = 0; i < _nfds; ++i) - { - pollfd &pfd = _fds[i]; - File_descriptor *libc_fd = libc_fd_to_fd(pfd.fd, "poll"); - if (!libc_fd) { - pfd.revents |= POLLNVAL; - ++nready; - continue; - } - - if (!libc_fd->plugin || !libc_fd->plugin->supports_poll()) { - Genode::warning("poll not supported for file descriptor ", pfd.fd); - continue; - } - - nready += libc_fd->plugin->poll(*libc_fd, pfd); - polling = true; - } - - return (polling && nready == 0); + for (i = 0; i < nfds; i++) { + fd = fds[i].fd; + if (fd >= (int)FD_SETSIZE) { + return Libc::Errno(EINVAL); } - - } check (fds, nfds); - - check.suspend(); - - if (timeout_ms == 0) { - return check.nready; + maxfd = MAX(maxfd, fd); } - if (timeout_ms == -1) { - while (check.nready == 0) { - Libc::suspend(check, 0); + /* populate event bit vectors for the events we're interested in */ + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + + for (i = 0; i < nfds; i++) { + fd = fds[i].fd; + if (fd == -1) + continue; + if (fds[i].events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { + FD_SET(fd, &readfds); + FD_SET(fd, &exceptfds); } - } else { - Genode::uint64_t remaining_ms = timeout_ms; - while (check.nready == 0 && remaining_ms > 0) { - remaining_ms = Libc::suspend(check, remaining_ms); + if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { + FD_SET(fd, &writefds); + FD_SET(fd, &exceptfds); } } - return check.nready; + /* poll timeout is msec, select is timeval (sec + usec) */ + if (timeout >= 0) { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tvp = &tv; + } + ret = select(maxfd + 1, &readfds, &writefds, &exceptfds, tvp); + + /* scan through select results and set poll() flags */ + for (i = 0; i < nfds; i++) { + fd = fds[i].fd; + fds[i].revents = 0; + if (fd == -1) + continue; + if ((fds[i].events & POLLIN) && FD_ISSET(fd, &readfds)) { + fds[i].revents |= POLLIN; + } + if ((fds[i].events & POLLOUT) && FD_ISSET(fd, &writefds)) { + fds[i].revents |= POLLOUT; + } + if (FD_ISSET(fd, &exceptfds)) { + fds[i].revents |= POLLERR; + } + } + + return ret; } diff --git a/repos/libports/src/lib/libc/pread_pwrite.cc b/repos/libports/src/lib/libc/pread_pwrite.cc index 4dac3d6f7..367e814c2 100644 --- a/repos/libports/src/lib/libc/pread_pwrite.cc +++ b/repos/libports/src/lib/libc/pread_pwrite.cc @@ -20,6 +20,9 @@ #include <sys/uio.h> #include <unistd.h> +/* libc-internal includes */ +#include <internal/types.h> + struct Read { @@ -39,16 +42,19 @@ struct Write }; +using namespace Libc; + + template <typename Rw_func, typename Buf_type> static ssize_t pread_pwrite_impl(Rw_func rw_func, int fd, Buf_type buf, ::size_t count, ::off_t offset) { - Libc::File_descriptor *fdesc = Libc::file_descriptor_allocator()->find_by_libc_fd(fd); + File_descriptor *fdesc = file_descriptor_allocator()->find_by_libc_fd(fd); if (fdesc == 0) return -1; - Genode::Lock_guard<Genode::Lock> rw_lock_guard(fdesc->lock); + Lock_guard<Lock> rw_lock_guard(fdesc->lock); - off_t old_offset = lseek(fd, 0, SEEK_CUR); + ::off_t old_offset = lseek(fd, 0, SEEK_CUR); if (old_offset == -1) return -1; diff --git a/repos/libports/src/lib/libc/thread.cc b/repos/libports/src/lib/libc/pthread.cc similarity index 57% rename from repos/libports/src/lib/libc/thread.cc rename to repos/libports/src/lib/libc/pthread.cc index c569e4275..ef8868906 100644 --- a/repos/libports/src/lib/libc/thread.cc +++ b/repos/libports/src/lib/libc/pthread.cc @@ -12,31 +12,44 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* Genode includes */ #include <base/log.h> #include <base/sleep.h> #include <base/thread.h> #include <util/list.h> #include <libc/allocator.h> +/* libc includes */ #include <errno.h> #include <pthread.h> #include <stdlib.h> /* malloc, free */ -#include "thread.h" -#include "task.h" -#include "timed_semaphore.h" -#include "libc_init.h" -using namespace Genode; +/* libc-internal includes */ +#include <internal/pthread.h> +#include <internal/timed_semaphore.h> +#include <internal/init.h> +#include <internal/suspend.h> +#include <internal/resume.h> + +using namespace Libc; -static Libc::Allocator object_alloc; +static Genode::Env *_env_ptr; /* solely needed to spawn the timeout thread for the + timed semaphore */ + +static Thread *_main_thread_ptr; + +static Suspend *_suspend_ptr; +static Resume *_resume_ptr; -static Env *_env_ptr; /* solely needed to spawn the timeout thread for the - timed semaphore */ - - -void Libc::init_pthread_support(Genode::Env &env) { _env_ptr = &env; } +void Libc::init_pthread_support(Genode::Env &env, Suspend &suspend, Resume &resume) +{ + _env_ptr = &env; + _main_thread_ptr = Thread::myself(); + _suspend_ptr = &suspend; + _resume_ptr = &resume; +} static Libc::Timeout_entrypoint &_global_timeout_ep() @@ -45,28 +58,16 @@ static Libc::Timeout_entrypoint &_global_timeout_ep() if (!_env_ptr) throw Missing_call_of_init_pthread_support(); - static Libc::Timeout_entrypoint timeout_ep { *_env_ptr }; + static Timeout_entrypoint timeout_ep { *_env_ptr }; return timeout_ep; } -/* - * We initialize the main-thread pointer in a constructor depending on the - * assumption that libpthread is loaded on application startup by ldso. During - * this stage only the main thread is executed. - */ -static __attribute__((constructor)) Thread * main_thread() -{ - static Thread *thread = Thread::myself(); +/************* + ** Pthread ** + *************/ - return thread; -} - - -/* - * pthread - */ -void pthread::Thread_object::entry() +void Libc::Pthread::Thread_object::entry() { /* obtain stack attributes of new thread */ Thread::Stack_info info = Thread::mystack(); @@ -77,16 +78,16 @@ void pthread::Thread_object::entry() } -void pthread::join(void **retval) +void Libc::Pthread::join(void **retval) { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; - pthread &_thread; + Pthread &_thread; + + Check(Pthread &thread) : _thread(thread) { } - Check(pthread &thread) : _thread(thread) { } - bool suspend() override { retry = !_thread._exiting; @@ -94,8 +95,12 @@ void pthread::join(void **retval) } } check(*this); + struct Missing_call_of_init_pthread_support : Exception { }; + if (!_suspend_ptr) + throw Missing_call_of_init_pthread_support(); + do { - Libc::suspend(check); + _suspend_ptr->suspend(check); } while (check.retry); _join_lock.lock(); @@ -105,10 +110,16 @@ void pthread::join(void **retval) } -void pthread::cancel() +void Libc::Pthread::cancel() { _exiting = true; - Libc::resume_all(); + + struct Missing_call_of_init_pthread_support : Exception { }; + if (!_resume_ptr) + throw Missing_call_of_init_pthread_support(); + + _resume_ptr->resume_all(); + _join_lock.unlock(); } @@ -117,53 +128,290 @@ void pthread::cancel() * Registry */ -void Pthread_registry::insert(pthread_t thread) +void Libc::Pthread_registry::insert(Pthread &thread) { /* prevent multiple insertions at the same location */ - static Genode::Lock insert_lock; - Genode::Lock::Guard insert_lock_guard(insert_lock); + static Lock insert_lock; + Lock::Guard insert_lock_guard(insert_lock); for (unsigned int i = 0; i < MAX_NUM_PTHREADS; i++) { if (_array[i] == 0) { - _array[i] = thread; + _array[i] = &thread; return; } } - Genode::error("pthread registry overflow, pthread_self() might fail"); + error("pthread registry overflow, pthread_self() might fail"); } -void Pthread_registry::remove(pthread_t thread) +void Libc::Pthread_registry::remove(Pthread &thread) { for (unsigned int i = 0; i < MAX_NUM_PTHREADS; i++) { - if (_array[i] == thread) { + if (_array[i] == &thread) { _array[i] = 0; return; } } - Genode::error("could not remove unknown pthread from registry"); + error("could not remove unknown pthread from registry"); } -bool Pthread_registry::contains(pthread_t thread) +bool Libc::Pthread_registry::contains(Pthread &thread) { for (unsigned int i = 0; i < MAX_NUM_PTHREADS; i++) - if (_array[i] == thread) + if (_array[i] == &thread) return true; return false; } -Pthread_registry &pthread_registry() +Libc::Pthread_registry &pthread_registry() { - static Pthread_registry instance; + static Libc::Pthread_registry instance; return instance; } +/*********** + ** Mutex ** + ***********/ + +namespace Libc { + struct Pthread_mutex_normal; + struct Pthread_mutex_errorcheck; + struct Pthread_mutex_recursive; +} + +/* + * This class is named 'struct pthread_mutex_attr' because the + * 'pthread_mutexattr_t' type is defined as 'struct pthread_mutex_attr *' + * in '_pthreadtypes.h' + */ +struct pthread_mutex_attr { pthread_mutextype type; }; + + +/* + * This class is named 'struct pthread_mutex' because the 'pthread_mutex_t' + * type is defined as 'struct pthread_mutex *' in '_pthreadtypes.h' + */ +struct pthread_mutex +{ + pthread_t _owner { nullptr }; + Lock _data_mutex; + + struct Missing_call_of_init_pthread_support : Exception { }; + + void _suspend(Suspend_functor &func) + { + if (!_suspend_ptr) + throw Missing_call_of_init_pthread_support(); + _suspend_ptr->suspend(func); + } + + void _resume_all() + { + if (!_resume_ptr) + throw Missing_call_of_init_pthread_support(); + _resume_ptr->resume_all(); + } + + pthread_mutex() { } + + virtual ~pthread_mutex() { } + + /* + * The behavior of the following function follows the "robust mutex" + * described IEEE Std 1003.1 POSIX.1-2017 + * https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html + */ + virtual int lock() = 0; + virtual int trylock() = 0; + virtual int unlock() = 0; +}; + + +struct Libc::Pthread_mutex_normal : pthread_mutex +{ + int lock() override final + { + struct Try_lock : Suspend_functor + { + bool retry { false }; /* have to try after resume */ + + Pthread_mutex_normal &_mutex; + + Try_lock(Pthread_mutex_normal &mutex) : _mutex(mutex) { } + + bool suspend() override + { + retry = _mutex.trylock() == EBUSY; + return retry; + } + } try_lock(*this); + + do { _suspend(try_lock); } while (try_lock.retry); + + return 0; + } + + int trylock() override final + { + Lock::Guard lock_guard(_data_mutex); + + if (!_owner) { + _owner = pthread_self(); + return 0; + } + + return EBUSY; + } + + int unlock() override final + { + Lock::Guard lock_guard(_data_mutex); + + if (_owner != pthread_self()) + return EPERM; + + _owner = nullptr; + _resume_all(); + + return 0; + } +}; + + +struct Libc::Pthread_mutex_errorcheck : pthread_mutex +{ + int lock() override final + { + /* + * We can't use trylock() as it returns EBUSY also for the + * EDEADLK case. + */ + struct Try_lock : Suspend_functor + { + bool retry { false }; /* have to try after resume */ + int result { 0 }; + + Pthread_mutex_errorcheck &_mutex; + + Try_lock(Pthread_mutex_errorcheck &mutex) : _mutex(mutex) { } + + bool suspend() override + { + Lock::Guard lock_guard(_mutex._data_mutex); + + if (!_mutex._owner) { + _mutex._owner = pthread_self(); + retry = false; + result = 0; + } else if (_mutex._owner == pthread_self()) { + retry = false; + result = EDEADLK; + } else { + retry = true; + } + + return retry; + } + } try_lock(*this); + + do { _suspend(try_lock); } while (try_lock.retry); + + return try_lock.result; + } + + int trylock() override final + { + Lock::Guard lock_guard(_data_mutex); + + if (!_owner) { + _owner = pthread_self(); + return 0; + } + + return EBUSY; + } + + int unlock() override final + { + Lock::Guard lock_guard(_data_mutex); + + if (_owner != pthread_self()) + return EPERM; + + _owner = nullptr; + _resume_all(); + + return 0; + } +}; + + +struct Libc::Pthread_mutex_recursive : pthread_mutex +{ + unsigned _nesting_level { 0 }; + + int lock() override final + { + struct Try_lock : Suspend_functor + { + bool retry { false }; /* have to try after resume */ + + Pthread_mutex_recursive &_mutex; + + Try_lock(Pthread_mutex_recursive &mutex) : _mutex(mutex) { } + + bool suspend() override + { + retry = _mutex.trylock() == EBUSY; + return retry; + } + } try_lock(*this); + + do { _suspend(try_lock); } while (try_lock.retry); + + return 0; + } + + int trylock() override final + { + Lock::Guard lock_guard(_data_mutex); + + if (!_owner) { + _owner = pthread_self(); + _nesting_level = 1; + return 0; + } else if (_owner == pthread_self()) { + ++_nesting_level; + return 0; + } + + return EBUSY; + } + + int unlock() override final + { + Lock::Guard lock_guard(_data_mutex); + + if (_owner != pthread_self()) + return EPERM; + + --_nesting_level; + if (_nesting_level == 0) { + _owner = nullptr; + _resume_all(); + } + + return 0; + } +}; + + extern "C" { /* Thread */ @@ -172,7 +420,8 @@ extern "C" { { thread->join(retval); - destroy(object_alloc, thread); + Libc::Allocator alloc { }; + destroy(alloc, thread); return 0; } @@ -183,7 +432,8 @@ extern "C" { if (!attr) return EINVAL; - *attr = new (object_alloc) pthread_attr; + Libc::Allocator alloc { }; + *attr = new (alloc) pthread_attr; return 0; } @@ -194,7 +444,8 @@ extern "C" { if (!attr || !*attr) return EINVAL; - destroy(object_alloc, *attr); + Libc::Allocator alloc { }; + destroy(alloc, *attr); *attr = 0; return 0; @@ -211,14 +462,14 @@ extern "C" { void pthread_exit(void *value_ptr) { pthread_self()->exit(value_ptr); - Genode::sleep_forever(); + sleep_forever(); } /* special non-POSIX function (for example used in libresolv) */ int _pthread_main_np(void) { - return (Thread::myself() == main_thread()); + return (Thread::myself() == _main_thread_ptr); } @@ -228,7 +479,7 @@ extern "C" { pthread_t pthread_myself = static_cast<pthread_t>(&Thread::Tls::Base::tls()); - if (pthread_registry().contains(pthread_myself)) + if (pthread_registry().contains(*pthread_myself)) return pthread_myself; } catch (Thread::Tls::Base::Undefined) { } @@ -251,7 +502,8 @@ extern "C" { * of the pthread object would also destruct the 'Thread' of the main * thread. */ - static pthread *main = new (object_alloc) pthread(*Thread::myself()); + Libc::Allocator alloc { }; + static pthread *main = new (alloc) pthread(*Thread::myself()); return main; } @@ -276,7 +528,7 @@ extern "C" { stacksize = max_stack; } - (*attr)->stack_size = Genode::align_addr(stacksize, 12); + (*attr)->stack_size = align_addr(stacksize, 12); return 0; } @@ -330,175 +582,13 @@ extern "C" { /* Mutex */ - - struct pthread_mutex_attr - { - int type; - - pthread_mutex_attr() : type(PTHREAD_MUTEX_NORMAL) { } - }; - - - struct pthread_mutex - { - pthread_mutex_attr mutexattr; - - Lock mutex_lock; - - pthread_t owner; - int lock_count; - Lock owner_and_counter_lock; - - pthread_mutex(const pthread_mutexattr_t *__restrict attr) - : owner(0), - lock_count(0) - { - if (attr && *attr) - mutexattr = **attr; - } - - int lock() - { - if (mutexattr.type == PTHREAD_MUTEX_RECURSIVE) { - - Lock::Guard lock_guard(owner_and_counter_lock); - - if (lock_count == 0) { - owner = pthread_self(); - lock_count++; - mutex_lock.lock(); - return 0; - } - - /* the mutex is already locked */ - if (pthread_self() == owner) { - lock_count++; - return 0; - } else { - mutex_lock.lock(); - return 0; - } - } - - if (mutexattr.type == PTHREAD_MUTEX_ERRORCHECK) { - - Lock::Guard lock_guard(owner_and_counter_lock); - - if (lock_count == 0) { - owner = pthread_self(); - mutex_lock.lock(); - return 0; - } - - /* the mutex is already locked */ - if (pthread_self() != owner) { - mutex_lock.lock(); - return 0; - } else - return EDEADLK; - } - - /* PTHREAD_MUTEX_NORMAL or PTHREAD_MUTEX_DEFAULT */ - mutex_lock.lock(); - return 0; - } - - int trylock() - { - if (mutexattr.type == PTHREAD_MUTEX_RECURSIVE) { - - Lock::Guard lock_guard(owner_and_counter_lock); - - if (lock_count == 0) { - owner = pthread_self(); - lock_count++; - mutex_lock.lock(); - return 0; - } - - /* the mutex is already locked */ - if (pthread_self() == owner) { - lock_count++; - return 0; - } else { - return EBUSY; - } - } - - if (mutexattr.type == PTHREAD_MUTEX_ERRORCHECK) { - - Lock::Guard lock_guard(owner_and_counter_lock); - - if (lock_count == 0) { - owner = pthread_self(); - mutex_lock.lock(); - return 0; - } - - /* the mutex is already locked */ - if (pthread_self() != owner) { - return EBUSY; - } else - return EDEADLK; - } - - /* PTHREAD_MUTEX_NORMAL or PTHREAD_MUTEX_DEFAULT */ - Lock::Guard lock_guard(owner_and_counter_lock); - - if (lock_count == 0) { - owner = pthread_self(); - mutex_lock.lock(); - return 0; - } - - return EBUSY; - } - - int unlock() - { - - if (mutexattr.type == PTHREAD_MUTEX_RECURSIVE) { - - Lock::Guard lock_guard(owner_and_counter_lock); - - if (pthread_self() != owner) - return EPERM; - - lock_count--; - - if (lock_count == 0) { - owner = 0; - mutex_lock.unlock(); - } - - return 0; - } - - if (mutexattr.type == PTHREAD_MUTEX_ERRORCHECK) { - - Lock::Guard lock_guard(owner_and_counter_lock); - - if (pthread_self() != owner) - return EPERM; - - owner = 0; - mutex_lock.unlock(); - return 0; - } - - /* PTHREAD_MUTEX_NORMAL or PTHREAD_MUTEX_DEFAULT */ - mutex_lock.unlock(); - return 0; - } - }; - - int pthread_mutexattr_init(pthread_mutexattr_t *attr) { if (!attr) return EINVAL; - *attr = new (object_alloc) pthread_mutex_attr; + Libc::Allocator alloc { }; + *attr = new (alloc) pthread_mutex_attr { PTHREAD_MUTEX_NORMAL }; return 0; } @@ -509,8 +599,9 @@ extern "C" { if (!attr || !*attr) return EINVAL; - destroy(object_alloc, *attr); - *attr = 0; + Libc::Allocator alloc { }; + destroy(alloc, *attr); + *attr = nullptr; return 0; } @@ -521,19 +612,32 @@ extern "C" { if (!attr || !*attr) return EINVAL; - (*attr)->type = type; + (*attr)->type = (pthread_mutextype)type; return 0; } - int pthread_mutex_init(pthread_mutex_t *__restrict mutex, - const pthread_mutexattr_t *__restrict attr) + int pthread_mutex_init(pthread_mutex_t *mutex, + pthread_mutexattr_t const *attr) { if (!mutex) return EINVAL; - *mutex = new (object_alloc) pthread_mutex(attr); + + Libc::Allocator alloc { }; + + pthread_mutextype const type = (!attr || !*attr) + ? PTHREAD_MUTEX_NORMAL : (*attr)->type; + switch (type) { + case PTHREAD_MUTEX_NORMAL: *mutex = new (alloc) Pthread_mutex_normal; break; + case PTHREAD_MUTEX_ERRORCHECK: *mutex = new (alloc) Pthread_mutex_errorcheck; break; + case PTHREAD_MUTEX_RECURSIVE: *mutex = new (alloc) Pthread_mutex_recursive; break; + + default: + *mutex = nullptr; + return EINVAL; + } return 0; } @@ -544,7 +648,8 @@ extern "C" { if ((!mutex) || (*mutex == PTHREAD_MUTEX_INITIALIZER)) return EINVAL; - destroy(object_alloc, *mutex); + Libc::Allocator alloc { }; + destroy(alloc, *mutex); *mutex = PTHREAD_MUTEX_INITIALIZER; return 0; @@ -557,11 +662,9 @@ extern "C" { return EINVAL; if (*mutex == PTHREAD_MUTEX_INITIALIZER) - pthread_mutex_init(mutex, 0); + pthread_mutex_init(mutex, nullptr); - (*mutex)->lock(); - - return 0; + return (*mutex)->lock(); } @@ -571,7 +674,7 @@ extern "C" { return EINVAL; if (*mutex == PTHREAD_MUTEX_INITIALIZER) - pthread_mutex_init(mutex, 0); + pthread_mutex_init(mutex, nullptr); return (*mutex)->trylock(); } @@ -583,11 +686,9 @@ extern "C" { return EINVAL; if (*mutex == PTHREAD_MUTEX_INITIALIZER) - pthread_mutex_init(mutex, 0); + return EINVAL; - (*mutex)->unlock(); - - return 0; + return (*mutex)->unlock(); } @@ -604,7 +705,7 @@ extern "C" { int num_waiters; int num_signallers; Lock counter_lock; - Libc::Timed_semaphore signal_sem { _global_timeout_ep() }; + Timed_semaphore signal_sem { _global_timeout_ep() }; Semaphore handshake_sem; pthread_cond() : num_waiters(0), num_signallers(0) { } @@ -648,14 +749,15 @@ extern "C" { static int cond_init(pthread_cond_t *__restrict cond, const pthread_condattr_t *__restrict attr) { - static Genode::Lock cond_init_lock { }; + static Lock cond_init_lock { }; if (!cond) return EINVAL; try { - Genode::Lock::Guard g(cond_init_lock); - *cond = new (object_alloc) pthread_cond; + Lock::Guard g(cond_init_lock); + Libc::Allocator alloc { }; + *cond = new (alloc) pthread_cond; return 0; } catch (...) { return ENOMEM; } } @@ -673,7 +775,8 @@ extern "C" { if (!cond || !*cond) return EINVAL; - destroy(object_alloc, *cond); + Libc::Allocator alloc { }; + destroy(alloc, *cond); *cond = 0; return 0; @@ -751,9 +854,9 @@ extern "C" { try { c->signal_sem.down(timeout); - } catch (Libc::Timeout_exception) { + } catch (Timeout_exception) { result = ETIMEDOUT; - } catch (Libc::Nonblocking_exception) { + } catch (Nonblocking_exception) { errno = ETIMEDOUT; result = ETIMEDOUT; } @@ -838,24 +941,42 @@ extern "C" { }; - static Lock key_list_lock; - List<Key_element> key_list[PTHREAD_KEYS_MAX]; + static Lock &key_list_lock() + { + static Lock inst { }; + return inst; + } + + + struct Keys + { + List<Key_element> key[PTHREAD_KEYS_MAX]; + }; + + + static Keys &keys() + { + static Keys inst { }; + return inst; + } + int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) { if (!key) return EINVAL; - Lock_guard<Lock> key_list_lock_guard(key_list_lock); + Lock_guard<Lock> key_list_lock_guard(key_list_lock()); for (int k = 0; k < PTHREAD_KEYS_MAX; k++) { /* * Find an empty key slot and insert an element for the current * thread to mark the key slot as used. */ - if (!key_list[k].first()) { - Key_element *key_element = new (object_alloc) Key_element(Thread::myself(), 0); - key_list[k].insert(key_element); + if (!keys().key[k].first()) { + Libc::Allocator alloc { }; + Key_element *key_element = new (alloc) Key_element(Thread::myself(), 0); + keys().key[k].insert(key_element); *key = k; return 0; } @@ -867,14 +988,15 @@ extern "C" { int pthread_key_delete(pthread_key_t key) { - if (key < 0 || key >= PTHREAD_KEYS_MAX || !key_list[key].first()) + if (key < 0 || key >= PTHREAD_KEYS_MAX || !keys().key[key].first()) return EINVAL; - Lock_guard<Lock> key_list_lock_guard(key_list_lock); + Lock_guard<Lock> key_list_lock_guard(key_list_lock()); - while (Key_element * element = key_list[key].first()) { - key_list[key].remove(element); - destroy(object_alloc, element); + while (Key_element * element = keys().key[key].first()) { + keys().key[key].remove(element); + Libc::Allocator alloc { }; + destroy(alloc, element); } return 0; @@ -888,9 +1010,9 @@ extern "C" { void *myself = Thread::myself(); - Lock_guard<Lock> key_list_lock_guard(key_list_lock); + Lock_guard<Lock> key_list_lock_guard(key_list_lock()); - for (Key_element *key_element = key_list[key].first(); key_element; + for (Key_element *key_element = keys().key[key].first(); key_element; key_element = key_element->next()) if (key_element->thread_base == myself) { key_element->value = value; @@ -898,8 +1020,9 @@ extern "C" { } /* key element does not exist yet - create a new one */ - Key_element *key_element = new (object_alloc) Key_element(Thread::myself(), value); - key_list[key].insert(key_element); + Libc::Allocator alloc { }; + Key_element *key_element = new (alloc) Key_element(Thread::myself(), value); + keys().key[key].insert(key_element); return 0; } @@ -911,9 +1034,9 @@ extern "C" { void *myself = Thread::myself(); - Lock_guard<Lock> key_list_lock_guard(key_list_lock); + Lock_guard<Lock> key_list_lock_guard(key_list_lock()); - for (Key_element *key_element = key_list[key].first(); key_element; + for (Key_element *key_element = keys().key[key].first(); key_element; key_element = key_element->next()) if (key_element->thread_base == myself) return (void*)(key_element->value); @@ -926,29 +1049,28 @@ extern "C" { { if (!once || ((once->state != PTHREAD_NEEDS_INIT) && (once->state != PTHREAD_DONE_INIT))) - return EINTR; + return EINVAL; if (!once->mutex) { - pthread_mutex_t p = new (object_alloc) pthread_mutex(0); - /* be paranoid */ - if (!p) - return EINTR; + pthread_mutex_t p; + pthread_mutex_init(&p, nullptr); + if (!p) return EINVAL; - static Lock lock; + { + static Lock lock; + Lock::Guard guard(lock); - lock.lock(); - if (!once->mutex) { - once->mutex = p; - p = nullptr; + if (!once->mutex) { + once->mutex = p; + p = nullptr; + } } - lock.unlock(); /* * If another thread concurrently allocated a mutex and was faster, * free our mutex since it is not used. */ - if (p) - destroy(object_alloc, p); + if (p) pthread_mutex_destroy(&p); } once->mutex->lock(); diff --git a/repos/libports/src/lib/libc/thread_create.cc b/repos/libports/src/lib/libc/pthread_create.cc similarity index 64% rename from repos/libports/src/lib/libc/thread_create.cc rename to repos/libports/src/lib/libc/pthread_create.cc index 7f54e8d29..97e09597f 100644 --- a/repos/libports/src/lib/libc/thread_create.cc +++ b/repos/libports/src/lib/libc/pthread_create.cc @@ -14,44 +14,45 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* libc includes */ #include <libc/allocator.h> - -#include "thread_create.h" -#include "thread.h" #include <errno.h> - -static Libc::Allocator object_alloc; +/* libc-internal includes */ +#include <internal/thread_create.h> +#include <internal/pthread.h> int Libc::pthread_create(pthread_t *thread, void *(*start_routine) (void *), void *arg, size_t stack_size, char const * name, - Genode::Cpu_session * cpu, Genode::Affinity::Location location) + Cpu_session * cpu, Affinity::Location location) { - pthread_t thread_obj = new (object_alloc) - pthread(start_routine, arg, - stack_size, name, cpu, location); - if (!thread_obj) - return EAGAIN; + Libc::Allocator alloc { }; + pthread_t thread_obj = new (alloc) + pthread(start_routine, arg, + stack_size, name, cpu, location); + if (!thread_obj) + return EAGAIN; - *thread = thread_obj; + *thread = thread_obj; - thread_obj->start(); + thread_obj->start(); - return 0; + return 0; } -int Libc::pthread_create(pthread_t *thread, Genode::Thread &t) +int Libc::pthread_create(pthread_t *thread, Thread &t) { - pthread_t thread_obj = new (object_alloc) pthread(t); + Libc::Allocator alloc { }; + pthread_t thread_obj = new (alloc) pthread(t); - if (!thread_obj) - return EAGAIN; + if (!thread_obj) + return EAGAIN; - *thread = thread_obj; - return 0; + *thread = thread_obj; + return 0; } diff --git a/repos/libports/src/lib/libc/readv_writev.cc b/repos/libports/src/lib/libc/readv_writev.cc index 7555062bd..b882ca962 100644 --- a/repos/libports/src/lib/libc/readv_writev.cc +++ b/repos/libports/src/lib/libc/readv_writev.cc @@ -22,32 +22,41 @@ #include <errno.h> #include <stdio.h> +/* libc-internal includes */ +#include <internal/types.h> -static Genode::Lock rw_lock; +using namespace Libc; struct Read { - ssize_t operator()(int fd, void *buf, size_t count) - { - return read(fd, buf, count); - } + ssize_t operator()(int fd, void *buf, size_t count) + { + return read(fd, buf, count); + } }; struct Write { - ssize_t operator()(int fd, const void *buf, size_t count) - { - return write(fd, buf, count); - } + ssize_t operator()(int fd, const void *buf, size_t count) + { + return write(fd, buf, count); + } }; +static Lock &rw_lock() +{ + static Lock rw_lock; + return rw_lock; +} + + template <typename Rw_func> static ssize_t readv_writev_impl(Rw_func rw_func, int fd, const struct iovec *iov, int iovcnt) { - Genode::Lock_guard<Genode::Lock> rw_lock_guard(rw_lock); + Lock_guard<Lock> rw_lock_guard(rw_lock()); char *v; ssize_t bytes_transfered_total = 0; diff --git a/repos/libports/src/lib/libc/rwlock.cc b/repos/libports/src/lib/libc/rwlock.cc index a1ac4ca2e..30c9702bd 100644 --- a/repos/libports/src/lib/libc/rwlock.cc +++ b/repos/libports/src/lib/libc/rwlock.cc @@ -2,7 +2,6 @@ * \brief POSIX readers/writer lock (rwlock) implementation * \author Alexander Senier * \date 2018-01-25 - * */ /* @@ -19,12 +18,14 @@ #include <base/thread.h> #include <libc/allocator.h> -/* Libc includes */ +/* libc includes */ #include <errno.h> #include <pthread.h> +/* libc-internal includes */ +#include <internal/types.h> -static Libc::Allocator object_alloc; +using namespace Libc; /* @@ -43,16 +44,16 @@ extern "C" { { private: - Genode::Thread *_owner = nullptr; - Genode::Lock _nbr_mutex {}; - Genode::Lock _global_mutex {}; + Thread *_owner = nullptr; + Lock _nbr_mutex {}; + Lock _global_mutex {}; int _nbr = 0; public: void rdlock() { - Genode::Lock_guard<Genode::Lock> guard(_nbr_mutex); + Lock_guard<Lock> guard(_nbr_mutex); ++_nbr; if (_nbr == 1) { _global_mutex.lock(); @@ -63,14 +64,14 @@ extern "C" { void wrlock() { _global_mutex.lock(); - _owner = Genode::Thread::myself(); + _owner = Thread::myself(); } int unlock() { /* Read lock */ if (_owner == nullptr) { - Genode::Lock_guard<Genode::Lock> guard(_nbr_mutex); + Lock_guard<Lock> guard(_nbr_mutex); _nbr--; if (_nbr == 0) { _owner = nullptr; @@ -79,8 +80,8 @@ extern "C" { return 0; }; - if (_owner != Genode::Thread::myself()) { - Genode::error("Unlocking writer lock owned by other thread"); + if (_owner != Thread::myself()) { + error("Unlocking writer lock owned by other thread"); errno = EPERM; return -1; }; @@ -98,14 +99,15 @@ extern "C" { static int rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { - static Genode::Lock rwlock_init_lock { }; + static Lock rwlock_init_lock { }; if (!rwlock) return EINVAL; try { - Genode::Lock::Guard g(rwlock_init_lock); - *rwlock = new (object_alloc) struct pthread_rwlock(); + Lock::Guard g(rwlock_init_lock); + Libc::Allocator alloc { }; + *rwlock = new (alloc) struct pthread_rwlock(); return 0; } catch (...) { return ENOMEM; } } @@ -117,7 +119,8 @@ extern "C" { int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) { - destroy(object_alloc, *rwlock); + Libc::Allocator alloc { }; + destroy(alloc, *rwlock); return 0; } @@ -154,7 +157,8 @@ extern "C" { int pthread_rwlockattr_init(pthread_rwlockattr_t *attr) { - *attr = new (object_alloc) struct pthread_rwlockattr(); + Libc::Allocator alloc { }; + *attr = new (alloc) struct pthread_rwlockattr(); return 0; } @@ -175,7 +179,8 @@ extern "C" { int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) { - destroy(object_alloc, *attr); + Libc::Allocator alloc { }; + destroy(alloc, *attr); return 0; } diff --git a/repos/libports/src/lib/libc/select.cc b/repos/libports/src/lib/libc/select.cc index 84abffc5b..eca9677a4 100644 --- a/repos/libports/src/lib/libc/select.cc +++ b/repos/libports/src/lib/libc/select.cc @@ -3,6 +3,7 @@ * \author Christian Prochaska * \author Christian Helmuth * \author Emery Hemingway + * \author Norman Feske * \date 2010-01-21 * * the 'select()' implementation is partially based on the lwip version as @@ -22,6 +23,7 @@ /* Genode includes */ #include <base/log.h> +#include <base/exception.h> #include <util/reconstructible.h> /* Libc includes */ @@ -32,14 +34,37 @@ #include <sys/select.h> #include <signal.h> -#include "task.h" - +/* libc-internal includes */ +#include <internal/init.h> +#include <internal/signal.h> +#include <internal/suspend.h> +#include <internal/resume.h> +#include <internal/select.h> +#include <internal/errno.h> namespace Libc { struct Select_cb; struct Select_cb_list; } +using namespace Libc; + + +static Suspend *_suspend_ptr; +static Resume *_resume_ptr; +static Select *_select_ptr; +static Libc::Signal *_signal_ptr; + + +void Libc::init_select(Suspend &suspend, Resume &resume, Select &select, + Signal &signal) +{ + _suspend_ptr = &suspend; + _resume_ptr = &resume; + _select_ptr = &select; + _signal_ptr = &signal; +} + void (*libc_select_notify)() __attribute__((weak)); @@ -64,14 +89,14 @@ struct Libc::Select_cb struct Libc::Select_cb_list { - Genode::Lock _mutex; - Select_cb *_first = nullptr; + Lock _mutex; + Select_cb *_first = nullptr; - struct Guard : Genode::Lock::Guard + struct Guard : Lock::Guard { -Select_cb_list *l; + Select_cb_list *l; - Guard(Select_cb_list &list) : Genode::Lock::Guard(list._mutex), l(&list) { } + Guard(Select_cb_list &list) : Lock::Guard(list._mutex), l(&list) { } }; void unsynchronized_insert(Select_cb *scb) @@ -110,7 +135,11 @@ Select_cb_list *l; }; /** The global list of tasks waiting for select */ -static Libc::Select_cb_list select_cb_list; +static Libc::Select_cb_list &select_cb_list() +{ + static Select_cb_list inst; + return inst; +} /** @@ -140,7 +169,7 @@ static int selscan(int nfds, if (out_writefds) FD_ZERO(out_writefds); if (out_exceptfds) FD_ZERO(out_exceptfds); - for (Libc::Plugin *plugin = Libc::plugin_registry()->first(); + for (Plugin *plugin = plugin_registry()->first(); plugin; plugin = plugin->next()) { if (plugin->supports_select(nfds, in_readfds, in_writefds, in_exceptfds, &tv_0)) { @@ -165,7 +194,7 @@ static int selscan(int nfds, } nready += plugin_nready; } else if (plugin_nready < 0) { - Genode::error("plugin->select() returned error value ", plugin_nready); + error("plugin->select() returned error value ", plugin_nready); } } } @@ -183,7 +212,7 @@ static void select_notify() /* check for each waiting select() function if one of its fds is ready now * and if so, wake all up */ - select_cb_list.for_each([&] (Libc::Select_cb &scb) { + select_cb_list().for_each([&] (Select_cb &scb) { scb.nready = selscan(scb.nfds, &scb.readfds, &scb.writefds, &scb.exceptfds, &tmp_readfds, &tmp_writefds, &tmp_exceptfds); @@ -196,12 +225,17 @@ static void select_notify() } }); - if (resume_all) - Libc::resume_all(); + if (resume_all) { + struct Missing_call_of_init_select : Exception { }; + if (!_resume_ptr) + throw Missing_call_of_init_select(); + + _resume_ptr->resume_all(); + } } -static inline void print(Genode::Output &output, timeval *tv) +static inline void print(Output &output, timeval *tv) { if (!tv) { print(output, "nullptr"); @@ -221,7 +255,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, { fd_set in_readfds, in_writefds, in_exceptfds; - Genode::Constructible<Libc::Select_cb> select_cb; + Constructible<Select_cb> select_cb; /* initialize the select notification function pointer */ if (!libc_select_notify) @@ -236,7 +270,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, * We use the guard directly to atomically check if any descripor is * ready, but insert into select-callback list otherwise. */ - Libc::Select_cb_list::Guard guard(select_cb_list); + Select_cb_list::Guard guard(select_cb_list()); int const nready = selscan(nfds, &in_readfds, &in_writefds, &in_exceptfds, @@ -254,7 +288,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, select_cb.construct(nfds, in_readfds, in_writefds, in_exceptfds); - select_cb_list.unsynchronized_insert(&(*select_cb)); + select_cb_list().unsynchronized_insert(&(*select_cb)); } struct Timeout @@ -269,25 +303,52 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, Timeout(timeval *tv) : _tv(tv) { } } timeout { tv }; - struct Check : Libc::Suspend_functor { - struct Timeout *timeout; - Libc::Select_cb *select_cb; + struct Check : Suspend_functor + { + struct Timeout *timeout; + Select_cb *select_cb; - Check(Timeout *timeout, Libc::Select_cb * select_cb) + Check(Timeout *timeout, Select_cb * select_cb) : timeout(timeout), select_cb(select_cb) { } bool suspend() override { return !timeout->expired() && select_cb->nready == 0; } } check ( &timeout, &*select_cb ); - while (!timeout.expired() && select_cb->nready == 0) - timeout.duration = Libc::suspend(check, timeout.duration); + { + struct Missing_call_of_init_select : Exception { }; + if (!_suspend_ptr || !_signal_ptr) + throw Missing_call_of_init_select(); + } - select_cb_list.remove(&(*select_cb)); + unsigned const orig_signal_count = _signal_ptr->count(); + + auto signal_occurred_during_select = [&] () + { + return _signal_ptr->count() != orig_signal_count; + }; + + for (;;) { + if (timeout.expired()) + break; + + if (select_cb->nready != 0) + break; + + if (signal_occurred_during_select()) + break; + + timeout.duration = _suspend_ptr->suspend(check, timeout.duration); + } + + select_cb_list().remove(&(*select_cb)); if (timeout.expired()) return 0; + if (signal_occurred_during_select()) + return Errno(EINTR); + /* not timed out -> results have been stored in select_cb by select_notify() */ if (readfds) *readfds = select_cb->readfds; @@ -352,14 +413,14 @@ int Libc::Select_handler_base::select(int nfds, fd_set &readfds, /* remove potentially enqueued callback from list */ if (_select_cb->constructed()) - select_cb_list.remove(&(**_select_cb)); + select_cb_list().remove(&(**_select_cb)); { /* * We use the guard directly to atomically check is any descripor is * ready, and insert into select-callback list otherwise. */ - Libc::Select_cb_list::Guard guard(select_cb_list); + Select_cb_list::Guard guard(select_cb_list()); int const nready = selscan(nfds, &in_readfds, &in_writefds, &in_exceptfds, @@ -373,10 +434,14 @@ int Libc::Select_handler_base::select(int nfds, fd_set &readfds, _select_cb->construct(nfds, in_readfds, in_writefds, in_exceptfds); - select_cb_list.unsynchronized_insert(&(**_select_cb)); + select_cb_list().unsynchronized_insert(&(**_select_cb)); } - Libc::schedule_select(this); + struct Missing_call_of_init_select : Exception { }; + if (!_select_ptr) + throw Missing_call_of_init_select(); + + _select_ptr->schedule_select(*this); return 0; } @@ -388,8 +453,10 @@ void Libc::Select_handler_base::dispatch_select() if (select_cb->nready == 0) return; - select_cb_list.remove(&(*select_cb)); - Libc::schedule_select(nullptr); + select_cb_list().remove(&(*select_cb)); + + if (_select_ptr) + _select_ptr->deschedule_select(); select_ready(select_cb->nready, select_cb->readfds, select_cb->writefds, select_cb->exceptfds); @@ -401,5 +468,6 @@ Libc::Select_handler_base::Select_handler_base() _select_cb((Select_handler_cb*)malloc(sizeof(*_select_cb))) { } + Libc::Select_handler_base::~Select_handler_base() { } diff --git a/repos/libports/src/lib/libc/semaphore.cc b/repos/libports/src/lib/libc/semaphore.cc index a2ef3c8f0..b0ec60f8d 100644 --- a/repos/libports/src/lib/libc/semaphore.cc +++ b/repos/libports/src/lib/libc/semaphore.cc @@ -12,15 +12,19 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* Genode includes */ #include <base/log.h> #include <base/semaphore.h> #include <semaphore.h> + +/* libc includes */ #include <libc/allocator.h> -using namespace Genode; +/* libc-internal includes */ +#include <internal/types.h> +using namespace Libc; -static Libc::Allocator object_alloc; extern "C" { @@ -28,7 +32,7 @@ extern "C" { * This class is named 'struct sem' because the 'sem_t' type is * defined as 'struct sem*' in 'semaphore.h' */ - struct sem : Semaphore + struct sem : Genode::Semaphore { sem(int value) : Semaphore(value) { } }; @@ -43,7 +47,8 @@ extern "C" { int sem_destroy(sem_t *sem) { - destroy(object_alloc, *sem); + Libc::Allocator alloc { }; + destroy(alloc, *sem); return 0; } @@ -57,7 +62,8 @@ extern "C" { int sem_init(sem_t *sem, int pshared, unsigned int value) { - *sem = new (object_alloc) struct sem(value); + Libc::Allocator alloc { }; + *sem = new (alloc) struct sem(value); return 0; } diff --git a/repos/libports/src/lib/libc/signal.cc b/repos/libports/src/lib/libc/signal.cc index 3b25fa8a9..dc9af2d44 100644 --- a/repos/libports/src/lib/libc/signal.cc +++ b/repos/libports/src/lib/libc/signal.cc @@ -21,8 +21,56 @@ extern "C" { #include <sys/wait.h> } -/* Genode includes */ -#include <base/log.h> +/* libc-internal includes */ +#include <internal/types.h> +#include <internal/init.h> +#include <internal/signal.h> +#include <internal/errno.h> + +using namespace Libc; + + +static Libc::Signal *_signal_ptr; + + +void Libc::init_signal(Signal &signal) +{ + _signal_ptr = &signal; +} + + +void Libc::Signal::_execute_signal_handler(unsigned n) +{ + if (signal_action[n].sa_flags & SA_SIGINFO) { + signal_action[n].sa_sigaction(n, 0, 0); + return; + } + + if (signal_action[n].sa_handler == SIG_DFL) { + switch (n) { + case SIGCHLD: + case SIGWINCH: + /* ignore */ + break; + default: + /* + * Trigger the termination of the process. + * + * We cannot call 'exit' immediately as the exiting code (e.g., + * 'atexit' handlers) may potentially issue I/O operations such + * as FD sync and close. Hence, we just flag the intention to + * exit and issue the actual exit call at the end of + * 'Signal::execute_signal_handlers' + */ + _exit = true; + _exit_code = (n << 8) | EXIT_FAILURE; + } + } else if (signal_action[n].sa_handler == SIG_IGN) { + /* do nothing */ + } else { + signal_action[n].sa_handler(n); + } +} extern "C" __attribute__((weak)) @@ -63,6 +111,49 @@ extern "C" int __i386_libc_sigprocmask(int how, const sigset_t *set, sigset_t *o } +extern "C" int sigaction(int, const struct sigaction *, struct sigaction *) __attribute__((weak)); + + +extern "C" int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) +{ + if ((signum < 1) || (signum > NSIG)) { + errno = EINVAL; + return -1; + } + + if (oldact) + *oldact = _signal_ptr->signal_action[signum]; + + if (act) + _signal_ptr->signal_action[signum] = *act; + + return 0; +} + + +extern "C" int _sigaction(int, const struct sigaction *, struct sigaction *) __attribute__((weak, alias("sigaction"))); +extern "C" int __sys_sigaction(int, const struct sigaction *, struct sigaction *) __attribute__((weak, alias("sigaction"))); +extern "C" int __libc_sigaction(int, const struct sigaction *, struct sigaction *) __attribute__((weak, alias("sigaction"))); + + +extern "C" int kill(pid_t pid, int signum) +{ + if (_signal_ptr->local_pid(pid)) { + _signal_ptr->charge(signum); + _signal_ptr->execute_signal_handlers(); + return 0; + } else { + warning("submitting signals to remote processes via 'kill' not supported"); + return Libc::Errno(EPERM); + } +} + + +extern "C" int _kill(pid_t, int) __attribute__((weak, alias("kill"))); +extern "C" int __sys_kill(pid_t, int) __attribute__((weak, alias("kill"))); +extern "C" int __libc_kill(pid_t, int) __attribute__((weak, alias("kill"))); + + extern "C" pid_t wait(int *istat) { return wait4(WAIT_ANY, istat, 0, NULL); } @@ -78,7 +169,7 @@ extern "C" pid_t _waitpid(pid_t pid, int *istat, int options) { extern "C" __attribute__((weak)) pid_t wait6(idtype_t, id_t, int*, int, struct __wrusage*, siginfo_t*) { - Genode::warning(__func__, " not implemented"); + warning(__func__, " not implemented"); errno = ENOSYS; return -1; } diff --git a/repos/libports/src/lib/libc/sleep.cc b/repos/libports/src/lib/libc/sleep.cc index fcd0b43dc..eac81a38a 100644 --- a/repos/libports/src/lib/libc/sleep.cc +++ b/repos/libports/src/lib/libc/sleep.cc @@ -12,19 +12,33 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* Libc includes */ +/* libc includes */ #include <sys/time.h> -#include "task.h" +/* libc-internal includes */ +#include <internal/suspend.h> +#include <internal/init.h> + +using namespace Libc; -/* Genode includes */ -#include <base/log.h> +static Suspend *_suspend_ptr; + + +void Libc::init_sleep(Suspend &suspend) +{ + _suspend_ptr = &suspend; +} + static void millisleep(Genode::uint64_t timeout_ms) { Genode::uint64_t remaining_ms = timeout_ms; + struct Missing_call_of_init_sleep : Exception { }; + if (!_suspend_ptr) + throw Missing_call_of_init_sleep(); + struct Check : Libc::Suspend_functor { bool suspend() override { return true; } @@ -32,14 +46,14 @@ static void millisleep(Genode::uint64_t timeout_ms) } check; while (remaining_ms > 0) - remaining_ms = Libc::suspend(check, remaining_ms); + remaining_ms = _suspend_ptr->suspend(check, remaining_ms); } extern "C" __attribute__((weak)) int nanosleep(const struct timespec *req, struct timespec *rem) { - Genode::uint64_t sleep_ms = (uint64_t)req->tv_sec*1000; + Genode::uint64_t sleep_ms = (Genode::uint64_t)req->tv_sec*1000; if (req->tv_nsec) sleep_ms += req->tv_nsec / 1000000; millisleep(sleep_ms); @@ -62,7 +76,7 @@ int clock_nanosleep(clockid_t clock_id, int flags, if (flags & TIMER_ABSTIME) { struct timespec now_ts { 0 }; if (clock_gettime(clock_id, &now_ts) != 0) { - Genode::error(__func__, ": RTC device not configured"); + error(__func__, ": RTC device not configured"); return -1; } @@ -87,7 +101,7 @@ int __sys_clock_nanosleep(clockid_t clock_id, int flags, extern "C" __attribute__((weak)) unsigned int sleep(unsigned int seconds) { - Genode::uint64_t sleep_ms = 1000 * (Genode::uint64_t)seconds; + Genode::uint64_t const sleep_ms = 1000 * (Genode::uint64_t)seconds; millisleep(sleep_ms); return 0; } diff --git a/repos/libports/src/lib/libc/socket_fs_plugin.cc b/repos/libports/src/lib/libc/socket_fs_plugin.cc index 6464d30a3..6590bc529 100644 --- a/repos/libports/src/lib/libc/socket_fs_plugin.cc +++ b/repos/libports/src/lib/libc/socket_fs_plugin.cc @@ -36,15 +36,25 @@ #include <net/if.h> /* libc-internal includes */ -#include "socket_fs_plugin.h" -#include "libc_file.h" -#include "libc_errno.h" -#include "task.h" +#include <internal/socket_fs_plugin.h> +#include <internal/file.h> +#include <internal/errno.h> +#include <internal/init.h> +#include <internal/suspend.h> namespace Libc { extern char const *config_socket(); - bool read_ready(Libc::File_descriptor *); + bool read_ready(File_descriptor *); +} + + +static Libc::Suspend *_suspend_ptr; + + +void Libc::init_socket_fs(Suspend &suspend) +{ + _suspend_ptr = &suspend; } @@ -52,11 +62,7 @@ namespace Libc { ** Utilities ** ***************/ -namespace Socket_fs { - - Libc::Allocator global_allocator; - - using Libc::Errno; +namespace Libc { namespace Socket_fs { struct Absolute_path : Vfs::Absolute_path { @@ -75,7 +81,6 @@ namespace Socket_fs { typedef String<NI_MAXSERV> Port_string; struct Sockaddr_string; - struct Exception { }; struct New_socket_failed : Exception { }; struct Address_conversion_failed : Exception { }; @@ -88,13 +93,13 @@ namespace Socket_fs { Plugin & plugin(); enum { MAX_CONTROL_PATH_LEN = 16 }; -} +} } -using namespace Socket_fs; +using namespace Libc::Socket_fs; -struct Socket_fs::Context : Libc::Plugin_context +struct Libc::Socket_fs::Context : Plugin_context { private: @@ -121,7 +126,7 @@ struct Socket_fs::Context : Libc::Plugin_context struct Inaccessible { }; /* exception */ Absolute_path const path { - _read_socket_path().base(), Libc::config_socket() }; + _read_socket_path().base(), config_socket() }; private: @@ -131,9 +136,9 @@ struct Socket_fs::Context : Libc::Plugin_context struct { - char const *name; - int num; - Libc::File_descriptor *file; + char const *name; + int num; + File_descriptor *file; } _fd[Fd::MAX] = { { "data", -1, nullptr }, { "connect", -1, nullptr }, { "bind", -1, nullptr }, @@ -161,11 +166,11 @@ struct Socket_fs::Context : Libc::Plugin_context Absolute_path file(_fd[type].name, path.base()); int const fd = open(file.base(), flags|_fd_flags); if (fd == -1) { - Genode::error(__func__, ": ", _fd[type].name, " file not accessible at ", file); + error(__func__, ": ", _fd[type].name, " file not accessible at ", file); throw Inaccessible(); } _fd[type].num = fd; - _fd[type].file = Libc::file_descriptor_allocator()->find_by_libc_fd(fd); + _fd[type].file = file_descriptor_allocator()->find_by_libc_fd(fd); } return _fd[type].num; @@ -244,10 +249,12 @@ struct Socket_fs::Context : Libc::Plugin_context sizeof(connect_status)); if (connect_status_len <= 0) { - Genode::error("socket_fs: reading from the connect file failed"); + error("socket_fs: reading from the connect file failed"); return -1; } + using ::strcmp; + if (strcmp(connect_status, "connected") == 0) return 0; @@ -257,13 +264,13 @@ struct Socket_fs::Context : Libc::Plugin_context if (strcmp(connect_status, "not connected") == 0) return Errno(ENOTCONN); - Genode::error("socket_fs: unhandled connection state"); + error("socket_fs: unhandled connection state"); return Errno(ECONNREFUSED); } }; -struct Socket_fs::Sockaddr_functor : Libc::Suspend_functor +struct Libc::Socket_fs::Sockaddr_functor : Suspend_functor { Socket_fs::Context &context; bool const nonblocking; @@ -275,7 +282,7 @@ struct Socket_fs::Sockaddr_functor : Libc::Suspend_functor }; -struct Socket_fs::Remote_functor : Socket_fs::Sockaddr_functor +struct Libc::Socket_fs::Remote_functor : Sockaddr_functor { Remote_functor(Socket_fs::Context &context, bool nonblocking) : Sockaddr_functor(context, nonblocking) { } @@ -285,9 +292,9 @@ struct Socket_fs::Remote_functor : Socket_fs::Sockaddr_functor }; -struct Socket_fs::Local_functor : Socket_fs::Sockaddr_functor +struct Libc::Socket_fs::Local_functor : Sockaddr_functor { - Local_functor(Socket_fs::Context &context, bool nonblocking) + Local_functor(Context &context, bool nonblocking) : Sockaddr_functor(context, nonblocking) { } bool suspend() override { return !nonblocking && !context.local_read_ready(); } @@ -295,22 +302,22 @@ struct Socket_fs::Local_functor : Socket_fs::Sockaddr_functor }; -struct Socket_fs::Plugin : Libc::Plugin +struct Libc::Socket_fs::Plugin : Libc::Plugin { bool supports_poll() override { return true; } bool supports_select(int, fd_set *, fd_set *, fd_set *, timeval *) override; - ssize_t read(Libc::File_descriptor *, void *, ::size_t) override; - ssize_t write(Libc::File_descriptor *, const void *, ::size_t) override; - int fcntl(Libc::File_descriptor *, int, long) override; - int close(Libc::File_descriptor *) override; - bool poll(Libc::File_descriptor &fd, struct pollfd &pfd) override; + ssize_t read(File_descriptor *, void *, ::size_t) override; + ssize_t write(File_descriptor *, const void *, ::size_t) override; + int fcntl(File_descriptor *, int, long) override; + int close(File_descriptor *) override; + bool poll(File_descriptor &fd, struct pollfd &pfd) override; int select(int, fd_set *, fd_set *, fd_set *, timeval *) override; - int ioctl(Libc::File_descriptor *, int, char *) override; + int ioctl(File_descriptor *, int, char *) override; }; -template <int CAPACITY> class Socket_fs::String +template <int CAPACITY> class Libc::Socket_fs::String { private: @@ -341,7 +348,7 @@ template <int CAPACITY> class Socket_fs::String * Both NI_MAXHOST and NI_MAXSERV include the terminating 0, which allows * use to put ':' between host and port on concatenation. */ -struct Socket_fs::Sockaddr_string : String<NI_MAXHOST + NI_MAXSERV> +struct Libc::Socket_fs::Sockaddr_string : String<NI_MAXHOST + NI_MAXSERV> { Sockaddr_string() { } @@ -381,6 +388,9 @@ struct Socket_fs::Sockaddr_string : String<NI_MAXHOST + NI_MAXSERV> }; +using namespace Libc; + + static Port_string port_string(sockaddr_in const &addr) { Port_string port; @@ -414,7 +424,7 @@ static sockaddr_in sockaddr_in_struct(Host_string const &host, Port_string const addrinfo hints; addrinfo *info = nullptr; - memset(&hints, 0, sizeof(hints)); + ::memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; if (getaddrinfo(host.base(), port.base(), &hints, &info)) @@ -434,8 +444,14 @@ static int read_sockaddr_in(Socket_fs::Sockaddr_functor &func, if (!addr) return Errno(EFAULT); if (!addrlen || *addrlen <= 0) return Errno(EINVAL); - while (!func.nonblocking && func.suspend()) - Libc::suspend(func); + while (!func.nonblocking && func.suspend()) { + + struct Missing_call_of_init_socket_fs : Exception { }; + if (!_suspend_ptr) + throw Missing_call_of_init_socket_fs(); + + _suspend_ptr->suspend(func); + } Sockaddr_string addr_string; int const n = read(func.fd(), addr_string.base(), addr_string.capacity() - 1); @@ -454,12 +470,12 @@ static int read_sockaddr_in(Socket_fs::Sockaddr_functor &func, try { /* convert the address but do not exceed the caller's buffer */ sockaddr_in saddr = sockaddr_in_struct(addr_string.host(), addr_string.port()); - memcpy(addr, &saddr, *addrlen); + ::memcpy(addr, &saddr, *addrlen); *addrlen = sizeof(saddr); return 0; } catch (Address_conversion_failed) { - Genode::warning("IP address conversion failed"); + warning("IP address conversion failed"); return Errno(ENOBUFS); } } @@ -471,7 +487,7 @@ static int read_sockaddr_in(Socket_fs::Sockaddr_functor &func, extern "C" int socket_fs_getpeername(int libc_fd, sockaddr *addr, socklen_t *addrlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -492,7 +508,7 @@ extern "C" int socket_fs_getpeername(int libc_fd, sockaddr *addr, socklen_t *add extern "C" int socket_fs_getsockname(int libc_fd, sockaddr *addr, socklen_t *addrlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -509,7 +525,7 @@ extern "C" int socket_fs_getsockname(int libc_fd, sockaddr *addr, socklen_t *add extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *listen_context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -531,23 +547,24 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen) return Errno(EINVAL); } - Absolute_path path = listen_context->path; + Socket_fs::Absolute_path path = listen_context->path; path.append("/accept_socket"); int handle_fd = ::open(path.base(), O_RDONLY); if (handle_fd < 0) { - Genode::error("failed to open accept socket at ", path); + error("failed to open accept socket at ", path); return Errno(EACCES); } Socket_fs::Context *accept_context; try { - accept_context = new (&global_allocator) + Libc::Allocator alloc { }; + accept_context = new (alloc) Socket_fs::Context(listen_context->proto(), handle_fd); } catch (New_socket_failed) { return Errno(EACCES); } - Libc::File_descriptor *accept_fd = - Libc::file_descriptor_allocator()->alloc(&plugin(), accept_context); + File_descriptor *accept_fd = + file_descriptor_allocator()->alloc(&plugin(), accept_context); /* inherit the O_NONBLOCK flag if set */ accept_context->fd_flags(listen_context->fd_flags()); @@ -564,7 +581,7 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen) extern "C" int socket_fs_bind(int libc_fd, sockaddr const *addr, socklen_t addrlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -573,7 +590,7 @@ extern "C" int socket_fs_bind(int libc_fd, sockaddr const *addr, socklen_t addrl if (!addr) return Errno(EFAULT); if (addr->sa_family != AF_INET) { - Genode::error(__func__, ": family not supported"); + error(__func__, ": family not supported"); return Errno(EAFNOSUPPORT); } @@ -586,7 +603,7 @@ extern "C" int socket_fs_bind(int libc_fd, sockaddr const *addr, socklen_t addrl catch (Address_conversion_failed) { return Errno(EINVAL); } try { - int const len = strlen(addr_string.base()); + int const len = ::strlen(addr_string.base()); int const n = write(context->bind_fd(), addr_string.base(), len); if (n != len) return Errno(EACCES); @@ -600,7 +617,7 @@ extern "C" int socket_fs_bind(int libc_fd, sockaddr const *addr, socklen_t addrl extern "C" int socket_fs_connect(int libc_fd, sockaddr const *addr, socklen_t addrlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -628,7 +645,7 @@ extern "C" int socket_fs_connect(int libc_fd, sockaddr const *addr, socklen_t ad context->state(Context::CONNECTING); - int const len = strlen(addr_string.base()); + int const len = ::strlen(addr_string.base()); int const n = write(context->connect_fd(), addr_string.base(), len); if (n != len) return Errno(ECONNREFUSED); @@ -696,14 +713,14 @@ extern "C" int socket_fs_connect(int libc_fd, sockaddr const *addr, socklen_t ad extern "C" int socket_fs_listen(int libc_fd, int backlog) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); if (!context) return Errno(ENOTSOCK); char buf[MAX_CONTROL_PATH_LEN]; - int const len = snprintf(buf, sizeof(buf), "%d", backlog); + int const len = ::snprintf(buf, sizeof(buf), "%d", backlog); int const n = write(context->listen_fd(), buf, len); if (n != len) return Errno(EOPNOTSUPP); @@ -716,7 +733,7 @@ extern "C" int socket_fs_listen(int libc_fd, int backlog) } -static ssize_t do_recvfrom(Libc::File_descriptor *fd, +static ssize_t do_recvfrom(File_descriptor *fd, void *buf, ::size_t len, int flags, struct sockaddr *src_addr, socklen_t *src_addrlen) { @@ -747,7 +764,7 @@ static ssize_t do_recvfrom(Libc::File_descriptor *fd, extern "C" ssize_t socket_fs_recvfrom(int libc_fd, void *buf, ::size_t len, int flags, sockaddr *src_addr, socklen_t *src_addrlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); return do_recvfrom(fd, buf, len, flags, src_addr, src_addrlen); @@ -763,12 +780,12 @@ extern "C" ssize_t socket_fs_recv(int libc_fd, void *buf, ::size_t len, int flag extern "C" ssize_t socket_fs_recvmsg(int libc_fd, msghdr *msg, int flags) { - Genode::warning("########## TODO ########## ", __func__); + warning("########## TODO ########## ", __func__); return 0; } -static ssize_t do_sendto(Libc::File_descriptor *fd, +static ssize_t do_sendto(File_descriptor *fd, void const *buf, ::size_t len, int flags, sockaddr const *dest_addr, socklen_t dest_addrlen) { @@ -778,7 +795,6 @@ static ssize_t do_sendto(Libc::File_descriptor *fd, if (!len) return Errno(EINVAL); /* TODO ENOTCONN, EISCONN, EDESTADDRREQ */ - /* TODO ECONNRESET */ try { if (dest_addr && context->proto() == Context::Proto::UDP) { @@ -786,7 +802,7 @@ static ssize_t do_sendto(Libc::File_descriptor *fd, Sockaddr_string addr_string(host_string(*(sockaddr_in const *)dest_addr), port_string(*(sockaddr_in const *)dest_addr)); - int const len = strlen(addr_string.base()); + int const len = ::strlen(addr_string.base()); int const n = write(context->remote_fd(), addr_string.base(), len); if (n != len) return Errno(EIO); } @@ -795,11 +811,26 @@ static ssize_t do_sendto(Libc::File_descriptor *fd, lseek(context->data_fd(), 0, 0); ssize_t out_len = write(context->data_fd(), buf, len); - if (out_len == 0) { - switch (context->proto()) { - case Socket_fs::Context::Proto::UDP: return Errno(ENETDOWN); - case Socket_fs::Context::Proto::TCP: return Errno(EAGAIN); - } + + switch (context->proto()) { + case Socket_fs::Context::Proto::UDP: + if (out_len == 0) return Errno(ENETDOWN); + break; + + case Socket_fs::Context::Proto::TCP: + if (out_len == 0) return Errno(EAGAIN); + /* + * Write errors to TCP-data files are reflected as EPIPE, which + * means the connection-mode socket is no longer connected. This + * explicitly does not differentiate ECONNRESET, which means the + * peer closed the connection while there was still unhandled data + * in the socket buffer on the remote side and sent an RST packet. + * + * TODO If the MSG_NOSIGNAL flag is not set, the SIGPIPE signal is + * generated to the calling thread. + */ + if (out_len == -1) return Errno(EPIPE); + break; } return out_len; } catch (Socket_fs::Context::Inaccessible) { @@ -811,7 +842,7 @@ static ssize_t do_sendto(Libc::File_descriptor *fd, extern "C" ssize_t socket_fs_sendto(int libc_fd, void const *buf, ::size_t len, int flags, sockaddr const *dest_addr, socklen_t dest_addrlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); return do_sendto(fd, buf, len, flags, dest_addr, dest_addrlen); @@ -828,7 +859,7 @@ extern "C" ssize_t socket_fs_send(int libc_fd, void const *buf, ::size_t len, in extern "C" int socket_fs_getsockopt(int libc_fd, int level, int optname, void *optval, socklen_t *optlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -879,7 +910,7 @@ extern "C" int socket_fs_getsockopt(int libc_fd, int level, int optname, extern "C" int socket_fs_setsockopt(int libc_fd, int level, int optname, void const *optval, socklen_t optlen) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -915,7 +946,7 @@ extern "C" int socket_fs_setsockopt(int libc_fd, int level, int optname, extern "C" int socket_fs_shutdown(int libc_fd, int how) { - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd); + File_descriptor *fd = file_descriptor_allocator()->find_by_libc_fd(libc_fd); if (!fd) return Errno(EBADF); Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); @@ -931,18 +962,18 @@ extern "C" int socket_fs_shutdown(int libc_fd, int how) extern "C" int socket_fs_socket(int domain, int type, int protocol) { - Absolute_path path(Libc::config_socket()); + Socket_fs::Absolute_path path(config_socket()); if (path == "") { - Genode::error(__func__, ": socket fs not mounted"); + error(__func__, ": socket fs not mounted"); return Errno(EACCES); } if (((type&7) != SOCK_STREAM || (protocol != 0 && protocol != IPPROTO_TCP)) && ((type&7) != SOCK_DGRAM || (protocol != 0 && protocol != IPPROTO_UDP))) { - Genode::error(__func__, - ": socket with type=", (Genode::Hex)type, - " protocol=", (Genode::Hex)protocol, " not supported"); + error(__func__, + ": socket with type=", (Hex)type, + " protocol=", (Hex)protocol, " not supported"); return Errno(EAFNOSUPPORT); } @@ -959,21 +990,21 @@ extern "C" int socket_fs_socket(int domain, int type, int protocol) path.append("/new_socket"); int handle_fd = ::open(path.base(), O_RDONLY); if (handle_fd < 0) { - Genode::error("failed to open new socket at ", path); + error("failed to open new socket at ", path); return Errno(EACCES); } - context = new (&global_allocator) + Libc::Allocator alloc { }; + context = new (alloc) Socket_fs::Context(proto, handle_fd); } catch (New_socket_failed) { return Errno(EACCES); } - Libc::File_descriptor *fd = - Libc::file_descriptor_allocator()->alloc(&plugin(), context); + File_descriptor *fd = file_descriptor_allocator()->alloc(&plugin(), context); return fd->libc_fd; } -static int read_ifaddr_file(sockaddr_in &sockaddr, Absolute_path const &path) +static int read_ifaddr_file(sockaddr_in &sockaddr, Socket_fs::Absolute_path const &path) { Host_string address; Port_string service; @@ -996,17 +1027,16 @@ static int read_ifaddr_file(sockaddr_in &sockaddr, Absolute_path const &path) extern "C" int getifaddrs(struct ifaddrs **ifap) { - static Genode::Lock lock; - Genode::Lock::Guard guard(lock); - - // TODO: dual-stack / multi-homing + static Lock lock; + Lock::Guard guard(lock); static sockaddr_in address; static sockaddr_in netmask { 0 }; static sockaddr_in broadcast { 0 }; + static char name[1] { }; static ifaddrs ifaddr { - .ifa_name = "", + .ifa_name = name, .ifa_flags = IFF_UP, .ifa_addr = (sockaddr*)&address, .ifa_netmask = (sockaddr*)&netmask, @@ -1015,7 +1045,9 @@ extern "C" int getifaddrs(struct ifaddrs **ifap) *ifap = &ifaddr; - Absolute_path const root(Libc::config_socket()); + using Socket_fs::Absolute_path; + + Absolute_path const root(config_socket()); if (read_ifaddr_file(address, Absolute_path("address", root.base()))) return -1; @@ -1032,7 +1064,7 @@ extern "C" void freeifaddrs(struct ifaddrs *) { } ** File-plugin operations ** ****************************/ -int Socket_fs::Plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) +int Socket_fs::Plugin::fcntl(File_descriptor *fd, int cmd, long arg) { Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); if (!context) return Errno(EBADF); @@ -1044,12 +1076,12 @@ int Socket_fs::Plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) context->fd_flags(arg); return 0; default: - Genode::error(__func__, " command ", cmd, " not supported on sockets"); + error(__func__, " command ", cmd, " not supported on sockets"); return Errno(EINVAL); } } -ssize_t Socket_fs::Plugin::read(Libc::File_descriptor *fd, void *buf, ::size_t count) +ssize_t Socket_fs::Plugin::read(File_descriptor *fd, void *buf, ::size_t count) { ssize_t const ret = do_recvfrom(fd, buf, count, 0, nullptr, nullptr); if (ret != -1) return ret; @@ -1061,7 +1093,7 @@ ssize_t Socket_fs::Plugin::read(Libc::File_descriptor *fd, void *buf, ::size_t c } -ssize_t Socket_fs::Plugin::write(Libc::File_descriptor *fd, const void *buf, ::size_t count) +ssize_t Socket_fs::Plugin::write(File_descriptor *fd, const void *buf, ::size_t count) { ssize_t const ret = do_sendto(fd, buf, count, 0, nullptr, 0); @@ -1074,8 +1106,7 @@ ssize_t Socket_fs::Plugin::write(Libc::File_descriptor *fd, const void *buf, ::s } -bool Socket_fs::Plugin::poll(Libc::File_descriptor &fdo, - struct pollfd &pfd) +bool Socket_fs::Plugin::poll(File_descriptor &fdo, struct pollfd &pfd) { if (fdo.plugin != this) return false; Socket_fs::Context *context { nullptr }; @@ -1118,8 +1149,7 @@ bool Socket_fs::Plugin::supports_select(int nfds, for (int fd = 0; fd < nfds; ++fd) { if (FD_ISSET(fd, readfds) || FD_ISSET(fd, writefds) || FD_ISSET(fd, exceptfds)) { - Libc::File_descriptor *fdo = - Libc::file_descriptor_allocator()->find_by_libc_fd(fd); + File_descriptor *fdo = file_descriptor_allocator()->find_by_libc_fd(fd); if (fdo && (fdo->plugin == this)) return true; @@ -1147,8 +1177,7 @@ int Socket_fs::Plugin::select(int nfds, for (int fd = 0; fd < nfds; ++fd) { - Libc::File_descriptor *fdo = - Libc::file_descriptor_allocator()->find_by_libc_fd(fd); + File_descriptor *fdo = file_descriptor_allocator()->find_by_libc_fd(fd); /* handle only fds that belong to this plugin */ if (!fdo || (fdo->plugin != this)) @@ -1183,13 +1212,14 @@ int Socket_fs::Plugin::select(int nfds, } -int Socket_fs::Plugin::close(Libc::File_descriptor *fd) +int Socket_fs::Plugin::close(File_descriptor *fd) { Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context); if (!context) return Errno(EBADF); - Genode::destroy(&global_allocator, context); - Libc::file_descriptor_allocator()->free(fd); + Libc::Allocator alloc { }; + destroy(alloc, context); + file_descriptor_allocator()->free(fd); /* * the socket is freed when the initial handle @@ -1200,7 +1230,7 @@ int Socket_fs::Plugin::close(Libc::File_descriptor *fd) } -int Socket_fs::Plugin::ioctl(Libc::File_descriptor *, int request, char*) +int Socket_fs::Plugin::ioctl(File_descriptor *, int request, char*) { if (request == FIONREAD) { /* @@ -1209,20 +1239,20 @@ int Socket_fs::Plugin::ioctl(Libc::File_descriptor *, int request, char*) */ static bool print_fionread_error_message = true; if (print_fionread_error_message) { - Genode::error(__func__, " request FIONREAD not supported on sockets" - " (this message will not be shown again)"); + error(__func__, " request FIONREAD not supported on sockets" + " (this message will not be shown again)"); print_fionread_error_message = false; } return -1; } - Genode::error(__func__, " request ", request, " not supported on sockets"); + error(__func__, " request ", request, " not supported on sockets"); return -1; } -Plugin & Socket_fs::plugin() +Libc::Socket_fs::Plugin &Libc::Socket_fs::plugin() { - static Plugin inst; + static Socket_fs::Plugin inst; return inst; } diff --git a/repos/libports/src/lib/libc/socket_operations.cc b/repos/libports/src/lib/libc/socket_operations.cc index d2647b7f0..4803c12ad 100644 --- a/repos/libports/src/lib/libc/socket_operations.cc +++ b/repos/libports/src/lib/libc/socket_operations.cc @@ -26,8 +26,8 @@ extern "C" { } /* libc-internal includes */ -#include "libc_file.h" -#include "socket_fs_plugin.h" +#include <internal/file.h> +#include <internal/socket_fs_plugin.h> using namespace Libc; @@ -49,7 +49,7 @@ namespace Libc { extern char const *config_socket(); } extern "C" int getpeername(int libc_fd, sockaddr *addr, socklen_t *addrlen) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_getpeername(libc_fd, addr, addrlen); FD_FUNC_WRAPPER(getpeername, libc_fd, addr, addrlen); @@ -62,7 +62,7 @@ int _getpeername(int libc_fd, sockaddr *addr, socklen_t *addrlen); extern "C" int getsockname(int libc_fd, sockaddr *addr, socklen_t *addrlen) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_getsockname(libc_fd, addr, addrlen); FD_FUNC_WRAPPER(getsockname, libc_fd, addr, addrlen); @@ -79,7 +79,7 @@ int _getsockname(int libc_fd, sockaddr *addr, socklen_t *addrlen); __SYS_(int, accept, (int libc_fd, sockaddr *addr, socklen_t *addrlen), { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_accept(libc_fd, addr, addrlen); File_descriptor *ret_fd; @@ -96,7 +96,7 @@ __SYS_(int, accept4, (int libc_fd, struct sockaddr *addr, socklen_t *addrlen, in extern "C" int bind(int libc_fd, sockaddr const *addr, socklen_t addrlen) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_bind(libc_fd, addr, addrlen); FD_FUNC_WRAPPER(bind, libc_fd, addr, addrlen); @@ -109,7 +109,7 @@ int _bind(int libc_fd, sockaddr const *addr, socklen_t addrlen); __SYS_(int, connect, (int libc_fd, sockaddr const *addr, socklen_t addrlen), { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_connect(libc_fd, addr, addrlen); FD_FUNC_WRAPPER(connect, libc_fd, addr, addrlen); @@ -118,7 +118,7 @@ __SYS_(int, connect, (int libc_fd, sockaddr const *addr, socklen_t addrlen), extern "C" int listen(int libc_fd, int backlog) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_listen(libc_fd, backlog); FD_FUNC_WRAPPER(listen, libc_fd, backlog); @@ -128,7 +128,7 @@ extern "C" int listen(int libc_fd, int backlog) __SYS_(ssize_t, recvfrom, (int libc_fd, void *buf, ::size_t len, int flags, sockaddr *src_addr, socklen_t *src_addrlen), { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_recvfrom(libc_fd, buf, len, flags, src_addr, src_addrlen); FD_FUNC_WRAPPER(recvfrom, libc_fd, buf, len, flags, src_addr, src_addrlen); @@ -137,7 +137,7 @@ __SYS_(ssize_t, recvfrom, (int libc_fd, void *buf, ::size_t len, int flags, __SYS_(ssize_t, recv, (int libc_fd, void *buf, ::size_t len, int flags), { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_recv(libc_fd, buf, len, flags); FD_FUNC_WRAPPER(recv, libc_fd, buf, len, flags); @@ -146,7 +146,7 @@ __SYS_(ssize_t, recv, (int libc_fd, void *buf, ::size_t len, int flags), __SYS_(ssize_t, recvmsg, (int libc_fd, msghdr *msg, int flags), { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_recvmsg(libc_fd, msg, flags); FD_FUNC_WRAPPER(recvmsg, libc_fd, msg, flags); @@ -156,7 +156,7 @@ __SYS_(ssize_t, recvmsg, (int libc_fd, msghdr *msg, int flags), __SYS_(ssize_t, sendto, (int libc_fd, void const *buf, ::size_t len, int flags, sockaddr const *dest_addr, socklen_t dest_addrlen), { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_sendto(libc_fd, buf, len, flags, dest_addr, dest_addrlen); FD_FUNC_WRAPPER(sendto, libc_fd, buf, len, flags, dest_addr, dest_addrlen); @@ -165,7 +165,7 @@ __SYS_(ssize_t, sendto, (int libc_fd, void const *buf, ::size_t len, int flags, extern "C" ssize_t send(int libc_fd, void const *buf, ::size_t len, int flags) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_send(libc_fd, buf, len, flags); FD_FUNC_WRAPPER(send, libc_fd, buf, len, flags); @@ -175,7 +175,7 @@ extern "C" ssize_t send(int libc_fd, void const *buf, ::size_t len, int flags) extern "C" int getsockopt(int libc_fd, int level, int optname, void *optval, socklen_t *optlen) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_getsockopt(libc_fd, level, optname, optval, optlen); FD_FUNC_WRAPPER(getsockopt, libc_fd, level, optname, optval, optlen); @@ -190,7 +190,7 @@ int _getsockopt(int libc_fd, int level, int optname, extern "C" int setsockopt(int libc_fd, int level, int optname, void const *optval, socklen_t optlen) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_setsockopt(libc_fd, level, optname, optval, optlen); FD_FUNC_WRAPPER(setsockopt, libc_fd, level, optname, optval, optlen); @@ -204,7 +204,7 @@ int _setsockopt(int libc_fd, int level, int optname, extern "C" int shutdown(int libc_fd, int how) { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_shutdown(libc_fd, how); FD_FUNC_WRAPPER(shutdown, libc_fd, how); @@ -212,7 +212,7 @@ extern "C" int shutdown(int libc_fd, int how) __SYS_(int, socket, (int domain, int type, int protocol), { - if (*Libc::config_socket()) + if (*config_socket()) return socket_fs_socket(domain, type, protocol); Plugin *plugin; @@ -221,13 +221,13 @@ __SYS_(int, socket, (int domain, int type, int protocol), plugin = plugin_registry()->get_plugin_for_socket(domain, type, protocol); if (!plugin) { - Genode::error("no plugin found for socket()"); + error("no plugin found for socket()"); return -1; } new_fdo = plugin->socket(domain, type, protocol); if (!new_fdo) { - Genode::error("plugin()->socket() failed"); + error("plugin()->socket() failed"); return -1; } diff --git a/repos/libports/src/lib/libc/include/spec/arm/internal/call_func.h b/repos/libports/src/lib/libc/spec/arm/internal/call_func.h similarity index 100% rename from repos/libports/src/lib/libc/include/spec/arm/internal/call_func.h rename to repos/libports/src/lib/libc/spec/arm/internal/call_func.h diff --git a/repos/libports/src/lib/libc/include/spec/arm_64/internal/call_func.h b/repos/libports/src/lib/libc/spec/arm_64/internal/call_func.h similarity index 100% rename from repos/libports/src/lib/libc/include/spec/arm_64/internal/call_func.h rename to repos/libports/src/lib/libc/spec/arm_64/internal/call_func.h diff --git a/repos/libports/src/lib/libc/include/spec/x86_32/internal/call_func.h b/repos/libports/src/lib/libc/spec/x86_32/internal/call_func.h similarity index 100% rename from repos/libports/src/lib/libc/include/spec/x86_32/internal/call_func.h rename to repos/libports/src/lib/libc/spec/x86_32/internal/call_func.h diff --git a/repos/libports/src/lib/libc/include/spec/x86_64/internal/call_func.h b/repos/libports/src/lib/libc/spec/x86_64/internal/call_func.h similarity index 100% rename from repos/libports/src/lib/libc/include/spec/x86_64/internal/call_func.h rename to repos/libports/src/lib/libc/spec/x86_64/internal/call_func.h diff --git a/repos/libports/src/lib/libc/sysctl.cc b/repos/libports/src/lib/libc/sysctl.cc index 81769400e..fafd86872 100644 --- a/repos/libports/src/lib/libc/sysctl.cc +++ b/repos/libports/src/lib/libc/sysctl.cc @@ -19,16 +19,18 @@ #include <libc-plugin/plugin.h> #include <libc-plugin/fd_alloc.h> -/* Libc includes */ +/* libc includes */ #include <sys/sysctl.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> -#include "libc_errno.h" -#include "libc_init.h" +/* libc-internal includes */ +#include <internal/errno.h> +#include <internal/init.h> +using namespace Libc; enum { PAGESIZE = 4096 }; @@ -54,8 +56,8 @@ extern "C" long sysconf(int name) case _SC_PHYS_PAGES: return _global_env->pd().ram_quota().value / PAGESIZE; default: - Genode::warning(__func__, "(", name, ") not implemented"); - return Libc::Errno(EINVAL); + warning(__func__, "(", name, ") not implemented"); + return Errno(EINVAL); } } @@ -66,9 +68,9 @@ extern "C" int __sysctl(const int *name, u_int namelen, { /* read only */ if (!oldp) /* check for write attempt */ - return Libc::Errno(newp ? EPERM : EINVAL); + return Errno(newp ? EPERM : EINVAL); - if (namelen != 2) return Libc::Errno(ENOENT); + if (namelen != 2) return Errno(ENOENT); char *buf = (char*)oldp; int index_a = name[0]; @@ -92,7 +94,7 @@ extern "C" int __sysctl(const int *name, u_int namelen, *(Genode::int64_t*)oldp = _global_env->pd().ram_quota().value; break; default: - return Libc::Errno(EINVAL); + return Errno(EINVAL); } return 0; @@ -162,6 +164,6 @@ extern "C" int __sysctl(const int *name, u_int namelen, } } - Genode::warning("missing sysctl for [", index_a, "][", index_b, "]"); - return Libc::Errno(ENOENT); + warning("missing sysctl for [", index_a, "][", index_b, "]"); + return Errno(ENOENT); } diff --git a/repos/libports/src/lib/libc/task.cc b/repos/libports/src/lib/libc/task.cc deleted file mode 100644 index bf176682a..000000000 --- a/repos/libports/src/lib/libc/task.cc +++ /dev/null @@ -1,1359 +0,0 @@ -/* - * \brief Libc kernel for main and pthreads user contexts - * \author Christian Helmuth - * \author Emery Hemingway - * \date 2016-01-22 - */ - -/* - * Copyright (C) 2016-2019 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 <base/component.h> -#include <base/log.h> -#include <base/thread.h> -#include <base/rpc_server.h> -#include <base/rpc_client.h> -#include <base/heap.h> -#include <base/attached_rom_dataspace.h> -#include <vfs/simple_env.h> -#include <timer_session/connection.h> - -/* libc includes */ -#include <libc/component.h> -#include <libc/select.h> -#include <libc-plugin/plugin_registry.h> - -/* libc-internal includes */ -#include <internal/call_func.h> -#include <base/internal/unmanaged_singleton.h> -#include <clone_session.h> -#include "vfs_plugin.h" -#include "libc_init.h" -#include "task.h" - -extern char **environ; - -namespace Libc { - class Env_implementation; - class Cloned_malloc_heap_range; - class Malloc_ram_allocator; - class Kernel; - class Pthreads; - class Timer; - class Timer_accessor; - class Timeout; - class Timeout_handler; - - using Genode::Microseconds; -} - - -class Libc::Env_implementation : public Libc::Env, public Config_accessor -{ - private: - - Genode::Env &_env; - Genode::Xml_node const _config; - - Genode::Xml_node _vfs_config() - { - try { return _config.sub_node("vfs"); } - catch (Genode::Xml_node::Nonexistent_sub_node) { } - try { - Genode::Xml_node node = - _config.sub_node("libc").sub_node("vfs"); - Genode::warning("'<config> <libc> <vfs/>' is deprecated, " - "please move to '<config> <vfs/>'"); - return node; - } - catch (Genode::Xml_node::Nonexistent_sub_node) { } - - return Genode::Xml_node("<vfs/>"); - } - - Genode::Xml_node _libc_config() - { - try { return _config.sub_node("libc"); } - catch (Genode::Xml_node::Nonexistent_sub_node) { } - - return Genode::Xml_node("<libc/>"); - } - - Vfs::Simple_env _vfs_env; - - Genode::Xml_node _config_xml() const override { - return _config; }; - - public: - - Env_implementation(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_node config) - : _env(env), _config(config), _vfs_env(_env, alloc, _vfs_config()) { } - - - /************************* - ** Libc::Env interface ** - *************************/ - - Vfs::File_system &vfs() override { - return _vfs_env.root_dir(); } - - Genode::Xml_node libc_config() override { - return _libc_config(); } - - - /************************************* - ** Libc::Config_accessor interface ** - *************************************/ - - Xml_node config() const override { return _config; } - - - /*************************** - ** Genode::Env interface ** - ***************************/ - - Parent &parent() override { return _env.parent(); } - Cpu_session &cpu() override { return _env.cpu(); } - Region_map &rm() override { return _env.rm(); } - Pd_session &pd() override { return _env.pd(); } - Entrypoint &ep() override { return _env.ep(); } - - Cpu_session_capability cpu_session_cap() override { - return _env.cpu_session_cap(); } - - Pd_session_capability pd_session_cap() override { - return _env.pd_session_cap(); } - - Id_space<Parent::Client> &id_space() override { - return _env.id_space(); } - - Session_capability session(Parent::Service_name const &name, - Parent::Client::Id id, - Parent::Session_args const &args, - Affinity const &aff) override { - return _env.session(name, id, args, aff); } - - void upgrade(Parent::Client::Id id, - Parent::Upgrade_args const &args) override { - return _env.upgrade(id, args); } - - void close(Parent::Client::Id id) override { - return _env.close(id); } - - /* already done by the libc */ - void exec_static_constructors() override { } - - void reinit(Native_capability::Raw raw) override { - _env.reinit(raw); } - - void reinit_main_thread(Capability<Region_map> &stack_area_rm) override { - _env.reinit_main_thread(stack_area_rm); } -}; - - -struct Libc::Timer -{ - ::Timer::Connection _timer; - - Timer(Genode::Env &env) : _timer(env) { } - - Genode::Duration curr_time() - { - return _timer.curr_time(); - } - - static Microseconds microseconds(Genode::uint64_t timeout_ms) - { - return Microseconds(1000*timeout_ms); - } - - static Genode::uint64_t max_timeout() - { - return ~0UL/1000; - } -}; - - -/** - * Interface for obtaining the libc-global timer instance - * - * The 'Timer' is instantiated on demand whenever the 'Timer_accessor::timer' - * method is first called. This way, libc-using components do not depend of a - * timer connection unless they actually use time-related functionality. - */ -struct Libc::Timer_accessor -{ - virtual Timer &timer() = 0; -}; - - -struct Libc::Timeout_handler -{ - virtual void handle_timeout() = 0; -}; - - -/* - * TODO curr_time wrapping - */ -struct Libc::Timeout -{ - Libc::Timer_accessor &_timer_accessor; - Timeout_handler &_handler; - ::Timer::One_shot_timeout<Timeout> _timeout; - - bool _expired = true; - Genode::uint64_t _absolute_timeout_ms = 0; - - void _handle(Duration now) - { - _expired = true; - _absolute_timeout_ms = 0; - _handler.handle_timeout(); - } - - Timeout(Timer_accessor &timer_accessor, Timeout_handler &handler) - : - _timer_accessor(timer_accessor), - _handler(handler), - _timeout(_timer_accessor.timer()._timer, *this, &Timeout::_handle) - { } - - void start(Genode::uint64_t timeout_ms) - { - Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms(); - - _expired = false; - _absolute_timeout_ms = now.value + timeout_ms; - - _timeout.schedule(_timer_accessor.timer().microseconds(timeout_ms)); - } - - Genode::uint64_t duration_left() const - { - Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms(); - - if (_expired || _absolute_timeout_ms < now.value) - return 0; - - return _absolute_timeout_ms - now.value; - } -}; - - -struct Libc::Pthreads -{ - struct Pthread : Timeout_handler - { - Genode::Lock lock { Genode::Lock::LOCKED }; - Pthread *next { nullptr }; - - Timer_accessor &_timer_accessor; - Constructible<Timeout> _timeout; - - void _construct_timeout_once() - { - if (!_timeout.constructed()) - _timeout.construct(_timer_accessor, *this); - } - - Pthread(Timer_accessor &timer_accessor, Genode::uint64_t timeout_ms) - : _timer_accessor(timer_accessor) - { - if (timeout_ms > 0) { - _construct_timeout_once(); - _timeout->start(timeout_ms); - } - } - - Genode::uint64_t duration_left() - { - _construct_timeout_once(); - return _timeout->duration_left(); - } - - void handle_timeout() override - { - lock.unlock(); - } - }; - - Genode::Lock mutex; - Pthread *pthreads = nullptr; - Timer_accessor &timer_accessor; - - - Pthreads(Timer_accessor &timer_accessor) - : timer_accessor(timer_accessor) { } - - void resume_all() - { - Genode::Lock::Guard g(mutex); - - for (Pthread *p = pthreads; p; p = p->next) - p->lock.unlock(); - } - - Genode::uint64_t suspend_myself(Suspend_functor & check, Genode::uint64_t timeout_ms) - { - Pthread myself { timer_accessor, timeout_ms }; - { - Genode::Lock::Guard g(mutex); - - myself.next = pthreads; - pthreads = &myself; - } - - if (check.suspend()) - myself.lock.lock(); - - { - Genode::Lock::Guard g(mutex); - - /* address of pointer to next pthread allows to change the head */ - for (Pthread **next = &pthreads; *next; next = &(*next)->next) { - if (*next == &myself) { - *next = myself.next; - break; - } - } - } - - return timeout_ms > 0 ? myself.duration_left() : 0; - } -}; - - -extern void (*libc_select_notify)(); - - -/* internal utility */ -static void resumed_callback(); -static void suspended_callback(); - - -struct Libc::Cloned_malloc_heap_range -{ - Genode::Ram_allocator &ram; - Genode::Region_map &rm; - - Genode::Ram_dataspace_capability ds; - - size_t const size; - addr_t const local_addr; - - Cloned_malloc_heap_range(Genode::Ram_allocator &ram, Genode::Region_map &rm, - void *start, size_t size) - try : - ram(ram), rm(rm), ds(ram.alloc(size)), size(size), - local_addr(rm.attach_at(ds, (addr_t)start)) - { } - catch (Region_map::Region_conflict) { - error("could not clone heap region ", Hex_range(local_addr, size)); - throw; - } - - void import_content(Clone_connection &clone_connection) - { - clone_connection.memory_content((void *)local_addr, size); - } - - virtual ~Cloned_malloc_heap_range() - { - rm.detach(local_addr); - ram.free(ds); - } -}; - - -/* - * Utility for tracking the allocation of dataspaces by the malloc heap - */ -struct Libc::Malloc_ram_allocator : Genode::Ram_allocator -{ - Genode::Allocator &_md_alloc; - Genode::Ram_allocator &_ram; - - struct Dataspace - { - Genode::Ram_dataspace_capability cap; - Dataspace(Genode::Ram_dataspace_capability cap) : cap(cap) { } - virtual ~Dataspace() { } - }; - - Genode::Registry<Genode::Registered<Dataspace> > _dataspaces { }; - - void _release(Genode::Registered<Dataspace> &ds) - { - _ram.free(ds.cap); - destroy(_md_alloc, &ds); - } - - Malloc_ram_allocator(Allocator &md_alloc, Ram_allocator &ram) - : _md_alloc(md_alloc), _ram(ram) { } - - ~Malloc_ram_allocator() - { - _dataspaces.for_each([&] (Registered<Dataspace> &ds) { - _release(ds); }); - } - - Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override - { - Ram_dataspace_capability cap = _ram.alloc(size, cached); - new (_md_alloc) Registered<Dataspace>(_dataspaces, cap); - return cap; - } - - void free(Ram_dataspace_capability ds_cap) override - { - _dataspaces.for_each([&] (Registered<Dataspace> &ds) { - if (ds_cap == ds.cap) - _release(ds); }); - } - - size_t dataspace_size(Ram_dataspace_capability ds_cap) const override - { - return _ram.dataspace_size(ds_cap); - } -}; - - -/** - * Libc "kernel" - * - * This class represents the "kernel" of the libc-based application - * Blocking and deblocking happens here on libc functions like read() or - * select(). This combines blocking of the VFS backend and other signal sources - * (e.g., timers). The libc task runs on the component thread and allocates a - * secondary stack for the application task. Context switching uses - * setjmp/longjmp. - */ -struct Libc::Kernel final : Vfs::Io_response_handler, - Genode::Entrypoint::Io_progress_handler, - Reset_malloc_heap -{ - private: - - Genode::Env &_env; - - /** - * Allocator for libc-internal data - * - * Not mirrored to forked processes. Preserved across 'execve' calls. - */ - Genode::Allocator &_heap; - - /** - * Allocator for application-owned data - * - * Mirrored to forked processes. Not preserved across 'execve' calls. - */ - Genode::Reconstructible<Malloc_ram_allocator> _malloc_ram { _heap, _env.ram() }; - - Genode::Constructible<Heap> _malloc_heap { }; - - Genode::Registry<Registered<Cloned_malloc_heap_range> > _cloned_heap_ranges { }; - - /** - * Reset_malloc_heap interface used by execve - */ - void reset_malloc_heap() override; - - Genode::Attached_rom_dataspace _config_ds { _env, "config" }; - Xml_node const _config = _config_ds.xml(); - - bool const _cloned = _config.has_sub_node("libc") && - _config.sub_node("libc").attribute_value("cloned", false); - - void _init_malloc_heap() - { - if (_cloned) - return; - - _malloc_heap.construct(*_malloc_ram, _env.rm()); - init_malloc(*_malloc_heap); - } - - bool const _malloc_heap_initialized = (_init_malloc_heap(), true); - - Env_implementation _libc_env { _env, _heap, _config }; - - pid_t const _pid = _libc_env.libc_config().attribute_value("pid", 0U); - - Vfs_plugin _vfs { _libc_env, _heap, *this }; - - Genode::Reconstructible<Genode::Io_signal_handler<Kernel>> _resume_main_handler { - _env.ep(), *this, &Kernel::_resume_main }; - - jmp_buf _kernel_context; - jmp_buf _user_context; - bool _valid_user_context = false; - bool _dispatch_pending_io_signals = false; - - /* io_progress_handler marker */ - bool _io_ready { false }; - - Genode::Thread &_myself { *Genode::Thread::myself() }; - - addr_t _kernel_stack = Thread::mystack().top; - - size_t _user_stack_size() - { - size_t size = Component::stack_size(); - if (!_cloned) - return size; - - _libc_env.libc_config().with_sub_node("stack", [&] (Xml_node stack) { - size = stack.attribute_value("size", 0UL); }); - - return size; - } - - void *_user_stack = { - _myself.alloc_secondary_stack(_myself.name().string(), - _user_stack_size()) }; - - void (*_original_suspended_callback)() = nullptr; - - enum State { KERNEL, USER }; - - State _state = KERNEL; - - Application_code *_nested_app_code = nullptr; - - Application_code *_app_code = nullptr; - bool _app_returned = false; - - bool _resume_main_once = false; - bool _suspend_scheduled = false; - - Select_handler_base *_scheduled_select_handler = nullptr; - - Kernel_routine *_kernel_routine = nullptr; - - void _resume_main() { _resume_main_once = true; } - - struct Timer_accessor : Libc::Timer_accessor - { - Genode::Env &_env; - - /* - * The '_timer' is constructed by whatever thread (main thread - * of pthread) that uses a time-related function first. Hence, - * the construction must be protected by a lock. - */ - Genode::Lock _lock; - - Genode::Constructible<Timer> _timer; - - Timer_accessor(Genode::Env &env) : _env(env) { } - - Timer &timer() override - { - Lock::Guard guard(_lock); - - if (!_timer.constructed()) - _timer.construct(_env); - - return *_timer; - } - }; - - Timer_accessor _timer_accessor { _env }; - - struct Main_timeout : Timeout_handler - { - Timer_accessor &_timer_accessor; - Constructible<Timeout> _timeout; - Kernel &_kernel; - - void _construct_timeout_once() - { - if (!_timeout.constructed()) - _timeout.construct(_timer_accessor, *this); - } - - Main_timeout(Timer_accessor &timer_accessor, Kernel &kernel) - : _timer_accessor(timer_accessor), _kernel(kernel) - { } - - void timeout(Genode::uint64_t timeout_ms) - { - _construct_timeout_once(); - _timeout->start(timeout_ms); - } - - Genode::uint64_t duration_left() - { - _construct_timeout_once(); - return _timeout->duration_left(); - } - - void handle_timeout() override - { - _kernel._resume_main(); - } - }; - - Main_timeout _main_timeout { _timer_accessor, *this }; - - Pthreads _pthreads { _timer_accessor }; - - struct Resumer - { - GENODE_RPC(Rpc_resume, void, resume); - GENODE_RPC_INTERFACE(Rpc_resume); - }; - - struct Resumer_component : Rpc_object<Resumer, Resumer_component> - { - Kernel &_kernel; - - Resumer_component(Kernel &kernel) : _kernel(kernel) { } - - void resume() { _kernel.run_after_resume(); } - }; - - /** - * Trampoline to application (user) code - * - * This function is called by the main thread. - */ - static void _user_entry(Libc::Kernel *kernel) - { - struct Check : Suspend_functor { - bool suspend() override { return true; } - } check; - - kernel->_app_code->execute(); - kernel->_app_returned = true; - kernel->_suspend_main(check, 0); - } - - bool _main_context() const { return &_myself == Genode::Thread::myself(); } - - /** - * Utility to switch main context to kernel - * - * User context must be saved explicitly before this function is called - * to enable _switch_to_user() later. - */ - void _switch_to_kernel() - { - _state = KERNEL; - _longjmp(_kernel_context, 1); - } - - /** - * Utility to switch main context to user - * - * Kernel context must be saved explicitly before this function is called - * to enable _switch_to_kernel() later. - */ - void _switch_to_user() - { - if (!_valid_user_context) - Genode::error("switching to invalid user context"); - - _resume_main_once = false; - _state = USER; - _longjmp(_user_context, 1); - } - - Genode::uint64_t _suspend_main(Suspend_functor &check, - Genode::uint64_t timeout_ms) - { - /* check that we're not running on libc kernel context */ - if (Thread::mystack().top == _kernel_stack) { - error("libc suspend() called from non-user context (", - __builtin_return_address(0), ") - aborting"); - exit(1); - } - - if (!check.suspend() && !_kernel_routine) - return 0; - - if (timeout_ms > 0) - _main_timeout.timeout(timeout_ms); - - if (!_setjmp(_user_context)) { - _valid_user_context = true; - _switch_to_kernel(); - } else { - _valid_user_context = false; - } - - /* - * During the suspension of the application code a nested - * Libc::with_libc() call took place, which will be executed - * before returning to the first Libc::with_libc() call. - */ - if (_nested_app_code) { - - /* - * We have to explicitly set the user context back to true - * because we are borrowing it to execute our nested application - * code. - */ - _valid_user_context = true; - - _nested_app_code->execute(); - _nested_app_code = nullptr; - _longjmp(_kernel_context, 1); - } - - return timeout_ms > 0 ? _main_timeout.duration_left() : 0; - } - - void _init_file_descriptors(); - - void _clone_state_from_parent(); - - public: - - Kernel(Genode::Env &env, Genode::Allocator &heap) - : - _env(env), _heap(heap) - { - _env.ep().register_io_progress_handler(*this); - - if (_cloned) - _clone_state_from_parent(); - - Libc::init_fork(_env, _libc_env, _heap, *_malloc_heap, _pid); - Libc::init_execve(_env, _heap, _user_stack, *this); - - _init_file_descriptors(); - } - - ~Kernel() { Genode::error(__PRETTY_FUNCTION__, " should not be executed!"); } - - Libc::Env & libc_env() { return _libc_env; } - - /** - * Setup kernel context and run libc application main context - * - * This function is called by the component thread on with_libc(). - */ - void run(Libc::Application_code &app_code) - { - if (!_main_context() || _state != KERNEL) { - Genode::error(__PRETTY_FUNCTION__, " called from non-kernel context"); - return; - } - - _resume_main_once = false; - _app_returned = false; - _app_code = &app_code; - - /* save continuation of libc kernel (incl. current stack) */ - if (!_setjmp(_kernel_context)) { - /* _setjmp() returned directly -> switch to user stack and call application code */ - - if (_cloned) { - _switch_to_user(); - } else { - _state = USER; - call_func(_user_stack, (void *)_user_entry, (void *)this); - } - - /* never reached */ - } - - /* _setjmp() returned after _longjmp() - user context suspended */ - - while ((!_app_returned) && (!_suspend_scheduled)) { - - if (_kernel_routine) { - Kernel_routine &routine = *_kernel_routine; - - /* the 'kernel_routine' may install another kernel routine */ - _kernel_routine = nullptr; - routine.execute_in_kernel(); - if (!_kernel_routine) - _switch_to_user(); - } - - if (_dispatch_pending_io_signals) { - /* dispatch pending signals but don't block */ - while (_env.ep().dispatch_pending_io_signal()) ; - } else { - /* block for signals */ - _env.ep().wait_and_dispatch_one_io_signal(); - } - - if (!_kernel_routine && _resume_main_once && !_setjmp(_kernel_context)) - _switch_to_user(); - } - - _suspend_scheduled = false; - } - - /* - * Run libc application main context after suspend and resume - */ - void run_after_resume() - { - if (!_setjmp(_kernel_context)) - _switch_to_user(); - - while ((!_app_returned) && (!_suspend_scheduled)) { - _env.ep().wait_and_dispatch_one_io_signal(); - if (_resume_main_once && !_setjmp(_kernel_context)) - _switch_to_user(); - } - - _suspend_scheduled = false; - } - - /** - * Resume all contexts (main and pthreads) - */ - void resume_all() - { - if (_app_returned) { - if (_scheduled_select_handler) - _scheduled_select_handler->dispatch_select(); - } else { - if (_main_context()) - _resume_main(); - else - Genode::Signal_transmitter(*_resume_main_handler).submit(); - } - - _pthreads.resume_all(); - } - - /** - * Suspend this context (main or pthread) - */ - Genode::uint64_t suspend(Suspend_functor &check, Genode::uint64_t timeout_ms) - { - if (timeout_ms > 0 - && timeout_ms > _timer_accessor.timer().max_timeout()) { - Genode::warning("libc: limiting exceeding timeout of ", - timeout_ms, " ms to maximum of ", - _timer_accessor.timer().max_timeout(), " ms"); - - timeout_ms = min(timeout_ms, _timer_accessor.timer().max_timeout()); - } - - return _main_context() ? _suspend_main(check, timeout_ms) - : _pthreads.suspend_myself(check, timeout_ms); - } - - void dispatch_pending_io_signals() - { - if (!_main_context()) return; - - if (!_setjmp(_user_context)) { - _valid_user_context = true; - _dispatch_pending_io_signals = true; - _resume_main_once = true; /* afterwards resume main */ - _switch_to_kernel(); - } else { - _valid_user_context = false; - _dispatch_pending_io_signals = false; - } - } - - Genode::Duration current_time() - { - return _timer_accessor.timer().curr_time(); - } - - /** - * Called from the main context (by fork) - */ - void schedule_suspend(void(*original_suspended_callback) ()) - { - if (_state != USER) { - Genode::error(__PRETTY_FUNCTION__, " called from non-user context"); - return; - } - - /* - * We hook into suspend-resume callback chain to destruct and - * reconstruct parts of the kernel from the context of the initial - * thread, i.e., without holding any object locks. - */ - _original_suspended_callback = original_suspended_callback; - _env.ep().schedule_suspend(suspended_callback, resumed_callback); - - if (!_setjmp(_user_context)) { - _valid_user_context = true; - _suspend_scheduled = true; - _switch_to_kernel(); - } else { - _valid_user_context = false; - } - } - - void schedule_select(Select_handler_base *h) - { - _scheduled_select_handler = h; - } - - /** - * Called from the context of the initial thread (on fork) - */ - void entrypoint_suspended() - { - _resume_main_handler.destruct(); - - _original_suspended_callback(); - } - - /** - * Called from the context of the initial thread (after fork) - */ - void entrypoint_resumed() - { - _resume_main_handler.construct(_env.ep(), *this, &Kernel::_resume_main); - - Resumer_component resumer { *this }; - - Capability<Resumer> resumer_cap = - _env.ep().rpc_ep().manage(&resumer); - - resumer_cap.call<Resumer::Rpc_resume>(); - - _env.ep().rpc_ep().dissolve(&resumer); - } - - /** - * Return if main is currently suspended - */ - bool main_suspended() { return _state == KERNEL; } - - /** - * Public alias for _main_context() - */ - bool main_context() const { return _main_context(); } - - /** - * Execute application code while already executing in run() - */ - void nested_execution(Libc::Application_code &app_code) - { - _nested_app_code = &app_code; - - if (!_setjmp(_kernel_context)) { - _switch_to_user(); - } - } - - /** - * Alloc new watch handler for given path - */ - Vfs::Vfs_watch_handle *alloc_watch_handle(char const *path) - { - Vfs::Vfs_watch_handle *watch_handle { nullptr }; - typedef Vfs::Directory_service::Watch_result Result; - return _libc_env.vfs().watch(path, &watch_handle, _heap) == Result::WATCH_OK - ? watch_handle : nullptr; - } - - - /**************************************** - ** Vfs::Io_response_handler interface ** - ****************************************/ - - void read_ready_response() override { - _io_ready = true; } - - void io_progress_response() override { - _io_ready = true; } - - - /********************************************** - * Entrypoint::Io_progress_handler interface ** - **********************************************/ - - void handle_io_progress() override - { - /* - * TODO: make VFS I/O completion checks during - * kernel time to avoid flapping between stacks - */ - - if (_io_ready) { - _io_ready = false; - - /* some contexts may have been deblocked from select() */ - if (libc_select_notify) - libc_select_notify(); - - /* - * resume all as any VFS context may have - * been deblocked from blocking I/O - */ - Kernel::resume_all(); - } - } - - void register_kernel_routine(Kernel_routine &kernel_routine) - { - _kernel_routine = &kernel_routine; - } -}; - - -void Libc::Kernel::reset_malloc_heap() -{ - _malloc_ram.construct(_heap, _env.ram()); - - _cloned_heap_ranges.for_each([&] (Registered<Cloned_malloc_heap_range> &r) { - destroy(_heap, &r); }); - - Heap &raw_malloc_heap = *_malloc_heap; - Genode::construct_at<Heap>(&raw_malloc_heap, *_malloc_ram, _env.rm()); - - reinit_malloc(raw_malloc_heap); -} - - -void Libc::Kernel::_init_file_descriptors() -{ - auto init_fd = [&] (Genode::Xml_node const &node, char const *attr, - int libc_fd, unsigned flags) - { - if (!node.has_attribute(attr)) - return; - - typedef Genode::String<Vfs::MAX_PATH_LEN> Path; - Path const path = node.attribute_value(attr, Path()); - - struct stat out_stat { }; - if (stat(path.string(), &out_stat) != 0) - return; - - Libc::File_descriptor *fd = _vfs.open(path.string(), flags, libc_fd); - if (fd->libc_fd != libc_fd) { - Genode::error("could not allocate fd ",libc_fd," for ",path,", " - "got fd ",fd->libc_fd); - _vfs.close(fd); - return; - } - - /* - * We need to manually register the path. Normally this is done - * by '_open'. But we call the local 'open' function directly - * because we want to explicitly specify the libc fd ID. - */ - if (fd->fd_path) - Genode::warning("may leak former FD path memory"); - - { - char *dst = (char *)_heap.alloc(path.length()); - Genode::strncpy(dst, path.string(), path.length()); - fd->fd_path = dst; - } - - ::off_t const seek = node.attribute_value("seek", 0ULL); - if (seek) - _vfs.lseek(fd, seek, SEEK_SET); - }; - - if (_vfs.root_dir_has_dirents()) { - - Xml_node const node = _libc_env.libc_config(); - - typedef Genode::String<Vfs::MAX_PATH_LEN> Path; - - if (node.has_attribute("cwd")) - chdir(node.attribute_value("cwd", Path()).string()); - - init_fd(node, "stdin", 0, O_RDONLY); - init_fd(node, "stdout", 1, O_WRONLY); - init_fd(node, "stderr", 2, O_WRONLY); - - node.for_each_sub_node("fd", [&] (Xml_node fd) { - - unsigned const id = fd.attribute_value("id", 0U); - - bool const rd = fd.attribute_value("readable", false); - bool const wr = fd.attribute_value("writeable", false); - - unsigned const flags = rd ? (wr ? O_RDWR : O_RDONLY) - : (wr ? O_WRONLY : 0); - - if (!fd.has_attribute("path")) - warning("Invalid <fd> node, 'path' attribute is missing"); - - init_fd(fd, "path", id, flags); - }); - - /* prevent use of IDs of stdin, stdout, and stderr for other files */ - for (unsigned fd = 0; fd <= 2; fd++) - Libc::file_descriptor_allocator()->preserve(fd); - } -} - - -void Libc::Kernel::_clone_state_from_parent() -{ - struct Range { void *at; size_t size; }; - - auto range_attr = [&] (Xml_node node) - { - return Range { - .at = (void *)node.attribute_value("at", 0UL), - .size = node.attribute_value("size", 0UL) - }; - }; - - /* - * Allocate local memory for the backing store of the application heap, - * mirrored from the parent. - * - * This step must precede the creation of the 'Clone_connection' because - * the shared-memory buffer of the clone session may otherwise potentially - * interfere with such a heap region. - */ - _libc_env.libc_config().for_each_sub_node("heap", [&] (Xml_node node) { - Range const range = range_attr(node); - new (_heap) - Registered<Cloned_malloc_heap_range>(_cloned_heap_ranges, - _env.ram(), _env.rm(), - range.at, range.size); }); - - Clone_connection clone_connection(_env); - - /* fetch heap content */ - _cloned_heap_ranges.for_each([&] (Cloned_malloc_heap_range &heap_range) { - heap_range.import_content(clone_connection); }); - - /* fetch user contex of the parent's application */ - clone_connection.memory_content(&_user_context, sizeof(_user_context)); - _valid_user_context = true; - - _libc_env.libc_config().for_each_sub_node([&] (Xml_node node) { - - auto copy_from_parent = [&] (Range range) - { - clone_connection.memory_content(range.at, range.size); - }; - - /* clone application stack */ - if (node.type() == "stack") - copy_from_parent(range_attr(node)); - - /* clone RW segment of a shared library or the binary */ - if (node.type() == "rw") { - typedef String<64> Name; - Name const name = node.attribute_value("name", Name()); - - /* - * The blacklisted segments are initialized via the - * regular startup of the child. - */ - bool const blacklisted = (name == "ld.lib.so") - || (name == "libc.lib.so") - || (name == "libm.lib.so") - || (name == "posix.lib.so") - || (strcmp(name.string(), "vfs", 3) == 0); - if (!blacklisted) - copy_from_parent(range_attr(node)); - } - }); - - /* import application-heap state from parent */ - clone_connection.object_content(_malloc_heap); - init_malloc_cloned(clone_connection); -} - - -/** - * Libc kernel singleton - * - * The singleton is implemented with the unmanaged-singleton utility - * in Component::construct() to ensure it is never destructed - * like normal static global objects. Otherwise, the task object may be - * destructed in a RPC to Rpc_resume, which would result in a deadlock. - */ -static Libc::Kernel *kernel; - - -/** - * Main context execution was suspended (on fork) - * - * This function is executed in the context of the initial thread. - */ -static void suspended_callback() { kernel->entrypoint_suspended(); } - - -/** - * Resume main context execution (after fork) - * - * This function is executed in the context of the initial thread. - */ -static void resumed_callback() { kernel->entrypoint_resumed(); } - - -/******************* - ** Libc task API ** - *******************/ - -void Libc::resume_all() { kernel->resume_all(); } - - -Genode::uint64_t Libc::suspend(Suspend_functor &s, Genode::uint64_t timeout_ms) -{ - if (!kernel) { - error("libc kernel not initialized, needed for suspend()"); - exit(1); - } - return kernel->suspend(s, timeout_ms); -} - - -void Libc::dispatch_pending_io_signals() -{ - kernel->dispatch_pending_io_signals(); -} - - -Vfs::Vfs_watch_handle *Libc::watch(char const *path) -{ - return kernel->alloc_watch_handle(path); -} - - -Genode::Duration Libc::current_time() -{ - return kernel->current_time(); -} - - -void Libc::schedule_suspend(void (*suspended) ()) -{ - if (!kernel) { - error("libc kernel not initialized, needed for fork()"); - exit(1); - } - kernel->schedule_suspend(suspended); -} - - -void Libc::schedule_select(Libc::Select_handler_base *h) -{ - if (!kernel) { - error("libc kernel not initialized, needed for select()"); - exit(1); - } - kernel->schedule_select(h); -} - - -void Libc::execute_in_application_context(Libc::Application_code &app_code) -{ - if (!kernel) { - error("libc kernel not initialized, needed for with_libc()"); - exit(1); - } - - /* - * The libc execution model builds on the main entrypoint, which handles - * all relevant signals (e.g., timing and VFS). Additional component - * entrypoints or pthreads should never call with_libc() but we catch this - * here and just execute the application code directly. - */ - if (!kernel->main_context()) { - app_code.execute(); - return; - } - - static bool nested = false; - - if (nested) { - - if (kernel->main_suspended()) { - kernel->nested_execution(app_code); - } else { - app_code.execute(); - } - return; - } - - nested = true; - kernel->run(app_code); - nested = false; -} - - -void Libc::register_kernel_routine(Kernel_routine &kernel_routine) -{ - kernel->register_kernel_routine(kernel_routine); -} - - -Genode::Xml_node Libc::libc_config() -{ - return kernel->libc_env().libc_config(); -} - - -/*************************** - ** Component entry point ** - ***************************/ - -Genode::size_t Component::stack_size() { return Libc::Component::stack_size(); } - - -void Component::construct(Genode::Env &env) -{ - /* initialize the global pointer to environment variables */ - static char *null_env = nullptr; - if (!environ) environ = &null_env; - - Genode::Allocator &heap = - *unmanaged_singleton<Genode::Heap>(env.ram(), env.rm()); - - /* pass Genode::Env to libc subsystems that depend on it */ - Libc::init_fd_alloc(heap); - Libc::init_mem_alloc(env); - Libc::init_dl(env); - Libc::sysctl_init(env); - Libc::init_pthread_support(env); - - kernel = unmanaged_singleton<Libc::Kernel>(env, heap); - - Libc::libc_config_init(kernel->libc_env().libc_config()); - - /* - * XXX The following two steps leave us with the dilemma that we don't know - * which linked library may depend on the successfull initialization of a - * plugin. For example, some high-level library may try to open a network - * connection in its constructor before the network-stack library is - * initialized. But, we can't initialize plugins before calling static - * constructors as those are needed to know about the libc plugin. The only - * solution is to remove all libc plugins beside the VFS implementation, - * which is our final goal anyway. - */ - - /* finish static construction of component and libraries */ - Libc::with_libc([&] () { env.exec_static_constructors(); }); - - /* initialize plugins that require Genode::Env */ - auto init_plugin = [&] (Libc::Plugin &plugin) { - plugin.init(env); - }; - Libc::plugin_registry()->for_each_plugin(init_plugin); - - /* construct libc component on kernel stack */ - Libc::Component::construct(kernel->libc_env()); -} - - -/** - * Default stack size for libc-using components - */ -Genode::size_t Libc::Component::stack_size() __attribute__((weak)); -Genode::size_t Libc::Component::stack_size() { return 32UL*1024*sizeof(long); } diff --git a/repos/libports/src/lib/libc/task.h b/repos/libports/src/lib/libc/task.h deleted file mode 100644 index 1df9512c3..000000000 --- a/repos/libports/src/lib/libc/task.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * \brief Libc-internal kernel API - * \author Christian Helmuth - * \author Emery Hemingway - * \date 2016-12-14 - * - * TODO document libc tasking including - * - the initial thread (which is neither component nor pthread) - * - processes incoming signals and forwards to entrypoint - * - the main thread (which is the kernel and the main user context) - * - pthreads (which are pthread user contexts only) - */ - -/* - * Copyright (C) 2016-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 _LIBC__TASK_H_ -#define _LIBC__TASK_H_ - -#include <base/duration.h> -#include <util/xml_node.h> -#include <vfs/vfs_handle.h> - -namespace Libc { - - /** - * Resume all user contexts - * - * This resumes the main user context as well as any pthread context. - */ - void resume_all(); - - /** - * Suspend the execution of the calling user context - * - * \param timeout_ms maximum time to stay suspended in milliseconds, - * 0 for infinite suspend - * - * \return remaining duration until timeout, - * 0 if the timeout expired - * - * The context could be running on the component entrypoint as main context - * or as separate pthread. This function returns after the libc kernel - * resumed the user context execution. - */ - struct Suspend_functor { virtual bool suspend() = 0; }; - Genode::uint64_t suspend(Suspend_functor &, Genode::uint64_t timeout_ms = 0); - - void dispatch_pending_io_signals(); - - /** - * Get watch handle for given path - * - * \param path path that should be be watched - * - * \return point to the watch handle object or a nullptr - * when the watch operation failed - */ - Vfs::Vfs_watch_handle *watch(char const *path); - - /** - * Get time since startup in ms - */ - Genode::Duration current_time(); - - /** - * Suspend main user context and the component entrypoint - * - * This interface is solely used by the implementation of fork(). - */ - void schedule_suspend(void (*suspended) ()); - - struct Select_handler_base; - - /** - * Schedule select handler that is deblocked by ready fd sets - */ - void schedule_select(Select_handler_base *); - - struct Kernel_routine : Genode::Interface - { - virtual void execute_in_kernel() = 0; - }; - - /** - * Register routine to be called once on the next libc-kernel activation - * - * The specified routine is executed only once. For a repeated execution, - * the routine must call 'register_kernel_routine' with itself as - * argument. - * - * This mechanism is used by 'fork' to implement the blocking for the - * startup of a new child and for 'wait4'. - */ - void register_kernel_routine(Kernel_routine &); - - /** - * Access libc configuration Xml_node. - */ - Genode::Xml_node libc_config(); -} - -#endif /* _LIBC__TASK_H_ */ diff --git a/repos/libports/src/lib/libc/time.cc b/repos/libports/src/lib/libc/time.cc index 676e88545..5827344d6 100644 --- a/repos/libports/src/lib/libc/time.cc +++ b/repos/libports/src/lib/libc/time.cc @@ -12,44 +12,70 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* Libc includes */ +/* Genode includes */ +#include <base/log.h> +#include <vfs/vfs_handle.h> + +/* Genode-internal includes */ +#include <base/internal/unmanaged_singleton.h> + +/* libc includes */ #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> +/* libc-internal includes */ +#include <internal/legacy.h> +#include <internal/errno.h> +#include <internal/init.h> +#include <internal/current_time.h> +#include <internal/watch.h> + +static Libc::Current_time *_current_time_ptr; +static char const *_rtc_path; +static Libc::Watch *_watch_ptr; -#include "task.h" -#include "libc_errno.h" +void Libc::init_time(Current_time ¤t_time, + Rtc_path const &rtc_path, + Watch &watch) +{ + static Rtc_path rtc_path_inst = rtc_path; -/* Genode includes */ -#include <base/log.h> -#include <vfs/vfs_handle.h> - - -namespace Libc { - extern char const *config_rtc(); + _current_time_ptr = ¤t_time; + _rtc_path = rtc_path_inst.string(); + _watch_ptr = &watch; } -struct Rtc : Vfs::Watch_response_handler +namespace Libc { struct Rtc; } + + +struct Libc::Rtc : Vfs::Watch_response_handler { Vfs::Vfs_watch_handle *_watch_handle { nullptr }; - char const *_file { nullptr }; - bool _read_file { true }; - time_t _rtc_value { 0 }; - Rtc(char const *rtc_file) - : _file(rtc_file) + Rtc_path const _rtc_path; + + Watch &_watch; + + bool _read_file { true }; + time_t _rtc_value { 0 }; + + bool const _rtc_path_valid = (_rtc_path != ""); + + Rtc(Rtc_path const &rtc_path, Watch &watch) + : + _rtc_path(rtc_path), _watch(watch) { - if (!Genode::strcmp(_file, "")) { - Genode::warning("rtc not configured, returning ", _rtc_value); + if (!_rtc_path_valid) { + warning("rtc not configured, returning ", _rtc_value); return; } - _watch_handle = Libc::watch(_file); + _watch_handle = _watch.alloc_watch_handle(_rtc_path.string()); if (_watch_handle) { _watch_handle->handler(this); } @@ -66,16 +92,16 @@ struct Rtc : Vfs::Watch_response_handler time_t read() { - if (!_file) { return 0; } + if (!_rtc_path_valid) { return 0; } /* return old value */ if (!_read_file) { return _rtc_value; } _read_file = false; - int fd = open(_file, O_RDONLY); + int fd = open(_rtc_path.string(), O_RDONLY); if (fd == -1) { - Genode::warning(Genode::Cstring(Libc::config_rtc()), " not readable, returning ", _rtc_value); + warning(_rtc_path, " not readable, returning ", _rtc_value); return _rtc_value; } @@ -84,7 +110,7 @@ struct Rtc : Vfs::Watch_response_handler if (n > 0) { buf[n - 1] = '\0'; struct tm tm; - Genode::memset(&tm, 0, sizeof(tm)); + memset(&tm, 0, sizeof(tm)); if (strptime(buf, "%Y-%m-%d %R", &tm)) { _rtc_value = mktime(&tm); @@ -95,8 +121,12 @@ struct Rtc : Vfs::Watch_response_handler close(fd); + struct Missing_call_of_init_time : Exception { }; + if (!_current_time_ptr) + throw Missing_call_of_init_time(); + uint64_t const ts_value = - Libc::current_time().trunc_to_plain_ms().value; + _current_time_ptr->current_time().trunc_to_plain_ms().value; _rtc_value += (time_t)ts_value / 1000; return _rtc_value; @@ -104,10 +134,26 @@ struct Rtc : Vfs::Watch_response_handler }; +using namespace Libc; + + extern "C" __attribute__((weak)) int clock_gettime(clockid_t clk_id, struct timespec *ts) { - if (!ts) return Libc::Errno(EFAULT); + typedef Libc::uint64_t uint64_t; + + if (!ts) return Errno(EFAULT); + + struct Missing_call_of_init_time : Exception { }; + + auto current_time = [&] () + { + if (!_current_time_ptr) + throw Missing_call_of_init_time(); + + return _current_time_ptr->current_time(); + }; + /* initialize timespec just in case users do not check for errors */ ts->tv_sec = 0; @@ -119,12 +165,18 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts) case CLOCK_REALTIME: case CLOCK_SECOND: /* FreeBSD specific */ { - static Rtc rtc(Libc::config_rtc()); + if (!_watch_ptr) + throw Missing_call_of_init_time(); + + /* + * XXX move instance to Libc::Kernel + */ + Rtc &rtc = *unmanaged_singleton<Rtc>(_rtc_path, *_watch_ptr); time_t const rtc_value = rtc.read(); - if (!rtc_value) return Libc::Errno(EINVAL); + if (!rtc_value) return Errno(EINVAL); - Genode::uint64_t const time = Libc::current_time().trunc_to_plain_ms().value; + uint64_t const time = current_time().trunc_to_plain_ms().value; ts->tv_sec = rtc_value + time/1000; ts->tv_nsec = (time % 1000) * (1000*1000); @@ -135,7 +187,7 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts) case CLOCK_MONOTONIC: case CLOCK_UPTIME: { - Genode::uint64_t us = Libc::current_time().trunc_to_plain_us().value; + uint64_t us = current_time().trunc_to_plain_us().value; ts->tv_sec = us / (1000*1000); ts->tv_nsec = (us % (1000*1000)) * 1000; @@ -143,7 +195,7 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts) } default: - return Libc::Errno(EINVAL); + return Errno(EINVAL); } return 0; @@ -177,6 +229,6 @@ int __sys_gettimeofday(struct timeval *tv, struct timezone *); extern "C" clock_t clock() { - Genode::error(__func__, " not implemented, use 'clock_gettime' instead"); + error(__func__, " not implemented, use 'clock_gettime' instead"); return -1; } diff --git a/repos/libports/src/lib/libc/vfs_plugin.cc b/repos/libports/src/lib/libc/vfs_plugin.cc index 6ca429e5c..ef8a9c72c 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.cc +++ b/repos/libports/src/lib/libc/vfs_plugin.cc @@ -34,12 +34,34 @@ /* libc plugin interface */ #include <libc-plugin/plugin.h> -#include <vfs_plugin.h> /* libc-internal includes */ -#include "libc_mem_alloc.h" -#include "libc_errno.h" -#include "task.h" +#include <internal/vfs_plugin.h> +#include <internal/mem_alloc.h> +#include <internal/errno.h> +#include <internal/init.h> +#include <internal/legacy.h> +#include <internal/suspend.h> + + +static Libc::Suspend *_suspend_ptr; + + +void Libc::init_vfs_plugin(Suspend &suspend) +{ + _suspend_ptr = &suspend; +} + + +static void suspend(Libc::Suspend_functor &check) +{ + struct Missing_call_of_init_vfs_plugin : Genode::Exception { }; + if (!_suspend_ptr) + throw Missing_call_of_init_vfs_plugin(); + + _suspend_ptr->suspend(check); +}; + static Genode::Lock &vfs_lock() { @@ -76,16 +98,36 @@ static void vfs_stat_to_libc_stat_struct(Vfs::Directory_service::Stat const &src { enum { FS_BLOCK_SIZE = 4096 }; - Genode::memset(dst, 0, sizeof(*dst)); + unsigned const readable_bits = S_IRUSR, + writeable_bits = S_IWUSR, + executable_bits = S_IXUSR; - dst->st_uid = src.uid; - dst->st_gid = src.gid; - dst->st_mode = src.mode; + auto type = [] (Vfs::Node_type type) + { + switch (type) { + case Vfs::Node_type::DIRECTORY: return S_IFDIR; + case Vfs::Node_type::CONTINUOUS_FILE: return S_IFREG; + case Vfs::Node_type::TRANSACTIONAL_FILE: return S_IFSOCK; + case Vfs::Node_type::SYMLINK: return S_IFLNK; + } + return 0; + }; + + *dst = { }; + + dst->st_uid = 0; + dst->st_gid = 0; + dst->st_mode = (src.rwx.readable ? readable_bits : 0) + | (src.rwx.writeable ? writeable_bits : 0) + | (src.rwx.executable ? executable_bits : 0) + | type(src.type); dst->st_size = src.size; dst->st_blksize = FS_BLOCK_SIZE; dst->st_blocks = (dst->st_size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE; dst->st_ino = src.inode; dst->st_dev = src.device; + long long mtime = src.modification_time.value; + dst->st_mtime = mtime != Vfs::Timestamp::INVALID ? mtime : 0; } @@ -96,8 +138,8 @@ char const *libc_resolv_path; namespace Libc { - Genode::Xml_node config() __attribute__((weak)); - Genode::Xml_node config() + Xml_node config() __attribute__((weak)); + Xml_node config() { if (!_config_node) { error("libc config not initialized - aborting"); @@ -117,18 +159,18 @@ namespace Libc { Config_attr(char const *attr_name, char const *default_value) : - _value(Libc::config().attribute_value(attr_name, - Value(default_value))) + _value(config().attribute_value(attr_name, + Value(default_value))) { } char const *string() const { return _value.string(); } }; - char const *config_rtc() __attribute__((weak)); - char const *config_rtc() + char const *config_pipe() __attribute__((weak)); + char const *config_pipe() { - static Config_attr rtc("rtc", ""); - return rtc.string(); + static Config_attr attr("pipe", ""); + return attr.string(); } char const *config_rng() __attribute__((weak)); @@ -153,9 +195,9 @@ namespace Libc { return ns_file.string(); } - void libc_config_init(Genode::Xml_node node) + void libc_config_init(Xml_node node) { - static Genode::Xml_node config = node; + static Xml_node config = node; _config_node = &config; libc_resolv_path = config_nameserver_file(); @@ -172,7 +214,7 @@ namespace Libc { VFS_THREAD_SAFE(handle->fs().notify_read_ready(handle)); } - bool read_ready(Libc::File_descriptor *fd) + bool read_ready(File_descriptor *fd) { Vfs::Vfs_handle *handle = vfs_handle(fd); if (!handle) return false; @@ -181,12 +223,34 @@ namespace Libc { return VFS_THREAD_SAFE(handle->fs().read_ready(handle)); } - } + +template <typename FN> +void Libc::Vfs_plugin::_with_info(File_descriptor &fd, FN const &fn) +{ + if (!_root_dir.constructed()) + return; + + Absolute_path path = ioctl_dir(fd); + path.append_element("info"); + + try { + Lock::Guard g(vfs_lock()); + + File_content const content(_alloc, *_root_dir, path.string(), + File_content::Limit{4096U}); + + content.xml([&] (Xml_node node) { + fn(node); }); + + } catch (...) { } +} + + int Libc::Vfs_plugin::access(const char *path, int amode) { - if (VFS_THREAD_SAFE(_root_dir.leaf_path(path))) + if (VFS_THREAD_SAFE(_root_fs.leaf_path(path))) return 0; errno = ENOENT; @@ -197,7 +261,7 @@ int Libc::Vfs_plugin::access(const char *path, int amode) Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags, int libc_fd) { - if (VFS_THREAD_SAFE(_root_dir.directory(path))) { + if (VFS_THREAD_SAFE(_root_fs.directory(path))) { if (((flags & O_ACCMODE) != O_RDONLY)) { errno = EISDIR; @@ -210,7 +274,7 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags, typedef Vfs::Directory_service::Opendir_result Opendir_result; - switch (VFS_THREAD_SAFE(_root_dir.opendir(path, false, &handle, _alloc))) { + switch (VFS_THREAD_SAFE(_root_fs.opendir(path, false, &handle, _alloc))) { case Opendir_result::OPENDIR_OK: break; case Opendir_result::OPENDIR_ERR_LOOKUP_FAILED: errno = ENOENT; return nullptr; case Opendir_result::OPENDIR_ERR_NAME_TOO_LONG: errno = ENAMETOOLONG; return nullptr; @@ -223,8 +287,8 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags, /* the directory was successfully opened */ - Libc::File_descriptor *fd = - Libc::file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd); + File_descriptor *fd = + file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd); /* FIXME error cleanup code leaks resources! */ @@ -251,7 +315,7 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags, while (handle == nullptr) { - switch (VFS_THREAD_SAFE(_root_dir.open(path, flags, &handle, _alloc))) { + switch (VFS_THREAD_SAFE(_root_fs.open(path, flags, &handle, _alloc))) { case Result::OPEN_OK: break; @@ -268,7 +332,7 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags, } /* O_CREAT is set, so try to create the file */ - switch (VFS_THREAD_SAFE(_root_dir.open(path, flags | O_EXCL, &handle, _alloc))) { + switch (VFS_THREAD_SAFE(_root_fs.open(path, flags | O_EXCL, &handle, _alloc))) { case Result::OPEN_OK: break; @@ -304,8 +368,8 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags, /* the file was successfully opened */ - Libc::File_descriptor *fd = - Libc::file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd); + File_descriptor *fd = + file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd); /* FIXME error cleanup code leaks resources! */ @@ -328,13 +392,52 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags, } +void Libc::Vfs_plugin::_vfs_write_mtime(Vfs::Vfs_handle &handle) +{ + struct timespec ts; + + if (_update_mtime == Update_mtime::NO) + return; + + /* XXX using clock_gettime directly is probably not the best idea */ + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) { + ts.tv_sec = 0; + } + + Vfs::Timestamp time { .value = (long long)ts.tv_sec }; + + struct Check : Libc::Suspend_functor + { + bool retry { false }; + + Vfs::Vfs_handle &vfs_handle; + Vfs::Timestamp &time; + + Check(Vfs::Vfs_handle &vfs_handle, Vfs::Timestamp &time) + : vfs_handle(vfs_handle), time(time) { } + + bool suspend() override + { + retry = !vfs_handle.fs().update_modification_timestamp(&vfs_handle, time); + return retry; + } + } check(handle, time); + + do { + _suspend_ptr->suspend(check); + } while (check.retry); +} + + int Libc::Vfs_plugin::_vfs_sync(Vfs::Vfs_handle &vfs_handle) { + _vfs_write_mtime(vfs_handle); + typedef Vfs::File_io_service::Sync_result Result; Result result = Result::SYNC_QUEUED; { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -351,18 +454,18 @@ int Libc::Vfs_plugin::_vfs_sync(Vfs::Vfs_handle &vfs_handle) } check(vfs_handle); /* - * Cannot call Libc::suspend() immediately, because the Libc kernel + * Cannot call suspend() immediately, because the Libc kernel * might not be running yet. */ if (!VFS_THREAD_SAFE(vfs_handle.fs().queue_sync(&vfs_handle))) { do { - Libc::suspend(check); + suspend(check); } while (check.retry); } } { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -381,52 +484,113 @@ int Libc::Vfs_plugin::_vfs_sync(Vfs::Vfs_handle &vfs_handle) } check(vfs_handle, result); /* - * Cannot call Libc::suspend() immediately, because the Libc kernel + * Cannot call suspend() immediately, because the Libc kernel * might not be running yet. */ result = VFS_THREAD_SAFE(vfs_handle.fs().complete_sync(&vfs_handle)); if (result == Result::SYNC_QUEUED) { do { - Libc::suspend(check); + suspend(check); } while (check.retry); } } - return result == Result::SYNC_OK ? 0 : Libc::Errno(EIO); + return result == Result::SYNC_OK ? 0 : Errno(EIO); } -int Libc::Vfs_plugin::close(Libc::File_descriptor *fd) +int Libc::Vfs_plugin::close(File_descriptor *fd) { Vfs::Vfs_handle *handle = vfs_handle(fd); - /* XXX: mark the handle as requiring sync or not */ - _vfs_sync(*handle); + + if ((fd->modified) || (fd->flags & O_CREAT)) { + _vfs_sync(*handle); + } + VFS_THREAD_SAFE(handle->close()); - Libc::file_descriptor_allocator()->free(fd); + file_descriptor_allocator()->free(fd); return 0; } -int Libc::Vfs_plugin::dup2(Libc::File_descriptor *fd, - Libc::File_descriptor *new_fd) +int Libc::Vfs_plugin::dup2(File_descriptor *fd, + File_descriptor *new_fd) { - new_fd->context = fd->context; + Vfs::Vfs_handle *handle = nullptr; + + typedef Vfs::Directory_service::Open_result Result; + + if (VFS_THREAD_SAFE(_root_fs.open(fd->fd_path, fd->flags, &handle, _alloc)) + != Result::OPEN_OK) { + + warning("dup2 failed for path ", fd->fd_path); + return Errno(EBADF); + } + + handle->seek(vfs_handle(fd)->seek()); + handle->handler(&_response_handler); + + new_fd->context = vfs_context(handle); + new_fd->flags = fd->flags; + new_fd->path(fd->fd_path); + return new_fd->libc_fd; } -int Libc::Vfs_plugin::fstat(Libc::File_descriptor *fd, struct stat *buf) +Libc::File_descriptor *Libc::Vfs_plugin::dup(File_descriptor *fd) { - Vfs::Vfs_handle *handle = vfs_handle(fd); - _vfs_sync(*handle); - return stat(fd->fd_path, buf); + Vfs::Vfs_handle *handle = nullptr; + + typedef Vfs::Directory_service::Open_result Result; + + if (VFS_THREAD_SAFE(_root_fs.open(fd->fd_path, fd->flags, &handle, _alloc)) + != Result::OPEN_OK) { + + warning("dup failed for path ", fd->fd_path); + errno = EBADF; + return nullptr; + } + + handle->seek(vfs_handle(fd)->seek()); + handle->handler(&_response_handler); + + File_descriptor * const new_fd = + file_descriptor_allocator()->alloc(this, vfs_context(handle)); + + new_fd->flags = fd->flags; + new_fd->path(fd->fd_path); + + return new_fd; } -int Libc::Vfs_plugin::fstatfs(Libc::File_descriptor *fd, struct statfs *buf) +int Libc::Vfs_plugin::fstat(File_descriptor *fd, struct stat *buf) +{ + Vfs::Vfs_handle *handle = vfs_handle(fd); + if (fd->modified) { + _vfs_sync(*handle); + fd->modified = false; + } + + int const result = stat(fd->fd_path, buf); + + /* + * The libc expects stdout to be a character device. + * If 'st_mode' is set to 'S_IFREG', 'printf' does not work. + */ + if (fd->libc_fd == 1) { + buf->st_mode &= ~S_IFMT; + buf->st_mode |= S_IFCHR; + } + return result; +} + + +int Libc::Vfs_plugin::fstatfs(File_descriptor *fd, struct statfs *buf) { if (!fd || !buf) - return Libc::Errno(EFAULT); + return Errno(EFAULT); Genode::memset(buf, 0, sizeof(*buf)); @@ -441,7 +605,7 @@ int Libc::Vfs_plugin::mkdir(const char *path, mode_t mode) typedef Vfs::Directory_service::Opendir_result Opendir_result; - switch (VFS_THREAD_SAFE(_root_dir.opendir(path, true, &dir_handle, _alloc))) { + switch (VFS_THREAD_SAFE(_root_fs.opendir(path, true, &dir_handle, _alloc))) { case Opendir_result::OPENDIR_OK: VFS_THREAD_SAFE(dir_handle->close()); break; @@ -474,7 +638,7 @@ int Libc::Vfs_plugin::stat(char const *path, struct stat *buf) Vfs::Directory_service::Stat stat; - switch (VFS_THREAD_SAFE(_root_dir.stat(path, stat))) { + switch (VFS_THREAD_SAFE(_root_fs.stat(path, stat))) { case Result::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1; case Result::STAT_ERR_NO_PERM: errno = EACCES; return -1; case Result::STAT_OK: break; @@ -485,11 +649,15 @@ int Libc::Vfs_plugin::stat(char const *path, struct stat *buf) } -ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf, +ssize_t Libc::Vfs_plugin::write(File_descriptor *fd, const void *buf, ::size_t count) { typedef Vfs::File_io_service::Write_result Result; + if ((fd->flags & O_ACCMODE) == O_RDONLY) { + return Errno(EBADF); + } + Vfs::Vfs_handle *handle = vfs_handle(fd); Vfs::file_size out_count = 0; @@ -500,51 +668,127 @@ ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf, try { out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf, count, out_count)); - /* wake up threads blocking for 'queue_*()' or 'write()' */ - Libc::resume_all(); + Plugin::resume_all(); } catch (Vfs::File_io_service::Insufficient_buffer) { } } else { - struct Check : Libc::Suspend_functor + Vfs::file_size const initial_seek { handle->seek() }; + + struct Check : Suspend_functor { - bool retry { false }; + bool retry { false }; - Vfs::Vfs_handle *handle; - void const *buf; - ::size_t count; - Vfs::file_size &out_count; - Result &out_result; + Vfs::File_system &_root_fs; + char const * const _fd_path; + Vfs::Vfs_handle *_handle; + void const *_buf; + ::size_t _count; + ::off_t _offset = 0; + Vfs::file_size &_out_count; + Result &_out_result; + unsigned _iteration = 0; - Check(Vfs::Vfs_handle *handle, void const *buf, + bool _fd_refers_to_continuous_file() + { + if (!_fd_path) { + warning("Vfs_plugin: _fd_refers_to_continuous_file: missing fd_path"); + return false; + } + + typedef Vfs::Directory_service::Stat_result Result; + + Vfs::Directory_service::Stat stat { }; + + if (VFS_THREAD_SAFE(_root_fs.stat(_fd_path, stat)) != Result::STAT_OK) + return false; + + return stat.type == Vfs::Node_type::CONTINUOUS_FILE; + }; + + Check(Vfs::File_system &root_fs, char const *fd_path, + Vfs::Vfs_handle *handle, void const *buf, ::size_t count, Vfs::file_size &out_count, Result &out_result) - : handle(handle), buf(buf), count(count), out_count(out_count), - out_result(out_result) + : + _root_fs(root_fs), _fd_path(fd_path), _handle(handle), _buf(buf), + _count(count), _out_count(out_count), _out_result(out_result) { } bool suspend() override { - try { - out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf, - count, out_count)); - retry = false; - } catch (Vfs::File_io_service::Insufficient_buffer) { - retry = true; - } + for (;;) { - return retry; + /* number of bytes written in one iteration */ + Vfs::file_size partial_out_count = 0; + + try { + char const * const src = (char const *)_buf + _offset; + + _out_result = VFS_THREAD_SAFE(_handle->fs().write(_handle, src, + _count, partial_out_count)); + } catch (Vfs::File_io_service::Insufficient_buffer) { + retry = true; + return retry; + } + + if (_out_result != Result::WRITE_OK) { + retry = false; + return retry; + } + + /* increment byte count reported to caller */ + _out_count += partial_out_count; + + bool const write_complete = (partial_out_count == _count); + if (write_complete) { + retry = false; + return retry; + } + + /* + * If the write has not consumed all bytes, set up + * another partial write iteration with the remaining + * bytes as 'count'. + * + * The costly 'fd_refers_to_continuous_file' is called + * for the first iteration only. + */ + bool const continuous_file = (_iteration > 0 || _fd_refers_to_continuous_file()); + + if (!continuous_file) { + warning("partial write on transactional file"); + _out_result = Result::WRITE_ERR_IO; + retry = false; + return retry; + } + + _iteration++; + + bool const stalled = (partial_out_count == 0); + if (stalled) { + retry = true; + return retry; + } + + /* issue new write operation for remaining bytes */ + _count -= partial_out_count; + _offset += partial_out_count; + _handle->advance_seek(partial_out_count); + } } - } check(handle, buf, count, out_count, out_result); + } check(_root_fs, fd->fd_path, handle, buf, count, out_count, out_result); do { - Libc::suspend(check); + suspend(check); } while (check.retry); + + /* XXX reset seek pointer after loop (will be advanced below by out_count) */ + handle->seek(initial_seek); } - /* wake up threads blocking for 'queue_*()' or 'write()' */ - Libc::resume_all(); + Plugin::resume_all(); switch (out_result) { case Result::WRITE_ERR_AGAIN: return Errno(EAGAIN); @@ -556,15 +800,20 @@ ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf, } VFS_THREAD_SAFE(handle->advance_seek(out_count)); + fd->modified = true; return out_count; } -ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf, +ssize_t Libc::Vfs_plugin::read(File_descriptor *fd, void *buf, ::size_t count) { - Libc::dispatch_pending_io_signals(); + dispatch_pending_io_signals(); + + if ((fd->flags & O_ACCMODE) == O_WRONLY) { + return Errno(EBADF); + } typedef Vfs::File_io_service::Read_result Result; @@ -573,11 +822,11 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf, if (fd->flags & O_DIRECTORY) return Errno(EISDIR); - if (fd->flags & O_NONBLOCK && !Libc::read_ready(fd)) + if (fd->flags & O_NONBLOCK && !read_ready(fd)) return Errno(EAGAIN); { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -595,7 +844,7 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf, } check ( handle, count); do { - Libc::suspend(check); + suspend(check); } while (check.retry); } @@ -603,7 +852,7 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf, Result out_result; { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -632,12 +881,11 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf, } check ( handle, buf, count, out_count, out_result); do { - Libc::suspend(check); + suspend(check); } while (check.retry); } - /* wake up threads blocking for 'queue_*()' or 'write()' */ - Libc::resume_all(); + Plugin::resume_all(); switch (out_result) { case Result::READ_ERR_AGAIN: return Errno(EAGAIN); @@ -656,11 +904,11 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf, } -ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf, +ssize_t Libc::Vfs_plugin::getdirentries(File_descriptor *fd, char *buf, ::size_t nbytes, ::off_t *basep) { if (nbytes < sizeof(struct dirent)) { - Genode::error("getdirentries: buffer too small"); + error("getdirentries: buffer too small"); return -1; } @@ -673,7 +921,7 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf, Dirent dirent_out; { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -690,7 +938,7 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf, } check(handle); do { - Libc::suspend(check); + suspend(check); } while (check.retry); } @@ -698,7 +946,7 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf, Vfs::file_size out_count; { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -718,6 +966,7 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf, (char*)&dirent_out, sizeof(Dirent), out_count)); + dirent_out.sanitize(); /* suspend me if read is still queued */ @@ -728,41 +977,48 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf, } check(handle, dirent_out, out_count, out_result); do { - Libc::suspend(check); + suspend(check); } while (check.retry); } - /* wake up threads blocking for 'queue_*()' or 'write()' */ - Libc::resume_all(); + Plugin::resume_all(); if ((out_result != Result::READ_OK) || (out_count < sizeof(Dirent))) { return 0; } + using Dirent_type = Vfs::Directory_service::Dirent_type; + + if (dirent_out.type == Dirent_type::END) + return 0; + /* * Convert dirent structure from VFS to libc */ - struct dirent *dirent = (struct dirent *)buf; - Genode::memset(dirent, 0, sizeof(struct dirent)); + auto dirent_type = [] (Dirent_type type) + { + switch (type) { + case Dirent_type::DIRECTORY: return DT_DIR; + case Dirent_type::CONTINUOUS_FILE: return DT_REG; + case Dirent_type::TRANSACTIONAL_FILE: return DT_SOCK; + case Dirent_type::SYMLINK: return DT_LNK; + case Dirent_type::END: return DT_UNKNOWN; + } + return DT_UNKNOWN; + }; - switch (dirent_out.type) { - case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: dirent->d_type = DT_DIR; break; - case Vfs::Directory_service::DIRENT_TYPE_FILE: dirent->d_type = DT_REG; break; - case Vfs::Directory_service::DIRENT_TYPE_SYMLINK: dirent->d_type = DT_LNK; break; - case Vfs::Directory_service::DIRENT_TYPE_FIFO: dirent->d_type = DT_FIFO; break; - case Vfs::Directory_service::DIRENT_TYPE_CHARDEV: dirent->d_type = DT_CHR; break; - case Vfs::Directory_service::DIRENT_TYPE_BLOCKDEV: dirent->d_type = DT_BLK; break; - case Vfs::Directory_service::DIRENT_TYPE_END: return 0; - } + dirent &dirent = *(struct dirent *)buf; + dirent = { }; - dirent->d_fileno = dirent_out.fileno; - dirent->d_reclen = sizeof(struct dirent); + dirent.d_type = dirent_type(dirent_out.type); + dirent.d_fileno = dirent_out.fileno; + dirent.d_reclen = sizeof(struct dirent); - Genode::strncpy(dirent->d_name, dirent_out.name, sizeof(dirent->d_name)); + Genode::strncpy(dirent.d_name, dirent_out.name.buf, sizeof(dirent.d_name)); - dirent->d_namlen = Genode::strlen(dirent->d_name); + dirent.d_namlen = Genode::strlen(dirent.d_name); /* * Keep track of VFS seek pointer and user-supplied basep. @@ -775,7 +1031,56 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf, } -int Libc::Vfs_plugin::ioctl(Libc::File_descriptor *fd, int request, char *argp) +int Libc::Vfs_plugin::ioctl(File_descriptor *fd, int request, char *argp) +{ + bool handled = false; + + if (request == TIOCGWINSZ) { + + if (!argp) + return Errno(EINVAL); + + _with_info(*fd, [&] (Xml_node info) { + if (info.type() == "terminal") { + ::winsize *winsize = (::winsize *)argp; + winsize->ws_row = info.attribute_value("rows", 25U); + winsize->ws_col = info.attribute_value("columns", 80U); + handled = true; + } + }); + + } else if (request == TIOCGETA) { + + ::termios *termios = (::termios *)argp; + + termios->c_iflag = 0; + termios->c_oflag = 0; + termios->c_cflag = 0; + /* + * Set 'ECHO' flag, needed by libreadline. Otherwise, echoing + * user input doesn't work in bash. + */ + termios->c_lflag = ECHO; + ::memset(termios->c_cc, _POSIX_VDISABLE, sizeof(termios->c_cc)); + termios->c_ispeed = 0; + termios->c_ospeed = 0; + handled = true; + } + + if (handled) + return 0; + + return _legacy_ioctl(fd, request, argp); +} + + +/** + * Fallback for ioctl operations targeting the deprecated VFS ioctl interface + * + * XXX Remove this method once all ioctl operations are supported via + * regular VFS file accesses. + */ +int Libc::Vfs_plugin::_legacy_ioctl(File_descriptor *fd, int request, char *argp) { using ::off_t; @@ -802,27 +1107,6 @@ int Libc::Vfs_plugin::ioctl(Libc::File_descriptor *fd, int request, char *argp) break; } - case TIOCGETA: - { - ::termios *termios = (::termios *)argp; - - termios->c_iflag = 0; - termios->c_oflag = 0; - termios->c_cflag = 0; - /* - * Set 'ECHO' flag, needed by libreadline. Otherwise, echoing - * user input doesn't work in bash. - */ - termios->c_lflag = ECHO; - ::memset(termios->c_cc, _POSIX_VDISABLE, sizeof(termios->c_cc)); - termios->c_ispeed = 0; - termios->c_ospeed = 0; - - return 0; - } - - break; - case TIOCSETAF: { opcode = Opcode::IOCTL_OP_TIOCSETAF; @@ -870,7 +1154,7 @@ int Libc::Vfs_plugin::ioctl(Libc::File_descriptor *fd, int request, char *argp) } default: - Genode::warning("unsupported ioctl (request=", Genode::Hex(request), ")"); + warning("unsupported ioctl (request=", Hex(request), ")"); break; } @@ -929,7 +1213,7 @@ int Libc::Vfs_plugin::ioctl(Libc::File_descriptor *fd, int request, char *argp) } -::off_t Libc::Vfs_plugin::lseek(Libc::File_descriptor *fd, ::off_t offset, int whence) +::off_t Libc::Vfs_plugin::lseek(File_descriptor *fd, ::off_t offset, int whence) { Vfs::Vfs_handle *handle = vfs_handle(fd); @@ -949,10 +1233,13 @@ int Libc::Vfs_plugin::ioctl(Libc::File_descriptor *fd, int request, char *argp) } -int Libc::Vfs_plugin::ftruncate(Libc::File_descriptor *fd, ::off_t length) +int Libc::Vfs_plugin::ftruncate(File_descriptor *fd, ::off_t length) { Vfs::Vfs_handle *handle = vfs_handle(fd); - _vfs_sync(*handle); + if (fd->modified) { + _vfs_sync(*handle); + fd->modified = false; + } typedef Vfs::File_io_service::Ftruncate_result Result; @@ -966,7 +1253,7 @@ int Libc::Vfs_plugin::ftruncate(Libc::File_descriptor *fd, ::off_t length) } -int Libc::Vfs_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) +int Libc::Vfs_plugin::fcntl(File_descriptor *fd, int cmd, long arg) { switch (cmd) { case F_DUPFD_CLOEXEC: @@ -975,18 +1262,16 @@ int Libc::Vfs_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) /* * Allocate free file descriptor locally. */ - Libc::File_descriptor *new_fd = - Libc::file_descriptor_allocator()->alloc(this, 0); + File_descriptor *new_fd = + file_descriptor_allocator()->alloc(this, 0); if (!new_fd) return Errno(EMFILE); - new_fd->path(fd->fd_path); - /* * Use new allocated number as name of file descriptor * duplicate. */ - if (dup2(fd, new_fd) == -1) { - Genode::error("Plugin::fcntl: dup2 unexpectedly failed"); + if (Vfs_plugin::dup2(fd, new_fd) == -1) { + error("Plugin::fcntl: dup2 unexpectedly failed"); return Errno(EINVAL); } @@ -996,21 +1281,33 @@ int Libc::Vfs_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) case F_SETFD: fd->cloexec = arg == FD_CLOEXEC; return 0; case F_GETFL: return fd->flags; - case F_SETFL: fd->flags = arg; return 0; + case F_SETFL: { + /* only the specified flags may be changed */ + long const mask = (O_NONBLOCK | O_APPEND | O_ASYNC | O_FSYNC); + fd->flags = (fd->flags & ~mask) | (arg & mask); + } return 0; default: break; } - Genode::error("fcntl(): command ", cmd, " not supported - vfs"); + error("fcntl(): command ", cmd, " not supported - vfs"); return Errno(EINVAL); } -int Libc::Vfs_plugin::fsync(Libc::File_descriptor *fd) +int Libc::Vfs_plugin::fsync(File_descriptor *fd) { Vfs::Vfs_handle *handle = vfs_handle(fd); - return _vfs_sync(*handle); + if (!fd->modified) { return 0; } + + /* + * XXX checking the return value of _vfs_sync amd returning -1 + * in the EIO case will break the lighttpd or rather the socket_fs + */ + fd->modified = !!_vfs_sync(*handle); + + return 0; } @@ -1021,7 +1318,7 @@ int Libc::Vfs_plugin::symlink(const char *oldpath, const char *newpath) Vfs::Vfs_handle *handle { 0 }; Openlink_result openlink_result = - VFS_THREAD_SAFE(_root_dir.openlink(newpath, true, &handle, _alloc)); + VFS_THREAD_SAFE(_root_fs.openlink(newpath, true, &handle, _alloc)); switch (openlink_result) { case Openlink_result::OPENLINK_OK: @@ -1047,7 +1344,7 @@ int Libc::Vfs_plugin::symlink(const char *oldpath, const char *newpath) handle->handler(&_response_handler); - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -1076,11 +1373,10 @@ int Libc::Vfs_plugin::symlink(const char *oldpath, const char *newpath) } check ( handle, oldpath, count, out_count); do { - Libc::suspend(check); + suspend(check); } while (check.retry); - /* wake up threads blocking for 'queue_*()' or 'write()' */ - Libc::resume_all(); + Plugin::resume_all(); _vfs_sync(*handle); VFS_THREAD_SAFE(handle->close()); @@ -1097,7 +1393,7 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_siz Vfs::Vfs_handle *symlink_handle { 0 }; Vfs::Directory_service::Openlink_result openlink_result = - VFS_THREAD_SAFE(_root_dir.openlink(path, false, &symlink_handle, _alloc)); + VFS_THREAD_SAFE(_root_fs.openlink(path, false, &symlink_handle, _alloc)); switch (openlink_result) { case Vfs::Directory_service::OPENLINK_OK: @@ -1118,7 +1414,7 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_siz symlink_handle->handler(&_response_handler); { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -1138,7 +1434,7 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_siz } check(symlink_handle, buf_size); do { - Libc::suspend(check); + suspend(check); } while (check.retry); } @@ -1148,7 +1444,7 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_siz Vfs::file_size out_len = 0; { - struct Check : Libc::Suspend_functor + struct Check : Suspend_functor { bool retry { false }; @@ -1179,12 +1475,11 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_siz } check(symlink_handle, buf, buf_size, out_len, out_result); do { - Libc::suspend(check); + suspend(check); } while (check.retry); } - /* wake up threads blocking for 'queue_*()' or 'write()' */ - Libc::resume_all(); + Plugin::resume_all(); switch (out_result) { case Result::READ_ERR_AGAIN: return Errno(EAGAIN); @@ -1213,7 +1508,7 @@ int Libc::Vfs_plugin::unlink(char const *path) { typedef Vfs::Directory_service::Unlink_result Result; - switch (VFS_THREAD_SAFE(_root_dir.unlink(path))) { + switch (VFS_THREAD_SAFE(_root_fs.unlink(path))) { case Result::UNLINK_ERR_NO_ENTRY: errno = ENOENT; return -1; case Result::UNLINK_ERR_NO_PERM: errno = EPERM; return -1; case Result::UNLINK_ERR_NOT_EMPTY: errno = ENOTEMPTY; return -1; @@ -1227,25 +1522,25 @@ int Libc::Vfs_plugin::rename(char const *from_path, char const *to_path) { typedef Vfs::Directory_service::Rename_result Result; - if (VFS_THREAD_SAFE(_root_dir.leaf_path(to_path))) { + if (VFS_THREAD_SAFE(_root_fs.leaf_path(to_path))) { - if (VFS_THREAD_SAFE(_root_dir.directory(to_path))) { - if (!VFS_THREAD_SAFE(_root_dir.directory(from_path))) { + if (VFS_THREAD_SAFE(_root_fs.directory(to_path))) { + if (!VFS_THREAD_SAFE(_root_fs.directory(from_path))) { errno = EISDIR; return -1; } - if (VFS_THREAD_SAFE(_root_dir.num_dirent(to_path))) { + if (VFS_THREAD_SAFE(_root_fs.num_dirent(to_path))) { errno = ENOTEMPTY; return -1; } } else { - if (VFS_THREAD_SAFE(_root_dir.directory(from_path))) { + if (VFS_THREAD_SAFE(_root_fs.directory(from_path))) { errno = ENOTDIR; return -1; } } } - switch (VFS_THREAD_SAFE(_root_dir.rename(from_path, to_path))) { + switch (VFS_THREAD_SAFE(_root_fs.rename(from_path, to_path))) { case Result::RENAME_ERR_NO_ENTRY: errno = ENOENT; return -1; case Result::RENAME_ERR_CROSS_FS: errno = EXDEV; return -1; case Result::RENAME_ERR_NO_PERM: errno = EPERM; return -1; @@ -1256,16 +1551,16 @@ int Libc::Vfs_plugin::rename(char const *from_path, char const *to_path) void *Libc::Vfs_plugin::mmap(void *addr_in, ::size_t length, int prot, int flags, - Libc::File_descriptor *fd, ::off_t offset) + File_descriptor *fd, ::off_t offset) { if (prot != PROT_READ && !(prot == (PROT_READ | PROT_WRITE) && flags == MAP_PRIVATE)) { - Genode::error("mmap for prot=", Genode::Hex(prot), " not supported"); + error("mmap for prot=", Hex(prot), " not supported"); errno = EACCES; return (void *)-1; } if (addr_in != 0) { - Genode::error("mmap for predefined address not supported"); + error("mmap for predefined address not supported"); errno = EINVAL; return (void *)-1; } @@ -1275,7 +1570,7 @@ void *Libc::Vfs_plugin::mmap(void *addr_in, ::size_t length, int prot, int flags * 'Vfs::Directory_service::dataspace'. */ - void *addr = Libc::mem_alloc()->alloc(length, PAGE_SHIFT); + void *addr = mem_alloc()->alloc(length, PAGE_SHIFT); if (addr == (void *)-1) { errno = ENOMEM; return (void *)-1; @@ -1289,7 +1584,7 @@ void *Libc::Vfs_plugin::mmap(void *addr_in, ::size_t length, int prot, int flags while (read_remain > 0) { ssize_t length_read = ::pread(fd->libc_fd, read_addr, read_remain, read_offset); if (length_read < 0) { /* error */ - Genode::error("mmap could not obtain file content"); + error("mmap could not obtain file content"); ::munmap(addr, length); errno = EACCES; return (void *)-1; @@ -1306,7 +1601,66 @@ void *Libc::Vfs_plugin::mmap(void *addr_in, ::size_t length, int prot, int flags int Libc::Vfs_plugin::munmap(void *addr, ::size_t) { - Libc::mem_alloc()->free(addr); + mem_alloc()->free(addr); + return 0; +} + + +int Libc::Vfs_plugin::pipe(Libc::File_descriptor *pipefdo[2]) +{ + Absolute_path base_path(Libc::config_pipe()); + if (base_path == "") { + error(__func__, ": pipe fs not mounted"); + return Errno(EACCES); + } + + Libc::File_descriptor *meta_fd { nullptr }; + + { + Absolute_path new_path = base_path; + new_path.append("/new"); + + meta_fd = open(new_path.base(), O_RDONLY, Libc::ANY_FD); + if (!meta_fd) { + Genode::error("failed to create pipe at ", new_path); + return Errno(EACCES); + } + meta_fd->path(new_path.string()); + + char buf[32] { }; + int const n = read(meta_fd, buf, sizeof(buf)-1); + if (n < 1) { + error("failed to read pipe at ", new_path); + close(meta_fd); + return Errno(EACCES); + } + buf[n] = '\0'; + base_path.append("/"); + base_path.append(buf); + } + + auto open_pipe_fd = [&] (auto path_suffix, auto flags) + { + Absolute_path path = base_path; + path.append(path_suffix); + + File_descriptor *fd = open(path.base(), flags, Libc::ANY_FD); + if (!fd) + error("failed to open pipe end at ", path); + else + fd->path(path.string()); + + return fd; + }; + + pipefdo[0] = open_pipe_fd("/out", O_RDONLY); + pipefdo[1] = open_pipe_fd("/in", O_WRONLY); + + close(meta_fd); + + if (!pipefdo[0] || !pipefdo[1]) + return Errno(EACCES); + return 0; } @@ -1354,8 +1708,8 @@ bool Libc::Vfs_plugin::supports_select(int nfds, if (FD_ISSET(fd, readfds) || FD_ISSET(fd, writefds) || FD_ISSET(fd, exceptfds)) { - Libc::File_descriptor *fdo = - Libc::file_descriptor_allocator()->find_by_libc_fd(fd); + File_descriptor *fdo = + file_descriptor_allocator()->find_by_libc_fd(fd); if (fdo && (fdo->plugin == this)) return true; @@ -1382,8 +1736,8 @@ int Libc::Vfs_plugin::select(int nfds, for (int fd = 0; fd < nfds; ++fd) { - Libc::File_descriptor *fdo = - Libc::file_descriptor_allocator()->find_by_libc_fd(fd); + File_descriptor *fdo = + file_descriptor_allocator()->find_by_libc_fd(fd); /* handle only fds that belong to this plugin */ if (!fdo || (fdo->plugin != this)) @@ -1397,7 +1751,7 @@ int Libc::Vfs_plugin::select(int nfds, FD_SET(fd, readfds); ++nready; } else { - Libc::notify_read_ready(handle); + notify_read_ready(handle); } } diff --git a/repos/libports/src/lib/libc/vfs_plugin.h b/repos/libports/src/lib/libc/vfs_plugin.h deleted file mode 100644 index d175b4591..000000000 --- a/repos/libports/src/lib/libc/vfs_plugin.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * \brief Libc plugin for using a process-local virtual file system - * \author Norman Feske - * \author Emery Hemingway - * \author Christian Helmuth - * \date 2014-04-09 - */ - -/* - * Copyright (C) 2014-2019 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 _LIBC_VFS__PLUGIN_H_ -#define _LIBC_VFS__PLUGIN_H_ - -/* Genode includes */ -#include <libc/component.h> - -/* libc includes */ -#include <fcntl.h> -#include <unistd.h> - -/* libc plugin interface */ -#include <libc-plugin/plugin.h> -#include <libc-plugin/fd_alloc.h> - -/* local includes */ -#include "task.h" -#include "libc_errno.h" - - -namespace Libc { class Vfs_plugin; } - - -class Libc::Vfs_plugin : public Libc::Plugin -{ - private: - - Genode::Allocator &_alloc; - Vfs::File_system &_root_dir; - Vfs::Io_response_handler &_response_handler; - - /** - * Sync a handle and propagate errors - */ - int _vfs_sync(Vfs::Vfs_handle&); - - public: - - Vfs_plugin(Libc::Env &env, - Genode::Allocator &alloc, - Vfs::Io_response_handler &handler) - : - _alloc(alloc), _root_dir(env.vfs()), _response_handler(handler) - { } - - ~Vfs_plugin() final { } - - bool root_dir_has_dirents() const { return _root_dir.num_dirent("/") > 0; } - - bool supports_access(const char *, int) override { return true; } - bool supports_mkdir(const char *, mode_t) override { return true; } - bool supports_open(const char *, int) override { return true; } - bool supports_poll() override { return true; } - bool supports_readlink(const char *, char *, ::size_t) override { return true; } - bool supports_rename(const char *, const char *) override { return true; } - bool supports_rmdir(const char *) override { return true; } - bool supports_stat(const char *) override { return true; } - bool supports_symlink(const char *, const char *) override { return true; } - bool supports_unlink(const char *) override { return true; } - bool supports_mmap() override { return true; } - - bool supports_select(int nfds, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - struct timeval *timeout) override; - - Libc::File_descriptor *open(const char *, int, int libc_fd); - - Libc::File_descriptor *open(const char *path, int flags) override - { - return open(path, flags, Libc::ANY_FD); - } - - int access(char const *, int) override; - int close(Libc::File_descriptor *) override; - int dup2(Libc::File_descriptor *, Libc::File_descriptor *) override; - int fcntl(Libc::File_descriptor *, int, long) override; - int fstat(Libc::File_descriptor *, struct stat *) override; - int fstatfs(Libc::File_descriptor *, struct statfs *) override; - int fsync(Libc::File_descriptor *fd) override; - int ftruncate(Libc::File_descriptor *, ::off_t) override; - ssize_t getdirentries(Libc::File_descriptor *, char *, ::size_t , ::off_t *) override; - int ioctl(Libc::File_descriptor *, int , char *) override; - ::off_t lseek(Libc::File_descriptor *fd, ::off_t offset, int whence) override; - int mkdir(const char *, mode_t) override; - bool poll(File_descriptor &fdo, struct pollfd &pfd) override; - ssize_t read(Libc::File_descriptor *, void *, ::size_t) override; - ssize_t readlink(const char *, char *, ::size_t) override; - int rename(const char *, const char *) override; - int rmdir(const char *) override; - int stat(const char *, struct stat *) override; - int symlink(const char *, const char *) override; - int unlink(const char *) override; - ssize_t write(Libc::File_descriptor *, const void *, ::size_t ) override; - void *mmap(void *, ::size_t, int, int, Libc::File_descriptor *, ::off_t) override; - int munmap(void *, ::size_t) override; - int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) override; -}; - -#endif diff --git a/repos/libports/src/lib/libc_fatfs/plugin.cc b/repos/libports/src/lib/libc_fatfs/plugin.cc deleted file mode 100644 index 5864e22fc..000000000 --- a/repos/libports/src/lib/libc_fatfs/plugin.cc +++ /dev/null @@ -1,805 +0,0 @@ -/* - * \brief FATFS libc plugin - * \author Christian Prochaska - * \date 2011-05-27 - */ - -/* - * Copyright (C) 2011-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. - */ - -/* Genode includes */ -#include <base/env.h> -#include <base/heap.h> -#include <base/log.h> -#include <os/path.h> - -/* libc includes */ -#include <errno.h> -#include <dirent.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* libc plugin interface */ -#include <libc-plugin/plugin.h> -#include <libc-plugin/fd_alloc.h> - -#include <fatfs/block.h> - -namespace Fatfs { extern "C" { -#include <fatfs/ff.h> -} } - -static bool const verbose = false; - - -namespace { - - -class Plugin_context : public Libc::Plugin_context -{ - private: - - char *_filename; /* needed for fstat() */ - int _fd_flags; - int _status_flags; - - public: - - Plugin_context(const char *filename) - : _fd_flags(0), _status_flags(0) - { - _filename = (char*)malloc(::strlen(filename) + 1); - ::strcpy(_filename, filename); - } - - virtual ~Plugin_context() - { - ::free(_filename); - } - - const char *filename() { return _filename; } - - /** - * Set/get file descriptor flags - */ - void fd_flags(int flags) { _fd_flags = flags; } - int fd_flags() { return _fd_flags; } - - /** - * Set/get file status status flags - */ - void status_flags(int flags) { _status_flags = flags; } - int status_flags() { return _status_flags; } -}; - - -static inline Plugin_context *context(Libc::File_descriptor *fd) -{ - return fd->context ? static_cast<Plugin_context *>(fd->context) : 0; -} - - -class File_plugin_context : public Plugin_context -{ - private: - - Fatfs::FIL _fatfs_file; - - public: - - /** - * Constructor - * - * \param filename - * \param fatfs_file file object used for interacting with the - * file API of fatfs - */ - File_plugin_context(const char *filename, Fatfs::FIL fatfs_file) : - Plugin_context(filename), _fatfs_file(fatfs_file) { } - - Fatfs::FIL *fatfs_file() { return &_fatfs_file; } -}; - - -class Directory_plugin_context : public Plugin_context -{ - private: - - Fatfs::DIR _fatfs_dir; - - public: - - /** - * Constructor - * - * \param filename - * \param fatfs_dir dir object used for interacting with the - * file API of fatfs - */ - Directory_plugin_context(const char *filename, Fatfs::DIR fatfs_dir) : - Plugin_context(filename), _fatfs_dir(fatfs_dir) { } - - Fatfs::DIR *fatfs_dir() { return &_fatfs_dir; } -}; - - -class Plugin : public Libc::Plugin -{ - private: - - Genode::Constructible<Genode::Heap> _heap; - - Fatfs::FATFS _fatfs; - - Fatfs::FIL *_get_fatfs_file(Libc::File_descriptor *fd) - { - File_plugin_context *file_plugin_context = - dynamic_cast<File_plugin_context*>(context(fd)); - if (!file_plugin_context) { - return 0; - } - return file_plugin_context->fatfs_file(); - } - - Fatfs::DIR *_get_fatfs_dir(Libc::File_descriptor *fd) - { - Directory_plugin_context *directory_plugin_context = - dynamic_cast<Directory_plugin_context*>(context(fd)); - if (!directory_plugin_context) { - return 0; - } - return directory_plugin_context->fatfs_dir(); - } - - /* - * Override libc_vfs - */ - enum { PLUGIN_PRIORITY = 1 }; - - public: - - /** - * Constructor - */ - Plugin() : Libc::Plugin(PLUGIN_PRIORITY) { } - - ~Plugin() - { - /* unmount the file system */ - Fatfs::f_unmount(""); - } - - void init(Genode::Env &env) override - { - _heap.construct(env.ram(), env.rm()); - - Fatfs::block_init(env, *_heap); - - /* mount the file system */ - if (verbose) - Genode::log(__func__, ": mounting device ..."); - - if (f_mount(&_fatfs, "", 0) != Fatfs::FR_OK) { - Genode::error("mount failed"); - } - } - - /* - * TODO: decide if the file named <path> shall be handled by this plugin - */ - - bool supports_mkdir(const char *path, mode_t) override - { - if (verbose) - Genode::log(__func__, ": path=", path); - return true; - } - - bool supports_open(const char *pathname, int flags) override - { - if (verbose) - Genode::log(__func__, ": pathname=", pathname); - return true; - } - - bool supports_rename(const char *oldpath, const char *newpath) override - { - if (verbose) - Genode::log(__func__, ": oldpath=", oldpath, ", newpath=", newpath); - return true; - } - - bool supports_rmdir(const char *path) override - { - if (verbose) - Genode::log(__func__, ": path=", path); - return true; - } - - bool supports_stat(const char *path) override - { - if (verbose) - Genode::log(__func__, ": path=", path); - return true; - } - - bool supports_unlink(const char *path) override - { - if (verbose) - Genode::log(__func__, ": path=", path); - return true; - } - - bool supports_symlink(const char *, const char *) override - { - return true; - } - - int close(Libc::File_descriptor *fd) override - { - using namespace Fatfs; - - FIL *fatfs_file = _get_fatfs_file(fd); - - if (!fatfs_file){ - /* directory */ - Genode::destroy(&*_heap, context(fd)); - Libc::file_descriptor_allocator()->free(fd); - return 0; - } - - FRESULT res = f_close(fatfs_file); - - Genode::destroy(&*_heap, context(fd)); - Libc::file_descriptor_allocator()->free(fd); - - switch(res) { - case FR_OK: - return 0; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_INVALID_OBJECT: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_close() returned an unexpected error code"); - return -1; - } - } - - int fcntl(Libc::File_descriptor *fd, int cmd, long arg) override - { - switch (cmd) { - case F_GETFD: return context(fd)->fd_flags(); - case F_SETFD: context(fd)->fd_flags(arg); return 0; - case F_GETFL: return context(fd)->status_flags(); - default: Genode::error("fcntl(): command ", cmd, " not supported", cmd); return -1; - } - } - - int fstat(Libc::File_descriptor *fd, struct stat *buf) override - { - return stat(context(fd)->filename(), buf); - } - - int fstatfs(Libc::File_descriptor *, struct statfs *buf) override - { - /* libc's opendir() fails if _fstatfs() returns -1, so we return 0 here */ - if (verbose) - Genode::warning("_fstatfs() called - not yet implemented"); - return 0; - } - - int fsync(Libc::File_descriptor *fd) override - { - using namespace Fatfs; - - FRESULT res = f_sync(_get_fatfs_file(fd)); - - switch(res) { - case FR_OK: - return 0; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_INVALID_OBJECT: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_sync() returned an unexpected error code"); - return -1; - } - } - - int ftruncate(Libc::File_descriptor *fd, ::off_t length) override - { - using namespace Fatfs; - - /* 'f_truncate()' truncates to the current seek pointer */ - - if (lseek(fd, length, SEEK_SET) == -1) - return -1; - - FRESULT res = f_truncate(_get_fatfs_file(fd)); - - switch(res) { - case FR_OK: - return 0; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_INVALID_OBJECT: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_truncate() returned an unexpected error code"); - return -1; - } - } - - ssize_t getdirentries(Libc::File_descriptor *fd, char *buf, - ::size_t nbytes, ::off_t *basep) override - { - using namespace Fatfs; - - if (nbytes < sizeof(struct dirent)) { - Genode::error(__func__, ": buf too small"); - errno = ENOMEM; - return -1; - } - - struct dirent *dirent = (struct dirent *)buf; - ::memset(dirent, 0, sizeof(struct dirent)); - - FILINFO fatfs_file_info; - - FRESULT res = f_readdir(_get_fatfs_dir(fd), &fatfs_file_info); - switch(res) { - case FR_OK: - break; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_INVALID_OBJECT: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_readdir() returned an unexpected error code"); - return -1; - } - - if (fatfs_file_info.fname[0] == 0) { /* no (more) entries */ - if (verbose) - Genode::log(__func__, ": no more dir entries"); - /* TODO: reset the f_readdir() index? */ - return 0; - } - - dirent->d_ino = 1; /* libc's readdir() wants an inode number */ - - if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR) - dirent->d_type = DT_DIR; - else - dirent->d_type = DT_REG; - - dirent->d_reclen = sizeof(struct dirent); - - ::strncpy(dirent->d_name, fatfs_file_info.fname, sizeof(dirent->d_name)); - - dirent->d_namlen = ::strlen(dirent->d_name); - - if (verbose) - Genode::log("found dir entry ", Genode::Cstring(dirent->d_name)); - - *basep += sizeof(struct dirent); - return sizeof(struct dirent); - } - - ::off_t lseek(Libc::File_descriptor *fd, ::off_t offset, int whence) override - { - using namespace Fatfs; - - switch(whence) { - case SEEK_CUR: - offset += f_tell(_get_fatfs_file(fd)); - break; - case SEEK_END: - offset += f_size(_get_fatfs_file(fd)); - break; - default: - break; - } - - FRESULT res = f_lseek(_get_fatfs_file(fd), offset); - - switch(res) { - case FR_OK: - /* according to the FatFs documentation this can happen */ - if ((off_t)f_tell(_get_fatfs_file(fd)) != offset) { - errno = EINVAL; - return -1; - } - return offset; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_INVALID_OBJECT: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_lseek() returned an unexpected error code"); - return -1; - } - } - - int mkdir(const char *path, mode_t mode) override - { - using namespace Fatfs; - - FRESULT res = f_mkdir(path); - - switch(res) { - case FR_OK: - return 0; - case FR_NO_PATH: - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - errno = ENOENT; - return -1; - case FR_DENIED: - case FR_WRITE_PROTECTED: - errno = EACCES; - return -1; - case FR_EXIST: - errno = EEXIST; - return -1; - case FR_NOT_READY: - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_ENABLED: - case FR_NO_FILESYSTEM: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_mkdir() returned an unexpected error code"); - return -1; - } - } - - Libc::File_descriptor *open(const char *pathname, int flags) override - { - using namespace Fatfs; - - if (verbose) - Genode::log(__func__, ": pathname=", pathname); - - FIL fatfs_file; - BYTE fatfs_flags = 0; - - /* convert libc flags to fatfs flags */ - if (((flags & O_RDONLY) == O_RDONLY) || ((flags & O_RDWR) == O_RDWR)) - fatfs_flags |= FA_READ; - - if (((flags & O_WRONLY) == O_WRONLY) || ((flags & O_RDWR) == O_RDWR)) - fatfs_flags |= FA_WRITE; - - if ((flags & O_CREAT) == O_CREAT) { - if ((flags & O_EXCL) == O_EXCL) - fatfs_flags |= FA_CREATE_NEW; - else - fatfs_flags |= FA_OPEN_ALWAYS; - } - - FRESULT res = f_open(&fatfs_file, pathname, fatfs_flags); - - switch(res) { - case FR_OK: { - Plugin_context *context = new (&*_heap) - File_plugin_context(pathname, fatfs_file); - context->status_flags(flags); - Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->alloc(this, context); - if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1)) - return 0; - return fd; - } - case FR_NO_FILE: { - /* - * libc's opendir() calls open() on directories, but - * that's not supported by f_open(). So we call - * f_opendir() in case the file is a directory. - */ - Fatfs::DIR fatfs_dir; - FRESULT f_opendir_res = f_opendir(&fatfs_dir, pathname); - if (verbose) - Genode::log(__func__, ": opendir res=", (int)f_opendir_res); - switch(f_opendir_res) { - case FR_OK: { - Plugin_context *context = new (&*_heap) - Directory_plugin_context(pathname, fatfs_dir); - context->status_flags(flags); - Libc::File_descriptor *f = - Libc::file_descriptor_allocator()->alloc(this, context); - if (verbose) - Genode::log(__func__, ": new fd=", f->libc_fd); - return f; - - } - case FR_NO_PATH: - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - errno = ENOENT; - return 0; - case FR_NOT_READY: - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_ENABLED: - case FR_NO_FILESYSTEM: - errno = EIO; - return 0; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_opendir() returned an unexpected error code"); - return 0; - } - } - case FR_NO_PATH: - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - errno = ENOENT; - return 0; - case FR_EXIST: - errno = EEXIST; - return 0; - case FR_DENIED: - case FR_WRITE_PROTECTED: - errno = EACCES; - return 0; - case FR_NOT_READY: - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_ENABLED: - case FR_NO_FILESYSTEM: - errno = EIO; - return 0; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_open() returned an unexpected error code"); - return 0; - } - } - - int rename(const char *oldpath, const char *newpath) override - { - using namespace Fatfs; - - FRESULT res = f_rename(oldpath, newpath); - - /* if newpath already exists - try to unlink it once */ - if (res == FR_EXIST) { - f_unlink(newpath); - res = f_rename(oldpath, newpath); - } - - switch(res) { - case FR_OK: - return 0; - case FR_NO_FILE: - case FR_NO_PATH: - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - errno = ENOENT; - return 0; - case FR_EXIST: - errno = EEXIST; - return -1; - case FR_DENIED: - case FR_WRITE_PROTECTED: - errno = EACCES; - return -1; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_NOT_ENABLED: - case FR_NO_FILESYSTEM: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_rename() returned an unexpected error code"); - return -1; - } - } - - ssize_t read(Libc::File_descriptor *fd, void *buf, ::size_t count) override - { - using namespace Fatfs; - - UINT result; - FRESULT res = f_read(_get_fatfs_file(fd), buf, count, &result); - - switch(res) { - case FR_OK: - return result; - case FR_DENIED: - errno = EACCES; - return -1; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_INVALID_OBJECT: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_read() returned an unexpected error code"); - return -1; - } - } - - int stat(const char *path, struct stat *buf) override - { - using namespace Fatfs; - - FILINFO file_info; - - ::memset(buf, 0, sizeof(struct stat)); - - /* 'f_stat()' does not work for the '/' directory */ - if (strcmp(path, "/") == 0) { - buf->st_mode |= S_IFDIR; - return 0; - } - - FRESULT res = f_stat(path, &file_info); - - switch(res) { - case FR_OK: - break; - case FR_NO_FILE: - case FR_NO_PATH: - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - errno = ENOENT; - return -1; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_NOT_ENABLED: - case FR_NO_FILESYSTEM: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_stat() returned an unexpected error code"); - return -1; - } - - /* convert FILINFO to struct stat */ - buf->st_size = file_info.fsize; - - if ((file_info.fattrib & AM_DIR) == AM_DIR) { - buf->st_mode |= S_IFDIR; - if (verbose) - Genode::log(__func__, ": type: directory"); - } else { - buf->st_mode |= S_IFREG; - if (verbose) - Genode::log(__func__, ": type: regular file with a " - "size of ", buf->st_size, " bytes"); - } - /* TODO: handle more attributes */ - - struct tm tm; - ::memset(&tm, 0, sizeof(tm)); - - tm.tm_year = ((file_info.fdate & 0b1111111000000000) >> 9) + 80; - tm.tm_mon = (file_info.fdate & 0b0000000111100000) >> 5; - tm.tm_mday = (file_info.fdate & 0b0000000000011111); - tm.tm_hour = (file_info.ftime & 0b1111100000000000) >> 11; - tm.tm_min = (file_info.ftime & 0b0000011111100000) >> 5; - tm.tm_sec = (file_info.ftime & 0b0000000000011111) * 2; - - if (verbose) - Genode::log("last modified: ", - 1900 + tm.tm_year, "-", tm.tm_mon, "-", tm.tm_mday, " ", - tm.tm_hour, ":", tm.tm_min, ":", tm.tm_sec); - - buf->st_mtime = mktime(&tm); - if (buf->st_mtime == -1) - Genode::error("mktime() returned -1, the file modification time reported by stat() will be incorrect"); - - return 0; - } - - int unlink(const char *path) override - { - using namespace Fatfs; - - FRESULT res = f_unlink(path); - - switch(res) { - case FR_OK: - return 0; - case FR_NO_FILE: - case FR_NO_PATH: - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - errno = ENOENT; - return -1; - case FR_DENIED: - case FR_WRITE_PROTECTED: - errno = EACCES; - return -1; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_NOT_ENABLED: - case FR_NO_FILESYSTEM: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_unlink() returned an unexpected error code"); - return -1; - } - } - - int rmdir(const char *path) override - { - return unlink(path); - } - - ssize_t write(Libc::File_descriptor *fd, const void *buf, ::size_t count) override - { - using namespace Fatfs; - - UINT result; - FRESULT res = f_write(_get_fatfs_file(fd), buf, count, &result); - - switch(res) { - case FR_OK: - return result; - case FR_DENIED: - errno = EACCES; - return -1; - case FR_DISK_ERR: - case FR_INT_ERR: - case FR_NOT_READY: - case FR_INVALID_OBJECT: - errno = EIO; - return -1; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_write() returned an unexpected error code"); - return -1; - } - } - - int symlink(const char *, const char *) override - { - errno = EPERM; - return -1; - } -}; - - -} /* unnamed namespace */ - - -void __attribute__((constructor)) init_libc_fatfs(void) -{ - static Plugin plugin; -} diff --git a/repos/libports/src/lib/lwip/platform/sys_arch.cc b/repos/libports/src/lib/lwip/platform/sys_arch.cc index 61e4c298c..c3b7087f3 100644 --- a/repos/libports/src/lib/lwip/platform/sys_arch.cc +++ b/repos/libports/src/lib/lwip/platform/sys_arch.cc @@ -48,7 +48,7 @@ namespace Lwip { Sys_timer(Genode::Timeout_scheduler &timer) : timer(timer) { } }; - static Genode::Constructible<Sys_timer> _sys_timer; + static Sys_timer *sys_timer_ptr; void genode_init(Genode::Allocator &heap, Genode::Timeout_scheduler &timer) { @@ -56,7 +56,10 @@ namespace Lwip { !heap.need_size_for_free()); _heap = &heap; - _sys_timer.construct(timer); + + static Sys_timer sys_timer(timer); + sys_timer_ptr = &sys_timer; + lwip_init(); } } @@ -93,7 +96,7 @@ extern "C" { } u32_t sys_now(void) { - return Lwip::_sys_timer->timer.curr_time().trunc_to_plain_ms().value; } + return Lwip::sys_timer_ptr->timer.curr_time().trunc_to_plain_ms().value; } void genode_memcpy(void *dst, const void *src, size_t len) { Genode::memcpy(dst, src, len); } diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp index 70254a631..f13c43f7a 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp @@ -1,11 +1,12 @@ /* * \brief QNitpickerPlatformWindow * \author Christian Prochaska + * \author Christian Helmuth * \date 2013-05-08 */ /* - * Copyright (C) 2013-2017 Genode Labs GmbH + * Copyright (C) 2013-2019 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. @@ -103,210 +104,269 @@ void QNitpickerPlatformWindow::_process_touch_events(QList<Input::Event> const & } -static Qt::Key translate_keycode(Input::Keycode key) +static Qt::Key key_from_unicode(unsigned unicode) { - switch (key) { - case Input::KEY_ENTER: return Qt::Key_Return; - case Input::KEY_KPENTER: return Qt::Key_Enter; - case Input::KEY_ESC: return Qt::Key_Escape; - case Input::KEY_TAB: return Qt::Key_Tab; - case Input::KEY_BACKSPACE: return Qt::Key_Backspace; - case Input::KEY_INSERT: return Qt::Key_Insert; - case Input::KEY_DELETE: return Qt::Key_Delete; - case Input::KEY_PRINT: return Qt::Key_Print; - case Input::KEY_CLEAR: return Qt::Key_Clear; - case Input::KEY_HOME: return Qt::Key_Home; - case Input::KEY_END: return Qt::Key_End; - case Input::KEY_LEFT: return Qt::Key_Left; - case Input::KEY_UP: return Qt::Key_Up; - case Input::KEY_RIGHT: return Qt::Key_Right; - case Input::KEY_DOWN: return Qt::Key_Down; - case Input::KEY_PAGEUP: return Qt::Key_PageUp; - case Input::KEY_PAGEDOWN: return Qt::Key_PageDown; - case Input::KEY_LEFTSHIFT: return Qt::Key_Shift; - case Input::KEY_LEFTCTRL: return Qt::Key_Control; - case Input::KEY_LEFTMETA: return Qt::Key_Meta; - case Input::KEY_LEFTALT: return Qt::Key_Alt; - case Input::KEY_RIGHTALT: return Qt::Key_AltGr; - case Input::KEY_CAPSLOCK: return Qt::Key_CapsLock; - case Input::KEY_F1: return Qt::Key_F1; - case Input::KEY_F2: return Qt::Key_F2; - case Input::KEY_F3: return Qt::Key_F3; - case Input::KEY_F4: return Qt::Key_F4; - case Input::KEY_F5: return Qt::Key_F5; - case Input::KEY_F6: return Qt::Key_F6; - case Input::KEY_F7: return Qt::Key_F7; - case Input::KEY_F8: return Qt::Key_F8; - case Input::KEY_F9: return Qt::Key_F9; - case Input::KEY_F10: return Qt::Key_F10; - case Input::KEY_F11: return Qt::Key_F11; - case Input::KEY_F12: return Qt::Key_F12; - case Input::KEY_SPACE: return Qt::Key_Space; - case Input::KEY_0: return Qt::Key_0; - case Input::KEY_1: return Qt::Key_1; - case Input::KEY_2: return Qt::Key_2; - case Input::KEY_3: return Qt::Key_3; - case Input::KEY_4: return Qt::Key_4; - case Input::KEY_5: return Qt::Key_5; - case Input::KEY_6: return Qt::Key_6; - case Input::KEY_7: return Qt::Key_7; - case Input::KEY_8: return Qt::Key_8; - case Input::KEY_9: return Qt::Key_9; - case Input::KEY_A: return Qt::Key_A; - case Input::KEY_B: return Qt::Key_B; - case Input::KEY_C: return Qt::Key_C; - case Input::KEY_D: return Qt::Key_D; - case Input::KEY_E: return Qt::Key_E; - case Input::KEY_F: return Qt::Key_F; - case Input::KEY_G: return Qt::Key_G; - case Input::KEY_H: return Qt::Key_H; - case Input::KEY_I: return Qt::Key_I; - case Input::KEY_J: return Qt::Key_J; - case Input::KEY_K: return Qt::Key_K; - case Input::KEY_L: return Qt::Key_L; - case Input::KEY_M: return Qt::Key_M; - case Input::KEY_N: return Qt::Key_N; - case Input::KEY_O: return Qt::Key_O; - case Input::KEY_P: return Qt::Key_P; - case Input::KEY_Q: return Qt::Key_Q; - case Input::KEY_R: return Qt::Key_R; - case Input::KEY_S: return Qt::Key_S; - case Input::KEY_T: return Qt::Key_T; - case Input::KEY_U: return Qt::Key_U; - case Input::KEY_V: return Qt::Key_V; - case Input::KEY_W: return Qt::Key_W; - case Input::KEY_X: return Qt::Key_X; - case Input::KEY_Y: return Qt::Key_Y; - case Input::KEY_Z: return Qt::Key_Z; - case Input::KEY_BACK: return Qt::Key_Back; - case Input::KEY_FORWARD: return Qt::Key_Forward; + /* special keys: function-key unicodes */ + switch (unicode) { + case 0x0008: return Qt::Key_Backspace; + case 0x0009: return Qt::Key_Tab; + case 0x000a: return Qt::Key_Return; + case 0x001b: return Qt::Key_Escape; + case 0xf700: return Qt::Key_Up; + case 0xf701: return Qt::Key_Down; + case 0xf702: return Qt::Key_Left; + case 0xf703: return Qt::Key_Right; + case 0xf704: return Qt::Key_F1; + case 0xf705: return Qt::Key_F2; + case 0xf706: return Qt::Key_F3; + case 0xf707: return Qt::Key_F4; + case 0xf708: return Qt::Key_F5; + case 0xf709: return Qt::Key_F6; + case 0xf70a: return Qt::Key_F7; + case 0xf70b: return Qt::Key_F8; + case 0xf70c: return Qt::Key_F9; + case 0xf70d: return Qt::Key_F10; + case 0xf70e: return Qt::Key_F11; + case 0xf70f: return Qt::Key_F12; + case 0xf727: return Qt::Key_Insert; + case 0xf728: return Qt::Key_Delete; + case 0xf729: return Qt::Key_Home; + case 0xf72b: return Qt::Key_End; + case 0xf72c: return Qt::Key_PageUp; + case 0xf72d: return Qt::Key_PageDown; default: break; }; + + /* + * Qt key enums are equal to the corresponding Unicode codepoints of the + * upper-case character. + */ + + /* printable keys */ + if (unicode >= (unsigned)Qt::Key_Space && unicode <= (unsigned)Qt::Key_ydiaeresis) + return Qt::Key(QChar(unicode).toUpper().unicode()); + return Qt::Key_unknown; } +QNitpickerPlatformWindow::Mapped_key QNitpickerPlatformWindow::_map_key(Input::Keycode key, + Codepoint codepoint, + Mapped_key::Event e) +{ + /* non-printable key mappings */ + switch (key) { + case Input::KEY_ENTER: return Mapped_key { Qt::Key_Return }; + case Input::KEY_KPENTER: return Mapped_key { Qt::Key_Return }; /* resolves aliasing on repeat */ + case Input::KEY_ESC: return Mapped_key { Qt::Key_Escape }; + case Input::KEY_TAB: return Mapped_key { Qt::Key_Tab }; + case Input::KEY_BACKSPACE: return Mapped_key { Qt::Key_Backspace }; + case Input::KEY_INSERT: return Mapped_key { Qt::Key_Insert }; + case Input::KEY_DELETE: return Mapped_key { Qt::Key_Delete }; + case Input::KEY_PRINT: return Mapped_key { Qt::Key_Print }; + case Input::KEY_CLEAR: return Mapped_key { Qt::Key_Clear }; + case Input::KEY_HOME: return Mapped_key { Qt::Key_Home }; + case Input::KEY_END: return Mapped_key { Qt::Key_End }; + case Input::KEY_LEFT: return Mapped_key { Qt::Key_Left }; + case Input::KEY_UP: return Mapped_key { Qt::Key_Up }; + case Input::KEY_RIGHT: return Mapped_key { Qt::Key_Right }; + case Input::KEY_DOWN: return Mapped_key { Qt::Key_Down }; + case Input::KEY_PAGEUP: return Mapped_key { Qt::Key_PageUp }; + case Input::KEY_PAGEDOWN: return Mapped_key { Qt::Key_PageDown }; + case Input::KEY_LEFTSHIFT: return Mapped_key { Qt::Key_Shift }; + case Input::KEY_RIGHTSHIFT: return Mapped_key { Qt::Key_Shift }; + case Input::KEY_LEFTCTRL: return Mapped_key { Qt::Key_Control }; + case Input::KEY_RIGHTCTRL: return Mapped_key { Qt::Key_Control }; + case Input::KEY_LEFTMETA: return Mapped_key { Qt::Key_Meta }; + case Input::KEY_RIGHTMETA: return Mapped_key { Qt::Key_Meta }; + case Input::KEY_LEFTALT: return Mapped_key { Qt::Key_Alt }; + case Input::KEY_RIGHTALT: return Mapped_key { Qt::Key_AltGr }; + case Input::KEY_COMPOSE: return Mapped_key { Qt::Key_Menu }; + case Input::KEY_CAPSLOCK: return Mapped_key { Qt::Key_CapsLock }; + case Input::KEY_SYSRQ: return Mapped_key { Qt::Key_SysReq }; + case Input::KEY_SCROLLLOCK: return Mapped_key { Qt::Key_ScrollLock }; + case Input::KEY_PAUSE: return Mapped_key { Qt::Key_Pause }; + case Input::KEY_F1: return Mapped_key { Qt::Key_F1 }; + case Input::KEY_F2: return Mapped_key { Qt::Key_F2 }; + case Input::KEY_F3: return Mapped_key { Qt::Key_F3 }; + case Input::KEY_F4: return Mapped_key { Qt::Key_F4 }; + case Input::KEY_F5: return Mapped_key { Qt::Key_F5 }; + case Input::KEY_F6: return Mapped_key { Qt::Key_F6 }; + case Input::KEY_F7: return Mapped_key { Qt::Key_F7 }; + case Input::KEY_F8: return Mapped_key { Qt::Key_F8 }; + case Input::KEY_F9: return Mapped_key { Qt::Key_F9 }; + case Input::KEY_F10: return Mapped_key { Qt::Key_F10 }; + case Input::KEY_F11: return Mapped_key { Qt::Key_F11 }; + case Input::KEY_F12: return Mapped_key { Qt::Key_F12 }; + case Input::KEY_F13: return Mapped_key { Qt::Key_F13 }; + case Input::KEY_F14: return Mapped_key { Qt::Key_F14 }; + case Input::KEY_F15: return Mapped_key { Qt::Key_F15 }; + case Input::KEY_F16: return Mapped_key { Qt::Key_F16 }; + case Input::KEY_F17: return Mapped_key { Qt::Key_F17 }; + case Input::KEY_F18: return Mapped_key { Qt::Key_F18 }; + case Input::KEY_F19: return Mapped_key { Qt::Key_F19 }; + case Input::KEY_F20: return Mapped_key { Qt::Key_F20 }; + case Input::KEY_F21: return Mapped_key { Qt::Key_F21 }; + case Input::KEY_F22: return Mapped_key { Qt::Key_F22 }; + case Input::KEY_F23: return Mapped_key { Qt::Key_F23 }; + case Input::KEY_F24: return Mapped_key { Qt::Key_F24 }; + case Input::KEY_BACK: return Mapped_key { Qt::Key_Back }; + case Input::KEY_FORWARD: return Mapped_key { Qt::Key_Forward }; + case Input::KEY_VOLUMEDOWN: return Mapped_key { Qt::Key_VolumeDown }; + case Input::KEY_MUTE: return Mapped_key { Qt::Key_VolumeMute }; + case Input::KEY_VOLUMEUP: return Mapped_key { Qt::Key_VolumeUp }; + case Input::KEY_PREVIOUSSONG: return Mapped_key { Qt::Key_MediaPrevious }; + case Input::KEY_PLAYPAUSE: return Mapped_key { Qt::Key_MediaTogglePlayPause }; + case Input::KEY_NEXTSONG: return Mapped_key { Qt::Key_MediaNext }; + + default: break; + }; + + /* + * We remember the mapping of pressed keys (but not repeated codepoints) in + * '_pressed' to derive the release mapping. + */ + + switch (e) { + case Mapped_key::PRESSED: + case Mapped_key::REPEAT: + { + Qt::Key const qt_key = key_from_unicode(codepoint.value); + if (qt_key != Qt::Key_unknown) { + /* do not insert repeated codepoints */ + if (e == Mapped_key::PRESSED) + _pressed.insert(key, qt_key); + + return Mapped_key { qt_key, codepoint }; + } + } break; + + case Mapped_key::RELEASED: + if (Qt::Key qt_key = _pressed.take(key)) { + return Mapped_key { qt_key }; + } + break; + } + + /* dead keys and aborted sequences end up here */ + Genode::warning("key (", Input::key_name(key), ",", (unsigned)key, + ",U+", Genode::Hex((unsigned short)codepoint.value, + Genode::Hex::OMIT_PREFIX, Genode::Hex::PAD), + ") lacks Qt mapping"); + return Mapped_key { Qt::Key_unknown, codepoint }; +} + + +void QNitpickerPlatformWindow::_key_event(Input::Keycode key, Codepoint codepoint, + Mapped_key::Event e) +{ + bool const pressed = e != Mapped_key::RELEASED; + + Qt::KeyboardModifier current_modifier = Qt::NoModifier; + + /* FIXME ignores two keys for one modifier were pressed and only one was released */ + switch (key) { + case Input::KEY_LEFTALT: current_modifier = Qt::AltModifier; break; + case Input::KEY_LEFTCTRL: + case Input::KEY_RIGHTCTRL: current_modifier = Qt::ControlModifier; break; + case Input::KEY_LEFTSHIFT: + case Input::KEY_RIGHTSHIFT: current_modifier = Qt::ShiftModifier; break; + default: break; + } + + _keyboard_modifiers.setFlag(current_modifier, pressed); + + QEvent::Type const event_type = pressed ? QEvent::KeyPress : QEvent::KeyRelease; + Mapped_key const mapped_key = _map_key(key, codepoint, e); + unsigned const unicode = mapped_key.codepoint.valid() + ? mapped_key.codepoint.value : 0; + bool const autorepeat = e == Mapped_key::REPEAT; + + QWindowSystemInterface::handleExtendedKeyEvent(window(), + event_type, + mapped_key.key, + _keyboard_modifiers, + key, 0, int(_keyboard_modifiers), + unicode ? QString(unicode) : QString(), + autorepeat); +} + + +void QNitpickerPlatformWindow::_mouse_button_event(Input::Keycode button, bool press) +{ + Qt::MouseButton current_mouse_button = Qt::NoButton; + + switch (button) { + case Input::BTN_LEFT: current_mouse_button = Qt::LeftButton; break; + case Input::BTN_RIGHT: current_mouse_button = Qt::RightButton; break; + case Input::BTN_MIDDLE: current_mouse_button = Qt::MidButton; break; + case Input::BTN_SIDE: current_mouse_button = Qt::ExtraButton1; break; + case Input::BTN_EXTRA: current_mouse_button = Qt::ExtraButton2; break; + case Input::BTN_FORWARD: current_mouse_button = Qt::ExtraButton3; break; + case Input::BTN_BACK: current_mouse_button = Qt::ExtraButton4; break; + case Input::BTN_TASK: current_mouse_button = Qt::ExtraButton5; break; + default: return; + } + + _mouse_button_state.setFlag(current_mouse_button, press); + + /* on mouse click, make this window the focused window */ + if (press) requestActivateWindow(); + + QWindowSystemInterface::handleMouseEvent(window(), + _local_position(), + _mouse_position, + _mouse_button_state, + current_mouse_button, + press ? QEvent::MouseButtonPress + : QEvent::MouseButtonRelease, + _keyboard_modifiers); +} + + void QNitpickerPlatformWindow::_handle_input() { QList<Input::Event> touch_events; _input_session.for_each_event([&] (Input::Event const &event) { - QPoint const orig_mouse_position = _mouse_position; - Qt::MouseButtons const orig_mouse_button_state = _mouse_button_state; - event.handle_absolute_motion([&] (int x, int y) { - _mouse_position = QPoint(x, y); }); + _mouse_position = QPoint(x, y); - event.handle_press([&] (Input::Keycode key, Genode::Codepoint codepoint) { - - switch (key) { - case Input::KEY_LEFTALT: - case Input::KEY_RIGHTALT: _keyboard_modifiers |= Qt::AltModifier; break; - case Input::KEY_LEFTCTRL: - case Input::KEY_RIGHTCTRL: _keyboard_modifiers |= Qt::ControlModifier; break; - case Input::KEY_LEFTSHIFT: - case Input::KEY_RIGHTSHIFT: _keyboard_modifiers |= Qt::ShiftModifier; break; - case Input::BTN_LEFT: _mouse_button_state |= Qt::LeftButton; break; - case Input::BTN_RIGHT: _mouse_button_state |= Qt::RightButton; break; - case Input::BTN_MIDDLE: _mouse_button_state |= Qt::MidButton; break; - case Input::BTN_SIDE: _mouse_button_state |= Qt::XButton1; break; - case Input::BTN_EXTRA: _mouse_button_state |= Qt::XButton2; break; - default: break; - } - - /* on mouse click, make this window the focused window */ - if (_mouse_button_state != orig_mouse_button_state) - requestActivateWindow(); - - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, - translate_keycode(key), - _keyboard_modifiers, - QString() + QChar(codepoint.value)); + QWindowSystemInterface::handleMouseEvent(window(), + _local_position(), + _mouse_position, + _mouse_button_state, + Qt::NoButton, + QEvent::MouseMove, + _keyboard_modifiers); }); - /* handle repeat of special keys */ - event.handle_repeat([&] (Genode::Codepoint codepoint) { - - /* function-key unicodes */ - enum { - CODEPOINT_UP = 0xf700, CODEPOINT_DOWN = 0xf701, - CODEPOINT_LEFT = 0xf702, CODEPOINT_RIGHT = 0xf703, - CODEPOINT_HOME = 0xf729, CODEPOINT_INSERT = 0xf727, - CODEPOINT_DELETE = 0xf728, CODEPOINT_END = 0xf72b, - CODEPOINT_PAGEUP = 0xf72c, CODEPOINT_PAGEDOWN = 0xf72d, - CODEPOINT_BACKSPACE = 8, CODEPOINT_LINEFEED = 10, - }; - - Qt::Key repeated_key = Qt::Key_unknown; - switch (codepoint.value) { - case CODEPOINT_UP: repeated_key = Qt::Key_Up; break; - case CODEPOINT_DOWN: repeated_key = Qt::Key_Down; break; - case CODEPOINT_LEFT: repeated_key = Qt::Key_Left; break; - case CODEPOINT_RIGHT: repeated_key = Qt::Key_Right; break; - case CODEPOINT_HOME: repeated_key = Qt::Key_Home; break; - case CODEPOINT_INSERT: repeated_key = Qt::Key_Insert; break; - case CODEPOINT_DELETE: repeated_key = Qt::Key_Delete; break; - case CODEPOINT_END: repeated_key = Qt::Key_End; break; - case CODEPOINT_PAGEUP: repeated_key = Qt::Key_PageUp; break; - case CODEPOINT_PAGEDOWN: repeated_key = Qt::Key_PageDown; break; - case CODEPOINT_BACKSPACE: repeated_key = Qt::Key_Backspace; break; - case CODEPOINT_LINEFEED: repeated_key = Qt::Key_Return; break; - default: return /* from lambda */; - }; - - /* - * A key repeat is triggered while a key is already pressed. We - * respond to it by simulating a tempoary release of the key. - */ - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, - repeated_key, - _keyboard_modifiers, - QString()); - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, - repeated_key, - _keyboard_modifiers, - QString()); + event.handle_press([&] (Input::Keycode key, Codepoint codepoint) { + if (key > 0 && key < 0x100) + _key_event(key, codepoint, Mapped_key::PRESSED); + else if (key >= Input::BTN_LEFT && key <= Input::BTN_TASK) + _mouse_button_event(key, true); }); event.handle_release([&] (Input::Keycode key) { + if (key > 0 && key < 0x100) + _key_event(key, Codepoint { Codepoint::INVALID }, Mapped_key::RELEASED); + else if (key >= Input::BTN_LEFT && key <= Input::BTN_TASK) + _mouse_button_event(key, false); + }); - switch (key) { - case Input::KEY_LEFTALT: - case Input::KEY_RIGHTALT: _keyboard_modifiers &= ~Qt::AltModifier; break; - case Input::KEY_LEFTCTRL: - case Input::KEY_RIGHTCTRL: _keyboard_modifiers &= ~Qt::ControlModifier; break; - case Input::KEY_LEFTSHIFT: - case Input::KEY_RIGHTSHIFT: _keyboard_modifiers &= ~Qt::ShiftModifier; break; - case Input::BTN_LEFT: _mouse_button_state &= ~Qt::LeftButton; break; - case Input::BTN_RIGHT: _mouse_button_state &= ~Qt::RightButton; break; - case Input::BTN_MIDDLE: _mouse_button_state &= ~Qt::MidButton; break; - case Input::BTN_SIDE: _mouse_button_state &= ~Qt::XButton1; break; - case Input::BTN_EXTRA: _mouse_button_state &= ~Qt::XButton2; break; - default: break; - } - - QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, - translate_keycode(key), - _keyboard_modifiers, - QString()); + event.handle_repeat([&] (Codepoint codepoint) { + _key_event(Input::KEY_UNKNOWN, codepoint, Mapped_key::REPEAT); }); event.handle_wheel([&] (int x, int y) { QWindowSystemInterface::handleWheelEvent(window(), _local_position(), _local_position(), - y * 120, - Qt::Vertical); }); - - if (_mouse_button_state != orig_mouse_button_state - || _mouse_position != orig_mouse_position) { - - QWindowSystemInterface::handleMouseEvent(window(), - _local_position(), - _mouse_position, - _mouse_button_state); - } + QPoint(), + QPoint(0, y * 120), + _keyboard_modifiers); }); if (event.touch() || event.touch_release()) touch_events.push_back(event); diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp index 14afb1b6c..34e673dce 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp @@ -43,7 +43,7 @@ QNitpickerWindowSurface::QNitpickerWindowSurface(QWindow *window) QNitpickerWindowSurface::~QNitpickerWindowSurface() { - qFree(_backbuffer); + free(_backbuffer); } QPaintDevice *QNitpickerWindowSurface::paintDevice() @@ -61,8 +61,8 @@ QPaintDevice *QNitpickerWindowSurface::paintDevice() QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); QRect geo = _platform_window->geometry(); unsigned int const bytes_per_pixel = QGuiApplication::primaryScreen()->depth() / 8; - qFree(_backbuffer); - _backbuffer = (unsigned char*)qMalloc(geo.width() * geo.height() * bytes_per_pixel); + free(_backbuffer); + _backbuffer = (unsigned char*)malloc(geo.width() * geo.height() * bytes_per_pixel); _image = QImage(_backbuffer, geo.width(), geo.height(), geo.width() * bytes_per_pixel, format); if (verbose) @@ -90,9 +90,7 @@ void QNitpickerWindowSurface::flush(QWindow *window, const QRegion ®ion, cons unsigned int const bytes_per_pixel = _image.depth() / 8; - for (int i = 0; i < region.rects().size(); i++) { - - QRect rect(region.rects()[i]); + for (QRect rect : region) { /* * It happened that after resizing a window, the given flush region was diff --git a/repos/libports/src/lib/vfs/fatfs/vfs_fatfs.cc b/repos/libports/src/lib/vfs/fatfs/vfs_fatfs.cc index 2c856ac9e..f507732d5 100644 --- a/repos/libports/src/lib/vfs/fatfs/vfs_fatfs.cc +++ b/repos/libports/src/lib/vfs/fatfs/vfs_fatfs.cc @@ -181,30 +181,39 @@ class Fatfs::File_system : public Vfs::File_system cur_index = 0; } - Dirent *vfs_dir = (Dirent*)buf; + Dirent &vfs_dirent = *(Dirent*)buf; FILINFO info; FRESULT res; - vfs_dir->fileno = 1; /* inode 0 is a pending unlink */ + + unsigned const fileno = 1; /* inode 0 is a pending unlink */ while (cur_index <= dir_index) { res = f_readdir (&dir, &info); if ((res != FR_OK) || (!info.fname[0])) { f_readdir(&dir, nullptr); cur_index = 0; - vfs_dir->type = DIRENT_TYPE_END; - vfs_dir->name[0] = '\0'; + + vfs_dirent = { + .fileno = fileno, + .type = Dirent_type::END, + .rwx = Node_rwx::rwx(), + .name = { } + }; out_count = sizeof(Dirent); return READ_OK; } cur_index++; } - vfs_dir->type = (info.fattrib & AM_DIR) ? - DIRENT_TYPE_DIRECTORY : DIRENT_TYPE_FILE; - Genode::strncpy(vfs_dir->name, (const char*)info.fname, - sizeof(vfs_dir->name)); - + vfs_dirent = { + .fileno = fileno, + .type = (info.fattrib & AM_DIR) + ? Dirent_type::DIRECTORY + : Dirent_type::CONTINUOUS_FILE, + .rwx = Node_rwx::rwx(), + .name = { (char const *)info.fname } + }; out_count = sizeof(Dirent); return READ_OK; } @@ -607,19 +616,22 @@ class Fatfs::File_system : public Vfs::File_system Stat_result stat(char const *path, Stat &stat) override { - stat = Stat(); + stat = Stat { }; FILINFO info; FRESULT const err = f_stat((const TCHAR*)path, &info); switch (err) { case FR_OK: - stat.inode = 1; + stat.inode = 1; stat.device = (Genode::addr_t)this; - stat.mode = (info.fattrib & AM_DIR) ? - STAT_MODE_DIRECTORY : STAT_MODE_FILE; + stat.type = (info.fattrib & AM_DIR) + ? Vfs::Node_type::DIRECTORY + : Vfs::Node_type::CONTINUOUS_FILE; + stat.rwx = Vfs::Node_rwx::rwx(); + /* XXX: size in f_stat is always zero */ - if ((stat.mode == STAT_MODE_FILE) && (info.fsize == 0)) { + if ((stat.type == Vfs::Node_type::CONTINUOUS_FILE) && (info.fsize == 0)) { File *file = _opened_file(path); if (file) { stat.size = f_size(&file->fil); diff --git a/repos/libports/src/lib/vfs/jitterentropy/vfs_jitterentropy.h b/repos/libports/src/lib/vfs/jitterentropy/vfs_jitterentropy.h index 766ac24ef..a4d0f5a39 100644 --- a/repos/libports/src/lib/vfs/jitterentropy/vfs_jitterentropy.h +++ b/repos/libports/src/lib/vfs/jitterentropy/vfs_jitterentropy.h @@ -102,7 +102,8 @@ class Jitterentropy_file_system : public Vfs::Single_file_system Jitterentropy_file_system(Genode::Allocator &alloc, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config), + Single_file_system(Vfs::Node_type::CONTINUOUS_FILE, name(), + Vfs::Node_rwx::ro(), config), _ec_stir(0), _initialized(_init_jitterentropy(alloc)) { } diff --git a/repos/libports/src/lib/vfs/lwip/vfs.cc b/repos/libports/src/lib/vfs/lwip/vfs.cc index 279503f0e..51df283c9 100644 --- a/repos/libports/src/lib/vfs/lwip/vfs.cc +++ b/repos/libports/src/lib/vfs/lwip/vfs.cc @@ -603,35 +603,51 @@ class Lwip::Protocol_dir_impl final : public Protocol_dir Path subpath(path); if (subpath == "/") { - st.size = 1; - st.mode = Directory_service::STAT_MODE_DIRECTORY; - st.inode = (Genode::addr_t)this; + st = { .size = 1, + .type = Node_type::DIRECTORY, + .rwx = Node_rwx::rwx(), + .inode = (Genode::addr_t)this, + .device = 0, + .modification_time = { 0 } }; return Directory_service::STAT_OK; } if (subpath == "/new_socket") { - st.size = 1; - st.mode = Directory_service::STAT_MODE_FILE | 0777; - st.inode = ((Genode::addr_t)this)+1; + st = { .size = 1, + .type = Node_type::TRANSACTIONAL_FILE, + .rwx = Node_rwx::rw(), + .inode = (Genode::addr_t)this + 1, + .device = 0, + .modification_time = { 0 } }; return Directory_service::STAT_OK; } if (!subpath.has_single_element()) subpath.strip_last_element(); + if (SOCKET_DIR *dir = lookup(subpath.string())) { Path filename(path); filename.keep_only_last_element(); if (filename == subpath.base()) { - st.size = Lwip_file_handle::INVALID; - st.mode = Directory_service::STAT_MODE_DIRECTORY; - st.inode = (Genode::addr_t)dir; + st = { .size = 0, + .type = Node_type::DIRECTORY, + .rwx = Node_rwx::rwx(), + .inode = (Genode::addr_t)dir, + .device = 0, + .modification_time = { 0 } }; return Directory_service::STAT_OK; } Lwip_file_handle::Kind k = Lwip_file_handle::kind_from_name(filename); if (k != Lwip_file_handle::INVALID) { - st.mode = Directory_service::STAT_MODE_CHARDEV; - st.inode = ((Genode::addr_t)dir)+k; + st = { .size = 0, + .type = (filename == "/data") + ? Node_type::CONTINUOUS_FILE + : Node_type::TRANSACTIONAL_FILE, + .rwx = Node_rwx::rw(), + .inode = (Genode::addr_t)dir + k, + .device = 0, + .modification_time = { 0 } }; return Directory_service::STAT_OK; } } @@ -896,6 +912,7 @@ class Lwip::Udp_socket_dir final : } result = Read_result::READ_OK; }); + break; } case Lwip_file_handle::PEEK: @@ -1418,7 +1435,7 @@ class Lwip::Tcp_socket_dir final : { if (_pcb == NULL) { /* socket is closed */ - return Write_result::WRITE_ERR_INVALID; + return Write_result::WRITE_ERR_IO; } switch(handle.kind) { @@ -1794,18 +1811,26 @@ class Lwip::File_system final : public Vfs::File_system, public Lwip::Directory Stat_result stat(char const *path, Stat &st) override { if (*path == '/') ++path; - st = Stat(); + st = Stat { }; st.device = (Genode::addr_t)this; if (match_address(path) || match_netmask(path)) { - st.size = ADDRESS_FILE_SIZE; - st.mode = STAT_MODE_FILE; + st = { .size = ADDRESS_FILE_SIZE, + .type = Node_type::TRANSACTIONAL_FILE, + .rwx = Node_rwx::rw(), + .inode = (Genode::addr_t)this, + .device = 0, + .modification_time = { 0 } }; return STAT_OK; } if (match_nameserver(path)) { - st.size = IPADDR_STRLEN_MAX; - st.mode = STAT_MODE_FILE; + st = { .size = IPADDR_STRLEN_MAX, + .type = Node_type::TRANSACTIONAL_FILE, + .rwx = Node_rwx::rw(), + .inode = 0, + .device = 0, + .modification_time = { 0 } }; return STAT_OK; } diff --git a/repos/libports/src/server/fatfs_fs/directory.h b/repos/libports/src/server/fatfs_fs/directory.h deleted file mode 100644 index 500e747fc..000000000 --- a/repos/libports/src/server/fatfs_fs/directory.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * \brief FATFS file-system directory node - * \author Christian Prochaska - * \date 2012-07-04 - */ - -/* - * Copyright (C) 2012-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 _DIRECTORY_H_ -#define _DIRECTORY_H_ - -/* fatfs includes */ -namespace Fatfs { extern "C" { -#include <fatfs/ff.h> -} } - -/* local includes */ -#include <node.h> - - -namespace Fatfs_fs { - using namespace Genode; - class Directory; -} - -class Fatfs_fs::Directory : public Node -{ - private: - - Fatfs::DIR _fatfs_dir; - int64_t _prev_index; - - public: - - Directory(const char *name) - : Node(name), - _prev_index(-1) { } - - void fatfs_dir(Fatfs::DIR fatfs_dir) { _fatfs_dir = fatfs_dir; } - Fatfs::DIR *fatfs_dir() { return &_fatfs_dir; } - - size_t read(char *dst, size_t len, seek_off_t seek_offset) - { - if (len < sizeof(Directory_entry)) { - error("read buffer too small for directory entry"); - return 0; - } - - if (seek_offset % sizeof(Directory_entry)) { - error("seek offset not alighed to sizeof(Directory_entry)"); - return 0; - } - - Directory_entry *e = (Directory_entry *)(dst); - - using namespace Fatfs; - - FILINFO fatfs_file_info; - - int64_t index = seek_offset / sizeof(Directory_entry); - - if (index != (_prev_index + 1)) { - /* rewind and iterate from the beginning */ - f_readdir(&_fatfs_dir, 0); - for (int i = 0; i < index; i++) - f_readdir(&_fatfs_dir, &fatfs_file_info); - } - - _prev_index = index; - - FRESULT res = f_readdir(&_fatfs_dir, &fatfs_file_info); - switch(res) { - case FR_OK: - break; - case FR_INVALID_OBJECT: - error("f_readdir() failed with error code FR_INVALID_OBJECT"); - return 0; - case FR_DISK_ERR: - error("f_readdir() failed with error code FR_DISK_ERR"); - return 0; - case FR_INT_ERR: - error("f_readdir() failed with error code FR_INT_ERR"); - return 0; - case FR_NOT_READY: - error("f_readdir() failed with error code FR_NOT_READY"); - return 0; - default: - /* not supposed to occur according to the libfatfs documentation */ - error("f_readdir() returned an unexpected error code"); - return 0; - } - - if (fatfs_file_info.fname[0] == 0) { /* no (more) entries */ - return 0; - } - - strncpy(e->name, fatfs_file_info.fname, sizeof(e->name)); - - if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR) - e->type = Directory_entry::TYPE_DIRECTORY; - else - e->type = Directory_entry::TYPE_FILE; - - return sizeof(Directory_entry); - } - - size_t write(char const *src, size_t len, seek_off_t) - { - /* writing to directory nodes is not supported */ - return 0; - } - -}; - -#endif /* _DIRECTORY_H_ */ diff --git a/repos/libports/src/server/fatfs_fs/file.h b/repos/libports/src/server/fatfs_fs/file.h deleted file mode 100644 index 1d30948c8..000000000 --- a/repos/libports/src/server/fatfs_fs/file.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * \brief FATFS file-system file node - * \author Christian Prochaska - * \date 2012-07-04 - */ - -/* - * Copyright (C) 2012-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 _FILE_H_ -#define _FILE_H_ - -/* fatfs includes */ -namespace Fatfs { extern "C" { -#include <fatfs/ff.h> -} } - -/* local includes */ -#include <node.h> - - -namespace Fatfs_fs { - class File; -} - -class Fatfs_fs::File : public Node -{ - private: - - Fatfs::FIL _fatfs_fil; - - public: - - File(const char *name) : Node(name) { } - - ~File() - { - using namespace Fatfs; - - FRESULT res = f_close(&_fatfs_fil); - - switch(res) { - case FR_OK: - return; - case FR_INVALID_OBJECT: - error("f_close() failed with error code FR_INVALID_OBJECT"); - return; - case FR_DISK_ERR: - error("f_close() failed with error code FR_DISK_ERR"); - return; - case FR_INT_ERR: - error("f_close() failed with error code FR_INT_ERR"); - return; - case FR_NOT_READY: - error("f_close() failed with error code FR_NOT_READY"); - return; - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_close() returned an unexpected error code"); - return; - } - } - - void fatfs_fil(Fatfs::FIL fatfs_fil) { _fatfs_fil = fatfs_fil; } - Fatfs::FIL *fatfs_fil() { return &_fatfs_fil; } - - size_t read(char *dst, size_t len, seek_off_t seek_offset) override - { - using namespace Fatfs; - - UINT result; - - if (seek_offset == (seek_off_t)(~0)) { - FILINFO file_info; - f_stat(name(), &file_info); - - seek_offset = file_info.fsize; - } - - FRESULT res = f_lseek(&_fatfs_fil, seek_offset); - - switch(res) { - case FR_OK: - break; - case FR_INVALID_OBJECT: - Genode::error("f_lseek() failed with error code FR_INVALID_OBJECT"); - return 0; - case FR_DISK_ERR: - Genode::error("f_lseek() failed with error code FR_DISK_ERR"); - return 0; - case FR_INT_ERR: - Genode::error("f_lseek() failed with error code FR_INT_ERR"); - return 0; - case FR_NOT_READY: - Genode::error("f_lseek() failed with error code FR_NOT_READY"); - return 0; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_lseek() returned an unexpected error code"); - return 0; - } - - res = f_read(&_fatfs_fil, dst, len, &result); - - switch(res) { - case FR_OK: - return result; - case FR_DENIED: - Genode::warning("f_read() failed with error code FR_DENIED"); - return 0; - case FR_INVALID_OBJECT: - Genode::error("f_read() failed with error code FR_INVALID_OBJECT"); - return 0; - case FR_DISK_ERR: - Genode::error("f_read() failed with error code FR_DISK_ERR"); - return 0; - case FR_INT_ERR: - Genode::error("f_read() failed with error code FR_INT_ERR"); - return 0; - case FR_NOT_READY: - Genode::error("f_read() failed with error code FR_NOT_READY"); - return 0; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_read() returned an unexpected error code"); - return 0; - } - } - - size_t write(char const *src, size_t len, seek_off_t seek_offset) override - { - using namespace Fatfs; - - UINT result; - - if (seek_offset == (seek_off_t)(~0)) { - FILINFO file_info; - f_stat(name(), &file_info); - - seek_offset = file_info.fsize; - } - - FRESULT res = f_lseek(&_fatfs_fil, seek_offset); - - switch(res) { - case FR_OK: - break; - case FR_INVALID_OBJECT: - Genode::error("f_lseek() failed with error code FR_INVALID_OBJECT"); - return 0; - case FR_DISK_ERR: - Genode::error("f_lseek() failed with error code FR_DISK_ERR"); - return 0; - case FR_INT_ERR: - Genode::error("f_lseek() failed with error code FR_INT_ERR"); - return 0; - case FR_NOT_READY: - Genode::error("f_lseek() failed with error code FR_NOT_READY"); - return 0; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_lseek() returned an unexpected error code"); - return 0; - } - - res = f_write(&_fatfs_fil, src, len, &result); - - switch(res) { - case FR_OK: - return result; - case FR_DENIED: - Genode::error("f_write() failed with error code FR_DENIED"); - return 0; - case FR_INVALID_OBJECT: - Genode::error("f_write() failed with error code FR_INVALID_OBJECT"); - return 0; - case FR_DISK_ERR: - Genode::error("f_write() failed with error code FR_DISK_ERR"); - return 0; - case FR_INT_ERR: - Genode::error("f_write() failed with error code FR_INT_ERR"); - return 0; - case FR_NOT_READY: - Genode::error("f_write() failed with error code FR_NOT_READY"); - return 0; - default: - /* not supposed to occur according to the fatfs documentation */ - Genode::error("f_write() returned an unexpected error code"); - return 0; - } - } - - void truncate(file_size_t size) override - { - using namespace Fatfs; - - /* - * This macro is defined in later versions of the FatFs lib, but not in the - * one currently used for Genode. - */ - #define f_tell(fp) ((fp)->fptr) - - /* 'f_truncate()' truncates to the current seek pointer */ - - FRESULT res = f_lseek(&_fatfs_fil, size); - - switch(res) { - case FR_OK: - /* according to the FatFs documentation this can happen */ - if (f_tell(&_fatfs_fil) != size) { - error("f_lseek() could not seek to offset ", size); - return; - } - break; - case FR_DISK_ERR: - error("f_lseek() failed with error code FR_DISK_ERR"); - return; - case FR_INT_ERR: - error("f_lseek() failed with error code FR_INT_ERR"); - return; - case FR_NOT_READY: - error("f_lseek() failed with error code FR_NOT_READY"); - return; - case FR_INVALID_OBJECT: - error("f_lseek() failed with error code FR_INVALID_OBJECT"); - throw Invalid_handle(); - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_lseek() returned an unexpected error code"); - return; - } - - res = f_truncate(&_fatfs_fil); - - switch(res) { - case FR_OK: - return; - case FR_INVALID_OBJECT: - error("f_truncate() failed with error code FR_INVALID_OBJECT"); - throw Invalid_handle(); - case FR_DISK_ERR: - error("f_truncate() failed with error code FR_DISK_ERR"); - return; - case FR_INT_ERR: - error("f_truncate() failed with error code FR_INT_ERR"); - return; - case FR_NOT_READY: - error("f_truncate() failed with error code FR_NOT_READY"); - return; - case FR_TIMEOUT: - error("f_truncate() failed with error code FR_TIMEOUT"); - return; - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_truncate() returned an unexpected error code"); - return; - } - } - -}; - -#endif /* _FILE_H_ */ diff --git a/repos/libports/src/server/fatfs_fs/main.cc b/repos/libports/src/server/fatfs_fs/main.cc deleted file mode 100644 index 74e61c5a7..000000000 --- a/repos/libports/src/server/fatfs_fs/main.cc +++ /dev/null @@ -1,999 +0,0 @@ -/* - * \brief FATFS file system - * \author Christian Prochaska - * \date 2012-07-03 - */ - -/* - * Copyright (C) 2012-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. - */ - -/* Genode includes */ -#include <base/component.h> -#include <file_system_session/rpc_object.h> -#include <root/component.h> -#include <base/attached_rom_dataspace.h> -#include <os/session_policy.h> -#include <util/xml_node.h> -#include <base/heap.h> -#include <base/log.h> - -/* local includes */ -#include <directory.h> -#include <file.h> -#include <open_node.h> -#include <util.h> - -/* Genode block backend */ -#include <fatfs/block.h> - -/* fatfs includes */ -namespace Fatfs { extern "C" { -#include <fatfs/ff.h> -} } - - -/************************* - ** File-system service ** - *************************/ - -namespace Fatfs_fs { - - using namespace Genode; - using File_system::Exception; - using File_system::Packet_descriptor; - using File_system::Path; - - class Session_component; - class Root; - struct Main; -} - -class Fatfs_fs::Session_component : public Session_rpc_object -{ - private: - - typedef File_system::Open_node<Node> Open_node; - - Genode::Env &_env; - Genode::Allocator &_heap; - - Directory &_root; - Id_space<File_system::Node> _open_node_registry; - bool _writable; - - Signal_handler<Session_component> _process_packet_dispatcher; - - /****************************** - ** Packet-stream processing ** - ******************************/ - - /** - * Perform packet operation - * - * \return true on success, false on failure - */ - void _process_packet_op(Packet_descriptor &packet, Open_node &open_node) - { - void * const content = tx_sink()->packet_content(packet); - size_t const length = packet.length(); - seek_off_t const offset = packet.position(); - - /* resulting length */ - size_t res_length = 0; - bool succeeded = false; - - switch (packet.operation()) { - - case Packet_descriptor::READ: - if (content && (packet.length() <= packet.size())) { - res_length = open_node.node().read((char *)content, length, - offset); - - /* read data or EOF is a success */ - succeeded = res_length > 0; - if (!succeeded) { - File * file = dynamic_cast<File *>(&open_node.node()); - if (file) - succeeded = f_eof((file->fatfs_fil())); - } - } - break; - - case Packet_descriptor::WRITE: - if (content && (packet.length() <= packet.size())) { - res_length = open_node.node().write((char const *)content, - length, offset); - - /* File system session can't handle partial writes */ - if (res_length != length) { - Genode::error("partial write detected ", - res_length, " vs ", length); - /* don't acknowledge */ - return; - } - succeeded = true; - } - break; - - case Packet_descriptor::CONTENT_CHANGED: - open_node.register_notify(*tx_sink()); - open_node.node().notify_listeners(); - return; - - case Packet_descriptor::READ_READY: - succeeded = true; - /* not supported */ - break; - - case Packet_descriptor::SYNC: - succeeded = true; - /* not supported */ - break; - } - - packet.length(res_length); - packet.succeeded(succeeded); - - tx_sink()->acknowledge_packet(packet); - } - - void _process_packet() - { - Packet_descriptor packet = tx_sink()->get_packet(); - - /* assume failure by default */ - packet.succeeded(false); - - auto process_packet_fn = [&] (Open_node &open_node) { - _process_packet_op(packet, open_node); - }; - - try { - _open_node_registry.apply<Open_node>(packet.handle(), process_packet_fn); - } catch (Id_space<File_system::Node>::Unknown_id const &) { - Genode::error("Invalid_handle"); - } - } - - /** - * Called by signal dispatcher, executed in the context of the main - * thread (not serialized with the RPC functions) - */ - void _process_packets() - { - while (tx_sink()->packet_avail()) { - - /* - * Make sure that the '_process_packet' function does not - * block. - * - * If the acknowledgement queue is full, we defer packet - * processing until the client processed pending - * acknowledgements and thereby emitted a ready-to-ack - * signal. Otherwise, the call of 'acknowledge_packet()' - * in '_process_packet' would infinitely block the context - * of the main thread. The main thread is however needed - * for receiving any subsequent 'ready-to-ack' signals. - */ - if (!tx_sink()->ready_to_ack()) - return; - - _process_packet(); - } - } - - /** - * Check if string represents a valid path (most start with '/') - */ - static void _assert_valid_path(char const *path) - { - if (!valid_path(path)) { - warning("malformed path '", path, "'"); - throw Lookup_failed(); - } - } - - public: - - /** - * Constructor - */ - Session_component(Genode::Env &env, - Genode::Allocator &heap, - size_t tx_buf_size, - Directory &root, - bool writable) - : - Session_rpc_object(env.ram().alloc(tx_buf_size), - env.rm(), env.ep().rpc_ep()), - _env(env), _heap(heap), _root(root), _writable(writable), - _process_packet_dispatcher(env.ep(), *this, - &Session_component::_process_packets) - { - /* - * Register '_process_packets' dispatch function as signal - * handler for packet-avail and ready-to-ack signals. - */ - _tx.sigh_packet_avail(_process_packet_dispatcher); - _tx.sigh_ready_to_ack(_process_packet_dispatcher); - } - - /** - * Destructor - */ - ~Session_component() - { - Dataspace_capability ds = tx_sink()->dataspace(); - _env.ram().free(static_cap_cast<Ram_dataspace>(ds)); - } - - /*************************** - ** File_system interface ** - ***************************/ - - File_handle file(Dir_handle dir_handle, Name const &name, - Mode mode, bool create) - { - if (!valid_filename(name.string())) - throw Invalid_name(); - - auto file_fn = [&] (Open_node &open_node) { - - using namespace Fatfs; - - FIL fatfs_fil; - BYTE fatfs_flags = 0; - - if (!_writable) - if (create || (mode != STAT_ONLY && mode != READ_ONLY)) - throw Permission_denied(); - - if (create) - fatfs_flags |= FA_CREATE_NEW; - - if ((mode == READ_ONLY) || (mode == READ_WRITE)) - fatfs_flags |= FA_READ; - - if ((mode == WRITE_ONLY) || (mode == READ_WRITE)) - fatfs_flags |= FA_WRITE; - - Absolute_path absolute_path(_root.name()); - - try { - absolute_path.append(open_node.node().name()); - absolute_path.append("/"); - absolute_path.append(name.string()); - } catch (Path_base::Path_too_long) { - throw Invalid_name(); - } - - FRESULT res = f_open(&fatfs_fil, absolute_path.base(), fatfs_flags); - - switch(res) { - case FR_OK: { - File *file_node = new (&_heap) File(absolute_path.base()); - file_node->fatfs_fil(fatfs_fil); - - Open_node *open_file = - new (_heap) Open_node(*file_node, _open_node_registry); - - return open_file->id(); - } - case FR_NO_FILE: - case FR_NO_PATH: - throw Lookup_failed(); - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - throw Invalid_name(); - case FR_EXIST: - throw Node_already_exists(); - case FR_DENIED: - case FR_WRITE_PROTECTED: - throw Permission_denied(); - case FR_NOT_READY: - error("f_open() failed with error code FR_NOT_READY"); - throw Lookup_failed(); - case FR_DISK_ERR: - error("f_open() failed with error code FR_DISK_ERR"); - throw Lookup_failed(); - case FR_INT_ERR: - error("f_open() failed with error code FR_INT_ERR"); - throw Lookup_failed(); - case FR_NOT_ENABLED: - error("f_open() failed with error code FR_NOT_ENABLED"); - throw Lookup_failed(); - case FR_NO_FILESYSTEM: - error("f_open() failed with error code FR_NO_FILESYSTEM"); - throw Lookup_failed(); - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_open() returned an unexpected error code"); - throw Lookup_failed(); - } - }; - - try { - return File_handle { - _open_node_registry.apply<Open_node>(dir_handle, file_fn).value - }; - } catch (Id_space<File_system::Node>::Unknown_id const &) { - throw Invalid_handle(); - } - } - - Symlink_handle symlink(Dir_handle, Name const &name, bool create) - { - /* not supported */ - throw Permission_denied(); - } - - Dir_handle dir(Path const &path, bool create) - { - if (create && !_writable) - throw Permission_denied(); - - _assert_valid_path(path.string()); - - /* - * The 'Directory' constructor removes trailing slashes, - * except for "/" - */ - Directory *dir_node = new (&_heap) Directory(path.string()); - - using namespace Fatfs; - - Absolute_path absolute_path(_root.name()); - - try { - absolute_path.append(dir_node->name()); - absolute_path.remove_trailing('/'); - } catch (Path_base::Path_too_long) { - throw Name_too_long(); - } - - if (create) { - - if (is_root(dir_node->name())) - throw Node_already_exists(); - - FRESULT res = f_mkdir(absolute_path.base()); - - try { - switch(res) { - case FR_OK: - break; - case FR_NO_PATH: - throw Lookup_failed(); - case FR_INVALID_NAME: - throw Name_too_long(); - case FR_INVALID_DRIVE: - throw Name_too_long(); - case FR_DENIED: - case FR_WRITE_PROTECTED: - throw Permission_denied(); - case FR_EXIST: - throw Node_already_exists(); - case FR_NOT_READY: - error("f_mkdir() failed with error code FR_NOT_READY"); - throw Lookup_failed(); - case FR_DISK_ERR: - error("f_mkdir() failed with error code FR_DISK_ERR"); - throw Lookup_failed(); - case FR_INT_ERR: - error("f_mkdir() failed with error code FR_INT_ERR"); - throw Lookup_failed(); - case FR_NOT_ENABLED: - error("f_mkdir() failed with error code FR_NOT_ENABLED"); - throw Lookup_failed(); - case FR_NO_FILESYSTEM: - error("f_mkdir() failed with error code FR_NO_FILESYSTEM"); - throw Lookup_failed(); - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_mkdir() returned an unexpected error code"); - throw Lookup_failed(); - } - } catch (Exception e) { - destroy(&_heap, dir_node); - throw e; - } - } - - Fatfs::DIR fatfs_dir; - FRESULT f_opendir_res = f_opendir(&fatfs_dir, absolute_path.base()); - - try { - switch(f_opendir_res) { - case FR_OK: { - dir_node->fatfs_dir(fatfs_dir); - - Open_node *open_dir = - new (_heap) Open_node(*dir_node, _open_node_registry); - - return Dir_handle { open_dir->id().value }; - } - case FR_NO_PATH: - throw Lookup_failed(); - case FR_INVALID_NAME: - throw Name_too_long(); - case FR_INVALID_DRIVE: - throw Name_too_long(); - case FR_NOT_READY: - error("f_opendir() failed with error code FR_NOT_READY"); - throw Lookup_failed(); - case FR_DISK_ERR: - error("f_opendir() failed with error code FR_DISK_ERR"); - throw Lookup_failed(); - case FR_INT_ERR: - error("f_opendir() failed with error code FR_INT_ERR"); - throw Lookup_failed(); - case FR_NOT_ENABLED: - error("f_opendir() failed with error code FR_NOT_ENABLED"); - throw Lookup_failed(); - case FR_NO_FILESYSTEM: - error("f_opendir() failed with error code FR_NO_FILESYSTEM"); - throw Lookup_failed(); - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_opendir() returned an unexpected error code"); - throw Lookup_failed(); - } - } catch (Exception e) { - destroy(&_heap, dir_node); - throw e; - } - } - - Node_handle node(Path const &path) - { - if (!valid_path(path.string())) - throw Lookup_failed(); - - Absolute_path absolute_path(_root.name()); - - try { - absolute_path.append(path.string()); - absolute_path.remove_trailing('/'); - } catch (Path_base::Path_too_long) { - throw Lookup_failed(); - } - - Node *node = new (&_heap) Node(absolute_path.base()); - - /* f_stat() does not work for "/" */ - if (!is_root(node->name())) { - - using namespace Fatfs; - - FILINFO file_info; - - FRESULT res = f_stat(node->name(), &file_info); - - try { - switch(res) { - case FR_OK: - break; - case FR_NO_FILE: - case FR_NO_PATH: - throw Lookup_failed(); - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - throw Lookup_failed(); - case FR_DISK_ERR: - error("f_stat() failed with error code FR_DISK_ERR"); - throw Lookup_failed(); - case FR_INT_ERR: - error("f_stat() failed with error code FR_INT_ERR"); - throw Lookup_failed(); - case FR_NOT_READY: - error("f_stat() failed with error code FR_NOT_READY"); - throw Lookup_failed(); - case FR_NOT_ENABLED: - error("f_stat() failed with error code FR_NOT_ENABLED"); - throw Lookup_failed(); - case FR_NO_FILESYSTEM: - error("f_stat() failed with error code FR_NO_FILESYSTEM"); - throw Lookup_failed(); - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_stat() returned an unexpected error code"); - throw Lookup_failed(); - } - } catch (Exception e) { - destroy(&_heap, node); - throw e; - } - } - - Open_node *open_node = - new (_heap) Open_node(*node, _open_node_registry); - - return open_node->id(); - } - - void close(Node_handle handle) - { - auto close_fn = [&] (Open_node &open_node) { - Node &node = open_node.node(); - destroy(_heap, &open_node); - destroy(_heap, &node); - }; - - try { - _open_node_registry.apply<Open_node>(handle, close_fn); - } catch (Id_space<File_system::Node>::Unknown_id const &) { - throw Invalid_handle(); - } - } - - Status status(Node_handle node_handle) - { - auto status_fn = [&] (Open_node &open_node) { - - Status status; - status.inode = 1; - status.size = 0; - status.mode = 0; - - Node &node = open_node.node(); - - using namespace Fatfs; - - /* f_stat() does not work for the '/' directory */ - if (!is_root(node.name())) { - - FILINFO fatfs_file_info; - - FRESULT res = f_stat(node.name(), &fatfs_file_info); - - switch(res) { - case FR_OK: - break; - case FR_NO_FILE: - error("f_stat() failed with error code FR_NO_FILE"); - return status; - case FR_NO_PATH: - error("f_stat() failed with error code FR_NO_PATH"); - return status; - case FR_INVALID_NAME: - error("f_stat() failed with error code FR_INVALID_NAME"); - return status; - case FR_INVALID_DRIVE: - error("f_stat() failed with error code FR_INVALID_DRIVE"); - return status; - case FR_DISK_ERR: - error("f_stat() failed with error code FR_DISK_ERR"); - return status; - case FR_INT_ERR: - error("f_stat() failed with error code FR_INT_ERR"); - return status; - case FR_NOT_READY: - error("f_stat() failed with error code FR_NOT_READY"); - return status; - case FR_NOT_ENABLED: - error("f_stat() failed with error code FR_NOT_ENABLED"); - return status; - case FR_NO_FILESYSTEM: - error("f_stat() failed with error code FR_NO_FILESYSTEM"); - return status; - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_stat() returned an unexpected error code"); - return status; - } - - if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR) { - status.mode = File_system::Status::MODE_DIRECTORY; } - else { - status.mode = File_system::Status::MODE_FILE; - status.size = fatfs_file_info.fsize; - } - - } else { - status.mode = File_system::Status::MODE_DIRECTORY; - } - - if (status.mode == File_system::Status::MODE_DIRECTORY) { - - /* determine the number of directory entries */ - - Fatfs::DIR fatfs_dir; - FRESULT f_opendir_res = f_opendir(&fatfs_dir, node.name()); - - if (f_opendir_res != FR_OK) - return status; - - FILINFO fatfs_file_info; - - int num_direntries = -1; - do { - ++num_direntries; - FRESULT res = f_readdir(&fatfs_dir, &fatfs_file_info); - if (res != FR_OK) - return status; - } while (fatfs_file_info.fname[0] != 0); - - status.size = num_direntries * sizeof(Directory_entry); - } - - return status; - }; - - try { - return _open_node_registry.apply<Open_node>(node_handle, status_fn); - } catch (Id_space<File_system::Node>::Unknown_id const &) { - throw Invalid_handle(); - } - } - - void control(Node_handle, Control) { } - - void unlink(Dir_handle dir_handle, Name const &name) - { - if (!valid_filename(name.string())) - throw Invalid_name(); - - if (!_writable) - throw Permission_denied(); - - auto unlink_fn = [&] (Open_node &open_node) { - - using namespace Fatfs; - - Absolute_path absolute_path(_root.name()); - - try { - absolute_path.append(open_node.node().name()); - absolute_path.append("/"); - absolute_path.append(name.string()); - } catch (Path_base::Path_too_long) { - throw Invalid_name(); - } - - FRESULT res = f_unlink(absolute_path.base()); - - switch(res) { - case FR_OK: - break; - case FR_NO_FILE: - case FR_NO_PATH: - throw Lookup_failed(); - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - throw Invalid_name(); - case FR_DENIED: - case FR_WRITE_PROTECTED: - throw Permission_denied(); - case FR_DISK_ERR: - error("f_unlink() failed with error code FR_DISK_ERR"); - return; - case FR_INT_ERR: - error("f_unlink() failed with error code FR_INT_ERR"); - return; - case FR_NOT_READY: - error("f_unlink() failed with error code FR_NOT_READY"); - return; - case FR_NOT_ENABLED: - error("f_unlink() failed with error code FR_NOT_ENABLED"); - return; - case FR_NO_FILESYSTEM: - error("f_unlink() failed with error code FR_NO_FILESYSTEM"); - return; - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_unlink() returned an unexpected error code"); - return; - } - }; - - try { - _open_node_registry.apply<Open_node>(dir_handle, unlink_fn); - } catch (Id_space<File_system::Node>::Unknown_id const &) { - throw Invalid_handle(); - } - } - - void truncate(File_handle file_handle, file_size_t size) - { - if (!_writable) - throw Permission_denied(); - - auto truncate_fn = [&] (Open_node &open_node) { - open_node.node().truncate(size); - }; - - try { - _open_node_registry.apply<Open_node>(file_handle, truncate_fn); - } catch (Id_space<File_system::Node>::Unknown_id const &) { - throw Invalid_handle(); - } - } - - void move(Dir_handle from_dir_handle, Name const &from_name, - Dir_handle to_dir_handle, Name const &to_name) - { - if (!_writable) - throw Permission_denied(); - - if (!valid_filename(from_name.string())) - throw Lookup_failed(); - - if (!valid_filename(to_name.string())) - throw Invalid_name(); - - auto move_fn = [&] (Open_node &open_from_dir_node) { - - auto inner_move_fn = [&] (Open_node &open_to_dir_node) { - - Absolute_path absolute_from_path(_root.name()); - Absolute_path absolute_to_path(_root.name()); - - try { - absolute_from_path.append(open_from_dir_node.node().name()); - absolute_from_path.append("/"); - absolute_from_path.append(from_name.string()); - absolute_to_path.append(open_to_dir_node.node().name()); - absolute_to_path.append("/"); - absolute_to_path.append(to_name.string()); - } catch (Path_base::Path_too_long) { - throw Invalid_name(); - } - - using namespace Fatfs; - - FRESULT res = f_rename(absolute_from_path.base(), absolute_to_path.base()); - - /* if newpath already exists - try to unlink it once */ - if (res == FR_EXIST) { - f_unlink(absolute_to_path.base()); - res = f_rename(absolute_from_path.base(), absolute_to_path.base()); - } - - switch(res) { - case FR_OK: - break; - case FR_NO_FILE: - case FR_NO_PATH: - throw Lookup_failed(); - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - throw Invalid_name(); - case FR_EXIST: - error("f_rename() failed with error code FR_EXIST"); - throw Invalid_name(); - case FR_DENIED: - case FR_WRITE_PROTECTED: - throw Permission_denied(); - case FR_DISK_ERR: - error("f_rename() failed with error code FR_DISK_ERR"); - throw Lookup_failed(); - case FR_INT_ERR: - error("f_rename() failed with error code FR_INT_ERR"); - throw Lookup_failed(); - case FR_NOT_READY: - error("f_rename() failed with error code FR_NOT_READY"); - throw Lookup_failed(); - case FR_NOT_ENABLED: - error("f_rename() failed with error code FR_NOT_ENABLED"); - throw Lookup_failed(); - case FR_NO_FILESYSTEM: - error("f_rename() failed with error code FR_NO_FILESYSTEM"); - throw Lookup_failed(); - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_rename() returned an unexpected error code"); - throw Lookup_failed(); - } - }; - - try { - _open_node_registry.apply<Open_node>(to_dir_handle, inner_move_fn); - } catch (Id_space<File_system::Node>::Unknown_id const &) { - throw Invalid_handle(); - } - }; - - try { - _open_node_registry.apply<Open_node>(from_dir_handle, move_fn); - } catch (Id_space<File_system::Node>::Unknown_id const &) { - throw Invalid_handle(); - } - } - - void sigh(Node_handle, Genode::Signal_context_capability) - { - error("File_system::Session::sigh not supported"); - } -}; - - -class Fatfs_fs::Root : public Root_component<Session_component> -{ - private: - - Genode::Env &_env; - Genode::Allocator &_md_alloc; - Genode::Allocator &_heap; - Genode::Attached_rom_dataspace _config { _env, "config" }; - Directory &_root_dir; - - protected: - - Session_component *_create_session(const char *args) - { - /* - * Determine client-specific policy defined implicitly by - * the client's label. - */ - Directory *session_root_dir = 0; - bool writeable = false; - - typedef String<256> Root_path; - Root_path root; - - Session_label const label = label_from_args(args); - try { - Session_policy policy(label, _config.xml()); - - /* - * Determine directory that is used as root directory of - * the session. - */ - try { - policy.attribute("root").value(root); - if (is_root(root.string())) { - session_root_dir = &_root_dir; - } else { - /* - * Make sure the root path is specified with a - * leading path delimiter. For performing the - * lookup, we skip the first character. - */ - if (root.string()[0] != '/') - throw Lookup_failed(); - - /* Check if the root path exists */ - - using namespace Fatfs; - - FRESULT res = f_chdir(root.string()); - - switch(res) { - case FR_OK: - break; - case FR_NO_PATH: - throw Lookup_failed(); - case FR_INVALID_NAME: - case FR_INVALID_DRIVE: - throw Lookup_failed(); - case FR_NOT_READY: - error("f_chdir() failed with error code FR_NOT_READY"); - throw Service_denied(); - case FR_DISK_ERR: - error("f_chdir() failed with error code FR_DISK_ERR"); - throw Service_denied(); - case FR_INT_ERR: - error("f_chdir() failed with error code FR_INT_ERR"); - throw Service_denied(); - case FR_NOT_ENABLED: - error("f_chdir() failed with error code FR_NOT_ENABLED"); - throw Service_denied(); - case FR_NO_FILESYSTEM: - error("f_chdir() failed with error code FR_NO_FILESYSTEM"); - throw Service_denied(); - default: - /* not supposed to occur according to the fatfs documentation */ - error("f_chdir() returned an unexpected error code"); - throw Service_denied(); - } - - session_root_dir = new (&_md_alloc) Directory(root.string()); - } - } - catch (Xml_node::Nonexistent_attribute) { - error("missing \"root\" attribute in policy definition"); - throw Service_denied(); - } - catch (Lookup_failed) { - error("session root directory \"", root, "\" does not exist"); - throw Service_denied(); - } - - /* - * Determine if write access is permitted for the session. - */ - writeable = policy.attribute_value("writeable", false); - } - catch (Session_policy::No_policy_defined) { - error("Invalid session request, no matching policy"); - throw Service_denied(); - } - - size_t ram_quota = - Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); - size_t tx_buf_size = - Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); - - if (!tx_buf_size) { - error(label, " requested a session with a zero length transmission buffer"); - throw Service_denied(); - } - - /* - * Check if donated ram quota suffices for session data, - * and communication buffer. - */ - size_t session_size = sizeof(Session_component) + tx_buf_size; - if (max((size_t)4096, session_size) > ram_quota) { - error("insufficient 'ram_quota', got ", ram_quota, ", " - "need ", session_size); - throw Insufficient_ram_quota(); - } - return new (md_alloc()) - Session_component(_env, _heap, tx_buf_size, - *session_root_dir, writeable); - } - - public: - - /** - * Constructor - * - * \param env reference to Genode environment - * \param heap meta-data allocator - * \param root normal root directory if root in policy starts - * at root - */ - Root(Genode::Env &env, Allocator &md_alloc, Genode::Allocator &heap, - Directory &root) - : - Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc), - _env(env), _md_alloc(md_alloc), _heap(heap), _root_dir(root) - { } -}; - - -struct Fatfs_fs::Main -{ - Genode::Env &_env; - Genode::Heap _heap { _env.ram(), _env.rm() }; - Genode::Sliced_heap _sliced_heap { _env.ram(), _env.rm() }; - - Directory _root_dir { "/" }; - Root _root { _env, _sliced_heap, _heap, _root_dir }; - - Fatfs::FATFS _fatfs; - - Main(Genode::Env &env) : _env(env) - { - Fatfs::block_init(_env, _heap); - - using namespace File_system; - using namespace Fatfs; - - /* mount the file system */ - if (f_mount(&_fatfs, "", 0) != Fatfs::FR_OK) { - error("mount failed"); - - struct Mount_failed : Genode::Exception { }; - throw Mount_failed(); - } - - Genode::log("--- Starting Fatfs_fs ---"); - - _env.parent().announce(_env.ep().manage(_root)); - } -}; - - -void Component::construct(Genode::Env &env) -{ - /* XXX execute constructors of global statics */ - env.exec_static_constructors(); - - static Fatfs_fs::Main main(env); -} diff --git a/repos/libports/src/server/fatfs_fs/node.h b/repos/libports/src/server/fatfs_fs/node.h deleted file mode 100644 index d41629e2f..000000000 --- a/repos/libports/src/server/fatfs_fs/node.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * \brief FATFS file-system node - * \author Christian Prochaska - * \date 2012-07-04 - */ - -/* - * Copyright (C) 2012-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 _NODE_H_ -#define _NODE_H_ - -/* Genode includes */ -#include <file_system/node.h> -#include <base/log.h> -#include <os/path.h> - -/* fatfs includes */ -namespace Fatfs { extern "C" { -#include <fatfs/ff.h> -} } - -namespace Fatfs_fs { - using namespace File_system; - - typedef Genode::Path<FF_MAX_LFN + 1> Absolute_path; - - class Node; -} - - -class Fatfs_fs::Node : public Node_base -{ - protected: - - Absolute_path _name; - - public: - - Node(const char *name) : _name(name) { } - - char const *name() { return _name.base(); } - - /* - * A generic Node object can be created to represent a file or - * directory by its name without opening it, so the functions - * of this class must not be abstract. - */ - - virtual size_t read(char *dst, size_t len, seek_off_t) - { - Genode::error("read() called on generic Node object"); - return 0; - } - - virtual size_t write(char const *src, size_t len, seek_off_t) - { - Genode::error("write() called on generic Node object"); - return 0; - } - - /* - * File functionality - */ - virtual void truncate(file_size_t size) - { - Genode::error(__PRETTY_FUNCTION__, " called on a non-file node"); - } -}; - -#endif /* _NODE_H_ */ diff --git a/repos/libports/src/server/fatfs_fs/open_node.h b/repos/libports/src/server/fatfs_fs/open_node.h deleted file mode 100644 index 942976828..000000000 --- a/repos/libports/src/server/fatfs_fs/open_node.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * \brief Representation of an open file system node within the component (deprecated) - * \author Christian Prochaska - * \date 2017-06-09 - */ - -/* - * Copyright (C) 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 _OPEN_NODE_H_ -#define _OPEN_NODE_H_ - -/* Genode includes */ -#include <file_system/listener.h> -#include <file_system_session/file_system_session.h> - -namespace File_system { - /* - * \param NODE component-specific node type - */ - template <typename NODE> class Open_node; -} - -template <typename NODE> -class File_system::Open_node : public File_system::Node -{ - private: - - Genode::Id_space<File_system::Node>::Element _element; - - NODE &_node; - Genode::Constructible<File_system::Listener> _listener; - - Listener::Version const _version_when_opened = _node.curr_version(); - - /* - * Flag to track whether the underlying file-system node was - * modified via this 'Open_node'. That is, if closing the 'Open_node' - * should notify listeners of the file. - */ - bool _was_written = false; - - public: - - Open_node(NODE &node, Genode::Id_space<File_system::Node> &id_space) - : _element(*this, id_space), _node(node) { } - - ~Open_node() - { - if (_listener.constructed()) { - _node.remove_listener(&*_listener); - _listener.destruct(); - } - - /* - * Notify remaining listeners about the changed file - */ - if (_was_written) - _node.notify_listeners(); - } - - NODE &node() { return _node; } - File_system::Listener &listener() { return *_listener; } - - Genode::Id_space<File_system::Node>::Id id() { return _element.id(); } - - /** - * Register packet stream sink to be notified of node changes - */ - void register_notify(File_system::Sink &sink) - { - /* - * If there was already a handler registered for the node, - * remove the old handler. - */ - if (_listener.constructed()) { - _node.remove_listener(&*_listener); - _listener.destruct(); - } - - /* - * Register new handler - */ - _listener.construct(sink, id(), _version_when_opened); - _node.add_listener(&*_listener); - } - - void mark_as_written() { _was_written = true; } -}; - -#endif /* _OPEN_NODE_H_ */ diff --git a/repos/libports/src/server/fatfs_fs/target.mk b/repos/libports/src/server/fatfs_fs/target.mk deleted file mode 100644 index 917d5901b..000000000 --- a/repos/libports/src/server/fatfs_fs/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = fatfs_fs -SRC_CC = main.cc -LIBS = base fatfs_block -INC_DIR += $(PRG_DIR) - -CC_CXX_WARN_STRICT = diff --git a/repos/libports/src/server/fatfs_fs/util.h b/repos/libports/src/server/fatfs_fs/util.h deleted file mode 100644 index 36f7c1c42..000000000 --- a/repos/libports/src/server/fatfs_fs/util.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * \brief Utilities - * \author Norman Feske - * \author Christian Prochaska - * \date 2012-04-11 - */ - -#ifndef _UTIL_H_ -#define _UTIL_H_ - -/* Genode includes */ -#include <util/string.h> -#include <file_system/util.h> - - -/** - * Return true if null-terminated string 'substr' occurs in null-terminated - * string 'str' - */ -static bool string_contains(char const *str, char const *substr) -{ - using namespace Genode; - - size_t str_len = strlen(str); - size_t substr_len = strlen(substr); - - if (str_len < substr_len) - return false; - - for (size_t i = 0; i <= (str_len - substr_len); i++) - if (strcmp(&str[i], substr, substr_len) == 0) - return true; - - return false; -} - - -/** - * Return true if 'str' is a valid file name - */ -static inline bool valid_filename(char const *str) -{ - if (!str) return false; - - /* must have at least one character */ - if (str[0] == 0) return false; - - /* must not contain '/' or '\' or ':' */ - if (File_system::string_contains(str, '/') || - File_system::string_contains(str, '\\') || - File_system::string_contains(str, ':')) - return false; - - return true; -} - -/** - * Return true if 'str' is a valid path - */ -static inline bool valid_path(char const *str) -{ - if (!str) return false; - - /* must start with '/' */ - if (str[0] != '/') - return false; - - /* must not contain '\' or ':' */ - if (File_system::string_contains(str, '\\') || - File_system::string_contains(str, ':')) - return false; - - /* must not contain "/../" */ - if (string_contains(str, "/../")) return false; - - return true; -} - -/** - * Return true if 'str' is "/" - */ -static inline bool is_root(const char *str) -{ - return (Genode::strcmp(str, "/") == 0); -} - -#endif /* _UTIL_H_ */ diff --git a/repos/libports/src/test/libc/main.cc b/repos/libports/src/test/libc/main.cc index 40f184d1c..49170b16c 100644 --- a/repos/libports/src/test/libc/main.cc +++ b/repos/libports/src/test/libc/main.cc @@ -152,6 +152,31 @@ int main(int argc, char **argv) } } + { + /* test dup of stderr (issue #3477) */ + int const new_fd = dup(STDERR_FILENO); + if (new_fd < 0) { + printf("dup of stderr failed\n"); + ++error_count; + } else { + close(new_fd); + } + } + + { + /* test double dup2 (issue #3505) */ + int const new_fd = 17, another_new_fd = 18; + if (dup2(STDERR_FILENO, new_fd) == new_fd + && dup2(STDERR_FILENO, another_new_fd) == another_new_fd) { + + close(new_fd); + close(another_new_fd); + } else { + printf("dup2 of stderr failed\n"); + ++error_count; + } + } + perror("perror"); struct timespec ts; diff --git a/repos/libports/src/test/libc_fatfs/target.mk b/repos/libports/src/test/libc_fatfs/target.mk deleted file mode 100644 index 491222bb2..000000000 --- a/repos/libports/src/test/libc_fatfs/target.mk +++ /dev/null @@ -1,8 +0,0 @@ -TARGET = test-libc_fatfs -LIBS = libc libc_fatfs -SRC_CC = main.cc - -# we re-use the libc_vfs test -vpath main.cc $(REP_DIR)/src/test/libc_vfs - -CC_CXX_WARN_STRICT = diff --git a/repos/libports/src/test/libc_pipe/main.cc b/repos/libports/src/test/libc_pipe/main.cc index 816dc99bf..f4f691325 100644 --- a/repos/libports/src/test/libc_pipe/main.cc +++ b/repos/libports/src/test/libc_pipe/main.cc @@ -76,7 +76,8 @@ int main(int argc, char *argv[]) ssize_t bytes_written = write(pipefd[1], buf, BUF_SIZE); if (bytes_written != BUF_SIZE) { - fprintf(stderr, "Error writing to pipe\n"); + fprintf(stderr, "Error writing to pipe (bytes_written=%zd, BUF_SIZE=%zd)\n", + bytes_written, (size_t)BUF_SIZE); exit(1); } diff --git a/repos/libports/src/test/libc_pipe/target.mk b/repos/libports/src/test/libc_pipe/target.mk index fb24f5958..00bd7025e 100644 --- a/repos/libports/src/test/libc_pipe/target.mk +++ b/repos/libports/src/test/libc_pipe/target.mk @@ -1,5 +1,5 @@ TARGET = test-libc_pipe -LIBS = base posix libc_pipe +LIBS = base posix SRC_CC = main.cc CC_CXX_WARN_STRICT = diff --git a/repos/libports/src/test/pthread/main.cc b/repos/libports/src/test/pthread/main.cc index 428420451..827026abd 100644 --- a/repos/libports/src/test/pthread/main.cc +++ b/repos/libports/src/test/pthread/main.cc @@ -1,24 +1,28 @@ /* * \brief POSIX thread and semaphore test * \author Christian Prochaska + * \author Christian Helmuth * \date 2012-04-04 */ /* - * Copyright (C) 2012-2017 Genode Labs GmbH + * Copyright (C) 2012-2019 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. */ +/* libc include */ #include <pthread.h> #include <semaphore.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <unistd.h> - -enum { NUM_THREADS = 2 }; +/* Genode includes */ +#include <base/log.h> +#include <base/thread.h> struct Thread_args { @@ -34,7 +38,7 @@ struct Thread { }; -void *thread_func(void *arg) +static void *thread_func(void *arg) { Thread_args *thread_args = (Thread_args*)arg; @@ -53,12 +57,13 @@ void *thread_func(void *arg) return 0; } + /* * Test self-destructing threads with 'pthread_join()', both when created and * joined by the main thread and when created and joined by a pthread. */ -void test_self_destruct(void *(*start_routine)(void*), uintptr_t num_iterations) +static void self_destruct_helper(void *(*start_routine)(void*), uintptr_t num_iterations) { for (uintptr_t i = 0; i < num_iterations; i++) { @@ -71,7 +76,7 @@ void test_self_destruct(void *(*start_routine)(void*), uintptr_t num_iterations) } pthread_join(t, &retval); - + if (retval != (void*)i) { printf("error: return value does not match\n"); exit(-1); @@ -79,36 +84,467 @@ void test_self_destruct(void *(*start_routine)(void*), uintptr_t num_iterations) } } -void *thread_func_self_destruct2(void *arg) +static void *thread_func_self_destruct2(void *arg) { return arg; } -void *thread_func_self_destruct(void *arg) +static void *thread_func_self_destruct(void *arg) { - test_self_destruct(thread_func_self_destruct2, 2); + /* also test nesting of pthreads */ + self_destruct_helper(thread_func_self_destruct2, 2); return arg; } +static void test_self_destruct() +{ + printf("main thread: create self-destructing pthreads\n"); + + self_destruct_helper(thread_func_self_destruct, 100); +} + + static inline void compare_semaphore_values(int reported_value, int expected_value) { - if (reported_value != expected_value) { - printf("error: sem_getvalue() did not return the expected value\n"); - exit(-1); - } + if (reported_value != expected_value) { + printf("error: sem_getvalue() did not return the expected value\n"); + exit(-1); + } } -int main(int argc, char **argv) + +struct Test_mutex_data { - printf("--- pthread test ---\n"); + sem_t main_thread_ready_sem; + sem_t test_thread_ready_sem; + pthread_mutex_t recursive_mutex; + pthread_mutex_t errorcheck_mutex; - pthread_t pthread_main = pthread_self(); + Test_mutex_data() + { + sem_init(&main_thread_ready_sem, 0, 0); + sem_init(&test_thread_ready_sem, 0, 0); - printf("main thread: running, my thread ID is %p\n", pthread_main); - if (!pthread_main) - return -1; + pthread_mutexattr_t recursive_mutex_attr; + pthread_mutexattr_init(&recursive_mutex_attr); + pthread_mutexattr_settype(&recursive_mutex_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&recursive_mutex, &recursive_mutex_attr); + pthread_mutexattr_destroy(&recursive_mutex_attr); + + pthread_mutexattr_t errorcheck_mutex_attr; + pthread_mutexattr_init(&errorcheck_mutex_attr); + pthread_mutexattr_settype(&errorcheck_mutex_attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutex_init(&errorcheck_mutex, &errorcheck_mutex_attr); + pthread_mutexattr_destroy(&errorcheck_mutex_attr); + } + + ~Test_mutex_data() + { + pthread_mutex_destroy(&errorcheck_mutex); + pthread_mutex_destroy(&recursive_mutex); + } +}; + +static void *thread_mutex_func(void *arg) +{ + Test_mutex_data *test_mutex_data = (Test_mutex_data*)arg; + + /************************** + ** test recursive mutex ** + **************************/ + + /* test unlocking unlocked mutex - should fail */ + + if (pthread_mutex_unlock(&test_mutex_data->recursive_mutex) == 0) { + printf("Error: could unlock unlocked recursive mutex\n"); + exit(-1); + } + + /* test locking once - should succeed */ + + if (pthread_mutex_lock(&test_mutex_data->recursive_mutex) != 0) { + printf("Error: could not lock recursive mutex\n"); + exit(-1); + } + + /* test locking twice - should succeed */ + + if (pthread_mutex_lock(&test_mutex_data->recursive_mutex) != 0) { + printf("Error: could not lock recursive mutex twice\n"); + exit(-1); + } + + /* test unlocking once - should succeed */ + + if (pthread_mutex_unlock(&test_mutex_data->recursive_mutex) != 0) { + printf("Error: could not unlock recursive mutex\n"); + exit(-1); + } + + /* test unlocking twice - should succeed */ + + if (pthread_mutex_unlock(&test_mutex_data->recursive_mutex) != 0) { + printf("Error: could not unlock recursive mutex twice\n"); + exit(-1); + } + + /* test unlocking a third time - should fail */ + + if (pthread_mutex_unlock(&test_mutex_data->recursive_mutex) == 0) { + printf("Error: could unlock recursive mutex a third time\n"); + exit(-1); + } + + /* wake up main thread */ + sem_post(&test_mutex_data->test_thread_ready_sem); + + /* wait for main thread - it should have the mutex locked */ + sem_wait(&test_mutex_data->main_thread_ready_sem); + + /* test unlocking mutex which is locked by main thread - should fail */ + + if (pthread_mutex_unlock(&test_mutex_data->recursive_mutex) == 0) { + printf("Error: could unlock recursive mutex which is owned by other thread\n"); + exit(-1); + } + + /* wake up main thread */ + sem_post(&test_mutex_data->test_thread_ready_sem); + + /* wait for main thread */ + sem_wait(&test_mutex_data->main_thread_ready_sem); + + /*************************** + ** test errorcheck mutex ** + ***************************/ + + /* test unlocking unlocked mutex - should fail */ + + if (pthread_mutex_unlock(&test_mutex_data->errorcheck_mutex) == 0) { + printf("Error: could unlock unlocked errorcheck mutex\n"); + exit(-1); + } + + /* test locking once - should succeed */ + + if (pthread_mutex_lock(&test_mutex_data->errorcheck_mutex) != 0) { + printf("Error: could not lock errorcheck mutex\n"); + exit(-1); + } + + /* test locking twice - should fail */ + + if (pthread_mutex_lock(&test_mutex_data->errorcheck_mutex) == 0) { + printf("Error: could lock errorcheck mutex twice\n"); + exit(-1); + } + + /* test unlocking once - should succeed */ + + if (pthread_mutex_unlock(&test_mutex_data->errorcheck_mutex) != 0) { + printf("Error: could not unlock errorcheck mutex\n"); + exit(-1); + } + + /* test unlocking twice - should fail */ + + if (pthread_mutex_unlock(&test_mutex_data->errorcheck_mutex) == 0) { + printf("Error: could unlock errorcheck mutex twice\n"); + exit(-1); + } + + /* wake up main thread */ + sem_post(&test_mutex_data->test_thread_ready_sem); + + /* wait for main thread - it should have the mutex locked */ + sem_wait(&test_mutex_data->main_thread_ready_sem); + + /* test unlocking mutex which is locked by main thread */ + + if (pthread_mutex_unlock(&test_mutex_data->errorcheck_mutex) == 0) { + printf("Error: could unlock errorcheck mutex which is locked by other thread\n"); + exit(-1); + } + + /* wake up main thread */ + sem_post(&test_mutex_data->test_thread_ready_sem); + + return nullptr; +} + +static void test_mutex() +{ + printf("main thread: testing mutexes\n"); + + pthread_t t; + + Test_mutex_data test_mutex_data; + + if (pthread_create(&t, 0, thread_mutex_func, &test_mutex_data) != 0) { + printf("Error: pthread_create() failed\n"); + exit(-1); + } + + /* wait for test thread - recursive mutex should be unlocked */ + sem_wait(&test_mutex_data.test_thread_ready_sem); + + /* lock the recursive mutex and let the test thread attempt to unlock it */ + + if (pthread_mutex_lock(&test_mutex_data.recursive_mutex) != 0) { + printf("Error: could not lock recursive mutex from main thread\n"); + exit(-1); + } + + /* wake up test thread */ + sem_post(&test_mutex_data.main_thread_ready_sem); + + /* wait for test thread - recursive mutex should still be locked */ + sem_wait(&test_mutex_data.test_thread_ready_sem); + + /* unlock the recursive mutex - should succeed */ + + if (pthread_mutex_unlock(&test_mutex_data.recursive_mutex) != 0) { + printf("Error: could not unlock recursive mutex from main thread\n"); + exit(-1); + } + + /* wake up test thread */ + sem_post(&test_mutex_data.main_thread_ready_sem); + + /* wait for test thread - errorcheck mutex should be unlocked */ + sem_wait(&test_mutex_data.test_thread_ready_sem); + + /* lock the errorcheck mutex and let the test thread attempt to unlock it */ + + if (pthread_mutex_lock(&test_mutex_data.errorcheck_mutex) != 0) { + printf("Error: could not lock errorcheck mutex from main thread\n"); + exit(-1); + } + + /* wake up test thread */ + sem_post(&test_mutex_data.main_thread_ready_sem); + + /* wait for test thread - errorcheck mutex should still be locked */ + sem_wait(&test_mutex_data.test_thread_ready_sem); + + /* unlock the errorcheck mutex - should succeed */ + + if (pthread_mutex_unlock(&test_mutex_data.errorcheck_mutex) != 0) { + printf("Error: could not unlock errorcheck mutex from main thread\n"); + exit(-1); + } + + pthread_join(t, NULL); +} + + +template <pthread_mutextype MUTEX_TYPE> +struct Mutex +{ + static const char *type_string() + { + switch (MUTEX_TYPE) { + case PTHREAD_MUTEX_NORMAL: return "PTHREAD_MUTEX_NORMAL"; + case PTHREAD_MUTEX_ERRORCHECK: return "PTHREAD_MUTEX_ERRORCHECK"; + case PTHREAD_MUTEX_RECURSIVE: return "PTHREAD_MUTEX_RECURSIVE"; + + default: break; + } + return "<unexpected mutex type>"; + }; + + pthread_mutexattr_t _attr; + pthread_mutex_t _mutex; + + Mutex() + { + pthread_mutexattr_init(&_attr); + pthread_mutexattr_settype(&_attr, MUTEX_TYPE); + pthread_mutex_init(&_mutex, &_attr); + pthread_mutexattr_destroy(&_attr); + } + + ~Mutex() + { + pthread_mutex_destroy(&_mutex); + } + + pthread_mutex_t * mutex() { return &_mutex; } +}; + + +template <pthread_mutextype MUTEX_TYPE> +struct Test_mutex_stress +{ + Mutex<MUTEX_TYPE> mutex; + + struct Thread + { + pthread_mutex_t *_mutex; + sem_t _startup_sem; + pthread_t _thread; + + static void * _entry_trampoline(void *arg) + { + Thread *t = (Thread *)arg; + t->_entry(); + return nullptr; + } + + void _lock() + { + if (int const err = pthread_mutex_lock(_mutex)) + Genode::error("lock() returned ", err); + } + + void _unlock() + { + if (int const err = pthread_mutex_unlock(_mutex)) + Genode::error("unlock() returned ", err); + } + + void _entry() + { + sem_wait(&_startup_sem); + + enum { ROUNDS = 800 }; + + for (unsigned i = 0; i < ROUNDS; ++i) { + _lock(); + if (MUTEX_TYPE == PTHREAD_MUTEX_RECURSIVE) { + _lock(); + _lock(); + } + + /* stay in mutex for some time */ + for (unsigned volatile d = 0; d < 30000; ++d) ; + + if (MUTEX_TYPE == PTHREAD_MUTEX_RECURSIVE) { + _unlock(); + _unlock(); + } + _unlock(); + } + Genode::log("thread ", this, ": ", (int)ROUNDS, " rounds done"); + } + + Thread(pthread_mutex_t *mutex) : _mutex(mutex) + { + sem_init(&_startup_sem, 0, 0); + + if (pthread_create(&_thread, 0, _entry_trampoline, this) != 0) { + printf("Error: pthread_create() failed\n"); + exit(-1); + } + } + + void start() { sem_post(&_startup_sem); } + void join() { pthread_join(_thread, nullptr); } + } threads[10] = { + mutex.mutex(), mutex.mutex(), mutex.mutex(), mutex.mutex(), mutex.mutex(), + mutex.mutex(), mutex.mutex(), mutex.mutex(), mutex.mutex(), mutex.mutex(), + }; + + Test_mutex_stress() + { + printf("main thread: start %s stress test\n", mutex.type_string()); + for (Thread &t : threads) t.start(); + for (Thread &t : threads) t.join(); + printf("main thread: finished %s stress test\n", mutex.type_string()); + } +}; + + +extern "C" void wait_for_continue(); + +static void test_mutex_stress() +{ + printf("main thread: stressing mutexes\n"); + + { Test_mutex_stress<PTHREAD_MUTEX_NORMAL> test_normal; } + { Test_mutex_stress<PTHREAD_MUTEX_ERRORCHECK> test_errorcheck; } + { Test_mutex_stress<PTHREAD_MUTEX_RECURSIVE> test_recursive; } + + printf("main thread: mutex stress testing done\n"); +}; + + +/* + * Test if the main thread resumes sleeping lock holders when it itself is + * waiting for the lock. + */ + +template <pthread_mutextype MUTEX_TYPE> +struct Test_lock_and_sleep +{ + sem_t _startup; + Mutex<MUTEX_TYPE> _mutex; + + enum { SLEEP_MS = 500 }; + + static void *thread_fn(void *arg) + { + ((Test_lock_and_sleep *)arg)->sleeper(); + return nullptr; + } + + void sleeper() + { + printf("sleeper: aquire mutex\n"); + pthread_mutex_lock(_mutex.mutex()); + + printf("sleeper: about to wake up main thread\n"); + sem_post(&_startup); + + printf("sleeper: sleep %u ms\n", SLEEP_MS); + usleep(SLEEP_MS*1000); + + printf("sleeper: woke up, now release mutex\n"); + pthread_mutex_unlock(_mutex.mutex()); + } + + Test_lock_and_sleep() + { + sem_init(&_startup, 0, 0); + + printf("main thread: start %s test\n", _mutex.type_string()); + + pthread_t id; + if (pthread_create(&id, 0, thread_fn, this) != 0) { + printf("error: pthread_create() failed\n"); + exit(-1); + } + + sem_wait(&_startup); + + printf("main thread: sleeper woke me up, now aquire mutex (which blocks)\n"); + pthread_mutex_lock(_mutex.mutex()); + + printf("main thread: aquired mutex, now release mutex and finish\n"); + pthread_mutex_unlock(_mutex.mutex()); + + printf("main thread: finished %s test\n", _mutex.type_string()); + } +}; + + +static void test_lock_and_sleep() +{ + printf("main thread: test resume in contended lock\n"); + + { Test_lock_and_sleep<PTHREAD_MUTEX_NORMAL> test_normal; } + { Test_lock_and_sleep<PTHREAD_MUTEX_ERRORCHECK> test_errorcheck; } + { Test_lock_and_sleep<PTHREAD_MUTEX_RECURSIVE> test_recursive; } + + printf("main thread: resume in contended lock testing done\n"); +} + + +static void test_interplay() +{ + enum { NUM_THREADS = 2 }; Thread thread[NUM_THREADS]; @@ -120,7 +556,7 @@ int main(int argc, char **argv) if (sem_init(&thread[i].thread_args.thread_finished_sem, 0, 1) != 0) { printf("sem_init() failed\n"); - return -1; + exit(-1); } /* check result of 'sem_getvalue()' before and after calling 'sem_wait()' */ @@ -142,7 +578,7 @@ int main(int argc, char **argv) if (pthread_create(&thread[i].thread_id_create, 0, thread_func, &thread[i].thread_args) != 0) { printf("error: pthread_create() failed\n"); - return -1; + exit(-1); } printf("main thread: thread %d has thread ID %p\n", thread[i].thread_args.thread_num, thread[i].thread_id_create); @@ -158,7 +594,7 @@ int main(int argc, char **argv) for (int i = 0; i < NUM_THREADS; i++) if (thread[i].thread_args.thread_id_self != thread[i].thread_id_create) { printf("error: thread IDs don't match\n"); - return -1; + exit(-1); } printf("main thread: destroying the threads\n"); @@ -173,7 +609,7 @@ int main(int argc, char **argv) if (retval != PTHREAD_CANCELED) { printf("error: return value is not PTHREAD_CANCELED\n"); - return -1; + exit(-1); } } @@ -181,10 +617,24 @@ int main(int argc, char **argv) for (int i = 0; i < NUM_THREADS; i++) sem_destroy(&thread[i].thread_args.thread_finished_sem); +} - printf("main thread: create pthreads which self de-struct\n"); - test_self_destruct(thread_func_self_destruct, 100); +int main(int argc, char **argv) +{ + printf("--- pthread test ---\n"); + + pthread_t pthread_main = pthread_self(); + + printf("main thread: running, my thread ID is %p\n", pthread_main); + if (!pthread_main) + exit(-1); + + test_interplay(); + test_self_destruct(); + test_mutex(); + test_mutex_stress(); + test_lock_and_sleep(); printf("--- returning from main ---\n"); return 0; diff --git a/repos/libports/src/test/stdcxx/main.cc b/repos/libports/src/test/stdcxx/main.cc index a46a270d7..3abe83a22 100644 --- a/repos/libports/src/test/stdcxx/main.cc +++ b/repos/libports/src/test/stdcxx/main.cc @@ -57,7 +57,7 @@ static void test_stdexcept() { try { throw std::invalid_argument("INVALID"); - } catch (std::invalid_argument) { + } catch (std::invalid_argument &) { std::cout << "caught std::invalid_argument"<< std::endl; } } diff --git a/repos/libports/src/test/timed_semaphore/target.mk b/repos/libports/src/test/timed_semaphore/target.mk index e0439f85b..d850f3780 100644 --- a/repos/libports/src/test/timed_semaphore/target.mk +++ b/repos/libports/src/test/timed_semaphore/target.mk @@ -1,4 +1,4 @@ TARGET = test-timed_semaphore SRC_CC = main.cc LIBS = base -INC_DIR += $(REP_DIR)/src/lib/libc +INC_DIR += $(REP_DIR)/src/lib/libc/internal diff --git a/repos/os/include/cli_monitor/child.h b/repos/os/include/cli_monitor/child.h deleted file mode 100644 index 3550871d0..000000000 --- a/repos/os/include/cli_monitor/child.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * \brief Child handling - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-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__CLI_MONITOR__CHILD_H_ -#define _INCLUDE__CLI_MONITOR__CHILD_H_ - -/* Genode includes */ -#include <util/list.h> -#include <base/registry.h> -#include <base/child.h> -#include <init/child_policy.h> -#include <os/child_policy_dynamic_rom.h> -#include <cpu_session/connection.h> -#include <pd_session/connection.h> -#include <base/session_label.h> - -/* CLI-monitor includes */ -#include <cli_monitor/ram.h> - -namespace Cli_monitor { class Child_base; } - - -class Cli_monitor::Child_base : public Genode::Child_policy -{ - public: - - /* - * XXX derive donated quota from information to be provided by - * the used 'Connection' interfaces - */ - enum { DONATED_RAM_QUOTA = 128*1024 }; - - class Quota_exceeded : public Genode::Exception { }; - - typedef Genode::size_t size_t; - typedef Genode::Cap_quota Cap_quota; - - typedef Genode::Registered<Genode::Parent_service> Parent_service; - - private: - - Genode::Env &_env; - - Ram &_ram; - - Genode::Allocator &_alloc; - - Genode::Session_label const _label; - Binary_name const _binary_name; - - Genode::Pd_session_capability _ref_pd_cap; - Genode::Pd_session &_ref_pd; - - Cap_quota _cap_quota; - - size_t _ram_quota; - size_t _ram_limit; - - struct Parent_services : Genode::Registry<Parent_service> - { - Genode::Allocator &_alloc; - Parent_services(Genode::Allocator &alloc) : _alloc(alloc) { } - ~Parent_services() - { - for_each([&] (Parent_service &s) { Genode::destroy(_alloc, &s); }); - } - } _parent_services { _alloc }; - - enum { ENTRYPOINT_STACK_SIZE = 12*1024 }; - Genode::Rpc_entrypoint _entrypoint; - - Genode::Child_policy_dynamic_rom_file _config_policy; - - /** - * If set to true, immediately withdraw resources yielded by the child - */ - bool _withdraw_on_yield_response = false; - - /** - * Arguments of current resource request from the child - */ - Genode::Parent::Resource_args _resource_args { }; - - Genode::Signal_context_capability _yield_response_sigh_cap; - - Genode::Signal_context_capability _exit_sig_cap; - - /* true if child is scheduled for destruction */ - bool _exited = false; - - Genode::Child _child; - - Genode::Service &_matching_service(Genode::Service::Name const &name, - Genode::Session_label const &label) - { - Genode::Service *service = nullptr; - - /* check for config file request */ - if ((service = _config_policy.resolve_session_request(name, label))) - return *service; - - /* populate session-local parent service registry on demand */ - _parent_services.for_each([&] (Parent_service &s) { - if (s.name() == name) - service = &s; }); - - if (service) - return *service; - - return *new (_alloc) Parent_service(_parent_services, _env, name); - } - - public: - - /** - * Constructor - * - * \param ref_ram used as reference account for the child'd RAM - * session and for allocating the backing store - * for the child's configuration - * \param alloc allocator used to fill parent-service registry - * on demand - */ - Child_base(Genode::Env &env, - Ram &ram, - Genode::Allocator &alloc, - Name const &label, - Binary_name const &binary_name, - Genode::Pd_session &ref_pd, - Genode::Pd_session_capability ref_pd_cap, - Genode::Region_map &local_rm, - Cap_quota cap_quota, - Genode::size_t ram_quota, - Genode::size_t ram_limit, - Genode::Signal_context_capability yield_response_sig_cap, - Genode::Signal_context_capability exit_sig_cap) - : - _env(env), _ram(ram), _alloc(alloc), - _label(label), _binary_name(binary_name), - _ref_pd_cap (ref_pd_cap), _ref_pd (ref_pd), - _cap_quota(cap_quota), _ram_quota(ram_quota), _ram_limit(ram_limit), - _entrypoint(&ref_pd, ENTRYPOINT_STACK_SIZE, _label.string(), false), - _config_policy(local_rm, "config", _entrypoint, &_env.ram()), - _yield_response_sigh_cap(yield_response_sig_cap), - _exit_sig_cap(exit_sig_cap), - _child(local_rm, _entrypoint, *this) - { } - - Genode::Session_label label() const { return _label; } - - void configure(char const *config, size_t config_len) - { - _config_policy.load(config, config_len); - } - - void start() - { - _entrypoint.activate(); - } - - /** - * Issue yield request to the child - */ - void yield(size_t amount, bool greedy) - { - if (requested_ram_quota()) - return; /* resource request in flight */ - - char buf[128]; - Genode::snprintf(buf, sizeof(buf), "ram_quota=%ld", amount); - _withdraw_on_yield_response = greedy; - _child.yield(buf); - } - - /** - * Return amount of RAM currently requested by the child - */ - size_t requested_ram_quota() const - { - return Genode::Arg_string::find_arg(_resource_args.string(), "ram_quota").ulong_value(0); - } - - /** - * Withdraw quota from the child - * - * \throw Ram::Transfer_quota_failed - */ - void withdraw_ram_quota(size_t amount) - { - if (!amount) - return; - - _ram.withdraw_from(_child.pd_session_cap(), amount); - _ram_quota -= amount; - } - - /** - * Upgrade quota of child - * - * \throw Ram::Transfer_quota_failed - */ - void upgrade_ram_quota(size_t amount) - { - _ram.transfer_to(_child.pd_session_cap(), amount); - _ram_quota += amount; - - /* wake up child if resource request is in flight */ - size_t const req = requested_ram_quota(); - if (req && _child.pd().avail_ram().value >= req) { - _child.notify_resource_avail(); - - /* clear request state */ - _resource_args = Genode::Parent::Resource_args(""); - } - } - - /** - * Try to respond to a current resource request issued by the child - * - * This method evaluates the conditions, under which a resource - * request can be answered: There must be enough room between the - * current quota and the configured limit, and there must be enough - * slack memory available. If both conditions are met, the quota - * of the child gets upgraded. - */ - void try_response_to_resource_request() - { - size_t const req = requested_ram_quota(); - - if (!req) - return; /* no resource request in flight */ - - /* - * Respond to the current request if the requested quota fits - * within the limit and if there is enough free quota available. - */ - if (req <= _ram.status().avail && req + _ram_quota <= _ram_limit) { - try { upgrade_ram_quota(req); } - catch (Ram::Transfer_quota_failed) { } - } - } - - /** - * Set limit for on-demand RAM quota expansion - */ - void ram_limit(size_t limit) - { - _ram_limit = limit; - try_response_to_resource_request(); - } - - struct Ram_status - { - size_t quota = 0, limit = 0, xfer = 0, used = 0, avail = 0, req = 0; - - Ram_status() { } - Ram_status(size_t quota, size_t limit, size_t xfer, size_t used, - size_t avail, size_t req) - : - quota(quota), limit(limit), xfer(xfer), used(used), - avail(avail), req(req) - { } - }; - - /** - * Return RAM quota status of the child - * - * XXX should be a const method, but the 'Pd_session' accessors - * are not const - */ - Ram_status ram_status() - { - return Ram_status(_ram_quota, - _ram_limit, - _ram_quota - _child.pd().ram_quota().value, - _child.pd().used_ram().value, - _child.pd().avail_ram().value, - requested_ram_quota()); - } - - /** - * Return true if child exited and should be destructed - */ - bool exited() const { return _exited; } - - - /**************************** - ** Child_policy interface ** - ****************************/ - - Name name() const override { return _label; } - Binary_name binary_name() const override { return _binary_name; } - - Genode::Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; } - Genode::Pd_session &ref_pd() override { return _ref_pd; } - - void init(Genode::Pd_session &session, Genode::Pd_session_capability cap) override - { - session.ref_account(_ref_pd_cap); - _ref_pd.transfer_quota(cap, _cap_quota); - _ref_pd.transfer_quota(cap, Genode::Ram_quota{_ram_quota}); - } - - Route resolve_session_request(Genode::Service::Name const &name, - Genode::Session_label const &label) override - { - return Route { .service = _matching_service(name, label), - .label = label, - .diag = Genode::Session::Diag() }; - } - - void yield_response() override - { - if (_withdraw_on_yield_response) { - enum { RESERVE = 4*1024*1024 }; - - size_t amount = _child.pd().avail_ram().value < RESERVE - ? 0 : _child.pd().avail_ram().value - RESERVE; - - /* try to immediately withdraw freed-up resources */ - try { withdraw_ram_quota(amount); } - catch (Ram::Transfer_quota_failed) { } - } - - /* propagate yield-response signal */ - Genode::Signal_transmitter(_yield_response_sigh_cap).submit(); - } - - void resource_request(Genode::Parent::Resource_args const &args) override - { - _resource_args = args; - try_response_to_resource_request(); - } - - void exit(int exit_value) override - { - Genode::log("subsystem \"", name(), "\" exited with value ", exit_value); - _exited = true; - - /* trigger destruction of the child */ - Genode::Signal_transmitter(_exit_sig_cap).submit(); - } -}; - -#endif /* _INCLUDE__CLI_MONITOR__CHILD_H_ */ diff --git a/repos/os/include/cli_monitor/ram.h b/repos/os/include/cli_monitor/ram.h deleted file mode 100644 index 7f6a42ae2..000000000 --- a/repos/os/include/cli_monitor/ram.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * \brief RAM management - * \author Norman Feske - * \date 2013-10-14 - */ - -/* - * Copyright (C) 2013-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__CLI_MONITOR__RAM_H_ -#define _INCLUDE__CLI_MONITOR__RAM_H_ - -/* Genode includes */ -#include <pd_session/client.h> - -namespace Cli_monitor { class Ram; } - - -class Cli_monitor::Ram -{ - private: - - typedef Genode::size_t size_t; - - Genode::Pd_session &_pd; - Genode::Pd_session_capability _pd_cap; - - Genode::Lock mutable _lock { }; - - Genode::Signal_context_capability _yield_sigh; - Genode::Signal_context_capability _resource_avail_sigh; - - size_t _preserve; - - void _validate_preservation() - { - if (_pd.avail_ram().value < _preserve) - Genode::Signal_transmitter(_yield_sigh).submit(); - - /* verify to answer outstanding resource requests too */ - if (_pd.avail_ram().value > _preserve) - Genode::Signal_transmitter(_resource_avail_sigh).submit(); - } - - public: - - struct Status - { - size_t quota, used, avail, preserve; - Status(size_t quota, size_t used, size_t avail, size_t preserve) - : quota(quota), used(used), avail(avail), preserve(preserve) { } - }; - - Ram(Genode::Pd_session &pd, - Genode::Pd_session_capability pd_cap, - size_t preserve, - Genode::Signal_context_capability yield_sigh, - Genode::Signal_context_capability resource_avail_sigh) - : - _pd(pd), _pd_cap(pd_cap), - _yield_sigh(yield_sigh), - _resource_avail_sigh(resource_avail_sigh), - _preserve(preserve) - { } - - size_t preserve() const - { - Genode::Lock::Guard guard(_lock); - - return _preserve; - } - - void preserve(size_t preserve) - { - Genode::Lock::Guard guard(_lock); - - _preserve = preserve; - - _validate_preservation(); - } - - Status status() const - { - Genode::Lock::Guard guard(_lock); - - return Status(_pd.ram_quota().value, _pd.used_ram().value, - _pd.avail_ram().value, _preserve); - } - - void validate_preservation() - { - Genode::Lock::Guard guard(_lock); - - _validate_preservation(); - } - - /** - * Exception type - */ - class Transfer_quota_failed { }; - - /** - * \throw Transfer_quota_failed - */ - void withdraw_from(Genode::Pd_session_capability from, size_t amount) - { - using namespace Genode; - - Lock::Guard guard(_lock); - - try { Pd_session_client(from).transfer_quota(_pd_cap, Ram_quota{amount}); } - catch (...) { throw Transfer_quota_failed(); } - - Signal_transmitter(_resource_avail_sigh).submit(); - } - - /** - * \throw Transfer_quota_failed - */ - void transfer_to(Genode::Pd_session_capability to, size_t amount) - { - Genode::Lock::Guard guard(_lock); - - if (_pd.avail_ram().value < (_preserve + amount)) { - Genode::Signal_transmitter(_yield_sigh).submit(); - throw Transfer_quota_failed(); - } - - try { _pd.transfer_quota(to, Genode::Ram_quota{amount}); } - catch (...) { throw Transfer_quota_failed(); } - } - - size_t avail() const { return _pd.avail_ram().value; } -}; - -#endif /* _INCLUDE__CLI_MONITOR__RAM_H_ */ diff --git a/repos/os/include/file_system_session/file_system_session.h b/repos/os/include/file_system_session/file_system_session.h index 5c8ba3b08..0d085a0c8 100644 --- a/repos/os/include/file_system_session/file_system_session.h +++ b/repos/os/include/file_system_session/file_system_session.h @@ -16,6 +16,7 @@ #ifndef _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_ #define _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_ +#include <util/string.h> #include <base/exception.h> #include <os/packet_stream.h> #include <packet_stream_tx/packet_stream_tx.h> @@ -66,11 +67,45 @@ namespace File_system { typedef Symlink::Id Symlink_handle; typedef Watch::Id Watch_handle; + enum class Node_type { + DIRECTORY, + SYMLINK, + CONTINUOUS_FILE, + TRANSACTIONAL_FILE + }; + + struct Node_rwx + { + bool readable; + bool writeable; + bool executable; + }; + using Genode::size_t; typedef Genode::uint64_t seek_off_t; typedef Genode::uint64_t file_size_t; + struct Timestamp + { + /* + * The INVALID value is used whenever the underlying file system + * session does not support modification timestamps. The value is + * chosen such that it is unlikely to occur, instead of simply '0', + * which would correspond to plausible time (see comment below). + * This allows for handling this case explicitly. In any case, an + * invalid timestamp should not be used for doing any calculations. + */ + static constexpr Genode::int64_t INVALID = 0x7fffffffffffffffLL; + + /* + * The 'value' member contains the modification timestamp in seconds. + * Value '0' is defined as 1970-01-01T00:00:00Z, where a positive value + * covers all seconds after this date and a negative one all before. + */ + Genode::int64_t value; + }; + typedef Genode::Out_of_ram Out_of_ram; typedef Genode::Out_of_caps Out_of_caps; @@ -81,7 +116,7 @@ namespace File_system { */ enum Mode { STAT_ONLY = 0, READ_ONLY = 1, WRITE_ONLY = 2, READ_WRITE = 3 }; - enum { MAX_NAME_LEN = 256, MAX_PATH_LEN = 1024 }; + enum { MAX_NAME_LEN = 128, MAX_PATH_LEN = 1024 }; /** * File offset constant for reading or writing to the end of a file @@ -127,6 +162,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor enum Opcode { READ, WRITE, + WRITE_TIMESTAMP, CONTENT_CHANGED, READ_READY, @@ -143,9 +179,16 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor Node_handle _handle { 0 }; /* node handle */ Opcode _op; /* requested operation */ - seek_off_t _position; /* file seek offset in bytes */ - size_t _length; /* transaction length in bytes */ bool _success; /* indicates success of operation */ + union + { + struct + { + seek_off_t _position; /* file seek offset in bytes */ + size_t _length; /* transaction length in bytes */ + }; + Timestamp _modification_time; /* seconds since the Unix epoch */ + }; public: @@ -156,7 +199,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor Genode::size_t buf_size = 0) : Genode::Packet_descriptor(buf_offset, buf_size), - _op(READ), _position(0), _length(0), _success(false) { } + _op(READ), _success(false), _position(0), _length(0) { } /** * Constructor @@ -172,8 +215,8 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor seek_off_t position = SEEK_TAIL) : Genode::Packet_descriptor(p.offset(), p.size()), - _handle(handle), _op(op), - _position(position), _length(length), _success(false) + _handle(handle), _op(op), _success(false), + _position(position), _length(length) { } /** @@ -185,16 +228,33 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor Packet_descriptor(Node_handle handle, Opcode op) : Genode::Packet_descriptor(0, 0), - _handle(handle), _op(op), - _position(0), _length(0), _success(true) + _handle(handle), _op(op), _success(true), + _position(0), _length(0) + { } + + /** + * Constructor + */ + Packet_descriptor(Packet_descriptor p, Node_handle handle, Opcode op, Timestamp const &mtime) + : + Genode::Packet_descriptor(p.offset(), p.size()), + _handle(handle), _op(op), _success(false), + _modification_time(mtime) { } Node_handle handle() const { return _handle; } Opcode operation() const { return _op; } - seek_off_t position() const { return _position; } - size_t length() const { return _length; } + seek_off_t position() const { return _op != Opcode::WRITE_TIMESTAMP ? _position : 0; } + size_t length() const { return _op != Opcode::WRITE_TIMESTAMP ? _length : 0; } bool succeeded() const { return _success; } + template <typename FN> + void with_timestamp(FN const &fn) const + { + if (_op == Opcode::WRITE_TIMESTAMP) + fn(_modification_time); + } + /* * Accessors called at the server side */ @@ -205,30 +265,21 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor struct File_system::Status { - enum { - MODE_SYMLINK = 0020000, - MODE_FILE = 0100000, - MODE_DIRECTORY = 0040000, - }; - - /* - * XXX add access time - * XXX add executable bit - */ - file_size_t size; - unsigned mode; + Node_type type; + Node_rwx rwx; unsigned long inode; + Timestamp modification_time; /** * Return true if node is a directory */ - bool directory() const { return mode & MODE_DIRECTORY; } + bool directory() const { return type == Node_type::DIRECTORY; } /** * Return true if node is a symbolic link */ - bool symlink() const { return mode & MODE_SYMLINK; } + bool symlink() const { return type == Node_type::SYMLINK; } }; @@ -240,11 +291,27 @@ struct File_system::Control { /* to manipulate the executable bit */ }; */ struct File_system::Directory_entry { - enum Type { TYPE_FILE, TYPE_DIRECTORY, TYPE_SYMLINK }; + struct Name + { + char buf[MAX_NAME_LEN] { }; + + Name() { }; + Name(char const *name) { Genode::strncpy(buf, name, sizeof(buf)); } + }; unsigned long inode; - Type type; - char name[MAX_NAME_LEN]; + Node_type type; + Node_rwx rwx; + Name name; + + /** + * Sanitize object received from a file-system server as plain bytes + */ + void sanitize() + { + /* enforce null termination */ + name.buf[MAX_NAME_LEN - 1] = 0; + } }; diff --git a/repos/os/include/input/event.h b/repos/os/include/input/event.h index 393c8ec18..3cf00a6d8 100644 --- a/repos/os/include/input/event.h +++ b/repos/os/include/input/event.h @@ -141,7 +141,7 @@ class Input::Event template <typename FN> void handle_repeat(FN const &fn) const { - if (key_press(KEY_UNKNOWN) && _attr.press.codepoint.value) + if (key_press(KEY_UNKNOWN) && _attr.press.codepoint.valid()) fn(_attr.press.codepoint); } diff --git a/repos/os/include/os/reporter.h b/repos/os/include/os/reporter.h index ea27b4e76..6c32a669c 100644 --- a/repos/os/include/os/reporter.h +++ b/repos/os/include/os/reporter.h @@ -156,6 +156,8 @@ class Genode::Expanding_reporter typedef Session_label Label; typedef String<64> Node_type; + struct Initial_buffer_size { size_t value; }; + private: Env &_env; @@ -165,7 +167,7 @@ class Genode::Expanding_reporter Constructible<Reporter> _reporter { }; - size_t _buffer_size = 4096; + size_t _buffer_size; void _construct() { @@ -181,8 +183,10 @@ class Genode::Expanding_reporter public: - Expanding_reporter(Env &env, Node_type const &type, Label const &label) - : _env(env), _type(type), _label(label) { _construct(); } + Expanding_reporter(Env &env, Node_type const &type, Label const &label, + Initial_buffer_size const size = { 4096 }) + : _env(env), _type(type), _label(label), _buffer_size(size.value) + { _construct(); } template <typename FN> void generate(FN const &fn) diff --git a/repos/gems/include/gems/vfs.h b/repos/os/include/os/vfs.h similarity index 89% rename from repos/gems/include/gems/vfs.h rename to repos/os/include/os/vfs.h index 49823cba9..5070f68e4 100644 --- a/repos/gems/include/gems/vfs.h +++ b/repos/os/include/os/vfs.h @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _INCLUDE__GEMS__VFS_H_ -#define _INCLUDE__GEMS__VFS_H_ +#ifndef _INCLUDE__OS__VFS_H_ +#define _INCLUDE__OS__VFS_H_ /* Genode includes */ #include <base/env.h> @@ -56,20 +56,22 @@ struct Genode::Directory : Noncopyable, Interface { using Genode::print; using Vfs::Directory_service; + using Dirent_type = Directory_service::Dirent_type; - print(out, _dirent.name, " ("); + print(out, _dirent.name.buf, " ("); switch (_dirent.type) { - case Directory_service::DIRENT_TYPE_FILE: print(out, "file"); break; - case Directory_service::DIRENT_TYPE_DIRECTORY: print(out, "dir"); break; - case Directory_service::DIRENT_TYPE_SYMLINK: print(out, "symlink"); break; - default: print(out, "other"); break; + case Dirent_type::TRANSACTIONAL_FILE: print(out, "file"); break; + case Dirent_type::CONTINUOUS_FILE: print(out, "file"); break; + case Dirent_type::DIRECTORY: print(out, "dir"); break; + case Dirent_type::SYMLINK: print(out, "symlink"); break; + default: print(out, "other"); break; } print(out, ")"); } - typedef String<Vfs::Directory_service::DIRENT_MAX_NAME_LEN> Name; + typedef String<Vfs::Directory_service::Dirent::Name::MAX_LEN> Name; - Name name() const { return Name(Cstring(_dirent.name)); } + Name name() const { return Name(Cstring(_dirent.name.buf)); } Vfs::Directory_service::Dirent_type type() const { return _dirent.type; } }; @@ -118,16 +120,10 @@ struct Genode::Directory : Noncopyable, Interface return const_cast<Vfs::File_system &>(_fs); } - Vfs::Directory_service::Stat _stat(Path const &rel_path) const + Vfs::Directory_service::Stat_result _stat(Path const &rel_path, + Vfs::Directory_service::Stat &out) const { - Vfs::Directory_service::Stat stat; - - /* - * Ignore return value as the validity of the result is can be - * checked by the caller via 'stat.mode != 0'. - */ - _nonconst_fs().stat(join(_path, rel_path).string(), stat); - return stat; + return _nonconst_fs().stat(join(_path, rel_path).string(), out); } public: @@ -199,7 +195,7 @@ struct Genode::Directory : Noncopyable, Interface throw Read_dir_failed(); } - if (entry._dirent.type == Vfs::Directory_service::DIRENT_TYPE_END) + if (entry._dirent.type == Vfs::Directory_service::Dirent_type::END) return; fn(entry); @@ -215,12 +211,23 @@ struct Genode::Directory : Noncopyable, Interface bool file_exists(Path const &rel_path) const { - return _stat(rel_path).mode & Vfs::Directory_service::STAT_MODE_FILE; + Vfs::Directory_service::Stat stat { }; + + if (_stat(rel_path, stat) != Vfs::Directory_service::STAT_OK) + return false; + + return stat.type == Vfs::Node_type::TRANSACTIONAL_FILE + || stat.type == Vfs::Node_type::CONTINUOUS_FILE; } bool directory_exists(Path const &rel_path) const { - return _stat(rel_path).mode & Vfs::Directory_service::STAT_MODE_DIRECTORY; + Vfs::Directory_service::Stat stat { }; + + if (_stat(rel_path, stat) != Vfs::Directory_service::STAT_OK) + return false; + + return stat.type == Vfs::Node_type::DIRECTORY; } /** @@ -232,11 +239,16 @@ struct Genode::Directory : Noncopyable, Interface */ Vfs::file_size file_size(Path const &rel_path) const { - Vfs::Directory_service::Stat stat = _stat(rel_path); + Vfs::Directory_service::Stat stat { }; - if (!(stat.mode & Vfs::Directory_service::STAT_MODE_FILE)) + if (_stat(rel_path, stat) != Vfs::Directory_service::STAT_OK) throw Nonexistent_file(); - return stat.size; + + if (stat.type == Vfs::Node_type::TRANSACTIONAL_FILE + || stat.type == Vfs::Node_type::CONTINUOUS_FILE) + return stat.size; + + throw Nonexistent_file(); } /** @@ -607,4 +619,4 @@ class Genode::Watch_handler : public Vfs::Watch_response_handler, void watch_response() override { (_obj.*_member)(); } }; -#endif /* _INCLUDE__GEMS__VFS_H_ */ +#endif /* _INCLUDE__OS__VFS_H_ */ diff --git a/repos/os/include/packet_stream_rx/rpc_object.h b/repos/os/include/packet_stream_rx/rpc_object.h index 8366689ad..e3b255a54 100644 --- a/repos/os/include/packet_stream_rx/rpc_object.h +++ b/repos/os/include/packet_stream_rx/rpc_object.h @@ -26,7 +26,7 @@ class Packet_stream_rx::Rpc_object : public Genode::Rpc_object<CHANNEL, Rpc_obje private: Genode::Rpc_entrypoint &_ep; - Genode::Capability<CHANNEL> _cap; + Genode::Capability<CHANNEL> _cap { }; typename CHANNEL::Source _source; Genode::Signal_context_capability _sigh_ready_to_submit; @@ -48,11 +48,14 @@ class Packet_stream_rx::Rpc_object : public Genode::Rpc_object<CHANNEL, Rpc_obje Genode::Region_map &rm, Genode::Range_allocator &buffer_alloc, Genode::Rpc_entrypoint &ep) - : _ep(ep), _cap(_ep.manage(this)), _source(ds, rm, buffer_alloc), + : _ep(ep), _source(ds, rm, buffer_alloc), /* init signal handlers with default handlers of source */ _sigh_ready_to_submit(_source.sigh_ready_to_submit()), - _sigh_ack_avail(_source.sigh_ack_avail()) { } + _sigh_ack_avail(_source.sigh_ack_avail()) + { + _cap = _ep.manage(this); + } /** * Destructor diff --git a/repos/os/include/packet_stream_tx/rpc_object.h b/repos/os/include/packet_stream_tx/rpc_object.h index 02fdf4bbe..8c9abbf14 100644 --- a/repos/os/include/packet_stream_tx/rpc_object.h +++ b/repos/os/include/packet_stream_tx/rpc_object.h @@ -26,7 +26,7 @@ class Packet_stream_tx::Rpc_object : public Genode::Rpc_object<CHANNEL, Rpc_obje private: Genode::Rpc_entrypoint &_ep; - Genode::Capability<CHANNEL> _cap; + Genode::Capability<CHANNEL> _cap { }; typename CHANNEL::Sink _sink; Genode::Signal_context_capability _sigh_ready_to_ack; @@ -46,12 +46,14 @@ class Packet_stream_tx::Rpc_object : public Genode::Rpc_object<CHANNEL, Rpc_obje Genode::Region_map &rm, Genode::Rpc_entrypoint &ep) : - _ep(ep), _cap(_ep.manage(this)), _sink(ds, rm), + _ep(ep), _sink(ds, rm), /* init signal handlers with default handlers of sink */ _sigh_ready_to_ack(_sink.sigh_ready_to_ack()), _sigh_packet_avail(_sink.sigh_packet_avail()) - { } + { + _cap = _ep.manage(this); + } /** * Destructor diff --git a/repos/os/include/os/smbios.h b/repos/os/include/smbios/smbios.h similarity index 100% rename from repos/os/include/os/smbios.h rename to repos/os/include/smbios/smbios.h diff --git a/repos/os/include/vfs/dir_file_system.h b/repos/os/include/vfs/dir_file_system.h index 4da5fd47a..a7c240538 100644 --- a/repos/os/include/vfs/dir_file_system.h +++ b/repos/os/include/vfs/dir_file_system.h @@ -343,8 +343,8 @@ class Vfs::Dir_file_system : public File_system if (count < sizeof(Dirent)) return READ_ERR_INVALID; - Dirent *dirent = (Dirent*)dst; - *dirent = Dirent(); + Dirent &dirent = *(Dirent*)dst; + dirent = Dirent { }; out_count = sizeof(Dirent); @@ -456,12 +456,14 @@ class Vfs::Dir_file_system : public File_system * current directory. */ if (strlen(path) == 0 || _top_dir(path)) { - out.size = 0; - out.mode = STAT_MODE_DIRECTORY | 0755; - out.uid = 0; - out.gid = 0; - out.inode = 1; - out.device = (Genode::addr_t)this; + out = { + .size = 0, + .type = Node_type::DIRECTORY, + .rwx = Node_rwx::rwx(), + .inode = 1, + .device = (Genode::addr_t)this, + .modification_time = { Vfs::Timestamp::INVALID }, + }; return STAT_OK; } @@ -902,16 +904,28 @@ class Vfs::Dir_file_system : public File_system return _complete_read_of_file_systems(dir_vfs_handle, dst, count, out_count); if (_top_dir(dir_vfs_handle->path.base())) { - Dirent *dirent = (Dirent*)dst; - file_offset index = vfs_handle->seek() / sizeof(Dirent); + + Dirent &dirent = *(Dirent*)dst; + + file_offset const index = vfs_handle->seek() / sizeof(Dirent); if (index == 0) { - strncpy(dirent->name, _name.string(), sizeof(dirent->name)); - dirent->type = DIRENT_TYPE_DIRECTORY; - dirent->fileno = 1; + dirent = { + .fileno = 1, + .type = Dirent_type::DIRECTORY, + .rwx = Node_rwx::rwx(), + .name = { _name.string() } + }; + } else { - dirent->type = DIRENT_TYPE_END; + + dirent = { + .fileno = 0, + .type = Dirent_type::END, + .rwx = { }, + .name = { } + }; } out_count = sizeof(Dirent); diff --git a/repos/os/include/vfs/directory_service.h b/repos/os/include/vfs/directory_service.h index b678f4259..8f994a740 100644 --- a/repos/os/include/vfs/directory_service.h +++ b/repos/os/include/vfs/directory_service.h @@ -141,25 +141,14 @@ struct Vfs::Directory_service : Interface ** Stat ** **********/ - /** - * These values are the same as in the FreeBSD libc - */ - enum { - STAT_MODE_SYMLINK = 0120000, - STAT_MODE_FILE = 0100000, - STAT_MODE_DIRECTORY = 0040000, - STAT_MODE_CHARDEV = 0020000, - STAT_MODE_BLOCKDEV = 0060000, - }; - struct Stat { - file_size size = 0; - unsigned mode = 0; - unsigned uid = 0; - unsigned gid = 0; - unsigned long inode = 0; - unsigned long device = 0; + file_size size; + Node_type type; + Node_rwx rwx; + unsigned long inode; + unsigned long device; + Timestamp modification_time; }; enum Stat_result { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS, @@ -176,23 +165,42 @@ struct Vfs::Directory_service : Interface ** Dirent ** ************/ - enum { DIRENT_MAX_NAME_LEN = 128 }; - - enum Dirent_type { - DIRENT_TYPE_FILE, - DIRENT_TYPE_DIRECTORY, - DIRENT_TYPE_FIFO, - DIRENT_TYPE_CHARDEV, - DIRENT_TYPE_BLOCKDEV, - DIRENT_TYPE_SYMLINK, - DIRENT_TYPE_END + enum class Dirent_type + { + END, + DIRECTORY, + SYMLINK, + CONTINUOUS_FILE, + TRANSACTIONAL_FILE, }; struct Dirent { - unsigned long fileno = 0; - Dirent_type type = DIRENT_TYPE_END; - char name[DIRENT_MAX_NAME_LEN] = { 0 }; + struct Name + { + enum { MAX_LEN = 128 }; + char buf[MAX_LEN] { }; + + Name() { }; + Name(char const *name) { strncpy(buf, name, sizeof(buf)); } + }; + + unsigned long fileno; + Dirent_type type; + Node_rwx rwx; + Name name; + + /** + * Sanitize dirent members + * + * This method must be called after receiving a 'Dirent' as + * a plain data copy. + */ + void sanitize() + { + /* enforce null termination */ + name.buf[Name::MAX_LEN - 1] = 0; + } }; diff --git a/repos/os/include/vfs/file_io_service.h b/repos/os/include/vfs/file_io_service.h index 178a74b90..8ff8a5530 100644 --- a/repos/os/include/vfs/file_io_service.h +++ b/repos/os/include/vfs/file_io_service.h @@ -172,6 +172,20 @@ struct Vfs::File_io_service : Interface virtual bool queue_sync(Vfs_handle *) { return true; } virtual Sync_result complete_sync(Vfs_handle *) { return SYNC_OK; } + + /*********************** + ** Modification time ** + ***********************/ + + /** + * Update the modification time of a file + * + * \return true if update attempt was successful + */ + virtual bool update_modification_timestamp(Vfs_handle *, Vfs::Timestamp) + { + return true; + } }; #endif /* _INCLUDE__VFS__FILE_IO_SERVICE_H_ */ diff --git a/repos/os/include/vfs/readonly_value_file_system.h b/repos/os/include/vfs/readonly_value_file_system.h index 7f0184086..6ca1cab33 100644 --- a/repos/os/include/vfs/readonly_value_file_system.h +++ b/repos/os/include/vfs/readonly_value_file_system.h @@ -84,12 +84,17 @@ class Vfs::Readonly_value_file_system : public Vfs::Single_file_system return Config(Genode::Cstring(buf)); } + typedef Genode::Registered<Vfs_watch_handle> Registered_watch_handle; + typedef Genode::Registry<Registered_watch_handle> Watch_handle_registry; + + Watch_handle_registry _handle_registry { }; + public: Readonly_value_file_system(Name const &name, T const &initial_value) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, type(), - Xml_node(_config(name).string())), + Single_file_system(Node_type::TRANSACTIONAL_FILE, type(), + Node_rwx::ro(), Xml_node(_config(name).string())), _file_name(name) { value(initial_value); @@ -99,7 +104,13 @@ class Vfs::Readonly_value_file_system : public Vfs::Single_file_system char const *type() override { return type_name(); } - void value(T const &value) { _buffer = Buffer(value); } + void value(T const &value) + { + _buffer = Buffer(value); + + _handle_registry.for_each([this] (Registered_watch_handle &handle) { + handle.watch_response(); }); + } bool matches(Xml_node node) const { @@ -107,6 +118,7 @@ class Vfs::Readonly_value_file_system : public Vfs::Single_file_system node.attribute_value("name", Name()) == _file_name; } + /********************************* ** Directory-service interface ** *********************************/ @@ -131,10 +143,32 @@ class Vfs::Readonly_value_file_system : public Vfs::Single_file_system Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.mode |= 0444; out.size = _buffer.length(); return result; } + + Watch_result watch(char const *path, + Vfs_watch_handle **handle, + Allocator &alloc) override + { + if (!_single_file(path)) + return WATCH_ERR_UNACCESSIBLE; + + try { + *handle = new (alloc) + Registered_watch_handle(_handle_registry, *this, alloc); + + return WATCH_OK; + } + catch (Genode::Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Genode::Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } + } + + void close(Vfs_watch_handle *handle) override + { + Genode::destroy(handle->alloc(), + static_cast<Registered_watch_handle *>(handle)); + } }; #endif /* _INCLUDE__VFS__READONLY_VALUE_FILE_SYSTEM_H_ */ diff --git a/repos/os/include/vfs/single_file_system.h b/repos/os/include/vfs/single_file_system.h index a06a6856b..ba5db3b3f 100644 --- a/repos/os/include/vfs/single_file_system.h +++ b/repos/os/include/vfs/single_file_system.h @@ -22,16 +22,10 @@ namespace Vfs { class Single_file_system; } class Vfs::Single_file_system : public File_system { - public: - - enum Node_type { - NODE_TYPE_FILE, NODE_TYPE_SYMLINK, - NODE_TYPE_CHAR_DEVICE, NODE_TYPE_BLOCK_DEVICE - }; - private: - Node_type const _node_type; + Node_type const _type; + Node_rwx const _rwx; typedef String<64> Filename; @@ -61,8 +55,10 @@ class Vfs::Single_file_system : public File_system { private: - Node_type _node_type; - char const *_filename; + Node_type const _type; + Node_rwx const _rwx; + + Filename const &_filename; /* * Noncopyable @@ -75,12 +71,12 @@ class Vfs::Single_file_system : public File_system Single_vfs_dir_handle(Directory_service &ds, File_io_service &fs, Genode::Allocator &alloc, - Node_type node_type, - char const *filename) + Node_type type, + Node_rwx rwx, + Filename const &filename) : Single_vfs_handle(ds, fs, alloc, 0), - _node_type(node_type), - _filename(filename) + _type(type), _rwx(rwx), _filename(filename) { } Read_result read(char *dst, file_size count, @@ -93,19 +89,33 @@ class Vfs::Single_file_system : public File_system file_size index = seek() / sizeof(Dirent); - Dirent *out = (Dirent*)dst; + Dirent &out = *(Dirent*)dst; + + auto dirent_type = [&] () + { + switch (_type) { + case Node_type::DIRECTORY: return Dirent_type::DIRECTORY; + case Node_type::SYMLINK: return Dirent_type::SYMLINK; + case Node_type::CONTINUOUS_FILE: return Dirent_type::CONTINUOUS_FILE; + case Node_type::TRANSACTIONAL_FILE: return Dirent_type::TRANSACTIONAL_FILE; + } + return Dirent_type::END; + }; if (index == 0) { - out->fileno = (Genode::addr_t)this; - switch (_node_type) { - case NODE_TYPE_FILE: out->type = DIRENT_TYPE_FILE; break; - case NODE_TYPE_SYMLINK: out->type = DIRENT_TYPE_SYMLINK; break; - case NODE_TYPE_CHAR_DEVICE: out->type = DIRENT_TYPE_CHARDEV; break; - case NODE_TYPE_BLOCK_DEVICE: out->type = DIRENT_TYPE_BLOCKDEV; break; - } - strncpy(out->name, _filename, sizeof(out->name)); + out = { + .fileno = (Genode::addr_t)this, + .type = dirent_type(), + .rwx = _rwx, + .name = { _filename.string() } + }; } else { - out->type = DIRENT_TYPE_END; + out = { + .fileno = (Genode::addr_t)this, + .type = Dirent_type::END, + .rwx = { }, + .name = { } + }; } out_count = sizeof(Dirent); @@ -134,9 +144,12 @@ class Vfs::Single_file_system : public File_system public: - Single_file_system(Node_type node_type, char const *type_name, Xml_node config) + Single_file_system(Node_type node_type, + char const *type_name, + Node_rwx rwx, + Xml_node config) : - _node_type(node_type), + _type(node_type), _rwx(rwx), _filename(config.attribute_value("name", Filename(type_name))) { } @@ -154,19 +167,15 @@ class Vfs::Single_file_system : public File_system Stat_result stat(char const *path, Stat &out) override { - out = Stat(); + out = Stat { }; out.device = (Genode::addr_t)this; if (_root(path)) { - out.mode = STAT_MODE_DIRECTORY; + out.type = Node_type::DIRECTORY; } else if (_single_file(path)) { - switch (_node_type) { - case NODE_TYPE_FILE: out.mode = STAT_MODE_FILE; break; - case NODE_TYPE_SYMLINK: out.mode = STAT_MODE_SYMLINK; break; - case NODE_TYPE_CHAR_DEVICE: out.mode = STAT_MODE_CHARDEV; break; - case NODE_TYPE_BLOCK_DEVICE: out.mode = STAT_MODE_BLOCKDEV; break; - } + out.type = _type; + out.rwx = _rwx; out.inode = 1; } else { return STAT_ERR_NO_ENTRY; @@ -208,7 +217,7 @@ class Vfs::Single_file_system : public File_system try { *out_handle = new (alloc) Single_vfs_dir_handle(*this, *this, alloc, - _node_type, _filename.string()); + _type, _rwx, _filename); return OPENDIR_OK; } catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; } diff --git a/repos/os/include/vfs/types.h b/repos/os/include/vfs/types.h index f4f555e89..a004162ed 100644 --- a/repos/os/include/vfs/types.h +++ b/repos/os/include/vfs/types.h @@ -49,6 +49,46 @@ namespace Vfs { using Genode::Interface; using Genode::String; + struct Timestamp + { + static constexpr Genode::int64_t INVALID = 0x7fffffffffffffffLL; + Genode::int64_t value; + }; + + enum class Node_type { + DIRECTORY, + SYMLINK, + CONTINUOUS_FILE, + TRANSACTIONAL_FILE + }; + + struct Node_rwx + { + bool readable; + bool writeable; + bool executable; + + static Node_rwx ro() { return { .readable = true, + .writeable = false, + .executable = false }; } + + static Node_rwx wo() { return { .readable = false, + .writeable = true, + .executable = false }; } + + static Node_rwx rw() { return { .readable = true, + .writeable = true, + .executable = false }; } + + static Node_rwx rx() { return { .readable = true, + .writeable = false, + .executable = true }; } + + static Node_rwx rwx() { return { .readable = true, + .writeable = false, + .executable = true }; } + }; + typedef Genode::Path<MAX_PATH_LEN> Absolute_path; } diff --git a/repos/os/recipes/api/file_system_session/hash b/repos/os/recipes/api/file_system_session/hash index a3d3f6050..d23044d14 100644 --- a/repos/os/recipes/api/file_system_session/hash +++ b/repos/os/recipes/api/file_system_session/hash @@ -1 +1 @@ -2019-02-25 091cb572394df3b965d3e4ec9e8cc47fe175feb4 +2019-11-18 5115a9a9f121713940ddee9fa24e32589ad8f243 diff --git a/repos/os/recipes/api/input_session/hash b/repos/os/recipes/api/input_session/hash index 1ac803565..b52f12114 100644 --- a/repos/os/recipes/api/input_session/hash +++ b/repos/os/recipes/api/input_session/hash @@ -1 +1 @@ -2019-08-27 f03edba9c4f4f8b36c5f5836b7f81a3ad7c5674d +2019-11-18 eeee30dca9361c547c46b00a6be73e0001552faf diff --git a/repos/os/recipes/api/os/hash b/repos/os/recipes/api/os/hash index aeb34f03a..f89768dfb 100644 --- a/repos/os/recipes/api/os/hash +++ b/repos/os/recipes/api/os/hash @@ -1 +1 @@ -2019-08-27 1a4cdebf3c7a67f9054cd9d0cc357cf701de77fb +2019-11-18 53b774aad58c3bc17bb604f1ac511524963fe2a6 diff --git a/repos/os/recipes/api/vfs/hash b/repos/os/recipes/api/vfs/hash index fd81bd6c6..6443fdd5f 100644 --- a/repos/os/recipes/api/vfs/hash +++ b/repos/os/recipes/api/vfs/hash @@ -1 +1 @@ -2019-04-07 35a9cdab5b0925e8ff9e72236f55ff55b7ecae11 +2019-11-25 46c3ec8686f774d5ebaf763fe9d62dc55bcc0554 diff --git a/repos/os/recipes/pkg/chroot/hash b/repos/os/recipes/pkg/chroot/hash index b1f73b590..81cd82b11 100644 --- a/repos/os/recipes/pkg/chroot/hash +++ b/repos/os/recipes/pkg/chroot/hash @@ -1 +1 @@ -2019-09-19 a4007ef52a71b4be5961ded2b10595a870937fa5 +2019-11-25 ad594adf9889d01d6fdfaaa822b12683bcadc2c1 diff --git a/repos/os/recipes/pkg/clipboard/hash b/repos/os/recipes/pkg/clipboard/hash index 422ba5785..8378ccaf1 100644 --- a/repos/os/recipes/pkg/clipboard/hash +++ b/repos/os/recipes/pkg/clipboard/hash @@ -1 +1 @@ -2019-09-19 212853809db87023ef3039b3f8e62cd5963be609 +2019-11-25 c5dcfc1d6fb76e9493e8c72ffc7c6a82de97faac diff --git a/repos/os/recipes/pkg/drivers_interactive-imx53_qsb/hash b/repos/os/recipes/pkg/drivers_interactive-imx53_qsb/hash index a1d816182..06303e1fa 100644 --- a/repos/os/recipes/pkg/drivers_interactive-imx53_qsb/hash +++ b/repos/os/recipes/pkg/drivers_interactive-imx53_qsb/hash @@ -1 +1 @@ -2019-09-19 f493a7016eab8ab36e1f77efc46fd2e62b64bf00 +2019-11-25 e6e9ce0845b32577638a070c8efe550163d02d8a diff --git a/repos/os/recipes/pkg/drivers_interactive-linux/hash b/repos/os/recipes/pkg/drivers_interactive-linux/hash index 1489f6b3c..468cafd4b 100644 --- a/repos/os/recipes/pkg/drivers_interactive-linux/hash +++ b/repos/os/recipes/pkg/drivers_interactive-linux/hash @@ -1 +1 @@ -2019-09-19 d89e11f46840b2982b929f40c64b7bac812f3139 +2019-11-25 f6dfb167f8ab92b5871b637486e26dfb4c1b6860 diff --git a/repos/os/recipes/pkg/drivers_interactive-muen/hash b/repos/os/recipes/pkg/drivers_interactive-muen/hash index 9dcb222fb..d42ae0548 100644 --- a/repos/os/recipes/pkg/drivers_interactive-muen/hash +++ b/repos/os/recipes/pkg/drivers_interactive-muen/hash @@ -1 +1 @@ -2019-09-19 1f52f164632bd10ff8662a633c738c4a1e0c1d68 +2019-11-25 79d6d27d24fbc8a8bb157260878536503ca96ff8 diff --git a/repos/os/recipes/pkg/drivers_interactive-pbxa9/hash b/repos/os/recipes/pkg/drivers_interactive-pbxa9/hash index 8acc376c8..f8b7fc80e 100644 --- a/repos/os/recipes/pkg/drivers_interactive-pbxa9/hash +++ b/repos/os/recipes/pkg/drivers_interactive-pbxa9/hash @@ -1 +1 @@ -2019-09-19 595a68d42cd7187fecab51701edae6052a87cc48 +2019-11-25 005d3b5cc9dc764b2db37254e6a627bbbb00c3ec diff --git a/repos/os/recipes/pkg/drivers_interactive-pc/hash b/repos/os/recipes/pkg/drivers_interactive-pc/hash index 702d130d3..4353ae59d 100644 --- a/repos/os/recipes/pkg/drivers_interactive-pc/hash +++ b/repos/os/recipes/pkg/drivers_interactive-pc/hash @@ -1 +1 @@ -2019-09-19 4570b6fd68609b5702b18e5ec29be15e0cce47ba +2019-11-25 70ec4b9751c973d6521f5823d5ef88a1fd567163 diff --git a/repos/os/recipes/pkg/drivers_nic-linux/hash b/repos/os/recipes/pkg/drivers_nic-linux/hash index 013fbcdc7..6e6e8beba 100644 --- a/repos/os/recipes/pkg/drivers_nic-linux/hash +++ b/repos/os/recipes/pkg/drivers_nic-linux/hash @@ -1 +1 @@ -2019-09-19 a2a53dbd227174de355a894e051f0b0e3d1886e6 +2019-11-25 63d02d11f4a5314d74fea2256e1467c417746554 diff --git a/repos/os/recipes/pkg/drivers_nic-pbxa9/hash b/repos/os/recipes/pkg/drivers_nic-pbxa9/hash index 55cc0e496..570bf8321 100644 --- a/repos/os/recipes/pkg/drivers_nic-pbxa9/hash +++ b/repos/os/recipes/pkg/drivers_nic-pbxa9/hash @@ -1 +1 @@ -2019-09-19 a28379e560a09969a3767ff32d1d0c91aa8a736d +2019-11-25 1e800d45e0c7286c7fa8e753aee0249be849760f diff --git a/repos/os/recipes/pkg/drivers_nic-zynq/hash b/repos/os/recipes/pkg/drivers_nic-zynq/hash index 0c079111b..414c83e3a 100644 --- a/repos/os/recipes/pkg/drivers_nic-zynq/hash +++ b/repos/os/recipes/pkg/drivers_nic-zynq/hash @@ -1 +1 @@ -2019-09-19 3fbacdc35daea40eafc3c439ad6405ac8c80479b +2019-11-25 f5717d5e429a64ebc31c077fbe7975e7e1962d9b diff --git a/repos/os/recipes/pkg/fs_rom/hash b/repos/os/recipes/pkg/fs_rom/hash index 9ce20ad06..8c2dffb57 100644 --- a/repos/os/recipes/pkg/fs_rom/hash +++ b/repos/os/recipes/pkg/fs_rom/hash @@ -1 +1 @@ -2019-09-19 171523ff1bc69c558b7e4fe6d6a2f4f629f756ac +2019-11-25 9beb14638a5dd63cb66027af02f5394550548aae diff --git a/repos/os/recipes/pkg/mixer/hash b/repos/os/recipes/pkg/mixer/hash index be14d7469..d625ab860 100644 --- a/repos/os/recipes/pkg/mixer/hash +++ b/repos/os/recipes/pkg/mixer/hash @@ -1 +1 @@ -2019-09-19 e2e32a20c82448569b954e44638e4f47e065b53b +2019-11-25 730ebd9df0975ccff551f88ffd0248b51c805e61 diff --git a/repos/os/recipes/pkg/nic_router-nat/hash b/repos/os/recipes/pkg/nic_router-nat/hash index 3978e358b..5240529fc 100644 --- a/repos/os/recipes/pkg/nic_router-nat/hash +++ b/repos/os/recipes/pkg/nic_router-nat/hash @@ -1 +1 @@ -2019-09-19 ec2c3b3081c1c8a56bc8bfd8dddfcbb7952438b2 +2019-11-25 acde4464647c3a984ef95365e82f1da056ce57e2 diff --git a/repos/os/recipes/pkg/nit_focus/hash b/repos/os/recipes/pkg/nit_focus/hash index 185d6f456..150502d94 100644 --- a/repos/os/recipes/pkg/nit_focus/hash +++ b/repos/os/recipes/pkg/nit_focus/hash @@ -1 +1 @@ -2019-09-19 eab8f12b3ef4b791b5d4b2f441429e047baad45f +2019-11-25 e893a50991e76769584e3fc0e11b8bde76f32ae6 diff --git a/repos/os/recipes/pkg/rom_filter/hash b/repos/os/recipes/pkg/rom_filter/hash index 06d4473e9..7175b8244 100644 --- a/repos/os/recipes/pkg/rom_filter/hash +++ b/repos/os/recipes/pkg/rom_filter/hash @@ -1 +1 @@ -2019-09-19 eadcacf984e0f37cb225204b5354f03f06eaa007 +2019-11-25 c79bb6efa19f7db61852f9baad58d7d6517c862e diff --git a/repos/os/recipes/pkg/rom_reporter/hash b/repos/os/recipes/pkg/rom_reporter/hash index 4478575c8..96022ec7b 100644 --- a/repos/os/recipes/pkg/rom_reporter/hash +++ b/repos/os/recipes/pkg/rom_reporter/hash @@ -1 +1 @@ -2019-09-19 22ad5f4a1c110456a07c32bdb1e484c6350df24a +2019-11-25 df3b4d189ddc005bee4f7f748792a2bcf2b1cc3e diff --git a/repos/os/recipes/pkg/test-block/hash b/repos/os/recipes/pkg/test-block/hash index 623cd9ec2..c54108365 100644 --- a/repos/os/recipes/pkg/test-block/hash +++ b/repos/os/recipes/pkg/test-block/hash @@ -1 +1 @@ -2019-09-19 b156b3559e86197a86e5727a3c7529cafa90cd87 +2019-11-25 6a92298bec21d8b79f1f80d728a5278cc14fb3a6 diff --git a/repos/os/recipes/pkg/test-block_cache/hash b/repos/os/recipes/pkg/test-block_cache/hash index 652881128..63eaf2a44 100644 --- a/repos/os/recipes/pkg/test-block_cache/hash +++ b/repos/os/recipes/pkg/test-block_cache/hash @@ -1 +1 @@ -2019-09-19 7812ce2a2910601fda18ab512650ac6312997ffb +2019-11-25 cf98e57bb8d91e09c92e6a6c6062cab47196a752 diff --git a/repos/os/recipes/pkg/test-clipboard/hash b/repos/os/recipes/pkg/test-clipboard/hash index d5b39a921..2ac592f89 100644 --- a/repos/os/recipes/pkg/test-clipboard/hash +++ b/repos/os/recipes/pkg/test-clipboard/hash @@ -1 +1 @@ -2019-09-19 f68c9445cf1c79c4af17f62547bf7a346d11c15a +2019-11-25 e0ae3f636d7c9806ad2236ddb1f2c389f3002bee diff --git a/repos/os/recipes/pkg/test-dynamic_config/hash b/repos/os/recipes/pkg/test-dynamic_config/hash index d560c1fd6..5a95c2eca 100644 --- a/repos/os/recipes/pkg/test-dynamic_config/hash +++ b/repos/os/recipes/pkg/test-dynamic_config/hash @@ -1 +1 @@ -2019-09-19 271206745f732f94948c81be6a0051acc8546260 +2019-11-25 cff57aa56728f5c29207f53e5f138a218a79e3f1 diff --git a/repos/os/recipes/pkg/test-dynamic_config_loader/hash b/repos/os/recipes/pkg/test-dynamic_config_loader/hash index 37c916f33..aa418eb4b 100644 --- a/repos/os/recipes/pkg/test-dynamic_config_loader/hash +++ b/repos/os/recipes/pkg/test-dynamic_config_loader/hash @@ -1 +1 @@ -2019-09-19 c66631ef8429fd05c2a5dc76191960765cf8c44e +2019-11-25 cb9dc43fb99ab13488aa6a8f46c107b1dcd0bb73 diff --git a/repos/os/recipes/pkg/test-dynamic_config_slave/hash b/repos/os/recipes/pkg/test-dynamic_config_slave/hash index 3a8f3a080..d99570145 100644 --- a/repos/os/recipes/pkg/test-dynamic_config_slave/hash +++ b/repos/os/recipes/pkg/test-dynamic_config_slave/hash @@ -1 +1 @@ -2019-09-19 d75056c9285abb3327de739871142dcb13e4c599 +2019-11-25 94203c9ee49910a9a3de92aa40d14dc0d918e44c diff --git a/repos/os/recipes/pkg/test-fault_detection/hash b/repos/os/recipes/pkg/test-fault_detection/hash index b104ddaf9..c79d4e401 100644 --- a/repos/os/recipes/pkg/test-fault_detection/hash +++ b/repos/os/recipes/pkg/test-fault_detection/hash @@ -1 +1 @@ -2019-09-19 de6d30874ff6fbdf53e1c0d2698a0a4477941d13 +2019-11-25 448a5074a0e3dfa148a2dee728ec459e5f17eb47 diff --git a/repos/os/recipes/pkg/test-fs_log/hash b/repos/os/recipes/pkg/test-fs_log/hash index 7eb747282..9b77bd61f 100644 --- a/repos/os/recipes/pkg/test-fs_log/hash +++ b/repos/os/recipes/pkg/test-fs_log/hash @@ -1 +1 @@ -2019-09-19 c39a78eb70cf6cf89c4abddda0f4db3dd252cb11 +2019-11-25 69cc7065b60533850a70736643fe6581ae6092fa diff --git a/repos/os/recipes/pkg/test-fs_packet/archives b/repos/os/recipes/pkg/test-fs_packet/archives index 9bbbb67a7..48781a774 100644 --- a/repos/os/recipes/pkg/test-fs_packet/archives +++ b/repos/os/recipes/pkg/test-fs_packet/archives @@ -1,5 +1,4 @@ _/src/init -_/src/vfs_jitterentropy _/src/vfs _/src/sequence _/src/test-fs_packet diff --git a/repos/os/recipes/pkg/test-fs_packet/hash b/repos/os/recipes/pkg/test-fs_packet/hash index e951e09d1..a5baa6c40 100644 --- a/repos/os/recipes/pkg/test-fs_packet/hash +++ b/repos/os/recipes/pkg/test-fs_packet/hash @@ -1 +1 @@ -2019-09-19 086c5226cc89f60f65ecd1be72101c05b5720af4 +2019-11-25 3d2171644f14fa49dac16da7b5a84132361d084f diff --git a/repos/os/recipes/pkg/test-fs_packet/runtime b/repos/os/recipes/pkg/test-fs_packet/runtime index d7733e6fa..f1a74dec1 100644 --- a/repos/os/recipes/pkg/test-fs_packet/runtime +++ b/repos/os/recipes/pkg/test-fs_packet/runtime @@ -3,7 +3,7 @@ <requires> <timer/> </requires> <events> - <timeout meaning="failed" sec="230" /> + <timeout meaning="failed" sec="30" /> <log meaning="succeeded">child "short-test" exited with exit value 0</log> </events> @@ -13,7 +13,6 @@ <rom label="sequence"/> <rom label="vfs"/> <rom label="vfs.lib.so"/> - <rom label="vfs_jitterentropy.lib.so"/> </content> <config> @@ -35,7 +34,7 @@ <resource name="RAM" quantum="4M"/> <provides> <service name="File_system"/> </provides> <config> - <vfs> <jitterentropy name="test"/> </vfs> + <vfs> <zero name="test"/> </vfs> <default-policy root="/" writeable="yes"/> </config> </start> diff --git a/repos/os/recipes/pkg/test-fs_report/hash b/repos/os/recipes/pkg/test-fs_report/hash index c53c8f516..d9f0c85c3 100644 --- a/repos/os/recipes/pkg/test-fs_report/hash +++ b/repos/os/recipes/pkg/test-fs_report/hash @@ -1 +1 @@ -2019-09-19 b479eada7a6f6b89d189da7644ea7ba9173acb35 +2019-11-25 3573d32739304b93cd68a113ed1d92dcc05cf7a5 diff --git a/repos/os/recipes/pkg/test-fs_rom_update/hash b/repos/os/recipes/pkg/test-fs_rom_update/hash index 000f1ffc0..c43ab1965 100644 --- a/repos/os/recipes/pkg/test-fs_rom_update/hash +++ b/repos/os/recipes/pkg/test-fs_rom_update/hash @@ -1 +1 @@ -2019-09-19 c9cf9a5623abf72faf27eea272862eff76ced5d7 +2019-11-25 b4aedcd55ffaf5e7696a5cef47ac729bfabf510f diff --git a/repos/os/recipes/pkg/test-fs_rom_update_fs/hash b/repos/os/recipes/pkg/test-fs_rom_update_fs/hash index 21f3e8ca4..2ceb5ae60 100644 --- a/repos/os/recipes/pkg/test-fs_rom_update_fs/hash +++ b/repos/os/recipes/pkg/test-fs_rom_update_fs/hash @@ -1 +1 @@ -2019-09-19 db04d969a28ba06a70346e2e7e4b1d03ed27ee3a +2019-11-25 cf30b0946c4ed66ae158b845fdaa57597127ac11 diff --git a/repos/os/recipes/pkg/test-fs_rom_update_ram/hash b/repos/os/recipes/pkg/test-fs_rom_update_ram/hash index 75077c184..ba8c04bb0 100644 --- a/repos/os/recipes/pkg/test-fs_rom_update_ram/hash +++ b/repos/os/recipes/pkg/test-fs_rom_update_ram/hash @@ -1 +1 @@ -2019-09-19 219d129fe7ddd2862c41163755102ce5386972eb +2019-11-25 ce39363a022d0b405a19b3700dface3507ef5273 diff --git a/repos/os/recipes/pkg/test-init/hash b/repos/os/recipes/pkg/test-init/hash index ef1e69e02..8ddb601c8 100644 --- a/repos/os/recipes/pkg/test-init/hash +++ b/repos/os/recipes/pkg/test-init/hash @@ -1 +1 @@ -2019-09-19 22c18aee4d3999d4d03d3911fb1db98f1bd31d0b +2019-11-25 455299dffe7a586f8ece48d4357a5ab7e681d594 diff --git a/repos/os/recipes/pkg/test-init_loop/hash b/repos/os/recipes/pkg/test-init_loop/hash index cb6c61251..86789cc69 100644 --- a/repos/os/recipes/pkg/test-init_loop/hash +++ b/repos/os/recipes/pkg/test-init_loop/hash @@ -1 +1 @@ -2019-09-19 01abe5b176c3cc947c14026ae3d46673419465ec +2019-11-25 56b4a5ad0caa1d11612caed3a459dce5a71990ed diff --git a/repos/os/recipes/pkg/test-lx_block/hash b/repos/os/recipes/pkg/test-lx_block/hash index 1cb035cd1..b7b2007dd 100644 --- a/repos/os/recipes/pkg/test-lx_block/hash +++ b/repos/os/recipes/pkg/test-lx_block/hash @@ -1 +1 @@ -2019-09-19 6822ae5a8cff570f48b6ed0b2b6cc509b982508d +2019-11-25 e37c0adde0586ff2ce47fb37c09c619aee033a8c diff --git a/repos/os/recipes/pkg/test-nic_loopback/hash b/repos/os/recipes/pkg/test-nic_loopback/hash index 6c533ad98..fdb138981 100644 --- a/repos/os/recipes/pkg/test-nic_loopback/hash +++ b/repos/os/recipes/pkg/test-nic_loopback/hash @@ -1 +1 @@ -2019-09-19 d5a0b75212ae102943204a477f66ded7bdd3aa54 +2019-11-25 fa37d7bb922b74332b54fbdcbf46eea0215c136c diff --git a/repos/os/recipes/pkg/test-part_block_gpt/hash b/repos/os/recipes/pkg/test-part_block_gpt/hash index 505bcf9f7..a2fd1a241 100644 --- a/repos/os/recipes/pkg/test-part_block_gpt/hash +++ b/repos/os/recipes/pkg/test-part_block_gpt/hash @@ -1 +1 @@ -2019-09-19 58c7a8a090ea162e4e53d6dab310b39563dc7548 +2019-11-25 e8004b37b45ba7b77cafc262ea8812d75814c5d9 diff --git a/repos/os/recipes/pkg/test-part_block_mbr/hash b/repos/os/recipes/pkg/test-part_block_mbr/hash index 9d84b8b5a..d183a11db 100644 --- a/repos/os/recipes/pkg/test-part_block_mbr/hash +++ b/repos/os/recipes/pkg/test-part_block_mbr/hash @@ -1 +1 @@ -2019-09-19 8faa17243028cda1583fd5110dc65d83b29a8f33 +2019-11-25 5381fab1a764a5c5295547d3bae1a999063ef507 diff --git a/repos/os/recipes/pkg/test-ram_fs_chunk/hash b/repos/os/recipes/pkg/test-ram_fs_chunk/hash index 4e16f2d07..ee1db9d67 100644 --- a/repos/os/recipes/pkg/test-ram_fs_chunk/hash +++ b/repos/os/recipes/pkg/test-ram_fs_chunk/hash @@ -1 +1 @@ -2019-09-19 9b252ec7acc8bfa709209741d1d880974dbb9d71 +2019-11-25 666898073e626a66e20b9c71d1a84025a3c0ed81 diff --git a/repos/os/recipes/pkg/test-read_only_rom/hash b/repos/os/recipes/pkg/test-read_only_rom/hash index ddf1ac35c..cd50f3d69 100644 --- a/repos/os/recipes/pkg/test-read_only_rom/hash +++ b/repos/os/recipes/pkg/test-read_only_rom/hash @@ -1 +1 @@ -2019-09-19 01bce20d2ba70ff01c81e729055468f009aa1ff3 +2019-11-25 d526cdf58d2309097368c9d1b32b14bd928d960a diff --git a/repos/os/recipes/pkg/test-report_rom/hash b/repos/os/recipes/pkg/test-report_rom/hash index dc39f3a0a..5611c848d 100644 --- a/repos/os/recipes/pkg/test-report_rom/hash +++ b/repos/os/recipes/pkg/test-report_rom/hash @@ -1 +1 @@ -2019-09-19 a3aa9db9c2b686c565d0ba8e034eb26a733b370c +2019-11-25 a61a1825c0133fc5b78cbe2ffe5dc924d50b2e47 diff --git a/repos/os/recipes/pkg/test-resource_request/hash b/repos/os/recipes/pkg/test-resource_request/hash index 3fd4aca00..921dbefda 100644 --- a/repos/os/recipes/pkg/test-resource_request/hash +++ b/repos/os/recipes/pkg/test-resource_request/hash @@ -1 +1 @@ -2019-09-19 9944fc17b92f1216185ddbc365ffc3fc86d448f5 +2019-11-25 9e9c7853607c4f08de48ef89b5c4fc203db2b7d8 diff --git a/repos/os/recipes/pkg/test-resource_yield/hash b/repos/os/recipes/pkg/test-resource_yield/hash index e74ff8809..8aab5efc0 100644 --- a/repos/os/recipes/pkg/test-resource_yield/hash +++ b/repos/os/recipes/pkg/test-resource_yield/hash @@ -1 +1 @@ -2019-09-19 5dca6ca60fa884d8b4431cab41f658f96d94c522 +2019-11-25 e4bfda222e856eecefc81c279eda736345833e52 diff --git a/repos/os/recipes/pkg/test-rom_block/hash b/repos/os/recipes/pkg/test-rom_block/hash index c67cff4a7..0d46b9cf4 100644 --- a/repos/os/recipes/pkg/test-rom_block/hash +++ b/repos/os/recipes/pkg/test-rom_block/hash @@ -1 +1 @@ -2019-09-19 f881d6273c2ae9eae4fb8111b15c04bec3614bd3 +2019-11-25 fc60de5ce9ef212f84e30a4594dac0d7fcb40293 diff --git a/repos/os/recipes/pkg/test-rom_filter/hash b/repos/os/recipes/pkg/test-rom_filter/hash index 1e2af8653..90c4a0b2a 100644 --- a/repos/os/recipes/pkg/test-rom_filter/hash +++ b/repos/os/recipes/pkg/test-rom_filter/hash @@ -1 +1 @@ -2019-09-19 9678337e026b42b6bc3abb02c4857b542620a4b3 +2019-11-25 0b8ee6a9e6d6316016e09d0dcb733096027f8b34 diff --git a/repos/os/recipes/pkg/test-rtc/hash b/repos/os/recipes/pkg/test-rtc/hash index b7978ed53..ec2f008fe 100644 --- a/repos/os/recipes/pkg/test-rtc/hash +++ b/repos/os/recipes/pkg/test-rtc/hash @@ -1 +1 @@ -2019-09-19 41f6b8cf94bcceeb1101b1ac69a3e5690de27545 +2019-11-25 f4c75e16682deac37d2f1c720bf99bd51b6964c9 diff --git a/repos/os/recipes/pkg/test-signal/hash b/repos/os/recipes/pkg/test-signal/hash index e4121ce00..c2967f464 100644 --- a/repos/os/recipes/pkg/test-signal/hash +++ b/repos/os/recipes/pkg/test-signal/hash @@ -1 +1 @@ -2019-09-19 c2f7e78525655e8b70ed0803419adb9e0d61e0c6 +2019-11-25 de6986a555dc9a2dfbc02274da4899beb4d185da diff --git a/repos/os/recipes/pkg/test-slab/hash b/repos/os/recipes/pkg/test-slab/hash index 26ce9c404..a0c789861 100644 --- a/repos/os/recipes/pkg/test-slab/hash +++ b/repos/os/recipes/pkg/test-slab/hash @@ -1 +1 @@ -2019-09-19 f22fbe8efe8c1b81114eb9633d13c0db5843cce6 +2019-11-25 fc8db895a644f21c3bbd6eeda9f6985970ed42a1 diff --git a/repos/os/recipes/pkg/test-terminal_crosslink/hash b/repos/os/recipes/pkg/test-terminal_crosslink/hash index ee572f7de..421e99a8a 100644 --- a/repos/os/recipes/pkg/test-terminal_crosslink/hash +++ b/repos/os/recipes/pkg/test-terminal_crosslink/hash @@ -1 +1 @@ -2019-09-19 8c9ba20921f91fe2cd59d6a24e48a9291dca7d04 +2019-11-25 33bc7b5d10a3dafb64bc962c492a2849017cd37a diff --git a/repos/os/recipes/pkg/test-trace/hash b/repos/os/recipes/pkg/test-trace/hash index 841187cf9..a147ca7ad 100644 --- a/repos/os/recipes/pkg/test-trace/hash +++ b/repos/os/recipes/pkg/test-trace/hash @@ -1 +1 @@ -2019-09-19 cdac0d706483853a9be55b1af0bbae70c8832153 +2019-11-25 2eca21072e21cba6192f9cf94fede8d3f7968f22 diff --git a/repos/os/recipes/pkg/test-trace_logger/hash b/repos/os/recipes/pkg/test-trace_logger/hash index 0d1203f39..133c23e79 100644 --- a/repos/os/recipes/pkg/test-trace_logger/hash +++ b/repos/os/recipes/pkg/test-trace_logger/hash @@ -1 +1 @@ -2019-09-19 77f04b141243b727b13faf1a7cd641f5ea95dbd3 +2019-11-25 bb33f4283853e4a7de86fe115f731fb282693c8a diff --git a/repos/os/recipes/pkg/test-utf8/hash b/repos/os/recipes/pkg/test-utf8/hash index 42df3624f..74ac0129b 100644 --- a/repos/os/recipes/pkg/test-utf8/hash +++ b/repos/os/recipes/pkg/test-utf8/hash @@ -1 +1 @@ -2019-09-19 322d0b3823edd0a5289b06253e22cec44388e53d +2019-11-25 6ed58cf260ce10a15ed51e9245476ac50b47087f diff --git a/repos/os/recipes/pkg/test-vfs_stress_fs/hash b/repos/os/recipes/pkg/test-vfs_stress_fs/hash index 1cf59db0c..87fc329e9 100644 --- a/repos/os/recipes/pkg/test-vfs_stress_fs/hash +++ b/repos/os/recipes/pkg/test-vfs_stress_fs/hash @@ -1 +1 @@ -2019-09-19 9dfcb2e98807752cbc0e2cf61bf9d7fed236b830 +2019-11-25 5392ab96a068a60d5afb139ac578a4301b42b7bd diff --git a/repos/os/recipes/pkg/test-vfs_stress_ram/hash b/repos/os/recipes/pkg/test-vfs_stress_ram/hash index 0d9a03cf9..dea21f868 100644 --- a/repos/os/recipes/pkg/test-vfs_stress_ram/hash +++ b/repos/os/recipes/pkg/test-vfs_stress_ram/hash @@ -1 +1 @@ -2019-09-19 926b9426df554490d64929ac8b8a5460dbf8eda0 +2019-11-25 303aeb52e4e8e3839d2ceeac7e4d6ab5bfd79b36 diff --git a/repos/os/recipes/pkg/test-weak_ptr/hash b/repos/os/recipes/pkg/test-weak_ptr/hash index 1f38363da..24535fcbc 100644 --- a/repos/os/recipes/pkg/test-weak_ptr/hash +++ b/repos/os/recipes/pkg/test-weak_ptr/hash @@ -1 +1 @@ -2019-09-19 fe05e758ec9367d9531ec9a7eb16f4df538697cd +2019-11-25 98cafc219cfdf112670ab7f34f4b073697943196 diff --git a/repos/os/recipes/raw/drivers_interactive-linux/drivers.config b/repos/os/recipes/raw/drivers_interactive-linux/drivers.config index 36676a10f..4e145a690 100644 --- a/repos/os/recipes/raw/drivers_interactive-linux/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-linux/drivers.config @@ -23,7 +23,7 @@ </start> <start name="input_filter" caps="80"> - <resource name="RAM" quantum="1M"/> + <resource name="RAM" quantum="1280K"/> <provides> <service name="Input"/> </provides> <route> <service name="ROM" label="config"> <parent label="input_filter.config"/> </service> diff --git a/repos/os/recipes/raw/drivers_interactive-linux/hash b/repos/os/recipes/raw/drivers_interactive-linux/hash index d2074b369..f1b40038f 100644 --- a/repos/os/recipes/raw/drivers_interactive-linux/hash +++ b/repos/os/recipes/raw/drivers_interactive-linux/hash @@ -1 +1 @@ -2019-08-27 f014499036b0d75e53349ca5f0a20472fb7207b3 +2019-11-18 39f9618f3a3b3341d4a19d3ccad7837f3eedaa5b diff --git a/repos/os/recipes/raw/drivers_interactive-muen/drivers.config b/repos/os/recipes/raw/drivers_interactive-muen/drivers.config index 8cc334f8b..e8deef8bc 100644 --- a/repos/os/recipes/raw/drivers_interactive-muen/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-muen/drivers.config @@ -88,7 +88,7 @@ </start> <start name="input_filter" caps="80"> - <resource name="RAM" quantum="1M"/> + <resource name="RAM" quantum="1280K"/> <provides> <service name="Input"/> </provides> <route> <service name="ROM" label="config"> <parent label="input_filter.config"/> </service> diff --git a/repos/os/recipes/raw/drivers_interactive-muen/hash b/repos/os/recipes/raw/drivers_interactive-muen/hash index 5144febf0..56863390e 100644 --- a/repos/os/recipes/raw/drivers_interactive-muen/hash +++ b/repos/os/recipes/raw/drivers_interactive-muen/hash @@ -1 +1 @@ -2019-08-27 ba4d2be150b6bb2b303914c4c13b7e45400f8856 +2019-11-18 74ba31f4c24174dffeaa04528ddc570af6032a47 diff --git a/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config b/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config index 00d124a41..a8b1683ca 100644 --- a/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config +++ b/repos/os/recipes/raw/drivers_interactive-pbxa9/drivers.config @@ -33,7 +33,7 @@ </start> <start name="input_filter" caps="80"> - <resource name="RAM" quantum="1M"/> + <resource name="RAM" quantum="1280K"/> <provides> <service name="Input"/> </provides> <route> <service name="ROM" label="config"> <parent label="input_filter.config"/> </service> diff --git a/repos/os/recipes/raw/drivers_interactive-pbxa9/hash b/repos/os/recipes/raw/drivers_interactive-pbxa9/hash index 238f5fd11..1c902e2d3 100644 --- a/repos/os/recipes/raw/drivers_interactive-pbxa9/hash +++ b/repos/os/recipes/raw/drivers_interactive-pbxa9/hash @@ -1 +1 @@ -2019-08-27 5af3e82e8d1647ba9074eab706aedddfa7042a3c +2019-11-18 2f59c08834d0e5bb944e13f288b527dd23b4760b diff --git a/repos/os/recipes/raw/drivers_interactive-pc/hash b/repos/os/recipes/raw/drivers_interactive-pc/hash index 124d1d4b0..afd6dbe2c 100644 --- a/repos/os/recipes/raw/drivers_interactive-pc/hash +++ b/repos/os/recipes/raw/drivers_interactive-pc/hash @@ -1 +1 @@ -2019-08-27 7c41f8861acb8edc00393916293d99b1274e8d04 +2019-11-18 4f76a1d7214b5aec743bc8e91e8e652de6850bf7 diff --git a/repos/os/recipes/src/acpi_drv/content.mk b/repos/os/recipes/src/acpi_drv/content.mk index ef2d6490a..f162d436d 100644 --- a/repos/os/recipes/src/acpi_drv/content.mk +++ b/repos/os/recipes/src/acpi_drv/content.mk @@ -1,2 +1,6 @@ SRC_DIR = src/drivers/acpi include $(GENODE_DIR)/repos/base/recipes/src/content.inc + +content: $(GENODE_DIR)/repos/os/include/smbios + mkdir -p include + cp -r $< include/smbios diff --git a/repos/os/recipes/src/acpi_drv/hash b/repos/os/recipes/src/acpi_drv/hash index 5934b27c6..ae2e40ea8 100644 --- a/repos/os/recipes/src/acpi_drv/hash +++ b/repos/os/recipes/src/acpi_drv/hash @@ -1 +1 @@ -2019-09-19 8032fdd194a39905cda5e9a717cff5f7e1c6b56c +2019-11-25 c3f713cc4c0c1dd1ca531c1bf79a61787f7016e8 diff --git a/repos/os/recipes/src/ahci_drv/hash b/repos/os/recipes/src/ahci_drv/hash index fcb36edb7..c687e804f 100644 --- a/repos/os/recipes/src/ahci_drv/hash +++ b/repos/os/recipes/src/ahci_drv/hash @@ -1 +1 @@ -2019-09-19 9a27eb133891a4ab3e29900da8ecad8b662873c5 +2019-11-25 a1850b663925934441f5f049f4a08596684a06cc diff --git a/repos/os/recipes/src/block_cache/hash b/repos/os/recipes/src/block_cache/hash index 320304c18..17c23f257 100644 --- a/repos/os/recipes/src/block_cache/hash +++ b/repos/os/recipes/src/block_cache/hash @@ -1 +1 @@ -2019-09-19 736aaed281716b6d9c15d7e7bcfc90ba756c8bc7 +2019-11-25 f2c74d1f0ce51b8d8910fa4102cb8288667846f1 diff --git a/repos/os/recipes/src/boot_fb_drv/hash b/repos/os/recipes/src/boot_fb_drv/hash index e19aaa8cb..5cbea207b 100644 --- a/repos/os/recipes/src/boot_fb_drv/hash +++ b/repos/os/recipes/src/boot_fb_drv/hash @@ -1 +1 @@ -2019-09-19 0e05b34ed78d57063fe827b8bac993e938ce2e55 +2019-11-25 70eae007e53385fc2fcc3f5f79714bb16f234b46 diff --git a/repos/os/recipes/src/cached_fs_rom/hash b/repos/os/recipes/src/cached_fs_rom/hash index c4834dcaf..76473a366 100644 --- a/repos/os/recipes/src/cached_fs_rom/hash +++ b/repos/os/recipes/src/cached_fs_rom/hash @@ -1 +1 @@ -2019-09-19 46fec8532fba18f731fbbe6d51647070f76eeb62 +2019-11-25 9bd4065f705bf707f68702eeb11ef1f39e5481fb diff --git a/repos/os/recipes/src/chroot/hash b/repos/os/recipes/src/chroot/hash index 02954eb42..cb5b1e561 100644 --- a/repos/os/recipes/src/chroot/hash +++ b/repos/os/recipes/src/chroot/hash @@ -1 +1 @@ -2019-09-19 5b2f13d48e990a45034e3bf2955696fc662beaba +2019-11-25 78f0772a843409d6f6d954eabe5980bc000ef666 diff --git a/repos/os/recipes/src/clipboard/hash b/repos/os/recipes/src/clipboard/hash index 63c3da96f..5834d623c 100644 --- a/repos/os/recipes/src/clipboard/hash +++ b/repos/os/recipes/src/clipboard/hash @@ -1 +1 @@ -2019-09-19 a2cc2c7e4f0fa883b4d24a2ccbdcb5dcf6c39ce5 +2019-11-25 043961eb49ef43279270dc2904fb7222f0ef3b75 diff --git a/repos/os/recipes/src/cpu_burner/hash b/repos/os/recipes/src/cpu_burner/hash index 561fc1e46..0ec0d9caf 100644 --- a/repos/os/recipes/src/cpu_burner/hash +++ b/repos/os/recipes/src/cpu_burner/hash @@ -1 +1 @@ -2019-09-19 0a0eb86b08081a5e2f9186f4d0be7f58144fb1c8 +2019-11-25 73c3a09cf1e4e91ad4953173e25bac9fca11daf5 diff --git a/repos/os/recipes/src/dummy/hash b/repos/os/recipes/src/dummy/hash index a29fcc029..221af494d 100644 --- a/repos/os/recipes/src/dummy/hash +++ b/repos/os/recipes/src/dummy/hash @@ -1 +1 @@ -2019-09-19 2f23e36661298d442e542415d9a8b0ff9da1502c +2019-11-25 ef205ebb62a8ab46afee38478a4339a3cfa4af5d diff --git a/repos/os/recipes/src/dynamic_rom/hash b/repos/os/recipes/src/dynamic_rom/hash index fd3a8b1fd..24065aa6f 100644 --- a/repos/os/recipes/src/dynamic_rom/hash +++ b/repos/os/recipes/src/dynamic_rom/hash @@ -1 +1 @@ -2019-09-19 2486e0b96e13632989a58a39f057e5449e78d405 +2019-11-25 6c1807d554584b76ed8385c6a0d480ba184fc3d3 diff --git a/repos/os/recipes/src/fb_sdl/hash b/repos/os/recipes/src/fb_sdl/hash index 30e19785f..a15d8b238 100644 --- a/repos/os/recipes/src/fb_sdl/hash +++ b/repos/os/recipes/src/fb_sdl/hash @@ -1 +1 @@ -2019-09-19 5cf24b12dd4a1794a2943e430a3186ca0d640f44 +2019-11-25 d49adb8e2a1f7054e23fcbe13ff5181a74987bef diff --git a/repos/os/recipes/src/fs_log/hash b/repos/os/recipes/src/fs_log/hash index a39640408..83eda1271 100644 --- a/repos/os/recipes/src/fs_log/hash +++ b/repos/os/recipes/src/fs_log/hash @@ -1 +1 @@ -2019-09-19 33e75e6e588f3c7e6838f3519960ec982e4719b3 +2019-11-25 63b2278609801feae5f9736cf55139e5cdc9a7a4 diff --git a/repos/os/recipes/src/fs_report/hash b/repos/os/recipes/src/fs_report/hash index f8cc3bb1f..4ee362264 100644 --- a/repos/os/recipes/src/fs_report/hash +++ b/repos/os/recipes/src/fs_report/hash @@ -1 +1 @@ -2019-09-19 93ea49f648ddd4950ae2fe35976c60bcfbfb60ed +2019-11-25 5b07c0c132b708584f0e6da1ae2f954cae2fc91c diff --git a/repos/os/recipes/src/fs_rom/hash b/repos/os/recipes/src/fs_rom/hash index b34135ffa..09293d587 100644 --- a/repos/os/recipes/src/fs_rom/hash +++ b/repos/os/recipes/src/fs_rom/hash @@ -1 +1 @@ -2019-09-19 b661f38cb874ae69b0838467feb463fc97971f9f +2019-11-25 4a6ab41eb84d49a8a83c5ea61c8eb47059c10584 diff --git a/repos/os/recipes/src/global_keys_handler/hash b/repos/os/recipes/src/global_keys_handler/hash index f86e92e79..176714988 100644 --- a/repos/os/recipes/src/global_keys_handler/hash +++ b/repos/os/recipes/src/global_keys_handler/hash @@ -1 +1 @@ -2019-09-19 3f59e37106c4115236415f0313eede38a743451c +2019-11-25 97020ec19204e3f2fe9dfec49a23684080426ffe diff --git a/repos/os/recipes/src/imx53_qsb_drivers/hash b/repos/os/recipes/src/imx53_qsb_drivers/hash index c4c29182f..a397995b4 100644 --- a/repos/os/recipes/src/imx53_qsb_drivers/hash +++ b/repos/os/recipes/src/imx53_qsb_drivers/hash @@ -1 +1 @@ -2019-09-19 a85427f78dacbfc5ac5461244928e42342185299 +2019-11-25 8dfddfc2b557e866aa6db7990dae61cd543968c7 diff --git a/repos/os/recipes/src/init/hash b/repos/os/recipes/src/init/hash index 587edff3a..0ebcf55c0 100644 --- a/repos/os/recipes/src/init/hash +++ b/repos/os/recipes/src/init/hash @@ -1 +1 @@ -2019-09-19 0c0dee408b2e9365aa0fc42d81401ef4079adce7 +2019-11-25 3856a62bc01a09db1606c0de1a4bb6f1fae4fe8f diff --git a/repos/os/recipes/src/input_filter/hash b/repos/os/recipes/src/input_filter/hash index 036cc8b15..bdf79e65e 100644 --- a/repos/os/recipes/src/input_filter/hash +++ b/repos/os/recipes/src/input_filter/hash @@ -1 +1 @@ -2019-09-19 e8f646c386f1e2f809970ec48fae211fea15345c +2019-11-25 e694bbfa50e27ae40c92e51c072d10d03111c5df diff --git a/repos/os/recipes/src/lan9118_nic_drv/hash b/repos/os/recipes/src/lan9118_nic_drv/hash index ad5e17b96..c1d89683c 100644 --- a/repos/os/recipes/src/lan9118_nic_drv/hash +++ b/repos/os/recipes/src/lan9118_nic_drv/hash @@ -1 +1 @@ -2019-09-19 7159fc0ef51074d433faa7d55e13755986287f91 +2019-11-25 26f4108c3159f75ee9468ee9b335a939c30b63ce diff --git a/repos/os/recipes/src/linux_nic_drv/hash b/repos/os/recipes/src/linux_nic_drv/hash index b0cd5cac4..2923a320b 100644 --- a/repos/os/recipes/src/linux_nic_drv/hash +++ b/repos/os/recipes/src/linux_nic_drv/hash @@ -1 +1 @@ -2019-09-19 cc9cf0a6b081519e0fe4fe10b77d724044cb0e87 +2019-11-25 b65b5dbf197e0388b4ea521ff4ac9e0231d2131f diff --git a/repos/os/recipes/src/loader/hash b/repos/os/recipes/src/loader/hash index 477471297..0c129b148 100644 --- a/repos/os/recipes/src/loader/hash +++ b/repos/os/recipes/src/loader/hash @@ -1 +1 @@ -2019-09-19 dcff0268544e00799951ac834a286f30b99a8739 +2019-11-25 ad5bc0533ea81383eaa21d03ddd96ca23c18535a diff --git a/repos/os/recipes/src/log_core/hash b/repos/os/recipes/src/log_core/hash index c937cfccb..e703c6a7b 100644 --- a/repos/os/recipes/src/log_core/hash +++ b/repos/os/recipes/src/log_core/hash @@ -1 +1 @@ -2019-09-19 ae5e7b93fbf231269082dd5ffb8d9534138dd2d5 +2019-11-25 9406794c92e4acba0d62baa1154c1715ca73d7d7 diff --git a/repos/os/recipes/src/log_terminal/hash b/repos/os/recipes/src/log_terminal/hash index 43b34bdcd..75e77b3e8 100644 --- a/repos/os/recipes/src/log_terminal/hash +++ b/repos/os/recipes/src/log_terminal/hash @@ -1 +1 @@ -2019-09-19 982bf026450bd2dedb9c2975c896d3dccdd0d2a8 +2019-11-25 48f674181cd6c788ba43c225caad85e7ba9987ac diff --git a/repos/os/recipes/src/lx_block/hash b/repos/os/recipes/src/lx_block/hash index b05b49260..b9d01de12 100644 --- a/repos/os/recipes/src/lx_block/hash +++ b/repos/os/recipes/src/lx_block/hash @@ -1 +1 @@ -2019-09-19 a87378c4c81a7f672641e3217ca61150de14d591 +2019-11-25 e3750033b21d5d92895c6511162a114fde5fb2ca diff --git a/repos/os/recipes/src/mixer/hash b/repos/os/recipes/src/mixer/hash index 26e5f28e8..66cc62709 100644 --- a/repos/os/recipes/src/mixer/hash +++ b/repos/os/recipes/src/mixer/hash @@ -1 +1 @@ -2019-09-19 f58dca3d60da3a781cb38db06ba4e437e840ee3e +2019-11-25 19f5646ae802cd2b8cc7284284799907bd226c35 diff --git a/repos/os/recipes/src/nic_bridge/hash b/repos/os/recipes/src/nic_bridge/hash index e43855a44..0304df840 100644 --- a/repos/os/recipes/src/nic_bridge/hash +++ b/repos/os/recipes/src/nic_bridge/hash @@ -1 +1 @@ -2019-09-19 5395b05f6ca43eb3c9ac2f9625cdae8d8691f22f +2019-11-25 6489e4d7b65639b53ff384eb6a6f1474e14dccf3 diff --git a/repos/os/recipes/src/nic_loopback/hash b/repos/os/recipes/src/nic_loopback/hash index 508f18451..6fda7e7c2 100644 --- a/repos/os/recipes/src/nic_loopback/hash +++ b/repos/os/recipes/src/nic_loopback/hash @@ -1 +1 @@ -2019-09-19 94c08fd713cac69eb30520bbb5bb22041a2991bd +2019-11-25 58337a3d9465d98399024e2e1d62c57029347b69 diff --git a/repos/os/recipes/src/nic_router/hash b/repos/os/recipes/src/nic_router/hash index 3bfcb3198..eaa03e2c4 100644 --- a/repos/os/recipes/src/nic_router/hash +++ b/repos/os/recipes/src/nic_router/hash @@ -1 +1 @@ -2019-09-19 60b70a2d5475ef7a493eb2043092b64bb6b713cf +2019-11-25 9f56c593740e295f034dcc815f55c11b1b5e06e2 diff --git a/repos/os/recipes/src/nit_fb/hash b/repos/os/recipes/src/nit_fb/hash index b44d96088..f20b71108 100644 --- a/repos/os/recipes/src/nit_fb/hash +++ b/repos/os/recipes/src/nit_fb/hash @@ -1 +1 @@ -2019-09-19 e1fe7048764f9ce6321e466fc5866120269dc458 +2019-11-25 0eacc83d0f81885f6d1a42ae874c310fc2bf287b diff --git a/repos/os/recipes/src/nit_focus/hash b/repos/os/recipes/src/nit_focus/hash index 7a09e1537..25438da90 100644 --- a/repos/os/recipes/src/nit_focus/hash +++ b/repos/os/recipes/src/nit_focus/hash @@ -1 +1 @@ -2019-09-19 f4c6ff6465d01f8b66114d30750b6329aa22e98b +2019-11-25 ad31ad0769bb91d5dd69a49acd6bb613f15d9206 diff --git a/repos/os/recipes/src/nitpicker/hash b/repos/os/recipes/src/nitpicker/hash index a7cad8caa..90e538536 100644 --- a/repos/os/recipes/src/nitpicker/hash +++ b/repos/os/recipes/src/nitpicker/hash @@ -1 +1 @@ -2019-09-19 284078b7ac78a761e642009c4d95340eadbfbb97 +2019-11-25 50e964c2b57c8bc2649e4903b7dc6f851951ddb9 diff --git a/repos/os/recipes/src/nvme_drv/hash b/repos/os/recipes/src/nvme_drv/hash index 07e510d8e..bc120eb74 100644 --- a/repos/os/recipes/src/nvme_drv/hash +++ b/repos/os/recipes/src/nvme_drv/hash @@ -1 +1 @@ -2019-09-19 05f6b54e79005e43998021a184291be289fcffe2 +2019-11-25 9b4b5c3fc30f7be6e75130f782ae272395ea7ede diff --git a/repos/os/recipes/src/part_block/hash b/repos/os/recipes/src/part_block/hash index 23d5c66ea..0cb7b25e0 100644 --- a/repos/os/recipes/src/part_block/hash +++ b/repos/os/recipes/src/part_block/hash @@ -1 +1 @@ -2019-09-19 8ce1c9b69e2a461b09947147812257d5f7c4471c +2019-11-25 345e9954b892cf911e8acad07928b322afb5dbd1 diff --git a/repos/os/recipes/src/pbxa9_drivers/hash b/repos/os/recipes/src/pbxa9_drivers/hash index d2146a5ba..05ed45c83 100644 --- a/repos/os/recipes/src/pbxa9_drivers/hash +++ b/repos/os/recipes/src/pbxa9_drivers/hash @@ -1 +1 @@ -2019-09-19 e3cdbdb9cfccada77912d2dab5f469c27463696d +2019-11-25 75eca0464d3486c4eb9eb281c2df6a61b3f7591a diff --git a/repos/os/recipes/src/platform_drv/hash b/repos/os/recipes/src/platform_drv/hash index 56106b7fe..ba86b192d 100644 --- a/repos/os/recipes/src/platform_drv/hash +++ b/repos/os/recipes/src/platform_drv/hash @@ -1 +1 @@ -2019-09-19 b2eebb824b70fe10ee7e467a4910b99749148139 +2019-11-25 e7260f0cbe15635121ee5175c5af2722d7f3a21e diff --git a/repos/os/recipes/src/ps2_drv/hash b/repos/os/recipes/src/ps2_drv/hash index 777ee6a31..a16a5bd15 100644 --- a/repos/os/recipes/src/ps2_drv/hash +++ b/repos/os/recipes/src/ps2_drv/hash @@ -1 +1 @@ -2019-09-19 865392d71fab4fbfbc74eb59188ce596c322c7de +2019-11-25 5670365c0943569e1a342ca04fb3874361801e60 diff --git a/repos/os/recipes/src/ram_block/hash b/repos/os/recipes/src/ram_block/hash index d2c84b731..eba0fce51 100644 --- a/repos/os/recipes/src/ram_block/hash +++ b/repos/os/recipes/src/ram_block/hash @@ -1 +1 @@ -2019-09-19 6dc1b0d0e59e584d7671bff429588dd9ff34f93e +2019-11-25 5c062c08bad03ec7a034950f7015d90a9e032b98 diff --git a/repos/os/recipes/src/ram_fs/hash b/repos/os/recipes/src/ram_fs/hash index c2772992b..ea99af29f 100644 --- a/repos/os/recipes/src/ram_fs/hash +++ b/repos/os/recipes/src/ram_fs/hash @@ -1 +1 @@ -2019-09-19 a0bbaa79178f0c6194724a9aa60a738b57bad27d +2019-11-25 47e4a73aea4f3958fea1f9ca4c1fa893e69f0fcf diff --git a/repos/os/recipes/src/report_rom/hash b/repos/os/recipes/src/report_rom/hash index 176284398..a56af8f86 100644 --- a/repos/os/recipes/src/report_rom/hash +++ b/repos/os/recipes/src/report_rom/hash @@ -1 +1 @@ -2019-09-19 a53f3514b146bf9c46f5c7c24465d58394ec3a05 +2019-11-25 9be0505f2b127d0664b2abf5fd76417f85d58546 diff --git a/repos/os/recipes/src/rom_block/hash b/repos/os/recipes/src/rom_block/hash index 6cde50e68..e1ff72089 100644 --- a/repos/os/recipes/src/rom_block/hash +++ b/repos/os/recipes/src/rom_block/hash @@ -1 +1 @@ -2019-09-19 834b172b058d7b41596b69f1989e73525ddad901 +2019-11-25 1d0622034b350a93f02d84a9bd3d61dffb037962 diff --git a/repos/os/recipes/src/rom_filter/hash b/repos/os/recipes/src/rom_filter/hash index b771b8bdc..f74cb0b47 100644 --- a/repos/os/recipes/src/rom_filter/hash +++ b/repos/os/recipes/src/rom_filter/hash @@ -1 +1 @@ -2019-09-19 2d95e4ea777f53050c3050e1955f393579794363 +2019-11-25 4eae72fc4dabf4a9e769f48b2a04d4193da4fbcb diff --git a/repos/os/recipes/src/rom_logger/hash b/repos/os/recipes/src/rom_logger/hash index 6c123cf5f..0e31ca656 100644 --- a/repos/os/recipes/src/rom_logger/hash +++ b/repos/os/recipes/src/rom_logger/hash @@ -1 +1 @@ -2019-09-19 039ce6a5a69ca01476f1076ac0a7d36551fc663b +2019-11-25 ce2f466981f6ca48e3b366b20a81f404b816cbbc diff --git a/repos/os/recipes/src/rom_reporter/hash b/repos/os/recipes/src/rom_reporter/hash index a7679c644..c33d9f582 100644 --- a/repos/os/recipes/src/rom_reporter/hash +++ b/repos/os/recipes/src/rom_reporter/hash @@ -1 +1 @@ -2019-09-19 b733aeebe00051ed98cee593599bd1b714a1f554 +2019-11-25 c01f2b4074dc794e031ff4de30e033836be4e210 diff --git a/repos/os/recipes/src/rom_to_file/hash b/repos/os/recipes/src/rom_to_file/hash index ae0eade38..0ab8ee4e1 100644 --- a/repos/os/recipes/src/rom_to_file/hash +++ b/repos/os/recipes/src/rom_to_file/hash @@ -1 +1 @@ -2019-09-19 600d44532d6fff5bef77c43a843586a376c9d2d9 +2019-11-25 7c9d5ab4a459f2aa274e09961bf023613fbe8eab diff --git a/repos/os/recipes/src/rpi_fb_drv/hash b/repos/os/recipes/src/rpi_fb_drv/hash index de9df5508..c0e622869 100644 --- a/repos/os/recipes/src/rpi_fb_drv/hash +++ b/repos/os/recipes/src/rpi_fb_drv/hash @@ -1 +1 @@ -2019-09-19 71e5f1a2066633fae77a4a54e97252d4c996bba8 +2019-11-25 bef783f5b7b82982277ff519b2e6e0b110663e86 diff --git a/repos/os/recipes/src/rtc_drv/hash b/repos/os/recipes/src/rtc_drv/hash index 770859499..1c63647fb 100644 --- a/repos/os/recipes/src/rtc_drv/hash +++ b/repos/os/recipes/src/rtc_drv/hash @@ -1 +1 @@ -2019-09-19 406482b89b6abb3c85d53b4ae592d1e5827b5f95 +2019-11-25 c502b0613f88f4fefa3b6950500602bb79a62ddd diff --git a/repos/os/recipes/src/sequence/hash b/repos/os/recipes/src/sequence/hash index ace1a0e79..bcb493868 100644 --- a/repos/os/recipes/src/sequence/hash +++ b/repos/os/recipes/src/sequence/hash @@ -1 +1 @@ -2019-09-19 a62a89674c3b9e4a8ff10a29a1f40806a7ab2045 +2019-11-25 5574dbdb5994278383fbe010b92d5efe38165670 diff --git a/repos/os/recipes/src/terminal_crosslink/hash b/repos/os/recipes/src/terminal_crosslink/hash index 95afc365a..c932903db 100644 --- a/repos/os/recipes/src/terminal_crosslink/hash +++ b/repos/os/recipes/src/terminal_crosslink/hash @@ -1 +1 @@ -2019-09-19 0eb48916ec1a438169e8b410bc692cd6f60106f6 +2019-11-25 04b57136c8eb318d9a1a78e64e86aecda23f9e3e diff --git a/repos/os/recipes/src/terminal_log/hash b/repos/os/recipes/src/terminal_log/hash index 2b4a79d2b..66bcaa634 100644 --- a/repos/os/recipes/src/terminal_log/hash +++ b/repos/os/recipes/src/terminal_log/hash @@ -1 +1 @@ -2019-09-19 2db8e2cb276034183de8d27044c6e93b112f81db +2019-11-25 7847a20d040bce19bf7af01a0202e597709a6ad2 diff --git a/repos/os/recipes/src/test-block/hash b/repos/os/recipes/src/test-block/hash index 662d8e42f..d180ed838 100644 --- a/repos/os/recipes/src/test-block/hash +++ b/repos/os/recipes/src/test-block/hash @@ -1 +1 @@ -2019-09-19 a91a352e6fcbb777ece70f9f775a6636b8185174 +2019-11-25 e6693cb7bc4187cb023a87833e494e808fda4930 diff --git a/repos/os/recipes/src/test-bomb/hash b/repos/os/recipes/src/test-bomb/hash index cb0a1da1b..8b79009f9 100644 --- a/repos/os/recipes/src/test-bomb/hash +++ b/repos/os/recipes/src/test-bomb/hash @@ -1 +1 @@ -2019-09-19 22019423c8b966cdc68cc491878432889d540fb3 +2019-11-25 417279d2d5ad8c0520dfad8abb3b270efa43b595 diff --git a/repos/os/recipes/src/test-clipboard/hash b/repos/os/recipes/src/test-clipboard/hash index 461ab06fe..c6ef5b522 100644 --- a/repos/os/recipes/src/test-clipboard/hash +++ b/repos/os/recipes/src/test-clipboard/hash @@ -1 +1 @@ -2019-09-19 531f1f15658b5fa5bcffb5e4e032b833699fce9a +2019-11-25 adbbf6dddcca1c931f67c5721b8bf486a1cf6a9d diff --git a/repos/os/recipes/src/test-dynamic_config/hash b/repos/os/recipes/src/test-dynamic_config/hash index df1f604d3..ed983011c 100644 --- a/repos/os/recipes/src/test-dynamic_config/hash +++ b/repos/os/recipes/src/test-dynamic_config/hash @@ -1 +1 @@ -2019-09-19 65ada68012606fab4c1d4f45145100374fdbe65e +2019-11-25 83eb6a76c91b1bb178cf080332f513269d257c99 diff --git a/repos/os/recipes/src/test-fault_detection/hash b/repos/os/recipes/src/test-fault_detection/hash index 5b1f72184..dc00e46e0 100644 --- a/repos/os/recipes/src/test-fault_detection/hash +++ b/repos/os/recipes/src/test-fault_detection/hash @@ -1 +1 @@ -2019-09-19 b7a2aa80c71301c187944fa32017461844371ee0 +2019-11-25 4e570314b39d4f225b4db3859c6b8b5f1b63daed diff --git a/repos/os/recipes/src/test-fs_packet/hash b/repos/os/recipes/src/test-fs_packet/hash index fd36e35a4..9463c8f30 100644 --- a/repos/os/recipes/src/test-fs_packet/hash +++ b/repos/os/recipes/src/test-fs_packet/hash @@ -1 +1 @@ -2019-09-19 9cc26a34179faf91c9a1a84e013806cc63d671ec +2019-11-25 1d7ef4909a977776fca978f7f885682f8cd40e94 diff --git a/repos/os/recipes/src/test-fs_report/hash b/repos/os/recipes/src/test-fs_report/hash index bbe0336b5..4ca997087 100644 --- a/repos/os/recipes/src/test-fs_report/hash +++ b/repos/os/recipes/src/test-fs_report/hash @@ -1 +1 @@ -2019-09-19 5f8b381bbdb2582233bb8c53dd88056dc223a2ef +2019-11-25 4dc21b2a60041bc962fe6e4c915de278e2c77d04 diff --git a/repos/os/recipes/src/test-immutable_rom/hash b/repos/os/recipes/src/test-immutable_rom/hash index 2f5a4c5d8..1c169a63b 100644 --- a/repos/os/recipes/src/test-immutable_rom/hash +++ b/repos/os/recipes/src/test-immutable_rom/hash @@ -1 +1 @@ -2019-09-19 55ebf5668e1d10159c82c849ff67076d52415419 +2019-11-25 918711860410f3d3f185be5e5c578639f9410509 diff --git a/repos/os/recipes/src/test-init/hash b/repos/os/recipes/src/test-init/hash index d8819402c..b8343eb8f 100644 --- a/repos/os/recipes/src/test-init/hash +++ b/repos/os/recipes/src/test-init/hash @@ -1 +1 @@ -2019-09-19 f13fad9c8334155c1f8e23be0e6322eb773bd08d +2019-11-25 d56b40d7c4ce0f234e08a9be98650503973adc1e diff --git a/repos/os/recipes/src/test-init_loop/hash b/repos/os/recipes/src/test-init_loop/hash index 81151b0f1..9b46dca30 100644 --- a/repos/os/recipes/src/test-init_loop/hash +++ b/repos/os/recipes/src/test-init_loop/hash @@ -1 +1 @@ -2019-09-19 bd37da2d89e7fd37d47e7a9d20838a67778b8250 +2019-11-25 fcd614247a5034d6f7ee1f67343216b5dac9c4b7 diff --git a/repos/os/recipes/src/test-nic_loopback/hash b/repos/os/recipes/src/test-nic_loopback/hash index ccec70273..84862b99b 100644 --- a/repos/os/recipes/src/test-nic_loopback/hash +++ b/repos/os/recipes/src/test-nic_loopback/hash @@ -1 +1 @@ -2019-09-19 de73bd5b28a696ab485087461259fb77b100dea2 +2019-11-25 5f0740fee7a5d755287c7ae972ba0378aadda7a7 diff --git a/repos/os/recipes/src/test-ram_fs_chunk/hash b/repos/os/recipes/src/test-ram_fs_chunk/hash index 300afbe66..e830551bb 100644 --- a/repos/os/recipes/src/test-ram_fs_chunk/hash +++ b/repos/os/recipes/src/test-ram_fs_chunk/hash @@ -1 +1 @@ -2019-09-19 0c76f5d7f162ac062fd0b614dc275489acda8ffb +2019-11-25 f7d26372be57c72259743eb365de5e4719ee1c70 diff --git a/repos/os/recipes/src/test-report_rom/hash b/repos/os/recipes/src/test-report_rom/hash index 1408a34de..55d8a9c3e 100644 --- a/repos/os/recipes/src/test-report_rom/hash +++ b/repos/os/recipes/src/test-report_rom/hash @@ -1 +1 @@ -2019-09-19 8fc435de244f5e72dba54f61e15d96efdabe0053 +2019-11-25 ee6c43636960d73de27b00da356114c98476e4a8 diff --git a/repos/os/recipes/src/test-resource_request/hash b/repos/os/recipes/src/test-resource_request/hash index 571d3f3bd..09b1afc09 100644 --- a/repos/os/recipes/src/test-resource_request/hash +++ b/repos/os/recipes/src/test-resource_request/hash @@ -1 +1 @@ -2019-09-19 25221c8801c75581396a4a4e7d9035e7365b760d +2019-11-25 702d0041c2d7c8ec10c83fbdef09e790a0053792 diff --git a/repos/os/recipes/src/test-resource_yield/hash b/repos/os/recipes/src/test-resource_yield/hash index bb7b908d3..366ef0280 100644 --- a/repos/os/recipes/src/test-resource_yield/hash +++ b/repos/os/recipes/src/test-resource_yield/hash @@ -1 +1 @@ -2019-09-19 80026de6e1a8b36644c5d8e1694e3800a7592fd9 +2019-11-25 5da464896d739e3bbb2d2dacfbb3edb575865dab diff --git a/repos/os/recipes/src/test-rom_block/hash b/repos/os/recipes/src/test-rom_block/hash index 7f0b5af74..c0402bfd0 100644 --- a/repos/os/recipes/src/test-rom_block/hash +++ b/repos/os/recipes/src/test-rom_block/hash @@ -1 +1 @@ -2019-09-19 7a2b4141d2489154d4c22f25bd465f6d3d5244b2 +2019-11-25 41a61f3677815390fedde71bf8a565ed700b9b91 diff --git a/repos/os/recipes/src/test-rtc/hash b/repos/os/recipes/src/test-rtc/hash index f73ae0840..4d846f7db 100644 --- a/repos/os/recipes/src/test-rtc/hash +++ b/repos/os/recipes/src/test-rtc/hash @@ -1 +1 @@ -2019-09-19 15ad0ee82032e69a4ae839f0af341259016a282b +2019-11-25 8de092bd60f79096fc031053c8b08b60e51426dd diff --git a/repos/os/recipes/src/test-signal/hash b/repos/os/recipes/src/test-signal/hash index 2f8a1b92e..4ca4d3445 100644 --- a/repos/os/recipes/src/test-signal/hash +++ b/repos/os/recipes/src/test-signal/hash @@ -1 +1 @@ -2019-09-19 a0cdfdbd273f1fc4dd1fd8ad6aa776b7a30eb949 +2019-11-25 8b176fc2ae60ca94ae8cde64abbc8dfa31ebcc1e diff --git a/repos/os/recipes/src/test-slab/hash b/repos/os/recipes/src/test-slab/hash index affb4f0af..c790aab38 100644 --- a/repos/os/recipes/src/test-slab/hash +++ b/repos/os/recipes/src/test-slab/hash @@ -1 +1 @@ -2019-09-19 ae9cdc1b6c1b59453b1f14c588fc403c58d35869 +2019-11-25 2cce6eb903a0e8d38ef18496bbff75d50fe0fa10 diff --git a/repos/os/recipes/src/test-terminal_crosslink/hash b/repos/os/recipes/src/test-terminal_crosslink/hash index c79a1e16f..b59b1a38c 100644 --- a/repos/os/recipes/src/test-terminal_crosslink/hash +++ b/repos/os/recipes/src/test-terminal_crosslink/hash @@ -1 +1 @@ -2019-09-19 ca46e8b9880a65d3e5f0164329d31b96cd143674 +2019-11-25 57593962e1875642ffc4dfdbc6d1eb6f96882a40 diff --git a/repos/os/recipes/src/test-trace/hash b/repos/os/recipes/src/test-trace/hash index 37a23fb6b..ffa8ab446 100644 --- a/repos/os/recipes/src/test-trace/hash +++ b/repos/os/recipes/src/test-trace/hash @@ -1 +1 @@ -2019-09-19 db777170a538573d3180b4d3d76d3ef897052f1f +2019-11-25 2f7d2938592ffa805f64e871e2b0692e270c4677 diff --git a/repos/os/recipes/src/test-trace_logger/hash b/repos/os/recipes/src/test-trace_logger/hash index 506da9b45..9af63c3fb 100644 --- a/repos/os/recipes/src/test-trace_logger/hash +++ b/repos/os/recipes/src/test-trace_logger/hash @@ -1 +1 @@ -2019-09-19 8563ab5b5cf9de4aa2a5148ca4fc44b44f83a8b9 +2019-11-25 44fd9af0310341fb01ba0300e048a7075ca81e20 diff --git a/repos/os/recipes/src/test-utf8/hash b/repos/os/recipes/src/test-utf8/hash index a2eb97b6d..f04633c10 100644 --- a/repos/os/recipes/src/test-utf8/hash +++ b/repos/os/recipes/src/test-utf8/hash @@ -1 +1 @@ -2019-09-19 30affe8ea2ff70df735ff3fc636214900901064b +2019-11-25 d324f00fc91221964e3009db3fc66b8a9dae9407 diff --git a/repos/os/recipes/src/test-vfs_stress/hash b/repos/os/recipes/src/test-vfs_stress/hash index 606af73cd..9e3ae856d 100644 --- a/repos/os/recipes/src/test-vfs_stress/hash +++ b/repos/os/recipes/src/test-vfs_stress/hash @@ -1 +1 @@ -2019-09-19 9346135777d8bf12c18c5f4e026b59b0f0dda890 +2019-11-25 c23c8cb7d55ed8571d33f65b41b9a770cc1a5777 diff --git a/repos/os/recipes/src/test-weak_ptr/hash b/repos/os/recipes/src/test-weak_ptr/hash index bebe18547..7e414fef3 100644 --- a/repos/os/recipes/src/test-weak_ptr/hash +++ b/repos/os/recipes/src/test-weak_ptr/hash @@ -1 +1 @@ -2019-09-19 49e1ec923535a9b8edf85072393a07141111dafd +2019-11-25 b23c389b7632563ab90ba839f073ecf1bd98258c diff --git a/repos/os/recipes/src/top/hash b/repos/os/recipes/src/top/hash index e4859cfb5..bedf2e74e 100644 --- a/repos/os/recipes/src/top/hash +++ b/repos/os/recipes/src/top/hash @@ -1 +1 @@ -2019-09-19 b5aa9bbd384c656f80a4a063482574c2a15001a5 +2019-11-25 f331cef18f6f60314205fbfeff65623300a64d37 diff --git a/repos/os/recipes/src/trace_logger/hash b/repos/os/recipes/src/trace_logger/hash index 70bfceb78..bf9099519 100644 --- a/repos/os/recipes/src/trace_logger/hash +++ b/repos/os/recipes/src/trace_logger/hash @@ -1 +1 @@ -2019-09-19 8dd42fce2b57693405931bdf9462bc1ff0f723b3 +2019-11-25 b64bbde989058809f489b42d2ece6b14e262c688 diff --git a/repos/os/recipes/src/trace_policy/hash b/repos/os/recipes/src/trace_policy/hash index 0441e8346..6cba5c645 100644 --- a/repos/os/recipes/src/trace_policy/hash +++ b/repos/os/recipes/src/trace_policy/hash @@ -1 +1 @@ -2019-09-19 2090fd2f09b2c4872c02f2c1e32098ce67cc4c56 +2019-11-25 d99ae0ceb955a78148a242171cdf0a919be9efb6 diff --git a/repos/os/recipes/src/trace_subject_reporter/hash b/repos/os/recipes/src/trace_subject_reporter/hash index c4b16360d..192d7c511 100644 --- a/repos/os/recipes/src/trace_subject_reporter/hash +++ b/repos/os/recipes/src/trace_subject_reporter/hash @@ -1 +1 @@ -2019-09-19 0932949fc0e4ceafc3d469813481a705243ec8c4 +2019-11-25 010e91ea26b2057ea60d578a0dbf4004c3b09ed3 diff --git a/repos/os/recipes/src/usb_block_drv/hash b/repos/os/recipes/src/usb_block_drv/hash index cebedfe19..48d324e8f 100644 --- a/repos/os/recipes/src/usb_block_drv/hash +++ b/repos/os/recipes/src/usb_block_drv/hash @@ -1 +1 @@ -2019-09-19 202a199b681479f1ac9c5cbaff5b2d4d5a13dc01 +2019-11-25 f22c3dc6f2c3d0bf12dca500e06598a768937aa9 diff --git a/repos/os/recipes/src/vfs/hash b/repos/os/recipes/src/vfs/hash index 18bfe64de..71c6a7739 100644 --- a/repos/os/recipes/src/vfs/hash +++ b/repos/os/recipes/src/vfs/hash @@ -1 +1 @@ -2019-09-19 d7933005c9e41595e7ec72176637157f89bef1de +2019-11-25 1f3b630ebff8aa5aa51a89f4a27d21f5ee695193 diff --git a/repos/os/recipes/src/zynq_nic_drv/hash b/repos/os/recipes/src/zynq_nic_drv/hash index 9a1315d65..0d95bfebe 100644 --- a/repos/os/recipes/src/zynq_nic_drv/hash +++ b/repos/os/recipes/src/zynq_nic_drv/hash @@ -1 +1 @@ -2019-09-19 de3a4964f45c566042162849c2b77c704fdd1538 +2019-11-25 fb610cdfbb32be1dd9eb83a566318951921de119 diff --git a/repos/os/run/nic_router_flood.run b/repos/os/run/nic_router_flood.run index aaa2bde00..2acb1c8ba 100644 --- a/repos/os/run/nic_router_flood.run +++ b/repos/os/run/nic_router_flood.run @@ -24,10 +24,9 @@ create_boot_directory import_from_depot [depot_user]/src/[base_src] \ [depot_user]/pkg/[drivers_nic_pkg] \ - [depot_user]/src/init \ - [depot_user]/src/nic_router + [depot_user]/src/init -build { app/ping test/net_flood } +build { app/ping test/net_flood server/nic_router server/dynamic_rom } install_config { <config> @@ -63,39 +62,89 @@ install_config { <provides> <service name="Nic"/> </provides> </start> + <start name="dynamic_rom"> + <resource name="RAM" quantum="4M"/> + <provides><service name="ROM"/> </provides> + <config verbose="yes"> + <rom name="nic_router.config"> + <inline> + +<config verbose="no" + verbose_packets="no" + verbose_packet_drop="yes" + verbose_domain_state="yes" + dhcp_discover_timeout_sec="1" + tcp_idle_timeout_sec="3600" + udp_idle_timeout_sec="3600" + icmp_idle_timeout_sec="3600"> + + <policy label_prefix="flood_links" domain="flood_links"/> + <policy label_prefix="ping" domain="flood_links"/> + <uplink domain="uplink"/> + + <domain name="uplink" interface="10.0.2.15/24" gateway="10.0.2.2" verbose_packets="no"> + <nat domain="flood_links" udp-ports="16384" + tcp-ports="16384" + icmp-ids="16384"/> + </domain> + + <domain name="flood_links" interface="10.0.1.1/24"> + <dhcp-server ip_first="10.0.1.100" + ip_last="10.0.1.200"/> + + <icmp dst="0.0.0.0/0" domain="uplink"/> + <udp dst="0.0.0.0/0"><permit-any domain="uplink"/></udp> + <tcp dst="0.0.0.0/0"><permit-any domain="uplink"/></tcp> + </domain> + +</config> + + </inline> + <sleep milliseconds="10000"/> + <inline> + +<config verbose="no" + verbose_packets="no" + verbose_packet_drop="no" + verbose_domain_state="yes" + dhcp_discover_timeout_sec="1" + tcp_idle_timeout_sec="3600" + udp_idle_timeout_sec="3600" + icmp_idle_timeout_sec="3600"> + + <policy label_prefix="flood_links" domain="flood_links"/> + <policy label_prefix="ping" domain="flood_links"/> + <uplink domain="uplink"/> + + <domain name="uplink" verbose_packets="no"> + <nat domain="flood_links" udp-ports="16384" + tcp-ports="16384" + icmp-ids="16384"/> + </domain> + + <domain name="flood_links" interface="10.0.1.1/24"> + <dhcp-server ip_first="10.0.1.100" + ip_last="10.0.1.200"/> + + <icmp dst="0.0.0.0/0" domain="uplink"/> + <udp dst="0.0.0.0/0"><permit-any domain="uplink"/></udp> + <tcp dst="0.0.0.0/0"><permit-any domain="uplink"/></tcp> + </domain> + +</config> + + </inline> + <sleep milliseconds="10000"/> + + </rom> + </config> + </start> + <start name="nic_router" caps="200"> <resource name="RAM" quantum="10M"/> <provides><service name="Nic"/></provides> - <config verbose="no" - verbose_packets="no" - verbose_packet_drop="yes" - verbose_domain_state="yes" - dhcp_discover_timeout_sec="1" - tcp_idle_timeout_sec="3600" - udp_idle_timeout_sec="3600" - icmp_idle_timeout_sec="3600"> - - <policy label_prefix="flood_links" domain="flood_links"/> - <policy label_prefix="ping" domain="flood_links"/> - <uplink domain="uplink"/> - - <domain name="uplink" verbose_packets="no"> - <nat domain="flood_links" udp-ports="16384" - tcp-ports="16384" - icmp-ids="16384"/> - </domain> - - <domain name="flood_links" interface="10.0.1.1/24"> - <dhcp-server ip_first="10.0.1.100" - ip_last="10.0.1.200"/> - - <icmp dst="0.0.0.0/0" domain="uplink"/> - <udp dst="0.0.0.0/0"><permit-any domain="uplink"/></udp> - <tcp dst="0.0.0.0/0"><permit-any domain="uplink"/></tcp> - </domain> - - </config> <route> + <service name="ROM" label="config"> <child name="dynamic_rom" label="nic_router.config"/> </service> <service name="Nic"> <child name="drivers"/> </service> <any-service> <parent/> <any-child/> </any-service> </route> @@ -149,7 +198,7 @@ install_config { </config>} -build_boot_image { test-net_flood ping } +build_boot_image { test-net_flood ping nic_router dynamic_rom } proc qemu_nic_model {} { if [have_spec x86] { return e1000 } diff --git a/repos/os/run/vmm_arm.run b/repos/os/run/vmm_arm.run index 480470fa7..6e3e5850b 100644 --- a/repos/os/run/vmm_arm.run +++ b/repos/os/run/vmm_arm.run @@ -6,7 +6,7 @@ assert_spec hw -if { ![have_spec imx7d_sabre] && ![have_spec arndale] } { +if { ![have_spec imx7d_sabre] && ![have_spec arndale] && ![have_spec imx8q_evk] } { puts "Run script is not supported on this platform" exit 0 } @@ -21,7 +21,7 @@ build $build_components create_boot_directory install_config { -<config verbose="yes"> +<config verbose="yes" prio_levels="2"> <parent-provides> <service name="ROM"/> <service name="IRQ"/> @@ -44,7 +44,7 @@ install_config { <resource name="RAM" quantum="1M"/> <provides> <service name="Terminal"/> </provides> </start> - <start name="vmm"> + <start name="vmm" caps="200" priority="-1"> <resource name="RAM" quantum="256M"/> </start> <start name="vm"> @@ -56,6 +56,18 @@ install_config { } +if { [have_spec arm] } { + + if {![file exists bin/linux]} { + puts "Download linux kernel ..." + exec >& /dev/null wget -c -O bin/linux http://genode.org/files/release-15.02/arm_vt/linux + } + + if {![file exists bin/dtb]} { + puts "Download device tree blob ..." + exec >& /dev/null wget -c -O bin/dtb http://genode.org/files/release-15.02/arm_vt/dtb + } + # # This test uses a Linux kernel built from unmodified vanilla kernel sources # but using a slightly simplified kernel configuration, as well as device tree @@ -76,15 +88,62 @@ install_config { # ! make ARCH=arm CROSS_COMPILE=<cross_compiler_prefix> -j8 Image # ! make ARCH=arm CROSS_COMPILE=<cross_compiler_prefix> vexpress-v2p-ca15-tc1.dtb # - -if {![file exists bin/linux]} { - puts "Download linux kernel ..." - exec >& /dev/null wget -c -O bin/linux http://genode.org/files/release-15.02/arm_vt/linux } -if {![file exists bin/dtb]} { - puts "Download device tree blob ..." - exec >& /dev/null wget -c -O bin/dtb http://genode.org/files/release-15.02/arm_vt/dtb +if { [have_spec arm_64] } { + + if {![file exists bin/linux]} { + puts "Download linux kernel ..." + exec >& /dev/null wget -c -O bin/linux http://genode.org/files/release-19.11/linux-arm64-image-5.2 + } + + if {![file exists bin/dtb]} { + puts "Download device tree blob ..." + exec >& /dev/null wget -c -O bin/dtb http://genode.org/files/release-19.11/dtb-arm64-virt + } + + if {![file exists bin/initrd]} { + puts "Download initramfs ..." + exec >& /dev/null wget -c -O bin/initrd http://genode.org/files/release-19.11/initrd-arm64 + } + +# +# To obtain the linux kernel, do the following steps: +# +# wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.53.tar.xz +# +# tar -xJf linux-4.19.53.tar.xz +# cd linux-4.19.53 +# +# make O=../build-linux-aarch64 ARCH=arm64 CROSS_COMPILE=/usr/local/genode/tool/current/bin/genode-aarch64- defconfig +# make O=../build-linux-aarch64 ARCH=arm64 CROSS_COMPILE=/usr/local/genode/tool/current/bin/genode-aarch64- -j32 +# +# copy ../build-linux-aarch64/arch/arm64/boot/Image to your build directory in 'bin/linux' +# +# +# To get the dtb (device-tree-binary), you have to compile the file: +# repos/os/src/server/vmm/spec/arm_v8/virt.dts with the dtc compiler: +# dtc repos/os/src/server/vmm/spec/arm_v8/virt.dts > bin/dtb +# +# +# To construct the initrd do the following: +# * get and install gcc from linaro +# (https://releases.linaro.org/components/toolchain/binaries/latest-7/) +# * build busybox +# wget https://busybox.net/downloads/busybox-1.29.3.tar.bz2 +# tar xjf busybox-1.29.3.tar.bz2 +# mkdir build-busybox-aarch64 +# cd busybox-1.29.3 +# make O=../build-busybox-aarch64 defconfig +# make O=../build-busybox-aarch64 menuconfig +# +# [*] Setting -> Build static binary (no shared libs) +# +# cd ../build-busybox-aarch64 +# make CROSS_COMPILE=/usr/local/gcc-linaro/bin/aarch64-linux-gnu- install -j6 +# * create ramdisk +# cd _install +# find . | cpio -H newc -o | gzip > ../initrd } set boot_modules { @@ -96,6 +155,7 @@ set boot_modules { linux dtb } +append_if [have_spec arm_64] boot_modules initrd build_boot_image $boot_modules # diff --git a/repos/os/src/app/block_tester/main.cc b/repos/os/src/app/block_tester/main.cc index 168602f0e..97dc3af5a 100644 --- a/repos/os/src/app/block_tester/main.cc +++ b/repos/os/src/app/block_tester/main.cc @@ -26,6 +26,7 @@ namespace Test { using namespace Genode; + struct Scratch_buffer; struct Result; struct Test_base; struct Main; @@ -35,6 +36,27 @@ namespace Test { } +class Test::Scratch_buffer +{ + private: + + Allocator &_alloc; + + Scratch_buffer(Scratch_buffer const &); + Scratch_buffer &operator = (Scratch_buffer const&); + + public: + + char * const base; + size_t const size; + + Scratch_buffer (Allocator &alloc, size_t size) + : _alloc(alloc), base((char*)alloc.alloc(size)), size(size) { } + + ~Scratch_buffer() { destroy(&_alloc, base); } +}; + + struct Test::Result { uint64_t duration { 0 }; @@ -161,11 +183,11 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element bool _finished { false }; bool _success { false }; - char _scratch_buffer[1u<<20] { }; + Scratch_buffer &_scratch_buffer; void _memcpy(char *dst, char const *src, size_t length) { - if (length > sizeof(_scratch_buffer)) { + if (length > _scratch_buffer.size) { warning("scratch buffer too small for copying"); return; } @@ -187,7 +209,7 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element log("job ", job.id, ": writing ", length, " bytes at ", offset); if (_copy) - _memcpy(dst, _scratch_buffer, length); + _memcpy(dst, _scratch_buffer.base, length); } /** @@ -203,7 +225,7 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element log("job ", job.id, ": got ", length, " bytes at ", offset); if (_copy) - _memcpy(_scratch_buffer, src, length); + _memcpy(_scratch_buffer.base, src, length); } /** @@ -256,7 +278,8 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element friend class Genode::Fifo<Test_base>; Test_base(Env &env, Allocator &alloc, Xml_node node, - Signal_context_capability finished_sig) + Signal_context_capability finished_sig, + Scratch_buffer &scratch_buffer) : _env(env), _alloc(alloc), _node(node), _verbose(node.attribute_value("verbose", false)), @@ -265,7 +288,8 @@ struct Test::Test_base : private Genode::Fifo<Test_base>::Element _progress_interval(_node.attribute_value("progress", (uint64_t)0)), _copy(_node.attribute_value("copy", true)), _batch(_node.attribute_value("batch", 1u)), - _finished_sig(finished_sig) + _finished_sig(finished_sig), + _scratch_buffer(scratch_buffer) { if (_progress_interval) _progress_timeout.construct(*_timer, *this, @@ -335,6 +359,10 @@ struct Test::Main bool const _stop_on_error { _config_rom.xml().attribute_value("stop_on_error", true) }; + Genode::Number_of_bytes const _scratch_buffer_size { + _config_rom.xml().attribute_value("scratch_buffer_size", + Genode::Number_of_bytes(1U<<20)) }; + Genode::Fifo<Test_base> _tests { }; struct Test_result : Genode::Fifo<Test_result>::Element @@ -430,6 +458,8 @@ struct Test::Main Genode::Signal_handler<Main> _finished_sigh { _env.ep(), *this, &Main::_handle_finished }; + Scratch_buffer _scratch_buffer { _heap, _scratch_buffer_size }; + void _construct_tests(Genode::Xml_node config) { try { @@ -438,25 +468,25 @@ struct Test::Main if (node.has_type("ping_pong")) { Test_base *t = new (&_heap) - Ping_pong(_env, _heap, node, _finished_sigh); + Ping_pong(_env, _heap, node, _finished_sigh, _scratch_buffer); _tests.enqueue(*t); } else if (node.has_type("random")) { Test_base *t = new (&_heap) - Random(_env, _heap, node, _finished_sigh); + Random(_env, _heap, node, _finished_sigh, _scratch_buffer); _tests.enqueue(*t); } else if (node.has_type("replay")) { Test_base *t = new (&_heap) - Replay(_env, _heap, node, _finished_sigh); + Replay(_env, _heap, node, _finished_sigh, _scratch_buffer); _tests.enqueue(*t); } else if (node.has_type("sequential")) { Test_base *t = new (&_heap) - Sequential(_env, _heap, node, _finished_sigh); + Sequential(_env, _heap, node, _finished_sigh, _scratch_buffer); _tests.enqueue(*t); } }); diff --git a/repos/os/src/app/block_tester/test_ping_pong.h b/repos/os/src/app/block_tester/test_ping_pong.h index ff9341a4a..10e2a9272 100644 --- a/repos/os/src/app/block_tester/test_ping_pong.h +++ b/repos/os/src/app/block_tester/test_ping_pong.h @@ -58,7 +58,7 @@ struct Test::Ping_pong : Test_base void _init() override { - if (_size > sizeof(_scratch_buffer)) { + if (_size > _scratch_buffer.size) { error("request size exceeds scratch buffer size"); throw Constructing_test_failed(); } diff --git a/repos/os/src/app/block_tester/test_random.h b/repos/os/src/app/block_tester/test_random.h index e2f1ed92a..889f58c57 100644 --- a/repos/os/src/app/block_tester/test_random.h +++ b/repos/os/src/app/block_tester/test_random.h @@ -109,7 +109,7 @@ struct Test::Random : Test_base void _init() override { - if (_size > sizeof(_scratch_buffer)) { + if (_size > _scratch_buffer.size) { error("request size exceeds scratch buffer size"); throw Constructing_test_failed(); } diff --git a/repos/os/src/app/block_tester/test_sequential.h b/repos/os/src/app/block_tester/test_sequential.h index a16c00ed1..f1032994e 100644 --- a/repos/os/src/app/block_tester/test_sequential.h +++ b/repos/os/src/app/block_tester/test_sequential.h @@ -37,7 +37,7 @@ struct Test::Sequential : Test_base void _init() override { - if (_size > sizeof(_scratch_buffer)) { + if (_size > _scratch_buffer.size) { error("request size exceeds scratch buffer size"); throw Constructing_test_failed(); } diff --git a/repos/os/src/app/cli_monitor/child.h b/repos/os/src/app/cli_monitor/child.h deleted file mode 100644 index 755c3241c..000000000 --- a/repos/os/src/app/cli_monitor/child.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * \brief Child carrying application-specific context information - * \author Norman Feske - * \date 2014-10-02 - */ - -/* - * Copyright (C) 2014-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 _CHILD_H_ -#define _CHILD_H_ - -/* public CLI-monitor includes */ -#include <cli_monitor/child.h> - -/* local includes */ -#include <line_editor.h> - -namespace Cli_monitor { struct Child; } - - -struct Cli_monitor::Child : Child_base, private List<Child>::Element -{ - friend class List<Child>; - - using List<Child>::Element::next; - - Argument argument; - - Child(Genode::Env &env, - Ram &ram, - Genode::Allocator &alloc, - Name const &label, - Binary_name const &binary, - Genode::Pd_session &ref_pd, - Genode::Pd_session_capability ref_pd_cap, - Genode::Region_map &local_rm, - Cap_quota cap_quota, - Genode::size_t ram_quota, - Genode::size_t ram_limit, - Genode::Signal_context_capability yield_response_sig_cap, - Genode::Signal_context_capability exit_sig_cap) - : - Child_base(env, - ram, - alloc, - label, - binary, - ref_pd, - ref_pd_cap, - local_rm, - cap_quota, - ram_quota, - ram_limit, - yield_response_sig_cap, - exit_sig_cap), - argument(label.string(), "subsystem") - { } -}; - -#endif /* _CHILD_H_ */ diff --git a/repos/os/src/app/cli_monitor/child_registry.h b/repos/os/src/app/cli_monitor/child_registry.h deleted file mode 100644 index abc8c2794..000000000 --- a/repos/os/src/app/cli_monitor/child_registry.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * \brief Registry of running children - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-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 _CHILD_REGISTRY_H_ -#define _CHILD_REGISTRY_H_ - -/* Genode includes */ -#include <util/list.h> - -/* local includes */ -#include <child.h> - -namespace Cli_monitor { class Child_registry; } - - -class Cli_monitor::Child_registry : public List<Child> -{ - private: - - /** - * Return true if a child with the specified name already exists - */ - bool _child_name_exists(const char *label) - { - for (Child *child = first() ; child; child = child->next()) - if (child->name() == label) - return true; - return false; - } - - public: - - enum { CHILD_NAME_MAX_LEN = 64 }; - - /** - * Produce new unique child name - */ - void unique_child_name(const char *prefix, char *dst, int dst_len) - { - char buf[CHILD_NAME_MAX_LEN]; - char suffix[8]; - suffix[0] = 0; - - for (int cnt = 1; true; cnt++) { - - /* build program name composed of prefix and numeric suffix */ - snprintf(buf, sizeof(buf), "%s%s", prefix, suffix); - - /* if such a program name does not exist yet, we are happy */ - if (!_child_name_exists(buf)) { - strncpy(dst, buf, dst_len); - return; - } - - /* increase number of suffix */ - snprintf(suffix, sizeof(suffix), ".%d", cnt + 1); - } - } - - /** - * Call functor 'fn' for each child - * - * The functor receives the child name as 'char const *'. - */ - template <typename FN> - void for_each_child_name(FN const &fn) const - { - for (Child const *child = first() ; child; child = child->next()) - fn(child->name()); - } -}; - -#endif /* _CHILD_REGISTRY_H_ */ diff --git a/repos/os/src/app/cli_monitor/command_line.h b/repos/os/src/app/cli_monitor/command_line.h deleted file mode 100644 index 5016e63bf..000000000 --- a/repos/os/src/app/cli_monitor/command_line.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * \brief Utility for command-line parsing - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-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 _COMMAND_LINE_H_ -#define _COMMAND_LINE_H_ - -#include <line_editor.h> - -namespace Cli_monitor { class Command_line; } - - -class Cli_monitor::Command_line -{ - private: - - char const *_cmd_line; - Command &_command; - - bool _parameter_is_known(Token token) - { - return Argument_tracker::lookup(token, _command.parameters()) != 0; - } - - Token _tag_token(char const *tag) - { - for (Token token(_cmd_line); token; token = token.next()) - if (strcmp(token.start(), tag, token.len()) == 0 - && strlen(tag) == token.len() - && _parameter_is_known(token)) - return token; - - return Token(); - } - - Token _value_token(char const *tag) - { - return _tag_token(tag).next().next(); - } - - static bool _is_parameter(Token token) - { - return token[0] == '-' && token[1] == '-'; - } - - - public: - - /** - * Constructor - * - * \param cmd_line null-terminated command line string - * \param command meta data about the command - */ - Command_line(char const *cmd_line, Command &command) - : _cmd_line(cmd_line), _command(command) { } - - /** - * Return true if tag is specified at the command line - */ - bool parameter_exists(char const *tag) - { - return _tag_token(tag); - } - - /** - * Return number argument specified for the given tag - */ - template <typename T> - bool parameter(char const *tag, T &result) - { - Token value = _value_token(tag); - return value && Genode::ascii_to(value.start(), result) != 0; - } - - /** - * Return string argument specified for the given tag - */ - bool parameter(char const *tag, char *result, size_t result_len) - { - Token value = _value_token(tag); - if (!value) - return false; - - value.string(result, result_len); - return true; - } - - bool argument(unsigned index, char *result, size_t result_len) - { - Argument_tracker argument_tracker(_command); - - /* argument counter */ - unsigned cnt = 0; - - for (Token token(_cmd_line); token; token = token.next()) { - - argument_tracker.supply_token(token); - - if (!argument_tracker.valid()) - return false; - - if (!argument_tracker.expect_arg()) - continue; - - Token arg = token.next(); - if (!arg) - return false; - - /* - * The 'arg' token could either the tag of a parameter or - * an argument. We only want to count the arguments. So - * we skip tokens that have the usual form a parameter tag. - */ - if (_is_parameter(arg)) - continue; - - if (cnt == index) { - arg.string(result, result_len); - return true; - } - cnt++; - } - return false; - } - - /** - * Validate parameter tags - * - * \return tag token of first unexpected parameter, or - * invalid token if no unexpected parameter was found - */ - Token unexpected_parameter() - { - Argument_tracker argument_tracker(_command); - - for (Token token(_cmd_line); token; token = token.next()) { - - argument_tracker.supply_token(token); - - if (!argument_tracker.valid()) - return token; - - if (!argument_tracker.expect_arg()) - continue; - - Token arg = token.next(); - - /* ignore non-parameter tokens (i.e., normal arguments) */ - if (!_is_parameter(arg)) - continue; - - /* if parameter with the given tag exists, we are fine */ - if (_parameter_is_known(arg)) - continue; - - /* we hit an unknown parameter tag */ - return arg; - } - return Token(); - } -}; - -#endif /* _COMMAND_LINE_H_ */ diff --git a/repos/os/src/app/cli_monitor/format_util.h b/repos/os/src/app/cli_monitor/format_util.h deleted file mode 100644 index cd3a9feb1..000000000 --- a/repos/os/src/app/cli_monitor/format_util.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * \brief Utilities for formatting output to terminal - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-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 _FORMAT_UTIL_H_ -#define _FORMAT_UTIL_H_ - -/* local includes */ -#include <terminal_util.h> - -namespace Cli_monitor { - - /** - * Print rational number with two fractional decimals - */ - static inline size_t format_number(char *dst, size_t len, size_t const value, - size_t const quotient, char const *unit) - { - size_t const integer = value / quotient; - size_t const n = snprintf(dst, len, "%ld.", integer); - size_t const remainder = ((value - (integer * quotient))*100) / quotient; - - if (len == n) return n; - - return n + snprintf(dst + n, len - n, "%s%ld%s", - remainder < 10 ? "0" : "", remainder, unit); - } - - - /** - * Print number of bytes using the best suitable unit - */ - static inline size_t format_bytes(char *dst, size_t len, size_t bytes) - { - enum { KB = 1024, MB = 1024*KB }; - - if (bytes > MB) - return format_number(dst, len, bytes, MB, " MiB"); - - if (bytes > KB) - return format_number(dst, len, bytes, KB, " KiB"); - - return snprintf(dst, len, "%ld bytes", bytes); - } - - - /** - * Print number in MiB, without unit - */ - static inline size_t format_mib(char *dst, size_t len, size_t bytes) - { - enum { KB = 1024, MB = 1024*KB }; - - return format_number(dst, len, bytes, MB , ""); - } - - - static inline size_t format_bytes(size_t bytes) - { - char buf[128]; - return format_bytes(buf, sizeof(buf), bytes); - } - - - static inline size_t format_mib(size_t bytes) - { - char buf[128]; - return format_mib(buf, sizeof(buf), bytes); - } - - - static inline void tprint_bytes(Terminal::Session &terminal, size_t bytes) - { - char buf[128]; - format_bytes(buf, sizeof(buf), bytes); - Terminal::tprintf(terminal, "%s", buf); - } - - - static inline void tprint_mib(Terminal::Session &terminal, size_t bytes) - { - char buf[128]; - format_mib(buf, sizeof(buf), bytes); - Terminal::tprintf(terminal, "%s", buf); - } - - - static inline void tprint_status_bytes(Terminal::Session &terminal, - char const *label, size_t bytes) - { - Terminal::tprintf(terminal, label); - tprint_bytes(terminal, bytes); - Terminal::tprintf(terminal, "\n"); - } - - - static void tprint_padding(Terminal::Session &terminal, size_t pad, char c = ' ') - { - char const buf[2] = { c, 0 }; - for (unsigned i = 0; i < pad; i++) - Terminal::tprintf(terminal, buf); - } -} - -#endif /* _FORMAT_UTIL_H_ */ diff --git a/repos/os/src/app/cli_monitor/help_command.h b/repos/os/src/app/cli_monitor/help_command.h deleted file mode 100644 index 691ed30cd..000000000 --- a/repos/os/src/app/cli_monitor/help_command.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * \brief Help command - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-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 _HELP_COMMAND_H_ -#define _HELP_COMMAND_H_ - -namespace Cli_monitor { struct Help_command; } - - -struct Cli_monitor::Help_command : Command -{ - Help_command() : Command("help", "brief help information") { } - - void execute(Command_line &, Terminal::Session &terminal) override - { - tprintf(terminal, " Press [tab] for a list of commands.\n"); - tprintf(terminal, " When given a command, press [tab] for a list of arguments.\n"); - } -}; - -#endif /* _HELP_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/kill_command.h b/repos/os/src/app/cli_monitor/kill_command.h deleted file mode 100644 index bd8875625..000000000 --- a/repos/os/src/app/cli_monitor/kill_command.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * \brief Kill command - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-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 _KILL_COMMAND_H_ -#define _KILL_COMMAND_H_ - -/* local includes */ -#include <child_registry.h> - -namespace Cli_monitor { struct Kill_command; } - - -struct Cli_monitor::Kill_command : Command -{ - Child_registry &_children; - - Genode::Allocator &_alloc; - - Parameter _kill_all_param { "--all", Parameter::VOID, "kill all subsystems" }; - - void _destroy_child(Child *child, Terminal::Session &terminal) - { - tprintf(terminal, "destroying subsystem '%s'\n", child->name().string()); - _children.remove(child); - Genode::destroy(_alloc, child); - } - - Kill_command(Child_registry &children, Genode::Allocator &alloc) - : - Command("kill", "destroy subsystem"), _children(children), _alloc(alloc) - { - add_parameter(_kill_all_param); - } - - void _for_each_argument(Argument_fn const &fn) const override - { - auto child_name_fn = [&] (Child_base::Name const &child_name) { - Argument arg(child_name.string(), ""); - fn(arg); - }; - - _children.for_each_child_name(child_name_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - bool const kill_all = cmd.parameter_exists("--all"); - - if (kill_all) { - for (Child *child = _children.first(); child; child = _children.first()) - _destroy_child(child, terminal); - return; - } - - char label[128]; - label[0] = 0; - if (cmd.argument(0, label, sizeof(label)) == false) { - tprintf(terminal, "Error: no subsystem name specified\n"); - return; - } - - /* lookup child by its unique name */ - for (Child *child = _children.first(); child; child = child->next()) { - if (child->name() == label) { - _destroy_child(child, terminal); - return; - } - } - - tprintf(terminal, "Error: subsystem '%s' does not exist\n", label); - } -}; - -#endif /* _KILL_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/line_editor.h b/repos/os/src/app/cli_monitor/line_editor.h deleted file mode 100644 index 1fbcd09af..000000000 --- a/repos/os/src/app/cli_monitor/line_editor.h +++ /dev/null @@ -1,890 +0,0 @@ -/* - * \brief Line editor for command-line interfaces - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-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 _LINE_EDITOR_H_ -#define _LINE_EDITOR_H_ - -/* Genode includes */ -#include <terminal_session/connection.h> -#include <util/string.h> -#include <util/list.h> -#include <util/token.h> -#include <util/misc_math.h> -#include <base/snprintf.h> - -namespace Cli_monitor { - - using Genode::List; - using Genode::max; - using Genode::strlen; - using Genode::strncpy; - using Genode::snprintf; - using Genode::strcmp; - using Genode::size_t; - using Genode::off_t; - using Genode::Interface; - - struct Completable; - struct Argument; - struct Parameter; - struct Command_line; - struct Command; - struct Command_registry; - struct Scanner_policy; - struct Argument_tracker; - struct Line_editor; - - typedef Genode::Token<Scanner_policy> Token; -} - - -struct Cli_monitor::Completable -{ - typedef Genode::String<64> Name; - typedef Genode::String<160> Short_help; - - Name const _name; - Short_help const _short_help; - - Name name() const { return _name; } - Short_help short_help() const { return _short_help; } - - Completable(char const *name, char const *short_help) - : _name(name), _short_help(short_help) { } -}; - - -/** - * Representation of normal command-line argument - */ -struct Cli_monitor::Argument : Completable -{ - Argument(char const *name, char const *short_help) - : Completable(name, short_help) { } - - char const *name_suffix() const { return ""; } -}; - - -/** - * Representation of a parameter of the form '--tag value' - */ -struct Cli_monitor::Parameter : List<Parameter>::Element, Completable -{ - enum Type { IDENT, NUMBER, VOID }; - - Type const _type; - - Parameter(char const *name, Type type, char const *short_help) - : - Completable(name, short_help), _type(type) - { } - - bool needs_value() const { return _type != VOID; } - - char const *name_suffix() const - { - switch (_type) { - case IDENT: return "<identifier>"; - case NUMBER: return "<number>"; - case VOID: return ""; - } - return ""; - } -}; - - -/** - * Representation of a command that can have arguments and parameters - */ -struct Cli_monitor::Command : private List<Command>::Element, - private Completable -{ - List<Parameter> _parameters { }; - - friend class List<Command>; - - using List<Command>::Element::next; - using Completable::name; - using Completable::short_help; - - /** - * Functor that takes a command 'Argument' object as argument - */ - struct Argument_fn : Interface - { - virtual void operator () (Argument const &) const = 0; - }; - - Command(char const *name, char const *short_help) - : Completable(name, short_help) { } - - virtual ~Command() { } - - void add_parameter(Parameter &par) { _parameters.insert(&par); } - - char const *name_suffix() const { return ""; } - - List<Parameter> ¶meters() { return _parameters; } - - virtual void execute(Command_line &, Terminal::Session &terminal) = 0; - - /** - * Command-specific support for 'for_each_argument' - */ - virtual void _for_each_argument(Argument_fn const &) const { }; - - /** - * Execute functor 'fn' for each command argument - */ - template <typename FN> - void for_each_argument(FN const &fn) const - { - struct _Fn : Argument_fn - { - FN const &fn; - void operator () (Argument const &arg) const override { fn(arg); } - _Fn(FN const &fn) : fn(fn) { } - } _fn(fn); - - _for_each_argument(_fn); - } -}; - - -struct Cli_monitor::Command_registry : List<Command> { }; - - -/** - * Scanner policy that accepts '-', '.' and '_' as valid identifier characters - */ -struct Cli_monitor::Scanner_policy -{ - static bool identifier_char(char c, unsigned i) - { - return Genode::is_letter(c) || (c == '_') || (c == '-') || (c == '.') - || (i && Genode::is_digit(c)); - } -}; - - -/** - * State machine used for sequentially parsing command-line arguments - */ -struct Cli_monitor::Argument_tracker -{ - private: - - Command &_command; - - enum State { EXPECT_COMMAND, EXPECT_SPACE_BEFORE_ARG, EXPECT_ARG, - EXPECT_SPACE_BEFORE_VAL, EXPECT_VAL, INVALID }; - - State _state; - - /** - * Return true if there is exactly one complete match and no additional - * partial matches - */ - static bool _one_matching_argument(char const *str, size_t str_len, - Command const &command) - { - unsigned complete_cnt = 0, partial_cnt = 0; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) { - partial_cnt++; - - if (strlen(arg.name().string()) == str_len) - complete_cnt++; - } - }; - - command.for_each_argument(argument_fn); - - return partial_cnt == 1 && complete_cnt == 1; - } - - public: - - Argument_tracker(Command &command) - : _command(command), _state(EXPECT_COMMAND) { } - - template <typename T> - static T *lookup(char const *str, size_t str_len, - List<T> &list) - { - Token tag(str, str_len); - for (T *curr = list.first(); curr; curr = curr->next()) - if (strcmp(tag.start(), curr->name().string(), tag.len()) == 0 - && strlen(curr->name().string()) == tag.len()) - return curr; - - return 0; - } - - template <typename T> - static T *lookup(Token token, List<T> &list) - { - return lookup(token.start(), token.len(), list); - } - - void supply_token(Token token, bool token_may_be_incomplete = false) - { - switch (_state) { - - case INVALID: break; - - case EXPECT_COMMAND: - - if (token.type() == Token::IDENT) { - _state = EXPECT_SPACE_BEFORE_ARG; - break; - } - _state = INVALID; - break; - - case EXPECT_SPACE_BEFORE_ARG: - - if (token.type() == Token::WHITESPACE) - _state = EXPECT_ARG; - break; - - case EXPECT_ARG: - - if (token.type() == Token::IDENT) { - - Parameter *parameter = - lookup(token.start(), token.len(), _command.parameters()); - - if (parameter && parameter->needs_value()) { - _state = EXPECT_SPACE_BEFORE_VAL; - break; - } - - if (!token_may_be_incomplete - || _one_matching_argument(token.start(), token.len(), _command)) - _state = EXPECT_SPACE_BEFORE_ARG; - } - break; - - case EXPECT_SPACE_BEFORE_VAL: - - if (token.type() == Token::WHITESPACE) - _state = EXPECT_VAL; - break; - - case EXPECT_VAL: - - if (token.type() == Token::IDENT - || token.type() == Token::NUMBER) { - - _state = EXPECT_SPACE_BEFORE_ARG; - } - break; - } - } - - bool valid() const { return _state != INVALID; } - bool expect_arg() const { return _state == EXPECT_ARG; } - bool expect_space() const { return _state == EXPECT_SPACE_BEFORE_ARG - || _state == EXPECT_SPACE_BEFORE_VAL; } -}; - - -/** - * Editing and completion logic - */ -class Cli_monitor::Line_editor -{ - private: - - char const *_prompt; - size_t const _prompt_len; - char * const _buf; - size_t const _buf_size; - unsigned _cursor_pos = 0; - Terminal::Session &_terminal; - Command_registry &_commands; - bool _complete = false; - - /** - * State tracker for escape sequences within user input - * - * This tracker is used to decode special keys (e.g., cursor keys). - */ - struct Seq_tracker - { - enum State { INIT, GOT_ESC, GOT_FIRST } _state = INIT; - char _normal = 0, _first = 0, _second = 0; - bool _sequence_complete { false }; - - Seq_tracker() { } - - void input(char c) - { - switch (_state) { - case INIT: - if (c == 27) - _state = GOT_ESC; - else - _normal = c; - _sequence_complete = false; - break; - - case GOT_ESC: - _first = c; - _state = GOT_FIRST; - break; - - case GOT_FIRST: - _second = c; - _state = INIT; - _sequence_complete = true; - break; - } - } - - bool normal() const { return _state == INIT && !_sequence_complete; } - - char normal_char() const { return _normal; } - - bool _fn_complete(char match_first, char match_second) const - { - return _sequence_complete - && _first == match_first - && _second == match_second; - } - - bool key_up() const { return _fn_complete(91, 65); } - bool key_down() const { return _fn_complete(91, 66); } - bool key_right() const { return _fn_complete(91, 67); } - bool key_left() const { return _fn_complete(91, 68); } - bool key_delete() const { return _fn_complete(91, 51); } - }; - - Seq_tracker _seq_tracker { }; - - void _write(char c) { _terminal.write(&c, sizeof(c)); } - - void _write(char const *s) { _terminal.write(s, strlen(s)); } - - void _write_spaces(unsigned num) - { - for (unsigned i = 0; i < num; i++) - _write(' '); - } - - void _write_newline() { _write(10); } - - void _clear_until_end_of_line() { _write("\e[K "); } - - void _move_cursor_to(unsigned pos) - { - char seq[10]; - snprintf(seq, sizeof(seq), "\e[%ldG", pos + _prompt_len); - _write(seq); - } - - void _delete_character() - { - strncpy(&_buf[_cursor_pos], &_buf[_cursor_pos + 1], _buf_size); - - _move_cursor_to(_cursor_pos); - _write(&_buf[_cursor_pos]); - _clear_until_end_of_line(); - _move_cursor_to(_cursor_pos); - } - - void _insert_character(char c) - { - /* insert regular character */ - if (_cursor_pos >= _buf_size - 1) - return; - - /* make room in the buffer */ - for (unsigned i = _buf_size - 1; i > _cursor_pos; i--) - _buf[i] = _buf[i - 1]; - _buf[_cursor_pos] = c; - - /* update terminal */ - _write(&_buf[_cursor_pos]); - _cursor_pos++; - _move_cursor_to(_cursor_pos); - } - - void _fresh_prompt() - { - _write(_prompt); - _write(_buf); - _move_cursor_to(_cursor_pos); - } - - void _handle_key() - { - enum { BACKSPACE = 8, - TAB = 9, - LINE_FEED = 10, - CARRIAGE_RETURN = 13 }; - - if (_seq_tracker.key_left()) { - if (_cursor_pos > 0) { - _cursor_pos--; - _write(BACKSPACE); - } - return; - } - - if (_seq_tracker.key_right()) { - if (_cursor_pos < strlen(_buf)) { - _cursor_pos++; - _move_cursor_to(_cursor_pos); - } - return; - } - - if (_seq_tracker.key_delete()) - _delete_character(); - - if (!_seq_tracker.normal()) - return; - - char const c = _seq_tracker.normal_char(); - - if (c == TAB) { - _perform_completion(); - return; - } - - if (c == CARRIAGE_RETURN || c == LINE_FEED) { - if (strlen(_buf) > 0) { - _write(LINE_FEED); - _complete = true; - } - return; - } - - if (c == BACKSPACE) { - if (_cursor_pos > 0) { - _cursor_pos--; - _delete_character(); - } - return; - } - - if (c == 126) - return; - - _insert_character(c); - } - - template <typename COMPLETABLE> - COMPLETABLE *_lookup_matching(char const *str, size_t str_len, - List<COMPLETABLE> &list) - { - Token tag(str, str_len); - COMPLETABLE *curr = list.first(); - for (; curr; curr = curr->next()) { - if (strcmp(tag.start(), curr->name(), tag.len()) == 0 - && strlen(curr->name()) == tag.len()) - return curr; - } - return nullptr; - } - - Command *_lookup_matching_command() - { - Token cmd(_buf, _cursor_pos); - for (Command *curr = _commands.first(); curr; curr = curr->next()) - if (strcmp(cmd.start(), curr->name().string(), cmd.len()) == 0 - && _cursor_pos > cmd.len()) - return curr; - return nullptr; - } - - template <typename T> - unsigned _num_partial_matches(char const *str, size_t str_len, List<T> &list) - { - Token token(str, str_len); - - unsigned num_partial_matches = 0; - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) != 0) - continue; - - num_partial_matches++; - } - return num_partial_matches; - } - - unsigned _num_matching_arguments(char const *str, size_t str_len, - Command const &command) const - { - unsigned num_matches = 0; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) - num_matches++; - }; - - command.for_each_argument(argument_fn); - - return num_matches; - } - - /** - * Determine the name-column width of list of partial matches - */ - template <typename T> - size_t _width_of_partial_matches(char const *str, size_t str_len, - List<T> &list) - { - Token token(str, str_len); - - size_t max_name_len = 0; - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) != 0) - continue; - - size_t const name_len = strlen(curr->name().string()) - + strlen(curr->name_suffix()); - max_name_len = max(max_name_len, name_len); - } - return max_name_len; - } - - unsigned _width_of_matching_arguments(char const *str, size_t str_len, - Command const &command) const - { - size_t max_name_len = 0; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) { - size_t const name_len = strlen(arg.name().string()); - if (name_len > max_name_len) - max_name_len = name_len; - } - }; - - command.for_each_argument(argument_fn); - - return max_name_len; - } - - template <typename T> - char const *_any_partial_match_name(char const *str, size_t str_len, - List<T> &list) - { - Token token(str, str_len); - - for (T *curr = list.first(); curr; curr = curr->next()) - if (strcmp(token.start(), curr->name().string(), token.len()) == 0) - return curr->name().string(); - - return 0; - } - - Argument::Name _any_matching_argument(char const *str, size_t str_len, - Command const &command) const - { - Argument::Name name; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) - name = arg.name(); - }; - - command.for_each_argument(argument_fn); - - return name; - } - - template <typename T> - void _list_partial_matches(char const *str, size_t str_len, - unsigned pad, List<T> &list) - { - Token token(str, str_len); - - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) != 0) - continue; - - _write_newline(); - _write_spaces(2); - _write(curr->name().string()); - _write_spaces(1); - _write(curr->name_suffix()); - - /* pad short help with whitespaces */ - size_t const name_len = strlen(curr->name().string()) - + strlen(curr->name_suffix()); - _write_spaces(pad + 3 - name_len); - _write(curr->short_help().string()); - } - } - - void _list_matching_arguments(char const *str, size_t str_len, - unsigned pad, Command const &command) - { - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) { - - _write_newline(); - _write_spaces(2); - _write(arg.name().string()); - _write_spaces(1); - _write(arg.name_suffix()); - - /* pad short help with whitespaces */ - size_t const name_len = strlen(arg.name().string()) - + strlen(arg.name_suffix()); - _write_spaces(pad + 3 - name_len); - _write(arg.short_help().string()); - } - }; - - command.for_each_argument(argument_fn); - } - - template <typename T> - void _do_completion(char const *str, size_t str_len, List<T> &list) - { - Token token(str, str_len); - - /* look up completable token */ - T *partial_match = 0; - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) == 0) { - partial_match = curr; - break; - } - } - - if (!partial_match) - return; - - for (unsigned i = token.len(); i < strlen(partial_match->name().string()); i++) - _insert_character(partial_match->name().string()[i]); - - _insert_character(' '); - } - - void _do_argument_completion(char const *str, size_t str_len, - Command const &command) - { - Argument::Name partial_match; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) - partial_match = arg.name(); - }; - - command.for_each_argument(argument_fn); - - for (unsigned i = str_len; i < strlen(partial_match.string()); i++) - _insert_character(partial_match.string()[i]); - - _insert_character(' '); - } - - void _complete_argument(char const *str, size_t str_len, Command &command) - { - unsigned const matching_parameters = - _num_partial_matches(str, str_len, command.parameters()); - - unsigned const matching_arguments = - _num_matching_arguments(str, str_len, command); - - /* matches are ambiguous */ - if (matching_arguments + matching_parameters > 1) { - - /* - * Try to complete additional characters that are common among - * all matches. - */ - char buf[Completable::Name::size()]; - strncpy(buf, str, Genode::min(sizeof(buf), str_len + 1)); - - /* pick any representative as a template to take characters from */ - char const *name = _any_partial_match_name(str, str_len, command.parameters()); - Argument::Name arg_name; - if (!name) { - arg_name = _any_matching_argument(str, str_len, command); - if (strlen(arg_name.string())) - name = arg_name.string(); - } - - size_t i = str_len; - for (; (i < sizeof(buf) - 1) && (i < strlen(name)); i++) { - - buf[i + 0] = name[i]; - buf[i + 1] = 0; - - if (matching_parameters != - _num_partial_matches(buf, i + 1, command.parameters())) - break; - - if (matching_arguments != - _num_matching_arguments(buf, i + 1, command)) - break; - - _insert_character(buf[i]); - } - - /* - * If we managed to do a partial completion, let's yield - * control to the user. - */ - if (i > str_len) - return; - - /* - * No automatic completion was possible, print list of possible - * parameters and arguments - */ - size_t const pad = - max(_width_of_partial_matches(str, str_len, command.parameters()), - _width_of_matching_arguments(str, str_len, command)); - - _list_partial_matches(str, str_len, pad, command.parameters()); - _list_matching_arguments(str, str_len, pad, command); - - _write_newline(); - _fresh_prompt(); - - return; - } - - if (matching_parameters == 1) - _do_completion(str, str_len, command.parameters()); - - if (matching_arguments == 1) - _do_argument_completion(str, str_len, command); - } - - void _perform_completion() - { - Command *command = _lookup_matching_command(); - - if (!command) { - unsigned const matches = _num_partial_matches(_buf, _cursor_pos, _commands); - - if (matches == 1) - _do_completion(_buf, _cursor_pos, _commands); - - if (matches > 1) { - unsigned const pad = - _width_of_partial_matches(_buf, _cursor_pos, _commands); - _list_partial_matches(_buf, _cursor_pos, pad, _commands); - _write_newline(); - _fresh_prompt(); - } - return; - } - - /* - * We hava a valid command, now try to complete the parameters... - */ - - /* determine token under the cursor */ - Argument_tracker argument_tracker(*command); - - Token token(_buf, _buf_size); - for (; token; token = token.next()) { - - argument_tracker.supply_token(token, true); - - if (!argument_tracker.valid()) - return; - - unsigned long const token_pos = (unsigned long)(token.start() - _buf); - - /* we have reached the token under the cursor */ - if (token.type() == Token::IDENT - && _cursor_pos >= token_pos - && _cursor_pos <= token_pos + token.len()) { - - if (argument_tracker.expect_arg()) { - char const *start = token.start(); - size_t const len = _cursor_pos - token_pos; - - _complete_argument(start, len, *command); - return; - } - } - } - - /* the cursor is positioned at beginning of new argument */ - if (argument_tracker.expect_arg()) - _complete_argument("", 0, *command); - - if (argument_tracker.expect_space()) - _insert_character(' '); - } - - public: - - /** - * Constructor - * - * \param prompt string to be printed at the beginning of the line - * \param buf destination buffer - * \param buf_size destination buffer size - * \param terminal terminal used as output device - * \param commands meta information about commands and their arguments - */ - Line_editor(char const *prompt, char *buf, size_t buf_size, - Terminal::Session &terminal, Command_registry &commands) - : - _prompt(prompt), _prompt_len(strlen(prompt)), - _buf(buf), _buf_size(buf_size), - _terminal(terminal), _commands(commands) - { - reset(); - } - - /** - * Reset prompt to initial state after construction - */ - void reset() - { - _buf[0] = 0; - _complete = false; - _cursor_pos = 0; - _seq_tracker = Seq_tracker(); - _fresh_prompt(); - } - - /** - * Supply a character of user input - */ - void submit_input(char c) - { - _seq_tracker.input(c); - _handle_key(); - } - - /** - * Returns true if the editing is complete, i.e., the user pressed the - * return key. - */ - bool completed() const { return _complete; } -}; - -#endif /* _LINE_EDITOR_H_ */ diff --git a/repos/os/src/app/cli_monitor/main.cc b/repos/os/src/app/cli_monitor/main.cc deleted file mode 100644 index 6c0a6029e..000000000 --- a/repos/os/src/app/cli_monitor/main.cc +++ /dev/null @@ -1,225 +0,0 @@ -/* - * \brief Simple command-line interface for managing Genode subsystems - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-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. - */ - -/* Genode includes */ -#include <base/attached_rom_dataspace.h> -#include <vfs/simple_env.h> -#include <base/component.h> - -/* public CLI-monitor includes */ -#include <cli_monitor/ram.h> - -/* local includes */ -#include <line_editor.h> -#include <command_line.h> -#include <format_util.h> -#include <status_command.h> -#include <kill_command.h> -#include <start_command.h> -#include <help_command.h> -#include <yield_command.h> -#include <ram_command.h> - -namespace Cli_monitor { - - struct Main; - using namespace Genode; -} - - -/****************** - ** Main program ** - ******************/ - -struct Cli_monitor::Main -{ - Genode::Env &_env; - - Terminal::Connection _terminal { _env }; - - Command_registry _commands { }; - - Child_registry _children { }; - - Command *_lookup_command(char const *buf) - { - Token token(buf); - for (Command *curr = _commands.first(); curr; curr = curr->next()) - if (strcmp(token.start(), curr->name().string(), token.len()) == 0 - && strlen(curr->name().string()) == token.len()) - return curr; - return 0; - } - - enum { COMMAND_MAX_LEN = 1000 }; - char _command_buf[COMMAND_MAX_LEN]; - Line_editor _line_editor { - "genode> ", _command_buf, sizeof(_command_buf), _terminal, _commands }; - - void _handle_terminal_read_avail(); - - Signal_handler<Main> _terminal_read_avail_handler { - _env.ep(), *this, &Main::_handle_terminal_read_avail }; - - /** - * Handler for child yield responses, or RAM resource-avail signals - */ - void _handle_yield_response() - { - for (Child *child = _children.first(); child; child = child->next()) - child->try_response_to_resource_request(); - } - - Signal_handler<Main> _yield_response_handler { - _env.ep(), *this, &Main::_handle_yield_response }; - - void _handle_child_exit() - { - Child *next = nullptr; - for (Child *child = _children.first(); child; child = next) { - next = child->next(); - if (child->exited()) { - _children.remove(child); - Genode::destroy(_heap, child); - } - } - } - - Signal_handler<Main> _child_exit_handler { - _env.ep(), *this, &Main::_handle_child_exit }; - - void _handle_yield_broadcast() - { - /* - * Compute argument of yield request to be broadcasted to all - * processes. - */ - size_t amount = 0; - - /* amount needed to reach preservation limit */ - Ram::Status ram_status = _ram.status(); - if (ram_status.avail < ram_status.preserve) - amount += ram_status.preserve - ram_status.avail; - - /* sum of pending resource requests */ - for (Child *child = _children.first(); child; child = child->next()) - amount += child->requested_ram_quota(); - - for (Child *child = _children.first(); child; child = child->next()) - child->yield(amount, true); - } - - Signal_handler<Main> _yield_broadcast_handler { - _env.ep(), *this, &Main::_handle_yield_broadcast }; - - Genode::Attached_rom_dataspace _config { _env, "config" }; - - Xml_node _vfs_config() const - { - try { return _config.xml().sub_node("vfs"); } - catch (Genode::Xml_node::Nonexistent_sub_node) { - Genode::error("missing '<vfs>' configuration"); - throw; - } - } - - size_t _ram_preservation_from_config() const - { - if (!_config.xml().has_sub_node("preservation")) - return 0; - - return _config.xml().sub_node("preservation") - .attribute_value("name", Genode::Number_of_bytes(0)); - } - - Ram _ram { _env.pd(), _env.pd_session_cap(), _ram_preservation_from_config(), - _yield_broadcast_handler, _yield_response_handler }; - - Heap _heap { _env.ram(), _env.rm() }; - - Vfs::Simple_env _vfs_env { _env, _heap, _vfs_config() }; - - Subsystem_config_registry _subsystem_config_registry { _vfs_env.root_dir(), _heap, _env.ep() }; - - template <typename T> - struct Registered : T - { - template <typename... ARGS> - Registered(Command_registry &commands, ARGS &&... args) - : T(args...) { commands.insert(this); } - }; - - /* initialize generic commands */ - Registered<Help_command> _help_command { _commands }; - Registered<Kill_command> _kill_command { _commands, _children, _heap }; - Registered<Start_command> _start_command { _commands, _env, _ram, _heap, - _env.pd(), _env.pd_session_cap(), - _env.rm(), _children, - _subsystem_config_registry, - _yield_response_handler, - _child_exit_handler }; - Registered<Status_command> _status_command { _commands, _ram, _children }; - Registered<Yield_command> _yield_command { _commands, _children }; - Registered<Ram_command> _ram_command { _commands, _children, _ram }; - - Main(Env &env) : _env(env) - { - _terminal.read_avail_sigh(_terminal_read_avail_handler); - } -}; - - -void Cli_monitor::Main::_handle_terminal_read_avail() -{ - /* supply pending terminal input to line editor */ - while (_terminal.avail() && !_line_editor.completed()) { - char c = 0; - _terminal.read(&c, 1); - _line_editor.submit_input(c); - } - - if (!_line_editor.completed()) - return; - - Command *command = _lookup_command(_command_buf); - if (!command) { - Token cmd_name(_command_buf); - tprintf(_terminal, "Error: unknown command \""); - _terminal.write(cmd_name.start(), cmd_name.len()); - tprintf(_terminal, "\"\n"); - _line_editor.reset(); - return; - } - - /* validate parameters against command meta data */ - Command_line cmd_line(_command_buf, *command); - Token unexpected = cmd_line.unexpected_parameter(); - if (unexpected) { - tprintf(_terminal, "Error: unexpected parameter \""); - _terminal.write(unexpected.start(), unexpected.len()); - tprintf(_terminal, "\"\n"); - _line_editor.reset(); - return; - } - command->execute(cmd_line, _terminal); - - /* - * The command might result in a change of the RAM usage. Validate - * that the preservation is satisfied. - */ - _ram.validate_preservation(); - _line_editor.reset(); -} - - -void Component::construct(Genode::Env &env) { static Cli_monitor::Main main(env); } diff --git a/repos/os/src/app/cli_monitor/no_extension.cc b/repos/os/src/app/cli_monitor/no_extension.cc deleted file mode 100644 index e64df753d..000000000 --- a/repos/os/src/app/cli_monitor/no_extension.cc +++ /dev/null @@ -1,17 +0,0 @@ -/* - * \brief Dummy implementation of CLI extension interface - * \author Norman Feske - * \date 2013-03-21 - */ - -/* - * Copyright (C) 2013-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 <extension.h> - -void Cli_monitor::init_extension(Command_registry &) { } - diff --git a/repos/os/src/app/cli_monitor/ram_command.h b/repos/os/src/app/cli_monitor/ram_command.h deleted file mode 100644 index a080db7df..000000000 --- a/repos/os/src/app/cli_monitor/ram_command.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * \brief RAM command - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-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 _RAM_COMMAND_H_ -#define _RAM_COMMAND_H_ - -/* local includes */ -#include <child_registry.h> - -namespace Cli_monitor { struct Ram_command; } - - -struct Cli_monitor::Ram_command : Command -{ - Child_registry &_children; - Ram &_ram; - - Parameter _quota_param { "--quota", Parameter::NUMBER, "new RAM quota" }; - Parameter _limit_param { "--limit", Parameter::NUMBER, "on-demand quota limit" }; - - Ram_command(Child_registry &children, Ram &ram) - : - Command("ram", "set RAM quota of subsystem"), - _children(children), _ram(ram) - { - add_parameter(_quota_param); - add_parameter(_limit_param); - } - - void _set_quota(Terminal::Session &terminal, Child &child, size_t const new_quota) - { - size_t const old_quota = child.ram_status().quota; - - if (new_quota > old_quota) { - - size_t amount = new_quota - old_quota; - size_t const avail = _ram.avail(); - if (amount > avail) { - tprintf(terminal, "upgrade of '%s' exceeds available quota of ", - child.name().string()); - tprint_bytes(terminal, avail); - tprintf(terminal, "\n"); - amount = avail; - } - - tprintf(terminal, "upgrading quota of '%s' to ", child.name().string()); - tprint_bytes(terminal, old_quota + amount); - tprintf(terminal, "\n"); - - try { - child.upgrade_ram_quota(amount); } - catch (Ram::Transfer_quota_failed) { - tprintf(terminal, "Error: transfer_quota failed\n"); } - - } if (new_quota < old_quota) { - - size_t amount = old_quota - new_quota; - size_t const avail = child.ram_status().avail; - - if (amount > avail) { - tprintf(terminal, "withdrawal of "); - tprint_bytes(terminal, amount); - tprintf(terminal, " exceeds available quota of "); - tprint_bytes(terminal, avail); - tprintf(terminal, "\n"); - amount = avail; - } - - tprintf(terminal, "depleting quota of '%s' to ", child.name().string()); - tprint_bytes(terminal, old_quota - amount); - tprintf(terminal, "\n"); - - try { - child.withdraw_ram_quota(amount); } - catch (Ram::Transfer_quota_failed) { - tprintf(terminal, "Error: transfer_quota failed\n"); } - } - } - - void _for_each_argument(Argument_fn const &fn) const override - { - auto child_name_fn = [&] (Child_base::Name const &child_name) { - Argument arg(child_name.string(), ""); - fn(arg); - }; - - _children.for_each_child_name(child_name_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - char label[128]; - label[0] = 0; - if (cmd.argument(0, label, sizeof(label)) == false) { - tprintf(terminal, "Error: no subsystem name specified\n"); - return; - } - - /* lookup child by its unique name */ - Child *child = _children.first(); - for (; child; child = child->next()) - if (child->name() == label) - break; - - if (!child) { - tprintf(terminal, "Error: subsystem '%s' does not exist\n", label); - return; - } - - bool const limit_specified = cmd.parameter_exists("--limit"); - Genode::Number_of_bytes limit = 0; - if (limit_specified) { - cmd.parameter("--limit", limit); - child->ram_limit(limit); - } - - if (cmd.parameter_exists("--quota")) { - Genode::Number_of_bytes quota = 0; - cmd.parameter("--quota", quota); - _set_quota(terminal, *child, quota); - } - } -}; - -#endif /* _RAM_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/start_command.h b/repos/os/src/app/cli_monitor/start_command.h deleted file mode 100644 index e217c59ee..000000000 --- a/repos/os/src/app/cli_monitor/start_command.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * \brief Start command - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-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 _START_COMMAND_H_ -#define _START_COMMAND_H_ - -/* Genode includes */ -#include <util/xml_node.h> - -/* local includes */ -#include <subsystem_config_registry.h> - -namespace Cli_monitor { class Start_command; } - - -class Cli_monitor::Start_command : public Command -{ - private: - - typedef Genode::Xml_node Xml_node; - typedef Genode::Signal_context_capability Signal_context_capability; - typedef Genode::Dataspace_capability Dataspace_capability; - - Genode::Env &_env; - Ram &_ram; - Genode::Allocator &_alloc; - Child_registry &_children; - Genode::Pd_session &_ref_pd; - Genode::Pd_session_capability _ref_pd_cap; - Genode::Region_map &_local_rm; - Subsystem_config_registry &_subsystem_configs; - List<Argument> _arguments { }; - Signal_context_capability _yield_response_sigh_cap; - Signal_context_capability _exit_sig_cap; - - void _execute_subsystem(char const *name, Command_line &cmd, - Terminal::Session &terminal, - Genode::Xml_node subsystem_node) - { - size_t count = 1; - Genode::Number_of_bytes ram = 0; - Genode::Number_of_bytes ram_limit = 0; - size_t caps = subsystem_node.attribute_value("caps", 0UL); - - /* read default RAM quota from config */ - try { - Xml_node rsc = subsystem_node.sub_node("resource"); - for (;; rsc = rsc.next("resource")) { - if (rsc.attribute("name").has_value("RAM")) { - rsc.attribute("quantum").value(ram); - - if (rsc.has_attribute("limit")) - rsc.attribute("limit").value(ram_limit); - break; - } - } - } catch (...) { } - - cmd.parameter("--count", count); - cmd.parameter("--ram", ram); - cmd.parameter("--ram-limit", ram_limit); - - /* acount for cli_monitor local metadata */ - size_t preserve_ram = 100*1024; - if (count * (ram + preserve_ram) > _ram.avail()) { - tprintf(terminal, "Error: RAM quota exceeds available quota\n"); - return; - } - - bool const verbose = cmd.parameter_exists("--verbose"); - - /* - * Determine binary name - * - * Use subsystem name by default, override with '<binary>' declaration. - */ - typedef Genode::String<128> Binary_name; - Binary_name binary_name; - try { - Xml_node bin = subsystem_node.sub_node("binary"); - binary_name = bin.attribute_value("name", Binary_name()); - } catch (...) { } - - for (unsigned i = 0; i < count; i++) { - - /* generate unique child name */ - char label[Child_registry::CHILD_NAME_MAX_LEN]; - _children.unique_child_name(name, label, sizeof(label)); - - tprintf(terminal, "starting new subsystem '%s'\n", label); - - if (verbose) { - tprintf(terminal, " RAM quota: "); - tprint_bytes(terminal, ram); - tprintf(terminal,"\n"); - if (ram_limit) { - tprintf(terminal, " RAM limit: "); - tprint_bytes(terminal, ram_limit); - tprintf(terminal,"\n"); - } - tprintf(terminal, " binary: %s\n", binary_name.string()); - } - - Child *child = 0; - try { - child = new (_alloc) - Child(_env, _ram, _alloc, label, binary_name, - _ref_pd, _ref_pd_cap, _local_rm, - Genode::Cap_quota{caps}, ram, ram_limit, - _yield_response_sigh_cap, _exit_sig_cap); - } - catch (Genode::Service_denied) { - tprintf(terminal, "Error: could not start child \"%s\"\n", - binary_name); - return; - } - catch (Child::Quota_exceeded) { - tprintf(terminal, "Error: insufficient memory, need "); - tprint_bytes(terminal, ram + Child::DONATED_RAM_QUOTA); - tprintf(terminal, ", have "); - tprint_bytes(terminal, _ram.avail()); - tprintf(terminal, "\n"); - return; - } - catch (Genode::Allocator::Out_of_memory) { - tprintf(terminal, "Error: could not allocate meta data, out of memory\n"); - return; - } - - /* configure child */ - try { - Xml_node config_node = subsystem_node.sub_node("config"); - config_node.with_raw_node([&] (char const *start, size_t length) { - child->configure(start, length); }); - - if (verbose) - tprintf(terminal, " config: inline\n"); - } catch (...) { - if (verbose) - tprintf(terminal, " config: none\n"); - } - - _children.insert(child); - child->start(); - } - } - - Parameter _count_param { "--count", Parameter::NUMBER, "number of instances" }; - Parameter _ram_param { "--ram", Parameter::NUMBER, "initial RAM quota" }; - Parameter _ram_limit_param { "--ram-limit", Parameter::NUMBER, "limit for expanding RAM quota" }; - Parameter _verbose_param { "--verbose", Parameter::VOID, "show diagnostics" }; - - public: - - Start_command(Genode::Env &env, - Ram &ram, - Genode::Allocator &alloc, - Genode::Pd_session &ref_pd, - Genode::Pd_session_capability ref_pd_cap, - Genode::Region_map &local_rm, - Child_registry &children, - Subsystem_config_registry &subsustem_configs, - Signal_context_capability yield_response_sigh_cap, - Signal_context_capability exit_sig_cap) - : - Command("start", "create new subsystem"), - _env(env), _ram(ram), _alloc(alloc), _children(children), - _ref_pd(ref_pd), _ref_pd_cap(ref_pd_cap), _local_rm(local_rm), - _subsystem_configs(subsustem_configs), - _yield_response_sigh_cap(yield_response_sigh_cap), - _exit_sig_cap(exit_sig_cap) - { - add_parameter(_count_param); - add_parameter(_ram_param); - add_parameter(_ram_limit_param); - add_parameter(_verbose_param); - } - - void _for_each_argument(Argument_fn const &fn) const override - { - /* functor for processing a subsystem configuration */ - auto process_subsystem_config_fn = [&] (Genode::Xml_node node) { - - if (!node.has_attribute("name")) { - Genode::warning("Missing name in '<subsystem>' configuration"); - return; - } - - typedef Genode::String<64> Name; - Name const name = node.attribute_value("name", Name()); - - char const *prefix = "config: "; - size_t const prefix_len = strlen(prefix); - - char help[Parameter::Short_help::size() + prefix_len]; - strncpy(help, prefix, ~0); - try { - Genode::Xml_attribute const help_attr = node.attribute("help"); - help_attr.with_raw_value([&] (char const *start, size_t len) { - strncpy(help + prefix_len, start, - Genode::min(len, Parameter::Short_help::size())); }); - } - catch (Xml_node::Nonexistent_attribute) { - Genode::warning("Missing help in '<subsystem>' configuration"); - return; - } - - Argument arg(name.string(), help); - fn(arg); - }; - - /* scan subsystem config registry for possible subsystem arguments */ - _subsystem_configs.for_each_config(process_subsystem_config_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - char name[128]; - name[0] = 0; - if (cmd.argument(0, name, sizeof(name)) == false) { - tprintf(terminal, "Error: no configuration name specified\n"); - return; - } - - char buf[128]; - if (cmd.argument(1, buf, sizeof(buf))) { - tprintf(terminal, "Error: unexpected argument \"%s\"\n", buf); - return; - } - - try { - _subsystem_configs.for_config(name, [&] (Genode::Xml_node node) - { - _execute_subsystem(name, cmd, terminal, node); - }); - - } catch (Subsystem_config_registry::Nonexistent_subsystem_config) { - tprintf(terminal, "Error: no configuration for \"%s\"\n", name); - } - } - - List<Argument> &arguments() { return _arguments; } -}; - -#endif /* _START_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/status_command.h b/repos/os/src/app/cli_monitor/status_command.h deleted file mode 100644 index 929a56d6f..000000000 --- a/repos/os/src/app/cli_monitor/status_command.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * \brief Status command - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-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 _STATUS_COMMAND_H_ -#define _STATUS_COMMAND_H_ - -/* local includes */ -#include <table.h> -#include <child_registry.h> - -namespace Cli_monitor { struct Status_command; } - - -struct Cli_monitor::Status_command : Command -{ - Child_registry &_children; - Ram &_ram; - - Status_command(Ram &ram, Child_registry &children) - : - Command("status", "show runtime status"), - _children(children), _ram(ram) - { } - - void execute(Command_line &, Terminal::Session &terminal) override - { - using Terminal::tprintf; - - Ram::Status const ram_status = _ram.status(); - - tprint_status_bytes(terminal, " RAM quota: ", ram_status.quota); - tprint_status_bytes(terminal, " used: ", ram_status.used); - tprint_status_bytes(terminal, " avail: ", ram_status.avail); - tprint_status_bytes(terminal, " preserve: ", ram_status.preserve); - - tprintf(terminal, "\n"); - - struct Child_info - { - enum Column { NAME, QUOTA, LIMIT, XFER, USED, AVAIL, STATUS }; - - constexpr static size_t num_columns() { return STATUS + 1; } - - char const *name = 0; - Child::Ram_status ram_status { }; - - static char const *label(Column column) - { - switch (column) { - case NAME: return "process"; - case QUOTA: return "quota"; - case LIMIT: return "limit"; - case XFER: return "xfer"; - case USED: return "alloc"; - case AVAIL: return "avail"; - case STATUS: return "status"; - }; - return ""; - } - - size_t len(Column column) const - { - switch (column) { - case NAME: return strlen(name); - case QUOTA: return format_mib(ram_status.quota); - case LIMIT: - return ram_status.limit ? format_mib(ram_status.limit) : 0; - - case XFER: return format_mib(ram_status.xfer); - case USED: return format_mib(ram_status.used); - case AVAIL: return format_mib(ram_status.avail); - case STATUS: - { - size_t const req = ram_status.req; - return req ? strlen("req ") + format_mib(req) : 0; - } - }; - return 0; - } - - static bool left_aligned(Column column) - { - switch (column) { - case NAME: return true; - case QUOTA: return false; - case LIMIT: return false; - case XFER: return false; - case USED: return false; - case AVAIL: return false; - case STATUS: return true; - }; - return false; - } - - void print_cell(Terminal::Session &terminal, Column column) - { - switch (column) { - case NAME: tprintf(terminal, "%s", name); break; - case QUOTA: tprint_mib(terminal, ram_status.quota); break; - case LIMIT: - - if (ram_status.limit) - tprint_mib(terminal, ram_status.limit); - break; - - case XFER: tprint_mib(terminal, ram_status.xfer); break; - case USED: tprint_mib(terminal, ram_status.used); break; - case AVAIL: tprint_mib(terminal, ram_status.avail); break; - case STATUS: - if (ram_status.req) { - tprintf(terminal, "req "); - tprint_mib(terminal, ram_status.req); - } - break; - }; - } - - Child_info() { } - Child_info(char const *name, Child::Ram_status ram_status) - : - name(name), ram_status(ram_status) - { } - }; - - /* - * Take snapshot of child information. - */ - size_t num_children = 0; - for (Child *c = _children.first(); c; c = c->next()) - num_children++; - - Child_info child_info[num_children]; - unsigned i = 0; - for (Child *c = _children.first(); c && i < num_children; c = c->next(), i++) - child_info[i] = Child_info(c->name().string(), c->ram_status()); - - /* - * Print table - */ - if (num_children) { - Table<Child_info>::print(terminal, child_info, num_children); - tprintf(terminal, "\n"); - } - } -}; - -#endif /* _STATUS_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/subsystem_config_registry.h b/repos/os/src/app/cli_monitor/subsystem_config_registry.h deleted file mode 100644 index f94c522e4..000000000 --- a/repos/os/src/app/cli_monitor/subsystem_config_registry.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * \brief Registry of subsystem configuration - * \author Norman Feske - * \date 2015-01-27 - */ - -/* - * Copyright (C) 2015-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 _SUBSYSTEM_CONFIG_REGISTRY_H_ -#define _SUBSYSTEM_CONFIG_REGISTRY_H_ - -/* Genode includes */ -#include <vfs/file_system.h> -#include <vfs/vfs_handle.h> - -namespace Cli_monitor { class Subsystem_config_registry; } - - -class Cli_monitor::Subsystem_config_registry -{ - public: - - /** - * Exception type - */ - class Nonexistent_subsystem_config { }; - - private: - - Vfs::File_system &_fs; - Genode::Allocator &_alloc; - Genode::Entrypoint &_ep; - - enum { CONFIG_BUF_SIZE = 32*1024 }; - char _config_buf[CONFIG_BUF_SIZE]; - - char const *_subsystems_path() { return "/subsystems"; } - char const *_subsystem_suffix() { return ".subsystem"; } - - /** - * Return index of ".subsystem" suffix in dirent name - * - * \return index, or 0 if no matching suffix could be found - */ - unsigned _subsystem_suffix(Vfs::Directory_service::Dirent const &dirent) - { - unsigned found = 0; - for (unsigned i = 0; i < sizeof(dirent.name) && dirent.name[i]; i++) - if (Genode::strcmp(_subsystem_suffix(), &dirent.name[i]) == 0) - found = i; - - return found; - } - - - public: - - /** - * Constructor - */ - Subsystem_config_registry(Vfs::File_system &fs, Genode::Allocator &alloc, - Genode::Entrypoint &ep) - : - _fs(fs), _alloc(alloc), _ep(ep) - { } - - /** - * Execute functor 'fn' for specified subsystem name - * - * The functor is called with the subsystem XML node as argument - * - * \throw Nonexistent_subsystem_config - */ - template <typename FN> - void for_config(char const *name, FN const &fn) - { - using Genode::error; - - /* - * Load subsystem configuration - */ - - Genode::Path<256> path(_subsystems_path()); - path.append("/"); - path.append(name); - path.append(_subsystem_suffix()); - - Vfs::Vfs_handle *handle = nullptr; - - Vfs::Directory_service::Open_result const open_result = - _fs.open(path.base(), - Vfs::Directory_service::OPEN_MODE_RDONLY, - &handle, _alloc); - - Vfs::Vfs_handle::Guard handle_guard(handle); - - if (open_result != Vfs::Directory_service::OPEN_OK) { - error("could not open '", path, "', err=", (int)open_result); - throw Nonexistent_subsystem_config(); - } - - Vfs::file_size out_count = 0; - - handle->fs().queue_read(handle, sizeof(_config_buf)); - - Vfs::File_io_service::Read_result read_result; - - while ((read_result = - handle->fs().complete_read(handle, _config_buf, - sizeof(_config_buf), - out_count)) == - Vfs::File_io_service::READ_QUEUED) - _ep.wait_and_dispatch_one_io_signal(); - - if (read_result != Vfs::File_io_service::READ_OK) { - error("could not read '", path, "', err=", (int)read_result); - throw Nonexistent_subsystem_config(); - } - - try { - Genode::Xml_node subsystem_node(_config_buf, out_count); - fn(subsystem_node); - - } catch (Genode::Xml_node::Invalid_syntax) { - error("subsystem configuration has invalid syntax"); - throw Nonexistent_subsystem_config(); - - } catch (Genode::Xml_node::Nonexistent_sub_node) { - error("invalid subsystem configuration"); - throw Nonexistent_subsystem_config(); - } - } - - /** - * Call specified functor for each subsystem config - */ - template <typename FN> - void for_each_config(FN const &fn) - { - using Genode::error; - - Vfs::Vfs_handle *dir_handle; - - if (_fs.opendir(_subsystems_path(), false, &dir_handle, _alloc) != - Vfs::Directory_service::OPENDIR_OK) { - error("could not access directory '", _subsystems_path(), "'"); - return; - } - - /* iterate over the directory entries */ - for (unsigned i = 0;; i++) { - - Vfs::Directory_service::Dirent dirent; - - dir_handle->seek(i * sizeof(dirent)); - dir_handle->fs().queue_read(dir_handle, sizeof(dirent)); - - Vfs::file_size out_count; - while (dir_handle->fs().complete_read(dir_handle, - (char*)&dirent, - sizeof(dirent), - out_count) == - Vfs::File_io_service::READ_QUEUED) - _ep.wait_and_dispatch_one_io_signal(); - - if (dirent.type == Vfs::Directory_service::DIRENT_TYPE_END) { - _fs.close(dir_handle); - return; - } - - unsigned const subsystem_suffix = _subsystem_suffix(dirent); - - /* if file has a matching suffix, apply 'fn' */ - if (subsystem_suffix) { - - /* subsystem name is file name without the suffix */ - char name[sizeof(dirent.name)]; - Genode::strncpy(name, dirent.name, subsystem_suffix + 1); - - try { - for_config(name, fn); - } catch (Nonexistent_subsystem_config) { } - } - } - - _fs.close(dir_handle); - } -}; - -#endif /* _PROCESS_ARG_REGISTRY_H_ */ diff --git a/repos/os/src/app/cli_monitor/table.h b/repos/os/src/app/cli_monitor/table.h deleted file mode 100644 index 2ba99495f..000000000 --- a/repos/os/src/app/cli_monitor/table.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * \brief Utility for printing a table to the terminal - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-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 _TABLE_H_ -#define _TABLE_H_ - -#include <terminal_session/terminal_session.h> - -namespace Cli_monitor { template <typename TI> class Table; } - - -template <typename TI> -class Cli_monitor::Table -{ - private: - - static void _print_cell(TI &info, Terminal::Session &terminal, - typename TI::Column column, size_t column_size) - { - size_t const padding = column_size - info.len(column); - - if (!TI::left_aligned(column)) - tprint_padding(terminal, padding); - - info.print_cell(terminal, column); - - if (TI::left_aligned(column)) - tprint_padding(terminal, padding); - } - - /** - * Print centered title of table column - */ - static void _print_label(Terminal::Session &terminal, - typename TI::Column column, size_t column_size) - { - size_t const padding = column_size - strlen(TI::label(column)); - size_t const left_padding = padding / 2; - - tprint_padding(terminal, left_padding); - tprintf(terminal, "%s", TI::label(column)); - tprint_padding(terminal, padding - left_padding); - } - - public: - - static void print(Terminal::Session &terminal, TI info[], unsigned num_rows) - { - /* - * Determine formatting of table - */ - size_t column_size[TI::num_columns()]; - for (unsigned i = 0; i < TI::num_columns(); i++) - column_size[i] = strlen(TI::label((typename TI::Column)i)); - - for (unsigned i = 0; i < num_rows; i++) { - for (unsigned j = 0; j < TI::num_columns(); j++) - column_size[j] = max(column_size[j], - info[i].len((typename TI::Column)j)); - } - - /* - * Print table - */ - tprintf(terminal, " "); - for (unsigned j = 0; j < TI::num_columns(); j++) { - _print_label(terminal, (typename TI::Column)j, column_size[j]); - if (j < TI::num_columns() - 1) tprintf(terminal, " | "); - } - tprintf(terminal, "\n"); - - tprintf(terminal, " "); - for (unsigned j = 0; j < TI::num_columns(); j++) { - for (unsigned i = 0; i < column_size[j]; i++) - tprintf(terminal, "-"); - if (j < TI::num_columns() - 1) tprintf(terminal, "-+-"); - } - tprintf(terminal, "\n"); - - for (unsigned i = 0; i < num_rows; i++) { - tprintf(terminal, " "); - for (unsigned j = 0; j < TI::num_columns(); j++) { - _print_cell(info[i], terminal, (typename TI::Column)j, column_size[j]); - if (j < TI::num_columns() - 1) tprintf(terminal, " | "); - } - tprintf(terminal, "\n"); - } - } -}; - -#endif /* _TABLE_H_ */ diff --git a/repos/os/src/app/cli_monitor/target.mk b/repos/os/src/app/cli_monitor/target.mk deleted file mode 100644 index 41ee20a17..000000000 --- a/repos/os/src/app/cli_monitor/target.mk +++ /dev/null @@ -1,4 +0,0 @@ -TARGET = cli_monitor -SRC_CC = main.cc -LIBS = base vfs -INC_DIR += $(PRG_DIR) diff --git a/repos/os/src/app/cli_monitor/terminal_util.h b/repos/os/src/app/cli_monitor/terminal_util.h deleted file mode 100644 index 75413a144..000000000 --- a/repos/os/src/app/cli_monitor/terminal_util.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * \brief Convenience functions for operating on a terminal session - * \author Norman Feske - * \date 2013-03-19 - */ - -#ifndef _TERMINAL_UTIL_H_ -#define _TERMINAL_UTIL_H_ - -/* Genode includes */ -#include <terminal_session/terminal_session.h> -#include <base/snprintf.h> - -namespace Terminal { - - static inline void tprintf(Session &terminal, const char *format_args, ...) - { - using namespace Genode; - - enum { MAX_LEN = 256 }; - char buf[MAX_LEN]; - - /* process format string */ - va_list list; - va_start(list, format_args); - - String_console sc(buf, MAX_LEN); - sc.vprintf(format_args, list); - - va_end(list); - - terminal.write(buf, strlen(buf)); - } -} - -#endif /* _TERMINAL_UTIL_H_ */ diff --git a/repos/os/src/app/cli_monitor/yield_command.h b/repos/os/src/app/cli_monitor/yield_command.h deleted file mode 100644 index bc0e2ebdf..000000000 --- a/repos/os/src/app/cli_monitor/yield_command.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * \brief Yield command - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-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 _YIELD_COMMAND_H_ -#define _YIELD_COMMAND_H_ - -/* local includes */ -#include <child_registry.h> - -namespace Cli_monitor { struct Yield_command; } - - -struct Cli_monitor::Yield_command : Command -{ - Child_registry &_children; - - Parameter _ram_param { "--ram", Parameter::NUMBER, "RAM quota to free" }; - Parameter _greedy_param { "--greedy", Parameter::VOID, "withdraw yielded RAM quota" }; - - Yield_command(Child_registry &children) - : - Command("yield", "instruct subsystem to yield resources"), - _children(children) - { - add_parameter(_ram_param); - add_parameter(_greedy_param); - } - - void _for_each_argument(Argument_fn const &fn) const override - { - auto child_name_fn = [&] (Child_base::Name const &child_name) { - Argument arg(child_name.string(), ""); - fn(arg); - }; - - _children.for_each_child_name(child_name_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - char label[128]; - label[0] = 0; - if (cmd.argument(0, label, sizeof(label)) == false) { - tprintf(terminal, "Error: no subsystem name specified\n"); - return; - } - - Genode::Number_of_bytes ram = 0; - cmd.parameter("--ram", ram); - - bool const greedy = cmd.parameter_exists("--greedy"); - - /* lookup child by its unique name */ - Child *child = _children.first(); - for (; child; child = child->next()) - if (child->name() == label) - break; - - if (!child) { - tprintf(terminal, "Error: subsystem '%s' does not exist\n", label); - return; - } - - child->yield(ram, greedy); - - tprintf(terminal, "requesting '%s' to yield ", child->name().string()); - tprint_bytes(terminal, ram); - tprintf(terminal, "\n"); - } -}; - -#endif /* _YIELD_COMMAND_H_ */ diff --git a/repos/os/src/app/smbios_decoder/main.cc b/repos/os/src/app/smbios_decoder/main.cc index 795d8d4c3..00d252ce0 100644 --- a/repos/os/src/app/smbios_decoder/main.cc +++ b/repos/os/src/app/smbios_decoder/main.cc @@ -13,7 +13,7 @@ */ /* Genode includes */ -#include <os/smbios.h> +#include <smbios/smbios.h> #include <base/attached_rom_dataspace.h> #include <os/reporter.h> #include <base/component.h> diff --git a/repos/os/src/drivers/acpi/acpi.cc b/repos/os/src/drivers/acpi/acpi.cc index eb1e124b3..5e56c533f 100644 --- a/repos/os/src/drivers/acpi/acpi.cc +++ b/repos/os/src/drivers/acpi/acpi.cc @@ -470,15 +470,11 @@ class Table_wrapper Table_wrapper(Acpi::Memory &memory, addr_t base) : _base(base), _table(0) { - /* if table is on page boundary, map two pages, otherwise one page */ - size_t const map_size = 0x1000UL - _offset() < 8 ? 0x1000UL : 1UL; - /* make table header accessible */ - _table = reinterpret_cast<Generic *>(memory.phys_to_virt(base, map_size)); + _table = reinterpret_cast<Generic *>(memory.map_region(base, 8)); - /* table size is known now - make it complete accessible */ - if (_offset() + _table->size > 0x1000UL) - memory.phys_to_virt(base, _table->size); + /* table size is known now - make it completely accessible (in place) */ + memory.map_region(base, _table->size); memset(_name, 0, 5); memcpy(_name, _table->signature, 4); diff --git a/repos/os/src/drivers/acpi/memory.h b/repos/os/src/drivers/acpi/memory.h index 28efb10ad..e43403793 100644 --- a/repos/os/src/drivers/acpi/memory.h +++ b/repos/os/src/drivers/acpi/memory.h @@ -20,97 +20,183 @@ #include <rm_session/connection.h> #include <region_map/client.h> -namespace Acpi { class Memory; } +namespace Acpi { + using namespace Genode; + + class Memory; +} class Acpi::Memory { + public: + + struct Unsupported_range { }; + private: - class Io_mem : public Genode::List<Io_mem>::Element + /* + * We wrap the connection into Constructible to prevent a "accessible + * non-virtual destructor" compiler error with Allocator_avl_base::Block. + */ + struct Io_mem { - private: - Genode::Io_mem_connection _io_mem; + struct Region + { + addr_t _base; + size_t _size; - public: - Io_mem(Genode::Env &env, Genode::addr_t phys) - : _io_mem(env, phys, 0x1000UL) { } - - Genode::Io_mem_dataspace_capability dataspace() + static addr_t _base_align(addr_t base) { - return _io_mem.dataspace(); + return base & ~0xfffUL; } + + static addr_t _size_align(addr_t base, size_t size) + { + return align_addr(base + (size - 1) - _base_align(base), 12); + } + + Region(addr_t base, size_t size) + : + _base(_base_align(base)), + _size(_size_align(base, size)) + { } + + addr_t base() const { return _base; } + addr_t last() const { return _base + (_size - 1); } + size_t size() const { return _size; } + + bool contains(Region const &o) const + { + return o.base() >= base() && o.last() <= last(); + } + + void print(Output &o) const + { + Genode::print(o, Hex_range<addr_t>(_base, _size)); + } + } region; + + Constructible<Io_mem_connection> connection { }; + + Io_mem(Env &env, Region region) : region(region) + { + connection.construct(env, region.base(), region.size()); + } }; - Genode::Env &_env; - Genode::addr_t const ACPI_REGION_SIZE_LOG2; - Genode::Rm_connection _rm; - Genode::Region_map_client _rm_acpi; - Genode::addr_t const _acpi_base; - Genode::Allocator &_heap; - Genode::Allocator_avl _range; - Genode::List<Io_mem> _io_mem_list { }; + static constexpr unsigned long + ACPI_REGION_SIZE_LOG2 = 30, /* 1 GiB range */ + ACPI_REGION_SIZE = 1UL << ACPI_REGION_SIZE_LOG2; + + Env &_env; + Allocator &_heap; + + Rm_connection _rm { _env }; + Region_map_client _acpi_window { _rm.create(ACPI_REGION_SIZE) }; + addr_t const _acpi_base { _env.rm().attach(_acpi_window.dataspace()) }; + + Constructible<Io_mem::Region> _io_region { }; + + addr_t _acpi_ptr(addr_t base) const + { + /* virtual address inside the mapped ACPI window */ + return _acpi_base + (base - _io_region->base()); + } + + Allocator_avl_tpl<Io_mem> _range { &_heap }; public: - Memory(Genode::Env &env, Genode::Allocator &heap) - : - _env(env), - /* 1 GB range */ - ACPI_REGION_SIZE_LOG2(30), - _rm(env), - _rm_acpi(_rm.create(1UL << ACPI_REGION_SIZE_LOG2)), - _acpi_base(env.rm().attach(_rm_acpi.dataspace())), - _heap(heap), - _range(&_heap) + Memory(Env &env, Allocator &heap) : _env(env), _heap(heap) { - _range.add_range(0, 1UL << ACPI_REGION_SIZE_LOG2); + _range.add_range(0, ~0UL); } - Genode::addr_t phys_to_virt(Genode::addr_t const phys, Genode::addr_t const p_size) + addr_t map_region(addr_t const req_base, addr_t const req_size) { - using namespace Genode; + /* + * The first caller sets the upper physical bits of addresses and, + * thereby, determines the valid range of addresses. + */ - /* the first caller sets the upper physical bits of addresses */ - static addr_t const high = phys & _align_mask(ACPI_REGION_SIZE_LOG2); - - /* sanity check that physical address is in range we support */ - if ((phys & _align_mask(ACPI_REGION_SIZE_LOG2)) != high) { - addr_t const end = high + (1UL << ACPI_REGION_SIZE_LOG2) - 1; - error("acpi table out of range - ", Hex(phys), " " - "not in ", Hex_range<addr_t>(high, end - high)); - throw -1; + if (!_io_region.constructed()) { + _io_region.construct(req_base & _align_mask(ACPI_REGION_SIZE_LOG2), + ACPI_REGION_SIZE); } - addr_t const phys_aligned = phys & _align_mask(12); - addr_t const size_aligned = align_addr(p_size + (phys & _align_offset(12)), 12); + /* requested region of I/O memory */ + Io_mem::Region loop_region { req_base, req_size }; - for (addr_t size = 0; size < size_aligned; size += 0x1000UL) { - addr_t const low = (phys_aligned + size) & - _align_offset(ACPI_REGION_SIZE_LOG2); - if (!_range.alloc_addr(0x1000UL, low).ok()) - continue; - - /* allocate acpi page as io memory */ - Io_mem *mem = new (_heap) Io_mem(_env, phys_aligned + size); - /* attach acpi page to this process */ - _rm_acpi.attach_at(mem->dataspace(), low, 0x1000UL); - /* add to list to free when parsing acpi table is done */ - _io_mem_list.insert(mem); + /* check that physical region fits into supported range */ + if (!_io_region->contains(loop_region)) { + error("acpi table out of range - ", loop_region, " not in ", *_io_region); + throw Unsupported_range(); } - return _acpi_base + (phys & _align_offset(ACPI_REGION_SIZE_LOG2)); + /* early return if the region is already mapped */ + if (Io_mem *m = _range.metadata((void *)req_base)) { + if (m->region.contains(loop_region)) { + return _acpi_ptr(req_base); + } + } + + /* + * We iterate over the requested region looking for collisions with + * existing mappings. On a collision, we extend the requested range + * to comprise also the existing mapping and destroy the mapping. + * Finally, we request the compound region as on I/O memory + * mapping. + * + * Note, this approach unfortunately does not merge consecutive + * regions. + */ + + addr_t loop_offset = 0; + while (loop_offset < loop_region.size()) { + void * const addr = (void *)(loop_region.base() + loop_offset); + + if (Io_mem *m = _range.metadata(addr)) { + addr_t const region_base = m->region.base(); + addr_t const region_size = m->region.size(); + addr_t const compound_base = min(loop_region.base(), region_base); + addr_t const compound_end = max(loop_region.base() + loop_region.size(), + region_base + region_size); + + m->~Io_mem(); + _range.free((void *)region_base); + + /* now start over */ + loop_region = Io_mem::Region(compound_base, compound_end - compound_base); + loop_offset = 0; + } + + loop_offset += 0x1000; + } + + /* allocate ACPI range as I/O memory */ + _range.alloc_addr(loop_region.size(), loop_region.base()); + _range.construct_metadata((void *)loop_region.base(), _env, loop_region); + + /* + * We attach the I/O memory dataspace into a virtual-memory window, + * which starts at _io_region.base(). Therefore, the attachment + * address is the offset of loop_region.base() from + * _io_region.base(). + */ + _acpi_window.attach_at( + _range.metadata((void *)loop_region.base())->connection->dataspace(), + loop_region.base() - _io_region->base(), loop_region.size()); + + return _acpi_ptr(req_base); } void free_io_memory() { - while (Io_mem * io_mem = _io_mem_list.first()) { - _io_mem_list.remove(io_mem); - destroy(_heap, io_mem); - } - - Genode::addr_t out_addr; - while (_range.any_block_addr(&out_addr)) + addr_t out_addr = 0; + while (_range.any_block_addr(&out_addr)) { + _range.metadata((void *)out_addr)->~Io_mem(); _range.free((void *)out_addr); + } } }; diff --git a/repos/os/src/drivers/acpi/smbios_table_reporter.cc b/repos/os/src/drivers/acpi/smbios_table_reporter.cc index 05702cd92..2658d56a7 100644 --- a/repos/os/src/drivers/acpi/smbios_table_reporter.cc +++ b/repos/os/src/drivers/acpi/smbios_table_reporter.cc @@ -18,7 +18,7 @@ /* Genode includes */ #include <base/attached_io_mem_dataspace.h> #include <base/attached_rom_dataspace.h> -#include <os/smbios.h> +#include <smbios/smbios.h> #include <util/fifo.h> using namespace Genode; diff --git a/repos/os/src/drivers/ahci/ata_driver.h b/repos/os/src/drivers/ahci/ata_driver.h index b65a77a97..538ee9e4b 100644 --- a/repos/os/src/drivers/ahci/ata_driver.h +++ b/repos/os/src/drivers/ahci/ata_driver.h @@ -138,6 +138,8 @@ struct Ncq_command : Io_command unsigned slot) override { table.fis.fpdma(read, block_number, count, slot); + /* ensure that 'Cmd::St' is 1 before writing 'Sact' */ + port.start(); /* set pending */ port.write<Port::Sact>(1U << slot); } diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index ad272cefd..cbb82fd40 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -170,7 +170,8 @@ struct Igd::Device */ _pci.upgrade_ram(size); try { - return _pci.alloc_dma_buffer(size); + return _pci.with_upgrade([&] () { + return _pci.alloc_dma_buffer(size); }); } catch (Platform::Out_of_ram) { throw Out_of_ram(); } @@ -1733,7 +1734,7 @@ class Gpu::Root : public Gpu::Root_component session_diag_from_args(args), _env.rm(), *md_alloc(), ram_quota, *_device); - } catch (...) { throw Genode::Service_denied(); } + } catch (...) { throw; } } void _upgrade_session(Session_component *s, char const *args) override diff --git a/repos/os/src/drivers/nic/lan9118/main.cc b/repos/os/src/drivers/nic/lan9118/main.cc index ee1bfc1f6..91a4d9cec 100644 --- a/repos/os/src/drivers/nic/lan9118/main.cc +++ b/repos/os/src/drivers/nic/lan9118/main.cc @@ -63,19 +63,14 @@ class Root : public Genode::Root_component<Lan9118, Genode::Single_client> size_t tx_buf_size = Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); size_t rx_buf_size = Arg_string::find_arg(args, "rx_buf_size").ulong_value(0); - /* deplete ram quota by the memory needed for the session structure */ - size_t session_size = max(4096UL, (unsigned long)sizeof(Lan9118)); - if (ram_quota < session_size) - throw Genode::Insufficient_ram_quota(); - /* * Check if donated ram quota suffices for both communication * buffers and check for overflow */ if (tx_buf_size + rx_buf_size < tx_buf_size || - tx_buf_size + rx_buf_size > ram_quota - session_size) { + tx_buf_size + rx_buf_size > ram_quota) { error("insufficient 'ram_quota', got ", ram_quota, ", " - "need ", tx_buf_size + rx_buf_size + session_size); + "need ", tx_buf_size + rx_buf_size); throw Genode::Insufficient_ram_quota(); } diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device.cc b/repos/os/src/drivers/platform/spec/x86/pci_device.cc index aaed6007b..cb2e1a4b7 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device.cc +++ b/repos/os/src/drivers/platform/spec/x86/pci_device.cc @@ -13,18 +13,19 @@ #include "pci_session_component.h" #include "pci_device_component.h" -Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::uint8_t v_id) +Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::uint8_t const v_id) { - Genode::uint8_t max = sizeof(_io_port_conn) / sizeof(_io_port_conn[0]); - Genode::uint8_t i = 0, r_id = 0; + Genode::uint8_t const max = sizeof(_io_port_conn) / sizeof(_io_port_conn[0]); + Genode::uint8_t r_id = 0; - for (Resource res = resource(0); i < max; i++, res = resource(i)) - { - if (res.type() != Resource::IO) + for (unsigned i = 0; i < max; ++i) { + Pci::Resource res = _device_config.resource(i); + + if (!res.valid() || res.mem()) continue; if (v_id != r_id) { - r_id ++; + ++r_id; continue; } @@ -48,15 +49,16 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin Genode::size_t const size) { Genode::uint8_t max = sizeof(_io_mem) / sizeof(_io_mem[0]); - Genode::uint8_t i = 0, r_id = 0; + Genode::uint8_t r_id = 0; - for (Resource res = resource(0); i < max; i++, res = resource(i)) - { - if (res.type() != Resource::MEMORY) + for (unsigned i = 0; i < max; ++i) { + Pci::Resource res = _device_config.resource(i); + + if (!res.valid() || !res.mem()) continue; if (v_id != r_id) { - r_id ++; + ++r_id; continue; } @@ -66,6 +68,14 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin if (offset >= res.size() || offset > res.size() - res_size) return Genode::Io_mem_session_capability(); + /* error if MEM64 resource base address above 4G on 32-bit */ + if (res.base() > ~(addr_t)0) { + Genode::error("request for MEM64 resource of ", _device_config, + " at ", Genode::Hex(res.base()), + " not supported on 32-bit system"); + return Genode::Io_mem_session_capability(); + } + try { bool const wc = caching == Genode::Cache_attribute::WRITE_COMBINED; Io_mem * io_mem = new (_slab_iomem) Io_mem(_env, diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h index f2386b5ac..d7645891a 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h @@ -89,8 +89,10 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>, char _mem_irq_component[sizeof(Irq_session_component)]; - Genode::Io_port_connection *_io_port_conn [Device::NUM_RESOURCES]; - Genode::List<Io_mem> _io_mem [Device::NUM_RESOURCES]; + Genode::Io_port_connection *_io_port_conn[Device::NUM_RESOURCES]; + + /* list of requested resource chunks per BAR */ + Genode::List<Io_mem> _io_mem[Device::NUM_RESOURCES]; struct Status : Genode::Register<8> { struct Capabilities : Bitfield<4,1> { }; @@ -189,7 +191,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>, public: /** - * Constructor + * Constructor for PCI devices */ Device_component(Genode::Env &env, Device_config device_config, Genode::addr_t addr, @@ -263,7 +265,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>, ** Methods used solely by pci session ** ****************************************/ - Device_config config() const { return _device_config; } + Device_config device_config() const { return _device_config; } Genode::addr_t config_space() const { return _config_space; } /************************** @@ -290,7 +292,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>, if (!_device_config.valid()) return Resource(0, 0); - return _device_config.resource(resource_id); + return _device_config.resource(resource_id).api_resource(); } unsigned config_read(unsigned char address, Access_size size) override diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_config.h b/repos/os/src/drivers/platform/spec/x86/pci_device_config.h index 8d42953f9..12f55e2bb 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_config.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_config.h @@ -16,8 +16,81 @@ #include <base/output.h> #include <platform_device/platform_device.h> +#include <util/register.h> #include "pci_config_access.h" + +namespace Platform { namespace Pci { + + struct Resource; +} } + + +class Platform::Pci::Resource +{ + public: + + struct Bar : Genode::Register<32> + { + struct Space : Bitfield<0,1> { enum { MEM = 0, PORT = 1 }; }; + + struct Mem_type : Bitfield<1,2> { enum { MEM32 = 0, MEM64 = 2 }; }; + struct Mem_prefetch : Bitfield<3,1> { }; + struct Mem_address_mask : Bitfield<4,28> { }; + struct Port_address_mask : Bitfield<2,14> { }; + + static bool mem(access_t r) { return Space::get(r) == Space::MEM; } + static bool mem64(access_t r) { return mem(r) + && Mem_type::get(r) == Mem_type::MEM64; } + static uint64_t mem_address(access_t r0, uint64_t r1) { return (r1 << 32) | Mem_address_mask::masked(r0); } + static uint64_t mem_size(access_t r0, uint64_t r1) { return ~mem_address(r0, r1) + 1; } + + static uint16_t port_address(access_t r) { return Port_address_mask::masked(r); } + static uint16_t port_size(access_t r) { return ~port_address(r) + 1; } + }; + + private: + + uint32_t _bar[2] { 0, 0 }; /* contains two consecutive BARs for MEM64 */ + uint64_t _size { 0 }; + + public: + + /* invalid resource */ + Resource() { } + + /* PORT or MEM32 resource */ + Resource(uint32_t bar, uint32_t size) + : _bar{bar, 0}, _size(mem() ? Bar::mem_size(size, ~0) : Bar::port_size(size)) + { } + + /* MEM64 resource */ + Resource(uint32_t bar0, uint32_t size0, uint32_t bar1, uint32_t size1) + : _bar{bar0, bar1}, _size(Bar::mem_size(size0, size1)) + { } + + bool valid() const { return !!_bar[0]; } /* no base address -> invalid */ + bool mem() const { return Bar::mem(_bar[0]); } + uint64_t base() const { return mem() ? Bar::mem_address(_bar[0], _bar[1]) + : Bar::port_address(_bar[0]); } + uint64_t size() const { return _size; } + + Platform::Device::Resource api_resource() + { + /* + * The API type limits to 32-bit currently (defined in + * spec/x86/platform_device/platform_device.h) + */ + return Device::Resource((unsigned)_bar[0], (unsigned)_size); + } + + void print(Genode::Output &out) const + { + Genode::print(out, Genode::Hex_range(base(), size())); + } +}; + + namespace Platform { class Device_config @@ -44,7 +117,7 @@ namespace Platform { HEADER_CARD_BUS = 2 }; - Device::Resource _resource[Device::NUM_RESOURCES]; + Platform::Pci::Resource _resource[Device::NUM_RESOURCES]; bool _resource_id_is_valid(int resource_id) { @@ -111,45 +184,62 @@ namespace Platform { return; } - for (int i = 0; _resource_id_is_valid(i); i++) { + /* + * We iterate over all BARs but check for 64-bit memory + * resources, which are stored in two consecutive BARs. The + * MEM64 information is stored in the first resource entry and + * the second resource is marked invalid. + */ + int i = 0; + while (_resource_id_is_valid(i)) { + + using Pci::Resource; /* index of base-address register in configuration space */ - unsigned bar_idx = 0x10 + 4 * i; + unsigned const bar_idx = 0x10 + 4 * i; - /* read original base-address register value */ - unsigned orig_bar = pci_config->read(bus, device, function, bar_idx, Device::ACCESS_32BIT); + /* read base-address register value */ + unsigned const bar_value = + pci_config->read(bus, device, function, bar_idx, Device::ACCESS_32BIT); - /* check for invalid resource */ - if (orig_bar == (unsigned)~0) { - _resource[i] = Device::Resource(0, 0); + /* skip invalid resource BARs */ + if (bar_value == ~0U || bar_value == 0U) { + _resource[i] = Resource(); + ++i; continue; } /* - * Determine resource size by writing a magic value (all bits set) - * to the base-address register. In response, the device clears a number - * of lowest-significant bits corresponding to the resource size. - * Finally, we write back the original value as assigned by the BIOS. + * Determine resource size by writing a magic value (all + * bits set) to the base-address register. In response, the + * device clears a number of lowest-significant bits + * corresponding to the resource size. Finally, we write + * back the bar-address value as assigned by the BIOS. */ pci_config->write(bus, device, function, bar_idx, ~0, Device::ACCESS_32BIT); - unsigned bar = pci_config->read(bus, device, function, bar_idx, Device::ACCESS_32BIT); - pci_config->write(bus, device, function, bar_idx, orig_bar, Device::ACCESS_32BIT); + unsigned const bar_size = pci_config->read(bus, device, function, bar_idx, Device::ACCESS_32BIT); + pci_config->write(bus, device, function, bar_idx, bar_value, Device::ACCESS_32BIT); - /* - * Scan base-address-register value for the lowest set bit but - * ignore the lower bits that are used to describe the resource type. - * I/O resources use the lowest 3 bits, memory resources use the - * lowest four bits for the resource description. - */ - unsigned start = (bar & 1) ? 3 : 4; - unsigned size = 1 << start; - for (unsigned bit = start; bit < 32; bit++, size += size) + if (!Resource::Bar::mem64(bar_value)) { + _resource[i] = Resource(bar_value, bar_size); + ++i; + } else { + /* also consume next BAR for MEM64 */ + unsigned const bar2_idx = bar_idx + 4; + unsigned const bar2_value = + pci_config->read(bus, device, function, bar2_idx, Device::ACCESS_32BIT); + pci_config->write(bus, device, function, bar2_idx, ~0, Device::ACCESS_32BIT); + unsigned const bar2_size = + pci_config->read(bus, device, function, bar2_idx, Device::ACCESS_32BIT); + pci_config->write(bus, device, function, bar2_idx, bar2_value, Device::ACCESS_32BIT); - /* stop at the lowest-significant set bit */ - if (bar & (1 << bit)) - break; - - _resource[i] = Device::Resource(orig_bar, size); + /* combine into first resource and mark second as invalid */ + _resource[i] = Resource(bar_value, bar_size, + bar2_value, bar2_size); + ++i; + _resource[i] = Resource(); + ++i; + } } } @@ -192,11 +282,11 @@ namespace Platform { /** * Return resource description by resource ID */ - Device::Resource resource(int resource_id) + Platform::Pci::Resource resource(int resource_id) { /* return invalid resource if sanity check fails */ if (!_resource_id_is_valid(resource_id)) - return Device::Resource(0, 0); + return Platform::Pci::Resource(); return _resource[resource_id]; } diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index 2a31dfa04..6c4376b9e 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -653,7 +653,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session> int bus = 0, device = 0, function = -1; if (prev) { - Device_config config = prev->config(); + Device_config config = prev->device_config(); bus = config.bus_number(); device = config.device_number(); function = config.function_number(); @@ -736,9 +736,9 @@ class Platform::Session_component : public Genode::Rpc_object<Session> if (!device) return; - unsigned const bus = device->config().bus_number(); - unsigned const dev = device->config().device_number(); - unsigned const func = device->config().function_number(); + unsigned const bus = device->device_config().bus_number(); + unsigned const dev = device->device_config().device_number(); + unsigned const func = device->device_config().function_number(); if (bdf_in_use.get(Device_config::MAX_BUSES * bus + Device_config::MAX_DEVICES * dev + @@ -753,7 +753,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session> /* lookup device component for previous device */ _env.ep().rpc_ep().apply(device_cap, lambda); - if (device && device->config().valid()) + if (device && device->device_config().valid()) destroy(_md_alloc, device); } @@ -765,9 +765,9 @@ class Platform::Session_component : public Genode::Rpc_object<Session> return; try { - addr_t const function = device->config().bus_number() * 32 * 8 + - device->config().device_number() * 8 + - device->config().function_number(); + addr_t const function = device->device_config().bus_number() * 32 * 8 + + device->device_config().device_number() * 8 + + device->device_config().function_number(); addr_t const base_ecam = Dataspace_client(_pciconf.cap()).phys_addr(); addr_t const base_offset = 0x1000UL * function; @@ -775,12 +775,12 @@ class Platform::Session_component : public Genode::Rpc_object<Session> throw 1; for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) { - Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->config()); + Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->device_config()); if (rmrr_cap.valid()) _device_pd.attach_dma_mem(rmrr_cap); } - _device_pd.assign_pci(_pciconf.cap(), base_offset, device->config().bdf()); + _device_pd.assign_pci(_pciconf.cap(), base_offset, device->device_config().bdf()); } catch (...) { Genode::error("assignment to device pd or of RMRR region failed"); diff --git a/repos/os/src/lib/vfs/block_file_system.h b/repos/os/src/lib/vfs/block_file_system.h index df8417cc8..ff485e77b 100644 --- a/repos/os/src/lib/vfs/block_file_system.h +++ b/repos/os/src/lib/vfs/block_file_system.h @@ -326,7 +326,8 @@ class Vfs::Block_file_system : public Single_file_system Block_file_system(Vfs::Env &env, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_BLOCK_DEVICE, name(), config), + Single_file_system(Node_type::CONTINUOUS_FILE, name(), + Node_rwx::rw(), config), _env(env), _label(config.attribute_value("label", Label())), _block_buffer(0), diff --git a/repos/os/src/lib/vfs/file_system_factory.cc b/repos/os/src/lib/vfs/file_system_factory.cc index 151e23be5..f52aca0df 100644 --- a/repos/os/src/lib/vfs/file_system_factory.cc +++ b/repos/os/src/lib/vfs/file_system_factory.cc @@ -221,7 +221,7 @@ Vfs::Global_file_system_factory::Global_file_system_factory(Genode::Allocator &a { _add_builtin_fs<Vfs::Tar_file_system>(); _add_builtin_fs<Vfs::Fs_file_system>(); - _add_builtin_fs<Vfs::Terminal_file_system>(); + _add_builtin_fs<Vfs::Terminal_file_system::Compound_file_system>(); _add_builtin_fs<Vfs::Null_file_system>(); _add_builtin_fs<Vfs::Zero_file_system>(); _add_builtin_fs<Vfs::Block_file_system>(); diff --git a/repos/os/src/lib/vfs/fs_file_system.h b/repos/os/src/lib/vfs/fs_file_system.h index 010f7c4c4..4c61619a5 100644 --- a/repos/os/src/lib/vfs/fs_file_system.h +++ b/repos/os/src/lib/vfs/fs_file_system.h @@ -69,6 +69,50 @@ class Vfs::Fs_file_system : public File_system struct Fs_vfs_handle; typedef Genode::Fifo<Fs_vfs_handle> Fs_vfs_handle_queue; + /** + * Convert 'File_system::Node_type' to 'Dirent_type' + */ + static Dirent_type _dirent_type(::File_system::Node_type type) + { + using ::File_system::Node_type; + + switch (type) { + case Node_type::DIRECTORY: return Dirent_type::DIRECTORY; + case Node_type::CONTINUOUS_FILE: return Dirent_type::CONTINUOUS_FILE; + case Node_type::TRANSACTIONAL_FILE: return Dirent_type::TRANSACTIONAL_FILE; + case Node_type::SYMLINK: return Dirent_type::SYMLINK; + } + return Dirent_type::END; + } + + /** + * Convert 'File_system::Node_type' to 'Vfs::Node_type' + */ + static Node_type _node_type(::File_system::Node_type type) + { + using Type = ::File_system::Node_type; + + switch (type) { + case Type::DIRECTORY: return Node_type::DIRECTORY; + case Type::CONTINUOUS_FILE: return Node_type::CONTINUOUS_FILE; + case Type::TRANSACTIONAL_FILE: return Node_type::TRANSACTIONAL_FILE; + case Type::SYMLINK: return Node_type::SYMLINK; + } + + Genode::error("invalid File_system::Node_type"); + return Node_type::CONTINUOUS_FILE; + } + + /** + * Convert 'File_system::Node_rwx' to 'Vfs::Node_rwx' + */ + static Node_rwx _node_rwx(::File_system::Node_rwx rwx) + { + return { .readable = rwx.readable, + .writeable = rwx.writeable, + .executable = rwx.executable }; + } + struct Fs_vfs_handle : Vfs_handle, private ::File_system::Node, private Handle_space::Element, @@ -225,6 +269,35 @@ class Vfs::Fs_file_system : public File_system return result; } + + bool update_modification_timestamp(Vfs::Timestamp time) + { + ::File_system::Session::Tx::Source &source = *_fs.tx(); + using ::File_system::Packet_descriptor; + + if (!source.ready_to_submit()) { + Genode::error(__func__, ":", __LINE__, " Insufficient_buffer"); + return false; + } + + try { + Packet_descriptor p(source.alloc_packet(0), + file_handle(), + Packet_descriptor::WRITE_TIMESTAMP, + ::File_system::Timestamp { .value = time.value }); + + /* pass packet to server side */ + source.submit_packet(p); + } catch (::File_system::Session::Tx::Source::Packet_alloc_failed) { + Genode::error(__func__, ":", __LINE__, " Insufficient_buffer"); + return false; + } catch (...) { + Genode::error("unhandled exception"); + return false; + } + + return true; + } }; struct Fs_vfs_file_handle : Fs_vfs_handle @@ -266,41 +339,38 @@ class Vfs::Fs_file_system : public File_system using ::File_system::Directory_entry; - Directory_entry entry; - file_size entry_out_count; + Directory_entry entry { }; + file_size entry_out_count = 0; - Read_result read_result = + Read_result const read_result = _complete_read(&entry, DIRENT_SIZE, entry_out_count); if (read_result != READ_OK) return read_result; - Dirent *dirent = (Dirent*)dst; + entry.sanitize(); + + Dirent &dirent = *(Dirent*)dst; if (entry_out_count < DIRENT_SIZE) { + /* no entry found for the given index, or error */ - *dirent = Dirent(); + dirent = Dirent { + .fileno = 0, + .type = Dirent_type::END, + .rwx = { }, + .name = { } + }; out_count = sizeof(Dirent); return READ_OK; } - /* - * The default value has no meaning because the switch below - * assigns a value in each possible branch. But it is needed to - * keep the compiler happy. - */ - Dirent_type type = DIRENT_TYPE_END; - - /* copy-out payload into destination buffer */ - switch (entry.type) { - case Directory_entry::TYPE_DIRECTORY: type = DIRENT_TYPE_DIRECTORY; break; - case Directory_entry::TYPE_FILE: type = DIRENT_TYPE_FILE; break; - case Directory_entry::TYPE_SYMLINK: type = DIRENT_TYPE_SYMLINK; break; - } - - dirent->fileno = entry.inode; - dirent->type = type; - strncpy(dirent->name, entry.name, sizeof(dirent->name)); + dirent = Dirent { + .fileno = entry.inode, + .type = _dirent_type(entry.type), + .rwx = _node_rwx(entry.rwx), + .name = { entry.name.buf } + }; out_count = sizeof(Dirent); @@ -518,6 +588,10 @@ class Vfs::Fs_file_system : public File_system case Packet_descriptor::CONTENT_CHANGED: /* previously handled */ break; + + case Packet_descriptor::WRITE_TIMESTAMP: + /* previously handled */ + break; } }; @@ -536,6 +610,11 @@ class Vfs::Fs_file_system : public File_system Lock::Guard guard(_lock); source.release_packet(packet); } + + if (packet.operation() == Packet_descriptor::WRITE_TIMESTAMP) { + Lock::Guard guard(_lock); + source.release_packet(packet); + } } } @@ -610,19 +689,13 @@ class Vfs::Fs_file_system : public File_system out = Stat(); - out.size = status.size; - out.mode = STAT_MODE_FILE | 0777; - - if (status.symlink()) - out.mode = STAT_MODE_SYMLINK | 0777; - - if (status.directory()) - out.mode = STAT_MODE_DIRECTORY | 0777; - - out.uid = 0; - out.gid = 0; - out.inode = status.inode; + out.size = status.size; + out.type = _node_type(status.type); + out.rwx = _node_rwx(status.rwx); + out.inode = status.inode; out.device = (Genode::addr_t)this; + out.modification_time.value = status.modification_time.value; + return STAT_OK; } @@ -1016,6 +1089,15 @@ class Vfs::Fs_file_system : public File_system return handle->complete_sync(); } + + bool update_modification_timestamp(Vfs_handle *vfs_handle, Vfs::Timestamp time) override + { + Lock::Guard guard(_lock); + + Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle); + + return handle->update_modification_timestamp(time); + } }; #endif /* _INCLUDE__VFS__FS_FILE_SYSTEM_H_ */ diff --git a/repos/os/src/lib/vfs/inline_file_system.h b/repos/os/src/lib/vfs/inline_file_system.h index 6554c0beb..ae541bf68 100644 --- a/repos/os/src/lib/vfs/inline_file_system.h +++ b/repos/os/src/lib/vfs/inline_file_system.h @@ -103,7 +103,9 @@ class Vfs::Inline_file_system : public Single_file_system */ Inline_file_system(Vfs::Env&, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_FILE, name(), config), _node(config) + Single_file_system(Node_type::CONTINUOUS_FILE, name(), + Node_rwx::rx(), config), + _node(config) { } static char const *name() { return "inline"; } @@ -140,9 +142,11 @@ class Vfs::Inline_file_system : public Single_file_system Stat_result stat(char const *path, Stat &out) override { - Stat_result result = Single_file_system::stat(path, out); + Stat_result const result = Single_file_system::stat(path, out); + _node.with_raw_content([&] (char const *, Genode::size_t size) { out.size = size; }); + return result; } }; diff --git a/repos/os/src/lib/vfs/log_file_system.h b/repos/os/src/lib/vfs/log_file_system.h index a9e9c46ef..757290fbf 100644 --- a/repos/os/src/lib/vfs/log_file_system.h +++ b/repos/os/src/lib/vfs/log_file_system.h @@ -141,7 +141,8 @@ class Vfs::Log_file_system : public Single_file_system Log_file_system(Vfs::Env &env, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config), + Single_file_system(Node_type::CONTINUOUS_FILE, name(), + Node_rwx::ro(), config), _label(config.attribute_value("label", Label())), _log(_log_session(env.env())) { } diff --git a/repos/os/src/lib/vfs/null_file_system.h b/repos/os/src/lib/vfs/null_file_system.h index e9ddd1505..fd790c214 100644 --- a/repos/os/src/lib/vfs/null_file_system.h +++ b/repos/os/src/lib/vfs/null_file_system.h @@ -24,7 +24,8 @@ struct Vfs::Null_file_system : Single_file_system { Null_file_system(Vfs::Env&, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config) + Single_file_system(Node_type::CONTINUOUS_FILE, name(), + Node_rwx::rw(), config) { } static char const *name() { return "null"; } diff --git a/repos/os/src/lib/vfs/ram_file_system.h b/repos/os/src/lib/vfs/ram_file_system.h index 6e1a85e85..b9aa602f1 100644 --- a/repos/os/src/lib/vfs/ram_file_system.h +++ b/repos/os/src/lib/vfs/ram_file_system.h @@ -119,6 +119,8 @@ class Vfs_ram::Node : private Genode::Avl_node<Node>, private Genode::Lock return ++inode_count; } + Vfs::Timestamp _modification_time { Vfs::Timestamp::INVALID }; + public: using Lock::lock; @@ -127,7 +129,10 @@ class Vfs_ram::Node : private Genode::Avl_node<Node>, private Genode::Lock unsigned inode; Node(char const *node_name) - : inode(_unique_inode()) { name(node_name); } + : inode(_unique_inode()) + { + name(node_name); + } virtual ~Node() { } @@ -156,6 +161,21 @@ class Vfs_ram::Node : private Genode::Avl_node<Node>, private Genode::Lock void unlink() { inode = 0; } bool unlinked() const { return inode == 0; } + bool update_modification_timestamp(Vfs::Timestamp time) + { + _modification_time = time; + return true; + } + + Vfs::Timestamp modification_time() const { return _modification_time; } + + Vfs::Node_rwx rwx() const + { + return { .readable = true, + .writeable = true, + .executable = true }; + } + virtual size_t read(char*, size_t, file_size) { Genode::error("Vfs_ram::Node::read() called"); @@ -437,39 +457,43 @@ class Vfs_ram::Directory : public Vfs_ram::Node file_offset index = seek_offset / sizeof(Dirent); - Dirent *dirent = (Dirent*)dst; - *dirent = Dirent(); + Dirent &dirent = *(Dirent*)dst; + + using Dirent_type = Vfs::Directory_service::Dirent_type; + out_count = sizeof(Dirent); - Node *node = _entries.first(); - if (node) node = node->index(index); - if (!node) { - dirent->type = Directory_service::DIRENT_TYPE_END; + Node *node_ptr = _entries.first(); + if (node_ptr) node_ptr = node_ptr->index(index); + if (!node_ptr) { + dirent.type = Dirent_type::END; return Vfs::File_io_service::READ_OK; } - dirent->fileno = node->inode; - strncpy(dirent->name, node->name(), sizeof(dirent->name)); + Node &node = *node_ptr; - File *file = dynamic_cast<File *>(node); - if (file) { - dirent->type = Directory_service::DIRENT_TYPE_FILE; - return Vfs::File_io_service::READ_OK; - } + auto dirent_type = [&] () + { + if (dynamic_cast<File *>(node_ptr)) return Dirent_type::CONTINUOUS_FILE; + if (dynamic_cast<Directory *>(node_ptr)) return Dirent_type::DIRECTORY; + if (dynamic_cast<Symlink *>(node_ptr)) return Dirent_type::SYMLINK; - Directory *dir = dynamic_cast<Directory *>(node); - if (dir) { - dirent->type = Directory_service::DIRENT_TYPE_DIRECTORY; - return Vfs::File_io_service::READ_OK; - } + return Dirent_type::END; + }; - Symlink *symlink = dynamic_cast<Symlink *>(node); - if (symlink) { - dirent->type = Directory_service::DIRENT_TYPE_SYMLINK; - return Vfs::File_io_service::READ_OK; - } + Dirent_type const type = dirent_type(); - return Vfs::File_io_service::READ_ERR_INVALID; + if (type == Dirent_type::END) + return Vfs::File_io_service::READ_ERR_INVALID; + + dirent = { + .fileno = node.inode, + .type = type, + .rwx = node.rwx(), + .name = { node.name() } + }; + + return Vfs::File_io_service::READ_OK; } }; @@ -767,34 +791,31 @@ class Vfs::Ram_file_system : public Vfs::File_system { using namespace Vfs_ram; - Node *node = lookup(path); - if (!node) return STAT_ERR_NO_ENTRY; - Node::Guard guard(node); + Node *node_ptr = lookup(path); + if (!node_ptr) return STAT_ERR_NO_ENTRY; - stat.size = node->length(); - stat.inode = node->inode; - stat.device = (Genode::addr_t)this; + Node::Guard guard(node_ptr); - File *file = dynamic_cast<File *>(node); - if (file) { - stat.mode = STAT_MODE_FILE | 0777; - return STAT_OK; - } + Node &node = *node_ptr; - Directory *dir = dynamic_cast<Directory *>(node); - if (dir) { - stat.mode = STAT_MODE_DIRECTORY | 0777; - return STAT_OK; - } + auto node_type = [&] () + { + if (dynamic_cast<Directory *>(node_ptr)) return Node_type::DIRECTORY; + if (dynamic_cast<Symlink *>(node_ptr)) return Node_type::SYMLINK; - Symlink *symlink = dynamic_cast<Symlink *>(node); - if (symlink) { - stat.mode = STAT_MODE_SYMLINK | 0777; - return STAT_OK; - } + return Node_type::CONTINUOUS_FILE; + }; - /* this should never happen */ - return STAT_ERR_NO_ENTRY; + stat = { + .size = node.length(), + .type = node_type(), + .rwx = node.rwx(), + .inode = node.inode, + .device = (Genode::addr_t)this, + .modification_time = node.modification_time() + }; + + return STAT_OK; } Rename_result rename(char const *from, char const *to) override @@ -1004,6 +1025,19 @@ class Vfs::Ram_file_system : public Vfs::File_system return SYNC_OK; } + bool update_modification_timestamp(Vfs_handle *vfs_handle, Vfs::Timestamp time) override + { + if ((vfs_handle->status_flags() & OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY) + return false; + + Vfs_ram::Io_handle *handle = + static_cast<Vfs_ram::Io_handle *>(vfs_handle); + handle->modifying = true; + + Vfs_ram::Node::Guard guard(&handle->node); + return handle->node.update_modification_timestamp(time); + } + /*************************** ** File_system interface ** ***************************/ diff --git a/repos/os/src/lib/vfs/rom_file_system.h b/repos/os/src/lib/vfs/rom_file_system.h index 9ede4e7a3..50496fd54 100644 --- a/repos/os/src/lib/vfs/rom_file_system.h +++ b/repos/os/src/lib/vfs/rom_file_system.h @@ -107,7 +107,8 @@ class Vfs::Rom_file_system : public Single_file_system Rom_file_system(Vfs::Env &env, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_FILE, name(), config), + Single_file_system(Node_type::CONTINUOUS_FILE, name(), + Node_rwx::ro(), config), /* use 'label' attribute if present, fall back to 'name' if not */ _label(config.attribute_value("label", @@ -161,10 +162,12 @@ class Vfs::Rom_file_system : public Single_file_system * found a file), obtain the size of the most current ROM module * version. */ - if (out.mode == STAT_MODE_FILE) { + if (out.type == Node_type::CONTINUOUS_FILE) { _rom.update(); out.size = _rom.valid() ? _rom.size() : 0; - out.mode |= 0555; + out.rwx = { .readable = true, + .writeable = false, + .executable = true }; } return result; diff --git a/repos/os/src/lib/vfs/rtc_file_system.h b/repos/os/src/lib/vfs/rtc_file_system.h index da7db4e63..c7db29acc 100644 --- a/repos/os/src/lib/vfs/rtc_file_system.h +++ b/repos/os/src/lib/vfs/rtc_file_system.h @@ -103,7 +103,8 @@ class Vfs::Rtc_file_system : public Single_file_system Rtc_file_system(Vfs::Env &env, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config), + Single_file_system(Node_type::TRANSACTIONAL_FILE, name(), + Node_rwx::ro(), config), _rtc(env.env()), _set_signal_handler(env.env().ep(), *this, &Rtc_file_system::_handle_set_signal) @@ -136,10 +137,7 @@ class Vfs::Rtc_file_system : public Single_file_system Stat_result stat(char const *path, Stat &out) override { - Stat_result result = Single_file_system::stat(path, out); - out.mode |= 0444; - - return result; + return Single_file_system::stat(path, out); } Watch_result watch(char const *path, @@ -159,6 +157,12 @@ class Vfs::Rtc_file_system : public Single_file_system catch (Genode::Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } catch (Genode::Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } } + + void close(Vfs_watch_handle *handle) override + { + Genode::destroy(handle->alloc(), + static_cast<Registered_watch_handle *>(handle)); + } }; #endif /* _INCLUDE__VFS__RTC_FILE_SYSTEM_H_ */ diff --git a/repos/os/src/lib/vfs/symlink_file_system.h b/repos/os/src/lib/vfs/symlink_file_system.h index 57562b088..63d44fcd6 100644 --- a/repos/os/src/lib/vfs/symlink_file_system.h +++ b/repos/os/src/lib/vfs/symlink_file_system.h @@ -60,7 +60,8 @@ class Vfs::Symlink_file_system : public Single_file_system Symlink_file_system(Vfs::Env&, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_SYMLINK, "symlink", config), + Single_file_system(Node_type::SYMLINK, "symlink", + Node_rwx::rw(), config), _target(config.attribute_value("target", Target())) { } diff --git a/repos/os/src/lib/vfs/tar_file_system.h b/repos/os/src/lib/vfs/tar_file_system.h index f00900dc2..e149f8218 100644 --- a/repos/os/src/lib/vfs/tar_file_system.h +++ b/repos/os/src/lib/vfs/tar_file_system.h @@ -110,12 +110,22 @@ class Vfs::Tar_file_system : public File_system TYPE_LONG_LINK = 75, TYPE_LONG_NAME = 76 }; - file_size size() const { return _long_name() ? _next()->size() : _read(_size); } - unsigned uid() const { return _long_name() ? _next()->uid() : _read(_uid); } - unsigned gid() const { return _long_name() ? _next()->gid() : _read(_gid); } - unsigned mode() const { return _long_name() ? _next()->mode() : _read(_mode); } - unsigned type() const { return _long_name() ? _next()->type() : _read(_type); } - void *data() const { return _long_name() ? _next()->data() : (void *)_data_begin(); } + file_size size() const { return _long_name() ? _next()->size() : _read(_size); } + long long mtime() const { return _long_name() ? _next()->mtime() : _read(_mtime); } + unsigned uid() const { return _long_name() ? _next()->uid() : _read(_uid); } + unsigned gid() const { return _long_name() ? _next()->gid() : _read(_gid); } + unsigned mode() const { return _long_name() ? _next()->mode() : _read(_mode); } + unsigned type() const { return _long_name() ? _next()->type() : _read(_type); } + void *data() const { return _long_name() ? _next()->data() : (void *)_data_begin(); } + + Node_rwx rwx() const + { + unsigned const mode_bits = mode(); + + return { .readable = (mode_bits & 0400) != 0, + .writeable = (mode_bits & 0200) != 0, + .executable = (mode_bits & 0100) != 0 }; + } char const *name() const { return _long_name() ? _data_begin() : _name; } unsigned max_name_len() const { return _long_name() ? MAX_PATH_LEN : 100; } @@ -193,50 +203,67 @@ class Vfs::Tar_file_system : public File_system if (count < sizeof(Dirent)) return READ_ERR_INVALID; - Dirent *dirent = (Dirent*)dst; + Dirent &dirent = *(Dirent*)dst; - /* initialize */ - *dirent = Dirent(); + file_offset const index = seek() / sizeof(Dirent); - file_offset index = seek() / sizeof(Dirent); + Node const *node_ptr = _node->lookup_child(index); - Node const *node = _node->lookup_child(index); - - if (!node) + if (!node_ptr) { + dirent = Dirent { }; + out_count = 0; return READ_OK; + } - dirent->fileno = (Genode::addr_t)node; + Node const &node = *node_ptr; - Record const *record = node->record; + Record const *record_ptr = node.record; - while (record && (record->type() == Record::TYPE_HARDLINK)) { + while (record_ptr && (record_ptr->type() == Record::TYPE_HARDLINK)) { Tar_file_system &tar_fs = static_cast<Tar_file_system&>(fs()); - Node const *target = tar_fs.dereference(record->linked_name()); - record = target ? target->record : 0; + Node const *target = tar_fs.dereference(record_ptr->linked_name()); + record_ptr = target ? target->record : 0; } - if (record) { - switch (record->type()) { - case Record::TYPE_FILE: - dirent->type = DIRENT_TYPE_FILE; break; - case Record::TYPE_SYMLINK: - dirent->type = DIRENT_TYPE_SYMLINK; break; - case Record::TYPE_DIR: - dirent->type = DIRENT_TYPE_DIRECTORY; break; + using Dirent_type = Vfs::Directory_service::Dirent_type; - default: - Genode::error("unhandled record type ", record->type(), " " - "for ", node->name); - } - } else { - /* If no record exists, assume it is a directory */ - dirent->type = DIRENT_TYPE_DIRECTORY; + /* if no record exists, assume it is a directory */ + if (!record_ptr) { + dirent = { + .fileno = (Genode::addr_t)node_ptr, + .type = Dirent_type::DIRECTORY, + .rwx = Node_rwx::rx(), + .name = { node.name } + }; + out_count = sizeof(Dirent); + return READ_OK; } - strncpy(dirent->name, node->name, sizeof(dirent->name)); + Record const &record = *record_ptr; + auto node_type = [&] () + { + switch (record.type()) { + case Record::TYPE_FILE: return Dirent_type::CONTINUOUS_FILE; + case Record::TYPE_SYMLINK: return Dirent_type::SYMLINK; + case Record::TYPE_DIR: return Dirent_type::DIRECTORY; + }; + + Genode::warning("unhandled record type ", record.type(), " " + "for ", node.name); + + return Dirent_type::END; + }; + + dirent = { + .fileno = (Genode::addr_t)node_ptr, + .type = node_type(), + .rwx = { .readable = true, + .writeable = false, + .executable = record.rwx().executable }, + .name = { node.name } + }; out_count = sizeof(Dirent); - return READ_OK; } }; @@ -576,35 +603,40 @@ class Vfs::Tar_file_system : public File_system Stat_result stat(char const *path, Stat &out) override { - out = Stat(); + out = Stat { }; - Node const *node = dereference(path); - if (!node) + Node const *node_ptr = dereference(path); + if (!node_ptr) return STAT_ERR_NO_ENTRY; - if (!node->record) { - out.mode = STAT_MODE_DIRECTORY; + if (!node_ptr->record) { + out.type = Node_type::DIRECTORY; + out.rwx = Node_rwx::rx(); return STAT_OK; } - Record const *record = node->record; + Record const &record = *node_ptr->record; - /* convert TAR record modes to stat modes */ - unsigned mode = record->mode(); - switch (record->type()) { - case Record::TYPE_FILE: mode |= STAT_MODE_FILE; break; - case Record::TYPE_SYMLINK: mode |= STAT_MODE_SYMLINK; break; - case Record::TYPE_DIR: mode |= STAT_MODE_DIRECTORY; break; + auto node_type = [&] () + { + switch (record.type()) { + case Record::TYPE_FILE: return Node_type::CONTINUOUS_FILE; + case Record::TYPE_SYMLINK: return Node_type::SYMLINK; + case Record::TYPE_DIR: return Node_type::DIRECTORY; + }; + return Node_type::DIRECTORY; + }; - default: break; - } - - out.mode = mode; - out.size = record->size(); - out.uid = record->uid(); - out.gid = record->gid(); - out.inode = (Genode::addr_t)node; - out.device = (Genode::addr_t)this; + out = { + .size = record.size(), + .type = node_type(), + .rwx = { .readable = true, + .writeable = false, + .executable = record.rwx().executable }, + .inode = (Genode::addr_t)node_ptr, + .device = (Genode::addr_t)this, + .modification_time = { record.mtime() } + }; return STAT_OK; } diff --git a/repos/os/src/lib/vfs/terminal_file_system.h b/repos/os/src/lib/vfs/terminal_file_system.h index d47fc9eac..3d996fced 100644 --- a/repos/os/src/lib/vfs/terminal_file_system.h +++ b/repos/os/src/lib/vfs/terminal_file_system.h @@ -18,58 +18,141 @@ #include <terminal_session/connection.h> #include <vfs/single_file_system.h> -#include <base/registry.h> +#include <vfs/dir_file_system.h> +#include <vfs/readonly_value_file_system.h> +#include <util/xml_generator.h> +#include <os/ring_buffer.h> namespace Vfs { class Terminal_file_system; } -class Vfs::Terminal_file_system : public Single_file_system +struct Vfs::Terminal_file_system { + typedef String<64> Name; + + struct Local_factory; + struct Data_file_system; + struct Compound_file_system; +}; + + +/** + * File system node for processing the terminal data read/write streams + */ +class Vfs::Terminal_file_system::Data_file_system : public Single_file_system +{ + public: + + /** + * Interface for propagating user interrupts (control-c) + */ + struct Interrupt_handler : Interface + { + virtual void handle_interrupt() = 0; + }; + private: - typedef Genode::String<64> Label; - Label _label; + Name const _name; - Genode::Env &_env; + Genode::Entrypoint &_ep; - Terminal::Connection _terminal { _env, _label.string() }; + Terminal::Connection &_terminal; + + Interrupt_handler &_interrupt_handler; + + enum { READ_BUFFER_SIZE = 4000 }; + + typedef Genode::Ring_buffer<char, READ_BUFFER_SIZE + 1, + Genode::Ring_buffer_unsynchronized> Read_buffer; + + Read_buffer _read_buffer { }; + + static void _fetch_data_from_terminal(Terminal::Connection &terminal, + Read_buffer &read_buffer, + Interrupt_handler &interrupt_handler) + { + while (terminal.avail()) { + + /* + * Copy new data into read buffer, detect user-interrupt + * characters (control-c) + */ + unsigned const buf_size = read_buffer.avail_capacity(); + if (buf_size == 0) + break; + + char buf[buf_size] { }; + + unsigned const received = terminal.read(buf, buf_size); + + for (unsigned i = 0; i < received; i++) { + + char const c = buf[i]; + + enum { INTERRUPT = 3 }; + + if (c == INTERRUPT) { + interrupt_handler.handle_interrupt(); + } else { + read_buffer.add(c); + } + } + } + } struct Terminal_vfs_handle : Single_vfs_handle { - Terminal::Connection &terminal; - bool notifying { false }; - bool blocked { false }; + Terminal::Connection &_terminal; + Read_buffer &_read_buffer; + Interrupt_handler &_interrupt_handler; - Terminal_vfs_handle(Terminal::Connection &term, + bool notifying = false; + bool blocked = false; + + Terminal_vfs_handle(Terminal::Connection &terminal, + Read_buffer &read_buffer, + Interrupt_handler &interrupt_handler, Directory_service &ds, File_io_service &fs, Genode::Allocator &alloc, int flags) : Single_vfs_handle(ds, fs, alloc, flags), - terminal(term) + _terminal(terminal), + _read_buffer(read_buffer), + _interrupt_handler(interrupt_handler) { } bool read_ready() override { - return terminal.avail(); } + return !_read_buffer.empty(); } Read_result read(char *dst, file_size count, file_size &out_count) override { - if (!terminal.avail()) { + if (_read_buffer.empty()) + _fetch_data_from_terminal(_terminal, _read_buffer, + _interrupt_handler); + + if (_read_buffer.empty()) { blocked = true; return READ_QUEUED; } - out_count = terminal.read(dst, count); + unsigned consumed = 0; + for (; consumed < count && !_read_buffer.empty(); consumed++) + dst[consumed] = _read_buffer.get(); + + out_count = consumed; + return READ_OK; } Write_result write(char const *src, file_size count, file_size &out_count) override { - out_count = terminal.write(src, count); + out_count = _terminal.write(src, count); return WRITE_OK; } }; @@ -79,11 +162,26 @@ class Vfs::Terminal_file_system : public Single_file_system Handle_registry _handle_registry { }; - Genode::Io_signal_handler<Terminal_file_system> _read_avail_handler { - _env.ep(), *this, &Terminal_file_system::_handle_read_avail }; + Genode::Io_signal_handler<Data_file_system> _read_avail_handler { + _ep, *this, &Data_file_system::_handle_read_avail }; void _handle_read_avail() { + /* + * Fetch as much data from the terminal as possible to detect + * user-interrupt characters (control-c), even before the VFS + * client attempts to read from the terminal. + * + * Note that a user interrupt that follows a large chunk of data + * (exceeding the capacity of the read buffer) cannot be detected + * without reading the data first. In the case where the VFS client + * never reads data (e.g., it just blocks for a timeout), + * consecutive user interrupts will never be delivered once such a + * situation occurs. This can be provoked by pasting a large amount + * of text into the terminal. + */ + _fetch_data_from_terminal(_terminal, _read_buffer, _interrupt_handler); + _handle_registry.for_each([this] (Registered_handle &handle) { if (handle.blocked) { handle.blocked = false; @@ -99,18 +197,22 @@ class Vfs::Terminal_file_system : public Single_file_system public: - Terminal_file_system(Vfs::Env &env, Genode::Xml_node config) + Data_file_system(Genode::Entrypoint &ep, + Terminal::Connection &terminal, + Name const &name, + Interrupt_handler &interrupt_handler) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config), - _label(config.attribute_value("label", Label())), - _env(env.env()) + Single_file_system(Node_type::TRANSACTIONAL_FILE, name.string(), + Node_rwx::rw(), Genode::Xml_node("<data/>")), + _name(name), _ep(ep), _terminal(terminal), + _interrupt_handler(interrupt_handler) { /* register for read-avail notification */ _terminal.read_avail_sigh(_read_avail_handler); } - static const char *name() { return "terminal"; } - char const *type() override { return "terminal"; } + static const char *name() { return "data"; } + char const *type() override { return "data"; } Open_result open(char const *path, unsigned flags, Vfs_handle **out_handle, @@ -121,7 +223,8 @@ class Vfs::Terminal_file_system : public Single_file_system try { *out_handle = new (alloc) - Registered_handle(_handle_registry, _terminal, *this, *this, alloc, flags); + Registered_handle(_handle_registry, _terminal, _read_buffer, + _interrupt_handler, *this, *this, alloc, flags); return OPEN_OK; } catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } @@ -155,4 +258,142 @@ class Vfs::Terminal_file_system : public Single_file_system } }; + +struct Vfs::Terminal_file_system::Local_factory : File_system_factory, + Data_file_system::Interrupt_handler +{ + typedef Genode::String<64> Label; + Label const _label; + + Name const _name; + + Genode::Env &_env; + + Terminal::Connection _terminal { _env, _label.string() }; + + Data_file_system _data_fs { _env.ep(), _terminal, _name, *this }; + + struct Info + { + Terminal::Session::Size size; + + void print(Genode::Output &out) const + { + char buf[128] { }; + Genode::Xml_generator xml(buf, sizeof(buf), "terminal", [&] () { + xml.attribute("rows", size.lines()); + xml.attribute("columns", size.columns()); + }); + Genode::print(out, Genode::Cstring(buf)); + } + }; + + /** + * Number of occurred user interrupts (control-c) + */ + unsigned _interrupts = 0; + + Readonly_value_file_system<Info> _info_fs { "info", Info{} }; + Readonly_value_file_system<unsigned> _rows_fs { "rows", 0 }; + Readonly_value_file_system<unsigned> _columns_fs { "columns", 0 }; + Readonly_value_file_system<unsigned> _interrupts_fs { "interrupts", _interrupts }; + + Genode::Io_signal_handler<Local_factory> _size_changed_handler { + _env.ep(), *this, &Local_factory::_handle_size_changed }; + + void _handle_size_changed() + { + Info const info { .size = _terminal.size() }; + + _info_fs .value(info); + _rows_fs .value(info.size.lines()); + _columns_fs.value(info.size.columns()); + } + + /** + * Interrupt_handler interface + */ + void handle_interrupt() override + { + _interrupts++; + _interrupts_fs.value(_interrupts); + } + + static Name name(Xml_node config) + { + return config.attribute_value("name", Name("terminal")); + } + + Local_factory(Vfs::Env &env, Xml_node config) + : + _label(config.attribute_value("label", Label(""))), + _name(name(config)), + _env(env.env()) + { + _terminal.size_changed_sigh(_size_changed_handler); + _handle_size_changed(); + } + + Vfs::File_system *create(Vfs::Env&, Xml_node node) override + { + if (node.has_type("data")) return &_data_fs; + if (node.has_type("info")) return &_info_fs; + if (node.has_type("rows")) return &_rows_fs; + if (node.has_type("columns")) return &_columns_fs; + if (node.has_type("interrupts")) return &_interrupts_fs; + + return nullptr; + } +}; + + +class Vfs::Terminal_file_system::Compound_file_system : private Local_factory, + public Vfs::Dir_file_system +{ + private: + + typedef Terminal_file_system::Name Name; + + typedef String<200> Config; + static Config _config(Name const &name) + { + char buf[Config::capacity()] { }; + + /* + * By not using the node type "dir", we operate the + * 'Dir_file_system' in root mode, allowing multiple sibling nodes + * to be present at the mount point. + */ + Genode::Xml_generator xml(buf, sizeof(buf), "compound", [&] () { + + xml.node("data", [&] () { + xml.attribute("name", name); }); + + xml.node("dir", [&] () { + xml.attribute("name", Name(".", name)); + xml.node("info", [&] () {}); + xml.node("rows", [&] () {}); + xml.node("columns", [&] () {}); + xml.node("interrupts", [&] () {}); + }); + }); + + return Config(Genode::Cstring(buf)); + } + + public: + + Compound_file_system(Vfs::Env &vfs_env, Genode::Xml_node node) + : + Local_factory(vfs_env, node), + Vfs::Dir_file_system(vfs_env, + Xml_node(_config(Local_factory::name(node)).string()), + *this) + { } + + static const char *name() { return "terminal"; } + + char const *type() override { return name(); } +}; + #endif /* _INCLUDE__VFS__TERMINAL_FILE_SYSTEM_H_ */ diff --git a/repos/os/src/lib/vfs/zero_file_system.h b/repos/os/src/lib/vfs/zero_file_system.h index 541113a15..0332512c5 100644 --- a/repos/os/src/lib/vfs/zero_file_system.h +++ b/repos/os/src/lib/vfs/zero_file_system.h @@ -24,7 +24,8 @@ struct Vfs::Zero_file_system : Single_file_system { Zero_file_system(Vfs::Env&, Genode::Xml_node config) : - Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config) + Single_file_system(Node_type::CONTINUOUS_FILE, name(), + Node_rwx::rw(), config) { } static char const *name() { return "zero"; } diff --git a/repos/os/src/server/fs_log/README b/repos/os/src/server/fs_log/README index db41b850b..0c35d004d 100644 --- a/repos/os/src/server/fs_log/README +++ b/repos/os/src/server/fs_log/README @@ -18,7 +18,7 @@ the file "/log". ! <provides><service name="LOG"/></provides> ! <config> ! <policy label_prefix="nic_drv" truncate="no"/> -! <policy label_prefix="cli_monitor -> " merge="yes"/> +! <policy label_prefix="runtime -> " merge="yes"/> ! <default-policy truncate="yes"/> ! </config> ! </start> diff --git a/repos/os/src/server/fs_rom/main.cc b/repos/os/src/server/fs_rom/main.cc index e0652c82b..2221af036 100755 --- a/repos/os/src/server/fs_rom/main.cc +++ b/repos/os/src/server/fs_rom/main.cc @@ -471,6 +471,9 @@ class Fs_rom::Rom_session_component : public Rpc_object<Rom_session> case File_system::Packet_descriptor::READ_READY: warning("discarding strange READ_READY acknowledgement"); return; + case File_system::Packet_descriptor::WRITE_TIMESTAMP: + warning("discarding strange WRITE_TIMESTAMP acknowledgement"); + return; } } }; diff --git a/repos/os/src/server/input_filter/de_ch.chargen b/repos/os/src/server/input_filter/de_ch.chargen index fbc0e2ea4..898a434f9 100644 --- a/repos/os/src/server/input_filter/de_ch.chargen +++ b/repos/os/src/server/input_filter/de_ch.chargen @@ -129,46 +129,6 @@ <key name="KEY_102ND" code="0x003e"/> <!-- > --> </map> - <!-- CONTROL --> - <map mod2="true"> - <key name="KEY_3" code="0x001b"/> <!-- ESC (escape) CTRL-3 --> - <key name="KEY_4" code="0x001c"/> <!-- FS (file separator) CTRL-4 --> - <key name="KEY_5" code="0x001d"/> <!-- GS (group separator) CTRL-5 --> - <key name="KEY_6" code="0x001e"/> <!-- RS (record separator) CTRL-6 --> - <key name="KEY_7" code="0x001f"/> <!-- US (unit separator) CTRL-7 --> - <key name="KEY_Q" code="0x0011"/> <!-- DC1 (device control 1) CTRL-q --> - <key name="KEY_W" code="0x0017"/> <!-- ETB (end of trans. blk) CTRL-w --> - <key name="KEY_E" code="0x0005"/> <!-- ENQ (enquiry) CTRL-e --> - <key name="KEY_R" code="0x0012"/> <!-- DC2 (device control 2) CTRL-r --> - <key name="KEY_T" code="0x0014"/> <!-- DC4 (device control 4) CTRL-t --> - <key name="KEY_Y" code="0x001a"/> <!-- SUB (substitute) CTRL-z --> - <key name="KEY_U" code="0x0015"/> <!-- NAK (negative ack.) CTRL-u --> - <key name="KEY_I" code="0x0009"/> <!-- HT '\t' (horizontal tab) CTRL-i --> - <key name="KEY_O" code="0x000f"/> <!-- SI (shift in) CTRL-o --> - <key name="KEY_P" code="0x0010"/> <!-- DLE (data link escape) CTRL-p --> - <key name="KEY_A" code="0x0001"/> <!-- SOH (start of heading) CTRL-a --> - <key name="KEY_S" code="0x0013"/> <!-- DC3 (device control 3) CTRL-s --> - <key name="KEY_D" code="0x0004"/> <!-- EOT (end of transmission) CTRL-d --> - <key name="KEY_F" code="0x0006"/> <!-- ACK (acknowledge) CTRL-f --> - <key name="KEY_G" code="0x0007"/> <!-- BEL '\a' (bell) CTRL-g --> - <key name="KEY_H" code="0x0008"/> <!-- BS '\b' (backspace) CTRL-h --> - <key name="KEY_J" code="0x000a"/> <!-- LF '\n' (new line) CTRL-j --> - <key name="KEY_K" code="0x000b"/> <!-- VT '\v' (vertical tab) CTRL-k --> - <key name="KEY_L" code="0x000c"/> <!-- FF '\f' (form feed) CTRL-l --> - <key name="KEY_Z" code="0x0019"/> <!-- EM (end of medium) CTRL-y --> - <key name="KEY_X" code="0x0018"/> <!-- CAN (cancel) CTRL-x --> - <key name="KEY_C" code="0x0003"/> <!-- ETX (end of text) CTRL-c --> - <key name="KEY_V" code="0x0016"/> <!-- SYN (synchronous idle) CTRL-v --> - <key name="KEY_B" code="0x0002"/> <!-- STX (start of text) CTRL-b --> - <key name="KEY_N" code="0x000e"/> <!-- SO (shift out) CTRL-n --> - <key name="KEY_M" code="0x000d"/> <!-- CR '\r' (carriage ret) CTRL-m --> - <key name="KEY_KP7" code="0x001f"/> <!-- US (unit separator) CTRL-KP_7 --> - <key name="KEY_KP4" code="0x001c"/> <!-- FS (file separator) CTRL-KP_4 --> - <key name="KEY_KP5" code="0x001d"/> <!-- GS (group separator) CTRL-KP_5 --> - <key name="KEY_KP6" code="0x001e"/> <!-- RS (record separator) CTRL-KP_6 --> - <key name="KEY_KP3" code="0x001b"/> <!-- ESC (escape) CTRL-KP_3 --> - </map> - <!-- ALTGR --> <map mod1="false" mod2="false" mod3="true" mod4="false"> <key name="KEY_1" code="0x00a6"/> <!-- ¦ (*) --> diff --git a/repos/os/src/server/input_filter/de_de.chargen b/repos/os/src/server/input_filter/de_de.chargen index 32e6e9f68..d1885f4a8 100644 --- a/repos/os/src/server/input_filter/de_de.chargen +++ b/repos/os/src/server/input_filter/de_de.chargen @@ -75,7 +75,6 @@ <key name="KEY_ENTER" ascii="10"/> <key name="KEY_KPENTER" ascii="10"/> <key name="KEY_DELETE" ascii="127"/> - <dummy/> </map> <!-- SHIFT --> @@ -127,54 +126,7 @@ <key name="KEY_COMMA" code="0x003b"/> <!-- ; --> <key name="KEY_DOT" code="0x003a"/> <!-- : --> <key name="KEY_SLASH" code="0x005f"/> <!-- _ --> - <key name="KEY_KPASTERISK" code="0x002a"/> <!-- * --> - <key name="KEY_KPMINUS" code="0x002d"/> <!-- - --> - <key name="KEY_KPPLUS" code="0x002b"/> <!-- + --> <key name="KEY_102ND" code="0x003e"/> <!-- > --> - <key name="KEY_KPSLASH" code="0x002f"/> <!-- / --> - <dummy/> - </map> - - <!-- CONTROL --> - <map mod2="true"> - <key name="KEY_3" code="0x001b"/> <!-- ESC (escape) CTRL-3 --> - <key name="KEY_4" code="0x001c"/> <!-- FS (file separator) CTRL-4 --> - <key name="KEY_5" code="0x001d"/> <!-- GS (group separator) CTRL-5 --> - <key name="KEY_6" code="0x001e"/> <!-- RS (record separator) CTRL-6 --> - <key name="KEY_7" code="0x001f"/> <!-- US (unit separator) CTRL-7 --> - <key name="KEY_Q" code="0x0011"/> <!-- DC1 (device control 1) CTRL-q --> - <key name="KEY_W" code="0x0017"/> <!-- ETB (end of trans. blk) CTRL-w --> - <key name="KEY_E" code="0x0005"/> <!-- ENQ (enquiry) CTRL-e --> - <key name="KEY_R" code="0x0012"/> <!-- DC2 (device control 2) CTRL-r --> - <key name="KEY_T" code="0x0014"/> <!-- DC4 (device control 4) CTRL-t --> - <key name="KEY_Y" code="0x001a"/> <!-- SUB (substitute) CTRL-z --> - <key name="KEY_U" code="0x0015"/> <!-- NAK (negative ack.) CTRL-u --> - <key name="KEY_I" code="0x0009"/> <!-- HT '\t' (horizontal tab) CTRL-i --> - <key name="KEY_O" code="0x000f"/> <!-- SI (shift in) CTRL-o --> - <key name="KEY_P" code="0x0010"/> <!-- DLE (data link escape) CTRL-p --> - <key name="KEY_A" code="0x0001"/> <!-- SOH (start of heading) CTRL-a --> - <key name="KEY_S" code="0x0013"/> <!-- DC3 (device control 3) CTRL-s --> - <key name="KEY_D" code="0x0004"/> <!-- EOT (end of transmission) CTRL-d --> - <key name="KEY_F" code="0x0006"/> <!-- ACK (acknowledge) CTRL-f --> - <key name="KEY_G" code="0x0007"/> <!-- BEL '\a' (bell) CTRL-g --> - <key name="KEY_H" code="0x0008"/> <!-- BS '\b' (backspace) CTRL-h --> - <key name="KEY_J" code="0x000a"/> <!-- LF '\n' (new line) CTRL-j --> - <key name="KEY_K" code="0x000b"/> <!-- VT '\v' (vertical tab) CTRL-k --> - <key name="KEY_L" code="0x000c"/> <!-- FF '\f' (form feed) CTRL-l --> - <key name="KEY_GRAVE" code="0x001e"/> <!-- RS (record separator) CTRL-asciicircum --> - <key name="KEY_Z" code="0x0019"/> <!-- EM (end of medium) CTRL-y --> - <key name="KEY_X" code="0x0018"/> <!-- CAN (cancel) CTRL-x --> - <key name="KEY_C" code="0x0003"/> <!-- ETX (end of text) CTRL-c --> - <key name="KEY_V" code="0x0016"/> <!-- SYN (synchronous idle) CTRL-v --> - <key name="KEY_B" code="0x0002"/> <!-- STX (start of text) CTRL-b --> - <key name="KEY_N" code="0x000e"/> <!-- SO (shift out) CTRL-n --> - <key name="KEY_M" code="0x000d"/> <!-- CR '\r' (carriage ret) CTRL-m --> - <key name="KEY_KP7" code="0x001f"/> <!-- US (unit separator) CTRL-KP_7 --> - <key name="KEY_KP4" code="0x001c"/> <!-- FS (file separator) CTRL-KP_4 --> - <key name="KEY_KP5" code="0x001d"/> <!-- GS (group separator) CTRL-KP_5 --> - <key name="KEY_KP6" code="0x001e"/> <!-- RS (record separator) CTRL-KP_6 --> - <key name="KEY_KP3" code="0x001b"/> <!-- ESC (escape) CTRL-KP_3 --> - <dummy/> </map> <!-- ALTGR --> @@ -195,7 +147,6 @@ <key name="KEY_RIGHTBRACE" code="0x007e"/> <!-- ~ --> <key name="KEY_M" code="0x00b5"/> <!-- µ --> <key name="KEY_102ND" code="0x007c"/> <!-- | --> - <dummy/> </map> <!-- CAPSLOCK --> @@ -283,7 +234,6 @@ <key name="KEY_DOT" code="0x003a"/> <!-- : --> <key name="KEY_SLASH" code="0x005f"/> <!-- _ --> <key name="KEY_102ND" code="0x003e"/> <!-- > --> - <dummy/> </map> <!-- ALTGR-CAPSLOCK --> @@ -304,7 +254,6 @@ <key name="KEY_RIGHTBRACE" code="0x007e"/> <!-- ~ --> <key name="KEY_M" code="0x00b5"/> <!-- µ --> <key name="KEY_102ND" code="0x007c"/> <!-- | --> - <dummy/> </map> <!-- SHIFT-ALTGR-CAPSLOCK --> diff --git a/repos/os/src/server/input_filter/en_us.chargen b/repos/os/src/server/input_filter/en_us.chargen index f826357de..a7b70234d 100644 --- a/repos/os/src/server/input_filter/en_us.chargen +++ b/repos/os/src/server/input_filter/en_us.chargen @@ -133,50 +133,6 @@ <key name="KEY_KPSLASH" code="0x002f"/> <!-- / --> </map> - <!-- CONTROL --> - <map mod2="true"> - <key name="KEY_3" code="0x001b"/> <!-- ESC (escape) CTRL-3 --> - <key name="KEY_4" code="0x001c"/> <!-- FS (file separator) CTRL-4 --> - <key name="KEY_5" code="0x001d"/> <!-- GS (group separator) CTRL-5 --> - <key name="KEY_6" code="0x001e"/> <!-- RS (record separator) CTRL-6 --> - <key name="KEY_7" code="0x001f"/> <!-- US (unit separator) CTRL-7 --> - <key name="KEY_Q" code="0x0011"/> <!-- DC1 (device control 1) CTRL-q --> - <key name="KEY_W" code="0x0017"/> <!-- ETB (end of trans. blk) CTRL-w --> - <key name="KEY_E" code="0x0005"/> <!-- ENQ (enquiry) CTRL-e --> - <key name="KEY_R" code="0x0012"/> <!-- DC2 (device control 2) CTRL-r --> - <key name="KEY_T" code="0x0014"/> <!-- DC4 (device control 4) CTRL-t --> - <key name="KEY_Y" code="0x0019"/> <!-- EM (end of medium) CTRL-y --> - <key name="KEY_U" code="0x0015"/> <!-- NAK (negative ack.) CTRL-u --> - <key name="KEY_I" code="0x0009"/> <!-- HT '\t' (horizontal tab) CTRL-i --> - <key name="KEY_O" code="0x000f"/> <!-- SI (shift in) CTRL-o --> - <key name="KEY_P" code="0x0010"/> <!-- DLE (data link escape) CTRL-p --> - <key name="KEY_LEFTBRACE" code="0x001b"/> <!-- ESC (escape) CTRL-bracketleft --> - <key name="KEY_RIGHTBRACE" code="0x001d"/> <!-- GS (group separator) CTRL-bracketright --> - <key name="KEY_A" code="0x0001"/> <!-- SOH (start of heading) CTRL-a --> - <key name="KEY_S" code="0x0013"/> <!-- DC3 (device control 3) CTRL-s --> - <key name="KEY_D" code="0x0004"/> <!-- EOT (end of transmission) CTRL-d --> - <key name="KEY_F" code="0x0006"/> <!-- ACK (acknowledge) CTRL-f --> - <key name="KEY_G" code="0x0007"/> <!-- BEL '\a' (bell) CTRL-g --> - <key name="KEY_H" code="0x0008"/> <!-- BS '\b' (backspace) CTRL-h --> - <key name="KEY_J" code="0x000a"/> <!-- LF '\n' (new line) CTRL-j --> - <key name="KEY_K" code="0x000b"/> <!-- VT '\v' (vertical tab) CTRL-k --> - <key name="KEY_L" code="0x000c"/> <!-- FF '\f' (form feed) CTRL-l --> - <key name="KEY_BACKSLASH" code="0x001c"/> <!-- FS (file separator) CTRL-backslash --> - <key name="KEY_Z" code="0x001a"/> <!-- SUB (substitute) CTRL-z --> - <key name="KEY_X" code="0x0018"/> <!-- CAN (cancel) CTRL-x --> - <key name="KEY_C" code="0x0003"/> <!-- ETX (end of text) CTRL-c --> - <key name="KEY_V" code="0x0016"/> <!-- SYN (synchronous idle) CTRL-v --> - <key name="KEY_B" code="0x0002"/> <!-- STX (start of text) CTRL-b --> - <key name="KEY_N" code="0x000e"/> <!-- SO (shift out) CTRL-n --> - <key name="KEY_M" code="0x000d"/> <!-- CR '\r' (carriage ret) CTRL-m --> - <key name="KEY_SLASH" code="0x001f"/> <!-- US (unit separator) CTRL-slash --> - <key name="KEY_KP7" code="0x001f"/> <!-- US (unit separator) CTRL-KP_7 --> - <key name="KEY_KP4" code="0x001c"/> <!-- FS (file separator) CTRL-KP_4 --> - <key name="KEY_KP5" code="0x001d"/> <!-- GS (group separator) CTRL-KP_5 --> - <key name="KEY_KP6" code="0x001e"/> <!-- RS (record separator) CTRL-KP_6 --> - <key name="KEY_KP3" code="0x001b"/> <!-- ESC (escape) CTRL-KP_3 --> - </map> - <!-- ALTGR --> <map mod1="false" mod2="false" mod3="true" mod4="false"> <key name="KEY_5" code="0x20ac"/> <!-- € --> diff --git a/repos/os/src/server/input_filter/en_workman.chargen b/repos/os/src/server/input_filter/en_workman.chargen index 432b5a531..e825065e4 100644 --- a/repos/os/src/server/input_filter/en_workman.chargen +++ b/repos/os/src/server/input_filter/en_workman.chargen @@ -118,32 +118,4 @@ <key name="KEY_DOT" ascii="62"/> <!-- '>' --> <key name="KEY_SLASH" char="?"/> </map> - <map mod2="yes"> - <key name="KEY_A" ascii="01" /> - <key name="KEY_B" ascii="22" /> - <key name="KEY_C" ascii="13" /> - <key name="KEY_D" ascii="08" /> - <key name="KEY_E" ascii="18" /> - <key name="KEY_F" ascii="20" /> - <key name="KEY_G" ascii="07" /> - <key name="KEY_H" ascii="25" /> - <key name="KEY_I" ascii="21" /> - <key name="KEY_J" ascii="14" /> - <key name="KEY_K" ascii="05" /> - <key name="KEY_L" ascii="15" /> - <key name="KEY_M" ascii="12" /> - <key name="KEY_N" ascii="11" /> - <key name="KEY_O" ascii="16" /> - <key name="KEY_P" ascii="09" /> - <key name="KEY_Q" ascii="17" /> - <key name="KEY_R" ascii="23" /> - <key name="KEY_S" ascii="19" /> - <key name="KEY_T" ascii="02" /> - <key name="KEY_U" ascii="06" /> - <key name="KEY_V" ascii="03" /> - <key name="KEY_W" ascii="04" /> - <key name="KEY_X" ascii="24" /> - <key name="KEY_Y" ascii="10" /> - <key name="KEY_Z" ascii="26" /> - </map> </chargen> diff --git a/repos/os/src/server/input_filter/fr_ch.chargen b/repos/os/src/server/input_filter/fr_ch.chargen index 094549897..a415289b0 100644 --- a/repos/os/src/server/input_filter/fr_ch.chargen +++ b/repos/os/src/server/input_filter/fr_ch.chargen @@ -129,46 +129,6 @@ <key name="KEY_102ND" code="0x003e"/> <!-- > --> </map> - <!-- CONTROL --> - <map mod2="true"> - <key name="KEY_3" code="0x001b"/> <!-- ESC (escape) CTRL-3 --> - <key name="KEY_4" code="0x001c"/> <!-- FS (file separator) CTRL-4 --> - <key name="KEY_5" code="0x001d"/> <!-- GS (group separator) CTRL-5 --> - <key name="KEY_6" code="0x001e"/> <!-- RS (record separator) CTRL-6 --> - <key name="KEY_7" code="0x001f"/> <!-- US (unit separator) CTRL-7 --> - <key name="KEY_Q" code="0x0011"/> <!-- DC1 (device control 1) CTRL-q --> - <key name="KEY_W" code="0x0017"/> <!-- ETB (end of trans. blk) CTRL-w --> - <key name="KEY_E" code="0x0005"/> <!-- ENQ (enquiry) CTRL-e --> - <key name="KEY_R" code="0x0012"/> <!-- DC2 (device control 2) CTRL-r --> - <key name="KEY_T" code="0x0014"/> <!-- DC4 (device control 4) CTRL-t --> - <key name="KEY_Y" code="0x001a"/> <!-- SUB (substitute) CTRL-z --> - <key name="KEY_U" code="0x0015"/> <!-- NAK (negative ack.) CTRL-u --> - <key name="KEY_I" code="0x0009"/> <!-- HT '\t' (horizontal tab) CTRL-i --> - <key name="KEY_O" code="0x000f"/> <!-- SI (shift in) CTRL-o --> - <key name="KEY_P" code="0x0010"/> <!-- DLE (data link escape) CTRL-p --> - <key name="KEY_A" code="0x0001"/> <!-- SOH (start of heading) CTRL-a --> - <key name="KEY_S" code="0x0013"/> <!-- DC3 (device control 3) CTRL-s --> - <key name="KEY_D" code="0x0004"/> <!-- EOT (end of transmission) CTRL-d --> - <key name="KEY_F" code="0x0006"/> <!-- ACK (acknowledge) CTRL-f --> - <key name="KEY_G" code="0x0007"/> <!-- BEL '\a' (bell) CTRL-g --> - <key name="KEY_H" code="0x0008"/> <!-- BS '\b' (backspace) CTRL-h --> - <key name="KEY_J" code="0x000a"/> <!-- LF '\n' (new line) CTRL-j --> - <key name="KEY_K" code="0x000b"/> <!-- VT '\v' (vertical tab) CTRL-k --> - <key name="KEY_L" code="0x000c"/> <!-- FF '\f' (form feed) CTRL-l --> - <key name="KEY_Z" code="0x0019"/> <!-- EM (end of medium) CTRL-y --> - <key name="KEY_X" code="0x0018"/> <!-- CAN (cancel) CTRL-x --> - <key name="KEY_C" code="0x0003"/> <!-- ETX (end of text) CTRL-c --> - <key name="KEY_V" code="0x0016"/> <!-- SYN (synchronous idle) CTRL-v --> - <key name="KEY_B" code="0x0002"/> <!-- STX (start of text) CTRL-b --> - <key name="KEY_N" code="0x000e"/> <!-- SO (shift out) CTRL-n --> - <key name="KEY_M" code="0x000d"/> <!-- CR '\r' (carriage ret) CTRL-m --> - <key name="KEY_KP7" code="0x001f"/> <!-- US (unit separator) CTRL-KP_7 --> - <key name="KEY_KP4" code="0x001c"/> <!-- FS (file separator) CTRL-KP_4 --> - <key name="KEY_KP5" code="0x001d"/> <!-- GS (group separator) CTRL-KP_5 --> - <key name="KEY_KP6" code="0x001e"/> <!-- RS (record separator) CTRL-KP_6 --> - <key name="KEY_KP3" code="0x001b"/> <!-- ESC (escape) CTRL-KP_3 --> - </map> - <!-- ALTGR --> <map mod1="false" mod2="false" mod3="true" mod4="false"> <key name="KEY_1" code="0x00a6"/> <!-- ¦ (*) --> diff --git a/repos/os/src/server/input_filter/fr_fr.chargen b/repos/os/src/server/input_filter/fr_fr.chargen index aa14770b4..64f0b66ea 100644 --- a/repos/os/src/server/input_filter/fr_fr.chargen +++ b/repos/os/src/server/input_filter/fr_fr.chargen @@ -129,42 +129,6 @@ <key name="KEY_102ND" code="0x003e"/> <!-- > --> </map> - <!-- CONTROL --> - <map mod2="true"> - <key name="KEY_8" code="0x001f"/> <!-- US (unit separator) CTRL-underscore --> - <key name="KEY_Q" code="0x0001"/> <!-- SOH (start of heading) CTRL-a --> - <key name="KEY_W" code="0x001a"/> <!-- SUB (substitute) CTRL-z --> - <key name="KEY_E" code="0x0005"/> <!-- ENQ (enquiry) CTRL-e --> - <key name="KEY_R" code="0x0012"/> <!-- DC2 (device control 2) CTRL-r --> - <key name="KEY_T" code="0x0014"/> <!-- DC4 (device control 4) CTRL-t --> - <key name="KEY_Y" code="0x0019"/> <!-- EM (end of medium) CTRL-y --> - <key name="KEY_U" code="0x0015"/> <!-- NAK (negative ack.) CTRL-u --> - <key name="KEY_I" code="0x0009"/> <!-- HT '\t' (horizontal tab) CTRL-i --> - <key name="KEY_O" code="0x000f"/> <!-- SI (shift in) CTRL-o --> - <key name="KEY_P" code="0x0010"/> <!-- DLE (data link escape) CTRL-p --> - <key name="KEY_A" code="0x0011"/> <!-- DC1 (device control 1) CTRL-q --> - <key name="KEY_S" code="0x0013"/> <!-- DC3 (device control 3) CTRL-s --> - <key name="KEY_D" code="0x0004"/> <!-- EOT (end of transmission) CTRL-d --> - <key name="KEY_F" code="0x0006"/> <!-- ACK (acknowledge) CTRL-f --> - <key name="KEY_G" code="0x0007"/> <!-- BEL '\a' (bell) CTRL-g --> - <key name="KEY_H" code="0x0008"/> <!-- BS '\b' (backspace) CTRL-h --> - <key name="KEY_J" code="0x000a"/> <!-- LF '\n' (new line) CTRL-j --> - <key name="KEY_K" code="0x000b"/> <!-- VT '\v' (vertical tab) CTRL-k --> - <key name="KEY_L" code="0x000c"/> <!-- FF '\f' (form feed) CTRL-l --> - <key name="KEY_SEMICOLON" code="0x000d"/> <!-- CR '\r' (carriage ret) CTRL-m --> - <key name="KEY_Z" code="0x0017"/> <!-- ETB (end of trans. blk) CTRL-w --> - <key name="KEY_X" code="0x0018"/> <!-- CAN (cancel) CTRL-x --> - <key name="KEY_C" code="0x0003"/> <!-- ETX (end of text) CTRL-c --> - <key name="KEY_V" code="0x0016"/> <!-- SYN (synchronous idle) CTRL-v --> - <key name="KEY_B" code="0x0002"/> <!-- STX (start of text) CTRL-b --> - <key name="KEY_N" code="0x000e"/> <!-- SO (shift out) CTRL-n --> - <key name="KEY_KP7" code="0x001f"/> <!-- US (unit separator) CTRL-KP_7 --> - <key name="KEY_KP4" code="0x001c"/> <!-- FS (file separator) CTRL-KP_4 --> - <key name="KEY_KP5" code="0x001d"/> <!-- GS (group separator) CTRL-KP_5 --> - <key name="KEY_KP6" code="0x001e"/> <!-- RS (record separator) CTRL-KP_6 --> - <key name="KEY_KP3" code="0x001b"/> <!-- ESC (escape) CTRL-KP_3 --> - </map> - <!-- ALTGR --> <map mod1="false" mod2="false" mod3="true" mod4="false"> <key name="KEY_1" code="0x00b9"/> <!-- ¹ --> @@ -279,6 +243,7 @@ <key name="KEY_L" code="0x0141"/> <!-- Ł --> <key name="KEY_SEMICOLON" code="0x00ba"/> <!-- º --> <key name="KEY_GRAVE" code="0x00ac"/> <!-- ¬ --> + <key name="KEY_BACKSLASH" code="0x00b5"/> <!-- µ --> <key name="KEY_Z" code="0x0141"/> <!-- Ł --> <key name="KEY_X" code="0x003e"/> <!-- > --> <key name="KEY_C" code="0x00a9"/> <!-- © --> @@ -314,6 +279,7 @@ <key name="KEY_I" code="0x0069"/> <!-- i --> <key name="KEY_O" code="0x006f"/> <!-- o --> <key name="KEY_P" code="0x0070"/> <!-- p --> + <key name="KEY_LEFTBRACE" code="0x0308"/> <!-- dead_diaeresis --> <key name="KEY_RIGHTBRACE" code="0x00a3"/> <!-- £ --> <key name="KEY_A" code="0x0071"/> <!-- q --> <key name="KEY_S" code="0x0073"/> <!-- s --> @@ -327,6 +293,7 @@ <key name="KEY_SEMICOLON" code="0x006d"/> <!-- m --> <key name="KEY_APOSTROPHE" code="0x0025"/> <!-- % --> <key name="KEY_GRAVE" code="0x007e"/> <!-- ~ --> + <key name="KEY_BACKSLASH" code="0x00b5"/> <!-- µ --> <key name="KEY_Z" code="0x0077"/> <!-- w --> <key name="KEY_X" code="0x0078"/> <!-- x --> <key name="KEY_C" code="0x0063"/> <!-- c --> @@ -354,33 +321,33 @@ <key name="KEY_0" code="0x0040"/> <!-- @ --> <key name="KEY_MINUS" code="0x005d"/> <!-- ] --> <key name="KEY_EQUAL" code="0x007d"/> <!-- } --> - <key name="KEY_Q" code="0x00e6"/> <!-- æ --> + <key name="KEY_Q" code="0x00c6"/> <!-- Æ --> <key name="KEY_W" code="0x00ab"/> <!-- « --> <key name="KEY_E" code="0x20ac"/> <!-- € --> <key name="KEY_R" code="0x00b6"/> <!-- ¶ --> - <key name="KEY_T" code="0x0167"/> <!-- ŧ --> + <key name="KEY_T" code="0x0166"/> <!-- Ŧ --> <key name="KEY_Y" code="0x2190"/> <!-- ← --> <key name="KEY_U" code="0x2193"/> <!-- ↓ --> <key name="KEY_I" code="0x2192"/> <!-- → --> - <key name="KEY_O" code="0x00f8"/> <!-- ø --> - <key name="KEY_P" code="0x00fe"/> <!-- þ --> + <key name="KEY_O" code="0x00d8"/> <!-- Ø --> + <key name="KEY_P" code="0x00de"/> <!-- Þ --> <key name="KEY_RIGHTBRACE" code="0x00a4"/> <!-- ¤ --> <key name="KEY_A" code="0x0040"/> <!-- @ --> <key name="KEY_S" code="0x00df"/> <!-- ß --> - <key name="KEY_D" code="0x00f0"/> <!-- ð --> - <key name="KEY_F" code="0x0111"/> <!-- đ --> - <key name="KEY_G" code="0x014b"/> <!-- ŋ --> - <key name="KEY_H" code="0x0127"/> <!-- ħ --> + <key name="KEY_D" code="0x00d0"/> <!-- Ð --> + <key name="KEY_F" code="0x0110"/> <!-- Đ --> + <key name="KEY_G" code="0x014a"/> <!-- Ŋ --> + <key name="KEY_H" code="0x0126"/> <!-- Ħ --> <key name="KEY_K" code="0x0138"/> <!-- ĸ --> - <key name="KEY_L" code="0x0142"/> <!-- ł --> + <key name="KEY_L" code="0x0141"/> <!-- Ł --> <key name="KEY_SEMICOLON" code="0x00b5"/> <!-- µ --> <key name="KEY_GRAVE" code="0x00ac"/> <!-- ¬ --> - <key name="KEY_Z" code="0x0142"/> <!-- ł --> + <key name="KEY_Z" code="0x0141"/> <!-- Ł --> <key name="KEY_X" code="0x00bb"/> <!-- » --> <key name="KEY_C" code="0x00a2"/> <!-- ¢ --> <key name="KEY_V" code="0x201c"/> <!-- “ --> <key name="KEY_B" code="0x201d"/> <!-- ” --> - <key name="KEY_N" code="0x006e"/> <!-- n --> + <key name="KEY_N" code="0x004e"/> <!-- N --> <key name="KEY_COMMA" code="0x2500"/> <!-- ─ --> <key name="KEY_DOT" code="0x00b7"/> <!-- · --> <key name="KEY_102ND" code="0x007c"/> <!-- | --> diff --git a/repos/os/src/server/lx_fs/directory.h b/repos/os/src/server/lx_fs/directory.h index a71c1fca9..6eca4fa97 100644 --- a/repos/os/src/server/lx_fs/directory.h +++ b/repos/os/src/server/lx_fs/directory.h @@ -69,7 +69,7 @@ class Lx_fs::Directory : public Node } } - struct stat s; + struct stat s { }; ret = lstat(path, &s); if (ret == -1) @@ -114,6 +114,17 @@ class Lx_fs::Directory : public Node closedir(_fd); } + void update_modification_time(Timestamp const time) override + { + struct timespec ts[2] = { + { .tv_sec = (time_t)0, .tv_nsec = 0 }, + { .tv_sec = (time_t)time.value, .tv_nsec = 0 } + }; + + /* silently ignore errors */ + futimens(dirfd(_fd), (const timespec*)&ts); + } + void rename(Directory &dir_to, char const *name_from, char const *name_to) { int ret = renameat(dirfd(_fd), name_from, @@ -192,19 +203,30 @@ class Lx_fs::Directory : public Node if (!dent) return 0; - Directory_entry *e = (Directory_entry *)(dst); + Path dent_path(dent->d_name, _path.base()); - switch (dent->d_type) { - case DT_REG: e->type = Directory_entry::TYPE_FILE; break; - case DT_DIR: e->type = Directory_entry::TYPE_DIRECTORY; break; - case DT_LNK: e->type = Directory_entry::TYPE_SYMLINK; break; - default: - return 0; - } + struct stat st { }; + lstat(dent_path.base(), &st); - e->inode = dent->d_ino; + auto type = [] (unsigned char type) + { + switch (type) { + case DT_REG: return Node_type::CONTINUOUS_FILE; + case DT_DIR: return Node_type::DIRECTORY; + case DT_LNK: return Node_type::SYMLINK; + default: return Node_type::CONTINUOUS_FILE; + } + }; - strncpy(e->name, dent->d_name, sizeof(e->name)); + Directory_entry &e = *(Directory_entry *)(dst); + e = { + .inode = (unsigned long)dent->d_ino, + .type = type(dent->d_type), + .rwx = { .readable = (st.st_mode & S_IRUSR), + .writeable = (st.st_mode & S_IWUSR), + .executable = (st.st_mode & S_IXUSR) }, + .name = { dent->d_name } + }; return sizeof(Directory_entry); } @@ -217,11 +239,21 @@ class Lx_fs::Directory : public Node Status status() override { - Status s; - s.inode = inode(); - s.size = _num_entries() * sizeof(File_system::Directory_entry); - s.mode = File_system::Status::MODE_DIRECTORY; - return s; + struct stat st { }; + + int fd = dirfd(_fd); + if (fd == -1 || fstat(fd, &st) < 0) + st.st_mtime = 0; + + return { + .size = _num_entries() * sizeof(File_system::Directory_entry), + .type = Node_type::DIRECTORY, + .rwx = { .readable = (st.st_mode & S_IRUSR), + .writeable = (st.st_mode & S_IWUSR), + .executable = (st.st_mode & S_IXUSR) }, + .inode = inode(), + .modification_time = { st.st_mtime } + }; } }; diff --git a/repos/os/src/server/lx_fs/file.h b/repos/os/src/server/lx_fs/file.h index 0e4921a47..fa94192fe 100644 --- a/repos/os/src/server/lx_fs/file.h +++ b/repos/os/src/server/lx_fs/file.h @@ -82,16 +82,6 @@ class Lx_fs::File : public Node return fd; } - file_size_t _length() const - { - struct stat s; - - if (fstat(_fd, &s) < 0) - return 0; - - return s.st_size; - } - public: File(int dir, @@ -118,6 +108,17 @@ class Lx_fs::File : public Node close(_fd); } + void update_modification_time(Timestamp const time) override + { + struct timespec ts[2] = { + { .tv_sec = (time_t)0, .tv_nsec = 0 }, + { .tv_sec = (time_t)time.value, .tv_nsec = 0 } + }; + + /* silently ignore errors */ + futimens(_fd, (const timespec*)&ts); + } + size_t read(char *dst, size_t len, seek_off_t seek_offset) override { int ret = pread(_fd, dst, len, seek_offset); @@ -142,11 +143,22 @@ class Lx_fs::File : public Node Status status() override { - Status s; - s.inode = inode(); - s.size = _length(); - s.mode = File_system::Status::MODE_FILE; - return s; + struct stat st { }; + + if (fstat(_fd, &st) < 0) { + st.st_size = 0; + st.st_mtime = 0; + } + + return { + .size = (file_size_t)st.st_size, + .type = File_system::Node_type::CONTINUOUS_FILE, + .rwx = { .readable = (st.st_mode & S_IRUSR), + .writeable = (st.st_mode & S_IWUSR), + .executable = (st.st_mode & S_IXUSR) }, + .inode = inode(), + .modification_time = { st.st_mtime } + }; } void truncate(file_size_t size) override diff --git a/repos/os/src/server/lx_fs/main.cc b/repos/os/src/server/lx_fs/main.cc index 77ac945a4..6c0373a58 100644 --- a/repos/os/src/server/lx_fs/main.cc +++ b/repos/os/src/server/lx_fs/main.cc @@ -97,6 +97,16 @@ class Lx_fs::Session_component : public Session_rpc_object } break; + case Packet_descriptor::WRITE_TIMESTAMP: + if (tx_sink()->packet_valid(packet) && (packet.length() <= packet.size())) { + + packet.with_timestamp([&] (File_system::Timestamp const time) { + open_node.node().update_modification_time(time); + succeeded = true; + }); + } + break; + case Packet_descriptor::CONTENT_CHANGED: open_node.register_notify(*tx_sink()); /* notify_listeners may bounce the packet back*/ diff --git a/repos/os/src/server/lx_fs/node.h b/repos/os/src/server/lx_fs/node.h index cacc610da..61e28f591 100644 --- a/repos/os/src/server/lx_fs/node.h +++ b/repos/os/src/server/lx_fs/node.h @@ -48,6 +48,8 @@ class Lx_fs::Node : public File_system::Node_base */ void name(char const *name) { Genode::strncpy(_name, name, sizeof(_name)); } + virtual void update_modification_time(Timestamp const) = 0; + virtual size_t read(char *dst, size_t len, seek_off_t) = 0; virtual size_t write(char const *src, size_t len, seek_off_t) = 0; diff --git a/repos/os/src/server/nic_router/component.cc b/repos/os/src/server/nic_router/component.cc index d9f46fe71..ba0637688 100644 --- a/repos/os/src/server/nic_router/component.cc +++ b/repos/os/src/server/nic_router/component.cc @@ -147,66 +147,75 @@ Session_component *Net::Root::_create_session(char const *args) { try { /* create session environment temporarily on the stack */ - Session_env session_env_tmp { _env, _shared_quota, + Session_env session_env_stack { _env, _shared_quota, Ram_quota { Arg_string::find_arg(args, "ram_quota").ulong_value(0) }, Cap_quota { Arg_string::find_arg(args, "cap_quota").ulong_value(0) } }; - Reference<Session_env> session_env { session_env_tmp }; /* alloc/attach RAM block and move session env to base of the block */ Ram_dataspace_capability ram_ds { - session_env().alloc(sizeof(Session_env) + - sizeof(Session_component), CACHED) }; + session_env_stack.alloc(sizeof(Session_env) + + sizeof(Session_component), CACHED) }; try { - void * const ram_ptr { session_env().attach(ram_ds) }; - session_env = *construct_at<Session_env>(ram_ptr, session_env()); + void * const ram_ptr { session_env_stack.attach(ram_ds) }; + Session_env &session_env { + *construct_at<Session_env>(ram_ptr, session_env_stack) }; /* create new session object behind session env in the RAM block */ try { Session_label const label { label_from_args(args) }; - return construct_at<Session_component>( - (void*)((addr_t)ram_ptr + sizeof(Session_env)), - session_env(), - Arg_string::find_arg(args, "tx_buf_size").ulong_value(0), - Arg_string::find_arg(args, "rx_buf_size").ulong_value(0), - _timer, _mac_alloc.alloc(), _router_mac, label, - _interfaces, _config(), ram_ds); + Mac_address const mac { _mac_alloc.alloc() }; + try { + Session_component *x = construct_at<Session_component>( + (void*)((addr_t)ram_ptr + sizeof(Session_env)), + session_env, + Arg_string::find_arg(args, "tx_buf_size").ulong_value(0), + Arg_string::find_arg(args, "rx_buf_size").ulong_value(0), + _timer, mac, _router_mac, label, _interfaces, + _config(), ram_ds); + return x; + } + catch (Out_of_ram) { + _mac_alloc.free(mac); + Session_env session_env_stack { session_env }; + session_env_stack.detach(ram_ptr); + session_env_stack.free(ram_ds); + _invalid_downlink("NIC session RAM quota"); + throw Insufficient_ram_quota(); + } + catch (Out_of_caps) { + _mac_alloc.free(mac); + Session_env session_env_stack { session_env }; + session_env_stack.detach(ram_ptr); + session_env_stack.free(ram_ds); + _invalid_downlink("NIC session CAP quota"); + throw Insufficient_cap_quota(); + } } catch (Mac_allocator::Alloc_failed) { - session_env().detach(ram_ptr); - session_env().free(ram_ds); + Session_env session_env_stack { session_env }; + session_env_stack.detach(ram_ptr); + session_env_stack.free(ram_ds); _invalid_downlink("failed to allocate MAC address"); throw Service_denied(); } - catch (Out_of_ram) { - session_env().detach(ram_ptr); - session_env().free(ram_ds); - _invalid_downlink("NIC session RAM quota"); - throw Insufficient_ram_quota(); - } - catch (Out_of_caps) { - session_env().detach(ram_ptr); - session_env().free(ram_ds); - _invalid_downlink("NIC session CAP quota"); - throw Insufficient_cap_quota(); - } } catch (Region_map::Invalid_dataspace) { - session_env().free(ram_ds); + session_env_stack.free(ram_ds); _invalid_downlink("Failed to attach RAM"); throw Service_denied(); } catch (Region_map::Region_conflict) { - session_env().free(ram_ds); + session_env_stack.free(ram_ds); _invalid_downlink("Failed to attach RAM"); throw Service_denied(); } catch (Out_of_ram) { - session_env().free(ram_ds); + session_env_stack.free(ram_ds); _invalid_downlink("NIC session RAM quota"); throw Insufficient_ram_quota(); } catch (Out_of_caps) { - session_env().free(ram_ds); + session_env_stack.free(ram_ds); _invalid_downlink("NIC session CAP quota"); throw Insufficient_cap_quota(); } diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd index 3cd521ef8..70c72df64 100644 --- a/repos/os/src/server/nic_router/config.xsd +++ b/repos/os/src/server/nic_router/config.xsd @@ -57,12 +57,14 @@ <xs:element name="report"> <xs:complexType> - <xs:attribute name="config" type="Boolean" /> - <xs:attribute name="config_triggers" type="Boolean" /> - <xs:attribute name="bytes" type="Boolean" /> - <xs:attribute name="stats" type="Boolean" /> - <xs:attribute name="quota" type="Boolean" /> - <xs:attribute name="interval_sec" type="Seconds" /> + <xs:attribute name="config" type="Boolean" /> + <xs:attribute name="config_triggers" type="Boolean" /> + <xs:attribute name="bytes" type="Boolean" /> + <xs:attribute name="stats" type="Boolean" /> + <xs:attribute name="link_state" type="Boolean" /> + <xs:attribute name="link_state_triggers" type="Boolean" /> + <xs:attribute name="quota" type="Boolean" /> + <xs:attribute name="interval_sec" type="Seconds" /> </xs:complexType> </xs:element><!-- report --> diff --git a/repos/os/src/server/nic_router/configuration.cc b/repos/os/src/server/nic_router/configuration.cc index 7f98683c5..175d77ad8 100644 --- a/repos/os/src/server/nic_router/configuration.cc +++ b/repos/os/src/server/nic_router/configuration.cc @@ -170,6 +170,24 @@ Configuration::Configuration(Env &env, } +void Configuration::stop_reporting() +{ + if (!_reporter.valid()) { + return; + } + _reporter().enabled(false); +} + + +void Configuration::start_reporting() +{ + if (!_reporter.valid()) { + return; + } + _reporter().enabled(true); +} + + Configuration::~Configuration() { /* destroy uplinks */ diff --git a/repos/os/src/server/nic_router/configuration.h b/repos/os/src/server/nic_router/configuration.h index 56a083da2..4e23a5625 100644 --- a/repos/os/src/server/nic_router/configuration.h +++ b/repos/os/src/server/nic_router/configuration.h @@ -84,6 +84,10 @@ class Net::Configuration ~Configuration(); + void stop_reporting(); + + void start_reporting(); + /*************** ** Accessors ** diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 4278b496a..58cb906bd 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -858,7 +858,7 @@ void Interface::handle_link_state() try { attach_to_domain_finish(); - /* if the wholde domain became down, discard IP config */ + /* if the whole domain is down, discard IP config */ Domain &domain_ = domain(); if (!link_state() && domain_.ip_config().valid) { domain_.interfaces().for_each([&] (Interface &interface) { @@ -870,6 +870,10 @@ void Interface::handle_link_state() } catch (Domain::Ip_config_static) { } catch (Keep_ip_config) { } + + /* force report if configured */ + try { _config().report().handle_link_state(); } + catch (Pointer<Report>::Invalid) { } } @@ -1956,6 +1960,7 @@ void Interface::handle_config_3() /* if the IP configs differ, detach completely from the IP config */ if (old_domain.ip_config() != new_domain.ip_config()) { detach_from_ip_config(); + attach_to_domain_finish(); return; } /* if there was/is no IP config, there is nothing more to update */ @@ -2016,21 +2021,28 @@ Interface::~Interface() void Interface::report(Genode::Xml_generator &xml) { - bool const stats = _config().report().stats(); - if (stats) { - xml.node("interface", [&] () { - bool empty = true; - xml.attribute("label", _policy.label()); - try { _policy.report(xml); empty = false; } catch (Report::Empty) { } + xml.node("interface", [&] () { + bool empty { true }; + xml.attribute("label", _policy.label()); + if (_config().report().link_state()) { + xml.attribute("link_state", link_state()); + empty = false; + } + if (_config().report().stats()) { + try { + _policy.report(xml); + empty = false; + } + catch (Report::Empty) { } try { xml.node("tcp-links", [&] () { _tcp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } try { xml.node("udp-links", [&] () { _udp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } try { xml.node("icmp-links", [&] () { _icmp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } try { xml.node("arp-waiters", [&] () { _arp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } try { xml.node("dhcp-allocations", [&] () { _dhcp_stats.report(xml); }); empty = false; } catch (Report::Empty) { } - if (empty) { throw Report::Empty(); } - }); - } + } + if (empty) { throw Report::Empty(); } + }); } diff --git a/repos/os/src/server/nic_router/main.cc b/repos/os/src/server/nic_router/main.cc index 95885acb4..bad4c7994 100644 --- a/repos/os/src/server/nic_router/main.cc +++ b/repos/os/src/server/nic_router/main.cc @@ -74,6 +74,8 @@ Net::Main::Main(Env &env) : _env(env) void Net::Main::_handle_config() { + _config().stop_reporting(); + _config_rom.update(); Configuration &old_config = _config(); Configuration &new_config = *new (_heap) @@ -87,6 +89,8 @@ void Net::Main::_handle_config() _for_each_interface([&] (Interface &intf) { intf.handle_config_3(); }); destroy(_heap, &old_config); + + _config().start_reporting(); } diff --git a/repos/os/src/server/nic_router/report.cc b/repos/os/src/server/nic_router/report.cc index 0180e7d84..ca3400700 100644 --- a/repos/os/src/server/nic_router/report.cc +++ b/repos/os/src/server/nic_router/report.cc @@ -28,25 +28,28 @@ Net::Report::Report(bool const &verbose, Pd_session &pd, Reporter &reporter) : - _verbose { verbose }, - _config { node.attribute_value("config", true) }, - _config_triggers { node.attribute_value("config_triggers", false) }, - _bytes { node.attribute_value("bytes", true) }, - _stats { node.attribute_value("stats", true) }, - _quota { node.attribute_value("quota", true) }, - _shared_quota { shared_quota }, - _pd { pd }, - _reporter { reporter }, - _domains { domains }, - _timeout { timer, *this, &Report::_handle_report_timeout, - read_sec_attr(node, "interval_sec", 5) } -{ - _reporter.enabled(true); -} + _verbose { verbose }, + _config { node.attribute_value("config", true) }, + _config_triggers { node.attribute_value("config_triggers", false) }, + _bytes { node.attribute_value("bytes", true) }, + _stats { node.attribute_value("stats", true) }, + _link_state { node.attribute_value("link_state", false) }, + _link_state_triggers { node.attribute_value("link_state_triggers", false) }, + _quota { node.attribute_value("quota", true) }, + _shared_quota { shared_quota }, + _pd { pd }, + _reporter { reporter }, + _domains { domains }, + _timeout { timer, *this, &Report::_handle_report_timeout, + read_sec_attr(node, "interval_sec", 5) } +{ } void Net::Report::_report() { + if (!_reporter.enabled()) { + return; + } try { Reporter::Xml_generator xml(_reporter, [&] () { if (_quota) { @@ -86,3 +89,11 @@ void Net::Report::handle_config() _report(); } + +void Net::Report::handle_link_state() +{ + if (!_link_state_triggers) { + return; } + + _report(); +} diff --git a/repos/os/src/server/nic_router/report.h b/repos/os/src/server/nic_router/report.h index 1a7bc6a12..9dcae3cd0 100644 --- a/repos/os/src/server/nic_router/report.h +++ b/repos/os/src/server/nic_router/report.h @@ -48,6 +48,8 @@ class Net::Report bool const _config_triggers; bool const _bytes; bool const _stats; + bool const _link_state; + bool const _link_state_triggers; bool const _quota; Quota const &_shared_quota; Genode::Pd_session &_pd; @@ -73,14 +75,18 @@ class Net::Report void handle_config(); + void handle_link_state(); + /*************** ** Accessors ** ***************/ - bool config() const { return _config; } - bool bytes() const { return _bytes; } - bool stats() const { return _stats; } + bool config() const { return _config; } + bool bytes() const { return _bytes; } + bool stats() const { return _stats; } + bool link_state() const { return _link_state; } + bool link_state_triggers() const { return _link_state_triggers; } }; #endif /* _REPORT_H_ */ diff --git a/repos/os/src/server/nic_router/uplink.h b/repos/os/src/server/nic_router/uplink.h index 9186eb93b..06a8760f8 100644 --- a/repos/os/src/server/nic_router/uplink.h +++ b/repos/os/src/server/nic_router/uplink.h @@ -104,8 +104,8 @@ class Net::Uplink_interface_base : public Interface_policy { private: - Const_reference<Domain_name> _domain_name; - Genode::Session_label const &_label; + Const_reference<Domain_name> _domain_name; + Genode::Session_label const _label; /*************************** diff --git a/repos/os/src/server/nitpicker/user_state.cc b/repos/os/src/server/nitpicker/user_state.cc index 0ab78d9fa..bd8f329e1 100644 --- a/repos/os/src/server/nitpicker/user_state.cc +++ b/repos/os/src/server/nitpicker/user_state.cc @@ -152,6 +152,9 @@ void User_state::_handle_input_event(Input::Event ev) View_owner *global_receiver = nullptr; + if (_mouse_button(keycode)) + _clicked_count++; + /* update focused session */ if (_mouse_button(keycode) && _hovered @@ -282,6 +285,7 @@ User_state::handle_input_events(Input::Event const * const ev_buf, View_owner const * const old_focused = _focused; View_owner const * const old_input_receiver = _input_receiver; View_owner const * const old_last_clicked = _last_clicked; + unsigned const old_clicked_count = _clicked_count; bool button_activity = false; @@ -333,6 +337,21 @@ User_state::handle_input_events(Input::Event const * const ev_buf, _apply_pending_focus_change(); + /* + * Determine condition for generating an updated "clicked" report + */ + bool const click_occurred = (old_clicked_count != _clicked_count); + + bool const clicked_report_up_to_date = + (_last_clicked == old_last_clicked) && !_last_clicked_redeliver; + + bool const last_clicked_changed = (click_occurred && !clicked_report_up_to_date); + + if (last_clicked_changed) { + _last_clicked_version++; + _last_clicked_redeliver = false; + } + return { .hover_changed = _hovered != old_hovered, .focus_changed = (_focused != old_focused) || @@ -341,7 +360,7 @@ User_state::handle_input_events(Input::Event const * const ev_buf, .button_activity = button_activity, .motion_activity = (_pointer_pos != old_pointer_pos), .key_pressed = _key_pressed(), - .last_clicked_changed = (_last_clicked != old_last_clicked) + .last_clicked_changed = last_clicked_changed }; } @@ -383,6 +402,8 @@ void User_state::report_last_clicked_view_owner(Xml_generator &xml) const { if (_last_clicked) _last_clicked->report(xml); + + xml.attribute("version", _last_clicked_version); } diff --git a/repos/os/src/server/nitpicker/user_state.h b/repos/os/src/server/nitpicker/user_state.h index ecb33a98b..35d93a5c8 100644 --- a/repos/os/src/server/nitpicker/user_state.h +++ b/repos/os/src/server/nitpicker/user_state.h @@ -95,6 +95,28 @@ class Nitpicker::User_state */ View_owner *_last_clicked = nullptr; + /** + * Number of clicks, used to detect whether a focus-relevant click + * happened during '_handle_input_event'. + */ + unsigned _clicked_count = 0; + + /** + * Version supplement for the "clicked" report + * + * The value allows the receiver of the report to detect the situation + * where two consecutive clicks refer to the same client but both + * events require a distinct focus response, i.e., if the focus (focus + * ROM) was changed in-between both clicks by other means than a click. + */ + unsigned _last_clicked_version = 0; + + /* + * If set, a "clicked" report is generated even if the clicked-on view + * is the same as the previously clicked-on view. + */ + bool _last_clicked_redeliver = false; + /** * Array for tracking the state of each key */ @@ -148,6 +170,14 @@ class Nitpicker::User_state if (_focused != _next_focused) { _focused = _next_focused; + /* + * Enforce the generation of a new "clicked" report for any click + * that follows a focus change. This is needed in situations + * where the focus is defined by clicks as well as other means + * (e.g., the appearance of a lock screen). + */ + _last_clicked_redeliver = true; + /* propagate changed focus to view stack */ if (_focused) _focus.assign(*_focused); diff --git a/repos/os/src/server/ram_block/main.cc b/repos/os/src/server/ram_block/main.cc index 4ef851fff..b14605668 100644 --- a/repos/os/src/server/ram_block/main.cc +++ b/repos/os/src/server/ram_block/main.cc @@ -174,7 +174,8 @@ struct Main size = config.attribute_value("size", Number_of_bytes()); } - block_size = config.attribute_value("block_size", block_size); + block_size = config.attribute_value("block_size", + Number_of_bytes(block_size)); } Block::Driver *create() override diff --git a/repos/os/src/server/ram_fs/directory.h b/repos/os/src/server/ram_fs/directory.h index 349d718d0..8b4919b92 100644 --- a/repos/os/src/server/ram_fs/directory.h +++ b/repos/os/src/server/ram_fs/directory.h @@ -181,7 +181,8 @@ class Ram_fs::Directory : public Node return static_cast<Directory *>(lookup(path, true)); } - size_t read(char *dst, size_t len, seek_off_t seek_offset) override + size_t read(char *dst, size_t len, seek_off_t seek_offset, + Session_writeable writeable) override { using File_system::Directory_entry; @@ -203,15 +204,25 @@ class Ram_fs::Directory : public Node if (!node) return 0; - Directory_entry *e = (Directory_entry *)(dst); + auto type = [&] () + { + using Node_type = File_system::Node_type; - e->inode = node->inode(); + if (dynamic_cast<Directory *>(node)) return Node_type::DIRECTORY; + if (dynamic_cast<Symlink *>(node)) return Node_type::SYMLINK; + return Node_type::CONTINUOUS_FILE; + }; - if (dynamic_cast<File *>(node)) e->type = Directory_entry::TYPE_FILE; - if (dynamic_cast<Directory *>(node)) e->type = Directory_entry::TYPE_DIRECTORY; - if (dynamic_cast<Symlink *>(node)) e->type = Directory_entry::TYPE_SYMLINK; + Directory_entry &e = *(Directory_entry *)(dst); - strncpy(e->name, node->name(), sizeof(e->name)); + e = { + .inode = node->inode(), + .type = type(), + .rwx = { .readable = true, + .writeable = writeable == Session_writeable::WRITEABLE, + .executable = true }, + .name = { node->name() } + }; return sizeof(Directory_entry); } @@ -222,13 +233,17 @@ class Ram_fs::Directory : public Node return 0; } - Status status() override + Status status(Session_writeable writeable) override { - Status s; - s.inode = inode(); - s.size = _num_entries * sizeof(File_system::Directory_entry); - s.mode = File_system::Status::MODE_DIRECTORY; - return s; + return { + .size = _num_entries * sizeof(File_system::Directory_entry), + .type = File_system::Node_type::DIRECTORY, + .rwx = { .readable = true, + .writeable = (writeable == Session_writeable::WRITEABLE), + .executable = true }, + .inode = inode(), + .modification_time = modification_time() + }; } }; diff --git a/repos/os/src/server/ram_fs/file.h b/repos/os/src/server/ram_fs/file.h index 87e837ab6..cf938a85a 100644 --- a/repos/os/src/server/ram_fs/file.h +++ b/repos/os/src/server/ram_fs/file.h @@ -49,7 +49,7 @@ class Ram_fs::File : public Node File(Allocator &alloc, char const *name) : _chunk(alloc, 0), _length(0) { Node::name(name); } - size_t read(char *dst, size_t len, seek_off_t seek_offset) override + size_t read(char *dst, size_t len, seek_off_t seek_offset, Session_writeable) override { file_size_t const chunk_used_size = _chunk.used_size(); @@ -108,13 +108,17 @@ class Ram_fs::File : public Node return len; } - Status status() override + Status status(Session_writeable writeable) override { - Status s; - s.inode = inode(); - s.size = _length; - s.mode = File_system::Status::MODE_FILE; - return s; + return { + .size = _length, + .type = File_system::Node_type::CONTINUOUS_FILE, + .rwx = { .readable = true, + .writeable = (writeable == Session_writeable::WRITEABLE), + .executable = true }, + .inode = inode(), + .modification_time = modification_time() + }; } void truncate(file_size_t size) override diff --git a/repos/os/src/server/ram_fs/main.cc b/repos/os/src/server/ram_fs/main.cc index b57338091..782e3b73b 100644 --- a/repos/os/src/server/ram_fs/main.cc +++ b/repos/os/src/server/ram_fs/main.cc @@ -51,7 +51,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object Genode::Allocator &_alloc; Directory &_root; Id_space<File_system::Node> _open_node_registry { }; - bool _writable; + Session_writeable const _writeable; Signal_handler<Session_component> _process_packet_handler; @@ -81,10 +81,10 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object if (!node.valid()) break; res_length = node->read((char *)tx_sink()->packet_content(packet), - length, packet.position()); + length, packet.position(), _writeable); /* read data or EOF is a success */ - succeeded = res_length || (packet.position() >= node->status().size); + succeeded = res_length || (packet.position() >= node->status(_writeable).size); } break; @@ -92,7 +92,11 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object if (packet.length() <= packet.size()) { Locked_ptr<Node> node { open_node.node() }; if (!node.valid()) - break; + break; + + if (_writeable == Session_writeable::READ_ONLY) + break; + res_length = node->write((char const *)tx_sink()->packet_content(packet), length, packet.position()); @@ -108,6 +112,19 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object open_node.mark_as_written(); break; + case Packet_descriptor::WRITE_TIMESTAMP: { + Locked_ptr<Node> node { open_node.node() }; + if (!node.valid()) + break; + + if (_writeable == Session_writeable::WRITEABLE) + packet.with_timestamp([&] (File_system::Timestamp const time) { + node->update_modification_time(time); + succeeded = true; + }); + break; + } + case Packet_descriptor::CONTENT_CHANGED: Genode::error("CONTENT_CHANGED packets from clients have no effect"); return; @@ -196,14 +213,14 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object Session_component(size_t tx_buf_size, Genode::Entrypoint &ep, Genode::Ram_allocator &ram, Genode::Region_map &rm, Genode::Allocator &alloc, - Directory &root, bool writable) + Directory &root, Session_writeable writeable) : Session_rpc_object(ram.alloc(tx_buf_size), rm, ep.rpc_ep()), _ep(ep), _ram(ram), _alloc(alloc), _root(root), - _writable(writable), + _writeable(writeable), _process_packet_handler(_ep, *this, &Session_component::_process_packets) { /* @@ -219,6 +236,9 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object */ ~Session_component() { + while (_open_node_registry.apply_any<Open_node>([&] (Open_node &node) { + destroy(_alloc, &node); })) { } + Dataspace_capability ds = tx_sink()->dataspace(); _ram.free(static_cap_cast<Ram_dataspace>(ds)); } @@ -241,13 +261,13 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object if (!dir.valid()) throw Unavailable(); - if (!_writable) + if (_writeable == Session_writeable::READ_ONLY) if (mode != STAT_ONLY && mode != READ_ONLY) throw Permission_denied(); if (create) { - if (!_writable) + if (_writeable == Session_writeable::READ_ONLY) throw Permission_denied(); if (dir->has_sub_node_unsynchronized(name.string())) @@ -293,7 +313,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object if (create) { - if (!_writable) + if (_writeable == Session_writeable::READ_ONLY) throw Permission_denied(); if (dir->has_sub_node_unsynchronized(name.string())) @@ -336,7 +356,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object if (create) { - if (!_writable) + if (_writeable == Session_writeable::READ_ONLY) throw Permission_denied(); if (!path.valid_string()) @@ -412,8 +432,8 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object auto status_fn = [&] (Open_node &open_node) { Locked_ptr<Node> node { open_node.node() }; if (!node.valid()) - throw Unavailable(); - return node->status(); + throw Unavailable(); + return node->status(_writeable); }; try { @@ -430,7 +450,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object if (!valid_name(name.string())) throw Invalid_name(); - if (!_writable) + if (_writeable == Session_writeable::READ_ONLY) throw Permission_denied(); auto unlink_fn = [&] (Open_node &open_node) { @@ -456,7 +476,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object void truncate(File_handle file_handle, file_size_t size) override { - if (!_writable) + if (_writeable == Session_writeable::READ_ONLY) throw Permission_denied(); auto truncate_fn = [&] (Open_node &open_node) { @@ -477,7 +497,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object void move(Dir_handle from_dir_handle, Name const &from_name, Dir_handle to_dir_handle, Name const &to_name) override { - if (!_writable) + if (_writeable == Session_writeable::READ_ONLY) throw Permission_denied(); if (!valid_name(from_name.string())) @@ -630,7 +650,9 @@ class Ram_fs::Root : public Root_component<Session_component> } return new (md_alloc()) Session_component(tx_buf_size, _ep, _ram, _rm, _alloc, - *session_root_dir, writeable); + *session_root_dir, + writeable ? Session_writeable::WRITEABLE + : Session_writeable::READ_ONLY); } public: diff --git a/repos/os/src/server/ram_fs/node.h b/repos/os/src/server/ram_fs/node.h index 6ccd1af32..d044a6a72 100644 --- a/repos/os/src/server/ram_fs/node.h +++ b/repos/os/src/server/ram_fs/node.h @@ -23,9 +23,12 @@ namespace Ram_fs { using namespace Genode; using File_system::seek_off_t; using File_system::Status; + using File_system::Timestamp; class Node; class File; class Symlink; + + enum class Session_writeable { READ_ONLY, WRITEABLE }; } @@ -48,6 +51,7 @@ class Ram_fs::Node : public File_system::Node_base, int _ref_count; Name _name; unsigned long const _inode; + Timestamp _modification_time { }; /** * Generate unique inode number @@ -62,7 +66,10 @@ class Ram_fs::Node : public File_system::Node_base, Node() : _ref_count(0), _inode(_unique_inode()) - { _name[0] = 0; } + { + _name[0] = 0; + _modification_time.value = File_system::Timestamp::INVALID; + } virtual ~Node() { lock_for_destruction(); } @@ -74,10 +81,21 @@ class Ram_fs::Node : public File_system::Node_base, */ void name(char const *name) { strncpy(_name, name, sizeof(_name)); } - virtual size_t read(char *dst, size_t len, seek_off_t) = 0; + void update_modification_time(Timestamp const time) + { + _modification_time = time; + } + + Timestamp modification_time() const { return _modification_time; } + + /* + * 'Session_writeable' is supplied to the 'read' method to reflect the + * writeability in directory entries read from 'Directory' nodes. + */ + virtual size_t read(char *dst, size_t len, seek_off_t, Session_writeable) = 0; virtual size_t write(char const *src, size_t len, seek_off_t) = 0; - virtual Status status() = 0; + virtual Status status(Session_writeable) = 0; /* File functionality */ diff --git a/repos/os/src/server/ram_fs/symlink.h b/repos/os/src/server/ram_fs/symlink.h index ef3376238..099afe7d1 100644 --- a/repos/os/src/server/ram_fs/symlink.h +++ b/repos/os/src/server/ram_fs/symlink.h @@ -31,7 +31,7 @@ class Ram_fs::Symlink : public Node Symlink(char const *name): _len(0) { Node::name(name); } - size_t read(char *dst, size_t len, seek_off_t seek_offset) override + size_t read(char *dst, size_t len, seek_off_t seek_offset, Session_writeable) override { size_t count = min(len, _len-seek_offset); Genode::memcpy(dst, _link_to+seek_offset, count); @@ -65,13 +65,17 @@ class Ram_fs::Symlink : public Node return consumed_len; } - Status status() override + Status status(Session_writeable writeable) override { - Status s; - s.inode = inode(); - s.size = _len; - s.mode = File_system::Status::MODE_SYMLINK; - return s; + return { + .size = _len, + .type = File_system::Node_type::SYMLINK, + .rwx = { .readable = true, + .writeable = (writeable == Session_writeable::WRITEABLE), + .executable = true }, + .inode = inode(), + .modification_time = modification_time() + }; } }; diff --git a/repos/os/src/server/vfs/main.cc b/repos/os/src/server/vfs/main.cc index dd6b2d94a..6764b5a73 100644 --- a/repos/os/src/server/vfs/main.cc +++ b/repos/os/src/server/vfs/main.cc @@ -2,6 +2,7 @@ * \brief VFS File_system server * \author Emery Hemingway * \author Christian Helmuth + * \author Norman Feske * \date 2015-08-16 */ @@ -25,7 +26,7 @@ #include <util/fifo.h> #include <vfs/simple_env.h> -/* Local includes */ +/* local includes */ #include "assert.h" #include "node.h" @@ -39,7 +40,8 @@ namespace Vfs_server { class Vfs_env; class Root; - typedef Genode::Fifo<Session_component> Session_queue; + typedef Genode::Fifo<Session_component> Session_queue; + typedef Genode::Entrypoint::Io_progress_handler Io_progress_handler; /** * Convenience utities for parsing quotas @@ -82,7 +84,8 @@ class Vfs_server::Session_resources class Vfs_server::Session_component : private Session_resources, public ::File_system::Session_rpc_object, - private Session_queue::Element + private Session_queue::Element, + private Watch_node::Watch_node_response_handler { friend Session_queue; @@ -92,19 +95,21 @@ class Vfs_server::Session_component : private Session_resources, Genode::Entrypoint &_ep; + Io_progress_handler &_io_progress_handler; + Packet_stream &_stream { *tx_sink() }; - /* global queue of nodes to process after an I/O signal */ - Node_queue &_pending_nodes; + /* nodes of this session with active jobs or pending acknowledgements */ + Node_queue _active_nodes { }; - /* global queue of sessions for which packets await progress */ - Session_queue &_pending_sessions; + /* global queue of sessions with active jobs */ + Session_queue &_active_sessions; /* collection of open nodes local to this session */ Node_space _node_space { }; - Genode::Signal_handler<Session_component> _process_packet_handler { - _ep, *this, &Session_component::_process_packets }; + Genode::Signal_handler<Session_component> _packet_stream_handler { + _ep, *this, &Session_component::_handle_packet_stream }; /* * The root node needs be allocated with the session struct @@ -114,7 +119,7 @@ class Vfs_server::Session_component : private Session_resources, Genode::Session_label const _label; - bool const _writable; + bool const _writeable; /**************************** @@ -160,104 +165,220 @@ class Vfs_server::Session_component : private Session_resources, ** Packet-stream processing ** ******************************/ - /** - * Attempt to process the head of the packet queue - * - * Return true if the packet can be popped from the - * queue or false if the the packet cannot be processed - * or further queued. - */ - bool _process_packet() + bool _try_import_jobs_from_submit_queue() { - /* leave the packet queued so that it cannot leak */ - Packet_descriptor packet = _stream.peek_packet(); + bool overall_progress = false; - /* assume failure by default */ - packet.succeeded(false); + for (;;) { - if ((packet.length() > packet.size())) { - /* not a valid packet */ - _stream.acknowledge_packet(packet); - return true; + bool progress_in_iteration = false; + + if (!_stream.packet_avail()) + break; + + /* ensure that ack for one malformed packet can be returned */ + if (!_stream.ready_to_ack()) + break; + + Packet_descriptor packet = _stream.peek_packet(); + + auto drop_packet_from_submit_queue = [&] () + { + _stream.get_packet(); + + overall_progress = true; + progress_in_iteration = true; + }; + + auto consume_and_ack_invalid_packet = [&] () + { + drop_packet_from_submit_queue(); + packet.succeeded(false); + _stream.acknowledge_packet(packet); + + overall_progress = true; + progress_in_iteration = true; + }; + + /* test for invalid packet */ + if (packet.length() > packet.size()) { + consume_and_ack_invalid_packet(); + continue; + } + + try { + _apply(packet.handle(), [&] (Io_node &node) { + + if (!node.job_acceptable()) + return; + + Payload_ptr payload_ptr { _stream.packet_content(packet) }; + + switch (node.submit_job(packet, payload_ptr)) { + + case Node::Submit_result::ACCEPTED: + if (!node.enqueued()) + _active_nodes.enqueue(node); + drop_packet_from_submit_queue(); + break; + + case Node::Submit_result::DENIED: + consume_and_ack_invalid_packet(); + break; + + case Node::Submit_result::STALLED: + /* keep request packet in submit queue */ + break; + } + }); + } + catch (File_system::Invalid_handle) { + consume_and_ack_invalid_packet(); } + + if (!progress_in_iteration) + break; } - - bool handle_invalid = true; - bool result = true; - - try { - _apply(packet.handle(), [&] (Io_node &node) { - handle_invalid = false; - result = node.process_packet(packet); - }); - } - catch (::File_system::Invalid_handle) { } - - /* send the packet back if the handle is missing */ - if (handle_invalid) - _stream.acknowledge_packet(packet); - - return (handle_invalid || result); + return overall_progress; } - protected: - - friend Vfs_server::Root; - using Session_queue::Element::enqueued; - - /** - * Called by the global Io_progress_handler as - * well as the local signal handler - * - * Return true if the packet queue was emptied - */ - bool process_packets() + void _execute_jobs() { - /** - * Process packets in batches, otherwise a client that - * submits packets as fast as they are processed will - * starve the signal handler. - */ - int quantum = TX_QUEUE_SIZE; + /* nodes with jobs that cannot make progress right now */ + Node_queue requeued_nodes { }; + + _active_nodes.dequeue_all([&] (Node &node) { + + if (node.job_in_progress()) + node.execute_job(); + + requeued_nodes.enqueue(node); + }); + + _active_nodes = requeued_nodes; + } + + bool _try_acknowledge_jobs() + { + bool overall_progress = false; + + for (;;) { + if (!_stream.ready_to_ack()) + break; + + if (_active_nodes.empty()) + break; + + bool progress_in_iteration = false; + + _active_nodes.dequeue([&] (Node &node) { - while (_stream.packet_avail()) { - if (_process_packet()) { /* - * the packet was rejected or associated with - * a handle, pop it from the packet queue + * Deliver only one acknowledgement per iteration to + * re-check the 'ready_to_ack' condition for each + * acknowledgement. */ - _stream.get_packet(); - } else { - /* no progress */ - return false; - } + if (node.acknowledgement_pending()) { + _stream.acknowledge_packet(node.dequeue_acknowledgement()); + progress_in_iteration = true; + } - if (--quantum == 0) { - /* come back to this later */ - Genode::Signal_transmitter(_process_packet_handler).submit(); - return false; - } + /* + * If there is still another acknowledgement pending, keep + * the node enqueud to process it in the next iteration. + * This can happen if there is a READ_READY acknowledgement + * in addition to the acknowledgement of an operation. + */ + if (node.active()) + _active_nodes.enqueue(node); + }); + + overall_progress |= progress_in_iteration; + + if (!progress_in_iteration) + break; } - return true; + return overall_progress; + } + + public: + + enum class Process_packets_result { NONE, PROGRESS, TOO_MUCH_PROGRESS }; + + /** + * Called by the global Io_progress_handler as well as the + * session-local packet-stream handler + * + * \return true if progress was made + */ + Process_packets_result process_packets() + { + bool overall_progress = false; + + /* + * Upper bound for the number of iterations. When reached, + * cancel the handler and trigger the re-execution via a local + * signal. This gives the config handler and the RPC functions + * a chance to run in situations when the submit queue of the + * packet stream is always saturated. + */ + unsigned iterations = 200; + + for (;;) { + + if (--iterations == 0) + return Process_packets_result::TOO_MUCH_PROGRESS; + + /* true if progress can be made in this iteration */ + bool progress_in_iteration = false; + + progress_in_iteration |= _try_import_jobs_from_submit_queue(); + + _execute_jobs(); + + progress_in_iteration |= _try_acknowledge_jobs(); + + if (!progress_in_iteration) + break; + + overall_progress |= progress_in_iteration; + } + return overall_progress ? Process_packets_result::PROGRESS + : Process_packets_result::NONE; + } + + bool no_longer_active() const + { + return Session_queue::Element::enqueued() && _active_nodes.empty(); + } + + bool no_longer_idle() const + { + return !Session_queue::Element::enqueued() && !_active_nodes.empty(); } private: /** - * Called by signal handler + * Signal handler called for session-local packet-stream signals */ - void _process_packets() + void _handle_packet_stream() { - bool done = process_packets(); + Process_packets_result const progress = process_packets(); - if (done && enqueued()) { - /* this session is idle */ - _pending_sessions.remove(*this); - } else - if (!done && !enqueued()) { - /* this session needs unblocking */ - _pending_sessions.enqueue(*this); - } + if (no_longer_idle()) + _active_sessions.enqueue(*this); + + if (progress == Process_packets_result::TOO_MUCH_PROGRESS) + Genode::Signal_transmitter(_packet_stream_handler).submit(); + + /* + * The activity of the session may have an unblocking effect on + * other sessions. So we call the global 'Io_progress_handler' to + * attempt the packet processing of all active sessions. + */ + if (progress == Process_packets_result::PROGRESS) + _io_progress_handler.handle_io_progress(); } /** @@ -294,38 +415,51 @@ class Vfs_server::Session_component : private Session_resources, destroy(_alloc, &node); } + /** + * Watch_node::Watch_node_response_handler interface + */ + void handle_watch_node_response(Watch_node &node) override + { + if (!node.enqueued()) + _active_nodes.enqueue(node); + + /* + * The acknowledgement and dequeuing will be delivered by + * 'Session_component::_try_acknowledge_jobs'. Mark the session as + * active to consider it for the acknowledgement handling. + */ + if (!enqueued()) + _active_sessions.enqueue(*this); + } + public: /** * Constructor */ - Session_component(Genode::Env &env, - char const *label, - Genode::Ram_quota ram_quota, - Genode::Cap_quota cap_quota, - size_t tx_buf_size, - Vfs::File_system &vfs, - Node_queue &pending_nodes, - Session_queue &pending_sessions, - char const *root_path, - bool writable) + Session_component(Genode::Env &env, + char const *label, + Genode::Ram_quota ram_quota, + Genode::Cap_quota cap_quota, + size_t tx_buf_size, + Vfs::File_system &vfs, + Session_queue &active_sessions, + Io_progress_handler &io_progress_handler, + char const *root_path, + bool writeable) : Session_resources(env.pd(), env.rm(), ram_quota, cap_quota, tx_buf_size), Session_rpc_object(_packet_ds.cap(), env.rm(), env.ep().rpc_ep()), _vfs(vfs), _ep(env.ep()), - _pending_nodes(pending_nodes), - _pending_sessions(pending_sessions), + _io_progress_handler(io_progress_handler), + _active_sessions(active_sessions), _root_path(root_path), _label(label), - _writable(writable) + _writeable(writeable) { - /* - * Register an I/O signal handler for - * packet-avail and ready-to-ack signals. - */ - _tx.sigh_packet_avail(_process_packet_handler); - _tx.sigh_ready_to_ack(_process_packet_handler); + _tx.sigh_packet_avail(_packet_stream_handler); + _tx.sigh_ready_to_ack(_packet_stream_handler); } /** @@ -338,7 +472,7 @@ class Vfs_server::Session_component : private Session_resources, _close(node); })) { } if (enqueued()) - _pending_sessions.remove(*this); + _active_sessions.remove(*this); } /** @@ -356,7 +490,7 @@ class Vfs_server::Session_component : private Session_resources, Dir_handle dir(::File_system::Path const &path, bool create) override { - if (create && (!_writable)) + if (create && (!_writeable)) throw Permission_denied(); char const *path_str = path.string(); @@ -373,19 +507,22 @@ class Vfs_server::Session_component : private Session_resources, if (!create && !_vfs.directory(path_str)) throw Lookup_failed(); - Directory *dir; - try { dir = new (_alloc) Directory(_node_space, _vfs, _alloc, - _pending_nodes, _stream, - path_str, create); } - catch (Out_of_memory) { throw Out_of_ram(); } + typedef Directory::Session_writeable Writeable; - return Dir_handle(dir->id().value); + Directory &dir = *new (_alloc) + Directory(_node_space, _vfs, _alloc, path_str, create, + _writeable ? Writeable::WRITEABLE : Writeable::READ_ONLY); + + if (create) + _io_progress_handler.handle_io_progress(); + + return Dir_handle(dir.id().value); } File_handle file(Dir_handle dir_handle, Name const &name, Mode fs_mode, bool create) override { - if ((create || (fs_mode & WRITE_ONLY)) && (!_writable)) + if ((create || (fs_mode & WRITE_ONLY)) && (!_writeable)) throw Permission_denied(); return _apply(dir_handle, [&] (Directory &dir) { @@ -400,15 +537,15 @@ class Vfs_server::Session_component : private Session_resources, Symlink_handle symlink(Dir_handle dir_handle, Name const &name, bool create) override { - if (create && !_writable) throw Permission_denied(); + if (create && !_writeable) throw Permission_denied(); return _apply(dir_handle, [&] (Directory &dir) { char const *name_str = name.string(); _assert_valid_name(name_str); - return Symlink_handle {dir.symlink( - _node_space, _vfs, _alloc, name_str, - _writable ? READ_WRITE : READ_ONLY, create).value + return Symlink_handle { + dir.symlink(_node_space, _vfs, _alloc, name_str, + _writeable ? READ_WRITE : READ_ONLY, create).value }; }); } @@ -420,18 +557,14 @@ class Vfs_server::Session_component : private Session_resources, _assert_valid_path(path_str); /* re-root the path */ - Path sub_path(path_str+1, _root_path.base()); + Path const sub_path(path_str + 1, _root_path.base()); path_str = sub_path.base(); if (sub_path != "/" && !_vfs.leaf_path(path_str)) throw Lookup_failed(); - Node *node; + Node &node = *new (_alloc) Node(_node_space, path_str); - try { node = new (_alloc) Node(_node_space, path_str, - _pending_nodes, _stream); } - catch (Out_of_memory) { throw Out_of_ram(); } - - return Node_handle { node->id().value }; + return Node_handle { node.id().value }; } Watch_handle watch(::File_system::Path const &path) override @@ -441,7 +574,7 @@ class Vfs_server::Session_component : private Session_resources, _assert_valid_path(path_str); /* re-root the path */ - Path sub_path(path_str+1, _root_path.base()); + Path const sub_path(path_str + 1, _root_path.base()); path_str = sub_path.base(); Vfs::Vfs_watch_handle *vfs_handle = nullptr; @@ -458,26 +591,40 @@ class Vfs_server::Session_component : private Session_resources, throw Out_of_caps(); } - Node *node; - try { node = new (_alloc) - Watch_node(_node_space, path_str, *vfs_handle, - _pending_nodes, _stream); } - catch (Out_of_memory) { throw Out_of_ram(); } + Node &node = *new (_alloc) + Watch_node(_node_space, path_str, *vfs_handle, *this); - return Watch_handle { node->id().value }; + return Watch_handle { node.id().value }; } void close(Node_handle handle) override { /* - * churn the packet queue so that any pending - * packets on this handle are processed + * Churn the packet queue so that any pending packets on this + * handle are processed. */ - process_packets(); + _io_progress_handler.handle_io_progress(); - try { _apply_node(handle, [&] (Node &node) { - _close(node); }); } + /* + * Closing a written file or symlink may have triggered a watch handler. + */ + bool node_modified = false; + + try { + _apply_node(handle, [&] (Node &node) { + + if (node.enqueued()) + _active_nodes.remove(node); + + node_modified = node.modified(); + + _close(node); + }); + } catch (::File_system::Invalid_handle) { } + + if (node_modified) + _io_progress_handler.handle_io_progress(); } Status status(Node_handle node_handle) override @@ -485,40 +632,60 @@ class Vfs_server::Session_component : private Session_resources, ::File_system::Status fs_stat; _apply_node(node_handle, [&] (Node &node) { + Directory_service::Stat vfs_stat; if (_vfs.stat(node.path(), vfs_stat) != Directory_service::STAT_OK) throw Invalid_handle(); - fs_stat.inode = vfs_stat.inode; + auto fs_node_type = [&] (Vfs::Node_type type) + { + using To = ::File_system::Node_type; - switch (vfs_stat.mode & ( - Directory_service::STAT_MODE_DIRECTORY | - Directory_service::STAT_MODE_SYMLINK | - ::File_system::Status::MODE_FILE)) { + switch (type) { + case Vfs::Node_type::DIRECTORY: return To::DIRECTORY; + case Vfs::Node_type::SYMLINK: return To::SYMLINK; + case Vfs::Node_type::CONTINUOUS_FILE: return To::CONTINUOUS_FILE; + case Vfs::Node_type::TRANSACTIONAL_FILE: return To::TRANSACTIONAL_FILE; + }; + return To::CONTINUOUS_FILE; + }; - case Directory_service::STAT_MODE_DIRECTORY: - fs_stat.mode = ::File_system::Status::MODE_DIRECTORY; - fs_stat.size = _vfs.num_dirent(node.path()) * sizeof(Directory_entry); - return; + auto fs_node_size = [&] (Vfs::Directory_service::Stat const &vfs_stat) + { + switch (vfs_stat.type) { + case Vfs::Node_type::DIRECTORY: + return _vfs.num_dirent(node.path()) * sizeof(Directory_entry); - case Directory_service::STAT_MODE_SYMLINK: - fs_stat.mode = ::File_system::Status::MODE_SYMLINK; - break; + case Vfs::Node_type::SYMLINK: + return 0ULL; - default: /* Directory_service::STAT_MODE_FILE */ - fs_stat.mode = ::File_system::Status::MODE_FILE; - break; - } + case Vfs::Node_type::CONTINUOUS_FILE: + case Vfs::Node_type::TRANSACTIONAL_FILE: + return vfs_stat.size; + }; + return 0ULL; + }; - fs_stat.size = vfs_stat.size; + fs_stat = ::File_system::Status { + .size = fs_node_size(vfs_stat), + .type = fs_node_type(vfs_stat.type), + .rwx = { + .readable = vfs_stat.rwx.readable, + .writeable = vfs_stat.rwx.writeable && _writeable, + .executable = vfs_stat.rwx.executable }, + + .inode = vfs_stat.inode, + .modification_time = { vfs_stat.modification_time.value } + }; }); + return fs_stat; } void unlink(Dir_handle dir_handle, Name const &name) override { - if (!_writable) throw Permission_denied(); + if (!_writeable) throw Permission_denied(); _apply(dir_handle, [&] (Directory &dir) { char const *name_str = name.string(); @@ -527,20 +694,27 @@ class Vfs_server::Session_component : private Session_resources, Path path(name_str, dir.path()); assert_unlink(_vfs.unlink(path.base())); - dir.mark_as_updated(); }); + + /* + * The unlinking may have triggered a directory-watch handler, + * or a watch handler of the deleted file. + */ + _io_progress_handler.handle_io_progress(); } void truncate(File_handle file_handle, file_size_t size) override { _apply(file_handle, [&] (File &file) { file.truncate(size); }); + + _io_progress_handler.handle_io_progress(); } void move(Dir_handle from_dir_handle, Name const &from_name, Dir_handle to_dir_handle, Name const &to_name) override { - if (!_writable) + if (!_writeable) throw Permission_denied(); char const *from_str = from_name.string(); @@ -555,18 +729,19 @@ class Vfs_server::Session_component : private Session_resources, Path to_path( to_str, to_dir.path()); assert_rename(_vfs.rename(from_path.base(), to_path.base())); - - from_dir.mark_as_updated(); - to_dir.mark_as_updated(); }); }); + + /* the move may have triggered a directory watch handler */ + _io_progress_handler.handle_io_progress(); } void control(Node_handle, Control) override { } }; -class Vfs_server::Root : public Genode::Root_component<Session_component> +class Vfs_server::Root : public Genode::Root_component<Session_component>, + private Genode::Entrypoint::Io_progress_handler { private: @@ -584,6 +759,9 @@ class Vfs_server::Root : public Genode::Root_component<Session_component> } } + Genode::Signal_handler<Root> _reactivate_handler { + _env.ep(), *this, &Root::handle_io_progress }; + Genode::Signal_handler<Root> _config_handler { _env.ep(), *this, &Root::_config_update }; @@ -600,73 +778,65 @@ class Vfs_server::Root : public Genode::Root_component<Session_component> Genode::Heap _vfs_heap { &_env.ram(), &_env.rm() }; Vfs::Simple_env _vfs_env { _env, _vfs_heap, vfs_config() }; + /* sessions with active jobs */ + Session_queue _active_sessions { }; + /** - * Object for post-I/O-signal processing - * - * This allows packet and VFS backend signals to - * be dispatched quickly followed by a processing - * of sessions that might be unblocked. + * Entrypoint::Io_progress_handler interface */ - struct Io_progress_handler : Genode::Entrypoint::Io_progress_handler + void handle_io_progress() override { - /* All nodes with a packet operation awaiting an I/O signal */ - Node_queue pending_nodes { }; + bool yield = false; - /* All sessions with packet queues that await processing */ - Session_queue pending_sessions { }; + unsigned iterations = 200; - /** - * Post-signal hook invoked by entrypoint - */ - void handle_io_progress() override - { - bool handle_progress = false; + for (;;) { - /* process handles awaiting progress */ - { - /* nodes to process later */ - Node_queue retry { }; - - /* empty the pending nodes and process */ - pending_nodes.dequeue_all([&] (Node &node) { - if (node.process_io()) { - handle_progress = true; - } else { - if (!node.enqueued()) { - retry.enqueue(node); - } - } - }); - - /* requeue the unprocessed nodes in order */ - retry.dequeue_all([&] (Node &node) { - pending_nodes.enqueue(node); }); + /* limit maximum number of iterations */ + if (--iterations == 0) { + yield = true; + break; } - /* - * if any pending handles were processed then - * process session packet queues awaiting progress - */ - if (handle_progress) { - /* sessions to process later */ - Session_queue retry { }; + bool progress = false; - /* empty the pending nodes and process */ - pending_sessions.dequeue_all([&] (Session_component &session) { - if (!session.process_packets()) { - /* requeue the session if there are packets remaining */ - if (!session.enqueued()) { - retry.enqueue(session); - } - } - }); + Session_queue still_active_sessions { }; - /* requeue the unprocessed sessions in order */ - retry.dequeue_all([&] (Session_component &session) { - pending_sessions.enqueue(session); }); - } + _active_sessions.dequeue_all([&] (Session_component &session) { + + typedef Session_component::Process_packets_result Result; + + switch (session.process_packets()) { + + case Result::PROGRESS: + progress = true; + break; + + case Result::TOO_MUCH_PROGRESS: + yield = true; + break; + + case Result::NONE: + break; + } + + if (!session.no_longer_active()) + still_active_sessions.enqueue(session); + }); + + _active_sessions = still_active_sessions; + + if (!progress) + break; } - } _progress_handler { }; + + /* + * Submit a local signal to re-schedule another execution of + * 'handle_io_progress' if the loop was exited via 'yield'. + */ + if (yield) + Genode::Signal_transmitter(_reactivate_handler).submit(); + } protected: @@ -754,8 +924,7 @@ class Vfs_server::Root : public Genode::Root_component<Session_component> Genode::Ram_quota{ram_quota}, Genode::Cap_quota{cap_quota}, tx_buf_size, _vfs_env.root_dir(), - _progress_handler.pending_nodes, - _progress_handler.pending_sessions, + _active_sessions, *this, session_root.base(), writeable); auto ram_used = _env.pd().used_ram().value - initial_ram_usage; @@ -772,7 +941,6 @@ class Vfs_server::Root : public Genode::Root_component<Session_component> ", '", label, "'"); } - Genode::log("session opened for '", label, "' at '", session_root, "'"); return session; } @@ -800,7 +968,7 @@ class Vfs_server::Root : public Genode::Root_component<Session_component> Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc), _env(env) { - _env.ep().register_io_progress_handler(_progress_handler); + _env.ep().register_io_progress_handler(*this); _config_rom.sigh(_config_handler); env.parent().announce(env.ep().manage(*this)); } diff --git a/repos/os/src/server/vfs/node.h b/repos/os/src/server/vfs/node.h index db9425c92..80d3e1598 100644 --- a/repos/os/src/server/vfs/node.h +++ b/repos/os/src/server/vfs/node.h @@ -2,6 +2,7 @@ * \brief Internal nodes of VFS server * \author Emery Hemingway * \author Christian Helmuth + * \author Norman Feske * \date 2016-03-29 */ @@ -16,7 +17,6 @@ #define _VFS__NODE_H_ /* Genode includes */ -#include <file_system/node.h> #include <vfs/file_system.h> #include <os/path.h> #include <base/id_space.h> @@ -52,6 +52,8 @@ namespace Vfs_server { typedef Genode::Allocator::Out_of_memory Out_of_memory; + struct Payload_ptr { char *ptr; }; + /** * Type trait for determining the node type for a given handle type */ @@ -75,16 +77,14 @@ namespace Vfs_server { /* * Note that the file objects are created at the * VFS in the local node constructors, this is to - * ensure that in the case of file creating that the + * ensure that in the case of file creation, the * Out_of_ram exception is thrown before the VFS is * modified. */ } -class Vfs_server::Node : public ::File_system::Node_base, - private Node_space::Element, - private Node_queue::Element +class Vfs_server::Node : Node_space::Element, Node_queue::Element { private: @@ -98,56 +98,128 @@ class Vfs_server::Node : public ::File_system::Node_base, protected: - /* - * Global queue of nodes that await - * some response from the VFS libray + /** + * Packet descriptor to be added to the acknowledgement queue * - * A global collection is perhaps dangerous - * but ensures fairness across sessions + * The '_acked_packet' is reset by 'submit_job' and assigned + * to a valid descriptor by 'try_execute_job'. The validity of the + * packet descriptor is tracked by '_acked_packet_valid'. */ - Node_queue &_response_queue; + Packet_descriptor _acked_packet { }; - /* stream used for reply packets */ - Packet_stream &_stream; + bool _submit_accepted = false; + + bool _acked_packet_valid = false; + + bool _packet_in_progress = false; + + enum class Read_ready_state { DONT_CARE, REQUESTED, READY }; + + Read_ready_state _read_ready_state { Read_ready_state::DONT_CARE }; public: friend Node_queue; using Node_queue::Element::enqueued; - Node(Node_space &space, - char const *node_path, - Node_queue &response_queue, - Packet_stream &stream) - : Node_space::Element(*this, space), - _path(node_path), - _response_queue(response_queue), - _stream(stream) + Node(Node_space &space, char const *node_path) + : + Node_space::Element(*this, space), _path(node_path) { } - virtual ~Node() - { - if (enqueued()) - _response_queue.remove(*this); - } + virtual ~Node() { } using Node_space::Element::id; char const *path() const { return _path.base(); } + enum class Submit_result { DENIED, ACCEPTED, STALLED }; + + bool job_in_progress() const { return _packet_in_progress; } + /** - * Process pending activity, called by post-signal hook + * Return true if node is ready to accept 'submit_job' * - * Default implementation is to return true so that the - * node is removed from the pending handle queue. + * Each node can deal with only one job at a time, except for file + * nodes, which accept a job in addition to an already submitted + * READ_READY request (which leaves '_packet_in_progress' untouched). */ - virtual bool process_io() { return true; } + bool job_acceptable() const { return !job_in_progress(); } + + /** + * Submit job to node + * + * When called, the node is expected to be idle (neither queued in + * the active-nodes queue nor the finished-nodes queue). + */ + virtual Submit_result submit_job(Packet_descriptor, Payload_ptr) + { + return Submit_result::DENIED; + } + + /** + * Execute submitted job + * + * This function must not be called if 'job_in_progress()' is false. + */ + virtual void execute_job() + { + Genode::warning("Node::execute_job unexpectedly called"); + } + + /** + * Return true if the node has at least one acknowledgement ready + */ + bool acknowledgement_pending() const + { + return (_read_ready_state == Read_ready_state::READY) + || _acked_packet_valid; + } + + bool active() const + { + return acknowledgement_pending() + || job_in_progress() + || (_read_ready_state == Read_ready_state::REQUESTED); + } + + /** + * Return and consume one pending acknowledgement + */ + Packet_descriptor dequeue_acknowledgement() + { + if (_read_ready_state == Read_ready_state::READY) { + _read_ready_state = Read_ready_state::DONT_CARE; + + Packet_descriptor ack_read_ready(Packet_descriptor(), + Node_handle { id().value }, + Packet_descriptor::READ_READY, + 0, 0); + ack_read_ready.succeeded(true); + return ack_read_ready; + } + + if (_acked_packet_valid) { + _acked_packet_valid = false; + return _acked_packet; + } + + Genode::warning("dequeue_acknowledgement called with no pending ack"); + return Packet_descriptor(); + } + + /** + * Return true if node was written to + */ + virtual bool modified() const { return false; } /** * Print for debugging */ - void print(Genode::Output &out) const { - out.out_string(_path.base()); } + void print(Genode::Output &out) const + { + Genode::print(out, _path.string(), " (id=", id(), ")"); + } }; @@ -155,11 +227,8 @@ class Vfs_server::Node : public ::File_system::Node_base, * Super-class for nodes that process read/write packets */ class Vfs_server::Io_node : public Vfs_server::Node, - public Vfs::Io_response_handler{ - public: - - enum Op_state { IDLE, READ_QUEUED, SYNC_QUEUED }; - + public Vfs::Io_response_handler +{ private: /* @@ -170,166 +239,231 @@ class Vfs_server::Io_node : public Vfs_server::Node, Mode const _mode; - bool _packet_queued = false; - bool _packet_op_pending = false; - protected: + Payload_ptr _payload_ptr { }; + + bool _modified = false; + Vfs::Vfs_handle &_handle; + void _import_job(Packet_descriptor packet, Payload_ptr payload_ptr) + { + /* + * Accept a READ_READY request without occupying '_packet'. + * This way, another request can follow a READ_READY request + * without blocking on the completion of READ_READY. + */ + if (packet.operation() == Packet_descriptor::READ_READY) { + _read_ready_state = Read_ready_state::REQUESTED; + return; + } + + if (job_in_progress()) + Genode::error("job unexpectedly submitted to busy node"); + + _packet = packet; + _payload_ptr = payload_ptr; + _acked_packet_valid = false; + _acked_packet = Packet_descriptor { }; + } + + void _acknowledge_as_success(size_t count) + { + /* + * Keep '_packet' and '_payload_ptr' intact to allow for the + * conversion of directory entries in 'Directory::execute_job'. + */ + + _packet_in_progress = false; + _acked_packet_valid = true; + _acked_packet = _packet; + + _acked_packet.length(count); + _acked_packet.succeeded(true); + } + + void _acknowledge_as_failure() + { + _packet = Packet_descriptor(); + _payload_ptr = Payload_ptr { nullptr }; + _packet_in_progress = false; + _acked_packet_valid = true; + _acked_packet = _packet; + + _acked_packet.succeeded(false); + } + /** - * Packets that have been removed from the - * packet stream are transfered here + * Current job of this node, assigned by 'submit_job' */ Packet_descriptor _packet { }; - /** - * Abstract read implementation - * - * Returns true if the pending packet - * shall be returned to client - */ - bool _vfs_read(char *dst, file_size count, - file_offset seek_offset, file_size &out_count) + protected: + + Submit_result _submit_read_at(file_offset seek_offset) { - if (!(_mode & READ_ONLY)) return true; + if (!(_mode & READ_ONLY)) + return Submit_result::DENIED; _handle.seek(seek_offset); - if (!_packet_op_pending) { - /* if the read cannot be queued with the VFS then stop here */ - if (!_handle.fs().queue_read(&_handle, count)) { - return false; - } - _packet_op_pending = true; + bool const queuing_succeeded = + _handle.fs().queue_read(&_handle, _packet.length()); + + if (queuing_succeeded) + _packet_in_progress = true; + + return queuing_succeeded ? Submit_result::ACCEPTED + : Submit_result::STALLED; + } + + Submit_result _submit_write_at(file_offset seek_offset) + { + if (!(_mode & WRITE_ONLY)) + return Submit_result::DENIED; + + _handle.seek(seek_offset); + + _packet_in_progress = true; + return Submit_result::ACCEPTED; + } + + Submit_result _submit_sync() + { + bool const queuing_succeeded = _handle.fs().queue_sync(&_handle); + + if (queuing_succeeded) + _packet_in_progress = true; + + return queuing_succeeded ? Submit_result::ACCEPTED + : Submit_result::STALLED; + } + + Submit_result _submit_read_ready() + { + _read_ready_state = Read_ready_state::REQUESTED; + + if (_handle.fs().read_ready(&_handle)) { + /* if the handle is ready, send a packet back immediately */ + read_ready_response(); + } else { + /* register to send READ_READY acknowledgement later */ + _handle.fs().notify_read_ready(&_handle); } + return Submit_result::ACCEPTED; + } - Read_result result = _handle.fs().complete_read( - &_handle, dst, count, out_count); + Submit_result _submit_content_changed() + { + Genode::warning("client unexpectedly submitted CONTENT_CHANGED packet"); + return Submit_result::DENIED; + } - switch (result) { + Submit_result _submit_write_timestamp() + { + if (!(_mode & WRITE_ONLY)) + return Submit_result::DENIED; + + _packet_in_progress = true; + return Submit_result::ACCEPTED; + } + + void _execute_read() + { + file_size out_count = 0; + + switch (_handle.fs().complete_read(&_handle, _payload_ptr.ptr, + _packet.length(), out_count)) { case Read_result::READ_OK: - _packet.succeeded(true); + _acknowledge_as_success(out_count); break; case Read_result::READ_ERR_IO: case Read_result::READ_ERR_INVALID: - _packet.length(out_count); + _acknowledge_as_failure(); break; case Read_result::READ_ERR_WOULD_BLOCK: case Read_result::READ_ERR_AGAIN: case Read_result::READ_ERR_INTERRUPT: case Read_result::READ_QUEUED: - /* packet is still pending */ - return false; + break; } - - /* packet is processed */ - _packet_op_pending = false; - return true; } /** - * Abstract write implementation + * Try to execute write operation at the VFS * - * Returns true if the pending packet - * shall be returned to client + * \return number of consumed bytes */ - bool _vfs_write(char const *src, file_size count, - file_offset seek_offset, file_size &out_count) + file_size _execute_write(char const *src_ptr, size_t length) { - if (!(_mode & WRITE_ONLY)) - return true; - - _handle.seek(seek_offset); - + file_size out_count = 0; try { - Write_result result = _handle.fs().write( - &_handle, src, count, out_count); + switch (_handle.fs().write(&_handle, src_ptr, length, out_count)) { + case Write_result::WRITE_ERR_AGAIN: + case Write_result::WRITE_ERR_WOULD_BLOCK: + break; - if (result == Write_result::WRITE_OK) { - mark_as_updated(); - _packet.succeeded(true); + case Write_result::WRITE_ERR_INVALID: + case Write_result::WRITE_ERR_IO: + case Write_result::WRITE_ERR_INTERRUPT: + _acknowledge_as_failure(); + break; + + case Write_result::WRITE_OK: + break; } } - catch (Vfs::File_io_service::Insufficient_buffer) - { - /* packet is pending */ - return false; - } + catch (Vfs::File_io_service::Insufficient_buffer) { /* re-execute */ } - /* packet is processed */ - return true; + _modified = true; - /* No further error handling! */ + return out_count; } - inline - void _drop_packet() + void _execute_sync() { - _packet = Packet_descriptor(); - _packet_queued = false; - } + switch (_handle.fs().complete_sync(&_handle)) { - inline - void _ack_packet(size_t count) - { - _packet.length(count); - _stream.acknowledge_packet(_packet); - _packet = Packet_descriptor(); - _packet_queued = false; - } - - /** - * Abstract sync implementation - */ - bool _sync() - { - if (!_packet_op_pending) { - /* if the sync cannot be queued with the VFS then stop here */ - if (!_handle.fs().queue_sync(&_handle)) { - return false; - } - _packet_op_pending = true; - } - - Sync_result result = _handle.fs().complete_sync(&_handle); - - switch (result) { case Sync_result::SYNC_OK: - _packet.succeeded(true); + _acknowledge_as_success(0); break; case Sync_result::SYNC_ERR_INVALID: + _acknowledge_as_failure(); break; case Sync_result::SYNC_QUEUED: - /* packet still pending */ - return false; + break; } - - /* packet processed */ - _ack_packet(0); - _packet_op_pending = false; - return true; } - /** - * Virtual methods for specialized node-type I/O - */ - virtual bool _read() = 0; - virtual bool _write() = 0; + void _execute_write_timestamp() + { + try { + _packet.with_timestamp([&] (File_system::Timestamp const time) { + Vfs::Timestamp ts { .value = time.value }; + _handle.fs().update_modification_timestamp(&_handle, ts); + }); + _acknowledge_as_success(0); + } + catch (Vfs::File_io_service::Insufficient_buffer) { } + + _modified = true; + } public: - Io_node(Node_space &space, char const *node_path, Mode node_mode, - Node_queue &response_queue, Packet_stream &stream, + Io_node(Node_space &space, + char const *path, + Mode mode, Vfs_handle &handle) - : Node(space, node_path, response_queue, stream), - _mode(node_mode), _handle(handle) + : + Node(space, path), _mode(mode), _handle(handle) { - _handle.handler(this); + _handle.handler(this); // XXX remove? } virtual ~Io_node() @@ -340,73 +474,18 @@ class Vfs_server::Io_node : public Vfs_server::Node, using Node_space::Element::id; - /** - * Process the packet that is queued at this handle - * - * Return true if the node was processed and is now idle. - */ - bool process_io() override - { - if (!_packet_queued) return true; - if (!_stream.ready_to_ack()) - return false; - - bool result = true; - - switch (_packet.operation()) { - case Packet_descriptor::READ: result = _read(); break; - case Packet_descriptor::WRITE: result = _write(); break; - case Packet_descriptor::SYNC: result = _sync(); break; - - case Packet_descriptor::READ_READY: - /* - * the read-ready pending state is managed - * by the VFS, this packet can be discarded - */ - _drop_packet(); - - if (_handle.fs().read_ready(&_handle)) { - /* if the handle is ready, send a packet back immediately */ - read_ready_response(); - } else { - /* register to send READ_READY later */ - _handle.fs().notify_read_ready(&_handle); - } - - break; - - case Packet_descriptor::CONTENT_CHANGED: - /* discard this packet */ - _drop_packet(); - break; - } - - return result; - } - - /** - * Process a packet by queuing it locally or sending - * an immediate response. Return false if no progress - * can be made. - * - * Called by packet stream signal handler - */ - bool process_packet(Packet_descriptor const &packet) - { - /* attempt to clear any pending packet */ - if (!process_io()) - return false; - - /* otherwise store the packet locally and process */ - _packet = packet; - _packet_queued = true; - process_io(); - return true; - } - Mode mode() const { return _mode; } + /******************************** + ** Vfs_server::Node interface ** + ********************************/ + + void execute_job() override { } + + bool modified() const override { return _modified; } + + /**************************************** ** Vfs::Io_response_handler interface ** ****************************************/ @@ -416,40 +495,27 @@ class Vfs_server::Io_node : public Vfs_server::Node, */ void read_ready_response() override { - if (!_stream.ready_to_ack()) { - /* log a message to catch loops */ - Genode::warning("deferring READ_READY response"); - _handle.fs().notify_read_ready(&_handle); - return; - } - - /* Send packet immediately, though this could be queued */ - Packet_descriptor packet(Packet_descriptor(), - Node_handle { id().value }, - Packet_descriptor::READ_READY, - 0, 0); - packet.succeeded(true); - _stream.acknowledge_packet(packet); + if (_read_ready_state == Read_ready_state::REQUESTED) + _read_ready_state = Read_ready_state::READY; } /** * Called by the VFS plugin of this handle */ - void io_progress_response() override - { - /* - * do not process packet immediately, - * queue to maintain ordering (priorities?) - */ - if (!enqueued()) - _response_queue.enqueue(*this); - } + void io_progress_response() override { } }; class Vfs_server::Watch_node final : public Vfs_server::Node, public Vfs::Watch_response_handler { + public: + + struct Watch_node_response_handler : Genode::Interface + { + virtual void handle_watch_node_response(Watch_node &) = 0; + }; + private: /* @@ -460,20 +526,26 @@ class Vfs_server::Watch_node final : public Vfs_server::Node, Vfs::Vfs_watch_handle &_watch_handle; + Watch_node_response_handler &_watch_node_response_handler; + public: - Watch_node(Node_space &space, char const *path, - Vfs::Vfs_watch_handle &handle, - Node_queue &response_queue, - Packet_stream &stream) - : Node(space, path, response_queue, stream), - _watch_handle(handle) + Watch_node(Node_space &space, + char const *path, + Vfs::Vfs_watch_handle &handle, + Watch_node_response_handler &watch_node_response_handler) + : + Node(space, path), + _watch_handle(handle), + _watch_node_response_handler(watch_node_response_handler) { _watch_handle.handler(this); } - ~Watch_node() { - _watch_handle.close(); } + ~Watch_node() + { + _watch_handle.close(); + } /******************************************* @@ -482,9 +554,13 @@ class Vfs_server::Watch_node final : public Vfs_server::Node, void watch_response() override { - /* send a packet immediately otherwise defer */ - if (!process_io() && !enqueued()) - _response_queue.enqueue(*this); + _acked_packet = Packet_descriptor(Packet_descriptor(), + Node_handle { id().value }, + Packet_descriptor::CONTENT_CHANGED, + 0, 0); + _acked_packet.succeeded(true); + _acked_packet_valid = true; + _watch_node_response_handler.handle_watch_node_response(*this); } @@ -492,92 +568,49 @@ class Vfs_server::Watch_node final : public Vfs_server::Node, ** Vfs_server::Node interface ** ********************************/ - /** - * Called by global I/O progress handler - */ - bool process_io() override + Submit_result submit_job(Packet_descriptor, Payload_ptr) override { - if (!_stream.ready_to_ack()) return false; + /* + * This can only happen if a client misbehaves by submitting + * work to a watch handle. + */ + Genode::warning("job unexpectedly submitted to watch handle"); - Packet_descriptor packet(Packet_descriptor(), - Node_handle { id().value }, - Packet_descriptor::CONTENT_CHANGED, - 0, 0); - packet.succeeded(true); - _stream.acknowledge_packet(packet); - return true; + /* don't reset '_acked_packet' as defined in the constructor */ + + return Submit_result::DENIED; } }; struct Vfs_server::Symlink : Io_node { - protected: + private: - /******************** - ** Node interface ** - ********************/ + typedef Genode::String<MAX_PATH_LEN + 1> Write_buffer; - bool _read() override + Write_buffer _write_buffer { }; + + bool _partial_operation() const { + /* partial read or write is not supported */ if (_packet.position() != 0) { - /* partial read is not supported */ - _ack_packet(0); + Genode::warning("attempt for partial operation on a symlink"); return true; } - - file_size out_count = 0; - bool result = _vfs_read(_stream.packet_content(_packet), - _packet.length(), 0, out_count); - if (result) - _ack_packet(out_count); - return result; + return false; } - bool _write() override + bool _max_path_length_exceeded() const { - if (_packet.position() != 0) { - /* partial write is not supported */ - _ack_packet(0); - return true; - } - - file_size count = _packet.length(); - - /* - * if the symlink target is too long return a short result - * because a competent File_system client will error on a - * length mismatch - */ - if (count > MAX_PATH_LEN) { - _ack_packet(1); - return true; - } - - /* ensure symlink gets something null-terminated */ - Genode::String<MAX_PATH_LEN+1> target(Genode::Cstring( - _stream.packet_content(_packet), count)); - size_t const target_len = target.length()-1; - - file_size out_count = 0; - bool result = _vfs_write(target.string(), target_len, 0, out_count); - - if (result) { - _ack_packet(out_count); - if (out_count > 0) { - mark_as_updated(); - notify_listeners(); - } - } - return result; + return _packet.length() >= MAX_PATH_LEN; } - static - Vfs_handle &_open(Vfs::File_system &vfs, Genode::Allocator &alloc, - char const *link_path, bool create) + static Vfs_handle &_open(Vfs::File_system &vfs, Genode::Allocator &alloc, + char const *path, bool create) { Vfs_handle *h = nullptr; - assert_openlink(vfs.openlink(link_path, create, &h, alloc)); + assert_openlink(vfs.openlink(path, create, &h, alloc)); return *h; } @@ -586,14 +619,81 @@ struct Vfs_server::Symlink : Io_node Symlink(Node_space &space, Vfs::File_system &vfs, Genode::Allocator &alloc, - Node_queue &response_queue, - Packet_stream &stream, - char const *link_path, + char const *path, Mode mode, bool create) - : Io_node(space, link_path, mode, response_queue, stream, - _open(vfs, alloc, link_path, create)) + : + Io_node(space, path, mode, _open(vfs, alloc, path, create)) { } + + Submit_result submit_job(Packet_descriptor packet, Payload_ptr payload_ptr) override + { + _import_job(packet, payload_ptr); + + switch (packet.operation()) { + + case Packet_descriptor::READ: + + if (_partial_operation()) + return Submit_result::DENIED; + + return _submit_read_at(0); + + case Packet_descriptor::WRITE: + { + if (_partial_operation() || _max_path_length_exceeded()) + return Submit_result::DENIED; + + /* accessed by 'execute_job' */ + _write_buffer = Write_buffer(Genode::Cstring(_payload_ptr.ptr, + packet.length())); + return _submit_write_at(0); + } + + case Packet_descriptor::SYNC: return _submit_sync(); + case Packet_descriptor::READ_READY: return _submit_read_ready(); + case Packet_descriptor::CONTENT_CHANGED: return _submit_content_changed(); + case Packet_descriptor::WRITE_TIMESTAMP: return _submit_write_timestamp(); + } + + Genode::warning("invalid operation ", (int)_packet.operation(), " " + "requested from symlink node"); + + return Submit_result::DENIED; + } + + void execute_job() override + { + switch (_packet.operation()) { + + /* + * Write symlink content from '_write_buffer' instead of the + * '_payload_ptr'. In contrast to '_payload_ptr', which points + * to shared memory, the null-termination of the content of + * '_write_buffer' does not depend on the goodwill of the client. + */ + case Packet_descriptor::WRITE: + { + size_t const count = _write_buffer.length(); + + if (_execute_write(_write_buffer.string(), count) == count) + _acknowledge_as_success(count); + else + _acknowledge_as_failure(); + break; + } + + /* generic */ + case Packet_descriptor::READ: _execute_read(); break; + case Packet_descriptor::SYNC: _execute_sync(); break; + case Packet_descriptor::WRITE_TIMESTAMP: _execute_write_timestamp(); break; + + /* never executed */ + case Packet_descriptor::READ_READY: + case Packet_descriptor::CONTENT_CHANGED: + break; + } + } }; @@ -607,68 +707,54 @@ class Vfs_server::File : public Io_node File(File const &); File &operator = (File const &); - char const *_leaf_path = nullptr; /* offset pointer to Node::_path */ + char const * const _leaf_path = nullptr; /* offset pointer to Node::_path */ - inline - seek_off_t seek_tail(file_size count) + typedef Directory_service::Stat Stat; + + template <typename FN> + void _with_stat(FN const &fn) { typedef Directory_service::Stat_result Result; - Vfs::Directory_service::Stat st; - /* if stat fails, try and see if the VFS will seek to the end */ - return (_handle.ds().stat(_leaf_path, st) == Result::STAT_OK) - ? ((count < st.size) ? (st.size - count) : 0) - : (seek_off_t)SEEK_TAIL; + Vfs::Directory_service::Stat stat { }; + if (_handle.ds().stat(_leaf_path, stat) == Result::STAT_OK) + fn(stat); } + seek_off_t _seek_pos() + { + seek_off_t seek_pos = _packet.position(); + + if (seek_pos == (seek_off_t)SEEK_TAIL) + _with_stat([&] (Stat const &stat) { + seek_pos = stat.size; }); + + return seek_pos; + } + + enum class Write_type { UNKNOWN, CONTINUOUS, TRANSACTIONAL }; + + Write_type _write_type = Write_type::UNKNOWN; + + /** + * Number of bytes consumed by VFS write + * + * Used for the incremental write to continuous files. + */ + seek_off_t _write_pos = 0; + + bool _watch_read_ready = false; + protected: - bool _read() override - { - file_size out_count = 0; - file_size count = _packet.length(); - seek_off_t seek_offset = _packet.position(); - - if (seek_offset == (seek_off_t)SEEK_TAIL) - seek_offset = seek_tail(count); - - bool result = _vfs_read(_stream.packet_content(_packet), - count, seek_offset, out_count); - if (result) - _ack_packet(out_count); - return result; - } - - bool _write() override - { - file_size out_count = 0; - file_size count = _packet.length(); - seek_off_t seek_offset = _packet.position(); - - if (seek_offset == (seek_off_t)SEEK_TAIL) - seek_offset = seek_tail(count); - - bool result = _vfs_write(_stream.packet_content(_packet), - count, seek_offset, out_count); - if (result) { - _ack_packet(out_count); - if (out_count > 0) { - mark_as_updated(); - notify_listeners(); - } - } - return result; - } - - static - Vfs_handle &_open(Vfs::File_system &vfs, Genode::Allocator &alloc, - char const *file_path, Mode fs_mode, bool create) + static Vfs_handle &_open(Vfs::File_system &vfs, Genode::Allocator &alloc, + char const *path, Mode mode, bool create) { Vfs_handle *h = nullptr; - unsigned vfs_mode = (fs_mode-1) | + unsigned vfs_mode = (mode-1) | (create ? Vfs::Directory_service::OPEN_MODE_CREATE : 0); - assert_open(vfs.open(file_path, vfs_mode, &h, alloc)); + assert_open(vfs.open(path, vfs_mode, &h, alloc)); return *h; } @@ -677,100 +763,202 @@ class Vfs_server::File : public Io_node File(Node_space &space, Vfs::File_system &vfs, Genode::Allocator &alloc, - Node_queue &response_queue, - Packet_stream &stream, - char const *file_path, - Mode fs_mode, + char const *path, + Mode mode, bool create) : - Io_node(space, file_path, fs_mode, response_queue, stream, - _open(vfs, alloc, file_path, fs_mode, create)) - { - _leaf_path = vfs.leaf_path(path()); - } + Io_node(space, path, mode, _open(vfs, alloc, path, mode, create)), + _leaf_path(vfs.leaf_path(Node::path())) + { } void truncate(file_size_t size) { assert_truncate(_handle.fs().ftruncate(&_handle, size)); - mark_as_updated(); + } + + Submit_result submit_job(Packet_descriptor packet, Payload_ptr payload_ptr) override + { + _import_job(packet, payload_ptr); + + _write_type = Write_type::UNKNOWN; + _write_pos = 0; + + switch (packet.operation()) { + + case Packet_descriptor::READ: return _submit_read_at(_seek_pos()); + case Packet_descriptor::WRITE: return _submit_write_at(_seek_pos()); + case Packet_descriptor::SYNC: return _submit_sync(); + case Packet_descriptor::READ_READY: return _submit_read_ready(); + case Packet_descriptor::CONTENT_CHANGED: return _submit_content_changed(); + case Packet_descriptor::WRITE_TIMESTAMP: return _submit_write_timestamp(); + } + + Genode::warning("invalid operation ", (int)_packet.operation(), " " + "requested from file node"); + + return Submit_result::DENIED; + } + + void execute_job() override + { + switch (_packet.operation()) { + + case Packet_descriptor::WRITE: + { + size_t const count = _packet.length() - _write_pos; + char const * const src_ptr = _payload_ptr.ptr + _write_pos; + size_t const consumed = _execute_write(src_ptr, count); + + if (consumed == count) { + _acknowledge_as_success(count); + break; + } + + /* + * The write request was only partially successful. + * Continue writing if the file is continuous. + * Return an error if the file is transactional. + */ + + /* determine write type once via 'stat' */ + if (_write_type == Write_type::UNKNOWN) { + _write_type = Write_type::TRANSACTIONAL; + + _with_stat([&] (Stat const &stat) { + if (stat.type == Vfs::Node_type::CONTINUOUS_FILE) + _write_type = Write_type::CONTINUOUS; }); + } + + if (_write_type == Write_type::TRANSACTIONAL) { + _acknowledge_as_failure(); + break; + } + + /* + * Keep executing the write operation for the remaining bytes. + * The seek offset used for subsequent VFS write operations + * is incremented automatically by the VFS handle. + */ + _write_pos += consumed; + break; + } + + /* generic */ + case Packet_descriptor::READ: _execute_read(); break; + case Packet_descriptor::SYNC: _execute_sync(); break; + case Packet_descriptor::WRITE_TIMESTAMP: _execute_write_timestamp(); break; + + /* never executed */ + case Packet_descriptor::READ_READY: + case Packet_descriptor::CONTENT_CHANGED: + break; + } } }; struct Vfs_server::Directory : Io_node { - protected: + public: - /******************** - ** Node interface ** - ********************/ + enum class Session_writeable { READ_ONLY, WRITEABLE }; - bool _read() override + private: + + Session_writeable const _writeable; + + typedef Directory_service::Dirent Vfs_dirent; + typedef File_system::Directory_entry Fs_dirent; + + bool _position_and_length_aligned_with_dirent_size() { - if (_packet.length() < sizeof(Directory_entry)) { - _ack_packet(0); - return true; - } + if (_packet.length() < sizeof(Directory_entry)) + return false; - seek_off_t seek_offset = _packet.position(); + if (_packet.length() % sizeof(::File_system::Directory_entry)) + return false; - Directory_service::Dirent vfs_dirent; - size_t blocksize = sizeof(::File_system::Directory_entry); + if (_packet.position() % sizeof(::File_system::Directory_entry)) + return false; - unsigned index = (seek_offset / blocksize); - - file_size out_count = 0; - bool result = _vfs_read( - (char*)&vfs_dirent, sizeof(vfs_dirent), - index * sizeof(vfs_dirent), out_count); - - if (result) { - if (out_count != sizeof(vfs_dirent)) { - _ack_packet(0); - return true; - } - - ::File_system::Directory_entry *fs_dirent = - (Directory_entry *)_stream.packet_content(_packet); - fs_dirent->inode = vfs_dirent.fileno; - - switch (vfs_dirent.type) { - case Vfs::Directory_service::DIRENT_TYPE_END: - _ack_packet(0); - return true; - - case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: - fs_dirent->type = ::File_system::Directory_entry::TYPE_DIRECTORY; - break; - case Vfs::Directory_service::DIRENT_TYPE_SYMLINK: - fs_dirent->type = ::File_system::Directory_entry::TYPE_SYMLINK; - break; - case Vfs::Directory_service::DIRENT_TYPE_FILE: - default: - fs_dirent->type = ::File_system::Directory_entry::TYPE_FILE; - break; - } - - strncpy(fs_dirent->name, vfs_dirent.name, MAX_NAME_LEN); - - _ack_packet(sizeof(Directory_entry)); - return true; - } - return false; - } - - bool _write() override - { - _ack_packet(0); return true; } - static - Vfs_handle &_open(Vfs::File_system &vfs, Genode::Allocator &alloc, - char const *dir_path, bool create) + static Fs_dirent _convert_dirent(Vfs_dirent from, Session_writeable writeable) + { + from.sanitize(); + + auto fs_dirent_type = [&] (Vfs::Directory_service::Dirent_type type) + { + using From = Vfs::Directory_service::Dirent_type; + using To = ::File_system::Node_type; + + /* + * This should never be taken because 'END' is checked as a + * precondition prior the call to of this function. + */ + To const default_result = To::CONTINUOUS_FILE; + + switch (type) { + case From::END: return default_result; + case From::DIRECTORY: return To::DIRECTORY; + case From::SYMLINK: return To::SYMLINK; + case From::CONTINUOUS_FILE: return To::CONTINUOUS_FILE; + case From::TRANSACTIONAL_FILE: return To::TRANSACTIONAL_FILE; + } + return default_result; + }; + + return { + .inode = from.fileno, + .type = fs_dirent_type(from.type), + .rwx = { + .readable = from.rwx.readable, + .writeable = (writeable == Session_writeable::WRITEABLE) + ? from.rwx.writeable : false, + .executable = from.rwx.executable }, + .name = { from.name.buf } + }; + } + + /** + * Convert VFS directory entry to FS directory entry in place in the + * payload buffer + * + * \return size of converted data in bytes + */ + file_size _convert_vfs_dirents_to_fs_dirents() + { + static_assert(sizeof(Vfs_dirent) == sizeof(Fs_dirent)); + + file_offset const step = sizeof(Fs_dirent); + file_offset const length = _packet.length(); + + file_size converted_length = 0; + + for (file_offset offset = 0; offset + step <= length; offset += step) { + + char * const ptr = _payload_ptr.ptr + offset; + + Vfs_dirent &vfs_dirent = *(Vfs_dirent *)(ptr); + Fs_dirent &fs_dirent = *(Fs_dirent *)(ptr); + + if (vfs_dirent.type == Vfs::Directory_service::Dirent_type::END) + break; + + fs_dirent = _convert_dirent(vfs_dirent, _writeable); + + converted_length += step; + } + + return converted_length; + } + + static Vfs_handle &_open(Vfs::File_system &vfs, Genode::Allocator &alloc, + char const *path, bool create) { Vfs_handle *h = nullptr; - assert_opendir(vfs.opendir(dir_path, create, &h, alloc)); + assert_opendir(vfs.opendir(path, create, &h, alloc)); return *h; } @@ -779,12 +967,12 @@ struct Vfs_server::Directory : Io_node Directory(Node_space &space, Vfs::File_system &vfs, Genode::Allocator &alloc, - Node_queue &response_queue, - Packet_stream &stream, - char const *dir_path, - bool create) - : Io_node(space, dir_path, READ_ONLY, response_queue, stream, - _open(vfs, alloc, dir_path, create)) + char const *path, + bool create, + Session_writeable writeable) + : + Io_node(space, path, READ_ONLY, _open(vfs, alloc, path, create)), + _writeable(writeable) { } /** @@ -793,23 +981,15 @@ struct Vfs_server::Directory : Io_node Node_space::Id file(Node_space &space, Vfs::File_system &vfs, Genode::Allocator &alloc, - char const *file_path, + char const *path, Mode mode, bool create) { - Path subpath(file_path, path()); - char const *path_str = subpath.base(); + File &file = *new (alloc) + File(space, vfs, alloc, + Path(path, Node::path()).base(), mode, create); - File *file; - try { - file = new (alloc) File(space, vfs, alloc, - _response_queue, _stream, - path_str, mode, create); - } catch (Out_of_memory) { throw Out_of_ram(); } - - if (create) - mark_as_updated(); - return file->id(); + return file.id(); } /** @@ -818,21 +998,79 @@ struct Vfs_server::Directory : Io_node Node_space::Id symlink(Node_space &space, Vfs::File_system &vfs, Genode::Allocator &alloc, - char const *link_path, + char const *path, Mode mode, bool create) { - Path subpath(link_path, path()); - char const *path_str = subpath.base(); + Symlink &link = *new (alloc) + Symlink(space, vfs, alloc, + Path(path, Node::path()).base(), mode, create); - Symlink *link; - try { link = new (alloc) Symlink(space, vfs, alloc, - _response_queue, _stream, - path_str, mode, create); } - catch (Out_of_memory) { throw Out_of_ram(); } - if (create) - mark_as_updated(); - return link->id(); + return link.id(); + } + + + /******************************** + ** Vfs_server::Node interface ** + ********************************/ + + Submit_result submit_job(Packet_descriptor packet, Payload_ptr payload_ptr) override + { + _import_job(packet, payload_ptr); + + switch (packet.operation()) { + + case Packet_descriptor::READ: + + if (!_position_and_length_aligned_with_dirent_size()) + return Submit_result::DENIED; + + return _submit_read_at(_packet.position()); + + case Packet_descriptor::WRITE: + return Submit_result::DENIED; + + case Packet_descriptor::SYNC: return _submit_sync(); + case Packet_descriptor::READ_READY: return _submit_read_ready(); + case Packet_descriptor::CONTENT_CHANGED: return _submit_content_changed(); + case Packet_descriptor::WRITE_TIMESTAMP: return _submit_write_timestamp(); + } + + Genode::warning("invalid operation ", (int)_packet.operation(), " " + "requested from directory node"); + return Submit_result::DENIED; + } + + void execute_job() override + { + switch (_packet.operation()) { + + case Packet_descriptor::READ: + _execute_read(); + + if (_acked_packet_valid) { + file_size const length = _convert_vfs_dirents_to_fs_dirents(); + + /* + * Overwrite the acknowledgement assigned by + * '_execute_read' with an acknowledgement featuring the + * converted length. This way, the client reads only the + * number of bytes until the end of the directory. + */ + _acknowledge_as_success(length); + } + break; + + /* generic */ + case Packet_descriptor::SYNC: _execute_sync(); break; + case Packet_descriptor::WRITE_TIMESTAMP: _execute_write_timestamp(); break; + + /* never executed */ + case Packet_descriptor::WRITE: + case Packet_descriptor::READ_READY: + case Packet_descriptor::CONTENT_CHANGED: + break; + } } }; diff --git a/repos/os/src/server/vmm/board.h b/repos/os/src/server/vmm/spec/arm_v7/board.h similarity index 100% rename from repos/os/src/server/vmm/board.h rename to repos/os/src/server/vmm/spec/arm_v7/board.h diff --git a/repos/os/src/server/vmm/main.cc b/repos/os/src/server/vmm/spec/arm_v7/main.cc similarity index 100% rename from repos/os/src/server/vmm/main.cc rename to repos/os/src/server/vmm/spec/arm_v7/main.cc diff --git a/repos/os/src/server/vmm/target.mk b/repos/os/src/server/vmm/spec/arm_v7/target.mk similarity index 100% rename from repos/os/src/server/vmm/target.mk rename to repos/os/src/server/vmm/spec/arm_v7/target.mk diff --git a/repos/os/src/server/vmm/test/kernel/main.s b/repos/os/src/server/vmm/spec/arm_v7/test/main.s similarity index 100% rename from repos/os/src/server/vmm/test/kernel/main.s rename to repos/os/src/server/vmm/spec/arm_v7/test/main.s diff --git a/repos/os/src/server/vmm/test/kernel/target.mk b/repos/os/src/server/vmm/spec/arm_v7/test/target.mk similarity index 100% rename from repos/os/src/server/vmm/test/kernel/target.mk rename to repos/os/src/server/vmm/spec/arm_v7/test/target.mk diff --git a/repos/os/src/server/vmm/spec/arm_v8/address_space.cc b/repos/os/src/server/vmm/spec/arm_v8/address_space.cc new file mode 100644 index 000000000..2c866b03d --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/address_space.cc @@ -0,0 +1,32 @@ +/* + * \brief VMM address space utility + * \author Stefan Kalkowski + * \date 2019-09-13 + */ + +/* + * Copyright (C) 2019 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 <address_space.h> + +using Vmm::Address_range; + +Address_range::Address_range(Genode::uint64_t start, + Genode::uint64_t size) +: start(start), size(size) { } + + +Address_range & Address_range::find(Address_range & bus_addr) +{ + if (match(bus_addr)) + return *this; + + Address_range * ar = + Avl_node<Address_range>::child(bus_addr.start > start); + if (!ar) throw Not_found(bus_addr); + return ar->find(bus_addr); +} diff --git a/repos/os/src/server/vmm/spec/arm_v8/address_space.h b/repos/os/src/server/vmm/spec/arm_v8/address_space.h new file mode 100644 index 000000000..4be408d89 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/address_space.h @@ -0,0 +1,82 @@ +/* + * \brief VMM address space utility + * \author Stefan Kalkowski + * \date 2019-09-13 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__ADDRESS_SPACE_H_ +#define _SRC__SERVER__VMM__ADDRESS_SPACE_H_ + +#include <exception.h> +#include <util/avl_tree.h> + +namespace Vmm { + struct Address_range; + class Address_space; +} + + +struct Vmm::Address_range : Genode::Avl_node<Address_range> +{ + Genode::uint64_t const start; + Genode::uint64_t const size; + + Address_range(Genode::uint64_t start, + Genode::uint64_t size); + + Genode::uint64_t end() const { return start + size; } + + bool match(Address_range & other) const { + return other.start >= start && other.end() <= end(); } + + Address_range & find(Address_range & bus_addr); + + struct Not_found : Exception + { + Not_found(Address_range & access) + : Exception("Could not find ", access) {} + }; + + void print(Genode::Output & out) const + { + Genode::print(out, "address=", Genode::Hex(start), + " width=", Genode::Hex(size)); + } + + /************************ + ** Avl_node interface ** + ************************/ + + bool higher(Address_range * range) { + return range->start > start; } +}; + + +class Vmm::Address_space +{ + private: + + Genode::Avl_tree<Address_range> _tree; + + public: + + template <typename T> + T & get(Address_range & bus_addr) + { + if (!_tree.first()) throw Address_range::Not_found(bus_addr); + + return *static_cast<T*>(&_tree.first()->find(bus_addr)); + } + + void add(Address_range & ar) { _tree.insert(&ar); } +}; + + +#endif /* _SRC__SERVER__VMM__ADDRESS_SPACE_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/cpu.cc b/repos/os/src/server/vmm/spec/arm_v8/cpu.cc new file mode 100644 index 000000000..c2ba88c33 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/cpu.cc @@ -0,0 +1,403 @@ +/* + * \brief VMM cpu object + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 <cpu.h> +#include <vm.h> +#include <psci.h> + +using Vmm::Cpu; +using Vmm::Gic; + +Genode::Lock & Vmm::lock() { static Genode::Lock l {}; return l; } + + +Cpu::System_register::Iss::access_t +Cpu::System_register::Iss::value(unsigned op0, unsigned crn, unsigned op1, + unsigned crm, unsigned op2) +{ + access_t v = 0; + Crn::set(v, crn); + Crm::set(v, crm); + Opcode0::set(v, op0); + Opcode1::set(v, op1); + Opcode2::set(v, op2); + return v; +}; + + +Cpu::System_register::Iss::access_t +Cpu::System_register::Iss::mask_encoding(access_t v) +{ + return Crm::masked(v) | + Crn::masked(v) | + Opcode1::masked(v) | + Opcode2::masked(v) | + Opcode0::masked(v); +} + + +Cpu::System_register::System_register(unsigned op0, + unsigned crn, + unsigned op1, + unsigned crm, + unsigned op2, + const char * name, + bool writeable, + Genode::addr_t v, + Genode::Avl_tree<System_register> & tree) +: _encoding(Iss::value(op0, crn, op1, crm, op2)), + _name(name), + _writeable(writeable), + _value(v) +{ + tree.insert(this); +} + + +Genode::addr_t Cpu::Ccsidr::read() const +{ + struct Clidr : Genode::Register<32> + { + enum Cache_entry { + NO_CACHE, + INSTRUCTION_CACHE_ONLY, + DATA_CACHE_ONLY, + SEPARATE_CACHE, + UNIFIED_CACHE + }; + + static unsigned level(unsigned l, access_t reg) { + return (reg >> l*3) & 0b111; } + }; + + struct Csselr : Genode::Register<32> + { + struct Instr : Bitfield<0, 1> {}; + struct Level : Bitfield<1, 4> {}; + }; + + enum { INVALID = 0xffffffff }; + + unsigned level = Csselr::Level::get(csselr.read()); + bool instr = Csselr::Instr::get(csselr.read()); + + if (level > 6) { + Genode::warning("Invalid Csselr value!"); + return INVALID; + } + + unsigned ce = Clidr::level(level, state.clidr_el1); + + if (ce == Clidr::NO_CACHE || + (ce == Clidr::DATA_CACHE_ONLY && instr)) { + Genode::warning("Invalid Csselr value!"); + return INVALID; + } + + if (ce == Clidr::INSTRUCTION_CACHE_ONLY || + (ce == Clidr::SEPARATE_CACHE && instr)) { + Genode::log("Return Ccsidr instr value ", state.ccsidr_inst_el1[level]); + return state.ccsidr_inst_el1[level]; + } + + Genode::log("Return Ccsidr value ", state.ccsidr_data_el1[level]); + return state.ccsidr_data_el1[level]; +} + + +Genode::addr_t Cpu::Ctr_el0::read() const +{ + Genode::addr_t ret; + asm volatile("mrs %0, ctr_el0" : "=r" (ret)); + return ret; +} + + +void Cpu::Icc_sgi1r_el1::write(Genode::addr_t v) +{ + + unsigned target_list = v & 0xffff; + unsigned irq = (v >> 24) & 0xf; + + for (unsigned i = 0; i <= Vm::last_cpu(); i++) { + if (target_list & (1<<i)) { + vm.cpu(i, [&] (Cpu & cpu) { + cpu.gic().irq(irq).assert(); + cpu.recall(); + }); + } + } +}; + + +bool Cpu::_handle_sys_reg() +{ + using Iss = System_register::Iss; + + Iss::access_t v = _state.esr_el2; + System_register * reg = _reg_tree.first(); + if (reg) reg = reg->find_by_encoding(Iss::mask_encoding(v)); + + if (!reg) { + Genode::error("ignore unknown system register access @ ip=", (void*)_state.ip, ":"); + Genode::error(Iss::Direction::get(v) ? "read" : "write", + ": " + "op0=", Iss::Opcode0::get(v), " " + "op1=", Iss::Opcode1::get(v), " " + "r", Iss::Register::get(v), " " + "crn=", Iss::Crn::get(v), " " + "crm=", Iss::Crm::get(v), " ", + "op2=", Iss::Opcode2::get(v)); + if (Iss::Direction::get(v)) _state.r[Iss::Register::get(v)] = 0; + _state.ip += sizeof(Genode::uint32_t); + return false; + } + + if (Iss::Direction::get(v)) { /* read access */ + _state.r[Iss::Register::get(v)] = reg->read(); + } else { /* write access */ + if (!reg->writeable()) { + Genode::error("writing to system register ", + reg->name(), " not allowed!"); + return false; + } + reg->write(_state.r[Iss::Register::get(v)]); + } + _state.ip += sizeof(Genode::uint32_t); + return true; +} + + +void Cpu::_handle_wfi() +{ + _state.ip += sizeof(Genode::uint32_t); + + if (_state.esr_el2 & 1) return; /* WFE */ + + _active = false; + _timer.schedule_timeout(); +} + + +void Cpu::_handle_brk() +{ + Genode::uint64_t offset = 0x0; + if (!(_state.pstate & 0b100)) { + offset = 0x400; + } else if (_state.pstate & 0b1) { + offset = 0x200; + } + _state.esr_el1 = _state.esr_el2; + _state.spsr_el1 = _state.pstate; + _state.elr_el1 = _state.ip; + _state.ip = _state.vbar_el1 + offset; + _state.pstate = 0b1111000101; +} + + +void Cpu::_handle_sync() +{ + /* check device number*/ + switch (Esr::Ec::get(_state.esr_el2)) { + case Esr::Ec::HVC: + _handle_hyper_call(); + break; + case Esr::Ec::MRS_MSR: + _handle_sys_reg(); + break; + case Esr::Ec::DA: + _handle_data_abort(); + break; + case Esr::Ec::WFI: + _handle_wfi(); + return; + case Esr::Ec::BRK: + _handle_brk(); + return; + default: + throw Exception("Unknown trap: %x", + Esr::Ec::get(_state.esr_el2)); + }; +} + + +void Cpu::_handle_irq() +{ + enum { /* FIXME */ VT_TIMER_IRQ = 27 }; + switch (_state.irqs.last_irq) { + case VT_TIMER_IRQ: + _timer.handle_irq(); + break; + default: + _gic.handle_irq(); + }; +} + + +void Cpu::_handle_hyper_call() +{ + switch(_state.r[0]) { + case Psci::PSCI_VERSION: + _state.r[0] = Psci::VERSION; + return; + case Psci::MIGRATE_INFO_TYPE: + _state.r[0] = Psci::NOT_SUPPORTED; + return; + case Psci::PSCI_FEATURES: + _state.r[0] = Psci::NOT_SUPPORTED; + return; + case Psci::CPU_ON: + _vm.cpu((unsigned)_state.r[1], [&] (Cpu & cpu) { + cpu.state().ip = _state.r[2]; + cpu.state().r[0] = _state.r[3]; + cpu.run(); + }); + _state.r[0] = Psci::SUCCESS; + return; + default: + Genode::warning("unknown hypercall! ", cpu_id()); + dump(); + }; +} + + +void Cpu::_handle_data_abort() +{ + _vm.bus().handle_memory_access(*this); + _state.ip += sizeof(Genode::uint32_t); +} + + +void Cpu::_update_state() +{ + if (!_gic.pending_irq()) return; + + _active = true; + _timer.cancel_timeout(); +} + +unsigned Cpu::cpu_id() const { return _vcpu_id.id; } +void Cpu::run() { _vm_session.run(_vcpu_id); } +void Cpu::pause() { _vm_session.pause(_vcpu_id); } +bool Cpu::active() const { return _active; } +Cpu::State & Cpu::state() const { return _state; } +Gic::Gicd_banked & Cpu::gic() { return _gic; } + + +void Cpu::handle_exception() +{ + /* check exception reason */ + switch (_state.exception_type) { + case NO_EXCEPTION: break; + case AARCH64_IRQ: _handle_irq(); break; + case AARCH64_SYNC: _handle_sync(); break; + default: + throw Exception("Curious exception ", + _state.exception_type, " occured"); + } + _state.exception_type = NO_EXCEPTION; +} + + +void Cpu::dump() +{ + using namespace Genode; + + auto lambda = [] (addr_t exc) { + switch (exc) { + case AARCH64_SYNC: return "aarch64 sync"; + case AARCH64_IRQ: return "aarch64 irq"; + case AARCH64_FIQ: return "aarch64 fiq"; + case AARCH64_SERROR: return "aarch64 serr"; + case AARCH32_SYNC: return "aarch32 sync"; + case AARCH32_IRQ: return "aarch32 irq"; + case AARCH32_FIQ: return "aarch32 fiq"; + case AARCH32_SERROR: return "aarch32 serr"; + default: return "unknown"; + }; + }; + + log("VM state (", _active ? "active" : "inactive", ") :"); + for (unsigned i = 0; i < 31; i++) { + log(" r", i, " = ", + Hex(_state.r[i], Hex::PREFIX, Hex::PAD)); + } + log(" sp = ", Hex(_state.sp, Hex::PREFIX, Hex::PAD)); + log(" ip = ", Hex(_state.ip, Hex::PREFIX, Hex::PAD)); + log(" sp_el1 = ", Hex(_state.sp_el1, Hex::PREFIX, Hex::PAD)); + log(" elr_el1 = ", Hex(_state.elr_el1, Hex::PREFIX, Hex::PAD)); + log(" pstate = ", Hex(_state.pstate, Hex::PREFIX, Hex::PAD)); + log(" exception = ", _state.exception_type, " (", + lambda(_state.exception_type), ")"); + log(" esr_el2 = ", Hex(_state.esr_el2, Hex::PREFIX, Hex::PAD)); + _timer.dump(); +} + + +void Cpu::recall() +{ + Genode::Signal_transmitter(_vm_handler).submit(); +}; + + +Cpu::Cpu(Vm & vm, + Genode::Vm_connection & vm_session, + Mmio_bus & bus, + Gic & gic, + Genode::Env & env, + Genode::Heap & heap, + Genode::Entrypoint & ep) +: _vm(vm), + _vm_session(vm_session), + _heap(heap), + _vm_handler(*this, ep, *this, &Cpu::_handle_nothing), + _vcpu_id(_vm_session.with_upgrade([&]() { + return _vm_session.create_vcpu(heap, env, _vm_handler); + })), + _state(*((State*)env.rm().attach(_vm_session.cpu_state(_vcpu_id)))), + // op0, crn, op1, crm, op2, writeable, reset value + _sr_id_aa64afr0_el1 (3, 0, 0, 5, 4, "ID_AA64AFR0_EL1", false, 0x0, _reg_tree), + _sr_id_aa64afr1_el1 (3, 0, 0, 5, 5, "ID_AA64AFR1_EL1", false, 0x0, _reg_tree), + _sr_id_aa64dfr0_el1 (3, 0, 0, 5, 0, "ID_AA64DFR0_EL1", false, 0x6, _reg_tree), + _sr_id_aa64dfr1_el1 (3, 0, 0, 5, 1, "ID_AA64DFR1_EL1", false, 0x0, _reg_tree), + _sr_id_aa64isar0_el1(3, 0, 0, 6, 0, "ID_AA64ISAR0_EL1", false, _state.id_aa64isar0_el1, _reg_tree), + _sr_id_aa64isar1_el1(3, 0, 0, 6, 1, "ID_AA64ISAR1_EL1", false, _state.id_aa64isar1_el1, _reg_tree), + _sr_id_aa64mmfr0_el1(3, 0, 0, 7, 0, "ID_AA64MMFR0_EL1", false, _state.id_aa64mmfr0_el1, _reg_tree), + _sr_id_aa64mmfr1_el1(3, 0, 0, 7, 1, "ID_AA64MMFR1_EL1", false, _state.id_aa64mmfr1_el1, _reg_tree), + _sr_id_aa64mmfr2_el1(3, 0, 0, 7, 2, "ID_AA64MMFR2_EL1", false, _state.id_aa64mmfr2_el1, _reg_tree), + _sr_id_aa64pfr0_el1 (_state.id_aa64pfr0_el1, _reg_tree), + _sr_id_aa64pfr1_el1 (3, 0, 0, 4, 1, "ID_AA64PFR1_EL1", false, 0x0, _reg_tree), + _sr_id_aa64zfr0_el1 (3, 0, 0, 4, 4, "ID_AA64ZFR0_EL1", false, 0x0, _reg_tree), + _sr_aidr_el1 (3, 0, 1, 0, 7, "AIDR_EL1", false, 0x0, _reg_tree), + _sr_revidr_el1 (3, 0, 0, 0, 6, "REVIDR_EL1", false, 0x0, _reg_tree), + + _sr_clidr_el1 (3, 0, 1, 0, 1, "CLIDR_EL1", false, _state.clidr_el1, _reg_tree), + _sr_csselr_el1 (3, 0, 2, 0, 0, "CSSELR_EL1", true, 0x0, _reg_tree), + _sr_ctr_el0 (_reg_tree), + _sr_ccsidr_el1 (_sr_csselr_el1, _state, _reg_tree), + +//_sr_pmccfiltr_el0 (3, 14, 3, 15, 7, "PMCCFILTR_EL0", true, 0x0, _reg_tree), + _sr_pmuserenr_el0 (3, 9, 3, 14, 0, "PMUSEREN_EL0", true, 0x0, _reg_tree), + _sr_dbgbcr0 (2, 0, 0, 0, 5, "DBGBCR_EL1", true, 0x0, _reg_tree), + _sr_dbgbvr0 (2, 0, 0, 0, 4, "DBGBVR_EL1", true, 0x0, _reg_tree), + _sr_dbgwcr0 (2, 0, 0, 0, 7, "DBGWCR_EL1", true, 0x0, _reg_tree), + _sr_dbgwvr0 (2, 0, 0, 0, 6, "DBGWVR_EL1", true, 0x0, _reg_tree), + _sr_mdscr (2, 0, 0, 2, 2, "MDSCR_EL1", true, 0x0, _reg_tree), + _sr_osdlr (2, 1, 0, 3, 4, "OSDLR_EL1", true, 0x0, _reg_tree), + _sr_oslar (2, 1, 0, 0, 4, "OSLAR_EL1", true, 0x0, _reg_tree), + _sr_sgi1r_el1 (_reg_tree, vm), + _gic(*this, gic, bus), + _timer(env, ep, _gic.irq(27), *this) +{ + _state.pstate = 0b1111000101; /* el1 mode and IRQs disabled */ + _state.vmpidr_el2 = cpu_id(); +} diff --git a/repos/os/src/server/vmm/spec/arm_v8/cpu.h b/repos/os/src/server/vmm/spec/arm_v8/cpu.h new file mode 100644 index 000000000..664059ddc --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/cpu.h @@ -0,0 +1,331 @@ +/* + * \brief VMM cpu object + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__CPU_H_ +#define _SRC__SERVER__VMM__CPU_H_ + +#include <exception.h> +#include <generic_timer.h> + +#include <base/env.h> +#include <base/heap.h> +#include <cpu/vm_state_virtualization.h> +#include <util/mmio.h> +#include <vm_session/connection.h> + +namespace Vmm { + class Vm; + class Cpu; + Genode::Lock & lock(); +} + +class Vmm::Cpu +{ + public: + + using State = Genode::Vm_state; + + struct Esr : Genode::Register<32> + { + struct Ec : Bitfield<26, 6> + { + enum { + WFI = 0x1, + HVC = 0x16, + MRS_MSR = 0x18, + DA = 0x24, + BRK = 0x3c + }; + }; + }; + + Cpu(Vm & vm, + Genode::Vm_connection & vm_session, + Mmio_bus & bus, + Gic & gic, + Genode::Env & env, + Genode::Heap & heap, + Genode::Entrypoint & ep); + + unsigned cpu_id() const; + void run(); + void pause(); + bool active() const; + State & state() const; + Gic::Gicd_banked & gic(); + void dump(); + void handle_exception(); + void recall(); + + template <typename FUNC> + void handle_signal(FUNC handler) + { + Genode::Lock::Guard guard(lock()); + + if (active()) { + pause(); + handle_exception(); + } + + handler(); + _update_state(); + if (active()) run(); + } + + template <typename T> + struct Signal_handler : Genode::Vm_handler<Signal_handler<T>> + { + using Base = Genode::Vm_handler<Signal_handler<T>>; + + Cpu & cpu; + T & obj; + void (T::*member)(); + + void handle() + { + try { + cpu.handle_signal([this] () { (obj.*member)(); }); + } catch(Exception &e) { + Genode::error(e); + cpu.dump(); + } + } + + Signal_handler(Cpu & cpu, + Genode::Entrypoint & ep, + T & o, + void (T::*f)()) + : Base(ep, *this, &Signal_handler::handle), + cpu(cpu), obj(o), member(f) {} + }; + + private: + + enum Exception_type { + AARCH64_SYNC = 0x400, + AARCH64_IRQ = 0x480, + AARCH64_FIQ = 0x500, + AARCH64_SERROR = 0x580, + AARCH32_SYNC = 0x600, + AARCH32_IRQ = 0x680, + AARCH32_FIQ = 0x700, + AARCH32_SERROR = 0x780, + NO_EXCEPTION = 0xffff + }; + + class System_register : public Genode::Avl_node<System_register> + { + private: + + const Esr::access_t _encoding; + const char *_name; + const bool _writeable; + Genode::uint64_t _value; + + public: + + struct Iss : Esr + { + struct Direction : Bitfield<0, 1> {}; + struct Crm : Bitfield<1, 4> {}; + struct Register : Bitfield<5, 5> {}; + struct Crn : Bitfield<10, 4> {}; + struct Opcode1 : Bitfield<14, 3> {}; + struct Opcode2 : Bitfield<17, 3> {}; + struct Opcode0 : Bitfield<20, 2> {}; + + static access_t value(unsigned op0, + unsigned crn, + unsigned op1, + unsigned crm, + unsigned op2); + + static access_t mask_encoding(access_t v); + }; + + System_register(unsigned op0, + unsigned crn, + unsigned op1, + unsigned crm, + unsigned op2, + const char * name, + bool writeable, + Genode::addr_t v, + Genode::Avl_tree<System_register> & tree); + + const char * name() const { return _name; } + const bool writeable() const { return _writeable; } + + System_register * find_by_encoding(Iss::access_t e) + { + if (e == _encoding) return this; + + System_register * r = + Avl_node<System_register>::child(e > _encoding); + return r ? r->find_by_encoding(e) : nullptr; + } + + virtual void write(Genode::addr_t v) { + _value = (Genode::addr_t)v; } + + virtual Genode::addr_t read() const { + return (Genode::addr_t)(_value); } + + + /************************ + ** Avl node interface ** + ************************/ + + bool higher(System_register *r) { + return (r->_encoding > _encoding); } + }; + + class Id_aa64pfr0 : public System_register, + public Genode::Register<64> + { + private: + + struct El0 : Bitfield<0, 4> { enum { AARCH64_ONLY = 1 }; }; + struct El1 : Bitfield<4, 4> { enum { AARCH64_ONLY = 1 }; }; + struct El2 : Bitfield<8, 4> { enum { NOT_IMPLEMENTED }; }; + struct El3 : Bitfield<12, 4> { enum { NOT_IMPLEMENTED }; }; + struct Ras : Bitfield<28, 4> { enum { NOT_IMPLEMENTED }; }; + struct Sve : Bitfield<32, 4> { enum { NOT_IMPLEMENTED }; }; + + access_t _reset_value(access_t orig) + { + El0::set(orig, El0::AARCH64_ONLY); + El1::set(orig, El1::AARCH64_ONLY); + El2::set(orig, El2::NOT_IMPLEMENTED); + El3::set(orig, El3::NOT_IMPLEMENTED); + Ras::set(orig, Ras::NOT_IMPLEMENTED); + Sve::set(orig, Sve::NOT_IMPLEMENTED); + return orig; + } + + public: + + Id_aa64pfr0(Genode::uint64_t id_aa64pfr0, + Genode::Avl_tree<System_register> & tree) + : System_register(3, 0, 0, 4, 0, "ID_AA64PFR0_EL1", false, + _reset_value(id_aa64pfr0), tree) {} + }; + + struct Ccsidr : System_register + { + System_register & csselr; + State & state; + + Ccsidr(System_register &csselr, + State & state, + Genode::Avl_tree<System_register> & tree) + : System_register(3, 0, 1, 0, 0, "CCSIDR_EL1", false, 0x0, tree), + csselr(csselr), state(state) {} + + virtual Genode::addr_t read() const override; + }; + + struct Ctr_el0 : System_register + { + Ctr_el0(Genode::Avl_tree<System_register> & tree) + : System_register(3, 0, 3, 0, 1, "CTR_EL0", false, 0x0, tree) {} + + virtual Genode::addr_t read() const override; + }; + + struct Icc_sgi1r_el1 : System_register + { + Vm & vm; + + Icc_sgi1r_el1(Genode::Avl_tree<System_register> & tree, Vm & vm) + : System_register(3, 12, 0, 11, 5, "SGI1R_EL1", true, 0x0, tree), + vm(vm) {} + + virtual void write(Genode::addr_t v) override; + }; + + bool _active { true }; + Vm & _vm; + Genode::Vm_connection & _vm_session; + Genode::Heap & _heap; + Signal_handler<Cpu> _vm_handler; + Genode::Vm_session::Vcpu_id _vcpu_id; + State & _state; + Genode::Avl_tree<System_register> _reg_tree; + + /****************************** + ** Identification registers ** + ******************************/ + + System_register _sr_id_aa64afr0_el1; + System_register _sr_id_aa64afr1_el1; + System_register _sr_id_aa64dfr0_el1; + System_register _sr_id_aa64dfr1_el1; + System_register _sr_id_aa64isar0_el1; + System_register _sr_id_aa64isar1_el1; + System_register _sr_id_aa64mmfr0_el1; + System_register _sr_id_aa64mmfr1_el1; + System_register _sr_id_aa64mmfr2_el1; + Id_aa64pfr0 _sr_id_aa64pfr0_el1; + System_register _sr_id_aa64pfr1_el1; + System_register _sr_id_aa64zfr0_el1; + System_register _sr_aidr_el1; + System_register _sr_revidr_el1; + + /********************* + ** Cache registers ** + *********************/ + + System_register _sr_clidr_el1; + System_register _sr_csselr_el1; + Ctr_el0 _sr_ctr_el0; + Ccsidr _sr_ccsidr_el1; + + /*********************************** + ** Performance monitor registers ** + ***********************************/ + + System_register _sr_pmuserenr_el0; + + /***************************** + ** Debug monitor registers ** + *****************************/ + + System_register _sr_dbgbcr0; + System_register _sr_dbgbvr0; + System_register _sr_dbgwcr0; + System_register _sr_dbgwvr0; + System_register _sr_mdscr; + System_register _sr_osdlr; + System_register _sr_oslar; + + /*********************** + ** Local peripherals ** + ***********************/ + + Icc_sgi1r_el1 _sr_sgi1r_el1; + Gic::Gicd_banked _gic; + Generic_timer _timer; + + void _handle_nothing() {} + bool _handle_sys_reg(); + void _handle_brk(); + void _handle_wfi(); + void _handle_sync(); + void _handle_irq(); + void _handle_data_abort(); + void _handle_hyper_call(); + void _update_state(); +}; + +#endif /* _SRC__SERVER__VMM__CPU_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/exception.h b/repos/os/src/server/vmm/spec/arm_v8/exception.h new file mode 100644 index 000000000..d155d5a38 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/exception.h @@ -0,0 +1,22 @@ +/* + * \brief VMM exception handling + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__EXCEPTION_H_ +#define _SRC__SERVER__VMM__EXCEPTION_H_ + +#include <util/string.h> + +namespace Vmm { using Exception = Genode::String<128>; } + +#endif /* _SRC__SERVER__VMM__EXCEPTION_H_ */ + diff --git a/repos/os/src/server/vmm/spec/arm_v8/generic_timer.cc b/repos/os/src/server/vmm/spec/arm_v8/generic_timer.cc new file mode 100644 index 000000000..003434053 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/generic_timer.cc @@ -0,0 +1,116 @@ +/* + * \brief VMM ARM Generic timer device model + * \author Stefan Kalkowski + * \date 2019-08-20 + */ + +/* + * Copyright (C) 2019 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 <cpu.h> +#include <generic_timer.h> + +using Vmm::Generic_timer; + +Genode::uint64_t Generic_timer::_ticks_per_ms() +{ + static Genode::uint64_t ticks_per_ms = 0; + if (!ticks_per_ms) { + Genode::uint32_t freq = 0; + asm volatile("mrs %0, cntfrq_el0" : "=r" (freq)); + ticks_per_ms = freq / 1000; + } + return ticks_per_ms; +} + + +bool Generic_timer::_enabled() { + return Ctrl::Enabled::get(_cpu.state().timer.control); } + + +bool Generic_timer::_masked() { + return Ctrl::Imask::get(_cpu.state().timer.control); } + + +bool Generic_timer::_pending() { + return Ctrl::Istatus::get(_cpu.state().timer.control); } + + +void Generic_timer::_handle_timeout(Genode::Duration) +{ + _cpu.handle_signal([this] (void) { + if (_enabled() && !_masked()) handle_irq(); + }); +} + + +Genode::uint64_t Generic_timer::_usecs_left() +{ + Genode::uint64_t count; + asm volatile("mrs %0, cntpct_el0" : "=r" (count)); + count -= _cpu.state().timer.offset; + if (count > _cpu.state().timer.compare) return 0; + return Genode::timer_ticks_to_us(_cpu.state().timer.compare - count, + _ticks_per_ms()); +} + + +Generic_timer::Generic_timer(Genode::Env & env, + Genode::Entrypoint & ep, + Gic::Irq & irq, + Cpu & cpu) +: _timer(env, ep), + _timeout(_timer, *this, &Generic_timer::_handle_timeout), + _irq(irq), + _cpu(cpu) +{ + _cpu.state().timer.irq = true; + _irq.handler(*this); +} + + +void Generic_timer::schedule_timeout() +{ + if (_pending()) { + handle_irq(); + return; + } + + if (_enabled()) { + if (_usecs_left()) { + _timeout.schedule(Genode::Microseconds(_usecs_left())); + } else _handle_timeout(Genode::Duration(Genode::Microseconds(0))); + } +} + + +void Generic_timer::cancel_timeout() +{ + if (_timeout.scheduled()) _timeout.discard(); +} + + +void Generic_timer::handle_irq() +{ + _irq.assert(); + _cpu.state().timer.irq = false; +} + + +void Generic_timer::eoi() +{ + _cpu.state().timer.irq = true; +}; + + +void Generic_timer::dump() +{ + using namespace Genode; + + log(" timer.ctl = ", Hex(_cpu.state().timer.control, Hex::PREFIX, Hex::PAD)); + log(" timer.cmp = ", Hex(_cpu.state().timer.compare, Hex::PREFIX, Hex::PAD)); +} diff --git a/repos/os/src/server/vmm/spec/arm_v8/generic_timer.h b/repos/os/src/server/vmm/spec/arm_v8/generic_timer.h new file mode 100644 index 000000000..09ccacc36 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/generic_timer.h @@ -0,0 +1,74 @@ +/* + * \brief VMM ARM Generic timer device model + * \author Stefan Kalkowski + * \date 2019-08-20 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__GENERIC_TIMER_H_ +#define _SRC__SERVER__VMM__GENERIC_TIMER_H_ + +#include <gic.h> + +#include <cpu/vm_state_virtualization.h> +#include <drivers/timer/util.h> +#include <timer_session/connection.h> +#include <util/register.h> + +namespace Vmm { + class Cpu; + class Generic_timer; +} + +class Vmm::Generic_timer : Gic::Irq::Irq_handler +{ + private: + + Timer::Connection _timer; + Timer::One_shot_timeout<Generic_timer> _timeout; + Gic::Irq & _irq; + Cpu & _cpu; + + struct Ctrl : Genode::Register<32> + { + struct Enabled : Bitfield<0,1> {}; + struct Imask : Bitfield<1,1> {}; + struct Istatus : Bitfield<2,1> {}; + }; + + Genode::uint64_t _ticks_per_ms(); + + bool _enabled(); + bool _masked(); + bool _pending(); + + void _handle_timeout(Genode::Duration); + Genode::uint64_t _usecs_left(); + + public: + + Generic_timer(Genode::Env & env, + Genode::Entrypoint & ep, + Gic::Irq & irq, + Cpu & cpu); + + void schedule_timeout(); + void cancel_timeout(); + void handle_irq(); + void dump(); + + + /***************** + ** Irq_handler ** + *****************/ + + void eoi() override; +}; + +#endif /* _SRC__SERVER__VMM__GENERIC_TIMER_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/gic.h b/repos/os/src/server/vmm/spec/arm_v8/gic.h new file mode 100644 index 000000000..96b015824 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/gic.h @@ -0,0 +1,440 @@ +/* + * \brief VMM ARM Generic Interrupt Controller device model + * \author Stefan Kalkowski + * \date 2019-08-05 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__GIC_H_ +#define _SRC__SERVER__VMM__GIC_H_ + +#include <mmio.h> + +#include <base/env.h> +#include <drivers/defs/arm_v7.h> +#include <util/list.h> +#include <util/register.h> +#include <util/reconstructible.h> + +namespace Vmm { class Gic; } + +class Vmm::Gic : public Vmm::Mmio_device +{ + public: + + enum Irqs { + MAX_SGI = 16, + MAX_PPI = 16, + MAX_SPI = 992, + MAX_IRQ = 1020, + SPURIOUS = 1023, + }; + + class Irq : public Genode::List<Irq>::Element + { + public: + + struct List : Genode::List<Irq> + { + void insert(Irq & irq); + Irq * highest_enabled(); + }; + + struct Irq_handler { + virtual void eoi() {}; + virtual void enabled() {}; + virtual void disabled() {}; + }; + + enum Type { SGI, PPI, SPI }; + enum State { INACTIVE, ACTIVE, PENDING, ACTIVE_PENDING }; + enum Config { LEVEL, EDGE }; + + Irq(unsigned num, Type t, List &pending_list); + + bool enabled() const; + bool active() const; + bool pending() const; + bool level() const; + unsigned number() const; + Genode::uint8_t priority() const; + Genode::uint8_t target() const; + + void enable(); + void disable(); + void activate(); + void deactivate(); + void assert(); + void deassert(); + void level(bool l); + void priority(Genode::uint8_t p); + void target(Genode::uint8_t t); + void handler(Irq_handler & handler); + + private: + + Irq(Irq const &); + Irq &operator = (Irq const &); + + bool _enabled { false }; + Type _type { SPI }; + State _state { INACTIVE }; + Config _config { LEVEL }; + unsigned _num { 0 }; + Genode::uint8_t _prio { 0 }; + Genode::uint8_t _target { 1 }; + List & _pending_list; + Irq_handler * _handler { nullptr }; + }; + + struct Irq_reg: Mmio_register + { + unsigned const irq_count; + + virtual Register read(Irq & irq) { return 0; } + virtual void write(Irq & irq, Register reg) { } + + Register read(Address_range & access, Cpu&) override; + void write(Address_range & access, Cpu&, Register value) override; + + Irq_reg(Mmio_register::Name name, + Mmio_register::Type type, + Genode::uint64_t start, + unsigned bits_per_irq, + unsigned irq_count) + : Mmio_register(name, type, start, bits_per_irq*irq_count/8), + irq_count(irq_count) {} + }; + + class Gicd_banked + { + public: + + Irq & irq(unsigned num); + void handle_irq(); + bool pending_irq(); + + Gicd_banked(Cpu & cpu, Gic & gic, Mmio_bus & bus); + + private: + + Cpu & _cpu; + Gic & _gic; + Genode::Constructible<Irq> _sgi[MAX_SGI]; + Genode::Constructible<Irq> _ppi[MAX_PPI]; + Irq::List _pending_list; + + struct Redistributor : Mmio_device + { + unsigned cpu_id; + bool last; + Mmio_register gicr_ctlr { "GICR_CTLR", Mmio_register::RO, + 0x0, 4, 0b10010 }; + Mmio_register gicr_typer { "GICR_TYPER", Mmio_register::RO, + 0x8, 8, (Genode::uint64_t)cpu_id<<32 | cpu_id<<8 | (last ? 1<<4 : 0) }; + Mmio_register gicr_waker { "GICR_WAKER", Mmio_register::RO, + 0x14, 4, 0 }; + Mmio_register gicr_pidr2 { "GICR_PIDR2", Mmio_register::RO, + 0xffe8, 4, (3<<4) }; + Mmio_register gicr_igroupr0 { "GICR_IGROUPR0", Mmio_register::RO, + 0x10080, 4, 0 }; + + struct Gicr_isenabler0 : Irq_reg + { + Register read(Irq & irq) { return irq.enabled(); } + void write(Irq & irq, Register v) { if (v) irq.enable(); } + + Gicr_isenabler0() + : Irq_reg("GICR_ISENABLER0", Mmio_register::RW, 0x10100, 1, 32) {} + } gicr_isenabler0; + + struct Gicr_icenabler0 : Irq_reg + { + Register read(Irq & irq) { return irq.enabled(); } + void write(Irq & irq, Register v) { if (v) irq.disable(); } + + Gicr_icenabler0() + : Irq_reg("GICR_ICENABLER0", Mmio_register::RW, 0x10180, 1, 32) {} + } gicr_icenabler0; + + struct Gicr_ispendr0 : Irq_reg + { + Register read(Irq & irq) { return irq.pending(); } + void write(Irq & irq, Register v) { if (v) irq.assert(); } + + Gicr_ispendr0() + : Irq_reg("GICR_ISPENDR0", Mmio_register::RW, 0x10200, 1, 32) {} + } gicr_ispendr0; + + struct Gicr_icpendr0 : Irq_reg + { + Register read(Irq & irq) { return irq.pending(); } + void write(Irq & irq, Register v) { if (v) irq.deassert(); } + + Gicr_icpendr0() + : Irq_reg("GICR_ICPENDR0", Mmio_register::RW, 0x10280, 1, 32) {} + } gicr_icpendr0; + + struct Gicr_isactiver0 : Irq_reg + { + Register read(Irq & irq) { return irq.active(); } + void write(Irq & irq, Register v) { if (v) irq.activate(); } + + Gicr_isactiver0() + : Irq_reg("GICR_ISACTIVER0", Mmio_register::RW, 0x10300, 1, 32) {} + } gicr_isactiver0; + + struct Gicr_icactiver0 : Irq_reg + { + Register read(Irq & irq) { return irq.active(); } + void write(Irq & irq, Register v) { if (v) irq.deactivate(); } + + Gicr_icactiver0() + : Irq_reg("GICR_ICACTIVER0", Mmio_register::RW, 0x10380, 1, 32) {} + } gicr_icactiver0; + + struct Gicr_ipriorityr : Irq_reg + { + Register read(Irq & irq) { return irq.priority(); } + void write(Irq & irq, Register v) { irq.priority(v); } + + Gicr_ipriorityr() + : Irq_reg("GICR_IPRIORITYR", Mmio_register::RW, 0x10400, 8, 32) {} + } gicr_ipriorityr; + + struct Gicr_icfgr : Irq_reg + { + Register read(Irq & irq) { return irq.level() ? 0 : 1; } + void write(Irq & irq, Register v) { irq.level(!v); } + + Gicr_icfgr() + : Irq_reg("GICR_ICFGR", Mmio_register::RW, 0x10c00, 8, 32) {} + } gicr_icfgr; + + Redistributor(const Genode::uint64_t addr, + const Genode::uint64_t size, + unsigned cpu_id, + bool last) + : Mmio_device("GICR", addr, size), cpu_id(cpu_id), last(last) + { + add(gicr_ctlr); + add(gicr_typer); + add(gicr_waker); + add(gicr_pidr2); + add(gicr_igroupr0); + add(gicr_isenabler0); + add(gicr_icenabler0); + add(gicr_ispendr0); + add(gicr_icpendr0); + add(gicr_isactiver0); + add(gicr_icactiver0); + add(gicr_ipriorityr); + add(gicr_icfgr); + } + }; + + Genode::Constructible<Redistributor> _rdist; + }; + + Gic(const char * const name, + const Genode::uint64_t addr, + const Genode::uint64_t size, + Mmio_bus & bus, + Genode::Env & env); + + private: + + friend struct Gicd_banked; + + Genode::Constructible<Irq> _spi[MAX_SPI]; + Irq::List _pending_list; + unsigned _cpu_cnt { 2 }; /* FIXME: smp support */ + unsigned _version { 3 }; /* FIXME: version support */ + + struct Gicd_ctlr : Genode::Register<32>, Mmio_register + { + struct Enable : Bitfield<0, 1> {}; + struct Disable : Bitfield<6, 1> {}; + + void write(Address_range & access, Cpu & cpu, + Mmio_register::Register value) override + { + access_t v = value; + Disable::set(v, 0); + Mmio_register::write(access, cpu, v); + } + + Gicd_ctlr() + : Mmio_register("GICD_CTLR", Mmio_register::RW, 0, 4, 0) {} + } _ctrl; + + struct Gicd_typer : Genode::Register<32>, Mmio_register + { + struct It_lines_number : Bitfield<0, 5> {}; + struct Cpu_number : Bitfield<5, 3> {}; + struct Id_bits : Bitfield<19, 5> {}; + + Gicd_typer(unsigned cpus) + : Mmio_register("GICD_TYPER", Mmio_register::RO, 0x4, 4, + It_lines_number::bits(31) | Cpu_number::bits(cpus-1) | Id_bits::bits(9)) {} + } _typer { _cpu_cnt }; + + struct Gicd_iidr : Genode::Register<32>, Mmio_register + { + struct Implementer : Bitfield<0, 12> {}; + struct Revision : Bitfield<12, 4> {}; + struct Variant : Bitfield<16, 4> {}; + struct Product_id : Bitfield<24, 8> {}; + + Gicd_iidr() + : Mmio_register("GICD_IIDR", Mmio_register::RO, 0x8, 4, 0x123) {} + } _iidr; + + struct Gicd_igroupr : Irq_reg + { + Gicd_igroupr() + : Irq_reg("GICD_IGROUPR", Mmio_register::RW, 0x80, 1, 1024) {} + } _igroupr; + + struct Gicd_isenabler : Irq_reg + { + Register read(Irq & irq) { return irq.enabled(); } + void write(Irq & irq, Register v) { if (v) irq.enable(); } + + Gicd_isenabler() + : Irq_reg("GICD_ISENABLER", Mmio_register::RW, 0x100, 1, 1024) {} + } _isenabler; + + struct Gicd_icenabler : Irq_reg + { + Register read(Irq & irq) { return irq.enabled(); } + void write(Irq & irq, Register v) { if (v) irq.disable(); } + + Gicd_icenabler() + : Irq_reg("GICD_ICENABLER", Mmio_register::RW, 0x180, 1, 1024) {} + } _csenabler; + + struct Gicd_ispendr : Irq_reg + { + Register read(Irq & irq) { return irq.pending(); } + void write(Irq & irq, Register v) { if (v) irq.assert(); } + + Gicd_ispendr() + : Irq_reg("GICD_ISPENDR", Mmio_register::RW, 0x200, 1, 1024) {} + } _ispendr; + + struct Gicd_icpendr : Irq_reg + { + Register read(Irq & irq) { return irq.pending(); } + void write(Irq & irq, Register v) { if (v) irq.deassert(); } + + Gicd_icpendr() + : Irq_reg("GICD_ICPENDR", Mmio_register::RW, 0x280, 1, 1024) {} + } _icpendr; + + struct Gicd_isactiver : Irq_reg + { + Register read(Irq & irq) { return irq.active(); } + void write(Irq & irq, Register v) { if (v) irq.activate(); } + + Gicd_isactiver() + : Irq_reg("GICD_ISACTIVER", Mmio_register::RW, 0x300, 1, 1024) {} + } _isactiver; + + struct Gicd_icactiver : Irq_reg + { + Register read(Irq & irq) { return irq.active(); } + void write(Irq & irq, Register v) { if (v) irq.deactivate(); } + + Gicd_icactiver() + : Irq_reg("GICD_ICACTIVER", Mmio_register::RW, 0x380, 1, 1024) {} + } _icactiver; + + struct Gicd_ipriorityr : Irq_reg + { + Register read(Irq & irq) { return irq.priority(); } + void write(Irq & irq, Register v) { irq.priority(v); } + + Gicd_ipriorityr() + : Irq_reg("GICD_IPRIORITYR", Mmio_register::RW, 0x400, 8, 1024) {} + } _ipriorityr; + + struct Gicd_itargetr : Irq_reg + { + Register read(Irq & irq) { return irq.target(); } + void write(Irq & irq, Register v) { irq.target(v); } + + Gicd_itargetr() + : Irq_reg("GICD_ITARGETSR", Mmio_register::RW, 0x800, 8, 1024) {} + } _itargetr; + + + struct Gicd_icfgr : Irq_reg + { + Register read(Irq & irq) { return irq.level() ? 0 : 1; } + void write(Irq & irq, Register v) { irq.level(!v); } + + Gicd_icfgr() + : Irq_reg("GICD_ICFGR", Mmio_register::RW, 0xc00, 8, 1024) {} + } _icfgr; + + struct Gicd_sgir : Genode::Register<32>, Mmio_register + { + struct Enable : Bitfield<0, 1> {}; + struct Disable : Bitfield<6, 1> {}; + + void write(Address_range & access, Cpu & cpu, + Mmio_register::Register value) override + { + Genode::error("SGIR WRITE ", value); + } + + Gicd_sgir() + : Mmio_register("GICD_SGIR", Mmio_register::WO, 0xf00, 4, 0) {} + } _sgir; + + + struct Gicd_irouter : Irq_reg + { + Register read(Irq &) { return 0x0; } // FIXME smp + void write(Irq &, Register) { } + + Gicd_irouter() + : Irq_reg("GICD_IROUTER", Mmio_register::RW, 0x6100, 64, 1024) {} + } _irouter; + + /** + * FIXME: missing registers: + * GICD_IGROUP = 0x80, + * GICD_NSACR = 0xe00, + * GICD_SGIR = 0xf00, + * GICD_CPENDSGIR0 = 0xf10, + * GICD_SPENDSGIR0 = 0xf20, + * GICD identification registers 0xfd0... + */ + + /** + * Dummy container for holding array of noncopyable objects + * Workaround for gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70395 + */ + struct Dummy { + Mmio_register regs[8]; + } _reg_container { .regs = { + { "GICD_PIDR4", Mmio_register::RO, 0xffd0, 4, 0x0 }, + { "GICD_PIDR5", Mmio_register::RO, 0xffd4, 4, 0x0 }, + { "GICD_PIDR6", Mmio_register::RO, 0xffd8, 4, 0x0 }, + { "GICD_PIDR7", Mmio_register::RO, 0xffdc, 4, 0x0 }, + { "GICD_PIDR0", Mmio_register::RO, 0xffe0, 4, 0x492 }, + { "GICD_PIDR1", Mmio_register::RO, 0xffe4, 4, 0xb0 }, + { "GICD_PIDR2", Mmio_register::RO, 0xffe8, 4, (_version<<4) | 0xb }, + { "GICD_PIDR3", Mmio_register::RO, 0xffec, 4, 0x44 } + }}; +}; + +#endif /* _SRC__SERVER__VMM__GIC_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/gicv2.cc b/repos/os/src/server/vmm/spec/arm_v8/gicv2.cc new file mode 100644 index 000000000..05bc1cc83 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/gicv2.cc @@ -0,0 +1,251 @@ +/* + * \brief VMM ARM Generic Interrupt Controller v2 device model + * \author Stefan Kalkowski + * \date 2019-08-05 + */ + +/* + * Copyright (C) 2019 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 <cpu.h> +#include <gic.h> +#include <vm.h> + +using Vmm::Gic; +using Register = Vmm::Mmio_register::Register; + +bool Gic::Irq::enabled() const { return _enabled; } + +bool Gic::Irq::active() const { + return _state == ACTIVE || _state == ACTIVE_PENDING; } + +bool Gic::Irq::pending() const { + return _state == PENDING || _state == ACTIVE_PENDING; } + +bool Gic::Irq::level() const { return _config == LEVEL; } + +unsigned Gic::Irq::number() const { return _num; } + +Genode::uint8_t Gic::Irq::priority() const { return _prio; } + +Genode::uint8_t Gic::Irq::target() const { return _target; } + + +void Gic::Irq::enable() +{ + _enabled = true; + if (_handler) _handler->enabled(); +} + + +void Gic::Irq::disable() +{ + _enabled = false; + if (_handler) _handler->disabled(); +} + + +void Gic::Irq::activate() +{ + switch (_state) { + case INACTIVE: return; + case PENDING: return; + case ACTIVE_PENDING: _state = PENDING; return; + case ACTIVE: _state = INACTIVE; return; + }; +} + + +void Gic::Irq::deactivate() +{ + switch (_state) { + case INACTIVE: return; + case PENDING: return; + case ACTIVE_PENDING: _state = PENDING; return; + case ACTIVE: _state = INACTIVE; return; + }; +} + + +void Gic::Irq::assert() +{ + if (pending()) return; + + _state = PENDING; + _pending_list.insert(*this); +} + + +void Gic::Irq::deassert() +{ + if (_state == INACTIVE) return; + + _state = INACTIVE; + _pending_list.remove(this); + if (_handler) _handler->eoi(); +} + + +void Gic::Irq::target(Genode::uint8_t t) +{ + if (_target == t) return; + + _target = t; +} + + +void Gic::Irq::level(bool l) +{ + if (level() == l) return; + + _config = l ? LEVEL : EDGE; +} + + +void Gic::Irq::priority(Genode::uint8_t p) +{ + if (_prio == p) return; + + _prio = p; +} + + +void Gic::Irq::handler(Gic::Irq::Irq_handler & handler) { _handler = &handler; } + + +Gic::Irq::Irq(unsigned num, Type t, Irq::List & l) +: _type(t), _num(num), _pending_list(l) {} + + +void Gic::Irq::List::insert(Irq & irq) +{ + Irq * i = first(); + while (i && i->priority() < irq.priority() && i->next()) i = i->next(); + Genode::List<Irq>::insert(&irq, i); +} + + +Gic::Irq * Gic::Irq::List::highest_enabled() +{ + Irq * i = first(); + while(i) { + if (i->enabled()) return i; + i = i->next(); + } + return nullptr; +} + + +Gic::Irq & Gic::Gicd_banked::irq(unsigned i) +{ + if (i < MAX_SGI) + return *_sgi[i]; + + if (i < MAX_SGI+MAX_PPI) + return *_ppi[i-MAX_SGI]; + + return *_gic._spi[i-MAX_SGI-MAX_PPI]; +} + + +void Gic::Gicd_banked::handle_irq() +{ + unsigned i = _cpu.state().irqs.virtual_irq; + if (i > MAX_IRQ) return; + + irq(i).deassert(); + + _cpu.state().irqs.virtual_irq = 1023; +} + + +bool Gic::Gicd_banked::pending_irq() +{ + if (_cpu.state().irqs.virtual_irq != 1023) return true; + + Irq * i = _gic._pending_list.highest_enabled(); + Irq * j = _pending_list.highest_enabled(); + Irq * n = j; + if (i && ((j && j->priority() > i->priority()) || !j)) n = i; + if (!n) return false; + _cpu.state().irqs.virtual_irq = n->number(); + n->activate(); + return true; +} + + +Gic::Gicd_banked::Gicd_banked(Cpu & cpu, Gic & gic, Mmio_bus & bus) +: _cpu(cpu), _gic(gic) +{ + for (unsigned i = 0; i < MAX_SGI; i++) + _sgi[i].construct(i, Irq::SGI, _pending_list); + + for (unsigned i = 0; i < MAX_PPI; i++) + _ppi[i].construct(i+MAX_SGI, Irq::PPI, _pending_list); + + _cpu.state().irqs.last_irq = 1023; + _cpu.state().irqs.virtual_irq = 1023; + + _rdist.construct(0x80a0000 + (cpu.cpu_id()*0x20000), 0x20000, cpu.cpu_id(), Vm::last_cpu() == cpu.cpu_id()); + bus.add(*_rdist); +} + + +Register Gic::Irq_reg::read(Address_range & access, Cpu & cpu) +{ + Register ret = 0; + + Register bits_per_irq = size * 8 / irq_count; + for (unsigned i = (access.start * 8) / bits_per_irq; + i < ((access.start+access.size) * 8) / bits_per_irq; i++) + ret |= read(cpu.gic().irq(i)) << (i % 32/bits_per_irq); + return ret; +} + + +void Gic::Irq_reg::write(Address_range & access, Cpu & cpu, Register value) +{ + Register bits_per_irq = size * 8 / irq_count; + Register irq_value_mask = (1<<bits_per_irq) - 1; + for (unsigned i = (access.start * 8) / bits_per_irq; + i < ((access.start+access.size) * 8) / bits_per_irq; i++) + write(cpu.gic().irq(i), (value >> (i % 32/bits_per_irq)) + & irq_value_mask); +} + + +Gic::Gic(const char * const name, + const Genode::uint64_t addr, + const Genode::uint64_t size, + Mmio_bus & bus, + Genode::Env & env) +: Mmio_device(name, addr, size) +{ + add(_ctrl); + add(_typer); + add(_iidr); + add(_igroupr); + add(_isenabler); + add(_csenabler); + add(_ispendr); + add(_icpendr); + add(_isactiver); + add(_icactiver); + add(_ipriorityr); + add(_itargetr); + add(_icfgr); + add(_irouter); + add(_sgir); + + for (unsigned i = 0; i < (sizeof(Dummy::regs) / sizeof(Mmio_register)); i++) + add(_reg_container.regs[i]); + + for (unsigned i = 0; i < MAX_SPI; i++) + _spi[i].construct(i+MAX_SGI+MAX_PPI, Irq::SPI, _pending_list); + + bus.add(*this); +} diff --git a/repos/os/src/server/vmm/spec/arm_v8/hw_device.h b/repos/os/src/server/vmm/spec/arm_v8/hw_device.h new file mode 100644 index 000000000..97bd14ca0 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/hw_device.h @@ -0,0 +1,125 @@ +/* + * \brief VMM dedicated hardware device passed-through to VM + * \author Stefan Kalkowski + * \date 2019-09-25 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__HW_DEVICE_H_ +#define _SRC__SERVER__VMM__HW_DEVICE_H_ + +#include <exception.h> +#include <mmio.h> +#include <gic.h> + +#include <base/attached_io_mem_dataspace.h> +#include <irq_session/connection.h> + +namespace Vmm { + template <unsigned, unsigned> class Hw_device; +} + + +template <unsigned MMIO_COUNT, unsigned IRQ_COUNT> +class Vmm::Hw_device +{ + private: + + class Irq : Gic::Irq::Irq_handler + { + private: + + using Session = Genode::Constructible<Genode::Irq_connection>; + + Gic::Irq & _irq; + Genode::Env & _env; + Session _session; + Cpu::Signal_handler<Irq> _handler; + + void _assert() + { + _irq.assert(); + } + + public: + + void enabled() override + { + if (!_session.constructed()) { + _session.construct(_env, _irq.number(), + _irq.level() ? + Genode::Irq_session::TRIGGER_LEVEL : + Genode::Irq_session::TRIGGER_EDGE); + _session->sigh(_handler); + _session->ack_irq(); + } + } + + void disabled() override + { + if (_session.constructed()) + _session.destruct(); + } + + void eoi() override + { + if (_session.constructed()) _session->ack_irq(); + } + + Irq(Gic::Irq & irq, Cpu & cpu, Genode::Env & env) + : _irq(irq), + _env(env), + _handler(cpu, env.ep(), *this, &Irq::_assert) + { + _irq.handler(*this); + } + }; + + Genode::Env & _env; + Genode::Vm_connection & _vm; + Cpu & _cpu; + + Genode::Constructible<Genode::Attached_io_mem_dataspace> _ds[MMIO_COUNT]; + Genode::Constructible<Irq> _irqs[IRQ_COUNT]; + + void mmio() { } + void irqs() { } + + public: + + Hw_device(Genode::Env &env, + Genode::Vm_connection &vm, + Cpu & cpu) + : _env(env), _vm(vm), _cpu(cpu) { }; + + template <typename... ARGS> + void mmio(Genode::addr_t start, Genode::size_t size, ARGS &&... args) + { + mmio(args...); + for (unsigned i = 0; i < MMIO_COUNT; i++) { + if (_ds[i].constructed()) continue; + _ds[i].construct(_env, start, size); + _vm.attach(_ds[i]->cap(), start); + return; + } + } + + template <typename... ARGS> + void irqs(unsigned irq, ARGS &&... args) + { + irqs(args...); + for (unsigned i = 0; i < IRQ_COUNT; i++) { + if (_irqs[i].constructed()) continue; + _irqs[i].construct(_cpu.gic().irq(irq), _cpu, _env); + return; + } + } +}; + +#endif /* _SRC__SERVER__VMM__HW_DEVICE_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/main.cc b/repos/os/src/server/vmm/spec/arm_v8/main.cc new file mode 100644 index 000000000..cdd6b19d2 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/main.cc @@ -0,0 +1,17 @@ +/* + * \brief VMM example for ARMv8 virtualization + * \author Stefan Kalkowski + * \date 2014-07-08 + */ + +/* + * Copyright (C) 2014-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 <vm.h> +#include <base/component.h> + +void Component::construct(Genode::Env & env) { static Vmm::Vm vm(env); } diff --git a/repos/os/src/server/vmm/spec/arm_v8/mmio.cc b/repos/os/src/server/vmm/spec/arm_v8/mmio.cc new file mode 100644 index 000000000..c7a1eb7fb --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/mmio.cc @@ -0,0 +1,126 @@ +/* + * \brief VMM mmio abstractions + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 <cpu.h> +#include <mmio.h> + +using namespace Vmm; + +Mmio_register::Register Mmio_register::read(Address_range & access, Cpu & cpu) +{ + if (_type == WO) + throw Exception("Invalid read access to register ", + _name, " ", access); + + using namespace Genode; + + switch (access.size) { + case 1: return *(uint8_t*) ((addr_t)&_value + access.start); + case 2: return *(uint16_t*) ((addr_t)&_value + access.start); + case 4: return *(uint32_t*) ((addr_t)&_value + access.start); + case 8: return _value; + default: return 0; + } +} + + +void Mmio_register::write(Address_range & access, Cpu & cpu, Register value) +{ + if (_type == RO) + throw Exception("Invalid write access to register ", + _name, " ", access); + + using namespace Genode; + + switch (access.size) { + case 1: *((uint8_t*) ((addr_t)&_value + access.start)) = value; + case 2: *((uint16_t*) ((addr_t)&_value + access.start)) = value; + case 4: *((uint32_t*) ((addr_t)&_value + access.start)) = value; + case 8: _value = value; + } +} + + +Mmio_register::Register Mmio_register::value() { return _value; } + + +void Mmio_register::set(Register value) { _value = value; } + + +Mmio_device::Register Mmio_device::read(Address_range & access, Cpu & cpu) +{ + Mmio_register & reg = _registers.get<Mmio_register>(access); + Address_range ar(access.start - reg.start, access.size); + return reg.read(ar, cpu); +} + + +void Mmio_device::write(Address_range & access, Cpu & cpu, Register value) +{ + Mmio_register & reg = _registers.get<Mmio_register>(access); + Address_range ar(access.start - reg.start, access.size); + reg.write(ar, cpu, value); +} + + +void Mmio_device::add(Mmio_register & reg) { _registers.add(reg); } + + +void Vmm::Mmio_bus::handle_memory_access(Vmm::Cpu & cpu) +{ + using namespace Genode; + + Cpu::State & state = cpu.state(); + + struct Iss : Cpu::Esr + { + struct Write : Bitfield<6, 1> {}; + struct Register : Bitfield<16, 5> {}; + struct Sign_extend : Bitfield<21, 1> {}; + struct Access_size : Bitfield<22, 2> { + enum { BYTE, HALFWORD, WORD, DOUBLEWORD }; }; + struct Valid : Bitfield<24, 1> {}; + + static bool valid(access_t v) { + return Valid::get(v) && !Sign_extend::get(v); } + + static bool write(access_t v) { return Write::get(v); } + static unsigned r(access_t v) { return Register::get(v); } + }; + + if (!Iss::valid(state.esr_el2)) + throw Exception("Mmio_bus: unknown ESR=", Genode::Hex(state.esr_el2)); + + bool wr = Iss::Write::get(state.esr_el2); + unsigned idx = Iss::Register::get(state.esr_el2); + uint64_t ipa = ((uint64_t)state.hpfar_el2 << 8) + + (state.far_el2 & ((1 << 12) - 1)); + uint64_t width = 1 << Iss::Access_size::get(state.esr_el2); + + try { + Address_range bus_range(ipa, width); + Mmio_device & dev = get<Mmio_device>(bus_range); + Address_range dev_range(ipa - dev.start,width); + if (wr) { + dev.write(dev_range, cpu, (idx == 31) ? 0 : state.r[idx]); + } else { + if (idx > 30) + throw Exception("Wrong register index when reading ", bus_range); + state.r[idx] = dev.read(dev_range, cpu); + } + } catch(Exception & e) { + Genode::warning(e); + Genode::warning("Will ignore invalid bus access (IPA=", + Genode::Hex(ipa), ")"); + } +} diff --git a/repos/os/src/server/vmm/spec/arm_v8/mmio.h b/repos/os/src/server/vmm/spec/arm_v8/mmio.h new file mode 100644 index 000000000..7b743b180 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/mmio.h @@ -0,0 +1,90 @@ +/* + * \brief VMM mmio abstractions + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__MMIO_H_ +#define _SRC__SERVER__VMM__MMIO_H_ + +#include <address_space.h> + +namespace Vmm { + class Cpu; + class Mmio_register; + class Mmio_device; + class Mmio_bus; +} + + +class Vmm::Mmio_register : public Vmm::Address_range +{ + public: + + enum Type { RO, WO, RW }; + + using Name = Genode::String<64>; + using Register = Genode::uint64_t; + + virtual Register read(Address_range & access, Cpu&); + virtual void write(Address_range & access, Cpu&, Register value); + void set(Register value); + Register value(); + + Mmio_register(Name name, + Type type, + Genode::uint64_t start, + Genode::uint64_t size, + Register reset_value = 0) + : Address_range(start, size), + _name(name), + _type(type), + _value(reset_value) { } + + protected: + + Name const _name; + Type const _type; + Register _value; + + bool _unaligned(Address_range & access); +}; + + +class Vmm::Mmio_device : public Vmm::Address_range +{ + public: + + using Name = Genode::String<64>; + using Register = Genode::uint64_t; + + virtual Register read(Address_range & access, Cpu&); + virtual void write(Address_range & access, Cpu&, Register value); + + void add(Mmio_register & reg); + + Mmio_device(Name name, + Genode::uint64_t start, + Genode::uint64_t size) + : Address_range(start, size), _name(name) { } + + private: + + Name const _name; + Address_space _registers; +}; + + +struct Vmm::Mmio_bus : Vmm::Address_space +{ + void handle_memory_access(Cpu & cpu); +}; + +#endif /* _SRC__SERVER__VMM__MMIO_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/pl011.cc b/repos/os/src/server/vmm/spec/arm_v8/pl011.cc new file mode 100644 index 000000000..e9903fd51 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/pl011.cc @@ -0,0 +1,102 @@ +/* + * \brief VMM PL011 serial device model + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 <cpu.h> +#include <pl011.h> + +using Vmm::Pl011; +using Register = Vmm::Mmio_register::Register; + +Register Pl011::Uartdr::read(Address_range&, Cpu&) +{ + ris.set(ris.value() & ~RX_MASK); + + if (!rx.empty()) return rx.get(); + + return 0; +} + + +void Pl011::Uartdr::write(Address_range&, Cpu&, Register reg) +{ + terminal.write(®, 1); +} + + +Register Pl011::Uartfr::read(Address_range&, Cpu&) +{ + return rx.empty() ? Rx_empty::bits(1) : Rx_full::bits(1); +} + + +void Pl011::Uartimsc::write(Address_range&, Cpu&, Register mask) +{ + if ((mask & RX_MASK) && !(value() & RX_MASK) && (ris.value() & RX_MASK)) + irq.assert(); + + set(mask); +} + + +Register Pl011::Uartmis::read(Address_range&, Cpu&) +{ + return ris.value() & imsc.value(); +} + + +void Pl011::Uarticr::write(Address_range & ar, Cpu &, Register value) +{ + ris.set(ris.value() & ~value); +} + + +void Pl011::_read() +{ + if (!_terminal.avail()) return; + + while (_terminal.avail()) { + unsigned char c = 0; + _terminal.read(&c, 1); + _rx_buf.add(c); + } + + _uart_ris.set(_uart_ris.value() | RX_MASK); + if (_uart_imsc.value() & RX_MASK) _irq.assert(); +} + + +Pl011::Pl011(const char * const name, + const Genode::uint64_t addr, + const Genode::uint64_t size, + unsigned irq, + Cpu & cpu, + Mmio_bus & bus, + Genode::Env & env) +: Mmio_device(name, addr, size), + _terminal(env), + _handler(cpu, env.ep(), *this, &Pl011::_read), + _irq(cpu.gic().irq(irq)) +{ + for (unsigned i = 0; i < (sizeof(Dummy::regs) / sizeof(Mmio_register)); i++) + add(_reg_container.regs[i]); + add(_uart_ris); + add(_uart_dr); + add(_uart_fr); + add(_uart_imsc); + add(_uart_mis); + add(_uart_icr); + + _terminal.read_avail_sigh(_handler); + + bus.add(*this); +} diff --git a/repos/os/src/server/vmm/spec/arm_v8/pl011.h b/repos/os/src/server/vmm/spec/arm_v8/pl011.h new file mode 100644 index 000000000..abd1f9b50 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/pl011.h @@ -0,0 +1,145 @@ +/* + * \brief VMM PL011 serial device model + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__PL011_H_ +#define _SRC__SERVER__VMM__PL011_H_ + +#include <os/ring_buffer.h> +#include <terminal_session/connection.h> + +#include <gic.h> + +namespace Vmm { + class Cpu; + class Pl011; +} + +class Vmm::Pl011 : public Vmm::Mmio_device +{ + private: + + using Ring_buffer = + Genode::Ring_buffer<char, 1024, + Genode::Ring_buffer_unsynchronized>; + + enum Mask : Genode::uint16_t { + RX_MASK = 1 << 4, + TX_MASK = 1 << 5 + }; + + Terminal::Connection _terminal; + Cpu::Signal_handler<Pl011> _handler; + Gic::Irq & _irq; + Ring_buffer _rx_buf; + Mmio_register _uart_ris { "UARTRIS", Mmio_register::RO, + 0x3c, 2 }; + + /** + * Dummy container for holding array of noncopyable objects + * Workaround for gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70395 + */ + struct Dummy { + Mmio_register regs[13]; + } _reg_container { .regs = { + { "UARTIBRD", Mmio_register::RW, 0x24, 2, 0 }, + { "UARTFBRD", Mmio_register::RW, 0x28, 2, 0 }, + { "UARTLCR_H", Mmio_register::RW, 0x2c, 2, 0 }, + { "UARTCR", Mmio_register::RW, 0x30, 2, 0x300 }, + { "UARTIFLS", Mmio_register::RW, 0x34, 2, 0x12 }, + { "UARTPERIPHID0", Mmio_register::RO, 0xfe0, 4, 0x11 }, + { "UARTPERIPHID1", Mmio_register::RO, 0xfe4, 4, 0x10 }, + { "UARTPERIPHID2", Mmio_register::RO, 0xfe8, 4, 0x14 }, + { "UARTPERIPHID3", Mmio_register::RO, 0xfec, 4, 0x0 }, + { "UARTPCELLID0", Mmio_register::RO, 0xff0, 4, 0xd }, + { "UARTPCELLID1", Mmio_register::RO, 0xff4, 4, 0xf0 }, + { "UARTPCELLID2", Mmio_register::RO, 0xff8, 4, 0x5 }, + { "UARTPCELLID3", Mmio_register::RO, 0xffc, 4, 0xb1 } + }}; + + struct Uartdr : Mmio_register + { + Terminal::Connection & terminal; + Ring_buffer & rx; + Mmio_register & ris; + + Register read(Address_range&, Cpu&) override; + void write(Address_range&, Cpu&, Register) override; + + Uartdr(Terminal::Connection & terminal, + Ring_buffer & rx, + Mmio_register & ris) + : Mmio_register("UARTDR", Mmio_register::RW, 0x0, 2), + terminal(terminal), rx(rx), ris(ris) {} + } _uart_dr { _terminal, _rx_buf, _uart_ris }; + + struct Uartfr : Mmio_register, Genode::Register<32> + { + struct Rx_empty : Bitfield<4, 1> {}; + struct Rx_full : Bitfield<6, 1> {}; + + Ring_buffer & rx; + + Mmio_register::Register read(Address_range&, Cpu&) override; + + Uartfr(Ring_buffer & rx) + : Mmio_register("UARTFR", Mmio_register::RO, 0x18, 4), rx(rx) {} + } _uart_fr { _rx_buf }; + + struct Uartimsc : Mmio_register + { + Gic::Irq & irq; + Mmio_register & ris; + + void write(Address_range&, Cpu&, Register) override; + + Uartimsc(Gic::Irq & irq, Mmio_register & ris) + : Mmio_register("UARTIMSC", Mmio_register::RW, 0x38, 2, 0xf), + irq(irq), ris(ris) {} + } _uart_imsc { _irq, _uart_ris }; + + struct Uartmis : Mmio_register + { + Mmio_register & ris; + Uartimsc & imsc; + + Register read(Address_range&, Cpu&) override; + + Uartmis(Mmio_register & ris, Uartimsc & imsc) + : Mmio_register("UARTMIS", Mmio_register::RO, 0x40, 2), + ris(ris), imsc(imsc) {} + } _uart_mis { _uart_ris, _uart_imsc }; + + struct Uarticr : Mmio_register + { + Mmio_register & ris; + + void write(Address_range&, Cpu&, Register) override; + + Uarticr(Mmio_register & ris) + : Mmio_register("UARTICR", Mmio_register::WO, 0x44, 2), ris(ris) {} + } _uart_icr { _uart_ris }; + + void _read(); + + public: + + Pl011(const char * const name, + const Genode::uint64_t addr, + const Genode::uint64_t size, + unsigned irq, + Cpu & cpu, + Mmio_bus & bus, + Genode::Env & env); +}; + +#endif /* _SRC__SERVER__VMM__PL011_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/psci.h b/repos/os/src/server/vmm/spec/arm_v8/psci.h new file mode 100644 index 000000000..ead06b8e3 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/psci.h @@ -0,0 +1,35 @@ +/* + * \brief Power State Coordination Interface for ARMv8 virtualization + * \author Stefan Kalkowski + * \date 2019-10-21 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__PSCI_H_ +#define _SRC__SERVER__VMM__PSCI_H_ + +namespace Vmm { + + namespace Psci { + enum Function_id { + PSCI_VERSION = 0x84000000, + MIGRATE_INFO_TYPE = 0x84000006, + PSCI_FEATURES = 0x8400000a, + CPU_ON = 0xc4000003, + }; + + enum { + VERSION = 1 << 16, /* 1.0 */ + SUCCESS = 0, + NOT_SUPPORTED = -1, + }; + }; +}; + +#endif /* _SRC__SERVER__VMM__PSCI_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/ram.h b/repos/os/src/server/vmm/spec/arm_v8/ram.h new file mode 100644 index 000000000..9789e6221 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/ram.h @@ -0,0 +1,39 @@ +/* + * \brief VMM ram object + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__RAM_H_ +#define _SRC__SERVER__VMM__RAM_H_ + +#include <base/stdint.h> + +class Ram { + + private: + + Genode::addr_t const _base; + Genode::size_t const _size; + Genode::addr_t const _local; + + public: + + Ram(Genode::addr_t const addr, + Genode::size_t const sz, + Genode::addr_t const local) + : _base(addr), _size(sz), _local(local) { } + + Genode::addr_t base() const { return _base; } + Genode::size_t size() const { return _size; } + Genode::addr_t local() const { return _local; } +}; + +#endif /* _SRC__SERVER__VMM__RAM_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v8/target.mk b/repos/os/src/server/vmm/spec/arm_v8/target.mk new file mode 100644 index 000000000..797b883a9 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/target.mk @@ -0,0 +1,14 @@ +TARGET = vmm +REQUIRES = hw arm_v8 +LIBS = base +SRC_CC += address_space.cc +SRC_CC += cpu.cc +SRC_CC += generic_timer.cc +SRC_CC += gicv2.cc +SRC_CC += main.cc +SRC_CC += mmio.cc +SRC_CC += pl011.cc +SRC_CC += vm.cc +INC_DIR += $(PRG_DIR) + +CC_CXX_WARN_STRICT := diff --git a/repos/os/src/server/vmm/spec/arm_v8/virt.dts b/repos/os/src/server/vmm/spec/arm_v8/virt.dts new file mode 100755 index 000000000..92a0110c8 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/virt.dts @@ -0,0 +1,65 @@ +/dts-v1/; + +/ { + compatible = "linux,dummy-virt"; + #address-cells = <0x02>; + #size-cells = <0x02>; + interrupt-parent = <0x8001>; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + + cpu@0 { + compatible = "arm,cortex-a53"; + reg = <0x00>; + device_type = "cpu"; + }; + }; + + timer { + interrupts = <0x01 0x0d 0x04 0x01 0x0e 0x04 0x01 0x0b 0x04 0x01 0x0a 0x04>; + compatible = "arm,armv8-timer\0arm,armv7-timer"; + always-on; + }; + + apb-pclk { + compatible = "fixed-clock"; + phandle = <0x8000>; + clock-output-names = "clk24mhz"; + clock-frequency = <0x16e3600>; + #clock-cells = <0x00>; + }; + + pl011@9000000 { + interrupts = <0x00 0x01 0x04>; + compatible = "arm,pl011\0arm,primecell"; + clock-names = "uartclk\0apb_pclk"; + reg = <0x00 0x9000000 0x00 0x1000>; + clocks = <0x8000 0x8000>; + }; + + memory@40000000 { + reg = <0x00 0x40000000 0x00 0x8000000>; + device_type = "memory"; + }; + + chosen { + bootargs = "rdinit=/bin/sh"; + linux,initrd-start = <0x42000000>; + linux,initrd-end = <0x42113b86>; + stdout-path = "/pl011@9000000"; + }; + + intc@8000000 { + compatible = "arm,gic-v3"; + phandle = <0x8001>; + reg = <0x00 0x8000000 0x00 0x10000 0x00 0x80a0000 0x00 0xf60000>; + ranges; + #address-cells = <0x02>; + #redistributor-regions = <0x01>; + interrupt-controller; + #interrupt-cells = <0x03>; + #size-cells = <0x02>; + }; +}; diff --git a/repos/os/src/server/vmm/spec/arm_v8/vm.cc b/repos/os/src/server/vmm/spec/arm_v8/vm.cc new file mode 100644 index 000000000..abe2e8e35 --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/vm.cc @@ -0,0 +1,75 @@ +/* + * \brief VMM example for ARMv8 virtualization + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 <vm.h> + +using Vmm::Vm; + +void Vm::_load_kernel() +{ + Genode::memcpy((void*)(_ram.local() + KERNEL_OFFSET), + _kernel_rom.local_addr<void>(), + _kernel_rom.size()); +} + +void Vm::_load_dtb() +{ + Genode::memcpy((void*)(_ram.local() + DTB_OFFSET), + _dtb_rom.local_addr<void>(), + _dtb_rom.size()); +} + + +void Vm::_load_initrd() +{ + Genode::memcpy((void*)(_ram.local() + INITRD_OFFSET), + _initrd_rom.local_addr<void>(), + _initrd_rom.size()); +} + + +Vmm::Cpu & Vm::boot_cpu() +{ + if (!_cpus[0].constructed()) + _cpus[0].construct(*this, _vm, _bus, _gic, _env, _heap, _env.ep()); + return *_cpus[0]; +} + + +Vm::Vm(Genode::Env & env) +: _env(env), + _gic("Gicv3", 0x8000000, 0x10000, _bus, env), + _uart("Pl011", 0x9000000, 0x1000, 33, boot_cpu(), _bus, env) +{ + _vm.attach(_vm_ram.cap(), RAM_ADDRESS); + + /* FIXME extend for gicv2 by: _vm.attach_pic(0x8010000); */ + + _load_kernel(); + _load_dtb(); + _load_initrd(); + + for (unsigned i = 1; i < MAX_CPUS; i++) { + Genode::Affinity::Space space = _env.cpu().affinity_space(); + Genode::Affinity::Location location(space.location_of_index(i)); + _eps[i].construct(_env, STACK_SIZE, "vcpu ep", location); + _cpus[i].construct(*this, _vm, _bus, _gic, _env, _heap, *_eps[i]); + } + + Genode::log("Start virtual machine ..."); + + Cpu & cpu = boot_cpu(); + cpu.state().ip = _ram.base() + KERNEL_OFFSET; + cpu.state().r[0] = _ram.base() + DTB_OFFSET; + cpu.run(); +}; diff --git a/repos/os/src/server/vmm/spec/arm_v8/vm.h b/repos/os/src/server/vmm/spec/arm_v8/vm.h new file mode 100644 index 000000000..b1b78cbaf --- /dev/null +++ b/repos/os/src/server/vmm/spec/arm_v8/vm.h @@ -0,0 +1,82 @@ +/* + * \brief VMM example for ARMv8 virtualization + * \author Stefan Kalkowski + * \date 2019-07-18 + */ + +/* + * Copyright (C) 2019 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 _SRC__SERVER__VMM__VM_H_ +#define _SRC__SERVER__VMM__VM_H_ + +#include <ram.h> +#include <exception.h> +#include <cpu.h> +#include <gic.h> +#include <pl011.h> + +#include <base/attached_ram_dataspace.h> +#include <base/attached_rom_dataspace.h> +#include <vm_session/connection.h> + +namespace Vmm { class Vm; } + +class Vmm::Vm +{ + private: + + using Ep = Genode::Entrypoint; + + enum { + RAM_ADDRESS = 0x40000000, + RAM_SIZE = 128 * 1024 *1024, + KERNEL_OFFSET = 0x80000, + INITRD_OFFSET = 32 * 1024 * 1024, + DTB_OFFSET = 64 * 1024 * 1024, + MAX_CPUS = 1, + STACK_SIZE = sizeof(unsigned long) * 2048, + }; + + Genode::Env & _env; + Genode::Vm_connection _vm { _env }; + Genode::Attached_rom_dataspace _kernel_rom { _env, "linux" }; + Genode::Attached_rom_dataspace _dtb_rom { _env, "dtb" }; + Genode::Attached_rom_dataspace _initrd_rom { _env, "initrd" }; + Genode::Attached_ram_dataspace _vm_ram { _env.ram(), _env.rm(), + RAM_SIZE, Genode::UNCACHED }; + Ram _ram { RAM_ADDRESS, RAM_SIZE, + (Genode::addr_t)_vm_ram.local_addr<void>()}; + Genode::Heap _heap { _env.ram(), _env.rm() }; + Mmio_bus _bus; + Gic _gic; + Genode::Constructible<Ep> _eps[MAX_CPUS]; + Genode::Constructible<Cpu> _cpus[MAX_CPUS]; + Pl011 _uart; + + void _load_kernel(); + void _load_dtb(); + void _load_initrd(); + + public: + + Vm(Genode::Env & env); + + Mmio_bus & bus() { return _bus; } + Cpu & boot_cpu(); + + template <typename F> + void cpu(unsigned cpu, F func) + { + if (cpu >= MAX_CPUS) Genode::error("Cpu number out of bounds "); + else func(*_cpus[cpu]); + } + + static unsigned last_cpu() { return MAX_CPUS - 1; } +}; + +#endif /* _SRC__SERVER__VMM__VM_H_ */ diff --git a/repos/os/src/test/nic_stress/main.cc b/repos/os/src/test/nic_stress/main.cc index 0c5c86d72..c537f5661 100644 --- a/repos/os/src/test/nic_stress/main.cc +++ b/repos/os/src/test/nic_stress/main.cc @@ -28,6 +28,24 @@ namespace Local { } +struct Bad_args_nic : Genode::Connection<Nic::Session> +{ + Bad_args_nic(Genode::Env &env, + Genode::size_t ram_quota, + Genode::size_t cap_quota, + Genode::size_t tx_buf_size, + Genode::size_t rx_buf_size, + char const *label) + : + Genode::Connection<Nic::Session>(env, + session(env.parent(), + "ram_quota=%ld, cap_quota=%ld, " + "tx_buf_size=%ld, rx_buf_size=%ld, label=\"%s\"", + ram_quota, cap_quota, tx_buf_size, rx_buf_size, label)) + { } +}; + + struct Local::Construct_destruct_test { enum { DEFAULT_NR_OF_ROUNDS = 10 }; @@ -37,12 +55,13 @@ struct Local::Construct_destruct_test using Nic_slot = Constructible<Nic::Connection>; - Env &_env; - Allocator &_alloc; - Signal_context_capability _completed_sigh; - Xml_node const &_config; - Nic::Packet_allocator _pkt_alloc { &_alloc }; - bool const _config_exists { _config.has_sub_node("construct_destruct") }; + Env &_env; + Allocator &_alloc; + Signal_context_capability &_completed_sigh; + Xml_node const &_config; + Nic::Packet_allocator _pkt_alloc { &_alloc }; + bool const _config_exists { _config.has_sub_node("construct_destruct") }; + Constructible<Bad_args_nic> _bad_args_nic { }; unsigned long const _nr_of_rounds { _config_exists ? @@ -61,6 +80,8 @@ struct Local::Construct_destruct_test void construct_all(Nic_slot *const nic, unsigned const round) { + _bad_args_nic.construct( + _env, 0, 0, BUF_SIZE, BUF_SIZE, "bad_args"); for (unsigned idx = 0; idx < _nr_of_sessions; idx++) { try { nic[idx].construct(_env, &_pkt_alloc, BUF_SIZE, BUF_SIZE); diff --git a/repos/os/src/test/vfs_stress/main.cc b/repos/os/src/test/vfs_stress/main.cc index 3ed1b2def..9fa87b800 100644 --- a/repos/os/src/test/vfs_stress/main.cc +++ b/repos/os/src/test/vfs_stress/main.cc @@ -445,7 +445,7 @@ struct Unlink_test : public Stress_test Vfs::Vfs_handle *dir_handle; assert_opendir(vfs.opendir(path, false, &dir_handle, alloc)); - Vfs::Directory_service::Dirent dirent; + Vfs::Directory_service::Dirent dirent { }; for (Vfs::file_size i = vfs.num_dirent(path); i;) { dir_handle->seek(--i * sizeof(dirent)); dir_handle->fs().queue_read(dir_handle, sizeof(dirent)); @@ -456,13 +456,13 @@ struct Unlink_test : public Stress_test Vfs::File_io_service::READ_QUEUED) _ep.wait_and_dispatch_one_io_signal(); - subpath.append(dirent.name); + subpath.append(dirent.name.buf); switch (dirent.type) { - case Vfs::Directory_service::DIRENT_TYPE_END: + case Vfs::Directory_service::Dirent_type::END: error("reached the end prematurely"); throw Exception(); - case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: + case Vfs::Directory_service::Dirent_type::DIRECTORY: empty_dir(subpath.base()); [[fallthrough]]; diff --git a/repos/ports/include/noux_session/sysio.h b/repos/ports/include/noux_session/sysio.h index ae2edc605..9ec3f8d54 100644 --- a/repos/ports/include/noux_session/sysio.h +++ b/repos/ports/include/noux_session/sysio.h @@ -74,41 +74,7 @@ struct Noux::Sysio OPEN_MODE_CREATE = 0x0800, /* libc O_EXCL */ }; - /** - * These values are the same as in the FreeBSD libc - */ - enum { - STAT_MODE_SYMLINK = 0120000, - STAT_MODE_FILE = 0100000, - STAT_MODE_DIRECTORY = 0040000, - STAT_MODE_CHARDEV = 0020000, - STAT_MODE_BLOCKDEV = 0060000, - }; - - /* - * Must be POD (in contrast to the VFS type) because it's used in a union - */ - struct Stat - { - Vfs::file_size size; - unsigned mode; - unsigned uid; - unsigned gid; - unsigned long inode; - unsigned long device; - - Stat & operator= (Vfs::Directory_service::Stat const &stat) - { - size = stat.size; - mode = stat.mode; - uid = stat.uid; - gid = stat.gid; - inode = stat.inode; - device = stat.device; - - return *this; - } - }; + typedef Vfs::Directory_service::Stat Stat; /** * Argument structure used for ioctl syscall @@ -130,7 +96,7 @@ struct Noux::Sysio enum Lseek_whence { LSEEK_SET, LSEEK_CUR, LSEEK_END }; - enum { DIRENT_MAX_NAME_LEN = Vfs::Directory_service::DIRENT_MAX_NAME_LEN }; + enum { DIRENT_MAX_NAME_LEN = Vfs::Directory_service::Dirent::Name::MAX_LEN }; typedef Vfs::Directory_service::Dirent_type Dirent_type; @@ -147,7 +113,7 @@ struct Noux::Sysio { fileno = dirent.fileno; type = dirent.type; - memcpy(name, dirent.name, DIRENT_MAX_NAME_LEN); + memcpy(name, dirent.name.buf, DIRENT_MAX_NAME_LEN); return *this; } diff --git a/repos/ports/mk/gnu_build.mk b/repos/ports/mk/gnu_build.mk index 035c57b78..40e93a57a 100644 --- a/repos/ports/mk/gnu_build.mk +++ b/repos/ports/mk/gnu_build.mk @@ -126,8 +126,8 @@ CXXFLAGS += $(COMMON_CFLAGS_CXXFLAGS) # in all cases because 'libtool' strips those arguments from the 'LIBS' variable. # LDLIBS_A = $(filter %.a, $(sort $(STATIC_LIBS)) $(EXT_OBJECTS) $(LIBGCC)) -LDLIBS_SO = $(addprefix $(PWD)/,$(sort $(SHARED_LIBS))) -LDLIBS += $(LDLIBS_A) $(LDLIBS_SO) $(LDLIBS_A) +LDLIBS_SO = $(addprefix -l:,$(sort $(SHARED_LIBS))) +LDLIBS += -L$(PWD) $(LDLIBS_A) $(LDLIBS_SO) $(LDLIBS_A) # # By default, assume that there exists a 'configure' script in the top-level @@ -145,7 +145,7 @@ Makefile reconfigure: $(MAKEFILE_LIST) # Makefile reconfigure: env.sh $(SHARED_LIBS) @$(MSG_CONFIG)$(TARGET) - $(VERBOSE)source env.sh && $(CONFIGURE_SCRIPT) $(ENV) $(CONFIGURE_ARGS) $(CONFIGURE_OUTPUT_FILTER) + $(VERBOSE)source env.sh && $(CONFIGURE_SCRIPT) $(MKENV) $(CONFIGURE_ARGS) $(CONFIGURE_OUTPUT_FILTER) env.sh: $(VERBOSE)rm -f $@ diff --git a/repos/ports/ports/gcc.hash b/repos/ports/ports/gcc.hash index 7f24e9c57..e770f28a0 100644 --- a/repos/ports/ports/gcc.hash +++ b/repos/ports/ports/gcc.hash @@ -1 +1 @@ -3283673a91ae961dfb4e439854ef4f2a23bdc793 +20345a83596fa42a25a85938329aea54bb4b2146 diff --git a/repos/ports/ports/gdb.hash b/repos/ports/ports/gdb.hash index 354ec23b9..614248f95 100644 --- a/repos/ports/ports/gdb.hash +++ b/repos/ports/ports/gdb.hash @@ -1 +1 @@ -b82025f7f85938ce713b6c442c693afe465dd83a +8eddf0d249a22993e57b3242112fb62f503101c9 diff --git a/repos/ports/ports/make.hash b/repos/ports/ports/make.hash index bb6fef395..aa2c4c279 100644 --- a/repos/ports/ports/make.hash +++ b/repos/ports/ports/make.hash @@ -1 +1 @@ -5e280e994155d92e18fbc7d7ad0e66ecf3bc174a +c8beffda9c98bfb34b038a55aadd83af8824bc8d diff --git a/repos/ports/ports/make.port b/repos/ports/ports/make.port index 7607d4084..dd6e76794 100644 --- a/repos/ports/ports/make.port +++ b/repos/ports/ports/make.port @@ -1,9 +1,9 @@ LICENSE := GPLv3 -VERSION := 3.82 +VERSION := 4.2.1 DOWNLOADS := make.archive URL(make) := http://ftp.gnu.org/pub/gnu/make/make-$(VERSION).tar.gz -SHA(make) := 3d991b33e604187c5881a0abc2e102d5b9776da5569640e73778f85d617242e7 +SHA(make) := e40b8f018c1da64edd1cc9a6fce5fa63b2e707e404e20cad91fbae337c98a5b7 SIG(make) := ${URL(make)}.sig KEY(make) := GNU DIR(make) := src/noux-pkg/make diff --git a/repos/ports/ports/netperf.hash b/repos/ports/ports/netperf.hash index a886f8362..ced5b426d 100644 --- a/repos/ports/ports/netperf.hash +++ b/repos/ports/ports/netperf.hash @@ -1 +1 @@ -0f8fcff2de9f71c697739023726f0ae9b0fef28a +7b5692dcbe87fc7e4fb528e33c5522f8f832c56d diff --git a/repos/ports/recipes/api/noux/hash b/repos/ports/recipes/api/noux/hash index c72902736..fe81eb74c 100644 --- a/repos/ports/recipes/api/noux/hash +++ b/repos/ports/recipes/api/noux/hash @@ -1 +1 @@ -2019-08-27 9cde70a55a67b91d22cd2ae2b3ef2bace2f2d2a3 +2019-11-18 624333bfbb2ed0b6187a032e8afba724877ee912 diff --git a/repos/ports/recipes/api/noux_session/hash b/repos/ports/recipes/api/noux_session/hash index bda135460..9321177ea 100644 --- a/repos/ports/recipes/api/noux_session/hash +++ b/repos/ports/recipes/api/noux_session/hash @@ -1 +1 @@ -2019-05-15 af7f1dcb1ef183a3d41678f4c1223f3b0f0dcf3b +2019-11-18 e3df42a2b6c490a86861cccd1d106b1a7e2c56be diff --git a/repos/ports/recipes/pkg/arora/hash b/repos/ports/recipes/pkg/arora/hash index a4bbd2cc0..64524a439 100644 --- a/repos/ports/recipes/pkg/arora/hash +++ b/repos/ports/recipes/pkg/arora/hash @@ -1 +1 @@ -2019-09-19 f7d378fc7b7d139ccfe5338ec6b7ba0f666feb95 +2019-11-25 03625cd33f8bdf62d86011285e4a556b72c8e9ec diff --git a/repos/ports/recipes/pkg/nic_router-nat-dns/hash b/repos/ports/recipes/pkg/nic_router-nat-dns/hash index 7bdeb3254..7c5e10663 100644 --- a/repos/ports/recipes/pkg/nic_router-nat-dns/hash +++ b/repos/ports/recipes/pkg/nic_router-nat-dns/hash @@ -1 +1 @@ -2019-09-19 97ef149fbeeee8a301ac13a73e0e096cb58f5f12 +2019-11-25 ad72c8e3010760a53630d8a7899d74167fba3c63 diff --git a/repos/ports/recipes/pkg/noux-build-x86/hash b/repos/ports/recipes/pkg/noux-build-x86/hash index 204899c00..d817566a7 100644 --- a/repos/ports/recipes/pkg/noux-build-x86/hash +++ b/repos/ports/recipes/pkg/noux-build-x86/hash @@ -1 +1 @@ -2019-09-19 7e97d6de02442d6a9ce215012b1e97de03dedb58 +2019-11-25 a078b5cc9de2fc00ff8fade977587d596cfc4f54 diff --git a/repos/ports/recipes/pkg/noux-system/hash b/repos/ports/recipes/pkg/noux-system/hash index 0a31f4574..d7c6569dd 100644 --- a/repos/ports/recipes/pkg/noux-system/hash +++ b/repos/ports/recipes/pkg/noux-system/hash @@ -1 +1 @@ -2019-09-19 85e5f6b8881226529412ab3da86097cd1625b914 +2019-11-25 9a917f0180c3921fdfd3d28fc3b82eab4649ae40 diff --git a/repos/ports/recipes/pkg/report_dump/hash b/repos/ports/recipes/pkg/report_dump/hash index 741294e16..91b5e80a0 100644 --- a/repos/ports/recipes/pkg/report_dump/hash +++ b/repos/ports/recipes/pkg/report_dump/hash @@ -1 +1 @@ -2019-09-19 44cfd20a8855a13d9d2417c4c09369ac1576fac3 +2019-11-25 58d512b58c312bd256c3c95a187a6f1b41ab74a0 diff --git a/repos/ports/recipes/pkg/vbox5-nova-sculpt/hash b/repos/ports/recipes/pkg/vbox5-nova-sculpt/hash index 935184e0e..dd40ffe11 100644 --- a/repos/ports/recipes/pkg/vbox5-nova-sculpt/hash +++ b/repos/ports/recipes/pkg/vbox5-nova-sculpt/hash @@ -1 +1 @@ -2019-09-19 8533cc0d31c24a412b70726d38c155e0b48f4c7e +2019-11-25 a559748bfe20d2d810f05a9e2a6de2867ba40c1d diff --git a/repos/ports/recipes/pkg/vbox5/README b/repos/ports/recipes/pkg/vbox5/README new file mode 100644 index 000000000..65e2382a9 --- /dev/null +++ b/repos/ports/recipes/pkg/vbox5/README @@ -0,0 +1,2 @@ + + VirtualBox runtime for hosting a large VM in the Sculpt scenario diff --git a/repos/ports/recipes/pkg/vbox5/archives b/repos/ports/recipes/pkg/vbox5/archives new file mode 100755 index 000000000..d7bb04def --- /dev/null +++ b/repos/ports/recipes/pkg/vbox5/archives @@ -0,0 +1,8 @@ +_/src/vbox5 +_/src/libc +_/src/init +_/src/posix +_/src/zlib +_/src/libiconv +_/src/stdcxx +_/src/vfs diff --git a/repos/ports/recipes/pkg/vbox5/hash b/repos/ports/recipes/pkg/vbox5/hash new file mode 100644 index 000000000..12ed95815 --- /dev/null +++ b/repos/ports/recipes/pkg/vbox5/hash @@ -0,0 +1 @@ +2019-11-25 a6b8ca8de7230feee3d8b508f36553c6f2a8cb20 diff --git a/repos/ports/recipes/pkg/vbox5/runtime b/repos/ports/recipes/pkg/vbox5/runtime new file mode 100755 index 000000000..e49a2e672 --- /dev/null +++ b/repos/ports/recipes/pkg/vbox5/runtime @@ -0,0 +1,89 @@ +<runtime ram="4300M" caps="1500" binary="init"> + + <requires> + <file_system label="vm"/> + <file_system label="shared"/> + <vm/> + <timer/> + <nitpicker/> + <nic/> + <rom label="capslock"/> + <rom label="platform_info"/> + <report label="shape"/> + <report label="clipboard"/> + <rom label="clipboard"/> + <rm/> + <rtc/> + <rom label="usb_devices"/> + <usb/> + </requires> + + <config verbose="yes" prio_levels="2"> + + <parent-provides> + <service name="ROM"/> + <service name="PD"/> + <service name="RM"/> + <service name="CPU"/> + <service name="LOG"/> + <service name="VM"/> + <service name="Nitpicker"/> + <service name="Timer"/> + <service name="Rtc"/> + <service name="Report"/> + <service name="File_system"/> + <service name="Usb"/> + <service name="Nic"/> + </parent-provides> + + <default-route> <any-service> <parent/> <any-child/> </any-service> </default-route> + + <default caps="100"/> + + <start name="vbox" priority="-1" caps="1000"> + <binary name="virtualbox5" /> + <resource name="RAM" quantum="8G"/> + <exit propagate="yes"/> + <config vbox_file="machine.vbox" xhci="yes" vm_name="linux" capslock="ROM"> + <vfs> + <dir name="dev"> + <log/> + <rtc/> + </dir> + <dir name="shared"> <fs label="shared" writeable="yes"/> </dir> + <fs writeable="yes"/> + </vfs> + <libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/> + </config> + <route> + <service name="Audio_out"> <parent/> </service> + <service name="File_system" label="shared"> <parent label="shared"/> </service> + <service name="File_system"> <parent label="vm"/> </service> + <service name="ROM" label="usb_devices"> <parent label="usb_devices"/> </service> + <service name="ROM" label="capslock"> <parent label="capslock"/> </service> + <service name="ROM" label="platform_info"> + <parent label="platform_info"/> </service> + <service name="Nic"> <parent/> </service> + <service name="Report" label="shape"> <parent label="shape"/> </service> + <service name="ROM" label="clipboard"> <parent label="clipboard"/> </service> + <service name="Report" label="clipboard"> <parent label="clipboard"/> </service> + <service name="Nitpicker"> <parent label=""/> </service> + <any-service> <parent/> </any-service> + </route> + </start> + </config> + + <content> + <rom label="ld.lib.so"/> + <rom label="init"/> + <rom label="virtualbox5"/> + <rom label="libc.lib.so"/> + <rom label="libc_pipe.lib.so"/> + <rom label="libm.lib.so"/> + <rom label="libiconv.lib.so"/> + <rom label="qemu-usb.lib.so"/> + <rom label="stdcxx.lib.so"/> + <rom label="vfs.lib.so"/> + </content> + +</runtime> diff --git a/repos/ports/recipes/src/arora/hash b/repos/ports/recipes/src/arora/hash index c95e30baf..12e188979 100644 --- a/repos/ports/recipes/src/arora/hash +++ b/repos/ports/recipes/src/arora/hash @@ -1 +1 @@ -2019-09-19 9c65213a9c4e6c55855297e62ff5dcce395e0240 +2019-11-25 f234db5b895a34ad25e3225b921ce9a9f9bf3ad2 diff --git a/repos/ports/recipes/src/bash-minimal/hash b/repos/ports/recipes/src/bash-minimal/hash index c9e101a55..34bd2b1b1 100644 --- a/repos/ports/recipes/src/bash-minimal/hash +++ b/repos/ports/recipes/src/bash-minimal/hash @@ -1 +1 @@ -2019-09-19 edc6153e63d38e565f930cbf608ba29db35b4d4e +2019-11-18 63b176665e53c92b31d0621b15b2c125a6add1af diff --git a/repos/ports/recipes/src/bash/hash b/repos/ports/recipes/src/bash/hash index 49e5e1bba..5fa9b9f8e 100644 --- a/repos/ports/recipes/src/bash/hash +++ b/repos/ports/recipes/src/bash/hash @@ -1 +1 @@ -2019-09-19 2586cf7b9fe8874417a3595c402f8a2e35df5b73 +2019-11-25 29f16c3029eef6bd8b5f1ec05e1f11b94a9bc6d7 diff --git a/repos/ports/recipes/src/binutils_x86/hash b/repos/ports/recipes/src/binutils_x86/hash index d0fd642f0..eedd9ac5c 100644 --- a/repos/ports/recipes/src/binutils_x86/hash +++ b/repos/ports/recipes/src/binutils_x86/hash @@ -1 +1 @@ -2019-09-19 3d09940c9e96757e0614e0c0a735b572bee8ad60 +2019-11-18 5ab8c7d6426238010bd3be79e6abab38ba3974bf diff --git a/repos/ports/recipes/src/coreutils-minimal/hash b/repos/ports/recipes/src/coreutils-minimal/hash index 27efe8137..103c1adbc 100644 --- a/repos/ports/recipes/src/coreutils-minimal/hash +++ b/repos/ports/recipes/src/coreutils-minimal/hash @@ -1 +1 @@ -2019-09-19 86bfc95ed482ec827117c517dc36acc51de04a68 +2019-11-18 566269b4522f08d6b97f14392d2e8e509a4c4b7a diff --git a/repos/ports/recipes/src/coreutils/hash b/repos/ports/recipes/src/coreutils/hash index 22ab59b57..cf2082c9b 100644 --- a/repos/ports/recipes/src/coreutils/hash +++ b/repos/ports/recipes/src/coreutils/hash @@ -1 +1 @@ -2019-09-19 f0bc4e55408733fbe946affd579a1182fb00cea1 +2019-11-18 6dcadd04a2d31dd1e2cbcef9e47e120445a6c433 diff --git a/repos/ports/recipes/src/e2fsprogs-minimal/hash b/repos/ports/recipes/src/e2fsprogs-minimal/hash index e3f920a2d..41e7eb8c8 100644 --- a/repos/ports/recipes/src/e2fsprogs-minimal/hash +++ b/repos/ports/recipes/src/e2fsprogs-minimal/hash @@ -1 +1 @@ -2019-09-19 986a3e4da5bdda4c0b7f372ba9d3b2890360ad6f +2019-11-18 20d118aa83db775e3f1cd5f79610b95dd714da94 diff --git a/repos/ports/recipes/src/e2fsprogs/hash b/repos/ports/recipes/src/e2fsprogs/hash index a9d729c74..ae740bf13 100644 --- a/repos/ports/recipes/src/e2fsprogs/hash +++ b/repos/ports/recipes/src/e2fsprogs/hash @@ -1 +1 @@ -2019-09-19 981923f1a6b7289a9183dd6edc4aa07522c0a0ab +2019-11-18 13552f3845d19a965243374e45c1bd1ddb1a0bc0 diff --git a/repos/ports/recipes/src/findutils/hash b/repos/ports/recipes/src/findutils/hash index cae35fef3..04455b446 100644 --- a/repos/ports/recipes/src/findutils/hash +++ b/repos/ports/recipes/src/findutils/hash @@ -1 +1 @@ -2019-09-19 0a8ccd6ef82d1f02a71567c8e8e2a246dca2c4ca +2019-11-18 ca0c305f30a0308aca82c4bea46f2c421531a81f diff --git a/repos/ports/recipes/src/gcc_x86/hash b/repos/ports/recipes/src/gcc_x86/hash index 56b098111..d5a435762 100644 --- a/repos/ports/recipes/src/gcc_x86/hash +++ b/repos/ports/recipes/src/gcc_x86/hash @@ -1 +1 @@ -2019-09-19 5b846144ec418cebe83ef9134302fd87d217aadc +2019-11-25 da1ac63597dfefb30eb72d69b0a143c0e6835171 diff --git a/repos/ports/recipes/src/gnumake/hash b/repos/ports/recipes/src/gnumake/hash index b9ae6a7e4..eea439e1d 100644 --- a/repos/ports/recipes/src/gnumake/hash +++ b/repos/ports/recipes/src/gnumake/hash @@ -1 +1 @@ -2019-09-19 1a8f3e27c86f6355d65f770a311c5e77d28aba49 +2019-11-18 4ea46ee9f056e5922dd44932df7ffbbe26918862 diff --git a/repos/ports/recipes/src/grep/hash b/repos/ports/recipes/src/grep/hash index 8e0c4ac98..46867d8b3 100644 --- a/repos/ports/recipes/src/grep/hash +++ b/repos/ports/recipes/src/grep/hash @@ -1 +1 @@ -2019-09-19 d6e4b69b9d3b6bc420ee142c845be642baa7e527 +2019-11-18 4c9fa93f89240ba6f13c146c30073ebc152d0d56 diff --git a/repos/ports/recipes/src/libgetdns/hash b/repos/ports/recipes/src/libgetdns/hash index 555b01144..35520d028 100644 --- a/repos/ports/recipes/src/libgetdns/hash +++ b/repos/ports/recipes/src/libgetdns/hash @@ -1 +1 @@ -2019-09-19 60222df9340ab35a0dd252ea9456e60b2d52f13d +2019-11-25 35a2be19e11fa0115bbcd73478f7141336c1d8ae diff --git a/repos/ports/recipes/src/lighttpd/hash b/repos/ports/recipes/src/lighttpd/hash index 0278a98f6..f91c831a2 100644 --- a/repos/ports/recipes/src/lighttpd/hash +++ b/repos/ports/recipes/src/lighttpd/hash @@ -1 +1 @@ -2019-09-19 96e195a7d116c3164ccdbdcb3551d3ab3957691c +2019-11-18 0b8ea9535311b481ee67ba0798da537c90cc896f diff --git a/repos/ports/recipes/src/noux/content.mk b/repos/ports/recipes/src/noux/content.mk index 780eecd47..d710e432d 100644 --- a/repos/ports/recipes/src/noux/content.mk +++ b/repos/ports/recipes/src/noux/content.mk @@ -5,7 +5,10 @@ content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_REP_DIR): $(mirror_from_rep_dir) -MIRROR_FROM_LIBPORTS := include/libc-plugin src/lib/libc/libc_mem_alloc.h +MIRROR_FROM_LIBPORTS := include/libc-plugin \ + src/lib/libc/internal/mem_alloc.h \ + src/lib/libc/internal/types.h \ + src/lib/libc/internal/legacy.h content: $(MIRROR_FROM_LIBPORTS) diff --git a/repos/ports/recipes/src/noux/hash b/repos/ports/recipes/src/noux/hash index d7f17299e..c77b8469e 100644 --- a/repos/ports/recipes/src/noux/hash +++ b/repos/ports/recipes/src/noux/hash @@ -1 +1 @@ -2019-09-19 5a6088ce1f4e7ae463d13a541549cfd6de607675 +2019-11-25 e23e482e8adba37e19903c08c2d5c4002c7f3723 diff --git a/repos/ports/recipes/src/noux/used_apis b/repos/ports/recipes/src/noux/used_apis index 0d8514f83..ddb9ebeff 100644 --- a/repos/ports/recipes/src/noux/used_apis +++ b/repos/ports/recipes/src/noux/used_apis @@ -7,3 +7,4 @@ noux_session terminal_session timer_session posix +rtc_session diff --git a/repos/ports/recipes/src/sed/hash b/repos/ports/recipes/src/sed/hash index f0a11d4ca..eaa61a08e 100644 --- a/repos/ports/recipes/src/sed/hash +++ b/repos/ports/recipes/src/sed/hash @@ -1 +1 @@ -2019-09-19 10b2f10b8fc8ae7b4c2f0ef209a837935ca8de20 +2019-11-18 0d260be2d3ab962a93a45ca98f862e0fb9e7aef0 diff --git a/repos/ports/recipes/src/seoul/hash b/repos/ports/recipes/src/seoul/hash index 3cbb671ef..8cf3e77e6 100644 --- a/repos/ports/recipes/src/seoul/hash +++ b/repos/ports/recipes/src/seoul/hash @@ -1 +1 @@ -2019-09-19 d54524384c76f17b5cc6aa3bf7d6f72051dbd3b4 +2019-11-25 635b401d325ceadffe416cf33cbcdee47c8ab347 diff --git a/repos/ports/recipes/src/stubby/hash b/repos/ports/recipes/src/stubby/hash index da8f0d77f..51e11e134 100644 --- a/repos/ports/recipes/src/stubby/hash +++ b/repos/ports/recipes/src/stubby/hash @@ -1 +1 @@ -2019-09-19 682a2ffe231a39be872c199418789ea10c4bc2af +2019-11-25 d820177e27372e3afe8dcf5ec374dfd372f4f1d2 diff --git a/repos/ports/recipes/src/tar/hash b/repos/ports/recipes/src/tar/hash index ac6def6f3..b8e00e4c2 100644 --- a/repos/ports/recipes/src/tar/hash +++ b/repos/ports/recipes/src/tar/hash @@ -1 +1 @@ -2019-09-19 16baeca3258c256ccf19c79aa58eed9dfebb110d +2019-11-18 8b3fa5a49b854746dddb433dcb75b5f627bb2be5 diff --git a/repos/ports/recipes/src/tclsh/hash b/repos/ports/recipes/src/tclsh/hash index 8362faad1..dbbe240d7 100644 --- a/repos/ports/recipes/src/tclsh/hash +++ b/repos/ports/recipes/src/tclsh/hash @@ -1 +1 @@ -2019-09-19 59f66d9b5a231d739a36ba0155e0c396efa8557c +2019-11-25 bad88673fb23c5aa966d556ec2518d74e5ad8074 diff --git a/repos/ports/recipes/src/vbox5-nova/content.mk b/repos/ports/recipes/src/vbox5-nova/content.mk index 6eeff2930..4a283df5f 100644 --- a/repos/ports/recipes/src/vbox5-nova/content.mk +++ b/repos/ports/recipes/src/vbox5-nova/content.mk @@ -38,10 +38,11 @@ MIRROR_FROM_LIBPORTS := lib/mk/libc_pipe.mk \ lib/mk/libc-mem.mk \ lib/mk/libc-common.inc \ src/lib/libc/libc_mem_alloc.cc \ - src/lib/libc/libc_mem_alloc.h \ - src/lib/libc/libc_init.h \ - src/lib/libc/thread_create.h \ - src/lib/libc/thread.h \ + src/lib/libc/internal/mem_alloc.h \ + src/lib/libc/internal/init.h \ + src/lib/libc/internal/thread_create.h \ + src/lib/libc/internal/pthread.h \ + src/lib/libc/internal/types.h \ include/libc-plugin \ lib/import/import-qemu-usb_include.mk \ lib/mk/qemu-usb_include.mk \ diff --git a/repos/ports/recipes/src/vbox5-nova/hash b/repos/ports/recipes/src/vbox5-nova/hash index 88e1f89b3..2defa2011 100644 --- a/repos/ports/recipes/src/vbox5-nova/hash +++ b/repos/ports/recipes/src/vbox5-nova/hash @@ -1 +1 @@ -2019-09-19 27979c7ae18c81ffb2b18c66b67c6919a2b5e82d +2019-11-25 53af4078f3a7ef842164aabd42995967fe1bf530 diff --git a/repos/ports/recipes/src/vbox5/content.mk b/repos/ports/recipes/src/vbox5/content.mk index 2f6f5d16e..5a7ac4838 100644 --- a/repos/ports/recipes/src/vbox5/content.mk +++ b/repos/ports/recipes/src/vbox5/content.mk @@ -39,10 +39,11 @@ MIRROR_FROM_LIBPORTS := lib/mk/libc_pipe.mk \ lib/mk/libc-mem.mk \ lib/mk/libc-common.inc \ src/lib/libc/libc_mem_alloc.cc \ - src/lib/libc/libc_mem_alloc.h \ - src/lib/libc/libc_init.h \ - src/lib/libc/thread_create.h \ - src/lib/libc/thread.h \ + src/lib/libc/internal/mem_alloc.h \ + src/lib/libc/internal/init.h \ + src/lib/libc/internal/thread_create.h \ + src/lib/libc/internal/pthread.h \ + src/lib/libc/internal/types.h \ include/libc-plugin \ lib/import/import-qemu-usb_include.mk \ lib/mk/qemu-usb_include.mk \ diff --git a/repos/ports/recipes/src/vbox5/hash b/repos/ports/recipes/src/vbox5/hash index d5026f7f4..2d394df4b 100644 --- a/repos/ports/recipes/src/vbox5/hash +++ b/repos/ports/recipes/src/vbox5/hash @@ -1 +1 @@ -2019-09-19 579f5a647440436a41540d0303f94ae4eb21a450 +2019-11-25 44833567c0add7ab957546fc11988ccebbd65aa1 diff --git a/repos/ports/recipes/src/verify/hash b/repos/ports/recipes/src/verify/hash index 4840d5958..0e3ea2d26 100644 --- a/repos/ports/recipes/src/verify/hash +++ b/repos/ports/recipes/src/verify/hash @@ -1 +1 @@ -2019-09-19 dbafe8043a9fbd406c0a8d840dd7cef0963d2999 +2019-11-25 64344585319e5b72a1ca29f8b303e06e72c2d2c9 diff --git a/repos/ports/recipes/src/vim-minimal/hash b/repos/ports/recipes/src/vim-minimal/hash index 94d4bd5e4..925ab37b7 100644 --- a/repos/ports/recipes/src/vim-minimal/hash +++ b/repos/ports/recipes/src/vim-minimal/hash @@ -1 +1 @@ -2019-09-19 18833da65af5a6542af25b20338b8c007f9a0659 +2019-11-18 e835201ead2cf02c4fbaa2b94ff385793dcb03d8 diff --git a/repos/ports/recipes/src/vim/hash b/repos/ports/recipes/src/vim/hash index bd972120b..ba5dd5430 100644 --- a/repos/ports/recipes/src/vim/hash +++ b/repos/ports/recipes/src/vim/hash @@ -1 +1 @@ -2019-09-19 924251b0c51753b36213b40009b78c0885bc8fd3 +2019-11-18 43005d1c917da42a0c3e2d3c9353edafca820459 diff --git a/repos/ports/recipes/src/which/hash b/repos/ports/recipes/src/which/hash index bf65b88f4..f7ec08e83 100644 --- a/repos/ports/recipes/src/which/hash +++ b/repos/ports/recipes/src/which/hash @@ -1 +1 @@ -2019-09-19 1f5da025408be27c45ec04630512d02ba0c48194 +2019-11-18 32ffd18da7b80d984ac6e6c144a1ee146e7e616e diff --git a/repos/ports/run/bash.run b/repos/ports/run/bash.run index 6fcf0f55a..0e3f37f26 100644 --- a/repos/ports/run/bash.run +++ b/repos/ports/run/bash.run @@ -10,6 +10,7 @@ import_from_depot [depot_user]/src/[base_src] \ [depot_user]/src/bash \ [depot_user]/src/coreutils \ [depot_user]/src/vfs \ + [depot_user]/src/vfs_pipe \ [depot_user]/src/fs_rom # write default vimrc file @@ -83,11 +84,12 @@ install_config { <dir name="tmp"> <ram/> </dir> <dir name="dev"> <zero/> <null/> <terminal/> + <dir name="pipe"> <pipe/> </dir> <inline name="rtc">2018-01-01 00:01</inline> </dir> </vfs> - <policy label_prefix="vfs_rom" root="/bin"/> + <policy label_prefix="vfs_rom" root="/"/> <default-policy root="/" writeable="yes"/> </config> </start> @@ -103,11 +105,11 @@ install_config { </route> </start> - <start name="bash" caps="1000"> + <start name="/bin/bash" caps="1000"> <resource name="RAM" quantum="30M" /> - <config> + <config ld_verbose="yes"> <libc stdin="/dev/terminal" stdout="/dev/terminal" - stderr="/dev/terminal" rtc="/dev/rtc"/> + stderr="/dev/terminal" rtc="/dev/rtc" pipe="/dev/pipe"/> <vfs> <fs/> </vfs> <arg value="bash"/> <env key="TERM" value="screen"/> @@ -115,9 +117,9 @@ install_config { </config> <route> <service name="File_system"> <child name="vfs"/> </service> - <service name="ROM" label_last="bash"> <child name="vfs_rom"/> </service> <service name="ROM" label_suffix=".lib.so"> <parent/> </service> - <service name="ROM" label_prefix=""> <child name="vfs_rom"/> </service> + <service name="ROM" label_last="/bin/bash"> <child name="vfs_rom"/> </service> + <service name="ROM" label_prefix="/bin"> <child name="vfs_rom"/> </service> <any-service> <parent/> <any-child/> </any-service> </route> </start> diff --git a/repos/ports/run/debug_nitpicker.run b/repos/ports/run/debug_nitpicker.run index d2adfa308..f7d4bcfaf 100644 --- a/repos/ports/run/debug_nitpicker.run +++ b/repos/ports/run/debug_nitpicker.run @@ -12,7 +12,10 @@ # 'tcp_terminal' could be used (to attach GDB via a network connection). # -assert_spec x86 +if {![have_include "power_on/qemu"] || + !([have_spec nova])} { + puts "Run script is only supported for NOVA in Qemu"; exit 0 +} create_boot_directory import_from_depot [depot_user]/src/[base_src] \ diff --git a/repos/ports/run/gdb_monitor_interactive.run b/repos/ports/run/gdb_monitor_interactive.run index 998c0209b..0b8e0a10f 100644 --- a/repos/ports/run/gdb_monitor_interactive.run +++ b/repos/ports/run/gdb_monitor_interactive.run @@ -5,7 +5,10 @@ # \date 2011-05-24 # -assert_spec x86 +if {![have_include "power_on/qemu"] || + !([have_spec nova])} { + puts "Run script is only supported for NOVA in Qemu"; exit 0 +} # # Build diff --git a/repos/ports/run/gdb_monitor_target_config.run b/repos/ports/run/gdb_monitor_target_config.run index 2a4de0326..ca87ba219 100644 --- a/repos/ports/run/gdb_monitor_target_config.run +++ b/repos/ports/run/gdb_monitor_target_config.run @@ -4,7 +4,11 @@ # \date 2012-04-16 # -assert_spec x86 +if {![have_include "power_on/qemu"] || + !([have_spec nova])} { + puts "Run script is only supported for NOVA in Qemu"; exit 0 +} + # # Build # diff --git a/repos/ports/run/genode_org.run b/repos/ports/run/genode_org.run index b31da972c..0b6282b28 100644 --- a/repos/ports/run/genode_org.run +++ b/repos/ports/run/genode_org.run @@ -112,7 +112,7 @@ if {![file exists bin/genode_org/website/index]} { # ignore wget errors catch { - exec wget -nH -Lrc -P bin/genode_org/website http://genode.org + exec wget -nH -Lrc -P bin/genode_org/website https://genode.org } } diff --git a/repos/ports/run/noux_tool_chain_auto.run b/repos/ports/run/noux_tool_chain_auto.run index bfecaa53b..baaa0c8ab 100644 --- a/repos/ports/run/noux_tool_chain_auto.run +++ b/repos/ports/run/noux_tool_chain_auto.run @@ -19,7 +19,8 @@ if {[get_cmd_switch --autopilot] && [have_include "power_on/qemu"]} { exit 0 } -if {[have_spec pistachio] || [have_spec sel4]} { +if {[have_spec pistachio] || [have_spec sel4] || + [expr [have_spec foc] && [have_spec imx7d_sabre]] } { puts "Platform is unsupported." exit 0 } @@ -72,6 +73,15 @@ if {[have_spec arm]} { } +if {[have_spec arm_64]} { + set binutils "binutils_arm_64" + set gcc "gcc_arm_64" + set tool_prefix "genode-aarch64-" + + set noux_boot_timeout 350 + set platform "arm_v8a" +} + if {[have_spec x86]} { set binutils "binutils_x86" set gcc "gcc_x86" diff --git a/repos/ports/run/test.vbox b/repos/ports/run/test.vbox index 26db043fb..022421e77 100644 --- a/repos/ports/run/test.vbox +++ b/repos/ports/run/test.vbox @@ -32,7 +32,7 @@ <Memory RAMSize="256" PageFusion="false"/> <HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/> <HPET enabled="false"/> - <Chipset type="ICH9"/> + <Chipset type="PIIX3"/> <Boot> <Order position="1" device="Floppy"/> <Order position="2" device="DVD"/> diff --git a/repos/ports/run/vbox5_genode_usb_hid.run b/repos/ports/run/vbox5_genode_usb_hid.run index 658b1d758..5ffae86a3 100644 --- a/repos/ports/run/vbox5_genode_usb_hid.run +++ b/repos/ports/run/vbox5_genode_usb_hid.run @@ -204,8 +204,7 @@ append config { <resource name="RAM" quantum="448M"/> <config vbox_file="vm_genode_usb_hid.vbox" vm_name="TestVM" xhci="yes"> <vfs> - <dir name="dev"> <log/> </dir> - <dir name="dev"> <terminal/> </dir> + <dir name="dev"> <log/> <terminal/> </dir> <rom name="vm_genode_usb_hid.vbox" /> <rom name="usb_hid.iso" /> </vfs> diff --git a/repos/ports/run/virtualbox.run b/repos/ports/run/virtualbox.run index 5ab3c9066..13a38d7ca 100644 --- a/repos/ports/run/virtualbox.run +++ b/repos/ports/run/virtualbox.run @@ -278,7 +278,7 @@ lappend_if [expr $use_top] boot_modules top lappend_if [expr $use_gui] boot_modules report_rom append boot_modules { - ld.lib.so libc.lib.so vfs.lib.so libm.lib.so libc_pipe.lib.so + libc.lib.so vfs.lib.so libm.lib.so libc_pipe.lib.so libiconv.lib.so stdcxx.lib.so qemu-usb.lib.so } diff --git a/repos/ports/run/virtualbox_auto.inc b/repos/ports/run/virtualbox_auto.inc index ea9b18d79..d1ce42dd7 100644 --- a/repos/ports/run/virtualbox_auto.inc +++ b/repos/ports/run/virtualbox_auto.inc @@ -36,7 +36,8 @@ append build_components { drivers/framebuffer } -lappend_if [expr $use_rumpfs] build_components server/rump_fs +lappend_if [expr $use_rumpfs] build_components lib/vfs/rump +lappend_if [expr $use_rumpfs] build_components server/vfs lappend_if [expr $use_vbox5] build_components virtualbox5 lappend_if [expr $use_ps2] build_components drivers/input lappend_if [expr $use_usb] build_components drivers/usb @@ -130,9 +131,13 @@ append_if [have_spec nova] config { append_if [expr $use_rumpfs] config { <start name="rump_fs" priority="-1" caps="200"> + <binary name="vfs"/> <resource name="RAM" quantum="32M"/> <provides><service name="File_system"/></provides> - <config ld_verbose="yes" fs="ext2fs">} + <config ld_verbose="yes"> + <vfs> + <rump fs="ext2fs" ram="28M"/> + </vfs>} append_if [expr $use_rumpfs && $use_ram_fs && $use_overlay_from_disk] config { <policy label_prefix="overlay_from_disk" root="/ram" writeable="no"/>} @@ -363,7 +368,8 @@ append boot_modules { lappend_if [expr $use_rumpfs] boot_modules rump.lib.so lappend_if [expr $use_rumpfs] boot_modules rump_fs.lib.so -lappend_if [expr $use_rumpfs] boot_modules rump_fs +lappend_if [expr $use_rumpfs] boot_modules vfs_rump.lib.so +lappend_if [expr $use_rumpfs] boot_modules vfs lappend_if [expr $use_vbox5] boot_modules $virtualbox5_binary lappend_if [expr $use_ram_fs || $use_usb] boot_modules ram_fs lappend_if [expr $use_ram_fs && !$use_overlay_from_disk] boot_modules $overlay_image diff --git a/repos/ports/src/app/netperf/netlib.patch b/repos/ports/src/app/netperf/netlib.patch index 360d7a855..f99cd1a92 100644 --- a/repos/ports/src/app/netperf/netlib.patch +++ b/repos/ports/src/app/netperf/netlib.patch @@ -1,15 +1,4 @@ +++ src/app/netperf/src/netlib.c -@@ -844,6 +844,10 @@ - exit(1); - } - -+ /* On Genode libc port -1 is returned for sysconf(_SC_NPROCESSORS_ONLN) */ -+ if (temp_cpus < 0) -+ temp_cpus = 1; -+ - return(temp_cpus); - - } @@ -1095,8 +1095,13 @@ #endif /* WIN32 */ @@ -34,3 +23,13 @@ } if (debug > 1) { fprintf(where, "netperf: set_sock_buffer: %s of %d requested.\n", ++++ src/app/netperf/src/netlib.h +@@ -368,7 +368,7 @@ + /* Let's define a macro to hide all of this. */ + + #ifndef WIN32 +-#define SOCKET_EINTR(return_value) (errno == EINTR) ++#define SOCKET_EINTR(return_value) (errno == EINTR || errno == EPIPE) + #define SOCKET_EADDRINUSE(return_value) (errno == EADDRINUSE) + #define SOCKET_EADDRNOTAVAIL(return_value) (errno == EADDRNOTAVAIL) + diff --git a/repos/ports/src/app/netperf/target.mk b/repos/ports/src/app/netperf/target.mk index 967dfe87a..cae4fa29c 100644 --- a/repos/ports/src/app/netperf/target.mk +++ b/repos/ports/src/app/netperf/target.mk @@ -14,7 +14,8 @@ SRC_CC += timer.cc INC_DIR += $(PRG_DIR) CC_OPT += -DHAVE_CONFIG_H -DGENODE_BUILD -CC_WARN = -Wall -Wno-unused +CC_WARN = -Wall -Wno-unused -Wno-maybe-uninitialized -Wno-format-truncation \ + -Wno-stringop-truncation -Wno-stringop-overflow CC_CXX_WARN_STRICT = diff --git a/repos/ports/src/lib/libc_noux/plugin.cc b/repos/ports/src/lib/libc_noux/plugin.cc index 658f268e6..a2d6b7b60 100644 --- a/repos/ports/src/lib/libc_noux/plugin.cc +++ b/repos/ports/src/lib/libc_noux/plugin.cc @@ -58,7 +58,8 @@ /* libc-internal includes */ -#include <libc_mem_alloc.h> +#include <internal/mem_alloc.h> +#include <internal/legacy.h> using Genode::log; @@ -387,15 +388,39 @@ extern "C" int getrlimit(int resource, struct rlimit *rlim) */ static void _sysio_to_stat_struct(Noux::Sysio const *sysio, struct stat *buf) { - Genode::memset(buf, 0, sizeof(*buf)); - buf->st_uid = sysio->stat_out.st.uid; - buf->st_gid = sysio->stat_out.st.gid; - buf->st_mode = sysio->stat_out.st.mode; - buf->st_size = sysio->stat_out.st.size; + unsigned const readable_bits = S_IRUSR, + writeable_bits = S_IWUSR, + executable_bits = S_IXUSR; + + auto type = [] (Vfs::Node_type type) + { + switch (type) { + case Vfs::Node_type::DIRECTORY: return S_IFDIR; + case Vfs::Node_type::CONTINUOUS_FILE: return S_IFREG; + case Vfs::Node_type::TRANSACTIONAL_FILE: return S_IFSOCK; + case Vfs::Node_type::SYMLINK: return S_IFLNK; + } + return 0; + }; + + Vfs::Directory_service::Stat const &src = sysio->stat_out.st; + + *buf = { }; + + buf->st_uid = 0; + buf->st_gid = 0; + buf->st_mode = (src.rwx.readable ? readable_bits : 0) + | (src.rwx.writeable ? writeable_bits : 0) + | (src.rwx.executable ? executable_bits : 0) + | type(src.type); + buf->st_size = src.size; buf->st_blksize = FS_BLOCK_SIZE; - buf->st_blocks = (buf->st_size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE; - buf->st_ino = sysio->stat_out.st.inode; - buf->st_dev = sysio->stat_out.st.device; + buf->st_blocks = (src.size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE; + buf->st_ino = src.inode; + buf->st_dev = src.device; + + if (src.modification_time.value != Vfs::Timestamp::INVALID) + buf->st_mtime = src.modification_time.value; } @@ -933,6 +958,13 @@ extern "C" int gettimeofday(struct timeval *tv, struct timezone *tz) extern "C" int utimes(const char* path, const struct timeval *times) { + char * const dst = sysio()->utimes_in.path; + size_t const max_len = sizeof(sysio()->utimes_in.path); + Genode::strncpy(dst, path, max_len); + + sysio()->utimes_in.sec = times ? times->tv_sec : 0; + sysio()->utimes_in.usec = times ? times->tv_usec : 0; + if (!noux_syscall(Noux::Session::SYSCALL_UTIMES)) { errno = EINVAL; return -1; @@ -1210,8 +1242,10 @@ namespace { Libc::Plugin_context *context = noux_context(sysio()->open_out.fd); Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->alloc(this, context, sysio()->open_out.fd); - if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1)) + if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1)) { + Plugin::close(fd); return 0; + } return fd; } @@ -1258,7 +1292,7 @@ namespace { if (!buf) { errno = EFAULT; return -1; } /* remember original len for the return value */ - int const orig_count = count; + size_t const orig_count = count; char *src = (char *)buf; while (count > 0) { @@ -1283,12 +1317,23 @@ namespace { errno = 0; break; } + + /* try again */ + bool const retry = (errno == EINTR + || errno == EAGAIN + || errno == EWOULDBLOCK); + if (errno && retry) + continue; + + /* leave writing loop on error */ + if (errno) + break; } count -= sysio()->write_out.count; src += sysio()->write_out.count; } - return orig_count; + return orig_count - count; } @@ -1321,6 +1366,14 @@ namespace { errno = 0; break; } + + /* try again */ + bool const retry = (errno == EINTR + || errno == EAGAIN + || errno == EWOULDBLOCK); + if (errno && retry) + continue; + return -1; } @@ -1682,9 +1735,6 @@ namespace { sysio()->dirent_in.fd = noux_fd(fd->context); - struct dirent *dirent = (struct dirent *)buf; - Genode::memset(dirent, 0, sizeof(struct dirent)); - if (!noux_syscall(Noux::Session::SYSCALL_DIRENT)) { switch (sysio()->error.general) { @@ -1697,23 +1747,35 @@ namespace { } } - switch (sysio()->dirent_out.entry.type) { - case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: dirent->d_type = DT_DIR; break; - case Vfs::Directory_service::DIRENT_TYPE_FILE: dirent->d_type = DT_REG; break; - case Vfs::Directory_service::DIRENT_TYPE_SYMLINK: dirent->d_type = DT_LNK; break; - case Vfs::Directory_service::DIRENT_TYPE_FIFO: dirent->d_type = DT_FIFO; break; - case Vfs::Directory_service::DIRENT_TYPE_CHARDEV: dirent->d_type = DT_CHR; break; - case Vfs::Directory_service::DIRENT_TYPE_BLOCKDEV: dirent->d_type = DT_BLK; break; - case Vfs::Directory_service::DIRENT_TYPE_END: return 0; - } + using Dirent_type = Vfs::Directory_service::Dirent_type; - dirent->d_fileno = sysio()->dirent_out.entry.fileno; - dirent->d_reclen = sizeof(struct dirent); + if (sysio()->dirent_out.entry.type == Dirent_type::END) + return 0; - Genode::strncpy(dirent->d_name, sysio()->dirent_out.entry.name, - sizeof(dirent->d_name)); + auto d_type = [] (Dirent_type const &type) + { + switch (sysio()->dirent_out.entry.type) { + case Dirent_type::DIRECTORY: return DT_DIR; + case Dirent_type::CONTINUOUS_FILE: return DT_REG; + case Dirent_type::TRANSACTIONAL_FILE: return DT_REG; + case Dirent_type::SYMLINK: return DT_LNK; + case Dirent_type::END: return 0; + } + return 0; + }; - dirent->d_namlen = Genode::strlen(dirent->d_name); + struct dirent &dirent = *(struct dirent *)buf; + + dirent = { }; + + dirent.d_type = d_type(sysio()->dirent_out.entry.type); + dirent.d_fileno = sysio()->dirent_out.entry.fileno; + dirent.d_reclen = sizeof(struct dirent); + + Genode::strncpy(dirent.d_name, sysio()->dirent_out.entry.name, + sizeof(dirent.d_name)); + + dirent.d_namlen = Genode::strlen(dirent.d_name); *basep += sizeof(struct dirent); return sizeof(struct dirent); diff --git a/repos/ports/src/noux-pkg/binutils/target.inc b/repos/ports/src/noux-pkg/binutils/target.inc index 141cbbe92..57780ea5a 100644 --- a/repos/ports/src/noux-pkg/binutils/target.inc +++ b/repos/ports/src/noux-pkg/binutils/target.inc @@ -7,9 +7,9 @@ CONFIGURE_ARGS = --disable-werror \ # # Pass CFLAGS and friends to the invokation of 'make' because # binutils execute 2nd-level configure scripts, which need -# the 'ENV' as well. +# the 'MKENV' as well. # -MAKE_ENV = $(ENV) +MAKE_ENV = $(MKENV) PKG_DIR = $(call select_from_ports,binutils)/src/noux-pkg/binutils diff --git a/repos/ports/src/noux-pkg/binutils_arm_64/target.mk b/repos/ports/src/noux-pkg/binutils_arm_64/target.mk new file mode 100644 index 000000000..cb37b5d5d --- /dev/null +++ b/repos/ports/src/noux-pkg/binutils_arm_64/target.mk @@ -0,0 +1,4 @@ +PROGRAM_PREFIX = genode-aarch64- +BINUTILS_TARGET = aarch64-none-elf + +include $(PRG_DIR)/../binutils/target.inc diff --git a/repos/ports/src/noux-pkg/gcc/patches/aarch64.patch b/repos/ports/src/noux-pkg/gcc/patches/aarch64.patch index 921e80b94..a2fd58fcd 100644 --- a/repos/ports/src/noux-pkg/gcc/patches/aarch64.patch +++ b/repos/ports/src/noux-pkg/gcc/patches/aarch64.patch @@ -1,10 +1,23 @@ +diff --git a/gcc/config.host b/gcc/config.host +index b5a4eb1..64a85dc 100644 +--- a/gcc/config.host ++++ b/gcc/config.host +@@ -99,7 +99,7 @@ case ${host} in + esac + + case ${host} in +- aarch64*-*-freebsd* | aarch64*-*-linux* | aarch64*-*-fuchsia*) ++ aarch64*-*-* | aarch64*-*-linux* | aarch64*-*-fuchsia*) + case ${target} in + aarch64*-*-*) + host_extra_gcc_objs="driver-aarch64.o" diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h -index b9bf979..86f64f9 100644 +index 976f9af..3c150d1 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h -@@ -935,4 +935,20 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); - extern tree aarch64_fp16_type_node; - extern tree aarch64_fp16_ptr_type_node; +@@ -1061,4 +1061,20 @@ extern poly_uint16 aarch64_sve_vg; + + #define REGMODE_NATURAL_SIZE(MODE) aarch64_regmode_natural_size (MODE) +/* genode.h */ + @@ -24,10 +37,10 @@ index b9bf979..86f64f9 100644 + #endif /* GCC_AARCH64_H */ diff --git a/libgcc/config.host b/libgcc/config.host -index fd206a4..a9a07ad 100644 +index 5e9cfa8..58af2f0 100644 --- a/libgcc/config.host +++ b/libgcc/config.host -@@ -331,8 +331,9 @@ esac +@@ -334,8 +334,9 @@ esac case ${host} in aarch64*-*-elf | aarch64*-*-rtems*) @@ -37,4 +50,4 @@ index fd206a4..a9a07ad 100644 + tmake_file="$tmake_file t-freebsd t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver" tmake_file="${tmake_file} ${cpu_type}/t-aarch64" tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" - ;; + md_unwind_header=aarch64/aarch64-unwind.h diff --git a/repos/ports/src/noux-pkg/gcc/target.inc b/repos/ports/src/noux-pkg/gcc/target.inc index 0d3726e18..1538ab375 100644 --- a/repos/ports/src/noux-pkg/gcc/target.inc +++ b/repos/ports/src/noux-pkg/gcc/target.inc @@ -22,17 +22,17 @@ CONFIGURE_ARGS = --program-prefix=$(PROGRAM_PREFIX) \ --disable-sjlj-exceptions \ --disable-nls -ENV += host_configargs="$(HOST_CONFIG_ARGS)" \ +MKENV += host_configargs="$(HOST_CONFIG_ARGS)" \ target_configargs="$(TARGET_CONFIG_ARGS)" -ENV += CC_FOR_TARGET=$(CC) CXX_FOR_TARGET=$(CXX) GCC_FOR_TARGET=$(CC) CPP_FOR_TARGET="$(CC) -E" \ +MKENV += CC_FOR_TARGET=$(CC) CXX_FOR_TARGET=$(CXX) GCC_FOR_TARGET=$(CC) CPP_FOR_TARGET="$(CC) -E" \ LD_FOR_TARGET=$(LD) AS_FOR_TARGET=$(AS) AR_FOR_TARGET=$(AR) # libgcc does not evaluate CPPFLAGS_FOR_TARGET, so everything is put into CFLAGS_FOR_TARGET here -ENV += CFLAGS_FOR_TARGET='-I$(BASE_DIR)/../../tool -DUSE_PT_GNU_EH_FRAME -Dinhibit_libc -fPIC' +MKENV += CFLAGS_FOR_TARGET='-I$(BASE_DIR)/../../tool -DUSE_PT_GNU_EH_FRAME -Dinhibit_libc -fPIC' # libsupc++ -ENV += CXXFLAGS_FOR_TARGET='-fPIC' +MKENV += CXXFLAGS_FOR_TARGET='-fPIC' MAKE_ENV += GENODE="yes" diff --git a/repos/ports/src/noux-pkg/gcc_arm_64/target.mk b/repos/ports/src/noux-pkg/gcc_arm_64/target.mk new file mode 100644 index 000000000..1993a6520 --- /dev/null +++ b/repos/ports/src/noux-pkg/gcc_arm_64/target.mk @@ -0,0 +1,7 @@ +PROGRAM_PREFIX = genode-aarch64- +GCC_TARGET = aarch64-none-elf + +# cross-compiling does not work yet +REQUIRES = arm_64 + +include $(PRG_DIR)/../gcc/target.inc diff --git a/repos/ports/src/noux-pkg/gdb/patches/gdbserver_genode.patch b/repos/ports/src/noux-pkg/gdb/patches/gdbserver_genode.patch index 3ec38f164..508b2ebf0 100644 --- a/repos/ports/src/noux-pkg/gdb/patches/gdbserver_genode.patch +++ b/repos/ports/src/noux-pkg/gdb/patches/gdbserver_genode.patch @@ -14,14 +14,14 @@ From: Christian Prochaska <christian.prochaska@genode-labs.com> gdb/gdbserver/linux-x86-low.c | 111 +++++++++++++++++++- gdb/gdbserver/linux-x86-tdesc-selftest.c | 31 ++++++ gdb/gdbserver/linux-x86-tdesc.c | 8 + - gdb/gdbserver/remote-utils.c | 11 ++ + gdb/gdbserver/remote-utils.c | 15 +++ gdb/gdbserver/server.c | 36 ++++++ gdb/gdbserver/server.h | 4 + gdb/nat/fork-inferior.c | 4 - gdb/nat/gdb_ptrace.h | 2 gdb/nat/linux-ptrace.c | 17 +++ gdb/nat/linux-ptrace.h | 4 + - 17 files changed, 418 insertions(+), 15 deletions(-) + 17 files changed, 422 insertions(+), 15 deletions(-) diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h index eb0ec21..4dc07ce 100644 @@ -1071,7 +1071,7 @@ index c3aa20c..e5a57c0 100644 init_target_desc (*tdesc, amd64_expedite_regs); } diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c -index 45d5c8d..7b6b1be 100644 +index 45d5c8d..b246402 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -27,6 +27,12 @@ @@ -1099,6 +1099,18 @@ index 45d5c8d..7b6b1be 100644 static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR; /* FIXME headerize? */ +@@ -312,7 +321,11 @@ remote_open (const char *name) + struct stat statbuf; + + if (stat (name, &statbuf) == 0 ++#ifndef __GENODE__ + && (S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))) ++#else ++ ) ++#endif + remote_desc = open (name, O_RDWR); + else + { diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index bf6302b..b6a9494 100644 --- a/gdb/gdbserver/server.c diff --git a/repos/ports/src/noux/child.h b/repos/ports/src/noux/child.h index 3c13d3e8c..06acf98b0 100644 --- a/repos/ports/src/noux/child.h +++ b/repos/ports/src/noux/child.h @@ -37,6 +37,7 @@ #include <verbose.h> #include <user_info.h> #include <armed_timeout.h> +#include <time_info.h> namespace Noux { @@ -124,6 +125,8 @@ class Noux::Child : public Rpc_object<Session>, User_info const &_user_info; + Time_info const &_time_info; + Parent_exit *_parent_exit; Kill_broadcaster &_kill_broadcaster; Timer::Connection &_timer_connection; @@ -319,6 +322,7 @@ class Noux::Child : public Rpc_object<Session>, Child(Child_policy::Name const &name, Verbose const &verbose, User_info const &user_info, + Time_info const &time_info, Parent_exit *parent_exit, Kill_broadcaster &kill_broadcaster, Timer::Connection &timer_connection, @@ -342,6 +346,7 @@ class Noux::Child : public Rpc_object<Session>, _name(name), _verbose(verbose), _user_info(user_info), + _time_info(time_info), _parent_exit(parent_exit), _kill_broadcaster(kill_broadcaster), _timer_connection(timer_connection), @@ -521,6 +526,7 @@ class Noux::Child : public Rpc_object<Session>, Child *child = new (_heap) Child(filename, _verbose, _user_info, + _time_info, _parent_exit, _kill_broadcaster, _timer_connection, diff --git a/repos/ports/src/noux/main.cc b/repos/ports/src/noux/main.cc index ca4f77c57..3fc8b2359 100644 --- a/repos/ports/src/noux/main.cc +++ b/repos/ports/src/noux/main.cc @@ -27,6 +27,7 @@ #include <kill_broadcaster.h> #include <vfs/dir_file_system.h> #include <vfs/simple_env.h> +#include <time_info.h> namespace Noux { @@ -98,7 +99,9 @@ connect_stdio(Genode::Env &env, Vfs::File_system &root, Noux::Vfs_io_waiter_registry &vfs_io_waiter_registry, Noux::Terminal_io_channel::Type type, - Genode::Allocator &alloc) + Genode::Allocator &alloc, + Noux::Time_info &time_info, + Timer::Connection &timer) { using namespace Vfs; using namespace Noux; @@ -142,7 +145,8 @@ connect_stdio(Genode::Env &env, return *new (alloc) Vfs_io_channel(path.string(), root.leaf_path(path.string()), - vfs_handle, vfs_io_waiter_registry, env.ep()); + vfs_handle, vfs_io_waiter_registry, env.ep(), + time_info, timer); } @@ -241,6 +245,8 @@ struct Noux::Main User_info _user_info { _config.xml() }; + Time_info _time_info { _env, _config.xml() }; + Signal_handler<Main> _destruct_handler { _env.ep(), *this, &Main::_handle_destruct }; @@ -273,6 +279,7 @@ struct Noux::Main Noux::Child _init_child { _name_of_init_process(), _verbose, _user_info, + _time_info, 0, _kill_broadcaster, _timer_connection, @@ -302,13 +309,13 @@ struct Noux::Main Shared_pointer<Io_channel> _channel_0 { &connect_stdio(_env, _terminal, _config.xml(), _root_dir, _io_response_handler.io_waiter_registry, - Tio::STDIN, _heap), _heap }, + Tio::STDIN, _heap, _time_info, _timer_connection), _heap }, _channel_1 { &connect_stdio(_env, _terminal, _config.xml(), _root_dir, _io_response_handler.io_waiter_registry, - Tio::STDOUT, _heap), _heap }, + Tio::STDOUT, _heap, _time_info, _timer_connection), _heap }, _channel_2 { &connect_stdio(_env, _terminal, _config.xml(), _root_dir, _io_response_handler.io_waiter_registry, - Tio::STDERR, _heap), _heap }; + Tio::STDERR, _heap, _time_info, _timer_connection), _heap }; Main(Env &env) : _env(env) { diff --git a/repos/ports/src/noux/pipe_io_channel.h b/repos/ports/src/noux/pipe_io_channel.h index 662b3ffae..9d7f8d449 100644 --- a/repos/ports/src/noux/pipe_io_channel.h +++ b/repos/ports/src/noux/pipe_io_channel.h @@ -271,7 +271,7 @@ class Noux::Pipe_sink_io_channel : public Io_channel bool fstat(Sysio &sysio) override { - sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV; + sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE; return true; } }; @@ -345,7 +345,7 @@ class Noux::Pipe_source_io_channel : public Io_channel bool fstat(Sysio &sysio) override { - sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV; + sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE; return true; } }; diff --git a/repos/ports/src/noux/syscall.cc b/repos/ports/src/noux/syscall.cc index 2cabfedaf..1d2722105 100644 --- a/repos/ports/src/noux/syscall.cc +++ b/repos/ports/src/noux/syscall.cc @@ -121,9 +121,6 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) * we use the ones specificed in the config. */ if (result) { - stat_out.uid = _user_info.uid(); - stat_out.gid = _user_info.gid(); - stat_out.inode = path_hash; } @@ -233,12 +230,17 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) if (&vfs_handle->ds() == &_root_dir) leaf_path = _sysio.open_in.path; + if (!leaf_path) + break; + Shared_pointer<Io_channel> channel(new (_heap) Vfs_io_channel(_sysio.open_in.path, leaf_path, vfs_handle, _vfs_io_waiter_registry, - _env.ep()), + _env.ep(), + _time_info, + _timer_connection), _heap); _sysio.open_out.fd = add_io_channel(channel); @@ -511,6 +513,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) child = new (_heap) Child(_child_policy.name(), _verbose, _user_info, + _time_info, this, _kill_broadcaster, _timer_connection, @@ -844,7 +847,8 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) Milliseconds const ms = _timer_connection.curr_time().trunc_to_plain_ms(); - _sysio.gettimeofday_out.sec = (ms.value / 1000); + _sysio.gettimeofday_out.sec = _time_info.initial_time(); + _sysio.gettimeofday_out.sec += (ms.value / 1000); _sysio.gettimeofday_out.usec = (ms.value % 1000) * 1000; result = true; @@ -864,7 +868,8 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) /* CLOCK_SECOND is used by time(3) in the libc. */ case Sysio::CLOCK_ID_SECOND: { - _sysio.clock_gettime_out.sec = (ms.value / 1000); + _sysio.clock_gettime_out.sec = _time_info.initial_time(); + _sysio.clock_gettime_out.sec += (ms.value / 1000); _sysio.clock_gettime_out.nsec = 0; result = true; @@ -889,13 +894,42 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) case SYSCALL_UTIMES: { /** - * This systemcall is currently not implemented because we lack - * the needed mechanisms in most file-systems. - * - * But we return true anyway to keep certain programs, e.g. make - * happy. + * Always return true, even if 'update_modification_timestamp' + * failed to keep programs, e.g. make, happy. */ result = true; + + char const *path = (char const *)_sysio.utimes_in.path; + unsigned long sec = _sysio.utimes_in.sec; + unsigned long usec = _sysio.utimes_in.usec; + (void)usec; + + Vfs::Vfs_handle *vfs_handle = 0; + _root_dir.open(path, 0, &vfs_handle, _heap); + if (!vfs_handle) { break; } + + if (!sec) { + Milliseconds const ms = + _timer_connection.curr_time().trunc_to_plain_ms(); + sec = _time_info.initial_time(); + sec += (ms.value / 1000); + usec = (ms.value % 1000) * 1000; + } + + Registered_no_delete<Vfs_io_waiter> + vfs_io_waiter(_vfs_io_waiter_registry); + + Vfs::Timestamp ts { .value = (long long)sec }; + + for (;;) { + if (vfs_handle->fs().update_modification_timestamp(vfs_handle, ts)) { + break; + } else { + vfs_io_waiter.wait_for_io(); + } + } + + _root_dir.close(vfs_handle); break; } diff --git a/repos/ports/src/noux/terminal_io_channel.h b/repos/ports/src/noux/terminal_io_channel.h index 76ad18cb7..71937f4b8 100644 --- a/repos/ports/src/noux/terminal_io_channel.h +++ b/repos/ports/src/noux/terminal_io_channel.h @@ -151,12 +151,7 @@ struct Noux::Terminal_io_channel : Io_channel bool fstat(Sysio &sysio) override { - /* - * Supply stat values such that libc is happy. I.e., the libc - * is checking for the file descriptor 1 being a character - * device. - */ - sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV; + sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE; return true; } diff --git a/repos/ports/src/noux/time_info.h b/repos/ports/src/noux/time_info.h new file mode 100644 index 000000000..df666fa2e --- /dev/null +++ b/repos/ports/src/noux/time_info.h @@ -0,0 +1,104 @@ +/* + * \brief Time information + * \author Josef Soentgen + * \date 2019-04-09 + */ + +/* + * Copyright (C) 2019 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 _NOUX__TIME_INFO_H_ +#define _NOUX__TIME_INFO_H_ + +/* Genode includes */ +#include <util/string.h> +#include <util/xml_node.h> +#include <rtc_session/connection.h> + +/* Noux includes */ +#include <noux_session/sysio.h> + +namespace Noux { + class Time_info; + using namespace Genode; +} + + +class Noux::Time_info : Noncopyable +{ + private: + + Constructible<Rtc::Connection> _rtc { }; + + Genode::int64_t _initial_time { 0 }; + + static bool _leap(unsigned year) + { + return ((year % 4) == 0 + && ((year % 100) != 0 || (year % 400) == 0)); + } + + /** + * Convert RTC timestamp to UNIX epoch (UTC) + */ + static Genode::int64_t _convert(Rtc::Timestamp const &ts) + { + if (ts.year < 1970) { return 0; } + + /* + * Seconds per year lookup table + */ + static constexpr unsigned _secs_per_year[2] = { + 365 * 86400, 366 * 86400, + }; + + /* + * Seconds per month lookup table + */ + static constexpr unsigned _sec_per_month[13] = { + 0 * 86400, + 31 * 86400, 28 * 86400, 31 * 86400, 30 * 86400, + 31 * 86400, 30 * 86400, 31 * 86400, 31 * 86400, + 30 * 86400, 31 * 86400, 30 * 86400, 31 * 86400 + }; + + Genode::int64_t time = 0; + + for (unsigned i = 1970; i < ts.year; i++) { + /* abuse bool conversion for seconds look up */ + time += _secs_per_year[(int)_leap(i)]; + } + + for (unsigned i = 1; i < ts.month; i++) { + time += _sec_per_month[i]; + } + time += _leap(ts.year) * 86400LL; + + time += 86400LL * (ts.day-1); + time += 3600LL * ts.hour; + time += 60LL * ts.minute; + time += ts.second; + + return time; + } + + public: + + Time_info(Env &env, Xml_node config) + { + /* only try to establish the connection on demand */ + bool const rtc = config.attribute_value("rtc", false); + if (!rtc) { return; } + + _rtc.construct(env); + _initial_time = _convert(_rtc->current_time()); + } + + Genode::int64_t initial_time() const { return _initial_time; } +}; + +#endif /* _NOUX__TIME_INFO_H_ */ diff --git a/repos/ports/src/noux/vfs_io_channel.h b/repos/ports/src/noux/vfs_io_channel.h index 8290088a7..e86babc29 100644 --- a/repos/ports/src/noux/vfs_io_channel.h +++ b/repos/ports/src/noux/vfs_io_channel.h @@ -14,9 +14,13 @@ #ifndef _NOUX__VFS_IO_CHANNEL_H_ #define _NOUX__VFS_IO_CHANNEL_H_ +/* Genode includes */ +#include <timer_session/connection.h> + /* Noux includes */ #include <io_channel.h> #include <vfs/dir_file_system.h> +#include <time_info.h> namespace Noux { class Vfs_io_waiter; @@ -69,11 +73,32 @@ struct Noux::Vfs_io_channel : Io_channel bool const _dir = _fh.ds().directory(_leaf_path.base()); + Time_info const &_time_info; + Timer::Connection &_timer; + void _sync() { + Milliseconds const ms = + _timer.curr_time().trunc_to_plain_ms(); + uint64_t sec = _time_info.initial_time(); + sec += (ms.value / 1000); + + Vfs::Timestamp ts { .value = (long long)sec }; + Registered_no_delete<Vfs_io_waiter> vfs_io_waiter(_vfs_io_waiter_registry); + if ((_fh.status_flags() & Sysio::OPEN_MODE_ACCMODE) != Sysio::OPEN_MODE_RDONLY) { + for (;;) { + if (_fh.fs().update_modification_timestamp(&_fh, ts)) { + break; + } else { + Genode::error("_sync: update_modification_timestamp failed"); + vfs_io_waiter.wait_for_io(); + } + } + } + while (!_fh.fs().queue_sync(&_fh)) vfs_io_waiter.wait_for_io(); @@ -89,11 +114,13 @@ struct Noux::Vfs_io_channel : Io_channel Vfs_io_channel(char const *path, char const *leaf_path, Vfs::Vfs_handle *vfs_handle, Vfs_io_waiter_registry &vfs_io_waiter_registry, - Entrypoint &ep) + Entrypoint &ep, + Time_info const &time_info, + Timer::Connection &timer) : _read_avail_handler(ep, *this, &Vfs_io_channel::_handle_read_avail), _fh(*vfs_handle), _vfs_io_waiter_registry(vfs_io_waiter_registry), - _path(path), _leaf_path(leaf_path) + _path(path), _leaf_path(leaf_path), _time_info(time_info), _timer(timer) { _fh.fs().register_read_ready_sigh(&_fh, _read_avail_handler); } @@ -244,7 +271,7 @@ struct Noux::Vfs_io_channel : Io_channel */ unsigned const index = _fh.seek() / sizeof(Sysio::Dirent); if (index < 2) { - sysio.dirent_out.entry.type = Vfs::Directory_service::DIRENT_TYPE_DIRECTORY; + sysio.dirent_out.entry.type = Vfs::Directory_service::Dirent_type::DIRECTORY; strncpy(sysio.dirent_out.entry.name, index ? ".." : ".", sizeof(sysio.dirent_out.entry.name)); @@ -259,12 +286,10 @@ struct Noux::Vfs_io_channel : Io_channel * Align index range to zero when calling the directory service. */ - Vfs::Directory_service::Dirent dirent; - Vfs::file_size noux_dirent_seek = _fh.seek(); - _fh.seek((index - 2) * sizeof(dirent)); + _fh.seek((index - 2) * sizeof(Vfs::Directory_service::Dirent)); - Vfs::file_size const count = sizeof(dirent); + Vfs::file_size const count = sizeof(Vfs::Directory_service::Dirent); Registered_no_delete<Vfs_io_waiter> vfs_io_waiter(_vfs_io_waiter_registry); @@ -273,10 +298,10 @@ struct Noux::Vfs_io_channel : Io_channel vfs_io_waiter.wait_for_io(); Vfs::File_io_service::Read_result read_result; - Vfs::file_size out_count = 0; + Vfs::file_size out_count = 0; + Vfs::Directory_service::Dirent dirent { }; for (;;) { - read_result = _fh.fs().complete_read(&_fh, (char*)&dirent, count, out_count); @@ -293,7 +318,7 @@ struct Noux::Vfs_io_channel : Io_channel if ((read_result != Vfs::File_io_service::READ_OK) || (out_count != sizeof(dirent))) { - dirent = Vfs::Directory_service::Dirent(); + dirent = { }; } _fh.seek(noux_dirent_seek); diff --git a/repos/ports/src/virtualbox5/devxhci.cc b/repos/ports/src/virtualbox5/devxhci.cc index 1e8640661..db385bf13 100644 --- a/repos/ports/src/virtualbox5/devxhci.cc +++ b/repos/ports/src/virtualbox5/devxhci.cc @@ -21,7 +21,7 @@ #include <qemu/usb.h> /* libc internal includes */ -#include <thread_create.h> +#include <internal/thread_create.h> /* Virtualbox includes */ #define LOG_GROUP LOG_GROUP_DEV_EHCI diff --git a/repos/ports/src/virtualbox5/frontend/console.cc b/repos/ports/src/virtualbox5/frontend/console.cc index 2344f15fa..23a01de29 100644 --- a/repos/ports/src/virtualbox5/frontend/console.cc +++ b/repos/ports/src/virtualbox5/frontend/console.cc @@ -12,6 +12,7 @@ */ #include <base/log.h> +#include <libc/component.h> #include <util/xml_node.h> #include <VBox/settings.h> @@ -123,7 +124,7 @@ void GenodeConsole::update_video_mode() 32); } -void GenodeConsole::handle_input() +void GenodeConsole::_handle_input() { /* disable input processing if vm is powered down */ if (vm_down && (_vbox_mouse || _vbox_keyboard)) { @@ -273,7 +274,7 @@ void GenodeConsole::handle_input() RTTimeMilliTS()); } -void GenodeConsole::handle_mode_change() +void GenodeConsole::_handle_mode_change() { IFramebuffer *pFramebuffer = NULL; HRESULT rc = i_getDisplay()->QueryFramebuffer(0, &pFramebuffer); @@ -312,7 +313,7 @@ void GenodeConsole::init_clipboard() } } -void GenodeConsole::handle_cb_rom_change() +void GenodeConsole::_handle_cb_rom_change() { if (!_clipboard_rom) return; @@ -332,7 +333,7 @@ void GenodeConsole::init_backends(IKeyboard * gKeyboard, IMouse * gMouse) _nitpicker.mode_sigh(_mode_change_signal_dispatcher); - handle_mode_change(); + _handle_mode_change(); } void GenodeConsole::i_onMouseCapabilityChange(BOOL supportsAbsolute, @@ -518,7 +519,7 @@ void fireKeyboardLedsChangedEvent(IEventSource *, bool num_lock, guest_caps_lock = caps_lock; } -void GenodeConsole::handle_sticky_keys() +void GenodeConsole::_handle_sticky_keys() { /* no keyboard - no sticky key handling */ if (!_vbox_keyboard || !_caps_lock.constructed()) @@ -553,3 +554,15 @@ void GenodeConsole::handle_sticky_keys() _vbox_keyboard->PutScancode(Input::KEY_CAPSLOCK | 0x80); } } + +void GenodeConsole::handle_input() { + Libc::with_libc([&] () { _handle_input(); }); } + +void GenodeConsole::handle_sticky_keys() { + Libc::with_libc([&] () { _handle_sticky_keys(); }); } + +void GenodeConsole::handle_mode_change() { + Libc::with_libc([&] () { _handle_mode_change(); }); } + +void GenodeConsole::handle_cb_rom_change() { + Libc::with_libc([&] () { _handle_cb_rom_change(); }); } diff --git a/repos/ports/src/virtualbox5/frontend/console.h b/repos/ports/src/virtualbox5/frontend/console.h index a8e5917b8..ddcbcca92 100644 --- a/repos/ports/src/virtualbox5/frontend/console.h +++ b/repos/ports/src/virtualbox5/frontend/console.h @@ -140,6 +140,11 @@ class GenodeConsole : public Console { || keycode == Input::BTN_MIDDLE; } + void _handle_input(); + void _handle_mode_change(); + void _handle_cb_rom_change(); + void _handle_sticky_keys(); + public: GenodeConsole() diff --git a/repos/ports/src/virtualbox5/frontend/fb.h b/repos/ports/src/virtualbox5/frontend/fb.h index fc9c7cec0..24e15bde1 100644 --- a/repos/ports/src/virtualbox5/frontend/fb.h +++ b/repos/ports/src/virtualbox5/frontend/fb.h @@ -37,12 +37,7 @@ class Genodefb : Nitpicker::Connection &_nitpicker; Fb_Genode::Session &_fb; View_handle _view; - - /* The mode at the time when the mode change signal was received */ - Fb_Genode::Mode _next_fb_mode { 1024, 768, Fb_Genode::Mode::RGB565 }; - - /* The mode matching the currently attached dataspace */ - Fb_Genode::Mode _fb_mode; + Fb_Genode::Mode _fb_mode { 1024, 768, Fb_Genode::Mode::RGB565 }; /* * The mode currently used by the VM. Can be smaller than the @@ -55,20 +50,21 @@ class Genodefb : void _clear_screen() { - size_t const num_pixels = _fb_mode.width() * _virtual_fb_mode.height(); + size_t const max_h = Genode::min(_fb_mode.height(), _virtual_fb_mode.height()); + size_t const num_pixels = _fb_mode.width() * max_h; memset(_fb_base, 0, num_pixels * _fb_mode.bytes_per_pixel()); _fb.refresh(0, 0, _virtual_fb_mode.width(), _virtual_fb_mode.height()); } void _adjust_buffer() { - _nitpicker.buffer(Fb_Genode::Mode(_next_fb_mode.width(), _next_fb_mode.height(), + _nitpicker.buffer(Fb_Genode::Mode(_fb_mode.width(), _fb_mode.height(), Fb_Genode::Mode::RGB565), false); typedef Nitpicker::Session::Command Command; Nitpicker::Rect rect(Nitpicker::Point(0, 0), - Nitpicker::Area(_next_fb_mode.width(), _next_fb_mode.height())); + Nitpicker::Area(_fb_mode.width(), _fb_mode.height())); _nitpicker.enqueue<Command::Geometry>(_view, rect); _nitpicker.execute(); @@ -85,7 +81,7 @@ class Genodefb : _nitpicker.enqueue<Command::To_front>(_view, View_handle()); _nitpicker.execute(); - return _next_fb_mode; + return _fb_mode; } public: @@ -95,22 +91,28 @@ class Genodefb : _env(env), _nitpicker(nitpicker), _fb(*nitpicker.framebuffer()), - _fb_mode(_initial_setup()), - _virtual_fb_mode(_fb_mode), + _virtual_fb_mode(_initial_setup()), _fb_base(env.rm().attach(_fb.dataspace())) { int rc = RTCritSectInit(&_fb_lock); Assert(rc == VINF_SUCCESS); } - /* Return the next mode of the framebuffer */ - int w() const { return _next_fb_mode.width(); } - int h() const { return _next_fb_mode.height(); } + int w() const { return _fb_mode.width(); } + int h() const { return _fb_mode.height(); } void update_mode(Fb_Genode::Mode mode) { Lock(); - _next_fb_mode = mode; + + _fb_mode = mode; + + _env.rm().detach(_fb_base); + + _adjust_buffer(); + + _fb_base = _env.rm().attach(_fb.dataspace()); + Unlock(); } @@ -131,42 +133,33 @@ class Genodefb : Lock(); - bool ok = (w <= (ULONG)_next_fb_mode.width()) && - (h <= (ULONG)_next_fb_mode.height()); + bool ok = (w <= (ULONG)_fb_mode.width()) && + (h <= (ULONG)_fb_mode.height()); if (ok) { Genode::log("fb resize : [", screen, "] ", _virtual_fb_mode.width(), "x", _virtual_fb_mode.height(), " -> ", w, "x", h, - " (host: ", _next_fb_mode.width(), "x", - _next_fb_mode.height(), ")"); + " (host: ", _fb_mode.width(), "x", + _fb_mode.height(), ")"); - if ((w < (ULONG)_next_fb_mode.width()) || - (h < (ULONG)_next_fb_mode.height())) { + if ((w < (ULONG)_fb_mode.width()) || + (h < (ULONG)_fb_mode.height())) { /* clear the old content around the new, smaller area. */ _clear_screen(); } - _fb_mode = _next_fb_mode; - _virtual_fb_mode = Fb_Genode::Mode(w, h, Fb_Genode::Mode::RGB565); - _env.rm().detach(_fb_base); - - _adjust_buffer(); - - _fb_base = _env.rm().attach(_fb.dataspace()); - result = S_OK; - } else Genode::log("fb resize : [", screen, "] ", _virtual_fb_mode.width(), "x", _virtual_fb_mode.height(), " -> ", w, "x", h, " ignored" - " (host: ", _next_fb_mode.width(), "x", - _next_fb_mode.height(), ")"); + " (host: ", _fb_mode.width(), "x", + _fb_mode.height(), ")"); Unlock(); @@ -201,9 +194,11 @@ class Genodefb : PRUint32 imageSize, PRUint8 *image) override { - Nitpicker::Area area_fb = Nitpicker::Area(_fb_mode.width(), - _fb_mode.height()); - Nitpicker::Area area_vm = Nitpicker::Area(width, height); + Lock(); + + Nitpicker::Area const area_fb = Nitpicker::Area(_fb_mode.width(), + _fb_mode.height()); + Nitpicker::Area const area_vm = Nitpicker::Area(width, height); using namespace Genode; @@ -217,6 +212,8 @@ class Genodefb : _fb.refresh(o_x, o_y, area_vm.w(), area_vm.h()); + Unlock(); + return S_OK; } @@ -234,8 +231,8 @@ class Genodefb : if (!supported) return E_POINTER; - *supported = ((width <= (ULONG)_next_fb_mode.width()) && - (height <= (ULONG)_next_fb_mode.height())); + *supported = ((width <= (ULONG)_fb_mode.width()) && + (height <= (ULONG)_fb_mode.height())); return S_OK; } diff --git a/repos/ports/src/virtualbox5/generic/sup_vmm.cc b/repos/ports/src/virtualbox5/generic/sup_vmm.cc index 8074d83a5..dfe9d8d05 100644 --- a/repos/ports/src/virtualbox5/generic/sup_vmm.cc +++ b/repos/ports/src/virtualbox5/generic/sup_vmm.cc @@ -33,10 +33,10 @@ #include "vcpu_vmx.h" /* libc memory allocator */ -#include <libc_mem_alloc.h> +#include <internal/mem_alloc.h> /* Genode libc pthread binding */ -#include <thread_create.h> +#include <internal/thread_create.h> /* libc */ #include <pthread.h> @@ -1154,8 +1154,10 @@ class Periodic_gip ASMAtomicIncU32(&cpu->u32TransactionId); /* call the timer function of the RTTimerCreate call */ - if (rttimer_func) - rttimer_func(nullptr, rttimer_obj, 0); + if (rttimer_func) { + Libc::with_libc([&] () { + rttimer_func(nullptr, rttimer_obj, 0); }); + } for (Vcpu_handler *vcpu_handler = vcpu_handler_list().first(); vcpu_handler; diff --git a/repos/ports/src/virtualbox5/libc.cc b/repos/ports/src/virtualbox5/libc.cc index 47689b119..99a1028b8 100644 --- a/repos/ports/src/virtualbox5/libc.cc +++ b/repos/ports/src/virtualbox5/libc.cc @@ -29,7 +29,7 @@ #include "vmm.h" /* libc memory allocator */ -#include <libc_mem_alloc.h> +#include <internal/mem_alloc.h> /* VirtualBox includes */ #include <iprt/mem.h> diff --git a/repos/ports/src/virtualbox5/mm.cc b/repos/ports/src/virtualbox5/mm.cc index 8077c8e50..f6d617e2e 100644 --- a/repos/ports/src/virtualbox5/mm.cc +++ b/repos/ports/src/virtualbox5/mm.cc @@ -31,7 +31,7 @@ #include <iprt/string.h> /* libc memory allocator */ -#include <libc_mem_alloc.h> +#include <internal/mem_alloc.h> #include "util.h" #include "mm.h" diff --git a/repos/ports/src/virtualbox5/network.cpp b/repos/ports/src/virtualbox5/network.cpp index a73cc302d..f743e6410 100644 --- a/repos/ports/src/virtualbox5/network.cpp +++ b/repos/ports/src/virtualbox5/network.cpp @@ -41,10 +41,11 @@ #include <nic/packet_allocator.h> #include <base/snprintf.h> -#include <thread_create.h> +#include <internal/thread_create.h> /* VBox Genode specific */ #include "vmm.h" +#include <libc/component.h> /******************************************************************************* * Structures and Typedefs * @@ -121,12 +122,13 @@ class Nic_client char *rx_content = _nic.rx()->packet_content(rx_packet); - int rc = _down_rx->pfnWaitReceiveAvail(_down_rx, RT_INDEFINITE_WAIT); - if (RT_FAILURE(rc)) - continue; + Libc::with_libc([&] () { + int rc = _down_rx->pfnWaitReceiveAvail(_down_rx, RT_INDEFINITE_WAIT); + if (RT_FAILURE(rc)) return; - rc = _down_rx->pfnReceive(_down_rx, rx_content, rx_packet.size()); - AssertRC(rc); + rc = _down_rx->pfnReceive(_down_rx, rx_content, rx_packet.size()); + AssertRC(rc); + }); _nic.rx()->acknowledge_packet(rx_packet); } @@ -138,9 +140,11 @@ class Nic_client { _link_up = _nic.link_state(); - _down_rx_config->pfnSetLinkState(_down_rx_config, - _link_up ? PDMNETWORKLINKSTATE_UP - : PDMNETWORKLINKSTATE_DOWN); + Libc::with_libc([&] () { + _down_rx_config->pfnSetLinkState(_down_rx_config, + _link_up ? PDMNETWORKLINKSTATE_UP + : PDMNETWORKLINKSTATE_DOWN); + }); } void _handle_destruct() diff --git a/repos/ports/src/virtualbox5/spec/nova/sup.cc b/repos/ports/src/virtualbox5/spec/nova/sup.cc index bcd8e0a62..71b968e16 100644 --- a/repos/ports/src/virtualbox5/spec/nova/sup.cc +++ b/repos/ports/src/virtualbox5/spec/nova/sup.cc @@ -39,7 +39,7 @@ #include "vcpu_vmx.h" /* libc memory allocator */ -#include <libc_mem_alloc.h> +#include <internal/mem_alloc.h> /* libc */ #include <sched.h> /* sched_yield */ diff --git a/repos/ports/src/virtualbox5/spec/nova/sup_old.cc b/repos/ports/src/virtualbox5/spec/nova/sup_old.cc index 64d734532..831a12394 100644 --- a/repos/ports/src/virtualbox5/spec/nova/sup_old.cc +++ b/repos/ports/src/virtualbox5/spec/nova/sup_old.cc @@ -21,11 +21,13 @@ /* VirtualBox includes */ #include <iprt/ldr.h> +#include <iprt/thread.h> #include <iprt/semaphore.h> #include <iprt/timer.h> #include <iprt/uint128.h> #include <VBox/err.h> + static PFNRTTIMER rttimer_func = nullptr; static void * rttimer_obj = nullptr; @@ -39,9 +41,26 @@ enum { PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPage; -struct Periodic_gip : public Genode::Thread +struct Periodic_gip { - Periodic_gip(Genode::Env &env) : Thread(env, "periodic_gip", 8192) { start(); } + struct Thread + { + static DECLCALLBACK(int) fn(RTTHREAD, void *) + { + genode_update_tsc(Periodic_gip::update, UPDATE_US); + return 0; + } + + Thread() + { + int const rc = RTThreadCreate(nullptr, fn, this, + 0, RTTHREADTYPE_TIMER, 0, "periodic_gip"); + if (RT_FAILURE(rc)) { + printf("Error: RTThreadCreate() %s\n", RTErrGetShort(rc)); + exit(-1); + } + } + } thread; static void update() { @@ -95,8 +114,6 @@ struct Periodic_gip : public Genode::Thread if (rttimer_func) rttimer_func(nullptr, rttimer_obj, 0); } - - void entry() override { genode_update_tsc(update, UPDATE_US); } }; @@ -139,7 +156,7 @@ struct Attached_gip : Genode::Attached_ram_dataspace cpu->idApic = 0; /* schedule periodic call of GIP update function */ - static Periodic_gip periodic_gip(genode_env()); + static Periodic_gip periodic_gip { }; } }; diff --git a/repos/ports/src/virtualbox5/spec/nova/vcpu.h b/repos/ports/src/virtualbox5/spec/nova/vcpu.h index 5b67b949d..7d77d2ee3 100644 --- a/repos/ports/src/virtualbox5/spec/nova/vcpu.h +++ b/repos/ports/src/virtualbox5/spec/nova/vcpu.h @@ -48,7 +48,7 @@ #include "sup.h" /* Genode libc pthread binding */ -#include "thread.h" +#include <internal/pthread.h> /* LibC includes */ #include <setjmp.h> diff --git a/repos/ports/src/virtualbox5/thread.cc b/repos/ports/src/virtualbox5/thread.cc index 67819b7e8..779a974fa 100644 --- a/repos/ports/src/virtualbox5/thread.cc +++ b/repos/ports/src/virtualbox5/thread.cc @@ -18,7 +18,7 @@ #include <cpu_session/connection.h> /* Genode libc pthread binding */ -#include <thread_create.h> +#include <internal/thread_create.h> #include "sup.h" #include "vmm.h" @@ -118,9 +118,15 @@ static int create_thread(pthread_t *thread, const pthread_attr_t *attr, */ } + /* + * Make sure timers run at the same priority as component threads, otherwise + * no timer progress can be made. See 'rtTimeNanoTSInternalRef' (timesupref.h) + * and 'rtTimerLRThread' (timerlr-generic.cpp) + */ + bool const rtthread_timer = rtthread->enmType == RTTHREADTYPE_TIMER; return Libc::pthread_create(thread, start_routine, arg, stack_size, rtthread->szName, - cpu_connection(rtthread->enmType), + rtthread_timer ? nullptr : cpu_connection(rtthread->enmType), Genode::Affinity::Location()); } diff --git a/repos/ports/src/virtualbox5/vcpu.h b/repos/ports/src/virtualbox5/vcpu.h index 8c7a4f3f1..2dfee83fa 100644 --- a/repos/ports/src/virtualbox5/vcpu.h +++ b/repos/ports/src/virtualbox5/vcpu.h @@ -41,7 +41,7 @@ #include "sup.h" /* Genode libc pthread binding */ -#include "thread.h" +#include <internal/pthread.h> #include <VBox/vmm/rem.h> diff --git a/tool/autopilot.list b/tool/autopilot.list index 905b81fa5..3b1bfe7aa 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -8,19 +8,20 @@ depot_download depot_query extract fb_bench -fetchurl_lxip fetchurl_lwip +fetchurl_lxip fs_query gdb_monitor ieee754 init_smp input_filter -libc_fatfs +libc_vfs_fs_ext2 log_core lwip lx_hybrid_ctors lx_hybrid_exception lx_hybrid_pthread_ipc +microcode moon netperf_lwip netperf_lwip_bridge @@ -69,9 +70,9 @@ vbox5_ubuntu_16_04_32 vbox5_ubuntu_16_04_64 vbox5_vm_ubuntu_16_04_32 vbox5_vm_ubuntu_16_04_64 +vbox5_vm_win10_64 vbox5_vm_win7_32 vbox5_vm_win7_64 -vbox5_vm_win10_64 vbox5_win10_64 vbox5_win7_32 vbox5_win7_64 @@ -82,4 +83,3 @@ verify vfs_import vmm_arm vmm_x86 -microcode diff --git a/tool/run/log/amt b/tool/run/log/amt index 5d1913ebd..7ef3d284a 100644 --- a/tool/run/log/amt +++ b/tool/run/log/amt @@ -78,6 +78,7 @@ proc run_log { wait_for_re timeout_value } { spawn /bin/sh -c "$amt_cmd" set output_spawn_id $spawn_id + fconfigure $output_spawn_id -translation { crlf lf } set kernel_msg [run_boot_string] diff --git a/tool/run/log/serial b/tool/run/log/serial index 02baa7ce1..98a604e98 100644 --- a/tool/run/log/serial +++ b/tool/run/log/serial @@ -55,6 +55,7 @@ proc run_log { wait_for_re timeout_value } { spawn /bin/sh -c "$serial_cmd_chain" set output_spawn_id $spawn_id + fconfigure $output_spawn_id -translation { crlf lf } expect { -i $output_spawn_id $kernel_msg { }