MCPcopy Create free account
hub / github.com/cloud-hypervisor/cloud-hypervisor / add_pci_bar

Method add_pci_bar

pci/src/configuration.rs:726–795  ·  view source on GitHub ↗

Adds a region specified by `config`. Configures the specified BAR(s) to report this region and size to the guest kernel. Enforces a few constraints (i.e, region size must be power of two, register not already used).

(&mut self, config: &PciBarConfiguration)

Source from the content-addressed store, hash-verified

724 /// report this region and size to the guest kernel. Enforces a few constraints
725 /// (i.e, region size must be power of two, register not already used).
726 pub fn add_pci_bar(&mut self, config: &PciBarConfiguration) -> Result<()> {
727 let bar_idx = config.idx;
728 let reg_idx = BAR0_REG + bar_idx;
729
730 if self.bars[bar_idx].used {
731 return Err(Error::BarInUse(bar_idx));
732 }
733
734 if !config.size.is_power_of_two() {
735 return Err(Error::BarSizeInvalid(config.size));
736 }
737
738 if bar_idx >= NUM_BAR_REGS {
739 return Err(Error::BarInvalid(bar_idx));
740 }
741
742 let end_addr = config
743 .addr
744 .checked_add(config.size - 1)
745 .ok_or(Error::BarAddressInvalid(config.addr, config.size))?;
746 match config.region_type {
747 PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => {
748 if end_addr > u64::from(u32::MAX) {
749 return Err(Error::BarAddressInvalid(config.addr, config.size));
750 }
751
752 // Encode the BAR size as expected by the software running in
753 // the guest.
754 self.bars[bar_idx].size =
755 encode_32_bits_bar_size(config.size as u32).ok_or(Error::Encode32BarSize)?;
756 }
757 PciBarRegionType::Memory64BitRegion => {
758 if bar_idx + 1 >= NUM_BAR_REGS {
759 return Err(Error::BarInvalid64(bar_idx));
760 }
761
762 if self.bars[bar_idx + 1].used {
763 return Err(Error::BarInUse64(bar_idx));
764 }
765
766 // Encode the BAR size as expected by the software running in
767 // the guest.
768 let (bar_size_hi, bar_size_lo) =
769 encode_64_bits_bar_size(config.size).ok_or(Error::Encode64BarSize)?;
770
771 self.registers[reg_idx + 1] = (config.addr >> 32) as u32;
772 self.writable_bits[reg_idx + 1] = 0xffff_ffff;
773 self.bars[bar_idx + 1].addr = self.registers[reg_idx + 1];
774 self.bars[bar_idx].size = bar_size_lo;
775 self.bars[bar_idx + 1].size = bar_size_hi;
776 self.bars[bar_idx + 1].used = true;
777 }
778 }
779
780 let (mask, lower_bits) = match config.region_type {
781 PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => (
782 BAR_MEM_ADDR_MASK,
783 config.prefetchable as u32 | config.region_type as u32,

Callers 5

allocate_barsMethod · 0.80
allocate_barsMethod · 0.80
allocate_barsMethod · 0.80
allocate_barsMethod · 0.80
allocate_barsMethod · 0.80

Calls 2

encode_32_bits_bar_sizeFunction · 0.85
encode_64_bits_bar_sizeFunction · 0.85

Tested by

no test coverage detected