Merge branch 'linus' into x86/entry, to resolve conflicts
Conflicts: arch/x86/kernel/traps.c Signed-off-by: Ingo Molnar <mingo@kernel.org>
这个提交包含在:
@@ -943,7 +943,7 @@ struct kvm_arch {
|
||||
atomic_t vapics_in_nmi_mode;
|
||||
struct mutex apic_map_lock;
|
||||
struct kvm_apic_map *apic_map;
|
||||
bool apic_map_dirty;
|
||||
atomic_t apic_map_dirty;
|
||||
|
||||
bool apic_access_page_done;
|
||||
unsigned long apicv_inhibit_reasons;
|
||||
@@ -1220,7 +1220,7 @@ struct kvm_x86_ops {
|
||||
void (*enable_log_dirty_pt_masked)(struct kvm *kvm,
|
||||
struct kvm_memory_slot *slot,
|
||||
gfn_t offset, unsigned long mask);
|
||||
int (*write_log_dirty)(struct kvm_vcpu *vcpu);
|
||||
int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
|
||||
|
||||
/* pmu operations of sub-arch */
|
||||
const struct kvm_pmu_ops *pmu_ops;
|
||||
|
@@ -25,8 +25,6 @@
|
||||
#define TPAUSE_C01_STATE 1
|
||||
#define TPAUSE_C02_STATE 0
|
||||
|
||||
u32 get_umwait_control_msr(void);
|
||||
|
||||
static inline void __monitor(const void *eax, unsigned long ecx,
|
||||
unsigned long edx)
|
||||
{
|
||||
|
@@ -278,7 +278,7 @@ static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs
|
||||
}
|
||||
|
||||
/* To avoid include hell, we can't include uaccess.h */
|
||||
extern long probe_kernel_read(void *dst, const void *src, size_t size);
|
||||
extern long copy_from_kernel_nofault(void *dst, const void *src, size_t size);
|
||||
|
||||
/**
|
||||
* regs_get_kernel_stack_nth() - get Nth entry of the stack
|
||||
@@ -298,7 +298,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
|
||||
|
||||
addr = regs_get_kernel_stack_nth_addr(regs, n);
|
||||
if (addr) {
|
||||
ret = probe_kernel_read(&val, addr, sizeof(val));
|
||||
ret = copy_from_kernel_nofault(&val, addr, sizeof(val));
|
||||
if (!ret)
|
||||
return val;
|
||||
}
|
||||
|
@@ -18,12 +18,6 @@
|
||||
*/
|
||||
static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
|
||||
|
||||
u32 get_umwait_control_msr(void)
|
||||
{
|
||||
return umwait_control_cached;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_umwait_control_msr);
|
||||
|
||||
/*
|
||||
* Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
|
||||
* hardware or BIOS before kernel boot.
|
||||
|
@@ -106,7 +106,7 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
|
||||
bad_ip = user_mode(regs) &&
|
||||
__chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX);
|
||||
|
||||
if (bad_ip || probe_kernel_read(opcodes, (u8 *)prologue,
|
||||
if (bad_ip || copy_from_kernel_nofault(opcodes, (u8 *)prologue,
|
||||
OPCODE_BUFSIZE)) {
|
||||
printk("%sCode: Bad RIP value.\n", loglvl);
|
||||
} else {
|
||||
|
@@ -86,7 +86,7 @@ static int ftrace_verify_code(unsigned long ip, const char *old_code)
|
||||
* sure what we read is what we expected it to be before modifying it.
|
||||
*/
|
||||
/* read the text we want to modify */
|
||||
if (probe_kernel_read(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
|
||||
if (copy_from_kernel_nofault(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
|
||||
WARN_ON(1);
|
||||
return -EFAULT;
|
||||
}
|
||||
@@ -355,7 +355,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||
npages = DIV_ROUND_UP(*tramp_size, PAGE_SIZE);
|
||||
|
||||
/* Copy ftrace_caller onto the trampoline memory */
|
||||
ret = probe_kernel_read(trampoline, (void *)start_offset, size);
|
||||
ret = copy_from_kernel_nofault(trampoline, (void *)start_offset, size);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto fail;
|
||||
|
||||
@@ -363,13 +363,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
|
||||
|
||||
/* The trampoline ends with ret(q) */
|
||||
retq = (unsigned long)ftrace_stub;
|
||||
ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
|
||||
ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto fail;
|
||||
|
||||
if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
|
||||
ip = trampoline + (ftrace_regs_caller_ret - ftrace_regs_caller);
|
||||
ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
|
||||
ret = copy_from_kernel_nofault(ip, (void *)retq, RET_SIZE);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto fail;
|
||||
}
|
||||
@@ -506,7 +506,7 @@ static void *addr_from_call(void *ptr)
|
||||
union text_poke_insn call;
|
||||
int ret;
|
||||
|
||||
ret = probe_kernel_read(&call, ptr, CALL_INSN_SIZE);
|
||||
ret = copy_from_kernel_nofault(&call, ptr, CALL_INSN_SIZE);
|
||||
if (WARN_ON_ONCE(ret < 0))
|
||||
return NULL;
|
||||
|
||||
|
@@ -732,11 +732,11 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
|
||||
int err;
|
||||
|
||||
bpt->type = BP_BREAKPOINT;
|
||||
err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
|
||||
err = copy_from_kernel_nofault(bpt->saved_instr, (char *)bpt->bpt_addr,
|
||||
BREAK_INSTR_SIZE);
|
||||
if (err)
|
||||
return err;
|
||||
err = probe_kernel_write((char *)bpt->bpt_addr,
|
||||
err = copy_to_kernel_nofault((char *)bpt->bpt_addr,
|
||||
arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
|
||||
if (!err)
|
||||
return err;
|
||||
@@ -768,7 +768,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
|
||||
return 0;
|
||||
|
||||
knl_write:
|
||||
return probe_kernel_write((char *)bpt->bpt_addr,
|
||||
return copy_to_kernel_nofault((char *)bpt->bpt_addr,
|
||||
(char *)bpt->saved_instr, BREAK_INSTR_SIZE);
|
||||
}
|
||||
|
||||
|
@@ -243,7 +243,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
|
||||
* Fortunately, we know that the original code is the ideal 5-byte
|
||||
* long NOP.
|
||||
*/
|
||||
if (probe_kernel_read(buf, (void *)addr,
|
||||
if (copy_from_kernel_nofault(buf, (void *)addr,
|
||||
MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
|
||||
return 0UL;
|
||||
|
||||
@@ -346,7 +346,8 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
|
||||
return 0;
|
||||
|
||||
/* This can access kernel text if given address is not recovered */
|
||||
if (probe_kernel_read(dest, (void *)recovered_insn, MAX_INSN_SIZE))
|
||||
if (copy_from_kernel_nofault(dest, (void *)recovered_insn,
|
||||
MAX_INSN_SIZE))
|
||||
return 0;
|
||||
|
||||
kernel_insn_init(insn, dest, MAX_INSN_SIZE);
|
||||
@@ -753,16 +754,11 @@ asm(
|
||||
NOKPROBE_SYMBOL(kretprobe_trampoline);
|
||||
STACK_FRAME_NON_STANDARD(kretprobe_trampoline);
|
||||
|
||||
static struct kprobe kretprobe_kprobe = {
|
||||
.addr = (void *)kretprobe_trampoline,
|
||||
};
|
||||
|
||||
/*
|
||||
* Called from kretprobe_trampoline
|
||||
*/
|
||||
__used __visible void *trampoline_handler(struct pt_regs *regs)
|
||||
{
|
||||
struct kprobe_ctlblk *kcb;
|
||||
struct kretprobe_instance *ri = NULL;
|
||||
struct hlist_head *head, empty_rp;
|
||||
struct hlist_node *tmp;
|
||||
@@ -772,16 +768,12 @@ __used __visible void *trampoline_handler(struct pt_regs *regs)
|
||||
void *frame_pointer;
|
||||
bool skipped = false;
|
||||
|
||||
preempt_disable();
|
||||
|
||||
/*
|
||||
* Set a dummy kprobe for avoiding kretprobe recursion.
|
||||
* Since kretprobe never run in kprobe handler, kprobe must not
|
||||
* be running at this point.
|
||||
*/
|
||||
kcb = get_kprobe_ctlblk();
|
||||
__this_cpu_write(current_kprobe, &kretprobe_kprobe);
|
||||
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
|
||||
kprobe_busy_begin();
|
||||
|
||||
INIT_HLIST_HEAD(&empty_rp);
|
||||
kretprobe_hash_lock(current, &head, &flags);
|
||||
@@ -857,7 +849,7 @@ __used __visible void *trampoline_handler(struct pt_regs *regs)
|
||||
__this_cpu_write(current_kprobe, &ri->rp->kp);
|
||||
ri->ret_addr = correct_ret_addr;
|
||||
ri->rp->handler(ri, regs);
|
||||
__this_cpu_write(current_kprobe, &kretprobe_kprobe);
|
||||
__this_cpu_write(current_kprobe, &kprobe_busy);
|
||||
}
|
||||
|
||||
recycle_rp_inst(ri, &empty_rp);
|
||||
@@ -873,8 +865,7 @@ __used __visible void *trampoline_handler(struct pt_regs *regs)
|
||||
|
||||
kretprobe_hash_unlock(current, &flags);
|
||||
|
||||
__this_cpu_write(current_kprobe, NULL);
|
||||
preempt_enable();
|
||||
kprobe_busy_end();
|
||||
|
||||
hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
|
||||
hlist_del(&ri->hlist);
|
||||
|
@@ -56,7 +56,7 @@ found:
|
||||
* overwritten by jump destination address. In this case, original
|
||||
* bytes must be recovered from op->optinsn.copied_insn buffer.
|
||||
*/
|
||||
if (probe_kernel_read(buf, (void *)addr,
|
||||
if (copy_from_kernel_nofault(buf, (void *)addr,
|
||||
MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
|
||||
return 0UL;
|
||||
|
||||
|
@@ -94,12 +94,12 @@ static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short
|
||||
}
|
||||
|
||||
static bool probe_list(struct pci_dev *pdev, unsigned short vendor,
|
||||
const unsigned char *rom_list)
|
||||
const void *rom_list)
|
||||
{
|
||||
unsigned short device;
|
||||
|
||||
do {
|
||||
if (probe_kernel_address(rom_list, device) != 0)
|
||||
if (get_kernel_nofault(device, rom_list) != 0)
|
||||
device = 0;
|
||||
|
||||
if (device && match_id(pdev, vendor, device))
|
||||
@@ -119,19 +119,19 @@ static struct resource *find_oprom(struct pci_dev *pdev)
|
||||
for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) {
|
||||
struct resource *res = &adapter_rom_resources[i];
|
||||
unsigned short offset, vendor, device, list, rev;
|
||||
const unsigned char *rom;
|
||||
const void *rom;
|
||||
|
||||
if (res->end == 0)
|
||||
break;
|
||||
|
||||
rom = isa_bus_to_virt(res->start);
|
||||
if (probe_kernel_address(rom + 0x18, offset) != 0)
|
||||
if (get_kernel_nofault(offset, rom + 0x18) != 0)
|
||||
continue;
|
||||
|
||||
if (probe_kernel_address(rom + offset + 0x4, vendor) != 0)
|
||||
if (get_kernel_nofault(vendor, rom + offset + 0x4) != 0)
|
||||
continue;
|
||||
|
||||
if (probe_kernel_address(rom + offset + 0x6, device) != 0)
|
||||
if (get_kernel_nofault(device, rom + offset + 0x6) != 0)
|
||||
continue;
|
||||
|
||||
if (match_id(pdev, vendor, device)) {
|
||||
@@ -139,8 +139,8 @@ static struct resource *find_oprom(struct pci_dev *pdev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (probe_kernel_address(rom + offset + 0x8, list) == 0 &&
|
||||
probe_kernel_address(rom + offset + 0xc, rev) == 0 &&
|
||||
if (get_kernel_nofault(list, rom + offset + 0x8) == 0 &&
|
||||
get_kernel_nofault(rev, rom + offset + 0xc) == 0 &&
|
||||
rev >= 3 && list &&
|
||||
probe_list(pdev, vendor, rom + offset + list)) {
|
||||
oprom = res;
|
||||
@@ -183,14 +183,14 @@ static int __init romsignature(const unsigned char *rom)
|
||||
const unsigned short * const ptr = (const unsigned short *)rom;
|
||||
unsigned short sig;
|
||||
|
||||
return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
|
||||
return get_kernel_nofault(sig, ptr) == 0 && sig == ROMSIGNATURE;
|
||||
}
|
||||
|
||||
static int __init romchecksum(const unsigned char *rom, unsigned long length)
|
||||
{
|
||||
unsigned char sum, c;
|
||||
|
||||
for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
|
||||
for (sum = 0; length && get_kernel_nofault(c, rom++) == 0; length--)
|
||||
sum += c;
|
||||
return !length && !sum;
|
||||
}
|
||||
@@ -211,7 +211,7 @@ void __init probe_roms(void)
|
||||
|
||||
video_rom_resource.start = start;
|
||||
|
||||
if (probe_kernel_address(rom + 2, c) != 0)
|
||||
if (get_kernel_nofault(c, rom + 2) != 0)
|
||||
continue;
|
||||
|
||||
/* 0 < length <= 0x7f * 512, historically */
|
||||
@@ -249,7 +249,7 @@ void __init probe_roms(void)
|
||||
if (!romsignature(rom))
|
||||
continue;
|
||||
|
||||
if (probe_kernel_address(rom + 2, c) != 0)
|
||||
if (get_kernel_nofault(c, rom + 2) != 0)
|
||||
continue;
|
||||
|
||||
/* 0 < length <= 0x7f * 512, historically */
|
||||
|
@@ -492,7 +492,8 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
|
||||
u8 insn_buf[MAX_INSN_SIZE];
|
||||
struct insn insn;
|
||||
|
||||
if (probe_kernel_read(insn_buf, (void *)regs->ip, MAX_INSN_SIZE))
|
||||
if (copy_from_kernel_nofault(insn_buf, (void *)regs->ip,
|
||||
MAX_INSN_SIZE))
|
||||
return GP_NO_HINT;
|
||||
|
||||
kernel_insn_init(&insn, insn_buf, MAX_INSN_SIZE);
|
||||
|
@@ -169,6 +169,18 @@ static void kvm_apic_map_free(struct rcu_head *rcu)
|
||||
kvfree(map);
|
||||
}
|
||||
|
||||
/*
|
||||
* CLEAN -> DIRTY and UPDATE_IN_PROGRESS -> DIRTY changes happen without a lock.
|
||||
*
|
||||
* DIRTY -> UPDATE_IN_PROGRESS and UPDATE_IN_PROGRESS -> CLEAN happen with
|
||||
* apic_map_lock_held.
|
||||
*/
|
||||
enum {
|
||||
CLEAN,
|
||||
UPDATE_IN_PROGRESS,
|
||||
DIRTY
|
||||
};
|
||||
|
||||
void kvm_recalculate_apic_map(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_apic_map *new, *old = NULL;
|
||||
@@ -176,17 +188,17 @@ void kvm_recalculate_apic_map(struct kvm *kvm)
|
||||
int i;
|
||||
u32 max_id = 255; /* enough space for any xAPIC ID */
|
||||
|
||||
if (!kvm->arch.apic_map_dirty) {
|
||||
/*
|
||||
* Read kvm->arch.apic_map_dirty before
|
||||
* kvm->arch.apic_map
|
||||
*/
|
||||
smp_rmb();
|
||||
/* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map. */
|
||||
if (atomic_read_acquire(&kvm->arch.apic_map_dirty) == CLEAN)
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&kvm->arch.apic_map_lock);
|
||||
if (!kvm->arch.apic_map_dirty) {
|
||||
/*
|
||||
* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map
|
||||
* (if clean) or the APIC registers (if dirty).
|
||||
*/
|
||||
if (atomic_cmpxchg_acquire(&kvm->arch.apic_map_dirty,
|
||||
DIRTY, UPDATE_IN_PROGRESS) == CLEAN) {
|
||||
/* Someone else has updated the map. */
|
||||
mutex_unlock(&kvm->arch.apic_map_lock);
|
||||
return;
|
||||
@@ -256,11 +268,11 @@ out:
|
||||
lockdep_is_held(&kvm->arch.apic_map_lock));
|
||||
rcu_assign_pointer(kvm->arch.apic_map, new);
|
||||
/*
|
||||
* Write kvm->arch.apic_map before
|
||||
* clearing apic->apic_map_dirty
|
||||
* Write kvm->arch.apic_map before clearing apic->apic_map_dirty.
|
||||
* If another update has come in, leave it DIRTY.
|
||||
*/
|
||||
smp_wmb();
|
||||
kvm->arch.apic_map_dirty = false;
|
||||
atomic_cmpxchg_release(&kvm->arch.apic_map_dirty,
|
||||
UPDATE_IN_PROGRESS, CLEAN);
|
||||
mutex_unlock(&kvm->arch.apic_map_lock);
|
||||
|
||||
if (old)
|
||||
@@ -282,20 +294,20 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
|
||||
else
|
||||
static_key_slow_inc(&apic_sw_disabled.key);
|
||||
|
||||
apic->vcpu->kvm->arch.apic_map_dirty = true;
|
||||
atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void kvm_apic_set_xapic_id(struct kvm_lapic *apic, u8 id)
|
||||
{
|
||||
kvm_lapic_set_reg(apic, APIC_ID, id << 24);
|
||||
apic->vcpu->kvm->arch.apic_map_dirty = true;
|
||||
atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
|
||||
}
|
||||
|
||||
static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id)
|
||||
{
|
||||
kvm_lapic_set_reg(apic, APIC_LDR, id);
|
||||
apic->vcpu->kvm->arch.apic_map_dirty = true;
|
||||
atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
|
||||
}
|
||||
|
||||
static inline u32 kvm_apic_calc_x2apic_ldr(u32 id)
|
||||
@@ -311,7 +323,7 @@ static inline void kvm_apic_set_x2apic_id(struct kvm_lapic *apic, u32 id)
|
||||
|
||||
kvm_lapic_set_reg(apic, APIC_ID, id);
|
||||
kvm_lapic_set_reg(apic, APIC_LDR, ldr);
|
||||
apic->vcpu->kvm->arch.apic_map_dirty = true;
|
||||
atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
|
||||
}
|
||||
|
||||
static inline int apic_lvt_enabled(struct kvm_lapic *apic, int lvt_type)
|
||||
@@ -1976,7 +1988,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
|
||||
case APIC_DFR:
|
||||
if (!apic_x2apic_mode(apic)) {
|
||||
kvm_lapic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF);
|
||||
apic->vcpu->kvm->arch.apic_map_dirty = true;
|
||||
atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
|
||||
} else
|
||||
ret = 1;
|
||||
break;
|
||||
@@ -2232,7 +2244,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
|
||||
static_key_slow_dec_deferred(&apic_hw_disabled);
|
||||
} else {
|
||||
static_key_slow_inc(&apic_hw_disabled.key);
|
||||
vcpu->kvm->arch.apic_map_dirty = true;
|
||||
atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2273,7 +2285,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||
if (!apic)
|
||||
return;
|
||||
|
||||
vcpu->kvm->arch.apic_map_dirty = false;
|
||||
/* Stop the timer in case it's a reset to an active apic */
|
||||
hrtimer_cancel(&apic->lapic_timer.timer);
|
||||
|
||||
@@ -2567,6 +2578,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
|
||||
}
|
||||
memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s));
|
||||
|
||||
atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
|
||||
kvm_recalculate_apic_map(vcpu->kvm);
|
||||
kvm_apic_set_version(vcpu);
|
||||
|
||||
|
@@ -222,7 +222,7 @@ void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
|
||||
void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
|
||||
bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
|
||||
struct kvm_memory_slot *slot, u64 gfn);
|
||||
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
|
||||
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
|
||||
|
||||
int kvm_mmu_post_init_vm(struct kvm *kvm);
|
||||
void kvm_mmu_pre_destroy_vm(struct kvm *kvm);
|
||||
|
@@ -1745,10 +1745,10 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
|
||||
* Emulate arch specific page modification logging for the
|
||||
* nested hypervisor
|
||||
*/
|
||||
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu)
|
||||
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa)
|
||||
{
|
||||
if (kvm_x86_ops.write_log_dirty)
|
||||
return kvm_x86_ops.write_log_dirty(vcpu);
|
||||
return kvm_x86_ops.write_log_dirty(vcpu, l2_gpa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -235,7 +235,7 @@ static inline unsigned FNAME(gpte_access)(u64 gpte)
|
||||
static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
|
||||
struct kvm_mmu *mmu,
|
||||
struct guest_walker *walker,
|
||||
int write_fault)
|
||||
gpa_t addr, int write_fault)
|
||||
{
|
||||
unsigned level, index;
|
||||
pt_element_t pte, orig_pte;
|
||||
@@ -260,7 +260,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
|
||||
!(pte & PT_GUEST_DIRTY_MASK)) {
|
||||
trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
|
||||
#if PTTYPE == PTTYPE_EPT
|
||||
if (kvm_arch_write_log_dirty(vcpu))
|
||||
if (kvm_arch_write_log_dirty(vcpu, addr))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
pte |= PT_GUEST_DIRTY_MASK;
|
||||
@@ -360,7 +360,6 @@ retry_walk:
|
||||
++walker->level;
|
||||
|
||||
do {
|
||||
gfn_t real_gfn;
|
||||
unsigned long host_addr;
|
||||
|
||||
pt_access = pte_access;
|
||||
@@ -375,7 +374,7 @@ retry_walk:
|
||||
walker->table_gfn[walker->level - 1] = table_gfn;
|
||||
walker->pte_gpa[walker->level - 1] = pte_gpa;
|
||||
|
||||
real_gfn = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
|
||||
real_gpa = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
|
||||
nested_access,
|
||||
&walker->fault);
|
||||
|
||||
@@ -389,12 +388,10 @@ retry_walk:
|
||||
* information to fix the exit_qualification or exit_info_1
|
||||
* fields.
|
||||
*/
|
||||
if (unlikely(real_gfn == UNMAPPED_GVA))
|
||||
if (unlikely(real_gpa == UNMAPPED_GVA))
|
||||
return 0;
|
||||
|
||||
real_gfn = gpa_to_gfn(real_gfn);
|
||||
|
||||
host_addr = kvm_vcpu_gfn_to_hva_prot(vcpu, real_gfn,
|
||||
host_addr = kvm_vcpu_gfn_to_hva_prot(vcpu, gpa_to_gfn(real_gpa),
|
||||
&walker->pte_writable[walker->level - 1]);
|
||||
if (unlikely(kvm_is_error_hva(host_addr)))
|
||||
goto error;
|
||||
@@ -457,7 +454,8 @@ retry_walk:
|
||||
(PT_GUEST_DIRTY_SHIFT - PT_GUEST_ACCESSED_SHIFT);
|
||||
|
||||
if (unlikely(!accessed_dirty)) {
|
||||
ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, write_fault);
|
||||
ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker,
|
||||
addr, write_fault);
|
||||
if (unlikely(ret < 0))
|
||||
goto error;
|
||||
else if (ret)
|
||||
|
@@ -3344,7 +3344,7 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
|
||||
|
||||
void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
|
||||
|
||||
static fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
fastpath_t exit_fastpath;
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
@@ -72,11 +72,24 @@ struct loaded_vmcs {
|
||||
struct vmcs_controls_shadow controls_shadow;
|
||||
};
|
||||
|
||||
static inline bool is_intr_type(u32 intr_info, u32 type)
|
||||
{
|
||||
const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK;
|
||||
|
||||
return (intr_info & mask) == (INTR_INFO_VALID_MASK | type);
|
||||
}
|
||||
|
||||
static inline bool is_intr_type_n(u32 intr_info, u32 type, u8 vector)
|
||||
{
|
||||
const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK |
|
||||
INTR_INFO_VECTOR_MASK;
|
||||
|
||||
return (intr_info & mask) == (INTR_INFO_VALID_MASK | type | vector);
|
||||
}
|
||||
|
||||
static inline bool is_exception_n(u32 intr_info, u8 vector)
|
||||
{
|
||||
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
|
||||
INTR_INFO_VALID_MASK)) ==
|
||||
(INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK);
|
||||
return is_intr_type_n(intr_info, INTR_TYPE_HARD_EXCEPTION, vector);
|
||||
}
|
||||
|
||||
static inline bool is_debug(u32 intr_info)
|
||||
@@ -106,28 +119,23 @@ static inline bool is_gp_fault(u32 intr_info)
|
||||
|
||||
static inline bool is_machine_check(u32 intr_info)
|
||||
{
|
||||
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
|
||||
INTR_INFO_VALID_MASK)) ==
|
||||
(INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
|
||||
return is_exception_n(intr_info, MC_VECTOR);
|
||||
}
|
||||
|
||||
/* Undocumented: icebp/int1 */
|
||||
static inline bool is_icebp(u32 intr_info)
|
||||
{
|
||||
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
|
||||
== (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK);
|
||||
return is_intr_type(intr_info, INTR_TYPE_PRIV_SW_EXCEPTION);
|
||||
}
|
||||
|
||||
static inline bool is_nmi(u32 intr_info)
|
||||
{
|
||||
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
|
||||
== (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
|
||||
return is_intr_type(intr_info, INTR_TYPE_NMI_INTR);
|
||||
}
|
||||
|
||||
static inline bool is_external_intr(u32 intr_info)
|
||||
{
|
||||
return (intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
|
||||
== (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR);
|
||||
return is_intr_type(intr_info, INTR_TYPE_EXT_INTR);
|
||||
}
|
||||
|
||||
enum vmcs_field_width {
|
||||
|
@@ -6606,23 +6606,6 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
|
||||
msrs[i].host, false);
|
||||
}
|
||||
|
||||
static void atomic_switch_umwait_control_msr(struct vcpu_vmx *vmx)
|
||||
{
|
||||
u32 host_umwait_control;
|
||||
|
||||
if (!vmx_has_waitpkg(vmx))
|
||||
return;
|
||||
|
||||
host_umwait_control = get_umwait_control_msr();
|
||||
|
||||
if (vmx->msr_ia32_umwait_control != host_umwait_control)
|
||||
add_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL,
|
||||
vmx->msr_ia32_umwait_control,
|
||||
host_umwait_control, false);
|
||||
else
|
||||
clear_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL);
|
||||
}
|
||||
|
||||
static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
@@ -6728,9 +6711,7 @@ reenter_guest:
|
||||
|
||||
pt_guest_enter(vmx);
|
||||
|
||||
if (vcpu_to_pmu(vcpu)->version)
|
||||
atomic_switch_perf_msrs(vmx);
|
||||
atomic_switch_umwait_control_msr(vmx);
|
||||
atomic_switch_perf_msrs(vmx);
|
||||
|
||||
if (enable_preemption_timer)
|
||||
vmx_update_hv_timer(vcpu);
|
||||
@@ -7501,11 +7482,11 @@ static void vmx_flush_log_dirty(struct kvm *kvm)
|
||||
kvm_flush_pml_buffers(kvm);
|
||||
}
|
||||
|
||||
static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
|
||||
static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
|
||||
{
|
||||
struct vmcs12 *vmcs12;
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
gpa_t gpa, dst;
|
||||
gpa_t dst;
|
||||
|
||||
if (is_guest_mode(vcpu)) {
|
||||
WARN_ON_ONCE(vmx->nested.pml_full);
|
||||
@@ -7524,7 +7505,7 @@ static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
|
||||
return 1;
|
||||
}
|
||||
|
||||
gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull;
|
||||
gpa &= ~0xFFFull;
|
||||
dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index;
|
||||
|
||||
if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa,
|
||||
|
@@ -288,8 +288,6 @@ struct vcpu_vmx {
|
||||
|
||||
u64 current_tsc_ratio;
|
||||
|
||||
u32 host_pkru;
|
||||
|
||||
unsigned long host_debugctlmsr;
|
||||
|
||||
/*
|
||||
|
@@ -2856,7 +2856,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
return kvm_mtrr_set_msr(vcpu, msr, data);
|
||||
case MSR_IA32_APICBASE:
|
||||
return kvm_set_apic_base(vcpu, msr_info);
|
||||
case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
|
||||
case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
|
||||
return kvm_x2apic_msr_write(vcpu, msr, data);
|
||||
case MSR_IA32_TSCDEADLINE:
|
||||
kvm_set_lapic_tscdeadline_msr(vcpu, data);
|
||||
@@ -3196,7 +3196,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
case MSR_IA32_APICBASE:
|
||||
msr_info->data = kvm_get_apic_base(vcpu);
|
||||
break;
|
||||
case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
|
||||
case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
|
||||
return kvm_x2apic_msr_read(vcpu, msr_info->index, &msr_info->data);
|
||||
case MSR_IA32_TSCDEADLINE:
|
||||
msr_info->data = kvm_get_lapic_tscdeadline_msr(vcpu);
|
||||
@@ -4603,7 +4603,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
|
||||
r = -EINVAL;
|
||||
user_tsc_khz = (u32)arg;
|
||||
|
||||
if (user_tsc_khz >= kvm_max_guest_tsc_khz)
|
||||
if (kvm_has_tsc_control &&
|
||||
user_tsc_khz >= kvm_max_guest_tsc_khz)
|
||||
goto out;
|
||||
|
||||
if (user_tsc_khz == 0)
|
||||
|
@@ -99,7 +99,7 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
|
||||
return !instr_lo || (instr_lo>>1) == 1;
|
||||
case 0x00:
|
||||
/* Prefetch instruction is 0x0F0D or 0x0F18 */
|
||||
if (probe_kernel_address(instr, opcode))
|
||||
if (get_kernel_nofault(opcode, instr))
|
||||
return 0;
|
||||
|
||||
*prefetch = (instr_lo == 0xF) &&
|
||||
@@ -133,7 +133,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
|
||||
while (instr < max_instr) {
|
||||
unsigned char opcode;
|
||||
|
||||
if (probe_kernel_address(instr, opcode))
|
||||
if (get_kernel_nofault(opcode, instr))
|
||||
break;
|
||||
|
||||
instr++;
|
||||
@@ -301,7 +301,7 @@ static int bad_address(void *p)
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
return probe_kernel_address((unsigned long *)p, dummy);
|
||||
return get_kernel_nofault(dummy, (unsigned long *)p);
|
||||
}
|
||||
|
||||
static void dump_pagetable(unsigned long address)
|
||||
@@ -442,7 +442,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
|
||||
return;
|
||||
}
|
||||
|
||||
if (probe_kernel_read(&desc, (void *)(gdt->address + offset),
|
||||
if (copy_from_kernel_nofault(&desc, (void *)(gdt->address + offset),
|
||||
sizeof(struct ldttss_desc))) {
|
||||
pr_alert("%s: 0x%hx -- GDT entry is not readable\n",
|
||||
name, index);
|
||||
|
@@ -737,7 +737,7 @@ static void __init test_wp_bit(void)
|
||||
|
||||
__set_fixmap(FIX_WP_TEST, __pa_symbol(empty_zero_page), PAGE_KERNEL_RO);
|
||||
|
||||
if (probe_kernel_write((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
|
||||
if (copy_to_kernel_nofault((char *)fix_to_virt(FIX_WP_TEST), &z, 1)) {
|
||||
clear_fixmap(FIX_WP_TEST);
|
||||
printk(KERN_CONT "Ok.\n");
|
||||
return;
|
||||
|
@@ -9,7 +9,7 @@ static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
|
||||
return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
|
||||
}
|
||||
|
||||
bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
|
||||
bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
|
||||
{
|
||||
unsigned long vaddr = (unsigned long)unsafe_src;
|
||||
|
||||
@@ -22,7 +22,7 @@ bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
|
||||
canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
|
||||
}
|
||||
#else
|
||||
bool probe_kernel_read_allowed(const void *unsafe_src, size_t size)
|
||||
bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
|
||||
{
|
||||
return (unsigned long)unsafe_src >= TASK_SIZE_MAX;
|
||||
}
|
||||
|
@@ -302,7 +302,7 @@ static const struct pci_raw_ops *__init pci_find_bios(void)
|
||||
check <= (union bios32 *) __va(0xffff0);
|
||||
++check) {
|
||||
long sig;
|
||||
if (probe_kernel_address(&check->fields.signature, sig))
|
||||
if (get_kernel_nofault(sig, &check->fields.signature))
|
||||
continue;
|
||||
|
||||
if (check->fields.signature != BIOS32_SIGNATURE)
|
||||
|
@@ -287,8 +287,8 @@ void intel_scu_devices_create(void)
|
||||
|
||||
adapter = i2c_get_adapter(i2c_bus[i]);
|
||||
if (adapter) {
|
||||
client = i2c_new_device(adapter, i2c_devs[i]);
|
||||
if (!client)
|
||||
client = i2c_new_client_device(adapter, i2c_devs[i]);
|
||||
if (IS_ERR(client))
|
||||
pr_err("can't create i2c device %s\n",
|
||||
i2c_devs[i]->type);
|
||||
} else
|
||||
|
@@ -34,6 +34,7 @@ KCOV_INSTRUMENT := n
|
||||
PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
|
||||
PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
|
||||
PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
|
||||
PURGATORY_CFLAGS += $(call cc-option,-fno-stack-protector)
|
||||
|
||||
# Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
|
||||
# in turn leaves some undefined symbols like __fentry__ in purgatory and not
|
||||
|
@@ -386,7 +386,7 @@ static void set_aliased_prot(void *v, pgprot_t prot)
|
||||
|
||||
preempt_disable();
|
||||
|
||||
probe_kernel_read(&dummy, v, 1);
|
||||
copy_from_kernel_nofault(&dummy, v, 1);
|
||||
|
||||
if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
|
||||
BUG();
|
||||
|
在新工单中引用
屏蔽一个用户