Commit 2985e5b9 authored by Jeff Dike's avatar Jeff Dike

Fixed highmem support for 2.5.

parent fc72f345
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
struct mem_region { struct mem_region {
char *driver; char *driver;
unsigned long start_pfn;
unsigned long start; unsigned long start;
unsigned long len; unsigned long len;
void *mem_map; void *mem_map;
...@@ -51,7 +52,7 @@ extern unsigned long task_size; ...@@ -51,7 +52,7 @@ extern unsigned long task_size;
extern int init_mem_user(void); extern int init_mem_user(void);
extern int create_mem_file(unsigned long len); extern int create_mem_file(unsigned long len);
extern void setup_range(int fd, char *driver, unsigned long start, extern void setup_range(int fd, char *driver, unsigned long start,
unsigned long total, int need_vm, unsigned long pfn, unsigned long total, int need_vm,
struct mem_region *region, void *reserved); struct mem_region *region, void *reserved);
extern void map(unsigned long virt, unsigned long p, unsigned long len, extern void map(unsigned long virt, unsigned long p, unsigned long len,
int r, int w, int x); int r, int w, int x);
...@@ -62,8 +63,6 @@ extern void setup_memory(void *entry); ...@@ -62,8 +63,6 @@ extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out); extern unsigned long find_iomem(char *driver, unsigned long *len_out);
extern int init_maps(struct mem_region *region); extern int init_maps(struct mem_region *region);
extern int nregions(void); extern int nregions(void);
extern void init_range(int n, int fd, char *driver, unsigned long start,
unsigned long len, struct mem_region *region);
extern int reserve_vm(unsigned long start, unsigned long end, void *e); extern int reserve_vm(unsigned long start, unsigned long end, void *e);
extern unsigned long get_vm(unsigned long len); extern unsigned long get_vm(unsigned long len);
extern void setup_physmem(unsigned long start, unsigned long usable, extern void setup_physmem(unsigned long start, unsigned long usable,
......
...@@ -71,10 +71,10 @@ void mem_init(void) ...@@ -71,10 +71,10 @@ void mem_init(void)
{ {
unsigned long start; unsigned long start;
max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT;
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
highmem_start_page = phys_page(__pa(high_physmem)); highmem_start_page = phys_page(__pa(high_physmem));
#endif #endif
max_mapnr = num_physpages = max_low_pfn;
/* clear the zero-page */ /* clear the zero-page */
memset((void *) empty_zero_page, 0, PAGE_SIZE); memset((void *) empty_zero_page, 0, PAGE_SIZE);
...@@ -97,7 +97,11 @@ void mem_init(void) ...@@ -97,7 +97,11 @@ void mem_init(void)
/* this will put all low memory onto the freelists */ /* this will put all low memory onto the freelists */
totalram_pages = free_all_bootmem(); totalram_pages = free_all_bootmem();
totalram_pages += highmem >> PAGE_SHIFT; totalhigh_pages = highmem >> PAGE_SHIFT;
totalram_pages += totalhigh_pages;
num_physpages = totalram_pages;
max_mapnr = totalram_pages;
max_pfn = totalram_pages;
printk(KERN_INFO "Memory: %luk available\n", printk(KERN_INFO "Memory: %luk available\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
kmalloc_ok = 1; kmalloc_ok = 1;
...@@ -108,7 +112,7 @@ pte_t *kmap_pte; ...@@ -108,7 +112,7 @@ pte_t *kmap_pte;
pgprot_t kmap_prot; pgprot_t kmap_prot;
#define kmap_get_fixmap_pte(vaddr) \ #define kmap_get_fixmap_pte(vaddr) \
pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
void __init kmap_init(void) void __init kmap_init(void)
{ {
...@@ -142,8 +146,8 @@ static void __init fixrange_init(unsigned long start, unsigned long end, ...@@ -142,8 +146,8 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
if (pmd_none(*pmd)) { if (pmd_none(*pmd)) {
pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
set_pmd(pmd, __pmd(_KERNPG_TABLE + set_pmd(pmd, __pmd(_KERNPG_TABLE +
(unsigned long) pte)); (unsigned long) __pa(pte)));
if (pte != pte_offset(pmd, 0)) if (pte != pte_offset_kernel(pmd, 0))
BUG(); BUG();
} }
vaddr += PMD_SIZE; vaddr += PMD_SIZE;
...@@ -183,7 +187,8 @@ int init_maps(struct mem_region *region) ...@@ -183,7 +187,8 @@ int init_maps(struct mem_region *region)
return(0); return(0);
} }
static int setup_one_range(int fd, char *driver, unsigned long start, int len, static int setup_one_range(int fd, char *driver, unsigned long start,
unsigned long pfn, int len,
struct mem_region *region) struct mem_region *region)
{ {
int i; int i;
...@@ -195,7 +200,22 @@ static int setup_one_range(int fd, char *driver, unsigned long start, int len, ...@@ -195,7 +200,22 @@ static int setup_one_range(int fd, char *driver, unsigned long start, int len,
printk("setup_range : no free regions\n"); printk("setup_range : no free regions\n");
return(-1); return(-1);
} }
init_range(i, fd, driver, start, len, region);
if(fd == -1)
fd = create_mem_file(len);
if(region == NULL){
region = alloc_bootmem_low_pages(sizeof(*region));
if(region == NULL)
panic("Failed to allocating mem_region");
}
*region = ((struct mem_region) { driver : driver,
start_pfn : pfn,
start : start,
len : len,
fd : fd } );
regions[i] = region;
return(i); return(i);
} }
...@@ -215,7 +235,7 @@ static void init_highmem(void) ...@@ -215,7 +235,7 @@ static void init_highmem(void)
pgd = swapper_pg_dir + __pgd_offset(vaddr); pgd = swapper_pg_dir + __pgd_offset(vaddr);
pmd = pmd_offset(pgd, vaddr); pmd = pmd_offset(pgd, vaddr);
pte = pte_offset(pmd, vaddr); pte = pte_offset_kernel(pmd, vaddr);
pkmap_page_table = pte; pkmap_page_table = pte;
kmap_init(); kmap_init();
...@@ -231,7 +251,8 @@ void setup_highmem(unsigned long len) ...@@ -231,7 +251,8 @@ void setup_highmem(unsigned long len)
phys = physmem_size; phys = physmem_size;
do { do {
cur = min(len, (unsigned long) REGION_SIZE); cur = min(len, (unsigned long) REGION_SIZE);
i = setup_one_range(-1, NULL, -1, cur, NULL); i = setup_one_range(-1, NULL, -1, phys >> PAGE_SHIFT, cur,
NULL);
if(i == -1){ if(i == -1){
printk("setup_highmem - setup_one_range failed\n"); printk("setup_highmem - setup_one_range failed\n");
return; return;
...@@ -485,14 +506,15 @@ int nregions(void) ...@@ -485,14 +506,15 @@ int nregions(void)
return(NREGIONS); return(NREGIONS);
} }
void setup_range(int fd, char *driver, unsigned long start, unsigned long len, void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn,
int need_vm, struct mem_region *region, void *reserved) unsigned long len, int need_vm, struct mem_region *region,
void *reserved)
{ {
int i, cur; int i, cur;
do { do {
cur = min(len, (unsigned long) REGION_SIZE); cur = min(len, (unsigned long) REGION_SIZE);
i = setup_one_range(fd, driver, start, cur, region); i = setup_one_range(fd, driver, start, pfn, cur, region);
region = regions[i]; region = regions[i];
if(need_vm && setup_region(region, reserved)){ if(need_vm && setup_region(region, reserved)){
kfree(region); kfree(region);
...@@ -500,6 +522,7 @@ void setup_range(int fd, char *driver, unsigned long start, unsigned long len, ...@@ -500,6 +522,7 @@ void setup_range(int fd, char *driver, unsigned long start, unsigned long len,
return; return;
} }
start += cur; start += cur;
if(pfn != -1) pfn += cur;
len -= cur; len -= cur;
} while(len > 0); } while(len > 0);
} }
...@@ -535,8 +558,8 @@ int setup_iomem(void) ...@@ -535,8 +558,8 @@ int setup_iomem(void)
for(i = 0; i < num_iomem_regions; i++){ for(i = 0; i < num_iomem_regions; i++){
iomem = &iomem_regions[i]; iomem = &iomem_regions[i];
setup_range(iomem->fd, iomem->name, -1, iomem->size, 1, NULL, setup_range(iomem->fd, iomem->name, -1, -1, iomem->size, 1,
NULL); NULL, NULL);
} }
return(0); return(0);
} }
...@@ -554,7 +577,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end, ...@@ -554,7 +577,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
{ {
struct mem_region *region = &physmem_region; struct mem_region *region = &physmem_region;
struct vm_reserved *reserved = &physmem_reserved; struct vm_reserved *reserved = &physmem_reserved;
unsigned long cur; unsigned long cur, pfn = 0;
int do_free = 1, bootmap_size; int do_free = 1, bootmap_size;
do { do {
...@@ -566,7 +589,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end, ...@@ -566,7 +589,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
if((region == NULL) || (reserved == NULL)) if((region == NULL) || (reserved == NULL))
panic("Couldn't allocate physmem region or vm " panic("Couldn't allocate physmem region or vm "
"reservation\n"); "reservation\n");
setup_range(-1, NULL, start, cur, 1, region, reserved); setup_range(-1, NULL, start, pfn, cur, 1, region, reserved);
if(do_free){ if(do_free){
unsigned long reserve = reserve_end - start; unsigned long reserve = reserve_end - start;
...@@ -579,6 +602,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end, ...@@ -579,6 +602,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
do_free = 0; do_free = 0;
} }
start += cur; start += cur;
pfn += cur >> PAGE_SHIFT;
len -= cur; len -= cur;
region = NULL; region = NULL;
reserved = NULL; reserved = NULL;
...@@ -628,6 +652,56 @@ struct mem_region *page_region(struct page *page, int *index_out) ...@@ -628,6 +652,56 @@ struct mem_region *page_region(struct page *page, int *index_out)
return(NULL); return(NULL);
} }
unsigned long page_to_pfn(struct page *page)
{
struct mem_region *region = page_region(page, NULL);
return(region->start_pfn + (page - (struct page *) region->mem_map));
}
struct mem_region *pfn_to_region(unsigned long pfn, int *index_out)
{
struct mem_region *region;
int i;
for(i = 0; i < NREGIONS; i++){
region = regions[i];
if(region == NULL)
continue;
if((region->start_pfn <= pfn) &&
(region->start_pfn + (region->len >> PAGE_SHIFT) > pfn)){
if(index_out != NULL)
*index_out = i;
return(region);
}
}
return(NULL);
}
struct page *pfn_to_page(unsigned long pfn)
{
struct mem_region *region = pfn_to_region(pfn, NULL);
struct page *mem_map = (struct page *) region->mem_map;
return(&mem_map[pfn - region->start_pfn]);
}
unsigned long phys_to_pfn(unsigned long p)
{
struct mem_region *region = regions[phys_region_index(p)];
return(region->start_pfn + (phys_addr(p) >> PAGE_SHIFT));
}
unsigned long pfn_to_phys(unsigned long pfn)
{
int n;
struct mem_region *region = pfn_to_region(pfn, &n);
return(mk_phys((pfn - region->start_pfn) << PAGE_SHIFT, n));
}
struct page *page_mem_map(struct page *page) struct page *page_mem_map(struct page *page)
{ {
return((struct page *) page_region(page, NULL)->mem_map); return((struct page *) page_region(page, NULL)->mem_map);
...@@ -730,7 +804,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) ...@@ -730,7 +804,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
struct page *pte; struct page *pte;
do { do {
pte = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0); pte = alloc_pages(GFP_KERNEL, 0);
if (pte) if (pte)
clear_highpage(pte); clear_highpage(pte);
else { else {
......
...@@ -77,25 +77,6 @@ int create_mem_file(unsigned long len) ...@@ -77,25 +77,6 @@ int create_mem_file(unsigned long len)
return(fd); return(fd);
} }
void init_range(int n, int fd, char *driver, unsigned long start,
unsigned long len, struct mem_region *region)
{
if(fd == -1)
fd = create_mem_file(len);
if(region == NULL){
region = malloc(sizeof(*region));
if(region == NULL){
perror("Allocating mem_region");
exit(1);
}
}
*region = ((struct mem_region) { driver : driver,
start : start,
len : len,
fd : fd } );
regions[n] = region;
}
int setup_region(struct mem_region *region, void *entry) int setup_region(struct mem_region *region, void *entry)
{ {
void *loc, *start; void *loc, *start;
......
...@@ -43,10 +43,11 @@ extern void *region_va(unsigned long phys); ...@@ -43,10 +43,11 @@ extern void *region_va(unsigned long phys);
#define __pa(virt) region_pa((void *) (virt)) #define __pa(virt) region_pa((void *) (virt))
#define __va(phys) region_va((unsigned long) (phys)) #define __va(phys) region_va((unsigned long) (phys))
extern unsigned long page_to_pfn(struct page *page);
extern struct page *pfn_to_page(unsigned long pfn);
extern struct page *phys_to_page(unsigned long phys); extern struct page *phys_to_page(unsigned long phys);
#define pfn_to_page(pfn) (phys_to_page(pfn << PAGE_SHIFT))
#define page_to_pfn(page) (page_to_phys(page) >> PAGE_SHIFT)
#define virt_to_page(v) (phys_to_page(__pa(v))) #define virt_to_page(v) (phys_to_page(__pa(v)))
extern struct page *page_mem_map(struct page *page); extern struct page *page_mem_map(struct page *page);
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
struct page *pte) struct page *pte)
{ {
set_pmd(pmd, __pmd(_PAGE_TABLE + phys_addr(page_to_phys(pte)))); set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
} }
extern pgd_t *pgd_alloc(struct mm_struct *); extern pgd_t *pgd_alloc(struct mm_struct *);
......
...@@ -187,15 +187,17 @@ static inline void pgd_clear(pgd_t * pgdp) { } ...@@ -187,15 +187,17 @@ static inline void pgd_clear(pgd_t * pgdp) { }
extern struct page *pte_mem_map(pte_t pte); extern struct page *pte_mem_map(pte_t pte);
extern struct page *phys_mem_map(unsigned long phys); extern struct page *phys_mem_map(unsigned long phys);
extern unsigned long phys_to_pfn(unsigned long p);
extern unsigned long pfn_to_phys(unsigned long pfn);
#define pte_page(x) pfn_to_page(pte_pfn(x)) #define pte_page(x) pfn_to_page(pte_pfn(x))
#define pte_address(x) (__va(pte_val(x) & PAGE_MASK)) #define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
#define mk_phys(a, r) ((a) + (r << REGION_SHIFT)) #define mk_phys(a, r) ((a) + (r << REGION_SHIFT))
#define phys_addr(p) ((p) & ~REGION_MASK) #define phys_addr(p) ((p) & ~REGION_MASK)
#define phys_page(p) (phys_mem_map(p) + ((phys_addr(p)) >> PAGE_SHIFT)) #define phys_page(p) (phys_mem_map(p) + ((phys_addr(p)) >> PAGE_SHIFT))
#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) #define pte_pfn(x) phys_to_pfn(pte_val(x))
#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) #define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
static inline pte_t pte_mknewprot(pte_t pte) static inline pte_t pte_mknewprot(pte_t pte)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment