mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
iommu/vt-d: Consolidate dmar policy management and force_on logic
Currently the dmar on/off is carried by multiple variables (no_iommu, dmar_disabled, no_platform_optin, etc.) with error-prone force_on logic scattered in multiple places. Unify/centralize the policy/priority management for various force_on scenarios. No functional impact except one case - "intel_iommu=off" sets no_platform_optin which is checked in platform_optin_force_iommu() but not in detect_intel_iommu(), leading to ACS unnecessarily requested when iommu could not be forced on later. Now with the unified logic this becomes more consistent. Signed-off-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
parent
a4bd40c7e2
commit
7e6bd2211e
|
|
@ -915,14 +915,61 @@ dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Centralized helper for deciding the force_on policy
|
||||
*
|
||||
* dmar off policies (for DMA Remapping) are defined from stronger
|
||||
* (more negative values) to weaker (less negative values).
|
||||
*
|
||||
* When a force_on type is passed in, it is associated to a reference
|
||||
* level for comparison. force_on is permitted when dmar is in a
|
||||
* off policy less negative than the reference level (if the policy is
|
||||
* on then the check is always true).
|
||||
*
|
||||
* For supported force_on types:
|
||||
*
|
||||
* - DMAR_FORCEON_TBOOT: tboot strictly requires DMA remapping for secure
|
||||
* boot hence supersedes any user opts ("iommu=off" or "intel_iommu=off")
|
||||
* and weaker off policies.
|
||||
*
|
||||
* - DMAR_FORCEON_PLATFORM: external-facing devices requires DMA
|
||||
* remapping to prevent malicious downstream external devices from
|
||||
* composing DMA attacks. force_on is permitted only if dmar policy is
|
||||
* off by build configurations (CONFIG_INTEL_IOMMU_DEFAULT_ON=off).
|
||||
*
|
||||
* In a nutshell, "trusted boot environment" is considered stronger than
|
||||
* "user choices", which in turn is stronger than "platform opt-in hint".
|
||||
*/
|
||||
bool dmar_can_force_on(enum dmar_force_on force_on)
|
||||
{
|
||||
int level;
|
||||
|
||||
switch (force_on) {
|
||||
case DMAR_FORCEON_TBOOT:
|
||||
level = DMAR_USER_OFF;
|
||||
break;
|
||||
case DMAR_FORCEON_PLATFORM:
|
||||
level = DMAR_DEFAULT_OFF;
|
||||
break;
|
||||
default:
|
||||
level = INT_MAX;
|
||||
pr_warn("Unsupported force_on type (%d)\n", force_on);
|
||||
break;
|
||||
}
|
||||
|
||||
return dmar_policy >= level;
|
||||
}
|
||||
|
||||
static bool dmar_required(void)
|
||||
{
|
||||
/* tboot supersedes any user/platform opt */
|
||||
if (!intel_iommu_tboot_noforce && tboot_enabled())
|
||||
if (dmar_policy_on())
|
||||
return true;
|
||||
|
||||
if (!no_iommu && (!dmar_disabled || dmar_platform_optin()))
|
||||
return true;
|
||||
if (!intel_iommu_tboot_noforce && tboot_enabled())
|
||||
return dmar_can_force_on(DMAR_FORCEON_TBOOT);
|
||||
|
||||
if (dmar_platform_optin())
|
||||
return dmar_can_force_on(DMAR_FORCEON_PLATFORM);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -936,6 +983,9 @@ void __init detect_intel_iommu(void)
|
|||
};
|
||||
|
||||
down_write(&dmar_global_lock);
|
||||
if (no_iommu)
|
||||
dmar_policy = DMAR_USER_OFF;
|
||||
|
||||
ret = dmar_table_detect();
|
||||
if (!ret)
|
||||
ret = dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
|
||||
|
|
|
|||
|
|
@ -199,6 +199,11 @@ static LIST_HEAD(dmar_satc_units);
|
|||
|
||||
static void intel_iommu_domain_free(struct iommu_domain *domain);
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
|
||||
int dmar_policy = DMAR_ON;
|
||||
#else
|
||||
int dmar_policy = DMAR_DEFAULT_OFF;
|
||||
#endif
|
||||
int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
|
||||
int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
|
||||
|
||||
|
|
@ -240,9 +245,11 @@ static int __init intel_iommu_setup(char *str)
|
|||
|
||||
while (*str) {
|
||||
if (!strncmp(str, "on", 2)) {
|
||||
dmar_policy = DMAR_ON;
|
||||
dmar_disabled = 0;
|
||||
pr_info("IOMMU enabled\n");
|
||||
} else if (!strncmp(str, "off", 3)) {
|
||||
dmar_policy = DMAR_USER_OFF;
|
||||
dmar_disabled = 1;
|
||||
no_platform_optin = 1;
|
||||
pr_info("IOMMU disabled\n");
|
||||
|
|
|
|||
|
|
@ -1351,6 +1351,51 @@ static inline bool ecmd_has_pmu_essential(struct intel_iommu *iommu)
|
|||
DMA_ECMD_ECCAP3_ESSENTIAL;
|
||||
}
|
||||
|
||||
enum dmar_force_on {
|
||||
DMAR_FORCEON_PLATFORM,
|
||||
DMAR_FORCEON_TBOOT
|
||||
};
|
||||
|
||||
/*
|
||||
* On policies are positive, with more positive value being stronger.
|
||||
* Off policies are negative, with more negative value being stronger.
|
||||
*
|
||||
* 'dmar' here refers to DMA remapping instead of the dmar/iommu unit.
|
||||
*
|
||||
* - DMAR_FORCE_ON:
|
||||
* force to turn on (e.g. by tboot or platform opt-in).
|
||||
*
|
||||
* - DMAR_ON:
|
||||
* turn on by build configuration (CONFIG_INTEL_IOMMU_DEFAULT_ON=on)
|
||||
* or user opts ("intel_iommu=on").
|
||||
*
|
||||
* - DMAR_DEFAULT_OFF
|
||||
* turn off by build configuration (CONFIG_INTEL_IOMMU_DEFAULT_ON=off).
|
||||
*
|
||||
* - DMAR_USER_OFF
|
||||
* turn off by user opts ("intel_iommu=off" or "iommu=off").
|
||||
*
|
||||
* - '0' is invalid, compared to decide the on/off policy
|
||||
*
|
||||
*/
|
||||
#define DMAR_FORCE_ON 2
|
||||
#define DMAR_ON 1
|
||||
#define DMAR_DEFAULT_OFF -1
|
||||
#define DMAR_USER_OFF -2
|
||||
extern int dmar_policy;
|
||||
|
||||
static inline bool dmar_policy_on(void)
|
||||
{
|
||||
return dmar_policy > 0;
|
||||
}
|
||||
|
||||
static inline bool dmar_policy_off(void)
|
||||
{
|
||||
return dmar_policy < 0;
|
||||
}
|
||||
|
||||
bool dmar_can_force_on(enum dmar_force_on force_on);
|
||||
|
||||
extern int dmar_disabled;
|
||||
extern int intel_iommu_enabled;
|
||||
extern int intel_iommu_tboot_noforce;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user