xref: /openbmc/qemu/hw/ppc/spapr_rtas_ddw.c (revision 8e9398e3b1a860b8c29c670c1b6c36afe8d87849)
1ae4de14cSAlexey Kardashevskiy /*
2ae4de14cSAlexey Kardashevskiy  * QEMU sPAPR Dynamic DMA windows support
3ae4de14cSAlexey Kardashevskiy  *
4ae4de14cSAlexey Kardashevskiy  * Copyright (c) 2015 Alexey Kardashevskiy, IBM Corporation.
5ae4de14cSAlexey Kardashevskiy  *
6ae4de14cSAlexey Kardashevskiy  *  This program is free software; you can redistribute it and/or modify
7ae4de14cSAlexey Kardashevskiy  *  it under the terms of the GNU General Public License as published by
8ae4de14cSAlexey Kardashevskiy  *  the Free Software Foundation; either version 2 of the License,
9ae4de14cSAlexey Kardashevskiy  *  or (at your option) any later version.
10ae4de14cSAlexey Kardashevskiy  *
11ae4de14cSAlexey Kardashevskiy  *  This program is distributed in the hope that it will be useful,
12ae4de14cSAlexey Kardashevskiy  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13ae4de14cSAlexey Kardashevskiy  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14ae4de14cSAlexey Kardashevskiy  *  GNU General Public License for more details.
15ae4de14cSAlexey Kardashevskiy  *
16ae4de14cSAlexey Kardashevskiy  *  You should have received a copy of the GNU General Public License
17ae4de14cSAlexey Kardashevskiy  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18ae4de14cSAlexey Kardashevskiy  */
19ae4de14cSAlexey Kardashevskiy 
20ae4de14cSAlexey Kardashevskiy #include "qemu/osdep.h"
21ae4de14cSAlexey Kardashevskiy #include "qemu/error-report.h"
220b8fa32fSMarkus Armbruster #include "qemu/module.h"
23ae4de14cSAlexey Kardashevskiy #include "hw/ppc/spapr.h"
24ae4de14cSAlexey Kardashevskiy #include "hw/pci-host/spapr.h"
25ae4de14cSAlexey Kardashevskiy #include "trace.h"
26ae4de14cSAlexey Kardashevskiy 
spapr_phb_get_active_win_num_cb(Object * child,void * opaque)27ae4de14cSAlexey Kardashevskiy static int spapr_phb_get_active_win_num_cb(Object *child, void *opaque)
28ae4de14cSAlexey Kardashevskiy {
29ce2918cbSDavid Gibson     SpaprTceTable *tcet;
30ae4de14cSAlexey Kardashevskiy 
31ce2918cbSDavid Gibson     tcet = (SpaprTceTable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
32ae4de14cSAlexey Kardashevskiy     if (tcet && tcet->nb_table) {
33ae4de14cSAlexey Kardashevskiy         ++*(unsigned *)opaque;
34ae4de14cSAlexey Kardashevskiy     }
35ae4de14cSAlexey Kardashevskiy     return 0;
36ae4de14cSAlexey Kardashevskiy }
37ae4de14cSAlexey Kardashevskiy 
spapr_phb_get_active_win_num(SpaprPhbState * sphb)38ce2918cbSDavid Gibson static unsigned spapr_phb_get_active_win_num(SpaprPhbState *sphb)
39ae4de14cSAlexey Kardashevskiy {
40ae4de14cSAlexey Kardashevskiy     unsigned ret = 0;
41ae4de14cSAlexey Kardashevskiy 
42ae4de14cSAlexey Kardashevskiy     object_child_foreach(OBJECT(sphb), spapr_phb_get_active_win_num_cb, &ret);
43ae4de14cSAlexey Kardashevskiy 
44ae4de14cSAlexey Kardashevskiy     return ret;
45ae4de14cSAlexey Kardashevskiy }
46ae4de14cSAlexey Kardashevskiy 
spapr_phb_get_free_liobn_cb(Object * child,void * opaque)47ae4de14cSAlexey Kardashevskiy static int spapr_phb_get_free_liobn_cb(Object *child, void *opaque)
48ae4de14cSAlexey Kardashevskiy {
49ce2918cbSDavid Gibson     SpaprTceTable *tcet;
50ae4de14cSAlexey Kardashevskiy 
51ce2918cbSDavid Gibson     tcet = (SpaprTceTable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
52ae4de14cSAlexey Kardashevskiy     if (tcet && !tcet->nb_table) {
53ae4de14cSAlexey Kardashevskiy         *(uint32_t *)opaque = tcet->liobn;
54ae4de14cSAlexey Kardashevskiy         return 1;
55ae4de14cSAlexey Kardashevskiy     }
56ae4de14cSAlexey Kardashevskiy     return 0;
57ae4de14cSAlexey Kardashevskiy }
58ae4de14cSAlexey Kardashevskiy 
spapr_phb_get_free_liobn(SpaprPhbState * sphb)59ce2918cbSDavid Gibson static unsigned spapr_phb_get_free_liobn(SpaprPhbState *sphb)
60ae4de14cSAlexey Kardashevskiy {
61ae4de14cSAlexey Kardashevskiy     uint32_t liobn = 0;
62ae4de14cSAlexey Kardashevskiy 
63ae4de14cSAlexey Kardashevskiy     object_child_foreach(OBJECT(sphb), spapr_phb_get_free_liobn_cb, &liobn);
64ae4de14cSAlexey Kardashevskiy 
65ae4de14cSAlexey Kardashevskiy     return liobn;
66ae4de14cSAlexey Kardashevskiy }
67ae4de14cSAlexey Kardashevskiy 
spapr_page_mask_to_query_mask(uint64_t page_mask)68ae4de14cSAlexey Kardashevskiy static uint32_t spapr_page_mask_to_query_mask(uint64_t page_mask)
69ae4de14cSAlexey Kardashevskiy {
70ae4de14cSAlexey Kardashevskiy     int i;
71ae4de14cSAlexey Kardashevskiy     uint32_t mask = 0;
72ae4de14cSAlexey Kardashevskiy     const struct { int shift; uint32_t mask; } masks[] = {
73ae4de14cSAlexey Kardashevskiy         { 12, RTAS_DDW_PGSIZE_4K },
74ae4de14cSAlexey Kardashevskiy         { 16, RTAS_DDW_PGSIZE_64K },
754c7daca3SAlexey Kardashevskiy         { 21, RTAS_DDW_PGSIZE_2M },
76ae4de14cSAlexey Kardashevskiy         { 24, RTAS_DDW_PGSIZE_16M },
77ae4de14cSAlexey Kardashevskiy         { 25, RTAS_DDW_PGSIZE_32M },
78ae4de14cSAlexey Kardashevskiy         { 26, RTAS_DDW_PGSIZE_64M },
79ae4de14cSAlexey Kardashevskiy         { 27, RTAS_DDW_PGSIZE_128M },
80ae4de14cSAlexey Kardashevskiy         { 28, RTAS_DDW_PGSIZE_256M },
81ae4de14cSAlexey Kardashevskiy         { 34, RTAS_DDW_PGSIZE_16G },
82ae4de14cSAlexey Kardashevskiy     };
83ae4de14cSAlexey Kardashevskiy 
84ae4de14cSAlexey Kardashevskiy     for (i = 0; i < ARRAY_SIZE(masks); ++i) {
85ae4de14cSAlexey Kardashevskiy         if (page_mask & (1ULL << masks[i].shift)) {
86ae4de14cSAlexey Kardashevskiy             mask |= masks[i].mask;
87ae4de14cSAlexey Kardashevskiy         }
88ae4de14cSAlexey Kardashevskiy     }
89ae4de14cSAlexey Kardashevskiy 
90ae4de14cSAlexey Kardashevskiy     return mask;
91ae4de14cSAlexey Kardashevskiy }
92ae4de14cSAlexey Kardashevskiy 
rtas_ibm_query_pe_dma_window(PowerPCCPU * cpu,SpaprMachineState * spapr,uint32_t token,uint32_t nargs,target_ulong args,uint32_t nret,target_ulong rets)93ae4de14cSAlexey Kardashevskiy static void rtas_ibm_query_pe_dma_window(PowerPCCPU *cpu,
94ce2918cbSDavid Gibson                                          SpaprMachineState *spapr,
95ae4de14cSAlexey Kardashevskiy                                          uint32_t token, uint32_t nargs,
96ae4de14cSAlexey Kardashevskiy                                          target_ulong args,
97ae4de14cSAlexey Kardashevskiy                                          uint32_t nret, target_ulong rets)
98ae4de14cSAlexey Kardashevskiy {
99ce2918cbSDavid Gibson     SpaprPhbState *sphb;
1008994e91eSAlexey Kardashevskiy     uint64_t buid;
101ae4de14cSAlexey Kardashevskiy     uint32_t avail, addr, pgmask = 0;
102ae4de14cSAlexey Kardashevskiy 
103*c0e765daSAlexey Kardashevskiy     if ((nargs != 3) || ((nret != 5) && (nret != 6))) {
104ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
105ae4de14cSAlexey Kardashevskiy     }
106ae4de14cSAlexey Kardashevskiy 
107ae4de14cSAlexey Kardashevskiy     buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
108ae4de14cSAlexey Kardashevskiy     addr = rtas_ld(args, 0);
109ae4de14cSAlexey Kardashevskiy     sphb = spapr_pci_find_phb(spapr, buid);
110ae4de14cSAlexey Kardashevskiy     if (!sphb || !sphb->ddw_enabled) {
111ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
112ae4de14cSAlexey Kardashevskiy     }
113ae4de14cSAlexey Kardashevskiy 
114ae4de14cSAlexey Kardashevskiy     /* Translate page mask to LoPAPR format */
115ae4de14cSAlexey Kardashevskiy     pgmask = spapr_page_mask_to_query_mask(sphb->page_size_mask);
116ae4de14cSAlexey Kardashevskiy 
117ae4de14cSAlexey Kardashevskiy     avail = SPAPR_PCI_DMA_MAX_WINDOWS - spapr_phb_get_active_win_num(sphb);
118ae4de14cSAlexey Kardashevskiy 
119ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
120ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 1, avail);
121*c0e765daSAlexey Kardashevskiy     if (nret == 6) {
122*c0e765daSAlexey Kardashevskiy         /*
123*c0e765daSAlexey Kardashevskiy          * Set the Max TCE number as 1<<(58-21) = 0x20.0000.0000
124*c0e765daSAlexey Kardashevskiy          * 1<<59 is the huge window start and 21 is 2M page shift.
125*c0e765daSAlexey Kardashevskiy          */
126*c0e765daSAlexey Kardashevskiy         rtas_st(rets, 2, 0x00000020);
127*c0e765daSAlexey Kardashevskiy         rtas_st(rets, 3, 0x00000000);
128*c0e765daSAlexey Kardashevskiy         rtas_st(rets, 4, pgmask);
129*c0e765daSAlexey Kardashevskiy         rtas_st(rets, 5, 0); /* DMA migration mask, not supported */
130*c0e765daSAlexey Kardashevskiy     } else {
131*c0e765daSAlexey Kardashevskiy         rtas_st(rets, 2, 0x80000000);
132ae4de14cSAlexey Kardashevskiy         rtas_st(rets, 3, pgmask);
133ae4de14cSAlexey Kardashevskiy         rtas_st(rets, 4, 0); /* DMA migration mask, not supported */
134*c0e765daSAlexey Kardashevskiy     }
135ae4de14cSAlexey Kardashevskiy 
1368994e91eSAlexey Kardashevskiy     trace_spapr_iommu_ddw_query(buid, addr, avail, 0x80000000, pgmask);
137ae4de14cSAlexey Kardashevskiy     return;
138ae4de14cSAlexey Kardashevskiy 
139ae4de14cSAlexey Kardashevskiy param_error_exit:
140ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
141ae4de14cSAlexey Kardashevskiy }
142ae4de14cSAlexey Kardashevskiy 
rtas_ibm_create_pe_dma_window(PowerPCCPU * cpu,SpaprMachineState * spapr,uint32_t token,uint32_t nargs,target_ulong args,uint32_t nret,target_ulong rets)143ae4de14cSAlexey Kardashevskiy static void rtas_ibm_create_pe_dma_window(PowerPCCPU *cpu,
144ce2918cbSDavid Gibson                                           SpaprMachineState *spapr,
145ae4de14cSAlexey Kardashevskiy                                           uint32_t token, uint32_t nargs,
146ae4de14cSAlexey Kardashevskiy                                           target_ulong args,
147ae4de14cSAlexey Kardashevskiy                                           uint32_t nret, target_ulong rets)
148ae4de14cSAlexey Kardashevskiy {
149ce2918cbSDavid Gibson     SpaprPhbState *sphb;
150ce2918cbSDavid Gibson     SpaprTceTable *tcet = NULL;
151ae4de14cSAlexey Kardashevskiy     uint32_t addr, page_shift, window_shift, liobn;
152ae4de14cSAlexey Kardashevskiy     uint64_t buid, win_addr;
153ae4de14cSAlexey Kardashevskiy     int windows;
154ae4de14cSAlexey Kardashevskiy 
155ae4de14cSAlexey Kardashevskiy     if ((nargs != 5) || (nret != 4)) {
156ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
157ae4de14cSAlexey Kardashevskiy     }
158ae4de14cSAlexey Kardashevskiy 
159ae4de14cSAlexey Kardashevskiy     buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
160ae4de14cSAlexey Kardashevskiy     addr = rtas_ld(args, 0);
161ae4de14cSAlexey Kardashevskiy     sphb = spapr_pci_find_phb(spapr, buid);
162ae4de14cSAlexey Kardashevskiy     if (!sphb || !sphb->ddw_enabled) {
163ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
164ae4de14cSAlexey Kardashevskiy     }
165ae4de14cSAlexey Kardashevskiy 
166ae4de14cSAlexey Kardashevskiy     page_shift = rtas_ld(args, 3);
167ae4de14cSAlexey Kardashevskiy     window_shift = rtas_ld(args, 4);
168ae4de14cSAlexey Kardashevskiy     liobn = spapr_phb_get_free_liobn(sphb);
169ae4de14cSAlexey Kardashevskiy     windows = spapr_phb_get_active_win_num(sphb);
170ae4de14cSAlexey Kardashevskiy 
171ae4de14cSAlexey Kardashevskiy     if (!(sphb->page_size_mask & (1ULL << page_shift)) ||
172ae4de14cSAlexey Kardashevskiy         (window_shift < page_shift)) {
173ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
174ae4de14cSAlexey Kardashevskiy     }
175ae4de14cSAlexey Kardashevskiy 
176ae4de14cSAlexey Kardashevskiy     if (!liobn || !sphb->ddw_enabled || windows == SPAPR_PCI_DMA_MAX_WINDOWS) {
177ae4de14cSAlexey Kardashevskiy         goto hw_error_exit;
178ae4de14cSAlexey Kardashevskiy     }
179ae4de14cSAlexey Kardashevskiy 
180ae4de14cSAlexey Kardashevskiy     tcet = spapr_tce_find_by_liobn(liobn);
181ae4de14cSAlexey Kardashevskiy     if (!tcet) {
182ae4de14cSAlexey Kardashevskiy         goto hw_error_exit;
183ae4de14cSAlexey Kardashevskiy     }
184ae4de14cSAlexey Kardashevskiy 
185ae4de14cSAlexey Kardashevskiy     win_addr = (windows == 0) ? sphb->dma_win_addr : sphb->dma64_win_addr;
1865f366667SAlexey Kardashevskiy     /*
1875f366667SAlexey Kardashevskiy      * We have just created a window, we know for the fact that it is empty,
1885f366667SAlexey Kardashevskiy      * use a hack to avoid iterating over the table as it is quite possible
1895f366667SAlexey Kardashevskiy      * to have billions of TCEs, all empty.
1905f366667SAlexey Kardashevskiy      * Note that we cannot delay this to the first H_PUT_TCE as this hcall is
1915f366667SAlexey Kardashevskiy      * mostly likely to be handled in KVM so QEMU just does not know if it
1925f366667SAlexey Kardashevskiy      * happened.
1935f366667SAlexey Kardashevskiy      */
1945f366667SAlexey Kardashevskiy     tcet->skipping_replay = true;
195ae4de14cSAlexey Kardashevskiy     spapr_tce_table_enable(tcet, page_shift, win_addr,
196ae4de14cSAlexey Kardashevskiy                            1ULL << (window_shift - page_shift));
1975f366667SAlexey Kardashevskiy     tcet->skipping_replay = false;
198ae4de14cSAlexey Kardashevskiy     if (!tcet->nb_table) {
199ae4de14cSAlexey Kardashevskiy         goto hw_error_exit;
200ae4de14cSAlexey Kardashevskiy     }
201ae4de14cSAlexey Kardashevskiy 
202ae4de14cSAlexey Kardashevskiy     trace_spapr_iommu_ddw_create(buid, addr, 1ULL << page_shift,
203ae4de14cSAlexey Kardashevskiy                                  1ULL << window_shift, tcet->bus_offset, liobn);
204ae4de14cSAlexey Kardashevskiy 
205ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
206ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 1, liobn);
207ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 2, tcet->bus_offset >> 32);
208ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 3, tcet->bus_offset & ((uint32_t) -1));
209ae4de14cSAlexey Kardashevskiy 
210ae4de14cSAlexey Kardashevskiy     return;
211ae4de14cSAlexey Kardashevskiy 
212ae4de14cSAlexey Kardashevskiy hw_error_exit:
213ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
214ae4de14cSAlexey Kardashevskiy     return;
215ae4de14cSAlexey Kardashevskiy 
216ae4de14cSAlexey Kardashevskiy param_error_exit:
217ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
218ae4de14cSAlexey Kardashevskiy }
219ae4de14cSAlexey Kardashevskiy 
rtas_ibm_remove_pe_dma_window(PowerPCCPU * cpu,SpaprMachineState * spapr,uint32_t token,uint32_t nargs,target_ulong args,uint32_t nret,target_ulong rets)220ae4de14cSAlexey Kardashevskiy static void rtas_ibm_remove_pe_dma_window(PowerPCCPU *cpu,
221ce2918cbSDavid Gibson                                           SpaprMachineState *spapr,
222ae4de14cSAlexey Kardashevskiy                                           uint32_t token, uint32_t nargs,
223ae4de14cSAlexey Kardashevskiy                                           target_ulong args,
224ae4de14cSAlexey Kardashevskiy                                           uint32_t nret, target_ulong rets)
225ae4de14cSAlexey Kardashevskiy {
226ce2918cbSDavid Gibson     SpaprPhbState *sphb;
227ce2918cbSDavid Gibson     SpaprTceTable *tcet;
228ae4de14cSAlexey Kardashevskiy     uint32_t liobn;
22931cc81f7SAlexey Kardashevskiy     bool def_win_removed;
230ae4de14cSAlexey Kardashevskiy 
231ae4de14cSAlexey Kardashevskiy     if ((nargs != 1) || (nret != 1)) {
232ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
233ae4de14cSAlexey Kardashevskiy     }
234ae4de14cSAlexey Kardashevskiy 
235ae4de14cSAlexey Kardashevskiy     liobn = rtas_ld(args, 0);
236ae4de14cSAlexey Kardashevskiy     tcet = spapr_tce_find_by_liobn(liobn);
237ae4de14cSAlexey Kardashevskiy     if (!tcet) {
238ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
239ae4de14cSAlexey Kardashevskiy     }
240ae4de14cSAlexey Kardashevskiy 
241ae4de14cSAlexey Kardashevskiy     sphb = SPAPR_PCI_HOST_BRIDGE(OBJECT(tcet)->parent);
242ae4de14cSAlexey Kardashevskiy     if (!sphb || !sphb->ddw_enabled || !tcet->nb_table) {
243ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
244ae4de14cSAlexey Kardashevskiy     }
245ae4de14cSAlexey Kardashevskiy 
24631cc81f7SAlexey Kardashevskiy     def_win_removed = tcet->def_win;
247ae4de14cSAlexey Kardashevskiy     spapr_tce_table_disable(tcet);
248ae4de14cSAlexey Kardashevskiy     trace_spapr_iommu_ddw_remove(liobn);
249ae4de14cSAlexey Kardashevskiy 
25031cc81f7SAlexey Kardashevskiy     /*
25131cc81f7SAlexey Kardashevskiy      * PAPR+/LoPAPR says:
25231cc81f7SAlexey Kardashevskiy      * The platform must restore the default DMA window for the PE on a call
25331cc81f7SAlexey Kardashevskiy      * to the ibm,remove-pe-dma-window RTAS call when all of the following
25431cc81f7SAlexey Kardashevskiy      * are true:
25531cc81f7SAlexey Kardashevskiy      * a. The call removes the last DMA window remaining for the PE.
25631cc81f7SAlexey Kardashevskiy      * b. The DMA window being removed is not the default window
25731cc81f7SAlexey Kardashevskiy      */
25831cc81f7SAlexey Kardashevskiy     if (spapr_phb_get_active_win_num(sphb) == 0 && !def_win_removed) {
25931cc81f7SAlexey Kardashevskiy         spapr_phb_dma_reset(sphb);
26031cc81f7SAlexey Kardashevskiy         trace_spapr_iommu_ddw_reset(sphb->buid, 0);
26131cc81f7SAlexey Kardashevskiy     }
26231cc81f7SAlexey Kardashevskiy 
263ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
264ae4de14cSAlexey Kardashevskiy     return;
265ae4de14cSAlexey Kardashevskiy 
266ae4de14cSAlexey Kardashevskiy param_error_exit:
267ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
268ae4de14cSAlexey Kardashevskiy }
269ae4de14cSAlexey Kardashevskiy 
rtas_ibm_reset_pe_dma_window(PowerPCCPU * cpu,SpaprMachineState * spapr,uint32_t token,uint32_t nargs,target_ulong args,uint32_t nret,target_ulong rets)270ae4de14cSAlexey Kardashevskiy static void rtas_ibm_reset_pe_dma_window(PowerPCCPU *cpu,
271ce2918cbSDavid Gibson                                          SpaprMachineState *spapr,
272ae4de14cSAlexey Kardashevskiy                                          uint32_t token, uint32_t nargs,
273ae4de14cSAlexey Kardashevskiy                                          target_ulong args,
274ae4de14cSAlexey Kardashevskiy                                          uint32_t nret, target_ulong rets)
275ae4de14cSAlexey Kardashevskiy {
276ce2918cbSDavid Gibson     SpaprPhbState *sphb;
277ae4de14cSAlexey Kardashevskiy     uint64_t buid;
278ae4de14cSAlexey Kardashevskiy     uint32_t addr;
279ae4de14cSAlexey Kardashevskiy 
280ae4de14cSAlexey Kardashevskiy     if ((nargs != 3) || (nret != 1)) {
281ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
282ae4de14cSAlexey Kardashevskiy     }
283ae4de14cSAlexey Kardashevskiy 
284ae4de14cSAlexey Kardashevskiy     buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
285ae4de14cSAlexey Kardashevskiy     addr = rtas_ld(args, 0);
286ae4de14cSAlexey Kardashevskiy     sphb = spapr_pci_find_phb(spapr, buid);
287ae4de14cSAlexey Kardashevskiy     if (!sphb || !sphb->ddw_enabled) {
288ae4de14cSAlexey Kardashevskiy         goto param_error_exit;
289ae4de14cSAlexey Kardashevskiy     }
290ae4de14cSAlexey Kardashevskiy 
291ae4de14cSAlexey Kardashevskiy     spapr_phb_dma_reset(sphb);
292ae4de14cSAlexey Kardashevskiy     trace_spapr_iommu_ddw_reset(buid, addr);
293ae4de14cSAlexey Kardashevskiy 
294ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
295ae4de14cSAlexey Kardashevskiy 
296ae4de14cSAlexey Kardashevskiy     return;
297ae4de14cSAlexey Kardashevskiy 
298ae4de14cSAlexey Kardashevskiy param_error_exit:
299ae4de14cSAlexey Kardashevskiy     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
300ae4de14cSAlexey Kardashevskiy }
301ae4de14cSAlexey Kardashevskiy 
spapr_rtas_ddw_init(void)302ae4de14cSAlexey Kardashevskiy static void spapr_rtas_ddw_init(void)
303ae4de14cSAlexey Kardashevskiy {
304ae4de14cSAlexey Kardashevskiy     spapr_rtas_register(RTAS_IBM_QUERY_PE_DMA_WINDOW,
305ae4de14cSAlexey Kardashevskiy                         "ibm,query-pe-dma-window",
306ae4de14cSAlexey Kardashevskiy                         rtas_ibm_query_pe_dma_window);
307ae4de14cSAlexey Kardashevskiy     spapr_rtas_register(RTAS_IBM_CREATE_PE_DMA_WINDOW,
308ae4de14cSAlexey Kardashevskiy                         "ibm,create-pe-dma-window",
309ae4de14cSAlexey Kardashevskiy                         rtas_ibm_create_pe_dma_window);
310ae4de14cSAlexey Kardashevskiy     spapr_rtas_register(RTAS_IBM_REMOVE_PE_DMA_WINDOW,
311ae4de14cSAlexey Kardashevskiy                         "ibm,remove-pe-dma-window",
312ae4de14cSAlexey Kardashevskiy                         rtas_ibm_remove_pe_dma_window);
313ae4de14cSAlexey Kardashevskiy     spapr_rtas_register(RTAS_IBM_RESET_PE_DMA_WINDOW,
314ae4de14cSAlexey Kardashevskiy                         "ibm,reset-pe-dma-window",
315ae4de14cSAlexey Kardashevskiy                         rtas_ibm_reset_pe_dma_window);
316ae4de14cSAlexey Kardashevskiy }
317ae4de14cSAlexey Kardashevskiy 
318ae4de14cSAlexey Kardashevskiy type_init(spapr_rtas_ddw_init)
319