인터럽트와 인터럽트 핸들러 추가 관련

getfeus의 이미지

인터럽트와 인터럽트 핸들러를 추가 해 보려고 합니다.

버스를 통해 날아오는 데이터는 전혀 없으며, (가상 머신의 게스트머신 커널 입니다.) VMCS레지스터에 인터럽트 통지 벡터에 데이터를 직접 써 넣어 인터럽트를 동작 시킬 생각 입니다.

문제는 이 부분이 아니라, 인터럽트의 등록 자체가 되지 않는 문제 입니다.

인터럽트 추가 방법을 확인하기 위해 타이머 인터럽트를의 추가 방법을 추적/분석 해 보았습니다.

http://getfeus.iptime.org/lxr/source/arch/x86/kernel/time.c?v=3.3.1

이것이 타이머를 추가하는 정보가 들어 있는 파일 입니다.

이곳에 다음 함수들을 추가 하였습니다.

static irqreturn_t custom_interrupt(int irq, void *dev_id)
{
//rintk("setup_irq Success!!!\n");
return IRQ_NONE;
}

static struct irqaction irq31 = {
//.handler = custom_interrupt,
.handler = custom_interrupt,
.flags = IRQF_NO_THREAD,
.name = "custom"
};

void __init setup_custom_irq(void)
{
setup_irq(31, &irq31);
}

추가한 장소도 이 파일 내부 입니다.

다음은 이 함수를 x86_init의 oem 장치 인터럽트 등록 함수 포인터 자리에 추가 하였습니다.

그 결과, 커널이 부팅 되지 않고 일체의 커널 메시지도 확인 할 수 없었습니다.

다음엔, 이 함수를 시스템콜을 사용하여 호출 할 수 있도록 시스템 콜을 추가 하여 보았 습니다.

결과는 첨부한 스크린샷과 같습니다.

보아하니, setup_default_timer가 문제를 일으킨 듯 합니다.

static irqreturn_t custom_interrupt(int irq, void *dev_id)
{
//rintk("setup_irq Success!!!\n");
return IRQ_NONE;
}
함수가 콜백 함수로 불려지는듯 하여 어디서 불려 지는지 제어/흐름을 모르겠는데, 보아하니 이곳에서 dev_id가 잘못 불려져서 타이머 인터럽트 추가 함수가 잘못 작동하는게 아닐까,,, 라고 근거없는 추측을 해봅니다.

혹시 커널컴파일에 밝으신 고수분 계시면 답변좀 부탁 드리겠습니다.

감사합니다.

File attachments: 
첨부파일 크기
Image icon 2012-06-12 14.51.34.png189.61 KB
bushi의 이미지

irq 가 발생했고, 핸들러(들)이 호출됐고, 그 결과가 IRQ_HANDLED 가 아니라면 panic 입니다.

부팅 극초반부터 돌아가야 할 irq 가 아니라면,
다른 irq 등의 mother 겪이라서 irq demux 를 번듯하게 구현하실 것이 아니라면,
request_irq, request_threaded_irq 를 사용하세요.

보고 계시는 부분은 OS 의 tick timer 로 사용할 clockevent source 를 등록하는 곳입니다.
등록된 핸들러도 글렀고, 그 곳에서 꼭 등록할 필요도 없고, 시스템 콜로 불려져도 괜찮은 함수도 아닙니다.

getfeus의 이미지

리턴치만 IRQ_HANDLED로 해서 변경해서 될 일이 아니군요.

인터럽트를 등록하려고 하는 이유는 인터럽트가 불려 졌을때에 프로세스를 보존 시키고 반드시 먼저 처리 해야 하는 중대한 함수가 있기 때문입니다.

시그날도 안되고 오로지 NMI와 같은 바로 처리 되는 핸들러 만으로 처리를 해야 하는 시급한 처리이기 때문에 인터럽트의 추가를 시고하고 있습니다.

outb_p(inb_p(0x61)| 0x80, 0x61);
등을 사용하여 핸들러 함수가 버스에 데이터를 쓰고, 장치에게 액크를 보내는것 같다고 생각 하는데, 제 경우는 어떠한 pci 장치도 존재하지 않습니다.(그래서 핸들러에서 ack 를 보내는 부분이라 생각되는 부분을 빼버렸습니다.)

VCPU(가상 CPU)의 레지스터에 인터럽트벡터 번호를 직접 통지하여 인터럽트 핸들러를 작동 시킬 예정인데 어떠한 장치/가상장치도 존재하지 않는 상태에 이러한 목적을 이룰 수 있을까요?

그리고 말씀하신 핸들러의 오류/핸들러의 호출 방식(x86_init의 구조체에 등록했었습니다 처음엔) 등에 대한 자료를 어디서 확인하면 좋을지 조언좀 부탁 드립니다.

답변 정말 감사합니다.

gurugio의 이미지

드라이버 개발한지 몇년이 지나서 요즘건 모릅니다만
LDD 책에서 공부하면서 개발했었습니다.
참고가 되실까싶어서 링크남깁니다.

http://lwn.net/Kernel/LDD3/

getfeus의 이미지

http://lwn.net/Kernel/LDD3/
의 10장,Interrupt Handling을 읽으며 작업중입니다.

10장 전반부에 나온 샘플코드를 이용하여 인터럽트를 등록하는 함수/핸들러를 등록하였습니다.

irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
//struct timeval tv;
//int written;
//do_gettimeofday(&tv);
/* Write a 16 byte record. Assume PAGE_SIZE is a multiple of 16 */
//written = sprintf((char *)short_head,"%08u.%06u\n", (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec));
//BUG_ON(written != 16);
//short_incr_bp(&short_head, written);
//wake_up_interruptible(&short_queue); /* awake any reading process */
printk("Handle IRQ Success\n");
return IRQ_HANDLED;
}

void __init setup_custom_irq(void)
{
int short_irq, result;
short_irq=31;

if(short_irq>=0)
result = request_irq(short_irq, short_interrupt, IRQF_DISABLED, "short", NULL);
if(result)
{
printk(KERN_INFO "short: can't get assigned irq %i\n",short_irq);
short_irq = -1;
}
else
{
enable_irq(short_irq);
printk(KERN_INFO "Setup IRQ success!!!\n");
}
}

커널크래시가 발생하며, /proc/interrupts에 31번은 여전히 등록되지 않네요.

그리고 책이 쓰여진 것이 꽤 오래된 탓인지 SA_INTERRUPT 플래그는 2004년쯤 사라져 버린 것 같네요.

이후의 버젼의 커널에서 매크로로 SA_INTERRUPT를 IRQF_DISABLED로 처리 한 것을 보고 똑같이 처리를 했습니다.(아마도 우선시 처리해야 하는 인터럽트이니, 인터럽트 처리 도중 다른 인터럽트로 인한 콘텍스트 전환을 막으라. 라는 플래그가 아닐까 짐작중입니다.)

setup_irq를 사용하지 않고, request_irq를 이용 할 경우 시스템콜로도 호출이 가능하며, 제가 짠 간단한 핸들링 함수로도 호출이 되는 줄 알았는데, 아닌것 같네요.

혹시 상세한 사용 방법을 알고 계시는 분 계시면 조언좀 부탁 드립니다.(영어를 잘 못해서 읽고는 있는데 좀 페이스가 느리군요.)

두분의 답변 감사합니다.

getfeus의 이미지

return IRQ_HANDLED;

를 short_interrupt의 리턴치로 지정한 후, x86_init 구조체에 함수포인터를 등록해줘서 작동 시키자 커널이 부팅중 프리징되어 커널메시지조차 뜨지 않던 문제는 해결 되었습니다.

하지만 cat /proc/intrrupts에는 등록한 벡터 번호에 해당하는 인터럽트가 등록 되어 있지 않네요.

getfeus의 이미지

드라이버의 등록 방법이 잘못 된 것 같네요.

arch/x86/kernel/x86_init.c

oem_init필드에 함수포인터를 추가 하였는데... 이 방식으론 안되나 보네요.

좀더 연구 해 보겠습니다.

gurugio의 이미지

드라이버 등록은 커널 소스에 직접 추가하는게 아니라
커널이 제공하는 드라이버 등록 인터페이스를 사용해야하는걸로 알고있습니다.
이름은 기억이 안나지만 드라이버 타입에 따라 register_chdev인가하는 함수도 있고
그리고 드라이버 등록을 위한 자료 구조들도 있구요.

지금 하시는 방식은 커널 소스를 수정하는 방식으로 보입니다.
LDD 책의 초반부를 보시면서 따라해보시는걸 어떨까요.

태훈의 이미지

질문과는 관련없는 내용이지만, 혹시 어떤 프로젝트를 하고 계시는지 알려주실수 있으신가요?

VMCS(는 레지스터가 아닙니다. 메모리의 특정 영역...)랑 VCPU등이 언급되는 것을 보면 Intel VT-x HVM을 활용하는 하이퍼바이저(가상 머신 모니터)
관련 프로젝트를 하고 계시는 것 같은데, 활용 분야가 궁급해서 그렇습니다.

Just do it!

getfeus의 이미지

가상머신을 마이그레이션 시킨 후에, 게스트 머신이 마이그레이션 후 실시간으로 처리 해야 할 작업(이것은 공개 해 드릴수가 없네요 ㅠㅠ)이 있어서(지연되어서는 안됨) 인터럽트를 통해 그 처리 하려고 하고 있습니다.

처음에는, 스냅샷 이미지의 CPU상태를 억지로 바꾼 후(eip등의 레지스터), 마이그레이션 후처리 후 본래의 레지스터 정보로 수정할 생각이었으나, 너무나 코드가 복잡해 져서 인터럽트 핸들러를 통해 NMI인터럽트를 등록하여 처리 하려고 생각 하고 있습니다.

태훈의 이미지

어떤 것을 하시는지 모르겠지만, 악의적 해킹등의 나쁜 일만 아니면 잘 되시길 바랍니다.

저도 어쩌다보니 가상화 분야에 대한 기술을 미약하게나마 익히게 되었는데, 이런 쪽으로 하시는 분이 많이 없어서 많이 외롭습니다.

Just do it!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.