================================================涉及的其他类
class PciDevice
PCI设备基类,存储pci设备状态,提供ReadBar、WriteBar虚接口函数。
ReadConfig
ReadConfigWord //读配置空间寄存器
WriteConfig //写配置寄存器空间
Interrupt //如果有pci pending中断则调用pcibus的中断处理
bus_->Interrupt
set_capabilities
SetupBarTraps
guest->CreateMapping //将bar的地址空间加入到guest的IoMappingList中,并设置访问trap为ZX_GUEST_TRAP_MEM(陷出).同时设置IoHandler为PciBar(实现Read和Write函数)
ReadConfigWord //从pci配置空间读取4字节对齐的值
ReadCapability
FindCapability
class PciBus
继承自PlatformDevice,成员变量包含:guest_(虚拟机)、config_addr_(pci配置空间)、device_(包含的pcidevice)、interrupt_controller_(中断控制器)、mmio_base_(mmio基地址)等
Interrupt
interrupt_controller_->Interrupt //调用中断控制器的中断处理(arm64为gic distributer)
ConfigureDtb //判断dtb中是否与pci-host-ecam-generic兼容的配置
class VirtioPci
VirtioPci //利用传入的VirtioDeviceConfig对象,初始化device_config_成员和父类的Attributes成员
ReadBar //只处理BAR0;
ConfigBarRead
WriteBar
ConfigBarWrite //BAR0,pcibar
NotifyBarWrite //BAR1,notifybar
device_config_->notify_queue //貌似virtionet中直接返回ZX_OK
add_isr_flags //Sets the given flags in the ISR register
// ISR flag values.
enum IsrFlags : uint8_t {
// Interrupt is caused by a queue.
ISR_QUEUE = 1 << 0,
// Interrupt is caused by a device config change.
ISR_CONFIG = 1 << 1,
};
ConfigBarRead
CommonCfgRead //通用配置读取
value->u8 = isr_status_;//中断状态配置
kVirtioPciDeviceCfgBase//Device-specific configuration
ConfigBarWrite //对common cfg和device specific cfg进行写配置
CommonCfgRead //通用配置读取,偏移从0x0~0x34
CommonCfgWrite
NotifyBarWrite
SetupCaps
queue_sel
struct VirtioDeviceConfig {
mutable std::mutex mutex;
// Virtio device ID.
const uint16_t device_id = 0;
// Virtio device features.
const uint32_t device_features = 0;
// Pointer to device configuration.
void* config __TA_GUARDED(mutex) = nullptr;
// Number of bytes used for this device's configuration space.
const uint64_t config_size = 0;
// Virtio queues for this device.
VirtioQueueConfig* const queue_configs __TA_GUARDED(mutex) = nullptr;
// Number of Virtio queues.
const uint16_t num_queues = 0;
// Invoked when the driver has made a change to the queue configuration.
using ConfigQueueFn =
fit::function
const ConfigQueueFn config_queue;
// Invoked when the driver sends notifications on a queue to the device.
using NotifyQueueFn = fit::function
const NotifyQueueFn notify_queue;
// Invoked when the driver has made a change to the device configuration.
using ConfigDeviceFn =
fit::function
const ConfigDeviceFn config_device;
// Invoked when the driver has accepted features and set the device into a
// 'Ready' state.
using ReadyDeviceFn =
fit::function
const ReadyDeviceFn ready_device;
};
static constexpr uint16_t kDefaultVirtioQueueSize = 128;
struct VirtioQueueConfig
{
union {
struct {
uint64_t desc;
uint64_t avail;
uint64_t used;
};
// Software will access these using 32 bit operations. Provide a
// convenience interface for these use cases.
uint32_t words[6] = {};
};
uint16_t size = kDefaultVirtioQueueSize;
}
===========
class VirtioQueue
VirtioQueue::VirtioQueue //创建event_对象
VirtioQueue::Configure //配置ring的size、描述符表、可用ring和已用ring。used_event_addr指向可用ring的后面2字节;avail_event_addr指向已用ring的后面2个字节(event是怎么分配的?与used ring和available ring正好相反!?)
VirtioQueue::NextChain //根据”可用ring项“构造VirtioChain对象返回
VirtioQueue::NextAvailLocked //获取下一个可用ring索引;更新avail_event(什么时候用??);如果没有可用ring,则调用event_.signal(SIGNAL_QUEUE_AVAIL, 0)发送ZX_USER_SIGNAL_0的清除信号(原型:signal(uint32_t clear_mask, uint32_t set_mask))
VirtioQueue::Notify //有可用ring时,调用event_.signal(0, SIGNAL_QUEUE_AVAIL)(通知前端?)
VirtioQueue::ReadDesc //取出guest的desc地址,映射到本地
VirtioQueue::Return //将index和len填入used ring,更新idx+1;如果use_event_index_为0,且ring_.used->flags为0则注入中断,否则如果ring_.used_event有值,且used->idx和used_event值相等则注入中断。
class VirtioChain
VirtioChain::NextDescriptor //调用VirtioQueue的ReadDesc
VirtioChain::Return //调用VirtioQueue的Return
struct VirtioDescriptor:virtio描述符结构体,包含了vring_desc的信息和更高层次的抽象。
// A higher-level API for vring_desc.
struct VirtioDescriptor {
// Pointer to the buffer in our address space.
void* addr;
// Number of bytes at addr.
uint32_t len;
// Only valid if has_next is true.
// TODO(abdulla): Remove this.
uint16_t next;
// Is there another buffer after this one?
// TODO(abdulla): Remove this.
bool has_next;
// If true, this buffer must only be written to (no reads). Otherwise this
// buffer must only be read from (no writes).
bool writable;
};
struct VirtioRing:包含vring的抽象
// Stores the Virtio queue based on the ring provided by the guest.
// NOTE(abdulla): This structure points to guest-controlled memory.
struct VirtioRing {
// Number of entries in the descriptor table.
uint16_t size;
uint16_t index; //指示当前处理的desc的idx
const struct vring_desc* desc; // guest-controlled
const struct vring_avail* avail; // guest-controlled
const uint16_t* used_event; // guest-controlled
struct vring_used* used; // guest-controlled
uint16_t* avail_event; // guest-controlled
};
========vring(虚拟队列)
每个虚拟队列由3部分组成:
1.描述符表
2.可用环
3.已用环
说明:描述符表只有一个,但是可以由多个描述符指向的buffer构成一个list(或者叫chain),而这个list可以从描述符表任意一个desc作为head开始(目前实现中list长度为1,并没利用起来)。
struct vring {
uint32_t num;
uint32_t num_mask;
uint16_t free_list; /* head of a free list of descriptors per ring. 0xffff is NULL */
uint16_t free_count;
uint16_t last_used;
struct vring_desc* desc;
struct vring_avail* avail;
struct vring_used* used;
};
/* This marks a buffer as continuing via the next field. */
#define VRING_DESC_F_NEXT 1
/* This marks a buffer as write-only (otherwise read-only). */
#define VRING_DESC_F_WRITE 2
/* This means the buffer contains a list of buffer descriptors. */
#define VRING_DESC_F_INDIRECT 4
/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
struct vring_desc {
/* Address (guest-physical). */
uint64_t addr;
/* Length. */
uint32_t len;
/* The flags as indicated above. */
uint16_t flags;
/* We chain unused descriptors via this, too */
uint16_t next;
};
struct vring_avail {
uint16_t flags;
uint16_t idx;
uint16_t ring[];
};
/* u32 is used here for ids for padding reasons. */
struct vring_used_elem {
/* Index of start of used descriptor chain. */
uint32_t id;
/* Total length of the descriptor chain which was used (written to) */
uint32_t len;
};
struct vring_used {
uint16_t flags;
uint16_t idx;
struct vring_used_elem ring[];
};