]> Git Repo - linux.git/commitdiff
Merge tag 'locking-core-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <[email protected]>
Tue, 24 May 2022 17:18:23 +0000 (10:18 -0700)
committerLinus Torvalds <[email protected]>
Tue, 24 May 2022 17:18:23 +0000 (10:18 -0700)
Pull locking updates from Ingo Molnar:

 - rwsem cleanups & optimizations/fixes:
    - Conditionally wake waiters in reader/writer slowpaths
    - Always try to wake waiters in out_nolock path

 - Add try_cmpxchg64() implementation, with arch optimizations - and use
   it to micro-optimize sched_clock_{local,remote}()

 - Various force-inlining fixes to address objdump instrumentation-check
   warnings

 - Add lock contention tracepoints:

    lock:contention_begin
    lock:contention_end

 - Misc smaller fixes & cleanups

* tag 'locking-core-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  sched/clock: Use try_cmpxchg64 in sched_clock_{local,remote}
  locking/atomic/x86: Introduce arch_try_cmpxchg64
  locking/atomic: Add generic try_cmpxchg64 support
  futex: Remove a PREEMPT_RT_FULL reference.
  locking/qrwlock: Change "queue rwlock" to "queued rwlock"
  lockdep: Delete local_irq_enable_in_hardirq()
  locking/mutex: Make contention tracepoints more consistent wrt adaptive spinning
  locking: Apply contention tracepoints in the slow path
  locking: Add lock contention tracepoints
  locking/rwsem: Always try to wake waiters in out_nolock path
  locking/rwsem: Conditionally wake waiters in reader/writer slowpaths
  locking/rwsem: No need to check for handoff bit if wait queue empty
  lockdep: Fix -Wunused-parameter for _THIS_IP_
  x86/mm: Force-inline __phys_addr_nodebug()
  x86/kvm/svm: Force-inline GHCB accessors
  task_stack, x86/cea: Force-inline stack helpers

1  2 
arch/arm64/kernel/entry-common.c
arch/x86/include/asm/svm.h
include/linux/kvm_host.h
kernel/entry/common.c
kernel/sched/idle.c

index 05cedd42103c676be4c9319abe8003827d4c579b,e04602ea4629c4fd54269992d4d418d849b356b9..56cefd33eb8e9a1ecbdc247e8af06637c0327981
@@@ -75,7 -75,7 +75,7 @@@ static __always_inline void __exit_to_k
        if (interrupts_enabled(regs)) {
                if (regs->exit_rcu) {
                        trace_hardirqs_on_prepare();
-                       lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+                       lockdep_hardirqs_on_prepare();
                        rcu_irq_exit();
                        lockdep_hardirqs_on(CALLER_ADDR0);
                        return;
@@@ -121,7 -121,7 +121,7 @@@ static __always_inline void enter_from_
  static __always_inline void __exit_to_user_mode(void)
  {
        trace_hardirqs_on_prepare();
-       lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+       lockdep_hardirqs_on_prepare();
        user_enter_irqoff();
        lockdep_hardirqs_on(CALLER_ADDR0);
  }
@@@ -179,7 -179,7 +179,7 @@@ static void noinstr arm64_exit_nmi(stru
        ftrace_nmi_exit();
        if (restore) {
                trace_hardirqs_on_prepare();
-               lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+               lockdep_hardirqs_on_prepare();
        }
  
        rcu_nmi_exit();
@@@ -215,7 -215,7 +215,7 @@@ static void noinstr arm64_exit_el1_dbg(
  
        if (restore) {
                trace_hardirqs_on_prepare();
-               lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+               lockdep_hardirqs_on_prepare();
        }
  
        rcu_nmi_exit();
@@@ -282,13 -282,13 +282,13 @@@ extern void (*handle_arch_irq)(struct p
  extern void (*handle_arch_fiq)(struct pt_regs *);
  
  static void noinstr __panic_unhandled(struct pt_regs *regs, const char *vector,
 -                                    unsigned int esr)
 +                                    unsigned long esr)
  {
        arm64_enter_nmi(regs);
  
        console_verbose();
  
 -      pr_crit("Unhandled %s exception on CPU%d, ESR 0x%08x -- %s\n",
 +      pr_crit("Unhandled %s exception on CPU%d, ESR 0x%016lx -- %s\n",
                vector, smp_processor_id(), esr,
                esr_get_class_string(esr));
  
@@@ -537,14 -537,6 +537,14 @@@ static void noinstr el0_sve_acc(struct 
        exit_to_user_mode(regs);
  }
  
 +static void noinstr el0_sme_acc(struct pt_regs *regs, unsigned long esr)
 +{
 +      enter_from_user_mode(regs);
 +      local_daif_restore(DAIF_PROCCTX);
 +      do_sme_acc(esr, regs);
 +      exit_to_user_mode(regs);
 +}
 +
  static void noinstr el0_fpsimd_exc(struct pt_regs *regs, unsigned long esr)
  {
        enter_from_user_mode(regs);
@@@ -653,9 -645,6 +653,9 @@@ asmlinkage void noinstr el0t_64_sync_ha
        case ESR_ELx_EC_SVE:
                el0_sve_acc(regs, esr);
                break;
 +      case ESR_ELx_EC_SME:
 +              el0_sme_acc(regs, esr);
 +              break;
        case ESR_ELx_EC_FP_EXC64:
                el0_fpsimd_exc(regs, esr);
                break;
@@@ -829,7 -818,7 +829,7 @@@ UNHANDLED(el0t, 32, error
  #ifdef CONFIG_VMAP_STACK
  asmlinkage void noinstr handle_bad_stack(struct pt_regs *regs)
  {
 -      unsigned int esr = read_sysreg(esr_el1);
 +      unsigned long esr = read_sysreg(esr_el1);
        unsigned long far = read_sysreg(far_el1);
  
        arm64_enter_nmi(regs);
index ec623e7da33d5d46ead369fdfc1a31381676cfb3,e255039b36b642cac185f0c1f918d56e3b97fb07..1b07fba11704ee63b5abb41db38db7bb519593f9
@@@ -271,7 -271,6 +271,7 @@@ struct vmcb_seg 
        u64 base;
  } __packed;
  
 +/* Save area definition for legacy and SEV-MEM guests */
  struct vmcb_save_area {
        struct vmcb_seg es;
        struct vmcb_seg cs;
        struct vmcb_seg ldtr;
        struct vmcb_seg idtr;
        struct vmcb_seg tr;
 -      u8 reserved_1[43];
 +      u8 reserved_1[42];
 +      u8 vmpl;
        u8 cpl;
        u8 reserved_2[4];
        u64 efer;
 -      u8 reserved_3[104];
 -      u64 xss;                /* Valid for SEV-ES only */
 +      u8 reserved_3[112];
        u64 cr4;
        u64 cr3;
        u64 cr0;
        u64 rip;
        u8 reserved_4[88];
        u64 rsp;
 -      u8 reserved_5[24];
 +      u64 s_cet;
 +      u64 ssp;
 +      u64 isst_addr;
        u64 rax;
        u64 star;
        u64 lstar;
        u64 sysenter_esp;
        u64 sysenter_eip;
        u64 cr2;
 -      u8 reserved_6[32];
 +      u8 reserved_5[32];
        u64 g_pat;
        u64 dbgctl;
        u64 br_from;
        u64 br_to;
        u64 last_excp_from;
        u64 last_excp_to;
 -
 -      /*
 -       * The following part of the save area is valid only for
 -       * SEV-ES guests when referenced through the GHCB or for
 -       * saving to the host save area.
 -       */
 -      u8 reserved_7[72];
 +      u8 reserved_6[72];
        u32 spec_ctrl;          /* Guest version of SPEC_CTRL at 0x2E0 */
 -      u8 reserved_7b[4];
 +} __packed;
 +
 +/* Save area definition for SEV-ES and SEV-SNP guests */
 +struct sev_es_save_area {
 +      struct vmcb_seg es;
 +      struct vmcb_seg cs;
 +      struct vmcb_seg ss;
 +      struct vmcb_seg ds;
 +      struct vmcb_seg fs;
 +      struct vmcb_seg gs;
 +      struct vmcb_seg gdtr;
 +      struct vmcb_seg ldtr;
 +      struct vmcb_seg idtr;
 +      struct vmcb_seg tr;
 +      u64 vmpl0_ssp;
 +      u64 vmpl1_ssp;
 +      u64 vmpl2_ssp;
 +      u64 vmpl3_ssp;
 +      u64 u_cet;
 +      u8 reserved_1[2];
 +      u8 vmpl;
 +      u8 cpl;
 +      u8 reserved_2[4];
 +      u64 efer;
 +      u8 reserved_3[104];
 +      u64 xss;
 +      u64 cr4;
 +      u64 cr3;
 +      u64 cr0;
 +      u64 dr7;
 +      u64 dr6;
 +      u64 rflags;
 +      u64 rip;
 +      u64 dr0;
 +      u64 dr1;
 +      u64 dr2;
 +      u64 dr3;
 +      u64 dr0_addr_mask;
 +      u64 dr1_addr_mask;
 +      u64 dr2_addr_mask;
 +      u64 dr3_addr_mask;
 +      u8 reserved_4[24];
 +      u64 rsp;
 +      u64 s_cet;
 +      u64 ssp;
 +      u64 isst_addr;
 +      u64 rax;
 +      u64 star;
 +      u64 lstar;
 +      u64 cstar;
 +      u64 sfmask;
 +      u64 kernel_gs_base;
 +      u64 sysenter_cs;
 +      u64 sysenter_esp;
 +      u64 sysenter_eip;
 +      u64 cr2;
 +      u8 reserved_5[32];
 +      u64 g_pat;
 +      u64 dbgctl;
 +      u64 br_from;
 +      u64 br_to;
 +      u64 last_excp_from;
 +      u64 last_excp_to;
 +      u8 reserved_7[80];
        u32 pkru;
 -      u8 reserved_7a[20];
 -      u64 reserved_8;         /* rax already available at 0x01f8 */
 +      u8 reserved_8[20];
 +      u64 reserved_9;         /* rax already available at 0x01f8 */
 +      u64 rcx;
 +      u64 rdx;
 +      u64 rbx;
 +      u64 reserved_10;        /* rsp already available at 0x01d8 */
 +      u64 rbp;
 +      u64 rsi;
 +      u64 rdi;
 +      u64 r8;
 +      u64 r9;
 +      u64 r10;
 +      u64 r11;
 +      u64 r12;
 +      u64 r13;
 +      u64 r14;
 +      u64 r15;
 +      u8 reserved_11[16];
 +      u64 guest_exit_info_1;
 +      u64 guest_exit_info_2;
 +      u64 guest_exit_int_info;
 +      u64 guest_nrip;
 +      u64 sev_features;
 +      u64 vintr_ctrl;
 +      u64 guest_exit_code;
 +      u64 virtual_tom;
 +      u64 tlb_id;
 +      u64 pcpu_id;
 +      u64 event_inj;
 +      u64 xcr0;
 +      u8 reserved_12[16];
 +
 +      /* Floating point area */
 +      u64 x87_dp;
 +      u32 mxcsr;
 +      u16 x87_ftw;
 +      u16 x87_fsw;
 +      u16 x87_fcw;
 +      u16 x87_fop;
 +      u16 x87_ds;
 +      u16 x87_cs;
 +      u64 x87_rip;
 +      u8 fpreg_x87[80];
 +      u8 fpreg_xmm[256];
 +      u8 fpreg_ymm[256];
 +} __packed;
 +
 +struct ghcb_save_area {
 +      u8 reserved_1[203];
 +      u8 cpl;
 +      u8 reserved_2[116];
 +      u64 xss;
 +      u8 reserved_3[24];
 +      u64 dr7;
 +      u8 reserved_4[16];
 +      u64 rip;
 +      u8 reserved_5[88];
 +      u64 rsp;
 +      u8 reserved_6[24];
 +      u64 rax;
 +      u8 reserved_7[264];
        u64 rcx;
        u64 rdx;
        u64 rbx;
 -      u64 reserved_9;         /* rsp already available at 0x01d8 */
 +      u8 reserved_8[8];
        u64 rbp;
        u64 rsi;
        u64 rdi;
        u64 r13;
        u64 r14;
        u64 r15;
 -      u8 reserved_10[16];
 +      u8 reserved_9[16];
        u64 sw_exit_code;
        u64 sw_exit_info_1;
        u64 sw_exit_info_2;
        u64 sw_scratch;
 -      u8 reserved_11[56];
 +      u8 reserved_10[56];
        u64 xcr0;
        u8 valid_bitmap[16];
        u64 x87_state_gpa;
  } __packed;
  
 +#define GHCB_SHARED_BUF_SIZE  2032
 +
  struct ghcb {
 -      struct vmcb_save_area save;
 -      u8 reserved_save[2048 - sizeof(struct vmcb_save_area)];
 +      struct ghcb_save_area save;
 +      u8 reserved_save[2048 - sizeof(struct ghcb_save_area)];
  
 -      u8 shared_buffer[2032];
 +      u8 shared_buffer[GHCB_SHARED_BUF_SIZE];
  
        u8 reserved_1[10];
        u16 protocol_version;   /* negotiated SEV-ES/GHCB protocol version */
  } __packed;
  
  
 -#define EXPECTED_VMCB_SAVE_AREA_SIZE          1032
 +#define EXPECTED_VMCB_SAVE_AREA_SIZE          740
 +#define EXPECTED_GHCB_SAVE_AREA_SIZE          1032
 +#define EXPECTED_SEV_ES_SAVE_AREA_SIZE                1648
  #define EXPECTED_VMCB_CONTROL_AREA_SIZE               1024
  #define EXPECTED_GHCB_SIZE                    PAGE_SIZE
  
  static inline void __unused_size_checks(void)
  {
        BUILD_BUG_ON(sizeof(struct vmcb_save_area)      != EXPECTED_VMCB_SAVE_AREA_SIZE);
 +      BUILD_BUG_ON(sizeof(struct ghcb_save_area)      != EXPECTED_GHCB_SAVE_AREA_SIZE);
 +      BUILD_BUG_ON(sizeof(struct sev_es_save_area)    != EXPECTED_SEV_ES_SAVE_AREA_SIZE);
        BUILD_BUG_ON(sizeof(struct vmcb_control_area)   != EXPECTED_VMCB_CONTROL_AREA_SIZE);
        BUILD_BUG_ON(sizeof(struct ghcb)                != EXPECTED_GHCB_SIZE);
  }
@@@ -566,26 -441,26 +566,26 @@@ struct vmcb 
  /* GHCB Accessor functions */
  
  #define GHCB_BITMAP_IDX(field)                                                        \
 -      (offsetof(struct vmcb_save_area, field) / sizeof(u64))
 +      (offsetof(struct ghcb_save_area, field) / sizeof(u64))
  
  #define DEFINE_GHCB_ACCESSORS(field)                                          \
-       static inline bool ghcb_##field##_is_valid(const struct ghcb *ghcb)     \
+       static __always_inline bool ghcb_##field##_is_valid(const struct ghcb *ghcb) \
        {                                                                       \
                return test_bit(GHCB_BITMAP_IDX(field),                         \
                                (unsigned long *)&ghcb->save.valid_bitmap);     \
        }                                                                       \
                                                                                \
-       static inline u64 ghcb_get_##field(struct ghcb *ghcb)                   \
+       static __always_inline u64 ghcb_get_##field(struct ghcb *ghcb)          \
        {                                                                       \
                return ghcb->save.field;                                        \
        }                                                                       \
                                                                                \
-       static inline u64 ghcb_get_##field##_if_valid(struct ghcb *ghcb)        \
+       static __always_inline u64 ghcb_get_##field##_if_valid(struct ghcb *ghcb) \
        {                                                                       \
                return ghcb_##field##_is_valid(ghcb) ? ghcb->save.field : 0;    \
        }                                                                       \
                                                                                \
-       static inline void ghcb_set_##field(struct ghcb *ghcb, u64 value)       \
+       static __always_inline void ghcb_set_##field(struct ghcb *ghcb, u64 value) \
        {                                                                       \
                __set_bit(GHCB_BITMAP_IDX(field),                               \
                          (unsigned long *)&ghcb->save.valid_bitmap);           \
diff --combined include/linux/kvm_host.h
index 34eed5f85ed607432bd40559d1f9c6356cb6f083,e1b2413750c029523f55062634b4eb4d52bb1a50..4640393f20ab708a6444ff1fec25f4bfde88c994
@@@ -315,10 -315,7 +315,10 @@@ struct kvm_vcpu 
        int cpu;
        int vcpu_id; /* id given by userspace at creation */
        int vcpu_idx; /* index in kvm->vcpus array */
 -      int srcu_idx;
 +      int ____srcu_idx; /* Don't use this directly.  You've been warned. */
 +#ifdef CONFIG_PROVE_RCU
 +      int srcu_depth;
 +#endif
        int mode;
        u64 requests;
        unsigned long guest_debug;
@@@ -453,7 -450,7 +453,7 @@@ static __always_inline void guest_state
  {
        instrumentation_begin();
        trace_hardirqs_on_prepare();
-       lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+       lockdep_hardirqs_on_prepare();
        instrumentation_end();
  
        guest_context_enter_irqoff();
@@@ -843,25 -840,6 +843,25 @@@ static inline void kvm_vm_bugged(struc
        unlikely(__ret);                                        \
  })
  
 +static inline void kvm_vcpu_srcu_read_lock(struct kvm_vcpu *vcpu)
 +{
 +#ifdef CONFIG_PROVE_RCU
 +      WARN_ONCE(vcpu->srcu_depth++,
 +                "KVM: Illegal vCPU srcu_idx LOCK, depth=%d", vcpu->srcu_depth - 1);
 +#endif
 +      vcpu->____srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 +}
 +
 +static inline void kvm_vcpu_srcu_read_unlock(struct kvm_vcpu *vcpu)
 +{
 +      srcu_read_unlock(&vcpu->kvm->srcu, vcpu->____srcu_idx);
 +
 +#ifdef CONFIG_PROVE_RCU
 +      WARN_ONCE(--vcpu->srcu_depth,
 +                "KVM: Illegal vCPU srcu_idx UNLOCK, depth=%d", vcpu->srcu_depth);
 +#endif
 +}
 +
  static inline bool kvm_dirty_log_manual_protect_and_init_set(struct kvm *kvm)
  {
        return !!(kvm->manual_dirty_log_protect & KVM_DIRTY_LOG_INITIALLY_SET);
@@@ -2219,8 -2197,6 +2219,8 @@@ static inline long kvm_arch_vcpu_async_
  void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
                                            unsigned long start, unsigned long end);
  
 +void kvm_arch_guest_memory_reclaimed(struct kvm *kvm);
 +
  #ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE
  int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu);
  #else
diff --combined kernel/entry/common.c
index 9e63923c5a0f6ae5a001237ea34cadd529b47b9a,2eef7b22e02a5386fdc32eab950083ef1dc0a4fe..032f164abe7cefb2011fa50f481bc6b661b88d7f
@@@ -17,7 -17,7 +17,7 @@@
  /* See comment for enter_from_user_mode() in entry-common.h */
  static __always_inline void __enter_from_user_mode(struct pt_regs *regs)
  {
 -      arch_check_user_regs(regs);
 +      arch_enter_from_user_mode(regs);
        lockdep_hardirqs_off(CALLER_ADDR0);
  
        CT_WARN_ON(ct_state() != CONTEXT_USER);
@@@ -126,7 -126,7 +126,7 @@@ static __always_inline void __exit_to_u
  {
        instrumentation_begin();
        trace_hardirqs_on_prepare();
-       lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+       lockdep_hardirqs_on_prepare();
        instrumentation_end();
  
        user_enter_irqoff();
@@@ -392,7 -392,7 +392,7 @@@ DEFINE_STATIC_CALL(irqentry_exit_cond_r
  DEFINE_STATIC_KEY_TRUE(sk_dynamic_irqentry_exit_cond_resched);
  void dynamic_irqentry_exit_cond_resched(void)
  {
 -      if (!static_key_unlikely(&sk_dynamic_irqentry_exit_cond_resched))
 +      if (!static_branch_unlikely(&sk_dynamic_irqentry_exit_cond_resched))
                return;
        raw_irqentry_exit_cond_resched();
  }
@@@ -416,7 -416,7 +416,7 @@@ noinstr void irqentry_exit(struct pt_re
                        instrumentation_begin();
                        /* Tell the tracer that IRET will enable interrupts */
                        trace_hardirqs_on_prepare();
-                       lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+                       lockdep_hardirqs_on_prepare();
                        instrumentation_end();
                        rcu_irq_exit();
                        lockdep_hardirqs_on(CALLER_ADDR0);
@@@ -465,7 -465,7 +465,7 @@@ void noinstr irqentry_nmi_exit(struct p
        ftrace_nmi_exit();
        if (irq_state.lockdep) {
                trace_hardirqs_on_prepare();
-               lockdep_hardirqs_on_prepare(CALLER_ADDR0);
+               lockdep_hardirqs_on_prepare();
        }
        instrumentation_end();
  
diff --combined kernel/sched/idle.c
index ecb0d705287753f080d347bcd3ae1961a5292f61,3984dd21a5aa036d6c66c17fc76a136d5f2f03a2..f85d7c7caab2de74a45f2c6572ccbe82a37d528e
@@@ -102,7 -102,7 +102,7 @@@ void __cpuidle default_idle_call(void
                 * last -- this is very similar to the entry code.
                 */
                trace_hardirqs_on_prepare();
-               lockdep_hardirqs_on_prepare(_THIS_IP_);
+               lockdep_hardirqs_on_prepare();
                rcu_idle_enter();
                lockdep_hardirqs_on(_THIS_IP_);
  
@@@ -434,6 -434,7 +434,6 @@@ static void set_next_task_idle(struct r
  {
        update_idle_core(rq);
        schedstat_inc(rq->sched_goidle);
 -      queue_core_balance(rq);
  }
  
  #ifdef CONFIG_SMP
This page took 0.138423 seconds and 4 git commands to generate.