union acpi_operand_object *region_desc =
            (union acpi_operand_object *)handle;
        struct acpi_mem_space_context *local_region_context;
+       struct acpi_mem_mapping *mm;
 
        ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
 
                        local_region_context =
                            (struct acpi_mem_space_context *)*region_context;
 
-                       /* Delete a cached mapping if present */
+                       /* Delete memory mappings if present */
 
-                       if (local_region_context->mapped_length) {
-                               acpi_os_unmap_memory(local_region_context->
-                                                    mapped_logical_address,
-                                                    local_region_context->
-                                                    mapped_length);
+                       while (local_region_context->first_mm) {
+                               mm = local_region_context->first_mm;
+                               local_region_context->first_mm = mm->next_mm;
+                               acpi_os_unmap_memory(mm->logical_address,
+                                                    mm->length);
+                               ACPI_FREE(mm);
                        }
                        ACPI_FREE(local_region_context);
                        *region_context = NULL;
 
        acpi_status status = AE_OK;
        void *logical_addr_ptr = NULL;
        struct acpi_mem_space_context *mem_info = region_context;
+       struct acpi_mem_mapping *mm = mem_info->cur_mm;
        u32 length;
        acpi_size map_length;
        acpi_size page_boundary_map_length;
         * Is 1) Address below the current mapping? OR
         *    2) Address beyond the current mapping?
         */
-       if ((address < mem_info->mapped_physical_address) ||
-           (((u64) address + length) > ((u64)
-                                        mem_info->mapped_physical_address +
-                                        mem_info->mapped_length))) {
+       if (!mm || (address < mm->physical_address) ||
+           ((u64) address + length > (u64) mm->physical_address + mm->length)) {
                /*
-                * The request cannot be resolved by the current memory mapping;
-                * Delete the existing mapping and create a new one.
+                * The request cannot be resolved by the current memory mapping.
+                *
+                * Look for an existing saved mapping covering the address range
+                * at hand.  If found, save it as the current one and carry out
+                * the access.
                 */
-               if (mem_info->mapped_length) {
+               for (mm = mem_info->first_mm; mm; mm = mm->next_mm) {
+                       if (mm == mem_info->cur_mm)
+                               continue;
+
+                       if (address < mm->physical_address)
+                               continue;
 
-                       /* Valid mapping, delete it */
+                       if ((u64) address + length >
+                                       (u64) mm->physical_address + mm->length)
+                               continue;
 
-                       acpi_os_unmap_memory(mem_info->mapped_logical_address,
-                                            mem_info->mapped_length);
+                       mem_info->cur_mm = mm;
+                       goto access;
+               }
+
+               /* Create a new mappings list entry */
+               mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm));
+               if (!mm) {
+                       ACPI_ERROR((AE_INFO,
+                                   "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
+                                   ACPI_FORMAT_UINT64(address), length));
+                       return_ACPI_STATUS(AE_NO_MEMORY);
                }
 
                /*
 
                /* Create a new mapping starting at the address given */
 
-               mem_info->mapped_logical_address =
-                   acpi_os_map_memory(address, map_length);
-               if (!mem_info->mapped_logical_address) {
+               logical_addr_ptr = acpi_os_map_memory(address, map_length);
+               if (!logical_addr_ptr) {
                        ACPI_ERROR((AE_INFO,
                                    "Could not map memory at 0x%8.8X%8.8X, size %u",
                                    ACPI_FORMAT_UINT64(address),
                                    (u32)map_length));
-                       mem_info->mapped_length = 0;
+                       ACPI_FREE(mm);
                        return_ACPI_STATUS(AE_NO_MEMORY);
                }
 
                /* Save the physical address and mapping size */
 
-               mem_info->mapped_physical_address = address;
-               mem_info->mapped_length = map_length;
+               mm->logical_address = logical_addr_ptr;
+               mm->physical_address = address;
+               mm->length = map_length;
+
+               /*
+                * Add the new entry to the mappigs list and save it as the
+                * current mapping.
+                */
+               mm->next_mm = mem_info->first_mm;
+               mem_info->first_mm = mm;
+
+               mem_info->cur_mm = mm;
        }
 
+access:
        /*
         * Generate a logical pointer corresponding to the address we want to
         * access
         */
-       logical_addr_ptr = mem_info->mapped_logical_address +
-           ((u64) address - (u64) mem_info->mapped_physical_address);
+       logical_addr_ptr = mm->logical_address +
+               ((u64) address - (u64) mm->physical_address);
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",