On 02/23/2017 01:28 PM, [email protected] wrote:
> Il giorno giovedì 23 febbraio 2017 20:39:39 UTC+1, Ralf Ramsauer ha scritto:
>> On 02/23/2017 04:15 AM, [email protected] wrote:
>>> Il giorno mercoledì 22 febbraio 2017 14:48:09 UTC+1, Errico Guidieri ha 
>>> scritto:
>>>> Dear guys,
>>>>     
>>>>     
>>>>
>>>>
>>>>     
>>>>     
>>>> I need to route a specific interrupt to my non-root cell (based
>>>>       on jetson-demo.cell) on a ARM64 device (TegraTX1), and I have the
>>>>       following questions.
>>>>     
>>>>
>>>>
>>>>     
>>>>     
>>>> 1. I've seen in gic-demo that interrupt 27, that seems to be
>>>>       tied to ARMv8 CPU internal Timer, even thought this is not
>>>>       reporterd in TegraX1 RFM AFAICS, is available to the non-root cell
>>>>       even without providing any specific IRQ configuration in the
>>>>       non-root cell configuration (jetson-demo.c cell). However, if I
>>>>       try to enable a different IRQ, the system hangs (I would have
>>>>       expected an exception TBH). Is there any reason why the timer
>>>>       interrupt behaves differently than the others ?
>>>>     
>>>>
>>>>
>>>>     
>>>>     
>>>> 2. How do I configure the non-root cell to route a specific IRQ
>>>>       to my cell  I guess that I've to use the jailhouse_irqchip
>>>>       structure and the .irqchips field, providing the right address and
>>>>       bitmask. However, I can't figure out these values.
>>>>
>>>>       I'm confused since I noted that in the FreeRTOS cell the GIC
>>>>       address differs between the root cell and the non-root cell, and I
>>>>       can't figure out the reason.
>>>>
>>>>       Even the bitmask value is not clear since the bit set by the
>>>>       FreeRTOS cell is IRQNO - 32: is it this a constant requiremet for
>>>>       GIC? In other words in any implementation of ARM that use GIC am I
>>>>       supposed to subtract 32 from the number I find in the Hardware
>>>>       Reference Manual?
>>>>
>>>>     
>>>>     
>>>>
>>>>
>>>>     
>>>>     
>>>> 3. I also noted that the FreeRTOS porting has re-implemented
>>>>       the inmate library from scratch and it does not link against the
>>>>       usual Jailhouse library. Since their implementation provide
>>>>       basically the same services with a few small additions (e.g.,
>>>>       priorities handling for IRQs), I wonder the reason why they have
>>>>       chosen to use a different implementation rather than merging these
>>>>       additions to the mainline project.
>>>>     
>>>>
>>>>
>>>>     
>>>>     
>>>> 4. This question is more a curiosity. In header.S the irq
>>>>       vector entries do not save and restore the scratch/volatile
>>>>       registers. IMHO this seems to not match the ARMv8 ABI and could
>>>>       even bring to abnormal behavior in some circumstances. Is it
>>>>       correct or am I wrong ?
>>>>
>>>>       original ARM porting (32 bit) used GCC
>>>>         __attribute__((interrupt("IRQ")))
>>>>       for vector_irq function, but this strategy is no more available on
>>>>       ARM64 (I don't know why this features has not been added for ARMv8
>>>>       version of the GCC too).
>>>>
>>>>     
>>>>     
>>>>
>>>>
>>>>     
>>>>     
>>>> Many thanks and best regards,
>>>>     
>>>>
>>>>
>>>>     
>>>>     
>>>>               Errico Guidieri
>>>>     
>>>>
>>>>     
>>>> -- 
>>>>
>>>>       Errico Gudieri
>>>> Senior Embedded Engineer
>>>> Phone: +39.050.99.11.224 (122)
>>>> E-mail: [email protected]
>>>>
>>>> EVIDENCE srl
>>>> Via Carducci 56 - Loc. Ghezzano - 56010 - S. Giuliano Terme - Pisa - Italy
>>>> Phone: +39.050.99.11.122 - 224
>>>> Fax: +39.050.99.10.812 - 855
>>>
>>> Thank You Andrea,
>>>
>>> with yours directions I understood better the jailhouse configuration and I 
>>> could make some step forward, but still I cannot make the interrupt in my 
>>> cell.
>>>
>>> The interrupt that I need is GPIO-1. For what I understood by TegraX1 the 
>>> documentation:
>>> 1) its global id is 32
>>> 2) it belongs to Secondary Interrupt Controller (SEC_ICTLR)
>>>
>>> So these basically are the changes that I have dono on jetson-demo.c cell:
>>>
>>>
>>> struct {
>>>         ...
>>>     struct jailhouse_irqchip irqchips[1];
>>> } __attribute__((packed)) config = {
>>>     .cell = {
>>>                 ...
>>>                  /* The following was initially Forgot   :) */
>>>             .num_irqchips = ARRAY_SIZE(config.irqchips),
>>>     },
>>>   
>>>         ...
>>>         
>> Hi Errico,
>>>     .mem_regions = {
>>>             /* GPIOs until exception vectors */ {
>>>                     .phys_start = 0x6000d000,
>>>                     .virt_start = 0x6000d000,
>>>                     .size = 0x2000,
>> Why 0x2000? GPIO region is 0x1000. Exception vectors start at 0x6000f000
>> and GPIO ends at 0x6000d7ff, but that's not the point...
> You are right I just copied the mem_regionfrom the jetson-tx1 cell that I 
> have in a localrepository, but seems to be not aligned to the official one 
> 
>>>                     .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
>>>                             JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED,
>>>             },
>> uh - rootshared. Only share the memory with you root cell if there's no
>> way out, and if you are 100% sure that the root cell won't undo or
>> overwrite settings that you just set in your non-root cell.
>>
>> Try to disable ROOTSHARED, and only activate it as last resort.
>>
> I could shrink the region to the only GPIO-1* (I'm using only the pins of 
> SPI1), but still I need to leave Linux access GPIO-1 to the pins that are not 
> on header J21, or not?
Well, depends if those pins are in use.
> 
> *Can I have a memory region of only 256 bytes? MMU Pages are not bigger (4k 
> 64K)?
Yes, you actually can, Jailhouse supports subpaging. But this introduces
a delay, because the hypervisor then traps on access and has to dispatch
access.
> 
>> What about the Pinmux device, i'm missing it.
>> I just had a quick look into the X1 reference manual, and it looks like
>> it's pretty similar to the K1, and I already successfully transferred
>> all GPIO access to a non-root cell on the K1.
>>
>> Do you 'setup' and configure interrupt edges/levels of your GPIO-device
>> from the root cell before starting the non-root cell?
> 
> No I don't. Where can I find this approach? In any case I would like to do 
> that inside the inmate, if it is possible.
> Just for information I'm able from the inmate cell to configure the GPIO-1, I 
> already have the registers populated with the right values and I can write 
> and read pins value. What I'm not able to do is route/enable the 
> corresponding SPI. 
Yes, but the corresponding SPI is completely different device?

How did you initialise it?

It's not enough to just gic_enable(gpioint), you also need to set the
edge/level of the interrupt (rising/falling/both/...), clear the status
register after the interrupt comes in, ...

Please find my code snippet attached, but beware that this is a bloody
fast hack and was originally written for a Jetson TK1. You may need to
change registers. Whenever I receive an interrupt, the only thing I do
is toggling an output.
> 
>>>                 ... 
>>>     },
>>>     .irqchips = {
>>>            /* GIC */ {
>>>             .address = 0x50041000,
>>>             .pin_base = 32,
>>>             .pin_bitmap = {
>>>                0,
>>>                (1 << ((32 + 32) % 32)), /* GPIO1 */
>> SPI 32, so I suppose you want to remap GPIO1 only, right? Then this
>> looks good.
> 
> Perfect.
> 
>>>                0,
>>>                0,
>>>             }, 
>>>     },
>>>     ...
>>> };
>>>
>>> In the root cell configuration I made GPIO mem region 
>>> JAILHOUSE_MEM_ROOTSHARED and I turned off the GPIO-1 interrupt for the root 
>>> cell:
>>>
>>> .pin_bitmap = {
>>>     0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff
>>> },
>> No need for that. The interrupt won't arrive in the root cell any longer
>> once the non-root cell is started.
> 
> Already undone, thank you.
> 
>>>
>>> But still I'm not hable to turn-on GPIO-1 interrupt in the inmate cell:
>>>
>>> if after a gic_enable_irq(32)
>>>
>>> I try to read the is enabler register:
>>>
>>> /* GIC base address for NVIDIA TEGRA X1 */
>>> #define OSEE_GIC_BASE         (0x50040000U)
>>> #define OSEE_GICD_OFFSET      (0x1000U)
>>> #define OSEE_GICC_OFFSET      (0x2000U)
>>>
>>> /* GICD and GICC base addresses */
>>> #define OSEE_GICD_BASE        (OSEE_GIC_BASE + OSEE_GICD_OFFSET)
>>> #define OSEE_GICC_BASE        (OSEE_GIC_BASE + OSEE_GICC_OFFSET)
>>> #define OSEE_GICD_ISENABLER   (0x0100U)
>>>
>>> static OsEE_bool gicd_isenabler(ISRSource source_id)
>>> {
>>>   unsigned bit = source_id & ((1U << OSEE_GICD_ISENABLER_SHIFT) - 1U);
>>>   unsigned reg_offset = ((source_id >> OSEE_GICD_ISENABLER_SHIFT) << 2U);
>> This looks odd... Sure that this is correct?
>>   Ralf
> 
> I'm quite sure this is right, I took inspiration from what arm trusted 
> firmware does in its own gic-v2 driver.
> Basically masks the lower bits of the SPI to get the "bit position inside the 
> register" + divide the SPI for 32 and multiply the result for 4 to get the 
> register offset.
Yes.

unsigned reg_offset = ((source_id >> OSEE_GICD_ISENABLER_SHIFT) << 2U);

OSEE_GICD_ISENABLER_SHIFT is probably 3, right?

Then you're shifting it three to the right and two back to the left :-)

GICv2 spec:
ISENABLER number is n = m / 32
Offset is 0x100 + 4*n
Bit is m % 32

Compare it to inmates/lib/arm-common/gic-v2.c:
void gic_enable(unsigned int irqn)
{
        mmio_write32(GICD_V2_BASE + GICD_ISENABLER +
                     ((irqn >> 3) & ~0x3),
                     1 << (irqn & 0x1f));
}

Am i missing sth.?
> 
>>>   return (OsEE_bool) (
>>>     (osEE_mmio_read32(OSEE_GICD_BASE + OSEE_GICD_ISENABLER + reg_offset) &
>>>       (1U << bit)) != 0U);
>>> }
>>>
>>> gicd_isenabler(32) return 0
>>>
>>> When
>>> gicd_isenabler(27) return 1
>>>
>>> So do you any Idea abot what I'm doing wrong?
>>>
>>> In any case I would like a comment regarding inmate lib IRQ vectors for 
>>> ARM64 support (point 4 of my original mail), more I undestand how the 
>>> things works, more I suspect that the support i buggy. :)
>>>
>>> Regards,
>>> Errico Guidieri
>>>
> 
> Thank you Ralph for your help.
> 
> Regards,
> Errico Guidieri
> 

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#define CNF 0x500
#define OE  0x510
#define OUT 0x520
#define STA 0x540
#define ENB 0x550
#define LVL 0x560
#define CLR 0x570

#define MUX_PU5 0x3198
#define MUX_PU6 0x319c
#define  MUX_EINPUT (1 << 5)
#define  MUX_TRISTATE (1 << 4)

#define PIN_OUT (1 << 5) /* PU 5 */
#define PIN_IN (1 << 6) /* PU 6 */

static void handler(unsigned int irqn)
{
	/* clear all interrupts. */
	mmio_write32(GPIO_BASE + CLR, 255);

	/* toggle the output */
	mmio_write32(GPIO_BASE + OUT, 0);
	printk("-> INT %u\n", irqn);
	mmio_write32(GPIO_BASE + OUT, PIN_OUT);
}

void cmain(void)
{
	uart->init(uart);
	uart_write("Hello, world!\n");

	uart_write("Initialising Pinmux device\n");
	mmio_write32(PINMUX_BASE + MUX_PU5, 0);
	mmio_write32(PINMUX_BASE + MUX_PU6, MUX_EINPUT | MUX_TRISTATE);

	uart_write("Initialising GPIO device\n");
	mmio_write32(GPIO_BASE + CNF, PIN_OUT | PIN_IN);
	mmio_write32(GPIO_BASE + OE, PIN_OUT);

	mmio_write32(GPIO_BASE + ENB, PIN_IN);
	mmio_write32(GPIO_BASE + LVL, /* PIN_IN | */ (PIN_IN << 8));
	mmio_write32(GPIO_BASE + STA, 0);

	mmio_write32(GPIO_BASE + CLR, 255);

	mmio_write32(GPIO_BASE + OUT, 0);

	uart_write("Initialising GICv2\n");
	gic_setup(handler);
	gic_enable_irq(87+32);

	for(;;) {
		cpu_relax();
	}
}

Reply via email to