diff --git a/src/vm/arch/x86/mptable.rs b/src/vm/arch/x86/mptable.rs index db9b9b8..81f55d5 100644 --- a/src/vm/arch/x86/mptable.rs +++ b/src/vm/arch/x86/mptable.rs @@ -1,10 +1,9 @@ -use byteorder::{LittleEndian, WriteBytesExt}; -use std::io::Write; use std::iter; +use crate::io::PciIrq; use crate::memory::GuestRam; -use crate::virtio::PciIrq; use crate::system::Result; +use crate::util::ByteBuffer; const APIC_DEFAULT_PHYS_BASE: u32 = 0xfee00000; const IO_APIC_DEFAULT_PHYS_BASE: u32 = 0xfec00000; @@ -37,16 +36,20 @@ const PCI_BUSTYPE: &[u8] = b"PCI "; const ISA_BUSID: u8 = 1; const ISA_BUSTYPE: &[u8] = b"ISA "; +const MPTABLE_START: u64 = 0x9fc00; + +const MPC_TABLE_SIZE: usize = 44; +const MPF_INTEL_SIZE: usize = 16; struct Buffer { - vec: Vec, + buffer: ByteBuffer>, count: usize, } impl Buffer { fn new() -> Buffer { Buffer { - vec: Vec::new(), + buffer: ByteBuffer::new_empty().little_endian(), count: 0, } } @@ -81,7 +84,7 @@ impl Buffer { } fn write_mpc_bus(&mut self, busid: u8, bustype: &[u8]) -> &mut Self { - assert!(bustype.len() == 6); + assert_eq!(bustype.len(), 6); self.count += 1; self.w8(MP_BUS) .w8(busid) @@ -117,20 +120,24 @@ impl Buffer { .w8(dstirq) // dest apid lint } - fn write_mpf_intel(&mut self, address: u32) -> &mut Self { - let start = self.vec.len(); + fn write_mpf_intel(&mut self) -> &mut Self { + let start = self.buffer.len(); + let config_address = (MPTABLE_START + MPF_INTEL_SIZE as u64) as u32; self.align(16) .bytes(b"_MP_") // Signature - .w32(address) // Configuration table address + .w32(config_address) // Configuration table address .w8(1) // Our length (paragraphs) .w8(4) // Specification version .w8(0) // checksum (offset 10) .pad(5) // feature1 - feature5 - .checksum(start, 16, 10) + .checksum(start, MPF_INTEL_SIZE, 10) } - fn write_mpctable(&mut self, ncpus: u16, body: &Buffer) -> &mut Self { - let len = 44 + body.vec.len(); + fn write_mpc_table(&mut self, offset: usize) -> &mut Self { + let old = self.buffer.len(); + let len = old - offset; + + self.buffer.set_offset(offset); self.bytes(b"PCMP") // 0 Signature .w16(len as u16) // 4 length .w8(4) // 6 Specification version @@ -138,48 +145,50 @@ impl Buffer { .bytes(b"SUBGRAPH") // 8 oem[8] .bytes(b"0.1 ") // 16 productid[12] .w32(0) // 28 oem ptr (0 if not present) - .w16(body.count as u16) // 32 oem size - .w16(ncpus) // 34 oem count + .w16(0) // 32 oem size + .w16(0) // 34 oem count .w32(APIC_DEFAULT_PHYS_BASE) // 36 APIC address .w32(0) // 40 reserved - .bytes(&body.vec) - .checksum(0, len, 7) + .checksum(offset, len, 7); + self.buffer.set_offset(old); + self } fn w8(&mut self, val: u8) -> &mut Self { - self.vec.push(val); + self.buffer.write(val); self } fn w16(&mut self, data: u16) -> &mut Self { - self.vec.write_u16::(data).unwrap(); + self.buffer.write(data); self } fn w32(&mut self, data: u32) -> &mut Self { - self.vec.write_u32::(data).unwrap(); + self.buffer.write(data); self } fn bytes(&mut self, data: &[u8]) -> &mut Self { - self.vec.write(data).unwrap(); + self.buffer.write(data); self } fn pad(&mut self, count: usize) -> &mut Self { if count > 0 { - self.vec.extend(iter::repeat(0).take(count)); + let zeros = iter::repeat(0).take(count).collect::>(); + self.buffer.write(zeros.as_slice()); } self } fn align(&mut self, n: usize) -> &mut Self { - let aligned = align(self.vec.len(), n); - let padlen = aligned - self.vec.len(); + let aligned = align(self.buffer.len(), n); + let padlen = aligned - self.buffer.len(); self.pad(padlen) } fn checksum(&mut self, start: usize, len: usize, csum_off: usize) -> &mut Self { { - let slice = &mut self.vec[start..start + len]; + let slice = self.buffer.mut_at(start, len); let csum = slice.iter().fold(0i32, |acc, &x| acc.wrapping_add(x as i32)); let b = (-csum & 0xFF) as u8; slice[csum_off] = b; @@ -194,19 +203,19 @@ fn align(sz: usize, n: usize) -> usize { pub fn setup_mptable(memory: &GuestRam, ncpus: usize, pci_irqs: &[PciIrq]) -> Result<()> { let ioapicid = (ncpus + 1) as u8; - let mut body = Buffer::new(); - let address = 0; + let mut buffer = Buffer::new(); + let address = MPTABLE_START; - body.write_all_mpc_cpu(ncpus) + buffer.write_mpf_intel() + .pad(MPC_TABLE_SIZE) + .write_all_mpc_cpu(ncpus) .write_mpc_bus(PCI_BUSID, PCI_BUSTYPE) .write_mpc_bus(ISA_BUSID, ISA_BUSTYPE) .write_mpc_ioapic(ioapicid) .write_all_mpc_intsrc(ioapicid, &pci_irqs) .write_mpc_lintsrc(MP_IRQ_SRC_INT, 0) .write_mpc_lintsrc(MP_IRQ_SRC_NMI, 1) - .write_mpf_intel(address); + .write_mpc_table(MPF_INTEL_SIZE); - let mut table = Buffer::new(); - table.write_mpctable(ncpus as u16, &body); - memory.write_bytes(address as u64, &table.vec) + memory.write_bytes(address, buffer.buffer.as_ref()) } \ No newline at end of file