xref: /openbmc/linux/arch/x86/um/ldt.c (revision 37e81a01)
15c48b108SAl Viro /*
25c48b108SAl Viro  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
35c48b108SAl Viro  * Licensed under the GPL
45c48b108SAl Viro  */
55c48b108SAl Viro 
65c48b108SAl Viro #include <linux/mm.h>
75c48b108SAl Viro #include <linux/sched.h>
85c48b108SAl Viro #include <linux/slab.h>
91d04c8d7SRichard Weinberger #include <linux/uaccess.h>
105c48b108SAl Viro #include <asm/unistd.h>
1137185b33SAl Viro #include <os.h>
1237185b33SAl Viro #include <skas.h>
1337185b33SAl Viro #include <sysdep/tls.h>
145c48b108SAl Viro 
1537e81a01SHans-Werner Hilse static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
1637e81a01SHans-Werner Hilse {
1737e81a01SHans-Werner Hilse 	return syscall(__NR_modify_ldt, func, ptr, bytecount);
1837e81a01SHans-Werner Hilse }
195c48b108SAl Viro 
205c48b108SAl Viro static long write_ldt_entry(struct mm_id *mm_idp, int func,
215c48b108SAl Viro 		     struct user_desc *desc, void **addr, int done)
225c48b108SAl Viro {
235c48b108SAl Viro 	long res;
245c48b108SAl Viro 	void *stub_addr;
255c48b108SAl Viro 	res = syscall_stub_data(mm_idp, (unsigned long *)desc,
265c48b108SAl Viro 				(sizeof(*desc) + sizeof(long) - 1) &
275c48b108SAl Viro 				    ~(sizeof(long) - 1),
285c48b108SAl Viro 				addr, &stub_addr);
295c48b108SAl Viro 	if (!res) {
305c48b108SAl Viro 		unsigned long args[] = { func,
315c48b108SAl Viro 					 (unsigned long)stub_addr,
325c48b108SAl Viro 					 sizeof(*desc),
335c48b108SAl Viro 					 0, 0, 0 };
345c48b108SAl Viro 		res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
355c48b108SAl Viro 				       0, addr, done);
365c48b108SAl Viro 	}
375c48b108SAl Viro 
385c48b108SAl Viro 	return res;
395c48b108SAl Viro }
405c48b108SAl Viro 
415c48b108SAl Viro /*
425c48b108SAl Viro  * In skas mode, we hold our own ldt data in UML.
435c48b108SAl Viro  * Thus, the code implementing sys_modify_ldt_skas
445c48b108SAl Viro  * is very similar to (and mostly stolen from) sys_modify_ldt
455c48b108SAl Viro  * for arch/i386/kernel/ldt.c
465c48b108SAl Viro  * The routines copied and modified in part are:
475c48b108SAl Viro  * - read_ldt
485c48b108SAl Viro  * - read_default_ldt
495c48b108SAl Viro  * - write_ldt
505c48b108SAl Viro  * - sys_modify_ldt_skas
515c48b108SAl Viro  */
525c48b108SAl Viro 
535c48b108SAl Viro static int read_ldt(void __user * ptr, unsigned long bytecount)
545c48b108SAl Viro {
555c48b108SAl Viro 	int i, err = 0;
565c48b108SAl Viro 	unsigned long size;
57b3ee571eSAl Viro 	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
585c48b108SAl Viro 
595c48b108SAl Viro 	if (!ldt->entry_count)
605c48b108SAl Viro 		goto out;
615c48b108SAl Viro 	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
625c48b108SAl Viro 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
635c48b108SAl Viro 	err = bytecount;
645c48b108SAl Viro 
655c48b108SAl Viro 	mutex_lock(&ldt->lock);
665c48b108SAl Viro 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
675c48b108SAl Viro 		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
685c48b108SAl Viro 		if (size > bytecount)
695c48b108SAl Viro 			size = bytecount;
705c48b108SAl Viro 		if (copy_to_user(ptr, ldt->u.entries, size))
715c48b108SAl Viro 			err = -EFAULT;
725c48b108SAl Viro 		bytecount -= size;
735c48b108SAl Viro 		ptr += size;
745c48b108SAl Viro 	}
755c48b108SAl Viro 	else {
765c48b108SAl Viro 		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
775c48b108SAl Viro 		     i++) {
785c48b108SAl Viro 			size = PAGE_SIZE;
795c48b108SAl Viro 			if (size > bytecount)
805c48b108SAl Viro 				size = bytecount;
815c48b108SAl Viro 			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
825c48b108SAl Viro 				err = -EFAULT;
835c48b108SAl Viro 				break;
845c48b108SAl Viro 			}
855c48b108SAl Viro 			bytecount -= size;
865c48b108SAl Viro 			ptr += size;
875c48b108SAl Viro 		}
885c48b108SAl Viro 	}
895c48b108SAl Viro 	mutex_unlock(&ldt->lock);
905c48b108SAl Viro 
915c48b108SAl Viro 	if (bytecount == 0 || err == -EFAULT)
925c48b108SAl Viro 		goto out;
935c48b108SAl Viro 
945c48b108SAl Viro 	if (clear_user(ptr, bytecount))
955c48b108SAl Viro 		err = -EFAULT;
965c48b108SAl Viro 
975c48b108SAl Viro out:
985c48b108SAl Viro 	return err;
995c48b108SAl Viro }
1005c48b108SAl Viro 
1015c48b108SAl Viro static int read_default_ldt(void __user * ptr, unsigned long bytecount)
1025c48b108SAl Viro {
1035c48b108SAl Viro 	int err;
1045c48b108SAl Viro 
1055c48b108SAl Viro 	if (bytecount > 5*LDT_ENTRY_SIZE)
1065c48b108SAl Viro 		bytecount = 5*LDT_ENTRY_SIZE;
1075c48b108SAl Viro 
1085c48b108SAl Viro 	err = bytecount;
1095c48b108SAl Viro 	/*
1105c48b108SAl Viro 	 * UML doesn't support lcall7 and lcall27.
1115c48b108SAl Viro 	 * So, we don't really have a default ldt, but emulate
1125c48b108SAl Viro 	 * an empty ldt of common host default ldt size.
1135c48b108SAl Viro 	 */
1145c48b108SAl Viro 	if (clear_user(ptr, bytecount))
1155c48b108SAl Viro 		err = -EFAULT;
1165c48b108SAl Viro 
1175c48b108SAl Viro 	return err;
1185c48b108SAl Viro }
1195c48b108SAl Viro 
1205c48b108SAl Viro static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
1215c48b108SAl Viro {
122b3ee571eSAl Viro 	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
1235c48b108SAl Viro 	struct mm_id * mm_idp = &current->mm->context.id;
1245c48b108SAl Viro 	int i, err;
1255c48b108SAl Viro 	struct user_desc ldt_info;
1265c48b108SAl Viro 	struct ldt_entry entry0, *ldt_p;
1275c48b108SAl Viro 	void *addr = NULL;
1285c48b108SAl Viro 
1295c48b108SAl Viro 	err = -EINVAL;
1305c48b108SAl Viro 	if (bytecount != sizeof(ldt_info))
1315c48b108SAl Viro 		goto out;
1325c48b108SAl Viro 	err = -EFAULT;
1335c48b108SAl Viro 	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
1345c48b108SAl Viro 		goto out;
1355c48b108SAl Viro 
1365c48b108SAl Viro 	err = -EINVAL;
1375c48b108SAl Viro 	if (ldt_info.entry_number >= LDT_ENTRIES)
1385c48b108SAl Viro 		goto out;
1395c48b108SAl Viro 	if (ldt_info.contents == 3) {
1405c48b108SAl Viro 		if (func == 1)
1415c48b108SAl Viro 			goto out;
1425c48b108SAl Viro 		if (ldt_info.seg_not_present == 0)
1435c48b108SAl Viro 			goto out;
1445c48b108SAl Viro 	}
1455c48b108SAl Viro 
1465c48b108SAl Viro 	mutex_lock(&ldt->lock);
1475c48b108SAl Viro 
1485c48b108SAl Viro 	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
1495c48b108SAl Viro 	if (err)
1505c48b108SAl Viro 		goto out_unlock;
1515c48b108SAl Viro 
1525c48b108SAl Viro 	if (ldt_info.entry_number >= ldt->entry_count &&
1535c48b108SAl Viro 	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
1545c48b108SAl Viro 		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
1555c48b108SAl Viro 		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
1565c48b108SAl Viro 		     i++) {
1575c48b108SAl Viro 			if (i == 0)
1585c48b108SAl Viro 				memcpy(&entry0, ldt->u.entries,
1595c48b108SAl Viro 				       sizeof(entry0));
1605c48b108SAl Viro 			ldt->u.pages[i] = (struct ldt_entry *)
1615c48b108SAl Viro 				__get_free_page(GFP_KERNEL|__GFP_ZERO);
1625c48b108SAl Viro 			if (!ldt->u.pages[i]) {
1635c48b108SAl Viro 				err = -ENOMEM;
1645c48b108SAl Viro 				/* Undo the change in host */
1655c48b108SAl Viro 				memset(&ldt_info, 0, sizeof(ldt_info));
1665c48b108SAl Viro 				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
1675c48b108SAl Viro 				goto out_unlock;
1685c48b108SAl Viro 			}
1695c48b108SAl Viro 			if (i == 0) {
1705c48b108SAl Viro 				memcpy(ldt->u.pages[0], &entry0,
1715c48b108SAl Viro 				       sizeof(entry0));
1725c48b108SAl Viro 				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
1735c48b108SAl Viro 				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
1745c48b108SAl Viro 			}
1755c48b108SAl Viro 			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
1765c48b108SAl Viro 		}
1775c48b108SAl Viro 	}
1785c48b108SAl Viro 	if (ldt->entry_count <= ldt_info.entry_number)
1795c48b108SAl Viro 		ldt->entry_count = ldt_info.entry_number + 1;
1805c48b108SAl Viro 
1815c48b108SAl Viro 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
1825c48b108SAl Viro 		ldt_p = ldt->u.entries + ldt_info.entry_number;
1835c48b108SAl Viro 	else
1845c48b108SAl Viro 		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
1855c48b108SAl Viro 			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
1865c48b108SAl Viro 
1875c48b108SAl Viro 	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
1885c48b108SAl Viro 	   (func == 1 || LDT_empty(&ldt_info))) {
1895c48b108SAl Viro 		ldt_p->a = 0;
1905c48b108SAl Viro 		ldt_p->b = 0;
1915c48b108SAl Viro 	}
1925c48b108SAl Viro 	else{
1935c48b108SAl Viro 		if (func == 1)
1945c48b108SAl Viro 			ldt_info.useable = 0;
1955c48b108SAl Viro 		ldt_p->a = LDT_entry_a(&ldt_info);
1965c48b108SAl Viro 		ldt_p->b = LDT_entry_b(&ldt_info);
1975c48b108SAl Viro 	}
1985c48b108SAl Viro 	err = 0;
1995c48b108SAl Viro 
2005c48b108SAl Viro out_unlock:
2015c48b108SAl Viro 	mutex_unlock(&ldt->lock);
2025c48b108SAl Viro out:
2035c48b108SAl Viro 	return err;
2045c48b108SAl Viro }
2055c48b108SAl Viro 
2065c48b108SAl Viro static long do_modify_ldt_skas(int func, void __user *ptr,
2075c48b108SAl Viro 			       unsigned long bytecount)
2085c48b108SAl Viro {
2095c48b108SAl Viro 	int ret = -ENOSYS;
2105c48b108SAl Viro 
2115c48b108SAl Viro 	switch (func) {
2125c48b108SAl Viro 		case 0:
2135c48b108SAl Viro 			ret = read_ldt(ptr, bytecount);
2145c48b108SAl Viro 			break;
2155c48b108SAl Viro 		case 1:
2165c48b108SAl Viro 		case 0x11:
2175c48b108SAl Viro 			ret = write_ldt(ptr, bytecount, func);
2185c48b108SAl Viro 			break;
2195c48b108SAl Viro 		case 2:
2205c48b108SAl Viro 			ret = read_default_ldt(ptr, bytecount);
2215c48b108SAl Viro 			break;
2225c48b108SAl Viro 	}
2235c48b108SAl Viro 	return ret;
2245c48b108SAl Viro }
2255c48b108SAl Viro 
2265c48b108SAl Viro static DEFINE_SPINLOCK(host_ldt_lock);
2275c48b108SAl Viro static short dummy_list[9] = {0, -1};
2285c48b108SAl Viro static short * host_ldt_entries = NULL;
2295c48b108SAl Viro 
2305c48b108SAl Viro static void ldt_get_host_info(void)
2315c48b108SAl Viro {
2325c48b108SAl Viro 	long ret;
2335c48b108SAl Viro 	struct ldt_entry * ldt;
2345c48b108SAl Viro 	short *tmp;
2355c48b108SAl Viro 	int i, size, k, order;
2365c48b108SAl Viro 
2375c48b108SAl Viro 	spin_lock(&host_ldt_lock);
2385c48b108SAl Viro 
2395c48b108SAl Viro 	if (host_ldt_entries != NULL) {
2405c48b108SAl Viro 		spin_unlock(&host_ldt_lock);
2415c48b108SAl Viro 		return;
2425c48b108SAl Viro 	}
2435c48b108SAl Viro 	host_ldt_entries = dummy_list+1;
2445c48b108SAl Viro 
2455c48b108SAl Viro 	spin_unlock(&host_ldt_lock);
2465c48b108SAl Viro 
2475c48b108SAl Viro 	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
2485c48b108SAl Viro 		;
2495c48b108SAl Viro 
2505c48b108SAl Viro 	ldt = (struct ldt_entry *)
2515c48b108SAl Viro 	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
2525c48b108SAl Viro 	if (ldt == NULL) {
2535c48b108SAl Viro 		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
2545c48b108SAl Viro 		       "for host ldt\n");
2555c48b108SAl Viro 		return;
2565c48b108SAl Viro 	}
2575c48b108SAl Viro 
2585c48b108SAl Viro 	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
2595c48b108SAl Viro 	if (ret < 0) {
2605c48b108SAl Viro 		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
2615c48b108SAl Viro 		goto out_free;
2625c48b108SAl Viro 	}
2635c48b108SAl Viro 	if (ret == 0) {
2645c48b108SAl Viro 		/* default_ldt is active, simply write an empty entry 0 */
2655c48b108SAl Viro 		host_ldt_entries = dummy_list;
2665c48b108SAl Viro 		goto out_free;
2675c48b108SAl Viro 	}
2685c48b108SAl Viro 
2695c48b108SAl Viro 	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
2705c48b108SAl Viro 		if (ldt[i].a != 0 || ldt[i].b != 0)
2715c48b108SAl Viro 			size++;
2725c48b108SAl Viro 	}
2735c48b108SAl Viro 
2745c48b108SAl Viro 	if (size < ARRAY_SIZE(dummy_list))
2755c48b108SAl Viro 		host_ldt_entries = dummy_list;
2765c48b108SAl Viro 	else {
2775c48b108SAl Viro 		size = (size + 1) * sizeof(dummy_list[0]);
2785c48b108SAl Viro 		tmp = kmalloc(size, GFP_KERNEL);
2795c48b108SAl Viro 		if (tmp == NULL) {
2805c48b108SAl Viro 			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
2815c48b108SAl Viro 			       "host ldt list\n");
2825c48b108SAl Viro 			goto out_free;
2835c48b108SAl Viro 		}
2845c48b108SAl Viro 		host_ldt_entries = tmp;
2855c48b108SAl Viro 	}
2865c48b108SAl Viro 
2875c48b108SAl Viro 	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
2885c48b108SAl Viro 		if (ldt[i].a != 0 || ldt[i].b != 0)
2895c48b108SAl Viro 			host_ldt_entries[k++] = i;
2905c48b108SAl Viro 	}
2915c48b108SAl Viro 	host_ldt_entries[k] = -1;
2925c48b108SAl Viro 
2935c48b108SAl Viro out_free:
2945c48b108SAl Viro 	free_pages((unsigned long)ldt, order);
2955c48b108SAl Viro }
2965c48b108SAl Viro 
2975c48b108SAl Viro long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
2985c48b108SAl Viro {
2995c48b108SAl Viro 	struct user_desc desc;
3005c48b108SAl Viro 	short * num_p;
3015c48b108SAl Viro 	int i;
3025c48b108SAl Viro 	long page, err=0;
3035c48b108SAl Viro 	void *addr = NULL;
3045c48b108SAl Viro 
3055c48b108SAl Viro 
306b3ee571eSAl Viro 	mutex_init(&new_mm->arch.ldt.lock);
3075c48b108SAl Viro 
3085c48b108SAl Viro 	if (!from_mm) {
3095c48b108SAl Viro 		memset(&desc, 0, sizeof(desc));
3105c48b108SAl Viro 		/*
3115c48b108SAl Viro 		 * Now we try to retrieve info about the ldt, we
3125c48b108SAl Viro 		 * inherited from the host. All ldt-entries found
3135c48b108SAl Viro 		 * will be reset in the following loop
3145c48b108SAl Viro 		 */
3155c48b108SAl Viro 		ldt_get_host_info();
3165c48b108SAl Viro 		for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
3175c48b108SAl Viro 			desc.entry_number = *num_p;
3185c48b108SAl Viro 			err = write_ldt_entry(&new_mm->id, 1, &desc,
3195c48b108SAl Viro 					      &addr, *(num_p + 1) == -1);
3205c48b108SAl Viro 			if (err)
3215c48b108SAl Viro 				break;
3225c48b108SAl Viro 		}
323b3ee571eSAl Viro 		new_mm->arch.ldt.entry_count = 0;
3245c48b108SAl Viro 
3255c48b108SAl Viro 		goto out;
3265c48b108SAl Viro 	}
3275c48b108SAl Viro 
3285c48b108SAl Viro 	/*
3295c48b108SAl Viro 	 * Our local LDT is used to supply the data for
3305c48b108SAl Viro 	 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
3315c48b108SAl Viro 	 * i.e., we have to use the stub for modify_ldt, which
3325c48b108SAl Viro 	 * can't handle the big read buffer of up to 64kB.
3335c48b108SAl Viro 	 */
334b3ee571eSAl Viro 	mutex_lock(&from_mm->arch.ldt.lock);
335b3ee571eSAl Viro 	if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
336b3ee571eSAl Viro 		memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
337b3ee571eSAl Viro 		       sizeof(new_mm->arch.ldt.u.entries));
3385c48b108SAl Viro 	else {
339b3ee571eSAl Viro 		i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
3405c48b108SAl Viro 		while (i-->0) {
3415c48b108SAl Viro 			page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
3425c48b108SAl Viro 			if (!page) {
3435c48b108SAl Viro 				err = -ENOMEM;
3445c48b108SAl Viro 				break;
3455c48b108SAl Viro 			}
346b3ee571eSAl Viro 			new_mm->arch.ldt.u.pages[i] =
3475c48b108SAl Viro 				(struct ldt_entry *) page;
348b3ee571eSAl Viro 			memcpy(new_mm->arch.ldt.u.pages[i],
349b3ee571eSAl Viro 			       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
3505c48b108SAl Viro 		}
3515c48b108SAl Viro 	}
352b3ee571eSAl Viro 	new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
353b3ee571eSAl Viro 	mutex_unlock(&from_mm->arch.ldt.lock);
3545c48b108SAl Viro 
3555c48b108SAl Viro     out:
3565c48b108SAl Viro 	return err;
3575c48b108SAl Viro }
3585c48b108SAl Viro 
3595c48b108SAl Viro 
3605c48b108SAl Viro void free_ldt(struct mm_context *mm)
3615c48b108SAl Viro {
3625c48b108SAl Viro 	int i;
3635c48b108SAl Viro 
364d0b5e15fSRichard Weinberger 	if (mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
365b3ee571eSAl Viro 		i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
3665c48b108SAl Viro 		while (i-- > 0)
367b3ee571eSAl Viro 			free_page((long) mm->arch.ldt.u.pages[i]);
3685c48b108SAl Viro 	}
369b3ee571eSAl Viro 	mm->arch.ldt.entry_count = 0;
3705c48b108SAl Viro }
3715c48b108SAl Viro 
3725c48b108SAl Viro int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
3735c48b108SAl Viro {
3745c48b108SAl Viro 	return do_modify_ldt_skas(func, ptr, bytecount);
3755c48b108SAl Viro }
376