diff options
| author | Fuad Tabba <fuad.tabba@linux.dev> | 2026-09-22 19:14:30 +0100 |
|---|---|---|
| committer | Will Deacon <will@kernel.org> | 2026-09-23 12:34:30 +0000 |
| commit | 2bc6b218717b9d08f466f88209251d54bc09b207 (patch) | |
| tree | cb91c941eccb15f94cbec4e96aa3a9c8736b5d66 /Documentation/livepatch/system-state.rst | |
| download | linux-stable-2bc6b218717b9d08f466f88209251d54bc09b207.tar.gz linux-stable-2bc6b218717b9d08f466f88209251d54bc09b207.zip | |
arm64/boot: Disable trapping of PMZR_EL0 writes to EL2grafted
__init_el2_fgt2() writes one mask to both HDFGRTR2_EL2 and HDFGWTR2_EL2.
PMZR_EL0 is write-only, so its trap bit, nPMZR_EL0, exists only in
HDFGWTR2_EL2 and is therefore never set: a PMZR_EL0 write from the host
traps to EL2, where the nVHE hypervisor has no handler and BUG()s. The
kernel never writes PMZR_EL0, but kernel.perf_user_access=1 has the PMU
driver set PMUSERENR_EL0.UEN for a task with a user-read event, so a
write from EL0 reaches the trap and takes the host down without a panic
message.
Accumulate the HDFGWTR2_EL2 bits separately, as __init_el2_fgt() already
does for HDFGWTR_EL2, and set nPMZR_EL0 with the other FEAT_PMUv3p9
bits.
Fixes: 858c7bfcb35e1 ("arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9")
Cc: stable@vger.kernel.org
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
Reviewed-by: Oliver Upton <oupton@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'Documentation/livepatch/system-state.rst')
| -rw-r--r-- | Documentation/livepatch/system-state.rst | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/Documentation/livepatch/system-state.rst b/Documentation/livepatch/system-state.rst new file mode 100644 index 000000000..7a3935fd8 --- /dev/null +++ b/Documentation/livepatch/system-state.rst @@ -0,0 +1,167 @@ +==================== +System State Changes +==================== + +Some users are really reluctant to reboot a system. This brings the need +to provide more livepatches and maintain some compatibility between them. + +Maintaining more livepatches is much easier with cumulative livepatches. +Each new livepatch completely replaces any older one. It can keep, +add, and even remove fixes. And it is typically safe to replace any version +of the livepatch with any other one thanks to the atomic replace feature. + +The problems might come with shadow variables and callbacks. They might +change the system behavior or state so that it is no longer safe to +go back and use an older livepatch or the original kernel code. Also +any new livepatch must be able to detect what changes have already been +done by the already installed livepatches. + +This is where the livepatch system state tracking gets useful. It +allows to: + + - store data needed to manipulate and restore the system state + + - define compatibility between livepatches using a change id + and version + + +1. Livepatch system state API +============================= + +The state of the system might get modified either by several livepatch callbacks +or by the newly used code. Also it must be possible to find changes done by +already installed livepatches. + +Each modified state is described by struct klp_state, see +include/linux/livepatch.h. + +Each livepatch defines an array of struct klp_states. They mention +all states that the livepatch modifies. + +The livepatch author must define the following two fields for each +struct klp_state: + + - *id* + + - Non-zero number used to identify the affected system state. + + - *version* + + - Number describing the variant of the system state change that + is supported by the given livepatch. + +The state can be manipulated using two functions: + + - klp_get_state() + + - Get struct klp_state associated with the given livepatch + and state id. + + - klp_get_prev_state() + + - Get struct klp_state associated with the given feature id and + already installed livepatches. + +2. Livepatch compatibility +========================== + +The system state version is used to prevent loading incompatible livepatches. +The check is done when the livepatch is enabled. The rules are: + + - Any completely new system state modification is allowed. + + - System state modifications with the same or higher version are allowed + for already modified system states. + + - Cumulative livepatches must handle all system state modifications from + already installed livepatches. + + - Non-cumulative livepatches are allowed to touch already modified + system states. + +3. Supported scenarios +====================== + +Livepatches have their life-cycle and the same is true for the system +state changes. Every compatible livepatch has to support the following +scenarios: + + - Modify the system state when the livepatch gets enabled and the state + has not been already modified by a livepatches that are being + replaced. + + - Take over or update the system state modification when is has already + been done by a livepatch that is being replaced. + + - Restore the original state when the livepatch is disabled. + + - Restore the previous state when the transition is reverted. + It might be the original system state or the state modification + done by livepatches that were being replaced. + + - Remove any already made changes when error occurs and the livepatch + cannot get enabled. + +4. Expected usage +================= + +System states are usually modified by livepatch callbacks. The expected +role of each callback is as follows: + +*pre_patch()* + + - Allocate *state->data* when necessary. The allocation might fail + and *pre_patch()* is the only callback that could stop loading + of the livepatch. The allocation is not needed when the data + are already provided by previously installed livepatches. + + - Do any other preparatory action that is needed by + the new code even before the transition gets finished. + For example, initialize *state->data*. + + The system state itself is typically modified in *post_patch()* + when the entire system is able to handle it. + + - Clean up its own mess in case of error. It might be done by a custom + code or by calling *post_unpatch()* explicitly. + +*post_patch()* + + - Copy *state->data* from the previous livepatch when they are + compatible. + + - Do the actual system state modification. Eventually allow + the new code to use it. + + - Make sure that *state->data* has all necessary information. + + - Free *state->data* from replaces livepatches when they are + not longer needed. + +*pre_unpatch()* + + - Prevent the code, added by the livepatch, relying on the system + state change. + + - Revert the system state modification.. + +*post_unpatch()* + + - Distinguish transition reverse and livepatch disabling by + checking *klp_get_prev_state()*. + + - In case of transition reverse, restore the previous system + state. It might mean doing nothing. + + - Remove any not longer needed setting or data. + +.. note:: + + *pre_unpatch()* typically does symmetric operations to *post_patch()*. + Except that it is called only when the livepatch is being disabled. + Therefore it does not need to care about any previously installed + livepatch. + + *post_unpatch()* typically does symmetric operations to *pre_patch()*. + It might be called also during the transition reverse. Therefore it + has to handle the state of the previously installed livepatches. |
