A Formal Semantic Description of VMK - The Functional Specification

0 downloads 0 Views 644KB Size Report
The Functional Specification. Ming-Yuan Zhu, Li-Meng Yin, Li-Jie Wang and Sheng-Lin Gui. CoreTek Systems, Inc. 1109 CEC Building. 6 South Zhongguancun ...
A Formal Semantic Description of VMK - The Functional Specification Ming-Yuan Zhu, Li-Meng Yin, Li-Jie Wang and Sheng-Lin Gui CoreTek Systems, Inc. 1109 CEC Building 6 South Zhongguancun Street Beijing 100086 People’s Republic of China E-Mail: [email protected]

Preface This work is a part of TRUSTIE Project and is supported in part by the HiTech Research and Development Program of China under the contract number 2007AA010304.

i

Contents I

Verification of Real-Time Operating Systems

2

1 Introduction 1.1 Common Criteria . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Software Specification . . . . . . . . . . . . . . . . . . . . . . . 1.3 Verification Technology . . . . . . . . . . . . . . . . . . . . . . 1.3.1 Model Checking . . . . . . . . . . . . . . . . . . . . . . 1.3.2 Theorem Proving . . . . . . . . . . . . . . . . . . . . . . 1.3.3 Verifying Kernels . . . . . . . . . . . . . . . . . . . . . . 1.4 Formal Verification of Microkernels . . . . . . . . . . . . . . . . 1.4.1 Formal Verification . . . . . . . . . . . . . . . . . . . . . 1.4.2 Monolithic and Microkernels . . . . . . . . . . . . . . . 1.4.3 Architectures . . . . . . . . . . . . . . . . . . . . . . . . 1.4.3.1 Monolithic Kernels . . . . . . . . . . . . . . . . 1.4.3.2 Microkernels . . . . . . . . . . . . . . . . . . . 1.4.3.3 Advantages and Disadvantages of Microkernels 1.4.3.4 Basic Services in Microkernels . . . . . . . . . 1.4.4 Services and Policies . . . . . . . . . . . . . . . . . . . . 1.4.4.1 Functional Specifications of Microkernels . . . 1.4.4.2 Access Control and Data Separation . . . . . . 1.4.4.3 Information Flow . . . . . . . . . . . . . . . . 1.4.4.4 Non-Interference . . . . . . . . . . . . . . . . . 1.4.4.5 Common Criteria . . . . . . . . . . . . . . . . 1.5 Sequential and Concurrent Programming . . . . . . . . . . . . 1.6 The Contribution of This Book . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . .

3 3 3 5 5 5 6 7 7 7 8 8 8 8 9 9 10 10 11 12 12 13 13

2 Type Theory and PowerEpsilon 2.1 PowerEpsilon . . . . . . . . . . . 2.2 Notations . . . . . . . . . . . . . 2.3 Lexicon . . . . . . . . . . . . . . 2.4 Syntax . . . . . . . . . . . . . . . 2.4.1 Variables . . . . . . . . . 2.4.2 Prop, Type(i), and Kind

. . . . . .

14 14 15 15 15 16 17

ii

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

CONTENTS

2.4.3 Π-Formulas . . . . . . . . . . . . . . . . . . . . 2.4.4 Σ-Formulas . . . . . . . . . . . . . . . . . . . . 2.4.5 λ-Abstractions . . . . . . . . . . . . . . . . . . 2.4.6 Implication-Formula . . . . . . . . . . . . . . . 2.4.7 Function Application . . . . . . . . . . . . . . . 2.4.8 Pair . . . . . . . . . . . . . . . . . . . . . . . . 2.4.9 Let-Expression . . . . . . . . . . . . . . . . . . 2.4.10 Lec-Formula . . . . . . . . . . . . . . . . . . . 2.5 Examples . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 Boolean . . . . . . . . . . . . . . . . . . . . . . 2.5.2 Natural Numbers . . . . . . . . . . . . . . . . . 2.5.3 List . . . . . . . . . . . . . . . . . . . . . . . . 2.6 Currying and Higher-Order Terms . . . . . . . . . . . 2.6.1 Higher-Order Functions . . . . . . . . . . . . . 2.6.2 Currying and Uncurrying . . . . . . . . . . . . 2.6.3 Generic Functions . . . . . . . . . . . . . . . . 2.7 Mathematical Logic in PowerEpsilon . . . . . . . . . . 2.7.1 Null Type . . . . . . . . . . . . . . . . . . . . . 2.7.2 Trivial Type . . . . . . . . . . . . . . . . . . . 2.7.3 Π-Type . . . . . . . . . . . . . . . . . . . . . . 2.7.4 Σ-Types . . . . . . . . . . . . . . . . . . . . . . 2.7.5 Product Types (×) . . . . . . . . . . . . . . . . 2.7.5.1 Product of Two Types P and Q . . . . 2.7.5.2 Product of Three Types U, V and W . 2.7.5.3 Product of Infinite Type Sequence . . 2.7.6 Sum Types (+) . . . . . . . . . . . . . . . . . . 2.7.6.1 Sum of Two Types U and V . . . . . . 2.7.6.2 Sum of Three Types U, V and W . . . . 2.7.6.3 Sum of Infinite Type Sequence . . . . 2.7.7 Subset Types . . . . . . . . . . . . . . . . . . . 2.7.8 Leibniz’s Equality . . . . . . . . . . . . . . . . 2.8 Transforming English to PowerEpsilon . . . . . . . . . 2.9 Propositions as Types and Proofs as Programs . . . . 2.10 Types, Sets and Domains . . . . . . . . . . . . . . . . 2.10.1 The Problem of Recursively Defined Functions 2.10.2 The Problem of Recursively Defined Sets . . . 2.10.3 The Role of Scott’s Domain Theory . . . . . . 2.10.4 Types as Domains . . . . . . . . . . . . . . . . 2.10.5 Defining Domains . . . . . . . . . . . . . . . . 2.10.5.1 Standard Domains . . . . . . . . . . . 2.10.5.2 Finite Domains . . . . . . . . . . . . . 2.10.5.3 Domain Constructors . . . . . . . . . 2.10.5.4 Domain Equations . . . . . . . . . . . 2.10.6 Functions . . . . . . . . . . . . . . . . . . . . .

iii

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17 17 17 18 18 18 18 18 19 19 20 23 28 28 28 30 30 30 31 31 32 32 32 33 34 35 35 35 36 37 38 39 40 41 42 42 43 43 44 44 44 45 45 46

CONTENTS

3 The Separation Kernel 3.1 Basic Architecture . . . . . . . . . . . . . . . . 3.1.1 Basic Definition . . . . . . . . . . . . . . 3.1.2 Temporal Separation . . . . . . . . . . . 3.1.3 Spatial Separation . . . . . . . . . . . . 3.1.4 The Round-Robin Scheme . . . . . . . . 3.1.5 Boundary of Kernel and User Processes 3.2 Extending the Architecture . . . . . . . . . . . 3.2.1 Trusted and Untrusted Software . . . . 3.2.2 Device Handling Code . . . . . . . . . . 3.3 Summary . . . . . . . . . . . . . . . . . . . . .

iv

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

47 47 47 48 48 48 49 49 49 50 50

4 The Programming Language C-VMK - Syntax 4.1 Expressions . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Identifiers and Other Lexical Entities . . . . 4.1.2 Type Definition of Expression . . . . . . . 4.1.3 Constructors of Expression . . . . . . . . . 4.1.4 Predicate Functions of Expression . . . . . 4.1.5 Projectors of Expression . . . . . . . . . . 4.1.6 Induction Rule for Expression . . . . . . . 4.1.7 Expression List . . . . . . . . . . . . . . . . 4.1.7.1 Type Definition of Expr list . . . 4.1.7.2 Constructors of Expr list . . . . 4.2 Declarations . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Array Declarations . . . . . . . . . . . . . . 4.2.2 Record Declarations . . . . . . . . . . . . . 4.2.3 Type Declarations . . . . . . . . . . . . . . 4.2.3.1 Type Definition of Type Decl . . . 4.2.3.2 Constructors of Type Decl . . . . 4.2.3.3 Predicate Functions of Type Decl 4.2.3.4 Projectors of Type Decl . . . . . . 4.2.4 Type Definitions . . . . . . . . . . . . . . . 4.2.4.1 Type Definition of Type Elem . . . 4.2.4.2 Constructors of Type Elem . . . . 4.2.4.3 Project Functions of Type Elem . 4.2.4.4 Predicate Functions of Type Elem 4.2.5 Type Definition of Declaration . . . . . . 4.2.6 Constructors of Declaration . . . . . . . . 4.2.7 Predicate Functions of Declaration . . . . 4.2.8 Projectors of Declaration . . . . . . . . . 4.2.9 Induction Rule for Declaration . . . . . . 4.3 Procedure Declarations . . . . . . . . . . . . . . . 4.3.1 Mode Definition . . . . . . . . . . . . . . . 4.3.1.1 Type Definition of Mode . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

51 51 51 51 52 52 52 53 53 53 53 54 54 54 55 55 55 55 56 56 56 56 57 57 57 57 58 58 58 59 59 59

. . . . . . . . . .

CONTENTS

4.4

4.5

v

4.3.1.2 Constructors of Mode . . . . . . . . . . . . 4.3.1.3 Call-By-Result . . . . . . . . . . . . . . . . 4.3.1.4 Call-By-Value and Result . . . . . . . . . . 4.3.1.5 Call-By-Variable (Call-By-Reference) . . . 4.3.1.6 Call-By-Value . . . . . . . . . . . . . . . . 4.3.1.7 Call-By-Constant . . . . . . . . . . . . . . 4.3.1.8 Call-By-Name . . . . . . . . . . . . . . . . 4.3.1.9 FORTRAN Based Call-By-Reference . . . 4.3.1.10 Call-By-Text . . . . . . . . . . . . . . . . . 4.3.1.11 Call-By-Denotation . . . . . . . . . . . . . 4.3.1.12 Predicate Functions of Mode . . . . . . . . 4.3.2 Formal Parameters . . . . . . . . . . . . . . . . . . . 4.3.2.1 Constructors of Form par . . . . . . . . . . 4.3.2.2 Projectors of Form par . . . . . . . . . . . 4.3.3 Formal Parameter List . . . . . . . . . . . . . . . . . 4.3.3.1 Type Definition of Form par list . . . . . 4.3.3.2 Constructors of Form par list . . . . . . . 4.3.3.3 Predicate Functions of Form par list . . . 4.3.3.4 Project Functions of Form par list . . . . 4.3.4 Type Definition of Proc . . . . . . . . . . . . . . . . 4.3.5 Constructors of Proc . . . . . . . . . . . . . . . . . . 4.3.6 Predicate Functions of Proc . . . . . . . . . . . . . . 4.3.7 Project Functions of Proc . . . . . . . . . . . . . . . Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.1 Type Definition of Statement . . . . . . . . . . . . . 4.4.2 Constructors of Statement . . . . . . . . . . . . . . 4.4.3 Predicate Functions of Statement . . . . . . . . . . 4.4.4 Projectors of Statement . . . . . . . . . . . . . . . . 4.4.5 System Service Calls for VM . . . . . . . . . . . . . 4.4.6 System Service Calls for TTS . . . . . . . . . . . . . 4.4.7 System Service Calls for Scheduling . . . . . . . . . 4.4.8 System Service Calls for Virtual Interrupt Handling 4.4.9 Induction Rule of Statement . . . . . . . . . . . . . Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5.1 Type Definition of Program . . . . . . . . . . . . . . 4.5.2 Constructor of Program . . . . . . . . . . . . . . . . 4.5.3 Project Function . . . . . . . . . . . . . . . . . . . .

5 The Environments and Continuations 5.1 The Environments . . . . . . . . . . . . . . . . 5.1.1 Denotable Values . . . . . . . . . . . . . 5.1.2 The Definition of Environment . . . . . 5.1.3 Constructors of Environment . . . . . . 5.1.4 Auxiliary Constructors of Environment

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

59 59 59 60 60 60 60 60 60 61 61 61 61 62 62 62 62 62 62 62 63 63 63 63 63 64 65 65 66 67 68 68 69 69 69 70 70

. . . . .

. . . . .

. . . . .

71 71 71 73 73 73

CONTENTS

5.2

5.3

vi

5.1.5 Predicate Functions of Environment 5.1.6 Selection Functions of Environment The Type Environments . . . . . . . . . . . 5.2.1 The Definition of KTypeEnv . . . . . 5.2.2 Constructors of KTypeEnv . . . . . . 5.2.3 Predicate Function of KTypeEnv . . . The Continuations . . . . . . . . . . . . . . 5.3.1 The Definition of VMKCont . . . . . . 5.3.2 Other Semantic Entities . . . . . . .

6 Manager of VMK 6.1 Interrupt Control Blocks of VMK . . . . 6.1.1 Type Definition of VMKIntCB . . 6.1.2 Constructor of VMKIntCB . . . . 6.1.3 Selectors of VMKIntCB . . . . . . 6.1.4 Modifiers of VMKIntCB . . . . . . 6.2 Health Manager . . . . . . . . . . . . . . 6.2.1 Health Management Type . . . . 6.2.2 Actions of Health Manager . . . 6.2.3 Exception Handling Contnuation 6.3 Manager of VMK . . . . . . . . . . . . . 6.3.1 Status of VMK . . . . . . . . . . 6.3.2 Definition of Priority VM Queue 6.3.3 Type Definition of VMKManager . 6.3.4 Constructor of VMKManager . . . 6.3.5 Selectors of VMKManager . . . . . 6.3.6 Modifiers of VMKManager . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

74 75 75 75 75 76 76 76 77

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . .

78 78 78 78 78 79 79 79 79 80 80 80 80 82 82 85 85

7 VM Control Blocks 7.1 Virtual Interrupt Control Blocks of VMs . 7.1.1 When Virtual Interrupt Delivered 7.1.2 Tick Interrupt Control Blocks . . . 7.1.3 Other Interrupt Control Blocks . . 7.2 Status of VMs . . . . . . . . . . . . . . . 7.3 VM Control Blocks . . . . . . . . . . . . . 7.3.1 Scheduling Type of VMs . . . . . . 7.3.2 VM Wakeup Type . . . . . . . . . 7.3.3 Other Utilities for VMs . . . . . . 7.3.4 Type Definition of VMCB . . . . . . 7.3.5 Constructor of VMCB . . . . . . . . 7.3.6 Selectors of VMCB . . . . . . . . . . 7.3.7 Modifiers of VMCB . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

87 87 87 88 88 89 90 90 90 91 91 91 94 94

CONTENTS

vii

8 TTS Control Blocks 8.1 TTS Nodes . . . . . . . . . . . . . 8.2 TTS Status Type . . . . . . . . . . 8.3 Tick Notify Type . . . . . . . . . . 8.4 TTS Control Blocks . . . . . . . . 8.4.1 Type Definition of TTSCB . 8.4.2 Constructor of TTSCB . . . . 8.4.3 Selectors of TTSCB . . . . . 8.4.4 Modifiers of TTSCB . . . . . 8.4.5 Other Operations on TTSCB 9 The 9.1 9.2 9.3

Configuration Management Configuration of VMK . . . . . Configuration of VMs . . . . . Configuration of TTS . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

96 96 96 97 98 98 98 98 99 99

of VMK 100 . . . . . . . . . . . . . . . . . . . 100 . . . . . . . . . . . . . . . . . . . 101 . . . . . . . . . . . . . . . . . . . 102

10 Semantics of Interrupt Handling and VM 10.1 Interrupting Sequential Programs . . . . . 10.2 Tick Interrupt Handling . . . . . . . . . . 10.2.1 Stream of Ticks . . . . . . . . . . . 10.2.2 Save Current Context in VMCB . . . 10.2.3 Schedule Next VM . . . . . . . . . 10.2.4 Switch to New VM . . . . . . . . . 10.2.5 An Interrupt-Driven Model . . . . 10.3 Interrupt Handling . . . . . . . . . . . . . 10.3.1 Interrupting Sequential Programs . 10.4 Exception Interrupt Handling . . . . . . . 10.5 Scheduler . . . . . . . . . . . . . . . . . . 10.5.1 Save Current Context . . . . . . . 10.5.2 Switch to New VM . . . . . . . . . 10.5.3 Scheduling Function . . . . . . . .

Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

103 103 103 105 105 105 105 106 107 107 108 109 110 110 111

11 Semantics of C-VMK 11.1 Semantics of Expressions . . . . . . . . 11.1.1 Auxiliary Functions . . . . . . 11.1.2 Semantic Function CONTENT . . 11.1.2.1 Informal Description . 11.1.3 Semantic Function UPDATE . . . 11.1.3.1 Informal Description . 11.1.4 Semantic Function REF . . . . . 11.1.4.1 Informal Description . 11.1.5 Semantic Function DEREF . . . 11.1.5.1 Informal Description . 11.1.6 Operations for Binop and Unop

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

113 113 113 114 114 114 114 114 114 115 115 115

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

CONTENTS

viii

11.1.7 Semantics for Expressions . . . . . . . . . . . . . . . . . . 115 11.2 Semantics of Declarations . . . . . . . . . . . . . . . . . . . . . . 120 11.2.1 Auxiliary Functions . . . . . . . . . . . . . . . . . . . . . 120 11.2.2 Semantics of Type Declarations . . . . . . . . . . . . . . . 121 11.2.3 Semantics of Declarations . . . . . . . . . . . . . . . . . . 122 11.2.3.1 Semantics of Record Types . . . . . . . . . . . . 122 11.2.3.2 Semantics of Array Types . . . . . . . . . . . . . 123 11.2.3.3 Semantics of Access Types . . . . . . . . . . . . 124 11.3 Semantics of Procedure and Function Declarations . . . . . . . . 128 11.3.1 Parameter Passing Mechanisms . . . . . . . . . . . . . . . 128 11.3.1.1 Call-By-Result . . . . . . . . . . . . . . . . . . . 128 11.3.1.2 Call-By-Value and Result . . . . . . . . . . . . . 129 11.3.1.3 Call-By-Reference . . . . . . . . . . . . . . . . . 129 11.3.1.4 Call-By-Variable . . . . . . . . . . . . . . . . . . 130 11.3.1.5 Call-By-Value . . . . . . . . . . . . . . . . . . . 130 11.3.1.6 Call-By-Constant . . . . . . . . . . . . . . . . . 130 11.3.1.7 Call-By-Name . . . . . . . . . . . . . . . . . . . 130 11.3.1.8 Call-By-Text . . . . . . . . . . . . . . . . . . . . 131 11.3.1.9 Call-By-Denotation . . . . . . . . . . . . . . . . 131 11.3.1.10 FORTRAN Call-By-Reference . . . . . . . . . . 131 11.3.1.11 Procedures as Parameters . . . . . . . . . . . . . 132 11.3.1.12 Functions as Parameters . . . . . . . . . . . . . 132 11.3.1.13 Formal and Actual Parameter Binding . . . . . 133 11.3.1.14 List of Formal and Actual Parameter Binding . 134 11.4 Semantics of Statements . . . . . . . . . . . . . . . . . . . . . . . 136 11.4.1 Auxiliary Functions . . . . . . . . . . . . . . . . . . . . . 136 11.4.2 Semantics of Statements . . . . . . . . . . . . . . . . . . . 138 11.4.3 Semantics for Jump . . . . . . . . . . . . . . . . . . . . . 146 11.5 Semantics of Programs . . . . . . . . . . . . . . . . . . . . . . . . 147 11.6 Hoare Logic Specification . . . . . . . . . . . . . . . . . . . . . . 148 11.6.1 Specifications in Hoare Logic . . . . . . . . . . . . . . . . 148 11.6.2 Termination and Total Correctness . . . . . . . . . . . . . 148 11.7 State Transition Specification . . . . . . . . . . . . . . . . . . . . 149 11.7.1 Specifications as State Transitions . . . . . . . . . . . . . 149 11.7.2 Termination and Deterministics . . . . . . . . . . . . . . . 149 11.8 Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 11.8.1 Strong Equivalence in Hoare Logic . . . . . . . . . . . . . 149 11.8.2 Strong Equivalence in State Transition System . . . . . . 150 11.8.3 Relationship Between StEquivHLSem and StEquivTranSem 150 11.8.3.1 From VMKCont to HLVMKCont . . . . . . . . . . . 150 11.8.3.2 StEquivHLSem Is Weaker Than StEquivTranSem 150 11.8.4 Weak Equivalence in State Transition System . . . . . . . 150

CONTENTS

ix

12 Semantics of Utility Functions 12.1 List of APIs . . . . . . . . . . . . . . . . . . . . 12.1.1 Utility Functions for VMs . . . . . . . . 12.1.2 Utility Functions in Hoare Logic . . . . 12.1.3 Constant Definitions . . . . . . . . . . . 12.1.4 Health Management Functions . . . . . 12.1.5 Functions on List of Locations . . . . . 12.2 Semantic Function ClearVM . . . . . . . . . . . 12.2.1 Clear Virtual Interrupt Control Block of 12.2.2 Clear Virtual Interrupt Control Blocks . 12.2.3 Clear VM . . . . . . . . . . . . . . . . . 12.3 Semantic Function ClearVMReady . . . . . . . . 12.4 Semantic Function SetVMReady . . . . . . . . . 12.5 Semantic Function ExactWaitedVM . . . . . . . 12.6 Semantic Function ClearVMWaiting . . . . . . 12.7 Semantic Function TickNotify . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . Tick . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

151 151 151 151 152 152 152 153 153 153 154 154 156 159 160 161

13 Semantics of APIs 13.1 List of APIs . . 13.2 Semantics of VM 13.3 Semantics of VM 13.4 Semantics of VM 13.5 Semantics of VM 13.6 Semantics of VM 13.7 Semantics of VM 13.8 Semantics of VM 13.9 Semantics of VM 13.10Semantics of VM

for VMs . . . . . . . GET ID . . GET NAME . GET STATUS HALT . . . . START . . . STOP . . . . SUSPEND . . RESUME . . RESET . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

168 168 168 169 169 170 173 174 175 176 177

14 Semantics of APIs for TTS 14.1 List of APIs . . . . . . . . . . . 14.2 Semantics of TTS INSTALL . . . 14.3 Semantics of TTS GET TTS ID . 14.4 Semantics of TTS GET TTS NAME 14.5 Semantics of TTS START . . . . 14.6 Semantics of TTS STOP . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

179 179 179 182 183 184 185

15 Semantics of APIs for Scheduler 15.1 List of APIs . . . . . . . . . . . 15.2 Semantics of VMK SCHEDULE . . 15.3 Semantics of SET VM READY . . 15.4 Semantics of CLEAR VM READY . 15.5 Semantics of EXACT VM WAIT . . 15.6 Semantics of CLEAR VM WAIT . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

186 186 186 186 187 187 187

. . . . . . . . . .

CONTENTS

x

15.7 Semantics of TICK NOTIFY . . . . . . . . . . . . . . . . . . . . . . 187 16 Semantics of APIs for Virtual Interrupt 16.1 List of APIs . . . . . . . . . . . . . . . . 16.2 Semantics of InitVTickInt . . . . . . . 16.3 Semantics of EnablePIC . . . . . . . . . 16.4 Semantics of DisablePIC . . . . . . . . 16.5 Semantics of SendServInt . . . . . . . . 16.6 Semantics of VAckException . . . . . . 16.7 Semantics of TriggerVInt . . . . . . . . 16.8 Semantics of DispatchInt . . . . . . . . 16.9 Semantics of GetVInt . . . . . . . . . .

Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

189 189 189 190 191 192 194 194 195 197

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

200 200 200 200 201 202 204 204 205

18 Semantics of APIs for Health Management 18.1 List of APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.2 Semantics of vmkDispatchHM . . . . . . . . . . . . . . . . . . . . 18.3 Semantics of vmkInformHM . . . . . . . . . . . . . . . . . . . . . .

208 208 208 209

17 Semantics of APIs for Configuration Management 17.1 List of APIs . . . . . . . . . . . . . . . . . . . . . . . . 17.2 Semantics of VMKInit . . . . . . . . . . . . . . . . . . 17.2.1 Intialization of VM Virtual Interrupt . . . . . . 17.2.1.1 Initialization of Priority Queue Array 17.2.2 Initialization of VMs . . . . . . . . . . . . . . . 17.2.3 Initialization of Idle VM . . . . . . . . . . . . . 17.2.4 Initialization of TTS . . . . . . . . . . . . . . . 17.2.5 Initialization of VMK . . . . . . . . . . . . . .

II

The Verification of VMK

. . . . . . . .

212

19 Separation-Kernel Properties of VMK 213 19.1 Definitions of Separation Kernel Properties . . . . . . . . . . . . 213 19.1.1 Well-Defined VMCB . . . . . . . . . . . . . . . . . . . . . 213 19.1.2 Well-Defined Addresses . . . . . . . . . . . . . . . . . . . 213 19.1.3 Uniqueness of VMK Manager Index . . . . . . . . . . . . 214 19.1.4 Uniqueness of VMCB Indexes . . . . . . . . . . . . . . . . 214 19.1.5 Space Separation Property . . . . . . . . . . . . . . . . . 215 19.1.6 Temporal Separation Property: Uniqueness of Running VM215 19.1.7 Uniqueness of VMKMagnager Configuration Table Index . . 215 19.1.8 Uniqueness of Idle VM Index . . . . . . . . . . . . . . . . 216 19.1.9 Uniqueness of VM Configuration Table Indexes . . . . . . 216 19.2 The Separation Kernel Theorem . . . . . . . . . . . . . . . . . . 216 19.2.1 The Uniqueness of Segment Index of VMK Manager . . . 216

CONTENTS

19.2.2 The Uniqueness of Segment Index of VMCBs . . 19.2.3 Uniqueness VMK Configuration Index Theorems 19.2.4 The Separation Kernel Theorem . . . . . . . . . 19.3 The Second Separation Kernel Theorem . . . . . . . . . 19.3.1 Well-Defined Continuation on State . . . . . . . 19.3.2 The Second Separation Kernel Theorem . . . . .

xi

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

216 217 217 219 219 220

20 Security Policies of VMK 20.1 Definition of Capability List in Meta-Language . . . . . . . . . . 20.1.1 Resource Access Mode . . . . . . . . . . . . . . . . . . . . 20.1.2 Subject Abstraction . . . . . . . . . . . . . . . . . . . . . 20.1.3 Partition Abstraction . . . . . . . . . . . . . . . . . . . . 20.1.4 Subject-Resource Flow . . . . . . . . . . . . . . . . . . . . 20.1.5 PA Set and SA Set . . . . . . . . . . . . . . . . . . . . . . 20.1.6 PA List and SA List . . . . . . . . . . . . . . . . . . . . . 20.1.7 Return Mode . . . . . . . . . . . . . . . . . . . . . . . . . 20.1.8 Rule for PA Set and PA List . . . . . . . . . . . . . . . . 20.1.9 Rules for LPA Set and LPA List . . . . . . . . . . . . . . 20.1.10 Security Checking . . . . . . . . . . . . . . . . . . . . . . 20.1.10.1 Checking List . . . . . . . . . . . . . . . . . . . 20.1.10.2 Checking of Well-Definedness of Flow List for Interrupt Service Routines . . . . . . . . . . . . 20.1.10.3 Trusted Flows . . . . . . . . . . . . . . . . . . . 20.1.10.4 Trusted Flow Lists . . . . . . . . . . . . . . . . . 20.2 Definition of Capability List in Object-Language . . . . . . . . . 20.2.1 Resource Access Mode in Object-Language . . . . . . . . 20.2.2 Subject-Resource Flow (Capability) in Object-Language . 20.2.3 Capability List in Object-Language . . . . . . . . . . . . 20.2.4 Rule for Capability List . . . . . . . . . . . . . . . . . . . 20.2.5 Security Checking . . . . . . . . . . . . . . . . . . . . . . 20.2.5.1 Checking List . . . . . . . . . . . . . . . . . . . 20.2.5.2 Checking Well-Definedness of Flow List for Interrupt Service Routines . . . . . . . . . . . . . 20.2.5.3 Trusted Flows . . . . . . . . . . . . . . . . . . . 20.2.5.4 Trusted Flow Lists . . . . . . . . . . . . . . . . . 20.3 Capability Checking of Interrupt Service Routines . . . . . . . . 20.3.1 Definition of Capability Checking . . . . . . . . . . . . . . 20.3.2 Functions for Capability Checking . . . . . . . . . . . . . 20.4 Soundness and Completeness of Capability Checking . . . . . . . 20.4.1 Soundness Theorem of Capability Checking for ISRs . . . 20.4.2 Completeness Theorem of Capability Checking for ISRs . 20.4.3 The Proof of CPIntCBFlowThm . . . . . . . . . . . . . . . 20.4.3.1 Lemmas CPIntCBFListLem . . . . . . . . . . . . 20.4.3.2 The Induction Rule on MList . . . . . . . . . . .

222 222 222 223 223 223 223 223 224 224 224 226 226 226 227 229 230 230 230 230 230 231 231 231 232 234 235 235 238 240 240 240 240 240 241

CONTENTS

xii

20.4.3.3 20.4.3.4 20.4.3.5 20.4.3.6 20.4.3.7 20.4.3.8

. . . . . .

241 241 242 245 246 246

21 The Verification of VMK System Service APIs 21.1 The Verification of VMK SCHEDULE . . . . . . . . . . . . . . . . . . 21.1.1 Requirement Specification of Scheduling . . . . . . . . . . 21.1.1.1 The Requirement Specification . . . . . . . . . . 21.1.1.2 Intentional Specification . . . . . . . . . . . . . . 21.1.1.3 Extensional Specification . . . . . . . . . . . . . 21.1.2 The Verification . . . . . . . . . . . . . . . . . . . . . . . 21.1.2.1 Rewriting Rule from Computational Statements to Predicate Statements . . . . . . . . . . . . . . 21.1.2.2 The Proof of VMKScheduleThm1 . . . . . . . . . 21.1.2.3 The Proof of VMKScheduleThm . . . . . . . . . . 21.1.2.4 Proof of VMKScheduleThm1 Deriving from of VMKScheduleThm . . . . . . . . . . . . . . . . . . 21.1.2.5 The Proof of VMKScheduleThm2 . . . . . . . . .

247 247 247 247 248 249 250

III

Conditional Proposition Selection Lemmas Lemma CondP2FTranLem1 and Proof . . . Lemma CondP2FTranLem2 and Proof . . . The Proof of CondP2FTranLem . . . . . . . The Proof of CPIntCBFListLem . . . . . . The Proof of CPIntCBFlowThm . . . . . . .

. . . . . .

. . . . . .

Epilogue

22 Related Works 22.1 KIT . . . . . . . . . . . . . . . . . . . . . . . . . 22.2 Formal Models of Operating System Kernels in Z 22.2.1 A Simple Kernel . . . . . . . . . . . . . . 22.2.2 A Swapping Kernel . . . . . . . . . . . . . 22.2.3 Messages Passing in the Swapping Kernel 22.2.4 Virtual Storage . . . . . . . . . . . . . . . 22.2.5 A Separation Kernel . . . . . . . . . . . .

250 250 252 253 253

254 . . . . . . . . and Object-Z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . .

255 256 258 258 258 259 259 259

23 Conclusions 260 23.1 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 23.2 Future Works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 23.2.1 Hardware Model . . . . . . . . . . . . . . . . . . . . . . . 261

List of Figures

xiii

List of Tables 1.1

Common Criteria Evaluation Levels . . . . . . . . . . . . . . . .

4

22.1 OS Verification Projects . . . . . . . . . . . . . . . . . . . . . . . 256

1

Part I

Verification of Real-Time Operating Systems

2

Chapter 1

Introduction 1.1

Common Criteria

The Common Criteria are a standard for software verification that is mutually recognized by a large number of countries. There are seven levels of assurance (EAL 1-7) in the standard and a number of so-called protection profiles that detail what exactly is being certified and for which application area. The standard is used for example by government agencies to specify software assurance requirements in requisitions and regulations. Fig 1.1 shows a table with the assurance levels on the left, and software artifacts on the top. From left to right, the software artifacts are: the software requirements, for example a security property, the functional specification, the high-level design of the system, the low-level design, and finally the implementation. The bottom row of the table compares this with software that is fully formally verified. The highest Common Criteria evaluation level requires a formal treatments of requirements, functional specification and high-level design. The low-level design may be treated semi-formally and correspondence between implementation and low-level design is usually affirmed in an informal way. To call a piece of software fully formally verified, the verification chain should reach at least down to the level of implementation.

1.2

Software Specification

For our purposes, the software specification process occurs in four distinct phases. • Functional Specification. First we develop the functional specification driven by a set of user requirements. This consists of the functional model and a set of operations that the user will employ to manipulate the operational model. Again, the sole purpose of this set of specifications is to 3

Introduction

Common Criteria EAL 1 EAL 2 EAL 3 EAL 4 EAL 5 EAL 6 EAL 7 Verified

4

Requirements Informal Informal Informal Informal Formal Formal Formal Formal

Functional Specification Informal Informal Informal Informal Semiformal Semiformal Formal Formal

HLD

LLD

Implementation

Informal Informal Informal Informal Semiformal Semiformal Formal Formal

Informal Informal Informal Informal Informal Semiformal Semiformal Formal

Informal Informal Informal Informal Informal Informal Informal Formal

Table 1.1: Common Criteria Evaluation Levels

define a virtual system that can be manipulated by the user by a set of very well-defined operations. The functional mode, together with the set of operations, defines what the new system is to do. • High-Level Design Specification. The next step in the software specification process is intimately bound to the software design process. During this phase we map the functional model onto a specific high-level design model. We solve the problem of how the functional model works within the confines of a new virtual architecture. This high-level design model is manipulated by a set of functionalities. The high-level design model, together with its set of functionalities, constitutes our high-level design specification. • Low-Level Design Specification. The third step in the software specification process is the decomposition of functionalities into specific program modules. This is the low-level design process. Each module receives data from a set of modules from which it can potentially receive execution control. Through an algorithm specified in the module design, this data is transformed according to the dictates of the algorithm and made available to the module that transferred control to the current module. At this stage, we are concerned with the specifics of each datum and the transformations made on that datum. • Implementation. The final step in the specification process is to select a programming language model that we can use to implement the lowlevel design. We will not be able to modify these models; we must simply choose the least bad model from a repertoire of simply awful and inefficient language models to use in our application.

Introduction

1.3

5

Verification Technology

At present there are two main verification techniques in use: model checking and theorem proving.

1.3.1

Model Checking

Model checking works on a model of the system that is typically reduced to what is relevant to the specific properties of interest. The model checker then exhaustively explores the models reachable state space to determine whether the properties hold. This approach is only feasible for systems with a moderatelysized state space, which implies dramatic simplification. As a consequence, model checking is unsuitable for establishing a kernel’s full compliance with its API. Instead it is typically used to establish very specific safety or liveness properties. Furthermore, the formalization step from system to model is quite large, commonly done manually and therefore error prone. Hence, model checking usually does not give guarantees about the actual system. Model checking has been applied to the OS layer and has shown utility here as a means of bug discovery in code involving concurrency. However, claims of implementation verification are disputable due to the manual abstraction step. Tools like SLAM can operate directly on the kernel source code and automatically find safe approximations of system behavior. However, they can only verify relatively simple properties, such as the correct sequencing of operations on a mutex necessary but not sufficient for correct system behavior.

1.3.2

Theorem Proving

The theorem proving approach involves describing the intended properties of the system and its model in a formal logic, and then deriving a mathematical proof showing that the model satisfies these properties. The size of the state space is not a problem, as mathematical proofs can deal with large or even infinite state spaces. This makes theorem proving applicable to more complex models and full functional correctness. Contrary to model checking, theorem proving is usually not an automatic procedure, but requires human interaction. While modern theorem provers remove some of the tedium from the proof process by providing rewriting, decision procedures, automated search tactics, etc, it is ultimately the user who guides the proof, provides the structure, or comes up with a suitably strong induction statement. While this is often seen as a drawback of theorem proving, we consider it its greatest strength: It ensures that verification does not only tell you that a system is correct, but also why it is correct. Proofs are developed interactively with this technique but can be checked automatically for validity once derived, making the size and complexity of the proof irrelevant to soundness.

Introduction

1.3.3

6

Verifying Kernels

What do the models and specifications look like in kernel verification? Clearly a kernel needs to implement its API, so the specification is typically a formalization of this API. This is created by a manual process with a potential for misstatement, as APIs tend to be specified informally or at best semi-formally using natural languages, and are typically incomplete and sometimes inconsistent. It is then desirable to utilize a formalism such that the correspondence between the informal and formal specification is relatively easy to see even for OS developers who are no experts in formal methods. The kernel model is ideally the kernel executing on the hardware. In reality it is preferable to take advantage of the abstraction provided by the programming language in which the kernel is implemented, so the model becomes the kernel’s source-level implementation. This introduces a reliance on the correctness of the compiler and linker (in addition to the hardware, boot-loader and firmware). Some criticisms are commonly voiced when considering OS verification. Is there any point if we have to rely on compiler and hardware correctness? With source-level verification, compiler and hardware correctness have become orthogonal issues - when we have the required formal semantics for the language and hardware, verification of these system components can be attempted independently to that of the OS. Both hardware and compiler verification are currently active areas of research. It should be noted that the gap between formal model and implementation will always exist, even in the presence of a verified processor, since real hardware is a physical realization of some model and its correct operation is beyond the scope of formal verification - one cannot prove the absence of manufacturing defects for example. The aim of OS verification is to significantly reduce the larger gap between user requirements and implementation and hence gain increased confidence in system correctness. Even if the kernel is verified, what has been gained when user-level applications such as file-systems are not? In the first scenario described in the introduction, the question is really that of what do we need to verify to be able to claim the trusted applications are correct. The kernel provides the basic abstraction over the underlying hardware necessary to enforce the boundary between trusted and un-trusted applications and allows the behavior of un-trusted applications to be abstracted away or ignored when verifying the trusted code. Trusted applications may also have some redeeming characteristics when it comes to verification - they should be relatively small in a well-designed TCB and may take advantage of higher-level languages. For a hypervisor no additional work remains after OS verification - if the correct resource management and isolation is provided at the OS level then there is no possibility of faulty or malicious code executing in one partition from influencing or knowing about another. As becomes clear from the discussion above, a wide variety of systems and architectures can be implemented with microkernels. One topic of discussion

Introduction

7

in the OS community is whether a microkernel should provide a hardware abstraction layer (HAL) and hide hardware details, or simply provide a set of mechanisms to control the hardware and export underlying complexities to user space. The verification projects surveyed in the next section take different views on this topic which influences what the formal models look like and what properties are being proved.

1.4

Formal Verification of Microkernels

This section introduces the subject of the verification projects in this report: operating system microkernels.

1.4.1

Formal Verification

Formal verification is about producing strict mathematical proofs of the correctness of a system. But what does this mean? From the formal-methods point of view, it means that a formal model of the system behaves in a manner that is consistent with a formal specification of the requirements. This leaves a significant semantic gap between the formal verification and the user’s view of correctness. The user (e.g. application programmer) views the system as “correct” if the behavior of its object code on the target hardware is consistent with the user’s interpretation of the (usually informally specified) API. Bridging this semantic gap is called formalization.

1.4.2

Monolithic and Microkernels

By definition, the kernel of an operating system is the part of the software that runs in the privileged mode of the hardware. This privileged mode typically distinguishes itself from normal user mode by additional machine instructions and by write access to hardware registers and devices that are invisible or readonly in user mode, for instance the memory management unit (MMU) of the processor. Microkernels try to minimize the amount of code that runs in the privileged mode. There are many kinds of such small OS kernels. For the purposes of this survey, we restrict ourselves to kernels such as Mach, L4, and VAMOS that do not rely on co-operation from user mode processes to implement their services. This usually implies that the kernel at least manages the MMU and runs only on hardware that provides such a unit. The MMU can be used to implement virtual memory. It provides translation from virtual to physical addresses and other management functions like memory access rights (read/write/execute). If operated correctly, it can be used to protect kernel memory and memory of different user applications from each other.

Introduction

1.4.3

8

Architectures

Kernels are classified into two categories: traditional monolithic kernels such as Windows and Linux and the microkernels. 1.4.3.1

Monolithic Kernels

In a monolithic kernel, device drivers, system services like the file system, and even parts of the graphical user interface are part of the kernel and run in privileged mode. 1.4.3.2

Microkernels

In the microkernel approach, only the microkernel itself runs in privileged mode. It exports sufficiently powerful mechanisms to run system services and even low-level device drivers with the same degree of protection that is afforded to applications. 1.4.3.3

Advantages and Disadvantages of Microkernels

The microkernel approach has several advantages for system design and reliability. In a monolithic kernel, even an unimportant part of the kernel, e.g. a graphics card driver on a network server, has full access to all memory and all kernel data structures. A fault in such a driver can be exploited to fully undermine the whole system, be it maliciously or by accident. This is not a theoretical threat. In a microkernel on the other hand, such a driver would run in its own protection domain. An exploit in the driver would compromise only memory of that driver and will only deny service to those parts of the system that rely on it. For the normal operation of a network server for instance, the graphics driver is irrelevant and could be safely terminated and restarted. The main disadvantage of the microkernel approach was famously brought forward by Linus Torvalds in 1992: Performance. Creating these protection domains, switching between them for execution, and passing messages across domain boundaries was considered expensive overhead. This overhead would be incurred at the innermost, lowest level and therefore accumulate rapidly and unacceptably for all OS services. Providing roughly equal services, the main selling point of operating systems is performance, and the years that followed seemed to prove Torvalds right. Monolithic OS kernels not only persevered, but rose in popularity. More recently, however, it has been shown that the performance of microkernels can be improved to minimize this overhead down to the order of magnitude of a C procedure call. As becomes clear from the discussion above, a wide variety of systems and architectures can be implemented with microkernels. One topic of discussion

Introduction

9

in the OS community is whether a microkernel should provide a hardware abstraction layer (HAL) and hide hardware details, or simply provide a set of mechanisms to control the hardware and export underlying complexities to user space. The verification projects surveyed in the next section take different views on this topic which influences what the formal models look like and what properties are being proved. 1.4.3.4

Basic Services in Microkernels

HAL or not, all microkernels used in these verification projects provide at least the following services: • Threads. Threads are an abstraction from the CPU, in effect allowing multiple programs to share a single CPU and provide the illusion of parallel execution. Typical operations on threads are starting and stopping execution, managing scheduling parameters or inspecting and possibly modifying the execution state of a thread. • IPC. IPC stands for inter process communication. This communication can be synchronous (communication partners have to rendezvous and be ready at the same time) or asynchronous (which usually involves some form of buffering or potential message loss). IPC is the central mechanism for transferring information across protection boundaries. • Virtual Memory. As mentioned above, protection domains are usually implemented using MMU hardware mechanisms. The kernel can either fully manage the MMU or just export sufficient mechanisms and resource arbitration to user space for implementing specific virtual memory policies there. In the latter case, the mechanism needs to be hardened against malicious use from user space. The typical implementation size of a microkernel is on the order of 10,000 lines of C code. The kernels differ in which additional services they provide and how access to shared resources such as interrupts and devices is managed. We will go into more detail where necessary in later sections when we look at specific verification projects.

1.4.4

Services and Policies

The usage scenarios and consequently the services and mechanisms the kernels are optimized to provide are as diverse as the microkernels themselves.Without attempting to create a full taxonomy of microkernels, we can divide them into kernels intended to support general-purpose operating systems and kernels that are optimized for smaller, embedded systems. The emphasis in the former case is often on abstraction and flexibility, such as the ability to dynamically reconfigure possibly hierarchical security policies and protection domains. The

Introduction

10

emphasis for embedded systems on the other hand is often on small memory footprint, short interrupt latencies, real-time capabilities and strong isolation guarantees. There are also systems that cater to both areas. The most complex end of the scale tend to be general-purpose kernels. The least complex end of the scale usually are specific-purpose embedded systems kernels. An example would be an extremely simple separation kernel whose only purpose is to multiplex hardware into a fixed number of partitions without any communication between them. These kernels would not even provide the IPC service mentioned above. Allowing controlled communication would be the next step up; allowing communication channels to be changed during runtime would further increase complexity. Allowing to adjust protection domains at runtime, or to create new protection domains at runtime increases complexity again, until we arrive at a fully dynamic system where communication, CPU, or memory access cannot only be changed dynamically, but the authority to do so can also be safely delegated to subsystems. 1.4.4.1

Functional Specifications of Microkernels

Functional specifications of microkernels usually consider at least two levels. • The first level concerns all the services the kernel provides, and their formalization. In order to be useful and general enough, this kind of specification needs to be fairly detailed and describe precisely which actions the kernel can perform and what their effect is. • The second, more abstract level concerns a specific purpose important for the kernel. For microkernels, these tend to be security and isolation properties. If the system can be reduced to its security aspects only, the specifications involved become much smaller, more abstract and easier to reason about. In the following, we concentrate on security-related properties that make interesting targets for formal verification. 1.4.4.2

Access Control and Data Separation

A classic target for verification is access control. One purpose of the kernel will be to arbitrate and restrict access to shared resources such as memory, devices and CPUs. There is a whole host of different abstract access control models that kernels can implement and that could be used as a top-level specification. Examples are capability modelsor the Bell-LaPadula model. In the first, access to a resource is granted only on presentation of a sufficiently authorised capability to that resource. A capability is basically a set of access rights together with a reference to a specific resource. Capability systems allow very fine-grained access control.

Introduction

11

Security-critical systems often require mandatory access control. This means that the kernel enforces a security policy via its access control method and does not rely on good behavior of processes and users not to circumvent the policy. Mandatory access control is used to implement system-wide security policies, for example stating that files with classification level top-secret have to remain protected. In contrast to that, discretionary access control allows users to make policy decisions themselves and for instance grant read access to everyone; an example is the standard Unix file system model. Access control can be used to achieve data separation between processes. Data separation means that no process is allowed access to memory of other processes, be it by accident or malicious intent. Because they are easy to formalize and already provide strong security implications, access control models are the most popular specification target for the verification projects surveyed below. 1.4.4.3

Information Flow

A stronger property is control of information flows. Formally, it is hard to define what information flow is, and there currently is still no universally accepted definition. Information flow properties are usually about secrecy: Process A stores a secret cryptographic key, and no other process should be able to infer what that key is. The information is not allowed to flow outside process A. Pure access control models are not strong enough to establish this property. They will prohibit direct access to the memory storing the key, and might also prohibit explicit communication channels, but there might be indirect means of inferring what the key is. One of the most challenging scenarios is collaboration between security levels to break system policies. For example, top-secret process A might be controlled by a spy in the organization, and unclassified process B might be the means to send the information outside. In this case, so-called covert channels need to be considered: process A could for instance use up its full time slice for transmitting a 1-bit and otherwise donate its remaining time slice. All B needs to observe is if more than its allocated time is available for computation. If yes, then A has transferred information. Of course, one can devise mechanisms against this specific attack, but the game becomes one of guessing the attack and guarding against it. Creating a new attack merely requires looking at the model and choosing something that is below its level of abstraction or that is otherwise not covered. The above example is a timing channel attack; it would not work against a kernel providing strict temporal separation, such that no thread can influence the scheduling and computing time available to other threads. Other attacks include observing CPU temperature, memory bus congestion, or cache misses. Known attacks against smart cards go as far as using radiation or heat to introduce memory faults into a computation, using an electron microscope to look at the chip in operation, etc. Modern high-security smart

Introduction

12

cards have physical tamper-proof devices against such attacks. It is unclear how far software alone can guard against them. 1.4.4.4

Non-Interference

More well-defined than general information flow is the property of noninterference. This property is able to capture indirect information flows in a model if the code for both sides is known. Given a secret process S and an attacker A, it requires one to prove that the behavior of A cannot depend on the actions of S, i.e. that S does not interfere with the behavior of A. It is possible to establish this property by looking at execution traces of the system: Given a trace where execution of both S and A occurs, one needs to show that the result in A is the same when all S actions are removed from the trace. Unfortunately, this property is not necessarily preserved by the proof technique of refinement which is the one most commonly used to relate an implementation to its model. This means that proving non-interference of the model only implies non-interference of the implementation when special care is taken in the implementation proof. The standard access control models do not have this problem. 1.4.4.5

Common Criteria

The Common Criteria have a protection profile geared towards separation kernels which are close to the services micro-kernels provide. The properties considered important for this class of kernels are: • Non-By-Passable, • Evaluatable, • Always Invoked, • Tamper Proof (NEAT). They are designed to be able to build systems with multiple independent levels of security (MILS), i.e. systems with components of different trust and assurance levels. • Non-By-Passable: In this context, non-by-passable means that the communication channels provided by the kernel are the only ones available to components and that there are no lower-level mechanisms that could be used for communication. • Evaluatable: Evaluatable means that the system must be designed such that an in-depth evaluation, including a fully formal evaluation if required, is possible. This restricts the size, complexity, and design of such systems.

Introduction

13

• Always Invoked: The term always invoked means that the access control methods of the kernel must be used every time a resource is accessed, not for instance just the first time a resource is requested. • Tamper Proof: Finally, tamper proof means that the access control system cannot be subverted, e.g. access rights be changed against the security policy by exploiting a loophole in the mechanism. These concepts, although intuitive, are not necessarily easy to formalize and prove directly. However, they can be established with reasonable effort by inspecting high-level formal models of the system. In this case it is important that the proof method used to relate the high-level model to code preserves these properties down to the code level. Because of their small size, the small number of services they provide, and their critical nature, micro-kernels offer a high-yield target for pervasive formal verification. The next section surveys the state of the art and the progress of current micro-kernel verification projects.

1.5

Sequential and Concurrent Programming

The approach adopted here is directly analogous to the use of a sequential programming paradigm to program a kernel: the whole program together with the operating system kernel can be viewed as a sequential program. The result might be parallel but the means of achieving it are sequential. The stream of interruption events is used to describe the interactions between the external events and software components and to prove behavioral equivalence between the interacting processes.

1.6

The Contribution of This Book

Our analysis will be conducted by a language driven approach. We start the work by design a concurrent and modular programming language called CVMK.

Chapter 2

Type Theory and PowerEpsilon 2.1

PowerEpsilon

PowerEpsilon, [ZW91, ZW92, ZW93b, ZW93a], is a strongly-typed polymorphic functional programming language based on Martin-L¨of’s type theory [ML84] and the Calculus of Constructions [CH88]. In PowerEpsilon, the concept of limit of type universe hierarchies (Kind) and a scheme for inductive defined types are introduced. The system can be used as both a programming language with a very rich set of data structures and a meta-language for formalizing constructive mathematics. The system has been implemented using the software development system AUTOSTAR constructed by author [Zhu89]. PowerEpsilon is a proof checker much similar to other mechanical proof checkers, such as LCF [GMW79] and Nuprl [Cea86], which are completely formal user-controlled systems. However, PowerEpsilon is more powerful than LCF and Nuprl, in which the equality and induction rules for arbitrary inductive types are definable. One of the main reasons for using type theory for programming is that it is a theory both for writing specifications and constructing programs. In type theory, a specification is expressed by a type and an element of that type is a program that satisfies the specification. We hope that this system will be useful for future development of programming environments, where programs will be developed consistently with logical propositions expressing in one unified formalism – types. PowerEpsilon, as we have claimed, can be used as both a programming language with a very rich set of data structures and a proof development system. PowerEpsilon can be classified into two categories: the core of the language – PowerEpsilon/Logic and a various of extension of PowerEpsilon

14

Type Theory and PowerEpsilon

15

– PowerEpsilon/Computation. In PowerEpsilon/Logic, functions cannot be defined with both dec and def constructs. In the other word, if a function is declared with dec construct, it cannot be defined with def construct again. However, in PowerEpsilon/Computation, functions can be defined with both dec and def constructs. It means that a restricted set of fixed-point operators are definable within PowerEpsilon.

2.2

Notations

For technical reasons the following notations are used in PowerEpsilon: • ! : for the universal quantifier ∀. • ? : for the existential quantifier ∃. • \ : for the λ-abstraction quantifier λ.

2.3

Lexicon

Since the limited usage of computer character set (ASCII codes only), we can use a variety of letters, both lowercase (a, b, . . . ), uppercase (A, B, . . . ), and even digits (0, 1, 2, . . . ). However, subscript and superscript letters, and Greek letters usually used in mathematics are not allowed. Comments are enclosed in between % and %.

2.4

Syntax

A program written in PowerEpsilon is a theory with an optional query part: program ::= theory {query} theory ::= theory identifier is {import} term decl list end; query ::= query import term list end; A theory is a syntactic unit in PowerEpsilon, which has no semantic meaning at all; the only role played is to syntactically wrap a set of closely related terms (propositions and proofs) into one package. The purpose of introduction of

Type Theory and PowerEpsilon

16

‘theory’ is to make it easy to manage the proof environment for PowerEpsilon. For instance, Nat is a theory that wraps all the propositions and functions for specifying properties of natural numbers. The query part describes the expressions to be evaluated. Terms in a theory or query may be dependent on other theories. This dependency is specified by a import clause. import ::= import ident list ident list ::= identifier {, identifier}∗ The main part of a theory is a sequence of term declarations. A term declaration is either a term specification or a term definition. A term specification specifies the type of a term. The specification of a term is optional. In the absence of such a specification, the term definition acts as the specification. There is a type inference system which can derive the specification of a term from its definition. If both a specification and a definition for a term are given, the term definition must conform to the term specification. term term term term

decl list ::= term decl {; term decl}∗ decl ::= term dec | term def dec ::= dec identifier : term def ::= def identifier = term

The dec-construct is used for variable declaration and the def-construct is used for variable definition. Similar to the programming languages such as Pascal and Ada, an identifier f must be declared before using it. The basic expressions of PowerEpsilon, called terms, are defined as follows: term ::= identifier | Prop | Type(natural) | Kind | (term) | ! (identifier : term {, identifier : term}∗ ) term | ?(identifier : term {, identifier : term}∗ ) term | \(identifier : term {, identifier : term}∗ ) term | [term -¿ term {-¿ term}∗ ] | @(term, term {, term}∗ ) | | let identifier = term in term | lec identifier : term in term

2.4.1

Variables

There are two kind of variables: identifiers and meta-variables. An identifier is a string of letters or digits beginning with a letter. A meta-variable is an

Type Theory and PowerEpsilon

17

identifier beginning with a character “*”. The meta-variables are specially used for defining inductively defined types.

2.4.2

Prop, Type(i), and Kind

An object T of type Prop defines a proposition. A proposition P has the type Type(0); Type(0) has the type Type(1); and so on. This forms a type hierarchy of the type system. The Kind can be used to define a generic type object as: def KT = \(T : Kind) [T -> Prop]; def KT0 = @(KT, Type(0));

2.4.3

Π-Formulas

The term !(x : A) B is usually called Π-formula which represents an universal qualified predicate. It can be read as ‘for every x of type A, the proposition B is true’. For instance, we may have the following predicate !(x : Bird) @(Can Fly, x), read as “for every bird x, x can fly”. The logical formulas in PowerEpsilon can be represented more abstractly in the sense that the type and logical formula can also be used as parameters inside of the formula, for instance, we may define the following logical formula: def Pi Form = !(T : Prop, P : [T -> Prop]) !(x : T) @(P, x), which can be instantiated as @(Pi Form, Bird, Can fly).

2.4.4

Σ-Formulas

The term ?(x : A) B is usually called Σ-formula which represents an existential qualified predicate. It can be read as ‘for some x of type A, the proposition B is true’. For instance, we may define the following predicate ?(x : Man) @(Is Married, x), read as “there is a number of men x, x is married”.

2.4.5

λ-Abstractions

Functions in PowerEpsilon is defined by λ-abstraction in forms of \(x : A) e, where x is the formal parameter and A is type of x and e is the body of function. There is a relationship between λ-abstraction and Π-formula. The type of function definition \(x : A) b is !(x : A) B, if within the context of x : A, we can infer that b : B.

Type Theory and PowerEpsilon

2.4.6

18

Implication-Formula

Computationally the formula [A -> B] specifies a function which maps type A to B. Logically the formula [A -> B] can be read as “A infers B”.

2.4.7

Function Application

The function application is represented as @(f, e), where the symbol @ may be read as “applying”. For instance, if we have a function f defined as def f = \(x : T) b; and we also have e of type T, we then will obtain @(f, e) = d, where d is obtained by substituting all of the occurrences of x by e.

2.4.8

Pair

The term represents a proof object of logical formula ?(x : A) B, if a has a type A, and b has a type D and B is obtained by replacing all occurrences of a in D by x. For example, if we have a : Man and b : @(Is Married, a), then we will be able to obtain : ?(x : Man) @(Is Married, x).

2.4.9

Let-Expression

The term of form let x = e in @(b, x) is a sugared PowerEpsilon expression which may be rewritten as @(\(x : A) @(b, x), e). Use of letconstruct can sometimes shorten expressions and highlight essential aspects of their structure. One can also use let-construct for ‘subsidiary’ functions, for example let f = \(x : Nat) @(TIMES, x, x) in @(ADD, @(f, ONE), @(f, TWO)); which means @(ADD, @(\(x : Nat) @(TIMES, x, x), ONE), @(\(x : Nat) @(TIMES, x, x), TWO));

2.4.10

Lec-Formula

The term of form lec x : T in @(S, x) is a formula declaring a local context inside of @(S, x). This construct can be used for defining a local recursive function. For example, we may define the following PowerEpsilon expression:

Type Theory and PowerEpsilon

19

\(e : A) lec f : [A -> A] in let f = \(x : A) @(f, x) in @(f, e); Since f is recursively defined in this expression, we must declare it before.

2.5

Examples

In this section we present some examples showing the expressive power of PowerEpsilon. Since PowerEpsilon is a purely symbolic language all of the mathematical objects can be built with it.

2.5.1

Boolean

In most programming languages, Boolean is a basic built-in data type for constructing more complicated data structures and functions. In PowerEpsilon, however, Boolean can be defined as follows: theory Bool is %-- Definition of Bool --% def Bool = !(T : Prop) [T -> T -> T]; %-- Function definitions for Bool --% %-- Constructors --% def TT = \(T : Prop, x : T, y : T) x; def FF = \(T : Prop, x : T, y : T) y; %-- Canonical functions --% def def def def

NOT = \(t : Bool) @(t, Bool, FF, TT); AND = \(t1 : Bool, t2 : Bool) @(t2, Bool, @(t1, Bool, TT, FF), FF); OR = \(t1 : Bool, t2 : Bool) @(t2, Bool, TT, @(t1, Bool, TT, FF)); IMPLY = \(t1 : Bool, t2 : Bool) @(OR, @(NOT, t1), t2);

def GIF_THEN_ELSE = \(U : Prop, t : Bool, u : U, v : U) @(t, U, u, v) end;

where TT and FF are the functions for Bool introduction and GIF THEN ELSE is the function for Bool elimination. The function @(GIF THEN ELSE, T, b, UU, VV) is a conditional function like if-then-else construct in most conven-

Type Theory and PowerEpsilon

20

tional programming languages which will select one of the two subcomponents UU and VV for execution, depending on the input Boolean value. For example, we will have @(GIF THEN ELSE, T, TT, UU, VV) −→ UU and @(GIF THEN ELSE, T, FF, UU, VV) −→ VV Other enumeration data types can be specified in a very similar way.

2.5.2

Natural Numbers

Let us present a definition for natural number and few functions over naturals. theory Nat is import Bool def BIF_THEN_ELSE

= @(GIF_THEN_ELSE, Bool);

%-- Definition of Nat --% def Nat = !(Ti : Prop) [Ti -> [Ti -> Ti] -> Ti]; dec ERR : [Nat -> Nat]; dec dec dec dec

PP EQUAL LESS MINUS

: : : :

[Nat [Nat [Nat [Nat

-> -> -> ->

Nat]; Nat -> Bool]; Nat -> Bool]; Nat -> Nat];

def NIF_THEN_ELSE = @(GIF_THEN_ELSE, Nat); %-- Function definitions for Nat --% %-- Constructors --% def OO = \(Ti : Prop, x : Ti, y : [Ti -> Ti]) x; def SS = \(t : Nat, Ti : Prop, x : Ti, y : [Ti -> Ti]) @(y, @(t, Ti, x, y)); %-- Canonical functions --% def def def def

IS_ZERO = \(n : Nat) @(n, Bool, TT, \(x : Bool) FF); ADD = \(n1 : Nat, n2 : Nat) @(n2, Nat, n1, SS); TIMES = \(n1 : Nat, n2 : Nat) @(n2, Nat, OO, @(ADD, n1)); EXP = \(n1 : Nat, n2 : Nat) @(n2, Nat, @(SS, OO), @(TIMES, n1));

Type Theory and PowerEpsilon

def T = \(x : Nat, y : Nat) x; def F = \(x : Nat, y : Nat) y; def PP = \(n : Nat) @(n, [[Nat -> Nat -> Nat] -> Nat], \(u : [Nat -> Nat -> Nat]) @(u, OO, OO), \(p : [[Nat -> Nat -> Nat] -> Nat], v : [Nat -> Nat -> Nat]) @(v, @(SS, @(p, T)), @(p, T)), F); def MINUS = \(n1 : Nat, n2 : Nat) @(NIF_THEN_ELSE, @(LESS, n1, n2), @(ERR, n1), @(NIF_THEN_ELSE, @(IS_ZERO, n2), n1, @(MINUS, @(PP, n1), @(PP, n2)))); def EQUAL = \(n1 : Nat, n2 : Nat) @(BIF_THEN_ELSE, @(IS_ZERO, n1), @(IS_ZERO, n2), @(BIF_THEN_ELSE, @(IS_ZERO, n2), FF, @(EQUAL, @(PP, n1), @(PP, n2)))); def LESS = \(n1 : Nat, n2 : Nat) @(BIF_THEN_ELSE, @(EQUAL, n1, n2), FF, @(BIF_THEN_ELSE, @(IS_ZERO, n1), TT, @(BIF_THEN_ELSE, @(IS_ZERO, n2), FF, @(LESS, @(PP, n1), @(PP, n2))))); dec REC : !(A : Prop) [Nat -> A -> [Nat -> A -> A] -> A];

21

Type Theory and PowerEpsilon

22

def REC = \(A : Prop) \(n : Nat, a : A, f : [Nat -> A -> A]) @(GIF_THEN_ELSE, A, @(IS_ZERO, n), a, @(f, n, @(REC, A, @(PP, n), a, f))) end;

where IS ZERO is a Boolean function to check whether a given natural number is zero or not. EQUAL is a Boolean function to check whether two given natural numbers are equal or not. PP is a predecessor function for any given natural numbers. We may see that natural numbers are polymorphic iterators. The addition function ADD is obtained by iterating successor SS; the multiplication function TIMES is obtained by iterating ADD; similarly, the exponentiation function EXP is obtained by iterating TIMES. The REC is a recursive operator. Iterating a natural on a functional type may produce non-primitive recursive functions; for example, we can get Ackermann’s function by the following definition: def ACK = \(n : Nat) @(n, [Nat -> Nat], SS, \(f : [Nat -> Nat]) \(m : Nat) @(m, Nat, m, f));

It is interesting to see the type Nat as expression the proposition “there are natural numbers”, which has the constructive proofs OO, @(SS, OO), @(SS, @(SS, OO)), . . . . The basic way of proving that a proposition holds for all natural numbers is by mathematical induction: from @(P, OO) and that @(P, n) implies @(P, @(SS, n)) we may conclude that @(P, n) holds for all natural numbers n. In order to be able to prove properties by induction on natural numbers in type theory, we introduce the formation Rec. From a computational point of view, Rec makes it possible to make definitions by primitive recursion. An inductive type over Nat can be defined as follows: theory Recnat is import Bool, Nat dec Rec : !(P : [Nat -> Prop]) [@(P, OO) -> !(u : Nat) [@(P, u) -> @(P, @(SS, u))] -> !(n : Nat) @(P, n)]; def Rec =

Type Theory and PowerEpsilon

23

\(P : [Nat -> Prop]) \(a : @(P, OO)) \(f : !(u : Nat) [@(P, u) -> @(P, @(SS, u))]) \(*n : Nat) @(GIF_THEN_ELSE, @(P, *n), @(IS_ZERO, *n), a, @(f, @(PP, *n), @(Rec, P, a, f, @(PP, *n)))); end;

2.5.3

List

For any type A, an important type built from it are lists of elements from A. The type is denoted in terms of PowerEpsilon @(List, A). All nonempty lists are built from the empty list which is denoted by NIL. If a is an element of A, then @(CONS, a, NIL) is a nonempty list. In general given a list t and an element h of A, @(CONS, h, t) is a list with h as its head and t as its tail. One important kind of construction arise from the inductive nature of lists. We can build an object incrementally from the elements of a list following the same pattern used to build the list. That is , a list starts from the empty list NIL. Suppose that corresponding to it we can specify some object, such as the natural number OO. Given a list t, we extend it by adjoining an element h to form @(CONS, h, t). In the same way, given a value associated with t, say its length v, we can build a value associated with @(CONS, h, t) incrementally, say by adding one to v, thereby associating @(SS, OO) to @(CONS, h, t). This process of associating a value with a list is sometimes called primitive recursion on lists or list recursion or list induction. The critical components in this definition are expression a for the value in the base case and an expression b for the value in the inductive base. We can use a linear format to present this definition: theory List is import Bool dec Uu : Prop; dec Aa : Prop; def BIF_THEN_ELSE

= @(GIF_THEN_ELSE, Bool);

dec EQUAL : [Uu -> Uu -> Bool]; %-- Definition of List --% def List = !(Ti : Prop) [Ti -> [Uu -> Ti -> Ti] -> Ti];

Type Theory and PowerEpsilon

dec ERR : Uu; dec ITM : Uu; dec LST : List; %-- Function declarations for List --% dec LISTREC : [List -> List -> [Uu -> List -> List -> List] -> List]; dec LEQUAL : [List -> List -> Bool]; def LIF_THEN_ELSE = @(GIF_THEN_ELSE, List); %-- Function definitions for List --% def NIL = \(Ti : Prop, x : Ti, y : [Uu -> Ti -> Ti]) x; def CONS = \(w : Uu, t : List) \(Ti : Prop, x : Ti, y : [Uu -> Ti -> Ti]) @(y, w, @(t, Ti, x, y)); def T = \(x : List, y : List) x; def F = \(x : List, y : List) y; def HEAD = \(s : List) @(s, Uu, ERR, \(u : Uu, v : Uu) u); def TAIL = \(n : List) @(n, [[List -> List -> List] -> List], \(u : [List -> List -> List]) @(u, NIL, NIL), \(e : Uu, p : [[List -> List -> List] -> List], v : [List -> List -> List]) @(v, @(CONS, e, @(p, T)), @(p, T)), F); def IS_EMPTY = \(s : List) @(s, Bool, TT, \(u : Uu, v : Bool) FF); def IS_IN_LIST = \(e : Uu, s : List) @(s, Bool, FF, \(u : Uu, v : Bool) @(BIF_THEN_ELSE, @(EQUAL, u, e), TT, v)); def EQUAL = \(s1 : List, s2 : List)

24

Type Theory and PowerEpsilon

25

@(BIF_THEN_ELSE, @(AND, @(IS_EMPTY, s1), @(IS_EMPTY, s2)), TT, @(BIF_THEN_ELSE, @(OR, @(IS_EMPTY, s1), @(IS_EMPTY, s2)), FF, @(s1, Bool, TT, \(u1 : Uu, v1 : Bool) @(BIF_THEN_ELSE, @(IS_IN_LIST, u1, s2), v1, FF)))); def CONCAT = \(s1 : List, s2 : List) @(s2, List, s1, \(u : Uu, v : List) @(CONS, u, v)); def LISTREC = \(l : List, a : List, b : [Uu -> List -> List -> List]) @(l, List, a, \(u : Uu, v : List) @(b, @(HEAD, l), @(TAIL, l), @(LISTREC, @(TAIL, l), a, b))); dec Rec : !(P : [List -> Prop]) [@(P, NIL) -> !(a : Uu, u : List) [@(P, u) -> @(P, @(CONS, a, u))] -> !(*n : List) @(P, *n)]; def Rec = \(P : [List -> Prop]) \(a : @(P, NIL)) \(f : !(x : Uu, u : List) [@(P, u) -> @(P, @(CONS, x, u))]) \(*n : List) @(GIF_THEN_ELSE, @(P, *n), @(LEQUAL, *n, NIL), a, @(f, @(HEAD, *n), @(TAIL, *n), @(Rec, P, a, f, @(TAIL, *n)))) end;

where given a list l, HEAD and TAIL are two functions to take its first and second components respectively; IS EMPTY is a Boolean function to check whether a given list l is empty or not; IS IN LIST is a Boolean function to check whether for a given list l and an element x, x is in l or not; CONCAT is a function concate-

Type Theory and PowerEpsilon

26

nate two lists l1 and l2 into one; LEQUAL is a Boolean function to check whether two given lists l1 and l2 are equal or not. LISTREC is a recursive function on List. Rec is an inductive type defined on Prop and Rec0 is an inductive type defined on Type(0) for List. Similarly, we may define Rec1, Rec2, . . . , and so on. The abstract data type List can be parameterized by taking the type of elements as a parameter. theory List is import Bool dec Aa : Prop; def BIF_THEN_ELSE = @(GIF_THEN_ELSE, Bool); %-- Definition of List --% def List = \(Uu : Prop) !(Ti : Prop) [Ti -> [Uu -> Ti -> Ti] -> Ti]; dec LERR : !(Uu : Prop) Uu; dec UEQUAL : !(Uu : Prop) [Uu -> Uu -> Bool]; dec HEAD : !(Uu : Prop) [@(List, Uu) -> Uu]; dec TAIL : !(Uu : Prop) [@(List, Uu) -> @(List, Uu)]; dec LISTREC : !(Uu : Prop) [@(List, Uu) -> Aa -> [Uu -> @(List, Uu) -> Aa -> Aa] -> Aa]; %-- Function definitions for List --% def NIL = \(Uu : Prop) \(Ti : Prop, x : Ti, y : [Uu -> Ti -> Ti]) x; def CONS = \(Uu : Prop) \(w : Uu, t : @(List, Uu)) \(Ti : Prop, x : Ti, y : [Uu -> Ti -> Ti]) @(y, w, @(t, Ti, x, y)); def HEAD = \(Uu : Prop, l : @(List, Uu)) @(l, Uu, @(LERR, Uu), \(u : Uu, v : Uu) u); def IS_EMPTY =

Type Theory and PowerEpsilon

\(Uu : Prop, s : @(List, Uu)) @(s, Bool, TT, \(u : Uu, v : Bool) FF); def IS_IN_LIST = \(Uu : Prop, e : Uu, s : @(List, Uu)) @(s, Bool, FF, \(u : Uu, v : Bool) @(BIF_THEN_ELSE, @(UEQUAL, Uu, u, e), TT, v)); def UEQUAL = \(Uu : Prop, s1 : @(List, Uu), s2 : @(List, Uu)) @(BIF_THEN_ELSE, @(AND, @(IS_EMPTY, Uu, s1), @(IS_EMPTY, Uu, s2)), TT, @(BIF_THEN_ELSE, @(OR, @(IS_EMPTY, Uu, s1), @(IS_EMPTY, Uu, s2)), FF, @(s1, Bool, TT, \(u1 : Uu, v1 : Bool) @(BIF_THEN_ELSE, @(IS_IN_LIST, Uu, u1, s2), v1, FF)))); def CONCAT = \(Uu : Prop, s1 : @(List, Uu), s2 : @(List, Uu)) @(s2, @(List, Uu), s1, \(u : Uu, v : @(List, Uu)) @(CONS, Uu, u, v)); def LISTREC = \(Uu : Prop, l : @(List, Uu), a : Aa, b : [Uu -> @(List, Uu) -> Aa -> Aa]) @(l, Aa, a, \(u : Uu, v : Aa) @(b, @(HEAD, Uu, l), @(TAIL, Uu, l), @(LISTREC, Uu, @(TAIL, Uu, l), a, b)))

27

Type Theory and PowerEpsilon

28

end;

2.6 2.6.1

Currying and Higher-Order Terms Higher-Order Functions

The function definition like \(x : A) \(y : B) x is a λ-expression which denotes a higher-order function. Higher-order functions are functions whose source and target contains functions. Thus \(x : A) \(y : B) x has a type of the form [A -> [B -> A]] and so the result of applying \(x : A) \(y : B) x to an argument, a say, is a member [B -> A] (\(y : B) x exact), i.e., a function. Another example of a higher-order function is dec TWICE : [[Nat -> Nat] -> [Nat -> Nat]]; defined by def TWICE = \(f : [Nat -> Nat]) \(x : Nat) @(f, @(f, x)); So @(TWICE, f) is a function which does f twice, for example, @(TWICE, \(n : Nat) @(ADD, n, ONE)) is a function which applies @(ADD, n, ONE) twice – i.e. adds 1 twice – i.e. adds 2. Higher-order functions are very useful and we shall frequently use them. Moreover, higher-order functions are perfectly ordinary and everything we say about functions in general applies to them also. The reason why we singled them out for discussion is because in many programming languages (for example Algol 60 and Pascal) ‘functions’ (as opposed to mathematical functions) are subject to various constraints. For example in neither Algol 60 nor Pascal can ‘functions’ return ‘functions’ as results (so TWICE could not be programmed). These constarints are to enable efficient implementations of the languages and do not reflect anything inherent in the concept of a function. Indeed other (less efficient) languages like LISP or POP-2 allow the unrestricted programming of higher-order ‘functions’.

2.6.2

Currying and Uncurrying

PowerEpsilon is a higher-order language – functions types are first class citizens and can be both passed as parameters and return as results. Function application is left-associative, so when we write @(f, x, y) it is passed as

Type Theory and PowerEpsilon

29

@(@(f, x), y), meaning that the result of applying f to x is a function, which is then applied to y. Functions of more than one argument which take them “one at a time” like f are called currying. The curring form of λ-expressions provides some flexibility which is important for writing easily understood programs. For example, \(x1 : A1 ) (\(x2 : A2 ) · · · (\(xn : An )M ) · · ·) can be written \(x1 : A1 ) \(x2 : A2 ) · · · \(xn : An )M, or further simplified to \(x1 : A1 , x2 : A2 , · · · , xn : An )M. !-terms and ?-terms are treated similarly. In addition, the following terms [A1 −> A2 −> · · · −> An−1 −> An ] @(A1 , A2 , A3 , ; · · · , An ) < A1 , A2 , · · · , An−1 , An > are respectively abbreviations for [A1 −> [A2 −> · · · [An−1 −> An ] · · · ; ]] @(· · · @(@(A1 , A2 ), A3 ), · · · , An ) < A1 , < A2 , · · · < An−1 , An > · · · >> Unlike function application which is left-associative, all of other constructs are right-associative. The dec and def constructs are sugared λ-expressions which can be decoded as an explicit on-line form of λ-expression. For instance, if a sequence of defconstructs are given as follows: def S = \(T : Prop) \(x : [T -> T -> T], y : [T -> T], z : T) @(x, z, @(y, z)); def K = \(T : Prop) \(x : T, y : T) x; def I = \(T : Prop) \(x : T) x; ...... These λ-expressions can be decoded as \(S : \(T : Prop)

Type Theory and PowerEpsilon

\(x : @(x, \(K : \(T : \(I : \(T : ......

30

[T -> T -> T], y : [T -> T], z : T) z, @(y, z))) Prop) \(x : T, y : T) x) Prop) \(x : T) x)

In PowerEpsilon, expressions and types have same forms of representation, for example, the term \(x : T) E can be interpreted as either an expression or a type depending on the role played by that term in context. Current version of PowerEpsilon has neither built-in functions nor built-in types. Everything must be constructed from bottom. The recursive functions can be defined using both dec and def constructs. For instance, we might define a factorial function FACT as dec FACT : [Nat -> Nat]; def FACT = \(n : Nat) @(GIF_THEN_ELSE, Nat, @(IS_ZERO, n), ONE, @(TIMES, n, @(FACT, @(PP, n))));

2.6.3

Generic Functions

Functions like GIF THEN ELSE which strictly speaking, are collections of functions, one for each domain of an appropriate type, are called generic. The actual functions which make up the collections of functions are called instances; thus @(GIF THEN ELSE, Bool) and @(GIF THEN ELSE, Nat), are instances of GIF THEN ELSE. The expressions which describe the types of the instances of generic functions are called generic types.

2.7 2.7.1

Mathematical Logic in PowerEpsilon Null Type

The Null type corresponding to logical value false can be defined in terms of PowerEpsilon as Null = !(A : TYPE) A. Since Null has no proof at all. theory Null is def Null = !(T : Prop) T

Type Theory and PowerEpsilon

31

end;

2.7.2

Trivial Type

Just as the false proposition ‘falsity’ (which should not be confused with the object FF of type Bool) was represented by the type Null, so the true proposition is represented by the one-element type Triv. Why one element? The intuition is that the proposition is valid for obvious reasons, so there is only one trivial proof TRIV of it. theory Trivial is def Triv = !(T : Prop) [T -> T]; def TRIV = \(T : Prop, t : T) t end;

2.7.3

Π-Type

Universal quantification, or general product, or Π-type, can be defined by a generalization of binary product Pi, where the Π-introduction, i.e. universal generalization, is proved by abstraction GEN and the Π-elimination is proved by instantiation INST, i.e. application. theory Pi is def Pi = \(T : Kind, Ai : T, Pp : [Ai -> Prop]) !(x : Ai) @(Pp, x); def GEN \(T : \(f : @(f,

= Kind, Ai : T, Pp : [Ai -> Prop], Bi : T) !(x : Ai) [Bi -> @(Pp, x)]) \(y : Bi, x : Ai) x, y);

def INST = \(T : Kind, Ai : T, Pp : [Ai -> Prop]) \(x : Ai, p : @(Pi, T, Ai, Pp)) @(p, x) end;

Type Theory and PowerEpsilon

2.7.4

32

Σ-Types

Existential quantification, or general sum, or Σ-type, can be defined by a generalization of the binary sum Sigma, where the Σ-introduction is proved by EXIST and the Σ-elimination is proved by WITNESS. theory Sigma is def Sigma = \(T : Kind, Ai : T, Pi : [Ai -> Prop]) !(Bi : T) [!(x : Ai) [@(Pi, x) -> Bi] -> Bi]; def EXIST = \(T : Kind, Ai : T, Pi : [Ai -> Prop]) \(x : Ai, y : @(Pi, x), Bi : T, q : !(x : Ai) [@(Pi, x) -> Bi]) @(q, x, y); def WITNESS = \(T : Kind, Ai : T, Pi : [Ai -> Prop], p : @(Sigma, T, Ai, Pi)) @(p, Ai, \(x : Ai, y : @(Pi, x)) x) end;

The Sigma type presented here is usually called weak sum. One of the major difference between the weak sum and the strong sum ?(x : A) B is that the elimination-rule for the weak sum is too weak and, in particular, there is no way to prove that the first component of a weak pair of type @(Sigma, Ai, Pi) satisfies the property Bi.

2.7.5

Product Types (×)

2.7.5.1

Product of Two Types P and Q

Given two types U and V, we can construct their Cartesian product – a type of which is a pair whose first component being U and whose second component being V. theory Product2 is def Product = \(Ui : Prop, Vi : Prop) !(Ti : Prop) [[Ui -> Vi -> Ti] -> Ti]; def PRODUCT = \(Ui : Prop, Vi : Prop) \(u : Ui, v : Vi, Ti : Prop, z : [Ui -> Vi -> Ti]) @(z, u, v); def PRO1 =

Type Theory and PowerEpsilon

33

\(Ui : Prop, Vi : Prop, t : @(Product, Ui, Vi)) @(t, Ui, \(x : Ui, y : Vi) x); def PRO2 = \(Ui : Prop, Vi : Prop, t : @(Product, Ui, Vi)) @(t, Vi, \(x : Ui, y : Vi) y); def SPLIT = \(Ui : Prop, Vi : Prop, Wi : Prop) \(t : @(Product, Ui, Vi), f : [Ui -> Vi -> Wi]) @(f, @(PRO1, Ui, Vi, t), @(PRO2, Ui, Vi, t)); def And = Product end;

@(Product, P, Q) is a method for proving any proposition A, provided one has a proof that A follows from P and Q. Note that the proof of productintroduction PRODUCT above is a pairing algorithm, the two projection functions PRO1 and PRO2 being the proofs of product-elimination on the left and on the right. 2.7.5.2

Product of Three Types U, V and W

Similarly we can define the intuitionistic product of three propositions P, Q and R which represent the conjunction of three propositions: theory Product3 is import Product2 def Product3 = \(Ui : Prop, Vi : Prop, Wi : Prop) @(Product, Ui, @(Product, Vi, Wi)); def PRODUCT3 = \(Ui : Prop, Vi : Prop, Wi : Prop) \(u : Ui, v : Vi, w : Wi) @(PRODUCT, Ui, @(Product, Vi, Wi), u, @(PRODUCT, Vi, Wi, v, w)); def PROJ1 = \(Ui : Prop, Vi : Prop, Wi : Prop) \(t : @(Product3, Ui, Vi, Wi)) @(PRO1, Ui, @(Product, Vi, Wi), t); def PROJ2 = \(Ui : Prop, Vi : Prop, Wi : Prop)

Type Theory and PowerEpsilon

34

\(t : @(Product3, Ui, Vi, Wi)) @(PRO1, Vi, Wi, @(PRO2, Ui, @(Product, Vi, Wi), t)); def PROJ3 = \(Ui : Prop, Vi : Prop, Wi : Prop) \(t : @(Product3, Ui, Vi, Wi)) @(PRO2, Vi, Wi, @(PRO2, Ui, @(Product, Vi, Wi), t)); def SPLIT3 = \(Ui : Prop, Vi \(Yi : Type(0), \(f : [Ui -> Vi @(f, @(PROJ1, Ui, @(PROJ2, Ui, @(PROJ3, Ui,

: Prop, Wi : Prop) t : @(Product3, Ui, Vi, Wi)) -> Wi -> Yi]) Vi, Wi, t), Vi, Wi, t), Vi, Wi, t))

end;

2.7.5.3

Product of Infinite Type Sequence

Consider the Cartesian product of an infinite sequence of types defined as a function A : [Nat -> Prop]. Now, the product type of A is @(GProduct, A), and @(GPRODUCT, A, a) is one of its element, if a is of type A. If t is an element of type @(GProduct, A), then @(GPROJ, A, n, t) is its nth component. theory GProduct is import Nat def GProduct = \(A : [Nat -> Prop]) !(T : Prop) [!(n : Nat) @(A, n) -> T] -> T]; def GPRODUCT = \(A : [Nat -> Prop) \(a : !(n : Nat) @(A, n)) \(T : Prop, z : [!(n : Nat) @(A, n) -> T]) @(z, a); def GPROJ = \(A : [Nat -> Prop]) \(n : Nat, t : @(GProduct, A)) @(t, @(A, n), \(a : !(n : Nat) @(A, n)) @(a, n)) end;

Type Theory and PowerEpsilon

2.7.6

Sum Types (+)

2.7.6.1

Sum of Two Types U and V

35

We may similarly construct the intuitionistic sum of two propositions P and Q which represents the disjunction of two propositions: theory Sum2 is def Sum2 = \(Ui : Prop, Vi : Prop) !(Ti : Prop) [[Ui -> Ti] -> [Vi -> Ti] -> Ti]; def INJ1 = \(Ui : Prop, Vi : Prop) \(u : Ui) \(Ti : Prop) \(x : [Ui -> Ti], y : [Vi -> Ti]) @(x, u); def INJ2 = \(Ui : Prop, Vi : Prop) \(v : Vi) \(Ti : Prop) \(x : [Ui -> Ti], y : [Vi -> Ti]) @(y, v); def CASE = \(U : Prop, V : Prop, Ti : Prop) \(x : [U -> Ti], y : [V -> Ti], s : @(Sum2, U, V)) @(s, Ti, x, y); def WHEN = \(U : Prop, V : Prop, W : Prop) \(a : @(Sum2, U, V), c : [U -> W], d : [V -> W]) @(a, W, \(x : U) @(CASE, U, V, W, c, d, a), \(y : V) @(CASE, U, V, W, c, d, a)); def Or = Sum2 end;

where the sum-elimination is proved by the conditional expression CASE and the two sum-introduction rules correspond to the two injection functions INJ1 and INJ2. 2.7.6.2

Sum of Three Types U, V and W

Similarly we can define the intuitionistic sum of three propositions P, Q and R which represent the disjunction of three propositions: theory Sum3 is

Type Theory and PowerEpsilon

36

import Sum2 def Sum3 = \(U : Prop, V : Prop, W : Prop) !(Ti : Type(0)) [[U -> Ti] -> [V -> Ti] -> [W -> Ti] -> Ti]; def CASE3 = \(U : Prop, V : Prop, W : Prop) \(T : Type(0), x : [U -> T], y : [V -> T], z : [W -> T]) \(s : @(Sum3, U, V, W)) @(s, T, x, y, z); def INJC1 = \(U : Prop, V : Prop, W : Prop) \(u : U) \(Ti : Type(0)) \(x : [U -> Ti], y : [V -> Ti], z : [W -> Ti]) @(x, u); def INJC2 = \(U : Prop, V : Prop, W : Prop) \(v : V) \(Ti : Type(0)) \(x : [U -> Ti], y : [V -> Ti], z : [W -> Ti]) @(y, v); def INJC3 = \(U : Prop, V : Prop, W : Prop) \(w : W) \(Ti : Type(0)) \(x : [U -> Ti], y : [V -> Ti], z : [W -> Ti]) @(z, w); def WHEN3 = \(U : Prop, V : Prop, W : Prop) \(Xi : Type(0), a : @(Sum3, U, V, \(c : [U -> Xi], d : [V -> Xi], e @(a, Xi, \(x : U) @(CASE3, U, V, W, Xi, \(y : V) @(CASE3, U, V, W, Xi, \(z : W) @(CASE3, U, V, W, Xi,

W)) : [W -> Xi])

c, d, e, a), c, d, e, a), c, d, e, a))

end;

2.7.6.3

Sum of Infinite Type Sequence

Consider the sum of an infinite sequence of types defined as a function A : [Nat -> Prop]. According to the definition, the infinite disjoint union type of A is

Type Theory and PowerEpsilon

37

@(GSum, A), and @(GINJ, A, a) is its element, if a is of type A. theory GSum is import Nat def GSum = \(A : [Nat -> Prop]) !(T : Prop) [?(n : Nat) @(A, n) -> T] -> T]; def GINJ = \(A : [Nat -> Prop) \(a : ?(n : Nat) @(A, n)) \(T : Prop, z : [?(n : Nat) @(A, n) -> T]) @(z, a); def GCASE = \(A : [Nat -> Prop]) \(n : Nat, a : [?(m : Nat) @(A, m) -> @(A, n)], t : @(GSum, A)) @(t, @(A, n), a) end;

2.7.7

Subset Types

We may also define the intuitionistic subset of a given type with the subsetintroduction rule INTRO and the subset-elimination rule ELIMIT: theory Subset is def Subset = \(T : Kind, Ai : T, Pi : [Ai -> Prop]) !(Bi : T) [!(x : Ai) [@(Pi, x) -> Bi] -> Bi]; def INTRO = \(T : Kind, Ai : T, Pi : [Ai -> Prop]) \(x : Ai, y : @(Pi, x)) \(Bi : T) \(q : !(x : Ai) [@(Pi, x) -> Bi]) @(q, x, y); def ELIMIT = \(T : Kind, Ai : T, Pi : [Ai -> Prop]) \(p : @(Subset, T, Ai, Pi)) @(p, Ai, \(x : Ai, y : @(Pi, x)) x) end;

There is a little difference between Subset and Sigma which can be seen as

Type Theory and PowerEpsilon

38

follows: def Subset = \(T : Kind) \(Ai : T) \(Pi : [Ai -> Prop]) !(Bi : T) [!(x : Ai) [@(Pi, x) -> Bi] -> Ai]; def Sigma = \(T : Kind) \(Ai : T) \(Pi : [Ai -> Prop]) !(Bi : T) [!(x : Ai) [@(Pi, x) -> Bi] -> Bi];

2.7.8

Leibniz’s Equality

Leibniz’s equality is definable in PowerEpsilon: theory Equal is def Equal = \(A : Type(0), x : A, y : A) !(P : [A -> Prop]) [@(P, x) -> @(P, y)] end;

The equality satisfies the reflexive, symmetric and transitive properties, which can be verified as follows. If REFLEX, SYMM and TRANS specify the desired properties, we will have: dec REFLEX : !(A : Type(0), R : [A -> A -> Prop], x : A) @(R, x, x); dec SYMM : !(A : Type(0), R : [A -> A -> Prop], x : A, y : A) [@(R, x, y) -> @(R, y, x)]; dec TRANS : !(A : Type(0), R : [A -> A -> Prop], x : A, y : A, z : A) [@(R, x, y) -> @(R, y, z) -> @(R, x, z)]

The following lemmas give the proofs which state that Equal satisfies the reflexive, symmetric and transitive properties. def LEMMA1 = @(REFLEX, Ti, @(Equal, Ti)); def LEMMA2 = @(SYMM, Ti, @(Equal, Ti));

Type Theory and PowerEpsilon

39

def LEMMA3 = @(TRANS, Ti, @(Equal, Ti))

The following results are delivered by PowerEpsilon system: LEMMA1 : !(x : Ti) @(Equal, Ti, x, x) LEMMA2 : !(x : Ti) !(y : Ti) [@(Equal, Ti, x, y) -> @(Equal, Ti, y, x)] LEMMA3 : !(x : Ti) !(y : Ti) !(z : Ti) [@(Equal, Ti, x, y) -> @(Equal, Ti, y, z) -> @(Equal, Ti, x, z)]

2.8

Transforming English to PowerEpsilon

At this point, we translate a few sentences into propositional form. Consider the sentence “if it rains, the picnic is cancelled.” Let identifier R stand for the proposition “it rains” and let identifier PC represent the “picnic is cancelled”. Then the sentence can be written as [R -> PC]. As shown by this example, the technique is to represent “atomic parts” of a sentence – how there are chosen is up to the translator – by identifiers and to describe their relationship using logical operators. Here are some more examples, using identifiers R, PC, Wet, and S defined as follows: it rains: R : Prop picnic is cancelled: PC : Prop be wet: Wet : Prop Stay at home: S : Prop We then may define the following propositions in terms of PowerEpsilon: 1. If it rains but I stay at home, I won’t be wet: [@(And, R, S) -> @(Not Wet). 2. I will be wet if it rains: [R -> Wet]. 3. If it rains and the picnic is not cancelled or I don’t stay home, I will be wet: either @(Or, @(And, R, @(Not, PC)), @(Not, S)) -> Wet] or @(And, R, @(Or, @(Not, PC)), @(Not, S)) -> Wet]. The English is ambiguous; the latter proposition is probably the desired one. 4. Whether or not the picnic is cancelled, I am staying home if it rains: [@(And, @(Or, PC, @(Not, PC)), R) -> S] . In classical logic, this may reduce to [R -> S]. However, in constructive logic, this is not reducible. 5. Either it does not rain or I am staying home: @(Or, @(Not, R), S).

Type Theory and PowerEpsilon

2.9

40

Propositions as Types and Proofs as Programs

One of the basic ideas behind constructive type theory is the Curry-Howard interpretation of propositions as types and proofs as programs. This view of propositions is related both to Heyting’s explanation of intuitionistic logic and, on a more formal level, to Kleene’s realizability interpretation of intuitionistic arithmetic. The judgement or type assignment “a : A” in PowerEpsilon can be read in at least the four following ways: • a is an element of type A. • a is a proof object for the proposition A. • a is a program satisfying the specification A. • a is a solution to the problem A. In classical mathematics, a proposition is thought of as being true or false independently of whether we can prove or disprove it. On the other hand, a proposition is constructively true only if we have a method to prove it. For example, classically the law of excluded middle, A ∨ ¬A, is true, since the proposition A is either true or false. Constructively, however, a disjunction is true only if we can prove one of the disjuncts. Since we have no method of proving or disproving an arbitrary proposition A, we have no proof of A ∨ ¬A and therefore the law of excluded middle is not constructively valid. We may establish the following identifications between propositions and types. • A proof of type [A -> B] is a function (method, program) which to each proof of A gives a proof of B. • A proof of type @(Product, A, B) is a pair whose first component is a proof A and whose second component is a proof of B. • A proof of type @(Sum, A, B) is either a proof A or a proof of B together with the information of which of A or B we have a proof. The elements in @(Sum, A, B) are of the form @(INJ1, A, B, a) and @(INJ2, A, B, b) where a : A and b : B. • A proof of type !(x : A) @(B, x) is a function (method, program) which to each element a of type A gives a proof of @(B, a). The type corresponding to this is the Cartesian product of a family of types. The elements of this type are functions which, when applied to an element a in the type A gives an element in the type @(B, a).

Type Theory and PowerEpsilon

41

• A proof of type ?(x : A) @(B, x) is a pair whose first component a is an element of type A and whose second component is a proof of @(B, a). The type corresponding to this is the disjoint union of a family of types. The elements of this type are pairs where a : A and b : @(B, a). The correspondence between propositions and types, and proofs and programs are called Curry-Howard isomorphism. From the points of view for computer programming, a proposition could be interpreted as the specifications of the task of a program in the following way. • @(Product, A, B) is a specification of programs which, when executed, yield a pair @(PRODUCT, A, B, a, b), where a is a program for the task A and b is a program for the task B. • @(Sum, A, B) is a specification of programs which, when executed, either yields @(INJ1, A, B, a) or @(INJ2, A, B, b), where a is a program for A and b is a program for B. • [A -> B] is a specification of programs which, when executed, yields \(x : A) b, where b is a program for B under the assumption that x is a program for A. • !(x : A) @(B, x) is a specification of programs which, when executed, yields \(x : A) b, where b is a program for @(B, x) under the assumption that x is an object of A. This means that when a program for the problem !(x : A) @(B, x) is applied to an arbitrary object x of A, the result will be the program for @(B, x). • ?(x : A) @(B, x) is a specification of programs which, when executed, yields , where a is an object of A and b a program for @(B, a). So, to solve the task ?(x : A) @(B, x) it is necessary to find a method which yields an object a in A and a program for @(B, a).

2.10

Types, Sets and Domains

In describing the semantics of programming languages, we usually use the word “domain” instead of “set”. This was for mathematical reasons. Unfortunately to fully explain the difference between sets and domains, and to convincingly justify our use of the latter, we would have to delve in detail into the underlying mathematics. This we wish to avoid, and so we shall just very crudely sketch some of the issues involved. There are really two related, but separate, problems which lead to the use of domains rather than sets: • Recursive definitions of functions.

Type Theory and PowerEpsilon

42

• Recursive definitions of sets. We shall look at the these in turn.

2.10.1

The Problem of Recursively Defined Functions

We often find it necessary to define functions recursively. For example, the semantic clause for @(WHILE, e, s), defines as let v = @(EXPR, e, r, z) in @(GIF_THEN_ELSE, State, @(GET_BVAL, v), @(STAT, @(SEQ, s, @(WHILE, e, s)), r, z), z), At first sight such ‘definitions’ are highly suspicious since they seem to assume that the thing they are trying to define is already defined. The way out is to regard recursive definitions as equations – to regards the definition given above as analogous to the quadratic equation x = a × x2 + b and to seek methods of solving functional equations. It turns out that the kind of functional equations we want to solve in semantics only have solutions when the functions involved map between specially structured sets called domains. To see what goes wrong with ordinary sets consider the following two equations ‘defining’ f : [Nat -> Nat]: 1. f(x) = f(x) + 1 2. f(x) = f(x) There is no f satisfying equation 1 and every f satisfies equation 2; thus neither of these two equations in any sense defines f .

2.10.2

The Problem of Recursively Defined Sets

It is often the case that intuitions about the ‘data’ manipulated by programs in a language lead us to want to define recursively the domains modelling the corresponding ‘data-types’. For example, we may have the following type definitions: def Sval = !(T : Prop) [[Bool -> T] -> [Int -> T] -> [Location -> T]

Type Theory and PowerEpsilon

43

[Cont -> T] -> T]; def Memory = !(T : Prop) [T -> [Location -> Sval -> T -> T] -> T]; def Input = @(List, Sval); def State = @(Product, Memory, Input); dec Ans : Prop; def Ans = @(Product, Sval, Ans); def Cont = [State -> Ans];

These domain equations are recursive: State is defined in terms of Memory, which is defined in terms of Sval, which is defined in terms of Cont, which is defined in terms of State. The domain Ans is defined in terms of itself. Thus just as the ‘looping’ of @(WHILE, e, s) led us to define its denotation as a recursive function, so the embedding of procedures in states leads us to define State as a recursive domain.

2.10.3

The Role of Scott’s Domain Theory

A major breakthrough in semantic theory came when Dana Scott showed how to consistently interpret both kinds of recursive definitions – definitions of members of domains and definitions of domains themselves – in a single framework. In summary what he did was: • Devise a class of ‘structured’ sets called domains and define the operators Product, Sum and -> etc. on them. • Show how elements of domains could be defined recursively. • Show how domains themselves could be defined recursively.

2.10.4

Types as Domains

In PowerEpsilon, there is a natural corresponding between types and sets. So the type assignment “a : A” in PowerEpsilon can be read as a is an element of set A. We may establish the following identifications between sets and types. • An element of set [A -> B] is a function which to each element of A gives an element of B. • An element of set @(Product, A, B) is a pair whose first component is an element A and whose second component is an element of B. • An element of set @(Sum, A, B) is either an element A or an element of B together with the information of which of A or B we have an element.

Type Theory and PowerEpsilon

44

The elements in @(Sum, A, B) are of the form @(INJ1, A, B, a) and @(INJ2, A, B, b) where a : A and b : B. • An element of set !(x : A) @(B, x) is a function which to each element a of set A gives an element of @(B, a). The corresponding to this is the Cartesian product of a family of sets. The elements of this set are functions which, when applied to an element a in the set A gives an element in the set @(B, a). • An element of set ?(x : A) @(B, x) is a pair whose first component a is an element of set A and whose second component is an element of @(B, a). The corresponding to this is the disjoint union of a family of sets. The elements of this set are pairs where a : A and b : @(B, a). Therefore for denotational semantics setting, we may view types of PowerEpsilon as domains. As a theoretical foundation, it will be easy to give a denotational semantics of PowerEpsilon, since PowerEpsilon by itself is a programming language too. The only difference is that the static semantics of PowerEpsilon is more complicated than its dynamic one. In this book, the words “type” and “domain” will be used denoting the same things without further explanation.

2.10.5

Defining Domains

2.10.5.1

Standard Domains

The following domains are standard domains and will be used without further explanation: Bool, Nat, Int, Rat and Identifier. 2.10.5.2

Finite Domains

Finite domains will be defined explicitly by listing their elements as we have already defined for Bool. The following is a seven elements of domain Spectrum: def Spectrum = !(T : Prop) [T -> T -> T -> T -> T -> T -> T -> T]; def RED = \(T : Prop) \(a : T, b : T, c : T, d : T, e : T, f : T, g : T) a; def ORANGE = \(T : Prop) \(a : T, b : T, c : T, d : T, e : T, f : T, g : T) b; def YELLOW = \(T : Prop) \(a : T, b : T, c : T, d : T, e : T, f : T, g : T) c;

Type Theory and PowerEpsilon

45

def GREEN = \(T : Prop) \(a : T, b : T, c : T, d : T, e : T, f : T, g : T) d; def BLUE = \(T : Prop) \(a : T, b : T, c : T, d : T, e : T, f : T, g : T) e; def INDIGO = \(T : Prop) \(a : T, b : T, c : T, d : T, e : T, f : T, g : T) f; def VIOLET = \(T : Prop) \(a : T, b : T, c : T, d : T, e : T, f : T, g : T) g;

2.10.5.3

Domain Constructors

We shall build domains out of standard, or finite, domains using the various domain constructors such as ->, !, ?, Product, Sum and List. 2.10.5.4

Domain Equations

In general the domain equations have the following general form def D1 = @(T1, D1, ..., Dn); def D2 = @(T1, D1, ..., Dn); . . . def Dn = @(T1, D1, ..., Dn); Where each @(Ti, D1, ..., Dn) is some expression built out of D1, D2, ..., Dn using some domain constructors such as ->, Product, Sum and List described above. An example of a single domain equation is the domain Dw of infinite sequences of members of D defined by def Dw = @(Product, D, Dw); In doing so, we need a pre-declaration of Dw:

Type Theory and PowerEpsilon

46

dec Dw : Prop;

2.10.6

Functions

The word “function” has a number of different meaning which, if not carefully distinguished, can lead to total confusion. It is especially important to distinguish mathematical functions from the so called “functions” which occur as constructs in several programming languages.

Chapter 3

The Separation Kernel The Separation Kernel is an architecture introduced by John Rushby as an architecture of cryptographic and other secure applications [11]. The purpose of this chapter is to describe the architecture and to outline its refinement.

3.1 3.1.1

Basic Architecture Basic Definition

The architecture of the Separation Kernel is simple. It is a single-processor model of a distributed system in which all user processes are separated in time and space from each other. In a distributed system, the execution of each process takes place in a manner independent of any other. Processes can wait for data inputs, particularly inputs from communications channels. For the remainder of the time, the component processes execute at rates independent of all others. There is, in a distributed system, temporal separation between the execution of one process and all other processes. Separation in space means that the processes constituting a distributed system each have their own disjoint address spaces. If two address spaces are disjoint, it is not possible for one process directly to write to the address space of any other process. The Separation Kernel is based on these two fundamental observations. • Separation in time results from the fact that no two processes can be active at exactly the same time. Furthermore, if processes communicate using asynchronous channels, no synchronization points are required, so processes can proceed at their own rate. • Separation in space results from the fact that processes are allocated their own disjoint address spaces.

47

CHAPTER 3. THE SEPARATION KERNEL

3.1.2

48

Temporal Separation

Temporal separation can be enforced by the system’s scheduler and by a message-passing system. On a uni-processor system, the scheduler ensures that only one process executes at any time and executions are interleaved in time. The length of time during which any process will be executing (be active) depends upon the scheduling algorithm and, as will be seen, the algorithm proposed by Rushby is particularly simple. In addition, the use of asynchronous messages means that processes do not synchronize during the exchange of messages, although they are permitted to wait for responses or results to be returned. Even in the case of waiting for a response, the waiting state depends upon the algorithms used to implement processes, not upon the underlying system.

3.1.3

Spatial Separation

Spatial separation can be enforced by segmentation. Most processors supporting segmented address spaces also have mechanisms for detecting and reacting to attempts by one process to access the segments of another. On the Intel IA32 and IA64 machines, for example, attempts to cross segment boundaries causes a hardware exception; a handler can be provided to handle the exception by, for example, killing the offending process. Each process is, therefore, allocated one or more segments. Should a process, either by error or through malice, attempt to address a location in another process’s segments, the hardware should cause an exception to be raised. This permits the kernel to detect such illegal accesses and to perform some action.

3.1.4

The Round-Robin Scheme

The original proposal for the Separation Kernel was included the stipulation that a round-robin scheduler would be adequate. The round-robin scheme can be used in real-time applications because of its simplicity; it can also be used to simulate distributed systems because processes only enter the queue when they are ready to execute. Temporal separation is supported by the fact that, under pure round-robin, there is no a priori limit to the length of the period during which a process can execute. In many systems, time-slicing is used to share the processor between processes; each process is permitted to execute for a defined period of time and, when this period is exhausted, the process is suspended and another continues its execution. The property that round-robin scheduling allows processes to execute for indefinite periods must be qualified. Processes execute until such time as they are no longer able to continue and at such a time, they must relinquish the processor. Processes relinquish the processor either on a purely voluntary basis by executing a voluntary suspension operation or by executing some other operation whose definition includes the an operator that suspends the caller. The primitive that sends messages might suspend the caller,

CHAPTER 3. THE SEPARATION KERNEL

49

for example.

3.1.5

Boundary of Kernel and User Processes

It should be clear that the kernel must reside in an address space that is disjoint from all user address spaces. This ensures that the kernel is protected against malicious processes. Furthermore, it is also separated in time because, by definition, it executes only when processes do not. In order to enforce the spatio-temporal separation of the kernel, it is essential to define a clean interface between it and user processes.

3.2

Extending the Architecture

3.2.1

Trusted and Untrusted Software

The Separation Kernel defines a basic and simple set of mechanisms for managing secure applications. It makes a distinction between trusted software (the kernel) and untrusted software (applications in user processes). The architecture requires some extension in order to include devices such as communications lines, printers and so on. The US National Security Agency has produced an extension to the Separation Kernel architecture so that device handling can be included. This introduces the concept of “trusted” code into the system. The context in which trusted code is introduced is the following. • The document assumes that the kernel is formally specified and that its properties are therefore well understood. Because it is formally specified, it is completely trusted. • User processes are completely untrusted; this is because they are not under the control of the developers of the kernel and are assumed not to have been formally constructed. There is no control, it is assumed, over the content of user processes. • Device processes (drivers and associated support code) require greater access to kernel facilities and might have to do such things as allocating their own storage, directly accessing the scheduler queues, and so on. This has the implication that devices should only be introduced into a secure system if they are trusted to a much greater extent than user code. The production of device-related code must be carefully controlled. Ideally, this code would be constructed using formal methods. One reason for assuming that it is not so constructed is the range of possible hardware that any implementation of the Separation Kernel can control. A second reason is that the NSA probably do not believe that device handling code can be constructed formally - our opinion is at variance with theirs (and

CHAPTER 3. THE SEPARATION KERNEL

50

we have unpublished cases that tend to support our position). No matter what the reason, it is important that device-handling code should be trusted.

3.2.2

Device Handling Code

It is important, then, to support device-handling code. This kind of code needs to be fast and it needs access to low-level facilities. One way to support devicehandling is to make the kernel open. This subverts the whole project. Instead, it is better to define and formally construct an interface to the kernel for use by device-handling code. The interface should only give device code access to a minimal set of services. In particular, it should define operations that • Pass parameters from and to requesting user processes. • Allow device-handling processes to suspend themselves. • Cause device-handling processes to become active (i.e., to enter the scheduler’s queue of processes ready to execute). In addition, it should be possible to determine whether the services requested by user processes correspond to what is possible. This is the approach adopted in this book. A set of operations is defined that provide exactly those capabilities listed above. In addition, devices are represented by “device numbers” as far as user processes are concerned. The kernel maps device numbers to actual devices, thus decoupling device (service) naming from the devices themselves (it also allows for some flexibility in the kernel). Some might object that device numbers are a low-level representation. The reply is that user processes use library calls to request such services; the bottom level of such libraries will use device numbers, not the higher levels and not user code.

3.3

Summary

The Separation Kernel can be summarized as follows: • A segmented main store that is supported by the processor hardware. • A round-robin scheduling regime. • Natural-break scheduling by user and device processes. • A well-defined set of interfaces for device-handling processes. • A well-defined interface for user processes.

Chapter 4

The Programming Language C-VMK - Syntax 4.1 4.1.1

Expressions Identifiers and Other Lexical Entities

dec Identifier : Prop; def Ident_List = @(List, Identifier); dec ERR_BOOL : Bool; dec ERR_INT : Int; dec ERR_IDEN : Identifier;

4.1.2

Type Definition of Expression

def Expression = !(T : Prop) [T -> %-- NIL Pointer or Null Pointer --% [Bool -> T] -> [Int -> T] -> [Bit16Word -> T] -> [Identifier -> T] -> [T -> T] -> %-- Content (Pointer Reference) --% [T -> T -> T] -> %-- Use of Record --% [T -> Expr_list -> T] -> %-- Use of Array --% [Expression -> Expr_list -> T] ->

51

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 52

[Binop -> T -> T -> T] -> [Unop -> T -> T] -> T];

4.1.3 dec dec dec dec dec dec dec dec dec dec dec

Constructors of Expression NIL_EXPR BOOL_EXPR INT_EXPR BIT16_EXPR IDEN_EXPR CONT_EXPR REC_EXPR ARR_EXPR APPL_EXPR BIN_EXPR UN_EXPR

dec ERR_EXPR

4.1.4 dec dec dec dec dec dec dec dec dec dec dec

4.1.5 dec dec dec dec dec

: : : : : : : : : : :

Expression; [Bool -> Expression]; [Int -> Expression]; [Bit16Word -> Expression]; [Identifier -> Expression]; [Expression -> Expression]; [Expression -> Expression -> Expression]; [Expression -> Expr_list -> Expression]; [Expression -> Expr_list -> Expression]; [Binop -> Expression -> Expression -> Expression]; [Unop -> Expression -> Expression];

: Expression;

Predicate Functions of Expression IS_NIL_EXPR IS_BOOL_EXPR IS_INT_EXPR IS_BIT16_EXPR IS_IDEN_EXPR IS_CONT_EXPR IS_REC_EXPR IS_ARR_EXPR IS_CALL_EXPR IS_BIN_EXPR IS_UN_EXPR

: : : : : : : : : : :

[Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression

-> -> -> -> -> -> -> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool];

Projectors of Expression GET_EXPR_BOOL GET_EXPR_INT GET_EXPR_BIT16 GET_EXPR_IDEN GET_EXPR_CONT

: : : : :

[Expression [Expression [Expression [Expression [Expression

-> -> -> -> ->

Bool]; Int]; Bit16Word]; Identifier]; Expression];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 53

dec dec dec dec dec dec dec dec dec dec dec

GET_EXPR_RECNAM GET_EXPR_RECIDX GET_EXPR_ARRNAM GET_EXPR_ARRIDX GET_EXPR_FUNC GET_EXPR_ELIST GET_EXPR_BINOP GET_EXPR_LEFT GET_EXPR_RIGHT GET_EXPR_UNOP GET_EXPR_UN

4.1.6

: : : : : : : : : : :

[Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression [Expression

-> -> -> -> -> -> -> -> -> -> ->

Expression]; Expression]; Expression]; Expr_list]; Expression]; Expr_list]; Binop]; Expression]; Expression]; Unop]; Expression];

Induction Rule for Expression

dec IndExpr : !(P : [Expression -> Prop]) [@(P, NIL_EXPR) -> !(x : Bool) @(P, @(BOOL_EXPR, x)) -> !(x : Int) @(P, @(INT_EXPR, x)) -> !(x : Bit16Word) @(P, @(BIT16_EXPR, x)) -> !(x : Identifier) @(P, @(IDEN_EXPR, x)) -> !(x : Expression) @(P, @(CONT_EXPR, x)) -> !(x1 : Expression, x2 : Expression) @(P, @(REC_EXPR, x1, x2)) -> !(x1 : Expression, x2 : Expr_list) @(P, @(ARR_EXPR, x1, x2)) -> !(f : Expression, l : Expr_list) @(P, @(APPL_EXPR, f, l)) -> !(o : Binop, e1 : Expression, e2 : Expression) @(P, @(BIN_EXPR, o, e1, e2)) -> !(o : Unop, e : Expression) @(P, @(UN_EXPR, o, e)) -> !(e : Expression) @(P, e)];

4.1.7

Expression List

4.1.7.1

Type Definition of Expr list

dec Expression : Prop; def Expr_list = @(List, Expression);

4.1.7.2

Constructors of Expr list

def EMPTY_ELIST = @(NIL,

Expression);

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 54

def ENTER_ELIST = @(CONS, Expression); dec ERR_ELIST : Expr_list; def HEAD_ELIST = @(HEAD, Expression); def TAIL_ELIST = @(TAIL, Expression); def IS_EMPTY_ELIST = @(IS_EMPTY, Expression);

4.2 4.2.1

Declarations Array Declarations

An array is declared as array I[e1..e2] or array I[e1..e2] of T. def Array_Decl = !(T : Prop) [[@(List, @(Product, Expression, Expression)) -> Type_Elem -> T] -> T]; dec MK_ARRAY_DECL : [@(List, @(Product, Expression, Expression)) -> Type_Elem -> Array_Decl]; dec GET_ARRDEC_RANLST : [Array_Decl -> @(List, @(Product, Expression, Expression))]; dec GET_ARRDEC_TYPE : [Array_Decl -> Type_Elem];

4.2.2

Record Declarations

A record is declared as follows record i1 : i2 : ...; ik : end;

rname is T1; T2; Tk;

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 55

def Record_Decl = !(T : Prop) [[Identifier -> Type_Elem -> T] -> T]; dec MK_RECORD_DECL : [Identifier -> Type_Elem -> Record_Decl]; dec GET_REC_IDEN : [Record_Decl -> Identifier]; dec GET_REC_TYPE : [Record_Decl -> Type_Elem]; def Record_Decl_List = @(List, Record_Decl);

4.2.3

Type Declarations

4.2.3.1

Type Definition of Type Decl

def Type_Decl = !(T : Prop) [[Identifier -> Record_Decl_List -> T] -> %-- Record Type --% [Identifier -> Array_Decl -> T] -> %-- Array Type --% [Identifier -> Type_Elem -> T] -> %-- Access Type --% [T -> T -> T] -> %-- Sequence of Type Declaration --% T];

4.2.3.2 dec dec dec dec

TDECL_REC TDECL_ARRAY TDECL_ACCESS TDECL_SEQ

4.2.3.3 dec dec dec dec

Constructors of Type Decl : : : :

[Identifier -> Record_Decl_List -> Type_Decl]; [Identifier -> Array_Decl -> Type_Decl]; [Identifier -> Type_Elem -> Type_Decl]; [Type_Decl -> Type_Decl -> Type_Decl];

Predicate Functions of Type Decl

IS_TDECL_REC IS_TDECL_ARRAY IS_TDECL_ACCESS IS_TDECL_SEQ

: : : :

[Type_Decl [Type_Decl [Type_Decl [Type_Decl

-> -> -> ->

Bool]; Bool]; Bool]; Bool];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 56

4.2.3.4

Projectors of Type Decl

dec GET_TDECL_RIDEN : [Type_Decl -> Identifier]; dec GET_TDECL_RRECL : [Type_Decl -> Record_Decl_List]; dec GET_TDECL_AIDEN : [Type_Decl -> Identifier]; dec GET_TDECL_ADECL : [Type_Decl -> Array_Decl]; dec GET_TDECL_PIDEN : [Type_Decl -> Identifier]; dec GET_TDECL_PDECL : [Type_Decl -> Type_Elem]; dec LEFT_TDECL dec RIGHT_TDECL

: [Type_Decl -> Type_Decl]; : [Type_Decl -> Type_Decl];

4.2.4

Type Definitions

4.2.4.1

Type Definition of Type Elem

def Type_Elem = !(T : Prop) [T -> %-- Boolean --% T -> %-- Integer --% T -> %-- Bit16Word --% [Identifier -> T] -> [Record_Decl_List -> T] -> %-- Record Type --% [Array_Decl -> T] -> %-- Array Type --% [T -> T] -> %-- Access Type --% T];

4.2.4.2 dec dec dec dec dec dec dec

Constructors of Type Elem

BOOL_TYPE INT_TYPE BIT16_TYPE IDEN_TYPE REC_TYPE ARRAY_TYPE ACCESS_TYPE

: : : : : : :

Type_Elem; Type_Elem; Type_Elem; [Identifier -> Type_Elem]; [Record_Decl_List -> Type_Elem]; [Array_Decl -> Type_Elem]; [Type_Elem -> Type_Elem];

dec ERR_TYPE_ELEM : Type_Elem;

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 57

4.2.4.3

Project Functions of Type Elem

dec GET_ACC_TYPE : [Type_Elem -> Type_Elem]; dec EQ_TYPE_ELEM : [Type_Elem -> Type_Elem -> Bool];

4.2.4.4 dec dec dec dec dec dec dec

4.2.5

Predicate Functions of Type Elem

IS_BOOL_TYPE IS_INT_TYPE IS_BIT16_TYPE IS_IDEN_TYPE IS_REC_TYPE IS_ARRAY_TYPE IS_ACCESS_TYPE

: : : : : : :

[Type_Elem [Type_Elem [Type_Elem [Type_Elem [Type_Elem [Type_Elem [Type_Elem

-> -> -> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool];

Type Definition of Declaration

def Declaration = !(T : Prop) [T -> [Identifier -> Type_Elem -> T] -> %-- Const Declaration --% [Identifier -> Expression -> Type_Elem -> T] -> %-- Var Declaration --% [Identifier -> Expression -> Type_Elem -> T] -> %-- Record Declaration --% [Identifier -> Record_Decl_List -> T] -> %-- Array Declaration --% [Identifier -> Array_Decl -> T] -> [T -> T -> T] -> T];

4.2.6 dec dec dec dec dec dec

Constructors of Declaration NULL_DECL DECL DECL_CONST DECL_VAR DECL_RECORD DECL_ARRAY

: : : : : :

Declaration; [Identifier -> [Identifier -> [Identifier -> [Identifier -> [Identifier ->

Type_Elem -> Declaration]; Expression -> Type_Elem -> Declaration]; Expression -> Type_Elem -> Declaration]; Record_Decl_List -> Declaration]; Array_Decl -> Declaration];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 58

dec DECL_SEQ

: [Declaration -> Declaration -> Declaration];

dec ERR_DECL : Declaration;

4.2.7 dec dec dec dec dec dec dec

4.2.8 dec dec dec dec dec dec dec dec dec dec dec dec dec dec

4.2.9

Predicate Functions of Declaration IS_NULL_DECL IS_DECL IS_DECL_CONST IS_DECL_VAR IS_DECL_RECORD IS_DECL_ARRAY IS_DECL_SEQ

: : : : : : :

[Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration

-> -> -> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool];

Projectors of Declaration GET_DECL_IDEN GET_DECL_TYPE GET_DECL_CIDEN GET_DECL_CEXPR GET_DECL_CTYPE GET_DECL_VIDEN GET_DECL_VEXPR GET_DECL_VTYPE GET_DECL_RIDEN GET_DECL_RDECL GET_DECL_AIDEN GET_DECL_ADECL LEFT_DECL RIGHT_DECL

: : : : : : : : : : : : : :

[Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration [Declaration

-> -> -> -> -> -> -> -> -> -> -> -> -> ->

Identifier]; Type_Elem]; Identifier]; Expression]; Type_Elem]; Identifier]; Expression]; Type_Elem]; Identifier]; Record_Decl]; Identifier]; Array_Decl]; Declaration]; Declaration];

Induction Rule for Declaration

dec IndDecl : !(P : [Declaration -> Prop]) [@(P, NULL_DECL) -> !(i : Identifier, t : Type_Elem) @(P, @(DECL, i, t)) -> !(i : Identifier, e : Expression, t : Type_Elem) @(P, @(DECL_CONST, i, e, t)) -> !(i : Identifier, e : Expression, t : Type_Elem) @(P, @(DECL_VAR, i, e, t)) -> !(i : Identifier, d : Record_Decl_List) @(P, @(DECL_RECORD, i, d)) ->

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 59

!(i : Identifier, d : Array_Decl) @(P, @(DECL_ARRAY, i, d)) -> !(d1 : Declaration, d2 : Declaration) @(P, @(DECL_SEQ, d1, d2)) -> !(d : Declaration) @(P, d)];

4.3

Procedure Declarations

4.3.1

Mode Definition

4.3.1.1

Type Definition of Mode

def Mode = !(T : Prop) [T -> T -> T -> T -> T -> T -> T -> T -> T -> T];

4.3.1.2 dec dec dec dec dec dec dec dec dec

Constructors of Mode

RES_MODE VAT_MODE VAR_MODE VAL_MODE CON_MODE NAM_MODE REF_MODE TEX_MODE DEN_MODE

4.3.1.3

: : : : : : : : :

Mode; Mode; Mode; Mode; Mode; Mode; Mode; Mode; Mode;

Call-By-Result

def RES_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) t;

4.3.1.4

Call-By-Value and Result

def VAT_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) w;

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 60

4.3.1.5

Call-By-Variable (Call-By-Reference)

def VAR_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) u;

4.3.1.6

Call-By-Value

def VAL_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) v;

4.3.1.7

Call-By-Constant

def CON_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) x;

4.3.1.8

Call-By-Name

def NAM_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) y;

4.3.1.9

FORTRAN Based Call-By-Reference

def REF_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) z;

4.3.1.10

Call-By-Text

def TEX_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) a;

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 61

4.3.1.11

Call-By-Denotation

def DEN_MODE = \(T : Prop) \(t : T, w : T, u : T, v : T, x : T, y : T, z : T, a : T, b : T) b; dec ERR_MODE : Mode;

4.3.1.12 dec dec dec dec dec dec dec dec dec

Predicate Functions of Mode

IS_RES_MODE IS_VAT_MODE IS_VAR_MODE IS_VAL_MODE IS_CON_MODE IS_NAM_MODE IS_REF_MODE IS_TEX_MODE IS_DEN_MODE

4.3.2

: : : : : : : : :

[Mode [Mode [Mode [Mode [Mode [Mode [Mode [Mode [Mode

-> -> -> -> -> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool];

Formal Parameters

dec Form_par_list : Prop; dec ERR_FPAR_LIST : Form_par_list; def Form_par = !(T : Prop) [[Identifier -> Type_Elem -> Mode -> T] -> [Identifier -> Form_par_list -> T] -> [Identifier -> Form_par_list -> Type_Elem -> T] -> T];

4.3.2.1

Constructors of Form par

dec MK_FORM_PAR : [Identifier -> Type_Elem -> Mode -> Form_par]; dec MK_PROC_PAR : [Identifier -> Form_par_list -> Form_par]; dec MK_FUNC_PAR : [Identifier -> Form_par_list -> Type_Elem -> Form_par]; dec ERR_FORM_PAR : Form_par;

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 62

4.3.2.2 dec dec dec dec dec dec dec dec

Projectors of Form par

GET_FPAR_IDEN GET_FPAR_TYPE GET_FPAR_MODE GET_PCPAR_IDEN GET_PCPAR_FLIST GET_FNPAR_IDEN GET_FNPAR_FLIST GET_FNPAR_TYPE

: : : : : : : :

[Form_par [Form_par [Form_par [Form_par [Form_par [Form_par [Form_par [Form_par

-> -> -> -> -> -> -> ->

Identifier]; Type_Elem]; Mode]; Identifier]; Form_par_list]; Identifier]; Form_par_list]; Type_Elem];

4.3.3

Formal Parameter List

4.3.3.1

Type Definition of Form par list

def Form_par_list = @(List, Form_par);

4.3.3.2

Constructors of Form par list

dec EMPTY_FPAR_LIST : Form_par_list; dec ENTER_FPAR_LIST : [Form_par -> Form_par_list -> Form_par_list];

4.3.3.3

Predicate Functions of Form par list

dec IS_EMPTY_FPAR_LIST : [Form_par_list -> Bool];

4.3.3.4

Project Functions of Form par list

dec HEAD_FPAR_LIST : [Form_par_list -> Form_par]; dec TAIL_FPAR_LIST : [Form_par_list -> Form_par_list];

4.3.4

Type Definition of Proc

def Proc = !(T : Prop) [T -> [Identifier -> Form_par_list -> Statement -> T] ->

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 63

[Identifier -> Form_par_list -> Statement -> Type_Elem -> T] -> [T -> T -> T] -> T];

4.3.5

Constructors of Proc

dec MK_NIL_PROC : Proc; dec MK_PROC : [Identifier -> Form_par_list -> Statement -> Proc]; dec MK_FUNC : [Identifier -> Form_par_list -> Statement -> Type_Elem -> Proc]; dec MK_SEQ_PROC : [Proc -> Proc -> Proc];

4.3.6 dec dec dec dec

4.3.7 dec dec dec dec dec dec dec dec dec

4.4 4.4.1

Predicate Functions of Proc IS_NIL_PROC IS_PROC_PROC IS_FUNC_PROC IS_SEQ_PROC

: : : :

[Proc [Proc [Proc [Proc

-> -> -> ->

Bool]; Bool]; Bool]; Bool];

Project Functions of Proc GET_PROC_IDEN GET_PROC_FPAR GET_PROC_STAT GET_FUNC_IDEN GET_FUNC_FPAR GET_FUNC_STAT GET_FUNC_RETS LEFT_PROC RIGHT_PROC

: : : : : : : : :

[Proc [Proc [Proc [Proc [Proc [Proc [Proc [Proc [Proc

-> -> -> -> -> -> -> -> ->

Identifier]; Form_par_list]; Statement]; Identifier]; Form_par_list]; Statement]; Type_Elem]; Proc]; Proc];

Statements Type Definition of Statement

def Statement = !(T : Prop)

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 64

[%-- Null --% T -> %-- Exit --% T -> %-- Return --% T -> %-- Return with Expression --% [Expression -> T] -> %-- Assignment --% [Variable -> Expression -> T] -> %-- If-Then --% [Expression -> T -> T] -> %-- If-Then-Else --% [Expression -> T -> T -> T] -> %-- While-Do --% [Expression -> T -> T] -> %-- Compound --% [T -> T -> T] -> %-- Label --% [Identifier -> T -> T] -> %-- Goto --% [Identifier -> T] -> [Expression -> T -> T] -> %-- With --% [Expression -> Expr_list -> T] -> %-- Call --% [Identifier -> Expression -> Expression -> T -> T] -> %-- For-To --% [Identifier -> Expression -> Expression -> T -> T] -> %-- For-Down --% [Expression -> T -> T] -> %-- Repeat --% [T -> T] -> %-- Loop --% [Type_Decl -> Declaration -> Proc -> T -> T] -> %-- Block --% [Identifier -> Type_Elem -> T] -> %-- New --% [Identifier -> T] -> %-- Depose --% T];

4.4.2 dec dec dec dec dec dec dec dec dec dec dec dec dec

Constructors of Statement NULL EXIT RETURN RETURNE ASSIGNMENT IFTHEN IFTHEL WHILE SEQ LABEL GOTO WITH CALL

dec FORTO :

: : : : : : : : : : : : :

Statement; Statement; Statement; [Expression -> Statement]; [Variable -> Expression -> Statement]; [Expression -> Statement -> Statement]; [Expression -> Statement -> Statement -> Statement]; [Expression -> Statement -> Statement]; [Statement -> Statement -> Statement]; [Identifier -> Statement -> Statement]; [Identifier -> Statement]; [Expression -> Statement -> Statement]; [Expression -> Expr_list -> Statement];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 65

[Identifier -> Expression -> Expression -> Statement -> Statement]; dec FORDOWN : [Identifier -> Expression -> Expression -> Statement -> Statement]; dec REPEAT : [Expression -> Statement -> Statement]; dec LOOP : [Statement -> Statement]; dec BLOCK : [Type_Decl -> Declaration -> Proc -> Statement -> Statement]; dec NEWSTAT : [Identifier -> Type_Elem -> Statement]; dec DEPOSE : [Identifier -> Statement];

4.4.3 dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec

Predicate Functions of Statement IS_NULL_STAT IS_EXIT_STAT IS_RETURN_STAT IS_RETURNE_STAT IS_ASSIGN_STAT IS_IFTHEN_STAT IS_IFTHEL_STAT IS_WHILE_STAT IS_SEQ_STAT IS_LABEL_STAT IS_GOTO_STAT IS_WITH_STAT IS_CALL_STAT IS_FORTO_STAT IS_FORDOWN_STAT IS_REPEAT_STAT IS_LOOP_STAT IS_BLOCK_STAT

: : : : : : : : : : : : : : : : : :

[Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement

-> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool];

dec IS_NEW_STAT : [Statement -> Bool]; dec IS_DEPOSE_STAT : [Statement -> Bool];

4.4.4

Projectors of Statement

dec ERR_STAT : Statement; dec dec dec dec

GET_RETURNE_EXPR GET_ASSIGN_IDEN GET_ASSIGN_EXPR GET_IFTHEN_EXPR

: : : :

[Statement [Statement [Statement [Statement

-> -> -> ->

Expression]; Variable]; Expression]; Expression];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 66

dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec

GET_IFTHEN_STAT GET_IFTHEL_EXPR GET_IFTHEL_THEN GET_IFTHEL_ELSE GET_WHILE_EXPR GET_WHILE_STAT GET_SEQ_HEAD GET_SEQ_TAIL GET_LABEL_IDEN GET_LABEL_STAT GET_GOTO_IDEN GET_WITH_EXPR GET_WITH_STAT GET_CALL_EXPR GET_CALL_PARL GET_FORTO_IDEN GET_FORTO_LEXPR GET_FORTO_REXPR GET_FORTO_STAT GET_FORDOWN_IDEN GET_FORDOWN_LEXP GET_FORDOWN_REXP GET_FORDOWN_STAT GET_REPEAT_EXPR GET_REPEAT_STAT GET_LOOP_STAT GET_BLOCK_TDECL GET_BLOCK_DECL GET_BLOCK_PROC GET_BLOCK_STAT

: : : : : : : : : : : : : : : : : : : : : : : : : : : : : :

[Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement

-> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> ->

Statement]; Expression]; Statement]; Statement]; Expression]; Statement]; Statement]; Statement]; Identifier]; Statement]; Identifier]; Expression]; Statement]; Expression]; Expr_list]; Identifier]; Expression]; Expression]; Statement]; Identifier]; Expression]; Expression]; Statement]; Expression]; Statement]; Statement]; Type_Decl]; Declaration]; Proc]; Statement];

dec GET_NEW_IDEN : [Statement -> Identifier]; dec GET_NEW_TYPE : [Statement -> Type_Elem]; dec GET_DEPOSE_IDEN : [Statement -> Identifier];

4.4.5

System Service Calls for VM

dec GET_VMGETID_IDENT : [Statement -> Identifier]; dec GET_VMGETID_RNLOC : [Statement -> Identifier]; dec GET_VMGETID_RETCD : [Statement -> Identifier]; dec GET_VMGETNM_RNLOC : [Statement -> Identifier]; dec GET_VMGETNM_IDENT : [Statement -> Identifier]; dec GET_VMGETNM_RETCD : [Statement -> Identifier];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 67

dec GET_VMGETST_IDENT : [Statement -> Identifier]; dec GET_VMGETST_STATU : [Statement -> Identifier]; dec GET_VMGETST_RETCD : [Statement -> Identifier]; dec GET_VMHALT_WTYPE : [Statement -> VMWakeupType]; dec GET_VMHALT_TICKS : [Statement -> Nat]; dec GET_VMHALT_RETCD : [Statement -> Identifier]; dec GET_VMSTART_IDENT : [Statement -> Identifier]; dec GET_VMSTART_SHTYP : [Statement -> VMScheduleType]; dec GET_VMSTART_RETCD : [Statement -> Identifier]; dec GET_VMSTOP_IDENT : [Statement -> Identifier]; dec GET_VMSTOP_RETCD : [Statement -> Identifier]; dec GET_VMSUSP_IDENT : [Statement -> Identifier]; dec GET_VMSUSP_RETCD : [Statement -> Identifier]; dec GET_VMRESM_IDENT : [Statement -> Identifier]; dec GET_VMRESM_RETCD : [Statement -> Identifier]; dec GET_VMRESET_IDENT : [Statement -> Identifier]; dec GET_VMRESET_STYPE : [Statement -> VMScheduleType]; dec GET_VMRESET_RETCD : [Statement -> Identifier];

4.4.6 dec dec dec dec dec

System Service Calls for TTS GET_INSLTTS_IDT GET_INSLTTS_TAB GET_INSLTTS_NUM GET_INSLTTS_MFT GET_INSLTTS_RET

: : : : :

[Statement [Statement [Statement [Statement [Statement

-> -> -> -> ->

Identifier]; Array]; Nat]; Nat]; Identifier];

dec GET_TTSGETID_IDT : [Statement -> Identifier]; dec GET_TTSGETID_LOC : [Statement -> Identifier]; dec GET_TTSGETID_RET : [Statement -> Identifier]; dec GET_TTSGETNM_LOC : [Statement -> Identifier]; dec GET_TTSGETNM_IDT : [Statement -> Identifier]; dec GET_TTSGETNM_RET : [Statement -> Identifier]; dec GET_TTSSTART_IDENT : [Statement -> Identifier]; dec GET_TTSSTART_RETCD : [Statement -> Identifier];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 68

dec GET_TTSSTOP_RETCD : [Statement -> Identifier];

4.4.7

System Service Calls for Scheduling

dec SET_VMREADY_IDENT : [Statement -> Identifier]; dec CLEAR_VMREADY_ID : [Statement -> Identifier]; dec EXACT_VMWAIT_ID : [Statement -> Identifier]; dec CLEAR_VMWAIT_ID : [Statement -> Identifier]; dec GET_TICKNOFY_TYP : [Statement -> Bit16Word]; dec GET_TICKNOFY_RET : [Statement -> Identifier];

4.4.8

System Service Calls for Virtual Interrupt Handling

dec dec dec dec

GET_TICKINT_GMK GET_TICKINT_MSK GET_TICKINT_SRV GET_TICKINT_RET

: : : :

[Statement [Statement [Statement [Statement

-> -> -> ->

Bool]; Bool]; VMKCont]; Identifier];

dec dec dec dec dec

GET_EXTRINT_LOC GET_EXTRINT_GMK GET_EXTRINT_MSK GET_EXTRINT_SRV GET_EXTRINT_RET

: : : : :

[Statement [Statement [Statement [Statement [Statement

-> -> -> -> ->

VMKLocation]; Bool]; Bool]; VMKCont]; Identifier];

dec GET_ENABPIC_LOC : [Statement -> VMKLocation]; dec GET_ENABPIC_RET : [Statement -> Identifier]; dec GET_DISABPIC_LOC : [Statement -> VMKLocation]; dec GET_DISABPIC_RET : [Statement -> Identifier]; dec GET_SNDVMINT_LOC : [Statement -> VMKLocation]; dec GET_SNDVMSRV_LOC : [Statement -> VMKLocation]; dec GET_SNTVMRET_RET : [Statement -> Identifier]; dec GET_ACKEXCEPT_RET : [Statement -> Identifier]; dec GET_DISPINT_NUM : [Statement -> Nat]; dec GET_DISPINT_RET : [Statement -> Identifier];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 69

dec dec dec dec

4.4.9

GET_GETVINT_TYP GET_GETVINT_LOC GET_GETVINT_CON GET_GETVINT_RET

: : : :

[Statement [Statement [Statement [Statement

-> -> -> ->

Identifier]; Identifier]; Identifier]; Identifier];

Induction Rule of Statement

dec IndStat : !(P : [Statement -> Prop]) [@(P, NULL) -> @(P, EXIT) -> @(P, RETURN) -> !(e : Expression) @(P, @(RETURNE, e)) -> !(i : Variable, e : Expression) @(P, @(ASSIGNMENT, i, e)) -> !(e : Expression, s : Statement) @(P, @(IFTHEN, e, s)) -> !(e : Expression, s1 : Statement, s2 : Statement) @(P, @(IFTHEL, e, s1, s2)) -> !(e : Expression, s : Statement) @(P, @(WHILE, e, s)) -> !(s1 : Statement, s2 : Statement) @(P, @(SEQ, s1, s2)) -> !(i : Identifier, s : Statement) @(P, @(LABEL, i, s)) -> !(e : Expression, s : Statement) @(P, @(WITH, e, s)) -> !(f : Expression, l : Expr_list) @(P, @(CALL, f, l)) -> !(i : Identifier, e1 : Expression, e2 : Expression, s : Statement) @(P, @(FORTO, i, e1, e2, s)) -> !(i : Identifier, e1 : Expression, e2 : Expression, s : Statement) @(P, @(FORDOWN, i, e1, e2, s)) -> !(e : Expression, s : Statement) @(P, @(REPEAT, e, s)) -> !(s : Statement) @(P, @(LOOP, s)) -> !(t : Type_Decl, d : Declaration, p : Proc, s : Statement) @(P, @(BLOCK, t, d, p, s)) -> !(i : Identifier, t : Type_Elem) @(P, @(NEWSTAT, i, t)) -> !(i : Identifier) @(P, @(DEPOSE, i)) -> !(s : Statement) @(P, s)];

4.5 4.5.1

Programs Type Definition of Program

def Program = !(T : Prop) [[Statement -> T] -> T];

CHAPTER 4. THE PROGRAMMING LANGUAGE C-VMK - SYNTAX 70

4.5.2

Constructor of Program

def PROG = \(p : Statement) \(T : Prop) \(b : [Statement -> T]) @(b, p); dec ERR_PROG : Program;

4.5.3

Project Function

def GET_PROG_BLOC = \(p : Program) @(p, Statement, \(b : Statement) b);

Chapter 5

The Environments and Continuations 5.1 5.1.1

The Environments Denotable Values

def KEval = KSval; dec ERR_KEVAL : KEval; dec VMKCont : Prop; dec ERR_KCONT : VMKCont; dec KProc_dval : Prop; dec ERR_KPROC_DVAL : KProc_dval; def VMKEont = [KEval -> VMKCont]; def KDval = @(Or30, KEval, VMKCont, KProc_dval); def MkEvalDval = \(e : KEval) @(INJ301, KEval, VMKCont, KProc_dval, e); def MkContDval = \(c : VMKCont) @(INJ302, KEval, VMKCont, KProc_dval, c);

71

CHAPTER 5. THE ENVIRONMENTS AND CONTINUATIONS

def MkProcDval = \(p : KProc_dval) @(INJ303, KEval, VMKCont, KProc_dval, p); def GetEval4Dval = \(dv : KDval) @(WHEN3, KEval, VMKCont, KProc_dval, KEval, dv, \(a1 : KEval) a1, \(a2 : VMKCont) ERR_KEVAL, \(a3 : KProc_dval) ERR_KEVAL); def GetCont4Dval = \(dv : KDval) @(WHEN3, KEval, VMKCont, KProc_dval, VMKCont, dv, \(a1 : KEval) ERR_KCONT, \(a2 : VMKCont) a2, \(a3 : KProc_dval) ERR_KCONT); def GetProc4Dval = \(dv : KDval) @(WHEN3, KEval, VMKCont, KProc_dval, KProc_dval, dv, \(a1 : KEval) ERR_KPROC_DVAL, \(a2 : VMKCont) ERR_KPROC_DVAL, \(a3 : KProc_dval) a3); dec IsEval4Dval : [KDval -> Bool]; dec IsCont4Dval : [KDval -> Bool]; dec IsProc4Dval : [KDval -> Bool]; dec ERR_KDVAL : KDval;

72

CHAPTER 5. THE ENVIRONMENTS AND CONTINUATIONS

dec KDVAL_EQ : [KDval -> KDval -> Bool];

5.1.2

The Definition of Environment

def KEnv = [Identifier -> KDval]; dec KENV_EQ : [KEnv -> KEnv -> Bool]; dec IDEN_EQ : [Identifier -> Identifier -> Bool]; dec GET_KEVAL : [KDval -> KEval]; dec GET_KCONT : [KDval -> VMKCont]; dec GET_KPROCDVAL : [KDval -> KProc_dval];

5.1.3

Constructors of Environment

dec EMPTY_KENV : KEnv; def ENTER_KENV = \(r : KEnv, i : Identifier, t : KDval) \(j : Identifier) @(GIF_THEN_ELSE2, KDval, @(KENV_EQ, r, EMPTY_KENV), ERR_KDVAL, @(GIF_THEN_ELSE2, KDval, @(IDEN_EQ, i, j), t, @(r, j)));

5.1.4

Auxiliary Constructors of Environment

def ENTER_LOC_KENV = \(r : KEnv, i : Identifier, t : KEval) \(j : Identifier) @(GIF_THEN_ELSE2, KDval, @(KENV_EQ, r, EMPTY_KENV), @(INJ301, KEval, VMKCont, KProc_dval, ERR_KSVAL), @(GIF_THEN_ELSE2,

73

CHAPTER 5. THE ENVIRONMENTS AND CONTINUATIONS

KDval, @(IDEN_EQ, i, j), @(INJ301, KEval, VMKCont, KProc_dval, t), @(r, j))); def ENTER_CON_KENV = \(r : KEnv, i : Identifier, t : VMKCont) \(j : Identifier) @(GIF_THEN_ELSE2, KDval, @(KENV_EQ, r, EMPTY_KENV), @(INJ302, KEval, VMKCont, KProc_dval, ERR_KCONT), @(GIF_THEN_ELSE2, KDval, @(IDEN_EQ, i, j), @(INJ302, KEval, VMKCont, KProc_dval, t), @(r, j))); def ENTER_PRO_KENV = \(r : KEnv, i : Identifier, t : KProc_dval) \(j : Identifier) @(GIF_THEN_ELSE2, KDval, @(KENV_EQ, r, EMPTY_KENV), @(INJ303, KEval, VMKCont, KProc_dval, ERR_KPROC_DVAL), @(GIF_THEN_ELSE2, KDval, @(IDEN_EQ, i, j), @(INJ303, KEval, VMKCont, KProc_dval, t), @(r, j))); def COMP_KENV = \(r1 : KEnv, r2 : KEnv) \(i : Identifier) let l = @(r2, i) in @(GIF_THEN_ELSE2, KDval, @(KDVAL_EQ, l, ERR_KDVAL), @(r2, i), @(r1, i)); dec ERR_KENV : KEnv;

5.1.5

Predicate Functions of Environment

def IS_IN_KENV =

74

CHAPTER 5. THE ENVIRONMENTS AND CONTINUATIONS

\(r : KEnv, i : Identifier) let t = @(r, i) in @(GIF_THEN_ELSE2, Bool, @(KDVAL_EQ, t, ERR_KDVAL), FF, TT); dec IS_EMPTY_KENV : [KEnv -> Bool];

5.1.6

Selection Functions of Environment

dec GET_KENV_IDN : [KEnv -> Identifier]; dec GET_KENV_ELM : [KEnv -> KDval]; dec GET_KENV_ENV : [KEnv -> KEnv]; dec KENV_LENGTH : [KEnv -> Nat];

5.2 5.2.1

The Type Environments The Definition of KTypeEnv

dec Type_Elem : Prop; dec ERR_TYPE_ELEM : Type_Elem; dec EQ_TYPE_ELEM : [Type_Elem -> Type_Elem -> Bool]; def KTypeEnv = [Identifier -> Type_Elem]; dec KTENV_EQ : [KTypeEnv -> KTypeEnv -> Bool]; dec IDEN_EQ : [Identifier -> Identifier -> Bool];

5.2.2

Constructors of KTypeEnv

dec EMPTY_KTENV : KTypeEnv; def ENTER_KTENV = \(r : KTypeEnv, i : Identifier, t : Type_Elem) \(j : Identifier)

75

CHAPTER 5. THE ENVIRONMENTS AND CONTINUATIONS

@(GIF_THEN_ELSE, Type_Elem, @(KTENV_EQ, r, EMPTY_KTENV), ERR_TYPE_ELEM, @(GIF_THEN_ELSE, Type_Elem, @(IDEN_EQ, i, j), t, @(r, j))); def COMP_KTENV = \(r1 : KTypeEnv, r2 : KTypeEnv) \(i : Identifier) let l = @(r2, i) in @(GIF_THEN_ELSE, Type_Elem, @(EQ_TYPE_ELEM, l, ERR_TYPE_ELEM), @(r2, i), @(r1, i)); dec ERR_KTENV : KTypeEnv;

5.2.3

Predicate Function of KTypeEnv

def IS_IN_KTENV = \(r : KTypeEnv, i : Identifier) let t = @(r, i) in @(GIF_THEN_ELSE, Bool, @(EQ_TYPE_ELEM, t, ERR_TYPE_ELEM), FF, TT);

5.3 5.3.1

The Continuations The Definition of VMKCont

def VMKCont = [VMKState -> VMKState]; dec NULL_VMKCONT : VMKCont; dec ERR_VMKCONT : VMKCont;

76

CHAPTER 5. THE ENVIRONMENTS AND CONTINUATIONS

dec EQ_VMKCONT : [VMKCont -> VMKCont -> Bool]; def KEval = KSval; def VMKDont = [KEnv -> VMKCont]; def VMKTont = [KTypeEnv -> VMKCont]; def VMKEont = [KEval -> VMKCont]; dec ERR_VMKCONT : VMKCont; dec ERR_VMKEONT : VMKEont; dec ERR_VMKDONT : VMKDont; dec EXCP_VMKCONT : [KEnv -> VMKCont]; dec EXCP_VMKDONT : [KEnv -> VMKCont]; dec EXCP_VMKEONT : [KEval -> KEnv -> VMKCont]; def EXCP_VMKDONT = \(r : KEnv) @(EXCP_VMKCONT, r); def EXCP_VMKEONT = \(e : KEval, r : KEnv) @(EXCP_VMKCONT, r);

5.3.2

Other Semantic Entities

def Procedure = [KEnv -> VMKCont -> Expr_list -> VMKCont]; def Function = [KEnv -> VMKEont -> Expr_list -> VMKCont]; def Thunk = [VMKEont -> VMKCont]; def Text = Expression; def Denotation = [KEnv -> VMKEont -> VMKCont]; def KProc_dval = @(Or5, Procedure, Function, Thunk, Text, Denotation); dec ERR_KPROC_DVAL : KProc_dval;

77

Chapter 6

Manager of VMK 6.1 6.1.1

Interrupt Control Blocks of VMK Type Definition of VMKIntCB

def VMKIntCB = KSval;

6.1.2

Constructor of VMKIntCB

dec MkVMKIntCB : [Identifier -> Bool -> Bool -> VMKCont -> VMKIntCB]; dec dec dec dec

VMKIntCB_NUMB_ID VMKIntCB_MASK_ID VMKIntCB_FIRE_ID VMKIntCB_CONT_ID

: : : :

Identifier; Identifier; Identifier; Identifier;

dec ERR_VMKIntCB : VMKIntCB;

6.1.3 dec dec dec dec

Selectors of VMKIntCB GET_VMKIntCB_NUMB GET_VMKIntCB_MASK GET_VMKIntCB_FIRE GET_VMKIntCB_CONT

: : : :

[VMKIntCB [VMKIntCB [VMKIntCB [VMKIntCB

-> -> -> ->

78

Identifier]; Bool]; Bool]; VMKCont];

CHAPTER 6. MANAGER OF VMK

6.1.4 dec dec dec dec

6.2 6.2.1

79

Modifiers of VMKIntCB SET_VMKIntCB_NUMB SET_VMKIntCB_MASK SET_VMKIntCB_FIRE SET_VMKIntCB_CONT

: : : :

[VMKIntCB [VMKIntCB [VMKIntCB [VMKIntCB

-> -> -> ->

Identifier Bool Bool VMKCont

Health Manager Health Management Type

def HMType = Nat; dec HM_NULL : HMType; dec dec dec dec dec dec

HM_VINT_ISR HM_VINT_SYSCALL HM_VINT_VIRET HM_VINT_EXCEPTION HM_EXCEPTION HM_ERROR_ACTION

dec dec dec dec dec dec

IS_HM_VINT_ISR IS_HM_VINT_SYSCALL IS_HM_VINT_VIRET IS_HM_VINT_EXCEPTION IS_HM_EXCEPTION IS_HM_ERROR_ACTION

6.2.2

: : : : : :

HMType; HMType; HMType; HMType; HMType; HMType; : : : : : :

[HMType [HMType [HMType [HMType [HMType [HMType

-> -> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool]; Bool];

Actions of Health Manager

def HMAction = Nat; dec HM_ACTION_NULL : HMAction; dec dec dec dec dec

HM_ACTION_RESET HM_ACTION_SHUTDOWN HM_ACTION_IGNORE HM_ACTION_UPGRADE HM_ACTION_DELIVER

dec IS_HM_ACT_RESET

: : : : :

HMAction; HMAction; HMAction; HMAction; HMAction;

: [HMAction -> Bool];

-> -> -> ->

VMKIntCB]; VMKIntCB]; VMKIntCB]; VMKIntCB];

CHAPTER 6. MANAGER OF VMK

dec dec dec dec

6.2.3

IS_HM_ACT_SHUTDOWN IS_HM_ACT_IGNORE IS_HM_ACT_UPGRADE IS_HM_ACT_DELIVER

: : : :

[HMAction [HMAction [HMAction [HMAction

80

-> -> -> ->

Bool]; Bool]; Bool]; Bool];

Exception Handling Contnuation

def ExcpCont = KSval; dec MkExcpCont : [Nat -> VMKCont -> ExcpCont]; dec GetExcpContNumb : [ExcpCont -> Nat]; dec GetExcpContCont : [ExcpCont -> VMKCont]; dec NullExcpCont : ExcpCont;

6.3 6.3.1

Manager of VMK Status of VMK

def SVMKStatus = KSval; def def def def def

6.3.2

MkColdStart MkWarmStart MkNormal MkFault MkShutdown

= = = = =

@(KNVAL, @(KNVAL, @(KNVAL, @(KNVAL, @(KNVAL,

OO); II); I2); I3); I4)

Definition of Priority VM Queue

dec IntDispatchTable : Prop; def IntDispatchTable = MList; dec VMK_PRIORITY_NUMBER : Nat; dec CURRENT_VM_NAME : Identifier; def PriorityVMQueue = KSval; dec PVMQ_ARRAY_ID

: Identifier;

CHAPTER 6. MANAGER OF VMK

dec PVMQ_MNUMB_ID

: Identifier;

def MK_PVMQ = \(array : KSval, n : Nat) @(KRVAL, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, EMPTY_KENV, PVMQ_ARRAY_ID, array), PVMQ_MNUMB_ID, @(KNVAL, n))); dec GET_PVMQ_ARRAY : [PriorityVMQueue -> Array]; dec GET_PVMQ_MNUMB : [PriorityVMQueue -> Nat]; def GET_PVMQ_ARRAY = \(q : PriorityVMQueue) let r = @(GET_KRVAL, q) in @(GET_KAVAL, @(GET_KEVAL, @(r, PVMQ_ARRAY_ID))); def GET_PVMQ_MNUMB = \(q : PriorityVMQueue) let r = @(GET_KRVAL, q) in @(GET_KNVAL, @(GET_KEVAL, @(r, PVMQ_MNUMB_ID))); dec SET_PVMQ_ARRAY : [PriorityVMQueue -> Array -> PriorityVMQueue]; dec SET_PVMQ_MNUMB : [PriorityVMQueue -> Nat -> PriorityVMQueue]; def SET_PVMQ_ARRAY = \(q : PriorityVMQueue, array : Array) let r = @(GET_KRVAL, q) in let nr = @(ENTER_KENV, r, PVMQ_ARRAY_ID, @(MkEvalDval, @(KAVAL, array))) in @(KRVAL, nr); def SET_PVMQ_MNUMB = \(q : PriorityVMQueue, numb : Nat) let r = @(GET_KRVAL, q) in let nr = @(ENTER_KENV, r, PVMQ_MNUMB_ID, @(MkEvalDval, @(KNVAL, numb))) in @(KRVAL, nr);

81

CHAPTER 6. MANAGER OF VMK

6.3.3

Type Definition of VMKManager

The VMKManager is defined as a record in terms of object-language. def VMKManager = KSval;

6.3.4

Constructor of VMKManager

dec MkVMKManager : [SVMKStatus -> Nat -> VMKLocation -> VMKLocation -> VMKLocation -> VMKLocation -> IntDispatchTable -> VMKLocation -> MList -> MList -> MList -> MList -> PriorityVMQueue -> Nat -> Nat -> MList -> MList -> VMKCont -> VMKMemoIndex -> MList -> VMKManager]; dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec

VMKMAN_STATUS_ID VMKMAN_TICKCN_ID VMKMAN_RUNVM_ID VMKMAN_TTSVM_ID VMKMAN_PQUEVM_ID VMKMAN_IDLEVM_ID VMKMAN_INTDIS_ID VMKMAN_CURTTS_ID VMKMAN_TTSLST_ID VMKMAN_VMLIST_ID VMKMAN_TICKWT_ID VMKMAN_EXCPVM_ID VMKMAN_PRIOTQ_ID VMKMAN_VMNUMB_ID VMKMAN_TTSNUM_ID

: : : : : : : : : : : : : : :

Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier;

82

CHAPTER 6. MANAGER OF VMK

dec dec dec dec dec

VMKMAN_INTCBL_ID VMKMAN_EXINTL_ID VMKMAN_CONTXT_ID VMKMAN_MEMIDX_ID VMKMAN_FLOWLT_ID

: : : : :

Identifier; Identifier; Identifier; Identifier; Identifier;

def MkVMKManager = \(status : SVMKStatus, tick_numb : Nat, runvm_loc : VMKLocation, ttsvm_loc : VMKLocation, pqvm_loc : VMKLocation, idlevm_loc : VMKLocation, intdistable : IntDispatchTable, curvm_loc : VMKLocation, ttsvm_list : MList, vm_list : MList, tickwtvm_list : MList, excpvm_list : MList, priorityvmq : PriorityVMQueue, vm_numb : Nat, tts_numb : Nat, intcb_list : MList, exintcb_list : MList, context : VMKCont, seg_index : VMKMemoIndex, flow_list : MList) @(KRVAL, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV,

83

CHAPTER 6. MANAGER OF VMK

@(ENTER_LOC_KENV, EMPTY_KENV, VMKMAN_STATUS_ID, status), VMKMAN_TICKCN_ID, @(KNVAL, tick_numb)), VMKMAN_RUNVM_ID, @(KLVAL, runvm_loc)), VMKMAN_TTSVM_ID, @(KLVAL, ttsvm_loc)), VMKMAN_PQUEVM_ID, @(KLVAL, pqvm_loc)), VMKMAN_IDLEVM_ID, @(KLVAL, idlevm_loc)), VMKMAN_INTDIS_ID, intdistable), VMKMAN_CURTTS_ID, @(KLVAL, curvm_loc)), VMKMAN_TTSLST_ID, ttsvm_list), VMKMAN_VMLIST_ID, vm_list), VMKMAN_TICKWT_ID, tickwtvm_list), VMKMAN_EXCPVM_ID, excpvm_list), VMKMAN_PRIOTQ_ID, priorityvmq), VMKMAN_VMNUMB_ID, @(KNVAL, vm_numb)), VMKMAN_TTSNUM_ID, @(KNVAL, tts_numb)), VMKMAN_INTCBL_ID, intcb_list), VMKMAN_EXINTL_ID, exintcb_list), VMKMAN_CONTXT_ID, @(KCVAL, context)), VMKMAN_MEMIDX_ID, @(KNVAL, seg_index)), VMKMAN_FLOWLT_ID, flow_list)); dec INIT_VMKMAN : KSval; dec ERR_VMKMAN : VMKManager;

84

CHAPTER 6. MANAGER OF VMK

6.3.5 dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec

85

Selectors of VMKManager GET_VMKMAN_STATUS GET_VMKMAN_TICKCN GET_VMKMAN_RUNVM GET_VMKMAN_TTSVM GET_VMKMAN_PQUEVM GET_VMKMAN_IDLEVM GET_VMKMAN_INTDIS GET_VMKMAN_CURTTS GET_VMKMAN_TTSLST GET_VMKMAN_VMLIST GET_VMKMAN_TICKWT GET_VMKMAN_EXCPVM GET_VMKMAN_PRIOTQ GET_VMKMAN_VMNUMB GET_VMKMAN_TTSNUM GET_VMKMAN_INTCBL GET_VMKMAN_EXINTL GET_VMKMAN_CONTXT GET_VMKMAN_MEMIDX GET_VMKMAN_FLOWLT

: : : : : : : : : : : : : : : : : : : :

[VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager

-> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> ->

SVMKStatus]; Nat]; VMKLocation]; VMKLocation]; VMKLocation]; VMKLocation]; IntDispatchTable]; VMKLocation]; MList]; MList]; MList]; MList]; PriorityVMQueue]; Nat]; Nat]; MList]; MList]; VMKCont]; VMKMemoIndex]; MList];

def GET_VMKMAN_STATUS = \(vmk_manager : VMKManager) let r = @(GET_KRVAL, vmk_manager) in @(GET_KEVAL, @(r, VMKMAN_STATUS_ID));

6.3.6 dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec

Modifiers of VMKManager SET_VMKMAN_STATUS SET_VMKMAN_TICKCN SET_VMKMAN_RUNVM SET_VMKMAN_TTSVM SET_VMKMAN_PQUEVM SET_VMKMAN_IDLEVM SET_VMKMAN_INTDIS SET_VMKMAN_CURTTS SET_VMKMAN_TTSLST SET_VMKMAN_VMLIST SET_VMKMAN_TICKWT SET_VMKMAN_EXCPVM SET_VMKMAN_PRIOTQ SET_VMKMAN_VMNUMB SET_VMKMAN_TTSNUM SET_VMKMAN_INTCBL

: : : : : : : : : : : : : : : :

[VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager [VMKManager

-> -> -> -> -> -> -> -> -> -> -> -> -> -> -> ->

SVMKStatus Nat VMKLocation VMKLocation VMKLocation VMKLocation IntDispatchTable VMKLocation MList MList MList MList PriorityVMQueue Nat Nat MList

-> -> -> -> -> -> -> -> -> -> -> -> -> -> -> ->

VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager]; VMKManager];

CHAPTER 6. MANAGER OF VMK

dec dec dec dec

SET_VMKMAN_EXINTL SET_VMKMAN_CONTXT SET_VMKMAN_MEMIDX SET_VMKMAN_FLOWLT

: : : :

[VMKManager [VMKManager [VMKManager [VMKManager

-> -> -> ->

86

MList VMKCont VMKMemoIndex MList

-> -> -> ->

VMKManager]; VMKManager]; VMKManager]; VMKManager];

def SET_VMKMAN_STATUS = \(vmk_manager : VMKManager, status : SVMKStatus) let r = @(GET_KRVAL, vmk_manager) in let nr = @(ENTER_KENV, r, VMKMAN_STATUS_ID, @(MkEvalDval, status)) in @(KRVAL, nr);

Chapter 7

VM Control Blocks 7.1 7.1.1

Virtual Interrupt Control Blocks of VMs When Virtual Interrupt Delivered

There are three cases for delivery of virtual interrupts: 1. The returning from external interrupt handler to VM. 2. The returning from system service call to VM. 3. The returning from exception handler to VM. Before returning to VM from the external interrupt handlers, the system service calls and exception handlers, if there is virtual interrupts needed to be delivered, then the current context and virtual interrupt will be saved in the current stack of VM, the virtual interrupt service routine in the VMCB will be invoked for processing of corresponding virtual interrupts. To return from the virtual ISRs, the system service call VMK Vint will be invoked, it will cause the execution return to the point of program being interrupted. For exceptions, there is a need to invoke VMK AckException for acknowledging the system that an exception has been handled already after the exception handling has completed its execution. def VIntType = KSval; def def def def

VTickIntType VExcpIntType VExtrIntType VServIntType

= = = =

@(KNVAL, @(KNVAL, @(KNVAL, @(KNVAL,

OO); II); I2); I3);

87

CHAPTER 7. VM CONTROL BLOCKS

7.1.2

88

Tick Interrupt Control Blocks

def VMVTickIntCB = KSval; dec MkVMVTickIntCB : [Bool -> Bool -> Nat -> VMKCont -> VMVTickIntCB]; dec dec dec dec

GetVMVTIntCBGMsk GetVMVTIntCBMask GetVMVTIntCBFire GetVMVTIntCBHand

: : : :

[VMVTickIntCB [VMVTickIntCB [VMVTickIntCB [VMVTickIntCB

-> -> -> ->

Bool]; Bool]; Nat]; VMKCont];

dec dec dec dec

SetVMVTIntCBGMsk SetVMVTIntCBMask SetVMVTIntCBFire SetVMVTIntCBHand

: : : :

[VMVTickIntCB [VMVTickIntCB [VMVTickIntCB [VMVTickIntCB

-> -> -> ->

Bool Bool Nat VMKCont

7.1.3

-> -> -> ->

VMVTickIntCB]; VMVTickIntCB]; VMVTickIntCB]; VMVTickIntCB];

Other Interrupt Control Blocks

def VMVIntCB = KSval; dec MkVMVIntCB : [Bool -> Bool -> Bool -> VMKCont -> VMVIntCB]; dec dec dec dec

GetVMVIntCBGMsk GetVMVIntCBMask GetVMVIntCBFire GetVMVIntCBHand

: : : :

[VMVIntCB [VMVIntCB [VMVIntCB [VMVIntCB

-> -> -> ->

Bool]; Bool]; Bool]; VMKCont];

dec dec dec dec

SetVMVIntCBGMsk SetVMVIntCBMask SetVMVIntCBFire SetVMVIntCBHand

: : : :

[VMVIntCB [VMVIntCB [VMVIntCB [VMVIntCB

-> -> -> ->

Bool Bool Bool VMKCont

-> -> -> ->

VMVIntCB]; VMVIntCB]; VMVIntCB]; VMVIntCB];

def VMVIntCBList = MList; dec IS_IN_INT_LIST : [VMKLocation -> MList -> VMKState -> Bool]; def VMVIntCBlock = KSval; dec MkVMVIntCBlock : [Bool -> Nat -> VMKLocation -> VMVIntCBList -> VMVIntCBList -> VMVIntCBList ->

CHAPTER 7. VM CONTROL BLOCKS

89

VMVIntCBlock]; dec dec dec dec dec dec

GetVMVIntInit GetVMVIntExcpNum GetVMVIntTickCB GetVMVIntExcpCB GetVMVIntExtrCB GetVMVIntServCB

: : : : : :

[VMVIntCBlock [VMVIntCBlock [VMVIntCBlock [VMVIntCBlock [VMVIntCBlock [VMVIntCBlock

-> -> -> -> -> ->

Bool]; Nat]; VMKLocation]; VMVIntCBList]; VMVIntCBList]; VMVIntCBList];

dec SetVMVIntInit dec SetVMVIntExcpNum dec SetVMVIntTickCB dec SetVMVIntExcpCB dec SetVMVIntExtrCB dec SetVMVIntServCB VMVIntCBlock];

: : : : : :

[VMVIntCBlock [VMVIntCBlock [VMVIntCBlock [VMVIntCBlock [VMVIntCBlock [VMVIntCBlock

-> -> -> -> -> ->

Bool Nat VMKLocation VMVIntCBList VMVIntCBList VMVIntCBList

7.2

Status of VMs

def VMStatus = KSval; dec dec dec dec dec dec dec

VMREADY VMSLEEP VMRUNNING VMSUSPEND VMWAIT VMFIRSTRUN VMDEBUG

: : : : : : :

VMStatus; VMStatus; VMStatus; VMStatus; VMStatus; VMStatus; VMStatus;

def def def def def def def

VMREADY VMSLEEP VMRUNNING VMSUSPEND VMWAIT VMFIRSTRUN VMDEBUG

= = = = = = =

@(KWVAL, @(KWVAL, @(KWVAL, @(KWVAL, @(KWVAL, @(KWVAL, @(KWVAL,

dec dec dec dec dec dec dec

IS_VMREADY IS_VMSLEEP IS_VMRUNNING IS_VMSUSPEND IS_VMWAIT IS_VMFIRSTRUN IS_VMDEBUG

dec SetVMREADY

: : : : : : :

Ox01); Ox02); Ox04); Ox08); Ox10); Ox20); Ox40);

[VMStatus [VMStatus [VMStatus [VMStatus [VMStatus [VMStatus [VMStatus

-> -> -> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool]; Bool]; Bool];

: [VMStatus -> VMStatus];

-> -> -> -> -> ->

VMVIntCBlock]; VMVIntCBlock]; VMVIntCBlock]; VMVIntCBlock]; VMVIntCBlock];

CHAPTER 7. VM CONTROL BLOCKS

dec dec dec dec dec dec

SetVMSLEEP SetVMRUNNING SetVMSUSPEND SetVMWAIT SetVMFIRSTRUN SetVMDEBUG

: : : : : :

[VMStatus [VMStatus [VMStatus [VMStatus [VMStatus [VMStatus

dec dec dec dec dec dec dec

SetVMNotREADY SetVMNotSLEEP SetVMNotRUNNING SetVMNotSUSPEND SetVMNotWAIT SetVMNotFIRSTRUN SetVMNotDEBUG

: : : : : : :

-> -> -> -> -> ->

[VMStatus [VMStatus [VMStatus [VMStatus [VMStatus [VMStatus [VMStatus

VMStatus]; VMStatus]; VMStatus]; VMStatus]; VMStatus]; VMStatus]; -> -> -> -> -> -> ->

VMStatus]; VMStatus]; VMStatus]; VMStatus]; VMStatus]; VMStatus]; VMStatus];

dec InclOrVMStatus : [VMStatus -> VMStatus -> VMStatus]; dec BitAndVMStatus : [VMStatus -> VMStatus -> VMStatus];

7.3 7.3.1

VM Control Blocks Scheduling Type of VMs

def VMScheduleType = Bool; def VMScheduleTT = TT; def VMSchedulePr = FF; dec IsVMScheduleTT : [VMScheduleType -> Bool]; dec IsVMSchedulePr : [VMScheduleType -> Bool];

7.3.2

VM Wakeup Type

def VMWakeupType = Bit16Word; dec dec dec dec dec

VMWUNull VMWUBasic VMWUTimed VMWUTTSWin VMWUTTSStart

: : : : :

VMWakeupType; VMWakeupType; VMWakeupType; VMWakeupType; VMWakeupType;

def VMWUNull = Ox00;

90

CHAPTER 7. VM CONTROL BLOCKS

91

dec dec dec dec dec

IS_VMWUNull IS_VMWUBasic IS_VMWUTimed IS_VMWUTTSWin IS_VMWUTTSStart

: : : : :

[VMWakeupType [VMWakeupType [VMWakeupType [VMWakeupType [VMWakeupType

-> -> -> -> ->

Bool]; Bool]; Bool]; Bool]; Bool];

dec dec dec dec dec

SetVMWUNull SetVMWUBasic SetVMWUTimed SetVMWUTTSWin SetVMWUTTSStart

: : : : :

[VMWakeupType [VMWakeupType [VMWakeupType [VMWakeupType [VMWakeupType

-> -> -> -> ->

VMWakeupType]; VMWakeupType]; VMWakeupType]; VMWakeupType]; VMWakeupType];

dec InclOrWUType : [VMWakeupType -> VMWakeupType -> VMWakeupType]; def InclOrWUType = \(type1 : VMWakeupType, type2 : VMWakeupType) @(ORBit16Word, type1, type2);

7.3.3

Other Utilities for VMs

def VMPriority = Nat; def VMResetCont = VMKCont; def def def def def

VMTickUsage VMTickSliceSize VMTickSlice VMWaitedTicks VMLeaveTicks

= = = = =

Nat; Nat; Nat; Nat; Nat;

def ExportVarList = MList;

7.3.4

Type Definition of VMCB

def VMCB = KSval;

7.3.5

Constructor of VMCB

dec MkVMCB : [Identifier -> VMStatus ->

CHAPTER 7. VM CONTROL BLOCKS

VMScheduleType -> VMWakeupType -> VMPriority -> VMKCont -> VMTickUsage -> VMTickSliceSize -> VMTickSlice -> VMWaitedTicks -> VMLeaveTicks -> VMVIntCBlock -> VMKCont -> ExcpCont -> HMType -> VMKMemoIndex -> ExportVarList -> VMCB]; dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec

VMCBNameId VMCBStatusId VMCBSchedTypeId VMCBWakeTypeId VMCBPriorityId VMCBResetContId VMCBTickUsageId VMCBTickSlSizId VMCBTickSliceId VMCBWaitTickId VMCBLeaveTickId VMCBVIntCBlckId VMCBIntContxtId VMCBHmContxtId VMCBHmTypeId VMCBMemoIndexId ExportVarListId

: : : : : : : : : : : : : : : : :

def MkVMCB = \(vmcb_name vm_status vm_sched_type vm_wakeup_type vm_priority vm_resetcontext vm_tick_usage vm_tickslicesize vm_tickslice vm_waitedtick vm_leavetick

Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier; Identifier;

: : : : : : : : : : :

Identifier, VMStatus, VMScheduleType, VMWakeupType, VMPriority, VMKCont, VMTickUsage, VMTickSliceSize, VMTickSlice, VMWaitedTicks, VMLeaveTicks,

92

CHAPTER 7. VM CONTROL BLOCKS

vm_intcblock : VMVIntCBlock, vm_context : VMKCont, vm_except_cont : ExcpCont, vm_hm_type : HMType, vm_memo_index : VMKMemoIndex, vm_export_vars : ExportVarList) @(KRVAL, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, @(ENTER_LOC_KENV, EMPTY_KENV, VMCBNameId, @(KTVAL, vmcb_name)), VMCBStatusId, vm_status), VMCBSchedTypeId, @(KBVAL, vm_sched_type)), VMCBWakeTypeId, @(KWVAL, vm_wakeup_type)), VMCBPriorityId, @(KNVAL, vm_priority)), VMCBResetContId, @(KCVAL, vm_resetcontext)), VMCBTickUsageId, @(KNVAL, vm_tick_usage)), VMCBTickSlSizId, @(KNVAL, vm_tickslicesize)), VMCBTickSliceId, @(KNVAL, vm_tickslice)), VMCBWaitTickId, @(KNVAL, vm_waitedtick)), VMCBLeaveTickId, @(KNVAL, vm_leavetick)),

93

CHAPTER 7. VM CONTROL BLOCKS

94

VMCBVIntCBlckId, vm_intcblock), VMCBIntContxtId, @(KCVAL, vm_context)), VMCBHmContxtId, vm_except_cont), VMCBHmTypeId, @(KNVAL, vm_hm_type)), VMCBMemoIndexId, @(KNVAL, vm_memo_index)), ExportVarListId, vm_export_vars));

7.3.6 dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec dec

7.3.7 dec dec dec dec dec dec dec dec

Selectors of VMCB GetVMCBName GetVMCBStatus GetVMCBSchedType GetVMCBWakeType GetVMCBPriority GetVMCBResetCont GetVMCBTickUsage GetVMCBTickSlSiz GetVMCBTickSlice GetVMCBWaitTick GetVMCBLeaveTick GetVMCBVIntCBlck GetVMCBIntContxt GetVMCBHmContxt GetVMCBHmType GetVMCBMemoIndex GetVMCBExportVar

: : : : : : : : : : : : : : : : :

[VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB

-> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> ->

Identifier]; VMStatus]; VMScheduleType]; VMWakeupType]; VMPriority]; VMKCont]; VMTickUsage]; VMTickSliceSize]; VMTickSlice]; VMWaitedTicks]; VMLeaveTicks]; VMVIntCBlock]; VMKCont]; ExcpCont]; HMType]; VMKMemoIndex]; ExportVarList];

-> -> -> -> -> -> -> ->

Identifier VMStatus VMScheduleType VMWakeupType VMPriority VMKCont VMTickUsage VMTickSliceSize

Modifiers of VMCB SetVMCBName SetVMCBStatus SetVMCBSchedType SetVMCBWakeType SetVMCBPriority SetVMCBResetCont SetVMCBTickUsage SetVMCBTickSlSiz

: : : : : : : :

[VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB

-> -> -> -> -> -> -> ->

VMCB]; VMCB]; VMCB]; VMCB]; VMCB]; VMCB]; VMCB]; VMCB];

CHAPTER 7. VM CONTROL BLOCKS

dec dec dec dec dec dec dec dec dec

SetVMCBTickSlice SetVMCBWaitTick SetVMCBLeaveTick SetVMCBVIntCBlck SetVMCBIntContxt SetVMCBHmContxt SetVMCBHmType SetVMCBMemoIndex SetVMCBExportVar

: : : : : : : : :

[VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB [VMCB

-> -> -> -> -> -> -> -> ->

VMTickSlice VMWaitedTicks VMLeaveTicks VMVIntCBlock VMKCont ExcpCont HMType VMKMemoIndex ExportVarList

95

-> -> -> -> -> -> -> -> ->

VMCB]; VMCB]; VMCB]; VMCB]; VMCB]; VMCB]; VMCB]; VMCB]; VMCB];

dec GetVMVIntCB : [VMKState -> VMKLocation -> VMVIntCB]; dec SetVMVIntCB : [VMKState -> VMKLocation -> VMVIntCB -> VMKState]; dec GetVMVTickIntCB : [VMKState -> VMKLocation -> VMVTickIntCB]; dec SetVMVTickIntCB : [VMKState -> VMKLocation -> VMVTickIntCB -> VMKState];

Chapter 8

TTS Control Blocks 8.1

TTS Nodes

def TTSNode = KSval; dec MkTTSNode : [VMKLocation -> Nat -> Nat -> TTSNode]; dec GetTTSNodId : [TTSNode -> VMKLocation]; dec GetTTSNodStart : [TTSNode -> Nat]; dec GetTTSNodDuring : [TTSNode -> Nat]; dec SetTTSNodId : [TTSNode -> VMKLocation -> TTSNode]; dec SetTTSNodStart : [TTSNode -> Nat -> TTSNode]; dec SetTTSNodDuring : [TTSNode -> Nat -> TTSNode];

8.2

TTS Status Type

def TTSStatusType = Nat; dec dec dec dec dec

TTSIdle TTSRunning TTSWaitFrame TTSWaitStatus TTSAbort

: : : : :

dec IsTTSIdle dec IsTTSRunning dec IsTTSWaitFrame

TTSStatusType; TTSStatusType; TTSStatusType; TTSStatusType; TTSStatusType; : [TTSStatusType -> Bool]; : [TTSStatusType -> Bool]; : [TTSStatusType -> Bool];

96

CHAPTER 8. TTS CONTROL BLOCKS

dec IsTTSWaitStatus : [TTSStatusType -> Bool]; dec IsTTSAbort : [TTSStatusType -> Bool];

8.3

Tick Notify Type

def TickNotifyType = Bit16Word; dec VMK_WINDOWTICK : TickNotifyType; dec VMK_SYSTICK : TickNotifyType; dec VMK_FRAMETICK : TickNotifyType; def VMK_WINDOWTICK = Ox01; def VMK_SYSTICK = Ox02; def VMK_FRAMETICK = Ox04; dec IS_VMK_WINDOWTICK

: [TickNotifyType -> Bool];

def IS_VMK_WINDOWTICK = \(type : TickNotifyType) @(PJBit16Word0, type); dec IS_VMK_SYSTICK : [TickNotifyType -> Bool]; def IS_VMK_SYSTICK = \(type : TickNotifyType) @(PJBit16Word1, type); dec IS_VMK_FRAMETICK : [TickNotifyType -> Bool]; def IS_VMK_FRAMETICK = \(type : TickNotifyType) @(PJBit16Word2, type); dec SET_VMK_WINDOWTICK : [TickNotifyType -> TickNotifyType]; def SET_VMK_WINDOWTICK = \(type : TickNotifyType) @(STBit16Word0, type, TT); dec SET_VMK_SYSTICK : [TickNotifyType -> TickNotifyType]; def SET_VMK_SYSTICK = \(type : TickNotifyType) @(STBit16Word1, type, TT);

97

CHAPTER 8. TTS CONTROL BLOCKS

dec SET_VMK_FRAMETICK : [TickNotifyType -> TickNotifyType]; def SET_VMK_FRAMETICK = \(type : TickNotifyType) @(STBit16Word2, type, TT); dec InclTickNotifyType : [TickNotifyType -> TickNotifyType -> TickNotifyType]; def InclTickNotifyType = \(type1 : TickNotifyType, type2 : TickNotifyType) @(ORBit16Word, type1, type2);

8.4 8.4.1

TTS Control Blocks Type Definition of TTSCB

def TTSCB = KSval;

8.4.2

Constructor of TTSCB

dec MkTTSCB : [Identifier -> TTSStatusType -> Nat -> VMKLocation -> Nat -> Nat -> Nat -> Nat -> Nat -> Array -> TTSCB];

8.4.3 dec dec dec dec dec

Selectors of TTSCB GetTTSName GetTTSStatus GETTTSNodeMax GetTTSId GetTTSMFrameTick

: : : : :

[TTSCB [TTSCB [TTSCB [TTSCB [TTSCB

-> -> -> -> ->

Identifier]; TTSStatusType]; Nat]; VMKLocation]; Nat];

98

CHAPTER 8. TTS CONTROL BLOCKS

dec dec dec dec dec

8.4.4 dec dec dec dec dec dec dec dec dec dec

8.4.5

GetTTSWindowTick GetTTSFrameTick GetTTSFrames GetTTSCurrentWin GetTTSNodes

: : : : :

[TTSCB [TTSCB [TTSCB [TTSCB [TTSCB

-> -> -> -> ->

Nat]; Nat]; Nat]; Nat]; Array];

-> -> -> -> -> -> -> -> -> ->

Identifier TTSStatusType Nat VMKLocation Nat Nat Nat Nat Nat Array

99

Modifiers of TTSCB SetTTSName SetTTSStatus SETTTSNodeMax SetTTSId SetTTSMFrameTick SetTTSWindowTick SetTTSFrameTick SetTTSFrames SetTTSCurrentWin SetTTSNodes

: : : : : : : : : :

[TTSCB [TTSCB [TTSCB [TTSCB [TTSCB [TTSCB [TTSCB [TTSCB [TTSCB [TTSCB

-> -> -> -> -> -> -> -> -> ->

TTSCB]; TTSCB]; TTSCB]; TTSCB]; TTSCB]; TTSCB]; TTSCB]; TTSCB]; TTSCB]; TTSCB];

Other Operations on TTSCB

dec AssignTTSNodes : [Array -> Nat -> VMKState -> VMKLocation -> Array]; dec RetrieveTTSNodes : [Array -> Nat -> VMKState -> VMKLocation];

Chapter 9

The Configuration Management of VMK 9.1

Configuration of VMK

def VMKConfigTable = KSval; dec MkVMKConfigTable : [MList -> MList -> VMKLocation -> IntDispatchTable -> Nat -> MList -> Nat -> MList -> VMKCont -> VMKMemoIndex -> MList -> VMKConfigTable]; dec dec dec dec dec dec dec dec dec

GetVMKConfVMConf GetVMKConfTTSConf GetVMKConfAutoStr GetVMKConfIntTabl GetVMKConfVMNumb GetVMKConfVMTable GetVMKConfTTSNumb GetVMKConfTTSTable GetVMKConfVMKCont

: : : : : : : : :

[VMKConfigTable [VMKConfigTable [VMKConfigTable [VMKConfigTable [VMKConfigTable [VMKConfigTable [VMKConfigTable [VMKConfigTable [VMKConfigTable

100

-> -> -> -> -> -> -> -> ->

MList]; MList]; VMKLocation]; IntDispatchTable]; Nat]; MList]; Nat]; MList]; VMKCont];

CHAPTER 9. THE CONFIGURATION MANAGEMENT OF VMK

dec GetVMKConfVMKMIdx dec GetVMKConfFlowLst

101

: [VMKConfigTable -> VMKMemoIndex]; : [VMKConfigTable -> MList];

dec VMKCONF_GET : [VMKState -> VMKLocation -> VMKConfigTable]; dec VMKCONF_SET : [VMKState -> VMKLocation -> VMKConfigTable -> VMKState]; dec VMCONF_GET : [VMKState -> VMKLocation -> VMConfigTable]; dec VMCONF_SET : [VMKState -> VMKLocation -> VMConfigTable -> VMKState]; dec TTSCONF_GET : [VMKState -> VMKLocation -> TTSConfigTable]; dec TTSCONF_SET : [VMKState -> VMKLocation -> TTSConfigTable -> VMKState];

9.2

Configuration of VMs

There will be two way to config the VMK system. • Using configuration table for VMK, VMs and TTSs. • Using APIs for creating VMK, VMs and TTSs. For instance, we may have APIs such as VMKCreate, VMCreate and TTSCreate to create and configure the system statically. I rather prefer the second method which looks more elegant. But now let us try the first one. The configuration table should be defined as a data structure of the object language instead of treating it as an entity in meta-language. def IntMaskDef = KSval; dec MkIntMaskDef

: [VMKLocation -> Bool -> IntMaskDef];

dec GetIntMaskDefLoc : [IntMaskDef -> VMKLocation]; dec GetIntMaskDefMsk : [IntMaskDef -> Bool]; def IntMaskDefList = MList; def VMConfigTable = KSval; dec MkVMConfigTable : [Identifier ->

CHAPTER 9. THE CONFIGURATION MANAGEMENT OF VMK

VMPriority -> VMScheduleType -> Bool -> VMKCont -> IntMaskDef -> IntMaskDefList -> IntMaskDefList -> IntMaskDefList -> VMTickSliceSize -> VMKMemoIndex -> ExportVarList -> VMConfigTable]; dec dec dec dec dec dec dec dec dec dec dec dec

GetVMConfName GetVMConfPriority GetVMConfSchdType GetVMConfAutoStrt GetVMConfResetAdr GetVMConfTickMask GetVMConfExcpMask GetVMConfExtrMask GetVMConfServMask GetVMConfTSlcSize GetVMConfVMMemIdx GetVMConfExpVars

: : : : : : : : : : : :

[VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable [VMConfigTable

-> -> -> -> -> -> -> -> -> -> -> ->

Identifier]; VMPriority]; VMScheduleType]; Bool]; VMKCont]; IntMaskDef]; IntMaskDefList]; IntMaskDefList]; IntMaskDefList]; VMTickSliceSize]; VMKMemoIndex]; ExportVarList];

dec IDLE_VM_SLICE_SIZE : Nat; dec IDLE_VM_LOC : VMKLocation; dec IDLE_VM_IDX : VMKMemoIndex;

9.3

Configuration of TTS

def TTSConfigTable = KSval; dec MkTTSConfigTable : [Identifier -> Nat -> Nat -> Array -> TTSConfigTable]; dec dec dec dec

GetTTSConfName GetTTSConfNodeMax GetTTSConfMFrmTck GetTTSConfNodes

: : : :

[TTSConfigTable [TTSConfigTable [TTSConfigTable [TTSConfigTable

-> -> -> ->

Identifier]; Nat]; Nat]; Array];

102

Chapter 10

Semantics of Interrupt Handling and VM Scheduling 10.1

Interrupting Sequential Programs

The whole program considered together with operating system kernel and interrupt mechanism disabled can be viewed as a sequential program running from one step to another in a very deterministic way. However, when the interrupt mechanism is considered, the system is no longer a sequential program. The execution of each component might be interrupted and preempted by the external events. Therefore we need to develop a mechanism to model the situation. We will use the dataflow model to describe the concurrent semantics of interrupt-based programs. The external interrupts are treated as a stream of events. It will cause the system to suspend the current running VM, save its status, trigger the event handlers to manipulate the events and finally to schedule another VM as the running VM. We would like to keep the model as abstract as possible and don’t go to details as it has been done in[PM02, FSDG08].

10.2

Tick Interrupt Handling

The continuation function tickcont should be a function to deliver a tick interruption to all the VMs as the virtual interruptions. def VMK_EVAL_TIMER = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in

103

Interrupt Handling and VM Scheduling

let let let let

vmkticks = @(GET_VMKMAN_TICKCN, vmk_manager) in nvmkticks = @(SS, vmkticks) in tickintcb = @(INTCB_GET, nz, TICK_LOC) in ticknumb = @(GET_VMKIntCB_NUMB, tickintcb), tickmask = @(GET_VMKIntCB_MASK, tickintcb), tickfire = @(GET_VMKIntCB_FIRE, tickintcb), tickcont = @(GET_VMKIntCB_CONT, tickintcb) in let ntickintcb = @(MkVMKIntCB, ticknumb, FF, FF, tickcont), nvmk_manager = @(SET_VMKMAN_TICKCN, vmk_manager, nvmkticks) in let nz1 = @(INTCB_SET, nz, TICK_LOC, ntickintcb), nz2 = @(CHANGE, nz1, VMK_MANAGER_LOC, vmk_manager) in @(tickcont, nz2);

tickcont should be defined as VMTICK DELIVER. dec VMTICK_ACC : [VMKState -> VMKLocation -> VMKState]; def VMTICK_ACC = \(z : VMKState, l : VMKLocation) let vmcb = @(VMCB_GET, z, l) in let tick = @(GetVMCBTickUsage, vmcb) in let ntick = @(SS, tick) in let nvmcb = @(SetVMCBTickUsage, vmcb, ntick) in @(VMCB_SET, z, l, nvmcb); dec VMTICK_ACC_LIST : [VMKState -> MList -> VMKState]; def VMTICK_ACC_LIST = \(z : VMKState, l : MList) @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, l), z, let hl = @(MHEAD, l, z), tl = @(MTAIL, l, z) in let nz = @(VMTICK_ACC, z, @(GET_KLVAL, hl)) in @(VMTICK_ACC_LIST, nz, tl)); def VMTICK_DELIVER = \(z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let vmtable = @(GET_VMKMAN_VMLIST, vmk_manager) in @(VMTICK_ACC_LIST, z, vmtable)

104

Interrupt Handling and VM Scheduling

10.2.1

105

Stream of Ticks

def TickStream = @(Stream, Bool);

Assumption: When an interrupt occurs the context will be automatically saved in VMKManager.

10.2.2

Save Current Context in VMCB

The function VMK SAVE CONTEXT is used to save the current context in the control block of the current running VM. dec VMK_SAVE_CONTEXT : [VMKCont -> VMKCont]; def VMK_SAVE_CONTEXT = \(c : VMKCont, z : VMKState) let nz = @(SET_VMKST_IDX, z, VMK_MANAGER_IDX) in let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let old_vm = @(VMCB_GET, nz, old_vm_loc), new_vm = @(SetVMCBIntContxt, old_vm, c) in @(VMCB_SET, nz, old_vm_loc, new_vm);

10.2.3

Schedule Next VM

dec VMK_SCHEDULE : VMKCont;

10.2.4

Switch to New VM

dec VMK_SWITCH_CONTEXT : VMKCont; def VMK_SWITCH_CONTEXT = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, VMK_MANAGER_IDX) in let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let run_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let run_vm = @(VMCB_GET, nz, run_vm_loc) in let memoidx = @(GetVMCBMemoIndex, run_vm), context = @(GetVMCBIntContxt, run_vm) in let nz2 = @(SET_VMKST_IDX, nz, memoidx) in @(context, nz2);

Interrupt Handling and VM Scheduling

10.2.5

An Interrupt-Driven Model

1. Disable the interruption. 2. Save the current context in current VM. 3. Evaluation of timer. 4. Schedule the next VM. 5. Switch to new VM. 6. Enable the interruption. 7. Waiting for another interruption.

def TICK_SET = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, VMK_MANAGER_IDX) in let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_INTCBL, vmk_manager) in let tick_intcb = @(INTCB_GET, nz, TICK_LOC) in let ticknumb = @(GET_VMKIntCB_NUMB, tick_intcb), tickmask = @(GET_VMKIntCB_MASK, tick_intcb), tickfire = @(GET_VMKIntCB_FIRE, tick_intcb), tickcont = @(GET_VMKIntCB_CONT, tick_intcb) in @(GIF_THEN_ELSE, VMKState, tickmask, nz, let ntick_intcb = @(MkVMKIntCB, ticknumb, tickmask, TT, tickcont) in @(INTCB_SET, nz, TICK_LOC, ntick_intcb)); dec VMK_EVAL_TICK : [TickStream -> VMKCont]; def VMK_EVAL_TICK = \(tick_stream : TickStream, z : VMKState) let nz = @(SET_VMKST_IDX, z, VMK_MANAGER_IDX) in let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let tick = @(SHEAD, Bool, tick_stream), rest_ticks = @(STAIL, Bool, tick_stream) in let c = @(GET_VMKMAN_CONTXT, vmk_manager) in let z0 = @(TICK_SET, nz), z1 = @(GLOBAL_INT_DISABLE, z0),

106

Interrupt Handling and VM Scheduling

z2 = @(VMK_SAVE_CONTEXT, c, z1), z3 = @(VMK_EVAL_TIMER, z2), z4 = @(VMK_SCHEDULE, z3), z5 = @(VMK_SWITCH_CONTEXT, z4), z6 = @(GLOBAL_INT_ENABLE, z5) in @(VMK_EVAL_TICK, rest_ticks, z6);

10.3

Interrupt Handling

10.3.1

Interrupting Sequential Programs

dec IntDispatch : [Nat -> VMKCont]; dec TICK_ID : Identifier; dec EQ_IDENT : [Identifier -> Identifier -> Bool]; dec DO_EVAL_INTCB : [VMKLocation -> Nat -> VMKCont]; def DO_EVAL_INTCB = \(l : VMKLocation, index : Nat, z : VMKState) let intcb = @(INTCB_GET, z, l) in let icbnumb = @(GET_VMKIntCB_NUMB, intcb), icbmask = @(GET_VMKIntCB_MASK, intcb), icbfire = @(GET_VMKIntCB_FIRE, intcb), icbcont = @(GET_VMKIntCB_CONT, intcb) in @(GIF_THEN_ELSE, VMKState, @(EQ_IDENT, TICK_ID, icbnumb), z, @(GIF_THEN_ELSE, VMKState, icbmask, z, @(GIF_THEN_ELSE, VMKState, icbfire, let nintcb = @(MkVMKIntCB, icbnumb, icbmask, FF, icbcont) in let z1 = @(INTCB_SET, z, l, nintcb) in @(GIF_THEN_ELSE, VMKState, @(EQ_VMKCONT, icbcont, NULL_VMKCONT), @(IntDispatch, index, z1), @(icbcont, z1)), z))); dec EVAL_INTCB_LIST : [MList -> Nat -> VMKCont];

107

Interrupt Handling and VM Scheduling

108

def EVAL_INTCB_LIST = \(int_list : MList, index : Nat, z : VMKState) @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, int_list), z, let hintcb = @(MHEAD, int_list, z), tintcb = @(MTAIL, int_list, z) in let nz = @(DO_EVAL_INTCB, @(GET_KLVAL, hintcb), index, z) in @(EVAL_INTCB_LIST, tintcb, @(SS, index), nz)); dec EVAL_INTCB : VMKCont; def EVAL_INTCB = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_INTCBL, vmk_manager) in @(EVAL_INTCB_LIST, int_table, OO, nz); def IntStream = @(Stream, @(List, Bool)); dec SET_INTCB_LIST : [@(List, Bool) -> VMKState -> VMKState]; dec VMK_EVAL_INT : [IntStream -> VMKCont]; def VMK_EVAL_INT = \(int_stream : IntStream, z : VMKState) let nz = @(SET_VMKST_IDX, z, VMK_MANAGER_IDX) in let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int = @(SHEAD, @(List, Bool), int_stream), rest_ints = @(STAIL, @(List, Bool), int_stream) in let c = @(GET_VMKMAN_CONTXT, vmk_manager) in let z0 = @(GLOBAL_INT_DISABLE, nz), z1 = @(SET_INTCB_LIST, int, z0), z2 = @(VMK_SAVE_CONTEXT, c, z1), z3 = @(EVAL_INTCB, z2), z4 = @(VMK_SCHEDULE, z3), z5 = @(VMK_SWITCH_CONTEXT, z4), z6 = @(GLOBAL_INT_ENABLE, z5) in @(VMK_EVAL_INT, rest_ints, z6);

10.4

Exception Interrupt Handling

dec DO_EVAL_EXINTCB : [VMKLocation -> Nat -> HMType -> ExcpCont -> VMKCont]; def DO_EVAL_EXINTCB = \(l : VMKLocation, index : Nat, type : HMType,

Interrupt Handling and VM Scheduling

109

context : ExcpCont, z : VMKState) let intcb = @(INTCB_GET, z, l) in let icbnumb = @(GET_VMKIntCB_NUMB, intcb), icbmask = @(GET_VMKIntCB_MASK, intcb), icbfire = @(GET_VMKIntCB_FIRE, intcb), icbcont = @(GET_VMKIntCB_CONT, intcb) in @(GIF_THEN_ELSE, VMKState, icbmask, z, let nintcb = @(MkVMKIntCB, icbnumb, icbmask, FF, icbcont) in let z1 = @(INTCB_SET, z, l, nintcb) in @(GIF_THEN_ELSE, VMKState, @(EQ_VMKCONT, icbcont, NULL_VMKCONT), @(vmkDispatchHM, index, type, context, z1), @(icbcont, z1))); dec EVAL_EXCPINTCB : [VMKLocation -> HMType -> ExcpCont -> VMKCont]; def EVAL_EXCPINTCB = \(int_loc : VMKLocation, type : HMType, c : ExcpCont, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_EXINTL, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, int_loc), int_table, nz), let index = @(GetExcpContNumb, c), context = @(GetExcpContCont, c) in @(DO_EVAL_EXINTCB, int_loc, index, type, c, nz), nz);

10.5

Scheduler

A function called SCHEDULE is provide to specify the scheduling algorithm. Normally, there will be two cases for context switching: • After the completion of a system call. • After the completion of an interrupt service routine. When there is need for context switching, we need first to save the context of current running VM into its VMCB. Otherwise it will be a incorrect result for its next execution. 1. Save current context in current running VM. 2. Select next VM for execution. 3. Continue the execution of system.

Interrupt Handling and VM Scheduling

10.5.1

Save Current Context

dec VMK_MANAGER_IDX : Nat; dec VMK_MANAGER_LOC : VMKLocation; dec VMK_SAVE_CONTEXT : [VMKCont -> VMKCont]; def VMK_SAVE_CONTEXT = \(c : VMKCont, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let old_vm = @(VMCB_GET, nz, old_vm_loc), new_vm = @(SetVMCBIntContxt, old_vm, c) in @(VMCB_SET, nz, old_vm_loc, new_vm); dec SAVE_CONTEXT : [VMKCont -> VMKCont]; def SAVE_CONTEXT = \(c : VMKCont) @(VMK_SAVE_CONTEXT, c);

10.5.2

Switch to New VM

dec VMK_SWITCH_CONTEXT : VMKCont; def VMK_SWITCH_CONTEXT = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let run_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let run_vm = @(VMCB_GET, nz, run_vm_loc) in let memoidx = @(GetVMCBMemoIndex, run_vm), context = @(GetVMCBIntContxt, run_vm) in let nz2 = @(SET_VMKST_IDX, nz, memoidx) in @(context, nz2); dec SWITCH_CONTEXT : VMKCont; def SWITCH_CONTEXT = \(z : VMKState) @(VMK_SWITCH_CONTEXT, z);

110

Interrupt Handling and VM Scheduling

10.5.3

Scheduling Function

dec GetVMVTickInt : [VMKLocation -> VMKState -> Nat]; def GetVMVTickInt = \(vm_loc : VMKLocation, z : VMKState) let vm = @(VMCB_GET, z, vm_loc) in let vint_block = @(GetVMCBVIntCBlck, vm) in let vtickcb_loc = @(GetVMVIntTickCB, vint_block) in let vtickcb = @(GetVMVTickIntCB, z, vtickcb_loc) in @(GetVMVTIntCBFire, vtickcb); dec SetVMVTickInt : [VMKLocation -> Nat -> VMKState -> VMKState]; def SetVMVTickInt = \(vm_loc : VMKLocation, tick : Nat, z : VMKState) let vm = @(VMCB_GET, z, vm_loc) in let vint_block = @(GetVMCBVIntCBlck, vm) in let vtickcb_loc = @(GetVMVIntTickCB, vint_block) in let vtickcb = @(GetVMVTickIntCB, z, vtickcb_loc) in let nvtickcb = @(SetVMVTIntCBFire, vtickcb, tick) in @(SetVMVTickIntCB, z, vtickcb_loc, nvtickcb); def VMK_SCHEDULE = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let tts_vm_loc = @(GET_VMKMAN_TTSVM, vmk_manager), prq_vm_loc = @(GET_VMKMAN_PQUEVM, vmk_manager) in let tts_vm = @(VMCB_GET, nz, tts_vm_loc), prq_vm = @(VMCB_GET, nz, prq_vm_loc) in let new_vm_loc = @(GIF_THEN_ELSE, VMKLocation, @(EQ_VMKLOC, tts_vm_loc, NIL_VMKLOC), prq_vm_loc, tts_vm_loc) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, new_vm_loc, old_vm_loc)), let old_vm = @(VMCB_GET, nz, old_vm_loc), new_vm = @(VMCB_GET, nz, new_vm_loc) in let nvmk_manager = @(SET_VMKMAN_RUNVM, vmk_manager, new_vm_loc) in let nold_vm = @(SetVMCBLeaveTick, old_vm, OO) in let z0 = @(GIF_THEN_ELSE, VMKState, @(IS_VMFIRSTRUN, @(GetVMCBStatus, new_vm)), @(SetVMVTickInt, new_vm_loc, @(GET_VMKMAN_TICKCN, nvmk_manager),

111

Interrupt Handling and VM Scheduling

112

nz), nz), z1 = @(CHANGE, z0, VMK_MANAGER_LOC, nvmk_manager), z2 = @(VMCB_SET, z1, old_vm_loc, nold_vm) in z2, nz);

[@(VMKStateTran, @(VMKStateTran, @(VMKStateTran, @(VMKStateTran, @(VMKStateTran, @(VMKStateTran,

z, z0, z1, z2, z3, z,

GLOBAL_INT_DISABLE, @(SAVE_CONTEXT, c), VMK_SCHEDULE, SWITCH_CONTEXT, GLOBAL_INT_ENABLE, @(SCHEDULE, c),

def SCHEDULE = \(c : VMKCont, z : VMKState) let z0 = @(GLOBAL_INT_DISABLE, z), z1 = @(SAVE_CONTEXT, c, z0), z2 = @(VMK_SCHEDULE, z1), z3 = @(SWITCH_CONTEXT, z2) in @(GLOBAL_INT_ENABLE, z3);

z0) -> z1) -> z2) -> z3) -> z4) -> z5)]

Chapter 11

Semantics of C-VMK 11.1

Semantics of Expressions

11.1.1

Auxiliary Functions

dec TDECL_TYPE : [Identifier -> Type_Elem -> KTypeEnv -> KEnv -> VMKEont -> VMKCont]; dec INT2NAT : [Int -> Nat]; dec GET_LOC_LIST : [Nat -> @(List, VMKLocation) -> VMKLocation]; dec DO_SUBSCRIPT : [@(List, @(Product, Nat, Nat)) -> @(List, Nat) -> Nat -> Nat]; def DO_SUBSCRIPT = \(pl : @(List, @(Product, Nat, Nat)), nl : @(List, Nat), n : Nat) @(GIF_THEN_ELSE, Nat, @(AND, @(IS_EMPTY, @(Product, Nat, Nat), pl), @(IS_EMPTY, Nat, nl)), n, @(GIF_THEN_ELSE, Nat, @(OR, @(IS_EMPTY, @(Product, Nat, Nat), pl), @(IS_EMPTY, Nat, nl)), ERR_NAT, let hpl = @(HEAD, @(Product, Nat, Nat), pl), tpl = @(TAIL, @(Product, Nat, Nat), pl) in let hnl = @(HEAD, Nat, nl), tnl = @(TAIL, Nat, nl) in let lb = @(PRO1, Nat, Nat, hpl), ub = @(PRO2, Nat, Nat, hpl) in let nn = @(ADD, @(TIMES, n, @(SS, @(MINUS, ub, lb))), hnl) in @(DO_SUBSCRIPT, tpl, tnl, nn)));

113

CHAPTER 11. SEMANTICS OF C-VMK

114

dec SUBSCRIPT : [Array -> VMKEont -> @(List, Nat) -> VMKState -> VMKState]; def SUBSCRIPT = \(a : Array, k : VMKEont, vl : @(List, Nat), z : VMKState) let bl = @(GET_ARRAY_RANLST, a), ll = @(GET_ARRAY_LOC, a) in let nv = @(DO_SUBSCRIPT, bl, vl, OO) in let loc = @(GET_LOC_LIST, nv, ll) in let ev = @(GET, z, loc) in @(k, ev, z);

11.1.2

Semantic Function CONTENT

11.1.2.1

Informal Description

@(CONTENT, k, e, z) checks that e is a location and if so, looks up its contents in z and passes the result, together with z, to k. If e is not a location, then @(CONTENT, k, e, s) = ERR STATE. def CONTENT = \(k : VMKEont, e : KEval, z : VMKState) @(GIF_THEN_ELSE, VMKState, @(IS_KLVAL, e), let l = @(GET_KLVAL, e) in @(k, @(GET, z, l), z), @(ERR_VMKSTATE, z));

11.1.3

Semantic Function UPDATE

11.1.3.1

Informal Description

@(UPDATE, l, c, e, z) stores e at location l in z and passes the resulting state to c. def UPDATE = \(l : VMKLocation, c : VMKCont, e : KEval, z : VMKState) @(c, @(CHANGE, z, l, e));

11.1.4

Semantic Function REF

11.1.4.1

Informal Description

@(REF, k, e, z) gets an unused location from z, updates it with e and then passes it, and the updated store, to k. def REF = \(k : VMKEont, e : KEval, z : VMKState) let l2z = @(NEW_VMKLOC, z) in

CHAPTER 11. SEMANTICS OF C-VMK

115

let nl = @(PJ1, VMKLocation, VMKState, l2z), nz = @(PJ2, VMKLocation, VMKState, l2z) in @(UPDATE, nl, @(k, @(KLVAL, nl)), e, nz);

11.1.5

Semantic Function DEREF

11.1.5.1

Informal Description

@(DEREF, k, e, s) tests whether e is a location and if so, passes its contents in s, together with s, to k. If e is not a location, then e and s are passed to k. def DEREF = \(k : VMKEont, e : KEval, s : VMKState) @(GIF_THEN_ELSE, VMKState, @(IS_KLVAL, e), @(CONTENT, k, e, s), @(k, e, s));

11.1.6

Operations for Binop and Unop

dec OPERATOR : [Binop -> KEval -> KEval -> KEval]; dec UNOPERATOR : [Unop -> KEval -> KEval]; dec EXPR : [Expression -> KEnv -> VMKEont -> VMKCont]; dec REXPR : [Expression -> KEnv -> VMKEont -> VMKCont]; dec INSERT_LAST : !(T : Prop) [T -> @(List, T) -> @(List, T)]; dec LENGTH : !(T : Prop) [@(List, T) -> Nat];

11.1.7

Semantics for Expressions

dec REXPR_LIST : [Expr_list -> @(List, Nat) -> KEnv -> [@(List, Nat) -> VMKCont] -> VMKCont]; def REXPR_LIST = \(el : Expr_list, nl : @(List, Nat), r : KEnv, k : [@(List, Nat) -> VMKCont]) @(GIF_THEN_ELSE, VMKCont, @(IS_EMPTY, Expression, el), @(k, nl), let hel = @(HEAD, Expression, el), tel = @(TAIL, Expression, el) in

CHAPTER 11. SEMANTICS OF C-VMK

let nk = \(v : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, v), let nv = @(INT2NAT, @(GET_KIVAL, v)) in let nnl = @(INSERT_LAST, Nat, nv, nl) in @(REXPR_LIST, tel, nnl, r, k), ERR_VMKCONT) in @(REXPR, hel, r, nk)); dec FIND_CALL_DVAL : [Expression -> KEnv -> [KDval -> VMKCont] -> VMKCont]; def FIND_CALL_DVAL = \(e : Expression, r : KEnv, k : [KDval -> VMKCont]) @(GIF_THEN_ELSE, VMKCont, @(IS_IDEN_EXPR, e), let i = @(GET_EXPR_IDEN, e) in @(k, @(r, i)), @(GIF_THEN_ELSE, VMKCont, @(IS_REC_EXPR, e), let e1 = @(GET_EXPR_RECNAM, e), e2 = @(GET_EXPR_RECIDX, e) in let nk = \(v : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KRVAL, v), let nr = @(GET_KRVAL, v) in @(FIND_CALL_DVAL, e2, @(COMP_KENV, r, nr), k), ERR_VMKCONT) in @(EXPR, e1, r, nk), ERR_VMKCONT)); def EXPRNil = \(r : KEnv, k : VMKEont) @(k, @(KLVAL, NIL_VMKLOC)); def EXPRBoolean = \(b : Bool, r : KEnv, k : VMKEont) @(k, @(KBVAL, b)); def EXPRInteger = \(i : Int, r : KEnv, k : VMKEont) @(k, @(KIVAL, i)); def EXPRBit16Word = \(w : Bit16Word, r : KEnv, k : VMKEont) @(k, @(KWVAL, w)); def EXPRIdentifier = \(i : Identifier, r : KEnv, k : VMKEont)

116

CHAPTER 11. SEMANTICS OF C-VMK

let t = @(r, i) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, t, \(a1 : KEval) \(s : VMKState) @(k, @(GET, s, @(GET_KLVAL, a1)), s), \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) @(WHEN5, Procedure, Function, Thunk, Text, Denotation, VMKCont, a3, \(b1 : Procedure) ERR_VMKCONT, \(b2 : Function) @(b2, r, k, EMPTY_ELIST), \(b3 : Thunk) @(b3, k), \(b4 : Text) @(EXPR, b4, r, k), \(b5 : Denotation) @(b5, r, k))); def EXPRCont = \(be : Expression, r : KEnv, k : VMKEont) let nk = \(v : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KLVAL, v), @(k, v), ERR_VMKCONT) in @(EXPR, be, r, @(CONTENT, nk)); def EXPRNew = \(i : Identifier, st : Type_Elem, tr : KTypeEnv, r : KEnv, k : VMKEont) @(TDECL_TYPE, i, st, tr, r, @(REF, \(v : KEval) @(k, v))); def EXPRRecord = \(e1 : Expression, e2 : Expression, r : KEnv, k : VMKEont) let nk = \(v : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KRVAL, v), let nr = @(GET_KRVAL, v) in @(EXPR, e2, @(COMP_KENV, r, nr), k), ERR_VMKCONT) in @(EXPR, e1, r, nk);

117

CHAPTER 11. SEMANTICS OF C-VMK

def EXPRArray = \(ee : Expression, el : Expr_list, r : KEnv, k : VMKEont) let nk1 = \(v1 : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KAVAL, v1), let array = @(GET_KAVAL, v1) in let nk2 = \(v2 : @(List, Nat)) @(SUBSCRIPT, array, k, v2) in @(REXPR_LIST, el, @(NIL, Nat), r, nk2), ERR_VMKCONT) in @(EXPR, ee, r, nk1); def EXPRFunctionCall = \(i : Expression, l : Expr_list, r : KEnv, k : VMKEont) @(FIND_CALL_DVAL, i, r, \(t : KDval) @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, t, \(a1 : KEval) ERR_VMKCONT, \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) @(WHEN5, Procedure, Function, Thunk, Text, Denotation, VMKCont, a3, \(p1 : Procedure) ERR_VMKCONT, \(p2 : Function) @(p2, r, k, l), \(p3 : Thunk) ERR_VMKCONT, \(p4 : Text) ERR_VMKCONT, \(p5 : Denotation) ERR_VMKCONT))); def EXPRBinaryOp = \(o : Binop, e1 : Expression, e2 : Expression, r : KEnv, k : VMKEont) @(EXPR, e1, r, \(v1 : KEval) @(EXPR, e2, r, \(v2 : KEval) @(k, @(OPERATOR, o, v1, v2)))); def EXPRUnaryOp = \(o : Unop, ne : Expression, r : KEnv, k : VMKEont) @(EXPR, ne, r, \(v : KEval) @(k, @(UNOPERATOR, o, v)));

118

CHAPTER 11. SEMANTICS OF C-VMK

def EXPR = \(e : Expression, r : KEnv, k : VMKEont) @(e, VMKCont, %-- Nil Expression --% @(EXPRNil, r, k), %-- Boolean Expression --% \(b : Bool) @(EXPRBoolean, b, r, k), %-- Integer Expression --% \(i : Int) @(EXPRInteger, i, r, k), \(w : Bit16Word) @(EXPRBit16Word, w, r, k), %-- Identifier Expression --% \(i : Identifier) @(EXPRIdentifier, i, r, k), %-- Cont --% \(x : VMKCont) let be = @(GET_EXPR_CONT, e) in @(EXPRCont, be, r, k), %-- Use of Record --% \(x1 : VMKCont, x2 : VMKCont) let e1 = @(GET_EXPR_RECNAM, e), e2 = @(GET_EXPR_RECIDX, e) in @(EXPRRecord, e1, e2, r, k), %-- Use of Array --% \(x1 : VMKCont, x2 : Expr_list) let ee = @(GET_EXPR_ARRNAM, e), el = @(GET_EXPR_ARRIDX, e) in @(EXPRArray, ee, el, r, k), %-- Function Call --% \(i : Expression, l : Expr_list) @(EXPRFunctionCall, i, l, r, k), %-- Binary Operation --% \(o : Binop, x1 : VMKCont, x2 : VMKCont) let e1 = @(GET_EXPR_LEFT, e), e2 = @(GET_EXPR_RIGHT, e) in @(EXPRBinaryOp, o, e1, e2, r, k), %-- Unary Operation --% \(o : Unop, x : VMKCont) let ne = @(GET_EXPR_UN, e) in @(EXPRUnaryOp, o, ne, r, k)); def REXPR = \(e : Expression, r : KEnv, k : VMKEont) @(EXPR, e, r, \(e : KEval) @(DEREF, k, e));

119

CHAPTER 11. SEMANTICS OF C-VMK

11.2

Semantics of Declarations

11.2.1

Auxiliary Functions

dec INSERT_LAST : !(T : Prop) [T -> @(List, T) -> @(List, T)]; dec ERR_EVAL : KEval; dec NEW_BOOL_LOC : [VMKState -> @(And, VMKLocation, VMKState)]; dec NEW_INT_LOC : [VMKState -> @(And, VMKLocation, VMKState)]; dec NEW_BIT16_LOC : [VMKState -> @(And, VMKLocation, VMKState)]; dec INT2NAT : [Int -> Nat]; dec NAT2INT : [Nat -> Int]; dec NEWS : [VMKState -> Nat -> @(And, @(List, VMKLocation), VMKState)]; def NEWS = \(z : VMKState, n : Nat) @(GIF_THEN_ELSE, @(And, @(List, VMKLocation), VMKState), @(IS_ZERO, n), @(ANDS, @(List, VMKLocation), VMKState, @(NIL, VMKLocation), z), let l2z = @(NEWS, z, @(PP, n)) in let nl = @(PJ1, @(List, VMKLocation), VMKState, l2z), nz = @(PJ2, @(List, VMKLocation), VMKState, l2z) in let loc2z = @(NEW_VMKLOC, nz) in let loc = @(PJ1, VMKLocation, VMKState, loc2z), nz2 = @(PJ2, VMKLocation, VMKState, loc2z) in let nl2 = @(CONS, VMKLocation, loc, nl) in @(ANDS, @(List, VMKLocation), VMKState, nl2, nz2)); dec RAN_CHK_OK : [@(List, @(Product, Nat, Nat)) -> Bool]; dec CALC_RAN_LENG : [@(List, @(Product, Nat, Nat)) -> Nat]; def NEWARRAY = \(rl : @(List, @(Product, Nat, Nat)), k : VMKEont) @(GIF_THEN_ELSE, VMKCont, @(RAN_CHK_OK, rl), ERR_VMKCONT, \(z : VMKState) let n = @(CALC_RAN_LENG, rl) in let l2z = @(NEWS, z, n) in let l = @(PJ1, @(List, VMKLocation), VMKState, l2z), nz = @(PJ2, @(List, VMKLocation), VMKState, l2z) in let array = @(MK_ARRAY, rl, l) in let av = @(KAVAL, array) in @(k, av, nz));

120

CHAPTER 11. SEMANTICS OF C-VMK

121

def TNEWARRAY = \(rl : @(List, @(Product, Nat, Nat)), z : VMKState) @(GIF_THEN_ELSE, @(And, KEval, VMKState), @(RAN_CHK_OK, rl), @(ANDS, KEval, VMKState, ERR_KEVAL, z), let n = @(CALC_RAN_LENG, rl) in let l2z = @(NEWS, z, n) in let l = @(PJ1, @(List, VMKLocation), VMKState, l2z), nz = @(PJ2, @(List, VMKLocation), VMKState, l2z) in let array = @(MK_ARRAY, rl, l) in let av = @(KAVAL, array) in @(ANDS, KEval, VMKState, av, nz));

11.2.2

Semantics of Type Declarations

dec JUMP : [Statement -> KTypeEnv -> KEnv -> VMKCont -> KEnv]; dec DECL : [Declaration -> KTypeEnv -> KEnv -> VMKDont -> VMKCont]; dec PROC : [Proc -> KTypeEnv -> KEnv -> KEnv]; dec TDECL : [Type_Decl -> KTypeEnv -> KEnv -> VMKTont -> VMKCont]; dec STAT : [Statement -> KTypeEnv -> KEnv -> VMKCont -> VMKCont]; dec ChangeStatePVal : [Identifier -> KSval -> KEnv -> VMKCont]; def TDECL = \(d : Type_Decl, tr : KTypeEnv, r : KEnv, c : VMKTont) @(d, VMKCont, \(i : Identifier, rl : Record_Decl_List) let ntr = @(ENTER_KTENV, EMPTY_KTENV, i, @(REC_TYPE, rl)) in @(c, ntr), \(i : Identifier, a : Array_Decl) let ntr = @(ENTER_KTENV, EMPTY_KTENV, i, @(ARRAY_TYPE, a)) in @(c, ntr), \(i : Identifier, t : Type_Elem) let ntr = @(ENTER_KTENV, EMPTY_KTENV, i, @(ACCESS_TYPE, t)) in @(c, ntr), \(c1 : VMKCont, c2 : VMKCont) let d1 = @(LEFT_TDECL, d), d2 = @(RIGHT_TDECL, d) in @(TDECL,

CHAPTER 11. SEMANTICS OF C-VMK

d1, tr, r, \(tr1 : KTypeEnv) @(TDECL, d2, @(COMP_KTENV, tr, tr1), r, \(tr2 : KTypeEnv) @(c, @(COMP_KTENV, tr1, tr2)))));

11.2.3

Semantics of Declarations

11.2.3.1

Semantics of Record Types

dec DECL_REC : [Record_Decl_List -> KTypeEnv -> KEnv -> VMKDont -> VMKCont]; dec TDECL_TYPE : [Identifier -> Type_Elem -> KTypeEnv -> KEnv -> VMKEont -> VMKCont]; def DECL_REC = \(dl : Record_Decl_List, tr : KTypeEnv, r : KEnv, c : VMKDont) @(GIF_THEN_ELSE, VMKCont, @(IS_EMPTY, Record_Decl, dl), @(c, r), let hdl = @(HEAD, Record_Decl, dl), tdl = @(TAIL, Record_Decl, dl) in @(DECL_REC, tdl, tr, r, \(nr : KEnv) let id = @(GET_REC_IDEN, hdl), ty = @(GET_REC_TYPE, hdl) in @(TDECL_TYPE, id, ty, tr, r, \(v : KEval) let nnr = @(ENTER_LOC_KENV, nr, id, v) in @(c, nnr))));

122

CHAPTER 11. SEMANTICS OF C-VMK

11.2.3.2

123

Semantics of Array Types

dec TRAN_EXPR_LIST : [Type_Elem -> @(List, @(Product, Expression, Expression)) -> @(List, @(Product, Nat, Nat)) -> KTypeEnv -> KEnv -> VMKEont -> VMKCont]; def TRAN_EXPR_LIST = \(ty : Type_Elem, el : @(List, @(Product, Expression, Expression)), nl : @(List, @(Product, Nat, Nat)), tr : KTypeEnv, r : KEnv, c : VMKEont) @(GIF_THEN_ELSE, VMKCont, @(IS_EMPTY, @(Product, Expression, Expression), el), \(z : VMKState) let av2z = @(TNEWARRAY, nl, z) in let av = @(PJ1, KEval, VMKState, av2z), nz = @(PJ2, KEval, VMKState, av2z) in @(c, av, nz), let hel = @(HEAD, @(Product, Expression, Expression), el), tel = @(TAIL, @(Product, Expression, Expression), el) in let e1 = @(PRO1, Expression, Expression, hel), e2 = @(PRO2, Expression, Expression, hel) in let nk1 = \(v1 : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, v1), let iv1 = @(GET_KIVAL, v1) in let nk2 = \(v2 : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, v2), let iv2 = @(GET_KIVAL, v2) in let nv1 = @(INT2NAT, iv1), nv2 = @(INT2NAT, iv2) in let nnl = @(INSERT_LAST, @(Product, Nat, Nat), @(PRODUCT, Nat, Nat, nv1, nv2), nl) in @(TRAN_EXPR_LIST, ty, tel, nnl, tr, r, c), ERR_VMKCONT) in @(REXPR, e2, r, nk2), ERR_VMKCONT) in @(REXPR, e1, r, nk1));

CHAPTER 11. SEMANTICS OF C-VMK

dec DECL_ARRAY : [Type_Elem -> @(List, @(Product, Expression, Expression)) -> KTypeEnv -> KEnv -> VMKEont -> VMKCont]; def DECL_ARRAY = \(ty : Type_Elem, el : @(List, @(Product, Expression, Expression)), tr : KTypeEnv, r : KEnv, c : VMKEont) @(TRAN_EXPR_LIST, ty, el, @(NIL, @(Product, Nat, Nat)), tr, r, c);

11.2.3.3

Semantics of Access Types

def DECL_ACCESS = \(i : Identifier, st : Type_Elem, tr : KTypeEnv, r : KEnv, c : VMKEont) @(TDECL_TYPE, i, st, tr, r, @(REF, \(v : KEval) @(c, v))); def TDECL_TYPE = \(i : Identifier, t : Type_Elem, tr : KTypeEnv, r : KEnv, c : VMKEont) @(t, VMKCont, \(z : VMKState) let l2z = @(NEW_BOOL_LOC, z) in let nl = @(PJ1, VMKLocation, VMKState, l2z), nz = @(PJ2, VMKLocation, VMKState, l2z) in @(c, @(KLVAL, nl), nz), \(z : VMKState) let l2z = @(NEW_INT_LOC, z) in let nl = @(PJ1, VMKLocation, VMKState, l2z), nz = @(PJ2, VMKLocation, VMKState, l2z) in @(c, @(KLVAL, nl), nz), \(z : VMKState) let l2z = @(NEW_BIT16_LOC, z) in let nl = @(PJ1, VMKLocation, VMKState, l2z), nz = @(PJ2, VMKLocation, VMKState, l2z) in @(c, @(KLVAL, nl), nz), \(v : Identifier) let ntm = @(tr, v) in @(TDECL_TYPE, i, ntm, tr, r, c),

124

CHAPTER 11. SEMANTICS OF C-VMK

125

\(rl : Record_Decl_List) %-- Record Type --% @(DECL_REC, rl, tr, r, \(nr : KEnv) @(c, @(KRVAL, nr))), \(a : Array_Decl) %-- Array Type --% let el = @(GET_ARRDEC_RANLST, a), ty = @(GET_ARRDEC_TYPE, a) in @(DECL_ARRAY, ty, el, tr, r, c), \(s : VMKCont) %-- Access Type --% let st = @(GET_ACC_TYPE, t) in @(DECL_ACCESS, i, st, tr, r, c));

• For const I := E, E is evaluated for its R-value e and then the little environment e/I is passed to the rest of the program c. • For var I := E, E is evaluated for its R-value e which is then stored in a new location l, and the little environment l/I is passed to the rest of the program c. • For ref I := E, if E’s value is a location l then ref I := E binds I to another location containing l. This differs from var I := E, which would bind I to a location containing l’s contents.

dec RAN_EXPR_LIST : [Identifier -> @(List, @(Product, Expression, Expression)) -> @(List, @(Product, Nat, Nat)) -> KEnv -> VMKDont -> VMKCont]; def RAN_EXPR_LIST = \(i : Identifier, el : @(List, @(Product, Expression, Expression)), nl : @(List, @(Product, Nat, Nat)), r : KEnv, c : VMKDont) @(GIF_THEN_ELSE, VMKCont, @(IS_EMPTY, @(Product, Expression, Expression), el), @(NEWARRAY, nl, \(e : KSval) @(c, @(ENTER_LOC_KENV, EMPTY_KENV, i, e))), let hel = @(HEAD, @(Product, Expression, Expression), el), tel = @(TAIL, @(Product, Expression, Expression), el) in let e1 = @(PRO1, Expression, Expression, hel), e2 = @(PRO2, Expression, Expression, hel) in let nk1 = \(v1 : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, v1), let iv1 = @(GET_KIVAL, v1) in let nk2 = \(v2 : KSval)

CHAPTER 11. SEMANTICS OF C-VMK

@(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, v2), let iv2 = @(GET_KIVAL, v2) in let nv1 = @(INT2NAT, iv1), nv2 = @(INT2NAT, iv2) in let nnl = @(INSERT_LAST, @(Product, Nat, Nat), @(PRODUCT, Nat, Nat, nv1, nv2), nl) in @(RAN_EXPR_LIST, i, tel, nnl, r, c), ERR_VMKCONT) in @(REXPR, e2, r, nk2), ERR_VMKCONT) in @(REXPR, e1, r, nk1)); def DECLNull = \(tr : KTypeEnv, r : KEnv, c : VMKDont) @(c, r); def DECLIdentifier = \(i : Identifier, t : Type_Elem, tr : KTypeEnv, r : KEnv, c : VMKDont) @(GIF_THEN_ELSE, VMKCont, @(IS_IN_KENV, r, i), @(c, r), @(GIF_THEN_ELSE, VMKCont, @(IS_ACCESS_TYPE, t), let st = @(GET_ACC_TYPE, t) in @(TDECL_TYPE, i, st, tr, r, @(REF, \(v : KEval) @(c, @(ENTER_LOC_KENV, r, i, v)))), @(TDECL_TYPE, i, t, tr, r, \(eval : KEval) @(c, @(ENTER_LOC_KENV, r, i, eval))))); def DECLConstBinding = \(i : Identifier, e : Expression, t : Type_Elem, tr : KTypeEnv, r : KEnv, c : VMKDont) @(REXPR, e, r, \(v : KEval) @(c, @(ENTER_LOC_KENV, r, i, v)));

126

CHAPTER 11. SEMANTICS OF C-VMK

127

def DECLVarBinding = \(i : Identifier, e : Expression, t : Type_Elem, tr : KTypeEnv, r : KEnv, c : VMKDont) @(REXPR, e, r, @(REF, \(v : KEval) @(c, @(ENTER_LOC_KENV, r, i, v)))); def DECLRecord = \(i : Identifier, d : Record_Decl_List, tr : KTypeEnv, r : KEnv, c : VMKDont) @(DECL_REC, d, tr, r, \(nr : KEnv) @(c, @(ENTER_LOC_KENV, nr, i, @(KRVAL, nr)))); def DECLArray = \(i : Identifier, d : Array_Decl, tr : KTypeEnv, r : KEnv, c : VMKDont) let el = @(GET_ARRDEC_RANLST, d) in @(RAN_EXPR_LIST, i, el, @(NIL, @(Product, Nat, Nat)), r, c); def DECLSequence = \(d1 : Declaration, d2 : Declaration, tr : KTypeEnv, r : KEnv, c : VMKDont) @(DECL, d1, tr, r, \(r1 : KEnv) @(DECL, d2, tr, r1, \(r2 : KEnv) @(c, r2))); def DECL = \(d : Declaration, tr : KTypeEnv, r : KEnv, c : VMKDont) @(d, VMKCont, %-- Null Declaration --% @(DECLNull, tr, r, c), %-- Identifier Declaration --% \(i : Identifier, t : Type_Elem) @(DECLIdentifier, i, t, tr, r, c), %-- Const Declaration Binding --% \(i : Identifier, e : Expression, t : Type_Elem)

CHAPTER 11. SEMANTICS OF C-VMK

128

@(DECLConstBinding, i, e, t, tr, r, c), %-- Var Declaration Binding --% \(i : Identifier, e : Expression, t : Type_Elem) @(DECLVarBinding, i, e, t, tr, r, c), %-- Record Declaration --% \(i : Identifier, d : Record_Decl_List) @(DECLRecord, i, d, tr, r, c), %-- Array Declaration --% \(i : Identifier, d : Array_Decl) @(DECLArray, i, d, tr, r, c), %-- Sequence of Declaration --% \(x1 : VMKCont, x2 : VMKCont) let d1 = @(LEFT_DECL, d), d2 = @(RIGHT_DECL, d) in @(DECLSequence, d1, d2, tr, r, c));

11.3

Semantics of Procedure and Function Declarations

11.3.1

Parameter Passing Mechanisms

def THUNK = \(e : Expression, r : KEnv, k : VMKEont) @(EXPR, e, r, k); dec FIND_CALL_DVAL : [KEnv -> Expression -> KDval]; dec ENTRY_BIND : [KEnv -> KEnv -> Form_par -> Expression -> VMKDont -> VMKCont]; dec ENTRY_BIND_LIST : [KEnv -> KEnv -> Form_par_list -> Expr_list -> VMKDont -> VMKCont];

11.3.1.1

Call-By-Result

def CallByResult = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(EXPR, e, r, \(v : KEval) @(GIF_THEN_ELSE, VMKCont, @(IS_KLVAL, v), \(x : VMKState)

CHAPTER 11. SEMANTICS OF C-VMK

let l = @(GET_KLVAL, v) in let loc2x = @(NEW_VMKLOC, x) in let loc = @(PJ1, VMKLocation, VMKState, loc2x), nx = @(PJ2, VMKLocation, VMKState, loc2x) in let cc = @(CONTENT, @(UPDATE, l, @(k, @(ENTER_LOC_KENV, r, i, @(KLVAL, loc)))), @(KLVAL, loc)) in @(cc, nx), @(k, ERR_KENV)));

11.3.1.2

Call-By-Value and Result

def CallByValueResult = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(EXPR, e, r, \(v : KEval) @(GIF_THEN_ELSE, VMKCont, @(IS_KLVAL, v), \(x : VMKState) let l = @(GET_KLVAL, v) in let loc2x = @(NEW_VMKLOC, x) in let loc = @(PJ1, VMKLocation, VMKState, loc2x), nx = @(PJ2, VMKLocation, VMKState, loc2x) in let cc = @(CONTENT, @(UPDATE, l, @(k, @(ENTER_LOC_KENV, r, i, @(KLVAL, loc)))), @(KLVAL, loc)) in @(cc, @(CHANGE, nx, loc, v)), @(k, ERR_KENV)));

11.3.1.3

Call-By-Reference

def CallByReference = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(EXPR, e, r, \(v : KEval) @(k, @(ENTER_LOC_KENV, r, i, v)));

129

CHAPTER 11. SEMANTICS OF C-VMK

11.3.1.4

Call-By-Variable

def CallByVariable = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(EXPR, e, r, \(v : KEval) @(GIF_THEN_ELSE, VMKCont, @(IS_KLVAL, v), @(k, @(ENTER_LOC_KENV, r, i, v)), @(k, ERR_KENV)));

11.3.1.5

Call-By-Value

def CallByValue = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(EXPR, e, r, \(v : KEval) \(x : VMKState) let loc2x = @(NEW_VMKLOC, x) in let loc = @(PJ1, VMKLocation, VMKState, loc2x), nx = @(PJ2, VMKLocation, VMKState, loc2x) in @(k, @(ENTER_LOC_KENV, r, i, @(KLVAL, loc)), @(CHANGE, nx, loc, v)));

11.3.1.6

Call-By-Constant

def CallByConstant = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(EXPR, e, r, \(v : KEval) @(k, @(ENTER_LOC_KENV, r, i, v)));

11.3.1.7

Call-By-Name

def CallByName = \(i : Identifier, e : Expression, r : KEnv, dr : KEnv, k : VMKDont) @(k, @(ENTER_PRO_KENV, r, i,

130

CHAPTER 11. SEMANTICS OF C-VMK

131

@(INJ53, Procedure, Function, Thunk, Text, Denotation, @(THUNK, e, dr))));

11.3.1.8

Call-By-Text

def CallByText = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(k, @(ENTER_PRO_KENV, r, i, @(INJ54, Procedure, Function, Thunk, Text, Denotation, e)));

11.3.1.9

Call-By-Denotation

def CallByDenote = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(k, @(ENTER_PRO_KENV, r, i, @(INJ55, Procedure, Function, Thunk, Text, Denotation, @(EXPR, e))));

11.3.1.10

FORTRAN Call-By-Reference

def FortranCallByRef = \(i : Identifier, e : Expression, r : KEnv, k : VMKDont) @(EXPR, e, r, \(v : KEval) @(GIF_THEN_ELSE, VMKCont, @(IS_KLVAL, v), @(k, @(ENTER_LOC_KENV, r, i, v)), \(x : VMKState) let loc2x = @(NEW_VMKLOC, x) in let loc = @(PJ1, VMKLocation, VMKState, loc2x), nx = @(PJ2, VMKLocation, VMKState, loc2x) in @(k,

CHAPTER 11. SEMANTICS OF C-VMK

@(ENTER_LOC_KENV, r, i, @(KLVAL, loc)), @(CHANGE, nx, loc, v))));

11.3.1.11

Procedures as Parameters

def ProcParameter = \(i : Identifier, l : Form_par_list, e : Expression, r : KEnv, dr : KEnv, k : VMKDont) @(GIF_THEN_ELSE, VMKCont, @(IS_CALL_EXPR, e), let pp = @(GET_EXPR_FUNC, e), el = @(GET_EXPR_ELIST, e) in let pr = @(FIND_CALL_DVAL, r, pp) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, pr, \(a1 : KEval) @(k, ERR_KENV), \(a2 : VMKCont) @(k, ERR_KENV), \(a3 : KProc_dval) @(ENTRY_BIND_LIST, @(ENTER_PRO_KENV, r, i, a3), dr, l, el, \(rr : KEnv) @(k, rr))), @(k, ERR_KENV));

11.3.1.12

Functions as Parameters

def FuncParameter = \(i : Identifier, l : Form_par_list, e : Expression, r : KEnv, dr : KEnv, k : VMKDont) @(GIF_THEN_ELSE, VMKCont, @(IS_CALL_EXPR, e), let fp = @(GET_EXPR_FUNC,

e),

132

CHAPTER 11. SEMANTICS OF C-VMK

el = @(GET_EXPR_ELIST, e) in let fr = @(FIND_CALL_DVAL, r, fp) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, fr, \(a1 : KEval) @(k, ERR_KENV), \(a2 : VMKCont) @(k, ERR_KENV), \(a3 : KProc_dval) @(ENTRY_BIND_LIST, @(ENTER_PRO_KENV, r, i, a3), dr, l, el, \(rr : KEnv) @(k, rr))), @(k, ERR_KENV));

11.3.1.13

Formal and Actual Parameter Binding

def ENTRY_BIND = \(r : KEnv, dr : KEnv, f : Form_par, e : Expression, k : VMKDont) @(f, VMKCont, %-- Normal Parameter --% \(i : Identifier, t : Type_Elem, m : Mode) @(m, VMKCont, %-- Call by Result --% @(CallByResult, i, e, r, k), %-- Call by Value and Result --% @(CallByValueResult, i, e, r, k), %-- Call by Variable --% @(CallByVariable, i, e, r, k), %-- Call by Value --% @(CallByValue, i, e, r, k), %-- Call by Constant --% @(CallByConstant, i, e, r, k), %-- Call by Name --% @(CallByName, i, e, r, dr, k), %-- Fortran based Call by Reference --% @(FortranCallByRef, i, e, r, k), %-- Call by Text --% @(CallByText, i, e, r, k), %-- Call by Denotation --% @(CallByDenote, i, e, r, k)), %-- Procedure as Parameter --% \(i : Identifier, l : Form_par_list) @(ProcParameter, i, l, e, r, dr, k),

133

CHAPTER 11. SEMANTICS OF C-VMK

134

%-- Function as Parameter --% \(i : Identifier, l : Form_par_list, t : Type_Elem) @(FuncParameter, i, l, e, r, dr, k));

11.3.1.14

List of Formal and Actual Parameter Binding

def ENTER_BIND_LIST = \(r : KEnv, dr : KEnv, fl : Form_par_list, el : Expr_list, c : VMKDont) @(GIF_THEN_ELSE, VMKCont, @(IS_EMPTY_FPAR_LIST, fl), %-- Empty Binding List --% @(GIF_THEN_ELSE, VMKCont, @(IS_EMPTY_ELIST, el), @(c, r), @(c, ERR_KENV)), %-- Non-Empty Binding List --% @(GIF_THEN_ELSE, VMKCont, @(IS_EMPTY_ELIST, el), @(c, ERR_KENV), let f = @(HEAD_FPAR_LIST, fl), nfl = @(TAIL_FPAR_LIST, fl), e = @(HEAD_ELIST, el), nel = @(TAIL_ELIST, el) in @(ENTRY_BIND, r, dr, f, e, \(nr : KEnv) @(ENTRY_BIND_LIST, nr, dr, nfl, nel, c)))); dec PROC : [Proc -> KTypeEnv -> KEnv -> VMKState -> @(And, KEnv, VMKState)]; dec RETLAB : Identifier; dec RETVALLAB : Identifier; def PROCNull = \(tr : KTypeEnv, r : KEnv, z : VMKState) @(ANDS, KEnv, VMKState, r, z);

The procedure name i is associated with the semantic entity pi and the return label RETLAB is associated with the continuation c. def PROCProcedure = \(i : Identifier, l : Form_par_list, s : Statement,

CHAPTER 11. SEMANTICS OF C-VMK

135

tr r z lec let let let

: KTypeEnv, : KEnv, : VMKState) pc : Procedure in pi = @(INJ51, Procedure, Function, Thunk, Text, Denotation, pc) in nr = @(ENTER_PRO_KENV, r, i, pi) in pc = \(dr : KEnv, c : VMKCont, e : Expr_list) @(ENTRY_BIND_LIST, nr, dr, l, e, \(rr : KEnv) @(STAT, s, tr, @(ENTER_CON_KENV, rr, RETLAB, c), c)) in @(ANDS, KEnv, VMKState, nr, z);

The function name i is associated with the semantic entity fi and the return value v is passed to the expression continuation k which is then associated with the return label RETLAB. Meanwhile a new location is created which is associated with both the function name i and the return value label RETVALLAB inside of fi where i is used for referencing the value denoted by i and RETVALLAB is used for updating the content of location associated with RETVALLAB when the statement return e is met. def PROCFunction = \(i : Identifier, l : Form_par_list, s : Statement, t : Type_Elem, tr : KTypeEnv, r : KEnv) \(z : VMKState) lec fc : Function in let fi = @(INJ52, Procedure, Function, Thunk, Text, Denotation, fc) in let nr = @(ENTER_PRO_KENV, r, i, fi) in let loc2z = @(NEW_VMKLOC, z) in let lo = @(PJ1, VMKLocation, VMKState, loc2z), nz = @(PJ2, VMKLocation, VMKState, loc2z) in let nnr1 = @(ENTER_LOC_KENV, nr, i, @(KLVAL, lo)), nnr2 = @(ENTER_LOC_KENV, nnr1, RETVALLAB, @(KLVAL, lo)) in let fc = \(dr : KEnv, k : VMKEont, e : Expr_list) @(ENTRY_BIND_LIST, nnr2, dr, l, e, \(rr : KEnv) \(x : VMKState) let v = @(GET, x, lo) in @(STAT, s, tr, @(ENTER_CON_KENV, rr, RETLAB, @(k, v)), @(k, v), x)) in @(ANDS, KEnv, VMKState, nr, nz);

CHAPTER 11. SEMANTICS OF C-VMK

def PROCSeq = \(p1 : Proc, p2 : Proc, tr : KTypeEnv, r : KEnv, z : VMKState) let r2z1 = @(PROC, p1, tr, r, z) in let r1 = @(PJ1, KEnv, VMKState, r2z1), z1 = @(PJ2, KEnv, VMKState, r2z1) in let r2z2 = @(PROC, p2, tr, r1, z1) in let r2 = @(PJ1, KEnv, VMKState, r2z2), z2 = @(PJ2, KEnv, VMKState, r2z2) in @(ANDS, KEnv, VMKState, @(COMP_KENV, r1, r2), z2); def PROC = \(p : Proc, tr : KTypeEnv, r : KEnv, z : VMKState) @(p, @(And, KEnv, VMKState), %-- Null Procedure Declaration --% @(PROCNull, tr, r, z), %-- Procedure --% \(i : Identifier, l : Form_par_list, s : Statement) @(PROCProcedure, i, l, s, tr, r, z), %-- Function --% \(i : Identifier, l : Form_par_list, s : Statement, t : Type_Elem) @(PROCFunction, i, l, s, t, tr, r, z), %-- Sequence of Procedure Declaration --% \(x1 : @(And, KEnv, VMKState), x2 : @(And, KEnv, VMKState)) let p1 = @(LEFT_PROC, p), p2 = @(RIGHT_PROC, p) in @(PROCSeq, p1, p2, tr, r, z));

11.4

Semantics of Statements

11.4.1

Auxiliary Functions

dec JUMP : [Statement -> KTypeEnv -> KEnv -> VMKCont -> KEnv]; dec INCR : [Int -> Int]; dec DECR : [Int -> Int]; dec LOOPUP : [Statement -> Identifier -> KEval -> KEval -> KTypeEnv -> KEnv -> VMKCont -> VMKCont]; def LOOPUP = \(b : Statement,

136

CHAPTER 11. SEMANTICS OF C-VMK

i : Identifier, n1 : KEval, n2 : KEval, tr : KTypeEnv, r : KEnv, c : VMKCont) @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, n1), @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, n2), let i1 = @(GET_KIVAL, n1), i2 = @(GET_KIVAL, n2) in let l = @(r, i) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, l, \(a1 : KEval) @(GIF_THEN_ELSE, VMKCont, @(IS_KLVAL, a1), let l1 = @(GET_KLVAL, a1) in @(GIF_THEN_ELSE, VMKCont, @(ILS, i1, i2), \(s : VMKState) @(STAT, b, tr, r, @(LOOPUP, b, i, @(KIVAL, @(INCR, i1)), n2, tr, r, c), @(CHANGE, s, l1, n1)), ERR_VMKCONT), ERR_VMKCONT), \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) ERR_VMKCONT), ERR_VMKCONT), ERR_VMKCONT); dec LOOPDOWN : [Statement -> Identifier -> KEval -> KEval -> KTypeEnv -> KEnv -> VMKCont -> VMKCont];

137

CHAPTER 11. SEMANTICS OF C-VMK

138

def LOOPDOWN = \(b : Statement, i : Identifier, n1 : KEval, n2 : KEval, tr : KTypeEnv, r : KEnv, c : VMKCont) @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, n1), @(GIF_THEN_ELSE, VMKCont, @(IS_KIVAL, n2), let i1 = @(GET_KIVAL, n1), i2 = @(GET_KIVAL, n2) in let l = @(r, i) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, l, \(a1 : KEval) @(GIF_THEN_ELSE, VMKCont, @(IS_KLVAL, a1), let l1 = @(GET_KLVAL, a1) in @(GIF_THEN_ELSE, VMKCont, @(ILS, i2, i1), \(s : VMKState) @(STAT, b, tr, r, @(LOOPDOWN, b, i, @(KIVAL, @(DECR, i1)), n2, tr, r, c), @(CHANGE, s, l1, n1)), ERR_VMKCONT), ERR_VMKCONT), \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) ERR_VMKCONT), ERR_VMKCONT), ERR_VMKCONT);

11.4.2

Semantics of Statements

dec FIND_CALL_DVAL : [Expression -> KEnv -> [KDval -> VMKCont] -> VMKCont];

CHAPTER 11. SEMANTICS OF C-VMK

def FIND_CALL_DVAL = \(e : Expression, r : KEnv, k : [KDval -> VMKCont]) @(GIF_THEN_ELSE, VMKCont, @(IS_IDEN_EXPR, e), let i = @(GET_EXPR_IDEN, e) in @(k, @(r, i)), ERR_VMKCONT); def STATNull = \(tr : KTypeEnv, r : KEnv, c : VMKCont) c; def STATExit = \(tr : KTypeEnv, r : KEnv, c : VMKCont) let cc = @(r, EXITLAB) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, cc, \(a1 : KEval) ERR_VMKCONT, \(a2 : VMKCont) a2, \(a3 : KProc_dval) ERR_VMKCONT); def STATReturn = \(tr : KTypeEnv, r : KEnv, c : VMKCont) let cc = @(r, RETLAB) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, cc, \(a1 : KEval) ERR_VMKCONT, \(a2 : VMKCont) a2, \(a3 : KProc_dval) ERR_VMKCONT); def STATReturnE = \(e : Expression, tr : KTypeEnv, r : KEnv, c : VMKCont) let l = @(r, RETVALLAB) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, l, \(a1 : KEval) @(EXPR, e,

139

CHAPTER 11. SEMANTICS OF C-VMK

140

r, \(v : KEval) let cc = @(r, RETLAB) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, cc, \(b1 : KEval) ERR_VMKCONT, \(b2 : VMKCont, z : VMKState) @(b2, @(CHANGE, z, @(GET_KLVAL, a1), v)), \(b3 : KProc_dval) ERR_VMKCONT)), \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) ERR_VMKCONT); def STATAssignment = \(v : Variable, e : Expression, tr : KTypeEnv, r : KEnv, c : VMKCont) @(REXPR, e, r, \(u : KSval) @(EXPR, v, r, \(w : KSval, z : VMKState) @(c, @(CHANGE, z, @(GET_KLVAL, w), u)))); def STATIfThen = \(e : Expression, b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) let rr = @(ENTER_CON_KENV, r, EXITLAB, c) in @(REXPR, e, rr, \(v : KEval) @(GIF_THEN_ELSE, VMKCont, @(GET_KBVAL, v), @(STAT, b, tr, rr, c), c)); def STATIfThenElse = \(e : Expression, b1 : Statement, b2 : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) let rr = @(ENTER_CON_KENV, r, EXITLAB, c) in @(REXPR, e, rr, \(v : KEval)

CHAPTER 11. SEMANTICS OF C-VMK

@(GIF_THEN_ELSE, VMKCont, @(GET_KBVAL, v), @(STAT, b1, tr, rr, c), @(STAT, b2, tr, rr, c))); def STATWhileLoop = \(e : Expression, b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) let rr = @(ENTER_CON_KENV, r, EXITLAB, c) in @(REXPR, e, rr, \(v : KEval) @(GIF_THEN_ELSE, VMKCont, @(GET_KBVAL, v), @(STAT, @(SEQ, b, @(WHILE, e, b)), tr, rr, c), c)); def STATSequence = \(b1 : Statement, b2 : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) @(STAT, b1, tr, r, @(STAT, b2, tr, r, c)); def STATLabel = \(l : Identifier, b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) @(STAT, b, tr, r, c); def STATGoto = \(l : Identifier, tr : KTypeEnv, r : KEnv, c : VMKCont) let cc = @(r, l) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, cc, \(a1 : KEval) ERR_VMKCONT, \(a2 : VMKCont) a2, \(a3 : KProc_dval) ERR_VMKCONT); def STATWith = \(e : Expression, b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) let nk = \(v : KSval) @(GIF_THEN_ELSE, VMKCont, @(IS_KRVAL, v), let nr = @(GET_KRVAL, v) in @(STAT, b, tr, @(COMP_KENV, r, nr), c), ERR_VMKCONT) in @(EXPR, e, r, nk); def STATProcedureCall =

141

CHAPTER 11. SEMANTICS OF C-VMK

\(p : Expression, l : Expr_list, tr : KTypeEnv, r : KEnv, c : VMKCont) @(FIND_CALL_DVAL, p, r, \(t : KDval) @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, t, \(a1 : KEval) ERR_VMKCONT, \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) @(WHEN5, Procedure, Function, Thunk, Text, Denotation, VMKCont, a3, \(p1 : Procedure) @(p1, r, c, l), \(p2 : Function) ERR_VMKCONT, \(p3 : Thunk) ERR_VMKCONT, \(p4 : Text) ERR_VMKCONT, \(p5 : Denotation) ERR_VMKCONT))); def STATForToLoop = \(i : Identifier, e1 : Expression, e2 : Expression, b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) let rr = @(ENTER_CON_KENV, r, EXITLAB, c) in @(EXPR, e1, rr, \(n1 : KEval) @(EXPR, e2, rr, \(n2 : KEval) @(LOOPUP, b, i, n1, n2, tr, rr, c))); def STATForDownLoop = \(i : Identifier, e1 : Expression, e2 : Expression, b : Statement,

142

CHAPTER 11. SEMANTICS OF C-VMK

tr : KTypeEnv, r : KEnv, c : VMKCont) let rr = @(ENTER_CON_KENV, r, EXITLAB, c) in @(EXPR, e1, rr, \(n1 : KEval) @(EXPR, e2, rr, \(n2 : KEval) @(LOOPDOWN, b, i, n1, n2, tr, rr, c))); def STATRepeat = \(e : Expression, b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) let rr = @(ENTER_CON_KENV, r, EXITLAB, c) in @(STAT, @(SEQ, b, @(WHILE, e, b)), tr, rr, c); def STATLoop = \(b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) let rr = @(ENTER_CON_KENV, r, EXITLAB, c) in @(STAT, @(SEQ, b, @(LOOP, b)), tr, rr, c); def STATBlock = \(t : Type_Decl, d : Declaration, p : Proc, b : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) @(TDECL, t, tr, r, \(tr1 : KTypeEnv) @(DECL, d, tr1, r, \(r1 : KEnv) \(z : VMKState) lec r2 : KEnv in let r2z2 = @(PROC, p, @(COMP_KENV, r1, r2), z) in let r2 = @(PJ1, KEnv, VMKState, r2z2), nz = @(PJ2, KEnv, VMKState, r2z2) in lec r3 : KEnv in let r3 = @(JUMP, b, tr, @(COMP_KENV, r2, r3), c) in @(STAT, b, tr1,

143

CHAPTER 11. SEMANTICS OF C-VMK

144

@(COMP_KENV, r1, @(COMP_KENV, r2, r3)), c, nz)));

We have to write new(i, T) instead of i := new(T). It looks a little bit strange. def STATNew = \(i : Identifier, st : Type_Elem, tr : KTypeEnv, r : KEnv, c : VMKCont) let l = @(r, i) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, l, \(a1 : KEval) @(TDECL_TYPE, i, st, tr, r, @(REF, \(v : KEval, z : VMKState) @(CHANGE, z, @(GET_KLVAL, a1), v))), \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) ERR_VMKCONT); def STATDepose = \(i : Identifier, tr : KTypeEnv, r : KEnv, c : VMKCont) let l = @(r, i) in @(WHEN31, KEval, VMKCont, KProc_dval, VMKCont, l, \(a1 : KEval) let la1 = @(GET_KLVAL, a1) in \(z : VMKState) let b1 = @(GET, z, la1) in let lb1 = @(GET_KLVAL, b1) in @(DELETE, z, lb1), \(a2 : VMKCont) ERR_VMKCONT, \(a3 : KProc_dval) ERR_VMKCONT); def STAT = \(s : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) @(s, VMKCont, %-- Null Statement --% @(STATNull, tr, r, c),

CHAPTER 11. SEMANTICS OF C-VMK

%-- Exit Statement --% @(STATExit, tr, r, c), %-- Return Statement --% @(STATReturn, tr, r, c), %-- Return Statement with Expression --% \(e : Expression) @(STATReturnE, e, tr, r, c), %-- Assignment --% \(i : Variable, e : Expression) @(STATAssignment, i, e, tr, r, c), %-- If-Then --% \(e : Expression, x : VMKCont) let b = @(GET_IFTHEN_STAT, s) in @(STATIfThen, e, b, tr, r, c), %-- If-Then-Else --% \(e : Expression, x1 : VMKCont, x2 : VMKCont) let b1 = @(GET_IFTHEL_THEN, s), b2 = @(GET_IFTHEL_ELSE, s) in @(STATIfThenElse, e, b1, b2, tr, r, c), %-- While-Loop --% \(e : Expression, x : VMKCont) let b = @(GET_WHILE_STAT, s) in @(STATWhileLoop, e, b, tr, r, c), %-- Sequence of Statements --% \(x1 : VMKCont, x2 : VMKCont) let b1 = @(GET_SEQ_HEAD, s), b2 = @(GET_SEQ_TAIL, s) in @(STATSequence, b1, b2, tr, r, c), %-- Label Statement --% \(l : Identifier, x : VMKCont) let b = @(GET_LABEL_STAT, s) in @(STATLabel, l, b, tr, r, c), %-- Goto Statement --% \(l : Identifier) @(STATGoto, l, tr, r, c), %-- With --% \(e : Expression, x : VMKCont) let b = @(GET_WITH_STAT, s) in @(STATWith, e, b, tr, r, c), %-- Procedure Call --% \(p : Expression, l : Expr_list) @(STATProcedureCall, p, l, tr, r, c), %-- For-To-Loop --% \(i : Identifier, e1 : Expression, e2 : Expression, x : VMKCont) let b = @(GET_FORTO_STAT, s) in @(STATForToLoop, i, e1, e2, b, tr, r, c), %-- For-Down-Loop --% \(i : Identifier, e1 : Expression, e2 : Expression, x : VMKCont) let b = @(GET_FORDOWN_STAT, s) in @(STATForDownLoop, i, e1, e2, b, tr, r, c), %-- Repeat --% \(e : Expression, x : VMKCont)

145

CHAPTER 11. SEMANTICS OF C-VMK

let b = @(GET_REPEAT_STAT, s) in @(STATRepeat, e, b, tr, r, c), %-- Loop --% \(x : VMKCont) let b = @(GET_LOOP_STAT, s) in @(STATLoop, b, tr, r, c), %-- Block --% \(t : Type_Decl, d : Declaration, p : Proc, x : VMKCont) let b = @(GET_BLOCK_STAT, s) in @(STATBlock, t, d, p, b, tr, r, c), %-- New --% \(i : Identifier, te : Type_Elem) @(STATNew, i, te, tr, r, c), %-- Depose --% \(i : Identifier) @(STATDepose, i, tr, r, c));

11.4.3

Semantics for Jump

def JUMP = \(s : Statement, tr : KTypeEnv, r : KEnv, c : VMKCont) @(s, KEnv, %-- Null Statement --% EMPTY_KENV, %-- Exit Statement --% EMPTY_KENV, %-- Return Statement --% EMPTY_KENV, %-- Return Statement with Expression --% \(e : Expression) EMPTY_KENV, %-- Assignment --% \(i : Variable, e : Expression) EMPTY_KENV, %-- If-Then --% \(e : Expression, x : KEnv) let b = @(GET_IFTHEN_STAT, s) in @(JUMP, b, tr, r, c), %-- If-Then-Else --% \(e : Expression, x1 : KEnv, x2 : KEnv) let b1 = @(GET_IFTHEL_THEN, s), b2 = @(GET_IFTHEL_ELSE, s) in @(COMP_KENV, @(JUMP, b1, tr, r, c), @(JUMP, b2, tr, r, c)), %-- While-Do --% \(e : Expression, x : KEnv) let b = @(GET_WHILE_STAT, s) in @(JUMP, b, tr, r, @(STAT, s, tr, r, c)), %-- Sequance --% \(x1 : KEnv, x2 : KEnv) let b1 = @(GET_SEQ_HEAD, s),

146

CHAPTER 11. SEMANTICS OF C-VMK

b2 = @(GET_SEQ_TAIL, s) in @(COMP_KENV, @(JUMP, b1, tr, r, @(STAT, b2, tr, r, c)), @(JUMP, b2, tr, r, c)), %-- Label --% \(l : Identifier, x : KEnv) let b = @(GET_LABEL_STAT, s) in @(COMP_KENV, @(JUMP, b, tr, r, c), @(ENTER_CON_KENV, EMPTY_KENV, l, @(STAT, b, tr, r, c))), %-- Goto --% \(l : Identifier) EMPTY_KENV, %-- With --% \(e : Expression, x : KEnv) let b = @(GET_WITH_STAT, s) in @(JUMP, b, tr, r, @(STAT, s, tr, r, c)), %-- Call --% \(p : Expression, l : Expr_list) EMPTY_KENV, %-- For-To --% \(i : Identifier, e1 : Expression, e2 : Expression, x : KEnv) let b = @(GET_FORTO_STAT, s) in @(JUMP, b, tr, r, @(STAT, s, tr, r, c)), %-- For-Down --% \(i : Identifier, e1 : Expression, e2 : Expression, x : KEnv) let b = @(GET_FORDOWN_STAT, s) in @(JUMP, b, tr, r, @(STAT, s, tr, r, c)), %-- Repeat --% \(e : Expression, x : KEnv) let b = @(GET_REPEAT_STAT, s) in @(JUMP, b, tr, r, @(STAT, s, tr, r, c)), %-- Loop --% \(x : KEnv) let b = @(GET_LOOP_STAT, s) in @(JUMP, b, tr, r, @(STAT, s, tr, r, c)), %-- Block --% \(t : Type_Decl, d : Declaration, p : Proc, x : KEnv) EMPTY_KENV, %-- New --% \(i : Identifier, te : Type_Elem) EMPTY_KENV, %-- Depose --% \(i : Identifier) EMPTY_KENV);

11.5

Semantics of Programs

def TOYC_SEMAN = \(p : Program) @(p, VMKCont,

147

CHAPTER 11. SEMANTICS OF C-VMK

\(s : Statement) @(STAT, s, EMPTY_KTENV, EMPTY_KENV, \(x : VMKState) x));

11.6

Hoare Logic Specification

11.6.1

Specifications in Hoare Logic

def VMKHLSpec = \(P : [VMKState -> Prop], C : [VMKState -> VMKState -> Prop], Q : [VMKState -> Prop]) !(s1 : VMKState, s2 : VMKState) [@(P, s1) -> @(C, s1, s2) -> @(Q, s2)];

11.6.2

Termination and Total Correctness

def VMKHLCont = [VMKState -> VMKState -> Prop]; def MkHaltResult = \(C : [VMKState -> VMKState -> Prop], s1 : VMKState, s2 : VMKState, p : @(C, s1, s2)) ; def VMKHLHalts = \(P : [VMKState -> Prop], C : VMKHLCont) !(s1 : VMKState) [@(P, s1) -> ?(s2 : VMKState) @(C, s1, s2)]; def VMKHLDet = \(C : VMKHLCont) \(s : VMKState) !(s1 : VMKState, s2 : VMKState) [@(C, s, s1) -> @(C, s, s2) -> @(Equal, VMKState, s1, s2)]; def VMKHLTotalSpec = \(P : [VMKState -> Prop], C : VMKHLCont, Q : [VMKState -> Prop]) @(And, @(VMKHLHalts, P, C), @(VMKHLSpec, P, C, Q));

148

CHAPTER 11. SEMANTICS OF C-VMK

11.7

State Transition Specification

11.7.1

Specifications as State Transitions

def VMKStateTransit = \(s1 : VMKState, s2 : VMKState) ?(c : VMKCont) @(Equal, VMKState, @(c, s1), s2); def VMKStateTran = \(s1 : VMKState, c : VMKCont, s2 : VMKState) @(Equal, VMKState, @(c, s1), s2);

11.7.2

Termination and Deterministics

def VMKHalts = \(c : VMKCont) !(s1 : VMKState) ?(s2 : VMKState) @(Equal, VMKState, @(c, s1), s2); def VMKDet = \(c : VMKCont) \(s : VMKState) !(s1 : VMKState, s2 : VMKState) [@(Equal, VMKState, @(c, s), s1) -> @(Equal, VMKState, @(c, s), s2) -> @(Equal, VMKState, s1, s2)]

11.8

Equivalence

11.8.1

Strong Equivalence in Hoare Logic

def StEquivHLSem = \(P : [VMKState c1 : [VMKState c2 : [VMKState Q : [VMKState @(And, [@(VMKHLSpec, [@(VMKHLSpec,

-> -> -> ->

Prop], VMKState -> Prop], VMKState -> Prop], Prop])

P, c1, Q) -> @(VMKHLSpec, P, c2, Q)], P, c2, Q) -> @(VMKHLSpec, P, c1, Q)]);

149

CHAPTER 11. SEMANTICS OF C-VMK

11.8.2

150

Strong Equivalence in State Transition System

def StEquivTranSem = \(x1 : VMKState, c1 : VMKCont, c2 : VMKCont, x2 : VMKState) @(And, [@(VMKStateTran, x1, c1, x2) -> @(VMKStateTran, x1, c2, x2)], [@(VMKStateTran, x1, c2, x2) -> @(VMKStateTran, x1, c1, x2)]);

11.8.3

Relationship Between StEquivHLSem and StEquivTranSem

11.8.3.1

From VMKCont to HLVMKCont

def VMKCont2HLCont = \(c : VMKCont) \(z1 : VMKState, z2 : VMKState) @(Equal, VMKState, z2, @(c, z1));

11.8.3.2

StEquivHLSem Is Weaker Than StEquivTranSem

def Tran2HLSpec = \(c : VMKCont, Q : [VMKState -> Prop]) let C = \(z1 : VMKState, z2 : VMKState) @(VMKStateTran, z1, c, z2), P = \(z : VMKState) @(Q, @(c, z)) in @(VMKHLSpec, P, C, Q);

11.8.4

Weak Equivalence in State Transition System

dec StateChangeSet : [VMKState -> VMKState -> @(List, VMKCont)]; dec VMKStSetIncl : [@(List, VMKCont) -> @(List, VMKCont) -> Prop]; def WkEquivTranSem = \(x1 : VMKState, c1 : VMKCont, c2 : VMKCont, x2 : VMKState, x3 : VMKState) [@(VMKStateTran, x1, c1, x2) -> @(VMKStateTran, x1, c2, x3) -> let vmkst_set1 = @(StateChangeSet, x1, x2), vmkst_set2 = @(StateChangeSet, x1, x3) in @(VMKStSetIncl, vmkst_set2, vmkst_set1)];

Chapter 12

Semantics of Utility Functions 12.1

List of APIs

12.1.1

Utility Functions for VMs

dec ClearVMReady : [VMKLocation -> VMKCont]; dec SetVMReady : [VMKLocation -> VMKCont]; dec ExactWaitedVM : [VMKLocation -> VMKCont]; dec ClearVMWaiting : [VMKLocation -> VMKCont]; dec TickNotify : [TickNotifyType -> VMKState -> @(Product, Bool, VMKState)]; dec ClearVM : [VMKLocation -> VMKCont];

12.1.2

Utility Functions in Hoare Logic

dec HLClearVMReady : [VMKLocation -> VMKState -> VMKState -> Prop];

151

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

12.1.3

Constant Definitions

dec VMM_EXCEPTION_SERVICE : Nat; dec NULL_IDENT : Identifier; dec VMK_VMM_ID : VMKLocation; dec VMK_NULL_VID : VMKLocation;

12.1.4

Health Management Functions

dec GetExceptionAction : [Nat -> VMKState -> HMAction]; dec HMResetHook : [Nat -> HMType -> ExcpCont -> VMKCont]; dec HMShutDownHook : [Nat -> HMType -> ExcpCont -> VMKCont]; dec HMIgnoreHook : [Nat -> HMType -> ExcpCont -> VMKCont];

12.1.5

Functions on List of Locations

dec GET_LOC_LIST : [Nat -> @(List, VMKLocation) -> VMKLocation]; dec DEL_LOC_LIST : [VMKLocation -> @(List, VMKLocation) -> @(List, VMKLocation)]; dec GET_LOC_MLIST : [Nat -> MList -> VMKState -> VMKLocation]; dec DEL_LOC_MLIST : [VMKLocation -> MList -> VMKState -> @(And, MList, VMKState)]; dec KSUBSCRIPT : [Array -> @(List, Nat) -> VMKState -> KSval]; dec KSUBSCRIPT_LOC : [Array -> @(List, Nat) -> VMKState -> VMKLocation]; dec TTSSUBSCRIPT : [Array -> Nat -> VMKState -> KSval]; dec TTSSUBSCRIPT_LOC : [Array -> Nat -> VMKState -> VMKLocation]

152

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

12.2

Semantic Function ClearVM

12.2.1

Clear Virtual Interrupt Control Block of Tick

dec ClearVMVTickCB : [VMKLocation -> VMKCont]; def ClearVMVTickCB = \(tickcb_loc : VMKLocation, z : VMKState) let vtickintcb = @(GetVMVTickIntCB, z, tickcb_loc) in let nvtickintcb = @(SetVMVTIntCBFire, vtickintcb, OO) in @(SetVMVTickIntCB, z, tickcb_loc, nvtickintcb);

12.2.2

Clear Virtual Interrupt Control Blocks

dec DoClearVMVIntCB : [VMKLocation -> VMKCont]; def DoClearVMVIntCB = \(intcb_loc : VMKLocation, z : VMKState) let vintcb = @(GetVMVIntCB, z, intcb_loc) in let nvintcb = @(SetVMVIntCBFire, vintcb, FF) in @(SetVMVIntCB, z, intcb_loc, nvintcb); dec ClearVMVIntCBList : [MList -> VMKCont]; def ClearVMVIntCBList = \(l : MList, z : VMKState) @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, l), z, let hl = @(MHEAD, l, z), tl = @(MTAIL, l, z) in let nz = @(DoClearVMVIntCB, @(GET_KLVAL, hl), z) in @(ClearVMVIntCBList, tl, nz)); dec ClearVMVIntCB : [VMKLocation -> VMKCont]; def ClearVMVIntCB = \(vmloc : VMKLocation, z : VMKState) let vm = @(VMCB_GET, z, vmloc) in let vintcb = @(GetVMCBVIntCBlck, vm) in let tickcb = @(GetVMVIntTickCB, vintcb), excpcb = @(GetVMVIntExcpCB, vintcb), extrcb = @(GetVMVIntExtrCB, vintcb),

153

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

servcb = @(GetVMVIntServCB, vintcb) in let z1 = @(ClearVMVTickCB, tickcb, z), z2 = @(ClearVMVIntCBList, excpcb, z1), z3 = @(ClearVMVIntCBList, extrcb, z2), z4 = @(ClearVMVIntCBList, servcb, z3) in let vintcb1 = @(SetVMVIntInit, vintcb, FF), vintcb2 = @(SetVMVIntExcpNum, vintcb1, OO) in let nvm = @(SetVMCBVIntCBlck, vm, vintcb2) in @(VMCB_SET, z4, vmloc, nvm);

12.2.3

Clear VM

dec ClearVM : [VMKLocation -> VMKCont]; def ClearVM = \(vmloc : VMKLocation, z : VMKState) let vm = @(VMCB_GET, z, vmloc) in let vm1 = @(SetVMCBStatus, vm, VMSLEEP), vm2 = @(SetVMCBTickSlice, vm1, @(GetVMCBTickSlSiz, vm1)), vm3 = @(SetVMCBHmContxt, vm2, NullExcpCont), vm4 = @(SetVMCBHmType, vm3, OO), vm5 = @(SetVMCBLeaveTick, vm4, OO), vm6 = @(SetVMCBTickUsage, vm5, OO), vm7 = @(SetVMCBWakeType, vm6, VMWUNull) in let nz = @(VMCB_SET, z, vmloc, vm7) in @(ClearVMVIntCB, vmloc, nz);

12.3

Semantic Function ClearVMReady

dec CLEAR_PRIORITYQ : [PriorityVMQueue -> Nat -> VMKLocation -> VMKState -> VMKState]; def CLEAR_PRIORITYQ = \(qarray : PriorityVMQueue, index : Nat, vm_loc : VMKLocation, z : VMKState) let vmqarray = @(GET_PVMQ_ARRAY, qarray), vmprnumb = @(GET_PVMQ_MNUMB, qarray) in let vmq = @(KSUBSCRIPT, vmqarray, @(CONS, Nat, index, @(NIL, Nat)), z) in

154

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

@(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, vm_loc), vmq, z), let nvmq2z = @(DEL_MLIST, @(KLVAL, vm_loc), vmq, z) in let nvmq = @(PJ1, MList, VMKState, nvmq2z), nz = @(PJ2, MList, VMKState, nvmq2z) in @(KASSIGN, vmqarray, @(CONS, Nat, index, @(NIL, Nat)), nvmq, nz), z); dec DoGetHighPriorVM : [PriorityVMQueue -> Nat -> VMKState -> VMKLocation]; def DoGetHighPriorVM = \(qarray : PriorityVMQueue, index : Nat, z : VMKState) let vmqarray = @(GET_PVMQ_ARRAY, qarray), vmprnumb = @(GET_PVMQ_MNUMB, qarray) in let vmq = @(KSUBSCRIPT, vmqarray, @(CONS, Nat, index, @(NIL, Nat)), z) in @(GIF_THEN_ELSE, VMKLocation, @(IS_ZERO, index), @(GIF_THEN_ELSE, VMKLocation, @(IS_EMPTY_MLIST, vmq), ERR_VMKLOC, @(GET_KLVAL, @(MHEAD, vmq, z))), @(GIF_THEN_ELSE, VMKLocation, @(IS_EMPTY_MLIST, vmq), @(DoGetHighPriorVM, qarray, @(PP, index), z), @(GET_KLVAL, @(MHEAD, vmq, z)))); dec GetHighPriorVM : [PriorityVMQueue -> VMKState -> VMKLocation]; def GetHighPriorVM = \(qarray : PriorityVMQueue, z : VMKState) let vmqarray = @(GET_PVMQ_ARRAY, qarray), vmprnumb = @(GET_PVMQ_MNUMB, qarray) in @(DoGetHighPriorVM, qarray, vmprnumb, z); dec ClearVMReady : [VMKLocation -> VMKCont]; def ClearVMReady = \(vm_loc : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let vm = @(VMCB_GET, nz, vm_loc) in let vm_status = @(GetVMCBStatus, vm), vm_schedule_type = @(GetVMCBSchedType, vm), vm_priority = @(GetVMCBPriority, vm) in let vm1 = @(SetVMCBStatus, vm, @(BitAndVMStatus, vm_status, @(SetVMNotREADY, VMREADY))) in let nz1 = @(VMCB_SET, nz, vm_loc, vm1) in @(GIF_THEN_ELSE,

155

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

VMKState, @(IsVMSchedulePr, vm_schedule_type), let priority_queue = @(GET_VMKMAN_PRIOTQ, vmk_manager) in let nz2 = @(CLEAR_PRIORITYQ, priority_queue, vm_priority, vm_loc, nz1) in let high_prior_qvm = @(GetHighPriorVM, priority_queue, nz1) in let nvmk_manager = @(SET_VMKMAN_PQUEVM, vmk_manager, high_prior_qvm) in @(CHANGE, nz2, VMK_MANAGER_LOC, nvmk_manager), let ttsvm = @(GET_VMKMAN_TTSVM, vmk_manager), curtts = @(GET_VMKMAN_CURTTS, vmk_manager), idlevm = @(GET_VMKMAN_IDLEVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(AND, @(EQ_VMKLOC, vm_loc, ttsvm), @(NOT, @(EQ_VMKLOC, curtts, NIL_VMKLOC))), let curttscb = @(TTSCB_GET, nz1, curtts), ncurttscb = @(SetTTSStatus, curttscb, TTSWaitStatus) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, idlevm) in @(TTSCB_SET, nz1, curtts, ncurttscb), nz1));

12.4

Semantic Function SetVMReady

dec DO_KSUBSCRIPT : [@(List, @(Product, Nat, Nat)) -> @(List, Nat) -> Nat -> Nat]; def DO_KSUBSCRIPT = \(pl : @(List, @(Product, Nat, Nat)), nl : @(List, Nat), n : Nat) @(GIF_THEN_ELSE, Nat, @(AND, @(IS_EMPTY, @(Product, Nat, Nat), pl), @(IS_EMPTY, Nat, nl)), n, @(GIF_THEN_ELSE, Nat, @(OR, @(IS_EMPTY, @(Product, Nat, Nat), pl), @(IS_EMPTY, Nat, nl)), ERR_NAT, let hpl = @(HEAD, @(Product, Nat, Nat), pl), tpl = @(TAIL, @(Product, Nat, Nat), pl) in let hnl = @(HEAD, Nat, nl), tnl = @(TAIL, Nat, nl) in let lb = @(PRO1, Nat, Nat, hpl),

156

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

157

ub = @(PRO2, Nat, Nat, hpl) in let nn = @(ADD, @(TIMES, n, @(SS, @(MINUS, ub, lb))), hnl) in @(DO_KSUBSCRIPT, tpl, tnl, nn))); dec KSUBSCRIPT : [Array -> @(List, Nat) -> VMKState -> KSval]; def KSUBSCRIPT = \(a : Array, vl : @(List, Nat), z : VMKState) let bl = @(GET_ARRAY_RANLST, a), ll = @(GET_ARRAY_LOC, a) in let nv = @(DO_KSUBSCRIPT, bl, vl, OO) in let loc = @(GET_LOC_LIST, nv, ll) in @(GET, z, loc); dec KSUBSCRIPT_LOC : [Array -> @(List, Nat) -> VMKState -> VMKLocation]; def KSUBSCRIPT_LOC = \(a : Array, vl : @(List, Nat), z : VMKState) let bl = @(GET_ARRAY_RANLST, a), ll = @(GET_ARRAY_LOC, a) in let nv = @(DO_KSUBSCRIPT, bl, vl, OO) in @(GET_LOC_LIST, nv, ll); dec INSERT_LAST : !(U : Prop) [@(List, U) -> U -> @(List, U)]; dec ADD_PRIORITYQ : [PriorityVMQueue -> Nat -> VMKLocation -> VMKState -> VMKState]; def ADD_PRIORITYQ = \(q : PriorityVMQueue, n : Nat, l : VMKLocation, z : VMKState) let vmqarray = @(GET_PVMQ_ARRAY, q), vmprnumb = @(GET_PVMQ_MNUMB, q) in let vmq = @(KSUBSCRIPT, vmqarray, @(CONS, Nat, n, @(NIL, Nat)), z) in let nvmq2z = @(INSERT_LAST_MLIST, vmq, @(KLVAL, l), z) in let nvmq = @(PJ1, MList, VMKState, nvmq2z), nz = @(PJ2, MList, VMKState, nvmq2z) in @(KASSIGN, vmqarray, @(CONS, Nat, n, @(NIL, Nat)), nvmq, nz); dec DoGetHighPriorVM : [PriorityVMQueue -> Nat -> VMKState -> VMKLocation]; def DoGetHighPriorVM = \(q : PriorityVMQueue, n : Nat, z : VMKState) let vmqarray = @(GET_PVMQ_ARRAY, q), vmprnumb = @(GET_PVMQ_MNUMB, q) in @(GIF_THEN_ELSE,

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

158

VMKLocation, @(EQUAL, n, ERR_NAT), ERR_VMKLOC, let vmq = @(KSUBSCRIPT, vmqarray, @(CONS, Nat, n, @(NIL, Nat)), z) in @(GIF_THEN_ELSE, VMKLocation, @(IS_EMPTY_MLIST, vmq), @(DoGetHighPriorVM, q, @(PP, n), z), @(GET_KLVAL, @(MHEAD, vmq, z)))); dec GetHighPriorVM : [PriorityVMQueue -> VMKState -> VMKLocation]; def GetHighPriorVM = \(q : PriorityVMQueue, z : VMKState) let vmqarray = @(GET_PVMQ_ARRAY, q), vmprnumb = @(GET_PVMQ_MNUMB, q) in @(DoGetHighPriorVM, q, vmprnumb, z); dec SetVMReady : [VMKLocation -> VMKCont]; def SetVMReady = \(vm_loc : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let vm = @(VMCB_GET, nz, vm_loc) in let vm1 = @(SetVMCBStatus, vm, @(InclOrVMStatus, @(GetVMCBStatus, vm), VMREADY)) in let vm_schedule_type = @(GetVMCBSchedType, vm1), vm_priority = @(GetVMCBPriority, vm1) in @(GIF_THEN_ELSE, VMKState, @(IsVMSchedulePr, vm_schedule_type), let priority_queue = @(GET_VMKMAN_PRIOTQ, vmk_manager) in let nz1 = @(ADD_PRIORITYQ, priority_queue, vm_priority, vm_loc, nz) in let high_prior_qvm = @(GetHighPriorVM, priority_queue, nz1) in let vm2 = @(SetVMCBTickSlice, vm1, @(GetVMCBTickSlSiz, vm1)) in let nz2 = @(VMCB_SET, nz1, vm_loc, vm2) in let nvmk_manager = @(SET_VMKMAN_PQUEVM, vmk_manager, high_prior_qvm) in @(CHANGE, nz2, VMK_MANAGER_LOC, nvmk_manager), let ttsvm = @(GET_VMKMAN_TTSVM, vmk_manager), curtts = @(GET_VMKMAN_CURTTS, vmk_manager), idlevm = @(GET_VMKMAN_IDLEVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, curtts, NIL_VMKLOC), nz,

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

159

let curttscb = @(TTSCB_GET, nz, curtts) in let tts_status = @(GetTTSStatus, curttscb), tts_cur_win = @(GetTTSCurrentWin, curttscb), tts_nodes = @(GetTTSNodes, curttscb) in let ttsv = @(KSUBSCRIPT, tts_nodes, @(CONS, Nat, tts_cur_win, @(NIL, Nat)), nz) in let ttsvloc = @(GET_KLVAL, ttsv) in @(GIF_THEN_ELSE, VMKState, @(AND, @(IsTTSWaitStatus, tts_status), @(EQ_VMKLOC, ttsvloc, vm_loc)), let ncurttscb = @(SetTTSStatus, curttscb, TTSWaitStatus), nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, vm_loc) in let z1 = @(VMCB_SET, nz, vm_loc, vm1), z2 = @(CHANGE, z1, VMK_MANAGER_LOC, nvmk_manager), z3 = @(TTSCB_SET, z2, curtts, ncurttscb) in z3, nz)));

12.5

Semantic Function ExactWaitedVM

dec MODIFY_WT_LIST : [VMKState -> VMKLocation -> MList -> @(Product, VMKState, MList)]; def MODIFY_WT_LIST = \(z : VMKState, vm_loc : VMKLocation, l : MList) @(GIF_THEN_ELSE, @(Product, VMKState, MList), @(IS_EMPTY_MLIST, l), @(PRODUCT, VMKState, MList, z, l), let hl = @(MHEAD, l, z), tl = @(MTAIL, l, z) in @(GIF_THEN_ELSE, @(Product, VMKState, MList), @(EQ_VMKLOC, @(GET_KLVAL, hl), vm_loc), @(GIF_THEN_ELSE, @(Product, VMKState, MList), @(IS_EMPTY_MLIST, tl), @(PRODUCT, VMKState, MList, z, tl), let next_wt_vm_loc = @(MHEAD, tl, z) in let vm = @(VMCB_GET, z, vm_loc), next_wt_vm = @(VMCB_GET, z, @(GET_KLVAL, next_wt_vm_loc)) in let waited_tick = @(GetVMCBWaitTick, vm), next_waited_tick = @(GetVMCBWaitTick, next_wt_vm) in let next_wt_vm1 = @(SetVMCBWaitTick, next_wt_vm,

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

160

@(ADD, waited_tick, next_waited_tick)) in let z1 = @(VMCB_SET, z, @(GET_KLVAL, next_wt_vm_loc), next_wt_vm1) in @(PRODUCT, VMKState, MList, z1, tl)), let z2l = @(MODIFY_WT_LIST, z, vm_loc, tl) in let z1 = @(PJ1, VMKState, MList, z2l), tl1 = @(PJ2, VMKState, MList, z2l) in let z2l2 = @(MCONS, hl, tl1, z1) in let z2 = @(PJ2, MList, VMKState, z2l2), tl2 = @(PJ1, MList, VMKState, z2l2) in @(PRODUCT, VMKState, MList, z2, tl2))); dec ExactWaitedVM : [VMKLocation -> VMKCont]; def ExactWaitedVM = \(vm_loc : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let vm = @(VMCB_GET, nz, vm_loc) in let tick_waited_vms = @(GET_VMKMAN_TICKWT, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, vm_loc), tick_waited_vms, nz), let z2l = @(MODIFY_WT_LIST, nz, vm_loc, tick_waited_vms) in let z1 = @(PJ1, VMKState, MList, z2l), tick_waited_vms1 = @(PJ2, VMKState, MList, z2l) in let nvmk_manager = @(SET_VMKMAN_TICKWT, vmk_manager, tick_waited_vms1) in let z2 = @(CHANGE, z1, VMK_MANAGER_LOC, nvmk_manager) in let nvm = @(SetVMCBWaitTick, vm, OO) in @(VMCB_SET, z2, vm_loc, nvm), let nvm = @(SetVMCBWaitTick, vm, OO) in @(VMCB_SET, nz, vm_loc, nvm));

12.6

Semantic Function ClearVMWaiting

dec ClearVMWaiting : [VMKLocation -> VMKCont]; def ClearVMWaiting = \(vm_loc : VMKLocation, nz : VMKState) let vm = @(VMCB_GET, nz, vm_loc) in let vm_status = @(GetVMCBStatus, vm), nvm_status = @(BitAndVMStatus, vm_status, @(SetVMNotWAIT, VMWAIT)) in let vm1 = @(SetVMCBStatus, vm, nvm_status), vm2 = @(SetVMCBWakeType, vm1, VMWUNull) in let z1 = @(VMCB_SET, nz, vm_loc, vm2) in @(GIF_THEN_ELSE,

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

VMKState, @(NOT, @(IS_VMSUSPEND, nvm_status)), @(SetVMReady, vm_loc, z1), z1);

12.7

Semantic Function TickNotify

dec DoTTSWinServInt : [Nat -> VMCB -> VMKCont]; def DoTTSWinServInt = \(vector : Nat, vm : VMCB, z : VMKState) let vint_block = @(GetVMCBVIntCBlck, vm) in let vint_init = @(GetVMVIntInit, vint_block), vint_serv = @(GetVMVIntServCB, vint_block) in let serv_int_loc = @(GET_LOC_MLIST, vector, vint_serv, z) in @(GIF_THEN_ELSE, VMKState, vint_init, let servintcb = @(GetVMVIntCB, z, serv_int_loc) in let nservintcb = @(SetVMVIntCBFire, servintcb, TT) in @(SetVMVIntCB, z, serv_int_loc, nservintcb), z); dec DoVTickIntCount : [VMCB -> VMKCont]; def DoVTickIntCount = \(vm : VMCB, z : VMKState) let leave_tick = @(GetVMCBLeaveTick, vm) in @(GIF_THEN_ELSE, VMKState, @(IS_ZERO, leave_tick), let vint_block = @(GetVMCBVIntCBlck, vm) in let tickintcb_loc = @(GetVMVIntTickCB, vint_block) in let tickintcb = @(GetVMVTickIntCB, z, tickintcb_loc) in let ticks = @(GetVMVTIntCBFire, tickintcb) in let ntickintcb = @(SetVMVTIntCBFire, tickintcb, @(SS, ticks)) in @(SetVMVTickIntCB, z, tickintcb_loc, ntickintcb), z); dec RRSchedule : [VMKLocation -> VMKCont]; def RRSchedule = \(vm_loc : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let vm = @(VMCB_GET, nz, vm_loc) in let vm_tick_slice = @(GetVMCBTickSlice, vm), vm_tick_slice_size = @(GetVMCBTickSlSiz, vm), vm_priority = @(GetVMCBPriority, vm) in let vm_priority_queue = @(GET_VMKMAN_PRIOTQ, vmk_manager) in

161

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

let vmqarray = @(GET_PVMQ_ARRAY, vm_priority_queue), vmprnumb = @(GET_PVMQ_MNUMB, vm_priority_queue) in let vm_loc_list = @(KSUBSCRIPT, vmqarray, @(CONS, Nat, vm_priority, @(NIL, Nat)), nz) in @(GIF_THEN_ELSE, VMKState, @(IS_ZERO, vm_tick_slice), let vm1 = @(SetVMCBTickSlice, vm, vm_tick_slice_size) in @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, vm_loc_list), nz, let hvm_loc = @(MHEAD, vm_loc_list, nz), tvm_loc_list = @(MTAIL, vm_loc_list, nz) in let vm_loc_list2z = @(INSERT_LAST_MLIST, hvm_loc, tvm_loc_list, nz) in let vm_loc_list1 = @(PJ1, MList, VMKState, vm_loc_list2z), z0 = @(PJ2, MList, VMKState, vm_loc_list2z) in let z1 = @(KASSIGN, vmqarray, @(CONS, Nat, vm_priority, @(NIL, Nat)), vm_loc_list1, z0) in let nvmk_manager = @(SET_VMKMAN_PQUEVM, vmk_manager, @(GET_KLVAL, @(MHEAD, vm_loc_list1, z1))) in @(CHANGE, z1, VMK_MANAGER_LOC, nvmk_manager)), nz); dec DoTickWaitedVM : VMKCont; dec CheckTickWaitedVM : [MList -> VMKCont]; def CheckTickWaitedVM = \(l : MList, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, l), nz, let vm_loc = @(MHEAD, l, nz), tail_l = @(MTAIL, l, nz) in let vm = @(VMCB_GET, nz, @(GET_KLVAL, vm_loc)) in let waited_tick = @(GetVMCBWaitTick, vm) in @(GIF_THEN_ELSE, VMKState, @(IS_ZERO, waited_tick), let nvmk_manager = @(SET_VMKMAN_TICKWT, vmk_manager, tail_l) in let z1 = @(CHANGE, nz, VMK_MANAGER_LOC, nvmk_manager), z2 = @(ClearVMWaiting, @(GET_KLVAL, vm_loc), z1) in @(CheckTickWaitedVM, tail_l, z2),

162

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

nz)); def DoTickWaitedVM = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let nodes = @(GET_VMKMAN_TICKWT, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, nodes), nz, let vm_loc = @(MHEAD, nodes, nz), tail_l = @(MTAIL, nodes, nz) in let vm = @(VMCB_GET, nz, @(GET_KLVAL, vm_loc)) in let waited_tick = @(GetVMCBWaitTick, vm) in let nwaited_tick = @(PP, waited_tick) in let vm1 = @(SetVMCBWaitTick, vm, nwaited_tick) in let z1 = @(VMCB_SET, nz, @(GET_KLVAL, vm_loc), vm1) in @(CheckTickWaitedVM, nodes, z1)); dec TTS_WIN_SERV_INT : Nat; dec ClearVMWaitUp : [VMCB -> VMCB]; dec TickNotify : [TickNotifyType -> VMKState -> @(Product, Bool, VMKState)]; def SystTickNotify = \(type : TickNotifyType, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), vmk_tick = @(GET_VMKMAN_TICKCN, vmk_manager) in let vm = @(VMCB_GET, nz, vm_loc) in let nvmk_tick = @(SS, vmk_tick) in let vm_tick = @(GetVMCBTickUsage, vm), nvm_tick = @(SS, vm_tick) in let vm_leave_tick = @(GetVMCBLeaveTick, vm), vm_schedule_type = @(GetVMCBSchedType, vm) in let nvm = @(SetVMCBTickUsage, vm, nvm_tick), z0 = @(GIF_THEN_ELSE, VMKState, @(IS_ZERO, vm_leave_tick), @(DoVTickIntCount, nvm, nz), nz) in let nvmk_manager = @(SET_VMKMAN_TICKCN, vmk_manager, nvmk_tick) in let z1 = @(CHANGE, z0, VMK_MANAGER_LOC, nvmk_manager), z2 = @(GIF_THEN_ELSE, VMKState, @(IsVMSchedulePr, vm_schedule_type), @(RRSchedule, vm_loc, z1), z1), z3 = @(VMCB_SET, z2, vm_loc, nvm) in @(DoTickWaitedVM, z3);

163

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

def CheckWindowTick = \(tts_loc : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let tts = @(TTSCB_GET, nz, tts_loc) in let status = @(GetTTSStatus, tts), node_max = @(GETTTSNodeMax, tts), main_frame_ticks = @(GetTTSMFrameTick, tts), window_ticks = @(GetTTSWindowTick, tts), frame_ticks = @(GetTTSFrameTick, tts), frames = @(GetTTSFrames, tts), current_window = @(GetTTSCurrentWin, tts), nodes = @(GetTTSNodes, tts) in let node_index = @(GIF_THEN_ELSE, Nat, @(IsTTSIdle, status), current_window, @(SS, current_window)) in let node = @(TTSSUBSCRIPT, nodes, node_index, nz) in let node_id = @(GetTTSNodId, node), node_start_time = @(GetTTSNodStart, node), node_during_time = @(GetTTSNodDuring, node) in @(GIF_THEN_ELSE, VMKState, @(IS_ZERO, node_during_time), let tts1 = @(SetTTSStatus, tts, TTSWaitFrame) in let z1 = @(TTSCB_SET, nz, tts_loc, tts1) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in @(CHANGE, z1, VMK_MANAGER_LOC, nvmk_manager), let tts1 = @(SetTTSCurrentWin, tts, node_index) in @(GIF_THEN_ELSE, VMKState, @(NGT, node_start_time, frame_ticks), let tts2 = @(SetTTSStatus, tts1, TTSIdle), tts3 = @(SetTTSWindowTick, tts2, @(MINUS, node_start_time, frame_ticks)) in let z1 = @(TTSCB_SET, nz, tts_loc, tts3) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in @(CHANGE, z1, VMK_MANAGER_LOC, nvmk_manager), let tts2 = @(SetTTSWindowTick, tts1, node_during_time) in let vm = @(VMCB_GET, nz, node_id) in let vm1 = @(ClearVMWaitUp, vm) in let vm_schedule_type = @(GetVMCBSchedType, vm1), vm_status = @(GetVMCBStatus, vm1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(IsVMScheduleTT, vm_schedule_type)), let tts3 = @(SetTTSStatus, tts2, TTSAbort) in

164

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

let z1 = @(TTSCB_SET, nz, tts_loc, tts3), z2 = @(VMCB_SET, z1, node_id, vm1) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in @(CHANGE, z2, VMK_MANAGER_LOC, nvmk_manager), @(GIF_THEN_ELSE, VMKState, @(NOT, @(IS_VMREADY, vm_status)), let tts3 = @(SetTTSStatus, tts2, TTSWaitStatus) in let z1 = @(TTSCB_SET, nz, tts_loc, tts3), z2 = @(VMCB_SET, z1, node_id, vm1) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in @(CHANGE, z2, VMK_MANAGER_LOC, nvmk_manager), let tts3 = @(SetTTSStatus, tts2, TTSRunning) in let z1 = @(TTSCB_SET, nz, tts_loc, tts3) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, node_id) in let z2 = @(DoTTSWinServInt, TTS_WIN_SERV_INT, vm1, z1), z3 = @(VMCB_SET, z2, node_id, vm1) in @(CHANGE, z3, VMK_MANAGER_LOC, nvmk_manager))))); dec DoTTSEnd : [VMKLocation -> VMKState -> @(Product, Bool, VMKState)]; def CheckFrameTick = \(tts_loc : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let tts = @(TTSCB_GET, nz, tts_loc) in let status = @(GetTTSStatus, tts), node_max = @(GETTTSNodeMax, tts), main_frame_ticks = @(GetTTSMFrameTick, tts), window_ticks = @(GetTTSWindowTick, tts), frame_ticks = @(GetTTSFrameTick, tts), frames = @(GetTTSFrames, tts), current_window = @(GetTTSCurrentWin, tts), nodes = @(GetTTSNodes, tts) in let tts1 = @(SetTTSFrameTick, tts, OO), tts2 = @(SetTTSFrames, tts1, @(SS, frames)), tts3 = @(SetTTSCurrentWin, tts2, OO) in let node = @(TTSSUBSCRIPT, nodes, OO, nz) in let node_id = @(GetTTSNodId, node), node_start_time = @(GetTTSNodStart, node), node_during_time = @(GetTTSNodDuring, node) in @(GIF_THEN_ELSE, VMKState, @(NGT, node_start_time, frame_ticks), let tts4 = @(SetTTSStatus, tts3, TTSIdle), tts5 = @(SetTTSWindowTick, tts4,

165

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

@(MINUS, node_start_time, frame_ticks)) in let z1 = @(TTSCB_SET, nz, tts_loc, tts5) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in @(CHANGE, z1, VMK_MANAGER_LOC, nvmk_manager), let tts4 = @(SetTTSWindowTick, tts3, node_during_time) in let vm = @(VMCB_GET, nz, node_id) in let vm1 = @(ClearVMWaitUp, vm) in let vm_schedule_type = @(GetVMCBSchedType, vm1), vm_status = @(GetVMCBStatus, vm1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(IsVMScheduleTT, vm_schedule_type)), let tts5 = @(SetTTSStatus, tts4, TTSAbort) in let z1 = @(TTSCB_SET, nz, tts_loc, tts5) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in let z2 = @(VMCB_SET, z1, node_id, vm1) in @(CHANGE, z2, VMK_MANAGER_LOC, nvmk_manager), @(GIF_THEN_ELSE, VMKState, @(NOT, @(IS_VMREADY, vm_status)), let tts5 = @(SetTTSStatus, tts4, TTSWaitStatus) in let z1 = @(TTSCB_SET, nz, tts_loc, tts5) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in let z2 = @(VMCB_SET, z1, node_id, vm1) in @(CHANGE, z2, VMK_MANAGER_LOC, nvmk_manager), let tts5 = @(SetTTSStatus, tts4, TTSRunning) in let z1 = @(TTSCB_SET, nz, tts_loc, tts5) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, node_id) in let z2 = @(DoTTSWinServInt, TTS_WIN_SERV_INT, vm1, z1), z3 = @(VMCB_SET, z2, node_id, vm1) in @(CHANGE, z3, VMK_MANAGER_LOC, nvmk_manager)))); def DoTTSEnd = \(tts_loc : VMKLocation, z : VMKState) let tts = @(TTSCB_GET, z, tts_loc) in let status = @(GetTTSStatus, tts), main_frame_ticks = @(GetTTSMFrameTick, tts), frame_ticks = @(GetTTSFrameTick, tts), window_ticks = @(GetTTSWindowTick, tts) in @(GIF_THEN_ELSE, @(Product, Bool, VMKState), @(NOT, @(NEQ, main_frame_ticks, frame_ticks)), let z1 = @(GIF_THEN_ELSE, VMKState, @(IsTTSWaitFrame, status), @(SetTTSTick,

166

CHAPTER 12. SEMANTICS OF UTILITY FUNCTIONS

@(MINUS, main_frame_ticks, frame_ticks), VMK_FRAMETICK, z), @(SetTTSTick, window_ticks, VMK_WINDOWTICK, z)) in @(PRODUCT, Bool, VMKState, FF, z1), @(PRODUCT, Bool, VMKState, TT, z)); def TickNotify = \(type : TickNotifyType, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let z1 = @(GLOBAL_INT_DISABLE, nz) in let z2 = @(GIF_THEN_ELSE, VMKState, @(IS_VMK_SYSTICK, type), @(SystTickNotify, type, z1), z1) in let tts_loc = @(GET_VMKMAN_CURTTS, vmk_manager) in let z3 = @(GIF_THEN_ELSE, VMKState, @(AND, @(NOT, @(EQ_VMKLOC, tts_loc, NIL_VMKLOC)), @(OR, @(IS_VMK_WINDOWTICK, type), @(IS_VMK_FRAMETICK, type))), let z4 = @(GIF_THEN_ELSE, VMKState, @(IS_VMK_WINDOWTICK, type), @(CheckWindowTick, tts_loc, z2), z2) in @(GIF_THEN_ELSE, VMKState, @(IS_VMK_FRAMETICK, type), @(CheckFrameTick, tts_loc, z4), z4), z2) in let ret2z = @(DoTTSEnd, tts_loc, z3) in let ret = @(PJ1, Bool, VMKState, ret2z), z5 = @(PJ2, Bool, VMKState, ret2z) in @(PRODUCT, Bool, VMKState, ret, @(GLOBAL_INT_ENABLE, z5));

167

Chapter 13

Semantics of APIs for VMs 13.1 dec dec dec dec dec dec dec dec dec

13.2

List of APIs VM_GET_ID VM_GET_NAME VM_GET_STATUS VM_HALT VM_START VM_STOP VM_SUSPEND VM_RESUME VM_RESET

: : : : : : : : :

[Statement -> [Statement -> [Statement -> [VMWakeupType [Statement -> [Statement -> [Statement -> [Statement -> [Statement ->

KEnv -> VMKCont -> VMKCont]; KEnv -> VMKCont -> VMKCont]; KEnv -> VMKCont -> VMKCont]; -> Nat -> VMKCont -> VMKCont]; KEnv -> VMKCont -> VMKCont]; KEnv -> VMKCont -> VMKCont]; KEnv -> VMKCont -> VMKCont]; KEnv -> VMKCont -> VMKCont]; KEnv -> VMKCont -> VMKCont];

Semantics of VM GET ID

def VM_GET_ID = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(GET_VMGETID_IDENT, s), vmrloc = @(GET_VMGETID_RNLOC, s), vmretc = @(GET_VMGETID_RETCD, s) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let dv = @(r, vmname) in @(GIF_THEN_ELSE, VMKState, @(IsEval4Dval, dv), let v1 = @(GetEval4Dval, @(r, vmname)), v2 = @(GetEval4Dval, @(r, vmrloc)), v3 = @(GetEval4Dval, @(r, vmretc)) in @(GIF_THEN_ELSE, VMKState,

168

CHAPTER 13. SEMANTICS OF APIS FOR VMS

@(IS_KLVAL, v1), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), v1), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2), let z1 = @(CHANGE, nz, @(GET_KLVAL, v3), @(KIVAL, VMK_FAIL)) in @(c, z1)), let v3 = @(GetEval4Dval, @(r, vmretc)) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v3), @(KIVAL, VMK_FAIL)) in @(c, z1));

13.3

Semantics of VM GET NAME

def VM_GET_NAME = \(s : Statement, r : KEnv, c : VMKCont) let vmrloc = @(GET_VMGETNM_RNLOC, s), vmname = @(GET_VMGETNM_IDENT, s), vmretc = @(GET_VMGETNM_RETCD, s) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let dv = @(r, vmrloc) in @(GIF_THEN_ELSE, VMKState, @(IsEval4Dval, dv), let v1 = @(GetEval4Dval, @(r, vmrloc)), v2 = @(GetEval4Dval, @(r, vmname)), v3 = @(GetEval4Dval, @(r, vmretc)) in @(GIF_THEN_ELSE, VMKState, @(IS_KIVAL, v1), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), v1), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2), let z1 = @(CHANGE, nz, @(GET_KLVAL, v3), @(KIVAL, VMK_FAIL)) in @(c, z1)), let v3 = @(GetEval4Dval, @(r, vmretc)) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v3), @(KIVAL, VMK_FAIL)) in @(c, z1));

13.4

Semantics of VM GET STATUS

def VM_GET_STATUS = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(GET_VMGETST_IDENT, s), vmstat = @(GET_VMGETST_STATU, s), vmretc = @(GET_VMGETST_RETCD, s) in \(nz : VMKState)

169

CHAPTER 13. SEMANTICS OF APIS FOR VMS

let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let v1 = @(GetEval4Dval, @(r, vmname)), v2 = @(GetEval4Dval, @(r, vmstat)), v3 = @(GetEval4Dval, @(r, vmretc)) in let thevmname = @(GET_KTVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(EQ_IDENT, thevmname, CURRENT_VM_NAME), let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vmcb = @(VMCB_GET, nz, current_vm_loc) in let vmcb_status = @(GetVMCBStatus, vmcb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), vmcb_status), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2), let vmcb = @(VMCB_GET, nz, @(GET_KLVAL, v1)) in let vmcb_status = @(GetVMCBStatus, vmcb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), vmcb_status), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2));

13.5

Semantics of VM HALT

def DoInsertWaitedVM = \(z : VMKState, vml : MList, l : VMKLocation) let vmk_manager = @(GET, z, VMK_MANAGER_LOC), vm = @(VMCB_GET, z, l) in @(GIF_THEN_ELSE, @(Product, VMKState, MList), @(IS_EMPTY_MLIST, vml), let l2z = @(MCONS, @(KLVAL, l), vml, z) in let nl = @(PJ1, MList, VMKState, l2z), nz = @(PJ2, MList, VMKState, l2z) in @(PRODUCT, VMKState, MList, nz, nl), let hvml = @(MHEAD, vml, z), tvml = @(MTAIL, vml, z) in let vm_waited = @(VMCB_GET, z, @(GET_KLVAL, hvml)) in @(GIF_THEN_ELSE, @(Product, VMKState, MList), @(NGT, @(GetVMCBWaitTick, vm), @(GetVMCBWaitTick, vm_waited)), let vm1 = @(SetVMCBWaitTick, vm, @(MINUS, @(GetVMCBWaitTick, vm), @(GetVMCBWaitTick, vm_waited))) in let z1 = @(VMCB_SET, z, l, vm1) in let z2vml = @(DoInsertWaitedVM, z1, tvml, l) in let z2 = @(PJ1, VMKState, MList, z2vml), vml2 = @(PJ2, VMKState, MList, z2vml) in let l2z = @(MCONS, hvml, vml2, z2) in let nl = @(PJ1, MList, VMKState, l2z),

170

CHAPTER 13. SEMANTICS OF APIS FOR VMS

nz = @(PJ2, MList, VMKState, l2z) in @(PRODUCT, VMKState, MList, nz, nl), let vm_waited1 = @(SetVMCBWaitTick, vm_waited, @(MINUS, @(GetVMCBWaitTick, vm_waited), @(GetVMCBWaitTick, vm))) in let z1 = @(VMCB_SET, z, @(GET_KLVAL, hvml), vm_waited1) in let l2z = @(MCONS, @(KLVAL, l), vml, z1) in let nl = @(PJ1, MList, VMKState, l2z), nz = @(PJ2, MList, VMKState, l2z) in @(PRODUCT, VMKState, MList, nz, nl))); dec InsertWaitedVM : [VMKState -> VMKLocation -> Nat -> VMKState]; def InsertWaitedVM = \(z : VMKState, vm_loc : VMKLocation, tick : Nat) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let vm = @(VMCB_GET, z, vm_loc) in let vm1 = @(SetVMCBWaitTick, vm, tick) in let tickwaitvml = @(GET_VMKMAN_TICKWT, vmk_manager) in let z2vml = @(DoInsertWaitedVM, z, tickwaitvml, vm_loc) in let z2 = @(PJ1, VMKState, MList, z2vml), ntickwaitvml = @(PJ2, VMKState, MList, z2vml) in let nvmk_manager = @(SET_VMKMAN_TICKWT, vmk_manager, ntickwaitvml) in @(CHANGE, z2, VMK_MANAGER_LOC, nvmk_manager); dec SetCurrentTTSStatus : [VMKState -> TTSStatusType -> VMKState]; def SetCurrentTTSStatus = \(z : VMKState, tts_status_type : TTSStatusType) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let tts_loc = @(GET_VMKMAN_CURTTS, vmk_manager) in let ttscb = @(TTSCB_GET, z, tts_loc) in let nttscb = @(SetTTSStatus, ttscb, tts_status_type) in @(TTSCB_SET, z, tts_loc, nttscb); def VM_HALT = \(s : Statement, r : KEnv, c : VMKCont) \(nz : VMKState) let vmwtype = @(GET_VMHALT_WTYPE, s), vmticks = @(GET_VMHALT_TICKS, s), vmretcd = @(GET_VMHALT_RETCD, s) in let v = @(GetEval4Dval, @(r, vmretcd)), vmk_manager = @(GET, nz, VMK_MANAGER_LOC), vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), vmcb = @(VMCB_GET, nz, vm_loc), vmcb_schedule = @(GetVMCBSchedType, vmcb) in @(GIF_THEN_ELSE, VMKState, @(AND, @(IS_ZERO, vmticks), @(IS_VMWUTimed, vmwtype)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_TIME)) in

171

CHAPTER 13. SEMANTICS OF APIS FOR VMS

@(c, z1), @(GIF_THEN_ELSE, VMKState, @(AND, @(IS_VMWUTTSStart, vmwtype), @(NOT, @(IsVMSchedulePr, vmcb_schedule))), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_TYPE)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(OR, @(IS_VMWUBasic, vmwtype), @(OR, @(IS_VMWUTimed, vmwtype), @(IS_VMWUTTSStart, vmwtype))), let z1 = @(GLOBAL_INT_DISABLE, nz), z2 = @(ClearVMReady, vm_loc, z1) in let vmcb1 = @(VMCB_GET, z2, vm_loc) in let vmcb_schedule1 = @(GetVMCBSchedType, vmcb1) in let z3 = @(GIF_THEN_ELSE, VMKState, @(AND, @(NOT, @(IS_ZERO, vmticks)), @(NOT, @(IS_VMWUTTSStart, vmwtype))), let vmcb2 = @(SetVMCBWakeType, vmcb1, vmwtype) in let nz = @(VMCB_SET, z2, vm_loc, vmcb2) in @(InsertWaitedVM, nz, vm_loc, vmticks), @(GIF_THEN_ELSE, VMKState, @(IS_VMWUTTSStart, vmwtype), let vmcb2 = @(SetVMCBSchedType, vmcb1, VMScheduleTT), vmcb3 = @(SetVMCBWakeType, vmcb2, vmwtype) in let nz = @(VMCB_SET, z2, vm_loc, vmcb3) in @(SetVMReady, vm_loc, nz), let vmcb2 = @(SetVMCBStatus, vmcb1, @(InclOrVMStatus, @(GetVMCBStatus, vmcb), VMWAIT)), vmcb3 = @(SetVMCBWakeType, vmcb2, vmwtype) in @(VMCB_SET, z2, vm_loc, vmcb3))) in let z4 = @(GLOBAL_INT_ENABLE, z3), z5 = @(CHANGE, z4, @(GET_KLVAL, v), @(KIVAL, VMK_OK)) in @(SCHEDULE, c, z5), let z1 = @(GLOBAL_INT_DISABLE, nz), z2 = @(ClearVMReady, vm_loc, z1) in @(GIF_THEN_ELSE, VMKState, @(AND, @(IS_VMWUTTSWin, vmwtype), @(IsVMScheduleTT, vmcb_schedule)), @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, @(GET_VMKMAN_CURTTS, vmk_manager), NIL_VMKLOC)), let vmcb1 = @(SetVMCBWakeType, vmcb, vmwtype) in let nvmk_manager = @(SET_VMKMAN_TTSVM, vmk_manager, @(GET_VMKMAN_IDLEVM, vmk_manager)) in

172

CHAPTER 13. SEMANTICS OF APIS FOR VMS

let z3 = @(VMCB_SET, z2, vm_loc, vmcb1), z4 = @(SetCurrentTTSStatus, z3, TTSAbort), z5 = @(CHANGE, z4, VMK_MANAGER_LOC, nvmk_manager), z6 = @(GLOBAL_INT_ENABLE, z5), z7 = @(CHANGE, z6, @(GET_KLVAL, v), @(KIVAL, VMK_OK)) in @(SCHEDULE, c, z7), let vmcb1 = @(SetVMCBWakeType, vmcb, vmwtype) in let z3 = @(VMCB_SET, z2, vm_loc, vmcb1), z4 = @(GLOBAL_INT_ENABLE, z3), z5 = @(CHANGE, z4, @(GET_KLVAL, v), @(KIVAL, VMK_OK)) in @(SCHEDULE, c, z5)), let z3 = @(GLOBAL_INT_ENABLE, z2), z4 = @(CHANGE, z3, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_TYPE)) in @(c, z4)))));

13.6

Semantics of VM START

def VM_START = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(GET_VMSTART_IDENT, s), vmtype = @(GET_VMSTART_SHTYP, s), vmretc = @(GET_VMSTART_RETCD, s) in let v1 = @(GetEval4Dval, @(r, vmname)), v2 = @(GetEval4Dval, @(r, vmretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), let vmcb = @(VMCB_GET, nz, @(GET_KLVAL, v1)) in let vmcb_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMSLEEP, vmcb_status), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_TYPE)) in @(c, z1), let vmcb1 = @(SetVMCBStatus, vmcb, VMFIRSTRUN), vmcb2 = @(SetVMCBSchedType, vmcb1, vmtype) in let z1 = @(VMCB_SET, nz, @(GET_KLVAL, v1), vmcb2), z2 = @(GLOBAL_INT_DISABLE, z1), z3 = @(SetVMReady, @(GET_KLVAL, v1), z2), z4 = @(GLOBAL_INT_ENABLE, z3), z5 = @(CHANGE, z4, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in @(SCHEDULE, c, z5)));

173

CHAPTER 13. SEMANTICS OF APIS FOR VMS

13.7

174

Semantics of VM STOP

def VM_STOP = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(GET_VMSTOP_IDENT, s), vmretc = @(GET_VMSTOP_RETCD, s) in let v1 = @(GetEval4Dval, @(r, vmname)), v2 = @(GetEval4Dval, @(r, vmretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), vm_loc = @(GET_KLVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), let vmcb = @(VMCB_GET, nz, vm_loc) in let vmcb_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMSLEEP, vmcb_status), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), let z1 = @(GLOBAL_INT_DISABLE, nz), z2 = @(GIF_THEN_ELSE, VMKState, @(IS_VMREADY, vmcb_status), @(ClearVMReady, vm_loc, z1), let tickwaitvms = @(GET_VMKMAN_TICKWT, vmk_manager), excptionvms = @(GET_VMKMAN_EXCPVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(AND, @(IS_VMWAIT, vmcb_status), @(IS_IN_MLIST, @(KLVAL, vm_loc), tickwaitvms, z1)), @(ExactWaitedVM, vm_loc, z1), @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, vm_loc), excptionvms, z1), let l2z = @(DEL_MLIST, @(KLVAL, vm_loc), excptionvms, z1) in let nexcptionvms = @(PJ1, MList, VMKState, l2z), nz1 = @(PJ2, MList, VMKState, l2z) in let nvmk_manager = @(SET_VMKMAN_EXCPVM, vmk_manager, nexcptionvms) in @(CHANGE, nz1, VMK_MANAGER_LOC, nvmk_manager), z1))) in let z3 = @(ClearVM, vm_loc, z2),

CHAPTER 13. SEMANTICS OF APIS FOR VMS

175

z4 = @(GLOBAL_INT_ENABLE, z3), z5 = @(CHANGE, z4, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in @(SCHEDULE, c, z5)));

13.8

Semantics of VM SUSPEND

def VM_SUSPEND = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(GET_VMSUSP_IDENT, s), vmretc = @(GET_VMSUSP_RETCD, s) in let v1 = @(GetEval4Dval, @(r, vmname)), v2 = @(GetEval4Dval, @(r, vmretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), vm_loc = @(GET_KLVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, vm_loc, VMK_VMM_ID), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_ID)) in @(c, z1), let vmcb = @(VMCB_GET, nz, vm_loc) in let vmcb_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMSLEEP, vmcb_status), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(IS_VMSUSPEND, vmcb_status), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), let z1 = @(GLOBAL_INT_DISABLE, nz) in let vmcb1 = @(SetVMCBStatus, vmcb, @(InclOrVMStatus, vmcb_status, VMSUSPEND)) in @(GIF_THEN_ELSE, VMKState, @(IS_VMREADY, vmcb_status), let z2 = @(VMCB_SET, z1, vm_loc, vmcb1), z3 = @(ClearVMReady, vm_loc, z2), z4 = @(GLOBAL_INT_ENABLE, z3), z5 = @(CHANGE, z4, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in

CHAPTER 13. SEMANTICS OF APIS FOR VMS

@(SCHEDULE, c, z5), let z2 = @(VMCB_SET, z1, vm_loc, vmcb1), z3 = @(GLOBAL_INT_ENABLE, z2), z4 = @(CHANGE, z3, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in @(c, z4))))));

13.9

Semantics of VM RESUME

def VM_RESUME = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(GET_VMRESM_IDENT, s), vmretc = @(GET_VMRESM_RETCD, s) in let v1 = @(GetEval4Dval, @(r, vmname)), v2 = @(GetEval4Dval, @(r, vmretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), vm_loc = @(GET_KLVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, vm_loc, VMK_VMM_ID), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_ID)) in @(c, z1), let vmcb = @(VMCB_GET, nz, @(GET_KLVAL, v1)) in let vmcb_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(IS_VMSUSPEND, vmcb_status)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_FAIL)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(IS_VMWAIT, vmcb_status), let vmcb1 = @(SetVMCBStatus, vmcb, VMREADY) in let z1 = @(GLOBAL_INT_DISABLE, nz), z2 = let excptionvms = @(GET_VMKMAN_EXCPVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, vm_loc), excptionvms, z1), let l2z = @(DEL_MLIST, @(KLVAL, vm_loc), excptionvms, z1) in let nexcptionvms = @(PJ1, MList, VMKState, l2z), zz = @(PJ2, MList, VMKState, l2z) in let nvmk_manager = @(SET_VMKMAN_EXCPVM,

176

CHAPTER 13. SEMANTICS OF APIS FOR VMS

177

vmk_manager, nexcptionvms) in @(CHANGE, zz, VMK_MANAGER_LOC, nvmk_manager), z1), z3 = @(SetVMReady, vm_loc, z2), z4 = @(VMCB_SET, z3, vm_loc, vmcb1), z5 = @(CHANGE, z4, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)), z6 = @(GLOBAL_INT_ENABLE, z5) in @(SCHEDULE, c, z6), let vmcb1 = @(SetVMCBStatus, vmcb, VMWAIT) in let z1 = @(VMCB_SET, nz, @(GET_KLVAL, v1), vmcb1), z2 = @(CHANGE, z1, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in @(c, z2)))));

13.10

Semantics of VM RESET

def DO_VM_RESET = \(vm_type : VMScheduleType, vm_loc : VMKLocation, ret_loc : VMKLocation, c : VMKCont, z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC), vmcb = @(VMCB_GET, z, vm_loc) in let vm_status = @(GetVMCBStatus, vmcb) in let z1 = @(GLOBAL_INT_DISABLE, z), z2 = @(GIF_THEN_ELSE, VMKState, @(IS_VMREADY, vm_status), @(ClearVMReady, vm_loc, z1), let tickwaitvms = @(GET_VMKMAN_TICKWT, vmk_manager), excptionvms = @(GET_VMKMAN_EXCPVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(AND, @(IS_VMWAIT, vm_status), @(IS_IN_MLIST, @(KLVAL, vm_loc), tickwaitvms, z1)), @(ExactWaitedVM, vm_loc, z1), @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, vm_loc), excptionvms, z1), let l2z = @(DEL_MLIST, @(KLVAL, vm_loc), excptionvms, z1) in let nexcptionvms = @(PJ1, MList, VMKState, l2z), zz = @(PJ2, MList, VMKState, l2z) in let nvmk_manager = @(SET_VMKMAN_EXCPVM, vmk_manager, nexcptionvms) in @(CHANGE, zz, VMK_MANAGER_LOC, nvmk_manager), z1))) in let z3 = @(ClearVM, vm_loc, z2) in let vmcb1 = @(VMCB_GET, z3, vm_loc),

CHAPTER 13. SEMANTICS OF APIS FOR VMS

vmcb2 = @(SetVMCBSchedType, vmcb1, vm_type), vmcb3 = @(SetVMCBStatus, vmcb2, VMFIRSTRUN) in let z3 = @(VMCB_SET, z2, vm_loc, vmcb3), z4 = @(SetVMReady, vm_loc, z3), z5 = @(GLOBAL_INT_ENABLE, z4), z6 = @(CHANGE, z5, ret_loc, @(KIVAL, VMK_OK)) in @(SCHEDULE, c, z6); def VM_RESET = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(GET_VMRESET_IDENT, s), vmtype = @(GET_VMRESET_STYPE, s), vmretc = @(GET_VMRESET_RETCD, s) in let v1 = @(GetEval4Dval, @(r, vmname)), v2 = @(GetEval4Dval, @(r, vmretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), vm_loc = @(GET_KLVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, vm_loc, VMK_NULL_VID), let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vm_loc = current_vm_loc in @(DO_VM_RESET, vmtype, vm_loc, @(GET_KLVAL, v2), c, nz), let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, current_vm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), let vmcb = @(VMCB_GET, nz, vm_loc) in let vmcb_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMSLEEP, vmcb_status), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), @(DO_VM_RESET, vmtype, vm_loc, @(GET_KLVAL, v2), c, nz))));

178

Chapter 14

Semantics of APIs for TTS 14.1 dec dec dec dec dec

14.2

List of APIs TTS_INSTALL TTS_GET_TTS_ID TTS_GET_TTS_NAME TTS_START TTS_STOP

: : : : :

[Statement [Statement [Statement [Statement [Statement

-> -> -> -> ->

KEnv KEnv KEnv KEnv KEnv

-> -> -> -> ->

VMKCont VMKCont VMKCont VMKCont VMKCont

-> -> -> -> ->

VMKCont]; VMKCont]; VMKCont]; VMKCont]; VMKCont];

Semantics of TTS INSTALL

dec SetNodeLastZero : [VMKState -> Array -> VMKState]; def SetNodeLastZero = \(z : VMKState, nodes : Array) let first_last_index = @(GET_ARRAY_RANLST, nodes) in let first_index = @(PJ1, Nat, Nat, @(HEAD, @(Product, Nat, Nat), first_last_index)), last_index = @(PJ2, Nat, Nat, @(HEAD, @(Product, Nat, Nat), first_last_index)) in let last_node = @(KSUBSCRIPT, nodes, @(CONS, Nat, @(SS, last_index), @(NIL, Nat)), z), last_node_loc = @(KSUBSCRIPT_LOC, nodes, @(CONS, Nat, @(SS, last_index), @(NIL, Nat)), z) in let nlast_node = @(SetTTSNodDuring, last_node, OO) in

179

CHAPTER 14. SEMANTICS OF APIS FOR TTS

@(CHANGE, z, last_node_loc, nlast_node); dec DoCheckTTSNode : [VMKState -> TTSNode -> TTSNode -> Nat -> Nat -> Nat -> Nat -> Bool]; def DoCheckTTSNode = \(z : VMKState, node : TTSNode, next_node : TTSNode, index : Nat, last_index : Nat, count : Nat, main_frame_ticks : Nat) let start_time = @(GetTTSNodStart, node), during_time = @(GetTTSNodDuring, node) in @(GIF_THEN_ELSE, Bool, @(NEQ, during_time, OO), FF, @(GIF_THEN_ELSE, Bool, @(NGT, index, last_index), let next_start_time = @(GetTTSNodStart, next_node), next_during_time = @(GetTTSNodDuring, next_node) in @(GIF_THEN_ELSE, Bool, @(NLT, next_start_time, @(ADD, start_time, during_time)), FF, @(GIF_THEN_ELSE, Bool, @(NLT, main_frame_ticks, @(ADD, start_time, during_time)), FF, TT)), @(GIF_THEN_ELSE, Bool, @(NLT, main_frame_ticks, @(ADD, start_time, during_time)), FF, TT))); dec DoCheckTTS : [VMKState -> Array -> Nat -> Nat -> Nat -> Nat -> Bool]; def DoCheckTTS = \(z : VMKState, nodes : Array, index : Nat, last_index : Nat, count : Nat, main_frame_ticks : Nat) @(GIF_THEN_ELSE, Bool, @(NGT, index, last_index), TT,

180

CHAPTER 14. SEMANTICS OF APIS FOR TTS

181

let node = @(KSUBSCRIPT, nodes, @(CONS, Nat, index, @(NIL, Nat)), z) in @(GIF_THEN_ELSE, Bool, @(NEQ, index, last_index), let next_node = ERR_KSVAL in let ret_code = @(DoCheckTTSNode, z, node, next_node, index, last_index, count, main_frame_ticks) in @(GIF_THEN_ELSE, Bool, ret_code, @(DoCheckTTS, z, nodes, @(SS, index), last_index, count, main_frame_ticks), FF), let next_node = @(KSUBSCRIPT, nodes, @(CONS, Nat, @(SS, index), @(NIL, Nat)), z) in let ret_code = @(DoCheckTTSNode, z, node, next_node, index, last_index, count, main_frame_ticks) in @(GIF_THEN_ELSE, Bool, ret_code, @(DoCheckTTS, z, nodes, @(SS, index), last_index, count, main_frame_ticks), FF))); dec CheckTTS : [VMKState -> Array -> Nat -> Nat -> Bool]; def CheckTTS = \(z : VMKState, nodes : Array, count : Nat, main_frame_ticks : Nat) let first_last_index = @(GET_ARRAY_RANLST, nodes) in let first_index = @(PJ1, Nat, Nat, @(HEAD, @(Product, Nat, Nat), first_last_index)), last_index = @(PJ2, Nat, Nat, @(HEAD, @(Product, Nat, Nat), first_last_index)) in @(DoCheckTTS, z, nodes, first_index, last_index, count, main_frame_ticks); def TTS_INSTALL = \(s : Statement, r : KEnv, c : VMKCont)

CHAPTER 14. SEMANTICS OF APIS FOR TTS

let ttsname = @(GET_INSLTTS_IDT, s), ttstabl = @(GET_INSLTTS_TAB, s), ttscoun = @(GET_INSLTTS_NUM, s), ttsmftc = @(GET_INSLTTS_MFT, s), ttsretc = @(GET_INSLTTS_RET, s) in let v1 = @(GetEval4Dval, @(r, ttsname)), v2 = @(GetEval4Dval, @(r, ttsretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), current_tts = @(GET_VMKMAN_CURTTS, vmk_manager), tts_loc = @(GET_KLVAL, v1) in let ttscb = @(TTSCB_GET, nz, tts_loc) in let ttscb_nodemax = @(GETTTSNodeMax, ttscb), ttscb_table = @(GetTTSNodes, ttscb) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, tts_loc, current_tts), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(OR, @(NGT, ttscoun, ttscb_nodemax), @(IS_ZERO, ttscoun)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_SIZE)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(NOT, @(CheckTTS, nz, ttscb_table, ttscoun, ttsmftc)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_CONTENT)) in @(c, z1), let z1 = @(SetNodeLastZero, nz, ttstabl) in let ttscb1 = @(SetTTSNodes, ttscb, ttstabl), ttscb2 = @(SetTTSMFrameTick, ttscb1, ttsmftc), ttscb3 = @(SetTTSId, ttscb2, @(GET_KLVAL, v1)) in let z2 = @(TTSCB_SET, z1, @(GET_KLVAL, v1), ttscb3), z3 = @(CHANGE, z2, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in @(c, z3)))));

14.3

Semantics of TTS GET TTS ID

def TTS_GET_TTS_ID = \(s : Statement, r : KEnv, c : VMKCont) let ttsname = @(GET_TTSGETID_IDT, s), ttsrloc = @(GET_TTSGETID_LOC, s),

182

CHAPTER 14. SEMANTICS OF APIS FOR TTS

ttsretc = @(GET_TTSGETID_RET, s) in let v1 = @(GetEval4Dval, @(r, ttsname)), v2 = @(GetEval4Dval, @(r, ttsrloc)), v3 = @(GetEval4Dval, @(r, ttsretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), current_tts = @(GET_VMKMAN_CURTTS, vmk_manager), tts_loc = @(GET_KLVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v3), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(EQ_IDENT, ttsname, NULL_IDENT), @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, current_tts, NIL_VMKLOC)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KLVAL, current_tts)), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1)), let ttscb = @(TTSCB_GET, nz, @(GET_KLVAL, v1)) in let ttscb_id = @(GetTTSId, ttscb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KLVAL, ttscb_id)), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2)));

14.4

Semantics of TTS GET TTS NAME

def TTS_GET_TTS_NAME = \(s : Statement, r : KEnv, c : VMKCont) let ttsrloc = @(GET_TTSGETNM_LOC, s), ttsname = @(GET_TTSGETNM_IDT, s), ttsretc = @(GET_TTSGETNM_RET, s) in let v1 = @(GetEval4Dval, @(r, ttsrloc)), v2 = @(GetEval4Dval, @(r, ttsname)), v3 = @(GetEval4Dval, @(r, ttsretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), current_tts = @(GET_VMKMAN_CURTTS, vmk_manager), tts_loc = @(GET_KLVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)),

183

CHAPTER 14. SEMANTICS OF APIS FOR TTS

184

let z1 = @(CHANGE, nz, @(GET_KLVAL, v3), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, @(GET_KLVAL, v1), NIL_VMKLOC), @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, current_tts, NIL_VMKLOC)), let ttscb = @(TTSCB_GET, nz, current_tts) in let ttscb_name = @(GetTTSName, ttscb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KTVAL, ttscb_name)), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1)), let ttscb = @(TTSCB_GET, nz, @(GET_KLVAL, v1)) in let ttscb_name = @(GetTTSName, ttscb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KTVAL, ttscb_name)), z2 = @(CHANGE, z1, @(GET_KLVAL, v3), @(KIVAL, VMK_OK)) in @(c, z2)));

14.5

Semantics of TTS START

def TTSCB_START = \(ttscb : TTSCB) @(SetTTSStatus, ttscb, TTSWaitFrame); def TTS_START = \(s : Statement, r : KEnv, c : VMKCont) let ttsname = @(GET_TTSSTART_IDENT, s), ttsretc = @(GET_TTSSTART_RETCD, s) in let v1 = @(GetEval4Dval, @(r, ttsname)), v2 = @(GetEval4Dval, @(r, ttsretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), current_tts = @(GET_VMKMAN_CURTTS, vmk_manager), tts_loc = @(GET_KLVAL, v1) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), let current_tts = @(GET_VMKMAN_CURTTS, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, current_tts, @(GET_KLVAL, v1)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1),

CHAPTER 14. SEMANTICS OF APIS FOR TTS

185

let let let let

ttscb = @(TTSCB_GET, nz, @(GET_KLVAL, v1)) in nttscb = @(TTSCB_START, ttscb) in z1 = @(TTSCB_SET, nz, @(GET_KLVAL, v1), nttscb) in vmk_manager1 = @(SET_VMKMAN_CURTTS, vmk_manager, NIL_VMKLOC), vmk_manager2 = @(SET_VMKMAN_TTSVM, vmk_manager1, @(GET_VMKMAN_IDLEVM, vmk_manager1)) in let z2 = @(CHANGE, z1, VMK_MANAGER_LOC, vmk_manager2) in let ret2z = @(TickNotify, VMK_FRAMETICK, z2) in let ret = @(PJ1, Bool, VMKState, ret2z), z3 = @(PJ2, Bool, VMKState, ret2z) in let z4 = @(CHANGE, z3, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in @(SCHEDULE, c, z4)));

14.6

Semantics of TTS STOP

def TTS_STOP = \(s : Statement, r : KEnv, c : VMKCont) let ttsretc = @(GET_TTSSTOP_RETCD, s) in let v2 = @(GetEval4Dval, @(r, ttsretc)) in \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), runvm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(NOT, @(EQ_VMKLOC, runvm_loc, VMK_VMM_ID)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_USER)) in @(c, z1), let current_tts_loc = @(GET_VMKMAN_CURTTS, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(EQ_VMKLOC, current_tts_loc, NIL_VMKLOC), let z1 = @(CHANGE, nz, @(GET_KLVAL, v2), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), let vmk_manager1 = @(SET_VMKMAN_CURTTS, vmk_manager, NIL_VMKLOC), vmk_manager2 = @(SET_VMKMAN_TTSVM, vmk_manager1, @(GET_VMKMAN_IDLEVM, vmk_manager1)) in let z1 = @(CHANGE, nz, VMK_MANAGER_LOC, vmk_manager2), z2 = @(CHANGE, z1, @(GET_KLVAL, v2), @(KIVAL, VMK_OK)) in @(c, z2)));

Chapter 15

Semantics of APIs for Scheduler 15.1 dec dec dec dec dec dec

15.2

List of APIs VMK_SCHEDULE SET_VM_READY CLEAR_VM_READY EXACT_VM_WAIT CLEAR_VM_WAIT TICK_NOTIFY

: : : : : :

[Statement [Statement [Statement [Statement [Statement [Statement

-> -> -> -> -> ->

KEnv KEnv KEnv KEnv KEnv KEnv

-> -> -> -> -> ->

VMKCont VMKCont VMKCont VMKCont VMKCont VMKCont

Semantics of VMK SCHEDULE

def VMK_SCHEDULE = \(s : Statement, r : KEnv, c : VMKCont) @(SCHEDULE, c);

15.3

Semantics of SET VM READY

def SET_VM_READY = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(SET_VMREADY_IDENT, s) in let v1 = @(GetEval4Dval, @(r, vmname)) in let vm_loc = @(GET_KLVAL, v1) in

186

-> -> -> -> -> ->

VMKCont]; VMKCont]; VMKCont]; VMKCont]; VMKCont]; VMKCont];

CHAPTER 15. SEMANTICS OF APIS FOR SCHEDULER

\(z : VMKState) @(SetVMReady, vm_loc, z);

15.4

Semantics of CLEAR VM READY

def CLEAR_VM_READY = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(CLEAR_VMREADY_ID, s) in let v1 = @(GetEval4Dval, @(r, vmname)) in \(z : VMKState) let vm_loc = @(GET_KLVAL, v1) in @(ClearVMReady, vm_loc, z);

15.5

Semantics of EXACT VM WAIT

def EXACT_VM_WAIT = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(EXACT_VMWAIT_ID, s) in let v1 = @(GetEval4Dval, @(r, vmname)) in \(z : VMKState) let vm_loc = @(GET_KLVAL, v1) in @(ExactWaitedVM, vm_loc, z);

15.6

Semantics of CLEAR VM WAIT

def CLEAR_VM_WAIT = \(s : Statement, r : KEnv, c : VMKCont) let vmname = @(CLEAR_VMWAIT_ID, s) in let v1 = @(GetEval4Dval, @(r, vmname)) in \(z : VMKState) let vm_loc = @(GET_KLVAL, v1) in @(ClearVMWaiting, vm_loc, z);

15.7

Semantics of TICK NOTIFY

def TICK_NOTIFY = \(s : Statement, r : KEnv, c : VMKCont)

187

CHAPTER 15. SEMANTICS OF APIS FOR SCHEDULER

let tick_type = @(GET_TICKNOFY_TYP, s), tick_retc = @(GET_TICKNOFY_RET, s) in let v1 = @(GetEval4Dval, @(r, tick_retc)) in \(z : VMKState) let ret2state = @(TickNotify, tick_type, z) in let ret = @(PJ1, Bool, VMKState, ret2state), z1 = @(PJ2, Bool, VMKState, ret2state) in let z2 = @(CHANGE, z1, @(GET_KLVAL, v1), @(KBVAL, ret)) in @(c, z2);

188

Chapter 16

Semantics of APIs for Virtual Interrupt Management 16.1 dec dec dec dec dec dec dec dec

List of APIs InitVTickInt EnablePIC DisablePIC SendServInt VAckException TriggerVInt DispatchInt GetVInt

: : : : : : : :

[Statement [Statement [Statement [Statement [Statement [Statement [Statement [Statement

-> -> -> -> -> -> -> ->

KEnv KEnv KEnv KEnv KEnv KEnv KEnv KEnv

-> -> -> -> -> -> -> ->

VMKCont VMKCont VMKCont VMKCont VMKCont VMKCont VMKCont VMKCont

dec IntDispatch : [Nat -> VMKCont];

16.2

Semantics of InitVTickInt

def InitVTickInt = \(s : Statement, r : KEnv, c : VMKCont) let tickintgmk = @(GET_TICKINT_GMK, s), tickintmsk = @(GET_TICKINT_MSK, s), tickintsrv = @(GET_TICKINT_SRV, s), tickintret = @(GET_TICKINT_RET, s) in \(nz : VMKState) let v = @(GetEval4Dval, @(r, tickintret)),

189

-> -> -> -> -> -> -> ->

VMKCont]; VMKCont]; VMKCont]; VMKCont]; VMKCont]; VMKCont]; VMKCont]; VMKCont];

Semantics for Virtual Interrupt Management

vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vmcb = @(VMCB_GET, nz, current_vm_loc) in let vintcblock = @(GetVMCBVIntCBlck, vmcb) in let vtickintcbloc = @(GetVMVIntTickCB, vintcblock) in let vtickintcb = @(GetVMVIntCB, nz, vtickintcbloc) in let vintinit = @(GetVMVIntInit, vintcblock) in @(GIF_THEN_ELSE, VMKState, @(NOT, vintinit), let vtickintcb1 = @(SetVMVIntCBGMsk, vtickintcb, tickintgmk), vtickintcb2 = @(SetVMVIntCBMask, vtickintcb1, tickintmsk), vtickintcb3 = @(SetVMVIntCBHand, vtickintcb2, tickintsrv) in let z0 = @(SetVMVIntCB, nz, vtickintcbloc, vtickintcb3) in let vintcblock1 = @(SetVMVIntInit, vintcblock, TT), vintcblock2 = @(SetVMVIntExcpNum, vintcblock1, OO) in let vmcb2 = @(SetVMCBVIntCBlck, vmcb, vintcblock2) in let z1 = @(VMCB_SET, z0, current_vm_loc, vmcb2), z2 = @(CHANGE, z1, @(GET_KLVAL, v), @(KIVAL, VMK_OK)) in @(c, z2), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1));

16.3

Semantics of EnablePIC

def DoEnablePIC = \(nz : VMKState, enable_pic_loc : VMKLocation, int_loc_list : MList, ret_loc : VMKLocation, c : VMKCont) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vintcb = @(GetVMVIntCB, nz, enable_pic_loc) in let intgmsk = @(GetVMVIntCBGMsk, vintcb) in @(GIF_THEN_ELSE, VMKState, @(NOT, intgmsk), let z1 = @(GLOBAL_INT_DISABLE, nz) in let vintcb1 = @(SetVMVIntCBMask, vintcb, FF) in let z2 = @(SetVMVIntCB, z1, enable_pic_loc, vintcb1), z3 = @(GLOBAL_INT_ENABLE, z2), z4 = @(CHANGE, z3, ret_loc, @(KIVAL, VMK_OK)) in @(c, z4), let z1 = @(CHANGE, nz, ret_loc, @(KIVAL, VMK_MASKED)) in @(c, z1));

190

Semantics for Virtual Interrupt Management

def EnablePIC = \(s : Statement, r : KEnv, c : VMKCont) let enabpicloc = @(GET_ENABPIC_LOC, s), enabpicret = @(GET_ENABPIC_RET, s) in \(nz : VMKState) let v = @(GetEval4Dval, @(r, enabpicret)), vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vmcb = @(VMCB_GET, nz, current_vm_loc) in let vextrintl = @(GetVMVIntExtrCB, @(GetVMCBVIntCBlck, vmcb)), vexcpintl = @(GetVMVIntExcpCB, @(GetVMCBVIntCBlck, vmcb)), vservintl = @(GetVMVIntServCB, @(GetVMCBVIntCBlck, vmcb)) in @(GIF_THEN_ELSE, VMKState, @(OR, @(IS_IN_INT_LIST, enabpicloc, vextrintl, nz), @(OR, @(IS_IN_INT_LIST, enabpicloc, vexcpintl, nz), @(IS_IN_INT_LIST, enabpicloc, vservintl, nz))), @(GIF_THEN_ELSE, VMKState, @(IS_IN_INT_LIST, enabpicloc, vextrintl, nz), @(DoEnablePIC, nz, enabpicloc, vextrintl, @(GET_KLVAL, v), c), @(GIF_THEN_ELSE, VMKState, @(IS_IN_INT_LIST, enabpicloc, vexcpintl, nz), @(DoEnablePIC, nz, enabpicloc, vexcpintl, @(GET_KLVAL, v), c), @(DoEnablePIC, nz, enabpicloc, vservintl, @(GET_KLVAL, v), c))), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_FAIL)) in @(c, z1));

16.4

Semantics of DisablePIC

def DoDisablePIC = \(nz : VMKState, disable_pic_loc : VMKLocation, int_loc_list : MList, ret_loc : VMKLocation, c : VMKCont) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vintcb = @(GetVMVIntCB, nz, disable_pic_loc) in let intgmsk = @(GetVMVIntCBGMsk, vintcb) in @(GIF_THEN_ELSE, VMKState, @(NOT, intgmsk), let z1 = @(GLOBAL_INT_DISABLE, nz) in let vintcb1 = @(SetVMVIntCBMask, vintcb, TT) in

191

Semantics for Virtual Interrupt Management

let z2 z3 z4 @(c, let z1 @(c,

= @(SetVMVIntCB, z1, disable_pic_loc, vintcb1), = @(GLOBAL_INT_ENABLE, z2), = @(CHANGE, z3, ret_loc, @(KIVAL, VMK_OK)) in z4), = @(CHANGE, nz, ret_loc, @(KIVAL, VMK_MASKED)) in z1));

def DisablePIC = \(s : Statement, r : KEnv, c : VMKCont) let disabpicloc = @(GET_DISABPIC_LOC, s), disabpicret = @(GET_DISABPIC_RET, s) in \(nz : VMKState) let v = @(GetEval4Dval, @(r, disabpicret)), vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vmcb = @(VMCB_GET, nz, current_vm_loc) in let vextrintl = @(GetVMVIntExtrCB, @(GetVMCBVIntCBlck, vmcb)), vexcpintl = @(GetVMVIntExcpCB, @(GetVMCBVIntCBlck, vmcb)), vservintl = @(GetVMVIntServCB, @(GetVMCBVIntCBlck, vmcb)) in @(GIF_THEN_ELSE, VMKState, @(OR, @(IS_IN_INT_LIST, disabpicloc, vextrintl, nz), @(OR, @(IS_IN_INT_LIST, disabpicloc, vexcpintl, nz), @(IS_IN_INT_LIST, disabpicloc, vservintl, nz))), @(GIF_THEN_ELSE, VMKState, @(IS_IN_INT_LIST, disabpicloc, vextrintl, nz), @(DoDisablePIC, nz, disabpicloc, vextrintl, @(GET_KLVAL, v), c), @(GIF_THEN_ELSE, VMKState, @(IS_IN_INT_LIST, disabpicloc, vexcpintl, nz), @(DoDisablePIC, nz, disabpicloc, vexcpintl, @(GET_KLVAL, v), c), @(DoDisablePIC, nz, disabpicloc, vservintl, @(GET_KLVAL, v), c))), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_FAIL)) in @(c, z1));

16.5

Semantics of SendServInt

def SendServInt = \(s : Statement, r : KEnv, c : VMKCont) let sendvmloc = @(GET_SNDVMINT_LOC, s), sdservloc = @(GET_SNDVMSRV_LOC, s), sendvmret = @(GET_SNTVMRET_RET, s) in \(nz : VMKState) let v = @(GetEval4Dval, @(r, sendvmret)), vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let vmcb = @(VMCB_GET, nz, sendvmloc) in

192

Semantics for Virtual Interrupt Management

193

let vintinit = @(GetVMVIntInit, @(GetVMCBVIntCBlck, vmcb)), vservintl = @(GetVMVIntServCB, @(GetVMCBVIntCBlck, vmcb)), vm_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMSLEEP, vm_status), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(NOT, vintinit), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(NOT, @(IS_IN_INT_LIST, sdservloc, vservintl, nz)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_INDEX)) in @(c, z1), let vservintcb = @(GetVMVIntCB, nz, sdservloc) in let servintgmsk = @(GetVMVIntCBGMsk, vservintcb), servintmask = @(GetVMVIntCBMask, vservintcb) in @(GIF_THEN_ELSE, VMKState, @(NOT, servintgmsk), @(GIF_THEN_ELSE, VMKState, @(NOT, servintmask), let vservintcb1 = @(SetVMVIntCBFire, vservintcb, TT) in let z1 = @(GLOBAL_INT_DISABLE, nz), z2 = @(SetVMVIntCB, z1, sdservloc, vservintcb1) in let vm_wakeup_type = @(GetVMCBWakeType, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMWUBasic, vm_wakeup_type), let z3 = let tick_waited_vms = @(GET_VMKMAN_TICKWT, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, sendvmloc), tick_waited_vms, z1), @(ExactWaitedVM, sendvmloc, z2), z2), z4 = @(ClearVMWaiting, sendvmloc, z3), z5 = @(CHANGE, z4, @(GET_KLVAL, v), @(KIVAL, VMK_OK)), z6 = @(GLOBAL_INT_ENABLE, z5) in @(SCHEDULE, c, z6), let z2 = @(GLOBAL_INT_ENABLE, z1), z3 = @(CHANGE, z2, @(GET_KLVAL, v), @(KIVAL, VMK_OK)) in @(c, z3)), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_FAIL)) in @(c, z1)),

Semantics for Virtual Interrupt Management

let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_FAIL)) in @(c, z1)))));

16.6

Semantics of VAckException

def VAckException = \(s : Statement, r : KEnv, c : VMKCont) let ackexceptret = @(GET_ACKEXCEPT_RET, s) in \(nz : VMKState) let v = @(GetEval4Dval, @(r, ackexceptret)), vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vmcb = @(VMCB_GET, nz, current_vm_loc) in let vintcblock = @(GetVMCBVIntCBlck, vmcb) in let nvintcblock = @(SetVMVIntExcpNum, vintcblock, OO) in let nvmcb = @(SetVMCBVIntCBlck, vmcb, nvintcblock) in let z1 = @(VMCB_SET, nz, current_vm_loc, nvmcb), z2 = @(CHANGE, z1, @(GET_KLVAL, v), @(KIVAL, VMK_OK)) in @(c, z2);

16.7

Semantics of TriggerVInt

def VIntTrigger = \(z : VMKState, intloc : VMKLocation) let vintcb = @(GetVMVIntCB, z, intloc) in let int = @(GetVMVIntCBFire, vintcb) in @(GIF_THEN_ELSE, VMKState, int, let cont = @(GetVMVIntCBHand, vintcb) in let nvintcb = @(SetVMVIntCBFire, vintcb, FF) in let nz = @(SetVMVIntCB, z, intloc, vintcb) in @(cont, nz), z); dec VIntTriggerList : [VMKState -> MList -> VMKState]; def VIntTriggerList = \(z : VMKState, intlocl : MList) @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, intlocl), z, let hintlocl = @(MHEAD, intlocl, z), tintlocl = @(MTAIL, intlocl, z) in let nz = @(VIntTrigger, z, @(GET_KLVAL, hintlocl)) in

194

Semantics for Virtual Interrupt Management

@(VIntTriggerList, nz, tintlocl)); def TriggerVInt = \(s : Statement, r : KEnv, c : VMKCont) \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vmcb = @(VMCB_GET, nz, current_vm_loc) in let vintcblock = @(GetVMCBVIntCBlck, vmcb) in let vtickint = @(GetVMVIntTickCB, vintcblock), vservintl = @(GetVMVIntServCB, vintcblock), vextrintl = @(GetVMVIntExtrCB, vintcblock), vexcpintl = @(GetVMVIntExcpCB, vintcblock) in let z1 = @(VIntTrigger, nz, vtickint), z2 = @(VIntTriggerList, z1, vservintl), z3 = @(VIntTriggerList, z2, vextrintl), z4 = @(VIntTriggerList, z3, vexcpintl) in @(c, z4);

16.8

Semantics of DispatchInt

def DispatchInt = \(s : Statement, r : KEnv, c : VMKCont) let dispatchintnum = @(GET_DISPINT_NUM, s), dispatchintret = @(GET_DISPINT_RET, s) in \(nz : VMKState) let v = @(GetEval4Dval, @(r, dispatchintret)), vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let intl = @(GET_VMKMAN_INTCBL, vmk_manager) in let vm_loc = @(GET_LOC_MLIST, dispatchintnum, intl, nz) in let vmcb = @(VMCB_GET, nz, vm_loc) in let vintinit = @(GetVMVIntInit, @(GetVMCBVIntCBlck, vmcb)), vextrintl = @(GetVMVIntExtrCB, @(GetVMCBVIntCBlck, vmcb)), vextrloc = @(GET_LOC_MLIST, dispatchintnum, vextrintl, nz), vm_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMSLEEP, vm_status), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), @(GIF_THEN_ELSE, VMKState, @(NOT, vintinit), let z1 = @(CHANGE, nz, @(GET_KLVAL, v), @(KIVAL, VMK_INVALID_STATE)) in @(c, z1), let vextrintcb = @(GetVMVIntCB, nz, vextrloc) in let vextrintcb1 = @(SetVMVIntCBFire, vextrintcb, TT) in let z0 = @(GLOBAL_INT_DISABLE, nz), z1 = @(SetVMVIntCB, z0, vextrloc, vextrintcb1) in

195

Semantics for Virtual Interrupt Management

let vm_wakeup_type = @(GetVMCBWakeType, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMWUBasic, vm_wakeup_type), let z2 = let tick_waited_vms = @(GET_VMKMAN_TICKWT, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, vm_loc), tick_waited_vms, z1), @(ExactWaitedVM, vm_loc, z1), z1), z3 = @(ClearVMWaiting, vm_loc, z2), z4 = @(CHANGE, z3, @(GET_KLVAL, v), @(KIVAL, VMK_OK)), z5 = @(GLOBAL_INT_ENABLE, z4) in @(SCHEDULE, c, z5), let z2 = @(GLOBAL_INT_ENABLE, z1), z3 = @(CHANGE, z2, @(GET_KLVAL, v), @(KIVAL, VMK_OK)) in @(c, z3)))); def IntDispatch = \(dispatchintnum : Nat, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let intl = @(GET_VMKMAN_INTDIS, vmk_manager) in let vm_loc = @(GET_LOC_MLIST, dispatchintnum, intl, nz) in let vmcb = @(VMCB_GET, nz, vm_loc) in let vintinit = @(GetVMVIntInit, @(GetVMCBVIntCBlck, vmcb)), vextrintl = @(GetVMVIntExtrCB, @(GetVMCBVIntCBlck, vmcb)), vextrloc = @(GET_LOC_MLIST, dispatchintnum, vextrintl, nz), vm_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMSLEEP, vm_status), @(ERR_VMKSTATE, nz), @(GIF_THEN_ELSE, VMKState, @(NOT, vintinit), @(ERR_VMKSTATE, nz), let vextrintcb = @(GetVMVIntCB, nz, vextrloc) in let vextrintcb1 = @(SetVMVIntCBFire, vextrintcb, TT) in let z0 = @(SetVMVIntCB, nz, vextrloc, vextrintcb1) in let vm_wakeup_type = @(GetVMCBWakeType, vmcb) in @(GIF_THEN_ELSE, VMKState, @(IS_VMWUBasic, vm_wakeup_type), let z1 = let tick_waited_vms = @(GET_VMKMAN_TICKWT, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, vm_loc), tick_waited_vms,

196

Semantics for Virtual Interrupt Management

nz), @(ExactWaitedVM, vm_loc, z0), z0) in @(ClearVMWaiting, vm_loc, z1), nz)));

16.9

Semantics of GetVInt

dec VIntCheck : [VMKState -> VMKLocation -> Bool]; def VIntCheck = \(z : VMKState, intloc : VMKLocation) let vintcb = @(GetVMVIntCB, z, intloc) in @(GetVMVIntCBFire, vintcb); dec VIntCheckList : [VMKState -> MList -> Bool]; def VIntCheckList = \(z : VMKState, intlocl : MList) @(GIF_THEN_ELSE, Bool, @(IS_EMPTY_MLIST, intlocl), FF, let hintlocl = @(MHEAD, intlocl, z), tintlocl = @(MTAIL, intlocl, z) in let intfire = @(VIntCheck, z, @(GET_KLVAL, hintlocl)) in @(GIF_THEN_ELSE, Bool, intfire, intfire, @(VIntCheckList, z, tintlocl))); dec FindVMVIntCB : [MList -> VMKState -> VMKLocation]; def FindVMVIntCB = \(intl : MList, z : VMKState) @(GIF_THEN_ELSE, VMKLocation, @(IS_EMPTY_MLIST, intl), ERR_VMKLOC, let hintl = @(MHEAD, intl, z), tintl = @(MTAIL, intl, z) in let vintcb = @(GetVMVIntCB, z, @(GET_KLVAL, hintl)) in let intfire = @(GetVMVIntCBFire, vintcb) in @(GIF_THEN_ELSE, VMKLocation, intfire, @(GET_KLVAL, hintl), @(FindVMVIntCB, tintl, z)));

197

Semantics for Virtual Interrupt Management

def GetVInt = \(s : Statement, r : KEnv, c : VMKCont) let getvinttyp = @(GET_GETVINT_TYP, s), getvintloc = @(GET_GETVINT_LOC, s), getvintcon = @(GET_GETVINT_CON, s), getvintret = @(GET_GETVINT_RET, s) in \(nz : VMKState) let v1 = @(GetEval4Dval, @(r, getvinttyp)), v2 = @(GetEval4Dval, @(r, getvintloc)), v3 = @(GetEval4Dval, @(r, getvintcon)), v4 = @(GetEval4Dval, @(r, getvintret)), vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let current_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) let vmcb = @(VMCB_GET, nz, current_vm_loc) in let vintcblock = @(GetVMCBVIntCBlck, vmcb) in let vtickint = @(GetVMVIntTickCB, vintcblock), vservintl = @(GetVMVIntServCB, vintcblock), vextrintl = @(GetVMVIntExtrCB, vintcblock), vexcpintl = @(GetVMVIntExcpCB, vintcblock) in @(GIF_THEN_ELSE, VMKState, @(VIntCheck, nz, vtickint), let vintcb = @(GetVMVIntCB, nz, vtickint) in let inttyp = VTickIntType, intloc = vtickint, intcon = @(GetVMVIntCBHand, vintcb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v1), inttyp), z2 = @(CHANGE, z1, @(GET_KLVAL, v2), @(KLVAL, z3 = @(CHANGE, z2, @(GET_KLVAL, v3), @(KCVAL, z4 = @(CHANGE, z3, @(GET_KLVAL, v4), @(KIVAL, @(c, z4), @(GIF_THEN_ELSE, VMKState, @(VIntCheckList, nz, vservintl), let vintcbloc = @(FindVMVIntCB, vservintl, nz) in let vintcb = @(GetVMVIntCB, nz, vintcbloc) in let inttyp = VServIntType, intloc = vintcbloc, intcon = @(GetVMVIntCBHand, vintcb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v1), inttyp), z2 = @(CHANGE, z1, @(GET_KLVAL, v2), @(KLVAL, z3 = @(CHANGE, z2, @(GET_KLVAL, v3), @(KCVAL, z4 = @(CHANGE, z3, @(GET_KLVAL, v4), @(KIVAL, @(c, z4), @(GIF_THEN_ELSE, VMKState, @(VIntCheckList, nz, vextrintl), let vintcbloc = @(FindVMVIntCB, vextrintl, nz) in let vintcb = @(GetVMVIntCB, nz, vintcbloc) in let inttyp = VExtrIntType, intloc = vintcbloc,

198

in

intloc)), intcon)), VMK_OK)) in

intloc)), intcon)), VMK_OK)) in

Semantics for Virtual Interrupt Management

intcon = @(GetVMVIntCBHand, vintcb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v1), inttyp), z2 = @(CHANGE, z1, @(GET_KLVAL, v2), @(KLVAL, z3 = @(CHANGE, z2, @(GET_KLVAL, v3), @(KCVAL, z4 = @(CHANGE, z3, @(GET_KLVAL, v4), @(KIVAL, @(c, z4), @(GIF_THEN_ELSE, VMKState, @(VIntCheckList, nz, vexcpintl), let vintcbloc = @(FindVMVIntCB, vexcpintl, nz) in let vintcb = @(GetVMVIntCB, nz, vintcbloc) in let inttyp = VExcpIntType, intloc = vintcbloc, intcon = @(GetVMVIntCBHand, vintcb) in let z1 = @(CHANGE, nz, @(GET_KLVAL, v1), inttyp), z2 = @(CHANGE, z1, @(GET_KLVAL, v2), @(KLVAL, z3 = @(CHANGE, z2, @(GET_KLVAL, v3), @(KCVAL, z4 = @(CHANGE, z3, @(GET_KLVAL, v4), @(KIVAL, @(c, z4), let z1 = @(CHANGE, nz, @(GET_KLVAL, v4), @(KIVAL, @(c, z1)))));

199

intloc)), intcon)), VMK_OK)) in

intloc)), intcon)), VMK_OK)) in VMK_FAIL)) in

Chapter 17

Semantics of APIs for Configuration Management 17.1

List of APIs

dec VMInit : [VMConfigTable -> KEnv -> VMKDont -> VMKCont];

17.2

Semantics of VMKInit

17.2.1

Intialization of VM Virtual Interrupt

dec VMIntInit : [VMKLocation -> Bool -> VMKCont]; def VMIntInit = \(vintloc : VMKLocation, mask : Bool, z : VMKState) let vintcb = @(GetVMVIntCB, z, vintloc) in let nvintcb = @(SetVMVIntCBMask, vintcb, mask) in @(SetVMVIntCB, z, vintloc, nvintcb); dec VMIntInitList : [MList -> IntMaskDefList -> VMKState -> VMKState]; dec GetIntLocList : [IntMaskDefList -> VMKState -> @(And, MList, VMKState)]; def GetIntLocList = \(intl : IntMaskDefList, z : VMKState) @(GIF_THEN_ELSE, @(And, MList, VMKState), @(IS_EMPTY_MLIST, intl), @(ANDS, MList, VMKState, MNIL, z),

200

Semantics for Configuration Management

let hintl = @(MHEAD, intl, z), tintl = @(MTAIL, intl, z) in let loc = @(GetIntMaskDefLoc, hintl) in let tl2z = @(GetIntLocList, tintl, z) in let tl = @(PJ1, MList, VMKState, tl2z), nz = @(PJ2, MList, VMKState, tl2z) in @(MCONS, @(KLVAL, loc), tl, nz));

17.2.1.1

Initialization of Priority Queue Array

dec DO_INIT_VM_QARRAY : [Array -> Nat -> Nat -> VMKCont]; def DO_INIT_VM_QARRAY = \(qarray : Array, i : Nat, n : Nat, z : VMKState) @(GIF_THEN_ELSE, VMKState, @(NGT, i, n), z, let nz = @(KASSIGN, qarray, @(CONS, Nat, i, @(NIL, Nat)), MNIL, z) in @(DO_INIT_VM_QARRAY, qarray, @(SS, i), n, nz)); dec INIT_VM_QARRAY : [Array -> VMKCont]; def INIT_VM_QARRAY = \(new_qarray : Array, z : VMKState) @(DO_INIT_VM_QARRAY, new_qarray, OO, VMK_PRIORITY_NUMBER, z); dec ADD_VM_TTLIST : [VMKLocation -> VMKCont]; def ADD_VM_TTLIST = \(l : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let tvmlist = @(GET_VMKMAN_TICKWT, vmk_manager) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, l), tvmlist, nz), nz, let ntvmlist2z = @(MCONS, @(KLVAL, l), tvmlist, nz) in let ntvmlist = @(PJ1, MList, VMKState, ntvmlist2z), xz = @(PJ2, MList, VMKState, ntvmlist2z) in let nvmk_manager = @(SET_VMKMAN_TICKWT, vmk_manager, ntvmlist) in @(CHANGE, xz, VMK_MANAGER_LOC, nvmk_manager)); dec ADD_VM_QARRAY : [VMPriority -> VMKLocation -> VMKCont]; def ADD_VM_QARRAY = \(p : VMPriority, l : VMKLocation, nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC), qarray = @(GET_PVMQ_ARRAY, @(GET_VMKMAN_PRIOTQ, vmk_manager)), qarray_size = @(GET_PVMQ_MNUMB, @(GET_VMKMAN_PRIOTQ, vmk_manager)) in

201

Semantics for Configuration Management

let qlist = @(KSUBSCRIPT, qarray, @(CONS, Nat, p, @(NIL, Nat)), nz) in @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, l), qlist, nz), nz, let nqlist2z = @(MCONS, @(KLVAL, l), qlist, nz) in let nqlist = @(PJ1, MList, VMKState, nqlist2z), z1 = @(PJ2, MList, VMKState, nqlist2z), z2 = @(KASSIGN, qarray, @(CONS, Nat, p, @(NIL, Nat)), nqlist, z1) in z2);

17.2.2

Initialization of VMs

def VMInit = \(vmconfig : VMConfigTable, r : KEnv, k : VMKDont) let vmname = @(GetVMConfName, vmconfig), vmpriority = @(GetVMConfPriority, vmconfig), vmschedtype = @(GetVMConfSchdType, vmconfig), vmautostart = @(GetVMConfAutoStrt, vmconfig), vmresetaddr = @(GetVMConfResetAdr, vmconfig), vmtickmask = @(GetVMConfTickMask, vmconfig), vmexcpmask = @(GetVMConfExcpMask, vmconfig), vmextrmask = @(GetVMConfExtrMask, vmconfig), vmservmask = @(GetVMConfServMask, vmconfig), vmtcslcsize = @(GetVMConfTSlcSize, vmconfig), vmmemoindex = @(GetVMConfVMMemIdx, vmconfig), vmexportvar = @(GetVMConfExpVars, vmconfig) in \(z : VMKState) let z0 = @(INIT_VM_MEMO, vmmemoindex, z), vmloc2vmkstate = @(NEW_VM_LOC, z0) in let vmloc = @(PJ1, VMKLocation, VMKState, vmloc2vmkstate), z1 = @(PJ2, VMKLocation, VMKState, vmloc2vmkstate) in let nr = @(ENTER_LOC_KENV, r, vmname, @(KLVAL, vmloc)) in let tickloc = @(GetIntMaskDefLoc, vmtickmask), tickmsk = @(GetIntMaskDefMsk, vmtickmask) in let excpintlocl2z = @(GetIntLocList, vmexcpmask, z1) in let excpintlocl = @(PJ1, MList, VMKState, excpintlocl2z), nz1 = @(PJ2, MList, VMKState, excpintlocl2z) in let extrintlocl2z = @(GetIntLocList, vmextrmask, nz1) in let extrintlocl = @(PJ1, MList, VMKState, extrintlocl2z), nz2 = @(PJ2, MList, VMKState, extrintlocl2z) in let servintlocl2z = @(GetIntLocList, vmservmask, z1) in let servintlocl = @(PJ1, MList, VMKState, servintlocl2z), nz3 = @(PJ2, MList, VMKState, servintlocl2z) in let vmstatus = @(GIF_THEN_ELSE, VMStatus, vmautostart, VMREADY, VMSLEEP) in let vmcb = @(MkVMCB,

202

Semantics for Configuration Management

vmname, vmstatus, vmschedtype, VMWUNull, vmpriority, vmresetaddr, OO, vmtcslcsize, vmtcslcsize, OO, OO, @(MkVMVIntCBlock, FF, OO, tickloc, excpintlocl, extrintlocl, servintlocl), \(x : VMKState) x, @(MkExcpCont, HM_ACTION_NULL, \(x : VMKState) x), HM_NULL, vmmemoindex, vmexportvar) in let z2 = @(VMIntInit, tickloc, tickmsk, nz3), z3 = @(VMIntInitList, excpintlocl, vmexcpmask, z2), z4 = @(VMIntInitList, extrintlocl, vmextrmask, z3), z5 = @(VMIntInitList, servintlocl, vmservmask, z4), z6 = @(VMCB_SET, z5, vmloc, vmcb) in @(GIF_THEN_ELSE, VMKState, vmschedtype, let z7 = @(ADD_VM_TTLIST, vmloc, z6) in @(k, nr, z7), let z7 = @(ADD_VM_QARRAY, vmpriority, vmloc, z6) in @(k, nr, z7)); dec VMInitList : [MList -> KEnv -> VMKDont -> VMKCont]; def VMInitList = \(vmcl : MList, r : KEnv, k : VMKDont, z : VMKState) @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, vmcl), @(k, r, z), let hvmcl = @(MHEAD, vmcl, z), tvmcl = @(MTAIL, vmcl, z) in @(VMInit, hvmcl, r, \(rr : KEnv) @(VMInitList, tvmcl, rr, k),

203

Semantics for Configuration Management

z));

17.2.3

Initialization of Idle VM

Idle VM is defined as a default backstage VM with lowest priority. dec VMKLOOP : VMKCont; def VMKLOOP = \(x : VMKState) @(VMKLOOP, x); def InitIdleVM = \(z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let idle_vmcb = @(MkVMCB, IDLE_VM_ID, VMREADY, VMSchedulePr, VMWUNull, @(PP, VMK_PRIORITY_NUMBER), VMKLOOP, OO, IDLE_VM_SLICE_SIZE, IDLE_VM_SLICE_SIZE, OO, OO, @(MkVMVIntCBlock, FF, OO, NIL_VMKLOC, MNIL, MNIL, MNIL), \(x : VMKState) x, @(MkExcpCont, HM_ACTION_NULL, \(x : VMKState) x), HM_NULL, IDLE_VM_IDX, MNIL) in let z1 = @(ADD_VM_QARRAY, @(PP, VMK_PRIORITY_NUMBER), IDLE_VM_LOC, z), z2 = @(VMCB_SET, z1, IDLE_VM_LOC, idle_vmcb) in let nvmk_manager = @(SET_VMKMAN_IDLEVM, vmk_manager, IDLE_VM_LOC) in @(CHANGE, z2, VMK_MANAGER_LOC, nvmk_manager);

17.2.4

Initialization of TTS

dec TTSInit : [TTSConfigTable -> KEnv -> VMKDont -> VMKCont]; def TTSInit = \(ttsconfig : TTSConfigTable, r : KEnv, k : VMKDont) let ttsname = @(GetTTSConfName, ttsconfig), nodemax = @(GetTTSConfNodeMax, ttsconfig), maxfrmtck = @(GetTTSConfMFrmTck, ttsconfig), nodes = @(GetTTSConfNodes, ttsconfig) in \(z : VMKState)

204

Semantics for Configuration Management

let ttsloc2z = @(NEW_VMKLOC, z) in let ttsloc = @(PJ1, VMKLocation, VMKState, ttsloc2z), nz = @(PJ2, VMKLocation, VMKState, ttsloc2z) in let ttscb = @(MkTTSCB, ttsname, TTSIdle, nodemax, ttsloc, maxfrmtck, OO, OO, OO, OO, nodes) in let nr = @(ENTER_LOC_KENV, r, ttsname, @(KLVAL, ttsloc)) in let z1 = @(TTSCB_SET, nz, ttsloc, ttscb) in @(k, nr, z1); dec TTSInitList : [MList -> KEnv -> VMKDont -> VMKCont]; def TTSInitList = \(ttsl : MList, r : KEnv, k : @(GIF_THEN_ELSE, VMKState, @(IS_EMPTY_MLIST, ttsl), @(k, r, z), let httsl = @(MHEAD, ttsl, tttsl = @(MTAIL, ttsl, @(TTSInit, httsl, r, \(rr : KEnv) @(TTSInitList, tttsl, z));

17.2.5

VMKDont, z : VMKState)

z), z) in

rr, k),

Initialization of VMK

dec VMKISRInstall : VMKCont; def VMKInit = \(s : Statement, r : KEnv, k : VMKDont) \(z : VMKState) let v = @(GetEval4Dval, @(r, VMK_CONF_ID)), nz = @(SET_VMKST_IDX, z, VMK_MANAGER_IDX), vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let vmkconfig = @(VMKCONF_GET, nz, @(GET_KLVAL, v)) in let vmconf = @(GetVMKConfVMConf, vmkconfig), ttsconf = @(GetVMKConfTTSConf, vmkconfig), autostarttts = @(GetVMKConfAutoStr, vmkconfig), inttable = @(GetVMKConfIntTabl, vmkconfig),

205

Semantics for Configuration Management

vmnumb = @(GetVMKConfVMNumb, vmkconfig), vmtable = @(GetVMKConfVMTable, vmkconfig), ttsnumb = @(GetVMKConfTTSNumb, vmkconfig), ttstable = @(GetVMKConfTTSTable, vmkconfig), vmkcont = @(GetVMKConfVMKCont, vmkconfig), vmkmemoindex = @(GetVMKConfVMKMIdx, vmkconfig), vmkflowlist = @(GetVMKConfFlowLst, vmkconfig) in let new_qarray = KCREATE, VMK_MANAGER_IDX = vmkmemoindex in let z1 = @(VMKInitHook, nz), z2 = @(INIT_VM_QARRAY, new_qarray, z1) in let vmk_manager1 = @(SET_VMKMAN_STATUS, vmk_manager, MkColdStart), vmk_manager2 = @(SET_VMKMAN_TICKCN, vmk_manager1, OO), vmk_manager3 = @(SET_VMKMAN_RUNVM, vmk_manager2, IDLE_VM_LOC), vmk_manager4 = @(SET_VMKMAN_IDLEVM, vmk_manager3, IDLE_VM_LOC), vmk_manager5 = @(SET_VMKMAN_INTDIS, vmk_manager4, inttable), vmk_manager6 = @(SET_VMKMAN_TTSLST, vmk_manager5, MNIL), vmk_manager7 = @(SET_VMKMAN_CURTTS, vmk_manager6, autostarttts), vmk_manager8 = @(SET_VMKMAN_TICKWT, vmk_manager7, MNIL), vmk_manager9 = @(SET_VMKMAN_EXCPVM, vmk_manager8, MNIL), vmk_manager10 = @(SET_VMKMAN_PRIOTQ, vmk_manager9, @(MK_PVMQ, @(KAVAL, new_qarray), VMK_PRIORITY_NUMBER)), vmk_manager11 = @(SET_VMKMAN_VMNUMB, vmk_manager10, vmnumb), vmk_manager12 = @(SET_VMKMAN_VMLIST, vmk_manager11, vmtable), vmk_manager13 = @(SET_VMKMAN_TTSNUM, vmk_manager12, ttsnumb), vmk_manager14 = @(SET_VMKMAN_TTSLST, vmk_manager13, ttstable), vmk_manager15 = @(SET_VMKMAN_MEMIDX, vmk_manager14, vmkmemoindex), vmk_manager16 = @(SET_VMKMAN_TTSVM, vmk_manager15, IDLE_VM_LOC), vmk_manager17 = @(SET_VMKMAN_CONTXT, vmk_manager16, VMKLOOP), vmk_manager18 = @(SET_VMKMAN_PQUEVM, vmk_manager17, NIL_VMKLOC), vmk_manager19 = @(SET_VMKMAN_INTCBL, vmk_manager18, MNIL), vmk_manager20 = @(SET_VMKMAN_EXINTL, vmk_manager19, MNIL), vmk_manager21 = @(SET_VMKMAN_FLOWLT, vmk_manager20, vmkflowlist) in let z3 = @(ADD_VM_QARRAY, OO, IDLE_VM_LOC, z2), z4 = @(InitIdleVM, z3), z5 = @(CHANGE, z4, VMK_MANAGER_LOC, vmk_manager21), z6 = @(VMInitList, vmconf, r, \(r1 : KEnv) @(TTSInitList, ttsconf, r1, \(r2 : KEnv) let c1 = VMKStartHook, c2 = @(SCHEDULE, VMKLOOP) in \(x : VMKState) @(c2, @(c1, @(k, r2, x)))), z5), z7 = @(VMKISRInstall, z6) in @(GIF_THEN_ELSE, VMKState,

206

Semantics for Configuration Management

@(AND, @(CHK_INTCB, z7), @(CHK_EXINTCB, z7)), z7, @(ERR_VMKSTATE, z7));

207

Chapter 18

Semantics of APIs for Health Management 18.1

List of APIs

dec vmkDispatchHM : [Nat -> HMType -> ExcpCont -> VMKCont]; dec vmkInformHM : [HMType -> ExcpCont -> VMKCont -> VMKState -> @(Product, HMAction, VMKState)];

18.2

Semantics of vmkDispatchHM

dec vmkDispatchHM : [Nat -> HMType -> ExcpCont -> VMKCont]; def vmkDispatchHM = \(vector : Nat, type : HMType, context : ExcpCont, z : VMKState) let action = @(GetExceptionAction, vector, z) in @(GIF_THEN_ELSE, VMKState, @(IS_HM_ACT_RESET, action), @(HMResetHook, vector, type, context, z), @(GIF_THEN_ELSE, VMKState, @(IS_HM_ACT_SHUTDOWN, action), @(HMShutDownHook, vector, type, context, z), @(HMIgnoreHook, vector, type, context, z)));

208

CHAPTER 18. SEMANTICS OF APIS FOR HEALTH MANAGEMENT 209

18.3

Semantics of vmkInformHM

dec DoServInt : [Nat -> VMCB -> VMKCont]; def DoServInt = \(vector : Nat, vm : VMCB, z : VMKState) let vint_block = @(GetVMCBVIntCBlck, vm) in let vint_init = @(GetVMVIntInit, vint_block), vint_serv = @(GetVMVIntServCB, vint_block) in let serv_int_loc = @(GET_LOC_MLIST, vector, vint_serv, z) in @(GIF_THEN_ELSE, VMKState, vint_init, let servintcb = @(GetVMVIntCB, z, serv_int_loc) in let nservintcb = @(SetVMVIntCBFire, servintcb, TT) in @(SetVMVIntCB, z, serv_int_loc, nservintcb), z); dec DovmkInformHM : [VMKLocation -> HMType -> ExcpCont -> VMKCont -> VMKState -> @(Product, HMAction, VMKState)]; def DovmkInformHM = \(vm_loc : VMKLocation, type : HMType, context : ExcpCont, c : VMKCont, z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC), vector = @(GetExcpContNumb, context), excont = @(GetExcpContCont, context) in let vmcb = @(VMCB_GET, z, vm_loc), vm_status = @(GetVMCBStatus, vmcb) in let z1 = @(GLOBAL_INT_DISABLE, z), z2 = @(ClearVMReady, vm_loc, z1) in let vmcb1 = @(SetVMCBStatus, vmcb, @(InclOrVMStatus, vm_status, VMSUSPEND)) in let z3 = @(GIF_THEN_ELSE, VMKState, @(NOT, @(IS_HM_ERROR_ACTION, type)), let vmcb2 = @(SetVMCBHmType, vmcb1, type), vmcb3 = @(SetVMCBHmContxt, vmcb2, context) in let vexcp_vm_list = @(GET_VMKMAN_EXCPVM, vmk_manager) in let nvexcp_vm_list2z = @(MCONS, @(KLVAL, vm_loc), vexcp_vm_list, z2) in let nvexcp_vm_list = @(PJ1, MList, VMKState, nvexcp_vm_list2z), nz0 = @(PJ2, MList, VMKState, nvexcp_vm_list2z) in let nvmk_manager = @(SET_VMKMAN_EXCPVM, vmk_manager, nvexcp_vm_list), nz1 = @(CHANGE, nz0, VMK_MANAGER_LOC, nvmk_manager) in let vmm0 = @(VMCB_GET, nz1, VMK_VMM_ID), nz2 = @(DoServInt, VMM_EXCEPTION_SERVICE, vmm0, nz1) in

CHAPTER 18. SEMANTICS OF APIS FOR HEALTH MANAGEMENT 210

let wakeup_type = @(GetVMCBWakeType, vmm0) in @(GIF_THEN_ELSE, VMKState, @(IS_VMWUBasic, wakeup_type), let tick_wait_list = @(GET_VMKMAN_TICKWT, nvmk_manager) in let nz3 = @(GIF_THEN_ELSE, VMKState, @(IS_IN_MLIST, @(KLVAL, VMK_VMM_ID), tick_wait_list, nz1), @(ExactWaitedVM, VMK_VMM_ID, nz2), nz2) in @(ClearVMWaiting, VMK_VMM_ID, nz3), @(ClearVMWaiting, VMK_VMM_ID, nz2)), z2), z4 = @(GLOBAL_INT_ENABLE, z3), z5 = @(SCHEDULE, c, z4) in let vmcb2 = @(SetVMCBHmType, vmcb1, HM_NULL), vmcb3 = @(SetVMCBHmContxt, vmcb2, NullExcpCont) in let z6 = @(VMCB_SET, z5, vm_loc, vmcb3) in @(PRODUCT, HMAction, VMKState, HM_ACTION_IGNORE, z6); dec vmkInformHM : [HMType -> ExcpCont -> VMKCont -> VMKState -> @(Product, HMAction, VMKState)]; def vmkInformHM = \(type : HMType, context : ExcpCont, c : VMKCont, z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC), vector = @(GetExcpContNumb, context), excont = @(GetExcpContCont, context) in let vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let vmcb = @(VMCB_GET, z, vm_loc), vm_status = @(GetVMCBStatus, vmcb) in @(GIF_THEN_ELSE, @(Product, HMAction, VMKState), @(EQ_VMKLOC, vm_loc, VMK_VMM_ID), let vint_block = @(GetVMCBVIntCBlck, vmcb) in let vintinit = @(GetVMVIntInit, vint_block), vexcpnumb = @(GetVMVIntExcpNum, vint_block), vexcpintl = @(GetVMVIntExcpCB, vint_block) in @(GIF_THEN_ELSE, @(Product, HMAction, VMKState), @(AND, @(IS_HM_EXCEPTION, type), @(IS_ZERO, vexcpnumb)), let excp_int_loc = @(GET_LOC_MLIST, vector, vexcpintl, z) in let excp_intcb = @(GetVMVIntCB, z, excp_int_loc) in let excp_intcb1 = @(SetVMVIntCBFire, excp_intcb, TT), vexcpnumb1 = @(SS, vexcpnumb) in let vint_block1 = @(SetVMVIntExcpNum, vint_block, vexcpnumb1) in let z0 = @(SetVMVIntCB, z, excp_int_loc, excp_intcb1), vmcb2 = @(SetVMCBVIntCBlck, vmcb, vint_block1) in let z1 = @(VMCB_SET, z, vm_loc, vmcb2) in @(PRODUCT, HMAction, VMKState, HM_ACTION_DELIVER, z1), @(GIF_THEN_ELSE, @(Product, HMAction, VMKState),

CHAPTER 18. SEMANTICS OF APIS FOR HEALTH MANAGEMENT 211

@(IS_HM_ERROR_ACTION, type), @(PRODUCT, HMAction, VMKState, HM_ACTION_UPGRADE, z), @(PRODUCT, HMAction, VMKState, HM_ACTION_IGNORE, z))), let vint_block = @(GetVMCBVIntCBlck, vmcb) in let vintinit = @(GetVMVIntInit, vint_block), vexcpnumb = @(GetVMVIntExcpNum, vint_block), vexcpintl = @(GetVMVIntExcpCB, vint_block) in @(GIF_THEN_ELSE, @(Product, HMAction, VMKState), @(AND, @(IS_HM_EXCEPTION, type), @(AND, @(NOT, @(IS_VMDEBUG, vm_status)), @(IS_ZERO, vexcpnumb))), let excp_int_loc = @(GET_LOC_MLIST, vector, vexcpintl, z) in let excp_intcb = @(GetVMVIntCB, z, excp_int_loc) in let excp_intcb1 = @(SetVMVIntCBFire, excp_intcb, TT), vexcpnumb1 = @(SS, vexcpnumb) in let vint_block1 = @(SetVMVIntExcpNum, vint_block, vexcpnumb1) in let z0 = @(SetVMVIntCB, z, excp_int_loc, excp_intcb1), vmcb2 = @(SetVMCBVIntCBlck, vmcb, vint_block1) in let z1 = @(VMCB_SET, z, vm_loc, vmcb2) in @(PRODUCT, HMAction, VMKState, HM_ACTION_DELIVER, z1), @(DovmkInformHM, vm_loc, type, context, c, z)));

Part II

The Verification of VMK

212

Chapter 19

Separation-Kernel Properties of VMK 19.1

Definitions of Separation Kernel Properties

19.1.1

Well-Defined VMCB

Definition 19.1 (Well-Defined VMCB) A vmcb of type VMCB is well-defined on state z if it is corresponding segment index is well-defined on state z. dec VMCB_In_VMKState : [VMCB -> VMKState -> Prop]; def VMCB_In_VMKState = \(vmcb : VMCB, z : VMKState) let vmcbidx = @(GetVMCBMemoIndex, vmcb) in let spc = @(GET_VMKST_SPC, z) in let seg = @(FIND_SEGMENT, spc, vmcbidx) in @(Not, @(Equal, VMKMemManager, seg, ERR_VMKMEMMAN));

19.1.2

Well-Defined Addresses

Definition 19.2 (Well-Defined VMK Addresses) An address l of type VMKAddress is well-defined on state z and vmcb of type VMCB if its corresponding segment index is equal to the segment index of vmcb and its local location is well-defined on corresponding memory space on state z. dec Addr_In_VMCB : [VMKAddress -> VMKState -> VMCB -> Prop];

213

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

def Addr_In_VMCB = \(l : VMKAddress, z : VMKState, vmcb : VMCB) let addr_idx = @(GET_VMKADDR_IDX, l), addr_loc = @(GET_VMKADDR_LOC, l) in let vmcb_idx = @(GetVMCBMemoIndex, vmcb) in @(And, @(Equal, VMKMemoIndex, addr_idx, vmcb_idx), let nz = @(SET_VMKST_IDX, z, addr_idx) in let v = @(GET, nz, addr_loc) in @(Not, @(Equal, KSval, v, ERR_KSVAL)));

19.1.3

Uniqueness of VMK Manager Index

def UniqVMKManIdxCond = \(z : VMKState) !(vmcb : VMCB) [@(VMCB_In_VMKState, vmcb, z) -> let vmindex = @(GetVMCBMemoIndex, vmcb) in @(Not, @(Equal, VMKMemoIndex, vmindex, VMK_MANAGER_IDX))];

19.1.4

Uniqueness of VMCB Indexes

def UniqVMCBIdxCond1 = \(z : VMKState) !(vmcb1 : VMCB, vmcb2 : VMCB) [@(VMCB_In_VMKState, vmcb1, z) -> @(VMCB_In_VMKState, vmcb2, z) -> @(Not, @(Equal, VMCB, vmcb1, vmcb2)) -> let vmindex1 = @(GetVMCBMemoIndex, vmcb1), vmindex2 = @(GetVMCBMemoIndex, vmcb2) in @(Not, @(Equal, Nat, vmindex1, vmindex2))]; def UniqVMCBIdxCond2 = \(z : VMKState) !(vmcb1 : VMCB, vmcb2 : VMCB) [@(VMCB_In_VMKState, vmcb1, z) -> @(VMCB_In_VMKState, vmcb2, z) -> let vmindex1 = @(GetVMCBMemoIndex, vmcb1), vmindex2 = @(GetVMCBMemoIndex, vmcb2) in @(Not, @(Equal, Nat, vmindex1, vmindex2)) -> @(Not, @(Equal, VMCB, vmcb1, vmcb2))];

214

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

19.1.5

215

Space Separation Property

Definition 19.3 (Separation Kernel Condition) For a given VMK state z, for any vmcb1 of type VMCB, if vmcb1 is well-defined in z, for any address l, if l is well-defined in z and vmcb1, for any vmcb2 of type VMCB, if vmcb2 is well-defined in z and l is well-defined in z and vmcb2, then vmcb1 and vmcb2 are equal. def SepKernelCond = \(z : VMKState) !(vmcb1 : VMCB) [@(VMCB_In_VMKState, vmcb1, z) -> !(l : VMKAddress) [@(Addr_In_VMCB, l, z, vmcb1) -> !(vmcb2 : VMCB) [@(VMCB_In_VMKState, vmcb2, z) -> @(Addr_In_VMCB, l, z, vmcb2) -> @(Equal, VMCB, vmcb1, vmcb2)]]];

19.1.6

Temporal Separation Property: Uniqueness of Running VM

def UniqeRunningVM = \(z : VMKState) !(vmcb1 : VMCB) [@(VMCB_In_VMKState, vmcb1, z) -> let status1 = @(GetVMCBStatus, vmcb1) in [@(Equal, VMStatus, status1, VMRUNNING) -> !(vmcb2 : VMCB) [@(VMCB_In_VMKState, vmcb2, z) -> let status2 = @(GetVMCBStatus, vmcb2) in [@(Equal, VMStatus, status2, VMRUNNING) -> @(Equal, VMCB, vmcb1, vmcb2)]]]]

19.1.7

Uniqueness of VMKMagnager Configuration Table Index

def UniqVMKConfIdxCd = !(vmconf : VMConfigTable) let vmindex = @(GetVMConfVMMemIdx, vmconf) in @(Not, @(Equal, VMKMemoIndex, vmindex, VMK_MANAGER_IDX));

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

19.1.8

216

Uniqueness of Idle VM Index

def UniqVMConfIdxCd0 = !(vmconf : VMConfigTable) let vmindex = @(GetVMConfVMMemIdx, vmconf) in @(Not, @(Equal, Nat, vmindex, IDLE_VM_IDX));

19.1.9

Uniqueness of VM Configuration Table Indexes

def UniqVMConfIdxCd1 = !(vmconf1 : VMConfigTable, vmconf2 : VMConfigTable) [@(Not, @(Equal, VMConfigTable, vmconf1, vmconf2)) -> let vmindex1 = @(GetVMConfVMMemIdx, vmconf1), vmindex2 = @(GetVMConfVMMemIdx, vmconf2) in @(Not, @(Equal, Nat, vmindex1, vmindex2))]; def UniqVMConfIdxCd2 = !(vmconf1 : VMConfigTable, vmconf2 : VMConfigTable) [let vmindex1 = @(GetVMConfVMMemIdx, vmconf1), vmindex2 = @(GetVMConfVMMemIdx, vmconf2) in @(Not, @(Equal, Nat, vmindex1, vmindex2)) -> @(Not, @(Equal, VMConfigTable, vmconf1, vmconf2))]

19.2

The Separation Kernel Theorem

19.2.1

The Uniqueness of Segment Index of VMK Manager

Theorem 19.1 The segment index of VMK manager is unique.

dec UniqVMKManIdxThm : !(z : VMKState) @(UniqVMKManIdxCond, z);

19.2.2

The Uniqueness of Segment Index of VMCBs

Theorem 19.2 The segment index of each of VMCB is unique.

dec UniqVMCBIdxThm1 : !(z : VMKState)

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

217

@(UniqVMCBIdxCond1, z); dec UniqVMCBIdxThm2 : !(z : VMKState) @(UniqVMCBIdxCond2, z);

19.2.3

Uniqueness VMK Configuration Index Theorems

dec UVMKConfIdxThm0 : !(vmkconf : VMKConfigTable) let vmkconfidx = @(GetVMKConfVMKMIdx, vmkconf) in @(Equal, VMKMemoIndex, vmkconfidx, VMK_MANAGER_IDX); dec UVMKConfIdxThm1 : !(vmkconf : VMKConfigTable) ?(vmk_manager : VMKManager) let vmkconfidx = @(GetVMKConfVMKMIdx, vmkconf), vmkmanindex = @(GET_VMKMAN_MEMIDX, vmk_manager) in @(Equal, VMKMemoIndex, vmkconfidx, vmkmanindex); dec UVMConfIdxThm : !(vmconf : VMConfigTable) ?(vmcb1 : VMCB) let vmconfidx = @(GetVMConfVMMemIdx, vmconf), vmcbindex1 = @(GetVMCBMemoIndex, vmcb1) in @(And, @(Equal, VMKMemoIndex, vmconfidx, vmcbindex1), !(vmcb2 : VMCB) let vmcbindex2 = @(GetVMCBMemoIndex, vmcb2) in [@(Equal, VMKMemoIndex, vmconfidx, vmcbindex2) -> @(Equal, VMCB, vmcb1, vmcb2)]);

19.2.4

The Separation Kernel Theorem

Theorem 19.3 (Separation Kernel Theorem) For any VMK state z and vmcb1 of type VMCB, if vmcb1 is well-defined on z, for any address l, if l is welldefined on z and vmcb1, for any vmcb2 of type VMCB, if vmcb2 is well-defined on z and l is well-defined on z and vmcb2, then vmcb1 and vmcb2 are equal. In terms of PowerEpsilon, we have the following description: dec SepKernelThm : !(z : VMKState) @(SepKernelCond, z);

To prove SepKernelThm, we need the following lemma.

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

218

Lemma 19.1 (Separation Kernel Lemma) For any VMK state z and vmcb1 of type VMCB, if vmcb1 is well-defined on z, for any address l, if l is welldefined on z and vmcb1, for any vmcb2 of type VMCB, if vmcb2 is well-defined on z and l is well-defined on z and vmcb2, then the segment index of vmcb1 and vmcb2, namely, vmindex1 and vmindex2 are equal. dec SepKernelLem : !(z : VMKState) !(vmcb1 : VMCB) [@(VMCB_In_VMKState, vmcb1, z) -> !(l : VMKAddress) [@(Addr_In_VMCB, l, z, vmcb1) -> !(vmcb2 : VMCB) [@(VMCB_In_VMKState, vmcb2, z) -> @(Addr_In_VMCB, l, z, vmcb2) -> let vmindex1 = @(GetVMCBMemoIndex, vmcb1), vmindex2 = @(GetVMCBMemoIndex, vmcb2) in @(Equal, Nat, vmindex1, vmindex2)]]];

To carry out the proof, we also need the exclusive-middle rule represented as follows: dec ExclMidRule : !(P : Prop) @(Or, P, @(Not, P));

The proof of SepKernelLem is given as follows: def SepKernelLem = \(z : VMKState) \(vmcb1 : VMCB) \(p : @(VMCB_In_VMKState, vmcb1, z)) \(l : VMKAddress) \(q : @(Addr_In_VMCB, l, z, vmcb1)) \(vmcb2 : VMCB) \(q1 : @(VMCB_In_VMKState, vmcb2, z), q2 : @(Addr_In_VMCB, l, z, vmcb2)) let vmindex1 = @(GetVMCBMemoIndex, vmcb1), vmindex2 = @(GetVMCBMemoIndex, vmcb2) in let addr_idx = @(GET_VMKADDR_IDX, l), addr_loc = @(GET_VMKADDR_LOC, l) in let vmcb_idx1 = @(GetVMCBMemoIndex, vmcb1), vmcb_idx2 = @(GetVMCBMemoIndex, vmcb2) in let P11 = @(Equal, VMKMemoIndex, addr_idx, vmcb_idx1), P12 = let nz = @(SET_VMKST_IDX, z, addr_idx) in let v = @(GET, nz, addr_loc) in @(Not, @(Equal, KSval, v, ERR_KSVAL)), P21 = @(Equal, VMKMemoIndex, addr_idx, vmcb_idx2),

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

219

P22 = let nz = @(SET_VMKST_IDX, z, addr_idx) in let v = @(GET, nz, addr_loc) in @(Not, @(Equal, KSval, v, ERR_KSVAL)) in let p11 = @(PJ1, P11, P12, q), p21 = @(PJ1, P21, P22, q2) in let w = @(Symm_Eq, VMKMemoIndex, addr_idx, vmcb_idx1, p11) in @(Tran_Eq, VMKMemoIndex, vmcb_idx1, addr_idx, vmcb_idx2, w, p21);

The proof of SepKernelThm is derived from ExclMidRule, UniqVMCBIdxThm1 and SepKernelLem. def SepKernelThm = \(z : VMKState) \(vmcb1 : VMCB) \(p : @(VMCB_In_VMKState, vmcb1, z)) \(l : VMKAddress) \(q : @(Addr_In_VMCB, l, z, vmcb1)) \(vmcb2 : VMCB) \(q1 : @(VMCB_In_VMKState, vmcb2, z), q2 : @(Addr_In_VMCB, l, z, vmcb2)) let P = @(Equal, VMCB, vmcb1, vmcb2) in let w = @(ExclMidRule, P) in @(WHEN, P, @(Not, P), P, w, \(u : P) u, \(u : @(Not, P)) let v1 = @(UniqVMCBIdxThm1, z, vmcb1, vmcb2, p, q1, u), v2 = @(SepKernelLem, z, vmcb1, p, l, q, vmcb2, q1, q2) in @(v1, v2, P))

19.3

The Second Separation Kernel Theorem

19.3.1

Well-Defined Continuation on State

dec IsStateUpdateCont : [VMKCont -> VMKState -> Type(0)]; def IsStateUpdateCont = \(c : VMKCont, z : VMKState) ?(nz : VMKState)

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

220

@(And, @(Not, @(Equal, VMKState, nz, z)), @(Equal, VMKState, @(c, z), nz)); def WTContOnStCond = \(c : VMKCont, z : VMKState) \(c1 : VMKCont, c2 : VMKCont, l : VMKLocation, v : KSval) let cc = \(x : VMKState) @(CHANGE, x, l, v) in let nc = \(x : VMKState) @(c2, @(cc, @(c1, x))) in @(And, @(Equal, VMKCont, c, nc), @(Not, @(Equal, VMKState, @(c, z), @(ERR_VMKSTATE, z)))); def WTContOnSt = \(c : VMKCont, z : VMKState) ?(c1 : VMKCont, c2 : VMKCont, l : VMKLocation, v : KSval) @(WTContOnStCond, c, z, c1, c2, l, v); def WTVMCBContOnSt = \(vmcb : VMCB, z : VMKState) let vmcbidx = @(GetVMCBMemoIndex, vmcb), c = @(GetVMCBIntContxt, vmcb), stidx = @(GET_VMKST_IDX, z) in @(And, @(Equal, VMKMemoIndex, vmcbidx, stidx), ?(c1 : VMKCont, c2 : VMKCont, l : VMKLocation, v : KSval) @(WTContOnStCond, c, z, c1, c2, l, v)); def WTVMCBContOnSt2 = \(vmcb : VMCB, z : VMKState) let vmcbidx = @(GetVMCBMemoIndex, vmcb), c = @(GetVMCBResetCont, vmcb), stidx = @(GET_VMKST_IDX, z) in @(And, @(Equal, VMKMemoIndex, vmcbidx, stidx), ?(c1 : VMKCont, c2 : VMKCont, l : VMKLocation, v : KSval) @(WTContOnStCond, c, z, c1, c2, l, v));

19.3.2

The Second Separation Kernel Theorem

The following theorem cannot be proved if the continuation c does not know its own execution segmentation space. In order to do so, the execution programs must be built (compiled and linked ) on its execution environment (VMs or KVM). dec SepKernelThm2 :

CHAPTER 19. SEPARATION-KERNEL PROPERTIES OF VMK

!(vmcb : VMCB, z : VMKState) [@(VMCB_In_VMKState, vmcb, z) -> @(WTVMCBContOnSt, vmcb, z) -> let vmcbidx = @(GetVMCBMemoIndex, vmcb), c = @(GetVMCBIntContxt, vmcb) in !(nvmcb : VMCB) let nvmcbidx = @(GetVMCBMemoIndex, nvmcb) in [@(Not, @(Equal, Nat, vmcbidx, nvmcbidx)) -> let nz = @(SET_VMKST_IDX, z, nvmcbidx) in @(Equal, VMKState, @(c, nz), @(ERR_VMKSTATE, nz))]];

221

Chapter 20

Security Policies of VMK 20.1

Definition of Capability List in Meta-Language

• PARTITION ABSTRACTION: The subjects in a partition have homogeneous requirements for access, on a per-partition basis, to exported resources. • LEAST PRIVILEGE ABSTRACTION: The subjects in a partition have heterogeneous requirements for access to exported resources.

20.1.1

Resource Access Mode

def VMKAccessMode = !(T : Prop) [T -> T -> T -> T -> T]; dec dec dec dec

VMKAccessNull VMKAccessRO VMKAccessWO VMKAccessRW

: : : :

VMKAccessMode; VMKAccessMode; VMKAccessMode; VMKAccessMode;

def VMKAccessNull = \(T : Prop) \(x1 : T, x2 : T, x3 : T, x4 : T) x1;

222

CHAPTER 20. SECURITY POLICIES OF VMK

20.1.2

Subject Abstraction

def Subject = KSval; def Resource = KSval; dec GetResourceNam : [Resource -> VMKLocation]; dec GetResourceLoc : [Resource -> VMKLocation];

20.1.3

Partition Abstraction

def VMKSubject = @(And, VMKLocation, KSval); def VMKResource = @(And, VMKLocation, KSval);

20.1.4

Subject-Resource Flow

def VMKFlow = !(T : Prop) [[Subject -> Resource -> VMKAccessMode -> T] -> T]; def MkVMKFlow = \(s : Subject, r : Resource, m : VMKAccessMode) \(T : Prop) \(f : [Subject -> Resource -> VMKAccessMode -> T]) @(f, s, r, m); dec GetFlowSubject : [VMKFlow -> Subject]; dec GetFlowResource : [VMKFlow -> Resource]; dec GetFlowMode : [VMKFlow -> VMKAccessMode];

20.1.5

PA Set and SA Set

def VMKFlowSet = [VMKFlow -> Prop];

20.1.6

PA List and SA List

def VMKFlowList = @(List, VMKFlow);

223

CHAPTER 20. SECURITY POLICIES OF VMK

20.1.7

224

Return Mode

def VMKReturnMode = !(T : Prop) [T -> T -> T -> T]; dec RM_ALLOW : VMKReturnMode; dec RM_DENY : VMKReturnMode; dec RM_NULL : VMKReturnMode; dec IS_RM_ALLOW : [VMKReturnMode -> Bool]; dec IS_RM_DENY : [VMKReturnMode -> Bool]; dec IS_RM_NULL : [VMKReturnMode -> Bool];

20.1.8

Rule for PA Set and PA List

An operation shall be allowed in the Partition Abstraction def WDOperationOnPA = \(fl : VMKFlow, PA : VMKFlowSet) @(PA, fl); def PASetRule = \(fl : VMKFlow, PA : VMKFlowSet, rtmode : VMKReturnMode) @(Or, [@(Not, @(PA, fl)) -> @(Equal, VMKReturnMode, rtmode, RM_DENY)], [@(PA, fl) -> @(Equal, VMKReturnMode, rtmode, RM_ALLOW)]); def PAListRule = \(fl : VMKFlow, PA : VMKFlowList) @(GIF_THEN_ELSE, VMKReturnMode, @(NOT, @(IS_IN_LIST, VMKFlow, fl, PA)), RM_DENY, RM_ALLOW);

20.1.9

Rules for LPA Set and LPA List

An operation shall be allowed in the Least Privilege Abstraction def WDOpOnSA2PA = \(fl : VMKFlow, PA : VMKFlowSet, SA : VMKFlowSet) @(Or, @(SA, fl), @(PA, fl)); def LPASetRule = \(fl : VMKFlow, PA : VMKFlowSet, SA : VMKFlowSet, rtmode : VMKReturnMode) @(Or, [@(Not, @(SA, fl)) -> @(Equal, VMKReturnMode, rtmode, RM_DENY)],

CHAPTER 20. SECURITY POLICIES OF VMK

225

@(Or, [@(SA, fl) -> @(Equal, VMKReturnMode, rtmode, RM_ALLOW)], @(Or, [@(Not, @(PA, fl)) -> @(Equal, VMKReturnMode, rtmode, RM_DENY)], [@(PA, fl) -> @(Equal, VMKReturnMode, rtmode, RM_ALLOW)]))); def LPAListRule = \(fl : VMKFlow, PA : VMKFlowList, SA : VMKFlowList) @(GIF_THEN_ELSE, VMKReturnMode, @(NOT, @(IS_IN_LIST, VMKFlow, fl, SA)), RM_DENY, @(GIF_THEN_ELSE, VMKReturnMode, @(IS_IN_LIST, VMKFlow, fl, SA), RM_ALLOW, @(GIF_THEN_ELSE, VMKReturnMode, @(NOT, @(IS_IN_LIST, VMKFlow, fl, PA)), RM_DENY, @(GIF_THEN_ELSE, VMKReturnMode, @(IS_IN_LIST, VMKFlow, fl, PA), RM_ALLOW, RM_DENY))));

An operation shall be allowed in the VMK Least Privilege Abstraction def VMKWDOpOnSA = \(fl : VMKFlow, SA : VMKFlowSet) @(Or, @(SA, fl)); def VMKLPASetRule = \(fl : VMKFlow, SA : VMKFlowSet, rtmode : VMKReturnMode) @(Or, [@(Not, @(SA, fl)) -> @(Equal, VMKReturnMode, rtmode, RM_DENY)], [@(SA, fl) -> @(Equal, VMKReturnMode, rtmode, RM_ALLOW)]); def VMKLPAListRule = \(fl : VMKFlow, SA : VMKFlowList) @(GIF_THEN_ELSE, VMKReturnMode, @(NOT, @(IS_IN_LIST, VMKFlow, fl, SA)), RM_DENY, @(GIF_THEN_ELSE, VMKReturnMode, @(IS_IN_LIST, VMKFlow, fl, SA), RM_ALLOW, RM_DENY));

CHAPTER 20. SECURITY POLICIES OF VMK

226

dec VMKLPAListRuleList : [VMKFlowList -> VMKFlowList -> Bool]; def VMKLPAListRuleList = \(fl : VMKFlowList, SA : VMKFlowList) @(GIF_THEN_ELSE, Bool, @(IS_EMPTY, VMKFlow, fl), TT, let hfl = @(HEAD, VMKFlow, fl), tfl = @(TAIL, VMKFlow, fl) in let rtmode = @(VMKLPAListRule, hfl, SA) in @(GIF_THEN_ELSE, Bool, @(IS_RM_ALLOW, rtmode), @(VMKLPAListRuleList, tfl, SA), FF));

20.1.10

Security Checking

20.1.10.1

Checking List

• Interrupt service routines • System service calls 20.1.10.2

Checking of Well-Definedness of Flow List for Interrupt Service Routines

Definition 20.1 We say that an interrupt service routine kcv is well-defined in flow fl only if there exist subject s, resource r and mode m such that f = [s, r, m] is defined in fl, s is equal to kcv, and there exist index idx and location l such that the content of l in the segment indexed by idx is equal to r. dec WDInFlowList : [KSval -> VMKFlowList -> VMKState -> Type(0)]; def WDInFlowList = \(kcv : KSval, fl : VMKFlowList, z : VMKState) ?(s : Subject, r : Resource, m : VMKAccessMode) let f = @(MkVMKFlow, s, r, m) in @(And, @(Equal, KSval, s, kcv), @(And, @(Equal, Bool, @(IS_IN_LIST, VMKFlow, f, fl), TT), let vml = @(GetResourceNam, r), loc = @(GetResourceLoc, r) in

CHAPTER 20. SECURITY POLICIES OF VMK

let vm = @(VMCB_GET, z, vml) in let idx = @(GetVMCBMemoIndex, vm) in @(And, @(Not, @(Equal, VMKMemoIndex, idx, VMK_MANAGER_IDX)), let nz = @(SET_VMKST_IDX, z, idx) in let v = @(GET, nz, loc) in @(Not, @(Equal, KSval, v, ERR_KSVAL))))); dec DoIntCBChk : [VMKIntCB -> VMKFlowList -> VMKState -> Type(0)]; def DoIntCBChk = \(intcb : VMKIntCB, fl : VMKFlowList, z : VMKState) let c = @(GET_VMKIntCB_CONT, intcb) in let kcv = @(KCVAL, c) in @(WDInFlowList, kcv, fl, z); dec DoIntCBListChk : [MList -> VMKFlowList -> VMKState -> Prop]; def DoIntCBListChk = \(intcb_list : MList, fl : VMKFlowList, z @(GIF_THEN_ELSE0, Prop, @(IS_EMPTY_MLIST, intcb_list), True, let hintcb_list = @(MHEAD, intcb_list, tintcb_list = @(MTAIL, intcb_list, @(And, @(DoIntCBChk, hintcb_list, fl, z), @(DoIntCBListChk, tintcb_list, fl,

: VMKState)

z), z) in

z)));

def VMKIntCBListChk = \(fl : VMKFlowList, z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let intcb_list = @(GET_VMKMAN_INTCBL, vmk_manager) in @(DoIntCBListChk, intcb_list, fl, z); def VMKExIntCBListChk = \(fl : VMKFlowList, z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let exintcb_list = @(GET_VMKMAN_EXINTL, vmk_manager) in @(DoIntCBListChk, exintcb_list, fl, z);

20.1.10.3

Trusted Flows

def TrustedFlowCond1 = \(fl : VMKFlow, SA : VMKFlowList)

227

CHAPTER 20. SECURITY POLICIES OF VMK

@(Equal, VMKReturnMode, @(VMKLPAListRule, fl, SA), RM_ALLOW); def TrustedFlowCond2 = \(fl : VMKFlow, z : VMKState) let s = @(GetFlowSubject, fl), r = @(GetFlowResource, fl), m = @(GetFlowMode, fl) in let c = @(GET_KCVAL, s) in let vml = @(GetResourceNam, r), loc = @(GetResourceLoc, r) in let vm = @(VMCB_GET, z, vml) in let idx = @(GetVMCBMemoIndex, vm), exl = @(GetVMCBExportVar, vm) in @(Equal, Bool, @(IS_IN_MLIST, @(KLVAL, loc), exl, z), TT); def SetOpInCont = \(c : VMKCont, l : VMKLocation) ?(c1 : VMKCont, c2 : VMKCont, v : KSval) let cc = \(x : VMKState) @(CHANGE, x, l, v) in let nc = \(x : VMKState) @(c2, @(cc, @(c1, x))) in @(Equal, VMKCont, c, nc); def GetOpInCont = \(c : VMKCont, l : VMKLocation) ?(c1 : VMKCont, c2 : VMKEont, v : KSval) let cc = \(x : VMKState) @(GET, x, l) in let nc = \(x : VMKState) @(c2, @(cc, @(c1, x)), @(c1, x)) in @(Equal, VMKCont, c, nc); def TrustedFlowCond3 = \(fl : VMKFlow, z : VMKState) let s = @(GetFlowSubject, fl), r = @(GetFlowResource, fl), m = @(GetFlowMode, fl) in let c = @(GET_KCVAL, s) in let vml = @(GetResourceNam, r), loc = @(GetResourceLoc, r) in @(And1, [@(Equal, VMKAccessMode, m, VMKAccessNull) -> @(And1, @(Neg0, @(SetOpInCont, c, loc)), @(Neg0, @(GetOpInCont, c, loc)))], @(And1, [@(Equal, VMKAccessMode, m, VMKAccessRO) -> @(Neg0, @(SetOpInCont, c, loc))], [@(Equal, VMKAccessMode, m, VMKAccessWO) -> @(Neg0, @(GetOpInCont, c, loc))])); def TrustedFlow = \(fl : VMKFlow, SA : VMKFlowList, z : VMKState) @(And, @(TrustedFlowCond1, fl, SA),

228

CHAPTER 20. SECURITY POLICIES OF VMK

@(And, @(TrustedFlowCond2, fl, z), @(TrustedFlowCond3, fl, z)));

20.1.10.4

Trusted Flow Lists

def TrustFlowLstCd1 = \(fl : VMKFlowList, SA : VMKFlowList) @(Equal, Bool, @(VMKLPAListRuleList, fl, SA), TT); dec TrustFlowLstCd2 : [VMKFlowList -> VMKState -> Prop]; def TrustFlowLstCd2 = \(fl : VMKFlowList, z : VMKState) @(GIF_THEN_ELSE0, Prop, @(IS_EMPTY, VMKFlow, fl), True, let hfl = @(HEAD, VMKFlow, fl), tfl = @(TAIL, VMKFlow, fl) in @(And, @(TrustedFlowCond2, hfl, z), @(TrustFlowLstCd2, tfl, z))); dec TrustFlowLstCd3 : [VMKFlowList -> VMKState -> Prop]; def TrustFlowLstCd3 = \(fl : VMKFlowList, z : VMKState) @(GIF_THEN_ELSE0, Prop, @(IS_EMPTY, VMKFlow, fl), True, let hfl = @(HEAD, VMKFlow, fl), tfl = @(TAIL, VMKFlow, fl) in @(And, @(TrustedFlowCond3, hfl, z), @(TrustFlowLstCd3, tfl, z))); def TrustFlowListCond = \(fl : VMKFlowList, SA : VMKFlowList, z : VMKState) @(And, @(TrustFlowLstCd1, fl, SA), @(And, @(TrustFlowLstCd2, fl, z), @(TrustFlowLstCd3, fl, z)));

229

CHAPTER 20. SECURITY POLICIES OF VMK

230

20.2

Definition of Capability List in Object-Language

20.2.1

Resource Access Mode in Object-Language

def MAccessMode = Nat; dec dec dec dec

MAccessNull MAccessRO MAccessWO MAccessRW

dec dec dec dec

IsMAccessNull IsMAccessRO IsMAccessWO IsMAccessRW

20.2.2

: : : :

MAccessMode; MAccessMode; MAccessMode; MAccessMode; : : : :

[MAccessMode [MAccessMode [MAccessMode [MAccessMode

-> -> -> ->

Bool]; Bool]; Bool]; Bool];

Subject-Resource Flow (Capability) in Object-Language

def MFlow = KSval; dec MkMFlow : [Subject -> Resource -> MAccessMode -> MFlow]; dec GetMFlowSubject : [MFlow -> Subject]; dec GetMFlowResource : [MFlow -> Resource]; dec GetMFlowMode : [MFlow -> MAccessMode];

20.2.3

Capability List in Object-Language

def MFlowList = MList;

20.2.4

Rule for Capability List

def MFlowListRule = \(fl : MFlow, PA : MFlowList, z : VMKState) @(GIF_THEN_ELSE, MReturnMode, @(NOT, @(IS_IN_MLIST, fl, PA, z)), M_DENY,

CHAPTER 20. SECURITY POLICIES OF VMK

231

M_ALLOW); dec MFlowListRuleList : [MFlowList -> MFlowList -> VMKState -> Bool]; def MFlowListRuleList = \(fl : MFlowList, SA : MFlowList, z : VMKState) @(GIF_THEN_ELSE, Bool, @(IS_EMPTY_MLIST, fl), TT, let hfl = @(MHEAD, fl, z), tfl = @(MTAIL, fl, z) in let rtmode = @(MFlowListRule, hfl, SA, z) in @(GIF_THEN_ELSE, Bool, @(IS_M_ALLOW, rtmode), @(MFlowListRuleList, tfl, SA, z), FF));

20.2.5

Security Checking

20.2.5.1

Checking List

• Interrupt service routines • System service calls 20.2.5.2

Checking Well-Definedness of Flow List for Interrupt Service Routines

Definition 20.2 We say that an interrupt service routine kcv is well-defined in flow fl only if there exist subject s, resource r and mode m such that f = [s, r, m] is defined in fl, s is equal to kcv, and there exist index idx and location l such that the content of l in the segment indexed by idx is equal to r.

dec WDInFlowList : [KSval -> MFlowList -> VMKState -> Type(0)]; def WDInFlowList = \(kcv : KSval, fl : MFlowList, z : VMKState) ?(s : Subject, r : Resource, m : MAccessMode) let f = @(MkMFlow, s, r, m) in @(And, @(Equal, KSval, s, kcv), @(And, @(Equal, Bool, @(IS_IN_MLIST, f, fl, z), TT), let vml = @(GetResourceNam, r), loc = @(GetResourceLoc, r) in let vm = @(VMCB_GET, z, vml) in

CHAPTER 20. SECURITY POLICIES OF VMK

let idx = @(GetVMCBMemoIndex, vm) in @(And, @(Not, @(Equal, VMKMemoIndex, idx, VMK_MANAGER_IDX)), let nz = @(SET_VMKST_IDX, z, idx) in let v = @(GET, nz, loc) in @(Not, @(Equal, KSval, v, ERR_KSVAL))))); dec DoIntCBChk : [VMKIntCB -> MFlowList -> VMKState -> Type(0)]; def DoIntCBChk = \(intcb : VMKIntCB, fl : MFlowList, z : VMKState) let c = @(GET_VMKIntCB_CONT, intcb) in let kcv = @(KCVAL, c) in @(WDInFlowList, kcv, fl, z); dec DoIntCBListChk : [MList -> MFlowList -> VMKState -> Prop]; def DoIntCBListChk = \(intcb_list : MList, fl : MFlowList, z : @(GIF_THEN_ELSE0, Prop, @(IS_EMPTY_MLIST, intcb_list), True, let hintcb_list = @(MHEAD, intcb_list, tintcb_list = @(MTAIL, intcb_list, @(And, @(DoIntCBChk, hintcb_list, fl, z), @(DoIntCBListChk, tintcb_list, fl,

VMKState)

z), z) in

z)));

def VMKIntCBListChk = \(fl : MFlowList, z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let intcb_list = @(GET_VMKMAN_INTCBL, vmk_manager) in @(DoIntCBListChk, intcb_list, fl, z); def VMKExIntCBListChk = \(fl : MFlowList, z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let exintcb_list = @(GET_VMKMAN_EXINTL, vmk_manager) in @(DoIntCBListChk, exintcb_list, fl, z);

20.2.5.3

Trusted Flows

def TrustedFlowCond1 = \(fl : MFlow, SA : MFlowList, z : VMKState) @(Equal, MReturnMode, @(MFlowListRule, fl, SA, z), M_ALLOW); def TrustedFlowCond2 = \(fl : MFlow, z : VMKState) let s = @(GetMFlowSubject,

fl),

232

CHAPTER 20. SECURITY POLICIES OF VMK

r = @(GetMFlowResource, fl), m = @(GetMFlowMode, fl) in let c = @(GET_KCVAL, s) in let vml = @(GetResourceNam, r), loc = @(GetResourceLoc, r) in let vm = @(VMCB_GET, z, vml) in let idx = @(GetVMCBMemoIndex, vm), exl = @(GetVMCBExportVar, vm) in @(Equal, Bool, @(IS_IN_MLIST, @(KLVAL, loc), exl, z), TT); def SetOpInCont = \(c : VMKCont, l : VMKLocation) ?(c1 : VMKCont, c2 : VMKCont, v : KSval) let cc = \(x : VMKState) @(CHANGE, x, l, v) in let nc = \(x : VMKState) @(c2, @(cc, @(c1, x))) in @(Equal, VMKCont, c, nc); def GetOpInCont = \(c : VMKCont, l : VMKLocation) ?(c1 : VMKCont, c2 : VMKEont, v : KSval) let cc = \(x : VMKState) @(GET, x, l) in let nc = \(x : VMKState) @(c2, @(cc, @(c1, x)), @(c1, x)) in @(Equal, VMKCont, c, nc); def TrustedFlowCond3 = \(fl : MFlow, z : VMKState) let s = @(GetMFlowSubject, fl), r = @(GetMFlowResource, fl), m = @(GetMFlowMode, fl) in let c = @(GET_KCVAL, s) in let vml = @(GetResourceNam, r), loc = @(GetResourceLoc, r) in @(And1, [@(Equal, MAccessMode, m, MAccessNull) -> @(And1, @(Neg0, @(SetOpInCont, c, loc)), @(Neg0, @(GetOpInCont, c, loc)))], @(And1, [@(Equal, MAccessMode, m, MAccessRO) -> @(Neg0, @(SetOpInCont, c, loc))], [@(Equal, MAccessMode, m, MAccessWO) -> @(Neg0, @(GetOpInCont, c, loc))])); def TrustedFlow = \(fl : MFlow, SA : MFlowList, z : VMKState) @(And, @(TrustedFlowCond1, fl, SA, z), @(And, @(TrustedFlowCond2, fl, z), @(TrustedFlowCond3, fl, z)));

233

CHAPTER 20. SECURITY POLICIES OF VMK

20.2.5.4

Trusted Flow Lists

def TrustFlowLstCd1 = \(fl : MFlowList, SA : MFlowList, z : VMKState) @(Equal, Bool, @(MFlowListRuleList, fl, SA, z), TT); dec TrustFlowLstCd2 : [MFlowList -> VMKState -> Prop]; def TrustFlowLstCd2 = \(fl : MFlowList, z : VMKState) @(GIF_THEN_ELSE0, Prop, @(IS_EMPTY_MLIST, fl), True, let hfl = @(MHEAD, fl, z), tfl = @(MTAIL, fl, z) in @(And, @(TrustedFlowCond2, hfl, z), @(TrustFlowLstCd2, tfl, z))); dec TrustFlowLstCd3 : [MFlowList -> VMKState -> Prop]; def TrustFlowLstCd3 = \(fl : MFlowList, z : VMKState) @(GIF_THEN_ELSE0, Prop, @(IS_EMPTY_MLIST, fl), True, let hfl = @(MHEAD, fl, z), tfl = @(MTAIL, fl, z) in @(And, @(TrustedFlowCond3, hfl, z), @(TrustFlowLstCd3, tfl, z))); def TrustFlowListCond = \(fl : MFlowList, SA : MFlowList, z : VMKState) @(And, @(TrustFlowLstCd1, fl, SA, z), @(And, @(TrustFlowLstCd2, fl, z), @(TrustFlowLstCd3, fl, z)));

234

CHAPTER 20. SECURITY POLICIES OF VMK

235

20.3

Capability Checking of Interrupt Service Routines

20.3.1

Definition of Capability Checking

def VMKContCond1 = \(c : VMKCont, nz : VMKState) ?(c1 : VMKCont, c2 : VMKCont, idx : VMKMemoIndex, loc : VMKLocation, l : VMKLocation, v : KSval) @(And, @(Not, @(Equal, VMKMemoIndex, idx, VMK_MANAGER_IDX)), @(And, let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(CHANGE, nz, l, v) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z))) in @(Equal, VMKCont, c, nc), let vmcb = @(VMCB_GET, nz, loc) in let vm_index = @(GetVMCBMemoIndex, vmcb), export_list = @(GetVMCBExportVar, vmcb) in @(And, @(Equal, VMKMemoIndex, vm_index, idx), @(Equal, Bool, @(IS_IN_MLIST, @(KLVAL, l), export_list, nz), TT)))); def VMKContCond2 = \(c : VMKCont, nz : VMKState) ?(c1 : VMKCont, c2 : VMKEont, idx : VMKMemoIndex, loc : VMKLocation, l : VMKLocation) @(And, @(Not, @(Equal, VMKMemoIndex, idx, VMK_MANAGER_IDX)), @(And, let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(GET, nz, loc) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z)), @(c1, z)) in @(Equal, VMKCont, c, nc), let vmcb = @(VMCB_GET, nz, loc) in let vm_index = @(GetVMCBMemoIndex, vmcb), export_list = @(GetVMCBExportVar, vmcb) in @(And,

CHAPTER 20. SECURITY POLICIES OF VMK

@(Equal, VMKMemoIndex, vm_index, idx), @(Equal, Bool, @(IS_IN_MLIST, @(KLVAL, l), export_list, nz), TT)))); def VMKIntCBCond = \(c : VMKCont, z : VMKState) @(Or0, @(VMKContCond1, c, z), @(VMKContCond2, c, z)); dec ChkContCapability : !(c : VMKCont, z : VMKState) [@(VMKIntCBCond, c, z) -> MList -> Prop]; def ChkContCapability = \(c : VMKCont, z : VMKState, p : @(VMKIntCBCond, c, z), flow_list : MList) @(WHEN0, @(VMKContCond1, c, z), @(VMKContCond2, c, z), Prop, p, \(u : @(VMKContCond1, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)), idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(FST, @(SND, @(SND, @(SND, @(SND, u))))), v = @(FST, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))) in let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(CHANGE, nz, loc, v) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z))) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessWO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(Equal, Bool, @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z)), TT), \(u : @(VMKContCond2, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)), idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(SND, @(SND, @(SND, @(SND, @(SND, u))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, u))))) in let cc = \(z : VMKState)

236

CHAPTER 20. SECURITY POLICIES OF VMK

let nz = @(SET_VMKST_IDX, z, idx) in @(GET, nz, loc) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z)), @(c1, z)) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(Equal, Bool, @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z)), TT)); dec VMKIntCBAxm : !(z : VMKState, l : VMKLocation) let intcb = @(INTCB_GET, z, l) in let icbnumb = @(GET_VMKIntCB_NUMB, icbmask = @(GET_VMKIntCB_MASK, icbfire = @(GET_VMKIntCB_FIRE, icbcont = @(GET_VMKIntCB_CONT, @(VMKIntCBCond, icbcont, z);

intcb), intcb), intcb), intcb) in

dec DoChkIntCB : [VMKLocation -> MList -> VMKState -> Prop]; def DoChkIntCB = \(l : VMKLocation, flow_list : MList, z : VMKState) let intcb = @(INTCB_GET, z, l) in let icbnumb = @(GET_VMKIntCB_NUMB, intcb), icbmask = @(GET_VMKIntCB_MASK, intcb), icbfire = @(GET_VMKIntCB_FIRE, intcb), icbcont = @(GET_VMKIntCB_CONT, intcb) in @(ChkContCapability, icbcont, z, @(VMKIntCBAxm, z, l), flow_list); dec ChkIntCBList : [MList -> MList -> VMKState -> Prop]; def ChkIntCBList = \(int_list : MList, flow_list : MList, z : VMKState) @(GIF_THEN_ELSE0, Prop, @(IS_EMPTY_MLIST, int_list), True, let hintcb = @(MHEAD, int_list, z), tintcb = @(MTAIL, int_list, z) in @(And, @(DoChkIntCB, @(GET_KLVAL, hintcb), flow_list, z), @(ChkIntCBList, tintcb, flow_list, z))); dec ChkIntCB : [VMKState -> Prop]; def ChkIntCB = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_INTCBL, vmk_manager),

237

CHAPTER 20. SECURITY POLICIES OF VMK

238

flow_list = @(GET_VMKMAN_FLOWLT, vmk_manager) in @(ChkIntCBList, int_table, flow_list, nz); dec ChkExIntCB : [VMKState -> Prop]; def ChkExIntCB = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_EXINTL, vmk_manager), flow_list = @(GET_VMKMAN_FLOWLT, vmk_manager) in @(ChkIntCBList, int_table, flow_list, nz);

20.3.2

Functions for Capability Checking

dec CHK_CONT_CAPABILITY : !(c : VMKCont, z : VMKState) [@(VMKIntCBCond, c, z) -> MList -> Bool]; def CHK_CONT_CAPABILITY = \(c : VMKCont, z : VMKState, p : @(VMKIntCBCond, c, z), flow_list : MList) @(WHEN0, @(VMKContCond1, c, z), @(VMKContCond2, c, z), Bool, p, \(u : @(VMKContCond1, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)), idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(FST, @(SND, @(SND, @(SND, @(SND, u))))), v = @(FST, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))) in let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(CHANGE, nz, loc, v) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z))) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessWO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z)), \(u : @(VMKContCond2, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)), idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(SND, @(SND, @(SND, @(SND, @(SND, u))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, u))))) in

CHAPTER 20. SECURITY POLICIES OF VMK

let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(GET, nz, loc) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z)), @(c1, z)) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z))); dec DO_CHK_INTCB : [VMKLocation -> MList -> VMKState -> Bool]; def DO_CHK_INTCB = \(l : VMKLocation, flow_list : MList, z : VMKState) let intcb = @(INTCB_GET, z, l) in let icbnumb = @(GET_VMKIntCB_NUMB, intcb), icbmask = @(GET_VMKIntCB_MASK, intcb), icbfire = @(GET_VMKIntCB_FIRE, intcb), icbcont = @(GET_VMKIntCB_CONT, intcb) in @(CHK_CONT_CAPABILITY, icbcont, z, @(VMKIntCBAxm, z, l), flow_list); dec CHK_INTCB_LIST : [MList -> MList -> VMKState -> Bool]; def CHK_INTCB_LIST = \(int_list : MList, flow_list : MList, z : VMKState) @(GIF_THEN_ELSE, Bool, @(IS_EMPTY_MLIST, int_list), TT, let hintcb = @(MHEAD, int_list, z), tintcb = @(MTAIL, int_list, z) in @(AND, @(DO_CHK_INTCB, @(GET_KLVAL, hintcb), flow_list, z), @(CHK_INTCB_LIST, tintcb, flow_list, z))); dec CHK_INTCB : [VMKState -> Bool]; def CHK_INTCB = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_INTCBL, vmk_manager), flow_list = @(GET_VMKMAN_FLOWLT, vmk_manager) in @(CHK_INTCB_LIST, int_table, flow_list, nz); dec CHK_EXINTCB : [VMKState -> Bool]; def CHK_EXINTCB = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_EXINTL, vmk_manager), flow_list = @(GET_VMKMAN_FLOWLT, vmk_manager) in

239

CHAPTER 20. SECURITY POLICIES OF VMK

240

@(CHK_INTCB_LIST, int_table, flow_list, nz);

20.4

Soundness and Completeness of Capability Checking

20.4.1

Soundness Theorem of Capability Checking for ISRs

Theorem 20.1 For any state z, if the function CHK INTCB is evaluated to truth on z, then the interrupt service routines of z are well-checked for capability.

dec SDIntCBFlowThm : !(z : VMKState) [@(Equal, Bool, @(CHK_INTCB, z), TT) -> @(ChkIntCB, z)];

20.4.2

Completeness Theorem of Capability Checking for ISRs

Theorem 20.2 For any state z, if all of the interrupt service routines of z are well-checked for capability, then the function CHK INTCB is evaluated to truth on z. dec CPIntCBFlowThm : !(z : VMKState) [@(ChkIntCB, z) -> @(Equal, Bool, @(CHK_INTCB, z), TT)];

20.4.3

The Proof of CPIntCBFlowThm

20.4.3.1 Lemmas CPIntCBFListLem To prove CPIntCBFlowThm, we need to prove the following lemma: CPIntCBFListLem. dec CPIntCBFListLem : !(z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_INTCBL, vmk_manager), flow_list = @(GET_VMKMAN_FLOWLT, vmk_manager) in [@(ChkIntCBList, int_table, flow_list, z) -> @(Equal, Bool, @(CHK_INTCB_LIST, int_table, flow_list, z), TT)];

CHAPTER 20. SECURITY POLICIES OF VMK

20.4.3.2

The Induction Rule on MList

dec MListRec : !(z : VMKState) !(P : [MList -> Prop]) [@(P, MNIL) -> !(l : MList) [@(Not, @(Equal, MList, l, MNIL)) -> let hl = @(MHEAD, l, z), tl = @(MTAIL, l, z) in [@(P, tl) -> @(P, l)]] -> !(n : MList) @(P, n)];

20.4.3.3

Conditional Proposition Selection Lemmas

dec PCondSelectLem1 : !(l : MList, P1 : [MList -> Prop], P2 : [MList -> Prop]) [@(GIF_THEN_ELSE0, Prop, @(IS_EMPTY_MLIST, l), @(P1, l), @(P2, l)) -> @(Equal, MList, l, MNIL) -> @(P1, l)]; dec PCondSelectLem2 : !(l : MList, P1 : [MList -> Prop], P2 : [MList -> Prop]) [@(GIF_THEN_ELSE0, Prop, @(IS_EMPTY_MLIST, l), @(P1, l), @(P2, l)) -> @(Not, @(Equal, MList, l, MNIL)) -> @(P2, l)];

20.4.3.4

Lemma CondP2FTranLem1 and Proof

dec CondP2FTranLem1 : !(z : VMKState, flow_list : MList) let P = \(l : MList) [@(ChkIntCBList, l, flow_list, z) -> @(Equal, Bool, @(CHK_INTCB_LIST, l, flow_list, z), TT)] in @(P, MNIL); dec CondT2TTranLem : !(z : VMKState, flow_list : MList) [@(GIF_THEN_ELSE0,

241

CHAPTER 20. SECURITY POLICIES OF VMK

Prop, @(IS_EMPTY_MLIST, MNIL), True, let hintcb = @(MHEAD, MNIL, z), tintcb = @(MTAIL, MNIL, z) in @(And, @(DoChkIntCB, @(GET_KLVAL, hintcb), flow_list, z), @(ChkIntCBList, tintcb, flow_list, z))) -> let f = @(GIF_THEN_ELSE, Bool, @(IS_EMPTY_MLIST, MNIL), TT, let hintcb = @(MHEAD, MNIL, z), tintcb = @(MTAIL, MNIL, z) in @(AND, @(DO_CHK_INTCB, @(GET_KLVAL, hintcb), flow_list, z), @(CHK_INTCB_LIST, tintcb, flow_list, z))) in @(Equal, Bool, f, TT)]; def CondP2FTranLem1 = \(z : VMKState, flow_list : MList) let P = \(l : MList) [@(ChkIntCBList, l, flow_list, z) -> @(Equal, Bool, @(CHK_INTCB_LIST, l, flow_list, z), TT)] in \(p : @(ChkIntCBList, MNIL, flow_list, z)) @(CondT2TTranLem, z, flow_list, p);

20.4.3.5

Lemma CondP2FTranLem2 and Proof

dec CondP2FTranLem2 : !(z : VMKState, flow_list : MList) let P = \(l : MList) [@(ChkIntCBList, l, flow_list, z) -> @(Equal, Bool, @(CHK_INTCB_LIST, l, flow_list, z), TT)] in !(l : MList) [@(Not, @(Equal, MList, l, MNIL)) -> let hl = @(MHEAD, l, z), tl = @(MTAIL, l, z) in [@(P, tl) -> @(P, l)]]; dec Or2ORTranLem : !(c : VMKCont, z : VMKState, p : @(VMKIntCBCond, c, z), flow_list : MList) [@(WHEN0, @(VMKContCond1, c, z), @(VMKContCond2, c, z), Prop, p, \(u : @(VMKContCond1, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)),

242

CHAPTER 20. SECURITY POLICIES OF VMK

idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(FST, @(SND, @(SND, @(SND, @(SND, u))))), v = @(FST, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))) in let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(CHANGE, nz, loc, v) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z))) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessWO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(Equal, Bool, @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z)), TT), \(u : @(VMKContCond2, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)), idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(SND, @(SND, @(SND, @(SND, @(SND, u))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, u))))) in let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(GET, nz, loc) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z)), @(c1, z)) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(Equal, Bool, @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z)), TT)) -> let F = @(WHEN0, @(VMKContCond1, c, z), @(VMKContCond2, c, z), Bool, p, \(u : @(VMKContCond1, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)), idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(FST, @(SND, @(SND, @(SND, @(SND, u))))), v = @(FST, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, @(SND, u)))))) in let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(CHANGE, nz, loc, v) in

243

CHAPTER 20. SECURITY POLICIES OF VMK

let nc = \(z : VMKState) @(c2, @(cc, @(c1, z))) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessWO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z)), \(u : @(VMKContCond2, c, z)) let c1 = @(FST, u), c2 = @(FST, @(SND, u)), idx = @(FST, @(SND, @(SND, u))), loc = @(FST, @(SND, @(SND, @(SND, u)))), l = @(SND, @(SND, @(SND, @(SND, @(SND, u))))), p = @(SND, @(SND, @(SND, @(SND, @(SND, u))))) in let cc = \(z : VMKState) let nz = @(SET_VMKST_IDX, z, idx) in @(GET, nz, loc) in let nc = \(z : VMKState) @(c2, @(cc, @(c1, z)), @(c1, z)) in let f1 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRO), f2 = @(MkMFlow, @(KCVAL, nc), @(KLVAL, loc), MAccessRW) in @(OR, @(IS_IN_MLIST, f1, flow_list, z), @(IS_IN_MLIST, f2, flow_list, z))) in @(Equal, Bool, F, TT)]; dec ChkContCapLem : !(c : VMKCont, z : VMKState) !(p : @(VMKIntCBCond, c, z), flow_list : MList) [@(ChkContCapability, c, z, p, flow_list) -> @(Equal, Bool, @(CHK_CONT_CAPABILITY, c, z, p, flow_list), TT)]; def ChkContCapLem = \(c : VMKCont, z : VMKState) \(p : @(VMKIntCBCond, c, z), flow_list : MList) \(q : @(ChkContCapability, c, z, p, flow_list)) @(Or2ORTranLem, c, z, p, flow_list, q); dec DoChkIntCBLem : !(l : VMKLocation, flow_list : MList, z : VMKState) [@(DoChkIntCB, l, flow_list, z) -> @(Equal, Bool, @(DO_CHK_INTCB, l, flow_list, z), TT)]; def DoChkIntCBLem = \(l : VMKLocation, flow_list : MList, z : VMKState) \(p : @(DoChkIntCB, l, flow_list, z)) let intcb = @(INTCB_GET, z, l) in let icbnumb = @(GET_VMKIntCB_NUMB, intcb), icbmask = @(GET_VMKIntCB_MASK, intcb), icbfire = @(GET_VMKIntCB_FIRE, intcb), icbcont = @(GET_VMKIntCB_CONT, intcb) in @(ChkContCapLem, icbcont, z, @(VMKIntCBAxm, z, l), flow_list, p); dec CondMergeLem :

244

CHAPTER 20. SECURITY POLICIES OF VMK

!(l : MList, flow_list : MList, z : VMKState) let hl = @(MHEAD, l, z), tl = @(MTAIL, l, z) in [@(Equal, Bool, @(DO_CHK_INTCB, @(GET_KLVAL, hl), flow_list, z), TT) -> @(Equal, Bool, @(CHK_INTCB_LIST, tl, flow_list, z), TT) -> let f = @(GIF_THEN_ELSE, Bool, @(IS_EMPTY_MLIST, l), TT, @(AND, @(DO_CHK_INTCB, @(GET_KLVAL, hl), flow_list, z), @(CHK_INTCB_LIST, tl, flow_list, z))) in @(Equal, Bool, f, TT)]; def CondP2FTranLem2 = \(z : VMKState, flow_list : MList) let P = \(l : MList) [@(ChkIntCBList, l, flow_list, z) -> @(Equal, Bool, @(CHK_INTCB_LIST, l, flow_list, z), TT)] in \(l : MList) \(w : @(Not, @(Equal, MList, l, MNIL))) let hl = @(MHEAD, l, z), tl = @(MTAIL, l, z) in \(p : @(P, tl)) \(q : @(ChkIntCBList, l, flow_list, z)) let P1 = \(l : MList) True, P2 = \(int_list : MList) let hintcb = @(MHEAD, int_list, z), tintcb = @(MTAIL, int_list, z) in @(And, @(DoChkIntCB, @(GET_KLVAL, hintcb), flow_list, z), @(ChkIntCBList, tintcb, flow_list, z)) in let p2 = @(PCondSelectLem2, l, P1, P2, q, w) in let Q1 = @(DoChkIntCB, @(GET_KLVAL, hl), flow_list, z), Q2 = @(ChkIntCBList, tl, flow_list, z) in let q1 = @(PJ1, Q1, Q2, p2), q2 = @(PJ2, Q1, Q2, p2) in let u1 = @(DoChkIntCBLem, @(GET_KLVAL, hl), flow_list, z, q1), u2 = @(p, q2) in @(CondMergeLem, l, flow_list, z, u1, u2);

20.4.3.6

The Proof of CondP2FTranLem

def CondP2FTranLem = \(z : VMKState, flow_list : MList) let P = \(l : MList) [@(ChkIntCBList, l, flow_list, z) -> @(Equal, Bool, @(CHK_INTCB_LIST, l, flow_list, z), TT)] in @(MListRec, z,

245

CHAPTER 20. SECURITY POLICIES OF VMK

P, @(CondP2FTranLem1, z, flow_list), @(CondP2FTranLem2, z, flow_list));

20.4.3.7

The Proof of CPIntCBFListLem

def CPIntCBFListLem = \(z : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let int_table = @(GET_VMKMAN_INTCBL, vmk_manager), flow_list = @(GET_VMKMAN_FLOWLT, vmk_manager) in @(CondP2FTranLem, z, flow_list, int_table);

20.4.3.8

The Proof of CPIntCBFlowThm

def CPIntCBFlowThm = \(z : VMKState, p : @(ChkIntCB, z)) @(CPIntCBFListLem, z, p);

246

Chapter 21

The Verification of VMK System Service APIs 21.1

The Verification of VMK SCHEDULE

21.1.1

Requirement Specification of Scheduling

21.1.1.1

The Requirement Specification

Normally a requirement specification is given in the following form: ∀(x : T1)∃(y : T2)@(R, x, y) where R is a relation defined on T1 and T2 to specify the input and output relationship in between x and y. def VMKScheduleCond = \(z : VMKState, nz : VMKState) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let tts_vm_loc = @(GET_VMKMAN_TTSVM, vmk_manager), prq_vm_loc = @(GET_VMKMAN_PQUEVM, vmk_manager) in let tts_vm = @(VMCB_GET, z, tts_vm_loc), prq_vm = @(VMCB_GET, z, prq_vm_loc) in let new_vm_loc = @(GIF_THEN_ELSE, VMKLocation, @(EQ_VMKLOC, tts_vm_loc, NIL_VMKLOC), prq_vm_loc, tts_vm_loc) in @(Or, [@(Equal, Bool, @(NOT, @(EQ_VMKLOC, new_vm_loc, old_vm_loc)), TT) -> let old_vm = @(VMCB_GET, z, old_vm_loc), new_vm = @(VMCB_GET, z, new_vm_loc) in let nvmk_manager = @(SET_VMKMAN_RUNVM, vmk_manager, new_vm_loc) in

247

CHAPTER 21. THE VERIFICATION OF VMK SYSTEM SERVICE APIS248

let nold_vm = @(SetVMCBLeaveTick, old_vm, OO) in let z0 = @(GIF_THEN_ELSE, VMKState, @(IS_VMFIRSTRUN, @(GetVMCBStatus, new_vm)), @(SetVMVTickInt, new_vm_loc, @(GET_VMKMAN_TICKCN, nvmk_manager), z), z), z1 = @(CHANGE, z0, VMK_MANAGER_LOC, nvmk_manager), z2 = @(VMCB_SET, z1, old_vm_loc, nold_vm) in @(Equal, VMKState, z2, nz)], [@(Equal, Bool, @(NOT, @(EQ_VMKLOC, new_vm_loc, old_vm_loc)), FF) -> @(Equal, VMKState, z, nz)]);

Theorem 21.1 For any state z there exists state nz such that @(VMKScheduleCond, z, nz). dec VMKScheduleSpec : !(z : VMKState) ?(nz : VMKState) @(VMKScheduleCond, z, nz);

21.1.1.2

Intentional Specification

Alternatively a functional requirement specification is given in the following form: ∃(f : [T1−> T2])∀(x : T1)@(R, x, @(f, x)) where R is a relation defined on T1 and T2 to specify the input and output relationship in between x and @(f, x). For the intentional specification, we mean that the relation R is built on the state transition from x and @(f, x) and the equality on x and @(f, x). def VMKScheduleCond1 = \(z : VMKState, f : VMKCont) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let nz = @(f, z) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), tts_vm_loc = @(GET_VMKMAN_TTSVM, vmk_manager), prq_vm_loc = @(GET_VMKMAN_PQUEVM, vmk_manager) in let tts_vm = @(VMCB_GET, z, tts_vm_loc), prq_vm = @(VMCB_GET, z, prq_vm_loc) in let new_vm_loc = @(GIF_THEN_ELSE, VMKLocation, @(EQ_VMKLOC, tts_vm_loc, NIL_VMKLOC), prq_vm_loc, tts_vm_loc) in @(Or, [@(Equal, Bool, @(NOT, @(EQ_VMKLOC, new_vm_loc, old_vm_loc)), TT) -> let old_vm = @(VMCB_GET, z, old_vm_loc),

CHAPTER 21. THE VERIFICATION OF VMK SYSTEM SERVICE APIS249

new_vm = @(VMCB_GET, z, new_vm_loc) in let nvmk_manager = @(SET_VMKMAN_RUNVM, vmk_manager, new_vm_loc) in let nold_vm = @(SetVMCBLeaveTick, old_vm, OO) in let z0 = @(GIF_THEN_ELSE, VMKState, @(IS_VMFIRSTRUN, @(GetVMCBStatus, new_vm)), @(SetVMVTickInt, new_vm_loc, @(GET_VMKMAN_TICKCN, nvmk_manager), z), z), z1 = @(CHANGE, z0, VMK_MANAGER_LOC, nvmk_manager), z2 = @(VMCB_SET, z1, old_vm_loc, nold_vm) in @(Equal, VMKState, z2, nz)], [@(Equal, Bool, @(NOT, @(EQ_VMKLOC, new_vm_loc, old_vm_loc)), FF) -> @(Equal, VMKState, z, nz)]);

Theorem 21.2 There exists function f such that for any state z @(VMKScheduleCond1, z, @(f, z)). dec VMKScheduleSpec1 : ?(f : VMKCont) !(z : VMKState) @(VMKScheduleCond1, z, f);

21.1.1.3

Extensional Specification

def VMKScheduleCond2 = \(z : VMKState, f : VMKCont) let vmk_manager = @(GET, z, VMK_MANAGER_LOC) in let nz = @(f, z) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager), tts_vm_loc = @(GET_VMKMAN_TTSVM, vmk_manager), prq_vm_loc = @(GET_VMKMAN_PQUEVM, vmk_manager) in let tts_vm = @(VMCB_GET, z, tts_vm_loc), prq_vm = @(VMCB_GET, z, prq_vm_loc) in let new_vm_loc = @(GIF_THEN_ELSE, VMKLocation, @(EQ_VMKLOC, tts_vm_loc, NIL_VMKLOC), prq_vm_loc, tts_vm_loc) in [@(Equal, Bool, @(NOT, @(EQ_VMKLOC, new_vm_loc, old_vm_loc)), TT) -> let old_vm = @(VMCB_GET, z, old_vm_loc), new_vm = @(VMCB_GET, z, new_vm_loc) in let nvmk_manager = @(GET, nz, VMK_MANAGER_LOC) in @(And, @(Equal, VMKLocation, @(GET_VMKMAN_RUNVM, vmk_manager), new_vm_loc), let nold_vm = @(VMCB_GET, nz, old_vm_loc), nnew_vm = @(VMCB_GET, nz, new_vm_loc) in @(And,

CHAPTER 21. THE VERIFICATION OF VMK SYSTEM SERVICE APIS250

@(Equal, Nat, @(GetVMCBLeaveTick, nold_vm), OO), @(Or, [@(Equal, Bool, @(IS_VMFIRSTRUN, @(GetVMCBStatus, new_vm)), TT) -> @(And, @(Equal, Nat, @(GetVMVTickInt, new_vm_loc, nz), @(GET_VMKMAN_TICKCN, nvmk_manager)), @(And, @(Equal, KSval, @(GET, nz, VMK_MANAGER_LOC), nvmk_manager), @(Equal, KSval, @(VMCB_GET, nz, old_vm_loc), nold_vm)))], [@(Equal, Bool, @(IS_VMFIRSTRUN, @(GetVMCBStatus, new_vm)), FF) -> @(And, @(Equal, KSval, @(GET, nz, VMK_MANAGER_LOC), nvmk_manager), @(Equal, KSval, @(VMCB_GET, nz, old_vm_loc), nold_vm))])))];

Theorem 21.3 There exists function f such that for any state z @(VMKScheduleCond2, z, @(f, z)). dec VMKScheduleSpec2 : ?(f : VMKCont) !(z : VMKState) @(VMKScheduleCond2, z, f);

21.1.2

The Verification

21.1.2.1

Rewriting Rule from Computational Statements to Predicate Statements The rewriting rule establishes the transformational relationship in between the computational if-then-else statements and the predicative ∨-statements. dec IfCond2OrRule : !(T : Prop, b : [T -> Bool], cond1 let f = \(z : T) @(GIF_THEN_ELSE, [@(Equal, T, @(f, z), nz) -> @(Or, [@(Equal, Bool, @(b, z), TT) [@(Equal, Bool, @(b, z), FF)

: [T -> T], cond2 : [T -> T], z : T, nz : T) T, @(b, z), @(cond1, z), @(cond2, z)) in

-> @(Equal, T, @(cond1, z), nz)], -> @(Equal, T, @(cond2, z), nz)])];

21.1.2.2 The Proof of VMKScheduleThm1 Let VMKScheduleSpec1 as VMKScheduleThm1. We want to prove the theorem VMKScheduleThm1. def VMKScheduleThm1 = VMKScheduleSpec1;

CHAPTER 21. THE VERIFICATION OF VMK SYSTEM SERVICE APIS251

To prove VMKScheduleThm1, we then need a auxiliary construction function MkVMKSchedCond1 and a lemma VMKScheduleLem1. def MkVMKSchedCond1 = \(f : VMKCont, p : !(z : VMKState) @(VMKScheduleCond1, z, f)) ; dec VMKScheduleLem1 : let f = VMK_SCHEDULE in !(z : VMKState) @(VMKScheduleCond1, z, f);

The proof of lemma VMKScheduleLem1 is derived using the rewriting rule IfCond2OrRule. def VMKScheduleLem1 = let f = VMK_SCHEDULE in \(z : VMKState) let b = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let tts_vm_loc = @(GET_VMKMAN_TTSVM, vmk_manager), prq_vm_loc = @(GET_VMKMAN_PQUEVM, vmk_manager) in let tts_vm = @(VMCB_GET, nz, tts_vm_loc), prq_vm = @(VMCB_GET, nz, prq_vm_loc) in let new_vm_loc = @(GIF_THEN_ELSE, VMKLocation, @(EQ_VMKLOC, tts_vm_loc, NIL_VMKLOC), prq_vm_loc, tts_vm_loc) in @(NOT, @(EQ_VMKLOC, new_vm_loc, old_vm_loc)), cond1 = \(nz : VMKState) let vmk_manager = @(GET, nz, VMK_MANAGER_LOC) in let old_vm_loc = @(GET_VMKMAN_RUNVM, vmk_manager) in let tts_vm_loc = @(GET_VMKMAN_TTSVM, vmk_manager), prq_vm_loc = @(GET_VMKMAN_PQUEVM, vmk_manager) in let tts_vm = @(VMCB_GET, nz, tts_vm_loc), prq_vm = @(VMCB_GET, nz, prq_vm_loc) in let new_vm_loc = @(GIF_THEN_ELSE, VMKLocation, @(EQ_VMKLOC, tts_vm_loc, NIL_VMKLOC), prq_vm_loc, tts_vm_loc) in let old_vm = @(VMCB_GET, nz, old_vm_loc), new_vm = @(VMCB_GET, nz, new_vm_loc) in let nvmk_manager = @(SET_VMKMAN_RUNVM, vmk_manager, new_vm_loc) in let nold_vm = @(SetVMCBLeaveTick, old_vm, OO) in let z0 = @(GIF_THEN_ELSE, VMKState, @(IS_VMFIRSTRUN, @(GetVMCBStatus, new_vm)), @(SetVMVTickInt, new_vm_loc,

CHAPTER 21. THE VERIFICATION OF VMK SYSTEM SERVICE APIS252

@(GET_VMKMAN_TICKCN, nvmk_manager), nz), nz), z1 = @(CHANGE, z0, VMK_MANAGER_LOC, nvmk_manager), z2 = @(VMCB_SET, z1, old_vm_loc, nold_vm) in z2, cond2 = \(nz : VMKState) nz in @(IfCond2OrRule, VMKState, b, cond1, cond2, z, @(f, z), @(Refl_Eq, VMKState, @(f, z)));

The proof of VMKScheduleThm1 is given in terms of VMKScheduleLem1 as follows: def VMKScheduleThm1 = \(z : VMKState) let f = VMK_SCHEDULE, p = @(VMKScheduleLem1, z) in @(MkVMKSchedCond1, z, f, p);

21.1.2.3 The Proof of VMKScheduleThm Similarly we can prove the theorem VMKScheduleThm. def VMKScheduleThm = VMKScheduleSpec; def MkVMKScheduleCond = \(z : VMKState, nz : VMKState, p : @(VMKScheduleCond, z, nz)) ; dec VMKScheduleLem : !(z : VMKState) let nz = @(VMK_SCHEDULE, z) in @(VMKScheduleCond, z, nz); def VMKScheduleLem = \(z : VMKState) let nz = @(VMK_SCHEDULE, z) in @(VMKScheduleLem1, z); def VMKScheduleThm = \(z : VMKState) let nz = @(VMK_SCHEDULE, z), np = @(VMKScheduleLem, z) in @(MkVMKScheduleCond, z, nz, np);

CHAPTER 21. THE VERIFICATION OF VMK SYSTEM SERVICE APIS253

21.1.2.4

Proof of VMKScheduleThm1 Deriving from of VMKScheduleThm

As we have stated in [ZD94], We can apply the axiom of choice to the VMKScheduleThm to obtain the proof of VMKScheduleThm1; indeed given this axiom the two specifications are logically equivalent. The axiom of choice is the statement: dec Choice_Axm : !(A : Prop, B : Prop, P : [A -> B -> Prop]) [!(x : A) ?(y : B) @(P, x, y) -> ?(f : [A -> B]) !(x : A) @(P, x, @(f, x))];

It is not hard to show that is type is inhabited. def Choice_Axm = \(A : Prop, B : Prop) \(P : [A -> B -> Prop]) \(l : !(x : A) ?(y : B) @(P, x, y)) let f = \(x : A) @(FST, @(l, x)), p = \(x : A, g : @(P, x, @(f, x))) g, q = \(x : A) @(p, x, @(SND, @(l, x))) in ;

We can obtain a proof by proving the axiom of choice in the following form. def VMKScheduleThm1 = @(Choice_Axm, VMKState, VMKState, VMKScheduleCond, VMKScheduleThm);

In Zermelo-Fraenkel axiomatic set theory, there is no proof of the axiom of choice, so it must be taken as axiom. In constructive type theory, however, a detailed justification of the axiom of choice in form given above can be provided. 21.1.2.5 The Proof of VMKScheduleThm2 Let VMKScheduleSpec2 as VMKScheduleThm2. The proof of VMKScheduleThm2 will be a little bit difficult. We will not give the proof in this report. def VMKScheduleThm2 = VMKScheduleSpec2;

Part III

Epilogue

254

Chapter 22

Related Works In [Kle08, Kle09, TKH05] Gerwin Klein has made a deep survey on current activities and status of formal verification for operating systems. The Table 22.1 is a list of the operating system verification projects in the past several decades. The Table 22.1 gives a condensed overview of the projects surveyed. The first two columns after the name of the project contain the highest and lowest levels of verification artifacts the project considers. They usually correspond to the terms Specification and Model of the verification. The next two columns detail what percentage of the specification artifacts in the project have been completed, and how much of the proofs are estimated to be discharged. The sixth column gives the main theorem proving tool used. The penultimate column contains one or two key phrases indicating the approach used, and the last column indicates when the project took place. Years in parentheses are estimated completion dates. • The first three projects in The Table 22.1, UCLA Secure Unix, PSOS, and KIT, concern early work in the 1970s and 1980s. While they pioneered the field and all finished successfully in their way, none of them produced a realistic OS kernel with full implementation proofs. • The next two projects in the table are recent, smaller-scale efforts that have made significant contributions. The first one, VFiasco, is a project at TU Dresden, Germany, and RU Nijmegen in the Netherlands. The second project, the verification of the Coyotos kernel, has unfortunately been cut short. • The last two projects are larger-scale efforts and have made substantial progress towards the goal of a realistic, fully verified OS kernel. At the time of writing, they are expected to complete their proofs in 2008. They differ in approach and main focus, but they also share a large portion of their verification technology. 255

CHAPTER 22. RELATED WORKS

Project

Highest Level

UCLA Security Unix PSOS

Security Model Application Level Isolated Tasks Does Not Crash Security Model Application Level Security Model

KIT VFiasco/ Rodin EROS/ Coyotos Verisoft L4.verified

256

Lowest Level

Specs

Proofs

Prover

Approach

Year

Pascal

90%

20%

XIVUS

Alphard

(?)-1980

Source Code Assembly

17 Layer 100%

0%

SPECIAL

HDM

1973-1983

100%

C++

70%

0%

BoyerMoore PVS

BitC

Security Model 100%

0%

ACL2(?)

75%

Isabelle

100%

70%

Isabelle

Interpreter Equivalence Semantic Compiler Language Based Fully Pervasive Performance Production Code

Gate Level C/ Assembly

(?)-1987 2001-2008 2004-(?) 2004(2008) 2005(2008)

Table 22.1: OS Verification Projects

The table does not include any currently commercially available OS kernels, because none have been formally verified to the degree discussed here. Three popular ones, Trusted Solaris, Windows NT, and SELinux (Red Hat Enterprise Linux 4.1) have been certified to Common Criteria EAL 4, but this level does not require any formal modeling and is not designed for systems deployed in potentially hostile situations. However, the security policies of SELinux have undergone formal analysis[ALP03]; in one instance using TAME[Arc06, Arc00, AHR00], which is based on the PVS prover[ORR+ 96], and in another instance by a different group using model checking[GHRS05]. The security framework is based on the Flask architecture[SSL+ 99] which was originally developed on the Fluke microkernel[FHL+ 96] and later ported by the NSA to Linux as the security architecture in SELinux. The two projects analyzed the security policies themselves, but did not aim at proofs establishing that the the SELinux kernel correctly implements them. Green Hill’s Integrity OS kernel has completed the EAL 6+ certification in November of 2008. EAL 6 does involve formal modeling, but only semi-formal treatment of the high-level design and below. Not much is publicly available about the certification effort at this time, but the + in EAL 6+ may mean that a formal information flow analysis on the C source code level being conducted. The theorem prover they were using is ACL2. Of the projects in Table 22.1, only the seL4 kernel[DEK+ 06] analyzed in L4.verified is targeted at the commercial market.

22.1

KIT

KIT is a small operating system kernel written for a uni-processor computer with a simple von Neumann architecture[Bev87]. KIT stands for kernel for isolated tasks, which is the main service that KIT provides. In addition, KIT provides access to asynchronous I/O devices, exception handling, and single-

CHAPTER 22. RELATED WORKS

257

word message passing. It does not provide shared memory or virtual memory in the modern sense. It also does not offer the dynamic creation of processes or communication channels, or services such as file systems. The implementation language is an artificial, but realistic assembler instruction set. With 620 lines of assembler source code and 300 lines of actual assembler instructions the kernel is extremely small and purposely very simple. It is several orders of magnitude smaller and less complex than modern microkernels. KIT is significant because it is the first kernel that fully deserves the attribute formally verified. Despite its simplicity, it provides a useful service, formally verified down to realistic assembly source code. Bevier is the first to demonstrate conclusively that the level of detail required in OS implementation verification is not an intrinsic problem for formal verification. The verification was conducted in the Boyer-Moore theorem prover[BM88], the predecessor of the ACL2 prover that was also used in the verification of the AAMP7 microprocessor. The syntax of the prover has been criticized as hard to read because of its parenthesized prefix form that is derived from the programming language LISP. In fact, the Boyer-Moore logic itself is very similar to pure LISP. The logic provides no explicit quantifiers like ∀ and ∃. One of the prover’s major advantages is that the logic is efficiently executable. The prover provides a high degree of automation for an interactive system. Very similar to UCLA Secure Unix and other refinement-based verifications, the proof of the KIT system shows correspondence between finite state machines. In this case, there are three such finite state machines: the abstract, operational specification, the ‘abstract kernel’, and the kernel running on hardware. • The kernel running on hardware is realized as an operational semantics of the assembler instructions: The states of the state machine are the hardware machine states, including its memory, registers, flags and program counter; the transitions describe the fetch-execute cycle of the machine. The restrictions of the Boyer-Moore logic make it necessary to reformulate it slightly to avoid an existential quantifier, but the content of the statement remains the same. • The medium level specification, i.e. the abstract kernel, defines a scheduling algorithm for a fixed number of tasks, implements the communication primitives (including the delay of tasks which block on a communication), and handles communication with asynchronous devices. • The abstract, top-level specification defines the communication transitions in which a task may engage, but says nothing about how tasks are scheduled. This abstract specification effectively provides a model of several communicating tasks running concurrently. The correspondence proof shows that the kernel correctly implements this abstraction on a single CPU.

CHAPTER 22. RELATED WORKS

258

There is no specific security model that KIT implements, but the top-level specification seems strong enough to at least imply data separation between processes. Bevier and Smith later also produced a formalization of the Mach microkernel[BS93a], [BS93b]. They did not proceed to implementations proofs, though. After KIT, more than a decade passed without any larger-scale, serious attempts at formally verifying the implementation of an operating system. UCLA Secure Unix, PSOS and KIT had shown that it was possible in principle, and had pioneered some of the techniques that could be employed, but the systems that were implemented were either unrealistically small like KIT, or were slow and/or incompletely verified like PSOS and UCLA Secure Unix. Formal verification on the required scale seemed prohibitively expensive, and machine support not yet sufficiently advanced.

22.2

Formal Models of Operating System Kernels in Z and Object-Z

In [Cra06, Cra07], Craig has made a effort on formal modeling of operating system kernels in Z and Object-Z. In his first book[Cra06], The formal models of three operating systems have been presented. All three kernels are intended for use on uni-processor systems.

22.2.1

A Simple Kernel

The first model is of a simple kernel of the kind often encountered in real-time and embedded systems. The system has no kernel interface and does not include such things as ISRs and device drivers. The user of this kernel is expected to provide these components on a per-application basis. This is common for such systems because the devices to which they are connected are not specified and are expected to vary among applications. The first kernel can be viewed as a kind of existence proof. It shows that it is possible to produce a formal model of an operating system kernel.

22.2.2

A Swapping Kernel

The second kernel is for a general-purpose system. The model includes a number of device drivers, in particular a clock process that is central to the processswapping mechanism. The kernel uses semaphores for synchronization and as the basic inter-process communication mechanism (here, shared memory). The kernel uses a time-based mechanism for multiplexing main store between processes; the kernel supports more processes than can be simultaneously maintained in main store. A storage-management subsystem is also provided to manage main store. It does so in a fairly rudimentary fashion, based upon

CHAPTER 22. RELATED WORKS

259

the allocation of relatively large chunks of store for each process. The framework contains the proofs of many kernel properties, and includes a proof of the correctness of the model for semaphores. The second kernel is of approximately the complexity of kernels such as those built by Digital Equipment for the excellent operating systems running its PDP11 series of minicomputers in the 1970s. It is of approximately the complexity of the kernel of Tannenbaum’s Minix [30] system (minus signals, file system and terminal interface).

22.2.3

Messages Passing in the Swapping Kernel

The third kernel is not presented in its entirety. It is a variation on the second one. The two differ in that the third uses message passing for IPC. The messagepassing primitives are modeled, as is a generic ISR based on the use of messages for the unblocking of drivers. All communication and synchronization in this kernel is based upon synchronous message exchange. The various device drivers and the process-swapping subsystem are outlined as message-passing processes. A kernel interface is also outlined. The interface implements system calls as messages and a library of system calls is presented. The chapter contains a number of proofs of properties of the message-passing mechanisms and also contains a proof that only one process can be in the kernel at any one time.

22.2.4

Virtual Storage

The final exercise is in the modeling of virtual storage. This was included because many systems today use virtual store for system and user processes. There are issues in the construction of virtual storage systems that are not covered in detail in standard textbooks (they must be confronted without much support from the literature). In a sense, it is necessary to have virtual store in order to construct it. Virtual storage affords a number of benefits including automatic storage management at the page level, management of large address spaces and support for more processes than will simultaneously fit into main store without having to resort to the all-or-nothing techniques exemplified by the swapping mechanisms in the previous kernels. Message passing is also assisted by virtual storage, as is device-independent I/O.

22.2.5

A Separation Kernel

In Craig’s second book[Cra07], the specification and refinement of a Separation Kernel is presented. This is a type of kernel that was specifically designed for cryptographic and other secure applications.

Chapter 23

Conclusions 23.1

Summary

This work is our first step on the project for formal development of operating system kernel VMK in CoreTek Systems. The functional specification of VMK is presented in formal language PowerEpsilon. Three properties have been verified: • The separation kernel property. • The security policy (information flow checking or capability checking). • The correctness of semantic definitions of system service APIs against its formal specifications.

23.2

Future Works

A characteristic problem of operating-system software is that hardware components become visible and the program functionality cannot be expressed in the pure semantics of a high-level language like C. Usually, this functionality is implemented in assembly and encapsulated in a small number of C functions, or primitives. Thus, only a small part of low-level code is indeed implemented in assembly while larger code portions are written in C and just use these primitives. From a model-theoretic point of view, such primitives extend the original C semantics. Another important problem related to operating systems regards the atomicity of operations in a concurrent setting. The processor might be interrupted in its current computation after each assembly instruction but a single C statement is usually compiled into several instructions.

260

CHAPTER 23. CONCLUSIONS

23.2.1

261

Hardware Model

For high-level design, a hardware model is required. A simple model of hardware will be defined. The purpose of the model is to make clear the assumptions about the hardware that are made for modeling of VMK. We may use the CCS instead of classical higher-logic for the hardware model, which is used to model the fundamental behavior of the hardware, in particular the interrupt structure.

Bibliography [AHR00]

M. Archer, C. L. Heitmeyer, and E. Riccobene. Using TAME to prove invariants of automata models: Two case studies. In FMSP 00: Proceedings of the 3rd Workshop on Formal Methods in Software Practice, New York, NY, USA, 2000. ACM.

[ALP03]

M. Archer, E. Leonard, and M Pradella. Analyzing SecurityEnhanced Linux Policy Specifications. In POLICY 03: Proceedings of the 4th IEEE International Workshop on Policies for Distributed Systems and Networks, Washington, DC, USA, 2003. IEEE Computer Society.

[Arc00]

M. Archer. TAME: Using PVS strategies for special-purpose theorem proving. Annals of Mathematics and Artificial Intelligence, 29(1-4), 2000.

[Arc06]

M. Archer. Basing a modelling environment on a general purpose theorem prover. Technical Report Technical Report NRL/MR/554606-8952, NRL, Washington, DC, USA, 2006.

[Bev87]

W. R. Bevier. A Verified Operating System Kernel. PhD thesis, University of Texas, Austin, 1987. ftp: ftp.cs.utexas.edu/pub/boyer/diss/bevier.pdf.

[BM88]

R. S. Boyer and J. S. Moore. A Computational Logic Handbook. Academic Press, Boston, MA, USA, 1988.

[BS93a]

W. R. Bevier and L. Smith. A Mathematical Model of the Mach Kernel: Atomic Actions and Locks. Technical Report 89, Computational Logic, Inc., Austin, TX, USA, 1993.

[BS93b]

W. R. Bevier and L. Smith. A Mathematical Model of the Mach Kernel: Entities and Relations. Technical Report 88, Computational Logic, Inc., Austin, TX, USA, 1993.

262

BIBLIOGRAPHY

263

[Cea86]

R. L. Constable and et al. Implementing Mathematics with the Nuprl Proof Development System. Prentice-Hall Inc., Englewood Cliffs, New Jersey, 1986.

[CH88]

T. Coquand and G. Huet. The calculus of constructions. Information and Computation, 76(2/3), 1988.

[Cra06]

Iain D. Craig. Formal Models of Operating System Kernels. SpringerVerlag, London, England, 2006.

[Cra07]

Iain D. Craig. Formal Refinement for Operating System Kernels. Springer-Verlag, London, England, 2007.

[DEK+ 06] P. Derrin, K. Elphinstone, G. Klein, D. Cock, and M. M. T. Chakravarty. Running the manual: An approach to high-assurance microkernel development. In Proceedings of the ACM SIGPLAN Haskell Workshop, Portland, OR, USA, 2006. [FHL+ 96] B. Ford, M. Hibler, J. Lepreau, P. Tullmann, G. Back, and S. Clawson. Microkernels meet recursive virtual machines. In Proceedings of the Second Symposium on Operating Systems Design and Implementation (OSDI96), Seattle, WA, USA, 1996. [FSDG08] Xinyu Feng, Zhong Shao, Yuan Dong, and Yu Guo. Certifying LowLevel Programs with Hardware Interrupts and Preemptive Threads. In Proceedings of 2008 ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’08), Tucson, Arizona, June 2008. [GHRS05] J. D. Guttman, A. L. Herzog, J. D. Ramsdell, and C. W. Skorupka. Verifying information flow goals in security-enhanced Linux. Journal of Computer Security, 13(1), 2005. [GMW79] M. Gordon, R. Milner, and C. Wadsworth. Edinburgh LCF. LNCS 78. Springer-Verlag, 1979. [Kle08]

Gerwin Klein. Operating System Verification - An Overview. Technical Report NRL-955, NICTA, Sydney, Australia, Jun 2008.

[Kle09]

Gerwin Klein. Operating System Verification - An Overview. S¯ adhan¯ a, 34(1):27–69, February 2009.

[ML84]

P. Martin-L¨of. Intuitionistic Type Theory. Studies in Proof Theory, Vol. 1. Bibliopolis, Naples, 1984.

[ORR+ 96] S. Owre, S. Rajan, J. Rushby, N. Shankar, and M. Srivas. PVS: Combining specification, proof checking, and model checking. In R. Alur and T. Henzinger, editors, Computer Aided Verification,

BIBLIOGRAPHY

264

volume 1102 of Lecture Notes in Computer Science. Springer-Verlag, 1996. [PM02]

Jens Palsberg and Di Ma. A typed interrupt calculus. In Proceedings of 7th International Symposium on Formal Techniques in Real-Time and Fault-Tolerant Systems (FTRTFT’02), volume 2469 of Lecture Notes in Computer Science, September 2002.

[SSL+ 99]

R. Spencer, S. Smalley, P. Loscocco, M. Hibler, D. Andersen, and J. Lepreau. The Flask security architecture: system support for diverse security policies. In SSYM99: Proceedings of the 8th conference on USENIX Security Symposium, Berkeley, CA, USA, 1999. USENIX Association.

[TKH05]

H. Tuch, G. Klein, and G. Heiser. OS Verification - Now! In Proceedings of the 10th Workshop on Hot Topics in Operating Systems, Santa Fe, NM, USA, 2005. USENIX.

[ZD94]

M.-Y. Zhu and Y.-Q. Ding. Program extraction by type erasing. In Proceedings of COMPSAC’94, Taipei, November 1994.

[Zhu89]

M.-Y. Zhu. AUTOSTAR – a software development system. ACM SIGPLAN Notices, 24(3), March 1989.

[ZW91]

M.-Y. Zhu and C.-W. Wang. A higher-order lambda calculus: PowerEpsilon. Technical report, Beijing Institute of Systems Engineering, Beijing, 1991.

[ZW92]

M.-Y. Zhu and C.-W. Wang. Program derivation in PowerEpsilon. In Proceedings of COMPSAC’92, Chicago, September 1992.

[ZW93a]

M.-Y. Zhu and C.-W. Wang. Decision making as theorem proving. Chinese Journal of Systems Engineering and Electronics, 4(1), 1993.

[ZW93b]

M.-Y. Zhu and C.-W. Wang. Mechanical synthesis of a matching algorithm in PowerEpsilon. Chinese Journal of Electronics, 2(1), 1993.

Index Π-elimination, 29 Π-formula, 16 Π-introduction, 29 Π-type, 29 Σ-elimination, 30 Σ-formula, 16 Σ-introduction, 30 Σ-type, 30 λ-abstraction, 14, 16 λ-expression, 26, 28 λ-expressions, 27, 28 AUTOSTAR, 13 Ada, 15 Algol 60, 27 C-VMK, 12 LCF, 13 LISP, 27 Nuprl, 13 POP-2, 27 Pascal, 15, 27 PowerEpsilon, 13–18, 21, 27–29, 36– 38, 41, 42 Calculus of Constructions, 13 Constructive logic, 37 Constructive mathematics, 13 Constructive proofs, 21 Curry-Howard Interpretation, 38 Isomorphism, 39 Domain, 39, 41–43 Recursive, 41 Domain constructors, 43 Domain equation, 43

Domain equations, 41, 43 Domains, 39–43 Finite, 42 Standard, 42 Existantial quantifier, 14 Existential quantification, 30 Fixed-point operators, 14 Functional programming language Polymorphic Strong-typed, 13 Higher-order Function, 26 Functions, 26, 27 Language, 27 Induction, 21 List, 22 Induction rules, 13 Inductive defined types, 13 Mathematical induction, 21 Meta-language, 13 Meta-variable, 15 Meta-variables, 15, 16 Proof checker, 13 Proof checkers, 13 Recursion List, 22 Type theory, 13, 21 Constructive, 38

265

INDEX

266

of Martin-L¨of, 13 Type universe hierarchies, 13 Universal Universal Universal Universal

generalization, 29 qualifier predicate, 16 quantification, 29 quantifier, 14

Suggest Documents