@@ -60,6 +60,103 @@ void amd_iommu_restart_ppr_log(struct amd_iommu *iommu)
60
60
MMIO_STATUS_PPR_OVERFLOW_MASK );
61
61
}
62
62
63
+ static inline u32 ppr_flag_to_fault_perm (u16 flag )
64
+ {
65
+ int perm = 0 ;
66
+
67
+ if (flag & PPR_FLAG_READ )
68
+ perm |= IOMMU_FAULT_PERM_READ ;
69
+ if (flag & PPR_FLAG_WRITE )
70
+ perm |= IOMMU_FAULT_PERM_WRITE ;
71
+ if (flag & PPR_FLAG_EXEC )
72
+ perm |= IOMMU_FAULT_PERM_EXEC ;
73
+ if (!(flag & PPR_FLAG_US ))
74
+ perm |= IOMMU_FAULT_PERM_PRIV ;
75
+
76
+ return perm ;
77
+ }
78
+
79
+ static bool ppr_is_valid (struct amd_iommu * iommu , u64 * raw )
80
+ {
81
+ struct device * dev = iommu -> iommu .dev ;
82
+ u16 devid = PPR_DEVID (raw [0 ]);
83
+
84
+ if (!(PPR_FLAGS (raw [0 ]) & PPR_FLAG_GN )) {
85
+ dev_dbg (dev , "PPR logged [Request ignored due to GN=0 (device=%04x:%02x:%02x.%x "
86
+ "pasid=0x%05llx address=0x%llx flags=0x%04llx tag=0x%03llx]\n" ,
87
+ iommu -> pci_seg -> id , PCI_BUS_NUM (devid ), PCI_SLOT (devid ), PCI_FUNC (devid ),
88
+ PPR_PASID (raw [0 ]), raw [1 ], PPR_FLAGS (raw [0 ]), PPR_TAG (raw [0 ]));
89
+ return false;
90
+ }
91
+
92
+ if (PPR_FLAGS (raw [0 ]) & PPR_FLAG_RVSD ) {
93
+ dev_dbg (dev , "PPR logged [Invalid request format (device=%04x:%02x:%02x.%x "
94
+ "pasid=0x%05llx address=0x%llx flags=0x%04llx tag=0x%03llx]\n" ,
95
+ iommu -> pci_seg -> id , PCI_BUS_NUM (devid ), PCI_SLOT (devid ), PCI_FUNC (devid ),
96
+ PPR_PASID (raw [0 ]), raw [1 ], PPR_FLAGS (raw [0 ]), PPR_TAG (raw [0 ]));
97
+ return false;
98
+ }
99
+
100
+ return true;
101
+ }
102
+
103
+ static void iommu_call_iopf_notifier (struct amd_iommu * iommu , u64 * raw )
104
+ {
105
+ struct iommu_dev_data * dev_data ;
106
+ struct iopf_fault event ;
107
+ struct pci_dev * pdev ;
108
+ u16 devid = PPR_DEVID (raw [0 ]);
109
+
110
+ if (PPR_REQ_TYPE (raw [0 ]) != PPR_REQ_FAULT ) {
111
+ pr_info_ratelimited ("Unknown PPR request received\n" );
112
+ return ;
113
+ }
114
+
115
+ pdev = pci_get_domain_bus_and_slot (iommu -> pci_seg -> id ,
116
+ PCI_BUS_NUM (devid ), devid & 0xff );
117
+ if (!pdev )
118
+ return ;
119
+
120
+ if (!ppr_is_valid (iommu , raw ))
121
+ goto out ;
122
+
123
+ memset (& event , 0 , sizeof (struct iopf_fault ));
124
+
125
+ event .fault .type = IOMMU_FAULT_PAGE_REQ ;
126
+ event .fault .prm .perm = ppr_flag_to_fault_perm (PPR_FLAGS (raw [0 ]));
127
+ event .fault .prm .addr = (u64 )(raw [1 ] & PAGE_MASK );
128
+ event .fault .prm .pasid = PPR_PASID (raw [0 ]);
129
+ event .fault .prm .grpid = PPR_TAG (raw [0 ]) & 0x1FF ;
130
+
131
+ /*
132
+ * PASID zero is used for requests from the I/O device without
133
+ * a PASID
134
+ */
135
+ dev_data = dev_iommu_priv_get (& pdev -> dev );
136
+ if (event .fault .prm .pasid == 0 ||
137
+ event .fault .prm .pasid >= dev_data -> max_pasids ) {
138
+ pr_info_ratelimited ("Invalid PASID : 0x%x, device : 0x%x\n" ,
139
+ event .fault .prm .pasid , pdev -> dev .id );
140
+ goto out ;
141
+ }
142
+
143
+ event .fault .prm .flags |= IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID ;
144
+ event .fault .prm .flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID ;
145
+ if (PPR_TAG (raw [0 ]) & 0x200 )
146
+ event .fault .prm .flags |= IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE ;
147
+
148
+ /* Submit event */
149
+ iommu_report_device_fault (& pdev -> dev , & event );
150
+
151
+ return ;
152
+
153
+ out :
154
+ /* Nobody cared, abort */
155
+ amd_iommu_complete_ppr (& pdev -> dev , PPR_PASID (raw [0 ]),
156
+ IOMMU_PAGE_RESP_FAILURE ,
157
+ PPR_TAG (raw [0 ]) & 0x1FF );
158
+ }
159
+
63
160
void amd_iommu_poll_ppr_log (struct amd_iommu * iommu )
64
161
{
65
162
u32 head , tail ;
@@ -105,7 +202,8 @@ void amd_iommu_poll_ppr_log(struct amd_iommu *iommu)
105
202
head = (head + PPR_ENTRY_SIZE ) % PPR_LOG_SIZE ;
106
203
writel (head , iommu -> mmio_base + MMIO_PPR_HEAD_OFFSET );
107
204
108
- /* TODO: PPR Handler will be added when we add IOPF support */
205
+ /* Handle PPR entry */
206
+ iommu_call_iopf_notifier (iommu , entry );
109
207
}
110
208
}
111
209
0 commit comments