[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-rt
Subject:    [rtl] port on the powerPC860
From:       vandwall () col ! bsf ! alcatel ! fr (Pierre Vandwalle)
Date:       1998-10-21 19:42:19
[Download RAW message or body]


Hello,


I have now finished the first part of the port of rt-linux
on the power PC. I have a rt-kernel that runs in an embedded
system ( high end PABX ) using a powerPC 860:
- uniprocessor
- I have not ported the rt-timer for the 860 yet (not much to do)
- I do not know if it works with the 8259 and other PC hardware
- I did not do the floating point register saving (because there is
none in the PowerPC) but it should be fairly easy to do it...

I send you the core of the port, in the case you don't like it
or would like to do something else by yourself, or want to
discuss it no problems... I did a lot of tests and profiling as well.
I am trying to make a patch against a linux-ppc with 860 archive 
(linux-2.1.125) and will post it when done (unless I'm told not
to bother everyone with it:-).


I also propose to use rt-linux in the same way as VxWorks, RTC, VrTX, ChorusOS
 etc.. by using soft rt_task. 
I may be completely mistaken:-) on that point, maybe the possibility already exist 
and I don't see it and I reinvent the wheel: sorry:-) ...

The powerPC chips are the chips mainly used in the industry in embedded
systems, which often use OSes like Vxworks, VrtX... and work with
a lot of concurent tasks.
 As the memory capacity of the embedded systems increase (We still don't
 know what to do with the 16Mb RAM the hardware people gave us the last 
access board:-) it become possible to embed real UNIXes with a lot of new 
functionalities, protected memory, user level applications, nfs. gdb embedded etc...
And thus LINUX is (shoud be) a real possibilities:-)



The code here will change soon a little (to handle system calls),
 but this is the idea...


I have included the switch macro, a code that intercept .int_return
and a function that will cause a rescheduling toward a rt_task on 
return from interrupt.
The idea is that when returning from interrupt, I directly restore the
context of the new rt_task, and that I store in the kernel stack at the 
FREE_OFFSET place where it will have to return (either .int_return for a full
return or the 10: label to return without bottom halves and the rest)

On a rt_task wake up from interrupt I have thus the following:
- linux context saved
- rtl_intercept()
- .rtl_intercept_int_return
- rt_task context is restored
- rt_task treatment
- rt_switch_to: rt_task context is saved, linux context is restored


Don't you think that it would be interesting to extend, in a way, the scope
of rt-linux: to have several rt_task that run concurently in kernel space,
 perform long treatments, may hard mask (and soft mask) and do _not_ block
the soft interrupts.
  
They would be a kind of "soft rt_tasks" : we will set rt_unactive when
such a task is scheduled (on the contrary, we set rt_active when
a hard rt_task is scheduled).

The goal is (as i said above) to emulate the functionalities of a VxWorks,
RTC, ChorusOS etc... which provide concurent kernel threads on a priority based scheme.

As an example, we use ChorusOS on our PABX to handle on the same processor
the three following tasks:
- very fast handling of communication chips (equivalent of usual rt_task)
- critical call handling tasks and packet switching which are very high priority
kernel threads (equivalent of the soft rt_tasks) but does not block the hard disk.
- standard UNIX functionalities (TCP, IP routing, hard drive, shell and
user level aplication)

Called from a softinterrupt, the rt_task_wakeup_from_interrupt function is exactly
a simple kind of "event post" to a soft rt_task, because it will generate a
rescheduling on the return from a _soft_ interruption. An event field in the
RT_TASK struct does the rest:-)

Regards,
	Pierre Vandwalle









-----------------------------------------------


/* this is the interception of int_return, in head.S
 * it is used for the external interrupts and the decrementer 
 * for now */

	.global rtl_intercept_int_return
rtl_intercept_int_return:	
	lis	r20,rt_need_resched@h
	ori	r20,r20,rt_need_resched@l
	lwz     r0,0(r20)
	cmpi    0,r0,1
	beq     19f
	lis	21,rt_current@h
	addi	21,21,rt_current@l
	lwz	22,0(21)
	lis	r23,rt_linux_task@h
	ori	r23,r23,rt_linux_task@l
	cmpw    0,r23,r22
	bne     10b
	cmpi    0,r3,0
	bne     0b     /* if no need to resched and may bottom half */
	b	10b    /* if no need to resched and may not bottom half */
19:	
	lis     r24,0
	stw     r24,0(r20)	
	bl	rt_schedule_half/*this func return the new task address, it doesn't switch*/
	lis	20,rt_current@h
	addi	20,20,rt_current@l
	lwz	22,0(20)
	stw	1,0(22)
	lis	r23,rt_linux_task@h
	ori	r23,r23,rt_linux_task@l
	cmpw    0,r23,r22
	beq	18f
21:	lis	21,10b@h
	addi	21,21,10b@l
	b	20f
18:
	cmpi    0,r3,0
	beq     21b	/* old task was linux which may not bottom half */
	lis	21,int_return@h   /* old task was linux which may bottom half */
	addi	21,21,int_return@l
20:	stw	21,FREE_OFFSET(1)   /* old task isn't linux; perform real switch */
	lwz	1,0(3)
	stw	r3,0(20)
        lwz	0,FREE_OFFSET(1)
	mtlr	0
	blr

------------------------------------------------

/* this is the switch macro, called from rt_schedule, tha stack layout
 * is the same than the linux stack except that FREE_OFFSET store the link
 * (any other place is good if it is not _LINK or _NIP) */

#define rt_switch_to(tsk) \
        __asm__ __volatile__( \
       		"stwu	1,-"STACK_UNDERHEAD"-"INT_FRAME_SIZE"(1)\n\t" \
		"stw    0,"GPR0"(1)\n\t"\
		"stw    2,"GPR2"(1)\n\t"\
		"stw    3,"GPR3"(1)\n\t"\
		"stw    4,"GPR4"(1)\n\t"\
		"stw    5,"GPR5"(1)\n\t"\
		"stw    6,"GPR6"(1)\n\t"\
		"stw    7,"GPR7"(1)\n\t"\
		"stw    8,"GPR8"(1)\n\t"\
		"stw    9,"GPR9"(1)\n\t"\
		"stw    10,"GPR10"(1)\n\t"\
		"stw    11,"GPR11"(1)\n\t"\
		"stw    12,"GPR12"(1)\n\t"\
		"stw    13,"GPR13"(1)\n\t"\
		"stw    14,"GPR14"(1)\n\t"\
		"stw    15,"GPR15"(1)\n\t"\
		"stw    16,"GPR16"(1)\n\t"\
		"stw    17,"GPR17"(1)\n\t"\
		"stw    18,"GPR18"(1)\n\t"\
		"stw    19,"GPR19"(1)\n\t"\
		"stw    20,"GPR20"(1)\n\t"\
		"stw    21,"GPR21"(1)\n\t"\
		"stw    22,"GPR22"(1)\n\t"\
		"stw    23,"GPR23"(1)\n\t"\
		"stw    24,"GPR24"(1)\n\t"\
		"stw    25,"GPR25"(1)\n\t"\
		"stw    26,"GPR26"(1)\n\t"\
		"stw    27,"GPR27"(1)\n\t"\
		"stw    28,"GPR28"(1)\n\t"\
		"stw    29,"GPR29"(1)\n\t"\
		"stw    30,"GPR30"(1)\n\t"\
		"stw    31,"GPR31"(1)\n\t"\
		"mfcr	0\n\t"\
		"stw    0,"_CCR"(1)\n\t"\
		"mfctr	0\n\t"\
		"stw    0,"_CTR"(1)\n\t"\
		"mfspr  0,"XER"\n\t"\
		"stw    0,"_XER"(1)\n\t"\
		"lis    20,"SYMBOL_NAME_STR(rt_current)"@h\n\t"\
		"addi   20,20,"SYMBOL_NAME_STR(rt_current)"@l\n\t"\
		"lwz    22,0(20)\n\t"\
		"stw    1,0(22)\n\t"\
		"lis    21,1f@h\n\t"\
		"addi   21,21,1f@l\n\t"\
		"stw    21,"_NIP"(1)\n\t"\
		"stw    21,"FREE_OFFSET"(1)\n\t"\
		"stw    21,"_LINK"(1)\n\t"\
		"lwz    1,0(%0)\n\t"\
		"stw    %0,0(20)\n\t"\
                "lwz    0,"FREE_OFFSET"(1)\n\t"\
		"mtlr   0\n\t"\
		"blr\n\t"\
		"1: lwz     0,"_CTR"(1)\n\t"\
		"mtctr   0\n\t"\
		"lwz     0,"_CCR"(1)\n\t"\
		"mtcr    0\n\t"\
		"lwz     0,"GPR0"(1)\n\t"\
		"lwz     2,"GPR2"(1)\n\t"\
		"lwz     3,"GPR3"(1)\n\t"\
		"lwz     4,"GPR4"(1)\n\t"\
		"lwz     5,"GPR5"(1)\n\t"\
		"lwz     6,"GPR6"(1)\n\t"\
		"lwz     7,"GPR7"(1)\n\t"\
		"lwz     8,"GPR8"(1)\n\t"\
		"lwz     9,"GPR9"(1)\n\t"\
		"lwz     10,"GPR10"(1)\n\t"\
		"lwz     11,"GPR11"(1)\n\t"\
		"lwz     12,"GPR12"(1)\n\t"\
		"lwz     13,"GPR13"(1)\n\t"\
		"lwz     14,"GPR14"(1)\n\t"\
		"lwz     15,"GPR15"(1)\n\t"\
		"lwz     16,"GPR16"(1)\n\t"\
		"lwz     17,"GPR17"(1)\n\t"\
		"lwz     18,"GPR18"(1)\n\t"\
		"lwz     19,"GPR19"(1)\n\t"\
		"lwz     20,"GPR20"(1)\n\t"\
		"lwz     21,"GPR21"(1)\n\t"\
		"lwz     22,"GPR22"(1)\n\t"\
		"lwz     23,"GPR23"(1)\n\t"\
		"lwz     24,"GPR24"(1)\n\t"\
		"lwz     25,"GPR25"(1)\n\t"\
		"lwz     26,"GPR26"(1)\n\t"\
		"lwz     27,"GPR27"(1)\n\t"\
		"lwz     28,"GPR28"(1)\n\t"\
		"lwz     29,"GPR29"(1)\n\t"\
		"lwz     30,"GPR30"(1)\n\t"\
		"lwz     31,"GPR31"(1)\n\t"\
		"addi    1,1,"STACK_UNDERHEAD"+"INT_FRAME_SIZE"\n\t"\
		:\
		: "r"(tsk)\
		: "cc");


------------------------------------------------
/* function to kick up a rescheduling on the return from interrupt,
 * in rt_prio_sched_o.c */

int rt_task_wakeup_from_interrupt(RT_TASK *task)
{
  if (task==rt_current)
	return 1;

  if (task->state!= RT_TASK_READY) {
    task->state = RT_TASK_READY;
    task->event=WHAT_YOU_WANT;
    rt_need_resched=1;
    return 0;
  }

  return 1;
}
--- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail majordomo@rtlinux.cs.nmt.edu OR
echo "unsubscribe rtl <Your_email>" | mail majordomo@rtlinux.cs.nmt.edu
----
For more information on Real-Time Linux see:
http://www.rtlinux.org/~rtlinux/

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic