[PATCH] usb-hub: Add support for v2.0 hubs

2024-09-18 Thread Guenter Roeck
When adding a high speed USB device to the USB hub supported by qemu,
it is added in full speed mode. Here is an example for a storage device.

/:  Bus 001.Port 001: Dev 001, Class=root_hub, Driver=platform-uhci/2p, 12M
|__ Port 002: Dev 002, If 0, Class=Hub, Driver=hub/8p, 12M
|__ Port 001: Dev 003, If 0, Class=Human Interface Device, 
Driver=usbhid, 12M
|__ Port 002: Dev 004, If 0, Class=Human Interface Device, 
Driver=usbhid, 12M
|__ Port 003: Dev 005, If 0, Class=Mass Storage, Driver=usb-storage, 12M

This also triggers messages such as

usb 1-2.3: new full-speed USB device number 5 using platform-uhci
usb 1-2.3: not running at top speed; connect to a high speed hub

when such devices are instantiated in the host (example from Linux).

Add basic support for USB v2.0 hubs to solve the problem. The usb_version
device parameter configures the USB version; version 1 is default for
compatibility reasons. Example:

-device usb-hub,bus=usb-bus.1,port=1,usb_version=2

This command line parameter can be used to attach devices to the hub in
high speed mode, as seen in the following example.

/:  Bus 002.Port 001: Dev 001, Class=root_hub, Driver=ehci-platform/6p, 480M
|__ Port 001: Dev 002, If 0, Class=Hub, Driver=hub/8p, 480M
|__ Port 002: Dev 004, If 0, Class=Mass Storage, Driver=usb-storage, 
480M

and

usb 2-1.2: new high-speed USB device number 4 using ehci-platform
usb 2-1.2: New USB device found, idVendor=46f4, idProduct=0001, bcdDevice= 0.00

To distinguish v1 from v2 instantiated hubs, the device version is set to
2.01 (from 1.01) if the hub ist instantiated as USB v2 hub. The product
name is set to "QEMU USB v2.0 Hub".

Signed-off-by: Guenter Roeck 
---
 hw/usb/dev-hub.c | 85 +++-
 1 file changed, 76 insertions(+), 9 deletions(-)

diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 06e9537d03..0ecc6828cb 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -46,6 +46,7 @@ struct USBHubState {
 USBDevice dev;
 USBEndpoint *intr;
 uint32_t num_ports;
+uint32_t usb_version;
 bool port_power;
 QEMUTimer *port_timer;
 USBHubPort ports[MAX_PORTS];
@@ -100,12 +101,14 @@ OBJECT_DECLARE_SIMPLE_TYPE(USBHubState, USB_HUB)
 enum {
 STR_MANUFACTURER = 1,
 STR_PRODUCT,
+STR_PRODUCT_V2,
 STR_SERIALNUMBER,
 };
 
 static const USBDescStrings desc_strings = {
 [STR_MANUFACTURER] = "QEMU",
 [STR_PRODUCT]  = "QEMU USB Hub",
+[STR_PRODUCT_V2]   = "QEMU USB v2.0 Hub",
 [STR_SERIALNUMBER] = "314159",
 };
 
@@ -123,6 +126,20 @@ static const USBDescIface desc_iface_hub = {
 }
 };
 
+static const USBDescIface desc_iface_hub_v2 = {
+.bInterfaceNumber  = 0,
+.bNumEndpoints = 1,
+.bInterfaceClass   = USB_CLASS_HUB,
+.eps = (USBDescEndpoint[]) {
+{
+.bEndpointAddress  = USB_DIR_IN | 0x01,
+.bmAttributes  = USB_ENDPOINT_XFER_INT,
+.wMaxPacketSize= 512,
+.bInterval = 10,
+},
+}
+};
+
 static const USBDescDevice desc_device_hub = {
 .bcdUSB= 0x0110,
 .bDeviceClass  = USB_CLASS_HUB,
@@ -140,6 +157,23 @@ static const USBDescDevice desc_device_hub = {
 },
 };
 
+static const USBDescDevice desc_device_hub_v2 = {
+.bcdUSB= 0x0200,
+.bDeviceClass  = USB_CLASS_HUB,
+.bMaxPacketSize0   = 64,
+.bNumConfigurations= 1,
+.confs = (USBDescConfig[]) {
+{
+.bNumInterfaces= 1,
+.bConfigurationValue   = 1,
+.bmAttributes  = USB_CFG_ATT_ONE | USB_CFG_ATT_SELFPOWER |
+ USB_CFG_ATT_WAKEUP,
+.nif = 1,
+.ifs = &desc_iface_hub_v2,
+},
+},
+};
+
 static const USBDesc desc_hub = {
 .id = {
 .idVendor  = 0x0409,
@@ -153,6 +187,20 @@ static const USBDesc desc_hub = {
 .str  = desc_strings,
 };
 
+static const USBDesc desc_hub_v2 = {
+.id = {
+.idVendor  = 0x0409,
+.idProduct = 0x55aa,
+.bcdDevice = 0x0201,
+.iManufacturer = STR_MANUFACTURER,
+.iProduct  = STR_PRODUCT_V2,
+.iSerialNumber = STR_SERIALNUMBER,
+},
+.full = &desc_device_hub,
+.high = &desc_device_hub_v2,
+.str  = desc_strings,
+};
+
 static const uint8_t qemu_hub_hub_descriptor[] =
 {
 0x00,   /*  u8  bLength; patched in later */
@@ -195,15 +243,20 @@ static bool usb_hub_port_clear(USBHubPort *port, uint16_t 
status)
 return usb_hub_port_change(port, status);
 }
 
-static bool usb_hub_port_update(USBHubPort *port)
+static bool usb_hub_port_update(USBHubState *s, USBHubPort *port)
 {
 bool notify 

Re: qemu emulation for USB ports of Allwinner H3

2024-09-16 Thread Guenter Roeck

On 9/13/24 15:20, Niek Linnenbank wrote:

Hello Guenter, Gerd,

Thanks for bringing up the question. To be honest I do not know a lot about USB 
internals.
When adding the orangepi-pc board emulation, it seemed fairly easy to add it, 
but apart from a few basic tests, I did not use the USB functionality 
extensively.

I do own the actual Orange Pi PC board hardware, so I downloaded the 
'Orangepipc_2.0.8_ubuntu_bionic_server_linux5.4.65.7z' image from the official 
page to test:
http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-PC.html
 
<http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-PC.html>

After booting that image from an SD card with a serial console, this is the 
output from the same 'lsusb' command:

root@orangepipc:~# lsusb
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 009 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
root@orangepipc:~# uname -a
Linux orangepipc 5.4.65-sunxi #2.0.8 SMP Mon Oct 26 10:20:38 CST 2020 armv7l 
armv7l armv7l GNU/Linux
root@orangepipc:~# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"

It does look like the same output compared to what we see under Qemu. But I'm 
not very sure if this confirms we are emulating correctly or not.



Yes, I found that as well, and Gerd has reported the same. The main difference,
as far as I can see, is that the host sees different register contents.
I am not sure if that is worth fixing. Either case it is not my highest 
priority.

Thanks,
Guenter


Regards,
Niek

On Mon, Sep 9, 2024 at 11:33 AM Gerd Hoffmann mailto:kra...@redhat.com>> wrote:

On Sun, Sep 08, 2024 at 11:36:18AM GMT, Guenter Roeck wrote:
 > Hi,
 >
 > the Allwinner H3 USB port qemu emulation creates separate USB ports
 > for its EHCI and OHCI controllers, resulting in a total of 8 USB ports.
 > From the orangepi-pc emulation:
 >
 > # lsusb
 > Bus 005 Device 001: ID 1d6b:0002
 > Bus 003 Device 001: ID 1d6b:0002
 > Bus 001 Device 001: ID 1d6b:0002
 > Bus 008 Device 001: ID 1d6b:0002
 > Bus 006 Device 001: ID 1d6b:0001
 > Bus 004 Device 001: ID 1d6b:0001
 > Bus 002 Device 001: ID 1d6b:0002
 > Bus 009 Device 001: ID 1d6b:0001
 > Bus 007 Device 001: ID 1d6b:0001
 >
 > The SoC supports EHCI companion interfaces, and my understanding is that
 > it only has four physical USB ports. Does the real hardware instantiate
 > separate EHCI and OHCI interfaces (for a total of 8 USB ports), or does 
it
 > use the companion functionality ?

Well, on the guest side you'll see 8 ports even when using the companion
functionality.  Each physical usb port has one ehci port (used when you
plug in usb 2.0+ devices) and one ohci port (used when you plug in usb
1.1 devices).

The main difference is on the qemu backend side.  When using the
companion functionality you have a single qemu usb bus accepting both
1.1 and 2.0+ devices.  When not using the companion functionality you
have one usb bus accepting 2.0+ devices and another usb bus accepting
usb 1.1 devices ...

The guest-visible difference is an per-port bit in ehci registers which
controls whenever ehci or the companion manages the device plugged in.
This bit exists for backward compatibility (guests without ehci driver
can manage all devices via ohci, with usb 2.0+ devices being downgraded
to 1.1 compatibility mode then).

 > If the real hardware only instantiates four USB ports (or, in other 
words,
 > if it utilizes EHCI companion functionality), would it make sense to
 > reflect that in qemu ?

Yes.

take care,
   Gerd



--
Niek Linnenbank






Re: [PATCH v2] aspeed: Deprecate the tacoma-bmc machine

2024-09-11 Thread Guenter Roeck

On 9/11/24 10:33, Cédric Le Goater wrote:

On 9/9/24 17:10, Guenter Roeck wrote:

On 9/9/24 04:20, Joel Stanley wrote:

On Sat, 31 Aug 2024 at 05:41, Guenter Roeck  wrote:


On Fri, Aug 30, 2024 at 10:09:25AM +0200, Cédric Le Goater wrote:

Hello,



I solved the problem by adding support for IBM Bonnell (which instantiates
the TPM chip through its devicetree file, similar to tacoma-bmc) to my local
copy of qemu.


Hmm, did you copy the rainier-bmc machine definition ?


For aspeed_machine_bonnell_class_init(), pretty much yes, since I don't know
the actual hardware. For I2C initialization I used the devicetree file.
You can find the patch in the master-local or v9.1.0-local branches
of my qemu clone at https://github.com/groeck/qemu if you are interested.


Oh nice ! Let's merge the IBM Bonnell machine. We can ask IBM to help fixing
the definitions (strapping). Enabling the PCA9554 is good to have too.


Instead of adding Bonnell to qemu, could we use the Rainier machine? I
know the kernel device tree removed the i2c tpm, but there's no harm
in it being present in the qemu machine.

The bonnell device tree should boot fine on the rainier machine for
your purposes.



Yes, I confirmed that works. Ok, I'll do that.


So I will drop the bonnell to avoid redundancy. Is that OK ?


Ok with me.

Guenter





Re: [PATCH for-9.2 00/53] arm: Drop deprecated boards

2024-09-09 Thread Guenter Roeck
On Mon, Sep 09, 2024 at 05:45:35PM +0200, Philippe Mathieu-Daudé wrote:
> On 9/9/24 17:02, Peter Maydell wrote:
> > On Mon, 9 Sept 2024 at 15:55, Guenter Roeck  wrote:
> > > 
> > > On 9/9/24 06:40, Philippe Mathieu-Daudé wrote:
> > > > Hi,
> > > > 
> > > > On 3/9/24 18:06, Peter Maydell wrote:
> > > > > This patchset removes the various Arm machines which we deprecated
> > > > > for the 9.0 release and are therefore allowed to remove for the 9.2
> > > > > release:
> > > > >akita, borzoi, cheetah, connex, mainstone, n800, n810,
> > > > >spitz, terrier, tosa, verdex, z2
> > > > 
> > > > > The series includes removal of some code which while not strictly
> > > > > specific to these machines was in practice used only by them:
> > > > >* the OneNAND flash memory device
> > > > >* the PCMCIA subsystem
> > > > >* the MUSB USB2.0 OTG USB controller chip (hcd-musb)
> > > > 
> > > > > thanks
> > > > > -- PMM
> > > > > 
> > > > > Peter Maydell (53):
> > > > > hw/input: Drop ADS7846 device
> > > > > hw/adc: Remove MAX111X device
> > > > > hw/gpio: Remove MAX7310 device
> > > 
> > > max7310 is a gpio controller which is at least somewhat compatible
> > > to pca953x. It is used on imx6qdl-sabreauto, and also instantiated
> > > by Linux with the INT3491 ACPI ID.
> 
> Can you use the PCF8574 port expander instead? It uses more recent
> QEMU design model.
> 

Ok with me.

Guenter



Re: [PATCH v2] aspeed: Deprecate the tacoma-bmc machine

2024-09-09 Thread Guenter Roeck

On 9/9/24 04:20, Joel Stanley wrote:

On Sat, 31 Aug 2024 at 05:41, Guenter Roeck  wrote:


On Fri, Aug 30, 2024 at 10:09:25AM +0200, Cédric Le Goater wrote:

Hello,



I solved the problem by adding support for IBM Bonnell (which instantiates
the TPM chip through its devicetree file, similar to tacoma-bmc) to my local
copy of qemu.


Hmm, did you copy the rainier-bmc machine definition ?


For aspeed_machine_bonnell_class_init(), pretty much yes, since I don't know
the actual hardware. For I2C initialization I used the devicetree file.
You can find the patch in the master-local or v9.1.0-local branches
of my qemu clone at https://github.com/groeck/qemu if you are interested.


Oh nice ! Let's merge the IBM Bonnell machine. We can ask IBM to help fixing
the definitions (strapping). Enabling the PCA9554 is good to have too.


Instead of adding Bonnell to qemu, could we use the Rainier machine? I
know the kernel device tree removed the i2c tpm, but there's no harm
in it being present in the qemu machine.

The bonnell device tree should boot fine on the rainier machine for
your purposes.



Yes, I confirmed that works. Ok, I'll do that.

Thanks,
Guenter




Re: [PATCH for-9.2 00/53] arm: Drop deprecated boards

2024-09-09 Thread Guenter Roeck

On 9/9/24 06:40, Philippe Mathieu-Daudé wrote:

Hi,

On 3/9/24 18:06, Peter Maydell wrote:

This patchset removes the various Arm machines which we deprecated
for the 9.0 release and are therefore allowed to remove for the 9.2
release:
  akita, borzoi, cheetah, connex, mainstone, n800, n810,
  spitz, terrier, tosa, verdex, z2



The series includes removal of some code which while not strictly
specific to these machines was in practice used only by them:
  * the OneNAND flash memory device
  * the PCMCIA subsystem
  * the MUSB USB2.0 OTG USB controller chip (hcd-musb)



thanks
-- PMM

Peter Maydell (53):
   hw/input: Drop ADS7846 device
   hw/adc: Remove MAX111X device
   hw/gpio: Remove MAX7310 device


max7310 is a gpio controller which is at least somewhat compatible
to pca953x. It is used on imx6qdl-sabreauto, and also instantiated
by Linux with the INT3491 ACPI ID.

Is there real pressure to remove support for such devices ?

Thanks,
Guenter


   hw/input: Remove tsc2005 touchscreen controller
   hw/input: Remove tsc210x device
   hw/rtc: Remove twl92230 device
   hw/input: Remove lm832x device
   hw/usb: Remove tusb6010 USB controller
   hw/usb: Remove MUSB USB host controller


Some of these devices are user-creatable and only rely on a bus
(not a particular removed machine), so could potentially be used
on other maintained machines which expose a similar bus.
We don't have in-tree (tests/) examples, but I wonder if it is OK
to remove them without first explicitly deprecating them in
docs/about/deprecated.rst. I wouldn't surprise users when 9.2 is
release. Maybe this isn't an issue, but I prefer to mention it
now to be sure.

Regards,

Phil.





qemu emulation for USB ports of Allwinner H3

2024-09-08 Thread Guenter Roeck
Hi,

the Allwinner H3 USB port qemu emulation creates separate USB ports
for its EHCI and OHCI controllers, resulting in a total of 8 USB ports.
>From the orangepi-pc emulation:

# lsusb
Bus 005 Device 001: ID 1d6b:0002
Bus 003 Device 001: ID 1d6b:0002
Bus 001 Device 001: ID 1d6b:0002
Bus 008 Device 001: ID 1d6b:0002
Bus 006 Device 001: ID 1d6b:0001
Bus 004 Device 001: ID 1d6b:0001
Bus 002 Device 001: ID 1d6b:0002
Bus 009 Device 001: ID 1d6b:0001
Bus 007 Device 001: ID 1d6b:0001

The SoC supports EHCI companion interfaces, and my understanding is that
it only has four physical USB ports. Does the real hardware instantiate
separate EHCI and OHCI interfaces (for a total of 8 USB ports), or does it
use the companion functionality ?

If the real hardware only instantiates four USB ports (or, in other words,
if it utilizes EHCI companion functionality), would it make sense to
reflect that in qemu ?

Thanks,
Guenter



Re: [PATCH v2 2/5] hw/sensor/tmp105: Use registerfields API

2024-09-06 Thread Guenter Roeck
On Fri, Sep 06, 2024 at 05:49:08PM +0200, Philippe Mathieu-Daudé wrote:
> To improve readability, use the registerfields API.
> Define the register bits with FIELD(), and use the
> FIELD_EX8() and FIELD_DP8() macros. Remove the
> abbreviations in comments.
> 
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Guenter Roeck 



Re: [PATCH v2 3/5] hw/sensor/tmp105: Pass 'oneshot' argument to tmp105_alarm_update()

2024-09-06 Thread Guenter Roeck
On Fri, Sep 06, 2024 at 05:49:09PM +0200, Philippe Mathieu-Daudé wrote:
> The next commit will clear the ONE_SHOT bit in the WRITE
> path (to keep the READ path trivial). As a preliminary step,
> pass the 'oneshot' value as argument to tmp105_alarm_update().
> No logical change intended.
> 
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Guenter Roeck 



Re: [PATCH] aspeed: Add support for IBM Bonnell

2024-09-06 Thread Guenter Roeck

On 9/6/24 07:49, Cédric Le Goater wrote:

Joel,

Would have access to a Bonnell BMC ? To get the HW strapping
register values.

On 9/6/24 14:35, Guenter Roeck wrote:

Introduce support for the IBM Bonnell BMC.

Use Rainier machine information for HW strapping and other machine details
since the actual hardware configuration is unknown. I2C device
instantiation is based on the devicetree file in the upstream Linux kernel.

Major difference to Rainier is that the Bonnell devicetree file
instantiates a TPM. It is therefore possible to test TPM functionality
without having to instantiate the TPM manually from the Linux command
line.

Signed-off-by: Guenter Roeck 
---
  hw/arm/aspeed.c | 87 +
  1 file changed, 87 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index fd5603f7aa..4f833c5708 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -865,6 +865,70 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc)
  create_pca9552(soc, 15, 0x60);
  }
+static void bonnell_bmc_i2c_init(AspeedMachineState *bmc)
+{
+    AspeedSoCState *soc = bmc->soc;
+    I2CBus *bus;
+
+    bus = aspeed_i2c_get_bus(&soc->i2c, 0);
+
+    at24c_eeprom_init(bus, 0x51, 8 * KiB);  /* atmel,24c64 */
+    /* tca9554@11:20 */
+    i2c_slave_create_simple(bus, "pca9554", 0x20);



The other machine tend to simply do :

   i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "pca9554", 0x20);

But that's fine.



I know, I tried to avoid multiple calls to aspeed_i2c_get_bus() if the bus
is needed multiple times.

Thanks,
Guenter




[PATCH 3/3] tmp105: Lower 4 bit of limit registers are always 0

2024-09-06 Thread Guenter Roeck
Per datasheet, "HIGH AND LOW LIMIT REGISTERS", the lower 4 bit
of the limit registers are unused and always report 0.
The lower 4 bit should not be used for temperature comparisons,
so mask the unused bits before storing the limits.

Signed-off-by: Guenter Roeck 
---
 hw/sensor/tmp105.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sensor/tmp105.c b/hw/sensor/tmp105.c
index 22728798f7..5fd30f8d50 100644
--- a/hw/sensor/tmp105.c
+++ b/hw/sensor/tmp105.c
@@ -166,7 +166,7 @@ static void tmp105_write(TMP105State *s)
 case TMP105_REG_T_HIGH:
 if (s->len >= 3)
 s->limit[s->pointer & 1] = (int16_t)
-uint16_t) s->buf[0]) << 8) | s->buf[1]);
+uint16_t) s->buf[0]) << 8) | (s->buf[1] & 0xf0));
 tmp105_alarm_update(s);
 break;
 }
-- 
2.45.2




[PATCH 1/3] tmp105: Coding style fixes

2024-09-06 Thread Guenter Roeck
Coding style asks for no space between variable and "++". The next patch
in this series will change one of those assignments. Instead of changing
just one with that patch, change all of them for consistency.

While at it, also fix other coding style problems reported by checkpatch.

Signed-off-by: Guenter Roeck 
---
 hw/sensor/tmp105.c | 40 +---
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/hw/sensor/tmp105.c b/hw/sensor/tmp105.c
index a8730d0b7f..77fbf2f8d3 100644
--- a/hw/sensor/tmp105.c
+++ b/hw/sensor/tmp105.c
@@ -29,16 +29,17 @@
 
 static void tmp105_interrupt_update(TMP105State *s)
 {
-qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1));  /* POL */
+qemu_set_irq(s->pin, s->alarm ^ ((~s->config >> 2) & 1));   /* POL */
 }
 
 static void tmp105_alarm_update(TMP105State *s)
 {
-if ((s->config >> 0) & 1) {/* SD */
-if ((s->config >> 7) & 1)  /* OS */
-s->config &= ~(1 << 7);/* OS */
-else
+if ((s->config >> 0) & 1) { /* SD */
+if ((s->config >> 7) & 1) { /* OS */
+s->config &= ~(1 << 7); /* OS */
+} else {
 return;
+}
 }
 
 if (s->config >> 1 & 1) {
@@ -89,7 +90,8 @@ static void tmp105_get_temperature(Object *obj, Visitor *v, 
const char *name,
 visit_type_int(v, name, &value, errp);
 }
 
-/* Units are 0.001 centigrades relative to 0 C.  s->temperature is 8.8
+/*
+ * Units are 0.001 centigrades relative to 0 C.  s->temperature is 8.8
  * fixed point, so units are 1/256 centigrades.  A simple ratio will do.
  */
 static void tmp105_set_temperature(Object *obj, Visitor *v, const char *name,
@@ -118,30 +120,30 @@ static void tmp105_read(TMP105State *s)
 {
 s->len = 0;
 
-if ((s->config >> 1) & 1) {/* TM */
+if ((s->config >> 1) & 1) { /* TM */
 s->alarm = 0;
 tmp105_interrupt_update(s);
 }
 
 switch (s->pointer & 3) {
 case TMP105_REG_TEMPERATURE:
-s->buf[s->len ++] = (((uint16_t) s->temperature) >> 8);
-s->buf[s->len ++] = (((uint16_t) s->temperature) >> 0) &
-(0xf0 << ((~s->config >> 5) & 3)); /* R */
+s->buf[s->len++] = (((uint16_t) s->temperature) >> 8);
+s->buf[s->len++] = (((uint16_t) s->temperature) >> 0) &
+(0xf0 << ((~s->config >> 5) & 3));  /* R */
 break;
 
 case TMP105_REG_CONFIG:
-s->buf[s->len ++] = s->config;
+s->buf[s->len++] = s->config;
 break;
 
 case TMP105_REG_T_LOW:
-s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 8;
-s->buf[s->len ++] = ((uint16_t) s->limit[0]) >> 0;
+s->buf[s->len++] = ((uint16_t) s->limit[0]) >> 8;
+s->buf[s->len++] = ((uint16_t) s->limit[0]) >> 0;
 break;
 
 case TMP105_REG_T_HIGH:
-s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 8;
-s->buf[s->len ++] = ((uint16_t) s->limit[1]) >> 0;
+s->buf[s->len++] = ((uint16_t) s->limit[1]) >> 8;
+s->buf[s->len++] = ((uint16_t) s->limit[1]) >> 0;
 break;
 }
 }
@@ -153,10 +155,10 @@ static void tmp105_write(TMP105State *s)
 break;
 
 case TMP105_REG_CONFIG:
-if (s->buf[0] & ~s->config & (1 << 0)) /* SD */
+if (s->buf[0] & ~s->config & (1 << 0))  /* SD */
 printf("%s: TMP105 shutdown\n", __func__);
 s->config = s->buf[0];
-s->faults = tmp105_faultq[(s->config >> 3) & 3];   /* F */
+s->faults = tmp105_faultq[(s->config >> 3) & 3];/* F */
 tmp105_alarm_update(s);
 break;
 
@@ -175,7 +177,7 @@ static uint8_t tmp105_rx(I2CSlave *i2c)
 TMP105State *s = TMP105(i2c);
 
 if (s->len < 2) {
-return s->buf[s->len ++];
+return s->buf[s->len++];
 } else {
 return 0xff;
 }
@@ -215,7 +217,7 @@ static int tmp105_post_load(void *opaque, int version_id)
 {
 TMP105State *s = opaque;
 
-s->faults = tmp105_faultq[(s->config >> 3) & 3];   /* F */
+s->faults = tmp105_faultq[(s->config >> 3) & 3];/* F */
 
 tmp105_interrupt_update(s);
 return 0;
-- 
2.45.2




[PATCH 2/3] tmp105: OS (one-shot) bit in configuration register always returns 0

2024-09-06 Thread Guenter Roeck
Per datasheet, "ONE-SHOT (OS)", the OS bit always returns 0 when reading
the configuration register.

Signed-off-by: Guenter Roeck 
---
 hw/sensor/tmp105.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sensor/tmp105.c b/hw/sensor/tmp105.c
index 77fbf2f8d3..22728798f7 100644
--- a/hw/sensor/tmp105.c
+++ b/hw/sensor/tmp105.c
@@ -133,7 +133,7 @@ static void tmp105_read(TMP105State *s)
 break;
 
 case TMP105_REG_CONFIG:
-s->buf[s->len++] = s->config;
+s->buf[s->len++] = s->config & 0x7f;
 break;
 
 case TMP105_REG_T_LOW:
-- 
2.45.2




[PATCH 0/3] tmp105: Improvements and fixes

2024-09-06 Thread Guenter Roeck
Fix coding style issues as well as a couple of implementation bugs.


Guenter Roeck (3):
  tmp105: Coding style fixes
  tmp105: OS (one-shot) bit in configuration register always returns 0
  tmp105: Lower 4 bit of limit registers are always 0

 hw/sensor/tmp105.c | 42 ++
 1 file changed, 22 insertions(+), 20 deletions(-)



[PATCH] aspeed: Add support for IBM Bonnell

2024-09-06 Thread Guenter Roeck
Introduce support for the IBM Bonnell BMC.

Use Rainier machine information for HW strapping and other machine details
since the actual hardware configuration is unknown. I2C device
instantiation is based on the devicetree file in the upstream Linux kernel.

Major difference to Rainier is that the Bonnell devicetree file
instantiates a TPM. It is therefore possible to test TPM functionality
without having to instantiate the TPM manually from the Linux command
line.

Signed-off-by: Guenter Roeck 
---
 hw/arm/aspeed.c | 87 +
 1 file changed, 87 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index fd5603f7aa..4f833c5708 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -865,6 +865,70 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc)
 create_pca9552(soc, 15, 0x60);
 }
 
+static void bonnell_bmc_i2c_init(AspeedMachineState *bmc)
+{
+AspeedSoCState *soc = bmc->soc;
+I2CBus *bus;
+
+bus = aspeed_i2c_get_bus(&soc->i2c, 0);
+
+at24c_eeprom_init(bus, 0x51, 8 * KiB);  /* atmel,24c64 */
+/* tca9554@11:20 */
+i2c_slave_create_simple(bus, "pca9554", 0x20);
+
+/* ucd90160@2:64 */
+
+/* fsg032@3:5a */
+/* fsg032@3:5b */
+
+bus = aspeed_i2c_get_bus(&soc->i2c, 7);
+
+/* si7020@7:40 */
+
+/* Bonnell expects a TMP275 but a TMP105 is compatible */
+i2c_slave_create_simple(bus, TYPE_TMP105, 0x48);
+at24c_eeprom_init(bus, 0x50, 8 * KiB);  /* atmel,24c64 */
+at24c_eeprom_init(bus, 0x51, 8 * KiB);  /* atmel,24c64 */
+i2c_slave_create_simple(bus, "max31785", 0x52);
+
+/* pca9551; assume/hope pca9552 is compatible enough */
+create_pca9552(soc, 7, 0x60);
+
+/* ibm,op-panel@7:62 */
+/* dps310@7:76 */
+
+bus = aspeed_i2c_get_bus(&soc->i2c, 8);
+
+/* rx8900@8:32 */
+
+/* Bonnell expects a TMP275 but a TMP105 is compatible */
+i2c_slave_create_simple(bus, TYPE_TMP105, 0x48);
+at24c_eeprom_init(bus, 0x51, 16 * KiB);  /* atmel,24c128 */
+
+/* pca9551@8:60 */
+create_pca9552(soc, 8, 0x60);
+
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c);
+
+bus = aspeed_i2c_get_bus(&soc->i2c, 11);
+
+/* tca9554@11:20 */
+i2c_slave_create_simple(bus, "pca9554", 0x20);
+i2c_slave_create_simple(bus, "tmp423", 0x4c);
+/* pca9849@11:75 */
+i2c_slave_create_simple(bus, "pca9546", 0x75);
+
+/* npct75x@12:2e (tpm) */
+
+/* atmel,24c64 */
+at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 12), 0x50, 8 * KiB);
+
+/* atmel,24c64 */
+at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 13), 0x50, 8 * KiB);
+/* pca9551@13:60 */
+create_pca9552(soc, 13, 0x60);
+}
+
 static void get_pca9548_channels(I2CBus *bus, uint8_t mux_addr,
  I2CBus **channels)
 {
@@ -1488,6 +1552,25 @@ static void 
aspeed_machine_rainier_class_init(ObjectClass *oc, void *data)
 aspeed_machine_ast2600_class_emmc_init(oc);
 };
 
+static void aspeed_machine_bonnell_class_init(ObjectClass *oc, void *data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+mc->desc   = "IBM Bonnell BMC (Cortex-A7)";
+amc->soc_name  = "ast2600-a3";
+amc->hw_strap1 = RAINIER_BMC_HW_STRAP1;
+amc->hw_strap2 = RAINIER_BMC_HW_STRAP2;
+amc->fmc_model = "mx66l1g45g";
+amc->spi_model = "mx66l1g45g";
+amc->num_cs= 2;
+amc->macs_mask  = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
+amc->i2c_init  = bonnell_bmc_i2c_init;
+mc->default_ram_size = 1 * GiB;
+aspeed_machine_class_init_cpus_defaults(mc);
+aspeed_machine_ast2600_class_emmc_init(oc);
+};
+
 #define FUJI_BMC_RAM_SIZE ASPEED_RAM_SIZE(2 * GiB)
 
 static void aspeed_machine_fuji_class_init(ObjectClass *oc, void *data)
@@ -1776,6 +1859,10 @@ static const TypeInfo aspeed_machine_types[] = {
 .name  = MACHINE_TYPE_NAME("rainier-bmc"),
 .parent= TYPE_ASPEED_MACHINE,
 .class_init= aspeed_machine_rainier_class_init,
+}, {
+.name  = MACHINE_TYPE_NAME("bonnell-bmc"),
+.parent= TYPE_ASPEED_MACHINE,
+.class_init= aspeed_machine_bonnell_class_init,
 }, {
 .name  = MACHINE_TYPE_NAME("fuji-bmc"),
 .parent= TYPE_ASPEED_MACHINE,
-- 
2.45.2




[RFC PATCH 8/8] aspeed: Add uhci support for ast2400 and ast2500

2024-09-06 Thread Guenter Roeck
Enable UHCI support for ast2400 and ast2500 SoCs. With this patch,
the UHCI port is successfully instantiated on the ast2500-evb machine.

Signed-off-by: Guenter Roeck 
---
 hw/arm/aspeed_ast2400.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/hw/arm/aspeed_ast2400.c b/hw/arm/aspeed_ast2400.c
index d125886207..93bfe3e3dd 100644
--- a/hw/arm/aspeed_ast2400.c
+++ b/hw/arm/aspeed_ast2400.c
@@ -31,6 +31,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
 [ASPEED_DEV_FMC]= 0x1E62,
 [ASPEED_DEV_SPI1]   = 0x1E63,
 [ASPEED_DEV_EHCI1]  = 0x1E6A1000,
+[ASPEED_DEV_UHCI]   = 0x1E6B,
 [ASPEED_DEV_VIC]= 0x1E6C,
 [ASPEED_DEV_SDMC]   = 0x1E6E,
 [ASPEED_DEV_SCU]= 0x1E6E2000,
@@ -68,6 +69,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = {
 [ASPEED_DEV_SPI2]   = 0x1E631000,
 [ASPEED_DEV_EHCI1]  = 0x1E6A1000,
 [ASPEED_DEV_EHCI2]  = 0x1E6A3000,
+[ASPEED_DEV_UHCI]   = 0x1E6B,
 [ASPEED_DEV_VIC]= 0x1E6C,
 [ASPEED_DEV_SDMC]   = 0x1E6E,
 [ASPEED_DEV_SCU]= 0x1E6E2000,
@@ -107,6 +109,7 @@ static const int aspeed_soc_ast2400_irqmap[] = {
 [ASPEED_DEV_FMC]= 19,
 [ASPEED_DEV_EHCI1]  = 5,
 [ASPEED_DEV_EHCI2]  = 13,
+[ASPEED_DEV_UHCI]   = 14,
 [ASPEED_DEV_SDMC]   = 0,
 [ASPEED_DEV_SCU]= 21,
 [ASPEED_DEV_ADC]= 31,
@@ -199,6 +202,8 @@ static void aspeed_ast2400_soc_init(Object *obj)
 TYPE_PLATFORM_EHCI);
 }
 
+object_initialize_child(obj, "uhci", &s->uhci, TYPE_ASPEED_UHCI);
+
 snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
 object_initialize_child(obj, "sdmc", &s->sdmc, typename);
 object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
@@ -393,6 +398,15 @@ static void aspeed_ast2400_soc_realize(DeviceState *dev, 
Error **errp)
aspeed_soc_get_irq(s, ASPEED_DEV_EHCI1 + i));
 }
 
+/* UHCI */
+if (!sysbus_realize(SYS_BUS_DEVICE(&s->uhci), errp)) {
+return;
+}
+aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->uhci), 0,
+sc->memmap[ASPEED_DEV_UHCI]);
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->uhci), 0,
+   aspeed_soc_get_irq(s, ASPEED_DEV_UHCI));
+
 /* SDMC - SDRAM Memory Controller */
 if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) {
 return;
-- 
2.45.2




[RFC PATCH 7/8] aspeed: Add uhci support for ast2600

2024-09-06 Thread Guenter Roeck
Enable UHCO support for the ast2600 SoC. With this patch, the UHCI port
is successfully instantiated on the rainier-bmc and ast2600-evb machines.

Signed-off-by: Guenter Roeck 
---
 hw/arm/aspeed_ast2600.c | 13 +
 include/hw/arm/aspeed_soc.h |  3 +++
 2 files changed, 16 insertions(+)

diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index be3eb70cdd..cd7e4ae6c9 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -33,6 +33,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
 [ASPEED_DEV_SPI2]  = 0x1E631000,
 [ASPEED_DEV_EHCI1] = 0x1E6A1000,
 [ASPEED_DEV_EHCI2] = 0x1E6A3000,
+[ASPEED_DEV_UHCI]  = 0x1E6B,
 [ASPEED_DEV_MII1]  = 0x1E65,
 [ASPEED_DEV_MII2]  = 0x1E650008,
 [ASPEED_DEV_MII3]  = 0x1E650010,
@@ -110,6 +111,7 @@ static const int aspeed_soc_ast2600_irqmap[] = {
 [ASPEED_DEV_SDHCI] = 43,
 [ASPEED_DEV_EHCI1] = 5,
 [ASPEED_DEV_EHCI2] = 9,
+[ASPEED_DEV_UHCI]  = 10,
 [ASPEED_DEV_EMMC]  = 15,
 [ASPEED_DEV_GPIO]  = 40,
 [ASPEED_DEV_GPIO_1_8V] = 11,
@@ -206,6 +208,8 @@ static void aspeed_soc_ast2600_init(Object *obj)
 TYPE_PLATFORM_EHCI);
 }
 
+object_initialize_child(obj, "uhci", &s->uhci, TYPE_ASPEED_UHCI);
+
 snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
 object_initialize_child(obj, "sdmc", &s->sdmc, typename);
 object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
@@ -481,6 +485,15 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
aspeed_soc_get_irq(s, ASPEED_DEV_EHCI1 + i));
 }
 
+/* UHCI */
+if (!sysbus_realize(SYS_BUS_DEVICE(&s->uhci), errp)) {
+return;
+}
+aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->uhci), 0,
+sc->memmap[ASPEED_DEV_UHCI]);
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->uhci), 0,
+   aspeed_soc_get_irq(s, ASPEED_DEV_UHCI));
+
 /* SDMC - SDRAM Memory Controller */
 if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdmc), errp)) {
 return;
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 624d489e0d..b54849db72 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -34,6 +34,7 @@
 #include "hw/gpio/aspeed_gpio.h"
 #include "hw/sd/aspeed_sdhci.h"
 #include "hw/usb/hcd-ehci.h"
+#include "hw/usb/hcd-uhci-sysbus.h"
 #include "qom/object.h"
 #include "hw/misc/aspeed_lpc.h"
 #include "hw/misc/unimp.h"
@@ -72,6 +73,7 @@ struct AspeedSoCState {
 AspeedSMCState fmc;
 AspeedSMCState spi[ASPEED_SPIS_NUM];
 EHCISysBusState ehci[ASPEED_EHCIS_NUM];
+ASPEEDUHCIState uhci;
 AspeedSBCState sbc;
 AspeedSLIState sli;
 AspeedSLIState sliio;
@@ -193,6 +195,7 @@ enum {
 ASPEED_DEV_SPI2,
 ASPEED_DEV_EHCI1,
 ASPEED_DEV_EHCI2,
+ASPEED_DEV_UHCI,
 ASPEED_DEV_VIC,
 ASPEED_DEV_INTC,
 ASPEED_DEV_SDMC,
-- 
2.45.2




[RFC PATCH 3/8] usb/uhci: Move PCI-related code into a separate file

2024-09-06 Thread Guenter Roeck
Some machines (like Aspeed ARM) only have a sysbus UHCI controller.
The current UHCI implementation only supports PCI based UHCI controllers.
Move the UHCI-PCI device code into a separate file so that it is possible
to create a sysbus UHCI device without PCI dependency.

Signed-off-by: Guenter Roeck 
---
 hw/isa/Kconfig|   4 +-
 hw/isa/vt82c686.c |   4 +-
 hw/usb/Kconfig|   6 +-
 hw/usb/hcd-uhci-pci.c | 255 ++
 hw/usb/hcd-uhci-pci.h |  63 +
 hw/usb/hcd-uhci.c | 221 +
 hw/usb/hcd-uhci.h |  30 ++--
 hw/usb/meson.build|   1 +
 hw/usb/vt82c686-uhci-pci.c|  18 +--
 include/hw/southbridge/piix.h |   4 +-
 10 files changed, 386 insertions(+), 220 deletions(-)
 create mode 100644 hw/usb/hcd-uhci-pci.c
 create mode 100644 hw/usb/hcd-uhci-pci.h

diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
index 73c6470805..b0e536fad9 100644
--- a/hw/isa/Kconfig
+++ b/hw/isa/Kconfig
@@ -47,7 +47,7 @@ config PIIX
 select IDE_PIIX
 select ISA_BUS
 select MC146818RTC
-select USB_UHCI
+select USB_UHCI_PCI
 
 config VT82C686
 bool
@@ -55,7 +55,7 @@ config VT82C686
 select ISA_SUPERIO
 select ACPI
 select ACPI_SMBUS
-select USB_UHCI
+select USB_UHCI_PCI
 select APM
 select I8254
 select I8257
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 505b44c4e6..de317b11cb 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -26,7 +26,7 @@
 #include "hw/intc/i8259.h"
 #include "hw/irq.h"
 #include "hw/dma/i8257.h"
-#include "hw/usb/hcd-uhci.h"
+#include "hw/usb/hcd-uhci-pci.h"
 #include "hw/timer/i8254.h"
 #include "hw/rtc/mc146818rtc.h"
 #include "migration/vmstate.h"
@@ -598,7 +598,7 @@ struct ViaISAState {
 ViaSuperIOState via_sio;
 MC146818RtcState rtc;
 PCIIDEState ide;
-UHCIState uhci[2];
+UHCIPCIState uhci[2];
 ViaPMState pm;
 ViaAC97State ac97;
 PCIDevice mc97;
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index 84bc7fbe36..7d034738ce 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -2,10 +2,14 @@ config USB
 bool
 
 config USB_UHCI
+bool
+select USB
+
+config USB_UHCI_PCI
 bool
 default y if PCI_DEVICES
 depends on PCI
-select USB
+select USB_UHCI
 
 config USB_OHCI
 bool
diff --git a/hw/usb/hcd-uhci-pci.c b/hw/usb/hcd-uhci-pci.c
new file mode 100644
index 00..4036fe9c27
--- /dev/null
+++ b/hw/usb/hcd-uhci-pci.c
@@ -0,0 +1,255 @@
+/*
+ * USB UHCI controller emulation
+ * PCI code
+ *
+ * Copyright (c) 2005 Fabrice Bellard
+ *
+ * Copyright (c) 2008 Max Krasnyansky
+ * Magor rewrite of the UHCI data structures parser and frame processor
+ * Support for fully async operation and multiple outstanding transactions
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/usb.h"
+#include "migration/vmstate.h"
+#include "hw/pci/pci.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "qemu/main-loop.h"
+#include "qemu/module.h"
+#include "qom/object.h"
+#include "hcd-uhci-pci.h"
+
+struct UHCIPCIDeviceClass {
+PCIDeviceClass parent_class;
+UHCIPCIInfo info;
+};
+
+static const VMStateDescription vmstate_uhci = {
+.name = "pci_uhci",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (const VMStateField[]) {
+VMSTATE_PCI_DEVICE(dev, UHCIPCIState),
+VMSTATE_STRUCT(state, UHCIPCIState, 1, vmstate_uhci_state, UHCIState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void uhci_pci_reset(UHCIState *uhci)
+{
+UHCIPCIState *pstate = container_of(uhci, UHCIPCISta

[RFC PATCH 6/8] usb/uhci: Add aspeed specific read and write functions

2024-09-06 Thread Guenter Roeck
Aspeed uses non-standard UHCI register addresses. On top of that,
registers are 32 bit wide instead of 16 bit.

Map Aspeed UHCI addresses to standard UHCI addresses and where needed
combine/split 32 bit accesses to solve the problem.

Signed-off-by: Guenter Roeck 
---
 hw/usb/hcd-uhci-sysbus.c | 101 +++
 hw/usb/hcd-uhci-sysbus.h |  11 +
 2 files changed, 112 insertions(+)

diff --git a/hw/usb/hcd-uhci-sysbus.c b/hw/usb/hcd-uhci-sysbus.c
index 6f2428cc15..ba5398beeb 100644
--- a/hw/usb/hcd-uhci-sysbus.c
+++ b/hw/usb/hcd-uhci-sysbus.c
@@ -20,7 +20,9 @@
 
 #include "qemu/osdep.h"
 #include "hw/irq.h"
+#include "hw/usb/uhci-regs.h"
 #include "qapi/error.h"
+#include "qemu/log.h"
 #include "qemu/module.h"
 #include "qemu/timer.h"
 #include "hw/usb.h"
@@ -88,6 +90,99 @@ static void uhci_sysbus_class_init(ObjectClass *klass, void 
*data)
 dc->reset = uhci_sysbus_reset_sysbus;
 }
 
+static hwaddr aspeed_uhci_chip_to_uhci(hwaddr addr)
+{
+switch (addr) {
+case 0x00:
+return UHCI_USBCMD;
+case 0x04:
+return UHCI_USBSTS;
+case 0x08:
+return UHCI_USBINTR;
+case 0x0c:
+return UHCI_USBFLBASEADD;
+case 0x80:
+return UHCI_USBFRNUM;
+case 0x84:
+return UHCI_USBSOF;
+case 0x88:
+return UHCI_USBPORTSC1;
+case 0x8c:
+return UHCI_USBPORTSC2;
+case 0x90:
+return UHCI_USBPORTSC3;
+case 0x94:
+return UHCI_USBPORTSC4;
+default:/* unimplemented */
+qemu_log_mask(LOG_UNIMP, "Unimplemented Aspeed UHCI register 0x%lx\n",
+  addr);
+return 0x20;
+}
+}
+
+/*
+ * Aspeed UHCI registers are 32 bit wide.
+ * Convert to 16 bit to access standard UHCI code.
+ */
+static uint64_t aspeed_uhci_port_read(void *opaque, hwaddr addr, unsigned size)
+{
+UHCIState *uhci = opaque;
+MemoryRegion *mr = &uhci->mem;
+hwaddr uaddr = aspeed_uhci_chip_to_uhci(addr);
+
+if (uaddr == UHCI_USBFLBASEADD) {
+return mr->ops->read(opaque, uaddr, 2) |
+   mr->ops->read(opaque, uaddr + 2, 2) << 16;
+}
+return mr->ops->read(opaque, uaddr, 2);
+}
+
+static void aspeed_uhci_port_write(void *opaque, hwaddr addr, uint64_t val,
+   unsigned size)
+{
+UHCIState *uhci = opaque;
+MemoryRegion *mr = &uhci->mem;
+hwaddr uaddr = aspeed_uhci_chip_to_uhci(addr);
+
+if (uaddr == UHCI_USBFLBASEADD) {
+mr->ops->write(opaque, uaddr, val & 0x, 2);
+mr->ops->write(opaque, uaddr + 2, val >> 16, 2);
+} else {
+mr->ops->write(opaque, uaddr, val, 2);
+}
+}
+
+static const MemoryRegionOps aspeed_uhci_mmio_ops = {
+.read = aspeed_uhci_port_read,
+.write = aspeed_uhci_port_write,
+.valid.min_access_size = 4,
+.valid.max_access_size = 4,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void uhci_sysbus_aspeed_realize(DeviceState *dev, Error **errp)
+{
+UHCISysBusState *s = SYSBUS_UHCI(dev);
+ASPEEDUHCIState *f = ASPEED_UHCI(dev);
+UHCIState *uhci = &s->uhci;
+
+uhci_sysbus_realize(dev, errp);
+
+memory_region_init_io(&f->mem_aspeed, OBJECT(f), &aspeed_uhci_mmio_ops,
+  uhci, "aspeed", 0x100);
+memory_region_add_subregion(&uhci->mem, 0, &f->mem_aspeed);
+}
+
+static void uhci_sysbus_aspeed_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = uhci_sysbus_aspeed_realize;
+set_bit(DEVICE_CATEGORY_USB, dc->categories);
+dc->desc = "ASPEED UHCI USB Controller";
+dc->reset = uhci_sysbus_reset_sysbus;
+}
+
 static const TypeInfo uhci_sysbus_types[] = {
 {
 .name  = TYPE_SYSBUS_UHCI,
@@ -95,6 +190,12 @@ static const TypeInfo uhci_sysbus_types[] = {
 .instance_size = sizeof(UHCISysBusState),
 .class_init= uhci_sysbus_class_init,
 },
+{
+.name  = TYPE_ASPEED_UHCI,
+.parent= TYPE_SYSBUS_UHCI,
+.instance_size = sizeof(ASPEEDUHCIState),
+.class_init= uhci_sysbus_aspeed_class_init,
+},
 };
 
 DEFINE_TYPES(uhci_sysbus_types);
diff --git a/hw/usb/hcd-uhci-sysbus.h b/hw/usb/hcd-uhci-sysbus.h
index c491b9fc92..75c4716c40 100644
--- a/hw/usb/hcd-uhci-sysbus.h
+++ b/hw/usb/hcd-uhci-sysbus.h
@@ -4,6 +4,7 @@
 #include "hcd-uhci.h"
 
 #define TYPE_SYSBUS_UHCI "sysbus-uhci"
+#define TYPE_ASPEED_UHCI "aspeed-uhci"
 
 OBJECT_DECLARE_SIMPLE_TYPE(UHCISysBusState, SYSBUS_UHCI)
 
@@ -20,4 +21,14 @@ struct UHCISysBusState {
 uint32_t num_ports;
 };
 
+OBJECT_DECLARE_SIMPLE_TYPE(ASPEEDUHCIState, ASPEED_UHCI)
+
+struct ASPEEDUHCIState {
+/*< private >*/
+UHCISysBusState parent_obj;
+/*< public >*/
+
+MemoryRegion mem_aspeed;
+};
+
 #endif /* HW_USB_HCD_UHCI_SYSBUS_H */
-- 
2.45.2




[RFC PATCH 0/8] usb/uhci: Add UHCI sysbus support, and enable for AST machines

2024-09-06 Thread Guenter Roeck
Some machines (like Aspeed ARM) only support a sysbus UHCI controller.
The current UHCI implementation in qemu only supports PCI based UHCI
controllers.

This patch series separates basic and PCI functionality from the hcd-uhci
implementation and then adds uhci-sysbus support. This is then used
to implement and enable sysbus based UHCI support for Aspeed machines.

The series is submitted as RFC since I am quite sure that I didn't get
everything right. All code surrounding VMStates deserves special scrutiny,
as well as the changes outside hw/usb/ and hw/arm/.

A side effect of this patch series is that all Aspeed machines will now
instantiate UHCI, even if the machine does not actually support it
(it also always instantiates both EHCI ports, so that is not really
different). This means that the default USB bus is now the UHCI bus,
not the second EHCI bus. The bus number must therefore now be specified
explicitly when attaching a device unless attaching it to the UHCI port
is ok. I don't know if it is possible to avoid that and to ensure that
the default USB port is still the second EHCI port.

The code was tested on x86 machines to ensure that the existing UHCI
implementation still works. It was also tested on various Aspeed machines
with enabled UHCI ports (ast2500-evb, ast2600-evb, and rainier-bmc).

--------
Guenter Roeck (8):
  usb/uhci: checkpatch cleanup
  usb/uhci: Introduce and use register defines
  usb/uhci: Move PCI-related code into a separate file
  usb/uhci: enlarge uhci memory space
  usb/uhci: Add support for usb-uhci-sysbus
  usb/uhci: Add aspeed specific read and write functions
  aspeed: Add uhci support for ast2600
  aspeed: Add uhci support for ast2400 and ast2500

 hw/arm/Kconfig|   1 +
 hw/arm/aspeed_ast2400.c   |  14 ++
 hw/arm/aspeed_ast2600.c   |  13 ++
 hw/isa/Kconfig|   4 +-
 hw/isa/vt82c686.c |   4 +-
 hw/usb/Kconfig|  10 +-
 hw/usb/hcd-uhci-pci.c | 255 
 hw/usb/hcd-uhci-pci.h |  63 
 hw/usb/hcd-uhci-sysbus.c  | 201 +
 hw/usb/hcd-uhci-sysbus.h  |  34 +
 hw/usb/hcd-uhci.c | 337 +-
 hw/usb/hcd-uhci.h |  30 ++--
 hw/usb/meson.build|   2 +
 hw/usb/vt82c686-uhci-pci.c|  18 +--
 include/hw/arm/aspeed_soc.h   |   3 +
 include/hw/southbridge/piix.h |   4 +-
 include/hw/usb/uhci-regs.h|  11 ++
 17 files changed, 737 insertions(+), 267 deletions(-)
 create mode 100644 hw/usb/hcd-uhci-pci.c
 create mode 100644 hw/usb/hcd-uhci-pci.h
 create mode 100644 hw/usb/hcd-uhci-sysbus.c
 create mode 100644 hw/usb/hcd-uhci-sysbus.h



[RFC PATCH 4/8] usb/uhci: enlarge uhci memory space

2024-09-06 Thread Guenter Roeck
hcd-uhci-sysbus will require more memory than hcd-uhci-pci
since registers for some hardware (specifically Aspeed) don't
map 1:1.

Signed-off-by: Guenter Roeck 
---
 hw/usb/hcd-uhci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 68b72f8d3b..d2993a98b8 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1212,7 +1212,7 @@ void usb_uhci_init(UHCIState *s, DeviceState *dev, Error 
**errp)
 QTAILQ_INIT(&s->queues);
 
 memory_region_init_io(&s->mem, OBJECT(s), &uhci_ioport_ops, s,
-  "uhci", 0x20);
+  "uhci", 0x100);
 }
 
 void usb_uhci_exit(UHCIState *s)
-- 
2.45.2




[RFC PATCH 2/8] usb/uhci: Introduce and use register defines

2024-09-06 Thread Guenter Roeck
Introduce defines for UHCI registers to simplify adding register access
in subsequent patches of the series.

No functional change.

Signed-off-by: Guenter Roeck 
---
 hw/usb/hcd-uhci.c  | 32 
 include/hw/usb/uhci-regs.h | 11 +++
 2 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index dfcc3e05c0..8bc163f688 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -389,7 +389,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 trace_usb_uhci_mmio_writew(addr, val);
 
 switch (addr) {
-case 0x00:
+case UHCI_USBCMD:
 if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
 /* start frame processing */
 trace_usb_uhci_schedule_start();
@@ -424,7 +424,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 }
 }
 break;
-case 0x02:
+case UHCI_USBSTS:
 s->status &= ~val;
 /*
  * XXX: the chip spec is not coherent, so we add a hidden
@@ -435,27 +435,27 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 }
 uhci_update_irq(s);
 break;
-case 0x04:
+case UHCI_USBINTR:
 s->intr = val;
 uhci_update_irq(s);
 break;
-case 0x06:
+case UHCI_USBFRNUM:
 if (s->status & UHCI_STS_HCHALTED) {
 s->frnum = val & 0x7ff;
 }
 break;
-case 0x08:
+case UHCI_USBFLBASEADD:
 s->fl_base_addr &= 0x;
 s->fl_base_addr |= val & ~0xfff;
 break;
-case 0x0a:
+case UHCI_USBFLBASEADD + 2:
 s->fl_base_addr &= 0x;
 s->fl_base_addr |= (val << 16);
 break;
-case 0x0c:
+case UHCI_USBSOF:
 s->sof_timing = val & 0xff;
 break;
-case 0x10 ... 0x1f:
+case UHCI_USBPORTSC1 ... UHCI_USBPORTSC4:
 {
 UHCIPort *port;
 USBDevice *dev;
@@ -493,28 +493,28 @@ static uint64_t uhci_port_read(void *opaque, hwaddr addr, 
unsigned size)
 uint32_t val;
 
 switch (addr) {
-case 0x00:
+case UHCI_USBCMD:
 val = s->cmd;
 break;
-case 0x02:
+case UHCI_USBSTS:
 val = s->status;
 break;
-case 0x04:
+case UHCI_USBINTR:
 val = s->intr;
 break;
-case 0x06:
+case UHCI_USBFRNUM:
 val = s->frnum;
 break;
-case 0x08:
+case UHCI_USBFLBASEADD:
 val = s->fl_base_addr & 0x;
 break;
-case 0x0a:
+case UHCI_USBFLBASEADD + 2:
 val = (s->fl_base_addr >> 16) & 0x;
 break;
-case 0x0c:
+case UHCI_USBSOF:
 val = s->sof_timing;
 break;
-case 0x10 ... 0x1f:
+case UHCI_USBPORTSC1 ... UHCI_USBPORTSC4:
 {
 UHCIPort *port;
 int n;
diff --git a/include/hw/usb/uhci-regs.h b/include/hw/usb/uhci-regs.h
index fd45d29db0..5b81714e5c 100644
--- a/include/hw/usb/uhci-regs.h
+++ b/include/hw/usb/uhci-regs.h
@@ -1,6 +1,17 @@
 #ifndef HW_USB_UHCI_REGS_H
 #define HW_USB_UHCI_REGS_H
 
+#define UHCI_USBCMD   0
+#define UHCI_USBSTS   2
+#define UHCI_USBINTR  4
+#define UHCI_USBFRNUM 6
+#define UHCI_USBFLBASEADD 8
+#define UHCI_USBSOF   0x0c
+#define UHCI_USBPORTSC1   0x10
+#define UHCI_USBPORTSC2   0x12
+#define UHCI_USBPORTSC3   0x14
+#define UHCI_USBPORTSC4   0x16
+
 #define UHCI_CMD_FGR  (1 << 4)
 #define UHCI_CMD_EGSM (1 << 3)
 #define UHCI_CMD_GRESET   (1 << 2)
-- 
2.45.2




[RFC PATCH 5/8] usb/uhci: Add support for usb-uhci-sysbus

2024-09-06 Thread Guenter Roeck
Signed-off-by: Guenter Roeck 
---
 hw/arm/Kconfig   |   1 +
 hw/usb/Kconfig   |   4 ++
 hw/usb/hcd-uhci-sysbus.c | 100 +++
 hw/usb/hcd-uhci-sysbus.h |  23 +
 hw/usb/meson.build   |   1 +
 5 files changed, 129 insertions(+)
 create mode 100644 hw/usb/hcd-uhci-sysbus.c
 create mode 100644 hw/usb/hcd-uhci-sysbus.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 1ad60da7aa..8b1253fae5 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -606,6 +606,7 @@ config ASPEED_SOC
 select PMBUS
 select MAX31785
 select FSI_APB2OPB_ASPEED
+select USB_UHCI_SYSBUS
 
 config MPS2
 bool
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index 7d034738ce..fe5375050c 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -11,6 +11,10 @@ config USB_UHCI_PCI
 depends on PCI
 select USB_UHCI
 
+config USB_UHCI_SYSBUS
+bool
+select USB_UHCI
+
 config USB_OHCI
 bool
 select USB
diff --git a/hw/usb/hcd-uhci-sysbus.c b/hw/usb/hcd-uhci-sysbus.c
new file mode 100644
index 00..6f2428cc15
--- /dev/null
+++ b/hw/usb/hcd-uhci-sysbus.c
@@ -0,0 +1,100 @@
+/*
+ * QEMU USB UHCI Emulation
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Copyright (c) 2010 CodeSourcery
+ * Copyright (c) 2024 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "hw/usb.h"
+#include "migration/vmstate.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-dma.h"
+#include "hw/qdev-properties.h"
+#include "trace.h"
+#include "hcd-uhci.h"
+#include "hcd-uhci-sysbus.h"
+
+static void uhci_sysbus_reset(UHCIState *uhci)
+{
+uhci_state_reset(uhci);
+}
+
+static void uhci_sysbus_realize(DeviceState *dev, Error **errp)
+{
+UHCISysBusState *s = SYSBUS_UHCI(dev);
+UHCIState *uhci = &s->uhci;
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+Error *err = NULL;
+
+uhci->masterbus = s->masterbus;
+uhci->firstport = s->firstport;
+uhci->maxframes = s->maxframes;
+uhci->frame_bandwidth = s->frame_bandwidth;
+uhci->as = &address_space_memory;
+uhci->uhci_reset = uhci_sysbus_reset;
+
+usb_uhci_init(uhci, dev, &err);
+
+if (err) {
+error_propagate(errp, err);
+return;
+}
+sysbus_init_irq(sbd, &uhci->irq);
+sysbus_init_mmio(sbd, &uhci->mem);
+}
+
+static void uhci_sysbus_reset_sysbus(DeviceState *dev)
+{
+UHCISysBusState *s = SYSBUS_UHCI(dev);
+UHCIState *uhci = &s->uhci;
+
+uhci_sysbus_reset(uhci);
+}
+
+static Property uhci_sysbus_properties[] = {
+DEFINE_PROP_STRING("masterbus", UHCISysBusState, masterbus),
+DEFINE_PROP_UINT32("firstport", UHCISysBusState, firstport, 0),
+DEFINE_PROP_UINT32("bandwidth", UHCISysBusState, frame_bandwidth, 1280),
+DEFINE_PROP_UINT32("maxframes", UHCISysBusState, maxframes, 128),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void uhci_sysbus_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = uhci_sysbus_realize;
+set_bit(DEVICE_CATEGORY_USB, dc->categories);
+dc->desc = "UHCI USB Controller";
+device_class_set_props(dc, uhci_sysbus_properties);
+dc->reset = uhci_sysbus_reset_sysbus;
+}
+
+static const TypeInfo uhci_sysbus_types[] = {
+{
+.name  = TYPE_SYSBUS_UHCI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(UHCISysBusState),
+.class_init= uhci_sysbus_class_init,
+},
+};
+
+DEFINE_TYPES(uhci_sysbus_types);
diff --git a/hw/usb/hcd-uhci-sysbus.h b/hw/usb/hcd-uhci-sysbus.h
new file mode 100644
index 00..c491b9fc92
--- /dev/null
+++ b/hw/usb/hcd-uhci-sysbus.h
@@ -0,0 +1,23 @@
+#ifndef HW_USB_HCD_UHCI_SYSBUS_H
+#define HW_USB_HCD_UHCI_SYSBUS_H
+
+#include "hcd-uhci.h"
+
+#define TYPE_SYSBUS_UHCI "sysbus-uhci"
+
+OBJECT_DECLARE_SIMPLE_TYPE(UHCISysBusState, SYSBUS_UHCI)
+
+struct UHCISysBusState {
+/*< private >*/
+SysBusDevice parent_obj;
+/*

[RFC PATCH 1/8] usb/uhci: checkpatch cleanup

2024-09-06 Thread Guenter Roeck
Fix reported checkpatch issues to prepare for next patches
in the series.

No functional change.

Signed-off-by: Guenter Roeck 
---
 hw/usb/hcd-uhci.c | 90 +--
 1 file changed, 56 insertions(+), 34 deletions(-)

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index a03cf22e69..dfcc3e05c0 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -67,7 +67,7 @@ struct UHCIPCIDeviceClass {
 UHCIInfo   info;
 };
 
-/* 
+/*
  * Pending async transaction.
  * 'packet' must be the first field because completion
  * handler does "(UHCIAsync *) pkt" cast.
@@ -220,8 +220,9 @@ static void uhci_async_cancel(UHCIAsync *async)
 uhci_async_unlink(async);
 trace_usb_uhci_packet_cancel(async->queue->token, async->td_addr,
  async->done);
-if (!async->done)
+if (!async->done) {
 usb_cancel_packet(&async->packet);
+}
 uhci_async_free(async);
 }
 
@@ -322,7 +323,7 @@ static void uhci_reset(DeviceState *dev)
 s->fl_base_addr = 0;
 s->sof_timing = 64;
 
-for(i = 0; i < UHCI_PORTS; i++) {
+for (i = 0; i < UHCI_PORTS; i++) {
 port = &s->ports[i];
 port->ctrl = 0x0080;
 if (port->port.dev && port->port.dev->attached) {
@@ -387,7 +388,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 
 trace_usb_uhci_mmio_writew(addr, val);
 
-switch(addr) {
+switch (addr) {
 case 0x00:
 if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
 /* start frame processing */
@@ -404,7 +405,7 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 int i;
 
 /* send reset on the USB bus */
-for(i = 0; i < UHCI_PORTS; i++) {
+for (i = 0; i < UHCI_PORTS; i++) {
 port = &s->ports[i];
 usb_device_reset(port->port.dev);
 }
@@ -425,10 +426,13 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 break;
 case 0x02:
 s->status &= ~val;
-/* XXX: the chip spec is not coherent, so we add a hidden
-   register to distinguish between IOC and SPD */
-if (val & UHCI_STS_USBINT)
+/*
+ * XXX: the chip spec is not coherent, so we add a hidden
+ * register to distinguish between IOC and SPD
+ */
+if (val & UHCI_STS_USBINT) {
 s->status2 = 0;
+}
 uhci_update_irq(s);
 break;
 case 0x04:
@@ -436,8 +440,9 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 uhci_update_irq(s);
 break;
 case 0x06:
-if (s->status & UHCI_STS_HCHALTED)
+if (s->status & UHCI_STS_HCHALTED) {
 s->frnum = val & 0x7ff;
+}
 break;
 case 0x08:
 s->fl_base_addr &= 0x;
@@ -464,8 +469,8 @@ static void uhci_port_write(void *opaque, hwaddr addr,
 dev = port->port.dev;
 if (dev && dev->attached) {
 /* port reset */
-if ( (val & UHCI_PORT_RESET) &&
- !(port->ctrl & UHCI_PORT_RESET) ) {
+if ((val & UHCI_PORT_RESET) &&
+ !(port->ctrl & UHCI_PORT_RESET)) {
 usb_device_reset(dev);
 }
 }
@@ -487,7 +492,7 @@ static uint64_t uhci_port_read(void *opaque, hwaddr addr, 
unsigned size)
 UHCIState *s = opaque;
 uint32_t val;
 
-switch(addr) {
+switch (addr) {
 case 0x00:
 val = s->cmd;
 break;
@@ -533,12 +538,13 @@ static uint64_t uhci_port_read(void *opaque, hwaddr addr, 
unsigned size)
 }
 
 /* signal resume if controller suspended */
-static void uhci_resume (void *opaque)
+static void uhci_resume(void *opaque)
 {
 UHCIState *s = (UHCIState *)opaque;
 
-if (!s)
+if (!s) {
 return;
+}
 
 if (s->cmd & UHCI_CMD_EGSM) {
 s->cmd |= UHCI_CMD_FGR;
@@ -674,7 +680,8 @@ static int uhci_handle_td_error(UHCIState *s, UHCI_TD *td, 
uint32_t td_addr,
 return ret;
 }
 
-static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, 
uint32_t *int_mask)
+static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async,
+uint32_t *int_mask)
 {
 int len = 0, max_len;
 uint8_t pid;
@@ -682,8 +689,9 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, 
UHCIAsync *async, uint32_
 max_len = ((td->token >> 21) + 1) & 0x7ff;
 pid = td->token & 0xff;
 
-if (td->ctrl & TD_CTRL_IOS)
+if (td->ctrl & TD_CTRL_IOS) {
 td->ctrl &= ~TD_CTRL_ACTIVE;
+}
 
 if (async->packet.status != USB_RET_SUCCESS) {
 return uhci_handle_td_error(s, td, async-&g

Re: [PATCH 1/2] hw/sd: Remove legacy sd_set_cb()

2024-09-03 Thread Guenter Roeck

On 9/3/24 13:10, Philippe Mathieu-Daudé wrote:

(Cc'ing Guenter who asked to keep the SX1 machine)

On 3/9/24 22:04, Philippe Mathieu-Daudé wrote:

sd_set_cb() was only used by omap2_mmc_init() which
got recently removed. Time to remove it. For historical
background on the me_no_qdev_me_kill_mammoth_with_rocks
kludge, see commit 007d1dbf72 ("sd: Hide the qdev-but-not-quite
thing created by sd_init()").

Signed-off-by: Philippe Mathieu-Daudé 
---
  include/hw/sd/sdcard_legacy.h |  1 -
  hw/sd/sd.c    | 30 --
  2 files changed, 4 insertions(+), 27 deletions(-)

diff --git a/include/hw/sd/sdcard_legacy.h b/include/hw/sd/sdcard_legacy.h
index 0dc3889555..a121232560 100644
--- a/include/hw/sd/sdcard_legacy.h
+++ b/include/hw/sd/sdcard_legacy.h
@@ -36,7 +36,6 @@ SDState *sd_init(BlockBackend *blk, bool is_spi);
  int sd_do_command(SDState *card, SDRequest *request, uint8_t *response);
  void sd_write_byte(SDState *card, uint8_t value);
  uint8_t sd_read_byte(SDState *card);
-void sd_set_cb(SDState *card, qemu_irq readonly, qemu_irq insert);
  /* sd_enable should not be used -- it is only used on the nseries boards,
   * where it is part of a broken implementation of the MMC card slot switch
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index a140a32ccd..8a30c61ce0 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -112,10 +112,6 @@ typedef struct SDProto {
  struct SDState {
  DeviceState parent_obj;
-    /* If true, created by sd_init() for a non-qdevified caller */
-    /* TODO purge them with fire */
-    bool me_no_qdev_me_kill_mammoth_with_rocks;
-
  /* SD Memory Card Registers */
  uint32_t ocr;
  uint8_t scr[8];
@@ -169,8 +165,6 @@ struct SDState {
  uint32_t data_offset;
  size_t data_size;
  uint8_t data[512];
-    qemu_irq readonly_cb;
-    qemu_irq inserted_cb;
  QEMUTimer *ocr_power_timer;
  bool enable;
  uint8_t dat_lines;
@@ -889,17 +883,10 @@ static void sd_cardchange(void *opaque, bool load, Error 
**errp)
  trace_sdcard_ejected();
  }
-    if (sd->me_no_qdev_me_kill_mammoth_with_rocks) {
-    qemu_set_irq(sd->inserted_cb, inserted);
-    if (inserted) {
-    qemu_set_irq(sd->readonly_cb, readonly);
-    }
-    } else {
-    sdbus = SD_BUS(qdev_get_parent_bus(dev));
-    sdbus_set_inserted(sdbus, inserted);
-    if (inserted) {
-    sdbus_set_readonly(sdbus, readonly);
-    }
+    sdbus = SD_BUS(qdev_get_parent_bus(dev));


Guenter, we don't have SX1 tests. I wonder if this call could
fire an assertion. Do you have test images I can use? I'd need
to eject/reinsert a card to get there.



Have a look into
https://github.com/groeck/linux-build-test/tree/master/rootfs/arm

rootfs-armv4*are root file systems. You'd boot those with "noreboot"
command line argument to prevent them from rebooting automatically.
Let me know if you need more detailed directions; if so, I can make
a directory with everything needed.

Guenter




Re: [PATCH] target/hppa: Fix PSW V-bit packaging in cpu_hppa_get for hppa64

2024-09-03 Thread Guenter Roeck

On 9/3/24 03:28, Helge Deller wrote:

While adding hppa64 support, the psw_v variable got extended from 32 to 64
bits.  So, when packaging the PSW-V bit from the psw_v variable for interrupt
processing, check bit 31 instead the 63th (sign) bit.

This fixes a hard to find Linux kernel boot issue where the loss of the PSW-V
bit due to an ITLB interruption in the middle of a series of ds/addc
instructions (from the divU milicode library) generated the wrong division
result and thus triggered a Linux kernel crash.

Link: 
https://lore.kernel.org/lkml/718b8afe-222f-4b3a-96d3-93af0e4ce...@roeck-us.net/
Reported-by: Guenter Roeck 
Signed-off-by: Helge Deller 
Fixes: 931adff31478 ("target/hppa: Update cpu_hppa_get/put_psw for hppa64")


Tested-by: Guenter Roeck 

Thanks!
Guenter



diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index b79ddd8184..d4b1a3cd5a 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -53,7 +53,7 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
  }
  
  psw |= env->psw_n * PSW_N;

-psw |= (env->psw_v < 0) * PSW_V;
+psw |= ((env->psw_v >> 31) & 1) * PSW_V;
  psw |= env->psw | env->psw_xb;
  
  return psw;





Re: [PATCH v2] aspeed: Deprecate the tacoma-bmc machine

2024-08-30 Thread Guenter Roeck
On Fri, Aug 30, 2024 at 10:09:25AM +0200, Cédric Le Goater wrote:
> Hello,
> 
> 
> > > > I solved the problem by adding support for IBM Bonnell (which 
> > > > instantiates
> > > > the TPM chip through its devicetree file, similar to tacoma-bmc) to my 
> > > > local
> > > > copy of qemu.
> > > 
> > > Hmm, did you copy the rainier-bmc machine definition ?
> > > 
> > For aspeed_machine_bonnell_class_init(), pretty much yes, since I don't know
> > the actual hardware. For I2C initialization I used the devicetree file.
> > You can find the patch in the master-local or v9.1.0-local branches
> > of my qemu clone at https://github.com/groeck/qemu if you are interested.
> 
> Oh nice ! Let's merge the IBM Bonnell machine. We can ask IBM to help fixing
> the definitions (strapping). Enabling the PCA9554 is good to have too.
> 

Sure, let me do that.

> Why are you keeping the tmp105 changes ? LGTM. Same for the new tmp models,
> they could be upstreamed.
> 
Ok, I'll work on that.

Thanks,
Guenter



Re: [PATCH v2] aspeed: Deprecate the tacoma-bmc machine

2024-08-28 Thread Guenter Roeck

On 8/28/24 05:35, Cédric Le Goater wrote:

On 8/26/24 20:50, Guenter Roeck wrote:

Hi,

On 8/26/24 02:58, Cédric Le Goater wrote:

Hello Guenter,

On 8/9/24 00:05, Guenter Roeck wrote:

Hi,

On Tue, Jun 25, 2024 at 09:08:30AM +0200, Cédric Le Goater wrote:

The tacoma-bmc machine was a board including an AST2600 SoC based BMC
and a witherspoon like OpenPOWER system. It was used for bring up of
the AST2600 SoC in labs. It can be easily replaced by the rainier-bmc
machine which is part of a real product offering.

Signed-off-by: Cédric Le Goater 


I have been using tacoma-bmc to test tcg,tpm-tis-i2c functionality
on arm. rainier-bmc doesn't support that, and other IBM BMCs which
do support it (bonnell, everest, system1) are not supported in qemu.

Do you have a suggested alternative ?


Could you use the ast2600-evb machine instead ? as done in
machine_aspeed.py, see routine test_arm_ast2600_evb_buildroot_tpm.



Unfortunately, that does not work for me because that requires instantiating
the tpm chip from the CLI by writing into the new_device sysfs attribute,
and I can not do that in my test environment.


Ah. too bad.


We can't add a "tpm-tis-i2c" device to the tacoma-bmc machine init
routine because a TPM backend is required.



Not sure I understand; tacoma-bmc instantiates the TPM chip through its
devicetree file which is what I was looking for.


I meant at the "HW" board level in QEMU.

We can not instantiate the TPM I2C chip device model in the tacoma-bmc
machine init routine and attach it to the I2C bus because of the required
TPM backend. This means that the device is necessarily defined on the QEMU
command line and this makes the ast2600-evb and tacoma-bmc machine very
similar in terms of HW definitions.



Yes, I found that as well.


I solved the problem by adding support for IBM Bonnell (which instantiates
the TPM chip through its devicetree file, similar to tacoma-bmc) to my local
copy of qemu. 


Hmm, did you copy the rainier-bmc machine definition ?


For aspeed_machine_bonnell_class_init(), pretty much yes, since I don't know
the actual hardware. For I2C initialization I used the devicetree file.
You can find the patch in the master-local or v9.1.0-local branches
of my qemu clone at https://github.com/groeck/qemu if you are interested.


It isn't perfect since I don't know the correct HW pin strapping
and reused the strapping from Rainier, but it works for me.


Keeping the tacoma-bmc machine is fine if there is a use for it. Testing
the TPM I2C device driver is certainly a good use but we should reflect
that in QEMU also (so that we don't forget). Could we change the test in
machine_aspeed.py to use the tacoma-bmc machine instead ? and revert the
deprecation patch of course.



No need from my perspective. This isn't the only patch I carry on top of
upstream qemu, after all.

Thanks,
Guenter




Re: [PATCH v2] aspeed: Deprecate the tacoma-bmc machine

2024-08-26 Thread Guenter Roeck

Hi,

On 8/26/24 02:58, Cédric Le Goater wrote:

Hello Guenter,

On 8/9/24 00:05, Guenter Roeck wrote:

Hi,

On Tue, Jun 25, 2024 at 09:08:30AM +0200, Cédric Le Goater wrote:

The tacoma-bmc machine was a board including an AST2600 SoC based BMC
and a witherspoon like OpenPOWER system. It was used for bring up of
the AST2600 SoC in labs. It can be easily replaced by the rainier-bmc
machine which is part of a real product offering.

Signed-off-by: Cédric Le Goater 


I have been using tacoma-bmc to test tcg,tpm-tis-i2c functionality
on arm. rainier-bmc doesn't support that, and other IBM BMCs which
do support it (bonnell, everest, system1) are not supported in qemu.

Do you have a suggested alternative ?


Could you use the ast2600-evb machine instead ? as done in
machine_aspeed.py, see routine test_arm_ast2600_evb_buildroot_tpm.



Unfortunately, that does not work for me because that requires instantiating
the tpm chip from the CLI by writing into the new_device sysfs attribute,
and I can not do that in my test environment.


We can't add a "tpm-tis-i2c" device to the tacoma-bmc machine init
routine because a TPM backend is required.



Not sure I understand; tacoma-bmc instantiates the TPM chip through its
devicetree file which is what I was looking for.

I solved the problem by adding support for IBM Bonnell (which instantiates
the TPM chip through its devicetree file, similar to tacoma-bmc) to my local
copy of qemu. It isn't perfect since I don't know the correct HW pin strapping
and reused the strapping from Rainier, but it works for me.

Thanks,
Guenter




Re: [PATCH v2] aspeed: Deprecate the tacoma-bmc machine

2024-08-08 Thread Guenter Roeck
Hi,

On Tue, Jun 25, 2024 at 09:08:30AM +0200, Cédric Le Goater wrote:
> The tacoma-bmc machine was a board including an AST2600 SoC based BMC
> and a witherspoon like OpenPOWER system. It was used for bring up of
> the AST2600 SoC in labs. It can be easily replaced by the rainier-bmc
> machine which is part of a real product offering.
> 
> Signed-off-by: Cédric Le Goater 

I have been using tacoma-bmc to test tcg,tpm-tis-i2c functionality
on arm. rainier-bmc doesn't support that, and other IBM BMCs which
do support it (bonnell, everest, system1) are not supported in qemu.

Do you have a suggested alternative ?

Thanks,
Guenter



Re: [PATCH 3/3] hw/watchdog/wdt_imx2: Remove redundant assignment

2024-05-13 Thread Guenter Roeck

On 5/13/24 03:11, Bernhard Beschow wrote:

The same statement is executed unconditionally right before the if statement.

Cc: Guenter Roeck 
Signed-off-by: Bernhard Beschow 

---

The duplicate line may indicate a bug. I'm not familiar with the code, so this
patch may go into the wrong direction. Please check!


Should be ok. Technically the function should not be called to start with
if the watchdog isn't running. If it is, it might be useful to trace the content
of wcr and try to determine why the timer isn't stopped if  / when the watchdog
is disabled.

Reviewed-by: Guenter Roeck 

Thanks,
Guenter


---
  hw/watchdog/wdt_imx2.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/hw/watchdog/wdt_imx2.c b/hw/watchdog/wdt_imx2.c
index 6452fc4721..f9a7ea287f 100644
--- a/hw/watchdog/wdt_imx2.c
+++ b/hw/watchdog/wdt_imx2.c
@@ -39,7 +39,6 @@ static void imx2_wdt_expired(void *opaque)
  
  /* Perform watchdog action if watchdog is enabled */

  if (s->wcr & IMX2_WDT_WCR_WDE) {
-s->wrsr = IMX2_WDT_WRSR_TOUT;
  watchdog_perform_action();
  }
  }





Re: [PATCH v3 07/11] hw/sh4/r2d: Realize IDE controller before accessing it

2024-05-03 Thread Guenter Roeck
Hi,

On Thu, Feb 08, 2024 at 07:12:40PM +0100, Philippe Mathieu-Daudé wrote:
> We should not wire IRQs on unrealized device.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> Reviewed-by: Peter Maydell 
> Reviewed-by: Yoshinori Sato 

qemu 9.0 fails to boot Linux from ide/ata drives with the sh4
and sh4eb emulations. Error log is as follows.

ata1.00: ATA-7: QEMU HARDDISK, 2.5+, max UDMA/100
ata1.00: 16384 sectors, multi 16: LBA48
ata1.00: configured for PIO
scsi 0:0:0:0: Direct-Access ATA  QEMU HARDDISK2.5+ PQ: 0 ANSI: 5
sd 0:0:0:0: [sda] 16384 512-byte logical blocks: (8.39 MB/8.00 MiB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support 
DPO or FUA
ata1: lost interrupt (Status 0x58)

[ and more similar errors ]

qemu command line:

qemu-system-sh4eb -M r2d -kernel arch/sh/boot/zImage \
-snapshot -drive file=rootfs.ext2,format=raw,if=ide \
-append "root=/dev/sda console=ttySC1,115200 noiotrap" \
-serial null -serial stdio -monitor null -nographic -no-reboot

Bisect points to this patch (see below). Reverting it fixes the problem.

Guenter

---
bisect log:

# bad: [c25df57ae8f9fe1c72eee2dab37d76d904ac382e] Update version for 9.0.0 
release
# good: [1600b9f46b1bd08b00fe86c46ef6dbb48cbe10d6] Update version for v8.2.0 
release
git bisect start 'v9.0.0' 'v8.2.0'
# good: [62357c047a5abc6ede992159ed7c0aaaeb50617a] Merge tag 
'qemu-sparc-20240213' of https://github.com/mcayland/qemu into staging
git bisect good 62357c047a5abc6ede992159ed7c0aaaeb50617a
# bad: [d65f1ed7de1559534d0a1fabca5bdd81c594c7ca] docs/acpi/bits: add some 
clarity and details while also improving formating
git bisect bad d65f1ed7de1559534d0a1fabca5bdd81c594c7ca
# bad: [99e1c1137b6f339be1e4b76e243ad7b7c3d3cb8c] hw/i386/pc: Populate RTC 
attribute directly
git bisect bad 99e1c1137b6f339be1e4b76e243ad7b7c3d3cb8c
# bad: [760b4dcdddba4a40b9fa0eb78fdfc7eda7cb83d0] Merge tag 'for-upstream' of 
https://gitlab.com/bonzini/qemu into staging
git bisect bad 760b4dcdddba4a40b9fa0eb78fdfc7eda7cb83d0
# good: [f2b4a98930c122648e9dc494e49cea5dffbcc2be] target/arm: Allow access to 
SPSR_hyp from hyp mode
git bisect good f2b4a98930c122648e9dc494e49cea5dffbcc2be
# bad: [1a8e2f58c5dd721086284f827326b370d19ad9eb] hw/i386/q35: Use DEVICE() 
cast macro with PCIDevice object
git bisect bad 1a8e2f58c5dd721086284f827326b370d19ad9eb
# good: [59ae6bcddc3651b55b96c2bf05a6cd4312e46d10] hw/ppc/prep: Realize ISA 
bridge before accessing it
git bisect good 59ae6bcddc3651b55b96c2bf05a6cd4312e46d10
# bad: [7ed9a5f626a6c932a8c869a91e6a8b3e2029f5ef] hw/intc/grlib_irqmp: 
implements the multiprocessor status register
git bisect bad 7ed9a5f626a6c932a8c869a91e6a8b3e2029f5ef
# bad: [d08b7af3f7f27f6f3da8446756bf0b9352026b1d] target/sparc: Provide hint 
about CPUSPARCState::irq_manager member
git bisect bad d08b7af3f7f27f6f3da8446756bf0b9352026b1d
# bad: [5e37bc4997c32a1c9a6621a060462c84df9f1b8f] hw/dma: Pass parent object to 
i8257_dma_init()
git bisect bad 5e37bc4997c32a1c9a6621a060462c84df9f1b8f
# bad: [3c5f86a22686ef475a8259c0d8ee714f61c770c9] hw/sh4/r2d: Realize IDE 
controller before accessing it
git bisect bad 3c5f86a22686ef475a8259c0d8ee714f61c770c9
# good: [fc432ba0f58343c8912b80e9056315bb9bd8df92] hw/misc/macio: Realize IDE 
controller before accessing it
git bisect good fc432ba0f58343c8912b80e9056315bb9bd8df92
# first bad commit: [3c5f86a22686ef475a8259c0d8ee714f61c770c9] hw/sh4/r2d: 
Realize IDE controller before accessing it



Re: Problems (timeouts) when testing usb-ohci with qemu

2024-04-24 Thread Guenter Roeck

On 4/24/24 08:23, Guenter Roeck wrote:

On 4/24/24 04:16, Gerd Hoffmann wrote:

qemu hack:

  hw/usb/hcd-ohci.c | 11 +++
  hw/usb/hcd-ohci.h |  1 +
  2 files changed, 12 insertions(+)

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index fc8fc91a1d..99e52ad13a 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -267,6 +267,10 @@ static inline void ohci_intr_update(OHCIState *ohci)
  (ohci->intr_status & ohci->intr))
  level = 1;
+    if (level && ohci->level)
+    qemu_set_irq(ohci->irq, 0);
+
+    ohci->level = level;
  qemu_set_irq(ohci->irq, level);
  }
diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h
index e1827227ac..6f82e72bd9 100644
--- a/hw/usb/hcd-ohci.h
+++ b/hw/usb/hcd-ohci.h
@@ -52,6 +52,7 @@ struct OHCIState {
  uint32_t ctl, status;
  uint32_t intr_status;
  uint32_t intr;
+    int level;
  /* memory pointer partition */
  uint32_t hcca;


Phew.  Disclaimer: Havn't looked at the ohci emulation code for years.

It should not be needed to store the interrupt level that way.  It is
possible to calculate what the interrupt level should be, based on the
interrupt status register and the interrupt mask register, and the code
above seems to do exactly that (the "ohci->intr_status & ohci->intr"
bit).



You are correct. For the purpose of this kludge a simpler
+    qemu_set_irq(ohci->irq, 0);
 qemu_set_irq(ohci->irq, level);

would have been sufficient. My original code added tracing,
where this generated a lot of noise. I didn't completely simplify
the kludge. Sorry for that and for any confusion it may have caused.


ohci_intr_update() must be called if one of these two registers changes,
i.e. if the guest changes the mask, if the guest acks an IRQ by clearing
an status bit, if the device raises an IRQ by setting an status bit.
Might be the ohci emulation has a bug here.

Another possible trouble spot is that the timing behavior is different
on virtual vs. physical hardware.  Specifically with the emulated
hardware some actions appear to complete instantly (when the vmexit to
handle the mmio register write returns it's finished already), which
will never complete that quickly on physical hardware.  So drivers can
have race conditions which only trigger on virtual hardware.  The error
pattern you are describing sounds like this could be the case here.



I think the underlying problem is that both the qemu emulation and
the Linux kernel driver expect that the interrupt is level triggered.
It looks like some entity in between handles the interrupts as edge
triggered. This makes the kludge necessary: All it does is to generate
an artificial interrupt edge.

This can be worked around in the Linux interrupt handler by checking
if another interrupt arrived while the original interrupt was handled.
This will ensure that all interrupts are handled and cleared when the
handler exits, and that a later arriving interrupt will generate the
necessary edge and thus another interrupt. That doesn't fix the
edge<->level triggered interrupt confusion (if that is indeed the root
cause of the problem), but it does address its consequences.

If anyone has an idea how to find out where the interrupt confusion
happens, please let me know, and I'll be happy to do some more testing.
I am quite curious myself, and it would make sense to solve the problem
at its root.


Update:

I found upstream commit 0b60557230ad ("usb: ehci: Prevent missed ehci
interrupts with edge-triggered MSI") which I think explains the problem.

Guenter




Re: Problems (timeouts) when testing usb-ohci with qemu

2024-04-24 Thread Guenter Roeck

On 4/24/24 04:16, Gerd Hoffmann wrote:

qemu hack:

  hw/usb/hcd-ohci.c | 11 +++
  hw/usb/hcd-ohci.h |  1 +
  2 files changed, 12 insertions(+)

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index fc8fc91a1d..99e52ad13a 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -267,6 +267,10 @@ static inline void ohci_intr_update(OHCIState *ohci)
  (ohci->intr_status & ohci->intr))
  level = 1;
  
+if (level && ohci->level)

+qemu_set_irq(ohci->irq, 0);
+
+ohci->level = level;
  qemu_set_irq(ohci->irq, level);
  }
  
diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h

index e1827227ac..6f82e72bd9 100644
--- a/hw/usb/hcd-ohci.h
+++ b/hw/usb/hcd-ohci.h
@@ -52,6 +52,7 @@ struct OHCIState {
  uint32_t ctl, status;
  uint32_t intr_status;
  uint32_t intr;
+int level;
  
  /* memory pointer partition */

  uint32_t hcca;


Phew.  Disclaimer: Havn't looked at the ohci emulation code for years.

It should not be needed to store the interrupt level that way.  It is
possible to calculate what the interrupt level should be, based on the
interrupt status register and the interrupt mask register, and the code
above seems to do exactly that (the "ohci->intr_status & ohci->intr"
bit).



You are correct. For the purpose of this kludge a simpler
+   qemu_set_irq(ohci->irq, 0);
qemu_set_irq(ohci->irq, level);

would have been sufficient. My original code added tracing,
where this generated a lot of noise. I didn't completely simplify
the kludge. Sorry for that and for any confusion it may have caused.


ohci_intr_update() must be called if one of these two registers changes,
i.e. if the guest changes the mask, if the guest acks an IRQ by clearing
an status bit, if the device raises an IRQ by setting an status bit.
Might be the ohci emulation has a bug here.

Another possible trouble spot is that the timing behavior is different
on virtual vs. physical hardware.  Specifically with the emulated
hardware some actions appear to complete instantly (when the vmexit to
handle the mmio register write returns it's finished already), which
will never complete that quickly on physical hardware.  So drivers can
have race conditions which only trigger on virtual hardware.  The error
pattern you are describing sounds like this could be the case here.



I think the underlying problem is that both the qemu emulation and
the Linux kernel driver expect that the interrupt is level triggered.
It looks like some entity in between handles the interrupts as edge
triggered. This makes the kludge necessary: All it does is to generate
an artificial interrupt edge.

This can be worked around in the Linux interrupt handler by checking
if another interrupt arrived while the original interrupt was handled.
This will ensure that all interrupts are handled and cleared when the
handler exits, and that a later arriving interrupt will generate the
necessary edge and thus another interrupt. That doesn't fix the
edge<->level triggered interrupt confusion (if that is indeed the root
cause of the problem), but it does address its consequences.

If anyone has an idea how to find out where the interrupt confusion
happens, please let me know, and I'll be happy to do some more testing.
I am quite curious myself, and it would make sense to solve the problem
at its root.

Thanks,
Guenter




Re: Problems (timeouts) when testing usb-ohci with qemu

2024-04-24 Thread Guenter Roeck

On 4/23/24 19:11, Alan Stern wrote:
[ ... ]


To avoid the overhead of repeated interrupts, it would be best to check the
interrupt status at the end of the routine and restart if any of the
enabled bits are set, as in your first patch.

If you would like to clean it up (get rid of the debugging stuff) and
submit it, I'll review it.


Sure, I'll do that.

Thanks,
Guenter




Re: Problems (timeouts) when testing usb-ohci with qemu

2024-04-23 Thread Guenter Roeck

Hi Alan,

On 4/23/24 10:30, Alan Stern wrote:

On Tue, Apr 23, 2024 at 10:04:17AM -0700, Guenter Roeck wrote:

Hi,

when testing usb-ohci


What is usb-ohci?  Do you mean ohci-hcd?


  with qemu's pci-ohci emulation, I keep getting
random usb interface timeouts. Sometimes the usb_hub_wq times out.

...


Sometimes there is an i/o scheduling timeout such as

...


This is not a new problem; I have seen it forever. Recently I spent some
time trying to understand the problem and found that the linux driver does
not always handle all ohci interupts.


Please be more specific: _Which_ interrupts aren't being handled?  That
is, which flags remain set in the intrstatus register when the handler
returns?


Sorry, I didn't think it was relevant.

Here is the result of repeating the test with the linux patch several times
and passing the log output through "sort | uniq".

  1 pending 0x2 mask 0x805a
  9 pending 0x4 mask 0x801e
208 pending 0x4 mask 0x805e

So it is almost always OHCI_INTR_SF and rarely OHCI_INTR_WDH.
For reference, this is repeatedly running

CMDLINE="panic=-1 kunit.stats_enabled=2 kunit.filter=speed>slow root=/dev/sda 
rootwait console=ttyS0,115200 earlycon=uart8250,mmio,0x1000,115200"
qemu-system-riscv32 -M virt -m 512M \
 -no-reboot -bios default -kernel arch/riscv/boot/Image -snapshot \
 -device virtio-net-device,netdev=net0 -netdev user,id=net0 -usb \
 -device pci-ohci,id=ohci -device usb-storage,bus=ohci.0,drive=d0 \
 -drive file=rootfs.ext2,if=none,id=d0,format=raw \
 -append "${CMDLINE}" \
 -nographic -monitor none \
 --trace 'usb*' -D "/tmp/usb-ohci.$$.${sequence}.trace.log"

Tracing isn't really necessary but it changes timing enough that
the problem is more likely to be seen if it is active. The problem
is seen with various emulations; I just picked one of them.


  Since the interrupt is shared and
thus level triggered, that means that interrupts are still pending when
ohci_irq() exits. The interrupt core in Linux does not re-enter the
interrupt handler, presumably because it is marked as shared interrupt
and returns that the interrupt has been handled.


Isn't that behavior mistaken?  A level-triggered IRQ that remains set when
it is re-enabled (when the various shared handlers return) should cause
another interrupt to occur right away.

Edged-triggered interrupts would be a different story, of course.



Maybe I got it wrong; I thought that shared interrupts would have to be
level triggered. But then you are correct: one would think that level
triggered interrupts would keep executing interrupt handlers until the
interrupt is completely handled. I guess that means that I don't really
understand what is happening. Sorry for jumping to conclusions.


I found two possible fixes for the problem. One essentially mirrors the
code from ehci_irq(), the other adds a (bad) kludge into qemu. Both "fix"
or work around the problem.

Question is: What is actually wrong ? Something in the generic interrupt
handling code in Linux, something in the Linux usb-ohci driver, or
something in qemu ? Any idea how a proper fix might look like ?


To answer these questions we need more information.


What else would you need ?

Thanks,
Guenter




Problems (timeouts) when testing usb-ohci with qemu

2024-04-23 Thread Guenter Roeck
Hi,

when testing usb-ohci with qemu's pci-ohci emulation, I keep getting
random usb interface timeouts. Sometimes the usb_hub_wq times out.

[9.555666] Waiting for root device /dev/sda...
[   62.452625] INFO: task kworker/0:2:42 blocked for more than 30 seconds.
[   62.453036]   Tainted: G N 6.9.0-rc1-00305-geae7a41d2233 
#1
[   62.453393] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this 
message.
[   62.453778] task:kworker/0:2 state:D stack:0 pid:42tgid:42
ppid:2  flags:0x
[   62.454700] Workqueue: usb_hub_wq hub_event
[   62.455137] Call Trace:
[   62.455416] [] __schedule+0x35c/0xe00
[   62.455708] [] schedule+0x32/0x178
[   62.455906] [] usb_kill_urb+0xa8/0xda
[   62.456220] [] usb_start_wait_urb+0xca/0xe2
[   62.456441] [] usb_control_msg+0x9a/0x102
[   62.456648] [] hub_port_init+0x5de/0xb40
[   62.456851] [] hub_event+0xb90/0x1364
[   62.457049] [] process_one_work+0x200/0x564

Sometimes there is an i/o scheduling timeout such as

[6.361811] Run /sbin/init as init process
[   93.167039] INFO: task kworker/u4:0:10 blocked for more than 30 seconds.
[   93.167715]   Tainted: G N 6.9.0-rc5-00036-gaece0dd54838 
#4
[   93.168169] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this 
message.
[   93.168607] task:kworker/u4:0state:D stack:0 pid:10tgid:10
ppid:2  flags:0x
[   93.169602] Workqueue: scsi_tmf_0 scmd_eh_abort_handler
[   93.170278] Call Trace:
[   93.170584] [] __schedule+0x358/0xd4e
[   93.170904] [] schedule+0x32/0x166
[   93.171161] [] schedule_timeout+0xd8/0x10a
[   93.171420] [] __wait_for_common+0xce/0x1ce
[   93.171604] [] wait_for_completion+0x1c/0x24
[   93.171716] [] command_abort_matching.part.0+0x38/0x52
[   93.171841] [] command_abort+0x36/0x70
[   93.171946] [] scmd_eh_abort_handler+0xa6/0x192
...

This is not a new problem; I have seen it forever. Recently I spent some
time trying to understand the problem and found that the linux driver does
not always handle all ohci interupts. Since the interrupt is shared and
thus level triggered, that means that interrupts are still pending when
ohci_irq() exits. The interrupt core in Linux does not re-enter the
interrupt handler, presumably because it is marked as shared interrupt
and returns that the interrupt has been handled.

I found two possible fixes for the problem. One essentially mirrors the
code from ehci_irq(), the other adds a (bad) kludge into qemu. Both "fix"
or work around the problem.

Question is: What is actually wrong ? Something in the generic interrupt
handling code in Linux, something in the Linux usb-ohci driver, or
something in qemu ? Any idea how a proper fix might look like ?

Thanks,
Guenter

---
Linux hack:

diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 4f9982ecfb58..48d523e71ea0 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -883,6 +883,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
 * optimization of checking the LSB of hcca->done_head; it doesn't
 * work on all systems (edge triggering for OHCI can be a factor).
 */
+retry:
ints = ohci_readl(ohci, ®s->intrstatus);
 
/* Check for an all 1's result which is a typical consequence
@@ -982,6 +983,14 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
}
spin_unlock(&ohci->lock);
 
+   ints = ohci_readl(ohci, ®s->intrstatus);
+   ints &= ohci_readl(ohci, ®s->intrenable);
+   if (ints) {
+   pr_err(" Interrupts still pending 0x%x mask 0x%x\n", 
ints,
+  ohci_readl(ohci, ®s->intrenable));
+   goto retry;
+   }
+
return IRQ_HANDLED;
 }

---
qemu hack:

 hw/usb/hcd-ohci.c | 11 +++
 hw/usb/hcd-ohci.h |  1 +
 2 files changed, 12 insertions(+)

diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index fc8fc91a1d..99e52ad13a 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -267,6 +267,10 @@ static inline void ohci_intr_update(OHCIState *ohci)
 (ohci->intr_status & ohci->intr))
 level = 1;
 
+if (level && ohci->level)
+qemu_set_irq(ohci->irq, 0);
+
+ohci->level = level;
 qemu_set_irq(ohci->irq, level);
 }
 
diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h
index e1827227ac..6f82e72bd9 100644
--- a/hw/usb/hcd-ohci.h
+++ b/hw/usb/hcd-ohci.h
@@ -52,6 +52,7 @@ struct OHCIState {
 uint32_t ctl, status;
 uint32_t intr_status;
 uint32_t intr;
+int level;
 
 /* memory pointer partition */
 uint32_t hcca;
-- 
2.39.2




Re: possible deprecation and removal of some old QEMU Arm machine types (pxa2xx, omap, sa1110)

2024-03-08 Thread Guenter Roeck
On Fri, Mar 08, 2024 at 03:41:48PM +, Peter Maydell wrote:
> On Tue, 13 Feb 2024 at 15:36, Guenter Roeck  wrote:
> >
> > On Tue, Feb 13, 2024 at 03:14:21PM +, Peter Maydell wrote:
> > > On Mon, 12 Feb 2024 at 14:36, Guenter Roeck  wrote:
> > > > On 2/12/24 04:32, Peter Maydell wrote:
> > > > > The machines I have in mind are:
> > > > >
> > > > > PXA2xx machines:
> > > > >
> > > > > akitaSharp SL-C1000 (Akita) PDA (PXA270)
> > > > > borzoi   Sharp SL-C3100 (Borzoi) PDA (PXA270)
> > > > > connex   Gumstix Connex (PXA255)
> > > > > mainstoneMainstone II (PXA27x)
> > > > > spitzSharp SL-C3000 (Spitz) PDA (PXA270)
> > > > > terrier  Sharp SL-C3200 (Terrier) PDA (PXA270)
> > > > > tosa Sharp SL-6000 (Tosa) PDA (PXA255)
> > > > > verdex   Gumstix Verdex Pro XL6P COMs (PXA270)
> > > > > z2   Zipit Z2 (PXA27x)
> 
> > > > > OMAP1 machines:
> > > > >
> > > > > cheetah  Palm Tungsten|E aka. Cheetah PDA (OMAP310)
> > > > > sx1  Siemens SX1 (OMAP310) V2
> > > > > sx1-v1   Siemens SX1 (OMAP310) V1
> 
> > > > > OMAP2 machines:
> > > > >
> > > > > n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
> > > > > n810 Nokia N810 tablet aka. RX-44 (OMAP2420)
> 
> > > > > The one SA1110 machine:
> > > > >
> > > > > collie   Sharp SL-5500 (Collie) PDA (SA-1110)
> 
> > I am copying Arnd, the OMAP1 Linux kernel maintainers, PXA2 maintainers,
> > and the Linux omap mailing list for input. Sorry for the noise for those
> > who don't care, but I think it is useful to have your voices heard.
> 
> Thanks to everybody for your input on this thread. My
> proposal is to drop from QEMU:
>  * all the PXA2xx machines
>  * all the OMAP2 machines
>  * the cheetah OMAP1 machine
> 
> leaving (at least for now) sx1, sx1-v1, collie.
> 
> Rationale:
>  * for QEMU dropping individual machines is much less beneficial
>than if we can drop support for an entire SoC
>  * the OMAP2 QEMU code in particular is large, old and unmaintained,
>and none of the OMAP2 kernel maintainers said they were using
>QEMU in any of their testing/development
>  * although Guenter is currently booting test kernels on some
>of the PXA2xx machines, nobody seemed to be using them as part
>of their active kernel development and my impression from the
>thread is that PXA is the closest of all these SoC families to
>being dropped from the kernel soon
>  * nobody said they were using cheetah, so it's entirely
>untested and quite probably broken
>  * on the other hand the OMAP1 sx1 model does seem to be being
>used as part of kernel development, and there was interest
>in keeping collie around
> 
> I'm going to mark these as deprecated for the QEMU 9.0 release,
> which by our deprecate-and-drop policy means they will be
> still present in 9.0 (due out in April) and 9.1 (August-ish),
> and removed in 9.2 (December).
> 
> I'm potentially open to persuasion if anybody thinks I'm
> being too drastic here; persuasion that came attached to
> a desire to help modernise the QEMU code for the relevant
> machines would be the most effective :-)
> 

sgtm

Guenter



Re: [PATCH] scsi: megasas: Internal cdbs have 16-byte length

2024-02-17 Thread Guenter Roeck

On 2/17/24 01:06, Michael Tokarev wrote:

28.02.2023 20:11, Guenter Roeck wrote:

Host drivers do not necessarily set cdb_len in megasas io commands.
With commits 6d1511cea0 ("scsi: Reject commands if the CDB length
exceeds buf_len") and fe9d8927e2 ("scsi: Add buf_len parameter to
scsi_req_new()"), this results in failures to boot Linux from affected
SCSI drives because cdb_len is set to 0 by the host driver.
Set the cdb length to its actual size to solve the problem.


Has this been lost/forgotten?



Not sure. My understanding was that I could not prove that this is how
real hardware handles the situation, thus it wasn't applied. I carry it
locally in my builds of qemu, so it is not a problem for me. Note that
I didn't check if the problem has since been fixed differently. Maybe
that is the case and the problem no longer exists in the upstream version
of qemu.

Guenter




[PATCH v2] target: hppa: Fix unaligned double word accesses for hppa64

2024-02-16 Thread Guenter Roeck
Unaligned 64-bit accesses were found in Linux to clobber carry bits,
resulting in bad results if an arithmetic operation involving a
carry bit was executed after an unaligned 64-bit operation.

hppa 2.0 defines additional carry bits in PSW register bits 32..39.
When restoring PSW after executing an unaligned instruction trap, those
bits were not cleared and ended up to be active all the time. Since there
are no bits other than the upper carry bits needed in the upper 32 bit of
env->psw and since those are stored in env->psw_cb, just clear the entire
upper 32 bit when storing psw to solve the problem unconditionally.

Fixes: 931adff31478 ("target/hppa: Update cpu_hppa_get/put_psw for hppa64")
Cc: Richard Henderson 
Cc: Charlie Jenkins 
Cc: Helge Deller 
Reviewed-by: Richard Henderson 
Signed-off-by: Guenter Roeck 
---
v2: Rework to not require conditional code [Richard]
Add Richard's Reviewed-by: tag

 target/hppa/helper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index 859644c47a..9d217d051c 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -76,7 +76,8 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
 }
 psw &= ~reserved;
 
-env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
+env->psw = psw & (uint32_t)~(PSW_N | PSW_V | PSW_CB);
+
 env->psw_n = (psw / PSW_N) & 1;
 env->psw_v = -((psw / PSW_V) & 1);
 
-- 
2.39.2




Re: [PATCH] target: hppa: Fix unaligned double word accesses for hppa64

2024-02-15 Thread Guenter Roeck

On 2/15/24 22:16, Richard Henderson wrote:

On 2/15/24 19:34, Guenter Roeck wrote:

-    env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
+    if (hppa_is_pa20(env)) {
+    env->psw = psw & ~(PSW_N | PSW_V | PSW_CB | 0xffull);
+    } else {
+    env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
+    }


There are never any bits above 31 set in env->psw, because all of the CB bits are 
supposed to be stored in env->psw_cb.  Thus

   env->psw = psw & (uint32_t)~(...)

with no need for the pa20 check.

With that,

Reviewed-by: Richard Henderson 



sgtm. I'll test that and send v2 tomorrow (it is getting late).

Thanks,
Guenter






[PATCH] target: hppa: Fix unaligned double word accesses for hppa64

2024-02-15 Thread Guenter Roeck
Unaligned 64-bit accesses were found in Linux to clobber carry bits,
resulting in bad results if an arithmetic operation involving a
carry bit was executed after an unaligned 64-bit operation.

hppa 2.0 defines additional carry bits in PSW register bits 32..39.
When restoring PSW after executing an unaligned instruction trap,
those bits were not cleared and ended up to be active all the time.
Clearing bit 32..39 in psw prior to restoring it solves the problem.

Fixes: 931adff31478 ("target/hppa: Update cpu_hppa_get/put_psw for hppa64")
Cc: Richard Henderson 
Cc: Charlie Jenkins 
Cc: Helge Deller 
Signed-off-by: Guenter Roeck 
---
 target/hppa/helper.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index 859644c47a..7b798d1227 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -76,7 +76,12 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
 }
 psw &= ~reserved;
 
-env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
+if (hppa_is_pa20(env)) {
+env->psw = psw & ~(PSW_N | PSW_V | PSW_CB | 0xffull);
+} else {
+env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
+}
+
 env->psw_n = (psw / PSW_N) & 1;
 env->psw_v = -((psw / PSW_V) & 1);
 
-- 
2.39.2




Re: possible deprecation and removal of some old QEMU Arm machine types (pxa2xx, omap, sa1110)

2024-02-13 Thread Guenter Roeck
On Tue, Feb 13, 2024 at 03:14:21PM +, Peter Maydell wrote:
> On Mon, 12 Feb 2024 at 14:36, Guenter Roeck  wrote:
> > On 2/12/24 04:32, Peter Maydell wrote:
> > > The machines I have in mind are:
> > >
> > > PXA2xx machines:
> > >
> > > akitaSharp SL-C1000 (Akita) PDA (PXA270)
> > > borzoi   Sharp SL-C3100 (Borzoi) PDA (PXA270)
> > > connex   Gumstix Connex (PXA255)
> > > mainstoneMainstone II (PXA27x)
> > > spitzSharp SL-C3000 (Spitz) PDA (PXA270)
> > > terrier  Sharp SL-C3200 (Terrier) PDA (PXA270)
> > > tosa Sharp SL-6000 (Tosa) PDA (PXA255)
> > > verdex   Gumstix Verdex Pro XL6P COMs (PXA270)
> > > z2   Zipit Z2 (PXA27x)
> > >
> > I test akita, borzoi, spitz, and terrier. Upstream Linux removed support
> > for mainstone, tosa, and z2 from the Linux kernel as of version 6.0, so
> > I am no longer testing those.
> >
> > I never managed to boot connex or verdex.
> >
> > > OMAP1 machines:
> > >
> > > cheetah  Palm Tungsten|E aka. Cheetah PDA (OMAP310)
> > > sx1  Siemens SX1 (OMAP310) V2
> > > sx1-v1   Siemens SX1 (OMAP310) V1
> > >
> > I test sx1. I don't think I ever tried cheetah, and I could not get sx1-v1
> > to work.
> >
> > > OMAP2 machines:
> > >
> > > n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
> > > n810 Nokia N810 tablet aka. RX-44 (OMAP2420)
> > >
> > I never managed to get those to boot the Linux kernel.
> >
> > > The one SA1110 machine:
> > >
> > > collie   Sharp SL-5500 (Collie) PDA (SA-1110)
> > >
> > I do test collie.
> >
> > All the ones I use still boot the latest Linux kernel.
> >
> > > Obviously if we can remove all the machines that used a given
> > > SoC, that's much more effective than if we just delete one or two.
> > >
> > > I don't have any test images for the SA1110 or OMAP1 machines,
> > > so those are the ones I am most keen to be able to drop.
> > > I do have test images for a few of the pxa2xx and the OMAP2 machines.
> > >
> > I don't mind dropping them, just listing what I use for testing the
> > Linux kernel. I suspect I may be the only "user" of those boards,
> > though, both in Linux and qemu.
> 
> Mmm; there's not much point in both QEMU and the kernel
> maintaining code that nobody's using. Are you considering
> dropping support for any of these SoC families from the kernel?
> 
Not me personally. Arnd is the one mostly involved in dropping
support of obsolete hardware from the kernel.

> It sounds like between the two of us we do have at least one
> test image per SoC type if we do keep any of these, but
> if it isn't going to inconvenience kernel testing I'm
> inclined to go ahead with deprecate-and-drop for the whole lot.
> (With QEMU's deprecate-and-drop policy, that would be "announce
> deprecation now for 9.0, keep in 9.1, remove before 9.2 release
> at the end of the year".) At a minimum I would like to drop
> the OMAP1 and OMAP2 boards, as that's the biggest code burden.
> 

I am copying Arnd, the OMAP1 Linux kernel maintainers, PXA2 maintainers,
and the Linux omap mailing list for input. Sorry for the noise for those
who don't care, but I think it is useful to have your voices heard.

Personally I think it very unlikely that anyone is using the latest Linux
kernel on any of the affected machines, but I may be wrong.

Thanks,
Guenter



Re: possible deprecation and removal of some old QEMU Arm machine types (pxa2xx, omap, sa1110)

2024-02-13 Thread Guenter Roeck
Hi,

On Tue, Feb 13, 2024 at 02:42:29PM +0100, Marcin Juszkiewicz wrote:
> 
> > > The one SA1110 machine:
> > > 
> > > collie   Sharp SL-5500 (Collie) PDA (SA-1110)
> > > 
> > I do test collie.
> 
> Can you share kernel/initrd/config? I wanted to boot something at 20th
> anniversary of buying one but was unable to build anything bootable on
> either QEMU/collie or physical one.
> 

You'll find it at
https://github.com/groeck/linux-build-test/tree/master/rootfs/arm

Essentially it is collie_defconfig plus some additional configuration
options (BLK_DEV_INITRD and EABI are essential), and the rootfs is
rootfs-sa110.cpio.gz. It boots from initrd. I never managed to get it
booting from flash.

Guenter



Re: possible deprecation and removal of some old QEMU Arm machine types (pxa2xx, omap, sa1110)

2024-02-12 Thread Guenter Roeck

[ sorry for the earlier noise; accidentally hit "send" ]

On 2/12/24 04:32, Peter Maydell wrote:

QEMU includes some models of old Arm machine types which are
a bit problematic for us because:
  * they're written in a very old way that uses numerous APIs that we
would like to get away from (eg they don't use qdev, they use
qemu_system_reset_request(), they use vmstate_register(), etc)
  * they've been that way for a decade plus and nobody particularly has
stepped up to try to modernise the code (beyond some occasional
work here and there)
  * we often don't have test cases for them, which means that if we
do try to do the necessary refactoring work on them we have no
idea if they even still work at all afterwards

All these machine types are also of hardware that has largely passed
away into history and where I would not be surprised to find that
e.g. the Linux kernel support was never tested on real hardware
any more.

So I would like to explore whether we can deprecate-and-drop
some or all of them. This would let us delete the code entirely
rather than spending a long time trying to bring it up to scratch
for a probably very small to nonexistent userbase. The aim of this
email is to see if anybody is still using any of these and would be
upset if they went away. Reports of "I tried to use this machine
type and it's just broken" are also interesting as they would
strongly suggest that the machine has no real users and can be
removed.

The machines I have in mind are:

PXA2xx machines:

akitaSharp SL-C1000 (Akita) PDA (PXA270)
borzoi   Sharp SL-C3100 (Borzoi) PDA (PXA270)
connex   Gumstix Connex (PXA255)
mainstoneMainstone II (PXA27x)
spitzSharp SL-C3000 (Spitz) PDA (PXA270)
terrier  Sharp SL-C3200 (Terrier) PDA (PXA270)
tosa Sharp SL-6000 (Tosa) PDA (PXA255)
verdex   Gumstix Verdex Pro XL6P COMs (PXA270)
z2   Zipit Z2 (PXA27x)


I test akita, borzoi, spitz, and terrier. Upstream Linux removed support
for mainstone, tosa, and z2 from the Linux kernel as of version 6.0, so
I am no longer testing those.

I never managed to boot connex or verdex.


OMAP1 machines:

cheetah  Palm Tungsten|E aka. Cheetah PDA (OMAP310)
sx1  Siemens SX1 (OMAP310) V2
sx1-v1   Siemens SX1 (OMAP310) V1


I test sx1. I don't think I ever tried cheetah, and I could not get sx1-v1
to work.


OMAP2 machines:

n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
n810 Nokia N810 tablet aka. RX-44 (OMAP2420)


I never managed to get those to boot the Linux kernel.


The one SA1110 machine:

collie   Sharp SL-5500 (Collie) PDA (SA-1110)


I do test collie.

All the ones I use still boot the latest Linux kernel.


Obviously if we can remove all the machines that used a given
SoC, that's much more effective than if we just delete one or two.

I don't have any test images for the SA1110 or OMAP1 machines,
so those are the ones I am most keen to be able to drop.
I do have test images for a few of the pxa2xx and the OMAP2 machines.


I don't mind dropping them, just listing what I use for testing the
Linux kernel. I suspect I may be the only "user" of those boards,
though, both in Linux and qemu.

Guenter




Re: possible deprecation and removal of some old QEMU Arm machine types (pxa2xx, omap, sa1110)

2024-02-12 Thread Guenter Roeck

On 2/12/24 04:32, Peter Maydell wrote:

QEMU includes some models of old Arm machine types which are
a bit problematic for us because:
  * they're written in a very old way that uses numerous APIs that we
would like to get away from (eg they don't use qdev, they use
qemu_system_reset_request(), they use vmstate_register(), etc)
  * they've been that way for a decade plus and nobody particularly has
stepped up to try to modernise the code (beyond some occasional
work here and there)
  * we often don't have test cases for them, which means that if we
do try to do the necessary refactoring work on them we have no
idea if they even still work at all afterwards

All these machine types are also of hardware that has largely passed
away into history and where I would not be surprised to find that
e.g. the Linux kernel support was never tested on real hardware
any more.

So I would like to explore whether we can deprecate-and-drop
some or all of them. This would let us delete the code entirely
rather than spending a long time trying to bring it up to scratch
for a probably very small to nonexistent userbase. The aim of this
email is to see if anybody is still using any of these and would be
upset if they went away. Reports of "I tried to use this machine
type and it's just broken" are also interesting as they would
strongly suggest that the machine has no real users and can be
removed.

The machines I have in mind are:

PXA2xx machines:

akitaSharp SL-C1000 (Akita) PDA (PXA270)
borzoi   Sharp SL-C3100 (Borzoi) PDA (PXA270)
connex   Gumstix Connex (PXA255)
mainstoneMainstone II (PXA27x)
spitzSharp SL-C3000 (Spitz) PDA (PXA270)
terrier  Sharp SL-C3200 (Terrier) PDA (PXA270)
tosa Sharp SL-6000 (Tosa) PDA (PXA255)
verdex   Gumstix Verdex Pro XL6P COMs (PXA270)
z2   Zipit Z2 (PXA27x)

OMAP1 machines:

cheetah  Palm Tungsten|E aka. Cheetah PDA (OMAP310)
sx1  Siemens SX1 (OMAP310) V2
sx1-v1   Siemens SX1 (OMAP310) V1

OMAP2 machines:

n800 Nokia N800 tablet aka. RX-34 (OMAP2420)
n810 Nokia N810 tablet aka. RX-44 (OMAP2420)

The one SA1110 machine:

collie   Sharp SL-5500 (Collie) PDA (SA-1110)

Obviously if we can remove all the machines that used a given
SoC, that's much more effective than if we just delete one or two.

I don't have any test images for the SA1110 or OMAP1 machines,
so those are the ones I am most keen to be able to drop.
I do have test images for a few of the pxa2xx and the OMAP2 machines.

thanks
-- PMM





Re: [PULL 02/10] hw/hppa/machine: Disable default devices with --nodefaults option

2024-02-04 Thread Guenter Roeck
Hi Helge,

On Thu, Feb 01, 2024 at 08:22:58PM -0800, Guenter Roeck wrote:
> Hi,
> 
> On Sat, Jan 13, 2024 at 06:57:20AM +0100, del...@kernel.org wrote:
> > From: Helge Deller 
> > 
> > Recognize the qemu --nodefaults option, which will disable the
> > following default devices on hppa:
> > - lsi53c895a SCSI controller,
> > - artist graphics card,
> > - LASI 82596 NIC,
> > - tulip PCI NIC,
> > - second serial PCI card,
> > - USB OHCI controller.
> > 
> > Adding this option is very useful to allow manual testing and
> > debugging of the other possible devices on the command line.
> > 
> 
> With this patch in the tree, I get some interesting crashes in Seabios
> if I provide a somewhat unusual command line option. For example,
> something like
> 
> -usb -device usb-ehci,id=ehci \
> -device usb-uas,bus=ehci.0,id=uas \
> -device scsi-hd,bus=uas.0,scsi-id=0,lun=0,drive=d0 \
> -drive file= ...
> 
> is accepted as command line option but results in
> 
> SeaBIOS PA-RISC 32-bit Firmware Version 15 (QEMU 8.2.1)
> Duplex Console IO Dependent Code (IODC) revision 1
> --
>   (c) Copyright 2017-2024 Helge Deller  and SeaBIOS developers.
> --
>   Processor   SpeedState   Coprocessor State  Cache Size
>   -     -  -  --
>   0  250 MHzActive Functional0 KB
>   1  250 MHzIdle   Functional0 KB
>   2  250 MHzIdle   Functional0 KB
>   3  250 MHzIdle   Functional0 KB
>   Emulated machine: HP C3700 (64-bit PA2.0) with 32-bit PDC
>   Available memory: 1024 MB
>   Good memory required: 16 MB
>   Primary boot path:FWSCSI.0.0
>   Alternate boot path:  FWSCSI.0.0
>   Console path: SERIAL_2.9600.8.none
>   Keyboard path:SERIAL_2.9600.8.none
> *ERROR* in SeaBIOS-hppa-v15:
> prepare_boot_path:2898
> SeaBIOS wants SYSTEM HALT.

Just in case it matters, the following partial revert fixes the problem
for me.

diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index eb78c46ff1..cc903bc323 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -346,10 +346,8 @@ static void machine_HP_common_init_tail(MachineState 
*machine, PCIBus *pci_bus,
 SysBusDevice *s;

 /* SCSI disk setup. */
-if (drive_get_max_bus(IF_SCSI) >= 0) {
-dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
-lsi53c8xx_handle_legacy_cmdline(dev);
-}
+dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
+lsi53c8xx_handle_legacy_cmdline(dev);

It seems that SeaBIOS doesn't like it if the SCSI interface is missing.

Guenter



Re: [PULL 02/10] hw/hppa/machine: Disable default devices with --nodefaults option

2024-02-02 Thread Guenter Roeck
On Fri, Feb 02, 2024 at 10:54:20AM +0100, Helge Deller wrote:
> Hi Guenter,
> 
> On 2/2/24 05:22, Guenter Roeck wrote:
> > On Sat, Jan 13, 2024 at 06:57:20AM +0100, del...@kernel.org wrote:
> > > From: Helge Deller 
> > > 
> > > Recognize the qemu --nodefaults option, which will disable the
> > > following default devices on hppa:
> > > - lsi53c895a SCSI controller,
> > > - artist graphics card,
> > > - LASI 82596 NIC,
> > > - tulip PCI NIC,
> > > - second serial PCI card,
> > > - USB OHCI controller.
> > > 
> > > Adding this option is very useful to allow manual testing and
> > > debugging of the other possible devices on the command line.
> > > 
> > 
> > With this patch in the tree, I get some interesting crashes in Seabios
> > if I provide a somewhat unusual command line option. For example,
> > something like
> > 
> >  -usb -device usb-ehci,id=ehci \
> >  -device usb-uas,bus=ehci.0,id=uas \
> >  -device scsi-hd,bus=uas.0,scsi-id=0,lun=0,drive=d0 \
> >  -drive file= ...
> > 
> > is accepted as command line option but results in
> > 
> > SeaBIOS PA-RISC 32-bit Firmware Version 15 (QEMU 8.2.1)
> > Duplex Console IO Dependent Code (IODC) revision 1
> > --
> >(c) Copyright 2017-2024 Helge Deller  and SeaBIOS 
> > developers.
> > --
> >Processor   SpeedState   Coprocessor State  Cache 
> > Size
> >-     -  -  
> > --
> >0  250 MHzActive Functional0 KB
> >1  250 MHzIdle   Functional0 KB
> >2  250 MHzIdle   Functional0 KB
> >3  250 MHzIdle   Functional0 KB
> >Emulated machine: HP C3700 (64-bit PA2.0) with 32-bit PDC
> >Available memory: 1024 MB
> >Good memory required: 16 MB
> >Primary boot path:FWSCSI.0.0
> >Alternate boot path:  FWSCSI.0.0
> >Console path: SERIAL_2.9600.8.none
> >Keyboard path:SERIAL_2.9600.8.none
> > *ERROR* in SeaBIOS-hppa-v15:
> > prepare_boot_path:2898
> > SeaBIOS wants SYSTEM HALT.
> > 
> > This is without --nodefaults, and it used to work. Is that intentional ?
> 
> This should now be fixed in the upcoming SeaBIOS-hppa-v16 version ("devel" 
> branch):
> https://github.com/hdeller/seabios-hppa/tree/devel
> Could you test?

I was able to build from the 'master' branch, but 'devel' gives me

hppa64-linux-ld: target elf32-hppa-linux not found

Do you have a binary seabios image, by any chance ?

> If it doesn't work, please give me the full command line.
> 

qemu-system-hppa -M C3700 -smp 4 \
-kernel vmlinux -no-reboot -snapshot \
-usb -device usb-ehci,id=ehci \
-device usb-uas,bus=ehci.0,id=uas \
-device scsi-hd,bus=uas.0,scsi-id=0,lun=0,drive=d0 \
-drive file=rootfs.ext2,if=none,format=raw,id=d0 \
-append "root=/dev/sda rootwait console=ttyS0,115200" \
-nographic -monitor null

This is with qemu 8.2.1. Note that the number of CPUs doesn't make a
difference. It turns out this also crashes/aborts immediately with
"nodefaults".

> > If I do use the --nodefaults parameter, I was unable to figure out how
> > to configure the serial console. What command line parameter(s) do I need to
> > get it ?
> 
> You need to add:
> -serial mon:stdio
> This will create a serial port if it's not yet there.
> 

And there was me trying all variants of "-device pci-serial-4x..." I could
think of ;-).

Guenter



Re: [PULL 02/10] hw/hppa/machine: Disable default devices with --nodefaults option

2024-02-01 Thread Guenter Roeck
Hi,

On Sat, Jan 13, 2024 at 06:57:20AM +0100, del...@kernel.org wrote:
> From: Helge Deller 
> 
> Recognize the qemu --nodefaults option, which will disable the
> following default devices on hppa:
> - lsi53c895a SCSI controller,
> - artist graphics card,
> - LASI 82596 NIC,
> - tulip PCI NIC,
> - second serial PCI card,
> - USB OHCI controller.
> 
> Adding this option is very useful to allow manual testing and
> debugging of the other possible devices on the command line.
> 

With this patch in the tree, I get some interesting crashes in Seabios
if I provide a somewhat unusual command line option. For example,
something like

-usb -device usb-ehci,id=ehci \
-device usb-uas,bus=ehci.0,id=uas \
-device scsi-hd,bus=uas.0,scsi-id=0,lun=0,drive=d0 \
-drive file= ...

is accepted as command line option but results in

SeaBIOS PA-RISC 32-bit Firmware Version 15 (QEMU 8.2.1)
Duplex Console IO Dependent Code (IODC) revision 1
--
  (c) Copyright 2017-2024 Helge Deller  and SeaBIOS developers.
--
  Processor   SpeedState   Coprocessor State  Cache Size
  -     -  -  --
  0  250 MHzActive Functional0 KB
  1  250 MHzIdle   Functional0 KB
  2  250 MHzIdle   Functional0 KB
  3  250 MHzIdle   Functional0 KB
  Emulated machine: HP C3700 (64-bit PA2.0) with 32-bit PDC
  Available memory: 1024 MB
  Good memory required: 16 MB
  Primary boot path:FWSCSI.0.0
  Alternate boot path:  FWSCSI.0.0
  Console path: SERIAL_2.9600.8.none
  Keyboard path:SERIAL_2.9600.8.none
*ERROR* in SeaBIOS-hppa-v15:
prepare_boot_path:2898
SeaBIOS wants SYSTEM HALT.

This is without --nodefaults, and it used to work. Is that intentional ?

If I do use the --nodefaults parameter, I was unable to figure out how
to configure the serial console. What command line parameter(s) do I need to
get it ?

Thanks,
Guenter



Re: [PATCH] pci-host: designware: Limit value range of iATU viewport register

2024-02-01 Thread Guenter Roeck
On Thu, Feb 01, 2024 at 02:58:40PM +, Peter Maydell wrote:
> On Mon, 29 Jan 2024 at 06:00, Guenter Roeck  wrote:
> >
> > The latest version of qemu (v8.2.0-869-g7a1dc45af5) crashes when booting
> > the mcimx7d-sabre emulation with Linux v5.11 and later.
> >
> > qemu-system-arm: ../system/memory.c:2750: memory_region_set_alias_offset: 
> > Assertion `mr->alias' failed.
> >
> > Problem is that the Designware PCIe emulation accepts the full value range
> > for the iATU Viewport Register. However, both hardware and emulation only
> > support four inbound and four outbound viewports.
> >
> > The Linux kernel determines the number of supported viewports by writing
> > 0xff into the viewport register and reading the value back. The expected
> > value when reading the register is the highest supported viewport index.
> 
> This behaviour by the kernel seems to me to be out of spec.
> Looking at the "i.MX6 6Dual/6Quad Applications Processor Referenc
> Manual IMXDQRM" it says about the PCIE_PL_iATUVR register field
> Region_Index: "Must not be set to a value greater than 3"
> (there being 4 regions in this case).
> Plus it says elsewhere that software "should" write all-0s to
> reserved fields, and bits [7:4] are reserved in this register.
> 

Yes, I have seen that, but apparently it works with real hardware.

> > Match that code by masking the supported viewport value range when the
> > register is written. With this change, the Linux kernel reports
> >
> > imx6q-pcie 3380.pcie: iATU: unroll F, 4 ob, 4 ib, align 0K, limit 4G
> >
> > as expected and supported.
> 
> However given this is presumably what the hardware does in this
> case where the guest does something out of spec, and we definitely
> need to do something to avoid asserting, we should take this patch.
> 

Another option might be to define some flag to enable the behavior,
in case other designware based implementations handle it differently.

At the very least the code will have to be changed to handle
situations where the register is set to a value outside the valid
range. I have no idea, though, how that should or could be handled
differently, given that we don't really know how the underlying
designware IP handles it (such as: maybe it is a mask in the IP
configuration file, and the mask for i.MX is really 0x03, not 0x0f).

On a side note, I have not been able to actually instantiate
a PCIe device behind the root bridge. If anyone knows how to do that,
please let me know.

Thanks,
Guenter



[PATCH] pci-host: designware: Limit value range of iATU viewport register

2024-01-28 Thread Guenter Roeck
The latest version of qemu (v8.2.0-869-g7a1dc45af5) crashes when booting
the mcimx7d-sabre emulation with Linux v5.11 and later.

qemu-system-arm: ../system/memory.c:2750: memory_region_set_alias_offset: 
Assertion `mr->alias' failed.

Problem is that the Designware PCIe emulation accepts the full value range
for the iATU Viewport Register. However, both hardware and emulation only
support four inbound and four outbound viewports.

The Linux kernel determines the number of supported viewports by writing
0xff into the viewport register and reading the value back. The expected
value when reading the register is the highest supported viewport index.
Match that code by masking the supported viewport value range when the
register is written. With this change, the Linux kernel reports

imx6q-pcie 3380.pcie: iATU: unroll F, 4 ob, 4 ib, align 0K, limit 4G

as expected and supported.

Fixes: d64e5eabc4c7 ("pci: Add support for Designware IP block")
Cc: Andrey Smirnov 
Cc: Nikita Ostrenkov 
Signed-off-by: Guenter Roeck 
---
 hw/pci-host/designware.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index dd9e389c07..c25d50f1c6 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -340,6 +340,8 @@ static void designware_pcie_root_config_write(PCIDevice *d, 
uint32_t address,
 break;
 
 case DESIGNWARE_PCIE_ATU_VIEWPORT:
+val &= DESIGNWARE_PCIE_ATU_REGION_INBOUND |
+(DESIGNWARE_PCIE_NUM_VIEWPORTS - 1);
 root->atu_viewport = val;
 break;
 
-- 
2.39.2




Re: [PATCH v2] hw/arm: add PCIe to Freescale i.MX6

2024-01-28 Thread Guenter Roeck
On Sat, Jan 27, 2024 at 11:11:58AM -0800, Guenter Roeck wrote:
> Hi,
> 
> On Mon, Jan 08, 2024 at 02:03:25PM +, Nikita Ostrenkov wrote:
> > Signed-off-by: Nikita Ostrenkov 
> > ---
> 
> This patch, with the "sabrelite" emulation and the Linux upstream kernel
> (v6.8-rc1, using imx_v6_v7_defconfig), results in:
> 
> qemu-system-arm: ../system/memory.c:2750: memory_region_set_alias_offset: 
> Assertion `mr->alias' failed.
> 
> with the backtrace below. Any idea what might be wrong ?
> 
Never mind. I found the problem. I'll send a patch.

Guenter



Re: [PATCH v2] hw/arm: add PCIe to Freescale i.MX6

2024-01-27 Thread Guenter Roeck
On Sat, Jan 27, 2024 at 11:11:58AM -0800, Guenter Roeck wrote:
> Hi,
> 
> On Mon, Jan 08, 2024 at 02:03:25PM +, Nikita Ostrenkov wrote:
> > Signed-off-by: Nikita Ostrenkov 
> > ---
> 
> This patch, with the "sabrelite" emulation and the Linux upstream kernel
> (v6.8-rc1, using imx_v6_v7_defconfig), results in:
> 
> qemu-system-arm: ../system/memory.c:2750: memory_region_set_alias_offset: 
> Assertion `mr->alias' failed.
> 
> with the backtrace below. Any idea what might be wrong ?
> 

Additional information: The only reason for not seing the same
problem with mcimx7d-sabre is that Linux needs the PF3000 PMIC
to instantiate the PCIe controller on that system. After implementing
PF3000 support in qemu and instantiating it for mcimx7d-sabre,
I get exactly the same assertion when trying to run that simulation
with Linux v6.8-rc1.

Guenter

> Thanks,
> Guenter
> 
> ---
> #0  __pthread_kill_implementation (no_tid=0, signo=6, 
> threadid=140737237087808) at ./nptl/pthread_kill.c:44
> #1  __pthread_kill_internal (signo=6, threadid=140737237087808) at 
> ./nptl/pthread_kill.c:78
> #2  __GI___pthread_kill (threadid=140737237087808, signo=signo@entry=6) at 
> ./nptl/pthread_kill.c:89
> #3  0x76242476 in __GI_raise (sig=sig@entry=6) at 
> ../sysdeps/posix/raise.c:26
> #4  0x762287f3 in __GI_abort () at ./stdlib/abort.c:79
> #5  0x7622871b in __assert_fail_base
> (fmt=0x763dd130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
> assertion=0x565712bd "mr->alias", file=0x56570da4 
> "../system/memory.c", line=2750, function=)
> at ./assert/assert.c:92
> #6  0x76239e96 in __GI___assert_fail
> (assertion=0x565712bd "mr->alias", file=0x56570da4 
> "../system/memory.c", line=2750, function=0x56571bf0 
> <__PRETTY_FUNCTION__.8> "memory_region_set_alias_offset")
> at ./assert/assert.c:101
> #7  0x560192ce in memory_region_set_alias_offset (mr=0x57a77ce0, 
> offset=286326784) at ../system/memory.c:2750
> #8  0x55b8bc9f in designware_pcie_update_viewport 
> (root=0x57a74d50, viewport=0x57a77bc0) at 
> ../hw/pci-host/designware.c:280
> #9  0x55b8c06d in designware_pcie_root_config_write 
> (d=0x57a74d50, address=2312, val=0, len=4) at 
> ../hw/pci-host/designware.c:375
> #10 0x55b78488 in pci_host_config_write_common 
> (pci_dev=0x57a74d50, addr=2312, limit=4096, val=0, len=4) at 
> ../hw/pci/pci_host.c:96
> #11 0x55b8c7ee in designware_pcie_host_mmio_write 
> (opaque=0x57a746c0, addr=2312, val=0, size=4) at 
> ../hw/pci-host/designware.c:635
> #12 0x56012388 in memory_region_write_accessor (mr=0x57a780a0, 
> addr=2312, value=0x7105a628, size=4, shift=0, mask=4294967295, attrs=...) 
> at ../system/memory.c:497
> #13 0x560126c1 in access_with_adjusted_size
>  (addr=2312, value=0x7105a628, size=4, access_size_min=4, 
> access_size_max=4, access_fn=0x5601228e , 
> mr=0x57a780a0, attrs=...) at ../system/memory.c:573
> #14 0x560159cd in memory_region_dispatch_write (mr=0x57a780a0, 
> addr=2312, data=0, op=MO_32, attrs=...) at ../system/memory.c:1521
> #15 0x5607351f in int_st_mmio_leN (cpu=0x57a47150, 
> full=0x7fffe841fe80, val_le=0, addr=3500312840, size=4, mmu_idx=7, 
> ra=140734908258821, mr=0x57a780a0, mr_offset=2312)
> at ../accel/tcg/cputlb.c:2545
> #16 0x56073697 in do_st_mmio_leN (cpu=0x57a47150, 
> full=0x7fffe841fe80, val_le=0, addr=3500312840, size=4, mmu_idx=7, 
> ra=140734908258821) at ../accel/tcg/cputlb.c:2581
> #17 0x56073f14 in do_st_4 (cpu=0x57a47150, p=0x7105a7c0, 
> val=0, mmu_idx=7, memop=1282, ra=140734908258821) at 
> ../accel/tcg/cputlb.c:2758
> #18 0x560742d7 in do_st4_mmu (cpu=0x57a47150, addr=3500312840, 
> val=0, oi=20519, ra=140734908258821) at ../accel/tcg/cputlb.c:2834
> #19 0x56074df3 in helper_stl_mmu (env=0x57a49910, 
> addr=3500312840, val=0, oi=20519, retaddr=140734908258821) at 
> ../accel/tcg/ldst_common.c.inc:100
> #20 0x7fff6636da46 in code_gen_buffer ()
> #21 0x560587e8 in cpu_tb_exec (cpu=0x57a47150, 
> itb=0x7fffa636d900, tb_exit=0x7105adf0) at ../accel/tcg/cpu-exec.c:458
> #22 0x56059565 in cpu_loop_exec_tb (cpu=0x57a47150, 
> tb=0x7fffa636d900, pc=3230581304, last_tb=0x7105ae00, 
> tb_exit=0x7105adf0) at ../accel/tcg/cpu-exec.c:920
> #23 0x560598da in cpu_exec_loop (cpu=0x57a47150, 
> sc=0x7105ae80) at ../accel/tcg/cpu-exec.c:1041
> #24 0x560599ab in cpu_exec_setjmp (cpu=0x57a47150, 
> sc=0x7105ae80) at ../acce

Re: [PATCH v2] hw/arm: add PCIe to Freescale i.MX6

2024-01-27 Thread Guenter Roeck
Hi,

On Mon, Jan 08, 2024 at 02:03:25PM +, Nikita Ostrenkov wrote:
> Signed-off-by: Nikita Ostrenkov 
> ---

This patch, with the "sabrelite" emulation and the Linux upstream kernel
(v6.8-rc1, using imx_v6_v7_defconfig), results in:

qemu-system-arm: ../system/memory.c:2750: memory_region_set_alias_offset: 
Assertion `mr->alias' failed.

with the backtrace below. Any idea what might be wrong ?

Thanks,
Guenter

---
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737237087808) 
at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737237087808) at 
./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737237087808, signo=signo@entry=6) at 
./nptl/pthread_kill.c:89
#3  0x76242476 in __GI_raise (sig=sig@entry=6) at 
../sysdeps/posix/raise.c:26
#4  0x762287f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x7622871b in __assert_fail_base
(fmt=0x763dd130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
assertion=0x565712bd "mr->alias", file=0x56570da4 "../system/memory.c", 
line=2750, function=)
at ./assert/assert.c:92
#6  0x76239e96 in __GI___assert_fail
(assertion=0x565712bd "mr->alias", file=0x56570da4 
"../system/memory.c", line=2750, function=0x56571bf0 
<__PRETTY_FUNCTION__.8> "memory_region_set_alias_offset")
at ./assert/assert.c:101
#7  0x560192ce in memory_region_set_alias_offset (mr=0x57a77ce0, 
offset=286326784) at ../system/memory.c:2750
#8  0x55b8bc9f in designware_pcie_update_viewport (root=0x57a74d50, 
viewport=0x57a77bc0) at ../hw/pci-host/designware.c:280
#9  0x55b8c06d in designware_pcie_root_config_write (d=0x57a74d50, 
address=2312, val=0, len=4) at ../hw/pci-host/designware.c:375
#10 0x55b78488 in pci_host_config_write_common (pci_dev=0x57a74d50, 
addr=2312, limit=4096, val=0, len=4) at ../hw/pci/pci_host.c:96
#11 0x55b8c7ee in designware_pcie_host_mmio_write 
(opaque=0x57a746c0, addr=2312, val=0, size=4) at 
../hw/pci-host/designware.c:635
#12 0x56012388 in memory_region_write_accessor (mr=0x57a780a0, 
addr=2312, value=0x7105a628, size=4, shift=0, mask=4294967295, attrs=...) 
at ../system/memory.c:497
#13 0x560126c1 in access_with_adjusted_size
 (addr=2312, value=0x7105a628, size=4, access_size_min=4, 
access_size_max=4, access_fn=0x5601228e , 
mr=0x57a780a0, attrs=...) at ../system/memory.c:573
#14 0x560159cd in memory_region_dispatch_write (mr=0x57a780a0, 
addr=2312, data=0, op=MO_32, attrs=...) at ../system/memory.c:1521
#15 0x5607351f in int_st_mmio_leN (cpu=0x57a47150, 
full=0x7fffe841fe80, val_le=0, addr=3500312840, size=4, mmu_idx=7, 
ra=140734908258821, mr=0x57a780a0, mr_offset=2312)
at ../accel/tcg/cputlb.c:2545
#16 0x56073697 in do_st_mmio_leN (cpu=0x57a47150, 
full=0x7fffe841fe80, val_le=0, addr=3500312840, size=4, mmu_idx=7, 
ra=140734908258821) at ../accel/tcg/cputlb.c:2581
#17 0x56073f14 in do_st_4 (cpu=0x57a47150, p=0x7105a7c0, val=0, 
mmu_idx=7, memop=1282, ra=140734908258821) at ../accel/tcg/cputlb.c:2758
#18 0x560742d7 in do_st4_mmu (cpu=0x57a47150, addr=3500312840, 
val=0, oi=20519, ra=140734908258821) at ../accel/tcg/cputlb.c:2834
#19 0x56074df3 in helper_stl_mmu (env=0x57a49910, addr=3500312840, 
val=0, oi=20519, retaddr=140734908258821) at ../accel/tcg/ldst_common.c.inc:100
#20 0x7fff6636da46 in code_gen_buffer ()
#21 0x560587e8 in cpu_tb_exec (cpu=0x57a47150, itb=0x7fffa636d900, 
tb_exit=0x7105adf0) at ../accel/tcg/cpu-exec.c:458
#22 0x56059565 in cpu_loop_exec_tb (cpu=0x57a47150, 
tb=0x7fffa636d900, pc=3230581304, last_tb=0x7105ae00, 
tb_exit=0x7105adf0) at ../accel/tcg/cpu-exec.c:920
#23 0x560598da in cpu_exec_loop (cpu=0x57a47150, sc=0x7105ae80) 
at ../accel/tcg/cpu-exec.c:1041
#24 0x560599ab in cpu_exec_setjmp (cpu=0x57a47150, 
sc=0x7105ae80) at ../accel/tcg/cpu-exec.c:1058
#25 0x56059a47 in cpu_exec (cpu=0x57a47150) at 
../accel/tcg/cpu-exec.c:1084
#26 0x560838c2 in tcg_cpus_exec (cpu=0x57a47150) at 
../accel/tcg/tcg-accel-ops.c:76
#27 0x5608403d in mttcg_cpu_thread_fn (arg=0x57a47150) at 
../accel/tcg/tcg-accel-ops-mttcg.c:95
#28 0x562b32d7 in qemu_thread_start (args=0x57c06360) at 
../util/qemu-thread-posix.c:541
#29 0x76294ac3 in start_thread (arg=) at 
./nptl/pthread_create.c:442
#30 0x76326850 in clone3 () at 
../sysdeps/unix/sysv/linux/x86_64/clone3.S:81



Re: [PATCH 0/4] esp-pci: fixes for Linux and MS-DOS

2024-01-20 Thread Guenter Roeck

On 1/20/24 05:09, Michael Tokarev wrote:

12.01.2024 16:15, Mark Cave-Ayland:

This series contains fixes for the esp-pci device (am53c974 or dc390) for a
few issues spotted whilst testing the previous ESP series.

Patches 1-3 are fixes for issues found by Helge/Guenter whilst testing the
hppa C3700 machine with the amd53c974/dc390 devices under Linux, whilst patch
4 fixes an issue that was exposed by testing MS-DOS and Windows drivers.

With this series applied on top of the reworked ESP device, it is possible to
boot Linux under qemu-system-hppa without any errors and also boot and install
Win98SE from a DC390 PCI SCSI controller (no IDE!) using an MS-DOS boot floppy.

Signed-off-by: Mark Cave-Ayland 
Based-on: 20240112125420.514425-1-mark.cave-ayl...@ilande.co.uk


Mark Cave-Ayland (4):
   esp-pci.c: use correct address register for PCI DMA transfers
   esp-pci.c: generate PCI interrupt from separate ESP and PCI sources
   esp-pci.c: synchronise setting of DMA_STAT_DONE with ESP completion
 interrupt
   esp-pci.c: set DMA_STAT_BCMBLT when BLAST command issued


Is it worth to pick up for stable?  Especially the first one.
It's interesting this bug is here for a very long time.. :)



FWIW, I never observed the first one with Linux. I had carried variants
of the other three in my tree for a long time, but they were never
in a shape to be sent upstream and I never bothered trying to find
the root cause. All those _can_ be observed when booting Linux. So,
if anything, I'd argue that they should all be taken into stable
releases.

Thanks,
Guenter




[PATCH] fsl-imx6ul: Add various missing unimplemented devices

2024-01-19 Thread Guenter Roeck
Add MMDC, OCOTP, SQPI, CAAM, and USBMISC as unimplemented devices.

This allows operating systems such as Linux to run emulations such as
mcimx6ul-evk.

Before commit 0cd4926b85 ("Refactor i.MX6UL processor code"), the affected
memory ranges were covered by the unimplemented DAP device. The commit
reduced the DAP address range from 0x10 to 4kB, and the emulation
thus no longer covered the various unimplemented devices in the affected
address range.

Fixes: 0cd4926b85 ("Refactor i.MX6UL processor code")
Cc: Jean-Christophe Dubois 
Signed-off-by: Guenter Roeck 
---
This patch is necessary to boot mcimx6ul-evk with Linux v6.7.

My apologies for the noise if a similar patch has already been submitted
and I missed it.

 hw/arm/fsl-imx6ul.c | 30 ++
 include/hw/arm/fsl-imx6ul.h |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index e37b69a5e1..7d2ee0df6e 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -192,6 +192,36 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error 
**errp)
 create_unimplemented_device("a7mpcore-dap", FSL_IMX6UL_A7MPCORE_DAP_ADDR,
 FSL_IMX6UL_A7MPCORE_DAP_SIZE);
 
+/*
+ * MMDC
+ */
+create_unimplemented_device("a7mpcore-mmdc", FSL_IMX6UL_MMDC_CFG_ADDR,
+FSL_IMX6UL_MMDC_CFG_SIZE);
+
+/*
+ * OCOTP
+ */
+create_unimplemented_device("a7mpcore-ocotp", FSL_IMX6UL_OCOTP_CTRL_ADDR,
+FSL_IMX6UL_OCOTP_CTRL_SIZE);
+
+/*
+ * QSPI
+ */
+create_unimplemented_device("a7mpcore-qspi", FSL_IMX6UL_QSPI_ADDR,
+FSL_IMX6UL_QSPI_SIZE);
+
+/*
+ * CAAM
+ */
+create_unimplemented_device("a7mpcore-qspi", FSL_IMX6UL_CAAM_ADDR,
+FSL_IMX6UL_CAAM_SIZE);
+
+/*
+ * USBMISC
+ */
+create_unimplemented_device("a7mpcore-usbmisc", 
FSL_IMX6UL_USBO2_USBMISC_ADDR,
+FSL_IMX6UL_USBO2_USBMISC_SIZE);
+
 /*
  * GPTs
  */
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index 14390f6014..8277b0e8b2 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -182,6 +182,8 @@ enum FslIMX6ULMemoryMap {
 FSL_IMX6UL_ENET1_ADDR   = 0x02188000,
 
 FSL_IMX6UL_USBO2_USBMISC_ADDR   = 0x02184800,
+FSL_IMX6UL_USBO2_USBMISC_SIZE   = 0x200,
+
 FSL_IMX6UL_USBO2_USB1_ADDR  = 0x02184000,
 FSL_IMX6UL_USBO2_USB2_ADDR  = 0x02184200,
 
-- 
2.39.2




Re: [PULL 39/41] hw/net/cadence_gem: use FIELD to describe PHYMNTNC register fields

2024-01-19 Thread Guenter Roeck
On Fri, Jan 19, 2024 at 02:32:47PM -0800, Guenter Roeck wrote:
> Hi,
> 
> On Fri, Oct 27, 2023 at 03:39:40PM +0100, Peter Maydell wrote:
> > From: Luc Michel 
> > 
> > Use the FIELD macro to describe the PHYMNTNC register fields.
> > 
> > Signed-off-by: Luc Michel 
> > Reviewed-by: sai.pavan.bo...@amd.com
> > Message-id: 20231017194422.4124691-10-luc.mic...@amd.com
> > Signed-off-by: Peter Maydell 
> 
> With qemu v8.2.0 and this patch in place, I get the following error when 
> trying
> to enable the network interface on the xilinx-zynq-a9 emulation.
> 
> macb e000b000.ethernet eth0: validation of  with support 
> 00,,5000,6000 and advertisement 00,,, 
> failed: -EINVAL
> macb e000b000.ethernet eth0: Could not attach PHY (-22)
> 
> The problem is gone after reverting this patch. Note that I also had
> to revert "hw/net/cadence_gem: perform PHY access on write only", but
> that alone did not fix the problem.
> 

Never mind, it looks like the problem was fixed with commit 0c7ffc977195c1.
Sorry for the noise.

Guenter



Re: [PULL 39/41] hw/net/cadence_gem: use FIELD to describe PHYMNTNC register fields

2024-01-19 Thread Guenter Roeck
Hi,

On Fri, Oct 27, 2023 at 03:39:40PM +0100, Peter Maydell wrote:
> From: Luc Michel 
> 
> Use the FIELD macro to describe the PHYMNTNC register fields.
> 
> Signed-off-by: Luc Michel 
> Reviewed-by: sai.pavan.bo...@amd.com
> Message-id: 20231017194422.4124691-10-luc.mic...@amd.com
> Signed-off-by: Peter Maydell 

With qemu v8.2.0 and this patch in place, I get the following error when trying
to enable the network interface on the xilinx-zynq-a9 emulation.

macb e000b000.ethernet eth0: validation of  with support 
00,,5000,6000 and advertisement 00,,, 
failed: -EINVAL
macb e000b000.ethernet eth0: Could not attach PHY (-22)

The problem is gone after reverting this patch. Note that I also had
to revert "hw/net/cadence_gem: perform PHY access on write only", but
that alone did not fix the problem.

Guenter



Re: [PATCH v2 3/3] hw/arm: Add watchdog timer to Allwinner H40 and Bananapi board

2024-01-16 Thread Guenter Roeck

On 1/16/24 02:04, Philippe Mathieu-Daudé wrote:

Hi,

(Cc'ing Li, Strahinja and Niek)

On 15/1/24 19:27, Guenter Roeck wrote:

Add watchdog timer support to Allwinner-H40 and Bananapi.
The watchdog timer is added as an overlay to the Timer
module memory map.


I'm confused by these registers from TYPE_AW_A10_PIT
and the TYPE_AW_WDT implementation you are using:

   #define AW_A10_PIT_WDOG_CONTROL    0x90
   #define AW_A10_PIT_WDOG_MODE   0x94

Do we have 2 implementations of the same peripheral?



The watchdog core in A10 and H40 is the same. Linux devicetree uses
allwinner,sun4i-a10-wdt for several chips.

arch/arm/boot/dts/allwinner/sun4i-a10.dtsi: compatible = 
"allwinner,sun4i-a10-wdt";
arch/arm/boot/dts/allwinner/sun5i.dtsi: compatible = 
"allwinner,sun4i-a10-wdt";
arch/arm/boot/dts/allwinner/sun7i-a20.dtsi: compatible = 
"allwinner,sun4i-a10-wdt";
arch/arm/boot/dts/allwinner/sun8i-r40.dtsi: compatible = 
"allwinner,sun4i-a10-wdt";


Should we instanciate AW_WDT within AW_A10_PIT?




As far as I can see, AW_A10_PIT_WDOG_CONTROL and AW_A10_PIT_WDOG_MODE
are not really handled in hw/timer/allwinner-a10-pit.c because of the
memory range overlay,  and the defines might as well be dropped from there.
It made some sense to have them when the watchdog wasn't implemented
to avoid emulation errors, but afaics they are now obsolete.

The wdt type (TYPE_AW_WDT_SUN4I) more accurately reflects the watchdog
type. Control and mode registers are model specific. For example,
sun6i and sun9i use the same timer and watchdog cores but with
different register offsets and bit values for the watchdog registers.
sun8i uses the same watchdog core (and same register offsets) as
sun6i/sun9i, but the timer module itself is different. Implementing that
with the current model (using memory map overlays) is straightforward.
I don't know how one would do that from the timer modules; it seems
more complex to me than the current implementation.

On the other side, I don't know how the "proper" implementation in
qemu would look like, so I don't really have a strong opinion either
way.

Guenter




[PATCH v2 1/3] hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board

2024-01-15 Thread Guenter Roeck
Allwinner R40 supports two USB host ports shared between a USB 2.0 EHCI
host controller and a USB 1.1 OHCI host controller. Add support for both
of them.

If machine USB support is not enabled, create unimplemented devices
for the USB memory ranges to avoid crashes when booting Linux.

Signed-off-by: Guenter Roeck 
---
v2: The USB Controllers are part of the chipset, so instantiate them
unconditionally

 docs/system/arm/bananapi_m2u.rst |  2 +-
 hw/arm/Kconfig   |  2 ++
 hw/arm/allwinner-r40.c   | 47 ++--
 include/hw/arm/allwinner-r40.h   |  9 ++
 4 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
index b09ba5c548..e77c425e2c 100644
--- a/docs/system/arm/bananapi_m2u.rst
+++ b/docs/system/arm/bananapi_m2u.rst
@@ -23,6 +23,7 @@ The Banana Pi M2U machine supports the following devices:
  * GMAC ethernet
  * Clock Control Unit
  * TWI (I2C)
+ * USB 2.0
 
 Limitations
 """""""""""
@@ -33,7 +34,6 @@ Currently, Banana Pi M2U does *not* support the following 
features:
 - Audio output
 - Hardware Watchdog
 - Real Time Clock
-- USB 2.0 interfaces
 
 Also see the 'unimplemented' array in the Allwinner R40 SoC module
 for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-r40.c``
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 39d255425b..6b508780d3 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -415,6 +415,8 @@ config ALLWINNER_R40
 select ARM_TIMER
 select ARM_GIC
 select UNIMP
+select USB_OHCI
+select USB_EHCI_SYSBUS
 select SD
 
 config RASPI
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index a0d367c60d..2e8943eff7 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -23,6 +23,7 @@
 #include "qemu/bswap.h"
 #include "qemu/module.h"
 #include "qemu/units.h"
+#include "hw/boards.h"
 #include "hw/qdev-core.h"
 #include "hw/sysbus.h"
 #include "hw/char/serial.h"
@@ -45,6 +46,10 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_MMC1]   = 0x01c1,
 [AW_R40_DEV_MMC2]   = 0x01c11000,
 [AW_R40_DEV_MMC3]   = 0x01c12000,
+[AW_R40_DEV_EHCI1]  = 0x01c19000,
+[AW_R40_DEV_OHCI1]  = 0x01c19400,
+[AW_R40_DEV_EHCI2]  = 0x01c1c000,
+[AW_R40_DEV_OHCI2]  = 0x01c1c400,
 [AW_R40_DEV_CCU]= 0x01c2,
 [AW_R40_DEV_PIT]= 0x01c20c00,
 [AW_R40_DEV_UART0]  = 0x01c28000,
@@ -89,9 +94,9 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "crypto", 0x01c15000, 4 * KiB },
 { "spi2",   0x01c17000, 4 * KiB },
 { "sata",   0x01c18000, 4 * KiB },
-{ "usb1-host",  0x01c19000, 4 * KiB },
+{ "usb1-phy",   0x01c19800, 2 * KiB },
 { "sid",0x01c1b000, 4 * KiB },
-{ "usb2-host",  0x01c1c000, 4 * KiB },
+{ "usb2-phy",   0x01c1c800, 2 * KiB },
 { "cs1",0x01c1d000, 4 * KiB },
 { "spi3",   0x01c1f000, 4 * KiB },
 { "rtc",0x01c20400, 1 * KiB },
@@ -181,6 +186,10 @@ enum {
 AW_R40_GIC_SPI_MMC2  = 34,
 AW_R40_GIC_SPI_MMC3  = 35,
 AW_R40_GIC_SPI_EMAC  = 55,
+AW_R40_GIC_SPI_OHCI1 = 64,
+AW_R40_GIC_SPI_OHCI2 = 65,
+AW_R40_GIC_SPI_EHCI1 = 76,
+AW_R40_GIC_SPI_EHCI2 = 78,
 AW_R40_GIC_SPI_GMAC  = 85,
 };
 
@@ -276,6 +285,13 @@ static void allwinner_r40_init(Object *obj)
 TYPE_AW_SDHOST_SUN50I_A64);
 }
 
+for (size_t i = 0; i < AW_R40_NUM_USB; i++) {
+object_initialize_child(obj, "ehci[*]", &s->ehci[i],
+TYPE_PLATFORM_EHCI);
+object_initialize_child(obj, "ohci[*]", &s->ohci[i],
+TYPE_SYSBUS_OHCI);
+}
+
 object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
 
 object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
@@ -407,6 +423,33 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_R40_DEV_CCU]);
 
+/* USB */
+for (size_t i = 0; i < AW_R40_NUM_USB; i++) {
+g_autofree char *bus = g_strdup_printf("usb-bus.%zu", i);
+
+object_property_set_bool(OBJECT(&s->ehci[i]), "companion-enable", true,
+ &error_fatal);
+sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), &error_fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0,
+allwinner_r40_memmap[i

[PATCH v2 2/3] hw/arm: Add AHCI/SATA controller to Allwinner R40 and Bananapi board

2024-01-15 Thread Guenter Roeck
Allwinner R40 supports an AHCI compliant SATA controller.
Add support for it.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Guenter Roeck 
---
 docs/system/arm/bananapi_m2u.rst |  1 +
 hw/arm/Kconfig   |  1 +
 hw/arm/allwinner-r40.c   | 12 +++-
 include/hw/arm/allwinner-r40.h   |  3 +++
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
index e77c425e2c..542310591d 100644
--- a/docs/system/arm/bananapi_m2u.rst
+++ b/docs/system/arm/bananapi_m2u.rst
@@ -22,6 +22,7 @@ The Banana Pi M2U machine supports the following devices:
  * EMAC ethernet
  * GMAC ethernet
  * Clock Control Unit
+ * SATA
  * TWI (I2C)
  * USB 2.0
 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 6b508780d3..98ca5ebc7d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -408,6 +408,7 @@ config ALLWINNER_H3
 config ALLWINNER_R40
 bool
 default y if TCG && ARM
+select AHCI
 select ALLWINNER_SRAMC
 select ALLWINNER_A10_PIT
 select AXP2XX_PMU
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index 2e8943eff7..534be4a735 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -46,6 +46,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_MMC1]   = 0x01c1,
 [AW_R40_DEV_MMC2]   = 0x01c11000,
 [AW_R40_DEV_MMC3]   = 0x01c12000,
+[AW_R40_DEV_AHCI]   = 0x01c18000,
 [AW_R40_DEV_EHCI1]  = 0x01c19000,
 [AW_R40_DEV_OHCI1]  = 0x01c19400,
 [AW_R40_DEV_EHCI2]  = 0x01c1c000,
@@ -93,7 +94,6 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "usb0-host",  0x01c14000, 4 * KiB },
 { "crypto", 0x01c15000, 4 * KiB },
 { "spi2",   0x01c17000, 4 * KiB },
-{ "sata",   0x01c18000, 4 * KiB },
 { "usb1-phy",   0x01c19800, 2 * KiB },
 { "sid",0x01c1b000, 4 * KiB },
 { "usb2-phy",   0x01c1c800, 2 * KiB },
@@ -186,6 +186,7 @@ enum {
 AW_R40_GIC_SPI_MMC2  = 34,
 AW_R40_GIC_SPI_MMC3  = 35,
 AW_R40_GIC_SPI_EMAC  = 55,
+AW_R40_GIC_SPI_AHCI  = 56,
 AW_R40_GIC_SPI_OHCI1 = 64,
 AW_R40_GIC_SPI_OHCI2 = 65,
 AW_R40_GIC_SPI_EHCI1 = 76,
@@ -285,6 +286,8 @@ static void allwinner_r40_init(Object *obj)
 TYPE_AW_SDHOST_SUN50I_A64);
 }
 
+object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
+
 for (size_t i = 0; i < AW_R40_NUM_USB; i++) {
 object_initialize_child(obj, "ehci[*]", &s->ehci[i],
 TYPE_PLATFORM_EHCI);
@@ -423,6 +426,13 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_R40_DEV_CCU]);
 
+/* SATA / AHCI */
+sysbus_realize(SYS_BUS_DEVICE(&s->sata), &error_fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0,
+allwinner_r40_memmap[AW_R40_DEV_AHCI]);
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0,
+   qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_AHCI));
+
 /* USB */
 for (size_t i = 0; i < AW_R40_NUM_USB; i++) {
 g_autofree char *bus = g_strdup_printf("usb-bus.%zu", i);
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index ae82822d42..c589fcc1c1 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -22,6 +22,7 @@
 
 #include "qom/object.h"
 #include "hw/timer/allwinner-a10-pit.h"
+#include "hw/ide/ahci.h"
 #include "hw/intc/arm_gic.h"
 #include "hw/sd/allwinner-sdhost.h"
 #include "hw/misc/allwinner-r40-ccu.h"
@@ -46,6 +47,7 @@ enum {
 AW_R40_DEV_MMC1,
 AW_R40_DEV_MMC2,
 AW_R40_DEV_MMC3,
+AW_R40_DEV_AHCI,
 AW_R40_DEV_EHCI1,
 AW_R40_DEV_OHCI1,
 AW_R40_DEV_EHCI2,
@@ -112,6 +114,7 @@ struct AwR40State {
 const hwaddr *memmap;
 AwSRAMCState sramc;
 AwA10PITState timer;
+AllwinnerAHCIState sata;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
 EHCISysBusState ehci[AW_R40_NUM_USB];
 OHCISysBusState ohci[AW_R40_NUM_USB];
-- 
2.39.2




[PATCH v2 3/3] hw/arm: Add watchdog timer to Allwinner H40 and Bananapi board

2024-01-15 Thread Guenter Roeck
Add watchdog timer support to Allwinner-H40 and Bananapi.
The watchdog timer is added as an overlay to the Timer
module memory map.

Signed-off-by: Guenter Roeck 
---
 docs/system/arm/bananapi_m2u.rst | 2 +-
 hw/arm/Kconfig   | 1 +
 hw/arm/allwinner-r40.c   | 8 
 include/hw/arm/allwinner-r40.h   | 3 +++
 4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
index 542310591d..587b488655 100644
--- a/docs/system/arm/bananapi_m2u.rst
+++ b/docs/system/arm/bananapi_m2u.rst
@@ -25,6 +25,7 @@ The Banana Pi M2U machine supports the following devices:
  * SATA
  * TWI (I2C)
  * USB 2.0
+ * Hardware Watchdog
 
 Limitations
 """""""""""
@@ -33,7 +34,6 @@ Currently, Banana Pi M2U does *not* support the following 
features:
 
 - Graphical output via HDMI, GPU and/or the Display Engine
 - Audio output
-- Hardware Watchdog
 - Real Time Clock
 
 Also see the 'unimplemented' array in the Allwinner R40 SoC module
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 98ca5ebc7d..386edbae15 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -411,6 +411,7 @@ config ALLWINNER_R40
 select AHCI
 select ALLWINNER_SRAMC
 select ALLWINNER_A10_PIT
+select ALLWINNER_WDT
 select AXP2XX_PMU
 select SERIAL
 select ARM_TIMER
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index 534be4a735..a28e5b3886 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -53,6 +53,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_OHCI2]  = 0x01c1c400,
 [AW_R40_DEV_CCU]= 0x01c2,
 [AW_R40_DEV_PIT]= 0x01c20c00,
+[AW_R40_DEV_WDT]= 0x01c20c90,
 [AW_R40_DEV_UART0]  = 0x01c28000,
 [AW_R40_DEV_UART1]  = 0x01c28400,
 [AW_R40_DEV_UART2]  = 0x01c28800,
@@ -279,6 +280,8 @@ static void allwinner_r40_init(Object *obj)
 object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
   "clk1-freq");
 
+object_initialize_child(obj, "wdt", &s->wdt, TYPE_AW_WDT_SUN4I);
+
 object_initialize_child(obj, "ccu", &s->ccu, TYPE_AW_R40_CCU);
 
 for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
@@ -545,6 +548,11 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_EMAC));
 
+/* WDT */
+sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0,
+allwinner_r40_memmap[AW_R40_DEV_WDT], 1);
+
 /* Unimplemented devices */
 for (unsigned i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
 create_unimplemented_device(r40_unimplemented[i].device_name,
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index c589fcc1c1..66c38e7d90 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -33,6 +33,7 @@
 #include "hw/net/allwinner-sun8i-emac.h"
 #include "hw/usb/hcd-ohci.h"
 #include "hw/usb/hcd-ehci.h"
+#include "hw/watchdog/allwinner-wdt.h"
 #include "target/arm/cpu.h"
 #include "sysemu/block-backend.h"
 
@@ -54,6 +55,7 @@ enum {
 AW_R40_DEV_OHCI2,
 AW_R40_DEV_CCU,
 AW_R40_DEV_PIT,
+AW_R40_DEV_WDT,
 AW_R40_DEV_UART0,
 AW_R40_DEV_UART1,
 AW_R40_DEV_UART2,
@@ -114,6 +116,7 @@ struct AwR40State {
 const hwaddr *memmap;
 AwSRAMCState sramc;
 AwA10PITState timer;
+AwWdtState wdt;
 AllwinnerAHCIState sata;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
 EHCISysBusState ehci[AW_R40_NUM_USB];
-- 
2.39.2




[PATCH v2 0/3] hw/arm: Add support for USB, SATA, and watchdog to Allwinner R40

2024-01-15 Thread Guenter Roeck
Add support for

- USB 2.0 EHCI/OHCI
- SATA/AHCI
- Watchdog

to Allwinner R40. The hardware is quite similar to Allwinner A10 and H3,
so the code is derived from the implementations for those SOCs.

Tested with bpim2u emulation by instantiating EHCI and OHCI keyboards,
by booting from USB, by booting from ATA/SATA drive, and by manually
testing watchdog operation.

v2:
- The USB Controllers are part of the chipset, so instantiate them
  unconditionally
- Add Reviewed-by: tag to patch 2/3


Guenter Roeck (3):
  hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board
  hw/arm: Add AHCI/SATA controller to Allwinner R40 and Bananapi board
  hw/arm: Add watchdog timer to Allwinner H40 and Bananapi board

 docs/system/arm/bananapi_m2u.rst |  5 +--
 hw/arm/Kconfig   |  4 +++
 hw/arm/allwinner-r40.c   | 67 ++--
 include/hw/arm/allwinner-r40.h   | 15 +
 4 files changed, 86 insertions(+), 5 deletions(-)



Re: [PATCH 1/2] hw/arm/allwinner-a10: Unconditionally map the USB Host controllers

2024-01-15 Thread Guenter Roeck
On Mon, Jan 15, 2024 at 05:56:14PM +0100, Philippe Mathieu-Daudé wrote:
> The USB Controllers are part of the chipset, thus are
> always present and mapped in memory.
> 
> Reported-by: Guenter Roeck 
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Guenter Roeck 
Tested-by: Guenter Roeck 



Re: [PATCH 1/3] hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board

2024-01-15 Thread Guenter Roeck

On 1/15/24 08:30, Philippe Mathieu-Daudé wrote:

On 15/1/24 17:12, Guenter Roeck wrote:

On 1/15/24 03:02, Philippe Mathieu-Daudé wrote:

Hi,

On 13/1/24 20:16, Guenter Roeck wrote:

Allwinner R40 supports two USB host ports shared between a USB 2.0 EHCI
host controller and a USB 1.1 OHCI host controller. Add support for both
of them.

If machine USB support is not enabled, create unimplemented devices
for the USB memory ranges to avoid crashes when booting Linux.


I never really understood the reason for machine_usb() and had on my
TODO to do some archeology research to figure it out since quite some
time. Having to map an UnimpDevice due to CLI options seems like an
anti-pattern when the device is indeed implemented in the repository.



Me not either. I copied the code from aw_a10_init(), trying to use the
same pattern. I am perfectly fine with making it unconditional, but then
I would argue that it should be unconditional for Allwinner A10 as well
(not that I really care much, just for consistency).


Certainly, but I'd rather have a global pattern cleanup, not just
Allwinner based machines. Looking at the repository:

$ git grep -w machine_usb hw/
hw/arm/allwinner-a10.c:82:    if (machine_usb(current_machine)) {
hw/arm/allwinner-a10.c:168:    if (machine_usb(current_machine)) {
hw/arm/nseries.c:1356:    if (machine_usb(machine)) {
hw/arm/realview.c:288:    if (machine_usb(machine)) {
hw/arm/realview.c-289-    pci_create_simple(pci_bus, -1, "pci-ohci");
hw/arm/versatilepb.c:276:    if (machine_usb(machine)) {
hw/arm/versatilepb.c-277-    pci_create_simple(pci_bus, -1, "pci-ohci");
hw/core/machine.c:1175:bool machine_usb(MachineState *machine)
hw/i386/acpi-microvm.c:88:    if (machine_usb(MACHINE(mms))) {
hw/i386/acpi-microvm.c-89-    xhci_sysbus_build_aml(scope, 
MICROVM_XHCI_BASE, MICROVM_XHCI_IRQ);
hw/i386/microvm.c:218:    if (x86_machine_is_acpi_enabled(x86ms) && 
machine_usb(MACHINE(mms))) {
hw/i386/microvm.c-225-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 
MICROVM_XHCI_BASE);
hw/i386/pc_piix.c:267: machine_usb(machine), &error_abort);
hw/i386/pc_q35.c:321:    if (machine_usb(machine)) {
hw/i386/pc_q35.c-323-    ehci_create_ich9_with_companions(host_bus, 0x1d);
hw/ppc/mac_oldworld.c:300:    if (machine_usb(machine)) {
hw/ppc/mac_oldworld.c-301-    pci_create_simple(pci_bus, -1, "pci-ohci");

I'd classify that as "USB controller over MMIO / over some bus (PCI)".

The "plug a PCI-to-USB card by default" seems a valid use case (except
for Q35 which is a Frankenstein case, ICH9 chipset is like ARM SoC,
USB bus is always there).

IMHO all the MMIO uses should be corrected.


The "-usb" option says "enable on-board USB host controller (if not
enabled by default)". Unfortunately, that doesn't tell me much,
and most specifically it doesn't tell me how to enable it by default.
One option I can think of would be to enable it on the machine level,
i.e., from bananapi_m2u.c, but then, again, I don't see if/how
that is done for other boards. Any suggestions ?

Of course, I could discuss this with the person who implemented this
code for A10, but it turns out that was me, for no good reason than
that I tried to follow the pattern I had seen elsewhere without really
understanding what I was doing.

So should I drop the conditional from H40 and send a separate patch
to drop it from the A10 code as well, following your line of argument ?
Or drop it and leave A10 alone ?


Well your patch isn't invalid, so:

Reviewed-by: Philippe Mathieu-Daudé 



I'll send v2 anyway, especially taking your other patch series into account.

Thanks,
Guenter




Re: [PATCH 1/3] hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board

2024-01-15 Thread Guenter Roeck

On 1/15/24 03:02, Philippe Mathieu-Daudé wrote:

Hi,

On 13/1/24 20:16, Guenter Roeck wrote:

Allwinner R40 supports two USB host ports shared between a USB 2.0 EHCI
host controller and a USB 1.1 OHCI host controller. Add support for both
of them.

If machine USB support is not enabled, create unimplemented devices
for the USB memory ranges to avoid crashes when booting Linux.


I never really understood the reason for machine_usb() and had on my
TODO to do some archeology research to figure it out since quite some
time. Having to map an UnimpDevice due to CLI options seems like an
anti-pattern when the device is indeed implemented in the repository.



Me not either. I copied the code from aw_a10_init(), trying to use the
same pattern. I am perfectly fine with making it unconditional, but then
I would argue that it should be unconditional for Allwinner A10 as well
(not that I really care much, just for consistency).

The "-usb" option says "enable on-board USB host controller (if not
enabled by default)". Unfortunately, that doesn't tell me much,
and most specifically it doesn't tell me how to enable it by default.
One option I can think of would be to enable it on the machine level,
i.e., from bananapi_m2u.c, but then, again, I don't see if/how
that is done for other boards. Any suggestions ?

Of course, I could discuss this with the person who implemented this
code for A10, but it turns out that was me, for no good reason than
that I tried to follow the pattern I had seen elsewhere without really
understanding what I was doing.

So should I drop the conditional from H40 and send a separate patch
to drop it from the A10 code as well, following your line of argument ?
Or drop it and leave A10 alone ?

Thanks,
Guenter




[PATCH 2/3] hw/arm: Add AHCI/SATA controller to Allwinner R40 and Bananapi board

2024-01-13 Thread Guenter Roeck
Allwinner R40 supports an AHCI compliant SATA controller.
Add support for it.

Signed-off-by: Guenter Roeck 
---
 docs/system/arm/bananapi_m2u.rst |  1 +
 hw/arm/Kconfig   |  1 +
 hw/arm/allwinner-r40.c   | 12 +++-
 include/hw/arm/allwinner-r40.h   |  3 +++
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
index e77c425e2c..542310591d 100644
--- a/docs/system/arm/bananapi_m2u.rst
+++ b/docs/system/arm/bananapi_m2u.rst
@@ -22,6 +22,7 @@ The Banana Pi M2U machine supports the following devices:
  * EMAC ethernet
  * GMAC ethernet
  * Clock Control Unit
+ * SATA
  * TWI (I2C)
  * USB 2.0
 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 6b508780d3..98ca5ebc7d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -408,6 +408,7 @@ config ALLWINNER_H3
 config ALLWINNER_R40
 bool
 default y if TCG && ARM
+select AHCI
 select ALLWINNER_SRAMC
 select ALLWINNER_A10_PIT
 select AXP2XX_PMU
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index f42b0fa0ce..f90d59fb5e 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -46,6 +46,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_MMC1]   = 0x01c1,
 [AW_R40_DEV_MMC2]   = 0x01c11000,
 [AW_R40_DEV_MMC3]   = 0x01c12000,
+[AW_R40_DEV_AHCI]   = 0x01c18000,
 [AW_R40_DEV_EHCI1]  = 0x01c19000,
 [AW_R40_DEV_OHCI1]  = 0x01c19400,
 [AW_R40_DEV_EHCI2]  = 0x01c1c000,
@@ -93,7 +94,6 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "usb0-host",  0x01c14000, 4 * KiB },
 { "crypto", 0x01c15000, 4 * KiB },
 { "spi2",   0x01c17000, 4 * KiB },
-{ "sata",   0x01c18000, 4 * KiB },
 { "usb1-phy",   0x01c19800, 2 * KiB },
 { "sid",0x01c1b000, 4 * KiB },
 { "usb2-phy",   0x01c1c800, 2 * KiB },
@@ -186,6 +186,7 @@ enum {
 AW_R40_GIC_SPI_MMC2  = 34,
 AW_R40_GIC_SPI_MMC3  = 35,
 AW_R40_GIC_SPI_EMAC  = 55,
+AW_R40_GIC_SPI_AHCI  = 56,
 AW_R40_GIC_SPI_OHCI1 = 64,
 AW_R40_GIC_SPI_OHCI2 = 65,
 AW_R40_GIC_SPI_EHCI1 = 76,
@@ -285,6 +286,8 @@ static void allwinner_r40_init(Object *obj)
 TYPE_AW_SDHOST_SUN50I_A64);
 }
 
+object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
+
 if (machine_usb(current_machine)) {
 int i;
 
@@ -427,6 +430,13 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_R40_DEV_CCU]);
 
+/* SATA / AHCI */
+sysbus_realize(SYS_BUS_DEVICE(&s->sata), &error_fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0,
+allwinner_r40_memmap[AW_R40_DEV_AHCI]);
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0,
+   qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_AHCI));
+
 /* USB */
 if (machine_usb(current_machine)) {
 int i;
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index ae82822d42..c589fcc1c1 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -22,6 +22,7 @@
 
 #include "qom/object.h"
 #include "hw/timer/allwinner-a10-pit.h"
+#include "hw/ide/ahci.h"
 #include "hw/intc/arm_gic.h"
 #include "hw/sd/allwinner-sdhost.h"
 #include "hw/misc/allwinner-r40-ccu.h"
@@ -46,6 +47,7 @@ enum {
 AW_R40_DEV_MMC1,
 AW_R40_DEV_MMC2,
 AW_R40_DEV_MMC3,
+AW_R40_DEV_AHCI,
 AW_R40_DEV_EHCI1,
 AW_R40_DEV_OHCI1,
 AW_R40_DEV_EHCI2,
@@ -112,6 +114,7 @@ struct AwR40State {
 const hwaddr *memmap;
 AwSRAMCState sramc;
 AwA10PITState timer;
+AllwinnerAHCIState sata;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
 EHCISysBusState ehci[AW_R40_NUM_USB];
 OHCISysBusState ohci[AW_R40_NUM_USB];
-- 
2.39.2




[PATCH 3/3] hw/arm: Add watchdog timer to Allwinner H40 and Bananapi board

2024-01-13 Thread Guenter Roeck
Add watchdog timer support to Allwinner-H40 and Bananapi.
The watchdog timer is added as an overlay to the Timer
module memory map.

Signed-off-by: Guenter Roeck 
---
 docs/system/arm/bananapi_m2u.rst | 2 +-
 hw/arm/Kconfig   | 1 +
 hw/arm/allwinner-r40.c   | 8 
 include/hw/arm/allwinner-r40.h   | 3 +++
 4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
index 542310591d..587b488655 100644
--- a/docs/system/arm/bananapi_m2u.rst
+++ b/docs/system/arm/bananapi_m2u.rst
@@ -25,6 +25,7 @@ The Banana Pi M2U machine supports the following devices:
  * SATA
  * TWI (I2C)
  * USB 2.0
+ * Hardware Watchdog
 
 Limitations
 """""""""""
@@ -33,7 +34,6 @@ Currently, Banana Pi M2U does *not* support the following 
features:
 
 - Graphical output via HDMI, GPU and/or the Display Engine
 - Audio output
-- Hardware Watchdog
 - Real Time Clock
 
 Also see the 'unimplemented' array in the Allwinner R40 SoC module
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 98ca5ebc7d..386edbae15 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -411,6 +411,7 @@ config ALLWINNER_R40
 select AHCI
 select ALLWINNER_SRAMC
 select ALLWINNER_A10_PIT
+select ALLWINNER_WDT
 select AXP2XX_PMU
 select SERIAL
 select ARM_TIMER
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index f90d59fb5e..334692ef97 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -53,6 +53,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_OHCI2]  = 0x01c1c400,
 [AW_R40_DEV_CCU]= 0x01c2,
 [AW_R40_DEV_PIT]= 0x01c20c00,
+[AW_R40_DEV_WDT]= 0x01c20c90,
 [AW_R40_DEV_UART0]  = 0x01c28000,
 [AW_R40_DEV_UART1]  = 0x01c28400,
 [AW_R40_DEV_UART2]  = 0x01c28800,
@@ -279,6 +280,8 @@ static void allwinner_r40_init(Object *obj)
 object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
   "clk1-freq");
 
+object_initialize_child(obj, "wdt", &s->wdt, TYPE_AW_WDT_SUN4I);
+
 object_initialize_child(obj, "ccu", &s->ccu, TYPE_AW_R40_CCU);
 
 for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
@@ -553,6 +556,11 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_EMAC));
 
+/* WDT */
+sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
+sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0,
+allwinner_r40_memmap[AW_R40_DEV_WDT], 1);
+
 /* Unimplemented devices */
 for (unsigned i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
 create_unimplemented_device(r40_unimplemented[i].device_name,
diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index c589fcc1c1..66c38e7d90 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -33,6 +33,7 @@
 #include "hw/net/allwinner-sun8i-emac.h"
 #include "hw/usb/hcd-ohci.h"
 #include "hw/usb/hcd-ehci.h"
+#include "hw/watchdog/allwinner-wdt.h"
 #include "target/arm/cpu.h"
 #include "sysemu/block-backend.h"
 
@@ -54,6 +55,7 @@ enum {
 AW_R40_DEV_OHCI2,
 AW_R40_DEV_CCU,
 AW_R40_DEV_PIT,
+AW_R40_DEV_WDT,
 AW_R40_DEV_UART0,
 AW_R40_DEV_UART1,
 AW_R40_DEV_UART2,
@@ -114,6 +116,7 @@ struct AwR40State {
 const hwaddr *memmap;
 AwSRAMCState sramc;
 AwA10PITState timer;
+AwWdtState wdt;
 AllwinnerAHCIState sata;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
 EHCISysBusState ehci[AW_R40_NUM_USB];
-- 
2.39.2




[PATCH 1/3] hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board

2024-01-13 Thread Guenter Roeck
Allwinner R40 supports two USB host ports shared between a USB 2.0 EHCI
host controller and a USB 1.1 OHCI host controller. Add support for both
of them.

If machine USB support is not enabled, create unimplemented devices
for the USB memory ranges to avoid crashes when booting Linux.

Signed-off-by: Guenter Roeck 
---
 docs/system/arm/bananapi_m2u.rst |  2 +-
 hw/arm/Kconfig   |  2 +
 hw/arm/allwinner-r40.c   | 70 +++-
 include/hw/arm/allwinner-r40.h   |  9 
 4 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
index b09ba5c548..e77c425e2c 100644
--- a/docs/system/arm/bananapi_m2u.rst
+++ b/docs/system/arm/bananapi_m2u.rst
@@ -23,6 +23,7 @@ The Banana Pi M2U machine supports the following devices:
  * GMAC ethernet
  * Clock Control Unit
  * TWI (I2C)
+ * USB 2.0
 
 Limitations
 """""""""""
@@ -33,7 +34,6 @@ Currently, Banana Pi M2U does *not* support the following 
features:
 - Audio output
 - Hardware Watchdog
 - Real Time Clock
-- USB 2.0 interfaces
 
 Also see the 'unimplemented' array in the Allwinner R40 SoC module
 for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-r40.c``
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 39d255425b..6b508780d3 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -415,6 +415,8 @@ config ALLWINNER_R40
 select ARM_TIMER
 select ARM_GIC
 select UNIMP
+select USB_OHCI
+select USB_EHCI_SYSBUS
 select SD
 
 config RASPI
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index a0d367c60d..f42b0fa0ce 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -23,6 +23,7 @@
 #include "qemu/bswap.h"
 #include "qemu/module.h"
 #include "qemu/units.h"
+#include "hw/boards.h"
 #include "hw/qdev-core.h"
 #include "hw/sysbus.h"
 #include "hw/char/serial.h"
@@ -45,6 +46,10 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_MMC1]   = 0x01c1,
 [AW_R40_DEV_MMC2]   = 0x01c11000,
 [AW_R40_DEV_MMC3]   = 0x01c12000,
+[AW_R40_DEV_EHCI1]  = 0x01c19000,
+[AW_R40_DEV_OHCI1]  = 0x01c19400,
+[AW_R40_DEV_EHCI2]  = 0x01c1c000,
+[AW_R40_DEV_OHCI2]  = 0x01c1c400,
 [AW_R40_DEV_CCU]= 0x01c2,
 [AW_R40_DEV_PIT]= 0x01c20c00,
 [AW_R40_DEV_UART0]  = 0x01c28000,
@@ -89,9 +94,9 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "crypto", 0x01c15000, 4 * KiB },
 { "spi2",   0x01c17000, 4 * KiB },
 { "sata",   0x01c18000, 4 * KiB },
-{ "usb1-host",  0x01c19000, 4 * KiB },
+{ "usb1-phy",   0x01c19800, 2 * KiB },
 { "sid",0x01c1b000, 4 * KiB },
-{ "usb2-host",  0x01c1c000, 4 * KiB },
+{ "usb2-phy",   0x01c1c800, 2 * KiB },
 { "cs1",0x01c1d000, 4 * KiB },
 { "spi3",   0x01c1f000, 4 * KiB },
 { "rtc",0x01c20400, 1 * KiB },
@@ -181,6 +186,10 @@ enum {
 AW_R40_GIC_SPI_MMC2  = 34,
 AW_R40_GIC_SPI_MMC3  = 35,
 AW_R40_GIC_SPI_EMAC  = 55,
+AW_R40_GIC_SPI_OHCI1 = 64,
+AW_R40_GIC_SPI_OHCI2 = 65,
+AW_R40_GIC_SPI_EHCI1 = 76,
+AW_R40_GIC_SPI_EHCI2 = 78,
 AW_R40_GIC_SPI_GMAC  = 85,
 };
 
@@ -276,6 +285,17 @@ static void allwinner_r40_init(Object *obj)
 TYPE_AW_SDHOST_SUN50I_A64);
 }
 
+if (machine_usb(current_machine)) {
+int i;
+
+for (i = 0; i < AW_R40_NUM_USB; i++) {
+object_initialize_child(obj, "ehci[*]", &s->ehci[i],
+TYPE_PLATFORM_EHCI);
+object_initialize_child(obj, "ohci[*]", &s->ohci[i],
+TYPE_SYSBUS_OHCI);
+}
+}
+
 object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
 
 object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
@@ -407,6 +427,37 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_R40_DEV_CCU]);
 
+/* USB */
+if (machine_usb(current_machine)) {
+int i;
+
+for (i = 0; i < AW_R40_NUM_USB; i++) {
+g_autofree char *bus = g_strdup_printf("usb-bus.%d", i);
+
+object_property_set_bool(OBJECT(&s->ehci[i]), "companion-enable",
+ true, &error_fatal);
+sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), &error_fatal);
+sysbus_mmio_ma

[PATCH 0/3] hw/arm: Add support for USB, SATA, and watchdog to Allwinner R40

2024-01-13 Thread Guenter Roeck
Add support for

- USB 2.0 EHCI/OHCI
- SATA/AHCI
- Watchdog

to Allwinner R40. The hardware is quite similar to Allwinner A10 and H3,
so the code is derived from the implementations for those SOCs.

Tested with bpim2u emulation by instantiating EHCI and OHCI keyboards,
by booting from USB, by booting from ATA/SATA drive, and by manually
testing watchdog operation.


Guenter Roeck (3):
  hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board
  hw/arm: Add AHCI/SATA controller to Allwinner R40 and Bananapi board
  hw/arm: Add watchdog timer to Allwinner H40 and Bananapi board

 docs/system/arm/bananapi_m2u.rst |  5 ++-
 hw/arm/Kconfig   |  4 ++
 hw/arm/allwinner-r40.c   | 90 ++--
 include/hw/arm/allwinner-r40.h   | 15 +++
 4 files changed, 109 insertions(+), 5 deletions(-)



Re: [PATCH 3/4] esp-pci.c: synchronise setting of DMA_STAT_DONE with ESP completion interrupt

2024-01-12 Thread Guenter Roeck
On Fri, Jan 12, 2024 at 01:15:28PM +, Mark Cave-Ayland wrote:
> The setting of DMA_STAT_DONE at the end of a DMA transfer can be configured to
> generate an interrupt, however the Linux driver manually checks for 
> DMA_STAT_DONE
> being set and if it is, considers that a DMA transfer has completed.
> 
> If DMA_STAT_DONE is set but the ESP device isn't indicating an interrupt then
> the Linux driver considers this to be a spurious interrupt. However this can
> occur in QEMU as there is a delay between the end of DMA transfer where
> DMA_STAT_DONE is set, and the ESP device raising its completion interrupt.
> 
> This appears to be an incorrect assumption in the Linux driver as the ESP and
> PCI DMA interrupt sources are separate (and may not be raised exactly
> together), however we can work around this by synchronising the setting of
> DMA_STAT_DONE at the end of a DMA transfer with the ESP completion interrupt.
> 
> In conjunction with the previous commit Linux is now able to correctly boot
> from an am53c974 PCI SCSI device on the hppa C3700 machine without emitting
> "iget: checksum invalid" and "Spurious irq, sreg=10" errors.
> 
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Guenter Roeck 
Tested-by: Guenter Roeck 

> ---
>  hw/scsi/esp-pci.c | 28 +---
>  1 file changed, 13 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
> index 15dc3c004d..875a49199d 100644
> --- a/hw/scsi/esp-pci.c
> +++ b/hw/scsi/esp-pci.c
> @@ -93,6 +93,18 @@ static void esp_irq_handler(void *opaque, int irq_num, int 
> level)
>  
>  if (level) {
>  pci->dma_regs[DMA_STAT] |= DMA_STAT_SCSIINT;
> +
> +/*
> + * If raising the ESP IRQ to indicate end of DMA transfer, set
> + * DMA_STAT_DONE at the same time. In theory this should be done in
> + * esp_pci_dma_memory_rw(), however there is a delay between setting
> + * DMA_STAT_DONE and the ESP IRQ arriving which is visible to the
> + * guest that can cause confusion e.g. Linux
> + */
> +if ((pci->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x3 &&
> +pci->dma_regs[DMA_WBC] == 0) {
> +pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
> +}
>  } else {
>  pci->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT;
>  }
> @@ -306,9 +318,6 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, 
> uint8_t *buf, int len,
>  /* update status registers */
>  pci->dma_regs[DMA_WBC] -= len;
>  pci->dma_regs[DMA_WAC] += len;
> -if (pci->dma_regs[DMA_WBC] == 0) {
> -pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
> -}
>  }
>  
>  static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
> @@ -363,24 +372,13 @@ static const VMStateDescription vmstate_esp_pci_scsi = {
>  }
>  };
>  
> -static void esp_pci_command_complete(SCSIRequest *req, size_t resid)
> -{
> -ESPState *s = req->hba_private;
> -PCIESPState *pci = container_of(s, PCIESPState, esp);
> -
> -esp_command_complete(req, resid);
> -pci->dma_regs[DMA_WBC] = 0;
> -pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
> -esp_pci_update_irq(pci);
> -}
> -
>  static const struct SCSIBusInfo esp_pci_scsi_info = {
>  .tcq = false,
>  .max_target = ESP_MAX_DEVS,
>  .max_lun = 7,
>  
>  .transfer_data = esp_transfer_data,
> -.complete = esp_pci_command_complete,
> +.complete = esp_command_complete,
>  .cancel = esp_request_cancelled,
>  };
>  
> -- 
> 2.39.2
> 



Re: [PATCH 4/4] esp-pci.c: set DMA_STAT_BCMBLT when BLAST command issued

2024-01-12 Thread Guenter Roeck
On Fri, Jan 12, 2024 at 01:15:29PM +, Mark Cave-Ayland wrote:
> Even though the BLAST command isn't fully implemented in QEMU, the 
> DMA_STAT_BCMBLT
> bit should be set after the command has been issued to indicate that the 
> command
> has completed.
> 
> This fixes an issue with the DC390 DOS driver which issues the BLAST command 
> as
> part of its normal error recovery routine at startup, and otherwise sits in a
> tight loop waiting for DMA_STAT_BCMBLT to be set before continuing.
> 
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Guenter Roeck 
Tested-by: Guenter Roeck 

> ---
>  hw/scsi/esp-pci.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
> index 875a49199d..42d9d2e483 100644
> --- a/hw/scsi/esp-pci.c
> +++ b/hw/scsi/esp-pci.c
> @@ -124,6 +124,7 @@ static void esp_pci_handle_blast(PCIESPState *pci, 
> uint32_t val)
>  {
>  trace_esp_pci_dma_blast(val);
>  qemu_log_mask(LOG_UNIMP, "am53c974: cmd BLAST not implemented\n");
> +pci->dma_regs[DMA_STAT] |= DMA_STAT_BCMBLT;
>  }
>  
>  static void esp_pci_handle_abort(PCIESPState *pci, uint32_t val)
> -- 
> 2.39.2
> 



Re: [PATCH 2/4] esp-pci.c: generate PCI interrupt from separate ESP and PCI sources

2024-01-12 Thread Guenter Roeck
On Fri, Jan 12, 2024 at 01:15:27PM +, Mark Cave-Ayland wrote:
> The am53c974/dc390 PCI interrupt has two separate sources: the first is from 
> the
> internal ESP device, and the second is from the PCI DMA transfer logic.
> 
> Update the ESP interrupt handler so that it sets DMA_STAT_SCSIINT rather than
> driving the PCI IRQ directly, and introduce a new esp_pci_update_irq() 
> function
> to generate the correct PCI IRQ level. In particular this fixes spurious 
> interrupts
> being generated by setting DMA_STAT_DONE at the end of a transfer if 
> DMA_CMD_INTE_D
> isn't set in the DMA_CMD register.
> 
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Guenter Roeck 
Tested-by: Guenter Roeck 

> ---
>  hw/scsi/esp-pci.c | 32 +++-
>  1 file changed, 27 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
> index 7117725371..15dc3c004d 100644
> --- a/hw/scsi/esp-pci.c
> +++ b/hw/scsi/esp-pci.c
> @@ -77,6 +77,29 @@ struct PCIESPState {
>  ESPState esp;
>  };
>  
> +static void esp_pci_update_irq(PCIESPState *pci)
> +{
> +int scsi_level = !!(pci->dma_regs[DMA_STAT] & DMA_STAT_SCSIINT);
> +int dma_level = (pci->dma_regs[DMA_CMD] & DMA_CMD_INTE_D) ?
> +!!(pci->dma_regs[DMA_STAT] & DMA_STAT_DONE) : 0;
> +int level = scsi_level || dma_level;
> +
> +pci_set_irq(PCI_DEVICE(pci), level);
> +}
> +
> +static void esp_irq_handler(void *opaque, int irq_num, int level)
> +{
> +PCIESPState *pci = PCI_ESP(opaque);
> +
> +if (level) {
> +pci->dma_regs[DMA_STAT] |= DMA_STAT_SCSIINT;
> +} else {
> +pci->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT;
> +}
> +
> +esp_pci_update_irq(pci);
> +}
> +
>  static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val)
>  {
>  ESPState *s = &pci->esp;
> @@ -151,6 +174,7 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t 
> saddr, uint32_t val)
>  /* clear some bits on write */
>  uint32_t mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE;
>  pci->dma_regs[DMA_STAT] &= ~(val & mask);
> +esp_pci_update_irq(pci);
>  }
>  break;
>  default:
> @@ -161,17 +185,14 @@ static void esp_pci_dma_write(PCIESPState *pci, 
> uint32_t saddr, uint32_t val)
>  
>  static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr)
>  {
> -ESPState *s = &pci->esp;
>  uint32_t val;
>  
>  val = pci->dma_regs[saddr];
>  if (saddr == DMA_STAT) {
> -if (s->rregs[ESP_RSTAT] & STAT_INT) {
> -val |= DMA_STAT_SCSIINT;
> -}
>  if (!(pci->sbac & SBAC_STATUS)) {
>  pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT |
>   DMA_STAT_DONE);
> +esp_pci_update_irq(pci);
>  }
>  }
>  
> @@ -350,6 +371,7 @@ static void esp_pci_command_complete(SCSIRequest *req, 
> size_t resid)
>  esp_command_complete(req, resid);
>  pci->dma_regs[DMA_WBC] = 0;
>  pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
> +esp_pci_update_irq(pci);
>  }
>  
>  static const struct SCSIBusInfo esp_pci_scsi_info = {
> @@ -386,7 +408,7 @@ static void esp_pci_scsi_realize(PCIDevice *dev, Error 
> **errp)
>"esp-io", 0x80);
>  
>  pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
> -s->irq = pci_allocate_irq(dev);
> +s->irq = qemu_allocate_irq(esp_irq_handler, pci, 0);
>  
>  scsi_bus_init(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info);
>  }
> -- 
> 2.39.2
> 



Re: [PATCH 1/4] esp-pci.c: use correct address register for PCI DMA transfers

2024-01-12 Thread Guenter Roeck
On Fri, Jan 12, 2024 at 01:15:26PM +, Mark Cave-Ayland wrote:
> The current code in esp_pci_dma_memory_rw() sets the DMA address to the value
> of the DMA_SPA (Starting Physical Address) register which is incorrect: this
> means that for each callback from the SCSI layer the DMA address is set back
> to the starting address.
> 
> In the case where only a single SCSI callback occurs (currently for transfer
> lengths < 128kB) this works fine, however for larger transfers the DMA address
> wraps back to the initial starting address, corrupting the buffer holding the
> data transferred to the guest.
> 
> Fix esp_pci_dma_memory_rw() to use the DMA_WAC (Working Address Counter) for
> the DMA address which is correctly incremented across multiple SCSI layer
> transfers.
> 
> Signed-off-by: Mark Cave-Ayland 

Reviewed-by: Guenter Roeck 
Tested-by: Guenter Roeck 

> ---
>  hw/scsi/esp-pci.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
> index 93b3429e0f..7117725371 100644
> --- a/hw/scsi/esp-pci.c
> +++ b/hw/scsi/esp-pci.c
> @@ -275,7 +275,7 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, 
> uint8_t *buf, int len,
>  qemu_log_mask(LOG_UNIMP, "am53c974: MDL transfer not implemented\n");
>  }
>  
> -addr = pci->dma_regs[DMA_SPA];
> +addr = pci->dma_regs[DMA_WAC];
>  if (pci->dma_regs[DMA_WBC] < len) {
>  len = pci->dma_regs[DMA_WBC];
>  }
> -- 
> 2.39.2
> 



Re: [PATCH] hw/sd/pxa2xx_mmci: Disable reentrancy detection

2023-12-13 Thread Guenter Roeck

On 12/13/23 09:19, Philippe Mathieu-Daudé wrote:

Hi Guenter,

On 13/12/23 18:12, Peter Maydell wrote:

On Wed, 13 Dec 2023 at 01:49, Guenter Roeck  wrote:


All tests using pxa2xx_mmc to access mmc cards on pxa2xx platforms
such as borzoi fail starting with commit a2e1753b80 ("memory: prevent
dma-reentracy issues"). Disable reentrancy guard to fix the problem.

Fixes: a2e1753b80 ("memory: prevent dma-reentracy issues")
Signed-off-by: Guenter Roeck 
---
  hw/sd/pxa2xx_mmci.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 5e8ea69188..27ae8f2888 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -555,6 +555,8 @@ static void pxa2xx_mmci_instance_init(Object *obj)
  qdev_init_gpio_out_named(dev, &s->rx_dma, "rx-dma", 1);
  qdev_init_gpio_out_named(dev, &s->tx_dma, "tx-dma", 1);

+    s->iomem.disable_reentrancy_guard = true;
+


All patches that set this flag should include a comment which
explains what the device access path that triggers the reentrancy
is, please.


Can we get a reproducer or backtrace please?


qemu-system-arm: warning: Blocked re-entrant IO on MemoryRegion: pxa2xx-mmci at 
addr: 0x40
[0.770246] mmc0: invalid bus width
[0.770962] mmc0: error -22 whilst initialising SD card
[0.828179] mmc0: invalid bus width
[0.828445] mmc0: error -22 whilst initialising SD card

with:

qemu-system-arm -M borzoi -kernel arch/arm/boot/zImage -no-reboot -snapshot \
-device sd-card,drive=d0 -drive 
file=/tmp/flash,format=raw,if=none,id=d0 \
-usb -device usb-net,netdev=net0 -netdev user,id=net0 \
--append "root=/dev/mmcblk0 rootwait console=ttyS0"

Guenter




Re: [PATCH] hw/sd/pxa2xx_mmci: Disable reentrancy detection

2023-12-13 Thread Guenter Roeck

On 12/13/23 09:12, Peter Maydell wrote:

On Wed, 13 Dec 2023 at 01:49, Guenter Roeck  wrote:


All tests using pxa2xx_mmc to access mmc cards on pxa2xx platforms
such as borzoi fail starting with commit a2e1753b80 ("memory: prevent
dma-reentracy issues"). Disable reentrancy guard to fix the problem.

Fixes: a2e1753b80 ("memory: prevent dma-reentracy issues")
Signed-off-by: Guenter Roeck 
---
  hw/sd/pxa2xx_mmci.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 5e8ea69188..27ae8f2888 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -555,6 +555,8 @@ static void pxa2xx_mmci_instance_init(Object *obj)
  qdev_init_gpio_out_named(dev, &s->rx_dma, "rx-dma", 1);
  qdev_init_gpio_out_named(dev, &s->tx_dma, "tx-dma", 1);

+s->iomem.disable_reentrancy_guard = true;
+


All patches that set this flag should include a comment which
explains what the device access path that triggers the reentrancy
is, please.



No idea what that would be, sorry. I noticed that the reentrancy guard
causes the affected emulations to fail, but I have no understanding or
knowledge of the code itself. NP if this is insufficient to apply the patch.
I am carrying it locally anyway, so for me it doesn't make a difference.
Maybe someone with better understanding of the underlying code can pick
it up at some point in the future and provide the necessary context.

Thanks,
Guenter




Re: [RFC 1/1] hw: tpmtisspi: add SPI support to QEMU TPM implementation

2023-12-13 Thread Guenter Roeck
Hi,

On Tue, Aug 02, 2022 at 07:32:41PM -0700, Iris Chen wrote:
> From: Iris Chen 
> 
> Signed-off-by: Iris Chen 
> ---

Are there any plans to submit a new version of this patch ?

Thanks,
Guenter

>  configs/devices/arm-softmmu/default.mak |   1 +
>  hw/arm/Kconfig  |   5 +
>  hw/tpm/Kconfig  |   5 +
>  hw/tpm/meson.build  |   1 +
>  hw/tpm/tpm_tis_spi.c| 311 
>  include/sysemu/tpm.h|   3 +
>  6 files changed, 326 insertions(+)
>  create mode 100644 hw/tpm/tpm_tis_spi.c
> 
> diff --git a/configs/devices/arm-softmmu/default.mak 
> b/configs/devices/arm-softmmu/default.mak
> index 6985a25377..80d2841568 100644
> --- a/configs/devices/arm-softmmu/default.mak
> +++ b/configs/devices/arm-softmmu/default.mak
> @@ -42,3 +42,4 @@ CONFIG_FSL_IMX6UL=y
>  CONFIG_SEMIHOSTING=y
>  CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
>  CONFIG_ALLWINNER_H3=y
> +CONFIG_FBOBMC_AST=y
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 15fa79afd3..193decaec1 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -458,6 +458,11 @@ config ASPEED_SOC
>  select PMBUS
>  select MAX31785
>  
> +config FBOBMC_AST
> +bool
> +select ASPEED_SOC
> +select TPM_TIS_SPI
> +
>  config MPS2
>  bool
>  imply I2C_DEVICES
> diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
> index 29e82f3c92..370a43f045 100644
> --- a/hw/tpm/Kconfig
> +++ b/hw/tpm/Kconfig
> @@ -8,6 +8,11 @@ config TPM_TIS_SYSBUS
>  depends on TPM
>  select TPM_TIS
>  
> +config TPM_TIS_SPI
> +bool
> +depends on TPM
> +select TPM_TIS
> +
>  config TPM_TIS
>  bool
>  depends on TPM
> diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
> index 1c68d81d6a..1a057f4e36 100644
> --- a/hw/tpm/meson.build
> +++ b/hw/tpm/meson.build
> @@ -2,6 +2,7 @@ softmmu_ss.add(when: 'CONFIG_TPM_TIS', if_true: 
> files('tpm_tis_common.c'))
>  softmmu_ss.add(when: 'CONFIG_TPM_TIS_ISA', if_true: files('tpm_tis_isa.c'))
>  softmmu_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: 
> files('tpm_tis_sysbus.c'))
>  softmmu_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
> +softmmu_ss.add(when: 'CONFIG_TPM_TIS_SPI', if_true: files('tpm_tis_spi.c'))
>  
>  specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TPM_TIS'], if_true: 
> files('tpm_ppi.c'))
>  specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TPM_CRB'], if_true: 
> files('tpm_ppi.c'))
> diff --git a/hw/tpm/tpm_tis_spi.c b/hw/tpm/tpm_tis_spi.c
> new file mode 100644
> index 00..c98ddcfddb
> --- /dev/null
> +++ b/hw/tpm/tpm_tis_spi.c
> @@ -0,0 +1,311 @@
> +#include "qemu/osdep.h"
> +#include "hw/qdev-properties.h"
> +#include "migration/vmstate.h"
> +#include "hw/acpi/tpm.h"
> +#include "tpm_prop.h"
> +#include "tpm_tis.h"
> +#include "qom/object.h"
> +#include "hw/ssi/ssi.h"
> +#include "hw/ssi/spi_gpio.h"
> +
> +#define TPM_TIS_SPI_ADDR_BYTES 3
> +#define SPI_WRITE 0
> +
> +typedef enum {
> +TIS_SPI_PKT_STATE_DEACTIVATED = 0,
> +TIS_SPI_PKT_STATE_START,
> +TIS_SPI_PKT_STATE_ADDRESS,
> +TIS_SPI_PKT_STATE_DATA_WR,
> +TIS_SPI_PKT_STATE_DATA_RD,
> +TIS_SPI_PKT_STATE_DONE,
> +} TpmTisSpiPktState;
> +
> +union TpmTisRWSizeByte {
> +uint8_t byte;
> +struct {
> +uint8_t data_expected_size:6;
> +uint8_t resv:1;
> +uint8_t rwflag:1;
> +};
> +};
> +
> +union TpmTisSpiHwAddr {
> +hwaddr addr;
> +uint8_t bytes[sizeof(hwaddr)];
> +};
> +
> +union TpmTisSpiData {
> +uint32_t data;
> +uint8_t bytes[64];
> +};
> +
> +struct TpmTisSpiState {
> +/*< private >*/
> +SSIPeripheral parent_obj;
> +
> +/*< public >*/
> +TPMState tpm_state; /* not a QOM object */
> +TpmTisSpiPktState tpm_tis_spi_state;
> +
> +union TpmTisRWSizeByte first_byte;
> +union TpmTisSpiHwAddr addr;
> +union TpmTisSpiData data;
> +
> +uint32_t data_size;
> +uint8_t data_idx;
> +uint8_t addr_idx;
> +};
> +
> +struct TpmTisSpiClass {
> +SSIPeripheralClass parent_class;
> +};
> +
> +OBJECT_DECLARE_TYPE(TpmTisSpiState, TpmTisSpiClass, TPM_TIS_SPI)
> +
> +static void tpm_tis_spi_mmio_read(TpmTisSpiState *tts)
> +{
> +uint16_t offset = tts->addr.addr & 0xffc;
> +
> +switch (offset) {
> +case TPM_TIS_REG_DATA_FIFO:
> +for (uint8_t i = 0; i < tts->data_size; i++) {
> +tts->data.bytes[i] = (uint8_t)tpm_tis_memory_ops.read(
> +  &tts->tpm_state,
> +  tts->addr.addr,
> +  1);
> +}
> +break;
> +default:
> +tts->data.data = (uint32_t)tpm_tis_memory_ops.read(
> +   &tts->tpm_state,
> +   tts->addr.addr,
> +   tts->data_size);
> +}
> +}
> +
> +static void tpm_tis_spi_mmio_write(TpmTisSpiState *tts)
> +{
> +uint16_t offset = tts-

[PATCH] hw/sd/pxa2xx_mmci: Disable reentrancy detection

2023-12-12 Thread Guenter Roeck
All tests using pxa2xx_mmc to access mmc cards on pxa2xx platforms
such as borzoi fail starting with commit a2e1753b80 ("memory: prevent
dma-reentracy issues"). Disable reentrancy guard to fix the problem.

Fixes: a2e1753b80 ("memory: prevent dma-reentracy issues")
Signed-off-by: Guenter Roeck 
---
 hw/sd/pxa2xx_mmci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 5e8ea69188..27ae8f2888 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -555,6 +555,8 @@ static void pxa2xx_mmci_instance_init(Object *obj)
 qdev_init_gpio_out_named(dev, &s->rx_dma, "rx-dma", 1);
 qdev_init_gpio_out_named(dev, &s->tx_dma, "tx-dma", 1);
 
+s->iomem.disable_reentrancy_guard = true;
+
 qbus_init(&s->sdbus, sizeof(s->sdbus),
   TYPE_PXA2XX_MMCI_BUS, DEVICE(obj), "sd-bus");
 }
-- 
2.39.2




Re: [PATCH v5 01/11] hw: arm: Add bananapi M2-Ultra and allwinner-r40 support

2023-08-01 Thread Guenter Roeck

On 8/1/23 09:01, Peter Maydell wrote:

On Sat, 24 Jun 2023 at 16:02, Guenter Roeck  wrote:


On 6/24/23 07:23, Guenter Roeck wrote:

On 6/24/23 03:40, Peter Maydell wrote:

On Fri, 23 Jun 2023 at 20:33, Guenter Roeck  wrote:


On 6/23/23 10:44, Peter Maydell wrote:

On Sat, 17 Jun 2023 at 17:29, Guenter Roeck  wrote:

Main problem is that the SD card gets instantiated randomly to
mmc0, mmc1, or mmc2, making it all but impossible to specify a
root file system device. The non-instantiated cards are always
reported as non-removable, including mmc0. Example:

mmc0: Failed to initialize a non-removable card


Do you mean that QEMU randomly connects the SD card to
a different MMC controller each time, or that Linux is
randomly assigning mmc0 to a different MMC controller each
time ?



Good question. Given the workaround (fix ?) I suggested is
in the devicetree file, I would assume it is the latter. I suspect
that Linux assigns drive names based on hardware detection order,
and that this is not deterministic for some reason. It is odd
because I have never experienced that with any other emulation.


Yeah, I don't really understand why it would be non-deterministic.
But it does make it sound like the right thing is for the
device tree file to explicitly say which MMC controller is
which -- presumably you might get unlucky with the timing
on real hardware too.



Agreed, only someone with real hardware would have to confirm
that this is the case.



Actually, the reason is quite simple. In the Linux kernel:

static struct platform_driver sunxi_mmc_driver = {
  .driver = {
  .name   = "sunxi-mmc",
  .probe_type = PROBE_PREFER_ASYNCHRONOUS,
^
  .of_match_table = sunxi_mmc_of_match,
  .pm = &sunxi_mmc_pm_ops,
  },
  .probe  = sunxi_mmc_probe,
  .remove = sunxi_mmc_remove,
};

All mmc devices instantiate at the same time, thus the
device name association is random. If I drop the probe_type
assignment, it becomes deterministic.

On top of that, Linux does know which drives are removable
from the devicetree file. However, since probe order is
random, the assignment of the one removable drive to device
names is random. Sometimes mmc0 shows up as removable,
sometimes it is mmc1 or mmc2.

So my conclusion is that qemu isn't doing anything wrong,
it is all happening in the Linux kernel.


Hi Guenter -- do you know if this "random MMC controller"
issue has been fixed in Linux ? If so, we might be able
to update our test case image to avoid the slightly ugly
"root=b300" workaround at some point.



No, it has not been fixed, or at least there is nothing in linux-next.
I don't have real hardware, so I am not in a position to submit, much
less test, a patch on it. Someone had mentioned that real hardware would
handle the problem in initramfs. That seems wrong to me, but it is what
it is.

I changed my own test to use the "root=b300" hack. That seems highly kludgy,
but at least it works.

Guenter




Re: [PATCH] hw/sd/sdhci: Do not force sdhci_mmio_*_ops onto all SD controllers

2023-07-24 Thread Guenter Roeck

On 7/24/23 00:18, Bernhard Beschow wrote:



Am 16. Juli 2023 19:53:37 UTC schrieb Bernhard Beschow :



Am 10. Juli 2023 16:01:46 UTC schrieb Bernhard Beschow :



Am 10. Juli 2023 10:16:35 UTC schrieb "Philippe Mathieu-Daudé" 
:

On 9/7/23 10:09, Bernhard Beschow wrote:

Since commit c0a55a0c9da2 "hw/sd/sdhci: Support big endian SD host controller
interfaces" sdhci_common_realize() forces all SD card controllers to use either
sdhci_mmio_le_ops or sdhci_mmio_be_ops, depending on the "endianness" property.
However, there are device models which use different MMIO ops: TYPE_IMX_USDHC
uses usdhc_mmio_ops and TYPE_S3C_SDHCI uses sdhci_s3c_mmio_ops.

Forcing sdhci_mmio_le_ops breaks SD card handling on the "sabrelite" board, for
example. Fix this by defaulting the io_ops to little endian and switch to big
endian in sdhci_common_realize() only if there is a matchig big endian variant
available.

Fixes: c0a55a0c9da2 ("hw/sd/sdhci: Support big endian SD host controller
interfaces")

Signed-off-by: Bernhard Beschow 
---
   hw/sd/sdhci.c | 8 +++-
   1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 6811f0f1a8..362c2c86aa 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1382,6 +1382,8 @@ void sdhci_initfn(SDHCIState *s)
 s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
sdhci_raise_insertion_irq, s);
   s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
sdhci_data_transfer, s);
+
+s->io_ops = &sdhci_mmio_le_ops;
   }
 void sdhci_uninitfn(SDHCIState *s)
@@ -1399,9 +1401,13 @@ void sdhci_common_realize(SDHCIState *s, Error **errp)
   


What about simply keeping the same code guarded with 'if (!s->io_ops)'?


I chose below approach since it provides an error message when one attempts to 
set one of the other device models to BE rather than just silently ignoring it.

Also, I didn't want to make the assumption that `s->io_ops == NULL` implied 
that sdhci_mmio_*_ops is needed. That's similar material the bug fixed is made of, 
so I wanted to prevent that in the first place by being more explicit.

In combination with the new error message the limitations of the current code 
become hopefully very apparent now, and at the same time should provide enough 
hints for adding BE support to the other device models if ever needed.

Best regards,
Bernhard


Ping


Ping^2

I would like to have the bug fixed in 8.1.



+1

Not that I care too much - I build qemu myself anyway and carry the patch 
locally -
but this really should get fixed.

Guenter




Re: [PATCH] hw/sd/sdhci: Do not force sdhci_mmio_*_ops onto all SD controllers

2023-07-10 Thread Guenter Roeck
On Mon, Jul 10, 2023 at 12:16:35PM +0200, Philippe Mathieu-Daudé wrote:
> On 9/7/23 10:09, Bernhard Beschow wrote:
> > Since commit c0a55a0c9da2 "hw/sd/sdhci: Support big endian SD host 
> > controller
> > interfaces" sdhci_common_realize() forces all SD card controllers to use 
> > either
> > sdhci_mmio_le_ops or sdhci_mmio_be_ops, depending on the "endianness" 
> > property.
> > However, there are device models which use different MMIO ops: 
> > TYPE_IMX_USDHC
> > uses usdhc_mmio_ops and TYPE_S3C_SDHCI uses sdhci_s3c_mmio_ops.
> > 
> > Forcing sdhci_mmio_le_ops breaks SD card handling on the "sabrelite" board, 
> > for
> > example. Fix this by defaulting the io_ops to little endian and switch to 
> > big
> > endian in sdhci_common_realize() only if there is a matchig big endian 
> > variant
> > available.
> > 
> > Fixes: c0a55a0c9da2 ("hw/sd/sdhci: Support big endian SD host controller
> > interfaces")
> > 
> > Signed-off-by: Bernhard Beschow 
> > ---
> >   hw/sd/sdhci.c | 8 +++-
> >   1 file changed, 7 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> > index 6811f0f1a8..362c2c86aa 100644
> > --- a/hw/sd/sdhci.c
> > +++ b/hw/sd/sdhci.c
> > @@ -1382,6 +1382,8 @@ void sdhci_initfn(SDHCIState *s)
> >   s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
> > sdhci_raise_insertion_irq, s);
> >   s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
> > sdhci_data_transfer, s);
> > +
> > +s->io_ops = &sdhci_mmio_le_ops;
> >   }
> >   void sdhci_uninitfn(SDHCIState *s)
> > @@ -1399,9 +1401,13 @@ void sdhci_common_realize(SDHCIState *s, Error 
> > **errp)
> 
> What about simply keeping the same code guarded with 'if (!s->io_ops)'?
> 

That was my quick fix which I considered a hack, and I didn't submit it
because I thought it was a hack ;-).

On the other side, this solution would probably break on big endian systems
which have their own io ops, so I am not sure if it is any better.

Guenter

> >   switch (s->endianness) {
> >   case DEVICE_LITTLE_ENDIAN:
> > -s->io_ops = &sdhci_mmio_le_ops;
> > +/* s->io_ops is little endian by default */
> >   break;
> >   case DEVICE_BIG_ENDIAN:
> > +if (s->io_ops != &sdhci_mmio_le_ops) {
> > +error_setg(errp, "SD controller doesn't support big 
> > endianness");
> > +return;
> > +}
> >   s->io_ops = &sdhci_mmio_be_ops;
> >   break;
> >   default:
> 



Re: [PATCH] hw/sd/sdhci: Do not force sdhci_mmio_*_ops onto all SD controllers

2023-07-09 Thread Guenter Roeck

On 7/9/23 01:09, Bernhard Beschow wrote:

Since commit c0a55a0c9da2 "hw/sd/sdhci: Support big endian SD host controller
interfaces" sdhci_common_realize() forces all SD card controllers to use either
sdhci_mmio_le_ops or sdhci_mmio_be_ops, depending on the "endianness" property.
However, there are device models which use different MMIO ops: TYPE_IMX_USDHC
uses usdhc_mmio_ops and TYPE_S3C_SDHCI uses sdhci_s3c_mmio_ops.

Forcing sdhci_mmio_le_ops breaks SD card handling on the "sabrelite" board, for
example. Fix this by defaulting the io_ops to little endian and switch to big
endian in sdhci_common_realize() only if there is a matchig big endian variant
available.

Fixes: c0a55a0c9da2 ("hw/sd/sdhci: Support big endian SD host controller
interfaces")

Signed-off-by: Bernhard Beschow 


Tested-by: Guenter Roeck 


---
  hw/sd/sdhci.c | 8 +++-
  1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 6811f0f1a8..362c2c86aa 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1382,6 +1382,8 @@ void sdhci_initfn(SDHCIState *s)
  
  s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);

  s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, 
s);
+
+s->io_ops = &sdhci_mmio_le_ops;
  }
  
  void sdhci_uninitfn(SDHCIState *s)

@@ -1399,9 +1401,13 @@ void sdhci_common_realize(SDHCIState *s, Error **errp)
  
  switch (s->endianness) {

  case DEVICE_LITTLE_ENDIAN:
-s->io_ops = &sdhci_mmio_le_ops;
+/* s->io_ops is little endian by default */
  break;
  case DEVICE_BIG_ENDIAN:
+if (s->io_ops != &sdhci_mmio_le_ops) {
+error_setg(errp, "SD controller doesn't support big endianness");
+return;
+}
  s->io_ops = &sdhci_mmio_be_ops;
  break;
  default:





[PATCH v2] riscv: Generate devicetree only after machine initialization is complete

2023-07-05 Thread Guenter Roeck
If the devicetree is created before machine initialization is complete,
it misses dynamic devices. Specifically, the tpm device is not added
to the devicetree file and is therefore not instantiated in Linux.
Load/create devicetree in virt_machine_done() to solve the problem.

Cc: Daniel Henrique Barboza 
Cc: Alistair Francis 
Cc: Daniel Henrique Barboza 
Fixes: 325b7c4e75 hw/riscv: Enable TPM backends
Signed-off-by: Guenter Roeck 
---
v2: Handle devicetree (load & create) entirely in machine_done function.

 hw/riscv/virt.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ed4c27487e..1c4bd823df 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1248,6 +1248,17 @@ static void virt_machine_done(Notifier *notifier, void 
*data)
 uint64_t kernel_entry = 0;
 BlockBackend *pflash_blk0;
 
+/* load/create device tree */
+if (machine->dtb) {
+machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
+if (!machine->fdt) {
+error_report("load_device_tree() failed");
+exit(1);
+}
+} else {
+create_fdt(s, memmap);
+}
+
 /*
  * Only direct boot kernel is currently supported for KVM VM,
  * so the "-bios" parameter is not supported when KVM is enabled.
@@ -1508,17 +1519,6 @@ static void virt_machine_init(MachineState *machine)
 }
 virt_flash_map(s, system_memory);
 
-/* load/create device tree */
-if (machine->dtb) {
-machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
-if (!machine->fdt) {
-error_report("load_device_tree() failed");
-exit(1);
-}
-} else {
-create_fdt(s, memmap);
-}
-
 s->machine_done.notify = virt_machine_done;
 qemu_add_machine_init_done_notifier(&s->machine_done);
 }
-- 
2.39.2




Re: [PATCH] riscv: Generate devicetree only after machine initialization is complete

2023-07-03 Thread Guenter Roeck

On 7/3/23 12:25, Daniel Henrique Barboza wrote:

On 7/3/23 00:46, Guenter Roeck wrote:

If the devicetree is created before machine initialization is complete,
it misses dynamic devices. Specifically, the tpm device is not added
to the devicetree file and is therefore not instantiated in Linux.
Create devicetree in virt_machine_done() to solve the problem.

Cc: Alistair Francis 
Fixes: 325b7c4e75 hw/riscv: Enable TPM backends
Signed-off-by: Guenter Roeck 
---
  hw/riscv/virt.c | 9 ++---
  1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ed4c27487e..08876284f5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1248,6 +1248,11 @@ static void virt_machine_done(Notifier *notifier, void 
*data)
  uint64_t kernel_entry = 0;
  BlockBackend *pflash_blk0;
+    /* create devicetree if not provided */
+    if (!machine->dtb) {
+    create_fdt(s, memmap);
+    }
+


I suggest moving the entire load/create DT code from virt_machine_init() to
the start of virt_machine_done():

     /* load/create device tree */
     if (machine->dtb) {
     machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
     if (!machine->fdt) {
     error_report("load_device_tree() failed");
     exit(1);
     }
     } else {
     create_fdt(s, memmap);
     }

This way we don't have to look in to 2 different functions to wonder what 
happens
in case machine->dtb is NULL.



I can do that, but I don't know how to test it. Is there a working dtb/machine
combination for riscv which would let me test loading a devicetree file ?

Guenter




Re: [PATCH] riscv: Generate devicetree only after machine initialization is complete

2023-07-03 Thread Guenter Roeck

On 7/3/23 00:46, Philippe Mathieu-Daudé wrote:

On 3/7/23 05:46, Guenter Roeck wrote:

If the devicetree is created before machine initialization is complete,
it misses dynamic devices. Specifically, the tpm device is not added
to the devicetree file and is therefore not instantiated in Linux.
Create devicetree in virt_machine_done() to solve the problem.


This makes sense, but what about the other archs/machines?
Shouldn't we fix this generically?



I had a brief look into various implementations. To me the code looks
all very machine specific. I don't think it can be solved generically
(if other machines are even affected), but then I am not a qemu expert
and may be wrong.

Guenter


Cc: Alistair Francis 
Fixes: 325b7c4e75 hw/riscv: Enable TPM backends
Signed-off-by: Guenter Roeck 
---
  hw/riscv/virt.c | 9 ++---
  1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ed4c27487e..08876284f5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1248,6 +1248,11 @@ static void virt_machine_done(Notifier *notifier, void 
*data)
  uint64_t kernel_entry = 0;
  BlockBackend *pflash_blk0;
+    /* create devicetree if not provided */
+    if (!machine->dtb) {
+    create_fdt(s, memmap);
+    }
+
  /*
   * Only direct boot kernel is currently supported for KVM VM,
   * so the "-bios" parameter is not supported when KVM is enabled.
@@ -1508,15 +1513,13 @@ static void virt_machine_init(MachineState *machine)
  }
  virt_flash_map(s, system_memory);
-    /* load/create device tree */
+    /* load device tree */
  if (machine->dtb) {
  machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
  if (!machine->fdt) {
  error_report("load_device_tree() failed");
  exit(1);
  }
-    } else {
-    create_fdt(s, memmap);
  }
  s->machine_done.notify = virt_machine_done;







[PATCH] riscv: Generate devicetree only after machine initialization is complete

2023-07-02 Thread Guenter Roeck
If the devicetree is created before machine initialization is complete,
it misses dynamic devices. Specifically, the tpm device is not added
to the devicetree file and is therefore not instantiated in Linux.
Create devicetree in virt_machine_done() to solve the problem.

Cc: Alistair Francis 
Fixes: 325b7c4e75 hw/riscv: Enable TPM backends
Signed-off-by: Guenter Roeck 
---
 hw/riscv/virt.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ed4c27487e..08876284f5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1248,6 +1248,11 @@ static void virt_machine_done(Notifier *notifier, void 
*data)
 uint64_t kernel_entry = 0;
 BlockBackend *pflash_blk0;
 
+/* create devicetree if not provided */
+if (!machine->dtb) {
+create_fdt(s, memmap);
+}
+
 /*
  * Only direct boot kernel is currently supported for KVM VM,
  * so the "-bios" parameter is not supported when KVM is enabled.
@@ -1508,15 +1513,13 @@ static void virt_machine_init(MachineState *machine)
 }
 virt_flash_map(s, system_memory);
 
-/* load/create device tree */
+/* load device tree */
 if (machine->dtb) {
 machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
 if (!machine->fdt) {
 error_report("load_device_tree() failed");
 exit(1);
 }
-} else {
-create_fdt(s, memmap);
 }
 
 s->machine_done.notify = virt_machine_done;
-- 
2.39.2




Re: [PATCH v5 01/11] hw: arm: Add bananapi M2-Ultra and allwinner-r40 support

2023-06-24 Thread Guenter Roeck

On 6/24/23 07:23, Guenter Roeck wrote:

On 6/24/23 03:40, Peter Maydell wrote:

On Fri, 23 Jun 2023 at 20:33, Guenter Roeck  wrote:


On 6/23/23 10:44, Peter Maydell wrote:

On Sat, 17 Jun 2023 at 17:29, Guenter Roeck  wrote:


Hi,

On Tue, May 23, 2023 at 06:04:58PM +0800, qianfangui...@163.com wrote:

From: qianfan Zhao 

Allwinner R40 (sun8i) SoC features a Quad-Core Cortex-A7 ARM CPU,
and a Mali400 MP2 GPU from ARM. It's also known as the Allwinner T3
for In-Car Entertainment usage, A40i and A40pro are variants that
differ in applicable temperatures range (industrial and military).

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 


I tried this in mainline linux with the following command.

qemu-system-arm -M bpim2u \
  -kernel arch/arm/boot/zImage -no-reboot \
  -snapshot -drive file=rootfs-armv7a.ext2,format=raw,if=sd \
  -nic user \
  --append "root=/dev/mmcblk0 rootwait console=ttyS0,115200" \
  -dtb arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb \
  -nographic -monitor null -serial stdio

Main problem is that the SD card gets instantiated randomly to
mmc0, mmc1, or mmc2, making it all but impossible to specify a
root file system device. The non-instantiated cards are always
reported as non-removable, including mmc0. Example:

mmc0: Failed to initialize a non-removable card


Do you mean that QEMU randomly connects the SD card to
a different MMC controller each time, or that Linux is
randomly assigning mmc0 to a different MMC controller each
time ?



Good question. Given the workaround (fix ?) I suggested is
in the devicetree file, I would assume it is the latter. I suspect
that Linux assigns drive names based on hardware detection order,
and that this is not deterministic for some reason. It is odd
because I have never experienced that with any other emulation.


Yeah, I don't really understand why it would be non-deterministic.
But it does make it sound like the right thing is for the
device tree file to explicitly say which MMC controller is
which -- presumably you might get unlucky with the timing
on real hardware too.



Agreed, only someone with real hardware would have to confirm
that this is the case.



Actually, the reason is quite simple. In the Linux kernel:

static struct platform_driver sunxi_mmc_driver = {
.driver = {
.name   = "sunxi-mmc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
  ^
.of_match_table = sunxi_mmc_of_match,
.pm = &sunxi_mmc_pm_ops,
},
.probe  = sunxi_mmc_probe,
.remove = sunxi_mmc_remove,
};

All mmc devices instantiate at the same time, thus the
device name association is random. If I drop the probe_type
assignment, it becomes deterministic.

On top of that, Linux does know which drives are removable
from the devicetree file. However, since probe order is
random, the assignment of the one removable drive to device
names is random. Sometimes mmc0 shows up as removable,
sometimes it is mmc1 or mmc2.

So my conclusion is that qemu isn't doing anything wrong,
it is all happening in the Linux kernel.

Thanks, and sorry for the noise.

Guenter




Re: [PATCH v5 01/11] hw: arm: Add bananapi M2-Ultra and allwinner-r40 support

2023-06-24 Thread Guenter Roeck

On 6/24/23 03:40, Peter Maydell wrote:

On Fri, 23 Jun 2023 at 20:33, Guenter Roeck  wrote:


On 6/23/23 10:44, Peter Maydell wrote:

On Sat, 17 Jun 2023 at 17:29, Guenter Roeck  wrote:


Hi,

On Tue, May 23, 2023 at 06:04:58PM +0800, qianfangui...@163.com wrote:

From: qianfan Zhao 

Allwinner R40 (sun8i) SoC features a Quad-Core Cortex-A7 ARM CPU,
and a Mali400 MP2 GPU from ARM. It's also known as the Allwinner T3
for In-Car Entertainment usage, A40i and A40pro are variants that
differ in applicable temperatures range (industrial and military).

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 


I tried this in mainline linux with the following command.

qemu-system-arm -M bpim2u \
  -kernel arch/arm/boot/zImage -no-reboot \
  -snapshot -drive file=rootfs-armv7a.ext2,format=raw,if=sd \
  -nic user \
  --append "root=/dev/mmcblk0 rootwait console=ttyS0,115200" \
  -dtb arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb \
  -nographic -monitor null -serial stdio

Main problem is that the SD card gets instantiated randomly to
mmc0, mmc1, or mmc2, making it all but impossible to specify a
root file system device. The non-instantiated cards are always
reported as non-removable, including mmc0. Example:

mmc0: Failed to initialize a non-removable card


Do you mean that QEMU randomly connects the SD card to
a different MMC controller each time, or that Linux is
randomly assigning mmc0 to a different MMC controller each
time ?



Good question. Given the workaround (fix ?) I suggested is
in the devicetree file, I would assume it is the latter. I suspect
that Linux assigns drive names based on hardware detection order,
and that this is not deterministic for some reason. It is odd
because I have never experienced that with any other emulation.


Yeah, I don't really understand why it would be non-deterministic.
But it does make it sound like the right thing is for the
device tree file to explicitly say which MMC controller is
which -- presumably you might get unlucky with the timing
on real hardware too.



Agreed, only someone with real hardware would have to confirm
that this is the case.


A secondary problem may be that Linux thinks that the first
drive is not removable, even though it is a SD drive. I  think
that is a problem with qemu, but I don't understand the qemu
code well enough to understand why. It seems that the mmc
capability register always has bit 8 set, even for the first
drive, but I don't know where/how that is set and how to
change it. SDHCI has the capareg property, but that isn't
used here (or I don't know how to use/set it).


Yeah, this seems likely to be something we're getting wrong.
I assume on other QEMU boards the SD card appears as
removeable ?



Yes. With some added debugging, sabrelite, and no drive provided
in the qemu command:

mmc0: SDHCI controller on 2198000.mmc [2198000.mmc] using ADMA
# mmc0: No card inserted, removable=1
mmc1: SDHCI controller on 219c000.mmc [219c000.mmc] using ADMA
# mmc1: No card inserted, removable=1

Thanks,
Guenter




Re: [PATCH v5 01/11] hw: arm: Add bananapi M2-Ultra and allwinner-r40 support

2023-06-23 Thread Guenter Roeck

On 6/23/23 10:44, Peter Maydell wrote:

On Sat, 17 Jun 2023 at 17:29, Guenter Roeck  wrote:


Hi,

On Tue, May 23, 2023 at 06:04:58PM +0800, qianfangui...@163.com wrote:

From: qianfan Zhao 

Allwinner R40 (sun8i) SoC features a Quad-Core Cortex-A7 ARM CPU,
and a Mali400 MP2 GPU from ARM. It's also known as the Allwinner T3
for In-Car Entertainment usage, A40i and A40pro are variants that
differ in applicable temperatures range (industrial and military).

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 


I tried this in mainline linux with the following command.

qemu-system-arm -M bpim2u \
 -kernel arch/arm/boot/zImage -no-reboot \
 -snapshot -drive file=rootfs-armv7a.ext2,format=raw,if=sd \
 -nic user \
 --append "root=/dev/mmcblk0 rootwait console=ttyS0,115200" \
 -dtb arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb \
 -nographic -monitor null -serial stdio

Main problem is that the SD card gets instantiated randomly to
mmc0, mmc1, or mmc2, making it all but impossible to specify a
root file system device. The non-instantiated cards are always
reported as non-removable, including mmc0. Example:

mmc0: Failed to initialize a non-removable card


Do you mean that QEMU randomly connects the SD card to
a different MMC controller each time, or that Linux is
randomly assigning mmc0 to a different MMC controller each
time ?



Good question. Given the workaround (fix ?) I suggested is
in the devicetree file, I would assume it is the latter. I suspect
that Linux assigns drive names based on hardware detection order,
and that this is not deterministic for some reason. It is odd
because I have never experienced that with any other emulation.

A secondary problem may be that Linux thinks that the first
drive is not removable, even though it is a SD drive. I  think
that is a problem with qemu, but I don't understand the qemu
code well enough to understand why. It seems that the mmc
capability register always has bit 8 set, even for the first
drive, but I don't know where/how that is set and how to
change it. SDHCI has the capareg property, but that isn't
used here (or I don't know how to use/set it).

Guenter




Re: [PATCH v5 01/11] hw: arm: Add bananapi M2-Ultra and allwinner-r40 support

2023-06-23 Thread Guenter Roeck
On Sun, Jun 18, 2023 at 08:40:28AM +0800, qianfan wrote:
> 
> 在 2023/6/18 0:29, Guenter Roeck 写道:
> > Hi,
> > 
> > On Tue, May 23, 2023 at 06:04:58PM +0800, qianfangui...@163.com wrote:
> > > From: qianfan Zhao 
> > > 
> > > Allwinner R40 (sun8i) SoC features a Quad-Core Cortex-A7 ARM CPU,
> > > and a Mali400 MP2 GPU from ARM. It's also known as the Allwinner T3
> > > for In-Car Entertainment usage, A40i and A40pro are variants that
> > > differ in applicable temperatures range (industrial and military).
> > > 
> > > Signed-off-by: qianfan Zhao 
> > > Reviewed-by: Niek Linnenbank 
> > I tried this in mainline linux with the following command.
> > 
> > qemu-system-arm -M bpim2u \
> > -kernel arch/arm/boot/zImage -no-reboot \
> > -snapshot -drive file=rootfs-armv7a.ext2,format=raw,if=sd \
> > -nic user \
> > --append "root=/dev/mmcblk0 rootwait console=ttyS0,115200" \
> > -dtb arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb \
> > -nographic -monitor null -serial stdio
> > 
> > Main problem is that the SD card gets instantiated randomly to
> > mmc0, mmc1, or mmc2, making it all but impossible to specify a
> > root file system device. The non-instantiated cards are always
> > reported as non-removable, including mmc0. Example:
> > 
> > mmc0: Failed to initialize a non-removable card
> > 
> > Using "-sd " instead of "-drive file=" does not
> > make a difference.
> > 
> > I can fix (work around ?) the problem by adding the following information
> > to the devicetree file.
> > 
> >  aliases {
> >  ethernet0 = &gmac;
> >  serial0 = &uart0;
> > +   mmc0 = &mmc0;
> > +   mmc1 = &mmc1;
> > +   mmc2 = &mmc2;
> >  };
> > 
> > Linux upstream commits fa2d0aa96941 and 2a43322ca7f3 describe the
> > logic behind this change.
> > 
> > Is this a bug in the Linux kernel, or a problem with the qemu emulation ?
> 
> On my work, the linux kenrel doesn't startup ext4 rootfs directly, it start
> 
> a custom ramdisk and we can handle this in ramdisk scripts.
> 

That won't help for automated testing.
I guess that means the answer to my question below is "no".

Thanks,
Guenter

> > Either case, is there a way to specify a qemu command line that doesn't
> > result in random assignments of the provided drive to mmc0/1/2 ?
> > 
> > Thanks,
> > Guenter
> 



Re: [PATCH v4 6/6] hw/riscv: Enable TPM backends

2023-06-20 Thread Guenter Roeck
On Mon, Jun 19, 2023 at 01:32:34PM -0700, Guenter Roeck wrote:
> Hi Alistair,
> 
> On Wed, Apr 20, 2022 at 03:52:48PM +1000, Alistair Francis wrote:
> > From: Alistair Francis 
> > 
> > Imply the TPM sysbus devices. This allows users to add TPM devices to
> > the RISC-V virt board.
> > 
> > This was tested by first creating an emulated TPM device:
> > 
> > swtpm socket --tpm2 -t -d --tpmstate dir=/tmp/tpm \
> > --ctrl type=unixio,path=swtpm-sock
> > 
> > Then launching QEMU with:
> > 
> > -chardev socket,id=chrtpm,path=swtpm-sock \
> > -tpmdev emulator,id=tpm0,chardev=chrtpm \
> > -device tpm-tis-device,tpmdev=tpm0
> > 
> > The TPM device can be seen in the memory tree and the generated device
> > tree.
> > 
> I tried to get this working with qemu 8.0, but I did not have any success.
> I am quite sure I have the above command line correctly, and it does work
> with arm64. Any idea what I might be missing ?
> 

Answering my own question: Nothing. The problem is that the devicetree
is created too early, before the tpm device is instantiated/realized in
qemu. The tpm device therefore does not show up in devicetree, and the
tom device does not instantiate in Linux. The patch below fixes the problem
for me.

Any comments / thoughts ? Is that change acceptable, or should it be
implemented differently ?

Thanks,
Guenter

---
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4e3efbee16..ea259d7ade 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1247,6 +1247,11 @@ static void virt_machine_done(Notifier *notifier, void 
*data)
 uint32_t fdt_load_addr;
 uint64_t kernel_entry;
 
+/* create devicetree if not provided */
+if (!machine->dtb) {
+create_fdt(s, memmap);
+}
+
 /*
  * Only direct boot kernel is currently supported for KVM VM,
  * so the "-bios" parameter is not supported when KVM is enabled.
@@ -1519,15 +1524,13 @@ static void virt_machine_init(MachineState *machine)
 }
 virt_flash_map(s, system_memory);
 
-/* load/create device tree */
+/* load device tree */
 if (machine->dtb) {
 machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
 if (!machine->fdt) {
 error_report("load_device_tree() failed");
 exit(1);
 }
-} else {
-create_fdt(s, memmap);
 }
 
 s->machine_done.notify = virt_machine_done;



Re: [PATCH v4 6/6] hw/riscv: Enable TPM backends

2023-06-19 Thread Guenter Roeck
Hi Alistair,

On Wed, Apr 20, 2022 at 03:52:48PM +1000, Alistair Francis wrote:
> From: Alistair Francis 
> 
> Imply the TPM sysbus devices. This allows users to add TPM devices to
> the RISC-V virt board.
> 
> This was tested by first creating an emulated TPM device:
> 
> swtpm socket --tpm2 -t -d --tpmstate dir=/tmp/tpm \
> --ctrl type=unixio,path=swtpm-sock
> 
> Then launching QEMU with:
> 
> -chardev socket,id=chrtpm,path=swtpm-sock \
> -tpmdev emulator,id=tpm0,chardev=chrtpm \
> -device tpm-tis-device,tpmdev=tpm0
> 
> The TPM device can be seen in the memory tree and the generated device
> tree.
> 
I tried to get this working with qemu 8.0, but I did not have any success.
I am quite sure I have the above command line correctly, and it does work
with arm64. Any idea what I might be missing ?

Thanks,
Guenter

> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/942
> Signed-off-by: Alistair Francis 
> Reviewed-by: Edgar E. Iglesias 
> ---
>  hw/riscv/virt.c  | 4 
>  hw/riscv/Kconfig | 1 +
>  2 files changed, 5 insertions(+)
> 
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 6eed1f4d70..b62fd66a49 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -43,6 +43,7 @@
>  #include "sysemu/device_tree.h"
>  #include "sysemu/sysemu.h"
>  #include "sysemu/kvm.h"
> +#include "sysemu/tpm.h"
>  #include "hw/pci/pci.h"
>  #include "hw/pci-host/gpex.h"
>  #include "hw/display/ramfb.h"
> @@ -1612,6 +1613,9 @@ static void virt_machine_class_init(ObjectClass *oc, 
> void *data)
>  hc->plug = virt_machine_device_plug_cb;
>  
>  machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> +#ifdef CONFIG_TPM
> +machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> +#endif
>  
>  object_class_property_add_bool(oc, "aclint", virt_get_aclint,
> virt_set_aclint);
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index da790f5936..79ff61c464 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -34,6 +34,7 @@ config RISCV_VIRT
>  imply PCI_DEVICES
>  imply VIRTIO_VGA
>  imply TEST_DEVICES
> +imply TPM_TIS_SYSBUS
>  select RISCV_NUMA
>  select GOLDFISH_RTC
>  select MSI_NONBROKEN
> -- 
> 2.35.1
> 
> 



Re: [PATCH v5 01/11] hw: arm: Add bananapi M2-Ultra and allwinner-r40 support

2023-06-17 Thread Guenter Roeck
Hi,

On Tue, May 23, 2023 at 06:04:58PM +0800, qianfangui...@163.com wrote:
> From: qianfan Zhao 
> 
> Allwinner R40 (sun8i) SoC features a Quad-Core Cortex-A7 ARM CPU,
> and a Mali400 MP2 GPU from ARM. It's also known as the Allwinner T3
> for In-Car Entertainment usage, A40i and A40pro are variants that
> differ in applicable temperatures range (industrial and military).
> 
> Signed-off-by: qianfan Zhao 
> Reviewed-by: Niek Linnenbank 

I tried this in mainline linux with the following command.

qemu-system-arm -M bpim2u \
-kernel arch/arm/boot/zImage -no-reboot \
-snapshot -drive file=rootfs-armv7a.ext2,format=raw,if=sd \
-nic user \
--append "root=/dev/mmcblk0 rootwait console=ttyS0,115200" \
-dtb arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb \
-nographic -monitor null -serial stdio

Main problem is that the SD card gets instantiated randomly to
mmc0, mmc1, or mmc2, making it all but impossible to specify a
root file system device. The non-instantiated cards are always
reported as non-removable, including mmc0. Example:

mmc0: Failed to initialize a non-removable card

Using "-sd " instead of "-drive file=" does not
make a difference.

I can fix (work around ?) the problem by adding the following information
to the devicetree file.

aliases {
ethernet0 = &gmac;
serial0 = &uart0;
+   mmc0 = &mmc0;
+   mmc1 = &mmc1;
+   mmc2 = &mmc2;
};

Linux upstream commits fa2d0aa96941 and 2a43322ca7f3 describe the
logic behind this change.

Is this a bug in the Linux kernel, or a problem with the qemu emulation ?
Either case, is there a way to specify a qemu command line that doesn't
result in random assignments of the provided drive to mmc0/1/2 ?

Thanks,
Guenter



Re: [PATCH 2/2] hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels

2023-06-06 Thread Guenter Roeck
On Tue, Jun 06, 2023 at 11:46:09AM +0100, Peter Maydell wrote:
> QEMU allows qemu_irq lines to transfer arbitrary integers.  However
> the convention is that for a simple IRQ line the values transferred
> are always 0 and 1.  The A10 SD controller device instead assumes a
> 0-vs-non-0 convention, which happens to work with the interrupt
> controller it is wired up to.
> 
> Coerce the value to boolean to follow our usual convention.
> 
> Signed-off-by: Peter Maydell 

Tested-by: Guenter Roeck 

> ---
>  hw/sd/allwinner-sdhost.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
> index 92a0f42708d..62df8f3d396 100644
> --- a/hw/sd/allwinner-sdhost.c
> +++ b/hw/sd/allwinner-sdhost.c
> @@ -191,7 +191,7 @@ static void allwinner_sdhost_update_irq(AwSdHostState *s)
>  }
>  
>  trace_allwinner_sdhost_update_irq(irq);
> -qemu_set_irq(s->irq, irq);
> +qemu_set_irq(s->irq, !!irq);
>  }
>  
>  static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
> -- 
> 2.34.1
> 



Re: [PATCH 1/2] hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1

2023-06-06 Thread Guenter Roeck
On Tue, Jun 06, 2023 at 11:46:08AM +0100, Peter Maydell wrote:
> In commit 2c5fa0778c3b430 we fixed an endianness bug in the Allwinner
> A10 PIC model; however in the process we introduced a regression.
> This is because the old code was robust against the incoming 'level'
> argument being something other than 0 or 1, whereas the new code was
> not.
> 
> In particular, the allwinner-sdhost code treats its IRQ line
> as 0-vs-non-0 rather than 0-vs-1, so when the SD controller
> set its IRQ line for any reason other than transmit the
> interrupt controller would ignore it. The observed effect
> was a guest timeout when rebooting the guest kernel.
> 
> Handle level values other than 0 or 1, to restore the old
> behaviour.
> 
> Fixes: 2c5fa0778c3b430 ("hw/intc/allwinner-a10-pic: Don't use 
> set_bit()/clear_bit()")
> Cc: qemu-sta...@nongnu.org
> Signed-off-by: Peter Maydell 

Tested-by: Guenter Roeck 

Tested on top of 8.0.2, both this patch alone as well as this
patch plus the second patch in the series.

Guenter

> ---
>  hw/intc/allwinner-a10-pic.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
> index 4875e68ba6a..d0bf8d545ba 100644
> --- a/hw/intc/allwinner-a10-pic.c
> +++ b/hw/intc/allwinner-a10-pic.c
> @@ -51,7 +51,7 @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int 
> level)
>  AwA10PICState *s = opaque;
>  uint32_t *pending_reg = &s->irq_pending[irq / 32];
>  
> -*pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
> +*pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
>  aw_a10_pic_update(s);
>  }
>  
> -- 
> 2.34.1
> 



Re: [PULL 31/35] hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()

2023-06-05 Thread Guenter Roeck

On 6/5/23 02:40, Peter Maydell wrote:

On Sat, 3 Jun 2023 at 19:06, Guenter Roeck  wrote:


On 6/3/23 10:46, Michael Tokarev wrote:

03.06.2023 18:03, Guenter Roeck wrote:

Hi,

On Tue, May 02, 2023 at 01:14:55PM +0100, Peter Maydell wrote:

The Allwinner PIC model uses set_bit() and clear_bit() to update the
values in its irq_pending[] array when an interrupt arrives.  However
it is using these functions wrongly: they work on an array of type
'long', and it is passing an array of type 'uint32_t'.  Because the
code manually figures out the right array element, this works on
little-endian hosts and on 32-bit big-endian hosts, where bits 0..31
in a 'long' are in the same place as they are in a 'uint32_t'.
However it breaks on 64-bit big-endian hosts.

Remove the use of set_bit() and clear_bit() in favour of using
deposit32() on the array element.  This fixes a bug where on
big-endian 64-bit hosts the guest kernel would hang early on in
bootup.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Peter Maydell 
Reviewed-by: Thomas Huth 
Reviewed-by: Philippe Mathieu-Daudé 
Message-id: 20230424152833.1334136-1-peter.mayd...@linaro.org


In v8.0.2, the cubieboard emulation running Linux crashes during reboot
with a hung task error. Tested with mainline Linux (v6.4-rc4-78-g929ed21dfdb6)
and with v5.15.114. Host is AMD Ryzen 5900X.

Requesting system reboot
[   61.927460] INFO: task kworker/0:1:13 blocked for more than 30 seconds.
[   61.927896]   Not tainted 5.15.115-rc2-00038-g31e35d9f1b8d #1
[   61.928144] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this 
message.
[   61.928419] task:kworker/0:1 state:D stack:0 pid:   13 ppid: 2 
flags:0x
[   61.928972] Workqueue: events_freezable mmc_rescan
[   61.929739] [] (__schedule) from [] (schedule+0x80/0x15c)
[   61.930041] [] (schedule) from [] 
(schedule_timeout+0xd4/0x12c)
[   61.930270] [] (schedule_timeout) from [] 
(do_wait_for_common+0xa0/0x154)
[   61.930523] [] (do_wait_for_common) from [] 
(wait_for_completion+0x40/0x4c)
[   61.930764] [] (wait_for_completion) from [] 
(mmc_wait_for_req_done+0x6c/0x90)
[   61.931012] [] (mmc_wait_for_req_done) from [] 
(mmc_wait_for_cmd+0x70/0xa8)
[   61.931252] [] (mmc_wait_for_cmd) from [] 
(sdio_reset+0x58/0x124)
[   61.931478] [] (sdio_reset) from [] 
(mmc_rescan+0x294/0x30c)
[   61.931692] [] (mmc_rescan) from [] 
(process_one_work+0x28c/0x720)
[   61.931924] [] (process_one_work) from [] 
(worker_thread+0x64/0x53c)
[   61.932153] [] (worker_thread) from [] 
(kthread+0x15c/0x180)
[   61.932365] [] (kthread) from [] 
(ret_from_fork+0x14/0x38)
[   61.932628] Exception stack(0xc31ddfb0 to 0xc31ddff8)

This was not seen with v8.0.0. Bisect points to this patch. Reverting it
fixes the problem.


Does this happen on master too, or just on stable-8.0 ?



It does. Tested with v8.0.0-1542-g848a6caa88.

Here is my command line in case you want to give it a try:

qemu-system-arm -M cubieboard -kernel arch/arm/boot/zImage -no-reboot \
  -initrd rootfs-armv5.cpio -m 512 \
  --append "panic=-1 rdinit=/sbin/init 
earlycon=uart8250,mmio32,0x1c28000,115200n8 console=ttyS0" \
  -dtb arch/arm/boot/dts/sun4i-a10-cubieboard.dtb -nographic \
  -monitor null -serial stdio

initrd is 
https://github.com/groeck/linux-build-test/blob/master/rootfs/arm-v7/rootfs-armv5.cpio.gz

This is with multi_v7_defconfig with some debug options added. If necessary
I'll be happy to provide the exact configuration.


If you can provide a link to the zImage and the dtb to reproduce
as well, that would be helpful.



Please see http://server.roeck-us.net/qemu/arm-v7/.

There are also compiled versions of qemu v8.0.0 and v8.0.2 as well as scripts
to run the test. Note that the initrd will auto-reboot. The cubieboard emulation
does not support board reset, so the test will normally end with

Requesting system reboot
[   22.020700] reboot: Restarting system

In the failure case, the second line is not seen, and there will be a hung task
crash about 30 seconds after the reboot request.

Requesting system reboot
[   61.960821] INFO: task kworker/0:2:67 blocked for more than 30 seconds.
[   61.961406]   Tainted: G N 6.4.0-rc5 #1

Hope this helps,
Guenter




Re: [PULL 31/35] hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()

2023-06-03 Thread Guenter Roeck

On 6/3/23 10:46, Michael Tokarev wrote:

03.06.2023 18:03, Guenter Roeck wrote:

Hi,

On Tue, May 02, 2023 at 01:14:55PM +0100, Peter Maydell wrote:

The Allwinner PIC model uses set_bit() and clear_bit() to update the
values in its irq_pending[] array when an interrupt arrives.  However
it is using these functions wrongly: they work on an array of type
'long', and it is passing an array of type 'uint32_t'.  Because the
code manually figures out the right array element, this works on
little-endian hosts and on 32-bit big-endian hosts, where bits 0..31
in a 'long' are in the same place as they are in a 'uint32_t'.
However it breaks on 64-bit big-endian hosts.

Remove the use of set_bit() and clear_bit() in favour of using
deposit32() on the array element.  This fixes a bug where on
big-endian 64-bit hosts the guest kernel would hang early on in
bootup.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Peter Maydell 
Reviewed-by: Thomas Huth 
Reviewed-by: Philippe Mathieu-Daudé 
Message-id: 20230424152833.1334136-1-peter.mayd...@linaro.org


In v8.0.2, the cubieboard emulation running Linux crashes during reboot
with a hung task error. Tested with mainline Linux (v6.4-rc4-78-g929ed21dfdb6)
and with v5.15.114. Host is AMD Ryzen 5900X.

Requesting system reboot
[   61.927460] INFO: task kworker/0:1:13 blocked for more than 30 seconds.
[   61.927896]   Not tainted 5.15.115-rc2-00038-g31e35d9f1b8d #1
[   61.928144] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this 
message.
[   61.928419] task:kworker/0:1 state:D stack:    0 pid:   13 ppid: 2 
flags:0x
[   61.928972] Workqueue: events_freezable mmc_rescan
[   61.929739] [] (__schedule) from [] (schedule+0x80/0x15c)
[   61.930041] [] (schedule) from [] 
(schedule_timeout+0xd4/0x12c)
[   61.930270] [] (schedule_timeout) from [] 
(do_wait_for_common+0xa0/0x154)
[   61.930523] [] (do_wait_for_common) from [] 
(wait_for_completion+0x40/0x4c)
[   61.930764] [] (wait_for_completion) from [] 
(mmc_wait_for_req_done+0x6c/0x90)
[   61.931012] [] (mmc_wait_for_req_done) from [] 
(mmc_wait_for_cmd+0x70/0xa8)
[   61.931252] [] (mmc_wait_for_cmd) from [] 
(sdio_reset+0x58/0x124)
[   61.931478] [] (sdio_reset) from [] 
(mmc_rescan+0x294/0x30c)
[   61.931692] [] (mmc_rescan) from [] 
(process_one_work+0x28c/0x720)
[   61.931924] [] (process_one_work) from [] 
(worker_thread+0x64/0x53c)
[   61.932153] [] (worker_thread) from [] 
(kthread+0x15c/0x180)
[   61.932365] [] (kthread) from [] 
(ret_from_fork+0x14/0x38)
[   61.932628] Exception stack(0xc31ddfb0 to 0xc31ddff8)

This was not seen with v8.0.0. Bisect points to this patch. Reverting it
fixes the problem.


Does this happen on master too, or just on stable-8.0 ?



It does. Tested with v8.0.0-1542-g848a6caa88.

Here is my command line in case you want to give it a try:

qemu-system-arm -M cubieboard -kernel arch/arm/boot/zImage -no-reboot \
-initrd rootfs-armv5.cpio -m 512 \
--append "panic=-1 rdinit=/sbin/init earlycon=uart8250,mmio32,0x1c28000,115200n8 
console=ttyS0" \
-dtb arch/arm/boot/dts/sun4i-a10-cubieboard.dtb -nographic \
-monitor null -serial stdio

initrd is 
https://github.com/groeck/linux-build-test/blob/master/rootfs/arm-v7/rootfs-armv5.cpio.gz

This is with multi_v7_defconfig with some debug options added. If necessary
I'll be happy to provide the exact configuration.

Guenter




Re: [PULL 31/35] hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()

2023-06-03 Thread Guenter Roeck
Hi,

On Tue, May 02, 2023 at 01:14:55PM +0100, Peter Maydell wrote:
> The Allwinner PIC model uses set_bit() and clear_bit() to update the
> values in its irq_pending[] array when an interrupt arrives.  However
> it is using these functions wrongly: they work on an array of type
> 'long', and it is passing an array of type 'uint32_t'.  Because the
> code manually figures out the right array element, this works on
> little-endian hosts and on 32-bit big-endian hosts, where bits 0..31
> in a 'long' are in the same place as they are in a 'uint32_t'.
> However it breaks on 64-bit big-endian hosts.
> 
> Remove the use of set_bit() and clear_bit() in favour of using
> deposit32() on the array element.  This fixes a bug where on
> big-endian 64-bit hosts the guest kernel would hang early on in
> bootup.
> 
> Cc: qemu-sta...@nongnu.org
> Signed-off-by: Peter Maydell 
> Reviewed-by: Thomas Huth 
> Reviewed-by: Philippe Mathieu-Daudé 
> Message-id: 20230424152833.1334136-1-peter.mayd...@linaro.org

In v8.0.2, the cubieboard emulation running Linux crashes during reboot
with a hung task error. Tested with mainline Linux (v6.4-rc4-78-g929ed21dfdb6)
and with v5.15.114. Host is AMD Ryzen 5900X.

Requesting system reboot
[   61.927460] INFO: task kworker/0:1:13 blocked for more than 30 seconds.
[   61.927896]   Not tainted 5.15.115-rc2-00038-g31e35d9f1b8d #1
[   61.928144] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this 
message.
[   61.928419] task:kworker/0:1 state:D stack:0 pid:   13 ppid: 2 
flags:0x
[   61.928972] Workqueue: events_freezable mmc_rescan
[   61.929739] [] (__schedule) from [] (schedule+0x80/0x15c)
[   61.930041] [] (schedule) from [] 
(schedule_timeout+0xd4/0x12c)
[   61.930270] [] (schedule_timeout) from [] 
(do_wait_for_common+0xa0/0x154)
[   61.930523] [] (do_wait_for_common) from [] 
(wait_for_completion+0x40/0x4c)
[   61.930764] [] (wait_for_completion) from [] 
(mmc_wait_for_req_done+0x6c/0x90)
[   61.931012] [] (mmc_wait_for_req_done) from [] 
(mmc_wait_for_cmd+0x70/0xa8)
[   61.931252] [] (mmc_wait_for_cmd) from [] 
(sdio_reset+0x58/0x124)
[   61.931478] [] (sdio_reset) from [] 
(mmc_rescan+0x294/0x30c)
[   61.931692] [] (mmc_rescan) from [] 
(process_one_work+0x28c/0x720)
[   61.931924] [] (process_one_work) from [] 
(worker_thread+0x64/0x53c)
[   61.932153] [] (worker_thread) from [] 
(kthread+0x15c/0x180)
[   61.932365] [] (kthread) from [] 
(ret_from_fork+0x14/0x38)
[   61.932628] Exception stack(0xc31ddfb0 to 0xc31ddff8)

This was not seen with v8.0.0. Bisect points to this patch. Reverting it
fixes the problem.

Bisect log is attached.

Guenter

---
# bad: [f7f686b61cf7ee142c9264d2e04ac2c6a96d37f8] Update version for 8.0.2 
release
# good: [c1eb2ddf0f8075faddc5f7c3d39feae3e8e9d6b4] Update version for v8.0.0 
release
git bisect start 'v8.0.2' 'v8.0.0'
# bad: [21b54a683d14c0c6f9af35536d9059c60b7449ca] s390x/pv: Fix spurious 
warning with asynchronous teardown
git bisect bad 21b54a683d14c0c6f9af35536d9059c60b7449ca
# bad: [4dc5df865c482c6e8894964c7f300fa556c3b78e] softfloat: Fix the incorrect 
computation in float32_exp2
git bisect bad 4dc5df865c482c6e8894964c7f300fa556c3b78e
# good: [f0c5a780292bd405bbce818b63757313cafcf262] target/arm: Initialize debug 
capabilities only once
git bisect good f0c5a780292bd405bbce818b63757313cafcf262
# bad: [af08c70ef5204fedb2b974fbecaf65e1b6cc0a2f] hw/intc/allwinner-a10-pic: 
Don't use set_bit()/clear_bit()
git bisect bad af08c70ef5204fedb2b974fbecaf65e1b6cc0a2f
# good: [168f193c5be54fc9a6d725dbb9974c0d2815792a] hw/arm/boot: Make 
write_bootloader() public as arm_write_bootloader()
git bisect good 168f193c5be54fc9a6d725dbb9974c0d2815792a
# good: [975f12aa528d6cab5cc41efebaf05d7eb7296d94] hw/arm/raspi: Use 
arm_write_bootloader() to write boot code
git bisect good 975f12aa528d6cab5cc41efebaf05d7eb7296d94
# first bad commit: [af08c70ef5204fedb2b974fbecaf65e1b6cc0a2f] 
hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()



Re: [PATCH v6 2/3] hw/sd/sdhci: Support big endian SD host controller interfaces

2023-04-29 Thread Guenter Roeck
On Sat, Apr 29, 2023 at 01:46:26PM -0700, Guenter Roeck wrote:
> Hi,
> 
> On Tue, Nov 01, 2022 at 11:29:33PM +0100, Philippe Mathieu-Daudé wrote:
> > Some SDHCI IP can be synthetized in various endianness:
> > https://github.com/u-boot/u-boot/blob/v2021.04/doc/README.fsl-esdhc
> > 
> >  - CONFIG_SYS_FSL_ESDHC_BE
> > 
> >ESDHC IP is in big-endian mode. Accessing ESDHC registers can be
> >determined by ESDHC IP's endian mode or processor's endian mode.
> > 
> > Our current implementation is little-endian. In order to support
> > big endianness:
> > 
> > - Rename current MemoryRegionOps as sdhci_mmio_le_ops ('le')
> > - Add an 'endianness' property to SDHCIState (default little endian)
> > - Set the 'io_ops' field in realize() after checking the property
> > - Add the sdhci_mmio_be_ops (big-endian) MemoryRegionOps.
> > 
> > Signed-off-by: Philippe Mathieu-Daudé 
> 
> With this patch in place (in qemu v8.0), I can no longer boot linux
> from SD card with sabrelite, mcimx6ul-evk, and mcimx7d-sabre emulations.
> I get the following persistent errors.
> 
> [   12.210101] sdhci-esdhc-imx 2194000.mmc: 
> esdhc_wait_for_card_clock_gate_off: card clock still not gate off in 100us!.
> [   12.213222] sdhci-esdhc-imx 2194000.mmc: 
> esdhc_wait_for_card_clock_gate_off: card clock still not gate off in 100us!.
> [   12.215072] sdhci-esdhc-imx 2194000.mmc: 
> esdhc_wait_for_card_clock_gate_off: card clock still not gate off in 100us!.
> [   12.218766] sdhci-esdhc-imx 219.mmc: 
> esdhc_wait_for_card_clock_gate_off: card clock still not gate off in 100us!.
> [   12.220441] sdhci-esdhc-imx 219.mmc: 
> esdhc_wait_for_card_clock_gate_off: card clock still not gate off in 100us!.
> [   12.221542] sdhci-esdhc-imx 219.mmc: 
> esdhc_wait_for_card_clock_gate_off: card clock still not gate off in 100us!.
> [   12.241544] sdhci-esdhc-imx 219.mmc: 
> esdhc_wait_for_card_clock_gate_off: card clock still not gate off in 100us!.
> [   12.242608] sdhci-esdhc-imx 219.mmc: card clock still not stable in 
> 100us!.
> 
> The emulations start to work again after reverting this patch.
> 
Cause explained below.

> Guenter
> 
> > ---
> >  hw/sd/sdhci-internal.h |  1 +
> >  hw/sd/sdhci.c  | 32 +---
> >  include/hw/sd/sdhci.h  |  1 +
> >  3 files changed, 31 insertions(+), 3 deletions(-)
> > 
> > diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> > index 964570f8e8..5f3765f12d 100644
> > --- a/hw/sd/sdhci-internal.h
> > +++ b/hw/sd/sdhci-internal.h
> > @@ -308,6 +308,7 @@ extern const VMStateDescription sdhci_vmstate;
> >  #define SDHC_CAPAB_REG_DEFAULT 0x057834b4
> >  
> >  #define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \
> > +DEFINE_PROP_UINT8("endianness", _state, endianness, 
> > DEVICE_LITTLE_ENDIAN), \
> >  DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \
> >  DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \
> >  DEFINE_PROP_UINT8("vendor", _state, vendor, SDHCI_VENDOR_NONE), \
> > diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> > index 22c758ad91..289baa879e 100644
> > --- a/hw/sd/sdhci.c
> > +++ b/hw/sd/sdhci.c
> > @@ -1329,7 +1329,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t 
> > val, unsigned size)
> > value >> shift, value >> shift);
> >  }
> >  
> > -static const MemoryRegionOps sdhci_mmio_ops = {
> > +static const MemoryRegionOps sdhci_mmio_le_ops = {
> >  .read = sdhci_read,
> >  .write = sdhci_write,
> >  .impl = {
> > @@ -1344,6 +1344,21 @@ static const MemoryRegionOps sdhci_mmio_ops = {
> >  .endianness = DEVICE_LITTLE_ENDIAN,
> >  };
> >  
> > +static const MemoryRegionOps sdhci_mmio_be_ops = {
> > +.read = sdhci_read,
> > +.write = sdhci_write,
> > +.impl = {
> > +.min_access_size = 4,
> > +.max_access_size = 4,
> > +},
> > +.valid = {
> > +.min_access_size = 1,
> > +.max_access_size = 4,
> > +.unaligned = false
> > +},
> > +.endianness = DEVICE_BIG_ENDIAN,
> > +};
> > +
> >  static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
> >  {
> >  ERRP_GUARD();
> > @@ -1371,8 +1386,6 @@ void sdhci_initfn(SDHCIState *s)
> >  
> >  s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
> > sdhci_raise_insertion_irq, s);
> >  s->

Re: [PATCH v6 2/3] hw/sd/sdhci: Support big endian SD host controller interfaces

2023-04-29 Thread Guenter Roeck
Hi,

On Tue, Nov 01, 2022 at 11:29:33PM +0100, Philippe Mathieu-Daudé wrote:
> Some SDHCI IP can be synthetized in various endianness:
> https://github.com/u-boot/u-boot/blob/v2021.04/doc/README.fsl-esdhc
> 
>  - CONFIG_SYS_FSL_ESDHC_BE
> 
>ESDHC IP is in big-endian mode. Accessing ESDHC registers can be
>determined by ESDHC IP's endian mode or processor's endian mode.
> 
> Our current implementation is little-endian. In order to support
> big endianness:
> 
> - Rename current MemoryRegionOps as sdhci_mmio_le_ops ('le')
> - Add an 'endianness' property to SDHCIState (default little endian)
> - Set the 'io_ops' field in realize() after checking the property
> - Add the sdhci_mmio_be_ops (big-endian) MemoryRegionOps.
> 
> Signed-off-by: Philippe Mathieu-Daudé 

With this patch in place (in qemu v8.0), I can no longer boot linux
from SD card with sabrelite, mcimx6ul-evk, and mcimx7d-sabre emulations.
I get the following persistent errors.

[   12.210101] sdhci-esdhc-imx 2194000.mmc: esdhc_wait_for_card_clock_gate_off: 
card clock still not gate off in 100us!.
[   12.213222] sdhci-esdhc-imx 2194000.mmc: esdhc_wait_for_card_clock_gate_off: 
card clock still not gate off in 100us!.
[   12.215072] sdhci-esdhc-imx 2194000.mmc: esdhc_wait_for_card_clock_gate_off: 
card clock still not gate off in 100us!.
[   12.218766] sdhci-esdhc-imx 219.mmc: esdhc_wait_for_card_clock_gate_off: 
card clock still not gate off in 100us!.
[   12.220441] sdhci-esdhc-imx 219.mmc: esdhc_wait_for_card_clock_gate_off: 
card clock still not gate off in 100us!.
[   12.221542] sdhci-esdhc-imx 219.mmc: esdhc_wait_for_card_clock_gate_off: 
card clock still not gate off in 100us!.
[   12.241544] sdhci-esdhc-imx 219.mmc: esdhc_wait_for_card_clock_gate_off: 
card clock still not gate off in 100us!.
[   12.242608] sdhci-esdhc-imx 219.mmc: card clock still not stable in 
100us!.

The emulations start to work again after reverting this patch.

Guenter

> ---
>  hw/sd/sdhci-internal.h |  1 +
>  hw/sd/sdhci.c  | 32 +---
>  include/hw/sd/sdhci.h  |  1 +
>  3 files changed, 31 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index 964570f8e8..5f3765f12d 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -308,6 +308,7 @@ extern const VMStateDescription sdhci_vmstate;
>  #define SDHC_CAPAB_REG_DEFAULT 0x057834b4
>  
>  #define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \
> +DEFINE_PROP_UINT8("endianness", _state, endianness, 
> DEVICE_LITTLE_ENDIAN), \
>  DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \
>  DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \
>  DEFINE_PROP_UINT8("vendor", _state, vendor, SDHCI_VENDOR_NONE), \
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 22c758ad91..289baa879e 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -1329,7 +1329,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
> unsigned size)
> value >> shift, value >> shift);
>  }
>  
> -static const MemoryRegionOps sdhci_mmio_ops = {
> +static const MemoryRegionOps sdhci_mmio_le_ops = {
>  .read = sdhci_read,
>  .write = sdhci_write,
>  .impl = {
> @@ -1344,6 +1344,21 @@ static const MemoryRegionOps sdhci_mmio_ops = {
>  .endianness = DEVICE_LITTLE_ENDIAN,
>  };
>  
> +static const MemoryRegionOps sdhci_mmio_be_ops = {
> +.read = sdhci_read,
> +.write = sdhci_write,
> +.impl = {
> +.min_access_size = 4,
> +.max_access_size = 4,
> +},
> +.valid = {
> +.min_access_size = 1,
> +.max_access_size = 4,
> +.unaligned = false
> +},
> +.endianness = DEVICE_BIG_ENDIAN,
> +};
> +
>  static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
>  {
>  ERRP_GUARD();
> @@ -1371,8 +1386,6 @@ void sdhci_initfn(SDHCIState *s)
>  
>  s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
> sdhci_raise_insertion_irq, s);
>  s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
> sdhci_data_transfer, s);
> -
> -s->io_ops = &sdhci_mmio_ops;
>  }
>  
>  void sdhci_uninitfn(SDHCIState *s)
> @@ -1388,10 +1401,23 @@ void sdhci_common_realize(SDHCIState *s, Error **errp)
>  {
>  ERRP_GUARD();
>  
> +switch (s->endianness) {
> +case DEVICE_LITTLE_ENDIAN:
> +s->io_ops = &sdhci_mmio_le_ops;
> +break;
> +case DEVICE_BIG_ENDIAN:
> +s->io_ops = &sdhci_mmio_be_ops;
> +break;
> +default:
> +error_setg(errp, "Incorrect endianness");
> +return;
> +}
> +
>  sdhci_init_readonly_registers(s, errp);
>  if (*errp) {
>  return;
>  }
> +
>  s->buf_maxsz = sdhci_get_fifolen(s);
>  s->fifo_buffer = g_malloc0(s->buf_maxsz);
>  
> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
> index 01a64c5442..a989fca3b2 100644
> --- a/include/hw/sd/sdhci.h
> +++ b/include/hw/sd/sdhci.h
> @@ -96,

  1   2   3   4   5   6   >