vmm: refactor userspace's emsr_fakewrite()
[akaros.git] / kern / include / ros / procinfo.h
1 /* See COPYRIGHT for copyright information. */
2
3 #pragma once
4
5 #include <ros/memlayout.h>
6 #include <ros/common.h>
7 #include <ros/resource.h>
8 #include <ros/atomic.h>
9 #include <ros/arch/arch.h>
10 #include <ros/cpu_feat.h>
11 #include <string.h>
12
13 /* Process creation flags */
14 #define PROC_DUP_FGRP                   1
15
16 #define PROCINFO_MAX_ARGP 32
17 #define PROCINFO_ARGBUF_SIZE 3072
18
19 #ifdef ROS_KERNEL
20 #include <sys/queue.h>
21 #endif /* ROS_KERNEL */
22
23 /* Not necessary to expose all of this, but it doesn't hurt, and is convenient
24  * for the kernel.  Need to do some acrobatics for the TAILQ_ENTRY. */
25 struct vcore;
26 struct vcore {
27 #ifdef ROS_KERNEL
28         TAILQ_ENTRY(vcore)              list;
29 #else /* userspace */
30         void                            *dummy_ptr1;
31         void                            *dummy_ptr2;
32 #endif /* ROS_KERNEL */
33         uint32_t                        pcoreid;
34         bool                            valid;
35         /* these two differ when a preempt is in flight. */
36         uint32_t                        nr_preempts_sent;
37         uint32_t                        nr_preempts_done;
38         uint64_t                        preempt_pending;
39         /* A process can see cumulative runtime as of the last resume, and can
40          * also calculate runtime in this interval, by adding (ns - resume) +
41          * total. */
42         uint64_t                        resume_ticks;   /* TSC at resume time */
43         /* ticks up to last offlining */
44         uint64_t                        total_ticks;
45 };
46
47 struct pcore {
48         uint32_t                        vcoreid;
49         bool                            valid;
50 };
51
52 typedef struct procinfo {
53         pid_t pid;
54         pid_t ppid;
55         size_t max_vcores;      /* TODO: change to a uint32_t */
56         uint64_t tsc_freq;
57         uint64_t timing_overhead;
58         uintptr_t program_end;
59         /* glibc relies on stuff above this point.  if you change it, you need
60          * to rebuild glibc. */
61         bool is_mcp;                    /* is in multi mode */
62         unsigned long                   res_grant[MAX_NUM_RESOURCES];
63         struct vcore                    vcoremap[MAX_NUM_CORES];
64         uint32_t                        num_vcores;
65         struct pcore                    pcoremap[MAX_NUM_CORES];
66         seq_ctr_t                       coremap_seqctr;
67 } procinfo_t;
68 #define PROCINFO_NUM_PAGES  ((sizeof(procinfo_t)-1)/PGSIZE + 1)
69
70 /* We align this so that the kernel can easily allocate it in the BSS */
71 struct proc_global_info {
72         unsigned long cpu_feats[__NR_CPU_FEAT_BITS];
73         uint64_t x86_default_xcr0;
74         uint64_t tsc_freq;
75         uint64_t tsc_overhead;
76         uint64_t bus_freq;
77         uint64_t walltime_ns_last;
78         uint64_t tsc_cycles_last;
79 } __attribute__((aligned(PGSIZE)));
80 #define PROCGINFO_NUM_PAGES  (sizeof(struct proc_global_info) / PGSIZE)
81
82 #ifdef ROS_KERNEL
83
84 /* defined in init.c */
85 extern struct proc_global_info __proc_global_info;
86
87 #else /* Userland */
88
89 #define __procinfo (*(procinfo_t*)UINFO)
90 #define __proc_global_info (*(struct proc_global_info*)UGINFO)
91
92 #include <ros/common.h>
93 #include <ros/atomic.h>
94 #include <ros/syscall.h>
95
96 /* Figure out what your vcoreid is from your pcoreid and procinfo.  Only low
97  * level or debugging code should call this. */
98 static inline uint32_t __get_vcoreid_from_procinfo(void)
99 {
100         /* The assumption is that any IPIs/KMSGs would knock userspace into the
101          * kernel before it could read the closing of the seqctr.  Put another
102          * way, there is a 'memory barrier' between the IPI write and the seqctr
103          * write.  I think this is true. */
104         uint32_t kpcoreid, kvcoreid;
105         extern long __ros_syscall_noerrno(unsigned int _num, long _a0, long _a1,
106                                           long _a2, long _a3, long _a4,
107                                           long _a5);
108
109         seq_ctr_t old_seq;
110         do {
111                 cmb();
112                 old_seq = __procinfo.coremap_seqctr;
113                 kpcoreid = __ros_syscall_noerrno(SYS_getpcoreid, 0, 0, 0, 0, 0,
114                                                  0);
115                 if (!__procinfo.pcoremap[kpcoreid].valid)
116                         continue;
117                 kvcoreid = __procinfo.pcoremap[kpcoreid].vcoreid;
118         } while (seqctr_retry(old_seq, __procinfo.coremap_seqctr));
119         return kvcoreid;
120 }
121
122 static inline uint32_t __get_vcoreid(void)
123 {
124         /* since sys_getvcoreid could lie (and might never change) */
125         return __get_vcoreid_from_procinfo();
126 }
127
128 #endif /* ifndef ROS_KERNEL */