cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tdp_iter.c (5288B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3#include "mmu_internal.h"
      4#include "tdp_iter.h"
      5#include "spte.h"
      6
      7/*
      8 * Recalculates the pointer to the SPTE for the current GFN and level and
      9 * reread the SPTE.
     10 */
     11static void tdp_iter_refresh_sptep(struct tdp_iter *iter)
     12{
     13	iter->sptep = iter->pt_path[iter->level - 1] +
     14		SHADOW_PT_INDEX(iter->gfn << PAGE_SHIFT, iter->level);
     15	iter->old_spte = kvm_tdp_mmu_read_spte(iter->sptep);
     16}
     17
     18static gfn_t round_gfn_for_level(gfn_t gfn, int level)
     19{
     20	return gfn & -KVM_PAGES_PER_HPAGE(level);
     21}
     22
     23/*
     24 * Return the TDP iterator to the root PT and allow it to continue its
     25 * traversal over the paging structure from there.
     26 */
     27void tdp_iter_restart(struct tdp_iter *iter)
     28{
     29	iter->yielded = false;
     30	iter->yielded_gfn = iter->next_last_level_gfn;
     31	iter->level = iter->root_level;
     32
     33	iter->gfn = round_gfn_for_level(iter->next_last_level_gfn, iter->level);
     34	tdp_iter_refresh_sptep(iter);
     35
     36	iter->valid = true;
     37}
     38
     39/*
     40 * Sets a TDP iterator to walk a pre-order traversal of the paging structure
     41 * rooted at root_pt, starting with the walk to translate next_last_level_gfn.
     42 */
     43void tdp_iter_start(struct tdp_iter *iter, struct kvm_mmu_page *root,
     44		    int min_level, gfn_t next_last_level_gfn)
     45{
     46	int root_level = root->role.level;
     47
     48	WARN_ON(root_level < 1);
     49	WARN_ON(root_level > PT64_ROOT_MAX_LEVEL);
     50
     51	iter->next_last_level_gfn = next_last_level_gfn;
     52	iter->root_level = root_level;
     53	iter->min_level = min_level;
     54	iter->pt_path[iter->root_level - 1] = (tdp_ptep_t)root->spt;
     55	iter->as_id = kvm_mmu_page_as_id(root);
     56
     57	tdp_iter_restart(iter);
     58}
     59
     60/*
     61 * Given an SPTE and its level, returns a pointer containing the host virtual
     62 * address of the child page table referenced by the SPTE. Returns null if
     63 * there is no such entry.
     64 */
     65tdp_ptep_t spte_to_child_pt(u64 spte, int level)
     66{
     67	/*
     68	 * There's no child entry if this entry isn't present or is a
     69	 * last-level entry.
     70	 */
     71	if (!is_shadow_present_pte(spte) || is_last_spte(spte, level))
     72		return NULL;
     73
     74	return (tdp_ptep_t)__va(spte_to_pfn(spte) << PAGE_SHIFT);
     75}
     76
     77/*
     78 * Steps down one level in the paging structure towards the goal GFN. Returns
     79 * true if the iterator was able to step down a level, false otherwise.
     80 */
     81static bool try_step_down(struct tdp_iter *iter)
     82{
     83	tdp_ptep_t child_pt;
     84
     85	if (iter->level == iter->min_level)
     86		return false;
     87
     88	/*
     89	 * Reread the SPTE before stepping down to avoid traversing into page
     90	 * tables that are no longer linked from this entry.
     91	 */
     92	iter->old_spte = kvm_tdp_mmu_read_spte(iter->sptep);
     93
     94	child_pt = spte_to_child_pt(iter->old_spte, iter->level);
     95	if (!child_pt)
     96		return false;
     97
     98	iter->level--;
     99	iter->pt_path[iter->level - 1] = child_pt;
    100	iter->gfn = round_gfn_for_level(iter->next_last_level_gfn, iter->level);
    101	tdp_iter_refresh_sptep(iter);
    102
    103	return true;
    104}
    105
    106/*
    107 * Steps to the next entry in the current page table, at the current page table
    108 * level. The next entry could point to a page backing guest memory or another
    109 * page table, or it could be non-present. Returns true if the iterator was
    110 * able to step to the next entry in the page table, false if the iterator was
    111 * already at the end of the current page table.
    112 */
    113static bool try_step_side(struct tdp_iter *iter)
    114{
    115	/*
    116	 * Check if the iterator is already at the end of the current page
    117	 * table.
    118	 */
    119	if (SHADOW_PT_INDEX(iter->gfn << PAGE_SHIFT, iter->level) ==
    120            (PT64_ENT_PER_PAGE - 1))
    121		return false;
    122
    123	iter->gfn += KVM_PAGES_PER_HPAGE(iter->level);
    124	iter->next_last_level_gfn = iter->gfn;
    125	iter->sptep++;
    126	iter->old_spte = kvm_tdp_mmu_read_spte(iter->sptep);
    127
    128	return true;
    129}
    130
    131/*
    132 * Tries to traverse back up a level in the paging structure so that the walk
    133 * can continue from the next entry in the parent page table. Returns true on a
    134 * successful step up, false if already in the root page.
    135 */
    136static bool try_step_up(struct tdp_iter *iter)
    137{
    138	if (iter->level == iter->root_level)
    139		return false;
    140
    141	iter->level++;
    142	iter->gfn = round_gfn_for_level(iter->gfn, iter->level);
    143	tdp_iter_refresh_sptep(iter);
    144
    145	return true;
    146}
    147
    148/*
    149 * Step the iterator back up a level in the paging structure. Should only be
    150 * used when the iterator is below the root level.
    151 */
    152void tdp_iter_step_up(struct tdp_iter *iter)
    153{
    154	WARN_ON(!try_step_up(iter));
    155}
    156
    157/*
    158 * Step to the next SPTE in a pre-order traversal of the paging structure.
    159 * To get to the next SPTE, the iterator either steps down towards the goal
    160 * GFN, if at a present, non-last-level SPTE, or over to a SPTE mapping a
    161 * highter GFN.
    162 *
    163 * The basic algorithm is as follows:
    164 * 1. If the current SPTE is a non-last-level SPTE, step down into the page
    165 *    table it points to.
    166 * 2. If the iterator cannot step down, it will try to step to the next SPTE
    167 *    in the current page of the paging structure.
    168 * 3. If the iterator cannot step to the next entry in the current page, it will
    169 *    try to step up to the parent paging structure page. In this case, that
    170 *    SPTE will have already been visited, and so the iterator must also step
    171 *    to the side again.
    172 */
    173void tdp_iter_next(struct tdp_iter *iter)
    174{
    175	if (iter->yielded) {
    176		tdp_iter_restart(iter);
    177		return;
    178	}
    179
    180	if (try_step_down(iter))
    181		return;
    182
    183	do {
    184		if (try_step_side(iter))
    185			return;
    186	} while (try_step_up(iter));
    187	iter->valid = false;
    188}
    189