blob: eb87f99b52e6ca175fa6c57ac6e31925f7ab8afc [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(DATA61_GPL)
*/
#pragma once
#include <stdint.h>
#include <pci/pci.h>
#include "vmm/driver/pci.h"
#include "vmm/vmm.h"
/* Struct definition of a PCI device. This is used for emulating a device from
* purely memory reads. This is not generally useful on its own, but provides
* a nice skeleton */
typedef struct vmm_pci_device_def {
uint16_t vendor_id;
uint16_t device_id;
uint16_t command;
uint16_t status;
uint8_t revision_id;
uint8_t prog_if;
uint8_t subclass;
uint8_t class_code;
uint8_t cache_line_size;
uint8_t latency_timer;
uint8_t header_type;
uint8_t bist;
uint32_t bar0;
uint32_t bar1;
uint32_t bar2;
uint32_t bar3;
uint32_t bar4;
uint32_t bar5;
uint32_t cardbus;
uint16_t subsystem_vendor_id;
uint16_t subsystem_id;
uint32_t expansion_rom;
uint8_t caps_pointer;
uint8_t reserved1;
uint16_t reserved2;
uint32_t reserved3;
uint8_t interrupt_line;
uint8_t interrupt_pin;
uint8_t min_grant;
uint8_t max_latency;
/* Now additional pointer to arbitrary capabilities */
int caps_len;
void *caps;
} __attribute__((packed)) vmm_pci_device_def_t;
typedef struct vmm_pci_bar {
int ismem;
/* Address must be size aligned */
uintptr_t address;
int size_bits;
/* only if memory */
int prefetchable;
} vmm_pci_bar_t;
/* Helper write function that just ignores any writes */
int vmm_pci_entry_ignore_write(void *cookie, int offset, int size, uint32_t value);
/* Read and write methods for a memory device */
int vmm_pci_mem_device_read(void *cookie, int offset, int size, uint32_t *result);
int vmm_pci_mem_device_write(void *cookie, int offset, int size, uint32_t value);
void define_pci_host_bridge(vmm_pci_device_def_t *bridge);
/* Construct a pure passthrough device based on the real PCI. This is almost always useless as
* you will almost certainly want to rebase io memory */
vmm_pci_entry_t vmm_pci_create_passthrough(vmm_pci_address_t addr, vmm_pci_config_t config);
/* Bar read/write emulation, rest passed on */
vmm_pci_entry_t vmm_pci_create_bar_emulation(vmm_pci_entry_t existing, int num_bars, vmm_pci_bar_t *bars);
/* Interrupt read/write emulation, rest passed on */
vmm_pci_entry_t vmm_pci_create_irq_emulation(vmm_pci_entry_t existing, int irq);
/* Capability space emulation. Takes list of addresses to use to form a capability
* linked list, as well as a ranges of the capability space that should be
* directly disallowed. Assumes a type 0 device.
*/
vmm_pci_entry_t vmm_pci_create_cap_emulation(vmm_pci_entry_t existing, int num_caps, uint8_t *caps, int num_ranges, uint8_t *range_starts, uint8_t *range_ends);
/* Finds the MSI capabilities and uses vmm_pci_create_cap_emulation to remove them */
vmm_pci_entry_t vmm_pci_no_msi_cap_emulation(vmm_pci_entry_t existing);
/* Takes a libpci device scan and adds the bar resources to the guest, creating
* new pci bar information that can be passed to a virtual config space creator.
* Creates at most 6 bars, returns how many it created, negative on error */
int vmm_pci_helper_map_bars(vmm_t *vmm, libpci_device_iocfg_t *cfg, vmm_pci_bar_t *bars);