All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-24 19:17 Gabriele Moabiti
  2008-10-26 23:49 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-24 19:17 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Jan Kiszka, Xenomai help

[-- Attachment #1: Type: text/plain, Size: 900 bytes --]


Gilles Chanteperdrix wrote:
> Gabriele Moabiti wrote:
>> (...)
>> I consider now ManageCustomExceptions a function that do nothing.
>> (...)
>> INT 0 (divide error) or 16 (fpu exception)
>> The system hangs.
> 
> It will not work. It is because you have to handle the exception.
> Otherwise, when returning to user-space, your programs tries the faulty
> exception again, triggers the handler, which does nothing, and loops
> indefinitely...
> 

so the int 1 and 3 are instead signed as traps with the old CS:EIP points past instruction causing exception...

Sorry for the question (I have always done it directly in asm reprogramming customizing the IDT), do I have to change the eip of the pt_regs structure passed to the function?

Thank you,
    Gabriele



      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1490 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-24 15:30 Gabriele Moabiti
  0 siblings, 0 replies; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-24 15:30 UTC (permalink / raw)
  To: Gilles Chanteperdrix, Jan Kiszka; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 490 bytes --]



>INT 0 (divide error) or 16 (fpu exception)
>The system hangs.

Maybe it's not too clear: the system hangs if i return RTHAL_EVENT_STOP doing nothing.
The next one is the default behaviour when xenomai manage itself the exception.

>When I pass to xenomai It doesn't handle the exception and relax the thread an propagate
>to linux (I think as expected to do).


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1143 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-24 13:53 Gabriele Moabiti
  2008-10-24 17:43 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-24 13:53 UTC (permalink / raw)
  To: Gilles Chanteperdrix, Jan Kiszka; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 1374 bytes --]

I have upgraded the kernel to 2.6.24 + xenomai 2.4.5

The custom exception doesn't work as I expected.

static rthal_trap_handler_t old_trap_handler;
  In an the kernel driver I set:
old_trap_handler = rthal_trap_catch(&custom_trap_fault);
  the custom handler is:
static int custom_trap_fault(unsigned event, unsigned domid, void *data)
{
  if (is_my_application(...) && i_want_to_manage_exception(event)) {
    ManageCustomExceptions();
    return RTHAL_EVENT_STOP; /* 1=STOP */
 }
 return ((rthal_trap_handler_t) old_trap_handler)(event, domid, data);
}

The exception 7 is passed to the xenomai exception handler (TS flag).

I consider now ManageCustomExceptions a function that do nothing.

INT 3 or 1
Adeos does what I expected. It returns and nothing done.
The program continue happy to the next instruction.

INT 0 (divide error) or 16 (fpu exception)
The system hangs.
When I pass to xenomai It doesn't handle the exception and relax the thread an propagate
to linux (I think as expected to do).
[in the xnpod_trap_fault, xnpod_shadow_p is true then xnshadow_relax is performed so the 
 routine return 0 (RTHAL_EVENT_PROPAGATE)]

Is it possible to customize such exceptions? Am I missing something?

    Gabriele


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1869 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-15 15:30 Gabriele Moabiti
  2008-10-15 15:39 ` Jan Kiszka
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-15 15:30 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 617 bytes --]

>rtdm_printk (read 'k' as 'kernel') is for driver development in kernel
>space only.
>
>What you are looking for is rt_printf from the rtdk lib. See related
>example (examples/native/rtprint.c).

At kernel level I usually write defines like this

#define DBG_PRINTF(expr...) \
  if (rtdm_in_rt_context()) \
    rtdm_printk(expr); \
  else if (kdb_on) \
    printk(expr)

to manage xenomai and linux output for debugging.
Is there something like rtdm_in_rt_context for the user space?


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1190 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-14 10:01 Gabriele Moabiti
  2008-10-14 10:21 ` Jan Kiszka
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-14 10:01 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 969 bytes --]

>>> You should trace the exception path in the I-pipe patch to find the
>>>  point where your exception handling callback is not called.
>> 
>> will it be a large print work or there are another ways to do that?
>> :)
>
> Yes, a small printk works. There is not that much code involved.

I have found the problem.
I used a printf some instructions before the call to the asm blob.
Once removed seems to work as expected.
I've seen also that writing
      printf(expr); \
      rt_task_set_mode(0, T_PRIMARY, 0);
it works (I think printf does a switch to secondary domain).
Now I should use a user-space-no-problem print like rtdm_printk in kernel space.
The docs says rtdm_in_rt_context and rtdm_printk are avalaible but in the rtdm.h
there is no trace of them and I can't use rtdm_driver.h 'cause it's kernel only...

    Gabriele


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1609 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-13  9:55 Gabriele Moabiti
  0 siblings, 0 replies; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-13  9:55 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 839 bytes --]

>> I did't specify I have passed mem=xxx to kernel to take the upper 16MB
>> I think the RTDM mapping works.
>
>Yes, but I still think this is useless. If your user-space code expects
>to be running from 1MB to 16MB, it expects this for virtual addresses,
>not for physical addresses. So, I really think you should mmap the 1MB
>to 16MB region by passing the start address to mmap with the MMAP_FIXED
>flag.

I have tried fixed mmap mode and I have no luck.
Outside the mmap mapped memory exceptions are trapped with rthal_trap_catch.
Inside the callback doesn't work... seems to dislike mapped memory...

Another question:
Is it right I can set rthal_trap_catch only in kernel rt/nrt task?

    Gabriele


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1406 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-11 19:32 Gabriele Moabiti
  2008-10-11 19:34 ` Gilles Chanteperdrix
  2008-10-11 21:35 ` Philippe Gerum
  0 siblings, 2 replies; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-11 19:32 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 1017 bytes --]


>Yes, but I still think this is useless. If your user-space code expects
>to be running from 1MB to 16MB, it expects this for virtual addresses,
>not for physical addresses. So, I really think you should mmap the 1MB
>to 16MB region by passing the start address to mmap with the MMAP_FIXED
>flag.

I know my way to solve this problem is very strange but there are some reasons.
It is done for compatibility reasons (DMA and a strange architecture with custom gdt entries needed by the asm blob...)
In this application I don't need contiguous physical addresses so I will try the mmap fixed way.
I didn't only want to fork the driver but it is not a big problem...

>You should trace the exception path in the I-pipe patch to find the
>point where your exception handling callback is not called.

will it be a large print work or there are another ways to do that? :)

    Gabriele


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1578 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-10 17:57 Gabriele Moabiti
  0 siblings, 0 replies; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-10 17:57 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 589 bytes --]


> 
> my_rt_task_func()
> {
>     int 3 // This is trapped by the custom exception routine (forwarded to xenomai handler). The terminal write
>             // trace/breakpoint trap
> }

> This does not tell me how the thread running "my_rt_task_func" is created.

In user space with the standard

        rt_task_create(&task_desc, "MyTaskName", TASK_STKSZ, TASK_PRIO, TASK_MODE);
        rt_task_start(&task_desc, &my_rt_task_func, NULL);

    Gabriele



      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1254 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-10 16:02 Gabriele Moabiti
  2008-10-10 16:04 ` Gilles Chanteperdrix
  2008-10-11 11:24 ` Gilles Chanteperdrix
  0 siblings, 2 replies; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-10 16:02 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 1505 bytes --]





>> It's a long story... I know anonymous mapping is better but I have need physical contiguos memory
>> (not for the test of course). The binary blob has fixed addresses between 1 to 16 MB so I have mapped the 
>To do this with RTDM, you should use rtdm_mmap_to_user, not
>rtdm_iomap_to_user. And to do this with an anonymous mapping, you simply
>need to pass the address where you want the mmap to occur to mmap, and
>pass MAP_FIXED to mmap flags, this is all documented in mmap manual.

I did't specify I have passed mem=xxx to kernel to take the upper 16MB so I have to use rtdm_iomap_to_user.
I think the RTDM mapping works.

>> I start UD from the terminal and the terminal always report the right error.
>
>Ok. Probably the I-pipe patch only calls your callback for real-time
>tasks. Is the thread which runs the binary blob created with xenomai
>services ?

my_rt_task_func()
{
    int 3 // This is trapped by the custom exception routine (forwarded to xenomai handler). The terminal write
            // trace/breakpoint trap
}

my_rt_task_func()
{
    call *asm_part
}

asm_part --- (it has been copied in the first 16 MB of user task mapped to the 16 MB kernel memory)

int 3 // This is not trapped by the custom exception routine however the a trace/breakpoint trap is raised and
       //  it is written in terminal
---

    Gabriele


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 2247 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-10 15:24 Gabriele Moabiti
  2008-10-10 15:38 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-10 15:24 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 2535 bytes --]


> Where does custom_except leaves, in kernel-space or user-space ?

I have called rthal_trap_catch in the init function of the KD.
I have tried also in a rt task inside KD.

>> - KD has an rtdm interface to map the 16 MB memory on user space with
>> rtdm_iomap_to_user.
>> - UD starts and It maps with the rtdm (rtdm_iomap_to_user)
>
>This is completely useless. You can use an anonymous mapping in
>user-space, you will not need the help from an rtdm driver. And your
>mapping needs to be executable (you need to pass PROT_EXEC to mmap).
>> 
>> - UD copy a binary asm x86 test fpu (some instructions to generate
>> exceptions for tests) in the 16 MB memory mapped
>
>If you do that, your binary needs to be relocatable, that is its code
>must not depend on the address at which it is loaded. Are you sure your
>binary blob has this property ?

It's a long story... I know anonymous mapping is better but I have need physical contiguos memory
(not for the test of course). The binary blob has fixed addresses between 1 to 16 MB so I have mapped the first 15 MB of the UD (starting to 1 MB). I Know it is very strange...

>> 
>> - UD start the real time task
>> 
>> Now here is a the problem. If I invoke an exception (int 3, floating
>> point exception and so on) outside the 16 MB mapped memory
>> "custom_except" is called ok. If the same code is invoked into the 16
>> MB mapped memory the program crash (and this is ok) reporting the
>> description of the exception in the terminal (also this is ok) but
>> "custom_except" is not called!
>
>Who reports the exception, then ? 

I start UD from the terminal and the terminal always report the right error.

>Are you sure the exception reported is
>the one you expect ? 

Yes, I tried floating point, debug (int 3), page fault..

>IOW, are you sure the problem is not that your
>memory mapping is not executable ?

The PROT_EXEC flag is set.
If I try to execute some instructions It works.

>> Is there something wrong using the mapped memory in this mode?
>> NOTE: I am using xenomai 2.4.0rc1 with kernel 2.6.23
>>Is this a joke ? Why choosing a release candidate of a release which
>>happened since then ? Why not using the latest stable release ?

you are right. It will be better to use the latest one (not rc). I had an already patched kernel
(with an other working xenomai application)

    Gabriele



      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 3311 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-10 13:50 Gabriele Moabiti
  2008-10-10 14:00 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-10 13:50 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 1330 bytes --]



> Xenomai uses rthal_trap_catch, so, you can use Xenomai code as an example.

Named
KD: kernel driver (ring 0).
UD: user space task (ring 3).

- KD reserve 16 MB  of memory (note: virtual and physical contiguous)

- I use rthal_trap_catch to customize exceptions (redirected to "custom_except" function)
  The "custom_except" function print the number of exception and recall the xenomai standard one.

- KD has an rtdm interface to map the 16 MB memory on user space with rtdm_iomap_to_user.

- UD starts and It maps with the rtdm (rtdm_iomap_to_user)

- UD copy a binary asm x86 test fpu (some instructions to generate exceptions for tests) in the 16 MB memory mapped

- UD start the real time task

Now here is a the problem.
If I invoke an exception (int 3, floating point exception and so on) outside the 16 MB mapped memory "custom_except" is called ok.
If the same code is invoked into the 16 MB mapped memory the program crash (and this is ok) reporting the description of the exception in the terminal (also this is ok) but "custom_except" is not called!

Is there something wrong using the mapped memory in this mode?

NOTE:
I am using xenomai 2.4.0rc1 with kernel 2.6.23


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1885 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-08 11:32 Gabriele Moabiti
  2008-10-08 12:29 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-08 11:32 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 1190 bytes --]

>You say yes, then propose to do what I told you was a bad idea. So, I
>repeat: this is a bad idea. 

Ok, now it's clear. This a port of a real time application first developed in DOS
then ported to Windows XP so dirty hacking was the rule.
Sorry for the misunderstanding.

> I think it is better not to touch the
>hardware vector and use the trap interception mechanism proposed by
>Xenomai rthal. And split exception handling in a kernel-space handler
>which signals a user-space server thread.

I think I can do the exception handling in a kernel-space handler without pass to an user space server thread
due to the memory of the process where the SIS live (both data and code) is kernel memory mapped in the user space and SIS.

I had read Adeos is the low level of the real time part and Xenomai is one of the possible
domain. Do I Have to use the rthal_trap_catch function to alter Xenomai? Is there some examples
to better understand how to do? 
NOTE: I have to used rtnet too. Can this customization alterate the behaviour of rtnet?

Thank you


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1740 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
* Re: [Xenomai-help] trap exceptions in user
@ 2008-10-08 10:34 Gabriele Moabiti
  2008-10-08 10:50 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-08 10:34 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Xenomai help

[-- Attachment #1: Type: text/plain, Size: 1451 bytes --]



>I think you are traping yourself with impossible constraints.
>
>Anyway, the only way is register a custom exception handler using rthal
>functions. In your trap handler, you may wake up a user-space server
>thread which role is to handle exceptions (in user-space). This means that:
>- upon exception, you have a switch to the user-space server thread
>context, this will be slow;

Do I change rthal inside xenomai? How can I do?
Is there a benchmark or some number to understand better this slowness (in us)?

>- you have to rewrite the exception handling code, you can not rely
>on the exception handling code that was written in the assembly blob.
>
>I do not think it is a good idea to simply override the exception
>vectors, the kernel uses them, and you certainly want the kernel to
>continue working.
 
Yes I think so

Now SIS is about 500 kb of pure asm and works with a big cli on start and a sti
on finish @ring 0 and reprogram the exception vectors but I want to integrate into xenomai. 

Proposal:

- At start SIS save the addresses of the exception vectors
- When an exception is raised then the processor switch to the custom exception vectors but
  if the SIS is not currently active then jump to the old exception vectors

Is it possible?

Sorry for the large number of questions


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e scrivi la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 2271 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread
[parent not found: <296620.67855.qm@domain.hid>]
* [Xenomai-help] trap exceptions in user
@ 2008-10-03 12:30 Gabriele Moabiti
  2008-10-03 14:58 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Moabiti @ 2008-10-03 12:30 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: Type: text/plain, Size: 692 bytes --]


I need to trap and manage  exceptions (floating point for example).
I want to execute at user domain (x86-ring 3) something like that

real_time_task function:
{
  <set exception handlers> (for example fpu_handler)

  <real time code (asm x86)>  (this code need  custom management of exceptions)

  <release exception handlers>
}

fpu_handler function
{
  ...
}

I need to customize some exception (fpu is the most important) inside real time.
How can I do that?
Is it possible in  the rt user domain? And what about that in the rt-kernel domain?

Thank you


      Scopri il blog di Yahoo! Mail:
Trucchi, novità e la tua opinione.
http://www.ymailblogit.com/blog

[-- Attachment #2: Type: text/html, Size: 1158 bytes --]

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

end of thread, other threads:[~2008-10-26 23:49 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-24 19:17 [Xenomai-help] trap exceptions in user Gabriele Moabiti
2008-10-26 23:49 ` Gilles Chanteperdrix
  -- strict thread matches above, loose matches on Subject: below --
2008-10-24 15:30 Gabriele Moabiti
2008-10-24 13:53 Gabriele Moabiti
2008-10-24 17:43 ` Gilles Chanteperdrix
2008-10-24 17:44   ` Gilles Chanteperdrix
2008-10-15 15:30 Gabriele Moabiti
2008-10-15 15:39 ` Jan Kiszka
2008-10-14 10:01 Gabriele Moabiti
2008-10-14 10:21 ` Jan Kiszka
2008-10-14 12:13   ` Gilles Chanteperdrix
2008-10-13  9:55 Gabriele Moabiti
2008-10-11 19:32 Gabriele Moabiti
2008-10-11 19:34 ` Gilles Chanteperdrix
2008-10-11 21:35 ` Philippe Gerum
2008-10-10 17:57 Gabriele Moabiti
2008-10-10 16:02 Gabriele Moabiti
2008-10-10 16:04 ` Gilles Chanteperdrix
2008-10-11 11:24 ` Gilles Chanteperdrix
2008-10-10 15:24 Gabriele Moabiti
2008-10-10 15:38 ` Gilles Chanteperdrix
2008-10-10 13:50 Gabriele Moabiti
2008-10-10 14:00 ` Gilles Chanteperdrix
2008-10-08 11:32 Gabriele Moabiti
2008-10-08 12:29 ` Gilles Chanteperdrix
2008-10-08 10:34 Gabriele Moabiti
2008-10-08 10:50 ` Gilles Chanteperdrix
     [not found] <296620.67855.qm@domain.hid>
2008-10-08 10:09 ` Gilles Chanteperdrix
2008-10-03 12:30 Gabriele Moabiti
2008-10-03 14:58 ` Gilles Chanteperdrix

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.