[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [Qemu-arm] [RFC PATCH 12/14] hw/arm/bcm2836: Add the BC
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [Qemu-devel] [Qemu-arm] [RFC PATCH 12/14] hw/arm/bcm2836: Add the BCM2838 which uses a GICv2 |
Date: |
Mon, 9 Sep 2019 19:10:30 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 |
Hi Luc,
On 9/5/19 10:41 AM, Luc Michel wrote:
> On 9/4/19 7:13 PM, Philippe Mathieu-Daudé wrote:
>> The BCM2838 is improvement of the BCM2837:
>> - Cortex-A72 instead of the A53
>> - peripheral block and local soc controller are mapped differently,
>> - GICv2
>> - PCIe block
>> - exhanced MMU to address over 4GiB of SDRAM
>>
>> See https://www.raspberrypi.org/forums/viewtopic.php?t=244479&start=25
>> and https://patchwork.kernel.org/patch/11053097/
>>
>> This patch starts mapping the GICv2 but interrupt lines are NOT
>> wired (yet).
>>
>> This is enough to start running the Ubuntu kernel8.img from [1].
>>
>> Extract the kernel with:
>>
>> $ mkdir bootpart
>> $ guestfish \
>> --ro \
>> -a ubuntu-18.04.3-preinstalled-server-arm64+raspi4.img \
>> -m /dev/sda1
>> Welcome to guestfish, the guest filesystem shell for
>> editing virtual machine filesystems and disk images.
>>
>> ><fs> ls /
>> COPYING.linux
>> LICENCE.broadcom
>> System.map
>> armstub8-gic.bin
>> bcm2710-rpi-3-b-plus.dtb
>> bcm2710-rpi-3-b.dtb
>> bcm2710-rpi-cm3.dtb
>> bcm2711-rpi-4-b.dtb
>> bcm2837-rpi-3-b-plus.dtb
>> bcm2837-rpi-3-b.dtb
>> cmdline.txt
>> config.txt
>> fixup4.dat
>> fixup4cd.dat
>> fixup4db.dat
>> fixup4x.dat
>> kernel8.img
>> overlays
>> start4.elf
>> start4cd.elf
>> start4db.elf
>> start4x.elf
>> ><fs> copy-out / bootpart/
>> ><fs> q
>>
>> Then some progress can be noticed running:
>>
>> $ qemu-system-aarch64 -d unimp,guest_errors,int,in_asm \
>> -M raspi4 \
>> -kernel bootpart/kernel8.img \
>> -dtb bootpart/bcm2711-rpi-4-b.dtb \
>> -initrd bootpart/boot/initrd.img \
>> -append \
>> "earlycon=pl011,0xfe201000 console=ttyAMA0 console=tty1 loglevel=8"
>>
>> Not very interesting, but it runs until configuring the GIC.
>> (remove 'in_asm' if too verbose).
>>
>> TODO:
>>
>> - wire IRQs to the GIC :)
>>
>> - map the SPI bootrom from [3] (boot sequence: [4])
>>
>> - per [2] we could try booting without using the GIC, adding "enable_gic=0"
>> in config.txt. this variable is parsed by the firmware:
>>
>> $ fgrep -r enable_gic bootpart
>> Binary file bootpart/start4x.elf matches
>> Binary file bootpart/start4.elf matches
>> Binary file bootpart/start4db.elf matches
>> Binary file bootpart/start4cd.elf matches
>> bootpart/config.txt:enable_gic=1
>>
>> the stub [5] doesn't seem to check a register for it.
>> maybe it falls back to kernel7l?
>>
>> - decompile start4.elf to check how 'enable_gic' is used
>> using vc4 toolchain from [6]
>>
>> [1] https://github.com/TheRemote/Ubuntu-Server-raspi4-unofficial/releases
>> [2]
>> https://jamesachambers.com/raspberry-pi-ubuntu-server-18-04-2-installation-guide/
>> [3]
>> https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md
>> [4]
>> https://raspberrypi.stackexchange.com/questions/10442/what-is-the-boot-sequence
>> [5]
>> https://github.com/raspberrypi/tools/commit/7f4a937e1bacbc111a22552169bc890b4bb26a94#diff-8c41083e9fa0c98f1c3015e11b897444
>> [6] https://github.com/christinaa/rpi-open-firmware
>>
>> Signed-off-by: Philippe Mathieu-Daudé <address@hidden>
>> ---
>> hw/arm/bcm2836.c | 75 ++++++++++++++++++++++++++++++++++++++++
>> include/hw/arm/bcm2836.h | 3 ++
>> 2 files changed, 78 insertions(+)
>>
>> diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
>> index 019e67b906..d89d7cd71d 100644
>> --- a/hw/arm/bcm2836.c
>> +++ b/hw/arm/bcm2836.c
>> @@ -21,6 +21,7 @@ struct BCM283XInfo {
>> const char *cpu_type;
>> hwaddr peri_base; /* Peripheral base address seen by the CPU */
>> hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
>> + hwaddr gic_base;
>> int clusterid;
>> };
>>
>> @@ -40,9 +41,25 @@ static const BCM283XInfo bcm283x_socs[] = {
>> .ctrl_base = 0x40000000,
>> .clusterid = 0x0,
>> },
>> + {
>> + .name = TYPE_BCM2838,
>> + .cpu_type = ARM_CPU_TYPE_NAME("cortex-a72"),
>> + .peri_base = 0xfe000000,
>> + .ctrl_base = 0xff800000,
>> + .gic_base = 0x40000,
>> + },
>> #endif
>> };
>>
>> +#define GIC_NUM_IRQS 256
>> +
>> +#define GIC_BASE_OFS 0x0000
>> +#define GIC_DIST_OFS 0x1000
>> +#define GIC_CPU_OFS 0x2000
>> +#define GIC_VIFACE_THIS_OFS 0x4000
>> +#define GIC_VIFACE_OTHER_OFS(cpu) (0x5000 + (cpu) * 0x200)
>> +#define GIC_VCPU_OFS 0x6000
>> +
>> static void bcm2836_init(Object *obj)
>> {
>> BCM283XState *s = BCM283X(obj);
>> @@ -55,6 +72,11 @@ static void bcm2836_init(Object *obj)
>> info->cpu_type, &error_abort, NULL);
>> }
>>
>> + if (info->gic_base) {
>> + sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic),
>> + TYPE_ARM_GIC);
>> + }
>> +
>> sysbus_init_child_obj(obj, "control", &s->control, sizeof(s->control),
>> TYPE_BCM2836_CONTROL);
>>
>> @@ -115,6 +137,59 @@ static void bcm2836_realize(DeviceState *dev, Error
>> **errp)
>>
>> sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, info->ctrl_base);
>>
>> + /* bcm2838 GICv2 */
>> + if (info->gic_base) {
>> + object_property_set_uint(OBJECT(&s->gic), 2, "revision", &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + object_property_set_uint(OBJECT(&s->gic),
>> + BCM283X_NCPUS, "num-cpu", &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + object_property_set_uint(OBJECT(&s->gic),
>> + 32 + GIC_NUM_IRQS, "num-irq", &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + object_property_set_bool(OBJECT(&s->gic),
>> + true, "has-virtualization-extensions",
>> &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0,
>> + info->ctrl_base + info->gic_base + GIC_DIST_OFS);
>> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1,
>> + info->ctrl_base + info->gic_base + GIC_CPU_OFS);
>> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2,
>> + info->ctrl_base + info->gic_base +
>> GIC_VIFACE_THIS_OFS);
>> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3,
>> + info->ctrl_base + info->gic_base + GIC_VCPU_OFS);
>> +
>> + for (n = 0; n < BCM283X_NCPUS; n++) {
>> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 4 + n,
>> + info->ctrl_base + info->gic_base
>> + + GIC_VIFACE_OTHER_OFS(n));> + }
>> +
>> + /* TODO wire IRQs!!! */
>
> I think as a bare minimum, you must wire:
> - the ARM generic timer IRQs going out of all the CPUs, into their
> respective PPI. Looking at [1], they seem to be connected to the usual
> PPIs (at least we have the same mapping in the vexpress, the xynqmp and
> the virt board).
Done :)
> - The PMU interrupts
Still TODO.
> - Possibly the GICv2 maintenance interrupt, but I can't find the IRQ
> number in the DTS. This is related to the virtualization extension. It
> should not prevent Linux from booting if it's not connected (I think KVM
> does not even use the GICv2 maintenance interrupts anyway).
Done, this is a GIC-400 so it is fixed as PPI IRQ#9 :)
> - Finally, Connect the four GICv2 output (irq, fiq, virq, vfiq) to
> their respective CPU inputs.
Done.
> [1]
> https://github.com/raspberrypi/linux/blob/rpi-5.3.y/arch/arm/boot/dts/bcm2838.dtsi
>
>
> Here is a snippet of the virt board, quickly adapted foc this SoC (I
> didn't test it):
Thanks! It helped :)
> #define BCM2838_ARCH_TIMER_VIRT_IRQ 11
> #define BCM2838_ARCH_TIMER_S_EL1_IRQ 13
> #define BCM2838_ARCH_TIMER_NS_EL1_IRQ 14
> #define BCM2838_ARCH_TIMER_NS_EL2_IRQ 10
>
> #define BCM2838_PMU_SPI_BASE 16
> [...]
>
> for (i = 0; i < BCM283X_NCPUS; i++) {
> DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
> int ppibase = GIC_NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
> int irq;
>
> /* Mapping from the output timer irq lines from the CPU to the
> * GIC PPI inputs.
> */
> const int timer_irq[] = {
> [GTIMER_PHYS] = BCM2838_ARCH_TIMER_NS_EL1_IRQ,
> [GTIMER_VIRT] = BCM2838_ARCH_TIMER_VIRT_IRQ,
> [GTIMER_HYP] = BCM2838_ARCH_TIMER_NS_EL2_IRQ,
> [GTIMER_SEC] = BCM2838_ARCH_TIMER_S_EL1_IRQ,
> };
>
> for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
> qdev_connect_gpio_out(cpudev, irq,
> qdev_get_gpio_in(gicdev,
> ppibase +
> timer_irq[irq]));
> }
>
> /* I don't know the maintenance IRQ number for the this SoC */
> #if 0
> qemu_irq irq = qdev_get_gpio_in(gicdev,
> ppibase + ARCH_GIC_MAINT_IRQ);
> sysbus_connect_irq(SYS_BUS_DEVICE(gicbusdevs->gic), i + 4 *
> smp_cpus, irq);
> #endif
>
> /* PMU interrupt */
> qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
> qdev_get_gpio_in(gicdev,
> BCM2838_PMU_SPI_BASE + i));
>
> /* Connect the GICv2 outputs to the CPU */
> sysbus_connect_irq(SYS_BUS_DEVICE(gicbusdevs->gic), i,
> qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
> sysbus_connect_irq(SYS_BUS_DEVICE(gicbusdevs->gic), i + smp_cpus,
> qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
> sysbus_connect_irq(SYS_BUS_DEVICE(gicbusdevs->gic), i + 2 *
> smp_cpus,
> qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
> sysbus_connect_irq(SYS_BUS_DEVICE(gicbusdevs->gic), i + 3 *
> smp_cpus,
> qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
> }
With this and few other changes I get some hopeful kernel output:
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
[ 0.000000] Linux version 4.19.67-v8+ (james@james-ubuntu2) (gcc
version 9.1.0 (GCC)) #1 SMP PREEMPT Mon Aug 26 21:26:31 MDT 2019
[ 0.000000] Machine model: Raspberry Pi 4 Model B
[ 0.000000] earlycon: pl11 at MMIO 0x00000000fe201000 (options '')
[ 0.000000] bootconsole [pl11] enabled
[ 0.000000] efi: Getting EFI parameters from FDT:
[ 0.000000] efi: UEFI not found.
[ 0.000000] cma: Reserved 8 MiB at 0x000000003b800000
[ 0.000000] On node 0 totalpages: 245760
[ 0.000000] DMA32 zone: 3840 pages used for memmap
[ 0.000000] DMA32 zone: 0 pages reserved
[ 0.000000] DMA32 zone: 245760 pages, LIFO batch:63
[ 0.000000] random: get_random_bytes called from
start_kernel+0xa0/0x46c with crng_init=0
[ 0.000000] percpu: Embedded 24 pages/cpu s57368 r8192 d32744 u98304
[ 0.000000] pcpu-alloc: s57368 r8192 d32744 u98304 alloc=24*4096
[ 0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3
[ 0.000000] Detected PIPT I-cache on CPU0
[ 0.000000] CPU features: enabling workaround for EL2 vector hardening
[ 0.000000] CPU features: detected: Kernel page table isolation (KPTI)
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 241920
[ 0.000000] Kernel command line: rw earlycon=pl011,0xfe201000
console=ttyAMA0 loglevel=8 root=/dev/mmcblk0p2 fsck.repair=yes
net.ifnames=0 rootwait rdinit=/sbin/init
[ 0.000000] Dentry cache hash table entries: 131072 (order: 8,
1048576 bytes)
[ 0.000000] Inode-cache hash table entries: 65536 (order: 7, 524288
bytes)
[ 0.000000] Memory: 923932K/983040K available (8060K kernel code,
966K rwdata, 2560K rodata, 960K init, 916K bss, 50916K reserved, 8192K
cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[ 0.000000] ftrace: allocating 28504 entries in 112 pages
[ 0.000000] rcu: Preemptible hierarchical RCU implementation.
[ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=64 to
nr_cpu_ids=4.
[ 0.000000] Tasks RCU enabled.
[ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] GIC: Using split EOI/Deactivate mode
[ 0.000000] arch_timer: cp15 timer(s) running at 54.00MHz (phys).
[ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff
max_cycles: 0xc743ce346, max_idle_ns: 440795203123 ns
[ 0.001377] sched_clock: 56 bits at 54MHz, resolution 18ns, wraps
every 4398046511102ns
[ 0.070247] Console: colour dummy device 80x25
[ 0.085191] Calibrating delay loop (skipped), value calculated using
timer frequency.. 108.00 BogoMIPS (lpj=216000)
[ 0.087407] pid_max: default: 32768 minimum: 301
[ 0.118255] Mount-cache hash table entries: 2048 (order: 2, 16384 bytes)
[ 0.120037] Mountpoint-cache hash table entries: 2048 (order: 2,
16384 bytes)
[ 0.462960] ASID allocator initialised with 32768 entries
[ 0.475367] rcu: Hierarchical SRCU implementation.
[ 0.540749] EFI services will not be available.
[ 0.563715] smp: Bringing up secondary CPUs ...
[ 0.624297] Detected PIPT I-cache on CPU1
[ 0.628830] CPU1: Booted secondary processor 0x0000000001 [0x410fd083]
[ 0.698386] Detected PIPT I-cache on CPU2
[ 0.699334] CPU2: Booted secondary processor 0x0000000002 [0x410fd083]
[ 0.752144] Detected PIPT I-cache on CPU3
[ 0.753057] CPU3: Booted secondary processor 0x0000000003 [0x410fd083]
[ 0.759037] smp: Brought up 1 node, 4 CPUs
[ 0.762310] SMP: Total of 4 processors activated.
[ 0.763888] CPU features: detected: 32-bit EL0 Support
[ 0.819489] CPU: All CPU(s) started at EL2
[ 0.826062] alternatives: patching kernel code
[ 0.948345] devtmpfs: initialized
[ 1.235286] Enabled cp15_barrier support
[ 1.237025] Enabled setend support
[ 1.253695] clocksource: jiffies: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 7645041785100000 ns
[ 1.255510] futex hash table entries: 1024 (order: 4, 65536 bytes)
[ 1.275781] pinctrl core: initialized pinctrl subsystem
[ 1.347547] DMI not present or invalid.
[ 1.378896] NET: Registered protocol family 16
[ 1.439424] cpuidle: using governor menu
[ 1.450693] vdso: 2 pages (1 code @ (____ptrval____), 1 data @
(____ptrval____))
[ 1.452529] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
Regards.
Phil.
- [Qemu-devel] [PATCH 10/14] hw/arm/raspi: Define various blocks base addresses, (continued)
- [Qemu-devel] [PATCH 10/14] hw/arm/raspi: Define various blocks base addresses, Philippe Mathieu-Daudé, 2019/09/04
- [Qemu-devel] [RFC PATCH 14/14] hw/arm/raspi: Add the Raspberry Pi 4B board, Philippe Mathieu-Daudé, 2019/09/04
- [Qemu-devel] [PATCH 11/14] hw/arm/bcm2835_peripherals: Map various BCM2838 blocks, Philippe Mathieu-Daudé, 2019/09/04
- [Qemu-devel] [RFC PATCH 13/14] hw/arm/bcm2838: Map the PCIe memory space, Philippe Mathieu-Daudé, 2019/09/04
- [Qemu-devel] [RFC PATCH 12/14] hw/arm/bcm2836: Add the BCM2838 which uses a GICv2, Philippe Mathieu-Daudé, 2019/09/04
- RE: [Qemu-arm] [RFC PATCH 00/14] hw/arm: Add the Raspberry Pi 4B, Stewart Hildebrand, 2019/09/21