88 * Author: Yazen Ghannam <Yazen.Ghannam@amd.com>
99 */
1010
11+ #include <linux/debugfs.h>
1112#include <asm/amd/node.h>
1213
1314/*
@@ -33,66 +34,11 @@ struct pci_dev *amd_node_get_func(u16 node, u8 func)
3334 return pci_get_domain_bus_and_slot (0 , 0 , PCI_DEVFN (AMD_NODE0_PCI_SLOT + node , func ));
3435}
3536
36- #define DF_BLK_INST_CNT 0x040
37- #define DF_CFG_ADDR_CNTL_LEGACY 0x084
38- #define DF_CFG_ADDR_CNTL_DF4 0xC04
39-
40- #define DF_MAJOR_REVISION GENMASK(27, 24)
41-
42- static u16 get_cfg_addr_cntl_offset (struct pci_dev * df_f0 )
43- {
44- u32 reg ;
45-
46- /*
47- * Revision fields added for DF4 and later.
48- *
49- * Major revision of '0' is found pre-DF4. Field is Read-as-Zero.
50- */
51- if (pci_read_config_dword (df_f0 , DF_BLK_INST_CNT , & reg ))
52- return 0 ;
53-
54- if (reg & DF_MAJOR_REVISION )
55- return DF_CFG_ADDR_CNTL_DF4 ;
56-
57- return DF_CFG_ADDR_CNTL_LEGACY ;
58- }
59-
60- struct pci_dev * amd_node_get_root (u16 node )
61- {
62- struct pci_dev * root ;
63- u16 cntl_off ;
64- u8 bus ;
65-
66- if (!cpu_feature_enabled (X86_FEATURE_ZEN ))
67- return NULL ;
68-
69- /*
70- * D18F0xXXX [Config Address Control] (DF::CfgAddressCntl)
71- * Bits [7:0] (SecBusNum) holds the bus number of the root device for
72- * this Data Fabric instance. The segment, device, and function will be 0.
73- */
74- struct pci_dev * df_f0 __free (pci_dev_put ) = amd_node_get_func (node , 0 );
75- if (!df_f0 )
76- return NULL ;
77-
78- cntl_off = get_cfg_addr_cntl_offset (df_f0 );
79- if (!cntl_off )
80- return NULL ;
81-
82- if (pci_read_config_byte (df_f0 , cntl_off , & bus ))
83- return NULL ;
84-
85- /* Grab the pointer for the actual root device instance. */
86- root = pci_get_domain_bus_and_slot (0 , bus , 0 );
87-
88- pci_dbg (root , "is root for AMD node %u\n" , node );
89- return root ;
90- }
91-
9237static struct pci_dev * * amd_roots ;
9338
9439/* Protect the PCI config register pairs used for SMN. */
9540static DEFINE_MUTEX (smn_mutex );
41+ static bool smn_exclusive ;
9642
9743#define SMN_INDEX_OFFSET 0x60
9844#define SMN_DATA_OFFSET 0x64
@@ -149,6 +95,9 @@ static int __amd_smn_rw(u8 i_off, u8 d_off, u16 node, u32 address, u32 *value, b
14995 if (!root )
15096 return err ;
15197
98+ if (!smn_exclusive )
99+ return err ;
100+
152101 guard (mutex )(& smn_mutex );
153102
154103 err = pci_write_config_dword (root , i_off , address );
@@ -188,23 +137,117 @@ int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write
188137}
189138EXPORT_SYMBOL_GPL (amd_smn_hsmp_rdwr );
190139
191- static int amd_cache_roots (void )
140+ static struct dentry * debugfs_dir ;
141+ static u16 debug_node ;
142+ static u32 debug_address ;
143+
144+ static ssize_t smn_node_write (struct file * file , const char __user * userbuf ,
145+ size_t count , loff_t * ppos )
192146{
193- u16 node , num_nodes = amd_num_nodes ();
147+ u16 node ;
148+ int ret ;
194149
195- amd_roots = kcalloc (num_nodes , sizeof (* amd_roots ), GFP_KERNEL );
196- if (!amd_roots )
197- return - ENOMEM ;
150+ ret = kstrtou16_from_user (userbuf , count , 0 , & node );
151+ if (ret )
152+ return ret ;
153+
154+ if (node >= amd_num_nodes ())
155+ return - ENODEV ;
156+
157+ debug_node = node ;
158+ return count ;
159+ }
160+
161+ static int smn_node_show (struct seq_file * m , void * v )
162+ {
163+ seq_printf (m , "0x%08x\n" , debug_node );
164+ return 0 ;
165+ }
166+
167+ static ssize_t smn_address_write (struct file * file , const char __user * userbuf ,
168+ size_t count , loff_t * ppos )
169+ {
170+ int ret ;
171+
172+ ret = kstrtouint_from_user (userbuf , count , 0 , & debug_address );
173+ if (ret )
174+ return ret ;
175+
176+ return count ;
177+ }
198178
199- for (node = 0 ; node < num_nodes ; node ++ )
200- amd_roots [node ] = amd_node_get_root (node );
179+ static int smn_address_show (struct seq_file * m , void * v )
180+ {
181+ seq_printf (m , "0x%08x\n" , debug_address );
182+ return 0 ;
183+ }
184+
185+ static int smn_value_show (struct seq_file * m , void * v )
186+ {
187+ u32 val ;
188+ int ret ;
189+
190+ ret = amd_smn_read (debug_node , debug_address , & val );
191+ if (ret )
192+ return ret ;
201193
194+ seq_printf (m , "0x%08x\n" , val );
202195 return 0 ;
203196}
204197
198+ static ssize_t smn_value_write (struct file * file , const char __user * userbuf ,
199+ size_t count , loff_t * ppos )
200+ {
201+ u32 val ;
202+ int ret ;
203+
204+ ret = kstrtouint_from_user (userbuf , count , 0 , & val );
205+ if (ret )
206+ return ret ;
207+
208+ add_taint (TAINT_CPU_OUT_OF_SPEC , LOCKDEP_STILL_OK );
209+
210+ ret = amd_smn_write (debug_node , debug_address , val );
211+ if (ret )
212+ return ret ;
213+
214+ return count ;
215+ }
216+
217+ DEFINE_SHOW_STORE_ATTRIBUTE (smn_node );
218+ DEFINE_SHOW_STORE_ATTRIBUTE (smn_address );
219+ DEFINE_SHOW_STORE_ATTRIBUTE (smn_value );
220+
221+ static struct pci_dev * get_next_root (struct pci_dev * root )
222+ {
223+ while ((root = pci_get_class (PCI_CLASS_BRIDGE_HOST << 8 , root ))) {
224+ /* Root device is Device 0 Function 0. */
225+ if (root -> devfn )
226+ continue ;
227+
228+ if (root -> vendor != PCI_VENDOR_ID_AMD &&
229+ root -> vendor != PCI_VENDOR_ID_HYGON )
230+ continue ;
231+
232+ break ;
233+ }
234+
235+ return root ;
236+ }
237+
238+ static bool enable_dfs ;
239+
240+ static int __init amd_smn_enable_dfs (char * str )
241+ {
242+ enable_dfs = true;
243+ return 1 ;
244+ }
245+ __setup ("amd_smn_debugfs_enable" , amd_smn_enable_dfs );
246+
205247static int __init amd_smn_init (void )
206248{
207- int err ;
249+ u16 count , num_roots , roots_per_node , node , num_nodes ;
250+ struct pci_dev * root ;
208251
209252 if (!cpu_feature_enabled (X86_FEATURE_ZEN ))
210253 return 0 ;
@@ -214,9 +257,58 @@ static int __init amd_smn_init(void)
214257 if (amd_roots )
215258 return 0 ;
216259
217- err = amd_cache_roots ();
218- if (err )
219- return err ;
260+ num_roots = 0 ;
261+ root = NULL ;
262+ while ((root = get_next_root (root ))) {
263+ pci_dbg (root , "Reserving PCI config space\n" );
264+
265+ /*
266+ * There are a few SMN index/data pairs and other registers
267+ * that shouldn't be accessed by user space. So reserve the
268+ * entire PCI config space for simplicity rather than covering
269+ * specific registers piecemeal.
270+ */
271+ if (!pci_request_config_region_exclusive (root , 0 , PCI_CFG_SPACE_SIZE , NULL )) {
272+ pci_err (root , "Failed to reserve config space\n" );
273+ return - EEXIST ;
274+ }
275+
276+ num_roots ++ ;
277+ }
278+
279+ pr_debug ("Found %d AMD root devices\n" , num_roots );
280+
281+ if (!num_roots )
282+ return - ENODEV ;
283+
284+ num_nodes = amd_num_nodes ();
285+ amd_roots = kcalloc (num_nodes , sizeof (* amd_roots ), GFP_KERNEL );
286+ if (!amd_roots )
287+ return - ENOMEM ;
288+
289+ roots_per_node = num_roots / num_nodes ;
290+
291+ count = 0 ;
292+ node = 0 ;
293+ root = NULL ;
294+ while (node < num_nodes && (root = get_next_root (root ))) {
295+ /* Use one root for each node and skip the rest. */
296+ if (count ++ % roots_per_node )
297+ continue ;
298+
299+ pci_dbg (root , "is root for AMD node %u\n" , node );
300+ amd_roots [node ++ ] = root ;
301+ }
302+
303+ if (enable_dfs ) {
304+ debugfs_dir = debugfs_create_dir ("amd_smn" , arch_debugfs_dir );
305+
306+ debugfs_create_file ("node" , 0600 , debugfs_dir , NULL , & smn_node_fops );
307+ debugfs_create_file ("address" , 0600 , debugfs_dir , NULL , & smn_address_fops );
308+ debugfs_create_file ("value" , 0600 , debugfs_dir , NULL , & smn_value_fops );
309+ }
310+
311+ smn_exclusive = true;
220312
221313 return 0 ;
222314}
0 commit comments