diff mbox series

[v1,3/3] xen/common: move device initialization code to common code

Message ID 128d17f3625807a26875b7a419fb56610424b18c.1726048521.git.oleksii.kurochko@gmail.com (mailing list archive)
State Superseded
Headers show
Series Move {acpi_}device_init() and device_get_class() to common code | expand

Commit Message

Oleksii Kurochko Sept. 11, 2024, 10:04 a.m. UTC
Remove the device initialization code from `xen/arch/arm/device.c`
and move it to the common code to avoid duplication and make it accessible
for both ARM and other architectures.
device_get_class(), device_init(), _sdevice[] and _edevice[] are wrapped by
"#ifdef CONFIG_HAS_DEVICE_TREE" for the case if an arch doesn't support
device tree.

Remove unnecessary inclusions of <asm/device.h> and <xen/init.h> from
`xen/arch/arm/device.c` as no code in the file relies on these headers.
Fix the inclusion order by moving <asm/setup.h> after <xen/*> headers to
resolve a compilation error:
   ./include/public/xen.h:968:35: error: unknown type name 'uint64_t'
    968 | __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
        |                                   ^~~~~~~~
   ./include/public/arch-arm.h:191:21: note: in definition of macro '___DEFINE_XEN_GUEST_HANDLE'
   191 |     typedef union { type *p; uint64_aligned_t q; }              \
       |                     ^~~~
   ./include/public/xen.h:968:1: note: in expansion of macro '__DEFINE_XEN_GUEST_HANDLE'
   968 | __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
because <asm/setup.h> includes <public/version.h>, which in turn includes
"xen.h", which requires <xen/types.h> to be processed correctly.
Additionally, add <xen/device_tree.h> to `device.c` as functions from this
header are used within the file.

Additionally, the Makefile is updated to compile `device.o` conditionally
based on whether `CONFIG_HAS_DEVICE_TREE` or `CONFIG_HAS_ACPI` is enabled,
ensuring the correct device initialization code is included as needed.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
 xen/arch/arm/device.c | 71 ++-----------------------------------
 xen/common/Makefile   |  1 +
 xen/common/device.c   | 82 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 69 deletions(-)
 create mode 100644 xen/common/device.c

Comments

Jan Beulich Sept. 12, 2024, 3:28 p.m. UTC | #1
On 11.09.2024 12:04, Oleksii Kurochko wrote:
> --- a/xen/common/Makefile
> +++ b/xen/common/Makefile
> @@ -6,6 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
>  obj-$(CONFIG_CORE_PARKING) += core_parking.o
>  obj-y += cpu.o
>  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
> +obj-$(call or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) += device.o

I can't spot any HAS_ACPI in the tree. And if this was switched to CONFIG_ACPI
I'd further ask why the file needs building on x86.

Also I think I'd prefer to avoid the of the "or" macro here:

obj-$(CONFIG_ACPI) += device.o
obj-$(CONFIG_HAS_DEVICE_TREE) += device.o

ought to be quite fine. There's de-duplication somewhere for what $(obj-y) lists.

> --- /dev/null
> +++ b/xen/common/device.c
> @@ -0,0 +1,82 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Based on the code from:
> + *   xen/arch/arm/device.c
> + */
> +
> +#include <xen/bug.h>
> +#include <xen/device_tree.h>
> +#include <xen/errno.h>
> +#include <xen/init.h>
> +
> +#include <asm-generic/device.h>
> +
> +#ifdef CONFIG_ACPI
> +extern const struct acpi_device_desc _asdevice[], _aedevice[];

Why does this live separately here, rather than ...

> +#endif
> +
> +#ifdef CONFIG_HAS_DEVICE_TREE
> +
> +extern const struct device_desc _sdevice[], _edevice[];

... like this ...

> +int __init device_init(struct dt_device_node *dev, enum device_class class,
> +                       const void *data)
> +{
> +    const struct device_desc *desc;
> +
> +    ASSERT(dev != NULL);
> +
> +    if ( !dt_device_is_available(dev) || dt_device_for_passthrough(dev) )
> +        return  -ENODEV;
> +
> +    for ( desc = _sdevice; desc != _edevice; desc++ )
> +    {
> +        if ( desc->class != class )
> +            continue;
> +
> +        if ( dt_match_node(desc->dt_match, dev) )
> +        {
> +            ASSERT(desc->init != NULL);
> +
> +            return desc->init(dev, data);
> +        }
> +    }
> +
> +    return -EBADF;
> +}
> +
> +enum device_class device_get_class(const struct dt_device_node *dev)
> +{
> +    const struct device_desc *desc;
> +
> +    ASSERT(dev != NULL);
> +
> +    for ( desc = _sdevice; desc != _edevice; desc++ )
> +    {
> +        if ( dt_match_node(desc->dt_match, dev) )
> +            return desc->class;
> +    }
> +
> +    return DEVICE_UNKNOWN;
> +}
> +
> +#endif
> +
> +#ifdef CONFIG_ACPI

... in the section where it's needed? Leaving just one #ifdef for ACPI.

Jan
Oleksii Kurochko Sept. 13, 2024, 2:35 p.m. UTC | #2
On Thu, 2024-09-12 at 17:28 +0200, Jan Beulich wrote:
> On 11.09.2024 12:04, Oleksii Kurochko wrote:
> > --- a/xen/common/Makefile
> > +++ b/xen/common/Makefile
> > @@ -6,6 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
> >  obj-$(CONFIG_CORE_PARKING) += core_parking.o
> >  obj-y += cpu.o
> >  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
> > +obj-$(call or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) +=
> > device.o
> 
> I can't spot any HAS_ACPI in the tree. And if this was switched to
> CONFIG_ACPI
> I'd further ask why the file needs building on x86.
Oh, there is no need for building this on x86. With what you suggested
here ...

> 
> Also I think I'd prefer to avoid the of the "or" macro here:
> 
> obj-$(CONFIG_ACPI) += device.o
> obj-$(CONFIG_HAS_DEVICE_TREE) += device.o
... IIUC it will fix the issue with building this file for x86 as
CONFIG_ACPI depends on (ARM_64 && ARM_EFI).

> 
> ought to be quite fine. There's de-duplication somewhere for what
> $(obj-y) lists.
> 
> > --- /dev/null
> > +++ b/xen/common/device.c
> > @@ -0,0 +1,82 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Based on the code from:
> > + *   xen/arch/arm/device.c
> > + */
> > +
> > +#include <xen/bug.h>
> > +#include <xen/device_tree.h>
> > +#include <xen/errno.h>
> > +#include <xen/init.h>
> > +
> > +#include <asm-generic/device.h>
> > +
> > +#ifdef CONFIG_ACPI
> > +extern const struct acpi_device_desc _asdevice[], _aedevice[];
> 
> Why does this live separately here, rather than ...
> 
> > +#endif
> > +
> > +#ifdef CONFIG_HAS_DEVICE_TREE
> > +
> > +extern const struct device_desc _sdevice[], _edevice[];
> 
> ... like this ...
> 
> > +int __init device_init(struct dt_device_node *dev, enum
> > device_class class,
> > +                       const void *data)
> > +{
> > +    const struct device_desc *desc;
> > +
> > +    ASSERT(dev != NULL);
> > +
> > +    if ( !dt_device_is_available(dev) ||
> > dt_device_for_passthrough(dev) )
> > +        return  -ENODEV;
> > +
> > +    for ( desc = _sdevice; desc != _edevice; desc++ )
> > +    {
> > +        if ( desc->class != class )
> > +            continue;
> > +
> > +        if ( dt_match_node(desc->dt_match, dev) )
> > +        {
> > +            ASSERT(desc->init != NULL);
> > +
> > +            return desc->init(dev, data);
> > +        }
> > +    }
> > +
> > +    return -EBADF;
> > +}
> > +
> > +enum device_class device_get_class(const struct dt_device_node
> > *dev)
> > +{
> > +    const struct device_desc *desc;
> > +
> > +    ASSERT(dev != NULL);
> > +
> > +    for ( desc = _sdevice; desc != _edevice; desc++ )
> > +    {
> > +        if ( dt_match_node(desc->dt_match, dev) )
> > +            return desc->class;
> > +    }
> > +
> > +    return DEVICE_UNKNOWN;
> > +}
> > +
> > +#endif
> > +
> > +#ifdef CONFIG_ACPI
> 
> ... in the section where it's needed? Leaving just one #ifdef for
> ACPI.
Just tried to follow the approach that first is going variables
declaration/definitions and then functions. But I am okay to move it to
CONFIG_ACPI #ifdef CONFIG_ACPI ... #endif.

Thanks.

~ Oleksii
Jan Beulich Sept. 13, 2024, 5:45 p.m. UTC | #3
On 13.09.2024 16:35, oleksii.kurochko@gmail.com wrote:
> On Thu, 2024-09-12 at 17:28 +0200, Jan Beulich wrote:
>> On 11.09.2024 12:04, Oleksii Kurochko wrote:
>>> --- a/xen/common/Makefile
>>> +++ b/xen/common/Makefile
>>> @@ -6,6 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
>>>  obj-$(CONFIG_CORE_PARKING) += core_parking.o
>>>  obj-y += cpu.o
>>>  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
>>> +obj-$(call or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) +=
>>> device.o
>>
>> I can't spot any HAS_ACPI in the tree. And if this was switched to
>> CONFIG_ACPI
>> I'd further ask why the file needs building on x86.
> Oh, there is no need for building this on x86. With what you suggested
> here ...
> 
>>
>> Also I think I'd prefer to avoid the of the "or" macro here:
>>
>> obj-$(CONFIG_ACPI) += device.o
>> obj-$(CONFIG_HAS_DEVICE_TREE) += device.o
> ... IIUC it will fix the issue with building this file for x86 as
> CONFIG_ACPI depends on (ARM_64 && ARM_EFI).

Except that "depends on" is itself Arm-only, so won't affect x86.
Or else x86 would end up without ACPI support, which would mean
full breakage on about every system.

Jan
Oleksii Kurochko Sept. 16, 2024, 3:51 p.m. UTC | #4
On Fri, 2024-09-13 at 19:45 +0200, Jan Beulich wrote:
> On 13.09.2024 16:35, oleksii.kurochko@gmail.com wrote:
> > On Thu, 2024-09-12 at 17:28 +0200, Jan Beulich wrote:
> > > On 11.09.2024 12:04, Oleksii Kurochko wrote:
> > > > --- a/xen/common/Makefile
> > > > +++ b/xen/common/Makefile
> > > > @@ -6,6 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
> > > >  obj-$(CONFIG_CORE_PARKING) += core_parking.o
> > > >  obj-y += cpu.o
> > > >  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
> > > > +obj-$(call or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) +=
> > > > device.o
> > > 
> > > I can't spot any HAS_ACPI in the tree. And if this was switched
> > > to
> > > CONFIG_ACPI
> > > I'd further ask why the file needs building on x86.
> > Oh, there is no need for building this on x86. With what you
> > suggested
> > here ...
> > 
> > > 
> > > Also I think I'd prefer to avoid the of the "or" macro here:
> > > 
> > > obj-$(CONFIG_ACPI) += device.o
> > > obj-$(CONFIG_HAS_DEVICE_TREE) += device.o
> > ... IIUC it will fix the issue with building this file for x86 as
> > CONFIG_ACPI depends on (ARM_64 && ARM_EFI).
> 
> Except that "depends on" is itself Arm-only, so won't affect x86.
> Or else x86 would end up without ACPI support, which would mean
> full breakage on about every system.
There is another CONFIG_ACPI in xen/drivers/acpi which is equal to 'y'
for x86 so it seems to me that it is needed another config (
GENERIC_DEVICE_INIT ? ) which will be disabled for x86 by default so
device.o won't be compiled for x86.

Have I overlooked something or better option exist? Probably it would
be better to use "and" macro?

~ Oleksii
Jan Beulich Sept. 23, 2024, 7:20 a.m. UTC | #5
On 16.09.2024 17:51, oleksii.kurochko@gmail.com wrote:
> On Fri, 2024-09-13 at 19:45 +0200, Jan Beulich wrote:
>> On 13.09.2024 16:35, oleksii.kurochko@gmail.com wrote:
>>> On Thu, 2024-09-12 at 17:28 +0200, Jan Beulich wrote:
>>>> On 11.09.2024 12:04, Oleksii Kurochko wrote:
>>>>> --- a/xen/common/Makefile
>>>>> +++ b/xen/common/Makefile
>>>>> @@ -6,6 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
>>>>>  obj-$(CONFIG_CORE_PARKING) += core_parking.o
>>>>>  obj-y += cpu.o
>>>>>  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
>>>>> +obj-$(call or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) +=
>>>>> device.o
>>>>
>>>> I can't spot any HAS_ACPI in the tree. And if this was switched
>>>> to
>>>> CONFIG_ACPI
>>>> I'd further ask why the file needs building on x86.
>>> Oh, there is no need for building this on x86. With what you
>>> suggested
>>> here ...
>>>
>>>>
>>>> Also I think I'd prefer to avoid the of the "or" macro here:
>>>>
>>>> obj-$(CONFIG_ACPI) += device.o
>>>> obj-$(CONFIG_HAS_DEVICE_TREE) += device.o
>>> ... IIUC it will fix the issue with building this file for x86 as
>>> CONFIG_ACPI depends on (ARM_64 && ARM_EFI).
>>
>> Except that "depends on" is itself Arm-only, so won't affect x86.
>> Or else x86 would end up without ACPI support, which would mean
>> full breakage on about every system.
> There is another CONFIG_ACPI in xen/drivers/acpi which is equal to 'y'
> for x86 so it seems to me that it is needed another config (
> GENERIC_DEVICE_INIT ? ) which will be disabled for x86 by default so
> device.o won't be compiled for x86.
> 
> Have I overlooked something or better option exist? Probably it would
> be better to use "and" macro?

I'm afraid I don't understand your response. There are two seemingly
separate ACPI in distinct Kconfig files, yes. They combine when both are
visible to kconfig (as is the case for Arm64). Can you try to re-express
your question with this aspect in mind?

Jan
Oleksii Kurochko Sept. 23, 2024, 8:51 a.m. UTC | #6
On Mon, 2024-09-23 at 09:20 +0200, Jan Beulich wrote:
> On 16.09.2024 17:51, oleksii.kurochko@gmail.com wrote:
> > On Fri, 2024-09-13 at 19:45 +0200, Jan Beulich wrote:
> > > On 13.09.2024 16:35, oleksii.kurochko@gmail.com wrote:
> > > > On Thu, 2024-09-12 at 17:28 +0200, Jan Beulich wrote:
> > > > > On 11.09.2024 12:04, Oleksii Kurochko wrote:
> > > > > > --- a/xen/common/Makefile
> > > > > > +++ b/xen/common/Makefile
> > > > > > @@ -6,6 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
> > > > > >  obj-$(CONFIG_CORE_PARKING) += core_parking.o
> > > > > >  obj-y += cpu.o
> > > > > >  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
> > > > > > +obj-$(call
> > > > > > or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) +=
> > > > > > device.o
> > > > > 
> > > > > I can't spot any HAS_ACPI in the tree. And if this was
> > > > > switched
> > > > > to
> > > > > CONFIG_ACPI
> > > > > I'd further ask why the file needs building on x86.
> > > > Oh, there is no need for building this on x86. With what you
> > > > suggested
> > > > here ...
> > > > 
> > > > > 
> > > > > Also I think I'd prefer to avoid the of the "or" macro here:
> > > > > 
> > > > > obj-$(CONFIG_ACPI) += device.o
> > > > > obj-$(CONFIG_HAS_DEVICE_TREE) += device.o
> > > > ... IIUC it will fix the issue with building this file for x86
> > > > as
> > > > CONFIG_ACPI depends on (ARM_64 && ARM_EFI).
> > > 
> > > Except that "depends on" is itself Arm-only, so won't affect x86.
> > > Or else x86 would end up without ACPI support, which would mean
> > > full breakage on about every system.
> > There is another CONFIG_ACPI in xen/drivers/acpi which is equal to
> > 'y'
> > for x86 so it seems to me that it is needed another config (
> > GENERIC_DEVICE_INIT ? ) which will be disabled for x86 by default
> > so
> > device.o won't be compiled for x86.
> > 
> > Have I overlooked something or better option exist? Probably it
> > would
> > be better to use "and" macro?
> 
> I'm afraid I don't understand your response. There are two seemingly
> separate ACPI in distinct Kconfig files, yes. They combine when both
> are
> visible to kconfig (as is the case for Arm64). Can you try to re-
> express
> your question with this aspect in mind?

I wanted to say that we can't simply rely on CONFIG_ACPI and
CONFIG_HAS_DEVICE_TREE to determine if device.o should be compiled
because, in the case of x86, CONFIG_ACPI=y, device.o will be compiled
and result in compilation errors.

~ Oleksii
Jan Beulich Sept. 23, 2024, 9:06 a.m. UTC | #7
On 23.09.2024 10:51, oleksii.kurochko@gmail.com wrote:
> On Mon, 2024-09-23 at 09:20 +0200, Jan Beulich wrote:
>> On 16.09.2024 17:51, oleksii.kurochko@gmail.com wrote:
>>> On Fri, 2024-09-13 at 19:45 +0200, Jan Beulich wrote:
>>>> On 13.09.2024 16:35, oleksii.kurochko@gmail.com wrote:
>>>>> On Thu, 2024-09-12 at 17:28 +0200, Jan Beulich wrote:
>>>>>> On 11.09.2024 12:04, Oleksii Kurochko wrote:
>>>>>>> --- a/xen/common/Makefile
>>>>>>> +++ b/xen/common/Makefile
>>>>>>> @@ -6,6 +6,7 @@ obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
>>>>>>>  obj-$(CONFIG_CORE_PARKING) += core_parking.o
>>>>>>>  obj-y += cpu.o
>>>>>>>  obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
>>>>>>> +obj-$(call
>>>>>>> or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) +=
>>>>>>> device.o
>>>>>>
>>>>>> I can't spot any HAS_ACPI in the tree. And if this was
>>>>>> switched
>>>>>> to
>>>>>> CONFIG_ACPI
>>>>>> I'd further ask why the file needs building on x86.
>>>>> Oh, there is no need for building this on x86. With what you
>>>>> suggested
>>>>> here ...
>>>>>
>>>>>>
>>>>>> Also I think I'd prefer to avoid the of the "or" macro here:
>>>>>>
>>>>>> obj-$(CONFIG_ACPI) += device.o
>>>>>> obj-$(CONFIG_HAS_DEVICE_TREE) += device.o
>>>>> ... IIUC it will fix the issue with building this file for x86
>>>>> as
>>>>> CONFIG_ACPI depends on (ARM_64 && ARM_EFI).
>>>>
>>>> Except that "depends on" is itself Arm-only, so won't affect x86.
>>>> Or else x86 would end up without ACPI support, which would mean
>>>> full breakage on about every system.
>>> There is another CONFIG_ACPI in xen/drivers/acpi which is equal to
>>> 'y'
>>> for x86 so it seems to me that it is needed another config (
>>> GENERIC_DEVICE_INIT ? ) which will be disabled for x86 by default
>>> so
>>> device.o won't be compiled for x86.
>>>
>>> Have I overlooked something or better option exist? Probably it
>>> would
>>> be better to use "and" macro?
>>
>> I'm afraid I don't understand your response. There are two seemingly
>> separate ACPI in distinct Kconfig files, yes. They combine when both
>> are
>> visible to kconfig (as is the case for Arm64). Can you try to re-
>> express
>> your question with this aspect in mind?
> 
> I wanted to say that we can't simply rely on CONFIG_ACPI and
> CONFIG_HAS_DEVICE_TREE to determine if device.o should be compiled
> because, in the case of x86, CONFIG_ACPI=y, device.o will be compiled
> and result in compilation errors.

Ah, I see. Of course. Ideally to be addressed without introducing yet
another (new) Kconfig setting.

Jan
diff mbox series

Patch

diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
index 3e02cff008..5610cddcba 100644
--- a/xen/arch/arm/device.c
+++ b/xen/arch/arm/device.c
@@ -8,79 +8,12 @@ 
  * Copyright (C) 2013 Linaro Limited.
  */
 
-#include <asm/device.h>
-#include <asm/setup.h>
+#include <xen/device_tree.h>
 #include <xen/errno.h>
-#include <xen/init.h>
 #include <xen/iocap.h>
 #include <xen/lib.h>
 
-extern const struct device_desc _sdevice[], _edevice[];
-
-#ifdef CONFIG_ACPI
-extern const struct acpi_device_desc _asdevice[], _aedevice[];
-#endif
-
-int __init device_init(struct dt_device_node *dev, enum device_class class,
-                       const void *data)
-{
-    const struct device_desc *desc;
-
-    ASSERT(dev != NULL);
-
-    if ( !dt_device_is_available(dev) || dt_device_for_passthrough(dev) )
-        return  -ENODEV;
-
-    for ( desc = _sdevice; desc != _edevice; desc++ )
-    {
-        if ( desc->class != class )
-            continue;
-
-        if ( dt_match_node(desc->dt_match, dev) )
-        {
-            ASSERT(desc->init != NULL);
-
-            return desc->init(dev, data);
-        }
-
-    }
-
-    return -EBADF;
-}
-
-#ifdef CONFIG_ACPI
-int __init acpi_device_init(enum device_class class, const void *data, int class_type)
-{
-    const struct acpi_device_desc *desc;
-
-    for ( desc = _asdevice; desc != _aedevice; desc++ )
-    {
-        if ( ( desc->class != class ) || ( desc->class_type != class_type ) )
-            continue;
-
-        ASSERT(desc->init != NULL);
-
-        return desc->init(data);
-    }
-
-    return -EBADF;
-}
-#endif
-
-enum device_class device_get_class(const struct dt_device_node *dev)
-{
-    const struct device_desc *desc;
-
-    ASSERT(dev != NULL);
-
-    for ( desc = _sdevice; desc != _edevice; desc++ )
-    {
-        if ( dt_match_node(desc->dt_match, dev) )
-            return desc->class;
-    }
-
-    return DEVICE_UNKNOWN;
-}
+#include <asm/setup.h>
 
 int map_irq_to_domain(struct domain *d, unsigned int irq,
                       bool need_mapping, const char *devname)
diff --git a/xen/common/Makefile b/xen/common/Makefile
index fc52e0857d..703e26de1d 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -6,6 +6,7 @@  obj-$(CONFIG_HYPFS_CONFIG) += config_data.o
 obj-$(CONFIG_CORE_PARKING) += core_parking.o
 obj-y += cpu.o
 obj-$(CONFIG_DEBUG_TRACE) += debugtrace.o
+obj-$(call or,$(CONFIG_HAS_DEVICE_TREE),$(CONFIG_HAS_ACPI)) += device.o
 obj-$(CONFIG_HAS_DEVICE_TREE) += device-tree/
 obj-$(CONFIG_IOREQ_SERVER) += dm.o
 obj-y += domain.o
diff --git a/xen/common/device.c b/xen/common/device.c
new file mode 100644
index 0000000000..e34a7dc88e
--- /dev/null
+++ b/xen/common/device.c
@@ -0,0 +1,82 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Based on the code from:
+ *   xen/arch/arm/device.c
+ */
+
+#include <xen/bug.h>
+#include <xen/device_tree.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+
+#include <asm-generic/device.h>
+
+#ifdef CONFIG_ACPI
+extern const struct acpi_device_desc _asdevice[], _aedevice[];
+#endif
+
+#ifdef CONFIG_HAS_DEVICE_TREE
+
+extern const struct device_desc _sdevice[], _edevice[];
+
+int __init device_init(struct dt_device_node *dev, enum device_class class,
+                       const void *data)
+{
+    const struct device_desc *desc;
+
+    ASSERT(dev != NULL);
+
+    if ( !dt_device_is_available(dev) || dt_device_for_passthrough(dev) )
+        return  -ENODEV;
+
+    for ( desc = _sdevice; desc != _edevice; desc++ )
+    {
+        if ( desc->class != class )
+            continue;
+
+        if ( dt_match_node(desc->dt_match, dev) )
+        {
+            ASSERT(desc->init != NULL);
+
+            return desc->init(dev, data);
+        }
+    }
+
+    return -EBADF;
+}
+
+enum device_class device_get_class(const struct dt_device_node *dev)
+{
+    const struct device_desc *desc;
+
+    ASSERT(dev != NULL);
+
+    for ( desc = _sdevice; desc != _edevice; desc++ )
+    {
+        if ( dt_match_node(desc->dt_match, dev) )
+            return desc->class;
+    }
+
+    return DEVICE_UNKNOWN;
+}
+
+#endif
+
+#ifdef CONFIG_ACPI
+int __init acpi_device_init(enum device_class class, const void *data, int class_type)
+{
+    const struct acpi_device_desc *desc;
+
+    for ( desc = _asdevice; desc != _aedevice; desc++ )
+    {
+        if ( ( desc->class != class ) || ( desc->class_type != class_type ) )
+            continue;
+
+        ASSERT(desc->init != NULL);
+
+        return desc->init(data);
+    }
+
+    return -EBADF;
+}
+#endif