Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/riscv/iommu/iommu_pci.c
288972 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2026 Ruslan Bukin <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/types.h>
29
#include <sys/systm.h>
30
#include <sys/bus.h>
31
#include <sys/bitstring.h>
32
#include <sys/kernel.h>
33
#include <sys/rman.h>
34
#include <sys/sysctl.h>
35
#include <sys/tree.h>
36
#include <sys/taskqueue.h>
37
#include <sys/malloc.h>
38
#include <sys/module.h>
39
#include <vm/vm.h>
40
#include <vm/pmap.h>
41
42
#include <machine/bus.h>
43
#include <machine/resource.h>
44
45
#include <dev/pci/pcireg.h>
46
#include <dev/pci/pcivar.h>
47
48
#include <dev/ofw/ofw_bus.h>
49
#include <dev/ofw/ofw_bus_subr.h>
50
51
#include <dev/iommu/iommu.h>
52
#include <riscv/iommu/iommu_pmap.h>
53
#include <riscv/iommu/iommu.h>
54
#include <riscv/iommu/iommu_frontend.h>
55
56
#define PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014
57
#define PCI_VENDOR_ID_REDHAT 0x1b36
58
#define PCI_DEVICE_ID_RIVOS_RISCV_IOMMU_GA 0x0008
59
#define PCI_VENDOR_ID_RIVOS 0x1efd
60
61
static int
62
iommu_pci_probe(device_t dev)
63
{
64
uint16_t vendor_id, device_id;
65
66
vendor_id = pci_get_vendor(dev);
67
device_id = pci_get_device(dev);
68
69
if (vendor_id == PCI_VENDOR_ID_REDHAT &&
70
device_id == PCI_DEVICE_ID_REDHAT_RISCV_IOMMU) {
71
device_set_desc(dev, "RedHat IOMMU");
72
return (BUS_PROBE_DEFAULT);
73
}
74
75
if (vendor_id == PCI_VENDOR_ID_RIVOS &&
76
device_id == PCI_DEVICE_ID_RIVOS_RISCV_IOMMU_GA) {
77
device_set_desc(dev, "Rivos IOMMU");
78
return (BUS_PROBE_DEFAULT);
79
}
80
81
return (ENXIO);
82
}
83
84
static int
85
iommu_pci_attach(device_t dev)
86
{
87
struct riscv_iommu_unit *unit;
88
struct riscv_iommu_softc *sc;
89
struct iommu_unit *iommu;
90
phandle_t node;
91
int count;
92
int error;
93
int rid;
94
int i;
95
96
sc = device_get_softc(dev);
97
sc->dev = dev;
98
99
node = ofw_bus_get_node(dev);
100
101
pci_enable_busmaster(dev);
102
103
rid = PCIR_BAR(0);
104
sc->res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
105
RF_ACTIVE);
106
if (sc->res[0] == NULL) {
107
device_printf(dev, "couldn't map memory\n");
108
goto error;
109
}
110
111
count = 4;
112
if (pci_alloc_msix(dev, &count) == 0) {
113
for (i = 0; i < 4; i++) {
114
rid = i;
115
sc->res[1 + i] = bus_alloc_resource_any(dev,
116
SYS_RES_IRQ, &rid, RF_ACTIVE);
117
if (sc->res[i + 1] == NULL) {
118
device_printf(dev, "Can't allocate IRQ "
119
" resource.\n");
120
goto error;
121
}
122
}
123
} else
124
device_printf(dev, "Can't allocate MSI-X interrupts."
125
" Ignoring.\n");
126
127
error = riscv_iommu_attach(dev);
128
if (error)
129
goto error;
130
131
unit = &sc->unit;
132
unit->dev = dev;
133
134
iommu = &unit->iommu;
135
iommu->dev = dev;
136
137
LIST_INIT(&unit->domain_list);
138
139
sc->xref = OF_xref_from_node(node);
140
141
error = iommu_register(iommu);
142
if (error) {
143
device_printf(dev, "Failed to register RISC-V IOMMU.\n");
144
goto error;
145
}
146
147
return (0);
148
149
error:
150
if (sc->res[0])
151
bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
152
sc->res[0]);
153
154
for (i = 0; i < 4; i++)
155
if (sc->res[i + 1])
156
bus_release_resource(dev, SYS_RES_IRQ, i,
157
sc->res[i + 1]);
158
159
return (error);
160
}
161
162
static device_method_t riscv_iommu_pci_methods[] = {
163
/* Device interface */
164
DEVMETHOD(device_probe, iommu_pci_probe),
165
DEVMETHOD(device_attach, iommu_pci_attach),
166
DEVMETHOD_END
167
};
168
169
DEFINE_CLASS_1(riscv_iommu, riscv_iommu_pci_driver,
170
riscv_iommu_pci_methods, sizeof(struct riscv_iommu_softc),
171
riscv_iommu_driver);
172
DRIVER_MODULE(riscv_iommu, pci, riscv_iommu_pci_driver, NULL, NULL);
173
174