1/* $OpenBSD: cpu_full.h,v 1.5 2019/05/17 19:07:47 guenther Exp $ */
2/*
3 * Copyright (c) 2018 Philip Guenther <guenther@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef _MACHINE_CPU_FULL_H_
19#define _MACHINE_CPU_FULL_H_
20
21#include <sys/param.h> /* offsetof, PAGE_SIZE */
22#include <machine/segments.h>
23#include <machine/tss.h>
24
25/*
26 * The layout of the full per-CPU information, including TSS, GDT,
27 * trampoline stacks, and cpu_info described in <machine/cpu.h>
28 */
29struct cpu_info_full {
30 /* page mapped kRO in u-k */
31 union {
32 struct {
33 struct x86_64_tss uu_tss;
34 uint64_t uu_gdt[GDT_SIZE / 8];
35 } u_tssgdt;
36 char u_align[PAGE_SIZE];
37 } cif_RO;
38#define cif_tss cif_RO.u_tssgdt.uu_tss
39#define cif_gdt cif_RO.u_tssgdt.uu_gdt
40
41 /* start of page mapped kRW in u-k */
42 uint64_t cif_tramp_stack[(PAGE_SIZE / 4
43 - offsetof(struct cpu_info, ci_PAGEALIGN)) / sizeof(uint64_t)];
44 uint64_t cif_dblflt_stack[(PAGE_SIZE / 4) / sizeof(uint64_t)];
45 uint64_t cif_nmi_stack[(2 * PAGE_SIZE / 4) / sizeof(uint64_t)];
46
47 /*
48 * Beginning of this hangs over into the kRW page; rest is
49 * unmapped in u-k
50 */
51 struct cpu_info cif_cpu;
52} __aligned(PAGE_SIZE);
53
54/* tss, align shim, and gdt must fit in a page */
55CTASSERT(_ALIGN(sizeof(struct x86_64_tss)) +
56 sizeof(struct mem_segment_descriptor) * (NGDT_MEM + 2*NGDT_SYS)
57 < PAGE_SIZE);
58
59/* verify expected alignment */
60CTASSERT(offsetof(struct cpu_info_full, cif_cpu.ci_PAGEALIGN) % PAGE_SIZE == 0);
61
62/* verify total size is multiple of page size */
63CTASSERT(sizeof(struct cpu_info_full) % PAGE_SIZE == 0);
64
65extern struct cpu_info_full cpu_info_full_primary;
66
67/* Now make sure the cpu_info_primary macro is correct */
68CTASSERT(&cpu_info_primary - &cpu_info_full_primary.cif_cpu == 0);
69
70#endif /* _MACHINE_CPU_FULL_H_ */