Skip to content

Commit

Permalink
acpica: add acpi_os_map_memory_opregion
Browse files Browse the repository at this point in the history
In confidential computing scenarios operation regions
need to be shared with the host in order for the
host to pass data via such regions to the guest.
Since by default all guest mappings are private, define
a new acpi_os_map_memory_opregion interface that maps
operation regions as shared in case we are executing
in a confidential guest. This avoids mapping rest of the
ACPI structures as shared and only shares the operation
regions.

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
  • Loading branch information
ereshetova authored and Kuppuswamy Sathyanarayanan committed May 8, 2023
1 parent 063e05d commit 70b3d57
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 17 deletions.
2 changes: 1 addition & 1 deletion drivers/acpi/acpica/exregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ acpi_ex_system_memory_space_handler(u32 function,

/* Create a new mapping starting at the address given */

logical_addr_ptr = acpi_os_map_memory(address, map_length);
logical_addr_ptr = acpi_os_map_memory_opregion(address, map_length);
if (!logical_addr_ptr) {
ACPI_ERROR((AE_INFO,
"Could not map memory at 0x%8.8X%8.8X, size %u",
Expand Down
68 changes: 52 additions & 16 deletions drivers/acpi/osl.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <linux/jiffies.h>
#include <linux/semaphore.h>
#include <linux/security.h>
#include <linux/cc_platform.h>

#include <asm/io.h>
#include <linux/uaccess.h>
Expand Down Expand Up @@ -307,21 +308,8 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
iounmap(vaddr);
}

/**
* acpi_os_map_iomem - Get a virtual address for a given physical address range.
* @phys: Start of the physical address range to map.
* @size: Size of the physical address range to map.
*
* Look up the given physical address range in the list of existing ACPI memory
* mappings. If found, get a reference to it and return a pointer to it (its
* virtual address). If not found, map it, add it to that list and return a
* pointer to it.
*
* During early init (when acpi_permanent_mmap has not been set yet) this
* routine simply calls __acpi_map_table() to get the job done.
*/
void __iomem __ref
*acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
static void __iomem __ref
*__acpi_os_map_iomem(acpi_physical_address phys, acpi_size size, bool map_shared)
{
struct acpi_ioremap *map;
void __iomem *virt;
Expand Down Expand Up @@ -352,7 +340,10 @@ void __iomem __ref

pg_off = round_down(phys, PAGE_SIZE);
pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
virt = acpi_map(phys, size);
if (map_shared)
virt = ioremap_cache_shared(phys, size);
else
virt = acpi_map(phys, size);
if (!virt) {
mutex_unlock(&acpi_ioremap_lock);
kfree(map);
Expand All @@ -371,6 +362,25 @@ void __iomem __ref
mutex_unlock(&acpi_ioremap_lock);
return map->virt + (phys - map->phys);
}

/**
* acpi_os_map_iomem - Get a virtual address for a given physical address range.
* @phys: Start of the physical address range to map.
* @size: Size of the physical address range to map.
*
* Look up the given physical address range in the list of existing ACPI memory
* mappings. If found, get a reference to it and return a pointer to it (its
* virtual address). If not found, map it, add it to that list and return a
* pointer to it.
*
* During early init (when acpi_permanent_mmap has not been set yet) this
* routine simply calls __acpi_map_table() to get the job done.
*/
void __iomem __ref
*acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
{
return (void *)__acpi_os_map_iomem(phys, size, false);
}
EXPORT_SYMBOL_GPL(acpi_os_map_iomem);

void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
Expand All @@ -379,6 +389,32 @@ void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
}
EXPORT_SYMBOL_GPL(acpi_os_map_memory);

/**
* acpi_os_map_memory_opregion - Get a virtual address for a given physical
* address range. This function is intended to be used only for AML operation
* regions. In a confidential computing guest such regions needs to be explicitly
* shared with the host to avoid breaking the communication.
*
* @phys: Start of the physical address range to map.
* @size: Size of the physical address range to map.
*
* Look up the given physical address range in the list of existing ACPI memory
* mappings. If found, get a reference to it and return a pointer to it (its
* virtual address). If not found, map it, add it to that list and return a
* pointer to it.
*
* During early init (when acpi_permanent_mmap has not been set yet) this
* routine simply calls __acpi_map_table() to get the job done.
*/
void *__ref acpi_os_map_memory_opregion(acpi_physical_address phys, acpi_size size)
{
if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
return (void *)__acpi_os_map_iomem(phys, size, false);
else
return (void *)__acpi_os_map_iomem(phys, size, true);
}
EXPORT_SYMBOL_GPL(acpi_os_map_memory_opregion);

static void acpi_os_map_remove(struct work_struct *work)
{
struct acpi_ioremap *map = container_of(to_rcu_work(work),
Expand Down
5 changes: 5 additions & 0 deletions include/acpi/acpiosxf.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ void acpi_os_free(void *memory);
void *acpi_os_map_memory(acpi_physical_address where, acpi_size length);
#endif

#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory_opregion
# define acpi_os_map_memory_opregion(address, length) \
acpi_os_map_memory(address, length)
#endif

#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_unmap_memory
void acpi_os_unmap_memory(void *logical_address, acpi_size size);
#endif
Expand Down
1 change: 1 addition & 0 deletions include/acpi/platform/aclinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_delete_raw_lock
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_acquire_raw_lock
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_release_raw_lock
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_map_memory_opregion

/*
* OSL interfaces used by debugger/disassembler
Expand Down
2 changes: 2 additions & 0 deletions include/acpi/platform/aclinuxex.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ static inline void acpi_os_terminate_debugger(void)
return;
}

void *__ref acpi_os_map_memory_opregion(acpi_physical_address phys, acpi_size size);

/*
* OSL interfaces added by Linux
*/
Expand Down

0 comments on commit 70b3d57

Please sign in to comment.