Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 24856
b: refs/heads/master
c: 02dea08
h: refs/heads/master
v: v3
  • Loading branch information
Jeff Dike authored and Linus Torvalds committed Mar 31, 2006
1 parent 1635d39 commit a8d636a
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 48 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 85b6bce3658a823aa169586fe71ffba0f12ccc71
refs/heads/master: 02dea0875b0f9b331a65fd6097dfd6115ca4ef24
138 changes: 138 additions & 0 deletions trunk/arch/um/drivers/mconsole_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "linux/namei.h"
#include "linux/proc_fs.h"
#include "linux/syscalls.h"
#include "linux/list.h"
#include "linux/mm.h"
#include "linux/console.h"
#include "asm/irq.h"
#include "asm/uaccess.h"
Expand Down Expand Up @@ -347,6 +349,142 @@ static struct mc_device *mconsole_find_dev(char *name)
return(NULL);
}

#define UNPLUGGED_PER_PAGE \
((PAGE_SIZE - sizeof(struct list_head)) / sizeof(unsigned long))

struct unplugged_pages {
struct list_head list;
void *pages[UNPLUGGED_PER_PAGE];
};

static unsigned long long unplugged_pages_count = 0;
static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages);
static int unplug_index = UNPLUGGED_PER_PAGE;

static int mem_config(char *str)
{
unsigned long long diff;
int err = -EINVAL, i, add;
char *ret;

if(str[0] != '=')
goto out;

str++;
if(str[0] == '-')
add = 0;
else if(str[0] == '+'){
add = 1;
}
else goto out;

str++;
diff = memparse(str, &ret);
if(*ret != '\0')
goto out;

diff /= PAGE_SIZE;

for(i = 0; i < diff; i++){
struct unplugged_pages *unplugged;
void *addr;

if(add){
if(list_empty(&unplugged_pages))
break;

unplugged = list_entry(unplugged_pages.next,
struct unplugged_pages, list);
if(unplug_index > 0)
addr = unplugged->pages[--unplug_index];
else {
list_del(&unplugged->list);
addr = unplugged;
unplug_index = UNPLUGGED_PER_PAGE;
}

free_page((unsigned long) addr);
unplugged_pages_count--;
}
else {
struct page *page;

page = alloc_page(GFP_ATOMIC);
if(page == NULL)
break;

unplugged = page_address(page);
if(unplug_index == UNPLUGGED_PER_PAGE){
INIT_LIST_HEAD(&unplugged->list);
list_add(&unplugged->list, &unplugged_pages);
unplug_index = 0;
}
else {
struct list_head *entry = unplugged_pages.next;
addr = unplugged;

unplugged = list_entry(entry,
struct unplugged_pages,
list);
unplugged->pages[unplug_index++] = addr;
err = os_drop_memory(addr, PAGE_SIZE);
if(err)
printk("Failed to release memory - "
"errno = %d\n", err);
}

unplugged_pages_count++;
}
}

err = 0;
out:
return err;
}

static int mem_get_config(char *name, char *str, int size, char **error_out)
{
char buf[sizeof("18446744073709551615")];
int len = 0;

sprintf(buf, "%ld", uml_physmem);
CONFIG_CHUNK(str, size, len, buf, 1);

return len;
}

static int mem_id(char **str, int *start_out, int *end_out)
{
*start_out = 0;
*end_out = 0;

return 0;
}

static int mem_remove(int n)
{
return -EBUSY;
}

static struct mc_device mem_mc = {
.name = "mem",
.config = mem_config,
.get_config = mem_get_config,
.id = mem_id,
.remove = mem_remove,
};

static int mem_mc_init(void)
{
if(can_drop_memory())
mconsole_register_dev(&mem_mc);
else printk("Can't release memory to the host - memory hotplug won't "
"be supported\n");
return 0;
}

__initcall(mem_mc_init);

#define CONFIG_BUF_SIZE 64

static void mconsole_get_config(int (*get_config)(char *, char *, int,
Expand Down
1 change: 0 additions & 1 deletion trunk/arch/um/include/mem_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ extern int iomem_size;
extern unsigned long host_task_size;
extern unsigned long task_size;

extern void check_devanon(void);
extern int init_mem_user(void);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/um/include/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ extern int os_map_memory(void *virt, int fd, unsigned long long off,
extern int os_protect_memory(void *addr, unsigned long len,
int r, int w, int x);
extern int os_unmap_memory(void *addr, int len);
extern int os_drop_memory(void *addr, int length);
extern int can_drop_memory(void);
extern void os_flush_stdout(void);

/* tt.c
Expand Down
27 changes: 1 addition & 26 deletions trunk/arch/um/os-Linux/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,36 +121,11 @@ int create_tmp_file(unsigned long long len)
return(fd);
}

static int create_anon_file(unsigned long long len)
{
void *addr;
int fd;

fd = open("/dev/anon", O_RDWR);
if(fd < 0) {
perror("opening /dev/anon");
exit(1);
}

addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if(addr == MAP_FAILED){
perror("mapping physmem file");
exit(1);
}
munmap(addr, len);

return(fd);
}

extern int have_devanon;

int create_mem_file(unsigned long long len)
{
int err, fd;

if(have_devanon)
fd = create_anon_file(len);
else fd = create_tmp_file(len);
fd = create_tmp_file(len);

err = os_set_exec_close(fd, 1);
if(err < 0){
Expand Down
44 changes: 44 additions & 0 deletions trunk/arch/um/os-Linux/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include "ptrace_user.h"
#include "os.h"
#include "user.h"
Expand All @@ -20,6 +21,7 @@
#include "kern_util.h"
#include "longjmp.h"
#include "skas_ptrace.h"
#include "kern_constants.h"

#define ARBITRARY_ADDR -1
#define FAILURE_PID -1
Expand Down Expand Up @@ -187,6 +189,48 @@ int os_unmap_memory(void *addr, int len)
return(0);
}

#ifndef MADV_REMOVE
#define MADV_REMOVE 0x5 /* remove these pages & resources */
#endif

int os_drop_memory(void *addr, int length)
{
int err;

err = madvise(addr, length, MADV_REMOVE);
if(err < 0)
err = -errno;
return err;
}

int can_drop_memory(void)
{
void *addr;
int fd;

printk("Checking host MADV_REMOVE support...");
fd = create_mem_file(UM_KERN_PAGE_SIZE);
if(fd < 0){
printk("Creating test memory file failed, err = %d\n", -fd);
return 0;
}

addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if(addr == MAP_FAILED){
printk("Mapping test memory file failed, err = %d\n", -errno);
return 0;
}

if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){
printk("MADV_REMOVE failed, err = %d\n", -errno);
return 0;
}

printk("OK\n");
return 1;
}

void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
{
int flags = 0, pages;
Expand Down
20 changes: 0 additions & 20 deletions trunk/arch/um/os-Linux/start_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,25 +470,6 @@ int can_do_skas(void)
}
#endif

int have_devanon = 0;

/* Runs on boot kernel stack - already safe to use printk. */

void check_devanon(void)
{
int fd;

printk("Checking for /dev/anon on the host...");
fd = open("/dev/anon", O_RDWR);
if(fd < 0){
printk("Not available (open failed with errno %d)\n", errno);
return;
}

printk("OK\n");
have_devanon = 1;
}

int __init parse_iomem(char *str, int *add)
{
struct iomem_region *new;
Expand Down Expand Up @@ -664,6 +645,5 @@ void os_check_bugs(void)
{
check_ptrace();
check_sigio();
check_devanon();
}

0 comments on commit a8d636a

Please sign in to comment.