Subject: sysarch argument handling
To: None <netbsd-bugs@NetBSD.ORG>
From: None <r_friedl@informatik.uni-kl.de>
List: netbsd-bugs
Date: 11/15/1995 17:15:00
Currently, every sysarch sub-function does a 'copyin' for the
arguments.  This could be moved to 'sysarch', similar to 'syscall'.
It is also simpler for the emulation functions, because they don't
have to 'copyout' the the arguments.


--- /mnt/tmp/new/new/new/sys/arch/i386/i386/sys_machdep.c	Sun Oct 15 11:35:32 1995
+++ arch/i386/i386/sys_machdep.c	Sun Nov  5 22:22:48 1995
@@ -145,26 +145,23 @@
 }
 
 int
-i386_get_ldt(p, args, retval)
+i386_get_ldt(p, v, retval)
 	struct proc *p;
-	char *args;
+	void *v;
 	register_t *retval;
 {
 	int error;
 	struct pcb *pcb = &p->p_addr->u_pcb;
 	int nldt, num;
 	union descriptor *lp;
-	struct i386_get_ldt_args ua;
-
-	if (error = copyin(args, &ua, sizeof(ua)))
-		return (error);
+	struct i386_get_ldt_args *uap = v;
 
 #ifdef	DEBUG
-	printf("i386_get_ldt: start=%d num=%d descs=%x\n", ua.start,
-	    ua.num, ua.desc);
+	printf("i386_get_ldt: start=%d num=%d descs=%x\n", uap->start,
+	    uap->num, uap->desc);
 #endif
 
-	if (ua.start < 0 || ua.num < 0)
+	if (uap->start < 0 || uap->num < 0)
 		return (EINVAL);
 
 	if (pcb->pcb_flags & PCB_USER_LDT) {
@@ -175,13 +172,13 @@
 		lp = ldt;
 	}
 
-	if (ua.start > nldt)
+	if (uap->start > nldt)
 		return (EINVAL);
 
-	lp += ua.start;
-	num = min(ua.num, nldt - ua.start);
+	lp += uap->start;
+	num = min(uap->num, nldt - uap->start);
 
-	if (error = copyout(lp, ua.desc, num * sizeof(union descriptor)))
+	if (error = copyout(lp, uap->desc, num * sizeof(union descriptor)))
 		return (error);
 
 	*retval = num;
@@ -189,33 +186,30 @@
 }
 
 int
-i386_set_ldt(p, args, retval)
+i386_set_ldt(p, v, retval)
 	struct proc *p;
-	char *args;
+	void *v;
 	register_t *retval;
 {
 	int error, i, n;
 	struct pcb *pcb = &p->p_addr->u_pcb;
 	int fsslot, gsslot;
 	int s;
-	struct i386_set_ldt_args ua;
+	struct i386_set_ldt_args *uap = v;
 	union descriptor desc;
 
-	if (error = copyin(args, &ua, sizeof(ua)))
-		return (error);
-
 #ifdef	DEBUG
-	printf("i386_set_ldt: start=%d num=%d descs=%x\n", ua.start,
-	    ua.num, ua.desc);
+	printf("i386_set_ldt: start=%d num=%d descs=%x\n", uap->start,
+	    uap->num, uap->desc);
 #endif
 
-	if (ua.start < 0 || ua.num < 0)
+	if (uap->start < 0 || uap->num < 0)
 		return (EINVAL);
-	if (ua.start > 8192 || (ua.start + ua.num) > 8192)
+	if (uap->start > 8192 || (uap->start + uap->num) > 8192)
 		return (EINVAL);
 
 	/* allocate user ldt */
-	if (pcb->pcb_ldt == 0 || (ua.start + ua.num) > pcb->pcb_ldt_len) {
+	if (pcb->pcb_ldt == 0 || (uap->start + uap->num) > pcb->pcb_ldt_len) {
 		size_t old_len, new_len;
 		union descriptor *old_ldt, *new_ldt;
 
@@ -227,7 +221,7 @@
 			old_ldt = ldt;
 			pcb->pcb_ldt_len = 512;
 		}
-		while ((ua.start + ua.num) > pcb->pcb_ldt_len)
+		while ((uap->start + uap->num) > pcb->pcb_ldt_len)
 			pcb->pcb_ldt_len *= 2;
 		new_len = pcb->pcb_ldt_len * sizeof(union descriptor);
 		new_ldt = (union descriptor *)kmem_alloc(kernel_map, new_len);
@@ -256,8 +250,8 @@
 	gsslot = IDXSEL(pcb->pcb_gs);
 
 	/* Check descriptors for access violations. */
-	for (i = 0, n = ua.start; i < ua.num; i++, n++) {
-		if (error = copyin(&ua.desc[i], &desc, sizeof(desc)))
+	for (i = 0, n = uap->start; i < uap->num; i++, n++) {
+		if (error = copyin(&uap->desc[i], &desc, sizeof(desc)))
 			return (error);
 
 		switch (desc.sd.sd_type) {
@@ -302,14 +296,14 @@
 	s = splhigh();
 
 	/* Now actually replace the descriptors. */
-	for (i = 0, n = ua.start; i < ua.num; i++, n++) {
-		if (error = copyin(&ua.desc[i], &desc, sizeof(desc)))
+	for (i = 0, n = uap->start; i < uap->num; i++, n++) {
+		if (error = copyin(&uap->desc[i], &desc, sizeof(desc)))
 			goto out;
 
 		pcb->pcb_ldt[n] = desc;
 	}
 
-	*retval = ua.start;
+	*retval = uap->start;
 
 out:
 	splx(s);
@@ -318,22 +312,19 @@
 #endif	/* USER_LDT */
 
 int
-i386_iopl(p, args, retval)
+i386_iopl(p, v, retval)
 	struct proc *p;
-	char *args;
+	void *v;
 	register_t *retval;
 {
 	int error;
 	struct trapframe *tf = p->p_md.md_regs;
-	struct i386_iopl_args ua;
+	struct i386_iopl_args *uap = v;
 
 	if (error = suser(p->p_ucred, &p->p_acflag))
 		return error;
 
-	if (error = copyin(args, &ua, sizeof(ua)))
-		return error;
-
-	if (ua.iopl)
+	if (uap->iopl)
 		tf->tf_eflags |= PSL_IOPL;
 	else
 		tf->tf_eflags &= ~PSL_IOPL;
@@ -342,40 +333,49 @@
 }
 
 int
-i386_get_ioperm(p, args, retval)
+i386_get_ioperm(p, v, retval)
 	struct proc *p;
-	char *args;
+	void *v;
 	register_t *retval;
 {
-	int error;
 	struct pcb *pcb = &p->p_addr->u_pcb;
-	struct i386_get_ioperm_args ua;
-
-	if (error = copyin(args, &ua, sizeof(ua)))
-		return (error);
+	struct i386_get_ioperm_args *uap = v;
 
-	return copyout(pcb->pcb_iomap, ua.iomap, sizeof(pcb->pcb_iomap));
+	return copyout(pcb->pcb_iomap, uap->iomap, sizeof(pcb->pcb_iomap));
 }
 
 int
-i386_set_ioperm(p, args, retval)
+i386_set_ioperm(p, v, retval)
 	struct proc *p;
-	char *args;
+	void *v;
 	register_t *retval;
 {
 	int error;
 	struct pcb *pcb = &p->p_addr->u_pcb;
-	struct i386_set_ioperm_args ua;
+	struct i386_set_ioperm_args *uap = v;
 
 	if (error = suser(p->p_ucred, &p->p_acflag))
 		return error;
 
-	if (error = copyin(args, &ua, sizeof(ua)))
-		return (error);
-
-	return copyin(ua.iomap, pcb->pcb_iomap, sizeof(pcb->pcb_iomap));
+	return copyin(uap->iomap, pcb->pcb_iomap, sizeof(pcb->pcb_iomap));
 }
 
+#define	f(n, name)	{ n, sizeof(struct __CONCAT(name,_args)), name}
+#define	nf()		{ 0, 0, sys_nosys}
+struct sysent const sysarch_ent[] = {
+#ifdef	USER_LDT
+	f(3, i386_get_ldt),	/* 0 = i386_get_ldt */
+	f(3, i386_set_ldt),	/* 1 = i386_set_ldt */
+#else
+	nf(),
+	nf(),
+#endif
+	f(1, i386_iopl),	/* 2 = i386_iopl */
+	f(1, i386_get_ioperm),	/* 3 = i386_get_ioperm */
+	f(1, i386_set_ioperm),	/* 4 = i386_set_ioperm */
+};
+#undef	f
+#undef	nf
+#define	nsysarch_ent	(sizeof (sysarch_ent) / sizeof (*sysarch_ent))
+
 int
 sys_sysarch(p, v, retval)
 	struct proc *p;
@@ -386,34 +386,21 @@
 		syscallarg(int) op;
 		syscallarg(char *) parms;
 	} */ *uap = v;
-	int error = 0;
-
-	switch(SCARG(uap, op)) {
-#ifdef	USER_LDT
-	case I386_GET_LDT: 
-		error = i386_get_ldt(p, SCARG(uap, parms), retval);
-		break;
-
-	case I386_SET_LDT: 
-		error = i386_set_ldt(p, SCARG(uap, parms), retval);
-		break;
-#endif
+	struct sysent const *sy;
+	register_t args[8];
+	int error;
+	int (*call) __P((struct proc *, void *, register_t *));
 
-	case I386_IOPL: 
-		error = i386_iopl(p, SCARG(uap, parms), retval);
-		break;
-
-	case I386_GET_IOPERM: 
-		error = i386_get_ioperm(p, SCARG(uap, parms), retval);
-		break;
-
-	case I386_SET_IOPERM: 
-		error = i386_set_ioperm(p, SCARG(uap, parms), retval);
-		break;
-
-	default:
-		error = EINVAL;
-		break;
-	}
-	return (error);
+	call = sys_nosys;
+	if (SCARG(uap, op) >= nsysarch_ent)
+		goto cont;
+	sy = sysarch_ent + SCARG(uap, op);
+	call = sy->sy_call;
+	if (sy->sy_argsize &&
+	    (error = copyin(SCARG(uap, parms), args, sy->sy_argsize)))
+		return error;
+  cont:
+	return (call(p, args, retval));
 }
--- /mnt/tmp/new/new/new/sys/arch/i386/include/sysarch.h	Sat Oct 14 02:57:52 1995
+++ arch/i386/include/sysarch.h	Sun Nov  5 22:38:45 1995
@@ -42,7 +42,7 @@
 int i386_iopl __P((int));
 int i386_get_ioperm __P((u_long *));
 int i386_set_ioperm __P((u_long *));
-int sysarch __P((int, char *));
+int sysarch __P((u_int, void *));
 #endif
 
 #endif /* !_I386_SYSARCH_H_ */
--- /mnt/tmp/new/new/new/sys/arch/i386/i386/linux_machdep.c	Sat Oct 14 02:56:36 1995
+++ arch/i386/i386/linux_machdep.c	Sun Nov  5 22:34:35 1995
@@ -269,21 +269,12 @@
 {
 	struct i386_get_ldt_args gl;
 	int error;
-	caddr_t sg;
-	char *parms;
-
-	sg = stackgap_init(p->p_emul);
 
 	gl.start = 0;
 	gl.desc = SCARG(uap, ptr);
 	gl.num = SCARG(uap, bytecount) / sizeof(union descriptor);
 
-	parms = stackgap_alloc(&sg, sizeof(gl));
-
-	if (error = copyout(&gl, parms, sizeof(gl)))
-		return (error);
-
-	if (error = i386_get_ldt(p, parms, retval))
+	if (error = i386_get_ldt(p, &gl, retval))
 		return (error);
 
 	*retval *= sizeof(union descriptor);
@@ -316,7 +307,6 @@
 	struct i386_set_ldt_args sl;
 	int error;
 	caddr_t sg;
-	char *parms;
 
 	if (SCARG(uap, bytecount) != sizeof(ldt_info))
 		return (EINVAL);
@@ -347,14 +337,10 @@
 	    ldt_info.entry_number, ldt_info.base_addr, ldt_info.limit);
 #endif
 
-	parms = stackgap_alloc(&sg, sizeof(sl));
-
 	if (error = copyout(&sd, sl.desc, sizeof(sd)))
 		return (error);
-	if (error = copyout(&sl, parms, sizeof(sl)))
-		return (error);
 
-	if (error = i386_set_ldt(p, parms, retval))
+	if (error = i386_set_ldt(p, &sl, retval))
 		return (error);
 
 	*retval = 0;
--- /mnt/tmp/new/new/new/sys/arch/i386/i386/svr4_machdep.c	Sat Oct 14 02:56:51 1995
+++ arch/i386/i386/svr4_machdep.c	Sun Nov  5 22:49:21 1995
@@ -402,8 +402,7 @@
 	case SVR4_SYSARCH_DSCR:
 #ifdef USER_LDT
 		{
-			struct i386_set_ldt_args sa, *sap;
-			struct sys_sysarch_args ua;
+			struct i386_set_ldt_args sa;
 
 			struct svr4_ssd ssd;
 			union descriptor bsd;
@@ -445,23 +444,12 @@
 			sa.start = IDXSEL(ssd.selector);
 			sa.desc = stackgap_alloc(&sg, sizeof(union descriptor));
 			sa.num = 1;
-			sap = stackgap_alloc(&sg,
-					     sizeof(struct i386_set_ldt_args));
-
-			if ((error = copyout(&sa, sap, sizeof(sa))) != 0) {
-				printf("Cannot copyout args\n");
-				return error;
-			}
-
-			SCARG(&ua, op) = I386_SET_LDT;
-			SCARG(&ua, parms) = (char *) sap;
-
 			if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) {
 				printf("Cannot copyout desc\n");
 				return error;
 			}
 
-			return sys_sysarch(p, &ua, retval);
+			return i386_set_ldt(p, &sa, retval);
 		}
 #endif