{"action":"created","issue":{"url":"https://api.github.com/repos/asamy/ksm/issues/13","repository_url":"https://api.github.com/repos/asamy/ksm","labels_url":"https://api.github.com/repos/asamy/ksm/issues/13/labels{/name}","comments_url":"https://api.github.com/repos/asamy/ksm/issues/13/comments","events_url":"https://api.github.com/repos/asamy/ksm/issues/13/events","html_url":"https://github.com/asamy/ksm/issues/13","id":197571588,"number":13,"title":"Create a separate PML4 table for the Host","user":{"login":"asamy","id":1820645,"avatar_url":"https://avatars.githubusercontent.com/u/1820645?v=3","gravatar_id":"","url":"https://api.github.com/users/asamy","html_url":"https://github.com/asamy","followers_url":"https://api.github.com/users/asamy/followers","following_url":"https://api.github.com/users/asamy/following{/other_user}","gists_url":"https://api.github.com/users/asamy/gists{/gist_id}","starred_url":"https://api.github.com/users/asamy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asamy/subscriptions","organizations_url":"https://api.github.com/users/asamy/orgs","repos_url":"https://api.github.com/users/asamy/repos","events_url":"https://api.github.com/users/asamy/events{/privacy}","received_events_url":"https://api.github.com/users/asamy/received_events","type":"User","site_admin":false},"labels":[{"id":407741116,"url":"https://api.github.com/repos/asamy/ksm/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":10,"created_at":"2016-12-26T10:21:00Z","updated_at":"2016-12-27T23:45:01Z","closed_at":null,"body":"On Linux, getting the kernel CR3 is difficult, mainly because it's not exported (`init_level4_pgd`, `init_mm`, `init_task`, etc, are no longer exported on newer kernels), so in order to get a consistent CR3 we hacked kworker's CR3, but this is not very nice, even running a kernel thread is bad because kernel threads can be executed in any context, so it's the same thing as doing it inside the module entry point.\r\n\r\nPerhaps even completely create new tables for the Host, e.g. GDT, IDT, LAPIC, etc.  This would make it a lot better and flexible, we could even use it as a boot time hypervisor that way (e.g. start before the kernel does).\r\n\r\nThis is quite a low priority issue, but I will play with this sometime later for fun."},"comment":{"url":"https://api.github.com/repos/asamy/ksm/issues/comments/269399029","html_url":"https://github.com/asamy/ksm/issues/13#issuecomment-269399029","issue_url":"https://api.github.com/repos/asamy/ksm/issues/13","id":269399029,"user":{"login":"asamy","id":1820645,"avatar_url":"https://avatars.githubusercontent.com/u/1820645?v=3","gravatar_id":"","url":"https://api.github.com/users/asamy","html_url":"https://github.com/asamy","followers_url":"https://api.github.com/users/asamy/followers","following_url":"https://api.github.com/users/asamy/following{/other_user}","gists_url":"https://api.github.com/users/asamy/gists{/gist_id}","starred_url":"https://api.github.com/users/asamy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asamy/subscriptions","organizations_url":"https://api.github.com/users/asamy/orgs","repos_url":"https://api.github.com/users/asamy/repos","events_url":"https://api.github.com/users/asamy/events{/privacy}","received_events_url":"https://api.github.com/users/asamy/received_events","type":"User","site_admin":false},"created_at":"2016-12-27T23:45:01Z","updated_at":"2016-12-27T23:45:01Z","body":"Sure...  Here's diff off the upstream tree:\r\n```\r\ndiff --git a/ksm.c b/ksm.c\r\nindex 2404912..fb12ba8 100644\r\n--- a/ksm.c\r\n+++ b/ksm.c\r\n@@ -123,6 +123,7 @@ int __ksm_init_cpu(struct ksm *k)\r\n \t/* Required MSR_IA32_FEATURE_CONTROL bits:  */\r\n \tu64 required_feat_bits = FEATURE_CONTROL_LOCKED |\r\n \t\tFEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;\r\n+\r\n #ifdef __linux__\r\n \tif (tboot_enabled())\r\n \t\trequired_feat_bits |= FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX;\r\n@@ -145,14 +146,13 @@ int __ksm_init_cpu(struct ksm *k)\r\n \t\t\treturn ERR_NOMEM;\r\n \t\t}\r\n \r\n-\t\tk->kernel_cr3 = __readcr3();\r\n+\t\tk->origin_cr3 = __readcr3();\r\n \t\tu8 ret = __vmx_vminit(vcpu);\r\n \t\tVCPU_DEBUG(\"Started: %d\\n\", !ret);\r\n \r\n \t\tif (ret == 0)\r\n \t\t\tk->active_vcpus++, vcpu->subverted = true;\r\n-\t\telse\r\n-\t\t\t/* vcpu_run() failed, cleanup:  */\r\n+\t\telse \t/* vcpu_run() failed, cleanup:  */\r\n \t\t\tvcpu_free(vcpu);\r\n \t\treturn ret;\r\n #ifndef __GNUC__\r\n@@ -212,9 +212,6 @@ int ksm_init(void)\r\n \t */\r\n \t__stosq((u64 *)&ksm, 0, sizeof(ksm) >> 3);\r\n \r\n-\t/* Caller cr3 (could be user)  */\r\n-\tksm.origin_cr3 = __readcr3();\r\n-\r\n #ifdef EPAGE_HOOK\r\n \thtable_init(&ksm.ht, rehash, NULL);\r\n #endif\r\ndiff --git a/main_linux.c b/main_linux.c\r\nindex 0caa7d1..431cf92 100644\r\n--- a/main_linux.c\r\n+++ b/main_linux.c\r\n@@ -25,22 +25,10 @@\r\n \r\n #include \"ksm.h\"\r\n \r\n-/*\r\n- * FIXME: Get rid of this work queue stuff.\r\n- * Currently they are just a workaround since init_mm / init_task /\r\n- * init_level4_pgd aren't exported, so we need some way to hack some resident\r\n- * CR3 which is kworker in this case...  Rather than using insmod/modprobe's\r\n- * CR3 which will die eventually.\r\n- */\r\n-static void ksm_worker(struct work_struct *);\r\n-static struct workqueue_struct *wq;\r\n-static DECLARE_DELAYED_WORK(work, ksm_worker);\r\n-\r\n static inline void do_cpu(void *v)\r\n {\r\n \tint (*f) (struct ksm *) = v;\r\n-\tVCPU_DEBUG(\"On CPU calling %p\\n\", f);\r\n-\tf(&ksm);\r\n+\tVCPU_DEBUG(\"On CPU %p: %d\\n\", f, f(&ksm));\r\n }\r\n \r\n static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)\r\n@@ -63,38 +51,35 @@ static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *\r\n static struct notifier_block cpu_notify = {\r\n \t.notifier_call = cpu_callback\r\n };\r\n-\r\n-static void ksm_worker(struct work_struct *w)\r\n-{\r\n-\tint ret;\r\n-\tVCPU_DEBUG(\"in ksm_worker(): %s\\n\", current->comm);\r\n-\r\n-\tret = ksm_init();\r\n-\tVCPU_DEBUG(\"init: %d\\n\", ret);\r\n-}\r\n+static struct mm_struct *mm;\r\n \r\n int __init ksm_start(void)\r\n {\r\n-\twq = create_singlethread_workqueue(\"worker_ksm\");\r\n-\tif (!wq)\r\n-\t\treturn -ENOMEM;\r\n+\tint ret = 0;\r\n \r\n-\tif (!queue_delayed_work(wq, &work, 100)) {\r\n-\t\tdestroy_workqueue(wq);\r\n-\t\treturn -EINVAL;\r\n-\t}\r\n+\tVCPU_DEBUG(\"ksm_start(): stealing %s's CR3 as host's\\n\", current->comm);\r\n+\tmm = current->active_mm; \t/* or even ->mm  */\r\n+\tatomic_inc(&mm->mm_count);\r\n+\tksm.kernel_cr3 = __readcr3(); \t/* or even __pa(mm->pgd)  */\r\n \r\n-\tVCPU_DEBUG_RAW(\"Done, wait for wq to fire\\n\");\r\n-\tregister_hotcpu_notifier(&cpu_notify);\r\n-\treturn 0;\r\n+\tret = ksm_init();\r\n+\tif (ret == 0)\r\n+\t\tregister_hotcpu_notifier(&cpu_notify);\r\n+\telse\r\n+\t\tmmdrop(mm);\r\n+\r\n+\tVCPU_DEBUG(\"init: %d\\n\", ret);\r\n+\treturn ret;\r\n }\r\n \r\n void __exit ksm_cleanup(void)\r\n {\r\n+\tint r;\r\n \tunregister_hotcpu_notifier(&cpu_notify);\r\n-\tdestroy_workqueue(wq);\r\n-\tVCPU_DEBUG(\"exit: %d\\n\", ksm_exit());\r\n-\tVCPU_DEBUG(\"Bye\\n\");\r\n+\r\n+\tr = ksm_exit();\r\n+\tmmdrop(mm);\r\n+\tVCPU_DEBUG(\"exit: %d\\n\", r);\r\n }\r\n \r\n module_init(ksm_start);```\r\n"}}
{"actor":{"display_login":"asamy"}}