Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 95338
b: refs/heads/master
c: 53492b1
h: refs/heads/master
v: v3
  • Loading branch information
Gerald Schaefer authored and Martin Schwidefsky committed Apr 30, 2008
1 parent b5e7b51 commit 2194ee9
Show file tree
Hide file tree
Showing 15 changed files with 438 additions and 43 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: 2e5061e40af88070984e3769eafb5a06022375fd
refs/heads/master: 53492b1de46a7576170e865062ffcfc93bb5650b
16 changes: 16 additions & 0 deletions trunk/arch/s390/kernel/early.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,19 @@ static noinline __init void setup_lowcore_early(void)
s390_base_pgm_handler_fn = early_pgm_check_handler;
}

static noinline __init void setup_hpage(void)
{
#ifndef CONFIG_DEBUG_PAGEALLOC
unsigned int facilities;

facilities = stfl();
if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29)))
return;
machine_flags |= MACHINE_FLAG_HPAGE;
__ctl_set_bit(0, 23);
#endif
}

static __init void detect_mvpg(void)
{
#ifndef CONFIG_64BIT
Expand Down Expand Up @@ -360,6 +373,8 @@ static __init void detect_machine_facilities(void)
facilities = stfl();
if (facilities & (1 << 28))
machine_flags |= MACHINE_FLAG_IDTE;
if (facilities & (1 << 23))
machine_flags |= MACHINE_FLAG_PFMF;
if (facilities & (1 << 4))
machine_flags |= MACHINE_FLAG_MVCOS;
#endif
Expand Down Expand Up @@ -388,6 +403,7 @@ void __init startup_init(void)
detect_diag9c();
detect_diag44();
detect_machine_facilities();
setup_hpage();
sclp_read_info_early();
sclp_facilities_detect();
memsize = sclp_memory_detect();
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/s390/kernel/head64.S
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ startup_continue:
# virtual and never return ...
.align 16
.Lentry:.quad 0x0000000180000000,_stext
.Lctl: .quad 0x04b50002 # cr0: various things
.Lctl: .quad 0x04350002 # cr0: various things
.quad 0 # cr1: primary space segment table
.quad .Lduct # cr2: dispatchable unit control table
.quad 0 # cr3: instruction authorization
Expand Down
10 changes: 7 additions & 3 deletions trunk/arch/s390/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,9 @@ static void __init setup_hwcaps(void)
elf_hwcap |= 1UL << 6;
}

if (MACHINE_HAS_HPAGE)
elf_hwcap |= 1UL << 7;

switch (cpuinfo->cpu_id.machine) {
case 0x9672:
#if !defined(CONFIG_64BIT)
Expand Down Expand Up @@ -872,8 +875,9 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)

static int show_cpuinfo(struct seq_file *m, void *v)
{
static const char *hwcap_str[7] = {
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
static const char *hwcap_str[8] = {
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
"edat"
};
struct cpuinfo_S390 *cpuinfo;
unsigned long n = (unsigned long) v - 1;
Expand All @@ -888,7 +892,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
num_online_cpus(), loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ))%100);
seq_puts(m, "features\t: ");
for (i = 0; i < 7; i++)
for (i = 0; i < 8; i++)
if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
seq_printf(m, "%s ", hwcap_str[i]);
seq_puts(m, "\n");
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/s390/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
obj-$(CONFIG_CMM) += cmm.o

obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
3 changes: 3 additions & 0 deletions trunk/arch/s390/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/hardirq.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
#include <linux/hugetlb.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/s390_ext.h>
Expand Down Expand Up @@ -367,6 +368,8 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
}

survive:
if (is_vm_hugetlb_page(vma))
address &= HPAGE_MASK;
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
Expand Down
134 changes: 134 additions & 0 deletions trunk/arch/s390/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* IBM System z Huge TLB Page Support for Kernel.
*
* Copyright 2007 IBM Corp.
* Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
*/

#include <linux/mm.h>
#include <linux/hugetlb.h>


void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *pteptr, pte_t pteval)
{
pmd_t *pmdp = (pmd_t *) pteptr;
pte_t shadow_pteval = pteval;
unsigned long mask;

if (!MACHINE_HAS_HPAGE) {
pteptr = (pte_t *) pte_page(pteval)[1].index;
mask = pte_val(pteval) &
(_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO);
pte_val(pteval) = (_SEGMENT_ENTRY + __pa(pteptr)) | mask;
if (mm->context.noexec) {
pteptr += PTRS_PER_PTE;
pte_val(shadow_pteval) =
(_SEGMENT_ENTRY + __pa(pteptr)) | mask;
}
}

pmd_val(*pmdp) = pte_val(pteval);
if (mm->context.noexec) {
pmdp = get_shadow_table(pmdp);
pmd_val(*pmdp) = pte_val(shadow_pteval);
}
}

int arch_prepare_hugepage(struct page *page)
{
unsigned long addr = page_to_phys(page);
pte_t pte;
pte_t *ptep;
int i;

if (MACHINE_HAS_HPAGE)
return 0;

ptep = (pte_t *) pte_alloc_one(&init_mm, address);
if (!ptep)
return -ENOMEM;

pte = mk_pte(page, PAGE_RW);
for (i = 0; i < PTRS_PER_PTE; i++) {
set_pte_at(&init_mm, addr + i * PAGE_SIZE, ptep + i, pte);
pte_val(pte) += PAGE_SIZE;
}
page[1].index = (unsigned long) ptep;
return 0;
}

void arch_release_hugepage(struct page *page)
{
pte_t *ptep;

if (MACHINE_HAS_HPAGE)
return;

ptep = (pte_t *) page[1].index;
if (!ptep)
return;
pte_free(&init_mm, ptep);
page[1].index = 0;
}

pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgdp;
pud_t *pudp;
pmd_t *pmdp = NULL;

pgdp = pgd_offset(mm, addr);
pudp = pud_alloc(mm, pgdp, addr);
if (pudp)
pmdp = pmd_alloc(mm, pudp, addr);
return (pte_t *) pmdp;
}

pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgdp;
pud_t *pudp;
pmd_t *pmdp = NULL;

pgdp = pgd_offset(mm, addr);
if (pgd_present(*pgdp)) {
pudp = pud_offset(pgdp, addr);
if (pud_present(*pudp))
pmdp = pmd_offset(pudp, addr);
}
return (pte_t *) pmdp;
}

int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
{
return 0;
}

struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
int write)
{
return ERR_PTR(-EINVAL);
}

int pmd_huge(pmd_t pmd)
{
if (!MACHINE_HAS_HPAGE)
return 0;

return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
}

struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmdp, int write)
{
struct page *page;

if (!MACHINE_HAS_HPAGE)
return NULL;

page = pmd_page(*pmdp);
if (page)
page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
return page;
}
23 changes: 0 additions & 23 deletions trunk/arch/s390/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,28 +77,6 @@ void show_mem(void)
printk("%lu pages pagetables\n", global_page_state(NR_PAGETABLE));
}

static void __init setup_ro_region(void)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pte_t new_pte;
unsigned long address, end;

address = ((unsigned long)&_stext) & PAGE_MASK;
end = PFN_ALIGN((unsigned long)&_eshared);

for (; address < end; address += PAGE_SIZE) {
pgd = pgd_offset_k(address);
pud = pud_offset(pgd, address);
pmd = pmd_offset(pud, address);
pte = pte_offset_kernel(pmd, address);
new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
*pte = new_pte;
}
}

/*
* paging_init() sets up the page tables
*/
Expand All @@ -121,7 +99,6 @@ void __init paging_init(void)
clear_table((unsigned long *) init_mm.pgd, pgd_type,
sizeof(unsigned long)*2048);
vmem_map_init();
setup_ro_region();

/* enable virtual mapping in kernel mode */
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
Expand Down
Loading

0 comments on commit 2194ee9

Please sign in to comment.