1  // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2  /******************************************************************************
3   *
4   * Module Name: exregion - ACPI default op_region (address space) handlers
5   *
6   * Copyright (C) 2000 - 2023, Intel Corp.
7   *
8   *****************************************************************************/
9  
10  #include <acpi/acpi.h>
11  #include "accommon.h"
12  #include "acinterp.h"
13  
14  #define _COMPONENT          ACPI_EXECUTER
15  ACPI_MODULE_NAME("exregion")
16  
17  /*******************************************************************************
18   *
19   * FUNCTION:    acpi_ex_system_memory_space_handler
20   *
21   * PARAMETERS:  function            - Read or Write operation
22   *              address             - Where in the space to read or write
23   *              bit_width           - Field width in bits (8, 16, or 32)
24   *              value               - Pointer to in or out value
25   *              handler_context     - Pointer to Handler's context
26   *              region_context      - Pointer to context specific to the
27   *                                    accessed region
28   *
29   * RETURN:      Status
30   *
31   * DESCRIPTION: Handler for the System Memory address space (Op Region)
32   *
33   ******************************************************************************/
34  acpi_status
acpi_ex_system_memory_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)35  acpi_ex_system_memory_space_handler(u32 function,
36  				    acpi_physical_address address,
37  				    u32 bit_width,
38  				    u64 *value,
39  				    void *handler_context, void *region_context)
40  {
41  	acpi_status status = AE_OK;
42  	void *logical_addr_ptr = NULL;
43  	struct acpi_mem_space_context *mem_info = region_context;
44  	struct acpi_mem_mapping *mm = mem_info->cur_mm;
45  	u32 length;
46  	acpi_size map_length;
47  #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
48  	u32 remainder;
49  #endif
50  
51  	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
52  
53  	/* Validate and translate the bit width */
54  
55  	switch (bit_width) {
56  	case 8:
57  
58  		length = 1;
59  		break;
60  
61  	case 16:
62  
63  		length = 2;
64  		break;
65  
66  	case 32:
67  
68  		length = 4;
69  		break;
70  
71  	case 64:
72  
73  		length = 8;
74  		break;
75  
76  	default:
77  
78  		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
79  			    bit_width));
80  		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
81  	}
82  
83  #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
84  	/*
85  	 * Hardware does not support non-aligned data transfers, we must verify
86  	 * the request.
87  	 */
88  	(void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
89  	if (remainder != 0) {
90  		return_ACPI_STATUS(AE_AML_ALIGNMENT);
91  	}
92  #endif
93  
94  	/*
95  	 * Does the request fit into the cached memory mapping?
96  	 * Is 1) Address below the current mapping? OR
97  	 *    2) Address beyond the current mapping?
98  	 */
99  	if (!mm || (address < mm->physical_address) ||
100  	    ((u64) address + length > (u64) mm->physical_address + mm->length)) {
101  		/*
102  		 * The request cannot be resolved by the current memory mapping.
103  		 *
104  		 * Look for an existing saved mapping covering the address range
105  		 * at hand.  If found, save it as the current one and carry out
106  		 * the access.
107  		 */
108  		for (mm = mem_info->first_mm; mm; mm = mm->next_mm) {
109  			if (mm == mem_info->cur_mm)
110  				continue;
111  
112  			if (address < mm->physical_address)
113  				continue;
114  
115  			if ((u64) address + length >
116  					(u64) mm->physical_address + mm->length)
117  				continue;
118  
119  			mem_info->cur_mm = mm;
120  			goto access;
121  		}
122  
123  		/* Create a new mappings list entry */
124  		mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm));
125  		if (!mm) {
126  			ACPI_ERROR((AE_INFO,
127  				    "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
128  				    ACPI_FORMAT_UINT64(address), length));
129  			return_ACPI_STATUS(AE_NO_MEMORY);
130  		}
131  
132  		/*
133  		 * October 2009: Attempt to map from the requested address to the
134  		 * end of the region. However, we will never map more than one
135  		 * page, nor will we cross a page boundary.
136  		 */
137  		map_length = (acpi_size)
138  		    ((mem_info->address + mem_info->length) - address);
139  
140  		if (map_length > ACPI_DEFAULT_PAGE_SIZE)
141  			map_length = ACPI_DEFAULT_PAGE_SIZE;
142  
143  		/* Create a new mapping starting at the address given */
144  
145  		logical_addr_ptr = acpi_os_map_memory(address, map_length);
146  		if (!logical_addr_ptr) {
147  			ACPI_ERROR((AE_INFO,
148  				    "Could not map memory at 0x%8.8X%8.8X, size %u",
149  				    ACPI_FORMAT_UINT64(address),
150  				    (u32)map_length));
151  			ACPI_FREE(mm);
152  			return_ACPI_STATUS(AE_NO_MEMORY);
153  		}
154  
155  		/* Save the physical address and mapping size */
156  
157  		mm->logical_address = logical_addr_ptr;
158  		mm->physical_address = address;
159  		mm->length = map_length;
160  
161  		/*
162  		 * Add the new entry to the mappigs list and save it as the
163  		 * current mapping.
164  		 */
165  		mm->next_mm = mem_info->first_mm;
166  		mem_info->first_mm = mm;
167  
168  		mem_info->cur_mm = mm;
169  	}
170  
171  access:
172  	/*
173  	 * Generate a logical pointer corresponding to the address we want to
174  	 * access
175  	 */
176  	logical_addr_ptr = mm->logical_address +
177  		((u64) address - (u64) mm->physical_address);
178  
179  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
180  			  "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
181  			  bit_width, function, ACPI_FORMAT_UINT64(address)));
182  
183  	/*
184  	 * Perform the memory read or write
185  	 *
186  	 * Note: For machines that do not support non-aligned transfers, the target
187  	 * address was checked for alignment above. We do not attempt to break the
188  	 * transfer up into smaller (byte-size) chunks because the AML specifically
189  	 * asked for a transfer width that the hardware may require.
190  	 */
191  	switch (function) {
192  	case ACPI_READ:
193  
194  		*value = 0;
195  		switch (bit_width) {
196  		case 8:
197  
198  			*value = (u64)ACPI_GET8(logical_addr_ptr);
199  			break;
200  
201  		case 16:
202  
203  			*value = (u64)ACPI_GET16(logical_addr_ptr);
204  			break;
205  
206  		case 32:
207  
208  			*value = (u64)ACPI_GET32(logical_addr_ptr);
209  			break;
210  
211  		case 64:
212  
213  			*value = (u64)ACPI_GET64(logical_addr_ptr);
214  			break;
215  
216  		default:
217  
218  			/* bit_width was already validated */
219  
220  			break;
221  		}
222  		break;
223  
224  	case ACPI_WRITE:
225  
226  		switch (bit_width) {
227  		case 8:
228  
229  			ACPI_SET8(logical_addr_ptr, *value);
230  			break;
231  
232  		case 16:
233  
234  			ACPI_SET16(logical_addr_ptr, *value);
235  			break;
236  
237  		case 32:
238  
239  			ACPI_SET32(logical_addr_ptr, *value);
240  			break;
241  
242  		case 64:
243  
244  			ACPI_SET64(logical_addr_ptr, *value);
245  			break;
246  
247  		default:
248  
249  			/* bit_width was already validated */
250  
251  			break;
252  		}
253  		break;
254  
255  	default:
256  
257  		status = AE_BAD_PARAMETER;
258  		break;
259  	}
260  
261  	return_ACPI_STATUS(status);
262  }
263  
264  /*******************************************************************************
265   *
266   * FUNCTION:    acpi_ex_system_io_space_handler
267   *
268   * PARAMETERS:  function            - Read or Write operation
269   *              address             - Where in the space to read or write
270   *              bit_width           - Field width in bits (8, 16, or 32)
271   *              value               - Pointer to in or out value
272   *              handler_context     - Pointer to Handler's context
273   *              region_context      - Pointer to context specific to the
274   *                                    accessed region
275   *
276   * RETURN:      Status
277   *
278   * DESCRIPTION: Handler for the System IO address space (Op Region)
279   *
280   ******************************************************************************/
281  
282  acpi_status
acpi_ex_system_io_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)283  acpi_ex_system_io_space_handler(u32 function,
284  				acpi_physical_address address,
285  				u32 bit_width,
286  				u64 *value,
287  				void *handler_context, void *region_context)
288  {
289  	acpi_status status = AE_OK;
290  	u32 value32;
291  
292  	ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
293  
294  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
295  			  "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
296  			  bit_width, function, ACPI_FORMAT_UINT64(address)));
297  
298  	/* Decode the function parameter */
299  
300  	switch (function) {
301  	case ACPI_READ:
302  
303  		status = acpi_hw_read_port((acpi_io_address)address,
304  					   &value32, bit_width);
305  		*value = value32;
306  		break;
307  
308  	case ACPI_WRITE:
309  
310  		status = acpi_hw_write_port((acpi_io_address)address,
311  					    (u32)*value, bit_width);
312  		break;
313  
314  	default:
315  
316  		status = AE_BAD_PARAMETER;
317  		break;
318  	}
319  
320  	return_ACPI_STATUS(status);
321  }
322  
323  #ifdef ACPI_PCI_CONFIGURED
324  /*******************************************************************************
325   *
326   * FUNCTION:    acpi_ex_pci_config_space_handler
327   *
328   * PARAMETERS:  function            - Read or Write operation
329   *              address             - Where in the space to read or write
330   *              bit_width           - Field width in bits (8, 16, or 32)
331   *              value               - Pointer to in or out value
332   *              handler_context     - Pointer to Handler's context
333   *              region_context      - Pointer to context specific to the
334   *                                    accessed region
335   *
336   * RETURN:      Status
337   *
338   * DESCRIPTION: Handler for the PCI Config address space (Op Region)
339   *
340   ******************************************************************************/
341  
342  acpi_status
acpi_ex_pci_config_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)343  acpi_ex_pci_config_space_handler(u32 function,
344  				 acpi_physical_address address,
345  				 u32 bit_width,
346  				 u64 *value,
347  				 void *handler_context, void *region_context)
348  {
349  	acpi_status status = AE_OK;
350  	struct acpi_pci_id *pci_id;
351  	u16 pci_register;
352  
353  	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
354  
355  	/*
356  	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
357  	 *
358  	 *  pci_segment is the PCI bus segment range 0-31
359  	 *  pci_bus     is the PCI bus number range 0-255
360  	 *  pci_device  is the PCI device number range 0-31
361  	 *  pci_function is the PCI device function number
362  	 *  pci_register is the Config space register range 0-255 bytes
363  	 *
364  	 *  value - input value for write, output address for read
365  	 *
366  	 */
367  	pci_id = (struct acpi_pci_id *)region_context;
368  	pci_register = (u16) (u32) address;
369  
370  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
371  			  "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
372  			  "Dev(%04x) Func(%04x) Reg(%04x)\n",
373  			  function, bit_width, pci_id->segment, pci_id->bus,
374  			  pci_id->device, pci_id->function, pci_register));
375  
376  	switch (function) {
377  	case ACPI_READ:
378  
379  		*value = 0;
380  		status =
381  		    acpi_os_read_pci_configuration(pci_id, pci_register, value,
382  						   bit_width);
383  		break;
384  
385  	case ACPI_WRITE:
386  
387  		status =
388  		    acpi_os_write_pci_configuration(pci_id, pci_register,
389  						    *value, bit_width);
390  		break;
391  
392  	default:
393  
394  		status = AE_BAD_PARAMETER;
395  		break;
396  	}
397  
398  	return_ACPI_STATUS(status);
399  }
400  #endif
401  
402  /*******************************************************************************
403   *
404   * FUNCTION:    acpi_ex_cmos_space_handler
405   *
406   * PARAMETERS:  function            - Read or Write operation
407   *              address             - Where in the space to read or write
408   *              bit_width           - Field width in bits (8, 16, or 32)
409   *              value               - Pointer to in or out value
410   *              handler_context     - Pointer to Handler's context
411   *              region_context      - Pointer to context specific to the
412   *                                    accessed region
413   *
414   * RETURN:      Status
415   *
416   * DESCRIPTION: Handler for the CMOS address space (Op Region)
417   *
418   ******************************************************************************/
419  
420  acpi_status
acpi_ex_cmos_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)421  acpi_ex_cmos_space_handler(u32 function,
422  			   acpi_physical_address address,
423  			   u32 bit_width,
424  			   u64 *value,
425  			   void *handler_context, void *region_context)
426  {
427  	acpi_status status = AE_OK;
428  
429  	ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
430  
431  	return_ACPI_STATUS(status);
432  }
433  
434  #ifdef ACPI_PCI_CONFIGURED
435  /*******************************************************************************
436   *
437   * FUNCTION:    acpi_ex_pci_bar_space_handler
438   *
439   * PARAMETERS:  function            - Read or Write operation
440   *              address             - Where in the space to read or write
441   *              bit_width           - Field width in bits (8, 16, or 32)
442   *              value               - Pointer to in or out value
443   *              handler_context     - Pointer to Handler's context
444   *              region_context      - Pointer to context specific to the
445   *                                    accessed region
446   *
447   * RETURN:      Status
448   *
449   * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
450   *
451   ******************************************************************************/
452  
453  acpi_status
acpi_ex_pci_bar_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)454  acpi_ex_pci_bar_space_handler(u32 function,
455  			      acpi_physical_address address,
456  			      u32 bit_width,
457  			      u64 *value,
458  			      void *handler_context, void *region_context)
459  {
460  	acpi_status status = AE_OK;
461  
462  	ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
463  
464  	return_ACPI_STATUS(status);
465  }
466  #endif
467  
468  /*******************************************************************************
469   *
470   * FUNCTION:    acpi_ex_data_table_space_handler
471   *
472   * PARAMETERS:  function            - Read or Write operation
473   *              address             - Where in the space to read or write
474   *              bit_width           - Field width in bits (8, 16, or 32)
475   *              value               - Pointer to in or out value
476   *              handler_context     - Pointer to Handler's context
477   *              region_context      - Pointer to context specific to the
478   *                                    accessed region
479   *
480   * RETURN:      Status
481   *
482   * DESCRIPTION: Handler for the Data Table address space (Op Region)
483   *
484   ******************************************************************************/
485  
486  acpi_status
acpi_ex_data_table_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)487  acpi_ex_data_table_space_handler(u32 function,
488  				 acpi_physical_address address,
489  				 u32 bit_width,
490  				 u64 *value,
491  				 void *handler_context, void *region_context)
492  {
493  	struct acpi_data_table_mapping *mapping;
494  	char *pointer;
495  
496  	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
497  
498  	mapping = (struct acpi_data_table_mapping *) region_context;
499  	pointer = ACPI_CAST_PTR(char, mapping->pointer) +
500  	    (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer));
501  
502  	/*
503  	 * Perform the memory read or write. The bit_width was already
504  	 * validated.
505  	 */
506  	switch (function) {
507  	case ACPI_READ:
508  
509  		memcpy(ACPI_CAST_PTR(char, value), pointer,
510  		       ACPI_DIV_8(bit_width));
511  		break;
512  
513  	case ACPI_WRITE:
514  
515  		memcpy(pointer, ACPI_CAST_PTR(char, value),
516  		       ACPI_DIV_8(bit_width));
517  		break;
518  
519  	default:
520  
521  		return_ACPI_STATUS(AE_BAD_PARAMETER);
522  	}
523  
524  	return_ACPI_STATUS(AE_OK);
525  }
526