Hi,

I'm trying to set up a system with a bare-metal guest/inmate, with shared 
memory between Linux root cell and inmate, and an (IPI) doorbell interrupt from 
inmate to Linux.

My configs are based on zynqmp-zcu102 (root), gic-demo (inmate). Modified to 
only have only one IVSHMEM device instead of two. 

Many things are working; gic-demo demo application runs correctly and from 
Linux I can access the shared memory via an uio device. However I'm stuck at 
generating the doorbell interrupt from inmate to Linux. 

# lsuio
uio0: name=uio_ivshmem, version=0.0.1, events=0
        map[0]: addr=0x00000000FC100000, size=4096
        map[1]: addr=0x0000000800400000, size=1048576

#cat /proc/interrupts
...
229:          0          0          0     GICv2 136 Edge      uio_ivshmem
...

I modified the gic-demo application slightly to generate a doorbell in the 
timer interrupt handler method. I attempt the generate the doorbell by writing 
the doorbell register in the ivshmem register region (map0). 
(https://github.com/henning-schild-work/ivshmem-guest-code/blob/master/device_spec.txt)

unsigned long* reg = (unsigned long*)0xFC100000;
*(reg + 3) = 1; // doorbell at offset 12byte

On Linux side the doorbell is seen (events=1) only as soon as the inmate is 
destroyed, see log below. For the inmate, the gic-demo timer interrupt is only 
handled once, likely because there is another interrupt pending.

# ./jailhouse cell start inmate0
Started cell "inmate0"
# lsuio
uio0: name=uio_ivshmem, version=0.0.1, events=0
        map[0]: addr=0x00000000FC100000, size=4096
        map[1]: addr=0x0000000800400000, size=1048576
# ./jailhouse cell shutdown inmate0
Cell "inmate0" can be loaded
# lsuio
uio0: name=uio_ivshmem, version=0.0.1, events=0
        map[0]: addr=0x00000000FC100000, size=4096
        map[1]: addr=0x0000000800400000, size=1048576
# ./jailhouse cell destroy inmate0
Closing cell "inmate0"
Page pool usage after cell destruction: mem 43/996, remap 69/131072
[  222.899818] ivshmem_handler irq: 229
[  222.920548] Detected VIPT I-cache on CPU3
[  222.920599] CPU3: Booted secondary processor [410fd034]
[  222.934074] Destroyed Jailhouse cell "inmate0"
# lsuio
uio0: name=uio_ivshmem, version=0.0.1, events=1
        map[0]: addr=0x00000000FC100000, size=4096
        map[1]: addr=0x0000000800400000, size=1048576

Message "[  222.899818] ivshmem_handler irq: 229" originates from a printk 
statement I added to "irqreturn_t ivshmem_handler(int irq, struct uio_info 
*dev_info)", which seems to be called only when the cpu is returned to Linux.

It seems the doorbell is generated for the core I perform the register write 
on. How do I generate doorbells for other cores? Am I using a correct method to 
generate doorbells in the first place? Are there other options to do so?

Kind regards, Jasper

-- 
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 jailhouse-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
/*
 * Jailhouse, a Linux-based partitioning hypervisor
 *
 * Configuration for gic-demo inmate on Xilinx ZynqMP ZCU102 eval board:
 * 1 CPU, 64K RAM, 1 serial port
 *
 * Copyright (c) Siemens AG, 2016
 *
 * Authors:
 *  Jan Kiszka <jan.kis...@siemens.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 */

#include <jailhouse/types.h>
#include <jailhouse/cell-config.h>

#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])

struct {
	struct jailhouse_cell_desc cell;
	__u64 cpus[1];
	struct jailhouse_memory mem_regions[4];
    struct jailhouse_pci_device pci_devices[1];
} __attribute__((packed)) config = {
	.cell = {
		.signature = JAILHOUSE_CELL_DESC_SIGNATURE,
		.revision = JAILHOUSE_CONFIG_REVISION,
		.name = "inmate0",
		.flags = JAILHOUSE_CELL_PASSIVE_COMMREG,

		.cpu_set_size = sizeof(config.cpus),
		.num_memory_regions = ARRAY_SIZE(config.mem_regions),
		.num_irqchips = 0,
		.pio_bitmap_size = 0,
		.num_pci_devices = ARRAY_SIZE(config.pci_devices),
	},

	.cpus = {
		0x8,
	},

	.mem_regions = {
		/* UART */ {
			.phys_start = 0xff010000,
			.virt_start = 0xff010000,
			.size = 0x1000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED,
		},
		/* RAM */ {
			.phys_start = 0x800600000,
			.virt_start = 0,
			.size = 0x00010000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE,
		},
		/* IVSHMEM shared memory region for 00:00.0 */ {
		    .phys_start = 0x800400000,
		    .virt_start = 0x800400000,
		    .size = 0x100000,
		    .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_ROOTSHARED,
		},
		/* IVSHMEM register region for 00:00.0 */ {
		    .phys_start = 0x0fc100000,
		    .virt_start = 0x0fc100000,
		    .size = 4096,
		    .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_ROOTSHARED,
		},
	},

	.pci_devices = {
	    /* 00:00.0 */ {
	        .type = JAILHOUSE_PCI_TYPE_IVSHMEM,
	        .bdf = 0 << 3,
	        .bar_mask = {
	            0xffffff00, 0xffffffff, 0x00000000,
	            0x00000000, 0x00000000, 0x00000000,
	        },
	        .shmem_region = 2,
	        .shmem_protocol = JAILHOUSE_SHMEM_PROTO_VETH,
	    },
	},	
};
/*
 * Jailhouse, a Linux-based partitioning hypervisor
 *
 * Configuration for Xilinx ZynqMP ZCU102 eval board
 *
 * Copyright (c) Siemens AG, 2016
 *
 * Authors:
 *  Jan Kiszka <jan.kis...@siemens.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
 * Reservation via device tree: 0x800000000..0x83fffffff
 */

#include <jailhouse/types.h>
#include <jailhouse/cell-config.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

struct {
	struct jailhouse_system header;
	__u64 cpus[1];
	struct jailhouse_memory mem_regions[5];
	struct jailhouse_irqchip irqchips[1];
	struct jailhouse_pci_device pci_devices[1];
} __attribute__((packed)) config = {
	.header = {
		.signature = JAILHOUSE_SYSTEM_SIGNATURE,
		.revision = JAILHOUSE_CONFIG_REVISION,
		.hypervisor_memory = {
			.phys_start = 0x800000000,
			.size =       0x000400000,
		},
		.debug_console = {
			.address = 0xff000000,
			.size = 0x1000,
			.flags = JAILHOUSE_CON1_TYPE_XUARTPS |
				 JAILHOUSE_CON1_ACCESS_MMIO |
				 JAILHOUSE_CON1_REGDIST_4 |
				 JAILHOUSE_CON2_TYPE_ROOTPAGE,
		},
		.platform_info = {
			.pci_mmconfig_base = 0xfc000000,
			.pci_mmconfig_end_bus = 0,
			.pci_is_virtual = 1,
			.arm = {
				.gic_version = 2,
				.gicd_base = 0xf9010000,
				.gicc_base = 0xf902f000,
				.gich_base = 0xf9040000,
				.gicv_base = 0xf906f000,
				.maintenance_irq = 25,
			},
		},
		.root_cell = {
			.name = "ZynqMP-ZCU102",

			.cpu_set_size = sizeof(config.cpus),
			.num_memory_regions = ARRAY_SIZE(config.mem_regions),
			.num_irqchips = ARRAY_SIZE(config.irqchips),
			.num_pci_devices = ARRAY_SIZE(config.pci_devices),

			.vpci_irq_base = 136-32,
		},
	},

	.cpus = {
		0xf,
	},

	.mem_regions = {
		/* MMIO (permissive) */ {
			.phys_start = 0xfd000000,
			.virt_start = 0xfd000000,
			.size =	      0x03000000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_IO,
		},
		/* RAM */ {
			.phys_start = 0x0,
			.virt_start = 0x0,
			.size = 0x80000000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE,
		},
		/* RAM */ {
			.phys_start = 0x800600000,
			.virt_start = 0x800600000,
			.size = 0x7fa00000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE,
		},
		/* IVSHMEM shared memory region for 00:00.0 */ {
			.phys_start = 0x800400000,
			.virt_start = 0x800400000,
			.size = 0x100000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE,
		},
		/* cfg */ {
			.phys_start = 0x8000000000,
			.virt_start = 0x8000000000,
			.size = 0x01000000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_IO,
		},
	},

	.irqchips = {
		/* GIC */ {
			.address = 0xf9010000,
			.pin_base = 32,
			.pin_bitmap = {
				0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
			},
		},
	},

	.pci_devices = {
		/* 00:00.0 */ {
			.type = JAILHOUSE_PCI_TYPE_IVSHMEM,
			.bdf = 0 << 3,
			.bar_mask = {
				0xffffff00, 0xffffffff, 0x00000000,
				0x00000000, 0x00000000, 0x00000000,
			},
			.shmem_region = 3,
			.shmem_protocol = JAILHOUSE_SHMEM_PROTO_VETH,
		},
	},
};

Attachment: plnx_aarch64-system.dts
Description: Binary data

/*
 * Jailhouse, a Linux-based partitioning hypervisor
 *
 * Copyright (c) ARM Limited, 2014
 * Copyright (c) Siemens AG, 2014-2017
 *
 * Authors:
 *  Jean-Philippe Brucker <jean-philippe.bruc...@arm.com>
 *  Jan Kiszka <jan.kis...@siemens.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 */

#include <mach.h>
#include <inmate.h>

#define BEATS_PER_SEC		10

static u64 ticks_per_beat;
static volatile u64 expected_ticks;

/*
 * Enables blinking LED
 * Banana Pi:           register 0x1c2090c, pin 24
 * Orange Pi Zero:      register 0x1c20810, pin 17
 */
static void *led_reg;
static unsigned int led_pin;

unsigned long counter = 0;
unsigned long* ptr = (unsigned long*)0x800400000;
unsigned long* reg = (unsigned long*)0xFC100000;

static void handle_IRQ(unsigned int irqn)
{
	static u64 min_delta = ~0ULL, max_delta = 0;
	u64 delta;

	if (irqn != TIMER_IRQ)
		return;

	delta = timer_get_ticks() - expected_ticks;
	if (delta < min_delta)
		min_delta = delta;
	if (delta > max_delta)
		max_delta = delta;
	
	counter++;

	printk("Timer fired (%3u), jitter: %6ld ns, min: %6ld ns, max: %6ld ns\n",
		   counter,
	       (long)timer_ticks_to_ns(delta),
	       (long)timer_ticks_to_ns(min_delta),
	       (long)timer_ticks_to_ns(max_delta));

	*ptr = counter;
	*(reg + (0*8) + 3) = 1;

	if (led_reg)
		mmio_write32(led_reg, mmio_read32(led_reg) ^ (1 << led_pin));

	expected_ticks = timer_get_ticks() + ticks_per_beat;
	timer_start(ticks_per_beat);
}

void inmate_main(void)
{
	printk("Initializing the GIC...\n");
	gic_setup(handle_IRQ);
	gic_enable_irq(TIMER_IRQ);

	printk("Initializing the timer...\n");
	ticks_per_beat = 10 * (timer_get_frequency() / BEATS_PER_SEC);
	expected_ticks = timer_get_ticks() + ticks_per_beat;
	timer_start(ticks_per_beat);

	led_reg = (void *)(unsigned long)cmdline_parse_int("led-reg", 0);
	led_pin = cmdline_parse_int("led-pin", 0);

	while (1)
		asm volatile("wfi" : : : "memory");
}

Reply via email to