* [PATCH v17 0/1] arm64: mm: Handle Granule Protection Faults (GPFs)
@ 2026-09-07 16:22 Suzuki K Poulose
2026-09-07 16:22 ` [PATCH v17 1/1] " Suzuki K Poulose
2026-09-11 13:02 ` [PATCH v17 0/1] " Will Deacon
0 siblings, 2 replies; 6+ messages in thread
From: Suzuki K Poulose @ 2026-09-07 16:22 UTC (permalink / raw)
To: linux-arm-kernel
Cc: catalin.marinas, will, linux-kernel, maz, pavan.kondeti, tabba,
aneesh.kumar, mark.rutland, sdonthineni, steven.price, gshan,
yuzenghui, kvmarm, Suzuki K Poulose
This single patch teaches the arm64 fault handling code about Granule
Protection Faults, introduced by FEAT_RME. This was posted with KVM CCA
support series, but split from that, to allow for other users of GPF.
The immediate user is KVM CCA, where the host may fault if it accesses
granules that have been delegated for use by a Realm. However, the fault
handling itself is architectural and not KVM-specific. It should also be useful
for other FEAT_RME users where an access to secure memory or root memory can
result in a GPF.
GPFs during a page table walk are treated as kernel bugs, while non-page-walk
faults can be reported to userspace with SIGBUS. The patch also allows existing
exception-table fixups to handle known in-kernel accesses such as
load_unaligned_zeropad() while private memory remains mapped in the linear map.
The KVM CCA v17 integration branch is available here:
[0] https://gitlab.arm.com/linux-arm/linux-cca.git cca/cca-host/kvm-integration/v17
Steven Price (1):
arm64: mm: Handle Granule Protection Faults (GPFs)
arch/arm64/mm/fault.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v17 1/1] arm64: mm: Handle Granule Protection Faults (GPFs)
2026-09-07 16:22 [PATCH v17 0/1] arm64: mm: Handle Granule Protection Faults (GPFs) Suzuki K Poulose
@ 2026-09-07 16:22 ` Suzuki K Poulose
2026-09-10 17:45 ` Catalin Marinas
2026-09-11 13:02 ` [PATCH v17 0/1] " Will Deacon
1 sibling, 1 reply; 6+ messages in thread
From: Suzuki K Poulose @ 2026-09-07 16:22 UTC (permalink / raw)
To: linux-arm-kernel
Cc: catalin.marinas, will, linux-kernel, maz, pavan.kondeti, tabba,
aneesh.kumar, mark.rutland, sdonthineni, steven.price, gshan,
yuzenghui, kvmarm, Suzuki K Poulose
From: Steven Price <steven.price@arm.com>
If the host attempts to access granules that have been delegated for use
in a realm these accesses will be caught and will trigger a Granule
Protection Fault (GPF).
A fault during a page walk signals a bug in the kernel and is handled by
oopsing the kernel. A non-page walk fault could be caused by user space
having access to a page which has been delegated to the kernel and will
trigger a SIGBUS to allow debugging why user space is trying to access a
delegated page.
Also, until we unmap the "private" memory pages from the linear map, we could
get spurious GPFs from within the kernel, e.g., load_unaligned_zeropad(). So,
try to fix them up for now.
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
Changes since v16:
* Update the commit description to indicate why we try to fixup GPFs
Changes since v10:
* Don't call arm64_notify_die() in do_gpf() but simply return 1.
Changes since v2:
* Include missing "Granule Protection Fault at level -1"
---
arch/arm64/mm/fault.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0b52557652be6..ad00997b1a873 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -910,6 +910,22 @@ static int do_tag_check_fault(unsigned long far, unsigned long esr,
return 0;
}
+static int do_gpf_ptw(unsigned long far, unsigned long esr, struct pt_regs *regs)
+{
+ const struct fault_info *inf = esr_to_fault_info(esr);
+
+ die_kernel_fault(inf->name, far, esr, regs);
+ return 0;
+}
+
+static int do_gpf(unsigned long far, unsigned long esr, struct pt_regs *regs)
+{
+ if (!is_el1_instruction_abort(esr) && fixup_exception(regs, esr))
+ return 0;
+
+ return 1;
+}
+
static const struct fault_info fault_info[] = {
{ do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" },
{ do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" },
@@ -946,12 +962,12 @@ static const struct fault_info fault_info[] = {
{ do_bad, SIGKILL, SI_KERNEL, "unknown 32" },
{ do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 34" },
- { do_bad, SIGKILL, SI_KERNEL, "unknown 35" },
- { do_bad, SIGKILL, SI_KERNEL, "unknown 36" },
- { do_bad, SIGKILL, SI_KERNEL, "unknown 37" },
- { do_bad, SIGKILL, SI_KERNEL, "unknown 38" },
- { do_bad, SIGKILL, SI_KERNEL, "unknown 39" },
- { do_bad, SIGKILL, SI_KERNEL, "unknown 40" },
+ { do_gpf_ptw, SIGKILL, SI_KERNEL, "level -1 granule protection fault (translation table walk)" },
+ { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 0 granule protection fault (translation table walk)" },
+ { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 1 granule protection fault (translation table walk)" },
+ { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 2 granule protection fault (translation table walk)" },
+ { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 3 granule protection fault (translation table walk)" },
+ { do_gpf, SIGBUS, SI_KERNEL, "granule protection fault" },
{ do_bad, SIGKILL, SI_KERNEL, "level -1 address size fault" },
{ do_bad, SIGKILL, SI_KERNEL, "unknown 42" },
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level -1 translation fault" },
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v17 1/1] arm64: mm: Handle Granule Protection Faults (GPFs)
2026-09-07 16:22 ` [PATCH v17 1/1] " Suzuki K Poulose
@ 2026-09-10 17:45 ` Catalin Marinas
2026-09-10 18:52 ` Suzuki K Poulose
0 siblings, 1 reply; 6+ messages in thread
From: Catalin Marinas @ 2026-09-10 17:45 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: linux-arm-kernel, will, linux-kernel, maz, pavan.kondeti, tabba,
aneesh.kumar, mark.rutland, sdonthineni, steven.price, gshan,
yuzenghui, kvmarm
On Mon, Sep 07, 2026 at 05:22:04PM +0100, Suzuki K Poulose wrote:
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 0b52557652be6..ad00997b1a873 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -910,6 +910,22 @@ static int do_tag_check_fault(unsigned long far, unsigned long esr,
> return 0;
> }
>
> +static int do_gpf_ptw(unsigned long far, unsigned long esr, struct pt_regs *regs)
> +{
> + const struct fault_info *inf = esr_to_fault_info(esr);
> +
> + die_kernel_fault(inf->name, far, esr, regs);
> + return 0;
> +}
> +
> +static int do_gpf(unsigned long far, unsigned long esr, struct pt_regs *regs)
> +{
> + if (!is_el1_instruction_abort(esr) && fixup_exception(regs, esr))
> + return 0;
> +
> + return 1;
> +}
If we end up with a user PC here, we correctly return 1 but only because
fixup_exception() won't find the PC. I'd rather have this explicit with
a user_mode() check.
> +
> static const struct fault_info fault_info[] = {
> { do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" },
> { do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" },
> @@ -946,12 +962,12 @@ static const struct fault_info fault_info[] = {
> { do_bad, SIGKILL, SI_KERNEL, "unknown 32" },
> { do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
> { do_bad, SIGKILL, SI_KERNEL, "unknown 34" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 35" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 36" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 37" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 38" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 39" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 40" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level -1 granule protection fault (translation table walk)" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 0 granule protection fault (translation table walk)" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 1 granule protection fault (translation table walk)" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 2 granule protection fault (translation table walk)" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 3 granule protection fault (translation table walk)" },
> + { do_gpf, SIGBUS, SI_KERNEL, "granule protection fault" },
For SIGBUS, we should use BUS_OBJERR like we do for do_sea().
Otherwise it looks fine to me.
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v17 1/1] arm64: mm: Handle Granule Protection Faults (GPFs)
2026-09-10 17:45 ` Catalin Marinas
@ 2026-09-10 18:52 ` Suzuki K Poulose
0 siblings, 0 replies; 6+ messages in thread
From: Suzuki K Poulose @ 2026-09-10 18:52 UTC (permalink / raw)
To: Catalin Marinas
Cc: linux-arm-kernel, will, linux-kernel, maz, pavan.kondeti, tabba,
aneesh.kumar, mark.rutland, sdonthineni, steven.price, gshan,
yuzenghui, kvmarm
On 10/09/2026 18:45, Catalin Marinas wrote:
> On Mon, Sep 07, 2026 at 05:22:04PM +0100, Suzuki K Poulose wrote:
>> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
>> index 0b52557652be6..ad00997b1a873 100644
>> --- a/arch/arm64/mm/fault.c
>> +++ b/arch/arm64/mm/fault.c
>> @@ -910,6 +910,22 @@ static int do_tag_check_fault(unsigned long far, unsigned long esr,
>> return 0;
>> }
>>
>> +static int do_gpf_ptw(unsigned long far, unsigned long esr, struct pt_regs *regs)
>> +{
>> + const struct fault_info *inf = esr_to_fault_info(esr);
>> +
>> + die_kernel_fault(inf->name, far, esr, regs);
>> + return 0;
>> +}
>> +
>> +static int do_gpf(unsigned long far, unsigned long esr, struct pt_regs *regs)
>> +{
>> + if (!is_el1_instruction_abort(esr) && fixup_exception(regs, esr))
>> + return 0;
>> +
>> + return 1;
>> +}
>
> If we end up with a user PC here, we correctly return 1 but only because
> fixup_exception() won't find the PC. I'd rather have this explicit with
> a user_mode() check.
Sure, I have made the condtion to:
+ if (!user_mode(regs) && !is_el1_instruction_abort(esr) &&
+ fixup_exception(regs, esr))
+ return 0;
>
>> +
>> static const struct fault_info fault_info[] = {
>> { do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" },
>> { do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" },
>> @@ -946,12 +962,12 @@ static const struct fault_info fault_info[] = {
>> { do_bad, SIGKILL, SI_KERNEL, "unknown 32" },
>> { do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
>> { do_bad, SIGKILL, SI_KERNEL, "unknown 34" },
>> - { do_bad, SIGKILL, SI_KERNEL, "unknown 35" },
>> - { do_bad, SIGKILL, SI_KERNEL, "unknown 36" },
>> - { do_bad, SIGKILL, SI_KERNEL, "unknown 37" },
>> - { do_bad, SIGKILL, SI_KERNEL, "unknown 38" },
>> - { do_bad, SIGKILL, SI_KERNEL, "unknown 39" },
>> - { do_bad, SIGKILL, SI_KERNEL, "unknown 40" },
>> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level -1 granule protection fault (translation table walk)" },
>> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 0 granule protection fault (translation table walk)" },
>> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 1 granule protection fault (translation table walk)" },
>> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 2 granule protection fault (translation table walk)" },
>> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "level 3 granule protection fault (translation table walk)" },
>> + { do_gpf, SIGBUS, SI_KERNEL, "granule protection fault" },
>
> For SIGBUS, we should use BUS_OBJERR like we do for do_sea().
Good point, I have added that.
>
> Otherwise it looks fine to me.
Thanks, I have already added the untagged_addr() as reported by Sashiko.
>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Cheers
Suzuki
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v17 0/1] arm64: mm: Handle Granule Protection Faults (GPFs)
2026-09-07 16:22 [PATCH v17 0/1] arm64: mm: Handle Granule Protection Faults (GPFs) Suzuki K Poulose
2026-09-07 16:22 ` [PATCH v17 1/1] " Suzuki K Poulose
@ 2026-09-11 13:02 ` Will Deacon
2026-09-11 16:09 ` Suzuki K Poulose
1 sibling, 1 reply; 6+ messages in thread
From: Will Deacon @ 2026-09-11 13:02 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: linux-arm-kernel, catalin.marinas, linux-kernel, maz,
pavan.kondeti, tabba, aneesh.kumar, mark.rutland, sdonthineni,
steven.price, gshan, yuzenghui, kvmarm
On Mon, Sep 07, 2026 at 05:22:03PM +0100, Suzuki K Poulose wrote:
> This single patch teaches the arm64 fault handling code about Granule
> Protection Faults, introduced by FEAT_RME. This was posted with KVM CCA
> support series, but split from that, to allow for other users of GPF.
>
> The immediate user is KVM CCA, where the host may fault if it accesses
> granules that have been delegated for use by a Realm. However, the fault
> handling itself is architectural and not KVM-specific. It should also be useful
> for other FEAT_RME users where an access to secure memory or root memory can
> result in a GPF.
>
> GPFs during a page table walk are treated as kernel bugs, while non-page-walk
> faults can be reported to userspace with SIGBUS. The patch also allows existing
> exception-table fixups to handle known in-kernel accesses such as
> load_unaligned_zeropad() while private memory remains mapped in the linear map.
I assume you can't handle GUP for realm memory, so you must be using
guest_memfd to avoid userspace mappings of realm memory. In that case,
why don't you unmap it from the linear map entirely? There's ongoing work
to do that afaik, it can be done largely outside of arch code and it
seems like people want it to defend against side channels anyway.
Will
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v17 0/1] arm64: mm: Handle Granule Protection Faults (GPFs)
2026-09-11 13:02 ` [PATCH v17 0/1] " Will Deacon
@ 2026-09-11 16:09 ` Suzuki K Poulose
0 siblings, 0 replies; 6+ messages in thread
From: Suzuki K Poulose @ 2026-09-11 16:09 UTC (permalink / raw)
To: Will Deacon
Cc: linux-arm-kernel, catalin.marinas, linux-kernel, maz,
pavan.kondeti, tabba, aneesh.kumar, mark.rutland, sdonthineni,
steven.price, gshan, yuzenghui, kvmarm
On 11/09/2026 14:02, Will Deacon wrote:
> On Mon, Sep 07, 2026 at 05:22:03PM +0100, Suzuki K Poulose wrote:
>> This single patch teaches the arm64 fault handling code about Granule
>> Protection Faults, introduced by FEAT_RME. This was posted with KVM CCA
>> support series, but split from that, to allow for other users of GPF.
>>
>> The immediate user is KVM CCA, where the host may fault if it accesses
>> granules that have been delegated for use by a Realm. However, the fault
>> handling itself is architectural and not KVM-specific. It should also be useful
>> for other FEAT_RME users where an access to secure memory or root memory can
>> result in a GPF.
>>
>> GPFs during a page table walk are treated as kernel bugs, while non-page-walk
>> faults can be reported to userspace with SIGBUS. The patch also allows existing
>> exception-table fixups to handle known in-kernel accesses such as
>> load_unaligned_zeropad() while private memory remains mapped in the linear map.
>
> I assume you can't handle GUP for realm memory, so you must be using
> guest_memfd to avoid userspace mappings of realm memory. In that case,
> why don't you unmap it from the linear map entirely? There's ongoing work
> to do that afaik, it can be done largely outside of arch code and it
> seems like people want it to defend against side channels anyway.
Yes, thats the plan. Sorry, the commit message is a bit vague. Until we
have that support, we should try to fixup the exception.
Once we get the support to unmap them from the linear map, we could
relax this.
Cheers
Suzuki
>
> Will
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-11 16:09 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-07 16:22 [PATCH v17 0/1] arm64: mm: Handle Granule Protection Faults (GPFs) Suzuki K Poulose
2026-09-07 16:22 ` [PATCH v17 1/1] " Suzuki K Poulose
2026-09-10 17:45 ` Catalin Marinas
2026-09-10 18:52 ` Suzuki K Poulose
2026-09-11 13:02 ` [PATCH v17 0/1] " Will Deacon
2026-09-11 16:09 ` Suzuki K Poulose
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®