[RFC PATCH 06/17] ARM: kernel: save/restore generic infrastructure
Amit Kachhap
amit.kachhap at linaro.org
Thu Jul 28 12:22:38 EDT 2011
On 7 July 2011 21:20, Lorenzo Pieralisi <lorenzo.pieralisi at arm.com> wrote:
>
> This patch provides the code infrastructure needed to maintain
> a generic per-cpu architecture implementation of idle code.
>
> sr_platform.c :
> - code manages patchset initialization and memory management
>
> sr_context.c:
> - code initializes run-time context save/restore generic
> support
>
> sr_power.c:
> - provides the generic infrastructure to enter exit low
> power modes and communicate with Power Control Unit (PCU)
>
> v7 support hinges on the basic infrastructure to provide per-cpu
> arch implementation basically through standard function pointers
> signatures.
>
> Preprocessor defines include size of data needed to save/restore
> L2 state. This define value should be moved to the respective
> subsystem (PL310) once the patchset IF to that subsystem is settled.
>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> ---
> arch/arm/kernel/sr.h | 162 +++++++++++++++++++++++++++++++++++++++++
> arch/arm/kernel/sr_context.c | 23 ++++++
> arch/arm/kernel/sr_helpers.h | 56 ++++++++++++++
> arch/arm/kernel/sr_platform.c | 48 ++++++++++++
> arch/arm/kernel/sr_power.c | 26 +++++++
> 5 files changed, 315 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/kernel/sr.h
> create mode 100644 arch/arm/kernel/sr_context.c
> create mode 100644 arch/arm/kernel/sr_helpers.h
> create mode 100644 arch/arm/kernel/sr_platform.c
> create mode 100644 arch/arm/kernel/sr_power.c
>
> diff --git a/arch/arm/kernel/sr.h b/arch/arm/kernel/sr.h
> new file mode 100644
> index 0000000..6b24e53
> --- /dev/null
> +++ b/arch/arm/kernel/sr.h
> @@ -0,0 +1,162 @@
> +#define SR_NR_CLUSTERS 1
> +
> +#define STACK_SIZE 512
> +
> +#define CPU_A5 0x4100c050
> +#define CPU_A8 0x4100c080
> +#define CPU_A9 0x410fc090
> +#define L2_DATA_SIZE 16
> +#define CONTEXT_SPACE_UNCACHED (2 * PAGE_SIZE)
> +#define PA(f) ((typeof(f) *)virt_to_phys((void *)f))
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <linux/types.h>
> +#include <linux/threads.h>
> +#include <linux/cpumask.h>
> +#include <asm/page.h>
> +
> +/*
> + * Structures we hide from the OS API
> + */
> +
> +struct sr_cpu_context {
> + u32 flags;
> + u32 saved_items;
> + u32 *mmu_data;
> +};
> +
> +struct sr_cluster_context {
> + u32 saved_items;
> + u32 *l2_data;
> +};
> +
> +struct sr_main_table {
> + pgd_t *os_mmu_context[SR_NR_CLUSTERS][CONFIG_NR_CPUS];
> + cpumask_t cpu_idle_mask[SR_NR_CLUSTERS];
> + pgd_t *fw_mmu_context;
> + u32 num_clusters;
> + struct sr_cluster *cluster_table;
> +};
> +
> +
> +/*
> + * A cluster is a container for CPUs, typically either a single CPU or a
> + * coherent cluster.
> + * We assume the CPUs in the cluster can be switched off independently.
> + */
> +struct sr_cluster {
> + u32 cpu_type; /* A9mpcore, A5mpcore, etc */
> + u32 num_cpus;
> + struct sr_cluster_context *context;
> + struct sr_cpu *cpu_table;
> + u32 power_state;
> + u32 cluster_down;
> + void __iomem *scu_address;
> + void *lock;
> +};
> +
> +struct sr_cpu {
> + struct sr_cpu_context *context;
> + u32 power_state;
> +};
> +
> +/*
> + * arch infrastructure
> + */
> +struct sr_arch {
> + unsigned int cpu_val;
> + unsigned int cpu_mask;
> +
> + int (*init)(void);
> +
> + int (*save_context)(struct sr_cluster *, struct sr_cpu *,
> + unsigned);
> + int (*restore_context)(struct sr_cluster *, struct sr_cpu *);
> + int (*enter_cstate)(unsigned cpu_index,
> + struct sr_cpu *cpu,
> + struct sr_cluster *cluster);
> + int (*leave_cstate)(unsigned, struct sr_cpu *,
> + struct sr_cluster *);
> + void (*reset)(void);
> +
> +};
> +
> +extern struct sr_arch *arch;
> +extern int lookup_arch(void);
> +
> +/*
> + * Global variables
> + */
> +extern struct sr_main_table main_table;
> +extern unsigned long idle_save_context;
> +extern unsigned long idle_restore_context;
> +extern unsigned long idle_mt;
> +extern void *context_memory_uncached;
> +
> +/*
> + * Context save/restore
> + */
> +typedef u32 (sr_save_context_t)
> + (struct sr_cluster *,
> + struct sr_cpu*, u32);
> +typedef u32 (sr_restore_context_t)
> + (struct sr_cluster *,
> + struct sr_cpu*);
> +
> +extern sr_save_context_t sr_save_context;
> +extern sr_restore_context_t sr_restore_context;
> +
> +
> +extern struct sr_arch *get_arch(void);
> +
> +
> +/*
> + * 1:1 mappings
> + */
> +
> +extern int linux_sr_setup_translation_tables(void);
> +
> +/*
> + * dumb memory allocator
> + */
> +
> +extern void *get_memory(unsigned int size);
> +
> +/*
> + * Entering/Leaving C-states function entries
> + */
> +
> +extern int sr_platform_enter_cstate(unsigned cpu_index, struct sr_cpu *cpu,
> + struct sr_cluster *cluster);
> +extern int sr_platform_leave_cstate(unsigned cpu_index, struct sr_cpu *cpu,
> + struct sr_cluster *cluster);
> +
> +/* save/restore main table */
> +extern struct sr_main_table main_table;
> +
> +/*
> + * Init functions
> + */
> +
> +extern int sr_platform_runtime_init(void);
> +extern int sr_platform_init(void);
> +extern int sr_context_init(void);
> +
> +
> +/*
> + * v7 specific
> + */
> +
> +extern char *cpu_v7_suspend_size;
> +extern void scu_cpu_mode(void __iomem *base, int state);
> +
> +/*
> + * These arrays keep suitable stack pointers for CPUs.
> + *
> + * The memory must be 8-byte aligned.
> + */
> +
> +extern unsigned long platform_cpu_stacks[CONFIG_NR_CPUS];
> +extern unsigned long platform_cpu_nc_stacks[CONFIG_NR_CPUS];
> +#endif
> diff --git a/arch/arm/kernel/sr_context.c b/arch/arm/kernel/sr_context.c
> new file mode 100644
> index 0000000..25eaa43
> --- /dev/null
> +++ b/arch/arm/kernel/sr_context.c
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright (C) 2008-2011 ARM Limited
> + * Author(s): Jon Callan, Lorenzo Pieralisi
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/cache.h>
> +#include <asm/cacheflush.h>
> +#include "sr.h"
> +
> +int sr_context_init(void)
> +{
> + idle_save_context = (unsigned long) arch->save_context;
> + idle_restore_context = __pa(arch->restore_context);
> + __cpuc_flush_dcache_area(&idle_restore_context, sizeof(unsigned long));
> + outer_clean_range(__pa(&idle_restore_context),
> + __pa(&idle_restore_context + 1));
> + return 0;
> +}
> diff --git a/arch/arm/kernel/sr_helpers.h b/arch/arm/kernel/sr_helpers.h
> new file mode 100644
> index 0000000..1ae3a9a
> --- /dev/null
> +++ b/arch/arm/kernel/sr_helpers.h
> @@ -0,0 +1,56 @@
> +/*
> + * Copyright (C) 2008-2011 ARM Limited
> + * Author(s): Jon Callan, Lorenzo Pieralisi
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +static inline int sr_platform_get_cpu_index(void)
> +{
> + unsigned int cpu;
> + __asm__ __volatile__(
> + "mrc p15, 0, %0, c0, c0, 5\n\t"
> + : "=r" (cpu));
> + return cpu & 0xf;
> +}
> +
> +/*
> + * Placeholder for further extensions
> + */
> +static inline int sr_platform_get_cluster_index(void)
> +{
> + return 0;
> +}
> +
> +static inline void __iomem *sr_platform_cbar(void)
> +{
> + void __iomem *base;
> + __asm__ __volatile__(
> + "mrc p15, 4, %0, c15, c0, 0\n\t"
> + : "=r" (base));
> + return base;
> +}
> +
> +#ifdef CONFIG_SMP
> +static inline void exit_coherency(void)
> +{
> + unsigned int v;
> + asm volatile (
> + "mrc p15, 0, %0, c1, c0, 1\n"
> + "bic %0, %0, %1\n"
> + "mcr p15, 0, %0, c1, c0, 1\n"
> + : "=&r" (v)
> + : "Ir" (0x40)
> + : );
The above line gives compilation error with my toolchain.
Adding it as : "cc"); fixes the error.
> +}
> +#else
> +static inline void exit_coherency(void) { }
> +#endif
> +
> +extern void default_sleep(void);
> +extern void sr_suspend(void *);
> +extern void sr_resume(void *, int);
> +extern void disable_clean_inv_dcache_v7_all(void);
> diff --git a/arch/arm/kernel/sr_platform.c b/arch/arm/kernel/sr_platform.c
> new file mode 100644
> index 0000000..530aa1b
> --- /dev/null
> +++ b/arch/arm/kernel/sr_platform.c
> @@ -0,0 +1,48 @@
> +/*
> + * Copyright (C) 2008-2011 ARM Limited
> + *
> + * Author(s): Jon Callan, Lorenzo Pieralisi
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <asm/memory.h>
> +#include <asm/page.h>
> +#include <asm/sr_platform_api.h>
> +#include "sr.h"
> +
> +void *context_memory_uncached;
> +
> +/*
> + * Simple memory allocator function.
> + * Returns start address of allocated region
> + * Memory is zero-initialized.
> + */
> +
> +static unsigned int watermark;
> +
> +void *get_memory(unsigned int size)
> +{
> + unsigned ret;
> + void *vmem = NULL;
> +
> + ret = watermark;
> + watermark += size;
> + BUG_ON(watermark >= CONTEXT_SPACE_UNCACHED);
> + vmem = (context_memory_uncached + ret);
> + watermark = ALIGN(watermark, sizeof(long long));
> +
> + return vmem;
> +}
> +
> +int sr_platform_init(void)
> +{
> + memset(context_memory_uncached, 0, CONTEXT_SPACE_UNCACHED);
> + return arch->init();
> +}
> diff --git a/arch/arm/kernel/sr_power.c b/arch/arm/kernel/sr_power.c
> new file mode 100644
> index 0000000..2585559
> --- /dev/null
> +++ b/arch/arm/kernel/sr_power.c
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright (C) 2008-2011 ARM Limited
> + *
> + * Author(s): Jon Callan, Lorenzo Pieralisi
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include "sr.h"
> +
> +int sr_platform_enter_cstate(unsigned cpu_index,
> + struct sr_cpu *cpu,
> + struct sr_cluster *cluster)
> +{
> + return arch->enter_cstate(cpu_index, cpu, cluster);
> +}
> +
> +int sr_platform_leave_cstate(unsigned cpu_index,
> + struct sr_cpu *cpu,
> + struct sr_cluster *cluster)
> +{
> + return arch->leave_cstate(cpu_index, cpu, cluster);
> +}
> --
> 1.7.4.4
>
>
More information about the linux-arm-kernel
mailing list