The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
cross_state_manager.c
Go to the documentation of this file.
1 
35 //#ifdef HAVE_CROSS_STATE
36 
37 #define EXPORT_SYMTAB
38 #include <linux/module.h>
39 #include <linux/kernel.h>
40 #include <linux/fs.h>
41 #include <linux/cdev.h>
42 #include <linux/errno.h>
43 #include <linux/device.h>
44 #include <linux/kprobes.h>
45 #include <linux/mutex.h>
46 #include <linux/mm.h>
47 #include <linux/sched.h>
48 #include <linux/slab.h>
49 #include <linux/version.h>
50 #include <asm/tlbflush.h>
51 #include <asm/page.h>
52 #include <asm/cacheflush.h>
53 #include <linux/uaccess.h>
54 
55 #include "cross_state_manager.h"
56 
57 #define AUXILIARY_FRAMES 256
58 
59 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
60 #error Unsupported Kernel Version
61 #endif
62 
63 
64 #define SET_BIT(p,n) ((*(ulong *)(p)) |= (1LL << (n)))
65 #define CLR_BIT(p,n) ((*(ulong *)(p)) &= ~((1LL) << (n)))
66 #define GET_BIT(p,n) ((*(ulong *)(p)) & (1LL << (n)))
67 
68 // Type to access original fault handler
69 typedef void (*do_page_fault_t)(struct pt_regs*, unsigned long);
70 
71 /* FUNCTION PROTOTYPES */
72 static int rs_ktblmgr_init(void);
73 static void rs_ktblmgr_cleanup(void);
74 static int rs_ktblmgr_open(struct inode *, struct file *);
75 static int rs_ktblmgr_release(struct inode *, struct file *);
76 static long rs_ktblmgr_ioctl(struct file *, unsigned int, unsigned long);
77 
78 MODULE_LICENSE("GPL");
79 MODULE_AUTHOR("Alessandro Pellegrini <pellegrini@dis.uniroma1.it>, Francesco Quaglia <quaglia@dis.uniroma1.it>");
80 MODULE_DESCRIPTION("ROOT-Sim Multiple Page Table Kernel Module");
81 module_init(rs_ktblmgr_init);
82 module_exit(rs_ktblmgr_cleanup);
83 
84 /* MODULE VARIABLES */
85 void (*rootsim_pager)(void)=NULL;
86 
88 static int major;
89 
91 static struct class *dev_cl = NULL;
92 
94 static struct device *device = NULL;
95 
97 static DEFINE_MUTEX(rs_ktblmgr_mutex);
98 
99 struct mutex pgd_get_mutex;
100 struct mm_struct *mm_struct_addr[SIBLING_PGD];
101 void *pgd_addr[SIBLING_PGD];
102 unsigned int managed_pgds = 0;
103 struct mm_struct *original_view[SIBLING_PGD];
104 
105 /* stack of auxiliary frames - used for chnage view */
106 int stack_index = AUXILIARY_FRAMES - 1;
107 void * auxiliary_frames[AUXILIARY_FRAMES];
108 
109 int root_sim_processes[SIBLING_PGD]={[0 ... (SIBLING_PGD-1)] = -1};
110 fault_info_t *root_sim_fault_info[SIBLING_PGD];
111 
112 //#define MAX_CROSS_STATE_DEPENDENCIES 1024
113 int currently_open[SIBLING_PGD][MAX_CROSS_STATE_DEPENDENCIES];
114 int open_index[SIBLING_PGD]={[0 ... (SIBLING_PGD-1)] = -1};
115 
116 void **ancestor_pml4;
117 int restore_pml4; /* starting entry of pml4 for release operations of shadow pdp tables */
118 int restore_pml4_entries; /* entries of the pml4 involvrd in release operations of shadow pdp tables */
119 int mapped_processes; /* number of processes (application objects) mapped onto the special segment */
120 
121 ulong callback;
122 
123 struct vm_area_struct* changed_mode_mmap;
124 struct vm_operations_struct * original_vm_ops;
125 struct vm_operations_struct auxiliary_vm_ops_table;
126 struct vm_area_struct *target_vma;
127 
128 int (*original_fault_handler)(struct vm_area_struct *vma, struct vm_fault *vmf);
129 
130 static DEVICE_ATTR(multimap, S_IRUSR|S_IRGRP|S_IROTH, NULL, NULL);
131 
133 struct file_operations fops = {
134  open: rs_ktblmgr_open,
135  unlocked_ioctl: rs_ktblmgr_ioctl,
136  compat_ioctl: rs_ktblmgr_ioctl, // Nothing strange is passed, so 32 bits programs should work out of the box. Never tested, yet.
137  release: rs_ktblmgr_release
138 };
139 
141 void (*flush_tlb_all_lookup)(void) = NULL;
142 
143 static inline void rootsim_load_cr3(pgd_t *pgdir) {
144  __asm__ __volatile__ ("mov %0, %%cr3" :: "r" (__pa(pgdir)));
145 }
146 
147 static void set_single_pte_sticky_flag(void *target_address) {
148  void **pgd;
149  void **pdp;
150  void **pde;
151  void **pte;
152 
153  pgd = (void **)current->mm->pgd;
154  pdp = (void **)__va((ulong)pgd[PML4(target_address)] & 0xfffffffffffff000);
155  pde = (void **)__va((ulong)pdp[PDP(target_address)] & 0xfffffffffffff000);
156  pte = (void **)__va((ulong)pde[PDE(target_address)] & 0xfffffffffffff000);
157 
158  SET_BIT(&pte[PTE(target_address)], 9);
159 }
160 
161 static void set_pte_sticky_flags(ioctl_info *info) {
162  void **pgd;
163  void **pdp;
164  void **pde;
165  void **pte;
166  int i,j;
167 
168  pgd = (void **)current->mm->pgd;
169  pdp = (void **)__va((ulong)pgd[PML4(info->base_address)] & 0xfffffffffffff000);
170  pde = (void **)__va((ulong)pdp[PDP(info->base_address)] & 0xfffffffffffff000);
171 
172  // This marks a LP as remote
173  SET_BIT(&pdp[PDP(info->base_address)], 11);
174 
175  for(i = 0; i < 512; i++) {
176  pte = (void **)__va((ulong)pde[i] & 0xfffffffffffff000);
177 
178  if(pte != NULL) {
179  for(j = 0; j < 512; j++) {
180  if(pte[j] != NULL) {
181  if(GET_BIT(&pte[j], 0)) {
182  CLR_BIT(&pte[j], 0);
183  SET_BIT(&pte[j], 9);
184  }
185  }
186  }
187  }
188  }
189 }
190 
191 // is pdp!
192 static int get_pde_sticky_bit(void *target_address) {
193  void **pgd;
194  void **pdp;
195 
196  pgd = (void **)current->mm->pgd;
197  pdp = (void **)__va((ulong)pgd[PML4(target_address)] & 0xfffffffffffff000);
198 
199  return GET_BIT(&pdp[PDP(target_address)], 11);
200 }
201 
202 static int get_pte_sticky_bit(void *target_address) {
203  void **pgd;
204  void **pdp;
205  void **pde;
206 
207  pgd = (void **)current->mm->pgd;
208  pdp = (void **)__va((ulong)pgd[PML4(target_address)] & 0xfffffffffffff000);
209  pde = (void **)__va((ulong)pdp[PDP(target_address)] & 0xfffffffffffff000);
210 
211  if(pde[PDE(target_address)] == NULL) {
212  return 0;
213  }
214 
215  return GET_BIT(&pde[PDE(target_address)], 9);
216 }
217 
218 static int get_presence_bit(void *target_address) {
219  void **pgd;
220  void **pdp;
221  void **pde;
222  void **pte;
223 
224  pgd = (void **)current->mm->pgd;
225  pdp = (void **)__va((ulong)pgd[PML4(target_address)] & 0xfffffffffffff000);
226  pde = (void **)__va((ulong)pdp[PDP(target_address)] & 0xfffffffffffff000);
227 
228 
229  if(pde[PDE(target_address)] == NULL) {
230  return 0;
231  }
232 
233  pte = (void **)__va((ulong)pde[PDE(target_address)] & 0xfffffffffffff000);
234 
235  return GET_BIT(&pte[PTE(target_address)], 0);
236 }
237 
238 static void set_presence_bit(void *target_address) {
239  void **pgd;
240  void **pdp;
241  void **pde;
242  void **pte;
243 
244  pgd = (void **)current->mm->pgd;
245  pdp = (void **)__va((ulong)pgd[PML4(target_address)] & 0xfffffffffffff000);
246  pde = (void **)__va((ulong)pdp[PDP(target_address)] & 0xfffffffffffff000);
247  pte = (void **)__va((ulong)pde[PDE(target_address)] & 0xfffffffffffff000);
248 
249  if(GET_BIT(&pte[PTE(target_address)], 9)) {
250  SET_BIT(&pte[PTE(target_address)], 0);
251  } else {
252  printk("Oh, guarda che sto dentro all'else!!!!\n");
253  }
254 }
255 
256 static void set_page_privilege(ioctl_info *info) {
257  void **pgd;
258  void **pdp;
259  void **pde;
260  void **pte;
261  int i, j;
262 
263  void *base_address = info->base_address;
264  void *final_address = info->base_address + info->count * PAGE_SIZE;
265 
266  pgd = (void **)current->mm->pgd;
267  pdp = (void **)__va((ulong)pgd[PML4(info->base_address)] & 0xfffffffffffff000);
268  pde = (void **)__va((ulong)pdp[PDP(info->base_address)] & 0xfffffffffffff000);
269 
270  for(i = PDE(base_address); i <= PDE(final_address); i++) {
271  pte = (void **)__va((ulong)pde[i] & 0xfffffffffffff000);
272 
273  if(pte == NULL)
274  continue;
275 
276  for(j = 0; j < 512; j++) {
277 
278  if(pte[j] == 0)
279  continue;
280 
281  if(info->write_mode) {
282  SET_BIT(&pte[j], 1);
283  } else {
284  CLR_BIT(&pte[j], 1);
285  }
286  }
287  }
288 }
289 
290 static void set_single_page_privilege(ioctl_info *info) {
291  void **pgd;
292  void **pdp;
293  void **pde;
294  void **pte;
295 
296  pgd = (void **)current->mm->pgd;
297  pdp = (void **)__va((ulong)pgd[PML4(info->base_address)] & 0xfffffffffffff000);
298  pde = (void **)__va((ulong)pdp[PDP(info->base_address)] & 0xfffffffffffff000);
299  pte = (void **)__va((ulong)pde[PDE(info->base_address)] & 0xfffffffffffff000);
300 
301  if(info->write_mode) {
302  SET_BIT(&pte[PTE(info->base_address)], 1);
303  } else {
304  CLR_BIT(&pte[PTE(info->base_address)], 1);
305  }
306 }
307 
308 
309 // WARNING: the last parameter is the original kernel fault handler. We have to call it in this function
310 // if needed, prior to returning. Failing to do so correctly can hang the system!
311 void root_sim_page_fault(struct pt_regs* regs, long error_code, do_page_fault_t kernel_handler) {
312  void *target_address;
313  void **my_pgd;
314  void **my_pdp;
315  ulong i;
316  ulong *auxiliary_stack_pointer;
317  ioctl_info info;
318 
319  if(current->mm == NULL) {
320  /* this is a kernel thread - not a rootsim thread */
321  kernel_handler(regs, error_code);
322  return;
323  }
324 
325  /* discriminate whether this is a classical fault or a root-sim proper fault */
326  for(i = 0; i < SIBLING_PGD; i++) {
327  if (root_sim_processes[i] == current->pid) {
328 
329  target_address = (void *)read_cr2();
330 
331  if(PML4(target_address) < restore_pml4 || PML4(target_address) >= restore_pml4 + restore_pml4_entries) {
332  /* a fault outside the root-sim object zone - it needs to be handeld by the traditional fault manager */
333  kernel_handler(regs, error_code);
334  return;
335  }
336 
337  // Compute the address of the PDP entry associated with the faulting address. It's content
338  // will discriminate whether this is a first invocation of ECS or not for the running event.
339  my_pgd =(void **)pgd_addr[i];
340  my_pdp =(void *)my_pgd[PML4(target_address)];
341  my_pdp = __va((ulong)my_pdp & 0xfffffffffffff000);
342 
343  // Post information about the fault. We fill this structure which is used by the
344  // userland handler to keep up with the ECS (distributed) protocol. We fill as much
345  // information as possible that we can get from kernel space.
346  // TODO: COPY TO USER
347  root_sim_fault_info[i]->rcx = regs->cx;
348  root_sim_fault_info[i]->rip = regs->ip;
349  root_sim_fault_info[i]->target_address = (long long)target_address;
350  root_sim_fault_info[i]->target_gid = (PML4(target_address) - restore_pml4) * 512 + PDP(target_address);
351 
352  if((ulong)my_pdp[PDP(target_address)] == NULL) {
353  printk("ECS Major Fault at %p\n", target_address);
354  // First activation of ECS targeting a new LP
355  root_sim_fault_info[i]->fault_type = ECS_MAJOR_FAULT;
356  } else {
357  if(get_pte_sticky_bit(target_address) != 0) {
358  printk("ECS Minor Fault (1) at %p\n", target_address);
359  // First activation of ECS targeting a new LP
360  secondary:
361  // ECS secondary fault on a remote page
362  root_sim_fault_info[i]->fault_type = ECS_MINOR_FAULT;
363  set_presence_bit(target_address);
364  } else {
365  if(get_presence_bit(target_address) == 0) {
366  printk("Materializing page for %p\n", target_address);
367  kernel_handler(regs, error_code);
368  if(get_pde_sticky_bit(target_address)) {
369  printk("ECS Minor Fault (2) at %p\n", target_address);
370  set_single_pte_sticky_flag(target_address);
371  goto secondary;
372  }
373  return;
374  } else {
375  root_sim_fault_info[i]->fault_type = ECS_CHANGE_PAGE_PRIVILEGE;
376 
377  info.base_address = (void *)((long long)target_address & (~(PAGE_SIZE-1)));
378  info.page_count = 1;
379  info.write_mode = 1;
380 
381  set_single_page_privilege(&info);
382 
383  // we're on the parallel view here
384  rootsim_load_cr3(pgd_addr[i]);
385  }
386  }
387  }
388 
389  printk("Activating userspace handler\n");
390 
391  rs_ktblmgr_ioctl(NULL, IOCTL_UNSCHEDULE_ON_PGD, (int)i);
392 
393  // Pass the address of the faulting instruction to userland
394  auxiliary_stack_pointer = (ulong *)regs->sp;
395  auxiliary_stack_pointer--;
396  copy_to_user((void *)auxiliary_stack_pointer, (void *)&regs->ip, 8);
397  regs->sp = (long)auxiliary_stack_pointer;
398  regs->ip = callback;
399 
400  return;
401  }
402  }
403 
404  kernel_handler(regs, error_code);
405 }
406 
407 EXPORT_SYMBOL(root_sim_page_fault);
408 
409 int rs_ktblmgr_open(struct inode *inode, struct file *filp) {
410 
411  // It's meaningless to open this device in write mode
412  if (((filp->f_flags & O_ACCMODE) == O_WRONLY)
413  || ((filp->f_flags & O_ACCMODE) == O_RDWR)) {
414  return -EACCES;
415  }
416 
417  // Only one access at a time
418  if (!mutex_trylock(&rs_ktblmgr_mutex)) {
419  printk(KERN_INFO "%s: Trying to open an already-opened special device file\n", KBUILD_MODNAME);
420  return -EBUSY;
421  }
422 
423  return 0;
424 }
425 
426 
427 int rs_ktblmgr_release(struct inode *inode, struct file *filp) {
428  int i,j;
429  int pml4;
430  int involved_pml4;
431  void **pgd_entry;
432  void **temp;
433  void *address;
434 
435  /* already logged by ancestor set */
436  pml4 = restore_pml4;
437  involved_pml4 = restore_pml4_entries;
438 
439  for (j=0;j<SIBLING_PGD;j++){
440 
441 
442  original_view[j] = NULL;
443  continue;
444 
445  // SOme super bug down here!
446 
447  if(original_view[j]!=NULL){ /* need to recover memory used for PDPs that have not been deallocated */
448 
449  pgd_entry = (void **)pgd_addr[i];
450  for (i=0; i<involved_pml4; i++){
451 
452  printk("\tPML4 ENTRY FOR CLOSE DEVICE IS %d\n",pml4);
453 
454  temp = pgd_entry[pml4];
455  temp = (void *)((ulong) temp & 0xfffffffffffff000);
456  printk("temp is %p\n", temp);
457  address = (void *)__va(temp);
458  if(address!=NULL){
459  // __free_pages(address, 0); // TODO: there's a bug here! We leak memory instead! :-)
460  printk("would free address at %p\n", address);
461  }
462  pgd_entry[pml4] = ancestor_pml4[pml4];
463 
464  }// end for i
465  original_view[j]=NULL;
466  }// enf if != NULL
467  }// end for j
468 
469  mutex_unlock(&rs_ktblmgr_mutex);
470 
471  return 0;
472 }
473 
474 
475 static long rs_ktblmgr_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
476  int ret = 0;
477  int i;
478  void **my_pgd;
479  void **my_pdp;
480  void **pgd_entry;
481  void **temp;
482  int descriptor;
483  void *address;
484  int pml4;
485  int involved_pml4;
486  int scheduled_object;
487  void **ancestor_pdp;
488  int *scheduled_objects;
489  int scheduled_objects_count;
490  int object_to_close;
491 
492  switch (cmd) {
493 
494  case IOCTL_SET_ANCESTOR_PGD:
495  ancestor_pml4 = (void **)current->mm->pgd;
496  break;
497 
498  case IOCTL_GET_PGD:
499 
500  printk("Entering IOCTL_GET_PGD\n");
501 
502  descriptor = -1;
503  mutex_lock(&pgd_get_mutex);
504  for (i = 0; i < SIBLING_PGD; i++) {
505  if (original_view[i] == NULL) {
506  memcpy((void *)pgd_addr[i], (void *)(current->mm->pgd), 4096);
507  original_view[i] = current->mm;
508  root_sim_fault_info[i] = (fault_info_t *)arg;
509  descriptor = i;
510  goto pgd_get_done;
511  }
512  }
513 
514  pgd_get_done:
515  ret = descriptor; // Return -1 if no PGD is available
516  mutex_unlock(&pgd_get_mutex);
517 
518  // If a valid descriptor is found, make a copy of the PGD entries
519  if(descriptor != -1) {
520  flush_cache_all();
521 
522  /* already logged by ancestor set */
523  pml4 = restore_pml4;
524  involved_pml4 = restore_pml4_entries;
525 
526  pgd_entry = (void **)pgd_addr[descriptor];
527 
528  for (i = 0; i < involved_pml4; i++) {
529 
530  address = (void *)__get_free_pages(GFP_KERNEL, 0); /* allocate and reset new PDP */
531  memset(address,0,4096);
532 
533  temp = pgd_entry[pml4];
534 
535  temp = (void *)((ulong) temp & 0x0000000000000fff);
536  address = (void *)__pa(address);
537  temp = (void *)((ulong)address | (ulong)temp);
538  pgd_entry[pml4] = temp;
539 
540  pml4++;
541  }
542  }
543  printk("Leaving IOCTL_GET_PGD\n");
544 
545  break;
546 
547  case IOCTL_SCHEDULE_ON_PGD:
548  //flush_cache_all();
549  descriptor = ((ioctl_info*)arg)->ds;
550  //scheduled_object = ((ioctl_info*)arg)->id;
551  scheduled_objects_count = ((ioctl_info*)arg)->count;
552  scheduled_objects = ((ioctl_info*)arg)->objects;
553 
554  //scheduled_object = ((ioctl_info*)arg)->id;
555  if (original_view[descriptor] != NULL) { //sanity check
556 
557  for(i = 0; i < scheduled_objects_count; i++) {
558 
559  //scheduled_object = TODO COPY FROM USER check return value
560  copy_from_user((void *)&scheduled_object,(void *)&scheduled_objects[i],sizeof(int));
561  open_index[descriptor]++;
562  currently_open[descriptor][open_index[descriptor]]=scheduled_object;
563 
564  //loadCR3 with pgd[arg]
565  pml4 = restore_pml4 + OBJECT_TO_PML4(scheduled_object);
566  my_pgd =(void **) pgd_addr[descriptor];
567  my_pdp =(void *) my_pgd[pml4];
568  my_pdp = __va((ulong)my_pdp & 0xfffffffffffff000);
569 
570  ancestor_pdp =(void *) ancestor_pml4[pml4];
571  ancestor_pdp = __va((ulong)ancestor_pdp & 0xfffffffffffff000);
572 
573  /* actual opening of the PDP entry */
574  my_pdp[OBJECT_TO_PDP(scheduled_object)] = ancestor_pdp[OBJECT_TO_PDP(scheduled_object)];
575  }// end for
576 
577  /* actual change of the view on memory */
578  root_sim_processes[descriptor] = current->pid;
579  rootsim_load_cr3(pgd_addr[descriptor]);
580  ret = 0;
581  } else {
582  ret = -1;
583  }
584  break;
585 
586 
587  case IOCTL_UNSCHEDULE_ON_PGD:
588 
589  descriptor = arg;
590 
591  if ((original_view[descriptor] != NULL) && (current->mm->pgd != NULL)) { //sanity check
592 
593  root_sim_processes[descriptor] = -1;
594  rootsim_load_cr3(current->mm->pgd);
595 
596  for(i=open_index[descriptor];i>=0;i--){
597 
598  object_to_close = currently_open[descriptor][i];
599 
600  pml4 = restore_pml4 + OBJECT_TO_PML4(object_to_close);
601  my_pgd =(void **)pgd_addr[descriptor];
602  my_pdp =(void *)my_pgd[pml4];
603  my_pdp = __va((ulong)my_pdp & 0xfffffffffffff000);
604 
605  /* actual closure of the PDP entry */
606 
607  my_pdp[OBJECT_TO_PDP(object_to_close)] = NULL;
608  }
609  open_index[descriptor] = -1;
610  ret = 0;
611  } else {
612  ret = -1;
613  }
614 
615  break;
616 
617  case IOCTL_SET_VM_RANGE:
618 
619  flush_cache_all(); /* to make new range visible across multiple runs */
620 
621  mapped_processes = (((ioctl_info*)arg)->mapped_processes);
622  involved_pml4 = (((ioctl_info*)arg)->mapped_processes) >> 9;
623  if ( (unsigned)((ioctl_info*)arg)->mapped_processes & 0x00000000000001ff ) involved_pml4++;
624 
625  callback = ((ioctl_info*)arg)->callback;
626 
627  pml4 = (int)PML4(((ioctl_info*)arg)->addr);
628  printk("LOGGING CHANGE VIEW INVOLVING %u PROCESSES AND %d PML4 ENTRIES STARTING FROM ENTRY %d (address %p)\n",((ioctl_info*)arg)->mapped_processes,involved_pml4,pml4, ((ioctl_info*)arg)->addr);
629  restore_pml4 = pml4;
630  restore_pml4_entries = involved_pml4;
631 
632  flush_cache_all(); /* to make new range visible across multiple runs */
633 
634  ret = 0;
635  break;
636 
637  case IOCTL_SET_PAGE_PRIVILEGE:
638  set_page_privilege((ioctl_info *)arg);
639 
640  ret = 0;
641  break;
642 
643  case IOCTL_PROTECT_REMOTE_LP:
644  set_pte_sticky_flags((ioctl_info *)arg);
645  break;
646 
647  default:
648  ret = -EINVAL;
649  }
650 
651  return ret;
652 
653 }
654 
655 
656 
657 void the_pager(void) {
658  int i;
659 
660  if(current->mm != NULL){
661  for(i=0;i<SIBLING_PGD;i++){
662  if ((root_sim_processes[i])==(current->pid)){
663  rootsim_load_cr3(pgd_addr[i]);
664  }
665  }
666  }
667 }
668 
669 
670 
671 static int rs_ktblmgr_init(void) {
672 
673  int ret;
674  int i;
675  //int j;
676  struct kprobe kp;
677 
678 
679  rootsim_pager = the_pager;
680  //rootsim_pager(NULL);
681 
682  mutex_init(&pgd_get_mutex);
683 
684 
685  // Dynamically allocate a major for the device
686  major = register_chrdev(0, "rs_ktblmgr", &fops);
687  if (major < 0) {
688 // printk(KERN_ERR "rs_ktblmgr: failed to register device. Error %d\n", major);
689  ret = major;
690  goto failed_chrdevreg;
691  }
692  printk("major for ktblmgr is %d\n",major);
693  goto allocate;
694 
695  // Create a class for the device
696  dev_cl = class_create(THIS_MODULE, "rootsim");
697  if (IS_ERR(dev_cl)) {
698 // printk(KERN_ERR "rs_ktblmgr: failed to register device class\n");
699  ret = PTR_ERR(dev_cl);
700  goto failed_classreg;
701  }
702 
703  // Create a device in the previously created class
704  device = device_create(dev_cl, NULL, MKDEV(major, 0), NULL, "ktblmgr");
705  if (IS_ERR(device)) {
706 // printk(KERN_ERR "rs_ktblmr: failed to create device\n");
707  ret = PTR_ERR(device);
708  goto failed_devreg;
709  }
710 
711 
712  // Create sysfs endpoints
713  // dev_attr_multimap comes from the DEVICE_ATTR(...) at the top of this module
714  // If this call succeds, then there is a new file in:
715  // /sys/devices/virtual/rootsim/ktblmgr/multimap
716  // Which can be used to dialogate with the driver
717  ret = device_create_file(device, &dev_attr_multimap);
718  if (ret < 0) {
719  printk(KERN_WARNING "rs_ktblmgr: failed to create write /sys endpoint - continuing without\n");
720  }
721 
722  // Initialize the device mutex
723  mutex_init(&rs_ktblmgr_mutex);
724 
725  allocate:
726 
727  // Preallocate pgd
728  for (i = 0; i < SIBLING_PGD; i++) {
729 
730  original_view[i] = NULL;
731 
732  if ( ! (mm_struct_addr[i] = kmalloc(sizeof(struct mm_struct), GFP_KERNEL)))
733  goto bad_alloc;
734 
735  //if (!(pgd_addr[i] = pgd_alloc(mm_struct_addr[i]))) {kfree(mm_struct_addr[i]); goto bad_startup;}
736 
737  if (!(pgd_addr[i] = (void *)__get_free_pages(GFP_KERNEL, 0))) {
738  kfree(mm_struct_addr[i]);
739  goto bad_alloc;
740  }
741  mm_struct_addr[i]->pgd = pgd_addr[i];
742  if ((void *)pgd_addr[i] != (void *)((struct mm_struct *)mm_struct_addr[i])->pgd) {
743  printk("bad referencing between mm_struct and pgd\n");
744  goto bad_alloc;
745  }
746  managed_pgds++;
747  }
748 
749  printk(KERN_INFO "Correctly allocated %d sibling pgds\n", managed_pgds);
750 
751 /*
752  for (i=0;i<AUXILIARY_FRAMES; i++) {
753  auxiliary_frames[i]=(void *)__get_free_pages(GFP_KERNEL,0);
754  if(auxiliary_frames[i]==NULL){
755  for(j=0;j<i;j++) __free_pages(auxiliary_frames[j],0);
756  printk("cannot allocate auxiliary frames\n");
757  }
758  else{
759  if(i==(AUXILIARY_FRAMES-1)) printk(KERN_INFO "Correctly allocated %d auxiliary fames\n", i);
760  }
761  }
762 */
763 
764  // Get a kernel probe to access flush_tlb_all
765  memset(&kp, 0, sizeof(kp));
766  kp.symbol_name = "flush_tlb_all";
767  if (!register_kprobe(&kp)) {
768  flush_tlb_all_lookup = (void *) kp.addr;
769  unregister_kprobe(&kp);
770  }
771 
772 
773  return 0;
774 
775 
776  failed_devreg:
777  class_unregister(dev_cl);
778  class_destroy(dev_cl);
779  failed_classreg:
780  unregister_chrdev(major, "rs_ktblmgr");
781  failed_chrdevreg:
782  return ret;
783 
784 
785  bad_alloc:
786  printk(KERN_ERR "rs_ktblmgr: something wrong while preallocatin pgds\n");
787  return -1;
788 }
789 
790 
791 
792 static void rs_ktblmgr_cleanup(void) {
793 
794 // int i;
795 // device_remove_file(device, &dev_attr_multimap);
796 // device_destroy(dev_cl, MKDEV(major, 0));
797 // class_unregister(dev_cl);
798 // class_destroy(dev_cl);
799 
800  rootsim_pager = NULL;
801  unregister_chrdev(major, "rs_ktblmgr");
802 
803  for (; managed_pgds > 0; managed_pgds--) {
804  __free_pages((void *)mm_struct_addr[managed_pgds-1],0);
805  kfree(mm_struct_addr[managed_pgds-1]);
806 
807  }
808 
809 /*
810  for (i=0;i<AUXILIARY_FRAMES; i++) {
811  if(auxiliary_frames[i]==NULL){
812  __free_pages(auxiliary_frames[i],0);
813  }
814  else{
815  printk(KERN_INFO "Error while deallocating auxiliary fames\n");
816  }
817  }
818 */
819 
820 
821 }
822 
823 //#endif /* HAVE_CROSS_STATE */
Per-thread page table.
struct file_operations fops
File operations for the module.
struct memory_map * mm
Memory map of the LP.
Definition: process.h:76
__thread struct lp_struct * current
This is a per-thread variable pointing to the block state of the LP currently scheduled.
Definition: scheduler.c:72
static int major
Device major number.
static DEFINE_MUTEX(rs_ktblmgr_mutex)
Only one process can access this device (before spawning threads!)
static struct device * device
Device being created.
void(* flush_tlb_all_lookup)(void)
This is to access the actual flush_tlb_all using a kernel proble.
static struct class * dev_cl
Device class being created.