mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-02 09:25:17 +00:00
dm: virtio-gpu: VGA compability support
Legacy VGA & VBE interface as a common interface is supported by many legacy and modern OS. Many installer of OS distribution use this interface to display the GUI of installer when setup a refresh new installation on bare-metal. Besides, Windows OS always use this interface to display it's BSOD, recovery mode & safe mode GUI. It is need because Windows don't include virtio-gpu driver as their in-box driver, VGA interface will be used before the virtio-gpu driver been installed. To be compatiable with the PCI bar layout of legacy VGA, the layout is refined to meet with the requirement of legacy VGA and modern virtio-gpu. BAR0: VGA Framebuffer memory, 16 MB in size. BAR2: MMIO Space [0x0000~0x03ff] EDID data blob [0x0400~0x041f] VGA ioports registers [0x0500~0x0516] bochs display interface registers [0x1000~0x17ff] Virtio common configuration registers [0x1800~0x1fff] Virtio ISR state registers [0x2000~0x2fff] Virtio device configuration registers [0x3000~0x3fff] Virtio notification registers BAR4: MSI/MSI-X BAR5: Virtio port io Tracked-On: #7210 Signed-off-by: Sun Peng <peng.p.sun@linux.intel.com> Reviewed-by: Zhao, yakui <yakui.zhao@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
struct gfx_ctx {
|
||||
struct gfx_ctx_image *gc_image;
|
||||
int raw;
|
||||
};
|
||||
|
||||
struct gfx_ctx_image *
|
||||
gc_get_image(struct gfx_ctx *gc)
|
||||
{
|
||||
if (gc == NULL)
|
||||
return NULL;
|
||||
|
||||
return gc->gc_image;
|
||||
}
|
@@ -94,6 +94,7 @@ struct hugetlb_info {
|
||||
int fd;
|
||||
int pg_size;
|
||||
size_t lowmem;
|
||||
size_t fbmem;
|
||||
size_t biosmem;
|
||||
size_t highmem;
|
||||
|
||||
@@ -110,6 +111,7 @@ static struct hugetlb_info hugetlb_priv[HUGETLB_LV_MAX] = {
|
||||
.fd = -1,
|
||||
.pg_size = 0,
|
||||
.lowmem = 0,
|
||||
.fbmem = 0,
|
||||
.biosmem = 0,
|
||||
.highmem = 0,
|
||||
|
||||
@@ -124,6 +126,7 @@ static struct hugetlb_info hugetlb_priv[HUGETLB_LV_MAX] = {
|
||||
.fd = -1,
|
||||
.pg_size = 0,
|
||||
.lowmem = 0,
|
||||
.fbmem = 0,
|
||||
.biosmem = 0,
|
||||
.highmem = 0,
|
||||
|
||||
@@ -237,6 +240,7 @@ static bool should_enable_hugetlb_level(int level)
|
||||
}
|
||||
|
||||
return (hugetlb_priv[level].lowmem > 0 ||
|
||||
hugetlb_priv[level].fbmem > 0 ||
|
||||
hugetlb_priv[level].biosmem > 0 ||
|
||||
hugetlb_priv[level].highmem > 0);
|
||||
}
|
||||
@@ -248,7 +252,7 @@ static bool should_enable_hugetlb_level(int level)
|
||||
* skip : skip offset in different level hugetlbfs fd
|
||||
*/
|
||||
static int mmap_hugetlbfs_from_level(struct vmctx *ctx, int level, size_t len,
|
||||
size_t offset, size_t skip)
|
||||
size_t offset, size_t skip, char **addr_out)
|
||||
{
|
||||
char *addr;
|
||||
size_t pagesz = 0;
|
||||
@@ -265,6 +269,9 @@ static int mmap_hugetlbfs_from_level(struct vmctx *ctx, int level, size_t len,
|
||||
if (addr == MAP_FAILED)
|
||||
return -ENOMEM;
|
||||
|
||||
if (addr_out)
|
||||
*addr_out = addr;
|
||||
|
||||
pr_info("mmap 0x%lx@%p\n", len, addr);
|
||||
|
||||
/* pre-allocate hugepages by touch them */
|
||||
@@ -282,7 +289,7 @@ static int mmap_hugetlbfs_from_level(struct vmctx *ctx, int level, size_t len,
|
||||
|
||||
static int mmap_hugetlbfs(struct vmctx *ctx, size_t offset,
|
||||
void (*get_param)(struct hugetlb_info *, size_t *, size_t *),
|
||||
size_t (*adj_param)(struct hugetlb_info *, struct hugetlb_info *, int))
|
||||
size_t (*adj_param)(struct hugetlb_info *, struct hugetlb_info *, int), char **addr)
|
||||
{
|
||||
size_t len, skip;
|
||||
int level, ret = 0, pg_size;
|
||||
@@ -292,7 +299,7 @@ static int mmap_hugetlbfs(struct vmctx *ctx, size_t offset,
|
||||
pg_size = hugetlb_priv[level].pg_size;
|
||||
|
||||
while (len > 0) {
|
||||
ret = mmap_hugetlbfs_from_level(ctx, level, len, offset, skip);
|
||||
ret = mmap_hugetlbfs_from_level(ctx, level, len, offset, skip, addr);
|
||||
|
||||
if (ret < 0 && level > HUGETLB_LV1) {
|
||||
len = adj_param(
|
||||
@@ -359,6 +366,28 @@ static size_t adj_biosmem_param(struct hugetlb_info *htlb,
|
||||
return htlb->biosmem;
|
||||
}
|
||||
|
||||
#define FB_SIZE (16 * MB)
|
||||
static void get_fbmem_param(struct hugetlb_info *htlb,
|
||||
size_t *len, size_t *skip)
|
||||
{
|
||||
if (htlb == &hugetlb_priv[0]) {
|
||||
*len = FB_SIZE;
|
||||
*skip = htlb->lowmem + htlb->highmem + htlb->biosmem;
|
||||
} else {
|
||||
*len = 0;
|
||||
*skip = htlb->lowmem + htlb->highmem + htlb->biosmem;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t adj_fbmem_param(struct hugetlb_info *htlb,
|
||||
struct hugetlb_info *htlb_prev, int adj_size)
|
||||
{
|
||||
htlb->fbmem -= adj_size;
|
||||
htlb_prev->fbmem += adj_size;
|
||||
|
||||
return htlb->fbmem;
|
||||
}
|
||||
|
||||
static int rm_hugetlb_dirs(int level)
|
||||
{
|
||||
char path[MAX_PATH_LEN]={0};
|
||||
@@ -484,8 +513,9 @@ static bool hugetlb_check_memgap(void)
|
||||
|
||||
for (lvl = HUGETLB_LV1; lvl < hugetlb_lv_max; lvl++) {
|
||||
free_pages = read_sys_info(hugetlb_priv[lvl].free_pages_path);
|
||||
need_pages = (hugetlb_priv[lvl].lowmem + hugetlb_priv[lvl].biosmem +
|
||||
hugetlb_priv[lvl].highmem) / hugetlb_priv[lvl].pg_size;
|
||||
need_pages = (hugetlb_priv[lvl].lowmem + hugetlb_priv[lvl].fbmem +
|
||||
hugetlb_priv[lvl].biosmem + hugetlb_priv[lvl].highmem) /
|
||||
hugetlb_priv[lvl].pg_size;
|
||||
|
||||
hugetlb_priv[lvl].pages_delta = need_pages - free_pages;
|
||||
/* if delta > 0, it's a gap for needed pages, to be handled */
|
||||
@@ -672,7 +702,7 @@ void uninit_hugetlb(void)
|
||||
int hugetlb_setup_memory(struct vmctx *ctx)
|
||||
{
|
||||
int level;
|
||||
size_t lowmem, biosmem, highmem;
|
||||
size_t lowmem, fbmem, biosmem, highmem;
|
||||
bool has_gap;
|
||||
|
||||
if (ctx->lowmem == 0) {
|
||||
@@ -692,6 +722,8 @@ int hugetlb_setup_memory(struct vmctx *ctx)
|
||||
* hugetlb_priv[HUGETLB_LV1].pg_size */
|
||||
ctx->lowmem =
|
||||
ALIGN_DOWN(ctx->lowmem, hugetlb_priv[HUGETLB_LV1].pg_size);
|
||||
ctx->fbmem =
|
||||
ALIGN_DOWN(ctx->fbmem, hugetlb_priv[HUGETLB_LV1].pg_size);
|
||||
ctx->biosmem =
|
||||
ALIGN_DOWN(ctx->biosmem, hugetlb_priv[HUGETLB_LV1].pg_size);
|
||||
ctx->highmem =
|
||||
@@ -701,12 +733,15 @@ int hugetlb_setup_memory(struct vmctx *ctx)
|
||||
|
||||
/* check & set hugetlb level memory size for lowmem/biosmem/highmem */
|
||||
lowmem = ctx->lowmem;
|
||||
fbmem = ctx->fbmem;
|
||||
biosmem = ctx->biosmem;
|
||||
highmem = ctx->highmem;
|
||||
|
||||
for (level = hugetlb_lv_max - 1; level >= HUGETLB_LV1; level--) {
|
||||
hugetlb_priv[level].lowmem =
|
||||
ALIGN_DOWN(lowmem, hugetlb_priv[level].pg_size);
|
||||
hugetlb_priv[level].fbmem =
|
||||
ALIGN_DOWN(fbmem, hugetlb_priv[level].pg_size);
|
||||
hugetlb_priv[level].biosmem =
|
||||
ALIGN_DOWN(biosmem, hugetlb_priv[level].pg_size);
|
||||
hugetlb_priv[level].highmem =
|
||||
@@ -715,6 +750,8 @@ int hugetlb_setup_memory(struct vmctx *ctx)
|
||||
if (level > HUGETLB_LV1) {
|
||||
hugetlb_priv[level-1].lowmem = lowmem =
|
||||
lowmem - hugetlb_priv[level].lowmem;
|
||||
hugetlb_priv[level-1].fbmem = fbmem =
|
||||
fbmem - hugetlb_priv[level].fbmem;
|
||||
hugetlb_priv[level-1].biosmem = biosmem =
|
||||
biosmem - hugetlb_priv[level].biosmem;
|
||||
hugetlb_priv[level-1].highmem = highmem =
|
||||
@@ -742,9 +779,10 @@ int hugetlb_setup_memory(struct vmctx *ctx)
|
||||
/* dump hugepage trying to setup */
|
||||
pr_info("\ntry to setup hugepage with:\n");
|
||||
for (level = HUGETLB_LV1; level < hugetlb_lv_max; level++) {
|
||||
pr_info("\tlevel %d - lowmem 0x%lx, biosmem 0x%lx, highmem 0x%lx\n",
|
||||
pr_info("\tlevel %d - lowmem 0x%lx, fbmem 0x%lx, biosmem 0x%lx, highmem 0x%lx\n",
|
||||
level,
|
||||
hugetlb_priv[level].lowmem,
|
||||
hugetlb_priv[level].fbmem,
|
||||
hugetlb_priv[level].biosmem,
|
||||
hugetlb_priv[level].highmem);
|
||||
}
|
||||
@@ -769,25 +807,31 @@ int hugetlb_setup_memory(struct vmctx *ctx)
|
||||
pr_info("mmap ptr 0x%p -> baseaddr 0x%p\n", ptr, ctx->baseaddr);
|
||||
|
||||
/* mmap lowmem */
|
||||
if (mmap_hugetlbfs(ctx, 0, get_lowmem_param, adj_lowmem_param) < 0) {
|
||||
if (mmap_hugetlbfs(ctx, 0, get_lowmem_param, adj_lowmem_param, NULL) < 0) {
|
||||
pr_err("lowmem mmap failed");
|
||||
goto err_lock;
|
||||
}
|
||||
|
||||
/* mmap highmem */
|
||||
if (mmap_hugetlbfs(ctx, ctx->highmem_gpa_base,
|
||||
get_highmem_param, adj_highmem_param) < 0) {
|
||||
get_highmem_param, adj_highmem_param, NULL) < 0) {
|
||||
pr_err("highmem mmap failed");
|
||||
goto err_lock;
|
||||
}
|
||||
|
||||
/* mmap biosmem */
|
||||
if (mmap_hugetlbfs(ctx, 4 * GB - ctx->biosmem,
|
||||
get_biosmem_param, adj_biosmem_param) < 0) {
|
||||
get_biosmem_param, adj_biosmem_param, NULL) < 0) {
|
||||
pr_err("biosmem mmap failed");
|
||||
goto err_lock;
|
||||
}
|
||||
|
||||
/* mmap fbmem */
|
||||
if (mmap_hugetlbfs(ctx, 4 * GB - ctx->biosmem - ctx->fbmem,
|
||||
get_fbmem_param, adj_fbmem_param, (char **)&ctx->fb_base) < 0) {
|
||||
pr_err("fbmem mmap failed");
|
||||
goto err_lock;
|
||||
}
|
||||
unlock_acrn_hugetlb();
|
||||
|
||||
/* dump hugepage really setup */
|
||||
|
@@ -372,6 +372,7 @@ vm_setup_memory(struct vmctx *ctx, size_t memsize)
|
||||
}
|
||||
|
||||
ctx->biosmem = high_bios_size();
|
||||
ctx->fbmem = (16 * 1024 * 1024);
|
||||
|
||||
ret = hugetlb_setup_memory(ctx);
|
||||
if (ret == 0) {
|
||||
|
Reference in New Issue
Block a user