Commit cab0d85c authored by Linus Torvalds's avatar Linus Torvalds

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
parents 57ed609d 3c5cffb6
...@@ -577,16 +577,16 @@ static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment