From: Alex Shi <alex.shi@linaro.org> To: Marc Zyngier <marc.zyngier@arm.com>, Will Deacon <will.deacon@arm.com>, Ard Biesheuvel <ard.biesheuvel@linaro.org>, Catalin Marinas <catalin.marinas@arm.com>, stable@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: Alex Shi <alex.shi@linaro.org> Subject: [PATCH 44/45] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support Date: Thu, 1 Mar 2018 20:54:21 +0800 [thread overview] Message-ID: <1519908862-11425-45-git-send-email-alex.shi@linaro.org> (raw) In-Reply-To: <1519908862-11425-1-git-send-email-alex.shi@linaro.org> From: Marc Zyngier <marc.zyngier@arm.com> commit b092201e0020 upstream. Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1. It is lovely. Really. Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Alex Shi <alex.shi@linaro.org> --- arch/arm64/kernel/bpi.S | 20 ++++++++++++ arch/arm64/kernel/cpu_errata.c | 72 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S index dec95bd..c72f261 100644 --- a/arch/arm64/kernel/bpi.S +++ b/arch/arm64/kernel/bpi.S @@ -17,6 +17,7 @@ */ #include <linux/linkage.h> +#include <linux/arm-smccc.h> .macro ventry target .rept 31 @@ -77,3 +78,22 @@ ENTRY(__psci_hyp_bp_inval_start) ldp x0, x1, [sp, #(16 * 8)] add sp, sp, #(8 * 18) ENTRY(__psci_hyp_bp_inval_end) + +.macro smccc_workaround_1 inst + sub sp, sp, #(8 * 4) + stp x2, x3, [sp, #(8 * 0)] + stp x0, x1, [sp, #(8 * 2)] + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 + \inst #0 + ldp x2, x3, [sp, #(8 * 0)] + ldp x0, x1, [sp, #(8 * 2)] + add sp, sp, #(8 * 4) +.endm + +ENTRY(__smccc_workaround_1_smc_start) + smccc_workaround_1 smc +ENTRY(__smccc_workaround_1_smc_end) + +ENTRY(__smccc_workaround_1_hvc_start) + smccc_workaround_1 hvc +ENTRY(__smccc_workaround_1_hvc_end) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f8810bf..9632319 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -54,6 +54,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); #ifdef CONFIG_KVM extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[]; +extern char __smccc_workaround_1_smc_start[]; +extern char __smccc_workaround_1_smc_end[]; +extern char __smccc_workaround_1_hvc_start[]; +extern char __smccc_workaround_1_hvc_end[]; static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, const char *hyp_vecs_end) @@ -96,8 +100,12 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, spin_unlock(&bp_lock); } #else -#define __psci_hyp_bp_inval_start NULL -#define __psci_hyp_bp_inval_end NULL +#define __psci_hyp_bp_inval_start NULL +#define __psci_hyp_bp_inval_end NULL +#define __smccc_workaround_1_smc_start NULL +#define __smccc_workaround_1_smc_end NULL +#define __smccc_workaround_1_hvc_start NULL +#define __smccc_workaround_1_hvc_end NULL static void __install_bp_hardening_cb(bp_hardening_cb_t fn, const char *hyp_vecs_start, @@ -124,17 +132,75 @@ static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end); } +#include <uapi/linux/psci.h> +#include <linux/arm-smccc.h> #include <linux/psci.h> +static void call_smc_arch_workaround_1(void) +{ + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); +} + +static void call_hvc_arch_workaround_1(void) +{ + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); +} + +static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) +{ + bp_hardening_cb_t cb; + void *smccc_start, *smccc_end; + struct arm_smccc_res res; + + if (!entry->matches(entry, SCOPE_LOCAL_CPU)) + return false; + + if (psci_ops.smccc_version == SMCCC_VERSION_1_0) + return false; + + switch (psci_ops.conduit) { + case PSCI_CONDUIT_HVC: + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + if (res.a0) + return false; + cb = call_hvc_arch_workaround_1; + smccc_start = __smccc_workaround_1_hvc_start; + smccc_end = __smccc_workaround_1_hvc_end; + break; + + case PSCI_CONDUIT_SMC: + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + if (res.a0) + return false; + cb = call_smc_arch_workaround_1; + smccc_start = __smccc_workaround_1_smc_start; + smccc_end = __smccc_workaround_1_smc_end; + break; + + default: + return false; + } + + install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); + + return true; +} + static int enable_psci_bp_hardening(void *data) { const struct arm64_cpu_capabilities *entry = data; - if (psci_ops.get_version) + if (psci_ops.get_version) { + if (check_smccc_arch_workaround_1(entry)) + return 0; + install_bp_hardening_cb(entry, (bp_hardening_cb_t)psci_ops.get_version, __psci_hyp_bp_inval_start, __psci_hyp_bp_inval_end); + } return 0; } -- 2.7.4
WARNING: multiple messages have this Message-ID (diff)
From: alex.shi@linaro.org (Alex Shi) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 44/45] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support Date: Thu, 1 Mar 2018 20:54:21 +0800 [thread overview] Message-ID: <1519908862-11425-45-git-send-email-alex.shi@linaro.org> (raw) In-Reply-To: <1519908862-11425-1-git-send-email-alex.shi@linaro.org> From: Marc Zyngier <marc.zyngier@arm.com> commit b092201e0020 upstream. Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1. It is lovely. Really. Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Alex Shi <alex.shi@linaro.org> --- arch/arm64/kernel/bpi.S | 20 ++++++++++++ arch/arm64/kernel/cpu_errata.c | 72 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S index dec95bd..c72f261 100644 --- a/arch/arm64/kernel/bpi.S +++ b/arch/arm64/kernel/bpi.S @@ -17,6 +17,7 @@ */ #include <linux/linkage.h> +#include <linux/arm-smccc.h> .macro ventry target .rept 31 @@ -77,3 +78,22 @@ ENTRY(__psci_hyp_bp_inval_start) ldp x0, x1, [sp, #(16 * 8)] add sp, sp, #(8 * 18) ENTRY(__psci_hyp_bp_inval_end) + +.macro smccc_workaround_1 inst + sub sp, sp, #(8 * 4) + stp x2, x3, [sp, #(8 * 0)] + stp x0, x1, [sp, #(8 * 2)] + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 + \inst #0 + ldp x2, x3, [sp, #(8 * 0)] + ldp x0, x1, [sp, #(8 * 2)] + add sp, sp, #(8 * 4) +.endm + +ENTRY(__smccc_workaround_1_smc_start) + smccc_workaround_1 smc +ENTRY(__smccc_workaround_1_smc_end) + +ENTRY(__smccc_workaround_1_hvc_start) + smccc_workaround_1 hvc +ENTRY(__smccc_workaround_1_hvc_end) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f8810bf..9632319 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -54,6 +54,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); #ifdef CONFIG_KVM extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[]; +extern char __smccc_workaround_1_smc_start[]; +extern char __smccc_workaround_1_smc_end[]; +extern char __smccc_workaround_1_hvc_start[]; +extern char __smccc_workaround_1_hvc_end[]; static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, const char *hyp_vecs_end) @@ -96,8 +100,12 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, spin_unlock(&bp_lock); } #else -#define __psci_hyp_bp_inval_start NULL -#define __psci_hyp_bp_inval_end NULL +#define __psci_hyp_bp_inval_start NULL +#define __psci_hyp_bp_inval_end NULL +#define __smccc_workaround_1_smc_start NULL +#define __smccc_workaround_1_smc_end NULL +#define __smccc_workaround_1_hvc_start NULL +#define __smccc_workaround_1_hvc_end NULL static void __install_bp_hardening_cb(bp_hardening_cb_t fn, const char *hyp_vecs_start, @@ -124,17 +132,75 @@ static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end); } +#include <uapi/linux/psci.h> +#include <linux/arm-smccc.h> #include <linux/psci.h> +static void call_smc_arch_workaround_1(void) +{ + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); +} + +static void call_hvc_arch_workaround_1(void) +{ + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); +} + +static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) +{ + bp_hardening_cb_t cb; + void *smccc_start, *smccc_end; + struct arm_smccc_res res; + + if (!entry->matches(entry, SCOPE_LOCAL_CPU)) + return false; + + if (psci_ops.smccc_version == SMCCC_VERSION_1_0) + return false; + + switch (psci_ops.conduit) { + case PSCI_CONDUIT_HVC: + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + if (res.a0) + return false; + cb = call_hvc_arch_workaround_1; + smccc_start = __smccc_workaround_1_hvc_start; + smccc_end = __smccc_workaround_1_hvc_end; + break; + + case PSCI_CONDUIT_SMC: + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + if (res.a0) + return false; + cb = call_smc_arch_workaround_1; + smccc_start = __smccc_workaround_1_smc_start; + smccc_end = __smccc_workaround_1_smc_end; + break; + + default: + return false; + } + + install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); + + return true; +} + static int enable_psci_bp_hardening(void *data) { const struct arm64_cpu_capabilities *entry = data; - if (psci_ops.get_version) + if (psci_ops.get_version) { + if (check_smccc_arch_workaround_1(entry)) + return 0; + install_bp_hardening_cb(entry, (bp_hardening_cb_t)psci_ops.get_version, __psci_hyp_bp_inval_start, __psci_hyp_bp_inval_end); + } return 0; } -- 2.7.4
next prev parent reply other threads:[~2018-03-01 13:01 UTC|newest] Thread overview: 119+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-03-01 12:53 [PATCH 00/45] arm Spectre fix backport review for LTS 4.9 Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 01/45] mm: Introduce lm_alias Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 02/45] arm64: alternatives: apply boot time fixups via the linear mapping Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 03/45] arm64: barrier: Add CSDB macros to control data-value prediction Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 04/45] arm64: Implement array_index_mask_nospec() Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 05/45] arm64: move TASK_* definitions to <asm/processor.h> Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 06/45] arm64: Factor out PAN enabling/disabling into separate uaccess_* macros Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 07/45] arm64: Factor out TTBR0_EL1 post-update workaround into a specific asm macro Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 08/45] arm64: uaccess: consistently check object sizes Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 09/45] arm64: Make USER_DS an inclusive limit Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 10/45] arm64: Use pointer masking to limit uaccess speculation Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 11/45] arm64: syscallno is secretly an int, make it official Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 12/45] arm64: entry: Ensure branch through syscall table is bounded under speculation Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 13/45] arm64: uaccess: Prevent speculative use of the current addr_limit Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 14/45] arm64: uaccess: Don't bother eliding access_ok checks in __{get, put}_user Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 15/45] arm64: uaccess: Mask __user pointers for __arch_{clear, copy_*}_user Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 16/45] arm64: futex: Mask __user pointers prior to dereference Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 17/45] drivers/firmware: Expose psci_get_version through psci_ops structure Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 18/45] arm64: cpufeature: __this_cpu_has_cap() shouldn't stop early Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 19/45] arm64: cpu_errata: Allow an erratum to be match for all revisions of a core Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 20/45] arm64: Run enable method for errata work arounds on late CPUs Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 21/45] arm64: cpufeature: Pass capability structure to ->enable callback Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:53 ` [PATCH 22/45] arm64: Move post_ttbr_update_workaround to C code Alex Shi 2018-03-01 12:53 ` Alex Shi 2018-03-01 12:54 ` [PATCH 23/45] arm64: Add skeleton to harden the branch predictor against aliasing attacks Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 24/45] arm64: Move BP hardening to check_and_switch_context Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 25/45] arm64: KVM: Use per-CPU vector when BP hardening is enabled Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 26/45] arm64: entry: Apply BP hardening for high-priority synchronous exceptions Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 27/45] arm64: entry: Apply BP hardening for suspicious interrupts from EL0 Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 28/45] arm64: cputype: Add missing MIDR values for Cortex-A72 and Cortex-A75 Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 29/45] arm64: Implement branch predictor hardening for affected Cortex-A CPUs Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 30/45] arm64: KVM: Increment PC after handling an SMC trap Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 31/45] arm/arm64: KVM: Consolidate the PSCI include files Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 32/45] arm/arm64: KVM: Add PSCI_VERSION helper Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 33/45] arm/arm64: KVM: Add smccc accessors to PSCI code Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 34/45] arm/arm64: KVM: Implement PSCI 1.0 support Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 35/45] arm/arm64: KVM: Advertise SMCCC v1.1 Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 36/45] arm64: KVM: Make PSCI_VERSION a fast path Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 37/45] arm/arm64: KVM: Turn kvm_psci_version into a static inline Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 38/45] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 39/45] arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 40/45] firmware/psci: Expose PSCI conduit Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 41/45] firmware/psci: Expose SMCCC version through psci_ops Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 42/45] arm/arm64: smccc: Make function identifiers an unsigned quantity Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` [PATCH 43/45] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 12:54 ` Alex Shi [this message] 2018-03-01 12:54 ` [PATCH 44/45] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support Alex Shi 2018-03-01 12:54 ` [PATCH 45/45] arm64: Kill PSCI_GET_VERSION as a variant-2 workaround Alex Shi 2018-03-01 12:54 ` Alex Shi 2018-03-01 16:45 ` [PATCH 00/45] arm Spectre fix backport review for LTS 4.9 Greg KH 2018-03-01 16:45 ` Greg KH 2018-03-02 7:26 ` Alex Shi 2018-03-02 7:26 ` Alex Shi 2018-03-01 16:46 ` Greg KH 2018-03-01 16:46 ` Greg KH 2018-03-02 9:02 ` Alex Shi 2018-03-02 9:02 ` Alex Shi 2018-03-02 10:29 ` Marc Zyngier 2018-03-02 10:29 ` Marc Zyngier 2018-03-03 0:52 ` Alex Shi 2018-03-03 0:52 ` Alex Shi 2018-03-02 10:30 ` Will Deacon 2018-03-02 10:30 ` Will Deacon 2018-03-03 0:54 ` Alex Shi 2018-03-03 0:54 ` Alex Shi 2018-03-08 12:27 ` Pavel Machek 2018-03-08 12:27 ` Pavel Machek 2018-03-08 13:21 ` Pali Rohár 2018-03-08 13:21 ` Pali Rohár 2018-03-08 13:33 ` Ivaylo Dimitrov 2018-03-08 13:33 ` Ivaylo Dimitrov 2018-03-08 13:33 ` Ivaylo Dimitrov 2018-03-08 13:35 ` Marc Zyngier 2018-03-08 13:35 ` Marc Zyngier 2018-03-08 17:01 ` Pali Rohár 2018-03-08 17:01 ` Pali Rohár
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1519908862-11425-45-git-send-email-alex.shi@linaro.org \ --to=alex.shi@linaro.org \ --cc=ard.biesheuvel@linaro.org \ --cc=catalin.marinas@arm.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=marc.zyngier@arm.com \ --cc=stable@vger.kernel.org \ --cc=will.deacon@arm.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.