Skip to contentSkip to conversation

cli()/sti() clarification

DISCUSSION [email protected] 4 participants 4 messages Jul 18, 2002

lore
Share & tools
lore
#0 lore raw

Hi,

I added two system calls, blockintr() and unblockintr() to give cli()/sti() control to userland programs (yes I know its not advisable) but I only want to do it as a test. My test program looks like this:

	blockintr();
	/* Some long calculations */
	unblockintr(); 

The problem is that if I press Ctrl+C during the calculation, the program
terminates. So I checked the _syscallN() and __syscall_return() macros to see if they explicitly call sti() before returning to userspace, but they dont.

Reading the lkml archives, I found that cli() disables only the interrupts, exceptions are allowed, so it makes sense that the SIGINT was delivered, but if thats the case, then how come the SIGINT was delivered from the Ctrl+C? Doesnt this mean that the SIGINT signal was generated as a result of the keyboard interrupt?

I know I am missing something here, would appreciate if someone could point me in the right direction.

Regards,
Irfan Hamid.

#1 lore raw
Quoted 16 lines · [email protected] wrote:

Hi,

I added two system calls, blockintr() and unblockintr() to give cli()/sti() control to userland programs (yes I know its not advisable) but I only want to do it as a test. My test program looks like this:

        blockintr();
        /* Some long calculations */
        unblockintr();

The problem is that if I press Ctrl+C during the calculation, the program terminates. So I checked the _syscallN() and __syscall_return() macros to see if they explicitly call sti() before returning to userspace, but they dont.

Quoted 8 lines

Reading the lkml archives, I found that cli() disables only the interrupts, exceptions are allowed, so it makes sense that the SIGINT was delivered, but if thats the case, then how come the SIGINT was delivered from the Ctrl+C? Doesnt this mean that the SIGINT signal was generated as a result of the keyboard interrupt?

I know I am missing something here, would appreciate if someone could point me in the right direction.

Return from sys to user space is done by executing a "iret" instruction. In addition to picking up the return address and segment it pick up EFLAGS which will contain the interrupt flag as it was saved when the system call was made...

Quoted 8 lines

Regards,
Irfan Hamid.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 6 lines
George Anzinger   [email protected]
High-res-timers: 
http://sourceforge.net/projects/high-res-timers/
Real time sched:  http://sourceforge.net/projects/rtsched/
Preemption patch:
http://www.kernel.org/pub/linux/kernel/people/rml
#2 lore raw
In reply to [email protected]
Quoted 7 lines · [email protected] wrote:

Hi,

I added two system calls, blockintr() and unblockintr() to give cli()/sti() control to userland programs (yes I know its not advisable) but I only want to do it as a test. My test program looks like this:

Quoted 8 lines
        blockintr();
        /* Some long calculations */
        unblockintr();

The problem is that if I press Ctrl+C during the calculation, the program terminates. So I checked the _syscallN() and __syscall_return() macros to see if they explicitly call sti() before returning to userspace, but they dont.

The flag register is saved on the stack and restored by the INT 0x80 and IRET instructions. You would want to change the interrupt flag in that register. Here is an ugly piece of code that is known to work on some kernel version, I don't remember which.

Another approach would be to use ioperm to get access to the IRQ controller, and block interrupts there.

Signature · 3 lines
Kasper Dupont -- der bruger for meget tid på usenet.
For sending spam use mailto:[email protected]
or mailto:[email protected]

/* This piece of code is ugly and inefficient. */

#include <stdlib.h>
#include <linux/module.h>
#include <asm/current.h>
#include "cli.h"

struct my_module {
struct module m;
char name[64];
unsigned long jmp;
unsigned long delta;
} my_module;

static int do_cli()

{
	(*(unsigned long*)(((char*)current)+0x1FF4)) &= ~0x200;
	return 0;
}

static int do_sti()

{
        (*(unsigned long*)(((char*)current)+0x1FF4)) |= 0x200;
        return 0;
}

void init_struct(int (*func)(),struct my_module *dst, struct my_module *p) {
dst->m.size_of_struct = sizeof(struct module); dst->m.next=NULL;
dst->m.name=p->name;
dst->m.size=sizeof(my_module);
dst->m.flags=0;
dst->m.nsyms=0;
dst->m.ndeps=0;
dst->m.syms=NULL;
dst->m.deps=NULL;
dst->m.refs=NULL;
dst->m.init=(void*)&(p->jmp);
dst->m.cleanup=NULL;
dst->m.ex_table_start=NULL;
dst->m.ex_table_end=NULL;
dst->m.persist_start=NULL;
dst->m.persist_end=NULL;
dst->m.can_unload=NULL; sprintf(dst->name,"hack_%d_hack",getpid()); dst->jmp=0xE9909090;
dst->delta=(unsigned long)func-(unsigned long)(p+1);
}

static void kernel_call(int (*func)())
{
struct my_module my_module;
init_struct(func,&my_module,&my_module); init_struct(func,&my_module,(void*)create_module(my_module.name,my_module.m.size)); init_module(my_module.name,&my_module.m); delete_module(my_module.name);
}

void cli()
{
kernel_call(do_cli);
}

void sti()
{
kernel_call(do_sti);
}

#3 lore raw
In reply to [email protected]
Quoted 9 lines · On Thu, 18 Jul 2002 [email protected] wrote:

Hi,

I added two system calls, blockintr() and unblockintr() to give cli()/sti() control to userland programs (yes I know its not advisable) but I only want to do it as a test. My test program looks like this:

	blockintr();
	/* Some long calculations */
	unblockintr(); 

May I ask what are you trying to achieve?

.TM.