Re: HIGH MEMORY access

From: Manfred Spraul (manfreds@colorfullife.com)
Date: Wed Apr 12 2000 - 08:08:10 EST


I've written a simple boot-time ioremap function, the patch is attached.
I merged Lyle's modification to the mp table parser (allow
mpc_spec=0x05)

TODO:
* alloc_bootmem_pages() or alloc_bootmem_low_pages()?
fixmap_init() uses alloc_bootmem_low(), but I don't understand why. IIRC
we must use the _low() functions?

* mpparse.c or a generic header file?
it seems that the mp table parser is the only function that needs these
functions, the ACPI routines can use ioremap().

I tested it with both normal and 64G kernels

--
	Manfred

// $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 3 // SUBLEVEL = 99 // EXTRAVERSION = -pre3 --- 2.3/arch/i386/kernel/mpparse.c Sun Feb 27 08:57:07 2000 +++ build-2.3/arch/i386/kernel/mpparse.c Wed Apr 12 14:35:25 2000 @@ -217,17 +217,90 @@ (m->mpc_destapiclint != 1)) BUG(); } +/* + * boot-up ioremap functions: + * + */ +int boot_map_init(void); +void boot_map_cleanup(void); +void* boot_map(unsigned long phys, unsigned int len); + +#define BOOTMAP_ADDR 0x40000000 +pgd_t g_oldpge; + +#if CONFIG_X86_PAE +pmd_t* g_pg_middle; +#endif +pte_t* g_pg_leaf; +int g_next=0; + +int boot_map_init(void) +{ + g_oldpge = swapper_pg_dir[pgd_index(BOOTMAP_ADDR)]; + g_pg_leaf = alloc_bootmem_pages(PAGE_SIZE); +#if CONFIG_X86_PAE + g_pg_middle = alloc_bootmem_pages(PAGE_SIZE); + { + pmd_t new = __pmd(_KERNPG_TABLE + __pa(g_pg_leaf)); + g_pg_middle[0] = new; + } + { + pgd_t new = __pgd(1 + __pa(g_pg_middle)); + + swapper_pg_dir[pgd_index(BOOTMAP_ADDR)] = new; + } +#else + { + pgd_t new = __pgd(_KERNPG_TABLE + __pa(g_pg_leaf)); + swapper_pg_dir[pgd_index(BOOTMAP_ADDR)] = new; + } +#endif + __flush_tlb_all(); + return 1; +} +void boot_map_cleanup(void) +{ + swapper_pg_dir[pgd_index(BOOTMAP_ADDR)] = g_oldpge; + __flush_tlb_all(); + + free_bootmem((unsigned long)g_pg_leaf,PAGE_SIZE); +#ifdef CONFIG_X86_PAE + free_bootmem((unsigned long)g_pg_middle,PAGE_SIZE); +#endif +} + +void* boot_map(unsigned long phys, unsigned int len) +{ + int offset = phys&(PAGE_SIZE-1); + unsigned long result = BOOTMAP_ADDR+g_next*PAGE_SIZE+offset; + + phys=phys&(~(PAGE_SIZE-1)); + len = (len+offset+PAGE_SIZE-1)/PAGE_SIZE; + while(len) { + set_pte(&g_pg_leaf[g_next],mk_pte_phys(phys,PAGE_KERNEL)); + __flush_tlb_one(BOOTMAP_ADDR+g_next*PAGE_SIZE); + g_next++; + len--; + phys += PAGE_SIZE; + } + return (void*)result; +} /* * Read/parse the MPC */ -static int __init smp_read_mpc(struct mp_config_table *mpc) +static int __init smp_read_mpc(unsigned long phys_mpc) { char str[16]; - int count=sizeof(*mpc); - unsigned char *mpt=((unsigned char *)mpc)+count; + int count; + unsigned char *mpt; + struct mp_config_table* mpc; + + if(!boot_map_init()) + return 1; + mpc = boot_map(phys_mpc,sizeof(*mpc)); if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) { panic("SMP mptable: bad signature [%c%c%c%c]!\n", @@ -237,12 +310,18 @@ mpc->mpc_signature[3]); return 1; } + if (mpc->mpc_length > 65536) { + panic("SMP mptable: too long (%d).\n", + mpc->mpc_length); + return 1; + } + mpc = boot_map(phys_mpc,mpc->mpc_length); if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) { panic("SMP mptable: checksum error!\n"); return 1; } - if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) + if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04 && mpc->mpc_spec!=0x05) { printk("Bad Config Table version (%d)!!\n",mpc->mpc_spec); return 1; @@ -263,6 +342,8 @@ /* * Now process the configuration blocks. */ + count=sizeof(*mpc); + mpt=((unsigned char *)mpc)+count; while (count < mpc->mpc_length) { switch(*mpt) { case MP_PROCESSOR: @@ -408,7 +489,7 @@ * defaults. */ if (mpf->mpf_physptr) - smp_read_mpc((void *)mpf->mpf_physptr); + smp_read_mpc(mpf->mpf_physptr); printk("Processors: %d\n", num_processors); /* --- 2.3/include/asm-i386/pgtable.h Fri Mar 3 00:41:00 2000 +++ build-2.3/include/asm-i386/pgtable.h Wed Apr 12 09:19:49 2000 @@ -80,7 +80,7 @@ #define __flush_tlb_one(addr) __flush_tlb() #else #define __flush_tlb_one(addr) \ -__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr)) +__asm__ __volatile__("invlpg %0": :"m" (*(char *) (addr))) #endif /*

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Apr 15 2000 - 21:00:18 EST