qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: OpenMPIC controller emulation in qemu ?


From: Andrew Randrianasulu
Subject: Re: OpenMPIC controller emulation in qemu ?
Date: Sat, 18 May 2024 00:59:51 +0300



On Fri, May 17, 2024 at 11:34 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
On Fri, 17 May 2024, Andrew Randrianasulu wrote:
> пт, 17 мая 2024 г., 22:49 BALATON Zoltan <balaton@eik.bme.hu>:
>
>> On Fri, 17 May 2024, Andrew Randrianasulu wrote:
>>> пт, 17 мая 2024 г., 22:02 BALATON Zoltan <balaton@eik.bme.hu>:
>>>
>>>> On Fri, 17 May 2024, Andrew Randrianasulu wrote:
>>>>> On Fri, May 17, 2024 at 9:01 PM Andrew Randrianasulu <
>>>>> randrianasulu@gmail.com> wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> On Fri, May 17, 2024 at 8:55 PM BALATON Zoltan <balaton@eik.bme.hu>
>>>> wrote:
>>>>>>
>>>>>>> On Fri, 17 May 2024, Andrew Randrianasulu wrote:
>>>>>>>> I also tried to add  multiple cpu support in openbios qemu ppc arch
>>>>>>> like it
>>>>>>>> was done for sparc, but sparc just dump cpus in / of device tree?
>>>>>>>>
>>>>>>>> so same trick ofc failed because I do not really know  forth so  no
>>>> idea
>>>>>>>> where  to put for() loop start :)
>>>>>>>
>>>>>>> No Forth needed for that. The device tree is constucred in in
>>>>>>> openbios/arch/ppc/qemu/init.c::arch_of_init(). You can try to put a
>>>> loop
>>>>>>> around cpu->initfn(cpu); in this function, you still have the number
>> of
>>>>>>> CPUs in temp at that point so maybe something like:
>>>>>>>
>>>>>>> for (int i = 0; i < temp; i++)
>>>>>>>      cpu->initfn(cpu);
>>>>>>>
>>>>>>> might work but I did not try it.
>>>>>>>
>>>>>>
>>>>>> Thanks.
>>>>>>
>>>>>>
>>>>>> Right now I am trying to modify hw/intc/openpic.c
>>>>>>
>>>>>>     case OPENPIC_MODEL_KEYLARGO:
>>>>>>         opp->nb_irqs = KEYLARGO_MAX_EXT + KEYLARGO_MAX_IPI;
>>>>>> // because  I think this is total number of IRQs, not just external
>>>> ones?
>>>>>>
>>>>>>         opp->vid = VID_REVISION_1_2;
>>>>>>         opp->vir = VIR_GENERIC;
>>>>>>
>>>>>>         opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) |
>>>>>>                ((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) |
>>>>>>                (opp->vid << FRR_VID_SHIFT);
>>>>>> // for some reason  Linux mpic probe still thinks I have only one CPU
>> ?
>>>>>> see p. 390 of CPC 945 manual
>>>>
>>>> I can't help with this as I have no idea about this Apple chip but I
>> still
>>>> think the CPC945 is a different chip not this one. Hope somebody can
>> chime
>>>> in and give some insight.
>>>>
>>>>>>         opp->vector_mask = 0xFF;
>>>>>>         opp->tfrr_reset = 4160000;
>>>>>>         opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
>>>>>>         opp->idr_reset = 0;
>>>>>>         opp->max_irq = KEYLARGO_MAX_IRQ;
>>>>>>         opp->irq_ipi0 = KEYLARGO_IPI_IRQ;
>>>>>>         opp->irq_tim0 = KEYLARGO_TMR_IRQ;
>>>>>>         opp->brr1 = -1;
>>>>>>         opp->mpic_mode_mask = GCR_MODE_MIXED;
>>>>>>
>>>>>>         for (i = KEYLARGO_MAX_EXT; i < KEYLARGO_MAX_IRQ; i++) {
>>>>>>         opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
>>>>>>         opp->src[i].level = false;
>>>>>>     }
>>>>>> // here i tried to init IPI sources ....
>>>>>>
>>>>>>         if (opp->nb_cpus != 1) {
>>>>>>             //error_setg(errp, "Only UP supported today");
>>>>>>             //return;
>>>>>>         }
>>>>>>
>>>>>>         map_list(opp, list_le, &list_count);
>>>>>>         break;
>>>>>>     }
>>>>>>
>>>>>
>>>>> ===========
>>>>>
>>>>> with this patch to openbios
>>>>>
>>>>> ample_1280x720_surfing_with_audio.mjpeg  smp_init_openbios.patch
>>>>> bash-5.1$ cat /dev/shm/smp_init_openbios.patch
>>>>> diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c
>>>>> index 253394c..2d39289 100644
>>>>> --- a/arch/ppc/qemu/init.c
>>>>> +++ b/arch/ppc/qemu/init.c
>>>>> @@ -1073,13 +1073,17 @@ arch_of_init(void)
>>>>>     push_str("reg");
>>>>>     fword("property");
>>>>>
>>>>> +    int i;
>>>>> +    for (i= 0; i<temp; i++) {
>>>>> +
>>>>>     cpu = id_cpu();
>>>>>     cpu->initfn(cpu);
>>>>>     printk("CPU type %s\n", cpu->name);
>>>>> -
>>>>> -    snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
>>>>> +        snprintf(buf, sizeof(buf), "/cpus/%s@%i", cpu->name, i);
>>>>
>>>> That's wrong. The @0 part should come from some property of the device
>>>> node, maybe reg? This is added in cpu_g4_init() which calls
>>>> cpu_add_pir_property() that reads SPR 1023 (PIR) and uses that as reg
>>>> property. The docs say:
>>>>
>>>> "2.3.17 Processor Identification Register (PIR)
>>>>
>>>> The PIR register is used to differentiate between individual processors
>> in
>>>> a multiprocessor environment.
>>>>
>>>> Note: The PIR is an optional register in the PowerPC Architecture and
>> may
>>>> be implemented differently (or not at all) in the design of each
>>>> processor. The user’s manual of a specific processor will describe the
>>>> func- tionality of the PIR, if it is implemented in that processor."
>>>>
>>>> And the CPU manual says read this doc for more info so it's a circular
>>>> reference. It also says this can be written and defaults to 0 so I think
>>>> something needs to set PIR to the CPU number. Maybe QEMU when creating
>> or
>>>> resetting the CPU should set PIR?
>>>>
>>>>> +    }
>>>>>     ofmem_register(find_dev("/memory"), find_dev(buf));
>>>>>     node_methods_init(buf);
>>>>> +
>>>>>
>>>>> #ifdef CONFIG_RTAS
>>>>>     /* OldWorld Macs don't have an /rtas node. */
>>>>> bash-5.1$
>>>>>
>>>>> finnix kernel sees more cpus in device tree!
>>>>>
>>>>> [    2.625299] device-tree: Duplicate name in /cpus, renamed to
>>>>> "PowerPC,G4@0#1"
>>>>> [    2.626218] device-tree: Duplicate name in /cpus, renamed to
>>>>> "PowerPC,G4@0#2"
>>>>> [    2.627226] device-tree: Duplicate name in /cpus, renamed to
>>>>> "PowerPC,G4@0#3"
>>>>>
>>>>> hm, well ..
>>>>>
>>>>> but void ppc kernel crashes  right away :
>>>>>
>>>>> bash-5.1$ /dev/shm/qemu-9.0.0/build/qemu-system-ppc -m 512 -M mac99
>> -smp
>>>> 4
>>>>> -nographic  -kernel /mnt/tmp/boot/vmlinux -append "console=ttyPZ0"
>> -bios
>>>>> /dev/shm/openbios-qemu.elf
>>>>>
>>>>> Booting Linux via __start() @ 0x01000000 ...
>>>>> Hello World !
>>>>> [    0.000000] Total memory = 512MB; using 1024kB for hash table
>>>>> [    0.000000] Activating Kernel Userspace Execution Prevention
>>>>> [    0.000000] Activating Kernel Userspace Access Protection
>>>>> [    0.000000] Linux version 5.13.12_1 (voidlinux@voidlinux) (gcc
>> (GCC)
>>>>> 10.2.1 20201203, GNU ld (GNU Binutils) 2.35.1) #1 SMP Thu Aug 19
>> 14:12:26
>>>>> UTC 2021
>>>>> [    0.000000] ioremap() called early from
>> pmac_feature_init+0xd4/0xad4.
>>>>> Use early_ioremap() instead
>>>>> [    0.000000] Found UniNorth memory controller & host bridge @
>>>> 0xf8000000
>>>>> revision: 0x07
>>>>> [    0.000000] Mapped at 0xf73c0000
>>>>> [    0.000000] ioremap() called early from probe_one_macio+0x17c/0x2b4.
>>>> Use
>>>>> early_ioremap() instead
>>>>> [    0.000000] Found a Keylargo mac-io controller, rev: 0, mapped at
>>>>> 0x(ptrval)
>>>>> [    0.000000] PowerMac motherboard: PowerMac G4 AGP Graphics
>>>>> [    0.000000] ioremap() called early from udbg_scc_init+0x1e4/0x3f8.
>> Use
>>>>> early_ioremap() instead
>>>>> [    0.000000] boot stdout isn't a display !
>>>>> [    0.000000] ioremap() called early from find_via_cuda+0xb4/0x404.
>> Use
>>>>> early_ioremap() instead
>>>>
>>>> This kernel seems to have some issues. Does it work on real machine?
>>>>
>>>
>>>
>>> no idea sadly, void ppc ceased to exist as project .....
>>
>> It would help if you tested with something known to work on real machine
>> otherwise you might hit problems with the OS instead of missing emulation
>> in QEMU and OpenBIOS parts which would make it more difficult to find
>> what's needed. So make sure the Linux distro you boot works on a real dual
>> CPU Mac. Also according to
>>
>> https://en.wikipedia.org/wiki/Power_Mac_G4#Graphite_model_variations
>>
>> PowerMac3,1 did not exist with two CPUs, only later version but I don't
>> know what else was different between them. Maybe it needs some other
>> hardware not emulated in QEMU?
>>
>>>
>>>>> [    0.000000] Using PowerMac machine description
>>>>> [    0.000000] printk: bootconsole [udbg0] enabled
>>>>> [    0.000000] CPU maps initialized for 1 thread per core
>>>>> [    0.000000] -----------------------------------------------------
>>>>> [    0.000000] phys_mem_size     = 0x20000000
>>>>> [    0.000000] dcache_bsize      = 0x20
>>>>> [    0.000000] icache_bsize      = 0x20
>>>>> [    0.000000] cpu_features      = 0x000000000501a00a
>>>>> [    0.000000]   possible        = 0x00000000277de14a
>>>>> [    0.000000]   always          = 0x0000000001000000
>>>>> [    0.000000] cpu_user_features = 0x9c000001 0x00000000
>>>>> [    0.000000] mmu_features      = 0x00000001
>>>>> [    0.000000] Hash_size         = 0x100000
>>>>> [    0.000000] Hash_mask         = 0x3fff
>>>>> [    0.000000] -----------------------------------------------------
>>>>> [    0.000000] ioremap() called early from pmac_setup_arch+0x118/0x290.
>>>> Use
>>>>> early_ioremap() instead
>>>>> [    0.000000] ioremap() called early from pmac_nvram_init+0x150/0x53c.
>>>> Use
>>>>> early_ioremap() instead
>>>>> [    0.000000] nvram: Checking bank 0...
>>>>> [    0.000000] Invalid signature
>>>>> [    0.000000] Invalid checksum
>>>>> [    0.000000] nvram: gen0=0, gen1=0
>>>>> [    0.000000] nvram: Active bank is: 0
>>>>> [    0.000000] nvram: OF partition at 0xffffffff
>>>>> [    0.000000] nvram: XP partition at 0xffffffff
>>>>> [    0.000000] nvram: NR partition at 0xffffffff
>>>>> [    0.000000] Zone ranges:
>>>>> [    0.000000]   DMA      [mem 0x0000000000000000-0x000000001fffffff]
>>>>> [    0.000000]   Normal   empty
>>>>> [    0.000000]   HighMem  empty
>>>>> [    0.000000] Movable zone start for each node
>>>>> [    0.000000] Early memory node ranges
>>>>> [    0.000000]   node   0: [mem 0x0000000000000000-0x000000001fffffff]
>>>>> [    0.000000] Initmem setup node 0 [mem
>>>>> 0x0000000000000000-0x000000001fffffff]
>>>>> [    0.000000] percpu: Embedded 22 pages/cpu s59884 r8192 d22036 u90112
>>>>> [    0.000000] ------------[ cut here ]------------
>>>>> [    0.000000] kernel BUG at arch/powerpc/kernel/smp.c:1107!
>>>>
>>>> I guess you could get more info by finding this source line in the
>>>> corresponding kernel source.
>>>>
>>>
>>> yeah, line moved a bit but
>>>
>>> https://elixir.bootlin.com/linux/latest/source/arch/powerpc/kernel/smp.c
>>>
>>> 1171 BUG_ON  in smp_prepare_boot_cpu
>>>
>>> so I guess MP system really need some way to discriminate cpus ....
>>
>> I've found these docs that might contain some info. Maybe not enough to
>> completely understand the issue but could help to show some direction:
>>
>> https://www.kernel.org/doc/html//v5.9/devicetree/booting-without-of.html
>
>
> ======
>
>
>   3. The /cpus/* nodes
>
> So under /cpus, you are supposed to create a node for every CPU on the
> machine. There is no specific restriction on the name of the CPU, though
> it’s common to call it <architecture>,<core>. For example, Apple uses
> PowerPC,G5 while IBM uses PowerPC,970FX. However, the Generic Names
> convention suggests that it would be better to simply use ‘cpu’ for each
> cpu node and use the compatible property to identify the specific cpu core.
>
> Required properties:
>
>
>   -
>
>   device_type : has to be “cpu”
>   -
>
>   reg : This is the physical CPU number, it’s a single 32-bit cell and is
>   also used as-is as the unit number for constructing the unit name in the
>   full path. For example, with 2 CPUs, you would have the full path:
>
>   /cpus/PowerPC,970FX@0
>   /cpus/PowerPC,970FX@1
>
>
> ====
>
> so ... some more work needed in openfirmware/openbios - thanks!

I think OpenBIOS would do the right thing if you only add the loop around
the CPU init function like this:

for (int i = 0; i < temp; i++) {
     cpu->initfn(cpu);
}

and set the SPR 1023 aka PIR to the CPU number in QEMU in the
qemu/hw/ppc/mac_newworld.c::ppc_core99_reset() function after it calls
cpu_reset. But don't know how to pass CPU number to that function, it
seems to be called for all CPUs and will run OpenBIOS on all CPUs. I'm not
sure that OpenBIOS is prepared for that so QEMU may need to do here what
the Linux doc says and put CPUs >= 1 in a sleep loop or do something with
that. So maybe it's more work in QEMU than OpenBIOS.

May be

So far modding hw/ppc/mac_newworld.c init  function so it reads in cpu  part

   /* init CPUs */
    for (i = 0; i < machine->smp.cpus; i++) {
        cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
        env = &cpu->env;
        CPUState *cs;
        cs = CPU(cpu);

        /* Set time-base frequency to 100 Mhz */
        cpu_ppc_tb_init(env, TBFREQ);
        qemu_register_reset(ppc_core99_reset, cpu);
        env->spr_cb[SPR_PIR].default_value = cs->cpu_index = i;
    }

===

does not result in openbios printing different values for this reg (I added printk() there)
 

Regards,
BALATON Zoltan

reply via email to

[Prev in Thread] Current Thread [Next in Thread]