x86: fix backwards merge of GDS/SRSO bit
[platform/kernel/linux-starfive.git] / mm / page_alloc.c
index 6e60657..6966881 100644 (file)
@@ -1402,6 +1402,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
                        unsigned int order, bool check_free, fpi_t fpi_flags)
 {
        int bad = 0;
+       bool skip_kasan_poison = should_skip_kasan_poison(page, fpi_flags);
        bool init = want_init_on_free();
 
        VM_BUG_ON_PAGE(PageTail(page), page);
@@ -1476,7 +1477,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
         * With hardware tag-based KASAN, memory tags must be set before the
         * page becomes unavailable via debug_pagealloc or arch_free_page.
         */
-       if (!should_skip_kasan_poison(page, fpi_flags)) {
+       if (!skip_kasan_poison) {
                kasan_poison_pages(page, order, init);
 
                /* Memory is already initialized if KASAN did it internally. */
@@ -5640,9 +5641,12 @@ EXPORT_SYMBOL(get_zeroed_page);
  */
 void __free_pages(struct page *page, unsigned int order)
 {
+       /* get PageHead before we drop reference */
+       int head = PageHead(page);
+
        if (put_page_testzero(page))
                free_the_page(page, order);
-       else if (!PageHead(page))
+       else if (!head)
                while (order-- > 0)
                        free_the_page(page + (1 << order), order);
 }
@@ -6595,7 +6599,21 @@ static void __build_all_zonelists(void *data)
        int nid;
        int __maybe_unused cpu;
        pg_data_t *self = data;
+       unsigned long flags;
 
+       /*
+        * Explicitly disable this CPU's interrupts before taking seqlock
+        * to prevent any IRQ handler from calling into the page allocator
+        * (e.g. GFP_ATOMIC) that could hit zonelist_iter_begin and livelock.
+        */
+       local_irq_save(flags);
+       /*
+        * Explicitly disable this CPU's synchronous printk() before taking
+        * seqlock to prevent any printk() from trying to hold port->lock, for
+        * tty_insert_flip_string_and_push_buffer() on other CPU might be
+        * calling kmalloc(GFP_ATOMIC | __GFP_NOWARN) with port->lock held.
+        */
+       printk_deferred_enter();
        write_seqlock(&zonelist_update_seq);
 
 #ifdef CONFIG_NUMA
@@ -6634,6 +6652,8 @@ static void __build_all_zonelists(void *data)
        }
 
        write_sequnlock(&zonelist_update_seq);
+       printk_deferred_exit();
+       local_irq_restore(flags);
 }
 
 static noinline void __init
@@ -9414,6 +9434,9 @@ static bool pfn_range_valid_contig(struct zone *z, unsigned long start_pfn,
 
                if (PageReserved(page))
                        return false;
+
+               if (PageHuge(page))
+                       return false;
        }
        return true;
 }