LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 05-19-2007, 04:35 AM   #1
qwijibow
Guru
 
Registered: Apr 2003
Location: nottingham england
Distribution: Gentoo
Posts: 2,670

Rep: Reputation: 47
inline assembly causing seg fault in AMD Geode Driver.


Greetings, i have googled for this, and it seems i'm the only person on earth ever making noise about this, so i will give a brief introduction to the AM Geode-lx processors hardware accelerated graphics....

the Geode-LX is an embedded processor by amd ( a clone of the National Smiconducter processor by the same name 'Geode' )

Amd have released an awkward hardware abstraction layer named 'Cimarron'
which is to be used to generate drivers.. it does all hardware access.

This driver is used currently by 2 projects to provide hardware accelerated graphics,

1) in a kernel patch to provide hardware accelerated text in your framebuffer console.

2) in the xorg driver named 'amd'


The Cimarron Driver works by mmaping the hardware registers and writing to them directly... so obviously, when this cimarron driver is statically linked to both the kernel, running in kernel mode, and the xorg driver, running in user mode, it all crashes terribly, as two differant programs are assuming complete control of the cardware... (pretty colours)

The cimarron driver uses a few clever pre-processor definitions to write to work in bother user mode, and in kernel space.

Anyway...

After Studying the two existing drivers, i am now attempting to write a 3rd driver for an embedded device, as the framebufer driver does not expose enough functionality, and the Xorg driver obviosl depends on Xorg, for which the embedded device does not have enough disk space, and does not require all the functionality of Xorg.

I may even end up using DirectFB, and write a driver for that...


NOW... to the actual problem...

I have a segmentation fault at the very first cimarron function call...

just like the other userspace driver for Xorg, before i start mmaping the hardware, i call init_detect_cpu, which seems to scan the PCI bus for the Geode-LX Graphics Hardware.

Code:
    for (bus = 0; bus < 256; bus++) {
        for (device = 0; device < 21; device++) {
            address = 0x80000000 | (bus << 16) | (device << 11);

            data = init_read_pci(address);


            < some code read data and test if its found the hardware >
         }
    }
Code:
unsigned long
init_read_pci(unsigned long address)
{
    OUTD(0xCF8, address);
    return IND(0xCFC);
}
And IND / OUTD can be any of the following inline assembly, depending on how cimarron is configured ( userspace / kernel space / win32 )


Code:
#define OUTD(port, data) cim_outd(port, data)
void
cim_outd(unsigned short port, unsigned long data)
{
    _asm {
    pushf mov eax, data mov dx, port out dx, eax popf}
}

/*-------------------------------------------
 * IND
 * Reads one DWORD from a single I/O address.
 *-------------------------------------------*/

#define IND(port) cim_ind(port)
unsigned long
cim_ind(unsigned short port)
{
    unsigned long data;

    _asm {
    pushf mov dx, port in eax, dx mov data, eax popf}
    return data;
}


#define OUTD(port, data) cim_outd(port, data)
void cim_outd(unsigned short port, unsigned long data);
void
cim_outd(unsigned short port, unsigned long data)
{
    __asm__ __volatile__("outl %0,%w1"::"a"(data), "Nd"(port));
}

/*-------------------------------------------
 * IND
 * Reads one DWORD from a single I/O address.
 *-------------------------------------------*/

#define IND(port) cim_ind(port)
unsigned long cim_ind(unsigned short port);
unsigned long
cim_ind(unsigned short port)
{
    unsigned long value;
    __asm__ __volatile__("inl %w1,%0":"=a"(value):"Nd"(port));

    return value;
}


I ama complete newb to assembly, and cannot work out why these functionsa re causing a seg faulot when i use them, but run perfectly fine in the other userspace Xorg stuff.

i assume there must be some kind of perm() call i need,
i seem to remember userspace splications need to tell the kernel that they intend to write to some hardware addresses like the parallel port.

can anyone shed any light on this.

as usual, AMD have been of no help what so ever.
and their "Technical ducumentation" PDF is nothing more than a picture of the proecessor, along with its speed in Mhz, and L2 cache...

THANKS for putting up with my long winded plea for help....

Chris.
 
Old 05-19-2007, 11:14 AM   #2
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 112Reputation: 112
I have never tried inline assembler with gcc, but I would expect a line like this to fail:
_asm {
pushf mov eax, data mov dx, port out dx, eax popf}

Try reordering it so that it looks like traditional assembler code:
Code:
_asm {
    pushf 
    mov eax,data 
    mov dx,port 
    out dx,eax 
    popf
}
This eliminates the possibility of the command parser getting it wrong.

Other than that the assembler looks OK.

Some versions of x86 assembler (older versions) don't support this: out dx,eax
In those versions, the register containing the port is assumed to be ax while here it is set to dx.

You might try changing the code to look like this:
Code:
_asm {
    pushf 
    mov eax,data 
    mov ax,port 
    out eax 
    popf
}
and see what happens.

Similarly, and to match, this
Code:
    _asm {
    pushf mov dx, port in eax, dx mov data, eax popf}
    return data;
}
would become this:
Code:
_asm {
pushf 
mov ax, port 
in eax
mov data, eax 
popf
}
    return data;
}
You'll also get a segfault instantly if you haven't allocated memory for everything. Particularly, you need to have allocated the memory for the buffer that your data is returned to, and you need to check buffer bounds to make sure you aren't looping past the end of the buffer.

You didn't specify the error messages that go with the segfault so I can't be any more specific.

You can learn a lot more about the assembler directive in gcc by entering this command at the command line:
info '(gcc) Extended Asm'

Presuming, of course, that you have all the gcc documentation installed.
 
Old 08-01-2007, 03:00 PM   #3
qwijibow
Guru
 
Registered: Apr 2003
Location: nottingham england
Distribution: Gentoo
Posts: 2,670

Original Poster
Rep: Reputation: 47
Ahaaa...

Thanks, but i found the problem.

I missed the call to iopl(3), which instructs the kernel to allow a userspace application to write to hardware pci addresses.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Fixed amd geode-klx framebuffer driver... how to sumbit a patch ? qwijibow Programming 0 01-20-2007 04:35 AM
inserting inline assembly in c andystanfordjason Programming 2 01-11-2007 07:28 PM
strcat is causing seg fault (c program) mfrick Programming 3 03-14-2006 10:27 PM
inline assembly in gcc gursev Programming 2 03-04-2005 02:17 AM
Inline Assembly Question tjt Programming 3 08-08-2004 04:38 AM


All times are GMT -5. The time now is 03:41 PM.

Main Menu
 
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration