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 <alistai...@gmail.com> wrote: > > On Wed, Jan 8, 2025 at 12:28 PM Sam Price <thesampr...@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