1315a1350SMichael S. Tsirkin /*
2315a1350SMichael S. Tsirkin * pcie.c
3315a1350SMichael S. Tsirkin *
4315a1350SMichael S. Tsirkin * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
5315a1350SMichael S. Tsirkin * VA Linux Systems Japan K.K.
6315a1350SMichael S. Tsirkin *
7315a1350SMichael S. Tsirkin * This program is free software; you can redistribute it and/or modify
8315a1350SMichael S. Tsirkin * it under the terms of the GNU General Public License as published by
9315a1350SMichael S. Tsirkin * the Free Software Foundation; either version 2 of the License, or
10315a1350SMichael S. Tsirkin * (at your option) any later version.
11315a1350SMichael S. Tsirkin *
12315a1350SMichael S. Tsirkin * This program is distributed in the hope that it will be useful,
13315a1350SMichael S. Tsirkin * but WITHOUT ANY WARRANTY; without even the implied warranty of
14315a1350SMichael S. Tsirkin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15315a1350SMichael S. Tsirkin * GNU General Public License for more details.
16315a1350SMichael S. Tsirkin *
17315a1350SMichael S. Tsirkin * You should have received a copy of the GNU General Public License along
18315a1350SMichael S. Tsirkin * with this program; if not, see <http://www.gnu.org/licenses/>.
19315a1350SMichael S. Tsirkin */
20315a1350SMichael S. Tsirkin
2197d5408fSPeter Maydell #include "qemu/osdep.h"
22da34e65cSMarkus Armbruster #include "qapi/error.h"
23c759b24fSMichael S. Tsirkin #include "hw/pci/pci_bridge.h"
24c759b24fSMichael S. Tsirkin #include "hw/pci/pcie.h"
25c759b24fSMichael S. Tsirkin #include "hw/pci/msix.h"
26c759b24fSMichael S. Tsirkin #include "hw/pci/msi.h"
2706aac7bdSMichael S. Tsirkin #include "hw/pci/pci_bus.h"
28c759b24fSMichael S. Tsirkin #include "hw/pci/pcie_regs.h"
293d67447fSAlex Williamson #include "hw/pci/pcie_port.h"
301de7afc9SPaolo Bonzini #include "qemu/range.h"
3186f0aa1dSVladimir Sementsov-Ogievskiy #include "trace.h"
32315a1350SMichael S. Tsirkin
33315a1350SMichael S. Tsirkin //#define DEBUG_PCIE
34315a1350SMichael S. Tsirkin #ifdef DEBUG_PCIE
35315a1350SMichael S. Tsirkin # define PCIE_DPRINTF(fmt, ...) \
36315a1350SMichael S. Tsirkin fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
37315a1350SMichael S. Tsirkin #else
38315a1350SMichael S. Tsirkin # define PCIE_DPRINTF(fmt, ...) do {} while (0)
39315a1350SMichael S. Tsirkin #endif
40315a1350SMichael S. Tsirkin #define PCIE_DEV_PRINTF(dev, fmt, ...) \
41315a1350SMichael S. Tsirkin PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
42315a1350SMichael S. Tsirkin
pcie_sltctl_powered_off(uint16_t sltctl)435aaed9caSVladimir Sementsov-Ogievskiy static bool pcie_sltctl_powered_off(uint16_t sltctl)
445aaed9caSVladimir Sementsov-Ogievskiy {
455aaed9caSVladimir Sementsov-Ogievskiy return (sltctl & PCI_EXP_SLTCTL_PCC) == PCI_EXP_SLTCTL_PWR_OFF
465aaed9caSVladimir Sementsov-Ogievskiy && (sltctl & PCI_EXP_SLTCTL_PIC) == PCI_EXP_SLTCTL_PWR_IND_OFF;
475aaed9caSVladimir Sementsov-Ogievskiy }
48315a1350SMichael S. Tsirkin
pcie_led_state_to_str(uint16_t value)4986f0aa1dSVladimir Sementsov-Ogievskiy static const char *pcie_led_state_to_str(uint16_t value)
5086f0aa1dSVladimir Sementsov-Ogievskiy {
5186f0aa1dSVladimir Sementsov-Ogievskiy switch (value) {
5286f0aa1dSVladimir Sementsov-Ogievskiy case PCI_EXP_SLTCTL_PWR_IND_ON:
5386f0aa1dSVladimir Sementsov-Ogievskiy case PCI_EXP_SLTCTL_ATTN_IND_ON:
5486f0aa1dSVladimir Sementsov-Ogievskiy return "on";
5586f0aa1dSVladimir Sementsov-Ogievskiy case PCI_EXP_SLTCTL_PWR_IND_BLINK:
5686f0aa1dSVladimir Sementsov-Ogievskiy case PCI_EXP_SLTCTL_ATTN_IND_BLINK:
5786f0aa1dSVladimir Sementsov-Ogievskiy return "blink";
5886f0aa1dSVladimir Sementsov-Ogievskiy case PCI_EXP_SLTCTL_PWR_IND_OFF:
5986f0aa1dSVladimir Sementsov-Ogievskiy case PCI_EXP_SLTCTL_ATTN_IND_OFF:
6086f0aa1dSVladimir Sementsov-Ogievskiy return "off";
6186f0aa1dSVladimir Sementsov-Ogievskiy default:
6286f0aa1dSVladimir Sementsov-Ogievskiy return "invalid";
6386f0aa1dSVladimir Sementsov-Ogievskiy }
6486f0aa1dSVladimir Sementsov-Ogievskiy }
6586f0aa1dSVladimir Sementsov-Ogievskiy
66315a1350SMichael S. Tsirkin /***************************************************************************
67315a1350SMichael S. Tsirkin * pci express capability helper functions
68315a1350SMichael S. Tsirkin */
696383292aSDmitry Fleytman
706383292aSDmitry Fleytman static void
pcie_cap_v1_fill(PCIDevice * dev,uint8_t port,uint8_t type,uint8_t version)716b449540SMichael S. Tsirkin pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
72315a1350SMichael S. Tsirkin {
736b449540SMichael S. Tsirkin uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
746b449540SMichael S. Tsirkin uint8_t *cmask = dev->cmask + dev->exp.exp_cap;
756b449540SMichael S. Tsirkin
76315a1350SMichael S. Tsirkin /* capability register
77315a1350SMichael S. Tsirkin interrupt message number defaults to 0 */
78315a1350SMichael S. Tsirkin pci_set_word(exp_cap + PCI_EXP_FLAGS,
79315a1350SMichael S. Tsirkin ((type << PCI_EXP_FLAGS_TYPE_SHIFT) & PCI_EXP_FLAGS_TYPE) |
806383292aSDmitry Fleytman version);
81315a1350SMichael S. Tsirkin
82315a1350SMichael S. Tsirkin /* device capability register
83315a1350SMichael S. Tsirkin * table 7-12:
84315a1350SMichael S. Tsirkin * roll based error reporting bit must be set by all
85315a1350SMichael S. Tsirkin * Functions conforming to the ECN, PCI Express Base
86315a1350SMichael S. Tsirkin * Specification, Revision 1.1., or subsequent PCI Express Base
87315a1350SMichael S. Tsirkin * Specification revisions.
88315a1350SMichael S. Tsirkin */
89449dca6aSMarcin Juszkiewicz uint32_t devcap = PCI_EXP_DEVCAP_RBER;
90449dca6aSMarcin Juszkiewicz
91449dca6aSMarcin Juszkiewicz if (dev->cap_present & QEMU_PCIE_EXT_TAG) {
92449dca6aSMarcin Juszkiewicz devcap = PCI_EXP_DEVCAP_RBER | PCI_EXP_DEVCAP_EXT_TAG;
93449dca6aSMarcin Juszkiewicz }
94449dca6aSMarcin Juszkiewicz
95449dca6aSMarcin Juszkiewicz pci_set_long(exp_cap + PCI_EXP_DEVCAP, devcap);
96315a1350SMichael S. Tsirkin
97315a1350SMichael S. Tsirkin pci_set_long(exp_cap + PCI_EXP_LNKCAP,
98315a1350SMichael S. Tsirkin (port << PCI_EXP_LNKCAP_PN_SHIFT) |
99315a1350SMichael S. Tsirkin PCI_EXP_LNKCAP_ASPMS_0S |
100d96a0ac7SAlex Williamson QEMU_PCI_EXP_LNKCAP_MLW(QEMU_PCI_EXP_LNK_X1) |
101d96a0ac7SAlex Williamson QEMU_PCI_EXP_LNKCAP_MLS(QEMU_PCI_EXP_LNK_2_5GT));
102315a1350SMichael S. Tsirkin
103315a1350SMichael S. Tsirkin pci_set_word(exp_cap + PCI_EXP_LNKSTA,
104d96a0ac7SAlex Williamson QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1) |
105d96a0ac7SAlex Williamson QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT));
1066b449540SMichael S. Tsirkin
1076b449540SMichael S. Tsirkin /* We changed link status bits over time, and changing them across
1086b449540SMichael S. Tsirkin * migrations is generally fine as hardware changes them too.
1096b449540SMichael S. Tsirkin * Let's not bother checking.
1106b449540SMichael S. Tsirkin */
1116b449540SMichael S. Tsirkin pci_set_word(cmask + PCI_EXP_LNKSTA, 0);
1126383292aSDmitry Fleytman }
113315a1350SMichael S. Tsirkin
1146d1bda91SJonathan Cameron /* Includes setting the target speed default */
pcie_cap_fill_lnk(uint8_t * exp_cap,PCIExpLinkWidth width,PCIExpLinkSpeed speed)1156d1bda91SJonathan Cameron static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
1166d1bda91SJonathan Cameron PCIExpLinkSpeed speed)
1176d1bda91SJonathan Cameron {
1186d1bda91SJonathan Cameron /* Clear and fill LNKCAP from what was configured above */
1196d1bda91SJonathan Cameron pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
1206d1bda91SJonathan Cameron PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
1216d1bda91SJonathan Cameron pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
1226d1bda91SJonathan Cameron QEMU_PCI_EXP_LNKCAP_MLW(width) |
1236d1bda91SJonathan Cameron QEMU_PCI_EXP_LNKCAP_MLS(speed));
1246d1bda91SJonathan Cameron
1256d1bda91SJonathan Cameron if (speed > QEMU_PCI_EXP_LNK_2_5GT) {
1266d1bda91SJonathan Cameron /*
1276d1bda91SJonathan Cameron * Target Link Speed defaults to the highest link speed supported by
1286d1bda91SJonathan Cameron * the component. 2.5GT/s devices are permitted to hardwire to zero.
1296d1bda91SJonathan Cameron */
1306d1bda91SJonathan Cameron pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKCTL2,
1316d1bda91SJonathan Cameron PCI_EXP_LNKCTL2_TLS);
1326d1bda91SJonathan Cameron pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKCTL2,
1336d1bda91SJonathan Cameron QEMU_PCI_EXP_LNKCAP_MLS(speed) &
1346d1bda91SJonathan Cameron PCI_EXP_LNKCTL2_TLS);
1356d1bda91SJonathan Cameron }
1366d1bda91SJonathan Cameron
1376d1bda91SJonathan Cameron /*
1386d1bda91SJonathan Cameron * 2.5 & 5.0GT/s can be fully described by LNKCAP, but 8.0GT/s is
1396d1bda91SJonathan Cameron * actually a reference to the highest bit supported in this register.
1406d1bda91SJonathan Cameron * We assume the device supports all link speeds.
1416d1bda91SJonathan Cameron */
1426d1bda91SJonathan Cameron if (speed > QEMU_PCI_EXP_LNK_5GT) {
1436d1bda91SJonathan Cameron pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP2, ~0U);
1446d1bda91SJonathan Cameron pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
1456d1bda91SJonathan Cameron PCI_EXP_LNKCAP2_SLS_2_5GB |
1466d1bda91SJonathan Cameron PCI_EXP_LNKCAP2_SLS_5_0GB |
1476d1bda91SJonathan Cameron PCI_EXP_LNKCAP2_SLS_8_0GB);
1486d1bda91SJonathan Cameron if (speed > QEMU_PCI_EXP_LNK_8GT) {
1496d1bda91SJonathan Cameron pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
1506d1bda91SJonathan Cameron PCI_EXP_LNKCAP2_SLS_16_0GB);
1516d1bda91SJonathan Cameron }
1526d1bda91SJonathan Cameron if (speed > QEMU_PCI_EXP_LNK_16GT) {
1536d1bda91SJonathan Cameron pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
1546d1bda91SJonathan Cameron PCI_EXP_LNKCAP2_SLS_32_0GB);
1556d1bda91SJonathan Cameron }
1566d1bda91SJonathan Cameron if (speed > QEMU_PCI_EXP_LNK_32GT) {
1576d1bda91SJonathan Cameron pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP2,
1586d1bda91SJonathan Cameron PCI_EXP_LNKCAP2_SLS_64_0GB);
1596d1bda91SJonathan Cameron }
1606d1bda91SJonathan Cameron }
1616d1bda91SJonathan Cameron }
1626d1bda91SJonathan Cameron
pcie_cap_fill_link_ep_usp(PCIDevice * dev,PCIExpLinkWidth width,PCIExpLinkSpeed speed)163ea3f0ebcSJonathan Cameron void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
164ea3f0ebcSJonathan Cameron PCIExpLinkSpeed speed)
165ea3f0ebcSJonathan Cameron {
166ea3f0ebcSJonathan Cameron uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
167ea3f0ebcSJonathan Cameron
168ea3f0ebcSJonathan Cameron /*
169ea3f0ebcSJonathan Cameron * For an end point or USP need to set the current status as well
170ea3f0ebcSJonathan Cameron * as the capabilities.
171ea3f0ebcSJonathan Cameron */
172ea3f0ebcSJonathan Cameron pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
173ea3f0ebcSJonathan Cameron PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW);
174ea3f0ebcSJonathan Cameron pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
175ea3f0ebcSJonathan Cameron QEMU_PCI_EXP_LNKSTA_NLW(width) |
176ea3f0ebcSJonathan Cameron QEMU_PCI_EXP_LNKSTA_CLS(speed));
177ea3f0ebcSJonathan Cameron
178ea3f0ebcSJonathan Cameron pcie_cap_fill_lnk(exp_cap, width, speed);
179ea3f0ebcSJonathan Cameron }
180ea3f0ebcSJonathan Cameron
pcie_cap_fill_slot_lnk(PCIDevice * dev)1813d67447fSAlex Williamson static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
1823d67447fSAlex Williamson {
1833d67447fSAlex Williamson PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
1843d67447fSAlex Williamson uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
1853d67447fSAlex Williamson
1863d67447fSAlex Williamson /* Skip anything that isn't a PCIESlot */
1873d67447fSAlex Williamson if (!s) {
1883d67447fSAlex Williamson return;
1893d67447fSAlex Williamson }
1903d67447fSAlex Williamson
1913d67447fSAlex Williamson /*
1923d67447fSAlex Williamson * Link bandwidth notification is required for all root ports and
1933d67447fSAlex Williamson * downstream ports supporting links wider than x1 or multiple link
1943d67447fSAlex Williamson * speeds.
1953d67447fSAlex Williamson */
1963d67447fSAlex Williamson if (s->width > QEMU_PCI_EXP_LNK_X1 ||
1973d67447fSAlex Williamson s->speed > QEMU_PCI_EXP_LNK_2_5GT) {
1983d67447fSAlex Williamson pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
1993d67447fSAlex Williamson PCI_EXP_LNKCAP_LBNC);
2003d67447fSAlex Williamson }
2013d67447fSAlex Williamson
2023d67447fSAlex Williamson if (s->speed > QEMU_PCI_EXP_LNK_2_5GT) {
2033d67447fSAlex Williamson /*
2043d67447fSAlex Williamson * Hot-plug capable downstream ports and downstream ports supporting
2053d67447fSAlex Williamson * link speeds greater than 5GT/s must hardwire PCI_EXP_LNKCAP_DLLLARC
2063d67447fSAlex Williamson * to 1b. PCI_EXP_LNKCAP_DLLLARC implies PCI_EXP_LNKSTA_DLLLA, which
2073d67447fSAlex Williamson * we also hardwire to 1b here. 2.5GT/s hot-plug slots should also
2083d67447fSAlex Williamson * technically implement this, but it's not done here for compatibility.
2093d67447fSAlex Williamson */
2103d67447fSAlex Williamson pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP,
2113d67447fSAlex Williamson PCI_EXP_LNKCAP_DLLLARC);
212df72184eSLaurent Vivier /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
2133d67447fSAlex Williamson }
2143d67447fSAlex Williamson
2156d1bda91SJonathan Cameron pcie_cap_fill_lnk(exp_cap, s->width, s->speed);
2163d67447fSAlex Williamson }
2173d67447fSAlex Williamson
pcie_cap_init(PCIDevice * dev,uint8_t offset,uint8_t type,uint8_t port,Error ** errp)218f8cd1b02SMao Zhongyi int pcie_cap_init(PCIDevice *dev, uint8_t offset,
219f8cd1b02SMao Zhongyi uint8_t type, uint8_t port,
220f8cd1b02SMao Zhongyi Error **errp)
2216383292aSDmitry Fleytman {
2226383292aSDmitry Fleytman /* PCIe cap v2 init */
2236383292aSDmitry Fleytman int pos;
2246383292aSDmitry Fleytman uint8_t *exp_cap;
2256383292aSDmitry Fleytman
2266383292aSDmitry Fleytman assert(pci_is_express(dev));
2276383292aSDmitry Fleytman
2289a7c2a59SMao Zhongyi pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
229f8cd1b02SMao Zhongyi PCI_EXP_VER2_SIZEOF, errp);
2306383292aSDmitry Fleytman if (pos < 0) {
2316383292aSDmitry Fleytman return pos;
2326383292aSDmitry Fleytman }
2336383292aSDmitry Fleytman dev->exp.exp_cap = pos;
2346383292aSDmitry Fleytman exp_cap = dev->config + pos;
2356383292aSDmitry Fleytman
2366383292aSDmitry Fleytman /* Filling values common with v1 */
2376b449540SMichael S. Tsirkin pcie_cap_v1_fill(dev, port, type, PCI_EXP_FLAGS_VER2);
2386383292aSDmitry Fleytman
2393d67447fSAlex Williamson /* Fill link speed and width options */
2403d67447fSAlex Williamson pcie_cap_fill_slot_lnk(dev);
2413d67447fSAlex Williamson
2426383292aSDmitry Fleytman /* Filling v2 specific values */
243315a1350SMichael S. Tsirkin pci_set_long(exp_cap + PCI_EXP_DEVCAP2,
244315a1350SMichael S. Tsirkin PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP);
245315a1350SMichael S. Tsirkin
24630b04f87SChen Fan pci_set_word(dev->wmask + pos + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_EETLPPB);
247f03d8ea3SMarcel Apfelbaum
248f03d8ea3SMarcel Apfelbaum if (dev->cap_present & QEMU_PCIE_EXTCAP_INIT) {
249f03d8ea3SMarcel Apfelbaum /* read-only to behave like a 'NULL' Extended Capability Header */
250f03d8ea3SMarcel Apfelbaum pci_set_long(dev->wmask + PCI_CONFIG_SPACE_SIZE, 0);
251f03d8ea3SMarcel Apfelbaum }
252f03d8ea3SMarcel Apfelbaum
253315a1350SMichael S. Tsirkin return pos;
254315a1350SMichael S. Tsirkin }
255315a1350SMichael S. Tsirkin
pcie_cap_v1_init(PCIDevice * dev,uint8_t offset,uint8_t type,uint8_t port)2566383292aSDmitry Fleytman int pcie_cap_v1_init(PCIDevice *dev, uint8_t offset, uint8_t type,
2576383292aSDmitry Fleytman uint8_t port)
2586383292aSDmitry Fleytman {
2596383292aSDmitry Fleytman /* PCIe cap v1 init */
2606383292aSDmitry Fleytman int pos;
2619a7c2a59SMao Zhongyi Error *local_err = NULL;
2626383292aSDmitry Fleytman
2636383292aSDmitry Fleytman assert(pci_is_express(dev));
2646383292aSDmitry Fleytman
2659a7c2a59SMao Zhongyi pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
2669a7c2a59SMao Zhongyi PCI_EXP_VER1_SIZEOF, &local_err);
2676383292aSDmitry Fleytman if (pos < 0) {
2689a7c2a59SMao Zhongyi error_report_err(local_err);
2696383292aSDmitry Fleytman return pos;
2706383292aSDmitry Fleytman }
2716383292aSDmitry Fleytman dev->exp.exp_cap = pos;
2726383292aSDmitry Fleytman
2736b449540SMichael S. Tsirkin pcie_cap_v1_fill(dev, port, type, PCI_EXP_FLAGS_VER1);
2746383292aSDmitry Fleytman
2756383292aSDmitry Fleytman return pos;
2766383292aSDmitry Fleytman }
2776383292aSDmitry Fleytman
2786383292aSDmitry Fleytman static int
pcie_endpoint_cap_common_init(PCIDevice * dev,uint8_t offset,uint8_t cap_size)2796383292aSDmitry Fleytman pcie_endpoint_cap_common_init(PCIDevice *dev, uint8_t offset, uint8_t cap_size)
2806214e73cSAlex Williamson {
2816214e73cSAlex Williamson uint8_t type = PCI_EXP_TYPE_ENDPOINT;
282f8cd1b02SMao Zhongyi Error *local_err = NULL;
283f8cd1b02SMao Zhongyi int ret;
2846214e73cSAlex Williamson
2856214e73cSAlex Williamson /*
2866214e73cSAlex Williamson * Windows guests will report Code 10, device cannot start, if
2876214e73cSAlex Williamson * a regular Endpoint type is exposed on a root complex. These
2886214e73cSAlex Williamson * should instead be Root Complex Integrated Endpoints.
2896214e73cSAlex Williamson */
290fd56e061SDavid Gibson if (pci_bus_is_express(pci_get_bus(dev))
291fd56e061SDavid Gibson && pci_bus_is_root(pci_get_bus(dev))) {
2926214e73cSAlex Williamson type = PCI_EXP_TYPE_RC_END;
2936214e73cSAlex Williamson }
2946214e73cSAlex Williamson
295f8cd1b02SMao Zhongyi if (cap_size == PCI_EXP_VER1_SIZEOF) {
296f8cd1b02SMao Zhongyi return pcie_cap_v1_init(dev, offset, type, 0);
297f8cd1b02SMao Zhongyi } else {
298f8cd1b02SMao Zhongyi ret = pcie_cap_init(dev, offset, type, 0, &local_err);
299f8cd1b02SMao Zhongyi
300f8cd1b02SMao Zhongyi if (ret < 0) {
301f8cd1b02SMao Zhongyi error_report_err(local_err);
302f8cd1b02SMao Zhongyi }
303f8cd1b02SMao Zhongyi
304f8cd1b02SMao Zhongyi return ret;
305f8cd1b02SMao Zhongyi }
3066383292aSDmitry Fleytman }
3076383292aSDmitry Fleytman
pcie_endpoint_cap_init(PCIDevice * dev,uint8_t offset)3086383292aSDmitry Fleytman int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset)
3096383292aSDmitry Fleytman {
3106383292aSDmitry Fleytman return pcie_endpoint_cap_common_init(dev, offset, PCI_EXP_VER2_SIZEOF);
3116383292aSDmitry Fleytman }
3126383292aSDmitry Fleytman
pcie_endpoint_cap_v1_init(PCIDevice * dev,uint8_t offset)3136383292aSDmitry Fleytman int pcie_endpoint_cap_v1_init(PCIDevice *dev, uint8_t offset)
3146383292aSDmitry Fleytman {
3156383292aSDmitry Fleytman return pcie_endpoint_cap_common_init(dev, offset, PCI_EXP_VER1_SIZEOF);
3166214e73cSAlex Williamson }
3176214e73cSAlex Williamson
pcie_cap_exit(PCIDevice * dev)318315a1350SMichael S. Tsirkin void pcie_cap_exit(PCIDevice *dev)
319315a1350SMichael S. Tsirkin {
320315a1350SMichael S. Tsirkin pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER2_SIZEOF);
321315a1350SMichael S. Tsirkin }
322315a1350SMichael S. Tsirkin
pcie_cap_v1_exit(PCIDevice * dev)3236383292aSDmitry Fleytman void pcie_cap_v1_exit(PCIDevice *dev)
3246383292aSDmitry Fleytman {
3256383292aSDmitry Fleytman pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER1_SIZEOF);
3266383292aSDmitry Fleytman }
3276383292aSDmitry Fleytman
pcie_cap_get_type(const PCIDevice * dev)328315a1350SMichael S. Tsirkin uint8_t pcie_cap_get_type(const PCIDevice *dev)
329315a1350SMichael S. Tsirkin {
330315a1350SMichael S. Tsirkin uint32_t pos = dev->exp.exp_cap;
331315a1350SMichael S. Tsirkin assert(pos > 0);
332315a1350SMichael S. Tsirkin return (pci_get_word(dev->config + pos + PCI_EXP_FLAGS) &
333315a1350SMichael S. Tsirkin PCI_EXP_FLAGS_TYPE) >> PCI_EXP_FLAGS_TYPE_SHIFT;
334315a1350SMichael S. Tsirkin }
335315a1350SMichael S. Tsirkin
pcie_cap_get_version(const PCIDevice * dev)336cf2916f6SAlex Williamson uint8_t pcie_cap_get_version(const PCIDevice *dev)
337cf2916f6SAlex Williamson {
338cf2916f6SAlex Williamson uint32_t pos = dev->exp.exp_cap;
339cf2916f6SAlex Williamson assert(pos > 0);
340cf2916f6SAlex Williamson return pci_get_word(dev->config + pos + PCI_EXP_FLAGS) & PCI_EXP_FLAGS_VERS;
341cf2916f6SAlex Williamson }
342cf2916f6SAlex Williamson
343315a1350SMichael S. Tsirkin /* MSI/MSI-X */
344315a1350SMichael S. Tsirkin /* pci express interrupt message number */
345315a1350SMichael S. Tsirkin /* 7.8.2 PCI Express Capabilities Register: Interrupt Message Number */
pcie_cap_flags_set_vector(PCIDevice * dev,uint8_t vector)346315a1350SMichael S. Tsirkin void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector)
347315a1350SMichael S. Tsirkin {
348315a1350SMichael S. Tsirkin uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
349315a1350SMichael S. Tsirkin assert(vector < 32);
350315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(exp_cap + PCI_EXP_FLAGS, PCI_EXP_FLAGS_IRQ);
351315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
352315a1350SMichael S. Tsirkin vector << PCI_EXP_FLAGS_IRQ_SHIFT);
353315a1350SMichael S. Tsirkin }
354315a1350SMichael S. Tsirkin
pcie_cap_flags_get_vector(PCIDevice * dev)355315a1350SMichael S. Tsirkin uint8_t pcie_cap_flags_get_vector(PCIDevice *dev)
356315a1350SMichael S. Tsirkin {
357315a1350SMichael S. Tsirkin return (pci_get_word(dev->config + dev->exp.exp_cap + PCI_EXP_FLAGS) &
358315a1350SMichael S. Tsirkin PCI_EXP_FLAGS_IRQ) >> PCI_EXP_FLAGS_IRQ_SHIFT;
359315a1350SMichael S. Tsirkin }
360315a1350SMichael S. Tsirkin
pcie_cap_deverr_init(PCIDevice * dev)361315a1350SMichael S. Tsirkin void pcie_cap_deverr_init(PCIDevice *dev)
362315a1350SMichael S. Tsirkin {
363315a1350SMichael S. Tsirkin uint32_t pos = dev->exp.exp_cap;
364315a1350SMichael S. Tsirkin pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP,
365315a1350SMichael S. Tsirkin PCI_EXP_DEVCAP_RBER);
366315a1350SMichael S. Tsirkin pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_DEVCTL,
367315a1350SMichael S. Tsirkin PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE |
368315a1350SMichael S. Tsirkin PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
369315a1350SMichael S. Tsirkin pci_long_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_DEVSTA,
370315a1350SMichael S. Tsirkin PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED |
3718e815eeeSGonglei PCI_EXP_DEVSTA_FED | PCI_EXP_DEVSTA_URD);
372315a1350SMichael S. Tsirkin }
373315a1350SMichael S. Tsirkin
pcie_cap_deverr_reset(PCIDevice * dev)374315a1350SMichael S. Tsirkin void pcie_cap_deverr_reset(PCIDevice *dev)
375315a1350SMichael S. Tsirkin {
376315a1350SMichael S. Tsirkin uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL;
377315a1350SMichael S. Tsirkin pci_long_test_and_clear_mask(devctl,
378315a1350SMichael S. Tsirkin PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE |
379315a1350SMichael S. Tsirkin PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
380315a1350SMichael S. Tsirkin }
381315a1350SMichael S. Tsirkin
pcie_cap_lnkctl_init(PCIDevice * dev)382d584f1b9SMarcel Apfelbaum void pcie_cap_lnkctl_init(PCIDevice *dev)
383d584f1b9SMarcel Apfelbaum {
384d584f1b9SMarcel Apfelbaum uint32_t pos = dev->exp.exp_cap;
385d584f1b9SMarcel Apfelbaum pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_LNKCTL,
386d584f1b9SMarcel Apfelbaum PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES);
387d584f1b9SMarcel Apfelbaum }
388d584f1b9SMarcel Apfelbaum
pcie_cap_lnkctl_reset(PCIDevice * dev)389d584f1b9SMarcel Apfelbaum void pcie_cap_lnkctl_reset(PCIDevice *dev)
390d584f1b9SMarcel Apfelbaum {
391d584f1b9SMarcel Apfelbaum uint8_t *lnkctl = dev->config + dev->exp.exp_cap + PCI_EXP_LNKCTL;
392d584f1b9SMarcel Apfelbaum pci_long_test_and_clear_mask(lnkctl,
393d584f1b9SMarcel Apfelbaum PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES);
394d584f1b9SMarcel Apfelbaum }
395d584f1b9SMarcel Apfelbaum
hotplug_event_update_event_status(PCIDevice * dev)396315a1350SMichael S. Tsirkin static void hotplug_event_update_event_status(PCIDevice *dev)
397315a1350SMichael S. Tsirkin {
398315a1350SMichael S. Tsirkin uint32_t pos = dev->exp.exp_cap;
399315a1350SMichael S. Tsirkin uint8_t *exp_cap = dev->config + pos;
400315a1350SMichael S. Tsirkin uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
401315a1350SMichael S. Tsirkin uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
402315a1350SMichael S. Tsirkin
403315a1350SMichael S. Tsirkin dev->exp.hpev_notified = (sltctl & PCI_EXP_SLTCTL_HPIE) &&
404315a1350SMichael S. Tsirkin (sltsta & sltctl & PCI_EXP_HP_EV_SUPPORTED);
405315a1350SMichael S. Tsirkin }
406315a1350SMichael S. Tsirkin
hotplug_event_notify(PCIDevice * dev)407315a1350SMichael S. Tsirkin static void hotplug_event_notify(PCIDevice *dev)
408315a1350SMichael S. Tsirkin {
409315a1350SMichael S. Tsirkin bool prev = dev->exp.hpev_notified;
410315a1350SMichael S. Tsirkin
411315a1350SMichael S. Tsirkin hotplug_event_update_event_status(dev);
412315a1350SMichael S. Tsirkin
413315a1350SMichael S. Tsirkin if (prev == dev->exp.hpev_notified) {
414315a1350SMichael S. Tsirkin return;
415315a1350SMichael S. Tsirkin }
416315a1350SMichael S. Tsirkin
417315a1350SMichael S. Tsirkin /* Note: the logic above does not take into account whether interrupts
418315a1350SMichael S. Tsirkin * are masked. The result is that interrupt will be sent when it is
419315a1350SMichael S. Tsirkin * subsequently unmasked. This appears to be legal: Section 6.7.3.4:
420315a1350SMichael S. Tsirkin * The Port may optionally send an MSI when there are hot-plug events that
421315a1350SMichael S. Tsirkin * occur while interrupt generation is disabled, and interrupt generation is
422315a1350SMichael S. Tsirkin * subsequently enabled. */
423315a1350SMichael S. Tsirkin if (msix_enabled(dev)) {
424315a1350SMichael S. Tsirkin msix_notify(dev, pcie_cap_flags_get_vector(dev));
425315a1350SMichael S. Tsirkin } else if (msi_enabled(dev)) {
426315a1350SMichael S. Tsirkin msi_notify(dev, pcie_cap_flags_get_vector(dev));
4272e865671SFrederic Barrat } else if (pci_intx(dev) != -1) {
4285a03e708SMarcel Apfelbaum pci_set_irq(dev, dev->exp.hpev_notified);
429315a1350SMichael S. Tsirkin }
430315a1350SMichael S. Tsirkin }
431315a1350SMichael S. Tsirkin
hotplug_event_clear(PCIDevice * dev)432315a1350SMichael S. Tsirkin static void hotplug_event_clear(PCIDevice *dev)
433315a1350SMichael S. Tsirkin {
434315a1350SMichael S. Tsirkin hotplug_event_update_event_status(dev);
4352e865671SFrederic Barrat if (!msix_enabled(dev) && !msi_enabled(dev) && pci_intx(dev) != -1 &&
4362e865671SFrederic Barrat !dev->exp.hpev_notified) {
4375a03e708SMarcel Apfelbaum pci_irq_deassert(dev);
438315a1350SMichael S. Tsirkin }
439315a1350SMichael S. Tsirkin }
440315a1350SMichael S. Tsirkin
pcie_cap_slot_enable_power(PCIDevice * dev)4416b0969f1SIgor Mammedov void pcie_cap_slot_enable_power(PCIDevice *dev)
4426b0969f1SIgor Mammedov {
4436b0969f1SIgor Mammedov uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
4446b0969f1SIgor Mammedov uint32_t sltcap = pci_get_long(exp_cap + PCI_EXP_SLTCAP);
4456b0969f1SIgor Mammedov
4466b0969f1SIgor Mammedov if (sltcap & PCI_EXP_SLTCAP_PCP) {
447f90d9320SVladimir Sementsov-Ogievskiy pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
448f90d9320SVladimir Sementsov-Ogievskiy PCI_EXP_SLTCTL_PCC);
4496b0969f1SIgor Mammedov }
4506b0969f1SIgor Mammedov }
4516b0969f1SIgor Mammedov
pcie_set_power_device(PCIBus * bus,PCIDevice * dev,void * opaque)452d5daff7dSGerd Hoffmann static void pcie_set_power_device(PCIBus *bus, PCIDevice *dev, void *opaque)
453d5daff7dSGerd Hoffmann {
454d5daff7dSGerd Hoffmann bool *power = opaque;
455d5daff7dSGerd Hoffmann
456d5daff7dSGerd Hoffmann pci_set_power(dev, *power);
457d5daff7dSGerd Hoffmann }
458d5daff7dSGerd Hoffmann
pcie_cap_update_power(PCIDevice * hotplug_dev)459d5daff7dSGerd Hoffmann static void pcie_cap_update_power(PCIDevice *hotplug_dev)
460d5daff7dSGerd Hoffmann {
461d5daff7dSGerd Hoffmann uint8_t *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
462d5daff7dSGerd Hoffmann PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(hotplug_dev));
463d5daff7dSGerd Hoffmann uint32_t sltcap = pci_get_long(exp_cap + PCI_EXP_SLTCAP);
464d5daff7dSGerd Hoffmann uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
465d5daff7dSGerd Hoffmann bool power = true;
466d5daff7dSGerd Hoffmann
467d5daff7dSGerd Hoffmann if (sltcap & PCI_EXP_SLTCAP_PCP) {
468d5daff7dSGerd Hoffmann power = (sltctl & PCI_EXP_SLTCTL_PCC) == PCI_EXP_SLTCTL_PWR_ON;
4695aaed9caSVladimir Sementsov-Ogievskiy /* Don't we need to check also (sltctl & PCI_EXP_SLTCTL_PIC) ? */
470d5daff7dSGerd Hoffmann }
471d5daff7dSGerd Hoffmann
472d5daff7dSGerd Hoffmann pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
473d5daff7dSGerd Hoffmann pcie_set_power_device, &power);
474d5daff7dSGerd Hoffmann }
475d5daff7dSGerd Hoffmann
476315a1350SMichael S. Tsirkin /*
477315a1350SMichael S. Tsirkin * A PCI Express Hot-Plug Event has occurred, so update slot status register
478315a1350SMichael S. Tsirkin * and notify OS of the event if necessary.
479315a1350SMichael S. Tsirkin *
480315a1350SMichael S. Tsirkin * 6.7.3 PCI Express Hot-Plug Events
481315a1350SMichael S. Tsirkin * 6.7.3.4 Software Notification of Hot-Plug Events
482315a1350SMichael S. Tsirkin */
pcie_cap_slot_event(PCIDevice * dev,PCIExpressHotPlugEvent event)483315a1350SMichael S. Tsirkin static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
484315a1350SMichael S. Tsirkin {
485315a1350SMichael S. Tsirkin /* Minor optimization: if nothing changed - no event is needed. */
486315a1350SMichael S. Tsirkin if (pci_word_test_and_set_mask(dev->config + dev->exp.exp_cap +
487861dc735SMichael S. Tsirkin PCI_EXP_SLTSTA, event) == event) {
488315a1350SMichael S. Tsirkin return;
489315a1350SMichael S. Tsirkin }
490315a1350SMichael S. Tsirkin hotplug_event_notify(dev);
491315a1350SMichael S. Tsirkin }
492315a1350SMichael S. Tsirkin
pcie_cap_slot_plug_common(PCIDevice * hotplug_dev,DeviceState * dev,Error ** errp)4935571727aSDavid Hildenbrand static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev,
494b9731850SDavid Hildenbrand Error **errp)
495315a1350SMichael S. Tsirkin {
496b9731850SDavid Hildenbrand uint8_t *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
497b9731850SDavid Hildenbrand uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
498315a1350SMichael S. Tsirkin
499e4bcd27cSMarcel Apfelbaum PCIE_DEV_PRINTF(PCI_DEVICE(dev), "hotplug state: 0x%x\n", sltsta);
500315a1350SMichael S. Tsirkin if (sltsta & PCI_EXP_SLTSTA_EIS) {
501315a1350SMichael S. Tsirkin /* the slot is electromechanically locked.
502315a1350SMichael S. Tsirkin * This error is propagated up to qdev and then to HMP/QMP.
503315a1350SMichael S. Tsirkin */
5046c150fbdSGonglei error_setg_errno(errp, EBUSY, "slot is electromechanically locked");
505315a1350SMichael S. Tsirkin }
506a66e657eSIgor Mammedov }
507315a1350SMichael S. Tsirkin
pcie_cap_slot_pre_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)508b9731850SDavid Hildenbrand void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
509b9731850SDavid Hildenbrand Error **errp)
510b9731850SDavid Hildenbrand {
5110dabc0f6SJulia Suvorova PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
5120dabc0f6SJulia Suvorova uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
5130dabc0f6SJulia Suvorova uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP);
5140dabc0f6SJulia Suvorova
5150dabc0f6SJulia Suvorova /* Check if hot-plug is disabled on the slot */
5160dabc0f6SJulia Suvorova if (dev->hotplugged && (sltcap & PCI_EXP_SLTCAP_HPC) == 0) {
5170dabc0f6SJulia Suvorova error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'",
5180dabc0f6SJulia Suvorova DEVICE(hotplug_pdev)->id);
5190dabc0f6SJulia Suvorova return;
5200dabc0f6SJulia Suvorova }
5210dabc0f6SJulia Suvorova
522b9731850SDavid Hildenbrand pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp);
523b9731850SDavid Hildenbrand }
524b9731850SDavid Hildenbrand
pcie_cap_slot_plug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)5255571727aSDavid Hildenbrand void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
526a66e657eSIgor Mammedov Error **errp)
527a66e657eSIgor Mammedov {
528b9731850SDavid Hildenbrand PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
529b9731850SDavid Hildenbrand uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
5306e1f0a55SIgor Mammedov PCIDevice *pci_dev = PCI_DEVICE(dev);
531df72184eSLaurent Vivier uint32_t lnkcap = pci_get_long(exp_cap + PCI_EXP_LNKCAP);
532a66e657eSIgor Mammedov
5337c0fa8dfSKnut Omang if (pci_is_vf(pci_dev)) {
5347c0fa8dfSKnut Omang /* Virtual function cannot be physically disconnected */
5357c0fa8dfSKnut Omang return;
5367c0fa8dfSKnut Omang }
5377c0fa8dfSKnut Omang
538a66e657eSIgor Mammedov /* Don't send event when device is enabled during qemu machine creation:
539a66e657eSIgor Mammedov * it is present on boot, no hotplug event is necessary. We do send an
540a66e657eSIgor Mammedov * event when the device is disabled later. */
541a66e657eSIgor Mammedov if (!dev->hotplugged) {
542315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
543315a1350SMichael S. Tsirkin PCI_EXP_SLTSTA_PDS);
544df72184eSLaurent Vivier if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA ||
545df72184eSLaurent Vivier (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) {
5462f2b18f6SZheng Xiang pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
5472f2b18f6SZheng Xiang PCI_EXP_LNKSTA_DLLLA);
5482f2b18f6SZheng Xiang }
549d5daff7dSGerd Hoffmann pcie_cap_update_power(hotplug_pdev);
550a66e657eSIgor Mammedov return;
551a66e657eSIgor Mammedov }
552a66e657eSIgor Mammedov
5533f1e1478SCao jin /* To enable multifunction hot-plug, we just ensure the function
5543f1e1478SCao jin * 0 added last. When function 0 is added, we set the sltsta and
5553f1e1478SCao jin * inform OS via event notification.
5566e1f0a55SIgor Mammedov */
5573f1e1478SCao jin if (pci_get_function_0(pci_dev)) {
558a66e657eSIgor Mammedov pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
559a66e657eSIgor Mammedov PCI_EXP_SLTSTA_PDS);
560df72184eSLaurent Vivier if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA ||
561df72184eSLaurent Vivier (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) {
5622f2b18f6SZheng Xiang pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
5632f2b18f6SZheng Xiang PCI_EXP_LNKSTA_DLLLA);
5642f2b18f6SZheng Xiang }
5656a1e0733SJulia Suvorova pcie_cap_slot_event(hotplug_pdev,
566554f802dSMarcel Apfelbaum PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
567d5daff7dSGerd Hoffmann pcie_cap_update_power(hotplug_pdev);
568a66e657eSIgor Mammedov }
5693f1e1478SCao jin }
570a66e657eSIgor Mammedov
pcie_cap_slot_unplug_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)571a1952d01SDavid Hildenbrand void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
572a1952d01SDavid Hildenbrand Error **errp)
5730d1c7d88SCao jin {
574981c3dcdSMarkus Armbruster qdev_unrealize(dev);
5750d1c7d88SCao jin }
5760d1c7d88SCao jin
pcie_unplug_device(PCIBus * bus,PCIDevice * dev,void * opaque)577a1952d01SDavid Hildenbrand static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
578a1952d01SDavid Hildenbrand {
579a1952d01SDavid Hildenbrand HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev));
580a1952d01SDavid Hildenbrand
581a99c4da9SJens Freimann if (dev->partially_hotplugged) {
582c000a9bdSJens Freimann dev->qdev.pending_deleted_event = false;
583a99c4da9SJens Freimann return;
584a99c4da9SJens Freimann }
585a1952d01SDavid Hildenbrand hotplug_handler_unplug(hotplug_ctrl, DEVICE(dev), &error_abort);
58607578b0aSDavid Hildenbrand object_unparent(OBJECT(dev));
587a1952d01SDavid Hildenbrand }
588a1952d01SDavid Hildenbrand
pcie_cap_slot_do_unplug(PCIDevice * dev)58944242d4dSGerd Hoffmann static void pcie_cap_slot_do_unplug(PCIDevice *dev)
59044242d4dSGerd Hoffmann {
59144242d4dSGerd Hoffmann PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
59244242d4dSGerd Hoffmann uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
59344242d4dSGerd Hoffmann uint32_t lnkcap = pci_get_long(exp_cap + PCI_EXP_LNKCAP);
59444242d4dSGerd Hoffmann
59544242d4dSGerd Hoffmann pci_for_each_device_under_bus(sec_bus, pcie_unplug_device, NULL);
59644242d4dSGerd Hoffmann
59744242d4dSGerd Hoffmann pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
59844242d4dSGerd Hoffmann PCI_EXP_SLTSTA_PDS);
59944242d4dSGerd Hoffmann if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA ||
60044242d4dSGerd Hoffmann (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) {
60144242d4dSGerd Hoffmann pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
60244242d4dSGerd Hoffmann PCI_EXP_LNKSTA_DLLLA);
60344242d4dSGerd Hoffmann }
60444242d4dSGerd Hoffmann pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
60544242d4dSGerd Hoffmann PCI_EXP_SLTSTA_PDC);
60644242d4dSGerd Hoffmann }
60744242d4dSGerd Hoffmann
pcie_cap_slot_unplug_request_cb(HotplugHandler * hotplug_dev,DeviceState * dev,Error ** errp)6085571727aSDavid Hildenbrand void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
60914d5a28fSIgor Mammedov DeviceState *dev, Error **errp)
610a66e657eSIgor Mammedov {
611b9731850SDavid Hildenbrand Error *local_err = NULL;
6120d1c7d88SCao jin PCIDevice *pci_dev = PCI_DEVICE(dev);
613fd56e061SDavid Gibson PCIBus *bus = pci_get_bus(pci_dev);
6140501e1aaSJulia Suvorova PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
6150501e1aaSJulia Suvorova uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
6160501e1aaSJulia Suvorova uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP);
61781124b3cSGerd Hoffmann uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
6180501e1aaSJulia Suvorova
6190501e1aaSJulia Suvorova /* Check if hot-unplug is disabled on the slot */
6200501e1aaSJulia Suvorova if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) {
6210501e1aaSJulia Suvorova error_setg(errp, "Hot-unplug failed: "
6220501e1aaSJulia Suvorova "unsupported by the port device '%s'",
6230501e1aaSJulia Suvorova DEVICE(hotplug_pdev)->id);
6240501e1aaSJulia Suvorova return;
6250501e1aaSJulia Suvorova }
626a66e657eSIgor Mammedov
6276a1e0733SJulia Suvorova pcie_cap_slot_plug_common(hotplug_pdev, dev, &local_err);
628b9731850SDavid Hildenbrand if (local_err) {
629b9731850SDavid Hildenbrand error_propagate(errp, local_err);
630b9731850SDavid Hildenbrand return;
631b9731850SDavid Hildenbrand }
632a66e657eSIgor Mammedov
63381124b3cSGerd Hoffmann if ((sltctl & PCI_EXP_SLTCTL_PIC) == PCI_EXP_SLTCTL_PWR_IND_BLINK) {
63481124b3cSGerd Hoffmann error_setg(errp, "Hot-unplug failed: "
63581124b3cSGerd Hoffmann "guest is busy (power indicator blinking)");
63681124b3cSGerd Hoffmann return;
63781124b3cSGerd Hoffmann }
63881124b3cSGerd Hoffmann
639c000a9bdSJens Freimann dev->pending_deleted_event = true;
64018416c62SGerd Hoffmann dev->pending_deleted_expires_ms =
64118416c62SGerd Hoffmann qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 5000; /* 5 secs */
642c000a9bdSJens Freimann
6430d1c7d88SCao jin /* In case user cancel the operation of multi-function hot-add,
6440d1c7d88SCao jin * remove the function that is unexposed to guest individually,
6450d1c7d88SCao jin * without interaction with guest.
6460d1c7d88SCao jin */
6470d1c7d88SCao jin if (pci_dev->devfn &&
6480d1c7d88SCao jin !bus->devices[0]) {
6490d1c7d88SCao jin pcie_unplug_device(bus, pci_dev, NULL);
6500d1c7d88SCao jin
6510d1c7d88SCao jin return;
6520d1c7d88SCao jin }
6530d1c7d88SCao jin
6545aaed9caSVladimir Sementsov-Ogievskiy if (pcie_sltctl_powered_off(sltctl)) {
6550d33415aSGerd Hoffmann /* slot is powered off -> unplug without round-trip to the guest */
6560d33415aSGerd Hoffmann pcie_cap_slot_do_unplug(hotplug_pdev);
6570d33415aSGerd Hoffmann hotplug_event_notify(hotplug_pdev);
6580d33415aSGerd Hoffmann pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
6590d33415aSGerd Hoffmann PCI_EXP_SLTSTA_ABP);
6600d33415aSGerd Hoffmann return;
6610d33415aSGerd Hoffmann }
6620d33415aSGerd Hoffmann
6636a1e0733SJulia Suvorova pcie_cap_slot_push_attention_button(hotplug_pdev);
664315a1350SMichael S. Tsirkin }
665315a1350SMichael S. Tsirkin
666315a1350SMichael S. Tsirkin /* pci express slot for pci express root/downstream port
667315a1350SMichael S. Tsirkin PCI express capability slot registers */
pcie_cap_slot_init(PCIDevice * dev,PCIESlot * s)668530a0963SJulia Suvorova void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s)
669315a1350SMichael S. Tsirkin {
670315a1350SMichael S. Tsirkin uint32_t pos = dev->exp.exp_cap;
671315a1350SMichael S. Tsirkin
672315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_FLAGS,
673315a1350SMichael S. Tsirkin PCI_EXP_FLAGS_SLOT);
674315a1350SMichael S. Tsirkin
675315a1350SMichael S. Tsirkin pci_long_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCAP,
676315a1350SMichael S. Tsirkin ~PCI_EXP_SLTCAP_PSN);
677315a1350SMichael S. Tsirkin pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP,
678530a0963SJulia Suvorova (s->slot << PCI_EXP_SLTCAP_PSN_SHIFT) |
679315a1350SMichael S. Tsirkin PCI_EXP_SLTCAP_EIP |
680315a1350SMichael S. Tsirkin PCI_EXP_SLTCAP_PIP |
681315a1350SMichael S. Tsirkin PCI_EXP_SLTCAP_AIP |
682315a1350SMichael S. Tsirkin PCI_EXP_SLTCAP_ABP);
6833f3cbbb2SJulia Suvorova
6843f3cbbb2SJulia Suvorova /*
6851d77e157SIgor Mammedov * Expose native hot-plug on all bridges if hot-plug is enabled on the slot.
6861d77e157SIgor Mammedov * (unless broken 6.1 ABI is enforced for compat reasons)
6873f3cbbb2SJulia Suvorova */
6883f3cbbb2SJulia Suvorova if (s->hotplug &&
6891d77e157SIgor Mammedov (!s->hide_native_hotplug_cap || DEVICE(dev)->hotplugged)) {
690530a0963SJulia Suvorova pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP,
691530a0963SJulia Suvorova PCI_EXP_SLTCAP_HPS |
692530a0963SJulia Suvorova PCI_EXP_SLTCAP_HPC);
693530a0963SJulia Suvorova }
694315a1350SMichael S. Tsirkin
695f23b6bdcSMarcel Apfelbaum if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) {
696f23b6bdcSMarcel Apfelbaum pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP,
697f23b6bdcSMarcel Apfelbaum PCI_EXP_SLTCAP_PCP);
698f23b6bdcSMarcel Apfelbaum pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL,
699f23b6bdcSMarcel Apfelbaum PCI_EXP_SLTCTL_PCC);
700f23b6bdcSMarcel Apfelbaum pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
701f23b6bdcSMarcel Apfelbaum PCI_EXP_SLTCTL_PCC);
702f23b6bdcSMarcel Apfelbaum }
703f23b6bdcSMarcel Apfelbaum
704315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL,
705315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_PIC |
706315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_AIC);
707315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCTL,
7080a80f1cdSVladimir Sementsov-Ogievskiy PCI_EXP_SLTCTL_PWR_IND_OFF |
7090a80f1cdSVladimir Sementsov-Ogievskiy PCI_EXP_SLTCTL_ATTN_IND_OFF);
710315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
711315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_PIC |
712315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_AIC |
713315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_HPIE |
714315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_CCIE |
715315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_PDCE |
716315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_ABPE);
717315a1350SMichael S. Tsirkin /* Although reading PCI_EXP_SLTCTL_EIC returns always 0,
718315a1350SMichael S. Tsirkin * make the bit writable here in order to detect 1b is written.
719315a1350SMichael S. Tsirkin * pcie_cap_slot_write_config() test-and-clear the bit, so
720315a1350SMichael S. Tsirkin * this bit always returns 0 to the guest.
721315a1350SMichael S. Tsirkin */
722315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
723315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_EIC);
724315a1350SMichael S. Tsirkin
725315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_SLTSTA,
726315a1350SMichael S. Tsirkin PCI_EXP_HP_EV_SUPPORTED);
727315a1350SMichael S. Tsirkin
728625b370cSLeonardo Bras /* Avoid migration abortion when this device hot-removed by guest */
729625b370cSLeonardo Bras pci_word_test_and_clear_mask(dev->cmask + pos + PCI_EXP_SLTSTA,
730625b370cSLeonardo Bras PCI_EXP_SLTSTA_PDS);
731625b370cSLeonardo Bras
732315a1350SMichael S. Tsirkin dev->exp.hpev_notified = false;
733315a1350SMichael S. Tsirkin
734a66e657eSIgor Mammedov qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))),
7359bc6bfdfSMarkus Armbruster OBJECT(dev));
736315a1350SMichael S. Tsirkin }
737315a1350SMichael S. Tsirkin
pcie_cap_slot_reset(PCIDevice * dev)738315a1350SMichael S. Tsirkin void pcie_cap_slot_reset(PCIDevice *dev)
739315a1350SMichael S. Tsirkin {
740315a1350SMichael S. Tsirkin uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
741f23b6bdcSMarcel Apfelbaum uint8_t port_type = pcie_cap_get_type(dev);
742f23b6bdcSMarcel Apfelbaum
743f23b6bdcSMarcel Apfelbaum assert(port_type == PCI_EXP_TYPE_DOWNSTREAM ||
744f23b6bdcSMarcel Apfelbaum port_type == PCI_EXP_TYPE_ROOT_PORT);
745315a1350SMichael S. Tsirkin
746315a1350SMichael S. Tsirkin PCIE_DEV_PRINTF(dev, "reset\n");
747315a1350SMichael S. Tsirkin
748315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
749315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_EIC |
750315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_PIC |
751315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_AIC |
752315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_HPIE |
753315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_CCIE |
754315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_PDCE |
755315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_ABPE);
756315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL,
7571768e97bSVladimir Sementsov-Ogievskiy PCI_EXP_SLTCTL_PWR_IND_OFF |
7580a80f1cdSVladimir Sementsov-Ogievskiy PCI_EXP_SLTCTL_ATTN_IND_OFF);
759315a1350SMichael S. Tsirkin
760f23b6bdcSMarcel Apfelbaum if (dev->cap_present & QEMU_PCIE_SLTCAP_PCP) {
761f23b6bdcSMarcel Apfelbaum /* Downstream ports enforce device number 0. */
76220de98afSMichael S. Tsirkin bool populated = pci_bridge_get_sec_bus(PCI_BRIDGE(dev))->devices[0];
76320de98afSMichael S. Tsirkin uint16_t pic;
764f23b6bdcSMarcel Apfelbaum
765f23b6bdcSMarcel Apfelbaum if (populated) {
766f23b6bdcSMarcel Apfelbaum pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
767f23b6bdcSMarcel Apfelbaum PCI_EXP_SLTCTL_PCC);
768f23b6bdcSMarcel Apfelbaum } else {
769f23b6bdcSMarcel Apfelbaum pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL,
770f23b6bdcSMarcel Apfelbaum PCI_EXP_SLTCTL_PCC);
771f23b6bdcSMarcel Apfelbaum }
772f23b6bdcSMarcel Apfelbaum
7730a80f1cdSVladimir Sementsov-Ogievskiy pic = populated ?
7740a80f1cdSVladimir Sementsov-Ogievskiy PCI_EXP_SLTCTL_PWR_IND_ON : PCI_EXP_SLTCTL_PWR_IND_OFF;
775f23b6bdcSMarcel Apfelbaum pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL, pic);
776f23b6bdcSMarcel Apfelbaum }
777f23b6bdcSMarcel Apfelbaum
778315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
779315a1350SMichael S. Tsirkin PCI_EXP_SLTSTA_EIS |/* on reset,
780315a1350SMichael S. Tsirkin the lock is released */
781315a1350SMichael S. Tsirkin PCI_EXP_SLTSTA_CC |
782315a1350SMichael S. Tsirkin PCI_EXP_SLTSTA_PDC |
783315a1350SMichael S. Tsirkin PCI_EXP_SLTSTA_ABP);
784315a1350SMichael S. Tsirkin
785d5daff7dSGerd Hoffmann pcie_cap_update_power(dev);
786315a1350SMichael S. Tsirkin hotplug_event_update_event_status(dev);
787315a1350SMichael S. Tsirkin }
788315a1350SMichael S. Tsirkin
pcie_cap_slot_get(PCIDevice * dev,uint16_t * slt_ctl,uint16_t * slt_sta)7892841ab43SMichael S. Tsirkin void pcie_cap_slot_get(PCIDevice *dev, uint16_t *slt_ctl, uint16_t *slt_sta)
7902841ab43SMichael S. Tsirkin {
7912841ab43SMichael S. Tsirkin uint32_t pos = dev->exp.exp_cap;
7922841ab43SMichael S. Tsirkin uint8_t *exp_cap = dev->config + pos;
7932841ab43SMichael S. Tsirkin *slt_ctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
7942841ab43SMichael S. Tsirkin *slt_sta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
7952841ab43SMichael S. Tsirkin }
7962841ab43SMichael S. Tsirkin
find_child_fn(PCIBus * bus,PCIDevice * dev,void * opaque)79786f0aa1dSVladimir Sementsov-Ogievskiy static void find_child_fn(PCIBus *bus, PCIDevice *dev, void *opaque)
79886f0aa1dSVladimir Sementsov-Ogievskiy {
79986f0aa1dSVladimir Sementsov-Ogievskiy PCIDevice **child = opaque;
80086f0aa1dSVladimir Sementsov-Ogievskiy
80186f0aa1dSVladimir Sementsov-Ogievskiy if (!*child) {
80286f0aa1dSVladimir Sementsov-Ogievskiy *child = dev;
80386f0aa1dSVladimir Sementsov-Ogievskiy }
80486f0aa1dSVladimir Sementsov-Ogievskiy }
80586f0aa1dSVladimir Sementsov-Ogievskiy
80686f0aa1dSVladimir Sementsov-Ogievskiy /*
80786f0aa1dSVladimir Sementsov-Ogievskiy * Returns the plugged device or first function of multifunction plugged device
80886f0aa1dSVladimir Sementsov-Ogievskiy */
pcie_cap_slot_find_child(PCIDevice * dev)80986f0aa1dSVladimir Sementsov-Ogievskiy static PCIDevice *pcie_cap_slot_find_child(PCIDevice *dev)
81086f0aa1dSVladimir Sementsov-Ogievskiy {
81186f0aa1dSVladimir Sementsov-Ogievskiy PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
81286f0aa1dSVladimir Sementsov-Ogievskiy PCIDevice *child = NULL;
81386f0aa1dSVladimir Sementsov-Ogievskiy
81486f0aa1dSVladimir Sementsov-Ogievskiy pci_for_each_device(sec_bus, pci_bus_num(sec_bus), find_child_fn, &child);
81586f0aa1dSVladimir Sementsov-Ogievskiy
81686f0aa1dSVladimir Sementsov-Ogievskiy return child;
81786f0aa1dSVladimir Sementsov-Ogievskiy }
81886f0aa1dSVladimir Sementsov-Ogievskiy
pcie_cap_slot_write_config(PCIDevice * dev,uint16_t old_slt_ctl,uint16_t old_slt_sta,uint32_t addr,uint32_t val,int len)819d85d65ccSMichael S. Tsirkin void pcie_cap_slot_write_config(PCIDevice *dev,
820d85d65ccSMichael S. Tsirkin uint16_t old_slt_ctl, uint16_t old_slt_sta,
821315a1350SMichael S. Tsirkin uint32_t addr, uint32_t val, int len)
822315a1350SMichael S. Tsirkin {
823315a1350SMichael S. Tsirkin uint32_t pos = dev->exp.exp_cap;
824315a1350SMichael S. Tsirkin uint8_t *exp_cap = dev->config + pos;
825315a1350SMichael S. Tsirkin uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
826315a1350SMichael S. Tsirkin
827315a1350SMichael S. Tsirkin if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) {
828110c477cSMichael S. Tsirkin /*
829110c477cSMichael S. Tsirkin * Guests tend to clears all bits during init.
830110c477cSMichael S. Tsirkin * If they clear bits that weren't set this is racy and will lose events:
831110c477cSMichael S. Tsirkin * not a big problem for manual button presses, but a problem for us.
832110c477cSMichael S. Tsirkin * As a work-around, detect this and revert status to what it was
833110c477cSMichael S. Tsirkin * before the write.
834110c477cSMichael S. Tsirkin *
835110c477cSMichael S. Tsirkin * Note: in theory this can be detected as a duplicate button press
836110c477cSMichael S. Tsirkin * which cancels the previous press. Does not seem to happen in
837110c477cSMichael S. Tsirkin * practice as guests seem to only have this bug during init.
838110c477cSMichael S. Tsirkin */
839110c477cSMichael S. Tsirkin #define PCIE_SLOT_EVENTS (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | \
840110c477cSMichael S. Tsirkin PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | \
841110c477cSMichael S. Tsirkin PCI_EXP_SLTSTA_CC)
842110c477cSMichael S. Tsirkin
843d85d65ccSMichael S. Tsirkin if (val & ~old_slt_sta & PCIE_SLOT_EVENTS) {
844d85d65ccSMichael S. Tsirkin sltsta = (sltsta & ~PCIE_SLOT_EVENTS) | (old_slt_sta & PCIE_SLOT_EVENTS);
845110c477cSMichael S. Tsirkin pci_set_word(exp_cap + PCI_EXP_SLTSTA, sltsta);
846110c477cSMichael S. Tsirkin }
847315a1350SMichael S. Tsirkin hotplug_event_clear(dev);
848315a1350SMichael S. Tsirkin }
849315a1350SMichael S. Tsirkin
850315a1350SMichael S. Tsirkin if (!ranges_overlap(addr, len, pos + PCI_EXP_SLTCTL, 2)) {
851315a1350SMichael S. Tsirkin return;
852315a1350SMichael S. Tsirkin }
853315a1350SMichael S. Tsirkin
854315a1350SMichael S. Tsirkin if (pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
855315a1350SMichael S. Tsirkin PCI_EXP_SLTCTL_EIC)) {
856315a1350SMichael S. Tsirkin sltsta ^= PCI_EXP_SLTSTA_EIS; /* toggle PCI_EXP_SLTSTA_EIS bit */
857315a1350SMichael S. Tsirkin pci_set_word(exp_cap + PCI_EXP_SLTSTA, sltsta);
858315a1350SMichael S. Tsirkin PCIE_DEV_PRINTF(dev, "PCI_EXP_SLTCTL_EIC: "
859315a1350SMichael S. Tsirkin "sltsta -> 0x%02"PRIx16"\n",
860315a1350SMichael S. Tsirkin sltsta);
861315a1350SMichael S. Tsirkin }
862315a1350SMichael S. Tsirkin
86386f0aa1dSVladimir Sementsov-Ogievskiy if (trace_event_get_state_backends(TRACE_PCIE_CAP_SLOT_WRITE_CONFIG)) {
86486f0aa1dSVladimir Sementsov-Ogievskiy DeviceState *parent = DEVICE(dev);
86586f0aa1dSVladimir Sementsov-Ogievskiy DeviceState *child = DEVICE(pcie_cap_slot_find_child(dev));
86686f0aa1dSVladimir Sementsov-Ogievskiy
86786f0aa1dSVladimir Sementsov-Ogievskiy trace_pcie_cap_slot_write_config(
86886f0aa1dSVladimir Sementsov-Ogievskiy parent->canonical_path,
86986f0aa1dSVladimir Sementsov-Ogievskiy child ? child->canonical_path : "no-child",
87086f0aa1dSVladimir Sementsov-Ogievskiy (sltsta & PCI_EXP_SLTSTA_PDS) ? "present" : "not present",
87186f0aa1dSVladimir Sementsov-Ogievskiy pcie_led_state_to_str(old_slt_ctl & PCI_EXP_SLTCTL_PIC),
87286f0aa1dSVladimir Sementsov-Ogievskiy pcie_led_state_to_str(val & PCI_EXP_SLTCTL_PIC),
87386f0aa1dSVladimir Sementsov-Ogievskiy pcie_led_state_to_str(old_slt_ctl & PCI_EXP_SLTCTL_AIC),
87486f0aa1dSVladimir Sementsov-Ogievskiy pcie_led_state_to_str(val & PCI_EXP_SLTCTL_AIC),
87586f0aa1dSVladimir Sementsov-Ogievskiy (old_slt_ctl & PCI_EXP_SLTCTL_PWR_OFF) ? "off" : "on",
87686f0aa1dSVladimir Sementsov-Ogievskiy (val & PCI_EXP_SLTCTL_PWR_OFF) ? "off" : "on");
87786f0aa1dSVladimir Sementsov-Ogievskiy }
87886f0aa1dSVladimir Sementsov-Ogievskiy
879554f802dSMarcel Apfelbaum /*
880d85d65ccSMichael S. Tsirkin * If the slot is populated, power indicator is off and power
881554f802dSMarcel Apfelbaum * controller is off, it is safe to detach the devices.
882d85d65ccSMichael S. Tsirkin *
883d85d65ccSMichael S. Tsirkin * Note: don't detach if condition was already true:
884d85d65ccSMichael S. Tsirkin * this is a work around for guests that overwrite
885d85d65ccSMichael S. Tsirkin * control of powered off slots before powering them on.
886554f802dSMarcel Apfelbaum */
8875aaed9caSVladimir Sementsov-Ogievskiy if ((sltsta & PCI_EXP_SLTSTA_PDS) && pcie_sltctl_powered_off(val) &&
8885aaed9caSVladimir Sementsov-Ogievskiy !pcie_sltctl_powered_off(old_slt_ctl))
8895aaed9caSVladimir Sementsov-Ogievskiy {
89044242d4dSGerd Hoffmann pcie_cap_slot_do_unplug(dev);
891554f802dSMarcel Apfelbaum }
892d5daff7dSGerd Hoffmann pcie_cap_update_power(dev);
893554f802dSMarcel Apfelbaum
894315a1350SMichael S. Tsirkin hotplug_event_notify(dev);
895315a1350SMichael S. Tsirkin
896315a1350SMichael S. Tsirkin /*
897315a1350SMichael S. Tsirkin * 6.7.3.2 Command Completed Events
898315a1350SMichael S. Tsirkin *
899315a1350SMichael S. Tsirkin * Software issues a command to a hot-plug capable Downstream Port by
900315a1350SMichael S. Tsirkin * issuing a write transaction that targets any portion of the Port’s Slot
901315a1350SMichael S. Tsirkin * Control register. A single write to the Slot Control register is
902315a1350SMichael S. Tsirkin * considered to be a single command, even if the write affects more than
903315a1350SMichael S. Tsirkin * one field in the Slot Control register. In response to this transaction,
904315a1350SMichael S. Tsirkin * the Port must carry out the requested actions and then set the
905315a1350SMichael S. Tsirkin * associated status field for the command completed event. */
906315a1350SMichael S. Tsirkin
907315a1350SMichael S. Tsirkin /* Real hardware might take a while to complete requested command because
908315a1350SMichael S. Tsirkin * physical movement would be involved like locking the electromechanical
909315a1350SMichael S. Tsirkin * lock. However in our case, command is completed instantaneously above,
910315a1350SMichael S. Tsirkin * so send a command completion event right now.
911315a1350SMichael S. Tsirkin */
912315a1350SMichael S. Tsirkin pcie_cap_slot_event(dev, PCI_EXP_HP_EV_CCI);
913315a1350SMichael S. Tsirkin }
914315a1350SMichael S. Tsirkin
pcie_cap_slot_post_load(void * opaque,int version_id)915315a1350SMichael S. Tsirkin int pcie_cap_slot_post_load(void *opaque, int version_id)
916315a1350SMichael S. Tsirkin {
917315a1350SMichael S. Tsirkin PCIDevice *dev = opaque;
918315a1350SMichael S. Tsirkin hotplug_event_update_event_status(dev);
919d5daff7dSGerd Hoffmann pcie_cap_update_power(dev);
920315a1350SMichael S. Tsirkin return 0;
921315a1350SMichael S. Tsirkin }
922315a1350SMichael S. Tsirkin
pcie_cap_slot_push_attention_button(PCIDevice * dev)923315a1350SMichael S. Tsirkin void pcie_cap_slot_push_attention_button(PCIDevice *dev)
924315a1350SMichael S. Tsirkin {
925315a1350SMichael S. Tsirkin pcie_cap_slot_event(dev, PCI_EXP_HP_EV_ABP);
926315a1350SMichael S. Tsirkin }
927315a1350SMichael S. Tsirkin
928315a1350SMichael S. Tsirkin /* root control/capabilities/status. PME isn't emulated for now */
pcie_cap_root_init(PCIDevice * dev)929315a1350SMichael S. Tsirkin void pcie_cap_root_init(PCIDevice *dev)
930315a1350SMichael S. Tsirkin {
931315a1350SMichael S. Tsirkin pci_set_word(dev->wmask + dev->exp.exp_cap + PCI_EXP_RTCTL,
932315a1350SMichael S. Tsirkin PCI_EXP_RTCTL_SECEE | PCI_EXP_RTCTL_SENFEE |
933315a1350SMichael S. Tsirkin PCI_EXP_RTCTL_SEFEE);
934315a1350SMichael S. Tsirkin }
935315a1350SMichael S. Tsirkin
pcie_cap_root_reset(PCIDevice * dev)936315a1350SMichael S. Tsirkin void pcie_cap_root_reset(PCIDevice *dev)
937315a1350SMichael S. Tsirkin {
938315a1350SMichael S. Tsirkin pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_RTCTL, 0);
939315a1350SMichael S. Tsirkin }
940315a1350SMichael S. Tsirkin
941315a1350SMichael S. Tsirkin /* function level reset(FLR) */
pcie_cap_flr_init(PCIDevice * dev)942315a1350SMichael S. Tsirkin void pcie_cap_flr_init(PCIDevice *dev)
943315a1350SMichael S. Tsirkin {
944315a1350SMichael S. Tsirkin pci_long_test_and_set_mask(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCAP,
945315a1350SMichael S. Tsirkin PCI_EXP_DEVCAP_FLR);
946315a1350SMichael S. Tsirkin
947315a1350SMichael S. Tsirkin /* Although reading BCR_FLR returns always 0,
948315a1350SMichael S. Tsirkin * the bit is made writable here in order to detect the 1b is written
949315a1350SMichael S. Tsirkin * pcie_cap_flr_write_config() test-and-clear the bit, so
950315a1350SMichael S. Tsirkin * this bit always returns 0 to the guest.
951315a1350SMichael S. Tsirkin */
952315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->wmask + dev->exp.exp_cap + PCI_EXP_DEVCTL,
953315a1350SMichael S. Tsirkin PCI_EXP_DEVCTL_BCR_FLR);
954315a1350SMichael S. Tsirkin }
955315a1350SMichael S. Tsirkin
pcie_cap_flr_write_config(PCIDevice * dev,uint32_t addr,uint32_t val,int len)956315a1350SMichael S. Tsirkin void pcie_cap_flr_write_config(PCIDevice *dev,
957315a1350SMichael S. Tsirkin uint32_t addr, uint32_t val, int len)
958315a1350SMichael S. Tsirkin {
959315a1350SMichael S. Tsirkin uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL;
960315a1350SMichael S. Tsirkin if (pci_get_word(devctl) & PCI_EXP_DEVCTL_BCR_FLR) {
961315a1350SMichael S. Tsirkin /* Clear PCI_EXP_DEVCTL_BCR_FLR after invoking the reset handler
962315a1350SMichael S. Tsirkin so the handler can detect FLR by looking at this bit. */
963315a1350SMichael S. Tsirkin pci_device_reset(dev);
964315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(devctl, PCI_EXP_DEVCTL_BCR_FLR);
965315a1350SMichael S. Tsirkin }
966315a1350SMichael S. Tsirkin }
967315a1350SMichael S. Tsirkin
968821be9dbSKnut Omang /* Alternative Routing-ID Interpretation (ARI)
969821be9dbSKnut Omang * forwarding support for root and downstream ports
970821be9dbSKnut Omang */
pcie_cap_arifwd_init(PCIDevice * dev)971821be9dbSKnut Omang void pcie_cap_arifwd_init(PCIDevice *dev)
972315a1350SMichael S. Tsirkin {
973315a1350SMichael S. Tsirkin uint32_t pos = dev->exp.exp_cap;
974315a1350SMichael S. Tsirkin pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP2,
975315a1350SMichael S. Tsirkin PCI_EXP_DEVCAP2_ARI);
976315a1350SMichael S. Tsirkin pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_DEVCTL2,
977315a1350SMichael S. Tsirkin PCI_EXP_DEVCTL2_ARI);
978315a1350SMichael S. Tsirkin }
979315a1350SMichael S. Tsirkin
pcie_cap_arifwd_reset(PCIDevice * dev)980821be9dbSKnut Omang void pcie_cap_arifwd_reset(PCIDevice *dev)
981315a1350SMichael S. Tsirkin {
982315a1350SMichael S. Tsirkin uint8_t *devctl2 = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2;
983315a1350SMichael S. Tsirkin pci_long_test_and_clear_mask(devctl2, PCI_EXP_DEVCTL2_ARI);
984315a1350SMichael S. Tsirkin }
985315a1350SMichael S. Tsirkin
pcie_cap_is_arifwd_enabled(const PCIDevice * dev)986821be9dbSKnut Omang bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev)
987315a1350SMichael S. Tsirkin {
988315a1350SMichael S. Tsirkin if (!pci_is_express(dev)) {
989315a1350SMichael S. Tsirkin return false;
990315a1350SMichael S. Tsirkin }
991315a1350SMichael S. Tsirkin if (!dev->exp.exp_cap) {
992315a1350SMichael S. Tsirkin return false;
993315a1350SMichael S. Tsirkin }
994315a1350SMichael S. Tsirkin
995315a1350SMichael S. Tsirkin return pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
996315a1350SMichael S. Tsirkin PCI_EXP_DEVCTL2_ARI;
997315a1350SMichael S. Tsirkin }
998315a1350SMichael S. Tsirkin
999315a1350SMichael S. Tsirkin /**************************************************************************
10004d5e17a5SGonglei * pci express extended capability list management functions
1001315a1350SMichael S. Tsirkin * uint16_t ext_cap_id (16 bit)
1002315a1350SMichael S. Tsirkin * uint8_t cap_ver (4 bit)
1003315a1350SMichael S. Tsirkin * uint16_t cap_offset (12 bit)
1004315a1350SMichael S. Tsirkin * uint16_t ext_cap_size
1005315a1350SMichael S. Tsirkin */
1006315a1350SMichael S. Tsirkin
10074bb571d8SMichael S. Tsirkin /* Passing a cap_id value > 0xffff will return 0 and put end of list in prev */
pcie_find_capability_list(PCIDevice * dev,uint32_t cap_id,uint16_t * prev_p)10084bb571d8SMichael S. Tsirkin static uint16_t pcie_find_capability_list(PCIDevice *dev, uint32_t cap_id,
1009315a1350SMichael S. Tsirkin uint16_t *prev_p)
1010315a1350SMichael S. Tsirkin {
1011315a1350SMichael S. Tsirkin uint16_t prev = 0;
1012315a1350SMichael S. Tsirkin uint16_t next;
1013315a1350SMichael S. Tsirkin uint32_t header = pci_get_long(dev->config + PCI_CONFIG_SPACE_SIZE);
1014315a1350SMichael S. Tsirkin
1015315a1350SMichael S. Tsirkin if (!header) {
1016315a1350SMichael S. Tsirkin /* no extended capability */
1017315a1350SMichael S. Tsirkin next = 0;
1018315a1350SMichael S. Tsirkin goto out;
1019315a1350SMichael S. Tsirkin }
1020315a1350SMichael S. Tsirkin for (next = PCI_CONFIG_SPACE_SIZE; next;
1021315a1350SMichael S. Tsirkin prev = next, next = PCI_EXT_CAP_NEXT(header)) {
1022315a1350SMichael S. Tsirkin
1023315a1350SMichael S. Tsirkin assert(next >= PCI_CONFIG_SPACE_SIZE);
1024315a1350SMichael S. Tsirkin assert(next <= PCIE_CONFIG_SPACE_SIZE - 8);
1025315a1350SMichael S. Tsirkin
1026315a1350SMichael S. Tsirkin header = pci_get_long(dev->config + next);
1027315a1350SMichael S. Tsirkin if (PCI_EXT_CAP_ID(header) == cap_id) {
1028315a1350SMichael S. Tsirkin break;
1029315a1350SMichael S. Tsirkin }
1030315a1350SMichael S. Tsirkin }
1031315a1350SMichael S. Tsirkin
1032315a1350SMichael S. Tsirkin out:
1033315a1350SMichael S. Tsirkin if (prev_p) {
1034315a1350SMichael S. Tsirkin *prev_p = prev;
1035315a1350SMichael S. Tsirkin }
1036315a1350SMichael S. Tsirkin return next;
1037315a1350SMichael S. Tsirkin }
1038315a1350SMichael S. Tsirkin
pcie_find_capability(PCIDevice * dev,uint16_t cap_id)1039315a1350SMichael S. Tsirkin uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id)
1040315a1350SMichael S. Tsirkin {
1041315a1350SMichael S. Tsirkin return pcie_find_capability_list(dev, cap_id, NULL);
1042315a1350SMichael S. Tsirkin }
1043315a1350SMichael S. Tsirkin
pcie_ext_cap_set_next(PCIDevice * dev,uint16_t pos,uint16_t next)1044315a1350SMichael S. Tsirkin static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next)
1045315a1350SMichael S. Tsirkin {
1046812d2594SKnut Omang uint32_t header = pci_get_long(dev->config + pos);
1047315a1350SMichael S. Tsirkin assert(!(next & (PCI_EXT_CAP_ALIGN - 1)));
1048315a1350SMichael S. Tsirkin header = (header & ~PCI_EXT_CAP_NEXT_MASK) |
1049315a1350SMichael S. Tsirkin ((next << PCI_EXT_CAP_NEXT_SHIFT) & PCI_EXT_CAP_NEXT_MASK);
1050315a1350SMichael S. Tsirkin pci_set_long(dev->config + pos, header);
1051315a1350SMichael S. Tsirkin }
1052315a1350SMichael S. Tsirkin
1053315a1350SMichael S. Tsirkin /*
1054d62d1eb6SCao jin * Caller must supply valid (offset, size) such that the range wouldn't
1055315a1350SMichael S. Tsirkin * overlap with other capability or other registers.
1056315a1350SMichael S. Tsirkin * This function doesn't check it.
1057315a1350SMichael S. Tsirkin */
pcie_add_capability(PCIDevice * dev,uint16_t cap_id,uint8_t cap_ver,uint16_t offset,uint16_t size)1058315a1350SMichael S. Tsirkin void pcie_add_capability(PCIDevice *dev,
1059315a1350SMichael S. Tsirkin uint16_t cap_id, uint8_t cap_ver,
1060315a1350SMichael S. Tsirkin uint16_t offset, uint16_t size)
1061315a1350SMichael S. Tsirkin {
1062315a1350SMichael S. Tsirkin assert(offset >= PCI_CONFIG_SPACE_SIZE);
1063bacf58caSDaniella Lee assert(offset < (uint16_t)(offset + size));
1064bacf58caSDaniella Lee assert((uint16_t)(offset + size) <= PCIE_CONFIG_SPACE_SIZE);
1065315a1350SMichael S. Tsirkin assert(size >= 8);
1066315a1350SMichael S. Tsirkin assert(pci_is_express(dev));
1067315a1350SMichael S. Tsirkin
1068d4e9b75aSPeter Xu if (offset != PCI_CONFIG_SPACE_SIZE) {
1069315a1350SMichael S. Tsirkin uint16_t prev;
1070315a1350SMichael S. Tsirkin
10714bb571d8SMichael S. Tsirkin /*
10724bb571d8SMichael S. Tsirkin * 0xffffffff is not a valid cap id (it's a 16 bit field). use
10734bb571d8SMichael S. Tsirkin * internally to find the last capability in the linked list.
10744bb571d8SMichael S. Tsirkin */
1075d4e9b75aSPeter Xu pcie_find_capability_list(dev, 0xffffffff, &prev);
1076315a1350SMichael S. Tsirkin assert(prev >= PCI_CONFIG_SPACE_SIZE);
1077315a1350SMichael S. Tsirkin pcie_ext_cap_set_next(dev, prev, offset);
1078315a1350SMichael S. Tsirkin }
1079d4e9b75aSPeter Xu pci_set_long(dev->config + offset, PCI_EXT_CAP(cap_id, cap_ver, 0));
1080315a1350SMichael S. Tsirkin
1081315a1350SMichael S. Tsirkin /* Make capability read-only by default */
1082315a1350SMichael S. Tsirkin memset(dev->wmask + offset, 0, size);
1083315a1350SMichael S. Tsirkin memset(dev->w1cmask + offset, 0, size);
1084315a1350SMichael S. Tsirkin /* Check capability by default */
1085315a1350SMichael S. Tsirkin memset(dev->cmask + offset, 0xFF, size);
1086315a1350SMichael S. Tsirkin }
1087315a1350SMichael S. Tsirkin
1088727b4866SAlex Williamson /*
1089727b4866SAlex Williamson * Sync the PCIe Link Status negotiated speed and width of a bridge with the
1090727b4866SAlex Williamson * downstream device. If downstream device is not present, re-write with the
109188c86919SAlex Williamson * Link Capability fields. If downstream device reports invalid width or
109288c86919SAlex Williamson * speed, replace with minimum values (LnkSta fields are RsvdZ on VFs but such
109388c86919SAlex Williamson * values interfere with PCIe native hotplug detecting new devices). Limit
109488c86919SAlex Williamson * width and speed to bridge capabilities for compatibility. Use config_read
109588c86919SAlex Williamson * to access the downstream device since it could be an assigned device with
109688c86919SAlex Williamson * volatile link information.
1097727b4866SAlex Williamson */
pcie_sync_bridge_lnk(PCIDevice * bridge_dev)1098727b4866SAlex Williamson void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
1099727b4866SAlex Williamson {
1100727b4866SAlex Williamson PCIBridge *br = PCI_BRIDGE(bridge_dev);
1101727b4866SAlex Williamson PCIBus *bus = pci_bridge_get_sec_bus(br);
1102727b4866SAlex Williamson PCIDevice *target = bus->devices[0];
1103727b4866SAlex Williamson uint8_t *exp_cap = bridge_dev->config + bridge_dev->exp.exp_cap;
1104727b4866SAlex Williamson uint16_t lnksta, lnkcap = pci_get_word(exp_cap + PCI_EXP_LNKCAP);
1105727b4866SAlex Williamson
1106727b4866SAlex Williamson if (!target || !target->exp.exp_cap) {
1107727b4866SAlex Williamson lnksta = lnkcap;
1108727b4866SAlex Williamson } else {
1109727b4866SAlex Williamson lnksta = target->config_read(target,
1110727b4866SAlex Williamson target->exp.exp_cap + PCI_EXP_LNKSTA,
1111727b4866SAlex Williamson sizeof(lnksta));
1112727b4866SAlex Williamson
1113727b4866SAlex Williamson if ((lnksta & PCI_EXP_LNKSTA_NLW) > (lnkcap & PCI_EXP_LNKCAP_MLW)) {
1114727b4866SAlex Williamson lnksta &= ~PCI_EXP_LNKSTA_NLW;
1115727b4866SAlex Williamson lnksta |= lnkcap & PCI_EXP_LNKCAP_MLW;
1116727b4866SAlex Williamson }
1117727b4866SAlex Williamson
1118727b4866SAlex Williamson if ((lnksta & PCI_EXP_LNKSTA_CLS) > (lnkcap & PCI_EXP_LNKCAP_SLS)) {
1119727b4866SAlex Williamson lnksta &= ~PCI_EXP_LNKSTA_CLS;
1120727b4866SAlex Williamson lnksta |= lnkcap & PCI_EXP_LNKCAP_SLS;
1121727b4866SAlex Williamson }
1122727b4866SAlex Williamson }
1123727b4866SAlex Williamson
1124*91b2cb9aSSebastian Ott if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
1125*91b2cb9aSSebastian Ott lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
1126*91b2cb9aSSebastian Ott }
1127*91b2cb9aSSebastian Ott
1128*91b2cb9aSSebastian Ott if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
1129*91b2cb9aSSebastian Ott lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
1130*91b2cb9aSSebastian Ott }
1131*91b2cb9aSSebastian Ott
1132727b4866SAlex Williamson pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
1133727b4866SAlex Williamson PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW);
1134727b4866SAlex Williamson pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, lnksta &
1135727b4866SAlex Williamson (PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW));
1136727b4866SAlex Williamson }
1137727b4866SAlex Williamson
1138315a1350SMichael S. Tsirkin /**************************************************************************
1139315a1350SMichael S. Tsirkin * pci express extended capability helper functions
1140315a1350SMichael S. Tsirkin */
1141315a1350SMichael S. Tsirkin
1142315a1350SMichael S. Tsirkin /* ARI */
pcie_ari_init(PCIDevice * dev,uint16_t offset)1143445416e3SAkihiko Odaki void pcie_ari_init(PCIDevice *dev, uint16_t offset)
1144315a1350SMichael S. Tsirkin {
11457c228c5fSAkihiko Odaki uint16_t nextfn = dev->cap_present & QEMU_PCIE_ARI_NEXTFN_1 ? 1 : 0;
1146445416e3SAkihiko Odaki
1147315a1350SMichael S. Tsirkin pcie_add_capability(dev, PCI_EXT_CAP_ID_ARI, PCI_ARI_VER,
1148315a1350SMichael S. Tsirkin offset, PCI_ARI_SIZEOF);
1149ec70b46bSKnut Omang pci_set_long(dev->config + offset + PCI_ARI_CAP, (nextfn & 0xff) << 8);
1150315a1350SMichael S. Tsirkin }
1151b56b9285SDmitry Fleytman
pcie_dev_ser_num_init(PCIDevice * dev,uint16_t offset,uint64_t ser_num)1152b56b9285SDmitry Fleytman void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num)
1153b56b9285SDmitry Fleytman {
1154b56b9285SDmitry Fleytman static const int pci_dsn_ver = 1;
1155b56b9285SDmitry Fleytman static const int pci_dsn_cap = 4;
1156b56b9285SDmitry Fleytman
1157b56b9285SDmitry Fleytman pcie_add_capability(dev, PCI_EXT_CAP_ID_DSN, pci_dsn_ver, offset,
1158b56b9285SDmitry Fleytman PCI_EXT_CAP_DSN_SIZEOF);
1159b56b9285SDmitry Fleytman pci_set_quad(dev->config + offset + pci_dsn_cap, ser_num);
1160b56b9285SDmitry Fleytman }
1161615c4ed2SJason Wang
pcie_ats_init(PCIDevice * dev,uint16_t offset,bool aligned)1162d83f46d1SJason Wang void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned)
1163615c4ed2SJason Wang {
1164615c4ed2SJason Wang pcie_add_capability(dev, PCI_EXT_CAP_ID_ATS, 0x1,
1165615c4ed2SJason Wang offset, PCI_EXT_CAP_ATS_SIZEOF);
1166615c4ed2SJason Wang
1167615c4ed2SJason Wang dev->exp.ats_cap = offset;
1168615c4ed2SJason Wang
1169d83f46d1SJason Wang /* Invalidate Queue Depth 0 */
1170d83f46d1SJason Wang if (aligned) {
11714c708753SJason Wang pci_set_word(dev->config + offset + PCI_ATS_CAP,
11724c708753SJason Wang PCI_ATS_CAP_PAGE_ALIGNED);
1173d83f46d1SJason Wang }
1174615c4ed2SJason Wang /* STU 0, Disabled by default */
1175615c4ed2SJason Wang pci_set_word(dev->config + offset + PCI_ATS_CTRL, 0);
1176615c4ed2SJason Wang
1177615c4ed2SJason Wang pci_set_word(dev->wmask + dev->exp.ats_cap + PCI_ATS_CTRL, 0x800f);
1178615c4ed2SJason Wang }
1179db891a9bSKnut Omang
1180db891a9bSKnut Omang /* ACS (Access Control Services) */
pcie_acs_init(PCIDevice * dev,uint16_t offset)1181db891a9bSKnut Omang void pcie_acs_init(PCIDevice *dev, uint16_t offset)
1182db891a9bSKnut Omang {
1183db891a9bSKnut Omang bool is_downstream = pci_is_express_downstream_port(dev);
1184db891a9bSKnut Omang uint16_t cap_bits = 0;
1185db891a9bSKnut Omang
1186db891a9bSKnut Omang /* For endpoints, only multifunction devs may have an ACS capability: */
1187db891a9bSKnut Omang assert(is_downstream ||
1188db891a9bSKnut Omang (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) ||
1189db891a9bSKnut Omang PCI_FUNC(dev->devfn));
1190db891a9bSKnut Omang
1191db891a9bSKnut Omang pcie_add_capability(dev, PCI_EXT_CAP_ID_ACS, PCI_ACS_VER, offset,
1192db891a9bSKnut Omang PCI_ACS_SIZEOF);
1193db891a9bSKnut Omang dev->exp.acs_cap = offset;
1194db891a9bSKnut Omang
1195db891a9bSKnut Omang if (is_downstream) {
1196db891a9bSKnut Omang /*
1197db891a9bSKnut Omang * Downstream ports must implement SV, TB, RR, CR, UF, and DT (with
1198db891a9bSKnut Omang * caveats on the latter four that we ignore for simplicity).
1199db891a9bSKnut Omang * Endpoints may also implement a subset of ACS capabilities,
1200db891a9bSKnut Omang * but these are optional if the endpoint does not support
1201db891a9bSKnut Omang * peer-to-peer between functions and thus omitted here.
1202db891a9bSKnut Omang */
1203db891a9bSKnut Omang cap_bits = PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
1204db891a9bSKnut Omang PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT;
1205db891a9bSKnut Omang }
1206db891a9bSKnut Omang
1207db891a9bSKnut Omang pci_set_word(dev->config + offset + PCI_ACS_CAP, cap_bits);
1208db891a9bSKnut Omang pci_set_word(dev->wmask + offset + PCI_ACS_CTRL, cap_bits);
1209db891a9bSKnut Omang }
1210db891a9bSKnut Omang
pcie_acs_reset(PCIDevice * dev)1211db891a9bSKnut Omang void pcie_acs_reset(PCIDevice *dev)
1212db891a9bSKnut Omang {
1213db891a9bSKnut Omang if (dev->exp.acs_cap) {
1214db891a9bSKnut Omang pci_set_word(dev->config + dev->exp.acs_cap + PCI_ACS_CTRL, 0);
1215db891a9bSKnut Omang }
1216db891a9bSKnut Omang }
1217