qemu_command_builder/
numa.rs

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