Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: [S390] mm: fix mmu_gather rework [S390] mm: fix storage key handling
This commit is contained in:
commit
cab0d85c8d
|
@ -577,16 +577,16 @@ static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)
|
||||||
static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
|
static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PGSTE
|
#ifdef CONFIG_PGSTE
|
||||||
unsigned long pfn, bits;
|
unsigned long address, bits;
|
||||||
unsigned char skey;
|
unsigned char skey;
|
||||||
|
|
||||||
pfn = pte_val(*ptep) >> PAGE_SHIFT;
|
address = pte_val(*ptep) & PAGE_MASK;
|
||||||
skey = page_get_storage_key(pfn);
|
skey = page_get_storage_key(address);
|
||||||
bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
|
bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
|
||||||
/* Clear page changed & referenced bit in the storage key */
|
/* Clear page changed & referenced bit in the storage key */
|
||||||
if (bits) {
|
if (bits) {
|
||||||
skey ^= bits;
|
skey ^= bits;
|
||||||
page_set_storage_key(pfn, skey, 1);
|
page_set_storage_key(address, skey, 1);
|
||||||
}
|
}
|
||||||
/* Transfer page changed & referenced bit to guest bits in pgste */
|
/* Transfer page changed & referenced bit to guest bits in pgste */
|
||||||
pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */
|
pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */
|
||||||
|
@ -628,16 +628,16 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
|
||||||
static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
|
static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PGSTE
|
#ifdef CONFIG_PGSTE
|
||||||
unsigned long pfn;
|
unsigned long address;
|
||||||
unsigned long okey, nkey;
|
unsigned long okey, nkey;
|
||||||
|
|
||||||
pfn = pte_val(*ptep) >> PAGE_SHIFT;
|
address = pte_val(*ptep) & PAGE_MASK;
|
||||||
okey = nkey = page_get_storage_key(pfn);
|
okey = nkey = page_get_storage_key(address);
|
||||||
nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
|
nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
|
||||||
/* Set page access key and fetch protection bit from pgste */
|
/* Set page access key and fetch protection bit from pgste */
|
||||||
nkey |= (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56;
|
nkey |= (pgste_val(pgste) & (RCP_ACC_BITS | RCP_FP_BIT)) >> 56;
|
||||||
if (okey != nkey)
|
if (okey != nkey)
|
||||||
page_set_storage_key(pfn, nkey, 1);
|
page_set_storage_key(address, nkey, 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,12 +71,15 @@ static void rcu_table_freelist_callback(struct rcu_head *head)
|
||||||
|
|
||||||
void rcu_table_freelist_finish(void)
|
void rcu_table_freelist_finish(void)
|
||||||
{
|
{
|
||||||
struct rcu_table_freelist *batch = __get_cpu_var(rcu_table_freelist);
|
struct rcu_table_freelist **batchp = &get_cpu_var(rcu_table_freelist);
|
||||||
|
struct rcu_table_freelist *batch = *batchp;
|
||||||
|
|
||||||
if (!batch)
|
if (!batch)
|
||||||
return;
|
goto out;
|
||||||
call_rcu(&batch->rcu, rcu_table_freelist_callback);
|
call_rcu(&batch->rcu, rcu_table_freelist_callback);
|
||||||
__get_cpu_var(rcu_table_freelist) = NULL;
|
*batchp = NULL;
|
||||||
|
out:
|
||||||
|
put_cpu_var(rcu_table_freelist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void smp_sync(void *arg)
|
static void smp_sync(void *arg)
|
||||||
|
@ -141,20 +144,23 @@ void crst_table_free_rcu(struct mm_struct *mm, unsigned long *table)
|
||||||
{
|
{
|
||||||
struct rcu_table_freelist *batch;
|
struct rcu_table_freelist *batch;
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
if (atomic_read(&mm->mm_users) < 2 &&
|
if (atomic_read(&mm->mm_users) < 2 &&
|
||||||
cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
|
cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
|
||||||
crst_table_free(mm, table);
|
crst_table_free(mm, table);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
batch = rcu_table_freelist_get(mm);
|
batch = rcu_table_freelist_get(mm);
|
||||||
if (!batch) {
|
if (!batch) {
|
||||||
smp_call_function(smp_sync, NULL, 1);
|
smp_call_function(smp_sync, NULL, 1);
|
||||||
crst_table_free(mm, table);
|
crst_table_free(mm, table);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
batch->table[--batch->crst_index] = table;
|
batch->table[--batch->crst_index] = table;
|
||||||
if (batch->pgt_index >= batch->crst_index)
|
if (batch->pgt_index >= batch->crst_index)
|
||||||
rcu_table_freelist_finish();
|
rcu_table_freelist_finish();
|
||||||
|
out:
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
|
@ -323,16 +329,17 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table)
|
||||||
struct page *page;
|
struct page *page;
|
||||||
unsigned long bits;
|
unsigned long bits;
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
if (atomic_read(&mm->mm_users) < 2 &&
|
if (atomic_read(&mm->mm_users) < 2 &&
|
||||||
cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
|
cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
|
||||||
page_table_free(mm, table);
|
page_table_free(mm, table);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
batch = rcu_table_freelist_get(mm);
|
batch = rcu_table_freelist_get(mm);
|
||||||
if (!batch) {
|
if (!batch) {
|
||||||
smp_call_function(smp_sync, NULL, 1);
|
smp_call_function(smp_sync, NULL, 1);
|
||||||
page_table_free(mm, table);
|
page_table_free(mm, table);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
bits = (mm->context.has_pgste) ? 3UL : 1UL;
|
bits = (mm->context.has_pgste) ? 3UL : 1UL;
|
||||||
bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
|
bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
|
||||||
|
@ -345,6 +352,8 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table)
|
||||||
batch->table[batch->pgt_index++] = table;
|
batch->table[batch->pgt_index++] = table;
|
||||||
if (batch->pgt_index >= batch->crst_index)
|
if (batch->pgt_index >= batch->crst_index)
|
||||||
rcu_table_freelist_finish();
|
rcu_table_freelist_finish();
|
||||||
|
out:
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -308,7 +308,7 @@ static inline void SetPageUptodate(struct page *page)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_S390
|
#ifdef CONFIG_S390
|
||||||
if (!test_and_set_bit(PG_uptodate, &page->flags))
|
if (!test_and_set_bit(PG_uptodate, &page->flags))
|
||||||
page_set_storage_key(page_to_pfn(page), PAGE_DEFAULT_KEY, 0);
|
page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, 0);
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* Memory barrier must be issued before setting the PG_uptodate bit,
|
* Memory barrier must be issued before setting the PG_uptodate bit,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user