mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull more kvm updates from Paolo Bonzini:
"The main batch of ARM + RISC-V changes, and a few fixes and cleanups
for x86 (PMU virtualization and selftests).
ARM:
- Fixes for single-stepping in the presence of an async exception as
well as the preservation of PSTATE.SS
- Better handling of AArch32 ID registers on AArch64-only systems
- Fixes for the dirty-ring API, allowing it to work on architectures
with relaxed memory ordering
- Advertise the new kvmarm mailing list
- Various minor cleanups and spelling fixes
RISC-V:
- Improved instruction encoding infrastructure for instructions not
yet supported by binutils
- Svinval support for both KVM Host and KVM Guest
- Zihintpause support for KVM Guest
- Zicbom support for KVM Guest
- Record number of signal exits as a VCPU stat
- Use generic guest entry infrastructure
x86:
- Misc PMU fixes and cleanups.
- selftests: fixes for Hyper-V hypercall
- selftests: fix nx_huge_pages_test on TDP-disabled hosts
- selftests: cleanups for fix_hypercall_test"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (57 commits)
riscv: select HAVE_POSIX_CPU_TIMERS_TASK_WORK
RISC-V: KVM: Use generic guest entry infrastructure
RISC-V: KVM: Record number of signal exits as a vCPU stat
RISC-V: KVM: add __init annotation to riscv_kvm_init()
RISC-V: KVM: Expose Zicbom to the guest
RISC-V: KVM: Provide UAPI for Zicbom block size
RISC-V: KVM: Make ISA ext mappings explicit
RISC-V: KVM: Allow Guest use Zihintpause extension
RISC-V: KVM: Allow Guest use Svinval extension
RISC-V: KVM: Use Svinval for local TLB maintenance when available
RISC-V: Probe Svinval extension form ISA string
RISC-V: KVM: Change the SBI specification version to v1.0
riscv: KVM: Apply insn-def to hlv encodings
riscv: KVM: Apply insn-def to hfence encodings
riscv: Introduce support for defining instructions
riscv: Add X register names to gpr-nums
KVM: arm64: Advertise new kvmarm mailing list
kvm: vmx: keep constant definition format consistent
kvm: mmu: fix typos in struct kvm_arch
KVM: selftests: Fix nx_huge_pages_test on TDP-disabled hosts
...
This commit is contained in:
@@ -7918,8 +7918,8 @@ guest according to the bits in the KVM_CPUID_FEATURES CPUID leaf
|
||||
(0x40000001). Otherwise, a guest may use the paravirtual features
|
||||
regardless of what has actually been exposed through the CPUID leaf.
|
||||
|
||||
8.29 KVM_CAP_DIRTY_LOG_RING
|
||||
---------------------------
|
||||
8.29 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL
|
||||
----------------------------------------------------------
|
||||
|
||||
:Architectures: x86
|
||||
:Parameters: args[0] - size of the dirty log ring
|
||||
@@ -7977,6 +7977,11 @@ on to the next GFN. The userspace should continue to do this until the
|
||||
flags of a GFN have the DIRTY bit cleared, meaning that it has harvested
|
||||
all the dirty GFNs that were available.
|
||||
|
||||
Note that on weakly ordered architectures, userspace accesses to the
|
||||
ring buffer (and more specifically the 'flags' field) must be ordered,
|
||||
using load-acquire/store-release accessors when available, or any
|
||||
other memory barrier that will ensure this ordering.
|
||||
|
||||
It's not necessary for userspace to harvest the all dirty GFNs at once.
|
||||
However it must collect the dirty GFNs in sequence, i.e., the userspace
|
||||
program cannot skip one dirty GFN to collect the one next to it.
|
||||
@@ -8005,6 +8010,14 @@ KVM_CAP_DIRTY_LOG_RING with an acceptable dirty ring size, the virtual
|
||||
machine will switch to ring-buffer dirty page tracking and further
|
||||
KVM_GET_DIRTY_LOG or KVM_CLEAR_DIRTY_LOG ioctls will fail.
|
||||
|
||||
NOTE: KVM_CAP_DIRTY_LOG_RING_ACQ_REL is the only capability that
|
||||
should be exposed by weakly ordered architecture, in order to indicate
|
||||
the additional memory ordering requirements imposed on userspace when
|
||||
reading the state of an entry and mutating it from DIRTY to HARVESTED.
|
||||
Architecture with TSO-like ordering (such as x86) are allowed to
|
||||
expose both KVM_CAP_DIRTY_LOG_RING and KVM_CAP_DIRTY_LOG_RING_ACQ_REL
|
||||
to userspace.
|
||||
|
||||
8.30 KVM_CAP_XEN_HVM
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -11204,7 +11204,8 @@ R: Alexandru Elisei <alexandru.elisei@arm.com>
|
||||
R: Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
R: Oliver Upton <oliver.upton@linux.dev>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: kvmarm@lists.cs.columbia.edu (moderated for non-subscribers)
|
||||
L: kvmarm@lists.linux.dev
|
||||
L: kvmarm@lists.cs.columbia.edu (deprecated, moderated for non-subscribers)
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
|
||||
F: arch/arm64/include/asm/kvm*
|
||||
|
||||
@@ -393,6 +393,7 @@ struct kvm_vcpu_arch {
|
||||
*/
|
||||
struct {
|
||||
u32 mdscr_el1;
|
||||
bool pstate_ss;
|
||||
} guest_debug_preserved;
|
||||
|
||||
/* vcpu power state */
|
||||
@@ -535,6 +536,9 @@ struct kvm_vcpu_arch {
|
||||
#define IN_WFIT __vcpu_single_flag(sflags, BIT(3))
|
||||
/* vcpu system registers loaded on physical CPU */
|
||||
#define SYSREGS_ON_CPU __vcpu_single_flag(sflags, BIT(4))
|
||||
/* Software step state is Active-pending */
|
||||
#define DBG_SS_ACTIVE_PENDING __vcpu_single_flag(sflags, BIT(5))
|
||||
|
||||
|
||||
/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
|
||||
#define vcpu_sve_pffr(vcpu) (kern_hyp_va((vcpu)->arch.sve_state) + \
|
||||
|
||||
@@ -2269,6 +2269,16 @@ static int __init early_kvm_mode_cfg(char *arg)
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(arg, "none") == 0) {
|
||||
kvm_mode = KVM_MODE_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!is_hyp_mode_available()) {
|
||||
pr_warn_once("KVM is not available. Ignoring kvm-arm.mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(arg, "protected") == 0) {
|
||||
if (!is_kernel_in_hyp_mode())
|
||||
kvm_mode = KVM_MODE_PROTECTED;
|
||||
@@ -2283,11 +2293,6 @@ static int __init early_kvm_mode_cfg(char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(arg, "none") == 0) {
|
||||
kvm_mode = KVM_MODE_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
early_param("kvm-arm.mode", early_kvm_mode_cfg);
|
||||
|
||||
@@ -32,6 +32,10 @@ static DEFINE_PER_CPU(u64, mdcr_el2);
|
||||
*
|
||||
* Guest access to MDSCR_EL1 is trapped by the hypervisor and handled
|
||||
* after we have restored the preserved value to the main context.
|
||||
*
|
||||
* When single-step is enabled by userspace, we tweak PSTATE.SS on every
|
||||
* guest entry. Preserve PSTATE.SS so we can restore the original value
|
||||
* for the vcpu after the single-step is disabled.
|
||||
*/
|
||||
static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
@@ -41,6 +45,9 @@ static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
|
||||
|
||||
trace_kvm_arm_set_dreg32("Saved MDSCR_EL1",
|
||||
vcpu->arch.guest_debug_preserved.mdscr_el1);
|
||||
|
||||
vcpu->arch.guest_debug_preserved.pstate_ss =
|
||||
(*vcpu_cpsr(vcpu) & DBG_SPSR_SS);
|
||||
}
|
||||
|
||||
static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
|
||||
@@ -51,6 +58,11 @@ static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
|
||||
|
||||
trace_kvm_arm_set_dreg32("Restored MDSCR_EL1",
|
||||
vcpu_read_sys_reg(vcpu, MDSCR_EL1));
|
||||
|
||||
if (vcpu->arch.guest_debug_preserved.pstate_ss)
|
||||
*vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
|
||||
else
|
||||
*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +200,18 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
|
||||
* debugging the system.
|
||||
*/
|
||||
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
|
||||
*vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
|
||||
/*
|
||||
* If the software step state at the last guest exit
|
||||
* was Active-pending, we don't set DBG_SPSR_SS so
|
||||
* that the state is maintained (to not run another
|
||||
* single-step until the pending Software Step
|
||||
* exception is taken).
|
||||
*/
|
||||
if (!vcpu_get_flag(vcpu, DBG_SS_ACTIVE_PENDING))
|
||||
*vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
|
||||
else
|
||||
*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
|
||||
|
||||
mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
|
||||
mdscr |= DBG_MDSCR_SS;
|
||||
vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
|
||||
@@ -262,6 +285,15 @@ void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
|
||||
* Restore the guest's debug registers if we were using them.
|
||||
*/
|
||||
if (vcpu->guest_debug || kvm_vcpu_os_lock_enabled(vcpu)) {
|
||||
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
|
||||
if (!(*vcpu_cpsr(vcpu) & DBG_SPSR_SS))
|
||||
/*
|
||||
* Mark the vcpu as ACTIVE_PENDING
|
||||
* until Software Step exception is taken.
|
||||
*/
|
||||
vcpu_set_flag(vcpu, DBG_SS_ACTIVE_PENDING);
|
||||
}
|
||||
|
||||
restore_guest_debug_regs(vcpu);
|
||||
|
||||
/*
|
||||
|
||||
@@ -937,6 +937,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
|
||||
} else {
|
||||
/* If not enabled clear all flags */
|
||||
vcpu->guest_debug = 0;
|
||||
vcpu_clear_flag(vcpu, DBG_SS_ACTIVE_PENDING);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -152,8 +152,14 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu)
|
||||
run->debug.arch.hsr_high = upper_32_bits(esr);
|
||||
run->flags = KVM_DEBUG_ARCH_HSR_HIGH_VALID;
|
||||
|
||||
if (ESR_ELx_EC(esr) == ESR_ELx_EC_WATCHPT_LOW)
|
||||
switch (ESR_ELx_EC(esr)) {
|
||||
case ESR_ELx_EC_WATCHPT_LOW:
|
||||
run->debug.arch.far = vcpu->arch.fault.far_el2;
|
||||
break;
|
||||
case ESR_ELx_EC_SOFTSTP_LOW:
|
||||
vcpu_clear_flag(vcpu, DBG_SS_ACTIVE_PENDING);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ static void __hyp_vgic_save_state(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore VGICv3 state on non_VEH systems */
|
||||
/* Restore VGICv3 state on non-VHE systems */
|
||||
static void __hyp_vgic_restore_state(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) {
|
||||
|
||||
@@ -1063,13 +1063,12 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
|
||||
}
|
||||
|
||||
/* Read a sanitised cpufeature ID register by sys_reg_desc */
|
||||
static u64 read_id_reg(const struct kvm_vcpu *vcpu,
|
||||
struct sys_reg_desc const *r, bool raz)
|
||||
static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r)
|
||||
{
|
||||
u32 id = reg_to_encoding(r);
|
||||
u64 val;
|
||||
|
||||
if (raz)
|
||||
if (sysreg_visible_as_raz(vcpu, r))
|
||||
return 0;
|
||||
|
||||
val = read_sanitised_ftr_reg(id);
|
||||
@@ -1145,34 +1144,37 @@ static unsigned int id_visibility(const struct kvm_vcpu *vcpu,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cpufeature ID register access trap handlers */
|
||||
|
||||
static bool __access_id_reg(struct kvm_vcpu *vcpu,
|
||||
struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r,
|
||||
bool raz)
|
||||
static unsigned int aa32_id_visibility(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return write_to_read_only(vcpu, p, r);
|
||||
/*
|
||||
* AArch32 ID registers are UNKNOWN if AArch32 isn't implemented at any
|
||||
* EL. Promote to RAZ/WI in order to guarantee consistency between
|
||||
* systems.
|
||||
*/
|
||||
if (!kvm_supports_32bit_el0())
|
||||
return REG_RAZ | REG_USER_WI;
|
||||
|
||||
p->regval = read_id_reg(vcpu, r, raz);
|
||||
return true;
|
||||
return id_visibility(vcpu, r);
|
||||
}
|
||||
|
||||
static unsigned int raz_visibility(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
return REG_RAZ;
|
||||
}
|
||||
|
||||
/* cpufeature ID register access trap handlers */
|
||||
|
||||
static bool access_id_reg(struct kvm_vcpu *vcpu,
|
||||
struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
bool raz = sysreg_visible_as_raz(vcpu, r);
|
||||
if (p->is_write)
|
||||
return write_to_read_only(vcpu, p, r);
|
||||
|
||||
return __access_id_reg(vcpu, p, r, raz);
|
||||
}
|
||||
|
||||
static bool access_raz_id_reg(struct kvm_vcpu *vcpu,
|
||||
struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
return __access_id_reg(vcpu, p, r, true);
|
||||
p->regval = read_id_reg(vcpu, r);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Visibility overrides for SVE-specific control registers */
|
||||
@@ -1208,9 +1210,9 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
|
||||
return -EINVAL;
|
||||
|
||||
/* We can only differ with CSV[23], and anything else is an error */
|
||||
val ^= read_id_reg(vcpu, rd, false);
|
||||
val &= ~((0xFUL << ID_AA64PFR0_EL1_CSV2_SHIFT) |
|
||||
(0xFUL << ID_AA64PFR0_EL1_CSV3_SHIFT));
|
||||
val ^= read_id_reg(vcpu, rd);
|
||||
val &= ~(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2) |
|
||||
ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3));
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1227,45 +1229,21 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
|
||||
* are stored, and for set_id_reg() we don't allow the effective value
|
||||
* to be changed.
|
||||
*/
|
||||
static int __get_id_reg(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *rd, u64 *val,
|
||||
bool raz)
|
||||
{
|
||||
*val = read_id_reg(vcpu, rd, raz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __set_id_reg(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *rd, u64 val,
|
||||
bool raz)
|
||||
{
|
||||
/* This is what we mean by invariant: you can't change it. */
|
||||
if (val != read_id_reg(vcpu, rd, raz))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
|
||||
u64 *val)
|
||||
{
|
||||
bool raz = sysreg_visible_as_raz(vcpu, rd);
|
||||
|
||||
return __get_id_reg(vcpu, rd, val, raz);
|
||||
*val = read_id_reg(vcpu, rd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
|
||||
u64 val)
|
||||
{
|
||||
bool raz = sysreg_visible_as_raz(vcpu, rd);
|
||||
/* This is what we mean by invariant: you can't change it. */
|
||||
if (val != read_id_reg(vcpu, rd))
|
||||
return -EINVAL;
|
||||
|
||||
return __set_id_reg(vcpu, rd, val, raz);
|
||||
}
|
||||
|
||||
static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
|
||||
u64 val)
|
||||
{
|
||||
return __set_id_reg(vcpu, rd, val, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_raz_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
|
||||
@@ -1367,6 +1345,15 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu,
|
||||
.visibility = id_visibility, \
|
||||
}
|
||||
|
||||
/* sys_reg_desc initialiser for known cpufeature ID registers */
|
||||
#define AA32_ID_SANITISED(name) { \
|
||||
SYS_DESC(SYS_##name), \
|
||||
.access = access_id_reg, \
|
||||
.get_user = get_id_reg, \
|
||||
.set_user = set_id_reg, \
|
||||
.visibility = aa32_id_visibility, \
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_reg_desc initialiser for architecturally unallocated cpufeature ID
|
||||
* register with encoding Op0=3, Op1=0, CRn=0, CRm=crm, Op2=op2
|
||||
@@ -1374,9 +1361,10 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu,
|
||||
*/
|
||||
#define ID_UNALLOCATED(crm, op2) { \
|
||||
Op0(3), Op1(0), CRn(0), CRm(crm), Op2(op2), \
|
||||
.access = access_raz_id_reg, \
|
||||
.get_user = get_raz_reg, \
|
||||
.set_user = set_raz_id_reg, \
|
||||
.access = access_id_reg, \
|
||||
.get_user = get_id_reg, \
|
||||
.set_user = set_id_reg, \
|
||||
.visibility = raz_visibility \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1386,9 +1374,10 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu,
|
||||
*/
|
||||
#define ID_HIDDEN(name) { \
|
||||
SYS_DESC(SYS_##name), \
|
||||
.access = access_raz_id_reg, \
|
||||
.get_user = get_raz_reg, \
|
||||
.set_user = set_raz_id_reg, \
|
||||
.access = access_id_reg, \
|
||||
.get_user = get_id_reg, \
|
||||
.set_user = set_id_reg, \
|
||||
.visibility = raz_visibility, \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1452,33 +1441,33 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
|
||||
/* AArch64 mappings of the AArch32 ID registers */
|
||||
/* CRm=1 */
|
||||
ID_SANITISED(ID_PFR0_EL1),
|
||||
ID_SANITISED(ID_PFR1_EL1),
|
||||
ID_SANITISED(ID_DFR0_EL1),
|
||||
AA32_ID_SANITISED(ID_PFR0_EL1),
|
||||
AA32_ID_SANITISED(ID_PFR1_EL1),
|
||||
AA32_ID_SANITISED(ID_DFR0_EL1),
|
||||
ID_HIDDEN(ID_AFR0_EL1),
|
||||
ID_SANITISED(ID_MMFR0_EL1),
|
||||
ID_SANITISED(ID_MMFR1_EL1),
|
||||
ID_SANITISED(ID_MMFR2_EL1),
|
||||
ID_SANITISED(ID_MMFR3_EL1),
|
||||
AA32_ID_SANITISED(ID_MMFR0_EL1),
|
||||
AA32_ID_SANITISED(ID_MMFR1_EL1),
|
||||
AA32_ID_SANITISED(ID_MMFR2_EL1),
|
||||
AA32_ID_SANITISED(ID_MMFR3_EL1),
|
||||
|
||||
/* CRm=2 */
|
||||
ID_SANITISED(ID_ISAR0_EL1),
|
||||
ID_SANITISED(ID_ISAR1_EL1),
|
||||
ID_SANITISED(ID_ISAR2_EL1),
|
||||
ID_SANITISED(ID_ISAR3_EL1),
|
||||
ID_SANITISED(ID_ISAR4_EL1),
|
||||
ID_SANITISED(ID_ISAR5_EL1),
|
||||
ID_SANITISED(ID_MMFR4_EL1),
|
||||
ID_SANITISED(ID_ISAR6_EL1),
|
||||
AA32_ID_SANITISED(ID_ISAR0_EL1),
|
||||
AA32_ID_SANITISED(ID_ISAR1_EL1),
|
||||
AA32_ID_SANITISED(ID_ISAR2_EL1),
|
||||
AA32_ID_SANITISED(ID_ISAR3_EL1),
|
||||
AA32_ID_SANITISED(ID_ISAR4_EL1),
|
||||
AA32_ID_SANITISED(ID_ISAR5_EL1),
|
||||
AA32_ID_SANITISED(ID_MMFR4_EL1),
|
||||
AA32_ID_SANITISED(ID_ISAR6_EL1),
|
||||
|
||||
/* CRm=3 */
|
||||
ID_SANITISED(MVFR0_EL1),
|
||||
ID_SANITISED(MVFR1_EL1),
|
||||
ID_SANITISED(MVFR2_EL1),
|
||||
AA32_ID_SANITISED(MVFR0_EL1),
|
||||
AA32_ID_SANITISED(MVFR1_EL1),
|
||||
AA32_ID_SANITISED(MVFR2_EL1),
|
||||
ID_UNALLOCATED(3,3),
|
||||
ID_SANITISED(ID_PFR2_EL1),
|
||||
AA32_ID_SANITISED(ID_PFR2_EL1),
|
||||
ID_HIDDEN(ID_DFR1_EL1),
|
||||
ID_SANITISED(ID_MMFR5_EL1),
|
||||
AA32_ID_SANITISED(ID_MMFR5_EL1),
|
||||
ID_UNALLOCATED(3,7),
|
||||
|
||||
/* AArch64 ID registers */
|
||||
@@ -2809,6 +2798,9 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
|
||||
if (!r)
|
||||
return -ENOENT;
|
||||
|
||||
if (sysreg_user_write_ignore(vcpu, r))
|
||||
return 0;
|
||||
|
||||
if (r->set_user) {
|
||||
ret = (r->set_user)(vcpu, r, val);
|
||||
} else {
|
||||
|
||||
@@ -86,6 +86,7 @@ struct sys_reg_desc {
|
||||
|
||||
#define REG_HIDDEN (1 << 0) /* hidden from userspace and guest */
|
||||
#define REG_RAZ (1 << 1) /* RAZ from userspace and guest */
|
||||
#define REG_USER_WI (1 << 2) /* WI from userspace only */
|
||||
|
||||
static __printf(2, 3)
|
||||
inline void print_sys_reg_msg(const struct sys_reg_params *p,
|
||||
@@ -136,22 +137,31 @@ static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r
|
||||
__vcpu_sys_reg(vcpu, r->reg) = r->val;
|
||||
}
|
||||
|
||||
static inline unsigned int sysreg_visibility(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
if (likely(!r->visibility))
|
||||
return 0;
|
||||
|
||||
return r->visibility(vcpu, r);
|
||||
}
|
||||
|
||||
static inline bool sysreg_hidden(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
if (likely(!r->visibility))
|
||||
return false;
|
||||
|
||||
return r->visibility(vcpu, r) & REG_HIDDEN;
|
||||
return sysreg_visibility(vcpu, r) & REG_HIDDEN;
|
||||
}
|
||||
|
||||
static inline bool sysreg_visible_as_raz(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
if (likely(!r->visibility))
|
||||
return false;
|
||||
return sysreg_visibility(vcpu, r) & REG_RAZ;
|
||||
}
|
||||
|
||||
return r->visibility(vcpu, r) & REG_RAZ;
|
||||
static inline bool sysreg_user_write_ignore(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
return sysreg_visibility(vcpu, r) & REG_USER_WI;
|
||||
}
|
||||
|
||||
static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
|
||||
|
||||
@@ -406,7 +406,7 @@ static void update_affinity_collection(struct kvm *kvm, struct vgic_its *its,
|
||||
struct its_ite *ite;
|
||||
|
||||
for_each_lpi_its(device, ite, its) {
|
||||
if (!ite->collection || coll != ite->collection)
|
||||
if (ite->collection != coll)
|
||||
continue;
|
||||
|
||||
update_affinity_ite(kvm, ite);
|
||||
|
||||
@@ -104,6 +104,7 @@ config RISCV
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select HAVE_POSIX_CPU_TIMERS_TASK_WORK
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_FUNCTION_ARG_ACCESS_API
|
||||
select HAVE_STACKPROTECTOR
|
||||
@@ -228,6 +229,9 @@ config RISCV_DMA_NONCOHERENT
|
||||
select ARCH_HAS_SETUP_DMA_OPS
|
||||
select DMA_DIRECT_REMAP
|
||||
|
||||
config AS_HAS_INSN
|
||||
def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
|
||||
|
||||
source "arch/riscv/Kconfig.socs"
|
||||
source "arch/riscv/Kconfig.erratas"
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
#define __ASM_GPR_NUM_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
.irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
|
||||
.equ .L__gpr_num_x\num, \num
|
||||
.endr
|
||||
|
||||
.equ .L__gpr_num_zero, 0
|
||||
.equ .L__gpr_num_ra, 1
|
||||
.equ .L__gpr_num_sp, 2
|
||||
@@ -39,6 +44,9 @@
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#define __DEFINE_ASM_GPR_NUMS \
|
||||
" .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31\n" \
|
||||
" .equ .L__gpr_num_x\\num, \\num\n" \
|
||||
" .endr\n" \
|
||||
" .equ .L__gpr_num_zero, 0\n" \
|
||||
" .equ .L__gpr_num_ra, 1\n" \
|
||||
" .equ .L__gpr_num_sp, 2\n" \
|
||||
|
||||
@@ -58,6 +58,7 @@ enum riscv_isa_ext_id {
|
||||
RISCV_ISA_EXT_ZICBOM,
|
||||
RISCV_ISA_EXT_ZIHINTPAUSE,
|
||||
RISCV_ISA_EXT_SSTC,
|
||||
RISCV_ISA_EXT_SVINVAL,
|
||||
RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
|
||||
};
|
||||
|
||||
@@ -69,6 +70,7 @@ enum riscv_isa_ext_id {
|
||||
enum riscv_isa_ext_key {
|
||||
RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */
|
||||
RISCV_ISA_EXT_KEY_ZIHINTPAUSE,
|
||||
RISCV_ISA_EXT_KEY_SVINVAL,
|
||||
RISCV_ISA_EXT_KEY_MAX,
|
||||
};
|
||||
|
||||
@@ -90,6 +92,8 @@ static __always_inline int riscv_isa_ext2key(int num)
|
||||
return RISCV_ISA_EXT_KEY_FPU;
|
||||
case RISCV_ISA_EXT_ZIHINTPAUSE:
|
||||
return RISCV_ISA_EXT_KEY_ZIHINTPAUSE;
|
||||
case RISCV_ISA_EXT_SVINVAL:
|
||||
return RISCV_ISA_EXT_KEY_SVINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
137
arch/riscv/include/asm/insn-def.h
Normal file
137
arch/riscv/include/asm/insn-def.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __ASM_INSN_DEF_H
|
||||
#define __ASM_INSN_DEF_H
|
||||
|
||||
#include <asm/asm.h>
|
||||
|
||||
#define INSN_R_FUNC7_SHIFT 25
|
||||
#define INSN_R_RS2_SHIFT 20
|
||||
#define INSN_R_RS1_SHIFT 15
|
||||
#define INSN_R_FUNC3_SHIFT 12
|
||||
#define INSN_R_RD_SHIFT 7
|
||||
#define INSN_R_OPCODE_SHIFT 0
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_AS_HAS_INSN
|
||||
|
||||
.macro insn_r, opcode, func3, func7, rd, rs1, rs2
|
||||
.insn r \opcode, \func3, \func7, \rd, \rs1, \rs2
|
||||
.endm
|
||||
|
||||
#else
|
||||
|
||||
#include <asm/gpr-num.h>
|
||||
|
||||
.macro insn_r, opcode, func3, func7, rd, rs1, rs2
|
||||
.4byte ((\opcode << INSN_R_OPCODE_SHIFT) | \
|
||||
(\func3 << INSN_R_FUNC3_SHIFT) | \
|
||||
(\func7 << INSN_R_FUNC7_SHIFT) | \
|
||||
(.L__gpr_num_\rd << INSN_R_RD_SHIFT) | \
|
||||
(.L__gpr_num_\rs1 << INSN_R_RS1_SHIFT) | \
|
||||
(.L__gpr_num_\rs2 << INSN_R_RS2_SHIFT))
|
||||
.endm
|
||||
|
||||
#endif
|
||||
|
||||
#define __INSN_R(...) insn_r __VA_ARGS__
|
||||
|
||||
#else /* ! __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_AS_HAS_INSN
|
||||
|
||||
#define __INSN_R(opcode, func3, func7, rd, rs1, rs2) \
|
||||
".insn r " opcode ", " func3 ", " func7 ", " rd ", " rs1 ", " rs2 "\n"
|
||||
|
||||
#else
|
||||
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/gpr-num.h>
|
||||
|
||||
#define DEFINE_INSN_R \
|
||||
__DEFINE_ASM_GPR_NUMS \
|
||||
" .macro insn_r, opcode, func3, func7, rd, rs1, rs2\n" \
|
||||
" .4byte ((\\opcode << " __stringify(INSN_R_OPCODE_SHIFT) ") |" \
|
||||
" (\\func3 << " __stringify(INSN_R_FUNC3_SHIFT) ") |" \
|
||||
" (\\func7 << " __stringify(INSN_R_FUNC7_SHIFT) ") |" \
|
||||
" (.L__gpr_num_\\rd << " __stringify(INSN_R_RD_SHIFT) ") |" \
|
||||
" (.L__gpr_num_\\rs1 << " __stringify(INSN_R_RS1_SHIFT) ") |" \
|
||||
" (.L__gpr_num_\\rs2 << " __stringify(INSN_R_RS2_SHIFT) "))\n" \
|
||||
" .endm\n"
|
||||
|
||||
#define UNDEFINE_INSN_R \
|
||||
" .purgem insn_r\n"
|
||||
|
||||
#define __INSN_R(opcode, func3, func7, rd, rs1, rs2) \
|
||||
DEFINE_INSN_R \
|
||||
"insn_r " opcode ", " func3 ", " func7 ", " rd ", " rs1 ", " rs2 "\n" \
|
||||
UNDEFINE_INSN_R
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ! __ASSEMBLY__ */
|
||||
|
||||
#define INSN_R(opcode, func3, func7, rd, rs1, rs2) \
|
||||
__INSN_R(RV_##opcode, RV_##func3, RV_##func7, \
|
||||
RV_##rd, RV_##rs1, RV_##rs2)
|
||||
|
||||
#define RV_OPCODE(v) __ASM_STR(v)
|
||||
#define RV_FUNC3(v) __ASM_STR(v)
|
||||
#define RV_FUNC7(v) __ASM_STR(v)
|
||||
#define RV_RD(v) __ASM_STR(v)
|
||||
#define RV_RS1(v) __ASM_STR(v)
|
||||
#define RV_RS2(v) __ASM_STR(v)
|
||||
#define __RV_REG(v) __ASM_STR(x ## v)
|
||||
#define RV___RD(v) __RV_REG(v)
|
||||
#define RV___RS1(v) __RV_REG(v)
|
||||
#define RV___RS2(v) __RV_REG(v)
|
||||
|
||||
#define RV_OPCODE_SYSTEM RV_OPCODE(115)
|
||||
|
||||
#define HFENCE_VVMA(vaddr, asid) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(17), \
|
||||
__RD(0), RS1(vaddr), RS2(asid))
|
||||
|
||||
#define HFENCE_GVMA(gaddr, vmid) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(49), \
|
||||
__RD(0), RS1(gaddr), RS2(vmid))
|
||||
|
||||
#define HLVX_HU(dest, addr) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(4), FUNC7(50), \
|
||||
RD(dest), RS1(addr), __RS2(3))
|
||||
|
||||
#define HLV_W(dest, addr) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(4), FUNC7(52), \
|
||||
RD(dest), RS1(addr), __RS2(0))
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define HLV_D(dest, addr) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(4), FUNC7(54), \
|
||||
RD(dest), RS1(addr), __RS2(0))
|
||||
#else
|
||||
#define HLV_D(dest, addr) \
|
||||
__ASM_STR(.error "hlv.d requires 64-bit support")
|
||||
#endif
|
||||
|
||||
#define SINVAL_VMA(vaddr, asid) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(11), \
|
||||
__RD(0), RS1(vaddr), RS2(asid))
|
||||
|
||||
#define SFENCE_W_INVAL() \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(12), \
|
||||
__RD(0), __RS1(0), __RS2(0))
|
||||
|
||||
#define SFENCE_INVAL_IR() \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(12), \
|
||||
__RD(0), __RS1(0), __RS2(1))
|
||||
|
||||
#define HINVAL_VVMA(vaddr, asid) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(19), \
|
||||
__RD(0), RS1(vaddr), RS2(asid))
|
||||
|
||||
#define HINVAL_GVMA(gaddr, vmid) \
|
||||
INSN_R(OPCODE_SYSTEM, FUNC3(0), FUNC7(51), \
|
||||
__RD(0), RS1(gaddr), RS2(vmid))
|
||||
|
||||
#endif /* __ASM_INSN_DEF_H */
|
||||
@@ -67,6 +67,7 @@ struct kvm_vcpu_stat {
|
||||
u64 mmio_exit_kernel;
|
||||
u64 csr_exit_user;
|
||||
u64 csr_exit_kernel;
|
||||
u64 signal_exits;
|
||||
u64 exits;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
#define KVM_SBI_IMPID 3
|
||||
|
||||
#define KVM_SBI_VERSION_MAJOR 0
|
||||
#define KVM_SBI_VERSION_MINOR 3
|
||||
#define KVM_SBI_VERSION_MAJOR 1
|
||||
#define KVM_SBI_VERSION_MINOR 0
|
||||
|
||||
struct kvm_vcpu_sbi_extension {
|
||||
unsigned long extid_start;
|
||||
|
||||
@@ -48,6 +48,7 @@ struct kvm_sregs {
|
||||
/* CONFIG registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
|
||||
struct kvm_riscv_config {
|
||||
unsigned long isa;
|
||||
unsigned long zicbom_block_size;
|
||||
};
|
||||
|
||||
/* CORE registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
|
||||
@@ -98,6 +99,9 @@ enum KVM_RISCV_ISA_EXT_ID {
|
||||
KVM_RISCV_ISA_EXT_M,
|
||||
KVM_RISCV_ISA_EXT_SVPBMT,
|
||||
KVM_RISCV_ISA_EXT_SSTC,
|
||||
KVM_RISCV_ISA_EXT_SVINVAL,
|
||||
KVM_RISCV_ISA_EXT_ZIHINTPAUSE,
|
||||
KVM_RISCV_ISA_EXT_ZICBOM,
|
||||
KVM_RISCV_ISA_EXT_MAX,
|
||||
};
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
|
||||
static struct riscv_isa_ext_data isa_ext_arr[] = {
|
||||
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
|
||||
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
|
||||
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
|
||||
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
|
||||
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
|
||||
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
|
||||
|
||||
@@ -204,6 +204,7 @@ void __init riscv_fill_hwcap(void)
|
||||
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
|
||||
SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE);
|
||||
SET_ISA_EXT_MAP("sstc", RISCV_ISA_EXT_SSTC);
|
||||
SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL);
|
||||
}
|
||||
#undef SET_ISA_EXT_MAP
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user