qemu_command_builder/
smp.rs

1use bon::Builder;
2
3use crate::to_command::ToCommand;
4
5/// Simulate a SMP system with ``n`` CPUs initially present on
6/// the machine type board. On boards supporting CPU hotplug, the optional
7/// ``maxcpus`` parameter can be set to enable further CPUs to be
8/// added at runtime. When both parameters are omitted, the maximum number
9/// of CPUs will be calculated from the provided topology members and the
10/// initial CPU count will match the maximum number. When only one of them
11/// is given then the omitted one will be set to its counterpart's value.
12/// Both parameters may be specified, but the maximum number of CPUs must
13/// be equal to or greater than the initial CPU count. Product of the
14/// CPU topology hierarchy must be equal to the maximum number of CPUs.
15/// Both parameters are subject to an upper limit that is determined by
16/// the specific machine type chosen.
17///
18/// To control reporting of CPU topology information, values of the topology
19/// parameters can be specified. Machines may only support a subset of the
20/// parameters and different machines may have different subsets supported
21/// which vary depending on capacity of the corresponding CPU targets. So
22/// for a particular machine type board, an expected topology hierarchy can
23/// be defined through the supported sub-option. Unsupported parameters can
24/// also be provided in addition to the sub-option, but their values must be
25/// set as 1 in the purpose of correct parsing.
26///
27/// Either the initial CPU count, or at least one of the topology parameters
28/// must be specified. The specified parameters must be greater than zero,
29/// explicit configuration like "cpus=0" is not allowed. Values for any
30/// omitted parameters will be computed from those which are given.
31///
32/// For example, the following sub-option defines a CPU topology hierarchy
33/// (2 sockets totally on the machine, 2 cores per socket, 2 threads per
34/// core) for a machine that only supports sockets/cores/threads.
35/// Some members of the option can be omitted but their values will be
36/// automatically computed:
37#[derive(Builder)]
38pub struct SMP {
39    /// set the number of initial CPUs to 'n' [default=1]
40    cpus: usize,
41    /// maximum number of total CPUs, including offline CPUs for hotplug, etc
42    maxcpus: Option<usize>,
43    /// number of drawers on the machine board
44    drawers: Option<usize>,
45    /// number of books in one drawer
46    books: Option<usize>,
47    /// number of sockets in one book
48    sockets: Option<usize>,
49    /// number of dies in one socket
50    dies: Option<usize>,
51    /// number of clusters in one die
52    clusters: Option<usize>,
53    /// number of modules in one cluster
54    modules: Option<usize>,
55    /// number of cores in one module
56    cores: Option<usize>,
57    /// number of threads in one core
58    threads: Option<usize>,
59}
60
61impl Default for SMP {
62    fn default() -> Self {
63        SMP::new(1)
64    }
65}
66
67impl SMP {
68    pub fn new(cpus: usize) -> Self {
69        Self {
70            cpus,
71            maxcpus: None,
72            drawers: None,
73            books: None,
74            sockets: None,
75            dies: None,
76            clusters: None,
77            modules: None,
78            cores: None,
79            threads: None,
80        }
81    }
82}
83
84impl ToCommand for SMP {
85    fn to_command(&self) -> Vec<String> {
86        let mut cmd = vec![];
87
88        cmd.push("-smp".to_string());
89
90        let mut arg = vec![self.cpus.to_string()];
91        if let Some(maxcpus) = self.maxcpus {
92            arg.push(format!("maxcpus={}", maxcpus));
93        }
94        if let Some(drawers) = self.drawers {
95            arg.push(format!("drawers={}", drawers));
96        }
97        if let Some(books) = self.books {
98            arg.push(format!("books={}", books));
99        }
100        if let Some(sockets) = self.sockets {
101            arg.push(format!("sockets={}", sockets));
102        }
103        if let Some(dies) = self.dies {
104            arg.push(format!("dies={}", dies));
105        }
106        if let Some(clusters) = self.clusters {
107            arg.push(format!("clusters={}", clusters));
108        }
109        if let Some(modules) = self.modules {
110            arg.push(format!("modules={}", modules));
111        }
112        if let Some(cores) = self.cores {
113            arg.push(format!("cores={}", cores));
114        }
115        if let Some(threads) = self.threads {
116            arg.push(format!("threads={}", threads));
117        }
118
119        cmd.push(arg.join(","));
120
121        cmd
122    }
123}