pci_emul.h revision 270159
112891Swpaul/*-
212891Swpaul * Copyright (c) 2011 NetApp, Inc.
312891Swpaul * All rights reserved.
412891Swpaul *
512891Swpaul * Redistribution and use in source and binary forms, with or without
612891Swpaul * modification, are permitted provided that the following conditions
712891Swpaul * are met:
812891Swpaul * 1. Redistributions of source code must retain the above copyright
912891Swpaul *    notice, this list of conditions and the following disclaimer.
1012891Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1112891Swpaul *    notice, this list of conditions and the following disclaimer in the
1212891Swpaul *    documentation and/or other materials provided with the distribution.
1312891Swpaul *
1412891Swpaul * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
1512891Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1612891Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1712891Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
1812891Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1912891Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2012891Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2112891Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2212891Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2312891Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2412891Swpaul * SUCH DAMAGE.
2512891Swpaul *
2612891Swpaul * $FreeBSD: stable/10/usr.sbin/bhyve/pci_emul.h 270159 2014-08-19 01:20:24Z grehan $
2712891Swpaul */
2812891Swpaul
2912891Swpaul#ifndef _PCI_EMUL_H_
3012891Swpaul#define _PCI_EMUL_H_
3112891Swpaul
3212891Swpaul#include <sys/types.h>
3312891Swpaul#include <sys/queue.h>
34114601Sobrien#include <sys/kernel.h>
35114601Sobrien#include <sys/_pthreadtypes.h>
3630827Scharnier
3720818Swpaul#include <dev/pci/pcireg.h>
3812891Swpaul
3930827Scharnier#include <assert.h>
4030827Scharnier
4112891Swpaul#define	PCI_BARMAX	PCIR_MAX_BAR_0	/* BAR registers in a Type 0 header */
4212891Swpaul
4312891Swpaulstruct vmctx;
4412891Swpaulstruct pci_devinst;
4512891Swpaulstruct memory_region;
4612891Swpaul
4712891Swpaulstruct pci_devemu {
4812997Swpaul	char      *pe_emu;		/* Name of device emulation */
4912891Swpaul
5012891Swpaul	/* instance creation */
5112891Swpaul	int       (*pe_init)(struct vmctx *, struct pci_devinst *,
5228042Swpaul			     char *opts);
5328042Swpaul
5428042Swpaul	/* ACPI DSDT enumeration */
5528042Swpaul	void	(*pe_write_dsdt)(struct pci_devinst *);
5628042Swpaul
5790298Sdes	/* config space read/write callbacks */
5890298Sdes	int	(*pe_cfgwrite)(struct vmctx *ctx, int vcpu,
5946186Swpaul			       struct pci_devinst *pi, int offset,
6046186Swpaul			       int bytes, uint32_t val);
6146186Swpaul	int	(*pe_cfgread)(struct vmctx *ctx, int vcpu,
6246186Swpaul			      struct pci_devinst *pi, int offset,
6346186Swpaul			      int bytes, uint32_t *retval);
6446186Swpaul
6546186Swpaul	/* BAR read/write callbacks */
6646186Swpaul	void      (*pe_barwrite)(struct vmctx *ctx, int vcpu,
6746186Swpaul				 struct pci_devinst *pi, int baridx,
6846186Swpaul				 uint64_t offset, int size, uint64_t value);
6914262Swpaul	uint64_t  (*pe_barread)(struct vmctx *ctx, int vcpu,
7014262Swpaul				struct pci_devinst *pi, int baridx,
7114262Swpaul				uint64_t offset, int size);
7214262Swpaul};
7312891Swpaul#define PCI_EMUL_SET(x)   DATA_SET(pci_devemu_set, x);
7412891Swpaul
7512891Swpaulenum pcibar_type {
7612891Swpaul	PCIBAR_NONE,
7712891Swpaul	PCIBAR_IO,
7812891Swpaul	PCIBAR_MEM32,
7919161Swpaul	PCIBAR_MEM64,
8019161Swpaul	PCIBAR_MEMHI64
8119161Swpaul};
8212891Swpaul
8319161Swpaulstruct pcibar {
8412891Swpaul	enum pcibar_type	type;		/* io or memory */
8512891Swpaul	uint64_t		size;
8612891Swpaul	uint64_t		addr;
8712891Swpaul};
8812891Swpaul
8912891Swpaul#define PI_NAMESZ	40
9012891Swpaul
9112891Swpaulstruct msix_table_entry {
9212891Swpaul	uint64_t	addr;
9312891Swpaul	uint32_t	msg_data;
9412891Swpaul	uint32_t	vector_control;
9512891Swpaul} __packed;
9619161Swpaul
9719161Swpaul/*
9819161Swpaul * In case the structure is modified to hold extra information, use a define
9912891Swpaul * for the size that should be emulated.
10019161Swpaul */
10112891Swpaul#define	MSIX_TABLE_ENTRY_SIZE	16
10212891Swpaul#define MAX_MSIX_TABLE_ENTRIES	2048
10312891Swpaul#define	PBA_SIZE(msgnum)	(roundup2((msgnum), 64) / 8)
10412891Swpaul
10512891Swpaulenum lintr_stat {
10612891Swpaul	IDLE,
10712891Swpaul	ASSERTED,
10812891Swpaul	PENDING
10912891Swpaul};
11012891Swpaul
11112891Swpaulstruct pci_devinst {
11212891Swpaul	struct pci_devemu *pi_d;
11312891Swpaul	struct vmctx *pi_vmctx;
11412891Swpaul	uint8_t	  pi_bus, pi_slot, pi_func;
11512891Swpaul	char	  pi_name[PI_NAMESZ];
11612891Swpaul	int	  pi_bar_getsize;
11712891Swpaul	int	  pi_prevcap;
11819161Swpaul	int	  pi_capend;
11919161Swpaul
12019161Swpaul	struct {
12112891Swpaul		int8_t    	pin;
12219161Swpaul		enum lintr_stat	state;
12312891Swpaul		int		pirq_pin;
12412891Swpaul		int	  	ioapic_irq;
12512891Swpaul		pthread_mutex_t	lock;
12612891Swpaul	} pi_lintr;
12712891Swpaul
12812891Swpaul	struct {
12912891Swpaul		int		enabled;
13012891Swpaul		uint64_t	addr;
13112891Swpaul		uint64_t	msg_data;
13212891Swpaul		int		maxmsgnum;
13312891Swpaul	} pi_msi;
13412891Swpaul
13512891Swpaul	struct {
13612891Swpaul		int	enabled;
13712891Swpaul		int	table_bar;
13814304Swpaul		int	pba_bar;
13914304Swpaul		uint32_t table_offset;
14019161Swpaul		int	table_count;
14119161Swpaul		uint32_t pba_offset;
14219161Swpaul		int	pba_size;
14319161Swpaul		int	function_mask;
14412891Swpaul		struct msix_table_entry *table;	/* allocated at runtime */
14519161Swpaul	} pi_msix;
14612891Swpaul
14712891Swpaul	void      *pi_arg;		/* devemu-private data */
14812891Swpaul
14912891Swpaul	u_char	  pi_cfgdata[PCI_REGMAX + 1];
15012891Swpaul	struct pcibar pi_bar[PCI_BARMAX + 1];
15112891Swpaul};
15212891Swpaul
15312891Swpaulstruct msicap {
15412891Swpaul	uint8_t		capid;
15533250Swpaul	uint8_t		nextptr;
15620818Swpaul	uint16_t	msgctrl;
15720818Swpaul	uint32_t	addrlo;
15812891Swpaul	uint32_t	addrhi;
15912891Swpaul	uint16_t	msgdata;
16020818Swpaul} __packed;
16120818Swpaul
16212891Swpaulstruct msixcap {
16312891Swpaul	uint8_t		capid;
16412891Swpaul	uint8_t		nextptr;
16512891Swpaul	uint16_t	msgctrl;
16619161Swpaul	uint32_t	table_info;	/* bar index and offset within it */
167159461Smaxim	uint32_t	pba_info;	/* bar index and offset within it */
16819161Swpaul} __packed;
169159461Smaxim
17019161Swpaulstruct pciecap {
171145792Sume	uint8_t		capid;
172145793Sume	uint8_t		nextptr;
17319161Swpaul	uint16_t	pcie_capabilities;
17427589Swpaul
17590297Sdes	uint32_t	dev_capabilities;	/* all devices */
17620818Swpaul	uint16_t	dev_control;
17727589Swpaul	uint16_t	dev_status;
17827589Swpaul
17912891Swpaul	uint32_t	link_capabilities;	/* devices with links */
18012891Swpaul	uint16_t	link_control;
18130827Scharnier	uint16_t	link_status;
18212891Swpaul
18312891Swpaul	uint32_t	slot_capabilities;	/* ports with slots */
184145792Sume	uint16_t	slot_control;
185145792Sume	uint16_t	slot_status;
18612891Swpaul
187145792Sume	uint16_t	root_control;		/* root ports */
188145792Sume	uint16_t	root_capabilities;
189145792Sume	uint32_t	root_status;
190145792Sume
191145792Sume	uint32_t	dev_capabilities2;	/* all devices */
192145792Sume	uint16_t	dev_control2;
193145792Sume	uint16_t	dev_status2;
194145792Sume
19512891Swpaul	uint32_t	link_capabilities2;	/* devices with links */
19620818Swpaul	uint16_t	link_control2;
19720818Swpaul	uint16_t	link_status2;
19812891Swpaul
19912891Swpaul	uint32_t	slot_capabilities2;	/* ports with slots */
20012891Swpaul	uint16_t	slot_control2;
20112891Swpaul	uint16_t	slot_status2;
20212891Swpaul} __packed;
20312891Swpaul
20412891Swpaultypedef void (*pci_lintr_cb)(int b, int s, int pin, int pirq_pin,
20512891Swpaul    int ioapic_irq, void *arg);
20612891Swpaul
20712891Swpaulint	init_pci(struct vmctx *ctx);
20814304Swpaulvoid	msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
20914304Swpaul	    int bytes, uint32_t val);
21019161Swpaulvoid	msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
21119161Swpaul	    int bytes, uint32_t val);
21219161Swpaulvoid	pci_callback(void);
21319161Swpaulint	pci_emul_alloc_bar(struct pci_devinst *pdi, int idx,
21412891Swpaul	    enum pcibar_type type, uint64_t size);
21519161Swpaulint	pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx,
21612891Swpaul	    uint64_t hostbase, enum pcibar_type type, uint64_t size);
21712891Swpaulint	pci_emul_add_msicap(struct pci_devinst *pi, int msgnum);
21812891Swpaulint	pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type);
21912891Swpaulvoid	pci_generate_msi(struct pci_devinst *pi, int msgnum);
22012891Swpaulvoid	pci_generate_msix(struct pci_devinst *pi, int msgnum);
22112891Swpaulvoid	pci_lintr_assert(struct pci_devinst *pi);
22212891Swpaulvoid	pci_lintr_deassert(struct pci_devinst *pi);
22312891Swpaulvoid	pci_lintr_request(struct pci_devinst *pi);
22412891Swpaulint	pci_msi_enabled(struct pci_devinst *pi);
22533250Swpaulint	pci_msix_enabled(struct pci_devinst *pi);
22612891Swpaulint	pci_msix_table_bar(struct pci_devinst *pi);
22712891Swpaulint	pci_msix_pba_bar(struct pci_devinst *pi);
22812891Swpaulint	pci_msi_msgnum(struct pci_devinst *pi);
22912891Swpaulint	pci_parse_slot(char *opt);
23020818Swpaulvoid	pci_populate_msicap(struct msicap *cap, int msgs, int nextptr);
23112891Swpaulint	pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum);
23212891Swpaulint	pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size,
23312891Swpaul			     uint64_t value);
23412891Swpauluint64_t pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size);
23512891Swpaulint	pci_count_lintr(int bus);
23612891Swpaulvoid	pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg);
23712891Swpaulvoid	pci_write_dsdt(void);
23812891Swpauluint64_t pci_ecfg_base(void);
23912891Swpaulint	pci_bus_configured(int bus);
24014304Swpaul
24114304Swpaulstatic __inline void
24215426Swpaulpci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val)
24319161Swpaul{
24419161Swpaul	assert(offset <= PCI_REGMAX);
24519161Swpaul	*(uint8_t *)(pi->pi_cfgdata + offset) = val;
24612891Swpaul}
24719161Swpaul
24812891Swpaulstatic __inline void
24912891Swpaulpci_set_cfgdata16(struct pci_devinst *pi, int offset, uint16_t val)
25012891Swpaul{
25112891Swpaul	assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
25212891Swpaul	*(uint16_t *)(pi->pi_cfgdata + offset) = val;
25312891Swpaul}
25412891Swpaul
25512891Swpaulstatic __inline void
25612891Swpaulpci_set_cfgdata32(struct pci_devinst *pi, int offset, uint32_t val)
25720818Swpaul{
25812891Swpaul	assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);
25912891Swpaul	*(uint32_t *)(pi->pi_cfgdata + offset) = val;
26012891Swpaul}
26112891Swpaul
26220818Swpaulstatic __inline uint8_t
26320818Swpaulpci_get_cfgdata8(struct pci_devinst *pi, int offset)
26412891Swpaul{
26520818Swpaul	assert(offset <= PCI_REGMAX);
26620818Swpaul	return (*(uint8_t *)(pi->pi_cfgdata + offset));
26712891Swpaul}
26812891Swpaul
26912891Swpaulstatic __inline uint16_t
27090298Sdespci_get_cfgdata16(struct pci_devinst *pi, int offset)
27190298Sdes{
27290298Sdes	assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
27312997Swpaul	return (*(uint16_t *)(pi->pi_cfgdata + offset));
27412997Swpaul}
27512997Swpaul
27612997Swpaulstatic __inline uint32_t
27712997Swpaulpci_get_cfgdata32(struct pci_devinst *pi, int offset)
27813375Swpaul{
27912997Swpaul	assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);
28013375Swpaul	return (*(uint32_t *)(pi->pi_cfgdata + offset));
28112997Swpaul}
28212997Swpaul
28312997Swpaul#endif /* _PCI_EMUL_H_ */
28419131Swpaul