diff --git a/src/composer/Cargo.lock b/src/composer/Cargo.lock index aaa11fcee..c604783d7 100644 --- a/src/composer/Cargo.lock +++ b/src/composer/Cargo.lock @@ -2,6 +2,86 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "ascent" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd36abb7ceed59bb5be428927e8c17e32085a94c837fde7eaed7887071a4393" +dependencies = [ + "ascent_base", + "ascent_macro", + "boxcar", + "dashmap", + "hashbrown", + "instant", + "once_cell", + "paste", + "rayon", + "rustc-hash", +] + +[[package]] +name = "ascent_base" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "607bcfa9c2865077d4580c7f38df9edcf69aa7c7f0010917e0cbcd19933791b9" +dependencies = [ + "paste", +] + +[[package]] +name = "ascent_macro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726b7cdaa8b822285ce86d69ed7bc8dc79be547d874b855d0aac305b04d769d7" +dependencies = [ + "ascent_base", + "derive-syn-parse", + "duplicate", + "itertools 0.12.1", + "lazy_static", + "petgraph", + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "boxcar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c99613cb3cd7429889a08dfcf651721ca971c86afa30798461f8eee994de47" + [[package]] name = "cfg-if" version = "1.0.0" @@ -12,7 +92,8 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" name = "compose" version = "0.1.0" dependencies = [ - "itertools", + "ascent", + "itertools 0.8.2", "petgraph", "serde", "serde_derive", @@ -22,6 +103,62 @@ dependencies = [ "xmas-elf", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", + "rayon", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "duplicate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de78e66ac9061e030587b2a2e75cc88f22304913c907b11307bca737141230cb" + [[package]] name = "either" version = "1.6.1" @@ -42,7 +179,7 @@ checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.1.57", "winapi", ] @@ -57,6 +194,11 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", + "rayon", +] [[package]] name = "indexmap" @@ -68,6 +210,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "itertools" version = "0.8.2" @@ -77,11 +228,61 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" -version = "0.2.82" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.3", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "petgraph" @@ -95,28 +296,69 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.8" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.119" @@ -131,7 +373,7 @@ checksum = "552954ce79a059ddd5fd68c271592374bd15cab2274970380c000118aeffe1cd" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.58", ] [[package]] @@ -140,6 +382,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "syn" version = "1.0.58" @@ -151,6 +399,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tar" version = "0.4.30" @@ -159,7 +418,7 @@ checksum = "489997b7557e9a43e192c527face4feacc78bfbe6eed67fd55c4c9e381cba290" dependencies = [ "filetime", "libc", - "redox_syscall", + "redox_syscall 0.1.57", "xattr", ] @@ -172,12 +431,24 @@ dependencies = [ "serde", ] +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "winapi" version = "0.3.9" @@ -200,6 +471,70 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "xattr" version = "0.2.2" @@ -223,3 +558,23 @@ name = "zero" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] diff --git a/src/composer/Cargo.toml b/src/composer/Cargo.toml index 5a3211472..c17e1fb9b 100644 --- a/src/composer/Cargo.toml +++ b/src/composer/Cargo.toml @@ -12,3 +12,4 @@ tar = "0.4" itertools = "0.8.0" shell-words = "1.0.0" petgraph = "0.6.5" +ascent = "*" diff --git a/src/composer/src/analysis.rs b/src/composer/src/analysis.rs new file mode 100644 index 000000000..e51609308 --- /dev/null +++ b/src/composer/src/analysis.rs @@ -0,0 +1,345 @@ +use ascent::{ascent_run, lattice::Dual}; +use passes::{AnalysisPass, BuildState, ComponentId, Interface, SystemState, Transition}; +use std::collections::HashMap; + +// A very simplistic criticality-level specification. +type CriticalityLvl = usize; +#[allow(dead_code)] +const HC: CriticalityLvl = 1; +#[allow(dead_code)] +const LC: CriticalityLvl = 0; +#[allow(dead_code)] +const NUM_CRIT: usize = 2; + +// Component properties that are useful in determining how they impact +// other components. +#[allow(dead_code)] +#[derive(Clone, PartialEq, Eq, Hash)] +enum CompProperties { + Scheduler, + CapMgr, + MemMgr, + Constructor, + MutExcl, + DynMem, + CanBlock, +} + +// The set of warnings we're deriving from the system structure. These +// warnings are associated with a specific component. +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum Warning { + // A shared component service services multiple criticalities + SharedServiceMultCrit(CriticalityLvl, CriticalityLvl), + // A LC component (first argument of tuple) can block a HC + // component (the component parameterized with this warning), + // through a virtual resource + BlockingMultCrit(ComponentId, VirtResource, VirtResourceId), + // Is there a potential DoS on a shared pool of resources? Can + // *both* a HC and a LC component dynamically allocate + PotentialDos(ComponentId, VirtResource), + // The server component uses locks and can cause interference + // on the listed component . + PotentialInterference(ComponentId), + // The server component uses locks that can cause interference + // between the send and third components are different + // criticalities. + PotentialInterferenceMultCrit(ComponentId, ComponentId), +} + +// The mapping between interfaces exported by a server, and the +// properties of that server. +// +// This is hard-coded for now, but should be configured somewhere more +// reasonable. +const SERVER_PROPERTIES: &[(&'static str, CompProperties)] = &[ + ("sched", CompProperties::Scheduler), + ("capmgr", CompProperties::CapMgr), + ("memmgr", CompProperties::MemMgr), +]; + +// If a component is a client of one of these interfaces, then it is +// tagged with these properties. +// +// This is hard-coded for now, but should be configured somewhere more +// reasonable. +const CLIENT_PROPERTIES: &[(&'static str, CompProperties)] = &[ + ("sched", CompProperties::MutExcl), // TODO: should have a separate blkpt interface for this + ("sched", CompProperties::CanBlock), // TODO: should have a separate blkpt interface for this + ("memmgr", CompProperties::DynMem), +]; + +// Virtual resources have a type (here, a string), and the composer +// has assigned specific ids for pre-allocated resources. +type VirtResource = String; +type VirtResourceId = usize; + +// Is a client allowed to read, modify, and/or dynamically allocate a +// virtual resource. No access only to Dyn as what is the point to +// allocating, but not having the ability to read/modify? +#[allow(dead_code)] +#[derive(Clone, PartialEq, Eq, Hash)] +enum VirtResAccess { + Read, // read/access resource + Modify, // modify/write to resource + DynAlloc, // dynamically allocate resources + Block, // can a component block on the resource? + Unspecified, // The interface is unlabeled (e.g. no virt resources) +} + +#[allow(dead_code)] +pub struct AnalysisInput { + components: Vec, + // What is the criticality level of each component. Some of these + // (a minority) will be input, and the analysis will calculate the + // criticality ranges (`comp_crit_range`) for shared components. + criticalities: Vec<(ComponentId, CriticalityLvl)>, + // Dependencies between components (client -> server), based on + // interfaces, augmented with which if the dependency on that + // interface includes functions that imbue specific virtual + // resource access rights. + dependencies: Vec<(ComponentId, ComponentId, Interface, VirtResAccess)>, + + // Virtual resources, and the server that provides them. + virt_res_service: Vec<(VirtResource, ComponentId)>, + // The access of clients to specific virtual resources + virt_res_access: Vec<(VirtResource, VirtResourceId, ComponentId, VirtResAccess)>, +} + +#[allow(dead_code)] +pub struct Analysis { + // Simple transitive closure over the `dependencies` relation for + // (client, server) + depends_on: Vec<(ComponentId, ComponentId)>, + // All of the properties for each component + comp_properties: Vec<(ComponentId, CompProperties)>, + // The range of criticalities (min, max) for a specific component + comp_crit_range: Vec<(ComponentId, usize, usize)>, + // The first component can block the second. + comp_can_block: Vec<(ComponentId, ())>, + // Potential DOS on shared resources in server, from client + comp_dos: Vec<(ComponentId, ComponentId, VirtResource)>, + // Lock interference is possible between the components + comp_shared_lock: Vec<(ComponentId, ComponentId)>, + // synchronous invocations while holding a lock can generate + // nested locking. This is the set of potential nested locks. Can + // take the server, while in a synchronous invocation from the + // client. + comp_nested_lock: Vec<(ComponentId, ComponentId)>, + // The maximum number of necessary threads for a component + //thread_limit: Vec<(ComponentId, usize)>, + // What is the limit on the number of static virtual resources in + // the server or client? + // virt_resource_static: Vec<(ComponentId, VirtResource, usize)>, + // A server/manager component that requires dynamic allocation of + // virtual resources. + // virt_resource_dynamic: Vec<(ComponentId, VirtResource)>, + + // The warnings we derive from all of the above data. + warnings: Vec<(ComponentId, Warning)>, + + // The public warnings hashmap to get warnings for a specific + // component. + pub_warnings: HashMap>, +} + +fn analysis_output(i: AnalysisInput) -> Analysis { + let srv_prop_map: Vec<(String, CompProperties)> = SERVER_PROPERTIES + .iter() + .map(|(i, p)| (i.to_string(), p.clone())) + .collect(); + let cli_prop_map: Vec<(String, CompProperties)> = CLIENT_PROPERTIES + .iter() + .map(|(i, p)| (i.to_string(), p.clone())) + .collect(); + + // Destructure, so that we can individually move the vectors + // into the program. + let AnalysisInput { + criticalities, + dependencies, + virt_res_service, + virt_res_access, + .. + } = i; + + let p = ascent_run! { + // inputs + relation criticalities(ComponentId, CriticalityLvl) = criticalities; + relation dependencies(ComponentId, ComponentId, Interface, VirtResAccess) = dependencies; + relation srv_prop_map(String, CompProperties) = srv_prop_map; + relation cli_prop_map(String, CompProperties) = cli_prop_map; + relation virt_res_service(VirtResource, ComponentId) = virt_res_service; + relation virt_res_access(VirtResource, VirtResourceId, ComponentId, VirtResAccess) = virt_res_access; + + // transient relations + relation criticality_exposure(ComponentId, CriticalityLvl); + lattice comp_crit_hi(ComponentId, CriticalityLvl); + lattice comp_crit_lo(ComponentId, Dual); + + // outputs + relation depends_on(ComponentId, ComponentId); + relation comp_properties(ComponentId, CompProperties); + relation comp_crit_range(ComponentId, usize, usize); + relation comp_can_block(ComponentId, ()); + relation comp_dos(ComponentId, ComponentId, VirtResource); + relation comp_shared_lock(ComponentId, ComponentId); + relation comp_nested_lock(ComponentId, ComponentId); + + // The main output + relation warnings(ComponentId, Warning); + + // Normal transitive closure + depends_on(c, s) <-- dependencies(c, s, _, _); + depends_on(c, ss) <-- depends_on(c, s), dependencies(s, ss, _, _); + + // server properties + comp_properties(s, p) <-- dependencies(_, s, i, _), srv_prop_map(i, p); + // client properties + comp_properties(c, p) <-- dependencies(c, _, i, _), cli_prop_map(i, p); + + // Compute the criticality exposure for each component + criticality_exposure(c, crit) <-- criticalities(c, crit); + criticality_exposure(s, crit) <-- depends_on(c, s), criticalities(c, crit); + comp_crit_hi(c, crit) <-- criticality_exposure(c, crit); + comp_crit_lo(c, Dual(*crit)) <-- criticality_exposure(c, crit); + // Potential bug: if the lattice isn't completely computed + // before processing this relation, then we might have + // multiple `comp_crit_range(c, _, _)` entries. + comp_crit_range(c, hi, lo) <-- comp_crit_hi(c, hi), comp_crit_lo(c, ?Dual(lo)); + + warnings(c, Warning::SharedServiceMultCrit(*hi, *lo)) <-- comp_crit_range(c, hi, lo), if lo < hi; + + // TODO: take into account blocking on shared virtual resources + comp_can_block(c, ()) <-- comp_properties(c, CompProperties::CanBlock); + + // If components of different criticalities share a virtual + // resource, and the higher criticality one can block, we have + // a progress issue for the higher criticality one. + warnings(hc, Warning::BlockingMultCrit(*lc, vr.clone(), *vrid)) <-- + comp_crit_hi(hc, hi_crit), comp_crit_lo(lc, ?Dual(lo_crit)), if lo_crit < hi_crit, + virt_res_access(vr, vrid, hc, VirtResAccess::Block), virt_res_access(vr, vrid, lc, _); + + // If both HC and LC components can dynamically allocate + // virtual resources in a service, the LC might exhaust + // resources, DoSing the HC task. + warnings(hc, Warning::PotentialDos(*sc, vr.clone())) <-- + virt_res_access(vr, _, hc, VirtResAccess::DynAlloc), virt_res_access(vr, _, lc, VirtResAccess::DynAlloc), + virt_res_service(vr, sc), comp_crit_hi(hc, hi), comp_crit_lo(lc, ?Dual(lo)), if lo < hi; + + comp_shared_lock(s, c) <-- comp_properties(s, CompProperties::MutExcl), depends_on(c, s); + comp_nested_lock(s, c) <-- comp_properties(s, CompProperties::MutExcl), comp_properties(c, CompProperties::MutExcl), depends_on(c, s); + + // Is a component's threads execute potentially impacted by + // mutual exclusion in a server component? + warnings(s, Warning::PotentialInterference(*c)) <-- comp_shared_lock(s, c); + // Do both LC and HC components share a component that uses + // mutual exclusion? + warnings(s, Warning::PotentialInterferenceMultCrit(*hc, *lc)) <-- + comp_shared_lock(s, hc), comp_shared_lock(s, lc), + comp_crit_hi(hc, hi), comp_crit_lo(lc, lo), if hi > lo; + }; + + let mut ws: HashMap> = HashMap::new(); + for (c, w) in &p.warnings { + if let Some(e) = ws.get_mut(&c) { + e.push(w.clone()); + } else { + ws.insert(c.clone(), vec![w.clone()]); + } + } + + Analysis { + depends_on: p.depends_on, + comp_properties: p.comp_properties, + comp_crit_range: p.comp_crit_range, + comp_can_block: p.comp_can_block, + comp_dos: p.comp_dos, + comp_shared_lock: p.comp_shared_lock, + comp_nested_lock: p.comp_nested_lock, + warnings: p.warnings, + pub_warnings: ws, + } +} + +impl Analysis { + fn build(s: &SystemState) -> Self { + let cs = s.get_spec(); + let ids = s.get_named(); + + let compid = |c| ids.rmap().get(c).unwrap(); + let components: Vec = cs.names().iter().map(|c| *compid(c)).collect(); + // TODO: get the criticalities from the spec + let criticalities: Vec<(ComponentId, CriticalityLvl)> = + components.iter().map(|c| (*c, LC)).collect(); + let dependencies: Vec<(ComponentId, ComponentId, Interface, VirtResAccess)> = cs + .names() + .iter() + .map(|c| { + cs.deps_named(c) + .iter() + .filter_map(|d| { + if d.variant != "kernel" { + Some(( + *compid(c), + *compid(&d.server), + d.interface.clone(), + VirtResAccess::Unspecified, + )) + } else { + None + } + }) + .collect::>() + }) + .flatten() + .collect(); + + // Calculate the analysis outputs + analysis_output(AnalysisInput { + components, + dependencies, + criticalities, + // TODO + virt_res_service: Vec::new(), + virt_res_access: Vec::new(), + }) + } +} + +impl AnalysisPass for Analysis { + fn warnings(&self) -> &HashMap> { + &self.pub_warnings + } + + fn warning_str(&self, id: ComponentId, s: &SystemState) -> String { + let ids = s.get_named(); + let name = |id| ids.ids().get(&id).unwrap(); + let compname = name(id); + let ws_map = self.warnings(); + + let ws = ws_map.get(&id).unwrap(); + ws.iter().fold(format!("Component {compname} warnings:\n"), |s, w| { + match w { + Warning::SharedServiceMultCrit(hi, lo) => + format!("{s}\tService shared between components of criticalities spanning from {lo} to {hi}\n"), + Warning::BlockingMultCrit(id, vr, vrid) => + format!("{s}\tThis higher criticality component can be blocked on virtual resource {vr} (id {vrid}) that is shared with component {}\n", name(*id)), + Warning::PotentialDos(id, vr) => + format!("{s}\tThis service exports dynamic allocation for virtual resource {vr} to various criticality components, opening the high-criticality component {} up to a DoS attack\n", name(*id)), + Warning::PotentialInterference(id) => + format!("{s}\tThis component uses locks, thus can impose low-priority interference on higher priority tasks in component {}\n", name(*id)), + Warning::PotentialInterferenceMultCrit(id1, id2) => + format!("{s}\tThe component uses locks and might cause cross-criticality inteference in components {} and {}\n", name(*id1), name(*id2)), + } + }) + } +} + +impl Transition for Analysis { + fn transition(s: &SystemState, _b: &mut dyn BuildState) -> Result, String> { + let a = Analysis::build(s); + + Ok(Box::new(a)) + } +} diff --git a/src/composer/src/main.rs b/src/composer/src/main.rs index 40542f729..ff61f504e 100644 --- a/src/composer/src/main.rs +++ b/src/composer/src/main.rs @@ -5,6 +5,7 @@ extern crate itertools; extern crate tar; extern crate xmas_elf; extern crate petgraph; +extern crate ascent; mod address_assignment; mod build; @@ -20,6 +21,7 @@ mod symbols; mod syshelpers; mod tot_order; mod graph; +mod analysis; use address_assignment::AddressAssignmentx86_64; use build::DefaultBuilder; diff --git a/src/composer/src/passes.rs b/src/composer/src/passes.rs index 9981e00a0..fcf7d4827 100644 --- a/src/composer/src/passes.rs +++ b/src/composer/src/passes.rs @@ -16,6 +16,7 @@ use std::collections::{BTreeMap, HashMap}; use cossystem::ConstantVal; use initargs::ArgsKV; use std::fmt; +use analysis::Warning; pub struct SystemState { spec: String, @@ -30,8 +31,10 @@ pub struct SystemState { invs: HashMap>, constructor: Option>, graph: Option>, + analysis: Option>, } +#[allow(dead_code)] impl SystemState { pub fn new(spec: String) -> SystemState { SystemState { @@ -46,6 +49,7 @@ impl SystemState { invs: HashMap::new(), constructor: None, graph: None, + analysis: None, } } @@ -89,6 +93,10 @@ impl SystemState { self.graph = Some(c); } + pub fn add_analysis(&mut self, c: Box) { + self.analysis = Some(c); + } + pub fn get_input(&self) -> String { self.spec.clone() } @@ -132,6 +140,10 @@ impl SystemState { pub fn get_graph(&self) -> &dyn GraphPass { &**(self.graph.as_ref().unwrap()) } + + pub fn get_analysis(&self) -> &dyn AnalysisPass { + &**(self.analysis.as_ref().unwrap()) + } } // Note that none of this API does uniqueness checking: if a pass asks @@ -428,3 +440,8 @@ pub trait ConstructorPass { pub trait GraphPass { } + +pub trait AnalysisPass { + fn warnings(&self) -> &HashMap>; + fn warning_str(&self, id: ComponentId, s: &SystemState) -> String; +} diff --git a/src/platform/i386/chal_cpu.h b/src/platform/i386/chal_cpu.h index 6500a565d..00bd029cd 100644 --- a/src/platform/i386/chal_cpu.h +++ b/src/platform/i386/chal_cpu.h @@ -218,7 +218,7 @@ chal_cpu_init(void) * Composite does not use INVLPG feature. */ printk("ERROR: PCID is not supported.\n"); - assert(0); +// assert(0); } diff --git a/tools/init_env.sh b/tools/init_env.sh index 20b39db56..70f65d6b5 100755 --- a/tools/init_env.sh +++ b/tools/init_env.sh @@ -11,7 +11,7 @@ ubuntu64() { # This is used to set evnironment deps in Ubuntu-64 for compile&run x86_32/x86_64 bit Composite # Tested Ubuntu version: 18.04/20.04/21.04 - local dependencies="build-essential git cargo xorriso mtools qemu-system-i386 gcc-multilib grub-pc-bin python3-pip graphviz" + local dependencies="build-essential git cargo xorriso mtools qemu-system-i386 gcc-multilib grub-pc-bin python3-pip graphviz gdb" sudo apt install ${dependencies} -y if [ "${grub}" == "" ] && [ "${grub2}" == "" ]