"Ka'plaagh 05-Jan-1996 1930 +0000": "EB164" (Jan 5, 20:27):
>
> I'm pleased to announce that Linux is _nearly_ working
> completely on an EB164. Thanks to Jay Estabrook and Joe
> Martin, the illegal instruction problems have been fixed.
> New images will appear on Gatekeeper (Miniloader/eb164)
> overnight. I've provided a full source tree rather than
> a patch file as the changes needed are not compatible with
> EV4 based systems. I'm sure that Linus has views on how the
> code should go in but I think there should be seperation based
> on generation of Alpha chip.
I don't think a separation is needed at least for the EV5: the changes
aren't that large between then EV4 and the EV5.
> The changes required were all to do with ASNs. EV5 allows
> finer control of page table entries and associated with each
> page table entry is an 8-bit ASN that should be unique for the
> set of active processes. The fact that there are less ASNs than
> there are possible processes means that some form of dynamic
> ASN allocation is needed whenever you swap context. The illegal
> instruction problems were as a result of not properly flushing
> a given process's page table entries when it was swapped out.
I just wrote my own version of the ASN code, and while I obviously can't
check, it's so cleverly done that it just _has_ to work. I'll put this
into the 1.3.55 kernel source tree, which I'll make available later
today on the normal sites.
The ASN code actually resulted in very few changes, so I'm including the
diff here for comments..
Linus
----------
diff -u --recursive --new-file uni-version/linux/include/asm-alpha/mmu_context.h linux/include/asm-alpha/mmu_context.h
--- uni-version/linux/include/asm-alpha/mmu_context.h Thu Jan 1 00:00:00 1970
+++ linux/include/asm-alpha/mmu_context.h Sat Jan 6 13:12:39 1996
@@ -0,0 +1,58 @@
+#ifndef __ALPHA_MMU_CONTEXT_H
+#define __ALPHA_MMU_CONTEXT_H
+
+/*
+ * get a new mmu context..
+ *
+ * Copyright (C) 1996, Linus Torvalds
+ */
+
+#include <asm/pgtable.h>
+
+/*
+ * The maximum ASN's the processor supports. On the EV4 this doesn't
+ * matter as the pal-code doesn't use the ASNs anyway, on the EV5
+ * EV5 this is 127.
+ */
+#define MAX_ASN 127
+
+#define ASN_VERSION_SHIFT 32
+#define ASN_VERSION_MASK ((~0UL) << ASN_VERSION_SHIFT)
+#define ASN_FIRST_VERSION (1UL << ASN_VERSION_SHIFT)
+
+/*
+ * NOTE! The way this is set up, the high bits of the "asn_cache" (and
+ * the "mm->context") are the ASN _version_ code. A version of 0 is
+ * always considered invalid, so to invalidate another process you only
+ * need to do "p->mm->context = 0".
+ *
+ * If we need more ASN's than the processor has, we invalidate the old
+ * user TLB's (tbiap()) and start a new ASN version. That will automatically
+ * force a new asn for any other processes the next time they want to
+ * run.
+ */
+extern inline void get_mmu_context(struct task_struct *p)
+{
+ static unsigned long asn_cache = ASN_FIRST_VERSION;
+ struct mm_struct * mm = p->mm;
+ unsigned long asn = mm->context;
+
+ /* Check if our ASN is of an older version and thus invalid */
+ if ((asn_cache ^ asn) & ASN_VERSION_MASK) {
+ /* get a new asn of the current version */
+ asn = asn_cache++;
+ /* check if it's legal.. */
+ if ((asn & ~ASN_VERSION_MASK) > MAX_ASN) {
+ /* start a new version, invalidate all old asn's */
+ tbiap();
+ asn_cache = (asn_cache & ASN_VERSION_MASK) + ASN_FIRST_VERSION;
+ if (!asn_cache)
+ asn_cache = ASN_FIRST_VERSION;
+ asn = asn_cache++;
+ }
+ mm->context = asn; /* full version + asn */
+ p->tss.asn = asn & ~ASN_VERSION_MASK; /* just asn */
+ }
+}
+
+#endif
diff -u --recursive --new-file uni-version/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- uni-version/linux/include/asm-alpha/pgtable.h Thu Jan 4 14:21:25 1996
+++ linux/include/asm-alpha/pgtable.h Sat Jan 6 13:24:18 1996
@@ -39,7 +39,10 @@
*/
static inline void invalidate_mm(struct mm_struct *mm)
{
- tbiap();
+ if (mm != current->mm)
+ mm->context = 0;
+ else
+ tbiap();
}
/*
@@ -53,7 +56,12 @@
static inline void invalidate_page(struct vm_area_struct *vma,
unsigned long addr)
{
- tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
+ struct mm_struct * mm = vma->vm_mm;
+
+ if (mm != current->mm)
+ mm->context = 0;
+ else
+ tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
}
/*
@@ -63,7 +71,10 @@
static inline void invalidate_range(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
- tbiap();
+ if (mm != current->mm)
+ mm->context = 0;
+ else
+ tbiap();
}
/* Certain architectures need to do special things when pte's
diff -u --recursive --new-file uni-version/linux/include/asm-i386/mmu_context.h linux/include/asm-i386/mmu_context.h
--- uni-version/linux/include/asm-i386/mmu_context.h Thu Jan 1 00:00:00 1970
+++ linux/include/asm-i386/mmu_context.h Sat Jan 6 12:54:55 1996
@@ -0,0 +1,9 @@
+#ifndef __I386_MMU_CONTEXT_H
+#define __I386_MMU_CONTEXT_H
+
+/*
+ * get a new mmu context.. x86's don't know about contexts.
+ */
+#define get_mmu_context(x) do { } while (0)
+
+#endif
diff -u --recursive --new-file uni-version/linux/kernel/sched.c linux/kernel/sched.c
--- uni-version/linux/kernel/sched.c Tue Nov 28 07:05:23 1995
+++ linux/kernel/sched.c Sat Jan 6 12:51:39 1996
@@ -31,6 +31,7 @@
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
#include <linux/timex.h>
@@ -338,6 +339,7 @@
timer.function = process_timeout;
add_timer(&timer);
}
+ get_mmu_context(next);
switch_to(next);
if (timeout)
del_timer(&timer);
----------