> > Could you send me the output of 'insmod -v -m freemware.o' ?
> Sections:       Size      Address   Align
> .this           0000004c  c2822000  2**2
> .rodata         00000829  c282204c  2**0
> __ex_table      00000010  c2822878  2**2
> .text           00003b05  c2822888  2**2
> .data           00000000  c2826390  2**2
> .kstrtab        0000000a  c2826390  2**0
> .bss            000004c8  c282639c  2**2

Argh!  It appears that recent insmod versions rearrange the section
sequence for some reason ...  I'm starting to think that using the
linker script hack is a bad idea.  Could you try the modified version
of retrieve_monitor_pages below, which doesn't rely on any linker 
script at all?

Please apply this patch to the current CVS version, re-run ./configure
and delete the host-linux.ld file (to make sure it isn't used).

After running 'insmod -v -m freemware.o', check out the output 
produced by the printk, and make sure that every page containing
any module code/data (according to the insmod map) is indeed 
among those mapped by this routine.

Bye,
Ulrich


diff -ur freemware/kernel/Makefile fmw-uw/kernel/Makefile
--- freemware/kernel/Makefile   Tue Dec 28 19:41:36 1999
+++ fmw-uw/kernel/Makefile      Thu Dec 30 21:52:39 1999
@@ -30,7 +30,7 @@
 
 # extra kernel CFLAGS and LDFLAGS for each host OS
 KCFLAGS_LINUX  = -D__KERNEL__ -I/usr/src/linux/include -DCPU=586 -DMODULE
-KLDFLAGS_LINUX = -r -T$(srcdir)/host-linux.ld
+KLDFLAGS_LINUX = -r 
 
 KCFLAGS_BEOS   =
 KLDFLAGS_BEOS  = -nostdlib /boot/develop/lib/x86/_KERNEL_
diff -ur freemware/kernel/host-linux.c fmw-uw/kernel/host-linux.c
--- freemware/kernel/host-linux.c       Tue Dec 28 19:39:08 1999
+++ fmw-uw/kernel/host-linux.c  Thu Dec 30 21:51:13 1999
@@ -532,34 +532,29 @@
 void
 retrieve_monitor_pages(void)
 {
-    /* These symbols are defined by the host-linux.ld linker script */
-    extern int freemware_start, freemware_end;
-
-    int start_addr = (int)&freemware_start, end_addr = (int)&freemware_end;
-    int start_page = start_addr >> 12, end_page = ((end_addr-1) >> 12) + 1;
-    int n_pages = end_page - start_page;
-    int i;
-    u32 host_cr3;
-    pageEntry_t *host_pgd;
-
-    printk(KERN_WARNING "freemware: start: %08x end: %08x: init: %08x pages: %d\n",
-           start_addr, end_addr, (unsigned)init_module, n_pages);
-
-    if (n_pages > FMW_MAX_MONITOR_PAGES)
-    {
-        printk(KERN_WARNING "freemware: FMW_MAX_MONITOR_PAGES is too small!\n");
-        return;
-    }
-
-    monitor_pages.start_addr = start_addr;
-    monitor_pages.end_addr   = end_addr;
-    monitor_pages.n_pages    = n_pages;
+    /* 
+     * Retrieve start address and size of this module.
+     *
+     * Note that with old kernels, we cannot access the module info (size),
+     * hence we rely on the fact that Linux lets at least one page of 
+     * virtual address space unused after the end of the module.
+     */
+#ifdef THIS_MODULE
+    int start_page = ((u32)THIS_MODULE) >> 12;
+    int n_pages    = ((THIS_MODULE->size - 1) >> 12) + 1;
+#else
+    int start_page = ((u32)&mod_use_count_) >> 12;
+    int n_pages    = FMW_MAX_MONITOR_PAGES + 1;  /* Size determined below */
+#endif
 
     /*  
      * Grrr.  There doesn't seem to be an exported mechanism to retrieve
      * the physical pages underlying a vmalloc()'ed area.  We do it the
      * hard way ... 
      */
+    pageEntry_t *host_pgd;
+    u32 host_cr3;
+    int i;
 
     asm volatile("movl %%cr3, %0" : "=r" (host_cr3));
     host_pgd = (pageEntry_t *)(phys_to_virt(host_cr3 & ~0xfff));
@@ -570,12 +565,30 @@
         pageEntry_t *pde = host_pgd + (virt_addr >> 22);
         pageEntry_t *pte = (pageEntry_t *)phys_to_virt(pde->base << 12)
                          + ((virt_addr >> 12) & 0x3ff);
+
+        /* If page isn't present, assume end of module */
+        if ( !pde->P || ! pte->P )
+        {
+            n_pages = i;
+            break;
+        }
         
+        /* Abort if our page list is too small */
+        if (i >= FMW_MAX_MONITOR_PAGES)
+        {
+            printk(KERN_WARNING "freemware: FMW_MAX_MONITOR_PAGES is too small!\n");
+            return;
+        }
+
         monitor_pages.page[i] = pte->base << 12;
 
-        //printk(KERN_WARNING "freemware: vm %08lx..%08lx -> page %08lx\n",
-        //       virt_addr, virt_addr + PAGE_SIZE-1, pte->base);
+        printk(KERN_WARNING "freemware: vm %08lx..%08lx -> page %08lx\n",
+               virt_addr, virt_addr + PAGE_SIZE-1, pte->base);
     }
+
+    monitor_pages.start_addr = start_page << 12;
+    monitor_pages.end_addr   = (start_page + n_pages) << 12;
+    monitor_pages.n_pages    = n_pages;
 }
 
 void


-- 
  Ulrich Weigand,
  IMMD 1, Universitaet Erlangen-Nuernberg,
  Martensstr. 3, D-91058 Erlangen, Phone: +49 9131 85-7688

Reply via email to