diff mbox

[v6,02/15] target-tricore: Add board for systemmode

Message ID 1408726356-14420-3-git-send-email-kbastian@mail.uni-paderborn.de
State New
Headers show

Commit Message

Bastian Koppelmann Aug. 22, 2014, 4:52 p.m. UTC
Add basic board to allow systemmode emulation

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
---
v5 -> v6:
    - tricore_testboard: Fix machine name containing blanks.

 hw/tricore/Makefile.objs       |   1 +
 hw/tricore/tricore_testboard.c | 129 +++++++++++++++++++++++++++++++++++++++++
 include/hw/tricore/tricore.h   |  54 +++++++++++++++++
 3 files changed, 184 insertions(+)
 create mode 100644 hw/tricore/Makefile.objs
 create mode 100644 hw/tricore/tricore_testboard.c
 create mode 100644 include/hw/tricore/tricore.h

Comments

Peter Maydell Aug. 29, 2014, 2:30 p.m. UTC | #1
On 22 August 2014 17:52, Bastian Koppelmann
<kbastian@mail.uni-paderborn.de> wrote:
> Add basic board to allow systemmode emulation
>
> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
> ---
> v5 -> v6:
>     - tricore_testboard: Fix machine name containing blanks.
>
>  hw/tricore/Makefile.objs       |   1 +
>  hw/tricore/tricore_testboard.c | 129 +++++++++++++++++++++++++++++++++++++++++
>  include/hw/tricore/tricore.h   |  54 +++++++++++++++++
>  3 files changed, 184 insertions(+)
>  create mode 100644 hw/tricore/Makefile.objs
>  create mode 100644 hw/tricore/tricore_testboard.c
>  create mode 100644 include/hw/tricore/tricore.h
>
> diff --git a/hw/tricore/Makefile.objs b/hw/tricore/Makefile.objs
> new file mode 100644
> index 0000000..435e095
> --- /dev/null
> +++ b/hw/tricore/Makefile.objs
> @@ -0,0 +1 @@
> +obj-y += tricore_testboard.o
> diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c
> new file mode 100644
> index 0000000..04c0f89
> --- /dev/null
> +++ b/hw/tricore/tricore_testboard.c
> @@ -0,0 +1,129 @@
> +/*
> + * TriCore Baseboard System emulation.
> + *
> + * Copyright (c) 2014 Bastian Koppelmann
> + *
> + * This code is licensed under the GPL.

Please at least say "v2 or later" (or whatever you mean here);
just "GPL" is ambiguous.

> + */
> +
> +#include "hw/hw.h"
> +#include "hw/devices.h"
> +#include "net/net.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/boards.h"
> +#include "hw/loader.h"
> +#include "sysemu/blockdev.h"
> +#include "exec/address-spaces.h"
> +#include "hw/block/flash.h"
> +#include "elf.h"
> +#include "hw/tricore/tricore.h"
> +
> +#define TRICORE_FLASH_ADDR 0xa0000000
> +#define TRICORE_FLASH_SIZE (2 * 1024 * 1024)
> +#define TRICORE_FLASH_SECT_SIZE (256 * 1024)
> +
> +
> +/* Board init.  */
> +
> +static struct tricore_boot_info tricoretb_binfo;
> +
> +static void tricore_load_kernel(CPUTRICOREState *env)
> +{
> +    int64_t entry;

Should this really be signed? It looks rather odd, especially
given you immediately cast it below.

> +    long kernel_size;
> +
> +    kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
> +                           NULL, (uint64_t *)&entry, NULL,
> +                           NULL, 0,
> +                           ELF_MACHINE, 1);
> +    if (kernel_size <= 0) {
> +        fprintf(stderr, "qemu: no kernel file '%s'\n",
> +                tricoretb_binfo.kernel_filename);

    error_report() is preferred over directly printing to stderr
(Note that it provides the trailing \n so you don't need to.)

> +        exit(1);
> +    }
> +    env->PC = entry;
> +
> +}
> +
> +static void tricore_testboard_init(MachineState *machine, int board_id)
> +{
> +    TRICORECPU *cpu;
> +    CPUTRICOREState *env;
> +
> +    MemoryRegion *sysmem = get_system_memory();
> +    MemoryRegion *ext_cram = g_new(MemoryRegion, 1);
> +    MemoryRegion *ext_dram = g_new(MemoryRegion, 1);
> +    MemoryRegion *int_cram = g_new(MemoryRegion, 1);
> +    MemoryRegion *int_dram = g_new(MemoryRegion, 1);
> +    MemoryRegion *pcp_data = g_new(MemoryRegion, 1);
> +    MemoryRegion *pcp_text = g_new(MemoryRegion, 1);
> +    DriveInfo *dinfo;
> +
> +    if (!machine->cpu_model) {
> +        machine->cpu_model = "tc1796";
> +    }
> +    cpu = cpu_tricore_init(machine->cpu_model);
> +    env = &cpu->env;
> +    if (!cpu) {
> +        fprintf(stderr, "Unable to find CPU definition\n");

    error_report("Unable to find CPU definition");

> +        exit(1);
> +    }
> +    memory_region_init_ram(ext_cram, NULL, "powerlink_ext_c.ram", 2*1024*1024);
> +    vmstate_register_ram_global(ext_cram);
> +    memory_region_init_ram(ext_dram, NULL, "powerlink_ext_d.ram", 4*1024*1024);
> +    vmstate_register_ram_global(ext_dram);
> +    memory_region_init_ram(int_cram, NULL, "powerlink_int_c.ram", 48*1024);
> +    vmstate_register_ram_global(int_cram);
> +    memory_region_init_ram(int_dram, NULL, "powerlink_int_d.ram", 48*1024);
> +    vmstate_register_ram_global(int_dram);
> +    memory_region_init_ram(pcp_data, NULL, "powerlink_pcp_data.ram", 16*1024);
> +    vmstate_register_ram_global(pcp_data);
> +    memory_region_init_ram(pcp_text, NULL, "powerlink_pcp_text.ram", 32*1024);
> +    vmstate_register_ram_global(pcp_text);
> +
> +    memory_region_add_subregion(sysmem, 0x80000000, ext_cram);
> +    memory_region_add_subregion(sysmem, 0xa1000000, ext_dram);
> +    memory_region_add_subregion(sysmem, 0xd4000000, int_cram);
> +    memory_region_add_subregion(sysmem, 0xd0000000, int_dram);
> +    memory_region_add_subregion(sysmem, 0xf0050000, pcp_data);
> +    memory_region_add_subregion(sysmem, 0xf0060000, pcp_text);

You could make this all data driven if you like, but I don't insist.

> +
> +    dinfo = drive_get(IF_PFLASH, 0, 0);
> +    if (!pflash_cfi01_register(TRICORE_FLASH_ADDR, NULL,
> +                          "tricore_testboard.flash",
> +                          TRICORE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
> +                          TRICORE_FLASH_SECT_SIZE,
> +                          TRICORE_FLASH_SIZE / TRICORE_FLASH_SECT_SIZE,
> +                          2, 0x00, 0x00, 0x0000, 0x0, 0)) {

Don't use pflash_cfi01_register() in new code, it gives you a
weird not-like-hardware flash device that we only have for
backwards compatibility with existing board models. Instantiate
and configure the flash device directly (compare vexpress.c's
ve_pflash_cfi01_register(), but use the correct config for the
hardware you're modelling, which might not be two parallel
16 bit wide flash chips).

> +
> +        fprintf(stderr, "qemu: Error registering flash memory.\n");

error_report().

> +    } else {
> +        env->PC = TRICORE_FLASH_ADDR;

This looks bogus. You should let the emulated CPU reset to its
own reset address as per whatever the architecture says CPUs
reset to. If the CPU allows a board to configure the reset address
(eg by setting input lines the CPU samples on reset) then you
should model that by making the reset address a QOM property
of the CPU.

> +    }
> +
> +    tricoretb_binfo.ram_size = machine->ram_size;
> +    tricoretb_binfo.kernel_filename = machine->kernel_filename;
> +
> +    if (machine->kernel_filename) {
> +        tricore_load_kernel(env);
> +    }
> +}
> +
> +static void tricoreboard_init(MachineState *machine)
> +{
> +    tricore_testboard_init(machine, 0x183);
> +}
> +
> +static QEMUMachine ttb_machine = {
> +    .name = "tricore_testboard",
> +    .desc = "Just for testing",
> +    .init = tricoreboard_init,
> +    .is_default = 1,
> +};

The .desc text here appears in the user-visible help output, so
can we have something slightly more useful to them, please?

$ ./build/all/tricore-softmmu/qemu-system-tricore -M help
Supported machines are:
tricore_testboard    Just for testing (default)
none                 empty machine

Also, think about whether you really want to set the
is_default flag. Will all users of TriCore based boards
always want the test board?

> +++ b/include/hw/tricore/tricore.h
> @@ -0,0 +1,54 @@
> +#ifndef TRICORE_MISC_H
> +#define TRICORE_MISC_H 1
> +
> +#include "exec/memory.h"
> +#include "hw/irq.h"
> +
> +struct tricore_boot_info {
> +    uint64_t ram_size;
> +    const char *kernel_filename;
> +    const char *kernel_cmdline;
> +    const char *initrd_filename;
> +    const char *dtb_filename;
> +    hwaddr loader_start;
> +    /* multicore boards that use the default secondary core boot functions
> +     * need to put the address of the secondary boot code, the boot reg,
> +     * and the GIC address in the next 3 values, respectively. boards that
> +     * have their own boot functions can use these values as they want.
> +     */
> +    hwaddr smp_loader_start;
> +    hwaddr smp_bootreg_addr;
> +    hwaddr gic_cpu_if_addr;
> +    int nb_cpus;
> +    int board_id;
> +    int (*atag_board)(const struct tricore_boot_info *info, void *p);
> +    /* multicore boards that use the default secondary core boot functions
> +     * can ignore these two function calls. If the default functions won't
> +     * work, then write_secondary_boot() should write a suitable blob of
> +     * code mimicking the secondary CPU startup process used by the board's
> +     * boot loader/boot ROM code, and secondary_cpu_reset_hook() should
> +     * perform any necessary CPU reset handling and set the PC for the
> +     * secondary CPUs to point at this boot blob.
> +     */
> +    void (*write_secondary_boot)(TRICORECPU *cpu,
> +                                 const struct tricore_boot_info *info);
> +    void (*secondary_cpu_reset_hook)(TRICORECPU *cpu,
> +                                     const struct tricore_boot_info *info);
> +    /* if a board is able to create a dtb without a dtb file then it
> +     * sets get_dtb. This will only be used if no dtb file is provided
> +     * by the user. On success, sets *size to the length of the created
> +     * dtb, and returns a pointer to it. (The caller must free this memory
> +     * with g_free() when it has finished with it.) On failure, returns NULL.
> +     */
> +    void *(*get_dtb)(const struct tricore_boot_info *info, int *size);
> +    /* if a board needs to be able to modify a device tree provided by
> +     * the user it should implement this hook.
> +     */
> +    void (*modify_dtb)(const struct tricore_boot_info *info, void *fdt);
> +    /* Used internally by arm_boot.c */
> +    int is_linux;
> +    hwaddr initrd_start;
> +    hwaddr initrd_size;
> +    hwaddr entry;
> +};

This looks pretty obviously like you just copied it wholesale from
the ARM board support code. Please only include struct fields
you actually use.

thanks
-- PMM
Peter Maydell Aug. 29, 2014, 6:08 p.m. UTC | #2
On 29 August 2014 20:00, Bastian Koppelmann
<kbastian@mail.uni-paderborn.de> wrote:
> Hi Peter,
>
>
> On 08/29/2014 03:30 PM, Peter Maydell wrote:
>> Don't use pflash_cfi01_register() in new code, it gives you a
>> weird not-like-hardware flash device that we only have for
>> backwards compatibility with existing board models. Instantiate
>> and configure the flash device directly (compare vexpress.c's
>> ve_pflash_cfi01_register(), but use the correct config for the
>> hardware you're modelling, which might not be two parallel
>> 16 bit wide flash chips).
>
>
> This board does not exists. It's purpose is just to be able to run TriCore
> binaries. So I rather just get rid of the flash drive.

OK, if you're not using it that's easy.

>>> +static QEMUMachine ttb_machine = {
>>> +    .name = "tricore_testboard",
>>> +    .desc = "Just for testing",
>>> +    .init = tricoreboard_init,
>>> +    .is_default = 1,
>>> +};
>>
>> The .desc text here appears in the user-visible help output, so
>> can we have something slightly more useful to them, please?
>>
>> $ ./build/all/tricore-softmmu/qemu-system-tricore -M help
>> Supported machines are:
>> tricore_testboard    Just for testing (default)
>> none                 empty machine
>
>
> Same as above. The description shows exactly the board's purpose. It is just
> for testing and not a real board. How about I change it to "a minimal
> TriCore board"?

Something like that would be OK, I just want it a bit more
descriptive and less flippant.

> I see your point about the default. For now I would leave it as is, since
> there are not other boards and qemu would give an error, when launched
> without -M.

The thing about this is that it's hard to change the default
later on, because it would mean that you'd break any
existing command lines that didn't specify the machine
but were expecting the test board. So personally I think
it's best not to specify a default if there isn't one that
makes sense.

thanks
-- PMM
Bastian Koppelmann Aug. 29, 2014, 7 p.m. UTC | #3
Hi Peter,

On 08/29/2014 03:30 PM, Peter Maydell wrote:
>
>> +
>> +    dinfo = drive_get(IF_PFLASH, 0, 0);
>> +    if (!pflash_cfi01_register(TRICORE_FLASH_ADDR, NULL,
>> +                          "tricore_testboard.flash",
>> +                          TRICORE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
>> +                          TRICORE_FLASH_SECT_SIZE,
>> +                          TRICORE_FLASH_SIZE / TRICORE_FLASH_SECT_SIZE,
>> +                          2, 0x00, 0x00, 0x0000, 0x0, 0)) {
> Don't use pflash_cfi01_register() in new code, it gives you a
> weird not-like-hardware flash device that we only have for
> backwards compatibility with existing board models. Instantiate
> and configure the flash device directly (compare vexpress.c's
> ve_pflash_cfi01_register(), but use the correct config for the
> hardware you're modelling, which might not be two parallel
> 16 bit wide flash chips).

This board does not exists. It's purpose is just to be able to run 
TriCore binaries. So I rather just get rid of the flash drive.
>> +    }
>> +
>> +    tricoretb_binfo.ram_size = machine->ram_size;
>> +    tricoretb_binfo.kernel_filename = machine->kernel_filename;
>> +
>> +    if (machine->kernel_filename) {
>> +        tricore_load_kernel(env);
>> +    }
>> +}
>> +
>> +static void tricoreboard_init(MachineState *machine)
>> +{
>> +    tricore_testboard_init(machine, 0x183);
>> +}
>> +
>> +static QEMUMachine ttb_machine = {
>> +    .name = "tricore_testboard",
>> +    .desc = "Just for testing",
>> +    .init = tricoreboard_init,
>> +    .is_default = 1,
>> +};
> The .desc text here appears in the user-visible help output, so
> can we have something slightly more useful to them, please?
>
> $ ./build/all/tricore-softmmu/qemu-system-tricore -M help
> Supported machines are:
> tricore_testboard    Just for testing (default)
> none                 empty machine

Same as above. The description shows exactly the board's purpose. It is 
just for testing and not a real board. How about I change it to "a 
minimal TriCore board"?
I see your point about the default. For now I would leave it as is, 
since there are not other boards and qemu would give an error, when 
launched without -M.

> Also, think about whether you really want to set the
> is_default flag. Will all users of TriCore based boards
> always want the test board?
>
>> +++ b/include/hw/tricore/tricore.h
>> @@ -0,0 +1,54 @@
>> +#ifndef TRICORE_MISC_H
>> +#define TRICORE_MISC_H 1
>> +
>> +#include "exec/memory.h"
>> +#include "hw/irq.h"
>> +
>> +struct tricore_boot_info {
>> +    uint64_t ram_size;
>> +    const char *kernel_filename;
>> +    const char *kernel_cmdline;
>> +    const char *initrd_filename;
>> +    const char *dtb_filename;
>> +    hwaddr loader_start;
>> +    /* multicore boards that use the default secondary core boot functions
>> +     * need to put the address of the secondary boot code, the boot reg,
>> +     * and the GIC address in the next 3 values, respectively. boards that
>> +     * have their own boot functions can use these values as they want.
>> +     */
>> +    hwaddr smp_loader_start;
>> +    hwaddr smp_bootreg_addr;
>> +    hwaddr gic_cpu_if_addr;
>> +    int nb_cpus;
>> +    int board_id;
>> +    int (*atag_board)(const struct tricore_boot_info *info, void *p);
>> +    /* multicore boards that use the default secondary core boot functions
>> +     * can ignore these two function calls. If the default functions won't
>> +     * work, then write_secondary_boot() should write a suitable blob of
>> +     * code mimicking the secondary CPU startup process used by the board's
>> +     * boot loader/boot ROM code, and secondary_cpu_reset_hook() should
>> +     * perform any necessary CPU reset handling and set the PC for the
>> +     * secondary CPUs to point at this boot blob.
>> +     */
>> +    void (*write_secondary_boot)(TRICORECPU *cpu,
>> +                                 const struct tricore_boot_info *info);
>> +    void (*secondary_cpu_reset_hook)(TRICORECPU *cpu,
>> +                                     const struct tricore_boot_info *info);
>> +    /* if a board is able to create a dtb without a dtb file then it
>> +     * sets get_dtb. This will only be used if no dtb file is provided
>> +     * by the user. On success, sets *size to the length of the created
>> +     * dtb, and returns a pointer to it. (The caller must free this memory
>> +     * with g_free() when it has finished with it.) On failure, returns NULL.
>> +     */
>> +    void *(*get_dtb)(const struct tricore_boot_info *info, int *size);
>> +    /* if a board needs to be able to modify a device tree provided by
>> +     * the user it should implement this hook.
>> +     */
>> +    void (*modify_dtb)(const struct tricore_boot_info *info, void *fdt);
>> +    /* Used internally by arm_boot.c */
>> +    int is_linux;
>> +    hwaddr initrd_start;
>> +    hwaddr initrd_size;
>> +    hwaddr entry;
>> +};
> This looks pretty obviously like you just copied it wholesale from
> the ARM board support code. Please only include struct fields
> you actually use.
>
> thanks
> -- PMM
>

Thanks,
Bastian
diff mbox

Patch

diff --git a/hw/tricore/Makefile.objs b/hw/tricore/Makefile.objs
new file mode 100644
index 0000000..435e095
--- /dev/null
+++ b/hw/tricore/Makefile.objs
@@ -0,0 +1 @@ 
+obj-y += tricore_testboard.o
diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c
new file mode 100644
index 0000000..04c0f89
--- /dev/null
+++ b/hw/tricore/tricore_testboard.c
@@ -0,0 +1,129 @@ 
+/*
+ * TriCore Baseboard System emulation.
+ *
+ * Copyright (c) 2014 Bastian Koppelmann
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/hw.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "hw/block/flash.h"
+#include "elf.h"
+#include "hw/tricore/tricore.h"
+
+#define TRICORE_FLASH_ADDR 0xa0000000
+#define TRICORE_FLASH_SIZE (2 * 1024 * 1024)
+#define TRICORE_FLASH_SECT_SIZE (256 * 1024)
+
+
+/* Board init.  */
+
+static struct tricore_boot_info tricoretb_binfo;
+
+static void tricore_load_kernel(CPUTRICOREState *env)
+{
+    int64_t entry;
+    long kernel_size;
+
+    kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
+                           NULL, (uint64_t *)&entry, NULL,
+                           NULL, 0,
+                           ELF_MACHINE, 1);
+    if (kernel_size <= 0) {
+        fprintf(stderr, "qemu: no kernel file '%s'\n",
+                tricoretb_binfo.kernel_filename);
+        exit(1);
+    }
+    env->PC = entry;
+
+}
+
+static void tricore_testboard_init(MachineState *machine, int board_id)
+{
+    TRICORECPU *cpu;
+    CPUTRICOREState *env;
+
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ext_cram = g_new(MemoryRegion, 1);
+    MemoryRegion *ext_dram = g_new(MemoryRegion, 1);
+    MemoryRegion *int_cram = g_new(MemoryRegion, 1);
+    MemoryRegion *int_dram = g_new(MemoryRegion, 1);
+    MemoryRegion *pcp_data = g_new(MemoryRegion, 1);
+    MemoryRegion *pcp_text = g_new(MemoryRegion, 1);
+    DriveInfo *dinfo;
+
+    if (!machine->cpu_model) {
+        machine->cpu_model = "tc1796";
+    }
+    cpu = cpu_tricore_init(machine->cpu_model);
+    env = &cpu->env;
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    memory_region_init_ram(ext_cram, NULL, "powerlink_ext_c.ram", 2*1024*1024);
+    vmstate_register_ram_global(ext_cram);
+    memory_region_init_ram(ext_dram, NULL, "powerlink_ext_d.ram", 4*1024*1024);
+    vmstate_register_ram_global(ext_dram);
+    memory_region_init_ram(int_cram, NULL, "powerlink_int_c.ram", 48*1024);
+    vmstate_register_ram_global(int_cram);
+    memory_region_init_ram(int_dram, NULL, "powerlink_int_d.ram", 48*1024);
+    vmstate_register_ram_global(int_dram);
+    memory_region_init_ram(pcp_data, NULL, "powerlink_pcp_data.ram", 16*1024);
+    vmstate_register_ram_global(pcp_data);
+    memory_region_init_ram(pcp_text, NULL, "powerlink_pcp_text.ram", 32*1024);
+    vmstate_register_ram_global(pcp_text);
+
+    memory_region_add_subregion(sysmem, 0x80000000, ext_cram);
+    memory_region_add_subregion(sysmem, 0xa1000000, ext_dram);
+    memory_region_add_subregion(sysmem, 0xd4000000, int_cram);
+    memory_region_add_subregion(sysmem, 0xd0000000, int_dram);
+    memory_region_add_subregion(sysmem, 0xf0050000, pcp_data);
+    memory_region_add_subregion(sysmem, 0xf0060000, pcp_text);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!pflash_cfi01_register(TRICORE_FLASH_ADDR, NULL,
+                          "tricore_testboard.flash",
+                          TRICORE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+                          TRICORE_FLASH_SECT_SIZE,
+                          TRICORE_FLASH_SIZE / TRICORE_FLASH_SECT_SIZE,
+                          2, 0x00, 0x00, 0x0000, 0x0, 0)) {
+
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+    } else {
+        env->PC = TRICORE_FLASH_ADDR;
+    }
+
+    tricoretb_binfo.ram_size = machine->ram_size;
+    tricoretb_binfo.kernel_filename = machine->kernel_filename;
+
+    if (machine->kernel_filename) {
+        tricore_load_kernel(env);
+    }
+}
+
+static void tricoreboard_init(MachineState *machine)
+{
+    tricore_testboard_init(machine, 0x183);
+}
+
+static QEMUMachine ttb_machine = {
+    .name = "tricore_testboard",
+    .desc = "Just for testing",
+    .init = tricoreboard_init,
+    .is_default = 1,
+};
+
+static void tricore_testboard_machine_init(void)
+{
+    qemu_register_machine(&ttb_machine);
+}
+
+machine_init(tricore_testboard_machine_init);
diff --git a/include/hw/tricore/tricore.h b/include/hw/tricore/tricore.h
new file mode 100644
index 0000000..4e68174
--- /dev/null
+++ b/include/hw/tricore/tricore.h
@@ -0,0 +1,54 @@ 
+#ifndef TRICORE_MISC_H
+#define TRICORE_MISC_H 1
+
+#include "exec/memory.h"
+#include "hw/irq.h"
+
+struct tricore_boot_info {
+    uint64_t ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+    const char *dtb_filename;
+    hwaddr loader_start;
+    /* multicore boards that use the default secondary core boot functions
+     * need to put the address of the secondary boot code, the boot reg,
+     * and the GIC address in the next 3 values, respectively. boards that
+     * have their own boot functions can use these values as they want.
+     */
+    hwaddr smp_loader_start;
+    hwaddr smp_bootreg_addr;
+    hwaddr gic_cpu_if_addr;
+    int nb_cpus;
+    int board_id;
+    int (*atag_board)(const struct tricore_boot_info *info, void *p);
+    /* multicore boards that use the default secondary core boot functions
+     * can ignore these two function calls. If the default functions won't
+     * work, then write_secondary_boot() should write a suitable blob of
+     * code mimicking the secondary CPU startup process used by the board's
+     * boot loader/boot ROM code, and secondary_cpu_reset_hook() should
+     * perform any necessary CPU reset handling and set the PC for the
+     * secondary CPUs to point at this boot blob.
+     */
+    void (*write_secondary_boot)(TRICORECPU *cpu,
+                                 const struct tricore_boot_info *info);
+    void (*secondary_cpu_reset_hook)(TRICORECPU *cpu,
+                                     const struct tricore_boot_info *info);
+    /* if a board is able to create a dtb without a dtb file then it
+     * sets get_dtb. This will only be used if no dtb file is provided
+     * by the user. On success, sets *size to the length of the created
+     * dtb, and returns a pointer to it. (The caller must free this memory
+     * with g_free() when it has finished with it.) On failure, returns NULL.
+     */
+    void *(*get_dtb)(const struct tricore_boot_info *info, int *size);
+    /* if a board needs to be able to modify a device tree provided by
+     * the user it should implement this hook.
+     */
+    void (*modify_dtb)(const struct tricore_boot_info *info, void *fdt);
+    /* Used internally by arm_boot.c */
+    int is_linux;
+    hwaddr initrd_start;
+    hwaddr initrd_size;
+    hwaddr entry;
+};
+#endif