Skip to content

Commit e650087

Browse files
JBYoshiJonathanWoollett-Light
authored andcommitted
Miscellaneous fixes that don't fall anywhere else
In vmm/builder.rs, the CPU count can be fetched from the VM configuration without having to do a type conversion. In the serial device and the networking code, I added explicit checks to ensure that values fit in bounds. In the vCPU code, the existing code uses floats for tolerance values. We can replace these all with integer multiplications and divisions. Signed-off-by: Jonathan Browne <[email protected]>
1 parent ca5e99c commit e650087

File tree

5 files changed

+34
-30
lines changed

5 files changed

+34
-30
lines changed

src/vmm/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ pub fn configure_system_for_boot(
812812
utils::vm_memory::GuestAddress(crate::arch::x86_64::layout::CMDLINE_START),
813813
cmdline_size,
814814
initrd,
815-
vcpus.len() as u8,
815+
vcpu_config.vcpu_count,
816816
)
817817
.map_err(ConfigureSystem)?;
818818
}

src/vmm/src/devices/legacy/serial.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -306,22 +306,22 @@ impl<I: Read + AsRawFd + Send + Debug + 'static>
306306
SerialWrapper<EventFdTrigger, SerialEventsWrapper, I>
307307
{
308308
pub fn bus_read(&mut self, offset: u64, data: &mut [u8]) {
309-
if data.len() != 1 {
309+
if let (Ok(offset), 1) = (u8::try_from(offset), data.len()) {
310+
data[0] = self.serial.read(offset);
311+
} else {
310312
METRICS.uart.missed_read_count.inc();
311-
return;
312313
}
313-
data[0] = self.serial.read(offset as u8);
314314
}
315315

316316
pub fn bus_write(&mut self, offset: u64, data: &[u8]) {
317-
if data.len() != 1 {
317+
if let (Ok(offset), 1) = (u8::try_from(offset), data.len()) {
318+
if let Err(err) = self.serial.write(offset, data[0]) {
319+
// Counter incremented for any handle_write() error.
320+
error!("Failed the write to serial: {:?}", err);
321+
METRICS.uart.error_count.inc();
322+
}
323+
} else {
318324
METRICS.uart.missed_write_count.inc();
319-
return;
320-
}
321-
if let Err(err) = self.serial.write(offset as u8, data[0]) {
322-
// Counter incremented for any handle_write() error.
323-
error!("Failed the write to serial: {:?}", err);
324-
METRICS.uart.error_count.inc();
325325
}
326326
}
327327
}

src/vmm/src/dumbo/pdu/udp.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub const UDP_HEADER_SIZE: usize = 8;
2626

2727
// A UDP datagram is carried in a single IP packet and is hence limited
2828
// to a maximum payload of 65,507 bytes for IPv4 and 65,527 bytes for IPv6 [2]
29-
const IPV4_MAX_UDP_PACKET_SIZE: usize = 65507;
29+
const IPV4_MAX_UDP_PACKET_SIZE: u16 = 65507;
3030

3131
/// Represents errors which may occur while parsing or writing a datagram.
3232
#[derive(Debug, PartialEq, Eq)]
@@ -136,14 +136,14 @@ impl<'a, T: NetworkBytesMut + Debug> UdpDatagram<'a, T> {
136136
let mut packet = UdpDatagram::from_bytes(buf, None)?;
137137
let len = payload.len() + UDP_HEADER_SIZE;
138138

139-
// TODO working with IPv4 only for now
140-
if len > IPV4_MAX_UDP_PACKET_SIZE {
141-
return Err(Error::PayloadTooBig);
142-
}
139+
let len = match u16::try_from(len) {
140+
Ok(len) if len <= IPV4_MAX_UDP_PACKET_SIZE => len,
141+
_ => return Err(Error::PayloadTooBig),
142+
};
143143

144-
packet.bytes.shrink_unchecked(len);
144+
packet.bytes.shrink_unchecked(len.into());
145145
packet.payload_mut().copy_from_slice(payload);
146-
packet.set_len(len as u16);
146+
packet.set_len(len);
147147

148148
Ok(Incomplete::new(packet))
149149
}
@@ -250,7 +250,7 @@ mod tests {
250250
#[test]
251251
fn test_failing_construction() {
252252
let mut raw = [0u8; 8];
253-
let huge_payload = [0u8; IPV4_MAX_UDP_PACKET_SIZE];
253+
let huge_payload = [0u8; IPV4_MAX_UDP_PACKET_SIZE as usize];
254254

255255
assert_eq!(
256256
UdpDatagram::write_incomplete_datagram(raw.as_mut(), &huge_payload).unwrap_err(),

src/vmm/src/dumbo/tcp/connection.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -877,11 +877,12 @@ impl Connection {
877877
if let Some((read_buf, payload_seq)) = payload_src {
878878
// Limit the size of read_buf so it doesn't mess up later calculations (as usual, I take
879879
// the easy way out).
880-
if read_buf.len() > MAX_WINDOW_SIZE as usize {
881-
return Err(WriteNextError::PayloadBufTooLarge);
882-
}
880+
let len = match u32::try_from(read_buf.len()) {
881+
Ok(len) if len <= MAX_WINDOW_SIZE => len,
882+
_ => return Err(WriteNextError::PayloadBufTooLarge),
883+
};
883884

884-
let payload_end = payload_seq + Wrapping(read_buf.len() as u32);
885+
let payload_end = payload_seq + Wrapping(len);
885886

886887
let mut rto_triggered = false;
887888

src/vmm/src/vstate/vcpu/x86_64.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ use crate::vstate::vm::Vm;
2929
// The value of 250 parts per million is based on
3030
// the QEMU approach, more details here:
3131
// https://bugzilla.redhat.com/show_bug.cgi?id=1839095
32-
const TSC_KHZ_TOL: f64 = 250.0 / 1_000_000.0;
32+
const TSC_KHZ_TOL_NUMERATOR: u32 = 250;
33+
const TSC_KHZ_TOL_DENOMINATOR: u32 = 1_000_000;
3334

3435
/// Errors associated with the wrappers over KVM ioctls.
3536
#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)]
@@ -439,7 +440,7 @@ impl KvmVcpu {
439440
// per million beacuse it is common for TSC frequency
440441
// to differ due to calibration at boot time.
441442
let diff = (i64::from(self.get_tsc_khz()?) - i64::from(state_tsc_freq)).abs();
442-
Ok(diff as f64 > (f64::from(state_tsc_freq) * TSC_KHZ_TOL).round())
443+
Ok(diff > i64::from(state_tsc_freq * TSC_KHZ_TOL_NUMERATOR / TSC_KHZ_TOL_DENOMINATOR))
443444
}
444445

445446
/// Scale the TSC frequency of this vCPU to the one provided as a parameter.
@@ -891,7 +892,7 @@ mod tests {
891892
}
892893

893894
#[test]
894-
#[allow(clippy::cast_sign_loss, clippy::redundant_clone)] // always positive, no u32::try_from(f64)
895+
#[allow(clippy::redundant_clone)]
895896
fn test_is_tsc_scaling_required() {
896897
// Test `is_tsc_scaling_required` as if it were on the same
897898
// CPU model as the one in the snapshot state.
@@ -901,7 +902,8 @@ mod tests {
901902
{
902903
// The frequency difference is within tolerance.
903904
let mut state = orig_state.clone();
904-
state.tsc_khz = Some(state.tsc_khz.unwrap() + (TSC_KHZ_TOL / 2.0).round() as u32);
905+
state.tsc_khz =
906+
Some(state.tsc_khz.unwrap() + TSC_KHZ_TOL_NUMERATOR / TSC_KHZ_TOL_DENOMINATOR / 2);
905907
assert!(!vcpu
906908
.is_tsc_scaling_required(state.tsc_khz.unwrap())
907909
.unwrap());
@@ -910,19 +912,20 @@ mod tests {
910912
{
911913
// The frequency difference is over the tolerance.
912914
let mut state = orig_state;
913-
state.tsc_khz = Some(state.tsc_khz.unwrap() + (TSC_KHZ_TOL * 2.0).round() as u32);
915+
state.tsc_khz =
916+
Some(state.tsc_khz.unwrap() + TSC_KHZ_TOL_NUMERATOR / TSC_KHZ_TOL_DENOMINATOR * 2);
914917
assert!(!vcpu
915918
.is_tsc_scaling_required(state.tsc_khz.unwrap())
916919
.unwrap());
917920
}
918921
}
919922

920923
#[test]
921-
#[allow(clippy::cast_sign_loss)] // always positive, no u32::try_from(f64)
922924
fn test_set_tsc() {
923925
let (vm, vcpu, _) = setup_vcpu(0x1000);
924926
let mut state = vcpu.save_state().unwrap();
925-
state.tsc_khz = Some(state.tsc_khz.unwrap() + (TSC_KHZ_TOL * 2.0).round() as u32);
927+
state.tsc_khz =
928+
Some(state.tsc_khz.unwrap() + TSC_KHZ_TOL_NUMERATOR / TSC_KHZ_TOL_DENOMINATOR * 2);
926929

927930
if vm.fd().check_extension(Cap::TscControl) {
928931
assert!(vcpu.set_tsc_khz(state.tsc_khz.unwrap()).is_ok());

0 commit comments

Comments
 (0)