OOPS! RE: Sharing memory between user and kernel space

From: Brian D. McGrew
Date: Wed May 31 2006 - 16:52:06 EST


I forgot to include the base struct in the previous mail. Sorry.

I got a lot of good help in the last couple days, thank you to everyone
who responded; I made major progress but I'm still having a hang up and
a bit confused.

In my driver, I allocate this structure:

typedef struct RtcDeviceStruct {
struct RtcShared *shared_host_mem;
} RtcSoftDev;

typedef struct rtc_shared {
unsigned long snap_addrs_loc;
time_t ntimestamp;
} RtcShared;

In the driver like this:

static int
alloc_rtc_usr_shared(RtcSoftDev *rtc_sp) {
unsigned long addr;
unsigned long bytes = PAGE_SIZE << get_order(RTC_COMMON_SIZE);
unsigned long sz;

rtc_sp->shared_host_mem =
__get_free_pages(GFP_KERNEL, get_order(RTC_COMMON_SIZE));

if (rtc_sp->shared_host_mem == NULL) {
debug_out(("alloc_rtc_usr_shared: out of memory.\n"));
return(0);
}

memset((void *)rtc_sp->shared_host_mem, 0, bytes);

for (addr = rtc_sp->shared_host_mem, sz = bytes;
sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {

SetPageReserved(virt_to_page(addr));
}

return(0);
}

And then in my driver mmap routine:

int
rtc_mmap(struct file *filep, struct vm_area_struct *vma) {
RtcSoftDev *rtc_sp = filep->private_data;

unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page = ((rtc_sp->iobase + offset) >> PAGE_SHIFT);

if (offset > __pa(high_memory) || (filep->f_flags & O_SYNC)) {
vma->vm_flags |= VM_IO;
}

vma->vm_flags |= VM_RESERVED;

if (offset == RTC_COMMON_VADDR) {
debug_out(("RTC_COMMON_VADDR: %x\n", offset));

// page = virt_to_phys((void*)((unsigned
long)rtc_sp->shared_host_mem));
// page = page_to_pfn(virt_to_page(phys_to_virt(__pa(page))));
while (size > 0) {
debug_out(("START: %#lx, SIZE: %#lx, OFFSET: %#lx, PAGE:
%#lx\n",
start, size, offset, page));

if (remap_pfn_range(vma,
start,
page,
PAGE_SIZE,
PAGE_SHARED)) {
return(-EAGAIN);
}

start += PAGE_SIZE;
page += PAGE_SIZE;

if (size > PAGE_SIZE) {
size -= PAGE_SIZE;
} else {
size = 0;
}
}
}

else {
debug_out(("RTC_???_OFFSET --- WE'RE BROKEN --- %x\n", offset));
}

return(0);
}

(Obviously I trimmed a lot of excess unrelated code from the stuff
above).

Now the driver like that loads and attaches without blowing up.
However, from userspace, when I open("/dev/mvp_rtc", O_RDWR) and then
try and mmap it, when I read it back, I can read back rtc_shared but I
can't read rtc_shared->snap_addrs_loc.

My main hope is that someone will spot something I'm obviously doing
wrong but if not, my next question is:

Is the virtual address that I get back from the kernel in
all_rtc_usr_shared going to be the same address that I read in
userspace? Because right now I'm getting back something like 0xc11a0000
from the kernel and then I'm seeing something like 0xbf73000 in
userspace.

Thanks again for all the help and with a little more coaching I just
might get this blasted thing working before I retire 99 years from now!

:b!

Brian D. McGrew { brian@xxxxxxxxxxxxx || brian@xxxxxxxxxxxxxxxxxxx }
--
> This is a test. This is only a test!
Had this been an actual emergency, you would have been
told to cancel this test and seek professional assistance!

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