1272343Sngie/* $NetBSD: t_lwp_create.c,v 1.2 2012/05/22 09:23:39 martin Exp $ */
2272343Sngie
3272343Sngie/*-
4272343Sngie * Copyright (c) 2012 The NetBSD Foundation, Inc.
5272343Sngie * All rights reserved.
6272343Sngie *
7272343Sngie * Redistribution and use in source and binary forms, with or without
8272343Sngie * modification, are permitted provided that the following conditions
9272343Sngie * are met:
10272343Sngie * 1. Redistributions of source code must retain the above copyright
11272343Sngie *    notice, this list of conditions and the following disclaimer.
12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
13272343Sngie *    notice, this list of conditions and the following disclaimer in the
14272343Sngie *    documentation and/or other materials provided with the distribution.
15272343Sngie *
16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19272343Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26272343Sngie * POSSIBILITY OF SUCH DAMAGE.
27272343Sngie */
28272343Sngie
29272343Sngie/*
30272343Sngie * This code is partly based on code by Joel Sing <joel at sing.id.au>
31272343Sngie */
32272343Sngie
33272343Sngie#include <atf-c.h>
34272343Sngie#include <lwp.h>
35272343Sngie#include <stdio.h>
36272343Sngie#include <stdlib.h>
37272343Sngie#include <ucontext.h>
38272343Sngie#include <inttypes.h>
39272343Sngie#include <errno.h>
40272343Sngie
41272343Sngie#ifdef __alpha__
42272343Sngie#include <machine/alpha_cpu.h>
43272343Sngie#endif
44272343Sngie#ifdef __amd64__
45272343Sngie#include <machine/vmparam.h>
46272343Sngie#include <machine/psl.h>
47272343Sngie#endif
48272343Sngie#ifdef __hppa__
49272343Sngie#include <machine/psl.h>
50272343Sngie#endif
51272343Sngie#ifdef __i386__
52272343Sngie#include <machine/segments.h>
53272343Sngie#include <machine/psl.h>
54272343Sngie#endif
55272343Sngie#if defined(__m68k__) || defined(__sh3__) || defined __vax__
56272343Sngie#include <machine/psl.h>
57272343Sngie#endif
58272343Sngie
59272343Sngievolatile lwpid_t the_lwp_id = 0;
60272343Sngie
61272343Sngiestatic void lwp_main_func(void* arg)
62272343Sngie{
63272343Sngie	the_lwp_id = _lwp_self();
64272343Sngie	_lwp_exit();
65272343Sngie}
66272343Sngie
67272343Sngie/*
68272343Sngie * Hard to document - see usage examples below.
69272343Sngie */
70272343Sngie#define INVALID_UCONTEXT(ARCH,NAME,DESC)	\
71272343Sngiestatic void ARCH##_##NAME(ucontext_t *);	\
72272343SngieATF_TC(lwp_create_##ARCH##_fail_##NAME);	\
73272343SngieATF_TC_HEAD(lwp_create_##ARCH##_fail_##NAME, tc)	\
74272343Sngie{	\
75272343Sngie	atf_tc_set_md_var(tc, "descr", "verify rejection of invalid ucontext " \
76272343Sngie		"on " #ARCH " due to " DESC);	\
77272343Sngie}	\
78272343Sngie	\
79272343SngieATF_TC_BODY(lwp_create_##ARCH##_fail_##NAME, tc)	\
80272343Sngie{	\
81272343Sngie	ucontext_t uc;		\
82272343Sngie	lwpid_t lid;		\
83272343Sngie	int error;		\
84272343Sngie				\
85272343Sngie	getcontext(&uc);	\
86272343Sngie	uc.uc_flags = _UC_CPU;	\
87272343Sngie	ARCH##_##NAME(&uc);	\
88272343Sngie				\
89272343Sngie	error = _lwp_create(&uc, 0, &lid);	\
90272343Sngie	ATF_REQUIRE(error != 0 && errno == EINVAL);	\
91272343Sngie}	\
92272343Sngiestatic void ARCH##_##NAME(ucontext_t *uc)	\
93272343Sngie{
94272343Sngie
95272343Sngie
96272343SngieATF_TC(lwp_create_works);
97272343SngieATF_TC_HEAD(lwp_create_works, tc)
98272343Sngie{
99272343Sngie	atf_tc_set_md_var(tc, "descr", "Verify creation of a lwp and waiting"
100272343Sngie	    " for it to finish");
101272343Sngie}
102272343Sngie
103272343SngieATF_TC_BODY(lwp_create_works, tc)
104272343Sngie{
105272343Sngie	ucontext_t uc;
106272343Sngie	lwpid_t lid;
107272343Sngie	int error;
108272343Sngie	void *stack;
109272343Sngie	static const size_t ssize = 16*1024;
110272343Sngie
111272343Sngie	stack = malloc(ssize);
112272343Sngie	_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
113272343Sngie
114272343Sngie	error = _lwp_create(&uc, 0, &lid);
115272343Sngie	ATF_REQUIRE(error == 0);
116272343Sngie
117272343Sngie	error = _lwp_wait(lid, NULL);
118272343Sngie	ATF_REQUIRE(error == 0);
119272343Sngie	ATF_REQUIRE(lid == the_lwp_id);
120272343Sngie}
121272343Sngie
122272343SngieINVALID_UCONTEXT(generic, no_uc_cpu, "not setting cpu registers")
123272343Sngie	uc->uc_flags &= ~_UC_CPU;
124272343Sngie}
125272343Sngie
126272343Sngie#ifdef __alpha__
127272343SngieINVALID_UCONTEXT(alpha, pslset, "trying to clear the USERMODE flag")
128272343Sngie	uc->uc_mcontext.__gregs[_REG_PS] &= ~ALPHA_PSL_USERMODE;
129272343Sngie}
130272343SngieINVALID_UCONTEXT(alpha, pslclr, "trying to set a 'must be zero' flag")
131272343Sngie	uc->uc_mcontext.__gregs[_REG_PS] |= ALPHA_PSL_IPL_HIGH;
132272343Sngie}
133272343Sngie#endif
134272343Sngie#ifdef __amd64__
135272343SngieINVALID_UCONTEXT(amd64, untouchable_rflags, "forbidden rflags changed")
136272343Sngie	uc->uc_mcontext.__gregs[_REG_RFLAGS] |= PSL_MBZ;
137272343Sngie}
138272343Sngie/*
139272343Sngie * XXX: add invalid GS/DS selector tests
140272343Sngie */
141272343SngieINVALID_UCONTEXT(amd64, pc_too_high,
142272343Sngie     "instruction pointer outside userland address space")
143272343Sngie	uc->uc_mcontext.__gregs[_REG_RIP] = VM_MAXUSER_ADDRESS;
144272343Sngie}
145272343Sngie#endif
146272343Sngie#ifdef __arm__
147272343SngieINVALID_UCONTEXT(arm, invalid_mode, "psr or r15 set to non-user-mode")
148272343Sngie	uc->uc_mcontext.__gregs[_REG_PC] |= 0x1f /*PSR_SYS32_MODE*/;
149272343Sngie	uc->uc_mcontext.__gregs[_REG_CPSR] |= 0x03 /*R15_MODE_SVC*/;
150272343Sngie}
151272343Sngie#endif
152272343Sngie#ifdef __hppa__
153272343SngieINVALID_UCONTEXT(hppa, invalid_1, "set illegal bits in psw")
154272343Sngie	uc->uc_mcontext.__gregs[_REG_PSW] |= PSW_MBZ;
155272343Sngie}
156272343SngieINVALID_UCONTEXT(hppa, invalid_0, "clear illegal bits in psw")
157272343Sngie	uc->uc_mcontext.__gregs[_REG_PSW] &= ~PSW_MBS;
158272343Sngie}
159272343Sngie#endif
160272343Sngie#ifdef __i386__
161272343SngieINVALID_UCONTEXT(i386, untouchable_eflags, "changing forbidden eflags")
162272343Sngie	uc->uc_mcontext.__gregs[_REG_EFL] |= PSL_IOPL;
163272343Sngie}
164272343SngieINVALID_UCONTEXT(i386, priv_escalation, "modifying priviledge level")
165272343Sngie	uc->uc_mcontext.__gregs[_REG_CS] &= ~SEL_RPL;
166272343Sngie}
167272343Sngie#endif
168272343Sngie#ifdef __m68k__
169272343SngieINVALID_UCONTEXT(m68k, invalid_ps_bits,
170272343Sngie    "setting forbidden bits in the ps register")
171272343Sngie	uc->uc_mcontext.__gregs[_REG_PS] |= (PSL_MBZ|PSL_IPL|PSL_S);
172272343Sngie}
173272343Sngie#endif
174272343Sngie#ifdef __sh3__
175272343SngieINVALID_UCONTEXT(sh3, modify_userstatic,
176272343Sngie    "modifying illegal bits in the status register")
177272343Sngie	uc->uc_mcontext.__gregs[_REG_SR] |= PSL_MD;
178272343Sngie}
179272343Sngie#endif
180272343Sngie#ifdef __sparc__
181272343SngieINVALID_UCONTEXT(sparc, pc_odd, "mis-aligned instruction pointer")
182272343Sngie	uc->uc_mcontext.__gregs[_REG_PC] = 0x100002;
183272343Sngie}
184272343SngieINVALID_UCONTEXT(sparc, npc_odd, "mis-aligned next instruction pointer")
185272343Sngie	uc->uc_mcontext.__gregs[_REG_nPC] = 0x100002;
186272343Sngie}
187272343SngieINVALID_UCONTEXT(sparc, pc_null, "NULL instruction pointer")
188272343Sngie	uc->uc_mcontext.__gregs[_REG_PC] = 0;
189272343Sngie}
190272343SngieINVALID_UCONTEXT(sparc, npc_null, "NULL next instruction pointer")
191272343Sngie	uc->uc_mcontext.__gregs[_REG_nPC] = 0;
192272343Sngie}
193272343Sngie#endif
194272343Sngie#ifdef __vax__
195272343SngieINVALID_UCONTEXT(vax, psl_0, "clearing forbidden bits in psl")
196272343Sngie	uc->uc_mcontext.__gregs[_REG_PSL] &= ~(PSL_U | PSL_PREVU);
197272343Sngie}
198272343SngieINVALID_UCONTEXT(vax, psl_1, "setting forbidden bits in psl")
199272343Sngie	uc->uc_mcontext.__gregs[_REG_PSL] |= PSL_IPL | PSL_IS;
200272343Sngie}
201272343SngieINVALID_UCONTEXT(vax, psl_cm, "setting CM bit in psl")
202272343Sngie	uc->uc_mcontext.__gregs[_REG_PSL] |= PSL_CM;
203272343Sngie}
204272343Sngie#endif
205272343Sngie
206272343SngieATF_TP_ADD_TCS(tp)
207272343Sngie{
208272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_works);
209272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_generic_fail_no_uc_cpu);
210272343Sngie#ifdef __alpha__
211272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_alpha_fail_pslset);
212272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_alpha_fail_pslclr);
213272343Sngie#endif
214272343Sngie#ifdef __amd64__
215272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_amd64_fail_untouchable_rflags);
216272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_amd64_fail_pc_too_high);
217272343Sngie#endif
218272343Sngie#ifdef __arm__
219272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_arm_fail_invalid_mode);
220272343Sngie#endif
221272343Sngie#ifdef __hppa__
222272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_hppa_fail_invalid_1);
223272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_hppa_fail_invalid_0);
224272343Sngie#endif
225272343Sngie#ifdef __i386__
226272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_i386_fail_untouchable_eflags);
227272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_i386_fail_priv_escalation);
228272343Sngie#endif
229272343Sngie#ifdef __m68k__
230272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_m68k_fail_invalid_ps_bits);
231272343Sngie#endif
232272343Sngie#ifdef __sh3__
233272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_sh3_fail_modify_userstatic);
234272343Sngie#endif
235272343Sngie#ifdef __sparc__
236272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_pc_odd);
237272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_npc_odd);
238272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_pc_null);
239272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_npc_null);
240272343Sngie#endif
241272343Sngie#ifdef __vax__
242272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_0);
243272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_1);
244272343Sngie	ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_cm);
245272343Sngie#endif
246272343Sngie	return atf_no_error();
247272343Sngie}
248