⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pass-through.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 2007, Neocleus Corporation. * Copyright (c) 2007, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * * Alex Novik <alex@neocleus.com> * Allen Kay <allen.m.kay@intel.com> * Guy Zana <guy@neocleus.com> * * This file implements direct PCI assignment to a HVM guest */#include "vl.h"#include "pass-through.h"#include "pci/header.h"#include "pci/pci.h"#include "pt-msi.h"extern FILE *logfile;struct php_dev {    struct pt_dev *pt_dev;    uint8_t valid;    uint8_t r_bus;    uint8_t r_dev;    uint8_t r_func;};struct dpci_infos {    struct php_dev php_devs[PHP_SLOT_LEN];    PCIBus *e_bus;    struct pci_access *pci_access;} dpci_infos;/* prototype */static uint32_t pt_common_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_status_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_irqpin_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_bar_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_linkctrl2_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_msgctrl_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_msgaddr32_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_msgaddr64_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint32_t pt_msixctrl_reg_init(struct pt_dev *ptdev,    struct pt_reg_info_tbl *reg, uint32_t real_offset);static uint8_t pt_reg_grp_size_init(struct pt_dev *ptdev,    struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);static uint8_t pt_msi_size_init(struct pt_dev *ptdev,    struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);static uint8_t pt_msix_size_init(struct pt_dev *ptdev,    struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);static uint8_t pt_vendor_size_init(struct pt_dev *ptdev,    struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);static int pt_byte_reg_read(struct pt_dev *ptdev,    struct pt_reg_tbl *cfg_entry,    uint8_t *valueu, uint8_t valid_mask);static int pt_word_reg_read(struct pt_dev *ptdev,    struct pt_reg_tbl *cfg_entry,    uint16_t *value, uint16_t valid_mask);static int pt_long_reg_read(struct pt_dev *ptdev,    struct pt_reg_tbl *cfg_entry,    uint32_t *value, uint32_t valid_mask);static int pt_bar_reg_read(struct pt_dev *ptdev,    struct pt_reg_tbl *cfg_entry,    uint32_t *value, uint32_t valid_mask);static int pt_byte_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint8_t *value, uint8_t dev_value, uint8_t valid_mask);static int pt_word_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_long_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint32_t *value, uint32_t dev_value, uint32_t valid_mask);static int pt_cmd_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_bar_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint32_t *value, uint32_t dev_value, uint32_t valid_mask);static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint32_t *value, uint32_t dev_value, uint32_t valid_mask);static int pt_pmcsr_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_devctrl_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_linkctrl_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_devctrl2_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_linkctrl2_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_msgctrl_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_msgaddr32_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint32_t *value, uint32_t dev_value, uint32_t valid_mask);static int pt_msgaddr64_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint32_t *value, uint32_t dev_value, uint32_t valid_mask);static int pt_msgdata_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);static int pt_msixctrl_reg_write(struct pt_dev *ptdev,     struct pt_reg_tbl *cfg_entry,     uint16_t *value, uint16_t dev_value, uint16_t valid_mask);/* pt_reg_info_tbl declaration * - only for emulated register (either a part or whole bit). * - for passthrough register that need special behavior (like interacting with *   other component), set emu_mask to all 0 and specify r/w func properly. * - do NOT use ALL F for init_val, otherwise the tbl will not be registered. */ /* Header Type0 reg static infomation table */static struct pt_reg_info_tbl pt_emu_reg_header0_tbl[] = {    /* Command reg */    {        .offset     = PCI_COMMAND,        .size       = 2,        .init_val   = 0x0000,        .ro_mask    = 0xF880,        .emu_mask   = 0x0340,        .init       = pt_common_reg_init,        .u.w.read   = pt_word_reg_read,        .u.w.write  = pt_cmd_reg_write,    },    /* Capabilities Pointer reg */    {        .offset     = PCI_CAPABILITY_LIST,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0xFF,        .init       = pt_ptr_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* Status reg */    /* use emulated Cap Ptr value to initialize,      * so need to be declared after Cap Ptr reg      */    {        .offset     = PCI_STATUS,        .size       = 2,        .init_val   = 0x0000,        .ro_mask    = 0x06FF,        .emu_mask   = 0x0010,        .init       = pt_status_reg_init,        .u.w.read   = pt_word_reg_read,        .u.w.write  = pt_word_reg_write,    },    /* Cache Line Size reg */    {        .offset     = PCI_CACHE_LINE_SIZE,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0x00,        .emu_mask   = 0xFF,        .init       = pt_common_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* Latency Timer reg */    {        .offset     = PCI_LATENCY_TIMER,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0x00,        .emu_mask   = 0xFF,        .init       = pt_common_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* Header Type reg */    {        .offset     = PCI_HEADER_TYPE,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0x80,        .init       = pt_common_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* Interrupt Line reg */    {        .offset     = PCI_INTERRUPT_LINE,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0x00,        .emu_mask   = 0xFF,        .init       = pt_common_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* Interrupt Pin reg */    {        .offset     = PCI_INTERRUPT_PIN,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0xFF,        .init       = pt_irqpin_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* BAR 0 reg */    /* mask of BAR need to be decided later, depends on IO/MEM type */    {        .offset     = PCI_BASE_ADDRESS_0,        .size       = 4,        .init_val   = 0x00000000,        .init       = pt_bar_reg_init,        .u.dw.read  = pt_bar_reg_read,        .u.dw.write = pt_bar_reg_write,    },    /* BAR 1 reg */    {        .offset     = PCI_BASE_ADDRESS_1,        .size       = 4,        .init_val   = 0x00000000,        .init       = pt_bar_reg_init,        .u.dw.read  = pt_bar_reg_read,        .u.dw.write = pt_bar_reg_write,    },    /* BAR 2 reg */    {        .offset     = PCI_BASE_ADDRESS_2,        .size       = 4,        .init_val   = 0x00000000,        .init       = pt_bar_reg_init,        .u.dw.read  = pt_bar_reg_read,        .u.dw.write = pt_bar_reg_write,    },    /* BAR 3 reg */    {        .offset     = PCI_BASE_ADDRESS_3,        .size       = 4,        .init_val   = 0x00000000,        .init       = pt_bar_reg_init,        .u.dw.read  = pt_bar_reg_read,        .u.dw.write = pt_bar_reg_write,    },    /* BAR 4 reg */    {        .offset     = PCI_BASE_ADDRESS_4,        .size       = 4,        .init_val   = 0x00000000,        .init       = pt_bar_reg_init,        .u.dw.read  = pt_bar_reg_read,        .u.dw.write = pt_bar_reg_write,    },    /* BAR 5 reg */    {        .offset     = PCI_BASE_ADDRESS_5,        .size       = 4,        .init_val   = 0x00000000,        .init       = pt_bar_reg_init,        .u.dw.read  = pt_bar_reg_read,        .u.dw.write = pt_bar_reg_write,    },    /* Expansion ROM BAR reg */    {        .offset     = PCI_ROM_ADDRESS,        .size       = 4,        .init_val   = 0x00000000,        .ro_mask    = 0x000007FE,        .emu_mask   = 0xFFFFF800,        .init       = pt_bar_reg_init,        .u.dw.read  = pt_long_reg_read,        .u.dw.write = pt_exp_rom_bar_reg_write,    },    {        .size = 0,    }, };/* Power Management Capability reg static infomation table */static struct pt_reg_info_tbl pt_emu_reg_pm_tbl[] = {    /* Next Pointer reg */    {        .offset     = PCI_CAP_LIST_NEXT,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0xFF,        .init       = pt_ptr_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* Power Management Capabilities reg */    {        .offset     = PCI_CAP_FLAGS,        .size       = 2,        .init_val   = 0x0000,        .ro_mask    = 0xFFFF,        .emu_mask   = 0xFFE8,        .init       = pt_common_reg_init,        .u.w.read   = pt_word_reg_read,        .u.w.write  = pt_word_reg_write,    },    /* PCI Power Management Control/Status reg */    {        .offset     = PCI_PM_CTRL,        .size       = 2,        .init_val   = 0x0008,        .ro_mask    = 0x60FC,        .emu_mask   = 0xFF0B,        .init       = pt_common_reg_init,        .u.w.read   = pt_word_reg_read,        .u.w.write  = pt_pmcsr_reg_write,    },    /* Data reg */    {        .offset     = PCI_PM_DATA_REGISTER,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0xFF,        .init       = pt_common_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    {        .size = 0,    }, };/* Vital Product Data Capability Structure reg static infomation table */static struct pt_reg_info_tbl pt_emu_reg_vpd_tbl[] = {    /* Next Pointer reg */    {        .offset     = PCI_CAP_LIST_NEXT,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0xFF,        .init       = pt_ptr_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    {        .size = 0,    }, };/* Vendor Specific Capability Structure reg static infomation table */static struct pt_reg_info_tbl pt_emu_reg_vendor_tbl[] = {    /* Next Pointer reg */    {        .offset     = PCI_CAP_LIST_NEXT,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0xFF,        .init       = pt_ptr_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    {        .size = 0,    }, };/* PCI Express Capability Structure reg static infomation table */static struct pt_reg_info_tbl pt_emu_reg_pcie_tbl[] = {    /* Next Pointer reg */    {        .offset     = PCI_CAP_LIST_NEXT,        .size       = 1,        .init_val   = 0x00,        .ro_mask    = 0xFF,        .emu_mask   = 0xFF,        .init       = pt_ptr_reg_init,        .u.b.read   = pt_byte_reg_read,        .u.b.write  = pt_byte_reg_write,    },    /* Device Capabilities reg */    {        .offset     = PCI_EXP_DEVCAP,        .size       = 4,        .init_val   = 0x00000000,        .ro_mask    = 0x1FFCFFFF,        .emu_mask   = 0x10000000,        .init       = pt_common_reg_init,        .u.dw.read  = pt_long_reg_read,        .u.dw.write = pt_long_reg_write,    },    /* Device Control reg */    {        .offset     = PCI_EXP_DEVCTL,        .size       = 2,        .init_val   = 0x2810,        .ro_mask    = 0x0000,        .emu_mask   = 0xFFFF,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -