All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel]  MIPS little endian - Bug when decoding physaddr
@ 2017-05-12 22:52 Vinicius Maciel
  2017-05-13 18:28 ` Aurelien Jarno
  0 siblings, 1 reply; 8+ messages in thread
From: Vinicius Maciel @ 2017-05-12 22:52 UTC (permalink / raw)
  To: qemu-devel

Hi all,

I'm trying to emulate a MIPS 74Kc using a custom machine in order to run a
CFE bootloader from broadcom. The CPU is Broadcom BCM5357. The problem
happens when Qemu calculates physaddr inside io_readx(), cputlb.c:line 784

physaddr = (physaddr & TARGET_PAGE_MASK) + addr;

After run this line the the value is 0x18000000, which is clearly wrong.
More informations:

BUG function: io_readx
Assembly instruction: lw t1,0(a2)
Machine code: 0x8cc90000 (Little endian)
Access address: 0xb8000000

Assembly code:
80702f30 <board_earlyinit>:
80702f30: 3c06b800 lui a2,0xb800
80702f34: 24075350 li a3,21328
80702f38: 8cc90000 lw t1,0(a2) <----

Thanks,
Vinicius

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] MIPS little endian - Bug when decoding physaddr
  2017-05-12 22:52 [Qemu-devel] MIPS little endian - Bug when decoding physaddr Vinicius Maciel
@ 2017-05-13 18:28 ` Aurelien Jarno
  2017-05-13 21:57   ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 8+ messages in thread
From: Aurelien Jarno @ 2017-05-13 18:28 UTC (permalink / raw)
  To: Vinicius Maciel; +Cc: qemu-devel

On 2017-05-12 19:52, Vinicius Maciel wrote:
> Hi all,
> 
> I'm trying to emulate a MIPS 74Kc using a custom machine in order to run a
> CFE bootloader from broadcom. The CPU is Broadcom BCM5357. The problem
> happens when Qemu calculates physaddr inside io_readx(), cputlb.c:line 784
> 
> physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
> 
> After run this line the the value is 0x18000000, which is clearly wrong.

I don't think it's wrong, see below:

> More informations:
> 
> BUG function: io_readx
> Assembly instruction: lw t1,0(a2)
> Machine code: 0x8cc90000 (Little endian)
> Access address: 0xb8000000
> 
> Assembly code:
> 80702f30 <board_earlyinit>:
> 80702f30: 3c06b800 lui a2,0xb800

This load 0xb8000000 in a2

> 80702f34: 24075350 li a3,21328
> 80702f38: 8cc90000 lw t1,0(a2) <----

Now this try to load a value from the virtual address 0xb8000000. This
address corresponds to kseg1 (Kernel Unmapped Uncached) and is mapped
to the physical address 0x18000000. See the MIPS32 Privileged Resource
Architecture Manual for more details how the virtual to physical mapping
works.

Aurelien

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] MIPS little endian - Bug when decoding physaddr
  2017-05-13 18:28 ` Aurelien Jarno
@ 2017-05-13 21:57   ` Philippe Mathieu-Daudé
  2017-05-13 22:10     ` Vinicius Maciel
  0 siblings, 1 reply; 8+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-13 21:57 UTC (permalink / raw)
  To: Aurelien Jarno, Vinicius Maciel; +Cc: qemu-devel

Hi Vinicius,

> On 2017-05-12 19:52, Vinicius Maciel wrote:
>> Hi all,
>>
>> I'm trying to emulate a MIPS 74Kc using a custom machine in order to run a
>> CFE bootloader from broadcom. The CPU is Broadcom BCM5357. The problem

Here is your problem, there is no such model in QEMU.

>> happens when Qemu calculates physaddr inside io_readx(), cputlb.c:line 784
>>
>> physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
>>
>> After run this line the the value is 0x18000000, which is clearly wrong.

The Broadcom BCM5357 is a WiSoc (Wireless System-On-Chip).

A SoC (System-On-Chip) is not limited to a MIPS CPU but has a large set 
of embedded peripherals.

QEMU does models the MIPS 74Kf cpu, but not the BCM5357 peripherals.

At this physical address this SoC family maps a bus called 
SiliconBackplane (BP).
The first peripheral mapped in the BP region is the ChipCommon (CC). 
Common meaning this core registers intend to be consistent between 
different models/releases using this BP bus, so a firmware can check it 
is running the correct hardware or check if peripherals/features are 
available/enabled to configure/use them.

My guess is your CFE function board_earlyinit() is trying to determine 
the chip model by reading the ChipID from the CC it supposed is 
physically mapped at 0x18000000, which is not modeled in QEMU.

Phil.

>
> I don't think it's wrong, see below:
>
>> More informations:
>>
>> BUG function: io_readx
>> Assembly instruction: lw t1,0(a2)
>> Machine code: 0x8cc90000 (Little endian)
>> Access address: 0xb8000000
>>
>> Assembly code:
>> 80702f30 <board_earlyinit>:
>> 80702f30: 3c06b800 lui a2,0xb800
>
> This load 0xb8000000 in a2
>
>> 80702f34: 24075350 li a3,21328
>> 80702f38: 8cc90000 lw t1,0(a2) <----
>
> Now this try to load a value from the virtual address 0xb8000000. This
> address corresponds to kseg1 (Kernel Unmapped Uncached) and is mapped
> to the physical address 0x18000000. See the MIPS32 Privileged Resource
> Architecture Manual for more details how the virtual to physical mapping
> works.
>
> Aurelien
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] MIPS little endian - Bug when decoding physaddr
  2017-05-13 21:57   ` Philippe Mathieu-Daudé
@ 2017-05-13 22:10     ` Vinicius Maciel
  2017-06-23 18:14       ` Vinicius Maciel
  0 siblings, 1 reply; 8+ messages in thread
From: Vinicius Maciel @ 2017-05-13 22:10 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Aurelien Jarno, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2529 bytes --]

Hi Philippe and Aurelien,

You are right. I have created a simple SYSBUS using sysbus_create_simple
at 0x18000000 and now my read function works!

Thanks for help. I am attaching my code if you are interested.

Vinicius

2017-05-13 18:57 GMT-03:00 Philippe Mathieu-Daudé <f4bug@amsat.org>:

> Hi Vinicius,
>
> On 2017-05-12 19:52, Vinicius Maciel wrote:
>>
>>> Hi all,
>>>
>>> I'm trying to emulate a MIPS 74Kc using a custom machine in order to run
>>> a
>>> CFE bootloader from broadcom. The CPU is Broadcom BCM5357. The problem
>>>
>>
> Here is your problem, there is no such model in QEMU.
>
> happens when Qemu calculates physaddr inside io_readx(), cputlb.c:line 784
>>>
>>> physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
>>>
>>> After run this line the the value is 0x18000000, which is clearly wrong.
>>>
>>
> The Broadcom BCM5357 is a WiSoc (Wireless System-On-Chip).
>
> A SoC (System-On-Chip) is not limited to a MIPS CPU but has a large set of
> embedded peripherals.
>
> QEMU does models the MIPS 74Kf cpu, but not the BCM5357 peripherals.
>
> At this physical address this SoC family maps a bus called
> SiliconBackplane (BP).
> The first peripheral mapped in the BP region is the ChipCommon (CC).
> Common meaning this core registers intend to be consistent between
> different models/releases using this BP bus, so a firmware can check it is
> running the correct hardware or check if peripherals/features are
> available/enabled to configure/use them.
>
> My guess is your CFE function board_earlyinit() is trying to determine the
> chip model by reading the ChipID from the CC it supposed is physically
> mapped at 0x18000000, which is not modeled in QEMU.
>
> Phil.
>
>
>
>> I don't think it's wrong, see below:
>>
>> More informations:
>>>
>>> BUG function: io_readx
>>> Assembly instruction: lw t1,0(a2)
>>> Machine code: 0x8cc90000 (Little endian)
>>> Access address: 0xb8000000
>>>
>>> Assembly code:
>>> 80702f30 <board_earlyinit>:
>>> 80702f30: 3c06b800 lui a2,0xb800
>>>
>>
>> This load 0xb8000000 in a2
>>
>> 80702f34: 24075350 li a3,21328
>>> 80702f38: 8cc90000 lw t1,0(a2) <----
>>>
>>
>> Now this try to load a value from the virtual address 0xb8000000. This
>> address corresponds to kseg1 (Kernel Unmapped Uncached) and is mapped
>> to the physical address 0x18000000. See the MIPS32 Privileged Resource
>> Architecture Manual for more details how the virtual to physical mapping
>> works.
>>
>> Aurelien
>>
>>

[-- Attachment #2: bcm_router.c --]
[-- Type: text/x-csrc, Size: 13124 bytes --]

/*
 * QEMU/mipssim emulation
 *
 * Emulates a very simple machine model similar to the one used by the
 * proprietary MIPS emulator.
 * 
 * Copyright (c) 2007 Thiemo Seufer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
#include "hw/char/serial.h"
#include "hw/isa/isa.h"
#include "net/net.h"
#include "sysemu/sysemu.h"
#include "hw/boards.h"
#include "hw/mips/bios.h"
#include "hw/loader.h"
#include "elf.h"
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
#include "sysemu/qtest.h"
#include "hw/block/flash.h"

#define BYTE_ACCESS_SIZE 1
#define HALFWORD_ACCESS_SIZE 2
#define WORD_ACCESS_SIZE 4


static struct _loaderparams {
    int ram_size;
    const char *kernel_filename;
    const char *kernel_cmdline;
    const char *initrd_filename;
} loaderparams;

typedef struct ResetData {
    MIPSCPU *cpu;
    uint64_t vector;
} ResetData;

static const int sector_len = 1 * 1024;

/* ChipID register.  */

#define TYPE_BCM_CHIP "bcm_chipid"
#define BCM_CHIP(obj) \
    OBJECT_CHECK(bcm_chipid_state, (obj), TYPE_BCM_CHIP)

typedef struct {
    SysBusDevice parent_obj;

    qemu_irq irq;
    MemoryRegion iomem;
    uint32_t chip_id;
    uint32_t mcs;
    uint32_t mdr;
    uint32_t mtpr;
    uint32_t mimr;
    uint32_t mris;
    uint32_t mcr;
} bcm_chipid_state;

static uint64_t bcm_chipid_read(void *opaque, hwaddr offset,
                                   unsigned size)
{
    bcm_chipid_state *s = (bcm_chipid_state *)opaque;

    switch (offset) {
    case 0x00: /* MSA */
        return s->chip_id;
    case 0x04: /* MCS */
        /* We don't emulate timing, so the controller is never busy.  */
        return s->mcs;
    default:
        hw_error("%s: Bad offset 0x%x\n", __func__, (int)offset);
        return 0;
    }
}

static void bcm_chipid_write(void *opaque, hwaddr offset,
                                uint64_t value, unsigned size)
{
    bcm_chipid_state *s = (bcm_chipid_state *)opaque;

    switch (offset) {
    case 0x00: /* MSA */
        //s->chip_id = value;
        break;
    case 0x04: /* MCS */
        break;
    case 0x08: /* MDR */
        s->mdr = value & 0xff;
        break;
    default:
        hw_error("bcm_chipid_write: Bad offset 0x%x\n",
                  (int)offset);
    }
}

static void bcm_chipid_reset(bcm_chipid_state *s)
{
    s->chip_id = 0x5357;
    s->mcs = 0;
    s->mdr = 0;
    s->mtpr = 1;
    s->mimr = 0;
    s->mris = 0;
    s->mcr = 0;
}

static const MemoryRegionOps bcm_chipid_ops = {
    .read = bcm_chipid_read,
    .write = bcm_chipid_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
	.impl = {
        .min_access_size = 4,
        .max_access_size = 4,
    }
};

static const VMStateDescription vmstate_bcm_chipid = {
    .name = "bcm-chipid",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(chip_id, bcm_chipid_state),
        VMSTATE_UINT32(mcs, bcm_chipid_state),
        VMSTATE_UINT32(mdr, bcm_chipid_state),
        VMSTATE_UINT32(mtpr, bcm_chipid_state),
        VMSTATE_UINT32(mimr, bcm_chipid_state),
        VMSTATE_UINT32(mris, bcm_chipid_state),
        VMSTATE_UINT32(mcr, bcm_chipid_state),
        VMSTATE_END_OF_LIST()
    }
};

static void bcm_chipid_init(Object *obj)
{
    //DeviceState *dev = DEVICE(obj);
    bcm_chipid_state *s = BCM_CHIP(obj);
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);

    sysbus_init_irq(sbd, &s->irq);

    memory_region_init_io(&s->iomem, obj, &bcm_chipid_ops, s,
                          "chipid", 0x1000);
    sysbus_init_mmio(sbd, &s->iomem);
    bcm_chipid_reset(s);
}

static void bcm_chipid_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->vmsd = &vmstate_bcm_chipid;
}

static const TypeInfo bcm_chipid_info = {
    .name          = TYPE_BCM_CHIP,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(bcm_chipid_state),
    .instance_init = bcm_chipid_init,
    .class_init    = bcm_chipid_class_init,
};

static int64_t load_kernel(void)
{
    int64_t entry, kernel_high;
    long kernel_size;
    long initrd_size;
    ram_addr_t initrd_offset;
    int big_endian;

#ifdef TARGET_WORDS_BIGENDIAN
    big_endian = 1;
#else
    big_endian = 0;
#endif

    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
                           NULL, (uint64_t *)&entry, NULL,
                           (uint64_t *)&kernel_high, big_endian,
                           EM_MIPS, 1, 0);
    if (kernel_size >= 0) {
        if ((entry & ~0x7fffffffULL) == 0x80000000)
            entry = (int32_t)entry;
    } else {
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
                loaderparams.kernel_filename);
        exit(1);
    }
    printf("kernel_size: %ld\n", kernel_size);

    /* load initrd */
    initrd_size = 0;
    initrd_offset = 0;
    if (loaderparams.initrd_filename) {
        initrd_size = get_image_size (loaderparams.initrd_filename);
        if (initrd_size > 0) {
            initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
            if (initrd_offset + initrd_size > loaderparams.ram_size) {
                fprintf(stderr,
                        "qemu: memory too small for initial ram disk '%s'\n",
                        loaderparams.initrd_filename);
                exit(1);
            }
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
                initrd_offset, loaderparams.ram_size - initrd_offset);
        }
        if (initrd_size == (target_ulong) -1) {
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                    loaderparams.initrd_filename);
            exit(1);
        }
    }
    return entry;
}

static void main_cpu_reset(void *opaque)
{
    ResetData *s = (ResetData *)opaque;
    CPUMIPSState *env = &s->cpu->env;

    cpu_reset(CPU(s->cpu));
    env->active_tc.PC = s->vector & ~(target_ulong)1;
    if (s->vector & 1) {
        env->hflags |= MIPS_HFLAG_M16;
    }
}

/*
static void mipschip_init(hwaddr base, qemu_irq irq)
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "bcm_chipid");
    //qdev_set_nic_properties(dev, nd);
    qdev_init_nofail(dev);

    s = SYS_BUS_DEVICE(dev);
    sysbus_connect_irq(s, 0, irq);
	sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
}
*/

static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "mipsnet");
    qdev_set_nic_properties(dev, nd);
    qdev_init_nofail(dev);

    s = SYS_BUS_DEVICE(dev);
    sysbus_connect_irq(s, 0, irq);
    memory_region_add_subregion(get_system_io(),
                                base,
                                sysbus_mmio_get_region(s, 0));
}

static void
bcm_router_init(MachineState *machine)
{
    ram_addr_t ram_size = machine->ram_size;
    const char *cpu_model = machine->cpu_model;
    const char *kernel_filename = machine->kernel_filename;
    const char *kernel_cmdline = machine->kernel_cmdline;
    const char *initrd_filename = machine->initrd_filename;
    char *filename;
    MemoryRegion *address_space_mem = get_system_memory();
    MemoryRegion *isa = g_new(MemoryRegion, 1);
    MemoryRegion *ram = g_new(MemoryRegion, 1);
    MemoryRegion *bios = g_new(MemoryRegion, 1);
    MIPSCPU *cpu;
    CPUMIPSState *env;
    ResetData *reset_info;
	DriveInfo *dinfo;
    int bios_size;
	uint32_t flash_size = 0x20000; // 0x1000000
	int big_endian;
	//uint64_t pagemask;

#ifdef TARGET_WORDS_BIGENDIAN
    big_endian = 1;
#else
    big_endian = 0;
#endif

    /* Init CPUs. */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "5Kf";
#else
        cpu_model = "74Kf";
#endif
    }
    cpu = cpu_mips_init(cpu_model);
    if (cpu == NULL) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }
    env = &cpu->env;

    reset_info = g_malloc0(sizeof(ResetData));
    reset_info->cpu = cpu;
    reset_info->vector = env->active_tc.PC;
    qemu_register_reset(main_cpu_reset, reset_info);

    /* Allocate RAM. */
    memory_region_allocate_system_memory(ram, NULL, "bcm.ram",
                                         ram_size);
    memory_region_init_ram(bios, NULL, "bcm.bios", BIOS_SIZE,
                           &error_fatal);
    vmstate_register_ram_global(bios);
    memory_region_set_readonly(bios, true);

    memory_region_add_subregion(address_space_mem, 0, ram);
	
	/* Map the BIOS / boot exception handler. */
    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
    /* Load a BIOS / boot exception handler image. */
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE);
        g_free(filename);
    } else {
        bios_size = -1;
    }
    if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
        !kernel_filename && !qtest_enabled()) {
        /* Bail out if we have neither a kernel image nor boot vector code. */
        error_report("Could not load MIPS bios '%s', and no "
                     "-kernel argument was specified", bios_name);
        //exit(1);
    } else {
        /* We have a boot vector start address. */
        env->active_tc.PC = (target_long)(int32_t)0xbfc00000;
    }

    if ((bios_size < 0) && !kernel_filename) {
		dinfo = drive_get(IF_PFLASH, 0, 0);
		if (!dinfo && !qtest_enabled()) {
			fprintf(stderr, "A flash image must big_endian given with the "
					"'pflash' parameter\n");
			exit(1);
		} else {
			if (!pflash_cfi01_register(0xbfc00000, NULL, "router.flash",
				flash_size,
				dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
				sector_len, flash_size / sector_len,
				4, 0, 0, 0, 0, big_endian)) {
				fprintf(stderr, "qemu: Error registering flash memory.\n");
				exit(1);
			}
		}
	}

    if (kernel_filename) {
        loaderparams.ram_size = ram_size;
        loaderparams.kernel_filename = kernel_filename;
        loaderparams.kernel_cmdline = kernel_cmdline;
        loaderparams.initrd_filename = initrd_filename;
        reset_info->vector = load_kernel();
    }
	/*MemoryRegionSection mrs = memory_region_find(address_space_mem,
						0x80700000, WORD_ACCESS_SIZE);
    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
    memory_region_init_alias(
            flash_alias,
            NULL,
            "router.flash.alias",
            mrs.mr,
            0,
            flash_size);
    memory_region_add_subregion(address_space_mem, 0, flash_alias);*/

    /* Init CPU internal devices. */
    cpu_mips_irq_init_cpu(cpu);
    cpu_mips_clock_init(cpu);
	/*pagemask = TARGET_PAGE_MASK;
	printf("TARGET_PAGE_MASK: %lx\n", pagemask);*/

    /* Register 64 KB of ISA IO space at 0x1fd00000. */
    memory_region_init_alias(isa, NULL, "isa_mmio",
                             get_system_io(), 0, 0x00010000);
    memory_region_add_subregion(get_system_memory(), 0x1fd00000, isa);

	sysbus_create_simple(TYPE_BCM_CHIP, 0x18000000, NULL);
	//mipschip_init(0xb8000000, NULL);

    /* A single 16450 sits at offset 0x3f8. It is attached to
       MIPS CPU INT2, which is interrupt 4. */
    if (serial_hds[0])
        serial_init(0x3f8, env->irq[4], 115200, serial_hds[0],
                    get_system_io());

    if (nd_table[0].used)
        /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
        mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
}

static void bcm_register_types(void)
{
    type_register_static(&bcm_chipid_info);
    //type_register_static(&stellaris_gptm_info);
    //type_register_static(&stellaris_adc_info);
}

type_init(bcm_register_types)

static void bcm_router_machine_init(MachineClass *mc)
{
    mc->desc = "Router based on BCM5358";
    mc->init = bcm_router_init;
}

DEFINE_MACHINE("bcm_router", bcm_router_machine_init)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] MIPS little endian - Bug when decoding physaddr
  2017-05-13 22:10     ` Vinicius Maciel
@ 2017-06-23 18:14       ` Vinicius Maciel
  2017-06-23 19:22         ` Aurelien Jarno
  0 siblings, 1 reply; 8+ messages in thread
From: Vinicius Maciel @ 2017-06-23 18:14 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Aurelien Jarno, qemu-devel

Hi everyone,

I'm having a problem similar to the reported in this email, but now I'm
trying to emulate a MIPS 24KEc,
ralink RT5350F.

Assembly Code:
0x802006a0 <reset+672>: lui t5,0xb011
0x802006a4 <reset+676>: ori t5,t5,0x168
0x802006a8 <reset+680>: li t6,23
0x802006ac <reset+684>: nop
0x802006b0 <reset+688>: sw t6,0(t5) <---

The instruction "sw t6,0(t5)" try to write to address 0xb0110168 (0x10110168),
but Qemu decodes
this address to 2952790112 (0xb0000060). Is this address right?

Qemu Debug:
#0  io_readx (env=0x5555566e4a78, iotlbentry=0x5555566ec348,
addr=2952790112,
    retaddr=140737129226144, size=4)
    at /home/vini/projs/emuladores/qemu-routers/cputlb.c:786
#1  0x00005555557c9a02 in io_readl (env=0x5555566e4a78, mmu_idx=0, index=0,
    addr=2952790112, retaddr=140737129226144)
    at /home/vini/projs/emuladores/qemu-routers/softmmu_template.h:104
#2  0x00005555557c9b89 in helper_le_ldul_mmu (env=0x5555566e4a78,
addr=2952790112, <----
    oi=32, retaddr=140737129226144)
    at /home/vini/projs/emuladores/qemu-routers/softmmu_template.h:141
#3  0x00007fffea982108 in code_gen_buffer ()

Thanks.


2017-05-13 19:10 GMT-03:00 Vinicius Maciel <viniciusfre@gmail.com>:

> Hi Philippe and Aurelien,
>
> You are right. I have created a simple SYSBUS using sysbus_create_simple
> at 0x18000000 and now my read function works!
>
> Thanks for help. I am attaching my code if you are interested.
>
> Vinicius
>
> 2017-05-13 18:57 GMT-03:00 Philippe Mathieu-Daudé <f4bug@amsat.org>:
>
>> Hi Vinicius,
>>
>> On 2017-05-12 19:52, Vinicius Maciel wrote:
>>>
>>>> Hi all,
>>>>
>>>> I'm trying to emulate a MIPS 74Kc using a custom machine in order to
>>>> run a
>>>> CFE bootloader from broadcom. The CPU is Broadcom BCM5357. The problem
>>>>
>>>
>> Here is your problem, there is no such model in QEMU.
>>
>> happens when Qemu calculates physaddr inside io_readx(), cputlb.c:line 784
>>>>
>>>> physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
>>>>
>>>> After run this line the the value is 0x18000000, which is clearly wrong.
>>>>
>>>
>> The Broadcom BCM5357 is a WiSoc (Wireless System-On-Chip).
>>
>> A SoC (System-On-Chip) is not limited to a MIPS CPU but has a large set
>> of embedded peripherals.
>>
>> QEMU does models the MIPS 74Kf cpu, but not the BCM5357 peripherals.
>>
>> At this physical address this SoC family maps a bus called
>> SiliconBackplane (BP).
>> The first peripheral mapped in the BP region is the ChipCommon (CC).
>> Common meaning this core registers intend to be consistent between
>> different models/releases using this BP bus, so a firmware can check it is
>> running the correct hardware or check if peripherals/features are
>> available/enabled to configure/use them.
>>
>> My guess is your CFE function board_earlyinit() is trying to determine
>> the chip model by reading the ChipID from the CC it supposed is physically
>> mapped at 0x18000000, which is not modeled in QEMU.
>>
>> Phil.
>>
>>
>>
>>> I don't think it's wrong, see below:
>>>
>>> More informations:
>>>>
>>>> BUG function: io_readx
>>>> Assembly instruction: lw t1,0(a2)
>>>> Machine code: 0x8cc90000 (Little endian)
>>>> Access address: 0xb8000000
>>>>
>>>> Assembly code:
>>>> 80702f30 <board_earlyinit>:
>>>> 80702f30: 3c06b800 lui a2,0xb800
>>>>
>>>
>>> This load 0xb8000000 in a2
>>>
>>> 80702f34: 24075350 li a3,21328
>>>> 80702f38: 8cc90000 lw t1,0(a2) <----
>>>>
>>>
>>> Now this try to load a value from the virtual address 0xb8000000. This
>>> address corresponds to kseg1 (Kernel Unmapped Uncached) and is mapped
>>> to the physical address 0x18000000. See the MIPS32 Privileged Resource
>>> Architecture Manual for more details how the virtual to physical mapping
>>> works.
>>>
>>> Aurelien
>>>
>>>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] MIPS little endian - Bug when decoding physaddr
  2017-06-23 18:14       ` Vinicius Maciel
@ 2017-06-23 19:22         ` Aurelien Jarno
  2017-06-23 20:21           ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 8+ messages in thread
From: Aurelien Jarno @ 2017-06-23 19:22 UTC (permalink / raw)
  To: Vinicius Maciel; +Cc: Philippe Mathieu-Daudé, qemu-devel

On 2017-06-23 15:14, Vinicius Maciel wrote:
> Hi everyone,
> 
> I'm having a problem similar to the reported in this email, but now I'm
> trying to emulate a MIPS 24KEc,
> ralink RT5350F.
> 
> Assembly Code:
> 0x802006a0 <reset+672>: lui t5,0xb011
> 0x802006a4 <reset+676>: ori t5,t5,0x168
> 0x802006a8 <reset+680>: li t6,23
> 0x802006ac <reset+684>: nop
> 0x802006b0 <reset+688>: sw t6,0(t5) <---
> 
> The instruction "sw t6,0(t5)" try to write to address 0xb0110168 (0x10110168),
> but Qemu decodes
> this address to 2952790112 (0xb0000060). Is this address right?

sw is a write instruction...

> Qemu Debug:
> #0  io_readx (env=0x5555566e4a78, iotlbentry=0x5555566ec348,
> addr=2952790112,
>     retaddr=140737129226144, size=4)
>     at /home/vini/projs/emuladores/qemu-routers/cputlb.c:786
> #1  0x00005555557c9a02 in io_readl (env=0x5555566e4a78, mmu_idx=0, index=0,
>     addr=2952790112, retaddr=140737129226144)
>     at /home/vini/projs/emuladores/qemu-routers/softmmu_template.h:104
> #2  0x00005555557c9b89 in helper_le_ldul_mmu (env=0x5555566e4a78,
> addr=2952790112, <----
>     oi=32, retaddr=140737129226144)
>     at /home/vini/projs/emuladores/qemu-routers/softmmu_template.h:141
> #3  0x00007fffea982108 in code_gen_buffer ()

... while helper_le_ldul_mmu and io_readl are read functions. The
assembly code and the backtrace do not match. We can not conclude
anything.

Aurelien


-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] MIPS little endian - Bug when decoding physaddr
  2017-06-23 19:22         ` Aurelien Jarno
@ 2017-06-23 20:21           ` Philippe Mathieu-Daudé
  2017-06-23 21:57             ` Vinicius Maciel
  0 siblings, 1 reply; 8+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-06-23 20:21 UTC (permalink / raw)
  To: Aurelien Jarno, Vinicius Maciel; +Cc: qemu-devel

Hi Vinicius,

On 06/23/2017 04:22 PM, Aurelien Jarno wrote:
> On 2017-06-23 15:14, Vinicius Maciel wrote:
>> Hi everyone,
>>
>> I'm having a problem similar to the reported in this email, but now I'm
>> trying to emulate a MIPS 24KEc,
>> ralink RT5350F.
>>
>> Assembly Code:
>> 0x802006a0 <reset+672>: lui t5,0xb011
>> 0x802006a4 <reset+676>: ori t5,t5,0x168
>> 0x802006a8 <reset+680>: li t6,23
>> 0x802006ac <reset+684>: nop
>> 0x802006b0 <reset+688>: sw t6,0(t5) <---
>>
>> The instruction "sw t6,0(t5)" try to write to address 0xb0110168 (0x10110168),
>> but Qemu decodes
>> this address to 2952790112 (0xb0000060). Is this address right?
> 
> sw is a write instruction...
[...]
> ... while helper_le_ldul_mmu and io_readl are read functions. The
> assembly code and the backtrace do not match. We can not conclude
> anything.
> 
> Aurelien

Looking at the RT5350 datasheet:
http://www.mouser.com/ds/2/813/RT5350-1022839.pdf

pp.19>
3.2 Memory Map Summary
1000.0000 - 1000.00FF 256 Mbps    SYSCTL
1011.0000 - 1011.7FFF  32 Kbps    Ethernet switch

pp.22>
3.4 System Control
3.4.3 Register Description (base: 0x1000_0000)
GPIOMODE: GPIO Purpose Select (offset: 0x0060)

pp.122>
3.19 Ethernet Switch
3.19.4 Register Description (base: 0x1011_0000)
LEDC: LED Control Register  (offset: 0x0168)
LED Polarity Control for each port: 1’b1: High active

having 23=0b10111 my guess is your reset() function try to toggle on 4 
leds. everything seems fine on QEMU side, now it depends how you 
implemented the SYSCTL and EthernetSwitch devices.

eventually you are missing some EthernetSwitch mapped registers and an 
exception is generated, ending reading some SYSCTL register...

running qemu-system with '-d in_asm,int,unimp' helps to understand if 
them problem comes from your model, before from QEMU core code.

regards,

Phil.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] MIPS little endian - Bug when decoding physaddr
  2017-06-23 20:21           ` Philippe Mathieu-Daudé
@ 2017-06-23 21:57             ` Vinicius Maciel
  0 siblings, 0 replies; 8+ messages in thread
From: Vinicius Maciel @ 2017-06-23 21:57 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Aurelien Jarno, qemu-devel

2017-06-23 17:21 GMT-03:00 Philippe Mathieu-Daudé <f4bug@amsat.org>:

> Hi Vinicius,
>
> Looking at the RT5350 datasheet:
> http://www.mouser.com/ds/2/813/RT5350-1022839.pdf
>
> pp.19>
> 3.2 Memory Map Summary
> 1000.0000 - 1000.00FF 256 Mbps    SYSCTL
> 1011.0000 - 1011.7FFF  32 Kbps    Ethernet switch
>
> pp.22>
> 3.4 System Control
> 3.4.3 Register Description (base: 0x1000_0000)
> GPIOMODE: GPIO Purpose Select (offset: 0x0060)
>
> pp.122>
> 3.19 Ethernet Switch
> 3.19.4 Register Description (base: 0x1011_0000)
> LEDC: LED Control Register  (offset: 0x0168)
> LED Polarity Control for each port: 1’b1: High active
>
> having 23=0b10111 my guess is your reset() function try to toggle on 4
> leds. everything seems fine on QEMU side, now it depends how you
> implemented the SYSCTL and EthernetSwitch devices.
>
> eventually you are missing some EthernetSwitch mapped registers and an
> exception is generated, ending reading some SYSCTL register...
>
> running qemu-system with '-d in_asm,int,unimp' helps to understand if them
> problem comes from your model, before from QEMU core code.
>
> regards,
>
> Phil.
>

Hi,

In the machine code, I added Ethernet Switch at 0x10110000:
ralink_router.c#L282
<https://gitlab.com/vinifr/qemu-routers/blob/ralink/hw/mips/ralink_router.c#L282>.
And here is Ethernet code: ralink_net.c
<https://gitlab.com/vinifr/qemu-routers/blob/ralink/hw/net/ralink_net.c>.
I'm trying to run u-boot bootloader: u-boot_RT5350F-OLinuXino
<https://github.com/OLIMEX/u-boot_RT5350F-OLinuXino>. The problem happens
when executing this line: start.S#L1540
<https://github.com/OLIMEX/u-boot_RT5350F-OLinuXino/blob/master/cpu/ralink_soc/start.S#L1540>
.

I have found Qemu reaches the function memory_region_dispatch_write:

memory_region_dispatch_write (mr=0x555556219880 <io_mem_unassigned>,
addr=269549928, data=23,
    size=4, attrs=...) at
/home/vini/projs/emuladores/qemu-routers/memory.c:1306
1306    if (!memory_region_access_valid(mr, addr, size, true)) {
(gdb) n
1307        unassigned_mem_write(mr, addr, data, size);
                return MEMTX_DECODE_ERROR;
    }

So, it happened a decode error even with Ethernet Switch registered at
0x10110000.

Thanks for help!
Vini

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-06-23 21:57 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-12 22:52 [Qemu-devel] MIPS little endian - Bug when decoding physaddr Vinicius Maciel
2017-05-13 18:28 ` Aurelien Jarno
2017-05-13 21:57   ` Philippe Mathieu-Daudé
2017-05-13 22:10     ` Vinicius Maciel
2017-06-23 18:14       ` Vinicius Maciel
2017-06-23 19:22         ` Aurelien Jarno
2017-06-23 20:21           ` Philippe Mathieu-Daudé
2017-06-23 21:57             ` Vinicius Maciel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.