All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] Emulating external registers
@ 2017-04-05 21:03 Wu, Michael Y [US] (MS)
  2017-04-06  8:32 ` Peter Maydell
  0 siblings, 1 reply; 5+ messages in thread
From: Wu, Michael Y [US] (MS) @ 2017-04-05 21:03 UTC (permalink / raw)
  To: qemu-devel

Hi,

I've been doing some bare metal programming using the powerpc system emulator. I was able to run some of my code using the g3beige system emulation. I am now currently trying emulate some external registers. Simply a powerpc address will be mapped to a register. My plan is to write a bare metal  C program that will access the contents of a given powerpc address via pointers.

My current approach is to create a new MemoryRegion in the init function of the g3beige source code (mac_oldworld.c). My idea is to set up some mmio to certain address to represent those registers. For now I only care about reading and writing, but in the future I hope to add additional logic when the registers are written.
I added the following lines:
MemoryRegion *reg = g_new(MemoryRegion, 1);
memory_region_init_alias(reg, NULL, "reg_mmio",
                            get_system_io(), 0, 0x00200000);
memory_region_add_subregion(sysmem, 0xfc000000, reg);

In my bare metal program I used the following lines to see  if it works using GDB. The issue is that GDB hangs when the pointer is either read or written. This makes me think I am doing something incorrectly.
volatile unsigned int  * const test = (unsigned int *) 0xFC000000;
  *test = 5640;

  //read from register to confirm
  if (5640 == *test) //seems to pause as well...
  {
    breakpoint_hit();
  }

I have very little limited experience with emulators so I thought I would ask to see if anyone has tips or suggestions.

Thanks!

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

* Re: [Qemu-devel] Emulating external registers
  2017-04-05 21:03 [Qemu-devel] Emulating external registers Wu, Michael Y [US] (MS)
@ 2017-04-06  8:32 ` Peter Maydell
  2017-04-06 17:23   ` [Qemu-devel] EXT :Re: " Wu, Michael Y [US] (MS)
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Maydell @ 2017-04-06  8:32 UTC (permalink / raw)
  To: Wu, Michael Y [US] (MS); +Cc: qemu-devel

On 5 April 2017 at 22:03, Wu, Michael Y [US] (MS) <Michael.Wu@ngc.com> wrote:
> My current approach is to create a new MemoryRegion in the init function of the g3beige source code (mac_oldworld.c). My idea is to set up some mmio to certain address to represent those registers. For now I only care about reading and writing, but in the future I hope to add additional logic when the registers are written.
> I added the following lines:
> MemoryRegion *reg = g_new(MemoryRegion, 1);
> memory_region_init_alias(reg, NULL, "reg_mmio",
>                             get_system_io(), 0, 0x00200000);

This is defining your region to be an alias into the
system IO region, so reading/writing your region will
act like reads and writes into those IO ports. This
doesn't sound like what you were trying to do.
Usually memory regions for registers are defined using
memory_region_init_io(), where you pass in a structure
that includes pointers to functions which are called
for reads and writes.

> memory_region_add_subregion(sysmem, 0xfc000000, reg);

Typically you would create a device model for whatever this device
is, and then map it in the board code, not directly create a
memory region in the board code.

You might find it useful to look at hw/misc/unimp.c, which
is a device which simply prints log messages when it is
read or written. Or try a simple device that your board
already has.

thanks
-- PMM

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

* Re: [Qemu-devel] EXT :Re:  Emulating external registers
  2017-04-06  8:32 ` Peter Maydell
@ 2017-04-06 17:23   ` Wu, Michael Y [US] (MS)
  2017-04-06 17:37     ` Peter Maydell
  0 siblings, 1 reply; 5+ messages in thread
From: Wu, Michael Y [US] (MS) @ 2017-04-06 17:23 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

Thank you Peter!

I changed my code to the following and added the appropriate read,write functions and a MemoryRegionOps.
    memory_region_init_io(reg_memory, NULL, &reg_ops, reg,
                          "reg_mem", 0x00000040); //set to 64 bytes
    memory_region_add_subregion(sysmem, 0xFC000000, reg_memory);

For the read function I just returned a zero. So if I were to read from the address 0xFC000000 it should return a value of 0? The current issue I am having is that gdb hangs when the pointer is accessed. I am starting to think my bare-metal program is incorrect. I also added log messages in my read and write functions. The read function was not accessed.

//Some code in my bare metal program
volatile unsigned int  * const test = (unsigned int *) 0xFC000000;
if (0x0 == *test)  //gdb hangs on this line, cannot step further
  {
    read_hit();
  }

The file 'unimp.c' you mentioned looks great! I will be using that as inspiration for creating my own device model.

-----Original Message-----
From: Peter Maydell [mailto:peter.maydell@linaro.org] 
Sent: Thursday, April 06, 2017 1:33 AM
To: Wu, Michael Y [US] (MS)
Cc: qemu-devel@nongnu.org
Subject: EXT :Re: [Qemu-devel] Emulating external registers

On 5 April 2017 at 22:03, Wu, Michael Y [US] (MS) <Michael.Wu@ngc.com> wrote:
> My current approach is to create a new MemoryRegion in the init function of the g3beige source code (mac_oldworld.c). My idea is to set up some mmio to certain address to represent those registers. For now I only care about reading and writing, but in the future I hope to add additional logic when the registers are written.
> I added the following lines:
> MemoryRegion *reg = g_new(MemoryRegion, 1); 
> memory_region_init_alias(reg, NULL, "reg_mmio",
>                             get_system_io(), 0, 0x00200000);

This is defining your region to be an alias into the system IO region, so reading/writing your region will act like reads and writes into those IO ports. This doesn't sound like what you were trying to do.
Usually memory regions for registers are defined using memory_region_init_io(), where you pass in a structure that includes pointers to functions which are called for reads and writes.

> memory_region_add_subregion(sysmem, 0xfc000000, reg);

Typically you would create a device model for whatever this device is, and then map it in the board code, not directly create a memory region in the board code.

You might find it useful to look at hw/misc/unimp.c, which is a device which simply prints log messages when it is read or written. Or try a simple device that your board already has.

thanks
-- PMM


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

* Re: [Qemu-devel] EXT :Re: Emulating external registers
  2017-04-06 17:23   ` [Qemu-devel] EXT :Re: " Wu, Michael Y [US] (MS)
@ 2017-04-06 17:37     ` Peter Maydell
  2017-04-12 18:44       ` Wu, Michael Y [US] (MS)
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Maydell @ 2017-04-06 17:37 UTC (permalink / raw)
  To: Wu, Michael Y [US] (MS); +Cc: qemu-devel

On 6 April 2017 at 18:23, Wu, Michael Y [US] (MS) <Michael.Wu@ngc.com> wrote:
> I changed my code to the following and added the appropriate read,write functions and a MemoryRegionOps.
>     memory_region_init_io(reg_memory, NULL, &reg_ops, reg,
>                           "reg_mem", 0x00000040); //set to 64 bytes
>     memory_region_add_subregion(sysmem, 0xFC000000, reg_memory);
>
> For the read function I just returned a zero. So if I were to read from the address 0xFC000000 it should return a value of 0? The current issue I am having is that gdb hangs when the pointer is accessed. I am starting to think my bare-metal program is incorrect. I also added log messages in my read and write functions. The read function was not accessed.

You'll probably find that what has happened is that your program
has taken an exception which you don't have an exception handler
installed for, and has then jumped off into nowhere or gone into
an infinite loop of taking exceptions. (Probably hitting ^c in
gdb will break into wherever it is.) It's a good idea in bare
metal test code to write at least a minimal set of exception handlers
that can print a message when an unexpected exception occurs and
stop, so you don't get too confused.

You might also want to investigate QEMU's tracing:
-d in_asm,exec,cpu,int,nochain -D debug.log will write tracing to
the debug.log file (a lot of it, and this set of trace flags
slow down execution a lot, but if you're doing very small bare
metal flags that should be ok). This can help in figuring out
what your test program is doing. (Watch out that the in_asm
shows when we first encounter a block of code, but if we
execute the same bit of code a second time we'll only print
the exec and cpu parts of the logging.)

thanks
-- PMM

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

* Re: [Qemu-devel] EXT :Re: Emulating external registers
  2017-04-06 17:37     ` Peter Maydell
@ 2017-04-12 18:44       ` Wu, Michael Y [US] (MS)
  0 siblings, 0 replies; 5+ messages in thread
From: Wu, Michael Y [US] (MS) @ 2017-04-12 18:44 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

Thank you for the suggestions. I found out that the issue was with how the bare metal program configured memory.
The program is now able to read and write from a pointer.

I included your unimplemented device into the g3 machine (mac_oldworld.c) I am emulating using the following code.
create_unimplemented_device("unimp",0x03400000,(4 << 20));

When I set a pointer to 0x03400000, I can read and write to that location. However I have no outputs from the read and write callbacks. I have the '-d unimp' set in the command arguments as well.

I added the create_unimplemented_device at the end of the function ppc_heathrow_init (mac_oldworld.c). Is my usage correct in adding this device to an existing machine?
In unimp.h, the comments mention that the priority is at -1000. Does that mean I can set a unimplemented device to a huge address range to pick up any read/writes?
 
-----Original Message-----
From: Peter Maydell [mailto:peter.maydell@linaro.org] 
Sent: Thursday, April 06, 2017 10:38 AM
To: Wu, Michael Y [US] (MS)
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] EXT :Re: Emulating external registers

On 6 April 2017 at 18:23, Wu, Michael Y [US] (MS) <Michael.Wu@ngc.com> wrote:
> I changed my code to the following and added the appropriate read,write functions and a MemoryRegionOps.
>     memory_region_init_io(reg_memory, NULL, &reg_ops, reg,
>                           "reg_mem", 0x00000040); //set to 64 bytes
>     memory_region_add_subregion(sysmem, 0xFC000000, reg_memory);
>
> For the read function I just returned a zero. So if I were to read from the address 0xFC000000 it should return a value of 0? The current issue I am having is that gdb hangs when the pointer is accessed. I am starting to think my bare-metal program is incorrect. I also added log messages in my read and write functions. The read function was not accessed.

You'll probably find that what has happened is that your program has taken an exception which you don't have an exception handler installed for, and has then jumped off into nowhere or gone into an infinite loop of taking exceptions. (Probably hitting ^c in gdb will break into wherever it is.) It's a good idea in bare metal test code to write at least a minimal set of exception handlers that can print a message when an unexpected exception occurs and stop, so you don't get too confused.

You might also want to investigate QEMU's tracing:
-d in_asm,exec,cpu,int,nochain -D debug.log will write tracing to the debug.log file (a lot of it, and this set of trace flags slow down execution a lot, but if you're doing very small bare metal flags that should be ok). This can help in figuring out what your test program is doing. (Watch out that the in_asm shows when we first encounter a block of code, but if we execute the same bit of code a second time we'll only print the exec and cpu parts of the logging.)

thanks
-- PMM


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

end of thread, other threads:[~2017-04-12 18:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-05 21:03 [Qemu-devel] Emulating external registers Wu, Michael Y [US] (MS)
2017-04-06  8:32 ` Peter Maydell
2017-04-06 17:23   ` [Qemu-devel] EXT :Re: " Wu, Michael Y [US] (MS)
2017-04-06 17:37     ` Peter Maydell
2017-04-12 18:44       ` Wu, Michael Y [US] (MS)

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.