Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implement copyout.9 and a draft of pmap_load with various fixes

Fix toolchain to not add underscores to C symbols when calling them from assembly
(define the builtin NO_LEADING_UNDERSCORE)

Fix intr.h, put _splraise() definition in intr.c

Add empty files for uart and timer SoC peripherals

Add information about files containing copyin/copyout/etc implementations for other archs in TODO file

Add a few defines in genassym.cf
  • Loading branch information...
commit 2f1952fcac7b6917e6b70be93bda26c454d7d456 1 parent 9d7eeea
Yann Sionneau authored
View
13 TODO
@@ -7,3 +7,16 @@ LM32 port TODO:
- make sure it's fine to hardwire CLKF_USERMOD to 0 or 1 (this and the following one seem to be used for statistics purposes only)
- make sure it's fine to hardwire CLKF_INTR to 0 or 1
- Do I need to implement cpu_did_resched() ?
+- implement copyin/copyout/copyinstr
+ - amd64: sys/arch/amd64/amd64/copy.S:ENTRY(copyout)
+ - arm: sys/arch/arm/arm/bcopyinout_xscale.S:ENTRY(copyout)
+ - hppa: sys/arch/hppa/hppa/copy.S: * copyin/copyout, fuword/suword, etc.
+ - i386: sys/arch/i386/i386/copy.S:ENTRY(copyout)
+ - ia64: sys/arch/ia64/ia64/support.S:ENTRY(copyoutstr, 4)
+ - m68k: sys/arch/m68k/060sp/dist/os.s:_copyout: | sys/arch/m68k/m68k/copy.s:ENTRY(copyout)
+ - ppc: sys/arch/powerpc/booke/copyout.c
+ - sh3: sys/arch/sh3/sh3/locore_subr.S:ENTRY(copyout)
+ - sparc: sys/arch/sparc/sparc/locore.s:ENTRY(copyout)
+ - sparc64: sys/arch/sparc64/sparc64/copy.S:ENTRY(copyout)
+ - usermod: sys/arch/usermode/usermode/copy.c
+ - vax: sys/arch/vax/boot/boot/if_le.c: copyout(void *f, int dest, int len)
View
1  external/gpl3/gcc/dist/gcc/config/lm32/lm32-netbsd.h
@@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */
do \
{ \
NETBSD_OS_CPP_BUILTINS_ELF(); \
+ builtin_define ("__NO_LEADING_UNDERSCORES__");\
} \
while (0)
View
2  sys/arch/lm32/conf/files.lm32
@@ -1,2 +1,4 @@
include "arch/lm32/conf/majors.lm32"
+file arch/lm32/lm32/pmap.c
+file arch/lm32/lm32/copy.c
View
2  sys/arch/lm32/include/asm.h
@@ -92,6 +92,8 @@
#define NENTRY(y) _ENTRY(_C_LABEL(y))
#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)) _PROF_PROLOGUE
+#define CPUVAR(off) _C_LABEL(cpu_info_store)+__CONCAT(CPU_INFO_,off)
+
#define SET_ENTRY_SIZE(y) \
.size _C_LABEL(y), . - _C_LABEL(y)
View
4 sys/arch/lm32/include/cpu.h
@@ -51,6 +51,8 @@
#include <machine/frame.h>
#include <machine/pte.h>
+#define curcpu() (&cpu_info_store)
+
#include <sys/cpu_data.h>
#include <sys/evcnt.h>
#include <sys/device_if.h> /* for device_t */
@@ -68,6 +70,7 @@ struct cpu_info {
cpuid_t ci_cpuid;
device_t ci_dev; /* pointer to our device */
int ci_current_ipl;
+ struct lwp *ci_curlwp; /* current owner of the processor */
struct cpu_info *ci_self; /* self-pointer */
void *ci_tlog_base; /* Trap log base */
int32_t ci_tlog_offset; /* Trap log current offset */
@@ -114,7 +117,6 @@ extern struct cpu_info cpu_info_primary;
extern struct cpu_info *cpu_info_list;
extern struct cpu_info cpu_info_store;
-#define curcpu() (&cpu_info_store)
/*
* definitions of cpu-dependent requirements
View
3  sys/arch/lm32/include/pmap.h
@@ -17,4 +17,7 @@ __CTASSERT(sizeof(struct vm_page_md) == sizeof(uintptr_t)*5);
#define pmap_pte_set(p, n) do { *(p) = (n); } while (0)
#define pmap_pte_flush() /* nothing */
+void tlbflush(void);
+void pmap_load(void);
+
#endif /* !_LM32_PMAP_H_ */
View
65 sys/arch/lm32/lm32/copy.c
@@ -0,0 +1,65 @@
+/*
+ * COPYRIGHT (C) 2013 Yann Sionneau <yann.sionneau@gmail.com>
+ */
+
+#include <lm32/cpu.h>
+#include <lm32/pmap.h>
+#include <lm32/vmparam.h>
+#include <sys/lwp.h>
+#include <sys/errno.h>
+
+void do_pmap_load(void);
+int copyout(const void *kaddr, void *uaddr, size_t len);
+
+void do_pmap_load(void)
+{
+ struct lwp *current_lwp = curcpu()->ci_curlwp;
+
+ do {
+ current_lwp->l_nopreempt++;
+ pmap_load();
+ current_lwp->l_nopreempt--;
+
+ if (current_lwp->l_nopreempt == 0)
+ {
+ if (current_lwp->l_dopreempt != 0)
+ kpreempt(0);
+ }
+
+ } while (curcpu()->ci_want_pmapload != 0);
+
+}
+
+int copyout(const void *kaddr, void *uaddr, size_t len)
+{
+ uint32_t *uaddr_32 = uaddr;
+ uint8_t *uaddr_8 = uaddr;
+ uint32_t *kaddr_32 = uaddr;
+ uint8_t *kaddr_8 = uaddr;
+ int count;
+
+ if ( curcpu()->ci_want_pmapload )
+ do_pmap_load();
+
+ uaddr_8 += len;
+ if ((size_t)uaddr_8 < len) /* is it correct as an overflow condition ? */
+ return EFAULT;
+ if ((size_t)uaddr_8 > VM_MAXUSER_ADDRESS)
+ return EFAULT;
+
+ count = len;
+ count >>= 2; /* count = count / 4 */
+ while ( count-- > 0)
+ *uaddr_32++ = *kaddr_32++;
+
+ count = len & 0x3; /* test if it is a multiple of 4 */
+ if (count == 0)
+ return 0;
+
+ uaddr_8 = (uint8_t *)uaddr + len - count;
+
+ while (count-- > 0)
+ *uaddr_8++ = *kaddr_8++;
+
+ return 0;
+}
View
117 sys/arch/lm32/lm32/pmap.c
@@ -0,0 +1,117 @@
+/*
+ * COPYRIGHT (C) 2013 Yann Sionneau <yann.sionneau@gmail.com>
+ */
+
+void tlbflush(void)
+{
+ /* flush DTLB */
+ asm volatile("xor r11, r11, r11\n\t"
+ "ori r11, r11, 0x3\n\t"
+ "wcsr tlbvaddr, r11" ::: "r11");
+
+ /* flush ITLB */
+ asm volatile("xor r11, r11, r11\n\t"
+ "ori r11, r11, 0x2\n\t"
+ "wcsr tlbvaddr, r11" ::: "r11");
+}
+
+/*
+ * pmap_load: perform the actual pmap switch
+ *
+ * Ensures that the current process' pmap is loaded on the current CPU's
+ * MMU and that there are no stale TLB entries.
+ *
+ * => The caller should disable kernel preemption or do check-and-retry
+ * to prevent a preemption from undoing our efforts.
+ * => This function may block.
+ */
+void
+pmap_load(void)
+{
+ struct cpu_info *ci;
+ struct pmap *pmap, *oldpmap;
+ struct lwp *l;
+ struct pcb *pcb;
+ cpuid_t cid;
+ uint64_t ncsw;
+
+ kpreempt_disable();
+ retry:
+ ci = curcpu();
+ if (!ci->ci_want_pmapload) {
+ kpreempt_enable();
+ return;
+ }
+ l = ci->ci_curlwp;
+ ncsw = l->l_ncsw;
+
+ /* should be able to take ipis. */
+ KASSERT(ci->ci_ilevel < IPL_HIGH);
+
+ KASSERT(l != NULL);
+ pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map);
+ KASSERT(pmap != pmap_kernel());
+ oldpmap = ci->ci_pmap;
+ pcb = lwp_getpcb(l);
+
+ if (pmap == oldpmap) {
+ if (!pmap_reactivate(pmap)) {
+ u_int gen = uvm_emap_gen_return();
+
+ /*
+ * pmap has been changed during deactivated.
+ * our tlb may be stale.
+ */
+
+ tlbflush();
+ uvm_emap_update(gen);
+ }
+
+ ci->ci_want_pmapload = 0;
+ kpreempt_enable();
+ return;
+ }
+
+ /*
+ * Acquire a reference to the new pmap and perform the switch.
+ */
+
+ pmap_reference(pmap);
+
+ cid = cpu_index(ci);
+ kcpuset_atomic_clear(oldpmap->pm_cpus, cid);
+ kcpuset_atomic_clear(oldpmap->pm_kernel_cpus, cid);
+
+ KASSERT(!kcpuset_isset(pmap->pm_cpus, cid));
+ KASSERT(!kcpuset_isset(pmap->pm_kernel_cpus, cid));
+
+ /*
+ * Mark the pmap in use by this CPU. Again, we must synchronize
+ * with TLB shootdown interrupts, so set the state VALID first,
+ * then register us for shootdown events on this pmap.
+ */
+ ci->ci_tlbstate = TLBSTATE_VALID;
+ kcpuset_atomic_set(pmap->pm_cpus, cid);
+ kcpuset_atomic_set(pmap->pm_kernel_cpus, cid);
+ ci->ci_pmap = pmap;
+
+
+ u_int gen = uvm_emap_gen_return();
+ cpu_load_pmap(pmap, oldpmap);
+ uvm_emap_update(gen);
+
+ ci->ci_want_pmapload = 0;
+
+ /*
+ * we're now running with the new pmap. drop the reference
+ * to the old pmap. if we block, we need to go around again.
+ */
+
+ pmap_destroy(oldpmap);
+ if (l->l_ncsw != ncsw) {
+ goto retry;
+ }
+
+ kpreempt_enable();
+}
+
View
2  sys/arch/milkymist/conf/files.milkymist
@@ -21,4 +21,6 @@ device uart: tty
attach uart at mainbus
file arch/milkymist/dev/uart.c uart needs-flag
+file arch/milkymist/milkymist/intr.c
+
include "arch/milkymist/conf/majors.milkymist"
View
0  sys/arch/milkymist/dev/timer.c
No changes.
View
0  sys/arch/milkymist/dev/uart.c
No changes.
View
3  sys/arch/milkymist/include/cpu.h
@@ -1,3 +1,6 @@
/* $NetBSD: cpu.h,v 1.3 2002/03/04 14:36:13 uch Exp $ */
+#define curcpu() (&cpu_info_store)
+extern struct cpu_info cpu_info_store;
+
#include <lm32/cpu.h>
View
32 sys/arch/milkymist/include/intr.h
@@ -37,7 +37,8 @@
#define _MACHINE_INTR_H_
#include <lm32/intr.h>
-#include <lm32/cpu.h>
+#include <machine/cpu.h>
+#include <lib/libkern/libkern.h>
/* Define the various Interrupt Priority Levels */
@@ -89,6 +90,8 @@ typedef struct {
ipl_t _ipl;
} ipl_cookie_t;
+ipl_t _splraise(ipl_t level);
+
static inline ipl_cookie_t
makeiplcookie(ipl_t ipl)
{
@@ -99,33 +102,6 @@ makeiplcookie(ipl_t ipl)
#define LM32_CSR_PSW_IE_SHIFT (0x0)
#define LM32_CSR_PSW_IE (1 << LM32_CSR_PSW_IE_SHIFT)
-
-static inline ipl_t _splraise(ipl_t level)
-{
- struct cpu_info *ci = curcpu();
- ipl_t olevel;
- int psw;
-
- if (ci->ci_current_ipl == level)
- return level;
- olevel = ci->ci_current_ipl;
-
-// KASSERT(level < NIPL);
-
- ci->ci_current_ipl = max(level, olevel);
-
- asm volatile("rcsr %0, PSW" : "=r"(psw) :: );
-
- if (level == IPL_NONE)
- psw |= LM32_CSR_PSW_IE;
- else
- psw &= ~(LM32_CSR_PSW_IE);
-
- asm volatile("wcsr PSW, %0" :: "r"(psw) : );
-
- return olevel;
-}
-
static inline int
splraiseipl(ipl_cookie_t icookie)
{
View
12 sys/arch/milkymist/milkymist/genassym.cf
@@ -34,7 +34,9 @@
include <machine/pte.h>
include <machine/vmparam.h>
-
+include <machine/types.h>
+include <sys/cpu.h>
+#include <sys/lwp.h>
# general constants
define PAGE_SIZE PAGE_SIZE
@@ -47,3 +49,11 @@ define PG_RO PG_RO
define PG_RW PG_RW
define PG_PROT PG_PROT
define PG_FRAME PG_FRAME
+
+
+define CPU_INFO_SELF offsetof(struct cpu_info, ci_self)
+define CPU_INFO_CURLWP offsetof(struct cpu_info, ci_curlwp)
+
+
+define L_NOPREEMPT offsetof(struct lwp, l_nopreempt)
+define L_DOPREEMPT offsetof(struct lwp, l_dopreempt)
View
32 sys/arch/milkymist/milkymist/intr.c
@@ -0,0 +1,32 @@
+/*
+ * COPYRIGHT (C) 2013 Yann Sionneau <yann.sionneau@gmail.com>
+ */
+
+#include <lm32/cpu.h>
+#include <lib/libkern/libkern.h>
+
+ipl_t _splraise(ipl_t level)
+{
+ struct cpu_info *ci = curcpu();
+ ipl_t olevel;
+ int psw;
+
+ if (ci->ci_current_ipl == level)
+ return level;
+ olevel = ci->ci_current_ipl;
+
+// KASSERT(level < NIPL);
+
+ ci->ci_current_ipl = max(level, olevel);
+
+ asm volatile("rcsr %0, PSW" : "=r"(psw) :: );
+
+ if (level == IPL_NONE)
+ psw |= LM32_CSR_PSW_IE;
+ else
+ psw &= ~(LM32_CSR_PSW_IE);
+
+ asm volatile("wcsr PSW, %0" :: "r"(psw) : );
+
+ return olevel;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.