Re: [Qemu-devel] [PATCH 4/7] m25p80: add a m25p80_set_rom_storage() routine

2016-07-09 Thread Peter Crosthwaite
On Mon, Jul 4, 2016 at 10:57 AM, mar.krzeminski
 wrote:
>
>
> W dniu 04.07.2016 o 14:18, Cédric Le Goater pisze:
>>
>> Some SPI controllers, such as the Aspeed AST2400, have a mode in which
>> accesses to the flash content are no different than doing MMIOs. The
>> controller generates all the necessary commands to load (or store)
>> data in memory.
>>
>> To emulate such a behavior, we need to have access to the underlying
>> storage of the flash object. The purpose of the routine is to set the
>> storage of a preinitialized SPI flash object, which can then be used
>> by the object itself but also by a SPI controller to handled the
>> MMIOs.
>
> Hi,
>
> I am not sure if this approach is correct. I can not find any datasheet
> to this SPI controller, but as you mentioned in first paragraph, controller
> generates all commands (probably ones are somehow configurable).
> In this series you hack this behaviour and you do direct access to file.
> IMHO you should emulate sending such commands in SPI controller
> model.
>

Actually I think this is a good approach for two reasons.

Firstly there is more than one SPI controller that does this, the
Xilinx Zynq QSPI controller does this for its LQSPI mode. See
lqspi_read() in hw/ssi/xilinx_spips.c, which already works the way
Marcin proposes. That one is semi-automatic, in that there are
software configurable registers that hold the actual command to do the
read etc. But once setup, the interface is linear-read-only and
software transparent. A lot of assumptions where made in writing that
code (the buffering scheme is completely made up) and I think the
direct approach might be cleaner. This approach can go beyond SPI, in
that it can work for other protocols and external storage devices.

The more interesting application of this approach though, is emulating
boot ROMs. Multiple SoCs in tree have pty bootroms that read SD cards
(or even SPI), mount file-systems and then blob+boot images. Rather
than emulators having to talk SDHCI through the controller to get
images, we should be able to go direct, and implement the boot-logic
off the raw block device. This means that there should be a general
approach to a machine fishing the backing block-dev out from an
external storage device, and linear SPI is another good application if
it.

Regards,
Peter

> Thanks,
> Marcin
>
>
>> This is sufficient to support read only accesses. For writes, we would
>> certainly need to externalize flash_write8() routine.
>>
>> Signed-off-by: Cédric Le Goater 
>> ---
>>   hw/block/m25p80.c| 14 +-
>>   include/hw/block/flash.h |  2 ++
>>   2 files changed, 15 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
>> index aa964280beab..fec0fd4c2228 100644
>> --- a/hw/block/m25p80.c
>> +++ b/hw/block/m25p80.c
>> @@ -29,6 +29,7 @@
>>   #include "qemu/bitops.h"
>>   #include "qemu/log.h"
>>   #include "qapi/error.h"
>> +#include "hw/block/flash.h"
>> #ifndef M25P80_ERR_DEBUG
>>   #define M25P80_ERR_DEBUG 0
>> @@ -1152,7 +1153,11 @@ static void m25p80_realize(SSISlave *ss, Error
>> **errp)
>> if (s->blk) {
>>   DB_PRINT_L(0, "Binding to IF_MTD drive\n");
>> -s->storage = blk_blockalign(s->blk, s->size);
>> +
>> +/* using an external storage. see m25p80_create_rom() */
>> +if (!s->storage) {
>> +s->storage = blk_blockalign(s->blk, s->size);
>> +}
>> if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
>>   error_setg(errp, "failed to read the initial flash
>> content");
>> @@ -1259,3 +1264,10 @@ static void m25p80_register_types(void)
>>   }
>> type_init(m25p80_register_types)
>> +
>> +void m25p80_set_rom_storage(DeviceState *dev, MemoryRegion *rom)
>> +{
>> +Flash *s = M25P80(dev);
>> +
>> +s->storage = memory_region_get_ram_ptr(rom);
>> +}
>> diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
>> index 50ccbbcf1352..9d780f4ae0c9 100644
>> --- a/include/hw/block/flash.h
>> +++ b/include/hw/block/flash.h
>> @@ -61,4 +61,6 @@ uint8_t ecc_digest(ECCState *s, uint8_t sample);
>>   void ecc_reset(ECCState *s);
>>   extern VMStateDescription vmstate_ecc_state;
>>   +void m25p80_set_rom_storage(DeviceState *dev, MemoryRegion *rom);
>> +
>>   #endif
>
>



Re: [Qemu-devel] how should a device implement an array of link(?) properties?

2016-04-28 Thread Peter Crosthwaite
On Tue, Apr 26, 2016 at 5:45 AM, Peter Maydell  wrote:
> Hi; I have what seems like a fairly straightforward requirement for
> a QOM device but no idea how to implement it, so I'm looking for
> advice on the right "modern" way to do it...
>
> Specifically, this is the GICv3 device. It would like to have
> a pointer to every CPU object it needs to be connected to.
> My guess is that this should be an array of QOM link properties
> of some kind, so that the board level code can do:
>  * create the gicv3 device

>  * set the 'num-cpu' property

I guess you want to init the array of links here?

I had something similar for the MPCore refactoring, but instead of
initing a number of links in the property setter, it inited an array
of child devices and property value passthroughs.

https://lists.nongnu.org/archive/html/qemu-devel/2015-06/msg03633.html

see:
+static void a9mpcore_set_num_cpus(Object *obj, Visitor *v,

I guess instead of object_initialize() you want to replace with
object_property_add_link()?

>  * for each cpu: set the cpu[i] property to that CPU
>  * realize the device
>
> But how should I implement this in the device? There are
> qdev array properties, but there's no link qdev property type.
> Or should I not be using a link property at all?
> Suggestions for the right approach welcome.
>

Does the [*] syntax work? This can implement arrays of props
implicitly. See object_property_add() and the special casing of "[*]"
suffix. In init code, you should be able to create your link property
in a loop with "foo[*]" naming then then elements will be foo[0],
foo[1] ... . May be worth adding a helper to QOM to do the array
instantiation but for the underlying QOM representation, we already
have precedent for just using "[]" suffixes as special names for
arrays.

Regards,
Peter

> thanks
> -- PMM



Re: [Qemu-devel] [Qemu-arm] [PATCH] bcm2835_property: use cached values when querying framebuffer

2016-04-22 Thread Peter Crosthwaite
On Fri, Apr 22, 2016 at 4:44 AM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
> Hi all,
>
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Friday, 22 April 2016 09:18
>>
>> On Thu, Apr 21, 2016 at 9:06 AM, Stephen Warren
>> <swar...@wwwdotorg.org> wrote:
>> > On 04/21/2016 08:07 AM, Sylvain Garrigues wrote:
>> >>
>> >> Le 21 avr. 2016 à 15:42, Peter Maydell <peter.mayd...@linaro.org> a
>> >> écrit
>> >> :
>> >>>
>> >>>
>> >>> There may be something we can do here to make FreeBSD's life easier,
>> >>> but we definitely can't do it on the eve of a release.
>> >>
>> >>
>> >> I didn’t know it was release day, my timing is not perfect then,
>> >> sorry about that, I didn’t intend to put stress on you guys today.
>> >> Like you mentioned, the Linux boot protocol doesn’t mandate any
>> >> loading address, hence the possibility to set it on the command line.
>> >> It would benefit not only to FreeBSD (which is strictly Linux boot
>> >> ABI compliant BTW - that is how I found the qemu bootloader bug and
>> >> fixed it in
>> >> b4850e5) but all other OS.
>> >> On the real hardware Raspberry Pi, there is the kernel_address
>> >> firmware feature which enable to set the kernel load address. Would
>> >> be neat to have it *someday* in qemu for any board if it is not too hard 
>> >> to
>> implement.
>> >
>> >
>> > It would indeed be nice if qemu for the Pi implemented the exact same
>> > bootloader setup as real HW does. That is, loading boot images from
>> > the FAT partition on the SD card, parsing config.txt, etc.
>> >
>> > Ideally as was mentioned earlier this would be done by simply
>> > executing the existing bootloader under emulation, rather than
>> > building all that code into qemu. However, in the Pi case, the
>> > bootloader runs on the VideoCore (a separate non-ARM CPU), so isn't
>> > (and likely won't be since IIUC it isn't fully documented) emulated by
>> > qemu. by the time the ARM CPU runs, everything (kernel, DTB/ATAGS, ARM
>> > boot stub, ...) is already loaded into RAM, the display is already
>> > probed over HDMI and the controller scanning out a dummy image, etc.
>> >
>> > So I think if that were to be supported, it'd have to be coded into
>> > qemu. Is that something that could happen, or would such patches not
>> > fit qemu's model well?
>>
>> I made half a start on this project but had to shelve it.
>>
>> The hard part is the FAT filesystem. The basic approach I started on was to 
>> link
>> in the relevant bits of the GNU mtools so QEMU can poke around in a FAT
>> filesystem hosted on a block device. Then just mount the SD card and emulate
>> the boot logic of the VideoCore bootloader.
>> This amount of new code should actually be pretty small, as the FS driver is
>> handled by mtools and the SDHCI can be shorted by just having this alternate
>> bootloader go direct to the block device (fish the blockdev out from the SD
>> card).
>
> You got further on this than I did. I considered a couple of options, of 
> varying complexity/compatibility:
>
>  0. The status quo: we support -kernel (for Linux images) and -bios (e.g. 
> Windows), but otherwise all the options that can be set in config.txt are 
> treated as the defaults. For example, -bios images are always loaded at 
> 0x8000. Additionally, framebuffer parameters can be set directly from the 
> command line (e.g. Windows wants -global bcm2835-fb.pixo=0).
>  1. More pi-specific parameters in the line of the framebuffer parameters 
> above, to control things like the image load address, and maybe to enable 
> trustzone boot akin to config.txt's kernel-old=1.
>  2. Code to parse config.txt and set the parameters above.
>  3. Code to emulate the bootloader entirely, pulling config.txt and all the 
> relevant boot bits out of an SD image (this is what Peter describes above).
>  4. An ARM-based reimplementation of the bootloader, running under emulation.

Setting up U-boot to be #4 could work.

>
> I discarded even considering option 3 because I assumed you wouldn't want a 
> FAT implementation linked into qemu.

rPI is not alone here though. Xilinx Zynq does exactly the same thing
with boot code pulling things out of SD card + FAT so you have at
least two precedents justifying the feature.

Regards,
Peter

> And I'm not inclined to add ini-parsing code, so my gut feeling was to go a 
> little further on option 1 and add parameters to the raspi machines (I assume 
> this is possible?) for basic things like the load address, and rely on users 
> to translate config.txt settings into command-line parameters.
>
> Andrew



Re: [Qemu-devel] [Qemu-arm] [PATCH] bcm2835_property: use cached values when querying framebuffer

2016-04-22 Thread Peter Crosthwaite
On Fri, Apr 22, 2016 at 12:46 AM, Gerd Hoffmann  wrote:
>   Hi,
>
>> > Ideally as was mentioned earlier this would be done by simply executing the
>> > existing bootloader under emulation, rather than building all that code 
>> > into
>> > qemu. However, in the Pi case, the bootloader runs on the VideoCore (a
>> > separate non-ARM CPU), so isn't (and likely won't be since IIUC it isn't
>> > fully documented) emulated by qemu. by the time the ARM CPU runs, 
>> > everything
>> > (kernel, DTB/ATAGS, ARM boot stub, ...) is already loaded into RAM, the
>> > display is already probed over HDMI and the controller scanning out a dummy
>> > image, etc.
>> >
>> > So I think if that were to be supported, it'd have to be coded into qemu. 
>> > Is
>> > that something that could happen, or would such patches not fit qemu's 
>> > model
>> > well?
>>
>> I made half a start on this project but had to shelve it.
>>
>> The hard part is the FAT filesystem. The basic approach I started on
>> was to link in the relevant bits of the GNU mtools so QEMU can poke
>> around in a FAT filesystem hosted on a block device. Then just mount
>> the SD card and emulate the boot logic of the VideoCore bootloader.
>> This amount of new code should actually be pretty small, as the FS
>> driver is handled by mtools and the SDHCI can be shorted by just
>> having this alternate bootloader go direct to the block device (fish
>> the blockdev out from the SD card).
>
> Alternatively we can just go for a later boot loader stage, i.e. put a
> u-boot build for rpi2 to pc-bios/ (we already have one for ppc there)
> and run that by default.
>

Rather than a later boot stage, could we set this up to be identical
in functionality to the early boot stage? This enables baremetal devs
who want to debug from the real bootrom handoff (handoff from
VideoCore).

Doing it over FAT+bootloader code does however have the advantage of
not having to go through emulated SD card and TCG.

Regards,
Peter

> Our sdcard emulation seems to have problems though:
>
>U-Boot 2016.05-rc2 (Apr 22 2016 - 09:11:45 +0200)
>
>DRAM:  960 MiB
>RPI 2 Model B (0xa21041)
>MMC:   
>
> Recent linux kernels have trouble talking to the mmc too.



Re: [Qemu-devel] [Qemu-arm] [PATCH] bcm2835_property: use cached values when querying framebuffer

2016-04-22 Thread Peter Crosthwaite
On Thu, Apr 21, 2016 at 9:06 AM, Stephen Warren  wrote:
> On 04/21/2016 08:07 AM, Sylvain Garrigues wrote:
>>
>> Le 21 avr. 2016 à 15:42, Peter Maydell  a écrit
>> :
>>>
>>>
>>> There may be something we can do here to make FreeBSD's life
>>> easier, but we definitely can't do it on the eve of a release.
>>
>>
>> I didn’t know it was release day, my timing is not perfect then, sorry
>> about that, I didn’t intend to put stress on you guys today.
>> Like you mentioned, the Linux boot protocol doesn’t mandate any loading
>> address, hence the possibility to set it on the command line.
>> It would benefit not only to FreeBSD (which is strictly Linux boot ABI
>> compliant BTW - that is how I found the qemu bootloader bug and fixed it in
>> b4850e5) but all other OS.
>> On the real hardware Raspberry Pi, there is the kernel_address firmware
>> feature which enable to set the kernel load address. Would be neat to have
>> it *someday* in qemu for any board if it is not too hard to implement.
>
>
> It would indeed be nice if qemu for the Pi implemented the exact same
> bootloader setup as real HW does. That is, loading boot images from the FAT
> partition on the SD card, parsing config.txt, etc.
>
> Ideally as was mentioned earlier this would be done by simply executing the
> existing bootloader under emulation, rather than building all that code into
> qemu. However, in the Pi case, the bootloader runs on the VideoCore (a
> separate non-ARM CPU), so isn't (and likely won't be since IIUC it isn't
> fully documented) emulated by qemu. by the time the ARM CPU runs, everything
> (kernel, DTB/ATAGS, ARM boot stub, ...) is already loaded into RAM, the
> display is already probed over HDMI and the controller scanning out a dummy
> image, etc.
>
> So I think if that were to be supported, it'd have to be coded into qemu. Is
> that something that could happen, or would such patches not fit qemu's model
> well?

I made half a start on this project but had to shelve it.

The hard part is the FAT filesystem. The basic approach I started on
was to link in the relevant bits of the GNU mtools so QEMU can poke
around in a FAT filesystem hosted on a block device. Then just mount
the SD card and emulate the boot logic of the VideoCore bootloader.
This amount of new code should actually be pretty small, as the FS
driver is handled by mtools and the SDHCI can be shorted by just
having this alternate bootloader go direct to the block device (fish
the blockdev out from the SD card).

Regards,
Peter

>



Re: [Qemu-devel] [PATCH 2/3] i.MX: Add the Freescale SPI Controller

2016-03-20 Thread Peter Crosthwaite
On Tue, Feb 16, 2016 at 9:15 AM, mar.krzeminski
 wrote:
>
>
> W dniu 15.02.2016 o 23:43, Jean-Christophe DUBOIS pisze:
>
>> Le 15/02/2016 17:46, mar.krzeminski a écrit :
>>>
>>>
>>>
>>> W dniu 15.02.2016 o 11:18, Jean-Christophe DUBOIS pisze:

 Le 14/02/2016 20:17, mar.krzeminski a écrit :
>
>

>> controller is working. Now this information (the number of bits actually
>> transferred) does not seem to be conveyed by the QEMU SSI API. So it is 
>> my
>> understanding that it is up to the EEPROM to only consider the bits it is
>> designed to work with.
>
> Current SSI API does not have these information, even more, the flash
> model assumes that data width will be one byte - see m25p80_transfer8 in
> m25p80.c. There you can also find sst25vf016b model,
> and with you current implementation it will not work. In my comment I
> mean only current ssi usage not the real world.


 OK, so to summarize, at present time all QEMU SPI slave devices are
 expecting to receive (and provide) data at a byte level only (even if the
 QEMU SSI API is capable of 4 bytes access). So I need to split the (up to) 
 4
 bytes access of the i.MX SPI master in 1 to 4 single byte access (depending
 on the burst size).

>>> Yes.
>>> I think about your idea to add interface to set transfer length fo SSI
>>> API. The question is, if someone really need such feature.
>>

I think so.

>>
>> Well, obviously, memory (or even LCD screen) are not good candidate for
>> access that are not byte aligned. I guess other type of devices (like an ADC
>> or a DAC) might work on 10, 12 (or other size) bits and accept more uncommon
>> access pattern. After all the i.MX SPI controller could handle any SPI burst
>> length between 1 and 4096 bits.
>>
>> Now I guess that such devices DAC/ADC are more difficult to emulate in a
>> useful way inside QEMU. So this might not be very popular and therefore not
>> very useful. It might not be worth the trouble inside QEMU ...
>>
> Modern flash memories have dummy clock cycles for fast operation commands,
> so instead of sending 12 bits I need to call 12 times ssi_trasfer.
> Having such feature could also allow to emulate QSPI and family transfer
> modes, but I guess all of this it is corner case...
>

This keeps coming up so the demand is less corner case than we think.

Regards,
Peter

> Thanks,
> Marcin
>>>



Re: [Qemu-devel] [PATCH v4 09/11] block: m25p80: Implemented FSR register

2016-03-19 Thread Peter Crosthwaite
On Mon, Feb 22, 2016 at 12:03 AM,  <marcin.krzemin...@nokia.com> wrote:
> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>
> Implements FSR register, it is used for busy waits.
>
> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
> ---
>  hw/block/m25p80.c | 11 +++
>  1 file changed, 11 insertions(+)
>
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 4acc79a..bc0dadb 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -222,6 +222,7 @@ typedef enum {
>  WREN = 0x6,
>  JEDEC_READ = 0x9f,
>  BULK_ERASE = 0xc7,
> +READ_FSR = 0x70,
>
>  READ = 0x3,
>  READ4 = 0x13,
> @@ -678,6 +679,16 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  s->state = STATE_READING_DATA;
>  break;
>
> +case READ_FSR:
> +s->data[0] = (1 << 7); /*Indicates flash is ready */
> +if (s->four_bytes_address_mode) {
> +s->data[0] |= 0x1;
> +}
> +s->pos = 0;
> +s->len = 1;
> +s->state = STATE_READING_DATA;
> +break;
> +

To be consistent with recommendation on CFG register macros it should
be done here too.

Otherwise:

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

>  case JEDEC_READ:
>  DB_PRINT_L(0, "populated jedec code\n");
>  s->data[0] = (s->pi->jedec >> 16) & 0xff;
> --
> 2.5.0
>



Re: [Qemu-devel] [PATCH v4 08/11] block: m25p80: Fast read and 4bytes commands

2016-03-19 Thread Peter Crosthwaite
On Mon, Feb 22, 2016 at 12:03 AM,  <marcin.krzemin...@nokia.com> wrote:
> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>
> Adds fast read and 4bytes commands family.
> This work is based on Pawel Lenkow patch from v1.
>
> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
> ---
>  hw/block/m25p80.c | 48 +---
>  1 file changed, 45 insertions(+), 3 deletions(-)
>
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index aff28f3..4acc79a 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -224,19 +224,28 @@ typedef enum {
>  BULK_ERASE = 0xc7,
>
>  READ = 0x3,

You should fix READ as "0x03"

> -FAST_READ = 0xb,
> +READ4 = 0x13,
> +FAST_READ = 0x0b,

To match this context change

> +FAST_READ4 = 0x0c,
>  DOR = 0x3b,
> +DOR4 = 0x3c,
>  QOR = 0x6b,
> +QOR4 = 0x6c,
>  DIOR = 0xbb,
> +DIOR4 = 0xbc,
>  QIOR = 0xeb,
> +QIOR4 = 0xec,
>
>  PP = 0x2,
> +PP4 = 0x12,
>  DPP = 0xa2,
>  QPP = 0x32,
>
>  ERASE_4K = 0x20,
> +ERASE4_4K = 0x21,
>  ERASE_32K = 0x52,
>  ERASE_SECTOR = 0xd8,
> +ERASE4_SECTOR = 0xdc,
>
>  EN_4BYTE_ADDR = 0xB7,
>  EX_4BYTE_ADDR = 0xE9,
> @@ -359,6 +368,7 @@ static void flash_erase(Flash *s, int offset, FlashCMD 
> cmd)
>
>  switch (cmd) {
>  case ERASE_4K:
> +case ERASE4_4K:
>  len = 4 << 10;
>  capa_to_assert = ER_4K;
>  break;
> @@ -367,6 +377,7 @@ static void flash_erase(Flash *s, int offset, FlashCMD 
> cmd)
>  capa_to_assert = ER_32K;
>  break;
>  case ERASE_SECTOR:
> +case ERASE4_SECTOR:
>  len = s->pi->sector_size;
>  break;
>  case BULK_ERASE:
> @@ -425,7 +436,20 @@ void flash_write8(Flash *s, uint64_t addr, uint8_t data)
>
>  static inline int get_addr_length(Flash *s)
>  {
> -return s->four_bytes_address_mode ? 4 : 3;
> +   switch (s->cmd_in_progress) {
> +   case PP4:
> +   case READ4:
> +   case QIOR4:
> +   case ERASE4_4K:
> +   case ERASE4_SECTOR:
> +   case FAST_READ4:
> +   case DOR4:
> +   case QOR4:
> +   case DIOR4:
> +   return 4;
> +   default:
> +   return s->four_bytes_address_mode ? 4 : 3;
> +   }
>  }
>
>  static void complete_collecting_data(Flash *s)
> @@ -449,19 +473,28 @@ static void complete_collecting_data(Flash *s)
>  case DPP:
>  case QPP:
>  case PP:
> +case PP4:
>  s->state = STATE_PAGE_PROGRAM;
>  break;
>  case READ:
> +case READ4:
>  case FAST_READ:
> +case FAST_READ4:
>  case DOR:
> +case DOR4:
>  case QOR:
> +case QOR4:
>  case DIOR:
> +case DIOR4:
>  case QIOR:
> +case QIOR4:
>  s->state = STATE_READ;
>  break;
>  case ERASE_4K:
> +case ERASE4_4K:
>  case ERASE_32K:
>  case ERASE_SECTOR:
> +case ERASE4_SECTOR:
>  flash_erase(s, s->cur_addr, s->cmd_in_progress);
>  break;
>  case WRSR:
> @@ -550,12 +583,16 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  switch (value) {
>
>  case ERASE_4K:
> +case ERASE4_4K:
>  case ERASE_32K:
>  case ERASE_SECTOR:
> +case ERASE4_SECTOR:
>  case READ:
> +case READ4:
>  case DPP:
>  case QPP:
>  case PP:
> +case PP4:
>  s->needed_bytes = get_addr_length(s);
>  s->pos = 0;
>  s->len = 0;
> @@ -563,11 +600,14 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>      break;
>
>  case FAST_READ:
> +case FAST_READ4:
>  case DOR:
> +case DOR4:
>  case QOR:
> +case QOR4:
>  s->needed_bytes = get_addr_length(s);
>  if (((s->pi->jedec >> 16) & 0xFF) == JEDEC_NUMONYX) {
> -/* Dummy cycles modeled with bytes writes instead of bits */
> +/* Dummy cycles - modeled with bytes writes instead of bits */

White change shouldn't be here.

Otherwise:

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

>  s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
>  }
>  s->pos = 0;
> @@ -576,6 +616,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  break;
>
>  case DIOR:
> +case DIOR4:
>  switch ((s->pi->jedec >> 16) & 0xFF) {
>  case JEDEC_WINBOND:
>  case JEDEC_SPANSION:
> @@ -595,6 +636,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  break;
>
>  case QIOR:
> +case QIOR4:
>  switch ((s->pi->jedec >> 16) & 0xFF) {
>  case JEDEC_WINBOND:
>  case JEDEC_SPANSION:
> --
> 2.5.0
>



Re: [Qemu-devel] [PATCH v4 06/11] block: m25p80: Add configuration registers

2016-03-19 Thread Peter Crosthwaite
On Mon, Feb 22, 2016 at 12:03 AM,  <marcin.krzemin...@nokia.com> wrote:
> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>
> This patch adds both volatile and non volatile configuration registers
> and commands to allow modify them. It is needed for proper handling
> dummy cycles. Initialization of those registers and flash state
> has been included as well.
> Some of this registers are used by kernel.
>
> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
> ---
>  hw/block/m25p80.c | 110 
> ++
>  1 file changed, 110 insertions(+)
>
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 0698e7b..9d5a071 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -26,6 +26,7 @@
>  #include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/ssi/ssi.h"
> +#include "qemu/bitops.h"
>
>  #ifndef M25P80_ERR_DEBUG
>  #define M25P80_ERR_DEBUG 0
> @@ -245,6 +246,15 @@ typedef enum {
>
>  RESET_ENABLE = 0x66,
>  RESET_MEMORY = 0x99,
> +
> +RNVCR = 0xB5,
> +WNVCR = 0xB1,
> +
> +RVCR = 0x85,
> +WVCR = 0x81,
> +
> +REVCR = 0x65,
> +WEVCR = 0x61,
>  } FlashCMD;
>
>  typedef enum {
> @@ -271,6 +281,9 @@ typedef struct Flash {
>  uint8_t needed_bytes;
>  uint8_t cmd_in_progress;
>  uint64_t cur_addr;
> +uint32_t nonvolatile_cfg;
> +uint32_t volatile_cfg;
> +uint32_t enh_volatile_cfg;
>  bool write_enable;
>  bool four_bytes_address_mode;
>  bool reset_enable;
> @@ -459,6 +472,15 @@ static void complete_collecting_data(Flash *s)
>  case EXTEND_ADDR_WRITE:
>  s->ear = s->data[0];
>  break;
> +case WNVCR:
> +s->nonvolatile_cfg = s->data[0] | (s->data[1] << 8);
> +break;
> +case WVCR:
> +s->volatile_cfg = s->data[0];
> +break;
> +case WEVCR:
> +s->enh_volatile_cfg = s->data[0];
> +break;
>  default:
>  break;
>  }
> @@ -477,6 +499,42 @@ static void reset_memory(Flash *s)
>  s->write_enable = false;
>  s->reset_enable = false;
>
> +if (((s->pi->jedec >> 16) & 0xFF) == JEDEC_NUMONYX) {
> +s->volatile_cfg = 0;
> +/* WRAP & reserved*/

These bitfield masks and their values need some macrofication. Then
the comments explaining what bits are what can be dropped.

> +s->volatile_cfg |= 0x3;

Why you set a reserved bit?

> +/* XIP */
> +if (extract32(s->nonvolatile_cfg, 9, 3) != 0x7) {

An example,
#define NVCFG_XIP_MODE_DISABLED 0x7

> +s->volatile_cfg |= (1 << 3);
> +}
> +/* Number of dummy cycles */
> +s->volatile_cfg |= deposit32(s->volatile_cfg,
> +4, 4, extract32(s->nonvolatile_cfg, 12, 4));
> +    s->enh_volatile_cfg = 0;
> +/* Output driver strength */
> +s->enh_volatile_cfg |= 0x7;
> +/* Vpp accelerator */
> +s->enh_volatile_cfg |= (1 << 3);

#define EVCFG_VPP_ACCELERATOR (1 << 3) ...

I am aware of my unreliability to get the review timely but the patch
intent looks good,

so with the macroification changes (globally to this function):

Acked-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Regards,
Peter

> +/* Reset/hold & reserved */
> +s->enh_volatile_cfg |= (1 << 4);
> +/* Dual I/O protocol */
> +if ((s->nonvolatile_cfg >> 1) & 0x1) {
> +s->enh_volatile_cfg |= (1 << 6);
> +}
> +/* Quad I/O protocol */
> +if ((s->nonvolatile_cfg >> 3) & 0x1) {
> +s->enh_volatile_cfg |= (1 << 7);
> +}
> +
> +if (!(s->nonvolatile_cfg & 0x1)) {
> +s->four_bytes_address_mode = true;
> +}
> +
> +if (!((s->nonvolatile_cfg >> 1) & 0x1)) {
> +s->ear = 0x3;
> +}
> +}
> +
>  DB_PRINT_L(0, "Reset done.\n");
>  }
>
> @@ -617,6 +675,49 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  s->state = STATE_COLLECTING_DATA;
>  }
>  break;
> +case RNVCR:
> +s->data[0] = s->nonvolatile_cfg & 0xFF;
> +s->data[1] = (s->nonvolatile_cfg >> 8) & 0xFF;
> +s->pos = 0;
> +s->len = 2;
> +s->state = STATE_READING_DATA;
> +break;
> +case WNVCR:
> +

Re: [Qemu-devel] [PATCH v4 05/11] block: m25p80: 4byte address mode

2016-03-19 Thread Peter Crosthwaite
On Mon, Feb 22, 2016 at 12:03 AM,  <marcin.krzemin...@nokia.com> wrote:
> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>
> This patch adds only 4byte address mode (does not cover dummy cycles).
> This mode is needed to access more than 16 MiB of flash.
>
> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
> ---
>  hw/block/m25p80.c | 41 +++--
>  1 file changed, 35 insertions(+), 6 deletions(-)
>
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 0540dde..0698e7b 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -237,6 +237,9 @@ typedef enum {
>  ERASE_32K = 0x52,
>  ERASE_SECTOR = 0xd8,
>
> +EN_4BYTE_ADDR = 0xB7,
> +EX_4BYTE_ADDR = 0xE9,
> +
>  EXTEND_ADDR_READ = 0xC8,
>  EXTEND_ADDR_WRITE = 0xC5,
>
> @@ -269,6 +272,7 @@ typedef struct Flash {
>  uint8_t cmd_in_progress;
>  uint64_t cur_addr;
>  bool write_enable;
> +bool four_bytes_address_mode;
>  bool reset_enable;
>  uint8_t ear;
>
> @@ -406,12 +410,25 @@ void flash_write8(Flash *s, uint64_t addr, uint8_t data)
>  s->dirty_page = page;
>  }
>
> +static inline int get_addr_length(Flash *s)
> +{
> +return s->four_bytes_address_mode ? 4 : 3;
> +}
> +
>  static void complete_collecting_data(Flash *s)
>  {
> -s->cur_addr = s->data[0] << 16;
> -s->cur_addr |= s->data[1] << 8;
> -s->cur_addr |= s->data[2];
> -s->cur_addr += (s->ear & 0x3) * MAX_3BYTES_SIZE;
> +int i;
> +
> +s->cur_addr = 0;
> +
> +for (i = 0; i < get_addr_length(s); ++i) {
> +s->cur_addr <<= 8;
> +s->cur_addr |= s->data[i];
> +}
> +
> +if (get_addr_length(s) == 3) {
> +s->cur_addr += (s->ear & 0x3) * MAX_3BYTES_SIZE;
> +}
>
>  s->state = STATE_IDLE;
>
> @@ -452,6 +469,7 @@ static void reset_memory(Flash *s)
>  s->cmd_in_progress = NOP;
>  s->cur_addr = 0;
>  s->ear = 0;
> +s->four_bytes_address_mode = false;
>  s->len = 0;
>  s->needed_bytes = 0;
>  s->pos = 0;
> @@ -480,7 +498,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  case DPP:
>  case QPP:
>  case PP:
> -s->needed_bytes = 3;
> +s->needed_bytes = get_addr_length(s);
>  s->pos = 0;
>  s->len = 0;
>  s->state = STATE_COLLECTING_DATA;
> @@ -489,7 +507,7 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  case FAST_READ:
>  case DOR:
>  case QOR:
> -s->needed_bytes = 4;
> +s->needed_bytes = get_addr_length(s);

You fix this later with the configuration of dummy cycles, but you
should preserve the existing behaviour until your fix lands. This
means that you should have +1 here.

>  s->pos = 0;
>  s->len = 0;
>  s->state = STATE_COLLECTING_DATA;
> @@ -502,6 +520,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  s->needed_bytes = 4;
>  break;
>  case JEDEC_NUMONYX:
> +s->needed_bytes = get_addr_length(s);
> +    break;

This change ...

>  default:
>  s->needed_bytes = 5;

Should be here, with a +2 (I think?).

>  }
> @@ -517,6 +537,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  s->needed_bytes = 6;
>  break;
>  case JEDEC_NUMONYX:
> +s->needed_bytes = get_addr_length(s);
> +break;

Similar.

Otherwise,

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Regards,
Peter

>  default:
>  s->needed_bytes = 8;
>  }
> @@ -575,6 +597,12 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  break;
>  case NOP:
>  break;
> +case EN_4BYTE_ADDR:
> +s->four_bytes_address_mode = true;
> +break;
> +case EX_4BYTE_ADDR:
> +s->four_bytes_address_mode = false;
> +break;
>  case EXTEND_ADDR_READ:
>  s->data[0] = s->ear;
>  s->pos = 0;
> @@ -724,6 +752,7 @@ static const VMStateDescription vmstate_m25p80 = {
>  VMSTATE_UINT8(cmd_in_progress, Flash),
>  VMSTATE_UINT64(cur_addr, Flash),
>  VMSTATE_BOOL(write_enable, Flash),
> +VMSTATE_BOOL(four_bytes_address_mode, Flash),
>  VMSTATE_UINT8(ear, Flash),
>  VMSTATE_BOOL(reset_enable, Flash),
>  VMSTATE_END_OF_LIST()
> --
> 2.5.0
>



Re: [Qemu-devel] [PATCH v4 02/11] block: m25p80: RESET_ENABLE and RESET_MEMORY commnads

2016-03-19 Thread Peter Crosthwaite
"commands" in commit msg

On Mon, Feb 22, 2016 at 12:03 AM,  <marcin.krzemin...@nokia.com> wrote:
> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>
> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
> ---
>  hw/block/m25p80.c | 35 ++-
>  1 file changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 124..06b0af3 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -233,6 +233,9 @@ typedef enum {
>  ERASE_4K = 0x20,
>  ERASE_32K = 0x52,
>  ERASE_SECTOR = 0xd8,
> +
> +RESET_ENABLE = 0x66,
> +RESET_MEMORY = 0x99,
>  } FlashCMD;
>
>  typedef enum {
> @@ -260,6 +263,7 @@ typedef struct Flash {
>  uint8_t cmd_in_progress;
>  uint64_t cur_addr;
>  bool write_enable;
> +bool reset_enable;
>
>  int64_t dirty_page;
>
> @@ -432,11 +436,29 @@ static void complete_collecting_data(Flash *s)
>  }
>  }
>
> +static void reset_memory(Flash *s)
> +{
> +s->cmd_in_progress = NOP;
> +s->cur_addr = 0;
> +s->len = 0;
> +s->needed_bytes = 0;
> +s->pos = 0;
> +s->state = STATE_IDLE;
> +s->write_enable = false;
> +s->reset_enable = false;
> +
> +DB_PRINT_L(0, "Reset done.\n");
> +}
> +
>  static void decode_new_cmd(Flash *s, uint32_t value)
>  {
>  s->cmd_in_progress = value;
>  DB_PRINT_L(0, "decoded new command:%x\n", value);
>
> +if (value != RESET_MEMORY) {
> +s->reset_enable = false;
> +}
> +
>  switch (value) {
>
>  case ERASE_4K:
> @@ -541,6 +563,14 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  break;
>  case NOP:
>  break;
> +case RESET_ENABLE:
> +s->reset_enable = true;
> +break;
> +case RESET_MEMORY:
> +if (s->reset_enable) {
> +reset_memory(s);
> +}
> +break;
>  default:
>  qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n", value);
>  break;
> @@ -622,6 +652,8 @@ static int m25p80_init(SSISlave *ss)
>  s->size = s->pi->sector_size * s->pi->n_sectors;
>  s->dirty_page = -1;
>
> +reset_memory(s);
> +

This shouldn't be here, you need to add a Device::reset function. Your
use case of persisting data through a warn system reset (that we
discussed previously) is difficult to support with QEMUs current reset
semantics and your board is out-of-tree. So I think this should be in
the Device::reset and we need to revisit your unique use case along
with the addition of your board.

So with the move to device::reset,

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

>  /* FIXME use a qdev drive property instead of drive_get_next() */
>  dinfo = drive_get_next(IF_MTD);
>
> @@ -654,7 +686,7 @@ static void m25p80_pre_save(void *opaque)
>
>  static const VMStateDescription vmstate_m25p80 = {
>  .name = "xilinx_spi",
> -.version_id = 1,
> +.version_id = 2,
>  .minimum_version_id = 1,
>  .pre_save = m25p80_pre_save,
>  .fields = (VMStateField[]) {
> @@ -666,6 +698,7 @@ static const VMStateDescription vmstate_m25p80 = {
>  VMSTATE_UINT8(cmd_in_progress, Flash),
>  VMSTATE_UINT64(cur_addr, Flash),
>  VMSTATE_BOOL(write_enable, Flash),
> +VMSTATE_BOOL(reset_enable, Flash),
>  VMSTATE_END_OF_LIST()
>  }
>  };
> --
> 2.5.0
>



Re: [Qemu-devel] [PATCH v4 11/11] block: m25p80: at25128a/at25256a models

2016-03-19 Thread Peter Crosthwaite
On Mon, Feb 22, 2016 at 12:03 AM,  <marcin.krzemin...@nokia.com> wrote:
> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>
> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
> ---
>  hw/block/m25p80.c | 11 +++
>  1 file changed, 11 insertions(+)
>
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 2b7d19f..987fe07 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -99,6 +99,12 @@ static const FlashPartInfo known_devices[] = {
>
>  { INFO("at45db081d",  0x1f2500,  0,  64 << 10,  16, ER_4K) },
>
> +/* Atmel EEPROMS - it is assumed, that don't care bit in command
> + * is set to 0. Block protection is not supported.
> + */
> +{ INFO("at25128a-nonjedec", 0x0, 0, 1, 131072, WR_1) },
> +{ INFO("at25256a-nonjedec", 0x0, 0, 1, 262144, WR_1) },
> +
>  /* EON -- en25xxx */
>  { INFO("en25f32", 0x1c3116,  0,  64 << 10,  64, ER_4K) },
>  { INFO("en25p32", 0x1c2016,  0,  64 << 10,  64, 0) },
> @@ -438,6 +444,11 @@ void flash_write8(Flash *s, uint64_t addr, uint8_t data)
>
>  static inline int get_addr_length(Flash *s)
>  {
> +   /* check if eeprom is in use */
> +if (s->pi->flags == WR_1) {
> +    return 2;
> +}
> +

Neat!

But I think this indicates the flag is incorrectly named. Should be
renamed to EEPROM or something like.

Otherwise:

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

> switch (s->cmd_in_progress) {
> case PP4:
> case READ4:
> --
> 2.5.0
>



Re: [Qemu-devel] [PATCH v4 07/11] block: m25p80: Dummy cycles for N25Q256/512

2016-03-19 Thread Peter Crosthwaite
On Mon, Feb 22, 2016 at 12:03 AM,  <marcin.krzemin...@nokia.com> wrote:
> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>
> This patch handles dummy cycles.
>

More commit message needed:

"Use the setting in the volatile cfg register to correctly set the
number of dummy bytes"

> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
> ---
>  hw/block/m25p80.c | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 9d5a071..aff28f3 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -566,6 +566,10 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  case DOR:
>  case QOR:
>  s->needed_bytes = get_addr_length(s);
> +if (((s->pi->jedec >> 16) & 0xFF) == JEDEC_NUMONYX) {
> +/* Dummy cycles modeled with bytes writes instead of bits */
> +s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
> +}
>  s->pos = 0;
>  s->len = 0;
>  s->state = STATE_COLLECTING_DATA;
> @@ -579,6 +583,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  break;
>  case JEDEC_NUMONYX:
>  s->needed_bytes = get_addr_length(s);
> +/* Dummy cycles modeled with bytes writes instead of bits */
> +s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
>  break;
>  default:
>  s->needed_bytes = 5;

Following on from before, these defaults are NUMONYX policy based, so
I think your patch is to the default.

Otherwise: Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Regards,
Peter

> @@ -596,6 +602,8 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>  break;
>  case JEDEC_NUMONYX:
>  s->needed_bytes = get_addr_length(s);
> +/* Dummy cycles modeled with bytes writes instead of bits */
> +s->needed_bytes += extract32(s->volatile_cfg, 4, 4);
>  break;
>  default:
>  s->needed_bytes = 8;
> --
> 2.5.0
>



Re: [Qemu-devel] [PATCH v12 8/9] hw/ptimer: Perform delayed tick instead of immediate if delta = 0

2016-03-08 Thread Peter Crosthwaite
On Sat, Jan 30, 2016 at 8:43 AM, Dmitry Osipenko  wrote:
> It might be necessary by some emulated HW to perform the tick after one
> period if delta = 0. Given that it is much less churny to implement immediate
> tick by the ptimer user itself, let's make ptimer do the delayed tick.
>

Isn't this related to previous patch? It is kind of a rounding problem
that will vary from timer to timer. Some timers may interpret the
"tick" as the wrap-around back to the load value (even if that is 0)
while others interpret the tick as the transition to zero (makes more
sense for a one-shot). It's hard to set a universal policy here.

But is this a non-issue when we consider that event latency (usually
interrupt latency) is undefined anyway?

Regards,
Peter

> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/core/ptimer.c | 34 +++---
>  1 file changed, 15 insertions(+), 19 deletions(-)
>
> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
> index b2044fb..bcd090c 100644
> --- a/hw/core/ptimer.c
> +++ b/hw/core/ptimer.c
> @@ -36,19 +36,7 @@ static void ptimer_reload(ptimer_state *s)
>  {
>  uint32_t period_frac = s->period_frac;
>  uint64_t period = s->period;
> -
> -if (s->delta == 0) {
> -ptimer_trigger(s);
> -}
> -
> -if (s->delta == 0 && s->enabled == 1) {
> -s->delta = s->limit;
> -}
> -
> -if (s->delta == 0) {
> -ptimer_stop(s);
> -return;
> -}
> +uint64_t delta = MAX(1, s->delta);
>
>  /*
>   * Artificially limit timeout rate to something
> @@ -59,15 +47,15 @@ static void ptimer_reload(ptimer_state *s)
>   * on the current generation of host machines.
>   */
>
> -if (s->enabled == 1 && (s->delta * period < 1) && !use_icount) {
> -period = 1 / s->delta;
> +if (s->enabled == 1 && (delta * period < 1) && !use_icount) {
> +period = 1 / delta;
>  period_frac = 0;
>  }
>
>  s->last_event = s->next_event;
> -s->next_event = s->last_event + s->delta * period;
> +s->next_event = s->last_event + delta * period;
>  if (period_frac) {
> -s->next_event += ((int64_t)period_frac * s->delta) >> 32;
> +s->next_event += ((int64_t)period_frac * delta) >> 32;
>  }
>  timer_mod(s->timer, s->next_event);
>  }
> @@ -75,8 +63,16 @@ static void ptimer_reload(ptimer_state *s)
>  static void ptimer_tick(void *opaque)
>  {
>  ptimer_state *s = (ptimer_state *)opaque;
> -s->delta = 0;
> -ptimer_reload(s);
> +
> +s->delta = (s->enabled == 1) ? s->limit : 0;
> +
> +if (s->delta == 0) {
> +s->enabled = 0;
> +} else {
> +ptimer_reload(s);
> +}
> +
> +ptimer_trigger(s);
>  }
>
>  uint64_t ptimer_get_count(ptimer_state *s)
> --
> 2.7.0
>



Re: [Qemu-devel] [PATCH v12 9/9] arm_mptimer: Convert to use ptimer

2016-03-08 Thread Peter Crosthwaite
On Sat, Jan 30, 2016 at 8:43 AM, Dmitry Osipenko <dig...@gmail.com> wrote:
> Current ARM MPTimer implementation uses QEMUTimer for the actual timer,
> this implementation isn't complete and mostly tries to duplicate of what
> generic ptimer is already doing fine.
>
> Conversion to ptimer brings the following benefits and fixes:
> - Simple timer pausing implementation
> - Fixes counter value preservation after stopping the timer
> - Correctly handles prescaler != 0 / counter = 0 / load = 0 cases
> - Code simplification and reduction
>
> Bump VMSD to version 3, since VMState is changed and is not compatible
> with the previous implementation.
>
> Signed-off-by: Dmitry Osipenko <dig...@gmail.com>

Im a little rusty on some of the corner cases that have come out of
your test suite, but the general idea is solid, and it adds those
missing features that got the whole discussion started.

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

> ---
>  hw/timer/arm_mptimer.c | 133 
> +
>  include/hw/timer/arm_mptimer.h |   5 +-
>  2 files changed, 70 insertions(+), 68 deletions(-)
>
> diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
> index 5dfab66..f002458 100644
> --- a/hw/timer/arm_mptimer.c
> +++ b/hw/timer/arm_mptimer.c
> @@ -19,8 +19,9 @@
>   * with this program; if not, see <http://www.gnu.org/licenses/>.
>   */
>
> +#include "hw/ptimer.h"
>  #include "hw/timer/arm_mptimer.h"
> -#include "qemu/timer.h"
> +#include "qemu/main-loop.h"
>  #include "qom/cpu.h"
>
>  /* This device implements the per-cpu private timer and watchdog block
> @@ -42,55 +43,54 @@ static inline void timerblock_update_irq(TimerBlock *tb)
>  }
>
>  /* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
> -static inline uint32_t timerblock_scale(TimerBlock *tb)
> +static inline uint32_t timerblock_scale(uint32_t control)
>  {
> -return (((tb->control >> 8) & 0xff) + 1) * 10;
> +return (((control >> 8) & 0xff) + 1) * 10;
>  }
>
> -static void timerblock_reload(TimerBlock *tb, int restart)
> +static inline void timerblock_set_count(struct ptimer_state *timer,
> +uint32_t control, uint64_t *count)
>  {
> -if (tb->count == 0) {
> -return;
> +/* PTimer would immediately trigger interrupt for periodic timer
> + * when counter set to 0, MPtimer under certain condition only.
> + */
> +if ((control & 3) == 3 && (control & 0xff00) == 0 && *count == 0) {
> +*count = ptimer_get_limit(timer);
>  }
> -if (restart) {
> -tb->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +ptimer_set_count(timer, *count);
> +}
> +
> +static inline void timerblock_run(struct ptimer_state *timer,
> +  uint32_t control, uint32_t load)
> +{
> +if ((control & 1) && ((control & 0xff00) || load != 0)) {
> +ptimer_run(timer, !(control & 2));
>  }
> -tb->tick += (int64_t)tb->count * timerblock_scale(tb);
> -timer_mod(tb->timer, tb->tick);
>  }
>
>  static void timerblock_tick(void *opaque)
>  {
>  TimerBlock *tb = (TimerBlock *)opaque;
>  tb->status = 1;
> -if (tb->control & 2) {
> -tb->count = tb->load;
> -timerblock_reload(tb, 0);
> -} else {
> -tb->count = 0;
> -}
>  timerblock_update_irq(tb);
> +/* Periodic timer with load = 0 and prescaler != 0 would re-trigger
> + * IRQ after one period, otherwise it either stops or wraps around.
> + */
> +if ((tb->control & 2) && (tb->control & 0xff00) &&
> +ptimer_get_limit(tb->timer) == 0) {
> +ptimer_run(tb->timer, 0);
> +}
>  }
>
>  static uint64_t timerblock_read(void *opaque, hwaddr addr,
>  unsigned size)
>  {
>  TimerBlock *tb = (TimerBlock *)opaque;
> -int64_t val;
>  switch (addr) {
>  case 0: /* Load */
> -return tb->load;
> +return ptimer_get_limit(tb->timer);
>  case 4: /* Counter.  */
> -if (((tb->control & 1) == 0) || (tb->count == 0)) {
> -return 0;
> -}
> -/* Slow and ugly, but hopefully won't happen too often.  */
> -val = tb->tick - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> -val /= timerblock_scale(tb);
> -if (val < 0) {
> -val = 0;
> -}
> -   

Re: [Qemu-devel] [PATCH v12 7/9] hw/ptimer: Fix counter - 1 returned by ptimer_get_count for the active timer

2016-03-07 Thread Peter Crosthwaite
On Tue, Feb 2, 2016 at 7:19 AM, Dmitry Osipenko  wrote:
> 30.01.2016 19:43, Dmitry Osipenko пишет:
>>
>> Due to rounding down performed by ptimer_get_count, it returns counter - 1
>> for
>> the active timer. That's incorrect because counter should decrement only
>> after
>> period been expired, not before. I.e. if running timer has been loaded
>> with
>> value X, then timer counter should stay with X until period expired and
>> decrement after. Fix this by adding 1 to the counter value for the active
>> and
>> unexpired timer.
>>
>> Signed-off-by: Dmitry Osipenko 
>> ---
>>   hw/core/ptimer.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
>> index 62f8cb1..b2044fb 100644
>> --- a/hw/core/ptimer.c
>> +++ b/hw/core/ptimer.c
>> @@ -136,7 +136,7 @@ uint64_t ptimer_get_count(ptimer_state *s)
>>   if ((uint32_t)(period_frac << shift))
>>   div += 1;
>>   }
>> -counter = rem / div;
>> +counter = rem / div + (expired ? 0 : 1);
>>
>>   if (expired && counter != 0) {
>>   /* Wrap around periodic counter.  */
>>
>
> Noticed one nit here:
>
> There is possibility to return timer counter = limit + 1, if the following
> ptimer calls execute in less than 1ns.
>
> ptimer_run(t, 1);
> // counter = 91, if set() count executed in less than 1ns
> ptimer_set_count(t, 90);
> counter = ptimer_get_count(t);
>
> Likely, it would be impossible to trigger that issue on a real current
> machine.
> But the fix is trivial, I'll incorporate it in V13 if it looks fine:
>
> ---
> @@ -76,20 +76,20 @@ static void ptimer_tick(void *opaque)
>  {
>  ptimer_state *s = (ptimer_state *)opaque;
>  s->delta = 0;
>  ptimer_reload(s);
>  }
>
>  uint64_t ptimer_get_count(ptimer_state *s)
>  {
> +int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>  uint64_t counter;
>
> -if (s->enabled && s->delta != 0) {
> -int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +if (s->enabled && s->delta != 0 && now != s->last_event) {
>  int64_t next = s->next_event;
>  bool expired = (now - next >= 0);
>  bool oneshot = (s->enabled == 2);
>
>  /* Figure out the current counter value.  */
>  if (expired && (oneshot || use_icount)) {
>  /* Prevent timer underflowing if it should already have
> triggered.  */
> @@ -131,17 +131,17 @@ uint64_t ptimer_get_count(ptimer_state *s)
>  } else {
>  if (shift != 0)
>  div |= (period_frac >> (32 - shift));
>  /* Look at remaining bits of period_frac and round div up
> if
> necessary.  */
>  if ((uint32_t)(period_frac << shift))
>  div += 1;
>  }
> -counter = rem / div;
> +counter = rem / div + (expired ? 0 : 1);
>

Sorry about the long delays. Im wondering what this has to do with
expiration though? the commit message suggests you want to change the
rounding scheme, so can that be done directly with DIV_ROUND_UP?

Regards,
Peter

>  if (expired && counter != 0) {
>  /* Wrap around periodic counter.  */
>  counter = s->limit - (counter - 1) % s->limit;
>  }
>  }
>  } else {
>  counter = s->delta;
>
>
> --
> Dmitry



Re: [Qemu-devel] [PATCH 2/9] hw/arm: QOM'ify highbank.c

2016-03-07 Thread Peter Crosthwaite
On Sun, Mar 6, 2016 at 11:05 PM, xiaoqiang zhao <zxq_yx_...@163.com> wrote:
> Drop the use of old SysBus init function and use instance_init
>
> Signed-off-by: xiaoqiang zhao <zxq_yx_...@163.com>

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

(just this one as I have done some highbank work recently - I cant do
the whole series).

Regards,
Peter

> ---
>  hw/arm/highbank.c | 12 +---
>  1 file changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
> index e25cf5e..8f38dff 100644
> --- a/hw/arm/highbank.c
> +++ b/hw/arm/highbank.c
> @@ -167,23 +167,20 @@ static void highbank_regs_reset(DeviceState *dev)
>  s->regs[0x43] = 0x05F40121;
>  }
>
> -static int highbank_regs_init(SysBusDevice *dev)
> +static void highbank_regs_init(Object *obj)
>  {
> -HighbankRegsState *s = HIGHBANK_REGISTERS(dev);
> +HighbankRegsState *s = HIGHBANK_REGISTERS(obj);
> +SysBusDevice *dev = SYS_BUS_DEVICE(obj);
>
> -memory_region_init_io(>iomem, OBJECT(s), _mem_ops, s->regs,
> +memory_region_init_io(>iomem, obj, _mem_ops, s->regs,
>"highbank_regs", 0x1000);
>  sysbus_init_mmio(dev, >iomem);
> -
> -return 0;
>  }
>
>  static void highbank_regs_class_init(ObjectClass *klass, void *data)
>  {
> -SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
>  DeviceClass *dc = DEVICE_CLASS(klass);
>
> -sbc->init = highbank_regs_init;
>  dc->desc = "Calxeda Highbank registers";
>  dc->vmsd = _highbank_regs;
>  dc->reset = highbank_regs_reset;
> @@ -193,6 +190,7 @@ static const TypeInfo highbank_regs_info = {
>  .name  = TYPE_HIGHBANK_REGISTERS,
>  .parent= TYPE_SYS_BUS_DEVICE,
>  .instance_size = sizeof(HighbankRegsState),
> +.instance_init = highbank_regs_init,
>  .class_init= highbank_regs_class_init,
>  };
>
> --
> 2.1.4
>
>
>



[Qemu-devel] [PATCH v2 16/18] loader: load_elf(): Add doc comment

2016-03-01 Thread Peter Crosthwaite
Document the usage of load_elf() for clarity on current features.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 include/hw/loader.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/include/hw/loader.h b/include/hw/loader.h
index a626c9b..264ef89 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -32,6 +32,29 @@ int load_image_gzipped(const char *filename, hwaddr addr, 
uint64_t max_sz);
 #define ELF_LOAD_WRONG_ARCH   -3
 #define ELF_LOAD_WRONG_ENDIAN -4
 const char *load_elf_strerror(int error);
+
+/** load_elf:
+ * @filename: Path of ELF file
+ * @translate_fn: optional function to translate load addresses
+ * @translate_opaque: opaque data passed to @translate_fn
+ * @pentry: Populated with program entry point. Ignored if NULL.
+ * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
+ * @highaddr: Populated with highest loaded address. Ignored if NULL.
+ * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
+ * @elf_machine: Expected ELF machine type
+ * @clear_lsb: Set to mask off LSB of addresses (Some architectures use
+ * this for non-address data)
+ *
+ * Load an ELF file's contents to the emulated system's address space.
+ * Clients may optionally specify a callback to perform address
+ * translations. @pentry, @lowaddr and @highaddr are optional pointers
+ * which will be populated with various load information. @bigendian and
+ * @elf_machine give the expected endianness and machine for the ELF the
+ * load will fail if the target ELF does not match. Some architectures
+ * have some architecture-specific behaviours that come into effect when
+ * their particular values for @elf_machine are set.
+ */
+
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
  uint64_t *highaddr, int big_endian, int elf_machine,
-- 
1.9.1




[Qemu-devel] [PATCH v2 17/18] loader: Add data swap option to load-elf

2016-03-01 Thread Peter Crosthwaite
Some CPUs are of an opposite data-endianness to other components in the
system. Sometimes elfs have the data sections layed out with this CPU
data-endianness accounting for when loaded via the CPU, so byte swaps
(relative to other system components) will occur.

The leading example, is ARM's BE32 mode, which is is basically LE with
address manipulation on half-word and byte accesses to access the
hw/byte reversed address. This means that word data is invariant
across LE and BE32. This also means that instructions are still LE.
The expectation is that the elf will be loaded via the CPU in this
endianness scheme, which means the data in the elf is reversed at
compile time.

As QEMU loads via the system memory directly, rather than the CPU, we
need a mechanism to reverse elf data endianness to implement this
possibility.

Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
changed since v1:
Added doc comment (PMM review)
Commit message typos

 hw/alpha/dp264.c   |  4 ++--
 hw/arm/armv7m.c|  2 +-
 hw/arm/boot.c  |  2 +-
 hw/core/loader.c   |  9 ++---
 hw/cris/boot.c |  2 +-
 hw/i386/multiboot.c|  3 ++-
 hw/lm32/lm32_boards.c  |  4 ++--
 hw/lm32/milkymist.c|  2 +-
 hw/m68k/an5206.c   |  2 +-
 hw/m68k/dummy_m68k.c   |  2 +-
 hw/m68k/mcf5208.c  |  2 +-
 hw/microblaze/boot.c   |  4 ++--
 hw/mips/mips_fulong2e.c|  2 +-
 hw/mips/mips_malta.c   |  2 +-
 hw/mips/mips_mipssim.c |  2 +-
 hw/mips/mips_r4k.c |  2 +-
 hw/moxie/moxiesim.c|  3 ++-
 hw/openrisc/openrisc_sim.c |  3 ++-
 hw/pci-host/prep.c |  2 +-
 hw/ppc/e500.c  |  2 +-
 hw/ppc/mac_newworld.c  |  5 +++--
 hw/ppc/mac_oldworld.c  |  5 +++--
 hw/ppc/ppc440_bamboo.c |  3 ++-
 hw/ppc/spapr.c |  6 --
 hw/ppc/virtex_ml507.c  |  3 ++-
 hw/s390x/ipl.c |  4 ++--
 hw/sparc/leon3.c   |  2 +-
 hw/sparc/sun4m.c   |  4 ++--
 hw/sparc64/sun4u.c |  4 ++--
 hw/tricore/tricore_testboard.c |  2 +-
 hw/xtensa/sim.c|  4 ++--
 hw/xtensa/xtfpga.c |  2 +-
 include/hw/elf_ops.h   | 22 +-
 include/hw/loader.h|  5 -
 34 files changed, 81 insertions(+), 46 deletions(-)

diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 992d1b2..7c5989b 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -111,7 +111,7 @@ static void clipper_init(MachineState *machine)
 }
 size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
 NULL, _entry, _low, _high,
-0, EM_ALPHA, 0);
+0, EM_ALPHA, 0, 0);
 if (size < 0) {
 error_report("could not load palcode '%s'", palcode_filename);
 exit(1);
@@ -131,7 +131,7 @@ static void clipper_init(MachineState *machine)
 
 size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
 NULL, _entry, _low, _high,
-0, EM_ALPHA, 0);
+0, EM_ALPHA, 0, 0);
 if (size < 0) {
 error_report("could not load kernel '%s'", kernel_filename);
 exit(1);
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index f3973f7..ed7d97f 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -211,7 +211,7 @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int 
mem_size, int num_irq,
 
 if (kernel_filename) {
 image_size = load_elf(kernel_filename, NULL, NULL, , ,
-  NULL, big_endian, EM_ARM, 1);
+  NULL, big_endian, EM_ARM, 1, 0);
 if (image_size < 0) {
 image_size = load_image_targphys(kernel_filename, 0, mem_size);
 lowaddr = 0;
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 0a56d34c..17400be 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -755,7 +755,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void 
*data)
 /* Assume that raw images are linux kernels, and ELF images are not.  */
 kernel_size = load_elf(info->kernel_filename, NULL, NULL, _entry,
_low_addr, _high_addr, big_endian,
-   elf_machine, 1);
+   elf_machine, 1, 0);
 if (kernel_size > 0 && have_dtb(info)) {
 /* If there is still some room left at the base of RAM, try and put
  * the DTB there like we do for images loaded with -bios or -pflash.
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 7d5e3a9..79877ec 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -390,7 +390,8 @@ fail:
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const

[Qemu-devel] [PATCH v2 18/18] arm: boot: Support big-endian elfs

2016-03-01 Thread Peter Crosthwaite
Support ARM big-endian ELF files in system-mode emulation. When loading
an elf, determine the endianness mode expected by the elf, and set the
relevant CPU state accordingly.

With this, big-endian modes are now fully supported via system-mode LE,
so there is no need to restrict the elf loading to the TARGET
endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
Changed since v1:
Factor out elf manipulation logic into static helper (PMM review)

 hw/arm/boot.c| 93 ++--
 include/hw/arm/arm.h |  9 +
 2 files changed, 92 insertions(+), 10 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 17400be..13aad42 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -518,9 +518,34 @@ static void do_cpu_reset(void *opaque)
 cpu_reset(cs);
 if (info) {
 if (!info->is_linux) {
+int i;
 /* Jump to the entry point.  */
 uint64_t entry = info->entry;
 
+switch (info->endianness) {
+case ARM_ENDIANNESS_LE:
+env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
+for (i = 1; i < 4; ++i) {
+env->cp15.sctlr_el[i] &= ~SCTLR_EE;
+}
+env->uncached_cpsr &= ~CPSR_E;
+break;
+case ARM_ENDIANNESS_BE8:
+env->cp15.sctlr_el[1] |= SCTLR_E0E;
+for (i = 1; i < 4; ++i) {
+env->cp15.sctlr_el[i] |= SCTLR_EE;
+}
+env->uncached_cpsr |= CPSR_E;
+break;
+case ARM_ENDIANNESS_BE32:
+env->cp15.sctlr_el[1] |= SCTLR_B;
+break;
+case ARM_ENDIANNESS_UNKNOWN:
+break; /* Board's decision */
+default:
+g_assert_not_reached();
+}
+
 if (!env->aarch64) {
 env->thumb = info->entry & 1;
 entry &= 0xfffe;
@@ -638,6 +663,62 @@ static int do_arm_linux_init(Object *obj, void *opaque)
 return 0;
 }
 
+static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
+ uint64_t *lowaddr, uint64_t *highaddr,
+ int elf_machine)
+{
+bool elf_is64;
+union {
+Elf32_Ehdr h32;
+Elf64_Ehdr h64;
+} elf_header;
+int data_swab = 0;
+bool big_endian;
+uint64_t ret = -1;
+Error *err = NULL;
+
+
+load_elf_hdr(info->kernel_filename, _header, _is64, );
+if (err) {
+return ret;
+}
+
+if (elf_is64) {
+big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
+info->endianness = big_endian ? ARM_ENDIANNESS_BE8
+  : ARM_ENDIANNESS_LE;
+} else {
+big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
+if (big_endian) {
+if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
+info->endianness = ARM_ENDIANNESS_BE8;
+} else {
+info->endianness = ARM_ENDIANNESS_BE32;
+/* In BE32, the CPU has a different view of the per-byte
+ * address map than the rest of the system. BE32 elfs are
+ * organised such that they can be programmed through the
+ * CPUs per-word byte-reversed view of the world. QEMU
+ * however loads elfs independently of the CPU. So tell
+ * the elf loader to byte reverse the data for us.
+ */
+data_swab = 2;
+}
+} else {
+info->endianness = ARM_ENDIANNESS_LE;
+}
+}
+
+ret = load_elf(info->kernel_filename, NULL, NULL,
+   pentry, lowaddr, highaddr, big_endian, elf_machine,
+   1, data_swab);
+if (ret <= 0) {
+/* The header loaded but the image didn't */
+exit(1);
+}
+
+return ret;
+}
+
 static void arm_load_kernel_notify(Notifier *notifier, void *data)
 {
 CPUState *cs;
@@ -647,7 +728,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void 
*data)
 uint64_t elf_entry, elf_low_addr, elf_high_addr;
 int elf_machine;
 hwaddr entry, kernel_load_offset;
-int big_endian;
 static const ARMInsnFixup *primary_loader;
 ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
  notifier, notifier);
@@ -733,12 +813,6 @@ static void arm_load_kernel_notify(Notifier *notifier, 
void *data)
 if (info->nb_cpus == 0)
 info->nb_cpus = 1;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-big_endian = 1;
-#else
-big_endian = 0;
-#endif
-
 /* We want to put the initrd far enough into RAM that when the
  * kernel is uncompressed it will not clobb

[Qemu-devel] [PATCH v2 15/18] loader: add API to load elf header

2016-03-01 Thread Peter Crosthwaite
Add an API to load an elf header header from a file. Populates a
buffer with the header contents, as well as a boolean for whether the
elf is 64b or not. Both arguments are optional.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
Changed since v1 (PMM review):
Add filname to error messages
Remove unneeded lseek()
Add doc comment

 hw/core/loader.c| 55 +
 include/hw/loader.h | 13 +
 2 files changed, 68 insertions(+)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index 3a57415..7d5e3a9 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -332,6 +332,61 @@ const char *load_elf_strerror(int error)
 }
 }
 
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
+{
+int fd;
+uint8_t e_ident_local[EI_NIDENT];
+uint8_t *e_ident;
+size_t hdr_size, off;
+bool is64l;
+
+if (!hdr) {
+hdr = e_ident_local;
+}
+e_ident = hdr;
+
+fd = open(filename, O_RDONLY | O_BINARY);
+if (fd < 0) {
+error_setg_errno(errp, errno, "Failed to open file: %s", filename);
+return;
+}
+if (read(fd, hdr, EI_NIDENT) != EI_NIDENT) {
+error_setg_errno(errp, errno, "Failed to read file: %s", filename);
+goto fail;
+}
+if (e_ident[0] != ELFMAG0 ||
+e_ident[1] != ELFMAG1 ||
+e_ident[2] != ELFMAG2 ||
+e_ident[3] != ELFMAG3) {
+error_setg(errp, "Bad ELF magic");
+goto fail;
+}
+
+is64l = e_ident[EI_CLASS] == ELFCLASS64;
+hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
+if (is64) {
+*is64 = is64l;
+}
+
+off = EI_NIDENT;
+while (hdr != e_ident_local && off < hdr_size) {
+size_t br = read(fd, hdr + off, hdr_size - off);
+switch (br) {
+case 0:
+error_setg(errp, "File too short: %s", filename);
+goto fail;
+case -1:
+error_setg_errno(errp, errno, "Failed to read file: %s",
+ filename);
+goto fail;
+}
+off += br;
+}
+
+fail:
+close(fd);
+}
+
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
diff --git a/include/hw/loader.h b/include/hw/loader.h
index f7b43ab..a626c9b 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -36,6 +36,19 @@ int load_elf(const char *filename, uint64_t 
(*translate_fn)(void *, uint64_t),
  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
  uint64_t *highaddr, int big_endian, int elf_machine,
  int clear_lsb);
+
+/** load_elf_hdr:
+ * @filename: Path of ELF file
+ * @hdr: Buffer to populate with header data. Header data will not be
+ * filled if set to NULL.
+ * @is64: Set to true if the ELF is 64bit. Ignored if set to NULL
+ * @errp: Populated with an error in failure cases
+ *
+ * Inspect as ELF file's header. Read its full header contents into a
+ * buffer and/or determine if the ELF is 64bit.
+ */
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
+
 int load_aout(const char *filename, hwaddr addr, int max_sz,
   int bswap_needed, hwaddr target_page_size);
 int load_uimage(const char *filename, hwaddr *ep,
-- 
1.9.1




[Qemu-devel] [PATCH v2 10/18] target-arm: introduce disas flag for endianness

2016-03-01 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Introduce a disas flag for setting the CPU data endianness. This allows
control of the endianness from the CPU state rather than hard-coding it
to TARGET_WORDS_BIGENDIAN.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[ PC changes:
  * Split off as new patch from original:
"target-arm: introduce tbflag for CPSR.E"
  * Wrote commit message from scratch
]
Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---
Changed since v1:
rename mo_endianness to be_data

 target-arm/translate-a64.c |  1 +
 target-arm/translate.c | 39 ---
 target-arm/translate.h |  1 +
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index f6dd44b..88b95ab 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11032,6 +11032,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, 
TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
 dc->thumb = 0;
 dc->sctlr_b = 0;
+dc->be_data = MO_TE;
 dc->condexec_mask = 0;
 dc->condexec_cond = 0;
 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2028908..88f24cb 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -924,26 +924,30 @@ static inline void store_reg_from_load(DisasContext *s, 
int reg, TCGv_i32 var)
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
-tcg_gen_qemu_ld_i32(val, addr, index, (OPC));\
+TCGMemOp opc = (OPC) | s->be_data;   \
+tcg_gen_qemu_ld_i32(val, addr, index, opc);  \
 }
 
 #define DO_GEN_ST(SUFF, OPC) \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
-tcg_gen_qemu_st_i32(val, addr, index, (OPC));\
+TCGMemOp opc = (OPC) | s->be_data;   \
+tcg_gen_qemu_st_i32(val, addr, index, opc);  \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
  TCGv_i32 addr, int index)
 {
-tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
+TCGMemOp opc = MO_Q | s->be_data;
+tcg_gen_qemu_ld_i64(val, addr, index, opc);
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
  TCGv_i32 addr, int index)
 {
-tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
+TCGMemOp opc = MO_Q | s->be_data;
+tcg_gen_qemu_st_i64(val, addr, index, opc);
 }
 
 #else
@@ -952,9 +956,10 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 
val,
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
+TCGMemOp opc = (OPC) | s->be_data;   \
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
-tcg_gen_qemu_ld_i32(val, addr64, index, OPC);\
+tcg_gen_qemu_ld_i32(val, addr64, index, opc);\
 tcg_temp_free(addr64);   \
 }
 
@@ -962,27 +967,30 @@ static inline void gen_aa32_ld##SUFF(DisasContext *s, 
TCGv_i32 val,  \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
+TCGMemOp opc = (OPC) | s->be_data;   \
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
-tcg_gen_qemu_st_i32(val, addr64, index, OPC);\
+tcg_gen_qemu_st_i32(val, addr64, index, opc);\
 tcg_temp_free(addr64);   \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
  TCGv_i32 addr, int index)
 {
+TCGMemOp opc = MO_Q | s->be_data;
 TCGv addr64 = tcg_temp_new();
 tcg_gen_extu_i32_i64(addr64, addr);
-tcg_gen_qemu_ld_i64(val, addr64, index, MO

[Qemu-devel] [PATCH v2 05/18] arm: cpu: handle BE32 user-mode as BE

2016-03-01 Thread Peter Crosthwaite
>From a system emulation point of view, BE32 is best modelled as little
endian with address manipulations on subword accesses (to give the
illusion of BE). But user-mode cannot tell the difference and is
already implemented as straight BE. So handle the difference in the
endianess query, where USER mode is BE and system is not.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
Changed since v1:
Rewrote commit subject and message formerly:
arm: linux-user: don't set CPSR.E in BE32 mode

 target-arm/cpu.h | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 75e5ea0..ab0ea92 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1915,7 +1915,22 @@ static inline bool 
arm_cpu_data_is_big_endian(CPUARMState *env)
 
 /* In 32bit endianness is determined by looking at CPSR's E bit */
 if (!is_a64(env)) {
-return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
+return
+#ifdef CONFIG_USER_ONLY
+/* In system mode, BE32 is modelled in line with the
+ * architecture (as word-invariant big-endianness), where loads
+ * and stores are done little endian but from addresses which
+ * are adjusted by XORing with the appropriate constant. So the
+ * endianness to use for the raw data access is not affected by
+ * SCTLR.B.
+ * In user mode, however, we model BE32 as byte-invariant
+ * big-endianness (because user-only code cannot tell the
+ * difference), and so we need to use a data access endianness
+ * that depends on SCTLR.B.
+ */
+arm_sctlr_b(env) ||
+#endif
+((env->uncached_cpsr & CPSR_E) ? 1 : 0);
 }
 
 cur_el = arm_current_el(env);
-- 
1.9.1




[Qemu-devel] [PATCH v2 03/18] target-arm: implement SCTLR.B, drop bswap_code

2016-03-01 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

bswap_code is a CPU property of sorts ("is the iside endianness the
opposite way round to TARGET_WORDS_BIGENDIAN?") but it is not the
actual CPU state involved here which is SCTLR.B (set for BE32
binaries, clear for BE8).

Replace bswap_code with SCTLR.B, and pass that to arm_ld*_code.
The next patches will make data fetches honor both SCTLR.B and
CPSR.E appropriately.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[PC changes:
 * rebased on master (Jan 2016)
 * s/TARGET_USER_ONLY/CONFIG_USER_ONLY
 * Use bswap_code() for disas_set_info() instead of raw sctlr_b
]
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
Changed since v1:
Re-added BE32 support

 linux-user/main.c  | 10 +++---
 target-arm/arm_ldst.h  |  8 
 target-arm/cpu.c   |  2 +-
 target-arm/cpu.h   | 47 ++
 target-arm/helper.c|  8 
 target-arm/translate-a64.c |  6 +++---
 target-arm/translate.c | 16 
 target-arm/translate.h |  2 +-
 8 files changed, 67 insertions(+), 32 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index bcb9f66..fe2a8dd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -437,7 +437,7 @@ void cpu_loop(CPUX86State *env)
 
 #define get_user_code_u32(x, gaddr, env)\
 ({ abi_long __r = get_user_u32((x), (gaddr));   \
-if (!__r && (env)->bswap_code) {\
+if (!__r && bswap_code(arm_sctlr_b(env))) { \
 (x) = bswap32(x);   \
 }   \
 __r;\
@@ -445,7 +445,7 @@ void cpu_loop(CPUX86State *env)
 
 #define get_user_code_u16(x, gaddr, env)\
 ({ abi_long __r = get_user_u16((x), (gaddr));   \
-if (!__r && (env)->bswap_code) {\
+if (!__r && bswap_code(arm_sctlr_b(env))) { \
 (x) = bswap16(x);   \
 }   \
 __r;\
@@ -4449,11 +4449,15 @@ int main(int argc, char **argv, char **envp)
 for(i = 0; i < 16; i++) {
 env->regs[i] = regs->uregs[i];
 }
+#ifdef TARGET_WORDS_BIGENDIAN
 /* Enable BE8.  */
 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
 && (info->elf_flags & EF_ARM_BE8)) {
-env->bswap_code = 1;
+/* nothing for now, CPSR.E not emulated yet */
+} else {
+env->cp15.sctlr_el[1] |= SCTLR_B;
 }
+#endif
 }
 #elif defined(TARGET_UNICORE32)
 {
diff --git a/target-arm/arm_ldst.h b/target-arm/arm_ldst.h
index b1ece01..35c2c43 100644
--- a/target-arm/arm_ldst.h
+++ b/target-arm/arm_ldst.h
@@ -25,10 +25,10 @@
 
 /* Load an instruction and return it in the standard little-endian order */
 static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
-bool do_swap)
+bool sctlr_b)
 {
 uint32_t insn = cpu_ldl_code(env, addr);
-if (do_swap) {
+if (bswap_code(sctlr_b)) {
 return bswap32(insn);
 }
 return insn;
@@ -36,10 +36,10 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, 
target_ulong addr,
 
 /* Ditto, for a halfword (Thumb) instruction */
 static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
- bool do_swap)
+ bool sctlr_b)
 {
 uint16_t insn = cpu_lduw_code(env, addr);
-if (do_swap) {
+if (bswap_code(sctlr_b)) {
 return bswap16(insn);
 }
 return insn;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index e95b030..001fccf 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -427,7 +427,7 @@ static void arm_disas_set_info(CPUState *cpu, 
disassemble_info *info)
 } else {
 info->print_insn = print_insn_arm;
 }
-if (env->bswap_code) {
+if (bswap_code(arm_sctlr_b(env))) {
 #ifdef TARGET_WORDS_BIGENDIAN
 info->endian = BFD_ENDIAN_LITTLE;
 #else
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 744f052..61b8b03 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -478,9 +478,6 @@ typedef struct CPUARMState {
 uint32_t cregs[16];
 } iwmmxt;
 
-/* For mixed endian mode.  */
-bool bswap_code;
-
 #if defined(CONFIG_USER_ONLY)
 /* For usermode syscall translation.  */
 int eabi;
@@ -1898,6 +1895,19 @@ static inline bool arm_singlestep_active(CPUARMSta

[Qemu-devel] [PATCH v2 13/18] target-arm: implement setend

2016-03-01 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Since this is not a high-performance path, just use a helper to
flip the E bit and force a lookup in the hash table since the
flags have changed.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 target-arm/helper.h|  1 +
 target-arm/op_helper.c |  5 +
 target-arm/translate.c | 14 ++
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/target-arm/helper.h b/target-arm/helper.h
index ea13202..e3d09d9 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, void, env, i32)
 DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
+DEF_HELPER_1(setend, void, env)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 DEF_HELPER_1(yield, void, env)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 4881e34..92fde0a 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -296,6 +296,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, 
uint32_t shift)
 return res;
 }
 
+void HELPER(setend)(CPUARMState *env)
+{
+env->uncached_cpsr ^= CPSR_E;
+}
+
 /* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
  * The function returns the target EL (1-3) if the instruction is to be 
trapped;
  * otherwise it returns 0 indicating it is not trapped.
diff --git a/target-arm/translate.c b/target-arm/translate.c
index fe0be00..d0f13e2 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7786,10 +7786,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 if ((insn & 0x0dff) == 0x0101) {
 ARCH(6);
 /* setend */
-if (((insn >> 9) & 1) != bswap_code(s->sctlr_b)) {
-/* Dynamic endianness switching not implemented. */
-qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-goto illegal_op;
+if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
+gen_helper_setend(cpu_env);
+s->is_jmp = DISAS_UPDATE;
 }
 return;
 } else if ((insn & 0x0f00) == 0x057ff000) {
@@ -11121,10 +11120,9 @@ static void disas_thumb_insn(CPUARMState *env, 
DisasContext *s)
 case 2:
 /* setend */
 ARCH(6);
-if (((insn >> 3) & 1) != bswap_code(s->sctlr_b)) {
-/* Dynamic endianness switching not implemented. */
-qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-goto illegal_op;
+if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
+gen_helper_setend(cpu_env);
+s->is_jmp = DISAS_UPDATE;
 }
 break;
 case 3:
-- 
1.9.1




[Qemu-devel] [PATCH v2 12/18] target-arm: introduce tbflag for endianness

2016-03-01 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

Introduce a tbflags for endianness, set based upon the CPUs current
endianness. This in turn propagates through to the disas endianness
flag.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---
changed since v1:
s/MOE/BE_DATA (PMM review)

 target-arm/cpu.h   | 7 +++
 target-arm/translate-a64.c | 2 +-
 target-arm/translate.c | 2 +-
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cbf171c..279c91f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1985,6 +1985,8 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState 
*env)
  */
 #define ARM_TBFLAG_NS_SHIFT 19
 #define ARM_TBFLAG_NS_MASK  (1 << ARM_TBFLAG_NS_SHIFT)
+#define ARM_TBFLAG_BE_DATA_SHIFT20
+#define ARM_TBFLAG_BE_DATA_MASK (1 << ARM_TBFLAG_BE_DATA_SHIFT)
 
 /* Bit usage when in AArch64 state: currently we have no A64 specific bits */
 
@@ -2015,6 +2017,8 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState 
*env)
 (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 #define ARM_TBFLAG_NS(F) \
 (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
+#define ARM_TBFLAG_BE_DATA(F) \
+(((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
 
 static inline bool bswap_code(bool sctlr_b)
 {
@@ -2157,6 +2161,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, 
target_ulong *pc,
 }
 }
 }
+if (arm_cpu_data_is_big_endian(env)) {
+*flags |= ARM_TBFLAG_BE_DATA_MASK;
+}
 *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
 
 *cs_base = 0;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 539e6d9..f0c73df 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11043,7 +11043,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, 
TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
 dc->thumb = 0;
 dc->sctlr_b = 0;
-dc->be_data = MO_TE;
+dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
 dc->condexec_mask = 0;
 dc->condexec_cond = 0;
 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 88f24cb..fe0be00 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11330,7 +11330,7 @@ void gen_intermediate_code(CPUARMState *env, 
TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
 dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
-dc->be_data = MO_TE;
+dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
-- 
1.9.1




[Qemu-devel] [PATCH v2 09/18] target-arm: pass DisasContext to gen_aa32_ld*/st*

2016-03-01 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

We'll need the DisasContext in the next patch to retrieve the
desired endianness, so pass it as a whole to gen_aa32_ld*/st*.

Unfortunately we cannot let those functions call get_mem_index,
because of user-mode load/store instructions.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[ PC changes:
 * Fix long lines
]
Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 target-arm/translate.c | 270 ++---
 1 file changed, 142 insertions(+), 128 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index ee04085..2028908 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -921,23 +921,27 @@ static inline void store_reg_from_load(DisasContext *s, 
int reg, TCGv_i32 var)
 #if TARGET_LONG_BITS == 32
 
 #define DO_GEN_LD(SUFF, OPC) \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 tcg_gen_qemu_ld_i32(val, addr, index, (OPC));\
 }
 
 #define DO_GEN_ST(SUFF, OPC) \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 tcg_gen_qemu_st_i32(val, addr, index, (OPC));\
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
 }
@@ -945,7 +949,8 @@ static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 
addr, int index)
 #else
 
 #define DO_GEN_LD(SUFF, OPC) \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
@@ -954,7 +959,8 @@ static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 
addr, int index) \
 }
 
 #define DO_GEN_ST(SUFF, OPC) \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
@@ -962,7 +968,8 @@ static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 
addr, int index) \
 tcg_temp_free(addr64);   \
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 TCGv addr64 = tcg_temp_new();
 tcg_gen_extu_i32_i64(addr64, addr);
@@ -970,7 +977,8 @@ static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 
addr, int index)
 tcg_temp_free(addr64);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 TCGv addr64 = tcg_temp_new();
 tcg_gen_extu_i32_i64(addr64, addr);
@@ -1285,18 +1293,18 @@ VFP_GEN_FIX(ulto, )
 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
 {
 if (dp) {
-gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
+gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
 } else {
-gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
+gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
 }
 }
 
 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
 {
 if (dp) 

[Qemu-devel] [PATCH v2 08/18] target-arm: implement SCTLR.EE

2016-03-01 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

Implement SCTLR.EE bit which controls data endianess for exceptions
and page table translations. SCTLR.EE is mirrored to the CPSR.E bit
on exception entry.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 target-arm/helper.c | 23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 32e66c8..c79c7b9 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -6234,6 +6234,11 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
 env->condexec_bits = 0;
 /* Switch to the new mode, and to the correct instruction set.  */
 env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
+/* Set new mode endianness */
+env->uncached_cpsr &= ~CPSR_E;
+if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
+env->uncached_cpsr |= ~CPSR_E;
+}
 env->daif |= mask;
 /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
  * and we should just guard the thumb mode on V4 */
@@ -6520,6 +6525,12 @@ static inline bool 
regime_translation_disabled(CPUARMState *env,
 return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 }
 
+static inline bool regime_translation_big_endian(CPUARMState *env,
+ ARMMMUIdx mmu_idx)
+{
+return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
+}
+
 /* Return the TCR controlling this translation regime */
 static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
@@ -6842,7 +6853,11 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, 
bool is_secure,
 if (fi->s1ptw) {
 return 0;
 }
-return address_space_ldl(as, addr, attrs, NULL);
+if (regime_translation_big_endian(env, mmu_idx)) {
+return address_space_ldl_be(as, addr, attrs, NULL);
+} else {
+return address_space_ldl_le(as, addr, attrs, NULL);
+}
 }
 
 static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
@@ -6860,7 +6875,11 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, 
bool is_secure,
 if (fi->s1ptw) {
 return 0;
 }
-return address_space_ldq(as, addr, attrs, NULL);
+if (regime_translation_big_endian(env, mmu_idx)) {
+return address_space_ldq_be(as, addr, attrs, NULL);
+} else {
+return address_space_ldq_le(as, addr, attrs, NULL);
+}
 }
 
 static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
-- 
1.9.1




[Qemu-devel] [PATCH v2 04/18] target-arm: cpu: Move cpu_is_big_endian to header

2016-03-01 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

There is a CPU data endianness test that is used to drive the
virtio_big_endian test.

Move this up to the header so it can be more generally used for endian
tests. The KVM specific cpu_syncronize_state call is left behind in the
virtio specific function.

Rename it arm_cpu-data_is_big_endian() to more accurately capture that
this is for data accesses only.

Reviewed-by: Alistair Francis <alistair.fran...@xilinx.com>
Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
Changed since v1:
rename to arm_cpu_data_is_big_endian (PMM review)
inline function to suppress compile warning.

 target-arm/cpu.c | 19 +++
 target-arm/cpu.h | 19 +++
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 001fccf..352d9f8 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -369,26 +369,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, 
int level)
 #endif
 }
 
-static bool arm_cpu_is_big_endian(CPUState *cs)
+static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
 {
 ARMCPU *cpu = ARM_CPU(cs);
 CPUARMState *env = >env;
-int cur_el;
 
 cpu_synchronize_state(cs);
-
-/* In 32bit guest endianness is determined by looking at CPSR's E bit */
-if (!is_a64(env)) {
-return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
-}
-
-cur_el = arm_current_el(env);
-
-if (cur_el == 0) {
-return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
-}
-
-return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+return arm_cpu_data_is_big_endian(env);
 }
 
 #endif
@@ -1476,7 +1463,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
 cc->asidx_from_attrs = arm_asidx_from_attrs;
 cc->vmsd = _arm_cpu;
-cc->virtio_is_big_endian = arm_cpu_is_big_endian;
+cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
 cc->write_elf64_note = arm_cpu_write_elf64_note;
 cc->write_elf32_note = arm_cpu_write_elf32_note;
 #endif
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 61b8b03..75e5ea0 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1908,6 +1908,25 @@ static inline bool arm_sctlr_b(CPUARMState *env)
 (env->cp15.sctlr_el[1] & SCTLR_B) != 0;
 }
 
+/* Return true if the processor is in big-endian mode. */
+static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
+{
+int cur_el;
+
+/* In 32bit endianness is determined by looking at CPSR's E bit */
+if (!is_a64(env)) {
+return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
+}
+
+cur_el = arm_current_el(env);
+
+if (cur_el == 0) {
+return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
+}
+
+return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+}
+
 #include "exec/cpu-all.h"
 
 /* Bit usage in the TB flags field: bit 31 indicates whether we are
-- 
1.9.1




[Qemu-devel] [PATCH v2 11/18] target-arm: a64: Add endianness support

2016-03-01 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

Set the dc->mo_endianness flag for AA64 and use it in all ldst ops.

Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 target-arm/translate-a64.c | 49 --
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 88b95ab..539e6d9 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -723,7 +723,7 @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 
source,
  TCGv_i64 tcg_addr, int size, int memidx)
 {
 g_assert(size <= 3);
-tcg_gen_qemu_st_i64(source, tcg_addr, memidx, MO_TE + size);
+tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->be_data + size);
 }
 
 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
@@ -738,7 +738,7 @@ static void do_gpr_st(DisasContext *s, TCGv_i64 source,
 static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
  int size, bool is_signed, bool extend, int memidx)
 {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->be_data + size;
 
 g_assert(size <= 3);
 
@@ -770,13 +770,18 @@ static void do_fp_st(DisasContext *s, int srcidx, 
TCGv_i64 tcg_addr, int size)
 TCGv_i64 tmp = tcg_temp_new_i64();
 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
 if (size < 4) {
-tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
+tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
+s->be_data + size);
 } else {
+bool be = s->be_data == MO_BE;
 TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
-tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
+
+tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
+tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
+s->be_data | MO_Q);
 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
-tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
+s->be_data | MO_Q);
 tcg_temp_free_i64(tcg_hiaddr);
 }
 
@@ -793,17 +798,21 @@ static void do_fp_ld(DisasContext *s, int destidx, 
TCGv_i64 tcg_addr, int size)
 TCGv_i64 tmphi;
 
 if (size < 4) {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->be_data + size;
 tmphi = tcg_const_i64(0);
 tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
 } else {
+bool be = s->be_data == MO_BE;
 TCGv_i64 tcg_hiaddr;
+
 tmphi = tcg_temp_new_i64();
 tcg_hiaddr = tcg_temp_new_i64();
 
-tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
 tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, 
get_mem_index(s),
+s->be_data | MO_Q);
+tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, 
get_mem_index(s),
+s->be_data | MO_Q);
 tcg_temp_free_i64(tcg_hiaddr);
 }
 
@@ -942,7 +951,7 @@ static void clear_vec_high(DisasContext *s, int rd)
 static void do_vec_st(DisasContext *s, int srcidx, int element,
   TCGv_i64 tcg_addr, int size)
 {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->be_data + size;
 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
 read_vec_element(s, tcg_tmp, srcidx, element, size);
@@ -955,7 +964,7 @@ static void do_vec_st(DisasContext *s, int srcidx, int 
element,
 static void do_vec_ld(DisasContext *s, int destidx, int element,
   TCGv_i64 tcg_addr, int size)
 {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->be_data + size;
 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
 tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
@@ -1702,7 +1711,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2,
TCGv_i64 addr, int size, bool is_pair)
 {
 TCGv_i64 tmp = tcg_temp_new_i64();
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->be_data + size;
 
 g_assert(size <= 3);
 tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
@@ -1764,7 +1773,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, 
int rt, int rt2,
 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
 
 tmp = tcg_temp_new_i64();
-tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size);
+tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), s-&g

[Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation

2016-03-01 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Now that CPSR.E is set correctly, prepare for when setend will be able
to change it; bswap data in and out of strex manually by comparing
SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury
of using TCGMemOps).

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[ PC changes:
  * Moved SCTLR/CPSR logic to arm_cpu_data_is_big_endian
]
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
Changed since v1:
Removed SCTLR logic from bwap_data()

 linux-user/main.c | 50 +++---
 target-arm/cpu.h  | 11 +++
 2 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 510b3b7..2b1e755 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -451,6 +451,38 @@ void cpu_loop(CPUX86State *env)
 __r;\
 })
 
+#define get_user_data_u32(x, gaddr, env)\
+({ abi_long __r = get_user_u32((x), (gaddr));   \
+if (!__r && arm_cpu_bswap_data(env)) {  \
+(x) = bswap32(x);   \
+}   \
+__r;\
+})
+
+#define get_user_data_u16(x, gaddr, env)\
+({ abi_long __r = get_user_u16((x), (gaddr));   \
+if (!__r && arm_cpu_bswap_data(env)) {  \
+(x) = bswap16(x);   \
+}   \
+__r;\
+})
+
+#define put_user_data_u32(x, gaddr, env)\
+({ typeof(x) __x = (x); \
+if (arm_cpu_bswap_data(env)) {  \
+__x = bswap32(__x); \
+}   \
+put_user_u32(__x, (gaddr)); \
+})
+
+#define put_user_data_u16(x, gaddr, env)\
+({ typeof(x) __x = (x); \
+if (arm_cpu_bswap_data(env)) {  \
+__x = bswap16(__x); \
+}   \
+put_user_u16(__x, (gaddr)); \
+})
+
 #ifdef TARGET_ABI32
 /* Commpage handling -- there is no commpage for AArch64 */
 
@@ -610,11 +642,11 @@ static int do_strex(CPUARMState *env)
 segv = get_user_u8(val, addr);
 break;
 case 1:
-segv = get_user_u16(val, addr);
+segv = get_user_data_u16(val, addr, env);
 break;
 case 2:
 case 3:
-segv = get_user_u32(val, addr);
+segv = get_user_data_u32(val, addr, env);
 break;
 default:
 abort();
@@ -625,12 +657,16 @@ static int do_strex(CPUARMState *env)
 }
 if (size == 3) {
 uint32_t valhi;
-segv = get_user_u32(valhi, addr + 4);
+segv = get_user_data_u32(valhi, addr + 4, env);
 if (segv) {
 env->exception.vaddress = addr + 4;
 goto done;
 }
-val = deposit64(val, 32, 32, valhi);
+if (arm_cpu_bswap_data(env)) {
+val = deposit64((uint64_t)valhi, 32, 32, val);
+} else {
+val = deposit64(val, 32, 32, valhi);
+}
 }
 if (val != env->exclusive_val) {
 goto fail;
@@ -642,11 +678,11 @@ static int do_strex(CPUARMState *env)
 segv = put_user_u8(val, addr);
 break;
 case 1:
-segv = put_user_u16(val, addr);
+segv = put_user_data_u16(val, addr, env);
 break;
 case 2:
 case 3:
-segv = put_user_u32(val, addr);
+segv = put_user_data_u32(val, addr, env);
 break;
 }
 if (segv) {
@@ -655,7 +691,7 @@ static int do_strex(CPUARMState *env)
 }
 if (size == 3) {
 val = env->regs[(env->exclusive_info >> 12) & 0xf];
-segv = put_user_u32(val, addr + 4);
+segv = put_user_data_u32(val, addr + 4, env);
 if (segv) {
 env->exception.vaddress = addr + 4;
 goto done;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ab0ea92..cbf171c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -2102,6 +2102,17 @@ static inline int fp_exception_el(CPUARMState *env)
 return 0;
 }
 
+#ifdef CONFIG_USER_ONLY
+static inline bool arm_cpu_bswap_data(CPUARMState *env)
+{
+return
+#ifdef TARGET_WORDS_BIGENDIAN
+   1 ^
+#endif
+   arm_cpu_data_is_big_endian(env);
+}
+#endif
+
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 target_ulong *cs_base, int *flags)
 {
-- 
1.9.1




[Qemu-devel] [PATCH v2 02/18] linux-user: arm: pass env to get_user_code_*

2016-03-01 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

This matches the idiom used by get_user_data_* later in the series,
and will help when bswap_code will be replaced by SCTLR.B.

Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)

 linux-user/main.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 700724e..bcb9f66 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -435,17 +435,17 @@ void cpu_loop(CPUX86State *env)
 
 #ifdef TARGET_ARM
 
-#define get_user_code_u32(x, gaddr, doswap) \
+#define get_user_code_u32(x, gaddr, env)\
 ({ abi_long __r = get_user_u32((x), (gaddr));   \
-if (!__r && (doswap)) { \
+if (!__r && (env)->bswap_code) {\
 (x) = bswap32(x);   \
 }   \
 __r;\
 })
 
-#define get_user_code_u16(x, gaddr, doswap) \
+#define get_user_code_u16(x, gaddr, env)\
 ({ abi_long __r = get_user_u16((x), (gaddr));   \
-if (!__r && (doswap)) { \
+if (!__r && (env)->bswap_code) {\
 (x) = bswap16(x);   \
 }   \
 __r;\
@@ -692,7 +692,7 @@ void cpu_loop(CPUARMState *env)
 /* we handle the FPU emulation here, as Linux */
 /* we get the opcode */
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u32(opcode, env->regs[15], env->bswap_code);
+get_user_code_u32(opcode, env->regs[15], env);
 
 rc = EmulateAll(opcode, >fpa, env);
 if (rc == 0) { /* illegal instruction */
@@ -762,25 +762,23 @@ void cpu_loop(CPUARMState *env)
 if (trapnr == EXCP_BKPT) {
 if (env->thumb) {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u16(insn, env->regs[15], 
env->bswap_code);
+get_user_code_u16(insn, env->regs[15], env);
 n = insn & 0xff;
 env->regs[15] += 2;
 } else {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u32(insn, env->regs[15], 
env->bswap_code);
+get_user_code_u32(insn, env->regs[15], env);
 n = (insn & 0xf) | ((insn >> 4) & 0xff0);
 env->regs[15] += 4;
 }
 } else {
 if (env->thumb) {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u16(insn, env->regs[15] - 2,
-  env->bswap_code);
+get_user_code_u16(insn, env->regs[15] - 2, env);
 n = insn & 0xff;
 } else {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u32(insn, env->regs[15] - 4,
-  env->bswap_code);
+get_user_code_u32(insn, env->regs[15] - 4, env);
 n = insn & 0xff;
 }
 }
-- 
1.9.1




[Qemu-devel] [PATCH v2 06/18] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode

2016-03-01 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

If doing big-endian linux-user mode, set both the CPSR.E and SCTLR.E0E
bits. This sets big-endian mode for data accesses.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
changed since v1:
Removed claim of AA64 support from commit message

 linux-user/main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index fe2a8dd..510b3b7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4453,7 +4453,8 @@ int main(int argc, char **argv, char **envp)
 /* Enable BE8.  */
 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
 && (info->elf_flags & EF_ARM_BE8)) {
-/* nothing for now, CPSR.E not emulated yet */
+env->uncached_cpsr |= CPSR_E;
+env->cp15.sctlr_el[1] |= SCTLR_E0E;
 } else {
 env->cp15.sctlr_el[1] |= SCTLR_B;
 }
-- 
1.9.1




[Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support

2016-03-01 Thread Peter Crosthwaite
Hi All,

This patch series adds system-mode big-endian support for ARM. It also
implements the setend instruction, and loading of BE binaries even in
LE emulation mode.

Based on Paolo's original work.

I have tested all of LE, BE8 and BE32 in both linux-user mode (for
regressions) and system mode (BE8 and BE32 are new here).
My test application is here, the README gives some example command
lines you can run:

https://github.com/pcrost/arm-be-test

Regards,
Peter

Changed since v1:
Addressed PMM review
Added doc comments to new/changed loader.h APIs


Paolo Bonzini (8):
  linux-user: arm: fix coding style for some linux-user signal functions
  linux-user: arm: pass env to get_user_code_*
  target-arm: implement SCTLR.B, drop bswap_code
  linux-user: arm: handle CPSR.E correctly in strex emulation
  target-arm: pass DisasContext to gen_aa32_ld*/st*
  target-arm: introduce disas flag for endianness
  target-arm: implement setend
  target-arm: implement BE32 mode in system emulation

Peter Crosthwaite (10):
  target-arm: cpu: Move cpu_is_big_endian to header
  arm: cpu: handle BE32 user-mode as BE
  linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode
  target-arm: implement SCTLR.EE
  target-arm: a64: Add endianness support
  target-arm: introduce tbflag for endianness
  loader: add API to load elf header
  loader: load_elf(): Add doc comment
  loader: Add data swap option to load-elf
  arm: boot: Support big-endian elfs

 hw/alpha/dp264.c   |   4 +-
 hw/arm/armv7m.c|   2 +-
 hw/arm/boot.c  |  93 +-
 hw/core/loader.c   |  64 ++-
 hw/cris/boot.c |   2 +-
 hw/i386/multiboot.c|   3 +-
 hw/lm32/lm32_boards.c  |   4 +-
 hw/lm32/milkymist.c|   2 +-
 hw/m68k/an5206.c   |   2 +-
 hw/m68k/dummy_m68k.c   |   2 +-
 hw/m68k/mcf5208.c  |   2 +-
 hw/microblaze/boot.c   |   4 +-
 hw/mips/mips_fulong2e.c|   2 +-
 hw/mips/mips_malta.c   |   2 +-
 hw/mips/mips_mipssim.c |   2 +-
 hw/mips/mips_r4k.c |   2 +-
 hw/moxie/moxiesim.c|   3 +-
 hw/openrisc/openrisc_sim.c |   3 +-
 hw/pci-host/prep.c |   2 +-
 hw/ppc/e500.c  |   2 +-
 hw/ppc/mac_newworld.c  |   5 +-
 hw/ppc/mac_oldworld.c  |   5 +-
 hw/ppc/ppc440_bamboo.c |   3 +-
 hw/ppc/spapr.c |   6 +-
 hw/ppc/virtex_ml507.c  |   3 +-
 hw/s390x/ipl.c |   4 +-
 hw/sparc/leon3.c   |   2 +-
 hw/sparc/sun4m.c   |   4 +-
 hw/sparc64/sun4u.c |   4 +-
 hw/tricore/tricore_testboard.c |   2 +-
 hw/xtensa/sim.c|   4 +-
 hw/xtensa/xtfpga.c |   2 +-
 include/hw/arm/arm.h   |   9 +
 include/hw/elf_ops.h   |  22 ++-
 include/hw/loader.h|  41 -
 linux-user/main.c  |  77 ++--
 linux-user/signal.c| 110 +--
 target-arm/arm_ldst.h  |   8 +-
 target-arm/cpu.c   |  21 +--
 target-arm/cpu.h   |  98 +-
 target-arm/helper.c|  31 +++-
 target-arm/helper.h|   1 +
 target-arm/op_helper.c |   5 +
 target-arm/translate-a64.c |  56 +++---
 target-arm/translate.c | 405 -
 target-arm/translate.h |   3 +-
 46 files changed, 783 insertions(+), 350 deletions(-)

-- 
1.9.1




[Qemu-devel] [PATCH v2 01/18] linux-user: arm: fix coding style for some linux-user signal functions

2016-03-01 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)

 linux-user/signal.c | 110 ++--
 1 file changed, 56 insertions(+), 54 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 962111c..96e86c0 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1536,82 +1536,84 @@ static void
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
  CPUARMState *env, abi_ulong mask)
 {
-   __put_user(env->regs[0], >arm_r0);
-   __put_user(env->regs[1], >arm_r1);
-   __put_user(env->regs[2], >arm_r2);
-   __put_user(env->regs[3], >arm_r3);
-   __put_user(env->regs[4], >arm_r4);
-   __put_user(env->regs[5], >arm_r5);
-   __put_user(env->regs[6], >arm_r6);
-   __put_user(env->regs[7], >arm_r7);
-   __put_user(env->regs[8], >arm_r8);
-   __put_user(env->regs[9], >arm_r9);
-   __put_user(env->regs[10], >arm_r10);
-   __put_user(env->regs[11], >arm_fp);
-   __put_user(env->regs[12], >arm_ip);
-   __put_user(env->regs[13], >arm_sp);
-   __put_user(env->regs[14], >arm_lr);
-   __put_user(env->regs[15], >arm_pc);
+__put_user(env->regs[0], >arm_r0);
+__put_user(env->regs[1], >arm_r1);
+__put_user(env->regs[2], >arm_r2);
+__put_user(env->regs[3], >arm_r3);
+__put_user(env->regs[4], >arm_r4);
+__put_user(env->regs[5], >arm_r5);
+__put_user(env->regs[6], >arm_r6);
+__put_user(env->regs[7], >arm_r7);
+__put_user(env->regs[8], >arm_r8);
+__put_user(env->regs[9], >arm_r9);
+__put_user(env->regs[10], >arm_r10);
+__put_user(env->regs[11], >arm_fp);
+__put_user(env->regs[12], >arm_ip);
+__put_user(env->regs[13], >arm_sp);
+__put_user(env->regs[14], >arm_lr);
+__put_user(env->regs[15], >arm_pc);
 #ifdef TARGET_CONFIG_CPU_32
-   __put_user(cpsr_read(env), >arm_cpsr);
+__put_user(cpsr_read(env), >arm_cpsr);
 #endif
 
-   __put_user(/* current->thread.trap_no */ 0, >trap_no);
-   __put_user(/* current->thread.error_code */ 0, >error_code);
-   __put_user(/* current->thread.address */ 0, >fault_address);
-   __put_user(mask, >oldmask);
+__put_user(/* current->thread.trap_no */ 0, >trap_no);
+__put_user(/* current->thread.error_code */ 0, >error_code);
+__put_user(/* current->thread.address */ 0, >fault_address);
+__put_user(mask, >oldmask);
 }
 
 static inline abi_ulong
 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 {
-   unsigned long sp = regs->regs[13];
+unsigned long sp = regs->regs[13];
 
-   /*
-* This is the X/Open sanctioned signal stack switching.
-*/
-   if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
-sp = target_sigaltstack_used.ss_sp + 
target_sigaltstack_used.ss_size;
-   /*
-* ATPCS B01 mandates 8-byte alignment
-*/
-   return (sp - framesize) & ~7;
+/*
+ * This is the X/Open sanctioned signal stack switching.
+ */
+if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
+sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+}
+/*
+ * ATPCS B01 mandates 8-byte alignment
+ */
+return (sp - framesize) & ~7;
 }
 
 static void
 setup_return(CPUARMState *env, struct target_sigaction *ka,
 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
 {
-   abi_ulong handler = ka->_sa_handler;
-   abi_ulong retcode;
-   int thumb = handler & 1;
-   uint32_t cpsr = cpsr_read(env);
+abi_ulong handler = ka->_sa_handler;
+abi_ulong retcode;
+int thumb = handler & 1;
+uint32_t cpsr = cpsr_read(env);
 
-   cpsr &= ~CPSR_IT;
-   if (thumb) {
-   cpsr |= CPSR_T;
-   } else {
-   cpsr &= ~CPSR_T;
-   }
+cpsr &= ~CPSR_IT;
+if (thumb) {
+cpsr |= CPSR_T;
+} else {
+cpsr &= ~CPSR_T;
+}
 
-   if (ka->sa_flags & TARGET_SA_RESTORER) {
-   retcode = ka->sa_restorer;
-   } else {
-   unsigned int idx = thumb;
+if (ka->sa_flags & TARGET_SA_RESTORER) {
+retcode = ka->sa_restorer;
+} else {
+unsigned int idx = thumb;
 
-   if

Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support

2016-03-01 Thread Peter Crosthwaite
On Tue, Mar 1, 2016 at 1:34 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Tuesday, 1 March 2016 10:44 AM
>>
>> On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <s...@weilnetz.de> wrote:
>> > Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
>> >> Hi All,
>> >>
>> >> This patch series adds system-mode big-endian support for ARM. It also
>> >> implements the setend instruction, and loading of BE binaries even in
>> >> LE emulation mode.
>> >>
>> >> Based on Paolo's original work. I have moved all the BE32 related work
>> >> to the back of the series. Multiple parties are interested in the BE8
>> >> work just on its own, so that could potentially be merged w/o BE32.
>> >> PMM requested BE32 be at least thought out architecturally, so this
>> >> series sees BE32 functionality through.
>> >>
>> >> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
>> >> regressions) and system mode (BE8 and BE32 are new here).
>> >> My test application is here, the README gives some example command
>> >> lines you can run:
>> >>
>> >> https://github.com/pcrost/arm-be-test
>> >>
>> >> Regards,
>> >> Peter
>> >
>> > It would be nice to get at least the emulation for 'setend' into the
>> > next version, because it is needed for the Raspberry Pi emulation.
>> >
>>
>> BTW if you can link me binaries and a failing command line for the
>> failing rPI work I can test it, I am currently doing my own standalone
>> tests (of linux user as well).
>
> Download and unzip:
> https://downloads.raspberrypi.org/raspbian_lite_latest
>
> Then, mount the boot partition, and grab a copy of kernel7.img. You should 
> now be able to boot on a current qemu with:
>
> qemu-system-arm -M raspi2 -kernel kernel7.img -sd 
> 2016-02-26-raspbian-jessie-lite.img -append "rw earlyprintk loglevel=8 
> console=ttyAMA0 root=/dev/mmcblk0p2 rootwait" -serial stdio -d unimp
>
> At present, this fails with:
>
> [   10.535232] VFS: Mounted root (ext4 filesystem) on device 179:2.
> [   10.729685] devtmpfs: mounted
> [   10.805125] Freeing unused kernel memory: 416K (80776000 - 807de000)
> [   17.317286] random: systemd urandom read with 6 bits of entropy available
> arm: unimplemented setend
> [   17.366656] Kernel panic - not syncing: Attempted to kill init! 
> exitcode=0x0004
> [   17.366656]
> [   17.384625] CPU: 0 PID: 1 Comm: systemd Not tainted 4.1.7-v7+ #817
> [   17.395562] Hardware name: BCM2709
> [   17.404738] [<80018440>] (unwind_backtrace) from [<80013e0c>] 
> (show_stack+0x20/0x24)
> [   17.419042] [<80013e0c>] (show_stack) from [<80558548>] 
> (dump_stack+0x98/0xe0)
> [   17.432237] [<80558548>] (dump_stack) from [<8055473c>] (panic+0xa4/0x204)
> [   17.444761] [<8055473c>] (panic) from [<8002937c>] (do_exit+0xa0c/0xa64)
> [   17.452507] [<8002937c>] (do_exit) from [<80029470>] 
> (do_group_exit+0x50/0xcc)
> [   17.462827] [<80029470>] (do_group_exit) from [<80033ed4>] 
> (get_signal+0x2b0/0x6e0)
> [   17.474429] [<80033ed4>] (get_signal) from [<80013194>] 
> (do_signal+0x98/0x3ac)
> [   17.482176] [<80013194>] (do_signal) from [<80013690>] 
> (do_work_pending+0xb8/0xc8)
> [   17.490129] [<80013690>] (do_work_pending) from [<8000f9e4>] 
> (work_pending+0xc/0x20)
> [   17.501020] ---[ end Kernel panic - not syncing: Attempted to kill init! 
> exitcode=0x0004
> [   17.501020]
>

Reproduced. With my patch series I am now getting further:

[5.570600] VFS: Mounted root (ext4 filesystem) on device 179:2.
[5.628967] devtmpfs: mounted
[5.667292] Freeing unused kernel memory: 448K (8078a000 - 807fa000)
[7.829100] random: systemd urandom read with 2 bits of entropy available
[7.902604] systemd[1]: systemd 215 running in system mode. (+PAM
+AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ
-SECCOMP -APPARMOR)
[7.913866] systemd[1]: Detected architecture 'arm'.

Welcome to Raspbian GNU/Linux 8 (jessie)!

[8.625874] NET: Registered protocol family 10
[8.645330] systemd[1]: Inserted module 'ipv6'
[8.671989] systemd[1]: Set hostname to .
[   12.670915] systemd[1]: Cannot add dependency job for unit
display-manager.service, ignoring: Unit display-manager.service failed
to load: No such file or directory.
[   12.720439] systemd[1]: Starting Forward Password Requests to Wall
Directory Watch.
[   12.731310] systemd[1]: Star

Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support

2016-03-01 Thread Peter Crosthwaite
On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <s...@weilnetz.de> wrote:
> Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
>> Hi All,
>>
>> This patch series adds system-mode big-endian support for ARM. It also
>> implements the setend instruction, and loading of BE binaries even in
>> LE emulation mode.
>>
>> Based on Paolo's original work. I have moved all the BE32 related work
>> to the back of the series. Multiple parties are interested in the BE8
>> work just on its own, so that could potentially be merged w/o BE32.
>> PMM requested BE32 be at least thought out architecturally, so this
>> series sees BE32 functionality through.
>>
>> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
>> regressions) and system mode (BE8 and BE32 are new here).
>> My test application is here, the README gives some example command
>> lines you can run:
>>
>> https://github.com/pcrost/arm-be-test
>>
>> Regards,
>> Peter
>
> It would be nice to get at least the emulation for 'setend' into the
> next version, because it is needed for the Raspberry Pi emulation.
>

BTW if you can link me binaries and a failing command line for the
failing rPI work I can test it, I am currently doing my own standalone
tests (of linux user as well).

Regards,
Peter

> Peter C., are you planning a new pull request? Maybe the number
> of commits needed can be reduced by adding the already reviewed
> ones to QEMU.
>
> Regards,
> Stefan
>
>



Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support

2016-03-01 Thread Peter Crosthwaite
On Mon, Feb 29, 2016 at 9:27 PM, Stefan Weil <s...@weilnetz.de> wrote:
> Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
>> Hi All,
>>
>> This patch series adds system-mode big-endian support for ARM. It also
>> implements the setend instruction, and loading of BE binaries even in
>> LE emulation mode.
>>
>> Based on Paolo's original work. I have moved all the BE32 related work
>> to the back of the series. Multiple parties are interested in the BE8
>> work just on its own, so that could potentially be merged w/o BE32.
>> PMM requested BE32 be at least thought out architecturally, so this
>> series sees BE32 functionality through.
>>
>> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
>> regressions) and system mode (BE8 and BE32 are new here).
>> My test application is here, the README gives some example command
>> lines you can run:
>>
>> https://github.com/pcrost/arm-be-test
>>
>> Regards,
>> Peter
>
> It would be nice to get at least the emulation for 'setend' into the
> next version, because it is needed for the Raspberry Pi emulation.
>
> Peter C., are you planning a new pull request? Maybe the number
> of commits needed can be reduced by adding the already reviewed
> ones to QEMU.
>

I have the respun branch based on Peter's comments tested as working.
I automated my tests so the last thing to do is bisect-ability test it
(test every commit for regressions) before I post it. I am stretched
and still have a series to review at the front of my todo list though.

Regards,
Peter

> Regards,
> Stefan
>
>



Re: [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf

2016-02-28 Thread Peter Crosthwaite
On Sun, Feb 28, 2016 at 7:28 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 27 February 2016 at 23:14, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> On Tue, Jan 19, 2016 at 9:53 AM, Peter Maydell <peter.mayd...@linaro.org> 
>> wrote:
>>> Can we have a doc comment so we have something that defines what
>>> values data_swab accepts? (it's not just a bool).
>>>
>>
>> This is difficult to capture without writing to whole documentation
>> for load_elf. So here goes:
>
> Thanks; a couple of typos below, but otherwise looks good.
>
>
>> /** load_elf:
>>  * @filename: Path of ELF file
>>  * @translate_fn: optional function to translate load addresses
>>  * @translate_opaque: opaque data passed to @translate_fn
>>  * @pentry: Populated with program entry point. Ignored if NULL.
>>  * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
>>  * @highaddr: Populated with highest loaded address. Ignored if NULL.
>>  * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
>>  * @elf_machine: Expected ELF machine type
>>  * @clear_lsb: Set to mask off LSB of addresses (Some arch's use this
>
> Can we just write out "architectures" here?
>
>>for non-address data)
>>  * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
>>  * for swapping bytes within halfwords, 2 for bytes within
>>  * words and 3 for within doublewords.
>>  *
>>  * Load an ELF file's contents to the emulated systems address space.
>
> "system's"
>
>>  * Clients may optionally specify a callback to perform address
>>  * translations. @pentry, @lowaddr and @highaddr are optional pointers
>>  * which will be populated with various load information. @bigendian and
>>  * @elf_machine give the expected endianness and machine for the ELF the
>>  * load will fail it the target ELF does not match. Some architectures
>
> "if"
>
>>  * have some arch-specific behaviours that come into effect when their
>
> "architecture"
>

All fixed. Thanks for the pre-review.

Regards,
Peter

>>  * particular values for @elf_machine are set.
>>  */
>
> thanks
> -- PMM



Re: [Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs

2016-02-27 Thread Peter Crosthwaite
On Tue, Jan 19, 2016 at 10:06 AM, Peter Maydell
<peter.mayd...@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> Support ARM big-endian ELF files in system-mode emulation. When loading
>> an elf, determine the endianness mode expected by the elf, and set the
>> relevant CPU state accordingly.
>>
>> With this, big-endian modes are now fully supported via system-mode LE,
>> so there is no need to restrict the elf loading to the TARGET
>> endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.
>>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
>> ---
>>
>>  hw/arm/boot.c| 96 
>> ++--
>>  include/hw/arm/arm.h |  9 +
>>  2 files changed, 88 insertions(+), 17 deletions(-)
>>
>> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
>> index 0de4269..053c9e8 100644
>> --- a/hw/arm/boot.c
>> +++ b/hw/arm/boot.c
>> @@ -465,9 +465,34 @@ static void do_cpu_reset(void *opaque)
>>  cpu_reset(cs);
>>  if (info) {
>>  if (!info->is_linux) {
>> +int i;
>>  /* Jump to the entry point.  */
>>  uint64_t entry = info->entry;
>>
>> +switch (info->endianness) {
>> +case ARM_ENDIANNESS_LE:
>> +env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
>> +for (i = 1; i < 4; ++i) {
>> +env->cp15.sctlr_el[i] &= ~SCTLR_EE;
>> +}
>> +env->uncached_cpsr &= ~CPSR_E;
>> +break;
>> +case ARM_ENDIANNESS_BE8:
>> +env->cp15.sctlr_el[1] |= SCTLR_E0E;
>> +for (i = 1; i < 4; ++i) {
>> +env->cp15.sctlr_el[i] |= SCTLR_EE;
>> +}
>> +env->uncached_cpsr |= CPSR_E;
>> +break;
>> +case ARM_ENDIANNESS_BE32:
>> +env->cp15.sctlr_el[1] |= SCTLR_B;
>> +break;
>> +case ARM_ENDIANNESS_UNKNOWN:
>> +break; /* Board's decision */
>> +default:
>> +g_assert_not_reached();
>> +}
>
> Do we really want this much magic for non-linux images?

I think so ...

>  I would
> expect that the image would be intended to run with whatever the
> state the board puts the CPU in from reset (ie the CPU has suitable
> QOM properties for its initial endianness state, corresponding to
> real hardware reset-config signals like the A15's CFGEND/CFGTE).
>

As with this you can handle two use cases:

1: Elfs for firmware development
2: Elfs for a real-world loadable guest.

Firmware elfs should match the hardwired (QOM properties) settings
anyway, but the more interesting case is the real-world loadable guest
ELF. That is, you have some elf-capable bootloader in real HW which
will DTRT based on the elf header before handoff. This will emulate
that case without needing to demote your elf to raw binary data (and
then explicitly load your bootloader).

>> +
>>  if (!env->aarch64) {
>>  env->thumb = info->entry & 1;
>>  entry &= 0xfffe;
>> @@ -589,16 +614,23 @@ static void arm_load_kernel_notify(Notifier *notifier, 
>> void *data)
>>  int kernel_size;
>>  int initrd_size;
>>  int is_linux = 0;
>> +
>>  uint64_t elf_entry, elf_low_addr, elf_high_addr;
>>  int elf_machine;
>> +bool elf_is64;
>> +union {
>> +Elf32_Ehdr h32;
>> +Elf64_Ehdr h64;
>> +} elf_header;
>> +
>>  hwaddr entry, kernel_load_offset;
>> -int big_endian;
>>  static const ARMInsnFixup *primary_loader;
>>  ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
>>   notifier, notifier);
>>  ARMCPU *cpu = n->cpu;
>>  struct arm_boot_info *info =
>>  container_of(n, struct arm_boot_info, load_kernel_notifier);
>> +Error *err = NULL;
>>
>>  /* The board code is not supposed to set secure_board_setup unless
>>   * running its code in secure mode is actually possible, and KVM
>> @@ -678,12 +710,6 @@ static void arm_load_kernel_notify(Notifier *notifier, 
>> void *data)
>>  if (info->nb_cpus == 0)
>>  info->nb_cpus = 1;
>>
>> -#ifdef TARGET_WORDS_BIGENDIAN
>> -big_endian = 1;
>> -#el

Re: [Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf

2016-02-27 Thread Peter Crosthwaite
On Tue, Jan 19, 2016 at 9:53 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> Some CPUs are of an opposite data-endianness to other components in the
>> system. Sometimes elfs have the data sections layed out with this CPU
>> data-endianess accounting for when loaded via the CPU, byte swaps
>> (relative to other system components) will occur.
>>
>> The leading example, is ARM's BE32 mode, which is is basically LE with
>> address manipulation on half-word and byte accesses to access the
>> hw/byte reversed address. This means that word data is invariant
>> accross LE and BE32. This also means that instructions are still LE.
>> The expectation is that the elf will be loaded via the CPU in this
>> endianness scheme, which means the data in the elf is reversed at
>> compile time.
>>
>> As QEMU loads via the system memory directly, rather than the CPU, we
>> need a mechanism to reverse elf data endianness to implement this
>> possibility.
>>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
>
>> diff --git a/include/hw/loader.h b/include/hw/loader.h
>> index 33067f8..e542575 100644
>> --- a/include/hw/loader.h
>> +++ b/include/hw/loader.h
>> @@ -35,7 +35,7 @@ const char *load_elf_strerror(int error);
>>  int load_elf(const char *filename, uint64_t (*translate_fn)(void *, 
>> uint64_t),
>>   void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>>   uint64_t *highaddr, int big_endian, int elf_machine,
>> - int clear_lsb);
>> + int clear_lsb, int data_swab);
>>  void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error 
>> **errp);
>>  int load_aout(const char *filename, hwaddr addr, int max_sz,
>>int bswap_needed, hwaddr target_page_size);
>
> Can we have a doc comment so we have something that defines what
> values data_swab accepts? (it's not just a bool).
>

This is difficult to capture without writing to whole documentation
for load_elf. So here goes:

/** load_elf:
 * @filename: Path of ELF file
 * @translate_fn: optional function to translate load addresses
 * @translate_opaque: opaque data passed to @translate_fn
 * @pentry: Populated with program entry point. Ignored if NULL.
 * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
 * @highaddr: Populated with highest loaded address. Ignored if NULL.
 * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
 * @elf_machine: Expected ELF machine type
 * @clear_lsb: Set to mask off LSB of addresses (Some arch's use this
   for non-address data)
 * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
 * for swapping bytes within halfwords, 2 for bytes within
 * words and 3 for within doublewords.
 *
 * Load an ELF file's contents to the emulated systems address space.
 * Clients may optionally specify a callback to perform address
 * translations. @pentry, @lowaddr and @highaddr are optional pointers
 * which will be populated with various load information. @bigendian and
 * @elf_machine give the expected endianness and machine for the ELF the
 * load will fail it the target ELF does not match. Some architectures
 * have some arch-specific behaviours that come into effect when their
 * particular values for @elf_machine are set.
 */

Regards,
Peter

> Otherwise
> Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
>
> thanks
> -- PMM



Re: [Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header

2016-02-27 Thread Peter Crosthwaite
On Tue, Jan 19, 2016 at 9:50 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> Add an API to load an elf header header from a file. Populates a
>> buffer with the header contents, as well as a boolean for whether the
>> elf is 64b or not. Both arguments are optional.
>>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
>> ---
>>
>>  hw/core/loader.c| 48 
>>  include/hw/loader.h |  1 +
>>  2 files changed, 49 insertions(+)
>>
>> diff --git a/hw/core/loader.c b/hw/core/loader.c
>> index 6b69852..28da8e2 100644
>> --- a/hw/core/loader.c
>> +++ b/hw/core/loader.c
>> @@ -331,6 +331,54 @@ const char *load_elf_strerror(int error)
>>  }
>>  }
>>
>> +void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
>> +{
>> +int fd;
>> +uint8_t e_ident[EI_NIDENT];
>> +size_t hdr_size, off = 0;
>> +bool is64l;
>> +
>> +fd = open(filename, O_RDONLY | O_BINARY);
>> +if (fd < 0) {
>> +error_setg_errno(errp, errno, "Fail to open file");
>
> "Failed" (also below).
>

Fixed (x2).

> I don't think we end up with the filename anywhere in the
> error message; it would be helpful if we could include it.
>

Fixed (x4)

>> +return;
>> +}
>> +if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) {
>> +error_setg_errno(errp, errno, "Fail to read file");
>> +goto fail;
>> +}
>> +if (e_ident[0] != ELFMAG0 ||
>> +e_ident[1] != ELFMAG1 ||
>> +e_ident[2] != ELFMAG2 ||
>> +e_ident[3] != ELFMAG3) {
>> +error_setg(errp, "Bad ELF magic");
>> +goto fail;
>> +}
>> +
>> +is64l = e_ident[EI_CLASS] == ELFCLASS64;
>> +hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
>> +if (is64) {
>> +*is64 = is64l;
>> +}
>> +
>> +lseek(fd, 0, SEEK_SET);
>
> You're not checking this lseek for failure (and you don't
> need it anyway, because you could just copy the magic bytes
> into *hdr and read four fewer bytes).
>

OK, so I have optimised it away. What I am doing now is always reading
to straight to hdr[], and if the caller passes hdr == NULL, then hdr
is set to a local buffer (and the full header read is still skipped as
per current logic).

>> +while (hdr && off < hdr_size) {
>> +size_t br = read(fd, hdr + off, hdr_size - off);
>> +switch (br) {
>> +case 0:
>> +error_setg(errp, "File too short");
>> +goto fail;
>> +case -1:
>> +error_setg_errno(errp, errno, "Failed to read file");
>> +goto fail;
>> +}
>> +off += br;
>> +}
>> +
>> +fail:
>> +close(fd);
>> +}
>> +
>>  /* return < 0 if error, otherwise the number of bytes loaded in memory */
>>  int load_elf(const char *filename, uint64_t (*translate_fn)(void *, 
>> uint64_t),
>>   void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>> diff --git a/include/hw/loader.h b/include/hw/loader.h
>> index f7b43ab..33067f8 100644
>> --- a/include/hw/loader.h
>> +++ b/include/hw/loader.h
>> @@ -36,6 +36,7 @@ int load_elf(const char *filename, uint64_t 
>> (*translate_fn)(void *, uint64_t),
>>   void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
>>   uint64_t *highaddr, int big_endian, int elf_machine,
>>   int clear_lsb);
>> +void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error 
>> **errp);
>
> Doc comment, please.
>

Added:

+
+/** load_elf_hdr:
+ * @filename: Path of ELF file
+ * @hdr: Buffer to populate with header data. Header data will not be
+ * filled if set to NULL.
+ * @is64: Set to true if the ELF is 64bit. Ignored if set to NULL
+ * @errp: Populated with an error in failure cases
+ *
+ * Inspect as ELF file's header. Read its full header contents into a
+ * buffer and/or determine if the ELF is 64bit.
+ */


Regards,
Peter

>>  int load_aout(const char *filename, hwaddr addr, int max_sz,
>>int bswap_needed, hwaddr target_page_size);
>>  int load_uimage(const char *filename, hwaddr *ep,
>> --
>> 1.9.1
>
> thanks
> -- PMM



Re: [Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode

2016-02-27 Thread Peter Crosthwaite
On Tue, Jan 19, 2016 at 9:35 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 19 January 2016 at 17:26, Peter Maydell <peter.mayd...@linaro.org> wrote:
>> On 18 January 2016 at 07:12, Peter Crosthwaite
>> <crosthwaitepe...@gmail.com> wrote:
>>> Don't set CPSR.E for BE32 linux-user mode. As linux-user mode models
>>> BE32, using normal BE (and system mode will not), a special case is
>>> needed for user-mode where if sctlr.b is set, the CPU identifies as BE.
>>>
>>> Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
>>> ---
>>>
>>>  linux-user/main.c |  2 --
>>>  target-arm/cpu.h  | 12 +++-
>>>  2 files changed, 11 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/linux-user/main.c b/linux-user/main.c
>>> index d481458..60375fb 100644
>>> --- a/linux-user/main.c
>>> +++ b/linux-user/main.c
>>> @@ -4496,8 +4496,6 @@ int main(int argc, char **argv, char **envp)
>>>  env->uncached_cpsr |= CPSR_E;
>>>  } else {
>>>  env->cp15.sctlr_el[1] |= SCTLR_B;
>>> -/* We model BE32 as regular BE, so set CPSR_E */
>>> -env->uncached_cpsr |= CPSR_E;
>>
>> ...this is undoing what we just did in the previous patch and
>> which I reviewed as being the wrong thing there...
>>
>>>  }
>>>  #endif
>>>  }
>>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>>> index 3edd56b..96b1e99 100644
>>> --- a/target-arm/cpu.h
>>> +++ b/target-arm/cpu.h
>>> @@ -1812,7 +1812,17 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
>>>
>>>  /* In 32bit endianness is determined by looking at CPSR's E bit */
>>>  if (!is_a64(env)) {
>>> -return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
>>> +return
>>> +#ifdef CONFIG_USER_ONLY
>>> +/* In user mode, BE32 data accesses are just modelled as
>>> + * regular BE access. In system mode, BE32 is modelled as
>>> + * little endian, with the appropriate address translations on
>>> + * non-word accesses. So sctlr.b only affects overall
>>> + * endianness in user mode
>>> + */
>>> +arm_sctlr_b(env) ||
>>> +#endif
>>> +((env->uncached_cpsr & CPSR_E) ? 1 : 0);
>>>  }
>>
>> This doesn't seem quite right -- for system emulation we currently
>> pick MO_BE or MO_LE based on the TB flag which is set according
>> to (arm_cpu_is_big_endian(env). So if we ignore SCTLR.B in
>> system mode then we'll still try to do LE accesses.
>
> Ah, no, looking at the next patch this is correct, it's just the
> comment is a touch confusing. I suggest
>
>  /* In system mode, BE32 is modelled in line with the architecture
>   * (as word-invariant big-endianness), where loads and stores are done
>   * little endian but from addresses which are adjusted by XORing
>   * with the appropriate constant. So the endianness to use for the
>   * raw data access is not affected by SCTLR.B.
>   * In user mode, however, we model BE32 as byte-invariant big-endianness
>   * (because user-only code cannot tell the difference), and so we
>   * need to use a data access endianness that depends on SCTLR.B.
>   */
>

Comment updated.

Regards,
Peter

> thanks
> -- PMM



Re: [Qemu-devel] [PATCH v1 10/17] target-arm: implement setend

2016-02-27 Thread Peter Crosthwaite
On Tue, Jan 19, 2016 at 8:29 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> From: Paolo Bonzini <pbonz...@redhat.com>
>>
>> Since this is not a high-performance path, just use a helper to
>> flip the E bit and force a lookup in the hash table since the
>> flags have changed.
>>
>> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
>> Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
>> ---
>>
>>  target-arm/helper.h|  1 +
>>  target-arm/op_helper.c |  5 +
>>  target-arm/translate.c | 16 
>>  3 files changed, 14 insertions(+), 8 deletions(-)
>>
>> diff --git a/target-arm/helper.h b/target-arm/helper.h
>> index c2a85c7..2315a9c 100644
>> --- a/target-arm/helper.h
>> +++ b/target-arm/helper.h
>> @@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
>> i32, i32, i32, i32)
>>  DEF_HELPER_2(exception_internal, void, env, i32)
>>  DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
>> +DEF_HELPER_1(setend, void, env)
>>  DEF_HELPER_1(wfi, void, env)
>>  DEF_HELPER_1(wfe, void, env)
>>  DEF_HELPER_1(yield, void, env)
>> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
>> index e42d287..2a4bc67 100644
>> --- a/target-arm/op_helper.c
>> +++ b/target-arm/op_helper.c
>> @@ -295,6 +295,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, 
>> uint32_t shift)
>>  return res;
>>  }
>>
>> +void HELPER(setend)(CPUARMState *env)
>> +{
>> +env->uncached_cpsr ^= CPSR_E;
>> +}
>> +
>>  /* Function checks whether WFx (WFI/WFE) instructions are set up to be 
>> trapped.
>>   * The function returns the target EL (1-3) if the instruction is to be 
>> trapped;
>>   * otherwise it returns 0 indicating it is not trapped.
>> diff --git a/target-arm/translate.c b/target-arm/translate.c
>> index cb925ef..192a5d6 100644
>> --- a/target-arm/translate.c
>> +++ b/target-arm/translate.c
>> @@ -7726,10 +7726,10 @@ static void disas_arm_insn(DisasContext *s, unsigned 
>> int insn)
>>  if ((insn & 0x0dff) == 0x0101) {
>>  ARCH(6);
>>  /* setend */
>> -if (((insn >> 9) & 1) != s->bswap_code) {
>> -/* Dynamic endianness switching not implemented. */
>> -qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
>> -goto illegal_op;
>> +if (((insn >> 9) & 1) != !!(s->mo_endianness == MO_BE)) {
>> +gen_helper_setend(cpu_env);
>> +gen_set_pc_im(s, s->pc);
>> +s->is_jmp = DISAS_JUMP;
>
> Rather than manually calling set_pc_im and using DISAS_JUMP, better
> to use DISAS_UPDATE, which will do the gen_set_pc_im() call for you.
>
> (Ditto in the other hunk.)
>

Fixed.

Regards,
Peter

> thanks
> -- PMM



Re: [Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header

2016-02-27 Thread Peter Crosthwaite
On Tue, Jan 19, 2016 at 8:11 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
>>
>> There is a CPU data endianness test that is used to drive the
>> virtio_big_endian test.
>>
>> Move this up to the header so it can be more generally used for endian
>> tests. The KVM specific cpu_syncronize_state call is left behind in the
>> virtio specific function.
>>
>> Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
>> ---
>>
>>  target-arm/cpu.c | 19 +++
>>  target-arm/cpu.h | 19 +++
>>  2 files changed, 22 insertions(+), 16 deletions(-)
>>
>> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
>> index 35a1f12..d3b73bf 100644
>> --- a/target-arm/cpu.c
>> +++ b/target-arm/cpu.c
>> @@ -368,26 +368,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, 
>> int level)
>>  #endif
>>  }
>>
>> -static bool arm_cpu_is_big_endian(CPUState *cs)
>> +static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
>>  {
>>  ARMCPU *cpu = ARM_CPU(cs);
>>  CPUARMState *env = >env;
>> -int cur_el;
>>
>>  cpu_synchronize_state(cs);
>> -
>> -/* In 32bit guest endianness is determined by looking at CPSR's E bit */
>> -if (!is_a64(env)) {
>> -return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
>> -}
>> -
>> -cur_el = arm_current_el(env);
>> -
>> -if (cur_el == 0) {
>> -return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
>> -}
>> -
>> -return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
>> +return arm_cpu_is_big_endian(env);
>>  }
>>
>>  #endif
>> @@ -1420,7 +1407,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void 
>> *data)
>>  cc->do_unaligned_access = arm_cpu_do_unaligned_access;
>>  cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
>>  cc->vmsd = _arm_cpu;
>> -cc->virtio_is_big_endian = arm_cpu_is_big_endian;
>> +cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
>>  #endif
>>  cc->gdb_num_core_regs = 26;
>>  cc->gdb_core_xml_file = "arm-core.xml";
>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>> index f83070a..54675c7 100644
>> --- a/target-arm/cpu.h
>> +++ b/target-arm/cpu.h
>> @@ -1795,6 +1795,25 @@ static inline bool arm_singlestep_active(CPUARMState 
>> *env)
>>  && arm_generate_debug_exceptions(env);
>>  }
>>
>> +/* Return true if the processor is in big-endian mode. */
>> +static bool arm_cpu_is_big_endian(CPUARMState *env)
>> +{
>
> No problems code-wise, but can we call the function
> arm_cpu_data_is_big_endian() or something?

Fixed.

Regards,
Peter

> This is returning the
> endianness to use for data accesses; there isn't an overall
> "big-endian mode" that affects everything except for the
> obsolete BE32.
>
> thanks
> -- PMM



Re: [Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE

2016-02-27 Thread Peter Crosthwaite
On Tue, Jan 19, 2016 at 7:58 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> On 18 January 2016 at 07:12, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
>>
>> Implement SCTLR.EE bit which controls data endianess for exceptions
>> and page table translations. SCTLR.EE is mirrored to the CPSR.E bit
>> on exception entry.
>>
>> Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
>> ---
>>
>>  target-arm/helper.c | 42 --
>>  1 file changed, 32 insertions(+), 10 deletions(-)
>>
>> diff --git a/target-arm/helper.c b/target-arm/helper.c
>> index 59d5a41..afac1b2 100644
>> --- a/target-arm/helper.c
>> +++ b/target-arm/helper.c
>> @@ -5889,7 +5889,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
>>  /* Clear IT bits.  */
>>  env->condexec_bits = 0;
>>  /* Switch to the new mode, and to the correct instruction set.  */
>> -env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
>> +env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_M)) | new_mode;
>
> Why change this line?
>

Reverted

>> +/* Set new mode endianess */
>
> "endianness"
>

Fixed

>> +env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_E)) |
>> +(env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE ? CPSR_E : 0);
>
> This is a bit confusing. I think just splitting it into
> multiple statements would help:
>env->uncached_cpsr &= ~CPSR_E;
>if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
>env->uncached_cpsr |= CPSR_E;
>}
>

Fixed.

>>  env->daif |= mask;
>>  /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
>>   * and we should just guard the thumb mode on V4 */
>> @@ -5958,6 +5961,12 @@ static inline bool 
>> regime_translation_disabled(CPUARMState *env,
>>  return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
>>  }
>>
>> +static inline bool regime_translation_big_endian(CPUARMState *env,
>> + ARMMMUIdx mmu_idx)
>> +{
>> +return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
>> +}
>> +
>>  /* Return the TCR controlling this translation regime */
>>  static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
>>  {
>> @@ -6263,7 +6272,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, 
>> ARMMMUIdx mmu_idx,
>>   */
>>  static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
>>  ARMMMUIdx mmu_idx, uint32_t *fsr,
>> -ARMMMUFaultInfo *fi)
>> +ARMMMUFaultInfo *fi, bool be)
>>  {
>>  ARMCPU *cpu = ARM_CPU(cs);
>>  CPUARMState *env = >env;
>> @@ -6274,12 +6283,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr 
>> addr, bool is_secure,
>>  if (fi->s1ptw) {
>>  return 0;
>>  }
>> -return address_space_ldl(cs->as, addr, attrs, NULL);
>> +if (be) {
>> +return address_space_ldl_be(cs->as, addr, attrs, NULL);
>> +} else {
>> +return address_space_ldl_le(cs->as, addr, attrs, NULL);
>> +}
>>  }
>
> Why not just call regime_translation_big_endian() inside arm_ldl_ptw()
> and arm_ldq_ptw(), rather than having every call site making the call
> and passing in the result?
>

Fixed.

> PS: this patch will conflict with the multi-ases series but only
> fairly trivially.
>

Resolved.

Regards,
Peter

> thanks
> -- PMM



Re: [Qemu-devel] [PATCH v2 7/9] i.MX: Add i.MX6 SOC implementation.

2016-02-20 Thread Peter Crosthwaite
On Sat, Feb 20, 2016 at 10:03 AM, Jean-Christophe DUBOIS
<j...@tribudubois.net> wrote:
> Le 20/02/2016 16:30, Peter Crosthwaite a écrit :
>>
>> On Sat, Feb 20, 2016 at 2:55 AM, Jean-Christophe DUBOIS
>> <j...@tribudubois.net> wrote:
>>>
>>> Just to compare I tried to run Linux on QEMU emulating highbank.
>>>
>>> For now I am unable to start in SMP mode. Only one core is activated.
>>>
>> This is probably due to the fact that the PSCI command encodings for
>> Highbank expected by the kernel are mismatched to the ones in QEMU. I
>> had some patches to change them, but once I got the PSCI right, the
>> boot hung (might be just extreme slowdown like you describe) and I
>> never got the time to fully debug it. SO there is a good chance
>> Highbank has the same bug.
>
>
> Thanks Peter,
>
> So we are not sure we have a reference Cortex A9 platform working with
> has_el3 set to true.
>

Not for SMP linux.

Regards,
Peter

> This is annoying.
>
> JC
>
>>
>> Regards,
>> Peter
>>
>



Re: [Qemu-devel] [PATCH v2 7/9] i.MX: Add i.MX6 SOC implementation.

2016-02-20 Thread Peter Crosthwaite
On Sat, Feb 20, 2016 at 2:55 AM, Jean-Christophe DUBOIS
 wrote:
> Just to compare I tried to run Linux on QEMU emulating highbank.
>
> For now I am unable to start in SMP mode. Only one core is activated.
>

This is probably due to the fact that the PSCI command encodings for
Highbank expected by the kernel are mismatched to the ones in QEMU. I
had some patches to change them, but once I got the PSCI right, the
boot hung (might be just extreme slowdown like you describe) and I
never got the time to fully debug it. SO there is a good chance
Highbank has the same bug.

Regards,
Peter



Re: [Qemu-devel] [PATCH v1 1/2] qdev-monitor.c: Register reset function if the device has one

2016-02-18 Thread Peter Crosthwaite
On Thu, Feb 18, 2016 at 1:47 PM, Paolo Bonzini  wrote:
>
>
> On 18/02/2016 10:56, Markus Armbruster wrote:
>> Alistair Francis  writes:
>>
>>> If the device being added when running qdev_device_add() has
>>> a reset function, register it so that it can be called.
>>>
>>> Signed-off-by: Alistair Francis 
>>> ---
>>>
>>>  qdev-monitor.c | 2 ++
>>>  1 file changed, 2 insertions(+)
>>>
>>> diff --git a/qdev-monitor.c b/qdev-monitor.c
>>> index 81e3ff3..0a99d01 100644
>>> --- a/qdev-monitor.c
>>> +++ b/qdev-monitor.c
>>> @@ -561,6 +561,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error 
>>> **errp)
>>>
>>>  if (bus) {
>>>  qdev_set_parent_bus(dev, bus);
>>> +} else if (dc->reset) {
>>> +qemu_register_reset((void (*)(void *))dc->reset, dev);
>>>  }
>>>
>>>  id = qemu_opts_id(opts);
>>
>> This looks wrong to me.
>>
>> You stuff all the device reset methods into the global reset_handlers
>> list, where they get called in some semi-random order.  This breaks when
>> there are reset order dependencies between devices, e.g. between a
>> device and the bus it plugs into.
>
> There is no bus here, see the "if" above the one that's being added.
>
> However, what devices have done so far is to register/unregister the
> reset in the realize/unrealize methods, and I suggest doing the same.
>

Does this assume the device itself knows whether it is bus-connected
or not? This way has the advantage of catchall-ing devices that have
no bus connected and the device may or may not know whether it is
bus-connected (nor should it need to know). Probably doesn't have in
tree precedent yet, but I thought we wanted to move away from
qdev/qbus managing the device-tree. So ideally, the new else should
become unconditional long term once we debusify (and properly QOMify)
the reset tree (and the if goes away).

> If you really want to add the magic qemu_register_reset, you should at
> least do one of the following:
>
> * add a matching unregister (no idea where)
>

You could add a boolean flag to DeviceState that is set by this
registration. It can then be checked at unrealize to remove reset
handler.

Regards,
Peter

> * assert that the device is not hot-unpluggable, otherwise hot-unplug
> would leave a dangling pointer.
>
> Paolo
>
>> Propagating the reset signal to all the devices is a qdev problem.
>> Copying Andreas for further insight.



Re: [Qemu-devel] [PATCH v3 02/16] register: Add Register API

2016-02-09 Thread Peter Crosthwaite
On Tue, Feb 9, 2016 at 11:35 AM, Alistair Francis
<alistair.fran...@xilinx.com> wrote:
> On Tue, Feb 9, 2016 at 8:06 AM, Alex Bennée <alex.ben...@linaro.org> wrote:
>>
>> Alistair Francis <alistair.fran...@xilinx.com> writes:
>>
>>> This API provides some encapsulation of registers and factors our some
>>> common functionality to common code. Bits of device state (usually MMIO
>>> registers), often have all sorts of access restrictions and semantics
>>> associated with them. This API allow you to define what those
>>> restrictions are on a bit-by-bit basis.
>>>
>>> Helper functions are then used to access the register which observe the
>>> semantics defined by the RegisterAccessInfo struct.
>>>
>>> Some features:
>>> Bits can be marked as read_only (ro field)
>>> Bits can be marked as write-1-clear (w1c field)
>>> Bits can be marked as reserved (rsvd field)
>>> Reset values can be defined (reset)
>>> Bits can throw guest errors when written certain values (ge0, ge1)
>>> Bits can throw unimp errors when written certain values (ui0, ui1)
>>> Bits can be marked clear on read (cor)
>>> Pre and post action callbacks can be added to read and write ops
>>> Verbose debugging info can be enabled/disabled
>>>
>>> Useful for defining device register spaces in a data driven way. Cuts
>>> down on a lot of the verbosity and repetition in the switch-case blocks
>>> in the standard foo_mmio_read/write functions.
>>>
>>> Also useful for automated generation of device models from hardware
>>> design sources.
>>>
>>> Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
>>> Signed-off-by: Alistair Francis <alistair.fran...@xilinx.com>
>>> ---
>>> V3:
>>>  - Address some comments from Fred
>>>
>>>  hw/core/Makefile.objs |   1 +
>>>  hw/core/register.c| 189 
>>> ++
>>>  include/hw/register.h | 132 +++
>>>  3 files changed, 322 insertions(+)
>>>  create mode 100644 hw/core/register.c
>>>  create mode 100644 include/hw/register.h
>>>
>>> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
>>> index abb3560..bf95db5 100644
>>> --- a/hw/core/Makefile.objs
>>> +++ b/hw/core/Makefile.objs
>>> @@ -14,4 +14,5 @@ common-obj-$(CONFIG_SOFTMMU) += machine.o
>>>  common-obj-$(CONFIG_SOFTMMU) += null-machine.o
>>>  common-obj-$(CONFIG_SOFTMMU) += loader.o
>>>  common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
>>> +common-obj-$(CONFIG_SOFTMMU) += register.o
>>>  common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
>>> diff --git a/hw/core/register.c b/hw/core/register.c
>>> new file mode 100644
>>> index 000..f0fc39c
>>> --- /dev/null
>>> +++ b/hw/core/register.c
>>> @@ -0,0 +1,189 @@
>>> +/*
>>> + * Register Definition API
>>> + *
>>> + * Copyright (c) 2013 Xilinx Inc.
>>> + * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwa...@xilinx.com>
>>> + *
>>> + * This work is licensed under the terms of the GNU GPL, version 2.  See
>>> + * the COPYING file in the top-level directory.
>>> + */
>>> +
>>> +#include "hw/register.h"
>>> +#include "qemu/log.h"
>>> +
>>> +static inline void register_write_log(RegisterInfo *reg, int dir, uint64_t 
>>> val,
>>> +  int mask, const char *msg,
>>> +  const char *reason)
>>> +{
>>> +qemu_log_mask(mask, "%s:%s bits %#" PRIx64 " %s write of %d%s%s\n",
>>> +  reg->prefix, reg->access->name, val, msg, dir,
>>> +  reason ? ": " : "", reason ? reason : "");
>>
>> I'm not sure mask needs to be passed down as every use of it seems to
>> imply LOG_GUEST_USER. If you think this might change I would consider
>> passing the mask as the first option to align with other logging functions.
>
> Removing this function as it is no longer required.
>
>>
>>> +}
>>> +
>>> +static inline void register_write_val(RegisterInfo *reg, uint64_t val)
>>> +{
>>> +if (!reg->data) {
>>> +return;
>>> +}
>>
>> Can you have a defined register without a data field? If it is invalid I
>> would use a g_assert() instead.
>
> Good point, I can't see any cases where there wouldn't be a data field.
>

>From the register API point of view it should be valid. It just so
happens when use the array based registration it never comes up. So I
think assert is not quite right even though the path is dead as of
this series.

Regards,
Peter



Re: [Qemu-devel] [Qemu-arm] Does QEMU support AArch64 Big Endian emulation on x86-64 host?

2016-02-01 Thread Peter Crosthwaite
On Mon, Feb 1, 2016 at 3:25 AM, Ruslan Bilovol <ruslan.bilo...@gmail.com> wrote:
> On Wed, Jan 27, 2016 at 7:39 PM, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> On Tue, Jan 26, 2016 at 4:05 AM, Ruslan Bilovol
>> <ruslan.bilo...@gmail.com> wrote:
>>> On Mon, Jan 25, 2016 at 6:07 PM, Peter Maydell <peter.mayd...@linaro.org> 
>>> wrote:
>>>> On 25 January 2016 at 13:51, Ruslan Bilovol <ruslan.bilo...@gmail.com> 
>>>> wrote:
>>>>>> I'm trying to run AArch64 Big Endian image under QEMU that I built for
>>>>>> my x86-64 Ubuntu host from latest master branch and when I'm running
>>>>>> kernel I'm getting next error:
>>>>>>  > qemu: fatal: Trying to execute code outside RAM or ROM at 
>>>>>> 0x50020880
>>>>>>
>>>>>> Similar image built as Little Endian runs fine with same QEMU tool
>>>>>> (qemu-system-aarch64)
>>>>>>
>>>>>> So I'm wondering is it possible to run QEMU AArch64 Big Endian
>>>>>> emulation on x86-64 host?
>>>>
>>>> It is not currently supported, no. However there are some patches
>>>> on the list[*] to add this support, so I expect a future QEMU version
>>>> will do this.
>>>>
>>>> [*] https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03025.html
>>>
>>> Thank you four quick answer.
>>> I tried to apply this patch series to latest qemu master branch, but it
>>> fails to apply in misc places. Peter Crosthwaite, could you please say
>>> which commit ID is it based on?
>>>
>>
>> I pushed the branch just now to here:
>>
>> https://github.com/pcrost/qemu/tree/arm-be.next
>
> Thanks Peter.
>
> I've built qemu on this branch and tried to run it with my
> AArch64 Big Endian binaries but still get same error:
> "qemu: fatal: Trying to execute code outside RAM or
> ROM at 0x7fe60d8e0a30"
>
> So it looks like (unfortunately) these patches do not enable
> AArch64 BE support
>

You need to patch more information, including your QEMU command line
and possible a link to your binary. Are you using an ELF or a raw
image?

Regards,
Peter

> Best regards,
> Ruslan



Re: [Qemu-devel] [PATCH 02/12] Added reset-pin emulation in model.

2016-02-01 Thread Peter Crosthwaite
On Mon, Dec 21, 2015 at 5:39 AM, Krzeminski, Marcin (Nokia -
PL/Wroclaw) <marcin.krzemin...@nokia.com> wrote:
>
>
> W dniu 21.12.2015 o 12:04, Peter Crosthwaite pisze:
>> On Wed, Dec 16, 2015 at 4:57 AM,  <marcin.krzemin...@nokia.com> wrote:
>>> From: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>>>
>>> Signed-off-by: Marcin Krzeminski <marcin.krzemin...@nokia.com>
>>> ---
>>>  hw/block/m25p80.c | 38 +-
>>>  1 file changed, 37 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
>>> index bfd493f..bcb66a5 100644
>>> --- a/hw/block/m25p80.c
>>> +++ b/hw/block/m25p80.c
>>> @@ -258,6 +258,8 @@ typedef struct Flash {
>>>  uint8_t cmd_in_progress;
>>>  uint64_t cur_addr;
>>>  bool write_enable;
>>> +bool initialized;
>>> +uint8_t reset_pin;
>>>
>>>  int64_t dirty_page;
>>>
>>> @@ -430,6 +432,19 @@ static void complete_collecting_data(Flash *s)
>>>  }
>>>  }
>>>
>>> +static void reset_memory(Flash *s)
>>> +{
>>> +s->cmd_in_progress = NOP;
>>> +s->cur_addr = 0;
>>> +s->len = 0;
>>> +s->needed_bytes = 0;
>>> +s->pos = 0;
>>> +s->state = STATE_IDLE;
>>> +s->write_enable = false;
>>> +
>>> +DB_PRINT_L(0, "Reset done.\n");
>>> +}
>>> +
>>>  static void decode_new_cmd(Flash *s, uint32_t value)
>>>  {
>>>  s->cmd_in_progress = value;
>>> @@ -620,6 +635,8 @@ static int m25p80_init(SSISlave *ss)
>>>  s->size = s->pi->sector_size * s->pi->n_sectors;
>>>  s->dirty_page = -1;
>>>
>>> +s->initialized = false;
>>> +
>>
>> Init functions should never set runtime state.
>>
>>>  /* FIXME use a qdev drive property instead of drive_get_next() */
>>>  dinfo = drive_get_next(IF_MTD);
>>>
>>> @@ -650,9 +667,24 @@ static void m25p80_pre_save(void *opaque)
>>>  flash_sync_dirty((Flash *)opaque, -1);
>>>  }
>>>
>>> +static void m25p80_reset(DeviceState *d)
>>> +{
>>> +Flash *s = M25P80(d);
>>> +
>>> +if (s->reset_pin || !s->initialized) {
>>> +reset_memory(s);
>>> +s->initialized = true;
>>
>> Bus I think the real issue here is that is trying to model something
>> other than a power-on-reset. Looks like a a soft reset. the dc->reset
>> should be a power-on-reset and not be conditional on anything. Only
>> the non-volatile state (the storage data) should persist.
>>
>> Is your board using qemu_system_reset_request() by any chance for
>> something that is not supposed to reset the whole board? If this is
>> the case, you need to limit the scope of that reset logic and just set
>> your board up to not use the centralized all-devices reset (which is
>> pretty broken for these modern boards/SoCs that have multiple reset
>> domains).
>>
>> Regards,
>> Peter
> That is not exactly my case.
> I want to emulate device that have a RESET signal functionality (eg. n25q128 
> has such option).
> The other think that I want to have is possibility to use this signal by qemu 
> model
> (eg. pin is connected on board to reset IC, or it is unused).
> The use case: qemu boots us powered-up board, then I issue 
> qemu_system_reset_request().
> Then if the pin is connected (propeti is set, flash wil also reset, in other 
> case will not).

The "will not" case is what is divergent I think. If the flash does
not reset itself through qemu_system_reset_request, it is not a
power-on reset. I would avoid using qemu_system_reset_request() in the
case you mention and model the DC::reset as application of power to
the flash chip in isolation. The signal-driven reset you want to model
can share code with it but there should be no reliance on the init
function setting initial state or the reset changing behaviour based
on volatile state.

Regards,
Peter

> I don't see why it against reset signal implementation.
>
> Regards,
> Marcin
>
>>
>>> +}
>>> +}
>>> +
>>> +static Property m25p80_properties[] = {
>>> +DEFINE_PROP_UINT8("reset-pin", Flash, reset_pin, 0),
>>> +DEFINE_PROP_END_OF_LIST(),
>>> +};
>>> +
>>>  static const VMStateDescription vmstate_m25p80 = {
>>>  .name = "xilinx_spi",
>>> -.version_id = 1,
>>> +.version_id = 2,
>>>  .minimum_version_id = 1,
>>>  .pre_save = m25p80_pre_save,
>>>  .fields = (VMStateField[]) {
>>> @@ -664,6 +696,8 @@ static const VMStateDescription vmstate_m25p80 = {
>>>  VMSTATE_UINT8(cmd_in_progress, Flash),
>>>  VMSTATE_UINT64(cur_addr, Flash),
>>>  VMSTATE_BOOL(write_enable, Flash),
>>> +VMSTATE_BOOL(initialized, Flash),
>>> +VMSTATE_UINT8(reset_pin, Flash),
>>>  VMSTATE_END_OF_LIST()
>>>  }
>>>  };
>>> @@ -679,6 +713,8 @@ static void m25p80_class_init(ObjectClass *klass, void 
>>> *data)
>>>  k->set_cs = m25p80_cs;
>>>  k->cs_polarity = SSI_CS_LOW;
>>>  dc->vmsd = _m25p80;
>>> +dc->reset = _reset;
>>> +dc->props = m25p80_properties;
>>>  mc->pi = data;
>>>  }
>>>
>>> --
>>> 2.5.0
>>>
>>>
>>
>>
>



Re: [Qemu-devel] [PATCH v4 8/8] raspi: add raspberry pi 2 machine

2016-01-29 Thread Peter Crosthwaite
On Fri, Jan 29, 2016 at 2:28 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Friday, 29 January 2016 14:23
>>
>> On Fri, Jan 29, 2016 at 1:50 PM, Andrew Baumann
>> <andrew.baum...@microsoft.com> wrote:
>> > Hi Peter,
>> >
>> > Thanks for all the reviews. I should have a respun version on the list 
>> > shortly.
>> There's one minor change to this last patch:
>> >
>> >> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> >> Sent: Thursday, 28 January 2016 23:31
>> >> > On Fri, Jan 15, 2016 at 3:58 PM, Andrew Baumann
>> <andrew.baum...@microsoft.com> wrote:
>> >  [...]
>> >> > +typedef struct RaspiState {
>> >>
>> >> A quick google search, I see the camel case form for rpi is usually
>> >> "RasPi". Should we follow?
>> >
>> > Ok.
>> >
>> >> > +union {
>> >>
>> >> union not needed.
>> >
>> > I know it's not needed now, but it will be as soon as we add pi1, which I
>> hope to address in the next patch series. It will make that diff cleaner if 
>> we
>> keep this here now, so I'm going to leave it as-is. I hope that's ok with 
>> you.
>> >
>>
>> It sounds like you are implementing an inheritance outside QOM. I'm
>> not sure about this, can we just drop the union and figure it out on
>> the next series?
>
> It's nothing nearly that clever/complicated. See 
> https://github.com/0xabu/qemu/blob/raspi/hw/arm/raspi.c#L116
>
> switch (version) {
> case 1:
> object_initialize(>soc.pi1, sizeof(s->soc.pi1), TYPE_BCM2835);
> break;
> case 2:
> object_initialize(>soc.pi2, sizeof(s->soc.pi2), TYPE_BCM2836);
> break;
> }
>
> And then later, we always refer simply to OBJECT(>soc). I suppose I could 
> use a generic Object pointer instead, and allocate the soc-specific type 
> elsewhere, but it seemed simpler with the union.
>

But this is effectively an upcast to an abstract type, here:

+
+/* Setup the SOC */
+object_property_add_const_link(OBJECT(>soc), "ram", OBJECT(>ram),
+   _abort);
+object_property_set_int(OBJECT(>soc), smp_cpus, "enabled-cpus",
+_abort);

Where that concrete type musts implement "ram" and "enabled-cpus". So
I am unsure of having a split implementation of "ram", "enabled-cpus"
etc from one SoC to the other as you are using a QOM property name as
an abstract interface definition.

Regards,
Peter

> Andrew



Re: [Qemu-devel] [PATCH v4 8/8] raspi: add raspberry pi 2 machine

2016-01-29 Thread Peter Crosthwaite
On Fri, Jan 29, 2016 at 1:50 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
> Hi Peter,
>
> Thanks for all the reviews. I should have a respun version on the list 
> shortly. There's one minor change to this last patch:
>
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Thursday, 28 January 2016 23:31
>> > On Fri, Jan 15, 2016 at 3:58 PM, Andrew Baumann 
>> > <andrew.baum...@microsoft.com> wrote:
>  [...]
>> > +typedef struct RaspiState {
>>
>> A quick google search, I see the camel case form for rpi is usually
>> "RasPi". Should we follow?
>
> Ok.
>
>> > +union {
>>
>> union not needed.
>
> I know it's not needed now, but it will be as soon as we add pi1, which I 
> hope to address in the next patch series. It will make that diff cleaner if 
> we keep this here now, so I'm going to leave it as-is. I hope that's ok with 
> you.
>

It sounds like you are implementing an inheritance outside QOM. I'm
not sure about this, can we just drop the union and figure it out on
the next series?

Regards,
Peter

> Thanks,
> Andrew



Re: [Qemu-devel] [PATCH v4 7/8] arm/boot: move highbank secure board setup code to common routine

2016-01-28 Thread Peter Crosthwaite
On Fri, Jan 15, 2016 at 3:58 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
> The new version is slightly different, to support Rasbperry Pi (in
> particular, Pi1's arm11 core which doesn't support v7 instructions
> such as MOVW).
>
> Signed-off-by: Andrew Baumann <andrew.baum...@microsoft.com>
> ---
>
> Notes:
> This has not yet been tested on Highbank! Peter C -- please help :)
>

qemu-system-arm -kernel
/home/pcrost/poky/build/tmp/deploy/images/qemuarm/zImage -dtb
/home/pcrost/poky/build/tmp/deploy/images/qemuarm/zImage-highbank.dtb
-device ide-drive,drive=sata,bus=ide.0 -M highbank --no-reboot -drive
file=/home/pcrost/poky/build/tmp/deploy/images/qemuarm/core-image-minimal-qemuarm-20160114031411.rootfs.ext4,if=none,id=sata,format=raw
-no-reboot -nographic -m 128 -serial mon:stdio -serial null --append
"console=tty console=ttyAMA0,115200 ip=dhcp mem=128M highres=off
root=/dev/sda rw rootfstype=ext4 console=ttyS0"
[0.00] Booting Linux on physical CPU 0x0
[0.00] Linux version 4.2.1 (pcrost@pcrost-box) (gcc version
5.2.0 (GCC) ) #1 SMP Wed Jan 13 19:43:13 PST 2016
[0.00] CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
[0.00] CPU: PIPT / VIPT nonaliasing data cache, VIPT
nonaliasing instruction cache
[0.00] Machine model: Calxeda Highbank
[0.00] cma: Failed to reserve 64 MiB
[0.00] Memory policy: Data cache writeback
[0.00] DT missing boot CPU MPIDR[23:0], fall back to default
cpu_logical_map
[0.00] psci: probing for conduit method from DT.
[0.00] psci: Using PSCI v0.1 Function IDs from DT
[0.00] CPU: All CPU(s) started in SVC mode.
...
[4.263064] random: dd urandom read with 84 bits of entropy available
[7.103537] random: nonblocking pool is initialized
[9.286935] uart-pl011 fff36000.serial: no DMA platform data

Poky (Yocto Project Reference Distro) 2.0 qemuarm /dev/ttyAMA0

qemuarm login: root
root@qemuarm:~# uname -a
Linux qemuarm 4.2.1 #1 SMP Wed Jan 13 19:43:13 PST 2016 armv7l GNU/Linux
root@qemuarm:~#

Tested-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

> Honestly, I fear that the overhead of maintaining support for two very
> different platforms (including Pi1) may outweigh the value of unifying
> these blobs.
>

Having a look at the new code it is more robust than the original in
its own right with the separation of the blobs.

>  hw/arm/boot.c| 53 
> 
>  hw/arm/highbank.c| 37 ++--
>  include/hw/arm/arm.h |  5 +
>  3 files changed, 60 insertions(+), 35 deletions(-)
>
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index 75f69bf..bc1ea4d 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -178,6 +178,59 @@ static void default_write_secondary(ARMCPU *cpu,
>   smpboot, fixupcontext);
>  }
>
> +void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
> +const struct arm_boot_info *info,
> +hwaddr mvbar_addr)
> +{
> +int n;
> +uint32_t mvbar_blob[] = {
> +/* mvbar_addr: secure monitor vectors
> + * Default unimplemented and unused vectors to spin. Makes it
> + * easier to debug (as opposed to the CPU running away).
> + */
> +0xEAFE, /* (spin) */
> +0xEAFE, /* (spin) */
> +0xE1B0F00E, /* movs pc, lr ;SMC exception return */
> +0xEAFE, /* (spin) */
> +0xEAFE, /* (spin) */
> +0xEAFE, /* (spin) */
> +0xEAFE, /* (spin) */
> +0xEAFE, /* (spin) */

The code currently in arm_boot uses lower case for hex constants so we
should preserve convention.

> +};
> +uint32_t board_setup_blob[] = {
> +/* board setup addr */
> +0xE3A00E00 + (mvbar_addr >> 4), /* mov r0, #mvbar_addr */
> +0xEE0C0F30, /* mcr p15, 0, r0, c12, c0, 1 ;set MVBAR */
> +0xEE110F11, /* mrc p15, 0, r0, c1 , c1, 0 ;read SCR */
> +0xE3800031, /* orr r0, #0x31  ;enable AW, FW, NS */
> +0xEE010F11, /* mcr p15, 0, r0, c1, c1, 0  ;write SCR */
> +0xE1A0100E, /* mov r1, lr ;save LR across SMC */
> +0xE1600070, /* smc #0 ;call monitor to flush 
> SCR */
> +0xE1A0F001, /* mov pc, r1 ;return */
> +};
> +
> +/* check that mvbar_addr is correctly aligned and relocatable (using 
> MOV) */
> +assert((mvbar_addr & 0x1f) == 0 && (mvbar_addr >> 4) < 0x100);
> +
> +/* check that these blobs don't overlap */
> +assert

Re: [Qemu-devel] [PATCH v4 8/8] raspi: add raspberry pi 2 machine

2016-01-28 Thread Peter Crosthwaite
 +static void reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
> +{
> +CPUState *cs = CPU(cpu);
> +cpu_set_pc(cs, info->smp_loader_start);
> +}
> +
> +static void setup_boot(MachineState *machine, int version, size_t ram_size)
> +{
> +static struct arm_boot_info binfo;
> +int r;
> +
> +binfo.board_id = raspi_boardid[version];
> +binfo.ram_size = ram_size;
> +binfo.nb_cpus = smp_cpus;
> +binfo.board_setup_addr = BOARDSETUP_ADDR;
> +binfo.write_board_setup = write_board_setup;
> +binfo.secure_board_setup = true;
> +binfo.secure_boot = true;
> +
> +/* Pi2 requires SMP setup */
> +if (version == 2) {
> +binfo.smp_loader_start = SMPBOOT_ADDR;
> +binfo.write_secondary_boot = write_smpboot;
> +binfo.secondary_cpu_reset_hook = reset_secondary;
> +}
> +
> +/* If the user specified a "firmware" image (e.g. UEFI), we bypass
> + * the normal Linux boot process
> + */
> +if (machine->firmware) {

Others on the qemu-arm list follow UEFI support better than I so Peter
or someone else should take a look at this section I think.

> +/* load the firmware image (typically kernel.img) */
> +r = load_image_targphys(machine->firmware, FIRMWARE_ADDR,
> +ram_size - FIRMWARE_ADDR);
> +if (r < 0) {
> +error_report("Failed to load firmware from %s", 
> machine->firmware);
> +exit(1);
> +}
> +
> +/* set variables so arm_load_kernel does the right thing */

This comment doesn't add too much. I think it can be dropped
(everything in a binfo is to make arm_load_kernel DTRT).

> +binfo.entry = FIRMWARE_ADDR;
> +binfo.firmware_loaded = true;
> +} else {
> +/* Just let arm_load_kernel do everything for us... */
> +binfo.kernel_filename = machine->kernel_filename;
> +binfo.kernel_cmdline = machine->kernel_cmdline;
> +binfo.initrd_filename = machine->initrd_filename;
> +}
> +
> +arm_load_kernel(ARM_CPU(first_cpu), );
> +}
> +
> +static void raspi2_init(MachineState *machine)
> +{
> +RaspiState *s = g_new0(RaspiState, 1);
> +
> +/* Initialise the SOC */

Drop comment.

> +object_initialize(>soc.pi2, sizeof(s->soc.pi2), TYPE_BCM2836);
> +object_property_add_child(OBJECT(machine), "soc", OBJECT(>soc),
> +  _abort);
> +
> +/* Allocate and map RAM */
> +memory_region_allocate_system_memory(>ram, OBJECT(machine), "ram",
> + machine->ram_size);

/* FIXME: Remove when we have custom CPU address space support */

> +memory_region_add_subregion_overlap(get_system_memory(), 0, >ram, 0);
> +
> +/* Setup the SOC */
> +object_property_add_const_link(OBJECT(>soc), "ram", OBJECT(>ram),
> +   _abort);
> +object_property_set_int(OBJECT(>soc), smp_cpus, "enabled-cpus",
> +_abort);
> +object_property_set_bool(OBJECT(>soc), true, "realized", 
> _abort);
> +
> +/* Prepare to boot */

Comment still doesn't add much so should drop.

Otherwise:

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Thanks for your continued persistence and sorry about the recent
delays through review process.

Regards,
Peter

> +setup_boot(machine, 2, machine->ram_size);
> +}
> +
> +static void raspi2_machine_init(MachineClass *mc)
> +{
> +mc->desc = "Raspberry Pi 2";
> +mc->init = raspi2_init;
> +mc->block_default_type = IF_SD;
> +mc->no_parallel = 1;
> +mc->no_floppy = 1;
> +mc->no_cdrom = 1;
> +mc->max_cpus = BCM2836_NCPUS;
> +
> +/* XXX: Temporary restriction in RAM size from the full 1GB. Since
> + * we do not yet support the framebuffer / GPU, we need to limit
> + * RAM usable by the OS to sit below the peripherals.
> + */
> +mc->default_ram_size = 0x3F00; /* BCM2836_PERI_BASE */
> +};
> +DEFINE_MACHINE("raspi2", raspi2_machine_init)
> --
> 2.5.3
>



Re: [Qemu-devel] [PATCH v4 5/8] bcm2836_control: add bcm2836 ARM control logic

2016-01-28 Thread Peter Crosthwaite
   if (s->timerirqs[i]) {
> +assert(s->timerirqs[i] < (1 << IRQ_MAILBOX0)); /* sanity check */
> +for (j = 0; j < IRQ_MAILBOX0; j++) {

I think <= IRQ_CNTVIRQ is cleaner, as it keeps "MAILBOX" out of the timer code.

> +if ((s->timerirqs[i] & (1 << j)) != 0) {
> +/* local interrupt j is set */
> +deliver_local(s, i, j, s->timercontrol[i], j);
> +}
> +}
> +}
> +
> +/* handle mailboxes for this core */
> +for (j = 0; j < BCM2836_MBPERCORE; j++) {
> +if (s->mailboxes[i * BCM2836_MBPERCORE + j] != 0) {
> +/* mailbox j is set */
> +deliver_local(s, i, j + IRQ_MAILBOX0, s->mailboxcontrol[i], 
> j);
> +}
> +}
> +}
> +
> +/* call set_irq appropriately for each output */
> +for (i = 0; i < BCM2836_NCORES; i++) {
> +qemu_set_irq(s->irq[i], s->irqsrc[i] != 0);
> +qemu_set_irq(s->fiq[i], s->fiqsrc[i] != 0);
> +}
> +}
> +
> +static void bcm2836_control_set_local_irq(void *opaque, int core, int 
> local_irq,
> +  int level)
> +{
> +BCM2836ControlState *s = opaque;
> +
> +assert(core >= 0 && core < BCM2836_NCORES);
> +assert(local_irq >= 0 && local_irq <= IRQ_CNTVIRQ);

Continuing above, this is inconsistent with the above where you use <
IRQ_MAILBOX0 instead for the same check.

> +
> +s->timerirqs[core] = deposit32(s->timerirqs[core], local_irq, 1, 
> !!level);
> +
> +bcm2836_control_update(s);
> +}
> +
> +/* XXX: the following wrapper functions are a kludgy workaround,
> + * needed because I can't seem to pass useful information in the "irq"
> + * parameter when using named interrupts. Feel free to clean this up!
> + */
> +
> +static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
> +{
> +bcm2836_control_set_local_irq(opaque, core, 0, level);
> +}
> +
> +static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
> +{
> +bcm2836_control_set_local_irq(opaque, core, 1, level);
> +}
> +
> +static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
> +{
> +bcm2836_control_set_local_irq(opaque, core, 2, level);
> +}
> +
> +static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
> +{
> +bcm2836_control_set_local_irq(opaque, core, 3, level);
> +}
> +

> +OBJECT_CHECK(BCM2836ControlState, (obj), TYPE_BCM2836_CONTROL)
> +
> +typedef struct BCM2836ControlState {
> +/*< private >*/
> +SysBusDevice busdev;
> +/*< public >*/
> +MemoryRegion iomem;
> +

> +/* interrupt status registers (not directly visible to user) */
> +bool gpu_irq, gpu_fiq;
> +uint8_t timerirqs[BCM2836_NCORES];
> +

This ...

> +/* mailboxes */
> +uint32_t mailboxes[BCM2836_NCORES * BCM2836_MBPERCORE];
> +
> +/* interrupt routing/control registers */
> +uint8_t route_gpu_irq, route_gpu_fiq;
> +uint32_t timercontrol[BCM2836_NCORES];
> +uint32_t mailboxcontrol[BCM2836_NCORES];
> +

> +/* interrupt source registers, post-routing (visible) */
> +uint32_t irqsrc[BCM2836_NCORES];
> +uint32_t fiqsrc[BCM2836_NCORES];
> +

And this are absent from the VMSD, but after some thought they don't
need to be as they are pure functions of the input pin state that is
always refreshable from other state no? I would these together with a
brief comment as to the above, and keep the migratable state (genuine
device state) all together.

Otherwise,

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Regards,
Peter

> +/* outputs to CPU cores */
> +qemu_irq irq[BCM2836_NCORES];
> +qemu_irq fiq[BCM2836_NCORES];
> +} BCM2836ControlState;
> +
> +#endif
> --
> 2.5.3
>



Re: [Qemu-devel] [PATCH v4 6/8] bcm2836: add bcm2836 soc device

2016-01-28 Thread Peter Crosthwaite
>control), "gpu-irq", 0));
> +sysbus_connect_irq(SYS_BUS_DEVICE(>peripherals), 1,
> +qdev_get_gpio_in_named(DEVICE(>control), "gpu-fiq", 0));
> +
> +for (n = 0; n < BCM2836_NCPUS; n++) {
> +/* Mirror bcm2836, which has clusterid set to 0xf
> + * TODO: this should be converted to a property of ARM_CPU
> + */
> +s->cpus[n].mp_affinity = 0xF00 | n;
> +
> +/* set periphbase/CBAR value for CPU-local registers */
> +object_property_set_int(OBJECT(>cpus[n]),
> +BCM2836_PERI_BASE + MCORE_OFFSET,
> +"reset-cbar", );
> +if (err) {
> +error_propagate(errp, err);
> +return;
> +}
> +
> +/* start powered off if not enabled */
> +object_property_set_bool(OBJECT(>cpus[n]), n >= s->enabled_cpus,
> + "start-powered-off", );
> +if (err) {
> +error_propagate(errp, err);
> +return;
> +}
> +
> +object_property_set_bool(OBJECT(>cpus[n]), true, "realized", 
> );
> +if (err) {
> +error_propagate(errp, err);
> +return;
> +}
> +
> +/* Connect irq/fiq outputs from the interrupt controller. */
> +qdev_connect_gpio_out_named(DEVICE(>control), "irq", n,
> +qdev_get_gpio_in(DEVICE(>cpus[n]), ARM_CPU_IRQ));
> +qdev_connect_gpio_out_named(DEVICE(>control), "fiq", n,
> +qdev_get_gpio_in(DEVICE(>cpus[n]), ARM_CPU_FIQ));
> +
> +/* Connect timers from the CPU to the interrupt controller */
> +s->cpus[n].gt_timer_outputs[GTIMER_PHYS]
> += qdev_get_gpio_in_named(DEVICE(>control), "cntpsirq", 0);
> +s->cpus[n].gt_timer_outputs[GTIMER_VIRT]
> += qdev_get_gpio_in_named(DEVICE(>control), "cntvirq", 0);

ARM CPU has

qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs,
   ARRAY_SIZE(cpu->gt_timer_outputs));

So you should be able to use qdev_connect_gpio_out rather than direct
assignment.

> +}
> +}
> +
> +static Property bcm2836_props[] = {
> +DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, 
> BCM2836_NCPUS),
> +DEFINE_PROP_END_OF_LIST()
> +};
> +
> +static void bcm2836_class_init(ObjectClass *oc, void *data)
> +{
> +DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +dc->props = bcm2836_props;
> +dc->realize = bcm2836_realize;
> +
> +/*
> + * Reason: creates an ARM CPU, thus use after free(), see
> + * arm_cpu_class_init()
> + */
> +dc->cannot_destroy_with_object_finalize_yet = true;
> +}
> +
> +static const TypeInfo bcm2836_type_info = {
> +.name = TYPE_BCM2836,
> +.parent = TYPE_SYS_BUS_DEVICE,
> +.instance_size = sizeof(BCM2836State),
> +.instance_init = bcm2836_init,
> +.class_init = bcm2836_class_init,
> +};
> +
> +static void bcm2836_register_types(void)
> +{
> +type_register_static(_type_info);
> +}
> +
> +type_init(bcm2836_register_types)
> diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
> new file mode 100644
> index 000..cd0fd02
> --- /dev/null
> +++ b/include/hw/arm/bcm2836.h
> @@ -0,0 +1,34 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
> + *
> + * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
> + * Written by Andrew Baumann
> + *
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2836_H
> +#define BCM2836_H
> +
> +#include "hw/arm/arm.h"
> +#include "hw/arm/bcm2835_peripherals.h"
> +#include "hw/intc/bcm2836_control.h"
> +
> +#define TYPE_BCM2836 "bcm2836"
> +#define BCM2836(obj) OBJECT_CHECK(BCM2836State, (obj), TYPE_BCM2836)
> +
> +#define BCM2836_NCPUS 4
> +
> +typedef struct BCM2836State {
> +/*< private >*/
> +DeviceState parent_obj;
> +/*< public >*/
> +
> +uint32_t enabled_cpus;

blank line here.

Otherwise,

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Regards,
Peter

> +ARMCPU cpus[BCM2836_NCPUS];
> +BCM2836ControlState control;
> +BCM2835PeripheralState peripherals;
> +} BCM2836State;
> +
> +#endif /* BCM2836_H */
> --
> 2.5.3
>



Re: [Qemu-devel] [Qemu-arm] Does QEMU support AArch64 Big Endian emulation on x86-64 host?

2016-01-27 Thread Peter Crosthwaite
On Tue, Jan 26, 2016 at 4:05 AM, Ruslan Bilovol
<ruslan.bilo...@gmail.com> wrote:
> On Mon, Jan 25, 2016 at 6:07 PM, Peter Maydell <peter.mayd...@linaro.org> 
> wrote:
>> On 25 January 2016 at 13:51, Ruslan Bilovol <ruslan.bilo...@gmail.com> wrote:
>>>> I'm trying to run AArch64 Big Endian image under QEMU that I built for
>>>> my x86-64 Ubuntu host from latest master branch and when I'm running
>>>> kernel I'm getting next error:
>>>>  > qemu: fatal: Trying to execute code outside RAM or ROM at 
>>>> 0x50020880
>>>>
>>>> Similar image built as Little Endian runs fine with same QEMU tool
>>>> (qemu-system-aarch64)
>>>>
>>>> So I'm wondering is it possible to run QEMU AArch64 Big Endian
>>>> emulation on x86-64 host?
>>
>> It is not currently supported, no. However there are some patches
>> on the list[*] to add this support, so I expect a future QEMU version
>> will do this.
>>
>> [*] https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03025.html
>
> Thank you four quick answer.
> I tried to apply this patch series to latest qemu master branch, but it
> fails to apply in misc places. Peter Crosthwaite, could you please say
> which commit ID is it based on?
>

I pushed the branch just now to here:

https://github.com/pcrost/qemu/tree/arm-be.next

Regards,
Peter

> Thanks,
> Ruslan Bilovol



Re: [Qemu-devel] [PATCH v4 4/8] bcm2835_peripherals: add rollup device for bcm2835 peripherals

2016-01-26 Thread Peter Crosthwaite
On Mon, Jan 25, 2016 at 10:23 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Monday, 25 January 2016 22:14
>>
>> On Fri, Jan 15, 2016 at 3:58 PM, Andrew Baumann
>> <andrew.baum...@microsoft.com> wrote:
> [...]
>> > +static void bcm2835_peripherals_init(Object *obj)
>> > +{
>> > +BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
>> > +
>> > +/* Memory region for peripheral devices, which we export to our
>> parent */
>> > +memory_region_init_io(>peri_mr, obj, NULL, s, "bcm2835-
>> peripherals",
>> > +  0x100);
>>
>> Should this just be normal memory_region_init?
>
> I think so -- it's just a container region, and I probably copy and pasted 
> the API here. The two MR init APIs seem almost but not-quite identical when 
> NULL callbacks are used. Can you briefly explain the difference?
>

hmm I guess the defaulting to _mem_ops. memory_region_init
looks to assume you will populate the usable subregions. Are you
relying on unassigned ops?

>> > +object_property_add_child(obj, "peripheral-io", OBJECT(>peri_mr),
>> NULL);
>>
>> This seems like a weird parenting, to have the SoC as child to an
>> object it just created. Is the problem you need a parent before others
>> can parent to you?
>
> I'm confused by this question: Unless I'm mistaken, the parent here is 
> BCM2835PeripheralState, the child is the new memory region we just called 
> init on.
>

My bad - I have it backwards.

Regards,
Peter

> Thanks,
> Andrew



Re: [Qemu-devel] [PATCH v4 2/8] bcm2835_property: add bcm2835 property channel

2016-01-25 Thread Peter Crosthwaite
On Fri, Jan 15, 2016 at 3:58 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
> This sits behind the mailbox interface, and implements
> request/response queries for system properties. The
> framebuffer-related properties will be added in a later patch.
>
> Signed-off-by: Andrew Baumann <andrew.baum...@microsoft.com>
> ---
>
> Notes:
> v4:
> * added LOG_UNIMP as appropriate
> * use qemu_macaddr_default_if_unset to allocate a MAC address, and 
> dma_memory_write to write it
> * assert that we're not pending, rather than dropping a request on the 
> floor
>
>  hw/misc/Makefile.objs  |   1 +
>  hw/misc/bcm2835_property.c | 286 
> +
>  include/hw/misc/bcm2835_property.h |  31 
>  3 files changed, 318 insertions(+)
>  create mode 100644 hw/misc/bcm2835_property.c
>  create mode 100644 include/hw/misc/bcm2835_property.h
>
> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
> index d0ea105..ea6cd3c 100644
> --- a/hw/misc/Makefile.objs
> +++ b/hw/misc/Makefile.objs
> @@ -37,6 +37,7 @@ obj-$(CONFIG_OMAP) += omap_l4.o
>  obj-$(CONFIG_OMAP) += omap_sdrc.o
>  obj-$(CONFIG_OMAP) += omap_tap.o
>  obj-$(CONFIG_RASPI) += bcm2835_mbox.o
> +obj-$(CONFIG_RASPI) += bcm2835_property.o
>  obj-$(CONFIG_SLAVIO) += slavio_misc.o
>  obj-$(CONFIG_ZYNQ) += zynq_slcr.o
>  obj-$(CONFIG_ZYNQ) += zynq-xadc.o
> diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
> new file mode 100644
> index 000..52c9b8d
> --- /dev/null
> +++ b/hw/misc/bcm2835_property.c
> @@ -0,0 +1,286 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#include "hw/misc/bcm2835_property.h"
> +#include "hw/misc/bcm2835_mbox_defs.h"
> +#include "sysemu/dma.h"
> +
> +/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
> +
> +static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t 
> value)
> +{
> +uint32_t tag;
> +uint32_t bufsize;
> +uint32_t tot_len;
> +size_t resplen;
> +uint32_t tmp;
> +
> +value &= ~0xf;
> +
> +s->addr = value;
> +
> +tot_len = ldl_phys(>dma_as, value);
> +
> +/* @(addr + 4) : Buffer response code */
> +value = s->addr + 8;
> +while (value + 8 <= s->addr + tot_len) {
> +tag = ldl_phys(>dma_as, value);
> +bufsize = ldl_phys(>dma_as, value + 4);
> +/* @(value + 8) : Request/response indicator */
> +resplen = 0;
> +switch (tag) {
> +case 0x: /* End tag */
> +break;
> +case 0x0001: /* Get firmware revision */
> +stl_phys(>dma_as, value + 12, 346337);
> +resplen = 4;
> +break;
> +case 0x00010001: /* Get board model */
> +qemu_log_mask(LOG_UNIMP,
> +  "bcm2835_property: %x get board model NYI\n", tag);
> +resplen = 4;
> +break;
> +case 0x00010002: /* Get board revision */
> +qemu_log_mask(LOG_UNIMP,
> +  "bcm2835_property: %x get board revision NYI\n", 
> tag);
> +resplen = 4;
> +break;
> +case 0x00010003: /* Get board MAC address */
> +resplen = sizeof(s->macaddr.a);
> +dma_memory_write(>dma_as, value + 12, s->macaddr.a, resplen);
> +break;
> +case 0x00010004: /* Get board serial */
> +qemu_log_mask(LOG_UNIMP,
> +  "bcm2835_property: %x get board serial NYI\n", 
> tag);
> +resplen = 8;
> +break;
> +case 0x00010005: /* Get ARM memory */
> +/* base */
> +stl_phys(>dma_as, value + 12, 0);
> +    /* size */
> +stl_phys(>dma_as, value + 16, s->ram_size);
> +resplen = 8;
> +break;
> +case 0x00028001: /* Set power state */
> +/* Assume that whatever device they asked for exists,
> + * and we'll just claim we set it to the desired state */

blank before */

A grep on "^\+[ \t]*\*.*\*\/$" on the patch series will catch-all.

Otherwise,

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Regards,
Peter

> +tmp = ldl_phys(>dma_as, value + 16);
> +stl_phys(>dma_as, value + 16, (tmp & 1));
> +resplen = 8;
> +break;
> +
> +/* Clocks */
> +
> +case 0x0003

Re: [Qemu-devel] [PATCH v4 1/8] bcm2835_mbox: add BCM2835 mailboxes

2016-01-25 Thread Peter Crosthwaite
ENDING)) {
> +/* Child busy, push delayed. Push it in the arm->vc mbox 
> */
> +mbox_push(>mbox[1], value);
> +} else {
> +/* Push it directly to the child device */
> +stl_phys(>mbox_as, childaddr, value);
> +}
> +} else {
> +/* Invalid channel number */
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid channel %u\n",
> +  __func__, ch);
> +}
> +}
> +break;
> +
> +default:
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +  __func__, offset);
> +return;
> +}
> +
> +bcm2835_mbox_update(s);
> +}
> +
> +static const MemoryRegionOps bcm2835_mbox_ops = {
> +.read = bcm2835_mbox_read,
> +.write = bcm2835_mbox_write,
> +.endianness = DEVICE_NATIVE_ENDIAN,
> +.valid.min_access_size = 4,
> +.valid.max_access_size = 4,
> +};
> +
> +/* vmstate of a single mailbox */
> +static const VMStateDescription vmstate_bcm2835_mbox_box = {
> +.name = TYPE_BCM2835_MBOX "_box",
> +.version_id = 1,
> +.minimum_version_id = 1,
> +.fields = (VMStateField[]) {
> +VMSTATE_UINT32_ARRAY(reg, BCM2835Mbox, MBOX_SIZE),
> +VMSTATE_UINT32(count, BCM2835Mbox),
> +VMSTATE_UINT32(status, BCM2835Mbox),
> +VMSTATE_UINT32(config, BCM2835Mbox),
> +VMSTATE_END_OF_LIST()
> +}
> +};
> +
> +/* vmstate of the entire device */
> +static const VMStateDescription vmstate_bcm2835_mbox = {
> +.name = TYPE_BCM2835_MBOX,
> +.version_id = 1,
> +.minimum_version_id = 1,
> +.minimum_version_id_old = 1,
> +.fields  = (VMStateField[]) {
> +VMSTATE_BOOL_ARRAY(available, BCM2835MboxState, MBOX_CHAN_COUNT),
> +VMSTATE_STRUCT_ARRAY(mbox, BCM2835MboxState, 2, 1,
> + vmstate_bcm2835_mbox_box, BCM2835Mbox),
> +VMSTATE_END_OF_LIST()
> +}
> +};
> +
> +static void bcm2835_mbox_init(Object *obj)
> +{
> +BCM2835MboxState *s = BCM2835_MBOX(obj);
> +
> +memory_region_init_io(>iomem, obj, _mbox_ops, s,
> +  TYPE_BCM2835_MBOX, 0x400);
> +sysbus_init_mmio(SYS_BUS_DEVICE(s), >iomem);
> +sysbus_init_irq(SYS_BUS_DEVICE(s), >arm_irq);
> +qdev_init_gpio_in(DEVICE(s), bcm2835_mbox_set_irq, MBOX_CHAN_COUNT);
> +}
> +
> +static void bcm2835_mbox_reset(DeviceState *dev)
> +{
> +BCM2835MboxState *s = BCM2835_MBOX(dev);
> +int n;
> +
> +mbox_reset(>mbox[0]);
> +mbox_reset(>mbox[1]);
> +s->mbox_irq_disabled = false;
> +for (n = 0; n < MBOX_CHAN_COUNT; n++) {
> +s->available[n] = false;
> +}
> +}
> +
> +static void bcm2835_mbox_realize(DeviceState *dev, Error **errp)
> +{
> +BCM2835MboxState *s = BCM2835_MBOX(dev);
> +Object *obj;
> +Error *err = NULL;
> +
> +obj = object_property_get_link(OBJECT(dev), "mbox-mr", );
> +if (obj == NULL) {
> +error_setg(errp, "%s: required mbox-mr link not found: %s",
> +   __func__, error_get_pretty(err));
> +return;
> +}
> +
> +s->mbox_mr = MEMORY_REGION(obj);
> +address_space_init(>mbox_as, s->mbox_mr, NULL);
> +bcm2835_mbox_reset(dev);
> +}
> +
> +static void bcm2835_mbox_class_init(ObjectClass *klass, void *data)
> +{
> +DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +dc->realize = bcm2835_mbox_realize;
> +dc->reset = bcm2835_mbox_reset;
> +dc->vmsd = _bcm2835_mbox;
> +}
> +
> +static TypeInfo bcm2835_mbox_info = {
> +.name  = TYPE_BCM2835_MBOX,
> +.parent= TYPE_SYS_BUS_DEVICE,
> +.instance_size = sizeof(BCM2835MboxState),
> +.class_init= bcm2835_mbox_class_init,
> +.instance_init = bcm2835_mbox_init,
> +};
> +
> +static void bcm2835_mbox_register_types(void)
> +{
> +type_register_static(_mbox_info);
> +}
> +
> +type_init(bcm2835_mbox_register_types)
> diff --git a/include/hw/misc/bcm2835_mbox.h b/include/hw/misc/bcm2835_mbox.h
> new file mode 100644
> index 000..32ae077
> --- /dev/null
> +++ b/include/hw/misc/bcm2835_mbox.h
> @@ -0,0 +1,37 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2835_MBOX_H
> +#define BCM2835_MBOX_H
> +
> +#include "bcm2835_mbox_defs.h"
> +#include "hw/sysbus.h"

Re: [Qemu-devel] [PATCH v4 4/8] bcm2835_peripherals: add rollup device for bcm2835 peripherals

2016-01-25 Thread Peter Crosthwaite
On Fri, Jan 15, 2016 at 3:58 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
> This device maintains all the non-CPU peripherals on bcm2835 (Pi1)
> which are also present on bcm2836 (Pi2). It also implements the
> private address spaces used for DMA and mailboxes.
>
> Signed-off-by: Andrew Baumann <andrew.baum...@microsoft.com>
> ---
>
> Notes:
> v3:
>  * clean up raspi_platform.h
>  * s/_/-/ in type/property/child names
>  * use memory_region_init where appropriate rather than 
> memory_region_init_io
>  * pass ram as link property
>
> v2:
>  * adapted to use common SDHCI emulation
>
>  hw/arm/Makefile.objs |   1 +
>  hw/arm/bcm2835_peripherals.c | 205 
> +++
>  include/hw/arm/bcm2835_peripherals.h |  42 +++
>  include/hw/arm/raspi_platform.h  | 128 ++
>  4 files changed, 376 insertions(+)
>  create mode 100644 hw/arm/bcm2835_peripherals.c
>  create mode 100644 include/hw/arm/bcm2835_peripherals.h
>  create mode 100644 include/hw/arm/raspi_platform.h
>
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index 2195b60..82cc142 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -11,6 +11,7 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o 
> pxa2xx_pic.o
>  obj-$(CONFIG_DIGIC) += digic.o
>  obj-y += omap1.o omap2.o strongarm.o
>  obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
> +obj-$(CONFIG_RASPI) += bcm2835_peripherals.o
>  obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
>  obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
>  obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
> new file mode 100644
> index 000..879a41d
> --- /dev/null
> +++ b/hw/arm/bcm2835_peripherals.c
> @@ -0,0 +1,205 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
> + *
> + * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
> + * Written by Andrew Baumann
> + *
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#include "hw/arm/bcm2835_peripherals.h"
> +#include "hw/misc/bcm2835_mbox_defs.h"
> +#include "hw/arm/raspi_platform.h"
> +
> +/* Peripheral base address on the VC (GPU) system bus */
> +#define BCM2835_VC_PERI_BASE 0x7e00
> +
> +/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
> +#define BCM2835_SDHC_CAPAREG 0x52034b4
> +
> +static void bcm2835_peripherals_init(Object *obj)
> +{
> +BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
> +
> +/* Memory region for peripheral devices, which we export to our parent */
> +memory_region_init_io(>peri_mr, obj, NULL, s, "bcm2835-peripherals",
> +  0x100);

Should this just be normal memory_region_init?

> +object_property_add_child(obj, "peripheral-io", OBJECT(>peri_mr), 
> NULL);

This seems like a weird parenting, to have the SoC as child to an
object it just created. Is the problem you need a parent before others
can parent to you?

Otherwise,

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

Regards,
Peter

> +sysbus_init_mmio(SYS_BUS_DEVICE(s), >peri_mr);
> +
> +/* Internal memory region for peripheral bus addresses (not exported) */
> +memory_region_init(>gpu_bus_mr, obj, "bcm2835-gpu", (uint64_t)1 << 
> 32);
> +object_property_add_child(obj, "gpu-bus", OBJECT(>gpu_bus_mr), NULL);
> +
> +/* Internal memory region for request/response communication with
> + * mailbox-addressable peripherals (not exported)
> + */
> +memory_region_init(>mbox_mr, obj, "bcm2835-mbox",
> +   MBOX_CHAN_COUNT << MBOX_AS_CHAN_SHIFT);
> +
> +/* Interrupt Controller */
> +object_initialize(>ic, sizeof(s->ic), TYPE_BCM2835_IC);
> +object_property_add_child(obj, "ic", OBJECT(>ic), NULL);
> +qdev_set_parent_bus(DEVICE(>ic), sysbus_get_default());
> +
> +/* UART0 */
> +s->uart0 = SYS_BUS_DEVICE(object_new("pl011"));
> +object_property_add_child(obj, "uart0", OBJECT(s->uart0), NULL);
> +qdev_set_parent_bus(DEVICE(s->uart0), sysbus_get_default());
> +
> +/* Mailboxes */
> +object_initialize(>mboxes, sizeof(s->mboxes), TYPE_BCM2835_MBOX);
> +object_property_add_child(obj, "mbox", OBJECT(>mboxes), NULL);
> +qdev_set_parent_bus

Re: [Qemu-devel] [PATCH v11 2/7] hw/ptimer: Perform counter wrap around if timer already expired

2016-01-23 Thread Peter Crosthwaite
On Thu, Jan 21, 2016 at 11:03 AM, Dmitry Osipenko <dig...@gmail.com> wrote:
> ptimer_get_count() might be called while QEMU timer already been expired.
> In that case ptimer would return counter = 0, which might be undesirable
> in case of polled timer. Do counter wrap around for periodic timer to keep
> it distributed. In order to achieve more accurate emulation behaviour of
> certain hardware, don't perform wrap around when in icount mode and return
> counter = 0 in that case (that doesn't affect polled counter distribution).
>
> Signed-off-by: Dmitry Osipenko <dig...@gmail.com>

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

> ---
>  hw/core/ptimer.c | 19 +--
>  1 file changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
> index 6dc1677..cb50d30 100644
> --- a/hw/core/ptimer.c
> +++ b/hw/core/ptimer.c
> @@ -83,14 +83,16 @@ static void ptimer_tick(void *opaque)
>
>  uint64_t ptimer_get_count(ptimer_state *s)
>  {
> -int64_t now;
>  uint64_t counter;
>
>  if (s->enabled) {
> -now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +int64_t next = s->next_event;
> +bool expired = (now - next >= 0);
> +bool oneshot = (s->enabled == 2);
> +
>  /* Figure out the current counter value.  */
> -if (now - s->next_event > 0
> -|| s->period == 0) {
> +if (s->period == 0 || (expired && (oneshot || use_icount))) {
>  /* Prevent timer underflowing if it should already have
> triggered.  */
>  counter = 0;
> @@ -102,7 +104,7 @@ uint64_t ptimer_get_count(ptimer_state *s)
>  uint32_t period_frac = s->period_frac;
>  uint64_t period = s->period;
>
> -if ((s->enabled == 1) && !use_icount && (s->delta * period < 
> 1)) {
> +if (!oneshot && (s->delta * period < 1) && !use_icount) {
>  period = 1 / s->delta;
>  period_frac = 0;
>  }
> @@ -117,7 +119,7 @@ uint64_t ptimer_get_count(ptimer_state *s)
> backwards.
>  */
>
> -rem = s->next_event - now;
> +rem = expired ? now - next : next - now;
>  div = period;
>
>  clz1 = clz64(rem);
> @@ -137,6 +139,11 @@ uint64_t ptimer_get_count(ptimer_state *s)
>  div += 1;
>  }
>  counter = rem / div;
> +
> +if (expired && (counter != 0)) {
> +/* Wrap around periodic counter.  */
> +counter = s->limit - counter % s->limit;
> +}
>  }
>  } else {
>  counter = s->delta;
> --
> 2.7.0
>



Re: [Qemu-devel] [PATCH v11 7/7] arm_mptimer: Convert to use ptimer

2016-01-23 Thread Peter Crosthwaite
On Thu, Jan 21, 2016 at 11:03 AM, Dmitry Osipenko  wrote:
> Current ARM MPTimer implementation uses QEMUTimer for the actual timer,
> this implementation isn't complete and mostly tries to duplicate of what
> generic ptimer is already doing fine.
>
> Conversion to ptimer brings the following benefits and fixes:
> - Simple timer pausing implementation
> - Fixes counter value preservation after stopping the timer
> - Correctly handles prescaler != 0 cases
> - Code simplification and reduction
>
> Bump VMSD to version 3, since VMState is changed and is not compatible
> with the previous implementation.
>
> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/timer/arm_mptimer.c | 131 
> +
>  include/hw/timer/arm_mptimer.h |   5 +-
>  2 files changed, 67 insertions(+), 69 deletions(-)
>
> diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
> index 3e59c2a..a5f46df 100644
> --- a/hw/timer/arm_mptimer.c
> +++ b/hw/timer/arm_mptimer.c
> @@ -19,8 +19,9 @@
>   * with this program; if not, see .
>   */
>
> +#include "hw/ptimer.h"
>  #include "hw/timer/arm_mptimer.h"
> -#include "qemu/timer.h"
> +#include "qemu/main-loop.h"
>  #include "qom/cpu.h"
>
>  /* This device implements the per-cpu private timer and watchdog block
> @@ -42,33 +43,34 @@ static inline void timerblock_update_irq(TimerBlock *tb)
>  }
>
>  /* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
> -static inline uint32_t timerblock_scale(TimerBlock *tb)
> +static inline uint32_t timerblock_scale(uint32_t control)
>  {
> -return (((tb->control >> 8) & 0xff) + 1) * 10;
> +return (((control >> 8) & 0xff) + 1) * 10;
>  }
>
> -static void timerblock_reload(TimerBlock *tb, int restart)
> +static inline void timerblock_set_count(struct ptimer_state *timer,
> +uint32_t control, uint64_t *count)
>  {
> -if (tb->count == 0) {
> -return;
> +/* PTimer would immediately trigger interrupt for periodic timer
> + * when counter set to 0, MPtimer under certain condition only.  */

newline before */

> +if ((control & 3) == 3 && (*count == 0) && (control & 0xff00) == 0) {
> +*count = ptimer_get_limit(timer);
>  }
> -if (restart) {
> -tb->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +ptimer_set_count(timer, *count);
> +}
> +
> +static inline void timerblock_run(struct ptimer_state *timer, uint32_t 
> control,
> +  bool cond)

drop cond ...

> +{
> +if (cond) {

... control & 1 ...

> +ptimer_run(timer, !(control & 2));
>  }
> -tb->tick += (int64_t)tb->count * timerblock_scale(tb);
> -timer_mod(tb->timer, tb->tick);
>  }
>
>  static void timerblock_tick(void *opaque)
>  {
>  TimerBlock *tb = (TimerBlock *)opaque;
>  tb->status = 1;
> -if (tb->control & 2) {
> -tb->count = tb->load;
> -timerblock_reload(tb, 0);
> -} else {
> -tb->count = 0;
> -}
>  timerblock_update_irq(tb);
>  }
>
> @@ -76,21 +78,11 @@ static uint64_t timerblock_read(void *opaque, hwaddr addr,
>  unsigned size)
>  {
>  TimerBlock *tb = (TimerBlock *)opaque;
> -int64_t val;
>  switch (addr) {
>  case 0: /* Load */
> -return tb->load;
> +return ptimer_get_limit(tb->timer);
>  case 4: /* Counter.  */
> -if (((tb->control & 1) == 0) || (tb->count == 0)) {
> -return 0;
> -}
> -/* Slow and ugly, but hopefully won't happen too often.  */
> -val = tb->tick - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> -val /= timerblock_scale(tb);
> -if (val < 0) {
> -val = 0;
> -}
> -return val;
> +return ptimer_get_count(tb->timer);
>  case 8: /* Control.  */
>  return tb->control;
>  case 12: /* Interrupt status.  */
> @@ -104,39 +96,51 @@ static void timerblock_write(void *opaque, hwaddr addr,
>   uint64_t value, unsigned size)
>  {
>  TimerBlock *tb = (TimerBlock *)opaque;
> -int64_t old;
> +uint32_t control = tb->control;
>  switch (addr) {
>  case 0: /* Load */
> -tb->load = value;
> -/* Fall through.  */
> -case 4: /* Counter.  */
> -if ((tb->control & 1) && tb->count) {
> -/* Cancel the previous timer.  */
> -timer_del(tb->timer);
> +/* Setting load to 0 stops the timer if prescaler == 0.  */
> +if ((control & 1) && (value == 0) && (control & 0xff00) == 0) {
> +ptimer_stop(tb->timer);
> +control &= ~1;
>  }
> -tb->count = value;
> -if (tb->control & 1) {
> -timerblock_reload(tb, 1);
> +ptimer_set_limit(tb->timer, value, 1);
> +timerblock_run(tb->timer, control, (control & 1));
> +

Re: [Qemu-devel] [PATCH v11 6/7] hw/ptimer: Legalize running with delta = load = 0 and abort on period = 0

2016-01-23 Thread Peter Crosthwaite
On Thu, Jan 21, 2016 at 11:03 AM, Dmitry Osipenko <dig...@gmail.com> wrote:
> Currently ptimer would print error message and clear enable flag for an
> arming timer that has delta = load = 0. That actually could be a valid case
> for some hardware, like instant IRQ trigger for oneshot timer or continuous
> in periodic mode. Support those cases by removing the error message and
> stopping the timer when delta = 0. Abort execution when period = 0 instead
> of printing the error message, otherwise there is a chance to miss that error.
>
> In addition, don't re-load oneshot timer when delta = 0 and remove duplicated
> code from ptimer_tick(), since ptimer_reload would invoke trigger and stop
> the timer.
>
> Signed-off-by: Dmitry Osipenko <dig...@gmail.com>

Reviewed-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>

> ---
>  hw/core/ptimer.c | 27 ---
>  1 file changed, 12 insertions(+), 15 deletions(-)
>
> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
> index 142cc64..cec59e1 100644
> --- a/hw/core/ptimer.c
> +++ b/hw/core/ptimer.c
> @@ -39,11 +39,14 @@ static void ptimer_reload(ptimer_state *s)
>
>  if (s->delta == 0) {
>  ptimer_trigger(s);
> +}
> +
> +if (s->delta == 0 && s->enabled == 1) {
>  s->delta = s->limit;
>  }
> -if (s->delta == 0 || s->period == 0) {
> -fprintf(stderr, "Timer with period zero, disabling\n");
> -s->enabled = 0;
> +
> +if (s->delta == 0) {
> +ptimer_stop(s);
>  return;
>  }
>
> @@ -72,27 +75,22 @@ static void ptimer_reload(ptimer_state *s)
>  static void ptimer_tick(void *opaque)
>  {
>  ptimer_state *s = (ptimer_state *)opaque;
> -ptimer_trigger(s);
>  s->delta = 0;
> -if (s->enabled == 2) {
> -s->enabled = 0;
> -} else {
> -ptimer_reload(s);
> -}
> +ptimer_reload(s);
>  }
>
>  uint64_t ptimer_get_count(ptimer_state *s)
>  {
>  uint64_t counter;
>
> -if (s->enabled) {
> +if (s->enabled && s->delta != 0) {
>  int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>  int64_t next = s->next_event;
>  bool expired = (now - next >= 0);
>  bool oneshot = (s->enabled == 2);
>
>  /* Figure out the current counter value.  */
> -if (s->period == 0 || (expired && (oneshot || use_icount))) {
> +if (expired && (oneshot || use_icount)) {
>  /* Prevent timer underflowing if it should already have
> triggered.  */
>  counter = 0;
> @@ -164,10 +162,7 @@ void ptimer_run(ptimer_state *s, int oneshot)
>  {
>  bool was_disabled = !s->enabled;
>
> -if (was_disabled && s->period == 0) {
> -fprintf(stderr, "Timer with period zero, disabling\n");
> -return;
> -}
> +g_assert(s->period != 0);
>  s->enabled = oneshot ? 2 : 1;
>  if (was_disabled) {
>  s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> @@ -190,6 +185,7 @@ void ptimer_stop(ptimer_state *s)
>  /* Set counter increment interval in nanoseconds.  */
>  void ptimer_set_period(ptimer_state *s, int64_t period)
>  {
> +g_assert(period != 0);
>  s->delta = ptimer_get_count(s);
>  s->period = period;
>  s->period_frac = 0;
> @@ -202,6 +198,7 @@ void ptimer_set_period(ptimer_state *s, int64_t period)
>  /* Set counter frequency in Hz.  */
>  void ptimer_set_freq(ptimer_state *s, uint32_t freq)
>  {
> +g_assert(freq != 0);
>  s->delta = ptimer_get_count(s);
>  s->period = 10ll / freq;
>  s->period_frac = (10ll << 32) / freq;
> --
> 2.7.0
>



Re: [Qemu-devel] [PATCH] cadence_gem: fix buffer overflow

2016-01-18 Thread Peter Crosthwaite
On Mon, Jan 18, 2016 at 12:12 AM, Jason Wang <jasow...@redhat.com> wrote:
>
>
> On 01/18/2016 03:04 PM, Peter Crosthwaite wrote:
>> On Sun, Jan 17, 2016 at 10:50 PM, Jason Wang <jasow...@redhat.com> wrote:
>>>
>>> On 01/14/2016 05:43 PM, Michael S. Tsirkin wrote:
>>>> gem_receive copies a packet received from network into an rxbuf[2048]
>>>> array on stack, with size limited by descriptor length set by guest.  If
>>>> guest is malicious and specifies a descriptor length that is too large,
>>>> and should packet size exceed array size, this results in a buffer
>>>> overflow.
>>>>
>>>> Reported-by: 刘令 <liuling...@360.cn>
>>>> Signed-off-by: Michael S. Tsirkin <m...@redhat.com>
>>>> ---
>>>>  hw/net/cadence_gem.c | 8 
>>>>  1 file changed, 8 insertions(+)
>>> Apply to my -net with tweak on commit log (changing receive to transmit
>>> as noticed).
>>>
>> As this is actually an unimplemented feature you should change the
>> message to a LOG_UNIMP rather than a debug printf.
>>
>> Regards,
>> Peter
>
> Thanks for the reminding. But we need know the whether real device could
> send packet whose length is greater than 2048. Do you know the link to
> the manual? (Haven't fond it in cadence page.) A hint is the linux

Xilinx UG585 has details:

http://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf

Regards,
Peter

> driver (drivers/net/ethernet/cadence/macb.c), use 1500 as its MTU.
>
>>
>>> Thanks
>>>
>>>> diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
>>>> index 3639fc1..15a0786 100644
>>>> --- a/hw/net/cadence_gem.c
>>>> +++ b/hw/net/cadence_gem.c
>>>> @@ -862,6 +862,14 @@ static void gem_transmit(CadenceGEMState *s)
>>>>  break;
>>>>  }
>>>>
>>>> +if (tx_desc_get_length(desc) > sizeof(tx_packet) - (p - 
>>>> tx_packet)) {
>>>> +DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space 
>>>> 0x%x\n",
>>>> + (unsigned)packet_desc_addr,
>>>> + (unsigned)tx_desc_get_length(desc),
>>>> + sizeof(tx_packet) - (p - tx_packet));
>>>> +break;
>>>> +}
>>>> +
>>>>  /* Gather this fragment of the packet from "dma memory" to our 
>>>> contig.
>>>>   * buffer.
>>>>   */
>



Re: [Qemu-devel] [PATCH] cadence_gem: fix buffer overflow

2016-01-17 Thread Peter Crosthwaite
On Sun, Jan 17, 2016 at 10:50 PM, Jason Wang  wrote:
>
>
> On 01/14/2016 05:43 PM, Michael S. Tsirkin wrote:
>> gem_receive copies a packet received from network into an rxbuf[2048]
>> array on stack, with size limited by descriptor length set by guest.  If
>> guest is malicious and specifies a descriptor length that is too large,
>> and should packet size exceed array size, this results in a buffer
>> overflow.
>>
>> Reported-by: 刘令 
>> Signed-off-by: Michael S. Tsirkin 
>> ---
>>  hw/net/cadence_gem.c | 8 
>>  1 file changed, 8 insertions(+)
>
> Apply to my -net with tweak on commit log (changing receive to transmit
> as noticed).
>

As this is actually an unimplemented feature you should change the
message to a LOG_UNIMP rather than a debug printf.

Regards,
Peter

> Thanks
>
>>
>> diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
>> index 3639fc1..15a0786 100644
>> --- a/hw/net/cadence_gem.c
>> +++ b/hw/net/cadence_gem.c
>> @@ -862,6 +862,14 @@ static void gem_transmit(CadenceGEMState *s)
>>  break;
>>  }
>>
>> +if (tx_desc_get_length(desc) > sizeof(tx_packet) - (p - tx_packet)) 
>> {
>> +DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space 
>> 0x%x\n",
>> + (unsigned)packet_desc_addr,
>> + (unsigned)tx_desc_get_length(desc),
>> + sizeof(tx_packet) - (p - tx_packet));
>> +break;
>> +}
>> +
>>  /* Gather this fragment of the packet from "dma memory" to our 
>> contig.
>>   * buffer.
>>   */
>



[Qemu-devel] [PATCH v1 01/17] linux-user: arm: fix coding style for some linux-user signal functions

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 linux-user/signal.c | 110 ++--
 1 file changed, 56 insertions(+), 54 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 919aa83..2cc6d73 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1541,82 +1541,84 @@ static void
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
  CPUARMState *env, abi_ulong mask)
 {
-   __put_user(env->regs[0], >arm_r0);
-   __put_user(env->regs[1], >arm_r1);
-   __put_user(env->regs[2], >arm_r2);
-   __put_user(env->regs[3], >arm_r3);
-   __put_user(env->regs[4], >arm_r4);
-   __put_user(env->regs[5], >arm_r5);
-   __put_user(env->regs[6], >arm_r6);
-   __put_user(env->regs[7], >arm_r7);
-   __put_user(env->regs[8], >arm_r8);
-   __put_user(env->regs[9], >arm_r9);
-   __put_user(env->regs[10], >arm_r10);
-   __put_user(env->regs[11], >arm_fp);
-   __put_user(env->regs[12], >arm_ip);
-   __put_user(env->regs[13], >arm_sp);
-   __put_user(env->regs[14], >arm_lr);
-   __put_user(env->regs[15], >arm_pc);
+__put_user(env->regs[0], >arm_r0);
+__put_user(env->regs[1], >arm_r1);
+__put_user(env->regs[2], >arm_r2);
+__put_user(env->regs[3], >arm_r3);
+__put_user(env->regs[4], >arm_r4);
+__put_user(env->regs[5], >arm_r5);
+__put_user(env->regs[6], >arm_r6);
+__put_user(env->regs[7], >arm_r7);
+__put_user(env->regs[8], >arm_r8);
+__put_user(env->regs[9], >arm_r9);
+__put_user(env->regs[10], >arm_r10);
+__put_user(env->regs[11], >arm_fp);
+__put_user(env->regs[12], >arm_ip);
+__put_user(env->regs[13], >arm_sp);
+__put_user(env->regs[14], >arm_lr);
+__put_user(env->regs[15], >arm_pc);
 #ifdef TARGET_CONFIG_CPU_32
-   __put_user(cpsr_read(env), >arm_cpsr);
+__put_user(cpsr_read(env), >arm_cpsr);
 #endif
 
-   __put_user(/* current->thread.trap_no */ 0, >trap_no);
-   __put_user(/* current->thread.error_code */ 0, >error_code);
-   __put_user(/* current->thread.address */ 0, >fault_address);
-   __put_user(mask, >oldmask);
+__put_user(/* current->thread.trap_no */ 0, >trap_no);
+__put_user(/* current->thread.error_code */ 0, >error_code);
+__put_user(/* current->thread.address */ 0, >fault_address);
+__put_user(mask, >oldmask);
 }
 
 static inline abi_ulong
 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 {
-   unsigned long sp = regs->regs[13];
+unsigned long sp = regs->regs[13];
 
-   /*
-* This is the X/Open sanctioned signal stack switching.
-*/
-   if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
-sp = target_sigaltstack_used.ss_sp + 
target_sigaltstack_used.ss_size;
-   /*
-* ATPCS B01 mandates 8-byte alignment
-*/
-   return (sp - framesize) & ~7;
+/*
+ * This is the X/Open sanctioned signal stack switching.
+ */
+if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
+sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+}
+/*
+ * ATPCS B01 mandates 8-byte alignment
+ */
+return (sp - framesize) & ~7;
 }
 
 static void
 setup_return(CPUARMState *env, struct target_sigaction *ka,
 abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
 {
-   abi_ulong handler = ka->_sa_handler;
-   abi_ulong retcode;
-   int thumb = handler & 1;
-   uint32_t cpsr = cpsr_read(env);
+abi_ulong handler = ka->_sa_handler;
+abi_ulong retcode;
+int thumb = handler & 1;
+uint32_t cpsr = cpsr_read(env);
 
-   cpsr &= ~CPSR_IT;
-   if (thumb) {
-   cpsr |= CPSR_T;
-   } else {
-   cpsr &= ~CPSR_T;
-   }
+cpsr &= ~CPSR_IT;
+if (thumb) {
+cpsr |= CPSR_T;
+} else {
+cpsr &= ~CPSR_T;
+}
 
-   if (ka->sa_flags & TARGET_SA_RESTORER) {
-   retcode = ka->sa_restorer;
-   } else {
-   unsigned int idx = thumb;
+if (ka->sa_flags & TARGET_SA_RESTORER) {
+retcode = ka->sa_restorer;
+} else {
+unsigned int idx = thumb;
 
-   if (ka->sa_flags & TARGET_SA_SIGINFO)
-   idx += 2;
+if (ka->sa_flags & TARGET_SA_SIGINFO) {
+idx += 2;
+}
 
 

[Qemu-devel] [PATCH v1 02/17] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode

2016-01-17 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

If doing big-endian linux-user mode, set both the CPSR.E and SCTLR.E0E
bits. This sets big-endian mode for data accesses in AA32 and AA64
resp.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 linux-user/main.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/linux-user/main.c b/linux-user/main.c
index ee12035..4f8ea9c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4454,6 +4454,10 @@ int main(int argc, char **argv, char **envp)
 for(i = 0; i < 16; i++) {
 env->regs[i] = regs->uregs[i];
 }
+#ifdef TARGET_WORDS_BIGENDIAN
+env->uncached_cpsr |= CPSR_E;
+env->cp15.sctlr_el[1] |= SCTLR_E0E;
+#endif
 /* Enable BE8.  */
 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
 && (info->elf_flags & EF_ARM_BE8)) {
-- 
1.9.1




[Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support

2016-01-17 Thread Peter Crosthwaite
Hi All,

This patch series adds system-mode big-endian support for ARM. It also
implements the setend instruction, and loading of BE binaries even in
LE emulation mode.

Based on Paolo's original work. I have moved all the BE32 related work
to the back of the series. Multiple parties are interested in the BE8
work just on its own, so that could potentially be merged w/o BE32.
PMM requested BE32 be at least thought out architecturally, so this
series sees BE32 functionality through.

I have tested all of LE. BE8 and BE32 in both linux-user mode (for
regressions) and system mode (BE8 and BE32 are new here).
My test application is here, the README gives some example command
lines you can run:

https://github.com/pcrost/arm-be-test

Regards,
Peter


Paolo Bonzini (8):
  linux-user: arm: fix coding style for some linux-user signal functions
  linux-user: arm: handle CPSR.E correctly in strex emulation
  target-arm: pass DisasContext to gen_aa32_ld*/st*
  target-arm: introduce disas flag for endianness
  target-arm: implement setend
  linux-user: arm: pass env to get_user_code_*
  target-arm: implement SCTLR.B, drop bswap_code
  target-arm: implement BE32 mode in system emulation

Peter Crosthwaite (9):
  linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode
  target-arm: implement SCTLR.EE
  target-arm: a64: Add endianness support
  target-arm: cpu: Move cpu_is_big_endian to header
  target-arm: introduce tbflag for endianness
  arm: linux-user: don't set CPSR.E in BE32 mode
  loader: add API to load elf header
  loader: Add data swap option to load-elf
  arm: boot: Support big-endian elfs

 hw/alpha/dp264.c   |   4 +-
 hw/arm/armv7m.c|   2 +-
 hw/arm/boot.c  |  96 --
 hw/core/loader.c   |  57 +-
 hw/cris/boot.c |   2 +-
 hw/i386/multiboot.c|   3 +-
 hw/lm32/lm32_boards.c  |   4 +-
 hw/lm32/milkymist.c|   2 +-
 hw/m68k/an5206.c   |   2 +-
 hw/m68k/dummy_m68k.c   |   2 +-
 hw/m68k/mcf5208.c  |   2 +-
 hw/microblaze/boot.c   |   4 +-
 hw/mips/mips_fulong2e.c|   2 +-
 hw/mips/mips_malta.c   |   2 +-
 hw/mips/mips_mipssim.c |   2 +-
 hw/mips/mips_r4k.c |   2 +-
 hw/moxie/moxiesim.c|   3 +-
 hw/openrisc/openrisc_sim.c |   3 +-
 hw/pci-host/prep.c |   2 +-
 hw/ppc/e500.c  |   2 +-
 hw/ppc/mac_newworld.c  |   5 +-
 hw/ppc/mac_oldworld.c  |   5 +-
 hw/ppc/ppc440_bamboo.c |   3 +-
 hw/ppc/spapr.c |   6 +-
 hw/ppc/virtex_ml507.c  |   3 +-
 hw/s390x/ipl.c |   4 +-
 hw/sparc/leon3.c   |   2 +-
 hw/sparc/sun4m.c   |   4 +-
 hw/sparc64/sun4u.c |   4 +-
 hw/tricore/tricore_testboard.c |   2 +-
 hw/xtensa/sim.c|   4 +-
 hw/xtensa/xtfpga.c |   2 +-
 include/hw/arm/arm.h   |   9 +
 include/hw/elf_ops.h   |  22 ++-
 include/hw/loader.h|   3 +-
 linux-user/main.c  |  77 ++--
 linux-user/signal.c| 110 +--
 target-arm/arm_ldst.h  |   8 +-
 target-arm/cpu.c   |  21 +--
 target-arm/cpu.h   | 103 ++-
 target-arm/helper.c|  50 +++--
 target-arm/helper.h|   1 +
 target-arm/op_helper.c |   5 +
 target-arm/translate-a64.c |  56 +++---
 target-arm/translate.c | 407 -
 target-arm/translate.h |   3 +-
 46 files changed, 752 insertions(+), 365 deletions(-)

-- 
1.9.1




[Qemu-devel] [PATCH v1 04/17] target-arm: implement SCTLR.EE

2016-01-17 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

Implement SCTLR.EE bit which controls data endianess for exceptions
and page table translations. SCTLR.EE is mirrored to the CPSR.E bit
on exception entry.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 target-arm/helper.c | 42 --
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 59d5a41..afac1b2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5889,7 +5889,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
 /* Clear IT bits.  */
 env->condexec_bits = 0;
 /* Switch to the new mode, and to the correct instruction set.  */
-env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
+env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_M)) | new_mode;
+/* Set new mode endianess */
+env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_E)) |
+(env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE ? CPSR_E : 0);
 env->daif |= mask;
 /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
  * and we should just guard the thumb mode on V4 */
@@ -5958,6 +5961,12 @@ static inline bool 
regime_translation_disabled(CPUARMState *env,
 return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
 }
 
+static inline bool regime_translation_big_endian(CPUARMState *env,
+ ARMMMUIdx mmu_idx)
+{
+return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
+}
+
 /* Return the TCR controlling this translation regime */
 static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
@@ -6263,7 +6272,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, 
ARMMMUIdx mmu_idx,
  */
 static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
 ARMMMUIdx mmu_idx, uint32_t *fsr,
-ARMMMUFaultInfo *fi)
+ARMMMUFaultInfo *fi, bool be)
 {
 ARMCPU *cpu = ARM_CPU(cs);
 CPUARMState *env = >env;
@@ -6274,12 +6283,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, 
bool is_secure,
 if (fi->s1ptw) {
 return 0;
 }
-return address_space_ldl(cs->as, addr, attrs, NULL);
+if (be) {
+return address_space_ldl_be(cs->as, addr, attrs, NULL);
+} else {
+return address_space_ldl_le(cs->as, addr, attrs, NULL);
+}
 }
 
 static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
 ARMMMUIdx mmu_idx, uint32_t *fsr,
-ARMMMUFaultInfo *fi)
+ARMMMUFaultInfo *fi, bool be)
 {
 ARMCPU *cpu = ARM_CPU(cs);
 CPUARMState *env = >env;
@@ -6290,7 +6303,11 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, 
bool is_secure,
 if (fi->s1ptw) {
 return 0;
 }
-return address_space_ldq(cs->as, addr, attrs, NULL);
+if (be) {
+return address_space_ldq_be(cs->as, addr, attrs, NULL);
+} else {
+return address_space_ldq_le(cs->as, addr, attrs, NULL);
+}
 }
 
 static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
@@ -6318,7 +6335,8 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t 
address,
 goto do_fault;
 }
 desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
-   mmu_idx, fsr, fi);
+   mmu_idx, fsr, fi,
+   regime_translation_big_endian(env, mmu_idx));
 type = (desc & 3);
 domain = (desc >> 5) & 0x0f;
 if (regime_el(env, mmu_idx) == 1) {
@@ -6355,7 +6373,8 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t 
address,
 table = (desc & 0xf000) | ((address >> 8) & 0xffc);
 }
 desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
-   mmu_idx, fsr, fi);
+   mmu_idx, fsr, fi,
+   regime_translation_big_endian(env, mmu_idx));
 switch (desc & 3) {
 case 0: /* Page translation fault.  */
 code = 7;
@@ -6437,7 +6456,8 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t 
address,
 goto do_fault;
 }
 desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
-   mmu_idx, fsr, fi);
+   mmu_idx, fsr, fi,
+   regime_translation_big_endian(env, mmu_idx));
 type = (desc & 3);
 if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
 /* Section translation fault, or attempt to use the encoding
@@ -6489,7 +6509,8 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t 
address,
 /* Lookup l2 entry.  */
 table = (desc & 0xfc00) | ((address >> 10) & 0x3fc);
  

[Qemu-devel] [PATCH v1 16/17] loader: Add data swap option to load-elf

2016-01-17 Thread Peter Crosthwaite
Some CPUs are of an opposite data-endianness to other components in the
system. Sometimes elfs have the data sections layed out with this CPU
data-endianess accounting for when loaded via the CPU, byte swaps
(relative to other system components) will occur.

The leading example, is ARM's BE32 mode, which is is basically LE with
address manipulation on half-word and byte accesses to access the
hw/byte reversed address. This means that word data is invariant
accross LE and BE32. This also means that instructions are still LE.
The expectation is that the elf will be loaded via the CPU in this
endianness scheme, which means the data in the elf is reversed at
compile time.

As QEMU loads via the system memory directly, rather than the CPU, we
need a mechanism to reverse elf data endianness to implement this
possibility.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 hw/alpha/dp264.c   |  4 ++--
 hw/arm/armv7m.c|  2 +-
 hw/arm/boot.c  |  2 +-
 hw/core/loader.c   |  9 ++---
 hw/cris/boot.c |  2 +-
 hw/i386/multiboot.c|  3 ++-
 hw/lm32/lm32_boards.c  |  4 ++--
 hw/lm32/milkymist.c|  2 +-
 hw/m68k/an5206.c   |  2 +-
 hw/m68k/dummy_m68k.c   |  2 +-
 hw/m68k/mcf5208.c  |  2 +-
 hw/microblaze/boot.c   |  4 ++--
 hw/mips/mips_fulong2e.c|  2 +-
 hw/mips/mips_malta.c   |  2 +-
 hw/mips/mips_mipssim.c |  2 +-
 hw/mips/mips_r4k.c |  2 +-
 hw/moxie/moxiesim.c|  3 ++-
 hw/openrisc/openrisc_sim.c |  3 ++-
 hw/pci-host/prep.c |  2 +-
 hw/ppc/e500.c  |  2 +-
 hw/ppc/mac_newworld.c  |  5 +++--
 hw/ppc/mac_oldworld.c  |  5 +++--
 hw/ppc/ppc440_bamboo.c |  3 ++-
 hw/ppc/spapr.c |  6 --
 hw/ppc/virtex_ml507.c  |  3 ++-
 hw/s390x/ipl.c |  4 ++--
 hw/sparc/leon3.c   |  2 +-
 hw/sparc/sun4m.c   |  4 ++--
 hw/sparc64/sun4u.c |  4 ++--
 hw/tricore/tricore_testboard.c |  2 +-
 hw/xtensa/sim.c|  4 ++--
 hw/xtensa/xtfpga.c |  2 +-
 include/hw/elf_ops.h   | 22 +-
 include/hw/loader.h|  2 +-
 34 files changed, 78 insertions(+), 46 deletions(-)

diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 27bdaa1..df071fa 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -109,7 +109,7 @@ static void clipper_init(MachineState *machine)
 }
 size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
 NULL, _entry, _low, _high,
-0, EM_ALPHA, 0);
+0, EM_ALPHA, 0, 0);
 if (size < 0) {
 hw_error("could not load palcode '%s'\n", palcode_filename);
 exit(1);
@@ -129,7 +129,7 @@ static void clipper_init(MachineState *machine)
 
 size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
 NULL, _entry, _low, _high,
-0, EM_ALPHA, 0);
+0, EM_ALPHA, 0, 0);
 if (size < 0) {
 hw_error("could not load kernel '%s'\n", kernel_filename);
 exit(1);
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index a80d2ad..d721e5b 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -210,7 +210,7 @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int 
mem_size, int num_irq,
 
 if (kernel_filename) {
 image_size = load_elf(kernel_filename, NULL, NULL, , ,
-  NULL, big_endian, EM_ARM, 1);
+  NULL, big_endian, EM_ARM, 1, 0);
 if (image_size < 0) {
 image_size = load_image_targphys(kernel_filename, 0, mem_size);
 lowaddr = 0;
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 75f69bf..0de4269 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -700,7 +700,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void 
*data)
 /* Assume that raw images are linux kernels, and ELF images are not.  */
 kernel_size = load_elf(info->kernel_filename, NULL, NULL, _entry,
_low_addr, _high_addr, big_endian,
-   elf_machine, 1);
+   elf_machine, 1, 0);
 if (kernel_size > 0 && have_dtb(info)) {
 /* If there is still some room left at the base of RAM, try and put
  * the DTB there like we do for images loaded with -bios or -pflash.
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 28da8e2..bee6cf5 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -382,7 +382,8 @@ fail:
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
-

[Qemu-devel] [PATCH v1 13/17] arm: linux-user: don't set CPSR.E in BE32 mode

2016-01-17 Thread Peter Crosthwaite
Don't set CPSR.E for BE32 linux-user mode. As linux-user mode models
BE32, using normal BE (and system mode will not), a special case is
needed for user-mode where if sctlr.b is set, the CPU identifies as BE.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 linux-user/main.c |  2 --
 target-arm/cpu.h  | 12 +++-
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index d481458..60375fb 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4496,8 +4496,6 @@ int main(int argc, char **argv, char **envp)
 env->uncached_cpsr |= CPSR_E;
 } else {
 env->cp15.sctlr_el[1] |= SCTLR_B;
-/* We model BE32 as regular BE, so set CPSR_E */
-env->uncached_cpsr |= CPSR_E;
 }
 #endif
 }
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 3edd56b..96b1e99 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1812,7 +1812,17 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
 
 /* In 32bit endianness is determined by looking at CPSR's E bit */
 if (!is_a64(env)) {
-return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
+return
+#ifdef CONFIG_USER_ONLY
+/* In user mode, BE32 data accesses are just modelled as
+ * regular BE access. In system mode, BE32 is modelled as
+ * little endian, with the appropriate address translations on
+ * non-word accesses. So sctlr.b only affects overall
+ * endianness in user mode
+ */
+arm_sctlr_b(env) ||
+#endif
+((env->uncached_cpsr & CPSR_E) ? 1 : 0);
 }
 
 cur_el = arm_current_el(env);
-- 
1.9.1




[Qemu-devel] [PATCH v1 08/17] target-arm: cpu: Move cpu_is_big_endian to header

2016-01-17 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

There is a CPU data endianness test that is used to drive the
virtio_big_endian test.

Move this up to the header so it can be more generally used for endian
tests. The KVM specific cpu_syncronize_state call is left behind in the
virtio specific function.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 target-arm/cpu.c | 19 +++
 target-arm/cpu.h | 19 +++
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 35a1f12..d3b73bf 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -368,26 +368,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, 
int level)
 #endif
 }
 
-static bool arm_cpu_is_big_endian(CPUState *cs)
+static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
 {
 ARMCPU *cpu = ARM_CPU(cs);
 CPUARMState *env = >env;
-int cur_el;
 
 cpu_synchronize_state(cs);
-
-/* In 32bit guest endianness is determined by looking at CPSR's E bit */
-if (!is_a64(env)) {
-return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
-}
-
-cur_el = arm_current_el(env);
-
-if (cur_el == 0) {
-return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
-}
-
-return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+return arm_cpu_is_big_endian(env);
 }
 
 #endif
@@ -1420,7 +1407,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->do_unaligned_access = arm_cpu_do_unaligned_access;
 cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
 cc->vmsd = _arm_cpu;
-cc->virtio_is_big_endian = arm_cpu_is_big_endian;
+cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
 #endif
 cc->gdb_num_core_regs = 26;
 cc->gdb_core_xml_file = "arm-core.xml";
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f83070a..54675c7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1795,6 +1795,25 @@ static inline bool arm_singlestep_active(CPUARMState 
*env)
 && arm_generate_debug_exceptions(env);
 }
 
+/* Return true if the processor is in big-endian mode. */
+static bool arm_cpu_is_big_endian(CPUARMState *env)
+{
+int cur_el;
+
+/* In 32bit endianness is determined by looking at CPSR's E bit */
+if (!is_a64(env)) {
+return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
+}
+
+cur_el = arm_current_el(env);
+
+if (cur_el == 0) {
+return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
+}
+
+return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+}
+
 #include "exec/cpu-all.h"
 
 /* Bit usage in the TB flags field: bit 31 indicates whether we are
-- 
1.9.1




[Qemu-devel] [PATCH v1 07/17] target-arm: a64: Add endianness support

2016-01-17 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

Set the dc->mo_endianness flag for AA64 and use it in all ldst ops.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 target-arm/translate-a64.c | 49 --
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index d826b92..59026b6 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -726,7 +726,7 @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 
source,
  TCGv_i64 tcg_addr, int size, int memidx)
 {
 g_assert(size <= 3);
-tcg_gen_qemu_st_i64(source, tcg_addr, memidx, MO_TE + size);
+tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->mo_endianness + size);
 }
 
 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
@@ -741,7 +741,7 @@ static void do_gpr_st(DisasContext *s, TCGv_i64 source,
 static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
  int size, bool is_signed, bool extend, int memidx)
 {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->mo_endianness + size;
 
 g_assert(size <= 3);
 
@@ -773,13 +773,18 @@ static void do_fp_st(DisasContext *s, int srcidx, 
TCGv_i64 tcg_addr, int size)
 TCGv_i64 tmp = tcg_temp_new_i64();
 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
 if (size < 4) {
-tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
+tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
+s->mo_endianness + size);
 } else {
+bool be = s->mo_endianness == MO_BE;
 TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
-tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
+
+tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
+tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
+s->mo_endianness | MO_Q);
 tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
-tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
+s->mo_endianness | MO_Q);
 tcg_temp_free_i64(tcg_hiaddr);
 }
 
@@ -796,17 +801,21 @@ static void do_fp_ld(DisasContext *s, int destidx, 
TCGv_i64 tcg_addr, int size)
 TCGv_i64 tmphi;
 
 if (size < 4) {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->mo_endianness + size;
 tmphi = tcg_const_i64(0);
 tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
 } else {
+bool be = s->mo_endianness == MO_BE;
 TCGv_i64 tcg_hiaddr;
+
 tmphi = tcg_temp_new_i64();
 tcg_hiaddr = tcg_temp_new_i64();
 
-tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
 tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, 
get_mem_index(s),
+s->mo_endianness | MO_Q);
+tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, 
get_mem_index(s),
+s->mo_endianness | MO_Q);
 tcg_temp_free_i64(tcg_hiaddr);
 }
 
@@ -945,7 +954,7 @@ static void clear_vec_high(DisasContext *s, int rd)
 static void do_vec_st(DisasContext *s, int srcidx, int element,
   TCGv_i64 tcg_addr, int size)
 {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->mo_endianness + size;
 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
 read_vec_element(s, tcg_tmp, srcidx, element, size);
@@ -958,7 +967,7 @@ static void do_vec_st(DisasContext *s, int srcidx, int 
element,
 static void do_vec_ld(DisasContext *s, int destidx, int element,
   TCGv_i64 tcg_addr, int size)
 {
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->mo_endianness + size;
 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
 
 tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
@@ -1703,7 +1712,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2,
TCGv_i64 addr, int size, bool is_pair)
 {
 TCGv_i64 tmp = tcg_temp_new_i64();
-TCGMemOp memop = MO_TE + size;
+TCGMemOp memop = s->mo_endianness + size;
 
 g_assert(size <= 3);
 tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
@@ -1765,7 +1774,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, 
int rt, int rt2,
 tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
 
 tmp = tcg_temp_new_i64();
-tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size);
+tcg_gen_qemu_ld_i64(tmp, addr

[Qemu-devel] [PATCH v1 06/17] target-arm: introduce disas flag for endianness

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Introduce a disas flag for setting the CPU data endianness. This allows
control of the endianness from the CPU state rather than hard-coding it
to TARGET_WORDS_BIGENDIAN.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[ PC changes:
  * Split off as new patch from original:
"target-arm: introduce tbflag for CPSR.E"
  * Wrote commit message from scratch
]
Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 target-arm/translate-a64.c |  1 +
 target-arm/translate.c | 39 ---
 target-arm/translate.h |  1 +
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 14e8131..d826b92 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11033,6 +11033,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, 
TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
 dc->thumb = 0;
 dc->bswap_code = 0;
+dc->mo_endianness = MO_TE;
 dc->condexec_mask = 0;
 dc->condexec_cond = 0;
 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 55ecca5..e1679d3 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -927,26 +927,30 @@ static inline void store_reg_from_load(DisasContext *s, 
int reg, TCGv_i32 var)
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
-tcg_gen_qemu_ld_i32(val, addr, index, (OPC));\
+TCGMemOp opc = (OPC) | s->mo_endianness; \
+tcg_gen_qemu_ld_i32(val, addr, index, opc);  \
 }
 
 #define DO_GEN_ST(SUFF, OPC) \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
-tcg_gen_qemu_st_i32(val, addr, index, (OPC));\
+TCGMemOp opc = (OPC) | s->mo_endianness; \
+tcg_gen_qemu_st_i32(val, addr, index, opc);  \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
  TCGv_i32 addr, int index)
 {
-tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
+TCGMemOp opc = MO_Q | s->mo_endianness;
+tcg_gen_qemu_ld_i64(val, addr, index, opc);
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
  TCGv_i32 addr, int index)
 {
-tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
+TCGMemOp opc = MO_Q | s->mo_endianness;
+tcg_gen_qemu_st_i64(val, addr, index, opc);
 }
 
 #else
@@ -955,9 +959,10 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 
val,
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
+TCGMemOp opc = (OPC) | s->mo_endianness; \
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
-tcg_gen_qemu_ld_i32(val, addr64, index, OPC);\
+tcg_gen_qemu_ld_i32(val, addr64, index, opc);\
 tcg_temp_free(addr64);   \
 }
 
@@ -965,27 +970,30 @@ static inline void gen_aa32_ld##SUFF(DisasContext *s, 
TCGv_i32 val,  \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
+TCGMemOp opc = (OPC) | s->mo_endianness; \
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
-tcg_gen_qemu_st_i32(val, addr64, index, OPC);\
+tcg_gen_qemu_st_i32(val, addr64, index, opc);\
 tcg_temp_free(addr64);   \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
  TCGv_i32 addr, int index)
 {
+TCGMemOp opc = MO_Q | s->mo_endianness;
 TCGv addr64 = tcg_temp_new();
 tcg_gen_extu_i32_i64(addr64, addr);
-tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
+tcg_gen_qemu_ld_i64(val, addr64, index, opc);
 tcg_temp_free(addr64)

[Qemu-devel] [PATCH v1 10/17] target-arm: implement setend

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Since this is not a high-performance path, just use a helper to
flip the E bit and force a lookup in the hash table since the
flags have changed.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 target-arm/helper.h|  1 +
 target-arm/op_helper.c |  5 +
 target-arm/translate.c | 16 
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/target-arm/helper.h b/target-arm/helper.h
index c2a85c7..2315a9c 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, void, env, i32)
 DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
+DEF_HELPER_1(setend, void, env)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 DEF_HELPER_1(yield, void, env)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index e42d287..2a4bc67 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -295,6 +295,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, 
uint32_t shift)
 return res;
 }
 
+void HELPER(setend)(CPUARMState *env)
+{
+env->uncached_cpsr ^= CPSR_E;
+}
+
 /* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
  * The function returns the target EL (1-3) if the instruction is to be 
trapped;
  * otherwise it returns 0 indicating it is not trapped.
diff --git a/target-arm/translate.c b/target-arm/translate.c
index cb925ef..192a5d6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7726,10 +7726,10 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 if ((insn & 0x0dff) == 0x0101) {
 ARCH(6);
 /* setend */
-if (((insn >> 9) & 1) != s->bswap_code) {
-/* Dynamic endianness switching not implemented. */
-qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-goto illegal_op;
+if (((insn >> 9) & 1) != !!(s->mo_endianness == MO_BE)) {
+gen_helper_setend(cpu_env);
+gen_set_pc_im(s, s->pc);
+s->is_jmp = DISAS_JUMP;
 }
 return;
 } else if ((insn & 0x0f00) == 0x057ff000) {
@@ -11064,10 +11064,10 @@ static void disas_thumb_insn(CPUARMState *env, 
DisasContext *s)
 case 2:
 /* setend */
 ARCH(6);
-if (((insn >> 3) & 1) != s->bswap_code) {
-/* Dynamic endianness switching not implemented. */
-qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-goto illegal_op;
+if (((insn >> 3) & 1) != !!(s->mo_endianness == MO_BE)) {
+gen_helper_setend(cpu_env);
+gen_set_pc_im(s, s->pc);
+s->is_jmp = DISAS_JUMP;
 }
 break;
 case 3:
-- 
1.9.1




[Qemu-devel] [PATCH v1 09/17] target-arm: introduce tbflag for endianness

2016-01-17 Thread Peter Crosthwaite
From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>

Introduce a tbflags for endianness, set based upon the CPUs current
endianness. This in turn propagates through to the disas endianness
flag.

Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
---

 target-arm/cpu.h   | 7 +++
 target-arm/translate-a64.c | 2 +-
 target-arm/translate.c | 2 +-
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 54675c7..74048d1 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1857,6 +1857,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
  */
 #define ARM_TBFLAG_NS_SHIFT 19
 #define ARM_TBFLAG_NS_MASK  (1 << ARM_TBFLAG_NS_SHIFT)
+#define ARM_TBFLAG_MOE_SHIFT20
+#define ARM_TBFLAG_MOE_MASK (1 << ARM_TBFLAG_MOE_SHIFT)
 
 /* Bit usage when in AArch64 state: currently we have no A64 specific bits */
 
@@ -1887,6 +1889,8 @@ static bool arm_cpu_is_big_endian(CPUARMState *env)
 (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
 #define ARM_TBFLAG_NS(F) \
 (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
+#define ARM_TBFLAG_MOE(F) \
+(((F) & ARM_TBFLAG_MOE_MASK) >> ARM_TBFLAG_MOE_SHIFT)
 
 /* Return the exception level to which FP-disabled exceptions should
  * be taken, or 0 if FP is enabled.
@@ -2018,6 +2022,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, 
target_ulong *pc,
 }
 }
 }
+if (arm_cpu_is_big_endian(env)) {
+*flags |= ARM_TBFLAG_MOE_MASK;
+}
 *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
 
 *cs_base = 0;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 59026b6..db68662 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11044,7 +11044,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, 
TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
 dc->thumb = 0;
 dc->bswap_code = 0;
-dc->mo_endianness = MO_TE;
+dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
 dc->condexec_mask = 0;
 dc->condexec_cond = 0;
 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e1679d3..cb925ef 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11274,7 +11274,7 @@ void gen_intermediate_code(CPUARMState *env, 
TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
-dc->mo_endianness = MO_TE;
+dc->mo_endianness = ARM_TBFLAG_MOE(tb->flags) ? MO_BE : MO_LE;
 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
-- 
1.9.1




[Qemu-devel] [PATCH v1 15/17] loader: add API to load elf header

2016-01-17 Thread Peter Crosthwaite
Add an API to load an elf header header from a file. Populates a
buffer with the header contents, as well as a boolean for whether the
elf is 64b or not. Both arguments are optional.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 hw/core/loader.c| 48 
 include/hw/loader.h |  1 +
 2 files changed, 49 insertions(+)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index 6b69852..28da8e2 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -331,6 +331,54 @@ const char *load_elf_strerror(int error)
 }
 }
 
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
+{
+int fd;
+uint8_t e_ident[EI_NIDENT];
+size_t hdr_size, off = 0;
+bool is64l;
+
+fd = open(filename, O_RDONLY | O_BINARY);
+if (fd < 0) {
+error_setg_errno(errp, errno, "Fail to open file");
+return;
+}
+if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) {
+error_setg_errno(errp, errno, "Fail to read file");
+goto fail;
+}
+if (e_ident[0] != ELFMAG0 ||
+e_ident[1] != ELFMAG1 ||
+e_ident[2] != ELFMAG2 ||
+e_ident[3] != ELFMAG3) {
+error_setg(errp, "Bad ELF magic");
+goto fail;
+}
+
+is64l = e_ident[EI_CLASS] == ELFCLASS64;
+hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
+if (is64) {
+*is64 = is64l;
+}
+
+lseek(fd, 0, SEEK_SET);
+while (hdr && off < hdr_size) {
+size_t br = read(fd, hdr + off, hdr_size - off);
+switch (br) {
+case 0:
+error_setg(errp, "File too short");
+goto fail;
+case -1:
+error_setg_errno(errp, errno, "Failed to read file");
+goto fail;
+}
+off += br;
+}
+
+fail:
+close(fd);
+}
+
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
diff --git a/include/hw/loader.h b/include/hw/loader.h
index f7b43ab..33067f8 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -36,6 +36,7 @@ int load_elf(const char *filename, uint64_t 
(*translate_fn)(void *, uint64_t),
  void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
  uint64_t *highaddr, int big_endian, int elf_machine,
  int clear_lsb);
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
 int load_aout(const char *filename, hwaddr addr, int max_sz,
   int bswap_needed, hwaddr target_page_size);
 int load_uimage(const char *filename, hwaddr *ep,
-- 
1.9.1




[Qemu-devel] [PATCH v1 14/17] target-arm: implement BE32 mode in system emulation

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

System emulation only has a little-endian target; BE32 mode
is implemented by adjusting the low bits of the address
for every byte and halfword load and store.  64-bit accesses
flip the low and high words.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[PC changes:
  * rebased against master (Jan 2016)
]
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 target-arm/cpu.h   |  5 ++-
 target-arm/translate.c | 86 +-
 2 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 96b1e99..5814019 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1925,9 +1925,8 @@ static inline bool bswap_code(bool sctlr_b)
 #endif
 sctlr_b;
 #else
-/* We do not implement BE32 mode for system-mode emulation, but
- * anyway it would always do little-endian accesses with
- * TARGET_WORDS_BIGENDIAN = 0.
+/* All code access in ARM is little endian, and there are no loaders
+ * doing swaps that need to be reversed
  */
 return 0;
 #endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 44c3ac9..2d80bb2 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -914,6 +914,12 @@ static inline void store_reg_from_load(DisasContext *s, 
int reg, TCGv_i32 var)
 }
 }
 
+#ifdef CONFIG_USER_ONLY
+#define IS_USER_ONLY 1
+#else
+#define IS_USER_ONLY 0
+#endif
+
 /* Abstractions of "generate code to do a guest load/store for
  * AArch32", where a vaddr is always 32 bits (and is zero
  * extended if we're a 64 bit core) and  data is also
@@ -923,19 +929,35 @@ static inline void store_reg_from_load(DisasContext *s, 
int reg, TCGv_i32 var)
  */
 #if TARGET_LONG_BITS == 32
 
-#define DO_GEN_LD(SUFF, OPC) \
+#define DO_GEN_LD(SUFF, OPC, BE32_XOR)   \
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
 TCGMemOp opc = (OPC) | s->mo_endianness; \
+/* Not needed for user-mode BE32, where we use MO_BE instead.  */\
+if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {   \
+TCGv addr_be = tcg_temp_new();   \
+tcg_gen_xori_i32(addr_be, addr, BE32_XOR);   \
+tcg_gen_qemu_ld_i32(val, addr_be, index, opc);   \
+tcg_temp_free(addr_be);  \
+return;  \
+}\
 tcg_gen_qemu_ld_i32(val, addr, index, opc);  \
 }
 
-#define DO_GEN_ST(SUFF, OPC) \
+#define DO_GEN_ST(SUFF, OPC, BE32_XOR)   \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
  TCGv_i32 addr, int index)   \
 {\
 TCGMemOp opc = (OPC) | s->mo_endianness; \
+/* Not needed for user-mode BE32, where we use MO_BE instead.  */\
+if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) {   \
+TCGv addr_be = tcg_temp_new();   \
+tcg_gen_xori_i32(addr_be, addr, BE32_XOR);   \
+tcg_gen_qemu_ld_i32(val, addr_be, index, opc);   \
+tcg_temp_free(addr_be);  \
+return;  \
+}\
 tcg_gen_qemu_st_i32(val, addr, index, opc);  \
 }
 
@@ -944,35 +966,55 @@ static inline void gen_aa32_ld64(DisasContext *s, 
TCGv_i64 val,
 {
 TCGMemOp opc = MO_Q | s->mo_endianness;
 tcg_gen_qemu_ld_i64(val, addr, index, opc);
+/* Not needed for user-mode BE32, where we use MO_BE instead.  */
+if (!IS_USER_ONLY && s->sctlr_b) {
+tcg_gen_rotri_i64(val, val, 32);
+}
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
  TCGv_i32 addr, int index)
 {
 TCGMemOp opc = MO_Q | s->mo_endianness;
+/* Not needed for user-mode BE32, where we use MO_BE instead.  */
+if (!IS_USER_ONLY && s->sctlr_b) {
+TCGv_i64 tmp = tcg_temp_new_i64();
+tcg_gen_rotri_i64(tmp, val, 32);
+tcg_gen_qemu_st_i64(tmp, addr, index, opc);
+tcg_temp_free_i64(tmp);
+

[Qemu-devel] [PATCH v1 05/17] target-arm: pass DisasContext to gen_aa32_ld*/st*

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

We'll need the DisasContext in the next patch to retrieve the
desired endianness, so pass it as a whole to gen_aa32_ld*/st*.

Unfortunately we cannot let those functions call get_mem_index,
because of user-mode load/store instructions.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[ PC changes:
 * Fix long lines
]
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 target-arm/translate.c | 270 ++---
 1 file changed, 142 insertions(+), 128 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index d485e7d..55ecca5 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -924,23 +924,27 @@ static inline void store_reg_from_load(DisasContext *s, 
int reg, TCGv_i32 var)
 #if TARGET_LONG_BITS == 32
 
 #define DO_GEN_LD(SUFF, OPC) \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 tcg_gen_qemu_ld_i32(val, addr, index, (OPC));\
 }
 
 #define DO_GEN_ST(SUFF, OPC) \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 tcg_gen_qemu_st_i32(val, addr, index, (OPC));\
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
 }
@@ -948,7 +952,8 @@ static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 
addr, int index)
 #else
 
 #define DO_GEN_LD(SUFF, OPC) \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
@@ -957,7 +962,8 @@ static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 
addr, int index) \
 }
 
 #define DO_GEN_ST(SUFF, OPC) \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val,  \
+ TCGv_i32 addr, int index)   \
 {\
 TCGv addr64 = tcg_temp_new();\
 tcg_gen_extu_i32_i64(addr64, addr);  \
@@ -965,7 +971,8 @@ static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 
addr, int index) \
 tcg_temp_free(addr64);   \
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 TCGv addr64 = tcg_temp_new();
 tcg_gen_extu_i32_i64(addr64, addr);
@@ -973,7 +980,8 @@ static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 
addr, int index)
 tcg_temp_free(addr64);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
 {
 TCGv addr64 = tcg_temp_new();
 tcg_gen_extu_i32_i64(addr64, addr);
@@ -1288,18 +1296,18 @@ VFP_GEN_FIX(ulto, )
 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
 {
 if (dp) {
-gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
+gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
 } else {
-gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
+gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
 }
 }
 
 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
 {
 if (dp) {
-gen_aa32_st64(cpu_F0d, add

[Qemu-devel] [PATCH v1 11/17] linux-user: arm: pass env to get_user_code_*

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

This matches the idiom used by get_user_data_* later in the series,
and will help when bswap_code will be replaced by SCTLR.B.

Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 linux-user/main.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 8348ddc..2157774 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -439,17 +439,17 @@ void cpu_loop(CPUX86State *env)
 
 #ifdef TARGET_ARM
 
-#define get_user_code_u32(x, gaddr, doswap) \
+#define get_user_code_u32(x, gaddr, env)\
 ({ abi_long __r = get_user_u32((x), (gaddr));   \
-if (!__r && (doswap)) { \
+if (!__r && (env)->bswap_code) {\
 (x) = bswap32(x);   \
 }   \
 __r;\
 })
 
-#define get_user_code_u16(x, gaddr, doswap) \
+#define get_user_code_u16(x, gaddr, env)\
 ({ abi_long __r = get_user_u16((x), (gaddr));   \
-if (!__r && (doswap)) { \
+if (!__r && (env)->bswap_code) {\
 (x) = bswap16(x);   \
 }   \
 __r;\
@@ -732,7 +732,7 @@ void cpu_loop(CPUARMState *env)
 /* we handle the FPU emulation here, as Linux */
 /* we get the opcode */
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u32(opcode, env->regs[15], env->bswap_code);
+get_user_code_u32(opcode, env->regs[15], env);
 
 rc = EmulateAll(opcode, >fpa, env);
 if (rc == 0) { /* illegal instruction */
@@ -802,25 +802,23 @@ void cpu_loop(CPUARMState *env)
 if (trapnr == EXCP_BKPT) {
 if (env->thumb) {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u16(insn, env->regs[15], 
env->bswap_code);
+get_user_code_u16(insn, env->regs[15], env);
 n = insn & 0xff;
 env->regs[15] += 2;
 } else {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u32(insn, env->regs[15], 
env->bswap_code);
+get_user_code_u32(insn, env->regs[15], env);
 n = (insn & 0xf) | ((insn >> 4) & 0xff0);
 env->regs[15] += 4;
 }
 } else {
 if (env->thumb) {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u16(insn, env->regs[15] - 2,
-  env->bswap_code);
+get_user_code_u16(insn, env->regs[15] - 2, env);
 n = insn & 0xff;
 } else {
 /* FIXME - what to do if get_user() fails? */
-get_user_code_u32(insn, env->regs[15] - 4,
-  env->bswap_code);
+get_user_code_u32(insn, env->regs[15] - 4, env);
 n = insn & 0xff;
 }
 }
-- 
1.9.1




[Qemu-devel] [PATCH v1 17/17] arm: boot: Support big-endian elfs

2016-01-17 Thread Peter Crosthwaite
Support ARM big-endian ELF files in system-mode emulation. When loading
an elf, determine the endianness mode expected by the elf, and set the
relevant CPU state accordingly.

With this, big-endian modes are now fully supported via system-mode LE,
so there is no need to restrict the elf loading to the TARGET
endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.

Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 hw/arm/boot.c| 96 ++--
 include/hw/arm/arm.h |  9 +
 2 files changed, 88 insertions(+), 17 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 0de4269..053c9e8 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -465,9 +465,34 @@ static void do_cpu_reset(void *opaque)
 cpu_reset(cs);
 if (info) {
 if (!info->is_linux) {
+int i;
 /* Jump to the entry point.  */
 uint64_t entry = info->entry;
 
+switch (info->endianness) {
+case ARM_ENDIANNESS_LE:
+env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
+for (i = 1; i < 4; ++i) {
+env->cp15.sctlr_el[i] &= ~SCTLR_EE;
+}
+env->uncached_cpsr &= ~CPSR_E;
+break;
+case ARM_ENDIANNESS_BE8:
+env->cp15.sctlr_el[1] |= SCTLR_E0E;
+for (i = 1; i < 4; ++i) {
+env->cp15.sctlr_el[i] |= SCTLR_EE;
+}
+env->uncached_cpsr |= CPSR_E;
+break;
+case ARM_ENDIANNESS_BE32:
+env->cp15.sctlr_el[1] |= SCTLR_B;
+break;
+case ARM_ENDIANNESS_UNKNOWN:
+break; /* Board's decision */
+default:
+g_assert_not_reached();
+}
+
 if (!env->aarch64) {
 env->thumb = info->entry & 1;
 entry &= 0xfffe;
@@ -589,16 +614,23 @@ static void arm_load_kernel_notify(Notifier *notifier, 
void *data)
 int kernel_size;
 int initrd_size;
 int is_linux = 0;
+
 uint64_t elf_entry, elf_low_addr, elf_high_addr;
 int elf_machine;
+bool elf_is64;
+union {
+Elf32_Ehdr h32;
+Elf64_Ehdr h64;
+} elf_header;
+
 hwaddr entry, kernel_load_offset;
-int big_endian;
 static const ARMInsnFixup *primary_loader;
 ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
  notifier, notifier);
 ARMCPU *cpu = n->cpu;
 struct arm_boot_info *info =
 container_of(n, struct arm_boot_info, load_kernel_notifier);
+Error *err = NULL;
 
 /* The board code is not supposed to set secure_board_setup unless
  * running its code in secure mode is actually possible, and KVM
@@ -678,12 +710,6 @@ static void arm_load_kernel_notify(Notifier *notifier, 
void *data)
 if (info->nb_cpus == 0)
 info->nb_cpus = 1;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-big_endian = 1;
-#else
-big_endian = 0;
-#endif
-
 /* We want to put the initrd far enough into RAM that when the
  * kernel is uncompressed it will not clobber the initrd. However
  * on boards without much RAM we must ensure that we still leave
@@ -698,16 +724,52 @@ static void arm_load_kernel_notify(Notifier *notifier, 
void *data)
 MIN(info->ram_size / 2, 128 * 1024 * 1024);
 
 /* Assume that raw images are linux kernels, and ELF images are not.  */
-kernel_size = load_elf(info->kernel_filename, NULL, NULL, _entry,
-   _low_addr, _high_addr, big_endian,
-   elf_machine, 1, 0);
-if (kernel_size > 0 && have_dtb(info)) {
-/* If there is still some room left at the base of RAM, try and put
- * the DTB there like we do for images loaded with -bios or -pflash.
- */
-if (elf_low_addr > info->loader_start
-|| elf_high_addr < info->loader_start) {
-/* Pass elf_low_addr as address limit to load_dtb if it may be
+
+load_elf_hdr(info->kernel_filename, _header, _is64, );
+
+if (!err) {
+int data_swab = 0;
+bool big_endian;
+
+if (elf_is64) {
+big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
+info->endianness = big_endian ? ARM_ENDIANNESS_BE8
+  : ARM_ENDIANNESS_LE;
+} else {
+big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
+if (big_endian) {
+if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
+info->endianness = ARM_ENDIANNESS_BE8;
+} else {
+info->endianness = ARM_ENDIANNESS_BE32;
+/* In BE32, the CPU has a different view of the per-byte
+ 

[Qemu-devel] [PATCH v1 03/17] linux-user: arm: handle CPSR.E correctly in strex emulation

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

Now that CPSR.E is set correctly, prepare for when setend will be able
to change it; bswap data in and out of strex manually by comparing
SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury
of using TCGMemOps).

Reviewed-by: Peter Maydell <peter.mayd...@linaro.org>
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[ PC changes:
  * Remove BE32 support
]
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 linux-user/main.c | 50 +++---
 target-arm/cpu.h  | 21 +
 2 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 4f8ea9c..8348ddc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -455,6 +455,38 @@ void cpu_loop(CPUX86State *env)
 __r;\
 })
 
+#define get_user_data_u32(x, gaddr, env)\
+({ abi_long __r = get_user_u32((x), (gaddr));   \
+if (!__r && arm_cpu_bswap_data(env)) {  \
+(x) = bswap32(x);   \
+}   \
+__r;\
+})
+
+#define get_user_data_u16(x, gaddr, env)\
+({ abi_long __r = get_user_u16((x), (gaddr));   \
+if (!__r && arm_cpu_bswap_data(env)) {  \
+(x) = bswap16(x);   \
+}   \
+__r;\
+})
+
+#define put_user_data_u32(x, gaddr, env)\
+({ typeof(x) __x = (x); \
+if (arm_cpu_bswap_data(env)) {  \
+__x = bswap32(__x); \
+}   \
+put_user_u32(__x, (gaddr)); \
+})
+
+#define put_user_data_u16(x, gaddr, env)\
+({ typeof(x) __x = (x); \
+if (arm_cpu_bswap_data(env)) {  \
+__x = bswap16(__x); \
+}   \
+put_user_u16(__x, (gaddr)); \
+})
+
 #ifdef TARGET_ABI32
 /* Commpage handling -- there is no commpage for AArch64 */
 
@@ -614,11 +646,11 @@ static int do_strex(CPUARMState *env)
 segv = get_user_u8(val, addr);
 break;
 case 1:
-segv = get_user_u16(val, addr);
+segv = get_user_data_u16(val, addr, env);
 break;
 case 2:
 case 3:
-segv = get_user_u32(val, addr);
+segv = get_user_data_u32(val, addr, env);
 break;
 default:
 abort();
@@ -629,12 +661,16 @@ static int do_strex(CPUARMState *env)
 }
 if (size == 3) {
 uint32_t valhi;
-segv = get_user_u32(valhi, addr + 4);
+segv = get_user_data_u32(valhi, addr + 4, env);
 if (segv) {
 env->exception.vaddress = addr + 4;
 goto done;
 }
-val = deposit64(val, 32, 32, valhi);
+if (arm_cpu_bswap_data(env)) {
+val = deposit64((uint64_t)valhi, 32, 32, val);
+} else {
+val = deposit64(val, 32, 32, valhi);
+}
 }
 if (val != env->exclusive_val) {
 goto fail;
@@ -646,11 +682,11 @@ static int do_strex(CPUARMState *env)
 segv = put_user_u8(val, addr);
 break;
 case 1:
-segv = put_user_u16(val, addr);
+segv = put_user_data_u16(val, addr, env);
 break;
 case 2:
 case 3:
-segv = put_user_u32(val, addr);
+segv = put_user_data_u32(val, addr, env);
 break;
 }
 if (segv) {
@@ -659,7 +695,7 @@ static int do_strex(CPUARMState *env)
 }
 if (size == 3) {
 val = env->regs[(env->exclusive_info >> 12) & 0xf];
-segv = put_user_u32(val, addr + 4);
+segv = put_user_data_u32(val, addr + 4, env);
 if (segv) {
 env->exception.vaddress = addr + 4;
 goto done;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 815fef8..f83070a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1934,6 +1934,27 @@ static inline int fp_exception_el(CPUARMState *env)
 return 0;
 }
 
+#ifdef CONFIG_USER_ONLY
+/* get_user and put_user respectively return and expect data according
+ * to TARGET_WORDS_BIGENDIAN, but ldrex/strex emulation needs to take
+ * into account CPSR.E.
+ *
+ *TARGET_WORDS_BIGENDIAN  CPSR.Eneed swap?
+ *   LE/LE no   0  no
+ *   LE/BE no   1  yes
+ *   BE8/LEyes  0  yes
+ *   BE8/BEyes  1  no
+ */
+static inline

[Qemu-devel] [PATCH] misc: zynq-xadc: Fix off-by-one

2016-01-17 Thread Peter Crosthwaite
This bounds check was off-by-one. Fix.

Reported-by: Paolo Bonzini <pbonz...@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---
 hw/misc/zynq-xadc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/misc/zynq-xadc.c b/hw/misc/zynq-xadc.c
index 1a32595..d160ff2 100644
--- a/hw/misc/zynq-xadc.c
+++ b/hw/misc/zynq-xadc.c
@@ -220,7 +220,7 @@ static void zynq_xadc_write(void *opaque, hwaddr offset, 
uint64_t val,
 break;
 }
 
-if (xadc_reg > ZYNQ_XADC_NUM_ADC_REGS && xadc_cmd != CMD_NOP) {
+if (xadc_reg >= ZYNQ_XADC_NUM_ADC_REGS && xadc_cmd != CMD_NOP) {
 qemu_log_mask(LOG_GUEST_ERROR, "read/write op to invalid xadc "
   "reg 0x%x\n", xadc_reg);
 break;
-- 
1.9.1




[Qemu-devel] [PATCH v1 12/17] target-arm: implement SCTLR.B, drop bswap_code

2016-01-17 Thread Peter Crosthwaite
From: Paolo Bonzini <pbonz...@redhat.com>

bswap_code is a CPU property of sorts ("is the iside endianness the
opposite way round to TARGET_WORDS_BIGENDIAN?") but it is not the
actual CPU state involved here which is SCTLR.B (set for BE32
binaries, clear for BE8).

Replace bswap_code with SCTLR.B, and pass that to arm_ld*_code.
The next patches will make data fetches honor both SCTLR.B and
CPSR.E appropriately.

Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
[PC changes:
 * rebased on master (Jan 2016)
 * Dropped comment about CPSR.E being unimplemented
 * s/TARGET_USER_ONLY/CONFIG_USER_ONLY
 * Use bswap_code() for disas_set_info() instead of raw sctlr_b
]
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
---

 linux-user/main.c  | 13 -
 target-arm/arm_ldst.h  |  8 
 target-arm/cpu.c   |  2 +-
 target-arm/cpu.h   | 47 ++
 target-arm/helper.c|  8 
 target-arm/translate-a64.c |  6 +++---
 target-arm/translate.c | 12 ++--
 target-arm/translate.h |  2 +-
 8 files changed, 66 insertions(+), 32 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 2157774..d481458 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -441,7 +441,7 @@ void cpu_loop(CPUX86State *env)
 
 #define get_user_code_u32(x, gaddr, env)\
 ({ abi_long __r = get_user_u32((x), (gaddr));   \
-if (!__r && (env)->bswap_code) {\
+if (!__r && bswap_code(arm_sctlr_b(env))) { \
 (x) = bswap32(x);   \
 }   \
 __r;\
@@ -449,7 +449,7 @@ void cpu_loop(CPUX86State *env)
 
 #define get_user_code_u16(x, gaddr, env)\
 ({ abi_long __r = get_user_u16((x), (gaddr));   \
-if (!__r && (env)->bswap_code) {\
+if (!__r && bswap_code(arm_sctlr_b(env))) { \
 (x) = bswap16(x);   \
 }   \
 __r;\
@@ -4489,14 +4489,17 @@ int main(int argc, char **argv, char **envp)
 env->regs[i] = regs->uregs[i];
 }
 #ifdef TARGET_WORDS_BIGENDIAN
-env->uncached_cpsr |= CPSR_E;
 env->cp15.sctlr_el[1] |= SCTLR_E0E;
-#endif
 /* Enable BE8.  */
 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
 && (info->elf_flags & EF_ARM_BE8)) {
-env->bswap_code = 1;
+env->uncached_cpsr |= CPSR_E;
+} else {
+env->cp15.sctlr_el[1] |= SCTLR_B;
+/* We model BE32 as regular BE, so set CPSR_E */
+env->uncached_cpsr |= CPSR_E;
 }
+#endif
 }
 #elif defined(TARGET_UNICORE32)
 {
diff --git a/target-arm/arm_ldst.h b/target-arm/arm_ldst.h
index b1ece01..35c2c43 100644
--- a/target-arm/arm_ldst.h
+++ b/target-arm/arm_ldst.h
@@ -25,10 +25,10 @@
 
 /* Load an instruction and return it in the standard little-endian order */
 static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
-bool do_swap)
+bool sctlr_b)
 {
 uint32_t insn = cpu_ldl_code(env, addr);
-if (do_swap) {
+if (bswap_code(sctlr_b)) {
 return bswap32(insn);
 }
 return insn;
@@ -36,10 +36,10 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, 
target_ulong addr,
 
 /* Ditto, for a halfword (Thumb) instruction */
 static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
- bool do_swap)
+ bool sctlr_b)
 {
 uint16_t insn = cpu_lduw_code(env, addr);
-if (do_swap) {
+if (bswap_code(sctlr_b)) {
 return bswap16(insn);
 }
 return insn;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index d3b73bf..cec5147 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -413,7 +413,7 @@ static void arm_disas_set_info(CPUState *cpu, 
disassemble_info *info)
 } else {
 info->print_insn = print_insn_arm;
 }
-if (env->bswap_code) {
+if (bswap_code(arm_sctlr_b(env))) {
 #ifdef TARGET_WORDS_BIGENDIAN
 info->endian = BFD_ENDIAN_LITTLE;
 #else
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 74048d1..3edd56b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -478,9 +478,6 @@ typedef struct CPUARMState {
 uint32_t cregs[16];
 } iwmmxt;
 
-/* For mixed endian mode.  */
-bool bswap_code;
-
 #if defined(CONFIG_USER_ONLY)
 /* For usermode syscall translation.  */
 int eabi;
@@ -1795,6 +1792,19 @@ static inline bool arm_singlestep_active(CPUARMState 
*en

Re: [Qemu-devel] [PATCH v7 1/6] qdev: get_child_bus(): Use QOM lookup if available

2016-01-15 Thread Peter Crosthwaite
On Fri, Jan 15, 2016 at 2:38 PM, Alistair Francis
<alistair.fran...@xilinx.com> wrote:
> From: Peter Crosthwaite <crosthwaitepe...@gmail.com>
>
> qbus_realize() adds busses as a QOM child of the device in addition to
> adding it to the qdev bus list. Change get_child_bus() to use the QOM
> child if it is available. This takes priority over the bus-list, but
> the child object is checked for type correctness.
>
> This prepares support for aliasing of buses. The use case is SoCs,
> where a SoC container needs to present buses to the board level, but
> the buses are implemented by controller IP we already model as self
> contained qbus-containing devices.
>
> Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com>
> Acked-by: Alistair Francis <alistair.fran...@xilinx.com>

As a re-sender, you need to Signed-off-by as well. I'm guessing you
can just do this on list like a review to avoid the respin.

Regards,
Peter

> ---
>  hw/core/qdev.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 2c7101d..75d1227 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -580,6 +580,12 @@ void qdev_pass_gpios(DeviceState *dev, DeviceState 
> *container,
>  BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
>  {
>  BusState *bus;
> +Object *child = object_resolve_path_component(OBJECT(dev), name);
> +
> +bus = (BusState *)object_dynamic_cast(child, TYPE_BUS);
> +if (bus) {
> +return bus;
> +}
>
>  QLIST_FOREACH(bus, >child_bus, sibling) {
>  if (strcmp(name, bus->name) == 0) {
> --
> 2.5.0
>



Re: [Qemu-devel] [PATCH v3 7/7] raspi: add raspberry pi 2 machine

2016-01-14 Thread Peter Crosthwaite
On Thu, Jan 14, 2016 at 3:04 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
> Hi Peter,
>
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Tuesday, 12 January 2016 16:44
>> On Tue, Jan 12, 2016 at 3:53 PM, Andrew Baumann
>> <andrew.baum...@microsoft.com> wrote:
>> >> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> >> Sent: Monday, 11 January 2016 19:58
>> >> > +/* Allocate and map RAM */
>> >> > +memory_region_allocate_system_memory(>ram,
>> >> OBJECT(machine), "ram",
>> >> > + machine->ram_size);
>> >> > +memory_region_add_subregion_overlap(get_system_memory(), 0,
>> >> >ram, 0);
>> >>
>> >> I thought the SoC handled this now? Why do you need to add to
>> >> system_memory?
>> >
>> > If I don't map it here, how do RAM accesses from the CPUs work?
>> >
>>
>> Do the CPUs not have their AS'es connected to your custom ASes by the SoC
>> layer?
>>
>> > Or are you saying that I should still do this, but do it in the SoC not the
>> board level?
>> >
>>
>> I was hoping we could get away with 0 use of system_memory.
>
> On further investigation, I don't think it's possible to wire up CPU ASes 
> explicitly. There's no obvious property to set. Each cpu->as is initialised 
> to point to address_space_memory at the top of cpu_exec_init(), and there is 
> no way I could see to override that.
>
> I think what I have now is pretty clean, but if you'd prefer to do the 
> mapping at into the global AS at SoC level that's fine with me too.
>

If it cant be done yet, what is here is a preferable approach. PMM has
some work on list for CPU ASes that may be realted, moreso for the
secure attributes though I think.

Regards,
Peter

> Thanks,
> Andrew



Re: [Qemu-devel] [PATCH v3 7/7] raspi: add raspberry pi 2 machine

2016-01-14 Thread Peter Crosthwaite
On Thu, Jan 14, 2016 at 4:43 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Thursday, 14 January 2016 15:35
>>
>> On Thu, Jan 14, 2016 at 3:04 PM, Andrew Baumann
>> <andrew.baum...@microsoft.com> wrote:
>> > Hi Peter,
>> >
>> >> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> >> Sent: Tuesday, 12 January 2016 16:44
>> >> On Tue, Jan 12, 2016 at 3:53 PM, Andrew Baumann
>> >> <andrew.baum...@microsoft.com> wrote:
>> >> >> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> >> >> Sent: Monday, 11 January 2016 19:58
>> >> >> > +/* Allocate and map RAM */
>> >> >> > +memory_region_allocate_system_memory(>ram,
>> >> >> OBJECT(machine), "ram",
>> >> >> > + machine->ram_size);
>> >> >> > +
>> memory_region_add_subregion_overlap(get_system_memory(), 0,
>> >> >> >ram, 0);
>> >> >>
>> >> >> I thought the SoC handled this now? Why do you need to add to
>> >> >> system_memory?
>> >> >
>> >> > If I don't map it here, how do RAM accesses from the CPUs work?
>> >> >
>> >>
>> >> Do the CPUs not have their AS'es connected to your custom ASes by the
>> SoC
>> >> layer?
>> >>
>> >> > Or are you saying that I should still do this, but do it in the SoC not 
>> >> > the
>> >> board level?
>> >> >
>> >>
>> >> I was hoping we could get away with 0 use of system_memory.
>> >
>> > On further investigation, I don't think it's possible to wire up CPU ASes
>> explicitly. There's no obvious property to set. Each cpu->as is initialised 
>> to
>> point to address_space_memory at the top of cpu_exec_init(), and there is
>> no way I could see to override that.
>> >
>> > I think what I have now is pretty clean, but if you'd prefer to do the
>> mapping at into the global AS at SoC level that's fine with me too.
>> >
>>
>> If it cant be done yet, what is here is a preferable approach. PMM has
>> some work on list for CPU ASes that may be realted, moreso for the
>> secure attributes though I think.
>
> Ok. It looks like the patch you CCed me on would enable this. But I don't 
> really want to wait for that with Pi, and honestly I don't think this is too 
> bad -- there are only a handful of things in the system_memory space (the 
> RAM, the peripherals blob, and the 2836 multi-core controller on pi2), and it 
> seems unlikely to be of great benefit unless some future madman starts 
> building multi-pi boards with bizarre mapping schemes. Let's hope not :)
>

Agree

Regards,
Peter

> Andrew



Re: [Qemu-devel] [Qemu-arm] [PATCH v3 12/19] qom/cpu: Add MemoryRegion property

2016-01-14 Thread Peter Crosthwaite
CC Andrew,

This may be the missing feature for your system_memory for CPU RAM
access problem.

Regards,
Peter

On Thu, Jan 14, 2016 at 5:52 AM, Peter Maydell <peter.mayd...@linaro.org> wrote:
> From: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
>
> Add a MemoryRegion property, which if set is used to construct
> the CPU's initial (default) AddressSpace.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
> [PMM: code is moved from qom/cpu.c to exec.c to avoid having to
>  make qom/cpu.o be a non-common object file; code to use the
>  MemoryRegion and to default it to system_memory added.]
> Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
> Acked-by: Edgar E. Iglesias <edgar.igles...@xilinx.com>
> ---
>  cpus.c|  4 +++-
>  exec.c| 14 ++
>  include/qom/cpu.h |  1 +
>  3 files changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/cpus.c b/cpus.c
> index 725a51d..3efff6b 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -1375,8 +1375,10 @@ void qemu_init_vcpu(CPUState *cpu)
>  /* If the target cpu hasn't set up any address spaces itself,
>   * give it the default one.
>   */
> +AddressSpace *as = address_space_init_shareable(cpu->memory,
> +"cpu-memory");
>  cpu->num_ases = 1;
> -cpu_address_space_init(cpu, _space_memory, 0);
> +cpu_address_space_init(cpu, as, 0);
>  }
>
>  if (kvm_enabled()) {
> diff --git a/exec.c b/exec.c
> index 0e4f681..5a1b208 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -628,6 +628,20 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
>
>  #ifndef CONFIG_USER_ONLY
>  cpu->thread_id = qemu_get_thread_id();
> +
> +/* This is a softmmu CPU object, so create a property for it
> + * so users can wire up its memory. (This can't go in qom/cpu.c
> + * because that file is compiled only once for both user-mode
> + * and system builds.) The default if no link is set up is to use
> + * the system address space.
> + */
> +object_property_add_link(OBJECT(cpu), "memory", TYPE_MEMORY_REGION,
> + (Object **)>memory,
> + qdev_prop_allow_set_link_before_realize,
> + OBJ_PROP_LINK_UNREF_ON_RELEASE,
> + _abort);
> +cpu->memory = system_memory;
> +object_ref(OBJECT(cpu->memory));
>  #endif
>
>  #if defined(CONFIG_USER_ONLY)
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index ed23246..2e5229d 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -297,6 +297,7 @@ struct CPUState {
>  CPUAddressSpace *cpu_ases;
>  int num_ases;
>  AddressSpace *as;
> +MemoryRegion *memory;
>
>  void *env_ptr; /* CPUArchState */
>  struct TranslationBlock *current_tb;
> --
> 1.9.1
>
>



Re: [Qemu-devel] [Qemu-arm] [PATCH] cadence_gem: fix buffer overflow

2016-01-14 Thread Peter Crosthwaite
On Thu, Jan 14, 2016 at 2:03 AM, Peter Maydell  wrote:
> On 14 January 2016 at 09:43, Michael S. Tsirkin  wrote:
>> gem_receive copies a packet received from network into an rxbuf[2048]
>> array on stack, with size limited by descriptor length set by guest.  If
>> guest is malicious and specifies a descriptor length that is too large,
>> and should packet size exceed array size, this results in a buffer
>> overflow.
>>
>> Reported-by: 刘令 
>> Signed-off-by: Michael S. Tsirkin 
>> ---
>>  hw/net/cadence_gem.c | 8 
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
>> index 3639fc1..15a0786 100644
>> --- a/hw/net/cadence_gem.c
>> +++ b/hw/net/cadence_gem.c
>> @@ -862,6 +862,14 @@ static void gem_transmit(CadenceGEMState *s)
>>  break;
>>  }
>>
>> +if (tx_desc_get_length(desc) > sizeof(tx_packet) - (p - tx_packet)) 
>> {
>> +DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space 
>> 0x%x\n",
>> + (unsigned)packet_desc_addr,
>> + (unsigned)tx_desc_get_length(desc),
>> + sizeof(tx_packet) - (p - tx_packet));
>> +break;
>> +}
>
> Is this what the real hardware does in this situation?
> Should we log this as a guest error?
>

I'm not sure it is a guest error. I think its just a shortcut in the
original implementation. I guess QEMU needs the whole packet before
handing off to the net layer and the assumption is that the packet is
always within 2048. I think the hardware is just going to put the data
on the wire as it goes. The easiest solution is to realloc the buffer
as it goes with the increasing sizes. Otherwise you could refactor the
code to be two pass over the descriptor ring section (containing the
packet). If we want to fix the buffer overflow more urgently, the
correct error would be an assert().

Regards,
Peter

>> +
>>  /* Gather this fragment of the packet from "dma memory" to our 
>> contig.
>>   * buffer.
>>   */
>> --
>> MST
>>
>
> thanks
> -- PMM
>



Re: [Qemu-devel] [PATCH V6 2/8] introduce aux-bus

2016-01-14 Thread Peter Crosthwaite
On Thu, Jan 14, 2016 at 1:57 AM, KONRAD Frederic
<fred.kon...@greensocs.com> wrote:
>
>
> Le 13/01/2016 22:02, Peter Crosthwaite a écrit :
>>
>> On Mon, Jan 4, 2016 at 10:25 AM,  <fred.kon...@greensocs.com> wrote:
>>>
>>> From: KONRAD Frederic <fred.kon...@greensocs.com>
>>>
>>> This introduces a new bus: aux-bus.
>>>
>>> It contains an address space for aux slaves devices and a bridge to an
>>> I2C bus
>>> for I2C through AUX transactions.
>>>
>>> Signed-off-by: KONRAD Frederic <fred.kon...@greensocs.com>
>>> Tested-By: Hyun Kwon <hyun.k...@xilinx.com>
>>> ---
>>>   default-configs/aarch64-softmmu.mak |   1 +
>>>   hw/misc/Makefile.objs   |   1 +
>>>   hw/misc/aux.c   | 348
>>> 
>>>   include/hw/misc/aux.h   | 124 +
>>>   4 files changed, 474 insertions(+)
>>>   create mode 100644 hw/misc/aux.c
>>>   create mode 100644 include/hw/misc/aux.h
>>>
>>> diff --git a/default-configs/aarch64-softmmu.mak
>>> b/default-configs/aarch64-softmmu.mak
>>> index 96dd994..d3a2665 100644
>>> --- a/default-configs/aarch64-softmmu.mak
>>> +++ b/default-configs/aarch64-softmmu.mak
>>> @@ -3,4 +3,5 @@
>>>   # We support all the 32 bit boards so need all their config
>>>   include arm-softmmu.mak
>>>
>>> +CONFIG_AUX=y
>>>   CONFIG_XLNX_ZYNQMP=y
>>> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
>>> index d4765c2..4af5fbe 100644
>>> --- a/hw/misc/Makefile.objs
>>> +++ b/hw/misc/Makefile.objs
>>> @@ -44,3 +44,4 @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
>>>   obj-$(CONFIG_PVPANIC) += pvpanic.o
>>>   obj-$(CONFIG_EDU) += edu.o
>>>   obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
>>> +obj-$(CONFIG_AUX) += aux.o
>>> diff --git a/hw/misc/aux.c b/hw/misc/aux.c
>>> new file mode 100644
>>> index 000..cdfec67
>>> --- /dev/null
>>> +++ b/hw/misc/aux.c
>>> @@ -0,0 +1,348 @@
>>> +/*
>>> + * aux.c
>>> + *
>>> + *  Copyright 2015 : GreenSocs Ltd
>>> + *  http://www.greensocs.com/ , email: i...@greensocs.com
>>> + *
>>> + *  Developed by :
>>> + *  Frederic Konrad   <fred.kon...@greensocs.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation, either version 2 of the License, or
>>> + * (at your option)any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> along
>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>> + *
>>> + */
>>> +
>>> +/*
>>> + * This is an implementation of the AUX bus for VESA Display Port v1.1a.
>>> + */
>>> +
>>> +#include "hw/misc/aux.h"
>>> +#include "hw/i2c/i2c.h"
>>> +#include "monitor/monitor.h"
>>> +
>>> +#ifndef DEBUG_AUX
>>> +#define DEBUG_AUX 0
>>> +#endif
>>> +
>>> +#define DPRINTF(fmt, ...) do {
>>> \
>>> +if (DEBUG_AUX) {
>>> \
>>> +qemu_log("aux: " fmt , ## __VA_ARGS__);
>>> \
>>> +}
>>> \
>>> +} while (0);
>>> +
>>> +#define TYPE_AUXTOI2C "aux-to-i2c-bridge"
>>> +#define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C)
>>> +
>>> +#define TYPE_AUX_BUS "aux-bus"
>>> +#define AUX_BUS(obj) OBJECT_CHECK(AUXBus, (obj), TYPE_AUX_BUS)
>>> +
>>> +static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int
>>> indent);
>>> +
>>> +static void aux_bus_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +BusClass *k = BUS_CLASS(klass);
>>> +
>>> +/* AUXSlave has an MMIO so we need to change the way we print
>>> information
>>> + * in monitor.
>>> +   

Re: [Qemu-devel] [PATCH] i2c-tiny-usb: add new usb to i2c bridge

2016-01-13 Thread Peter Crosthwaite
On Wed, Jan 13, 2016 at 8:07 AM, Tim Sander <t...@krieglstein.org> wrote:
> Hi
> Am Donnerstag, 7. Januar 2016, 02:14:23 schrieb Peter Crosthwaite:
>> Patch subject prefix should contain the version number. Use the
>> --subject-prefix or -v options to git format-patch.
> Ok, i will try to remember this next time.
>>
>> On Wed, Jan 6, 2016 at 6:58 AM, Tim Sander <t...@krieglstein.org> wrote:
>> > Version 4 with improvements suggested by Gerd Hoffmann:
>> Changelog information should go below the line ...
>>
>> > Signed-off-by: Tim Sander <t...@krieglstein.org>
>>
>> Signed-off-by usually at end of the commit message.
>>
>> > i2c-tiny-usb is a small usb to i2c bridge:
>> >  http://www.harbaum.org/till/i2c_tiny_usb/index.shtml
>> >
>> > It is pretty simple and has no usb endpoints just a control.
>> > Reasons for adding this device:
>> > * Linux device driver available
>> > * adding an additional i2c bus via command line e.g.
>> >
>> >   -device usb-i2c-tiny,id=i2c-0 -device tmp105,bus=i2c,address=0x50
>> >
>> > ---
>>
>> ... here.
> Ok.
>
>> >  default-configs/usb.mak |   1 +
>> >  hw/usb/Makefile.objs|   1 +
>> >  hw/usb/dev-i2c-tiny.c   | 320
>> >   trace-events
>> >  |  11 ++
>> >  4 files changed, 333 insertions(+)
>> >  create mode 100644 hw/usb/dev-i2c-tiny.c
>> >
>> > diff --git a/default-configs/usb.mak b/default-configs/usb.mak
>> > index f4b8568..01d2c9f 100644
>> > --- a/default-configs/usb.mak
>> > +++ b/default-configs/usb.mak
>> > @@ -8,3 +8,4 @@ CONFIG_USB_AUDIO=y
>> >
>> >  CONFIG_USB_SERIAL=y
>> >  CONFIG_USB_NETWORK=y
>> >  CONFIG_USB_BLUETOOTH=y
>> >
>> > +CONFIG_USB_I2C_TINY=y
>> > diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
>> > index 8f00fbd..3a4c337 100644
>> > --- a/hw/usb/Makefile.objs
>> > +++ b/hw/usb/Makefile.objs
>> > @@ -20,6 +20,7 @@ common-obj-$(CONFIG_USB_AUDIO)+= dev-audio.o
>> >
>> >  common-obj-$(CONFIG_USB_SERIAL)   += dev-serial.o
>> >  common-obj-$(CONFIG_USB_NETWORK)  += dev-network.o
>> >  common-obj-$(CONFIG_USB_BLUETOOTH)+= dev-bluetooth.o
>> >
>> > +common-obj-$(CONFIG_USB_I2C_TINY) += dev-i2c-tiny.o
>> >
>> >  ifeq ($(CONFIG_USB_SMARTCARD),y)
>> >  common-obj-y  += dev-smartcard-reader.o
>> >
>> > diff --git a/hw/usb/dev-i2c-tiny.c b/hw/usb/dev-i2c-tiny.c
>> > new file mode 100644
>> > index 000..c28d7a5
>> > --- /dev/null
>> > +++ b/hw/usb/dev-i2c-tiny.c
>> > @@ -0,0 +1,320 @@
>> > +/*
>> > + * I2C tiny usb device emulation
>> > + *
>> > + * i2c-tiny-usb is a small usb to i2c bridge:
>> > + *
>> > + * http://www.harbaum.org/till/i2c_tiny_usb/index.shtml
>> > + *
>> > + * The simulated device is pretty simple and has no usb endpoints.
>> > + * There is a Linux device driver available named i2c-tiny-usb.
>> > + *
>> > + * Below is an example how to use this device from command line:
>> > + *  -device usb-i2c-tiny,id=i2c-0 -device tmp105,bus=i2c,address=0x50
>> > + *
>> > + * Copyright (c) 2015 Tim Sander <t...@krieglstein.org>
>> > + *
>> > + * Loosly based on usb dev-serial.c:
>> > + * Copyright (c) 2006 CodeSourcery.
>> > + * Copyright (c) 2008 Samuel Thibault <samuel.thiba...@ens-lyon.org>
>> > + * Written by Paul Brook, reused for FTDI by Samuel Thibault
>> > + *
>> > + * This code is licensed under the LGPL.
>> > + *
>> > + */
>> > +
>> > +#include "trace.h"
>> > +#include "qemu-common.h"
>> > +#include "qemu/error-report.h"
>> > +#include "hw/usb.h"
>> > +#include "hw/usb/desc.h"
>> > +#include "hw/i2c/i2c.h"
>> > +#include "hw/i2c/smbus.h"
>> > +#include "sysemu/char.h"
>> > +#include "endian.h"
>> > +
>> > +/* commands from USB, must e.g. match command ids in kernel driver */
>> > +#define CMD_ECHO   0
>> > +#define CMD_GET_FUNC   1
>> > +#define CMD_SET_DELAY  2
>> > +#define CMD_GET_STATUS 3
>> > +
>> > +/* To determine what functionality is present */
>> > +#define I2C_FUNC_I2C  

Re: [Qemu-devel] [PATCH V6 2/8] introduce aux-bus

2016-01-13 Thread Peter Crosthwaite
On Mon, Jan 4, 2016 at 10:25 AM,   wrote:
> From: KONRAD Frederic 
>
> This introduces a new bus: aux-bus.
>
> It contains an address space for aux slaves devices and a bridge to an I2C bus
> for I2C through AUX transactions.
>
> Signed-off-by: KONRAD Frederic 
> Tested-By: Hyun Kwon 
> ---
>  default-configs/aarch64-softmmu.mak |   1 +
>  hw/misc/Makefile.objs   |   1 +
>  hw/misc/aux.c   | 348 
> 
>  include/hw/misc/aux.h   | 124 +
>  4 files changed, 474 insertions(+)
>  create mode 100644 hw/misc/aux.c
>  create mode 100644 include/hw/misc/aux.h
>
> diff --git a/default-configs/aarch64-softmmu.mak 
> b/default-configs/aarch64-softmmu.mak
> index 96dd994..d3a2665 100644
> --- a/default-configs/aarch64-softmmu.mak
> +++ b/default-configs/aarch64-softmmu.mak
> @@ -3,4 +3,5 @@
>  # We support all the 32 bit boards so need all their config
>  include arm-softmmu.mak
>
> +CONFIG_AUX=y
>  CONFIG_XLNX_ZYNQMP=y
> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
> index d4765c2..4af5fbe 100644
> --- a/hw/misc/Makefile.objs
> +++ b/hw/misc/Makefile.objs
> @@ -44,3 +44,4 @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
>  obj-$(CONFIG_PVPANIC) += pvpanic.o
>  obj-$(CONFIG_EDU) += edu.o
>  obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
> +obj-$(CONFIG_AUX) += aux.o
> diff --git a/hw/misc/aux.c b/hw/misc/aux.c
> new file mode 100644
> index 000..cdfec67
> --- /dev/null
> +++ b/hw/misc/aux.c
> @@ -0,0 +1,348 @@
> +/*
> + * aux.c
> + *
> + *  Copyright 2015 : GreenSocs Ltd
> + *  http://www.greensocs.com/ , email: i...@greensocs.com
> + *
> + *  Developed by :
> + *  Frederic Konrad   
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option)any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see .
> + *
> + */
> +
> +/*
> + * This is an implementation of the AUX bus for VESA Display Port v1.1a.
> + */
> +
> +#include "hw/misc/aux.h"
> +#include "hw/i2c/i2c.h"
> +#include "monitor/monitor.h"
> +
> +#ifndef DEBUG_AUX
> +#define DEBUG_AUX 0
> +#endif
> +
> +#define DPRINTF(fmt, ...) do {   
>   \
> +if (DEBUG_AUX) { 
>   \
> +qemu_log("aux: " fmt , ## __VA_ARGS__);  
>   \
> +}
>   \
> +} while (0);
> +
> +#define TYPE_AUXTOI2C "aux-to-i2c-bridge"
> +#define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C)
> +
> +#define TYPE_AUX_BUS "aux-bus"
> +#define AUX_BUS(obj) OBJECT_CHECK(AUXBus, (obj), TYPE_AUX_BUS)
> +
> +static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent);
> +
> +static void aux_bus_class_init(ObjectClass *klass, void *data)
> +{
> +BusClass *k = BUS_CLASS(klass);
> +
> +/* AUXSlave has an MMIO so we need to change the way we print information
> + * in monitor.
> + */
> +k->print_dev = aux_slave_dev_print;
> +}
> +
> +static const TypeInfo aux_bus_info = {
> +.name = TYPE_AUX_BUS,
> +.parent = TYPE_BUS,
> +.instance_size = sizeof(AUXBus),
> +.class_init = aux_bus_class_init
> +};
> +
> +AUXBus *aux_init_bus(DeviceState *parent, const char *name)
> +{
> +AUXBus *bus;
> +
> +bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name));
> +bus->bridge = AUXTOI2C(qdev_create(BUS(bus), TYPE_AUXTOI2C));
> +
> +/* Memory related. */
> +bus->aux_io = g_malloc(sizeof(*bus->aux_io));
> +memory_region_init(bus->aux_io, OBJECT(bus), "aux-io", (1 << 20));
> +address_space_init(>aux_addr_space, bus->aux_io, "aux-io");
> +return bus;
> +}
> +
> +static void aux_bus_map_device(AUXBus *bus, AUXSlave *dev, hwaddr addr)
> +{
> +memory_region_add_subregion(bus->aux_io, addr, dev->mmio);
> +}
> +
> +static bool aux_bus_is_bridge(AUXBus *bus, DeviceState *dev)
> +{
> +return (dev == DEVICE(bus->bridge));
> +}
> +
> +AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
> +  uint8_t len, uint8_t *data)
> +{
> +int temp;
> +AUXReply ret = AUX_NACK;
> +I2CBus *i2c_bus = aux_get_i2c_bus(bus);
> +size_t i;
> +bool is_write = false;
> +
> +DPRINTF("request 

Re: [Qemu-devel] [PATCH v4 1/1] xlnx-zynqmp: Add support for high DDR memory regions

2016-01-12 Thread Peter Crosthwaite
On Tue, Jan 12, 2016 at 1:59 PM, Alistair Francis
 wrote:
> On Tue, Jan 12, 2016 at 1:01 AM, Peter Maydell  
> wrote:
>> On 12 January 2016 at 00:24, Alistair Francis
>>  wrote:
>>> On Mon, Jan 11, 2016 at 8:04 AM, Peter Maydell  
>>> wrote:
 There are a couple of problems you're running into:

 (1) machine->ram_size is a ram_addr_t so might be 32 bit; you
 can do what virt.c does to avoid the warning and use a local
 uin64_t variable for the comparison
>>>
>>> Ok, I now create a uint64_t variable to store the value.
>>>

 (2) complaint about reassigning back to ram_size. this is spurious
 but you can avoid it by making this board behave the same way as
 virt.c, vexpress.c etc do if presented with an unsupported
 ram_size -- you should fail, rather than truncating and continuing.
>>>
>>> If I'm using a 64-bit variable to store the value won't this no longer
>>> be a problem?
>>
>> I think you should do the same thing the other boards do anyway.
>
> Ok, I have changed it to exit instead of resize.
>
>>
 (3) %llx is not the correct format string for a ram_addr_t:
 use RAM_ADDR_FMT. (This isn't making the compiler complain,
 but I noticed it looking at the code.)
>>>
>>> Again, isn't this fixed by changing to a variable?
>>
>> %llx isn't right for uint64_t either :-)
>
> I still have a %llx for the macro as it isn't a ram_addr_t.
>

Should be PRIx64 though.

Regards,
Peter

> Re sending now.
>
> Thanks,
>
> Alistair
>
>>
>> thanks
>> -- PMM
>>



Re: [Qemu-devel] [PATCH v4 1/1] xlnx-zynqmp: Add support for high DDR memory regions

2016-01-12 Thread Peter Crosthwaite
On Tue, Jan 12, 2016 at 2:07 PM, Alistair Francis
<alistair.fran...@xilinx.com> wrote:
> On Tue, Jan 12, 2016 at 2:00 PM, Peter Crosthwaite
> <crosthwaitepe...@gmail.com> wrote:
>> On Tue, Jan 12, 2016 at 1:59 PM, Alistair Francis
>> <alistair.fran...@xilinx.com> wrote:
>>> On Tue, Jan 12, 2016 at 1:01 AM, Peter Maydell <peter.mayd...@linaro.org> 
>>> wrote:
>>>> On 12 January 2016 at 00:24, Alistair Francis
>>>> <alistair.fran...@xilinx.com> wrote:
>>>>> On Mon, Jan 11, 2016 at 8:04 AM, Peter Maydell <peter.mayd...@linaro.org> 
>>>>> wrote:
>>>>>> There are a couple of problems you're running into:
>>>>>>
>>>>>> (1) machine->ram_size is a ram_addr_t so might be 32 bit; you
>>>>>> can do what virt.c does to avoid the warning and use a local
>>>>>> uin64_t variable for the comparison
>>>>>
>>>>> Ok, I now create a uint64_t variable to store the value.
>>>>>
>>>>>>
>>>>>> (2) complaint about reassigning back to ram_size. this is spurious
>>>>>> but you can avoid it by making this board behave the same way as
>>>>>> virt.c, vexpress.c etc do if presented with an unsupported
>>>>>> ram_size -- you should fail, rather than truncating and continuing.
>>>>>
>>>>> If I'm using a 64-bit variable to store the value won't this no longer
>>>>> be a problem?
>>>>
>>>> I think you should do the same thing the other boards do anyway.
>>>
>>> Ok, I have changed it to exit instead of resize.
>>>
>>>>
>>>>>> (3) %llx is not the correct format string for a ram_addr_t:
>>>>>> use RAM_ADDR_FMT. (This isn't making the compiler complain,
>>>>>> but I noticed it looking at the code.)
>>>>>
>>>>> Again, isn't this fixed by changing to a variable?
>>>>
>>>> %llx isn't right for uint64_t either :-)
>>>
>>> I still have a %llx for the macro as it isn't a ram_addr_t.
>>>
>>
>> Should be PRIx64 though.
>
> Then I get a compiler warning as the macro is a long long unsigned int.
>

Ahh, the llx is for printing the constant, which hasn't really changed
from original code anyway (other than a rename). I think the
RAM_ADDR_FMT  goes to uint64_t and the llx stays?

Regards,
Peter

> Thanks,
>
> Alistair
>
>>
>> Regards,
>> Peter
>>
>>> Re sending now.
>>>
>>> Thanks,
>>>
>>> Alistair
>>>
>>>>
>>>> thanks
>>>> -- PMM
>>>>
>>



Re: [Qemu-devel] [PATCH v3 6/7] bcm2836: add bcm2836 soc device

2016-01-12 Thread Peter Crosthwaite
On Tue, Jan 12, 2016 at 2:56 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
> Hi Peter,
>
> Thanks again for the reviews.
>
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Monday, 11 January 2016 19:57
>> On Thu, Dec 31, 2015 at 04:31:33PM -0800, Andrew Baumann wrote:
>> > +/* TODO: probably shouldn't be using smp_cpus here */
>>
>> I agree. I have started ignoring smp_cpus completely for new ARM SoCs,
>> as if you change the number of CPUs for a SoC, it is not that SoC
>> anymore. The virt platform is suitable for CPU scalability, whereas
>> with ARM SoCs, cpu # variation is invalid.
>>
>> > +assert(smp_cpus <= BCM2836_NCPUS);
>> > +for (n = 0; n < smp_cpus; n++) {
>>
>> So can we just use BCM2836_NCPUS here as the loop bound? Any
>> conditionals out there check the existance of CPUs can be removed or
>> promoted to assert() as a BCM2836 must always have 4 CPUs.
>
> I'd love to do that, but there's at least one good reason to respect the -smp 
> parameter and not start all the CPUs: with full-system emulation, qemu is 
> noticeably faster emulating a single-core target than multi-core. E.g., Linux 
> boots fine with -smp 1 (it fails to start the other CPUs but proceeds with 
> just one), and many users will be better off running it this way, so I 
> definitely don't want to break that.
>

What are the secondary CPUs doing in this case? In most systems they
end up penning on a WFI/WFE. Is Linux actually trying to do the SMP
bringup - are you are getting a secondary entry point?

If not and it is just a busy wait killing perf, start-powered-off
property might help. Is the firmware responsible for secondary-penning
an actual busy-wait or does it involve power-control periphs etc?

Regards,
Peter

> I tried always initing all 4 CPUs in bcm2836_init, and only starting a 
> configurable number (based on a property) in realize. However, arm 
> cpu_exec_init already adds the cpu to the global list of all CPUs, and if you 
> try to start the system in this state it quickly segfaults on uninitialized 
> state in the CPU, so it seems we shouldn't even init CPUs that won't later be 
> started. However, I can't refer to properties in the _init method, which is 
> why I'm stuck using the smp_cpus global.
>
> If you have a better suggestion, I'm all ears :) Would it make sense to defer 
> calling init() until the realize method, when we can access a property?
>
> Cheers,
> Andrew



Re: [Qemu-devel] [PATCH v3 7/7] raspi: add raspberry pi 2 machine

2016-01-12 Thread Peter Crosthwaite
On Tue, Jan 12, 2016 at 3:53 PM, Andrew Baumann
<andrew.baum...@microsoft.com> wrote:
>> From: Peter Crosthwaite [mailto:crosthwaitepe...@gmail.com]
>> Sent: Monday, 11 January 2016 19:58
> [...]
>> > +static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info
>> *info)
>>
>> This is almost identical to Highbank, I'm guessing you are stubbing monitor
>> firmware where you get away with nopping all the SMCs? Maybe we should
>> split
>> Highbanks version off to common code, and parameterise the few
>> differences.
>>
>> write_board_setup_dummy_monitior(ARMCPU *cpu ..., uint32_t scr_flags);
>>
>> or something like it. Makes sense to be in arm/boot.c .
>
> Actually, I added this only to make Linux happy (and yes, it was derived from 
> highbank). Without it, I was seeing complaints about:
> Ignoring attempt to switch CPSR_A flag from non-secure world with SCR.AW bit 
> clear
> Ignoring attempt to switch CPSR_F flag from non-secure world with SCR.FW bit 
> clear
>
> I don't believe anything actually uses the SMC handler after boot. I think 
> it's just an architectural requirement to flush the change to non-secure mode.
>
> I would prefer not to touch highbank, because I don't know how to test it. Is 
> it better to submit this patch without the board setup?
>

I can test Highbank for you, or you can use this project:

https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg00755.html

The build takes a while and costs about 50GB of disk space, but the
amount of setup needed should be pretty low.

FWIW, that was the test system that found the need for this FW in HB.

>>
>> > +{
>> > +static const uint32_t board_setup[] = {
>> > +/* MVBAR_ADDR: secure monitor vectors */
>> > +0xEAFE, /* (spin) */
>> > +0xEAFE, /* (spin) */
>> > +0xE1B0F00E, /* movs pc, lr ;SMC exception return */
>> > +0xEAFE, /* (spin) */
>> > +0xEAFE, /* (spin) */
>> > +0xEAFE, /* (spin) */
>> > +0xEAFE, /* (spin) */
>> > +0xEAFE, /* (spin) */
>> > +/* BOARDSETUP_ADDR */
>> > +0xE3A00B01, /* mov r0, #0x400 ;MVBAR_ADDR */
>> > +0xEE0C0F30, /* mcr p15, 0, r0, c12, c0, 1 ;set MVBAR */
>> > +0xE3A00031, /* mov r0, #0x31  ;enable AW, FW, NS 
>> > */
>> > +0xEE010F11, /* mcr p15, 0, r0, c1, c1, 0  ;write SCR */
>>
>> If combining with HB, could you do this as read-modify-write?
>>
>> > +0xE1A0100E, /* mov r1, lr ;save LR across SMC 
>> > */
>> > +0xE1600070, /* smc #0 ;monitor call */
>> > +0xE1A0F001, /* mov pc, r1 ;return */
>>
>> I'm looking at the Highbank version which doesn't save lr across the SMC and
>> wondering why it doesn't. Is this banked by CPU mode and do you get from
>> already-in-monitor-mode? Or simply, that Highbank code may have a bug?
>
> I think it's needed because I call the board setup blob on each core (from 
> the smpboot blob), but highbank doesn't. I found that I needed to do this to 
> avoid the above warnings on an SMP boot; I don't know why highbank doesn't.
>
> [...]
>> > +/* Allocate and map RAM */
>> > +memory_region_allocate_system_memory(>ram,
>> OBJECT(machine), "ram",
>> > + machine->ram_size);
>> > +memory_region_add_subregion_overlap(get_system_memory(), 0,
>> >ram, 0);
>>
>> I thought the SoC handled this now? Why do you need to add to
>> system_memory?
>
> If I don't map it here, how do RAM accesses from the CPUs work?
>

Do the CPUs not have their AS'es connected to your custom ASes by the SoC layer?

> Or are you saying that I should still do this, but do it in the SoC not the 
> board level?
>

I was hoping we could get away with 0 use of system_memory.

Regards,
Peter

> [...]
>> > +static void raspi2_machine_init(MachineClass *mc)
>> > +{
>> > +mc->desc = "Raspberry Pi 2";
>> > +mc->init = raspi2_init;
>> > +mc->block_default_type = IF_SD;
>>
>> > +mc->no_parallel = 1;
>> > +mc->no_floppy = 1;
>> > +mc->no_cdrom = 1;
>>
>> Curious, what do these do from a user-visible point of view? Maybe we
>> should
>> add them to more ARM boards as they certainly make sense.
>
> I think they turn off some redundant stuff in the UI (e.g., there's no 
> View->Parallel menu option). I'm guessing they also disable the -cdrom and  
> -fd* options, but didn't test that.
>
> Cheers,
> Andrew



Re: [Qemu-devel] [PATCH v10 5/7] hw/ptimer: Legalize running with delta = load = 0

2016-01-11 Thread Peter Crosthwaite
On Sat, Jan 09, 2016 at 08:39:53PM +0300, Dmitry Osipenko wrote:
> Currently ptimer would print error message and clear enable flag for an
> arming timer that has delta = load = 0. That actually could be a valid case
> for some hardware, like instant IRQ trigger for oneshot timer or continuous
> in periodic mode. Support those cases by printing error message only when
> period = 0.
> 

Isn't the continuous-periodic the same as period = 0, so if we were to really
support this, there should be no error message. This would simplify as we
can remove the conditionals of 0 period completely and rely only on the
too-fast clamps you add in previous patches.

Regards,
Peter

> In addition, don't load one-shot timer when delta = 0 and actually stop the
> timer by timer_del().
> 
> Signed-off-by: Dmitry Osipenko 
> ---
>  hw/core/ptimer.c | 21 ++---
>  1 file changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
> index 6960738..42e44f9 100644
> --- a/hw/core/ptimer.c
> +++ b/hw/core/ptimer.c
> @@ -36,13 +36,20 @@ static void ptimer_reload(ptimer_state *s)
>  {
>  uint32_t period_frac = s->period_frac;
>  uint64_t period = s->period;
> +int periodic = (s->enabled == 1);
>  
> -if (s->delta == 0) {
> +if (s->delta == 0 && period != 0) {
>  ptimer_trigger(s);
> -s->delta = s->limit;
> +if (periodic) {
> +s->delta = s->limit;
> +}
>  }
> -if (s->delta == 0 || s->period == 0) {
> -fprintf(stderr, "Timer with period zero, disabling\n");
> +if (s->delta == 0 || period == 0) {
> +if (period == 0) {
> +fprintf(stderr, "Timer with period zero, disabling\n");
> +s->delta = 0;
> +}
> +timer_del(s->timer);
>  s->enabled = 0;
>  return;
>  }
> @@ -56,7 +63,7 @@ static void ptimer_reload(ptimer_state *s)
>   * on the current generation of host machines.
>   */
>  
> -if ((s->enabled == 1) && !use_icount && (s->delta * period < 1)) {
> +if (periodic && !use_icount && (s->delta * period < 1)) {
>  period = 1 / s->delta;
>  period_frac = 0;
>  }
> @@ -86,14 +93,14 @@ uint64_t ptimer_get_count(ptimer_state *s)
>  int enabled = s->enabled;
>  uint64_t counter;
>  
> -if (enabled) {
> +if (enabled && s->delta != 0) {
>  int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>  int64_t next = s->next_event;
>  int expired = (now - next >= 0);
>  int oneshot = (enabled == 2);
>  
>  /* Figure out the current counter value.  */
> -if (s->period == 0 || (expired && (use_icount || oneshot))) {
> +if (expired && (use_icount || oneshot)) {
>  /* Prevent timer underflowing if it should already have
> triggered.  */
>  counter = 0;
> -- 
> 2.6.4
> 



  1   2   3   4   5   6   7   8   9   10   >