public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* [Linux-ia64] still patching syscall into module
@ 2001-07-31 10:57 chas williams
  2001-08-01 11:43 ` chas williams
  2001-08-01 20:59 ` chas williams
  0 siblings, 2 replies; 3+ messages in thread
From: chas williams @ 2001-07-31 10:57 UTC (permalink / raw)
  To: linux-ia64

i solved my problem for the time being by linking directly with the
kernel.  i am again looking at trying to make patch the syscall
table to call a module.

the following does what i want:

GLOBAL_ENTRY(afs_syscall)
        movl r15=0xa0000000001749e0;;
        ld8 r16=[r15],8
        mov r14=gp;;
        ld8 gp=[r15]
        mov b6=r16;;
        br.few b6
END(afs_syscall)

however, its rather inconvenient to use 0xa0000000001749e0 since the
correct value changes somewhat.  normally i suspect one would write:

	addl r15=@ltoff(@fptr(real_afs_syscall#)),gp

but this would be wrong in this case since when the syscall occurred
i would using the kernel's gp and not the module's gp.  so i thought
i would write:

        .globl afs_syscall_fptr
afs_syscall_fptr:
        data8 0x0
        data8 0x0
GLOBAL_ENTRY(afs_syscall)
        movl r15¯s_syscall_fptr

and the module could fill in afs_syscall_fptr during init.  when i load
this though i get the following:

insmod: obj_ia64.c:258: obj_ia64_ins_imm64: Assertion `slot = 1' failed.

after looking the modutil code i guess that insmod is unable to insert
the relocation for my 64-bit absolute reference?  how should i write this?


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Linux-ia64] still patching syscall into module
  2001-07-31 10:57 [Linux-ia64] still patching syscall into module chas williams
@ 2001-08-01 11:43 ` chas williams
  2001-08-01 20:59 ` chas williams
  1 sibling, 0 replies; 3+ messages in thread
From: chas williams @ 2001-08-01 11:43 UTC (permalink / raw)
  To: linux-ia64

i solved most of my patching a syscall to a module problem the following
way:

unsigned char ia64_syscall_stub[] {
        0x05, 0x00, 0x00, 0x00, 0x01, 0x00,   /* [MLX]     nop.m 0x0         */
        0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,   /*           movl r15=0x0;;    */
        0x01, 0x00, 0x00, 0x60,               /*                             */
        0x0b, 0x80, 0x20, 0x1e, 0x18, 0x14,   /* [MMI]     ld8 r16=[r15],8;; */
        0x10, 0x00, 0x3c, 0x30, 0x20, 0xc0,   /*           ld8 gp=[r15]      */
        0x00, 0x09, 0x00, 0x07,               /*           mov b6=r16;;      */
        0x1d, 0x00, 0x00, 0x00, 0x01, 0x00,   /* [MFB]     nop.m 0x0         */
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00,   /*           nop.f 0x0         */
        0x60, 0x00, 0x80, 0x00,               /*           br.few b6;;       */
        0x0c, 0x00, 0x00, 0x00, 0x01, 0x00,   /* [MFI]     nop.m 0x0         */
        0x00, 0x00, 0x00, 0x02, 0x00, 0x00,   /*           nop.f 0x0         */
        0x00, 0x00, 0x04, 0x00                /*           nop.i 0x0         */
};

void ia64_imm64_fixup(unsigned long v, void *code)
{
        unsigned long *bundle = (unsigned long *) code;

        unsigned long insn;
        unsigned long slot1;

        insn = ((v & 0x8000000000000000) >> 27) | ((v & 0x0000000000200000)) |
           ((v & 0x00000000001f0000) <<  6) | ((v & 0x000000000000ff80) << 20) |
           ((v & 0x000000000000007f) << 13);

        slot1 = (v & 0x7fffffffffc00000) >> 22;

        *bundle |= slot1 << 46;
        *(bundle+1) |= insn << 23;
        *(bundle+1) |= slot1 >> 18;
}

at module load time i use ia64_imm64_fixup to patch the initial movl 
in the stub.   its very similar to the way insmod works. i only have
one hurdle left.  after returning from the syscall in the module the gp
needs to be returned to the kernel's gp so that ia64_leave_kernel wont die. 
not sure how to do this since i am new to the itanium.  should i save the rp
in my assembly stub and set the rp to come back to my stub so i can
patch the gp again?  something like:

...
	movl r14=gp
	movl b6=r16
	movl r15=rp
	movl r16=<current ip> cur_iip?
	aadl r16,<skip next bundle>
	br.few b6
	movl gp=r14
	movl rp=r15
	br.few rp



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Linux-ia64] still patching syscall into module
  2001-07-31 10:57 [Linux-ia64] still patching syscall into module chas williams
  2001-08-01 11:43 ` chas williams
@ 2001-08-01 20:59 ` chas williams
  1 sibling, 0 replies; 3+ messages in thread
From: chas williams @ 2001-08-01 20:59 UTC (permalink / raw)
  To: linux-ia64

in case anyone cares i think the following is the answer to my problem

	.globl module_syscall_stub
        alloc r42 = ar.pfs, 8, 3, 6, 0
        mov r41 = b0 
        mov r43 = r32
        mov r44 = r33
        mov r45 = r34
        mov r46 = r35
        mov r47 = r36
        mov r48 = gp
        ;;
        movl r15=<fptr adddress>
        ;;
        ld8 r16=[r15],8
        ;;
        ld8 gp=[r15]
        mov b6=r16
        br.call.sptk.many b0 = b6
        ;;
        mov ar.pfs = r42
        mov b0 = r41
        mov gp = r48

        br.ret.sptk.many b0
	.endp module_syscall_stub

perhaps someone could comment but i mostly just wrote this based on what
i read in the software developer's manual.  i allocate a little space on
the register stack, pass along the args (only 5 actually)  and then call
the routine in the module via its fptr (patched 'dynamically' at insmod)

after returning the gp is restored from the saved registers.  the old
rp is called (which should be ia64_leave_kernel or something similar)


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2001-08-01 20:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-07-31 10:57 [Linux-ia64] still patching syscall into module chas williams
2001-08-01 11:43 ` chas williams
2001-08-01 20:59 ` chas williams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox