qemu-devel
[Top][All Lists]
Advanced

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

Re: Subject: [PATCH] loader: Add register setting support via cli


From: Sam Price
Subject: Re: Subject: [PATCH] loader: Add register setting support via cli
Date: Fri, 10 Jan 2025 00:33:42 -0500

Yes that is true a boot loader will do more than just set registers.
Ill rework the text a bit on the next update.
In my case i need to set the r5 register that specifies the memory
location to the device tree.
I also use the device loader to load in a elf file to ram, and the
device-loader to load in the device tree to the location specified by
the r5 register

I could add a gdb call that would return an array of string mappings
to integers.
If the machine doesn't implement the function/  leaves it as null
pointer then you wouldn't get the cli support.
Not sure where you would document all the machine register names /
numbers at though.
This might be too much though?
I left the door somewhat open on this via the NAME_NUMBER format.

There was some checking logic where if data is supplied then it forces
a check for data-len.
I could relax that check if you supply the reg.name field.

I am unsure how to determine the machine register size.
I assumed the max register size on any machine would be 8 bytes, this
might be wrong.
the gdb call seems to just pass in the full 8 bytes, but I didn't dig
into it for all machines.

Ill look at this a bit more and try to configure the git email.
I also need to set up a docker container to build /test latest.
I have been building / testing on an old ubuntu machine.
(To test this I need to run it on qemu-xilinx).
My workplace has us on ubuntu 20.

So it might be a while before I have another version up.

Thanks,
Sam

On Thu, Jan 9, 2025 at 7:34 PM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Wed, Jan 8, 2025 at 12:28 PM Sam Price <thesamprice@gmail.com> wrote:
> >
> > I made the changes, and added documentation.
> > https://gitlab.com/thesamprice/qemu/-/compare/master...loader?from_project_id=11167699
> >
> > I left it as [PREFIX]<RegNumber>
> >
> > I can switch this to just RegNumber if desired.
> >
> > I am still struggling with the email format sorry.
> > ---
> > docs/system/generic-loader.rst | 98 ++++++++++++++++++++++++++++++++
> > hw/core/generic-loader.c | 46 +++++++++++----
> > include/hw/core/generic-loader.h | 7 +++
> > 3 files changed, 139 insertions(+), 12 deletions(-)
> >
> > diff --git a/docs/system/generic-loader.rst b/docs/system/generic-loader.rst
> > index 4f9fb005f1..71d4aaa097 100644
> > --- a/docs/system/generic-loader.rst
> > +++ b/docs/system/generic-loader.rst
> > @@ -117,4 +117,102 @@ future the internal state 'set_pc' (which exists
> > in the generic loader
> > now) should be exposed to the user so that they can choose if the PC
> > is set or not.
> > +Loading Data into Registers
> > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > +
> > +The `loader` device allows the initialization of CPU registers from the 
> > command
> > +line. This feature is particularly useful for setting up the processor 
> > state
> > +before starting an executable. By configuring registers prior to 
> > execution, the
> > +`loader` can mimic the state that a bootloader would leave the processor in
> > +before transferring control to an ELF file or another executable.
>
> This isn't really true though. A bootloader generally will set more
> than the GP registers. A boot loader will configure devices and
> perhaps initalise memory.
>
> > +
> > +The syntax for loading data into registers is as follows::
> > +
> > + -device loader,reg=<reg>,data=<data>,data-len=<data-len>
> > +
> > +**Parameters:**
> > +
> > +``<reg>``
> > + The target register to set. Format must pass the following regex
> > + ``[a-zA-Z]+[0-9]+``. The numeric part corresponds to the processor's GDB \
> > + register index. For general-purpose registers, this is typically the
> > + number in the register's name (e.g., ``r5`` translates to ``5``).
> > + Special-purpose registers have specific IDs defined in their processor's
> > + `gdbstub.c` file. Note that these IDs vary between processors.
> > +
> > +``<data>``
> > + The value to load into the specified register. The data must not exceed 8
> > + bytes in size.
>
> Why 8 bytes?
>
> > +
> > +``<data-len>``
> > + The length of the data in bytes. This parameter is mandatory when using
> > + the ``data`` argument.
>
> Do we need data-len? Why not just use the register size
>
> > +
> > +**Examples:**
> > +
> > +Set a general-purpose register
> > +""""""""""""""""""""""""""""""
> > +
> > +To set register ``r5`` to ``0xc0001000`` (4 bytes) on CPU 0::
> > +
> > + -device loader,reg=r5,data=0xc0001000,data-len=4
> > +
> > +Set a special register
> > +""""""""""""""""""""""
> > +
> > +To set the Program Counter (PC, register ``32``) to ``0x80000000`` on CPU 
> > 0::
> > +
> > + -device loader,reg=pc32,data=0x80000000,data-len=4
> > +
> > +You must look in your processor's `gdbstub.c` file to special register to 
> > index
> > +mappings.
>
> That isn't really helpful for users, but I don't have a better idea
>
> > +
> > +**Special Registers:**
> > +
> > +Special registers are defined in the processor's ``gdbstub.c`` file
> > with numeric IDs.
> > +Examples from the MicroBlaze processor at one point looked like. include::
> > +
> > + enum {
> > + GDB_PC = 32 + 0,
> > + GDB_MSR = 32 + 1,
> > + GDB_EAR = 32 + 2,
> > + GDB_ESR = 32 + 3,
> > + GDB_FSR = 32 + 4,
> > + GDB_BTR = 32 + 5,
> > + GDB_PVR0 = 32 + 6,
> > + GDB_PVR11 = 32 + 17,
> > + GDB_EDR = 32 + 18,
> > + GDB_SLR = 32 + 25,
> > + GDB_SHR = 32 + 26,
> > + };
> > +
> > +For example, to set the Machine State Register (``GDB_MSR``) on a 
> > MicroBlaze
> > +processor::
> > +
> > + -device loader,reg=MSR33,data=0x00000001,data-len=4
> > +
> > +**Register Loading Notes:**
> > +
> > +1. **Processor-Specific IDs**:
> > + The numeric IDs for registers vary between processors. Always refer to the
> > + `gdbstub.c` file for the target processor to identify the correct register
> > + mappings.
> > +
> > +2. **Pre-Execution State**:
> > + This capability is ideal for initializing a simulated environment to match
> > + the state expected by an ELF file. For example, you can configure stack
> > + pointers, machine state registers, and program counters to prepare the
> > + processor to run a bootstrapped application.
> > +
> > +3. **Validation**:
> > + Register numbers are validated by the `gdb_write_register` function. 
> > Ensure
> > + the specified register is supported by the target architecture.
> > +
> > +4. **Endianess**:
> > + The `data` value is written using the processor's native endian format.
> > +
> > +By using the `loader` device to initialize registers, you can simulate
> > +realistic execution environments, enabling detailed testing and debugging
> > +of embedded software, including bootloaders interactions and operating
> > +system kernels.
> > diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
> > index ea8628b892..9408ecd150 100644
> > --- a/hw/core/generic-loader.c
> > +++ b/hw/core/generic-loader.c
> > @@ -55,6 +55,14 @@ static void generic_loader_reset(void *opaque)
> > }
> > }
> > + if(s->reg.name) {
> > + CPUClass *cc = CPU_GET_CLASS(s->cpu);
> > + int bytes_written = cc->gdb_write_register(s->cpu, (uint8_t*)
> > &s->reg.value, s->reg.num);
> > + if(bytes_written != s->reg.data_len) {
> > + printf("Error setting register %d to value %lX expected to write %d,
> > but wrote %d\n", s->reg.num, s->reg.value, s->reg.data_len,
> > bytes_written);
>
> The line wrapping is muddled up here. Can you please send it with git
> send-email. Do some sends against yourself to make sure it works.
>
> You mentioned gmail in an earlier thread I think, did you follow the
> instructions: 
> https://git-scm.com/docs/git-send-email#_use_gmail_as_the_smtp_server
>
> Alistair



-- 
Sincerely,

Sam Price



reply via email to

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