clear-pkgs-linux-iot-lts2018/1148-acrn_hvlog-use-ioremap...

282 lines
9.5 KiB
Diff

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
index 87b1cb23ddc9..c6b2a981f1df 100644
--- 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
index 010acb9872c4..136564da644f 100644
--- 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
index b51ee04e12fa..018e1f4df72b 100644
--- 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
index d08bf9fedf70..f8bed41bbb58 100644
--- 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