Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,182 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ARM Generic Timer specific interface
*/
#ifndef SELFTEST_KVM_ARCH_TIMER_H
#define SELFTEST_KVM_ARCH_TIMER_H
#include "processor.h"
enum arch_timer {
VIRTUAL,
PHYSICAL,
};
#define CTL_ENABLE (1 << 0)
#define CTL_IMASK (1 << 1)
#define CTL_ISTATUS (1 << 2)
#define msec_to_cycles(msec) \
(timer_get_cntfrq() * (u64)(msec) / 1000)
#define usec_to_cycles(usec) \
(timer_get_cntfrq() * (u64)(usec) / 1000000)
#define cycles_to_usec(cycles) \
((u64)(cycles) * 1000000 / timer_get_cntfrq())
static inline u32 timer_get_cntfrq(void)
{
return read_sysreg(cntfrq_el0);
}
static inline u64 timer_get_cntct(enum arch_timer timer)
{
isb();
switch (timer) {
case VIRTUAL:
return read_sysreg(cntvct_el0);
case PHYSICAL:
return read_sysreg(cntpct_el0);
default:
GUEST_FAIL("Unexpected timer type = %u", timer);
}
/* We should not reach here */
return 0;
}
static inline void timer_set_cval(enum arch_timer timer, u64 cval)
{
switch (timer) {
case VIRTUAL:
write_sysreg(cval, cntv_cval_el0);
break;
case PHYSICAL:
write_sysreg(cval, cntp_cval_el0);
break;
default:
GUEST_FAIL("Unexpected timer type = %u", timer);
}
isb();
}
static inline u64 timer_get_cval(enum arch_timer timer)
{
switch (timer) {
case VIRTUAL:
return read_sysreg(cntv_cval_el0);
case PHYSICAL:
return read_sysreg(cntp_cval_el0);
default:
GUEST_FAIL("Unexpected timer type = %u", timer);
}
/* We should not reach here */
return 0;
}
static inline void timer_set_tval(enum arch_timer timer, s32 tval)
{
switch (timer) {
case VIRTUAL:
write_sysreg(tval, cntv_tval_el0);
break;
case PHYSICAL:
write_sysreg(tval, cntp_tval_el0);
break;
default:
GUEST_FAIL("Unexpected timer type = %u", timer);
}
isb();
}
static inline s32 timer_get_tval(enum arch_timer timer)
{
isb();
switch (timer) {
case VIRTUAL:
return read_sysreg(cntv_tval_el0);
case PHYSICAL:
return read_sysreg(cntp_tval_el0);
default:
GUEST_FAIL("Could not get timer %d\n", timer);
}
/* We should not reach here */
return 0;
}
static inline void timer_set_ctl(enum arch_timer timer, u32 ctl)
{
switch (timer) {
case VIRTUAL:
write_sysreg(ctl, cntv_ctl_el0);
break;
case PHYSICAL:
write_sysreg(ctl, cntp_ctl_el0);
break;
default:
GUEST_FAIL("Unexpected timer type = %u", timer);
}
isb();
}
static inline u32 timer_get_ctl(enum arch_timer timer)
{
switch (timer) {
case VIRTUAL:
return read_sysreg(cntv_ctl_el0);
case PHYSICAL:
return read_sysreg(cntp_ctl_el0);
default:
GUEST_FAIL("Unexpected timer type = %u", timer);
}
/* We should not reach here */
return 0;
}
static inline void timer_set_next_cval_ms(enum arch_timer timer, u32 msec)
{
u64 now_ct = timer_get_cntct(timer);
u64 next_ct = now_ct + msec_to_cycles(msec);
timer_set_cval(timer, next_ct);
}
static inline void timer_set_next_tval_ms(enum arch_timer timer, u32 msec)
{
timer_set_tval(timer, msec_to_cycles(msec));
}
static inline u32 vcpu_get_vtimer_irq(struct kvm_vcpu *vcpu)
{
u32 intid;
u64 attr;
attr = vcpu_has_el2(vcpu) ? KVM_ARM_VCPU_TIMER_IRQ_HVTIMER :
KVM_ARM_VCPU_TIMER_IRQ_VTIMER;
vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL, attr, &intid);
return intid;
}
static inline u32 vcpu_get_ptimer_irq(struct kvm_vcpu *vcpu)
{
u32 intid;
u64 attr;
attr = vcpu_has_el2(vcpu) ? KVM_ARM_VCPU_TIMER_IRQ_HPTIMER :
KVM_ARM_VCPU_TIMER_IRQ_PTIMER;
vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL, attr, &intid);
return intid;
}
#endif /* SELFTEST_KVM_ARCH_TIMER_H */
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ARM simple delay routines
*/
#ifndef SELFTEST_KVM_ARM_DELAY_H
#define SELFTEST_KVM_ARM_DELAY_H
#include "arch_timer.h"
static inline void __delay(u64 cycles)
{
enum arch_timer timer = VIRTUAL;
u64 start = timer_get_cntct(timer);
while ((timer_get_cntct(timer) - start) < cycles)
cpu_relax();
}
static inline void udelay(unsigned long usec)
{
__delay(usec_to_cycles(usec));
}
#endif /* SELFTEST_KVM_ARM_DELAY_H */
@@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ARM Generic Interrupt Controller (GIC) specific defines
*/
#ifndef SELFTEST_KVM_GIC_H
#define SELFTEST_KVM_GIC_H
#include <asm/kvm.h>
enum gic_type {
GIC_V3,
GIC_TYPE_MAX,
};
/*
* Note that the redistributor frames are at the end, as the range scales
* with the number of vCPUs in the VM.
*/
#define GITS_BASE_GPA 0x8000000ULL
#define GICD_BASE_GPA (GITS_BASE_GPA + KVM_VGIC_V3_ITS_SIZE)
#define GICR_BASE_GPA (GICD_BASE_GPA + KVM_VGIC_V3_DIST_SIZE)
/* The GIC is identity-mapped into the guest at the time of setup. */
#define GITS_BASE_GVA ((volatile void *)GITS_BASE_GPA)
#define GICD_BASE_GVA ((volatile void *)GICD_BASE_GPA)
#define GICR_BASE_GVA ((volatile void *)GICR_BASE_GPA)
#define MIN_SGI 0
#define MIN_PPI 16
#define MIN_SPI 32
#define MAX_SPI 1019
#define IAR_SPURIOUS 1023
#define INTID_IS_SGI(intid) (0 <= (intid) && (intid) < MIN_PPI)
#define INTID_IS_PPI(intid) (MIN_PPI <= (intid) && (intid) < MIN_SPI)
#define INTID_IS_SPI(intid) (MIN_SPI <= (intid) && (intid) <= MAX_SPI)
void gic_init(enum gic_type type, unsigned int nr_cpus);
void gic_irq_enable(unsigned int intid);
void gic_irq_disable(unsigned int intid);
unsigned int gic_get_and_ack_irq(void);
void gic_set_eoi(unsigned int intid);
void gic_set_dir(unsigned int intid);
/*
* Sets the EOI mode. When split is false, EOI just drops the priority. When
* split is true, EOI drops the priority and deactivates the interrupt.
*/
void gic_set_eoi_split(bool split);
void gic_set_priority_mask(u64 mask);
void gic_set_priority(u32 intid, u32 prio);
void gic_irq_set_active(unsigned int intid);
void gic_irq_clear_active(unsigned int intid);
bool gic_irq_get_active(unsigned int intid);
void gic_irq_set_pending(unsigned int intid);
void gic_irq_clear_pending(unsigned int intid);
bool gic_irq_get_pending(unsigned int intid);
void gic_irq_set_config(unsigned int intid, bool is_edge);
void gic_irq_set_group(unsigned int intid, bool group);
void gic_rdist_enable_lpis(gpa_t cfg_table, size_t cfg_table_size,
gpa_t pend_table);
#endif /* SELFTEST_KVM_GIC_H */
@@ -0,0 +1,604 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
* Author: Marc Zyngier <marc.zyngier@arm.com>
*/
#ifndef __SELFTESTS_GIC_V3_H
#define __SELFTESTS_GIC_V3_H
/*
* Distributor registers. We assume we're running non-secure, with ARE
* being set. Secure-only and non-ARE registers are not described.
*/
#define GICD_CTLR 0x0000
#define GICD_TYPER 0x0004
#define GICD_IIDR 0x0008
#define GICD_TYPER2 0x000C
#define GICD_STATUSR 0x0010
#define GICD_SETSPI_NSR 0x0040
#define GICD_CLRSPI_NSR 0x0048
#define GICD_SETSPI_SR 0x0050
#define GICD_CLRSPI_SR 0x0058
#define GICD_IGROUPR 0x0080
#define GICD_ISENABLER 0x0100
#define GICD_ICENABLER 0x0180
#define GICD_ISPENDR 0x0200
#define GICD_ICPENDR 0x0280
#define GICD_ISACTIVER 0x0300
#define GICD_ICACTIVER 0x0380
#define GICD_IPRIORITYR 0x0400
#define GICD_ICFGR 0x0C00
#define GICD_IGRPMODR 0x0D00
#define GICD_NSACR 0x0E00
#define GICD_IGROUPRnE 0x1000
#define GICD_ISENABLERnE 0x1200
#define GICD_ICENABLERnE 0x1400
#define GICD_ISPENDRnE 0x1600
#define GICD_ICPENDRnE 0x1800
#define GICD_ISACTIVERnE 0x1A00
#define GICD_ICACTIVERnE 0x1C00
#define GICD_IPRIORITYRnE 0x2000
#define GICD_ICFGRnE 0x3000
#define GICD_IROUTER 0x6000
#define GICD_IROUTERnE 0x8000
#define GICD_IDREGS 0xFFD0
#define GICD_PIDR2 0xFFE8
#define ESPI_BASE_INTID 4096
/*
* Those registers are actually from GICv2, but the spec demands that they
* are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).
*/
#define GICD_ITARGETSR 0x0800
#define GICD_SGIR 0x0F00
#define GICD_CPENDSGIR 0x0F10
#define GICD_SPENDSGIR 0x0F20
#define GICD_CTLR_RWP (1U << 31)
#define GICD_CTLR_nASSGIreq (1U << 8)
#define GICD_CTLR_DS (1U << 6)
#define GICD_CTLR_ARE_NS (1U << 4)
#define GICD_CTLR_ENABLE_G1A (1U << 1)
#define GICD_CTLR_ENABLE_G1 (1U << 0)
#define GICD_IIDR_IMPLEMENTER_SHIFT 0
#define GICD_IIDR_IMPLEMENTER_MASK (0xfff << GICD_IIDR_IMPLEMENTER_SHIFT)
#define GICD_IIDR_REVISION_SHIFT 12
#define GICD_IIDR_REVISION_MASK (0xf << GICD_IIDR_REVISION_SHIFT)
#define GICD_IIDR_VARIANT_SHIFT 16
#define GICD_IIDR_VARIANT_MASK (0xf << GICD_IIDR_VARIANT_SHIFT)
#define GICD_IIDR_PRODUCT_ID_SHIFT 24
#define GICD_IIDR_PRODUCT_ID_MASK (0xff << GICD_IIDR_PRODUCT_ID_SHIFT)
/*
* In systems with a single security state (what we emulate in KVM)
* the meaning of the interrupt group enable bits is slightly different
*/
#define GICD_CTLR_ENABLE_SS_G1 (1U << 1)
#define GICD_CTLR_ENABLE_SS_G0 (1U << 0)
#define GICD_TYPER_RSS (1U << 26)
#define GICD_TYPER_LPIS (1U << 17)
#define GICD_TYPER_MBIS (1U << 16)
#define GICD_TYPER_ESPI (1U << 8)
#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)
#define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1)
#define GICD_TYPER_SPIS(typer) ((((typer) & 0x1f) + 1) * 32)
#define GICD_TYPER_ESPIS(typer) \
(((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
#define GICD_TYPER2_nASSGIcap (1U << 8)
#define GICD_TYPER2_VIL (1U << 7)
#define GICD_TYPER2_VID GENMASK(4, 0)
#define GICD_IROUTER_SPI_MODE_ONE (0U << 31)
#define GICD_IROUTER_SPI_MODE_ANY (1U << 31)
#define GIC_PIDR2_ARCH_MASK 0xf0
#define GIC_PIDR2_ARCH_GICv3 0x30
#define GIC_PIDR2_ARCH_GICv4 0x40
#define GIC_V3_DIST_SIZE 0x10000
#define GIC_PAGE_SIZE_4K 0ULL
#define GIC_PAGE_SIZE_16K 1ULL
#define GIC_PAGE_SIZE_64K 2ULL
#define GIC_PAGE_SIZE_MASK 3ULL
/*
* Re-Distributor registers, offsets from RD_base
*/
#define GICR_CTLR GICD_CTLR
#define GICR_IIDR 0x0004
#define GICR_TYPER 0x0008
#define GICR_STATUSR GICD_STATUSR
#define GICR_WAKER 0x0014
#define GICR_SETLPIR 0x0040
#define GICR_CLRLPIR 0x0048
#define GICR_PROPBASER 0x0070
#define GICR_PENDBASER 0x0078
#define GICR_INVLPIR 0x00A0
#define GICR_INVALLR 0x00B0
#define GICR_SYNCR 0x00C0
#define GICR_IDREGS GICD_IDREGS
#define GICR_PIDR2 GICD_PIDR2
#define GICR_CTLR_ENABLE_LPIS (1UL << 0)
#define GICR_CTLR_CES (1UL << 1)
#define GICR_CTLR_IR (1UL << 2)
#define GICR_CTLR_RWP (1UL << 3)
#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff)
#define EPPI_BASE_INTID 1056
#define GICR_TYPER_NR_PPIS(r) \
({ \
unsigned int __ppinum = ((r) >> 27) & 0x1f; \
unsigned int __nr_ppis = 16; \
if (__ppinum == 1 || __ppinum == 2) \
__nr_ppis += __ppinum * 32; \
\
__nr_ppis; \
})
#define GICR_WAKER_ProcessorSleep (1U << 1)
#define GICR_WAKER_ChildrenAsleep (1U << 2)
#define GIC_BASER_CACHE_nCnB 0ULL
#define GIC_BASER_CACHE_SameAsInner 0ULL
#define GIC_BASER_CACHE_nC 1ULL
#define GIC_BASER_CACHE_RaWt 2ULL
#define GIC_BASER_CACHE_RaWb 3ULL
#define GIC_BASER_CACHE_WaWt 4ULL
#define GIC_BASER_CACHE_WaWb 5ULL
#define GIC_BASER_CACHE_RaWaWt 6ULL
#define GIC_BASER_CACHE_RaWaWb 7ULL
#define GIC_BASER_CACHE_MASK 7ULL
#define GIC_BASER_NonShareable 0ULL
#define GIC_BASER_InnerShareable 1ULL
#define GIC_BASER_OuterShareable 2ULL
#define GIC_BASER_SHAREABILITY_MASK 3ULL
#define GIC_BASER_CACHEABILITY(reg, inner_outer, type) \
(GIC_BASER_CACHE_##type << reg##_##inner_outer##_CACHEABILITY_SHIFT)
#define GIC_BASER_SHAREABILITY(reg, type) \
(GIC_BASER_##type << reg##_SHAREABILITY_SHIFT)
/* encode a size field of width @w containing @n - 1 units */
#define GIC_ENCODE_SZ(n, w) (((unsigned long)(n) - 1) & GENMASK_ULL(((w) - 1), 0))
#define GICR_PROPBASER_SHAREABILITY_SHIFT (10)
#define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT (7)
#define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT (56)
#define GICR_PROPBASER_SHAREABILITY_MASK \
GIC_BASER_SHAREABILITY(GICR_PROPBASER, SHAREABILITY_MASK)
#define GICR_PROPBASER_INNER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, MASK)
#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_PROPBASER, OUTER, MASK)
#define GICR_PROPBASER_CACHEABILITY_MASK GICR_PROPBASER_INNER_CACHEABILITY_MASK
#define GICR_PROPBASER_InnerShareable \
GIC_BASER_SHAREABILITY(GICR_PROPBASER, InnerShareable)
#define GICR_PROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nCnB)
#define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC)
#define GICR_PROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWt)
#define GICR_PROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWb)
#define GICR_PROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWt)
#define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb)
#define GICR_PROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWt)
#define GICR_PROPBASER_RaWaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWb)
#define GICR_PROPBASER_IDBITS_MASK (0x1f)
#define GICR_PROPBASER_ADDRESS(x) ((x) & GENMASK_ULL(51, 12))
#define GICR_PENDBASER_ADDRESS(x) ((x) & GENMASK_ULL(51, 16))
#define GICR_PENDBASER_SHAREABILITY_SHIFT (10)
#define GICR_PENDBASER_INNER_CACHEABILITY_SHIFT (7)
#define GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT (56)
#define GICR_PENDBASER_SHAREABILITY_MASK \
GIC_BASER_SHAREABILITY(GICR_PENDBASER, SHAREABILITY_MASK)
#define GICR_PENDBASER_INNER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, MASK)
#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_PENDBASER, OUTER, MASK)
#define GICR_PENDBASER_CACHEABILITY_MASK GICR_PENDBASER_INNER_CACHEABILITY_MASK
#define GICR_PENDBASER_InnerShareable \
GIC_BASER_SHAREABILITY(GICR_PENDBASER, InnerShareable)
#define GICR_PENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nCnB)
#define GICR_PENDBASER_nC GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nC)
#define GICR_PENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWt)
#define GICR_PENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWb)
#define GICR_PENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWt)
#define GICR_PENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWb)
#define GICR_PENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWaWt)
#define GICR_PENDBASER_RaWaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWaWb)
#define GICR_PENDBASER_PTZ BIT_ULL(62)
/*
* Re-Distributor registers, offsets from SGI_base
*/
#define GICR_IGROUPR0 GICD_IGROUPR
#define GICR_ISENABLER0 GICD_ISENABLER
#define GICR_ICENABLER0 GICD_ICENABLER
#define GICR_ISPENDR0 GICD_ISPENDR
#define GICR_ICPENDR0 GICD_ICPENDR
#define GICR_ISACTIVER0 GICD_ISACTIVER
#define GICR_ICACTIVER0 GICD_ICACTIVER
#define GICR_IPRIORITYR0 GICD_IPRIORITYR
#define GICR_ICFGR0 GICD_ICFGR
#define GICR_IGRPMODR0 GICD_IGRPMODR
#define GICR_NSACR GICD_NSACR
#define GICR_TYPER_PLPIS (1U << 0)
#define GICR_TYPER_VLPIS (1U << 1)
#define GICR_TYPER_DIRTY (1U << 2)
#define GICR_TYPER_DirectLPIS (1U << 3)
#define GICR_TYPER_LAST (1U << 4)
#define GICR_TYPER_RVPEID (1U << 7)
#define GICR_TYPER_COMMON_LPI_AFF GENMASK_ULL(25, 24)
#define GICR_TYPER_AFFINITY GENMASK_ULL(63, 32)
#define GICR_INVLPIR_INTID GENMASK_ULL(31, 0)
#define GICR_INVLPIR_VPEID GENMASK_ULL(47, 32)
#define GICR_INVLPIR_V GENMASK_ULL(63, 63)
#define GICR_INVALLR_VPEID GICR_INVLPIR_VPEID
#define GICR_INVALLR_V GICR_INVLPIR_V
#define GIC_V3_REDIST_SIZE 0x20000
#define LPI_PROP_GROUP1 (1 << 1)
#define LPI_PROP_ENABLED (1 << 0)
/*
* Re-Distributor registers, offsets from VLPI_base
*/
#define GICR_VPROPBASER 0x0070
#define GICR_VPROPBASER_IDBITS_MASK 0x1f
#define GICR_VPROPBASER_SHAREABILITY_SHIFT (10)
#define GICR_VPROPBASER_INNER_CACHEABILITY_SHIFT (7)
#define GICR_VPROPBASER_OUTER_CACHEABILITY_SHIFT (56)
#define GICR_VPROPBASER_SHAREABILITY_MASK \
GIC_BASER_SHAREABILITY(GICR_VPROPBASER, SHAREABILITY_MASK)
#define GICR_VPROPBASER_INNER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, MASK)
#define GICR_VPROPBASER_OUTER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_VPROPBASER, OUTER, MASK)
#define GICR_VPROPBASER_CACHEABILITY_MASK \
GICR_VPROPBASER_INNER_CACHEABILITY_MASK
#define GICR_VPROPBASER_InnerShareable \
GIC_BASER_SHAREABILITY(GICR_VPROPBASER, InnerShareable)
#define GICR_VPROPBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nCnB)
#define GICR_VPROPBASER_nC GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, nC)
#define GICR_VPROPBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWt)
#define GICR_VPROPBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWb)
#define GICR_VPROPBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWt)
#define GICR_VPROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, WaWb)
#define GICR_VPROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWt)
#define GICR_VPROPBASER_RaWaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWb)
/*
* GICv4.1 VPROPBASER reinvention. A subtle mix between the old
* VPROPBASER and ITS_BASER. Just not quite any of the two.
*/
#define GICR_VPROPBASER_4_1_VALID (1ULL << 63)
#define GICR_VPROPBASER_4_1_ENTRY_SIZE GENMASK_ULL(61, 59)
#define GICR_VPROPBASER_4_1_INDIRECT (1ULL << 55)
#define GICR_VPROPBASER_4_1_PAGE_SIZE GENMASK_ULL(54, 53)
#define GICR_VPROPBASER_4_1_Z (1ULL << 52)
#define GICR_VPROPBASER_4_1_ADDR GENMASK_ULL(51, 12)
#define GICR_VPROPBASER_4_1_SIZE GENMASK_ULL(6, 0)
#define GICR_VPENDBASER 0x0078
#define GICR_VPENDBASER_SHAREABILITY_SHIFT (10)
#define GICR_VPENDBASER_INNER_CACHEABILITY_SHIFT (7)
#define GICR_VPENDBASER_OUTER_CACHEABILITY_SHIFT (56)
#define GICR_VPENDBASER_SHAREABILITY_MASK \
GIC_BASER_SHAREABILITY(GICR_VPENDBASER, SHAREABILITY_MASK)
#define GICR_VPENDBASER_INNER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, MASK)
#define GICR_VPENDBASER_OUTER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GICR_VPENDBASER, OUTER, MASK)
#define GICR_VPENDBASER_CACHEABILITY_MASK \
GICR_VPENDBASER_INNER_CACHEABILITY_MASK
#define GICR_VPENDBASER_NonShareable \
GIC_BASER_SHAREABILITY(GICR_VPENDBASER, NonShareable)
#define GICR_VPENDBASER_InnerShareable \
GIC_BASER_SHAREABILITY(GICR_VPENDBASER, InnerShareable)
#define GICR_VPENDBASER_nCnB GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nCnB)
#define GICR_VPENDBASER_nC GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, nC)
#define GICR_VPENDBASER_RaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWt)
#define GICR_VPENDBASER_RaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWb)
#define GICR_VPENDBASER_WaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWt)
#define GICR_VPENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, WaWb)
#define GICR_VPENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWaWt)
#define GICR_VPENDBASER_RaWaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, RaWaWb)
#define GICR_VPENDBASER_Dirty (1ULL << 60)
#define GICR_VPENDBASER_PendingLast (1ULL << 61)
#define GICR_VPENDBASER_IDAI (1ULL << 62)
#define GICR_VPENDBASER_Valid (1ULL << 63)
/*
* GICv4.1 VPENDBASER, used for VPE residency. On top of these fields,
* also use the above Valid, PendingLast and Dirty.
*/
#define GICR_VPENDBASER_4_1_DB (1ULL << 62)
#define GICR_VPENDBASER_4_1_VGRP0EN (1ULL << 59)
#define GICR_VPENDBASER_4_1_VGRP1EN (1ULL << 58)
#define GICR_VPENDBASER_4_1_VPEID GENMASK_ULL(15, 0)
#define GICR_VSGIR 0x0080
#define GICR_VSGIR_VPEID GENMASK(15, 0)
#define GICR_VSGIPENDR 0x0088
#define GICR_VSGIPENDR_BUSY (1U << 31)
#define GICR_VSGIPENDR_PENDING GENMASK(15, 0)
/*
* ITS registers, offsets from ITS_base
*/
#define GITS_CTLR 0x0000
#define GITS_IIDR 0x0004
#define GITS_TYPER 0x0008
#define GITS_MPIDR 0x0018
#define GITS_CBASER 0x0080
#define GITS_CWRITER 0x0088
#define GITS_CREADR 0x0090
#define GITS_BASER 0x0100
#define GITS_IDREGS_BASE 0xffd0
#define GITS_PIDR0 0xffe0
#define GITS_PIDR1 0xffe4
#define GITS_PIDR2 GICR_PIDR2
#define GITS_PIDR4 0xffd0
#define GITS_CIDR0 0xfff0
#define GITS_CIDR1 0xfff4
#define GITS_CIDR2 0xfff8
#define GITS_CIDR3 0xfffc
#define GITS_TRANSLATER 0x10040
#define GITS_SGIR 0x20020
#define GITS_SGIR_VPEID GENMASK_ULL(47, 32)
#define GITS_SGIR_VINTID GENMASK_ULL(3, 0)
#define GITS_CTLR_ENABLE (1U << 0)
#define GITS_CTLR_ImDe (1U << 1)
#define GITS_CTLR_ITS_NUMBER_SHIFT 4
#define GITS_CTLR_ITS_NUMBER (0xFU << GITS_CTLR_ITS_NUMBER_SHIFT)
#define GITS_CTLR_QUIESCENT (1U << 31)
#define GITS_TYPER_PLPIS (1UL << 0)
#define GITS_TYPER_VLPIS (1UL << 1)
#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT 4
#define GITS_TYPER_ITT_ENTRY_SIZE GENMASK_ULL(7, 4)
#define GITS_TYPER_IDBITS_SHIFT 8
#define GITS_TYPER_DEVBITS_SHIFT 13
#define GITS_TYPER_DEVBITS GENMASK_ULL(17, 13)
#define GITS_TYPER_PTA (1UL << 19)
#define GITS_TYPER_HCC_SHIFT 24
#define GITS_TYPER_HCC(r) (((r) >> GITS_TYPER_HCC_SHIFT) & 0xff)
#define GITS_TYPER_VMOVP (1ULL << 37)
#define GITS_TYPER_VMAPP (1ULL << 40)
#define GITS_TYPER_SVPET GENMASK_ULL(42, 41)
#define GITS_IIDR_REV_SHIFT 12
#define GITS_IIDR_REV_MASK (0xf << GITS_IIDR_REV_SHIFT)
#define GITS_IIDR_REV(r) (((r) >> GITS_IIDR_REV_SHIFT) & 0xf)
#define GITS_IIDR_PRODUCTID_SHIFT 24
#define GITS_CBASER_VALID (1ULL << 63)
#define GITS_CBASER_SHAREABILITY_SHIFT (10)
#define GITS_CBASER_INNER_CACHEABILITY_SHIFT (59)
#define GITS_CBASER_OUTER_CACHEABILITY_SHIFT (53)
#define GITS_CBASER_SHAREABILITY_MASK \
GIC_BASER_SHAREABILITY(GITS_CBASER, SHAREABILITY_MASK)
#define GITS_CBASER_INNER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, MASK)
#define GITS_CBASER_OUTER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GITS_CBASER, OUTER, MASK)
#define GITS_CBASER_CACHEABILITY_MASK GITS_CBASER_INNER_CACHEABILITY_MASK
#define GITS_CBASER_InnerShareable \
GIC_BASER_SHAREABILITY(GITS_CBASER, InnerShareable)
#define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB)
#define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC)
#define GITS_CBASER_RaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)
#define GITS_CBASER_RaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWb)
#define GITS_CBASER_WaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt)
#define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb)
#define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt)
#define GITS_CBASER_RaWaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWb)
#define GITS_CBASER_ADDRESS(cbaser) ((cbaser) & GENMASK_ULL(51, 12))
#define GITS_BASER_NR_REGS 8
#define GITS_BASER_VALID (1ULL << 63)
#define GITS_BASER_INDIRECT (1ULL << 62)
#define GITS_BASER_INNER_CACHEABILITY_SHIFT (59)
#define GITS_BASER_OUTER_CACHEABILITY_SHIFT (53)
#define GITS_BASER_INNER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GITS_BASER, INNER, MASK)
#define GITS_BASER_CACHEABILITY_MASK GITS_BASER_INNER_CACHEABILITY_MASK
#define GITS_BASER_OUTER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, MASK)
#define GITS_BASER_SHAREABILITY_MASK \
GIC_BASER_SHAREABILITY(GITS_BASER, SHAREABILITY_MASK)
#define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nCnB)
#define GITS_BASER_nC GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC)
#define GITS_BASER_RaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWt)
#define GITS_BASER_RaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)
#define GITS_BASER_WaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWt)
#define GITS_BASER_WaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWb)
#define GITS_BASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWaWt)
#define GITS_BASER_RaWaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWaWb)
#define GITS_BASER_TYPE_SHIFT (56)
#define GITS_BASER_TYPE(r) (((r) >> GITS_BASER_TYPE_SHIFT) & 7)
#define GITS_BASER_ENTRY_SIZE_SHIFT (48)
#define GITS_BASER_ENTRY_SIZE(r) ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
#define GITS_BASER_ENTRY_SIZE_MASK GENMASK_ULL(52, 48)
#define GITS_BASER_PHYS_52_to_48(phys) \
(((phys) & GENMASK_ULL(47, 16)) | (((phys) >> 48) & 0xf) << 12)
#define GITS_BASER_ADDR_48_to_52(baser) \
(((baser) & GENMASK_ULL(47, 16)) | (((baser) >> 12) & 0xf) << 48)
#define GITS_BASER_SHAREABILITY_SHIFT (10)
#define GITS_BASER_InnerShareable \
GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
#define GITS_BASER_PAGE_SIZE_SHIFT (8)
#define __GITS_BASER_PSZ(sz) (GIC_PAGE_SIZE_ ## sz << GITS_BASER_PAGE_SIZE_SHIFT)
#define GITS_BASER_PAGE_SIZE_4K __GITS_BASER_PSZ(4K)
#define GITS_BASER_PAGE_SIZE_16K __GITS_BASER_PSZ(16K)
#define GITS_BASER_PAGE_SIZE_64K __GITS_BASER_PSZ(64K)
#define GITS_BASER_PAGE_SIZE_MASK __GITS_BASER_PSZ(MASK)
#define GITS_BASER_PAGES_MAX 256
#define GITS_BASER_PAGES_SHIFT (0)
#define GITS_BASER_NR_PAGES(r) (((r) & 0xff) + 1)
#define GITS_BASER_TYPE_NONE 0
#define GITS_BASER_TYPE_DEVICE 1
#define GITS_BASER_TYPE_VCPU 2
#define GITS_BASER_TYPE_RESERVED3 3
#define GITS_BASER_TYPE_COLLECTION 4
#define GITS_BASER_TYPE_RESERVED5 5
#define GITS_BASER_TYPE_RESERVED6 6
#define GITS_BASER_TYPE_RESERVED7 7
#define GITS_LVL1_ENTRY_SIZE (8UL)
/*
* ITS commands
*/
#define GITS_CMD_MAPD 0x08
#define GITS_CMD_MAPC 0x09
#define GITS_CMD_MAPTI 0x0a
#define GITS_CMD_MAPI 0x0b
#define GITS_CMD_MOVI 0x01
#define GITS_CMD_DISCARD 0x0f
#define GITS_CMD_INV 0x0c
#define GITS_CMD_MOVALL 0x0e
#define GITS_CMD_INVALL 0x0d
#define GITS_CMD_INT 0x03
#define GITS_CMD_CLEAR 0x04
#define GITS_CMD_SYNC 0x05
/*
* GICv4 ITS specific commands
*/
#define GITS_CMD_GICv4(x) ((x) | 0x20)
#define GITS_CMD_VINVALL GITS_CMD_GICv4(GITS_CMD_INVALL)
#define GITS_CMD_VMAPP GITS_CMD_GICv4(GITS_CMD_MAPC)
#define GITS_CMD_VMAPTI GITS_CMD_GICv4(GITS_CMD_MAPTI)
#define GITS_CMD_VMOVI GITS_CMD_GICv4(GITS_CMD_MOVI)
#define GITS_CMD_VSYNC GITS_CMD_GICv4(GITS_CMD_SYNC)
/* VMOVP, VSGI and INVDB are the odd ones, as they dont have a physical counterpart */
#define GITS_CMD_VMOVP GITS_CMD_GICv4(2)
#define GITS_CMD_VSGI GITS_CMD_GICv4(3)
#define GITS_CMD_INVDB GITS_CMD_GICv4(0xe)
/*
* ITS error numbers
*/
#define E_ITS_MOVI_UNMAPPED_INTERRUPT 0x010107
#define E_ITS_MOVI_UNMAPPED_COLLECTION 0x010109
#define E_ITS_INT_UNMAPPED_INTERRUPT 0x010307
#define E_ITS_CLEAR_UNMAPPED_INTERRUPT 0x010507
#define E_ITS_MAPD_DEVICE_OOR 0x010801
#define E_ITS_MAPD_ITTSIZE_OOR 0x010802
#define E_ITS_MAPC_PROCNUM_OOR 0x010902
#define E_ITS_MAPC_COLLECTION_OOR 0x010903
#define E_ITS_MAPTI_UNMAPPED_DEVICE 0x010a04
#define E_ITS_MAPTI_ID_OOR 0x010a05
#define E_ITS_MAPTI_PHYSICALID_OOR 0x010a06
#define E_ITS_INV_UNMAPPED_INTERRUPT 0x010c07
#define E_ITS_INVALL_UNMAPPED_COLLECTION 0x010d09
#define E_ITS_MOVALL_PROCNUM_OOR 0x010e01
#define E_ITS_DISCARD_UNMAPPED_INTERRUPT 0x010f07
/*
* CPU interface registers
*/
#define ICC_CTLR_EL1_EOImode_SHIFT (1)
#define ICC_CTLR_EL1_EOImode_drop_dir (0U << ICC_CTLR_EL1_EOImode_SHIFT)
#define ICC_CTLR_EL1_EOImode_drop (1U << ICC_CTLR_EL1_EOImode_SHIFT)
#define ICC_CTLR_EL1_EOImode_MASK (1 << ICC_CTLR_EL1_EOImode_SHIFT)
#define ICC_CTLR_EL1_CBPR_SHIFT 0
#define ICC_CTLR_EL1_CBPR_MASK (1 << ICC_CTLR_EL1_CBPR_SHIFT)
#define ICC_CTLR_EL1_PMHE_SHIFT 6
#define ICC_CTLR_EL1_PMHE_MASK (1 << ICC_CTLR_EL1_PMHE_SHIFT)
#define ICC_CTLR_EL1_PRI_BITS_SHIFT 8
#define ICC_CTLR_EL1_PRI_BITS_MASK (0x7 << ICC_CTLR_EL1_PRI_BITS_SHIFT)
#define ICC_CTLR_EL1_ID_BITS_SHIFT 11
#define ICC_CTLR_EL1_ID_BITS_MASK (0x7 << ICC_CTLR_EL1_ID_BITS_SHIFT)
#define ICC_CTLR_EL1_SEIS_SHIFT 14
#define ICC_CTLR_EL1_SEIS_MASK (0x1 << ICC_CTLR_EL1_SEIS_SHIFT)
#define ICC_CTLR_EL1_A3V_SHIFT 15
#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
#define ICC_CTLR_EL1_RSS (0x1 << 18)
#define ICC_CTLR_EL1_ExtRange (0x1 << 19)
#define ICC_PMR_EL1_SHIFT 0
#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
#define ICC_BPR0_EL1_SHIFT 0
#define ICC_BPR0_EL1_MASK (0x7 << ICC_BPR0_EL1_SHIFT)
#define ICC_BPR1_EL1_SHIFT 0
#define ICC_BPR1_EL1_MASK (0x7 << ICC_BPR1_EL1_SHIFT)
#define ICC_IGRPEN0_EL1_SHIFT 0
#define ICC_IGRPEN0_EL1_MASK (1 << ICC_IGRPEN0_EL1_SHIFT)
#define ICC_IGRPEN1_EL1_SHIFT 0
#define ICC_IGRPEN1_EL1_MASK (1 << ICC_IGRPEN1_EL1_SHIFT)
#define ICC_SRE_EL1_DIB (1U << 2)
#define ICC_SRE_EL1_DFB (1U << 1)
#define ICC_SRE_EL1_SRE (1U << 0)
/* These are for GICv2 emulation only */
#define GICH_LR_VIRTUALID (0x3ffUL << 0)
#define GICH_LR_PHYSID_CPUID_SHIFT (10)
#define GICH_LR_PHYSID_CPUID (7UL << GICH_LR_PHYSID_CPUID_SHIFT)
#define ICC_IAR1_EL1_SPURIOUS 0x3ff
#define ICC_SRE_EL2_SRE (1 << 0)
#define ICC_SRE_EL2_ENABLE (1 << 3)
#define ICC_SGI1R_TARGET_LIST_SHIFT 0
#define ICC_SGI1R_TARGET_LIST_MASK (0xffff << ICC_SGI1R_TARGET_LIST_SHIFT)
#define ICC_SGI1R_AFFINITY_1_SHIFT 16
#define ICC_SGI1R_AFFINITY_1_MASK (0xff << ICC_SGI1R_AFFINITY_1_SHIFT)
#define ICC_SGI1R_SGI_ID_SHIFT 24
#define ICC_SGI1R_SGI_ID_MASK (0xfULL << ICC_SGI1R_SGI_ID_SHIFT)
#define ICC_SGI1R_AFFINITY_2_SHIFT 32
#define ICC_SGI1R_AFFINITY_2_MASK (0xffULL << ICC_SGI1R_AFFINITY_2_SHIFT)
#define ICC_SGI1R_IRQ_ROUTING_MODE_BIT 40
#define ICC_SGI1R_RS_SHIFT 44
#define ICC_SGI1R_RS_MASK (0xfULL << ICC_SGI1R_RS_SHIFT)
#define ICC_SGI1R_AFFINITY_3_SHIFT 48
#define ICC_SGI1R_AFFINITY_3_MASK (0xffULL << ICC_SGI1R_AFFINITY_3_SHIFT)
#endif
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __SELFTESTS_GIC_V3_ITS_H__
#define __SELFTESTS_GIC_V3_ITS_H__
#include <linux/sizes.h>
void its_init(gpa_t coll_tbl, size_t coll_tbl_sz, gpa_t device_tbl,
size_t device_tbl_sz, gpa_t cmdq, size_t cmdq_size);
void its_send_mapd_cmd(void *cmdq_base, u32 device_id, gpa_t itt_base,
size_t itt_size, bool valid);
void its_send_mapc_cmd(void *cmdq_base, u32 vcpu_id, u32 collection_id, bool valid);
void its_send_mapti_cmd(void *cmdq_base, u32 device_id, u32 event_id,
u32 collection_id, u32 intid);
void its_send_invall_cmd(void *cmdq_base, u32 collection_id);
void its_send_sync_cmd(void *cmdq_base, u32 vcpu_id);
#endif // __SELFTESTS_GIC_V3_ITS_H__
@@ -0,0 +1,150 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SELFTESTS_GIC_V5_H
#define __SELFTESTS_GIC_V5_H
#include <asm/barrier.h>
#include <asm/sysreg.h>
#include <linux/bitfield.h>
#include "processor.h"
/*
* Definitions for GICv5 instructions for the Current Domain
*/
#define GICV5_OP_GIC_CDAFF sys_insn(1, 0, 12, 1, 3)
#define GICV5_OP_GIC_CDDI sys_insn(1, 0, 12, 2, 0)
#define GICV5_OP_GIC_CDDIS sys_insn(1, 0, 12, 1, 0)
#define GICV5_OP_GIC_CDHM sys_insn(1, 0, 12, 2, 1)
#define GICV5_OP_GIC_CDEN sys_insn(1, 0, 12, 1, 1)
#define GICV5_OP_GIC_CDEOI sys_insn(1, 0, 12, 1, 7)
#define GICV5_OP_GIC_CDPEND sys_insn(1, 0, 12, 1, 4)
#define GICV5_OP_GIC_CDPRI sys_insn(1, 0, 12, 1, 2)
#define GICV5_OP_GIC_CDRCFG sys_insn(1, 0, 12, 1, 5)
#define GICV5_OP_GICR_CDIA sys_insn(1, 0, 12, 3, 0)
#define GICV5_OP_GICR_CDNMIA sys_insn(1, 0, 12, 3, 1)
/* Definitions for GIC CDAFF */
#define GICV5_GIC_CDAFF_IAFFID_MASK GENMASK_ULL(47, 32)
#define GICV5_GIC_CDAFF_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDAFF_IRM_MASK BIT_ULL(28)
#define GICV5_GIC_CDAFF_ID_MASK GENMASK_ULL(23, 0)
/* Definitions for GIC CDDI */
#define GICV5_GIC_CDDI_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDDI_ID_MASK GENMASK_ULL(23, 0)
/* Definitions for GIC CDDIS */
#define GICV5_GIC_CDDIS_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDDIS_TYPE(r) FIELD_GET(GICV5_GIC_CDDIS_TYPE_MASK, r)
#define GICV5_GIC_CDDIS_ID_MASK GENMASK_ULL(23, 0)
#define GICV5_GIC_CDDIS_ID(r) FIELD_GET(GICV5_GIC_CDDIS_ID_MASK, r)
/* Definitions for GIC CDEN */
#define GICV5_GIC_CDEN_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDEN_ID_MASK GENMASK_ULL(23, 0)
/* Definitions for GIC CDHM */
#define GICV5_GIC_CDHM_HM_MASK BIT_ULL(32)
#define GICV5_GIC_CDHM_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDHM_ID_MASK GENMASK_ULL(23, 0)
/* Definitions for GIC CDPEND */
#define GICV5_GIC_CDPEND_PENDING_MASK BIT_ULL(32)
#define GICV5_GIC_CDPEND_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDPEND_ID_MASK GENMASK_ULL(23, 0)
/* Definitions for GIC CDPRI */
#define GICV5_GIC_CDPRI_PRIORITY_MASK GENMASK_ULL(39, 35)
#define GICV5_GIC_CDPRI_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDPRI_ID_MASK GENMASK_ULL(23, 0)
/* Definitions for GIC CDRCFG */
#define GICV5_GIC_CDRCFG_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GIC_CDRCFG_ID_MASK GENMASK_ULL(23, 0)
/* Definitions for GICR CDIA */
#define GICV5_GICR_CDIA_VALID_MASK BIT_ULL(32)
#define GICV5_GICR_CDIA_VALID(r) FIELD_GET(GICV5_GICR_CDIA_VALID_MASK, r)
#define GICV5_GICR_CDIA_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GICR_CDIA_ID_MASK GENMASK_ULL(23, 0)
#define GICV5_GICR_CDIA_INTID GENMASK_ULL(31, 0)
/* Definitions for GICR CDNMIA */
#define GICV5_GICR_CDNMIA_VALID_MASK BIT_ULL(32)
#define GICV5_GICR_CDNMIA_VALID(r) FIELD_GET(GICV5_GICR_CDNMIA_VALID_MASK, r)
#define GICV5_GICR_CDNMIA_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GICR_CDNMIA_ID_MASK GENMASK_ULL(23, 0)
#define gicr_insn(insn) read_sysreg_s(GICV5_OP_GICR_##insn)
#define gic_insn(v, insn) write_sysreg_s(v, GICV5_OP_GIC_##insn)
#define __GIC_BARRIER_INSN(op0, op1, CRn, CRm, op2, Rt) \
__emit_inst(0xd5000000 | \
sys_insn((op0), (op1), (CRn), (CRm), (op2)) | \
((Rt) & 0x1f))
#define GSB_SYS_BARRIER_INSN __GIC_BARRIER_INSN(1, 0, 12, 0, 0, 31)
#define GSB_ACK_BARRIER_INSN __GIC_BARRIER_INSN(1, 0, 12, 0, 1, 31)
#define gsb_ack() asm volatile(GSB_ACK_BARRIER_INSN : : : "memory")
#define gsb_sys() asm volatile(GSB_SYS_BARRIER_INSN : : : "memory")
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
#define GICV5_IRQ_DEFAULT_PRI 0b10000
#define GICV5_ARCH_PPI_SW_PPI 0x3
void gicv5_ppi_priority_init(void)
{
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR0_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR1_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR2_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR3_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR4_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR5_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR6_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR7_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR8_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR9_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR10_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR11_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR12_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR13_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR14_EL1);
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_DEFAULT_PRI), SYS_ICC_PPI_PRIORITYR15_EL1);
/*
* Context syncronization required to make sure system register writes
* effects are synchronised.
*/
isb();
}
void gicv5_cpu_disable_interrupts(void)
{
u64 cr0;
cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 0);
write_sysreg_s(cr0, SYS_ICC_CR0_EL1);
}
void gicv5_cpu_enable_interrupts(void)
{
u64 cr0, pcr;
write_sysreg_s(0, SYS_ICC_PPI_ENABLER0_EL1);
write_sysreg_s(0, SYS_ICC_PPI_ENABLER1_EL1);
gicv5_ppi_priority_init();
pcr = FIELD_PREP(ICC_PCR_EL1_PRIORITY, GICV5_IRQ_DEFAULT_PRI);
write_sysreg_s(pcr, SYS_ICC_PCR_EL1);
cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 1);
write_sysreg_s(cr0, SYS_ICC_CR0_EL1);
}
#endif
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UTIL_ARCH_H
#define SELFTEST_KVM_UTIL_ARCH_H
struct kvm_mmu_arch {};
struct kvm_vm_arch {
bool has_gic;
int gic_fd;
};
#endif // SELFTEST_KVM_UTIL_ARCH_H
@@ -0,0 +1,391 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* AArch64 processor specific defines
*
* Copyright (C) 2018, Red Hat, Inc.
*/
#ifndef SELFTEST_KVM_PROCESSOR_H
#define SELFTEST_KVM_PROCESSOR_H
#include "kvm_util.h"
#include "ucall_common.h"
#include <linux/stringify.h>
#include <linux/types.h>
#include <asm/brk-imm.h>
#include <asm/esr.h>
#include <asm/sysreg.h>
#define ARM64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
/*
* KVM_ARM64_SYS_REG(sys_reg_id): Helper macro to convert
* SYS_* register definitions in asm/sysreg.h to use in KVM
* calls such as vcpu_get_reg() and vcpu_set_reg().
*/
#define KVM_ARM64_SYS_REG(sys_reg_id) \
ARM64_SYS_REG(sys_reg_Op0(sys_reg_id), \
sys_reg_Op1(sys_reg_id), \
sys_reg_CRn(sys_reg_id), \
sys_reg_CRm(sys_reg_id), \
sys_reg_Op2(sys_reg_id))
/*
* Default MAIR
* index attribute
* DEVICE_nGnRnE 0 0000:0000
* DEVICE_nGnRE 1 0000:0100
* DEVICE_GRE 2 0000:1100
* NORMAL_NC 3 0100:0100
* NORMAL 4 1111:1111
* NORMAL_WT 5 1011:1011
*/
/* Linux doesn't use these memory types, so let's define them. */
#define MAIR_ATTR_DEVICE_GRE UL(0x0c)
#define MAIR_ATTR_NORMAL_WT UL(0xbb)
#define MT_DEVICE_nGnRnE 0
#define MT_DEVICE_nGnRE 1
#define MT_DEVICE_GRE 2
#define MT_NORMAL_NC 3
#define MT_NORMAL 4
#define MT_NORMAL_WT 5
#define DEFAULT_MAIR_EL1 \
(MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \
MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \
MAIR_ATTRIDX(MAIR_ATTR_DEVICE_GRE, MT_DEVICE_GRE) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT))
/* TCR_EL1 specific flags */
#define TCR_T0SZ_OFFSET 0
#define TCR_T0SZ(x) ((UL(64) - (x)) << TCR_T0SZ_OFFSET)
#define TCR_IRGN0_SHIFT 8
#define TCR_IRGN0_MASK (UL(3) << TCR_IRGN0_SHIFT)
#define TCR_IRGN0_NC (UL(0) << TCR_IRGN0_SHIFT)
#define TCR_IRGN0_WBWA (UL(1) << TCR_IRGN0_SHIFT)
#define TCR_IRGN0_WT (UL(2) << TCR_IRGN0_SHIFT)
#define TCR_IRGN0_WBnWA (UL(3) << TCR_IRGN0_SHIFT)
#define TCR_ORGN0_SHIFT 10
#define TCR_ORGN0_MASK (UL(3) << TCR_ORGN0_SHIFT)
#define TCR_ORGN0_NC (UL(0) << TCR_ORGN0_SHIFT)
#define TCR_ORGN0_WBWA (UL(1) << TCR_ORGN0_SHIFT)
#define TCR_ORGN0_WT (UL(2) << TCR_ORGN0_SHIFT)
#define TCR_ORGN0_WBnWA (UL(3) << TCR_ORGN0_SHIFT)
#define TCR_SH0_SHIFT 12
#define TCR_SH0_MASK (UL(3) << TCR_SH0_SHIFT)
#define TCR_SH0_INNER (UL(3) << TCR_SH0_SHIFT)
#define TCR_TG0_SHIFT 14
#define TCR_TG0_MASK (UL(3) << TCR_TG0_SHIFT)
#define TCR_TG0_4K (UL(0) << TCR_TG0_SHIFT)
#define TCR_TG0_64K (UL(1) << TCR_TG0_SHIFT)
#define TCR_TG0_16K (UL(2) << TCR_TG0_SHIFT)
#define TCR_EPD1_SHIFT 23
#define TCR_EPD1_MASK (UL(1) << TCR_EPD1_SHIFT)
#define TCR_IPS_SHIFT 32
#define TCR_IPS_MASK (UL(7) << TCR_IPS_SHIFT)
#define TCR_IPS_52_BITS (UL(6) << TCR_IPS_SHIFT)
#define TCR_IPS_48_BITS (UL(5) << TCR_IPS_SHIFT)
#define TCR_IPS_40_BITS (UL(2) << TCR_IPS_SHIFT)
#define TCR_IPS_36_BITS (UL(1) << TCR_IPS_SHIFT)
#define TCR_TBI1 (UL(1) << 38)
#define TCR_HA (UL(1) << 39)
#define TCR_DS (UL(1) << 59)
/*
* AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
*/
#define PTE_ATTRINDX(t) ((t) << 2)
#define PTE_ATTRINDX_MASK GENMASK(4, 2)
#define PTE_ATTRINDX_SHIFT 2
#define PTE_VALID BIT(0)
#define PGD_TYPE_TABLE BIT(1)
#define PUD_TYPE_TABLE BIT(1)
#define PMD_TYPE_TABLE BIT(1)
#define PTE_TYPE_PAGE BIT(1)
#define PTE_SHARED (UL(3) << 8) /* SH[1:0], inner shareable */
#define PTE_AF BIT(10)
#define PTE_ADDR_MASK(page_shift) GENMASK(47, (page_shift))
#define PTE_ADDR_51_48 GENMASK(15, 12)
#define PTE_ADDR_51_48_SHIFT 12
#define PTE_ADDR_MASK_LPA2(page_shift) GENMASK(49, (page_shift))
#define PTE_ADDR_51_50_LPA2 GENMASK(9, 8)
#define PTE_ADDR_51_50_LPA2_SHIFT 8
void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init);
struct kvm_vcpu *aarch64_vcpu_add(struct kvm_vm *vm, u32 vcpu_id,
struct kvm_vcpu_init *init, void *guest_code);
struct ex_regs {
u64 regs[31];
u64 sp;
u64 pc;
u64 pstate;
};
#define VECTOR_NUM 16
enum {
VECTOR_SYNC_CURRENT_SP0,
VECTOR_IRQ_CURRENT_SP0,
VECTOR_FIQ_CURRENT_SP0,
VECTOR_ERROR_CURRENT_SP0,
VECTOR_SYNC_CURRENT,
VECTOR_IRQ_CURRENT,
VECTOR_FIQ_CURRENT,
VECTOR_ERROR_CURRENT,
VECTOR_SYNC_LOWER_64,
VECTOR_IRQ_LOWER_64,
VECTOR_FIQ_LOWER_64,
VECTOR_ERROR_LOWER_64,
VECTOR_SYNC_LOWER_32,
VECTOR_IRQ_LOWER_32,
VECTOR_FIQ_LOWER_32,
VECTOR_ERROR_LOWER_32,
};
#define VECTOR_IS_SYNC(v) ((v) == VECTOR_SYNC_CURRENT_SP0 || \
(v) == VECTOR_SYNC_CURRENT || \
(v) == VECTOR_SYNC_LOWER_64 || \
(v) == VECTOR_SYNC_LOWER_32)
void aarch64_get_supported_page_sizes(u32 ipa, u32 *ipa4k,
u32 *ipa16k, u32 *ipa64k);
void vm_init_descriptor_tables(struct kvm_vm *vm);
void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu);
typedef void(*handler_fn)(struct ex_regs *);
void vm_install_exception_handler(struct kvm_vm *vm,
int vector, handler_fn handler);
void vm_install_sync_handler(struct kvm_vm *vm,
int vector, int ec, handler_fn handler);
u64 *virt_get_pte_hva_at_level(struct kvm_vm *vm, gva_t gva, int level);
u64 *virt_get_pte_hva(struct kvm_vm *vm, gva_t gva);
static inline void cpu_relax(void)
{
asm volatile("yield" ::: "memory");
}
#define isb() asm volatile("isb" : : : "memory")
#define dsb(opt) asm volatile("dsb " #opt : : : "memory")
#define dmb(opt) asm volatile("dmb " #opt : : : "memory")
#define dma_wmb() dmb(oshst)
#define __iowmb() dma_wmb()
#define dma_rmb() dmb(oshld)
#define __iormb(v) \
({ \
unsigned long tmp; \
\
dma_rmb(); \
\
/* \
* Courtesy of arch/arm64/include/asm/io.h: \
* Create a dummy control dependency from the IO read to any \
* later instructions. This ensures that a subsequent call \
* to udelay() will be ordered due to the ISB in __delay(). \
*/ \
asm volatile("eor %0, %1, %1\n" \
"cbnz %0, ." \
: "=r" (tmp) : "r" ((unsigned long)(v)) \
: "memory"); \
})
static __always_inline void __raw_writel(u32 val, volatile void *addr)
{
asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
}
static __always_inline u32 __raw_readl(const volatile void *addr)
{
u32 val;
asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
return val;
}
static __always_inline void __raw_writeq(u64 val, volatile void *addr)
{
asm volatile("str %0, [%1]" : : "rZ" (val), "r" (addr));
}
static __always_inline u64 __raw_readq(const volatile void *addr)
{
u64 val;
asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr));
return val;
}
#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c)))
#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
#define writeq_relaxed(v,c) ((void)__raw_writeq((__force u64)cpu_to_le64(v),(c)))
#define readq_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64)__raw_readq(c)); __r; })
#define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c));})
#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(__v); __v; })
#define writeq(v,c) ({ __iowmb(); writeq_relaxed((v),(c));})
#define readq(c) ({ u64 __v = readq_relaxed(c); __iormb(__v); __v; })
static inline void local_irq_enable(void)
{
asm volatile("msr daifclr, #3" : : : "memory");
}
static inline void local_irq_disable(void)
{
asm volatile("msr daifset, #3" : : : "memory");
}
static inline void local_serror_enable(void)
{
asm volatile("msr daifclr, #4" : : : "memory");
}
static inline void local_serror_disable(void)
{
asm volatile("msr daifset, #4" : : : "memory");
}
/**
* struct arm_smccc_res - Result from SMC/HVC call
* @a0-a3 result values from registers 0 to 3
*/
struct arm_smccc_res {
unsigned long a0;
unsigned long a1;
unsigned long a2;
unsigned long a3;
};
/**
* smccc_hvc - Invoke a SMCCC function using the hvc conduit
* @function_id: the SMCCC function to be called
* @arg0-arg6: SMCCC function arguments, corresponding to registers x1-x7
* @res: pointer to write the return values from registers x0-x3
*
*/
void smccc_hvc(u32 function_id, u64 arg0, u64 arg1,
u64 arg2, u64 arg3, u64 arg4, u64 arg5,
u64 arg6, struct arm_smccc_res *res);
/**
* smccc_smc - Invoke a SMCCC function using the smc conduit
* @function_id: the SMCCC function to be called
* @arg0-arg6: SMCCC function arguments, corresponding to registers x1-x7
* @res: pointer to write the return values from registers x0-x3
*
*/
void smccc_smc(u32 function_id, u64 arg0, u64 arg1,
u64 arg2, u64 arg3, u64 arg4, u64 arg5,
u64 arg6, struct arm_smccc_res *res);
/* Execute a Wait For Interrupt instruction. */
void wfi(void);
void test_wants_mte(void);
void test_disable_default_vgic(void);
bool vm_supports_el2(struct kvm_vm *vm);
static inline bool test_supports_el2(void)
{
struct kvm_vm *vm = vm_create(1);
bool supported = vm_supports_el2(vm);
kvm_vm_free(vm);
return supported;
}
static inline bool vcpu_has_el2(struct kvm_vcpu *vcpu)
{
return vcpu->init.features[0] & BIT(KVM_ARM_VCPU_HAS_EL2);
}
#define MAPPED_EL2_SYSREG(el2, el1) \
case SYS_##el1: \
if (vcpu_has_el2(vcpu)) \
alias = SYS_##el2; \
break
static __always_inline u64 ctxt_reg_alias(struct kvm_vcpu *vcpu, u32 encoding)
{
u32 alias = encoding;
BUILD_BUG_ON(!__builtin_constant_p(encoding));
switch (encoding) {
MAPPED_EL2_SYSREG(SCTLR_EL2, SCTLR_EL1);
MAPPED_EL2_SYSREG(CPTR_EL2, CPACR_EL1);
MAPPED_EL2_SYSREG(TTBR0_EL2, TTBR0_EL1);
MAPPED_EL2_SYSREG(TTBR1_EL2, TTBR1_EL1);
MAPPED_EL2_SYSREG(TCR_EL2, TCR_EL1);
MAPPED_EL2_SYSREG(VBAR_EL2, VBAR_EL1);
MAPPED_EL2_SYSREG(AFSR0_EL2, AFSR0_EL1);
MAPPED_EL2_SYSREG(AFSR1_EL2, AFSR1_EL1);
MAPPED_EL2_SYSREG(ESR_EL2, ESR_EL1);
MAPPED_EL2_SYSREG(FAR_EL2, FAR_EL1);
MAPPED_EL2_SYSREG(MAIR_EL2, MAIR_EL1);
MAPPED_EL2_SYSREG(TCR2_EL2, TCR2_EL1);
MAPPED_EL2_SYSREG(PIR_EL2, PIR_EL1);
MAPPED_EL2_SYSREG(PIRE0_EL2, PIRE0_EL1);
MAPPED_EL2_SYSREG(POR_EL2, POR_EL1);
MAPPED_EL2_SYSREG(AMAIR_EL2, AMAIR_EL1);
MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1);
MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1);
MAPPED_EL2_SYSREG(ZCR_EL2, ZCR_EL1);
MAPPED_EL2_SYSREG(CONTEXTIDR_EL2, CONTEXTIDR_EL1);
MAPPED_EL2_SYSREG(SCTLR2_EL2, SCTLR2_EL1);
MAPPED_EL2_SYSREG(CNTHCTL_EL2, CNTKCTL_EL1);
case SYS_SP_EL1:
if (!vcpu_has_el2(vcpu))
return ARM64_CORE_REG(sp_el1);
alias = SYS_SP_EL2;
break;
default:
BUILD_BUG();
}
return KVM_ARM64_SYS_REG(alias);
}
void kvm_get_default_vcpu_target(struct kvm_vm *vm, struct kvm_vcpu_init *init);
static inline unsigned int get_current_el(void)
{
return (read_sysreg(CurrentEL) >> 2) & 0x3;
}
#define do_smccc(...) \
do { \
if (get_current_el() == 2) \
smccc_smc(__VA_ARGS__); \
else \
smccc_hvc(__VA_ARGS__); \
} while (0)
#endif /* SELFTEST_KVM_PROCESSOR_H */
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef SELFTEST_KVM_ARM64_SPINLOCK_H
#define SELFTEST_KVM_ARM64_SPINLOCK_H
struct spinlock {
int v;
};
extern void spin_lock(struct spinlock *lock);
extern void spin_unlock(struct spinlock *lock);
#endif /* SELFTEST_KVM_ARM64_SPINLOCK_H */
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UCALL_H
#define SELFTEST_KVM_UCALL_H
#include "kvm_util.h"
#define UCALL_EXIT_REASON KVM_EXIT_MMIO
/*
* ucall_exit_mmio_addr holds per-VM values (global data is duplicated by each
* VM), it must not be accessed from host code.
*/
extern gva_t *ucall_exit_mmio_addr;
static inline void ucall_arch_do_ucall(gva_t uc)
{
WRITE_ONCE(*ucall_exit_mmio_addr, uc);
}
#endif
@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ARM Generic Interrupt Controller (GIC) host specific defines
*/
#ifndef SELFTEST_KVM_VGIC_H
#define SELFTEST_KVM_VGIC_H
#include <linux/kvm.h>
#include "kvm_util.h"
#define REDIST_REGION_ATTR_ADDR(count, base, flags, index) \
(((u64)(count) << 52) | \
((u64)((base) >> 16) << 16) | \
((u64)(flags) << 12) | \
index)
bool kvm_supports_vgic_v3(void);
int __vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, u32 nr_irqs);
void __vgic_v3_init(int fd);
int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, u32 nr_irqs);
#define VGIC_MAX_RESERVED 1023
void kvm_irq_set_level_info(int gic_fd, u32 intid, int level);
int _kvm_irq_set_level_info(int gic_fd, u32 intid, int level);
void kvm_arm_irq_line(struct kvm_vm *vm, u32 intid, int level);
int _kvm_arm_irq_line(struct kvm_vm *vm, u32 intid, int level);
/* The vcpu arg only applies to private interrupts. */
void kvm_irq_write_ispendr(int gic_fd, u32 intid, struct kvm_vcpu *vcpu);
void kvm_irq_write_isactiver(int gic_fd, u32 intid, struct kvm_vcpu *vcpu);
#define KVM_IRQCHIP_NUM_PINS (1020 - 32)
int vgic_its_setup(struct kvm_vm *vm);
#endif // SELFTEST_KVM_VGIC_H
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020, Red Hat, Inc.
*/
#include "kvm_util.h"
struct guest_mode {
bool supported;
bool enabled;
};
extern struct guest_mode guest_modes[NUM_VM_MODES];
#define guest_mode_append(mode, enabled) ({ \
guest_modes[mode] = (struct guest_mode){ (enabled), (enabled) }; \
})
void guest_modes_append_default(void);
void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *arg);
void guest_modes_help(void);
void guest_modes_cmdline(const char *arg);
@@ -0,0 +1,98 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_SYSCALLS_H
#define SELFTEST_KVM_SYSCALLS_H
/*
* Include both the kernel and libc versions of mman.h. The kernel provides
* the most up-to-date flags and definitions, while libc provides the syscall
* wrappers tests expect.
*/
#include <linux/mman.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <test_util.h>
#define MAP_ARGS0(m,...)
#define MAP_ARGS1(m,t,a,...) m(t,a)
#define MAP_ARGS2(m,t,a,...) m(t,a), MAP_ARGS1(m,__VA_ARGS__)
#define MAP_ARGS3(m,t,a,...) m(t,a), MAP_ARGS2(m,__VA_ARGS__)
#define MAP_ARGS4(m,t,a,...) m(t,a), MAP_ARGS3(m,__VA_ARGS__)
#define MAP_ARGS5(m,t,a,...) m(t,a), MAP_ARGS4(m,__VA_ARGS__)
#define MAP_ARGS6(m,t,a,...) m(t,a), MAP_ARGS5(m,__VA_ARGS__)
#define MAP_ARGS(n,...) MAP_ARGS##n(__VA_ARGS__)
#define __DECLARE_ARGS(t, a) t a
#define __UNPACK_ARGS(t, a) a
#define DECLARE_ARGS(nr_args, args...) MAP_ARGS(nr_args, __DECLARE_ARGS, args)
#define UNPACK_ARGS(nr_args, args...) MAP_ARGS(nr_args, __UNPACK_ARGS, args)
#define __KVM_SYSCALL_ERROR(_name, _ret) \
"%s failed, rc: %i errno: %i (%s)", (_name), (_ret), errno, strerror(errno)
/* Define a kvm_<syscall>() API to assert success. */
#define __KVM_SYSCALL_DEFINE(name, nr_args, args...) \
static inline void kvm_##name(DECLARE_ARGS(nr_args, args)) \
{ \
int r; \
\
r = name(UNPACK_ARGS(nr_args, args)); \
TEST_ASSERT(!r, __KVM_SYSCALL_ERROR(#name, r)); \
}
/*
* Macro to define syscall APIs, either because KVM selftests doesn't link to
* the standard library, e.g. libnuma, or because there is no library that yet
* provides the syscall. These
*/
#define KVM_SYSCALL_DEFINE(name, nr_args, args...) \
static inline long name(DECLARE_ARGS(nr_args, args)) \
{ \
return syscall(__NR_##name, UNPACK_ARGS(nr_args, args)); \
} \
__KVM_SYSCALL_DEFINE(name, nr_args, args)
/*
* Special case mmap(), as KVM selftest rarely/never specific an address,
* rarely specify an offset, and because the unique return code requires
* special handling anyways.
*/
static inline void *__kvm_mmap(size_t size, int prot, int flags, int fd,
off_t offset)
{
void *mem;
mem = mmap(NULL, size, prot, flags, fd, offset);
TEST_ASSERT(mem != MAP_FAILED, __KVM_SYSCALL_ERROR("mmap()",
(int)(unsigned long)MAP_FAILED));
return mem;
}
static inline void *kvm_mmap(size_t size, int prot, int flags, int fd)
{
return __kvm_mmap(size, prot, flags, fd, 0);
}
static inline int kvm_dup(int fd)
{
int new_fd = dup(fd);
TEST_ASSERT(new_fd >= 0, __KVM_SYSCALL_ERROR("dup()", new_fd));
return new_fd;
}
__KVM_SYSCALL_DEFINE(munmap, 2, void *, mem, size_t, size);
__KVM_SYSCALL_DEFINE(close, 1, int, fd);
__KVM_SYSCALL_DEFINE(fallocate, 4, int, fd, int, mode, loff_t, offset, loff_t, len);
__KVM_SYSCALL_DEFINE(ftruncate, 2, unsigned int, fd, off_t, length);
__KVM_SYSCALL_DEFINE(madvise, 3, void *, addr, size_t, length, int, advice);
#define kvm_free_fd(fd) \
do { \
kvm_close(fd); \
(fd) = -1; \
} while (0)
#endif /* SELFTEST_KVM_SYSCALLS_H */
@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Macros for defining a KVM test
*
* Copyright (C) 2022, Google LLC.
*/
#ifndef SELFTEST_KVM_TEST_HARNESS_H
#define SELFTEST_KVM_TEST_HARNESS_H
#include "kselftest_harness.h"
#define KVM_ONE_VCPU_TEST_SUITE(name) \
FIXTURE(name) { \
struct kvm_vcpu *vcpu; \
}; \
\
FIXTURE_SETUP(name) { \
(void)vm_create_with_one_vcpu(&self->vcpu, NULL); \
} \
\
FIXTURE_TEARDOWN(name) { \
kvm_vm_free(self->vcpu->vm); \
}
#define KVM_ONE_VCPU_TEST(suite, test, guestcode) \
static void __suite##_##test(struct kvm_vcpu *vcpu); \
\
TEST_F(suite, test) \
{ \
vcpu_arch_set_entry_point(self->vcpu, guestcode); \
__suite##_##test(self->vcpu); \
} \
static void __suite##_##test(struct kvm_vcpu *vcpu)
#endif /* SELFTEST_KVM_TEST_HARNESS_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UTIL_TYPES_H
#define SELFTEST_KVM_UTIL_TYPES_H
#include <linux/types.h>
/*
* Provide a version of static_assert() that is guaranteed to have an optional
* message param. _GNU_SOURCE is defined for all KVM selftests, _GNU_SOURCE
* implies _ISOC11_SOURCE, and if _ISOC11_SOURCE is defined, glibc #undefs and
* #defines static_assert() as a direct alias to _Static_assert() (see
* usr/include/assert.h). Define a custom macro instead of redefining
* static_assert() to avoid creating non-deterministic behavior that is
* dependent on include order.
*/
#define __kvm_static_assert(expr, msg, ...) _Static_assert(expr, msg)
#define kvm_static_assert(expr, ...) __kvm_static_assert(expr, ##__VA_ARGS__, #expr)
typedef u64 gpa_t; /* Virtual Machine (Guest) physical address */
typedef u64 gva_t; /* Virtual Machine (Guest) virtual address */
#define INVALID_GPA (~(u64)0)
#endif /* SELFTEST_KVM_UTIL_TYPES_H */
@@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* LoongArch Constant Timer specific interface
*/
#ifndef SELFTEST_KVM_ARCH_TIMER_H
#define SELFTEST_KVM_ARCH_TIMER_H
#include "processor.h"
/* LoongArch timer frequency is constant 100MHZ */
#define TIMER_FREQ (100UL << 20)
#define msec_to_cycles(msec) (TIMER_FREQ * (unsigned long)(msec) / 1000)
#define usec_to_cycles(usec) (TIMER_FREQ * (unsigned long)(usec) / 1000000)
#define cycles_to_usec(cycles) ((unsigned long)(cycles) * 1000000 / TIMER_FREQ)
static inline unsigned long timer_get_cycles(void)
{
unsigned long val = 0;
__asm__ __volatile__(
"rdtime.d %0, $zero\n\t"
: "=r"(val)
:
);
return val;
}
static inline unsigned long timer_get_cfg(void)
{
return csr_read(LOONGARCH_CSR_TCFG);
}
static inline unsigned long timer_get_val(void)
{
return csr_read(LOONGARCH_CSR_TVAL);
}
static inline void disable_timer(void)
{
csr_write(0, LOONGARCH_CSR_TCFG);
}
static inline void timer_irq_enable(void)
{
unsigned long val;
val = csr_read(LOONGARCH_CSR_ECFG);
val |= ECFGF_TIMER;
csr_write(val, LOONGARCH_CSR_ECFG);
}
static inline void timer_irq_disable(void)
{
unsigned long val;
val = csr_read(LOONGARCH_CSR_ECFG);
val &= ~ECFGF_TIMER;
csr_write(val, LOONGARCH_CSR_ECFG);
}
static inline void timer_set_next_cmp_ms(unsigned int msec, bool period)
{
unsigned long val;
val = msec_to_cycles(msec) & CSR_TCFG_VAL;
val |= CSR_TCFG_EN;
if (period)
val |= CSR_TCFG_PERIOD;
csr_write(val, LOONGARCH_CSR_TCFG);
}
static inline void __delay(u64 cycles)
{
u64 start = timer_get_cycles();
while ((timer_get_cycles() - start) < cycles)
cpu_relax();
}
static inline void udelay(unsigned long usec)
{
__delay(usec_to_cycles(usec));
}
#endif /* SELFTEST_KVM_ARCH_TIMER_H */
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UTIL_ARCH_H
#define SELFTEST_KVM_UTIL_ARCH_H
struct kvm_mmu_arch {};
struct kvm_vm_arch {};
#endif // SELFTEST_KVM_UTIL_ARCH_H
@@ -0,0 +1,66 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* LoongArch PMU specific interface
*/
#ifndef SELFTEST_KVM_PMU_H
#define SELFTEST_KVM_PMU_H
#include "processor.h"
#define LOONGARCH_CPUCFG6 0x6
#define CPUCFG6_PMP BIT(0)
#define CPUCFG6_PAMVER GENMASK(3, 1)
#define CPUCFG6_PMNUM GENMASK(7, 4)
#define CPUCFG6_PMNUM_SHIFT 4
#define CPUCFG6_PMBITS GENMASK(13, 8)
#define CPUCFG6_PMBITS_SHIFT 8
#define CPUCFG6_UPM BIT(14)
/* Performance Counter registers */
#define LOONGARCH_CSR_PERFCTRL0 0x200 /* perf event 0 config */
#define LOONGARCH_CSR_PERFCNTR0 0x201 /* perf event 0 count value */
#define LOONGARCH_CSR_PERFCTRL1 0x202 /* perf event 1 config */
#define LOONGARCH_CSR_PERFCNTR1 0x203 /* perf event 1 count value */
#define LOONGARCH_CSR_PERFCTRL2 0x204 /* perf event 2 config */
#define LOONGARCH_CSR_PERFCNTR2 0x205 /* perf event 2 count value */
#define LOONGARCH_CSR_PERFCTRL3 0x206 /* perf event 3 config */
#define LOONGARCH_CSR_PERFCNTR3 0x207 /* perf event 3 count value */
#define CSR_PERFCTRL_PLV0 BIT(16)
#define CSR_PERFCTRL_PLV1 BIT(17)
#define CSR_PERFCTRL_PLV2 BIT(18)
#define CSR_PERFCTRL_PLV3 BIT(19)
#define CSR_PERFCTRL_PMIE BIT(20)
#define PMU_ENVENT_ENABLED (CSR_PERFCTRL_PLV0 | CSR_PERFCTRL_PLV1 | CSR_PERFCTRL_PLV2 | CSR_PERFCTRL_PLV3)
/* Hardware event codes (from LoongArch perf_event.c */
#define LOONGARCH_PMU_EVENT_CYCLES 0x00 /* CPU cycles */
#define LOONGARCH_PMU_EVENT_INSTR_RETIRED 0x01 /* Instructions retired */
#define PERF_COUNT_HW_BRANCH_INSTRUCTIONS 0x02 /* Branch instructions */
#define PERF_COUNT_HW_BRANCH_MISSES 0x03 /* Branch misses */
#define NUM_LOOPS 1000
#define EXPECTED_INSTR_MIN (NUM_LOOPS + 10) /* Loop + overhead */
#define EXPECTED_CYCLES_MIN NUM_LOOPS /* At least 1 cycle per iteration */
#define UPPER_BOUND (10 * NUM_LOOPS)
#define PMU_OVERFLOW (1ULL << 63)
static inline void pmu_irq_enable(void)
{
unsigned long val;
val = csr_read(LOONGARCH_CSR_ECFG);
val |= ECFGF_PMU;
csr_write(val, LOONGARCH_CSR_ECFG);
}
static inline void pmu_irq_disable(void)
{
unsigned long val;
val = csr_read(LOONGARCH_CSR_ECFG);
val &= ~ECFGF_PMU;
csr_write(val, LOONGARCH_CSR_ECFG);
}
#endif
@@ -0,0 +1,235 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_PROCESSOR_H
#define SELFTEST_KVM_PROCESSOR_H
#ifndef __ASSEMBLER__
#include "ucall_common.h"
#else
/* general registers */
#define zero $r0
#define ra $r1
#define tp $r2
#define sp $r3
#define a0 $r4
#define a1 $r5
#define a2 $r6
#define a3 $r7
#define a4 $r8
#define a5 $r9
#define a6 $r10
#define a7 $r11
#define t0 $r12
#define t1 $r13
#define t2 $r14
#define t3 $r15
#define t4 $r16
#define t5 $r17
#define t6 $r18
#define t7 $r19
#define t8 $r20
#define u0 $r21
#define fp $r22
#define s0 $r23
#define s1 $r24
#define s2 $r25
#define s3 $r26
#define s4 $r27
#define s5 $r28
#define s6 $r29
#define s7 $r30
#define s8 $r31
#endif
/*
* LoongArch page table entry definition
* Original header file arch/loongarch/include/asm/loongarch.h
*/
#define _PAGE_VALID_SHIFT 0
#define _PAGE_DIRTY_SHIFT 1
#define _PAGE_PLV_SHIFT 2 /* 2~3, two bits */
#define PLV_KERN 0
#define PLV_USER 3
#define PLV_MASK 0x3
#define _CACHE_SHIFT 4 /* 4~5, two bits */
#define _PAGE_PRESENT_SHIFT 7
#define _PAGE_WRITE_SHIFT 8
#define _PAGE_VALID BIT_ULL(_PAGE_VALID_SHIFT)
#define _PAGE_PRESENT BIT_ULL(_PAGE_PRESENT_SHIFT)
#define _PAGE_WRITE BIT_ULL(_PAGE_WRITE_SHIFT)
#define _PAGE_DIRTY BIT_ULL(_PAGE_DIRTY_SHIFT)
#define _PAGE_USER (PLV_USER << _PAGE_PLV_SHIFT)
#define __READABLE (_PAGE_VALID)
#define __WRITEABLE (_PAGE_DIRTY | _PAGE_WRITE)
/* Coherent Cached */
#define _CACHE_CC BIT_ULL(_CACHE_SHIFT)
#define PS_4K 0x0000000c
#define PS_16K 0x0000000e
#define PS_64K 0x00000010
#define PS_DEFAULT_SIZE PS_16K
/* LoongArch Basic CSR registers */
#define LOONGARCH_CSR_CRMD 0x0 /* Current mode info */
#define CSR_CRMD_PG_SHIFT 4
#define CSR_CRMD_PG BIT_ULL(CSR_CRMD_PG_SHIFT)
#define CSR_CRMD_IE_SHIFT 2
#define CSR_CRMD_IE BIT_ULL(CSR_CRMD_IE_SHIFT)
#define CSR_CRMD_PLV_SHIFT 0
#define CSR_CRMD_PLV_WIDTH 2
#define CSR_CRMD_PLV (0x3UL << CSR_CRMD_PLV_SHIFT)
#define PLV_MASK 0x3
#define LOONGARCH_CSR_PRMD 0x1
#define LOONGARCH_CSR_EUEN 0x2
#define LOONGARCH_CSR_ECFG 0x4
#define ECFGB_PMU 10
#define ECFGF_PMU (BIT_ULL(ECFGB_PMU))
#define ECFGB_TIMER 11
#define ECFGF_TIMER (BIT_ULL(ECFGB_TIMER))
#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
#define CSR_ESTAT_EXC_SHIFT 16
#define CSR_ESTAT_EXC_WIDTH 6
#define CSR_ESTAT_EXC (0x3f << CSR_ESTAT_EXC_SHIFT)
#define EXCCODE_INT 0 /* Interrupt */
#define INT_PMI 10 /* PMU interrupt */
#define INT_TI 11 /* Timer interrupt*/
#define LOONGARCH_CSR_ERA 0x6 /* ERA */
#define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */
#define LOONGARCH_CSR_EENTRY 0xc
#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize */
#define CSR_TLBIDX_PS_SHIFT 24
#define CSR_TLBIDX_PS_WIDTH 6
#define CSR_TLBIDX_PS (0x3fUL << CSR_TLBIDX_PS_SHIFT)
#define CSR_TLBIDX_SIZEM 0x3f000000
#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT
#define LOONGARCH_CSR_ASID 0x18 /* ASID */
#define LOONGARCH_CSR_PGDL 0x19
#define LOONGARCH_CSR_PGDH 0x1a
/* Page table base */
#define LOONGARCH_CSR_PGD 0x1b
#define LOONGARCH_CSR_PWCTL0 0x1c
#define LOONGARCH_CSR_PWCTL1 0x1d
#define LOONGARCH_CSR_STLBPGSIZE 0x1e
#define LOONGARCH_CSR_CPUID 0x20
#define LOONGARCH_CSR_KS0 0x30
#define LOONGARCH_CSR_KS1 0x31
#define LOONGARCH_CSR_TMID 0x40
#define LOONGARCH_CSR_TCFG 0x41
#define CSR_TCFG_VAL (BIT_ULL(48) - BIT_ULL(2))
#define CSR_TCFG_PERIOD_SHIFT 1
#define CSR_TCFG_PERIOD (0x1UL << CSR_TCFG_PERIOD_SHIFT)
#define CSR_TCFG_EN (0x1UL)
#define LOONGARCH_CSR_TVAL 0x42
#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */
#define CSR_TINTCLR_TI_SHIFT 0
#define CSR_TINTCLR_TI (1 << CSR_TINTCLR_TI_SHIFT)
/* TLB refill exception entry */
#define LOONGARCH_CSR_TLBRENTRY 0x88
#define LOONGARCH_CSR_TLBRSAVE 0x8b
#define LOONGARCH_CSR_TLBREHI 0x8e
#define CSR_TLBREHI_PS_SHIFT 0
#define CSR_TLBREHI_PS (0x3fUL << CSR_TLBREHI_PS_SHIFT)
#define read_cpucfg(reg) \
({ \
register unsigned long __v; \
__asm__ __volatile__( \
"cpucfg %0, %1\n\t" \
: "=r" (__v) \
: "r" (reg) \
: "memory"); \
__v; \
})
#define csr_read(csr) \
({ \
register unsigned long __v; \
__asm__ __volatile__( \
"csrrd %[val], %[reg]\n\t" \
: [val] "=r" (__v) \
: [reg] "i" (csr) \
: "memory"); \
__v; \
})
#define csr_write(v, csr) \
({ \
register unsigned long __v = v; \
__asm__ __volatile__ ( \
"csrwr %[val], %[reg]\n\t" \
: [val] "+r" (__v) \
: [reg] "i" (csr) \
: "memory"); \
__v; \
})
#define EXREGS_GPRS (32)
#ifndef __ASSEMBLER__
void handle_tlb_refill(void);
void handle_exception(void);
struct ex_regs {
unsigned long regs[EXREGS_GPRS];
unsigned long pc;
unsigned long estat;
unsigned long badv;
unsigned long prmd;
};
#define PC_OFFSET_EXREGS offsetof(struct ex_regs, pc)
#define ESTAT_OFFSET_EXREGS offsetof(struct ex_regs, estat)
#define BADV_OFFSET_EXREGS offsetof(struct ex_regs, badv)
#define PRMD_OFFSET_EXREGS offsetof(struct ex_regs, prmd)
#define EXREGS_SIZE sizeof(struct ex_regs)
#define VECTOR_NUM 64
typedef void(*handler_fn)(struct ex_regs *);
struct handlers {
handler_fn exception_handlers[VECTOR_NUM];
};
void loongarch_vcpu_setup(struct kvm_vcpu *vcpu);
void vm_init_descriptor_tables(struct kvm_vm *vm);
void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn handler);
static inline void cpu_relax(void)
{
asm volatile("nop" ::: "memory");
}
static inline void local_irq_enable(void)
{
unsigned int flags = CSR_CRMD_IE;
register unsigned int mask asm("$t0") = CSR_CRMD_IE;
__asm__ __volatile__(
"csrxchg %[val], %[mask], %[reg]\n\t"
: [val] "+r" (flags)
: [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
: "memory");
}
static inline void local_irq_disable(void)
{
unsigned int flags = 0;
register unsigned int mask asm("$t0") = CSR_CRMD_IE;
__asm__ __volatile__(
"csrxchg %[val], %[mask], %[reg]\n\t"
: [val] "+r" (flags)
: [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
: "memory");
}
#else
#define PC_OFFSET_EXREGS ((EXREGS_GPRS + 0) * 8)
#define ESTAT_OFFSET_EXREGS ((EXREGS_GPRS + 1) * 8)
#define BADV_OFFSET_EXREGS ((EXREGS_GPRS + 2) * 8)
#define PRMD_OFFSET_EXREGS ((EXREGS_GPRS + 3) * 8)
#define EXREGS_SIZE ((EXREGS_GPRS + 4) * 8)
#endif
#endif /* SELFTEST_KVM_PROCESSOR_H */
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UCALL_H
#define SELFTEST_KVM_UCALL_H
#include "kvm_util.h"
#define UCALL_EXIT_REASON KVM_EXIT_MMIO
/*
* ucall_exit_mmio_addr holds per-VM values (global data is duplicated by each
* VM), it must not be accessed from host code.
*/
extern gva_t *ucall_exit_mmio_addr;
static inline void ucall_arch_do_ucall(gva_t uc)
{
WRITE_ONCE(*ucall_exit_mmio_addr, uc);
}
#endif
@@ -0,0 +1,51 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Tools for integrating with lru_gen, like parsing the lru_gen debugfs output.
*
* Copyright (C) 2025, Google LLC.
*/
#ifndef SELFTEST_KVM_LRU_GEN_UTIL_H
#define SELFTEST_KVM_LRU_GEN_UTIL_H
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include "test_util.h"
#define MAX_NR_GENS 16 /* MAX_NR_GENS in include/linux/mmzone.h */
#define MAX_NR_NODES 32 /* Maximum number of nodes supported by the test */
#define LRU_GEN_DEBUGFS "/sys/kernel/debug/lru_gen"
#define LRU_GEN_ENABLED_PATH "/sys/kernel/mm/lru_gen/enabled"
#define LRU_GEN_ENABLED 1
#define LRU_GEN_MM_WALK 2
struct generation_stats {
int gen;
long age_ms;
long nr_anon;
long nr_file;
};
struct node_stats {
int node;
int nr_gens; /* Number of populated gens entries. */
struct generation_stats gens[MAX_NR_GENS];
};
struct memcg_stats {
unsigned long memcg_id;
int nr_nodes; /* Number of populated nodes entries. */
struct node_stats nodes[MAX_NR_NODES];
};
void lru_gen_read_memcg_stats(struct memcg_stats *stats, const char *memcg);
long lru_gen_sum_memcg_stats(const struct memcg_stats *stats);
long lru_gen_sum_memcg_stats_for_gen(int gen, const struct memcg_stats *stats);
void lru_gen_do_aging(struct memcg_stats *stats, const char *memcg);
int lru_gen_find_generation(const struct memcg_stats *stats,
unsigned long total_pages);
bool lru_gen_usable(void);
#endif /* SELFTEST_KVM_LRU_GEN_UTIL_H */
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0
/*
* tools/testing/selftests/kvm/include/memstress.h
*
* Copyright (C) 2020, Google LLC.
*/
#ifndef SELFTEST_KVM_MEMSTRESS_H
#define SELFTEST_KVM_MEMSTRESS_H
#include <pthread.h>
#include "kvm_util.h"
/* Default guest test virtual memory offset */
#define DEFAULT_GUEST_TEST_MEM 0xc0000000
#define DEFAULT_PER_VCPU_MEM_SIZE (1 << 30) /* 1G */
#define MEMSTRESS_MEM_SLOT_INDEX 1
struct memstress_vcpu_args {
gpa_t gpa;
gva_t gva;
u64 pages;
/* Only used by the host userspace part of the vCPU thread */
struct kvm_vcpu *vcpu;
int vcpu_idx;
};
struct memstress_args {
struct kvm_vm *vm;
/* The starting address and size of the guest test region. */
gpa_t gpa;
u64 size;
u64 guest_page_size;
u32 random_seed;
u32 write_percent;
/* Run vCPUs in L2 instead of L1, if the architecture supports it. */
bool nested;
/* Randomize which pages are accessed by the guest. */
bool random_access;
/* True if all vCPUs are pinned to pCPUs */
bool pin_vcpus;
/* The vCPU=>pCPU pinning map. Only valid if pin_vcpus is true. */
u32 vcpu_to_pcpu[KVM_MAX_VCPUS];
/* Test is done, stop running vCPUs. */
bool stop_vcpus;
struct memstress_vcpu_args vcpu_args[KVM_MAX_VCPUS];
};
extern struct memstress_args memstress_args;
struct kvm_vm *memstress_create_vm(enum vm_guest_mode mode, int nr_vcpus,
u64 vcpu_memory_bytes, int slots,
enum vm_mem_backing_src_type backing_src,
bool partition_vcpu_memory_access);
void memstress_destroy_vm(struct kvm_vm *vm);
void memstress_set_write_percent(struct kvm_vm *vm, u32 write_percent);
void memstress_set_random_access(struct kvm_vm *vm, bool random_access);
void memstress_start_vcpu_threads(int vcpus, void (*vcpu_fn)(struct memstress_vcpu_args *));
void memstress_join_vcpu_threads(int vcpus);
void memstress_guest_code(u32 vcpu_id);
u64 memstress_nested_pages(int nr_vcpus);
void memstress_setup_nested(struct kvm_vm *vm, int nr_vcpus, struct kvm_vcpu *vcpus[]);
void memstress_enable_dirty_logging(struct kvm_vm *vm, int slots);
void memstress_disable_dirty_logging(struct kvm_vm *vm, int slots);
void memstress_get_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[], int slots);
void memstress_clear_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[],
int slots, u64 pages_per_slot);
unsigned long **memstress_alloc_bitmaps(int slots, u64 pages_per_slot);
void memstress_free_bitmaps(unsigned long *bitmaps[], int slots);
#endif /* SELFTEST_KVM_MEMSTRESS_H */
@@ -0,0 +1,83 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2020, Google LLC. */
#ifndef SELFTEST_KVM_NUMAIF_H
#define SELFTEST_KVM_NUMAIF_H
#include <dirent.h>
#include <linux/mempolicy.h>
#include "kvm_syscalls.h"
KVM_SYSCALL_DEFINE(get_mempolicy, 5, int *, policy, const unsigned long *, nmask,
unsigned long, maxnode, void *, addr, int, flags);
KVM_SYSCALL_DEFINE(set_mempolicy, 3, int, mode, const unsigned long *, nmask,
unsigned long, maxnode);
KVM_SYSCALL_DEFINE(set_mempolicy_home_node, 4, unsigned long, start,
unsigned long, len, unsigned long, home_node,
unsigned long, flags);
KVM_SYSCALL_DEFINE(migrate_pages, 4, int, pid, unsigned long, maxnode,
const unsigned long *, frommask, const unsigned long *, tomask);
KVM_SYSCALL_DEFINE(move_pages, 6, int, pid, unsigned long, count, void *, pages,
const int *, nodes, int *, status, int, flags);
KVM_SYSCALL_DEFINE(mbind, 6, void *, addr, unsigned long, size, int, mode,
const unsigned long *, nodemask, unsigned long, maxnode,
unsigned int, flags);
static inline int get_max_numa_node(void)
{
struct dirent *de;
int max_node = 0;
DIR *d;
/*
* Assume there's a single node if the kernel doesn't support NUMA,
* or if no nodes are found.
*/
d = opendir("/sys/devices/system/node");
if (!d)
return 0;
while ((de = readdir(d)) != NULL) {
int node_id;
char *endptr;
if (strncmp(de->d_name, "node", 4) != 0)
continue;
node_id = strtol(de->d_name + 4, &endptr, 10);
if (*endptr != '\0')
continue;
if (node_id > max_node)
max_node = node_id;
}
closedir(d);
return max_node;
}
static bool is_numa_available(void)
{
/*
* Probe for NUMA by doing a dummy get_mempolicy(). If the syscall
* fails with ENOSYS, then the kernel was built without NUMA support.
* if the syscall fails with EPERM, then the process/user lacks the
* necessary capabilities (CAP_SYS_NICE).
*/
return !get_mempolicy(NULL, NULL, 0, NULL, 0) ||
(errno != ENOSYS && errno != EPERM);
}
static inline bool is_multi_numa_node_system(void)
{
return is_numa_available() && get_max_numa_node() >= 1;
}
#endif /* SELFTEST_KVM_NUMAIF_H */
@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* RISC-V Arch Timer(sstc) specific interface
*
* Copyright (c) 2024 Intel Corporation
*/
#ifndef SELFTEST_KVM_ARCH_TIMER_H
#define SELFTEST_KVM_ARCH_TIMER_H
#include <asm/csr.h>
#include <asm/vdso/processor.h>
static unsigned long timer_freq;
#define msec_to_cycles(msec) \
((timer_freq) * (u64)(msec) / 1000)
#define usec_to_cycles(usec) \
((timer_freq) * (u64)(usec) / 1000000)
#define cycles_to_usec(cycles) \
((u64)(cycles) * 1000000 / (timer_freq))
static inline u64 timer_get_cycles(void)
{
return csr_read(CSR_TIME);
}
static inline void timer_set_cmp(u64 cval)
{
csr_write(CSR_STIMECMP, cval);
}
static inline u64 timer_get_cmp(void)
{
return csr_read(CSR_STIMECMP);
}
static inline void timer_irq_enable(void)
{
csr_set(CSR_SIE, IE_TIE);
}
static inline void timer_irq_disable(void)
{
csr_clear(CSR_SIE, IE_TIE);
}
static inline void timer_set_next_cmp_ms(u32 msec)
{
u64 now_ct = timer_get_cycles();
u64 next_ct = now_ct + msec_to_cycles(msec);
timer_set_cmp(next_ct);
}
static inline void __delay(u64 cycles)
{
u64 start = timer_get_cycles();
while ((timer_get_cycles() - start) < cycles)
cpu_relax();
}
static inline void udelay(unsigned long usec)
{
__delay(usec_to_cycles(usec));
}
#endif /* SELFTEST_KVM_ARCH_TIMER_H */
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UTIL_ARCH_H
#define SELFTEST_KVM_UTIL_ARCH_H
struct kvm_mmu_arch {};
struct kvm_vm_arch {};
#endif // SELFTEST_KVM_UTIL_ARCH_H
@@ -0,0 +1,196 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* RISC-V processor specific defines
*
* Copyright (C) 2021 Western Digital Corporation or its affiliates.
*/
#ifndef SELFTEST_KVM_PROCESSOR_H
#define SELFTEST_KVM_PROCESSOR_H
#include <linux/stringify.h>
#include <asm/csr.h>
#include <asm/vdso/processor.h>
#include "kvm_util.h"
#define INSN_OPCODE_MASK 0x007c
#define INSN_OPCODE_SHIFT 2
#define INSN_OPCODE_SYSTEM 28
#define INSN_MASK_FUNCT3 0x7000
#define INSN_SHIFT_FUNCT3 12
#define INSN_CSR_MASK 0xfff00000
#define INSN_CSR_SHIFT 20
#define GET_RM(insn) (((insn) & INSN_MASK_FUNCT3) >> INSN_SHIFT_FUNCT3)
#define GET_CSR_NUM(insn) (((insn) & INSN_CSR_MASK) >> INSN_CSR_SHIFT)
static inline u64 __kvm_reg_id(u64 type, u64 subtype, u64 idx, u64 size)
{
return KVM_REG_RISCV | type | subtype | idx | size;
}
#if __riscv_xlen == 64
#define KVM_REG_SIZE_ULONG KVM_REG_SIZE_U64
#else
#define KVM_REG_SIZE_ULONG KVM_REG_SIZE_U32
#endif
#define RISCV_CONFIG_REG(name) __kvm_reg_id(KVM_REG_RISCV_CONFIG, 0, \
KVM_REG_RISCV_CONFIG_REG(name), \
KVM_REG_SIZE_ULONG)
#define RISCV_CORE_REG(name) __kvm_reg_id(KVM_REG_RISCV_CORE, 0, \
KVM_REG_RISCV_CORE_REG(name), \
KVM_REG_SIZE_ULONG)
#define RISCV_GENERAL_CSR_REG(name) __kvm_reg_id(KVM_REG_RISCV_CSR, \
KVM_REG_RISCV_CSR_GENERAL, \
KVM_REG_RISCV_CSR_REG(name), \
KVM_REG_SIZE_ULONG)
#define RISCV_TIMER_REG(name) __kvm_reg_id(KVM_REG_RISCV_TIMER, 0, \
KVM_REG_RISCV_TIMER_REG(name), \
KVM_REG_SIZE_U64)
#define RISCV_ISA_EXT_REG(idx) __kvm_reg_id(KVM_REG_RISCV_ISA_EXT, \
KVM_REG_RISCV_ISA_SINGLE, \
idx, KVM_REG_SIZE_ULONG)
#define RISCV_SBI_EXT_REG(idx) __kvm_reg_id(KVM_REG_RISCV_SBI_EXT, \
KVM_REG_RISCV_SBI_SINGLE, \
idx, KVM_REG_SIZE_ULONG)
bool __vcpu_has_ext(struct kvm_vcpu *vcpu, u64 ext);
static inline bool __vcpu_has_isa_ext(struct kvm_vcpu *vcpu, u64 isa_ext)
{
return __vcpu_has_ext(vcpu, RISCV_ISA_EXT_REG(isa_ext));
}
static inline bool __vcpu_has_sbi_ext(struct kvm_vcpu *vcpu, u64 sbi_ext)
{
return __vcpu_has_ext(vcpu, RISCV_SBI_EXT_REG(sbi_ext));
}
struct pt_regs {
unsigned long epc;
unsigned long ra;
unsigned long sp;
unsigned long gp;
unsigned long tp;
unsigned long t0;
unsigned long t1;
unsigned long t2;
unsigned long s0;
unsigned long s1;
unsigned long a0;
unsigned long a1;
unsigned long a2;
unsigned long a3;
unsigned long a4;
unsigned long a5;
unsigned long a6;
unsigned long a7;
unsigned long s2;
unsigned long s3;
unsigned long s4;
unsigned long s5;
unsigned long s6;
unsigned long s7;
unsigned long s8;
unsigned long s9;
unsigned long s10;
unsigned long s11;
unsigned long t3;
unsigned long t4;
unsigned long t5;
unsigned long t6;
/* Supervisor/Machine CSRs */
unsigned long status;
unsigned long badaddr;
unsigned long cause;
/* a0 value before the syscall */
unsigned long orig_a0;
};
#define NR_VECTORS 2
#define NR_EXCEPTIONS 32
#define EC_MASK (NR_EXCEPTIONS - 1)
typedef void(*exception_handler_fn)(struct pt_regs *);
void vm_init_vector_tables(struct kvm_vm *vm);
void vcpu_init_vector_tables(struct kvm_vcpu *vcpu);
void vm_install_exception_handler(struct kvm_vm *vm, int vector, exception_handler_fn handler);
void vm_install_interrupt_handler(struct kvm_vm *vm, exception_handler_fn handler);
/* L3 index Bit[47:39] */
#define PGTBL_L3_INDEX_MASK 0x0000FF8000000000ULL
#define PGTBL_L3_INDEX_SHIFT 39
#define PGTBL_L3_BLOCK_SHIFT 39
#define PGTBL_L3_BLOCK_SIZE 0x0000008000000000ULL
#define PGTBL_L3_MAP_MASK (~(PGTBL_L3_BLOCK_SIZE - 1))
/* L2 index Bit[38:30] */
#define PGTBL_L2_INDEX_MASK 0x0000007FC0000000ULL
#define PGTBL_L2_INDEX_SHIFT 30
#define PGTBL_L2_BLOCK_SHIFT 30
#define PGTBL_L2_BLOCK_SIZE 0x0000000040000000ULL
#define PGTBL_L2_MAP_MASK (~(PGTBL_L2_BLOCK_SIZE - 1))
/* L1 index Bit[29:21] */
#define PGTBL_L1_INDEX_MASK 0x000000003FE00000ULL
#define PGTBL_L1_INDEX_SHIFT 21
#define PGTBL_L1_BLOCK_SHIFT 21
#define PGTBL_L1_BLOCK_SIZE 0x0000000000200000ULL
#define PGTBL_L1_MAP_MASK (~(PGTBL_L1_BLOCK_SIZE - 1))
/* L0 index Bit[20:12] */
#define PGTBL_L0_INDEX_MASK 0x00000000001FF000ULL
#define PGTBL_L0_INDEX_SHIFT 12
#define PGTBL_L0_BLOCK_SHIFT 12
#define PGTBL_L0_BLOCK_SIZE 0x0000000000001000ULL
#define PGTBL_L0_MAP_MASK (~(PGTBL_L0_BLOCK_SIZE - 1))
#define PGTBL_PTE_ADDR_MASK 0x003FFFFFFFFFFC00ULL
#define PGTBL_PTE_ADDR_SHIFT 10
#define PGTBL_PTE_RSW_MASK 0x0000000000000300ULL
#define PGTBL_PTE_RSW_SHIFT 8
#define PGTBL_PTE_DIRTY_MASK 0x0000000000000080ULL
#define PGTBL_PTE_DIRTY_SHIFT 7
#define PGTBL_PTE_ACCESSED_MASK 0x0000000000000040ULL
#define PGTBL_PTE_ACCESSED_SHIFT 6
#define PGTBL_PTE_GLOBAL_MASK 0x0000000000000020ULL
#define PGTBL_PTE_GLOBAL_SHIFT 5
#define PGTBL_PTE_USER_MASK 0x0000000000000010ULL
#define PGTBL_PTE_USER_SHIFT 4
#define PGTBL_PTE_EXECUTE_MASK 0x0000000000000008ULL
#define PGTBL_PTE_EXECUTE_SHIFT 3
#define PGTBL_PTE_WRITE_MASK 0x0000000000000004ULL
#define PGTBL_PTE_WRITE_SHIFT 2
#define PGTBL_PTE_READ_MASK 0x0000000000000002ULL
#define PGTBL_PTE_READ_SHIFT 1
#define PGTBL_PTE_PERM_MASK (PGTBL_PTE_ACCESSED_MASK | \
PGTBL_PTE_DIRTY_MASK | \
PGTBL_PTE_EXECUTE_MASK | \
PGTBL_PTE_WRITE_MASK | \
PGTBL_PTE_READ_MASK)
#define PGTBL_PTE_VALID_MASK 0x0000000000000001ULL
#define PGTBL_PTE_VALID_SHIFT 0
#define PGTBL_PAGE_SIZE PGTBL_L0_BLOCK_SIZE
#define PGTBL_PAGE_SIZE_SHIFT PGTBL_L0_BLOCK_SHIFT
static inline void local_irq_enable(void)
{
csr_set(CSR_SSTATUS, SR_SIE);
}
static inline void local_irq_disable(void)
{
csr_clear(CSR_SSTATUS, SR_SIE);
}
unsigned long riscv64_get_satp_mode(void);
#endif /* SELFTEST_KVM_PROCESSOR_H */
@@ -0,0 +1,178 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* RISC-V SBI specific definitions
*
* Copyright (C) 2024 Rivos Inc.
*/
#ifndef SELFTEST_KVM_SBI_H
#define SELFTEST_KVM_SBI_H
/* SBI spec version fields */
#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff
/* SBI return error codes */
#define SBI_SUCCESS 0
#define SBI_ERR_FAILURE -1
#define SBI_ERR_NOT_SUPPORTED -2
#define SBI_ERR_INVALID_PARAM -3
#define SBI_ERR_DENIED -4
#define SBI_ERR_INVALID_ADDRESS -5
#define SBI_ERR_ALREADY_AVAILABLE -6
#define SBI_ERR_ALREADY_STARTED -7
#define SBI_ERR_ALREADY_STOPPED -8
#define SBI_EXT_EXPERIMENTAL_START 0x08000000
#define SBI_EXT_EXPERIMENTAL_END 0x08FFFFFF
#define KVM_RISCV_SELFTESTS_SBI_EXT SBI_EXT_EXPERIMENTAL_END
#define KVM_RISCV_SELFTESTS_SBI_UCALL 0
#define KVM_RISCV_SELFTESTS_SBI_UNEXP 1
enum sbi_ext_id {
SBI_EXT_BASE = 0x10,
SBI_EXT_STA = 0x535441,
SBI_EXT_PMU = 0x504D55,
};
enum sbi_ext_base_fid {
SBI_EXT_BASE_GET_SPEC_VERSION = 0,
SBI_EXT_BASE_GET_IMP_ID,
SBI_EXT_BASE_GET_IMP_VERSION,
SBI_EXT_BASE_PROBE_EXT = 3,
};
enum sbi_ext_pmu_fid {
SBI_EXT_PMU_NUM_COUNTERS = 0,
SBI_EXT_PMU_COUNTER_GET_INFO,
SBI_EXT_PMU_COUNTER_CFG_MATCH,
SBI_EXT_PMU_COUNTER_START,
SBI_EXT_PMU_COUNTER_STOP,
SBI_EXT_PMU_COUNTER_FW_READ,
SBI_EXT_PMU_COUNTER_FW_READ_HI,
SBI_EXT_PMU_SNAPSHOT_SET_SHMEM,
};
union sbi_pmu_ctr_info {
unsigned long value;
struct {
unsigned long csr:12;
unsigned long width:6;
#if __riscv_xlen == 32
unsigned long reserved:13;
#else
unsigned long reserved:45;
#endif
unsigned long type:1;
};
};
struct riscv_pmu_snapshot_data {
u64 ctr_overflow_mask;
u64 ctr_values[64];
u64 reserved[447];
};
struct sbiret {
long error;
long value;
};
/** General pmu event codes specified in SBI PMU extension */
enum sbi_pmu_hw_generic_events_t {
SBI_PMU_HW_NO_EVENT = 0,
SBI_PMU_HW_CPU_CYCLES = 1,
SBI_PMU_HW_INSTRUCTIONS = 2,
SBI_PMU_HW_CACHE_REFERENCES = 3,
SBI_PMU_HW_CACHE_MISSES = 4,
SBI_PMU_HW_BRANCH_INSTRUCTIONS = 5,
SBI_PMU_HW_BRANCH_MISSES = 6,
SBI_PMU_HW_BUS_CYCLES = 7,
SBI_PMU_HW_STALLED_CYCLES_FRONTEND = 8,
SBI_PMU_HW_STALLED_CYCLES_BACKEND = 9,
SBI_PMU_HW_REF_CPU_CYCLES = 10,
SBI_PMU_HW_GENERAL_MAX,
};
enum sbi_pmu_fw_generic_events_t {
SBI_PMU_FW_MISALIGNED_LOAD = 0,
SBI_PMU_FW_MISALIGNED_STORE = 1,
SBI_PMU_FW_ACCESS_LOAD = 2,
SBI_PMU_FW_ACCESS_STORE = 3,
SBI_PMU_FW_ILLEGAL_INSN = 4,
SBI_PMU_FW_SET_TIMER = 5,
SBI_PMU_FW_IPI_SENT = 6,
SBI_PMU_FW_IPI_RCVD = 7,
SBI_PMU_FW_FENCE_I_SENT = 8,
SBI_PMU_FW_FENCE_I_RCVD = 9,
SBI_PMU_FW_SFENCE_VMA_SENT = 10,
SBI_PMU_FW_SFENCE_VMA_RCVD = 11,
SBI_PMU_FW_SFENCE_VMA_ASID_SENT = 12,
SBI_PMU_FW_SFENCE_VMA_ASID_RCVD = 13,
SBI_PMU_FW_HFENCE_GVMA_SENT = 14,
SBI_PMU_FW_HFENCE_GVMA_RCVD = 15,
SBI_PMU_FW_HFENCE_GVMA_VMID_SENT = 16,
SBI_PMU_FW_HFENCE_GVMA_VMID_RCVD = 17,
SBI_PMU_FW_HFENCE_VVMA_SENT = 18,
SBI_PMU_FW_HFENCE_VVMA_RCVD = 19,
SBI_PMU_FW_HFENCE_VVMA_ASID_SENT = 20,
SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD = 21,
SBI_PMU_FW_MAX,
};
/* SBI PMU event types */
enum sbi_pmu_event_type {
SBI_PMU_EVENT_TYPE_HW = 0x0,
SBI_PMU_EVENT_TYPE_CACHE = 0x1,
SBI_PMU_EVENT_TYPE_RAW = 0x2,
SBI_PMU_EVENT_TYPE_RAW_V2 = 0x3,
SBI_PMU_EVENT_TYPE_FW = 0xf,
};
/* SBI PMU counter types */
enum sbi_pmu_ctr_type {
SBI_PMU_CTR_TYPE_HW = 0x0,
SBI_PMU_CTR_TYPE_FW,
};
/* Flags defined for config matching function */
#define SBI_PMU_CFG_FLAG_SKIP_MATCH BIT(0)
#define SBI_PMU_CFG_FLAG_CLEAR_VALUE BIT(1)
#define SBI_PMU_CFG_FLAG_AUTO_START BIT(2)
#define SBI_PMU_CFG_FLAG_SET_VUINH BIT(3)
#define SBI_PMU_CFG_FLAG_SET_VSINH BIT(4)
#define SBI_PMU_CFG_FLAG_SET_UINH BIT(5)
#define SBI_PMU_CFG_FLAG_SET_SINH BIT(6)
#define SBI_PMU_CFG_FLAG_SET_MINH BIT(7)
/* Flags defined for counter start function */
#define SBI_PMU_START_FLAG_SET_INIT_VALUE BIT(0)
#define SBI_PMU_START_FLAG_INIT_SNAPSHOT BIT(1)
/* Flags defined for counter stop function */
#define SBI_PMU_STOP_FLAG_RESET BIT(0)
#define SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT BIT(1)
struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
unsigned long arg1, unsigned long arg2,
unsigned long arg3, unsigned long arg4,
unsigned long arg5);
bool guest_sbi_probe_extension(int extid, long *out_val);
/* Make SBI version */
static inline unsigned long sbi_mk_version(unsigned long major,
unsigned long minor)
{
return ((major & SBI_SPEC_VERSION_MAJOR_MASK) << SBI_SPEC_VERSION_MAJOR_SHIFT)
| (minor & SBI_SPEC_VERSION_MINOR_MASK);
}
unsigned long get_host_sbi_spec_version(void);
#endif /* SELFTEST_KVM_SBI_H */
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UCALL_H
#define SELFTEST_KVM_UCALL_H
#include "processor.h"
#include "sbi.h"
#define UCALL_EXIT_REASON KVM_EXIT_RISCV_SBI
static inline void ucall_arch_init(struct kvm_vm *vm, gpa_t mmio_gpa)
{
}
static inline void ucall_arch_do_ucall(gva_t uc)
{
sbi_ecall(KVM_RISCV_SELFTESTS_SBI_EXT,
KVM_RISCV_SELFTESTS_SBI_UCALL,
uc, 0, 0, 0, 0, 0);
}
#endif
@@ -0,0 +1,69 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Definition for kernel virtual machines on s390x
*
* Copyright IBM Corp. 2024
*
* Authors:
* Christoph Schlameuss <schlameuss@linux.ibm.com>
*/
#ifndef SELFTEST_KVM_DEBUG_PRINT_H
#define SELFTEST_KVM_DEBUG_PRINT_H
#include "asm/ptrace.h"
#include "kvm_util.h"
#include "sie.h"
static inline void print_hex_bytes(const char *name, u64 addr, size_t len)
{
u64 pos;
pr_debug("%s (%p)\n", name, (void *)addr);
pr_debug(" 0/0x00---------|");
if (len > 8)
pr_debug(" 8/0x08---------|");
if (len > 16)
pr_debug(" 16/0x10--------|");
if (len > 24)
pr_debug(" 24/0x18--------|");
for (pos = 0; pos < len; pos += 8) {
if ((pos % 32) == 0)
pr_debug("\n %3lu 0x%.3lx ", pos, pos);
pr_debug(" %16lx", *((u64 *)(addr + pos)));
}
pr_debug("\n");
}
static inline void print_hex(const char *name, u64 addr)
{
print_hex_bytes(name, addr, 512);
}
static inline void print_psw(struct kvm_run *run, struct kvm_s390_sie_block *sie_block)
{
pr_debug("flags:0x%x psw:0x%.16llx:0x%.16llx exit:%u %s\n",
run->flags,
run->psw_mask, run->psw_addr,
run->exit_reason, exit_reason_str(run->exit_reason));
pr_debug("sie_block psw:0x%.16llx:0x%.16llx\n",
sie_block->psw_mask, sie_block->psw_addr);
}
static inline void print_run(struct kvm_run *run, struct kvm_s390_sie_block *sie_block)
{
print_hex_bytes("run", (u64)run, 0x150);
print_hex("sie_block", (u64)sie_block);
print_psw(run, sie_block);
}
static inline void print_regs(struct kvm_run *run)
{
struct kvm_sync_regs *sync_regs = &run->s.regs;
print_hex_bytes("GPRS", (u64)sync_regs->gprs, 8 * NUM_GPRS);
print_hex_bytes("ACRS", (u64)sync_regs->acrs, 4 * NUM_ACRS);
print_hex_bytes("CRS", (u64)sync_regs->crs, 8 * NUM_CRS);
}
#endif /* SELFTEST_KVM_DEBUG_PRINT_H */
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
*
* Test handler for the s390x DIAGNOSE 0x0318 instruction.
*
* Copyright (C) 2020, IBM
*/
#ifndef SELFTEST_KVM_DIAG318_TEST_HANDLER
#define SELFTEST_KVM_DIAG318_TEST_HANDLER
u64 get_diag318_info(void);
#endif
@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright IBM Corp. 2024
*
* Authors:
* Hariharan Mari <hari55@linux.ibm.com>
*
* Get the facility bits with the STFLE instruction
*/
#ifndef SELFTEST_KVM_FACILITY_H
#define SELFTEST_KVM_FACILITY_H
#include <linux/atomic.h>
#include <linux/bitops.h>
/* alt_stfle_fac_list[16] + stfle_fac_list[16] */
#define NB_STFL_DOUBLEWORDS 32
extern u64 stfl_doublewords[NB_STFL_DOUBLEWORDS];
extern bool stfle_flag;
static inline bool clear_bit_inv(unsigned long nr, unsigned long *ptr)
{
return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
static inline bool test_bit_inv(unsigned long nr, const unsigned long *ptr)
{
return test_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
static inline void stfle(u64 *fac, unsigned int nb_doublewords)
{
register unsigned long r0 asm("0") = nb_doublewords - 1;
asm volatile(" .insn s,0xb2b00000,0(%1)\n"
: "+d" (r0)
: "a" (fac)
: "memory", "cc");
}
static inline void setup_facilities(void)
{
stfle(stfl_doublewords, NB_STFL_DOUBLEWORDS);
stfle_flag = true;
}
static inline bool test_facility(int nr)
{
if (!stfle_flag)
setup_facilities();
return test_bit_inv(nr, stfl_doublewords);
}
#endif
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UTIL_ARCH_H
#define SELFTEST_KVM_UTIL_ARCH_H
struct kvm_mmu_arch {};
struct kvm_vm_arch {};
#endif // SELFTEST_KVM_UTIL_ARCH_H
@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* s390x processor specific defines
*/
#ifndef SELFTEST_KVM_PROCESSOR_H
#define SELFTEST_KVM_PROCESSOR_H
#include <linux/compiler.h>
/* Bits in the region/segment table entry */
#define REGION_ENTRY_ORIGIN ~0xfffUL /* region/segment table origin */
#define REGION_ENTRY_PROTECT 0x200 /* region protection bit */
#define REGION_ENTRY_NOEXEC 0x100 /* region no-execute bit */
#define REGION_ENTRY_OFFSET 0xc0 /* region table offset */
#define REGION_ENTRY_INVALID 0x20 /* invalid region table entry */
#define REGION_ENTRY_TYPE 0x0c /* region/segment table type mask */
#define REGION_ENTRY_LENGTH 0x03 /* region third length */
/* Bits in the page table entry */
#define PAGE_INVALID 0x400 /* HW invalid bit */
#define PAGE_PROTECT 0x200 /* HW read-only bit */
#define PAGE_NOEXEC 0x100 /* HW no-execute bit */
/* Page size definitions */
#define PAGE_SHIFT 12
#define PAGE_SIZE BIT_ULL(PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
/* Is there a portable way to do this? */
static inline void cpu_relax(void)
{
barrier();
}
/* Get the instruction length */
static inline int insn_length(unsigned char code)
{
return ((((int)code + 64) >> 7) + 1) << 1;
}
#endif
@@ -0,0 +1,240 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Definition for kernel virtual machines on s390.
*
* Adapted copy of struct definition kvm_s390_sie_block from
* arch/s390/include/asm/kvm_host.h for use in userspace selftest programs.
*
* Copyright IBM Corp. 2008, 2024
*
* Authors:
* Christoph Schlameuss <schlameuss@linux.ibm.com>
* Carsten Otte <cotte@de.ibm.com>
*/
#ifndef SELFTEST_KVM_SIE_H
#define SELFTEST_KVM_SIE_H
#include <linux/types.h>
struct kvm_s390_sie_block {
#define CPUSTAT_STOPPED 0x80000000
#define CPUSTAT_WAIT 0x10000000
#define CPUSTAT_ECALL_PEND 0x08000000
#define CPUSTAT_STOP_INT 0x04000000
#define CPUSTAT_IO_INT 0x02000000
#define CPUSTAT_EXT_INT 0x01000000
#define CPUSTAT_RUNNING 0x00800000
#define CPUSTAT_RETAINED 0x00400000
#define CPUSTAT_TIMING_SUB 0x00020000
#define CPUSTAT_SIE_SUB 0x00010000
#define CPUSTAT_RRF 0x00008000
#define CPUSTAT_SLSV 0x00004000
#define CPUSTAT_SLSR 0x00002000
#define CPUSTAT_ZARCH 0x00000800
#define CPUSTAT_MCDS 0x00000100
#define CPUSTAT_KSS 0x00000200
#define CPUSTAT_SM 0x00000080
#define CPUSTAT_IBS 0x00000040
#define CPUSTAT_GED2 0x00000010
#define CPUSTAT_G 0x00000008
#define CPUSTAT_GED 0x00000004
#define CPUSTAT_J 0x00000002
#define CPUSTAT_P 0x00000001
__u32 cpuflags; /* 0x0000 */
__u32: 1; /* 0x0004 */
__u32 prefix : 18;
__u32: 1;
__u32 ibc : 12;
__u8 reserved08[4]; /* 0x0008 */
#define PROG_IN_SIE BIT(0)
__u32 prog0c; /* 0x000c */
union {
__u8 reserved10[16]; /* 0x0010 */
struct {
__u64 pv_handle_cpu;
__u64 pv_handle_config;
};
};
#define PROG_BLOCK_SIE BIT(0)
#define PROG_REQUEST BIT(1)
__u32 prog20; /* 0x0020 */
__u8 reserved24[4]; /* 0x0024 */
__u64 cputm; /* 0x0028 */
__u64 ckc; /* 0x0030 */
__u64 epoch; /* 0x0038 */
__u32 svcc; /* 0x0040 */
#define LCTL_CR0 0x8000
#define LCTL_CR6 0x0200
#define LCTL_CR9 0x0040
#define LCTL_CR10 0x0020
#define LCTL_CR11 0x0010
#define LCTL_CR14 0x0002
__u16 lctl; /* 0x0044 */
__s16 icpua; /* 0x0046 */
#define ICTL_OPEREXC 0x80000000
#define ICTL_PINT 0x20000000
#define ICTL_LPSW 0x00400000
#define ICTL_STCTL 0x00040000
#define ICTL_ISKE 0x00004000
#define ICTL_SSKE 0x00002000
#define ICTL_RRBE 0x00001000
#define ICTL_TPROT 0x00000200
__u32 ictl; /* 0x0048 */
#define ECA_CEI 0x80000000
#define ECA_IB 0x40000000
#define ECA_SIGPI 0x10000000
#define ECA_MVPGI 0x01000000
#define ECA_AIV 0x00200000
#define ECA_VX 0x00020000
#define ECA_PROTEXCI 0x00002000
#define ECA_APIE 0x00000008
#define ECA_SII 0x00000001
__u32 eca; /* 0x004c */
#define ICPT_INST 0x04
#define ICPT_PROGI 0x08
#define ICPT_INSTPROGI 0x0C
#define ICPT_EXTREQ 0x10
#define ICPT_EXTINT 0x14
#define ICPT_IOREQ 0x18
#define ICPT_WAIT 0x1c
#define ICPT_VALIDITY 0x20
#define ICPT_STOP 0x28
#define ICPT_OPEREXC 0x2C
#define ICPT_PARTEXEC 0x38
#define ICPT_IOINST 0x40
#define ICPT_KSS 0x5c
#define ICPT_MCHKREQ 0x60
#define ICPT_INT_ENABLE 0x64
#define ICPT_PV_INSTR 0x68
#define ICPT_PV_NOTIFY 0x6c
#define ICPT_PV_PREF 0x70
__u8 icptcode; /* 0x0050 */
__u8 icptstatus; /* 0x0051 */
__u16 ihcpu; /* 0x0052 */
__u8 reserved54; /* 0x0054 */
#define IICTL_CODE_NONE 0x00
#define IICTL_CODE_MCHK 0x01
#define IICTL_CODE_EXT 0x02
#define IICTL_CODE_IO 0x03
#define IICTL_CODE_RESTART 0x04
#define IICTL_CODE_SPECIFICATION 0x10
#define IICTL_CODE_OPERAND 0x11
__u8 iictl; /* 0x0055 */
__u16 ipa; /* 0x0056 */
__u32 ipb; /* 0x0058 */
__u32 scaoh; /* 0x005c */
#define FPF_BPBC 0x20
__u8 fpf; /* 0x0060 */
#define ECB_GS 0x40
#define ECB_TE 0x10
#define ECB_SPECI 0x08
#define ECB_SRSI 0x04
#define ECB_HOSTPROTINT 0x02
#define ECB_PTF 0x01
__u8 ecb; /* 0x0061 */
#define ECB2_CMMA 0x80
#define ECB2_IEP 0x20
#define ECB2_PFMFI 0x08
#define ECB2_ESCA 0x04
#define ECB2_ZPCI_LSI 0x02
__u8 ecb2; /* 0x0062 */
#define ECB3_AISI 0x20
#define ECB3_AISII 0x10
#define ECB3_DEA 0x08
#define ECB3_AES 0x04
#define ECB3_RI 0x01
__u8 ecb3; /* 0x0063 */
#define ESCA_SCAOL_MASK ~0x3fU
__u32 scaol; /* 0x0064 */
__u8 sdf; /* 0x0068 */
__u8 epdx; /* 0x0069 */
__u8 cpnc; /* 0x006a */
__u8 reserved6b; /* 0x006b */
__u32 todpr; /* 0x006c */
#define GISA_FORMAT1 0x00000001
__u32 gd; /* 0x0070 */
__u8 reserved74[12]; /* 0x0074 */
__u64 mso; /* 0x0080 */
__u64 msl; /* 0x0088 */
__u64 psw_mask; /* 0x0090 */
__u64 psw_addr; /* 0x0098 */
__u64 gg14; /* 0x00a0 */
__u64 gg15; /* 0x00a8 */
__u8 reservedb0[8]; /* 0x00b0 */
#define HPID_KVM 0x4
#define HPID_VSIE 0x5
__u8 hpid; /* 0x00b8 */
__u8 reservedb9[7]; /* 0x00b9 */
union {
struct {
__u32 eiparams; /* 0x00c0 */
__u16 extcpuaddr; /* 0x00c4 */
__u16 eic; /* 0x00c6 */
};
__u64 mcic; /* 0x00c0 */
} __packed;
__u32 reservedc8; /* 0x00c8 */
union {
struct {
__u16 pgmilc; /* 0x00cc */
__u16 iprcc; /* 0x00ce */
};
__u32 edc; /* 0x00cc */
} __packed;
union {
struct {
__u32 dxc; /* 0x00d0 */
__u16 mcn; /* 0x00d4 */
__u8 perc; /* 0x00d6 */
__u8 peratmid; /* 0x00d7 */
};
__u64 faddr; /* 0x00d0 */
} __packed;
__u64 peraddr; /* 0x00d8 */
__u8 eai; /* 0x00e0 */
__u8 peraid; /* 0x00e1 */
__u8 oai; /* 0x00e2 */
__u8 armid; /* 0x00e3 */
__u8 reservede4[4]; /* 0x00e4 */
union {
__u64 tecmc; /* 0x00e8 */
struct {
__u16 subchannel_id; /* 0x00e8 */
__u16 subchannel_nr; /* 0x00ea */
__u32 io_int_parm; /* 0x00ec */
__u32 io_int_word; /* 0x00f0 */
};
} __packed;
__u8 reservedf4[8]; /* 0x00f4 */
#define CRYCB_FORMAT_MASK 0x00000003
#define CRYCB_FORMAT0 0x00000000
#define CRYCB_FORMAT1 0x00000001
#define CRYCB_FORMAT2 0x00000003
__u32 crycbd; /* 0x00fc */
__u64 gcr[16]; /* 0x0100 */
union {
__u64 gbea; /* 0x0180 */
__u64 sidad;
};
__u8 reserved188[8]; /* 0x0188 */
__u64 sdnxo; /* 0x0190 */
__u8 reserved198[8]; /* 0x0198 */
__u32 fac; /* 0x01a0 */
__u8 reserved1a4[20]; /* 0x01a4 */
__u64 cbrlo; /* 0x01b8 */
__u8 reserved1c0[8]; /* 0x01c0 */
#define ECD_HOSTREGMGMT 0x20000000
#define ECD_MEF 0x08000000
#define ECD_ETOKENF 0x02000000
#define ECD_ECC 0x00200000
__u32 ecd; /* 0x01c8 */
__u8 reserved1cc[18]; /* 0x01cc */
__u64 pp; /* 0x01de */
__u8 reserved1e6[2]; /* 0x01e6 */
__u64 itdba; /* 0x01e8 */
__u64 riccbd; /* 0x01f0 */
__u64 gvrd; /* 0x01f8 */
} __packed __aligned(512);
#endif /* SELFTEST_KVM_SIE_H */
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UCALL_H
#define SELFTEST_KVM_UCALL_H
#include "kvm_util.h"
#define UCALL_EXIT_REASON KVM_EXIT_S390_SIEIC
static inline void ucall_arch_init(struct kvm_vm *vm, gpa_t mmio_gpa)
{
}
static inline void ucall_arch_do_ucall(gva_t uc)
{
/* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */
asm volatile ("diag 0,%0,0x501" : : "a"(uc) : "memory");
}
#endif
@@ -0,0 +1,93 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* tools/testing/selftests/kvm/include/sparsebit.h
*
* Copyright (C) 2018, Google LLC.
*
* Header file that describes API to the sparsebit library.
* This library provides a memory efficient means of storing
* the settings of bits indexed via a u64. Memory usage
* is reasonable, significantly less than (2^64 / 8) bytes, as
* long as bits that are mostly set or mostly cleared are close
* to each other. This library is efficient in memory usage
* even in the case where most bits are set.
*/
#ifndef SELFTEST_KVM_SPARSEBIT_H
#define SELFTEST_KVM_SPARSEBIT_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct sparsebit;
typedef u64 sparsebit_idx_t;
typedef u64 sparsebit_num_t;
struct sparsebit *sparsebit_alloc(void);
void sparsebit_free(struct sparsebit **sbitp);
void sparsebit_copy(struct sparsebit *dstp, const struct sparsebit *src);
bool sparsebit_is_set(const struct sparsebit *sbit, sparsebit_idx_t idx);
bool sparsebit_is_set_num(const struct sparsebit *sbit,
sparsebit_idx_t idx, sparsebit_num_t num);
bool sparsebit_is_clear(const struct sparsebit *sbit, sparsebit_idx_t idx);
bool sparsebit_is_clear_num(const struct sparsebit *sbit,
sparsebit_idx_t idx, sparsebit_num_t num);
sparsebit_num_t sparsebit_num_set(const struct sparsebit *sbit);
bool sparsebit_any_set(const struct sparsebit *sbit);
bool sparsebit_any_clear(const struct sparsebit *sbit);
bool sparsebit_all_set(const struct sparsebit *sbit);
bool sparsebit_all_clear(const struct sparsebit *sbit);
sparsebit_idx_t sparsebit_first_set(const struct sparsebit *sbit);
sparsebit_idx_t sparsebit_first_clear(const struct sparsebit *sbit);
sparsebit_idx_t sparsebit_next_set(const struct sparsebit *sbit, sparsebit_idx_t prev);
sparsebit_idx_t sparsebit_next_clear(const struct sparsebit *sbit, sparsebit_idx_t prev);
sparsebit_idx_t sparsebit_next_set_num(const struct sparsebit *sbit,
sparsebit_idx_t start, sparsebit_num_t num);
sparsebit_idx_t sparsebit_next_clear_num(const struct sparsebit *sbit,
sparsebit_idx_t start, sparsebit_num_t num);
void sparsebit_set(struct sparsebit *sbitp, sparsebit_idx_t idx);
void sparsebit_set_num(struct sparsebit *sbitp, sparsebit_idx_t start,
sparsebit_num_t num);
void sparsebit_set_all(struct sparsebit *sbitp);
void sparsebit_clear(struct sparsebit *sbitp, sparsebit_idx_t idx);
void sparsebit_clear_num(struct sparsebit *sbitp,
sparsebit_idx_t start, sparsebit_num_t num);
void sparsebit_clear_all(struct sparsebit *sbitp);
void sparsebit_dump(FILE *stream, const struct sparsebit *sbit,
unsigned int indent);
void sparsebit_validate_internal(const struct sparsebit *sbit);
/*
* Iterate over an inclusive ranges within sparsebit @s. In each iteration,
* @range_begin and @range_end will take the beginning and end of the set
* range, which are of type sparsebit_idx_t.
*
* For example, if the range [3, 7] (inclusive) is set, within the
* iteration,@range_begin will take the value 3 and @range_end will take
* the value 7.
*
* Ensure that there is at least one bit set before using this macro with
* sparsebit_any_set(), because sparsebit_first_set() will abort if none
* are set.
*/
#define sparsebit_for_each_set_range(s, range_begin, range_end) \
for (range_begin = sparsebit_first_set(s), \
range_end = sparsebit_next_clear(s, range_begin) - 1; \
range_begin && range_end; \
range_begin = sparsebit_next_set(s, range_end), \
range_end = sparsebit_next_clear(s, range_begin) - 1)
#ifdef __cplusplus
}
#endif
#endif /* SELFTEST_KVM_SPARSEBIT_H */
@@ -0,0 +1,243 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* tools/testing/selftests/kvm/include/test_util.h
*
* Copyright (C) 2018, Google LLC.
*/
#ifndef SELFTEST_KVM_TEST_UTIL_H
#define SELFTEST_KVM_TEST_UTIL_H
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "kselftest.h"
#include <linux/mman.h>
#include <linux/types.h>
#define msecs_to_usecs(msec) ((msec) * 1000ULL)
static inline __printf(1, 2) int _no_printf(const char *format, ...) { return 0; }
#ifdef DEBUG
#define pr_debug(...) printf(__VA_ARGS__)
#else
#define pr_debug(...) _no_printf(__VA_ARGS__)
#endif
#ifndef QUIET
#define pr_info(...) printf(__VA_ARGS__)
#else
#define pr_info(...) _no_printf(__VA_ARGS__)
#endif
void __printf(1, 2) print_skip(const char *fmt, ...);
#define __TEST_REQUIRE(f, fmt, ...) \
do { \
if (!(f)) \
ksft_exit_skip("- " fmt "\n", ##__VA_ARGS__); \
} while (0)
#define TEST_REQUIRE(f) __TEST_REQUIRE(f, "Requirement not met: %s", #f)
ssize_t test_write(int fd, const void *buf, size_t count);
ssize_t test_read(int fd, void *buf, size_t count);
int test_seq_read(const char *path, char **bufp, size_t *sizep);
void __printf(5, 6) test_assert(bool exp, const char *exp_str,
const char *file, unsigned int line,
const char *fmt, ...);
#define TEST_ASSERT(e, fmt, ...) \
test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define TEST_ASSERT_EQ(a, b) \
do { \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
test_assert(__a == __b, #a " == " #b, __FILE__, __LINE__, \
"%#lx != %#lx (%s != %s)", \
(unsigned long)(__a), (unsigned long)(__b), #a, #b);\
} while (0)
#define TEST_ASSERT_KVM_EXIT_REASON(vcpu, expected) do { \
__u32 exit_reason = (vcpu)->run->exit_reason; \
\
TEST_ASSERT(exit_reason == (expected), \
"Wanted KVM exit reason: %u (%s), got: %u (%s)", \
(expected), exit_reason_str((expected)), \
exit_reason, exit_reason_str(exit_reason)); \
} while (0)
#define TEST_FAIL(fmt, ...) do { \
TEST_ASSERT(false, fmt, ##__VA_ARGS__); \
__builtin_unreachable(); \
} while (0)
extern sigjmp_buf expect_sigbus_jmpbuf;
void expect_sigbus_handler(int signum);
#define TEST_EXPECT_SIGBUS(action) \
do { \
struct sigaction sa_old, sa_new = { \
.sa_handler = expect_sigbus_handler, \
}; \
\
sigaction(SIGBUS, &sa_new, &sa_old); \
if (sigsetjmp(expect_sigbus_jmpbuf, 1) == 0) { \
action; \
TEST_FAIL("'%s' should have triggered SIGBUS", #action); \
} \
sigaction(SIGBUS, &sa_old, NULL); \
} while (0)
size_t parse_size(const char *size);
s64 timespec_to_ns(struct timespec ts);
struct timespec timespec_add_ns(struct timespec ts, s64 ns);
struct timespec timespec_add(struct timespec ts1, struct timespec ts2);
struct timespec timespec_sub(struct timespec ts1, struct timespec ts2);
struct timespec timespec_elapsed(struct timespec start);
struct timespec timespec_div(struct timespec ts, int divisor);
struct guest_random_state {
u32 seed;
};
extern u32 guest_random_seed;
extern struct guest_random_state guest_rng;
struct guest_random_state new_guest_random_state(u32 seed);
u32 guest_random_u32(struct guest_random_state *state);
static inline bool __guest_random_bool(struct guest_random_state *state,
u8 percent)
{
return (guest_random_u32(state) % 100) < percent;
}
static inline bool guest_random_bool(struct guest_random_state *state)
{
return __guest_random_bool(state, 50);
}
static inline u64 guest_random_u64(struct guest_random_state *state)
{
return ((u64)guest_random_u32(state) << 32) | guest_random_u32(state);
}
enum vm_mem_backing_src_type {
VM_MEM_SRC_ANONYMOUS,
VM_MEM_SRC_ANONYMOUS_THP,
VM_MEM_SRC_ANONYMOUS_HUGETLB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_16KB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_64KB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_512KB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_1MB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_2MB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_8MB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_16MB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_32MB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_256MB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_512MB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_1GB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_2GB,
VM_MEM_SRC_ANONYMOUS_HUGETLB_16GB,
VM_MEM_SRC_SHMEM,
VM_MEM_SRC_SHARED_HUGETLB,
NUM_SRC_TYPES,
};
#define DEFAULT_VM_MEM_SRC VM_MEM_SRC_ANONYMOUS
struct vm_mem_backing_src_alias {
const char *name;
u32 flag;
};
#define MIN_RUN_DELAY_NS 200000UL
bool thp_configured(void);
size_t get_trans_hugepagesz(void);
size_t get_def_hugetlb_pagesz(void);
const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(u32 i);
size_t get_backing_src_pagesz(u32 i);
bool is_backing_src_hugetlb(u32 i);
void backing_src_help(const char *flag);
enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name);
long get_run_delay(void);
bool is_numa_balancing_enabled(void);
/*
* Whether or not the given source type is shared memory (as opposed to
* anonymous).
*/
static inline bool backing_src_is_shared(enum vm_mem_backing_src_type t)
{
return vm_mem_backing_src_alias(t)->flag & MAP_SHARED;
}
static inline bool backing_src_can_be_huge(enum vm_mem_backing_src_type t)
{
return t != VM_MEM_SRC_ANONYMOUS && t != VM_MEM_SRC_SHMEM;
}
/* Aligns x up to the next multiple of size. Size must be a power of 2. */
static inline u64 align_up(u64 x, u64 size)
{
u64 mask = size - 1;
TEST_ASSERT(size != 0 && !(size & (size - 1)),
"size not a power of 2: %lu", size);
return ((x + mask) & ~mask);
}
static inline u64 align_down(u64 x, u64 size)
{
u64 x_aligned_up = align_up(x, size);
if (x == x_aligned_up)
return x;
else
return x_aligned_up - size;
}
static inline void *align_ptr_up(void *x, size_t size)
{
return (void *)align_up((unsigned long)x, size);
}
int atoi_paranoid(const char *num_str);
static inline u32 atoi_positive(const char *name, const char *num_str)
{
int num = atoi_paranoid(num_str);
TEST_ASSERT(num > 0, "%s must be greater than 0, got '%s'", name, num_str);
return num;
}
static inline u32 atoi_non_negative(const char *name, const char *num_str)
{
int num = atoi_paranoid(num_str);
TEST_ASSERT(num >= 0, "%s must be non-negative, got '%s'", name, num_str);
return num;
}
int guest_vsnprintf(char *buf, int n, const char *fmt, va_list args);
__printf(3, 4) int guest_snprintf(char *buf, int n, const char *fmt, ...);
char *strdup_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2), nonnull(1)));
char *sys_get_cur_clocksource(void);
#endif /* SELFTEST_KVM_TEST_UTIL_H */
@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* timer test specific header
*
* Copyright (C) 2018, Google LLC
*/
#ifndef SELFTEST_KVM_TIMER_TEST_H
#define SELFTEST_KVM_TIMER_TEST_H
#include "kvm_util.h"
#define NR_VCPUS_DEF 4
#define NR_TEST_ITERS_DEF 5
#define TIMER_TEST_PERIOD_MS_DEF 10
#define TIMER_TEST_ERR_MARGIN_US 100
#define TIMER_TEST_MIGRATION_FREQ_MS 2
/* Timer test cmdline parameters */
struct test_args {
u32 nr_vcpus;
u32 nr_iter;
u32 timer_period_ms;
u32 migration_freq_ms;
u32 timer_err_margin_us;
/* Members of struct kvm_arm_counter_offset */
u64 counter_offset;
u64 reserved;
};
/* Shared variables between host and guest */
struct test_vcpu_shared_data {
u32 nr_iter;
int guest_stage;
u64 xcnt;
};
extern struct test_args test_args;
extern struct kvm_vcpu *vcpus[];
extern struct test_vcpu_shared_data vcpu_shared_data[];
struct kvm_vm *test_vm_create(void);
void test_vm_cleanup(struct kvm_vm *vm);
#endif /* SELFTEST_KVM_TIMER_TEST_H */
@@ -0,0 +1,116 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2018, Google LLC.
*/
#ifndef SELFTEST_KVM_UCALL_COMMON_H
#define SELFTEST_KVM_UCALL_COMMON_H
#include "test_util.h"
#include "ucall.h"
/* Common ucalls */
enum {
UCALL_NONE,
UCALL_SYNC,
UCALL_ABORT,
UCALL_PRINTF,
UCALL_DONE,
UCALL_UNHANDLED,
};
#define UCALL_MAX_ARGS 7
#define UCALL_BUFFER_LEN 1024
struct ucall {
u64 cmd;
u64 args[UCALL_MAX_ARGS];
char buffer[UCALL_BUFFER_LEN];
/* Host virtual address of this struct. */
struct ucall *hva;
};
void ucall_arch_init(struct kvm_vm *vm, gpa_t mmio_gpa);
void ucall_arch_do_ucall(gva_t uc);
void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu);
void ucall(u64 cmd, int nargs, ...);
__printf(2, 3) void ucall_fmt(u64 cmd, const char *fmt, ...);
__printf(5, 6) void ucall_assert(u64 cmd, const char *exp,
const char *file, unsigned int line,
const char *fmt, ...);
u64 get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc);
void ucall_init(struct kvm_vm *vm, gpa_t mmio_gpa);
int ucall_nr_pages_required(u64 page_size);
/*
* Perform userspace call without any associated data. This bare call avoids
* allocating a ucall struct, which can be useful if the atomic operations in
* the full ucall() are problematic and/or unwanted. Note, this will come out
* as UCALL_NONE on the backend.
*/
#define GUEST_UCALL_NONE() ucall_arch_do_ucall((gva_t)NULL)
#define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \
ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4)
#define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage)
#define GUEST_SYNC1(arg0) ucall(UCALL_SYNC, 1, arg0)
#define GUEST_SYNC2(arg0, arg1) ucall(UCALL_SYNC, 2, arg0, arg1)
#define GUEST_SYNC3(arg0, arg1, arg2) \
ucall(UCALL_SYNC, 3, arg0, arg1, arg2)
#define GUEST_SYNC4(arg0, arg1, arg2, arg3) \
ucall(UCALL_SYNC, 4, arg0, arg1, arg2, arg3)
#define GUEST_SYNC5(arg0, arg1, arg2, arg3, arg4) \
ucall(UCALL_SYNC, 5, arg0, arg1, arg2, arg3, arg4)
#define GUEST_SYNC6(arg0, arg1, arg2, arg3, arg4, arg5) \
ucall(UCALL_SYNC, 6, arg0, arg1, arg2, arg3, arg4, arg5)
#define GUEST_PRINTF(_fmt, _args...) ucall_fmt(UCALL_PRINTF, _fmt, ##_args)
#define GUEST_DONE() ucall(UCALL_DONE, 0)
#define REPORT_GUEST_PRINTF(ucall) pr_info("%s", (ucall).buffer)
enum guest_assert_builtin_args {
GUEST_ERROR_STRING,
GUEST_FILE,
GUEST_LINE,
GUEST_ASSERT_BUILTIN_NARGS
};
#define ____GUEST_ASSERT(_condition, _exp, _fmt, _args...) \
do { \
if (!(_condition)) \
ucall_assert(UCALL_ABORT, _exp, __FILE__, __LINE__, _fmt, ##_args); \
} while (0)
#define __GUEST_ASSERT(_condition, _fmt, _args...) \
____GUEST_ASSERT(_condition, #_condition, _fmt, ##_args)
#define GUEST_ASSERT(_condition) \
__GUEST_ASSERT(_condition, #_condition)
#define GUEST_FAIL(_fmt, _args...) \
ucall_assert(UCALL_ABORT, "Unconditional guest failure", \
__FILE__, __LINE__, _fmt, ##_args)
#define GUEST_ASSERT_EQ(a, b) \
do { \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
____GUEST_ASSERT(__a == __b, #a " == " #b, "%#lx != %#lx (%s != %s)", \
(unsigned long)(__a), (unsigned long)(__b), #a, #b); \
} while (0)
#define GUEST_ASSERT_NE(a, b) \
do { \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
____GUEST_ASSERT(__a != __b, #a " != " #b, "%#lx == %#lx (%s == %s)", \
(unsigned long)(__a), (unsigned long)(__b), #a, #b); \
} while (0)
#define REPORT_GUEST_ASSERT(ucall) \
test_assert(false, (const char *)(ucall).args[GUEST_ERROR_STRING], \
(const char *)(ucall).args[GUEST_FILE], \
(ucall).args[GUEST_LINE], "%s", (ucall).buffer)
#endif /* SELFTEST_KVM_UCALL_COMMON_H */
@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* KVM userfaultfd util
*
* Copyright (C) 2018, Red Hat, Inc.
* Copyright (C) 2019-2022 Google LLC
*/
#include <inttypes.h>
#include <time.h>
#include <pthread.h>
#include <linux/userfaultfd.h>
#include "test_util.h"
typedef int (*uffd_handler_t)(int uffd_mode, int uffd, struct uffd_msg *msg);
struct uffd_reader_args {
int uffd_mode;
int uffd;
useconds_t delay;
uffd_handler_t handler;
/* Holds the read end of the pipe for killing the reader. */
int pipe;
};
struct uffd_desc {
int uffd;
u64 num_readers;
/* Holds the write ends of the pipes for killing the readers. */
int *pipefds;
pthread_t *readers;
struct uffd_reader_args *reader_args;
};
struct uffd_desc *uffd_setup_demand_paging(int uffd_mode, useconds_t delay,
void *hva, u64 len,
u64 num_readers,
uffd_handler_t handler);
void uffd_stop_demand_paging(struct uffd_desc *uffd);
#ifdef PRINT_PER_PAGE_UPDATES
#define PER_PAGE_DEBUG(...) printf(__VA_ARGS__)
#else
#define PER_PAGE_DEBUG(...) _no_printf(__VA_ARGS__)
#endif
#ifdef PRINT_PER_VCPU_UPDATES
#define PER_VCPU_DEBUG(...) printf(__VA_ARGS__)
#else
#define PER_VCPU_DEBUG(...) _no_printf(__VA_ARGS__)
#endif
@@ -0,0 +1,125 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2021, Google LLC.
*/
#ifndef SELFTEST_KVM_APIC_H
#define SELFTEST_KVM_APIC_H
#include <stdint.h>
#include "processor.h"
#include "ucall_common.h"
#define APIC_DEFAULT_GPA 0xfee00000ULL
/* APIC base address MSR and fields */
#define MSR_IA32_APICBASE 0x0000001b
#define MSR_IA32_APICBASE_BSP (1<<8)
#define MSR_IA32_APICBASE_EXTD (1<<10)
#define MSR_IA32_APICBASE_ENABLE (1<<11)
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
#define GET_APIC_BASE(x) (((x) >> 12) << 12)
#define APIC_BASE_MSR 0x800
#define X2APIC_ENABLE (1UL << 10)
#define APIC_ID 0x20
#define APIC_LVR 0x30
#define GET_APIC_ID_FIELD(x) (((x) >> 24) & 0xFF)
#define APIC_TASKPRI 0x80
#define APIC_PROCPRI 0xA0
#define GET_APIC_PRI(x) (((x) & GENMASK(7, 4)) >> 4)
#define SET_APIC_PRI(x, y) (((x) & ~GENMASK(7, 4)) | (y << 4))
#define APIC_EOI 0xB0
#define APIC_SPIV 0xF0
#define APIC_SPIV_FOCUS_DISABLED (1 << 9)
#define APIC_SPIV_APIC_ENABLED (1 << 8)
#define APIC_ISR 0x100
#define APIC_IRR 0x200
#define APIC_ICR 0x300
#define APIC_LVTCMCI 0x2f0
#define APIC_DEST_SELF 0x40000
#define APIC_DEST_ALLINC 0x80000
#define APIC_DEST_ALLBUT 0xC0000
#define APIC_ICR_RR_MASK 0x30000
#define APIC_ICR_RR_INVALID 0x00000
#define APIC_ICR_RR_INPROG 0x10000
#define APIC_ICR_RR_VALID 0x20000
#define APIC_INT_LEVELTRIG 0x08000
#define APIC_INT_ASSERT 0x04000
#define APIC_ICR_BUSY 0x01000
#define APIC_DEST_LOGICAL 0x00800
#define APIC_DEST_PHYSICAL 0x00000
#define APIC_DM_FIXED 0x00000
#define APIC_DM_FIXED_MASK 0x00700
#define APIC_DM_LOWEST 0x00100
#define APIC_DM_SMI 0x00200
#define APIC_DM_REMRD 0x00300
#define APIC_DM_NMI 0x00400
#define APIC_DM_INIT 0x00500
#define APIC_DM_STARTUP 0x00600
#define APIC_DM_EXTINT 0x00700
#define APIC_VECTOR_MASK 0x000FF
#define APIC_ICR2 0x310
#define SET_APIC_DEST_FIELD(x) ((x) << 24)
#define APIC_LVTT 0x320
#define APIC_LVT_TIMER_ONESHOT (0 << 17)
#define APIC_LVT_TIMER_PERIODIC (1 << 17)
#define APIC_LVT_TIMER_TSCDEADLINE (2 << 17)
#define APIC_LVT_MASKED (1 << 16)
#define APIC_TMICT 0x380
#define APIC_TMCCT 0x390
#define APIC_TDCR 0x3E0
#define APIC_SELF_IPI 0x3F0
#define APIC_VECTOR_TO_BIT_NUMBER(v) ((unsigned int)(v) % 32)
#define APIC_VECTOR_TO_REG_OFFSET(v) ((unsigned int)(v) / 32 * 0x10)
void apic_disable(void);
void xapic_enable(void);
void x2apic_enable(void);
static inline u32 get_bsp_flag(void)
{
return rdmsr(MSR_IA32_APICBASE) & MSR_IA32_APICBASE_BSP;
}
static inline u32 xapic_read_reg(unsigned int reg)
{
return ((volatile u32 *)APIC_DEFAULT_GPA)[reg >> 2];
}
static inline void xapic_write_reg(unsigned int reg, u32 val)
{
((volatile u32 *)APIC_DEFAULT_GPA)[reg >> 2] = val;
}
static inline u64 x2apic_read_reg(unsigned int reg)
{
return rdmsr(APIC_BASE_MSR + (reg >> 4));
}
static inline u8 x2apic_write_reg_safe(unsigned int reg, u64 value)
{
return wrmsr_safe(APIC_BASE_MSR + (reg >> 4), value);
}
static inline void x2apic_write_reg(unsigned int reg, u64 value)
{
u8 fault = x2apic_write_reg_safe(reg, value);
__GUEST_ASSERT(!fault, "Unexpected fault 0x%x on WRMSR(%x) = %lx\n",
fault, APIC_BASE_MSR + (reg >> 4), value);
}
static inline void x2apic_write_reg_fault(unsigned int reg, u64 value)
{
u8 fault = x2apic_write_reg_safe(reg, value);
__GUEST_ASSERT(fault == GP_VECTOR,
"Wanted #GP on WRMSR(%x) = %lx, got 0x%x\n",
APIC_BASE_MSR + (reg >> 4), value, fault);
}
#endif /* SELFTEST_KVM_APIC_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,361 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021, Red Hat, Inc.
*/
#ifndef SELFTEST_KVM_HYPERV_H
#define SELFTEST_KVM_HYPERV_H
#include "processor.h"
#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS 0x40000000
#define HYPERV_CPUID_INTERFACE 0x40000001
#define HYPERV_CPUID_VERSION 0x40000002
#define HYPERV_CPUID_FEATURES 0x40000003
#define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004
#define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005
#define HYPERV_CPUID_CPU_MANAGEMENT_FEATURES 0x40000007
#define HYPERV_CPUID_NESTED_FEATURES 0x4000000A
#define HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS 0x40000080
#define HYPERV_CPUID_SYNDBG_INTERFACE 0x40000081
#define HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x40000082
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
#define HV_X64_MSR_HYPERCALL 0x40000001
#define HV_X64_MSR_VP_INDEX 0x40000002
#define HV_X64_MSR_RESET 0x40000003
#define HV_X64_MSR_VP_RUNTIME 0x40000010
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
#define HV_X64_MSR_TSC_FREQUENCY 0x40000022
#define HV_X64_MSR_APIC_FREQUENCY 0x40000023
#define HV_X64_MSR_EOI 0x40000070
#define HV_X64_MSR_ICR 0x40000071
#define HV_X64_MSR_TPR 0x40000072
#define HV_X64_MSR_VP_ASSIST_PAGE 0x40000073
#define HV_X64_MSR_SCONTROL 0x40000080
#define HV_X64_MSR_SVERSION 0x40000081
#define HV_X64_MSR_SIEFP 0x40000082
#define HV_X64_MSR_SIMP 0x40000083
#define HV_X64_MSR_EOM 0x40000084
#define HV_X64_MSR_SINT0 0x40000090
#define HV_X64_MSR_SINT1 0x40000091
#define HV_X64_MSR_SINT2 0x40000092
#define HV_X64_MSR_SINT3 0x40000093
#define HV_X64_MSR_SINT4 0x40000094
#define HV_X64_MSR_SINT5 0x40000095
#define HV_X64_MSR_SINT6 0x40000096
#define HV_X64_MSR_SINT7 0x40000097
#define HV_X64_MSR_SINT8 0x40000098
#define HV_X64_MSR_SINT9 0x40000099
#define HV_X64_MSR_SINT10 0x4000009A
#define HV_X64_MSR_SINT11 0x4000009B
#define HV_X64_MSR_SINT12 0x4000009C
#define HV_X64_MSR_SINT13 0x4000009D
#define HV_X64_MSR_SINT14 0x4000009E
#define HV_X64_MSR_SINT15 0x4000009F
#define HV_X64_MSR_STIMER0_CONFIG 0x400000B0
#define HV_X64_MSR_STIMER0_COUNT 0x400000B1
#define HV_X64_MSR_STIMER1_CONFIG 0x400000B2
#define HV_X64_MSR_STIMER1_COUNT 0x400000B3
#define HV_X64_MSR_STIMER2_CONFIG 0x400000B4
#define HV_X64_MSR_STIMER2_COUNT 0x400000B5
#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6
#define HV_X64_MSR_STIMER3_COUNT 0x400000B7
#define HV_X64_MSR_GUEST_IDLE 0x400000F0
#define HV_X64_MSR_CRASH_P0 0x40000100
#define HV_X64_MSR_CRASH_P1 0x40000101
#define HV_X64_MSR_CRASH_P2 0x40000102
#define HV_X64_MSR_CRASH_P3 0x40000103
#define HV_X64_MSR_CRASH_P4 0x40000104
#define HV_X64_MSR_CRASH_CTL 0x40000105
#define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106
#define HV_X64_MSR_TSC_EMULATION_CONTROL 0x40000107
#define HV_X64_MSR_TSC_EMULATION_STATUS 0x40000108
#define HV_X64_MSR_TSC_INVARIANT_CONTROL 0x40000118
#define HV_X64_MSR_SYNDBG_CONTROL 0x400000F1
#define HV_X64_MSR_SYNDBG_STATUS 0x400000F2
#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x400000F3
#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x400000F4
#define HV_X64_MSR_SYNDBG_PENDING_BUFFER 0x400000F5
#define HV_X64_MSR_SYNDBG_OPTIONS 0x400000FF
/* HYPERV_CPUID_FEATURES.EAX */
#define HV_MSR_VP_RUNTIME_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 0)
#define HV_MSR_TIME_REF_COUNT_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 1)
#define HV_MSR_SYNIC_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 2)
#define HV_MSR_SYNTIMER_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 3)
#define HV_MSR_APIC_ACCESS_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 4)
#define HV_MSR_HYPERCALL_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 5)
#define HV_MSR_VP_INDEX_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 6)
#define HV_MSR_RESET_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 7)
#define HV_MSR_STAT_PAGES_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 8)
#define HV_MSR_REFERENCE_TSC_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 9)
#define HV_MSR_GUEST_IDLE_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 10)
#define HV_ACCESS_FREQUENCY_MSRS \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 11)
#define HV_ACCESS_REENLIGHTENMENT \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 13)
#define HV_ACCESS_TSC_INVARIANT \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EAX, 15)
/* HYPERV_CPUID_FEATURES.EBX */
#define HV_CREATE_PARTITIONS \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 0)
#define HV_ACCESS_PARTITION_ID \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 1)
#define HV_ACCESS_MEMORY_POOL \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 2)
#define HV_ADJUST_MESSAGE_BUFFERS \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 3)
#define HV_POST_MESSAGES \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 4)
#define HV_SIGNAL_EVENTS \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 5)
#define HV_CREATE_PORT \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 6)
#define HV_CONNECT_PORT \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 7)
#define HV_ACCESS_STATS \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 8)
#define HV_DEBUGGING \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 11)
#define HV_CPU_MANAGEMENT \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 12)
#define HV_ENABLE_EXTENDED_HYPERCALLS \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 20)
#define HV_ISOLATION \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EBX, 22)
/* HYPERV_CPUID_FEATURES.EDX */
#define HV_X64_MWAIT_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 0)
#define HV_X64_GUEST_DEBUGGING_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 1)
#define HV_X64_PERF_MONITOR_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 2)
#define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 3)
#define HV_X64_HYPERCALL_XMM_INPUT_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 4)
#define HV_X64_GUEST_IDLE_STATE_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 5)
#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 8)
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 10)
#define HV_FEATURE_DEBUG_MSRS_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 11)
#define HV_STIMER_DIRECT_MODE_AVAILABLE \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_FEATURES, 0, EDX, 19)
/* HYPERV_CPUID_ENLIGHTMENT_INFO.EAX */
#define HV_X64_AS_SWITCH_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 0)
#define HV_X64_LOCAL_TLB_FLUSH_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 1)
#define HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 2)
#define HV_X64_APIC_ACCESS_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 3)
#define HV_X64_SYSTEM_RESET_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 4)
#define HV_X64_RELAXED_TIMING_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 5)
#define HV_DEPRECATING_AEOI_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 9)
#define HV_X64_CLUSTER_IPI_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 10)
#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 11)
#define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_ENLIGHTMENT_INFO, 0, EAX, 14)
/* HYPERV_CPUID_NESTED_FEATURES.EAX */
#define HV_X64_NESTED_DIRECT_FLUSH \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EAX, 17)
#define HV_X64_NESTED_GUEST_MAPPING_FLUSH \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EAX, 18)
#define HV_X64_NESTED_MSR_BITMAP \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EAX, 19)
/* HYPERV_CPUID_NESTED_FEATURES.EBX */
#define HV_X64_NESTED_EVMCS1_PERF_GLOBAL_CTRL \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_NESTED_FEATURES, 0, EBX, 0)
/* HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX */
#define HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING \
KVM_X86_CPU_FEATURE(HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES, 0, EAX, 1)
/* Hypercalls */
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003
#define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008
#define HVCALL_SEND_IPI 0x000b
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
#define HVCALL_SEND_IPI_EX 0x0015
#define HVCALL_GET_PARTITION_ID 0x0046
#define HVCALL_DEPOSIT_MEMORY 0x0048
#define HVCALL_CREATE_VP 0x004e
#define HVCALL_GET_VP_REGISTERS 0x0050
#define HVCALL_SET_VP_REGISTERS 0x0051
#define HVCALL_POST_MESSAGE 0x005c
#define HVCALL_SIGNAL_EVENT 0x005d
#define HVCALL_POST_DEBUG_DATA 0x0069
#define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
#define HVCALL_RESET_DEBUG_SESSION 0x006b
#define HVCALL_ADD_LOGICAL_PROCESSOR 0x0076
#define HVCALL_MAP_DEVICE_INTERRUPT 0x007c
#define HVCALL_UNMAP_DEVICE_INTERRUPT 0x007d
#define HVCALL_RETARGET_INTERRUPT 0x007e
#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
/* Extended hypercalls */
#define HV_EXT_CALL_QUERY_CAPABILITIES 0x8001
#define HV_FLUSH_ALL_PROCESSORS BIT(0)
#define HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES BIT(1)
#define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2)
#define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3)
/* hypercall status code */
#define HV_STATUS_SUCCESS 0
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
#define HV_STATUS_INVALID_ALIGNMENT 4
#define HV_STATUS_INVALID_PARAMETER 5
#define HV_STATUS_ACCESS_DENIED 6
#define HV_STATUS_OPERATION_DENIED 8
#define HV_STATUS_INSUFFICIENT_MEMORY 11
#define HV_STATUS_INVALID_PORT_ID 17
#define HV_STATUS_INVALID_CONNECTION_ID 18
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
/* hypercall options */
#define HV_HYPERCALL_FAST_BIT BIT(16)
#define HV_HYPERCALL_VARHEAD_OFFSET 17
#define HV_HYPERCALL_REP_COMP_OFFSET 32
/*
* Issue a Hyper-V hypercall. Returns exception vector raised or 0, 'hv_status'
* is set to the hypercall status (if no exception occurred).
*/
static inline u8 __hyperv_hypercall(u64 control, gva_t input_address,
gva_t output_address,
u64 *hv_status)
{
u64 error_code;
u8 vector;
/* Note both the hypercall and the "asm safe" clobber r9-r11. */
asm volatile("mov %[output_address], %%r8\n\t"
KVM_ASM_SAFE("vmcall")
: "=a" (*hv_status),
"+c" (control), "+d" (input_address),
KVM_ASM_SAFE_OUTPUTS(vector, error_code)
: [output_address] "r"(output_address),
"a" (-EFAULT)
: "cc", "memory", "r8", KVM_ASM_SAFE_CLOBBERS);
return vector;
}
/* Issue a Hyper-V hypercall and assert that it succeeded. */
static inline void hyperv_hypercall(u64 control, gva_t input_address,
gva_t output_address)
{
u64 hv_status;
u8 vector;
vector = __hyperv_hypercall(control, input_address, output_address, &hv_status);
GUEST_ASSERT(!vector);
GUEST_ASSERT((hv_status & 0xffff) == 0);
}
/* Write 'Fast' hypercall input 'data' to the first 'n_sse_regs' SSE regs */
static inline void hyperv_write_xmm_input(void *data, int n_sse_regs)
{
int i;
for (i = 0; i < n_sse_regs; i++)
write_sse_reg(i, (sse128_t *)(data + sizeof(sse128_t) * i));
}
/* Proper HV_X64_MSR_GUEST_OS_ID value */
#define HYPERV_LINUX_OS_ID ((u64)0x8100 << 48)
#define HV_X64_MSR_VP_ASSIST_PAGE 0x40000073
#define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE 0x00000001
#define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT 12
#define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_MASK \
(~((1ull << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
struct hv_nested_enlightenments_control {
struct {
__u32 directhypercall:1;
__u32 reserved:31;
} features;
struct {
__u32 reserved;
} hypercallControls;
} __packed;
/* Define virtual processor assist page structure. */
struct hv_vp_assist_page {
__u32 apic_assist;
__u32 reserved1;
__u64 vtl_control[3];
struct hv_nested_enlightenments_control nested_control;
__u8 enlighten_vmentry;
__u8 reserved2[7];
__u64 current_nested_vmcs;
} __packed;
extern struct hv_vp_assist_page *current_vp_assist;
int enable_vp_assist(u64 vp_assist_pa, void *vp_assist);
struct hyperv_test_pages {
/* VP assist page */
void *vp_assist_hva;
u64 vp_assist_gpa;
void *vp_assist;
/* Partition assist page */
void *partition_assist_hva;
u64 partition_assist_gpa;
void *partition_assist;
/* Enlightened VMCS */
void *enlightened_vmcs_hva;
u64 enlightened_vmcs_gpa;
void *enlightened_vmcs;
};
struct hyperv_test_pages *vcpu_alloc_hyperv_test_pages(struct kvm_vm *vm,
gva_t *p_hv_pages_gva);
/* HV_X64_MSR_TSC_INVARIANT_CONTROL bits */
#define HV_INVARIANT_TSC_EXPOSED BIT_ULL(0)
const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void);
const struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vcpu *vcpu);
void vcpu_set_hv_cpuid(struct kvm_vcpu *vcpu);
bool kvm_hv_cpu_has(struct kvm_x86_cpu_feature feature);
#endif /* !SELFTEST_KVM_HYPERV_H */
@@ -0,0 +1,73 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UTIL_ARCH_H
#define SELFTEST_KVM_UTIL_ARCH_H
#include <stdbool.h>
#include <stdint.h>
#include "kvm_util_types.h"
#include "test_util.h"
extern bool is_forced_emulation_enabled;
struct pte_masks {
u64 present;
u64 writable;
u64 user;
u64 readable;
u64 executable;
u64 accessed;
u64 dirty;
u64 huge;
u64 nx;
u64 c;
u64 s;
u64 always_set;
};
struct kvm_mmu_arch {
struct pte_masks pte_masks;
};
struct kvm_mmu;
struct kvm_vm_arch {
gva_t gdt;
gva_t tss;
gva_t idt;
u64 c_bit;
u64 s_bit;
int sev_fd;
bool is_pt_protected;
};
static inline bool __vm_arch_has_protected_memory(struct kvm_vm_arch *arch)
{
return arch->c_bit || arch->s_bit;
}
#define vm_arch_has_protected_memory(vm) \
__vm_arch_has_protected_memory(&(vm)->arch)
#define vcpu_arch_put_guest(mem, __val) \
do { \
const typeof(mem) val = (__val); \
\
if (!is_forced_emulation_enabled || guest_random_bool(&guest_rng)) { \
(mem) = val; \
} else if (guest_random_bool(&guest_rng)) { \
__asm__ __volatile__(KVM_FEP "mov %1, %0" \
: "+m" (mem) \
: "r" (val) : "memory"); \
} else { \
u64 __old = READ_ONCE(mem); \
\
__asm__ __volatile__(KVM_FEP LOCK_PREFIX "cmpxchg %[new], %[ptr]" \
: [ptr] "+m" (mem), [old] "+a" (__old) \
: [new]"r" (val) : "memory", "cc"); \
} \
} while (0)
#endif // SELFTEST_KVM_UTIL_ARCH_H
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2022, Google LLC.
*/
#ifndef SELFTEST_KVM_MCE_H
#define SELFTEST_KVM_MCE_H
#define MCG_CTL_P BIT_ULL(8) /* MCG_CTL register available */
#define MCG_SER_P BIT_ULL(24) /* MCA recovery/new status bits */
#define MCG_LMCE_P BIT_ULL(27) /* Local machine check supported */
#define MCG_CMCI_P BIT_ULL(10) /* CMCI supported */
#define KVM_MAX_MCE_BANKS 32
#define MCG_CAP_BANKS_MASK 0xff /* Bit 0-7 of the MCG_CAP register are #banks */
#define MCI_STATUS_VAL (1ULL << 63) /* valid error */
#define MCI_STATUS_UC (1ULL << 61) /* uncorrected error */
#define MCI_STATUS_EN (1ULL << 60) /* error enabled */
#define MCI_STATUS_MISCV (1ULL << 59) /* misc error reg. valid */
#define MCI_STATUS_ADDRV (1ULL << 58) /* addr reg. valid */
#define MCM_ADDR_PHYS 2 /* physical address */
#define MCI_CTL2_CMCI_EN BIT_ULL(30)
#endif /* SELFTEST_KVM_MCE_H */
@@ -0,0 +1,124 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2023, Tencent, Inc.
*/
#ifndef SELFTEST_KVM_PMU_H
#define SELFTEST_KVM_PMU_H
#include <stdbool.h>
#include <linux/types.h>
#include <linux/bits.h>
#define KVM_PMU_EVENT_FILTER_MAX_EVENTS 300
/*
* Encode an eventsel+umask pair into event-select MSR format. Note, this is
* technically AMD's format, as Intel's format only supports 8 bits for the
* event selector, i.e. doesn't use bits 24:16 for the selector. But, OR-ing
* in '0' is a nop and won't clobber the CMASK.
*/
#define RAW_EVENT(eventsel, umask) (((eventsel & 0xf00UL) << 24) | \
((eventsel) & 0xff) | \
((umask) & 0xff) << 8)
/*
* These are technically Intel's definitions, but except for CMASK (see above),
* AMD's layout is compatible with Intel's.
*/
#define ARCH_PERFMON_EVENTSEL_EVENT GENMASK_ULL(7, 0)
#define ARCH_PERFMON_EVENTSEL_UMASK GENMASK_ULL(15, 8)
#define ARCH_PERFMON_EVENTSEL_USR BIT_ULL(16)
#define ARCH_PERFMON_EVENTSEL_OS BIT_ULL(17)
#define ARCH_PERFMON_EVENTSEL_EDGE BIT_ULL(18)
#define ARCH_PERFMON_EVENTSEL_PIN_CONTROL BIT_ULL(19)
#define ARCH_PERFMON_EVENTSEL_INT BIT_ULL(20)
#define ARCH_PERFMON_EVENTSEL_ANY BIT_ULL(21)
#define ARCH_PERFMON_EVENTSEL_ENABLE BIT_ULL(22)
#define ARCH_PERFMON_EVENTSEL_INV BIT_ULL(23)
#define ARCH_PERFMON_EVENTSEL_CMASK GENMASK_ULL(31, 24)
/* RDPMC control flags, Intel only. */
#define INTEL_RDPMC_METRICS BIT_ULL(29)
#define INTEL_RDPMC_FIXED BIT_ULL(30)
#define INTEL_RDPMC_FAST BIT_ULL(31)
/* Fixed PMC controls, Intel only. */
#define FIXED_PMC_GLOBAL_CTRL_ENABLE(_idx) BIT_ULL((32 + (_idx)))
#define FIXED_PMC_KERNEL BIT_ULL(0)
#define FIXED_PMC_USER BIT_ULL(1)
#define FIXED_PMC_ANYTHREAD BIT_ULL(2)
#define FIXED_PMC_ENABLE_PMI BIT_ULL(3)
#define FIXED_PMC_NR_BITS 4
#define FIXED_PMC_CTRL(_idx, _val) ((_val) << ((_idx) * FIXED_PMC_NR_BITS))
#define PMU_CAP_FW_WRITES BIT_ULL(13)
#define PMU_CAP_LBR_FMT 0x3f
#define INTEL_ARCH_CPU_CYCLES RAW_EVENT(0x3c, 0x00)
#define INTEL_ARCH_INSTRUCTIONS_RETIRED RAW_EVENT(0xc0, 0x00)
#define INTEL_ARCH_REFERENCE_CYCLES RAW_EVENT(0x3c, 0x01)
#define INTEL_ARCH_LLC_REFERENCES RAW_EVENT(0x2e, 0x4f)
#define INTEL_ARCH_LLC_MISSES RAW_EVENT(0x2e, 0x41)
#define INTEL_ARCH_BRANCHES_RETIRED RAW_EVENT(0xc4, 0x00)
#define INTEL_ARCH_BRANCHES_MISPREDICTED RAW_EVENT(0xc5, 0x00)
#define INTEL_ARCH_TOPDOWN_SLOTS RAW_EVENT(0xa4, 0x01)
#define INTEL_ARCH_TOPDOWN_BE_BOUND RAW_EVENT(0xa4, 0x02)
#define INTEL_ARCH_TOPDOWN_BAD_SPEC RAW_EVENT(0x73, 0x00)
#define INTEL_ARCH_TOPDOWN_FE_BOUND RAW_EVENT(0x9c, 0x01)
#define INTEL_ARCH_TOPDOWN_RETIRING RAW_EVENT(0xc2, 0x02)
#define INTEL_ARCH_LBR_INSERTS RAW_EVENT(0xe4, 0x01)
#define AMD_ZEN_CORE_CYCLES RAW_EVENT(0x76, 0x00)
#define AMD_ZEN_INSTRUCTIONS_RETIRED RAW_EVENT(0xc0, 0x00)
#define AMD_ZEN_BRANCHES_RETIRED RAW_EVENT(0xc2, 0x00)
#define AMD_ZEN_BRANCHES_MISPREDICTED RAW_EVENT(0xc3, 0x00)
/*
* Note! The order and thus the index of the architectural events matters as
* support for each event is enumerated via CPUID using the index of the event.
*/
enum intel_pmu_architectural_events {
INTEL_ARCH_CPU_CYCLES_INDEX,
INTEL_ARCH_INSTRUCTIONS_RETIRED_INDEX,
INTEL_ARCH_REFERENCE_CYCLES_INDEX,
INTEL_ARCH_LLC_REFERENCES_INDEX,
INTEL_ARCH_LLC_MISSES_INDEX,
INTEL_ARCH_BRANCHES_RETIRED_INDEX,
INTEL_ARCH_BRANCHES_MISPREDICTED_INDEX,
INTEL_ARCH_TOPDOWN_SLOTS_INDEX,
INTEL_ARCH_TOPDOWN_BE_BOUND_INDEX,
INTEL_ARCH_TOPDOWN_BAD_SPEC_INDEX,
INTEL_ARCH_TOPDOWN_FE_BOUND_INDEX,
INTEL_ARCH_TOPDOWN_RETIRING_INDEX,
INTEL_ARCH_LBR_INSERTS_INDEX,
NR_INTEL_ARCH_EVENTS,
};
enum amd_pmu_zen_events {
AMD_ZEN_CORE_CYCLES_INDEX,
AMD_ZEN_INSTRUCTIONS_INDEX,
AMD_ZEN_BRANCHES_INDEX,
AMD_ZEN_BRANCH_MISSES_INDEX,
NR_AMD_ZEN_EVENTS,
};
extern const u64 intel_pmu_arch_events[];
extern const u64 amd_pmu_zen_events[];
enum pmu_errata {
INSTRUCTIONS_RETIRED_OVERCOUNT,
BRANCHES_RETIRED_OVERCOUNT,
};
extern u64 pmu_errata_mask;
void kvm_init_pmu_errata(void);
static inline bool this_pmu_has_errata(enum pmu_errata errata)
{
return pmu_errata_mask & BIT_ULL(errata);
}
#endif /* SELFTEST_KVM_PMU_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,171 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Helpers used for SEV guests
*
*/
#ifndef SELFTEST_KVM_SEV_H
#define SELFTEST_KVM_SEV_H
#include <stdint.h>
#include <stdbool.h>
#include "linux/psp-sev.h"
#include "kvm_util.h"
#include "svm_util.h"
#include "processor.h"
enum sev_guest_state {
SEV_GUEST_STATE_UNINITIALIZED = 0,
SEV_GUEST_STATE_LAUNCH_UPDATE,
SEV_GUEST_STATE_LAUNCH_SECRET,
SEV_GUEST_STATE_RUNNING,
};
#define SEV_POLICY_NO_DBG (1UL << 0)
#define SEV_POLICY_ES (1UL << 2)
#define SNP_POLICY_SMT (1ULL << 16)
#define SNP_POLICY_RSVD_MBO (1ULL << 17)
#define SNP_POLICY_DBG (1ULL << 19)
#define GHCB_MSR_TERM_REQ 0x100
static inline bool is_sev_snp_vm(struct kvm_vm *vm)
{
return vm->type == KVM_X86_SNP_VM;
}
static inline bool is_sev_es_vm(struct kvm_vm *vm)
{
return is_sev_snp_vm(vm) || vm->type == KVM_X86_SEV_ES_VM;
}
static inline bool is_sev_vm(struct kvm_vm *vm)
{
return is_sev_es_vm(vm) || vm->type == KVM_X86_SEV_VM;
}
void sev_vm_launch(struct kvm_vm *vm, u32 policy);
void sev_vm_launch_measure(struct kvm_vm *vm, u8 *measurement);
void sev_vm_launch_finish(struct kvm_vm *vm);
void snp_vm_launch_start(struct kvm_vm *vm, u64 policy);
void snp_vm_launch_update(struct kvm_vm *vm);
void snp_vm_launch_finish(struct kvm_vm *vm);
struct kvm_vm *vm_sev_create_with_one_vcpu(u32 type, void *guest_code,
struct kvm_vcpu **cpu);
void vm_sev_launch(struct kvm_vm *vm, u64 policy, u8 *measurement);
kvm_static_assert(SEV_RET_SUCCESS == 0);
/*
* A SEV-SNP VM requires the policy reserved bit to always be set.
* The SMT policy bit is also required to be set based on SMT being
* available and active on the system.
*/
static inline u64 snp_default_policy(void)
{
return SNP_POLICY_RSVD_MBO | (is_smt_on() ? SNP_POLICY_SMT : 0);
}
/*
* The KVM_MEMORY_ENCRYPT_OP uAPI is utter garbage and takes an "unsigned long"
* instead of a proper struct. The size of the parameter is embedded in the
* ioctl number, i.e. is ABI and thus immutable. Hack around the mess by
* creating an overlay to pass in an "unsigned long" without a cast (casting
* will make the compiler unhappy due to dereferencing an aliased pointer).
*/
#define __vm_sev_ioctl(vm, cmd, arg) \
({ \
int r; \
\
union { \
struct kvm_sev_cmd c; \
unsigned long raw; \
} sev_cmd = { .c = { \
.id = (cmd), \
.data = (u64)(arg), \
.sev_fd = (vm)->arch.sev_fd, \
} }; \
\
r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &sev_cmd.raw); \
r ?: sev_cmd.c.error; \
})
#define vm_sev_ioctl(vm, cmd, arg) \
({ \
int ret = __vm_sev_ioctl(vm, cmd, arg); \
\
__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \
})
void sev_vm_init(struct kvm_vm *vm);
void sev_es_vm_init(struct kvm_vm *vm);
void snp_vm_init(struct kvm_vm *vm);
static inline void vmgexit(void)
{
__asm__ __volatile__("rep; vmmcall");
}
static inline void sev_register_encrypted_memory(struct kvm_vm *vm,
struct userspace_mem_region *region)
{
struct kvm_enc_region range = {
.addr = region->region.userspace_addr,
.size = region->region.memory_size,
};
vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
}
static inline void sev_launch_update_data(struct kvm_vm *vm, gpa_t gpa,
u64 size)
{
struct kvm_sev_launch_update_data update_data = {
.uaddr = (unsigned long)addr_gpa2hva(vm, gpa),
.len = size,
};
vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data);
}
static inline void snp_launch_update_data(struct kvm_vm *vm, gpa_t gpa,
u64 hva, u64 size, u8 type)
{
struct kvm_sev_snp_launch_update update_data = {
.uaddr = hva,
.gfn_start = gpa >> PAGE_SHIFT,
.len = size,
.type = type,
};
vm_sev_ioctl(vm, KVM_SEV_SNP_LAUNCH_UPDATE, &update_data);
}
static inline void sev_dbg_crypt_memory(struct kvm_vm *vm, unsigned int cmd,
void *dst, void *src, unsigned int len)
{
struct kvm_sev_dbg dbg = {
.src_uaddr = (unsigned long)src,
.dst_uaddr = (unsigned long)dst,
.len = len,
};
vm_sev_ioctl(vm, cmd, &dbg);
}
static inline void sev_decrypt_memory(struct kvm_vm *vm, void *dst, void *src,
unsigned int len)
{
sev_dbg_crypt_memory(vm, KVM_SEV_DBG_DECRYPT, dst, src, len);
}
static inline void sev_encrypt_memory(struct kvm_vm *vm, void *dst, void *src,
unsigned int len)
{
sev_dbg_crypt_memory(vm, KVM_SEV_DBG_ENCRYPT, dst, src, len);
}
#endif /* SELFTEST_KVM_SEV_H */
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-only
#ifndef SELFTEST_KVM_SMM_H
#define SELFTEST_KVM_SMM_H
#include "kvm_util.h"
#define SMRAM_SIZE 65536
#define SMRAM_MEMSLOT ((1 << 16) | 1)
#define SMRAM_PAGES (SMRAM_SIZE / PAGE_SIZE)
void setup_smram(struct kvm_vm *vm, struct kvm_vcpu *vcpu, u64 smram_gpa,
const void *smi_handler, size_t handler_size);
void inject_smi(struct kvm_vcpu *vcpu);
#endif /* SELFTEST_KVM_SMM_H */
@@ -0,0 +1,319 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef SELFTEST_KVM_SVM_H
#define SELFTEST_KVM_SVM_H
enum {
INTERCEPT_INTR,
INTERCEPT_NMI,
INTERCEPT_SMI,
INTERCEPT_INIT,
INTERCEPT_VINTR,
INTERCEPT_SELECTIVE_CR0,
INTERCEPT_STORE_IDTR,
INTERCEPT_STORE_GDTR,
INTERCEPT_STORE_LDTR,
INTERCEPT_STORE_TR,
INTERCEPT_LOAD_IDTR,
INTERCEPT_LOAD_GDTR,
INTERCEPT_LOAD_LDTR,
INTERCEPT_LOAD_TR,
INTERCEPT_RDTSC,
INTERCEPT_RDPMC,
INTERCEPT_PUSHF,
INTERCEPT_POPF,
INTERCEPT_CPUID,
INTERCEPT_RSM,
INTERCEPT_IRET,
INTERCEPT_INTn,
INTERCEPT_INVD,
INTERCEPT_PAUSE,
INTERCEPT_HLT,
INTERCEPT_INVLPG,
INTERCEPT_INVLPGA,
INTERCEPT_IOIO_PROT,
INTERCEPT_MSR_PROT,
INTERCEPT_TASK_SWITCH,
INTERCEPT_FERR_FREEZE,
INTERCEPT_SHUTDOWN,
INTERCEPT_VMRUN,
INTERCEPT_VMMCALL,
INTERCEPT_VMLOAD,
INTERCEPT_VMSAVE,
INTERCEPT_STGI,
INTERCEPT_CLGI,
INTERCEPT_SKINIT,
INTERCEPT_RDTSCP,
INTERCEPT_ICEBP,
INTERCEPT_WBINVD,
INTERCEPT_MONITOR,
INTERCEPT_MWAIT,
INTERCEPT_MWAIT_COND,
INTERCEPT_XSETBV,
INTERCEPT_RDPRU,
};
struct hv_vmcb_enlightenments {
struct __packed hv_enlightenments_control {
u32 nested_flush_hypercall:1;
u32 msr_bitmap:1;
u32 enlightened_npt_tlb: 1;
u32 reserved:29;
} __packed hv_enlightenments_control;
u32 hv_vp_id;
u64 hv_vm_id;
u64 partition_assist_page;
u64 reserved;
} __packed;
/*
* Hyper-V uses the software reserved clean bit in VMCB
*/
#define HV_VMCB_NESTED_ENLIGHTENMENTS (1U << 31)
/* Synthetic VM-Exit */
#define HV_SVM_EXITCODE_ENL 0xf0000000
#define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH (1)
struct __attribute__ ((__packed__)) vmcb_control_area {
u32 intercept_cr;
u32 intercept_dr;
u32 intercept_exceptions;
u64 intercept;
u8 reserved_1[40];
u16 pause_filter_thresh;
u16 pause_filter_count;
u64 iopm_base_pa;
u64 msrpm_base_pa;
u64 tsc_offset;
u32 asid;
u8 tlb_ctl;
u8 reserved_2[3];
u32 int_ctl;
u32 int_vector;
u32 int_state;
u8 reserved_3[4];
u64 exit_code;
u64 exit_info_1;
u64 exit_info_2;
u32 exit_int_info;
u32 exit_int_info_err;
u64 misc_ctl;
u64 avic_vapic_bar;
u8 reserved_4[8];
u32 event_inj;
u32 event_inj_err;
u64 nested_cr3;
u64 misc_ctl2;
u32 clean;
u32 reserved_5;
u64 next_rip;
u8 insn_len;
u8 insn_bytes[15];
u64 avic_backing_page; /* Offset 0xe0 */
u8 reserved_6[8]; /* Offset 0xe8 */
u64 avic_logical_id; /* Offset 0xf0 */
u64 avic_physical_id; /* Offset 0xf8 */
u8 reserved_7[8];
u64 vmsa_pa; /* Used for an SEV-ES guest */
u8 reserved_8[720];
/*
* Offset 0x3e0, 32 bytes reserved
* for use by hypervisor/software.
*/
union {
struct hv_vmcb_enlightenments hv_enlightenments;
u8 reserved_sw[32];
};
};
#define TLB_CONTROL_DO_NOTHING 0
#define TLB_CONTROL_FLUSH_ALL_ASID 1
#define TLB_CONTROL_FLUSH_ASID 3
#define TLB_CONTROL_FLUSH_ASID_LOCAL 7
#define V_TPR_MASK 0x0f
#define V_IRQ_SHIFT 8
#define V_IRQ_MASK (1 << V_IRQ_SHIFT)
#define V_GIF_SHIFT 9
#define V_GIF_MASK (1 << V_GIF_SHIFT)
#define V_INTR_PRIO_SHIFT 16
#define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
#define V_IGN_TPR_SHIFT 20
#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
#define V_INTR_MASKING_SHIFT 24
#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
#define V_GIF_ENABLE_SHIFT 25
#define V_GIF_ENABLE_MASK (1 << V_GIF_ENABLE_SHIFT)
#define AVIC_ENABLE_SHIFT 31
#define AVIC_ENABLE_MASK (1 << AVIC_ENABLE_SHIFT)
#define SVM_INTERRUPT_SHADOW_MASK 1
#define SVM_IOIO_STR_SHIFT 2
#define SVM_IOIO_REP_SHIFT 3
#define SVM_IOIO_SIZE_SHIFT 4
#define SVM_IOIO_ASIZE_SHIFT 7
#define SVM_IOIO_TYPE_MASK 1
#define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT)
#define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT)
#define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT)
#define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT)
#define SVM_VM_CR_VALID_MASK 0x001fULL
#define SVM_VM_CR_SVM_LOCK_MASK 0x0008ULL
#define SVM_VM_CR_SVM_DIS_MASK 0x0010ULL
#define SVM_MISC_ENABLE_NP BIT(0)
#define SVM_MISC_ENABLE_SEV BIT(1)
#define SVM_MISC2_ENABLE_V_LBR BIT_ULL(0)
#define SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE BIT_ULL(1)
struct __attribute__ ((__packed__)) vmcb_seg {
u16 selector;
u16 attrib;
u32 limit;
u64 base;
};
struct __attribute__ ((__packed__)) vmcb_save_area {
struct vmcb_seg es;
struct vmcb_seg cs;
struct vmcb_seg ss;
struct vmcb_seg ds;
struct vmcb_seg fs;
struct vmcb_seg gs;
struct vmcb_seg gdtr;
struct vmcb_seg ldtr;
struct vmcb_seg idtr;
struct vmcb_seg tr;
u8 reserved_1[43];
u8 cpl;
u8 reserved_2[4];
u64 efer;
u8 reserved_3[112];
u64 cr4;
u64 cr3;
u64 cr0;
u64 dr7;
u64 dr6;
u64 rflags;
u64 rip;
u8 reserved_4[88];
u64 rsp;
u8 reserved_5[24];
u64 rax;
u64 star;
u64 lstar;
u64 cstar;
u64 sfmask;
u64 kernel_gs_base;
u64 sysenter_cs;
u64 sysenter_esp;
u64 sysenter_eip;
u64 cr2;
u8 reserved_6[32];
u64 g_pat;
u64 dbgctl;
u64 br_from;
u64 br_to;
u64 last_excp_from;
u64 last_excp_to;
};
struct __attribute__ ((__packed__)) vmcb {
struct vmcb_control_area control;
struct vmcb_save_area save;
};
#define SVM_VM_CR_SVM_DISABLE 4
#define SVM_SELECTOR_S_SHIFT 4
#define SVM_SELECTOR_DPL_SHIFT 5
#define SVM_SELECTOR_P_SHIFT 7
#define SVM_SELECTOR_AVL_SHIFT 8
#define SVM_SELECTOR_L_SHIFT 9
#define SVM_SELECTOR_DB_SHIFT 10
#define SVM_SELECTOR_G_SHIFT 11
#define SVM_SELECTOR_TYPE_MASK (0xf)
#define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT)
#define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT)
#define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT)
#define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT)
#define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT)
#define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT)
#define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT)
#define SVM_SELECTOR_WRITE_MASK (1 << 1)
#define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK
#define SVM_SELECTOR_CODE_MASK (1 << 3)
#define INTERCEPT_CR0_READ 0
#define INTERCEPT_CR3_READ 3
#define INTERCEPT_CR4_READ 4
#define INTERCEPT_CR8_READ 8
#define INTERCEPT_CR0_WRITE (16 + 0)
#define INTERCEPT_CR3_WRITE (16 + 3)
#define INTERCEPT_CR4_WRITE (16 + 4)
#define INTERCEPT_CR8_WRITE (16 + 8)
#define INTERCEPT_DR0_READ 0
#define INTERCEPT_DR1_READ 1
#define INTERCEPT_DR2_READ 2
#define INTERCEPT_DR3_READ 3
#define INTERCEPT_DR4_READ 4
#define INTERCEPT_DR5_READ 5
#define INTERCEPT_DR6_READ 6
#define INTERCEPT_DR7_READ 7
#define INTERCEPT_DR0_WRITE (16 + 0)
#define INTERCEPT_DR1_WRITE (16 + 1)
#define INTERCEPT_DR2_WRITE (16 + 2)
#define INTERCEPT_DR3_WRITE (16 + 3)
#define INTERCEPT_DR4_WRITE (16 + 4)
#define INTERCEPT_DR5_WRITE (16 + 5)
#define INTERCEPT_DR6_WRITE (16 + 6)
#define INTERCEPT_DR7_WRITE (16 + 7)
#define SVM_EVTINJ_VEC_MASK 0xff
#define SVM_EVTINJ_TYPE_SHIFT 8
#define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT)
#define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT)
#define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT)
#define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT)
#define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT)
#define SVM_EVTINJ_VALID (1 << 31)
#define SVM_EVTINJ_VALID_ERR (1 << 11)
#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
#define SVM_EXITINTINFO_TYPE_MASK SVM_EVTINJ_TYPE_MASK
#define SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
#define SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
#define SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT
#define SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT
#define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID
#define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR
#define SVM_EXITINFOSHIFT_TS_REASON_IRET 36
#define SVM_EXITINFOSHIFT_TS_REASON_JMP 38
#define SVM_EXITINFOSHIFT_TS_HAS_ERROR_CODE 44
#define SVM_EXITINFO_REG_MASK 0x0F
#define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
#endif /* SELFTEST_KVM_SVM_H */
@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2020, Red Hat, Inc.
*/
#ifndef SELFTEST_KVM_SVM_UTILS_H
#define SELFTEST_KVM_SVM_UTILS_H
#include <asm/svm.h>
#include <stdint.h>
#include "svm.h"
#include "processor.h"
struct svm_test_data {
/* VMCB */
struct vmcb *vmcb; /* gva */
void *vmcb_hva;
u64 vmcb_gpa;
/* host state-save area */
struct vmcb_save_area *save_area; /* gva */
void *save_area_hva;
u64 save_area_gpa;
/* MSR-Bitmap */
void *msr; /* gva */
void *msr_hva;
u64 msr_gpa;
/* NPT */
u64 ncr3_gpa;
};
static inline void vmmcall(void)
{
/*
* Stuff RAX and RCX with "safe" values to make sure L0 doesn't handle
* it as a valid hypercall (e.g. Hyper-V L2 TLB flush) as the intended
* use of this function is to exit to L1 from L2. Clobber all other
* GPRs as L1 doesn't correctly preserve them during vmexits.
*/
__asm__ __volatile__("push %%rbp; vmmcall; pop %%rbp"
: : "a"(0xdeadbeef), "c"(0xbeefdead)
: "rbx", "rdx", "rsi", "rdi", "r8", "r9",
"r10", "r11", "r12", "r13", "r14", "r15");
}
#define stgi() \
__asm__ __volatile__( \
"stgi\n" \
)
#define clgi() \
__asm__ __volatile__( \
"clgi\n" \
)
struct svm_test_data *vcpu_alloc_svm(struct kvm_vm *vm, gva_t *p_svm_gva);
void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_rsp);
void run_guest(struct vmcb *vmcb, u64 vmcb_gpa);
static inline bool kvm_cpu_has_npt(void)
{
return kvm_cpu_has(X86_FEATURE_NPT);
}
void vm_enable_npt(struct kvm_vm *vm);
int open_sev_dev_path_or_exit(void);
#endif /* SELFTEST_KVM_SVM_UTILS_H */
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UCALL_H
#define SELFTEST_KVM_UCALL_H
#include "kvm_util.h"
#define UCALL_EXIT_REASON KVM_EXIT_IO
static inline void ucall_arch_init(struct kvm_vm *vm, gpa_t mmio_gpa)
{
}
#endif
@@ -0,0 +1,564 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2018, Google LLC.
*/
#ifndef SELFTEST_KVM_VMX_H
#define SELFTEST_KVM_VMX_H
#include <asm/vmx.h>
#include <stdint.h>
#include "processor.h"
#include "apic.h"
/*
* Definitions of Primary Processor-Based VM-Execution Controls.
*/
#define CPU_BASED_INTR_WINDOW_EXITING 0x00000004
#define CPU_BASED_USE_TSC_OFFSETTING 0x00000008
#define CPU_BASED_HLT_EXITING 0x00000080
#define CPU_BASED_INVLPG_EXITING 0x00000200
#define CPU_BASED_MWAIT_EXITING 0x00000400
#define CPU_BASED_RDPMC_EXITING 0x00000800
#define CPU_BASED_RDTSC_EXITING 0x00001000
#define CPU_BASED_CR3_LOAD_EXITING 0x00008000
#define CPU_BASED_CR3_STORE_EXITING 0x00010000
#define CPU_BASED_CR8_LOAD_EXITING 0x00080000
#define CPU_BASED_CR8_STORE_EXITING 0x00100000
#define CPU_BASED_TPR_SHADOW 0x00200000
#define CPU_BASED_NMI_WINDOW_EXITING 0x00400000
#define CPU_BASED_MOV_DR_EXITING 0x00800000
#define CPU_BASED_UNCOND_IO_EXITING 0x01000000
#define CPU_BASED_USE_IO_BITMAPS 0x02000000
#define CPU_BASED_MONITOR_TRAP 0x08000000
#define CPU_BASED_USE_MSR_BITMAPS 0x10000000
#define CPU_BASED_MONITOR_EXITING 0x20000000
#define CPU_BASED_PAUSE_EXITING 0x40000000
#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000
#define CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x0401e172
/*
* Definitions of Secondary Processor-Based VM-Execution Controls.
*/
#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
#define SECONDARY_EXEC_ENABLE_EPT 0x00000002
#define SECONDARY_EXEC_DESC 0x00000004
#define SECONDARY_EXEC_ENABLE_RDTSCP 0x00000008
#define SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE 0x00000010
#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
#define SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100
#define SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY 0x00000200
#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
#define SECONDARY_EXEC_RDRAND_EXITING 0x00000800
#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
#define SECONDARY_EXEC_ENABLE_VMFUNC 0x00002000
#define SECONDARY_EXEC_SHADOW_VMCS 0x00004000
#define SECONDARY_EXEC_RDSEED_EXITING 0x00010000
#define SECONDARY_EXEC_ENABLE_PML 0x00020000
#define SECONDARY_EPT_VE 0x00040000
#define SECONDARY_ENABLE_XSAV_RESTORE 0x00100000
#define SECONDARY_EXEC_TSC_SCALING 0x02000000
#define PIN_BASED_EXT_INTR_MASK 0x00000001
#define PIN_BASED_NMI_EXITING 0x00000008
#define PIN_BASED_VIRTUAL_NMIS 0x00000020
#define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040
#define PIN_BASED_POSTED_INTR 0x00000080
#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016
#define VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000004
#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200
#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000
#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
#define VM_EXIT_SAVE_IA32_PAT 0x00040000
#define VM_EXIT_LOAD_IA32_PAT 0x00080000
#define VM_EXIT_SAVE_IA32_EFER 0x00100000
#define VM_EXIT_LOAD_IA32_EFER 0x00200000
#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000
#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff
#define VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004
#define VM_ENTRY_IA32E_MODE 0x00000200
#define VM_ENTRY_SMM 0x00000400
#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000
#define VM_ENTRY_LOAD_IA32_PAT 0x00004000
#define VM_ENTRY_LOAD_IA32_EFER 0x00008000
#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff
#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK 0x0000001f
#define VMX_MISC_SAVE_EFER_LMA 0x00000020
#define VMX_EPT_VPID_CAP_1G_PAGES 0x00020000
#define VMX_EPT_VPID_CAP_AD_BITS 0x00200000
#define EXIT_REASON_FAILED_VMENTRY 0x80000000
enum vmcs_field {
VIRTUAL_PROCESSOR_ID = 0x00000000,
POSTED_INTR_NV = 0x00000002,
GUEST_ES_SELECTOR = 0x00000800,
GUEST_CS_SELECTOR = 0x00000802,
GUEST_SS_SELECTOR = 0x00000804,
GUEST_DS_SELECTOR = 0x00000806,
GUEST_FS_SELECTOR = 0x00000808,
GUEST_GS_SELECTOR = 0x0000080a,
GUEST_LDTR_SELECTOR = 0x0000080c,
GUEST_TR_SELECTOR = 0x0000080e,
GUEST_INTR_STATUS = 0x00000810,
GUEST_PML_INDEX = 0x00000812,
HOST_ES_SELECTOR = 0x00000c00,
HOST_CS_SELECTOR = 0x00000c02,
HOST_SS_SELECTOR = 0x00000c04,
HOST_DS_SELECTOR = 0x00000c06,
HOST_FS_SELECTOR = 0x00000c08,
HOST_GS_SELECTOR = 0x00000c0a,
HOST_TR_SELECTOR = 0x00000c0c,
IO_BITMAP_A = 0x00002000,
IO_BITMAP_A_HIGH = 0x00002001,
IO_BITMAP_B = 0x00002002,
IO_BITMAP_B_HIGH = 0x00002003,
MSR_BITMAP = 0x00002004,
MSR_BITMAP_HIGH = 0x00002005,
VM_EXIT_MSR_STORE_ADDR = 0x00002006,
VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
PML_ADDRESS = 0x0000200e,
PML_ADDRESS_HIGH = 0x0000200f,
TSC_OFFSET = 0x00002010,
TSC_OFFSET_HIGH = 0x00002011,
VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
APIC_ACCESS_ADDR = 0x00002014,
APIC_ACCESS_ADDR_HIGH = 0x00002015,
POSTED_INTR_DESC_ADDR = 0x00002016,
POSTED_INTR_DESC_ADDR_HIGH = 0x00002017,
EPT_POINTER = 0x0000201a,
EPT_POINTER_HIGH = 0x0000201b,
EOI_EXIT_BITMAP0 = 0x0000201c,
EOI_EXIT_BITMAP0_HIGH = 0x0000201d,
EOI_EXIT_BITMAP1 = 0x0000201e,
EOI_EXIT_BITMAP1_HIGH = 0x0000201f,
EOI_EXIT_BITMAP2 = 0x00002020,
EOI_EXIT_BITMAP2_HIGH = 0x00002021,
EOI_EXIT_BITMAP3 = 0x00002022,
EOI_EXIT_BITMAP3_HIGH = 0x00002023,
VMREAD_BITMAP = 0x00002026,
VMREAD_BITMAP_HIGH = 0x00002027,
VMWRITE_BITMAP = 0x00002028,
VMWRITE_BITMAP_HIGH = 0x00002029,
XSS_EXIT_BITMAP = 0x0000202C,
XSS_EXIT_BITMAP_HIGH = 0x0000202D,
ENCLS_EXITING_BITMAP = 0x0000202E,
ENCLS_EXITING_BITMAP_HIGH = 0x0000202F,
TSC_MULTIPLIER = 0x00002032,
TSC_MULTIPLIER_HIGH = 0x00002033,
GUEST_PHYSICAL_ADDRESS = 0x00002400,
GUEST_PHYSICAL_ADDRESS_HIGH = 0x00002401,
VMCS_LINK_POINTER = 0x00002800,
VMCS_LINK_POINTER_HIGH = 0x00002801,
GUEST_IA32_DEBUGCTL = 0x00002802,
GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
GUEST_IA32_PAT = 0x00002804,
GUEST_IA32_PAT_HIGH = 0x00002805,
GUEST_IA32_EFER = 0x00002806,
GUEST_IA32_EFER_HIGH = 0x00002807,
GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808,
GUEST_IA32_PERF_GLOBAL_CTRL_HIGH= 0x00002809,
GUEST_PDPTR0 = 0x0000280a,
GUEST_PDPTR0_HIGH = 0x0000280b,
GUEST_PDPTR1 = 0x0000280c,
GUEST_PDPTR1_HIGH = 0x0000280d,
GUEST_PDPTR2 = 0x0000280e,
GUEST_PDPTR2_HIGH = 0x0000280f,
GUEST_PDPTR3 = 0x00002810,
GUEST_PDPTR3_HIGH = 0x00002811,
GUEST_BNDCFGS = 0x00002812,
GUEST_BNDCFGS_HIGH = 0x00002813,
HOST_IA32_PAT = 0x00002c00,
HOST_IA32_PAT_HIGH = 0x00002c01,
HOST_IA32_EFER = 0x00002c02,
HOST_IA32_EFER_HIGH = 0x00002c03,
HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04,
HOST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002c05,
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
EXCEPTION_BITMAP = 0x00004004,
PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
CR3_TARGET_COUNT = 0x0000400a,
VM_EXIT_CONTROLS = 0x0000400c,
VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
VM_ENTRY_CONTROLS = 0x00004012,
VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
TPR_THRESHOLD = 0x0000401c,
SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
PLE_GAP = 0x00004020,
PLE_WINDOW = 0x00004022,
VM_INSTRUCTION_ERROR = 0x00004400,
VM_EXIT_REASON = 0x00004402,
VM_EXIT_INTR_INFO = 0x00004404,
VM_EXIT_INTR_ERROR_CODE = 0x00004406,
IDT_VECTORING_INFO_FIELD = 0x00004408,
IDT_VECTORING_ERROR_CODE = 0x0000440a,
VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
VMX_INSTRUCTION_INFO = 0x0000440e,
GUEST_ES_LIMIT = 0x00004800,
GUEST_CS_LIMIT = 0x00004802,
GUEST_SS_LIMIT = 0x00004804,
GUEST_DS_LIMIT = 0x00004806,
GUEST_FS_LIMIT = 0x00004808,
GUEST_GS_LIMIT = 0x0000480a,
GUEST_LDTR_LIMIT = 0x0000480c,
GUEST_TR_LIMIT = 0x0000480e,
GUEST_GDTR_LIMIT = 0x00004810,
GUEST_IDTR_LIMIT = 0x00004812,
GUEST_ES_AR_BYTES = 0x00004814,
GUEST_CS_AR_BYTES = 0x00004816,
GUEST_SS_AR_BYTES = 0x00004818,
GUEST_DS_AR_BYTES = 0x0000481a,
GUEST_FS_AR_BYTES = 0x0000481c,
GUEST_GS_AR_BYTES = 0x0000481e,
GUEST_LDTR_AR_BYTES = 0x00004820,
GUEST_TR_AR_BYTES = 0x00004822,
GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
GUEST_ACTIVITY_STATE = 0X00004826,
GUEST_SYSENTER_CS = 0x0000482A,
VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,
HOST_IA32_SYSENTER_CS = 0x00004c00,
CR0_GUEST_HOST_MASK = 0x00006000,
CR4_GUEST_HOST_MASK = 0x00006002,
CR0_READ_SHADOW = 0x00006004,
CR4_READ_SHADOW = 0x00006006,
CR3_TARGET_VALUE0 = 0x00006008,
CR3_TARGET_VALUE1 = 0x0000600a,
CR3_TARGET_VALUE2 = 0x0000600c,
CR3_TARGET_VALUE3 = 0x0000600e,
EXIT_QUALIFICATION = 0x00006400,
GUEST_LINEAR_ADDRESS = 0x0000640a,
GUEST_CR0 = 0x00006800,
GUEST_CR3 = 0x00006802,
GUEST_CR4 = 0x00006804,
GUEST_ES_BASE = 0x00006806,
GUEST_CS_BASE = 0x00006808,
GUEST_SS_BASE = 0x0000680a,
GUEST_DS_BASE = 0x0000680c,
GUEST_FS_BASE = 0x0000680e,
GUEST_GS_BASE = 0x00006810,
GUEST_LDTR_BASE = 0x00006812,
GUEST_TR_BASE = 0x00006814,
GUEST_GDTR_BASE = 0x00006816,
GUEST_IDTR_BASE = 0x00006818,
GUEST_DR7 = 0x0000681a,
GUEST_RSP = 0x0000681c,
GUEST_RIP = 0x0000681e,
GUEST_RFLAGS = 0x00006820,
GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
GUEST_SYSENTER_ESP = 0x00006824,
GUEST_SYSENTER_EIP = 0x00006826,
HOST_CR0 = 0x00006c00,
HOST_CR3 = 0x00006c02,
HOST_CR4 = 0x00006c04,
HOST_FS_BASE = 0x00006c06,
HOST_GS_BASE = 0x00006c08,
HOST_TR_BASE = 0x00006c0a,
HOST_GDTR_BASE = 0x00006c0c,
HOST_IDTR_BASE = 0x00006c0e,
HOST_IA32_SYSENTER_ESP = 0x00006c10,
HOST_IA32_SYSENTER_EIP = 0x00006c12,
HOST_RSP = 0x00006c14,
HOST_RIP = 0x00006c16,
};
struct vmx_msr_entry {
u32 index;
u32 reserved;
u64 value;
} __attribute__ ((aligned(16)));
#include "evmcs.h"
static inline int vmxon(u64 phys)
{
u8 ret;
__asm__ __volatile__ ("vmxon %[pa]; setna %[ret]"
: [ret]"=rm"(ret)
: [pa]"m"(phys)
: "cc", "memory");
return ret;
}
static inline void vmxoff(void)
{
__asm__ __volatile__("vmxoff");
}
static inline int vmclear(u64 vmcs_pa)
{
u8 ret;
__asm__ __volatile__ ("vmclear %[pa]; setna %[ret]"
: [ret]"=rm"(ret)
: [pa]"m"(vmcs_pa)
: "cc", "memory");
return ret;
}
static inline int vmptrld(u64 vmcs_pa)
{
u8 ret;
if (enable_evmcs)
return -1;
__asm__ __volatile__ ("vmptrld %[pa]; setna %[ret]"
: [ret]"=rm"(ret)
: [pa]"m"(vmcs_pa)
: "cc", "memory");
return ret;
}
static inline int vmptrst(u64 *value)
{
u64 tmp;
u8 ret;
if (enable_evmcs)
return evmcs_vmptrst(value);
__asm__ __volatile__("vmptrst %[value]; setna %[ret]"
: [value]"=m"(tmp), [ret]"=rm"(ret)
: : "cc", "memory");
*value = tmp;
return ret;
}
/*
* A wrapper around vmptrst that ignores errors and returns zero if the
* vmptrst instruction fails.
*/
static inline u64 vmptrstz(void)
{
u64 value = 0;
vmptrst(&value);
return value;
}
/*
* No guest state (e.g. GPRs) is established by this vmlaunch.
*/
static inline int vmlaunch(void)
{
int ret;
if (enable_evmcs)
return evmcs_vmlaunch();
__asm__ __volatile__("push %%rbp;"
"push %%rcx;"
"push %%rdx;"
"push %%rsi;"
"push %%rdi;"
"push $0;"
"vmwrite %%rsp, %[host_rsp];"
"lea 1f(%%rip), %%rax;"
"vmwrite %%rax, %[host_rip];"
"vmlaunch;"
"incq (%%rsp);"
"1: pop %%rax;"
"pop %%rdi;"
"pop %%rsi;"
"pop %%rdx;"
"pop %%rcx;"
"pop %%rbp;"
: [ret]"=&a"(ret)
: [host_rsp]"r"((u64)HOST_RSP),
[host_rip]"r"((u64)HOST_RIP)
: "memory", "cc", "rbx", "r8", "r9", "r10",
"r11", "r12", "r13", "r14", "r15");
return ret;
}
/*
* No guest state (e.g. GPRs) is established by this vmresume.
*/
static inline int vmresume(void)
{
int ret;
if (enable_evmcs)
return evmcs_vmresume();
__asm__ __volatile__("push %%rbp;"
"push %%rcx;"
"push %%rdx;"
"push %%rsi;"
"push %%rdi;"
"push $0;"
"vmwrite %%rsp, %[host_rsp];"
"lea 1f(%%rip), %%rax;"
"vmwrite %%rax, %[host_rip];"
"vmresume;"
"incq (%%rsp);"
"1: pop %%rax;"
"pop %%rdi;"
"pop %%rsi;"
"pop %%rdx;"
"pop %%rcx;"
"pop %%rbp;"
: [ret]"=&a"(ret)
: [host_rsp]"r"((u64)HOST_RSP),
[host_rip]"r"((u64)HOST_RIP)
: "memory", "cc", "rbx", "r8", "r9", "r10",
"r11", "r12", "r13", "r14", "r15");
return ret;
}
static inline void vmcall(void)
{
/*
* Stuff RAX and RCX with "safe" values to make sure L0 doesn't handle
* it as a valid hypercall (e.g. Hyper-V L2 TLB flush) as the intended
* use of this function is to exit to L1 from L2. Clobber all other
* GPRs as L1 doesn't correctly preserve them during vmexits.
*/
__asm__ __volatile__("push %%rbp; vmcall; pop %%rbp"
: : "a"(0xdeadbeef), "c"(0xbeefdead)
: "rbx", "rdx", "rsi", "rdi", "r8", "r9",
"r10", "r11", "r12", "r13", "r14", "r15");
}
static inline int vmread(u64 encoding, u64 *value)
{
u64 tmp;
u8 ret;
if (enable_evmcs)
return evmcs_vmread(encoding, value);
__asm__ __volatile__("vmread %[encoding], %[value]; setna %[ret]"
: [value]"=rm"(tmp), [ret]"=rm"(ret)
: [encoding]"r"(encoding)
: "cc", "memory");
*value = tmp;
return ret;
}
/*
* A wrapper around vmread that ignores errors and returns zero if the
* vmread instruction fails.
*/
static inline u64 vmreadz(u64 encoding)
{
u64 value = 0;
vmread(encoding, &value);
return value;
}
static inline int vmwrite(u64 encoding, u64 value)
{
u8 ret;
if (enable_evmcs)
return evmcs_vmwrite(encoding, value);
__asm__ __volatile__ ("vmwrite %[value], %[encoding]; setna %[ret]"
: [ret]"=rm"(ret)
: [value]"rm"(value), [encoding]"r"(encoding)
: "cc", "memory");
return ret;
}
static inline u32 vmcs_revision(void)
{
return rdmsr(MSR_IA32_VMX_BASIC);
}
struct vmx_pages {
void *vmxon_hva;
u64 vmxon_gpa;
void *vmxon;
void *vmcs_hva;
u64 vmcs_gpa;
void *vmcs;
void *msr_hva;
u64 msr_gpa;
void *msr;
void *shadow_vmcs_hva;
u64 shadow_vmcs_gpa;
void *shadow_vmcs;
void *vmread_hva;
u64 vmread_gpa;
void *vmread;
void *vmwrite_hva;
u64 vmwrite_gpa;
void *vmwrite;
void *apic_access_hva;
u64 apic_access_gpa;
void *apic_access;
u64 eptp_gpa;
};
union vmx_basic {
u64 val;
struct {
u32 revision;
u32 size:13,
reserved1:3,
width:1,
dual:1,
type:4,
insouts:1,
ctrl:1,
vm_entry_exception_ctrl:1,
reserved2:7;
};
};
union vmx_ctrl_msr {
u64 val;
struct {
u32 set, clr;
};
};
struct vmx_pages *vcpu_alloc_vmx(struct kvm_vm *vm, gva_t *p_vmx_gva);
bool prepare_for_vmx_operation(struct vmx_pages *vmx);
void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp);
bool load_vmcs(struct vmx_pages *vmx);
bool ept_1g_pages_supported(void);
bool kvm_cpu_has_ept(void);
void vm_enable_ept(struct kvm_vm *vm);
void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm);
#endif /* SELFTEST_KVM_VMX_H */