From 7630c26507f2cbddddf40363009278d70e6f556e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 4 Apr 2008 18:41:12 +0000 Subject: [PATCH] Reintroduce UMA_SLAB_KMAP; however, change its spelling to UMA_SLAB_KERNEL for consistency with its sibling UMA_SLAB_KMEM. (UMA_SLAB_KMAP met its original demise in revision 1.30 of vm/uma_core.c.) UMA_SLAB_KERNEL is now required by the jumbo frame allocators. Without it, UMA cannot correctly return pages from the jumbo frame zones to the VM system because it resets the pages' object field to NULL instead of the kernel object. In more detail, the jumbo frame zones are created with the option UMA_ZONE_REFCNT. This causes UMA to overwrite the pages' object field with the address of the slab. However, when UMA wants to release these pages, it doesn't know how to restore the object field, so it sets it to NULL. This change teaches UMA how to reset the object field to the kernel object. Crashes reported by: kris Fix tested by: kris Fix discussed with: jeff MFC after: 6 weeks --- sys/i386/i386/pmap.c | 4 +++- sys/kern/kern_mbuf.c | 3 ++- sys/vm/uma.h | 1 + sys/vm/uma_core.c | 4 ++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 567363abc899..623943f5c9c2 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -561,7 +561,9 @@ static MALLOC_DEFINE(M_PMAPPDPT, "pmap", "pmap pdpt"); static void * pmap_pdpt_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) { - *flags = UMA_SLAB_PRIV; + + /* Inform UMA that this allocator uses kernel_map/object. */ + *flags = UMA_SLAB_KERNEL; return (contigmalloc(PAGE_SIZE, M_PMAPPDPT, 0, 0x0ULL, 0xffffffffULL, 1, 0)); } diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index 4cdb12e23c52..7846be818ce5 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -352,7 +352,8 @@ static void * mbuf_jumbo_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) { - *flags = UMA_SLAB_PRIV; + /* Inform UMA that this allocator uses kernel_map/object. */ + *flags = UMA_SLAB_KERNEL; return (contigmalloc(bytes, M_JUMBOFRAME, wait, (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0)); } diff --git a/sys/vm/uma.h b/sys/vm/uma.h index c082e9633f12..ffa8d628de84 100644 --- a/sys/vm/uma.h +++ b/sys/vm/uma.h @@ -488,6 +488,7 @@ void uma_zone_set_freef(uma_zone_t zone, uma_free freef); */ #define UMA_SLAB_BOOT 0x01 /* Slab alloced from boot pages */ #define UMA_SLAB_KMEM 0x02 /* Slab alloced from kmem_map */ +#define UMA_SLAB_KERNEL 0x04 /* Slab alloced from kernel_map */ #define UMA_SLAB_PRIV 0x08 /* Slab alloced from priv allocator */ #define UMA_SLAB_OFFP 0x10 /* Slab is managed separately */ #define UMA_SLAB_MALLOC 0x20 /* Slab is a large malloc slab */ diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index c32f4d78e0ca..a74ca32c7ca1 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -751,6 +751,8 @@ finished: if (flags & UMA_SLAB_KMEM) obj = kmem_object; + else if (flags & UMA_SLAB_KERNEL) + obj = kernel_object; else obj = NULL; for (i = 0; i < keg->uk_ppera; i++) @@ -871,6 +873,8 @@ slab_zalloc(uma_zone_t zone, int wait) if (flags & UMA_SLAB_KMEM) obj = kmem_object; + else if (flags & UMA_SLAB_KERNEL) + obj = kernel_object; else obj = NULL; for (i = 0; i < keg->uk_ppera; i++)