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

page_track.c (4776B)


      1/*
      2 * Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice (including the next
     12 * paragraph) shall be included in all copies or substantial portions of the
     13 * Software.
     14 *
     15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21 * SOFTWARE.
     22 */
     23#include "i915_drv.h"
     24#include "gvt.h"
     25
     26/**
     27 * intel_vgpu_find_page_track - find page track rcord of guest page
     28 * @vgpu: a vGPU
     29 * @gfn: the gfn of guest page
     30 *
     31 * Returns:
     32 * A pointer to struct intel_vgpu_page_track if found, else NULL returned.
     33 */
     34struct intel_vgpu_page_track *intel_vgpu_find_page_track(
     35		struct intel_vgpu *vgpu, unsigned long gfn)
     36{
     37	return radix_tree_lookup(&vgpu->page_track_tree, gfn);
     38}
     39
     40/**
     41 * intel_vgpu_register_page_track - register a guest page to be tacked
     42 * @vgpu: a vGPU
     43 * @gfn: the gfn of guest page
     44 * @handler: page track handler
     45 * @priv: tracker private
     46 *
     47 * Returns:
     48 * zero on success, negative error code if failed.
     49 */
     50int intel_vgpu_register_page_track(struct intel_vgpu *vgpu, unsigned long gfn,
     51		gvt_page_track_handler_t handler, void *priv)
     52{
     53	struct intel_vgpu_page_track *track;
     54	int ret;
     55
     56	track = intel_vgpu_find_page_track(vgpu, gfn);
     57	if (track)
     58		return -EEXIST;
     59
     60	track = kzalloc(sizeof(*track), GFP_KERNEL);
     61	if (!track)
     62		return -ENOMEM;
     63
     64	track->handler = handler;
     65	track->priv_data = priv;
     66
     67	ret = radix_tree_insert(&vgpu->page_track_tree, gfn, track);
     68	if (ret) {
     69		kfree(track);
     70		return ret;
     71	}
     72
     73	return 0;
     74}
     75
     76/**
     77 * intel_vgpu_unregister_page_track - unregister the tracked guest page
     78 * @vgpu: a vGPU
     79 * @gfn: the gfn of guest page
     80 *
     81 */
     82void intel_vgpu_unregister_page_track(struct intel_vgpu *vgpu,
     83		unsigned long gfn)
     84{
     85	struct intel_vgpu_page_track *track;
     86
     87	track = radix_tree_delete(&vgpu->page_track_tree, gfn);
     88	if (track) {
     89		if (track->tracked)
     90			intel_gvt_page_track_remove(vgpu, gfn);
     91		kfree(track);
     92	}
     93}
     94
     95/**
     96 * intel_vgpu_enable_page_track - set write-protection on guest page
     97 * @vgpu: a vGPU
     98 * @gfn: the gfn of guest page
     99 *
    100 * Returns:
    101 * zero on success, negative error code if failed.
    102 */
    103int intel_vgpu_enable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
    104{
    105	struct intel_vgpu_page_track *track;
    106	int ret;
    107
    108	track = intel_vgpu_find_page_track(vgpu, gfn);
    109	if (!track)
    110		return -ENXIO;
    111
    112	if (track->tracked)
    113		return 0;
    114
    115	ret = intel_gvt_page_track_add(vgpu, gfn);
    116	if (ret)
    117		return ret;
    118	track->tracked = true;
    119	return 0;
    120}
    121
    122/**
    123 * intel_vgpu_enable_page_track - cancel write-protection on guest page
    124 * @vgpu: a vGPU
    125 * @gfn: the gfn of guest page
    126 *
    127 * Returns:
    128 * zero on success, negative error code if failed.
    129 */
    130int intel_vgpu_disable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
    131{
    132	struct intel_vgpu_page_track *track;
    133	int ret;
    134
    135	track = intel_vgpu_find_page_track(vgpu, gfn);
    136	if (!track)
    137		return -ENXIO;
    138
    139	if (!track->tracked)
    140		return 0;
    141
    142	ret = intel_gvt_page_track_remove(vgpu, gfn);
    143	if (ret)
    144		return ret;
    145	track->tracked = false;
    146	return 0;
    147}
    148
    149/**
    150 * intel_vgpu_page_track_handler - called when write to write-protected page
    151 * @vgpu: a vGPU
    152 * @gpa: the gpa of this write
    153 * @data: the writed data
    154 * @bytes: the length of this write
    155 *
    156 * Returns:
    157 * zero on success, negative error code if failed.
    158 */
    159int intel_vgpu_page_track_handler(struct intel_vgpu *vgpu, u64 gpa,
    160		void *data, unsigned int bytes)
    161{
    162	struct intel_vgpu_page_track *page_track;
    163	int ret = 0;
    164
    165	mutex_lock(&vgpu->vgpu_lock);
    166
    167	page_track = intel_vgpu_find_page_track(vgpu, gpa >> PAGE_SHIFT);
    168	if (!page_track) {
    169		ret = -ENXIO;
    170		goto out;
    171	}
    172
    173	if (unlikely(vgpu->failsafe)) {
    174		/* Remove write protection to prevent furture traps. */
    175		intel_gvt_page_track_remove(vgpu, gpa >> PAGE_SHIFT);
    176	} else {
    177		ret = page_track->handler(page_track, gpa, data, bytes);
    178		if (ret)
    179			gvt_err("guest page write error, gpa %llx\n", gpa);
    180	}
    181
    182out:
    183	mutex_unlock(&vgpu->vgpu_lock);
    184	return ret;
    185}