Forum Discussion
Altera_Forum
Honored Contributor
16 years agoLinux with MMU on NEEK
Hi, all.
I'm testing Linux MMU version, on my NEEK. http://www.nioswiki.com/linux It works fine and I can use "bash" shell. This is the evident proof that we are using the true 'fork' instead of 'vfork'. May be this will depends on the version, but TSE driver claims an error and doesn't work on this design. The error is
ERROR: altera_tse.c:1666: request_mem_region() failed
I think that this error is caused by misunderstanding of the usage for the function request_mem_region(). Inside of the request_mem_region(), the function __request_region() is called. If the resource has been already registered, this function returns a non-NULL value, that is the pointer for its resource. But the resource 'sgdma_rx_base' is already registered in the initialization process, so this function returns the 'conflict' and
if (!request_mem_region(sgdma_rx_base, sgdma_rx_size, "altera_tse")) {
is always true. So I made a dirty patch,
if (!request_mem_region(sgdma_rx_base, sgdma_rx_size, "altera_tse")) {
reg_resource = __request_region(&iomem_resource, sgdma_rx_base, sgdma_rx_size, "altera_tse", 0);
if (reg_resource != NULL && reg_resource->flags & IORESOURCE_BUSY) {
printk(KERN_ERR "ERROR: %s:%d: request_mem_region() failed\n", __FILE__, __LINE__);
ret = -EBUSY;
goto out_sgdma_rx;
}
}
Moreover, the author is forgetting that the DMA is working in the physical address world, so we need to set the pointers of descripters like
// desc->source = read_addr;
desc->source = virt_to_phys(read_addr);
// desc->destination = write_addr;
desc->destination = virt_to_phys(write_addr);
// desc->next = (unsigned int *)next;
desc->next = (unsigned int *)((unsigned long)next & 0x1fffffffUL);
and so on. Also the frame buffer fb0 will not work well, because the driver 'altfb.c' is not implemented for Linux with MMU version. So I put some codes for altfb_mmap(), like
/* We implement our own mmap to set MAY_SHARE and add the correct size */
static int altfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
unsigned long phys_addr, phys_size;
unsigned long addr;
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
// vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
// vma->vm_start = info->screen_base;
// vma->vm_end = vma->vm_start + info->fix.smem_len;
/* check range */
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
if (offset + size > altfb_fix.smem_len)
return -EINVAL;
vma->vm_flags |= VM_IO | VM_RESERVED;
addr = vma->vm_start;
phys_addr = altfb_fix.smem_start + offset;
if ((offset + size) < altfb_fix.smem_len)
phys_size = size;
else
phys_size = altfb_fix.smem_len - offset;
vma->vm_page_prot = __pgprot(_PAGE_PRESENT|_PAGE_READ|_PAGE_WRITE);
if (remap_pfn_range(vma, addr, phys_addr >> PAGE_SHIFT, phys_size, vma->vm_page_prot))
return -EAGAIN;
return 0;
}
and rewrite the DMA descripters like
desc->next = (void *)virt_to_phys((desc + 1));
So now, I can evoke telnetd and control NEEK through ethernet, and use Nano-X on Linux MMU version, but can't enter ftp session, because 'getservbyname()' function will not work well. I don't know the directory that the souce of 'getservbyname()' is included. Would anyone please tell me where is it? Thank you, in advance.95 Replies
- Altera_Forum
Honored Contributor
Hi,
I repaired my stupid copying bug and changed my shell to 'bash', 'dhclient' works well with UDP checksum, though 'dhclient-script' requires 'sed', 'expr', etc.:p About the SIGBUS error of checksum, please give me time to debug. I'm only a Sunday programmer.:D But I would appreciate receiving the information of SIGBUS error, by setting
. Kazuecho 1 > /proc/sys/kernel/print-fatal-signals - Altera_Forum
Honored Contributor
I had the cache changed in the custom design to the minimum as in the NEEK design (it was 8+8k) and the ethernet works now. *headdesk*
My theory is something isn't getting flagged properly for uncached IO and using the smaller cache just happens to avoid caching those bits. - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- I had the cache changed in the custom design to the minimum as in the NEEK design (it was 8+8k) and the ethernet works now. *headdesk* My theory is something isn't getting flagged properly for uncached IO and using the smaller cache just happens to avoid caching those bits. --- Quote End --- I have a little bit doubt that Nios CPU with MMU can't have over 4Kbytes caches. There are several ways of connecting method for CPU, cache and MMU. For example, 1) CPU -- cache -- MMU -- Memory 2) CPU -- MMU -- cache -- Memory. The first method has low latency, but also has 'synonym problems'. The second method accesses the cache by physical addresses, but has larger latency to the contrary. So I think that Nios CPU takes the next strategy i.e. 3) CPU |--cache --| -- Memory ............|--MMU --| by limiting the size of cache under page size.(Please refer Nios handbook n2cpu_nii5v1.pdf, page 2-10, Figure 2-2.) If so, we can't have both instruction and data caches larger than page size(=4Kbytes). Kazu - Altera_Forum
Honored Contributor
--- Quote Start --- If so, we can't have both instruction and data caches larger than page size(=4Kbytes). --- Quote End --- Is this confirmed by the hardware Gurus ? If yes this would slow down the CPU with dynamic memory greatly. I can't believe that Altera would choose such a silly implementation. I do know that ARM uses the "low latency" CPU->cache->MMU->RAM way, which needs a cache flush with any MMU table update and thus any task switch, thus very bad with complex OSes, while the PC uses the "correct" higher latency CPU->MMU->cache->RAM way, I was told NIOS features a "correct" implementation and with my first tests I found that the RAM latency in fact seems a lot greater than without an MMU and I took this for a confirmation.But of course I might be wrong. -Michael - Altera_Forum
Honored Contributor
Does the MMU system still use the "uncached" bit 31 (0x80000000)?
- Altera_Forum
Honored Contributor
No. The cacheable Bit is in the page descriptor of each virtual page.
-Michael - Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- Is this confirmed by the hardware Gurus ? --- Quote End --- No, not yet. But where is the nest of MMU's Gurus? --- Quote Start --- I can't believe that Altera would choose such a silly implementation. --- Quote End --- Yes, of course, I want to believe that Altera is NOT silly. But the bit order of tlbacc register is silly, there is no present bit, it's silly... Now I tested the 'modprobe' and system call 'init_module'. It works, but unfortunately, the module is loaded in the 'vmalloc' area(0x80000000~). Nios instructions 'call' and 'jmpi' can't jump beyond the boundary of 256MBytes. So the kernel can't reach the module codes and module codes can't call kernel routines. The easiest way to solve this problem is to change 'vmalloc' to 'kmalloc' in the function 'load_module' of the file '/kernel/module.c', as follows.
Yes, OK, I'm sure. It's the file inside the directory /linux-2.6/kernel !:eek: But don't tell Linus about this tampering... Kazu/* Allocate and load the module: note that size of section 0 is always zero, and we rely on this for optional sections. */ static noinline struct module *load_module(void __user *umod, unsigned long len, const char __user *uargs) { Elf_Ehdr *hdr; Elf_Shdr *sechdrs; char *secstrings, *args, *modmagic, *strtab = NULL; char *staging; unsigned int i; unsigned int symindex = 0; unsigned int strindex = 0; unsigned int modindex, versindex, infoindex, pcpuindex; unsigned int num_mcount; struct module *mod; long err = 0; void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ unsigned long *mseg; mm_segment_t old_fs; DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", umod, len, uargs); if (len < sizeof(*hdr)) return ERR_PTR(-ENOEXEC); /* Suck in entire file: we'll want most of it. */ /* vmalloc barfs on "unusual" numbers. Check here */ // if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) if (len > 64 * 1024 * 1024 || (hdr = kmalloc(len, GFP_KERNEL)) == NULL) return ERR_PTR(-ENOMEM); if (copy_from_user(hdr, umod, len) != 0) { err = -EFAULT; goto free_hdr; } /* Sanity checks against insmoding binaries or wrong arch, weird elf version */ if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 || hdr->e_type != ET_REL || !elf_check_arch(hdr) || hdr->e_shentsize != sizeof(*sechdrs)) { err = -ENOEXEC; goto free_hdr; } ............................ err = mod_sysfs_setup(mod, mod->kp, mod->num_kp); if (err < 0) goto unlink; add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); /* Get rid of temporary copy */ // vfree(hdr); kfree(hdr); /* Done! */ return mod; unlink: /* Unlink carefully: kallsyms could be walking list. */ list_del_rcu(&mod->list); synchronize_sched(); module_arch_cleanup(mod); cleanup: kobject_del(&mod->mkobj.kobj); kobject_put(&mod->mkobj.kobj); ftrace_release(mod->module_core, mod->core_size); free_unload: module_unload_free(mod);# if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) free_init: percpu_modfree(mod->refptr);# endif module_free(mod, mod->module_init); free_core: module_free(mod, mod->module_core); /* mod will be freed with core. Don't access it beyond this line! */ free_percpu: if (percpu) percpu_modfree(percpu); free_mod: kfree(args); free_hdr: // vfree(hdr); kfree(hdr); return ERR_PTR(err); truncated: printk(KERN_ERR "Module len %lu truncated\n", len); err = -ENOEXEC; goto free_hdr; } - Altera_Forum
Honored Contributor
--- Quote Start --- Now I tested the 'modprobe' and system call 'init_module'. It works, but unfortunately, the module is loaded in the 'vmalloc' area(0x80000000~). Nios instructions 'call' and 'jmpi' can't jump beyond the boundary of 256MBytes. So the kernel can't reach the module codes and module codes can't call kernel routines. --- Quote End --- Ahh. this is why Kernel Modules don't work with the MMU based distribution. (A "not usable" crit for me). I do hope Hippo and your are able to solve this issue. Thanks for helpin out here !!!! -Michael - Altera_Forum
Honored Contributor
Hi,
Maybe the dynamic linker 'ld.so.1' has some relocation problems, so I'm going to debug it on this weekend. And do we have any other major problems around the kernel of Nios Linux with MMU version? Now, should I tackle the problems of futex and SMP?:D Kazu - Altera_Forum
Honored Contributor
Great ! Thanks :)
-Michael