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