Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 73961
b: refs/heads/master
c: 072ef40
h: refs/heads/master
i:
  73959: 6c3a64b
v: v3
  • Loading branch information
Paul Mackerras committed Nov 20, 2007
1 parent d56d1c7 commit 39ea436
Show file tree
Hide file tree
Showing 25 changed files with 229 additions and 85 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bebfa06c61da6246d4aab38efa06a460eb3db4ed
refs/heads/master: 072ef40e08a71aae4ff2835e3c7f601b29daf227
4 changes: 4 additions & 0 deletions trunk/arch/powerpc/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ int main(void)
DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size));
DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size));
DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size));
DEFINE(CFG_DCACHE_LOGBLOCKSZ, offsetof(struct vdso_data, dcache_log_block_size));
#ifdef CONFIG_PPC64
DEFINE(CFG_SYSCALL_MAP64, offsetof(struct vdso_data, syscall_map_64));
DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
Expand Down
111 changes: 64 additions & 47 deletions trunk/arch/powerpc/kernel/rtas.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#include <linux/init.h>
#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/smp.h>
#include <linux/completion.h>
#include <linux/cpumask.h>

#include <asm/prom.h>
#include <asm/rtas.h>
Expand All @@ -34,15 +37,19 @@
#include <asm/lmb.h>
#include <asm/udbg.h>
#include <asm/syscalls.h>
#include <asm/smp.h>
#include <asm/atomic.h>

struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED
};
EXPORT_SYMBOL(rtas);

struct rtas_suspend_me_data {
long waiting;
struct rtas_args *args;
atomic_t working; /* number of cpus accessing this struct */
int token; /* ibm,suspend-me */
int error;
struct completion *complete; /* wait on this until working == 0 */
};

DEFINE_SPINLOCK(rtas_data_buf_lock);
Expand Down Expand Up @@ -631,18 +638,18 @@ void rtas_halt(void)
/* Must be in the RMO region, so we place it here */
static char rtas_os_term_buf[2048];

void rtas_os_term(char *str)
void rtas_panic_msg(char *str)
{
int status;
snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);
}

if (panic_timeout)
return;
void rtas_os_term(void)
{
int status;

if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term"))
return;

snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);

do {
status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
__pa(rtas_os_term_buf));
Expand All @@ -657,50 +664,62 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
#ifdef CONFIG_PPC_PSERIES
static void rtas_percpu_suspend_me(void *info)
{
int i;
long rc;
long flags;
unsigned long msr_save;
int cpu;
struct rtas_suspend_me_data *data =
(struct rtas_suspend_me_data *)info;

/*
* We use "waiting" to indicate our state. As long
* as it is >0, we are still trying to all join up.
* If it goes to 0, we have successfully joined up and
* one thread got H_CONTINUE. If any error happens,
* we set it to <0.
*/
local_irq_save(flags);
do {
rc = plpar_hcall_norets(H_JOIN);
smp_rmb();
} while (rc == H_SUCCESS && data->waiting > 0);
if (rc == H_SUCCESS)
goto out;
atomic_inc(&data->working);

/* really need to ensure MSR.EE is off for H_JOIN */
msr_save = mfmsr();
mtmsr(msr_save & ~(MSR_EE));

rc = plpar_hcall_norets(H_JOIN);

if (rc == H_CONTINUE) {
data->waiting = 0;
data->args->args[data->args->nargs] =
rtas_call(ibm_suspend_me_token, 0, 1, NULL);
for_each_possible_cpu(i)
plpar_hcall_norets(H_PROD,i);
mtmsr(msr_save);

if (rc == H_SUCCESS) {
/* This cpu was prodded and the suspend is complete. */
goto out;
} else if (rc == H_CONTINUE) {
/* All other cpus are in H_JOIN, this cpu does
* the suspend.
*/
printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n",
smp_processor_id());
data->error = rtas_call(data->token, 0, 1, NULL);

if (data->error)
printk(KERN_DEBUG "ibm,suspend-me returned %d\n",
data->error);
} else {
data->waiting = -EBUSY;
printk(KERN_ERR "Error on H_JOIN hypervisor call\n");
printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n",
smp_processor_id(), rc);
data->error = rc;
}

/* This cpu did the suspend or got an error; in either case,
* we need to prod all other other cpus out of join state.
* Extra prods are harmless.
*/
for_each_online_cpu(cpu)
plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
out:
local_irq_restore(flags);
return;
if (atomic_dec_return(&data->working) == 0)
complete(data->complete);
}

static int rtas_ibm_suspend_me(struct rtas_args *args)
{
int i;
long state;
long rc;
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
struct rtas_suspend_me_data data;
DECLARE_COMPLETION_ONSTACK(done);

if (!rtas_service_present("ibm,suspend-me"))
return -ENOSYS;

/* Make sure the state is valid */
rc = plpar_hcall(H_VASI_STATE, retbuf,
Expand All @@ -721,25 +740,23 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
return 0;
}

data.waiting = 1;
data.args = args;
atomic_set(&data.working, 0);
data.token = rtas_token("ibm,suspend-me");
data.error = 0;
data.complete = &done;

/* Call function on all CPUs. One of us will make the
* rtas call
*/
if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
data.waiting = -EINVAL;
data.error = -EINVAL;

if (data.waiting != 0)
printk(KERN_ERR "Error doing global join\n");
wait_for_completion(&done);

/* Prod each CPU. This won't hurt, and will wake
* anyone we successfully put to sleep with H_JOIN.
*/
for_each_possible_cpu(i)
plpar_hcall_norets(H_PROD, i);
if (data.error != 0)
printk(KERN_ERR "Error doing global join\n");

return data.waiting;
return data.error;
}
#else /* CONFIG_PPC_PSERIES */
static int rtas_ibm_suspend_me(struct rtas_args *args)
Expand Down
5 changes: 3 additions & 2 deletions trunk/arch/powerpc/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ void account_system_vtime(struct task_struct *tsk)
/* deltascaled includes both user and system time.
* Hence scale it based on the purr ratio to estimate
* the system time */
deltascaled = deltascaled * get_paca()->system_time /
(get_paca()->system_time + get_paca()->user_time);
if (get_paca()->user_time)
deltascaled = deltascaled * get_paca()->system_time /
(get_paca()->system_time + get_paca()->user_time);
delta += get_paca()->system_time;
get_paca()->system_time = 0;
}
Expand Down
11 changes: 11 additions & 0 deletions trunk/arch/powerpc/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,11 +699,22 @@ static int __init vdso_init(void)
vdso_data->icache_size = ppc64_caches.isize;
vdso_data->icache_line_size = ppc64_caches.iline_size;

/* XXXOJN: Blocks should be added to ppc64_caches and used instead */
vdso_data->dcache_block_size = ppc64_caches.dline_size;
vdso_data->icache_block_size = ppc64_caches.iline_size;
vdso_data->dcache_log_block_size = ppc64_caches.log_dline_size;
vdso_data->icache_log_block_size = ppc64_caches.log_iline_size;

/*
* Calculate the size of the 64 bits vDSO
*/
vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT;
DBG("vdso64_kbase: %p, 0x%x pages\n", vdso64_kbase, vdso64_pages);
#else
vdso_data->dcache_block_size = L1_CACHE_BYTES;
vdso_data->dcache_log_block_size = L1_CACHE_SHIFT;
vdso_data->icache_block_size = L1_CACHE_BYTES;
vdso_data->icache_log_block_size = L1_CACHE_SHIFT;
#endif /* CONFIG_PPC64 */


Expand Down
41 changes: 29 additions & 12 deletions trunk/arch/powerpc/kernel/vdso32/cacheflush.S
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,46 @@
*
* Flushes the data cache & invalidate the instruction cache for the
* provided range [start, end[
*
* Note: all CPUs supported by this kernel have a 128 bytes cache
* line size so we don't have to peek that info from the datapage
*/
V_FUNCTION_BEGIN(__kernel_sync_dicache)
.cfi_startproc
li r5,127
andc r6,r3,r5 /* round low to line bdy */
mflr r12
.cfi_register lr,r12
mr r11,r3
bl __get_datapage@local
mtlr r12
mr r10,r3

lwz r7,CFG_DCACHE_BLOCKSZ(r10)
addi r5,r7,-1
andc r6,r11,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */
add r8,r8,r5 /* ensure we get enough */
srwi. r8,r8,7 /* compute line count */
lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10)
srw. r8,r8,r9 /* compute line count */
crclr cr0*4+so
beqlr /* nothing to do? */
mtctr r8
mr r3,r6
1: dcbst 0,r3
addi r3,r3,128
1: dcbst 0,r6
add r6,r6,r7
bdnz 1b
sync

/* Now invalidate the instruction cache */

lwz r7,CFG_ICACHE_BLOCKSZ(r10)
addi r5,r7,-1
andc r6,r11,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */
add r8,r8,r5
lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10)
srw. r8,r8,r9 /* compute line count */
crclr cr0*4+so
beqlr /* nothing to do? */
mtctr r8
1: icbi 0,r6
addi r6,r6,128
bdnz 1b
2: icbi 0,r6
add r6,r6,r7
bdnz 2b
isync
li r3,0
blr
Expand Down
41 changes: 29 additions & 12 deletions trunk/arch/powerpc/kernel/vdso64/cacheflush.S
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,46 @@
*
* Flushes the data cache & invalidate the instruction cache for the
* provided range [start, end[
*
* Note: all CPUs supported by this kernel have a 128 bytes cache
* line size so we don't have to peek that info from the datapage
*/
V_FUNCTION_BEGIN(__kernel_sync_dicache)
.cfi_startproc
li r5,127
andc r6,r3,r5 /* round low to line bdy */
mflr r12
.cfi_register lr,r12
mr r11,r3
bl V_LOCAL_FUNC(__get_datapage)
mtlr r12
mr r10,r3

lwz r7,CFG_DCACHE_BLOCKSZ(r10)
addi r5,r7,-1
andc r6,r11,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */
add r8,r8,r5 /* ensure we get enough */
srwi. r8,r8,7 /* compute line count */
lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10)
srw. r8,r8,r9 /* compute line count */
crclr cr0*4+so
beqlr /* nothing to do? */
mtctr r8
mr r3,r6
1: dcbst 0,r3
addi r3,r3,128
1: dcbst 0,r6
add r6,r6,r7
bdnz 1b
sync

/* Now invalidate the instruction cache */

lwz r7,CFG_ICACHE_BLOCKSZ(r10)
addi r5,r7,-1
andc r6,r11,r5 /* round low to line bdy */
subf r8,r6,r4 /* compute length */
add r8,r8,r5
lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10)
srw. r8,r8,r9 /* compute line count */
crclr cr0*4+so
beqlr /* nothing to do? */
mtctr r8
1: icbi 0,r6
addi r6,r6,128
bdnz 1b
2: icbi 0,r6
add r6,r6,r7
bdnz 2b
isync
li r3,0
blr
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/powerpc/mm/stab.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <asm/lmb.h>
#include <asm/abs_addr.h>
#include <asm/firmware.h>
#include <asm/iseries/hv_call.h>

struct stab_entry {
unsigned long esid_data;
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/powerpc/platforms/40x/walnut.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
*/

#include <linux/init.h>
#include <linux/of_platform.h>

#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
#include <asm/of_platform.h>

static struct of_device_id walnut_of_bus[] = {
{ .compatible = "ibm,plb3", },
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/powerpc/platforms/44x/bamboo.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
* option) any later version.
*/
#include <linux/init.h>
#include <linux/of_platform.h>

#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
#include <asm/of_platform.h>
#include "44x.h"

static struct of_device_id bamboo_of_bus[] = {
Expand Down
Loading

0 comments on commit 39ea436

Please sign in to comment.