Message ID | 08d341428f0fba44ef47935be9f2d413169601ee.1367188423.git.julien.grall@linaro.org |
---|---|
State | Changes Requested, archived |
Headers | show |
On Mon, 2013-04-29 at 00:02 +0100, Julien Grall wrote: > Xen can include various platform support (ie: exynos5, versatile express...) > and choose during boot time a set of callbacks for the current board. > These callbacks will be called in places where each board can have specific > code. For the moment the callbacks are: > - platform_init: additional initialization for the platform > - platform_init_time: some platform (ie: Exynos 5) needs to initialize > the timer with an uncommon way > - platform_specific_mapping: add mapping to dom0 which are not specified > in the device tree > - platform_reset: reset the platform > > Signed-off-by: Julien Grall <julien.grall@linaro.org> alignment in xen.lds.S again, otherwise: Acked-by: Ian Campbell <ian.campbell@citrix.com>
On 04/29/2013 05:15 PM, Ian Campbell wrote: > On Mon, 2013-04-29 at 00:02 +0100, Julien Grall wrote: >> Xen can include various platform support (ie: exynos5, versatile express...) >> and choose during boot time a set of callbacks for the current board. >> These callbacks will be called in places where each board can have specific >> code. For the moment the callbacks are: >> - platform_init: additional initialization for the platform >> - platform_init_time: some platform (ie: Exynos 5) needs to initialize >> the timer with an uncommon way >> - platform_specific_mapping: add mapping to dom0 which are not specified >> in the device tree >> - platform_reset: reset the platform >> >> Signed-off-by: Julien Grall <julien.grall@linaro.org> > > alignment in xen.lds.S again, otherwise: I will fix with ALIGN(8). > Acked-by: Ian Campbell <ian.campbell@citrix.com> > > >
On Mon, 29 Apr 2013, Julien Grall wrote: > Xen can include various platform support (ie: exynos5, versatile express...) > and choose during boot time a set of callbacks for the current board. > These callbacks will be called in places where each board can have specific > code. For the moment the callbacks are: > - platform_init: additional initialization for the platform > - platform_init_time: some platform (ie: Exynos 5) needs to initialize > the timer with an uncommon way > - platform_specific_mapping: add mapping to dom0 which are not specified > in the device tree > - platform_reset: reset the platform given that you added a platform_reset hook, you might as well add a platform_poweroff hook too. > Signed-off-by: Julien Grall <julien.grall@linaro.org> > --- > xen/arch/arm/Makefile | 1 + > xen/arch/arm/domain_build.c | 4 ++ > xen/arch/arm/platform.c | 121 ++++++++++++++++++++++++++++++++++++++++ > xen/arch/arm/setup.c | 3 + > xen/arch/arm/shutdown.c | 2 + > xen/arch/arm/time.c | 6 ++ > xen/arch/arm/xen.lds.S | 6 ++ > xen/include/asm-arm/platform.h | 70 +++++++++++++++++++++++ > 8 files changed, 213 insertions(+) > create mode 100644 xen/arch/arm/platform.c > create mode 100644 xen/include/asm-arm/platform.h > > diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile > index 7a73b79..981ad78 100644 > --- a/xen/arch/arm/Makefile > +++ b/xen/arch/arm/Makefile > @@ -17,6 +17,7 @@ obj-y += p2m.o > obj-y += percpu.o > obj-y += guestcopy.o > obj-y += physdev.o > +obj-y += platform.o > obj-y += setup.o > obj-y += time.o > obj-y += smpboot.o > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c > index 11298e1..d6b8086 100644 > --- a/xen/arch/arm/domain_build.c > +++ b/xen/arch/arm/domain_build.c > @@ -12,6 +12,7 @@ > #include <xen/libfdt/libfdt.h> > #include <xen/guest_access.h> > #include <asm/setup.h> > +#include <asm/platform.h> > > #include <asm/gic.h> > #include <xen/irq.h> > @@ -516,6 +517,9 @@ int construct_dom0(struct domain *d) > return rc; > > parse_device_tree(d); > + rc = platform_specific_mapping(d); > + if ( rc < 0 ) > + return rc; > > /* The following loads use the domain's p2m */ > p2m_load_VTTBR(d); > diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c > new file mode 100644 > index 0000000..ba569ea > --- /dev/null > +++ b/xen/arch/arm/platform.c > @@ -0,0 +1,121 @@ > +/* > + * xen/arch/arm/platform.c > + * > + * Helpers to execute platform specific code. > + * > + * Julien Grall <julien.grall@linaro.org> > + * Copyright (C) 2013 Linaro Limited. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include <asm/platform.h> > +#include <xen/device_tree.h> > +#include <xen/init.h> > + > +extern const struct platform_desc _splatform[], _eplatform[]; > + > +/* Pointer to the current platform description */ > +static const struct platform_desc *platform; > + > + > +static bool_t __init platform_is_compatible(const struct platform_desc *plat) > +{ > + const char *const *compat; > + > + if ( !plat->compatible ) > + return 0; > + > + for ( compat = plat->compatible; *compat; compat++ ) > + { > + if ( dt_machine_is_compatible(*compat) ) > + return 1; > + } > + > + return 0; > +} > + > +/* List of possible platform */ > +static void dump_platform_table(void) > +{ > + const struct platform_desc *p; > + > + printk("Available platform support:\n"); > + > + for ( p = _splatform; p != _eplatform; p++ ) > + printk(" - %s\n", p->name); > +} > + > +int __init platform_init(void) > +{ > + int res = 0; > + > + ASSERT(platform == NULL); > + > + /* Looking for the platform description */ > + for ( platform = _splatform; platform != _eplatform; platform++ ) > + { > + if ( platform_is_compatible(platform) ) > + break; > + } > + > + /* We don't have specific operations for this platform */ > + if ( platform == _eplatform ) > + { > + /* TODO: List compatible */ > + printk(XENLOG_WARNING "WARNING: Unrecognized/unsupported device tree " > + "compatible list\n"); > + dump_platform_table(); > + platform = NULL; > + } > + else > + printk(XENLOG_INFO "Platform: %s\n", platform->name); > + > + if ( platform && platform->init ) > + res = platform->init(); > + > + return res; > +} > + > +int __init platform_init_time(void) > +{ > + int res = 0; > + > + if ( platform && platform->init_time ) > + res = platform->init_time(); > + > + return res; > +} > + > +int __init platform_specific_mapping(struct domain *d) > +{ > + int res = 0; > + > + if ( platform && platform->specific_mapping ) > + res = platform->specific_mapping(d); > + > + return res; > +} > + > +void platform_reset(void) > +{ > + if ( platform && platform->reset ) > + platform->reset(); > +} > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c > index aee491d..9721150 100644 > --- a/xen/arch/arm/setup.c > +++ b/xen/arch/arm/setup.c > @@ -41,6 +41,7 @@ > #include <asm/early_printk.h> > #include <asm/gic.h> > #include <asm/cpufeature.h> > +#include <asm/platform.h> > > struct cpuinfo_arm __read_mostly boot_cpu_data; > > @@ -439,6 +440,8 @@ void __init start_xen(unsigned long boot_phys_offset, > > processor_id(); > > + platform_init(); > + > init_xen_time(); > > gic_init(); > diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c > index c1b60af..a5c2085 100644 > --- a/xen/arch/arm/shutdown.c > +++ b/xen/arch/arm/shutdown.c > @@ -5,6 +5,7 @@ > #include <xen/lib.h> > #include <xen/mm.h> > #include <xen/smp.h> > +#include <asm/platform.h> > > static void raw_machine_reset(void) > { > @@ -21,6 +22,7 @@ static void raw_machine_reset(void) > dsb(); isb(); > clear_fixmap(FIXMAP_MISC); > #endif > + platform_reset(); > } > > static void halt_this_cpu(void *arg) > diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c > index 63dace2..f01be3f 100644 > --- a/xen/arch/arm/time.c > +++ b/xen/arch/arm/time.c > @@ -33,6 +33,7 @@ > #include <asm/time.h> > #include <asm/gic.h> > #include <asm/cpufeature.h> > +#include <asm/platform.h> > > /* > * Unfortunately the hypervisor timer interrupt appears to be buggy in > @@ -130,6 +131,11 @@ int __init init_xen_time(void) > panic("CPU does not support the Generic Timer v1 interface.\n"); > > cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000; > + > + res = platform_init_time(); > + if ( res ) > + return res; > + > boot_count = READ_SYSREG64(CNTPCT_EL0); > printk("Using generic timer at %lu KHz\n", cpu_khz); > > diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S > index 7434e83..b5c99b7 100644 > --- a/xen/arch/arm/xen.lds.S > +++ b/xen/arch/arm/xen.lds.S > @@ -76,6 +76,12 @@ SECTIONS > __lock_profile_end = .; > #endif > > + .arch.info : { > + _splatform = .; > + *(.arch.info) > + _eplatform = .; > + } :text > + > .dev.info : { > _sdevice = .; > *(.dev.info) > diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h > new file mode 100644 > index 0000000..c89a4ca > --- /dev/null > +++ b/xen/include/asm-arm/platform.h > @@ -0,0 +1,70 @@ > +#ifndef __ASM_ARM_PLATFORM_H > +#define __ASM_ARM_PLATFORM_H > + > +#include <xen/init.h> > +#include <xen/sched.h> > +#include <xen/mm.h> > + > +/* Describe specific operation for a board */ > +struct platform_desc { > + /* Platform name */ > + const char *name; > + /* Array of device tree 'compatible' strings */ > + const char *const *compatible; > + /* Platform initialization */ > + int (*init)(void); > + int (*init_time)(void); > + /* Specific mapping for dom0 */ > + int (*specific_mapping)(struct domain *d); > + /* Platform reset */ > + void (*reset)(void); > +}; > + > +int __init platform_init(void); > +int __init platform_init_time(void); > +int __init platform_specific_mapping(struct domain *d); > +void platform_reset(void); > + > +/* Helper to read/write a register */ > +static inline uint32_t platform_read_register(uint32_t addr) > +{ > + volatile const uint32_t *reg; > + uint32_t value; > + > + set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED); > + reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK)); > + value = *reg; > + dsb(); isb(); > + clear_fixmap(FIXMAP_MISC); > + > + return value; > +} > + > +static inline void platform_write_register(uint32_t addr, uint32_t value) > +{ > + volatile uint32_t *reg; > + > + set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED); > + reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK)); > + *reg = value; > + clear_fixmap(FIXMAP_MISC); > +} > + > +#define PLATFORM_START(_name, _namestr) \ > +static const struct platform_desc __plat_desc_##_name __used \ > +__attribute__((__section__(".arch.info"))) = { \ > + .name = _namestr, > + > +#define PLATFORM_END \ > +}; > + > +#endif /* __ASM_ARM_PLATFORM_H */ > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > -- > Julien Grall >
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 7a73b79..981ad78 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -17,6 +17,7 @@ obj-y += p2m.o obj-y += percpu.o obj-y += guestcopy.o obj-y += physdev.o +obj-y += platform.o obj-y += setup.o obj-y += time.o obj-y += smpboot.o diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 11298e1..d6b8086 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -12,6 +12,7 @@ #include <xen/libfdt/libfdt.h> #include <xen/guest_access.h> #include <asm/setup.h> +#include <asm/platform.h> #include <asm/gic.h> #include <xen/irq.h> @@ -516,6 +517,9 @@ int construct_dom0(struct domain *d) return rc; parse_device_tree(d); + rc = platform_specific_mapping(d); + if ( rc < 0 ) + return rc; /* The following loads use the domain's p2m */ p2m_load_VTTBR(d); diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c new file mode 100644 index 0000000..ba569ea --- /dev/null +++ b/xen/arch/arm/platform.c @@ -0,0 +1,121 @@ +/* + * xen/arch/arm/platform.c + * + * Helpers to execute platform specific code. + * + * Julien Grall <julien.grall@linaro.org> + * Copyright (C) 2013 Linaro Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <asm/platform.h> +#include <xen/device_tree.h> +#include <xen/init.h> + +extern const struct platform_desc _splatform[], _eplatform[]; + +/* Pointer to the current platform description */ +static const struct platform_desc *platform; + + +static bool_t __init platform_is_compatible(const struct platform_desc *plat) +{ + const char *const *compat; + + if ( !plat->compatible ) + return 0; + + for ( compat = plat->compatible; *compat; compat++ ) + { + if ( dt_machine_is_compatible(*compat) ) + return 1; + } + + return 0; +} + +/* List of possible platform */ +static void dump_platform_table(void) +{ + const struct platform_desc *p; + + printk("Available platform support:\n"); + + for ( p = _splatform; p != _eplatform; p++ ) + printk(" - %s\n", p->name); +} + +int __init platform_init(void) +{ + int res = 0; + + ASSERT(platform == NULL); + + /* Looking for the platform description */ + for ( platform = _splatform; platform != _eplatform; platform++ ) + { + if ( platform_is_compatible(platform) ) + break; + } + + /* We don't have specific operations for this platform */ + if ( platform == _eplatform ) + { + /* TODO: List compatible */ + printk(XENLOG_WARNING "WARNING: Unrecognized/unsupported device tree " + "compatible list\n"); + dump_platform_table(); + platform = NULL; + } + else + printk(XENLOG_INFO "Platform: %s\n", platform->name); + + if ( platform && platform->init ) + res = platform->init(); + + return res; +} + +int __init platform_init_time(void) +{ + int res = 0; + + if ( platform && platform->init_time ) + res = platform->init_time(); + + return res; +} + +int __init platform_specific_mapping(struct domain *d) +{ + int res = 0; + + if ( platform && platform->specific_mapping ) + res = platform->specific_mapping(d); + + return res; +} + +void platform_reset(void) +{ + if ( platform && platform->reset ) + platform->reset(); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index aee491d..9721150 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -41,6 +41,7 @@ #include <asm/early_printk.h> #include <asm/gic.h> #include <asm/cpufeature.h> +#include <asm/platform.h> struct cpuinfo_arm __read_mostly boot_cpu_data; @@ -439,6 +440,8 @@ void __init start_xen(unsigned long boot_phys_offset, processor_id(); + platform_init(); + init_xen_time(); gic_init(); diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c index c1b60af..a5c2085 100644 --- a/xen/arch/arm/shutdown.c +++ b/xen/arch/arm/shutdown.c @@ -5,6 +5,7 @@ #include <xen/lib.h> #include <xen/mm.h> #include <xen/smp.h> +#include <asm/platform.h> static void raw_machine_reset(void) { @@ -21,6 +22,7 @@ static void raw_machine_reset(void) dsb(); isb(); clear_fixmap(FIXMAP_MISC); #endif + platform_reset(); } static void halt_this_cpu(void *arg) diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index 63dace2..f01be3f 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -33,6 +33,7 @@ #include <asm/time.h> #include <asm/gic.h> #include <asm/cpufeature.h> +#include <asm/platform.h> /* * Unfortunately the hypervisor timer interrupt appears to be buggy in @@ -130,6 +131,11 @@ int __init init_xen_time(void) panic("CPU does not support the Generic Timer v1 interface.\n"); cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000; + + res = platform_init_time(); + if ( res ) + return res; + boot_count = READ_SYSREG64(CNTPCT_EL0); printk("Using generic timer at %lu KHz\n", cpu_khz); diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S index 7434e83..b5c99b7 100644 --- a/xen/arch/arm/xen.lds.S +++ b/xen/arch/arm/xen.lds.S @@ -76,6 +76,12 @@ SECTIONS __lock_profile_end = .; #endif + .arch.info : { + _splatform = .; + *(.arch.info) + _eplatform = .; + } :text + .dev.info : { _sdevice = .; *(.dev.info) diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h new file mode 100644 index 0000000..c89a4ca --- /dev/null +++ b/xen/include/asm-arm/platform.h @@ -0,0 +1,70 @@ +#ifndef __ASM_ARM_PLATFORM_H +#define __ASM_ARM_PLATFORM_H + +#include <xen/init.h> +#include <xen/sched.h> +#include <xen/mm.h> + +/* Describe specific operation for a board */ +struct platform_desc { + /* Platform name */ + const char *name; + /* Array of device tree 'compatible' strings */ + const char *const *compatible; + /* Platform initialization */ + int (*init)(void); + int (*init_time)(void); + /* Specific mapping for dom0 */ + int (*specific_mapping)(struct domain *d); + /* Platform reset */ + void (*reset)(void); +}; + +int __init platform_init(void); +int __init platform_init_time(void); +int __init platform_specific_mapping(struct domain *d); +void platform_reset(void); + +/* Helper to read/write a register */ +static inline uint32_t platform_read_register(uint32_t addr) +{ + volatile const uint32_t *reg; + uint32_t value; + + set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED); + reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK)); + value = *reg; + dsb(); isb(); + clear_fixmap(FIXMAP_MISC); + + return value; +} + +static inline void platform_write_register(uint32_t addr, uint32_t value) +{ + volatile uint32_t *reg; + + set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED); + reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK)); + *reg = value; + clear_fixmap(FIXMAP_MISC); +} + +#define PLATFORM_START(_name, _namestr) \ +static const struct platform_desc __plat_desc_##_name __used \ +__attribute__((__section__(".arch.info"))) = { \ + .name = _namestr, + +#define PLATFORM_END \ +}; + +#endif /* __ASM_ARM_PLATFORM_H */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */
Xen can include various platform support (ie: exynos5, versatile express...) and choose during boot time a set of callbacks for the current board. These callbacks will be called in places where each board can have specific code. For the moment the callbacks are: - platform_init: additional initialization for the platform - platform_init_time: some platform (ie: Exynos 5) needs to initialize the timer with an uncommon way - platform_specific_mapping: add mapping to dom0 which are not specified in the device tree - platform_reset: reset the platform Signed-off-by: Julien Grall <julien.grall@linaro.org> --- xen/arch/arm/Makefile | 1 + xen/arch/arm/domain_build.c | 4 ++ xen/arch/arm/platform.c | 121 ++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/setup.c | 3 + xen/arch/arm/shutdown.c | 2 + xen/arch/arm/time.c | 6 ++ xen/arch/arm/xen.lds.S | 6 ++ xen/include/asm-arm/platform.h | 70 +++++++++++++++++++++++ 8 files changed, 213 insertions(+) create mode 100644 xen/arch/arm/platform.c create mode 100644 xen/include/asm-arm/platform.h