Merge tag 'x86-apic-2023-04-24' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 18:39:45 +0000 (11:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 18:39:45 +0000 (11:39 -0700)
Pull x86 APIC updates from Thomas Gleixner:

 - Fix the incorrect handling of atomic offset updates in
   reserve_eilvt_offset()

   The check for the return value of atomic_cmpxchg() is not compared
   against the old value, it is compared against the new value, which
   makes it two round on success.

   Convert it to atomic_try_cmpxchg() which does the right thing.

 - Handle IO/APIC less systems correctly

   When IO/APIC is not advertised by ACPI then the computation of the
   lower bound for dynamically allocated interrupts like MSI goes wrong.

   This lower bound is used to exclude the IO/APIC legacy GSI space as
   that must stay reserved for the legacy interrupts.

   In case that the system, e.g. VM, does not advertise an IO/APIC the
   lower bound stays at 0.

   0 is an invalid interrupt number except for the legacy timer
   interrupt on x86. The return value is unchecked in the core code, so
   it ends up to allocate interrupt number 0 which is subsequently
   considered to be invalid by the caller, e.g. the MSI allocation code.

   A similar problem was already cured for device tree based systems
   years ago, but that missed - or did not envision - the zero IO/APIC
   case.

   Consolidate the zero check and return the provided "from" argument to
   the core code call site, which is guaranteed to be greater than 0.

 - Simplify the X2APIC cluster CPU mask logic for CPU hotplug

   Per cluster CPU masks are required for X2APIC in cluster mode to
   determine the correct cluster for a target CPU when calculating the
   destination for IPIs

   These masks are established when CPUs are borught up. The first CPU
   in a cluster must allocate a new cluster CPU mask. As this happens
   during the early startup of a CPU, where memory allocations cannot be
   done, the mask has to be allocated by the control CPU.

   The current implementation allocates a clustermask just in case and
   if the to be brought up CPU is the first in a cluster the CPU takes
   over this allocation from a global pointer.

   This works nicely in the fully serialized CPU bringup scenario which
   is used today, but would fail completely for parallel bringup of
   CPUs.

   The cluster association of a CPU can be computed from the APIC ID
   which is enumerated by ACPI/MADT.

   So the cluster CPU masks can be preallocated and associated upfront
   and the upcoming CPUs just need to set their corresponding bit.

   Aside of preparing for parallel bringup this is a valuable
   simplification on its own.

 - Remove global variables which control the early startup of secondary
   CPUs on 64-bit

   The only information which is needed by a starting CPU is the Linux
   CPU number. The CPU number allows it to retrieve the rest of the
   required data from already existing per CPU storage.

   So instead of initial_stack, early_gdt_desciptor and initial_gs
   provide a new variable smpboot_control which contains the Linux CPU
   number for now. The starting CPU can retrieve and compute all
   required information for startup from there.

   Aside of being a cleanup, this is also preparing for parallel CPU
   bringup, where starting CPUs will look up their Linux CPU number via
   the APIC ID, when smpboot_control has the corresponding control bit
   set.

 - Make cc_vendor globally accesible

   Subsequent parallel bringup changes require access to cc_vendor
   because confidental computing platforms need special treatment in the
   early startup phase vs. CPUID and APCI ID readouts.

   The change makes cc_vendor global and provides stub accessors in case
   that CONFIG_ARCH_HAS_CC_PLATFORM is not set.

   This was merged from the x86/cc branch in anticipation of further
   parallel bringup commits which require access to cc_vendor. Due to
   late discoveries of fundamental issue with those patches these
   commits never happened.

   The merge commit is unfortunately in the middle of the APIC commits
   so unraveling it would have required a rebase or revert. As the
   parallel bringup seems to be well on its way for 6.5 this would be
   just pointless churn. As the commit does not contain any functional
   change it's not a risk to keep it.

* tag 'x86-apic-2023-04-24' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/ioapic: Don't return 0 from arch_dynirq_lower_bound()
  x86/apic: Fix atomic update of offset in reserve_eilvt_offset()
  x86/coco: Export cc_vendor
  x86/smpboot: Reference count on smpboot_setup_warm_reset_vector()
  x86/smpboot: Remove initial_gs
  x86/smpboot: Remove early_gdt_descr on 64-bit
  x86/smpboot: Remove initial_stack on 64-bit
  x86/apic/x2apic: Allow CPU cluster_mask to be populated in parallel

1  2 
arch/x86/coco/core.c
arch/x86/include/asm/coco.h
arch/x86/kernel/apic/io_apic.c

index f4f0625691fd43d8015404dedc2cd43fd893f575,684f0a910475cf6622bb32535ba47cd9d59f80be..73f83233d25df8481b322456039b49b0f108699f
@@@ -97,9 -76,14 +97,9 @@@ static bool amd_cc_platform_has(enum cc
  #endif
  }
  
 -static bool hyperv_cc_platform_has(enum cc_attr attr)
 -{
 -      return attr == CC_ATTR_GUEST_MEM_ENCRYPT;
 -}
 -
  bool cc_platform_has(enum cc_attr attr)
  {
-       switch (vendor) {
+       switch (cc_vendor) {
        case CC_VENDOR_AMD:
                return amd_cc_platform_has(attr);
        case CC_VENDOR_INTEL:
@@@ -117,14 -103,11 +117,14 @@@ u64 cc_mkenc(u64 val
         * encryption status of the page.
         *
         * - for AMD, bit *set* means the page is encrypted
 -       * - for Intel *clear* means encrypted.
 +       * - for AMD with vTOM and for Intel, *clear* means encrypted
         */
-       switch (vendor) {
+       switch (cc_vendor) {
        case CC_VENDOR_AMD:
 -              return val | cc_mask;
 +              if (sev_status & MSR_AMD64_SNP_VTOM)
 +                      return val & ~cc_mask;
 +              else
 +                      return val | cc_mask;
        case CC_VENDOR_INTEL:
                return val & ~cc_mask;
        default:
  u64 cc_mkdec(u64 val)
  {
        /* See comment in cc_mkenc() */
-       switch (vendor) {
+       switch (cc_vendor) {
        case CC_VENDOR_AMD:
 -              return val & ~cc_mask;
 +              if (sev_status & MSR_AMD64_SNP_VTOM)
 +                      return val | cc_mask;
 +              else
 +                      return val & ~cc_mask;
        case CC_VENDOR_INTEL:
                return val | cc_mask;
        default:
Simple merge
Simple merge