Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Обработка внешнего вектора прерываний PowerPC



Как было описано ранее, процессор переходит по адресу 0x500 в случае внешнего прерывания. Перед тем как продолжить рассмотрение макроса EXCEPTION () в файле head. S, мы рассмотрим следующие строки кода, которые связываются, загружаются


Асинхронный поток выполнения



и отображаются в память таким образом, чтобы они находились по отступу 0x500. Эта ап­паратная таблица переходов работает аналогично ГОТ на х86.

arch/ppc/kernel/head.S

453 /* External interrupt */

454 EXCEPTION(0x500, Hardwarelnterrupt, do_IRQ, EXC_XFER_LITE)

Далее вызывается третий параметр, do_IRQ(). Давайте рассмотрим соответст­вующую функцию.

arch/ppc/kernel/irq.с

510 void do_IRQ(struct pt_regs *regs)

511 {

512 int irq, first = 1;

513 irq_enter();

523 while ((irq = ppc_md.get_irq(regs)) > = 0) {

524 ppc_irq_dispatch_handler(regs, irq);

525 first = 0;

 

526 }

527 if (irq! = -2 & & first)

528 /* С точки зрения SMP это небезопасно... но кого это волнует? */

529 ppc_spurious_interrupts++;
53 0 irq_exit ();

531 }

Строки 513-530

Сообщают коду приоритетного обслуживания прерываний, что мы находимся внутри аппаратного прерывания.

Строка 523

Чтение из контроллера прерываний незаконченного прерывания и преобразование его в номер IRQ (до тех пор, пока не будут обработаны все прерывания).

Строка 524

ppc_ircx_dispatch_handler () обрабатывает прерывание. (Мы рассмотрим эту функцию позже.)

Функция ppc_irq__dispatch_handler () практически идентична функции do_IRQ () для х86:

arch/ppc/kernel/irq.с



Глава 3 • Процессы: принципиальная модель выполнения


428 void ppc__irq_dispatch_handler(struct pt_regs *regs, int irg)

429 {

43 0 int status;

431 struct irqaction *action;

432 irq_desc__t *desc = irq_desc + irq; 433

 

434 kstat_this_cpu.irqs[irq]++;

435 spin_lock(& desc-> lock); 43 6 ack_irq(irq);

 

441 status = desc-> status & ~(IRQ_REPLAY | IRQ_WAITING);

442 if (! (status & IRQ_PER_CPU))

443 status |= IRQ_PENDING; /* мы хотим это обработать */

449 action = NULL;

450 if (likely(! (status & (IRQ__DISABLED | IRQ_INPROGRESS) ) ) ) {

451 action = desc-> action;

452 if (! action ||! action-> handler) {

453 ppc_spurious_interrupts++;

454 printk(KERN_JDEBUG " Unhandled interrupt %x, disabled\n", irq);

455 /* Мы не будем вызывать здесь disable_irq, потому что иначе

попадем в тупик */

456 ++desc-> depth;

457 desc-> status |= IRQ_DISABLED;

458 mask_irq(irq);

459 /* Это настоящее прерывание, находящееся в eoi,

460 к которому мы хотим перейти */

461 goto out;

462 }

463 status & = ~IRQ_PENDING; /* поручение обработки*/

464 if (! (status & IRQ_PER_CPU))

465 status |= IRQ_INPROGRESS; /* мы выполняем обработку */

466 }

567 desc-> status = status;

489 for (;; ) {

490 spin_unlock(& desc-> lock);

491 handle_irq_event(irq, regs, action);

492 spin_lock(& desc-> lock); 493

494 if (likely(! (desc-> status & IRQ_PENDING)))

495 break;

496 desc-> status & = ~IRQ_PENDING;

497 }

498 out:

499 desc-> status & = -IRQ_INPROGRESS;


Асинхронный поток выполнения



511 }

Строка 432

Получает IRQ из параметров и получает доступ к соответствующей irq_desc.

Строка 435

Получает циклическую блокировку описателя IRQ в случае конкурентного доступа к тому же прерыванию другим процессором.

Строка 436

Посылает подтверждение оборудованию. Оборудование реагирует соответствую­щим образом, предотвращая дальнейшую обработку прерываний этого типа до тех пор, пока обработка данного не будет завершена.

Строки 441-443

Очистка флагов IRQ REPLAY и IRQ WAITING. В этом случае IRQ_REPLAY де­монстрирует, что IRQ сбрасывается ранее и перепосылается. IRQ WAITING обо­значает, что IRQ протестировано. (Оба случая выходят за рамки данного обсужде­ния.) В однопроцессорных системах устанавливается флаг IRQ_PENDING, который показывает, что мы выполняем обработку прерывания.

Строка 450

Этот блок кода проверяет состояние, при котором мы не будем обрабатывать прерывание. Если установлены IRQ DISABLED или IRQ_INPROGRESS, мы можем пропустить этот блок кода. Флаг IRQ_DISABLED устанавливается, когда мы не хо­тим, чтобы система отвечала на определенную линию IRQ. Указывает, что прерыва­ние будет обрабатываться процессором. Этот флаг используется в том случае, когда второй процессор многопроцессорной системы пытается обработать то же самое прерывание.

Строки 451-462

Здесь мы проверяем существование обработчика. Если нет, мы делает перерыв и переходим на метку «out» в строке 498.

Строки 463-465

В этой точке мы очищаем все три состояния для необслуживаемых прерываний, как было поручено. Устанавливается флаг IRQ_INPROGRESS, а флаг IRQ PENDING снимается, это означает, что прерывание обработано.

Строки 489-497

Здесь производится обслуживание прерываний. Перед обслуживанием прерываний снимается циклическая блокировка с описателя прерывания. После того как бло-



Глава 3 • Процессы: принципиальная модель выполнения


кировка снята, вызывается вспомогательная функция handle_irq_event (). Эта функция выполняет обработчик прерывания. По завершении снова устанавливается блокировка описателя. Если флаг IRQ PENDING не установлен (другим процес­сором) во время обработки IRQ, цикл прерывается. В противном случае служба опять прерывается.

Обработка прерывания системного таймера PowerPC

Как указано в timer_init (), декрементор жестко привязан к 0x900. Мы можем считать, что счетчик терминала достигнут и вызван обработчик timer_interrupt () в arch/kernel/time.с:

arch/ppc/kernel/head.S

/* Декрементор */ 479 EXCEPTION(0x900, Decremented timer_interrupt, EXC_XFER_LITE)

Вот функция timer_interrupt ():

arch/ppc/kernel/time.с

145 void timer_interrupt(struct pt_regs * regs)

146 {

152 if (atomic_read(& ppc_n_lost_.interrupts)! = 0)

153 do__IRQ(regs);
154

155 irq_enter();

159 if (! user_mode(regs))

160 ppc_do_profile(instruction_pointer(regs));

165 write_seqlock(& xtime_lock);

167 do_timer (regs);

189 if (ppc_md.set__rtc_time(xtime. tv_sec+l + time_offset) == 0)

195 write_sequnlock(& xtime_lock);

198 set_dec(next_dec);

208 irq_exit();

209 }


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-03-25; Просмотров: 931; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.016 с.)
Главная | Случайная страница | Обратная связь