2019-08-26 15:09:31 +08:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Fu YanX <yanx.fu@intel.com>
|
|
|
|
Date: Mon, 13 May 2019 18:25:32 +0800
|
|
|
|
Subject: [PATCH] acrn_hvlog:use ioremap for hvlog to avoid memory crash
|
|
|
|
|
|
|
|
In acrn_hvlog use a fixed phyaddr, but this phyaddr may be memory
|
|
|
|
mapped and used for kernel's other module in kaslr mode.
|
|
|
|
To avoid this condition, reserved the fixed phyaddr before memory
|
|
|
|
mapping, and ioremap the fixed phyaddr in acrn_hvlog to use.
|
|
|
|
|
|
|
|
Tracked-On: PKT-2559
|
|
|
|
Tracked-On: projectacrn/acrn-hypervisor#3027
|
|
|
|
Signed-off-by: Fu YanX <yanx.fu@intel.com>
|
|
|
|
Reviewed-by: Li Fei1 <fei1.li@intel.com>
|
|
|
|
---
|
|
|
|
drivers/acrn/acrn_hvlog.c | 54 ++++++++++++++++++++++++---------------
|
|
|
|
drivers/acrn/acrn_trace.c | 7 ++---
|
|
|
|
drivers/acrn/sbuf.c | 25 +++++++-----------
|
|
|
|
drivers/acrn/sbuf.h | 6 ++---
|
|
|
|
4 files changed, 50 insertions(+), 42 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/drivers/acrn/acrn_hvlog.c b/drivers/acrn/acrn_hvlog.c
|
2020-10-27 02:14:06 +08:00
|
|
|
index 87b1cb23ddc9..c6b2a981f1df 100644
|
2019-08-26 15:09:31 +08:00
|
|
|
--- a/drivers/acrn/acrn_hvlog.c
|
|
|
|
+++ b/drivers/acrn/acrn_hvlog.c
|
|
|
|
@@ -95,7 +95,8 @@ struct acrn_hvlog {
|
|
|
|
static struct acrn_hvlog *acrn_hvlog_devs[SBUF_HVLOG_TYPES];
|
|
|
|
static uint16_t pcpu_nr = DEFAULT_PCPU_NR;
|
|
|
|
static unsigned long long hvlog_buf_size;
|
|
|
|
-static unsigned long long hvlog_buf_base;
|
|
|
|
+static unsigned long long hvlog_buf_phyaddr_base;
|
|
|
|
+static void *hvlog_buf_virtaddr_base;
|
|
|
|
|
|
|
|
static int __init early_hvlog(char *p)
|
|
|
|
{
|
|
|
|
@@ -105,14 +106,14 @@ static int __init early_hvlog(char *p)
|
|
|
|
hvlog_buf_size = memparse(p, &p);
|
|
|
|
if (*p != '@')
|
|
|
|
return 0;
|
|
|
|
- hvlog_buf_base = memparse(p + 1, &p);
|
|
|
|
+ hvlog_buf_phyaddr_base = memparse(p + 1, &p);
|
|
|
|
|
|
|
|
- if (!!hvlog_buf_base && !!hvlog_buf_size) {
|
|
|
|
- ret = memblock_reserve(hvlog_buf_base, hvlog_buf_size);
|
|
|
|
+ if (!!hvlog_buf_phyaddr_base && !!hvlog_buf_size) {
|
|
|
|
+ ret = memblock_reserve(hvlog_buf_phyaddr_base, hvlog_buf_size);
|
|
|
|
if (ret) {
|
|
|
|
pr_err("%s: Error reserving hvlog memblock\n",
|
|
|
|
__func__);
|
|
|
|
- hvlog_buf_base = 0;
|
|
|
|
+ hvlog_buf_phyaddr_base = 0;
|
|
|
|
hvlog_buf_size = 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
@@ -219,8 +220,8 @@ static const struct file_operations acrn_hvlog_fops = {
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
- * base0 = hvlog_buf_base;
|
|
|
|
- * base1 = hvlog_buf_base + (hvlog_buf_size >> 1)
|
|
|
|
+ * base0 = hvlog_buf_phyaddr_base;
|
|
|
|
+ * base1 = hvlog_buf_phyaddr_base + (hvlog_buf_size >> 1)
|
|
|
|
* if there is valid data in base0, cur_logbuf = base1, last_logbuf = base0.
|
|
|
|
* if there is valid data in base1, cur_logbuf = base0, last_logbuf = base1.
|
|
|
|
* if there is no valid data both in base0 and base1, cur_logbuf = base0,
|
|
|
|
@@ -228,18 +229,20 @@ static const struct file_operations acrn_hvlog_fops = {
|
|
|
|
*/
|
|
|
|
static void assign_hvlog_buf_base(uint64_t *cur_logbuf, uint64_t *last_logbuf)
|
|
|
|
{
|
|
|
|
- uint64_t base0, base1;
|
|
|
|
+ uint64_t base0, base1, offset;
|
|
|
|
uint32_t ele_num, size;
|
|
|
|
uint16_t pcpu_id;
|
|
|
|
+ void *sbuf;
|
|
|
|
|
|
|
|
- base0 = hvlog_buf_base;
|
|
|
|
- base1 = hvlog_buf_base + (hvlog_buf_size >> 1);
|
|
|
|
+ base0 = hvlog_buf_phyaddr_base;
|
|
|
|
+ base1 = hvlog_buf_phyaddr_base + (hvlog_buf_size >> 1);
|
|
|
|
size = (hvlog_buf_size >> 1) / pcpu_nr;
|
|
|
|
ele_num = (size - SBUF_HEAD_SIZE) / LOG_ENTRY_SIZE;
|
|
|
|
|
|
|
|
foreach_cpu(pcpu_id, pcpu_nr) {
|
|
|
|
- if (sbuf_check_valid(ele_num, LOG_ENTRY_SIZE,
|
|
|
|
- base0 + (size * pcpu_id))) {
|
|
|
|
+ offset = (base0 + (size * pcpu_id)) - hvlog_buf_phyaddr_base;
|
|
|
|
+ sbuf = hvlog_buf_virtaddr_base + offset;
|
|
|
|
+ if (sbuf_check_valid(ele_num, LOG_ENTRY_SIZE, sbuf)) {
|
|
|
|
*last_logbuf = base0;
|
|
|
|
*cur_logbuf = base1;
|
|
|
|
return;
|
|
|
|
@@ -247,8 +250,9 @@ static void assign_hvlog_buf_base(uint64_t *cur_logbuf, uint64_t *last_logbuf)
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach_cpu(pcpu_id, pcpu_nr) {
|
|
|
|
- if (sbuf_check_valid(ele_num, LOG_ENTRY_SIZE,
|
|
|
|
- base1 + (size * pcpu_id))) {
|
|
|
|
+ offset = (base1 + (size * pcpu_id)) - hvlog_buf_phyaddr_base;
|
|
|
|
+ sbuf = hvlog_buf_virtaddr_base + offset;
|
|
|
|
+ if (sbuf_check_valid(ele_num, LOG_ENTRY_SIZE, sbuf)) {
|
|
|
|
*last_logbuf = base1;
|
|
|
|
*cur_logbuf = base0;
|
|
|
|
return;
|
|
|
|
@@ -267,6 +271,7 @@ static int init_hvlog_dev(uint64_t base, uint32_t hvlog_type)
|
|
|
|
shared_buf_t *sbuf;
|
|
|
|
struct acrn_hvlog *hvlog;
|
|
|
|
uint32_t ele_size, ele_num, size;
|
|
|
|
+ uint64_t offset;
|
|
|
|
|
|
|
|
if (!base)
|
|
|
|
return -ENODEV;
|
|
|
|
@@ -282,15 +287,17 @@ static int init_hvlog_dev(uint64_t base, uint32_t hvlog_type)
|
|
|
|
case SBUF_CUR_HVLOG:
|
|
|
|
snprintf(hvlog->name, sizeof(hvlog->name),
|
|
|
|
"acrn_hvlog_cur_%hu", idx);
|
|
|
|
- sbuf = sbuf_construct(ele_num, ele_size,
|
|
|
|
- base + (size * idx));
|
|
|
|
- sbuf_share_setup(idx, ACRN_HVLOG, sbuf);
|
|
|
|
+ offset = (base + (size * idx)) - hvlog_buf_phyaddr_base;
|
|
|
|
+ sbuf = hvlog_buf_virtaddr_base + offset;
|
|
|
|
+ sbuf = sbuf_construct(ele_num, ele_size, sbuf);
|
|
|
|
+ sbuf_share_setup(idx, ACRN_HVLOG, base + (size * idx));
|
|
|
|
break;
|
|
|
|
case SBUF_LAST_HVLOG:
|
|
|
|
snprintf(hvlog->name, sizeof(hvlog->name),
|
|
|
|
"acrn_hvlog_last_%hu", idx);
|
|
|
|
- sbuf = sbuf_check_valid(ele_num, ele_size,
|
|
|
|
- base + (size * idx));
|
|
|
|
+ offset = (base + (size * idx)) - hvlog_buf_phyaddr_base;
|
|
|
|
+ sbuf = hvlog_buf_virtaddr_base + offset;
|
|
|
|
+ sbuf = sbuf_check_valid(ele_num, ele_size, sbuf);
|
|
|
|
hvlog_mark_unread(sbuf);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
@@ -355,11 +362,18 @@ static int __init acrn_hvlog_init(void)
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
- if (!hvlog_buf_base || !hvlog_buf_size) {
|
|
|
|
+ if (!hvlog_buf_phyaddr_base || !hvlog_buf_size) {
|
|
|
|
pr_warn("no fixed memory reserve for hvlog.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ hvlog_buf_virtaddr_base = ioremap(hvlog_buf_phyaddr_base,
|
|
|
|
+ hvlog_buf_size);
|
|
|
|
+ if (!hvlog_buf_virtaddr_base) {
|
|
|
|
+ pr_info("%s: Error ioremap hvlog memblock.\n", __func__);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
memset(&hw_info, 0, sizeof(struct acrn_hw_info));
|
|
|
|
ret = hcall_get_hw_info(virt_to_phys(&hw_info));
|
|
|
|
if (!ret)
|
|
|
|
diff --git a/drivers/acrn/acrn_trace.c b/drivers/acrn/acrn_trace.c
|
2020-10-27 02:14:06 +08:00
|
|
|
index 010acb9872c4..136564da644f 100644
|
2019-08-26 15:09:31 +08:00
|
|
|
--- a/drivers/acrn/acrn_trace.c
|
|
|
|
+++ b/drivers/acrn/acrn_trace.c
|
|
|
|
@@ -207,7 +207,8 @@ static int __init acrn_trace_init(void)
|
|
|
|
|
|
|
|
foreach_cpu(cpu, pcpu_num) {
|
|
|
|
sbuf = acrn_trace_devs[cpu].sbuf;
|
|
|
|
- ret = sbuf_share_setup(cpu, ACRN_TRACE, sbuf);
|
|
|
|
+ WARN_ON(!virt_addr_valid(sbuf));
|
|
|
|
+ ret = sbuf_share_setup(cpu, ACRN_TRACE, virt_to_phys(sbuf));
|
|
|
|
if (ret < 0) {
|
|
|
|
pr_err("Failed to setup SBuf, cpuid %d\n", cpu);
|
|
|
|
goto out_sbuf;
|
|
|
|
@@ -243,7 +244,7 @@ static int __init acrn_trace_init(void)
|
|
|
|
|
|
|
|
out_sbuf:
|
|
|
|
for (i = --cpu; i >= 0; i--)
|
|
|
|
- sbuf_share_setup(i, ACRN_TRACE, NULL);
|
|
|
|
+ sbuf_share_setup(i, ACRN_TRACE, 0);
|
|
|
|
cpu = pcpu_num;
|
|
|
|
|
|
|
|
out_free:
|
|
|
|
@@ -268,7 +269,7 @@ static void __exit acrn_trace_exit(void)
|
|
|
|
misc_deregister(&acrn_trace_devs[cpu].miscdev);
|
|
|
|
|
|
|
|
/* set sbuf pointer to NULL in HV */
|
|
|
|
- sbuf_share_setup(cpu, ACRN_TRACE, NULL);
|
|
|
|
+ sbuf_share_setup(cpu, ACRN_TRACE, 0);
|
|
|
|
|
|
|
|
/* free sbuf, per-cpu sbuf should be set NULL */
|
|
|
|
sbuf_free(acrn_trace_devs[cpu].sbuf);
|
|
|
|
diff --git a/drivers/acrn/sbuf.c b/drivers/acrn/sbuf.c
|
2020-10-27 02:14:06 +08:00
|
|
|
index b51ee04e12fa..018e1f4df72b 100644
|
2019-08-26 15:09:31 +08:00
|
|
|
--- a/drivers/acrn/sbuf.c
|
|
|
|
+++ b/drivers/acrn/sbuf.c
|
|
|
|
@@ -167,7 +167,7 @@ int sbuf_get(shared_buf_t *sbuf, uint8_t *data)
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(sbuf_get);
|
|
|
|
|
|
|
|
-int sbuf_share_setup(uint32_t pcpu_id, uint32_t sbuf_id, shared_buf_t *sbuf)
|
|
|
|
+int sbuf_share_setup(uint32_t pcpu_id, uint32_t sbuf_id, uint64_t gpa)
|
|
|
|
{
|
|
|
|
struct sbuf_setup_param ssp;
|
|
|
|
|
|
|
|
@@ -177,12 +177,7 @@ int sbuf_share_setup(uint32_t pcpu_id, uint32_t sbuf_id, shared_buf_t *sbuf)
|
|
|
|
ssp.pcpu_id = pcpu_id;
|
|
|
|
ssp.sbuf_id = sbuf_id;
|
|
|
|
|
|
|
|
- if (!sbuf) {
|
|
|
|
- ssp.gpa = 0;
|
|
|
|
- } else {
|
|
|
|
- BUG_ON(!virt_addr_valid(sbuf));
|
|
|
|
- ssp.gpa = virt_to_phys(sbuf);
|
|
|
|
- }
|
|
|
|
+ ssp.gpa = gpa;
|
|
|
|
pr_info("setup phys add = 0x%llx\n", ssp.gpa);
|
|
|
|
|
|
|
|
return hcall_setup_sbuf(virt_to_phys(&ssp));
|
|
|
|
@@ -190,15 +185,14 @@ int sbuf_share_setup(uint32_t pcpu_id, uint32_t sbuf_id, shared_buf_t *sbuf)
|
|
|
|
EXPORT_SYMBOL(sbuf_share_setup);
|
|
|
|
|
|
|
|
shared_buf_t *sbuf_check_valid(uint32_t ele_num, uint32_t ele_size,
|
|
|
|
- uint64_t paddr)
|
|
|
|
+ void *vaddr)
|
|
|
|
{
|
|
|
|
shared_buf_t *sbuf;
|
|
|
|
|
|
|
|
- if (!ele_num || !ele_size || !paddr)
|
|
|
|
+ if (!ele_num || !ele_size || !vaddr)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
- sbuf = (shared_buf_t *)phys_to_virt(paddr);
|
|
|
|
- BUG_ON(!virt_addr_valid(sbuf));
|
|
|
|
+ sbuf = (shared_buf_t *)vaddr;
|
|
|
|
|
|
|
|
if ((sbuf->magic == SBUF_MAGIC) &&
|
|
|
|
(sbuf->ele_num == ele_num) &&
|
|
|
|
@@ -211,22 +205,21 @@ shared_buf_t *sbuf_check_valid(uint32_t ele_num, uint32_t ele_size,
|
|
|
|
EXPORT_SYMBOL(sbuf_check_valid);
|
|
|
|
|
|
|
|
shared_buf_t *sbuf_construct(uint32_t ele_num, uint32_t ele_size,
|
|
|
|
- uint64_t paddr)
|
|
|
|
+ void *vaddr)
|
|
|
|
{
|
|
|
|
shared_buf_t *sbuf;
|
|
|
|
|
|
|
|
- if (!ele_num || !ele_size || !paddr)
|
|
|
|
+ if (!ele_num || !ele_size || !vaddr)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
- sbuf = (shared_buf_t *)phys_to_virt(paddr);
|
|
|
|
- BUG_ON(!virt_addr_valid(sbuf));
|
|
|
|
+ sbuf = (shared_buf_t *)vaddr;
|
|
|
|
|
|
|
|
memset(sbuf, 0, SBUF_HEAD_SIZE);
|
|
|
|
sbuf->magic = SBUF_MAGIC;
|
|
|
|
sbuf->ele_num = ele_num;
|
|
|
|
sbuf->ele_size = ele_size;
|
|
|
|
sbuf->size = ele_num * ele_size;
|
|
|
|
- pr_info("construct sbuf at 0x%llx.\n", paddr);
|
|
|
|
+ pr_info("construct sbuf at 0x%llx.\n", (unsigned long long)sbuf);
|
|
|
|
return sbuf;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(sbuf_construct);
|
|
|
|
diff --git a/drivers/acrn/sbuf.h b/drivers/acrn/sbuf.h
|
2020-10-27 02:14:06 +08:00
|
|
|
index d08bf9fedf70..f8bed41bbb58 100644
|
2019-08-26 15:09:31 +08:00
|
|
|
--- a/drivers/acrn/sbuf.h
|
|
|
|
+++ b/drivers/acrn/sbuf.h
|
|
|
|
@@ -121,11 +121,11 @@ static inline void sbuf_add_flags(shared_buf_t *sbuf, uint64_t flags)
|
|
|
|
shared_buf_t *sbuf_allocate(uint32_t ele_num, uint32_t ele_size);
|
|
|
|
void sbuf_free(shared_buf_t *sbuf);
|
|
|
|
int sbuf_get(shared_buf_t *sbuf, uint8_t *data);
|
|
|
|
-int sbuf_share_setup(uint32_t pcpu_id, uint32_t sbuf_id, shared_buf_t *sbuf);
|
|
|
|
+int sbuf_share_setup(uint32_t pcpu_id, uint32_t sbuf_id, uint64_t gpa);
|
|
|
|
shared_buf_t *sbuf_check_valid(uint32_t ele_num, uint32_t ele_size,
|
|
|
|
- uint64_t gpa);
|
|
|
|
+ void *vaddr);
|
|
|
|
shared_buf_t *sbuf_construct(uint32_t ele_num, uint32_t ele_size,
|
|
|
|
- uint64_t gpa);
|
|
|
|
+ void *vaddr);
|
|
|
|
void sbuf_deconstruct(shared_buf_t *sbuf);
|
|
|
|
|
|
|
|
#endif /* SHARED_BUF_H */
|
|
|
|
--
|
|
|
|
https://clearlinux.org
|
|
|
|
|