diff -urN 2.2.10-bigmem-D/arch/i386/mm/init.c 2.2.10-bigmem/arch/i386/mm/init.c --- 2.2.10-bigmem-D/arch/i386/mm/init.c Sat Aug 7 15:02:59 1999 +++ 2.2.10-bigmem/arch/i386/mm/init.c Sat Aug 7 18:04:24 1999 @@ -228,15 +228,29 @@ #ifdef CONFIG_BIGMEM unsigned long bigmem_start; unsigned long bigmem_end; +unsigned long bigmem_mapnr; int nr_free_bigmem = 0; -pte_t *kmap_pte; +/* NOTE: fixmap_init alloc all the fixmap pagetables contigous on the + physical space so we can cache the place of the first one and move + around without checking the pgd every time. */ +pte_t * kmap_pte, * kmap_pte_req_buf; pgprot_t kmap_prot; -static void kmap_init(void) +#define kmap_get_fixmap_pte(vaddr) \ + pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + +static void __init kmap_init(void) { - unsigned long kmap_vstart = __fix_to_virt(FIX_KMAP_START); + unsigned long kmap_vstart; + + /* cache the first kmap pte */ + kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); + kmap_pte = kmap_get_fixmap_pte(kmap_vstart); + + /* cache the first kmap_req_buf pte */ + kmap_vstart = __fix_to_virt(FIX_KMAP_REQUEST_BEGIN); + kmap_pte_req_buf = kmap_get_fixmap_pte(kmap_vstart); - kmap_pte = pte_offset(pmd_offset(pgd_offset_k(kmap_vstart), kmap_vstart), kmap_vstart); kmap_prot = PAGE_KERNEL; if (boot_cpu_data.x86_capability & X86_FEATURE_PGE) pgprot_val(kmap_prot) |= _PAGE_GLOBAL; @@ -431,11 +445,17 @@ unsigned long tmp; end_mem &= PAGE_MASK; +#ifdef CONFIG_BIGMEM + bigmem_start = PAGE_ALIGN(bigmem_start); + bigmem_end &= PAGE_MASK; +#endif high_memory = (void *) end_mem; #ifndef CONFIG_BIGMEM max_mapnr = num_physpages = MAP_NR(end_mem); #else max_mapnr = num_physpages = PHYSMAP_NR(bigmem_end); + /* cache the bigmem_mapnr */ + bigmem_mapnr = PHYSMAP_NR(bigmem_start); #endif /* clear the zero-page */ diff -urN 2.2.10-bigmem-D/drivers/block/ll_rw_blk.c 2.2.10-bigmem/drivers/block/ll_rw_blk.c --- 2.2.10-bigmem-D/drivers/block/ll_rw_blk.c Wed Mar 24 01:45:19 1999 +++ 2.2.10-bigmem/drivers/block/ll_rw_blk.c Sat Aug 7 19:33:49 1999 @@ -3,6 +3,7 @@ * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, Karl Keyte: Added support for disk statistics + * Andrea Arcangeli : BIGMEM kmap_io_buf(). */ /* @@ -30,6 +31,10 @@ */ static struct request all_requests[NR_REQUEST]; +#ifdef CONFIG_BIGMEM +#include /* needs all_request and needs to be per-arch */ +#endif + /* * The "disk" task queue is used to start the actual requests * after a plug @@ -518,7 +523,11 @@ } else if (req->sector - count == sector) { bh->b_reqnext = req->bh; req->bh = bh; +#ifndef CONFIG_BIGMEM req->buffer = bh->b_data; +#else + req->buffer = kmap_req_buf(req, bh->b_data); +#endif req->current_nr_sectors = count; req->sector = sector; req->nr_sectors += count; @@ -550,7 +559,11 @@ req->sector = sector; req->nr_sectors = count; req->current_nr_sectors = count; +#ifndef CONFIG_BIGMEM req->buffer = bh->b_data; +#else + req->buffer = kmap_req_buf(req, bh->b_data); +#endif req->sem = NULL; req->bh = bh; req->bhtail = bh; @@ -693,7 +706,11 @@ req->nr_sectors = req->current_nr_sectors; printk("end_request: buffer-list destroyed\n"); } +#ifndef CONFIG_BIGMEM req->buffer = bh->b_data; +#else + req->buffer = kmap_req_buf(req, bh->b_data); +#endif return 1; } } diff -urN 2.2.10-bigmem-D/include/asm-i386/fixmap.h 2.2.10-bigmem/include/asm-i386/fixmap.h --- 2.2.10-bigmem-D/include/asm-i386/fixmap.h Thu Aug 5 19:08:01 1999 +++ 2.2.10-bigmem/include/asm-i386/fixmap.h Sat Aug 7 17:50:19 1999 @@ -18,6 +18,7 @@ #include #ifdef CONFIG_BIGMEM #include +#include #include #endif @@ -60,8 +61,10 @@ FIX_LI_PCIB, /* Lithium PCI Bridge B */ #endif #ifdef CONFIG_BIGMEM - FIX_KMAP_START, /* reserved pte's for temporary kernel mappings */ - FIX_KMAP_END = FIX_KMAP_START+(KM_TYPE_NR*NR_CPUS), + FIX_KMAP_BEGIN, + FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, + FIX_KMAP_REQUEST_BEGIN, + FIX_KMAP_REQUEST_END = FIX_KMAP_REQUEST_BEGIN+NR_REQUEST-1, #endif __end_of_fixed_addresses }; diff -urN 2.2.10-bigmem-D/include/asm-i386/io.h 2.2.10-bigmem/include/asm-i386/io.h --- 2.2.10-bigmem-D/include/asm-i386/io.h Fri Aug 6 16:18:27 1999 +++ 2.2.10-bigmem/include/asm-i386/io.h Sat Aug 7 18:20:32 1999 @@ -101,14 +101,13 @@ #include #include - #ifdef CONFIG_BIGMEM -#define __io_virt(x) __va(x) -#define __io_phys(x) __pa(x) -#else +#include +#include +#endif + #define __io_virt(x) ((void *)(PAGE_OFFSET | (unsigned long)(x))) #define __io_phys(x) ((unsigned long)(x) & ~PAGE_OFFSET) -#endif /* * Change virtual addresses to physical addresses and vv. @@ -116,12 +115,63 @@ */ extern inline unsigned long virt_to_phys(volatile void * address) { +#ifndef CONFIG_BIGMEM return __io_phys(address); +#else + /* We must handle the virt_to_phys request to allow block device + drivers to do DMA over the bigmem pages mapped by kmap_req_buf. */ + unsigned long kaddr = (unsigned long) address; + unsigned long koffset; + + /* remeber: FIX_KMAP_REQUEST_END will point to the lower vaddr */ + koffset = kaddr - __fix_to_virt(FIX_KMAP_REQUEST_END); + + /* check if the virtual address fit in the KMAP_REQUEST vmapping */ + if (koffset <= + ((FIX_KMAP_REQUEST_END - FIX_KMAP_REQUEST_BEGIN)<>= PAGE_SHIFT; + /* koffset now is the offset in respect of + FIX_KMAP_REQUEST_END but my kmap_pte_req_buf is an offset + of FIX_KMAP_REQUEST_BEGIN. So now I calculate the + fixmap idx, where `NR_REQUEST-1 <= idx <= 0 */ + idx = koffset - FIX_KMAP_REQUEST_END - FIX_KMAP_REQUEST_BEGIN; + + /* now that I have the idx I can read the physical address + of the kmapped page. */ + phys_addr = pte_val(kmap_pte_req_buf[idx]) & PAGE_MASK; + +#ifdef KMAP_DEBUG + if (!phys_addr) + printk(KERN_WARNING + "kmap_pte_req_buf resolved a NULL page\n"); +#endif + + /* don't forget to add the original offset */ + phys_addr |= kaddr & ~PAGE_MASK; + + return phys_addr; + } +#endif } extern inline void * phys_to_virt(unsigned long address) { +#ifndef CONFIG_BIGMEM return __io_virt(address); +#else + return __va(address); +#endif } extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); diff -urN 2.2.10-bigmem-D/include/asm-i386/kmap.h 2.2.10-bigmem/include/asm-i386/kmap.h --- 2.2.10-bigmem-D/include/asm-i386/kmap.h Thu Aug 5 19:08:02 1999 +++ 2.2.10-bigmem/include/asm-i386/kmap.h Sat Aug 7 18:37:54 1999 @@ -18,16 +18,18 @@ extern unsigned long bigmem_start, bigmem_end; extern int nr_free_bigmem; -extern pte_t *kmap_pte; +extern pte_t *kmap_pte, * kmap_pte_req_buf; extern pgprot_t kmap_prot; +#define is_bigmem_address(kaddr) (__pa(kaddr) >= bigmem_start) + extern inline unsigned long kmap(unsigned long kaddr, enum km_type type) { - if (__pa(kaddr) < bigmem_start) + if (!is_bigmem_address(kaddr)) return kaddr; { enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id(); - unsigned long vaddr = __fix_to_virt(FIX_KMAP_START+idx); + unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN+idx); #ifdef KMAP_DEBUG if (!pte_none(*(kmap_pte-idx))) @@ -49,7 +51,7 @@ { #ifdef KMAP_DEBUG enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id(); - if ((vaddr & PAGE_MASK) == __fix_to_virt(FIX_KMAP_START+idx)) + if ((vaddr & PAGE_MASK) == __fix_to_virt(FIX_KMAP_BEGIN+idx)) { /* force other mappings to Oops if they'll try to access this pte without first remap it */ diff -urN 2.2.10-bigmem-D/include/asm-i386/kmap_req_buf.h 2.2.10-bigmem/include/asm-i386/kmap_req_buf.h --- 2.2.10-bigmem-D/include/asm-i386/kmap_req_buf.h Thu Jan 1 01:00:00 1970 +++ 2.2.10-bigmem/include/asm-i386/kmap_req_buf.h Sat Aug 7 18:38:34 1999 @@ -0,0 +1,29 @@ +#ifndef _ASM_KMAP_REQ_BUF_H +#define _ASM_KMAP_REQ_BUF_H + +#include + +extern inline char * kmap_req_buf(struct request * req, char * b_data) +{ + if (!is_bigmem_address(b_data)) + return b_data; + { + enum fixed_addresses idx = req - all_requests; + unsigned long vaddr, kaddr; + + kaddr = (unsigned long) b_data; + vaddr = __fix_to_virt(FIX_KMAP_REQUEST_BEGIN+idx); + + set_pte(kmap_pte_req_buf-idx, mk_pte(kaddr & PAGE_MASK, kmap_prot)); + /* NOTE: this is SMP safe only on 2.3.x because + previous kernels needed the big kernel lock to + call flush_tlb_all() and kmap_req_buf() can as well + be called from IO-completation irq handlers. + ... thanks to Linus who simplified my life ;). */ + flush_tlb_all(); + + return (char *) (vaddr | (kaddr & ~PAGE_MASK)); + } +} + +#endif /* _ASM_KMAP_REQ_BUF_H */ diff -urN 2.2.10-bigmem-D/include/linux/blk.h 2.2.10-bigmem/include/linux/blk.h --- 2.2.10-bigmem-D/include/linux/blk.h Fri Aug 6 16:17:23 1999 +++ 2.2.10-bigmem/include/linux/blk.h Sat Aug 7 18:16:15 1999 @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -13,13 +14,6 @@ * multiple CPU's.. */ extern spinlock_t io_request_lock; - -/* - * NR_REQUEST is the number of entries in the request-queue. - * NOTE that writes may use only the low 2/3 of these: reads - * take precedence. - */ -#define NR_REQUEST 64 /* * This is used in the elevator algorithm. We don't prioritise reads diff -urN 2.2.10-bigmem-D/include/linux/nr_request.h 2.2.10-bigmem/include/linux/nr_request.h --- 2.2.10-bigmem-D/include/linux/nr_request.h Thu Jan 1 01:00:00 1970 +++ 2.2.10-bigmem/include/linux/nr_request.h Fri Aug 6 16:18:10 1999 @@ -0,0 +1,11 @@ +#ifndef _NR_REQUEST_H +#define _NR_REQUEST_H + +/* + * NR_REQUEST is the number of entries in the request-queue. + * NOTE that writes may use only the low 2/3 of these: reads + * take precedence. + */ +#define NR_REQUEST 64 + +#endif diff -urN 2.2.10-bigmem-D/mm/page_alloc.c 2.2.10-bigmem/mm/page_alloc.c --- 2.2.10-bigmem-D/mm/page_alloc.c Sat Aug 7 15:02:59 1999 +++ 2.2.10-bigmem/mm/page_alloc.c Sat Aug 7 18:05:43 1999 @@ -105,13 +105,16 @@ unsigned long index = map_nr >> (1 + order); unsigned long mask = (~0UL) << order; unsigned long flags; +#ifdef CONFIG_BIGMEM + extern unsigned long bigmem_mapnr; +#endif spin_lock_irqsave(&page_alloc_lock, flags); #define list(x) (mem_map+(x)) #ifdef CONFIG_BIGMEM - if (map_nr >= PHYSMAP_NR(bigmem_start)) { + if (map_nr >= bigmem_mapnr) { area += BIGMEM_LISTS_OFFSET; nr_free_bigmem -= mask; } diff -urN 2.2.10-bigmem-D/mm/swap_state.c 2.2.10-bigmem/mm/swap_state.c --- 2.2.10-bigmem-D/mm/swap_state.c Mon Jan 18 02:27:02 1999 +++ 2.2.10-bigmem/mm/swap_state.c Sat Aug 7 16:35:28 1999 @@ -302,7 +302,11 @@ if (found_page) goto out_free_swap; +#ifndef CONFIG_BIGMEM new_page_addr = __get_free_page(GFP_USER); +#else + new_page_addr = __get_free_page(GFP_BIGUSER); +#endif if (!new_page_addr) goto out_free_swap; /* Out of memory */ new_page = mem_map + MAP_NR(new_page_addr); diff -urN 2.2.10-bigmem-D/mm/vmscan.c 2.2.10-bigmem/mm/vmscan.c --- 2.2.10-bigmem-D/mm/vmscan.c Thu Aug 5 17:52:17 1999 +++ 2.2.10-bigmem/mm/vmscan.c Fri Aug 6 16:30:17 1999 @@ -59,8 +59,7 @@ if (PageReserved(page_map) || PageLocked(page_map) - || ((gfp_mask & __GFP_DMA) && !PageDMA(page_map)) - || PageBIGMEM(page_map)) + || ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))) return 0; /*