qemu_command_builder/
numa.rs

1use bon::Builder;
2
3use crate::to_command::ToCommand;
4
5#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Default, Builder)]
6pub struct NUMANodeMem {
7    mem_size: Option<usize>,
8    cpu_first: Option<usize>,
9    cpu_last: Option<usize>,
10    node_id: Option<usize>,
11    initiator: Option<usize>,
12}
13
14#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Default, Builder)]
15pub struct NUMANodeMemDev {
16    mem_id: Option<usize>,
17    cpu_first: Option<usize>,
18    cpu_last: Option<usize>,
19    node_id: Option<usize>,
20    initiator: Option<usize>,
21}
22#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Default, Builder)]
23pub struct NUMADist {
24    src: usize,
25    dst: usize,
26    val: usize,
27}
28
29#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Default, Builder)]
30pub struct NUMACPU {
31    node_id: usize,
32    socket_id: Option<usize>,
33    core_id: Option<usize>,
34    thread_id: Option<usize>,
35}
36
37#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
38pub enum NUMAHierarchy {
39    Memory,
40    FirstLevel,
41    SecondLevel,
42    ThirdLevel,
43}
44#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
45pub enum NUMADataType {
46    AccessLatency,
47    ReadLatency,
48    WriteLatency,
49}
50
51#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
52pub struct NUMAHMATLb {
53    initiator: usize,
54    target: usize,
55    hierarchy: NUMAHierarchy,
56    data_type: NUMADataType,
57    latency: Option<usize>,   // TODO nanoseconds type
58    bandwidth: Option<usize>, // TODO add value the possible value and units are NUM[M|G|T] mean that the bandwidth value are NUM byte per second (or MB/s, GB/s or TB/s depending on used suffix). Note that if latency or bandwidth value is 0, means the corresponding latency or bandwidth information is not provided.
59}
60
61#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
62pub enum HMATCacheAssociativity {
63    None,
64    Direct,
65    Complex,
66}
67#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
68pub enum HMATCachePolicy {
69    None,
70    WriteBack,
71    WriteThrough,
72}
73
74#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
75pub struct NUMAHMATCache {
76    node_id: usize,
77    size: usize,
78    level: usize,
79    associativity: Option<HMATCacheAssociativity>,
80    policy: Option<HMATCachePolicy>,
81    line: Option<usize>,
82}
83
84#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
85pub enum NUMA {
86    NodeMem(NUMANodeMem),
87    NodeMemDev(NUMANodeMemDev),
88    Dist(NUMADist),
89    Cpu(NUMACPU),
90    HMATLB(NUMAHMATLb),
91    HMATCache(NUMAHMATCache),
92}
93
94impl ToCommand for NUMA {
95    fn to_command(&self) -> Vec<String> {
96        let mut cmd = vec!["-numa".to_string()];
97
98        match self {
99            NUMA::NodeMem(node_mem) => {
100                let mut node_mem_args = "node".to_string();
101                if let Some(mem) = &node_mem.mem_size {
102                    node_mem_args.push_str(format!(",mem={}", mem).as_str());
103                }
104                if let Some(cpu) = &node_mem.cpu_first {
105                    node_mem_args.push_str(format!(",cpu={}", cpu).as_str());
106                }
107                if let Some(cpu) = &node_mem.cpu_last {
108                    node_mem_args.push_str(format!("-{}", cpu).as_str());
109                }
110                if let Some(node_id) = &node_mem.node_id {
111                    node_mem_args.push_str(format!(",nodeid={}", node_id).as_str());
112                }
113                if let Some(initiator) = &node_mem.initiator {
114                    node_mem_args.push_str(format!(",initiator={}", initiator).as_str());
115                }
116                cmd.push(node_mem_args.to_string());
117            }
118            NUMA::NodeMemDev(node_memdev) => {
119                let mut node_memdev_args = "node".to_string();
120                if let Some(memdev) = &node_memdev.mem_id {
121                    node_memdev_args.push_str(format!(",memdev={}", memdev).as_str());
122                }
123                if let Some(cpu) = &node_memdev.cpu_first {
124                    node_memdev_args.push_str(format!(",cpu={}", cpu).as_str());
125                }
126                if let Some(cpu) = &node_memdev.cpu_last {
127                    node_memdev_args.push_str(format!("-{}", cpu).as_str());
128                }
129                if let Some(node_id) = &node_memdev.node_id {
130                    node_memdev_args.push_str(format!(",nodeid={}", node_id).as_str());
131                }
132                if let Some(initiator) = &node_memdev.initiator {
133                    node_memdev_args.push_str(format!(",initiator={}", initiator).as_str());
134                }
135                cmd.push(node_memdev_args.to_string());
136            }
137            NUMA::Dist(dist) => {
138                cmd.push(format!(
139                    "dist,src={},dst={},val={}",
140                    dist.src, dist.dst, dist.val
141                ));
142            }
143            NUMA::Cpu(cpu) => {
144                let mut cpu_args = "cpu".to_string();
145
146                cpu_args.push_str(format!(",node-id={}", cpu.node_id).as_str());
147                if let Some(socket_id) = &cpu.socket_id {
148                    cpu_args.push_str(format!(",socket-id={}", socket_id).as_str());
149                }
150                if let Some(core_id) = &cpu.core_id {
151                    cpu_args.push_str(format!(",core-id={}", core_id).as_str());
152                }
153                if let Some(thread_id) = &cpu.thread_id {
154                    cpu_args.push_str(format!(",thread-id={}", thread_id).as_str());
155                }
156                cmd.push(cpu_args.to_string());
157            }
158            NUMA::HMATLB(hmat_lb) => {
159                let mut hmat_lb_args = "hmat-lb".to_string();
160                hmat_lb_args.push_str(
161                    format!(
162                        ",initiator={},target={},hierarchy=",
163                        hmat_lb.initiator, hmat_lb.target
164                    )
165                    .as_str(),
166                );
167                match hmat_lb.hierarchy {
168                    NUMAHierarchy::Memory => hmat_lb_args.push_str("memory"),
169                    NUMAHierarchy::FirstLevel => hmat_lb_args.push_str("first-level"),
170                    NUMAHierarchy::SecondLevel => hmat_lb_args.push_str("second-level"),
171                    NUMAHierarchy::ThirdLevel => hmat_lb_args.push_str("third-level"),
172                }
173                hmat_lb_args.push_str("data-type=");
174                match hmat_lb.data_type {
175                    NUMADataType::AccessLatency => hmat_lb_args.push_str("access-latency"),
176                    NUMADataType::ReadLatency => hmat_lb_args.push_str("read-latency"),
177                    NUMADataType::WriteLatency => hmat_lb_args.push_str("write-latency"),
178                }
179                if let Some(lat) = &hmat_lb.latency {
180                    hmat_lb_args.push_str(format!(",latency={}", lat).as_str());
181                }
182                if let Some(bw) = &hmat_lb.bandwidth {
183                    hmat_lb_args.push_str(format!(",bandwidth={}", bw).as_str());
184                }
185                cmd.push(hmat_lb_args);
186            }
187            NUMA::HMATCache(hmat_cache) => {
188                let mut hmat_cache_args = "hmat-cache".to_string();
189                hmat_cache_args.push_str(
190                    format!(
191                        ",node-id={},size={},level={}",
192                        hmat_cache.node_id, hmat_cache.size, hmat_cache.level
193                    )
194                    .as_str(),
195                );
196                if let Some(assoc) = &hmat_cache.associativity {
197                    hmat_cache_args.push_str(",associativity=");
198                    match assoc {
199                        HMATCacheAssociativity::None => hmat_cache_args.push_str("none"),
200                        HMATCacheAssociativity::Direct => hmat_cache_args.push_str("direct"),
201                        HMATCacheAssociativity::Complex => hmat_cache_args.push_str("complex"),
202                    }
203                }
204                if let Some(policy) = &hmat_cache.policy {
205                    hmat_cache_args.push_str(",policy=");
206                    match policy {
207                        HMATCachePolicy::None => hmat_cache_args.push_str("none"),
208                        HMATCachePolicy::WriteBack => hmat_cache_args.push_str("write-back"),
209                        HMATCachePolicy::WriteThrough => hmat_cache_args.push_str("write-through"),
210                    }
211                }
212                if let Some(line) = &hmat_cache.line {
213                    hmat_cache_args.push_str(format!(",line={}", line).as_str());
214                }
215            }
216        }
217        cmd
218    }
219}