tools/testing/selftests/kvm/x86/debug_regs.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/x86/debug_regs.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/x86/debug_regs.c
Extension
.c
Size
9374 bytes
Lines
300
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * KVM guest debug register tests
 *
 * Copyright (C) 2020, Red Hat, Inc.
 */
#include <stdio.h>
#include <string.h>
#include "kvm_util.h"
#include "processor.h"
#include "apic.h"

#define DR6_BD		(1 << 13)
#define DR7_GD		(1 << 13)

#define IRQ_VECTOR 0xAA

#define  CAST_TO_RIP(v)  ((unsigned long long)&(v))

/* For testing data access debug BP */
u32 guest_value;

extern unsigned char sw_bp, hw_bp, write_data, ss_start, bd_start;
extern unsigned char fep_bd_start, fep_sti_start, fep_sti_end;

static int irqs_received;

static void guest_db_handler(struct ex_regs *regs)
{
	static int count;
	unsigned long target_rips[2] = {
		CAST_TO_RIP(fep_sti_start),
		CAST_TO_RIP(fep_sti_end),
	};

	__GUEST_ASSERT(regs->rip == target_rips[count],
	               "STI[%u]: unexpected rip 0x%lx (should be 0x%lx)",
		       count, regs->rip, target_rips[count]);
	regs->rflags &= ~X86_EFLAGS_TF;
	count++;
}

static void guest_irq_handler(struct ex_regs *regs)
{
	/*
	 * The pending IRQ should finally be take when KVM_GUESTDBG_BLOCKIRQ is
	 * cleared and IRQs are enabled.  Note, the IRQ is expected to arrive
	 * on the instruction immediately after STI, even though its in an STI
	 * shadow.  Because the next instruction has a coincident #DB, and #DBs
	 * are not subject to STI-blocking, the #DB will push RFLAGS.IF=1 on
	 * the stack, and the eventual IRET will unmask IRQs and obliterate the
	 * STI shadow in the process.
	 */
	unsigned long target_rip = CAST_TO_RIP(fep_sti_start);

	__GUEST_ASSERT(regs->rip == target_rip,
		       "IRQ: unexpected rip 0x%lx (should be 0x%lx)",
		       regs->rip, target_rip);

	irqs_received++;
	x2apic_write_reg(APIC_EOI, 0);
}

static void guest_code(void)
{
	/* Create a pending interrupt on current vCPU */
	x2apic_enable();
	x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT |
			 APIC_DM_FIXED | IRQ_VECTOR);

	/*
	 * Software BP tests.
	 *
	 * NOTE: sw_bp need to be before the cmd here, because int3 is an
	 * exception rather than a normal trap for KVM_SET_GUEST_DEBUG (we
	 * capture it using the vcpu exception bitmap).
	 */
	asm volatile("sw_bp: int3");

	/* Hardware instruction BP test */
	asm volatile("hw_bp: nop");

	/* Hardware data BP test */
	asm volatile("mov $1234,%%rax;\n\t"
		     "mov %%rax,%0;\n\t write_data:"
		     : "=m" (guest_value) : : "rax");

	/*
	 * Single step test, covers 2 basic instructions and 2 emulated
	 *

Annotation

Implementation Notes