Import of kernel-4.18.0-553.147.1.el8_10

This commit is contained in:
almalinux-bot-kernel 2026-07-25 05:08:53 +00:00
parent 716d17b51c
commit 0dc80ff683
23 changed files with 348 additions and 230 deletions

View File

@ -12,7 +12,7 @@ RHEL_MINOR = 10
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 553.146.1
RHEL_RELEASE = 553.147.1
#
# ZSTREAM

View File

@ -280,10 +280,29 @@ EXPORT_SYMBOL_GPL(fpu_enable_guest_xfd_features);
#ifdef CONFIG_X86_64
void fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xfd)
{
struct fpstate *fpstate = guest_fpu->fpstate;
fpregs_lock();
guest_fpu->fpstate->xfd = xfd;
if (guest_fpu->fpstate->in_use)
xfd_update_state(guest_fpu->fpstate);
/*
* KVM's guest ABI is that setting XFD[i]=1 *can* immediately revert the
* save state to its initial configuration. Likewise, KVM_GET_XSAVE does
* the same as XSAVE and returns XSTATE_BV[i]=0 whenever XFD[i]=1.
*
* If the guest's FPU state is in hardware, just update XFD: the XSAVE
* in fpu_swap_kvm_fpstate will clear XSTATE_BV[i] whenever XFD[i]=1.
*
* If however the guest's FPU state is NOT resident in hardware, clear
* disabled components in XSTATE_BV now, or a subsequent XRSTOR will
* attempt to load disabled components and generate #NM _in the host_.
*/
if (xfd && test_thread_flag(TIF_NEED_FPU_LOAD))
fpstate->regs.xsave.header.xfeatures &= ~xfd;
fpstate->xfd = xfd;
if (fpstate->in_use)
xfd_update_state(fpstate);
fpregs_unlock();
}
EXPORT_SYMBOL_GPL(fpu_update_guest_xfd);
@ -391,6 +410,13 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
if (ustate->xsave.header.xfeatures & ~xcr0)
return -EINVAL;
/*
* Disabled features must be in their initial state, otherwise XRSTOR
* causes an exception.
*/
if (WARN_ON_ONCE(ustate->xsave.header.xfeatures & kstate->xfd))
return -EINVAL;
/*
* Nullify @vpkru to preserve its current value if PKRU's bit isn't set
* in the header. KVM's odd ABI is to leave PKRU untouched in this

View File

@ -5141,12 +5141,11 @@ void init_decode_cache(struct x86_emulate_ctxt *ctxt)
ctxt->mem_read.end = 0;
}
int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts)
{
const struct x86_emulate_ops *ops = ctxt->ops;
int rc = X86EMUL_CONTINUE;
int saved_dst_type = ctxt->dst.type;
unsigned emul_flags;
ctxt->mem_read.pos = 0;
@ -5161,7 +5160,6 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
goto done;
}
emul_flags = ctxt->ops->get_hflags(ctxt);
if (unlikely(ctxt->d &
(No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
@ -5195,7 +5193,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
fetch_possible_mmx_operand(&ctxt->dst);
}
if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) {
if (unlikely(check_intercepts) && ctxt->intercept) {
rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_PRE_EXCEPT);
if (rc != X86EMUL_CONTINUE)
@ -5224,7 +5222,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
goto done;
}
if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
if (unlikely(check_intercepts) && (ctxt->d & Intercept)) {
rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_POST_EXCEPT);
if (rc != X86EMUL_CONTINUE)
@ -5278,7 +5276,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
special_insn:
if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
if (unlikely(check_intercepts) && (ctxt->d & Intercept)) {
rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_POST_MEMACCESS);
if (rc != X86EMUL_CONTINUE)

View File

@ -492,7 +492,7 @@ bool x86_page_table_writing_insn(struct x86_emulate_ctxt *ctxt);
#define EMULATION_RESTART 1
#define EMULATION_INTERCEPTED 2
void init_decode_cache(struct x86_emulate_ctxt *ctxt);
int x86_emulate_insn(struct x86_emulate_ctxt *ctxt);
int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts);
int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
u16 tss_selector, int idt_index, int reason,
bool has_error_code, u32 error_code);

View File

@ -4079,22 +4079,23 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
if (handle_abnormal_pfn(vcpu, fault, ACC_ALL, &r))
return r;
r = RET_PF_RETRY;
if (is_tdp_mmu_fault)
read_lock(&vcpu->kvm->mmu_lock);
else
else {
write_lock(&vcpu->kvm->mmu_lock);
r = make_mmu_pages_available(vcpu);
if (r)
goto out_unlock;
}
if (is_page_fault_stale(vcpu, fault, mmu_seq))
if (is_page_fault_stale(vcpu, fault, mmu_seq)) {
r = RET_PF_RETRY;
goto out_unlock;
}
if (is_tdp_mmu_fault) {
r = kvm_tdp_mmu_map(vcpu, fault);
} else {
r = make_mmu_pages_available(vcpu);
if (r)
goto out_unlock;
r = __direct_map(vcpu, fault);
}
@ -6044,13 +6045,19 @@ restart:
pfn = spte_to_pfn(*sptep);
/*
* We cannot do huge page mapping for indirect shadow pages,
* which are found on the last rmap (level = 1) when not using
* tdp; such shadow pages are synced with the page table in
* the guest, and the guest page table is using 4K page size
* mapping if the indirect sp has level = 1.
* Direct shadow page can be replaced by a hugepage if the host
* mapping level allows it and the memslot maps all of the host
* hugepage. Note! If the memslot maps only part of the
* hugepage, sp->gfn may be below slot->base_gfn, and querying
* the max mapping level would cause an out-of-bounds lpage_info
* access. So the gfn bounds check *must* be done first.
*
* Indirect shadow pages are created when the guest page tables
* are using 4K pages. Since the host mapping is always
* constrained by the page size in the guest, indirect shadow
* pages are never collapsible.
*/
if (sp->role.direct && !kvm_is_reserved_pfn(pfn) &&
if (sp->role.direct && !kvm_is_reserved_pfn(pfn) && is_gfn_in_memslot(slot, sp->gfn) &&
sp->role.level < kvm_mmu_max_mapping_level(kvm, slot, sp->gfn,
pfn, PG_LEVEL_NUM)) {
pte_list_remove(kvm, rmap_head, sptep);

View File

@ -893,15 +893,17 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
walker.pte_access &= ~ACC_EXEC_MASK;
}
r = RET_PF_RETRY;
write_lock(&vcpu->kvm->mmu_lock);
if (is_page_fault_stale(vcpu, fault, mmu_seq))
goto out_unlock;
r = make_mmu_pages_available(vcpu);
if (r)
goto out_unlock;
if (is_page_fault_stale(vcpu, fault, mmu_seq)) {
r = RET_PF_RETRY;
goto out_unlock;
}
r = FNAME(fetch)(vcpu, fault, &walker);
out_unlock:

View File

@ -154,7 +154,7 @@ TRACE_EVENT(kvm_xen_hypercall,
TRACE_EVENT(kvm_pio,
TP_PROTO(unsigned int rw, unsigned int port, unsigned int size,
unsigned int count, void *data),
unsigned int count, const void *data),
TP_ARGS(rw, port, size, count, data),
TP_STRUCT__entry(

View File

@ -280,6 +280,21 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
vcpu->arch.regs_dirty = 0;
}
static void nested_put_vmcs12_pages(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
/*
* Unpin physical memory we referred to in the vmcs02. The APIC access
* page's backing page (yeah, confusing) shouldn't actually be accessed,
* and if it is written, the contents are irrelevant.
*/
kvm_vcpu_unmap(vcpu, &vmx->nested.apic_access_page_map, false);
kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);
kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map, true);
vmx->nested.pi_desc = NULL;
}
/*
* Free whatever needs to be freed from vmx->nested when L1 goes down, or
* just stops using VMX.
@ -287,6 +302,7 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
static void free_nested(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
struct vmcs *shadow_vmcs;
if (WARN_ON_ONCE(vmx->loaded_vmcs != &vmx->vmcs01))
vmx_switch_vmcs(vcpu, &vmx->vmcs01);
@ -304,22 +320,22 @@ static void free_nested(struct kvm_vcpu *vcpu)
vmx->nested.current_vmptr = INVALID_GPA;
if (enable_shadow_vmcs) {
vmx_disable_shadow_vmcs(vmx);
vmcs_clear(vmx->vmcs01.shadow_vmcs);
free_vmcs(vmx->vmcs01.shadow_vmcs);
/*
* Keep the pointer visible until after VMCLEAR, so migration
* can clear an active shadow VMCS on the old CPU.
*/
shadow_vmcs = vmx->vmcs01.shadow_vmcs;
vmcs_clear(shadow_vmcs);
vmx->vmcs01.shadow_vmcs = NULL;
free_vmcs(shadow_vmcs);
}
kfree(vmx->nested.cached_vmcs12);
vmx->nested.cached_vmcs12 = NULL;
kfree(vmx->nested.cached_shadow_vmcs12);
vmx->nested.cached_shadow_vmcs12 = NULL;
/* Unpin physical memory we referred to in the vmcs02 */
if (vmx->nested.apic_access_page) {
kvm_release_page_clean(vmx->nested.apic_access_page);
vmx->nested.apic_access_page = NULL;
}
kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);
kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map, true);
vmx->nested.pi_desc = NULL;
nested_put_vmcs12_pages(vcpu);
kvm_mmu_free_roots(vcpu->kvm, &vcpu->arch.guest_mmu, KVM_MMU_ROOTS_ALL);
@ -3172,8 +3188,6 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
struct vcpu_vmx *vmx = to_vmx(vcpu);
struct kvm_host_map *map;
struct page *page;
u64 hpa;
if (!vcpu->arch.pdptrs_from_userspace &&
!nested_cpu_has_ept(vmcs12) && is_pae_paging(vcpu)) {
@ -3188,23 +3202,12 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
/*
* Translate L1 physical address to host physical
* address for vmcs02. Keep the page pinned, so this
* physical address remains valid. We keep a reference
* to it so we can release it later.
*/
if (vmx->nested.apic_access_page) { /* shouldn't happen */
kvm_release_page_clean(vmx->nested.apic_access_page);
vmx->nested.apic_access_page = NULL;
}
page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->apic_access_addr);
if (!is_error_page(page)) {
vmx->nested.apic_access_page = page;
hpa = page_to_phys(vmx->nested.apic_access_page);
vmcs_write64(APIC_ACCESS_ADDR, hpa);
map = &vmx->nested.apic_access_page_map;
if (!kvm_vcpu_map(vcpu, gpa_to_gfn(vmcs12->apic_access_addr), map)) {
vmcs_write64(APIC_ACCESS_ADDR, pfn_to_hpa(map->pfn));
} else {
pr_debug_ratelimited("%s: no backing 'struct page' for APIC-access address in vmcs12\n",
pr_debug_ratelimited("%s: no backing for APIC-access address in vmcs12\n",
__func__);
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
vcpu->run->internal.suberror =
@ -3515,6 +3518,8 @@ vmentry_fail_vmexit:
if (!from_vmentry)
return NVMX_VMENTRY_VMEXIT;
nested_put_vmcs12_pages(vcpu);
load_vmcs12_host_state(vcpu, vmcs12);
vmcs12->vm_exit_reason = exit_reason.full;
if (enable_shadow_vmcs || evmptr_is_valid(vmx->nested.hv_evmcs_vmptr))
@ -4650,14 +4655,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
vmx_update_cpu_dirty_logging(vcpu);
}
/* Unpin physical memory we referred to in vmcs02 */
if (vmx->nested.apic_access_page) {
kvm_release_page_clean(vmx->nested.apic_access_page);
vmx->nested.apic_access_page = NULL;
}
kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);
kvm_vcpu_unmap(vcpu, &vmx->nested.pi_desc_map, true);
vmx->nested.pi_desc = NULL;
nested_put_vmcs12_pages(vcpu);
if (vmx->nested.reload_vmcs01_apic_access_page) {
vmx->nested.reload_vmcs01_apic_access_page = false;

View File

@ -205,7 +205,7 @@ struct nested_vmx {
* Guest pages referred to in the vmcs02 with host-physical
* pointers, so we must keep them pinned while L2 runs.
*/
struct page *apic_access_page;
struct kvm_host_map apic_access_page_map;
struct kvm_host_map virtual_apic_map;
struct kvm_host_map pi_desc_map;

View File

@ -5126,9 +5126,18 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
struct kvm_xsave *guest_xsave)
{
union fpregs_state *xstate = (union fpregs_state *)guest_xsave->region;
if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
return 0;
/*
* For backwards compatibility, do not expect disabled features to be in
* their initial state. XSTATE_BV[i] must still be cleared whenever
* XFD[i]=1, or XRSTOR would cause a #NM.
*/
xstate->xsave.header.xfeatures &= ~vcpu->arch.guest_fpu.fpstate->xfd;
return fpu_copy_uabi_to_guest_fpstate(&vcpu->arch.guest_fpu,
guest_xsave->region,
supported_xcr0, &vcpu->arch.pkru);
@ -7380,36 +7389,47 @@ emul_write:
return emulator_write_emulated(ctxt, addr, new, bytes, exception);
}
static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
{
int r = 0, i;
for (i = 0; i < vcpu->arch.pio.count; i++) {
if (vcpu->arch.pio.in)
r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
vcpu->arch.pio.size, pd);
else
r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
vcpu->arch.pio.port, vcpu->arch.pio.size,
pd);
if (r)
break;
pd += vcpu->arch.pio.size;
}
return r;
}
static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
unsigned short port,
unsigned short port, void *data,
unsigned int count, bool in)
{
unsigned i;
int r;
WARN_ON_ONCE(vcpu->arch.pio.count);
for (i = 0; i < count; i++) {
if (in)
r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, port, size, data);
else
r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, port, size, data);
if (r) {
if (i == 0)
goto userspace_io;
/*
* Userspace must have unregistered the device while PIO
* was running. Drop writes / read as 0.
*/
if (in)
memset(data, 0, size * (count - i));
break;
}
data += size;
}
return 1;
userspace_io:
vcpu->arch.pio.port = port;
vcpu->arch.pio.in = in;
vcpu->arch.pio.count = count;
vcpu->arch.pio.count = count;
vcpu->arch.pio.size = size;
if (!kernel_pio(vcpu, vcpu->arch.pio_data))
return 1;
if (in)
memset(vcpu->arch.pio_data, 0, size * count);
else
memcpy(vcpu->arch.pio_data, data, size * count);
vcpu->run->exit_reason = KVM_EXIT_IO;
vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
@ -7417,22 +7437,23 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE;
vcpu->run->io.count = count;
vcpu->run->io.port = port;
return 0;
}
static int __emulator_pio_in(struct kvm_vcpu *vcpu, int size,
unsigned short port, unsigned int count)
unsigned short port, void *val, unsigned int count)
{
WARN_ON(vcpu->arch.pio.count);
memset(vcpu->arch.pio_data, 0, size * count);
return emulator_pio_in_out(vcpu, size, port, count, true);
int r = emulator_pio_in_out(vcpu, size, port, val, count, true);
if (r)
trace_kvm_pio(KVM_PIO_IN, port, size, count, val);
return r;
}
static void complete_emulator_pio_in(struct kvm_vcpu *vcpu, void *val)
{
int size = vcpu->arch.pio.size;
unsigned count = vcpu->arch.pio.count;
unsigned int count = vcpu->arch.pio.count;
memcpy(val, vcpu->arch.pio_data, size * count);
trace_kvm_pio(KVM_PIO_IN, vcpu->arch.pio.port, size, count, vcpu->arch.pio_data);
vcpu->arch.pio.count = 0;
@ -7449,16 +7470,11 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size,
* shenanigans as KVM doesn't support modifying the rep count,
* and the emulator ensures @count doesn't overflow the buffer.
*/
} else {
int r = __emulator_pio_in(vcpu, size, port, count);
if (!r)
return r;
/* Results already available, fall through. */
complete_emulator_pio_in(vcpu, val);
return 1;
}
complete_emulator_pio_in(vcpu, val);
return 1;
return __emulator_pio_in(vcpu, size, port, val, count);
}
static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt,
@ -7473,15 +7489,8 @@ static int emulator_pio_out(struct kvm_vcpu *vcpu, int size,
unsigned short port, const void *val,
unsigned int count)
{
int ret;
memcpy(vcpu->arch.pio_data, val, size * count);
trace_kvm_pio(KVM_PIO_OUT, port, size, count, vcpu->arch.pio_data);
ret = emulator_pio_in_out(vcpu, size, port, count, false);
if (ret)
vcpu->arch.pio.count = 0;
return ret;
trace_kvm_pio(KVM_PIO_OUT, port, size, count, val);
return emulator_pio_in_out(vcpu, size, port, (void *)val, count, false);
}
static int emulator_pio_out_emulated(struct x86_emulate_ctxt *ctxt,
@ -8474,7 +8483,14 @@ restart:
ctxt->exception.address = 0;
}
r = x86_emulate_insn(ctxt);
/*
* Check L1's instruction intercepts when emulating instructions for
* L2, unless KVM is re-emulating a previously decoded instruction,
* e.g. to complete userspace I/O, in which case KVM has already
* checked the intercepts.
*/
r = x86_emulate_insn(ctxt, is_guest_mode(vcpu) &&
!(emulation_type & EMULTYPE_NO_DECODE));
if (r == EMULATION_INTERCEPTED)
return 1;
@ -12754,7 +12770,7 @@ static int kvm_sev_es_outs(struct kvm_vcpu *vcpu, unsigned int size,
/* memcpy done already by emulator_pio_out. */
vcpu->arch.sev_pio_count -= count;
vcpu->arch.sev_pio_data += count * vcpu->arch.pio.size;
vcpu->arch.sev_pio_data += count * size;
if (!ret)
break;
@ -12770,20 +12786,20 @@ static int kvm_sev_es_outs(struct kvm_vcpu *vcpu, unsigned int size,
static int kvm_sev_es_ins(struct kvm_vcpu *vcpu, unsigned int size,
unsigned int port);
static void advance_sev_es_emulated_ins(struct kvm_vcpu *vcpu)
static void advance_sev_es_emulated_ins(struct kvm_vcpu *vcpu, unsigned count, int size)
{
unsigned count = vcpu->arch.pio.count;
complete_emulator_pio_in(vcpu, vcpu->arch.sev_pio_data);
vcpu->arch.sev_pio_count -= count;
vcpu->arch.sev_pio_data += count * vcpu->arch.pio.size;
vcpu->arch.sev_pio_data += count * size;
}
static int complete_sev_es_emulated_ins(struct kvm_vcpu *vcpu)
{
unsigned count = vcpu->arch.pio.count;
int size = vcpu->arch.pio.size;
int port = vcpu->arch.pio.port;
advance_sev_es_emulated_ins(vcpu);
complete_emulator_pio_in(vcpu, vcpu->arch.sev_pio_data);
advance_sev_es_emulated_ins(vcpu, count, size);
if (vcpu->arch.sev_pio_count)
return kvm_sev_es_ins(vcpu, size, port);
return 1;
@ -12795,11 +12811,11 @@ static int kvm_sev_es_ins(struct kvm_vcpu *vcpu, unsigned int size,
for (;;) {
unsigned int count =
min_t(unsigned int, PAGE_SIZE / size, vcpu->arch.sev_pio_count);
if (!__emulator_pio_in(vcpu, size, port, count))
if (!__emulator_pio_in(vcpu, size, port, vcpu->arch.sev_pio_data, count))
break;
/* Emulation done by the kernel. */
advance_sev_es_emulated_ins(vcpu);
advance_sev_es_emulated_ins(vcpu, count, size);
if (!vcpu->arch.sev_pio_count)
return 1;
}

View File

@ -368,7 +368,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
struct log_c *lc;
uint32_t region_size;
unsigned int region_count;
sector_t region_count;
size_t bitset_size, buf_size;
int r;
char dummy;
@ -397,6 +397,10 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
}
region_count = dm_sector_div_up(ti->len, region_size);
if (region_count > UINT_MAX) {
DMWARN("region count exceeds limit of %u", UINT_MAX);
return -EINVAL;
}
lc = kmalloc(sizeof(*lc), GFP_KERNEL);
if (!lc) {

View File

@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/rational.h>
#include <linux/util_macros.h>
#include <linux/dma/hsu.h>
#include <linux/8250_pci.h>
@ -364,8 +365,16 @@ static const struct mid8250_board dnv_board = {
.flags = FL_BASE1,
.freq = 133333333,
.base_baud = 115200,
.setup = dnv_setup,
.exit = dnv_exit,
/*
* Errata:
* HSUART May Stop Functioning when DMA is Active.
*
* - Denverton document #572409, rev 3.4, DNV60
* - Ice Lake Xeon D document #714070, ICXD65
* - Snowridge document #731931, SNR44
*/
.setup = PTR_IF(false, dnv_setup),
.exit = PTR_IF(false, dnv_exit),
};
#define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board }

View File

@ -1635,8 +1635,13 @@ static int do_umount(struct mount *mnt, int flags)
namespace_lock();
lock_mount_hash();
event++;
/* Recheck MNT_LOCKED with the locks held */
retval = -EINVAL;
if (mnt->mnt.mnt_flags & MNT_LOCKED)
goto out;
event++;
if (flags & MNT_DETACH) {
if (!list_empty(&mnt->mnt_list))
umount_tree(mnt, UMOUNT_PROPAGATE);
@ -1650,6 +1655,7 @@ static int do_umount(struct mount *mnt, int flags)
retval = 0;
}
}
out:
unlock_mount_hash();
namespace_unlock();
return retval;
@ -1740,7 +1746,7 @@ int ksys_umount(char __user *name, int flags)
goto dput_and_out;
if (!check_mnt(mnt))
goto dput_and_out;
if (mnt->mnt.mnt_flags & MNT_LOCKED)
if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
goto dput_and_out;
retval = -EPERM;
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
@ -1823,8 +1829,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
for (s = r; s; s = next_mnt(s, r)) {
if (!(flag & CL_COPY_UNBINDABLE) &&
IS_MNT_UNBINDABLE(s)) {
s = skip_mnt_tree(s);
continue;
if (s->mnt.mnt_flags & MNT_LOCKED) {
/* Both unbindable and locked. */
q = ERR_PTR(-EPERM);
goto out;
} else {
s = skip_mnt_tree(s);
continue;
}
}
if (!(flag & CL_COPY_MNT_NS_FILE) &&
is_mnt_ns_file(s->mnt.mnt_root)) {
@ -1898,7 +1910,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
{
namespace_lock();
lock_mount_hash();
umount_tree(real_mount(mnt), UMOUNT_SYNC);
umount_tree(real_mount(mnt), 0);
unlock_mount_hash();
namespace_unlock();
}

View File

@ -35,17 +35,36 @@
#include "xfs_ag.h"
static DEFINE_MUTEX(xfs_uuid_table_mutex);
static int xfs_uuid_table_size;
static uuid_t *xfs_uuid_table;
static DEFINE_XARRAY_ALLOC(xfs_uuid_table);
static uuid_t *
xfs_uuid_search(
uuid_t *new_uuid)
{
unsigned long index = 0;
uuid_t *uuid;
xa_for_each(&xfs_uuid_table, index, uuid) {
if (uuid_equal(uuid, new_uuid))
return uuid;
}
return NULL;
}
static void
xfs_uuid_delete(
uuid_t *uuid,
unsigned int index)
{
ASSERT(uuid_equal(xa_load(&xfs_uuid_table, index), uuid));
xa_erase(&xfs_uuid_table, index);
}
void
xfs_uuid_table_free(void)
{
if (xfs_uuid_table_size == 0)
return;
kmem_free(xfs_uuid_table);
xfs_uuid_table = NULL;
xfs_uuid_table_size = 0;
ASSERT(xa_empty(&xfs_uuid_table));
xa_destroy(&xfs_uuid_table);
}
/*
@ -57,7 +76,7 @@ xfs_uuid_mount(
struct xfs_mount *mp)
{
uuid_t *uuid = &mp->m_sb.sb_uuid;
int hole, i;
int ret;
/* Publish UUID in struct super_block */
uuid_copy(&mp->m_super->s_uuid, uuid);
@ -71,30 +90,17 @@ xfs_uuid_mount(
}
mutex_lock(&xfs_uuid_table_mutex);
for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) {
if (uuid_is_null(&xfs_uuid_table[i])) {
hole = i;
continue;
}
if (uuid_equal(uuid, &xfs_uuid_table[i]))
goto out_duplicate;
if (unlikely(xfs_uuid_search(uuid))) {
xfs_warn(mp, "Filesystem has duplicate UUID %pU - can't mount",
uuid);
mutex_unlock(&xfs_uuid_table_mutex);
return -EINVAL;
}
if (hole < 0) {
xfs_uuid_table = krealloc(xfs_uuid_table,
(xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table),
GFP_KERNEL | __GFP_NOFAIL);
hole = xfs_uuid_table_size++;
}
xfs_uuid_table[hole] = *uuid;
ret = xa_alloc(&xfs_uuid_table, &mp->m_uuid_table_index, uuid,
xa_limit_32b, GFP_KERNEL);
mutex_unlock(&xfs_uuid_table_mutex);
return 0;
out_duplicate:
mutex_unlock(&xfs_uuid_table_mutex);
xfs_warn(mp, "Filesystem has duplicate UUID %pU - can't mount", uuid);
return -EINVAL;
return ret;
}
STATIC void
@ -102,21 +108,12 @@ xfs_uuid_unmount(
struct xfs_mount *mp)
{
uuid_t *uuid = &mp->m_sb.sb_uuid;
int i;
if (mp->m_flags & XFS_MOUNT_NOUUID)
return;
mutex_lock(&xfs_uuid_table_mutex);
for (i = 0; i < xfs_uuid_table_size; i++) {
if (uuid_is_null(&xfs_uuid_table[i]))
continue;
if (!uuid_equal(uuid, &xfs_uuid_table[i]))
continue;
memset(&xfs_uuid_table[i], 0, sizeof(uuid_t));
break;
}
ASSERT(i < xfs_uuid_table_size);
xfs_uuid_delete(uuid, mp->m_uuid_table_index);
mutex_unlock(&xfs_uuid_table_mutex);
}

View File

@ -221,6 +221,9 @@ typedef struct xfs_mount {
unsigned int *m_errortag;
struct xfs_kobj m_errortag_kobj;
#endif
/* Index of uuid record in the uuid xarray. */
unsigned int m_uuid_table_index;
} xfs_mount_t;
#define M_IGEO(mp) (&(mp)->m_ino_geo)

View File

@ -1454,6 +1454,11 @@ int kvm_request_irq_source_id(struct kvm *kvm);
void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args);
static inline bool is_gfn_in_memslot(const struct kvm_memory_slot *slot, gfn_t gfn)
{
return gfn >= slot->base_gfn && gfn < slot->base_gfn + slot->npages;
}
/*
* Returns a pointer to the memslot if it contains gfn.
* Otherwise returns NULL.
@ -1464,7 +1469,7 @@ try_get_memslot(struct kvm_memory_slot *slot, gfn_t gfn)
if (!slot)
return NULL;
if (gfn >= slot->base_gfn && gfn < slot->base_gfn + slot->npages)
if (is_gfn_in_memslot(slot, gfn))
return slot;
else
return NULL;

View File

@ -1,2 +1,2 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
kernel.centos,1,Red Hat,kernel-core,4.18.0-553.146.1.el8.x86_64,mailto:secalert@redhat.com
kernel.centos,1,Red Hat,kernel-core,4.18.0-553.147.1.el8.x86_64,mailto:secalert@redhat.com

View File

@ -453,8 +453,8 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
return err;
}
if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
if (ALIGN(skb->data_len + tailen, L1_CACHE_BYTES) >
PAGE_SIZE)
goto cow;
if (!skb_cloned(skb)) {

View File

@ -500,8 +500,8 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
return err;
}
if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
if (ALIGN(skb->data_len + tailen, L1_CACHE_BYTES) >
PAGE_SIZE)
goto cow;
if (!skb_cloned(skb)) {

View File

@ -183,8 +183,20 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
if (fragid == LAST_FRAGMENT) {
TIPC_SKB_CB(head)->validated = 0;
if (unlikely(!tipc_msg_validate(&head)))
/* If the reassembled skb has been freed in
* tipc_msg_validate() because of an invalid truesize,
* then head will point to a newly allocated reassembled
* skb, while *headbuf points to freed reassembled skb.
* In such cases, correct *headbuf for freeing the newly
* allocated reassembled skb later.
*/
if (unlikely(!tipc_msg_validate(&head))) {
if (head != *headbuf)
*headbuf = head;
goto err;
}
*buf = head;
TIPC_SKB_CB(head)->tail = NULL;
*headbuf = NULL;

View File

@ -405,6 +405,7 @@ static inline unsigned int x86_model(unsigned int eax)
return ((eax >> 12) & 0xf0) | ((eax >> 4) & 0x0f);
}
void vcpu_xsave_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_xsave *xstate);
struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid);
void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_x86_state *state);

View File

@ -1179,6 +1179,16 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
return state;
}
void vcpu_xsave_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_xsave *xstate)
{
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
int r;
r = ioctl(vcpu->fd, KVM_SET_XSAVE, xstate);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i",
r);
}
void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state)
{
struct vcpu *vcpu = vcpu_find(vm, vcpuid);

View File

@ -252,6 +252,20 @@ static void init_regs(void)
__xsetbv(0x0, xcr0);
}
enum {
/* Retrieve TMM0 from guest, stash it for TEST_RESTORE_TILEDATA */
TEST_SAVE_TILEDATA = 1,
/* Check TMM0 against tiledata */
TEST_COMPARE_TILEDATA = 2,
/* Restore TMM0 from earlier save */
TEST_RESTORE_TILEDATA = 4,
/* Full VM save/restore */
TEST_SAVE_RESTORE = 8,
};
static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
struct tile_data *tiledata,
struct xsave_data *xsave_data)
@ -268,20 +282,29 @@ static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
GUEST_ASSERT(xtile.bytes_per_tile == 1024);
GUEST_ASSERT(xtile.bytes_per_row == 64);
GUEST_ASSERT(xtile.max_rows == 16);
GUEST_SYNC(1);
GUEST_SYNC(TEST_SAVE_RESTORE);
/* xfd=0, enable amx */
wrmsr(MSR_IA32_XFD, 0);
GUEST_SYNC(2);
GUEST_SYNC(TEST_SAVE_RESTORE);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD) == 0);
set_tilecfg(amx_cfg);
__ldtilecfg(amx_cfg);
GUEST_SYNC(3);
GUEST_SYNC(TEST_SAVE_RESTORE);
/* Check save/restore when trap to userspace */
__tileloadd(tiledata);
GUEST_SYNC(4);
GUEST_SYNC(TEST_SAVE_TILEDATA | TEST_COMPARE_TILEDATA | TEST_SAVE_RESTORE);
/* xfd=0x40000, disable amx tiledata */
wrmsr(MSR_IA32_XFD, XFEATURE_MASK_XTILEDATA);
/* host tries setting tiledata while guest XFD is set */
GUEST_SYNC(TEST_RESTORE_TILEDATA);
GUEST_SYNC(TEST_SAVE_RESTORE);
wrmsr(MSR_IA32_XFD, 0);
__tilerelease();
GUEST_SYNC(5);
GUEST_SYNC(TEST_SAVE_RESTORE);
/* bit 18 not in the XCOMP_BV after xsavec() */
set_xstatebv(xsave_data, XFEATURE_MASK_XTILEDATA);
__xsavec(xsave_data, XFEATURE_MASK_XTILEDATA);
@ -289,13 +312,13 @@ static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
/* xfd=0x40000, disable amx tiledata */
wrmsr(MSR_IA32_XFD, XFEATURE_MASK_XTILEDATA);
GUEST_SYNC(6);
GUEST_SYNC(TEST_SAVE_RESTORE);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD) == XFEATURE_MASK_XTILEDATA);
set_tilecfg(amx_cfg);
__ldtilecfg(amx_cfg);
/* Trigger #NM exception */
__tileloadd(tiledata);
GUEST_SYNC(10);
GUEST_SYNC(TEST_COMPARE_TILEDATA | TEST_SAVE_RESTORE);
GUEST_DONE();
}
@ -303,15 +326,15 @@ static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
void guest_nm_handler(struct ex_regs *regs)
{
/* Check if #NM is triggered by XFEATURE_MASK_XTILEDATA */
GUEST_SYNC(7);
GUEST_SYNC(TEST_SAVE_RESTORE);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD_ERR) == XFEATURE_MASK_XTILEDATA);
GUEST_SYNC(8);
GUEST_SYNC(TEST_SAVE_RESTORE);
GUEST_ASSERT(rdmsr(MSR_IA32_XFD_ERR) == XFEATURE_MASK_XTILEDATA);
/* Clear xfd_err */
wrmsr(MSR_IA32_XFD_ERR, 0);
/* xfd=0, enable amx */
wrmsr(MSR_IA32_XFD, 0);
GUEST_SYNC(9);
GUEST_SYNC(TEST_SAVE_RESTORE);
}
int main(int argc, char *argv[])
@ -322,11 +345,11 @@ int main(int argc, char *argv[])
struct kvm_vm *vm;
struct kvm_run *run;
struct kvm_x86_state *state;
struct kvm_x86_state *tile_state = NULL;
int xsave_restore_size = 0;
vm_vaddr_t amx_cfg, tiledata, xsavedata;
struct ucall uc;
u32 amx_offset;
int stage, ret;
int ret;
vm_xsave_req_perm(XSTATE_XTILE_DATA_BIT);
@ -371,11 +394,12 @@ int main(int argc, char *argv[])
memset(addr_gva2hva(vm, xsavedata), 0, 3 * getpagesize());
vcpu_args_set(vm, VCPU_ID, 3, amx_cfg, tiledata, xsavedata);
for (stage = 1; ; stage++) {
int iter = 0;
for (;;) {
_vcpu_run(vm, VCPU_ID);
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
"Stage %d: unexpected exit reason: %u (%s),\n",
stage, run->exit_reason,
iter, run->exit_reason,
exit_reason_str(run->exit_reason));
switch (get_ucall(vm, VCPU_ID, &uc)) {
@ -384,37 +408,50 @@ int main(int argc, char *argv[])
__FILE__, uc.args[1]);
/* NOT REACHED */
case UCALL_SYNC:
switch (uc.args[1]) {
case 1:
case 2:
case 3:
case 5:
case 6:
case 7:
case 8:
fprintf(stderr, "GUEST_SYNC(%ld)\n", uc.args[1]);
break;
case 4:
case 10:
fprintf(stderr,
"GUEST_SYNC(%ld), check save/restore status\n", uc.args[1]);
++iter;
if (uc.args[1] & TEST_SAVE_TILEDATA) {
fprintf(stderr, "GUEST_SYNC #%d, save tiledata\n", iter);
tile_state = vcpu_save_state(vm, VCPU_ID);
}
if (uc.args[1] & TEST_COMPARE_TILEDATA) {
fprintf(stderr, "GUEST_SYNC #%d, check TMM0 contents\n", iter);
/* Compacted mode, get amx offset by xsave area
* size subtract 8K amx size.
*/
amx_offset = xsave_restore_size - NUM_TILES*TILE_SIZE;
state = vcpu_save_state(vm, VCPU_ID);
void *amx_start = (void *)state->xsave + amx_offset;
u32 amx_offset = xsave_restore_size - NUM_TILES*TILE_SIZE;
void *amx_start = (void *)tile_state->xsave + amx_offset;
void *tiles_data = (void *)addr_gva2hva(vm, tiledata);
/* Only check TMM0 register, 1 tile */
ret = memcmp(amx_start, tiles_data, TILE_SIZE);
TEST_ASSERT(ret == 0, "memcmp failed, ret=%d\n", ret);
}
if (uc.args[1] & TEST_RESTORE_TILEDATA) {
fprintf(stderr, "GUEST_SYNC #%d, before KVM_SET_XSAVE\n", iter);
vcpu_xsave_set(vm, VCPU_ID, tile_state->xsave);
fprintf(stderr, "GUEST_SYNC #%d, after KVM_SET_XSAVE\n", iter);
}
if (uc.args[1] & TEST_SAVE_RESTORE) {
fprintf(stderr, "GUEST_SYNC #%d, save/restore VM state\n", iter);
state = vcpu_save_state(vm, VCPU_ID);
memset(&regs1, 0, sizeof(regs1));
vcpu_regs_get(vm, VCPU_ID, &regs1);
kvm_vm_release(vm);
/* Restore state in a new VM. */
kvm_vm_restart(vm, O_RDWR);
vm_vcpu_add(vm, VCPU_ID);
vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
vcpu_load_state(vm, VCPU_ID, state);
run = vcpu_state(vm, VCPU_ID);
kvm_x86_state_cleanup(state);
break;
case 9:
fprintf(stderr,
"GUEST_SYNC(%ld), #NM exception and enable amx\n", uc.args[1]);
break;
memset(&regs2, 0, sizeof(regs2));
vcpu_regs_get(vm, VCPU_ID, &regs2);
TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
"Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
(ulong) regs2.rdi, (ulong) regs2.rsi);
}
break;
case UCALL_DONE:
@ -424,25 +461,6 @@ int main(int argc, char *argv[])
TEST_FAIL("Unknown ucall %lu", uc.cmd);
}
state = vcpu_save_state(vm, VCPU_ID);
memset(&regs1, 0, sizeof(regs1));
vcpu_regs_get(vm, VCPU_ID, &regs1);
kvm_vm_release(vm);
/* Restore state in a new VM. */
kvm_vm_restart(vm, O_RDWR);
vm_vcpu_add(vm, VCPU_ID);
vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
vcpu_load_state(vm, VCPU_ID, state);
run = vcpu_state(vm, VCPU_ID);
kvm_x86_state_cleanup(state);
memset(&regs2, 0, sizeof(regs2));
vcpu_regs_get(vm, VCPU_ID, &regs2);
TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
"Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
(ulong) regs2.rdi, (ulong) regs2.rsi);
}
done:
kvm_vm_free(vm);