User-Guided Device Driver Synthesis

Page created by Shane Jackson
 
CONTINUE READING
User-Guided Device Driver Synthesis
User-Guided Device Driver Synthesis∗
        Leonid Ryzhyk1,2                Adam Walker2 John Keys3 Alexander Legg2                              Arun Raghunath3
                                              Michael Stumm1 Mona Vij3
                                                            1
                                                        University of Toronto
                                              2            †
                                                  NICTA and UNSW, Sydney, Australia
                                                         3
                                                           Intel Corporation

Abstract                                                                     lated the key principles behind the approach and demon-
                                                                             strated its feasibility by synthesizing drivers for several
   Automatic device driver synthesis is a radical approach                   real-world devices. The next logical step is to develop
to creating drivers faster and with fewer defects by gener-                  driver synthesis into a practical methodology, capable of
ating them automatically based on hardware device spec-                      replacing the conventional driver development process.
ifications. We present the design and implementation of a                    To this end we have to address the key problems left open
new driver synthesis toolkit, called Termite-2. Termite-2                    by Termite-1. The most important one is the quality of
is the first tool to combine the power of automation with                    synthesized drivers. While functionally correct, Termite-
the flexibility of conventional development. It is also the                  1 drivers were bloated and poorly structured. This made it
first practical synthesis tool based on abstraction refine-                  impossible for a programmer to maintain and improve the
ment. Finally, it is the first synthesis tool to support auto-               generated code and prevented synthesized drivers from
mated debugging of input specifications. We demonstrate                      being adopted by Linux and other major OSs. Further-
the practicality of Termite-2 by synthesizing drivers for a                  more, it was impossible to enforce non-functional proper-
number of I/O devices representative of a typical embed-                     ties such as CPU and power efficiency.
ded platform.
                                                                                Another critical limitation of Termite-1 was the limited
                                                                             scalability of its synthesis algorithm, which made synthe-
1      Introduction                                                          sis of drivers for real-world devices intractable. Termite-1
   Device driver synthesis has been proposed as a radical                    got around the problem by using carefully crafted simpli-
alternative to traditional driver development that offers the                fied device specifications, which is acceptable in a proof-
promise of creating drivers faster and with far fewer de-                    of-concept prototype, but not in a practical tool.
fects [24]. The idea is to automatically generate the driver                    In the present project we set out to address these limi-
code responsible for controlling device operations from a                    tations. After several years of research we achieved sig-
behavioral model of the device and a specification of the                    nificant improvement to all components of the synthesis
driver-OS interface.                                                         technology: the specification language, the synthesis al-
   The primary motivation for device driver synthesis is                     gorithm and the code generator.
the fact that device drivers are hard and tedious to write,                     Despite these improvements, we had come to the con-
and they are notorious for being unreliable [8, 13]. Drivers                 clusion that the approach taken was initially critically
generally take a long time to bring to production—given                      flawed. The fundamental problem, in our view, was that
the speed at which new devices can be brought to mar-                        the synthesis was viewed as a “push-button” technology
ket today, it is not uncommon for a device release to be                     that generated a specification-compliant implementation
delayed by driver rather than silicon issues [33].                           without any user involvement. As a result, the user had to
   Automatic driver synthesis was proposed in our ear-                       rely on the synthesis tool to produce a good implementa-
lier work on the Termite-1 project [24], where we formu-                     tion. Unfortunately, even the most intelligent algorithm
    ∗ This
                                                                             cannot fully capture the user-perceived notion of high-
             research is supported by a grant from Intel Corporation.
    † NICTA is funded by the Australian Government through the Depart-       quality code. While in theory one might be able to en-
ment of Communications and the Australian Research Council through           force some of the desired properties by adding appropri-
the ICT Centre of Excellence Program.                                        ate constraints to the input specification, in our experience

                                                                         1
user-guided
creating such specifications is extremely hard and seldom                                                                 code
yields satisfactory results.                                        input specifications:
                                                                                                                        generator
                                                                                                                                         synthesised driver
                                                                    - device model
   A radically different approach was needed—one that               - OS model
                                                                    - driver template synthesis
                                                                                                      the most general strategy

combines the power of automation with the flexibility of                              engine
                                                                                                      explanation of synthesis failure
conventional development, and that involves the devel-
oper from the start, guiding the generation of the driver.                                                                visual
                                                                                                                        debugger
                                                                                       corrected input specifications
In many ways, synthesis and conventional development
are conflicting. Hence, a key challenge was to conceive of
                                                                                   Figure 1: Termite synthesis workflow.
a way that allowed the two to be combined so that the de-
veloper could do their job more efficiently and with fewer          ing Termite-1, considered input specifications to be “cor-
errors without having the synthesis tool get in the way.            rect by definition”. In contrast, we recognise that input
   The primary contribution of this paper is a novel user-          specifications produced by human developers are likely to
guided approach to driver synthesis implemented in our              contain defects, which can prevent the synthesis algorithm
new tool called Termite-2 (further referred to as Termite).         from finding a correct driver implementation. There-
In Termite, the user has full control over the synthesis pro-       fore Termite incorporates powerful debugging tools that
cess, while the tool acts as an assistant that suggests, but        help the developer identify and fix specification defects
does not enforce, implementation options and ensures cor-           through well-defined steps, similar to how conventional
rectness of the resulting code. At any point during synthe-         debuggers help troubleshoot implementation errors.
sis the user can modify or extend previously synthesized               Another important contribution of this project is a new
code. The tool automatically analyses user-provided code            scalable synthesis algorithm, which mitigates the compu-
and, on user’s request, suggests possible ways to extend it         tational bottleneck in driver synthesis. Following the ap-
to a complete implementation. If such an extension is not           proach proposed in Termite-1, we treat the driver synthe-
possible due to an error in the user code, the tool generates       sis problem as a two-player game between the driver and
an explanation of the failure that helps the user to identify       its environment, comprised of the device and the OS. In
and correct the error.                                              this work, we develop this approach into the first precise
   In an extreme scenario, Termite can be used to synthe-           mathematical formulation of the driver synthesis problem
size the complete implementation fully automatically. At            based on game theory. This enables us to apply theoret-
the other extreme, the user can build the complete imple-           ical results and algorithmic techniques from game theory
mentation by hand, in which case Termite acts as a static           to driver synthesis.
verifier for the driver. In practice, we found the interme-            Our game-based synthesis algorithm relies on abstrac-
diate approach, where most of the code is auto-generated,           tion and symbolic reasoning to achieve orders of magni-
but manual involvement is used when needed to improve               tude speed up compared to the current state-of-the-art syn-
the implementation, to be the most practical.                       thesis techniques. The main idea of the algorithm is de-
   From the developer’s perspective, user-guided syn-               scribed in Section 4, but we refer the reader to a detailed
thesis appears as an enhancement of the conventional                description in an accompanying publication [30].
development process with very powerful autocomplete                    We evaluate Termite by synthesizing drivers for sev-
functionality, rather than a completely new development             eral I/O devices. Our experience demonstrates that our
methodology. This vision is implemented in all aspects of           methodology meets our design goals, and indeed makes
the design of Termite. In particular, input specifications          automatic driver synthesis practical.
for driver synthesis are written as imperative programs             Overview of Termite Figure 1 gives an overview of the
that model the behavior of the device and the OS. The               driver synthesis process, described in detail in the rest of
driver itself is modelled as a source code template where           the paper. Termite takes three specifications as its inputs:
parts to be synthesized are omitted. This approach enables          a device model that simulates software-visible device be-
the use of familiar programming techniques in building              havior, an OS model that specifies the software interface
input specifications. In contrast, previous synthesis tools,        between the driver and the OS, and a driver template that
including Termite-1, require specifications to be written           contains driver entry point declarations and, optionally,
in formal languages based on state machines and temporal            their partial implementation to be completed by Termite.
logic, which proved difficult and error-prone to use even              Given these specifications, driver synthesis proceeds in
for formal methods experts, not to mention software de-             two steps. The first step is carried out fully automati-
velopment practitioners.                                            cally by the Termite game-based synthesis engine, which
   Most previous research on automatic synthesis, includ-           computes the most general strategy for the driver—a data

                                                                2
OS model                                                             and the OS, but are used by the OS model to specify cor-
                           IO requests          IO completions
                                                /*send_ack()*/
                                                                                                           rectness constraints for the driver (see Section 2.3).
                                 /*send()*/
                                                                                                              Finally, the driver template contains a partial driver im-
                                                                     virtual callbacks
                                 driver template                     /*evt_send(), evt_send_fail()*/       plementation to be completed by Termite. A minimal tem-
                   device commands
    /*write_dat(), write_cmd(), read_cmd()*/
                                               device notifications
                                               /*irq()*/
                                                                                                           plate consists of a list of driver entrypoints without imple-
                                                                                                           mentation. At the other extreme, it can provide a complete
                                   device model
                                                                                                           implementation, in which case Termite acts as a static ver-
                                                                                                           ifier for the driver.
Figure 2: Input specifications for driver synthesis. Labels in                                                All specifications are written using the Termite Speci-
italics show interfaces from the running example (Figure 3).
                                                                                                           fication Language (TSL). In line with our goal of making
structure that compactly represents all possible correct                                                   synthesis as close to the conventional driver development
driver implementations. This step encapsulates the com-                                                    workflow as possible, TSL is designed as a dialect of C
putationally expensive part of synthesis. At the second                                                    with additional constructs for use in synthesis. We intro-
step, the most general strategy is used by the Termite code                                                duce relevant features of TSL throughout this section.
generator to construct one specific driver implementation                                                     We minimize the amount of work needed to develop
in C with the help of interactive input from the user.                                                     specifications for every synthesized driver by maximiz-
   The synthesis engine may establish that, due to a de-                                                   ing the reuse of specifications. In particular, Termite al-
fect in one of the input specifications, there does not exist                                              lows the use of existing device specifications developed
a specification-compliant driver implementation. In this                                                   by hardware designers in driver synthesis. Furthermore,
case, it produces an explanation of the failure, which can                                                 the OS specification for the driver can be derived from a
be analysed with the help of the Termite debugger tool in                                                  generic specification for a class of similar devices (e.g.,
order identify and correct the defect.                                                                     network or storage). Thus we expect that additional per-
                                                                                                           driver effort will consist of: (1) inserting device-class call-
Limitations of Termite The device driver synthesis
                                                                                                           backs in appropriate locations of the device model and (2)
technology is still in its early days and, as such, has sev-
                                                                                                           extending the OS specification to support device-specific
eral important limitations. Most notably, Termite does
                                                                                                           features missing in the generic OS specification.
not currently support synthesis or verification of code for
managing direct memory access (DMA) queues. This                                                           2.1    Device model
code must be written manually and is treated by Termite                                                    The device model simulates the device operation at a level
as an external API invoked by the driver. As another ex-                                                   of detail sufficient to synthesize a correct driver for it. To
ample, in certain situations, explained in Section 3, Ter-                                                 this end, it must accurately model external device behav-
mite is unable to produce correct code without user as-                                                    ior visible to software. At the same time, it is not required
sistance; however it is able to verify the correctness of                                                  to precisely capture internal device operation and timing,
user-provided code. We discuss limitations of Termite in                                                   as these aspects are opaque to the driver.
more detail in Section 6.                                                                                     Such device models are routinely developed by hard-
                                                                                                           ware designers for the purposes of design exploration,
2     Developing specifications                                                                            simulation, and testing. They are widely used by hard-
   Input to Termite consists of the three specifications,                                                  ware manufacturers in-house [14] and are available com-
which model the complete system consisting of the driver,                                                  mercially from major silicon IP vendors [28]. These mod-
the device, and the OS, shown in Figure 2. The OS and                                                      els are known as transaction-level models (TLMs) (in
device models simulate the execution environment of the                                                    contrast to the detailed register-transfer-level models used
driver and specify constraints on correct driver behavior.                                                 in gate-level synthesis) [4]. A TLM focuses on software-
The device model simulates software-visible device be-                                                     visible events, or transactions, such as a write to a device
havior. The OS model serves as a workload generator that                                                   register or a network packet transmission.
issues I/O requests to the driver and accepts request com-                                                    Existing TLMs created by hardware designers can be
pletions in a way consistent with real OS behavior.                                                        used with minor modifications (explained in Section 2.3)
   The virtual interface between the device and the OS,                                                    for driver synthesis. Model reuse dramatically reduces the
shown with the dashed arrow in Figure 2, is used by the                                                    effort involved in synthesizing a driver and is therefore
device model to notify the OS model about important                                                        crucial to practical success of driver synthesis. By reusing
hardware events, such as completion of I/O transactions                                                    an existing model, we also reuse the effort invested by
and error conditions. Methods of the virtual interface do                                                  hardware designers into testing and debugging the model
not represent real runtime interactions between the device                                                 throughout the hardware design cycle, thus making driver

                                                                                                       3
1 template dev /* Device model */                                    synthesis less susceptible to specification bugs. Finally,
 2   uint8 reg_dat, reg_cmd, reg_status = 0;
 3   /* device commands */                                            since TLMs are created early in the hardware design cy-
 4   controllable void write_dat(uint8 v)                             cle, TLM-based driver synthesis can be carried out early
 5   { reg_dat = v; };                                                as well, thus removing driver development from the criti-
 6   controllable void write_cmd(uint8 v)                             cal path to product delivery.
 7   { reg_cmd = v; };
 8   controllable uint8 read_cmd()                                       TLMs are written in high-level hardware description
 9   { return reg_cmd; };                                             languages like SystemC and DML. In order to use these
10   controllable uint8 read_status()                                 models in driver synthesis, we need to convert them to
11   { return reg_status; };
12   /* internal behavior */                                          TSL. This translation can be performed automatically, and
13   process ptx {                                                    we are currently working on a DML-to-TSL compiler.
14     forever {                                                      Since this work is not yet complete, device models used in
15        wait (reg_cmd == 1);
                                                                      the experimental section of this paper are either manually
16        choice {
17          { os.evt_send(reg_dat);                                   translated from existing TLMs or written from scratch us-
18            reg_status=0; };                                        ing TLM modeling style guidelines [31].
19          { os.evt_send_fail(reg_dat);                                 The top part of Figure 3 shows a fragment of a model
20            reg_status=1; };
21        };                                                          of a trivial serial controller device used as a running ex-
22        reg_cmd = 0;                                                ample. The fragment specifies the send logic of the con-
23        /*drv.irq(); (see Section 4*/                               troller, which allows software to send data characters over
24     };
                                                                      the serial line. The model is implemented as a TSL tem-
25   };
26 endtemplate
                                                                      plate. The template encapsulates data and code that ma-
27                                                                    nipulates the data, similar to a class in OOP.
28 template os /* OS model */
                                                                         The software interface of the device consists of
29   uint8 dat;
30   bool inprogress, acked, success;                                 data, command, and status registers declared in line 2.
31   /* driver workload generator */                                  The registers can be accessed from software via the
32   process psend {                                                  write dat, write cmd, read cmd, and read status
33     forever {
34       dat = *; /*randomise dat*/
                                                                      methods (lines 4–11). The controllable qualifier de-
35       inprogress = true;                                           notes a method that is available to the driver and can be
36       acked = false;                                               invoked from synthesized code.
37       drv.send(dat);
                                                                         The transmitter logic is modelled in lines 13–25. It is
38       wait(acked);
39     };                                                             implemented as a TSL process. A TSL specification can
40   };                                                               contain multiple processes. The choice of the process to
41   /* I/O completions */                                            run is made non-deterministically by the scheduler. The
42   controllable void send_ack(bool status) {
43     assert (!inprogress && !acked &&
                                                                      process executes atomically until reaching a wait state-
44              status == success);                                   ment or a controllable placeholder (see below).
45     acked = true;                                                     In line 15, the transmitter waits for a command, issued
46   };
47   /* virtual callbacks */
                                                                      by the driver by writing value 1 to the command register.
48   void evt_send(uint8 v) {                                         Upon receiving the command, it sends the value in the
49     assert (inprogress && v==dat);                                 data register over the serial line. The transmission may
50     inprogress = false;                                            fail, e.g., due to a serial link problem. The device signals
51     success = true;
52   };
                                                                      transmission status to software by setting the status regis-
53   void evt_send_fail(uint8 v) {                                    ter to 0 or 1. Finally, it clears the command register, thus
54     assert (inprogress && v==dat);                                 notifying the driver the request has completed.
55     inprogress = false;
56     success = false;
                                                                         Internally, the transmitter circuit consists of a shift reg-
57   };                                                               ister and a baud rate generator used to output data on
58   goal idle_goal = acked;                                          the serial line. These details are not visible to soft-
59 endtemplate
                                                                      ware and are abstracted away in the model. We use
60
61 template drv /* Driver template */
                                                                      the non-deterministic choice construct to choose be-
62   void send(uint8 v){...;};                                        tween successful transmission and failure, without mod-
63   /*void irq(){...;}; (see Section 4)*/                            elling the details of serial link operation. Successful and
64 endtemplate
                                                                      failed transmissions are modelled using evt send and
     Figure 3: Trivial serial controller driver specifications.       evt send fail events, explained in Section 2.2.

                                                                  4
2.2   OS model                                                    specification reuse, we would like to keep the OS specifi-
                                                                  cation device-independent. To reconcile these conflicting
The OS model specifies the API mandated by the OS for
                                                                  requirements, we introduce a virtual interface between the
all drivers of the given type. For example, any Ether-
                                                                  device and OS model. This interface consists of callbacks
net driver must implement the interface for sending and
                                                                  used by the device model to notify the OS model about
receiving Ethernet packets. A separate specification is
                                                                  important hardware events. The virtual interface does not
needed for each supported OS, as different OSs define dif-
                                                                  represent real runtime interactions between the device and
ferent interfaces for device drivers.
                                                                  the OS, but serves as part of the correctness specification.
   Additionally, each particular device can support non-
standard features, e.g., device-specific configuration op-          We define a virtual interface for each class of devices.
tions or transfer modes. These features must be added as          Such device-class interfaces are both device and OS-
extensions to the generic OS specification in order to syn-       independent. The device-class interface can be extended
thesize support for them in the driver. TSL supports such         with additional device-specific callbacks as required to
extensions in a systematic way via the template inheri-           specify a driver for a particular device.
tance mechanism. We do not describe this in detail due to
limited space.                                                       In our example, we define a device-class interface
   The OS model is written in the form of a test harness          consisting of two virtual callbacks: evt send and
that simulates all possible sequences of driver invocations       ev send failed, invoked respectively when the device
issued by the OS. The os template in Figure 3 shows the           successfully transmits and fails to transmit a byte. These
OS model for our running example. The main part of the            callbacks are invoked in lines 17 and 19 of the device
model is the psend process. At every iteration of the loop,       model. The evt send handler is shown in line 48 of
it non-deterministically chooses an 8-bit value (line 34)         the OS model. The assertion in line 49 specifies that the
and calls the send method of the driver, passing this value       send event is only allowed to occur if there is an outstand-
as an argument. It then waits for the driver to acknowl-          ing send request in progress and the value being sent is
edge the transmission of the byte (line 38) before issuing        the same as the one requested by the OS. We reset the
another request. The driver acknowledges the transmis-            inprogress flag to false in line 50, thus marking the cur-
sion via the send ack callback (line 42). The callback            rent request as completed; line 51 sets the success flag
sets the acked flag, which unblocks the psend process.            to true, thus indicating that the transfer completed with-
   We keep the specification concise by modeling the state        out an error. The evt send fail handler is identical,
of the driver-OS interface, as opposed to the internal OS         except that it sets the success flag to false. The flags
state and behavior. For example, the acked variable               are checked by the send ack method, which asserts that
(line 30) serves to model the flow of data between the OS         the driver is only allowed to acknowledge a completed
and the driver and is not necessarily present in the OS im-       request (!inprogress) that has not been acknowledged
plementation.                                                     yet (!acked) and that the completion status reported by
                                                                  the driver must match the one recorded in the success
2.3   Connecting device and OS models                             flag.
In addition to simulating I/O requests to the driver, the            In this example we use C-style assertions to rule out
OS model also specifies the semantics of each request in          invalid system behaviors. Assertions alone do not fully
terms of device-internal events that must occur in order to       capture requirements for a correct driver behavior. For
complete the requested I/O operation. In our running ex-          example, a driver that remains idle does not violate any as-
ample, after the OS invokes the send method of the driver         sertions. Hence, we need to specify requirements for the
and before the driver acknowledges completion of the re-          driver to make forward progress. We introduce such re-
quest, the device must attempt to send the requested data         quirements into the model in the form of goal conditions,
over the serial line. This requirement establishes a con-         that must hold infinitely often in any run of the system. For
nection between the device and OS models and must be              example, a goal may require that the driver is infinitely of-
specified explicitly in order to enable Termite to generate       ten in an idle state with no outstanding requests from the
a driver implementation that correctly handles the OS re-         OS. The OS can force the driver out of the goal by issu-
quest. Note that we only need to specify which hardware           ing a new I/O request. To satisfy the goal condition, the
events must occur, but not how the driver generates them.         driver must return to the goal state by completing the re-
   In order to develop such specifications, we need a way         quest. Line 58 in Figure 3 defines such a goal condition
to refer to relevant state and behavior of the device from        that holds whenever the acked flag is set, i.e., the driver
the OS model. At the same time, in order to maximize              has no unacknowledged send requests.

                                                              5
2.4    Driver template                                     out branching. For example, when running the generator
The bottom part of Figure 3 shows the driver template on the specification in Figure 3, it automatically generates
for the running example consisting of a single send entry the following code for the send function (line 62):
point invoked by the OS. The ellipsis in line 62 represent void send(uint8 v){
                                                                dev.write_dat(v);
a location for inserting synthesized code and are part of       dev.write_cmd(1);
TSL syntax. We refer to such locations as controllable          wait(dev.reg_cmd==0);
placeholders.                                                   if (os.success) {
                                                                             os.send_ack(true);
                                                                         } else {
3     User-guided code generation                                            os.send_ack(false);
   The set of input TSL specifications is fed into the Ter-              };}
mite synthesis engine, which then automatically computes            This implementation correctly starts the data transfer by
the most general strategy for the driver. Given a state of          writing the value to be sent to the data register and setting
the system, the most general strategy determines the set            the command register to 1. It then waits for the transfer
of all valid driver actions in this state. The most general         to complete, which is signalled by the device by resetting
strategy is used by the Termite code generator to produce           the command register to 0. Finally, it acknowledges the
a driver implementation in C in a user-guide fashion.               completion of the transfer to the OS.
   The Termite code generator GUI is similar to a tradi-               Note that the generated code refers to the dev.reg cmd
tional integrated development environment with two ad-              and os.success variables. These variables model in-
ditional built-in tools: the generator and the verifier. The        ternal device and OS state respectively and cannot be di-
generator works as advanced auto-complete that helps the            rectly accessed by the driver. This example illustrates an
user to fill the controllable placeholders inside the driver        important limitation of Termite—it assumes a white-box
template with code. At any point, the user can invoke               model of the system, where every state variable is visi-
the generator to synthesize a single statement or a com-            ble to the driver. Ideally, we would like to synthesize an
plete block of code inside a controllable placeholder via a         implementation that automatically infers the values of im-
mouse click on the target code location. The user can ar-           portant unobservable variables. In this case, the value of
bitrarily modify and amend the generated code. However,             the command register can be obtained by the driver by ex-
the generator never modifies user code. Instead it tries to         ecuting the read cmd action. Furthermore, the value of
extend it to a complete implementation, which is always             the os.success variable is correlated with the comple-
possible provided that the existing code is consistent with         tion status of the last transfer, which can be obtained by
the most general strategy. The generator currently only al-         reading the device status register.
lows synthesizing statements after the last control location           While Termite currently cannot produce such an imple-
within a branch. However this restriction is not a concep-          mentation automatically, it implements a pragmatic trade-
tual one and will be lifted by ongoing development.                 off that helps the user build and validate a correct im-
   The verifier automatically and on the fly checks that            plementation with modest manual effort. The code gen-
the driver implementation, comprised of a mix of gen-               erator warns the user that the auto-generated code ac-
erated and manually written code, is consistent with the            cesses private variables of the device and OS templates.
most general strategy, thus maintaining strong correctness          This prompts the user to provide a functionally equiva-
guarantees that one would expect in automatically synthe-           lent valid implementation, replacing the wait statement
sized code. The verifier symbolically simulates execution           with a polling loop and using the read status method
of the system, following the partial driver implementation          to check transfer status:
created so far, and signals the user whenever it encounters         void send(uint8 v){
a transition that violates the most general strategy.                   dev.write_dat(v);
   In the first approximation, the generator algorithm is               dev.write_cmd(1);
quite simple: given a source code location, it determines               while(dev.read cmd()==1);
                                                                        if (dev.read status()) {
the set of possible system states in this location, picks an                os.send_ack(true);
action for each state from the most general strategy and                } else {
translates this action into a code statement. In practice the               os.send_ack(false);
algorithm uses a number of heuristics to produce compact                };}
and human-readable code. In particular, whenever there              The verifier automatically checks the resulting implemen-
exists a common action in all possible states in the given          tation and confirms that it satisfies the input specification.
location, the algorithm produces straight-line code with-              Note that in this example we have synthesized code

                                                                6
that correctly handles device errors. This was possible,                    dev.write_dat(v);
as our input device specification correctly captures device                 dev.write_cmd(1);}
failure modes (namely, transmission failure) and our OS               Finally, we run Termite on the resulting specifications and
specification describes how the driver must report errors             use the generator to automatically produce the following
to the OS (via the status argument of the completion                  implementation of the new irq method:
callback).
                                                                      void irq(){
   In principle, it is also possible to synthesize a driver im-
                                                                          if (os.success) {
plementation that handles device and OS failures not cap-                     os.send_ack(true);
tured in the specifications: since the synthesis tool knows               } else {
all possible valid environment behaviors, it can easily de-                   os.send_ack(false);
                                                                          };}
tect invalid behaviors and handle them gracefully. Au-
tomatic synthesis of such hardened device drivers is a                As before, we manually replace the if-condition in the first
promising direction of future research.                               line with
   The final step of the code generation process translates           if (dev.read_status())
the synthesized driver implementation to C. This is a triv-
                                                                         This example illustrates how Termite supports incre-
ial line-by-line translation. We expect this translation to
                                                                      mental changes to the driver by reusing previously syn-
become unnecessary in the future as our ongoing work on
                                                                      thesized code, while maintaining strong correctness guar-
the TSL syntax aims to make the synthesized subset of
                                                                      antees.
TSL a strict subset of C.
                                                                      Instrumenting synthesized code Termite does not auto-
Maintaining synthesized code Device driver develop-
                                                                      matically instrument synthesized code for debugging, log-
ment is not a one-off task: following the initial implemen-
                                                                      ging, accounting, etc. However, the user can add such in-
tation, drivers are routinely modified to implement addi-
                                                                      strumentation manually. Termite interprets such code as
tional functionality, adapt to the changing OS interface or
                                                                      no-ops and, as with any manual code, never makes any
support new device features.
                                                                      modifications to it.
   The user-guided code generation method naturally sup-
ports such incremental maintenance. A typical main-
tenance task proceeds in three steps. First, the devel-
                                                                      4     Synthesis
oper amends device and OS models to reflect the new                     In this section we give a high-level overview of the Ter-
or changed functionality. Second, they add new methods                mite synthesis algorithm. We refer the reader to the ac-
to the previously synthesized driver, if necessary, and re-           companying publication [30] for a detailed description.
place existing driver code that is expected to change with a
controllable placeholder. Finally, the user runs Termite to           4.1    Driver synthesis as a game
synthesize code for all controllable placeholders. Termite            We formalize the driver synthesis problem as a two-player
treats all existing driver code as part of the uncontrollable         game [29] between the driver and its environment. The
environment. Hence, if some of the old code is incorrect              game is played over a finite automaton that represents all
in the context of the new specifications, this will lead to a         possible states and behaviors of the system. Transitions
synthesis failure, and counterexample-based debugging is              of the automaton are classified into controllable transi-
used to identify the faulty code, as described in Section 5.          tions triggered by the driver and uncontrollable transitions
   As an example, we synthesize a new version of the                  triggered by the device or OS. A winning strategy for the
driver for our running example assuming a more advanced               driver in the game corresponds to a correct driver imple-
version of the serial controller device that uses interrupts          mentation. If, on the other hand, a winning strategy does
to notify the driver on completion of a data transfer. The            not exist, this means that there exists no specification-
new device model is obtained by uncommenting line 23                  conforming driver implementation.
of the device model in Figure 3, which invokes the inter-                Two-player games naturally capture the essence of the
rupt handler method of the driver after each transfer. The            driver synthesis problem: the driver must enforce a cer-
driver template is extended with the irq method (line 63).            tain subset of system behaviors while having only partial
We use the previously synthesized implementation of the               control over the system.
send method, but manually remove the last two lines,                     Figure 4 illustrates the concept using a trivial game au-
which implement polling, as we want the new implemen-                 tomaton that models the core of our running example.
tation to use interrupts instead:                                     Controllable and uncontrollable transitions of the automa-
void send(uint8 v){                                                   ton are shown with solid and dashed arrows respectively.

                                                                  7
send_ack
                                                                        π(s) are winning moves in s. The game G is winning for
                                    s3
                    write_data
                                          write_cmd                     the driver if all states in I are winning. The most general
                                                                        winning strategy maps every winning state s to a set of all
             G           s2                  s5                s6
                 send                               evt_send            winning moves in s, and all other states to an empty set.
                   write_cmd              write_data                       In Termite we use game objectives of a particular form,
                                   s4                   E
                                         evt_send                       called generalised reactivity-1 (GR-1) objectives [22].
                                                                        Such an objective consists of a finite set {B1 , ...Bn },
            Figure 4: A simple two-player game.                         Bi ⊆ S of goal sets and a finite set {F1 , ...Fk }, Fi ⊆ S of
                                                                        fair sets. A winning strategy for the driver must make sure
The goal of the driver in the game is to infinitely often visit
                                                                        that the game infinitely often visits each of the goal sets,
the initial state, labelled G, which represents the situation
                                                                        provided that the environment guarantees that the game
when the driver does not have any outstanding requests.
                                                                        does not get stuck in a fair set forever.
After getting a send request from the OS, the driver must
                                                                           Intuitively, a goal set represents a constraint on the
write data and command registers to start the data transfer.
                                                                        driver behavior, requiring the driver to force the game into
Writing the command register first may trigger a hardware
                                                                        the goal infinitely often, while a fair set represents a con-
send event before the driver has a chance to write the data
                                                                        straint on the environment, preventing it from staying in
register. As a result, wrong data value gets sent, taking
                                                                        certain states forever. The game in Figure 4 has a single
the game into an error state E. Hence, state s4 is losing
                                                                        goal set B1 = {g} and a single fair set F1 = {s4 , s5 }, i.e.,
for the driver. To avoid this state, the correct strategy for
                                                                        the driver must acknowledge each send request from the
the driver is to play write data in state s2 , followed by
                                                                        OS, provided that the environment eventually performs
write cmd. In s5 the driver must remain idle until the
                                                                        the evt send action after it has been enabled.
environment executes the evt send transition.
Games and strategies Formally, a two-player game                        4.2    TSL compiler
G = hS, I, Lc , Lu , δc , δu , Φi consists of a set of states           In order to compute the most general driver strategy as a
S, a subset of initial states I ⊆ S, sets of controllable and           solution of a two-player game, we must first convert input
uncontrollable actions Lc and Lu , controllable transition              TSL specifications into a game automaton. This conver-
relation δc ⊆ S×Lc ×S, uncontrollable transition relation               sion is performed by the TSL compiler.
δu ⊆ S × Lu × S, and a game objective Φ ⊆ S ω (where                       Real driver specifications have large state spaces, which
S ω represents the set of infinite sequences of states in S).           cannot be feasibly represented by explicitly enumerating
   The game proceeds in rounds, starting from an ini-                   states, as in Figure 2. Therefore, in Termite we repre-
tial state. In each round, in state s, both players select              sent games symbolically. The state space of the game is
actions lc and lu available to them in s, and the game                  defined in terms of a finite set of state variables X, with
transitions non-deterministically to one of the states in               each state s ∈ S representing a valuation of variables in
δc (s, lc ) ∪ δu (s, lu ). Intuitively, the system scheduler            X. The TSL compiler introduces a state variable for each
chooses the player to make a move at each round. The                    TSL variable declared in one of the input templates. In
scheduler can be thought of as part of the uncontrollable               addition, auxiliary state variables are introduced to model
environment. Note that this is different from turn-based                the current control location of each TSL process.
games like chess, where players strictly alternate in mak-                 We model controllable and uncontrollable actions as
ing moves. In the example in Figure 4, the driver can                   valuations of action variables Yc and Yu . Transition rela-
avoid the error state by choosing the write dat action in               tions δc and δu are represented symbolically as formulas
state s4 ; however the environment can override this choice             over state variables X, action variables Yc and Yu , and
by playing evt send.                                                    next-state variables X 0 .
   The infinite sequence of states (s0 , s1 , ...) ∈ S ω vis-              The TSL compiler splits the input specification
ited by the game is called a run. A strategy for the driver             into controllable and uncontrollable parts and trans-
player is a function π : S → 2Lc that maps each state of                lates them into controllable and uncontrollable transi-
the game into a set of actions to play in this state. The               tion relations respectively. The controllable part is
strategy determines a set Outcomes(I, π) ⊆ S ω of all                   comprised of controllable methods that can be in-
possible runs generated by the driver choosing one of the               voked by the driver. The controllable transition re-
actions in π(s) in every state s in the run.                            lation δc is computed by rewriting controllable meth-
   Given a state s and a strategy π such that                           ods in the variable update form. Consider, for ex-
Outcomes({s}, π) ⊆ Φ, we say that s is a winning state                  ample, variable reg dat declared in line 2 in Fig-
for the driver, π is a winning strategy in s, and actions in            ure 3. This variable is only modified by the write dat

                                                                    8
method in line 4. The corresponding fragment of the               Algorithm 1 Computing the set of winning states
controllable transition relation in the variable update             function R EACH(B)
form is reg dat0 := (tag = write dat) ? v : reg dat,                   Y ←∅
                                                                       loop
where reg dat0 is the next-state variable representing                     Y 0 ← CP re(Y ∪ B)
the value of reg dat after the transition, and tag and                     if Y 0 = Y return Y
v are controllable action variables, where tag models                      Y ←Y0
the method being invoked, and v is the argument of the
                                                                    function W INNING S ET({B1 , ..., Bn })
method.                                                                Z←S
   The uncontrollable part of the specification is com-                loop
                                                                           Z 0 ← i=1..n R EACH(Z ∩ Bi )
                                                                                 T
prised of TSL processes, which model device and OS
                                                                               0
                                                                           if Z = Z return Z
behavior. We syntactically decompose each process
                                                                           Z ← Z0
into atomic transitions. Recall that a process executes
atomically until reaching a wait statement or a con-                 The algorithm is based on exhaustive exploration of the
trollable placeholder. Consider the ptx process in                state space of the game. Given a goal set B, we first de-
line 13 in Figure 3. The process is initially paused in           termine the set of states from which the driver can force
the wait statement. It is scheduled to run when the wait          the game into B in one step, called the controllable pre-
condition holds. It executes the statements in lines 16–22        decessor of B. The controllable predecessor consists of
atomically and stops again in line 15. As part of this            all states s that satisfy both of the following conditions:
atomic transition, the process sets the reg cmd variable
to 0 (line 22). This is the only uncontrollable transition         1. All uncontrollable transitions available in s lead to
that modifies this variable, hence the uncontrollable                 some state in B. Hence, if the scheduler chooses to
update function for this variable is defined as follows:              execute an uncontrollable transition, it is guaranteed
reg cmd0 := (reg cmd = 1 ∧ pid = ptx) ? 0 : reg cmd,                  to take the game to B.
where pid is an uncontrollable action variable that mod-           2. There exists at least one winning controllable tran-
els the scheduler’s choice of a process to run, and the               sition from s to B or s belongs to a fair region. In
reg cmd = 1 conjunct corresponds to the wait condition                the former case, the driver must perform the winning
in line 15.                                                           transition; in the latter case it must remain idle wait-
   Finally, we need to generate the game objective Φ. In a            ing for an uncontrollable transition, which is guaran-
symbolic representation of the game, goal and fair sets are           teed to occur due to fairness.
specified as conditions over state variables that hold for
each state in the set. The TSL compiler outputs a goal set           Having computed the controllable predecessor of B, we
Bi for each goal declared in the input specification and a        apply the controllable predecessor operator again to the
fair set Fi for each wait statement. The latter guarantees        resulting set, thus obtaining the set of states from which
that every runnable process gets scheduled eventually.            the driver can force the game into the goal within two
   In addition to goal conditions, a TSL specification also       steps. We repeat until no new states can be discovered,
contains assertions, which must never be violated. We             at which point we have found all states from which the
model assertions using an auxiliary boolean state variable        driver can force the game into the goal in a finite number
ε, which is set to true whenever an assertion is violated         of rounds. This computation is performed by the R EACH
and remains true forever after. We add an extra constraint        function shown in Algorithm 1.
ε = f alse to each accepting set Bi . An assertion viola-            Recall that a GR-1 game can have multiple goal re-
tion permanently takes the game out of Bi , and therefore         gions, and in order to win the game the driver must visit
can not occur in any winning run of the game.                     each goal region Bi infinitely often. T Using the R EACH
                                                                  function, we compute the set Z = i R EACH(Bi ), from
4.3   Solving the game                                            which any of the goalsT can be reached at least once. Next,
The Termite game solver takes a game automaton pro-               we compute Z 0 = i R EACH(Z ∩ Bi ). It is easy to see
duced by the TSL compiler, determines whether all initial         that Z 0 contains all states from which any of the goals can
states of the system are winning and, if so, computes the         be reached twice. Furthermore, by construction, Z 0 ⊆ Z.
most general winning strategy for the game. A successful          By continuing the last computation until a fixed point is
approach to solving two-player games with GR-1 objec-             reached, we obtain all winning states of the game, as
tives was proposed by Piterman et al. [22]. We give an            shown in function W INNING S ET (Algorithm 1).
overview of their algorithm and briefly explain how we               The algorithm presented above is polynomial in the size
extend it to address the scalability bottleneck.                  of the game automaton. We have developed a highly opti-

                                                              9
mized implementation of the algorithm, which uses sym-              In order to detect and fix the defect in an input specifi-
bolic data structures [3] to compactly represent large sets      cation, the driver developer relies on their understanding
of states and transitions. Nevertheless, when applying it to     of the OS and device logic. The role of the counterexam-
games arising in driver synthesis, we hit a computational        ple strategy is to guide the developer towards the defect.
bottleneck due to a state explosion.                             To automate this process, we developed a powerful visual
   We overcome this bottleneck by using abstraction to           debugging tool that allows the user to interactively sim-
reduce the dimensionality of the problem. The partic-            ulate intended driver behavior and observe environment
ular form of abstraction used by Termite is predicate            responses to it. The user plays the game on behalf of the
abstraction [12], where concrete state variables of the          driver, while the tool responds on behalf of the environ-
game are replaced with boolean predicates over the orig-         ment, according to the counterexample strategy.
inal variables. Abstraction is adaptively refined by in-            In a typical debugging session, the debugger, following
troducing new predicates that capture important rela-            the counterexample strategy, generates a sequence of re-
tions among concrete variables. The predicate-based              quests that are guaranteed to win against the driver. The
abstraction-refinement algorithm for games is one of the         user plays against these requests by specifying device
key technical contributions of Termite. It is described in       commands that, they believe, represent a correct way to
detail in an accompanying paper [30].                            handle the request. Since this sequence of requests can-
                                                                 not be handled correctly given the current input specifi-
4.4    Verification as a special case of synthesis               cation, at some point in the game the user runs into an
Consider the situation where not only the OS and the de-         unexpected behavior of one of the players, e.g., one of
vice, but also the driver behavior is fully specified, so that   user-provided commands does not change the state of the
the synthesizer does not have any freedom to pick driver         device as expected or the environment performs an uncon-
actions. If the resulting game is winning for the driver,        trollable transition that violates an assertion. Based on this
i.e., every possible run of the game satisfies the objective,    information, the user can revise the faulty specification.
then the provided driver implementation is correct. Thus,           At every step of the interactive debugging session, the
verification can be seen as a special case of the synthesis      debugger either chooses a spoiling uncontrollable action
problem where all transitions in the system are uncontrol-       based on the counterexample strategy or, if the system
lable. Hence, our game solving algorithm doubles as a            is inside a controllable placeholder, allows the user to
driver verification algorithm. Termite also supports hy-         choose a controllable action to execute on behalf of the
brid scenarios: given a partially implemented driver with        driver. In the former case the spoiling uncontrollable ac-
placeholders for synthesized code, it determines whether         tion corresponds to a transition in one of the TSL pro-
the given partial implementation can be extended to a            cesses. The user can explore this transition by stepping
complete one and, if so, fills out the placeholders in the       through it, exactly as they would in a conventional debug-
user-guided fashion.                                             ger. In the latter case, the user provides the action that
                                                                 they would like to perform by typing and executing corre-
5     Debugging with counterexamples                             sponding code statements.
                                                                    The tool supports a number of features aimed to make
   An important practical issue in game-based synthesis is
                                                                 the debugging process as simple as possible for the user.
the complexity of diagnosing synthesis failures due to de-
                                                                 We mention two of them here. First, the debugger interac-
fects in the input specifications. In the event that Termite
                                                                 tively prompts actions available to the driver at each step.
fails to solve the game, the user needs to trace the failure
                                                                 Second, the debugger keeps the entire history of the game
back to the specification defect. However, the failure does
                                                                 and allows the user to go back to one of previously ex-
not carry any information about the defect, which makes
                                                                 plored states and try a different behavior from there.
the problem harder to resolve.
   In Termite we propose a new approach to troubleshoot-
ing synthesis failures based on the use of counterexample
                                                                 6    Limitations of Termite
strategies. A counterexample strategy is a strategy on be-         In Section 3, we described one limitation of Termite,
half of the environment that prevents the driver from win-       namely the lack of support for grey-box synthesis. In this
ning the game. It is obtained by solving the dual game,          section we discuss other limitations, which, we hope, will
where, in order to win, the environment must permanently         help define the agenda for continuing research in driver
force the game out of one of the goal regions. A winning         synthesis.
strategy in the dual game is guaranteed to exist whenever          Most importantly, Termite does not currently support
solving of the primary game fails.                               automatic synthesis of direct memory access (DMA)

                                                             10
management code. Many modern devices transfer data                havior without having to explicitly reason about time. To
directly to and from main memory, where it is buffered            this end, Termite conservatively approximates timed oper-
in data structures such as circular buffers and linked lists.     ations by fairness constraints: it ignores the exact duration
These data structures can have very large or infinite state       of each device operation, but keeps the knowledge that
spaces and cannot be easily modeled within the finite state       the operation will complete eventually, and synthesizes a
machine-based framework of Termite. Efficient synthesis           driver that waits for the completion. Termite is also able
for DMA requires enhancing the synthesis algorithm to             to handle time-out conditions, modeled as external events.
use more compact representation of DMA data structures,           However, at this time it is not capable of generating device
which is the focus of our ongoing research. At this time,         drivers for hard real-time systems, where the driver must
code for manipulating DMA data structures must be writ-           guarantee completion of I/O operations by a certain dead-
ten manually. This code is not interpreted or verified by         line.
Termite. For example, we use this approach to synthesize
a DMA-capable IDE disk driver (Section 7).                        7       Implementation and evaluation
   Device drivers in modern OSs contain a significant                The version of Termite presented here consists of
amount of boilerplate code that is not directly related to        30,000 lines of Haskell code. The estimated overall
the task of controlling the device. This includes binding         project effort is 10 person years. Termite is available in
the driver to I/O resources (memory mapped regions, in-           source and binary form from the project webpage1 .
terrupts, timers), registering the driver with various OS            We evaluate Termite by synthesizing drivers for eight
subsystems, allocating DMA memory regions, creating               I/O devices. Specifically, we synthesized drivers for a
sysfs entries, etc. While much of this functionality could        UVC-compliant USB webcam, the 16550 UART serial
be synthesized within the game-based framework, we do             controller, the DS12887 real-time clock, and the IDE disk
not believe that this is the correct approach. Previous re-       controller for Linux, as well as seL4 [16] drivers for I2C,
search has demonstrated that this boilerplate code can be         SPI, and UART controllers on the Samsung exynos 5
generated in a principled way from declarative specifica-         chipset2 and SPI controller on the STM32F10 chipset.
tions of the driver’s requirements and capabilities [26].         With the exception of the IDE disk, these devices are
This technique has lower computational complexity than            representative of peripherals found in a typical embed-
game solving and better captures the essence of the task.         ded platform, such as a smartphone. Our synthesized
A practical driver synthesis tool can combine game-based          drivers implement data transfer, configuration and error
synthesis of the core driver logic responsible for control-       handling. The main barrier to synthesizing drivers for
ling the device with declarative synthesis of boilerplate         more advanced devices, e.g., high-performance network
code. As a result, the current version of Termite assumes         controllers, is the current lack of support for synthesis of
this boilerplate code is written manually as a wrapper            DMA code in the current version of Termite.
around the synthesized driver.
                                                                  Modelling complexity Models of UART and DS12887
   Drivers execute in a concurrent OS environment and             devices were developed based on existing publicly avail-
must handle invocations from multiple threads, as well as         able device models [32, 20]. Models of other devices were
asynchronous hardware interrupts. We separate synthesis           derived from their vendor-provided documentation, fol-
for concurrency into a separate step. Drivers synthesized         lowing standard TLM modeling guidelines [31]. OS mod-
by Termite are correct assuming a sequential environment,         els for the relevant device classes were created based on
where driver entry points are invoked atomically. The re-         Linux kernel documentation and source code.
sulting sequential driver is then processed by a separate            Table 1 summarises the size, in lines of code, of device
tool that performs a sequence of transformations of the           and OS models in our case studies. Developing a com-
driver source code, which preserve the driver’s sequential        plete set of specifications for each driver took approxi-
behavior, while making the driver thread-safe. Such trans-        mately one week, of which only one to three days were
formations include adding locks around critical code sec-         spent building the models and the rest of the time was
tions, inserting memory barriers, and reordering instruc-         spent studying device and OS documentation. This effi-
tions to avoid race conditions. Concurrency synthesis is          ciency can be attributed to the choice of the right level of
still work in progress and is beyond the scope of this pa-
per. Our preliminary results are published in [5, 6].                 1 http://termite2.org
                                                                      2
                                                               At the time of writing, the exynos drivers have not yet been tested
  Termite does not explicitly support specification and due to    hardware availability issues; however we confirmed via manual
synthesis of timed behaviors. Instead, it uses a pragmatic inspection that they implement the same device control sequences as
approach that allows it to synthesize time-sensitive be- existing manually developed drivers.

                                                               11
input spec              driver                                             refine-   predi-     synt.      verif.
                                                                                       vars(bits)
                        OS      device   synthesized     native                                      ments     cates    time (s)   time (s)
         webcam         102      385         113          307           webcam        128 (125565)     47       192        215        794
         16450 UART     122      167          74          261           16450 UART      81 (407)       65       128        210        464
         exynos UART    128      252          37          166           exynos UART    80 (1185)       54       111        645        82
         STM SPI         73      244          24          64            STM SPI         68 (389)       29        63         67         31
         exynos SPI      88      239          40          183           exynos SPI      83 (933)       31        72         25         44
         exynos I2C     146      180          79          211           exynos I2C      65 (303)       21        56         45         96
         RT clock       118      252          84          183           RT clock        92 (810)       25        74         56        127
                                                a
         IDE            188      480         94           474           IDE            114 (1333)      42       105        285        778

  a Excluding 36 lines of manually written code that manipulates the
                                                                             Table 2: Performance of the Termite game solver.
DMA descriptor table.
                                                                       the input specifications in terms of the number of states
Table 1: Size (in lines of code) of input specifications and of
                                                                       variables and the total number of bits in these variables.
synthesized and equivalent manually written drivers.
                                                                       The third column shows the number of iterations of the
                                                                       abstraction refinement loop required to solve the game.
abstraction and modeling language. In particular, the use
                                                                       The next column shows the size of the abstract game at
of transaction-level device modeling abstracts away com-
                                                                       the final iteration, in terms of the number of predicates
plicated internal device machinery by focusing on high-
                                                                       in the abstract state space of the game. These results
level events relevant to driver synthesis, while the TSL
                                                                       demonstrate the dramatic reduction of the problem dimen-
language allows modeling the driver environment using
                                                                       sion achieved by our abstraction refinement method. The
standard programming techniques, as illustrated by our
                                                                       second-last column shows that the Termite game solver
running example.
                                                                       was able to find the most general winning strategy within
   Interestingly, we found the most error-prone step in de-            a few minutes in all case studies.
veloping specifications for driver synthesis to be defin-                 We compared the performance of the Termite game
ing correct relative ordering of OS-level and device-level             solver against a state-of-the-art abstraction refinement al-
events with the help of the virtual interface (Section 2.3).           gorithm for games [10] as well as against the standard
Naı̈ve specifications tend to be either too restrictive, lead-         symbolic algorithm for solving games without abstrac-
ing to synthesis failures, or too liberal, leading to incorrect        tion [22]. In all case studies, the Termite solver was the
synthesized drivers. As we gained more experience syn-                 only one to find a winning strategy within a two-hour
thesizing different types of drivers, we identified common             limit. We refer the reader to [30] for a more detailed per-
modeling patterns that help avoid errors in virtual inter-             formance analysis of the Termite synthesis algorithm.
face specifications.
                                                                          The final column of Table 2 shows the time that it took
   As a common example, most virtual interfaces contain                Termite to verify a complete driver. Recall that the Ter-
callbacks that signal a change to one of device configura-             mite synthesis algorithm doubles as a verification algo-
tion parameters, e.g., transfer speed, parity, etc. A naı̈ve           rithm and can be used to verify drivers written in TSL.
OS model may only allow such a callback to be triggered                We used complete synthesized drivers, containing a com-
when the OS has requested a change to the corresponding                bination of manual and automatically generated code, as
device setting. However, many devices only allow setting               inputs to Termite. We have been able to successfully ver-
multiple configuration parameters simultaneously, so that              ify all of our drivers. We also experimented with intro-
setting any individual parameter triggers multiple call-               ducing faults to synthesized drivers. Termite was able
backs, thus making the specification non-synthesizable.                to detect these faults and produce correct counterexample
The problem can be rectified by changing the device spec-              strategies. In most cases verification took longer than syn-
ification to only trigger callbacks if the new value of the            thesis. The reason for this is that Termite has not yet been
parameter is different from the old one; however this                  optimized for verification workloads. This is one area for
bloats the device model due to the extra checks. A better              future improvement.
solution, used in all our models, is to design the OS speci-
                                                                User-guided code generation and debugging We eval-
fication to allow configuration callbacks to be triggered at
                                                                uate the key contribution of this paper, namely the user-
any time, provided that the new value of the parameter is
                                                                guided debugging and code generation technique. Each
equal to the last value requested by the OS.
                                                                line of code in a Termite-generated driver originates from
Synthesis time Table 2 summarises the performance of one of three sources: it can be (1) synthesized automati-
the Termite game solver in our case studies. The second cally by the tool, (2) developed offline and given to Ter-
column of the table characterises the complexity of the mite as part of the driver template, or (3) added or modi-
two-player game constructed by the TSL compiler from fied by the user during an interactive code generation ses-

                                                                   12
You can also read